{"version":3,"sources":["../../src/constants.ts","../../src/lib/pkce.ts","../../src/errors.ts","../../src/react/ai-hooks.ts","../../src/react/services-context.ts","../../src/react/components/billing-card.tsx","../../src/react/hooks.ts","../../src/react/context.ts","../../src/react/platform-context.ts","../../src/connection-url.ts","../../src/config.ts","../../src/orgs.ts","../../src/react/hooks/use-config.ts","../../src/react/hooks/use-oauth-providers.ts","../../src/react/hooks/use-sdk-ready.tsx","../../src/react/ui/configuration-error.tsx","../../src/react/ui/styles.ts","../../src/react/platform-hooks.ts","../../src/react/components/checkout-button.tsx","../../src/react/components/forgot-password.tsx","../../src/react/security-utils.ts","../../src/react/ui/modal.tsx","../../src/react/components/invite-member.tsx","../../src/react/components/members-list.tsx","../../src/react/components/organization-switcher.tsx","../../src/react/components/pricing-table.tsx","../../src/react/components/reset-password.tsx","../../src/react/components/sign-in.tsx","../../src/react/ui/sign-in-form.tsx","../../src/react/hooks/use-sign-in-form.ts","../../src/react/ui/oauth-buttons.tsx","../../src/oauth-providers.ts","../../src/react/ui/oauth-provider-icons.tsx","../../src/react/ui/sign-up-form.tsx","../../src/react/hooks/use-sign-up-form.ts","../../src/react/components/sign-up.tsx","../../src/react/components/user-button.tsx","../../src/react/components/verify-email.tsx","../../src/react/components/protect.tsx","../../src/react/consent-hooks.ts","../../src/react/consent-scripts.tsx","../../src/react/email-hooks.ts","../../src/react/engagement-hooks.ts","../../src/react/feature-flag-hooks.tsx","../../src/react/hooks/use-forgot-password-form.ts","../../src/react/hooks/use-reset-password-form.ts","../../src/react/hooks/use-task-run.ts","../../src/react/monitoring-hooks.ts","../../src/react/newsletter-hooks.ts","../../src/react/protected.tsx","../../src/react/provider.tsx","../../src/consent.ts","../../src/key-validation.ts","../../src/react/context-values/ai.ts","../../src/react/context-values/consent.ts","../../src/react/context-values/database.ts","../../src/react/context-values/email.ts","../../src/react/context-values/tasks.ts","../../src/react/context-values/monitoring.ts","../../src/react/context-values/newsletter.ts","../../src/react/context-values/webhooks.ts","../../src/react/rest-client.ts","../../src/react/storage-utils.ts","../../src/react/token-manager.ts","../../src/react/rbac-hooks.ts","../../src/permissions.ts","../../src/roles.ts","../../src/react/storage-hooks.ts","../../src/storage.ts","../../src/contract-http.ts","../../src/lib/retry.ts","../../src/react/task-hooks.ts","../../src/react/webhooks-hooks.ts","../../src/react/ui/account-section.tsx","../../src/react/ui/analytics-dashboard.tsx","../../src/react/ui/api-key-manager.tsx","../../src/react/ui/billing-management.tsx","../../src/formatting.ts","../../src/react/ui/billing-section.tsx","../../src/react/ui/chat-interface.tsx","../../src/react/ui/consent-preferences.tsx","../../src/react/ui/cookie-banner.tsx","../../src/react/ui/error-boundary.tsx","../../src/react/ui/feature-gate.tsx","../../src/react/ui/file-upload.tsx","../../src/react/ui/job-scheduler.tsx","../../src/react/job-hooks.ts","../../src/react/ui/model-selector.tsx","../../src/react/ui/newsletter-form.tsx","../../src/react/ui/notification-settings.tsx","../../src/react/ui/organization-management.tsx","../../src/react/ui/push-notifications.tsx","../../src/react/ui/referral-card.tsx","../../src/react/ui/security-settings.tsx","../../src/react/ui/subscriber-preferences.tsx","../../src/react/ui/unsubscribe-confirm.tsx","../../src/react/ui/user-profile.tsx","../../src/react/ui/webhook-manager.tsx","../../src/lib/monitoring/error-tracking/breadcrumbs.ts","../../src/lib/monitoring/network-interceptor.ts","../../src/lib/monitoring/session-replay/privacy.ts","../../src/lib/monitoring/error-tracking/pii-scrubber.ts","../../src/lib/monitoring/error-tracking/types.ts","../../src/lib/monitoring/error-tracking/tracker.ts","../../src/lib/monitoring/session-replay/detectors.ts","../../src/lib/monitoring/session-replay/recorder.ts","../../src/lib/monitoring/session-replay/types.ts","../../../../../../.bun-cache/links/web-vitals@5.1.0-8d3498403ac6cf73/node_modules/web-vitals/dist/web-vitals.js","../../src/lib/monitoring/web-vitals/index.ts","../../src/react/hooks/use-session-replay.tsx","../../src/react/hooks/use-web-vitals.ts","../../src/react/hooks/use-error-tracking.ts","../../src/lib/flags/evaluator.ts","../../src/lib/flags/hash.ts","../../src/lib/flags/targeting.ts","../../src/lib/flags/experiments.ts","../../src/lib/flags/streaming.ts","../../src/lib/flags/types.ts","../../src/react/hooks/use-flag.ts","../../src/react/hooks/use-flags.tsx","../../src/lib/analytics/element-naming.ts","../../src/lib/analytics/types.ts","../../src/lib/analytics/autocapture.ts","../../src/lib/analytics/destinations.ts","../../src/lib/analytics/navigation.ts","../../src/lib/analytics/tracker.ts","../../src/react/hooks/use-analytics.tsx","../../src/react/hooks/use-destination-router.tsx","../../src/lib/tasks/handler.ts","../../src/lib/tasks/types.ts","../../src/lib/tasks/legacy.ts","../../src/lib/tasks/workflow-builder.ts","../../src/react/hooks/use-realtime.ts","../../src/react/hooks/use-kv.ts","../../src/react/hooks/use-search.ts","../../src/search.ts","../../src/react/components/web-analytics.tsx","../../src/lib/analytics/web-analytics.ts","../../src/react/components/speed-insights.tsx"],"sourcesContent":["/**\n * SDK Constants — Single Source of Truth\n *\n * Shared constants used across the SDK. Centralizing these\n * prevents magic number duplication and makes changes easier.\n *\n * IMPORTANT: All time-based constants should be used consistently\n * across the SDK. Never hardcode magic numbers like 30000, 5 * 60 * 1000, etc.\n */\n\n// =============================================================================\n// API Configuration\n// =============================================================================\n\n/**\n * Canonical environment variable name for the client connection URL.\n *\n * Format: sylphx://pk_prod_{hex}@tenant-slug.api.sylphx.com\n * Browser-safe (publishable key only).\n */\nexport const ENV_URL = 'SYLPHX_URL'\n\n/**\n * Canonical environment variable name for the Next.js public connection URL.\n *\n * Same format as ENV_URL, browser-safe.\n */\nexport const ENV_PUBLIC_URL = 'NEXT_PUBLIC_SYLPHX_URL'\n\n/**\n * Canonical environment variable name for the server secret connection URL.\n *\n * Format: sylphx://sk_prod_{hex}@tenant-slug.api.sylphx.com\n * Server-side only — never expose to client.\n */\nexport const ENV_SECRET_URL = 'SYLPHX_SECRET_URL'\n\n/**\n * Resolve the secret connection URL from environment variables.\n */\nexport function resolveSecretUrl(explicit?: string): string | undefined {\n\treturn explicit || process.env[ENV_SECRET_URL]\n}\n\n/**\n * SDK API path for the per-project subdomain-based SDK server.\n *\n * The full base URL is built as: https://{tenant-slug}.api.sylphx.com/v1\n */\nexport const SDK_API_PATH = `/v1`\nexport const SDK_API_VERSION = 'v1'\n\n/**\n * Default SDK API host.\n *\n * Management API:  https://api.sylphx.com/v1/*\n * BaaS/SDK API:    https://{tenant-slug}.api.sylphx.com/v1/*\n */\nexport const DEFAULT_SDK_API_HOST = 'api.sylphx.com'\nexport const DEFAULT_PLATFORM_URL = 'https://sylphx.com'\n\n/**\n * Default auth route prefix\n *\n * Used for OAuth callbacks and signout routes.\n * Must match the middleware's authPrefix config.\n */\nexport const DEFAULT_AUTH_PREFIX = '/auth'\n\n/**\n * SDK package version\n *\n * Sent in X-SDK-Version header for debugging and analytics.\n * Update this when releasing new SDK versions.\n */\nexport const SDK_VERSION = '0.5.0'\n\n/**\n * SDK platform identifier\n *\n * Sent in X-SDK-Platform header to identify the runtime environment.\n */\ntype SdkRuntimeGlobal = typeof globalThis & {\n\treadonly EdgeRuntime?: string\n}\n\nfunction detectSdkPlatform(): 'browser' | 'edge' | 'node' {\n\tif (typeof window !== 'undefined') return 'browser'\n\tconst runtimeGlobal = globalThis as SdkRuntimeGlobal\n\tif (typeof runtimeGlobal.EdgeRuntime !== 'undefined') return 'edge'\n\treturn 'node'\n}\n\nexport const SDK_PLATFORM = detectSdkPlatform()\n\n// =============================================================================\n// Timeouts & Durations\n// =============================================================================\n\n/** Default request timeout in milliseconds (30 seconds) */\nexport const DEFAULT_TIMEOUT_MS = 30_000\n\n/**\n * Sandbox create waits for the Runtime API to provision runtime resources and for\n * the exec-server readiness probe to pass. The server-side readiness budget is\n * 120s; this client budget adds transport margin without changing the default\n * timeout for ordinary API calls.\n */\nexport const SANDBOX_CREATE_TIMEOUT_MS = 150_000\n\n/**\n * Token expiry buffer in milliseconds (30 seconds)\n *\n * Refresh tokens this many milliseconds BEFORE they expire\n * to account for network latency and clock skew.\n */\nexport const TOKEN_EXPIRY_BUFFER_MS = 30_000\n\n/**\n * Session token lifetime in seconds (5 minutes)\n *\n * Matches Clerk's short-lived access token pattern.\n * Used for cookie maxAge and React Query staleTime.\n */\nexport const SESSION_TOKEN_LIFETIME_SECONDS = 5 * 60\n\n/** Session token lifetime in milliseconds (for React Query staleTime) */\nexport const SESSION_TOKEN_LIFETIME_MS = SESSION_TOKEN_LIFETIME_SECONDS * 1000\n\n/**\n * Refresh token lifetime in seconds (30 days)\n *\n * Long-lived token for silent refresh.\n */\nexport const REFRESH_TOKEN_LIFETIME_SECONDS = 30 * 24 * 60 * 60\n\n// =============================================================================\n// Feature Flags Cache\n// =============================================================================\n\n/**\n * Feature flags cache TTL in milliseconds (5 minutes)\n *\n * How long to cache flags before fetching fresh values.\n * Matches LaunchDarkly's default streaming connection behavior.\n */\nexport const FLAGS_CACHE_TTL_MS = 5 * 60 * 1000\n\n/**\n * Feature flags stale-while-revalidate window in milliseconds (1 minute)\n *\n * Allow serving stale flags while fetching fresh values.\n */\nexport const FLAGS_STALE_WHILE_REVALIDATE_MS = 60 * 1000\n\n// =============================================================================\n// Retry & Backoff\n// =============================================================================\n\n/** Maximum retry delay for exponential backoff (30 seconds) */\nexport const MAX_RETRY_DELAY_MS = 30_000\n\n/** Base retry delay for exponential backoff (1 second) */\nexport const BASE_RETRY_DELAY_MS = 1_000\n\n/** Maximum number of retries for network requests */\nexport const MAX_RETRIES = 3\n\n// =============================================================================\n// Analytics\n// =============================================================================\n\n/**\n * Analytics session timeout in milliseconds (30 minutes)\n *\n * After this much inactivity, a new session is started.\n */\nexport const ANALYTICS_SESSION_TIMEOUT_MS = 30 * 60 * 1000\n\n// =============================================================================\n// Webhooks\n// =============================================================================\n\n/**\n * Maximum age for webhook signature validation (5 minutes)\n *\n * Reject webhooks with timestamps older than this.\n */\nexport const WEBHOOK_MAX_AGE_MS = 5 * 60 * 1000\n\n/**\n * Clock skew allowance for webhook validation (30 seconds)\n *\n * Allow timestamps this far in the future.\n */\nexport const WEBHOOK_CLOCK_SKEW_MS = 30 * 1000\n\n// =============================================================================\n// PKCE (OAuth)\n// =============================================================================\n\n/**\n * PKCE code verifier TTL in milliseconds (10 minutes)\n *\n * How long the code verifier is stored during OAuth flow.\n */\nexport const PKCE_CODE_TTL_MS = 10 * 60 * 1000\n\n// =============================================================================\n// Jobs\n// =============================================================================\n\n/**\n * Job dead-letter queue retention in milliseconds (7 days)\n */\nexport const JOBS_DLQ_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000\n\n// =============================================================================\n// Session Replay\n// =============================================================================\n\n/**\n * Maximum session replay recording duration in milliseconds (60 minutes)\n */\nexport const SESSION_REPLAY_MAX_DURATION_MS = 60 * 60 * 1000\n\n/**\n * Session replay upload interval in milliseconds (5 seconds)\n */\nexport const SESSION_REPLAY_UPLOAD_INTERVAL_MS = 5_000\n\n/**\n * Session replay scroll event throttle interval (150 ms)\n */\nexport const SESSION_REPLAY_SCROLL_THROTTLE_MS = 150\n\n/**\n * Session replay media time update throttle interval (800 ms)\n */\nexport const SESSION_REPLAY_MEDIA_THROTTLE_MS = 800\n\n/**\n * Session replay rage click detection window (1 second)\n */\nexport const SESSION_REPLAY_RAGE_CLICK_WINDOW_MS = 1_000\n\n/**\n * Session replay dead click detection timeout (500 ms)\n */\nexport const SESSION_REPLAY_DEAD_CLICK_TIMEOUT_MS = 500\n\n/**\n * Session replay scroll heat detection window (2 seconds)\n */\nexport const SESSION_REPLAY_SCROLL_HEAT_WINDOW_MS = 2_000\n\n/**\n * Session replay status check interval (5 seconds)\n */\nexport const SESSION_REPLAY_STATUS_CHECK_MS = 5_000\n\n// =============================================================================\n// Analytics (Extended)\n// =============================================================================\n\n/**\n * Analytics event flush interval in milliseconds (5 seconds)\n */\nexport const ANALYTICS_FLUSH_INTERVAL_MS = 5_000\n\n/**\n * Analytics maximum text length for autocapture (100 characters)\n */\nexport const ANALYTICS_MAX_TEXT_LENGTH = 100\n\n/**\n * Analytics flush timeout in milliseconds (1 second)\n */\nexport const ANALYTICS_FLUSH_TIMEOUT_MS = 1_000\n\n/**\n * Analytics interval check in milliseconds (1 second)\n */\nexport const ANALYTICS_INTERVAL_CHECK_MS = 1_000\n\n/**\n * Analytics retry base delay in milliseconds (1 second)\n * Exponential backoff: delay = base * 2^retries (with jitter)\n */\nexport const ANALYTICS_RETRY_BASE_DELAY_MS = 1_000\n\n/**\n * Analytics retry max delay in milliseconds (30 seconds)\n */\nexport const ANALYTICS_RETRY_MAX_DELAY_MS = 30_000\n\n/**\n * Analytics retry jitter factor (±20%)\n * Prevents thundering herd when multiple clients retry simultaneously\n */\nexport const ANALYTICS_RETRY_JITTER = 0.2\n\n/**\n * Analytics maximum retries before dropping event (Segment pattern: 10)\n */\nexport const ANALYTICS_MAX_RETRIES = 10\n\n// =============================================================================\n// Feature Flags (Extended)\n// =============================================================================\n\n/**\n * Feature flags exposure deduplication window (1 hour)\n *\n * Prevents duplicate exposure events for A/B tests within this window.\n */\nexport const FLAGS_EXPOSURE_DEDUPE_WINDOW_MS = 60 * 60 * 1000\n\n/**\n * Flag stream initial reconnection delay (1 second)\n */\nexport const FLAGS_STREAM_INITIAL_RECONNECT_MS = 1_000\n\n/**\n * Flag stream maximum reconnection delay (30 seconds)\n */\nexport const FLAGS_STREAM_MAX_RECONNECT_MS = 30_000\n\n/**\n * Flag stream heartbeat timeout (45 seconds)\n */\nexport const FLAGS_STREAM_HEARTBEAT_TIMEOUT_MS = 45_000\n\n/**\n * Flag HTTP polling interval fallback (60 seconds)\n */\nexport const FLAGS_HTTP_POLLING_INTERVAL_MS = 60_000\n\n// =============================================================================\n// Jobs (Extended)\n// =============================================================================\n\n/**\n * Default retry delay sequence for exponential backoff (ms)\n */\nexport const DEFAULT_RETRY_DELAYS_MS = [1_000, 5_000, 15_000, 30_000, 60_000] as const\n\n/**\n * Default job timeout in milliseconds (60 seconds)\n */\nexport const JOB_DEFAULT_TIMEOUT_MS = 60_000\n\n/**\n * Default job status polling interval (2 seconds)\n */\nexport const JOB_POLL_INTERVAL_MS = 2_000\n\n// =============================================================================\n// Storage Keys & Prefixes\n// =============================================================================\n\n/**\n * Storage key prefix for SDK data\n */\nexport const STORAGE_KEY_PREFIX = 'sylphx_'\n\n/**\n * localStorage key for cached feature flags\n */\nexport const FLAGS_CACHE_KEY = 'sylphx_feature_flags'\n\n/**\n * localStorage key for feature flags cache timestamp\n */\nexport const FLAGS_CACHE_TIMESTAMP_KEY = 'sylphx_feature_flags_ts'\n\n/**\n * localStorage key for feature flags overrides\n */\nexport const FLAGS_OVERRIDES_KEY = 'sylphx_feature_flags_overrides'\n\n/**\n * localStorage key for active organization\n */\nexport const ORG_STORAGE_KEY = 'sylphx_active_org'\n\n/**\n * BroadcastChannel name for cross-tab org sync\n */\nexport const ORG_BROADCAST_CHANNEL = 'sylphx_org_sync'\n\n/**\n * Storage prefix for PKCE verifiers\n */\nexport const PKCE_STORAGE_PREFIX = 'sylphx_pkce_'\n\n/**\n * Test key for checking storage availability\n */\nexport const STORAGE_TEST_KEY = '__sylphx_test__'\n\n/**\n * Cookie/storage name for analytics sessions\n */\nexport const ANALYTICS_SESSION_KEY = 'sylphx_session'\n\n/**\n * Default storage key for flags persistence\n */\nexport const FLAGS_STORAGE_KEY = 'sylphx_flags'\n\n// =============================================================================\n// Click ID & Attribution\n// =============================================================================\n\n/**\n * Click ID attribution window in milliseconds (90 days)\n *\n * How long click IDs are stored for conversion attribution.\n */\nexport const CLICK_ID_EXPIRY_MS = 90 * 24 * 60 * 60 * 1000\n\n// =============================================================================\n// React Query Stale Times\n// =============================================================================\n\n/**\n * React Query staleTime for frequently-changing data (1 minute)\n *\n * Use for: real-time metrics, live feeds, active sessions\n */\nexport const STALE_TIME_FREQUENT_MS = 60 * 1_000\n\n/**\n * React Query staleTime for moderately-changing data (2 minutes)\n *\n * Use for: subscriptions, user profiles, preferences\n */\nexport const STALE_TIME_MODERATE_MS = 2 * 60 * 1_000\n\n/**\n * React Query staleTime for stable/config data (5 minutes)\n *\n * Use for: plans, feature flags, app config\n */\nexport const STALE_TIME_STABLE_MS = 5 * 60 * 1_000\n\n/**\n * React Query staleTime for webhook stats (30 seconds)\n */\nexport const STALE_TIME_STATS_MS = 30 * 1_000\n\n// =============================================================================\n// UI Component Timeouts\n// =============================================================================\n\n/**\n * Copy-to-clipboard feedback display duration (2 seconds)\n */\nexport const UI_COPY_FEEDBACK_MS = 2_000\n\n/**\n * Form success message display duration (3 seconds)\n */\nexport const UI_FORM_SUCCESS_MS = 3_000\n\n/**\n * General notification display duration (5 seconds)\n */\nexport const UI_NOTIFICATION_MS = 5_000\n\n/**\n * Prompt auto-show delay (3 seconds)\n */\nexport const UI_PROMPT_DELAY_MS = 3_000\n\n/**\n * Redirect delay after action (3 seconds)\n */\nexport const UI_REDIRECT_DELAY_MS = 3_000\n\n/**\n * Animation out duration (200 ms)\n */\nexport const UI_ANIMATION_OUT_MS = 200\n\n/**\n * Animation in duration (300 ms)\n */\nexport const UI_ANIMATION_IN_MS = 300\n\n// =============================================================================\n// Email & Verification\n// =============================================================================\n\n/**\n * Email resend cooldown tick interval (1 second)\n */\nexport const EMAIL_RESEND_COOLDOWN_TICK_MS = 1_000\n\n/**\n * New user detection threshold (1 minute)\n *\n * Users created within this window are considered \"new\" for signup tracking.\n */\nexport const NEW_USER_THRESHOLD_MS = 60 * 1_000\n\n// =============================================================================\n// Web Vitals Thresholds\n// =============================================================================\n\n/**\n * FCP (First Contentful Paint) \"good\" threshold (1800 ms)\n */\nexport const WEB_VITALS_FCP_GOOD_MS = 1_800\n\n/**\n * FCP (First Contentful Paint) \"poor\" threshold (3000 ms)\n */\nexport const WEB_VITALS_FCP_POOR_MS = 3_000\n\n// =============================================================================\n// Storage Sizes\n// =============================================================================\n\n/**\n * Multipart upload threshold (5 MB)\n *\n * Files larger than this use multipart upload for better reliability.\n */\nexport const STORAGE_MULTIPART_THRESHOLD_BYTES = 5 * 1024 * 1024\n\n/**\n * Default max file size for uploads (5 MB)\n */\nexport const STORAGE_DEFAULT_MAX_SIZE_BYTES = 5 * 1024 * 1024\n\n/**\n * Avatar max file size (2 MB)\n */\nexport const STORAGE_AVATAR_MAX_SIZE_BYTES = 2 * 1024 * 1024\n\n/**\n * Large file max size for file uploads (10 MB)\n */\nexport const STORAGE_LARGE_MAX_SIZE_BYTES = 10 * 1024 * 1024\n\n// =============================================================================\n// Cache TTLs\n// =============================================================================\n\n/**\n * JWK cache TTL (1 hour)\n */\nexport const JWK_CACHE_TTL_MS = 60 * 60 * 1000\n\n// =============================================================================\n// Analytics Event Tracking\n// =============================================================================\n\n/**\n * Max tracked event IDs to keep in memory\n */\nexport const ANALYTICS_MAX_TRACKED_EVENT_IDS = 1000\n\n/**\n * Number of event IDs to keep after cleanup\n */\nexport const ANALYTICS_TRACKED_IDS_KEEP = 500\n\n/**\n * Analytics queue limit before force flush\n */\nexport const ANALYTICS_QUEUE_LIMIT = 100\n\n// =============================================================================\n// Session Replay (Extended)\n// =============================================================================\n\n/**\n * Session replay check interval (1 second)\n */\nexport const SESSION_REPLAY_CHECK_INTERVAL_MS = 1_000\n\n/**\n * Success feedback delay for invite/account actions (1.5 seconds)\n */\nexport const UI_SUCCESS_REDIRECT_MS = 1_500\n\n// =============================================================================\n// String Truncation Limits\n// =============================================================================\n\n/**\n * Max message length for logging (1000 chars)\n */\nexport const LOG_MESSAGE_MAX_LENGTH = 1_000\n\n/**\n * Max DOM snapshot length for debugging (1000 chars)\n */\nexport const DOM_SNAPSHOT_MAX_LENGTH = 1_000\n\n/**\n * Max stack trace length for error tracking (500 chars)\n */\nexport const STACK_TRACE_MAX_LENGTH = 500\n\n/**\n * Google Consent Mode wait for update timeout (500 ms)\n */\nexport const CONSENT_WAIT_FOR_UPDATE_MS = 500\n\n// =============================================================================\n// Time Unit Conversions\n// =============================================================================\n\n/** Milliseconds per minute (60,000) */\nexport const MS_PER_MINUTE = 60_000\n\n/** Milliseconds per hour (3,600,000) */\nexport const MS_PER_HOUR = 3_600_000\n\n/** Milliseconds per day (86,400,000) */\nexport const MS_PER_DAY = 86_400_000\n\n/** Seconds per minute (60) */\nexport const SECONDS_PER_MINUTE = 60\n\n/** Seconds per hour (3,600) */\nexport const SECONDS_PER_HOUR = 3_600\n\n// =============================================================================\n// Z-Index Values\n// =============================================================================\n\n/** Z-index for modal overlays (9999) */\nexport const Z_INDEX_OVERLAY = 9999\n\n/** Z-index for critical overlays like feature gates (99999) */\nexport const Z_INDEX_CRITICAL_OVERLAY = 99999\n\n// =============================================================================\n// API Key Expiry (seconds)\n// =============================================================================\n\n/** API key expiry: 1 day (86,400 seconds) */\nexport const API_KEY_EXPIRY_1_DAY = 86_400\n\n/** API key expiry: 7 days (604,800 seconds) */\nexport const API_KEY_EXPIRY_7_DAYS = 604_800\n\n/** API key expiry: 30 days (2,592,000 seconds) */\nexport const API_KEY_EXPIRY_30_DAYS = 2_592_000\n\n/** API key expiry: 90 days (7,776,000 seconds) */\nexport const API_KEY_EXPIRY_90_DAYS = 7_776_000\n\n/** API key expiry: 1 year (31,536,000 seconds) */\nexport const API_KEY_EXPIRY_1_YEAR = 31_536_000\n\n// =============================================================================\n// Web Vitals Thresholds (Google standards)\n// =============================================================================\n\n/** LCP (Largest Contentful Paint) \"good\" threshold (2500 ms) */\nexport const WEB_VITALS_LCP_GOOD_MS = 2_500\n\n/** LCP (Largest Contentful Paint) \"poor\" threshold (4000 ms) */\nexport const WEB_VITALS_LCP_POOR_MS = 4_000\n\n/** INP (Interaction to Next Paint) \"good\" threshold (200 ms) */\nexport const WEB_VITALS_INP_GOOD_MS = 200\n\n/** INP (Interaction to Next Paint) \"poor\" threshold (500 ms) */\nexport const WEB_VITALS_INP_POOR_MS = 500\n\n/** TTFB (Time to First Byte) \"good\" threshold (800 ms) */\nexport const WEB_VITALS_TTFB_GOOD_MS = 800\n\n/** TTFB (Time to First Byte) \"poor\" threshold (1800 ms) */\nexport const WEB_VITALS_TTFB_POOR_MS = 1_800\n\n// =============================================================================\n// Security\n// =============================================================================\n\n/** Minimum password length (NIST SP 800-63B recommends 12+) */\nexport const MIN_PASSWORD_LENGTH = 12\n\n// =============================================================================\n// AI\n// =============================================================================\n\n/** Default context window for AI models (4096 tokens) */\nexport const DEFAULT_CONTEXT_WINDOW = 4_096\n\n// =============================================================================\n// Circuit Breaker (AWS/Resilience4j pattern)\n// =============================================================================\n\n/**\n * Circuit breaker failure threshold\n *\n * Number of failures in the window before circuit opens.\n */\nexport const CIRCUIT_BREAKER_FAILURE_THRESHOLD = 5\n\n/**\n * Circuit breaker failure window in milliseconds (10 seconds)\n *\n * Time window for counting failures.\n */\nexport const CIRCUIT_BREAKER_WINDOW_MS = 10_000\n\n/**\n * Circuit breaker open duration in milliseconds (30 seconds)\n *\n * How long the circuit stays open before allowing a test request.\n */\nexport const CIRCUIT_BREAKER_OPEN_DURATION_MS = 30_000\n\n// =============================================================================\n// ETag Cache (HTTP conditional requests)\n// =============================================================================\n\n/**\n * Maximum ETag cache entries\n *\n * LRU eviction when exceeded.\n */\nexport const ETAG_CACHE_MAX_ENTRIES = 100\n\n/**\n * ETag cache TTL in milliseconds (5 minutes)\n *\n * How long cached responses are valid.\n */\nexport const ETAG_CACHE_TTL_MS = 5 * 60 * 1000\n","/**\n * PKCE (Proof Key for Code Exchange) Utilities\n *\n * Implements RFC 7636 for secure OAuth 2.0 authorization code flow.\n * Required for public clients (browsers, mobile apps) per OAuth 2.1.\n *\n * Security improvements:\n * - Uses in-memory Map instead of sessionStorage (not accessible to XSS)\n * - Correlates verifier with state nonce to prevent race conditions\n * - Auto-expires entries after 10 minutes (matches state TTL)\n *\n * Flow:\n * 1. Generate code_verifier (random 43-128 char string)\n * 2. Create code_challenge = base64url(SHA256(code_verifier))\n * 3. Send code_challenge to authorization endpoint\n * 4. Store code_verifier in memory (keyed by appId + nonce)\n * 5. Send code_verifier with token exchange request\n * 6. Server verifies: base64url(SHA256(code_verifier)) === code_challenge\n *\n * @see https://datatracker.ietf.org/doc/html/rfc7636\n */\n\nimport { PKCE_CODE_TTL_MS, PKCE_STORAGE_PREFIX, STORAGE_TEST_KEY } from '../constants'\n\n// ==========================================\n// Constants\n// ==========================================\n\n/** Verifier length (43-128 chars per RFC 7636) */\nconst VERIFIER_LENGTH = 64\n\n/** Characters allowed in code_verifier (unreserved URI chars) */\nconst VERIFIER_CHARSET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~'\n\n/** PKCE entry TTL from constants (10 minutes, matches OAuth state) */\nconst PKCE_TTL_MS = PKCE_CODE_TTL_MS\n\ninterface PKCEEntry {\n\tverifier: string\n\tcreatedAt: number\n}\n\n/**\n * Build storage key from appId and optional nonce\n */\nfunction buildKey(appId: string, nonce?: string): string {\n\treturn `${PKCE_STORAGE_PREFIX}${nonce ? `${appId}:${nonce}` : appId}`\n}\n\n/**\n * In-memory fallback storage (used when sessionStorage is unavailable)\n * Note: This loses verifier on page navigation, so sessionStorage is preferred\n */\nconst pkceMemoryFallback = new Map<string, PKCEEntry>()\n\n/**\n * Check if sessionStorage is available\n */\nfunction isSessionStorageAvailable(): boolean {\n\tif (typeof window === 'undefined') return false\n\ttry {\n\t\tsessionStorage.setItem(STORAGE_TEST_KEY, 'test')\n\t\tsessionStorage.removeItem(STORAGE_TEST_KEY)\n\t\treturn true\n\t} catch {\n\t\treturn false\n\t}\n}\n\n/**\n * Get PKCE entry from storage\n */\nfunction getEntry(key: string): PKCEEntry | null {\n\tif (typeof window === 'undefined') return null\n\n\tif (isSessionStorageAvailable()) {\n\t\tconst stored = sessionStorage.getItem(key)\n\t\tif (!stored) return null\n\t\ttry {\n\t\t\treturn JSON.parse(stored) as PKCEEntry\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\t// Fallback to in-memory (less secure, loses on navigation)\n\treturn pkceMemoryFallback.get(key) || null\n}\n\n/**\n * Set PKCE entry in storage\n */\nfunction setEntry(key: string, entry: PKCEEntry): void {\n\tif (typeof window === 'undefined') return\n\n\tif (isSessionStorageAvailable()) {\n\t\tsessionStorage.setItem(key, JSON.stringify(entry))\n\t} else {\n\t\t// Fallback to in-memory\n\t\tpkceMemoryFallback.set(key, entry)\n\t}\n}\n\n/**\n * Delete PKCE entry from storage\n */\nfunction deleteEntry(key: string): void {\n\tif (typeof window === 'undefined') return\n\n\tif (isSessionStorageAvailable()) {\n\t\tsessionStorage.removeItem(key)\n\t} else {\n\t\tpkceMemoryFallback.delete(key)\n\t}\n}\n\n/**\n * Clean up expired entries from sessionStorage\n */\nfunction cleanupExpiredEntries(): void {\n\tif (typeof window === 'undefined') return\n\n\tconst now = Date.now()\n\n\tif (isSessionStorageAvailable()) {\n\t\t// Clean sessionStorage\n\t\tconst keysToRemove: string[] = []\n\t\tfor (let i = 0; i < sessionStorage.length; i++) {\n\t\t\tconst key = sessionStorage.key(i)\n\t\t\tif (key?.startsWith(PKCE_STORAGE_PREFIX)) {\n\t\t\t\tconst entry = getEntry(key)\n\t\t\t\tif (entry && now - entry.createdAt > PKCE_TTL_MS) {\n\t\t\t\t\tkeysToRemove.push(key)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (const key of keysToRemove) {\n\t\t\tsessionStorage.removeItem(key)\n\t\t}\n\t} else {\n\t\t// Clean in-memory fallback\n\t\tfor (const [key, entry] of pkceMemoryFallback.entries()) {\n\t\t\tif (now - entry.createdAt > PKCE_TTL_MS) {\n\t\t\t\tpkceMemoryFallback.delete(key)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// ==========================================\n// PKCE Generation\n// ==========================================\n\n/**\n * Generate a cryptographically random code_verifier.\n * Uses Web Crypto API for secure random generation.\n */\nexport function generateCodeVerifier(): string {\n\tconst randomValues = new Uint8Array(VERIFIER_LENGTH)\n\tcrypto.getRandomValues(randomValues)\n\n\tlet verifier = ''\n\tfor (let i = 0; i < VERIFIER_LENGTH; i++) {\n\t\tverifier += VERIFIER_CHARSET[randomValues[i] % VERIFIER_CHARSET.length]\n\t}\n\n\treturn verifier\n}\n\n/**\n * Generate code_challenge from code_verifier using S256 method.\n * S256 = base64url(SHA256(code_verifier))\n */\nexport async function generateCodeChallenge(verifier: string): Promise<string> {\n\t// SHA-256 hash\n\tconst encoder = new TextEncoder()\n\tconst data = encoder.encode(verifier)\n\tconst hash = await crypto.subtle.digest('SHA-256', data)\n\n\t// Base64url encode (no padding, URL-safe chars)\n\tconst base64 = btoa(String.fromCharCode(...new Uint8Array(hash)))\n\treturn base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\n\n/**\n * Generate a complete PKCE pair (verifier + challenge).\n */\nexport async function generatePKCE(): Promise<{\n\tcodeVerifier: string\n\tcodeChallenge: string\n\tcodeChallengeMethod: 'S256'\n}> {\n\tconst codeVerifier = generateCodeVerifier()\n\tconst codeChallenge = await generateCodeChallenge(codeVerifier)\n\n\treturn {\n\t\tcodeVerifier,\n\t\tcodeChallenge,\n\t\tcodeChallengeMethod: 'S256',\n\t}\n}\n\n// ==========================================\n// PKCE Storage (In-Memory, XSS-Resistant)\n// ==========================================\n\n/**\n * Store code_verifier for later use in token exchange.\n *\n * Uses sessionStorage to persist across OAuth redirects (page navigations).\n * Falls back to in-memory storage if sessionStorage is unavailable.\n *\n * Security notes:\n * - sessionStorage is scoped to tab/window and cleared on close\n * - Auto-expires after 10 minutes\n * - XSS can access sessionStorage, but code_verifier alone is useless\n *   without the authorization code (attacker would need both)\n *\n * @param verifier - The code_verifier to store\n * @param appId - The app ID for namespacing\n * @param nonce - Optional nonce for correlating with specific OAuth flow\n */\nexport function storePKCEVerifier(verifier: string, appId: string, nonce?: string): void {\n\tif (typeof window === 'undefined') return\n\n\t// Cleanup expired entries periodically\n\tcleanupExpiredEntries()\n\n\tconst key = buildKey(appId, nonce)\n\tsetEntry(key, {\n\t\tverifier,\n\t\tcreatedAt: Date.now(),\n\t})\n}\n\n/**\n * Clear stored PKCE verifier (cleanup on error).\n *\n * @param appId - The app ID for namespacing\n * @param nonce - Optional nonce for correlating with specific OAuth flow\n */\nexport function clearPKCEVerifier(appId: string, nonce?: string): void {\n\tif (typeof window === 'undefined') return\n\n\tconst key = buildKey(appId, nonce)\n\tdeleteEntry(key)\n}\n\n// ==========================================\n// PKCE Verification (for testing/reference)\n// ==========================================\n\n/**\n * Constant-time string comparison to prevent timing attacks.\n *\n * Even though this is primarily for testing, we use timing-safe comparison\n * to establish correct patterns and prevent copy-paste vulnerabilities.\n *\n * @see OWASP: https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html\n */\nfunction timingSafeEqual(a: string, b: string): boolean {\n\tif (a.length !== b.length) {\n\t\t// Still do comparison to maintain constant time\n\t\t// but we know it will fail\n\t\tlet _result = 1\n\t\tfor (let i = 0; i < a.length; i++) {\n\t\t\t_result |= a.charCodeAt(i) ^ (b.charCodeAt(i % b.length) || 0)\n\t\t}\n\t\treturn false\n\t}\n\n\tlet result = 0\n\tfor (let i = 0; i < a.length; i++) {\n\t\tresult |= a.charCodeAt(i) ^ b.charCodeAt(i)\n\t}\n\treturn result === 0\n}\n\n/**\n * Verify code_verifier against stored code_challenge.\n *\n * ⚠️ This is a reference implementation for testing.\n * The actual server-side verification lives in packages/core/src/features/auth/lib/service.ts\n * which has the same timing-safe comparison implementation.\n *\n * Uses constant-time comparison to prevent timing attacks (OWASP A02:2021).\n *\n * @see RFC 7636 - Proof Key for Code Exchange\n */\nexport async function verifyPKCE(\n\tcodeVerifier: string,\n\tcodeChallenge: string,\n\tmethod: 'S256' | 'plain' = 'S256',\n): Promise<boolean> {\n\tif (method === 'plain') {\n\t\t// Plain method: code_verifier === code_challenge (timing-safe)\n\t\treturn timingSafeEqual(codeVerifier, codeChallenge)\n\t}\n\n\t// S256 method: BASE64URL(SHA256(code_verifier)) === code_challenge\n\tconst computedChallenge = await generateCodeChallenge(codeVerifier)\n\n\t// Timing-safe comparison\n\treturn timingSafeEqual(computedChallenge, codeChallenge)\n}\n","/**\n * Sylphx SDK Error Classes\n *\n * Typed error classes for better error handling and debugging.\n * Compatible with tRPC error codes and provides rich context.\n *\n * @example\n * ```typescript\n * import { SylphxError, isRetryableError, getErrorMessage } from '@sylphx/sdk'\n *\n * try {\n *   await sylphx.auth.login.mutate({ email, password })\n * } catch (error) {\n *   if (error instanceof SylphxError) {\n *     console.log(error.code) // 'UNAUTHORIZED'\n *     console.log(error.isRetryable) // false\n *   }\n *   if (isRetryableError(error)) {\n *     // Safe to retry\n *   }\n * }\n * ```\n */\n\nimport { BASE_RETRY_DELAY_MS, DEFAULT_TIMEOUT_MS, MAX_RETRY_DELAY_MS } from './constants'\n\n// ============================================================================\n// Error Codes (aligned with tRPC and HTTP semantics)\n// ============================================================================\n\nexport type SylphxErrorCode =\n\t// Client errors (4xx)\n\t| 'BAD_REQUEST' // 400 - Invalid input\n\t| 'UNAUTHORIZED' // 401 - Not authenticated\n\t| 'FORBIDDEN' // 403 - Not authorized\n\t| 'NOT_FOUND' // 404 - Resource not found\n\t| 'CONFLICT' // 409 - Resource conflict (e.g., duplicate)\n\t| 'PAYLOAD_TOO_LARGE' // 413 - Request too large\n\t| 'UNPROCESSABLE_ENTITY' // 422 - Validation failed\n\t| 'TOO_MANY_REQUESTS' // 429 - Rate limited\n\t| 'QUOTA_EXCEEDED' // 402/429 - Quota/plan limit exceeded\n\t// Server errors (5xx)\n\t| 'INTERNAL_SERVER_ERROR' // 500 - Server error\n\t| 'NOT_IMPLEMENTED' // 501 - Feature not available\n\t| 'BAD_GATEWAY' // 502 - Upstream error\n\t| 'SERVICE_UNAVAILABLE' // 503 - Temporarily unavailable\n\t| 'GATEWAY_TIMEOUT' // 504 - Upstream timeout\n\t// Network/Client errors\n\t| 'NETWORK_ERROR' // Network failure\n\t| 'TIMEOUT' // Request timeout\n\t| 'ABORTED' // Request aborted\n\t// SDK-specific\n\t| 'PARSE_ERROR' // JSON/response parse error\n\t| 'UNKNOWN' // Unknown error\n\n/**\n * Simplified semantic error codes (DX-friendly aliases).\n * Maps to the more granular SylphxErrorCode internally.\n *\n * @example\n * ```ts\n * if (SylphxError.isRateLimited(err)) {\n *   console.log(`Retry after ${err.retryAfter}s`)\n * }\n * ```\n */\nexport type ErrorCode =\n\t| 'UNAUTHORIZED'\n\t| 'FORBIDDEN'\n\t| 'NOT_FOUND'\n\t| 'RATE_LIMITED'\n\t| 'QUOTA_EXCEEDED'\n\t| 'VALIDATION_ERROR'\n\t| 'NETWORK_ERROR'\n\t| 'UPSTREAM_ERROR'\n\t| 'INTERNAL_ERROR'\n\n/**\n * HTTP status code mapping for error codes\n */\nexport const ERROR_CODE_STATUS: Record<SylphxErrorCode, number> = {\n\tBAD_REQUEST: 400,\n\tUNAUTHORIZED: 401,\n\tFORBIDDEN: 403,\n\tNOT_FOUND: 404,\n\tCONFLICT: 409,\n\tPAYLOAD_TOO_LARGE: 413,\n\tUNPROCESSABLE_ENTITY: 422,\n\tTOO_MANY_REQUESTS: 429,\n\tQUOTA_EXCEEDED: 402,\n\tINTERNAL_SERVER_ERROR: 500,\n\tNOT_IMPLEMENTED: 501,\n\tBAD_GATEWAY: 502,\n\tSERVICE_UNAVAILABLE: 503,\n\tGATEWAY_TIMEOUT: 504,\n\tNETWORK_ERROR: 0,\n\tTIMEOUT: 0,\n\tABORTED: 0,\n\tPARSE_ERROR: 0,\n\tUNKNOWN: 0,\n}\n\n/**\n * Retryable error codes (safe to retry automatically)\n */\nexport const RETRYABLE_CODES: Set<SylphxErrorCode> = new Set([\n\t'NETWORK_ERROR',\n\t'TIMEOUT',\n\t'BAD_GATEWAY',\n\t'SERVICE_UNAVAILABLE',\n\t'GATEWAY_TIMEOUT',\n\t'TOO_MANY_REQUESTS', // With backoff\n\t'INTERNAL_SERVER_ERROR', // Sometimes transient\n])\n\n// ============================================================================\n// Error Classes\n// ============================================================================\n\nexport interface SylphxErrorOptions {\n\t/** Error code for programmatic handling */\n\tcode?: SylphxErrorCode\n\t/** HTTP status code (inferred from code if not provided) */\n\tstatus?: number\n\t/** Additional context data */\n\tdata?: Record<string, unknown>\n\t/** Original error that caused this */\n\tcause?: Error\n\t/** Retry-After header value (seconds) for rate limiting */\n\tretryAfter?: number\n}\n\n/**\n * Base error class for all Sylphx SDK errors\n *\n * @example\n * ```typescript\n * throw new SylphxError('Invalid email format', {\n *   code: 'BAD_REQUEST',\n *   data: { field: 'email' }\n * })\n * ```\n */\nexport class SylphxError extends Error {\n\t/** Error code for programmatic handling */\n\treadonly code: SylphxErrorCode\n\n\t/** HTTP status code */\n\treadonly status: number\n\n\t/** Additional context data */\n\treadonly data?: Record<string, unknown>\n\n\t/** Whether this error is safe to retry */\n\treadonly isRetryable: boolean\n\n\t/** Retry-After value in seconds (for rate limiting) */\n\treadonly retryAfter?: number\n\n\t/** Timestamp when error occurred */\n\treadonly timestamp: Date\n\n\tconstructor(message: string, options: SylphxErrorOptions = {}) {\n\t\tsuper(message, { cause: options.cause })\n\t\tthis.name = 'SylphxError'\n\t\tthis.code = options.code ?? 'UNKNOWN'\n\t\tthis.status = options.status ?? ERROR_CODE_STATUS[this.code]\n\t\tthis.data = options.data\n\t\tthis.isRetryable = RETRYABLE_CODES.has(this.code)\n\t\tthis.retryAfter = options.retryAfter\n\t\tthis.timestamp = new Date()\n\n\t\t// Maintain proper stack trace in V8\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, SylphxError)\n\t\t}\n\t}\n\n\t// ============================================================================\n\t// Static Type Guards (DX helpers)\n\t// ============================================================================\n\n\t/**\n\t * Check if error is a rate-limit error (429 Too Many Requests)\n\t */\n\tstatic isRateLimited(err: unknown): err is SylphxError & { code: 'TOO_MANY_REQUESTS' } {\n\t\treturn err instanceof SylphxError && err.code === 'TOO_MANY_REQUESTS'\n\t}\n\n\t/**\n\t * Check if error is an account lockout error (too many failed login attempts).\n\t * When true, `error.data?.lockoutUntil` contains the ISO 8601 timestamp when the lockout expires.\n\t */\n\tstatic isAccountLocked(\n\t\terr: unknown,\n\t): err is SylphxError & { code: 'TOO_MANY_REQUESTS'; data: { lockoutUntil: string | null } } {\n\t\treturn (\n\t\t\terr instanceof SylphxError &&\n\t\t\terr.code === 'TOO_MANY_REQUESTS' &&\n\t\t\terr.data?.code === 'ACCOUNT_LOCKED'\n\t\t)\n\t}\n\n\t/**\n\t * Check if error is a quota exceeded error (plan limit reached)\n\t */\n\tstatic isQuotaExceeded(err: unknown): err is SylphxError & { code: 'QUOTA_EXCEEDED' } {\n\t\treturn err instanceof SylphxError && err.code === 'QUOTA_EXCEEDED'\n\t}\n\n\t/**\n\t * Check if error is an authentication error (401 Unauthorized)\n\t */\n\tstatic isUnauthorized(err: unknown): err is SylphxError & { code: 'UNAUTHORIZED' } {\n\t\treturn err instanceof SylphxError && err.code === 'UNAUTHORIZED'\n\t}\n\n\t/**\n\t * Check if error is a not-found error (404 Not Found)\n\t */\n\tstatic isNotFound(err: unknown): err is SylphxError & { code: 'NOT_FOUND' } {\n\t\treturn err instanceof SylphxError && err.code === 'NOT_FOUND'\n\t}\n\n\t/**\n\t * Check if error is an authorization error (403 Forbidden)\n\t */\n\tstatic isForbidden(err: unknown): err is SylphxError & { code: 'FORBIDDEN' } {\n\t\treturn err instanceof SylphxError && err.code === 'FORBIDDEN'\n\t}\n\n\t/**\n\t * Check if error is a validation error (422 Unprocessable Entity)\n\t */\n\tstatic isValidationError(err: unknown): err is SylphxError & { code: 'UNPROCESSABLE_ENTITY' } {\n\t\treturn err instanceof SylphxError && err.code === 'UNPROCESSABLE_ENTITY'\n\t}\n\n\t/**\n\t * Check if error is a network error (no response received)\n\t */\n\tstatic isNetworkError(err: unknown): err is SylphxError & { code: 'NETWORK_ERROR' } {\n\t\treturn err instanceof SylphxError && err.code === 'NETWORK_ERROR'\n\t}\n\n\t/**\n\t * Check if error is an upstream/gateway error (502/504)\n\t */\n\tstatic isUpstreamError(err: unknown): err is SylphxError {\n\t\treturn (\n\t\t\terr instanceof SylphxError &&\n\t\t\t(err.code === 'BAD_GATEWAY' ||\n\t\t\t\terr.code === 'GATEWAY_TIMEOUT' ||\n\t\t\t\terr.code === 'SERVICE_UNAVAILABLE')\n\t\t)\n\t}\n\n\t/**\n\t * Convert to JSON-serializable object\n\t */\n\ttoJSON(): Record<string, unknown> {\n\t\treturn {\n\t\t\tname: this.name,\n\t\t\tmessage: this.message,\n\t\t\tcode: this.code,\n\t\t\tstatus: this.status,\n\t\t\tdata: this.data,\n\t\t\tisRetryable: this.isRetryable,\n\t\t\tretryAfter: this.retryAfter,\n\t\t\ttimestamp: this.timestamp.toISOString(),\n\t\t}\n\t}\n}\n\n/**\n * Network-related errors (no response received)\n */\nexport class NetworkError extends SylphxError {\n\tconstructor(message = 'Network request failed', options?: Omit<SylphxErrorOptions, 'code'>) {\n\t\tsuper(message, { ...options, code: 'NETWORK_ERROR' })\n\t\tthis.name = 'NetworkError'\n\t}\n}\n\n/**\n * Request timeout errors\n */\nexport class TimeoutError extends SylphxError {\n\t/** Timeout duration in milliseconds */\n\treadonly timeout: number\n\n\tconstructor(timeout: number, options?: Omit<SylphxErrorOptions, 'code'>) {\n\t\tsuper(`Request timed out after ${timeout}ms`, {\n\t\t\t...options,\n\t\t\tcode: 'TIMEOUT',\n\t\t})\n\t\tthis.name = 'TimeoutError'\n\t\tthis.timeout = timeout\n\t}\n}\n\n/**\n * Authentication errors (401)\n */\nexport class AuthenticationError extends SylphxError {\n\tconstructor(message = 'Authentication required', options?: Omit<SylphxErrorOptions, 'code'>) {\n\t\tsuper(message, { ...options, code: 'UNAUTHORIZED' })\n\t\tthis.name = 'AuthenticationError'\n\t}\n}\n\n/**\n * Authorization errors (403)\n */\nexport class AuthorizationError extends SylphxError {\n\tconstructor(message = 'Permission denied', options?: Omit<SylphxErrorOptions, 'code'>) {\n\t\tsuper(message, { ...options, code: 'FORBIDDEN' })\n\t\tthis.name = 'AuthorizationError'\n\t}\n}\n\n/**\n * Validation errors (422)\n */\nexport class ValidationError extends SylphxError {\n\t/** Field-specific errors */\n\treadonly fieldErrors?: Record<string, string[]>\n\n\tconstructor(\n\t\tmessage: string,\n\t\toptions?: Omit<SylphxErrorOptions, 'code'> & {\n\t\t\tfieldErrors?: Record<string, string[]>\n\t\t},\n\t) {\n\t\tsuper(message, { ...options, code: 'UNPROCESSABLE_ENTITY' })\n\t\tthis.name = 'ValidationError'\n\t\tthis.fieldErrors = options?.fieldErrors\n\t}\n\n\t/**\n\t * Get error message for a specific field\n\t */\n\tgetFieldError(field: string): string | undefined {\n\t\treturn this.fieldErrors?.[field]?.[0]\n\t}\n}\n\n/**\n * Rate limit metadata (Stripe SDK pattern)\n */\nexport interface RateLimitInfo {\n\t/** Maximum requests allowed in window */\n\tlimit?: number\n\t/** Remaining requests in current window */\n\tremaining?: number\n\t/** Unix timestamp (seconds) when limit resets */\n\tresetAt?: number\n\t/** Seconds until limit resets (Retry-After header) */\n\tretryAfter?: number\n}\n\n/**\n * Rate limit errors (429)\n *\n * Provides full rate limit metadata for consumer apps to implement\n * proper backoff UI (countdown timers, retry buttons, etc.)\n *\n * @example\n * ```typescript\n * try {\n *   await sendEmail(config, options)\n * } catch (error) {\n *   if (error instanceof RateLimitError) {\n *     const waitSeconds = error.retryAfter ?? 60\n *     console.log(`Rate limited. Retry after ${waitSeconds}s`)\n *     console.log(`Remaining: ${error.remaining}/${error.limit}`)\n *     console.log(`Resets at: ${new Date(error.resetAt! * 1000)}`)\n *   }\n * }\n * ```\n */\nexport class RateLimitError extends SylphxError {\n\t/** Maximum requests allowed in window */\n\treadonly limit?: number\n\n\t/** Remaining requests in current window */\n\treadonly remaining?: number\n\n\t/** Unix timestamp (seconds) when limit resets */\n\treadonly resetAt?: number\n\n\tconstructor(\n\t\tmessage = 'Too many requests',\n\t\toptions?: Omit<SylphxErrorOptions, 'code'> & RateLimitInfo,\n\t) {\n\t\tsuper(message, { ...options, code: 'TOO_MANY_REQUESTS' })\n\t\tthis.name = 'RateLimitError'\n\t\tthis.limit = options?.limit\n\t\tthis.remaining = options?.remaining\n\t\tthis.resetAt = options?.resetAt\n\t}\n\n\t/**\n\t * Get Date when rate limit resets\n\t */\n\tgetResetDate(): Date | undefined {\n\t\treturn this.resetAt ? new Date(this.resetAt * 1000) : undefined\n\t}\n\n\t/**\n\t * Get human-readable retry message\n\t */\n\tgetRetryMessage(): string {\n\t\tif (this.retryAfter) {\n\t\t\treturn `Please retry after ${this.retryAfter} seconds`\n\t\t}\n\t\tif (this.resetAt) {\n\t\t\tconst seconds = Math.max(0, this.resetAt - Math.floor(Date.now() / 1000))\n\t\t\treturn `Rate limit resets in ${seconds} seconds`\n\t\t}\n\t\treturn 'Please wait before retrying'\n\t}\n}\n\n/**\n * Resource not found errors (404)\n */\nexport class NotFoundError extends SylphxError {\n\t/** Type of resource that wasn't found */\n\treadonly resourceType?: string\n\n\t/** ID of the resource that wasn't found */\n\treadonly resourceId?: string\n\n\tconstructor(\n\t\tmessage = 'Resource not found',\n\t\toptions?: Omit<SylphxErrorOptions, 'code'> & {\n\t\t\tresourceType?: string\n\t\t\tresourceId?: string\n\t\t},\n\t) {\n\t\tsuper(message, { ...options, code: 'NOT_FOUND' })\n\t\tthis.name = 'NotFoundError'\n\t\tthis.resourceType = options?.resourceType\n\t\tthis.resourceId = options?.resourceId\n\t}\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Check if an error is a Sylphx SDK error\n */\nexport function isSylphxError(error: unknown): error is SylphxError {\n\treturn error instanceof SylphxError\n}\n\n/**\n * Check if an error is safe to retry\n */\nexport function isRetryableError(error: unknown): boolean {\n\tif (error instanceof SylphxError) {\n\t\treturn error.isRetryable\n\t}\n\n\t// Check for network errors\n\tif (error instanceof Error) {\n\t\tconst message = error.message.toLowerCase()\n\t\tconst name = error.name.toLowerCase()\n\n\t\t// Network errors\n\t\tif (name === 'typeerror' && message.includes('fetch')) return true\n\t\tif (name === 'networkerror') return true\n\n\t\t// Timeout patterns\n\t\tif (message.includes('timeout')) return true\n\t\tif (message.includes('timed out')) return true\n\n\t\t// Connection errors\n\t\tif (message.includes('econnrefused')) return true\n\t\tif (message.includes('econnreset')) return true\n\t\tif (message.includes('socket')) return true\n\n\t\t// Server errors that might be transient\n\t\tif (message.includes('502')) return true\n\t\tif (message.includes('503')) return true\n\t\tif (message.includes('504')) return true\n\t}\n\n\treturn false\n}\n\n/**\n * Extract error message from any error type\n */\nexport function getErrorMessage(error: unknown, fallback = 'An unknown error occurred'): string {\n\tif (error instanceof Error) {\n\t\treturn error.message\n\t}\n\tif (typeof error === 'string') {\n\t\treturn error\n\t}\n\tif (error && typeof error === 'object' && 'message' in error) {\n\t\tconst message = (error as { message: unknown }).message\n\t\tif (typeof message === 'string') return message\n\t}\n\tif (error && typeof error === 'object' && 'response' in error) {\n\t\tconst response = (error as { response?: { data?: { message?: string; error?: string } } })\n\t\t\t.response\n\t\tif (response?.data?.message) return response.data.message\n\t\tif (response?.data?.error) return response.data.error\n\t}\n\treturn fallback\n}\n\n/**\n * Get error code from any error type\n */\nexport function getErrorCode(error: unknown): SylphxErrorCode {\n\tif (error instanceof SylphxError) {\n\t\treturn error.code\n\t}\n\treturn 'UNKNOWN'\n}\n\nfunction getErrorStatus(error: unknown): number | undefined {\n\tif (!error || typeof error !== 'object') return undefined\n\tif ('status' in error && typeof (error as { status: unknown }).status === 'number') {\n\t\treturn (error as { status: number }).status\n\t}\n\tif ('statusCode' in error && typeof (error as { statusCode: unknown }).statusCode === 'number') {\n\t\treturn (error as { statusCode: number }).statusCode\n\t}\n\treturn undefined\n}\n\nfunction getSafeErrorKey(error: unknown): string | undefined {\n\tif (error instanceof SylphxError) return error.code\n\tif (!error || typeof error !== 'object') return undefined\n\tif ('code' in error && typeof (error as { code: unknown }).code === 'string') {\n\t\treturn (error as { code: string }).code\n\t}\n\tconst status = getErrorStatus(error)\n\treturn status == null ? undefined : String(status)\n}\n\nexport interface ErrorDetails {\n\treadonly message: string\n\treadonly code?: string\n\treadonly name?: string\n\treadonly stack?: string\n\treadonly status?: number\n\treadonly cause?: unknown\n}\n\nexport function getErrorDetails(\n\terror: unknown,\n\tfallbackMessage = 'An unknown error occurred',\n): ErrorDetails {\n\tconst details: ErrorDetails = {\n\t\tmessage: getErrorMessage(error, fallbackMessage),\n\t}\n\tconst code = getSafeErrorKey(error)\n\tif (code) {\n\t\tObject.assign(details, { code })\n\t}\n\tconst status = getErrorStatus(error)\n\tif (status != null) {\n\t\tObject.assign(details, { status })\n\t}\n\tif (error instanceof Error) {\n\t\tObject.assign(details, {\n\t\t\tname: error.name,\n\t\t\tstack: error.stack,\n\t\t\t...(error.cause ? { cause: error.cause } : {}),\n\t\t})\n\t}\n\treturn details\n}\n\nconst INTERNAL_ERROR_PATTERNS = [\n\t/sql/i,\n\t/database/i,\n\t/postgres/i,\n\t/neon/i,\n\t/drizzle/i,\n\t/prisma/i,\n\t/constraint/i,\n\t/foreign key/i,\n\t/unique violation/i,\n\t/null value/i,\n\t/column/i,\n\t/table/i,\n\t/relation/i,\n\t/trpc/i,\n\t/internal server/i,\n\t/unexpected/i,\n\t/cannot read propert/i,\n\t/undefined is not/i,\n\t/null is not/i,\n\t/cannot find module/i,\n\t/econnrefused/i,\n\t/etimedout/i,\n\t/enotfound/i,\n]\n\nconst SAFE_ERROR_MESSAGES: Record<string, string> = {\n\t'400': 'Invalid request. Please check your input and try again.',\n\t'401': 'Please sign in to continue.',\n\t'403': \"You don't have permission to perform this action.\",\n\t'404': 'The requested resource was not found.',\n\t'409': 'This action conflicts with existing data. Please refresh and try again.',\n\t'429': 'Too many requests. Please wait a moment and try again.',\n\t'500': 'Something went wrong on our end. Please try again later.',\n\t'502': 'Service temporarily unavailable. Please try again in a moment.',\n\t'503': 'Service temporarily unavailable. Please try again in a moment.',\n\tBAD_REQUEST: 'Invalid request. Please check your input.',\n\tUNAUTHORIZED: 'Please sign in to continue.',\n\tFORBIDDEN: \"You don't have permission to perform this action.\",\n\tNOT_FOUND: 'The requested item was not found.',\n\tCONFLICT: 'This action conflicts with existing data.',\n\tTOO_MANY_REQUESTS: 'Too many requests. Please wait a moment.',\n\tINTERNAL_SERVER_ERROR: 'Something went wrong. Please try again later.',\n\tTIMEOUT: 'Request timed out. Please try again.',\n\tPRECONDITION_FAILED: 'This action cannot be completed right now.',\n\tQUOTA_EXCEEDED: \"You've reached your usage limit. Please upgrade your plan.\",\n\tPAYMENT_REQUIRED: 'Payment is required to continue.',\n\tINVALID_CREDENTIALS: 'Invalid email or password.',\n\tEMAIL_NOT_VERIFIED: 'Please verify your email address.',\n\tACCOUNT_LOCKED: 'Your account has been locked. Please contact support.',\n\tSESSION_EXPIRED: 'Your session has expired. Please sign in again.',\n}\n\nexport function getSafeErrorMessage(\n\terror: unknown,\n\tfallback = 'Something went wrong. Please try again.',\n): string {\n\tconst errorCode = getSafeErrorKey(error)\n\t// Own-property checks only: an attacker-influenced `code` like \"toString\" or\n\t// \"constructor\" must not resolve to an inherited Object.prototype member.\n\tif (errorCode && Object.hasOwn(SAFE_ERROR_MESSAGES, errorCode))\n\t\treturn SAFE_ERROR_MESSAGES[errorCode]\n\n\tif (error && typeof error === 'object') {\n\t\tconst coded = error as { data?: { code?: string } }\n\t\tif (coded.data?.code && Object.hasOwn(SAFE_ERROR_MESSAGES, coded.data.code)) {\n\t\t\treturn SAFE_ERROR_MESSAGES[coded.data.code]\n\t\t}\n\t}\n\n\tconst rawMessage = getErrorMessage(error, '')\n\tif (\n\t\trawMessage &&\n\t\trawMessage.length < 200 &&\n\t\t!rawMessage.includes('\\n') &&\n\t\t!rawMessage.includes('at ') &&\n\t\t!INTERNAL_ERROR_PATTERNS.some((pattern) => pattern.test(rawMessage))\n\t) {\n\t\treturn rawMessage\n\t}\n\n\treturn fallback\n}\n\nexport function isChallengeRequired(err: unknown): boolean {\n\tif (!(err instanceof Error)) return false\n\tif (err.message.includes('challenge')) return true\n\tconst errWithData = err as { data?: { code?: string } }\n\treturn errWithData.data?.code === 'FORBIDDEN'\n}\n\n/**\n * Convert any error to SylphxError\n */\nexport function toSylphxError(error: unknown): SylphxError {\n\tif (error instanceof SylphxError) {\n\t\treturn error\n\t}\n\n\tif (error instanceof Error) {\n\t\t// Try to infer error type from message/name\n\t\tconst message = error.message.toLowerCase()\n\t\tconst name = error.name.toLowerCase()\n\n\t\t// Network errors\n\t\tif (name === 'typeerror' && message.includes('fetch')) {\n\t\t\treturn new NetworkError(error.message, { cause: error })\n\t\t}\n\t\tif (name === 'aborterror' || message.includes('aborted')) {\n\t\t\treturn new SylphxError(error.message, { code: 'ABORTED', cause: error })\n\t\t}\n\n\t\t// Timeout\n\t\tif (message.includes('timeout')) {\n\t\t\treturn new TimeoutError(DEFAULT_TIMEOUT_MS, { cause: error })\n\t\t}\n\n\t\t// HTTP status codes in message\n\t\tif (message.includes('401') || message.includes('unauthorized')) {\n\t\t\treturn new AuthenticationError(error.message, { cause: error })\n\t\t}\n\t\tif (message.includes('403') || message.includes('forbidden')) {\n\t\t\treturn new AuthorizationError(error.message, { cause: error })\n\t\t}\n\t\tif (message.includes('404') || message.includes('not found')) {\n\t\t\treturn new NotFoundError(error.message, { cause: error })\n\t\t}\n\t\tif (message.includes('429') || message.includes('rate limit')) {\n\t\t\treturn new RateLimitError(error.message, { cause: error })\n\t\t}\n\n\t\treturn new SylphxError(error.message, { cause: error })\n\t}\n\n\treturn new SylphxError(getErrorMessage(error))\n}\n\n/**\n * Calculate exponential backoff delay with jitter\n *\n * @param attempt - Retry attempt number (0-indexed)\n * @param baseDelay - Base delay in milliseconds (default: 1000)\n * @param maxDelay - Maximum delay in milliseconds (default: 30000)\n * @returns Delay in milliseconds with jitter\n */\nexport function exponentialBackoff(\n\tattempt: number,\n\tbaseDelay = BASE_RETRY_DELAY_MS,\n\tmaxDelay = MAX_RETRY_DELAY_MS,\n): number {\n\t// Calculate exponential delay: baseDelay * 2^attempt\n\tconst exponentialDelay = baseDelay * 2 ** attempt\n\n\t// Cap at maxDelay\n\tconst cappedDelay = Math.min(exponentialDelay, maxDelay)\n\n\t// Add jitter (±25% randomness)\n\tconst jitter = cappedDelay * 0.25 * (Math.random() * 2 - 1)\n\n\treturn Math.round(cappedDelay + jitter)\n}\n","/**\n * AI Hooks\n *\n * React hooks for the Sylphx AI Gateway.\n * Provides chat, completion, embedding, and vision capabilities.\n *\n * Uses proper React Context pattern (no module singletons).\n */\n\n'use client'\n\nimport { useInfiniteQuery, useQueryClient } from '@tanstack/react-query'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { STALE_TIME_STABLE_MS } from '../constants'\nimport { useAIContext } from './services-context'\nimport type {\n\tAIListModelsOptions,\n\tAIListModelsResponse,\n\tAIMessage,\n\tAIModelInfo,\n\tAIRateLimitInfo,\n\tAITool,\n\tAIUsageStats,\n\tChatCompletionResponse,\n} from './types'\n\n// ============================================\n// Types\n// ============================================\n\nexport interface UseChatOptions {\n\t/** Model to use (default: app config default) */\n\tmodel?: string\n\t/** System message to prepend to conversation */\n\tsystemMessage?: string\n\t/** Temperature (0-2) */\n\ttemperature?: number\n\t/** Max tokens for response */\n\tmaxTokens?: number\n\t/** Tools/functions the model can call */\n\ttools?: AITool[]\n\t/** Initial messages */\n\tinitialMessages?: AIMessage[]\n\t/** Enable streaming mode (default: false) */\n\tstream?: boolean\n\t/** Called for each token during streaming */\n\tonToken?: (token: string) => void\n\t/** Called when streaming completes */\n\tonStreamComplete?: () => void\n\t/** Called when a message is received */\n\tonMessage?: (message: AIMessage) => void\n\t/** Called on error */\n\tonError?: (error: Error) => void\n}\n\nexport interface UseChatReturn {\n\t/** All messages in the conversation */\n\tmessages: AIMessage[]\n\t/** Whether a request is in progress */\n\tisLoading: boolean\n\t/** Whether currently streaming a response */\n\tisStreaming: boolean\n\t/** Current streaming content (updated in real-time) */\n\tstreamingContent: string\n\t/** Error from last request */\n\terror: Error | null\n\t/** Send a message and get response */\n\tsend: (content: string) => Promise<void>\n\t/** Append a message without sending */\n\tappend: (message: AIMessage) => void\n\t/** Clear all messages */\n\tclear: () => void\n\t/** Stop current streaming response */\n\tstop: () => void\n\t/** Retry last message */\n\tretry: () => Promise<void>\n}\n\nexport interface UseCompletionOptions {\n\t/** Model to use */\n\tmodel?: string\n\t/** Temperature (0-2) */\n\ttemperature?: number\n\t/** Max tokens for response */\n\tmaxTokens?: number\n\t/** Stop sequences */\n\tstop?: string | string[]\n\t/** Called when completion is received */\n\tonComplete?: (text: string) => void\n\t/** Called on error */\n\tonError?: (error: Error) => void\n}\n\nexport interface UseCompletionReturn {\n\t/** Complete a prompt */\n\tcomplete: (prompt: string) => Promise<string>\n\t/** Current completion text */\n\tcompletion: string\n\t/** Whether a request is in progress */\n\tisLoading: boolean\n\t/** Error from last request */\n\terror: Error | null\n}\n\nexport interface UseEmbeddingOptions {\n\t/** Model to use */\n\tmodel?: string\n\t/** Embedding dimensions */\n\tdimensions?: number\n}\n\nexport interface UseEmbeddingReturn {\n\t/** Embed a single text */\n\tembed: (text: string) => Promise<number[]>\n\t/** Embed multiple texts */\n\tembedMany: (texts: string[]) => Promise<number[][]>\n\t/** Whether a request is in progress */\n\tisLoading: boolean\n\t/** Error from last request */\n\terror: Error | null\n}\n\n// ============================================\n// useChat\n// ============================================\n\n/**\n * Hook for conversational AI chat\n *\n * Supports both streaming and non-streaming modes.\n *\n * @example\n * ```tsx\n * // Non-streaming (default)\n * function ChatBot() {\n *   const { messages, send, isLoading } = useChat({\n *     systemMessage: 'You are a helpful assistant.',\n *   })\n *\n *   return (\n *     <div>\n *       {messages.map((m, i) => (\n *         <div key={i} className={m.role}>{m.content}</div>\n *       ))}\n *       <input\n *         onKeyDown={(e) => {\n *           if (e.key === 'Enter') {\n *             send(e.currentTarget.value)\n *             e.currentTarget.value = ''\n *           }\n *         }}\n *         disabled={isLoading}\n *       />\n *     </div>\n *   )\n * }\n *\n * // Streaming mode - real-time token display\n * function StreamingChatBot() {\n *   const { messages, send, isLoading, isStreaming, streamingContent, stop } = useChat({\n *     stream: true,\n *     systemMessage: 'You are a helpful assistant.',\n *     onToken: (token) => console.log('Token:', token),\n *   })\n *\n *   return (\n *     <div>\n *       {messages.map((m, i) => (\n *         <div key={i} className={m.role}>{m.content}</div>\n *       ))}\n *       {isStreaming && (\n *         <div className=\"assistant streaming\">{streamingContent}</div>\n *       )}\n *       <button onClick={stop} disabled={!isStreaming}>Stop</button>\n *     </div>\n *   )\n * }\n * ```\n */\nexport function useChat(options: UseChatOptions = {}): UseChatReturn {\n\tconst ctx = useAIContext()\n\tconst [messages, setMessages] = useState<AIMessage[]>(options.initialMessages ?? [])\n\tconst [isLoading, setIsLoading] = useState(false)\n\tconst [isStreaming, setIsStreaming] = useState(false)\n\tconst [streamingContent, setStreamingContent] = useState('')\n\tconst [error, setError] = useState<Error | null>(null)\n\tconst abortControllerRef = useRef<AbortController | null>(null)\n\tconst lastUserMessageRef = useRef<string | null>(null)\n\tconst shouldAbortRef = useRef(false)\n\n\t// Build messages with system message\n\tconst buildMessages = useCallback(\n\t\t(userContent: string): AIMessage[] => {\n\t\t\tconst allMessages: AIMessage[] = []\n\n\t\t\tif (options.systemMessage) {\n\t\t\t\tallMessages.push({ role: 'system', content: options.systemMessage })\n\t\t\t}\n\n\t\t\tallMessages.push(...messages)\n\t\t\tallMessages.push({ role: 'user', content: userContent })\n\n\t\t\treturn allMessages\n\t\t},\n\t\t[messages, options.systemMessage],\n\t)\n\n\tconst send = useCallback(\n\t\tasync (content: string) => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\t\t\tsetStreamingContent('')\n\t\t\tshouldAbortRef.current = false\n\t\t\tlastUserMessageRef.current = content\n\n\t\t\tconst userMessage: AIMessage = { role: 'user', content }\n\t\t\tsetMessages((prev) => [...prev, userMessage])\n\n\t\t\ttry {\n\t\t\t\tabortControllerRef.current = new AbortController()\n\n\t\t\t\tconst chatInput = {\n\t\t\t\t\tmodel: options.model,\n\t\t\t\t\tmessages: buildMessages(content),\n\t\t\t\t\ttemperature: options.temperature,\n\t\t\t\t\tmaxTokens: options.maxTokens,\n\t\t\t\t\ttools: options.tools,\n\t\t\t\t}\n\n\t\t\t\tif (options.stream) {\n\t\t\t\t\t// Streaming mode\n\t\t\t\t\tsetIsStreaming(true)\n\t\t\t\t\tlet fullContent = ''\n\n\t\t\t\t\tfor await (const chunk of ctx.chatStream(chatInput)) {\n\t\t\t\t\t\tif (shouldAbortRef.current) break\n\n\t\t\t\t\t\tconst token = chunk.choices?.[0]?.delta?.content ?? chunk.delta?.content ?? ''\n\t\t\t\t\t\tif (token) {\n\t\t\t\t\t\t\tfullContent += token\n\t\t\t\t\t\t\tsetStreamingContent(fullContent)\n\t\t\t\t\t\t\toptions.onToken?.(token)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tsetIsStreaming(false)\n\t\t\t\t\toptions.onStreamComplete?.()\n\n\t\t\t\t\tconst assistantMessage: AIMessage = {\n\t\t\t\t\t\trole: 'assistant',\n\t\t\t\t\t\tcontent: fullContent,\n\t\t\t\t\t}\n\n\t\t\t\t\tsetMessages((prev) => [...prev, assistantMessage])\n\t\t\t\t\tsetStreamingContent('')\n\t\t\t\t\toptions.onMessage?.(assistantMessage)\n\t\t\t\t} else {\n\t\t\t\t\t// Non-streaming mode\n\t\t\t\t\tconst response = await ctx.chat(chatInput)\n\n\t\t\t\t\tconst assistantMessage: AIMessage = {\n\t\t\t\t\t\trole: 'assistant',\n\t\t\t\t\t\tcontent: response.choices[0]?.message.content ?? '',\n\t\t\t\t\t}\n\n\t\t\t\t\tsetMessages((prev) => [...prev, assistantMessage])\n\t\t\t\t\toptions.onMessage?.(assistantMessage)\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Chat failed')\n\t\t\t\tsetError(error)\n\t\t\t\toptions.onError?.(error)\n\t\t\t\tsetIsStreaming(false)\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t\tabortControllerRef.current = null\n\t\t\t}\n\t\t},\n\t\t[ctx, buildMessages, options],\n\t)\n\n\tconst append = useCallback((message: AIMessage) => {\n\t\tsetMessages((prev) => [...prev, message])\n\t}, [])\n\n\tconst clear = useCallback(() => {\n\t\tsetMessages([])\n\t\tsetError(null)\n\t\tsetStreamingContent('')\n\t}, [])\n\n\tconst stop = useCallback(() => {\n\t\tshouldAbortRef.current = true\n\t\tabortControllerRef.current?.abort()\n\t\tsetIsStreaming(false)\n\t}, [])\n\n\tconst retry = useCallback(async () => {\n\t\tif (lastUserMessageRef.current) {\n\t\t\t// Remove last user and assistant messages\n\t\t\tsetMessages((prev) => prev.slice(0, -2))\n\t\t\tawait send(lastUserMessageRef.current)\n\t\t}\n\t}, [send])\n\n\treturn {\n\t\tmessages,\n\t\tisLoading,\n\t\tisStreaming,\n\t\tstreamingContent,\n\t\terror,\n\t\tsend,\n\t\tappend,\n\t\tclear,\n\t\tstop,\n\t\tretry,\n\t}\n}\n\n// ============================================\n// useCompletion\n// ============================================\n\n/**\n * Hook for text completion\n *\n * @example\n * ```tsx\n * function TextCompleter() {\n *   const { complete, completion, isLoading } = useCompletion()\n *\n *   return (\n *     <div>\n *       <input\n *         onBlur={(e) => complete(e.target.value)}\n *         disabled={isLoading}\n *       />\n *       <p>{completion}</p>\n *     </div>\n *   )\n * }\n * ```\n */\nexport function useCompletion(options: UseCompletionOptions = {}): UseCompletionReturn {\n\tconst ctx = useAIContext()\n\tconst [completion, setCompletion] = useState('')\n\tconst [isLoading, setIsLoading] = useState(false)\n\tconst [error, setError] = useState<Error | null>(null)\n\n\tconst complete = useCallback(\n\t\tasync (prompt: string): Promise<string> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tconst stopSequences = options.stop\n\t\t\t\t\t? Array.isArray(options.stop)\n\t\t\t\t\t\t? options.stop\n\t\t\t\t\t\t: [options.stop]\n\t\t\t\t\t: undefined\n\t\t\t\tconst response = await ctx.complete({\n\t\t\t\t\tmodel: options.model,\n\t\t\t\t\tprompt,\n\t\t\t\t\ttemperature: options.temperature,\n\t\t\t\t\tmaxTokens: options.maxTokens,\n\t\t\t\t\tstop: stopSequences,\n\t\t\t\t})\n\n\t\t\t\tconst text = response.choices[0]?.text ?? ''\n\t\t\t\tsetCompletion(text)\n\t\t\t\toptions.onComplete?.(text)\n\t\t\t\treturn text\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Completion failed')\n\t\t\t\tsetError(error)\n\t\t\t\toptions.onError?.(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx, options],\n\t)\n\n\treturn {\n\t\tcomplete,\n\t\tcompletion,\n\t\tisLoading,\n\t\terror,\n\t}\n}\n\n// ============================================\n// useEmbedding\n// ============================================\n\n/**\n * Hook for generating text embeddings\n *\n * @example\n * ```tsx\n * function SemanticSearch() {\n *   const { embed, embedMany, isLoading } = useEmbedding()\n *\n *   const search = async (query: string) => {\n *     const queryEmbedding = await embed(query)\n *     // Use queryEmbedding for similarity search\n *   }\n *\n *   return <input onBlur={(e) => search(e.target.value)} />\n * }\n * ```\n */\nexport function useEmbedding(options: UseEmbeddingOptions = {}): UseEmbeddingReturn {\n\tconst ctx = useAIContext()\n\tconst [isLoading, setIsLoading] = useState(false)\n\tconst [error, setError] = useState<Error | null>(null)\n\n\tconst embed = useCallback(\n\t\tasync (text: string): Promise<number[]> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tconst response = await ctx.embed({\n\t\t\t\t\tmodel: options.model,\n\t\t\t\t\tinput: text,\n\t\t\t\t\tdimensions: options.dimensions,\n\t\t\t\t})\n\n\t\t\t\treturn response.data[0]?.embedding ?? []\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Embedding failed')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx, options],\n\t)\n\n\tconst embedMany = useCallback(\n\t\tasync (texts: string[]): Promise<number[][]> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tconst response = await ctx.embed({\n\t\t\t\t\tmodel: options.model,\n\t\t\t\t\tinput: texts,\n\t\t\t\t\tdimensions: options.dimensions,\n\t\t\t\t})\n\n\t\t\t\treturn response.data.map((d) => d.embedding)\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Embedding failed')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx, options],\n\t)\n\n\treturn {\n\t\tembed,\n\t\tembedMany,\n\t\tisLoading,\n\t\terror,\n\t}\n}\n\n// ============================================\n// useAI\n// ============================================\n\nexport interface UseAIReturn {\n\t/** Generate chat completion */\n\tchat: (\n\t\tmessages: AIMessage[],\n\t\toptions?: {\n\t\t\tmodel?: string\n\t\t\ttemperature?: number\n\t\t\tmaxTokens?: number\n\t\t\ttools?: AITool[]\n\t\t},\n\t) => Promise<ChatCompletionResponse>\n\t/** Generate text completion */\n\tcomplete: (\n\t\tprompt: string,\n\t\toptions?: {\n\t\t\tmodel?: string\n\t\t\ttemperature?: number\n\t\t\tmaxTokens?: number\n\t\t},\n\t) => Promise<string>\n\t/** Generate embeddings */\n\tembed: (\n\t\tinput: string | string[],\n\t\toptions?: { model?: string; dimensions?: number },\n\t) => Promise<number[][] | number[]>\n\t/** Analyze image */\n\tvision: (\n\t\timageUrl: string,\n\t\tprompt: string,\n\t\toptions?: { model?: string; maxTokens?: number },\n\t) => Promise<string>\n\t/** Get usage statistics */\n\tgetUsage: (period?: 'day' | 'week' | 'month') => Promise<AIUsageStats>\n\t/** Get rate limit status */\n\tgetRateLimitStatus: () => Promise<AIRateLimitInfo>\n\t/** Get available models */\n\tgetModels: (options?: AIListModelsOptions) => Promise<AIListModelsResponse>\n\t/** Whether any AI request is in progress */\n\tisLoading: boolean\n\t/** Last error */\n\terror: Error | null\n}\n\n/**\n * Low-level hook for AI Gateway access\n *\n * @example\n * ```tsx\n * function AIDemo() {\n *   const { chat, embed, vision, isLoading } = useAI()\n *\n *   const analyze = async () => {\n *     const response = await chat([\n *       { role: 'user', content: 'Hello!' }\n *     ])\n *     console.log(response.choices[0].message.content)\n *   }\n *\n *   return <button onClick={analyze} disabled={isLoading}>Analyze</button>\n * }\n * ```\n */\nexport function useAI(): UseAIReturn {\n\tconst ctx = useAIContext()\n\tconst [isLoading, setIsLoading] = useState(false)\n\tconst [error, setError] = useState<Error | null>(null)\n\n\tconst chat = useCallback(\n\t\tasync (\n\t\t\tmessages: AIMessage[],\n\t\t\toptions?: {\n\t\t\t\tmodel?: string\n\t\t\t\ttemperature?: number\n\t\t\t\tmaxTokens?: number\n\t\t\t\ttools?: AITool[]\n\t\t\t},\n\t\t): Promise<ChatCompletionResponse> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\treturn await ctx.chat({\n\t\t\t\t\tmessages,\n\t\t\t\t\t...options,\n\t\t\t\t})\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Chat failed')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst complete = useCallback(\n\t\tasync (\n\t\t\tprompt: string,\n\t\t\toptions?: {\n\t\t\t\tmodel?: string\n\t\t\t\ttemperature?: number\n\t\t\t\tmaxTokens?: number\n\t\t\t},\n\t\t): Promise<string> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tconst response = await ctx.complete({\n\t\t\t\t\tprompt,\n\t\t\t\t\t...options,\n\t\t\t\t})\n\t\t\t\treturn response.choices[0]?.text ?? ''\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Completion failed')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst embed = useCallback(\n\t\tasync (\n\t\t\tinput: string | string[],\n\t\t\toptions?: { model?: string; dimensions?: number },\n\t\t): Promise<number[][] | number[]> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tconst response = await ctx.embed({\n\t\t\t\t\tinput,\n\t\t\t\t\t...options,\n\t\t\t\t})\n\n\t\t\t\tif (Array.isArray(input)) {\n\t\t\t\t\treturn response.data.map((d) => d.embedding)\n\t\t\t\t}\n\t\t\t\treturn response.data[0]?.embedding ?? []\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Embedding failed')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst vision = useCallback(\n\t\tasync (\n\t\t\timageUrl: string,\n\t\t\tprompt: string,\n\t\t\toptions?: { model?: string; maxTokens?: number },\n\t\t): Promise<string> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tconst response = await ctx.vision({\n\t\t\t\t\tmessages: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\trole: 'user',\n\t\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t\t{ type: 'text', text: prompt },\n\t\t\t\t\t\t\t\t{ type: 'image_url', image_url: { url: imageUrl } },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\t...options,\n\t\t\t\t})\n\t\t\t\treturn response.choices[0]?.message.content ?? ''\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Vision analysis failed')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst getUsage = useCallback(\n\t\tasync (period: 'day' | 'week' | 'month' = 'day'): Promise<AIUsageStats> => {\n\t\t\treturn await ctx.getUsage(period)\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst getRateLimitStatus = useCallback(async (): Promise<AIRateLimitInfo> => {\n\t\treturn await ctx.getRateLimitStatus()\n\t}, [ctx])\n\n\tconst getModels = useCallback(\n\t\tasync (options?: AIListModelsOptions): Promise<AIListModelsResponse> => {\n\t\t\treturn await ctx.listModels(options)\n\t\t},\n\t\t[ctx],\n\t)\n\n\treturn {\n\t\tchat,\n\t\tcomplete,\n\t\tembed,\n\t\tvision,\n\t\tgetUsage,\n\t\tgetRateLimitStatus,\n\t\tgetModels,\n\t\tisLoading,\n\t\terror,\n\t}\n}\n\n// ============================================\n// useModels\n// ============================================\n\nexport interface UseModelsOptions {\n\t/** Filter by capability */\n\tcapability?: 'chat' | 'vision' | 'tool' | 'embedding'\n\t/** Search by name or ID */\n\tsearch?: string\n\t/** Number of models per page */\n\tpageSize?: number\n\t/** Whether to fetch immediately */\n\tfetchOnMount?: boolean\n}\n\nexport interface UseModelsReturn {\n\t/** List of models */\n\tmodels: AIModelInfo[]\n\t/** Total number of models matching filters */\n\ttotal: number\n\t/** Whether more models are available */\n\thasMore: boolean\n\t/** Whether loading */\n\tisLoading: boolean\n\t/** Error if any */\n\terror: Error | null\n\t/** Fetch models with current filters */\n\tfetch: () => Promise<void>\n\t/** Load more models (pagination) */\n\tloadMore: () => Promise<void>\n\t/** Search models */\n\tsetSearch: (search: string) => void\n\t/** Filter by capability */\n\tsetCapability: (capability: UseModelsOptions['capability']) => void\n}\n\n/**\n * Hook for fetching and filtering available AI models\n *\n * @example\n * ```tsx\n * function ModelSelector({ onSelect }: { onSelect: (modelId: string) => void }) {\n *   const { models, isLoading, setSearch, setCapability } = useModels({\n *     fetchOnMount: true,\n *     capability: 'chat',\n *   })\n *\n *   return (\n *     <div>\n *       <input\n *         placeholder=\"Search models...\"\n *         onChange={(e) => setSearch(e.target.value)}\n *       />\n *       <select onChange={(e) => setCapability(e.target.value as UseModelsOptions['capability'] || undefined)}>\n *         <option value=\"\">All</option>\n *         <option value=\"chat\">Chat</option>\n *         <option value=\"vision\">Vision</option>\n *         <option value=\"embedding\">Embedding</option>\n *       </select>\n *       {isLoading ? (\n *         <div>Loading...</div>\n *       ) : (\n *         <ul>\n *           {models.map((model) => (\n *             <li key={model.id} onClick={() => onSelect(model.id)}>\n *               <strong>{model.name}</strong>\n *               <span>{model.contextWindow.toLocaleString()} tokens</span>\n *               <span>${model.inputCostPer1M}/1M input</span>\n *             </li>\n *           ))}\n *         </ul>\n *       )}\n *     </div>\n *   )\n * }\n * ```\n */\nexport function useModels(options: UseModelsOptions = {}): UseModelsReturn {\n\tconst ctx = useAIContext()\n\tconst queryClient = useQueryClient()\n\tconst [search, setSearch] = useState(options.search ?? '')\n\tconst [capability, setCapability] = useState(options.capability)\n\tconst [debouncedSearch, setDebouncedSearch] = useState(search)\n\tconst pageSize = options.pageSize ?? 50\n\n\t// Debounce search input\n\tuseEffect(() => {\n\t\tconst timer = setTimeout(() => {\n\t\t\tsetDebouncedSearch(search)\n\t\t}, 300)\n\t\treturn () => clearTimeout(timer)\n\t}, [search])\n\n\t// React Query infinite query for paginated models\n\tconst modelsQuery = useInfiniteQuery({\n\t\tqueryKey: ['sylphx', 'ai-models', capability, debouncedSearch, pageSize],\n\t\tqueryFn: async ({ pageParam = 0 }) => {\n\t\t\treturn ctx.listModels({\n\t\t\t\tcapability,\n\t\t\t\tsearch: debouncedSearch || undefined,\n\t\t\t\tlimit: pageSize,\n\t\t\t\toffset: pageParam,\n\t\t\t})\n\t\t},\n\t\tinitialPageParam: 0,\n\t\tgetNextPageParam: (lastPage, allPages) => {\n\t\t\tif (!lastPage.hasMore) return undefined\n\t\t\treturn allPages.length * pageSize\n\t\t},\n\t\tenabled: options.fetchOnMount !== false,\n\t\tstaleTime: STALE_TIME_STABLE_MS, // 5 min - model list is stable\n\t})\n\n\t// Flatten all pages into single models array\n\tconst models = useMemo(\n\t\t() => modelsQuery.data?.pages.flatMap((page) => page.models) ?? [],\n\t\t[modelsQuery.data],\n\t)\n\tconst total = modelsQuery.data?.pages[0]?.total ?? 0\n\n\t// Fetch (refresh) via React Query invalidation\n\tconst fetch = useCallback(async () => {\n\t\tawait queryClient.invalidateQueries({\n\t\t\tqueryKey: ['sylphx', 'ai-models'],\n\t\t})\n\t}, [queryClient])\n\n\t// Load more via fetchNextPage\n\tconst loadMore = useCallback(async () => {\n\t\tif (modelsQuery.hasNextPage && !modelsQuery.isFetchingNextPage) {\n\t\t\tawait modelsQuery.fetchNextPage()\n\t\t}\n\t}, [modelsQuery])\n\n\treturn {\n\t\tmodels,\n\t\ttotal,\n\t\thasMore: modelsQuery.hasNextPage ?? false,\n\t\tisLoading: modelsQuery.isLoading,\n\t\terror: modelsQuery.error as Error | null,\n\t\tfetch,\n\t\tloadMore,\n\t\tsetSearch,\n\t\tsetCapability,\n\t}\n}\n","/**\n * Services Context\n *\n * React Context for all SDK services including Auth, AI, Jobs, etc.\n * All types are imported from types.ts (SSOT).\n */\n\nimport { type Context, createContext, useContext } from 'react'\n\n// ============================================================================\n// Import ALL types from types.ts\n// ============================================================================\n\n// Cross-layer SDK types (consent/webhooks wire re-exports) live in `../types`.\nimport type {\n\t// Consent\n\tConsentCategory,\n\tConsentType,\n\tUserConsent,\n\t// Webhooks\n\tWebhookConfig,\n\tWebhookDeliveriesResult,\n\tWebhookStats,\n} from '../types'\n// React-layer (tRPC-like wrapper) shapes live in `./types`.\nimport type {\n\tAIListModelsResponse,\n\tAIRateLimitInfo,\n\tAIUsagePeriod,\n\t// AI\n\tAIUsageStats,\n\t// Monitoring\n\tCaptureExceptionResult,\n\tCaptureMessageResult,\n\tConnectedAccount,\n\tCreateCronInput,\n\tCreateCronResult,\n\tGetDeliveriesInput,\n\tLoginHistoryEntry,\n\tMonitoringLevel,\n\tNewsletterPreferences,\n\t// Newsletter\n\tNewsletterSubscribeInput,\n\tNewsletterSubscribeResult,\n\tNewsletterUnsubscribeInfo,\n\tNewsletterUnsubscribeResult,\n\tNewsletterVerifyResult,\n\tPasskeyInfo,\n\tReplayDeliveryResult,\n\tScheduleJobInput,\n\tScheduleJobResult,\n\tSecurityFactor,\n\tSecurityGrade,\n\tSecurityPriority,\n\tSecurityRecommendation,\n\tSecurityScoreResult,\n\t// Email\n\tSendEmailResult,\n\tSetConsentsResult,\n\tTwoFactorSetupResult,\n\t// Security\n\tTwoFactorStatus,\n\tTwoFactorVerifyResult,\n\tUpdateWebhookConfigInput,\n\tUpdateWebhookConfigResult,\n\tUserSessionInfo,\n\tWebhookStatsPeriod,\n} from './types'\n\n// Re-export commonly used types for convenience\nexport type {\n\t// Tasks (note: Task/TasksListResult are SDK-specific, defined below)\n\n\tScheduleJobInput,\n\tScheduleJobResult,\n\tCreateCronInput,\n\tCreateCronResult,\n\t// Webhooks\n\tWebhookConfig,\n\t// Consent\n\tConsentCategory,\n\tConsentType,\n\tUserConsent,\n\t// User\n\n\tLoginHistoryEntry,\n\tUserSessionInfo,\n\tConnectedAccount,\n\t// Security\n\tTwoFactorStatus,\n\tTwoFactorSetupResult,\n\tPasskeyInfo,\n\tSecurityScoreResult,\n\tSecurityFactor,\n\tSecurityRecommendation,\n\tSecurityPriority,\n\tSecurityGrade,\n\t// AI\n\tAIUsageStats,\n\tAIListModelsResponse,\n}\n\n// ============================================================================\n// SDK-Specific Job Types\n// The SDK layer uses its own job status enum that includes all possible states\n// ============================================================================\n\n/** Job status - includes all possible states */\nexport type JobStatus =\n\t| 'pending'\n\t| 'queued'\n\t| 'running'\n\t| 'completed'\n\t| 'failed'\n\t| 'cancelled'\n\t| 'scheduled'\n\t| 'paused'\n\t| 'deleted'\n\n/** Task status filter for listing tasks */\nexport type TaskStatusFilter = JobStatus\n\n// ============================================================================\n// Email Types\n// ============================================================================\n\nexport interface EmailOptions {\n\tto: string\n\tsubject: string\n\thtml: string\n\ttext?: string\n\treplyTo?: string\n}\n\n/** Simple alias for EmailOptions */\nexport type SimpleEmailOptions = EmailOptions\n\n/** Email delivery status */\nexport type EmailStatus = 'sent' | 'pending' | 'failed'\n\n/** Email template name type */\nexport type EmailTemplateName = string\n\n// ============================================================================\n// Consent Types\n// ============================================================================\n\nimport type {\n\tConsentHistoryResult,\n\tConsentPurposeDefaults,\n\tGetConsentHistoryInput,\n} from '../consent'\nexport type { ConsentPurposeDefaults, ConsentHistoryResult, GetConsentHistoryInput }\n\n// ============================================================================\n// SDK-Specific Types for Monitoring (Sentry-compatible)\n// ============================================================================\n\n/** Stack frame for exception tracing */\nexport interface StackFrame {\n\tfilename?: string\n\tfunction?: string\n\tlineno?: number\n\tcolno?: number\n\tin_app?: boolean\n}\n\n/** Exception value with stack trace */\nexport interface ExceptionValue {\n\ttype: string\n\tvalue: string\n\tstacktrace?: {\n\t\tframes: StackFrame[]\n\t}\n}\n\n/** Breadcrumb for debugging context */\nexport interface Breadcrumb {\n\ttype?: string\n\tcategory?: string\n\tmessage?: string\n\tlevel?: MonitoringLevel\n\tdata?: Record<string, unknown>\n\ttimestamp?: number\n}\n\n/** Options for captureException */\nexport interface CaptureExceptionOptions {\n\tlevel?: MonitoringLevel\n\ttags?: Record<string, string>\n\textra?: Record<string, unknown>\n\tfingerprint?: string[]\n\troute?: string\n\tuserAgent?: string\n}\n\n/** Options for captureMessage */\nexport interface CaptureMessageOptions {\n\tlevel?: MonitoringLevel\n\ttags?: Record<string, string>\n\textra?: Record<string, unknown>\n\troute?: string\n}\n\n// ============================================================================\n// SDK-Specific Types for Newsletter\n// ============================================================================\n\n/** Subscriber status */\nexport type SubscriberStatus = 'pending' | 'active' | 'unsubscribed'\n\n/** Subscriber preference key type */\nexport type SubscriberPreferenceKey = string\n\n/** Subscriber type for newsletter */\nexport interface Subscriber {\n\temail: string\n\tname?: string\n\tstatus: SubscriberStatus\n\tpreferences?: Record<string, boolean>\n\tsubscribedAt?: string\n\tunsubscribedAt?: string\n}\n\n// Import AI types that are SDK-specific (not from router)\nimport type {\n\tAIListModelsOptions,\n\tAIStreamChunk,\n\tChatCompletionInput,\n\tChatCompletionResponse,\n\tEmbeddingInput,\n\tEmbeddingResponse,\n\tTextCompletionInput,\n\tTextCompletionResponse,\n\tVisionInput,\n} from './types'\n\n// ============================================\n// SDK-Specific Types (not from router)\n// ============================================\n\n/**\n * Standard async operation state\n */\nexport interface AsyncState<TError = Error> {\n\t/** Whether an operation is in progress */\n\tisLoading: boolean\n\t/** Last error from an operation */\n\terror: TError | null\n}\n\n/**\n * Standard data fetch state\n */\nexport interface DataState<T, TError = Error> extends AsyncState<TError> {\n\t/** The fetched data */\n\tdata: T | null\n\t/** Whether there was an error */\n\tisError: boolean\n}\n\n// ============================================\n// Generic Context Helper\n// ============================================\n\n/**\n * Generic helper to get required context value\n * Throws descriptive error if used outside provider\n */\nexport function useRequiredContext<T>(context: Context<T | null>, serviceName: string): T {\n\tconst value = useContext(context)\n\tif (!value) {\n\t\tthrow new Error(`${serviceName} hooks must be used within a SylphxProvider`)\n\t}\n\treturn value\n}\n\n// ============================================\n// AI Context\n// ============================================\n\nexport interface AIContextValue {\n\tchat: (input: ChatCompletionInput) => Promise<ChatCompletionResponse>\n\tchatStream: (input: ChatCompletionInput) => AsyncIterable<AIStreamChunk>\n\tcomplete: (input: TextCompletionInput) => Promise<TextCompletionResponse>\n\tembed: (input: EmbeddingInput) => Promise<EmbeddingResponse>\n\tvision: (input: VisionInput) => Promise<ChatCompletionResponse>\n\tgetUsage: (period: AIUsagePeriod) => Promise<AIUsageStats>\n\tgetRateLimitStatus: () => Promise<AIRateLimitInfo>\n\tlistModels: (options?: AIListModelsOptions) => Promise<AIListModelsResponse>\n}\n\nexport const AIContext = createContext<AIContextValue | null>(null)\n\nexport function useAIContext(): AIContextValue {\n\treturn useRequiredContext(AIContext, 'AI')\n}\n\n// ============================================\n// Tasks Context\n// ============================================\n\n/** Job type with all optional fields for flexibility */\nexport interface Job {\n\tid: string\n\tscheduleId?: string | null\n\tname: string | null\n\ttype: string\n\tstatus: JobStatus\n\tcallbackUrl: string\n\tpayload?: unknown\n\tscheduledFor: string | null\n\tstartedAt?: string | null\n\tcompletedAt?: string | null\n\tfailedAt?: string | null\n\terrorMessage?: string | null\n\tlastError?: string | null\n\tretries: number\n\tmaxRetries: number\n\tcreatedAt: string\n}\n\n/** Result of checkStatus() for the Tasks service */\nexport interface TasksStatusResult {\n\tavailable: boolean\n}\n\n// Backward-compat / forward-compat aliases\nexport type Task = Job\nexport type TaskStatus = JobStatus\n/** @deprecated Use TaskStatusFilter */\nexport type JobStatusFilter = TaskStatusFilter\n\n/** Tasks List Result */\nexport interface TasksListResult {\n\ttasks: Job[]\n\ttotal: number\n\tlimit?: number\n\toffset?: number\n\thasMore?: boolean\n}\n\nexport interface TasksContextValue {\n\tcheckStatus: () => Promise<TasksStatusResult>\n\tschedule: (options: ScheduleJobInput) => Promise<ScheduleJobResult>\n\tcreateCron: (options: CreateCronInput) => Promise<CreateCronResult>\n\tpauseCron: (scheduleId: string) => Promise<boolean>\n\tresumeCron: (scheduleId: string) => Promise<boolean>\n\tdeleteCron: (scheduleId: string) => Promise<boolean>\n\tgetJob: (jobId: string) => Promise<Job>\n\tlistTasks: (options?: {\n\t\tstatus?: TaskStatusFilter\n\t\ttype?: 'one-time' | 'cron'\n\t\tlimit?: number\n\t\toffset?: number\n\t}) => Promise<TasksListResult>\n\t/** @deprecated Use listTasks */\n\tlistJobs: TasksContextValue['listTasks']\n\tcancelJob: (jobId: string) => Promise<boolean>\n}\n\n// Context + hook\nexport const TasksContext = createContext<TasksContextValue | null>(null)\n/** @deprecated Use TasksContext */\nexport const JobsContext = TasksContext\nexport type JobsContextValue = TasksContextValue\n\nexport function useTasksContext(): TasksContextValue {\n\treturn useRequiredContext(TasksContext, 'Tasks')\n}\n\n/** @deprecated Use useTasksContext instead */\nexport const useJobsContext = useTasksContext\n\n// ============================================\n// Monitoring Context\n// ============================================\n\nexport interface MonitoringContextValue {\n\tcaptureException: (\n\t\terror: Error,\n\t\toptions?: {\n\t\t\tlevel?: MonitoringLevel\n\t\t\ttags?: Record<string, string>\n\t\t\textra?: Record<string, unknown>\n\t\t\tfingerprint?: string[]\n\t\t\troute?: string\n\t\t\tuserAgent?: string\n\t\t},\n\t) => Promise<CaptureExceptionResult>\n\tcaptureMessage: (\n\t\tmessage: string,\n\t\toptions?: {\n\t\t\tlevel?: MonitoringLevel\n\t\t\ttags?: Record<string, string>\n\t\t\textra?: Record<string, unknown>\n\t\t\troute?: string\n\t\t},\n\t) => Promise<CaptureMessageResult>\n}\n\nexport const MonitoringContext = createContext<MonitoringContextValue | null>(null)\n\nexport function useMonitoringContext(): MonitoringContextValue {\n\treturn useRequiredContext(MonitoringContext, 'Monitoring')\n}\n\n// ============================================\n// Consent Context\n// ============================================\n\nexport interface ConsentContextValue {\n\tanonymousId: string | null\n\tuserId: string | null\n\tgetConsentTypes: () => Promise<ConsentType[]>\n\tgetUserConsents: () => Promise<UserConsent[]>\n\tsetConsents: (consents: { slug: string; granted: boolean }[]) => Promise<SetConsentsResult>\n\tacceptAll: () => Promise<SetConsentsResult>\n\tdeclineOptional: () => Promise<SetConsentsResult>\n\t/** Check consent for a purpose with optional inline defaults for auto-discovery */\n\tcheckConsent: (purposeSlug: string, defaults?: ConsentPurposeDefaults) => Promise<boolean>\n\t/** Get consent change history for GDPR audit trail */\n\tgetHistory: (\n\t\toptions?: Pick<GetConsentHistoryInput, 'limit' | 'cursor'>,\n\t) => Promise<ConsentHistoryResult>\n\t/** Consent types from server-fetched config */\n\tinitialConsentTypes: ConsentType[]\n}\n\nexport const ConsentContext = createContext<ConsentContextValue | null>(null)\n\nexport function useConsentContext(): ConsentContextValue {\n\treturn useRequiredContext(ConsentContext, 'Consent')\n}\n\n// ============================================\n// Newsletter Context (Marketing/Bulk Email)\n// ============================================\n\nexport interface NewsletterContextValue {\n\tsubscribe: (options: NewsletterSubscribeInput) => Promise<NewsletterSubscribeResult>\n\tverify: (token: string) => Promise<NewsletterVerifyResult>\n\tunsubscribe: (email: string, token: string) => Promise<NewsletterUnsubscribeResult>\n\tresendVerification: (email: string) => Promise<{ success: boolean; message: string }>\n\tgetUnsubscribeInfo: (token: string) => Promise<NewsletterUnsubscribeInfo>\n\tupdatePreferences: (\n\t\temail: string,\n\t\tpreferences: Record<string, boolean>,\n\t) => Promise<{\n\t\tsuccess: boolean\n\t\tpreferences: Array<{ key: string; enabled: boolean }>\n\t}>\n\tgetPreferences: (email: string) => Promise<NewsletterPreferences>\n}\n\nexport const NewsletterContext = createContext<NewsletterContextValue | null>(null)\n\nexport function useNewsletterContext(): NewsletterContextValue {\n\treturn useRequiredContext(NewsletterContext, 'Newsletter')\n}\n\n// ============================================\n// Database Context\n// ============================================\n\nexport interface QueryResult<T = unknown> {\n\trows: T[]\n\trowCount: number\n}\n\nexport interface DatabaseContextValue {\n\tquery: <T = unknown>(sql: string, params?: unknown[]) => Promise<QueryResult<T>>\n\texecute: (sql: string, params?: unknown[]) => Promise<{ rowCount: number }>\n\ttransaction: <T>(fn: (tx: DatabaseContextValue) => Promise<T>) => Promise<T>\n}\n\nexport const DatabaseContext = createContext<DatabaseContextValue | null>(null)\n\nexport function useDatabaseContext(): DatabaseContextValue {\n\treturn useRequiredContext(DatabaseContext, 'Database')\n}\n\n// ============================================\n// Email Context\n// ============================================\n\nexport interface EmailContextValue {\n\tsend: (options: {\n\t\tto: string\n\t\tsubject: string\n\t\thtml: string\n\t\ttext?: string\n\t\treplyTo?: string\n\t}) => Promise<SendEmailResult>\n\tsendTemplated: (options: {\n\t\ttemplate: string\n\t\tto: string\n\t\tdata?: Record<string, unknown>\n\t}) => Promise<{ success: boolean; template: string }>\n\tsendToUser: (options: {\n\t\tuserId: string\n\t\tsubject: string\n\t\thtml: string\n\t\ttext?: string\n\t}) => Promise<SendEmailResult>\n\tnewsletter: NewsletterContextValue\n}\n\nexport const EmailContext = createContext<EmailContextValue | null>(null)\n\nexport function useEmailContext(): EmailContextValue {\n\treturn useRequiredContext(EmailContext, 'Email')\n}\n\n// ============================================\n// Webhooks Context\n// ============================================\n\nexport interface WebhooksContextValue {\n\tgetConfig: () => Promise<WebhookConfig>\n\tupdateConfig: (options: UpdateWebhookConfigInput) => Promise<UpdateWebhookConfigResult>\n\tgetDeliveries: (options?: GetDeliveriesInput) => Promise<WebhookDeliveriesResult>\n\treplayDelivery: (deliveryId: string) => Promise<ReplayDeliveryResult>\n\tgetStats: (period: WebhookStatsPeriod) => Promise<WebhookStats>\n}\n\nexport const WebhooksContext = createContext<WebhooksContextValue | null>(null)\n\nexport function useWebhooksContext(): WebhooksContextValue {\n\treturn useRequiredContext(WebhooksContext, 'Webhooks')\n}\n\n// ============================================\n// Auth Context (SDK Auth for direct API calls)\n// ============================================\n\n/**\n * Authenticated user from SDK auth operations (login, 2FA, me())\n *\n * Includes security-related fields like twoFactorEnabled.\n * For basic user data without auth fields, use User from types.ts.\n */\nexport interface AuthUser {\n\tid: string\n\temail: string\n\tname: string | null\n\timage: string | null\n\temailVerified: boolean\n\ttwoFactorEnabled: boolean\n}\n\n/** Login result shape from SDK */\nexport interface SdkLoginResult {\n\trequiresTwoFactor: boolean\n\tuserId?: string\n\tuser?: AuthUser\n}\n\n/** 2FA verification result shape from SDK */\nexport interface SdkVerify2FAResult {\n\taccessToken: string\n\trefreshToken: string\n\texpiresIn: number\n\tuser: AuthUser\n}\n\n/** Registration result shape from SDK (minimal user data before setup) */\nexport interface SdkRegisterResult {\n\trequiresVerification: boolean\n\tmessage: string\n\tuser: {\n\t\tid: string\n\t\temail: string\n\t\tname: string | null\n\t}\n}\n\nexport interface SdkAuthContextValue {\n\tlogin: (email: string, password: string) => Promise<SdkLoginResult>\n\tverifyTwoFactor: (userId: string, code: string) => Promise<SdkVerify2FAResult>\n\tregister: (\n\t\tname: string,\n\t\temail: string,\n\t\tpassword: string,\n\t\toptions?: {\n\t\t\tcaptchaToken?: string\n\t\t\tinvitationToken?: string\n\t\t\tmetadata?: Record<string, unknown>\n\t\t},\n\t) => Promise<SdkRegisterResult>\n\tforgotPassword: (\n\t\temail: string,\n\t\toptions?: { redirectUrl?: string },\n\t) => Promise<{ success: boolean; message: string }>\n\tresetPassword: (token: string, password: string) => Promise<{ success: boolean }>\n\tverifyEmail: (token: string) => Promise<{ success: boolean }>\n\tlogout: (refreshToken?: string) => Promise<{ success: boolean }>\n\tme: () => Promise<AuthUser>\n\tgetOAuthProviders: () => Promise<{ providers: string[] }>\n}\n\nexport const SdkAuthContext = createContext<SdkAuthContextValue | null>(null)\n\nexport function useSdkAuthContext(): SdkAuthContextValue {\n\treturn useRequiredContext(SdkAuthContext, 'SdkAuth')\n}\n\n// ============================================\n// User Context\n// ============================================\n\n/** SDK User Profile (includes computed fields) */\nexport interface SdkUserProfile {\n\tid: string\n\temail: string\n\tname: string | null\n\timage: string | null\n\temailVerified: boolean\n\ttwoFactorEnabled: boolean\n\tcreatedAt: Date\n}\n\n/** SDK Login History Entry (transformed from API) */\nexport interface SdkLoginHistoryEntry {\n\tid: string\n\tipAddress: string | null\n\tuserAgent: string | null\n\tlocation: string | null\n\tdevice: string | null\n\tbrowser: string | null\n\tos: string | null\n\tloginAt: Date\n\t/** Whether login was successful (matches API field name) */\n\tsuccess: boolean\n}\n\n/** SDK Connected Account (transformed from API) */\nexport interface SdkConnectedAccount {\n\tprovider: string\n\taccountId: string\n\temail: string | null\n\tname: string | null\n\timage: string | null\n\tconnectedAt: Date\n}\n\nexport interface UserContextValue {\n\tgetProfile: () => Promise<SdkUserProfile>\n\tupdateProfile: (data: { name?: string; image?: string }) => Promise<SdkUserProfile>\n\tchangePassword: (currentPassword: string, newPassword: string) => Promise<{ success: boolean }>\n\tgetLoginHistory: (options?: { limit?: number }) => Promise<SdkLoginHistoryEntry[]>\n\tgetSessions: () => Promise<UserSessionInfo[]>\n\trevokeSession: (sessionId: string) => Promise<{ success: boolean }>\n\trenameSession: (sessionId: string, name: string) => Promise<{ success: boolean }>\n\trevokeAllSessions: () => Promise<{ success: boolean; count: number }>\n\tgetConnectedAccounts: () => Promise<SdkConnectedAccount[]>\n\tdeleteAccount: (password?: string) => Promise<{ success: boolean }>\n\texportData: () => Promise<{ downloadUrl: string; expiresAt: Date }>\n}\n\nexport const UserContext = createContext<UserContextValue | null>(null)\n\nexport function useUserContext(): UserContextValue {\n\treturn useRequiredContext(UserContext, 'User')\n}\n\n// ============================================\n// Security Context\n// ============================================\n\n/** SDK 2FA Status */\nexport interface SdkTwoFactorStatus {\n\tenabled: boolean\n\tbackupCodesRemaining: number\n}\n\n/** SDK Password Status */\nexport interface SdkPasswordStatus {\n\thasPassword: boolean\n}\n\n/** SDK Passkey Info (transformed from API) */\nexport interface SdkPasskeyInfo {\n\tid: string\n\tname?: string\n\tdeviceType?: string\n\tcreatedAt: Date\n\tlastUsedAt: Date | null\n}\n\n/** SDK Security Alert (transformed from API) */\nexport interface SdkSecurityAlert {\n\tid: string\n\ttype: string\n\ttitle: string\n\tdescription: string | null\n\tmetadata: Record<string, unknown> | null\n\tread: boolean\n\tcreatedAt: Date\n}\n\n/** SDK Security Alerts Result */\nexport interface SdkSecurityAlertsResult {\n\talerts: SdkSecurityAlert[]\n\ttotal: number\n}\n\nexport interface SecurityContextValue {\n\tgetTwoFactorStatus: () => Promise<SdkTwoFactorStatus>\n\ttwoFactorSetup: () => Promise<TwoFactorSetupResult>\n\ttwoFactorVerify: (code: string) => Promise<TwoFactorVerifyResult>\n\ttwoFactorDisable: (code: string) => Promise<{ success: boolean }>\n\tbackupCodesView: (code: string) => Promise<{ codes: string[]; remaining?: number }>\n\tbackupCodesRegenerate: (code: string) => Promise<{ codes: string[] }>\n\tgetPasswordStatus: () => Promise<SdkPasswordStatus>\n\tpasswordSet: (password: string) => Promise<{ success: boolean }>\n\temailChangeRequest: (newEmail: string) => Promise<{ success: boolean; message: string }>\n\temailChangeConfirm: (token: string) => Promise<{ success: boolean; newEmail: string }>\n\tpasskeyList: () => Promise<SdkPasskeyInfo[]>\n\tpasskeyRegisterStart: () => Promise<unknown>\n\tpasskeyRegisterVerify: (credential: unknown, name?: string) => Promise<SdkPasskeyInfo>\n\tpasskeyRename: (passkeyId: string, name: string) => Promise<{ success: boolean }>\n\tpasskeyDelete: (passkeyId: string) => Promise<{ success: boolean }>\n\toauthConnect: (provider: string) => Promise<{ redirectUrl: string }>\n\toauthDisconnect: (provider: string) => Promise<{ success: boolean }>\n\tgetSecurityScore: () => Promise<SecurityScoreResult>\n\t// Security Alerts\n\tgetSecurityAlerts: (options?: {\n\t\tlimit?: number\n\t\tunreadOnly?: boolean\n\t}) => Promise<SdkSecurityAlertsResult>\n\tmarkAlertRead: (alertId: string) => Promise<{ success: boolean }>\n\tmarkAllAlertsRead: () => Promise<{ success: boolean }>\n}\n\nexport const SecurityContext = createContext<SecurityContextValue | null>(null)\n\nexport function useSecurityContext(): SecurityContextValue {\n\treturn useRequiredContext(SecurityContext, 'Security')\n}\n","/**\n * BillingCard Component\n *\n * Displays current subscription status with manage options.\n * Shows plan name, status, renewal date, and upgrade CTA.\n */\n\n'use client'\n\nimport { useCallback, useEffect, useState } from 'react'\nimport { RequireSdk } from '../hooks'\nimport { useBilling } from '../platform-hooks'\nimport {\n\tbaseStyles,\n\tdefaultTheme,\n\tinjectGlobalStyles,\n\tmergeStyles,\n\ttype ThemeVariables,\n} from '../ui/styles'\n\nexport interface BillingCardProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** URL to pricing page */\n\tpricingUrl?: string\n\t/** Show manage subscription button */\n\tshowManageButton?: boolean\n\t/** Show upgrade CTA for free users */\n\tshowUpgradeCta?: boolean\n\t/** Callback when portal is opened */\n\tonPortalOpen?: () => void\n\t/** Callback on error */\n\tonError?: (error: string) => void\n\t/** Custom class name */\n\tclassName?: string\n\t/** Card variant */\n\tvariant?: 'default' | 'compact' | 'detailed'\n}\n\n/**\n * BillingCard component for subscription status display\n *\n * @example\n * ```tsx\n * <BillingCard\n *   showUpgradeCta\n *   pricingUrl=\"/pricing\"\n * />\n * ```\n */\nexport function BillingCard(props: BillingCardProps) {\n\treturn (\n\t\t<RequireSdk services={['billing']} componentType=\"billing\" theme={props.theme}>\n\t\t\t<BillingCardInner {...props} />\n\t\t</RequireSdk>\n\t)\n}\n\n/** Inner component that safely uses platform hooks */\nfunction BillingCardInner({\n\ttheme = defaultTheme,\n\tpricingUrl = '/pricing',\n\tshowManageButton = true,\n\tshowUpgradeCta = true,\n\tonPortalOpen,\n\tonError,\n\tclassName,\n\tvariant = 'default',\n}: BillingCardProps) {\n\tconst { subscription, isLoading, isPremium, isTrialing, openPortal, plans } = useBilling()\n\tconst styles = baseStyles(theme)\n\n\tconst [isOpeningPortal, setIsOpeningPortal] = useState(false)\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tconst handleManageSubscription = useCallback(async () => {\n\t\tsetIsOpeningPortal(true)\n\t\tonPortalOpen?.()\n\n\t\ttry {\n\t\t\tawait openPortal()\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to open billing portal'\n\t\t\tonError?.(message)\n\t\t} finally {\n\t\t\tsetIsOpeningPortal(false)\n\t\t}\n\t}, [openPortal, onPortalOpen, onError])\n\n\tif (isLoading) {\n\t\treturn (\n\t\t\t<div style={styles.card} className={className}>\n\t\t\t\t<div\n\t\t\t\t\tstyle={mergeStyles(styles.cardContent, styles.flexCenter, {\n\t\t\t\t\t\tpadding: '2rem',\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\t<span\n\t\t\t\t\t\tstyle={mergeStyles(styles.spinner, {\n\t\t\t\t\t\t\twidth: '1.5rem',\n\t\t\t\t\t\t\theight: '1.5rem',\n\t\t\t\t\t\t})}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t)\n\t}\n\n\t// Get status badge color\n\tconst getStatusBadge = () => {\n\t\tif (!subscription) return null\n\n\t\tconst statusConfig: Record<string, { bg: string; color: string; label: string }> = {\n\t\t\tactive: {\n\t\t\t\tbg: `${theme.colorSuccess}15`,\n\t\t\t\tcolor: theme.colorSuccess,\n\t\t\t\tlabel: 'Active',\n\t\t\t},\n\t\t\ttrialing: {\n\t\t\t\tbg: `${theme.colorPrimary}15`,\n\t\t\t\tcolor: theme.colorPrimary,\n\t\t\t\tlabel: 'Trial',\n\t\t\t},\n\t\t\tpast_due: {\n\t\t\t\tbg: `${theme.colorWarning}15`,\n\t\t\t\tcolor: theme.colorWarning,\n\t\t\t\tlabel: 'Past Due',\n\t\t\t},\n\t\t\tcanceled: {\n\t\t\t\tbg: `${theme.colorMutedForeground}15`,\n\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\tlabel: 'Canceled',\n\t\t\t},\n\t\t\tunpaid: {\n\t\t\t\tbg: `${theme.colorDestructive}15`,\n\t\t\t\tcolor: theme.colorDestructive,\n\t\t\t\tlabel: 'Unpaid',\n\t\t\t},\n\t\t}\n\n\t\tconst config = statusConfig[subscription.status] || statusConfig.active\n\t\treturn (\n\t\t\t<span\n\t\t\t\tstyle={{\n\t\t\t\t\tdisplay: 'inline-flex',\n\t\t\t\t\talignItems: 'center',\n\t\t\t\t\tpadding: '0.125rem 0.5rem',\n\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\tborderRadius: '9999px',\n\t\t\t\t\tbackgroundColor: config.bg,\n\t\t\t\t\tcolor: config.color,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{config.label}\n\t\t\t</span>\n\t\t)\n\t}\n\n\t// Format date\n\tconst formatDate = (dateStr: string | null | undefined) => {\n\t\tif (!dateStr) return 'N/A'\n\t\treturn new Date(dateStr).toLocaleDateString(undefined, {\n\t\t\tyear: 'numeric',\n\t\t\tmonth: 'long',\n\t\t\tday: 'numeric',\n\t\t})\n\t}\n\n\t// Compact variant\n\tif (variant === 'compact') {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tstyle={mergeStyles(styles.flexBetween, {\n\t\t\t\t\tpadding: '0.75rem 1rem',\n\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t})}\n\t\t\t\tclassName={className}\n\t\t\t>\n\t\t\t\t<div style={styles.flexRow}>\n\t\t\t\t\t<span style={{ fontWeight: 500, marginRight: '0.5rem' }}>\n\t\t\t\t\t\t{subscription?.planSlug || 'Free'}\n\t\t\t\t\t</span>\n\t\t\t\t\t{getStatusBadge()}\n\t\t\t\t</div>\n\t\t\t\t{isPremium && showManageButton && (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={handleManageSubscription}\n\t\t\t\t\t\tdisabled={isOpeningPortal}\n\t\t\t\t\t\tstyle={mergeStyles(styles.link, { fontSize: theme.fontSizeSm })}\n\t\t\t\t\t>\n\t\t\t\t\t\t{isOpeningPortal ? 'Opening...' : 'Manage'}\n\t\t\t\t\t</button>\n\t\t\t\t)}\n\t\t\t\t{!isPremium && showUpgradeCta && (\n\t\t\t\t\t<a\n\t\t\t\t\t\thref={pricingUrl}\n\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary, {\n\t\t\t\t\t\t\tpadding: '0.25rem 0.75rem',\n\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\tUpgrade\n\t\t\t\t\t</a>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t)\n\t}\n\n\t// Free user - show upgrade CTA\n\tif (!isPremium && showUpgradeCta) {\n\t\t// Find the best plan to highlight (first paid plan or 'pro')\n\t\tconst highlightPlan =\n\t\t\tplans.find((p) => p.slug === 'pro') || plans.find((p) => (p.monthlyPrice ?? 0) > 0)\n\n\t\treturn (\n\t\t\t<div style={styles.card} className={className}>\n\t\t\t\t<div style={styles.cardContent}>\n\t\t\t\t\t<div style={styles.flexBetween}>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<h3\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.cardTitle, {\n\t\t\t\t\t\t\t\t\tmarginBottom: '0.25rem',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tFree Plan\n\t\t\t\t\t\t\t</h3>\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tUpgrade to unlock premium features\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<CrownIcon color={theme.colorWarning} size={32} />\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t\t\t\tpadding: '0.75rem',\n\t\t\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ul\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tlistStyle: 'none',\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{highlightPlan?.features?.slice(0, 3).map((feature: string, i: number) => (\n\t\t\t\t\t\t\t\t<li\n\t\t\t\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<CheckIcon color={theme.colorSuccess} size={16} />\n\t\t\t\t\t\t\t\t\t{feature}\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<a\n\t\t\t\t\t\thref={pricingUrl}\n\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary, styles.buttonFullWidth, {\n\t\t\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t<SparklesIcon size={16} />\n\t\t\t\t\t\tUpgrade Now\n\t\t\t\t\t</a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t)\n\t}\n\n\t// Premium user - show subscription details\n\treturn (\n\t\t<div style={styles.card} className={className}>\n\t\t\t<div style={styles.cardContent}>\n\t\t\t\t{/* Header */}\n\t\t\t\t<div style={mergeStyles(styles.flexBetween, { marginBottom: '1rem' })}>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.flexRow, {\n\t\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<h3 style={mergeStyles(styles.cardTitle, { margin: 0 })}>\n\t\t\t\t\t\t\t\t{subscription?.planSlug || 'Free'}\n\t\t\t\t\t\t\t</h3>\n\t\t\t\t\t\t\t{getStatusBadge()}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t{subscription?.interval && (\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tBilled {subscription.interval}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t\t{isPremium && <CrownIcon color={theme.colorWarning} size={28} />}\n\t\t\t\t</div>\n\n\t\t\t\t{/* Detailed variant - show more info */}\n\t\t\t\t{variant === 'detailed' && subscription && (\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tdisplay: 'grid',\n\t\t\t\t\t\t\tgridTemplateColumns: 'repeat(2, 1fr)',\n\t\t\t\t\t\t\tgap: '1rem',\n\t\t\t\t\t\t\tmarginBottom: '1rem',\n\t\t\t\t\t\t\tpadding: '1rem',\n\t\t\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textXs, styles.textMuted, {\n\t\t\t\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tPlan\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, {\n\t\t\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{subscription.planSlug}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textXs, styles.textMuted, {\n\t\t\t\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{subscription.cancelAtPeriodEnd ? 'Ends' : 'Renews'}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, {\n\t\t\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{formatDate(subscription.currentPeriodEnd)}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Trial banner */}\n\t\t\t\t{isTrialing && subscription?.trialEnd && (\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tmarginBottom: '1rem',\n\t\t\t\t\t\t\tpadding: '0.75rem',\n\t\t\t\t\t\t\tbackgroundColor: `${theme.colorPrimary}10`,\n\t\t\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\t\t\tborder: `1px solid ${theme.colorPrimary}30`,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.flexRow, {\n\t\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<ClockIcon color={theme.colorPrimary} size={16} />\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\t\tcolor: theme.colorPrimary,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tTrial ends {formatDate(subscription.trialEnd)}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Cancellation warning */}\n\t\t\t\t{subscription?.cancelAtPeriodEnd && (\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tmarginBottom: '1rem',\n\t\t\t\t\t\t\tpadding: '0.75rem',\n\t\t\t\t\t\t\tbackgroundColor: `${theme.colorWarning}10`,\n\t\t\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\t\t\tborder: `1px solid ${theme.colorWarning}30`,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.flexRow, {\n\t\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<AlertIcon color={theme.colorWarning} size={16} />\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\t\tcolor: theme.colorWarning,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tYour subscription will end on {formatDate(subscription.currentPeriodEnd)}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Action buttons */}\n\t\t\t\t{showManageButton && (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={handleManageSubscription}\n\t\t\t\t\t\tdisabled={isOpeningPortal}\n\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\t\tstyles.buttonOutline,\n\t\t\t\t\t\t\tstyles.buttonFullWidth,\n\t\t\t\t\t\t\tisOpeningPortal ? styles.buttonDisabled : {},\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{isOpeningPortal ? (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t\t\t\tOpening...\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<SettingsIcon size={16} />\n\t\t\t\t\t\t\t\tManage Subscription\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</button>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n// Icons\nfunction CrownIcon({ color, size = 24 }: { color: string; size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill={color}\n\t\t\tstroke=\"none\"\n\t\t\tstyle={{ flexShrink: 0 }}\n\t\t>\n\t\t\t<path d=\"M2 4l3 12h14l3-12-6 7-4-9-4 9-6-7zm3 14h14v2H5v-2z\" />\n\t\t</svg>\n\t)\n}\n\nfunction SparklesIcon({ size = 24 }: { size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tstyle={{ flexShrink: 0 }}\n\t\t>\n\t\t\t<path d=\"m12 3-1.912 5.813a2 2 0 0 1-1.275 1.275L3 12l5.813 1.912a2 2 0 0 1 1.275 1.275L12 21l1.912-5.813a2 2 0 0 1 1.275-1.275L21 12l-5.813-1.912a2 2 0 0 1-1.275-1.275L12 3Z\" />\n\t\t\t<path d=\"M5 3v4\" />\n\t\t\t<path d=\"M19 17v4\" />\n\t\t\t<path d=\"M3 5h4\" />\n\t\t\t<path d=\"M17 19h4\" />\n\t\t</svg>\n\t)\n}\n\nfunction CheckIcon({ color, size = 24 }: { color: string; size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tstyle={{ flexShrink: 0 }}\n\t\t>\n\t\t\t<path d=\"M20 6 9 17l-5-5\" />\n\t\t</svg>\n\t)\n}\n\nfunction ClockIcon({ color, size = 24 }: { color: string; size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tstyle={{ flexShrink: 0 }}\n\t\t>\n\t\t\t<circle cx=\"12\" cy=\"12\" r=\"10\" />\n\t\t\t<polyline points=\"12 6 12 12 16 14\" />\n\t\t</svg>\n\t)\n}\n\nfunction AlertIcon({ color, size = 24 }: { color: string; size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tstyle={{ flexShrink: 0 }}\n\t\t>\n\t\t\t<path d=\"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\" />\n\t\t\t<line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\" />\n\t\t\t<line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\" />\n\t\t</svg>\n\t)\n}\n\nfunction SettingsIcon({ size = 24 }: { size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tstyle={{ flexShrink: 0 }}\n\t\t>\n\t\t\t<path d=\"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z\" />\n\t\t\t<circle cx=\"12\" cy=\"12\" r=\"3\" />\n\t\t</svg>\n\t)\n}\n","/**\n * Sylphx React Hooks\n *\n * Hooks for accessing authentication state and actions.\n */\n\n'use client'\n\nimport { useCallback, useContext, useEffect, useRef, useState } from 'react'\nimport type { User } from '../types'\nimport {\n\tAuthContext,\n\ttype AuthContextValue,\n\ttype ForgotPasswordOptions,\n\ttype ResendVerificationEmailOptions,\n\ttype ResetPasswordOptions,\n\ttype SignInOptions,\n\ttype SignInWithOAuthOptions,\n\ttype VerifyEmailOptions,\n} from './context'\nimport { PlatformContext } from './platform-context'\nimport { useRequiredContext } from './services-context'\n\n/**\n * Internal hook to get auth context\n */\nfunction useAuthContext(): AuthContextValue {\n\treturn useRequiredContext(AuthContext, 'Auth')\n}\n\n/**\n * Internal hook to get auth context (safe version - returns null if no provider)\n */\nfunction useAuthContextSafe(): AuthContextValue | null {\n\treturn useContext(AuthContext)\n}\n\n/**\n * Internal hook to get platform context\n */\nfunction usePlatformContextInternal() {\n\treturn useRequiredContext(PlatformContext, 'Platform')\n}\n\n/**\n * Convert HeadersInit to Record<string, string>\n */\nfunction _headersToRecord(headers?: HeadersInit): Record<string, string> {\n\tif (!headers) return {}\n\tif (headers instanceof Headers) {\n\t\tconst result: Record<string, string> = {}\n\t\theaders.forEach((value, key) => {\n\t\t\tresult[key] = value\n\t\t})\n\t\treturn result\n\t}\n\tif (Array.isArray(headers)) {\n\t\treturn Object.fromEntries(headers)\n\t}\n\treturn headers as Record<string, string>\n}\n\n// ============================================\n// useUser\n// ============================================\n\nexport interface UseUserReturn {\n\t/** Whether auth state has been loaded */\n\tisLoaded: boolean\n\t/** Whether auth state is still loading (inverse of isLoaded) */\n\tisLoading: boolean\n\t/** Whether user is signed in */\n\tisSignedIn: boolean\n\t/** Current user data (null if not signed in) */\n\tuser: User | null\n\t/** Refresh user data from server */\n\trefresh: () => Promise<void>\n}\n\n/**\n * Hook to get the current user\n *\n * @example\n * ```tsx\n * function Profile() {\n *   const { user, isLoaded, isSignedIn, refresh } = useUser()\n *\n *   if (!isLoaded) return <Spinner />\n *   if (!isSignedIn) return <SignIn />\n *\n *   return <div>Hello, {user.name}!</div>\n * }\n * ```\n */\nexport function useUser(): UseUserReturn {\n\tconst { isLoaded, isSignedIn, user, getToken } = useAuthContext()\n\tconst platform = useContext(PlatformContext)\n\n\tconst refresh = useCallback(async () => {\n\t\t// Cookie keep-alive only (ADR-3457) — getToken never returns a bearer.\n\t\ttry {\n\t\t\tawait getToken()\n\t\t\tif (platform) {\n\t\t\t\twindow.dispatchEvent(\n\t\t\t\t\tnew StorageEvent('storage', {\n\t\t\t\t\t\tkey: `sylphx_${platform.appId}_user`,\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t}\n\t\t} catch {\n\t\t\t// Silently fail - session refresh errors are handled by the auth context\n\t\t}\n\t}, [getToken, platform])\n\n\treturn { isLoaded, isLoading: !isLoaded, isSignedIn, user, refresh }\n}\n\n// ============================================\n// useAuth\n// ============================================\n\nexport interface UseAuthReturn {\n\t/** Whether user is signed in */\n\tisSignedIn: boolean\n\t/** Auth error (e.g., token refresh failed) */\n\terror: Error | null\n\t/** Whether there was an auth error */\n\tisError: boolean\n\t/** Whether an OAuth flow is in progress */\n\tisOAuthLoading: boolean\n\t/** OAuth-specific error */\n\toauthError: Error | null\n\t/** Clear OAuth error state */\n\tclearOAuthError: () => void\n\t/** Redirect to sign in page */\n\tsignIn: (options?: SignInOptions) => void\n\t/** Redirect to sign up page */\n\tsignUp: (options?: SignInOptions) => void\n\t/** Sign out the current user */\n\tsignOut: (options?: { redirectUrl?: string }) => Promise<void>\n\t/** Get current access token (auto-refreshes if needed) */\n\tgetToken: () => Promise<string | null>\n\t/** Reset password with token */\n\tresetPassword: (options: ResetPasswordOptions) => Promise<void>\n\t/** Verify email with token */\n\tverifyEmail: (options: VerifyEmailOptions) => Promise<void>\n\t/** Resend verification email */\n\tresendVerificationEmail: (options: ResendVerificationEmailOptions) => Promise<void>\n\t/** Request password reset email */\n\tforgotPassword: (options: ForgotPasswordOptions) => Promise<void>\n\n\t// ==========================================\n\t// Direct OAuth Methods (Firebase/Supabase pattern)\n\t// User goes directly to OAuth provider - no platform UI\n\t// ==========================================\n\n\t/**\n\t * Sign in with OAuth provider directly (Firebase/Supabase pattern).\n\t * Redirects user straight to OAuth provider - no platform login UI.\n\t *\n\t * @example\n\t * ```tsx\n\t * const { signInWithOAuth } = useAuth()\n\t * await signInWithOAuth({ provider: 'google', redirectUrl: '/dashboard' })\n\t * ```\n\t */\n\tsignInWithOAuth: (options: SignInWithOAuthOptions) => Promise<void>\n\n\t/** Convenience: Sign in with Google directly */\n\tsignInWithGoogle: (redirectUrl?: string) => Promise<void>\n\n\t/** Convenience: Sign in with GitHub directly */\n\tsignInWithGithub: (redirectUrl?: string) => Promise<void>\n\n\t/** Convenience: Sign in with Apple directly */\n\tsignInWithApple: (redirectUrl?: string) => Promise<void>\n\n\t/** Convenience: Sign in with Discord directly */\n\tsignInWithDiscord: (redirectUrl?: string) => Promise<void>\n\n\t/** Convenience: Sign in with Twitter directly */\n\tsignInWithTwitter: (redirectUrl?: string) => Promise<void>\n\n\t/** Convenience: Sign in with Microsoft directly */\n\tsignInWithMicrosoft: (redirectUrl?: string) => Promise<void>\n}\n\n/**\n * Hook to get auth actions\n *\n * @example\n * ```tsx\n * function LoginButton() {\n *   const { signIn, isSignedIn } = useAuth()\n *\n *   if (isSignedIn) return null\n *\n *   return (\n *     <button onClick={() => signIn({ redirectUrl: '/dashboard' })}>\n *       Sign In\n *     </button>\n *   )\n * }\n * ```\n */\nexport function useAuth(): UseAuthReturn {\n\tconst {\n\t\tisSignedIn,\n\t\tsignIn,\n\t\tsignUp,\n\t\tsignOut,\n\t\tgetToken,\n\t\terror,\n\t\tisOAuthLoading,\n\t\toauthError,\n\t\tclearOAuthError,\n\t\tresetPassword,\n\t\tverifyEmail,\n\t\tresendVerificationEmail,\n\t\tforgotPassword,\n\t\t// Direct OAuth methods\n\t\tsignInWithOAuth,\n\t\tsignInWithGoogle,\n\t\tsignInWithGithub,\n\t\tsignInWithApple,\n\t\tsignInWithDiscord,\n\t\tsignInWithTwitter,\n\t\tsignInWithMicrosoft,\n\t} = useAuthContext()\n\n\treturn {\n\t\tisSignedIn,\n\t\terror,\n\t\tisError: error !== null,\n\t\tisOAuthLoading,\n\t\toauthError,\n\t\tclearOAuthError,\n\t\tsignIn,\n\t\tsignUp,\n\t\tsignOut,\n\t\tgetToken,\n\t\tresetPassword,\n\t\tverifyEmail,\n\t\tresendVerificationEmail,\n\t\tforgotPassword,\n\t\t// Direct OAuth methods (Firebase/Supabase pattern)\n\t\tsignInWithOAuth,\n\t\tsignInWithGoogle,\n\t\tsignInWithGithub,\n\t\tsignInWithApple,\n\t\tsignInWithDiscord,\n\t\tsignInWithTwitter,\n\t\tsignInWithMicrosoft,\n\t}\n}\n\n// ============================================\n// useSafeUser (doesn't throw when outside provider)\n// ============================================\n\nexport interface UseSafeUserReturn {\n\t/** Whether Sylphx is configured (provider is mounted) */\n\tisConfigured: boolean\n\t/** Whether auth state has been loaded */\n\tisLoaded: boolean\n\t/** Whether auth state is still loading */\n\tisLoading: boolean\n\t/** Whether user is signed in */\n\tisSignedIn: boolean\n\t/** Current user data (null if not signed in or not configured) */\n\tuser: User | null\n}\n\n/**\n * Safe version of useUser that doesn't throw when outside SylphxProvider.\n * Use this for optional auth features that should gracefully degrade.\n *\n * @example\n * ```tsx\n * function OptionalUserDisplay() {\n *   const { isConfigured, user } = useSafeUser()\n *\n *   if (!isConfigured) return null // Sylphx not set up\n *   if (!user) return <SignInPrompt />\n *\n *   return <span>Hi, {user.name}</span>\n * }\n * ```\n */\nexport function useSafeUser(): UseSafeUserReturn {\n\tconst context = useAuthContextSafe()\n\n\tif (!context) {\n\t\treturn {\n\t\t\tisConfigured: false,\n\t\t\tisLoaded: true,\n\t\t\tisLoading: false,\n\t\t\tisSignedIn: false,\n\t\t\tuser: null,\n\t\t}\n\t}\n\n\treturn {\n\t\tisConfigured: true,\n\t\tisLoaded: context.isLoaded,\n\t\tisLoading: !context.isLoaded,\n\t\tisSignedIn: context.isSignedIn,\n\t\tuser: context.user,\n\t}\n}\n\n// ============================================\n// useSafeAuth (doesn't throw when outside provider)\n// ============================================\n\nexport interface UseSafeAuthReturn {\n\t/** Whether Sylphx is configured (provider is mounted) */\n\tisConfigured: boolean\n\t/** Whether user is signed in */\n\tisSignedIn: boolean\n\t/** Auth error (null if not configured) */\n\terror: Error | null\n\t/** Whether there was an auth error */\n\tisError: boolean\n\t/** Whether an OAuth flow is in progress */\n\tisOAuthLoading: boolean\n\t/** OAuth-specific error */\n\toauthError: Error | null\n\t/** Clear OAuth error state */\n\tclearOAuthError: () => void\n\t/** Redirect to sign in page (no-op if not configured) */\n\tsignIn: (options?: SignInOptions) => void\n\t/** Redirect to sign up page (no-op if not configured) */\n\tsignUp: (options?: SignInOptions) => void\n\t/** Sign out the current user (no-op if not configured) */\n\tsignOut: (options?: { redirectUrl?: string }) => Promise<void>\n\t/** Get current access token (returns null if not configured) */\n\tgetToken: () => Promise<string | null>\n\t/** Reset password with token (throws if not configured) */\n\tresetPassword: ((options: ResetPasswordOptions) => Promise<void>) | null\n\t/** Verify email with token (throws if not configured) */\n\tverifyEmail: ((options: VerifyEmailOptions) => Promise<void>) | null\n\t/** Resend verification email (throws if not configured) */\n\tresendVerificationEmail: ((options: ResendVerificationEmailOptions) => Promise<void>) | null\n\t/** Request password reset email (throws if not configured) */\n\tforgotPassword: ((options: ForgotPasswordOptions) => Promise<void>) | null\n\n\t// ==========================================\n\t// Direct OAuth Methods (Firebase/Supabase pattern)\n\t// User goes directly to OAuth provider - no platform UI\n\t// ==========================================\n\n\t/**\n\t * Sign in with OAuth provider directly (Firebase/Supabase pattern).\n\t * Redirects user straight to OAuth provider - no platform login UI.\n\t *\n\t * @example\n\t * ```tsx\n\t * const { signInWithOAuth } = useSafeAuth()\n\t *\n\t * // Direct to Google consent screen\n\t * await signInWithOAuth({ provider: 'google' })\n\t * ```\n\t */\n\tsignInWithOAuth: ((options: SignInWithOAuthOptions) => Promise<void>) | null\n\n\t/** Convenience: Sign in with Google directly */\n\tsignInWithGoogle: ((redirectUrl?: string) => Promise<void>) | null\n\n\t/** Convenience: Sign in with GitHub directly */\n\tsignInWithGithub: ((redirectUrl?: string) => Promise<void>) | null\n\n\t/** Convenience: Sign in with Apple directly */\n\tsignInWithApple: ((redirectUrl?: string) => Promise<void>) | null\n\n\t/** Convenience: Sign in with Discord directly */\n\tsignInWithDiscord: ((redirectUrl?: string) => Promise<void>) | null\n\n\t/** Convenience: Sign in with Twitter directly */\n\tsignInWithTwitter: ((redirectUrl?: string) => Promise<void>) | null\n\n\t/** Convenience: Sign in with Microsoft directly */\n\tsignInWithMicrosoft: ((redirectUrl?: string) => Promise<void>) | null\n}\n\n/**\n * Safe version of useAuth that doesn't throw when outside SylphxProvider.\n * Use this for optional auth features that should gracefully degrade.\n *\n * @example\n * ```tsx\n * function LogoutButton() {\n *   const { isConfigured, isSignedIn, signOut } = useSafeAuth()\n *\n *   if (!isConfigured || !isSignedIn) return null\n *\n *   return <button onClick={() => signOut()}>Sign Out</button>\n * }\n * ```\n */\nexport function useSafeAuth(): UseSafeAuthReturn {\n\tconst context = useAuthContextSafe()\n\n\tif (!context) {\n\t\treturn {\n\t\t\tisConfigured: false,\n\t\t\tisSignedIn: false,\n\t\t\terror: null,\n\t\t\tisError: false,\n\t\t\tisOAuthLoading: false,\n\t\t\toauthError: null,\n\t\t\tclearOAuthError: () => {},\n\t\t\tsignIn: () => {},\n\t\t\tsignUp: () => {},\n\t\t\tsignOut: async () => {},\n\t\t\tgetToken: async () => null,\n\t\t\tresetPassword: null,\n\t\t\tverifyEmail: null,\n\t\t\tresendVerificationEmail: null,\n\t\t\tforgotPassword: null,\n\t\t\t// Direct OAuth methods (not configured)\n\t\t\tsignInWithOAuth: null,\n\t\t\tsignInWithGoogle: null,\n\t\t\tsignInWithGithub: null,\n\t\t\tsignInWithApple: null,\n\t\t\tsignInWithDiscord: null,\n\t\t\tsignInWithTwitter: null,\n\t\t\tsignInWithMicrosoft: null,\n\t\t}\n\t}\n\n\treturn {\n\t\tisConfigured: true,\n\t\tisSignedIn: context.isSignedIn,\n\t\terror: context.error,\n\t\tisError: context.error !== null,\n\t\tisOAuthLoading: context.isOAuthLoading,\n\t\toauthError: context.oauthError,\n\t\tclearOAuthError: context.clearOAuthError,\n\t\tsignIn: context.signIn,\n\t\tsignUp: context.signUp,\n\t\tsignOut: context.signOut,\n\t\tgetToken: context.getToken,\n\t\tresetPassword: context.resetPassword,\n\t\tverifyEmail: context.verifyEmail,\n\t\tresendVerificationEmail: context.resendVerificationEmail,\n\t\tforgotPassword: context.forgotPassword,\n\t\t// Direct OAuth methods (Firebase/Supabase pattern)\n\t\tsignInWithOAuth: context.signInWithOAuth,\n\t\tsignInWithGoogle: context.signInWithGoogle,\n\t\tsignInWithGithub: context.signInWithGithub,\n\t\tsignInWithApple: context.signInWithApple,\n\t\tsignInWithDiscord: context.signInWithDiscord,\n\t\tsignInWithTwitter: context.signInWithTwitter,\n\t\tsignInWithMicrosoft: context.signInWithMicrosoft,\n\t}\n}\n\n// ============================================\n// useSession\n// ============================================\n\n/**\n * Current authentication session state\n * Note: This is different from DeviceSession which represents active device sessions\n */\nexport interface AuthSession {\n\t/** Current user */\n\tuser: User\n\t/** Access token */\n\taccessToken: string\n}\n\nexport interface UseSessionReturn {\n\t/** Whether session has been loaded */\n\tisLoaded: boolean\n\t/** Current session (null if not signed in) */\n\tsession: AuthSession | null\n}\n\n/**\n * Hook to get the current session\n *\n * @example\n * ```tsx\n * function Dashboard() {\n *   const { session, isLoaded } = useSession()\n *\n *   if (!isLoaded) return <Spinner />\n *   if (!session) return <Redirect to=\"/login\" />\n *\n *   return (\n *     <div>\n *       <h1>Welcome, {session.user.name}</h1>\n *     </div>\n *   )\n * }\n * ```\n */\nexport function useSession(): UseSessionReturn {\n\tconst { isLoaded, isSignedIn, user, accessToken } = useAuthContext()\n\n\tif (!isLoaded) {\n\t\treturn { isLoaded: false, session: null }\n\t}\n\n\tif (!isSignedIn || !user || !accessToken) {\n\t\treturn { isLoaded: true, session: null }\n\t}\n\n\treturn {\n\t\tisLoaded: true,\n\t\tsession: {\n\t\t\tuser,\n\t\t\taccessToken,\n\t\t},\n\t}\n}\n\n// ============================================\n// useSylphx (convenience hook)\n// ============================================\n\n/**\n * Client-side SDK configuration (subset of PlatformContextValue)\n *\n * This is different from SylphxConfig in config.ts which is for pure functions.\n * Use this type for client-side context access.\n */\nexport interface SylphxClientConfig {\n\t/** App ID (environment-specific: app_dev_xxx, app_stg_xxx, app_prod_xxx) */\n\tappId: string\n\t/** Platform API URL */\n\tplatformUrl: string\n\t/** Project ref (16-char alphanumeric nanoid). Preferred for createConfig(). */\n\tref?: string\n}\n\nexport interface UseSylphxReturn extends AuthContextValue {\n\t/** SDK configuration */\n\tconfig: SylphxClientConfig\n}\n\n/**\n * Full access to Sylphx context including config\n *\n * Prefer using useUser, useAuth, or useSession for specific needs.\n */\nexport function useSylphx(): UseSylphxReturn {\n\tconst auth = useAuthContext()\n\tconst platform = usePlatformContextInternal()\n\n\treturn {\n\t\t...auth,\n\t\tconfig: {\n\t\t\tappId: platform.appId,\n\t\t\tplatformUrl: platform.platformUrl,\n\t\t},\n\t}\n}\n\n// ============================================\n// useOrganization\n// Full organization management via SDK REST API\n// ============================================\n\nimport { createConfig } from '../config'\nimport type {\n\tCreateOrgInput,\n\tOrganization,\n\tOrganizationInvitation,\n\tOrganizationMember,\n\tOrgRole,\n} from '../orgs'\n// Import Organization types and functions from orgs.ts (SSOT)\nimport * as OrgFunctions from '../orgs'\n\nexport type { Organization, OrganizationMember, OrganizationInvitation, OrgRole }\n\nfunction mutableOrganizations(organizations: readonly Organization[]): Organization[] {\n\treturn [...organizations]\n}\n\n/**\n * Return type for useOrganization hook\n */\nexport interface UseOrganizationReturn {\n\t/** Current selected organization */\n\torganization: Organization | null\n\t/** List of all user's organizations */\n\torganizations: Organization[]\n\t/** Members of current organization */\n\tmembers: OrganizationMember[]\n\t/** Pending invitations (if admin) */\n\tinvitations: OrganizationInvitation[]\n\t/** Whether data is loading */\n\tisLoading: boolean\n\t/** Loading error */\n\terror: Error | null\n\t/** User's role in current organization */\n\trole: OrgRole | null\n\t/** Check if user has a specific permission */\n\thasPermission: (\n\t\tpermission: 'manage_members' | 'access_billing' | 'manage_apps' | 'view_analytics',\n\t) => boolean\n\t/** Switch to a different organization */\n\tsetOrganization: (orgIdOrSlug: string | null) => Promise<void>\n\t/** Switch to a different organization and refresh the active session token. */\n\tswitchOrg: (orgIdOrSlug: string | null) => Promise<void>\n\t/** Create a new organization */\n\tcreateOrganization: (data: CreateOrgInput) => Promise<Organization>\n\t/** Update current organization */\n\tupdateOrganization: (data: {\n\t\tname?: string\n\t\tslug?: string\n\t\tlogoUrl?: string | null\n\t}) => Promise<Organization>\n\t/** Delete current organization (requires super_admin) */\n\tdeleteOrganization: () => Promise<void>\n\t/** Invite a member to current organization */\n\tinviteMember: (email: string, role: OrgRole) => Promise<OrganizationInvitation>\n\t/** Update a member's role */\n\tupdateMemberRole: (userId: string, role: OrgRole) => Promise<OrganizationMember>\n\t/** Remove a member from organization */\n\tremoveMember: (userId: string) => Promise<void>\n\t/** Leave current organization */\n\tleave: () => Promise<void>\n\t/** Revoke a pending invitation */\n\trevokeInvitation: (invitationId: string) => Promise<void>\n\t/** Refresh organization data */\n\trefresh: () => Promise<void>\n}\n\n// Cross-tab sync constants for organizations (Clerk pattern)\nconst ORG_STORAGE_KEY = 'sylphx_active_org'\nconst ORG_BROADCAST_CHANNEL = 'sylphx_org_sync'\n\n/**\n * Hook to manage organizations and RBAC\n *\n * Provides full organization management including CRUD operations,\n * member management, and invitation handling.\n *\n * ## Cross-Tab Sync (Clerk Pattern)\n * Organization context automatically syncs across browser tabs via:\n * - BroadcastChannel API for instant sync between tabs\n * - localStorage fallback for persistence\n *\n * @example\n * ```tsx\n * function OrgSettings() {\n *   const { organization, organizations, isLoading, role } = useOrganization()\n *\n *   if (isLoading) return <Spinner />\n *   if (!organization) return <CreateOrgForm />\n *\n *   return (\n *     <div>\n *       <h1>{organization.name}</h1>\n *       <p>Your role: {role}</p>\n *     </div>\n *   )\n * }\n * ```\n */\nexport function useOrganization(): UseOrganizationReturn {\n\tconst platform = useContext(PlatformContext)\n\tconst auth = useAuthContextSafe()\n\n\t// Initialize from localStorage for SSR safety\n\tconst [organizations, setOrganizations] = useState<Organization[]>([])\n\tconst [organization, setOrganization] = useState<Organization | null>(null)\n\tconst [members, setMembers] = useState<OrganizationMember[]>([])\n\tconst [invitations, setInvitations] = useState<OrganizationInvitation[]>([])\n\tconst [role, setRole] = useState<OrgRole | null>(null)\n\tconst [isLoading, setIsLoading] = useState(true)\n\tconst [error, setError] = useState<Error | null>(null)\n\n\t// BroadcastChannel ref for cross-tab sync (Clerk pattern)\n\tconst channelRef = useRef<BroadcastChannel | null>(null)\n\n\t// Create config for API calls using platform context\n\tconst config = platform?.slug\n\t\t? createConfig({\n\t\t\t\tsecretKey: platform.appId,\n\t\t\t\tslug: platform.slug,\n\t\t\t})\n\t\t: null\n\n\t// Get stored org slug from localStorage\n\tconst getStoredOrgSlug = useCallback((): string | null => {\n\t\tif (typeof window === 'undefined') return null\n\t\ttry {\n\t\t\tconst key = platform?.appId ? `${ORG_STORAGE_KEY}_${platform.appId}` : ORG_STORAGE_KEY\n\t\t\treturn localStorage.getItem(key)\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}, [platform?.appId])\n\n\t// Store org slug to localStorage\n\tconst storeOrgSlug = useCallback(\n\t\t(slug: string | null) => {\n\t\t\tif (typeof window === 'undefined') return\n\t\t\ttry {\n\t\t\t\tconst key = platform?.appId ? `${ORG_STORAGE_KEY}_${platform.appId}` : ORG_STORAGE_KEY\n\t\t\t\tif (slug) {\n\t\t\t\t\tlocalStorage.setItem(key, slug)\n\t\t\t\t} else {\n\t\t\t\t\tlocalStorage.removeItem(key)\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Ignore storage errors\n\t\t\t}\n\t\t},\n\t\t[platform?.appId],\n\t)\n\n\t// Broadcast org change to other tabs (Clerk pattern)\n\tconst broadcastOrgChange = useCallback((org: Organization | null) => {\n\t\tif (channelRef.current) {\n\t\t\tchannelRef.current.postMessage({\n\t\t\t\ttype: 'org_change',\n\t\t\t\torganization: org,\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t})\n\t\t}\n\t}, [])\n\n\t// Set up cross-tab sync via BroadcastChannel (Clerk pattern)\n\tuseEffect(() => {\n\t\tif (typeof window === 'undefined' || !('BroadcastChannel' in window)) return\n\n\t\tconst channelName = platform?.appId\n\t\t\t? `${ORG_BROADCAST_CHANNEL}_${platform.appId}`\n\t\t\t: ORG_BROADCAST_CHANNEL\n\n\t\tconst channel = new BroadcastChannel(channelName)\n\t\tchannelRef.current = channel\n\n\t\tchannel.onmessage = (event) => {\n\t\t\tif (event.data.type === 'org_change') {\n\t\t\t\tconst newOrg = event.data.organization as Organization | null\n\t\t\t\tsetOrganization(newOrg)\n\t\t\t\tsetRole(null) // Role will be refreshed on next load\n\t\t\t\t// Store the change locally too\n\t\t\t\tstoreOrgSlug(newOrg?.slug ?? null)\n\t\t\t}\n\t\t}\n\n\t\treturn () => {\n\t\t\tchannel.close()\n\t\t\tchannelRef.current = null\n\t\t}\n\t}, [platform?.appId, storeOrgSlug])\n\n\t// Load organizations on mount (with localStorage restore)\n\n\tconst selectOrganization = useCallback(\n\t\tasync (orgIdOrSlug: string | null) => {\n\t\t\tif (!config || !orgIdOrSlug) {\n\t\t\t\tsetOrganization(null)\n\t\t\t\tsetMembers([])\n\t\t\t\tsetInvitations([])\n\t\t\t\tsetRole(null)\n\t\t\t\tstoreOrgSlug(null)\n\t\t\t\tbroadcastOrgChange(null)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst result = await OrgFunctions.getOrganization(config, orgIdOrSlug)\n\t\t\t\tif (auth?.isSignedIn) {\n\t\t\t\t\tawait auth.switchOrganizationToken(result.organization.id)\n\t\t\t\t}\n\t\t\t\tsetOrganization(result.organization)\n\t\t\t\tsetRole(result.membership?.role ?? null)\n\n\t\t\t\t// Persist selection to localStorage and broadcast to other tabs\n\t\t\t\tstoreOrgSlug(result.organization.slug)\n\t\t\t\tbroadcastOrgChange(result.organization)\n\n\t\t\t\t// Load members\n\t\t\t\tconst membersResult = await OrgFunctions.getOrganizationMembers(config, orgIdOrSlug)\n\t\t\t\tsetMembers(membersResult.members)\n\n\t\t\t\t// Load invitations if admin\n\t\t\t\tif (result.membership && ['super_admin', 'admin'].includes(result.membership.role)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst invResult = await OrgFunctions.getOrganizationInvitations(config, orgIdOrSlug)\n\t\t\t\t\t\tsetInvitations(invResult.invitations)\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// May not have permission\n\t\t\t\t\t\tsetInvitations([])\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tsetInvitations([])\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tsetError(err instanceof Error ? err : new Error('Failed to load organization'))\n\t\t\t}\n\t\t},\n\t\t[auth, config, storeOrgSlug, broadcastOrgChange],\n\t)\n\n\tuseEffect(() => {\n\t\tif (!config) {\n\t\t\tsetIsLoading(false)\n\t\t\treturn\n\t\t}\n\n\t\tlet mounted = true\n\n\t\tasync function loadOrgs() {\n\t\t\ttry {\n\t\t\t\tconst result = await OrgFunctions.getOrganizations(config!)\n\t\t\t\tif (mounted) {\n\t\t\t\t\tconst organizations = mutableOrganizations(result.organizations)\n\t\t\t\t\tsetOrganizations(organizations)\n\n\t\t\t\t\t// Restore from localStorage first, then fallback to first org\n\t\t\t\t\tconst storedSlug = getStoredOrgSlug()\n\t\t\t\t\tconst orgToSelect = storedSlug\n\t\t\t\t\t\t? organizations.find((o) => o.slug === storedSlug)\n\t\t\t\t\t\t: organizations[0]\n\n\t\t\t\t\tif (orgToSelect && !organization) {\n\t\t\t\t\t\tawait selectOrganization(orgToSelect.slug)\n\t\t\t\t\t}\n\t\t\t\t\tsetIsLoading(false)\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tif (mounted) {\n\t\t\t\t\tsetError(err instanceof Error ? err : new Error('Failed to load organizations'))\n\t\t\t\t\tsetIsLoading(false)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tloadOrgs()\n\t\treturn () => {\n\t\t\tmounted = false\n\t\t}\n\t}, [config?.baseUrl, getStoredOrgSlug, selectOrganization, organization, config])\n\n\t// Select an organization by ID or slug (with cross-tab sync)\n\t// Permission checking\n\tconst hasPermission = useCallback(\n\t\t(permission: string): boolean => {\n\t\t\tif (!role) return false\n\n\t\t\tconst rolePermissions: Record<OrgRole, string[]> = {\n\t\t\t\tsuper_admin: ['manage_members', 'access_billing', 'manage_apps', 'view_analytics'],\n\t\t\t\tadmin: ['manage_members', 'access_billing', 'manage_apps', 'view_analytics'],\n\t\t\t\tbilling: ['access_billing'],\n\t\t\t\tanalytics: ['view_analytics'],\n\t\t\t\tdeveloper: ['manage_apps', 'view_analytics'],\n\t\t\t\tviewer: ['view_analytics'],\n\t\t\t}\n\n\t\t\treturn rolePermissions[role]?.includes(permission) ?? false\n\t\t},\n\t\t[role],\n\t)\n\n\t// CRUD operations\n\tconst createOrg = useCallback(\n\t\tasync (data: CreateOrgInput) => {\n\t\t\tif (!config) throw new Error('Not configured')\n\t\t\tconst result = await OrgFunctions.createOrganization(config, data)\n\t\t\tsetOrganizations((prev) => [...prev, result.organization])\n\t\t\tawait selectOrganization(result.organization.slug)\n\t\t\treturn result.organization\n\t\t},\n\t\t[config, selectOrganization],\n\t)\n\n\tconst updateOrg = useCallback(\n\t\tasync (data: { name?: string; slug?: string; logoUrl?: string | null }) => {\n\t\t\tif (!config || !organization) throw new Error('No organization selected')\n\t\t\tconst result = await OrgFunctions.updateOrganization(config, organization.id, data)\n\t\t\tsetOrganization(result.organization)\n\t\t\tsetOrganizations((prev) =>\n\t\t\t\tprev.map((o) => (o.id === result.organization.id ? result.organization : o)),\n\t\t\t)\n\t\t\treturn result.organization\n\t\t},\n\t\t[config, organization],\n\t)\n\n\tconst deleteOrg = useCallback(async () => {\n\t\tif (!config || !organization) throw new Error('No organization selected')\n\t\tawait OrgFunctions.deleteOrganization(config, organization.id)\n\t\tsetOrganizations((prev) => prev.filter((o) => o.id !== organization.id))\n\t\tconst remaining = organizations.filter((o) => o.id !== organization.id)\n\t\tif (remaining.length > 0) {\n\t\t\tawait selectOrganization(remaining[0].slug)\n\t\t} else {\n\t\t\tsetOrganization(null)\n\t\t\tsetMembers([])\n\t\t\tsetRole(null)\n\t\t}\n\t}, [config, organization, organizations, selectOrganization])\n\n\t// Member operations\n\tconst inviteMember = useCallback(\n\t\tasync (email: string, memberRole: OrgRole) => {\n\t\t\tif (!config || !organization) throw new Error('No organization selected')\n\t\t\tconst result = await OrgFunctions.inviteOrganizationMember(config, organization.id, {\n\t\t\t\temail,\n\t\t\t\trole: memberRole,\n\t\t\t})\n\t\t\tsetInvitations((prev) => [...prev, result.invitation])\n\t\t\treturn result.invitation\n\t\t},\n\t\t[config, organization],\n\t)\n\n\tconst updateMemberRole = useCallback(\n\t\tasync (userId: string, newRole: OrgRole) => {\n\t\t\tif (!config || !organization) throw new Error('No organization selected')\n\t\t\tconst result = await OrgFunctions.updateOrganizationMemberRole(\n\t\t\t\tconfig,\n\t\t\t\torganization.id,\n\t\t\t\tuserId,\n\t\t\t\tnewRole,\n\t\t\t)\n\t\t\tsetMembers((prev) => prev.map((m) => (m.userId === userId ? result.member : m)))\n\t\t\treturn result.member\n\t\t},\n\t\t[config, organization],\n\t)\n\n\tconst removeMember = useCallback(\n\t\tasync (userId: string) => {\n\t\t\tif (!config || !organization) throw new Error('No organization selected')\n\t\t\tawait OrgFunctions.removeOrganizationMember(config, organization.id, userId)\n\t\t\tsetMembers((prev) => prev.filter((m) => m.userId !== userId))\n\t\t},\n\t\t[config, organization],\n\t)\n\n\tconst leave = useCallback(async () => {\n\t\tif (!config || !organization) throw new Error('No organization selected')\n\t\tawait OrgFunctions.leaveOrganization(config, organization.id)\n\t\tsetOrganizations((prev) => prev.filter((o) => o.id !== organization.id))\n\t\tconst remaining = organizations.filter((o) => o.id !== organization.id)\n\t\tif (remaining.length > 0) {\n\t\t\tawait selectOrganization(remaining[0].slug)\n\t\t} else {\n\t\t\tsetOrganization(null)\n\t\t\tsetMembers([])\n\t\t\tsetRole(null)\n\t\t}\n\t}, [config, organization, organizations, selectOrganization])\n\n\tconst revokeInvitation = useCallback(\n\t\tasync (invitationId: string) => {\n\t\t\tif (!config || !organization) throw new Error('No organization selected')\n\t\t\tawait OrgFunctions.revokeOrganizationInvitation(config, organization.id, invitationId)\n\t\t\tsetInvitations((prev) => prev.filter((i) => i.id !== invitationId))\n\t\t},\n\t\t[config, organization],\n\t)\n\n\t// Refresh all data\n\tconst refresh = useCallback(async () => {\n\t\tif (!config) return\n\t\tsetIsLoading(true)\n\t\ttry {\n\t\t\tconst result = await OrgFunctions.getOrganizations(config)\n\t\t\tsetOrganizations(mutableOrganizations(result.organizations))\n\t\t\tif (organization) {\n\t\t\t\tawait selectOrganization(organization.slug)\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tsetError(err instanceof Error ? err : new Error('Failed to refresh'))\n\t\t} finally {\n\t\t\tsetIsLoading(false)\n\t\t}\n\t}, [config, organization, selectOrganization])\n\n\treturn {\n\t\torganization,\n\t\torganizations,\n\t\tmembers,\n\t\tinvitations,\n\t\tisLoading,\n\t\terror,\n\t\trole,\n\t\thasPermission,\n\t\tsetOrganization: selectOrganization,\n\t\tswitchOrg: selectOrganization,\n\t\tcreateOrganization: createOrg,\n\t\tupdateOrganization: updateOrg,\n\t\tdeleteOrganization: deleteOrg,\n\t\tinviteMember,\n\t\tupdateMemberRole,\n\t\tremoveMember,\n\t\tleave,\n\t\trevokeInvitation,\n\t\trefresh,\n\t}\n}\n\n// OAuth Providers Hook - fetch enabled providers from platform\nexport {\n\ttype EnabledProvider,\n\ttype UseOAuthProvidersReturn,\n\tuseOAuthProviders,\n} from './hooks/use-oauth-providers'\n// SDK Ready Hook - SSOT for configuration checking\nexport { RequireSdk, useSdkReady } from './hooks/use-sdk-ready'\n","/**\n * Sylphx Auth Context\n *\n * React context for managing authentication state.\n */\n\nimport { createContext } from 'react'\nimport type { OAuthProviderId, User } from '../types'\n\n// Re-export for convenience\nexport type { OAuthProviderId }\n\nexport interface AuthState {\n\t/** Whether auth state has been loaded from storage */\n\tisLoaded: boolean\n\t/** Whether user is currently signed in */\n\tisSignedIn: boolean\n\t/** Current user data */\n\tuser: User | null\n\t/** Access token for API calls */\n\taccessToken: string | null\n\t/** Refresh token for getting new access tokens */\n\trefreshToken: string | null\n\t/** Auth error (e.g., token refresh failed) */\n\terror: Error | null\n\t/** Whether an OAuth flow is in progress (loading authorization URL or exchanging code) */\n\tisOAuthLoading: boolean\n\t/** OAuth-specific error (e.g., user denied, provider error) */\n\toauthError: Error | null\n}\n\nexport interface SignInOptions {\n\t/** URL to redirect back to after sign in */\n\tredirectUrl?: string\n\t/**\n\t * OAuth providers to show (SDK-level filtering)\n\t * - undefined/null = show all app-enabled providers\n\t * - [] = hide OAuth (email only)\n\t * - ['google'] = only show these\n\t */\n\tproviders?: OAuthProviderId[] | null\n}\n\nexport interface ResetPasswordOptions {\n\t/** Reset password token from email */\n\ttoken: string\n\t/** New password */\n\tnewPassword: string\n}\n\nexport interface VerifyEmailOptions {\n\t/** Verification token from email */\n\ttoken: string\n}\n\nexport interface ResendVerificationEmailOptions {\n\t/** Email address to resend verification to */\n\temail: string\n}\n\nexport interface ForgotPasswordOptions {\n\t/** Email address to send reset link to */\n\temail: string\n\t/** Absolute reset URL. Next.js apps should normally use the SDK middleware route. */\n\tredirectUrl?: string\n}\n\n/**\n * Options for magic link (passwordless) sign-in.\n */\nexport interface SignInWithMagicLinkOptions {\n\t/** Email address to send magic link to */\n\temail: string\n\t/** URL to redirect back to after magic link verification. Defaults to current URL. */\n\tredirectUrl?: string\n}\n\n/**\n * Options for direct OAuth sign-in (Firebase/Supabase pattern).\n * User goes directly to OAuth provider, bypassing platform UI.\n */\nexport interface SignInWithOAuthOptions {\n\t/** OAuth provider to use */\n\tprovider: OAuthProviderId\n\t/** URL to redirect back to after OAuth completes. Defaults to current URL. */\n\tredirectUrl?: string\n\t/**\n\t * Additional OAuth scopes to request from the provider.\n\t * Default scopes (email, profile) are always included.\n\t *\n\t * @example\n\t * ```tsx\n\t * // Request Google Calendar access\n\t * signInWithOAuth({\n\t *   provider: 'google',\n\t *   scopes: ['https://www.googleapis.com/auth/calendar.readonly']\n\t * })\n\t *\n\t * // Request GitHub private repo access\n\t * signInWithOAuth({\n\t *   provider: 'github',\n\t *   scopes: ['repo']\n\t * })\n\t * ```\n\t */\n\tscopes?: string[]\n}\n\nexport interface AuthContextValue extends AuthState {\n\t/** Auth error (e.g., token refresh failed) */\n\terror: Error | null\n\t/** Whether an OAuth flow is in progress */\n\tisOAuthLoading: boolean\n\t/** OAuth-specific error */\n\toauthError: Error | null\n\t/** Clear OAuth error state */\n\tclearOAuthError: () => void\n\t/** Redirect to Sylphx login page (shows platform UI) */\n\tsignIn: (options?: SignInOptions) => void\n\t/** Redirect to Sylphx signup page (shows platform UI) */\n\tsignUp: (options?: SignInOptions) => void\n\t/** Sign out and clear tokens */\n\tsignOut: (options?: { redirectUrl?: string }) => Promise<void>\n\t/** Get current access token (refreshes if expired) */\n\tgetToken: () => Promise<string | null>\n\t/** Exchange the current session for an org-scoped access token. */\n\tswitchOrganizationToken: (orgId: string) => Promise<void>\n\t/** Reset password with token */\n\tresetPassword: (options: ResetPasswordOptions) => Promise<void>\n\t/** Verify email with token */\n\tverifyEmail: (options: VerifyEmailOptions) => Promise<void>\n\t/** Resend verification email */\n\tresendVerificationEmail: (options: ResendVerificationEmailOptions) => Promise<void>\n\t/** Request password reset email */\n\tforgotPassword: (options: ForgotPasswordOptions) => Promise<void>\n\n\t// ==========================================\n\t// Direct OAuth Methods (Firebase/Supabase pattern)\n\t// User goes directly to OAuth provider - no platform UI\n\t// ==========================================\n\n\t/**\n\t * Sign in with OAuth provider directly.\n\t * Redirects user straight to the OAuth provider (Google, GitHub, etc.)\n\t * without showing the platform login UI.\n\t *\n\t * @example\n\t * ```tsx\n\t * const { signInWithOAuth } = useAuth()\n\t *\n\t * // Direct to Google consent screen\n\t * await signInWithOAuth({ provider: 'google' })\n\t *\n\t * // With custom redirect\n\t * await signInWithOAuth({ provider: 'github', redirectUrl: '/dashboard' })\n\t * ```\n\t */\n\tsignInWithOAuth: (options: SignInWithOAuthOptions) => Promise<void>\n\n\t/** Convenience: Sign in with Google directly */\n\tsignInWithGoogle: (redirectUrl?: string) => Promise<void>\n\n\t/** Convenience: Sign in with GitHub directly */\n\tsignInWithGithub: (redirectUrl?: string) => Promise<void>\n\n\t/** Convenience: Sign in with Apple directly */\n\tsignInWithApple: (redirectUrl?: string) => Promise<void>\n\n\t/** Convenience: Sign in with Discord directly */\n\tsignInWithDiscord: (redirectUrl?: string) => Promise<void>\n\n\t/** Convenience: Sign in with Twitter directly */\n\tsignInWithTwitter: (redirectUrl?: string) => Promise<void>\n\n\t/** Convenience: Sign in with Microsoft directly */\n\tsignInWithMicrosoft: (redirectUrl?: string) => Promise<void>\n\n\t// ==========================================\n\t// Magic Link (Passwordless) Methods\n\t// ==========================================\n\n\t/**\n\t * Sign in with magic link (passwordless).\n\t * Sends an email with a one-time login link.\n\t * User clicks the link and is automatically signed in.\n\t *\n\t * @example\n\t * ```tsx\n\t * const { signInWithMagicLink } = useAuth()\n\t *\n\t * // Request magic link email\n\t * await signInWithMagicLink({ email: 'user@example.com' })\n\t *\n\t * // With custom redirect after verification\n\t * await signInWithMagicLink({\n\t *   email: 'user@example.com',\n\t *   redirectUrl: '/dashboard'\n\t * })\n\t * ```\n\t */\n\tsignInWithMagicLink: (options: SignInWithMagicLinkOptions) => Promise<void>\n}\n\nexport const AuthContext = createContext<AuthContextValue | null>(null)\n","/**\n * Platform Context\n *\n * Context for platform services: billing, analytics, push, referrals.\n *\n * Type Strategy:\n * - Types that match API responses are imported from ../types (SSOT)\n * - SDK-specific types (transformed/computed) are defined here with Sdk prefix\n */\n\nimport type { QueryClient } from '@tanstack/react-query'\nimport { createContext } from 'react'\nimport type {\n\tAchievementDefaults,\n\tAchievementUnlockEvent,\n\tLeaderboardDefaults,\n\tLeaderboardQueryOptions,\n\tLeaderboardResult,\n\tRecordActivityResult,\n\tStreakDefaults,\n\tStreakState,\n\tSubmitScoreResult,\n\tUserAchievement,\n} from '../lib/engagement/types'\n// Import referral inline defaults for auto-discovery\nimport type { RedeemResult, ReferralRewardDefaults } from '../referrals'\nimport type { Plan, ReferralStats, Subscription, User } from '../types'\n// React-layer in-app message shapes\nimport type { InAppMessagePriority, InAppMessageType, InAppMessageWithReadStatus } from './types'\nexport type { ReferralRewardDefaults, RedeemResult }\n\n// Re-export types for convenience\nexport type { Plan, ReferralStats, Subscription }\n\n// Re-export InAppMessage types\nexport type { InAppMessageType, InAppMessagePriority, InAppMessageWithReadStatus }\n\nexport interface PushPreferences {\n\tenabled: boolean\n\tsubscriptionCount: number\n\tcategories?: Record<string, boolean>\n}\n\n// ==========================================\n// Mobile Push Types (SDK-specific)\n//\n// These are SDK transformations of the API types.\n// ==========================================\n\n/** SDK mobile push platform - includes 'web' for SDK flexibility */\nexport type MobilePushPlatform = 'ios' | 'android' | 'web'\n\n/** SDK mobile device info */\nexport interface MobileDevice {\n\tid: string\n\tplatform: MobilePushPlatform\n\tname: string | null\n\tregisteredAt: string\n\tlastUsedAt: string | null | undefined\n}\n\n/** SDK mobile push preferences (transformed from API) */\nexport interface MobilePushPreferences {\n\tenabled: boolean\n\tdevices: MobileDevice[]\n}\n\n/** SDK mobile push config (transformed from API) */\nexport interface MobilePushConfig {\n\tios: boolean\n\tandroid: boolean\n\tanyConfigured: boolean\n}\n\n// ==========================================\n// In-App Message Types (SDK-specific)\n// ==========================================\n\nexport interface InboxPreferences {\n\tenabled: boolean\n\tmutedTopics: string[]\n\thighPriorityOnly: boolean\n}\n\n// ==========================================\n// Analytics Types\n// ==========================================\n\n/** Destination platforms for conversion tracking */\nexport type DestinationPlatform = 'google_ads' | 'meta' | 'tiktok'\n\n/**\n * Conversion data for ad platform destinations\n * Used for enhanced conversion tracking (Google Ads, Meta, TikTok)\n */\nexport interface ConversionData {\n\t/** Click ID for attribution (gclid, fbclid, ttclid) */\n\tclickId?: string\n\t/** Conversion value */\n\tvalue?: number\n\t/** Currency code (USD, EUR, etc.) */\n\tcurrency?: string\n\t/** Order ID for deduplication */\n\torderId?: string\n\t/** User email (auto-hashed by destinations) */\n\tuserEmail?: string\n\t/** User phone (auto-hashed by destinations) */\n\tuserPhone?: string\n\t/** User first name (auto-hashed by destinations) */\n\tuserFirstName?: string\n\t/** User last name (auto-hashed by destinations) */\n\tuserLastName?: string\n}\n\n/**\n * Track options for controlling destination forwarding\n */\nexport interface TrackOptions {\n\t/**\n\t * Specific destinations to forward this event to.\n\t * If not specified, events are forwarded to all active destinations with auto-forward enabled.\n\t */\n\tdestinations?: DestinationPlatform[]\n\t/**\n\t * Skip all destination forwarding for this event.\n\t * Useful for internal events that shouldn't be sent to ad platforms.\n\t */\n\tskipDestinations?: boolean\n\t/**\n\t * Conversion data for ad platforms.\n\t * User data (email, phone, name) is automatically hashed before sending.\n\t */\n\tconversion?: ConversionData\n}\n\n// Analytics Query Types (matches server analytics.query input)\nexport interface AnalyticsQuery {\n\t/** Date range start (ISO date string) */\n\tdateFrom?: string\n\t/** Date range end (ISO date string) */\n\tdateTo?: string\n\t/** Events to query */\n\tevents?: string[]\n\t/** Time interval for grouping */\n\tinterval?: 'hour' | 'day' | 'week' | 'month'\n\t/** Limit results */\n\tlimit?: number\n}\n\nexport interface AnalyticsDataPoint {\n\t/** Event name */\n\teventName: string\n\t/** Event count */\n\tcount: number\n}\n\nexport interface AnalyticsQueryResult {\n\t/** Query results */\n\tdata: AnalyticsDataPoint[]\n\t/** Total count */\n\ttotal: number\n}\n\n/**\n * Click IDs for ad platform attribution\n * Automatically captured from URL parameters (gclid, fbclid, ttclid)\n */\nexport interface ClickIds {\n\t/** Google Ads click ID */\n\tgclid?: string\n\t/** Meta/Facebook click ID */\n\tfbclid?: string\n\t/** TikTok click ID */\n\tttclid?: string\n}\n\nexport interface PlatformContextValue {\n\t/** App ID (environment-specific: app_dev_xxx, app_stg_xxx, app_prod_xxx) */\n\tappId: string\n\t/** Platform API URL */\n\tplatformUrl: string\n\t/** Same-origin auth route prefix used by middleware BFF routes. */\n\tauthPrefix: string\n\t/** Project slug (ADR-055) for SDK config */\n\tslug?: string\n\t/**\n\t * @deprecated Use `slug`. Kept for backward compatibility.\n\t */\n\tref?: string\n\t/** Anonymous ID for tracking (persisted in localStorage) */\n\tanonymousId: string\n\t/** React Query client for hooks to use caching/deduplication */\n\tqueryClient: QueryClient\n\t/**\n\t * Auto-captured click IDs for conversion attribution\n\t * Captured from URL on provider mount (gclid, fbclid, ttclid)\n\t * Persisted in localStorage with 90-day expiry\n\t */\n\tclickIds: ClickIds\n\n\t// Billing\n\tsubscription: Subscription | null\n\tsubscriptionLoading: boolean\n\tsubscriptionError: Error | null\n\tplans: Plan[]\n\tplansLoading: boolean\n\tplansError: Error | null\n\tcreateCheckout: (planSlug: string, interval: 'monthly' | 'annual' | 'lifetime') => Promise<string>\n\topenPortal: () => Promise<void>\n\trefreshSubscription: () => Promise<void>\n\n\t// Analytics\n\t/**\n\t * Track a custom event with optional destination forwarding\n\t *\n\t * @example Basic tracking\n\t * ```ts\n\t * track('page_view', { path: '/products' })\n\t * ```\n\t *\n\t * @example Track purchase with conversion data\n\t * ```ts\n\t * track('purchase', { product: 'Premium' }, {\n\t *   destinations: ['google_ads', 'meta'],\n\t *   conversion: {\n\t *     value: 99.99,\n\t *     currency: 'USD',\n\t *     orderId: 'ORDER-123',\n\t *     userEmail: user.email,\n\t *   }\n\t * })\n\t * ```\n\t *\n\t * @example Skip destinations for internal events\n\t * ```ts\n\t * track('button_click', { button: 'nav' }, { skipDestinations: true })\n\t * ```\n\t */\n\ttrack: (\n\t\tevent: string,\n\t\tproperties?: Record<string, unknown>,\n\t\toptions?: TrackOptions,\n\t) => Promise<void>\n\tpage: (name: string, properties?: Record<string, unknown>) => Promise<void>\n\tidentify: (traits?: Record<string, unknown>) => Promise<void>\n\tqueryAnalytics: (query: AnalyticsQuery) => Promise<AnalyticsQueryResult>\n\tanalyticsError: Error | null\n\n\t// Push notifications (Web)\n\tpushSupported: boolean\n\tpushSubscribed: boolean\n\tpushPreferences: PushPreferences | null\n\tpushError: Error | null\n\tsubscribePush: () => Promise<boolean>\n\tunsubscribePush: () => Promise<void>\n\tupdatePushPreferences: (prefs: {\n\t\tenabled?: boolean\n\t\tcategories?: Record<string, boolean>\n\t}) => Promise<void>\n\n\t// Push notifications (Mobile)\n\tmobilePushConfig: MobilePushConfig | null\n\tmobilePushPreferences: MobilePushPreferences | null\n\tmobilePushError: Error | null\n\tregisterMobileDevice: (options: {\n\t\tplatform: MobilePushPlatform\n\t\ttoken: string\n\t\tdeviceId?: string\n\t\tdeviceName?: string\n\t\tappVersion?: string\n\t\tosVersion?: string\n\t}) => Promise<{ success: boolean; tokenId: string }>\n\tunregisterMobileDevice: (token: string) => Promise<void>\n\tgetMobilePushPreferences: () => Promise<MobilePushPreferences>\n\n\t// Referrals\n\treferralStats: ReferralStats | null\n\treferralCode: string | null\n\treferralLoading: boolean\n\treferralError: Error | null\n\tcopyReferralCode: () => Promise<void>\n\tregenerateReferralCode: () => Promise<string>\n\t/**\n\t * Redeem a referral code with optional inline defaults\n\t *\n\t * @param code - Referral code to redeem\n\t * @param defaults - Optional inline defaults for reward configuration\n\t */\n\tredeemReferralCode: (code: string, defaults?: ReferralRewardDefaults) => Promise<RedeemResult>\n\tgetReferralLeaderboard: (options?: {\n\t\tlimit?: number\n\t\tperiod?: 'all' | 'month' | 'week'\n\t}) => Promise<{\n\t\tperiod: 'all' | 'month' | 'week'\n\t\tentries: Array<{\n\t\t\trank: number\n\t\t\tuserId: string | null\n\t\t\t/** Masked username for privacy */\n\t\t\tname: string\n\t\t\tavatarUrl: string | null\n\t\t\t/** Number of successful referrals */\n\t\t\treferrals: number\n\t\t\ttotalReferrals: number\n\t\t\tisCurrentUser: boolean\n\t\t}>\n\t\tcurrentUserRank: number | null\n\t}>\n\n\t// In-App Messages (Inbox)\n\tinboxMessages: InAppMessageWithReadStatus[]\n\tinboxUnreadCount: number\n\tinboxLoading: boolean\n\tinboxError: Error | null\n\tinboxPreferences: InboxPreferences | null\n\trefreshInbox: () => Promise<void>\n\tmarkInboxMessageAsRead: (messageId: string) => Promise<void>\n\tmarkAllInboxMessagesAsRead: () => Promise<void>\n\tdismissInboxMessage: (messageId: string) => Promise<void>\n\trecordInboxMessageClick: (messageId: string, action: 'primary' | 'secondary') => Promise<void>\n\tupdateInboxPreferences: (prefs: {\n\t\tenabled?: boolean\n\t\tmutedTopics?: string[]\n\t\thighPriorityOnly?: boolean\n\t}) => Promise<void>\n\n\t// Direct billing API methods (for advanced use cases)\n\tgetBillingBalance: () => Promise<{\n\t\tbalance: { current: number; currentFormatted: string }\n\t\tstatus: {\n\t\t\tlevel: string\n\t\t\tisHealthy: boolean\n\t\t\tisLow: boolean\n\t\t\talertThreshold: number\n\t\t}\n\t\tbillingType: string\n\t\ttrustLevel: string\n\t\tspendingCap: number | null\n\t\tcurrentMonthSpend: number\n\t\tspendingCapPercent: number | null\n\t\tgracePeriodEndsAt: string | null\n\t\tisAdminOrg: boolean\n\t}>\n\tgetBillingUsage: (options?: { month?: string }) => Promise<{\n\t\tperiod: { type: string; start: string; end: string }\n\t\tmetrics: {\n\t\t\taiCostMicrodollars: number\n\t\t\tstorageBytesUsed: number\n\t\t\tstorageEgressBytes: number\n\t\t\tstorageUploads: number\n\t\t\tdbStorageBytes: number\n\t\t\tdbComputeSeconds: number\n\t\t\temailSentCount: number\n\t\t\tjobInvocationCount: number\n\t\t\tcronActiveCount: number\n\t\t\tpushSentCount?: number\n\t\t\tanalyticsEventCount: number\n\t\t\twebhookDeliveryCount: number\n\t\t\terrorEventCount: number\n\t\t\tauthMau: number\n\t\t} | null\n\t}>\n\n\t// Engagement (Streaks, Leaderboards, Achievements)\n\t/** Current authenticated user (needed for engagement features) */\n\tuser: User | null\n\t/**\n\t * Get streak state for a user (with optional inline defaults for auto-discovery)\n\t * @param streakId - Streak identifier\n\t * @param defaults - Optional inline defaults for auto-discovery when streak not pre-configured\n\t * @param userTimezone - Optional IANA timezone (e.g., 'America/New_York') for expiry display\n\t */\n\tgetStreak: (\n\t\tstreakId: string,\n\t\tdefaults?: StreakDefaults,\n\t\tuserTimezone?: string,\n\t) => Promise<StreakState>\n\t/**\n\t * Record activity to extend streak (with optional inline defaults for auto-discovery)\n\t * @param streakId - Streak identifier\n\t * @param metadata - Optional metadata\n\t * @param defaults - Optional inline defaults for auto-discovery\n\t * @param userTimezone - Optional IANA timezone (e.g., 'America/New_York') for calculating streak expiry at user's local midnight\n\t */\n\trecordStreakActivity: (\n\t\tstreakId: string,\n\t\tmetadata?: Record<string, unknown>,\n\t\tdefaults?: StreakDefaults,\n\t\tuserTimezone?: string,\n\t) => Promise<RecordActivityResult>\n\t/**\n\t * Recover streak within grace period\n\t * @param streakId - Streak identifier\n\t * @param userTimezone - Optional IANA timezone (e.g., 'America/New_York') for calculating new expiry\n\t */\n\trecoverStreak: (\n\t\tstreakId: string,\n\t\tuserTimezone?: string,\n\t) => Promise<{ success: boolean; streak: StreakState }>\n\t/** Get leaderboard data */\n\tgetLeaderboard: (\n\t\tleaderboardId: string,\n\t\toptions?: LeaderboardQueryOptions,\n\t) => Promise<LeaderboardResult>\n\t/** Submit score to leaderboard (with optional inline defaults for auto-discovery) */\n\tsubmitScore: (\n\t\tleaderboardId: string,\n\t\tvalue: number,\n\t\tmetadata?: Record<string, unknown>,\n\t\tdefaults?: LeaderboardDefaults,\n\t) => Promise<SubmitScoreResult>\n\t/** Get all user achievements */\n\tgetAchievements: () => Promise<UserAchievement[]>\n\t/** Unlock an achievement (with optional inline defaults for auto-discovery) */\n\tunlockAchievement: (\n\t\tachievementId: string,\n\t\tdefaults?: AchievementDefaults,\n\t) => Promise<AchievementUnlockEvent>\n\t/** Increment achievement progress (with optional inline defaults for auto-discovery) */\n\tincrementAchievementProgress: (\n\t\tachievementId: string,\n\t\tamount: number,\n\t\tdefaults?: AchievementDefaults,\n\t) => Promise<UserAchievement>\n}\n\nexport const PlatformContext = createContext<PlatformContextValue | null>(null)\n","/**\n * Sylphx Connection URL — Single Source of Truth (ADR-123)\n *\n * Implements the canonical connection string format defined in ADR-055 §5.\n * This module is the SDK-owned SSOT per ADR-123 (SDK/application boundary).\n * Consuming applications MUST import from `@sylphx/sdk` rather than duplicating\n * this logic.\n *\n * Hosted format:\n *   sylphx://{credential}@{tenant-slug}.api.sylphx.com[:port][/v{version}]\n *\n * Custom/self-hosted domains are also accepted as long as the first DNS label\n * is the tenant slug.\n *\n * Examples:\n *   sylphx://pk_prod_f19e5cdc3cc54f7ff81bdc26ec5bfbad@bold-river-a1b2c3.api.sylphx.com\n *   sylphx://sk_prod_5120bfeb5120bfeb5120bfeb5120bfeb@bold-river-a1b2c3.api.sylphx.com/v1\n *   sylphx://pk_dev_abc12345abc12345abc12345abc12345@calm-peak-z9x4d5.sylphx.dev\n *\n * Invariants:\n *   - Protocol is always `sylphx:` (no exceptions)\n *   - Credential matches `(pk|sk)_(dev|stg|prod|prev)(_{ref})?_{hex}`\n *   - Host's first DNS label is the resource slug (validated by slug regex)\n *   - `apiBaseUrl` is always HTTPS, with `/v{version}` appended (default `v1`)\n *\n * Parsing uses the WHATWG `URL` constructor — custom regex parsing is banned\n * because it is notoriously brittle (ADR-055 §5.3).\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type ConnectionCredentialType = 'pk' | 'sk'\nexport type ConnectionEnv = 'dev' | 'stg' | 'prod' | 'prev'\n\nexport interface ParsedConnectionUrl {\n\t/** Full credential string, e.g. `pk_prod_f19e...` */\n\treadonly credential: string\n\t/** Credential kind — `pk` (publishable) or `sk` (secret) */\n\treadonly credentialType: ConnectionCredentialType\n\t/** Target environment encoded in the credential */\n\treadonly env: ConnectionEnv\n\t/** First DNS label of the host — the resource slug (e.g. `bold-river-a1b2c3`) */\n\treadonly slug: string\n\t/** Full host including port when present (e.g. `bold-river-a1b2c3.api.sylphx.com`) */\n\treadonly host: string\n\t/** Ready-to-use SDK base URL, always HTTPS (e.g. `https://bold-river-a1b2c3.api.sylphx.com/v1`) */\n\treadonly apiBaseUrl: string\n}\n\nexport interface BuildConnectionUrlInput {\n\t/** Credential — must match the credential format regex */\n\treadonly credential: string\n\t/** Resource slug — validated DNS label */\n\treadonly slug: string\n\t/** SDK API domain suffix; defaults to `api.sylphx.com`. Use `sylphx.dev` for dev. */\n\treadonly domain?: string\n\t/** API version suffix, e.g. `v1`. Defaults to `v1`. Pass empty string to omit. */\n\treadonly version?: string\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst SYLPHX_PROTOCOL = 'sylphx:'\nconst DEFAULT_DOMAIN = 'api.sylphx.com'\nconst DEFAULT_VERSION = 'v1'\n\n/**\n * Credential format — opaque token with type, env, optional project ref, and\n * hex payload. Ref-scoped credentials are emitted by Platform app-env injection;\n * legacy credentials without the ref remain valid for existing deploys.\n */\nexport const CREDENTIAL_REGEX = /^(pk|sk)_(dev|stg|prod|prev)(?:_[a-z0-9]{12})?_[a-f0-9]{32,64}$/\n\n/** Version segment, e.g. `v1`, `v2`, `v10`. */\nconst VERSION_REGEX = /^v[0-9]+$/\n\n/**\n * Slug validation regex — RFC 1035 DNS label.\n * Lowercase letters, numbers, and hyphens; must start and end with alnum.\n * Length 1–63.\n */\nconst SLUG_REGEX = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/\n\n// ============================================================================\n// Errors\n// ============================================================================\n\nexport class InvalidConnectionUrlError extends Error {\n\treadonly code = 'INVALID_CONNECTION_URL' as const\n\n\tconstructor(message: string) {\n\t\tsuper(message)\n\t\tthis.name = 'InvalidConnectionUrlError'\n\t\tObject.setPrototypeOf(this, InvalidConnectionUrlError.prototype)\n\t}\n}\n\n// ============================================================================\n// Internal helpers\n// ============================================================================\n\nfunction fail(reason: string): never {\n\tthrow new InvalidConnectionUrlError(`Invalid Sylphx connection URL: ${reason}`)\n}\n\nfunction parseCredential(raw: string): {\n\tcredentialType: ConnectionCredentialType\n\tenv: ConnectionEnv\n} {\n\tconst match = CREDENTIAL_REGEX.exec(raw)\n\tif (!match) {\n\t\tfail(`credential must match (pk|sk)_(dev|stg|prod|prev)(_{ref})?_{hex}, got \"${raw}\"`)\n\t}\n\treturn {\n\t\tcredentialType: match[1] as ConnectionCredentialType,\n\t\tenv: match[2] as ConnectionEnv,\n\t}\n}\n\nfunction validateSlug(candidate: string): string {\n\tif (!candidate || candidate.length > 63 || !SLUG_REGEX.test(candidate)) {\n\t\tfail(`slug \"${candidate}\" is not a valid DNS label (lowercase alnum + hyphens, 1-63 chars)`)\n\t}\n\treturn candidate\n}\n\nfunction validateDomain(domain: string): string {\n\tif (!domain || domain.includes('/') || domain.includes('@') || domain.includes(' ')) {\n\t\tfail(`domain \"${domain}\" is not a valid hostname suffix`)\n\t}\n\t// Reject schemes — domain is just a hostname suffix\n\tif (domain.includes('://')) {\n\t\tfail(`domain \"${domain}\" must not contain a scheme`)\n\t}\n\treturn domain.toLowerCase()\n}\n\nfunction normaliseVersion(version: string | undefined): string {\n\tif (version === undefined) return DEFAULT_VERSION\n\tif (version === '') return ''\n\tif (!VERSION_REGEX.test(version)) {\n\t\tfail(`version \"${version}\" must match /^v[0-9]+$/`)\n\t}\n\treturn version\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Build a canonical Sylphx connection URL.\n *\n * Throws `InvalidConnectionUrlError` if any component is malformed.\n */\nexport function buildConnectionUrl(input: BuildConnectionUrlInput): string {\n\tconst { credential, slug, domain = DEFAULT_DOMAIN, version = DEFAULT_VERSION } = input\n\n\tparseCredential(credential)\n\tconst safeSlug = validateSlug(slug)\n\tconst safeDomain = validateDomain(domain)\n\tconst safeVersion = normaliseVersion(version)\n\n\tconst host = `${safeSlug}.${safeDomain}`\n\tconst pathSuffix = safeVersion ? `/${safeVersion}` : ''\n\treturn `${SYLPHX_PROTOCOL}//${credential}@${host}${pathSuffix}`\n}\n\n/**\n * Parse a Sylphx connection URL into its structured components.\n *\n * Throws `InvalidConnectionUrlError` on any structural problem.\n */\nexport function parseConnectionUrl(url: string): ParsedConnectionUrl {\n\tif (typeof url !== 'string' || url.length === 0) {\n\t\tfail('url must be a non-empty string')\n\t}\n\n\tlet parsed: URL\n\ttry {\n\t\tparsed = new URL(url)\n\t} catch {\n\t\tfail(`not a valid URL: \"${url}\"`)\n\t}\n\n\tif (parsed.protocol !== SYLPHX_PROTOCOL) {\n\t\tfail(`protocol must be \"sylphx:\", got \"${parsed.protocol}\"`)\n\t}\n\n\t// URL parses `sylphx://cred@host/path` but places `cred` in `username` only\n\t// when the authority is parsed. For non-special schemes, browsers/Node parse\n\t// the authority uniformly — we defensively read both `username` and `host`.\n\tconst credential = decodeURIComponent(parsed.username)\n\tif (!credential) {\n\t\tfail('missing credential (expected `sylphx://<credential>@<host>`)')\n\t}\n\tif (parsed.password) {\n\t\tfail('connection URL must not contain a password component')\n\t}\n\n\tconst { credentialType, env } = parseCredential(credential)\n\n\tconst host = parsed.host\n\tif (!host) {\n\t\tfail('missing host')\n\t}\n\n\t// Extract slug from the first DNS label\n\tconst hostname = parsed.hostname\n\tconst firstDot = hostname.indexOf('.')\n\tif (firstDot <= 0) {\n\t\tfail(`host \"${hostname}\" must contain at least one dot (slug.domain)`)\n\t}\n\tconst slugCandidate = hostname.slice(0, firstDot)\n\tconst domainSuffix = hostname.slice(firstDot + 1)\n\tif (!domainSuffix) {\n\t\tfail(`host \"${hostname}\" has empty domain suffix`)\n\t}\n\tconst slug = validateSlug(slugCandidate)\n\n\t// Path is either empty, `/`, or `/v{N}`\n\tconst rawPath = parsed.pathname.replace(/^\\/+/, '').replace(/\\/+$/, '')\n\tlet version = DEFAULT_VERSION\n\tif (rawPath !== '') {\n\t\tif (!VERSION_REGEX.test(rawPath)) {\n\t\t\tfail(`path \"${parsed.pathname}\" must be empty or match /v{N}`)\n\t\t}\n\t\tversion = rawPath\n\t}\n\n\tif (parsed.search) {\n\t\tfail('connection URL must not contain a query string')\n\t}\n\tif (parsed.hash) {\n\t\tfail('connection URL must not contain a fragment')\n\t}\n\n\tconst apiBaseUrl = `https://${host}/${version}`\n\n\treturn {\n\t\tcredential,\n\t\tcredentialType,\n\t\tenv,\n\t\tslug,\n\t\thost,\n\t\tapiBaseUrl,\n\t}\n}\n","/**\n * SDK Configuration — ADR-055 Connection URL API\n *\n * v0.5.0: The primary entry point is `createClient(url)` which accepts\n * a `sylphx://` connection URL. The old `createConfig({ ref, publicKey })`\n * API is removed.\n *\n * @example\n * ```typescript\n * import { createClient } from '@sylphx/sdk'\n *\n * const sylphx = createClient(process.env.SYLPHX_URL!)\n * // Parses: sylphx://pk_prod_{ref?}_{hex}@bold-river-a1b2c3.api.sylphx.com\n * ```\n */\n\nimport {\n\tCREDENTIAL_REGEX,\n\tInvalidConnectionUrlError,\n\ttype ParsedConnectionUrl,\n\tparseConnectionUrl,\n} from './connection-url'\nimport { DEFAULT_SDK_API_HOST, DEFAULT_TIMEOUT_MS } from './constants'\nimport {\n\tNetworkError,\n\tRateLimitError,\n\tSylphxError,\n\ttype SylphxErrorCode,\n\tTimeoutError,\n} from './errors'\n\nexport type {\n\tBuildConnectionUrlInput,\n\tConnectionCredentialType,\n\tConnectionEnv,\n\tParsedConnectionUrl,\n} from './connection-url'\n// Re-export connection URL primitives for consumers (ADR-123 SSOT)\nexport {\n\tbuildConnectionUrl,\n\tCREDENTIAL_REGEX,\n\tInvalidConnectionUrlError,\n\tparseConnectionUrl,\n} from './connection-url'\n\n// =============================================================================\n// Legacy format detection — produces clear migration errors\n// =============================================================================\n\n/** Matches a bare ref-scoped credential mistakenly passed without the `sylphx://` URL wrapper. */\nconst LEGACY_EMBEDDED_REF_PATTERN = /^(pk|sk)_(dev|stg|prod|prev)_[a-z0-9]{12}_[a-f0-9]+$/\n\n/** Matches old app_* format: app_{env}_{anything} */\nconst LEGACY_APP_KEY_PATTERN = /^app_(dev|stg|prod|prev)_/\n\nconst MIGRATION_MESSAGE =\n\t'API key format has changed. Use a sylphx:// connection URL instead.\\n\\n' +\n\t'New format: sylphx://pk_prod_{ref?}_{hex}@your-slug.api.sylphx.com\\n\\n' +\n\t'Generate new credentials from the Sylphx Console → Your App → Environments.\\n' +\n\t'See https://docs.sylphx.com/migration for details.'\n\n/**\n * Detect legacy key formats and throw a helpful migration error.\n */\nfunction rejectLegacyKeyFormat(input: string): void {\n\tconst trimmed = input.trim().toLowerCase()\n\n\tif (LEGACY_APP_KEY_PATTERN.test(trimmed)) {\n\t\tthrow new SylphxError(`[Sylphx] ${MIGRATION_MESSAGE}`, { code: 'BAD_REQUEST' })\n\t}\n\n\tif (LEGACY_EMBEDDED_REF_PATTERN.test(trimmed)) {\n\t\tthrow new SylphxError(`[Sylphx] ${MIGRATION_MESSAGE}`, { code: 'BAD_REQUEST' })\n\t}\n}\n\n// =============================================================================\n// Config types\n// =============================================================================\n\n/**\n * SDK Configuration object — immutable, frozen.\n *\n * Created by `createClient()` or `createServerClient()`.\n * Passed to all pure SDK functions (`track()`, `signIn()`, etc.).\n */\nexport interface SylphxConfig {\n\t/** The credential string (pk_* or sk_*) */\n\treadonly credential: string\n\t/** Credential type: 'pk' (publishable) or 'sk' (secret) */\n\treadonly credentialType: 'pk' | 'sk'\n\t/** Target environment: dev, stg, prod, or prev */\n\treadonly env: 'dev' | 'stg' | 'prod' | 'prev'\n\t/** Resource slug (first DNS label), e.g. 'bold-river-a1b2c3' */\n\treadonly slug: string\n\t/** Pre-computed API base URL, e.g. 'https://bold-river-a1b2c3.api.sylphx.com/v1' */\n\treadonly baseUrl: string\n\t/** Optional access token for authenticated requests */\n\treadonly accessToken?: string\n\t/**\n\t * Secret key — populated when credentialType is 'sk'.\n\t * Backward-compatible alias for `credential` when credential is sk_*.\n\t */\n\treadonly secretKey?: string\n\t/**\n\t * Publishable key — populated when credentialType is 'pk'.\n\t * Backward-compatible alias for `credential` when credential is pk_*.\n\t */\n\treadonly publicKey?: string\n\t/**\n\t * @deprecated Use `slug`. Backward-compatible alias.\n\t */\n\treadonly ref: string\n}\n\n/**\n * Explicit components input — alternative to connection URL string.\n *\n * For multi-tenant apps or cases where components are stored separately.\n */\nexport interface SylphxClientInput {\n\t/** Resource slug, e.g. 'bold-river-a1b2c3' */\n\tslug?: string\n\t/** Publishable key (pk_*) — client-safe */\n\tpublicKey?: string\n\t/** Secret key (sk_*) — server-side only */\n\tsecretKey?: string\n\t/** Optional access token */\n\taccessToken?: string\n\t/** API domain override (default: api.sylphx.com) */\n\tdomain?: string\n\t/**\n\t * @deprecated Use `slug`. Accepted for backward compatibility during migration.\n\t */\n\tref?: string\n\t/**\n\t * @deprecated Use `domain`. Accepted for backward compatibility during migration.\n\t */\n\tplatformUrl?: string\n}\n\n/**\n * Build a frozen SylphxConfig with backward-compat fields (secretKey, publicKey, ref).\n */\nfunction freezeConfig(opts: {\n\tcredential: string\n\tcredentialType: 'pk' | 'sk'\n\tenv: 'dev' | 'stg' | 'prod' | 'prev'\n\tslug: string\n\tbaseUrl: string\n\taccessToken?: string\n}): SylphxConfig {\n\treturn Object.freeze({\n\t\tcredential: opts.credential,\n\t\tcredentialType: opts.credentialType,\n\t\tenv: opts.env,\n\t\tslug: opts.slug,\n\t\tbaseUrl: opts.baseUrl,\n\t\taccessToken: opts.accessToken,\n\t\t// Backward-compat aliases\n\t\tsecretKey: opts.credentialType === 'sk' ? opts.credential : undefined,\n\t\tpublicKey: opts.credentialType === 'pk' ? opts.credential : undefined,\n\t\tref: opts.slug,\n\t})\n}\n\n// =============================================================================\n// createClient — primary entry point (ADR-055)\n// =============================================================================\n\n/**\n * Create a Sylphx client from a connection URL or explicit components.\n *\n * This is the primary SDK entry point for client-side (browser) usage.\n * Accepts a `sylphx://` connection URL or an explicit components object.\n *\n * @example Connection URL (recommended)\n * ```typescript\n * const sylphx = createClient(process.env.NEXT_PUBLIC_SYLPHX_URL!)\n * // Parses: sylphx://pk_prod_{ref?}_{hex}@bold-river-a1b2c3.api.sylphx.com\n * ```\n *\n * @example Explicit components\n * ```typescript\n * const sylphx = createClient({\n *   slug: 'bold-river-a1b2c3',\n *   publicKey: 'pk_prod_f19e...',\n * })\n * ```\n */\nexport function createClient(input: string | SylphxClientInput): SylphxConfig {\n\tif (typeof input === 'string') {\n\t\treturn createConfigFromUrl(input)\n\t}\n\treturn createConfigFromComponents(input)\n}\n\n/**\n * Create a Sylphx server client from a connection URL or explicit components.\n *\n * Equivalent to `createClient()` but validates that a secret key (sk_*) is provided.\n * Use this for server-side operations that require elevated permissions.\n *\n * @example Connection URL (recommended)\n * ```typescript\n * const sylphx = createServerClient(process.env.SYLPHX_SECRET_URL!)\n * // Parses: sylphx://sk_prod_{ref?}_{hex}@bold-river-a1b2c3.api.sylphx.com\n * ```\n *\n * @example Explicit components\n * ```typescript\n * const sylphx = createServerClient({\n *   slug: 'bold-river-a1b2c3',\n *   secretKey: 'sk_prod_5120...',\n * })\n * ```\n */\nexport function createServerClient(input: string | SylphxClientInput): SylphxConfig {\n\tconst config = createClient(input)\n\n\tif (config.credentialType !== 'sk') {\n\t\tthrow new SylphxError(\n\t\t\t'[Sylphx] createServerClient() requires a secret key (sk_*). ' +\n\t\t\t\t'Use a SYLPHX_SECRET_URL with an sk_ credential, or pass { secretKey } in the components object.',\n\t\t\t{ code: 'BAD_REQUEST' },\n\t\t)\n\t}\n\n\treturn config\n}\n\n// =============================================================================\n// Internal construction\n// =============================================================================\n\nfunction createConfigFromUrl(url: string): SylphxConfig {\n\tif (!url || typeof url !== 'string') {\n\t\tthrow new SylphxError(\n\t\t\t'[Sylphx] Connection URL is required. Set SYLPHX_URL or NEXT_PUBLIC_SYLPHX_URL environment variable.\\n\\n' +\n\t\t\t\t'Format: sylphx://pk_prod_{hex}@your-slug.api.sylphx.com',\n\t\t\t{ code: 'BAD_REQUEST' },\n\t\t)\n\t}\n\n\tconst trimmed = url.trim()\n\n\t// Detect legacy key formats passed as the URL string\n\trejectLegacyKeyFormat(trimmed)\n\n\t// If someone passes a bare key instead of a URL, give a helpful error\n\tif (!trimmed.startsWith('sylphx://')) {\n\t\t// Check if it looks like a new-format bare credential\n\t\tif (CREDENTIAL_REGEX.test(trimmed)) {\n\t\t\tthrow new SylphxError(\n\t\t\t\t'[Sylphx] Received a bare credential instead of a connection URL.\\n\\n' +\n\t\t\t\t\t'Wrap it in a connection URL: sylphx://<credential>@<slug>.api.sylphx.com\\n' +\n\t\t\t\t\t'Or use createClient({ slug, publicKey }) for explicit components.',\n\t\t\t\t{ code: 'BAD_REQUEST' },\n\t\t\t)\n\t\t}\n\t\tthrow new SylphxError(\n\t\t\t`[Sylphx] Invalid connection URL — must start with \"sylphx://\". Got: \"${trimmed.slice(0, 30)}...\"`,\n\t\t\t{ code: 'BAD_REQUEST' },\n\t\t)\n\t}\n\n\tlet parsed: ParsedConnectionUrl\n\ttry {\n\t\tparsed = parseConnectionUrl(trimmed)\n\t} catch (err) {\n\t\tif (err instanceof InvalidConnectionUrlError) {\n\t\t\tthrow new SylphxError(err.message, { code: 'BAD_REQUEST', cause: err })\n\t\t}\n\t\tthrow err\n\t}\n\n\treturn freezeConfig({\n\t\tcredential: parsed.credential,\n\t\tcredentialType: parsed.credentialType,\n\t\tenv: parsed.env,\n\t\tslug: parsed.slug,\n\t\tbaseUrl: parsed.apiBaseUrl,\n\t})\n}\n\nfunction createConfigFromComponents(input: SylphxClientInput): SylphxConfig {\n\tconst credential = input.secretKey || input.publicKey\n\tif (!credential) {\n\t\tthrow new SylphxError('[Sylphx] Either publicKey or secretKey must be provided.', {\n\t\t\tcode: 'BAD_REQUEST',\n\t\t})\n\t}\n\n\t// Accept deprecated `ref` as fallback for `slug` during migration\n\tconst resolvedSlug = input.slug || input.ref\n\n\tif (!resolvedSlug) {\n\t\tthrow new SylphxError('[Sylphx] slug is required when using explicit components.', {\n\t\t\tcode: 'BAD_REQUEST',\n\t\t})\n\t}\n\n\t// Try to validate as ADR-055 credential first; if invalid, check for legacy\n\tconst trimmedCred = credential.trim().toLowerCase()\n\n\tif (CREDENTIAL_REGEX.test(trimmedCred)) {\n\t\t// Connection credential: pk/sk_{env}_{optional ref}_{hex}\n\t\tconst match = CREDENTIAL_REGEX.exec(trimmedCred)!\n\t\tconst credentialType = match[1] as 'pk' | 'sk'\n\t\tconst env = match[2] as 'dev' | 'stg' | 'prod' | 'prev'\n\n\t\tconst slug = resolvedSlug.trim().toLowerCase()\n\t\t// Default to `api.sylphx.com` (DNS-only) — `sylphx.com` is Cloudflare-\n\t\t// proxied with no per-slug origin mapping and returns 404 for any\n\t\t// `<slug>.sylphx.com` request. The legacy components path below\n\t\t// (4-segment credentials) already defaults to `api.sylphx.com`; this\n\t\t// brings the new-format path in line so both behave consistently and\n\t\t// match the ADR-055 SYLPHX_URL injected by the platform.\n\t\tconst domain = input.domain?.trim() || DEFAULT_SDK_API_HOST\n\t\tconst baseUrl = `https://${slug}.${domain}/v1`\n\n\t\treturn freezeConfig({\n\t\t\tcredential: trimmedCred,\n\t\t\tcredentialType,\n\t\t\tenv,\n\t\t\tslug,\n\t\t\tbaseUrl,\n\t\t\taccessToken: input.accessToken,\n\t\t})\n\t}\n\n\t\t// Backward-compat legacy embedded-ref keys have 4 underscore-delimited\n\t\t// segments. Extract env from segment 1; ADR-055 routing resolves server-side.\n\tconst parts = trimmedCred.split('_')\n\tconst prefix = parts[0] as 'pk' | 'sk'\n\tif ((prefix === 'pk' || prefix === 'sk') && parts.length >= 3) {\n\t\tconst envSegment = parts[1]\n\t\tconst validEnvs = ['dev', 'stg', 'prod', 'prev']\n\t\tconst env = validEnvs.includes(envSegment)\n\t\t\t? (envSegment as 'dev' | 'stg' | 'prod' | 'prev')\n\t\t\t: 'prod'\n\n\t\tconst slug = resolvedSlug.trim().toLowerCase()\n\t\t// Accept deprecated platformUrl for base URL construction\n\t\tlet baseUrl: string\n\t\tif (input.platformUrl) {\n\t\t\tconst platform = input.platformUrl.trim().replace(/\\/$/, '')\n\t\t\tbaseUrl = platform.includes('/v1') ? platform : `${platform}/v1`\n\t\t} else {\n\t\t\tconst domain = input.domain?.trim() || DEFAULT_SDK_API_HOST\n\t\t\tbaseUrl = `https://${slug}.${domain}/v1`\n\t\t}\n\n\t\treturn freezeConfig({\n\t\t\tcredential: trimmedCred,\n\t\t\tcredentialType: prefix,\n\t\t\tenv,\n\t\t\tslug,\n\t\t\tbaseUrl,\n\t\t\taccessToken: input.accessToken,\n\t\t})\n\t}\n\n\tthrow new SylphxError(\n\t\t`[Sylphx] Invalid credential format. Expected (pk|sk)_(dev|stg|prod|prev)(_{ref})?_{hex}. Got: \"${trimmedCred.slice(0, 30)}...\"`,\n\t\t{ code: 'BAD_REQUEST' },\n\t)\n}\n\n// =============================================================================\n// Config utilities\n// =============================================================================\n\n/**\n * Create a new config with an updated access token.\n *\n * Returns a new frozen config — does not mutate the original.\n *\n * @example\n * ```typescript\n * const authenticatedConfig = withToken(config, 'access_token_here')\n * ```\n */\nexport function withToken(config: SylphxConfig, accessToken: string): SylphxConfig {\n\treturn Object.freeze({\n\t\t...config,\n\t\taccessToken,\n\t})\n}\n\n// =============================================================================\n// Backward compatibility — createConfig (deprecated, will be removed)\n// =============================================================================\n\n/**\n * @deprecated Use `createClient()` or `createServerClient()` instead.\n * This function is kept temporarily for migration but will be removed.\n */\nexport type SylphxConfigInput = string | SylphxClientInput\n\n/**\n * @deprecated Use `createClient()` instead. See ADR-055.\n */\nexport const createConfig = createClient\n\n// =============================================================================\n// Request helpers — internal SDK plumbing\n// =============================================================================\n\n/**\n * Map HTTP status code to SylphxErrorCode\n */\nfunction httpStatusToErrorCode(status: number): SylphxErrorCode {\n\tswitch (status) {\n\t\tcase 400:\n\t\t\treturn 'BAD_REQUEST'\n\t\tcase 401:\n\t\t\treturn 'UNAUTHORIZED'\n\t\tcase 403:\n\t\t\treturn 'FORBIDDEN'\n\t\tcase 404:\n\t\t\treturn 'NOT_FOUND'\n\t\tcase 409:\n\t\t\treturn 'CONFLICT'\n\t\tcase 413:\n\t\t\treturn 'PAYLOAD_TOO_LARGE'\n\t\tcase 422:\n\t\t\treturn 'UNPROCESSABLE_ENTITY'\n\t\tcase 429:\n\t\t\treturn 'TOO_MANY_REQUESTS'\n\t\tcase 500:\n\t\t\treturn 'INTERNAL_SERVER_ERROR'\n\t\tcase 501:\n\t\t\treturn 'NOT_IMPLEMENTED'\n\t\tcase 502:\n\t\t\treturn 'BAD_GATEWAY'\n\t\tcase 503:\n\t\t\treturn 'SERVICE_UNAVAILABLE'\n\t\tcase 504:\n\t\t\treturn 'GATEWAY_TIMEOUT'\n\t\tdefault:\n\t\t\treturn status >= 500 ? 'INTERNAL_SERVER_ERROR' : 'BAD_REQUEST'\n\t}\n}\n\n/**\n * Internal: Build headers for API requests.\n *\n * Sends the credential as `x-app-secret` header.\n */\nexport function buildHeaders(config: SylphxConfig): Record<string, string> {\n\tconst headers: Record<string, string> = {\n\t\t'Content-Type': 'application/json',\n\t}\n\n\tif (config.credential) {\n\t\theaders['x-app-secret'] = config.credential\n\t}\n\tif (config.accessToken) {\n\t\theaders.Authorization = `Bearer ${config.accessToken}`\n\t}\n\n\treturn headers\n}\n\n/**\n * Internal: Build REST API URL.\n *\n * Appends path to the pre-computed base URL.\n */\nexport function buildApiUrl(config: SylphxConfig, path: string): string {\n\tconst base = config.baseUrl.replace(/\\/$/, '')\n\tconst cleanPath = path.startsWith('/') ? path : `/${path}`\n\treturn `${base}${cleanPath}`\n}\n\n/**\n * Internal: Call REST API endpoint.\n *\n * Features:\n * - Request timeout (default 30s) prevents infinite hangs\n * - Proper HTTP status code mapping to error codes\n * - Safe JSON parsing with error handling\n * - Idempotency key support (Stripe pattern)\n */\nexport async function callApi<TOutput>(\n\tconfig: SylphxConfig,\n\tpath: string,\n\toptions: {\n\t\tmethod?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'\n\t\tbody?: unknown\n\t\tquery?: Record<string, string | number | boolean | undefined>\n\t\ttimeout?: number\n\t\tsignal?: AbortSignal\n\t\tidempotencyKey?: string\n\t\theaders?: Record<string, string>\n\t} = {},\n): Promise<TOutput> {\n\tconst {\n\t\tmethod = 'GET',\n\t\tbody,\n\t\tquery,\n\t\ttimeout = DEFAULT_TIMEOUT_MS,\n\t\tsignal,\n\t\tidempotencyKey,\n\t\theaders: extraHeaders,\n\t} = options\n\n\tlet url = buildApiUrl(config, path)\n\n\t// Add query parameters\n\tif (query) {\n\t\tconst params = new URLSearchParams()\n\t\tfor (const [key, value] of Object.entries(query)) {\n\t\t\tif (value !== undefined) {\n\t\t\t\tparams.set(key, String(value))\n\t\t\t}\n\t\t}\n\t\tconst queryString = params.toString()\n\t\tif (queryString) {\n\t\t\turl += `?${queryString}`\n\t\t}\n\t}\n\n\t// Create AbortController for timeout\n\tconst controller = new AbortController()\n\tconst timeoutId = setTimeout(() => controller.abort(), timeout)\n\n\t// Combine user signal with timeout signal\n\tconst combinedSignal = signal ? AbortSignal.any([signal, controller.signal]) : controller.signal\n\n\tconst headers = buildHeaders(config)\n\n\t// Add idempotency key header for safe retries (Stripe pattern)\n\tif (idempotencyKey) {\n\t\theaders['Idempotency-Key'] = idempotencyKey\n\t}\n\n\t// Merge user-supplied headers\n\tif (extraHeaders) {\n\t\tfor (const [k, v] of Object.entries(extraHeaders)) {\n\t\t\theaders[k] = v\n\t\t}\n\t}\n\n\tconst fetchOptions: RequestInit = {\n\t\tmethod,\n\t\theaders,\n\t\tsignal: combinedSignal,\n\t}\n\n\tif (body) {\n\t\tfetchOptions.body = JSON.stringify(body)\n\t}\n\n\tlet response: Response\n\ttry {\n\t\tresponse = await fetch(url, fetchOptions)\n\t} catch (error) {\n\t\tclearTimeout(timeoutId)\n\n\t\t// Handle abort/timeout\n\t\tif (error instanceof Error) {\n\t\t\tif (error.name === 'AbortError') {\n\t\t\t\t// Check if it was our timeout or user cancellation\n\t\t\t\tif (controller.signal.aborted && !signal?.aborted) {\n\t\t\t\t\tthrow new TimeoutError(timeout)\n\t\t\t\t}\n\t\t\t\tthrow new SylphxError('Request aborted', {\n\t\t\t\t\tcode: 'ABORTED',\n\t\t\t\t\tcause: error,\n\t\t\t\t})\n\t\t\t}\n\t\t\t// Network errors\n\t\t\tthrow new NetworkError(error.message, { cause: error })\n\t\t}\n\t\tthrow new NetworkError('Network request failed')\n\t} finally {\n\t\tclearTimeout(timeoutId)\n\t}\n\n\tif (!response.ok) {\n\t\tconst errorBody = await response.text().catch(() => '')\n\t\tlet errorMessage = 'Request failed'\n\t\tlet errorData: Record<string, unknown> | undefined\n\n\t\t// Safe JSON parsing\n\t\tif (errorBody) {\n\t\t\ttry {\n\t\t\t\tconst parsed = JSON.parse(errorBody) as {\n\t\t\t\t\terror?: { message?: string }\n\t\t\t\t\tmessage?: string\n\t\t\t\t}\n\t\t\t\terrorMessage = parsed.error?.message ?? parsed.message ?? errorMessage\n\t\t\t\terrorData = parsed.error as Record<string, unknown> | undefined\n\t\t\t} catch {\n\t\t\t\terrorMessage = response.statusText || errorMessage\n\t\t\t}\n\t\t}\n\n\t\tconst errorCode = httpStatusToErrorCode(response.status)\n\n\t\t// Extract rate limit headers (Stripe SDK pattern)\n\t\tconst retryAfterHeader = response.headers.get('Retry-After')\n\t\tconst rateLimitLimit = response.headers.get('X-RateLimit-Limit')\n\t\tconst rateLimitRemaining = response.headers.get('X-RateLimit-Remaining')\n\t\tconst rateLimitReset = response.headers.get('X-RateLimit-Reset')\n\n\t\tconst retryAfter = retryAfterHeader ? Number.parseInt(retryAfterHeader, 10) : undefined\n\n\t\t// Use specialized RateLimitError for 429 responses\n\t\tif (response.status === 429) {\n\t\t\tthrow new RateLimitError(errorMessage || 'Too many requests', {\n\t\t\t\tstatus: response.status,\n\t\t\t\tdata: errorData,\n\t\t\t\tretryAfter,\n\t\t\t\tlimit: rateLimitLimit ? Number.parseInt(rateLimitLimit, 10) : undefined,\n\t\t\t\tremaining: rateLimitRemaining ? Number.parseInt(rateLimitRemaining, 10) : undefined,\n\t\t\t\tresetAt: rateLimitReset ? Number.parseInt(rateLimitReset, 10) : undefined,\n\t\t\t})\n\t\t}\n\n\t\tthrow new SylphxError(errorMessage, {\n\t\t\tcode: errorCode,\n\t\t\tstatus: response.status,\n\t\t\tdata: errorData,\n\t\t\tretryAfter,\n\t\t})\n\t}\n\n\t// Handle empty responses (204 No Content)\n\tconst text = await response.text()\n\tif (!text) {\n\t\treturn {} as TOutput\n\t}\n\n\t// Safe JSON parsing for response body\n\ttry {\n\t\treturn JSON.parse(text) as TOutput\n\t} catch (error) {\n\t\tthrow new SylphxError('Failed to parse response', {\n\t\t\tcode: 'PARSE_ERROR',\n\t\t\tcause: error instanceof Error ? error : undefined,\n\t\t\tdata: { body: text.slice(0, 200) },\n\t\t})\n\t}\n}\n","/**\n * Organization Functions\n *\n * Pure functions for organization management - no hidden state.\n * Each function takes config as the first parameter.\n *\n * Uses REST API at /api/sdk/orgs/* for all operations.\n *\n * Types are re-exported from `@sylphx/contract` (ADR-084). The contract is\n * the single source of truth for every wire shape — this module only adds\n * ergonomic aliases (`Organization*` wrappers) and inline envelopes for\n * request bodies + member role updates.\n */\n\n// Contract is the SSOT for both endpoint paths and wire types.\nimport {\n\ttype CreateOrgInput as ContractCreateOrgInput,\n\ttype InviteMemberInput as ContractInviteMemberInput,\n\ttype UpdateOrgInput as ContractUpdateOrgInput,\n\ttype MembershipInfo,\n\ttype Organization,\n\ttype OrgInvitation,\n\ttype OrgMember,\n\ttype OrgSdkRole,\n\torganizationsEndpoints,\n\ttype UserOrganizationMembership,\n\ttype UserOrganizationsResponse,\n} from '@sylphx/contract'\nimport { callApi, type SylphxConfig } from './config'\n\n// ============================================================================\n// Types (re-exported from @sylphx/contract)\n// ============================================================================\n\nexport type { Organization }\n/**\n * The contract types `OrgMember.role` as a permissive `string` so it can\n * absorb any role stored in the DB (including legacy `'member'`). The SDK\n * surface is narrower — components key off the six-value role union — so\n * re-narrow here to keep `member.role` valid in existing call sites.\n */\nexport type OrganizationMember = Omit<OrgMember, 'role'> & {\n\trole: OrgSdkRole\n}\nexport type OrganizationInvitation = OrgInvitation\n/**\n * Membership info returned inline with `GET /orgs/:idOrSlug`. The endpoint\n * may return `null` when the caller has no role on the org (platform-admin\n * path) — SDK callers get the union on the response envelope, not here.\n */\nexport type OrganizationMembership = MembershipInfo\nexport type UserOrganization = UserOrganizationMembership\nexport type OrganizationsListResult = {\n\torganizations: Organization[]\n\ttotal: number\n\tlimit: number\n\toffset: number\n}\nexport type OrgRole = OrgSdkRole\nexport type CreateOrgInput = ContractCreateOrgInput\nexport type UpdateOrgInput = ContractUpdateOrgInput & {\n\tmetadata?: Record<string, unknown> | null\n}\nexport type InviteMemberInput = ContractInviteMemberInput\n\n// ============================================================================\n// Organization CRUD\n// ============================================================================\n\n/**\n * Get all organizations the current user belongs to\n *\n * @example\n * ```typescript\n * const { organizations } = await getOrganizations(config)\n * ```\n */\nexport async function getOrganizations(config: SylphxConfig): Promise<UserOrganizationsResponse> {\n\tconst endpoint = organizationsEndpoints.memberships\n\treturn callApi<UserOrganizationsResponse>(config, endpoint.path, {\n\t\tmethod: endpoint.method,\n\t})\n}\n\n/**\n * Admin-only organization list.\n *\n * `getOrganizations()` is intentionally user-scoped. Use this function only\n * from Platform operator contexts that are allowed to enumerate every org.\n *\n * @example\n * ```typescript\n * const { organizations, total } = await listOrganizations(adminConfig)\n * ```\n */\nexport async function listOrganizations(\n\tconfig: SylphxConfig,\n\toptions: { limit?: number; offset?: number } = {},\n): Promise<OrganizationsListResult> {\n\tconst endpoint = organizationsEndpoints.list\n\treturn callApi<OrganizationsListResult>(config, endpoint.path, {\n\t\tmethod: endpoint.method,\n\t\tquery: options,\n\t})\n}\n\n/**\n * Get organization by ID or slug\n *\n * @example\n * ```typescript\n * const { organization, membership } = await getOrganization(config, 'my-org')\n * ```\n */\nexport async function getOrganization(\n\tconfig: SylphxConfig,\n\torgIdOrSlug: string,\n): Promise<{\n\torganization: Organization\n\tmembership: OrganizationMembership | null\n}> {\n\treturn callApi<{\n\t\torganization: Organization\n\t\tmembership: OrganizationMembership | null\n\t}>(config, `/orgs/${orgIdOrSlug}`)\n}\n\n/**\n * Create a new organization\n *\n * @example\n * ```typescript\n * const { organization } = await createOrganization(config, {\n *   name: 'My Company',\n *   slug: 'my-company',\n * })\n * ```\n */\nexport async function createOrganization(\n\tconfig: SylphxConfig,\n\tinput: CreateOrgInput,\n): Promise<{ organization: Organization }> {\n\tconst endpoint = organizationsEndpoints.create\n\tconst organization = await callApi<Organization>(config, endpoint.path, {\n\t\tmethod: endpoint.method,\n\t\tbody: input,\n\t})\n\treturn { organization }\n}\n\n/**\n * Update an organization\n *\n * @example\n * ```typescript\n * const { organization } = await updateOrganization(config, 'my-org', {\n *   name: 'New Name',\n * })\n * ```\n */\nexport async function updateOrganization(\n\tconfig: SylphxConfig,\n\torgIdOrSlug: string,\n\tinput: UpdateOrgInput,\n): Promise<{ organization: Organization }> {\n\treturn callApi<{ organization: Organization }>(config, `/orgs/${orgIdOrSlug}`, {\n\t\tmethod: 'PUT',\n\t\tbody: input,\n\t})\n}\n\n/**\n * Delete an organization\n *\n * Requires super_admin role.\n *\n * @example\n * ```typescript\n * await deleteOrganization(config, 'my-org')\n * ```\n */\nexport async function deleteOrganization(\n\tconfig: SylphxConfig,\n\torgIdOrSlug: string,\n): Promise<{ success: boolean }> {\n\treturn callApi<{ success: boolean }>(config, `/orgs/${orgIdOrSlug}`, {\n\t\tmethod: 'DELETE',\n\t})\n}\n\n// ============================================================================\n// Members\n// ============================================================================\n\n/**\n * Get organization members\n *\n * @example\n * ```typescript\n * const { members } = await getOrganizationMembers(config, 'my-org')\n * ```\n */\nexport async function getOrganizationMembers(\n\tconfig: SylphxConfig,\n\torgIdOrSlug: string,\n): Promise<{ members: OrganizationMember[] }> {\n\treturn callApi<{ members: OrganizationMember[] }>(config, `/orgs/${orgIdOrSlug}/members`)\n}\n\n/**\n * Invite a member to an organization\n *\n * Requires admin or super_admin role.\n *\n * @example\n * ```typescript\n * const { invitation } = await inviteOrganizationMember(config, 'my-org', {\n *   email: 'user@example.com',\n *   role: 'developer',\n * })\n * ```\n */\nexport async function inviteOrganizationMember(\n\tconfig: SylphxConfig,\n\torgIdOrSlug: string,\n\tinput: InviteMemberInput,\n): Promise<{ invitation: OrganizationInvitation }> {\n\treturn callApi<{ invitation: OrganizationInvitation }>(\n\t\tconfig,\n\t\t`/orgs/${orgIdOrSlug}/members/invite`,\n\t\t{\n\t\t\tmethod: 'POST',\n\t\t\tbody: input,\n\t\t},\n\t)\n}\n\n/**\n * Update a member's role\n *\n * Requires admin or super_admin role.\n *\n * @example\n * ```typescript\n * const { member } = await updateOrganizationMemberRole(config, 'my-org', userId, 'admin')\n * ```\n */\nexport async function updateOrganizationMemberRole(\n\tconfig: SylphxConfig,\n\torgIdOrSlug: string,\n\tmemberId: string,\n\trole: OrgRole,\n): Promise<{ member: OrganizationMember }> {\n\treturn callApi<{ member: OrganizationMember }>(\n\t\tconfig,\n\t\t`/orgs/${orgIdOrSlug}/members/${memberId}/role`,\n\t\t{\n\t\t\tmethod: 'PUT',\n\t\t\tbody: { role },\n\t\t},\n\t)\n}\n\n/**\n * Remove a member from an organization\n *\n * Requires admin or super_admin role.\n *\n * @example\n * ```typescript\n * await removeOrganizationMember(config, 'my-org', userId)\n * ```\n */\nexport async function removeOrganizationMember(\n\tconfig: SylphxConfig,\n\torgIdOrSlug: string,\n\tmemberId: string,\n): Promise<{ success: boolean }> {\n\treturn callApi<{ success: boolean }>(config, `/orgs/${orgIdOrSlug}/members/${memberId}`, {\n\t\tmethod: 'DELETE',\n\t})\n}\n\n/**\n * Leave an organization\n *\n * @example\n * ```typescript\n * await leaveOrganization(config, 'my-org')\n * ```\n */\nexport async function leaveOrganization(\n\tconfig: SylphxConfig,\n\torgIdOrSlug: string,\n): Promise<{ success: boolean }> {\n\treturn callApi<{ success: boolean }>(config, `/orgs/${orgIdOrSlug}/leave`, {\n\t\tmethod: 'POST',\n\t})\n}\n\n// ============================================================================\n// Invitations\n// ============================================================================\n\n/**\n * Get pending invitations for an organization\n *\n * Requires admin or super_admin role.\n *\n * @example\n * ```typescript\n * const { invitations } = await getOrganizationInvitations(config, 'my-org')\n * ```\n */\nexport async function getOrganizationInvitations(\n\tconfig: SylphxConfig,\n\torgIdOrSlug: string,\n): Promise<{ invitations: OrganizationInvitation[] }> {\n\treturn callApi<{ invitations: OrganizationInvitation[] }>(\n\t\tconfig,\n\t\t`/orgs/${orgIdOrSlug}/invitations`,\n\t)\n}\n\n/**\n * Accept an organization invitation\n *\n * @example\n * ```typescript\n * const { organization } = await acceptOrganizationInvitation(config, invitationToken)\n * ```\n */\nexport async function acceptOrganizationInvitation(\n\tconfig: SylphxConfig,\n\ttoken: string,\n): Promise<{ organization: Organization }> {\n\treturn callApi<{ organization: Organization }>(config, '/orgs/invitations/accept', {\n\t\tmethod: 'POST',\n\t\tbody: { token },\n\t})\n}\n\n/**\n * Revoke a pending invitation\n *\n * Requires admin or super_admin role.\n *\n * @example\n * ```typescript\n * await revokeOrganizationInvitation(config, 'my-org', invitationId)\n * ```\n */\nexport async function revokeOrganizationInvitation(\n\tconfig: SylphxConfig,\n\torgIdOrSlug: string,\n\tinvitationId: string,\n): Promise<{ success: boolean }> {\n\treturn callApi<{ success: boolean }>(config, `/orgs/${orgIdOrSlug}/invitations/${invitationId}`, {\n\t\tmethod: 'DELETE',\n\t})\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Check if user has a specific role or higher in the organization\n */\nexport function hasRole(membership: OrganizationMembership | null, minimumRole: OrgRole): boolean {\n\tif (!membership) return false\n\n\tconst roleHierarchy: OrgRole[] = [\n\t\t'viewer',\n\t\t'analytics',\n\t\t'developer',\n\t\t'billing',\n\t\t'admin',\n\t\t'super_admin',\n\t]\n\n\tconst userRoleIndex = roleHierarchy.indexOf(membership.role)\n\tconst requiredRoleIndex = roleHierarchy.indexOf(minimumRole)\n\n\treturn userRoleIndex >= requiredRoleIndex\n}\n\n/**\n * Check if user can manage members (invite, remove, change roles)\n */\nexport function canManageMembers(membership: OrganizationMembership | null): boolean {\n\treturn hasRole(membership, 'admin')\n}\n\n/**\n * Check if user can manage organization settings\n */\nexport function canManageSettings(membership: OrganizationMembership | null): boolean {\n\treturn hasRole(membership, 'admin')\n}\n\n/**\n * Check if user can delete the organization\n */\nexport function canDeleteOrganization(membership: OrganizationMembership | null): boolean {\n\treturn hasRole(membership, 'super_admin')\n}\n","/**\n * Config Hooks\n *\n * Hooks for accessing server-fetched configuration data.\n * Config is required and passed to SylphxProvider from Server Components via getAppConfig().\n *\n * This eliminates client-side config fetching and the associated:\n * - Loading states\n * - staleTime tuning\n * - Delayed updates after admin changes\n */\n\n'use client'\n\nimport { createContext, useContext } from 'react'\nimport type { Plan } from '../../billing'\nimport type { ConsentType } from '../../consent'\nimport type { AppConfig, AppMetadata, FeatureFlagDefinition, OAuthProviderInfo } from '../../types'\n\n// ============================================\n// Config Context\n// ============================================\n\n/**\n * Context for server-fetched configuration (required)\n */\nexport const ConfigContext = createContext<AppConfig | null>(null)\n\n/**\n * Hook to get the full app config\n *\n * @throws Error if used outside SylphxProvider\n *\n * @example\n * ```tsx\n * function Debug() {\n *   const config = useConfig()\n *   console.log('Config fetched at:', config.fetchedAt)\n *   return <pre>{JSON.stringify(config, null, 2)}</pre>\n * }\n * ```\n */\nexport function useConfig(): AppConfig {\n\tconst config = useContext(ConfigContext)\n\tif (!config) {\n\t\tthrow new Error('useConfig must be used within a SylphxProvider')\n\t}\n\treturn config\n}\n\n// ============================================\n// Derived Config Hooks\n// ============================================\n\n/**\n * Get subscription plans from server-fetched config\n *\n * @example\n * ```tsx\n * function PricingTable() {\n *   const plans = usePlans()\n *   return plans.map(plan => <PlanCard key={plan.id} plan={plan} />)\n * }\n * ```\n */\nexport function usePlans(): Plan[] {\n\treturn useConfig().plans\n}\n\n/**\n * Get enabled OAuth providers from config\n *\n * @example\n * ```tsx\n * function OAuthButtons() {\n *   const providers = useOAuthProviders()\n *   return providers.map(p => <OAuthButton key={p.id} provider={p.id} />)\n * }\n * ```\n */\nexport function useOAuthProviders(): OAuthProviderInfo[] {\n\treturn useConfig().oauthProviders\n}\n\n/**\n * Get consent types from config\n *\n * @example\n * ```tsx\n * function CookieBanner() {\n *   const types = useConsentTypes()\n *   return types.map(type => <ConsentToggle key={type.id} type={type} />)\n * }\n * ```\n */\nexport function useConsentTypes(): ConsentType[] {\n\treturn useConfig().consentTypes\n}\n\n/**\n * Get feature flag definitions from config\n *\n * Note: For flag evaluation, use useFlag() or useFeatureFlag() instead.\n * This hook returns raw definitions, not evaluated values.\n *\n * @example\n * ```tsx\n * function FlagsDebug() {\n *   const flags = useFeatureFlagDefinitions()\n *   return flags.map(f => <FlagRow key={f.key} flag={f} />)\n * }\n * ```\n */\nexport function useFeatureFlagDefinitions(): FeatureFlagDefinition[] {\n\treturn useConfig().featureFlags\n}\n\n/**\n * Get app metadata from config\n *\n * @example\n * ```tsx\n * function AppInfo() {\n *   const app = useAppMetadata()\n *   return <span>{app.name}</span>\n * }\n * ```\n */\nexport function useAppMetadata(): AppMetadata {\n\treturn useConfig().app\n}\n\n// Re-export types\nexport type { AppConfig, OAuthProviderInfo, FeatureFlagDefinition, AppMetadata }\nexport type { Plan }\nexport type { ConsentType }\n","/**\n * useOAuthProviders Hook\n *\n * Returns the list of OAuth providers enabled for the current app.\n * Reads directly from server-fetched config (no client-side fetching).\n *\n * @example\n * ```tsx\n * function LoginPage() {\n *   const { providers } = useOAuthProviders()\n *\n *   return (\n *     <div>\n *       {providers.map(provider => (\n *         <OAuthButton key={provider} provider={provider} />\n *       ))}\n *     </div>\n *   )\n * }\n * ```\n */\n\n'use client'\n\nimport type { OAuthProvider } from '../../oauth'\nimport { useConfig } from './use-config'\n\n// ============================================\n// Types\n// ============================================\n\nexport interface EnabledProvider {\n\tid: OAuthProvider\n\tname: string\n}\n\nexport interface UseOAuthProvidersReturn {\n\t/** List of enabled OAuth provider IDs */\n\tproviders: OAuthProvider[]\n\t/** Full provider info with names */\n\tproviderDetails: EnabledProvider[]\n\t/** Always false - no client-side loading */\n\tisLoading: false\n\t/** Always null - no client-side errors */\n\terror: null\n}\n\n// ============================================\n// Hook Implementation\n// ============================================\n\n/**\n * Hook to get enabled OAuth providers for the current app\n *\n * Reads directly from server-fetched config (instant, no loading state).\n */\nexport function useOAuthProviders(): UseOAuthProvidersReturn {\n\tconst config = useConfig()\n\tconst providerDetails = config.oauthProviders as EnabledProvider[]\n\tconst providers = providerDetails.map((p) => p.id)\n\n\treturn {\n\t\tproviders,\n\t\tproviderDetails,\n\t\tisLoading: false,\n\t\terror: null,\n\t}\n}\n","/**\n * useSdkReady Hook\n *\n * SSOT for SDK configuration checking across all components.\n * Handles SSR safety, mount detection, and environment-aware error display.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n *   const { isReady, renderError } = useSdkReady({\n *     services: ['auth', 'user'],\n *     componentType: 'sign-in'\n *   })\n *\n *   // Early return if not ready\n *   if (!isReady) return renderError()\n *\n *   // Safe to use hooks now\n *   const { signIn } = useAuth()\n *   ...\n * }\n * ```\n */\n\nimport { useCallback, useContext, useEffect, useMemo, useState } from 'react'\nimport { PlatformContext } from '../platform-context'\nimport { type ConfigurationComponentType, ConfigurationError } from '../ui/configuration-error'\nimport type { ThemeVariables } from '../ui/styles'\nimport { defaultTheme } from '../ui/styles'\n\n// ============================================\n// Types\n// ============================================\n\nexport type SdkService =\n\t| 'auth'\n\t| 'user'\n\t| 'billing'\n\t| 'storage'\n\t| 'analytics'\n\t| 'flags'\n\t| 'consent'\n\t| 'organization'\n\t| 'monitoring'\n\t| 'ai'\n\t| 'jobs'\n\t| 'notifications'\n\t| 'newsletter'\n\n// Re-export for convenience\ntype ComponentType = ConfigurationComponentType\n\nexport interface UseSdkReadyOptions {\n\t/** Required services for this component */\n\tservices?: SdkService[]\n\t/** Component type for error messaging */\n\tcomponentType?: ComponentType\n\t/** Theme for error display */\n\ttheme?: ThemeVariables\n\t/** Custom retry handler */\n\tonRetry?: () => void\n\t/**\n\t * Behavior when not configured:\n\t * - 'error': Show ConfigurationError (default for auth components)\n\t * - 'null': Return null silently (for optional UI like UserButton)\n\t * - 'children': Render children anyway (for graceful degradation)\n\t */\n\tfallback?: 'error' | 'null' | 'children'\n}\n\nexport interface UseSdkReadyReturn {\n\t/** Whether SDK is ready to use */\n\tisReady: boolean\n\t/** Whether component is mounted (client-side) */\n\tisMounted: boolean\n\t/** Whether SDK is configured */\n\tisConfigured: boolean\n\t/** Whether we're in SSR */\n\tisSSR: boolean\n\t/** Render the appropriate error/fallback */\n\trenderError: () => React.ReactElement | null\n\t/** Service availability map */\n\tservices: Record<SdkService, boolean>\n}\n\n// ============================================\n// Main Hook\n// ============================================\n\n/**\n * Hook for checking SDK readiness with SSOT pattern\n */\nexport function useSdkReady(options: UseSdkReadyOptions = {}): UseSdkReadyReturn {\n\tconst {\n\t\tservices = [],\n\t\tcomponentType = 'general',\n\t\ttheme = defaultTheme,\n\t\tonRetry,\n\t\tfallback = 'error',\n\t} = options\n\n\tconst [isMounted, setIsMounted] = useState(false)\n\n\t// Get platform context (null if not in provider)\n\tconst platformContext = useContext(PlatformContext)\n\n\t// Track mount state\n\tuseEffect(() => {\n\t\tsetIsMounted(true)\n\t}, [])\n\n\t// Check if we're in SSR\n\tconst isSSR = typeof window === 'undefined'\n\n\t// Check if SDK is configured (has appId)\n\tconst isConfigured = Boolean(platformContext?.appId)\n\n\t// Check individual service availability\n\tconst serviceAvailability = useMemo<Record<SdkService, boolean>>(() => {\n\t\tif (!isConfigured) {\n\t\t\t// If not configured, all services are unavailable\n\t\t\treturn {\n\t\t\t\tauth: false,\n\t\t\t\tuser: false,\n\t\t\t\tbilling: false,\n\t\t\t\tstorage: false,\n\t\t\t\tanalytics: false,\n\t\t\t\tflags: false,\n\t\t\t\tconsent: false,\n\t\t\t\torganization: false,\n\t\t\t\tmonitoring: false,\n\t\t\t\tai: false,\n\t\t\t\tjobs: false,\n\t\t\t\tnotifications: false,\n\t\t\t\tnewsletter: false,\n\t\t\t}\n\t\t}\n\n\t\t// When configured, all services are available\n\t\t// (individual service checks could be added here if needed)\n\t\treturn {\n\t\t\tauth: true,\n\t\t\tuser: true,\n\t\t\tbilling: true,\n\t\t\tstorage: true,\n\t\t\tanalytics: true,\n\t\t\tflags: true,\n\t\t\tconsent: true,\n\t\t\torganization: true,\n\t\t\tmonitoring: true,\n\t\t\tai: true,\n\t\t\tjobs: true,\n\t\t\tnotifications: true,\n\t\t\tnewsletter: true,\n\t\t}\n\t}, [isConfigured])\n\n\t// Check if all required services are available\n\tconst requiredServicesReady =\n\t\tservices.length === 0 || services.every((s) => serviceAvailability[s])\n\n\t// Overall readiness\n\tconst isReady = !isSSR && isMounted && isConfigured && requiredServicesReady\n\n\t// Render error function\n\tconst renderError = useCallback((): React.ReactElement | null => {\n\t\t// During SSR, always return null\n\t\tif (isSSR) {\n\t\t\treturn null\n\t\t}\n\n\t\t// Still hydrating, return null\n\t\tif (!isMounted) {\n\t\t\treturn null\n\t\t}\n\n\t\t// If configured and ready, no error to render\n\t\tif (isConfigured && requiredServicesReady) {\n\t\t\treturn null\n\t\t}\n\n\t\t// Handle fallback modes\n\t\tif (fallback === 'null') {\n\t\t\treturn null\n\t\t}\n\n\t\tif (fallback === 'children') {\n\t\t\t// This case is handled by the component itself\n\t\t\treturn null\n\t\t}\n\n\t\t// Use the ConfigurationError component for consistent, polished UI\n\t\treturn (\n\t\t\t<ConfigurationError\n\t\t\t\ttheme={theme}\n\t\t\t\tcomponentType={componentType}\n\t\t\t\tonRetry={onRetry ?? (() => window.location.reload())}\n\t\t\t/>\n\t\t)\n\t}, [\n\t\tisSSR,\n\t\tisMounted,\n\t\tisConfigured,\n\t\trequiredServicesReady,\n\t\tfallback,\n\t\ttheme,\n\t\tcomponentType,\n\t\tonRetry,\n\t])\n\n\treturn {\n\t\tisReady,\n\t\tisMounted,\n\t\tisConfigured,\n\t\tisSSR,\n\t\trenderError,\n\t\tservices: serviceAvailability,\n\t}\n}\n\n// ============================================\n// RequireSdk Wrapper Component\n// ============================================\n\nexport interface RequireSdkProps {\n\t/** Required services */\n\tservices?: SdkService[]\n\t/** Component type for error messaging */\n\tcomponentType?: ComponentType\n\t/** Theme for error display */\n\ttheme?: ThemeVariables\n\t/** Fallback behavior */\n\tfallback?: 'error' | 'null' | 'children'\n\t/** Children to render when ready */\n\tchildren: React.ReactNode\n}\n\n/**\n * Declarative wrapper for SDK configuration checking\n *\n * @example\n * ```tsx\n * <RequireSdk services={['auth', 'user']} componentType=\"sign-in\">\n *   <SignInForm />\n * </RequireSdk>\n * ```\n */\nexport function RequireSdk({\n\tservices = [],\n\tcomponentType = 'general',\n\ttheme,\n\tfallback = 'error',\n\tchildren,\n}: RequireSdkProps): React.ReactElement | null {\n\tconst { isReady, renderError } = useSdkReady({\n\t\tservices,\n\t\tcomponentType,\n\t\ttheme,\n\t\tfallback,\n\t})\n\n\tif (!isReady) {\n\t\tconst error = renderError()\n\t\tif (error) return error\n\t\tif (fallback === 'children') return <>{children}</>\n\t\treturn null\n\t}\n\n\treturn <>{children}</>\n}\n","/**\n * Configuration Error Component\n *\n * Environment-aware error display when SDK is not configured.\n * - Development: Shows helpful setup instructions with step-by-step guide\n * - Production: Shows generic user-friendly message\n *\n * Design inspired by Clerk and other best-in-class auth providers.\n */\n\n'use client'\n\nimport { type CSSProperties, useState } from 'react'\nimport { UI_COPY_FEEDBACK_MS } from '../../constants'\nimport { defaultTheme, type ThemeVariables } from './styles'\n\nexport type ConfigurationComponentType =\n\t| 'sign-in'\n\t| 'sign-up'\n\t| 'user-button'\n\t| 'user'\n\t| 'account'\n\t| 'auth'\n\t| 'billing'\n\t| 'storage'\n\t| 'analytics'\n\t| 'organization'\n\t| 'notifications'\n\t| 'protect'\n\t| 'referral'\n\t| 'general'\n\nexport interface ConfigurationErrorProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Component type for contextual messaging */\n\tcomponentType?: ConfigurationComponentType\n\t/** Custom retry handler */\n\tonRetry?: () => void\n}\n\n/**\n * Detects if we're in a development environment\n */\nfunction isDevelopment(): boolean {\n\t// Check Next.js / Node environment\n\tif (typeof process !== 'undefined' && process.env?.NODE_ENV === 'development') {\n\t\treturn true\n\t}\n\t// Check for localhost\n\tif (typeof window !== 'undefined') {\n\t\tconst hostname = window.location.hostname\n\t\treturn hostname === 'localhost' || hostname === '127.0.0.1' || hostname.endsWith('.local')\n\t}\n\treturn false\n}\n\nconst ENV_VARS_CODE = `NEXT_PUBLIC_SYLPHX_APP_ID=\"app_xxx\"`\n\n/**\n * Development-only setup card with helpful instructions\n */\nfunction DeveloperSetupCard({ theme }: { theme: ThemeVariables }) {\n\tconst [copied, setCopied] = useState(false)\n\n\tconst handleCopy = async () => {\n\t\ttry {\n\t\t\tawait navigator.clipboard.writeText(ENV_VARS_CODE)\n\t\t\tsetCopied(true)\n\t\t\tsetTimeout(() => setCopied(false), UI_COPY_FEEDBACK_MS)\n\t\t} catch {\n\t\t\t// Fallback for older browsers\n\t\t\tconst textarea = document.createElement('textarea')\n\t\t\ttextarea.value = ENV_VARS_CODE\n\t\t\tdocument.body.appendChild(textarea)\n\t\t\ttextarea.select()\n\t\t\tdocument.execCommand('copy')\n\t\t\tdocument.body.removeChild(textarea)\n\t\t\tsetCopied(true)\n\t\t\tsetTimeout(() => setCopied(false), UI_COPY_FEEDBACK_MS)\n\t\t}\n\t}\n\n\treturn (\n\t\t<div style={styles.devCard}>\n\t\t\t{/* Header with icon */}\n\t\t\t<div style={styles.devHeader}>\n\t\t\t\t<div style={styles.iconContainer}>\n\t\t\t\t\t<ToolIcon />\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<h3 style={styles.devTitle}>SDK Configuration Required</h3>\n\t\t\t\t\t<p style={styles.devSubtitle}>Complete setup to enable authentication</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{/* Steps */}\n\t\t\t<div style={styles.stepsContainer}>\n\t\t\t\t{/* Step 1 */}\n\t\t\t\t<div style={styles.step}>\n\t\t\t\t\t<div style={styles.stepNumber}>1</div>\n\t\t\t\t\t<div style={styles.stepContent}>\n\t\t\t\t\t\t<p style={styles.stepTitle}>Get your API keys</p>\n\t\t\t\t\t\t<p style={styles.stepDescription}>\n\t\t\t\t\t\t\tVisit the{' '}\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\thref=\"https://sylphx.com/console\"\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\tstyle={styles.link}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tSylphx Console\n\t\t\t\t\t\t\t</a>{' '}\n\t\t\t\t\t\t\tto create an app and get your keys.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t\t{/* Step 2 */}\n\t\t\t\t<div style={styles.step}>\n\t\t\t\t\t<div style={styles.stepNumber}>2</div>\n\t\t\t\t\t<div style={styles.stepContent}>\n\t\t\t\t\t\t<p style={styles.stepTitle}>\n\t\t\t\t\t\t\tAdd to <code style={styles.inlineCode}>.env.local</code>\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<div style={styles.codeBlock}>\n\t\t\t\t\t\t\t<pre style={styles.codeContent}>{ENV_VARS_CODE}</pre>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tstyle={styles.copyButton}\n\t\t\t\t\t\t\t\tonClick={handleCopy}\n\t\t\t\t\t\t\t\ttitle={copied ? 'Copied!' : 'Copy to clipboard'}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{copied ? <CheckIcon /> : <CopyIcon />}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t\t{/* Step 3 */}\n\t\t\t\t<div style={styles.step}>\n\t\t\t\t\t<div style={styles.stepNumber}>3</div>\n\t\t\t\t\t<div style={styles.stepContent}>\n\t\t\t\t\t\t<p style={styles.stepTitle}>Restart your dev server</p>\n\t\t\t\t\t\t<p style={styles.stepDescription}>\n\t\t\t\t\t\t\tRun <code style={styles.inlineCode}>npm run dev</code> or restart your server to load\n\t\t\t\t\t\t\tthe new environment variables.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{/* Footer */}\n\t\t\t<div style={styles.devFooter}>\n\t\t\t\t<a\n\t\t\t\t\t// `/docs/sdk/getting-started` was never published — the SDK getting-started\n\t\t\t\t\t// content lives under the canonical `/docs/installation` + `/docs/quickstart`\n\t\t\t\t\t// pair (both verified live).\n\t\t\t\t\thref=\"https://sylphx.com/docs/installation\"\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\tstyle={styles.docsButton}\n\t\t\t\t>\n\t\t\t\t\t<BookIcon />\n\t\t\t\t\tRead the docs\n\t\t\t\t</a>\n\t\t\t\t<p style={styles.devNote}>This message only appears in development mode.</p>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n/**\n * Production-friendly error card\n */\nfunction ProductionErrorCard({\n\ttheme,\n\tcomponentType,\n\tonRetry,\n}: {\n\ttheme: ThemeVariables\n\tcomponentType: ConfigurationComponentType\n\tonRetry?: () => void\n}) {\n\tconst getMessage = () => {\n\t\tswitch (componentType) {\n\t\t\tcase 'sign-in':\n\t\t\t\treturn 'Sign in is temporarily unavailable.'\n\t\t\tcase 'sign-up':\n\t\t\t\treturn 'Sign up is temporarily unavailable.'\n\t\t\tcase 'billing':\n\t\t\t\treturn 'Billing is temporarily unavailable.'\n\t\t\tcase 'storage':\n\t\t\t\treturn 'File upload is temporarily unavailable.'\n\t\t\tcase 'organization':\n\t\t\t\treturn 'Organization features are temporarily unavailable.'\n\t\t\tcase 'notifications':\n\t\t\t\treturn 'Notifications are temporarily unavailable.'\n\t\t\tdefault:\n\t\t\t\treturn 'This feature is temporarily unavailable.'\n\t\t}\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tstyle={{\n\t\t\t\t...styles.prodCard,\n\t\t\t\tbackgroundColor: theme.colorBackground,\n\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\tfontFamily: theme.fontFamily,\n\t\t\t}}\n\t\t>\n\t\t\t<div style={styles.prodIcon}>\n\t\t\t\t<AlertIcon color={theme.colorWarning} />\n\t\t\t</div>\n\n\t\t\t<h3\n\t\t\t\tstyle={{\n\t\t\t\t\t...styles.prodTitle,\n\t\t\t\t\tcolor: theme.colorForeground,\n\t\t\t\t\tfontSize: theme.fontSizeLg,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{getMessage()}\n\t\t\t</h3>\n\n\t\t\t<p\n\t\t\t\tstyle={{\n\t\t\t\t\t...styles.prodDescription,\n\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\tPlease try again later or contact support if the problem persists.\n\t\t\t</p>\n\n\t\t\t{onRetry && (\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={onRetry}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\t...styles.retryButton,\n\t\t\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\tbackgroundColor: theme.colorBackground,\n\t\t\t\t\t\tcolor: theme.colorForeground,\n\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\tTry Again\n\t\t\t\t</button>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n/**\n * Main ConfigurationError component\n *\n * Shows different UI based on environment:\n * - Development: Helpful setup instructions\n * - Production: Generic user-friendly error\n */\nexport function ConfigurationError({\n\ttheme = defaultTheme,\n\tcomponentType = 'auth',\n\tonRetry,\n}: ConfigurationErrorProps) {\n\t// Log error for debugging (always)\n\tif (typeof console !== 'undefined') {\n\t\tconsole.error(\n\t\t\t'[Sylphx SDK] Configuration missing. Please set NEXT_PUBLIC_SYLPHX_APP_ID environment variable.',\n\t\t)\n\t}\n\n\t// Development: Show helpful setup card\n\tif (isDevelopment()) {\n\t\treturn <DeveloperSetupCard theme={theme} />\n\t}\n\n\t// Production: Show generic error\n\treturn <ProductionErrorCard theme={theme} componentType={componentType} onRetry={onRetry} />\n}\n\n// ============================================\n// Icons\n// ============================================\n\nfunction ToolIcon() {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"24\"\n\t\t\theight=\"24\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z\" />\n\t\t</svg>\n\t)\n}\n\nfunction CopyIcon() {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\" />\n\t\t\t<path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\" />\n\t\t</svg>\n\t)\n}\n\nfunction CheckIcon() {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"#22c55e\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<polyline points=\"20 6 9 17 4 12\" />\n\t\t</svg>\n\t)\n}\n\nfunction BookIcon() {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M4 19.5A2.5 2.5 0 0 1 6.5 17H20\" />\n\t\t\t<path d=\"M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z\" />\n\t\t</svg>\n\t)\n}\n\nfunction AlertIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"24\"\n\t\t\theight=\"24\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<circle cx=\"12\" cy=\"12\" r=\"10\" />\n\t\t\t<line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n\t\t\t<line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n\t\t</svg>\n\t)\n}\n\n// ============================================\n// Styles\n// ============================================\n\nconst styles: Record<string, CSSProperties> = {\n\t// Development card styles\n\tdevCard: {\n\t\tmaxWidth: '420px',\n\t\tmargin: '0 auto',\n\t\tpadding: '1.5rem',\n\t\tbackgroundColor: '#fffbeb', // amber-50\n\t\tborder: '1px solid #fcd34d', // amber-300\n\t\tborderRadius: '12px',\n\t\tfontFamily:\n\t\t\t'-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n\t\tboxShadow: '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)',\n\t},\n\tdevHeader: {\n\t\tdisplay: 'flex',\n\t\talignItems: 'flex-start',\n\t\tgap: '0.75rem',\n\t\tmarginBottom: '1.25rem',\n\t},\n\ticonContainer: {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'center',\n\t\twidth: '40px',\n\t\theight: '40px',\n\t\tborderRadius: '10px',\n\t\tbackgroundColor: '#fef3c7', // amber-100\n\t\tcolor: '#d97706', // amber-600\n\t\tflexShrink: 0,\n\t},\n\tdevTitle: {\n\t\tmargin: 0,\n\t\tfontSize: '1rem',\n\t\tfontWeight: 600,\n\t\tcolor: '#78350f', // amber-900\n\t\tlineHeight: 1.4,\n\t},\n\tdevSubtitle: {\n\t\tmargin: '0.125rem 0 0',\n\t\tfontSize: '0.8125rem',\n\t\tcolor: '#92400e', // amber-800\n\t\tlineHeight: 1.4,\n\t},\n\tstepsContainer: {\n\t\tdisplay: 'flex',\n\t\tflexDirection: 'column',\n\t\tgap: '1rem',\n\t},\n\tstep: {\n\t\tdisplay: 'flex',\n\t\tgap: '0.75rem',\n\t},\n\tstepNumber: {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'center',\n\t\twidth: '24px',\n\t\theight: '24px',\n\t\tborderRadius: '50%',\n\t\tbackgroundColor: '#d97706', // amber-600\n\t\tcolor: '#fff',\n\t\tfontSize: '0.75rem',\n\t\tfontWeight: 600,\n\t\tflexShrink: 0,\n\t},\n\tstepContent: {\n\t\tflex: 1,\n\t\tminWidth: 0,\n\t},\n\tstepTitle: {\n\t\tmargin: 0,\n\t\tfontSize: '0.875rem',\n\t\tfontWeight: 500,\n\t\tcolor: '#78350f', // amber-900\n\t\tlineHeight: 1.4,\n\t},\n\tstepDescription: {\n\t\tmargin: '0.25rem 0 0',\n\t\tfontSize: '0.8125rem',\n\t\tcolor: '#92400e', // amber-800\n\t\tlineHeight: 1.5,\n\t},\n\tlink: {\n\t\tcolor: '#0369a1', // sky-700\n\t\ttextDecoration: 'none',\n\t\tfontWeight: 500,\n\t},\n\tinlineCode: {\n\t\tbackgroundColor: '#fde68a', // amber-200\n\t\tpadding: '0.125rem 0.375rem',\n\t\tborderRadius: '4px',\n\t\tfontSize: '0.8125rem',\n\t\tfontFamily: 'ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, monospace',\n\t},\n\tcodeBlock: {\n\t\tposition: 'relative',\n\t\tmarginTop: '0.5rem',\n\t\tbackgroundColor: '#1e293b', // slate-800\n\t\tborderRadius: '8px',\n\t\toverflow: 'hidden',\n\t},\n\tcodeContent: {\n\t\tdisplay: 'block',\n\t\tmargin: 0,\n\t\tpadding: '0.875rem 1rem',\n\t\tpaddingRight: '3rem',\n\t\tcolor: '#e2e8f0', // slate-200\n\t\tfontSize: '0.75rem',\n\t\tfontFamily: 'ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, monospace',\n\t\twhiteSpace: 'pre',\n\t\tlineHeight: 1.6,\n\t\toverflow: 'auto',\n\t},\n\tcopyButton: {\n\t\tposition: 'absolute',\n\t\ttop: '0.5rem',\n\t\tright: '0.5rem',\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'center',\n\t\twidth: '28px',\n\t\theight: '28px',\n\t\tpadding: 0,\n\t\tbackground: 'rgba(255, 255, 255, 0.1)',\n\t\tborder: 'none',\n\t\tborderRadius: '6px',\n\t\tcursor: 'pointer',\n\t\tcolor: '#94a3b8', // slate-400\n\t\ttransition: 'background-color 0.15s, color 0.15s',\n\t},\n\tdevFooter: {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'space-between',\n\t\tmarginTop: '1.25rem',\n\t\tpaddingTop: '1rem',\n\t\tborderTop: '1px solid #fcd34d', // amber-300\n\t},\n\tdocsButton: {\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\tgap: '0.375rem',\n\t\tpadding: '0.5rem 0.75rem',\n\t\tbackgroundColor: '#d97706', // amber-600\n\t\tcolor: '#fff',\n\t\tfontSize: '0.8125rem',\n\t\tfontWeight: 500,\n\t\tborderRadius: '6px',\n\t\ttextDecoration: 'none',\n\t\ttransition: 'background-color 0.15s',\n\t},\n\tdevNote: {\n\t\tmargin: 0,\n\t\tfontSize: '0.6875rem',\n\t\tcolor: '#92400e', // amber-800\n\t\tfontStyle: 'italic',\n\t},\n\n\t// Production card styles\n\tprodCard: {\n\t\tmaxWidth: '400px',\n\t\tmargin: '0 auto',\n\t\tpadding: '2rem',\n\t\tborderRadius: '12px',\n\t\ttextAlign: 'center',\n\t},\n\tprodIcon: {\n\t\tdisplay: 'flex',\n\t\tjustifyContent: 'center',\n\t\tmarginBottom: '1rem',\n\t},\n\tprodTitle: {\n\t\tmargin: '0 0 0.5rem 0',\n\t\tfontWeight: 600,\n\t},\n\tprodDescription: {\n\t\tmargin: '0 0 1.5rem 0',\n\t\tlineHeight: 1.5,\n\t},\n\tretryButton: {\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'center',\n\t\tpadding: '0.625rem 1.25rem',\n\t\tfontWeight: 500,\n\t\tcursor: 'pointer',\n\t\ttransition: 'background-color 0.15s, border-color 0.15s',\n\t},\n}\n","/**\n * Sylphx SDK Styling System\n *\n * Self-contained CSS-in-JS styles for SDK components.\n * Uses CSS custom properties for theming.\n */\n\nimport type { CSSProperties } from 'react'\n\n// ============================================\n// Theme Variables\n// ============================================\n\nexport interface ThemeVariables {\n\t// Colors\n\tcolorPrimary: string\n\tcolorPrimaryForeground: string\n\tcolorBackground: string\n\tcolorForeground: string\n\tcolorMuted: string\n\tcolorMutedForeground: string\n\tcolorBorder: string\n\tcolorInput: string\n\tcolorInputBackground: string\n\tcolorRing: string\n\tcolorDestructive: string\n\tcolorDestructiveForeground: string\n\tcolorSuccess: string\n\tcolorSuccessForeground: string\n\tcolorWarning: string\n\tcolorWarningForeground: string\n\n\t// Typography\n\tfontFamily: string\n\tfontSizeXs: string\n\tfontSizeSm: string\n\tfontSizeBase: string\n\tfontSizeLg: string\n\tfontSizeXl: string\n\tfontSizeXxl: string\n\n\t// Spacing & Borders\n\tborderRadius: string\n\tborderRadiusSm: string\n\tborderRadiusLg: string\n\tspacingUnit: string\n}\n\nexport const defaultTheme: ThemeVariables = {\n\t// Colors - Light theme\n\tcolorPrimary: '#0ea5e9',\n\tcolorPrimaryForeground: '#ffffff',\n\tcolorBackground: '#ffffff',\n\tcolorForeground: '#0f172a',\n\tcolorMuted: '#f1f5f9',\n\tcolorMutedForeground: '#64748b',\n\tcolorBorder: '#e2e8f0',\n\tcolorInput: '#e2e8f0',\n\tcolorInputBackground: '#ffffff',\n\tcolorRing: '#0ea5e9',\n\tcolorDestructive: '#ef4444',\n\tcolorDestructiveForeground: '#ffffff',\n\tcolorSuccess: '#22c55e',\n\tcolorSuccessForeground: '#ffffff',\n\tcolorWarning: '#f59e0b',\n\tcolorWarningForeground: '#ffffff',\n\n\t// Typography\n\tfontFamily:\n\t\t'-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n\tfontSizeXs: '0.75rem',\n\tfontSizeSm: '0.875rem',\n\tfontSizeBase: '1rem',\n\tfontSizeLg: '1.125rem',\n\tfontSizeXl: '1.25rem',\n\tfontSizeXxl: '1.5rem',\n\n\t// Spacing & Borders\n\tborderRadius: '0.5rem',\n\tborderRadiusSm: '0.375rem',\n\tborderRadiusLg: '0.75rem',\n\tspacingUnit: '0.25rem',\n}\n\nexport const darkTheme: Partial<ThemeVariables> = {\n\tcolorBackground: '#0f172a',\n\tcolorForeground: '#f8fafc',\n\tcolorMuted: '#1e293b',\n\tcolorMutedForeground: '#94a3b8',\n\tcolorBorder: '#334155',\n\tcolorInput: '#334155',\n\tcolorInputBackground: '#1e293b',\n}\n\n// ============================================\n// Style Utilities\n// ============================================\n\ntype StyleFunction = (theme: ThemeVariables) => CSSProperties\n\n/**\n * Create themed styles\n */\nexport function createStyles<T extends Record<string, StyleFunction | CSSProperties>>(\n\tstylesFn: (theme: ThemeVariables) => T,\n): (theme: ThemeVariables) => { [K in keyof T]: CSSProperties } {\n\treturn (theme: ThemeVariables) => {\n\t\tconst styles = stylesFn(theme)\n\t\tconst result: Record<string, CSSProperties> = {}\n\n\t\tfor (const [key, value] of Object.entries(styles)) {\n\t\t\tif (typeof value === 'function') {\n\t\t\t\tresult[key] = value(theme)\n\t\t\t} else {\n\t\t\t\tresult[key] = value\n\t\t\t}\n\t\t}\n\n\t\treturn result as { [K in keyof T]: CSSProperties }\n\t}\n}\n\n/**\n * Merge multiple style objects\n */\nexport function mergeStyles(...styles: (CSSProperties | undefined)[]): CSSProperties {\n\treturn Object.assign({}, ...styles.filter(Boolean))\n}\n\n/**\n * Conditional styles\n */\nexport function conditionalStyle(\n\tcondition: boolean,\n\ttrueStyle: CSSProperties,\n\tfalseStyle?: CSSProperties,\n): CSSProperties {\n\treturn condition ? trueStyle : (falseStyle ?? {})\n}\n\n// ============================================\n// Base Component Styles\n// ============================================\n\nexport const baseStyles = createStyles((theme) => ({\n\t// Container\n\tcontainer: {\n\t\tfontFamily: theme.fontFamily,\n\t\tfontSize: theme.fontSizeBase,\n\t\tcolor: theme.colorForeground,\n\t\tbackgroundColor: theme.colorBackground,\n\t\tlineHeight: 1.5,\n\t\tboxSizing: 'border-box',\n\t},\n\n\t// Card\n\tcard: {\n\t\tbackgroundColor: theme.colorBackground,\n\t\tborderRadius: theme.borderRadiusLg,\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tboxShadow: '0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)',\n\t\toverflow: 'hidden',\n\t},\n\n\tcardHeader: {\n\t\tpadding: '1.5rem',\n\t\tpaddingBottom: '0',\n\t},\n\n\tcardContent: {\n\t\tpadding: '1.5rem',\n\t},\n\n\tcardTitle: {\n\t\tfontSize: theme.fontSizeXl,\n\t\tfontWeight: 600,\n\t\tmargin: 0,\n\t\tmarginBottom: '0.25rem',\n\t},\n\n\tcardDescription: {\n\t\tfontSize: theme.fontSizeSm,\n\t\tcolor: theme.colorMutedForeground,\n\t\tmargin: 0,\n\t},\n\n\t// Form Elements\n\tformGroup: {\n\t\tmarginBottom: '1rem',\n\t},\n\n\tlabel: {\n\t\tdisplay: 'block',\n\t\tfontSize: theme.fontSizeSm,\n\t\tfontWeight: 500,\n\t\tmarginBottom: '0.5rem',\n\t\tcolor: theme.colorForeground,\n\t},\n\n\tinput: {\n\t\twidth: '100%',\n\t\tpadding: '0.5rem 0.75rem',\n\t\tfontSize: theme.fontSizeBase,\n\t\tlineHeight: 1.5,\n\t\tcolor: theme.colorForeground,\n\t\tbackgroundColor: theme.colorInputBackground,\n\t\tborder: `1px solid ${theme.colorInput}`,\n\t\tborderRadius: theme.borderRadius,\n\t\toutline: 'none',\n\t\ttransition: 'border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out',\n\t\tboxSizing: 'border-box',\n\t},\n\n\tinputFocus: {\n\t\tborderColor: theme.colorRing,\n\t\tboxShadow: `0 0 0 3px ${theme.colorRing}33`,\n\t},\n\n\tinputError: {\n\t\tborderColor: theme.colorDestructive,\n\t},\n\n\tinputDisabled: {\n\t\tbackgroundColor: theme.colorMuted,\n\t\tcursor: 'not-allowed',\n\t\topacity: 0.7,\n\t},\n\n\t// Buttons\n\tbutton: {\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'center',\n\t\tgap: '0.5rem',\n\t\tpadding: '0.5rem 1rem',\n\t\tfontSize: theme.fontSizeSm,\n\t\tfontWeight: 500,\n\t\tlineHeight: 1.5,\n\t\tborderRadius: theme.borderRadius,\n\t\tborder: 'none',\n\t\tcursor: 'pointer',\n\t\ttransition: 'all 0.15s ease-in-out',\n\t\ttextDecoration: 'none',\n\t\twhiteSpace: 'nowrap',\n\t},\n\n\tbuttonPrimary: {\n\t\tbackgroundColor: theme.colorPrimary,\n\t\tcolor: theme.colorPrimaryForeground,\n\t},\n\n\tbuttonPrimaryHover: {\n\t\tbackgroundColor: theme.colorPrimary,\n\t\tfilter: 'brightness(1.1)',\n\t},\n\n\tbuttonSecondary: {\n\t\tbackgroundColor: theme.colorMuted,\n\t\tcolor: theme.colorForeground,\n\t},\n\n\tbuttonOutline: {\n\t\tbackgroundColor: 'transparent',\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tcolor: theme.colorForeground,\n\t},\n\n\tbuttonGhost: {\n\t\tbackgroundColor: 'transparent',\n\t\tcolor: theme.colorForeground,\n\t},\n\n\tbuttonDestructive: {\n\t\tbackgroundColor: theme.colorDestructive,\n\t\tcolor: theme.colorDestructiveForeground,\n\t},\n\n\tbuttonDisabled: {\n\t\topacity: 0.5,\n\t\tcursor: 'not-allowed',\n\t},\n\n\tbuttonFullWidth: {\n\t\twidth: '100%',\n\t},\n\n\t// Links\n\tlink: {\n\t\tcolor: theme.colorPrimary,\n\t\ttextDecoration: 'none',\n\t\tcursor: 'pointer',\n\t},\n\n\tlinkHover: {\n\t\ttextDecoration: 'underline',\n\t},\n\n\t// Alerts\n\talert: {\n\t\tpadding: '0.75rem 1rem',\n\t\tborderRadius: theme.borderRadius,\n\t\tfontSize: theme.fontSizeSm,\n\t\tmarginBottom: '1rem',\n\t},\n\n\talertError: {\n\t\tbackgroundColor: `${theme.colorDestructive}15`,\n\t\tcolor: theme.colorDestructive,\n\t\tborder: `1px solid ${theme.colorDestructive}30`,\n\t},\n\n\talertSuccess: {\n\t\tbackgroundColor: `${theme.colorSuccess}15`,\n\t\tcolor: theme.colorSuccess,\n\t\tborder: `1px solid ${theme.colorSuccess}30`,\n\t},\n\n\talertWarning: {\n\t\tbackgroundColor: `${theme.colorWarning}15`,\n\t\tcolor: theme.colorWarning,\n\t\tborder: `1px solid ${theme.colorWarning}30`,\n\t},\n\n\t// Divider\n\tdivider: {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tmargin: '1.5rem 0',\n\t},\n\n\tdividerLine: {\n\t\tflex: 1,\n\t\theight: '1px',\n\t\tbackgroundColor: theme.colorBorder,\n\t},\n\n\tdividerText: {\n\t\tpadding: '0 1rem',\n\t\tfontSize: theme.fontSizeXs,\n\t\tcolor: theme.colorMutedForeground,\n\t\ttextTransform: 'uppercase',\n\t\tletterSpacing: '0.05em',\n\t},\n\n\t// Tabs\n\ttabs: {\n\t\tdisplay: 'flex',\n\t\tbackgroundColor: theme.colorMuted,\n\t\tpadding: '0.25rem',\n\t\tborderRadius: theme.borderRadius,\n\t\tmarginBottom: '1.5rem',\n\t},\n\n\ttab: {\n\t\tflex: 1,\n\t\tpadding: '0.5rem 0.75rem',\n\t\tfontSize: theme.fontSizeSm,\n\t\tfontWeight: 500,\n\t\tcolor: theme.colorMutedForeground,\n\t\tbackgroundColor: 'transparent',\n\t\tborder: 'none',\n\t\tborderRadius: theme.borderRadiusSm,\n\t\tcursor: 'pointer',\n\t\ttransition: 'all 0.15s ease-in-out',\n\t},\n\n\ttabActive: {\n\t\tbackgroundColor: theme.colorBackground,\n\t\tcolor: theme.colorForeground,\n\t\tboxShadow: '0 1px 2px 0 rgb(0 0 0 / 0.05)',\n\t},\n\n\t// Badge\n\tbadge: {\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\tpadding: '0.125rem 0.5rem',\n\t\tfontSize: theme.fontSizeXs,\n\t\tfontWeight: 500,\n\t\tborderRadius: '9999px',\n\t},\n\n\tbadgePrimary: {\n\t\tbackgroundColor: `${theme.colorPrimary}15`,\n\t\tcolor: theme.colorPrimary,\n\t},\n\n\tbadgeSuccess: {\n\t\tbackgroundColor: `${theme.colorSuccess}15`,\n\t\tcolor: theme.colorSuccess,\n\t},\n\n\tbadgeWarning: {\n\t\tbackgroundColor: `${theme.colorWarning}15`,\n\t\tcolor: theme.colorWarning,\n\t},\n\n\tbadgeDestructive: {\n\t\tbackgroundColor: `${theme.colorDestructive}15`,\n\t\tcolor: theme.colorDestructive,\n\t},\n\n\t// Spinner\n\tspinner: {\n\t\twidth: '1rem',\n\t\theight: '1rem',\n\t\tborder: '2px solid transparent',\n\t\tborderTopColor: 'currentColor',\n\t\tborderRadius: '50%',\n\t\tanimation: 'sylphx-spin 0.75s linear infinite',\n\t},\n\n\t// Text utilities\n\ttextMuted: {\n\t\tcolor: theme.colorMutedForeground,\n\t},\n\n\ttextCenter: {\n\t\ttextAlign: 'center',\n\t},\n\n\ttextSm: {\n\t\tfontSize: theme.fontSizeSm,\n\t},\n\n\ttextXs: {\n\t\tfontSize: theme.fontSizeXs,\n\t},\n\n\t// Spacing utilities\n\tmt1: { marginTop: '0.25rem' },\n\tmt2: { marginTop: '0.5rem' },\n\tmt4: { marginTop: '1rem' },\n\tmt6: { marginTop: '1.5rem' },\n\tmb1: { marginBottom: '0.25rem' },\n\tmb2: { marginBottom: '0.5rem' },\n\tmb4: { marginBottom: '1rem' },\n\tmb6: { marginBottom: '1.5rem' },\n\n\t// Flexbox utilities\n\tflexRow: {\n\t\tdisplay: 'flex',\n\t\tflexDirection: 'row',\n\t},\n\n\tflexCol: {\n\t\tdisplay: 'flex',\n\t\tflexDirection: 'column',\n\t},\n\n\tflexCenter: {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'center',\n\t},\n\n\tflexBetween: {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'space-between',\n\t},\n\n\tgap1: { gap: '0.25rem' },\n\tgap2: { gap: '0.5rem' },\n\tgap3: { gap: '0.75rem' },\n\tgap4: { gap: '1rem' },\n\n\t// Grid\n\tgrid: {\n\t\tdisplay: 'grid',\n\t},\n\n\tgridCols2: {\n\t\tgridTemplateColumns: 'repeat(2, 1fr)',\n\t},\n}))\n\n// ============================================\n// CSS Keyframes (injected once)\n// ============================================\n\nlet stylesInjected = false\n\nexport function injectGlobalStyles(): void {\n\tif (stylesInjected || typeof document === 'undefined') return\n\n\tconst style = document.createElement('style')\n\tstyle.id = 'sylphx-runtime-styles'\n\tstyle.textContent = `\n    @keyframes sylphx-spin {\n      to { transform: rotate(360deg); }\n    }\n\n    @keyframes sylphx-fade-in {\n      from { opacity: 0; }\n      to { opacity: 1; }\n    }\n\n    @keyframes sylphx-slide-up {\n      from {\n        opacity: 0;\n        transform: translateY(10px);\n      }\n      to {\n        opacity: 1;\n        transform: translateY(0);\n      }\n    }\n\n    @keyframes sylphx-scale-in {\n      from {\n        opacity: 0;\n        transform: scale(0.95);\n      }\n      to {\n        opacity: 1;\n        transform: scale(1);\n      }\n    }\n\n    .sylphx-focus-visible:focus-visible {\n      outline: 2px solid var(--sylphx-ring);\n      outline-offset: 2px;\n    }\n\n    .sylphx-upload-hover:hover .sylphx-upload-hover__overlay,\n    .sylphx-upload-hover:focus-within .sylphx-upload-hover__overlay {\n      opacity: 1 !important;\n    }\n  `\n\tdocument.head.appendChild(style)\n\tstylesInjected = true\n}\n","/**\n * Platform Hooks\n *\n * Hooks for billing, analytics, notifications, and referrals.\n */\n\n'use client'\n\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useCallback, useContext } from 'react'\nimport { STALE_TIME_FREQUENT_MS } from '../constants'\nimport {\n\ttype AnalyticsQuery,\n\ttype AnalyticsQueryResult,\n\ttype ClickIds,\n\ttype ConversionData,\n\ttype DestinationPlatform,\n\ttype InAppMessagePriority,\n\ttype InAppMessageType,\n\ttype InAppMessageWithReadStatus,\n\ttype InboxPreferences,\n\ttype Plan,\n\tPlatformContext,\n\ttype PushPreferences,\n\ttype RedeemResult,\n\ttype ReferralRewardDefaults,\n\ttype ReferralStats,\n\ttype Subscription,\n\ttype TrackOptions,\n} from './platform-context'\n\n// Re-export types for convenience\nexport type { TrackOptions, ConversionData, DestinationPlatform, ClickIds }\nexport type { InAppMessageWithReadStatus, InAppMessageType, InAppMessagePriority, InboxPreferences }\n\n/** Alias for easier naming */\nexport type InAppMessage = InAppMessageWithReadStatus\n\n/**\n * Internal hook to get platform context\n */\nfunction usePlatformContext() {\n\tconst context = useContext(PlatformContext)\n\tif (!context) {\n\t\tthrow new Error('Platform hooks must be used within a SylphxProvider')\n\t}\n\treturn context\n}\n\n/**\n * Internal hook to get platform context (safe version - returns null if no provider)\n * Use this for hooks that need to work outside SylphxProvider during SSR/prerendering\n */\nfunction usePlatformContextSafe() {\n\treturn useContext(PlatformContext)\n}\n\n// ============================================\n// useBilling\n// ============================================\n\nexport interface UseBillingReturn {\n\t/** Current subscription (null if free/none) */\n\tsubscription: Subscription | null\n\t/** Whether subscription is loading */\n\tisLoading: boolean\n\t/** Error loading subscription */\n\terror: Error | null\n\t/** Whether there was an error loading subscription */\n\tisError: boolean\n\t/** All available plans */\n\tplans: Plan[]\n\t/** Whether plans are loading */\n\tplansLoading: boolean\n\t/** Error loading plans */\n\tplansError: Error | null\n\t/** Whether user has an active paid subscription */\n\tisPremium: boolean\n\t/** Whether user is on a trial */\n\tisTrialing: boolean\n\t/** Create checkout session and get URL */\n\tcreateCheckout: (planSlug: string, interval: 'monthly' | 'annual' | 'lifetime') => Promise<string>\n\t/** Open billing portal to manage subscription */\n\topenPortal: () => Promise<void>\n\t/** Refresh subscription data */\n\trefresh: () => Promise<void>\n}\n\n/**\n * Hook for billing and subscription management\n *\n * @example\n * ```tsx\n * function PricingPage() {\n *   const { plans, subscription, isPremium, createCheckout } = useBilling()\n *\n *   if (isPremium) {\n *     return <div>You're on {subscription?.planName}!</div>\n *   }\n *\n *   return (\n *     <div>\n *       {plans.map(plan => (\n *         <button\n *           key={plan.id}\n *           onClick={() => createCheckout(plan.slug, 'monthly')}\n *         >\n *           Subscribe to {plan.name}\n *         </button>\n *       ))}\n *     </div>\n *   )\n * }\n * ```\n */\nexport function useBilling(): UseBillingReturn {\n\tconst ctx = usePlatformContext()\n\n\tconst isPremium = ctx.subscription?.status === 'active' || ctx.subscription?.status === 'trialing'\n\n\tconst isTrialing = ctx.subscription?.status === 'trialing'\n\n\treturn {\n\t\tsubscription: ctx.subscription,\n\t\tisLoading: ctx.subscriptionLoading,\n\t\terror: ctx.subscriptionError,\n\t\tisError: ctx.subscriptionError !== null,\n\t\tplans: ctx.plans,\n\t\tplansLoading: ctx.plansLoading,\n\t\tplansError: ctx.plansError,\n\t\tisPremium,\n\t\tisTrialing,\n\t\tcreateCheckout: ctx.createCheckout,\n\t\topenPortal: ctx.openPortal,\n\t\trefresh: ctx.refreshSubscription,\n\t}\n}\n\n// ============================================\n// useSafeBilling (SSR-safe version)\n// ============================================\n\nexport interface UseSafeBillingReturn {\n\t/** Whether SDK is configured */\n\tisConfigured: boolean\n\t/** Current subscription (null if free/none or not configured) */\n\tsubscription: Subscription | null\n\t/** Whether subscription is loading */\n\tisLoading: boolean\n\t/** Whether user has an active paid subscription */\n\tisPremium: boolean\n\t/** Whether user is on a trial */\n\tisTrialing: boolean\n}\n\n/**\n * SSR-safe version of useBilling that returns safe defaults when outside SylphxProvider\n *\n * Use this in components that may render during SSR/static generation.\n *\n * @example\n * ```tsx\n * function FeatureGate({ children }) {\n *   const { isConfigured, isPremium } = useSafeBilling()\n *\n *   // Not configured - show content to all\n *   if (!isConfigured) return children\n *\n *   // Configured - check premium status\n *   return isPremium ? children : <UpgradePrompt />\n * }\n * ```\n */\nexport function useSafeBilling(): UseSafeBillingReturn {\n\tconst ctx = usePlatformContextSafe()\n\n\tif (!ctx) {\n\t\treturn {\n\t\t\tisConfigured: false,\n\t\t\tsubscription: null,\n\t\t\tisLoading: false,\n\t\t\tisPremium: false,\n\t\t\tisTrialing: false,\n\t\t}\n\t}\n\n\tconst isPremium = ctx.subscription?.status === 'active' || ctx.subscription?.status === 'trialing'\n\n\tconst isTrialing = ctx.subscription?.status === 'trialing'\n\n\treturn {\n\t\tisConfigured: true,\n\t\tsubscription: ctx.subscription,\n\t\tisLoading: ctx.subscriptionLoading,\n\t\tisPremium,\n\t\tisTrialing,\n\t}\n}\n\n// ============================================\n// useAnalytics\n// ============================================\n\nexport interface UseAnalyticsReturn {\n\t/**\n\t * Track a custom event with optional destination forwarding\n\t *\n\t * @example Basic tracking\n\t * ```ts\n\t * track('page_view', { path: '/products' })\n\t * ```\n\t *\n\t * @example Track purchase with conversion data\n\t * ```ts\n\t * track('purchase', { product: 'Premium' }, {\n\t *   destinations: ['google_ads', 'meta'],\n\t *   conversion: {\n\t *     value: 99.99,\n\t *     currency: 'USD',\n\t *     orderId: 'ORDER-123',\n\t *     userEmail: user.email,\n\t *   }\n\t * })\n\t * ```\n\t *\n\t * @example Skip destinations for internal events\n\t * ```ts\n\t * track('button_click', { button: 'nav' }, { skipDestinations: true })\n\t * ```\n\t */\n\ttrack: (\n\t\tevent: string,\n\t\tproperties?: Record<string, unknown>,\n\t\toptions?: TrackOptions,\n\t) => Promise<void>\n\t/** Track a page view */\n\tpage: (name: string, properties?: Record<string, unknown>) => Promise<void>\n\t/** Identify user with traits */\n\tidentify: (traits?: Record<string, unknown>) => Promise<void>\n\t/** Error from analytics operations */\n\terror: Error | null\n\t/** Whether there was an error */\n\tisError: boolean\n}\n\n/**\n * Hook for analytics tracking with conversion destinations\n *\n * @example Basic tracking\n * ```tsx\n * function GameComplete() {\n *   const { track } = useAnalytics()\n *\n *   useEffect(() => {\n *     track('game_completed', {\n *       score: 100,\n *       timeMs: 5000,\n *       difficulty: 'hard',\n *     })\n *   }, [])\n *\n *   return <div>Game Complete!</div>\n * }\n * ```\n *\n * @example Track conversion with ad platform forwarding\n * ```tsx\n * function CheckoutSuccess() {\n *   const { track } = useAnalytics()\n *\n *   useEffect(() => {\n *     track('purchase', { product: 'Premium Plan' }, {\n *       destinations: ['google_ads', 'meta', 'tiktok'],\n *       conversion: {\n *         value: 99.99,\n *         currency: 'USD',\n *         orderId: order.id,\n *         userEmail: user.email,\n *         clickId: gclid || fbclid || ttclid,\n *       }\n *     })\n *   }, [])\n *\n *   return <div>Thank you for your purchase!</div>\n * }\n * ```\n */\nexport function useAnalytics(): UseAnalyticsReturn {\n\tconst ctx = usePlatformContext()\n\n\treturn {\n\t\ttrack: ctx.track,\n\t\tpage: ctx.page,\n\t\tidentify: ctx.identify,\n\t\terror: ctx.analyticsError,\n\t\tisError: ctx.analyticsError !== null,\n\t}\n}\n\n// ============================================\n// useSafeAnalytics (SSR-safe version)\n// ============================================\n\nexport interface UseSafeAnalyticsReturn {\n\t/** Whether SDK is configured */\n\tisConfigured: boolean\n\t/** Track a custom event (no-op if not configured) */\n\ttrack: (\n\t\tevent: string,\n\t\tproperties?: Record<string, unknown>,\n\t\toptions?: TrackOptions,\n\t) => Promise<void>\n\t/** Track a page view (no-op if not configured) */\n\tpage: (name: string, properties?: Record<string, unknown>) => Promise<void>\n\t/** Identify user with traits (no-op if not configured) */\n\tidentify: (traits?: Record<string, unknown>) => Promise<void>\n}\n\n// No-op async function for safe hooks\nconst noopAsync = async () => {}\n\n/**\n * SSR-safe version of useAnalytics that returns no-op functions when outside SylphxProvider\n *\n * Use this in components that may render during SSR/static generation.\n *\n * @example\n * ```tsx\n * function Analytics() {\n *   const { isConfigured, track } = useSafeAnalytics()\n *\n *   useEffect(() => {\n *     // Safe to call even outside provider\n *     track('page_view', { path: window.location.pathname })\n *   }, [])\n *\n *   return null\n * }\n * ```\n */\nexport function useSafeAnalytics(): UseSafeAnalyticsReturn {\n\tconst ctx = usePlatformContextSafe()\n\n\tif (!ctx) {\n\t\treturn {\n\t\t\tisConfigured: false,\n\t\t\ttrack: noopAsync,\n\t\t\tpage: noopAsync,\n\t\t\tidentify: noopAsync,\n\t\t}\n\t}\n\n\treturn {\n\t\tisConfigured: true,\n\t\ttrack: ctx.track,\n\t\tpage: ctx.page,\n\t\tidentify: ctx.identify,\n\t}\n}\n\n// ============================================\n// useNotifications\n// ============================================\n\nexport interface UseNotificationsReturn {\n\t/** Whether push notifications are supported in this browser */\n\tisSupported: boolean\n\t/** Whether user is subscribed to push */\n\tisSubscribed: boolean\n\t/** User's notification preferences */\n\tpreferences: PushPreferences | null\n\t/** Error from notification operations */\n\terror: Error | null\n\t/** Whether there was an error */\n\tisError: boolean\n\t/** Subscribe to notifications */\n\tsubscribe: () => Promise<boolean>\n\t/** Unsubscribe from notifications */\n\tunsubscribe: () => Promise<void>\n\t/** Update notification preferences */\n\tupdatePreferences: (prefs: Partial<PushPreferences>) => Promise<void>\n}\n\n/**\n * Hook for notification management\n *\n * @example\n * ```tsx\n * function NotificationSettings() {\n *   const { isSupported, isSubscribed, subscribe, unsubscribe, preferences } = useNotifications()\n *\n *   if (!isSupported) {\n *     return <div>Notifications not supported</div>\n *   }\n *\n *   return (\n *     <button onClick={isSubscribed ? unsubscribe : subscribe}>\n *       {isSubscribed ? 'Disable' : 'Enable'} Notifications\n *     </button>\n *   )\n * }\n * ```\n */\nexport function useNotifications(): UseNotificationsReturn {\n\tconst ctx = usePlatformContext()\n\n\treturn {\n\t\tisSupported: ctx.pushSupported,\n\t\tisSubscribed: ctx.pushSubscribed,\n\t\tpreferences: ctx.pushPreferences,\n\t\terror: ctx.pushError,\n\t\tisError: ctx.pushError !== null,\n\t\tsubscribe: ctx.subscribePush,\n\t\tunsubscribe: ctx.unsubscribePush,\n\t\tupdatePreferences: ctx.updatePushPreferences,\n\t}\n}\n\n// ============================================\n// useMobilePush\n// ============================================\n\nexport interface MobileDevice {\n\tid: string\n\tplatform: 'ios' | 'android' | 'web'\n\tname: string | null\n\tregisteredAt: string\n\tlastUsedAt: string | null | undefined\n}\n\nexport interface UseMobilePushReturn {\n\t/** Whether iOS push is configured for this app */\n\tiosConfigured: boolean\n\t/** Whether Android push is configured for this app */\n\tandroidConfigured: boolean\n\t/** Whether any mobile push is configured */\n\tisConfigured: boolean\n\t/** List of registered devices for current user */\n\tdevices: MobileDevice[]\n\t/** Whether mobile push is enabled (has registered devices) */\n\tisEnabled: boolean\n\t/** Error from mobile push operations */\n\terror: Error | null\n\t/** Whether there was an error */\n\tisError: boolean\n\t/**\n\t * Register a mobile device for push notifications\n\t *\n\t * Call this after obtaining a device token from APNs (iOS) or FCM (Android).\n\t *\n\t * @example iOS with react-native-push-notification\n\t * ```tsx\n\t * import PushNotification from 'react-native-push-notification'\n\t *\n\t * PushNotification.configure({\n\t *   onRegister: async (token) => {\n\t *     await registerDevice({\n\t *       platform: 'ios',\n\t *       token: token.token,\n\t *       deviceName: DeviceInfo.getDeviceId(),\n\t *       appVersion: DeviceInfo.getVersion(),\n\t *       osVersion: DeviceInfo.getSystemVersion(),\n\t *     })\n\t *   },\n\t * })\n\t * ```\n\t *\n\t * @example Android with firebase messaging\n\t * ```tsx\n\t * import messaging from '@react-native-firebase/messaging'\n\t *\n\t * const token = await messaging().getToken()\n\t * await registerDevice({\n\t *   platform: 'android',\n\t *   token,\n\t *   deviceName: DeviceInfo.getDeviceId(),\n\t *   appVersion: DeviceInfo.getVersion(),\n\t *   osVersion: DeviceInfo.getSystemVersion(),\n\t * })\n\t * ```\n\t */\n\tregisterDevice: (options: {\n\t\tplatform: 'ios' | 'android'\n\t\ttoken: string\n\t\tdeviceId?: string\n\t\tdeviceName?: string\n\t\tappVersion?: string\n\t\tosVersion?: string\n\t}) => Promise<{ success: boolean; tokenId: string }>\n\t/**\n\t * Unregister a mobile device\n\t *\n\t * Call this when the user logs out or disables notifications.\n\t */\n\tunregisterDevice: (token: string) => Promise<void>\n\t/** Refresh device list */\n\trefresh: () => Promise<void>\n}\n\n/**\n * Hook for mobile push notification management (iOS/Android)\n *\n * Use this hook in React Native apps to register device tokens and manage\n * push notification settings.\n *\n * @example\n * ```tsx\n * function PushNotificationSetup() {\n *   const { isConfigured, registerDevice, devices } = useMobilePush()\n *\n *   useEffect(() => {\n *     if (!isConfigured) return\n *\n *     // Get device token from native push service\n *     messaging().getToken().then(token => {\n *       registerDevice({\n *         platform: Platform.OS === 'ios' ? 'ios' : 'android',\n *         token,\n *       })\n *     })\n *\n *     // Listen for token refresh\n *     return messaging().onTokenRefresh(token => {\n *       registerDevice({\n *         platform: Platform.OS === 'ios' ? 'ios' : 'android',\n *         token,\n *       })\n *     })\n *   }, [isConfigured])\n *\n *   return (\n *     <View>\n *       <Text>Registered devices: {devices.length}</Text>\n *     </View>\n *   )\n * }\n * ```\n */\nexport function useMobilePush(): UseMobilePushReturn {\n\tconst ctx = usePlatformContext()\n\n\tconst config = ctx.mobilePushConfig\n\tconst prefs = ctx.mobilePushPreferences\n\n\t// Wrap refresh to return void (the data is already in context)\n\tconst refresh = useCallback(async (): Promise<void> => {\n\t\tawait ctx.getMobilePushPreferences()\n\t}, [ctx])\n\n\treturn {\n\t\tiosConfigured: config?.ios ?? false,\n\t\tandroidConfigured: config?.android ?? false,\n\t\tisConfigured: config?.anyConfigured ?? false,\n\t\tdevices: prefs?.devices ?? [],\n\t\tisEnabled: prefs?.enabled ?? false,\n\t\terror: ctx.mobilePushError,\n\t\tisError: ctx.mobilePushError !== null,\n\t\tregisterDevice: ctx.registerMobileDevice,\n\t\tunregisterDevice: ctx.unregisterMobileDevice,\n\t\trefresh,\n\t}\n}\n\n// ============================================\n// useReferral\n// ============================================\n\nexport interface UseReferralReturn {\n\t/** Referral statistics */\n\tstats: ReferralStats | null\n\t/** Whether referral data is loading */\n\tisLoading: boolean\n\t/** Error loading referral data */\n\terror: Error | null\n\t/** Whether there was an error */\n\tisError: boolean\n\t/** User's referral code */\n\tcode: string | null\n\t/** Referral link to share */\n\tlink: string | null\n\t/** Copy referral code to clipboard */\n\tcopyCode: () => Promise<void>\n\t/** Copy referral link to clipboard */\n\tcopyLink: () => Promise<void>\n\t/** Regenerate referral code */\n\tregenerateCode: () => Promise<string>\n\t/**\n\t * Redeem a referral code with optional inline defaults\n\t *\n\t * If the referral program rewards aren't configured in Console, the provided\n\t * defaults will be used. Console can override any values without deployment.\n\t *\n\t * @param code - Referral code to redeem\n\t * @param defaults - Optional inline defaults for reward configuration\n\t *\n\t * @example\n\t * ```tsx\n\t * const { redeemCode } = useReferral()\n\t *\n\t * const handleRedeem = async (code: string) => {\n\t *   const result = await redeemCode(code, {\n\t *     referrerReward: { type: 'premium_trial', days: 7 },\n\t *     refereeReward: { type: 'premium_trial', days: 7 },\n\t *   })\n\t *   if (result.success) {\n\t *     toast.success('Code redeemed!')\n\t *   }\n\t * }\n\t * ```\n\t */\n\tredeemCode: (code: string, defaults?: ReferralRewardDefaults) => Promise<RedeemResult>\n\t/**\n\t * Get leaderboard of top referrers\n\t *\n\t * @param options - Leaderboard options\n\t * @param options.limit - Maximum entries (1-100, default: 10)\n\t * @param options.period - Time period ('all', 'month', 'week')\n\t */\n\tgetLeaderboard: (options?: { limit?: number; period?: 'all' | 'month' | 'week' }) => Promise<{\n\t\tperiod: 'all' | 'month' | 'week'\n\t\tentries: Array<{\n\t\t\trank: number\n\t\t\tuserId: string | null\n\t\t\t/** Masked username for privacy */\n\t\t\tname: string\n\t\t\tavatarUrl: string | null\n\t\t\t/** Number of successful referrals */\n\t\t\treferrals: number\n\t\t\ttotalReferrals: number\n\t\t\tisCurrentUser: boolean\n\t\t}>\n\t\tcurrentUserRank: number | null\n\t}>\n}\n\n/**\n * Hook for referral program\n *\n * @example\n * ```tsx\n * function ReferralCard() {\n *   const { code, link, stats, copyLink } = useReferral()\n *\n *   return (\n *     <div>\n *       <p>Your code: {code}</p>\n *       <p>Successful referrals: {stats?.successfulReferrals || 0}</p>\n *       <button onClick={copyLink}>Share Link</button>\n *     </div>\n *   )\n * }\n * ```\n */\nexport function useReferral(): UseReferralReturn {\n\tconst ctx = usePlatformContext()\n\n\tconst code = ctx.referralCode || null\n\tconst link = code ? `${ctx.platformUrl}/r/${code}` : null\n\n\tconst copyCode = useCallback(async () => {\n\t\tif (code) {\n\t\t\tawait navigator.clipboard.writeText(code)\n\t\t}\n\t}, [code])\n\n\tconst copyLink = useCallback(async () => {\n\t\tif (link) {\n\t\t\tawait navigator.clipboard.writeText(link)\n\t\t}\n\t}, [link])\n\n\treturn {\n\t\tstats: ctx.referralStats,\n\t\tisLoading: ctx.referralLoading,\n\t\terror: ctx.referralError,\n\t\tisError: ctx.referralError !== null,\n\t\tcode,\n\t\tlink,\n\t\tcopyCode,\n\t\tcopyLink,\n\t\tregenerateCode: ctx.regenerateReferralCode,\n\t\tredeemCode: ctx.redeemReferralCode,\n\t\tgetLeaderboard: ctx.getReferralLeaderboard,\n\t}\n}\n\n// ============================================\n// useAnalyticsQuery\n// ============================================\n\nexport interface UseAnalyticsQueryOptions {\n\t/** The query parameters */\n\tquery: AnalyticsQuery\n\t/** Whether to skip initial fetch */\n\tskip?: boolean\n\t/** Refetch interval in ms */\n\trefetchInterval?: number\n}\n\nexport interface UseAnalyticsQueryReturn {\n\t/** Query results */\n\tdata: AnalyticsQueryResult | null\n\t/** Whether query is loading */\n\tisLoading: boolean\n\t/** Whether initial load is complete */\n\tisInitialized: boolean\n\t/** Error from query */\n\terror: Error | null\n\t/** Whether there was an error */\n\tisError: boolean\n\t/** Refetch the query */\n\trefetch: () => Promise<void>\n}\n\n/**\n * Hook for querying analytics data\n *\n * Uses React Query for automatic caching, deduplication, and background refetching.\n *\n * @example\n * ```tsx\n * function AnalyticsDashboard() {\n *   const { data, isLoading, refetch } = useAnalyticsQuery({\n *     query: {\n *       type: 'events',\n *       dateRange: { start: '2024-01-01', end: '2024-01-31' },\n *       groupBy: ['day'],\n *       metrics: ['count'],\n *     },\n *     refetchInterval: 60000, // Auto-refresh every minute\n *   })\n *\n *   if (isLoading) return <Spinner />\n *\n *   return (\n *     <div>\n *       <p>Rows: {data?.meta.rowCount}</p>\n *       <Chart data={data?.data} />\n *       <button onClick={refetch}>Refresh</button>\n *     </div>\n *   )\n * }\n * ```\n */\nexport function useAnalyticsQuery(options: UseAnalyticsQueryOptions): UseAnalyticsQueryReturn {\n\tconst ctx = usePlatformContext()\n\tconst queryClient = useQueryClient()\n\n\t// Stable query key from options\n\tconst queryKey = ['sylphx', ctx.appId, 'analytics', options.query] as const\n\n\t// React Query for analytics data\n\tconst analyticsQuery = useQuery({\n\t\tqueryKey,\n\t\tqueryFn: () => ctx.queryAnalytics(options.query),\n\t\tenabled: !options.skip,\n\t\tstaleTime: STALE_TIME_FREQUENT_MS, // 1 min - analytics data is often time-sensitive\n\t\trefetchInterval: options.refetchInterval ?? false,\n\t})\n\n\t// Refetch via React Query invalidation\n\tconst refetch = useCallback(async () => {\n\t\tawait queryClient.invalidateQueries({ queryKey })\n\t}, [queryClient, queryKey])\n\n\treturn {\n\t\tdata: analyticsQuery.data ?? null,\n\t\tisLoading: analyticsQuery.isLoading,\n\t\tisInitialized: analyticsQuery.isFetched,\n\t\terror: analyticsQuery.error as Error | null,\n\t\tisError: analyticsQuery.isError,\n\t\trefetch,\n\t}\n}\n\n// ============================================\n// useConversionTracking\n// ============================================\n\nexport interface UseConversionTrackingReturn {\n\t/**\n\t * Track a conversion event with automatic enrichment\n\t *\n\t * Automatically includes:\n\t * - Click IDs (gclid, fbclid, ttclid) from URL capture\n\t * - User data from auth state (email, name)\n\t *\n\t * Events are forwarded to all configured destinations with auto-forward enabled.\n\t */\n\ttrackConversion: (\n\t\tevent: string,\n\t\tdata: {\n\t\t\tvalue?: number\n\t\t\tcurrency?: string\n\t\t\torderId?: string\n\t\t\tproperties?: Record<string, unknown>\n\t\t},\n\t\toptions?: {\n\t\t\t/** Override auto-captured click ID */\n\t\t\tclickId?: string\n\t\t\t/** Override auto-captured user email */\n\t\t\tuserEmail?: string\n\t\t\t/** Override auto-captured user phone */\n\t\t\tuserPhone?: string\n\t\t\t/** Only forward to specific destinations (default: all with auto-forward enabled) */\n\t\t\tdestinations?: DestinationPlatform[]\n\t\t},\n\t) => Promise<void>\n\t/**\n\t * Auto-captured click IDs from URL parameters\n\t */\n\tclickIds: ClickIds\n\t/**\n\t * Get the primary click ID (gclid > fbclid > ttclid)\n\t */\n\tprimaryClickId: string | undefined\n}\n\n/**\n * Hook for conversion tracking with automatic click ID and user data enrichment\n *\n * This is a convenience hook that wraps useAnalytics.track() with\n * conversion-specific defaults and automatic data enrichment.\n *\n * @example Basic conversion tracking\n * ```tsx\n * function CheckoutSuccess({ order }) {\n *   const { trackConversion } = useConversionTracking()\n *\n *   useEffect(() => {\n *     // Click IDs and user data are automatically included\n *     trackConversion('purchase', {\n *       value: order.total,\n *       currency: 'USD',\n *       orderId: order.id,\n *     })\n *   }, [order])\n *\n *   return <div>Thank you for your purchase!</div>\n * }\n * ```\n *\n * @example With custom properties\n * ```tsx\n * function SignupComplete({ user }) {\n *   const { trackConversion } = useConversionTracking()\n *\n *   useEffect(() => {\n *     trackConversion('signup', {\n *       properties: {\n *         plan: 'free',\n *         source: 'landing_page',\n *       }\n *     })\n *   }, [])\n * }\n * ```\n *\n * @example Check for click IDs\n * ```tsx\n * function LandingPage() {\n *   const { clickIds, primaryClickId } = useConversionTracking()\n *\n *   // Show different content for ad traffic\n *   if (primaryClickId) {\n *     return <AdLandingPage />\n *   }\n *\n *   return <OrganicLandingPage />\n * }\n * ```\n */\nexport function useConversionTracking(): UseConversionTrackingReturn {\n\tconst ctx = usePlatformContext()\n\n\tconst trackConversion = useCallback(\n\t\tasync (\n\t\t\tevent: string,\n\t\t\tdata: {\n\t\t\t\tvalue?: number\n\t\t\t\tcurrency?: string\n\t\t\t\torderId?: string\n\t\t\t\tproperties?: Record<string, unknown>\n\t\t\t},\n\t\t\toptions?: {\n\t\t\t\tclickId?: string\n\t\t\t\tuserEmail?: string\n\t\t\t\tuserPhone?: string\n\t\t\t\tdestinations?: DestinationPlatform[]\n\t\t\t},\n\t\t) => {\n\t\t\t// Track with conversion data (auto-enriched by ctx.track)\n\t\t\tawait ctx.track(event, data.properties || {}, {\n\t\t\t\tdestinations: options?.destinations,\n\t\t\t\tconversion: {\n\t\t\t\t\tvalue: data.value,\n\t\t\t\t\tcurrency: data.currency,\n\t\t\t\t\torderId: data.orderId,\n\t\t\t\t\tclickId: options?.clickId,\n\t\t\t\t\tuserEmail: options?.userEmail,\n\t\t\t\t\tuserPhone: options?.userPhone,\n\t\t\t\t},\n\t\t\t})\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst primaryClickId = ctx.clickIds.gclid || ctx.clickIds.fbclid || ctx.clickIds.ttclid\n\n\treturn {\n\t\ttrackConversion,\n\t\tclickIds: ctx.clickIds,\n\t\tprimaryClickId,\n\t}\n}\n\n// ============================================\n// useInbox (In-App Messages / Notification Center)\n// ============================================\n\nexport interface UseInboxReturn {\n\t/** List of in-app messages */\n\tmessages: InAppMessage[]\n\t/** Number of unread messages */\n\tunreadCount: number\n\t/** Whether inbox is loading */\n\tisLoading: boolean\n\t/** Error loading inbox */\n\terror: Error | null\n\t/** Whether there was an error */\n\tisError: boolean\n\t/** User preferences for inbox */\n\tpreferences: InboxPreferences | null\n\t/** Mark a specific message as read */\n\tmarkAsRead: (messageId: string) => Promise<void>\n\t/** Mark all messages as read */\n\tmarkAllAsRead: () => Promise<void>\n\t/** Dismiss a message (user closed it) */\n\tdismiss: (messageId: string) => Promise<void>\n\t/** Record that user clicked an action button */\n\trecordClick: (messageId: string, action: 'primary' | 'secondary') => Promise<void>\n\t/** Update inbox preferences */\n\tupdatePreferences: (prefs: Partial<InboxPreferences>) => Promise<void>\n\t/** Refresh the inbox data */\n\trefresh: () => Promise<void>\n\t/** Get messages filtered by topic */\n\tgetByTopic: (topic: string) => InAppMessage[]\n\t/** Get messages filtered by type */\n\tgetByType: (type: InAppMessageType) => InAppMessage[]\n\t/** Get unread messages only */\n\tunreadMessages: InAppMessage[]\n}\n\n/**\n * Hook for in-app messages / notification center\n *\n * @example Basic usage\n * ```tsx\n * function NotificationBell() {\n *   const { unreadCount, messages, markAsRead } = useInbox()\n *\n *   return (\n *     <div>\n *       <Bell />\n *       {unreadCount > 0 && <Badge>{unreadCount}</Badge>}\n *       <Dropdown>\n *         {messages.map(msg => (\n *           <NotificationItem\n *             key={msg.id}\n *             message={msg}\n *             onClick={() => markAsRead(msg.id)}\n *           />\n *         ))}\n *       </Dropdown>\n *     </div>\n *   )\n * }\n * ```\n *\n * @example With action buttons\n * ```tsx\n * function NotificationCard({ message }: { message: InAppMessage }) {\n *   const { recordClick, dismiss } = useInbox()\n *\n *   const handleAction = async () => {\n *     await recordClick(message.id, 'primary')\n *     if (message.actionUrl) {\n *       window.open(message.actionUrl, '_blank')\n *     }\n *   }\n *\n *   return (\n *     <Card>\n *       <h3>{message.title}</h3>\n *       <p>{message.body}</p>\n *       {message.actionText && (\n *         <Button onClick={handleAction}>{message.actionText}</Button>\n *       )}\n *       <CloseButton onClick={() => dismiss(message.id)} />\n *     </Card>\n *   )\n * }\n * ```\n *\n * @example Filtering by topic\n * ```tsx\n * function SystemAlerts() {\n *   const { getByType } = useInbox()\n *   const alerts = getByType('warning').concat(getByType('error'))\n *\n *   return (\n *     <AlertBanner>\n *       {alerts.map(alert => (\n *         <Alert key={alert.id} severity={alert.type}>\n *           {alert.title}\n *         </Alert>\n *       ))}\n *     </AlertBanner>\n *   )\n * }\n * ```\n */\nexport function useInbox(): UseInboxReturn {\n\tconst ctx = usePlatformContext()\n\n\tconst getByTopic = useCallback(\n\t\t(topic: string): InAppMessage[] => {\n\t\t\treturn ctx.inboxMessages.filter((m) => m.topic === topic)\n\t\t},\n\t\t[ctx.inboxMessages],\n\t)\n\n\tconst getByType = useCallback(\n\t\t(type: InAppMessageType): InAppMessage[] => {\n\t\t\treturn ctx.inboxMessages.filter((m) => m.type === type)\n\t\t},\n\t\t[ctx.inboxMessages],\n\t)\n\n\tconst unreadMessages = ctx.inboxMessages.filter((m) => !m.isRead && !m.isDismissed)\n\n\treturn {\n\t\tmessages: ctx.inboxMessages,\n\t\tunreadCount: ctx.inboxUnreadCount,\n\t\tisLoading: ctx.inboxLoading,\n\t\terror: ctx.inboxError,\n\t\tisError: ctx.inboxError !== null,\n\t\tpreferences: ctx.inboxPreferences,\n\t\tmarkAsRead: ctx.markInboxMessageAsRead,\n\t\tmarkAllAsRead: ctx.markAllInboxMessagesAsRead,\n\t\tdismiss: ctx.dismissInboxMessage,\n\t\trecordClick: ctx.recordInboxMessageClick,\n\t\tupdatePreferences: ctx.updateInboxPreferences,\n\t\trefresh: ctx.refreshInbox,\n\t\tgetByTopic,\n\t\tgetByType,\n\t\tunreadMessages,\n\t}\n}\n","/**\n * CheckoutButton Component\n *\n * Simple button to initiate checkout for a specific plan.\n */\n\n'use client'\n\nimport { useCallback, useEffect, useState } from 'react'\nimport { RequireSdk } from '../hooks'\nimport { useBilling } from '../platform-hooks'\nimport {\n\tbaseStyles,\n\tdefaultTheme,\n\tinjectGlobalStyles,\n\tmergeStyles,\n\ttype ThemeVariables,\n} from '../ui/styles'\n\nexport interface CheckoutButtonProps {\n\t/** Plan slug to checkout */\n\tplanSlug: string\n\t/** Billing interval */\n\tinterval?: 'monthly' | 'annual' | 'lifetime'\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Button variant */\n\tvariant?: 'primary' | 'secondary' | 'outline' | 'ghost'\n\t/** Button size */\n\tsize?: 'sm' | 'md' | 'lg'\n\t/** Custom button text */\n\tchildren?: React.ReactNode\n\t/** Called before checkout starts */\n\tonCheckoutStart?: () => void\n\t/** Called on error */\n\tonError?: (error: string) => void\n\t/** Disabled state */\n\tdisabled?: boolean\n\t/** Full width */\n\tfullWidth?: boolean\n\t/** Custom class name */\n\tclassName?: string\n}\n\n/**\n * CheckoutButton for quick plan checkout\n *\n * @example\n * ```tsx\n * <CheckoutButton planSlug=\"pro\" interval=\"annual\">\n *   Upgrade to Pro\n * </CheckoutButton>\n * ```\n */\nexport function CheckoutButton(props: CheckoutButtonProps) {\n\treturn (\n\t\t<RequireSdk services={['billing']} componentType=\"billing\" theme={props.theme}>\n\t\t\t<CheckoutButtonInner {...props} />\n\t\t</RequireSdk>\n\t)\n}\n\n/** Inner component that safely uses platform hooks */\nfunction CheckoutButtonInner({\n\tplanSlug,\n\tinterval = 'monthly',\n\ttheme = defaultTheme,\n\tvariant = 'primary',\n\tsize = 'md',\n\tchildren,\n\tonCheckoutStart,\n\tonError,\n\tdisabled = false,\n\tfullWidth = false,\n\tclassName,\n}: CheckoutButtonProps) {\n\tconst { plans, createCheckout, isPremium, subscription } = useBilling()\n\tconst styles = baseStyles(theme)\n\n\tconst [isLoading, setIsLoading] = useState(false)\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tconst handleClick = useCallback(async () => {\n\t\tsetIsLoading(true)\n\t\tonCheckoutStart?.()\n\n\t\ttry {\n\t\t\tconst checkoutUrl = await createCheckout(planSlug, interval)\n\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\twindow.location.href = checkoutUrl\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to start checkout'\n\t\t\tonError?.(message)\n\t\t} finally {\n\t\t\tsetIsLoading(false)\n\t\t}\n\t}, [planSlug, interval, createCheckout, onCheckoutStart, onError])\n\n\t// Check if user is already on this plan\n\tconst isCurrentPlan = subscription?.planSlug === planSlug\n\n\t// Get plan info for default text\n\tconst plan = plans.find((p) => p.slug === planSlug)\n\n\t// Get size styles\n\tconst sizeStyles: Record<string, React.CSSProperties> = {\n\t\tsm: { padding: '0.375rem 0.75rem', fontSize: theme.fontSizeXs },\n\t\tmd: { padding: '0.5rem 1rem', fontSize: theme.fontSizeSm },\n\t\tlg: { padding: '0.75rem 1.5rem', fontSize: theme.fontSizeBase },\n\t}\n\n\t// Get variant styles\n\tconst variantStyleMap: Record<string, React.CSSProperties> = {\n\t\tprimary: styles.buttonPrimary,\n\t\tsecondary: styles.buttonSecondary,\n\t\toutline: styles.buttonOutline,\n\t\tghost: styles.buttonGhost,\n\t}\n\n\tconst buttonStyles = mergeStyles(\n\t\tstyles.button,\n\t\tvariantStyleMap[variant],\n\t\tsizeStyles[size],\n\t\tfullWidth ? styles.buttonFullWidth : {},\n\t\tisLoading || disabled || isCurrentPlan ? styles.buttonDisabled : {},\n\t)\n\n\tconst defaultText = isCurrentPlan\n\t\t? 'Current Plan'\n\t\t: isPremium\n\t\t\t? `Switch to ${plan?.name || planSlug}`\n\t\t\t: `Get ${plan?.name || planSlug}`\n\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tonClick={handleClick}\n\t\t\tdisabled={isLoading || disabled || isCurrentPlan}\n\t\t\tclassName={className}\n\t\t\tstyle={buttonStyles}\n\t\t>\n\t\t\t{isLoading ? (\n\t\t\t\t<>\n\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\tProcessing...\n\t\t\t\t</>\n\t\t\t) : isCurrentPlan ? (\n\t\t\t\t<>\n\t\t\t\t\t<CheckIcon size={16} />\n\t\t\t\t\t{children || 'Current Plan'}\n\t\t\t\t</>\n\t\t\t) : (\n\t\t\t\tchildren || defaultText\n\t\t\t)}\n\t\t</button>\n\t)\n}\n\nfunction CheckIcon({ size = 24 }: { size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tstyle={{ flexShrink: 0 }}\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M20 6 9 17l-5-5\" />\n\t\t</svg>\n\t)\n}\n","/**\n * ForgotPassword Component\n *\n * Allows users to request a password reset email.\n * Matches Clerk's ForgotPassword component API.\n */\n\n'use client'\n\nimport { type FormEvent, useCallback, useEffect, useId, useState } from 'react'\nimport { UI_COPY_FEEDBACK_MS } from '../../constants'\nimport { useSafeAuth, useSafeUser, useSdkReady } from '../hooks'\nimport { safeRedirect } from '../security-utils'\nimport { Modal } from '../ui/modal'\nimport {\n\tbaseStyles,\n\tdefaultTheme,\n\tinjectGlobalStyles,\n\tmergeStyles,\n\ttype ThemeVariables,\n} from '../ui/styles'\n\nexport interface ForgotPasswordProps {\n\t/** URL to redirect after password reset email is sent */\n\tafterSubmitUrl?: string\n\t/** URL for sign in link */\n\tsignInUrl?: string\n\t/** Display mode */\n\tmode?: 'redirect' | 'embedded' | 'modal'\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Custom class name */\n\tclassName?: string\n\t/** Button content (for redirect/modal mode) */\n\tchildren?: React.ReactNode\n\t/** Called on successful submission */\n\tonSuccess?: () => void\n\t/** Called on error */\n\tonError?: (error: string) => void\n\t/** Show card wrapper (embedded mode) */\n\tshowCard?: boolean\n\t/** Custom header content */\n\theader?: React.ReactNode\n}\n\n/**\n * ForgotPassword component for requesting password reset emails\n *\n * @example\n * ```tsx\n * // Embedded mode\n * <ForgotPassword mode=\"embedded\" afterSubmitUrl=\"/check-email\" />\n *\n * // Modal mode\n * <ForgotPassword mode=\"modal\">\n *   Forgot password?\n * </ForgotPassword>\n * ```\n */\nexport function ForgotPassword({\n\tafterSubmitUrl = '/check-email',\n\tsignInUrl = '/sign-in',\n\tmode = 'embedded',\n\ttheme = defaultTheme,\n\tclassName,\n\tchildren,\n\tonSuccess,\n\tonError,\n\tshowCard = true,\n\theader,\n}: ForgotPasswordProps) {\n\t// SDK readiness check (SSOT for SSR safety and configuration)\n\tconst { isReady, renderError } = useSdkReady({\n\t\tservices: ['auth', 'user'],\n\t\tcomponentType: 'auth',\n\t\ttheme,\n\t})\n\n\tconst { forgotPassword } = useSafeAuth()\n\tconst { isSignedIn, isLoaded } = useSafeUser()\n\tconst styles = baseStyles(theme)\n\tconst emailId = useId()\n\n\tconst [modalOpen, setModalOpen] = useState(false)\n\tconst [email, setEmail] = useState('')\n\tconst [error, setError] = useState<string | null>(null)\n\tconst [isLoading, setIsLoading] = useState(false)\n\tconst [isSubmitted, setIsSubmitted] = useState(false)\n\tconst [focusedField, setFocusedField] = useState<string | null>(null)\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tconst handleSubmit = useCallback(\n\t\tasync (e: FormEvent) => {\n\t\t\te.preventDefault()\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tif (!forgotPassword) {\n\t\t\t\t\tthrow new Error('Authentication not configured')\n\t\t\t\t}\n\t\t\t\tawait forgotPassword({ email })\n\t\t\t\tsetIsSubmitted(true)\n\t\t\t\tonSuccess?.()\n\n\t\t\t\t// Redirect after short delay\n\t\t\t\tif (afterSubmitUrl && typeof window !== 'undefined') {\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tsafeRedirect(afterSubmitUrl, { fallback: '/sign-in' })\n\t\t\t\t\t}, UI_COPY_FEEDBACK_MS)\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : 'Failed to send reset email'\n\t\t\t\tsetError(message)\n\t\t\t\tonError?.(message)\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[email, forgotPassword, afterSubmitUrl, onSuccess, onError],\n\t)\n\n\t// SDK not ready - render error or null\n\tif (!isReady) {\n\t\treturn renderError()\n\t}\n\n\t// Don't show if already signed in\n\tif (isLoaded && isSignedIn) {\n\t\treturn null\n\t}\n\n\tconst renderForm = () => {\n\t\tif (isSubmitted) {\n\t\t\treturn (\n\t\t\t\t<div style={styles.textCenter}>\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={mergeStyles(styles.flexCenter, {\n\t\t\t\t\t\t\twidth: '3rem',\n\t\t\t\t\t\t\theight: '3rem',\n\t\t\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\t\t\tbackgroundColor: `${theme.colorSuccess}15`,\n\t\t\t\t\t\t\tmargin: '0 auto 1rem',\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t<MailIcon color={theme.colorSuccess} />\n\t\t\t\t\t</div>\n\t\t\t\t\t<h3 style={mergeStyles(styles.cardTitle, styles.mb2)}>Check your email</h3>\n\t\t\t\t\t<p style={mergeStyles(styles.textMuted, styles.textSm, styles.mb4)}>\n\t\t\t\t\t\tWe sent a password reset link to <strong>{email}</strong>\n\t\t\t\t\t</p>\n\t\t\t\t\t<p style={mergeStyles(styles.textXs, styles.textMuted)}>\n\t\t\t\t\t\tDidn't receive it? Check spam or{' '}\n\t\t\t\t\t\t<button type=\"button\" onClick={() => setIsSubmitted(false)} style={styles.link}>\n\t\t\t\t\t\t\ttry again\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t)\n\t\t}\n\n\t\treturn (\n\t\t\t<form onSubmit={handleSubmit}>\n\t\t\t\t<div style={styles.formGroup}>\n\t\t\t\t\t<label htmlFor={emailId} style={styles.label}>\n\t\t\t\t\t\tEmail address\n\t\t\t\t\t</label>\n\t\t\t\t\t<input\n\t\t\t\t\t\tid={emailId}\n\t\t\t\t\t\ttype=\"email\"\n\t\t\t\t\t\tvalue={email}\n\t\t\t\t\t\tonChange={(e) => {\n\t\t\t\t\t\t\tsetEmail(e.target.value)\n\t\t\t\t\t\t\tsetError(null)\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonFocus={() => setFocusedField('email')}\n\t\t\t\t\t\tonBlur={() => setFocusedField(null)}\n\t\t\t\t\t\tplaceholder=\"you@example.com\"\n\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\tautoComplete=\"email\"\n\t\t\t\t\t\trequired\n\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\tstyles.input,\n\t\t\t\t\t\t\tfocusedField === 'email' ? styles.inputFocus : {},\n\t\t\t\t\t\t\tisLoading ? styles.inputDisabled : {},\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\n\t\t\t\t{error && <div style={mergeStyles(styles.alert, styles.alertError)}>{error}</div>}\n\n\t\t\t\t<button\n\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\tstyles.buttonPrimary,\n\t\t\t\t\t\tstyles.buttonFullWidth,\n\t\t\t\t\t\tisLoading ? styles.buttonDisabled : {},\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t{isLoading ? (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t\t\tSending...\n\t\t\t\t\t\t</>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t'Send reset link'\n\t\t\t\t\t)}\n\t\t\t\t</button>\n\n\t\t\t\t<p style={mergeStyles(styles.textCenter, styles.textSm, styles.textMuted, styles.mt4)}>\n\t\t\t\t\tRemember your password?{' '}\n\t\t\t\t\t<a href={signInUrl} style={styles.link}>\n\t\t\t\t\t\tSign in\n\t\t\t\t\t</a>\n\t\t\t\t</p>\n\t\t\t</form>\n\t\t)\n\t}\n\n\tconst content = (\n\t\t<div style={styles.container}>\n\t\t\t{header || (\n\t\t\t\t<div style={mergeStyles(styles.cardHeader, styles.textCenter)}>\n\t\t\t\t\t<h2 style={styles.cardTitle}>Forgot password?</h2>\n\t\t\t\t\t<p style={styles.cardDescription}>Enter your email and we'll send you a reset link</p>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<div style={styles.cardContent}>{renderForm()}</div>\n\t\t</div>\n\t)\n\n\t// Embedded mode\n\tif (mode === 'embedded') {\n\t\tif (showCard) {\n\t\t\treturn <div style={styles.card}>{content}</div>\n\t\t}\n\t\treturn content\n\t}\n\n\t// Modal mode\n\tif (mode === 'modal') {\n\t\tconst defaultStyles: React.CSSProperties = {\n\t\t\tbackground: 'none',\n\t\t\tborder: 'none',\n\t\t\tpadding: 0,\n\t\t\tcursor: 'pointer',\n\t\t\tcolor: theme.colorPrimary,\n\t\t\tfontSize: theme.fontSizeSm,\n\t\t\ttextDecoration: 'underline',\n\t\t}\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<button\n\t\t\t\t\tonClick={() => setModalOpen(true)}\n\t\t\t\t\tclassName={className}\n\t\t\t\t\tstyle={className ? undefined : defaultStyles}\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t>\n\t\t\t\t\t{children || 'Forgot password?'}\n\t\t\t\t</button>\n\t\t\t\t<Modal open={modalOpen} onClose={() => setModalOpen(false)} theme={theme}>\n\t\t\t\t\t{content}\n\t\t\t\t</Modal>\n\t\t\t</>\n\t\t)\n\t}\n\n\treturn null\n}\n\nfunction MailIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"24\"\n\t\t\theight=\"24\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\" />\n\t\t\t<path d=\"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\" />\n\t\t</svg>\n\t)\n}\n","/**\n * Security Utilities\n *\n * Safe redirect and URL validation functions to prevent XSS attacks.\n */\n\n/**\n * Dangerous URL protocols that should never be allowed in redirects.\n */\nconst DANGEROUS_PROTOCOLS = ['javascript:', 'data:', 'vbscript:', 'file:']\n\n/**\n * Regex to detect control characters and other dangerous chars.\n * Matches: ASCII 0-31 (control chars), DEL (127), and null byte.\n * These can be used to bypass protocol checks (e.g., \"jav\\x00ascript:\").\n */\n// biome-ignore lint/suspicious/noControlCharactersInRegex: security check intentionally matches control characters\nconst CONTROL_CHAR_REGEX = /[\\x00-\\x1f\\x7f]/\n\n/**\n * Check if a URL contains dangerous control characters.\n * These must be rejected before any other validation to prevent bypass attacks.\n *\n * @param url - URL to check\n * @returns true if URL contains control characters (unsafe)\n */\nfunction hasControlCharacters(url: string): boolean {\n\treturn CONTROL_CHAR_REGEX.test(url)\n}\n\n/**\n * Validate that a URL is safe for redirect.\n *\n * Checks:\n * 1. No dangerous protocols (javascript:, data:, vbscript:, file:)\n * 2. URL is parseable\n * 3. Either same-origin OR in allowed origins list\n *\n * @param url - URL to validate\n * @param options - Validation options\n * @returns true if URL is safe for redirect\n */\nexport function isValidRedirectUrl(\n\turl: string,\n\toptions: {\n\t\t/** Current origin (default: window.location.origin) */\n\t\torigin?: string\n\t\t/** Additional allowed origins (for OAuth etc) */\n\t\tallowedOrigins?: string[]\n\t\t/** Allow relative URLs (default: true) */\n\t\tallowRelative?: boolean\n\t} = {},\n): boolean {\n\tconst {\n\t\torigin = typeof window !== 'undefined' && window.location != null ? window.location.origin : '',\n\t\tallowedOrigins = [],\n\t\tallowRelative = true,\n\t} = options\n\n\t// Empty or whitespace-only URLs are invalid\n\tif (!url || !url.trim()) {\n\t\treturn false\n\t}\n\n\tconst trimmedUrl = url.trim()\n\n\t// CRITICAL: Reject control characters first to prevent bypass attacks\n\t// e.g., \"jav\\x00ascript:\" could bypass protocol checks\n\tif (hasControlCharacters(trimmedUrl)) {\n\t\treturn false\n\t}\n\n\t// Check for dangerous protocols (case-insensitive)\n\tconst lowerUrl = trimmedUrl.toLowerCase()\n\tfor (const protocol of DANGEROUS_PROTOCOLS) {\n\t\tif (lowerUrl.startsWith(protocol)) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\t// Relative URLs starting with / are safe\n\tif (allowRelative && trimmedUrl.startsWith('/') && !trimmedUrl.startsWith('//')) {\n\t\treturn true\n\t}\n\n\t// Try to parse as URL\n\ttry {\n\t\tconst parsed = new URL(trimmedUrl, origin)\n\n\t\t// Only allow http and https protocols\n\t\tif (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n\t\t\treturn false\n\t\t}\n\n\t\t// Same-origin is always allowed\n\t\tif (parsed.origin === origin) {\n\t\t\treturn true\n\t\t}\n\n\t\t// Check against allowed origins\n\t\tif (allowedOrigins.includes(parsed.origin)) {\n\t\t\treturn true\n\t\t}\n\n\t\t// External URLs not in allowlist are rejected\n\t\treturn false\n\t} catch {\n\t\t// URL parsing failed - reject\n\t\treturn false\n\t}\n}\n\n/**\n * Safely redirect to a URL, with fallback if URL is invalid.\n *\n * @param url - URL to redirect to\n * @param options - Redirect options\n */\nexport function safeRedirect(\n\turl: string,\n\toptions: {\n\t\t/** Fallback URL if the provided URL is invalid (default: '/') */\n\t\tfallback?: string\n\t\t/** Current origin for validation */\n\t\torigin?: string\n\t\t/** Additional allowed origins */\n\t\tallowedOrigins?: string[]\n\t\t/** Allow relative URLs (default: true) */\n\t\tallowRelative?: boolean\n\t} = {},\n): void {\n\tconst { fallback = '/', ...validationOptions } = options\n\n\t// Skip redirect if not in browser\n\tif (typeof window === 'undefined') {\n\t\treturn\n\t}\n\n\t// Validate URL\n\tif (isValidRedirectUrl(url, validationOptions)) {\n\t\twindow.location.href = url\n\t} else {\n\t\t// Log warning in development\n\t\tif (process.env.NODE_ENV === 'development') {\n\t\t\tconsole.warn(`[Sylphx] Blocked potentially unsafe redirect to: ${url}`)\n\t\t}\n\t\t// Use fallback\n\t\twindow.location.href = fallback\n\t}\n}\n\n/**\n * Sanitize a URL for safe use in the UI.\n *\n * Returns the original URL if safe, or null if dangerous.\n *\n * @param url - URL to sanitize\n * @returns Sanitized URL or null if unsafe\n */\nexport function sanitizeUrl(url: string): string | null {\n\tif (!url || !url.trim()) {\n\t\treturn null\n\t}\n\n\tconst trimmedUrl = url.trim()\n\n\t// CRITICAL: Reject control characters first to prevent bypass attacks\n\tif (hasControlCharacters(trimmedUrl)) {\n\t\treturn null\n\t}\n\n\tconst lowerUrl = trimmedUrl.toLowerCase()\n\n\t// Block dangerous protocols\n\tfor (const protocol of DANGEROUS_PROTOCOLS) {\n\t\tif (lowerUrl.startsWith(protocol)) {\n\t\t\treturn null\n\t\t}\n\t}\n\n\t// Try to parse and normalize\n\ttry {\n\t\t// For relative URLs, just validate they don't have dangerous content\n\t\tif (trimmedUrl.startsWith('/') && !trimmedUrl.startsWith('//')) {\n\t\t\treturn trimmedUrl\n\t\t}\n\n\t\tconst parsed = new URL(trimmedUrl)\n\n\t\t// Only allow http and https\n\t\tif (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n\t\t\treturn null\n\t\t}\n\n\t\treturn parsed.href\n\t} catch {\n\t\t// If it looks like a relative URL without /, treat carefully\n\t\tif (!trimmedUrl.includes(':')) {\n\t\t\treturn `/${trimmedUrl}`\n\t\t}\n\t\treturn null\n\t}\n}\n","/**\n * Modal Component\n *\n * Overlay modal for SignIn/SignUp in modal mode.\n * Self-contained with portal rendering.\n */\n\nimport { type ReactNode, useEffect, useRef } from 'react'\nimport { createPortal } from 'react-dom'\nimport { Z_INDEX_OVERLAY } from '../../constants'\nimport type { ThemeVariables } from './styles'\nimport { defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\nexport interface ModalProps {\n\t/** Whether the modal is open */\n\topen: boolean\n\t/** Called when the modal should close */\n\tonClose: () => void\n\t/** Modal content */\n\tchildren: ReactNode\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Custom class name for the modal container */\n\tclassName?: string\n\t/** Whether to close on backdrop click (default: true) */\n\tcloseOnBackdropClick?: boolean\n\t/** Whether to close on Escape key (default: true) */\n\tcloseOnEscape?: boolean\n}\n\n/**\n * Modal component with backdrop and portal rendering\n */\nexport function Modal({\n\topen,\n\tonClose,\n\tchildren,\n\ttheme = defaultTheme,\n\tclassName,\n\tcloseOnBackdropClick = true,\n\tcloseOnEscape = true,\n}: ModalProps) {\n\tconst modalRef = useRef<HTMLDivElement>(null)\n\n\t// Inject global styles (keyframes)\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// Handle escape key\n\tuseEffect(() => {\n\t\tif (!open || !closeOnEscape) return\n\n\t\tfunction handleKeyDown(e: KeyboardEvent) {\n\t\t\tif (e.key === 'Escape') {\n\t\t\t\tonClose()\n\t\t\t}\n\t\t}\n\n\t\tdocument.addEventListener('keydown', handleKeyDown)\n\t\treturn () => document.removeEventListener('keydown', handleKeyDown)\n\t}, [open, onClose, closeOnEscape])\n\n\t// Lock body scroll when open\n\tuseEffect(() => {\n\t\tif (!open) return\n\n\t\tconst originalOverflow = document.body.style.overflow\n\t\tdocument.body.style.overflow = 'hidden'\n\n\t\treturn () => {\n\t\t\tdocument.body.style.overflow = originalOverflow\n\t\t}\n\t}, [open])\n\n\t// Focus trap with cycling and focus restoration\n\tuseEffect(() => {\n\t\tif (!open || !modalRef.current) return\n\n\t\t// Store previously focused element for restoration\n\t\tconst previousActiveElement = document.activeElement as HTMLElement | null\n\n\t\tconst focusableSelector =\n\t\t\t'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n\t\tconst focusableElements = modalRef.current.querySelectorAll<HTMLElement>(focusableSelector)\n\n\t\tif (focusableElements.length === 0) return\n\n\t\tconst firstElement = focusableElements[0]\n\t\tconst lastElement = focusableElements[focusableElements.length - 1]\n\n\t\t// Focus first element\n\t\tfirstElement.focus()\n\n\t\t// Handle Tab key for focus cycling\n\t\tfunction handleKeyDown(e: KeyboardEvent) {\n\t\t\tif (e.key !== 'Tab') return\n\n\t\t\t// Shift+Tab on first element -> focus last element\n\t\t\tif (e.shiftKey && document.activeElement === firstElement) {\n\t\t\t\te.preventDefault()\n\t\t\t\tlastElement.focus()\n\t\t\t}\n\t\t\t// Tab on last element -> focus first element\n\t\t\telse if (!e.shiftKey && document.activeElement === lastElement) {\n\t\t\t\te.preventDefault()\n\t\t\t\tfirstElement.focus()\n\t\t\t}\n\t\t}\n\n\t\tdocument.addEventListener('keydown', handleKeyDown)\n\n\t\treturn () => {\n\t\t\tdocument.removeEventListener('keydown', handleKeyDown)\n\t\t\t// Restore focus when modal closes\n\t\t\tpreviousActiveElement?.focus()\n\t\t}\n\t}, [open])\n\n\tif (!open) return null\n\n\t// Don't render on server\n\tif (typeof document === 'undefined') return null\n\n\tconst handleBackdropClick = (e: React.MouseEvent) => {\n\t\tif (closeOnBackdropClick && e.target === e.currentTarget) {\n\t\t\tonClose()\n\t\t}\n\t}\n\n\tconst backdropStyle: React.CSSProperties = {\n\t\tposition: 'fixed',\n\t\tinset: 0,\n\t\tzIndex: Z_INDEX_OVERLAY,\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'center',\n\t\tbackgroundColor: 'rgba(0, 0, 0, 0.5)',\n\t\tbackdropFilter: 'blur(4px)',\n\t\tanimation: 'sylphx-fade-in 0.15s ease-out',\n\t}\n\n\tconst contentStyle: React.CSSProperties = {\n\t\tposition: 'relative',\n\t\tmaxWidth: '28rem',\n\t\twidth: '100%',\n\t\tmaxHeight: '90vh',\n\t\toverflow: 'auto',\n\t\tmargin: '1rem',\n\t\tbackgroundColor: theme.colorBackground,\n\t\tborderRadius: theme.borderRadiusLg,\n\t\tboxShadow: '0 25px 50px -12px rgb(0 0 0 / 0.25)',\n\t\tanimation: 'sylphx-scale-in 0.2s ease-out',\n\t}\n\n\tconst closeButtonStyle: React.CSSProperties = {\n\t\tposition: 'absolute',\n\t\ttop: '0.75rem',\n\t\tright: '0.75rem',\n\t\twidth: '2rem',\n\t\theight: '2rem',\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'center',\n\t\tbackgroundColor: 'transparent',\n\t\tborder: 'none',\n\t\tborderRadius: theme.borderRadiusSm,\n\t\tcolor: theme.colorMutedForeground,\n\t\tcursor: 'pointer',\n\t\ttransition: 'color 0.15s ease-in-out, background-color 0.15s ease-in-out',\n\t}\n\n\tconst modal = (\n\t\t<div\n\t\t\tstyle={backdropStyle}\n\t\t\tonClick={handleBackdropClick}\n\t\t\tonKeyDown={(e) => {\n\t\t\t\tif (closeOnEscape && e.key === 'Escape') onClose()\n\t\t\t}}\n\t\t\trole=\"dialog\"\n\t\t\taria-modal=\"true\"\n\t\t>\n\t\t\t<div ref={modalRef} style={mergeStyles(contentStyle)} className={className}>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={onClose}\n\t\t\t\t\tstyle={closeButtonStyle}\n\t\t\t\t\taria-label=\"Close\"\n\t\t\t\t\tonMouseEnter={(e) => {\n\t\t\t\t\t\te.currentTarget.style.backgroundColor = theme.colorMuted\n\t\t\t\t\t\te.currentTarget.style.color = theme.colorForeground\n\t\t\t\t\t}}\n\t\t\t\t\tonMouseLeave={(e) => {\n\t\t\t\t\t\te.currentTarget.style.backgroundColor = 'transparent'\n\t\t\t\t\t\te.currentTarget.style.color = theme.colorMutedForeground\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<CloseIcon />\n\t\t\t\t</button>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t</div>\n\t)\n\n\treturn createPortal(modal, document.body)\n}\n\n/**\n * Close icon SVG\n */\nfunction CloseIcon() {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 16 16\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M4 4L12 12M12 4L4 12\" />\n\t\t</svg>\n\t)\n}\n\n/**\n * Hook to manage modal state\n */\nexport function useModal(initialOpen = false) {\n\tconst [open, setOpen] = useState(initialOpen)\n\n\tconst openModal = useCallback(() => setOpen(true), [])\n\tconst closeModal = useCallback(() => setOpen(false), [])\n\tconst toggleModal = useCallback(() => setOpen((prev) => !prev), [])\n\n\treturn {\n\t\topen,\n\t\topenModal,\n\t\tcloseModal,\n\t\ttoggleModal,\n\t\tsetOpen,\n\t}\n}\n\n// Import React hooks for useModal\nimport { useCallback, useState } from 'react'\n","/**\n * InviteMember Component\n *\n * Modal/form for inviting new members to an organization.\n */\n\n'use client'\n\nimport { type FormEvent, useCallback, useEffect, useId, useState } from 'react'\nimport { UI_SUCCESS_REDIRECT_MS } from '../../constants'\nimport { type OrgRole, RequireSdk, useOrganization } from '../hooks'\nimport {\n\tbaseStyles,\n\tdefaultTheme,\n\tinjectGlobalStyles,\n\tmergeStyles,\n\ttype ThemeVariables,\n} from '../ui/styles'\n\nexport interface InviteMemberProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Called when invite is successful */\n\tonSuccess?: (email: string, role: OrgRole) => void\n\t/** Called on error */\n\tonError?: (error: string) => void\n\t/** Called when modal is closed */\n\tonClose?: () => void\n\t/** Show as modal */\n\tasModal?: boolean\n\t/** Default role for new invites */\n\tdefaultRole?: OrgRole\n\t/** Custom class name */\n\tclassName?: string\n\t/** Show role descriptions */\n\tshowRoleDescriptions?: boolean\n}\n\nconst ROLE_OPTIONS: { value: OrgRole; label: string; description: string }[] = [\n\t{\n\t\tvalue: 'viewer',\n\t\tlabel: 'Viewer',\n\t\tdescription: 'Read-only access to analytics',\n\t},\n\t{\n\t\tvalue: 'developer',\n\t\tlabel: 'Developer',\n\t\tdescription: 'Manage apps and deployments',\n\t},\n\t{\n\t\tvalue: 'analytics',\n\t\tlabel: 'Analytics',\n\t\tdescription: 'View analytics and reports',\n\t},\n\t{\n\t\tvalue: 'billing',\n\t\tlabel: 'Billing',\n\t\tdescription: 'Access billing and payments',\n\t},\n\t{\n\t\tvalue: 'admin',\n\t\tlabel: 'Admin',\n\t\tdescription: 'Manage members, apps, and analytics',\n\t},\n\t{\n\t\tvalue: 'super_admin',\n\t\tlabel: 'Super Admin',\n\t\tdescription: 'Full access to everything',\n\t},\n]\n\n/**\n * InviteMember component for inviting users to an organization\n *\n * @example\n * ```tsx\n * // As modal\n * {showInviteModal && (\n *   <InviteMember\n *     asModal\n *     onClose={() => setShowInviteModal(false)}\n *     onSuccess={(email) => toast.success(`Invited ${email}`)}\n *   />\n * )}\n *\n * // As form\n * <InviteMember\n *   onSuccess={(email) => toast.success(`Invited ${email}`)}\n * />\n * ```\n */\nexport function InviteMember(props: InviteMemberProps) {\n\treturn (\n\t\t<RequireSdk services={['organization']} componentType=\"organization\" theme={props.theme}>\n\t\t\t<InviteMemberInner {...props} />\n\t\t</RequireSdk>\n\t)\n}\n\n/** Inner component that safely uses platform hooks */\nfunction InviteMemberInner({\n\ttheme = defaultTheme,\n\tonSuccess,\n\tonError,\n\tonClose,\n\tasModal = false,\n\tdefaultRole = 'viewer',\n\tclassName,\n\tshowRoleDescriptions = true,\n}: InviteMemberProps) {\n\tconst { organization, inviteMember, hasPermission } = useOrganization()\n\tconst styles = baseStyles(theme)\n\tconst emailId = useId()\n\tconst roleGroupId = useId()\n\n\tconst [email, setEmail] = useState('')\n\tconst [role, setRole] = useState<OrgRole>(defaultRole)\n\tconst [isLoading, setIsLoading] = useState(false)\n\tconst [error, setError] = useState<string | null>(null)\n\tconst [success, setSuccess] = useState(false)\n\tconst [focusedField, setFocusedField] = useState<string | null>(null)\n\n\tconst canInvite = hasPermission('manage_members')\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// Handle escape key for modal\n\tuseEffect(() => {\n\t\tif (!asModal) return\n\n\t\tconst handleEscape = (e: KeyboardEvent) => {\n\t\t\tif (e.key === 'Escape') {\n\t\t\t\tonClose?.()\n\t\t\t}\n\t\t}\n\n\t\tdocument.addEventListener('keydown', handleEscape)\n\t\treturn () => document.removeEventListener('keydown', handleEscape)\n\t}, [asModal, onClose])\n\n\tconst handleSubmit = useCallback(\n\t\tasync (e: FormEvent) => {\n\t\t\te.preventDefault()\n\t\t\tif (!email.trim()) return\n\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tawait inviteMember(email.trim(), role)\n\t\t\t\tsetSuccess(true)\n\t\t\t\tonSuccess?.(email.trim(), role)\n\n\t\t\t\t// Reset form after success\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tsetEmail('')\n\t\t\t\t\tsetRole(defaultRole)\n\t\t\t\t\tsetSuccess(false)\n\t\t\t\t\tif (asModal) {\n\t\t\t\t\t\tonClose?.()\n\t\t\t\t\t}\n\t\t\t\t}, UI_SUCCESS_REDIRECT_MS)\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : 'Failed to send invite'\n\t\t\t\tsetError(message)\n\t\t\t\tonError?.(message)\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[email, role, inviteMember, onSuccess, onError, asModal, onClose, defaultRole],\n\t)\n\n\tif (!canInvite) {\n\t\treturn (\n\t\t\t<div style={mergeStyles(styles.alert, styles.alertWarning)}>\n\t\t\t\tYou don't have permission to invite members\n\t\t\t</div>\n\t\t)\n\t}\n\n\tif (!organization) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tstyle={mergeStyles(styles.textCenter, styles.textMuted, {\n\t\t\t\t\tpadding: '1rem',\n\t\t\t\t})}\n\t\t\t>\n\t\t\t\tNo organization selected\n\t\t\t</div>\n\t\t)\n\t}\n\n\tconst formContent = (\n\t\t<form onSubmit={handleSubmit}>\n\t\t\t{/* Email input */}\n\t\t\t<div style={styles.formGroup}>\n\t\t\t\t<label htmlFor={emailId} style={styles.label}>\n\t\t\t\t\tEmail address\n\t\t\t\t</label>\n\t\t\t\t<input\n\t\t\t\t\tid={emailId}\n\t\t\t\t\ttype=\"email\"\n\t\t\t\t\tvalue={email}\n\t\t\t\t\tonChange={(e) => {\n\t\t\t\t\t\tsetEmail(e.target.value)\n\t\t\t\t\t\tsetError(null)\n\t\t\t\t\t\tsetSuccess(false)\n\t\t\t\t\t}}\n\t\t\t\t\tonFocus={() => setFocusedField('email')}\n\t\t\t\t\tonBlur={() => setFocusedField(null)}\n\t\t\t\t\tplaceholder=\"colleague@company.com\"\n\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\trequired\n\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\tstyles.input,\n\t\t\t\t\t\tfocusedField === 'email' ? styles.inputFocus : {},\n\t\t\t\t\t\tisLoading ? styles.inputDisabled : {},\n\t\t\t\t\t)}\n\t\t\t\t/>\n\t\t\t</div>\n\n\t\t\t{/* Role selector */}\n\t\t\t<div style={styles.formGroup}>\n\t\t\t\t<div id={roleGroupId} style={styles.label}>\n\t\t\t\t\tRole\n\t\t\t\t</div>\n\t\t\t\t<div\n\t\t\t\t\trole=\"radiogroup\"\n\t\t\t\t\taria-labelledby={roleGroupId}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\tflexDirection: 'column',\n\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{ROLE_OPTIONS.map((option) => (\n\t\t\t\t\t\t<label\n\t\t\t\t\t\t\tkey={option.value}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\talignItems: 'flex-start',\n\t\t\t\t\t\t\t\tgap: '0.75rem',\n\t\t\t\t\t\t\t\tpadding: '0.75rem',\n\t\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t\t\tbackgroundColor: role === option.value ? theme.colorMuted : 'transparent',\n\t\t\t\t\t\t\t\tborderBottom:\n\t\t\t\t\t\t\t\t\toption.value !== ROLE_OPTIONS[ROLE_OPTIONS.length - 1].value\n\t\t\t\t\t\t\t\t\t\t? `1px solid ${theme.colorBorder}`\n\t\t\t\t\t\t\t\t\t\t: 'none',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\t\t\tname=\"role\"\n\t\t\t\t\t\t\t\tvalue={option.value}\n\t\t\t\t\t\t\t\tchecked={role === option.value}\n\t\t\t\t\t\t\t\tonChange={() => setRole(option.value)}\n\t\t\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tmarginTop: '0.125rem',\n\t\t\t\t\t\t\t\t\taccentColor: theme.colorPrimary,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t<div style={{ fontWeight: 500, fontSize: theme.fontSizeSm }}>{option.label}</div>\n\t\t\t\t\t\t\t\t{showRoleDescriptions && (\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t\t\tmarginTop: '0.125rem',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{option.description}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</label>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{/* Error message */}\n\t\t\t{error && <div style={mergeStyles(styles.alert, styles.alertError)}>{error}</div>}\n\n\t\t\t{/* Success message */}\n\t\t\t{success && (\n\t\t\t\t<div style={mergeStyles(styles.alert, styles.alertSuccess)}>\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={mergeStyles(styles.flexRow, {\n\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t<CheckIcon color={theme.colorSuccess} size={16} />\n\t\t\t\t\t\tInvite sent to {email}!\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Actions */}\n\t\t\t<div\n\t\t\t\tstyle={mergeStyles(styles.flexRow, {\n\t\t\t\t\tgap: '0.75rem',\n\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t})}\n\t\t\t>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\tdisabled={isLoading || !email.trim() || success}\n\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\tstyles.buttonPrimary,\n\t\t\t\t\t\t{ flex: 1 },\n\t\t\t\t\t\tisLoading || !email.trim() || success ? styles.buttonDisabled : {},\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t{isLoading ? (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t\t\tSending...\n\t\t\t\t\t\t</>\n\t\t\t\t\t) : success ? (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<CheckIcon color={theme.colorPrimaryForeground} size={16} />\n\t\t\t\t\t\t\tSent!\n\t\t\t\t\t\t</>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<SendIcon size={16} />\n\t\t\t\t\t\t\tSend Invite\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t</button>\n\t\t\t\t{asModal && onClose && (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={onClose}\n\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline)}\n\t\t\t\t\t>\n\t\t\t\t\t\tCancel\n\t\t\t\t\t</button>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</form>\n\t)\n\n\t// Modal wrapper\n\tif (asModal) {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{/* Backdrop */}\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\taria-label=\"Close dialog\"\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tposition: 'fixed',\n\t\t\t\t\t\tinset: 0,\n\t\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0.5)',\n\t\t\t\t\t\tzIndex: 99,\n\t\t\t\t\t\tanimation: 'sylphx-fade-in 0.15s ease-out',\n\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t}}\n\t\t\t\t\tonClick={onClose}\n\t\t\t\t/>\n\n\t\t\t\t{/* Modal */}\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tposition: 'fixed',\n\t\t\t\t\t\ttop: '50%',\n\t\t\t\t\t\tleft: '50%',\n\t\t\t\t\t\ttransform: 'translate(-50%, -50%)',\n\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\tmaxWidth: '420px',\n\t\t\t\t\t\tmaxHeight: '90vh',\n\t\t\t\t\t\toverflow: 'auto',\n\t\t\t\t\t\tzIndex: 100,\n\t\t\t\t\t\tanimation: 'sylphx-scale-in 0.15s ease-out',\n\t\t\t\t\t}}\n\t\t\t\t\tclassName={className}\n\t\t\t\t>\n\t\t\t\t\t<div style={styles.card}>\n\t\t\t\t\t\t<div style={styles.container}>\n\t\t\t\t\t\t\t<div style={mergeStyles(styles.cardHeader, styles.flexBetween)}>\n\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t<h2 style={styles.cardTitle}>Invite Member</h2>\n\t\t\t\t\t\t\t\t\t<p style={styles.cardDescription}>Invite a new member to {organization.name}</p>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tonClick={onClose}\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tpadding: '0.25rem',\n\t\t\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<XIcon size={20} />\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div style={styles.cardContent}>{formContent}</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</>\n\t\t)\n\t}\n\n\t// Card wrapper (non-modal)\n\treturn (\n\t\t<div style={styles.card} className={className}>\n\t\t\t<div style={styles.container}>\n\t\t\t\t<div style={styles.cardHeader}>\n\t\t\t\t\t<h2 style={styles.cardTitle}>Invite Member</h2>\n\t\t\t\t\t<p style={styles.cardDescription}>Invite a new member to {organization.name}</p>\n\t\t\t\t</div>\n\t\t\t\t<div style={styles.cardContent}>{formContent}</div>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n// Icons\nfunction CheckIcon({ color, size = 24 }: { color: string; size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tstyle={{ flexShrink: 0 }}\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M20 6 9 17l-5-5\" />\n\t\t</svg>\n\t)\n}\n\nfunction SendIcon({ size = 24 }: { size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tstyle={{ flexShrink: 0 }}\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z\" />\n\t\t\t<path d=\"m21.854 2.147-10.94 10.939\" />\n\t\t</svg>\n\t)\n}\n\nfunction XIcon({ size = 24 }: { size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tstyle={{ flexShrink: 0 }}\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M18 6 6 18\" />\n\t\t\t<path d=\"m6 6 12 12\" />\n\t\t</svg>\n\t)\n}\n","/**\n * MembersList Component\n *\n * Displays organization members with role management.\n * Uses optimistic updates for instant UI feedback with proper\n * rollback on failure.\n */\n\n'use client'\n\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport {\n\ttype OrganizationMember,\n\ttype OrgRole,\n\tRequireSdk,\n\tuseOrganization,\n\tuseUser,\n} from '../hooks'\nimport {\n\tbaseStyles,\n\tdefaultTheme,\n\tinjectGlobalStyles,\n\tmergeStyles,\n\ttype ThemeVariables,\n} from '../ui/styles'\n\nexport interface MembersListProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Show invite button */\n\tshowInviteButton?: boolean\n\t/** Called when invite button is clicked */\n\tonInviteClick?: () => void\n\t/** Hide role editor */\n\thideRoleEditor?: boolean\n\t/** Custom class name */\n\tclassName?: string\n\t/** Maximum members to show before \"show all\" */\n\tmaxVisible?: number\n\t/** Compact mode */\n\tcompact?: boolean\n}\n\nconst ROLE_LABELS: Record<OrgRole, string> = {\n\tsuper_admin: 'Super Admin',\n\tadmin: 'Admin',\n\tbilling: 'Billing',\n\tanalytics: 'Analytics',\n\tdeveloper: 'Developer',\n\tviewer: 'Viewer',\n}\n\nconst ROLE_DESCRIPTIONS: Record<OrgRole, string> = {\n\tsuper_admin: 'Full access to everything',\n\tadmin: 'Manage members, apps, and settings',\n\tbilling: 'Access billing and payments',\n\tanalytics: 'View analytics and reports',\n\tdeveloper: 'Manage apps and deployments',\n\tviewer: 'Read-only access',\n}\n\nconst ROLE_ORDER: OrgRole[] = [\n\t'super_admin',\n\t'admin',\n\t'billing',\n\t'analytics',\n\t'developer',\n\t'viewer',\n]\n\n/**\n * MembersList component for displaying organization members\n *\n * @example\n * ```tsx\n * <MembersList\n *   showInviteButton\n *   onInviteClick={() => setShowInviteModal(true)}\n * />\n * ```\n */\nexport function MembersList(props: MembersListProps) {\n\treturn (\n\t\t<RequireSdk services={['organization']} componentType=\"organization\" theme={props.theme}>\n\t\t\t<MembersListInner {...props} />\n\t\t</RequireSdk>\n\t)\n}\n\n/** Inner component that safely uses platform hooks */\nfunction MembersListInner({\n\ttheme = defaultTheme,\n\tshowInviteButton = true,\n\tonInviteClick,\n\thideRoleEditor = false,\n\tclassName,\n\tmaxVisible,\n\tcompact = false,\n}: MembersListProps) {\n\tconst { user } = useUser()\n\tconst {\n\t\torganization,\n\t\tmembers: serverMembers,\n\t\tisLoading,\n\t\thasPermission,\n\t\tupdateMemberRole,\n\t\tremoveMember,\n\t} = useOrganization()\n\tconst styles = baseStyles(theme)\n\n\tconst [editingMember, setEditingMember] = useState<string | null>(null)\n\tconst [confirmingRemove, setConfirmingRemove] = useState<string | null>(null)\n\tconst [error, setError] = useState<string | null>(null)\n\tconst [showAll, setShowAll] = useState(false)\n\n\t// Track which member is being updated for loading indicator\n\tconst [pendingAction, setPendingAction] = useState<string | null>(null)\n\n\tconst canManageMembers = hasPermission('manage_members')\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t/**\n\t * Optimistic list management using simple React state.\n\t * Syncs with server data and handles rollback on failure.\n\t */\n\tconst [members, setMembers] = useState<OrganizationMember[]>(serverMembers)\n\tconst [isPending, setIsPending] = useState(false)\n\tconst prevServerMembersRef = useRef(serverMembers)\n\n\t// Sync with server data when it changes (and no pending operations)\n\tuseEffect(() => {\n\t\tif (serverMembers !== prevServerMembersRef.current && !isPending) {\n\t\t\tsetMembers(serverMembers)\n\t\t\tprevServerMembersRef.current = serverMembers\n\t\t}\n\t}, [serverMembers, isPending])\n\n\t// Optimistic role update with rollback\n\tconst handleRoleChange = useCallback(\n\t\tasync (userId: string, newRole: OrgRole) => {\n\t\t\tsetError(null)\n\t\t\tconst member = members.find((m) => m.userId === userId)\n\t\t\tif (!member) return\n\n\t\t\tsetPendingAction(userId)\n\t\t\tsetEditingMember(null)\n\t\t\tsetIsPending(true)\n\n\t\t\t// Snapshot for rollback\n\t\t\tconst snapshot = [...members]\n\n\t\t\t// Apply optimistic update\n\t\t\tsetMembers((prev) => prev.map((m) => (m.userId === userId ? { ...m, role: newRole } : m)))\n\n\t\t\ttry {\n\t\t\t\tawait updateMemberRole(userId, newRole)\n\t\t\t} catch (err) {\n\t\t\t\t// Rollback on failure\n\t\t\t\tsetMembers(snapshot)\n\t\t\t\tconst message = err instanceof Error ? err.message : 'Failed to update role'\n\t\t\t\tsetError(message)\n\t\t\t} finally {\n\t\t\t\tsetPendingAction(null)\n\t\t\t\tsetIsPending(false)\n\t\t\t}\n\t\t},\n\t\t[members, updateMemberRole],\n\t)\n\n\t// Optimistic remove with rollback\n\tconst handleRemove = useCallback(\n\t\tasync (userId: string) => {\n\t\t\tsetError(null)\n\t\t\tconst member = members.find((m) => m.userId === userId)\n\t\t\tif (!member) return\n\n\t\t\tsetPendingAction(userId)\n\t\t\tsetConfirmingRemove(null)\n\t\t\tsetIsPending(true)\n\n\t\t\t// Snapshot for rollback\n\t\t\tconst snapshot = [...members]\n\n\t\t\t// Apply optimistic update\n\t\t\tsetMembers((prev) => prev.filter((m) => m.userId !== userId))\n\n\t\t\ttry {\n\t\t\t\tawait removeMember(userId)\n\t\t\t} catch (err) {\n\t\t\t\t// Rollback on failure\n\t\t\t\tsetMembers(snapshot)\n\t\t\t\tconst message = err instanceof Error ? err.message : 'Failed to remove member'\n\t\t\t\tsetError(message)\n\t\t\t} finally {\n\t\t\t\tsetPendingAction(null)\n\t\t\t\tsetIsPending(false)\n\t\t\t}\n\t\t},\n\t\t[members, removeMember],\n\t)\n\n\t// Loading state for individual actions\n\tconst actionLoading = isPending ? pendingAction : null\n\n\tif (isLoading) {\n\t\treturn (\n\t\t\t<div style={mergeStyles(styles.flexCenter, { padding: '2rem' })}>\n\t\t\t\t<span\n\t\t\t\t\tstyle={mergeStyles(styles.spinner, {\n\t\t\t\t\t\twidth: '1.5rem',\n\t\t\t\t\t\theight: '1.5rem',\n\t\t\t\t\t})}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t)\n\t}\n\n\tif (!organization) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tstyle={mergeStyles(styles.textCenter, styles.textMuted, {\n\t\t\t\t\tpadding: '2rem',\n\t\t\t\t})}\n\t\t\t>\n\t\t\t\tNo organization selected\n\t\t\t</div>\n\t\t)\n\t}\n\n\tconst visibleMembers = maxVisible && !showAll ? members.slice(0, maxVisible) : members\n\tconst hasMore = maxVisible && members.length > maxVisible\n\n\tconst avatarStyles: React.CSSProperties = {\n\t\twidth: compact ? '2rem' : '2.5rem',\n\t\theight: compact ? '2rem' : '2.5rem',\n\t\tborderRadius: '50%',\n\t\tbackgroundColor: theme.colorPrimary,\n\t\tcolor: theme.colorPrimaryForeground,\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'center',\n\t\tfontSize: compact ? theme.fontSizeSm : theme.fontSizeBase,\n\t\tfontWeight: 600,\n\t\tflexShrink: 0,\n\t}\n\n\tconst memberItemStyles: React.CSSProperties = {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tgap: '0.75rem',\n\t\tpadding: compact ? '0.5rem' : '0.75rem',\n\t\tborderBottom: `1px solid ${theme.colorBorder}`,\n\t}\n\n\tconst roleBadgeStyles = (role: OrgRole): React.CSSProperties => ({\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\tpadding: '0.125rem 0.5rem',\n\t\tfontSize: theme.fontSizeXs,\n\t\tfontWeight: 500,\n\t\tborderRadius: '9999px',\n\t\tbackgroundColor:\n\t\t\trole === 'super_admin'\n\t\t\t\t? `${theme.colorWarning}15`\n\t\t\t\t: role === 'admin'\n\t\t\t\t\t? `${theme.colorPrimary}15`\n\t\t\t\t\t: theme.colorMuted,\n\t\tcolor:\n\t\t\trole === 'super_admin'\n\t\t\t\t? theme.colorWarning\n\t\t\t\t: role === 'admin'\n\t\t\t\t\t? theme.colorPrimary\n\t\t\t\t\t: theme.colorMutedForeground,\n\t})\n\n\treturn (\n\t\t<div className={className}>\n\t\t\t{/* Header */}\n\t\t\t<div\n\t\t\t\tstyle={mergeStyles(styles.flexBetween, {\n\t\t\t\t\tmarginBottom: '1rem',\n\t\t\t\t\tpadding: compact ? 0 : '0 0.75rem',\n\t\t\t\t})}\n\t\t\t>\n\t\t\t\t<div>\n\t\t\t\t\t<h3 style={mergeStyles(styles.cardTitle, { margin: 0 })}>Members</h3>\n\t\t\t\t\t<p\n\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t{members.length} member{members.length !== 1 ? 's' : ''}\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t\t{showInviteButton && canManageMembers && (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={onInviteClick}\n\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary, {\n\t\t\t\t\t\t\tpadding: '0.375rem 0.75rem',\n\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t<PlusIcon size={16} />\n\t\t\t\t\t\tInvite\n\t\t\t\t\t</button>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{/* Error message */}\n\t\t\t{error && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={mergeStyles(styles.alert, styles.alertError, {\n\t\t\t\t\t\tmargin: '0 0.75rem 1rem',\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\t{error}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Members list */}\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{visibleMembers.map((member) => (\n\t\t\t\t\t<div key={member.userId} style={memberItemStyles}>\n\t\t\t\t\t\t{/* Avatar */}\n\t\t\t\t\t\t{member.image ? (\n\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\tsrc={member.image}\n\t\t\t\t\t\t\t\talt={member.name || member.email}\n\t\t\t\t\t\t\t\tstyle={{ ...avatarStyles, objectFit: 'cover' }}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<div style={avatarStyles}>\n\t\t\t\t\t\t\t\t{(member.name || member.email).charAt(0).toUpperCase()}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{/* Info */}\n\t\t\t\t\t\t<div style={{ flex: 1, minWidth: 0 }}>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.flexRow, {\n\t\t\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\t\t\t\t\t\ttextOverflow: 'ellipsis',\n\t\t\t\t\t\t\t\t\t\twhiteSpace: 'nowrap',\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{member.name || member.email.split('@')[0]}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t{member.userId === user?.id && (\n\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\t\t\t\t\t\t\tpadding: '0.0625rem 0.375rem',\n\t\t\t\t\t\t\t\t\t\t\tborderRadius: '9999px',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tYou\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{!compact && member.name && (\n\t\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{member.email}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t{/* Role */}\n\t\t\t\t\t\t{editingMember === member.userId ? (\n\t\t\t\t\t\t\t<RoleSelector\n\t\t\t\t\t\t\t\tcurrentRole={member.role}\n\t\t\t\t\t\t\t\tonSelect={(role) => handleRoleChange(member.userId, role)}\n\t\t\t\t\t\t\t\tonCancel={() => setEditingMember(null)}\n\t\t\t\t\t\t\t\tisLoading={actionLoading === member.userId}\n\t\t\t\t\t\t\t\ttheme={theme}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : confirmingRemove === member.userId ? (\n\t\t\t\t\t\t\t<div style={mergeStyles(styles.flexRow, { gap: '0.5rem' })}>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tonClick={() => handleRemove(member.userId)}\n\t\t\t\t\t\t\t\t\tdisabled={actionLoading === member.userId}\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonDestructive, {\n\t\t\t\t\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{actionLoading === member.userId ? <span style={styles.spinner} /> : 'Confirm'}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tonClick={() => setConfirmingRemove(null)}\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline, {\n\t\t\t\t\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.flexRow, {\n\t\t\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span style={roleBadgeStyles(member.role)}>{ROLE_LABELS[member.role]}</span>\n\n\t\t\t\t\t\t\t\t{/* Actions dropdown */}\n\t\t\t\t\t\t\t\t{canManageMembers && !hideRoleEditor && member.userId !== user?.id && (\n\t\t\t\t\t\t\t\t\t<MemberActions\n\t\t\t\t\t\t\t\t\t\tmember={member}\n\t\t\t\t\t\t\t\t\t\tonEditRole={() => setEditingMember(member.userId)}\n\t\t\t\t\t\t\t\t\t\tonRemove={() => setConfirmingRemove(member.userId)}\n\t\t\t\t\t\t\t\t\t\ttheme={theme}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t))}\n\n\t\t\t\t{/* Show more button */}\n\t\t\t\t{hasMore && (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={() => setShowAll(!showAll)}\n\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonGhost, {\n\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\tjustifyContent: 'center',\n\t\t\t\t\t\t\tpadding: '0.75rem',\n\t\t\t\t\t\t\tborderRadius: 0,\n\t\t\t\t\t\t\tcolor: theme.colorPrimary,\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t{showAll ? 'Show less' : `Show all ${members.length} members`}\n\t\t\t\t\t</button>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n// Role selector component\nfunction RoleSelector({\n\tcurrentRole,\n\tonSelect,\n\tonCancel,\n\tisLoading,\n\ttheme,\n}: {\n\tcurrentRole: OrgRole\n\tonSelect: (role: OrgRole) => void\n\tonCancel: () => void\n\tisLoading: boolean\n\ttheme: ThemeVariables\n}) {\n\tconst styles = baseStyles(theme)\n\n\treturn (\n\t\t<div\n\t\t\tstyle={{\n\t\t\t\tposition: 'absolute',\n\t\t\t\tright: '0.5rem',\n\t\t\t\tbackgroundColor: theme.colorBackground,\n\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\tboxShadow: '0 4px 6px -1px rgb(0 0 0 / 0.1)',\n\t\t\t\tzIndex: 50,\n\t\t\t\tminWidth: '180px',\n\t\t\t\toverflow: 'hidden',\n\t\t\t}}\n\t\t>\n\t\t\t{ROLE_ORDER.map((role) => (\n\t\t\t\t<button\n\t\t\t\t\tkey={role}\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={() => onSelect(role)}\n\t\t\t\t\tdisabled={isLoading || role === currentRole}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\tpadding: '0.5rem 0.75rem',\n\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\ttextAlign: 'left',\n\t\t\t\t\t\tbackgroundColor: role === currentRole ? theme.colorMuted : 'transparent',\n\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\tcursor: role === currentRole ? 'default' : 'pointer',\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<div style={{ fontWeight: 500 }}>{ROLE_LABELS[role]}</div>\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{ROLE_DESCRIPTIONS[role]}\n\t\t\t\t\t</div>\n\t\t\t\t</button>\n\t\t\t))}\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\tborderTop: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\tpadding: '0.5rem',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={onCancel}\n\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline, styles.buttonFullWidth, {\n\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\tCancel\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n// Member actions dropdown\nfunction MemberActions({\n\tmember,\n\tonEditRole,\n\tonRemove,\n\ttheme,\n}: {\n\tmember: OrganizationMember\n\tonEditRole: () => void\n\tonRemove: () => void\n\ttheme: ThemeVariables\n}) {\n\tconst [isOpen, setIsOpen] = useState(false)\n\n\treturn (\n\t\t<div style={{ position: 'relative' }}>\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tonClick={() => setIsOpen(!isOpen)}\n\t\t\t\tstyle={{\n\t\t\t\t\tpadding: '0.25rem',\n\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\tborder: 'none',\n\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<MoreIcon />\n\t\t\t</button>\n\n\t\t\t{isOpen && (\n\t\t\t\t<>\n\t\t\t\t\t{/* Backdrop */}\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\taria-label=\"Close dropdown\"\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tposition: 'fixed',\n\t\t\t\t\t\t\tinset: 0,\n\t\t\t\t\t\t\tzIndex: 40,\n\t\t\t\t\t\t\tbackground: 'transparent',\n\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\tcursor: 'default',\n\t\t\t\t\t\t}}\n\t\t\t\t\t\ttabIndex={-1}\n\t\t\t\t\t\tonClick={() => setIsOpen(false)}\n\t\t\t\t\t/>\n\n\t\t\t\t\t{/* Dropdown */}\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\t\t\tright: 0,\n\t\t\t\t\t\t\ttop: '100%',\n\t\t\t\t\t\t\tmarginTop: '0.25rem',\n\t\t\t\t\t\t\tbackgroundColor: theme.colorBackground,\n\t\t\t\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\t\t\tboxShadow: '0 4px 6px -1px rgb(0 0 0 / 0.1)',\n\t\t\t\t\t\t\tzIndex: 50,\n\t\t\t\t\t\t\tminWidth: '120px',\n\t\t\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\tsetIsOpen(false)\n\t\t\t\t\t\t\t\tonEditRole()\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\t\tpadding: '0.5rem 0.75rem',\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\ttextAlign: 'left',\n\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t\t\tcolor: theme.colorForeground,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<EditIcon size={14} />\n\t\t\t\t\t\t\tChange role\n\t\t\t\t\t\t</button>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\tsetIsOpen(false)\n\t\t\t\t\t\t\t\tonRemove()\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\t\tpadding: '0.5rem 0.75rem',\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\ttextAlign: 'left',\n\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t\t\tcolor: theme.colorDestructive,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<TrashIcon size={14} color={theme.colorDestructive} />\n\t\t\t\t\t\t\tRemove\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n// Icons\nfunction PlusIcon({ size = 24 }: { size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t>\n\t\t\t<path d=\"M12 5v14M5 12h14\" />\n\t\t</svg>\n\t)\n}\n\nfunction MoreIcon() {\n\treturn (\n\t\t<svg\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t>\n\t\t\t<circle cx=\"12\" cy=\"12\" r=\"1\" />\n\t\t\t<circle cx=\"12\" cy=\"5\" r=\"1\" />\n\t\t\t<circle cx=\"12\" cy=\"19\" r=\"1\" />\n\t\t</svg>\n\t)\n}\n\nfunction EditIcon({ size = 24 }: { size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t>\n\t\t\t<path d=\"M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z\" />\n\t\t</svg>\n\t)\n}\n\nfunction TrashIcon({ size = 24, color = 'currentColor' }: { size?: number; color?: string }) {\n\treturn (\n\t\t<svg\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t>\n\t\t\t<path d=\"M3 6h18\" />\n\t\t\t<path d=\"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\" />\n\t\t\t<path d=\"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\" />\n\t\t</svg>\n\t)\n}\n","/**\n * OrganizationSwitcher Component\n *\n * Dropdown to switch between organizations.\n * Matches Clerk's OrganizationSwitcher component API.\n */\n\n'use client'\n\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { RequireSdk, useOrganization, useUser } from '../hooks'\nimport { safeRedirect } from '../security-utils'\nimport {\n\tbaseStyles,\n\tdefaultTheme,\n\tinjectGlobalStyles,\n\tmergeStyles,\n\ttype ThemeVariables,\n} from '../ui/styles'\n\nexport interface OrganizationSwitcherProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Show personal workspace option */\n\thidePersonal?: boolean\n\t/** Called when organization is switched */\n\tonOrganizationSwitch?: (orgId: string | null) => void\n\t/** URL to navigate to after creating an org */\n\tafterCreateOrganizationUrl?: string\n\t/** URL to navigate to for organization settings */\n\torganizationSettingsUrl?: string\n\t/** Custom class name */\n\tclassName?: string\n\t/** Trigger button appearance */\n\tappearance?: {\n\t\tbaseStyle?: React.CSSProperties\n\t}\n}\n\n/**\n * Organization switcher dropdown\n *\n * @example\n * ```tsx\n * <OrganizationSwitcher\n *   onOrganizationSwitch={(orgId) => console.log('Switched to', orgId)}\n *   afterCreateOrganizationUrl=\"/org/settings\"\n * />\n * ```\n */\nexport function OrganizationSwitcher(props: OrganizationSwitcherProps) {\n\treturn (\n\t\t<RequireSdk services={['organization']} componentType=\"organization\" theme={props.theme}>\n\t\t\t<OrganizationSwitcherInner {...props} />\n\t\t</RequireSdk>\n\t)\n}\n\n/** Inner component that safely uses platform hooks */\nfunction OrganizationSwitcherInner({\n\ttheme = defaultTheme,\n\thidePersonal = false,\n\tonOrganizationSwitch,\n\tafterCreateOrganizationUrl = '/org/settings',\n\torganizationSettingsUrl,\n\tclassName,\n\tappearance,\n}: OrganizationSwitcherProps) {\n\tconst { user, isLoaded: userLoaded } = useUser()\n\tconst { organization, organizations, isLoading, setOrganization, createOrganization } =\n\t\tuseOrganization()\n\tconst styles = baseStyles(theme)\n\n\tconst [isOpen, setIsOpen] = useState(false)\n\tconst [isCreating, setIsCreating] = useState(false)\n\tconst [newOrgName, setNewOrgName] = useState('')\n\tconst [error, setError] = useState<string | null>(null)\n\tconst dropdownRef = useRef<HTMLDivElement>(null)\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// Close dropdown when clicking outside\n\tuseEffect(() => {\n\t\tconst handleClickOutside = (e: MouseEvent) => {\n\t\t\tif (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {\n\t\t\t\tsetIsOpen(false)\n\t\t\t\tsetIsCreating(false)\n\t\t\t}\n\t\t}\n\n\t\tdocument.addEventListener('mousedown', handleClickOutside)\n\t\treturn () => document.removeEventListener('mousedown', handleClickOutside)\n\t}, [])\n\n\tconst handleSwitch = useCallback(\n\t\t(orgId: string | null) => {\n\t\t\tsetOrganization(orgId)\n\t\t\tonOrganizationSwitch?.(orgId)\n\t\t\tsetIsOpen(false)\n\t\t},\n\t\t[setOrganization, onOrganizationSwitch],\n\t)\n\n\tconst handleCreate = useCallback(async () => {\n\t\tif (!newOrgName.trim()) return\n\n\t\tsetError(null)\n\t\ttry {\n\t\t\tconst newOrg = await createOrganization({ name: newOrgName.trim() })\n\t\t\tsetNewOrgName('')\n\t\t\tsetIsCreating(false)\n\t\t\tsetIsOpen(false)\n\t\t\tonOrganizationSwitch?.(newOrg.id)\n\n\t\t\tif (afterCreateOrganizationUrl && typeof window !== 'undefined') {\n\t\t\t\tsafeRedirect(afterCreateOrganizationUrl, { fallback: '/dashboard' })\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to create organization'\n\t\t\tsetError(message)\n\t\t}\n\t}, [newOrgName, createOrganization, onOrganizationSwitch, afterCreateOrganizationUrl])\n\n\tif (!userLoaded || isLoading) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline, {\n\t\t\t\t\twidth: '180px',\n\t\t\t\t\tjustifyContent: 'flex-start',\n\t\t\t\t\topacity: 0.5,\n\t\t\t\t})}\n\t\t\t>\n\t\t\t\t<span style={styles.spinner} />\n\t\t\t\tLoading...\n\t\t\t</div>\n\t\t)\n\t}\n\n\tif (!user) {\n\t\treturn null\n\t}\n\n\tconst currentDisplay = organization?.name || 'Personal'\n\n\tconst triggerStyles: React.CSSProperties = {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tgap: '0.5rem',\n\t\tpadding: '0.5rem 0.75rem',\n\t\tfontSize: theme.fontSizeSm,\n\t\tfontWeight: 500,\n\t\tborderRadius: theme.borderRadius,\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tbackgroundColor: theme.colorBackground,\n\t\tcolor: theme.colorForeground,\n\t\tcursor: 'pointer',\n\t\tminWidth: '160px',\n\t\tjustifyContent: 'space-between',\n\t\t...appearance?.baseStyle,\n\t}\n\n\tconst dropdownStyles: React.CSSProperties = {\n\t\tposition: 'absolute',\n\t\ttop: '100%',\n\t\tleft: 0,\n\t\tmarginTop: '0.25rem',\n\t\tminWidth: '220px',\n\t\tbackgroundColor: theme.colorBackground,\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t\tboxShadow: '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)',\n\t\tzIndex: 50,\n\t\toverflow: 'hidden',\n\t}\n\n\tconst itemStyles: React.CSSProperties = {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tgap: '0.75rem',\n\t\tpadding: '0.625rem 0.75rem',\n\t\tfontSize: theme.fontSizeSm,\n\t\tcolor: theme.colorForeground,\n\t\tcursor: 'pointer',\n\t\tbackgroundColor: 'transparent',\n\t\tborder: 'none',\n\t\twidth: '100%',\n\t\ttextAlign: 'left',\n\t\ttransition: 'background-color 0.15s',\n\t}\n\n\tconst itemHoverStyles: React.CSSProperties = {\n\t\tbackgroundColor: theme.colorMuted,\n\t}\n\n\tconst avatarStyles: React.CSSProperties = {\n\t\twidth: '1.75rem',\n\t\theight: '1.75rem',\n\t\tborderRadius: '4px',\n\t\tbackgroundColor: theme.colorPrimary,\n\t\tcolor: '#fff',\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'center',\n\t\tfontSize: '0.75rem',\n\t\tfontWeight: 600,\n\t}\n\n\tconst personalAvatarStyles: React.CSSProperties = {\n\t\t...avatarStyles,\n\t\tborderRadius: '50%',\n\t}\n\n\treturn (\n\t\t<div ref={dropdownRef} style={{ position: 'relative', display: 'inline-block' }}>\n\t\t\t{/* Trigger */}\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tonClick={() => setIsOpen(!isOpen)}\n\t\t\t\tclassName={className}\n\t\t\t\tstyle={triggerStyles}\n\t\t\t>\n\t\t\t\t<span style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>\n\t\t\t\t\t{organization ? (\n\t\t\t\t\t\t<span style={avatarStyles}>\n\t\t\t\t\t\t\t{organization.logoUrl ? (\n\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\tsrc={organization.logoUrl}\n\t\t\t\t\t\t\t\t\talt={organization.name}\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\t\t\t\theight: '100%',\n\t\t\t\t\t\t\t\t\t\tobjectFit: 'cover',\n\t\t\t\t\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\torganization.name.charAt(0).toUpperCase()\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<span style={personalAvatarStyles}>\n\t\t\t\t\t\t\t{user.image ? (\n\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\tsrc={user.image}\n\t\t\t\t\t\t\t\t\talt={user.name || 'User'}\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\t\t\t\theight: '100%',\n\t\t\t\t\t\t\t\t\t\tobjectFit: 'cover',\n\t\t\t\t\t\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t(user.name || user.email).charAt(0).toUpperCase()\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)}\n\t\t\t\t\t<span\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\t\t\ttextOverflow: 'ellipsis',\n\t\t\t\t\t\t\twhiteSpace: 'nowrap',\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{currentDisplay}\n\t\t\t\t\t</span>\n\t\t\t\t</span>\n\t\t\t\t<ChevronIcon />\n\t\t\t</button>\n\n\t\t\t{/* Dropdown */}\n\t\t\t{isOpen && (\n\t\t\t\t<div style={dropdownStyles}>\n\t\t\t\t\t{/* Personal workspace */}\n\t\t\t\t\t{!hidePersonal && (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={() => handleSwitch(null)}\n\t\t\t\t\t\t\tstyle={itemStyles}\n\t\t\t\t\t\t\tonMouseEnter={(e) => Object.assign(e.currentTarget.style, itemHoverStyles)}\n\t\t\t\t\t\t\tonMouseLeave={(e) =>\n\t\t\t\t\t\t\t\tObject.assign(e.currentTarget.style, {\n\t\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<span style={personalAvatarStyles}>\n\t\t\t\t\t\t\t\t{user.image ? (\n\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\tsrc={user.image}\n\t\t\t\t\t\t\t\t\t\talt={user.name || 'User'}\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\t\t\t\t\theight: '100%',\n\t\t\t\t\t\t\t\t\t\t\tobjectFit: 'cover',\n\t\t\t\t\t\t\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t(user.name || user.email).charAt(0).toUpperCase()\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<span style={{ flex: 1 }}>Personal</span>\n\t\t\t\t\t\t\t{!organization && <CheckIcon color={theme.colorPrimary} size={16} />}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* Organizations */}\n\t\t\t\t\t{organizations.length > 0 && (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tborderTop: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t\t\t\tmargin: '0.25rem 0',\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tpadding: '0.375rem 0.75rem',\n\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\ttextTransform: 'uppercase',\n\t\t\t\t\t\t\t\t\tletterSpacing: '0.05em',\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tOrganizations\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{organizations.map((org) => (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\tkey={org.id}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tonClick={() => handleSwitch(org.id)}\n\t\t\t\t\t\t\t\t\tstyle={itemStyles}\n\t\t\t\t\t\t\t\t\tonMouseEnter={(e) => Object.assign(e.currentTarget.style, itemHoverStyles)}\n\t\t\t\t\t\t\t\t\tonMouseLeave={(e) =>\n\t\t\t\t\t\t\t\t\t\tObject.assign(e.currentTarget.style, {\n\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span style={avatarStyles}>\n\t\t\t\t\t\t\t\t\t\t{org.logoUrl ? (\n\t\t\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\t\t\tsrc={org.logoUrl}\n\t\t\t\t\t\t\t\t\t\t\t\talt={org.name}\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\t\t\t\t\t\t\theight: '100%',\n\t\t\t\t\t\t\t\t\t\t\t\t\tobjectFit: 'cover',\n\t\t\t\t\t\t\t\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\torg.name.charAt(0).toUpperCase()\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tflex: 1,\n\t\t\t\t\t\t\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\t\t\t\t\t\t\ttextOverflow: 'ellipsis',\n\t\t\t\t\t\t\t\t\t\t\twhiteSpace: 'nowrap',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{org.name}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t{organization?.id === org.id && (\n\t\t\t\t\t\t\t\t\t\t<CheckIcon color={theme.colorPrimary} size={16} />\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* Create organization */}\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tborderTop: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t\tmargin: '0.25rem 0',\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t\t{isCreating ? (\n\t\t\t\t\t\t<div style={{ padding: '0.75rem' }}>\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\tvalue={newOrgName}\n\t\t\t\t\t\t\t\tonChange={(e) => setNewOrgName(e.target.value)}\n\t\t\t\t\t\t\t\tplaceholder=\"Organization name\"\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.input, {\n\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\tonKeyDown={(e) => {\n\t\t\t\t\t\t\t\t\tif (e.key === 'Enter') handleCreate()\n\t\t\t\t\t\t\t\t\tif (e.key === 'Escape') setIsCreating(false)\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t{error && (\n\t\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textXs, {\n\t\t\t\t\t\t\t\t\t\tcolor: theme.colorDestructive,\n\t\t\t\t\t\t\t\t\t\tmarginTop: '0.25rem',\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{error}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<div style={{ display: 'flex', gap: '0.5rem', marginTop: '0.5rem' }}>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tonClick={handleCreate}\n\t\t\t\t\t\t\t\t\tdisabled={!newOrgName.trim()}\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\t\t\t\t\tstyles.buttonPrimary,\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tflex: 1,\n\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\t\t\t\tpadding: '0.375rem 0.5rem',\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t!newOrgName.trim() ? styles.buttonDisabled : {},\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tCreate\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\tsetIsCreating(false)\n\t\t\t\t\t\t\t\t\t\tsetNewOrgName('')\n\t\t\t\t\t\t\t\t\t\tsetError(null)\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline, {\n\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\t\t\tpadding: '0.375rem 0.5rem',\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={() => setIsCreating(true)}\n\t\t\t\t\t\t\tstyle={itemStyles}\n\t\t\t\t\t\t\tonMouseEnter={(e) => Object.assign(e.currentTarget.style, itemHoverStyles)}\n\t\t\t\t\t\t\tonMouseLeave={(e) =>\n\t\t\t\t\t\t\t\tObject.assign(e.currentTarget.style, {\n\t\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tstyle={mergeStyles(avatarStyles, {\n\t\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\t\tborder: `1px dashed ${theme.colorBorder}`,\n\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<PlusIcon />\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<span style={{ color: theme.colorMutedForeground }}>Create organization</span>\n\t\t\t\t\t\t</button>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* Org settings link */}\n\t\t\t\t\t{organization && organizationSettingsUrl && (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tborderTop: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t\t\t\tmargin: '0.25rem 0',\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\thref={organizationSettingsUrl}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(itemStyles, { textDecoration: 'none' })}\n\t\t\t\t\t\t\t\tonMouseEnter={(e) => Object.assign(e.currentTarget.style, itemHoverStyles)}\n\t\t\t\t\t\t\t\tonMouseLeave={(e) =>\n\t\t\t\t\t\t\t\t\tObject.assign(e.currentTarget.style, {\n\t\t\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<SettingsIcon color={theme.colorMutedForeground} />\n\t\t\t\t\t\t\t\t<span style={{ color: theme.colorMutedForeground }}>Organization settings</span>\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\nfunction ChevronIcon() {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"m6 9 6 6 6-6\" />\n\t\t</svg>\n\t)\n}\n\nfunction CheckIcon({ color, size = 24 }: { color: string; size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M20 6 9 17l-5-5\" />\n\t\t</svg>\n\t)\n}\n\nfunction PlusIcon() {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"14\"\n\t\t\theight=\"14\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M12 5v14M5 12h14\" />\n\t\t</svg>\n\t)\n}\n\nfunction SettingsIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"18\"\n\t\t\theight=\"18\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z\" />\n\t\t\t<circle cx=\"12\" cy=\"12\" r=\"3\" />\n\t\t</svg>\n\t)\n}\n","/**\n * PricingTable Component\n *\n * Displays available plans with pricing and features.\n * Matches Clerk's pricing table pattern but for billing.\n */\n\n'use client'\n\nimport { useCallback, useEffect, useState } from 'react'\nimport { RequireSdk } from '../hooks'\nimport { useBilling } from '../platform-hooks'\nimport {\n\tbaseStyles,\n\tdefaultTheme,\n\tinjectGlobalStyles,\n\tmergeStyles,\n\ttype ThemeVariables,\n} from '../ui/styles'\n\nexport interface PricingTableProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Billing interval to show by default */\n\tdefaultInterval?: 'monthly' | 'annual' | 'lifetime'\n\t/** Show interval toggle */\n\tshowIntervalToggle?: boolean\n\t/** Highlight this plan slug */\n\thighlightPlan?: string\n\t/** Called when checkout starts */\n\tonCheckoutStart?: (planSlug: string, interval: 'monthly' | 'annual' | 'lifetime') => void\n\t/** Called on checkout error */\n\tonError?: (error: string) => void\n\t/** Custom class name */\n\tclassName?: string\n\t/** Show annual savings badge */\n\tshowAnnualSavings?: boolean\n\t/** Feature comparison mode */\n\tshowFeatureComparison?: boolean\n}\n\n/**\n * PricingTable component for displaying subscription plans\n *\n * @example\n * ```tsx\n * <PricingTable\n *   defaultInterval=\"annual\"\n *   highlightPlan=\"pro\"\n *   showAnnualSavings\n * />\n * ```\n */\nexport function PricingTable(props: PricingTableProps) {\n\treturn (\n\t\t<RequireSdk services={['billing']} componentType=\"billing\" theme={props.theme}>\n\t\t\t<PricingTableInner {...props} />\n\t\t</RequireSdk>\n\t)\n}\n\n/** Inner component that safely uses platform hooks */\nfunction PricingTableInner({\n\ttheme = defaultTheme,\n\tdefaultInterval = 'monthly',\n\tshowIntervalToggle = true,\n\thighlightPlan,\n\tonCheckoutStart,\n\tonError,\n\tclassName,\n\tshowAnnualSavings = true,\n\tshowFeatureComparison = false,\n}: PricingTableProps) {\n\tconst { plans, plansLoading, plansError, subscription, isPremium, createCheckout, refresh } =\n\t\tuseBilling()\n\tconst styles = baseStyles(theme)\n\n\tconst [interval, setSelectedInterval] = useState<'monthly' | 'annual' | 'lifetime'>(\n\t\tdefaultInterval,\n\t)\n\tconst [loadingPlan, setLoadingPlan] = useState<string | null>(null)\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tconst handleCheckout = useCallback(\n\t\tasync (planSlug: string) => {\n\t\t\tsetLoadingPlan(planSlug)\n\t\t\tonCheckoutStart?.(planSlug, interval)\n\n\t\t\ttry {\n\t\t\t\tconst checkoutUrl = await createCheckout(planSlug, interval)\n\t\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\t\twindow.location.href = checkoutUrl\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : 'Failed to start checkout'\n\t\t\t\tonError?.(message)\n\t\t\t} finally {\n\t\t\t\tsetLoadingPlan(null)\n\t\t\t}\n\t\t},\n\t\t[interval, createCheckout, onCheckoutStart, onError],\n\t)\n\n\tif (plansLoading) {\n\t\treturn (\n\t\t\t<div style={mergeStyles(styles.flexCenter, { padding: '3rem' })}>\n\t\t\t\t<span style={mergeStyles(styles.spinner, { width: '2rem', height: '2rem' })} />\n\t\t\t</div>\n\t\t)\n\t}\n\n\tif (plansError) {\n\t\treturn (\n\t\t\t<div className={className} style={{ padding: '2rem' }}>\n\t\t\t\t<div style={mergeStyles(styles.alert, styles.alertError)}>\n\t\t\t\t\t<div style={{ marginBottom: '0.75rem' }}>\n\t\t\t\t\t\tFailed to load pricing plans. Please try again.\n\t\t\t\t\t</div>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={() => refresh()}\n\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline, {\n\t\t\t\t\t\t\tpadding: '0.5rem 1rem',\n\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t<RefreshIcon size={14} color={theme.colorForeground} />\n\t\t\t\t\t\tTry Again\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t)\n\t}\n\n\tif (!plans || plans.length === 0) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tstyle={mergeStyles(styles.textCenter, styles.textMuted, {\n\t\t\t\t\tpadding: '2rem',\n\t\t\t\t})}\n\t\t\t>\n\t\t\t\tNo plans available\n\t\t\t</div>\n\t\t)\n\t}\n\n\t// Get price for a plan based on interval\n\tconst getPlanPrice = (plan: (typeof plans)[0], int: 'monthly' | 'annual' | 'lifetime') => {\n\t\tswitch (int) {\n\t\t\tcase 'monthly':\n\t\t\t\treturn plan.monthlyPrice || 0\n\t\t\tcase 'annual':\n\t\t\t\treturn plan.annualPrice || 0\n\t\t\tcase 'lifetime':\n\t\t\t\treturn plan.lifetimePrice || 0\n\t\t\tdefault:\n\t\t\t\treturn 0\n\t\t}\n\t}\n\n\t// Calculate annual savings\n\tconst getAnnualSavings = (plan: (typeof plans)[0]) => {\n\t\tconst monthly = plan.monthlyPrice || 0\n\t\tconst annual = plan.annualPrice || 0\n\t\tif (monthly > 0 && annual > 0) {\n\t\t\tconst yearlyFromMonthly = monthly * 12\n\t\t\tconst savings = Math.round(((yearlyFromMonthly - annual) / yearlyFromMonthly) * 100)\n\t\t\treturn savings > 0 ? savings : 0\n\t\t}\n\t\treturn 0\n\t}\n\n\tconst containerStyles: React.CSSProperties = {\n\t\tdisplay: 'grid',\n\t\tgridTemplateColumns: `repeat(${Math.min(plans.length, 3)}, 1fr)`,\n\t\tgap: '1.5rem',\n\t\tmaxWidth: '1000px',\n\t\tmargin: '0 auto',\n\t}\n\n\tconst planCardStyles = (isHighlighted: boolean): React.CSSProperties => ({\n\t\tbackgroundColor: theme.colorBackground,\n\t\tborderRadius: theme.borderRadiusLg,\n\t\tborder: `${isHighlighted ? '2px' : '1px'} solid ${isHighlighted ? theme.colorPrimary : theme.colorBorder}`,\n\t\tpadding: '1.5rem',\n\t\tdisplay: 'flex',\n\t\tflexDirection: 'column',\n\t\tposition: 'relative',\n\t\tboxShadow: isHighlighted\n\t\t\t? `0 8px 30px ${theme.colorPrimary}20`\n\t\t\t: '0 1px 3px 0 rgb(0 0 0 / 0.1)',\n\t})\n\n\tconst badgeStyles: React.CSSProperties = {\n\t\tposition: 'absolute',\n\t\ttop: '-0.75rem',\n\t\tleft: '50%',\n\t\ttransform: 'translateX(-50%)',\n\t\tbackgroundColor: theme.colorPrimary,\n\t\tcolor: theme.colorPrimaryForeground,\n\t\tpadding: '0.25rem 0.75rem',\n\t\tborderRadius: '9999px',\n\t\tfontSize: theme.fontSizeXs,\n\t\tfontWeight: 600,\n\t\ttextTransform: 'uppercase',\n\t\tletterSpacing: '0.05em',\n\t\twhiteSpace: 'nowrap',\n\t}\n\n\tconst priceStyles: React.CSSProperties = {\n\t\tfontSize: '2.5rem',\n\t\tfontWeight: 700,\n\t\tcolor: theme.colorForeground,\n\t\tlineHeight: 1,\n\t}\n\n\tconst intervalTextStyles: React.CSSProperties = {\n\t\tfontSize: theme.fontSizeSm,\n\t\tcolor: theme.colorMutedForeground,\n\t\tmarginLeft: '0.25rem',\n\t}\n\n\tconst featureListStyles: React.CSSProperties = {\n\t\tlistStyle: 'none',\n\t\tpadding: 0,\n\t\tmargin: '1.5rem 0',\n\t\tflex: 1,\n\t}\n\n\tconst featureItemStyles: React.CSSProperties = {\n\t\tdisplay: 'flex',\n\t\talignItems: 'flex-start',\n\t\tgap: '0.5rem',\n\t\tmarginBottom: '0.75rem',\n\t\tfontSize: theme.fontSizeSm,\n\t\tcolor: theme.colorForeground,\n\t}\n\n\treturn (\n\t\t<div className={className}>\n\t\t\t{/* Interval Toggle */}\n\t\t\t{showIntervalToggle && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={mergeStyles(styles.flexCenter, {\n\t\t\t\t\t\tmarginBottom: '2rem',\n\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\t<div style={styles.tabs}>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={() => setSelectedInterval('monthly')}\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.tab, interval === 'monthly' ? styles.tabActive : {})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tMonthly\n\t\t\t\t\t\t</button>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={() => setSelectedInterval('annual')}\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.tab, interval === 'annual' ? styles.tabActive : {})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tAnnual\n\t\t\t\t\t\t\t{showAnnualSavings && (\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tmarginLeft: '0.5rem',\n\t\t\t\t\t\t\t\t\t\tbackgroundColor: `${theme.colorSuccess}20`,\n\t\t\t\t\t\t\t\t\t\tcolor: theme.colorSuccess,\n\t\t\t\t\t\t\t\t\t\tpadding: '0.125rem 0.375rem',\n\t\t\t\t\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tSave up to 20%\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Plans Grid */}\n\t\t\t<div style={containerStyles}>\n\t\t\t\t{plans.map((plan) => {\n\t\t\t\t\tconst isHighlighted = plan.slug === highlightPlan || plan.slug === 'pro'\n\t\t\t\t\tconst isCurrentPlan = subscription?.planSlug === plan.slug\n\t\t\t\t\tconst price = getPlanPrice(plan, interval)\n\t\t\t\t\tconst annualSavings = interval === 'monthly' ? getAnnualSavings(plan) : 0\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div key={plan.id} style={planCardStyles(isHighlighted)}>\n\t\t\t\t\t\t\t{/* Popular Badge */}\n\t\t\t\t\t\t\t{isHighlighted && <div style={badgeStyles}>Most Popular</div>}\n\n\t\t\t\t\t\t\t{/* Plan Header */}\n\t\t\t\t\t\t\t<div style={{ marginBottom: '1rem' }}>\n\t\t\t\t\t\t\t\t<h3\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeLg,\n\t\t\t\t\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\t\t\t\t\tmarginBottom: '0.25rem',\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{plan.name}\n\t\t\t\t\t\t\t\t</h3>\n\t\t\t\t\t\t\t\t{plan.description && (\n\t\t\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{plan.description}\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t{/* Price */}\n\t\t\t\t\t\t\t<div style={{ marginBottom: '1rem' }}>\n\t\t\t\t\t\t\t\t<span style={priceStyles}>\n\t\t\t\t\t\t\t\t\t{price === 0 ? (\n\t\t\t\t\t\t\t\t\t\t'Free'\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t${(price / 100).toFixed(price % 100 === 0 ? 0 : 2)}\n\t\t\t\t\t\t\t\t\t\t\t<span style={intervalTextStyles}>\n\t\t\t\t\t\t\t\t\t\t\t\t/\n\t\t\t\t\t\t\t\t\t\t\t\t{interval === 'lifetime'\n\t\t\t\t\t\t\t\t\t\t\t\t\t? 'lifetime'\n\t\t\t\t\t\t\t\t\t\t\t\t\t: interval === 'annual'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? 'year'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: 'mo'}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t{annualSavings > 0 && showAnnualSavings && (\n\t\t\t\t\t\t\t\t\t<div style={{ marginTop: '0.5rem' }}>\n\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorSuccess,\n\t\t\t\t\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\tSwitch to annual, save {annualSavings}%\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t{/* Features */}\n\t\t\t\t\t\t\t<ul style={featureListStyles}>\n\t\t\t\t\t\t\t\t{plan.features?.map((feature: string, index: number) => (\n\t\t\t\t\t\t\t\t\t<li key={index} style={featureItemStyles}>\n\t\t\t\t\t\t\t\t\t\t<CheckIcon color={theme.colorSuccess} size={18} />\n\t\t\t\t\t\t\t\t\t\t<span>{feature}</span>\n\t\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</ul>\n\n\t\t\t\t\t\t\t{/* CTA Button */}\n\t\t\t\t\t\t\t{isCurrentPlan ? (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline, styles.buttonFullWidth, {\n\t\t\t\t\t\t\t\t\t\tcursor: 'default',\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<CheckIcon color={theme.colorSuccess} size={16} />\n\t\t\t\t\t\t\t\t\tCurrent Plan\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t) : price === 0 ? (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tdisabled\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\t\t\t\t\tstyles.buttonOutline,\n\t\t\t\t\t\t\t\t\t\tstyles.buttonFullWidth,\n\t\t\t\t\t\t\t\t\t\tstyles.buttonDisabled,\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tFree Plan\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tonClick={() => handleCheckout(plan.slug)}\n\t\t\t\t\t\t\t\t\tdisabled={loadingPlan !== null}\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\t\t\t\t\tisHighlighted ? styles.buttonPrimary : styles.buttonOutline,\n\t\t\t\t\t\t\t\t\t\tstyles.buttonFullWidth,\n\t\t\t\t\t\t\t\t\t\tloadingPlan !== null ? styles.buttonDisabled : {},\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{loadingPlan === plan.slug ? (\n\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t\t\t\t\t\t\tProcessing...\n\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t) : isPremium ? (\n\t\t\t\t\t\t\t\t\t\t'Switch Plan'\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t'Get Started'\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)\n\t\t\t\t})}\n\t\t\t</div>\n\n\t\t\t{/* Feature Comparison Table */}\n\t\t\t{showFeatureComparison && plans.length > 1 && (\n\t\t\t\t<div style={{ marginTop: '3rem' }}>\n\t\t\t\t\t<h3 style={mergeStyles(styles.textCenter, { marginBottom: '1.5rem' })}>Compare Plans</h3>\n\t\t\t\t\t<FeatureComparisonTable plans={plans} theme={theme} />\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n// Feature comparison table component\nfunction FeatureComparisonTable({\n\tplans,\n\ttheme,\n}: {\n\tplans: ReadonlyArray<{ name: string; features?: readonly string[] | null }>\n\ttheme: ThemeVariables\n}) {\n\t// Extract all unique features across plans\n\tconst allFeatures = Array.from(new Set(plans.flatMap((p) => p.features || [])))\n\n\tconst cellStyles: React.CSSProperties = {\n\t\tpadding: '0.75rem 1rem',\n\t\tborderBottom: `1px solid ${theme.colorBorder}`,\n\t\tfontSize: theme.fontSizeSm,\n\t}\n\n\tconst headerCellStyles: React.CSSProperties = {\n\t\t...cellStyles,\n\t\tfontWeight: 600,\n\t\tbackgroundColor: theme.colorMuted,\n\t}\n\n\treturn (\n\t\t<table\n\t\t\tstyle={{\n\t\t\t\twidth: '100%',\n\t\t\t\tborderCollapse: 'collapse',\n\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\toverflow: 'hidden',\n\t\t\t}}\n\t\t>\n\t\t\t<thead>\n\t\t\t\t<tr>\n\t\t\t\t\t<th style={headerCellStyles}>Feature</th>\n\t\t\t\t\t{plans.map((plan) => (\n\t\t\t\t\t\t<th key={plan.name} style={mergeStyles(headerCellStyles, { textAlign: 'center' })}>\n\t\t\t\t\t\t\t{plan.name}\n\t\t\t\t\t\t</th>\n\t\t\t\t\t))}\n\t\t\t\t</tr>\n\t\t\t</thead>\n\t\t\t<tbody>\n\t\t\t\t{allFeatures.map((feature, index) => (\n\t\t\t\t\t<tr key={index}>\n\t\t\t\t\t\t<td style={cellStyles}>{feature}</td>\n\t\t\t\t\t\t{plans.map((plan) => (\n\t\t\t\t\t\t\t<td key={plan.name} style={mergeStyles(cellStyles, { textAlign: 'center' })}>\n\t\t\t\t\t\t\t\t{plan.features?.includes(feature) ? (\n\t\t\t\t\t\t\t\t\t<CheckIcon color={theme.colorSuccess} size={18} />\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<XIcon color={theme.colorMutedForeground} size={18} />\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</tr>\n\t\t\t\t))}\n\t\t\t</tbody>\n\t\t</table>\n\t)\n}\n\nfunction CheckIcon({ color, size = 24 }: { color: string; size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tstyle={{ flexShrink: 0 }}\n\t\t>\n\t\t\t<path d=\"M20 6 9 17l-5-5\" />\n\t\t</svg>\n\t)\n}\n\nfunction XIcon({ color, size = 24 }: { color: string; size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tstyle={{ flexShrink: 0 }}\n\t\t>\n\t\t\t<path d=\"M18 6 6 18\" />\n\t\t\t<path d=\"m6 6 12 12\" />\n\t\t</svg>\n\t)\n}\n\nfunction RefreshIcon({ color, size = 24 }: { color: string; size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tstyle={{ flexShrink: 0, marginRight: '0.25rem' }}\n\t\t>\n\t\t\t<path d=\"M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" />\n\t\t\t<path d=\"M3 3v5h5\" />\n\t\t\t<path d=\"M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16\" />\n\t\t\t<path d=\"M16 16h5v5\" />\n\t\t</svg>\n\t)\n}\n","/**\n * ResetPassword Component\n *\n * Allows users to set a new password using a reset token.\n * Matches Clerk's ResetPassword component API.\n */\n\n'use client'\n\nimport { type FormEvent, useCallback, useEffect, useId, useState } from 'react'\nimport { UI_COPY_FEEDBACK_MS } from '../../constants'\nimport { useSafeAuth, useSafeUser, useSdkReady } from '../hooks'\nimport { safeRedirect } from '../security-utils'\nimport {\n\tbaseStyles,\n\tdefaultTheme,\n\tinjectGlobalStyles,\n\tmergeStyles,\n\ttype ThemeVariables,\n} from '../ui/styles'\n\nexport interface ResetPasswordProps {\n\t/** Password reset token (usually from URL) */\n\ttoken?: string\n\t/** URL to redirect after successful reset */\n\tafterResetUrl?: string\n\t/** URL for sign in link */\n\tsignInUrl?: string\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Called on successful reset */\n\tonSuccess?: () => void\n\t/** Called on error */\n\tonError?: (error: string) => void\n\t/** Show card wrapper */\n\tshowCard?: boolean\n\t/** Custom header content */\n\theader?: React.ReactNode\n}\n\n/**\n * ResetPassword component for setting a new password\n *\n * @example\n * ```tsx\n * // On /reset-password?token=xxx page\n * const searchParams = useSearchParams()\n * const token = searchParams.get('token')\n *\n * <ResetPassword\n *   token={token}\n *   afterResetUrl=\"/sign-in\"\n * />\n * ```\n */\nexport function ResetPassword({\n\ttoken,\n\tafterResetUrl = '/sign-in',\n\tsignInUrl = '/sign-in',\n\ttheme = defaultTheme,\n\tonSuccess,\n\tonError,\n\tshowCard = true,\n\theader,\n}: ResetPasswordProps) {\n\t// SDK readiness check (SSOT for SSR safety and configuration)\n\tconst { isReady, renderError } = useSdkReady({\n\t\tservices: ['auth', 'user'],\n\t\tcomponentType: 'auth',\n\t\ttheme,\n\t})\n\n\tconst { resetPassword } = useSafeAuth()\n\tconst { isSignedIn, isLoaded } = useSafeUser()\n\tconst styles = baseStyles(theme)\n\tconst passwordId = useId()\n\tconst confirmPasswordId = useId()\n\n\tconst [password, setPassword] = useState('')\n\tconst [confirmPassword, setConfirmPassword] = useState('')\n\tconst [error, setError] = useState<string | null>(null)\n\tconst [isLoading, setIsLoading] = useState(false)\n\tconst [isSuccess, setIsSuccess] = useState(false)\n\tconst [focusedField, setFocusedField] = useState<string | null>(null)\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tconst handleSubmit = useCallback(\n\t\tasync (e: FormEvent) => {\n\t\t\te.preventDefault()\n\t\t\tsetError(null)\n\n\t\t\t// Validate passwords match\n\t\t\tif (password !== confirmPassword) {\n\t\t\t\tsetError('Passwords do not match')\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Validate password length (NIST SP 800-63B recommends 12+ chars)\n\t\t\tif (password.length < 12) {\n\t\t\t\tsetError('Password must be at least 12 characters')\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (!token) {\n\t\t\t\tsetError('Missing reset token')\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tsetIsLoading(true)\n\n\t\t\ttry {\n\t\t\t\tif (!resetPassword) {\n\t\t\t\t\tthrow new Error('Authentication not configured')\n\t\t\t\t}\n\t\t\t\tawait resetPassword({ token, newPassword: password })\n\t\t\t\tsetIsSuccess(true)\n\t\t\t\tonSuccess?.()\n\n\t\t\t\t// Redirect after short delay\n\t\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tsafeRedirect(afterResetUrl, { fallback: '/sign-in' })\n\t\t\t\t\t}, UI_COPY_FEEDBACK_MS)\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : 'Failed to reset password'\n\t\t\t\tsetError(message)\n\t\t\t\tonError?.(message)\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[token, password, confirmPassword, resetPassword, afterResetUrl, onSuccess, onError],\n\t)\n\n\t// SDK not ready - render error or null\n\tif (!isReady) {\n\t\treturn renderError()\n\t}\n\n\t// Redirect if already signed in\n\tif (isLoaded && isSignedIn) {\n\t\tif (typeof window !== 'undefined') {\n\t\t\tsafeRedirect(afterResetUrl, { fallback: '/sign-in' })\n\t\t}\n\t\treturn null\n\t}\n\n\t// Show error if no token\n\tif (!token) {\n\t\treturn (\n\t\t\t<div style={showCard ? styles.card : {}}>\n\t\t\t\t<div style={styles.container}>\n\t\t\t\t\t<div style={mergeStyles(styles.cardHeader, styles.textCenter)}>\n\t\t\t\t\t\t<h2 style={styles.cardTitle}>Invalid reset link</h2>\n\t\t\t\t\t\t<p style={styles.cardDescription}>\n\t\t\t\t\t\t\tThis password reset link is invalid or has expired.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div style={styles.cardContent}>\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\thref={signInUrl}\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary, styles.buttonFullWidth)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tBack to sign in\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t)\n\t}\n\n\tconst renderForm = () => {\n\t\tif (isSuccess) {\n\t\t\treturn (\n\t\t\t\t<div style={styles.textCenter}>\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={mergeStyles(styles.flexCenter, {\n\t\t\t\t\t\t\twidth: '3rem',\n\t\t\t\t\t\t\theight: '3rem',\n\t\t\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\t\t\tbackgroundColor: `${theme.colorSuccess}15`,\n\t\t\t\t\t\t\tmargin: '0 auto 1rem',\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t<CheckIcon color={theme.colorSuccess} />\n\t\t\t\t\t</div>\n\t\t\t\t\t<h3 style={mergeStyles(styles.cardTitle, styles.mb2)}>Password reset!</h3>\n\t\t\t\t\t<p style={mergeStyles(styles.textMuted, styles.textSm, styles.mb4)}>\n\t\t\t\t\t\tYour password has been updated. Redirecting to sign in...\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t)\n\t\t}\n\n\t\treturn (\n\t\t\t<form onSubmit={handleSubmit}>\n\t\t\t\t<div style={styles.formGroup}>\n\t\t\t\t\t<label htmlFor={passwordId} style={styles.label}>\n\t\t\t\t\t\tNew password\n\t\t\t\t\t</label>\n\t\t\t\t\t<input\n\t\t\t\t\t\tid={passwordId}\n\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\tvalue={password}\n\t\t\t\t\t\tonChange={(e) => {\n\t\t\t\t\t\t\tsetPassword(e.target.value)\n\t\t\t\t\t\t\tsetError(null)\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonFocus={() => setFocusedField('password')}\n\t\t\t\t\t\tonBlur={() => setFocusedField(null)}\n\t\t\t\t\t\tplaceholder=\"••••••••\"\n\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\tautoComplete=\"new-password\"\n\t\t\t\t\t\trequired\n\t\t\t\t\t\tminLength={12}\n\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\tstyles.input,\n\t\t\t\t\t\t\tfocusedField === 'password' ? styles.inputFocus : {},\n\t\t\t\t\t\t\tisLoading ? styles.inputDisabled : {},\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t\t<p style={mergeStyles(styles.textXs, styles.textMuted, styles.mt1)}>\n\t\t\t\t\t\tMust be at least 12 characters\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\n\t\t\t\t<div style={styles.formGroup}>\n\t\t\t\t\t<label htmlFor={confirmPasswordId} style={styles.label}>\n\t\t\t\t\t\tConfirm password\n\t\t\t\t\t</label>\n\t\t\t\t\t<input\n\t\t\t\t\t\tid={confirmPasswordId}\n\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\tvalue={confirmPassword}\n\t\t\t\t\t\tonChange={(e) => {\n\t\t\t\t\t\t\tsetConfirmPassword(e.target.value)\n\t\t\t\t\t\t\tsetError(null)\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonFocus={() => setFocusedField('confirmPassword')}\n\t\t\t\t\t\tonBlur={() => setFocusedField(null)}\n\t\t\t\t\t\tplaceholder=\"••••••••\"\n\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\tautoComplete=\"new-password\"\n\t\t\t\t\t\trequired\n\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\tstyles.input,\n\t\t\t\t\t\t\tfocusedField === 'confirmPassword' ? styles.inputFocus : {},\n\t\t\t\t\t\t\tisLoading ? styles.inputDisabled : {},\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\n\t\t\t\t{error && <div style={mergeStyles(styles.alert, styles.alertError)}>{error}</div>}\n\n\t\t\t\t<button\n\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\tstyles.buttonPrimary,\n\t\t\t\t\t\tstyles.buttonFullWidth,\n\t\t\t\t\t\tisLoading ? styles.buttonDisabled : {},\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t{isLoading ? (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t\t\tResetting...\n\t\t\t\t\t\t</>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t'Reset password'\n\t\t\t\t\t)}\n\t\t\t\t</button>\n\n\t\t\t\t<p style={mergeStyles(styles.textCenter, styles.textSm, styles.textMuted, styles.mt4)}>\n\t\t\t\t\t<a href={signInUrl} style={styles.link}>\n\t\t\t\t\t\tBack to sign in\n\t\t\t\t\t</a>\n\t\t\t\t</p>\n\t\t\t</form>\n\t\t)\n\t}\n\n\tconst content = (\n\t\t<div style={styles.container}>\n\t\t\t{header || (\n\t\t\t\t<div style={mergeStyles(styles.cardHeader, styles.textCenter)}>\n\t\t\t\t\t<h2 style={styles.cardTitle}>Reset password</h2>\n\t\t\t\t\t<p style={styles.cardDescription}>Enter your new password</p>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<div style={styles.cardContent}>{renderForm()}</div>\n\t\t</div>\n\t)\n\n\tif (showCard) {\n\t\treturn <div style={styles.card}>{content}</div>\n\t}\n\n\treturn content\n}\n\nfunction CheckIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"24\"\n\t\t\theight=\"24\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M20 6 9 17l-5-5\" />\n\t\t</svg>\n\t)\n}\n","/**\n * SignIn Component\n *\n * Flexible sign-in component supporting redirect, embedded, and modal modes.\n */\n\n'use client'\n\nimport { useState } from 'react'\nimport type { OAuthProviderId } from '../../types'\nimport { useSafeAuth, useSafeUser, useSdkReady } from '../hooks'\nimport {\n\tdefaultTheme,\n\tModal,\n\ttype OAuthProvider,\n\tSignInForm,\n\ttype SignInMethod,\n\ttype ThemeVariables,\n} from '../ui'\n\n// Re-export for convenience\n\nexport interface SignInProps {\n\t/** URL to redirect to after successful sign in */\n\tafterSignInUrl?: string\n\t/**\n\t * Display mode:\n\t * - 'redirect': Navigate to platform login page (default)\n\t * - 'embedded': Show full sign-in form inline\n\t * - 'modal': Show full sign-in form in a modal\n\t */\n\tmode?: 'redirect' | 'embedded' | 'modal'\n\t/**\n\t * OAuth providers to show (SDK-level filtering)\n\t * This further filters the providers enabled at platform and app level.\n\t * - undefined/null = show all app-enabled providers\n\t * - [] = hide OAuth section (email only)\n\t * - ['google', 'github'] = only show these (if they're app-enabled)\n\t */\n\tproviders?: OAuthProviderId[] | null\n\t/**\n\t * Auth methods to enable for embedded/modal mode\n\t * Default: ['password']\n\t */\n\tmethods?: SignInMethod[]\n\t/** Theme variables for embedded/modal mode */\n\ttheme?: ThemeVariables\n\t/** Custom appearance for redirect button */\n\tappearance?: {\n\t\tbaseStyle?: React.CSSProperties\n\t\thoverStyle?: React.CSSProperties\n\t}\n\t/** Custom class name */\n\tclassName?: string\n\t/** Button content (for redirect mode) */\n\tchildren?: React.ReactNode\n\t/** URL for sign up link (embedded/modal mode) */\n\tsignUpUrl?: string\n\t/** URL for forgot password (embedded/modal mode) */\n\tforgotPasswordUrl?: string\n\t/** Called on successful sign in */\n\tonSuccess?: () => void\n\t/** Called on error */\n\tonError?: (error: string) => void\n\t/** Show card wrapper (embedded mode, default: true) */\n\tshowCard?: boolean\n}\n\n/**\n * SignIn component with multiple display modes\n *\n * @example\n * ```tsx\n * // Redirect mode (default) - navigates to platform login\n * <SignIn afterSignInUrl=\"/dashboard\" />\n *\n * // Embedded mode - shows full form inline\n * <SignIn mode=\"embedded\" afterSignInUrl=\"/dashboard\" />\n *\n * // Modal mode - shows form in a modal (for buttons)\n * <SignIn mode=\"modal\" afterSignInUrl=\"/dashboard\">\n *   Click to Sign In\n * </SignIn>\n *\n * // With specific OAuth providers\n * <SignIn mode=\"embedded\" providers={['google', 'github']} />\n *\n * // Email/password only\n * <SignIn mode=\"embedded\" providers={[]} />\n * ```\n */\nexport function SignIn({\n\tafterSignInUrl,\n\tmode = 'redirect',\n\tproviders,\n\tmethods = ['password'],\n\ttheme = defaultTheme,\n\tappearance,\n\tclassName,\n\tchildren,\n\tsignUpUrl = '/sign-up',\n\tforgotPasswordUrl = '/forgot-password',\n\tonSuccess,\n\tonError,\n\tshowCard = true,\n}: SignInProps) {\n\t// SDK readiness check (SSOT for SSR safety and configuration)\n\tconst { isReady, renderError } = useSdkReady({\n\t\tservices: ['auth', 'user'],\n\t\tcomponentType: 'sign-in',\n\t\ttheme,\n\t})\n\n\tconst { signIn } = useSafeAuth()\n\tconst { isSignedIn, isLoaded } = useSafeUser()\n\tconst [modalOpen, setModalOpen] = useState(false)\n\n\t// SDK not ready - render error or null\n\tif (!isReady) {\n\t\treturn renderError()\n\t}\n\n\t// Don't show if already signed in\n\tif (isLoaded && isSignedIn) {\n\t\treturn null\n\t}\n\n\t// Convert OAuthProviderId to OAuthProvider (compatible types)\n\tconst oauthProviders = providers as OAuthProvider[] | undefined | null\n\n\t// Redirect mode - show button that navigates to platform\n\tif (mode === 'redirect') {\n\t\tconst handleClick = () => {\n\t\t\tsignIn({\n\t\t\t\tredirectUrl: afterSignInUrl || window.location.href,\n\t\t\t\tproviders,\n\t\t\t})\n\t\t}\n\n\t\tconst defaultStyles: React.CSSProperties = {\n\t\t\tdisplay: 'inline-flex',\n\t\t\talignItems: 'center',\n\t\t\tjustifyContent: 'center',\n\t\t\tpadding: '0.5rem 1rem',\n\t\t\tfontSize: '0.875rem',\n\t\t\tfontWeight: 500,\n\t\t\tborderRadius: '0.375rem',\n\t\t\tborder: '1px solid transparent',\n\t\t\tbackgroundColor: '#000',\n\t\t\tcolor: '#fff',\n\t\t\tcursor: 'pointer',\n\t\t\ttransition: 'opacity 0.2s',\n\t\t\t...appearance?.baseStyle,\n\t\t}\n\n\t\treturn (\n\t\t\t<button\n\t\t\t\tonClick={handleClick}\n\t\t\t\tclassName={className}\n\t\t\t\tstyle={className ? undefined : defaultStyles}\n\t\t\t\ttype=\"button\"\n\t\t\t>\n\t\t\t\t{children || 'Sign In'}\n\t\t\t</button>\n\t\t)\n\t}\n\n\t// Embedded mode - show form inline\n\tif (mode === 'embedded') {\n\t\treturn (\n\t\t\t<SignInForm\n\t\t\t\ttheme={theme}\n\t\t\t\tmethods={methods}\n\t\t\t\tproviders={oauthProviders || []}\n\t\t\t\tafterSignInUrl={afterSignInUrl || '/dashboard'}\n\t\t\t\tsignUpUrl={signUpUrl}\n\t\t\t\tforgotPasswordUrl={forgotPasswordUrl}\n\t\t\t\tonSuccess={onSuccess}\n\t\t\t\tonError={onError}\n\t\t\t\tshowCard={showCard}\n\t\t\t/>\n\t\t)\n\t}\n\n\t// Modal mode - show button that opens modal\n\tif (mode === 'modal') {\n\t\tconst defaultStyles: React.CSSProperties = {\n\t\t\tdisplay: 'inline-flex',\n\t\t\talignItems: 'center',\n\t\t\tjustifyContent: 'center',\n\t\t\tpadding: '0.5rem 1rem',\n\t\t\tfontSize: '0.875rem',\n\t\t\tfontWeight: 500,\n\t\t\tborderRadius: '0.375rem',\n\t\t\tborder: '1px solid transparent',\n\t\t\tbackgroundColor: '#000',\n\t\t\tcolor: '#fff',\n\t\t\tcursor: 'pointer',\n\t\t\ttransition: 'opacity 0.2s',\n\t\t\t...appearance?.baseStyle,\n\t\t}\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<button\n\t\t\t\t\tonClick={() => setModalOpen(true)}\n\t\t\t\t\tclassName={className}\n\t\t\t\t\tstyle={className ? undefined : defaultStyles}\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t>\n\t\t\t\t\t{children || 'Sign In'}\n\t\t\t\t</button>\n\t\t\t\t<Modal open={modalOpen} onClose={() => setModalOpen(false)} theme={theme}>\n\t\t\t\t\t<SignInForm\n\t\t\t\t\t\ttheme={theme}\n\t\t\t\t\t\tmethods={methods}\n\t\t\t\t\t\tproviders={oauthProviders || []}\n\t\t\t\t\t\tafterSignInUrl={afterSignInUrl || '/dashboard'}\n\t\t\t\t\t\tsignUpUrl={signUpUrl}\n\t\t\t\t\t\tforgotPasswordUrl={forgotPasswordUrl}\n\t\t\t\t\t\tonSuccess={() => {\n\t\t\t\t\t\t\tsetModalOpen(false)\n\t\t\t\t\t\t\tonSuccess?.()\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonError={onError}\n\t\t\t\t\t\tshowCard={false}\n\t\t\t\t\t/>\n\t\t\t\t</Modal>\n\t\t\t</>\n\t\t)\n\t}\n\n\treturn null\n}\n","/**\n * SignIn Form Component\n *\n * Full embedded sign-in form with email/password and OAuth support.\n * Self-contained with CSS-in-JS styles.\n *\n * NOW USES useSignInForm hook (dogfooding).\n */\n\n'use client'\n\nimport { useEffect } from 'react'\nimport { RequireSdk } from '../hooks'\nimport { type SignInMethod, useSignInForm } from '../hooks/use-sign-in-form'\nimport { OAuthButtons, type OAuthProvider, OrDivider } from './oauth-buttons'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\nexport type { SignInMethod } from '../hooks/use-sign-in-form'\n\nexport interface SignInFormProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Available auth methods */\n\tmethods?: SignInMethod[]\n\t/** OAuth providers to show */\n\tproviders?: OAuthProvider[]\n\t/** URL to redirect after sign in */\n\tafterSignInUrl?: string\n\t/** URL for sign up link */\n\tsignUpUrl?: string\n\t/** URL for forgot password link */\n\tforgotPasswordUrl?: string\n\t/** Called on successful sign in */\n\tonSuccess?: () => void\n\t/** Called on error */\n\tonError?: (error: string) => void\n\t/** Custom header content */\n\theader?: React.ReactNode\n\t/** Custom footer content */\n\tfooter?: React.ReactNode\n\t/** Hide the sign up link */\n\thideSignUpLink?: boolean\n\t/** Hide the forgot password link */\n\thideForgotPassword?: boolean\n\t/** Show the card wrapper (default: true) */\n\tshowCard?: boolean\n}\n\n/**\n * Full sign-in form component (uses useSignInForm hook)\n */\nexport function SignInForm(props: SignInFormProps) {\n\treturn (\n\t\t<RequireSdk services={['auth']} componentType=\"sign-in\" theme={props.theme}>\n\t\t\t<SignInFormInner {...props} />\n\t\t</RequireSdk>\n\t)\n}\n\n/** Inner component that safely uses platform hooks */\nfunction SignInFormInner({\n\ttheme = defaultTheme,\n\tmethods = ['password'],\n\tproviders = [],\n\tafterSignInUrl = '/dashboard',\n\tsignUpUrl = '/signup',\n\tforgotPasswordUrl = '/forgot-password',\n\tonSuccess,\n\tonError,\n\theader,\n\tfooter,\n\thideSignUpLink = false,\n\thideForgotPassword = false,\n\tshowCard = true,\n}: SignInFormProps) {\n\tconst styles = baseStyles(theme)\n\n\t// Use the headless hook (dogfooding!)\n\tconst {\n\t\tform,\n\t\tsetEmail,\n\t\tsetPassword,\n\t\tsetOtp,\n\t\tstep,\n\t\tsetStep,\n\t\tisLoading,\n\t\tloadingProvider,\n\t\terror,\n\t\thandlePasswordSubmit,\n\t\thandleOAuthSignIn,\n\t\thandleMagicLinkRequest,\n\t\thandleOtpRequest,\n\t\thandleOtpVerify,\n\t} = useSignInForm({\n\t\tmethods,\n\t\tproviders,\n\t\tafterSignInUrl,\n\t\tonSuccess: () => {\n\t\t\tonSuccess?.()\n\t\t},\n\t\tonError,\n\t})\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// Render input with theme and accessibility\n\tconst renderInput = (\n\t\ttype: string,\n\t\tname: 'email' | 'password' | 'otp',\n\t\tplaceholder: string,\n\t\tvalue: string,\n\t\tonChange: (value: string) => void,\n\t\toptions?: {\n\t\t\tautoComplete?: string\n\t\t\trequired?: boolean\n\t\t\tminLength?: number\n\t\t\tautoFocus?: boolean\n\t\t},\n\t) => {\n\t\t// Generate unique ID for label association\n\t\tconst inputId = `signin-${name}`\n\t\treturn (\n\t\t\t<input\n\t\t\t\tid={inputId}\n\t\t\t\ttype={type}\n\t\t\t\tname={name}\n\t\t\t\tvalue={value}\n\t\t\t\tonChange={(e) => onChange(e.target.value)}\n\t\t\t\tplaceholder={placeholder}\n\t\t\t\tdisabled={isLoading}\n\t\t\t\tautoComplete={options?.autoComplete}\n\t\t\t\trequired={options?.required !== false}\n\t\t\t\tminLength={options?.minLength}\n\t\t\t\taria-describedby={name === 'otp' ? 'otp-hint' : undefined}\n\t\t\t\tstyle={mergeStyles(styles.input, isLoading ? styles.inputDisabled : {})}\n\t\t\t/>\n\t\t)\n\t}\n\n\t// Render error alert with accessibility\n\tconst renderError = () => {\n\t\treturn (\n\t\t\t<div aria-live=\"assertive\" aria-atomic=\"true\">\n\t\t\t\t{error && (\n\t\t\t\t\t<div role=\"alert\" style={mergeStyles(styles.alert, styles.alertError)}>\n\t\t\t\t\t\t{error}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t)\n\t}\n\n\t// Render submit button\n\tconst renderButton = (text: string, loadingText: string, onClick?: () => void) => {\n\t\tconst buttonProps = onClick ? { type: 'button' as const, onClick } : { type: 'submit' as const }\n\n\t\treturn (\n\t\t\t<button\n\t\t\t\t{...buttonProps}\n\t\t\t\tdisabled={isLoading}\n\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\tstyles.button,\n\t\t\t\t\tstyles.buttonPrimary,\n\t\t\t\t\tstyles.buttonFullWidth,\n\t\t\t\t\tisLoading ? styles.buttonDisabled : {},\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{isLoading ? (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t\t{loadingText}\n\t\t\t\t\t</>\n\t\t\t\t) : (\n\t\t\t\t\ttext\n\t\t\t\t)}\n\t\t\t</button>\n\t\t)\n\t}\n\n\t// Method tabs\n\tconst renderMethodTabs = () => {\n\t\tif (methods.length <= 1) return null\n\n\t\treturn (\n\t\t\t<div style={styles.tabs}>\n\t\t\t\t{methods.includes('password') && (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={() => setStep('password')}\n\t\t\t\t\t\tstyle={mergeStyles(styles.tab, step === 'password' ? styles.tabActive : {})}\n\t\t\t\t\t>\n\t\t\t\t\t\tPassword\n\t\t\t\t\t</button>\n\t\t\t\t)}\n\t\t\t\t{methods.includes('magic-link') && (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={() => setStep('email')}\n\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\tstyles.tab,\n\t\t\t\t\t\t\tstep === 'email' || step === 'magic-link-sent' ? styles.tabActive : {},\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\tMagic Link\n\t\t\t\t\t</button>\n\t\t\t\t)}\n\t\t\t\t{methods.includes('otp') && (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={() => setStep('email')}\n\t\t\t\t\t\tstyle={mergeStyles(styles.tab, step === 'otp' ? styles.tabActive : {})}\n\t\t\t\t\t>\n\t\t\t\t\t\tEmail Code\n\t\t\t\t\t</button>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t)\n\t}\n\n\t// Render password form\n\tconst renderPasswordForm = () => (\n\t\t<form onSubmit={handlePasswordSubmit}>\n\t\t\t<div style={styles.formGroup}>\n\t\t\t\t<label htmlFor=\"signin-email\" style={styles.label}>\n\t\t\t\t\tEmail\n\t\t\t\t</label>\n\t\t\t\t{renderInput('email', 'email', 'you@example.com', form.email, setEmail, {\n\t\t\t\t\tautoComplete: 'email',\n\t\t\t\t})}\n\t\t\t</div>\n\t\t\t<div style={styles.formGroup}>\n\t\t\t\t<div style={styles.flexBetween}>\n\t\t\t\t\t<label htmlFor=\"signin-password\" style={styles.label}>\n\t\t\t\t\t\tPassword\n\t\t\t\t\t</label>\n\t\t\t\t\t{!hideForgotPassword && (\n\t\t\t\t\t\t<a href={forgotPasswordUrl} style={mergeStyles(styles.link, styles.textSm)}>\n\t\t\t\t\t\t\tForgot password?\n\t\t\t\t\t\t</a>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t{renderInput('password', 'password', '••••••••', form.password, setPassword, {\n\t\t\t\t\tautoComplete: 'current-password',\n\t\t\t\t\tminLength: 12,\n\t\t\t\t})}\n\t\t\t</div>\n\t\t\t{renderError()}\n\t\t\t{renderButton('Sign In', 'Signing in...')}\n\t\t</form>\n\t)\n\n\t// Render magic link form\n\tconst _renderMagicLinkForm = () => (\n\t\t<form onSubmit={handleMagicLinkRequest}>\n\t\t\t<div style={styles.formGroup}>\n\t\t\t\t<label htmlFor=\"signin-email\" style={styles.label}>\n\t\t\t\t\tEmail\n\t\t\t\t</label>\n\t\t\t\t{renderInput('email', 'email', 'you@example.com', form.email, setEmail, {\n\t\t\t\t\tautoComplete: 'email',\n\t\t\t\t})}\n\t\t\t</div>\n\t\t\t{renderError()}\n\t\t\t{renderButton('Send Magic Link', 'Sending...')}\n\t\t</form>\n\t)\n\n\t// Render magic link sent message\n\tconst renderMagicLinkSent = () => (\n\t\t<div style={styles.textCenter}>\n\t\t\t<div\n\t\t\t\tstyle={mergeStyles(styles.flexCenter, {\n\t\t\t\t\twidth: '3rem',\n\t\t\t\t\theight: '3rem',\n\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\tbackgroundColor: `${theme.colorSuccess}15`,\n\t\t\t\t\tmargin: '0 auto 1rem',\n\t\t\t\t})}\n\t\t\t>\n\t\t\t\t<MailIcon color={theme.colorSuccess} />\n\t\t\t</div>\n\t\t\t<h3 style={mergeStyles(styles.cardTitle, styles.mb2)}>Check your email</h3>\n\t\t\t<p style={mergeStyles(styles.textMuted, styles.textSm, styles.mb4)}>\n\t\t\t\tWe sent a magic link to <strong>{form.email}</strong>\n\t\t\t</p>\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tonClick={() => setStep('email')}\n\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline, styles.buttonFullWidth)}\n\t\t\t>\n\t\t\t\tUse different email\n\t\t\t</button>\n\t\t</div>\n\t)\n\n\t// Render OTP form\n\tconst renderOTPForm = () => (\n\t\t<form onSubmit={handleOtpVerify}>\n\t\t\t<div style={styles.formGroup}>\n\t\t\t\t<label htmlFor=\"signin-otp\" style={styles.label}>\n\t\t\t\t\tEnter verification code\n\t\t\t\t</label>\n\t\t\t\t<p id=\"otp-hint\" style={mergeStyles(styles.textMuted, styles.textSm, styles.mb2)}>\n\t\t\t\t\tSent to {form.email}\n\t\t\t\t</p>\n\t\t\t\t{renderInput('text', 'otp', '000000', form.otp, setOtp, {\n\t\t\t\t\tautoComplete: 'one-time-code',\n\t\t\t\t\tautoFocus: true,\n\t\t\t\t})}\n\t\t\t</div>\n\t\t\t{renderError()}\n\t\t\t{renderButton('Verify', 'Verifying...')}\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tonClick={() => setStep('email')}\n\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonGhost, styles.buttonFullWidth, styles.mt2)}\n\t\t\t>\n\t\t\t\tUse different email\n\t\t\t</button>\n\t\t</form>\n\t)\n\n\t// Render email form for OTP request\n\tconst renderEmailForm = () => (\n\t\t<form\n\t\t\tonSubmit={(e) => {\n\t\t\t\te.preventDefault()\n\t\t\t\tif (methods.includes('otp')) {\n\t\t\t\t\thandleOtpRequest()\n\t\t\t\t} else if (methods.includes('magic-link')) {\n\t\t\t\t\thandleMagicLinkRequest(e)\n\t\t\t\t}\n\t\t\t}}\n\t\t>\n\t\t\t<div style={styles.formGroup}>\n\t\t\t\t<label htmlFor=\"signin-email\" style={styles.label}>\n\t\t\t\t\tEmail\n\t\t\t\t</label>\n\t\t\t\t{renderInput('email', 'email', 'you@example.com', form.email, setEmail, {\n\t\t\t\t\tautoComplete: 'email',\n\t\t\t\t})}\n\t\t\t</div>\n\t\t\t{renderError()}\n\t\t\t{renderButton(methods.includes('otp') ? 'Send Code' : 'Send Magic Link', 'Sending...')}\n\t\t</form>\n\t)\n\n\t// Main content based on step\n\tconst renderContent = () => {\n\t\tswitch (step) {\n\t\t\tcase 'password':\n\t\t\t\treturn renderPasswordForm()\n\t\t\tcase 'email':\n\t\t\t\treturn renderEmailForm()\n\t\t\tcase 'magic-link-sent':\n\t\t\t\treturn renderMagicLinkSent()\n\t\t\tcase 'otp':\n\t\t\t\treturn renderOTPForm()\n\t\t\tdefault:\n\t\t\t\treturn renderPasswordForm()\n\t\t}\n\t}\n\n\t// Full form content\n\tconst content = (\n\t\t<div style={styles.container}>\n\t\t\t{/* Header */}\n\t\t\t{header || (\n\t\t\t\t<div style={mergeStyles(styles.cardHeader, styles.textCenter)}>\n\t\t\t\t\t<h2 style={styles.cardTitle}>Welcome back</h2>\n\t\t\t\t\t<p style={styles.cardDescription}>Sign in to your account to continue</p>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Card content */}\n\t\t\t<div style={styles.cardContent}>\n\t\t\t\t{/* Method tabs */}\n\t\t\t\t{renderMethodTabs()}\n\n\t\t\t\t{/* OAuth buttons (if not in verification steps) */}\n\t\t\t\t{providers.length > 0 && step !== 'otp' && step !== 'magic-link-sent' && (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<OAuthButtons\n\t\t\t\t\t\t\tproviders={providers}\n\t\t\t\t\t\t\tonProviderClick={handleOAuthSignIn}\n\t\t\t\t\t\t\tloadingProvider={loadingProvider}\n\t\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\t\ttheme={theme}\n\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<OrDivider theme={theme} />\n\t\t\t\t\t</>\n\t\t\t\t)}\n\n\t\t\t\t{/* Form content */}\n\t\t\t\t{renderContent()}\n\n\t\t\t\t{/* Sign up link */}\n\t\t\t\t{!hideSignUpLink && step !== 'magic-link-sent' && (\n\t\t\t\t\t<p style={mergeStyles(styles.textCenter, styles.textSm, styles.textMuted, styles.mt4)}>\n\t\t\t\t\t\tDon&apos;t have an account?{' '}\n\t\t\t\t\t\t<a href={signUpUrl} style={styles.link}>\n\t\t\t\t\t\t\tSign up\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</p>\n\t\t\t\t)}\n\n\t\t\t\t{/* Footer */}\n\t\t\t\t{footer}\n\t\t\t</div>\n\t\t</div>\n\t)\n\n\t// Wrap in card if needed\n\tif (showCard) {\n\t\treturn <div style={styles.card}>{content}</div>\n\t}\n\n\treturn content\n}\n\n// Mail icon (decorative)\nfunction MailIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"24\"\n\t\t\theight=\"24\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t>\n\t\t\t<rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\" />\n\t\t\t<path d=\"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\" />\n\t\t</svg>\n\t)\n}\n","/**\n * useSignInForm Hook\n *\n * Headless hook for sign-in form logic.\n * Can be used with SDK's default UI or custom UI.\n *\n * @example\n * ```tsx\n * // With SDK default UI\n * function MySignIn() {\n *   const signIn = useSignInForm({ afterSignInUrl: '/dashboard' });\n *   return <SignInFormUI {...signIn} />;\n * }\n *\n * // With custom lockout protection (Platform)\n * function PlatformLogin() {\n *   const signIn = useSignInForm({\n *     onBeforeSubmit: preCheckLogin,\n *     onSubmitError: recordLoginFailure,\n *     submitHandler: async ({ email, password }) => {\n *       const result = await authClient.signIn.email({ email, password });\n *       if (result.error) throw new Error(result.error.message);\n *     },\n *   });\n *   return <CustomUI {...signIn} />;\n * }\n * ```\n */\n\n'use client'\n\nimport { useCallback, useContext, useState } from 'react'\nimport type { OAuthProvider } from '../../oauth'\nimport { safeRedirect } from '../security-utils'\nimport { SdkAuthContext, type SdkAuthContextValue } from '../services-context'\n\n// Re-export for convenience\nexport type { OAuthProvider } from '../../oauth'\n\n// ============================================\n// Types\n// ============================================\n\nexport type SignInMethod = 'password' | 'magic-link' | 'otp'\n\nexport interface SignInFormState {\n\temail: string\n\tpassword: string\n\totp: string\n}\n\nexport type SignInStep = 'email' | 'password' | 'otp' | 'otp-verify' | 'magic-link-sent'\n\nexport interface PreSubmitResult {\n\tsuccess: boolean\n\terror?: string\n\tlockoutUntil?: string\n}\n\nexport interface UseSignInFormOptions {\n\t/** Auth methods to enable */\n\tmethods?: SignInMethod[]\n\t/** OAuth providers to show */\n\tproviders?: OAuthProvider[]\n\t/** URL to redirect after sign in */\n\tafterSignInUrl?: string\n\t/**\n\t * Called before submit to validate/check lockout.\n\t * Return { success: false, error: '...' } to block submit.\n\t */\n\tonBeforeSubmit?: (credentials: { email: string; password: string }) => Promise<PreSubmitResult>\n\t/**\n\t * Called on submit error (e.g., to record failure).\n\t */\n\tonSubmitError?: (email: string, error: string) => Promise<void>\n\t/**\n\t * Custom submit handler. If provided, replaces context-based auth.\n\t * Throw error to indicate failure.\n\t */\n\tsubmitHandler?: (credentials: { email: string; password: string }) => Promise<void>\n\t/**\n\t * Custom OAuth handler. If provided, replaces default redirect.\n\t */\n\toauthHandler?: (provider: OAuthProvider) => Promise<void>\n\t/**\n\t * Custom magic link handler.\n\t */\n\tmagicLinkHandler?: (email: string) => Promise<void>\n\t/**\n\t * Custom OTP request handler.\n\t */\n\totpRequestHandler?: (email: string) => Promise<void>\n\t/**\n\t * Custom OTP verify handler.\n\t */\n\totpVerifyHandler?: (email: string, code: string) => Promise<void>\n\t/** Callback on successful sign in */\n\tonSuccess?: () => void\n\t/** Callback on error */\n\tonError?: (error: string) => void\n}\n\nexport interface UseSignInFormReturn {\n\t// Form state\n\tform: SignInFormState\n\tsetEmail: (email: string) => void\n\tsetPassword: (password: string) => void\n\tsetOtp: (otp: string) => void\n\tresetForm: () => void\n\n\t// UI state\n\tstep: SignInStep\n\tsetStep: (step: SignInStep) => void\n\tisLoading: boolean\n\tloadingProvider: OAuthProvider | null\n\terror: string | null\n\tlockoutUntil: string | null\n\tclearError: () => void\n\n\t// 2FA state\n\tpendingTwoFactor: { userId: string; email: string } | null\n\n\t// Handlers\n\thandlePasswordSubmit: (e?: React.FormEvent) => Promise<void>\n\thandleOAuthSignIn: (provider: OAuthProvider) => void\n\thandleMagicLinkRequest: (e?: React.FormEvent) => Promise<void>\n\thandleOtpRequest: () => Promise<void>\n\thandleOtpVerify: (e?: React.FormEvent) => Promise<void>\n\thandleTwoFactorVerify: (e?: React.FormEvent) => Promise<void>\n\n\t// Config (for UI)\n\tmethods: SignInMethod[]\n\tproviders: OAuthProvider[]\n\tafterSignInUrl: string\n}\n\n// ============================================\n// Hook Implementation\n// ============================================\n\nexport function useSignInForm(options: UseSignInFormOptions = {}): UseSignInFormReturn {\n\tconst {\n\t\tmethods = ['password'],\n\t\tproviders = [],\n\t\tafterSignInUrl = '/dashboard',\n\t\tonBeforeSubmit,\n\t\tonSubmitError,\n\t\tsubmitHandler,\n\t\toauthHandler,\n\t\tmagicLinkHandler,\n\t\totpRequestHandler,\n\t\totpVerifyHandler,\n\t\tonSuccess,\n\t\tonError,\n\t} = options\n\n\t// Get auth context (may be null if outside provider)\n\tconst authContext = useContext(SdkAuthContext) as SdkAuthContextValue | null\n\n\t// Form state\n\tconst [form, setForm] = useState<SignInFormState>({\n\t\temail: '',\n\t\tpassword: '',\n\t\totp: '',\n\t})\n\n\t// UI state\n\tconst [step, setStep] = useState<SignInStep>(methods.includes('password') ? 'password' : 'email')\n\tconst [isLoading, setIsLoading] = useState(false)\n\tconst [loadingProvider, setLoadingProvider] = useState<OAuthProvider | null>(null)\n\tconst [error, setError] = useState<string | null>(null)\n\tconst [lockoutUntil, setLockoutUntil] = useState<string | null>(null)\n\n\t// 2FA state\n\tconst [pendingTwoFactor, setPendingTwoFactor] = useState<{\n\t\tuserId: string\n\t\temail: string\n\t} | null>(null)\n\n\t// Form setters\n\tconst setEmail = useCallback((email: string) => {\n\t\tsetForm((prev) => ({ ...prev, email }))\n\t\tsetError(null)\n\t\tsetLockoutUntil(null)\n\t}, [])\n\n\tconst setPassword = useCallback((password: string) => {\n\t\tsetForm((prev) => ({ ...prev, password }))\n\t\tsetError(null)\n\t}, [])\n\n\tconst setOtp = useCallback((otp: string) => {\n\t\tsetForm((prev) => ({ ...prev, otp }))\n\t\tsetError(null)\n\t}, [])\n\n\tconst resetForm = useCallback(() => {\n\t\tsetForm({ email: '', password: '', otp: '' })\n\t\tsetError(null)\n\t\tsetLockoutUntil(null)\n\t\tsetPendingTwoFactor(null)\n\t}, [])\n\n\tconst clearError = useCallback(() => {\n\t\tsetError(null)\n\t\tsetLockoutUntil(null)\n\t}, [])\n\n\t// Password submit handler\n\tconst handlePasswordSubmit = useCallback(\n\t\tasync (e?: React.FormEvent) => {\n\t\t\te?.preventDefault()\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\t\t\tsetLockoutUntil(null)\n\n\t\t\ttry {\n\t\t\t\t// Pre-submit check (e.g., lockout protection)\n\t\t\t\tif (onBeforeSubmit) {\n\t\t\t\t\tconst preCheck = await onBeforeSubmit({\n\t\t\t\t\t\temail: form.email,\n\t\t\t\t\t\tpassword: form.password,\n\t\t\t\t\t})\n\t\t\t\t\tif (!preCheck.success) {\n\t\t\t\t\t\tsetError(preCheck.error || 'Login blocked')\n\t\t\t\t\t\tif (preCheck.lockoutUntil) {\n\t\t\t\t\t\t\tsetLockoutUntil(preCheck.lockoutUntil)\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Custom submit handler (Platform mode)\n\t\t\t\tif (submitHandler) {\n\t\t\t\t\tawait submitHandler({\n\t\t\t\t\t\temail: form.email,\n\t\t\t\t\t\tpassword: form.password,\n\t\t\t\t\t})\n\t\t\t\t\tonSuccess?.()\n\t\t\t\t\t// Use safeRedirect to prevent XSS via malicious afterSignInUrl\n\t\t\t\t\tsafeRedirect(afterSignInUrl, { fallback: '/dashboard' })\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// Use auth context (SDK mode)\n\t\t\t\tif (!authContext) {\n\t\t\t\t\tsetError('SDK not configured. Please wrap your app with SylphxProvider.')\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst result = await authContext.login(form.email, form.password)\n\n\t\t\t\t// Check if 2FA is required\n\t\t\t\tif (result.requiresTwoFactor) {\n\t\t\t\t\tif (!result.userId) {\n\t\t\t\t\t\tsetError('Authentication failed: missing user ID for two-factor verification')\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tsetPendingTwoFactor({ userId: result.userId, email: form.email })\n\t\t\t\t\tsetStep('otp-verify')\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tonSuccess?.()\n\n\t\t\t\t// Use safeRedirect to prevent XSS via malicious afterSignInUrl\n\t\t\t\tsafeRedirect(afterSignInUrl, { fallback: '/dashboard' })\n\t\t\t} catch (err) {\n\t\t\t\t// Distinguish between network errors and auth errors\n\t\t\t\tlet message: string\n\t\t\t\tif (err instanceof TypeError && err.message === 'Failed to fetch') {\n\t\t\t\t\tmessage = 'Unable to connect. Please check your internet connection and try again.'\n\t\t\t\t} else if (err instanceof Error) {\n\t\t\t\t\tmessage = err.message\n\t\t\t\t} else {\n\t\t\t\t\tmessage = 'Sign in failed'\n\t\t\t\t}\n\t\t\t\tsetError(message)\n\t\t\t\tonError?.(message)\n\n\t\t\t\t// Record failure if handler provided\n\t\t\t\tif (onSubmitError) {\n\t\t\t\t\tawait onSubmitError(form.email, message).catch(() => {\n\t\t\t\t\t\t// Silently ignore failure recording errors\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\tform,\n\t\t\tonBeforeSubmit,\n\t\t\tsubmitHandler,\n\t\t\tauthContext,\n\t\t\tafterSignInUrl,\n\t\t\tonSuccess,\n\t\t\tonError,\n\t\t\tonSubmitError,\n\t\t],\n\t)\n\n\t// 2FA verification handler\n\tconst handleTwoFactorVerify = useCallback(\n\t\tasync (e?: React.FormEvent) => {\n\t\t\te?.preventDefault()\n\t\t\tif (!pendingTwoFactor) {\n\t\t\t\tsetError('No pending two-factor authentication')\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tif (!authContext) {\n\t\t\t\t\tsetError('SDK not configured. Please wrap your app with SylphxProvider.')\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tawait authContext.verifyTwoFactor(pendingTwoFactor.userId, form.otp)\n\n\t\t\t\tonSuccess?.()\n\t\t\t\tsetPendingTwoFactor(null)\n\n\t\t\t\t// Use safeRedirect to prevent XSS via malicious afterSignInUrl\n\t\t\t\tsafeRedirect(afterSignInUrl, { fallback: '/dashboard' })\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : 'Invalid verification code'\n\t\t\t\tsetError(message)\n\t\t\t\tonError?.(message)\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[pendingTwoFactor, form.otp, authContext, afterSignInUrl, onSuccess, onError],\n\t)\n\n\t// OAuth handler\n\tconst handleOAuthSignIn = useCallback(\n\t\t(provider: OAuthProvider) => {\n\t\t\tsetLoadingProvider(provider)\n\t\t\tsetError(null)\n\n\t\t\tif (oauthHandler) {\n\t\t\t\toauthHandler(provider).catch((err) => {\n\t\t\t\t\tsetError(err instanceof Error ? err.message : 'OAuth sign in failed')\n\t\t\t\t\tsetLoadingProvider(null)\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\t// OAuth requires redirect - this should be handled by the platform\n\t\t\t\t// SDK apps should configure oauthHandler or use <SignIn> component\n\t\t\t\tsetError('OAuth sign-in requires a custom oauthHandler or use the SignIn component')\n\t\t\t\tsetLoadingProvider(null)\n\t\t\t}\n\t\t},\n\t\t[oauthHandler],\n\t)\n\n\t// Magic link request\n\tconst handleMagicLinkRequest = useCallback(\n\t\tasync (e?: React.FormEvent) => {\n\t\t\te?.preventDefault()\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tif (magicLinkHandler) {\n\t\t\t\t\tawait magicLinkHandler(form.email)\n\t\t\t\t} else {\n\t\t\t\t\t// Magic link requires custom handler\n\t\t\t\t\tthrow new Error('Magic link sign-in requires a custom magicLinkHandler')\n\t\t\t\t}\n\n\t\t\t\tsetStep('magic-link-sent')\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : 'Failed to send magic link'\n\t\t\t\tsetError(message)\n\t\t\t\tonError?.(message)\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[form.email, magicLinkHandler, onError],\n\t)\n\n\t// OTP request\n\tconst handleOtpRequest = useCallback(async () => {\n\t\tsetIsLoading(true)\n\t\tsetError(null)\n\n\t\ttry {\n\t\t\tif (otpRequestHandler) {\n\t\t\t\tawait otpRequestHandler(form.email)\n\t\t\t} else {\n\t\t\t\t// OTP requires custom handler\n\t\t\t\tthrow new Error('OTP sign-in requires a custom otpRequestHandler')\n\t\t\t}\n\n\t\t\tsetStep('otp')\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to send code'\n\t\t\tsetError(message)\n\t\t\tonError?.(message)\n\t\t} finally {\n\t\t\tsetIsLoading(false)\n\t\t}\n\t}, [form.email, otpRequestHandler, onError])\n\n\t// OTP verify\n\tconst handleOtpVerify = useCallback(\n\t\tasync (e?: React.FormEvent) => {\n\t\t\te?.preventDefault()\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tif (otpVerifyHandler) {\n\t\t\t\t\tawait otpVerifyHandler(form.email, form.otp)\n\t\t\t\t} else {\n\t\t\t\t\t// OTP requires custom handler\n\t\t\t\t\tthrow new Error('OTP verification requires a custom otpVerifyHandler')\n\t\t\t\t}\n\n\t\t\t\tonSuccess?.()\n\n\t\t\t\t// Use safeRedirect to prevent XSS via malicious afterSignInUrl\n\t\t\t\tsafeRedirect(afterSignInUrl, { fallback: '/dashboard' })\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : 'Verification failed'\n\t\t\t\tsetError(message)\n\t\t\t\tonError?.(message)\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[form, otpVerifyHandler, afterSignInUrl, onSuccess, onError],\n\t)\n\n\treturn {\n\t\t// Form state\n\t\tform,\n\t\tsetEmail,\n\t\tsetPassword,\n\t\tsetOtp,\n\t\tresetForm,\n\n\t\t// UI state\n\t\tstep,\n\t\tsetStep,\n\t\tisLoading,\n\t\tloadingProvider,\n\t\terror,\n\t\tlockoutUntil,\n\t\tclearError,\n\n\t\t// 2FA state\n\t\tpendingTwoFactor,\n\n\t\t// Handlers\n\t\thandlePasswordSubmit,\n\t\thandleOAuthSignIn,\n\t\thandleMagicLinkRequest,\n\t\thandleOtpRequest,\n\t\thandleOtpVerify,\n\t\thandleTwoFactorVerify,\n\n\t\t// Config\n\t\tmethods,\n\t\tproviders,\n\t\tafterSignInUrl,\n\t}\n}\n","/**\n * OAuth Provider Buttons\n *\n * Configurable OAuth login buttons for various providers.\n */\n\nimport type * as React from 'react'\nimport { useState } from 'react'\nimport {\n\ttype OAuthProvider,\n\toauthProviderIcon,\n\tproviderBrandColor,\n\tproviderDisplayName,\n} from './oauth-provider-icons'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, mergeStyles } from './styles'\n\n// Re-export for convenience\nexport type { OAuthProvider } from './oauth-provider-icons'\n\nexport interface OAuthButtonProps {\n\t/** OAuth provider */\n\tprovider: OAuthProvider\n\t/** Called when button is clicked */\n\tonClick: (provider: OAuthProvider) => void\n\t/** Whether the button is disabled */\n\tdisabled?: boolean\n\t/** Whether to show loading state */\n\tloading?: boolean\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Button variant */\n\tvariant?: 'default' | 'outline' | 'icon-only'\n\t/** Full width button */\n\tfullWidth?: boolean\n}\n\n// Provider styling, including custom-provider fallback labels.\nconst getProviderStyle = (provider: OAuthProvider) => {\n\tconst brandColor = providerBrandColor(provider)\n\tconst isLight = provider === 'google' // Google has white bg\n\treturn {\n\t\tname: providerDisplayName(provider),\n\t\tbackgroundColor: isLight ? '#ffffff' : brandColor,\n\t\tcolor: isLight ? '#1f2937' : '#ffffff',\n\t\thoverBackgroundColor: isLight ? '#f3f4f6' : brandColor,\n\t}\n}\n\n/**\n * Single OAuth provider button\n */\nexport function OAuthButton({\n\tprovider,\n\tonClick,\n\tdisabled = false,\n\tloading = false,\n\ttheme = defaultTheme,\n\tvariant = 'default',\n\tfullWidth = true,\n}: OAuthButtonProps) {\n\tconst [isHovered, setIsHovered] = useState(false)\n\tconst style = getProviderStyle(provider)\n\tconst styles = baseStyles(theme)\n\tconst IconComponent = oauthProviderIcon(provider)\n\n\tconst isOutline = variant === 'outline'\n\tconst isIconOnly = variant === 'icon-only'\n\n\tconst buttonStyle: React.CSSProperties = mergeStyles(\n\t\tstyles.button,\n\t\t{\n\t\t\twidth: fullWidth ? '100%' : 'auto',\n\t\t\tbackgroundColor: isOutline ? 'transparent' : style.backgroundColor,\n\t\t\tcolor: isOutline ? theme.colorForeground : style.color,\n\t\t\tborder: isOutline ? `1px solid ${theme.colorBorder}` : `1px solid ${style.backgroundColor}`,\n\t\t\topacity: disabled || loading ? 0.6 : 1,\n\t\t\tcursor: disabled || loading ? 'not-allowed' : 'pointer',\n\t\t\tpadding: isIconOnly ? '0.625rem' : '0.625rem 1rem',\n\t\t\tminHeight: '2.5rem',\n\t\t},\n\t\tisHovered && !disabled && !loading\n\t\t\t? {\n\t\t\t\t\tbackgroundColor: isOutline ? theme.colorMuted : style.hoverBackgroundColor,\n\t\t\t\t\tborderColor: isOutline ? theme.colorBorder : style.hoverBackgroundColor,\n\t\t\t\t\tfilter: isOutline ? 'none' : 'brightness(0.9)',\n\t\t\t\t}\n\t\t\t: {},\n\t)\n\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tonClick={() => !disabled && !loading && onClick(provider)}\n\t\t\tdisabled={disabled || loading}\n\t\t\tstyle={buttonStyle}\n\t\t\tonMouseEnter={() => setIsHovered(true)}\n\t\t\tonMouseLeave={() => setIsHovered(false)}\n\t\t\taria-label={isIconOnly ? `Continue with ${style.name}` : undefined}\n\t\t\taria-busy={loading}\n\t\t>\n\t\t\t{loading ? (\n\t\t\t\t<Spinner aria-label={`Loading ${style.name}`} />\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<span\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\tjustifyContent: 'center',\n\t\t\t\t\t\t\twidth: '1.25rem',\n\t\t\t\t\t\t\theight: '1.25rem',\n\t\t\t\t\t\t}}\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{IconComponent ? (\n\t\t\t\t\t\t\t<IconComponent width={20} height={20} />\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<span style={{ fontWeight: 700 }}>{style.name.charAt(0).toUpperCase()}</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</span>\n\t\t\t\t\t{!isIconOnly && <span>Continue with {style.name}</span>}\n\t\t\t\t</>\n\t\t\t)}\n\t\t</button>\n\t)\n}\n\nexport interface OAuthButtonsProps {\n\t/** List of providers to show */\n\tproviders: OAuthProvider[]\n\t/** Called when a provider button is clicked */\n\tonProviderClick: (provider: OAuthProvider) => void\n\t/** Provider currently being processed */\n\tloadingProvider?: OAuthProvider | null\n\t/** Whether all buttons are disabled */\n\tdisabled?: boolean\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Button variant */\n\tvariant?: 'default' | 'outline' | 'icon-only'\n\t/** Layout direction */\n\tlayout?: 'vertical' | 'horizontal'\n}\n\n/**\n * Group of OAuth provider buttons\n */\nexport function OAuthButtons({\n\tproviders,\n\tonProviderClick,\n\tloadingProvider,\n\tdisabled = false,\n\ttheme = defaultTheme,\n\tvariant = 'default',\n\tlayout = 'vertical',\n}: OAuthButtonsProps) {\n\tif (providers.length === 0) return null\n\n\tconst containerStyle: React.CSSProperties = {\n\t\tdisplay: 'flex',\n\t\tflexDirection: layout === 'horizontal' ? 'row' : 'column',\n\t\tgap: layout === 'horizontal' ? '0.5rem' : '0.75rem',\n\t}\n\n\treturn (\n\t\t<div style={containerStyle}>\n\t\t\t{providers.map((provider) => (\n\t\t\t\t<OAuthButton\n\t\t\t\t\tkey={provider}\n\t\t\t\t\tprovider={provider}\n\t\t\t\t\tonClick={onProviderClick}\n\t\t\t\t\tdisabled={disabled || (loadingProvider != null && loadingProvider !== provider)}\n\t\t\t\t\tloading={loadingProvider === provider}\n\t\t\t\t\ttheme={theme}\n\t\t\t\t\tvariant={variant}\n\t\t\t\t\tfullWidth={layout === 'vertical'}\n\t\t\t\t/>\n\t\t\t))}\n\t\t</div>\n\t)\n}\n\n/**\n * Divider with \"or\" text\n */\nexport function OrDivider({ theme = defaultTheme }: { theme?: ThemeVariables }) {\n\tconst styles = baseStyles(theme)\n\n\treturn (\n\t\t<div style={styles.divider}>\n\t\t\t<div style={styles.dividerLine} />\n\t\t\t<span style={styles.dividerText}>or</span>\n\t\t\t<div style={styles.dividerLine} />\n\t\t</div>\n\t)\n}\n\n// Loading spinner\nfunction Spinner({ 'aria-label': ariaLabel }: { 'aria-label'?: string }) {\n\treturn (\n\t\t<svg\n\t\t\tstyle={{\n\t\t\t\twidth: '1.25rem',\n\t\t\t\theight: '1.25rem',\n\t\t\t\tanimation: 'sylphx-spin 0.75s linear infinite',\n\t\t\t}}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\trole=\"img\"\n\t\t\taria-label={ariaLabel || 'Loading'}\n\t\t>\n\t\t\t<circle cx=\"12\" cy=\"12\" r=\"10\" opacity=\"0.25\" />\n\t\t\t<path d=\"M12 2a10 10 0 0 1 10 10\" opacity=\"0.75\" />\n\t\t</svg>\n\t)\n}\n","import type { AdminOAuthProvider as ContractOAuthProvider } from '@sylphx/contract'\nimport type { OAuthProvider } from './oauth'\n\nexport interface OAuthProviderMeta {\n\treadonly name: string\n\treadonly color: string\n}\n\nconst CONTRACT_OAUTH_PROVIDER_META = {\n\tgoogle: { name: 'Google', color: '#4285F4' },\n\tgithub: { name: 'GitHub', color: '#181717' },\n\tapple: { name: 'Apple', color: '#000000' },\n\tmicrosoft: { name: 'Microsoft', color: '#00A4EF' },\n\tfacebook: { name: 'Facebook', color: '#1877F2' },\n\ttwitter: { name: 'X (Twitter)', color: '#000000' },\n\tdiscord: { name: 'Discord', color: '#5865F2' },\n\tlinkedin: { name: 'LinkedIn', color: '#0A66C2' },\n\ttwitch: { name: 'Twitch', color: '#9146FF' },\n\tspotify: { name: 'Spotify', color: '#1DB954' },\n} as const satisfies Record<ContractOAuthProvider, OAuthProviderMeta>\n\nexport const OAUTH_PROVIDER_META = {\n\t...CONTRACT_OAUTH_PROVIDER_META,\n\tslack: { name: 'Slack', color: '#4A154B' },\n\tgitlab: { name: 'GitLab', color: '#FC6D26' },\n\tbitbucket: { name: 'Bitbucket', color: '#0052CC' },\n} as const satisfies Record<string, OAuthProviderMeta>\n\nexport function resolveOAuthProviderMeta(provider: OAuthProvider): OAuthProviderMeta {\n\treturn (\n\t\tOAUTH_PROVIDER_META[provider as keyof typeof OAUTH_PROVIDER_META] ?? {\n\t\t\tname: formatOAuthProviderName(provider),\n\t\t\tcolor: '#4B5563',\n\t\t}\n\t)\n}\n\nfunction formatOAuthProviderName(provider: OAuthProvider): string {\n\treturn provider\n\t\t.split(/[-_\\s]+/)\n\t\t.filter((part) => part.length > 0)\n\t\t.map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n\t\t.join(' ')\n}\n","import type { SVGProps } from 'react'\nimport type { OAuthProvider } from '../../oauth'\nimport { OAUTH_PROVIDER_META, resolveOAuthProviderMeta } from '../../oauth-providers'\n\ntype IconProps = SVGProps<SVGSVGElement>\n\nexport function GoogleIcon(props: IconProps) {\n\treturn (\n\t\t<svg aria-hidden=\"true\" viewBox=\"0 0 24 24\" fill=\"currentColor\" {...props}>\n\t\t\t<path\n\t\t\t\td=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z\"\n\t\t\t\tfill=\"#4285F4\"\n\t\t\t/>\n\t\t\t<path\n\t\t\t\td=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\"\n\t\t\t\tfill=\"#34A853\"\n\t\t\t/>\n\t\t\t<path\n\t\t\t\td=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\"\n\t\t\t\tfill=\"#FBBC05\"\n\t\t\t/>\n\t\t\t<path\n\t\t\t\td=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\"\n\t\t\t\tfill=\"#EA4335\"\n\t\t\t/>\n\t\t</svg>\n\t)\n}\n\nexport function GitHubIcon(props: IconProps) {\n\treturn (\n\t\t<svg aria-hidden=\"true\" viewBox=\"0 0 24 24\" fill=\"currentColor\" {...props}>\n\t\t\t<path d=\"M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0024 12c0-6.63-5.37-12-12-12z\" />\n\t\t</svg>\n\t)\n}\n\nexport function AppleIcon(props: IconProps) {\n\treturn (\n\t\t<svg aria-hidden=\"true\" viewBox=\"0 0 24 24\" fill=\"currentColor\" {...props}>\n\t\t\t<path d=\"M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701\" />\n\t\t</svg>\n\t)\n}\n\nexport function DiscordIcon(props: IconProps) {\n\treturn (\n\t\t<svg aria-hidden=\"true\" viewBox=\"0 0 24 24\" fill=\"currentColor\" {...props}>\n\t\t\t<path d=\"M20.317 4.37a19.791 19.791 0 00-4.885-1.515.074.074 0 00-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 00-5.487 0 12.64 12.64 0 00-.617-1.25.077.077 0 00-.079-.037A19.736 19.736 0 003.677 4.37a.07.07 0 00-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 00.031.057 19.9 19.9 0 005.993 3.03.078.078 0 00.084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 00-.041-.106 13.107 13.107 0 01-1.872-.892.077.077 0 01-.008-.128 10.2 10.2 0 00.372-.292.074.074 0 01.077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 01.078.01c.12.098.246.198.373.292a.077.077 0 01-.006.127 12.299 12.299 0 01-1.873.892.077.077 0 00-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 00.084.028 19.839 19.839 0 006.002-3.03.077.077 0 00.032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 00-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z\" />\n\t\t</svg>\n\t)\n}\n\nexport function TwitterIcon(props: IconProps) {\n\treturn (\n\t\t<svg aria-hidden=\"true\" viewBox=\"0 0 24 24\" fill=\"currentColor\" {...props}>\n\t\t\t<path d=\"M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z\" />\n\t\t</svg>\n\t)\n}\n\nexport function MicrosoftIcon(props: IconProps) {\n\treturn (\n\t\t<svg aria-hidden=\"true\" viewBox=\"0 0 24 24\" fill=\"currentColor\" {...props}>\n\t\t\t<path d=\"M0 0h11.377v11.372H0zm12.623 0H24v11.372H12.623zM0 12.623h11.377V24H0zm12.623 0H24V24H12.623\" />\n\t\t</svg>\n\t)\n}\n\nexport function FacebookIcon(props: IconProps) {\n\treturn (\n\t\t<svg aria-hidden=\"true\" viewBox=\"0 0 24 24\" fill=\"currentColor\" {...props}>\n\t\t\t<path d=\"M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z\" />\n\t\t</svg>\n\t)\n}\n\nexport function LinkedInIcon(props: IconProps) {\n\treturn (\n\t\t<svg aria-hidden=\"true\" viewBox=\"0 0 24 24\" fill=\"currentColor\" {...props}>\n\t\t\t<path d=\"M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z\" />\n\t\t</svg>\n\t)\n}\n\nexport function TwitchIcon(props: IconProps) {\n\treturn (\n\t\t<svg aria-hidden=\"true\" viewBox=\"0 0 24 24\" fill=\"currentColor\" {...props}>\n\t\t\t<path d=\"M11.571 4.714h1.715v5.143H11.57zm4.715 0H18v5.143h-1.714zM6 0L1.714 4.286v15.428h5.143V24l4.286-4.286h3.428L22.286 12V0zm14.571 11.143l-3.428 3.428h-3.429l-3 3v-3H6.857V1.714h13.714z\" />\n\t\t</svg>\n\t)\n}\n\nexport function SpotifyIcon(props: IconProps) {\n\treturn (\n\t\t<svg aria-hidden=\"true\" viewBox=\"0 0 24 24\" fill=\"currentColor\" {...props}>\n\t\t\t<path d=\"M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.66 0 12 0zm5.521 17.34c-.24.359-.66.48-1.021.24-2.82-1.74-6.36-2.101-10.561-1.141-.418.122-.779-.179-.899-.539-.12-.421.18-.78.54-.9 4.56-1.021 8.52-.6 11.64 1.32.42.18.479.659.301 1.02zm1.44-3.3c-.301.42-.841.6-1.262.3-3.239-1.98-8.159-2.58-11.939-1.38-.479.12-1.02-.12-1.14-.6-.12-.48.12-1.021.6-1.141C9.6 9.9 15 10.561 18.72 12.84c.361.181.54.78.241 1.2zm.12-3.36C15.24 8.4 8.82 8.16 5.16 9.301c-.6.179-1.2-.181-1.38-.721-.18-.601.18-1.2.72-1.381 4.26-1.26 11.28-1.02 15.721 1.621.539.3.719 1.02.419 1.56-.299.421-1.02.599-1.559.3z\" />\n\t\t</svg>\n\t)\n}\n\nexport function GenericOAuthProviderIcon(props: IconProps) {\n\treturn (\n\t\t<svg aria-hidden=\"true\" viewBox=\"0 0 24 24\" fill=\"none\" {...props}>\n\t\t\t<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"5\" fill=\"currentColor\" opacity=\"0.14\" />\n\t\t\t<path\n\t\t\t\td=\"M8.5 12a3.5 3.5 0 017 0 3.5 3.5 0 01-7 0zm-2.25 6.25c.76-2.25 2.87-3.75 5.75-3.75s4.99 1.5 5.75 3.75\"\n\t\t\t\tstroke=\"currentColor\"\n\t\t\t\tstrokeWidth=\"1.8\"\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t/>\n\t\t</svg>\n\t)\n}\n\nexport function SlackIcon(props: IconProps) {\n\treturn <GenericOAuthProviderIcon {...props} />\n}\n\nexport function GitLabIcon(props: IconProps) {\n\treturn <GenericOAuthProviderIcon {...props} />\n}\n\nexport function BitbucketIcon(props: IconProps) {\n\treturn <GenericOAuthProviderIcon {...props} />\n}\n\nexport const OAuthIcons = {\n\tgoogle: GoogleIcon,\n\tgithub: GitHubIcon,\n\tapple: AppleIcon,\n\tdiscord: DiscordIcon,\n\ttwitter: TwitterIcon,\n\tmicrosoft: MicrosoftIcon,\n\tfacebook: FacebookIcon,\n\tlinkedin: LinkedInIcon,\n\tslack: SlackIcon,\n\tgitlab: GitLabIcon,\n\tbitbucket: BitbucketIcon,\n\ttwitch: TwitchIcon,\n\tspotify: SpotifyIcon,\n} as const\n\nexport function resolveOAuthProviderIcon(provider: OAuthProvider) {\n\treturn OAuthIcons[provider as keyof typeof OAuthIcons] ?? GenericOAuthProviderIcon\n}\n\nexport type OAuthProviderWithIcon = keyof typeof OAuthIcons\n\nexport const providerDisplayName = (provider: OAuthProvider): string =>\n\tresolveOAuthProviderMeta(provider).name\n\nexport const providerBrandColor = (provider: OAuthProvider): string =>\n\tresolveOAuthProviderMeta(provider).color\n\nexport const oauthProviderIcon = (provider: OAuthProvider) =>\n\tOAuthIcons[provider as keyof typeof OAuthIcons] ?? null\n\nexport { OAUTH_PROVIDER_META, resolveOAuthProviderMeta }\nexport type { OAuthProvider }\n","/**\n * SignUp Form Component\n *\n * Full embedded sign-up form with email/password and OAuth support.\n * Self-contained with CSS-in-JS styles.\n *\n * NOW USES useSignUpForm hook (dogfooding).\n */\n\n'use client'\n\nimport { useEffect } from 'react'\nimport { RequireSdk } from '../hooks'\nimport { type AdditionalField, useSignUpForm } from '../hooks/use-sign-up-form'\nimport { OAuthButtons, type OAuthProvider, OrDivider } from './oauth-buttons'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\nexport interface SignUpFormProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** OAuth providers to show */\n\tproviders?: OAuthProvider[]\n\t/** URL to redirect after sign up */\n\tafterSignUpUrl?: string\n\t/** URL for sign in link */\n\tsignInUrl?: string\n\t/** Terms of Service URL */\n\ttermsUrl?: string\n\t/** Privacy Policy URL */\n\tprivacyUrl?: string\n\t/** URL to redirect to waitlist page (Clerk feature - shows waitlist instead of signup) */\n\twaitlistUrl?: string\n\t/** Called on successful sign up */\n\tonSuccess?: () => void\n\t/** Called on error */\n\tonError?: (error: string) => void\n\t/** Custom header content */\n\theader?: React.ReactNode\n\t/** Custom footer content */\n\tfooter?: React.ReactNode\n\t/** Hide the sign in link */\n\thideSignInLink?: boolean\n\t/** Hide the legal links */\n\thideLegalLinks?: boolean\n\t/** Show the card wrapper (default: true) */\n\tshowCard?: boolean\n\t/** Initial invite code */\n\tinviteCode?: string\n\t/** Show invite code field */\n\tshowInviteCode?: boolean\n\t/** Require invite code */\n\trequireInviteCode?: boolean\n\t/** Additional fields to collect */\n\tadditionalFields?: AdditionalField[]\n}\n\n/**\n * Full sign-up form component (uses useSignUpForm hook)\n */\nexport function SignUpForm(props: SignUpFormProps) {\n\treturn (\n\t\t<RequireSdk services={['auth']} componentType=\"sign-up\" theme={props.theme}>\n\t\t\t<SignUpFormInner {...props} />\n\t\t</RequireSdk>\n\t)\n}\n\n/** Inner component that safely uses platform hooks */\nfunction SignUpFormInner({\n\ttheme = defaultTheme,\n\tproviders = [],\n\tafterSignUpUrl = '/dashboard',\n\tsignInUrl = '/sign-in',\n\ttermsUrl = '/terms',\n\tprivacyUrl = '/privacy',\n\twaitlistUrl,\n\tonSuccess,\n\tonError,\n\theader,\n\tfooter,\n\thideSignInLink = false,\n\thideLegalLinks = false,\n\tshowCard = true,\n\tinviteCode: initialInviteCode = '',\n\tshowInviteCode = false,\n\trequireInviteCode = false,\n\tadditionalFields = [],\n}: SignUpFormProps) {\n\tconst styles = baseStyles(theme)\n\n\t// Use the headless hook (dogfooding!)\n\tconst {\n\t\tform,\n\t\tsetName,\n\t\tsetEmail,\n\t\tsetPassword,\n\t\tsetInviteCode,\n\t\tsetVerificationCode,\n\t\tsetField,\n\t\tstep,\n\t\tsetStep,\n\t\tinviteInfo,\n\t\tisVerifyingInvite,\n\t\tisLoading,\n\t\tloadingProvider,\n\t\terror,\n\t\thandleSubmit,\n\t\thandleVerifyEmail,\n\t\thandleJoinWaitlist,\n\t\thandleOAuthSignUp,\n\t\tisWaitlistMode,\n\t} = useSignUpForm({\n\t\tproviders,\n\t\tafterSignUpUrl,\n\t\tinviteCode: initialInviteCode,\n\t\tshowInviteCode,\n\t\trequireInviteCode,\n\t\tadditionalFields,\n\t\twaitlistUrl,\n\t\tonSuccess,\n\t\tonError,\n\t})\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// Render input with theme and accessibility\n\tconst renderInput = (\n\t\ttype: string,\n\t\tname: string,\n\t\tplaceholder: string,\n\t\tvalue: string,\n\t\tonChange: (value: string) => void,\n\t\toptions?: {\n\t\t\tautoComplete?: string\n\t\t\trequired?: boolean\n\t\t\tminLength?: number\n\t\t\treadOnly?: boolean\n\t\t\tautoFocus?: boolean\n\t\t},\n\t) => {\n\t\t// Generate unique ID for label association\n\t\tconst inputId = `signup-${name}`\n\t\treturn (\n\t\t\t<input\n\t\t\t\tid={inputId}\n\t\t\t\ttype={type}\n\t\t\t\tname={name}\n\t\t\t\tvalue={value}\n\t\t\t\tonChange={(e) => onChange(e.target.value)}\n\t\t\t\tplaceholder={placeholder}\n\t\t\t\tdisabled={isLoading}\n\t\t\t\treadOnly={options?.readOnly}\n\t\t\t\tautoComplete={options?.autoComplete}\n\t\t\t\trequired={options?.required !== false}\n\t\t\t\tminLength={options?.minLength}\n\t\t\t\taria-describedby={\n\t\t\t\t\tname === 'password'\n\t\t\t\t\t\t? 'password-hint'\n\t\t\t\t\t\t: name === 'verificationCode'\n\t\t\t\t\t\t\t? 'verification-hint'\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\tstyles.input,\n\t\t\t\t\tisLoading || options?.readOnly ? styles.inputDisabled : {},\n\t\t\t\t)}\n\t\t\t/>\n\t\t)\n\t}\n\n\t// Render error alert with accessibility\n\tconst renderError = () => {\n\t\treturn (\n\t\t\t<div aria-live=\"assertive\" aria-atomic=\"true\">\n\t\t\t\t{error && (\n\t\t\t\t\t<div role=\"alert\" style={mergeStyles(styles.alert, styles.alertError)}>\n\t\t\t\t\t\t{error}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t)\n\t}\n\n\t// Render submit button\n\tconst renderButton = (text: string, loadingText: string, onClick?: () => void) => {\n\t\tconst buttonProps = onClick ? { type: 'button' as const, onClick } : { type: 'submit' as const }\n\n\t\treturn (\n\t\t\t<button\n\t\t\t\t{...buttonProps}\n\t\t\t\tdisabled={isLoading}\n\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\tstyles.button,\n\t\t\t\t\tstyles.buttonPrimary,\n\t\t\t\t\tstyles.buttonFullWidth,\n\t\t\t\t\tisLoading ? styles.buttonDisabled : {},\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{isLoading ? (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t\t{loadingText}\n\t\t\t\t\t</>\n\t\t\t\t) : (\n\t\t\t\t\ttext\n\t\t\t\t)}\n\t\t\t</button>\n\t\t)\n\t}\n\n\t// Render invite info banner\n\tconst renderInviteBanner = () => {\n\t\tif (!inviteInfo?.valid) return null\n\n\t\treturn (\n\t\t\t<div\n\t\t\t\tstyle={mergeStyles(styles.alert, {\n\t\t\t\t\tbackgroundColor: `${theme.colorSuccess}15`,\n\t\t\t\t\tcolor: theme.colorSuccess,\n\t\t\t\t\tborder: `1px solid ${theme.colorSuccess}30`,\n\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\talignItems: 'center',\n\t\t\t\t\tgap: '0.75rem',\n\t\t\t\t})}\n\t\t\t>\n\t\t\t\t<CheckIcon color={theme.colorSuccess} />\n\t\t\t\t<div>\n\t\t\t\t\t<p style={{ fontWeight: 500, margin: 0 }}>Valid invitation</p>\n\t\t\t\t\t<p style={{ fontSize: theme.fontSizeXs, margin: 0, opacity: 0.8 }}>\n\t\t\t\t\t\t{inviteInfo.email}\n\t\t\t\t\t\t{inviteInfo.role && inviteInfo.role !== 'user' && (\n\t\t\t\t\t\t\t<> &bull; {inviteInfo.role.replace('_', ' ')}</>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t)\n\t}\n\n\t// Render sign up form\n\tconst renderSignUpForm = () => (\n\t\t<form onSubmit={handleSubmit}>\n\t\t\t{/* Invite banner */}\n\t\t\t{renderInviteBanner()}\n\n\t\t\t{/* Name field */}\n\t\t\t<div style={styles.formGroup}>\n\t\t\t\t<label htmlFor=\"signup-name\" style={styles.label}>\n\t\t\t\t\tName\n\t\t\t\t</label>\n\t\t\t\t{renderInput('text', 'name', 'Your name', form.name, setName, {\n\t\t\t\t\tautoComplete: 'name',\n\t\t\t\t})}\n\t\t\t</div>\n\n\t\t\t{/* Email field */}\n\t\t\t<div style={styles.formGroup}>\n\t\t\t\t<label htmlFor=\"signup-email\" style={styles.label}>\n\t\t\t\t\tEmail\n\t\t\t\t</label>\n\t\t\t\t{renderInput('email', 'email', 'you@example.com', form.email, setEmail, {\n\t\t\t\t\tautoComplete: 'email',\n\t\t\t\t\treadOnly: !!inviteInfo?.email,\n\t\t\t\t})}\n\t\t\t\t{inviteInfo?.email && (\n\t\t\t\t\t<p style={mergeStyles(styles.textXs, styles.textMuted, styles.mt1)}>\n\t\t\t\t\t\tEmail is locked to the invitation address\n\t\t\t\t\t</p>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{/* Password field */}\n\t\t\t<div style={styles.formGroup}>\n\t\t\t\t<label htmlFor=\"signup-password\" style={styles.label}>\n\t\t\t\t\tPassword\n\t\t\t\t</label>\n\t\t\t\t{renderInput(\n\t\t\t\t\t'password',\n\t\t\t\t\t'password',\n\t\t\t\t\t'\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022',\n\t\t\t\t\tform.password,\n\t\t\t\t\tsetPassword,\n\t\t\t\t\t{\n\t\t\t\t\t\tautoComplete: 'new-password',\n\t\t\t\t\t\tminLength: 12,\n\t\t\t\t\t},\n\t\t\t\t)}\n\t\t\t\t<p id=\"password-hint\" style={mergeStyles(styles.textXs, styles.textMuted, styles.mt1)}>\n\t\t\t\t\tMust be at least 12 characters\n\t\t\t\t</p>\n\t\t\t</div>\n\n\t\t\t{/* Invite code field */}\n\t\t\t{(showInviteCode || requireInviteCode) && !inviteInfo?.valid && (\n\t\t\t\t<div style={styles.formGroup}>\n\t\t\t\t\t<label htmlFor=\"signup-inviteCode\" style={styles.label}>\n\t\t\t\t\t\tInvite Code{' '}\n\t\t\t\t\t\t{requireInviteCode && <span style={{ color: theme.colorDestructive }}>*</span>}\n\t\t\t\t\t</label>\n\t\t\t\t\t{renderInput('text', 'inviteCode', 'Enter invite code', form.inviteCode, setInviteCode, {\n\t\t\t\t\t\trequired: requireInviteCode,\n\t\t\t\t\t})}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Additional fields */}\n\t\t\t{additionalFields.map((field) => (\n\t\t\t\t<div key={field.name} style={styles.formGroup}>\n\t\t\t\t\t<label htmlFor={`signup-${field.name}`} style={styles.label}>\n\t\t\t\t\t\t{field.label}\n\t\t\t\t\t\t{field.required && <span style={{ color: theme.colorDestructive }}> *</span>}\n\t\t\t\t\t</label>\n\t\t\t\t\t{field.type === 'select' ? (\n\t\t\t\t\t\t<select\n\t\t\t\t\t\t\tid={`signup-${field.name}`}\n\t\t\t\t\t\t\tname={field.name}\n\t\t\t\t\t\t\tvalue={form[field.name] || ''}\n\t\t\t\t\t\t\tonChange={(e) => setField(field.name, e.target.value)}\n\t\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\t\trequired={field.required}\n\t\t\t\t\t\t\tstyle={styles.input}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<option value=\"\">Select...</option>\n\t\t\t\t\t\t\t{field.options?.map((opt) => (\n\t\t\t\t\t\t\t\t<option key={opt.value} value={opt.value}>\n\t\t\t\t\t\t\t\t\t{opt.label}\n\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</select>\n\t\t\t\t\t) : (\n\t\t\t\t\t\trenderInput(\n\t\t\t\t\t\t\tfield.type,\n\t\t\t\t\t\t\tfield.name,\n\t\t\t\t\t\t\tfield.placeholder || '',\n\t\t\t\t\t\t\tform[field.name] || '',\n\t\t\t\t\t\t\t(v) => setField(field.name, v),\n\t\t\t\t\t\t\t{ required: field.required },\n\t\t\t\t\t\t)\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t))}\n\n\t\t\t{renderError()}\n\t\t\t{renderButton('Create Account', 'Creating account...')}\n\n\t\t\t{/* Legal links */}\n\t\t\t{!hideLegalLinks && (\n\t\t\t\t<p style={mergeStyles(styles.textCenter, styles.textXs, styles.textMuted, styles.mt4)}>\n\t\t\t\t\tBy creating an account, you agree to our{' '}\n\t\t\t\t\t<a href={termsUrl} style={styles.link}>\n\t\t\t\t\t\tTerms of Service\n\t\t\t\t\t</a>{' '}\n\t\t\t\t\tand{' '}\n\t\t\t\t\t<a href={privacyUrl} style={styles.link}>\n\t\t\t\t\t\tPrivacy Policy\n\t\t\t\t\t</a>\n\t\t\t\t</p>\n\t\t\t)}\n\t\t</form>\n\t)\n\n\t// Render email verification form\n\tconst renderVerifyEmailForm = () => (\n\t\t<div>\n\t\t\t<div style={styles.textCenter}>\n\t\t\t\t<div\n\t\t\t\t\tstyle={mergeStyles(styles.flexCenter, {\n\t\t\t\t\t\twidth: '3rem',\n\t\t\t\t\t\theight: '3rem',\n\t\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\t\tbackgroundColor: `${theme.colorPrimary}15`,\n\t\t\t\t\t\tmargin: '0 auto 1rem',\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\t<MailIcon color={theme.colorPrimary} />\n\t\t\t\t</div>\n\t\t\t\t<h3 style={mergeStyles(styles.cardTitle, styles.mb2)}>Verify your email</h3>\n\t\t\t\t<p style={mergeStyles(styles.textMuted, styles.textSm, styles.mb4)}>\n\t\t\t\t\tWe sent a verification code to <strong>{form.email}</strong>\n\t\t\t\t</p>\n\t\t\t</div>\n\n\t\t\t<form onSubmit={handleVerifyEmail}>\n\t\t\t\t<div style={styles.formGroup}>\n\t\t\t\t\t<label\n\t\t\t\t\t\thtmlFor=\"signup-verificationCode\"\n\t\t\t\t\t\tclassName=\"sr-only\"\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\t\t\twidth: 1,\n\t\t\t\t\t\t\theight: 1,\n\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\tmargin: -1,\n\t\t\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\t\t\tclip: 'rect(0,0,0,0)',\n\t\t\t\t\t\t\tborder: 0,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tVerification code\n\t\t\t\t\t</label>\n\t\t\t\t\t<p\n\t\t\t\t\t\tid=\"verification-hint\"\n\t\t\t\t\t\tstyle={mergeStyles(styles.textMuted, styles.textSm, styles.mb2)}\n\t\t\t\t\t>\n\t\t\t\t\t\tEnter the 6-digit code from your email\n\t\t\t\t\t</p>\n\t\t\t\t\t{renderInput(\n\t\t\t\t\t\t'text',\n\t\t\t\t\t\t'verificationCode',\n\t\t\t\t\t\t'000000',\n\t\t\t\t\t\tform.verificationCode,\n\t\t\t\t\t\tsetVerificationCode,\n\t\t\t\t\t\t{ autoComplete: 'one-time-code', autoFocus: true },\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t{renderError()}\n\t\t\t\t{renderButton('Verify Email', 'Verifying...')}\n\t\t\t</form>\n\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tonClick={() => setStep('form')}\n\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonGhost, styles.buttonFullWidth, styles.mt2)}\n\t\t\t>\n\t\t\t\tUse different email\n\t\t\t</button>\n\t\t</div>\n\t)\n\n\t// Render complete step\n\tconst renderComplete = () => (\n\t\t<div style={styles.textCenter}>\n\t\t\t<div\n\t\t\t\tstyle={mergeStyles(styles.flexCenter, {\n\t\t\t\t\twidth: '3rem',\n\t\t\t\t\theight: '3rem',\n\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\tbackgroundColor: `${theme.colorSuccess}15`,\n\t\t\t\t\tmargin: '0 auto 1rem',\n\t\t\t\t})}\n\t\t\t>\n\t\t\t\t<CheckIcon color={theme.colorSuccess} />\n\t\t\t</div>\n\t\t\t<h3 style={mergeStyles(styles.cardTitle, styles.mb2)}>Account created!</h3>\n\t\t\t<p style={mergeStyles(styles.textMuted, styles.textSm, styles.mb4)}>\n\t\t\t\tWelcome aboard! Redirecting you...\n\t\t\t</p>\n\t\t</div>\n\t)\n\n\t// Render waitlist form\n\tconst renderWaitlistForm = () => (\n\t\t<form onSubmit={handleJoinWaitlist}>\n\t\t\t<div style={styles.formGroup}>\n\t\t\t\t<label htmlFor=\"signup-email\" style={styles.label}>\n\t\t\t\t\tEmail\n\t\t\t\t</label>\n\t\t\t\t{renderInput('email', 'email', 'you@example.com', form.email, setEmail, {\n\t\t\t\t\tautoComplete: 'email',\n\t\t\t\t})}\n\t\t\t</div>\n\n\t\t\t<div style={styles.formGroup}>\n\t\t\t\t<label htmlFor=\"signup-name\" style={styles.label}>\n\t\t\t\t\tName (optional)\n\t\t\t\t</label>\n\t\t\t\t{renderInput('text', 'name', 'Your name', form.name, setName, {\n\t\t\t\t\tautoComplete: 'name',\n\t\t\t\t\trequired: false,\n\t\t\t\t})}\n\t\t\t</div>\n\n\t\t\t{renderError()}\n\t\t\t{renderButton('Join Waitlist', 'Joining...')}\n\t\t</form>\n\t)\n\n\t// Render waitlist joined confirmation\n\tconst renderWaitlistJoined = () => (\n\t\t<div style={styles.textCenter}>\n\t\t\t<div\n\t\t\t\tstyle={mergeStyles(styles.flexCenter, {\n\t\t\t\t\twidth: '3rem',\n\t\t\t\t\theight: '3rem',\n\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\tbackgroundColor: `${theme.colorSuccess}15`,\n\t\t\t\t\tmargin: '0 auto 1rem',\n\t\t\t\t})}\n\t\t\t>\n\t\t\t\t<CheckIcon color={theme.colorSuccess} />\n\t\t\t</div>\n\t\t\t<h3 style={mergeStyles(styles.cardTitle, styles.mb2)}>You're on the list!</h3>\n\t\t\t<p style={mergeStyles(styles.textMuted, styles.textSm, styles.mb4)}>\n\t\t\t\tWe'll let you know when it's your turn.\n\t\t\t</p>\n\t\t\t{waitlistUrl && (\n\t\t\t\t<a\n\t\t\t\t\thref={waitlistUrl}\n\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary, styles.buttonFullWidth)}\n\t\t\t\t>\n\t\t\t\t\tView Waitlist Status\n\t\t\t\t</a>\n\t\t\t)}\n\t\t</div>\n\t)\n\n\t// Show loading while verifying invite\n\tif (isVerifyingInvite) {\n\t\treturn (\n\t\t\t<div style={showCard ? styles.card : {}}>\n\t\t\t\t<div\n\t\t\t\t\tstyle={mergeStyles(styles.cardContent, styles.flexCenter, {\n\t\t\t\t\t\tminHeight: '12rem',\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\t<div style={styles.flexCol}>\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.spinner, {\n\t\t\t\t\t\t\t\twidth: '2rem',\n\t\t\t\t\t\t\t\theight: '2rem',\n\t\t\t\t\t\t\t\tmargin: '0 auto 1rem',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<p style={styles.textMuted}>Verifying invitation...</p>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t)\n\t}\n\n\t// Render content based on step\n\tconst renderContent = () => {\n\t\t// If waitlistUrl is provided, show waitlist flow instead of signup\n\t\tif (isWaitlistMode && step === 'form') {\n\t\t\treturn renderWaitlistForm()\n\t\t}\n\t\tif (step === 'waitlist-joined') {\n\t\t\treturn renderWaitlistJoined()\n\t\t}\n\n\t\tswitch (step) {\n\t\t\tcase 'verify-email':\n\t\t\t\treturn renderVerifyEmailForm()\n\t\t\tcase 'complete':\n\t\t\t\treturn renderComplete()\n\t\t\tdefault:\n\t\t\t\treturn renderSignUpForm()\n\t\t}\n\t}\n\n\t// Full form content\n\tconst content = (\n\t\t<div style={styles.container}>\n\t\t\t{/* Header */}\n\t\t\t{header || (\n\t\t\t\t<div style={mergeStyles(styles.cardHeader, styles.textCenter)}>\n\t\t\t\t\t<h2 style={styles.cardTitle}>\n\t\t\t\t\t\t{isWaitlistMode ? 'Join the waitlist' : 'Create account'}\n\t\t\t\t\t</h2>\n\t\t\t\t\t<p style={styles.cardDescription}>\n\t\t\t\t\t\t{isWaitlistMode\n\t\t\t\t\t\t\t? 'Be the first to know when we launch'\n\t\t\t\t\t\t\t: inviteInfo?.valid\n\t\t\t\t\t\t\t\t? \"You've been invited to join\"\n\t\t\t\t\t\t\t\t: 'Sign up to get started'}\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Card content */}\n\t\t\t<div style={styles.cardContent}>\n\t\t\t\t{/* OAuth buttons (hide for waitlist mode) */}\n\t\t\t\t{providers.length > 0 && step === 'form' && !isWaitlistMode && (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<OAuthButtons\n\t\t\t\t\t\t\tproviders={providers}\n\t\t\t\t\t\t\tonProviderClick={handleOAuthSignUp}\n\t\t\t\t\t\t\tloadingProvider={loadingProvider}\n\t\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\t\ttheme={theme}\n\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<OrDivider theme={theme} />\n\t\t\t\t\t</>\n\t\t\t\t)}\n\n\t\t\t\t{/* Form content */}\n\t\t\t\t{renderContent()}\n\n\t\t\t\t{/* Sign in link (hide for waitlist mode) */}\n\t\t\t\t{!hideSignInLink && step === 'form' && !isWaitlistMode && (\n\t\t\t\t\t<p style={mergeStyles(styles.textCenter, styles.textSm, styles.textMuted, styles.mt4)}>\n\t\t\t\t\t\tAlready have an account?{' '}\n\t\t\t\t\t\t<a href={signInUrl} style={styles.link}>\n\t\t\t\t\t\t\tSign in\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</p>\n\t\t\t\t)}\n\n\t\t\t\t{/* Footer */}\n\t\t\t\t{footer}\n\t\t\t</div>\n\t\t</div>\n\t)\n\n\t// Wrap in card if needed\n\tif (showCard) {\n\t\treturn <div style={styles.card}>{content}</div>\n\t}\n\n\treturn content\n}\n\n// Decorative icons\nfunction MailIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"24\"\n\t\t\theight=\"24\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t>\n\t\t\t<rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\" />\n\t\t\t<path d=\"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\" />\n\t\t</svg>\n\t)\n}\n\nfunction CheckIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"24\"\n\t\t\theight=\"24\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t>\n\t\t\t<path d=\"M20 6 9 17l-5-5\" />\n\t\t</svg>\n\t)\n}\n","/**\n * useSignUpForm Hook\n *\n * Headless hook for sign-up form logic.\n * Supports: basic signup, invite codes, email verification, waitlist, additional fields.\n *\n * @example\n * ```tsx\n * // Basic usage\n * function MySignUp() {\n *   const signUp = useSignUpForm({ afterSignUpUrl: '/dashboard' });\n *   return <CustomSignUpUI {...signUp} />;\n * }\n *\n * // Platform mode (direct BetterAuth)\n * function PlatformSignUp() {\n *   const signUp = useSignUpForm({\n *     submitHandler: async ({ name, email, password }) => {\n *       const result = await authClient.signUp.email({ name, email, password });\n *       if (result.error) throw new Error(result.error.message);\n *       return { requiresVerification: false };\n *     },\n *   });\n *   return <CustomUI {...signUp} />;\n * }\n *\n * // With invite code\n * function InviteSignUp() {\n *   const signUp = useSignUpForm({\n *     inviteCode: 'abc123',\n *     requireInviteCode: true,\n *   });\n *   return <InviteSignUpUI {...signUp} />;\n * }\n * ```\n */\n\n'use client'\n\nimport { useCallback, useContext, useEffect, useMemo, useState } from 'react'\nimport { MIN_PASSWORD_LENGTH } from '../../constants'\nimport type { OAuthProvider } from '../../oauth'\nimport { safeRedirect } from '../security-utils'\nimport { SdkAuthContext, type SdkAuthContextValue } from '../services-context'\n\n// Re-export for convenience\nexport type { OAuthProvider } from '../../oauth'\n\n// ============================================\n// Types\n// ============================================\n\nexport type SignUpStep = 'form' | 'verify-email' | 'complete' | 'waitlist-joined'\n\nexport interface AdditionalField {\n\tname: string\n\tlabel: string\n\ttype: 'text' | 'email' | 'tel' | 'url' | 'select'\n\tplaceholder?: string\n\trequired?: boolean\n\toptions?: { label: string; value: string }[]\n}\n\nexport interface InviteInfo {\n\tvalid: boolean\n\temail?: string\n\trole?: string\n}\n\nexport interface SignUpFormState {\n\tname: string\n\temail: string\n\tpassword: string\n\tinviteCode: string\n\tcaptchaToken: string\n\tverificationCode: string\n\t[key: string]: string // for additional fields\n}\n\nexport interface SignUpSubmitResult {\n\trequiresVerification?: boolean\n\taccessToken?: string\n\trefreshToken?: string\n}\n\nexport interface UseSignUpFormOptions {\n\t/** OAuth providers to show */\n\tproviders?: OAuthProvider[]\n\t/** URL to redirect after sign up */\n\tafterSignUpUrl?: string\n\t/** Minimum password length */\n\tminPasswordLength?: number\n\t/** Initial invite code */\n\tinviteCode?: string\n\t/** Show invite code field */\n\tshowInviteCode?: boolean\n\t/** Require invite code */\n\trequireInviteCode?: boolean\n\t/** Additional fields to collect */\n\tadditionalFields?: AdditionalField[]\n\t/** Waitlist URL (enables waitlist mode) */\n\twaitlistUrl?: string\n\t/**\n\t * Custom submit handler. If provided, replaces context-based auth.\n\t * Return { requiresVerification: true } to show email verification step.\n\t * Throw error to indicate failure.\n\t */\n\tsubmitHandler?: (data: SignUpFormState) => Promise<SignUpSubmitResult | undefined>\n\t/**\n\t * Custom email verification handler.\n\t */\n\tverifyEmailHandler?: (email: string, code: string) => Promise<SignUpSubmitResult | undefined>\n\t/**\n\t * Custom invite verification handler.\n\t */\n\tverifyInviteHandler?: (code: string) => Promise<InviteInfo>\n\t/**\n\t * Custom waitlist handler.\n\t */\n\twaitlistHandler?: (email: string, name?: string) => Promise<void>\n\t/**\n\t * Custom OAuth handler. If provided, replaces default redirect.\n\t */\n\toauthHandler?: (provider: OAuthProvider) => Promise<void>\n\t/** Callback on successful sign up */\n\tonSuccess?: () => void\n\t/** Callback on error */\n\tonError?: (error: string) => void\n}\n\nexport interface UseSignUpFormReturn {\n\t// Form state\n\tform: SignUpFormState\n\tsetName: (name: string) => void\n\tsetEmail: (email: string) => void\n\tsetPassword: (password: string) => void\n\tsetInviteCode: (code: string) => void\n\tsetVerificationCode: (code: string) => void\n\tsetField: (name: string, value: string) => void\n\tresetForm: () => void\n\n\t// Multi-step\n\tstep: SignUpStep\n\tsetStep: (step: SignUpStep) => void\n\n\t// Validation\n\tpasswordValid: boolean\n\tminPasswordLength: number\n\n\t// Invite\n\tinviteInfo: InviteInfo | null\n\tisVerifyingInvite: boolean\n\n\t// UI state\n\tisLoading: boolean\n\tloadingProvider: OAuthProvider | null\n\terror: string | null\n\tclearError: () => void\n\n\t// Handlers\n\thandleSubmit: (e?: React.FormEvent) => Promise<void>\n\thandleVerifyEmail: (e?: React.FormEvent) => Promise<void>\n\thandleJoinWaitlist: (e?: React.FormEvent) => Promise<void>\n\thandleOAuthSignUp: (provider: OAuthProvider) => void\n\n\t// Config (for UI)\n\tproviders: OAuthProvider[]\n\tafterSignUpUrl: string\n\tadditionalFields: AdditionalField[]\n\tshowInviteCode: boolean\n\trequireInviteCode: boolean\n\tisWaitlistMode: boolean\n\twaitlistUrl?: string\n}\n\n// ============================================\n// Hook Implementation\n// ============================================\n\nexport function useSignUpForm(options: UseSignUpFormOptions = {}): UseSignUpFormReturn {\n\tconst {\n\t\tproviders = [],\n\t\tafterSignUpUrl = '/dashboard',\n\t\tminPasswordLength = MIN_PASSWORD_LENGTH, // NIST SP 800-63B (2023) recommends 12+ chars\n\t\tinviteCode: initialInviteCode = '',\n\t\tshowInviteCode = false,\n\t\trequireInviteCode = false,\n\t\tadditionalFields = [],\n\t\twaitlistUrl,\n\t\tsubmitHandler,\n\t\tverifyEmailHandler,\n\t\tverifyInviteHandler,\n\t\twaitlistHandler,\n\t\toauthHandler,\n\t\tonSuccess,\n\t\tonError,\n\t} = options\n\n\t// Get auth context (may be null if outside provider)\n\tconst authContext = useContext(SdkAuthContext) as SdkAuthContextValue | null\n\n\t// Multi-step state\n\tconst [step, setStep] = useState<SignUpStep>('form')\n\n\t// Form state\n\tconst [form, setForm] = useState<SignUpFormState>({\n\t\tname: '',\n\t\temail: '',\n\t\tpassword: '',\n\t\tinviteCode: initialInviteCode,\n\t\tverificationCode: '',\n\t\tcaptchaToken: '',\n\t})\n\n\t// Invite state\n\tconst [inviteInfo, setInviteInfo] = useState<InviteInfo | null>(null)\n\tconst [isVerifyingInvite, setIsVerifyingInvite] = useState(!!initialInviteCode)\n\n\t// UI state\n\tconst [isLoading, setIsLoading] = useState(false)\n\tconst [loadingProvider, setLoadingProvider] = useState<OAuthProvider | null>(null)\n\tconst [error, setError] = useState<string | null>(null)\n\n\t// Derived\n\tconst isWaitlistMode = !!waitlistUrl\n\tconst passwordValid = useMemo(\n\t\t() => form.password.length >= minPasswordLength,\n\t\t[form.password, minPasswordLength],\n\t)\n\n\t// Verify invite code on mount\n\tuseEffect(() => {\n\t\tasync function verifyInvite() {\n\t\t\tif (!initialInviteCode) {\n\t\t\t\tsetIsVerifyingInvite(false)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tif (verifyInviteHandler) {\n\t\t\t\t\tconst info = await verifyInviteHandler(initialInviteCode)\n\t\t\t\t\tif (info.valid) {\n\t\t\t\t\t\tsetInviteInfo(info)\n\t\t\t\t\t\tif (info.email) {\n\t\t\t\t\t\t\tsetForm((prev) => ({ ...prev, email: info.email! }))\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// If no verifyInviteHandler, skip invite verification\n\t\t\t} catch {\n\t\t\t\t// Ignore - just proceed without invite validation\n\t\t\t} finally {\n\t\t\t\tsetIsVerifyingInvite(false)\n\t\t\t}\n\t\t}\n\n\t\tverifyInvite()\n\t}, [initialInviteCode, verifyInviteHandler])\n\n\t// Form setters\n\tconst setName = useCallback((name: string) => {\n\t\tsetForm((prev) => ({ ...prev, name }))\n\t\tsetError(null)\n\t}, [])\n\n\tconst setEmail = useCallback((email: string) => {\n\t\tsetForm((prev) => ({ ...prev, email }))\n\t\tsetError(null)\n\t}, [])\n\n\tconst setPassword = useCallback((password: string) => {\n\t\tsetForm((prev) => ({ ...prev, password }))\n\t\tsetError(null)\n\t}, [])\n\n\tconst setInviteCode = useCallback((inviteCode: string) => {\n\t\tsetForm((prev) => ({ ...prev, inviteCode }))\n\t\tsetError(null)\n\t}, [])\n\n\tconst setVerificationCode = useCallback((verificationCode: string) => {\n\t\tsetForm((prev) => ({ ...prev, verificationCode }))\n\t\tsetError(null)\n\t}, [])\n\n\tconst setField = useCallback((name: string, value: string) => {\n\t\tsetForm((prev) => ({ ...prev, [name]: value }))\n\t\tsetError(null)\n\t}, [])\n\n\tconst resetForm = useCallback(() => {\n\t\tsetForm({\n\t\t\tname: '',\n\t\t\temail: '',\n\t\t\tpassword: '',\n\t\t\tinviteCode: initialInviteCode,\n\t\t\tcaptchaToken: '',\n\t\t\tverificationCode: '',\n\t\t})\n\t\tsetError(null)\n\t\tsetStep('form')\n\t}, [initialInviteCode])\n\n\tconst clearError = useCallback(() => {\n\t\tsetError(null)\n\t}, [])\n\n\t// Handle form submission\n\tconst handleSubmit = useCallback(\n\t\tasync (e?: React.FormEvent) => {\n\t\t\te?.preventDefault()\n\n\t\t\t// Validate invite code if required\n\t\t\tif (requireInviteCode && !form.inviteCode && !inviteInfo?.valid) {\n\t\t\t\tsetError('Invite code is required')\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Validate password\n\t\t\tif (!passwordValid) {\n\t\t\t\tsetError(`Password must be at least ${minPasswordLength} characters`)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tlet result: SignUpSubmitResult | undefined\n\n\t\t\t\tif (submitHandler) {\n\t\t\t\t\tresult = await submitHandler(form)\n\t\t\t\t} else {\n\t\t\t\t\t// Use auth context (SDK mode)\n\t\t\t\t\tif (!authContext) {\n\t\t\t\t\t\tsetError('SDK not configured. Please wrap your app with SylphxProvider.')\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\tconst registerResult = await authContext.register(form.name, form.email, form.password, {\n\t\t\t\t\t\tinvitationToken: form.inviteCode || undefined,\n\t\t\t\t\t\tcaptchaToken: form.captchaToken || undefined,\n\t\t\t\t\t})\n\t\t\t\t\tresult = {\n\t\t\t\t\t\trequiresVerification: registerResult.requiresVerification,\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Check if email verification is required\n\t\t\t\tif (result?.requiresVerification) {\n\t\t\t\t\tsetStep('verify-email')\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// Auth cookies are set server-side by the API\n\t\t\t\t// Just complete and redirect\n\n\t\t\t\tsetStep('complete')\n\t\t\t\tonSuccess?.()\n\n\t\t\t\t// Use safeRedirect to prevent XSS via malicious afterSignUpUrl\n\t\t\t\tsafeRedirect(afterSignUpUrl, { fallback: '/dashboard' })\n\t\t\t} catch (err) {\n\t\t\t\t// Distinguish between network errors and auth errors\n\t\t\t\tlet message: string\n\t\t\t\tif (err instanceof TypeError && err.message === 'Failed to fetch') {\n\t\t\t\t\tmessage = 'Unable to connect. Please check your internet connection and try again.'\n\t\t\t\t} else if (err instanceof Error) {\n\t\t\t\t\tmessage = err.message\n\t\t\t\t} else {\n\t\t\t\t\tmessage = 'Sign up failed'\n\t\t\t\t}\n\t\t\t\tsetError(message)\n\t\t\t\tonError?.(message)\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\tform,\n\t\t\tpasswordValid,\n\t\t\tminPasswordLength,\n\t\t\trequireInviteCode,\n\t\t\tinviteInfo,\n\t\t\tsubmitHandler,\n\t\t\tauthContext,\n\t\t\tafterSignUpUrl,\n\t\t\tonSuccess,\n\t\t\tonError,\n\t\t],\n\t)\n\n\t// Handle email verification\n\tconst handleVerifyEmail = useCallback(\n\t\tasync (e?: React.FormEvent) => {\n\t\t\te?.preventDefault()\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tlet _result: SignUpSubmitResult | undefined\n\n\t\t\t\tif (verifyEmailHandler) {\n\t\t\t\t\t_result = await verifyEmailHandler(form.email, form.verificationCode)\n\t\t\t\t} else {\n\t\t\t\t\t// Use auth context (SDK mode)\n\t\t\t\t\tif (!authContext) {\n\t\t\t\t\t\tsetError('SDK not configured. Please wrap your app with SylphxProvider.')\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\t// verifyEmail uses the verification token\n\t\t\t\t\t// The verification code IS the token in this case\n\t\t\t\t\tawait authContext.verifyEmail(form.verificationCode)\n\t\t\t\t\t_result = {}\n\t\t\t\t}\n\n\t\t\t\t// Auth cookies are set server-side by the API\n\t\t\t\t// Just complete and redirect\n\n\t\t\t\tsetStep('complete')\n\t\t\t\tonSuccess?.()\n\n\t\t\t\t// Use safeRedirect to prevent XSS via malicious afterSignUpUrl\n\t\t\t\tsafeRedirect(afterSignUpUrl, { fallback: '/dashboard' })\n\t\t\t} catch (err) {\n\t\t\t\t// Distinguish between network errors and auth errors\n\t\t\t\tlet message: string\n\t\t\t\tif (err instanceof TypeError && err.message === 'Failed to fetch') {\n\t\t\t\t\tmessage = 'Unable to connect. Please check your internet connection and try again.'\n\t\t\t\t} else if (err instanceof Error) {\n\t\t\t\t\tmessage = err.message\n\t\t\t\t} else {\n\t\t\t\t\tmessage = 'Verification failed'\n\t\t\t\t}\n\t\t\t\tsetError(message)\n\t\t\t\tonError?.(message)\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\tform.email,\n\t\t\tform.verificationCode,\n\t\t\tverifyEmailHandler,\n\t\t\tauthContext,\n\t\t\tafterSignUpUrl,\n\t\t\tonSuccess,\n\t\t\tonError,\n\t\t],\n\t)\n\n\t// Handle waitlist join\n\tconst handleJoinWaitlist = useCallback(\n\t\tasync (e?: React.FormEvent) => {\n\t\t\te?.preventDefault()\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tif (waitlistHandler) {\n\t\t\t\t\tawait waitlistHandler(form.email, form.name || undefined)\n\t\t\t\t} else {\n\t\t\t\t\t// Waitlist requires custom handler\n\t\t\t\t\tthrow new Error('Waitlist join requires a custom waitlistHandler')\n\t\t\t\t}\n\n\t\t\t\tsetStep('waitlist-joined')\n\t\t\t\tonSuccess?.()\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : 'Failed to join waitlist'\n\t\t\t\tsetError(message)\n\t\t\t\tonError?.(message)\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[form.email, form.name, waitlistHandler, onSuccess, onError],\n\t)\n\n\t// OAuth handler\n\tconst handleOAuthSignUp = useCallback(\n\t\t(provider: OAuthProvider) => {\n\t\t\tsetLoadingProvider(provider)\n\t\t\tsetError(null)\n\n\t\t\tif (oauthHandler) {\n\t\t\t\toauthHandler(provider).catch((err) => {\n\t\t\t\t\tsetError(err instanceof Error ? err.message : 'OAuth sign up failed')\n\t\t\t\t\tsetLoadingProvider(null)\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\t// OAuth requires redirect - this should be handled by the platform\n\t\t\t\t// SDK apps should configure oauthHandler or use <SignUp> component\n\t\t\t\tsetError('OAuth sign-up requires a custom oauthHandler or use the SignUp component')\n\t\t\t\tsetLoadingProvider(null)\n\t\t\t}\n\t\t},\n\t\t[oauthHandler],\n\t)\n\n\treturn {\n\t\t// Form state\n\t\tform,\n\t\tsetName,\n\t\tsetEmail,\n\t\tsetPassword,\n\t\tsetInviteCode,\n\t\tsetVerificationCode,\n\t\tsetField,\n\t\tresetForm,\n\n\t\t// Multi-step\n\t\tstep,\n\t\tsetStep,\n\n\t\t// Validation\n\t\tpasswordValid,\n\t\tminPasswordLength,\n\n\t\t// Invite\n\t\tinviteInfo,\n\t\tisVerifyingInvite,\n\n\t\t// UI state\n\t\tisLoading,\n\t\tloadingProvider,\n\t\terror,\n\t\tclearError,\n\n\t\t// Handlers\n\t\thandleSubmit,\n\t\thandleVerifyEmail,\n\t\thandleJoinWaitlist,\n\t\thandleOAuthSignUp,\n\n\t\t// Config\n\t\tproviders,\n\t\tafterSignUpUrl,\n\t\tadditionalFields,\n\t\tshowInviteCode,\n\t\trequireInviteCode,\n\t\tisWaitlistMode,\n\t\twaitlistUrl,\n\t}\n}\n","/**\n * SignUp Component\n *\n * Flexible sign-up component supporting redirect, embedded, and modal modes.\n */\n\n'use client'\n\nimport { useState } from 'react'\nimport type { OAuthProviderId } from '../../types'\nimport { useSafeAuth, useSafeUser, useSdkReady } from '../hooks'\nimport { defaultTheme, Modal, type OAuthProvider, SignUpForm, type ThemeVariables } from '../ui'\n\n// Re-export for convenience\n\nexport interface SignUpProps {\n\t/** URL to redirect to after successful sign up */\n\tafterSignUpUrl?: string\n\t/** URL to redirect users to a waitlist page */\n\twaitlistUrl?: string\n\t/**\n\t * Display mode:\n\t * - 'redirect': Navigate to platform signup page (default)\n\t * - 'embedded': Show full sign-up form inline\n\t * - 'modal': Show full sign-up form in a modal\n\t */\n\tmode?: 'redirect' | 'embedded' | 'modal'\n\t/**\n\t * OAuth providers to show (SDK-level filtering)\n\t * This further filters the providers enabled at platform and app level.\n\t * - undefined/null = show all app-enabled providers\n\t * - [] = hide OAuth section (email only)\n\t * - ['google', 'github'] = only show these (if they're app-enabled)\n\t */\n\tproviders?: OAuthProviderId[] | null\n\t/** Theme variables for embedded/modal mode */\n\ttheme?: ThemeVariables\n\t/** Custom appearance for redirect button */\n\tappearance?: {\n\t\tbaseStyle?: React.CSSProperties\n\t\thoverStyle?: React.CSSProperties\n\t}\n\t/** Custom class name */\n\tclassName?: string\n\t/** Button content (for redirect mode) */\n\tchildren?: React.ReactNode\n\t/** URL for sign in link (embedded/modal mode) */\n\tsignInUrl?: string\n\t/** Terms of Service URL */\n\ttermsUrl?: string\n\t/** Privacy Policy URL */\n\tprivacyUrl?: string\n\t/** Initial invite code */\n\tinviteCode?: string\n\t/** Show invite code field */\n\tshowInviteCode?: boolean\n\t/** Require invite code */\n\trequireInviteCode?: boolean\n\t/** Called on successful sign up */\n\tonSuccess?: () => void\n\t/** Called on error */\n\tonError?: (error: string) => void\n\t/** Show card wrapper (embedded mode, default: true) */\n\tshowCard?: boolean\n}\n\n/**\n * SignUp component with multiple display modes\n *\n * @example\n * ```tsx\n * // Redirect mode (default) - navigates to platform signup\n * <SignUp afterSignUpUrl=\"/onboarding\" />\n *\n * // Embedded mode - shows full form inline\n * <SignUp mode=\"embedded\" afterSignUpUrl=\"/onboarding\" />\n *\n * // Modal mode - shows form in a modal (for buttons)\n * <SignUp mode=\"modal\" afterSignUpUrl=\"/onboarding\">\n *   Create Account\n * </SignUp>\n *\n * // With specific OAuth providers\n * <SignUp mode=\"embedded\" providers={['google', 'github']} />\n *\n * // Email/password only\n * <SignUp mode=\"embedded\" providers={[]} />\n *\n * // With invite code\n * <SignUp mode=\"embedded\" showInviteCode requireInviteCode />\n *\n * // With waitlist (redirects instead of signup)\n * <SignUp mode=\"embedded\" waitlistUrl=\"/waitlist\" />\n * ```\n */\nexport function SignUp({\n\tafterSignUpUrl,\n\twaitlistUrl,\n\tmode = 'redirect',\n\tproviders,\n\ttheme = defaultTheme,\n\tappearance,\n\tclassName,\n\tchildren,\n\tsignInUrl = '/sign-in',\n\ttermsUrl = '/terms',\n\tprivacyUrl = '/privacy',\n\tinviteCode,\n\tshowInviteCode = false,\n\trequireInviteCode = false,\n\tonSuccess,\n\tonError,\n\tshowCard = true,\n}: SignUpProps) {\n\t// SDK readiness check (SSOT for SSR safety and configuration)\n\tconst { isReady, renderError } = useSdkReady({\n\t\tservices: ['auth', 'user'],\n\t\tcomponentType: 'sign-up',\n\t\ttheme,\n\t})\n\n\tconst { signUp } = useSafeAuth()\n\tconst { isSignedIn, isLoaded } = useSafeUser()\n\tconst [modalOpen, setModalOpen] = useState(false)\n\n\t// SDK not ready - render error or null\n\tif (!isReady) {\n\t\treturn renderError()\n\t}\n\n\t// Don't show if already signed in\n\tif (isLoaded && isSignedIn) {\n\t\treturn null\n\t}\n\n\t// Convert OAuthProviderId to OAuthProvider (compatible types)\n\tconst oauthProviders = providers as OAuthProvider[] | undefined | null\n\n\t// Redirect mode - show button that navigates to platform\n\tif (mode === 'redirect') {\n\t\tconst handleClick = () => {\n\t\t\tsignUp({\n\t\t\t\tredirectUrl: afterSignUpUrl || window.location.href,\n\t\t\t\tproviders,\n\t\t\t})\n\t\t}\n\n\t\tconst defaultStyles: React.CSSProperties = {\n\t\t\tdisplay: 'inline-flex',\n\t\t\talignItems: 'center',\n\t\t\tjustifyContent: 'center',\n\t\t\tpadding: '0.5rem 1rem',\n\t\t\tfontSize: '0.875rem',\n\t\t\tfontWeight: 500,\n\t\t\tborderRadius: '0.375rem',\n\t\t\tborder: '1px solid #e5e7eb',\n\t\t\tbackgroundColor: '#fff',\n\t\t\tcolor: '#000',\n\t\t\tcursor: 'pointer',\n\t\t\ttransition: 'background-color 0.2s',\n\t\t\t...appearance?.baseStyle,\n\t\t}\n\n\t\treturn (\n\t\t\t<button\n\t\t\t\tonClick={handleClick}\n\t\t\t\tclassName={className}\n\t\t\t\tstyle={className ? undefined : defaultStyles}\n\t\t\t\ttype=\"button\"\n\t\t\t>\n\t\t\t\t{children || 'Sign Up'}\n\t\t\t</button>\n\t\t)\n\t}\n\n\t// Embedded mode - show form inline\n\tif (mode === 'embedded') {\n\t\treturn (\n\t\t\t<SignUpForm\n\t\t\t\ttheme={theme}\n\t\t\t\tproviders={oauthProviders || []}\n\t\t\t\tafterSignUpUrl={afterSignUpUrl || '/dashboard'}\n\t\t\t\tsignInUrl={signInUrl}\n\t\t\t\ttermsUrl={termsUrl}\n\t\t\t\tprivacyUrl={privacyUrl}\n\t\t\t\tinviteCode={inviteCode}\n\t\t\t\tshowInviteCode={showInviteCode}\n\t\t\t\trequireInviteCode={requireInviteCode}\n\t\t\t\twaitlistUrl={waitlistUrl}\n\t\t\t\tonSuccess={onSuccess}\n\t\t\t\tonError={onError}\n\t\t\t\tshowCard={showCard}\n\t\t\t/>\n\t\t)\n\t}\n\n\t// Modal mode - show button that opens modal\n\tif (mode === 'modal') {\n\t\tconst defaultStyles: React.CSSProperties = {\n\t\t\tdisplay: 'inline-flex',\n\t\t\talignItems: 'center',\n\t\t\tjustifyContent: 'center',\n\t\t\tpadding: '0.5rem 1rem',\n\t\t\tfontSize: '0.875rem',\n\t\t\tfontWeight: 500,\n\t\t\tborderRadius: '0.375rem',\n\t\t\tborder: '1px solid #e5e7eb',\n\t\t\tbackgroundColor: '#fff',\n\t\t\tcolor: '#000',\n\t\t\tcursor: 'pointer',\n\t\t\ttransition: 'background-color 0.2s',\n\t\t\t...appearance?.baseStyle,\n\t\t}\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<button\n\t\t\t\t\tonClick={() => setModalOpen(true)}\n\t\t\t\t\tclassName={className}\n\t\t\t\t\tstyle={className ? undefined : defaultStyles}\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t>\n\t\t\t\t\t{children || 'Sign Up'}\n\t\t\t\t</button>\n\t\t\t\t<Modal open={modalOpen} onClose={() => setModalOpen(false)} theme={theme}>\n\t\t\t\t\t<SignUpForm\n\t\t\t\t\t\ttheme={theme}\n\t\t\t\t\t\tproviders={oauthProviders || []}\n\t\t\t\t\t\tafterSignUpUrl={afterSignUpUrl || '/dashboard'}\n\t\t\t\t\t\tsignInUrl={signInUrl}\n\t\t\t\t\t\ttermsUrl={termsUrl}\n\t\t\t\t\t\tprivacyUrl={privacyUrl}\n\t\t\t\t\t\tinviteCode={inviteCode}\n\t\t\t\t\t\tshowInviteCode={showInviteCode}\n\t\t\t\t\t\trequireInviteCode={requireInviteCode}\n\t\t\t\t\t\twaitlistUrl={waitlistUrl}\n\t\t\t\t\t\tonSuccess={() => {\n\t\t\t\t\t\t\tsetModalOpen(false)\n\t\t\t\t\t\t\tonSuccess?.()\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonError={onError}\n\t\t\t\t\t\tshowCard={false}\n\t\t\t\t\t/>\n\t\t\t\t</Modal>\n\t\t\t</>\n\t\t)\n\t}\n\n\treturn null\n}\n","/**\n * UserButton Component\n *\n * Displays user avatar with dropdown menu for profile/sign out.\n */\n\n'use client'\n\nimport { useEffect, useRef, useState } from 'react'\nimport { useSafeAuth, useSafeUser, useSdkReady } from '../hooks'\nimport { defaultTheme, injectGlobalStyles, type ThemeVariables } from '../ui/styles'\n\nexport interface UserButtonProps {\n\t/** URL to redirect to after sign out */\n\tafterSignOutUrl?: string\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Custom appearance */\n\tappearance?: {\n\t\tavatarSize?: number\n\t\tbaseStyle?: React.CSSProperties\n\t\tmenuStyle?: React.CSSProperties\n\t}\n\t/** Custom class name */\n\tclassName?: string\n\t/** Show user name next to avatar */\n\tshowName?: boolean\n}\n\n/**\n * User avatar button with dropdown menu\n *\n * @example\n * ```tsx\n * <UserButton afterSignOutUrl=\"/\" />\n *\n * // With name display\n * <UserButton showName afterSignOutUrl=\"/\" />\n * ```\n */\nexport function UserButton({\n\tafterSignOutUrl = '/',\n\ttheme = defaultTheme,\n\tappearance,\n\tclassName,\n\tshowName = false,\n}: UserButtonProps) {\n\t// SDK readiness check with silent fallback (returns null if not configured)\n\tconst { isReady } = useSdkReady({\n\t\tservices: ['auth', 'user'],\n\t\tcomponentType: 'user-button',\n\t\ttheme,\n\t\tfallback: 'null', // Silent - don't show error, just return null\n\t})\n\n\tconst { user, isLoaded, isSignedIn } = useSafeUser()\n\tconst { signOut } = useSafeAuth()\n\tconst [isOpen, setIsOpen] = useState(false)\n\tconst menuRef = useRef<HTMLDivElement>(null)\n\tconst buttonRef = useRef<HTMLButtonElement>(null)\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// Close menu on outside click\n\tuseEffect(() => {\n\t\tconst handleClickOutside = (event: MouseEvent) => {\n\t\t\tif (\n\t\t\t\tmenuRef.current &&\n\t\t\t\tbuttonRef.current &&\n\t\t\t\t!menuRef.current.contains(event.target as Node) &&\n\t\t\t\t!buttonRef.current.contains(event.target as Node)\n\t\t\t) {\n\t\t\t\tsetIsOpen(false)\n\t\t\t}\n\t\t}\n\n\t\tdocument.addEventListener('mousedown', handleClickOutside)\n\t\treturn () => document.removeEventListener('mousedown', handleClickOutside)\n\t}, [])\n\n\t// Close menu on Escape key\n\tuseEffect(() => {\n\t\tconst handleEscape = (event: KeyboardEvent) => {\n\t\t\tif (event.key === 'Escape' && isOpen) {\n\t\t\t\tsetIsOpen(false)\n\t\t\t\tbuttonRef.current?.focus()\n\t\t\t}\n\t\t}\n\n\t\tdocument.addEventListener('keydown', handleEscape)\n\t\treturn () => document.removeEventListener('keydown', handleEscape)\n\t}, [isOpen])\n\n\t// Don't render if SDK not ready or user not signed in\n\tif (!isReady || !isLoaded || !isSignedIn || !user) {\n\t\treturn null\n\t}\n\n\tconst avatarSize = appearance?.avatarSize || 32\n\tconst initials = user.name\n\t\t? user.name\n\t\t\t\t.split(' ')\n\t\t\t\t.map((n: string) => n[0])\n\t\t\t\t.join('')\n\t\t\t\t.toUpperCase()\n\t\t\t\t.slice(0, 2)\n\t\t: user.email[0].toUpperCase()\n\n\tconst handleSignOut = async () => {\n\t\tsetIsOpen(false)\n\t\tawait signOut({ redirectUrl: afterSignOutUrl })\n\t}\n\n\tconst containerStyles: React.CSSProperties = {\n\t\tposition: 'relative',\n\t\tdisplay: 'inline-block',\n\t\t...appearance?.baseStyle,\n\t}\n\n\tconst buttonStyles: React.CSSProperties = {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tgap: '0.5rem',\n\t\tpadding: '0.25rem',\n\t\tborder: 'none',\n\t\tbackground: 'transparent',\n\t\tcursor: 'pointer',\n\t\tborderRadius: '9999px',\n\t}\n\n\tconst avatarStyles: React.CSSProperties = {\n\t\twidth: avatarSize,\n\t\theight: avatarSize,\n\t\tborderRadius: '9999px',\n\t\tbackgroundColor: theme.colorMuted,\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'center',\n\t\tfontSize: avatarSize * 0.4,\n\t\tfontWeight: 500,\n\t\tcolor: theme.colorMutedForeground,\n\t\toverflow: 'hidden',\n\t}\n\n\tconst menuStyles: React.CSSProperties = {\n\t\tposition: 'absolute',\n\t\ttop: 'calc(100% + 0.5rem)',\n\t\tright: 0,\n\t\tminWidth: '200px',\n\t\tbackgroundColor: theme.colorBackground,\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t\tboxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.1)',\n\t\tzIndex: 50,\n\t\toverflow: 'hidden',\n\t\t...appearance?.menuStyle,\n\t}\n\n\tconst menuItemStyles: React.CSSProperties = {\n\t\tdisplay: 'block',\n\t\twidth: '100%',\n\t\tpadding: '0.75rem 1rem',\n\t\ttextAlign: 'left',\n\t\tborder: 'none',\n\t\tbackground: 'transparent',\n\t\tcursor: 'pointer',\n\t\tfontSize: theme.fontSizeSm,\n\t\tcolor: theme.colorForeground,\n\t}\n\n\treturn (\n\t\t<div style={containerStyles} className={className}>\n\t\t\t<button\n\t\t\t\tref={buttonRef}\n\t\t\t\tonClick={() => setIsOpen(!isOpen)}\n\t\t\t\tstyle={buttonStyles}\n\t\t\t\ttype=\"button\"\n\t\t\t\taria-label={`User menu for ${user.name || user.email}`}\n\t\t\t\taria-haspopup=\"menu\"\n\t\t\t\taria-expanded={isOpen}\n\t\t\t>\n\t\t\t\t<div style={avatarStyles} aria-hidden=\"true\">\n\t\t\t\t\t{user.image ? (\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tsrc={user.image}\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\t\theight: '100%',\n\t\t\t\t\t\t\t\tobjectFit: 'cover',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : (\n\t\t\t\t\t\tinitials\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t{showName && (\n\t\t\t\t\t<span\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\tcolor: theme.colorForeground,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{user.name || user.email}\n\t\t\t\t\t</span>\n\t\t\t\t)}\n\t\t\t</button>\n\n\t\t\t{isOpen && (\n\t\t\t\t<div ref={menuRef} style={menuStyles} role=\"menu\" aria-label=\"User menu\">\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tpadding: '0.75rem 1rem',\n\t\t\t\t\t\t\tborderBottom: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\tcolor: theme.colorForeground,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{user.name || 'User'}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\tmarginTop: '0.125rem',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{user.email}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<button\n\t\t\t\t\t\tonClick={handleSignOut}\n\t\t\t\t\t\tstyle={menuItemStyles}\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\trole=\"menuitem\"\n\t\t\t\t\t\tonMouseEnter={(e) => {\n\t\t\t\t\t\t\te.currentTarget.style.backgroundColor = theme.colorMuted\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonMouseLeave={(e) => {\n\t\t\t\t\t\t\te.currentTarget.style.backgroundColor = 'transparent'\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonFocus={(e) => {\n\t\t\t\t\t\t\te.currentTarget.style.backgroundColor = theme.colorMuted\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonBlur={(e) => {\n\t\t\t\t\t\t\te.currentTarget.style.backgroundColor = 'transparent'\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tSign out\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n","/**\n * VerifyEmail Component\n *\n * Handles email verification with a code or token.\n * Matches Clerk's email verification flow.\n */\n\n'use client'\n\nimport { type FormEvent, useCallback, useEffect, useState } from 'react'\nimport { EMAIL_RESEND_COOLDOWN_TICK_MS, UI_COPY_FEEDBACK_MS } from '../../constants'\nimport { useSafeAuth, useSafeUser, useSdkReady } from '../hooks'\nimport { safeRedirect } from '../security-utils'\nimport {\n\tbaseStyles,\n\tdefaultTheme,\n\tinjectGlobalStyles,\n\tmergeStyles,\n\ttype ThemeVariables,\n} from '../ui/styles'\n\nexport interface VerifyEmailProps {\n\t/** Verification token (if using link-based verification) */\n\ttoken?: string\n\t/** Email address being verified (for code-based verification) */\n\temail?: string\n\t/** URL to redirect after successful verification */\n\tafterVerifyUrl?: string\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Called on successful verification */\n\tonSuccess?: () => void\n\t/** Called on error */\n\tonError?: (error: string) => void\n\t/** Show card wrapper */\n\tshowCard?: boolean\n\t/** Custom header content */\n\theader?: React.ReactNode\n}\n\n/**\n * VerifyEmail component for email verification\n *\n * @example\n * ```tsx\n * // Token-based (from URL)\n * const searchParams = useSearchParams()\n * const token = searchParams.get('token')\n * <VerifyEmail token={token} afterVerifyUrl=\"/dashboard\" />\n *\n * // Code-based (user enters code)\n * <VerifyEmail email=\"user@example.com\" afterVerifyUrl=\"/dashboard\" />\n * ```\n */\nexport function VerifyEmail({\n\ttoken,\n\temail,\n\tafterVerifyUrl = '/dashboard',\n\ttheme = defaultTheme,\n\tonSuccess,\n\tonError,\n\tshowCard = true,\n\theader,\n}: VerifyEmailProps) {\n\t// SDK readiness check (SSOT for SSR safety and configuration)\n\tconst { isReady, renderError } = useSdkReady({\n\t\tservices: ['auth', 'user'],\n\t\tcomponentType: 'auth',\n\t\ttheme,\n\t})\n\n\tconst { verifyEmail, resendVerificationEmail } = useSafeAuth()\n\tconst { isSignedIn, isLoaded } = useSafeUser()\n\tconst styles = baseStyles(theme)\n\n\tconst [code, setCode] = useState('')\n\tconst [error, setError] = useState<string | null>(null)\n\tconst [isLoading, setIsLoading] = useState(false)\n\tconst [isResending, setIsResending] = useState(false)\n\tconst [isSuccess, setIsSuccess] = useState(false)\n\tconst [autoVerified, setAutoVerified] = useState(false)\n\tconst [focusedField, setFocusedField] = useState<string | null>(null)\n\tconst [resendCooldown, setResendCooldown] = useState(0)\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// SDK not ready - render error or null\n\tif (!isReady) {\n\t\treturn renderError()\n\t}\n\n\t// Resend cooldown timer\n\t// biome-ignore lint/correctness/useHookAtTopLevel: hooks precede return in component lifecycle\n\tuseEffect(() => {\n\t\tif (resendCooldown > 0) {\n\t\t\tconst timer = setTimeout(() => setResendCooldown((c) => c - 1), EMAIL_RESEND_COOLDOWN_TICK_MS)\n\t\t\treturn () => clearTimeout(timer)\n\t\t}\n\t}, [resendCooldown])\n\n\t// biome-ignore lint/correctness/useHookAtTopLevel: hooks precede return in component lifecycle\n\tconst handleVerifyToken = useCallback(async () => {\n\t\tif (!token) return\n\n\t\tsetIsLoading(true)\n\t\tsetError(null)\n\n\t\ttry {\n\t\t\tif (!verifyEmail) {\n\t\t\t\tthrow new Error('Authentication not configured')\n\t\t\t}\n\t\t\tawait verifyEmail({ token })\n\t\t\tsetIsSuccess(true)\n\t\t\tonSuccess?.()\n\n\t\t\t// Redirect after short delay\n\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tsafeRedirect(afterVerifyUrl, { fallback: '/dashboard' })\n\t\t\t\t}, UI_COPY_FEEDBACK_MS)\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : 'Verification failed'\n\t\t\tsetError(message)\n\t\t\tonError?.(message)\n\t\t} finally {\n\t\t\tsetIsLoading(false)\n\t\t}\n\t}, [token, verifyEmail, afterVerifyUrl, onSuccess, onError])\n\n\t// Auto-verify if token is provided\n\t// biome-ignore lint/correctness/useHookAtTopLevel: hooks precede return in component lifecycle\n\tuseEffect(() => {\n\t\tif (token && !autoVerified && !isSuccess) {\n\t\t\tsetAutoVerified(true)\n\t\t\thandleVerifyToken()\n\t\t}\n\t}, [token, autoVerified, handleVerifyToken, isSuccess])\n\n\t// biome-ignore lint/correctness/useHookAtTopLevel: hooks precede return in component lifecycle\n\tconst handleSubmitCode = useCallback(\n\t\tasync (e: FormEvent) => {\n\t\t\te.preventDefault()\n\t\t\tif (!code) return\n\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tif (!verifyEmail) {\n\t\t\t\t\tthrow new Error('Authentication not configured')\n\t\t\t\t}\n\t\t\t\t// For code-based verification, we treat the code as the token\n\t\t\t\tawait verifyEmail({ token: code })\n\t\t\t\tsetIsSuccess(true)\n\t\t\t\tonSuccess?.()\n\n\t\t\t\t// Redirect after short delay\n\t\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tsafeRedirect(afterVerifyUrl, { fallback: '/dashboard' })\n\t\t\t\t\t}, UI_COPY_FEEDBACK_MS)\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : 'Invalid verification code'\n\t\t\t\tsetError(message)\n\t\t\t\tonError?.(message)\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[code, verifyEmail, afterVerifyUrl, onSuccess, onError],\n\t)\n\n\t// biome-ignore lint/correctness/useHookAtTopLevel: hooks precede return in component lifecycle\n\tconst handleResend = useCallback(async () => {\n\t\tif (!email || resendCooldown > 0) return\n\n\t\tsetIsResending(true)\n\t\tsetError(null)\n\n\t\ttry {\n\t\t\tif (!resendVerificationEmail) {\n\t\t\t\tthrow new Error('Authentication not configured')\n\t\t\t}\n\t\t\tawait resendVerificationEmail({ email })\n\t\t\tsetResendCooldown(60) // 60 second cooldown\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to resend email'\n\t\t\tsetError(message)\n\t\t\tonError?.(message)\n\t\t} finally {\n\t\t\tsetIsResending(false)\n\t\t}\n\t}, [email, resendCooldown, resendVerificationEmail, onError])\n\n\t// Redirect if already signed in and verified\n\tif (isLoaded && isSignedIn) {\n\t\tif (typeof window !== 'undefined') {\n\t\t\tsafeRedirect(afterVerifyUrl, { fallback: '/dashboard' })\n\t\t}\n\t\treturn null\n\t}\n\n\tconst renderContent = () => {\n\t\t// Loading state for auto-verification\n\t\tif (token && isLoading && !isSuccess) {\n\t\t\treturn (\n\t\t\t\t<div style={styles.textCenter}>\n\t\t\t\t\t<span\n\t\t\t\t\t\tstyle={mergeStyles(styles.spinner, {\n\t\t\t\t\t\t\twidth: '2rem',\n\t\t\t\t\t\t\theight: '2rem',\n\t\t\t\t\t\t\tmargin: '0 auto 1rem',\n\t\t\t\t\t\t})}\n\t\t\t\t\t/>\n\t\t\t\t\t<p style={styles.textMuted}>Verifying your email...</p>\n\t\t\t\t</div>\n\t\t\t)\n\t\t}\n\n\t\t// Success state\n\t\tif (isSuccess) {\n\t\t\treturn (\n\t\t\t\t<div style={styles.textCenter}>\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={mergeStyles(styles.flexCenter, {\n\t\t\t\t\t\t\twidth: '3rem',\n\t\t\t\t\t\t\theight: '3rem',\n\t\t\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\t\t\tbackgroundColor: `${theme.colorSuccess}15`,\n\t\t\t\t\t\t\tmargin: '0 auto 1rem',\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t<CheckIcon color={theme.colorSuccess} />\n\t\t\t\t\t</div>\n\t\t\t\t\t<h3 style={mergeStyles(styles.cardTitle, styles.mb2)}>Email verified!</h3>\n\t\t\t\t\t<p style={mergeStyles(styles.textMuted, styles.textSm, styles.mb4)}>\n\t\t\t\t\t\tYour email has been verified. Redirecting...\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t)\n\t\t}\n\n\t\t// Error state for token verification\n\t\tif (token && error) {\n\t\t\treturn (\n\t\t\t\t<div style={styles.textCenter}>\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={mergeStyles(styles.flexCenter, {\n\t\t\t\t\t\t\twidth: '3rem',\n\t\t\t\t\t\t\theight: '3rem',\n\t\t\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\t\t\tbackgroundColor: `${theme.colorDestructive}15`,\n\t\t\t\t\t\t\tmargin: '0 auto 1rem',\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t<XIcon color={theme.colorDestructive} />\n\t\t\t\t\t</div>\n\t\t\t\t\t<h3 style={mergeStyles(styles.cardTitle, styles.mb2)}>Verification failed</h3>\n\t\t\t\t\t<p style={mergeStyles(styles.textMuted, styles.textSm, styles.mb4)}>{error}</p>\n\t\t\t\t\t{email && (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={handleResend}\n\t\t\t\t\t\t\tdisabled={isResending || resendCooldown > 0}\n\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\t\t\tstyles.buttonPrimary,\n\t\t\t\t\t\t\t\tstyles.buttonFullWidth,\n\t\t\t\t\t\t\t\tisResending || resendCooldown > 0 ? styles.buttonDisabled : {},\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{isResending\n\t\t\t\t\t\t\t\t? 'Sending...'\n\t\t\t\t\t\t\t\t: resendCooldown > 0\n\t\t\t\t\t\t\t\t\t? `Resend in ${resendCooldown}s`\n\t\t\t\t\t\t\t\t\t: 'Resend verification email'}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)\n\t\t}\n\n\t\t// Code entry form (when no token provided)\n\t\treturn (\n\t\t\t<form onSubmit={handleSubmitCode}>\n\t\t\t\t<div style={mergeStyles(styles.textCenter, styles.mb4)}>\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={mergeStyles(styles.flexCenter, {\n\t\t\t\t\t\t\twidth: '3rem',\n\t\t\t\t\t\t\theight: '3rem',\n\t\t\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\t\t\tbackgroundColor: `${theme.colorPrimary}15`,\n\t\t\t\t\t\t\tmargin: '0 auto 1rem',\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t<MailIcon color={theme.colorPrimary} />\n\t\t\t\t\t</div>\n\t\t\t\t\t{email && (\n\t\t\t\t\t\t<p style={mergeStyles(styles.textMuted, styles.textSm)}>\n\t\t\t\t\t\t\tWe sent a verification code to <strong>{email}</strong>\n\t\t\t\t\t\t</p>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\n\t\t\t\t<div style={styles.formGroup}>\n\t\t\t\t\t<label htmlFor=\"verify-code\" style={styles.label}>\n\t\t\t\t\t\tVerification code\n\t\t\t\t\t</label>\n\t\t\t\t\t<input\n\t\t\t\t\t\tid=\"verify-code\"\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tvalue={code}\n\t\t\t\t\t\tonChange={(e) => {\n\t\t\t\t\t\t\tsetCode(e.target.value)\n\t\t\t\t\t\t\tsetError(null)\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonFocus={() => setFocusedField('code')}\n\t\t\t\t\t\tonBlur={() => setFocusedField(null)}\n\t\t\t\t\t\tplaceholder=\"Enter code\"\n\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\tautoComplete=\"one-time-code\"\n\t\t\t\t\t\trequired\n\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\tstyles.input,\n\t\t\t\t\t\t\tfocusedField === 'code' ? styles.inputFocus : {},\n\t\t\t\t\t\t\tisLoading ? styles.inputDisabled : {},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\t\t\tletterSpacing: '0.5em',\n\t\t\t\t\t\t\t\tfontSize: '1.25rem',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\n\t\t\t\t{error && <div style={mergeStyles(styles.alert, styles.alertError)}>{error}</div>}\n\n\t\t\t\t<button\n\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\tdisabled={isLoading || !code}\n\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\tstyles.buttonPrimary,\n\t\t\t\t\t\tstyles.buttonFullWidth,\n\t\t\t\t\t\tisLoading || !code ? styles.buttonDisabled : {},\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t{isLoading ? (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t\t\tVerifying...\n\t\t\t\t\t\t</>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t'Verify email'\n\t\t\t\t\t)}\n\t\t\t\t</button>\n\n\t\t\t\t{email && (\n\t\t\t\t\t<p style={mergeStyles(styles.textCenter, styles.textSm, styles.textMuted, styles.mt4)}>\n\t\t\t\t\t\tDidn't receive it?{' '}\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={handleResend}\n\t\t\t\t\t\t\tdisabled={isResending || resendCooldown > 0}\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.link, {\n\t\t\t\t\t\t\t\tbackground: 'none',\n\t\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\tcursor: resendCooldown > 0 ? 'default' : 'pointer',\n\t\t\t\t\t\t\t\topacity: resendCooldown > 0 ? 0.5 : 1,\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{isResending\n\t\t\t\t\t\t\t\t? 'Sending...'\n\t\t\t\t\t\t\t\t: resendCooldown > 0\n\t\t\t\t\t\t\t\t\t? `Resend in ${resendCooldown}s`\n\t\t\t\t\t\t\t\t\t: 'Resend code'}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</p>\n\t\t\t\t)}\n\t\t\t</form>\n\t\t)\n\t}\n\n\tconst content = (\n\t\t<div style={styles.container}>\n\t\t\t{header || (\n\t\t\t\t<div style={mergeStyles(styles.cardHeader, styles.textCenter)}>\n\t\t\t\t\t<h2 style={styles.cardTitle}>Verify your email</h2>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<div style={styles.cardContent}>{renderContent()}</div>\n\t\t</div>\n\t)\n\n\tif (showCard) {\n\t\treturn <div style={styles.card}>{content}</div>\n\t}\n\n\treturn content\n}\n\nfunction MailIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\trole=\"img\"\n\t\t\taria-label=\"Mail\"\n\t\t\twidth=\"24\"\n\t\t\theight=\"24\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t>\n\t\t\t<rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\" />\n\t\t\t<path d=\"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\" />\n\t\t</svg>\n\t)\n}\n\nfunction CheckIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\trole=\"img\"\n\t\t\taria-label=\"Check\"\n\t\t\twidth=\"24\"\n\t\t\theight=\"24\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t>\n\t\t\t<path d=\"M20 6 9 17l-5-5\" />\n\t\t</svg>\n\t)\n}\n\nfunction XIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\trole=\"img\"\n\t\t\taria-label=\"Close\"\n\t\t\twidth=\"24\"\n\t\t\theight=\"24\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t>\n\t\t\t<path d=\"M18 6 6 18\" />\n\t\t\t<path d=\"m6 6 12 12\" />\n\t\t</svg>\n\t)\n}\n","/**\n * Protect Component\n *\n * Role-based access control wrapper (similar to Clerk's <Protect>).\n * Renders children only if user meets the required conditions.\n *\n * Usage:\n * ```tsx\n * // Require signed in\n * <Protect>\n *   <ProtectedContent />\n * </Protect>\n *\n * // Require specific role\n * <Protect role=\"admin\">\n *   <AdminPanel />\n * </Protect>\n *\n * // Require any of multiple roles\n * <Protect roles={['admin', 'billing']}>\n *   <BillingDashboard />\n * </Protect>\n *\n * // Require premium subscription\n * <Protect premium>\n *   <PremiumFeature />\n * </Protect>\n *\n * // Custom permission check\n * <Protect permission=\"manage:users\">\n *   <UserManagement />\n * </Protect>\n *\n * // Custom condition\n * <Protect condition={(user) => user.email?.endsWith('@company.com')}>\n *   <InternalTool />\n * </Protect>\n *\n * // With fallback\n * <Protect role=\"admin\" fallback={<NoAccess />}>\n *   <AdminPanel />\n * </Protect>\n * ```\n */\n\n'use client'\n\nimport { type ReactNode, useContext } from 'react'\nimport type { User } from '../../types'\nimport { useSafeAuth, useSafeUser, useSdkReady } from '../hooks'\nimport { PlatformContext } from '../platform-context'\n\n/**\n * Internal hook to get platform context for Protect component (safe version)\n */\nfunction useSafePlatformContext() {\n\tconst context = useContext(PlatformContext)\n\treturn context // Returns null if not configured, doesn't throw\n}\n\n// Standard role types (can be extended via platform admin)\nexport type StandardRole =\n\t| 'super_admin'\n\t| 'admin'\n\t| 'billing'\n\t| 'analytics'\n\t| 'developer'\n\t| 'viewer'\n\t| 'member'\n\nexport interface ProtectProps {\n\tchildren: ReactNode\n\n\t/**\n\t * Fallback content when access is denied (default: null)\n\t */\n\tfallback?: ReactNode\n\n\t/**\n\t * Require user to be signed in (default: true)\n\t */\n\tsignedIn?: boolean\n\n\t/**\n\t * Require user to have a specific role\n\t */\n\trole?: StandardRole | string\n\n\t/**\n\t * Require user to have any of the specified roles\n\t */\n\troles?: (StandardRole | string)[]\n\n\t/**\n\t * Require user to have a specific permission\n\t * Permissions are checked against the user's role\n\t */\n\tpermission?: string\n\n\t/**\n\t * Require user to have premium/paid subscription\n\t */\n\tpremium?: boolean\n\n\t/**\n\t * Custom condition function\n\t * Return true to allow access, false to deny\n\t */\n\tcondition?: (user: User) => boolean\n\n\t/**\n\t * Loading component while auth state is loading\n\t */\n\tloading?: ReactNode\n}\n\n// Role hierarchy for inheritance checks\nconst ROLE_HIERARCHY: Record<string, number> = {\n\tsuper_admin: 100,\n\tadmin: 80,\n\tbilling: 60,\n\tanalytics: 50,\n\tdeveloper: 40,\n\tviewer: 20,\n\tmember: 10,\n}\n\n// Permission mappings per role\nconst ROLE_PERMISSIONS: Record<string, string[]> = {\n\tsuper_admin: ['*'], // All permissions\n\tadmin: ['manage:apps', 'manage:users', 'view:analytics', 'view:billing', 'manage:settings'],\n\tbilling: ['view:billing', 'manage:billing'],\n\tanalytics: ['view:analytics', 'export:analytics'],\n\tdeveloper: ['manage:apps', 'view:analytics'],\n\tviewer: ['view:analytics'],\n\tmember: [],\n}\n\n/**\n * Check if a role has a specific permission\n */\nfunction roleHasPermission(role: string, permission: string): boolean {\n\tconst permissions = ROLE_PERMISSIONS[role] || []\n\t// Super admin has all permissions\n\tif (permissions.includes('*')) return true\n\t// Check exact match\n\tif (permissions.includes(permission)) return true\n\t// Check wildcard match (e.g., \"manage:*\" matches \"manage:users\")\n\tconst [action, resource] = permission.split(':')\n\tif (permissions.includes(`${action}:*`)) return true\n\tif (permissions.includes(`*:${resource}`)) return true\n\treturn false\n}\n\n/**\n * Check if user has required role\n */\nfunction hasRole(userRole: string | undefined, requiredRole: string): boolean {\n\tif (!userRole) return false\n\tif (userRole === requiredRole) return true\n\n\t// Check role hierarchy - higher roles inherit lower role access\n\tconst userLevel = ROLE_HIERARCHY[userRole] ?? 0\n\tconst requiredLevel = ROLE_HIERARCHY[requiredRole] ?? 0\n\n\treturn userLevel >= requiredLevel\n}\n\n/**\n * Check if user has any of the required roles\n */\nfunction hasAnyRole(userRole: string | undefined, requiredRoles: string[]): boolean {\n\tif (!userRole) return false\n\treturn requiredRoles.some((role) => hasRole(userRole, role))\n}\n\nexport function Protect({\n\tchildren,\n\tfallback = null,\n\tsignedIn = true,\n\trole,\n\troles,\n\tpermission,\n\tpremium,\n\tcondition,\n\tloading = null,\n}: ProtectProps) {\n\t// SDK readiness check - silent fallback if not configured\n\tconst { isReady } = useSdkReady({\n\t\tservices: ['auth', 'user'],\n\t\tcomponentType: 'protect',\n\t\tfallback: 'null', // Silent - just render fallback if not configured\n\t})\n\n\tconst { isSignedIn } = useSafeAuth()\n\tconst { user, isLoaded } = useSafeUser()\n\tconst platformContext = useSafePlatformContext()\n\tconst subscription = platformContext?.subscription\n\n\t// If SDK not ready, render fallback (silent behavior)\n\tif (!isReady) {\n\t\treturn <>{fallback}</>\n\t}\n\n\t// Show loading while auth state is being determined\n\tif (!isLoaded) {\n\t\treturn <>{loading}</>\n\t}\n\n\t// Check signed in requirement\n\tif (signedIn && !isSignedIn) {\n\t\treturn <>{fallback}</>\n\t}\n\n\t// If not requiring sign in and user is not signed in, allow access\n\tif (!signedIn && !isSignedIn) {\n\t\treturn <>{children}</>\n\t}\n\n\t// At this point, user should be signed in\n\tif (!user) {\n\t\treturn <>{fallback}</>\n\t}\n\n\t// Check role requirement\n\tif (role && !hasRole(user.role, role)) {\n\t\treturn <>{fallback}</>\n\t}\n\n\t// Check roles (any of) requirement\n\tif (roles && roles.length > 0 && !hasAnyRole(user.role, roles)) {\n\t\treturn <>{fallback}</>\n\t}\n\n\t// Check permission requirement\n\tif (permission && !roleHasPermission(user.role || 'member', permission)) {\n\t\treturn <>{fallback}</>\n\t}\n\n\t// Check premium requirement\n\tif (premium) {\n\t\tconst isPremium = subscription?.status === 'active' || subscription?.status === 'trialing'\n\t\tif (!isPremium) {\n\t\t\treturn <>{fallback}</>\n\t\t}\n\t}\n\n\t// Check custom condition\n\tif (condition && !condition(user)) {\n\t\treturn <>{fallback}</>\n\t}\n\n\t// All checks passed - render children\n\treturn <>{children}</>\n}\n\n// Convenience components for common patterns\nfunction _SignedIn({ children }: { children: ReactNode }) {\n\treturn <Protect signedIn>{children}</Protect>\n}\n\nfunction _SignedOut({ children }: { children: ReactNode }) {\n\treturn <Protect signedIn={false}>{children}</Protect>\n}\n\nexport function AdminOnly({ children, fallback }: { children: ReactNode; fallback?: ReactNode }) {\n\treturn <Protect fallback={fallback}>{children}</Protect>\n}\n\nexport function PremiumOnly({ children, fallback }: { children: ReactNode; fallback?: ReactNode }) {\n\treturn (\n\t\t<Protect premium fallback={fallback}>\n\t\t\t{children}\n\t\t</Protect>\n\t)\n}\n\n// Hook for programmatic access checks\nexport function useProtect() {\n\tconst { isSignedIn } = useSafeAuth()\n\tconst { user, isLoaded, isConfigured } = useSafeUser()\n\tconst platformContext = useSafePlatformContext()\n\tconst subscription = platformContext?.subscription\n\n\treturn {\n\t\tisLoaded,\n\t\tisSignedIn,\n\t\tisConfigured, // SDK configuration status\n\t\tuser,\n\n\t\t/**\n\t\t * Check if user has a specific role\n\t\t */\n\t\thasRole: (requiredRole: string) => hasRole(user?.role, requiredRole),\n\n\t\t/**\n\t\t * Check if user has any of the specified roles\n\t\t */\n\t\thasAnyRole: (requiredRoles: string[]) => hasAnyRole(user?.role, requiredRoles),\n\n\t\t/**\n\t\t * Check if user has a specific permission\n\t\t */\n\t\thasPermission: (requiredPermission: string) =>\n\t\t\troleHasPermission(user?.role || 'member', requiredPermission),\n\n\t\t/**\n\t\t * Check if user has premium subscription\n\t\t */\n\t\tisPremium: subscription?.status === 'active' || subscription?.status === 'trialing',\n\n\t\t/**\n\t\t * Check custom condition\n\t\t */\n\t\tcheck: (condition: (user: User | null) => boolean) => condition(user),\n\t}\n}\n","/**\n * Consent Hooks\n *\n * React hooks for GDPR/CCPA consent management.\n * Uses server as Single Source of Truth (SSOT) - no local localStorage duplication.\n *\n * ## Architecture (ADR-004)\n *\n * Consent uses **Inline Defaults + Auto-Discovery + Console Override**:\n * - Code provides optional inline defaults when checking consent\n * - Platform auto-discovers/creates consent types when first referenced\n * - Console can override names, descriptions, requirements without deployment\n *\n * ## React Query Integration\n *\n * All hooks use React Query for:\n * - Automatic caching (5 min staleTime for consent data)\n * - Deduplication of concurrent requests\n * - Background refetching\n * - Optimistic updates via useMutation\n */\n\n'use client'\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useCallback, useContext, useEffect, useState } from 'react'\nimport type { ConsentPurposeDefaults } from '../consent'\nimport { STALE_TIME_STABLE_MS } from '../constants'\nimport {\n\ttype ConsentCategory,\n\tConsentContext,\n\ttype ConsentContextValue,\n\ttype ConsentType,\n\ttype UserConsent,\n\tuseConsentContext,\n} from './services-context'\n\n// Re-export types from services-context for convenience\nexport type { ConsentCategory, ConsentType, UserConsent }\n\n// ============================================\n// useConsent\n// ============================================\n\nexport interface UseConsentReturn {\n\t/** All consent types for this app */\n\ttypes: ConsentType[]\n\t/** User's current consent values by type ID */\n\tconsents: Record<string, boolean>\n\t/** Whether consent data is loading */\n\tisLoading: boolean\n\t/** Error from consent operations */\n\terror: Error | null\n\t/** Whether consent banner should be shown */\n\tshowBanner: boolean\n\t/** Whether user has given any consent */\n\thasConsented: boolean\n\t/** Check if a specific category is consented */\n\thasConsent: (category: ConsentCategory) => boolean\n\t/** Set consent for a single type */\n\tsetConsent: (typeId: string, value: boolean) => void\n\t/** Set multiple consents at once */\n\tsetConsents: (consents: Record<string, boolean>) => void\n\t/** Accept all consents */\n\tacceptAll: () => Promise<void>\n\t/** Decline optional consents (keep only required) */\n\tdeclineOptional: () => Promise<void>\n\t/** Save current consent selections */\n\tsaveConsents: () => Promise<void>\n\t/** Open consent preferences modal/banner */\n\topenPreferences: () => void\n\t/** Close consent banner */\n\tcloseBanner: () => void\n\t/**\n\t * Grant consent for a category and save immediately (Google Consent Mode v2 pattern)\n\t *\n\t * Equivalent to: `gtag('consent', 'update', { analytics_storage: 'granted' })`\n\t *\n\t * @example\n\t * ```typescript\n\t * // Grant analytics consent when user clicks \"Accept Analytics\"\n\t * await grantConsent('analytics')\n\t * ```\n\t */\n\tgrantConsent: (category: ConsentCategory) => Promise<void>\n\t/**\n\t * Revoke consent for a category and save immediately (Google Consent Mode v2 pattern)\n\t *\n\t * Equivalent to: `gtag('consent', 'update', { analytics_storage: 'denied' })`\n\t *\n\t * @example\n\t * ```typescript\n\t * // Revoke marketing consent\n\t * await revokeConsent('marketing')\n\t * ```\n\t */\n\trevokeConsent: (category: ConsentCategory) => Promise<void>\n}\n\n/**\n * Hook for consent management\n *\n * Server is the Single Source of Truth (SSOT) for consent data.\n * Local state is only used for optimistic updates during user interaction.\n *\n * @example\n * ```tsx\n * function CookieBanner() {\n *   const {\n *     showBanner,\n *     types,\n *     consents,\n *     acceptAll,\n *     declineOptional,\n *     setConsent,\n *     saveConsents,\n *   } = useConsent()\n *\n *   if (!showBanner) return null\n *\n *   return (\n *     <div className=\"cookie-banner\">\n *       <h3>We use cookies</h3>\n *       <p>We use cookies to improve your experience.</p>\n *\n *       {types.map(type => (\n *         <label key={type.id}>\n *           <input\n *             type=\"checkbox\"\n *             checked={consents[type.id] ?? type.defaultValue}\n *             disabled={type.required}\n *             onChange={(e) => setConsent(type.id, e.target.checked)}\n *           />\n *           {type.name}\n *         </label>\n *       ))}\n *\n *       <button onClick={declineOptional}>Decline Optional</button>\n *       <button onClick={saveConsents}>Save Preferences</button>\n *       <button onClick={acceptAll}>Accept All</button>\n *     </div>\n *   )\n * }\n * ```\n */\nexport function useConsent(): UseConsentReturn {\n\tconst ctx = useConsentContext()\n\tconst queryClient = useQueryClient()\n\n\t// Local state for user selections (before saving)\n\tconst [localConsents, setLocalConsentsState] = useState<Record<string, boolean>>({})\n\tconst [showBanner, setShowBanner] = useState(false)\n\tconst [initialized, setInitialized] = useState(false)\n\n\t// React Query for consent types\n\t// Use initialData for SSR hydration to avoid loading states\n\tconst typesQuery = useQuery({\n\t\tqueryKey: ['sylphx', 'consent', 'types'],\n\t\tqueryFn: () => ctx.getConsentTypes(),\n\t\tstaleTime: STALE_TIME_STABLE_MS, // 5 min\n\t\tinitialData: ctx.initialConsentTypes,\n\t})\n\n\t// React Query for user consents\n\t// Note: Errors are NOT silently swallowed - GDPR compliance requires explicit handling\n\tconst userConsentsQuery = useQuery({\n\t\tqueryKey: ['sylphx', 'consent', 'user'],\n\t\tqueryFn: async () => {\n\t\t\tconst consentsResponse = await ctx.getUserConsents()\n\t\t\tconst consentsMap: Record<string, boolean> = {}\n\t\t\t// Check if user has explicitly made any consent choices\n\t\t\t// If grantedAt is set, user has made an explicit choice\n\t\t\tlet hasExplicitChoice = false\n\t\t\tfor (const consent of consentsResponse) {\n\t\t\t\tconsentsMap[consent.slug] = consent.granted ?? false\n\t\t\t\tif (consent.grantedAt) {\n\t\t\t\t\thasExplicitChoice = true\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { consents: consentsMap, hasExplicitChoice }\n\t\t},\n\t\tstaleTime: STALE_TIME_STABLE_MS, // 5 min\n\t\t// Return empty object for unauthenticated users (explicit retry: false)\n\t\tretry: false,\n\t})\n\n\t// Initialize local state and banner visibility when data loads\n\tuseEffect(() => {\n\t\tif (!typesQuery.isLoading && !userConsentsQuery.isLoading && !initialized) {\n\t\t\tconst data = userConsentsQuery.data\n\t\t\tconst serverConsents = data?.consents ?? {}\n\t\t\tconst hasExplicitChoice = data?.hasExplicitChoice ?? false\n\t\t\tsetLocalConsentsState(serverConsents)\n\t\t\t// Show banner if user has NOT made any explicit consent choices\n\t\t\tsetShowBanner(!hasExplicitChoice)\n\t\t\tsetInitialized(true)\n\t\t}\n\t}, [typesQuery.isLoading, userConsentsQuery.isLoading, userConsentsQuery.data, initialized])\n\n\t// Mutations for saving consents\n\tconst saveConsentsMutation = useMutation({\n\t\tmutationFn: async (consentList: Array<{ slug: string; granted: boolean }>) => {\n\t\t\tawait ctx.setConsents(consentList)\n\t\t\treturn consentList\n\t\t},\n\t\tonSuccess: (consentList) => {\n\t\t\t// Update cache with saved values\n\t\t\tconst consentsMap: Record<string, boolean> = {}\n\t\t\tfor (const consent of consentList) {\n\t\t\t\tconsentsMap[consent.slug] = consent.granted\n\t\t\t}\n\t\t\tqueryClient.setQueryData(['sylphx', 'consent', 'user'], {\n\t\t\t\tconsents: consentsMap,\n\t\t\t\thasExplicitChoice: true,\n\t\t\t})\n\t\t\tsetLocalConsentsState(consentsMap)\n\t\t\tsetShowBanner(false)\n\t\t},\n\t})\n\n\tconst acceptAllMutation = useMutation({\n\t\tmutationFn: async () => {\n\t\t\tawait ctx.acceptAll()\n\t\t},\n\t\tonSuccess: () => {\n\t\t\t// Set all consents to true\n\t\t\tconst types = typesQuery.data ?? []\n\t\t\tconst allConsents: Record<string, boolean> = {}\n\t\t\tfor (const type of types) {\n\t\t\t\tallConsents[type.slug] = true\n\t\t\t}\n\t\t\tqueryClient.setQueryData(['sylphx', 'consent', 'user'], {\n\t\t\t\tconsents: allConsents,\n\t\t\t\thasExplicitChoice: true,\n\t\t\t})\n\t\t\tsetLocalConsentsState(allConsents)\n\t\t\tsetShowBanner(false)\n\t\t},\n\t})\n\n\tconst declineOptionalMutation = useMutation({\n\t\tmutationFn: async () => {\n\t\t\tawait ctx.declineOptional()\n\t\t},\n\t\tonSuccess: () => {\n\t\t\t// Set only required consents to true\n\t\t\tconst types = typesQuery.data ?? []\n\t\t\tconst requiredConsents: Record<string, boolean> = {}\n\t\t\tfor (const type of types) {\n\t\t\t\trequiredConsents[type.slug] = type.required\n\t\t\t}\n\t\t\tqueryClient.setQueryData(['sylphx', 'consent', 'user'], {\n\t\t\t\tconsents: requiredConsents,\n\t\t\t\thasExplicitChoice: true,\n\t\t\t})\n\t\t\tsetLocalConsentsState(requiredConsents)\n\t\t\tsetShowBanner(false)\n\t\t},\n\t})\n\n\tconst types = typesQuery.data ?? []\n\tconst consents = localConsents\n\tconst hasConsented = userConsentsQuery.data?.hasExplicitChoice ?? false\n\tconst isLoading = typesQuery.isLoading || userConsentsQuery.isLoading\n\tconst error = (typesQuery.error ??\n\t\tuserConsentsQuery.error ??\n\t\tsaveConsentsMutation.error ??\n\t\tacceptAllMutation.error ??\n\t\tdeclineOptionalMutation.error) as Error | null\n\n\tconst hasConsent = useCallback(\n\t\t(category: ConsentCategory): boolean => {\n\t\t\t// Necessary is always consented\n\t\t\tif (category === 'necessary') return true\n\n\t\t\t// Check if any consent type in this category is consented\n\t\t\tconst categoryTypes = types.filter((t) => t.category === category)\n\t\t\treturn categoryTypes.some((t) => consents[t.slug] ?? t.defaultEnabled)\n\t\t},\n\t\t[types, consents],\n\t)\n\n\tconst setConsent = useCallback((typeId: string, value: boolean) => {\n\t\tsetLocalConsentsState((prev) => ({ ...prev, [typeId]: value }))\n\t}, [])\n\n\tconst setConsents = useCallback((newConsents: Record<string, boolean>) => {\n\t\tsetLocalConsentsState((prev) => ({ ...prev, ...newConsents }))\n\t}, [])\n\n\tconst saveConsents = useCallback(async () => {\n\t\tconst consentList = types.map((type) => ({\n\t\t\tslug: type.slug,\n\t\t\tgranted: consents[type.slug] ?? type.defaultEnabled,\n\t\t}))\n\t\tawait saveConsentsMutation.mutateAsync(consentList)\n\t}, [types, consents, saveConsentsMutation])\n\n\tconst acceptAll = useCallback(async () => {\n\t\tawait acceptAllMutation.mutateAsync()\n\t}, [acceptAllMutation])\n\n\tconst declineOptional = useCallback(async () => {\n\t\tawait declineOptionalMutation.mutateAsync()\n\t}, [declineOptionalMutation])\n\n\tconst openPreferences = useCallback(() => {\n\t\tsetShowBanner(true)\n\t}, [])\n\n\tconst closeBanner = useCallback(() => {\n\t\tsetShowBanner(false)\n\t}, [])\n\n\t/**\n\t * Grant consent for a specific category and save immediately\n\t * (Google Consent Mode v2 pattern: single call to grant and persist)\n\t */\n\tconst grantConsent = useCallback(\n\t\tasync (category: ConsentCategory) => {\n\t\t\t// Find all types in this category\n\t\t\tconst categoryTypes = types.filter((t) => t.category === category)\n\t\t\tif (categoryTypes.length === 0) return\n\n\t\t\t// Build updated consents\n\t\t\tconst updatedConsents: Record<string, boolean> = { ...consents }\n\t\t\tfor (const type of categoryTypes) {\n\t\t\t\tupdatedConsents[type.slug] = true\n\t\t\t}\n\t\t\tsetLocalConsentsState(updatedConsents)\n\n\t\t\t// Save immediately\n\t\t\tconst consentList = types.map((type) => ({\n\t\t\t\tslug: type.slug,\n\t\t\t\tgranted: updatedConsents[type.slug] ?? type.defaultEnabled,\n\t\t\t}))\n\t\t\tawait saveConsentsMutation.mutateAsync(consentList)\n\t\t},\n\t\t[types, consents, saveConsentsMutation],\n\t)\n\n\t/**\n\t * Revoke consent for a specific category and save immediately\n\t * (Google Consent Mode v2 pattern: single call to revoke and persist)\n\t */\n\tconst revokeConsent = useCallback(\n\t\tasync (category: ConsentCategory) => {\n\t\t\t// Find all types in this category\n\t\t\tconst categoryTypes = types.filter((t) => t.category === category)\n\t\t\tif (categoryTypes.length === 0) return\n\n\t\t\t// Build updated consents (only revoke non-required types)\n\t\t\tconst updatedConsents: Record<string, boolean> = { ...consents }\n\t\t\tfor (const type of categoryTypes) {\n\t\t\t\t// Required consents cannot be revoked\n\t\t\t\tif (!type.required) {\n\t\t\t\t\tupdatedConsents[type.slug] = false\n\t\t\t\t}\n\t\t\t}\n\t\t\tsetLocalConsentsState(updatedConsents)\n\n\t\t\t// Save immediately\n\t\t\tconst consentList = types.map((type) => ({\n\t\t\t\tslug: type.slug,\n\t\t\t\tgranted: updatedConsents[type.slug] ?? type.defaultEnabled,\n\t\t\t}))\n\t\t\tawait saveConsentsMutation.mutateAsync(consentList)\n\t\t},\n\t\t[types, consents, saveConsentsMutation],\n\t)\n\n\treturn {\n\t\ttypes,\n\t\tconsents,\n\t\tisLoading,\n\t\terror,\n\t\tshowBanner,\n\t\thasConsented,\n\t\thasConsent,\n\t\tsetConsent,\n\t\tsetConsents,\n\t\tacceptAll,\n\t\tdeclineOptional,\n\t\tsaveConsents,\n\t\topenPreferences,\n\t\tcloseBanner,\n\t\tgrantConsent,\n\t\trevokeConsent,\n\t}\n}\n\n// ============================================\n// useConsentGate\n// ============================================\n\nexport interface UseConsentGateOptions {\n\t/** Required consent category */\n\tcategory: ConsentCategory\n\t/** Called when consent is granted */\n\tonConsent?: () => void\n\t/** Called when consent is denied */\n\tonDeny?: () => void\n}\n\nexport interface UseConsentGateReturn {\n\t/** Whether the required consent is granted */\n\thasConsent: boolean\n\t/** Whether consent data is loading */\n\tisLoading: boolean\n\t/** Request consent (opens preferences) */\n\trequestConsent: () => void\n}\n\n/**\n * Hook to gate functionality behind consent\n *\n * @example\n * ```tsx\n * function AnalyticsLoader() {\n *   const { hasConsent, isLoading } = useConsentGate({\n *     category: 'analytics',\n *     onConsent: () => initAnalytics(),\n *   })\n *\n *   if (isLoading) return null\n *   if (!hasConsent) return null\n *\n *   return <AnalyticsProvider />\n * }\n * ```\n */\nexport function useConsentGate(options: UseConsentGateOptions): UseConsentGateReturn {\n\tconst { hasConsent: checkConsent, isLoading, openPreferences } = useConsent()\n\tconst hasConsent = checkConsent(options.category)\n\n\tuseEffect(() => {\n\t\tif (!isLoading) {\n\t\t\tif (hasConsent) {\n\t\t\t\toptions.onConsent?.()\n\t\t\t} else {\n\t\t\t\toptions.onDeny?.()\n\t\t\t}\n\t\t}\n\t}, [hasConsent, isLoading, options])\n\n\treturn {\n\t\thasConsent,\n\t\tisLoading,\n\t\trequestConsent: openPreferences,\n\t}\n}\n\n// ============================================\n// ConsentGuard Component\n// ============================================\n\nexport interface ConsentGuardProps {\n\t/** Required consent category */\n\tcategory: ConsentCategory\n\t/** Content to render when consent is granted */\n\tchildren: React.ReactNode\n\t/** Fallback content when consent is denied */\n\tfallback?: React.ReactNode\n\t/** Show loading state */\n\tloading?: React.ReactNode\n}\n\n/**\n * Component to gate children behind consent\n *\n * @example\n * ```tsx\n * <ConsentGuard\n *   category=\"marketing\"\n *   fallback={<p>Enable marketing to see personalized content</p>}\n * >\n *   <MarketingBanner />\n * </ConsentGuard>\n * ```\n */\nexport function ConsentGuard({\n\tcategory,\n\tchildren,\n\tfallback = null,\n\tloading = null,\n}: ConsentGuardProps): React.ReactNode {\n\tconst { hasConsent, isLoading } = useConsentGate({ category })\n\n\tif (isLoading) return loading\n\tif (!hasConsent) return fallback\n\treturn children\n}\n\n// ============================================\n// useConsentCheck (Auto-Discovery)\n// ============================================\n\n// Re-export ConsentPurposeDefaults for convenience\n\nexport interface UseConsentCheckOptions {\n\t/** Consent purpose slug (e.g., 'analytics', 'marketing') */\n\tpurposeSlug: string\n\t/** Optional inline defaults for auto-discovery */\n\tdefaults?: ConsentPurposeDefaults\n}\n\nexport interface UseConsentCheckReturn {\n\t/** Whether consent is granted */\n\thasConsent: boolean\n\t/** Whether consent check is loading */\n\tisLoading: boolean\n\t/** Error if any */\n\terror: Error | null\n\t/** Refresh consent status */\n\trefresh: () => Promise<void>\n}\n\n/**\n * Hook to check consent for a specific purpose with auto-discovery support\n *\n * If the consent type doesn't exist, it will be auto-discovered with the provided defaults.\n * Console can override any values without deployment.\n *\n * @param options - Purpose slug and optional inline defaults\n *\n * @example\n * ```tsx\n * function AnalyticsTracker() {\n *   const { hasConsent, isLoading } = useConsentCheck({\n *     purposeSlug: 'analytics',\n *     defaults: {\n *       name: 'Analytics Cookies',\n *       description: 'Help us understand how visitors use our site',\n *       category: 'analytics',\n *       required: false,\n *     },\n *   })\n *\n *   useEffect(() => {\n *     if (!isLoading && hasConsent) {\n *       // Initialize analytics\n *       track('page_view')\n *     }\n *   }, [hasConsent, isLoading])\n *\n *   return null\n * }\n * ```\n */\nexport function useConsentCheck(options: UseConsentCheckOptions): UseConsentCheckReturn {\n\tconst ctx = useConsentContext()\n\tconst queryClient = useQueryClient()\n\n\t// React Query for consent check\n\tconst consentQuery = useQuery({\n\t\tqueryKey: ['sylphx', 'consent', 'check', options.purposeSlug, options.defaults],\n\t\tqueryFn: () => ctx.checkConsent(options.purposeSlug, options.defaults),\n\t\tstaleTime: STALE_TIME_STABLE_MS, // 5 min\n\t})\n\n\t// Refresh via React Query\n\tconst refresh = useCallback(async () => {\n\t\tawait queryClient.invalidateQueries({\n\t\t\tqueryKey: ['sylphx', 'consent', 'check', options.purposeSlug],\n\t\t})\n\t}, [queryClient, options.purposeSlug])\n\n\treturn {\n\t\thasConsent: consentQuery.data ?? false,\n\t\tisLoading: consentQuery.isLoading,\n\t\terror: consentQuery.error as Error | null,\n\t\trefresh,\n\t}\n}\n\n// ============================================\n// Safe Versions (for SSR/prerendering)\n// ============================================\n\n// No-op async function for safe hooks\nconst noopAsync = async () => {}\n\n/** Safe return type for useConsent when outside provider */\nexport interface UseSafeConsentReturn {\n\ttypes: ConsentType[]\n\tconsents: Record<string, boolean>\n\tisLoading: boolean\n\terror: Error | null\n\tshowBanner: boolean\n\thasConsented: boolean\n\thasConsent: (category: ConsentCategory) => boolean\n\tsetConsent: (typeId: string, value: boolean) => void\n\tsetConsents: (consents: Record<string, boolean>) => void\n\tacceptAll: () => Promise<void>\n\tdeclineOptional: () => Promise<void>\n\tsaveConsents: () => Promise<void>\n\topenPreferences: () => void\n\tcloseBanner: () => void\n\tgrantConsent: (category: ConsentCategory) => Promise<void>\n\trevokeConsent: (category: ConsentCategory) => Promise<void>\n\tisConfigured: boolean\n}\n\n/**\n * No-op ConsentContext for SSR-safe hooks when no provider is mounted.\n * All methods are inert and return safe defaults so hooks can still be\n * called unconditionally without reaching any real backend.\n */\nconst NOOP_CONSENT_CTX: ConsentContextValue = {\n\tanonymousId: null,\n\tuserId: null,\n\tgetConsentTypes: async () => [],\n\tgetUserConsents: async () => [],\n\tsetConsents: async () => ({ success: true, consents: [] }),\n\tacceptAll: async () => ({ success: true, consents: [] }),\n\tdeclineOptional: async () => ({ success: true, consents: [] }),\n\tcheckConsent: async () => false,\n\tgetHistory: async () => ({ entries: [], nextCursor: null, hasMore: false }),\n\tinitialConsentTypes: [],\n}\n\nconst SAFE_CONSENT_DEFAULTS: UseSafeConsentReturn = {\n\ttypes: [],\n\tconsents: {},\n\tisLoading: false,\n\terror: null,\n\tshowBanner: false,\n\thasConsented: false,\n\thasConsent: () => false,\n\tsetConsent: () => {},\n\tsetConsents: () => {},\n\tacceptAll: noopAsync,\n\tdeclineOptional: noopAsync,\n\tsaveConsents: noopAsync,\n\topenPreferences: () => {},\n\tcloseBanner: () => {},\n\tgrantConsent: noopAsync,\n\trevokeConsent: noopAsync,\n\tisConfigured: false,\n}\n\n/**\n * SSR-safe version of useConsent\n *\n * Returns safe defaults when called outside SylphxProvider.\n * Use this in components that may render during static generation.\n *\n * Hooks are always called unconditionally (using an inert context when\n * no provider is present) to comply with the Rules of Hooks.\n */\nexport function useSafeConsent(): UseSafeConsentReturn {\n\tconst ctx = useContext(ConsentContext)\n\tconst effectiveCtx = ctx ?? NOOP_CONSENT_CTX\n\tconst queryClient = useQueryClient()\n\n\t// Local state for user selections (before saving)\n\tconst [localConsents, setLocalConsentsState] = useState<Record<string, boolean>>({})\n\tconst [showBanner, setShowBanner] = useState(false)\n\tconst [initialized, setInitialized] = useState(false)\n\n\t// React Query for consent types\n\t// Use initialData for SSR hydration to avoid loading states\n\tconst typesQuery = useQuery({\n\t\tqueryKey: ['sylphx', 'consent', 'types', ctx ? 'live' : 'noop'],\n\t\tqueryFn: () => effectiveCtx.getConsentTypes(),\n\t\tstaleTime: STALE_TIME_STABLE_MS,\n\t\tinitialData: effectiveCtx.initialConsentTypes,\n\t\tenabled: !!ctx,\n\t})\n\n\t// React Query for user consents\n\t// Note: Errors are NOT silently swallowed - GDPR compliance requires explicit handling\n\tconst userConsentsQuery = useQuery({\n\t\tqueryKey: ['sylphx', 'consent', 'user', ctx ? 'live' : 'noop'],\n\t\tqueryFn: async () => {\n\t\t\tconst consentsResponse = await effectiveCtx.getUserConsents()\n\t\t\tconst consentsMap: Record<string, boolean> = {}\n\t\t\t// Check if user has explicitly made any consent choices\n\t\t\tlet hasExplicitChoice = false\n\t\t\tfor (const consent of consentsResponse) {\n\t\t\t\tconsentsMap[consent.slug] = consent.granted ?? false\n\t\t\t\tif (consent.grantedAt) {\n\t\t\t\t\thasExplicitChoice = true\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { consents: consentsMap, hasExplicitChoice }\n\t\t},\n\t\tstaleTime: STALE_TIME_STABLE_MS,\n\t\t// Return empty object for unauthenticated users (explicit retry: false)\n\t\tretry: false,\n\t\tenabled: !!ctx,\n\t})\n\n\t// Initialize local state and banner visibility when data loads\n\tuseEffect(() => {\n\t\tif (!ctx) return\n\t\tif (!typesQuery.isLoading && !userConsentsQuery.isLoading && !initialized) {\n\t\t\tconst data = userConsentsQuery.data\n\t\t\tconst serverConsents = data?.consents ?? {}\n\t\t\tconst hasExplicitChoice = data?.hasExplicitChoice ?? false\n\t\t\tsetLocalConsentsState(serverConsents)\n\t\t\t// Show banner if user has NOT made any explicit consent choices\n\t\t\tsetShowBanner(!hasExplicitChoice)\n\t\t\tsetInitialized(true)\n\t\t}\n\t}, [ctx, typesQuery.isLoading, userConsentsQuery.isLoading, userConsentsQuery.data, initialized])\n\n\t// Mutations for saving consents\n\tconst saveConsentsMutation = useMutation({\n\t\tmutationFn: async (consentList: Array<{ slug: string; granted: boolean }>) => {\n\t\t\tawait effectiveCtx.setConsents(consentList)\n\t\t\treturn consentList\n\t\t},\n\t\tonSuccess: (consentList) => {\n\t\t\tconst consentsMap: Record<string, boolean> = {}\n\t\t\tfor (const consent of consentList) {\n\t\t\t\tconsentsMap[consent.slug] = consent.granted\n\t\t\t}\n\t\t\tqueryClient.setQueryData(['sylphx', 'consent', 'user', 'live'], {\n\t\t\t\tconsents: consentsMap,\n\t\t\t\thasExplicitChoice: true,\n\t\t\t})\n\t\t\tsetLocalConsentsState(consentsMap)\n\t\t\tsetShowBanner(false)\n\t\t},\n\t})\n\n\tconst acceptAllMutation = useMutation({\n\t\tmutationFn: async () => {\n\t\t\tawait effectiveCtx.acceptAll()\n\t\t},\n\t\tonSuccess: () => {\n\t\t\tconst types = typesQuery.data ?? []\n\t\t\tconst allConsents: Record<string, boolean> = {}\n\t\t\tfor (const type of types) {\n\t\t\t\tallConsents[type.slug] = true\n\t\t\t}\n\t\t\tqueryClient.setQueryData(['sylphx', 'consent', 'user', 'live'], {\n\t\t\t\tconsents: allConsents,\n\t\t\t\thasExplicitChoice: true,\n\t\t\t})\n\t\t\tsetLocalConsentsState(allConsents)\n\t\t\tsetShowBanner(false)\n\t\t},\n\t})\n\n\tconst declineOptionalMutation = useMutation({\n\t\tmutationFn: async () => {\n\t\t\tawait effectiveCtx.declineOptional()\n\t\t},\n\t\tonSuccess: () => {\n\t\t\tconst types = typesQuery.data ?? []\n\t\t\tconst requiredConsents: Record<string, boolean> = {}\n\t\t\tfor (const type of types) {\n\t\t\t\trequiredConsents[type.slug] = type.required\n\t\t\t}\n\t\t\tqueryClient.setQueryData(['sylphx', 'consent', 'user', 'live'], {\n\t\t\t\tconsents: requiredConsents,\n\t\t\t\thasExplicitChoice: true,\n\t\t\t})\n\t\t\tsetLocalConsentsState(requiredConsents)\n\t\t\tsetShowBanner(false)\n\t\t},\n\t})\n\n\tconst types = typesQuery.data ?? []\n\tconst consents = localConsents\n\tconst hasConsented = userConsentsQuery.data?.hasExplicitChoice ?? false\n\tconst isLoading = typesQuery.isLoading || userConsentsQuery.isLoading\n\tconst error = (typesQuery.error ??\n\t\tuserConsentsQuery.error ??\n\t\tsaveConsentsMutation.error ??\n\t\tacceptAllMutation.error ??\n\t\tdeclineOptionalMutation.error) as Error | null\n\n\tconst hasConsentFn = useCallback(\n\t\t(category: ConsentCategory): boolean => {\n\t\t\tif (category === 'necessary') return true\n\t\t\tconst categoryTypes = types.filter((t) => t.category === category)\n\t\t\treturn categoryTypes.some((t) => consents[t.slug] ?? t.defaultEnabled)\n\t\t},\n\t\t[types, consents],\n\t)\n\n\tconst setConsent = useCallback((typeId: string, value: boolean) => {\n\t\tsetLocalConsentsState((prev) => ({ ...prev, [typeId]: value }))\n\t}, [])\n\n\tconst setConsents = useCallback((newConsents: Record<string, boolean>) => {\n\t\tsetLocalConsentsState((prev) => ({ ...prev, ...newConsents }))\n\t}, [])\n\n\tconst saveConsents = useCallback(async () => {\n\t\tconst consentList = types.map((type) => ({\n\t\t\tslug: type.slug,\n\t\t\tgranted: consents[type.slug] ?? type.defaultEnabled,\n\t\t}))\n\t\tawait saveConsentsMutation.mutateAsync(consentList)\n\t}, [types, consents, saveConsentsMutation])\n\n\tconst acceptAll = useCallback(async () => {\n\t\tawait acceptAllMutation.mutateAsync()\n\t}, [acceptAllMutation])\n\n\tconst declineOptional = useCallback(async () => {\n\t\tawait declineOptionalMutation.mutateAsync()\n\t}, [declineOptionalMutation])\n\n\tconst openPreferences = useCallback(() => {\n\t\tsetShowBanner(true)\n\t}, [])\n\n\tconst closeBanner = useCallback(() => {\n\t\tsetShowBanner(false)\n\t}, [])\n\n\t/**\n\t * Grant consent for a specific category and save immediately\n\t */\n\tconst grantConsent = useCallback(\n\t\tasync (category: ConsentCategory) => {\n\t\t\tconst categoryTypes = types.filter((t) => t.category === category)\n\t\t\tif (categoryTypes.length === 0) return\n\n\t\t\tconst updatedConsents: Record<string, boolean> = { ...consents }\n\t\t\tfor (const type of categoryTypes) {\n\t\t\t\tupdatedConsents[type.slug] = true\n\t\t\t}\n\t\t\tsetLocalConsentsState(updatedConsents)\n\n\t\t\tconst consentList = types.map((type) => ({\n\t\t\t\tslug: type.slug,\n\t\t\t\tgranted: updatedConsents[type.slug] ?? type.defaultEnabled,\n\t\t\t}))\n\t\t\tawait saveConsentsMutation.mutateAsync(consentList)\n\t\t},\n\t\t[types, consents, saveConsentsMutation],\n\t)\n\n\t/**\n\t * Revoke consent for a specific category and save immediately\n\t */\n\tconst revokeConsent = useCallback(\n\t\tasync (category: ConsentCategory) => {\n\t\t\tconst categoryTypes = types.filter((t) => t.category === category)\n\t\t\tif (categoryTypes.length === 0) return\n\n\t\t\tconst updatedConsents: Record<string, boolean> = { ...consents }\n\t\t\tfor (const type of categoryTypes) {\n\t\t\t\tif (!type.required) {\n\t\t\t\t\tupdatedConsents[type.slug] = false\n\t\t\t\t}\n\t\t\t}\n\t\t\tsetLocalConsentsState(updatedConsents)\n\n\t\t\tconst consentList = types.map((type) => ({\n\t\t\t\tslug: type.slug,\n\t\t\t\tgranted: updatedConsents[type.slug] ?? type.defaultEnabled,\n\t\t\t}))\n\t\t\tawait saveConsentsMutation.mutateAsync(consentList)\n\t\t},\n\t\t[types, consents, saveConsentsMutation],\n\t)\n\n\t// If no provider, return inert defaults (hooks above were still called\n\t// unconditionally to satisfy the Rules of Hooks).\n\tif (!ctx) return SAFE_CONSENT_DEFAULTS\n\n\treturn {\n\t\ttypes,\n\t\tconsents,\n\t\tisLoading,\n\t\terror,\n\t\tshowBanner,\n\t\thasConsented,\n\t\thasConsent: hasConsentFn,\n\t\tsetConsent,\n\t\tsetConsents,\n\t\tacceptAll,\n\t\tdeclineOptional,\n\t\tsaveConsents,\n\t\topenPreferences,\n\t\tcloseBanner,\n\t\tgrantConsent,\n\t\trevokeConsent,\n\t\tisConfigured: true,\n\t}\n}\n\n// The useConsent hook is the primary export for consent management.\n// Additional exports:\n// - useConsentGate for gating features behind consent\n// - ConsentGuard for gating components behind consent\n// - useConsentCheck for checking specific purposes with auto-discovery\n// - useSafeConsent for SSR-safe consent management\n","/**\n * Consent-Aware Script Loading\n *\n * GDPR/CCPA-compliant script blocking that prevents third-party scripts\n * from loading until user consent is granted.\n *\n * ## Features\n *\n * - **Script Blocking**: Scripts only load after consent is granted\n * - **Script Queue**: Blocked scripts are queued and executed when consent changes\n * - **Known Scripts**: Pre-configured patterns for common analytics/marketing scripts\n * - **SSR Safe**: Works with Next.js SSR and client-side rendering\n * - **Dynamic Consent**: Automatically loads scripts when consent is granted later\n *\n * ## Usage\n *\n * @example\n * ```tsx\n * // Block a specific script\n * <ConsentScript\n *   src=\"https://www.googletagmanager.com/gtag/js?id=G-XXXXXX\"\n *   category=\"analytics\"\n *   strategy=\"afterInteractive\"\n * />\n *\n * // Using known script presets\n * <GoogleAnalytics measurementId=\"G-XXXXXX\" />\n * <GoogleTagManager containerId=\"GTM-XXXXXX\" />\n * <FacebookPixel pixelId=\"XXXXXX\" />\n *\n * // Inline script with consent\n * <ConsentScript category=\"marketing\">\n *   {`console.log('Marketing script loaded')`}\n * </ConsentScript>\n * ```\n */\n\n'use client'\n\nimport {\n\tcreateContext,\n\ttype ReactNode,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react'\nimport { CONSENT_WAIT_FOR_UPDATE_MS } from '../constants'\nimport { type ConsentCategory, useConsent, useConsentGate } from './consent-hooks'\n\n// ============================================\n// Types\n// ============================================\n\nexport type ScriptStrategy = 'beforeInteractive' | 'afterInteractive' | 'lazyOnload' | 'worker'\n\nexport interface ConsentScriptProps {\n\t/** External script URL */\n\tsrc?: string\n\t/** Inline script content (children) */\n\tchildren?: string\n\t/** Required consent category */\n\tcategory: ConsentCategory\n\t/** Script loading strategy (Next.js compatible) */\n\tstrategy?: ScriptStrategy\n\t/** Called when script loads successfully */\n\tonLoad?: () => void\n\t/** Called when script fails to load */\n\tonError?: (error: Error) => void\n\t/** Called when script is blocked due to no consent */\n\tonBlock?: () => void\n\t/** Additional script attributes */\n\tasync?: boolean\n\tdefer?: boolean\n\tid?: string\n\tnonce?: string\n\t/** data-* attributes */\n\t[key: `data-${string}`]: string | undefined\n}\n\nexport interface ScriptQueueItem {\n\tid: string\n\tsrc?: string\n\tcontent?: string\n\tcategory: ConsentCategory\n\tstrategy: ScriptStrategy\n\tattributes: Record<string, string | boolean | undefined>\n\tonLoad?: () => void\n\tonError?: (error: Error) => void\n}\n\nexport interface ScriptManagerContextValue {\n\t/** Queue a script for loading when consent is granted */\n\tqueueScript: (item: ScriptQueueItem) => void\n\t/** Remove a script from queue */\n\tdequeueScript: (id: string) => void\n\t/** Check if a script is loaded */\n\tisLoaded: (id: string) => boolean\n\t/** Get all blocked scripts */\n\tgetBlockedScripts: () => ScriptQueueItem[]\n}\n\n// ============================================\n// Script Manager Context\n// ============================================\n\nconst ScriptManagerContext = createContext<ScriptManagerContextValue | null>(null)\n\n/**\n * Script Manager Provider\n *\n * Manages the queue of blocked scripts and loads them when consent changes.\n * Should be placed inside SylphxProvider.\n *\n * @example\n * ```tsx\n * <SylphxProvider config={config}>\n *   <ScriptManagerProvider>\n *     <App />\n *   </ScriptManagerProvider>\n * </SylphxProvider>\n * ```\n */\nexport function ScriptManagerProvider({ children }: { children: ReactNode }) {\n\tconst [queue, setQueue] = useState<ScriptQueueItem[]>([])\n\tconst [loadedScripts, setLoadedScripts] = useState<Set<string>>(new Set())\n\n\tconst queueScript = useCallback((item: ScriptQueueItem) => {\n\t\tsetQueue((prev) => {\n\t\t\t// Don't add duplicates\n\t\t\tif (prev.some((s) => s.id === item.id)) return prev\n\t\t\treturn [...prev, item]\n\t\t})\n\t}, [])\n\n\tconst dequeueScript = useCallback((id: string) => {\n\t\tsetQueue((prev) => prev.filter((s) => s.id !== id))\n\t}, [])\n\n\tconst isLoaded = useCallback((id: string) => loadedScripts.has(id), [loadedScripts])\n\n\tconst getBlockedScripts = useCallback(() => queue, [queue])\n\n\t// Mark script as loaded\n\tconst markLoaded = useCallback((id: string) => {\n\t\tsetLoadedScripts((prev) => new Set(prev).add(id))\n\t}, [])\n\n\tconst value: ScriptManagerContextValue = {\n\t\tqueueScript,\n\t\tdequeueScript,\n\t\tisLoaded,\n\t\tgetBlockedScripts,\n\t}\n\n\treturn (\n\t\t<ScriptManagerContext.Provider value={value}>\n\t\t\t{children}\n\t\t\t{/* Render queue processors for each category */}\n\t\t\t<QueueProcessor\n\t\t\t\tcategory=\"analytics\"\n\t\t\t\tqueue={queue}\n\t\t\t\tonLoad={markLoaded}\n\t\t\t\tonDequeue={dequeueScript}\n\t\t\t/>\n\t\t\t<QueueProcessor\n\t\t\t\tcategory=\"marketing\"\n\t\t\t\tqueue={queue}\n\t\t\t\tonLoad={markLoaded}\n\t\t\t\tonDequeue={dequeueScript}\n\t\t\t/>\n\t\t\t<QueueProcessor\n\t\t\t\tcategory=\"preferences\"\n\t\t\t\tqueue={queue}\n\t\t\t\tonLoad={markLoaded}\n\t\t\t\tonDequeue={dequeueScript}\n\t\t\t/>\n\t\t</ScriptManagerContext.Provider>\n\t)\n}\n\n/**\n * Hook to access script manager\n */\nexport function useScriptManager(): ScriptManagerContextValue | null {\n\treturn useContext(ScriptManagerContext)\n}\n\n// ============================================\n// Queue Processor\n// ============================================\n\ninterface QueueProcessorProps {\n\tcategory: ConsentCategory\n\tqueue: ScriptQueueItem[]\n\tonLoad: (id: string) => void\n\tonDequeue: (id: string) => void\n}\n\nfunction QueueProcessor({ category, queue, onLoad, onDequeue }: QueueProcessorProps) {\n\tconst { hasConsent, isLoading } = useConsentGate({ category })\n\tconst processedRef = useRef<Set<string>>(new Set())\n\n\tuseEffect(() => {\n\t\tif (isLoading || !hasConsent) return\n\n\t\t// Process all queued scripts for this category\n\t\tconst categoryScripts = queue.filter(\n\t\t\t(s) => s.category === category && !processedRef.current.has(s.id),\n\t\t)\n\n\t\tfor (const script of categoryScripts) {\n\t\t\tprocessedRef.current.add(script.id)\n\t\t\tloadScript(script)\n\t\t\t\t.then(() => {\n\t\t\t\t\tscript.onLoad?.()\n\t\t\t\t\tonLoad(script.id)\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tscript.onError?.(error)\n\t\t\t\t})\n\t\t\t\t.finally(() => {\n\t\t\t\t\tonDequeue(script.id)\n\t\t\t\t})\n\t\t}\n\t}, [hasConsent, isLoading, queue, category, onLoad, onDequeue])\n\n\treturn null\n}\n\n// ============================================\n// Script Loading Utility\n// ============================================\n\n/**\n * Load a script dynamically\n */\nasync function loadScript(item: ScriptQueueItem): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\t// Check if already loaded\n\t\tif (item.src && document.querySelector(`script[src=\"${item.src}\"]`)) {\n\t\t\tresolve()\n\t\t\treturn\n\t\t}\n\n\t\tconst script = document.createElement('script')\n\n\t\tif (item.src) {\n\t\t\tscript.src = item.src\n\t\t} else if (item.content) {\n\t\t\tscript.textContent = item.content\n\t\t}\n\n\t\t// Apply attributes\n\t\tfor (const [key, value] of Object.entries(item.attributes)) {\n\t\t\tif (value === undefined) continue\n\t\t\tif (typeof value === 'boolean') {\n\t\t\t\tif (value) script.setAttribute(key, '')\n\t\t\t} else {\n\t\t\t\tscript.setAttribute(key, value)\n\t\t\t}\n\t\t}\n\n\t\t// Set id for tracking\n\t\tif (item.id) {\n\t\t\tscript.id = item.id\n\t\t}\n\n\t\t// Apply strategy\n\t\tswitch (item.strategy) {\n\t\t\tcase 'beforeInteractive':\n\t\t\t\t// Load immediately (blocking)\n\t\t\t\tbreak\n\t\t\tcase 'afterInteractive':\n\t\t\t\tscript.async = true\n\t\t\t\tbreak\n\t\t\tcase 'lazyOnload':\n\t\t\t\tscript.async = true\n\t\t\t\tscript.defer = true\n\t\t\t\tbreak\n\t\t\tcase 'worker':\n\t\t\t\t// Web Worker strategy - not supported for external scripts\n\t\t\t\t// Falls back to async\n\t\t\t\tscript.async = true\n\t\t\t\tbreak\n\t\t}\n\n\t\tscript.onload = () => resolve()\n\t\tscript.onerror = () => reject(new Error(`Failed to load script: ${item.src ?? 'inline'}`))\n\n\t\t// Inline scripts execute immediately\n\t\tif (!item.src && item.content) {\n\t\t\tdocument.head.appendChild(script)\n\t\t\tresolve()\n\t\t\treturn\n\t\t}\n\n\t\tdocument.head.appendChild(script)\n\t})\n}\n\n// ============================================\n// ConsentScript Component\n// ============================================\n\nlet scriptIdCounter = 0\nfunction generateScriptId(src?: string): string {\n\tif (src) {\n\t\t// Generate ID from URL\n\t\ttry {\n\t\t\tconst url = new URL(src)\n\t\t\treturn `consent-script-${url.hostname.replace(/\\./g, '-')}-${scriptIdCounter++}`\n\t\t} catch {\n\t\t\treturn `consent-script-${scriptIdCounter++}`\n\t\t}\n\t}\n\treturn `consent-script-inline-${scriptIdCounter++}`\n}\n\n/**\n * Consent-aware script component\n *\n * Only loads scripts when the required consent category is granted.\n * If consent is not granted, the script is queued for later loading.\n *\n * @example\n * ```tsx\n * // External script\n * <ConsentScript\n *   src=\"https://example.com/analytics.js\"\n *   category=\"analytics\"\n *   onLoad={() => console.log('Loaded!')}\n * />\n *\n * // Inline script\n * <ConsentScript category=\"marketing\">\n *   {`window.fbq('init', 'PIXEL_ID')`}\n * </ConsentScript>\n * ```\n */\nexport function ConsentScript({\n\tsrc,\n\tchildren,\n\tcategory,\n\tstrategy = 'afterInteractive',\n\tonLoad,\n\tonError,\n\tonBlock,\n\tasync: asyncAttr,\n\tdefer,\n\tid: providedId,\n\tnonce,\n\t...dataAttributes\n}: ConsentScriptProps) {\n\tconst scriptManager = useScriptManager()\n\tconst { hasConsent, isLoading } = useConsentGate({\n\t\tcategory,\n\t\tonDeny: onBlock,\n\t})\n\tconst scriptIdRef = useRef(providedId ?? generateScriptId(src))\n\tconst loadedRef = useRef(false)\n\n\t// Build attributes object — memoized so it's stable across renders\n\t// (otherwise `useEffect(..., [attributes])` would retrigger every render).\n\tconst attributes: Record<string, string | boolean | undefined> = useMemo(\n\t\t() => ({\n\t\t\tasync: asyncAttr,\n\t\t\tdefer,\n\t\t\tnonce,\n\t\t\t...dataAttributes,\n\t\t}),\n\t\t[asyncAttr, defer, nonce, dataAttributes],\n\t)\n\n\tuseEffect(() => {\n\t\t// Skip if already loaded\n\t\tif (loadedRef.current) return\n\n\t\t// Skip during loading\n\t\tif (isLoading) return\n\n\t\tif (hasConsent) {\n\t\t\t// Load immediately\n\t\t\tconst item: ScriptQueueItem = {\n\t\t\t\tid: scriptIdRef.current,\n\t\t\t\tsrc,\n\t\t\t\tcontent: children,\n\t\t\t\tcategory,\n\t\t\t\tstrategy,\n\t\t\t\tattributes,\n\t\t\t\tonLoad,\n\t\t\t\tonError,\n\t\t\t}\n\n\t\t\tloadScript(item)\n\t\t\t\t.then(() => {\n\t\t\t\t\tloadedRef.current = true\n\t\t\t\t\tonLoad?.()\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tonError?.(error)\n\t\t\t\t})\n\t\t} else if (scriptManager) {\n\t\t\t// Queue for later\n\t\t\tscriptManager.queueScript({\n\t\t\t\tid: scriptIdRef.current,\n\t\t\t\tsrc,\n\t\t\t\tcontent: children,\n\t\t\t\tcategory,\n\t\t\t\tstrategy,\n\t\t\t\tattributes,\n\t\t\t\tonLoad,\n\t\t\t\tonError,\n\t\t\t})\n\t\t}\n\t}, [\n\t\thasConsent,\n\t\tisLoading,\n\t\tsrc,\n\t\tchildren,\n\t\tcategory,\n\t\tstrategy,\n\t\tscriptManager,\n\t\tonLoad,\n\t\tonError,\n\t\tattributes,\n\t])\n\n\t// Cleanup on unmount\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tif (scriptManager) {\n\t\t\t\tscriptManager.dequeueScript(scriptIdRef.current)\n\t\t\t}\n\t\t}\n\t}, [scriptManager])\n\n\t// Don't render anything - script is loaded dynamically\n\treturn null\n}\n\n// ============================================\n// Known Script Components\n// ============================================\n\nexport interface GoogleAnalyticsProps {\n\t/** Google Analytics Measurement ID (G-XXXXXX) */\n\tmeasurementId: string\n\t/** Script loading strategy */\n\tstrategy?: ScriptStrategy\n\t/** Additional gtag config options */\n\tconfig?: Record<string, unknown>\n\t/** Called when GA loads */\n\tonLoad?: () => void\n}\n\n/**\n * Google Analytics 4 with consent management\n *\n * Automatically blocks GA until analytics consent is granted.\n * Supports Google Consent Mode v2.\n *\n * @example\n * ```tsx\n * <GoogleAnalytics\n *   measurementId=\"G-XXXXXX\"\n *   config={{ debug_mode: true }}\n * />\n * ```\n */\nexport function GoogleAnalytics({\n\tmeasurementId,\n\tstrategy = 'afterInteractive',\n\tconfig,\n\tonLoad,\n}: GoogleAnalyticsProps) {\n\tconst { hasConsent, isLoading } = useConsentGate({ category: 'analytics' })\n\tconst loadedRef = useRef(false)\n\n\tuseEffect(() => {\n\t\tif (loadedRef.current || isLoading || !hasConsent) return\n\n\t\t// Load gtag.js\n\t\tconst script = document.createElement('script')\n\t\tscript.src = `https://www.googletagmanager.com/gtag/js?id=${measurementId}`\n\t\tscript.async = true\n\n\t\tscript.onload = () => {\n\t\t\t// Initialize gtag\n\t\t\twindow.dataLayer = window.dataLayer || []\n\t\t\tfunction gtag(...args: unknown[]) {\n\t\t\t\twindow.dataLayer.push(args)\n\t\t\t}\n\t\t\twindow.gtag = gtag\n\t\t\tgtag('js', new Date())\n\t\t\tgtag('config', measurementId, config ?? {})\n\n\t\t\tloadedRef.current = true\n\t\t\tonLoad?.()\n\t\t}\n\n\t\tdocument.head.appendChild(script)\n\t}, [hasConsent, isLoading, measurementId, config, onLoad])\n\n\treturn null\n}\n\nexport interface GoogleTagManagerProps {\n\t/** GTM Container ID (GTM-XXXXXX) */\n\tcontainerId: string\n\t/** Script loading strategy */\n\tstrategy?: ScriptStrategy\n\t/** Data layer name (default: dataLayer) */\n\tdataLayerName?: string\n\t/** Called when GTM loads */\n\tonLoad?: () => void\n}\n\n/**\n * Google Tag Manager with consent management\n *\n * Blocks GTM until analytics consent is granted.\n * GTM typically requires analytics consent as it can load many sub-scripts.\n *\n * @example\n * ```tsx\n * <GoogleTagManager containerId=\"GTM-XXXXXX\" />\n * ```\n */\nexport function GoogleTagManager({\n\tcontainerId,\n\tstrategy = 'afterInteractive',\n\tdataLayerName = 'dataLayer',\n\tonLoad,\n}: GoogleTagManagerProps) {\n\tconst { hasConsent, isLoading } = useConsentGate({ category: 'analytics' })\n\tconst loadedRef = useRef(false)\n\n\tuseEffect(() => {\n\t\tif (loadedRef.current || isLoading || !hasConsent) return\n\n\t\t// Initialize dataLayer\n\t\twindow[dataLayerName as 'dataLayer'] = window[dataLayerName as 'dataLayer'] || []\n\t\twindow[dataLayerName as 'dataLayer'].push({\n\t\t\t'gtm.start': Date.now(),\n\t\t\tevent: 'gtm.js',\n\t\t})\n\n\t\t// Load GTM script\n\t\tconst script = document.createElement('script')\n\t\tscript.src = `https://www.googletagmanager.com/gtm.js?id=${containerId}${dataLayerName !== 'dataLayer' ? `&l=${dataLayerName}` : ''}`\n\t\tscript.async = true\n\n\t\tscript.onload = () => {\n\t\t\tloadedRef.current = true\n\t\t\tonLoad?.()\n\t\t}\n\n\t\tdocument.head.appendChild(script)\n\t}, [hasConsent, isLoading, containerId, dataLayerName, onLoad])\n\n\treturn null\n}\n\nexport interface FacebookPixelProps {\n\t/** Facebook Pixel ID */\n\tpixelId: string\n\t/** Called when Pixel loads */\n\tonLoad?: () => void\n\t/** Auto-track PageView on load */\n\tautoPageView?: boolean\n}\n\n/**\n * Facebook Pixel with consent management\n *\n * Blocks Facebook Pixel until marketing consent is granted.\n *\n * @example\n * ```tsx\n * <FacebookPixel pixelId=\"XXXXXX\" autoPageView />\n * ```\n */\nexport function FacebookPixel({ pixelId, onLoad, autoPageView = true }: FacebookPixelProps) {\n\tconst { hasConsent, isLoading } = useConsentGate({ category: 'marketing' })\n\tconst loadedRef = useRef(false)\n\n\tuseEffect(() => {\n\t\tif (loadedRef.current || isLoading || !hasConsent) return\n\n\t\t// Initialize fbq\n\t\tconst n = ((...args: unknown[]) => {\n\t\t\tif (n.callMethod) {\n\t\t\t\tn.callMethod.apply(n, args)\n\t\t\t} else {\n\t\t\t\tn.queue.push(args)\n\t\t\t}\n\t\t}) as unknown as typeof window.fbq\n\t\twindow.fbq = n\n\t\tif (!window._fbq) window._fbq = n\n\t\tn.push = n\n\t\tn.loaded = true\n\t\tn.version = '2.0'\n\t\tn.queue = []\n\n\t\t// Load Facebook Pixel script\n\t\tconst script = document.createElement('script')\n\t\tscript.src = 'https://connect.facebook.net/en_US/fbevents.js'\n\t\tscript.async = true\n\n\t\tscript.onload = () => {\n\t\t\twindow.fbq('init', pixelId)\n\t\t\tif (autoPageView) {\n\t\t\t\twindow.fbq('track', 'PageView')\n\t\t\t}\n\t\t\tloadedRef.current = true\n\t\t\tonLoad?.()\n\t\t}\n\n\t\tdocument.head.appendChild(script)\n\t}, [hasConsent, isLoading, pixelId, autoPageView, onLoad])\n\n\treturn null\n}\n\nexport interface HotjarProps {\n\t/** Hotjar Site ID */\n\tsiteId: number\n\t/** Hotjar Snippet Version (default: 6) */\n\tversion?: number\n\t/** Called when Hotjar loads */\n\tonLoad?: () => void\n}\n\n/**\n * Hotjar with consent management\n *\n * Blocks Hotjar until analytics consent is granted.\n *\n * @example\n * ```tsx\n * <Hotjar siteId={123456} />\n * ```\n */\nexport function Hotjar({ siteId, version = 6, onLoad }: HotjarProps) {\n\tconst { hasConsent, isLoading } = useConsentGate({ category: 'analytics' })\n\tconst loadedRef = useRef(false)\n\n\tuseEffect(() => {\n\t\tif (loadedRef.current || isLoading || !hasConsent) return\n\n\t\t// Initialize Hotjar\n\t\twindow.hj =\n\t\t\twindow.hj ||\n\t\t\t((...args: unknown[]) => {\n\t\t\t\twindow.hj.q = window.hj.q || []\n\t\t\t\twindow.hj.q.push(args)\n\t\t\t})\n\t\twindow._hjSettings = { hjid: siteId, hjsv: version }\n\n\t\t// Load Hotjar script\n\t\tconst script = document.createElement('script')\n\t\tscript.src = `https://static.hotjar.com/c/hotjar-${siteId}.js?sv=${version}`\n\t\tscript.async = true\n\n\t\tscript.onload = () => {\n\t\t\tloadedRef.current = true\n\t\t\tonLoad?.()\n\t\t}\n\n\t\tdocument.head.appendChild(script)\n\t}, [hasConsent, isLoading, siteId, version, onLoad])\n\n\treturn null\n}\n\nexport interface IntercomProps {\n\t/** Intercom App ID */\n\tappId: string\n\t/** Called when Intercom loads */\n\tonLoad?: () => void\n}\n\n/**\n * Intercom with consent management\n *\n * Blocks Intercom until preferences consent is granted.\n * (Intercom stores user preferences and communication history)\n *\n * @example\n * ```tsx\n * <Intercom appId=\"abc123\" />\n * ```\n */\nexport function Intercom({ appId, onLoad }: IntercomProps) {\n\tconst { hasConsent, isLoading } = useConsentGate({ category: 'preferences' })\n\tconst loadedRef = useRef(false)\n\n\tuseEffect(() => {\n\t\tif (loadedRef.current || isLoading || !hasConsent) return\n\n\t\t// Initialize Intercom\n\t\twindow.intercomSettings = { app_id: appId }\n\n\t\tconst ic = window.Intercom\n\t\tif (typeof ic === 'function') {\n\t\t\tic('reattach_activator')\n\t\t\tic('update', window.intercomSettings)\n\t\t} else {\n\t\t\tconst i = ((...args: unknown[]) => {\n\t\t\t\ti.c(args)\n\t\t\t}) as unknown as typeof window.Intercom\n\t\t\ti.q = []\n\t\t\ti.c = (args: unknown[]) => {\n\t\t\t\ti.q.push(args)\n\t\t\t}\n\t\t\twindow.Intercom = i\n\t\t}\n\n\t\t// Load Intercom script\n\t\tconst script = document.createElement('script')\n\t\tscript.src = `https://widget.intercom.io/widget/${appId}`\n\t\tscript.async = true\n\n\t\tscript.onload = () => {\n\t\t\tloadedRef.current = true\n\t\t\tonLoad?.()\n\t\t}\n\n\t\tdocument.head.appendChild(script)\n\t}, [hasConsent, isLoading, appId, onLoad])\n\n\treturn null\n}\n\n// ============================================\n// Google Consent Mode v2\n// ============================================\n\n/**\n * Consent Mode v2 consent states\n *\n * These map to Google's consent types:\n * - ad_storage: Enables storage related to advertising\n * - ad_user_data: Sets consent for sending user data to Google for ads\n * - ad_personalization: Sets consent for personalized advertising\n * - analytics_storage: Enables storage related to analytics\n * - functionality_storage: Enables storage for website functionality\n * - personalization_storage: Enables storage for personalization\n * - security_storage: Enables storage for security (always granted)\n */\nexport type GoogleConsentType =\n\t| 'ad_storage'\n\t| 'ad_user_data'\n\t| 'ad_personalization'\n\t| 'analytics_storage'\n\t| 'functionality_storage'\n\t| 'personalization_storage'\n\t| 'security_storage'\n\nexport type GoogleConsentState = 'granted' | 'denied'\n\nexport interface GoogleConsentModeConfig {\n\t/** Default consent states (before user interaction) */\n\tdefaults?: Partial<Record<GoogleConsentType, GoogleConsentState>>\n\t/** Wait for update timeout in ms (default: CONSENT_WAIT_FOR_UPDATE_MS) */\n\twaitForUpdate?: number\n\t/** Regions to apply defaults (e.g., ['EU', 'US-CA']) */\n\tregions?: string[]\n\t/** Enable URL passthrough for ad click info */\n\turlPassthrough?: boolean\n\t/** Enable ads data redaction when consent denied */\n\tadsDataRedaction?: boolean\n}\n\nexport interface GoogleConsentModeProps extends GoogleConsentModeConfig {\n\t/** Called when consent mode is initialized */\n\tonInit?: () => void\n}\n\n/**\n * Map our consent categories to Google Consent Mode types\n */\nconst CONSENT_CATEGORY_TO_GOOGLE: Record<ConsentCategory, GoogleConsentType[]> = {\n\tnecessary: ['security_storage'],\n\tfunctional: ['functionality_storage'],\n\tpreferences: ['personalization_storage'],\n\tanalytics: ['analytics_storage'],\n\tmarketing: ['ad_storage', 'ad_user_data', 'ad_personalization'],\n}\n\n/**\n * Google Consent Mode v2 Integration\n *\n * Automatically syncs consent state with Google's Consent Mode API.\n * Place this component early in your app (before Google tags).\n *\n * @see https://developers.google.com/tag-platform/security/guides/consent\n *\n * @example\n * ```tsx\n * // Basic usage with defaults\n * <GoogleConsentMode\n *   defaults={{\n *     ad_storage: 'denied',\n *     analytics_storage: 'denied',\n *   }}\n * />\n *\n * // With region-specific defaults (EU only)\n * <GoogleConsentMode\n *   defaults={{\n *     ad_storage: 'denied',\n *     ad_user_data: 'denied',\n *     ad_personalization: 'denied',\n *     analytics_storage: 'denied',\n *   }}\n *   regions={['EU']}\n *   waitForUpdate={500}\n *   urlPassthrough={true}\n *   adsDataRedaction={true}\n * />\n * ```\n */\nexport function GoogleConsentMode({\n\tdefaults = {\n\t\tad_storage: 'denied',\n\t\tad_user_data: 'denied',\n\t\tad_personalization: 'denied',\n\t\tanalytics_storage: 'denied',\n\t\tfunctionality_storage: 'granted',\n\t\tpersonalization_storage: 'denied',\n\t\tsecurity_storage: 'granted',\n\t},\n\twaitForUpdate = CONSENT_WAIT_FOR_UPDATE_MS,\n\tregions,\n\turlPassthrough = true,\n\tadsDataRedaction = true,\n\tonInit,\n}: GoogleConsentModeProps) {\n\tconst { hasConsent: checkConsent, isLoading } = useConsent()\n\tconst initializedRef = useRef(false)\n\tconst lastConsentRef = useRef<Record<string, boolean>>({})\n\n\t// Initialize consent mode defaults\n\tuseEffect(() => {\n\t\tif (initializedRef.current) return\n\n\t\t// Initialize dataLayer and gtag\n\t\twindow.dataLayer = window.dataLayer || []\n\t\tfunction gtag(...args: unknown[]) {\n\t\t\twindow.dataLayer.push(args)\n\t\t}\n\t\twindow.gtag = gtag\n\n\t\t// Set default consent state\n\t\tconst defaultConsent: Record<string, string> = {}\n\t\tfor (const [type, state] of Object.entries(defaults)) {\n\t\t\tdefaultConsent[type] = state\n\t\t}\n\n\t\t// Add regions if specified\n\t\tif (regions?.length) {\n\t\t\tgtag('consent', 'default', {\n\t\t\t\t...defaultConsent,\n\t\t\t\tregions,\n\t\t\t\twait_for_update: waitForUpdate,\n\t\t\t})\n\t\t} else {\n\t\t\tgtag('consent', 'default', {\n\t\t\t\t...defaultConsent,\n\t\t\t\twait_for_update: waitForUpdate,\n\t\t\t})\n\t\t}\n\n\t\t// Configure additional settings\n\t\tif (urlPassthrough) {\n\t\t\tgtag('set', 'url_passthrough', true)\n\t\t}\n\n\t\tif (adsDataRedaction) {\n\t\t\tgtag('set', 'ads_data_redaction', true)\n\t\t}\n\n\t\tinitializedRef.current = true\n\t\tonInit?.()\n\t}, [defaults, waitForUpdate, regions, urlPassthrough, adsDataRedaction, onInit])\n\n\t// Update consent when user preferences change\n\tuseEffect(() => {\n\t\tif (!initializedRef.current || isLoading) return\n\n\t\t// Build Google consent update from our categories\n\t\tconst consentUpdate: Record<string, GoogleConsentState> = {}\n\n\t\t// Check each category and map to Google consent types\n\t\tfor (const category of [\n\t\t\t'necessary',\n\t\t\t'functional',\n\t\t\t'preferences',\n\t\t\t'analytics',\n\t\t\t'marketing',\n\t\t] as ConsentCategory[]) {\n\t\t\tconst hasCategory = checkConsent(category)\n\t\t\tconst googleTypes = CONSENT_CATEGORY_TO_GOOGLE[category]\n\n\t\t\tfor (const googleType of googleTypes) {\n\t\t\t\tconsentUpdate[googleType] = hasCategory ? 'granted' : 'denied'\n\t\t\t}\n\t\t}\n\n\t\t// Only update if something changed\n\t\tconst consentKey = JSON.stringify(consentUpdate)\n\t\tif (consentKey === JSON.stringify(lastConsentRef.current)) return\n\n\t\tlastConsentRef.current = consentUpdate as unknown as Record<string, boolean>\n\n\t\t// Send consent update to Google\n\t\twindow.gtag?.('consent', 'update', consentUpdate)\n\t}, [checkConsent, isLoading])\n\n\treturn null\n}\n\n/**\n * Hook to manually update Google Consent Mode\n *\n * @example\n * ```tsx\n * const { updateConsent, revokeAll, grantAll } = useGoogleConsentMode()\n *\n * // Update specific consent type\n * updateConsent('analytics_storage', 'granted')\n *\n * // Revoke all marketing consent\n * updateConsent('ad_storage', 'denied')\n * updateConsent('ad_user_data', 'denied')\n * updateConsent('ad_personalization', 'denied')\n * ```\n */\nexport function useGoogleConsentMode() {\n\tconst updateConsent = useCallback((type: GoogleConsentType, state: GoogleConsentState) => {\n\t\tif (typeof window === 'undefined' || !window.gtag) return\n\n\t\twindow.gtag('consent', 'update', {\n\t\t\t[type]: state,\n\t\t})\n\t}, [])\n\n\tconst updateMultiple = useCallback(\n\t\t(consents: Partial<Record<GoogleConsentType, GoogleConsentState>>) => {\n\t\t\tif (typeof window === 'undefined' || !window.gtag) return\n\n\t\t\twindow.gtag('consent', 'update', consents)\n\t\t},\n\t\t[],\n\t)\n\n\tconst revokeAll = useCallback(() => {\n\t\tupdateMultiple({\n\t\t\tad_storage: 'denied',\n\t\t\tad_user_data: 'denied',\n\t\t\tad_personalization: 'denied',\n\t\t\tanalytics_storage: 'denied',\n\t\t\tpersonalization_storage: 'denied',\n\t\t})\n\t}, [updateMultiple])\n\n\tconst grantAll = useCallback(() => {\n\t\tupdateMultiple({\n\t\t\tad_storage: 'granted',\n\t\t\tad_user_data: 'granted',\n\t\t\tad_personalization: 'granted',\n\t\t\tanalytics_storage: 'granted',\n\t\t\tfunctionality_storage: 'granted',\n\t\t\tpersonalization_storage: 'granted',\n\t\t})\n\t}, [updateMultiple])\n\n\treturn {\n\t\tupdateConsent,\n\t\tupdateMultiple,\n\t\trevokeAll,\n\t\tgrantAll,\n\t}\n}\n\n// ============================================\n// Type Declarations for Global Objects\n// ============================================\n\ndeclare global {\n\tinterface Window {\n\t\t// Google Analytics / Consent Mode\n\t\tdataLayer: unknown[]\n\t\tgtag: (...args: unknown[]) => void\n\n\t\t// Facebook Pixel\n\t\tfbq: {\n\t\t\t(...args: unknown[]): void\n\t\t\tcallMethod?: (...args: unknown[]) => void\n\t\t\tqueue: unknown[][]\n\t\t\tpush: (...args: unknown[]) => void\n\t\t\tloaded: boolean\n\t\t\tversion: string\n\t\t}\n\t\t_fbq: typeof window.fbq\n\n\t\t// Hotjar\n\t\thj: {\n\t\t\t(...args: unknown[]): void\n\t\t\tq?: unknown[][]\n\t\t}\n\t\t_hjSettings: { hjid: number; hjsv: number }\n\n\t\t// Intercom\n\t\tIntercom: {\n\t\t\t(...args: unknown[]): void\n\t\t\tq: unknown[][]\n\t\t\tc: (args: unknown[]) => void\n\t\t}\n\t\tintercomSettings: { app_id: string; [key: string]: unknown }\n\t}\n}\n","/**\n * Email Hooks\n *\n * React hooks for Sylphx Platform transactional email service.\n * Send emails, use templates, and send to users.\n */\n\n'use client'\n\nimport { useCallback, useState } from 'react'\nimport {\n\ttype EmailTemplateName,\n\ttype SimpleEmailOptions,\n\tuseEmailContext,\n} from './services-context'\n\n// Re-export types for convenience\n\n// ============================================\n// useEmail\n// ============================================\n\nexport interface UseEmailReturn {\n\t/** Send an email */\n\tsend: (options: SimpleEmailOptions) => Promise<{ success: boolean; id?: string }>\n\t/** Send a templated email */\n\tsendTemplated: (options: {\n\t\ttemplate: EmailTemplateName\n\t\tto: string\n\t\tdata?: Record<string, unknown>\n\t}) => Promise<{ success: boolean; template: string }>\n\t/** Send email to a user by ID */\n\tsendToUser: (options: {\n\t\tuserId: string\n\t\tsubject: string\n\t\thtml: string\n\t\ttext?: string\n\t}) => Promise<{ success: boolean; id?: string }>\n\t/** Whether an operation is in progress */\n\tisLoading: boolean\n\t/** Whether the last send was successful */\n\tisSuccess: boolean\n\t/** Last error */\n\terror: Error | null\n\t/** Reset state */\n\treset: () => void\n}\n\n/**\n * Hook for sending transactional emails\n *\n * @example\n * ```tsx\n * function SendEmailButton() {\n *   const { send, isLoading, isSuccess, error } = useEmail()\n *\n *   const handleSend = async () => {\n *     await send({\n *       to: 'user@example.com',\n *       subject: 'Welcome!',\n *       html: '<h1>Welcome to our app</h1>',\n *     })\n *   }\n *\n *   return (\n *     <div>\n *       <button onClick={handleSend} disabled={isLoading}>\n *         {isLoading ? 'Sending...' : 'Send Email'}\n *       </button>\n *       {isSuccess && <p>Email sent!</p>}\n *       {error && <p className=\"error\">{error.message}</p>}\n *     </div>\n *   )\n * }\n * ```\n */\nexport function useEmail(): UseEmailReturn {\n\tconst ctx = useEmailContext()\n\tconst [isLoading, setIsLoading] = useState(false)\n\tconst [isSuccess, setIsSuccess] = useState(false)\n\tconst [error, setError] = useState<Error | null>(null)\n\n\tconst reset = useCallback(() => {\n\t\tsetIsSuccess(false)\n\t\tsetError(null)\n\t}, [])\n\n\tconst send = useCallback(\n\t\tasync (options: SimpleEmailOptions): Promise<{ success: boolean; id?: string }> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\t\t\tsetIsSuccess(false)\n\n\t\t\ttry {\n\t\t\t\tconst result = await ctx.send(options)\n\t\t\t\tsetIsSuccess(result.success)\n\t\t\t\treturn result\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to send email')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst sendTemplated = useCallback(\n\t\tasync (options: {\n\t\t\ttemplate: EmailTemplateName\n\t\t\tto: string\n\t\t\tdata?: Record<string, unknown>\n\t\t}): Promise<{ success: boolean; template: string }> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\t\t\tsetIsSuccess(false)\n\n\t\t\ttry {\n\t\t\t\tconst result = await ctx.sendTemplated(options)\n\t\t\t\tsetIsSuccess(result.success)\n\t\t\t\treturn result\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to send templated email')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst sendToUser = useCallback(\n\t\tasync (options: {\n\t\t\tuserId: string\n\t\t\tsubject: string\n\t\t\thtml: string\n\t\t\ttext?: string\n\t\t}): Promise<{ success: boolean; id?: string }> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\t\t\tsetIsSuccess(false)\n\n\t\t\ttry {\n\t\t\t\tconst result = await ctx.sendToUser(options)\n\t\t\t\tsetIsSuccess(result.success)\n\t\t\t\treturn result\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to send email to user')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\treturn {\n\t\tsend,\n\t\tsendTemplated,\n\t\tsendToUser,\n\t\tisLoading,\n\t\tisSuccess,\n\t\terror,\n\t\treset,\n\t}\n}\n","/**\n * Engagement React Hooks\n *\n * Hooks for streaks, leaderboards, and achievements.\n *\n * ## Architecture (ADR-004)\n *\n * Engagement uses **Auto-Discovery + Console Override**:\n * - Entities are auto-discovered when first referenced\n * - No config required - just use the hooks\n * - Console can override values without deployment\n *\n * ## React Query Integration\n *\n * All hooks use React Query for:\n * - Automatic caching and deduplication\n * - Stale-while-revalidate updates\n * - Background refetching\n */\n\n'use client'\n\nimport { useQuery } from '@tanstack/react-query'\nimport { useCallback, useContext, useMemo, useState } from 'react'\nimport { STALE_TIME_FREQUENT_MS, STALE_TIME_MODERATE_MS, STALE_TIME_STABLE_MS } from '../constants'\nimport type {\n\tAchievementDefaults,\n\tAchievementUnlockEvent,\n\tLeaderboardDefaults,\n\tLeaderboardEntry,\n\tLeaderboardQueryOptions,\n\tLeaderboardResult,\n\tRecordActivityResult,\n\tStreakDefaults,\n\tStreakState,\n\tSubmitScoreResult,\n\tUserAchievement,\n} from '../lib/engagement/types'\nimport { PlatformContext } from './platform-context'\n\n// ============================================================================\n// Context Hook\n// ============================================================================\n\nfunction useEngagementContext() {\n\tconst context = useContext(PlatformContext)\n\tif (!context) {\n\t\tthrow new Error('Engagement hooks must be used within a SylphxProvider')\n\t}\n\treturn context\n}\n\n/**\n * Safe version that returns null if no provider (for SSR/prerendering)\n */\nfunction useEngagementContextSafe() {\n\treturn useContext(PlatformContext)\n}\n\n// ============================================================================\n// useStreak\n// ============================================================================\n\nexport interface UseStreakReturn {\n\t/** Current streak state */\n\tstate: StreakState | null\n\t/** Whether loading */\n\tisLoading: boolean\n\t/** Error if any */\n\terror: Error | null\n\t/** Current streak value */\n\tcurrent: number\n\t/** Longest streak ever */\n\tlongest: number\n\t/** Whether streak can be recovered */\n\tcanRecover: boolean\n\t/** Time remaining until expiry (ms) */\n\ttimeRemainingMs: number | null\n\t/** User's stored timezone preference (IANA timezone) */\n\tuserTimezone: string | null\n\t/** Record activity to extend streak */\n\trecordActivity: (metadata?: Record<string, unknown>) => Promise<RecordActivityResult>\n\t/** Recover streak (if within grace period) */\n\trecover: () => Promise<{ success: boolean; streak: StreakState }>\n\t/** Refresh streak state */\n\trefresh: () => Promise<void>\n}\n\n/** Options for useStreak hook */\ninterface UseStreakOptions {\n\t/** Optional inline defaults for auto-discovery */\n\tdefaults?: StreakDefaults\n\t/** User's IANA timezone (e.g., 'America/New_York') for calculating streak expiry at user's local midnight */\n\tuserTimezone?: string\n}\n\n/**\n * Hook for managing a streak\n *\n * If the streak doesn't exist, it will be auto-discovered with the provided defaults.\n * Console can override any values without deployment.\n *\n * @param streakId - Streak identifier\n * @param options - Optional options including defaults for auto-discovery and user timezone\n *\n * @example\n * ```tsx\n * function DailyStreakCard() {\n *   const {\n *     current,\n *     longest,\n *     timeRemainingMs,\n *     canRecover,\n *     recordActivity,\n *     recover,\n *     userTimezone,\n *   } = useStreak('daily-challenge', {\n *     defaults: {\n *       name: 'Daily Challenge',\n *       frequency: 'daily',\n *       gracePeriodHours: 12,\n *     },\n *     userTimezone: 'America/New_York', // Streak expires at user's local midnight\n *   })\n *\n *   const handleComplete = async () => {\n *     const result = await recordActivity()\n *     if (result.newPersonalBest) {\n *       showConfetti()\n *     }\n *   }\n *\n *   return (\n *     <div>\n *       <p>Current streak: {current} 🔥</p>\n *       <p>Best: {longest}</p>\n *       {timeRemainingMs && (\n *         <p>Expires in: {formatTime(timeRemainingMs)}</p>\n *       )}\n *       {canRecover && (\n *         <button onClick={recover}>Recover Streak</button>\n *       )}\n *     </div>\n *   )\n * }\n * ```\n */\nexport function useStreak(streakId: string, options?: UseStreakOptions): UseStreakReturn {\n\tconst { defaults, userTimezone } = options ?? {}\n\tconst ctx = useEngagementContext()\n\n\t// React Query for streak data\n\tconst streakQuery = useQuery({\n\t\tqueryKey: ['sylphx', ctx.appId, 'streak', streakId, userTimezone],\n\t\tqueryFn: () => ctx.getStreak(streakId, defaults, userTimezone),\n\t\tenabled: !!ctx.user,\n\t\tstaleTime: STALE_TIME_FREQUENT_MS, // 1 min - streaks can change frequently\n\t})\n\n\tconst state = streakQuery.data ?? null\n\n\t// Record activity (passes inline defaults for auto-discovery and timezone)\n\tconst recordActivity = useCallback(\n\t\tasync (metadata?: Record<string, unknown>): Promise<RecordActivityResult> => {\n\t\t\tconst result = await ctx.recordStreakActivity(streakId, metadata, defaults, userTimezone)\n\t\t\t// Update cache with new streak state\n\t\t\tctx.queryClient.setQueryData(\n\t\t\t\t['sylphx', ctx.appId, 'streak', streakId, userTimezone],\n\t\t\t\tresult.streak,\n\t\t\t)\n\t\t\treturn result\n\t\t},\n\t\t[ctx, streakId, defaults, userTimezone],\n\t)\n\n\t// Recover streak (passes timezone)\n\tconst recover = useCallback(async (): Promise<{\n\t\tsuccess: boolean\n\t\tstreak: StreakState\n\t}> => {\n\t\tconst result = await ctx.recoverStreak(streakId, userTimezone)\n\t\tif (result.success) {\n\t\t\tctx.queryClient.setQueryData(\n\t\t\t\t['sylphx', ctx.appId, 'streak', streakId, userTimezone],\n\t\t\t\tresult.streak,\n\t\t\t)\n\t\t}\n\t\treturn result\n\t}, [ctx, streakId, userTimezone])\n\n\t// Refresh via React Query invalidation\n\tconst refresh = useCallback(async () => {\n\t\tawait ctx.queryClient.invalidateQueries({\n\t\t\tqueryKey: ['sylphx', ctx.appId, 'streak', streakId],\n\t\t})\n\t}, [ctx, streakId])\n\n\treturn {\n\t\tstate,\n\t\tisLoading: streakQuery.isLoading,\n\t\terror: streakQuery.error as Error | null,\n\t\tcurrent: state?.current ?? 0,\n\t\tlongest: state?.longest ?? 0,\n\t\tcanRecover: state?.canRecover ?? false,\n\t\ttimeRemainingMs: state?.timeRemainingMs ?? null,\n\t\tuserTimezone: state?.userTimezone ?? null,\n\t\trecordActivity,\n\t\trecover,\n\t\trefresh,\n\t}\n}\n\n// ============================================================================\n// useLeaderboard\n// ============================================================================\n\nexport interface UseLeaderboardReturn {\n\t/** Leaderboard data */\n\tdata: LeaderboardResult | null\n\t/** Whether loading */\n\tisLoading: boolean\n\t/** Error if any */\n\terror: Error | null\n\t/** Top entries */\n\tentries: LeaderboardEntry[]\n\t/** Current user's entry */\n\tcurrentUserEntry: LeaderboardEntry | null\n\t/** Total participants */\n\ttotalParticipants: number\n\t/** Submit a score */\n\tsubmitScore: (value: number, metadata?: Record<string, unknown>) => Promise<SubmitScoreResult>\n\t/** Refresh leaderboard */\n\trefresh: () => Promise<void>\n}\n\n/**\n * Hook for managing a leaderboard\n *\n * If the leaderboard doesn't exist, it will be auto-discovered with the provided defaults.\n * Console can override any values without deployment.\n *\n * @param leaderboardId - Leaderboard identifier\n * @param options - Query options (limit, offset, etc.)\n * @param defaults - Optional inline defaults for auto-discovery\n *\n * @example\n * ```tsx\n * function Leaderboard() {\n *   const {\n *     entries,\n *     currentUserEntry,\n *     totalParticipants,\n *     submitScore,\n *     isLoading,\n *   } = useLeaderboard('high-scores', { limit: 10 }, {\n *     name: 'High Scores',\n *     sortDirection: 'desc',\n *     resetPeriod: 'weekly',\n *   })\n *\n *   if (isLoading) return <Spinner />\n *\n *   return (\n *     <div>\n *       <h2>Top Players ({totalParticipants} total)</h2>\n *       {entries.map(entry => (\n *         <div key={entry.rank} className={entry.isCurrentUser ? 'highlight' : ''}>\n *           #{entry.rank} {entry.displayName}: {entry.value}\n *         </div>\n *       ))}\n *       {currentUserEntry && !entries.find(e => e.isCurrentUser) && (\n *         <div>\n *           ... Your rank: #{currentUserEntry.rank}\n *         </div>\n *       )}\n *     </div>\n *   )\n * }\n * ```\n */\nexport function useLeaderboard(\n\tleaderboardId: string,\n\toptions?: LeaderboardQueryOptions,\n\tdefaults?: LeaderboardDefaults,\n): UseLeaderboardReturn {\n\tconst ctx = useEngagementContext()\n\n\t// Stable key for options\n\tconst optionsKey = JSON.stringify(options ?? {})\n\n\t// React Query for leaderboard data\n\tconst leaderboardQuery = useQuery({\n\t\tqueryKey: ['sylphx', ctx.appId, 'leaderboard', leaderboardId, optionsKey],\n\t\tqueryFn: () => ctx.getLeaderboard(leaderboardId, options),\n\t\tstaleTime: STALE_TIME_MODERATE_MS, // 2 min - leaderboards change moderately\n\t})\n\n\tconst data = leaderboardQuery.data ?? null\n\n\t// Submit score (passes inline defaults for auto-discovery)\n\tconst submitScore = useCallback(\n\t\tasync (value: number, metadata?: Record<string, unknown>): Promise<SubmitScoreResult> => {\n\t\t\tconst result = await ctx.submitScore(leaderboardId, value, metadata, defaults)\n\t\t\t// Invalidate to get updated rankings\n\t\t\tvoid ctx.queryClient.invalidateQueries({\n\t\t\t\tqueryKey: ['sylphx', ctx.appId, 'leaderboard', leaderboardId],\n\t\t\t})\n\t\t\treturn result\n\t\t},\n\t\t[ctx, leaderboardId, defaults],\n\t)\n\n\t// Refresh via React Query invalidation\n\tconst refresh = useCallback(async () => {\n\t\tawait ctx.queryClient.invalidateQueries({\n\t\t\tqueryKey: ['sylphx', ctx.appId, 'leaderboard', leaderboardId],\n\t\t})\n\t}, [ctx, leaderboardId])\n\n\treturn {\n\t\tdata,\n\t\tisLoading: leaderboardQuery.isLoading,\n\t\terror: leaderboardQuery.error as Error | null,\n\t\tentries: data?.entries ?? [],\n\t\tcurrentUserEntry: data?.currentUserEntry ?? null,\n\t\ttotalParticipants: data?.totalParticipants ?? 0,\n\t\tsubmitScore,\n\t\trefresh,\n\t}\n}\n\n// ============================================================================\n// useAchievements\n// ============================================================================\n\nexport interface UseAchievementsReturn {\n\t/** User achievement states */\n\tachievements: UserAchievement[]\n\t/** Whether loading */\n\tisLoading: boolean\n\t/** Error if any */\n\terror: Error | null\n\t/** Unlocked achievements */\n\tunlocked: UserAchievement[]\n\t/** Locked achievements (with progress) */\n\tlocked: UserAchievement[]\n\t/** Get achievement state by ID */\n\tgetAchievement: (id: string) => UserAchievement | null\n\t/** Manually unlock an achievement (with optional inline defaults for auto-discovery) */\n\tunlock: (achievementId: string, defaults?: AchievementDefaults) => Promise<AchievementUnlockEvent>\n\t/** Increment progress (with optional inline defaults for auto-discovery) */\n\tincrementProgress: (\n\t\tachievementId: string,\n\t\tamount: number,\n\t\tdefaults?: AchievementDefaults,\n\t) => Promise<UserAchievement>\n\t/** Refresh achievements */\n\trefresh: () => Promise<void>\n\t/** Recently unlocked (for toast) */\n\trecentUnlock: AchievementUnlockEvent | null\n\t/** Dismiss recent unlock */\n\tdismissRecentUnlock: () => void\n}\n\n/**\n * Hook for managing achievements\n *\n * Achievements are auto-discovered with inline defaults when unlock/incrementProgress is called.\n * Console can override any values without deployment.\n *\n * @example\n * ```tsx\n * function AchievementsPage() {\n *   const {\n *     achievements,\n *     unlocked,\n *     locked,\n *     unlock,\n *     incrementProgress,\n *     recentUnlock,\n *     dismissRecentUnlock,\n *   } = useAchievements()\n *\n *   // Unlock with inline defaults (auto-discovered if doesn't exist)\n *   const handleFirstPurchase = async () => {\n *     await unlock('first-purchase', {\n *       name: 'First Purchase',\n *       description: 'Made your first purchase',\n *       points: 100,\n *       tier: 'bronze',\n *     })\n *   }\n *\n *   // Increment progress with inline defaults\n *   const handleCollect = async () => {\n *     await incrementProgress('collector-100', 1, {\n *       name: 'Collector',\n *       description: 'Collect 100 items',\n *       type: 'incremental',\n *       target: 100,\n *     })\n *   }\n *\n *   return (\n *     <div>\n *       <h2>Achievements ({unlocked.length}/{achievements.length})</h2>\n *\n *       <h3>Unlocked</h3>\n *       {unlocked.map(a => (\n *         <AchievementCard key={a.achievementId} achievement={a} unlocked />\n *       ))}\n *\n *       <h3>In Progress</h3>\n *       {locked.filter(a => a.progress > 0).map(a => (\n *         <AchievementCard\n *           key={a.achievementId}\n *           achievement={a}\n *           progress={a.progress}\n *           target={a.target}\n *         />\n *       ))}\n *\n *       {recentUnlock && (\n *         <AchievementToast\n *           achievement={recentUnlock.achievement}\n *           onDismiss={dismissRecentUnlock}\n *         />\n *       )}\n *     </div>\n *   )\n * }\n * ```\n */\nexport function useAchievements(): UseAchievementsReturn {\n\tconst ctx = useEngagementContext()\n\tconst [recentUnlock, setRecentUnlock] = useState<AchievementUnlockEvent | null>(null)\n\n\t// React Query for achievements data\n\tconst achievementsQuery = useQuery({\n\t\tqueryKey: ['sylphx', ctx.appId, 'achievements'],\n\t\tqueryFn: () => ctx.getAchievements(),\n\t\tenabled: !!ctx.user,\n\t\tstaleTime: STALE_TIME_STABLE_MS, // 5 min - achievements don't change often\n\t})\n\n\tconst achievements = achievementsQuery.data ?? []\n\n\t// Computed values\n\tconst unlocked = useMemo(() => achievements.filter((a) => a.unlocked), [achievements])\n\tconst locked = useMemo(() => achievements.filter((a) => !a.unlocked), [achievements])\n\n\t// Get achievement by ID\n\tconst getAchievement = useCallback(\n\t\t(id: string): UserAchievement | null => {\n\t\t\treturn achievements.find((a) => a.achievementId === id) ?? null\n\t\t},\n\t\t[achievements],\n\t)\n\n\t// Unlock achievement (passes inline defaults for auto-discovery)\n\tconst unlock = useCallback(\n\t\tasync (\n\t\t\tachievementId: string,\n\t\t\tdefaults?: AchievementDefaults,\n\t\t): Promise<AchievementUnlockEvent> => {\n\t\t\tconst result = await ctx.unlockAchievement(achievementId, defaults)\n\t\t\tif (result.isNew) {\n\t\t\t\tsetRecentUnlock(result)\n\t\t\t}\n\t\t\t// Invalidate to get updated achievements list\n\t\t\tvoid ctx.queryClient.invalidateQueries({\n\t\t\t\tqueryKey: ['sylphx', ctx.appId, 'achievements'],\n\t\t\t})\n\t\t\treturn result\n\t\t},\n\t\t[ctx],\n\t)\n\n\t// Increment progress (passes inline defaults for auto-discovery)\n\tconst incrementProgress = useCallback(\n\t\tasync (\n\t\t\tachievementId: string,\n\t\t\tamount: number,\n\t\t\tdefaults?: AchievementDefaults,\n\t\t): Promise<UserAchievement> => {\n\t\t\tconst result = await ctx.incrementAchievementProgress(achievementId, amount, defaults)\n\t\t\t// Invalidate to get updated achievements list\n\t\t\tvoid ctx.queryClient.invalidateQueries({\n\t\t\t\tqueryKey: ['sylphx', ctx.appId, 'achievements'],\n\t\t\t})\n\t\t\treturn result\n\t\t},\n\t\t[ctx],\n\t)\n\n\t// Refresh via React Query invalidation\n\tconst refresh = useCallback(async () => {\n\t\tawait ctx.queryClient.invalidateQueries({\n\t\t\tqueryKey: ['sylphx', ctx.appId, 'achievements'],\n\t\t})\n\t}, [ctx])\n\n\t// Dismiss recent unlock\n\tconst dismissRecentUnlock = useCallback(() => {\n\t\tsetRecentUnlock(null)\n\t}, [])\n\n\treturn {\n\t\tachievements,\n\t\tisLoading: achievementsQuery.isLoading,\n\t\terror: achievementsQuery.error as Error | null,\n\t\tunlocked,\n\t\tlocked,\n\t\tgetAchievement,\n\t\tunlock,\n\t\tincrementProgress,\n\t\trefresh,\n\t\trecentUnlock,\n\t\tdismissRecentUnlock,\n\t}\n}\n\n// ============================================================================\n// Safe Versions (for SSR/prerendering)\n// ============================================================================\n\n// Type-safe stub functions for safe hooks when context is unavailable\n// These return sensible defaults instead of using unsafe type assertions\n\nconst noopAsyncVoid = async (): Promise<void> => {}\n\n/** Default streak state for stubs */\nconst defaultStreakState: StreakState = {\n\tstreakId: '',\n\tcurrent: 0,\n\tlongest: 0,\n\tlastActivityAt: null,\n\texpiresAt: null,\n\tcanRecover: false,\n\ttimeRemainingMs: null,\n\tuserTimezone: null,\n}\n\n/** Stub for recordActivity when no context */\nconst stubRecordActivity = async (): Promise<RecordActivityResult> => ({\n\tstreak: defaultStreakState,\n\textended: false,\n\tnewPersonalBest: false,\n\tpreviousValue: 0,\n})\n\n/** Stub for recover when no context */\nconst stubRecover = async (): Promise<{\n\tsuccess: boolean\n\tstreak: StreakState\n}> => ({\n\tsuccess: false,\n\tstreak: defaultStreakState,\n})\n\n/** Stub for submitScore when no context */\nconst stubSubmitScore = async (): Promise<SubmitScoreResult> => ({\n\taccepted: false,\n\trank: null,\n\tpreviousBest: null,\n\tnewPersonalBest: false,\n\trankChange: null,\n})\n\n/** Default user achievement for stubs */\nconst defaultUserAchievement: UserAchievement = {\n\tachievementId: '',\n\tunlocked: false,\n\tunlockedAt: null,\n\tprogress: 0,\n\ttarget: null,\n\tprogressPercent: 0,\n}\n\n/** Stub for achievement unlock when no context */\nconst stubUnlockAchievement = async (): Promise<AchievementUnlockEvent> => ({\n\tachievement: {\n\t\tid: '',\n\t\tname: '',\n\t\tdescription: '',\n\t\ttype: 'standard',\n\t\ttier: 'bronze',\n\t\tcategory: '',\n\t\ticon: '',\n\t\tcriteria: {},\n\t},\n\tuserAchievement: defaultUserAchievement,\n\tisNew: false,\n})\n\n/** Stub for achievement progress when no context */\nconst stubIncrementProgress = async (): Promise<UserAchievement> => defaultUserAchievement\n\n/** Safe return type for useStreak when outside provider */\nexport interface UseSafeStreakReturn {\n\tstate: StreakState | null\n\tisLoading: boolean\n\terror: Error | null\n\tcurrent: number\n\tlongest: number\n\tcanRecover: boolean\n\ttimeRemainingMs: number | null\n\tuserTimezone: string | null\n\trecordActivity: (metadata?: Record<string, unknown>) => Promise<RecordActivityResult>\n\trecover: () => Promise<{ success: boolean; streak: StreakState }>\n\trefresh: () => Promise<void>\n\tisConfigured: boolean\n}\n\n/**\n * SSR-safe version of useStreak\n *\n * Returns safe defaults when called outside SylphxProvider.\n * Use this in components that may render during static generation.\n */\nexport function useSafeStreak(streakId: string, options?: UseStreakOptions): UseSafeStreakReturn {\n\tconst ctx = useEngagementContextSafe()\n\tconst { defaults, userTimezone } = options ?? {}\n\n\t// Always call hooks unconditionally to satisfy the Rules of Hooks.\n\t// Query is disabled when ctx is null; callbacks short-circuit to stubs.\n\tconst streakQuery = useQuery({\n\t\tqueryKey: ['sylphx', ctx?.appId ?? '__noop__', 'streak', streakId, userTimezone],\n\t\tqueryFn: () => {\n\t\t\tif (!ctx) throw new Error('useSafeStreak called without provider')\n\t\t\treturn ctx.getStreak(streakId, defaults, userTimezone)\n\t\t},\n\t\tenabled: !!ctx && !!ctx.user,\n\t\tstaleTime: STALE_TIME_FREQUENT_MS,\n\t})\n\n\tconst recordActivity = useCallback(\n\t\tasync (metadata?: Record<string, unknown>): Promise<RecordActivityResult> => {\n\t\t\tif (!ctx) return stubRecordActivity()\n\t\t\tconst result = await ctx.recordStreakActivity(streakId, metadata, defaults, userTimezone)\n\t\t\tctx.queryClient.setQueryData(\n\t\t\t\t['sylphx', ctx.appId, 'streak', streakId, userTimezone],\n\t\t\t\tresult.streak,\n\t\t\t)\n\t\t\treturn result\n\t\t},\n\t\t[ctx, streakId, defaults, userTimezone],\n\t)\n\n\tconst recover = useCallback(async (): Promise<{\n\t\tsuccess: boolean\n\t\tstreak: StreakState\n\t}> => {\n\t\tif (!ctx) return stubRecover()\n\t\tconst result = await ctx.recoverStreak(streakId, userTimezone)\n\t\tif (result.success) {\n\t\t\tctx.queryClient.setQueryData(\n\t\t\t\t['sylphx', ctx.appId, 'streak', streakId, userTimezone],\n\t\t\t\tresult.streak,\n\t\t\t)\n\t\t}\n\t\treturn result\n\t}, [ctx, streakId, userTimezone])\n\n\tconst refresh = useCallback(async () => {\n\t\tif (!ctx) return\n\t\tawait ctx.queryClient.invalidateQueries({\n\t\t\tqueryKey: ['sylphx', ctx.appId, 'streak', streakId],\n\t\t})\n\t}, [ctx, streakId])\n\n\t// Return inert defaults when no provider (hooks above were called unconditionally).\n\tif (!ctx) {\n\t\treturn {\n\t\t\tstate: null,\n\t\t\tisLoading: false,\n\t\t\terror: null,\n\t\t\tcurrent: 0,\n\t\t\tlongest: 0,\n\t\t\tcanRecover: false,\n\t\t\ttimeRemainingMs: null,\n\t\t\tuserTimezone: null,\n\t\t\trecordActivity: stubRecordActivity,\n\t\t\trecover: stubRecover,\n\t\t\trefresh: noopAsyncVoid,\n\t\t\tisConfigured: false,\n\t\t}\n\t}\n\n\tconst state = streakQuery.data ?? null\n\treturn {\n\t\tstate,\n\t\tisLoading: streakQuery.isLoading,\n\t\terror: streakQuery.error as Error | null,\n\t\tcurrent: state?.current ?? 0,\n\t\tlongest: state?.longest ?? 0,\n\t\tcanRecover: state?.canRecover ?? false,\n\t\ttimeRemainingMs: state?.timeRemainingMs ?? null,\n\t\tuserTimezone: state?.userTimezone ?? null,\n\t\trecordActivity,\n\t\trecover,\n\t\trefresh,\n\t\tisConfigured: true,\n\t}\n}\n\n/** Safe return type for useLeaderboard when outside provider */\nexport interface UseSafeLeaderboardReturn {\n\tdata: LeaderboardResult | null\n\tisLoading: boolean\n\terror: Error | null\n\tentries: LeaderboardEntry[]\n\tcurrentUserEntry: LeaderboardEntry | null\n\ttotalParticipants: number\n\tsubmitScore: (value: number, metadata?: Record<string, unknown>) => Promise<SubmitScoreResult>\n\trefresh: () => Promise<void>\n\tisConfigured: boolean\n}\n\n/**\n * SSR-safe version of useLeaderboard\n *\n * Returns safe defaults when called outside SylphxProvider.\n * Use this in components that may render during static generation.\n */\nexport function useSafeLeaderboard(\n\tleaderboardId: string,\n\toptions?: LeaderboardQueryOptions,\n\tdefaults?: LeaderboardDefaults,\n): UseSafeLeaderboardReturn {\n\tconst ctx = useEngagementContextSafe()\n\tconst optionsKey = JSON.stringify(options ?? {})\n\n\t// Always call hooks unconditionally (Rules of Hooks).\n\tconst leaderboardQuery = useQuery({\n\t\tqueryKey: ['sylphx', ctx?.appId ?? '__noop__', 'leaderboard', leaderboardId, optionsKey],\n\t\tqueryFn: () => {\n\t\t\tif (!ctx) throw new Error('useSafeLeaderboard called without provider')\n\t\t\treturn ctx.getLeaderboard(leaderboardId, options)\n\t\t},\n\t\tenabled: !!ctx,\n\t\tstaleTime: STALE_TIME_MODERATE_MS,\n\t})\n\n\tconst submitScore = useCallback(\n\t\tasync (value: number, metadata?: Record<string, unknown>): Promise<SubmitScoreResult> => {\n\t\t\tif (!ctx) return stubSubmitScore()\n\t\t\tconst result = await ctx.submitScore(leaderboardId, value, metadata, defaults)\n\t\t\tvoid ctx.queryClient.invalidateQueries({\n\t\t\t\tqueryKey: ['sylphx', ctx.appId, 'leaderboard', leaderboardId],\n\t\t\t})\n\t\t\treturn result\n\t\t},\n\t\t[ctx, leaderboardId, defaults],\n\t)\n\n\tconst refresh = useCallback(async () => {\n\t\tif (!ctx) return\n\t\tawait ctx.queryClient.invalidateQueries({\n\t\t\tqueryKey: ['sylphx', ctx.appId, 'leaderboard', leaderboardId],\n\t\t})\n\t}, [ctx, leaderboardId])\n\n\tif (!ctx) {\n\t\treturn {\n\t\t\tdata: null,\n\t\t\tisLoading: false,\n\t\t\terror: null,\n\t\t\tentries: [],\n\t\t\tcurrentUserEntry: null,\n\t\t\ttotalParticipants: 0,\n\t\t\tsubmitScore: stubSubmitScore,\n\t\t\trefresh: noopAsyncVoid,\n\t\t\tisConfigured: false,\n\t\t}\n\t}\n\n\tconst data = leaderboardQuery.data ?? null\n\treturn {\n\t\tdata,\n\t\tisLoading: leaderboardQuery.isLoading,\n\t\terror: leaderboardQuery.error as Error | null,\n\t\tentries: data?.entries ?? [],\n\t\tcurrentUserEntry: data?.currentUserEntry ?? null,\n\t\ttotalParticipants: data?.totalParticipants ?? 0,\n\t\tsubmitScore,\n\t\trefresh,\n\t\tisConfigured: true,\n\t}\n}\n\n/** Safe return type for useAchievements when outside provider */\nexport interface UseSafeAchievementsReturn {\n\tachievements: UserAchievement[]\n\tisLoading: boolean\n\terror: Error | null\n\tunlocked: UserAchievement[]\n\tlocked: UserAchievement[]\n\tgetAchievement: (id: string) => UserAchievement | null\n\tunlock: (achievementId: string, defaults?: AchievementDefaults) => Promise<AchievementUnlockEvent>\n\tincrementProgress: (\n\t\tachievementId: string,\n\t\tamount: number,\n\t\tdefaults?: AchievementDefaults,\n\t) => Promise<UserAchievement>\n\trefresh: () => Promise<void>\n\trecentUnlock: AchievementUnlockEvent | null\n\tdismissRecentUnlock: () => void\n\tisConfigured: boolean\n}\n\n/**\n * SSR-safe version of useAchievements\n *\n * Returns safe defaults when called outside SylphxProvider.\n * Use this in components that may render during static generation.\n */\nexport function useSafeAchievements(): UseSafeAchievementsReturn {\n\tconst ctx = useEngagementContextSafe()\n\tconst [recentUnlock, setRecentUnlock] = useState<AchievementUnlockEvent | null>(null)\n\n\t// Always call hooks unconditionally (Rules of Hooks).\n\tconst achievementsQuery = useQuery({\n\t\tqueryKey: ['sylphx', ctx?.appId ?? '__noop__', 'achievements'],\n\t\tqueryFn: () => {\n\t\t\tif (!ctx) throw new Error('useSafeAchievements called without provider')\n\t\t\treturn ctx.getAchievements()\n\t\t},\n\t\tenabled: !!ctx && !!ctx.user,\n\t\tstaleTime: STALE_TIME_STABLE_MS,\n\t})\n\n\tconst achievements = achievementsQuery.data ?? []\n\n\tconst unlocked = useMemo(() => achievements.filter((a) => a.unlocked), [achievements])\n\tconst locked = useMemo(() => achievements.filter((a) => !a.unlocked), [achievements])\n\n\tconst getAchievement = useCallback(\n\t\t(id: string): UserAchievement | null => {\n\t\t\treturn achievements.find((a) => a.achievementId === id) ?? null\n\t\t},\n\t\t[achievements],\n\t)\n\n\tconst unlock = useCallback(\n\t\tasync (\n\t\t\tachievementId: string,\n\t\t\tdefaults?: AchievementDefaults,\n\t\t): Promise<AchievementUnlockEvent> => {\n\t\t\tif (!ctx) return stubUnlockAchievement()\n\t\t\tconst result = await ctx.unlockAchievement(achievementId, defaults)\n\t\t\tif (result.isNew) {\n\t\t\t\tsetRecentUnlock(result)\n\t\t\t}\n\t\t\tvoid ctx.queryClient.invalidateQueries({\n\t\t\t\tqueryKey: ['sylphx', ctx.appId, 'achievements'],\n\t\t\t})\n\t\t\treturn result\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst incrementProgress = useCallback(\n\t\tasync (\n\t\t\tachievementId: string,\n\t\t\tamount: number,\n\t\t\tdefaults?: AchievementDefaults,\n\t\t): Promise<UserAchievement> => {\n\t\t\tif (!ctx) return stubIncrementProgress()\n\t\t\tconst result = await ctx.incrementAchievementProgress(achievementId, amount, defaults)\n\t\t\tvoid ctx.queryClient.invalidateQueries({\n\t\t\t\tqueryKey: ['sylphx', ctx.appId, 'achievements'],\n\t\t\t})\n\t\t\treturn result\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst refresh = useCallback(async () => {\n\t\tif (!ctx) return\n\t\tawait ctx.queryClient.invalidateQueries({\n\t\t\tqueryKey: ['sylphx', ctx.appId, 'achievements'],\n\t\t})\n\t}, [ctx])\n\n\tconst dismissRecentUnlock = useCallback(() => {\n\t\tsetRecentUnlock(null)\n\t}, [])\n\n\tif (!ctx) {\n\t\treturn {\n\t\t\tachievements: [],\n\t\t\tisLoading: false,\n\t\t\terror: null,\n\t\t\tunlocked: [],\n\t\t\tlocked: [],\n\t\t\tgetAchievement: () => null,\n\t\t\tunlock: stubUnlockAchievement,\n\t\t\tincrementProgress: stubIncrementProgress,\n\t\t\trefresh: noopAsyncVoid,\n\t\t\trecentUnlock: null,\n\t\t\tdismissRecentUnlock: () => {},\n\t\t\tisConfigured: false,\n\t\t}\n\t}\n\n\treturn {\n\t\tachievements,\n\t\tisLoading: achievementsQuery.isLoading,\n\t\terror: achievementsQuery.error as Error | null,\n\t\tunlocked,\n\t\tlocked,\n\t\tgetAchievement,\n\t\tunlock,\n\t\tincrementProgress,\n\t\trefresh,\n\t\trecentUnlock,\n\t\tdismissRecentUnlock,\n\t\tisConfigured: true,\n\t}\n}\n","/**\n * Feature Flag Hooks (React Query Version)\n *\n * Simple polling-based feature flag hooks using React Query.\n * Good for basic use cases without SSE streaming requirements.\n *\n * ## When to Use This vs SOTA Flags\n *\n * USE THIS (feature-flag-hooks.tsx):\n * - Simple flag checks without complex targeting\n * - Apps that prefer polling over streaming\n * - When React Query is already your data layer\n *\n * USE SOTA FLAGS (hooks/use-flags.tsx):\n * - Real-time flag updates via SSE streaming\n * - Complex targeting rules and segments\n * - A/B testing with ExperimentManager\n * - Local evaluation with consistent bucketing\n *\n * @see hooks/use-flags.tsx for SOTA implementation\n *\n * ## React Query Integration\n *\n * All data fetching uses React Query for:\n * - Automatic caching (configurable staleTime)\n * - Deduplication of concurrent requests\n * - Background refetching via refetchInterval (no manual setInterval)\n */\n\n'use client'\n\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport {\n\tcreateContext,\n\ttype ReactNode,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseMemo,\n\tuseState,\n} from 'react'\nimport {\n\tFLAGS_CACHE_KEY,\n\tFLAGS_CACHE_TIMESTAMP_KEY,\n\tFLAGS_CACHE_TTL_MS,\n\tSTALE_TIME_FREQUENT_MS,\n\tSTALE_TIME_STABLE_MS,\n} from '../constants'\nimport type { EvaluationReason } from '../types'\nimport type { FeatureFlagDetailResult } from './types'\n\n// ============================================\n// Types\n// ============================================\n\nexport type FlagValue = boolean | string | number | Record<string, unknown>\n\nexport interface FeatureFlag {\n\tkey: string\n\tvalue: FlagValue\n\tenabled: boolean\n\tvariant?: string\n\tpayload?: Record<string, unknown>\n}\n\nexport interface FlagOverrides {\n\t[key: string]: FlagValue\n}\n\nexport interface FeatureFlagContextValue {\n\t/** Get a flag value */\n\tgetFlag: (key: string) => FlagValue | undefined\n\t/** Check if a boolean flag is enabled */\n\tisEnabled: (key: string) => boolean\n\t/** Get flag variant (for A/B tests) */\n\tgetVariant: (key: string) => string | undefined\n\t/** All loaded flags */\n\tflags: Map<string, FeatureFlag>\n\t/** Whether flags are loading */\n\tisLoading: boolean\n\t/** Error loading flags */\n\terror: Error | null\n\t/** Refresh flags from server */\n\trefresh: () => Promise<void>\n\t/** Local overrides for testing */\n\toverrides: FlagOverrides\n\t/** Set a local override */\n\tsetOverride: (key: string, value: FlagValue) => void\n\t/** Clear all overrides */\n\tclearOverrides: () => void\n}\n\n// ============================================\n// Context\n// ============================================\n\n/** Feature Flag Context - internal use for FlagDevTools */\nexport const FeatureFlagContext = createContext<FeatureFlagContextValue | null>(null)\n\nexport interface FeatureFlagProviderProps {\n\tchildren: ReactNode\n\t/** API endpoint to fetch flags */\n\tendpoint?: string\n\t/** Initial flags (for SSR) */\n\tinitialFlags?: FeatureFlag[]\n\t/** User context for flag evaluation */\n\tuserContext?: {\n\t\tuserId?: string\n\t\temail?: string\n\t\tattributes?: Record<string, unknown>\n\t}\n\t/** Refresh interval in ms (0 to disable) - uses React Query refetchInterval */\n\trefreshInterval?: number\n\t/** Enable localStorage caching */\n\tenableCache?: boolean\n}\n\n/** Cache TTL from constants (5 minutes - LaunchDarkly pattern) */\nconst CACHE_TTL_MS = FLAGS_CACHE_TTL_MS\n\n/**\n * Feature Flag Provider\n *\n * Uses React Query for data fetching with refetchInterval for automatic refreshes.\n *\n * @example\n * ```tsx\n * <FeatureFlagProvider\n *   endpoint=\"/api/flags\"\n *   userContext={{ userId: user.id }}\n *   refreshInterval={60000} // Refresh every minute via React Query\n * >\n *   <App />\n * </FeatureFlagProvider>\n * ```\n */\nexport function FeatureFlagProvider({\n\tchildren,\n\tendpoint = '/api/flags',\n\tinitialFlags = [],\n\tuserContext,\n\trefreshInterval = 0,\n\tenableCache = true,\n}: FeatureFlagProviderProps) {\n\tconst queryClient = useQueryClient()\n\n\t// Hydration-safe: start with server-safe defaults, populate from localStorage in useEffect.\n\t// Both server and client initial render produce the same value — no mismatch.\n\tconst [cachedInitialFlags, setCachedInitialFlags] = useState<FeatureFlag[]>(initialFlags)\n\n\tuseEffect(() => {\n\t\tif (!enableCache) return\n\t\ttry {\n\t\t\tconst cached = localStorage.getItem(FLAGS_CACHE_KEY)\n\t\t\tconst timestamp = localStorage.getItem(FLAGS_CACHE_TIMESTAMP_KEY)\n\n\t\t\tif (cached && timestamp && !initialFlags.length) {\n\t\t\t\tconst cacheAge = Date.now() - Number.parseInt(timestamp, 10)\n\t\t\t\tif (cacheAge < CACHE_TTL_MS) {\n\t\t\t\t\tsetCachedInitialFlags(JSON.parse(cached) as FeatureFlag[])\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t// Cache expired — clear it\n\t\t\t\tlocalStorage.removeItem(FLAGS_CACHE_KEY)\n\t\t\t\tlocalStorage.removeItem(FLAGS_CACHE_TIMESTAMP_KEY)\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore cache errors\n\t\t}\n\t}, [enableCache, initialFlags])\n\n\t// Overrides state — hydration-safe with localStorage sync in useEffect\n\tconst [overrides, setOverrides] = useState<FlagOverrides>({})\n\n\tuseEffect(() => {\n\t\ttry {\n\t\t\tconst stored = localStorage.getItem(`${FLAGS_CACHE_KEY}_overrides`)\n\t\t\tif (stored) {\n\t\t\t\tsetOverrides(JSON.parse(stored))\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore cache errors\n\t\t}\n\t}, [])\n\n\t// React Query for flag fetching with automatic refetch\n\tconst flagsQuery = useQuery({\n\t\tqueryKey: ['sylphx', 'feature-flags', endpoint, userContext?.userId, userContext?.email],\n\t\tqueryFn: async () => {\n\t\t\tconst response = await fetch(endpoint, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\t\tbody: JSON.stringify({ context: userContext }),\n\t\t\t})\n\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(`Failed to fetch flags: ${response.status}`)\n\t\t\t}\n\n\t\t\tconst data = await response.json()\n\t\t\tconst flagList = data.flags as FeatureFlag[]\n\n\t\t\t// Cache flags to localStorage with timestamp for TTL validation\n\t\t\tif (enableCache && typeof window !== 'undefined') {\n\t\t\t\tlocalStorage.setItem(FLAGS_CACHE_KEY, JSON.stringify(flagList))\n\t\t\t\tlocalStorage.setItem(FLAGS_CACHE_TIMESTAMP_KEY, Date.now().toString())\n\t\t\t}\n\n\t\t\treturn flagList\n\t\t},\n\t\tinitialData: cachedInitialFlags.length > 0 ? cachedInitialFlags : undefined,\n\t\tstaleTime: STALE_TIME_FREQUENT_MS, // 1 minute - flags change occasionally\n\t\trefetchInterval: refreshInterval > 0 ? refreshInterval : undefined,\n\t\tenabled: cachedInitialFlags.length === 0 || refreshInterval > 0,\n\t})\n\n\t// Convert flag array to Map for fast lookups\n\tconst flags = useMemo(() => {\n\t\tconst map = new Map<string, FeatureFlag>()\n\t\tconst flagList = flagsQuery.data ?? cachedInitialFlags\n\t\tflagList.forEach((flag) => {\n\t\t\tmap.set(flag.key, flag)\n\t\t})\n\t\treturn map\n\t}, [flagsQuery.data, cachedInitialFlags])\n\n\t// Get flag value (with override support)\n\tconst getFlag = useCallback(\n\t\t(key: string): FlagValue | undefined => {\n\t\t\tif (key in overrides) {\n\t\t\t\treturn overrides[key]\n\t\t\t}\n\t\t\tconst flag = flags.get(key)\n\t\t\treturn flag?.value\n\t\t},\n\t\t[flags, overrides],\n\t)\n\n\t// Check if boolean flag is enabled\n\tconst isEnabled = useCallback(\n\t\t(key: string): boolean => {\n\t\t\tif (key in overrides) {\n\t\t\t\treturn Boolean(overrides[key])\n\t\t\t}\n\t\t\tconst flag = flags.get(key)\n\t\t\treturn flag?.enabled ?? false\n\t\t},\n\t\t[flags, overrides],\n\t)\n\n\t// Get variant for A/B tests\n\tconst getVariant = useCallback(\n\t\t(key: string): string | undefined => {\n\t\t\tconst flag = flags.get(key)\n\t\t\treturn flag?.variant\n\t\t},\n\t\t[flags],\n\t)\n\n\t// Override management\n\tconst setOverride = useCallback((key: string, value: FlagValue) => {\n\t\tsetOverrides((prev) => {\n\t\t\tconst next = { ...prev, [key]: value }\n\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\tlocalStorage.setItem(`${FLAGS_CACHE_KEY}_overrides`, JSON.stringify(next))\n\t\t\t}\n\t\t\treturn next\n\t\t})\n\t}, [])\n\n\tconst clearOverrides = useCallback(() => {\n\t\tsetOverrides({})\n\t\tif (typeof window !== 'undefined') {\n\t\t\tlocalStorage.removeItem(`${FLAGS_CACHE_KEY}_overrides`)\n\t\t}\n\t}, [])\n\n\t// Refresh via React Query invalidation\n\tconst refresh = useCallback(async () => {\n\t\tawait queryClient.invalidateQueries({\n\t\t\tqueryKey: ['sylphx', 'feature-flags', endpoint],\n\t\t})\n\t}, [queryClient, endpoint])\n\n\tconst value: FeatureFlagContextValue = {\n\t\tgetFlag,\n\t\tisEnabled,\n\t\tgetVariant,\n\t\tflags,\n\t\tisLoading: flagsQuery.isLoading,\n\t\terror: flagsQuery.error as Error | null,\n\t\trefresh,\n\t\toverrides,\n\t\tsetOverride,\n\t\tclearOverrides,\n\t}\n\n\treturn <FeatureFlagContext.Provider value={value}>{children}</FeatureFlagContext.Provider>\n}\n\n// ============================================\n// useFeatureFlag\n// ============================================\n\nexport interface UseFeatureFlagOptions<T extends FlagValue = boolean> {\n\t/** Default value if flag not found */\n\tdefaultValue?: T\n\t/** Track flag exposure for analytics */\n\ttrackExposure?: boolean\n}\n\nexport interface UseFeatureFlagReturn<T extends FlagValue = boolean> {\n\t/** Flag value */\n\tvalue: T\n\t/** Whether flag is enabled (for boolean flags) */\n\tisEnabled: boolean\n\t/** Flag variant (for A/B tests) */\n\tvariant: string | undefined\n\t/** Whether flags are loading */\n\tisLoading: boolean\n\t/** Error loading flags */\n\terror: Error | null\n}\n\n/**\n * Hook to get a feature flag value\n *\n * @example\n * ```tsx\n * function NewFeature() {\n *   const { isEnabled, isLoading } = useFeatureFlag('new-dashboard')\n *\n *   if (isLoading) return <Skeleton />\n *\n *   if (!isEnabled) {\n *     return <OldDashboard />\n *   }\n *\n *   return <NewDashboard />\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With A/B testing\n * function PricingPage() {\n *   const { variant, isLoading } = useFeatureFlag('pricing-experiment')\n *\n *   if (isLoading) return <Skeleton />\n *\n *   switch (variant) {\n *     case 'control': return <OriginalPricing />\n *     case 'variant-a': return <NewPricingA />\n *     case 'variant-b': return <NewPricingB />\n *     default: return <OriginalPricing />\n *   }\n * }\n * ```\n */\nexport function useFeatureFlag<T extends FlagValue = boolean>(\n\tkey: string,\n\toptions: UseFeatureFlagOptions<T> = {},\n): UseFeatureFlagReturn<T> {\n\tconst context = useContext(FeatureFlagContext)\n\n\tif (!context) {\n\t\t// Return default if no provider (for testing/SSR)\n\t\treturn {\n\t\t\tvalue: (options.defaultValue ?? false) as T,\n\t\t\tisEnabled: Boolean(options.defaultValue),\n\t\t\tvariant: undefined,\n\t\t\tisLoading: false,\n\t\t\terror: null,\n\t\t}\n\t}\n\n\tconst { getFlag, isEnabled, getVariant, isLoading, error } = context\n\n\tconst flagValue = getFlag(key)\n\tconst value = (flagValue ?? options.defaultValue ?? false) as T\n\tconst enabled = isEnabled(key)\n\tconst variant = getVariant(key)\n\n\treturn {\n\t\tvalue,\n\t\tisEnabled: enabled,\n\t\tvariant,\n\t\tisLoading,\n\t\terror,\n\t}\n}\n\n// ============================================\n// useFeatureFlags (bulk)\n// ============================================\n\n/**\n * Hook to get multiple feature flags at once\n *\n * @example\n * ```tsx\n * function App() {\n *   const flags = useFeatureFlags(['new-ui', 'dark-mode', 'beta-features'])\n *\n *   return (\n *     <div className={flags['dark-mode'] ? 'dark' : ''}>\n *       {flags['new-ui'] ? <NewUI /> : <OldUI />}\n *     </div>\n *   )\n * }\n * ```\n */\nexport function useFeatureFlags(keys: string[]): Record<string, boolean> {\n\tconst context = useContext(FeatureFlagContext)\n\n\tif (!context) {\n\t\treturn keys.reduce(\n\t\t\t(acc, key) => {\n\t\t\t\tacc[key] = false\n\t\t\t\treturn acc\n\t\t\t},\n\t\t\t{} as Record<string, boolean>,\n\t\t)\n\t}\n\n\treturn keys.reduce(\n\t\t(acc, key) => {\n\t\t\tacc[key] = context.isEnabled(key)\n\t\t\treturn acc\n\t\t},\n\t\t{} as Record<string, boolean>,\n\t)\n}\n\n// ============================================\n// useFlagOverrides (for dev/testing)\n// ============================================\n\n/**\n * Hook to manage flag overrides (for development/testing)\n *\n * @example\n * ```tsx\n * function DevTools() {\n *   const { overrides, setOverride, clearOverrides } = useFlagOverrides()\n *\n *   return (\n *     <div>\n *       <h3>Flag Overrides</h3>\n *       <button onClick={() => setOverride('new-feature', true)}>\n *         Enable new-feature\n *       </button>\n *       <button onClick={clearOverrides}>Clear All</button>\n *     </div>\n *   )\n * }\n * ```\n */\nexport function useFlagOverrides() {\n\tconst context = useContext(FeatureFlagContext)\n\n\tif (!context) {\n\t\treturn {\n\t\t\toverrides: {} as FlagOverrides,\n\t\t\tsetOverride: () => {},\n\t\t\tclearOverrides: () => {},\n\t\t}\n\t}\n\n\treturn {\n\t\toverrides: context.overrides,\n\t\tsetOverride: context.setOverride,\n\t\tclearOverrides: context.clearOverrides,\n\t}\n}\n\n// ============================================\n// useFeatureFlagWithDetail (detailed evaluation)\n// ============================================\n\ninterface UseFeatureFlagDetailOptions {\n\t/** Default value if flag not found */\n\tdefaultValue?: boolean\n\t/** User context for targeting rules */\n\tuserContext?: {\n\t\tisPremium?: boolean\n\t\tisAdmin?: boolean\n\t}\n}\n\ninterface UseFeatureFlagDetailReturn {\n\t/** Flag value */\n\tenabled: boolean\n\t/** Whether flags are loading */\n\tisLoading: boolean\n\t/** Error loading flags */\n\terror: Error | null\n\t/** Full evaluation detail (null while loading) */\n\tdetail: FeatureFlagDetailResult | null\n\t/** Evaluation reason (null while loading) */\n\treason: EvaluationReason | null\n\t/** Rollout bucket for this user (for debugging) */\n\trolloutBucket: number | null\n}\n\n/**\n * Hook to get a feature flag with detailed evaluation information\n *\n * LaunchDarkly-style detailed evaluation with full reason metadata.\n * Useful for debugging, analytics, and understanding rollout behavior.\n *\n * Uses React Query for caching and automatic data management.\n *\n * @example\n * ```tsx\n * function DebugPanel() {\n *   const { enabled, reason, rolloutBucket, detail } = useFeatureFlagWithDetail('new-feature')\n *\n *   return (\n *     <div>\n *       <p>Enabled: {enabled ? 'Yes' : 'No'}</p>\n *       <p>Reason: {reason?.kind} - {reason?.description}</p>\n *       {rolloutBucket !== null && (\n *         <p>Rollout bucket: {rolloutBucket}/100</p>\n *       )}\n *     </div>\n *   )\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With user context for targeting\n * function PremiumFeature() {\n *   const { enabled, reason } = useFeatureFlagWithDetail('premium-feature', {\n *     userContext: { isPremium: true }\n *   })\n *\n *   if (!enabled) {\n *     console.log(`Feature disabled: ${reason?.description}`)\n *     return <UpgradePrompt />\n *   }\n *\n *   return <PremiumContent />\n * }\n * ```\n */\nfunction _useFeatureFlagWithDetail(\n\tkey: string,\n\toptions: UseFeatureFlagDetailOptions = {},\n): UseFeatureFlagDetailReturn {\n\t// React Query for flag detail fetching\n\tconst detailQuery = useQuery({\n\t\tqueryKey: ['sylphx', 'feature-flag-detail', key, options.userContext],\n\t\tqueryFn: async () => {\n\t\t\tconst response = await fetch(`/api/flags/${encodeURIComponent(key)}/detail`, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\t\tbody: JSON.stringify({ userContext: options.userContext }),\n\t\t\t})\n\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(`Failed to fetch flag detail: ${response.status}`)\n\t\t\t}\n\n\t\t\treturn response.json() as Promise<FeatureFlagDetailResult>\n\t\t},\n\t\tstaleTime: STALE_TIME_STABLE_MS, // 5 min - flag details don't change frequently\n\t})\n\n\tconst detail = detailQuery.data ?? null\n\tconst enabled = detail?.enabled ?? options.defaultValue ?? false\n\tconst reason = detail?.reason ?? null\n\tconst rolloutBucket =\n\t\tdetail?.reason && typeof detail.reason === 'object' && 'rolloutBucket' in detail.reason\n\t\t\t? ((detail.reason as { rolloutBucket?: number }).rolloutBucket ?? null)\n\t\t\t: null\n\n\treturn {\n\t\tenabled,\n\t\tisLoading: detailQuery.isLoading,\n\t\terror: detailQuery.error as Error | null,\n\t\tdetail,\n\t\treason,\n\t\trolloutBucket,\n\t}\n}\n\n// Re-export types for convenience\n","/**\n * useForgotPasswordForm Hook\n *\n * Headless hook for forgot password form logic.\n *\n * @example\n * ```tsx\n * function MyForgotPassword() {\n *   const forgot = useForgotPasswordForm({\n *     redirectTo: '/reset-password',\n *   });\n *\n *   if (forgot.success) return <SuccessMessage email={forgot.form.email} />;\n *\n *   return (\n *     <form onSubmit={forgot.handleSubmit}>\n *       <input value={forgot.form.email} onChange={e => forgot.setEmail(e.target.value)} />\n *       <button disabled={forgot.isLoading}>Send reset link</button>\n *     </form>\n *   );\n * }\n * ```\n */\n\n'use client'\n\nimport { useCallback, useContext, useState } from 'react'\nimport { SdkAuthContext, type SdkAuthContextValue } from '../services-context'\n\n// ============================================\n// Types\n// ============================================\n\nexport interface ForgotPasswordFormState {\n\temail: string\n}\n\nexport interface UseForgotPasswordFormOptions {\n\t/** URL to redirect to in reset email */\n\tredirectTo?: string\n\t/**\n\t * Custom submit handler. If provided, replaces context-based auth.\n\t * Should NOT throw on success (even for non-existent emails - security).\n\t */\n\tsubmitHandler?: (email: string, redirectTo: string) => Promise<void>\n\t/** Callback on success */\n\tonSuccess?: () => void\n\t/** Callback on error */\n\tonError?: (error: string) => void\n}\n\nexport interface UseForgotPasswordFormReturn {\n\t// Form state\n\tform: ForgotPasswordFormState\n\tsetEmail: (email: string) => void\n\tresetForm: () => void\n\n\t// UI state\n\tisLoading: boolean\n\terror: string | null\n\tsuccess: boolean\n\tclearError: () => void\n\n\t// Handlers\n\thandleSubmit: (e?: React.FormEvent) => Promise<void>\n\n\t// Config\n\tredirectTo: string\n}\n\nfunction resolveRedirectUrl(redirectTo: string): string {\n\tif (/^https?:\\/\\//iu.test(redirectTo)) return redirectTo\n\tif (typeof window !== 'undefined' && redirectTo.startsWith('/')) {\n\t\treturn new URL(redirectTo, window.location.origin).toString()\n\t}\n\treturn redirectTo\n}\n\n// ============================================\n// Hook Implementation\n// ============================================\n\nexport function useForgotPasswordForm(\n\toptions: UseForgotPasswordFormOptions = {},\n): UseForgotPasswordFormReturn {\n\tconst { redirectTo = '/reset-password', submitHandler, onSuccess, onError } = options\n\n\t// Get auth context (may be null if outside provider)\n\tconst authContext = useContext(SdkAuthContext) as SdkAuthContextValue | null\n\n\t// Form state\n\tconst [form, setForm] = useState<ForgotPasswordFormState>({ email: '' })\n\n\t// UI state\n\tconst [isLoading, setIsLoading] = useState(false)\n\tconst [error, setError] = useState<string | null>(null)\n\tconst [success, setSuccess] = useState(false)\n\n\t// Form setters\n\tconst setEmail = useCallback((email: string) => {\n\t\tsetForm({ email })\n\t\tsetError(null)\n\t}, [])\n\n\tconst resetForm = useCallback(() => {\n\t\tsetForm({ email: '' })\n\t\tsetError(null)\n\t\tsetSuccess(false)\n\t}, [])\n\n\tconst clearError = useCallback(() => {\n\t\tsetError(null)\n\t}, [])\n\n\t// Submit handler\n\tconst handleSubmit = useCallback(\n\t\tasync (e?: React.FormEvent) => {\n\t\t\te?.preventDefault()\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tif (submitHandler) {\n\t\t\t\t\tawait submitHandler(form.email, redirectTo)\n\t\t\t\t} else {\n\t\t\t\t\t// Use auth context (SDK mode)\n\t\t\t\t\tif (!authContext) {\n\t\t\t\t\t\tsetError('SDK not configured. Please wrap your app with SylphxProvider.')\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\tawait authContext.forgotPassword(form.email, {\n\t\t\t\t\t\tredirectUrl: resolveRedirectUrl(redirectTo),\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tsetSuccess(true)\n\t\t\t\tonSuccess?.()\n\t\t\t} catch (err) {\n\t\t\t\t// Still show success to prevent email enumeration\n\t\t\t\t// But call onError for logging purposes\n\t\t\t\tsetSuccess(true)\n\t\t\t\tconst message = err instanceof Error ? err.message : 'Request failed'\n\t\t\t\tonError?.(message)\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[form.email, redirectTo, submitHandler, authContext, onSuccess, onError],\n\t)\n\n\treturn {\n\t\t// Form state\n\t\tform,\n\t\tsetEmail,\n\t\tresetForm,\n\n\t\t// UI state\n\t\tisLoading,\n\t\terror,\n\t\tsuccess,\n\t\tclearError,\n\n\t\t// Handlers\n\t\thandleSubmit,\n\n\t\t// Config\n\t\tredirectTo,\n\t}\n}\n","/**\n * useResetPasswordForm Hook\n *\n * Headless hook for reset password form logic.\n *\n * @example\n * ```tsx\n * function MyResetPassword({ token }: { token: string }) {\n *   const reset = useResetPasswordForm({\n *     token,\n *     afterResetUrl: '/login',\n *   });\n *\n *   if (reset.success) return <SuccessMessage />;\n *\n *   return (\n *     <form onSubmit={reset.handleSubmit}>\n *       <input\n *         type={reset.showPassword ? 'text' : 'password'}\n *         value={reset.form.password}\n *         onChange={e => reset.setPassword(e.target.value)}\n *       />\n *       <button onClick={reset.toggleShowPassword}>Show</button>\n *       {!reset.passwordsMatch && <p>Passwords don't match</p>}\n *       <button disabled={reset.isLoading || !reset.isValid}>Reset</button>\n *     </form>\n *   );\n * }\n * ```\n */\n\n'use client'\n\nimport { useCallback, useContext, useMemo, useState } from 'react'\nimport { MIN_PASSWORD_LENGTH, UI_COPY_FEEDBACK_MS } from '../../constants'\nimport { SdkAuthContext, type SdkAuthContextValue } from '../services-context'\n\n// ============================================\n// Types\n// ============================================\n\nexport interface ResetPasswordFormState {\n\tpassword: string\n\tconfirmPassword: string\n}\n\nexport interface UseResetPasswordFormOptions {\n\t/** Reset token from URL */\n\ttoken: string\n\t/** Minimum password length */\n\tminPasswordLength?: number\n\t/** URL to redirect after reset */\n\tafterResetUrl?: string\n\t/**\n\t * Custom submit handler. If provided, replaces context-based auth.\n\t * Throw error to indicate failure.\n\t */\n\tsubmitHandler?: (token: string, newPassword: string) => Promise<void>\n\t/** Callback on success */\n\tonSuccess?: () => void\n\t/** Callback on error */\n\tonError?: (error: string) => void\n}\n\nexport interface UseResetPasswordFormReturn {\n\t// Form state\n\tform: ResetPasswordFormState\n\tsetPassword: (password: string) => void\n\tsetConfirmPassword: (confirmPassword: string) => void\n\tresetForm: () => void\n\n\t// Password visibility\n\tshowPassword: boolean\n\ttoggleShowPassword: () => void\n\n\t// Validation\n\tpasswordValid: boolean\n\tpasswordsMatch: boolean\n\tisValid: boolean\n\tminPasswordLength: number\n\n\t// UI state\n\tisLoading: boolean\n\terror: string | null\n\tsuccess: boolean\n\tclearError: () => void\n\n\t// Handlers\n\thandleSubmit: (e?: React.FormEvent) => Promise<void>\n\n\t// Config\n\ttoken: string\n\tafterResetUrl: string\n}\n\n// ============================================\n// Hook Implementation\n// ============================================\n\nexport function useResetPasswordForm(\n\toptions: UseResetPasswordFormOptions,\n): UseResetPasswordFormReturn {\n\tconst {\n\t\ttoken,\n\t\tminPasswordLength = MIN_PASSWORD_LENGTH, // NIST SP 800-63B (2023) recommends 12+ chars\n\t\tafterResetUrl = '/login',\n\t\tsubmitHandler,\n\t\tonSuccess,\n\t\tonError,\n\t} = options\n\n\t// Get auth context (may be null if outside provider)\n\tconst authContext = useContext(SdkAuthContext) as SdkAuthContextValue | null\n\n\t// Form state\n\tconst [form, setForm] = useState<ResetPasswordFormState>({\n\t\tpassword: '',\n\t\tconfirmPassword: '',\n\t})\n\n\t// UI state\n\tconst [showPassword, setShowPassword] = useState(false)\n\tconst [isLoading, setIsLoading] = useState(false)\n\tconst [error, setError] = useState<string | null>(null)\n\tconst [success, setSuccess] = useState(false)\n\n\t// Validation\n\tconst passwordValid = useMemo(\n\t\t() => form.password.length >= minPasswordLength,\n\t\t[form.password, minPasswordLength],\n\t)\n\tconst passwordsMatch = useMemo(\n\t\t() => form.password === form.confirmPassword && form.confirmPassword.length > 0,\n\t\t[form.password, form.confirmPassword],\n\t)\n\tconst isValid = useMemo(() => passwordValid && passwordsMatch, [passwordValid, passwordsMatch])\n\n\t// Form setters\n\tconst setPassword = useCallback((password: string) => {\n\t\tsetForm((prev) => ({ ...prev, password }))\n\t\tsetError(null)\n\t}, [])\n\n\tconst setConfirmPassword = useCallback((confirmPassword: string) => {\n\t\tsetForm((prev) => ({ ...prev, confirmPassword }))\n\t\tsetError(null)\n\t}, [])\n\n\tconst resetForm = useCallback(() => {\n\t\tsetForm({ password: '', confirmPassword: '' })\n\t\tsetError(null)\n\t\tsetSuccess(false)\n\t}, [])\n\n\tconst clearError = useCallback(() => {\n\t\tsetError(null)\n\t}, [])\n\n\tconst toggleShowPassword = useCallback(() => {\n\t\tsetShowPassword((prev) => !prev)\n\t}, [])\n\n\t// Submit handler\n\tconst handleSubmit = useCallback(\n\t\tasync (e?: React.FormEvent) => {\n\t\t\te?.preventDefault()\n\n\t\t\t// Validate\n\t\t\tif (!passwordsMatch) {\n\t\t\t\tsetError('Passwords do not match')\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (!passwordValid) {\n\t\t\t\tsetError(`Password must be at least ${minPasswordLength} characters`)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tif (submitHandler) {\n\t\t\t\t\tawait submitHandler(token, form.password)\n\t\t\t\t} else {\n\t\t\t\t\t// Use auth context (SDK mode)\n\t\t\t\t\tif (!authContext) {\n\t\t\t\t\t\tsetError('SDK not configured. Please wrap your app with SylphxProvider.')\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\tawait authContext.resetPassword(token, form.password)\n\t\t\t\t}\n\n\t\t\t\tsetSuccess(true)\n\t\t\t\tonSuccess?.()\n\n\t\t\t\t// Redirect after short delay\n\t\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\twindow.location.href = afterResetUrl\n\t\t\t\t\t}, UI_COPY_FEEDBACK_MS)\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : 'Failed to reset password'\n\t\t\t\tsetError(message)\n\t\t\t\tonError?.(message)\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\tform,\n\t\t\ttoken,\n\t\t\tpasswordValid,\n\t\t\tpasswordsMatch,\n\t\t\tminPasswordLength,\n\t\t\tsubmitHandler,\n\t\t\tauthContext,\n\t\t\tafterResetUrl,\n\t\t\tonSuccess,\n\t\t\tonError,\n\t\t],\n\t)\n\n\treturn {\n\t\t// Form state\n\t\tform,\n\t\tsetPassword,\n\t\tsetConfirmPassword,\n\t\tresetForm,\n\n\t\t// Password visibility\n\t\tshowPassword,\n\t\ttoggleShowPassword,\n\n\t\t// Validation\n\t\tpasswordValid,\n\t\tpasswordsMatch,\n\t\tisValid,\n\t\tminPasswordLength,\n\n\t\t// UI state\n\t\tisLoading,\n\t\terror,\n\t\tsuccess,\n\t\tclearError,\n\n\t\t// Handlers\n\t\thandleSubmit,\n\n\t\t// Config\n\t\ttoken,\n\t\tafterResetUrl,\n\t}\n}\n","/**\n * useTaskRun — Poll a background task run until it reaches a terminal state.\n *\n * Polls `GET /api/v1/tasks/:runId` on a configurable interval while the run\n * is active (`pending` | `running` | `waiting`), then stops automatically\n * when the run completes, fails, or is cancelled.\n *\n * @example\n * ```tsx\n * function OrderStatus({ runId }: { runId: string }) {\n *   const { run, isRunning, isComplete, isFailed, error } = useTaskRun(runId)\n *\n *   if (isRunning) return <Spinner />\n *   if (isFailed)  return <Error message={error?.message} />\n *   if (isComplete) return <Success result={run?.result} />\n *   return null\n * }\n * ```\n */\n\n'use client'\n\nimport { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'\nimport { DEFAULT_SDK_API_HOST, SDK_API_PATH, SDK_PLATFORM, SDK_VERSION } from '../../constants'\nimport { RateLimitError, SylphxError, type SylphxErrorCode } from '../../errors'\nimport type { TaskRunStatus } from '../../lib/tasks/types'\nimport { PlatformContext } from '../platform-context'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface UseTaskRunOptions {\n\t/**\n\t * Polling interval in ms while the run is active.\n\t * Default: 2 000 (2 s).\n\t * Set to 0 to disable automatic polling (use `refetch` manually).\n\t */\n\tpollInterval?: number\n\t/** Callback fired once when the run reaches `completed` */\n\tonComplete?: (run: TaskRunStatus) => void\n\t/** Callback fired once when the run reaches `failed` or `cancelled` */\n\tonFailed?: (run: TaskRunStatus, errorMessage: string | undefined) => void\n\t/** Override the platform URL (uses provider config by default) */\n\tplatformUrl?: string\n}\n\nexport interface UseTaskRunResult {\n\t/** The latest task run snapshot, or `null` before the first fetch */\n\trun: TaskRunStatus | null\n\t/** True while waiting for the first response */\n\tloading: boolean\n\t/** Non-null when the API call fails */\n\terror: SylphxError | null\n\t/** True when status is `completed` */\n\tisComplete: boolean\n\t/** True when status is `failed` or `cancelled` */\n\tisFailed: boolean\n\t/** True when status is `pending`, `running`, or `waiting` */\n\tisRunning: boolean\n\t/** Manually trigger a single fetch (idempotent) */\n\trefetch: () => Promise<void>\n}\n\n// ---------------------------------------------------------------------------\n// Terminal / active status sets\n// ---------------------------------------------------------------------------\n\nconst TERMINAL_STATUSES = new Set<TaskRunStatus['status']>(['completed', 'failed', 'cancelled'])\n\nconst ACTIVE_STATUSES = new Set<TaskRunStatus['status']>(['pending', 'running', 'waiting'])\n\n// ---------------------------------------------------------------------------\n// HTTP status → SylphxErrorCode map\n// ---------------------------------------------------------------------------\n\nconst HTTP_CODE_MAP: Record<number, SylphxErrorCode> = {\n\t400: 'BAD_REQUEST',\n\t401: 'UNAUTHORIZED',\n\t403: 'FORBIDDEN',\n\t404: 'NOT_FOUND',\n\t422: 'UNPROCESSABLE_ENTITY',\n\t500: 'INTERNAL_SERVER_ERROR',\n\t502: 'BAD_GATEWAY',\n\t503: 'SERVICE_UNAVAILABLE',\n\t504: 'GATEWAY_TIMEOUT',\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_POLL_INTERVAL_MS = 2_000\n\n/**\n * Poll a background task run until it reaches a terminal state.\n *\n * @param runId   - Task run ID returned by the platform when a task is triggered.\n *                  Pass `null` to suspend the hook without error.\n * @param options - Polling and callback options\n */\nexport function useTaskRun(runId: string | null, options?: UseTaskRunOptions): UseTaskRunResult {\n\tconst {\n\t\tpollInterval = DEFAULT_POLL_INTERVAL_MS,\n\t\tonComplete,\n\t\tonFailed,\n\t\tplatformUrl: customPlatformUrl,\n\t} = options ?? {}\n\n\tconst platformCtx = useContext(PlatformContext)\n\tconst appId = platformCtx?.appId ?? ''\n\tconst platformUrl =\n\t\tcustomPlatformUrl ?? platformCtx?.platformUrl ?? `https://${DEFAULT_SDK_API_HOST}`\n\n\tconst [run, setRun] = useState<TaskRunStatus | null>(null)\n\tconst [loading, setLoading] = useState(!!runId)\n\tconst [error, setError] = useState<SylphxError | null>(null)\n\n\tconst mountedRef = useRef(true)\n\tconst callbacksFiredRef = useRef({ complete: false, failed: false })\n\tconst pollingRef = useRef(true) // controls whether we should keep polling\n\n\t// SDK request headers\n\tconst headers = useMemo(\n\t\t() => ({\n\t\t\t'Content-Type': 'application/json',\n\t\t\t'x-app-secret': appId,\n\t\t\t'X-SDK-Version': SDK_VERSION,\n\t\t\t'X-SDK-Platform': SDK_PLATFORM,\n\t\t}),\n\t\t[appId],\n\t)\n\n\t// Core fetch function\n\tconst fetchRun = useCallback(async (): Promise<TaskRunStatus | null> => {\n\t\tif (!runId || !appId) return null\n\n\t\tconst response = await fetch(`${platformUrl}${SDK_API_PATH}/tasks/${runId}`, {\n\t\t\tmethod: 'GET',\n\t\t\theaders,\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tconst body = (await response.json().catch(() => ({}))) as Record<string, unknown>\n\t\t\tconst message =\n\t\t\t\ttypeof body.error === 'string' ? body.error : `Task fetch failed (${response.status})`\n\n\t\t\tif (response.status === 429) {\n\t\t\t\tthrow new RateLimitError(message, {\n\t\t\t\t\tretryAfter: Number(response.headers.get('Retry-After')) || undefined,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tthrow new SylphxError(message, {\n\t\t\t\tcode: HTTP_CODE_MAP[response.status] ?? 'UNKNOWN',\n\t\t\t\tstatus: response.status,\n\t\t\t})\n\t\t}\n\n\t\treturn response.json() as Promise<TaskRunStatus>\n\t}, [runId, appId, platformUrl, headers])\n\n\t// Refetch (public API)\n\tconst refetch = useCallback(async (): Promise<void> => {\n\t\tif (!mountedRef.current) return\n\t\tsetError(null)\n\t\ttry {\n\t\t\tconst data = await fetchRun()\n\t\t\tif (!mountedRef.current) return\n\n\t\t\tif (data) {\n\t\t\t\tsetRun(data)\n\t\t\t\tsetLoading(false)\n\n\t\t\t\t// Fire terminal callbacks (once only)\n\t\t\t\tif (data.status === 'completed' && !callbacksFiredRef.current.complete) {\n\t\t\t\t\tcallbacksFiredRef.current.complete = true\n\t\t\t\t\tonComplete?.(data)\n\t\t\t\t} else if (\n\t\t\t\t\t(data.status === 'failed' || data.status === 'cancelled') &&\n\t\t\t\t\t!callbacksFiredRef.current.failed\n\t\t\t\t) {\n\t\t\t\t\tcallbacksFiredRef.current.failed = true\n\t\t\t\t\tonFailed?.(data, data.error)\n\t\t\t\t}\n\n\t\t\t\t// Stop polling when terminal\n\t\t\t\tif (TERMINAL_STATUSES.has(data.status)) {\n\t\t\t\t\tpollingRef.current = false\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tif (mountedRef.current) {\n\t\t\t\tsetError(\n\t\t\t\t\terr instanceof SylphxError\n\t\t\t\t\t\t? err\n\t\t\t\t\t\t: new SylphxError(err instanceof Error ? err.message : 'Task fetch failed', {\n\t\t\t\t\t\t\t\tcode: 'SERVICE_UNAVAILABLE',\n\t\t\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t\tsetLoading(false)\n\t\t\t}\n\t\t}\n\t}, [fetchRun, onComplete, onFailed])\n\n\t// Reset state when runId changes\n\tuseEffect(() => {\n\t\tif (!runId) {\n\t\t\tsetRun(null)\n\t\t\tsetLoading(false)\n\t\t\tsetError(null)\n\t\t\tpollingRef.current = false\n\t\t\tcallbacksFiredRef.current = { complete: false, failed: false }\n\t\t\treturn\n\t\t}\n\n\t\t// New run — reset and start fetching\n\t\tsetRun(null)\n\t\tsetLoading(true)\n\t\tsetError(null)\n\t\tpollingRef.current = true\n\t\tcallbacksFiredRef.current = { complete: false, failed: false }\n\n\t\trefetch()\n\t}, [runId, refetch])\n\n\t// Polling interval — stops automatically when run is terminal\n\tuseEffect(() => {\n\t\tif (!runId || !pollInterval || pollInterval <= 0) return\n\n\t\tconst id = setInterval(() => {\n\t\t\t// Don't poll if terminal or unmounted\n\t\t\tif (!mountedRef.current || !pollingRef.current) {\n\t\t\t\tclearInterval(id)\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// Also stop if current run is already in a terminal state\n\t\t\tif (run && TERMINAL_STATUSES.has(run.status)) {\n\t\t\t\tpollingRef.current = false\n\t\t\t\tclearInterval(id)\n\t\t\t\treturn\n\t\t\t}\n\t\t\trefetch().catch(() => {\n\t\t\t\t// Error surfaces via `error` state\n\t\t\t})\n\t\t}, pollInterval)\n\n\t\treturn () => clearInterval(id)\n\t}, [runId, pollInterval, run, refetch])\n\n\t// Lifecycle\n\tuseEffect(() => {\n\t\tmountedRef.current = true\n\t\treturn () => {\n\t\t\tmountedRef.current = false\n\t\t}\n\t}, [])\n\n\t// Derived status flags\n\tconst isComplete = run?.status === 'completed'\n\tconst isFailed = run?.status === 'failed' || run?.status === 'cancelled'\n\tconst isRunning = !!(run && ACTIVE_STATUSES.has(run.status))\n\n\treturn {\n\t\trun,\n\t\tloading,\n\t\terror,\n\t\tisComplete,\n\t\tisFailed,\n\t\tisRunning,\n\t\trefetch,\n\t}\n}\n","/**\n * Monitoring Hooks\n *\n * React hooks for Sylphx Platform error tracking and monitoring.\n * Apps can capture errors without their own Sentry DSN.\n *\n * Uses proper React Context pattern (no module singletons).\n */\n\n'use client'\n\nimport { useCallback, useEffect, useRef } from 'react'\nimport {\n\ttype Breadcrumb,\n\ttype CaptureExceptionOptions,\n\ttype CaptureMessageOptions,\n\ttype ExceptionValue,\n\tuseMonitoringContext,\n} from './services-context'\nimport type { MonitoringLevel } from './types'\n\n// Re-export types for convenience\nexport type { MonitoringLevel, Breadcrumb, CaptureExceptionOptions, CaptureMessageOptions }\n\n// ============================================\n// Helper Functions\n// ============================================\n\n/**\n * Parse an Error object into Sentry exception format\n */\nfunction _parseError(error: Error): ExceptionValue {\n\tconst frames: ExceptionValue['stacktrace'] = { frames: [] }\n\n\tif (error.stack) {\n\t\tconst lines = error.stack.split('\\n').slice(1) // Skip first line (error message)\n\t\tfor (const line of lines) {\n\t\t\t// Parse stack trace lines like \"    at functionName (file:line:col)\"\n\t\t\tconst match = line.match(/^\\s*at\\s+(?:(.+?)\\s+)?(?:\\()?(.+?):(\\d+):(\\d+)\\)?$/)\n\t\t\tif (match) {\n\t\t\t\tframes.frames.push({\n\t\t\t\t\tfunction: match[1] || '<anonymous>',\n\t\t\t\t\tfilename: match[2],\n\t\t\t\t\tlineno: Number.parseInt(match[3] ?? '0', 10),\n\t\t\t\t\tcolno: Number.parseInt(match[4] ?? '0', 10),\n\t\t\t\t\tin_app: !match[2]?.includes('node_modules'),\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\ttype: error.name || 'Error',\n\t\tvalue: error.message,\n\t\tstacktrace: frames.frames.length > 0 ? frames : undefined,\n\t}\n}\n\n// ============================================\n// useErrorTracking\n// ============================================\n\nexport interface UseErrorTrackingReturn {\n\t/** Capture an error/exception */\n\tcaptureException: (error: Error, options?: CaptureExceptionOptions) => Promise<string | null>\n\t/** Capture a message */\n\tcaptureMessage: (message: string, options?: CaptureMessageOptions) => Promise<string | null>\n\t/** Add a breadcrumb */\n\taddBreadcrumb: (breadcrumb: Breadcrumb) => void\n\t/** Set current route/page for context */\n\tsetRoute: (route: string) => void\n}\n\n/**\n * Hook for error tracking\n *\n * @example\n * ```tsx\n * function MyComponent() {\n *   const { captureException, captureMessage, addBreadcrumb } = useErrorTracking()\n *\n *   useEffect(() => {\n *     addBreadcrumb({ category: 'navigation', message: 'Loaded MyComponent' })\n *   }, [])\n *\n *   const handleClick = async () => {\n *     try {\n *       await riskyOperation()\n *     } catch (error) {\n *       captureException(error, { tags: { feature: 'my-feature' } })\n *     }\n *   }\n *\n *   return <button onClick={handleClick}>Do Something</button>\n * }\n * ```\n */\nexport function useErrorTracking(): UseErrorTrackingReturn {\n\tconst ctx = useMonitoringContext()\n\tconst breadcrumbsRef = useRef<Breadcrumb[]>([])\n\tconst routeRef = useRef<string | null>(null)\n\n\tconst captureException = useCallback(\n\t\tasync (error: Error, options: CaptureExceptionOptions = {}): Promise<string | null> => {\n\t\t\ttry {\n\t\t\t\tconst result = await ctx.captureException(error, {\n\t\t\t\t\tlevel: options.level ?? 'error',\n\t\t\t\t\ttags: options.tags,\n\t\t\t\t\textra: {\n\t\t\t\t\t\t...options.extra,\n\t\t\t\t\t\tbreadcrumbs: breadcrumbsRef.current,\n\t\t\t\t\t},\n\t\t\t\t\tfingerprint: options.fingerprint,\n\t\t\t\t\troute: options.route ?? routeRef.current ?? undefined,\n\t\t\t\t\tuserAgent: typeof navigator !== 'undefined' ? navigator.userAgent : undefined,\n\t\t\t\t})\n\n\t\t\t\t// Clear breadcrumbs after sending\n\t\t\t\tbreadcrumbsRef.current = []\n\n\t\t\t\treturn result.eventId\n\t\t\t} catch {\n\t\t\t\tconsole.error('[Sylphx] Failed to capture exception:', error)\n\t\t\t\treturn null\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst captureMessage = useCallback(\n\t\tasync (message: string, options: CaptureMessageOptions = {}): Promise<string | null> => {\n\t\t\ttry {\n\t\t\t\tconst result = await ctx.captureMessage(message, {\n\t\t\t\t\tlevel: options.level ?? 'info',\n\t\t\t\t\ttags: options.tags,\n\t\t\t\t\textra: options.extra,\n\t\t\t\t\troute: options.route ?? routeRef.current ?? undefined,\n\t\t\t\t})\n\t\t\t\treturn result.eventId\n\t\t\t} catch {\n\t\t\t\tconsole.error('[Sylphx] Failed to capture message:', message)\n\t\t\t\treturn null\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst addBreadcrumb = useCallback((breadcrumb: Breadcrumb) => {\n\t\tbreadcrumbsRef.current.push({\n\t\t\t...breadcrumb,\n\t\t\ttimestamp: breadcrumb.timestamp ?? Date.now(),\n\t\t})\n\n\t\t// Keep only last 100 breadcrumbs\n\t\tif (breadcrumbsRef.current.length > 100) {\n\t\t\tbreadcrumbsRef.current = breadcrumbsRef.current.slice(-100)\n\t\t}\n\t}, [])\n\n\tconst setRoute = useCallback(\n\t\t(route: string) => {\n\t\t\trouteRef.current = route\n\t\t\taddBreadcrumb({\n\t\t\t\ttype: 'navigation',\n\t\t\t\tcategory: 'route',\n\t\t\t\tmessage: route,\n\t\t\t})\n\t\t},\n\t\t[addBreadcrumb],\n\t)\n\n\treturn {\n\t\tcaptureException,\n\t\tcaptureMessage,\n\t\taddBreadcrumb,\n\t\tsetRoute,\n\t}\n}\n\n// ============================================\n// ErrorBoundary Integration\n// ============================================\n\nexport interface UseErrorBoundaryOptions {\n\t/** Called when an error is caught */\n\tonError?: (error: Error, eventId: string | null) => void\n\t/** Component name for context */\n\tcomponentName?: string\n}\n\n/**\n * Hook for error boundary integration\n * Use this inside your error boundary component\n *\n * @example\n * ```tsx\n * function MyErrorBoundary({ children }) {\n *   const { handleError, ErrorFallback } = useErrorBoundary({\n *     componentName: 'App'\n *   })\n *\n *   return (\n *     <ErrorBoundary onError={handleError} FallbackComponent={ErrorFallback}>\n *       {children}\n *     </ErrorBoundary>\n *   )\n * }\n * ```\n */\nexport function useErrorBoundary(options: UseErrorBoundaryOptions = {}) {\n\tconst { captureException } = useErrorTracking()\n\n\tconst handleError = useCallback(\n\t\tasync (error: Error, errorInfo?: { componentStack?: string }) => {\n\t\t\tconst eventId = await captureException(error, {\n\t\t\t\ttags: {\n\t\t\t\t\terrorBoundary: 'true',\n\t\t\t\t\t...(options.componentName && { component: options.componentName }),\n\t\t\t\t},\n\t\t\t\textra: {\n\t\t\t\t\tcomponentStack: errorInfo?.componentStack,\n\t\t\t\t},\n\t\t\t})\n\n\t\t\toptions.onError?.(error, eventId)\n\t\t},\n\t\t[captureException, options],\n\t)\n\n\treturn { handleError }\n}\n\n// ============================================\n// Global Error Handlers\n// ============================================\n\nexport interface UseGlobalErrorHandlerOptions {\n\t/** Enable window.onerror handler */\n\thandleErrors?: boolean\n\t/** Enable unhandledrejection handler */\n\thandleRejections?: boolean\n\t/** Called when an error is captured */\n\tonCapture?: (eventId: string | null) => void\n}\n\n/**\n * Hook that sets up global error handlers\n * Should be used once at the app root\n *\n * @example\n * ```tsx\n * function App() {\n *   useGlobalErrorHandler({\n *     handleErrors: true,\n *     handleRejections: true,\n *   })\n *\n *   return <MyApp />\n * }\n * ```\n */\nexport function useGlobalErrorHandler(options: UseGlobalErrorHandlerOptions = {}) {\n\tconst { handleErrors = true, handleRejections = true, onCapture } = options\n\tconst { captureException } = useErrorTracking()\n\n\tuseEffect(() => {\n\t\tif (typeof window === 'undefined') return\n\n\t\tconst handleWindowError = async (event: ErrorEvent) => {\n\t\t\tif (event.error instanceof Error) {\n\t\t\t\tconst eventId = await captureException(event.error, {\n\t\t\t\t\ttags: { source: 'window.onerror' },\n\t\t\t\t\textra: {\n\t\t\t\t\t\tfilename: event.filename,\n\t\t\t\t\t\tlineno: event.lineno,\n\t\t\t\t\t\tcolno: event.colno,\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\tonCapture?.(eventId)\n\t\t\t}\n\t\t}\n\n\t\tconst handleUnhandledRejection = async (event: PromiseRejectionEvent) => {\n\t\t\tconst error = event.reason instanceof Error ? event.reason : new Error(String(event.reason))\n\n\t\t\tconst eventId = await captureException(error, {\n\t\t\t\ttags: { source: 'unhandledrejection' },\n\t\t\t})\n\t\t\tonCapture?.(eventId)\n\t\t}\n\n\t\tif (handleErrors) {\n\t\t\twindow.addEventListener('error', handleWindowError)\n\t\t}\n\t\tif (handleRejections) {\n\t\t\twindow.addEventListener('unhandledrejection', handleUnhandledRejection)\n\t\t}\n\n\t\treturn () => {\n\t\t\tif (handleErrors) {\n\t\t\t\twindow.removeEventListener('error', handleWindowError)\n\t\t\t}\n\t\t\tif (handleRejections) {\n\t\t\t\twindow.removeEventListener('unhandledrejection', handleUnhandledRejection)\n\t\t\t}\n\t\t}\n\t}, [handleErrors, handleRejections, captureException, onCapture])\n}\n\n// Note: The useMonitoring alias has been intentionally removed.\n// Use useErrorTracking directly for clarity.\n","/**\n * Newsletter Hooks (Part of Email Service)\n *\n * React hooks for Sylphx Platform marketing email (newsletter).\n * Newsletter is a sub-feature of the Email service for marketing/bulk emails.\n * Subscribe users and manage preferences.\n *\n * @see useEmail for transactional emails\n */\n\n'use client'\n\nimport { useCallback, useState } from 'react'\nimport { useNewsletterContext } from './services-context'\nimport type { NewsletterSubscribeInput, NewsletterSubscribeResult } from './types'\n\n// Re-export types for convenience\nexport type { NewsletterSubscribeInput, NewsletterSubscribeResult }\n\n// ============================================\n// useNewsletter\n// ============================================\n\nimport type { SubscriberPreferenceKey } from './services-context'\n\nexport interface UseNewsletterReturn {\n\t/** Subscribe an email to the newsletter */\n\tsubscribe: (options: NewsletterSubscribeInput) => Promise<NewsletterSubscribeResult>\n\t/** Verify a subscription with token */\n\tverify: (token: string) => Promise<{ success: boolean; message: string; email: string }>\n\t/** Unsubscribe an email (requires token) */\n\tunsubscribe: (\n\t\temail: string,\n\t\ttoken: string,\n\t) => Promise<{ success: boolean; message: string; email: string }>\n\t/** Resend verification email */\n\tresendVerification: (email: string) => Promise<{ success: boolean; message: string }>\n\t/** Get unsubscribe info from token */\n\tgetUnsubscribeInfo: (\n\t\ttoken: string,\n\t) => Promise<{ email: string; name?: string; isUnsubscribed: boolean }>\n\t/** Update subscriber preferences */\n\tupdatePreferences: (\n\t\temail: string,\n\t\tpreferences: Record<string, boolean>,\n\t) => Promise<{\n\t\tsuccess: boolean\n\t\tpreferences: Array<{ key: SubscriberPreferenceKey; enabled: boolean }>\n\t}>\n\t/** Get subscriber preferences */\n\tgetPreferences: (email: string) => Promise<Record<string, boolean>>\n\t/** Whether an operation is in progress */\n\tisLoading: boolean\n\t/** Whether the last operation was successful */\n\tsuccess: boolean\n\t/** Last error */\n\terror: Error | null\n\t/** Reset success/error state */\n\treset: () => void\n}\n\n/**\n * Hook for newsletter subscriber management\n *\n * @example\n * ```tsx\n * function NewsletterSignup() {\n *   const { subscribe, isLoading, success, error } = useNewsletter()\n *   const [email, setEmail] = useState('')\n *\n *   const handleSubmit = async (e: React.FormEvent) => {\n *     e.preventDefault()\n *     const result = await subscribe({\n *       email,\n *       preferences: { product_updates: true },\n *       source: 'website',\n *     })\n *     if (result.requiresVerification) {\n *       alert('Check your email to confirm!')\n *     }\n *   }\n *\n *   if (success) {\n *     return <p>Check your email to confirm!</p>\n *   }\n *\n *   return (\n *     <form onSubmit={handleSubmit}>\n *       <input\n *         type=\"email\"\n *         value={email}\n *         onChange={(e) => setEmail(e.target.value)}\n *         placeholder=\"Enter your email\"\n *       />\n *       <button type=\"submit\" disabled={isLoading}>\n *         {isLoading ? 'Subscribing...' : 'Subscribe'}\n *       </button>\n *       {error && <p className=\"error\">{error.message}</p>}\n *     </form>\n *   )\n * }\n * ```\n */\nexport function useNewsletter(): UseNewsletterReturn {\n\tconst ctx = useNewsletterContext()\n\tconst [isLoading, setIsLoading] = useState(false)\n\tconst [success, setSuccess] = useState(false)\n\tconst [error, setError] = useState<Error | null>(null)\n\n\tconst reset = useCallback(() => {\n\t\tsetSuccess(false)\n\t\tsetError(null)\n\t}, [])\n\n\tconst subscribe = useCallback(\n\t\tasync (options: NewsletterSubscribeInput): Promise<NewsletterSubscribeResult> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\t\t\tsetSuccess(false)\n\n\t\t\ttry {\n\t\t\t\tconst result = await ctx.subscribe(options)\n\t\t\t\tsetSuccess(true)\n\t\t\t\treturn result\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to subscribe')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst verify = useCallback(\n\t\tasync (token: string) => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tconst result = await ctx.verify(token)\n\t\t\t\tsetSuccess(true)\n\t\t\t\treturn result\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to verify')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst unsubscribe = useCallback(\n\t\tasync (email: string, token: string) => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tconst result = await ctx.unsubscribe(email, token)\n\t\t\t\tsetSuccess(true)\n\t\t\t\treturn result\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to unsubscribe')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst resendVerification = useCallback(\n\t\tasync (email: string) => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tconst result = await ctx.resendVerification(email)\n\t\t\t\tsetSuccess(true)\n\t\t\t\treturn result\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to resend verification')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst getUnsubscribeInfo = useCallback(\n\t\tasync (token: string) => {\n\t\t\ttry {\n\t\t\t\treturn await ctx.getUnsubscribeInfo(token)\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to get unsubscribe info')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst updatePreferences = useCallback(\n\t\tasync (email: string, preferences: Record<string, boolean>) => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tconst result = await ctx.updatePreferences(email, preferences)\n\t\t\t\tsetSuccess(true)\n\t\t\t\treturn result\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to update preferences')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst getPreferences = useCallback(\n\t\tasync (email: string) => {\n\t\t\ttry {\n\t\t\t\treturn await ctx.getPreferences(email)\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to get preferences')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\treturn {\n\t\tsubscribe,\n\t\tverify,\n\t\tunsubscribe,\n\t\tresendVerification,\n\t\tgetUnsubscribeInfo,\n\t\tupdatePreferences,\n\t\tgetPreferences,\n\t\tisLoading,\n\t\tsuccess,\n\t\terror,\n\t\treset,\n\t}\n}\n\n// ============================================\n// useSubscriberForm\n// ============================================\n\nexport interface UseSubscriberFormOptions {\n\t/** Pre-selected preferences */\n\tpreferences?: Record<string, boolean>\n\t/** Source identifier */\n\tsource?: 'website' | 'waitlist' | 'referral' | 'api' | 'import'\n\t/** Subscriber name */\n\tname?: string\n\t/** Additional metadata */\n\tmetadata?: Record<string, unknown>\n\t/** Callback on successful subscription */\n\tonSuccess?: (result: NewsletterSubscribeResult) => void\n\t/** Callback on error */\n\tonError?: (error: Error) => void\n}\n\nexport interface UseSubscriberFormReturn {\n\t/** Current email value */\n\temail: string\n\t/** Set email value */\n\tsetEmail: (email: string) => void\n\t/** Current preferences */\n\tpreferences: Record<string, boolean>\n\t/** Toggle a preference */\n\ttogglePreference: (pref: string) => void\n\t/** Set a preference */\n\tsetPreference: (pref: string, value: boolean) => void\n\t/** Submit the form */\n\tsubmit: (e?: React.FormEvent) => Promise<void>\n\t/** Whether submission is in progress */\n\tisLoading: boolean\n\t/** Whether submission was successful */\n\tsuccess: boolean\n\t/** Whether verification is required */\n\trequiresVerification: boolean\n\t/** Whether user was already subscribed */\n\talreadySubscribed: boolean\n\t/** Last error */\n\terror: Error | null\n\t/** Reset the form */\n\treset: () => void\n}\n\n/**\n * Hook for newsletter signup form state management\n *\n * @example\n * ```tsx\n * function NewsletterForm() {\n *   const {\n *     email,\n *     setEmail,\n *     preferences,\n *     togglePreference,\n *     submit,\n *     isLoading,\n *     success,\n *     requiresVerification,\n *     error,\n *   } = useSubscriberForm({\n *     preferences: { product_updates: true },\n *     source: 'website',\n *     onSuccess: (result) => {\n *       if (result.requiresVerification) {\n *         toast('Check your email!')\n *       }\n *     },\n *   })\n *\n *   if (success) {\n *     return <p>Thanks for subscribing!</p>\n *   }\n *\n *   return (\n *     <form onSubmit={submit}>\n *       <input\n *         type=\"email\"\n *         value={email}\n *         onChange={(e) => setEmail(e.target.value)}\n *       />\n *       <label>\n *         <input\n *           type=\"checkbox\"\n *           checked={preferences.promotions ?? false}\n *           onChange={() => togglePreference('promotions')}\n *         />\n *         Promotions\n *       </label>\n *       <button type=\"submit\" disabled={isLoading}>\n *         Subscribe\n *       </button>\n *       {error && <p className=\"error\">{error.message}</p>}\n *     </form>\n *   )\n * }\n * ```\n */\nexport function useSubscriberForm(options: UseSubscriberFormOptions = {}): UseSubscriberFormReturn {\n\tconst ctx = useNewsletterContext()\n\tconst [email, setEmail] = useState('')\n\tconst [preferences, setPreferences] = useState<Record<string, boolean>>(options.preferences || {})\n\tconst [isLoading, setIsLoading] = useState(false)\n\tconst [success, setSuccess] = useState(false)\n\tconst [requiresVerification, setRequiresVerification] = useState(false)\n\tconst [alreadySubscribed, setAlreadySubscribed] = useState(false)\n\tconst [error, setError] = useState<Error | null>(null)\n\n\tconst togglePreference = useCallback((pref: string) => {\n\t\tsetPreferences((prev) => ({ ...prev, [pref]: !prev[pref] }))\n\t}, [])\n\n\tconst setPreference = useCallback((pref: string, value: boolean) => {\n\t\tsetPreferences((prev) => ({ ...prev, [pref]: value }))\n\t}, [])\n\n\tconst reset = useCallback(() => {\n\t\tsetEmail('')\n\t\tsetPreferences(options.preferences || {})\n\t\tsetSuccess(false)\n\t\tsetRequiresVerification(false)\n\t\tsetAlreadySubscribed(false)\n\t\tsetError(null)\n\t}, [options.preferences])\n\n\tconst submit = useCallback(\n\t\tasync (e?: React.FormEvent) => {\n\t\t\te?.preventDefault()\n\n\t\t\tif (!email) {\n\t\t\t\tsetError(new Error('Email is required'))\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tconst result = await ctx.subscribe({\n\t\t\t\t\temail,\n\t\t\t\t\tpreferences,\n\t\t\t\t\tsource: options.source,\n\t\t\t\t\tname: options.name,\n\t\t\t\t\tmetadata: options.metadata,\n\t\t\t\t})\n\t\t\t\tsetSuccess(result.success)\n\t\t\t\tsetRequiresVerification(result.requiresVerification)\n\t\t\t\tsetAlreadySubscribed(result.alreadySubscribed ?? false)\n\t\t\t\toptions.onSuccess?.(result)\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to subscribe')\n\t\t\t\tsetError(error)\n\t\t\t\toptions.onError?.(error)\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx, email, preferences, options],\n\t)\n\n\treturn {\n\t\temail,\n\t\tsetEmail,\n\t\tpreferences,\n\t\ttogglePreference,\n\t\tsetPreference,\n\t\tsubmit,\n\t\tisLoading,\n\t\tsuccess,\n\t\trequiresVerification,\n\t\talreadySubscribed,\n\t\terror,\n\t\treset,\n\t}\n}\n","/**\n * Protected Route Components\n *\n * Conditionally render content based on auth state.\n */\n\n'use client'\n\nimport { useSafeUser } from './hooks'\nimport { safeRedirect } from './security-utils'\n\ninterface ChildrenProps {\n\tchildren: React.ReactNode\n}\n\n/**\n * Only renders children when user is signed in\n *\n * @example\n * ```tsx\n * <SignedIn>\n *   <UserButton />\n *   <Link href=\"/dashboard\">Dashboard</Link>\n * </SignedIn>\n * ```\n */\nexport function SignedIn({ children }: ChildrenProps) {\n\tconst { isConfigured, isLoaded, isSignedIn } = useSafeUser()\n\n\t// Gracefully handle unconfigured SDK\n\tif (!isConfigured || !isLoaded || !isSignedIn) {\n\t\treturn null\n\t}\n\n\treturn <>{children}</>\n}\n\n/**\n * Only renders children when user is NOT signed in\n *\n * @example\n * ```tsx\n * <SignedOut>\n *   <Link href=\"/login\">Sign In</Link>\n *   <Link href=\"/signup\">Sign Up</Link>\n * </SignedOut>\n * ```\n */\nexport function SignedOut({ children }: ChildrenProps) {\n\tconst { isConfigured, isLoaded, isSignedIn } = useSafeUser()\n\n\t// Gracefully handle unconfigured SDK - show SignedOut content\n\tif (!isConfigured) {\n\t\treturn <>{children}</>\n\t}\n\n\tif (!isLoaded || isSignedIn) {\n\t\treturn null\n\t}\n\n\treturn <>{children}</>\n}\n\ninterface ProtectedRouteProps extends ChildrenProps {\n\t/** URL to redirect to if not authenticated */\n\tredirectTo?: string\n\t/** Content to show while loading auth state */\n\tfallback?: React.ReactNode\n}\n\n/**\n * Redirects to login if user is not authenticated\n *\n * @example\n * ```tsx\n * <ProtectedRoute redirectTo=\"/login\">\n *   <Dashboard />\n * </ProtectedRoute>\n * ```\n */\nexport function ProtectedRoute({\n\tchildren,\n\tredirectTo = '/login',\n\tfallback = null,\n}: ProtectedRouteProps) {\n\tconst { isConfigured, isLoaded, isSignedIn } = useSafeUser()\n\n\t// Gracefully handle unconfigured SDK - render children (dev experience)\n\tif (!isConfigured) {\n\t\treturn <>{children}</>\n\t}\n\n\tif (!isLoaded) {\n\t\treturn <>{fallback}</>\n\t}\n\n\tif (!isSignedIn) {\n\t\t// Client-side redirect (use safeRedirect to prevent XSS)\n\t\tsafeRedirect(redirectTo, { fallback: '/login' })\n\t\treturn <>{fallback}</>\n\t}\n\n\treturn <>{children}</>\n}\n\ninterface AuthLoadingProps extends ChildrenProps {\n\t/** Content to show when auth is loading */\n\tloading?: React.ReactNode\n}\n\n/**\n * Shows loading content while auth state is being determined\n *\n * @example\n * ```tsx\n * <AuthLoading loading={<Spinner />}>\n *   <App />\n * </AuthLoading>\n * ```\n */\nexport function AuthLoading({ children, loading = null }: AuthLoadingProps) {\n\tconst { isConfigured, isLoaded } = useSafeUser()\n\n\t// Gracefully handle unconfigured SDK - render children\n\tif (!isConfigured) {\n\t\treturn <>{children}</>\n\t}\n\n\tif (!isLoaded) {\n\t\treturn <>{loading}</>\n\t}\n\n\treturn <>{children}</>\n}\n","'use client'\n\n/**\n * Sylphx Provider\n *\n * React context provider for Sylphx Platform.\n * Provides: Auth, Billing, Analytics, Push, Referrals, Storage, and optional services.\n *\n * ARCHITECTURE:\n * - All localStorage keys are namespaced by appId to prevent collisions\n * - Services use proper React Context (not module singletons)\n * - Auto-tracking events are deduplicated by tracking IDs\n * - React Query provides caching, deduplication, and stale-while-revalidate for server data\n */\n\nimport { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { createConfig } from '../config'\nimport { linkAnonymousConsents } from '../consent'\nimport {\n\tANALYTICS_FLUSH_TIMEOUT_MS,\n\tANALYTICS_MAX_TRACKED_EVENT_IDS,\n\tANALYTICS_QUEUE_LIMIT,\n\tANALYTICS_TRACKED_IDS_KEEP,\n\tDEFAULT_SDK_API_HOST,\n\tNEW_USER_THRESHOLD_MS,\n\tSDK_API_PATH,\n\tSTALE_TIME_FREQUENT_MS,\n\tSTALE_TIME_MODERATE_MS,\n\tSTALE_TIME_STABLE_MS,\n} from '../constants'\nimport { validateAndSanitizeAppId } from '../key-validation'\nimport type {\n\tAchievementDefaults,\n\tAchievementUnlockEvent,\n\tLeaderboardDefaults,\n\tLeaderboardQueryOptions,\n\tLeaderboardResult,\n\tRecordActivityResult,\n\tStreakDefaults,\n\tStreakState,\n\tSubmitScoreResult,\n\tUserAchievement,\n} from '../lib/engagement/types'\nimport type { AppConfig, TokenResponse, User } from '../types'\nimport { AuthContext, type AuthState } from './context'\nimport {\n\tcreateAIValue,\n\tcreateConsentValue,\n\tcreateDatabaseValue,\n\tcreateEmailValue,\n\tcreateMonitoringValue,\n\tcreateNewsletterValue,\n\tcreateTasksValue,\n\tcreateWebhooksValue,\n} from './context-values'\nimport { ConfigContext } from './hooks/use-config'\nimport {\n\ttype InAppMessageWithReadStatus,\n\ttype InboxPreferences,\n\ttype MobilePushConfig,\n\ttype MobilePushPlatform,\n\ttype MobilePushPreferences,\n\tPlatformContext,\n\ttype PushPreferences,\n\ttype ReferralStats,\n\ttype Subscription,\n} from './platform-context'\nimport { createRestApi } from './rest-client'\nimport { isValidRedirectUrl, safeRedirect } from './security-utils'\nimport {\n\tAIContext,\n\ttype AIContextValue,\n\tConsentContext,\n\ttype ConsentContextValue,\n\tDatabaseContext,\n\ttype DatabaseContextValue,\n\tEmailContext,\n\ttype EmailContextValue,\n\tMonitoringContext,\n\ttype MonitoringContextValue,\n\tNewsletterContext,\n\ttype NewsletterContextValue,\n\tSdkAuthContext,\n\ttype SdkAuthContextValue,\n\tSecurityContext,\n\ttype SecurityContextValue,\n\tTasksContext,\n\ttype TasksContextValue,\n\tUserContext,\n\ttype UserContextValue,\n\tWebhooksContext,\n\ttype WebhooksContextValue,\n} from './services-context'\nimport {\n\tautoCaptureClickIds,\n\ttype ClickIds,\n\tclearUserCookie,\n\tgetOrCreateAnonymousId,\n\tgetPrimaryClickId,\n\tgetStoredClickIds,\n\tgetUserFromCookie,\n\tSTORAGE_KEYS,\n\tSylphxStorage,\n} from './storage-utils'\nimport { TokenManager } from './token-manager'\n\n// TokenManager extracted to ./token-manager.ts for maintainability\n// REST API Client extracted to ./rest-client.ts for maintainability\n// Service context value factories extracted to ./context-values/ for maintainability\n\n// Storage upload is now handled via presigned URLs in context-values/storage.ts\n\n// ============================================\n// Types\n// ============================================\n\nexport interface SylphxProviderProps {\n\tchildren: React.ReactNode\n\t/**\n\t * Your app's ID (environment-specific identifier)\n\t * Format: app_dev_xxx, app_stg_xxx, or app_prod_xxx\n\t * Get this from Platform Admin → Apps → Your App → Environments\n\t *\n\t * The App ID IS the app identity — no separate key needed.\n\t */\n\tappId?: string\n\t/** Project ref (16-char alphanumeric) — preferred over platformUrl */\n\tprojectRef?: string\n\t/** Platform URL — legacy, use projectRef instead */\n\tplatformUrl?: string\n\t/** After sign out, redirect to this URL */\n\tafterSignOutUrl?: string\n\t/** VAPID public key for push notifications (get from platform) */\n\tvapidPublicKey?: string\n\t/**\n\t * Auto-tracking configuration\n\t * - true: enable all auto-tracking (default)\n\t * - false: disable all auto-tracking\n\t * - object: fine-grained control\n\t */\n\tautoTracking?:\n\t\t| boolean\n\t\t| {\n\t\t\t\tpageview?: boolean\n\t\t\t\tlogin?: boolean\n\t\t\t\tsignup?: boolean\n\t\t\t\tlogout?: boolean\n\t\t\t\tpurchase?: boolean\n\t\t  }\n\t/**\n\t * App configuration fetched server-side via getAppConfig()\n\t *\n\t * **Required:** Use `getAppConfig()` from '@sylphx/sdk/server' in Server Components\n\t * to fetch all config data and pass it here.\n\t *\n\t * @example\n\t * ```tsx\n\t * // layout.tsx (Server Component)\n\t * import { getAppConfig } from '@sylphx/sdk/server'\n\t *\n\t * export default async function RootLayout({ children }) {\n\t *   const config = await getAppConfig({\n\t *     secretKey: createServerClient(process.env.SYLPHX_SECRET_URL!).secretKey!,\n\t *     appId: process.env.NEXT_PUBLIC_SYLPHX_APP_ID!,\n\t *   })\n\t *\n\t *   return (\n\t *     <SylphxProvider config={config} appId={...}>\n\t *       {children}\n\t *     </SylphxProvider>\n\t *   )\n\t * }\n\t * ```\n\t */\n\tconfig: AppConfig\n\t/**\n\t * Auth route prefix. Must match the `authPrefix` in your middleware config.\n\t * Default: '/auth' (matches middleware default)\n\t *\n\t * This determines where OAuth callbacks are routed:\n\t * - '/auth' → callback at /auth/callback\n\t * - '/api/auth' → callback at /api/auth/callback\n\t */\n\tauthPrefix?: string\n}\n\n// ============================================\n// Provider Component\n// ============================================\n\n/**\n * SylphxProvider\n *\n * Wrapper that sets up QueryClientProvider first, then renders the inner provider.\n * This is necessary because the inner provider uses useQuery hooks that require\n * QueryClientProvider context.\n */\nexport function SylphxProvider({\n\tchildren,\n\tappId,\n\tprojectRef: providedRef,\n\tplatformUrl: providedPlatformUrl,\n\tafterSignOutUrl = '/',\n\tvapidPublicKey,\n\tautoTracking = true,\n\tconfig,\n\tauthPrefix = '/auth',\n}: SylphxProviderProps) {\n\t// Create QueryClient at the outer level\n\tconst [queryClient] = useState(\n\t\t() =>\n\t\t\tnew QueryClient({\n\t\t\t\tdefaultOptions: {\n\t\t\t\t\tqueries: {\n\t\t\t\t\t\t// SDK default: 5 min stale time, no refetch on window focus\n\t\t\t\t\t\tstaleTime: STALE_TIME_STABLE_MS,\n\t\t\t\t\t\trefetchOnWindowFocus: false,\n\t\t\t\t\t\tretry: 1,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}),\n\t)\n\n\t// Wrap with QueryClientProvider FIRST, then render inner provider\n\t// ConfigContext wraps everything to provide server-fetched config\n\treturn (\n\t\t<ConfigContext.Provider value={config}>\n\t\t\t<QueryClientProvider client={queryClient}>\n\t\t\t\t<SylphxProviderInner\n\t\t\t\t\tappId={appId}\n\t\t\t\t\tprojectRef={providedRef}\n\t\t\t\t\tplatformUrl={providedPlatformUrl}\n\t\t\t\t\tafterSignOutUrl={afterSignOutUrl}\n\t\t\t\t\tvapidPublicKey={vapidPublicKey}\n\t\t\t\t\tautoTracking={autoTracking}\n\t\t\t\t\tqueryClient={queryClient}\n\t\t\t\t\tconfig={config}\n\t\t\t\t\tauthPrefix={authPrefix}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</SylphxProviderInner>\n\t\t\t</QueryClientProvider>\n\t\t</ConfigContext.Provider>\n\t)\n}\n\n/**\n * SylphxProviderInner\n *\n * Inner provider that uses useQuery hooks. Must be rendered inside QueryClientProvider.\n */\nfunction SylphxProviderInner({\n\tchildren,\n\tappId: appIdProp,\n\tprojectRef: providedRef,\n\tplatformUrl: providedPlatformUrl,\n\tafterSignOutUrl = '/',\n\tvapidPublicKey,\n\tautoTracking = true,\n\tqueryClient,\n\tconfig,\n\tauthPrefix = '/auth',\n}: SylphxProviderProps & { queryClient: QueryClient }) {\n\t// Validate and sanitize app ID at initialization\n\t// Following industry-standard \"fail fast\" pattern (Stripe, Clerk, Firebase)\n\t// - Validates key format against expected pattern\n\t// - Logs warning if key contains whitespace (common Vercel CLI bug)\n\t// - Throws error if key is completely invalid\n\tconst appId = validateAndSanitizeAppId(appIdProp)\n\n\t// Resolve ref: explicit prop wins; otherwise extract only from legacy\n\t// embedded-ref compatibility keys. ADR-055 keys route server-side.\n\tconst resolvedRef = (() => {\n\t\tif (providedRef) return providedRef\n\t\tconst parts = appId?.split('_') ?? []\n\t\t// Legacy compatibility key format: [type, env, ref, token] — ref at index 2\n\t\treturn parts.length === 4 && /^[a-z0-9]{12}$/.test(parts[2] ?? '') ? parts[2] : undefined\n\t})()\n\n\tconst platformUrl = resolvedRef\n\t\t? `https://${resolvedRef}.${DEFAULT_SDK_API_HOST}`\n\t\t: providedPlatformUrl?.trim() || `https://${DEFAULT_SDK_API_HOST}`\n\n\t// ============================================\n\t// Storage (namespaced by app identifier)\n\t// ============================================\n\tconst storage = useMemo(() => new SylphxStorage(appId), [appId])\n\n\t// Hydration-safe: start with empty string, populate from localStorage in useEffect\n\t// Server and client initial render both produce '' — no mismatch\n\tconst [anonymousId, setAnonymousId] = useState('')\n\tuseEffect(() => {\n\t\tsetAnonymousId(getOrCreateAnonymousId(storage))\n\t}, [storage])\n\n\t// ============================================\n\t// Click ID Auto-Capture (for conversion attribution)\n\t// ============================================\n\tconst [clickIds, setClickIds] = useState<ClickIds>({})\n\tconst hasInitializedClickIds = useRef(false)\n\n\t// Auto-capture click IDs from URL on mount\n\tuseEffect(() => {\n\t\tif (hasInitializedClickIds.current) return\n\t\thasInitializedClickIds.current = true\n\n\t\t// Capture and store any click IDs from URL\n\t\tconst captured = autoCaptureClickIds(storage)\n\t\tsetClickIds(captured)\n\t}, [storage])\n\n\t// ============================================\n\t// Auth State — Cookie-Centric (Single Source of Truth)\n\t// ============================================\n\t// Hydration-safe: start with isLoaded: false (loading state).\n\t// Both server and client initial render produce the same output.\n\t// Cookie is read in useEffect below to populate the real auth state.\n\t//\n\t// Note: Declared early because TokenManager needs isSignedIn check\n\tconst [authState, setAuthState] = useState<AuthState>({\n\t\tisLoaded: false,\n\t\tisSignedIn: false,\n\t\tuser: null,\n\t\taccessToken: null,\n\t\trefreshToken: null,\n\t\terror: null,\n\t\tisOAuthLoading: false,\n\t\toauthError: null,\n\t})\n\n\t// Hydrate auth state from cookie after mount (avoids server/client mismatch)\n\tuseEffect(() => {\n\t\tconst userCookieData = getUserFromCookie(appId)\n\t\tif (userCookieData && userCookieData.expiresAt > Date.now()) {\n\t\t\tsetAuthState({\n\t\t\t\tisLoaded: true,\n\t\t\t\tisSignedIn: true,\n\t\t\t\tuser: userCookieData.user,\n\t\t\t\taccessToken: null,\n\t\t\t\trefreshToken: null,\n\t\t\t\terror: null,\n\t\t\t\tisOAuthLoading: false,\n\t\t\t\toauthError: null,\n\t\t\t})\n\t\t} else {\n\t\t\tsetAuthState((prev) => ({ ...prev, isLoaded: true }))\n\t\t}\n\t}, [appId])\n\n\t// Ref to track current auth state for TokenManager (avoids stale closure)\n\tconst authStateRef = useRef(authState)\n\tuseEffect(() => {\n\t\tauthStateRef.current = authState\n\t}, [authState])\n\n\t// ============================================\n\t// Token Manager — State of the Art\n\t// ============================================\n\t// Handles: Lazy fetch, request queuing, auto-refresh, retry with backoff, 401 recovery\n\tconst tokenManager = useMemo(\n\t\t() =>\n\t\t\tnew TokenManager({\n\t\t\t\tisSignedIn: () => authStateRef.current.isSignedIn,\n\t\t\t\tonSessionExpired: () => {\n\t\t\t\t\t// Session expired — clear auth state\n\t\t\t\t\tsetAuthState((prev) => ({\n\t\t\t\t\t\t...prev,\n\t\t\t\t\t\tisSignedIn: false,\n\t\t\t\t\t\tuser: null,\n\t\t\t\t\t\terror: new Error('Session expired'),\n\t\t\t\t\t}))\n\t\t\t\t\t// Clear user cookie\n\t\t\t\t\tclearUserCookie(appId)\n\t\t\t\t},\n\t\t\t\tauthPrefix,\n\t\t\t}),\n\t\t[appId, authPrefix],\n\t)\n\n\t// Clear token manager when auth state changes to signed out\n\tuseEffect(() => {\n\t\tif (!authState.isSignedIn) {\n\t\t\ttokenManager.clear()\n\t\t}\n\t}, [authState.isSignedIn, tokenManager])\n\n\t// ============================================\n\t// Identity Link on Login (Segment/Mixpanel Pattern)\n\t// ============================================\n\t// When user transitions from anonymous to authenticated,\n\t// link their anonymous consent records to their user account.\n\t// This ensures consent history is preserved across the identity merge.\n\t//\n\t// Uses null sentinel to distinguish \"not yet initialized\" from \"signed out\".\n\t// Only tracks transitions AFTER isLoaded is true, preventing the false\n\t// anonymous→authenticated transition that occurs during initial hydration\n\t// (authState starts at isSignedIn:false then becomes true from cookie read).\n\tconst prevIsSignedIn = useRef<boolean | null>(null)\n\tuseEffect(() => {\n\t\t// Wait until auth state is loaded before tracking transitions\n\t\tif (!authState.isLoaded) return\n\n\t\t// First time isLoaded becomes true — establish baseline, don't trigger link\n\t\tif (prevIsSignedIn.current === null) {\n\t\t\tprevIsSignedIn.current = authState.isSignedIn\n\t\t\treturn\n\t\t}\n\n\t\tconst wasAnonymous = !prevIsSignedIn.current\n\t\tconst isNowAuthenticated = authState.isSignedIn && authState.user?.id\n\n\t\tif (wasAnonymous && isNowAuthenticated && authState.user && anonymousId && resolvedRef) {\n\t\t\t// User just logged in — link anonymous consents\n\t\t\tconst config = createConfig({\n\t\t\t\tsecretKey: appId,\n\t\t\t\tslug: resolvedRef,\n\t\t\t})\n\n\t\t\tlinkAnonymousConsents(config, {\n\t\t\t\tuserId: authState.user.id,\n\t\t\t\tanonymousId,\n\t\t\t}).catch((err) => {\n\t\t\t\t// Non-fatal: log but don't break the app\n\t\t\t\tconsole.warn('[Sylphx] Failed to link anonymous consents:', err)\n\t\t\t})\n\t\t}\n\n\t\tprevIsSignedIn.current = authState.isSignedIn\n\t}, [\n\t\tauthState.isLoaded,\n\t\tauthState.isSignedIn,\n\t\tauthState.user?.id,\n\t\tanonymousId,\n\t\tappId,\n\t\tauthState.user,\n\t\tresolvedRef,\n\t])\n\n\t// ============================================\n\t// REST API Client — same-origin cookie BFF (ADR-3457)\n\t// ============================================\n\tconst api = useMemo(\n\t\t() =>\n\t\t\tcreateRestApi({\n\t\t\t\tbaasPrefix: '/sylphx',\n\t\t\t\tauthPrefix,\n\t\t\t\ttokenManager,\n\t\t\t}),\n\t\t[authPrefix, tokenManager],\n\t)\n\n\t// ============================================\n\t// Platform State - React Query for server data\n\t// ============================================\n\n\t// Plans: Always from server-fetched config (no client-side fetching)\n\tconst plans = config.plans\n\tconst plansLoading = false\n\tconst plansError: Error | null = null\n\n\t// Subscription - React Query (enabled when signed in)\n\tconst subscriptionQuery = useQuery({\n\t\tqueryKey: ['sylphx', appId, 'subscription', authState.user?.id],\n\t\tqueryFn: () =>\n\t\t\tapi.get<Subscription | null>('/billing/subscription', {\n\t\t\t\tuserId: authState.user!.id,\n\t\t\t}),\n\t\tenabled: authState.isSignedIn && !!authState.user?.id,\n\t\tstaleTime: STALE_TIME_MODERATE_MS, // 2 min - subscription can change after payment\n\t})\n\tconst subscription = subscriptionQuery.data ?? null\n\tconst subscriptionLoading = subscriptionQuery.isLoading\n\tconst subscriptionError = subscriptionQuery.error as Error | null\n\n\t// Referrals - React Query (enabled when signed in)\n\tconst referralsQuery = useQuery({\n\t\tqueryKey: ['sylphx', appId, 'referrals'],\n\t\tqueryFn: async () => {\n\t\t\tconst [stats, codeData] = await Promise.all([\n\t\t\t\tapi.get<ReferralStats>('/referrals/stats'),\n\t\t\t\tapi.get<{ code: string }>('/referrals/code'),\n\t\t\t])\n\t\t\treturn { stats, code: codeData.code }\n\t\t},\n\t\tenabled: authState.isSignedIn,\n\t\tstaleTime: STALE_TIME_STABLE_MS, // 5 min\n\t})\n\tconst referralStats = referralsQuery.data?.stats ?? null\n\tconst referralCode = referralsQuery.data?.code ?? null\n\tconst referralLoading = referralsQuery.isLoading\n\tconst referralError = referralsQuery.error as Error | null\n\n\t// Push Preferences - React Query (enabled when signed in)\n\tconst pushPreferencesQuery = useQuery({\n\t\tqueryKey: ['sylphx', appId, 'pushPreferences'],\n\t\tqueryFn: () => api.get<PushPreferences>('/notifications/preferences'),\n\t\tenabled: authState.isSignedIn,\n\t\tstaleTime: STALE_TIME_STABLE_MS, // 5 min\n\t})\n\tconst pushPreferences = pushPreferencesQuery.data ?? null\n\tconst pushError = pushPreferencesQuery.error as Error | null\n\tconst [pushSubscribed, setPushSubscribed] = useState(false)\n\tconst [analyticsError, setAnalyticsError] = useState<Error | null>(null)\n\n\t// Mobile Push Config/Preferences - React Query (enabled when signed in)\n\tconst mobilePushQuery = useQuery({\n\t\tqueryKey: ['sylphx', appId, 'mobilePush'],\n\t\tqueryFn: async () => {\n\t\t\tconst [config, preferences] = await Promise.all([\n\t\t\t\tapi.get<MobilePushConfig>('/notifications/mobile/config'),\n\t\t\t\tapi.get<MobilePushPreferences>('/notifications/mobile/preferences'),\n\t\t\t])\n\t\t\treturn { config, preferences }\n\t\t},\n\t\tenabled: authState.isSignedIn,\n\t\tstaleTime: STALE_TIME_STABLE_MS, // 5 min\n\t})\n\tconst mobilePushConfig = mobilePushQuery.data?.config ?? null\n\tconst mobilePushPreferences = mobilePushQuery.data?.preferences ?? null\n\tconst mobilePushError = mobilePushQuery.error as Error | null\n\n\t// ============================================\n\t// In-App Messages (Inbox) - React Query (enabled when signed in)\n\t// ============================================\n\tconst inboxQuery = useQuery({\n\t\tqueryKey: ['sylphx', appId, 'inbox'],\n\t\tqueryFn: async () => {\n\t\t\tconst [messages, unreadCountResult, preferences] = await Promise.all([\n\t\t\t\tapi.get<InAppMessageWithReadStatus[]>('/notifications/messages', {\n\t\t\t\t\tlimit: '50',\n\t\t\t\t}),\n\t\t\t\tapi.get<{ count: number }>('/notifications/messages/unread-count'),\n\t\t\t\tapi.get<InboxPreferences>('/notifications/messages/preferences'),\n\t\t\t])\n\t\t\treturn { messages, unreadCount: unreadCountResult.count, preferences }\n\t\t},\n\t\tenabled: authState.isSignedIn,\n\t\tstaleTime: STALE_TIME_FREQUENT_MS, // 1 min - inbox changes frequently\n\t})\n\tconst inboxMessages = inboxQuery.data?.messages ?? []\n\tconst inboxUnreadCount = inboxQuery.data?.unreadCount ?? 0\n\tconst inboxPreferences = inboxQuery.data?.preferences ?? null\n\tconst inboxLoading = inboxQuery.isLoading\n\tconst inboxError = inboxQuery.error as Error | null\n\n\t// Check if push is supported (deferred to useEffect to avoid hydration mismatch)\n\tconst [pushSupported, setPushSupported] = useState(false)\n\tuseEffect(() => {\n\t\tsetPushSupported('serviceWorker' in navigator && 'PushManager' in window)\n\t}, [])\n\n\t// Analytics queue for batching\n\tconst analyticsQueue = useRef<\n\t\tArray<{ type: string; data: Record<string, unknown>; eventId: string }>\n\t>([])\n\tconst flushTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\tconst trackedEventIds = useRef<Set<string>>(new Set())\n\n\t// ============================================\n\t// sendBeacon Fallback for Analytics (Segment/Amplitude Pattern)\n\t// ============================================\n\t// Ensures analytics events are not lost when user closes the tab\n\t// sendBeacon is designed to work during page unload when fetch would be cancelled\n\tuseEffect(() => {\n\t\tif (typeof window === 'undefined') return\n\n\t\tconst handleBeforeUnload = () => {\n\t\t\tconst events = analyticsQueue.current\n\t\t\tif (events.length === 0) return\n\n\t\t\ttry {\n\t\t\t\t// Build payload for sendBeacon\n\t\t\t\tconst payload = JSON.stringify({\n\t\t\t\t\tevents: events.map(({ type, data }) => ({\n\t\t\t\t\t\tevent: type,\n\t\t\t\t\t\tproperties: data,\n\t\t\t\t\t\ttimestamp: data.timestamp as string | undefined,\n\t\t\t\t\t})),\n\t\t\t\t})\n\n\t\t\t\t// sendBeacon returns true if the request is successfully queued\n\t\t\t\t// It works even during page unload when fetch would be cancelled\n\t\t\t\tconst beaconUrl = `${platformUrl}${SDK_API_PATH}/analytics/track`\n\t\t\t\tconst blob = new Blob([payload], { type: 'application/json' })\n\n\t\t\t\t// Note: sendBeacon doesn't support custom headers, so we include appId in URL\n\t\t\t\t// Server should accept this for beacon requests\n\t\t\t\tconst beaconSent = navigator.sendBeacon(\n\t\t\t\t\t`${beaconUrl}?appId=${encodeURIComponent(appId)}`,\n\t\t\t\t\tblob,\n\t\t\t\t)\n\n\t\t\t\tif (beaconSent) {\n\t\t\t\t\t// Clear the queue since beacon was queued successfully\n\t\t\t\t\tanalyticsQueue.current = []\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Best effort - if sendBeacon fails, events are lost\n\t\t\t\t// This is acceptable as it's a rare edge case\n\t\t\t}\n\t\t}\n\n\t\twindow.addEventListener('beforeunload', handleBeforeUnload)\n\t\t// Also handle visibilitychange for mobile (tab switch = potential app close)\n\t\tconst handleVisibilityChange = () => {\n\t\t\tif (document.visibilityState === 'hidden') {\n\t\t\t\thandleBeforeUnload()\n\t\t\t}\n\t\t}\n\t\tdocument.addEventListener('visibilitychange', handleVisibilityChange)\n\n\t\treturn () => {\n\t\t\twindow.removeEventListener('beforeunload', handleBeforeUnload)\n\t\t\tdocument.removeEventListener('visibilitychange', handleVisibilityChange)\n\t\t}\n\t}, [appId, platformUrl])\n\n\t// ============================================\n\t// Auto-tracking configuration\n\t// ============================================\n\tconst autoTrackConfig = useMemo(() => {\n\t\tif (autoTracking === false) {\n\t\t\treturn {\n\t\t\t\tpageview: false,\n\t\t\t\tlogin: false,\n\t\t\t\tsignup: false,\n\t\t\t\tlogout: false,\n\t\t\t\tpurchase: false,\n\t\t\t}\n\t\t}\n\t\tif (autoTracking === true) {\n\t\t\treturn {\n\t\t\t\tpageview: true,\n\t\t\t\tlogin: true,\n\t\t\t\tsignup: true,\n\t\t\t\tlogout: true,\n\t\t\t\tpurchase: true,\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tpageview: autoTracking.pageview ?? true,\n\t\t\tlogin: autoTracking.login ?? true,\n\t\t\tsignup: autoTracking.signup ?? true,\n\t\t\tlogout: autoTracking.logout ?? true,\n\t\t\tpurchase: autoTracking.purchase ?? true,\n\t\t}\n\t}, [autoTracking])\n\n\t// ============================================\n\t// Auth State Updates\n\t// ============================================\n\t// Note: Tokens are stored in HttpOnly cookies (server-side).\n\t// These functions only update React state for UI reactivity.\n\t// Cookies are managed by middleware and server-side handlers.\n\n\t/**\n\t * Update auth state after successful authentication.\n\t *\n\t * Note: This does NOT store tokens in localStorage (XSS protection).\n\t * Tokens are in HttpOnly cookies, managed server-side.\n\t */\n\tconst saveTokens = useCallback(\n\t\t(response: TokenResponse) => {\n\t\t\t// Update auth state (tokens are in HttpOnly cookies, not accessible to JS)\n\t\t\tsetAuthState({\n\t\t\t\tisLoaded: true,\n\t\t\t\tisSignedIn: true,\n\t\t\t\tuser: response.user,\n\t\t\t\t// Tokens not exposed to JavaScript — they're in HttpOnly cookies\n\t\t\t\taccessToken: null,\n\t\t\t\trefreshToken: null,\n\t\t\t\terror: null,\n\t\t\t\tisOAuthLoading: false,\n\t\t\t\toauthError: null,\n\t\t\t})\n\n\t\t\t// Broadcast auth change to other tabs\n\t\t\tif (typeof window !== 'undefined' && typeof BroadcastChannel !== 'undefined') {\n\t\t\t\ttry {\n\t\t\t\t\tconst channel = new BroadcastChannel(`sylphx-auth-${appId}`)\n\t\t\t\t\tchannel.postMessage({\n\t\t\t\t\t\ttype: 'auth-change',\n\t\t\t\t\t\tisSignedIn: true,\n\t\t\t\t\t\tuser: response.user,\n\t\t\t\t\t})\n\t\t\t\t\tchannel.close()\n\t\t\t\t} catch {\n\t\t\t\t\t// BroadcastChannel not supported\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[appId],\n\t)\n\n\t/**\n\t * Clear auth state on sign out.\n\t *\n\t * Note: Actual cookie clearing happens server-side via signOut().\n\t * This function clears the JS-readable user cookie for immediate UI update.\n\t */\n\tconst clearTokens = useCallback(\n\t\t(error?: Error) => {\n\t\t\t// Clear the JS-readable user cookie (for immediate UI update)\n\t\t\tclearUserCookie(appId)\n\n\t\t\tsetAuthState({\n\t\t\t\tisLoaded: true,\n\t\t\t\tisSignedIn: false,\n\t\t\t\tuser: null,\n\t\t\t\taccessToken: null,\n\t\t\t\trefreshToken: null,\n\t\t\t\terror: error || null,\n\t\t\t\tisOAuthLoading: false,\n\t\t\t\toauthError: null,\n\t\t\t})\n\n\t\t\t// Broadcast sign-out to other tabs\n\t\t\tif (typeof window !== 'undefined' && typeof BroadcastChannel !== 'undefined') {\n\t\t\t\ttry {\n\t\t\t\t\tconst channel = new BroadcastChannel(`sylphx-auth-${appId}`)\n\t\t\t\t\tchannel.postMessage({\n\t\t\t\t\t\ttype: 'auth-change',\n\t\t\t\t\t\tisSignedIn: false,\n\t\t\t\t\t\tuser: null,\n\t\t\t\t\t})\n\t\t\t\t\tchannel.close()\n\t\t\t\t} catch {\n\t\t\t\t\t// BroadcastChannel not supported\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[appId],\n\t)\n\n\t// ============================================\n\t// Cross-Tab Auth Sync (BroadcastChannel)\n\t// ============================================\n\t// With cookie-centric auth, cookies sync automatically across tabs.\n\t// We use BroadcastChannel to sync React state across tabs for immediate UI updates.\n\tuseEffect(() => {\n\t\tif (typeof BroadcastChannel === 'undefined') return\n\n\t\tconst channel = new BroadcastChannel(`sylphx-auth-${appId}`)\n\n\t\tconst handleMessage = (event: MessageEvent) => {\n\t\t\tif (event.data?.type === 'auth-change') {\n\t\t\t\tsetAuthState((prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\tisLoaded: true,\n\t\t\t\t\tisSignedIn: event.data.isSignedIn,\n\t\t\t\t\tuser: event.data.user,\n\t\t\t\t\terror: null,\n\t\t\t\t}))\n\t\t\t} else if (event.data?.type === 'org-token-change') {\n\t\t\t\ttokenManager.invalidate()\n\t\t\t}\n\t\t}\n\n\t\tchannel.addEventListener('message', handleMessage)\n\n\t\treturn () => {\n\t\t\tchannel.removeEventListener('message', handleMessage)\n\t\t\tchannel.close()\n\t\t}\n\t}, [appId, tokenManager])\n\n\t// ============================================\n\t// Tab Focus Sync (re-read cookie on visibility change)\n\t// ============================================\n\t// When user switches tabs, re-read cookie to catch any auth changes\n\tuseEffect(() => {\n\t\tconst handleVisibilityChange = () => {\n\t\t\tif (document.visibilityState === 'visible') {\n\t\t\t\tconst userCookieData = getUserFromCookie(appId)\n\t\t\t\tconst isSignedIn = !!(userCookieData && userCookieData.expiresAt > Date.now())\n\n\t\t\t\tsetAuthState((prev) => {\n\t\t\t\t\t// Only update if auth state actually changed\n\t\t\t\t\tif (prev.isSignedIn !== isSignedIn || prev.user?.id !== userCookieData?.user?.id) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...prev,\n\t\t\t\t\t\t\tisLoaded: true,\n\t\t\t\t\t\t\tisSignedIn,\n\t\t\t\t\t\t\tuser: userCookieData?.user ?? null,\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn prev\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tdocument.addEventListener('visibilitychange', handleVisibilityChange)\n\t\treturn () => document.removeEventListener('visibilitychange', handleVisibilityChange)\n\t}, [appId])\n\n\t// ============================================\n\t// Handle OAuth Error in URL (error from provider)\n\t// ============================================\n\tuseEffect(() => {\n\t\tif (typeof window === 'undefined') return\n\n\t\tconst params = new URLSearchParams(window.location.search)\n\t\tconst error = params.get('error')\n\t\tconst errorDescription = params.get('error_description')\n\n\t\tif (error) {\n\t\t\tconst oauthError = new Error(errorDescription || error)\n\t\t\tsetAuthState((prev) => ({\n\t\t\t\t...prev,\n\t\t\t\tisLoaded: true,\n\t\t\t\tisSignedIn: false,\n\t\t\t\toauthError,\n\t\t\t}))\n\n\t\t\t// Clean up URL params\n\t\t\tconst cleanUrl = new URL(window.location.href)\n\t\t\tcleanUrl.searchParams.delete('error')\n\t\t\tcleanUrl.searchParams.delete('error_description')\n\t\t\twindow.history.replaceState({}, '', cleanUrl.toString())\n\t\t}\n\t}, [])\n\n\t// ============================================\n\t// Token Refresh — Handled by Middleware (Server-Side)\n\t// ============================================\n\t// With the new cookie-centric architecture, token refresh happens\n\t// server-side in the middleware. No client-side refresh needed.\n\t// The middleware checks session expiry and refreshes automatically.\n\n\t// ============================================\n\t// All server data is now handled by React Query:\n\t// - Plans (plansQuery)\n\t// - Subscription (subscriptionQuery)\n\t// - Referrals (referralsQuery)\n\t// - Push Preferences (pushPreferencesQuery)\n\t// - Mobile Push (mobilePushQuery)\n\t// - Inbox Messages (inboxQuery)\n\t// ============================================\n\n\t// ============================================\n\t// Auth Actions\n\t// ============================================\n\n\t/**\n\t * Resolve a redirect URL to an absolute URL.\n\t * Platform requires absolute URLs for redirect_uri validation.\n\t */\n\tconst resolveRedirectUrl = useCallback((url: string | undefined): string => {\n\t\tif (typeof window === 'undefined') return ''\n\t\tif (!url) return window.location.href\n\n\t\t// Relative URL starting with / - resolve against current origin\n\t\tif (url.startsWith('/') && !url.startsWith('//')) {\n\t\t\treturn `${window.location.origin}${url}`\n\t\t}\n\n\t\t// Already absolute URL\n\t\treturn url\n\t}, [])\n\n\tconst signIn = useCallback(\n\t\t(options?: { redirectUrl?: string; providers?: string[] | null }) => {\n\t\t\t// Resolve and validate redirectUrl to prevent open redirect attacks\n\t\t\tconst resolvedUrl = resolveRedirectUrl(options?.redirectUrl)\n\t\t\tconst redirectUri = isValidRedirectUrl(resolvedUrl, {\n\t\t\t\tallowedOrigins: [platformUrl],\n\t\t\t})\n\t\t\t\t? resolvedUrl\n\t\t\t\t: typeof window !== 'undefined'\n\t\t\t\t\t? window.location.href\n\t\t\t\t\t: ''\n\t\t\tconst params = new URLSearchParams({\n\t\t\t\tclient_id: appId || '',\n\t\t\t\tredirect_uri: redirectUri,\n\t\t\t\tresponse_type: 'code',\n\t\t\t})\n\t\t\tif (options?.providers !== undefined && options.providers !== null) {\n\t\t\t\tparams.set('providers', options.providers.join(','))\n\t\t\t}\n\t\t\t// Safe redirect to platform auth (platformUrl is trusted)\n\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\twindow.location.href = `${platformUrl}/auth/authorize?${params}`\n\t\t\t}\n\t\t},\n\t\t[appId, platformUrl, resolveRedirectUrl],\n\t)\n\n\tconst signUp = useCallback(\n\t\t(options?: { redirectUrl?: string; providers?: string[] | null }) => {\n\t\t\t// Resolve and validate redirectUrl to prevent open redirect attacks\n\t\t\tconst resolvedUrl = resolveRedirectUrl(options?.redirectUrl)\n\t\t\tconst redirectUri = isValidRedirectUrl(resolvedUrl, {\n\t\t\t\tallowedOrigins: [platformUrl],\n\t\t\t})\n\t\t\t\t? resolvedUrl\n\t\t\t\t: typeof window !== 'undefined'\n\t\t\t\t\t? window.location.href\n\t\t\t\t\t: ''\n\t\t\tconst params = new URLSearchParams({\n\t\t\t\tclient_id: appId || '',\n\t\t\t\tredirect_uri: redirectUri,\n\t\t\t\tresponse_type: 'code',\n\t\t\t\tmode: 'signup',\n\t\t\t})\n\t\t\tif (options?.providers !== undefined && options.providers !== null) {\n\t\t\t\tparams.set('providers', options.providers.join(','))\n\t\t\t}\n\t\t\t// Safe redirect to platform auth (platformUrl is trusted)\n\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\twindow.location.href = `${platformUrl}/auth/authorize?${params}`\n\t\t\t}\n\t\t},\n\t\t[appId, platformUrl, resolveRedirectUrl],\n\t)\n\n\tconst signOut = useCallback(\n\t\tasync (options?: { redirectUrl?: string }) => {\n\t\t\t// Call server-side signout to clear HttpOnly cookies and revoke tokens\n\t\t\t// Uses authPrefix to match middleware route (default: /auth/signout)\n\t\t\ttry {\n\t\t\t\tawait fetch(`${authPrefix}/signout`, {\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\tcredentials: 'include', // Send cookies\n\t\t\t\t})\n\t\t\t} catch {\n\t\t\t\t// Best-effort signout - continue even if server call fails\n\t\t\t}\n\n\t\t\t// Clear client-side state\n\t\t\tclearTokens()\n\n\t\t\t// Use safe redirect with validation to prevent XSS\n\t\t\tconst redirectUrl = options?.redirectUrl || afterSignOutUrl\n\t\t\tsafeRedirect(redirectUrl, { fallback: afterSignOutUrl || '/' })\n\t\t},\n\t\t[clearTokens, afterSignOutUrl, authPrefix],\n\t)\n\n\t/**\n\t * @deprecated ADR-3457 — always returns `null`. Session bearers are never\n\t * exported to browser JS. Use same-origin BaaS proxy (`/sylphx/…` with\n\t * `credentials: 'include'`) for Platform/BaaS APIs, or server\n\t * `getSessionToken()` in RSC/route handlers.\n\t */\n\tconst getToken = useCallback(async (): Promise<string | null> => {\n\t\tif (!authState.isSignedIn) {\n\t\t\treturn null\n\t\t}\n\t\t// Keep-alive HttpOnly cookies only; never return a bearer.\n\t\tawait tokenManager.ensureSession()\n\t\treturn null\n\t}, [authState.isSignedIn, tokenManager])\n\n\tconst switchOrganizationToken = useCallback(\n\t\tasync (orgId: string): Promise<void> => {\n\t\t\tif (!authState.isSignedIn) {\n\t\t\t\tthrow new Error('Not authenticated')\n\t\t\t}\n\n\t\t\tconst response = await fetch(`${authPrefix}/switch-org`, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\t\tcredentials: 'include',\n\t\t\t\tbody: JSON.stringify({ orgId }),\n\t\t\t})\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst data = (await response.json().catch(() => ({}))) as {\n\t\t\t\t\terror?: string\n\t\t\t\t\tmessage?: string\n\t\t\t\t}\n\t\t\t\tthrow new Error(data.error || data.message || 'Failed to switch organization')\n\t\t\t}\n\n\t\t\ttokenManager.invalidate()\n\t\t\tsetAuthState((prev) => ({\n\t\t\t\t...prev,\n\t\t\t\tisLoaded: true,\n\t\t\t\tisSignedIn: true,\n\t\t\t\terror: null,\n\t\t\t}))\n\n\t\t\tif (typeof window !== 'undefined' && typeof BroadcastChannel !== 'undefined') {\n\t\t\t\ttry {\n\t\t\t\t\tconst channel = new BroadcastChannel(`sylphx-auth-${appId}`)\n\t\t\t\t\tchannel.postMessage({ type: 'org-token-change' })\n\t\t\t\t\tchannel.close()\n\t\t\t\t} catch {\n\t\t\t\t\t// BroadcastChannel not supported\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[appId, authPrefix, authState.isSignedIn, tokenManager],\n\t)\n\n\tconst resetPassword = useCallback(\n\t\tasync (options: { token: string; newPassword: string }) => {\n\t\t\tawait api.post('/auth/reset-password', {\n\t\t\t\ttoken: options.token,\n\t\t\t\tpassword: options.newPassword,\n\t\t\t})\n\t\t},\n\t\t[api],\n\t)\n\n\tconst verifyEmail = useCallback(\n\t\tasync (options: { token: string }) => {\n\t\t\tawait api.post('/auth/verify-email', { token: options.token })\n\t\t},\n\t\t[api],\n\t)\n\n\tconst resendVerificationEmail = useCallback(\n\t\tasync (options: { email: string }) => {\n\t\t\tawait api.post('/auth/resend-verification', { email: options.email })\n\t\t},\n\t\t[api],\n\t)\n\n\tconst forgotPassword = useCallback(\n\t\tasync (options: { email: string; redirectUrl?: string }) => {\n\t\t\tconst redirectUrl = resolveRedirectUrl(options.redirectUrl ?? '/reset-password')\n\t\t\tawait api.post('/auth/forgot-password', {\n\t\t\t\temail: options.email,\n\t\t\t\t...(redirectUrl ? { redirectUrl } : {}),\n\t\t\t})\n\t\t},\n\t\t[api, resolveRedirectUrl],\n\t)\n\n\t// ============================================\n\t// Direct OAuth Methods (Firebase/Supabase pattern)\n\t// User goes directly to OAuth provider - no platform UI\n\t// ============================================\n\n\t/**\n\t * Clear OAuth error state.\n\t * Call this to reset error state before a retry.\n\t */\n\tconst clearOAuthError = useCallback(() => {\n\t\tsetAuthState((prev) => ({ ...prev, oauthError: null }))\n\t}, [])\n\n\t/**\n\t * Sign in with OAuth provider directly.\n\t * Fetches authorization URL from platform, then redirects user to OAuth provider.\n\t * No platform login UI is shown - user goes straight to Google/GitHub/etc.\n\t *\n\t * Uses PKCE (RFC 7636) for security - required for public clients per OAuth 2.1.\n\t *\n\t * SSR AUTHENTICATION:\n\t * OAuth callback is handled by middleware at /auth/callback.\n\t * Middleware exchanges the code and sets HTTP-only cookies server-side.\n\t * This ensures `auth()` works in Server Components.\n\t */\n\tconst signInWithOAuth = useCallback(\n\t\tasync (options: { provider: string; redirectUrl?: string; scopes?: string[] }) => {\n\t\t\tconst { provider, redirectUrl, scopes } = options\n\t\t\tconst finalDestination = resolveRedirectUrl(redirectUrl)\n\n\t\t\t// Set loading state and clear any previous OAuth error\n\t\t\tsetAuthState((prev) => ({\n\t\t\t\t...prev,\n\t\t\t\tisOAuthLoading: true,\n\t\t\t\toauthError: null,\n\t\t\t}))\n\n\t\t\ttry {\n\t\t\t\t// Generate PKCE codes (RFC 7636) - required for public clients\n\t\t\t\tconst { generatePKCE, storePKCEVerifier } = await import('../lib/pkce')\n\t\t\t\tconst pkce = await generatePKCE()\n\n\t\t\t\t// Store code_verifier for later use in token exchange\n\t\t\t\tstorePKCEVerifier(pkce.codeVerifier, appId)\n\n\t\t\t\t// Build the server-side callback URL that will handle code exchange\n\t\t\t\t// This ensures cookies are set for SSR authentication\n\t\t\t\t// Format: {authPrefix}/callback?redirect_to=<finalDestination>\n\t\t\t\tconst callbackUrl = new URL(`${authPrefix}/callback`, window.location.origin)\n\t\t\t\tcallbackUrl.searchParams.set('redirect_to', finalDestination)\n\t\t\t\tconst serverCallbackUri = callbackUrl.toString()\n\n\t\t\t\t// Fetch OAuth authorization URL from platform\n\t\t\t\tconst response = await fetch(`${platformUrl}${SDK_API_PATH}/oauth/authorize`, {\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t\t\t'x-app-secret': appId || '',\n\t\t\t\t\t},\n\t\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\t\tprovider,\n\t\t\t\t\t\tredirect_uri: serverCallbackUri,\n\t\t\t\t\t\tcode_challenge: pkce.codeChallenge,\n\t\t\t\t\t\tcode_challenge_method: pkce.codeChallengeMethod,\n\t\t\t\t\t\t// Custom scopes support (optional)\n\t\t\t\t\t\t...(scopes && scopes.length > 0 && { scopes }),\n\t\t\t\t\t}),\n\t\t\t\t})\n\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\t// Clear stored verifier on error\n\t\t\t\t\tconst { clearPKCEVerifier } = await import('../lib/pkce')\n\t\t\t\t\tclearPKCEVerifier(appId)\n\n\t\t\t\t\tconst error = await response.json().catch(() => ({ message: 'Failed to initiate OAuth' }))\n\t\t\t\t\tthrow new Error(error.message || `Failed to initiate ${provider} sign-in`)\n\t\t\t\t}\n\n\t\t\t\tconst { authorization_url } = await response.json()\n\n\t\t\t\t// Redirect directly to OAuth provider (no platform UI)\n\t\t\t\t// Note: isOAuthLoading stays true until page unloads (redirect)\n\t\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\t\twindow.location.href = authorization_url\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\t// Set error state and clear loading\n\t\t\t\tconst oauthError = error instanceof Error ? error : new Error('OAuth sign-in failed')\n\t\t\t\tsetAuthState((prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\tisOAuthLoading: false,\n\t\t\t\t\toauthError,\n\t\t\t\t}))\n\t\t\t\tthrow error\n\t\t\t}\n\t\t},\n\t\t[platformUrl, appId, resolveRedirectUrl, authPrefix],\n\t)\n\n\t// Convenience methods for common OAuth providers\n\tconst signInWithGoogle = useCallback(\n\t\t(redirectUrl?: string) => signInWithOAuth({ provider: 'google', redirectUrl }),\n\t\t[signInWithOAuth],\n\t)\n\n\tconst signInWithGithub = useCallback(\n\t\t(redirectUrl?: string) => signInWithOAuth({ provider: 'github', redirectUrl }),\n\t\t[signInWithOAuth],\n\t)\n\n\tconst signInWithApple = useCallback(\n\t\t(redirectUrl?: string) => signInWithOAuth({ provider: 'apple', redirectUrl }),\n\t\t[signInWithOAuth],\n\t)\n\n\tconst signInWithDiscord = useCallback(\n\t\t(redirectUrl?: string) => signInWithOAuth({ provider: 'discord', redirectUrl }),\n\t\t[signInWithOAuth],\n\t)\n\n\tconst signInWithTwitter = useCallback(\n\t\t(redirectUrl?: string) => signInWithOAuth({ provider: 'twitter', redirectUrl }),\n\t\t[signInWithOAuth],\n\t)\n\n\tconst signInWithMicrosoft = useCallback(\n\t\t(redirectUrl?: string) => signInWithOAuth({ provider: 'microsoft', redirectUrl }),\n\t\t[signInWithOAuth],\n\t)\n\n\t// ============================================\n\t// Magic Link (Passwordless) Methods\n\t// ============================================\n\n\t/**\n\t * Sign in with magic link (passwordless).\n\t * Sends an email with a one-time login link.\n\t * The user clicks the link to authenticate without a password.\n\t */\n\tconst signInWithMagicLink = useCallback(\n\t\tasync (options: { email: string; redirectUrl?: string }) => {\n\t\t\tconst { email, redirectUrl } = options\n\t\t\tconst resolvedRedirect = resolveRedirectUrl(redirectUrl)\n\n\t\t\tconst response = await fetch(`${platformUrl}${SDK_API_PATH}/auth/magic-link`, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t\t'x-app-secret': appId || '',\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\temail,\n\t\t\t\t\tredirectUrl: resolvedRedirect,\n\t\t\t\t}),\n\t\t\t})\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst error = await response.json().catch(() => ({ message: 'Failed to send magic link' }))\n\t\t\t\tthrow new Error(error.message || 'Failed to send magic link')\n\t\t\t}\n\n\t\t\t// Magic link sent successfully - no further action needed\n\t\t\t// User will click the link in their email to complete sign-in\n\t\t},\n\t\t[platformUrl, appId, resolveRedirectUrl],\n\t)\n\n\t// ============================================\n\t// Billing Actions\n\t// ============================================\n\tconst createCheckout = useCallback(\n\t\tasync (planSlug: string, interval: 'monthly' | 'annual' | 'lifetime'): Promise<string> => {\n\t\t\tif (!authState.user?.id) {\n\t\t\t\tthrow new Error('User must be authenticated to create checkout')\n\t\t\t}\n\t\t\tconst data = await api.post<{ checkoutUrl?: string }>('/billing/checkout', {\n\t\t\t\tuserId: authState.user.id,\n\t\t\t\tplanSlug,\n\t\t\t\tinterval,\n\t\t\t\tsuccessUrl: window.location.href,\n\t\t\t\tcancelUrl: window.location.href,\n\t\t\t})\n\t\t\treturn data.checkoutUrl ?? ''\n\t\t},\n\t\t[api, authState.user?.id],\n\t)\n\n\tconst openPortal = useCallback(async (): Promise<void> => {\n\t\tif (!authState.user?.id) {\n\t\t\tthrow new Error('User must be signed in to access billing portal')\n\t\t}\n\t\tconst data = await api.post<{ portalUrl: string }>('/billing/portal', {\n\t\t\tuserId: authState.user.id,\n\t\t\treturnUrl: window.location.href,\n\t\t})\n\t\twindow.location.href = data.portalUrl\n\t}, [api, authState.user?.id])\n\n\tconst refreshSubscription = useCallback(async (): Promise<void> => {\n\t\t// Use React Query invalidation to refetch subscription\n\t\tawait queryClient.invalidateQueries({\n\t\t\tqueryKey: ['sylphx', appId, 'subscription'],\n\t\t})\n\t}, [queryClient, appId])\n\n\t// ============================================\n\t// Offline Analytics Queue (Segment Pattern)\n\t// ============================================\n\t// Track online status for offline queuing\n\t// Hydration-safe: assume online initially (matches server rendering)\n\tconst [isOnline, setIsOnline] = useState(true)\n\n\t// Sync with actual navigator.onLine after mount\n\tuseEffect(() => {\n\t\tsetIsOnline(navigator.onLine)\n\n\t\tconst handleOnline = () => setIsOnline(true)\n\t\tconst handleOffline = () => setIsOnline(false)\n\n\t\twindow.addEventListener('online', handleOnline)\n\t\twindow.addEventListener('offline', handleOffline)\n\n\t\treturn () => {\n\t\t\twindow.removeEventListener('online', handleOnline)\n\t\t\twindow.removeEventListener('offline', handleOffline)\n\t\t}\n\t}, [])\n\n\t// Queue events to localStorage when offline\n\tconst queueToOfflineStorage = useCallback(\n\t\t(\n\t\t\tevents: Array<{\n\t\t\t\ttype: string\n\t\t\t\tdata: Record<string, unknown>\n\t\t\t\teventId: string\n\t\t\t}>,\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst existingQueue =\n\t\t\t\t\tstorage.getJSON<typeof events>(STORAGE_KEYS.OFFLINE_ANALYTICS_QUEUE) || []\n\t\t\t\tconst merged = [...existingQueue, ...events]\n\t\t\t\t// Keep only the most recent events to prevent storage bloat\n\t\t\t\tconst trimmed =\n\t\t\t\t\tmerged.length > ANALYTICS_QUEUE_LIMIT ? merged.slice(-ANALYTICS_QUEUE_LIMIT) : merged\n\t\t\t\tstorage.setJSON(STORAGE_KEYS.OFFLINE_ANALYTICS_QUEUE, trimmed)\n\t\t\t} catch {\n\t\t\t\t// localStorage might be full or unavailable - best effort\n\t\t\t}\n\t\t},\n\t\t[storage],\n\t)\n\n\t// Get offline queue from localStorage\n\tconst getOfflineQueue = useCallback(() => {\n\t\ttry {\n\t\t\treturn (\n\t\t\t\tstorage.getJSON<\n\t\t\t\t\tArray<{\n\t\t\t\t\t\ttype: string\n\t\t\t\t\t\tdata: Record<string, unknown>\n\t\t\t\t\t\teventId: string\n\t\t\t\t\t}>\n\t\t\t\t>(STORAGE_KEYS.OFFLINE_ANALYTICS_QUEUE) || []\n\t\t\t)\n\t\t} catch {\n\t\t\treturn []\n\t\t}\n\t}, [storage])\n\n\t// Clear offline queue\n\tconst clearOfflineQueue = useCallback(() => {\n\t\ttry {\n\t\t\tstorage.remove(STORAGE_KEYS.OFFLINE_ANALYTICS_QUEUE)\n\t\t} catch {\n\t\t\t// Best effort\n\t\t}\n\t}, [storage])\n\n\t// ============================================\n\t// Analytics Actions (with deduplication)\n\t// ============================================\n\n\tconst flushAnalytics = useCallback(async () => {\n\t\t// Include offline queue in flush\n\t\tconst offlineEvents = getOfflineQueue()\n\t\tconst memoryEvents = analyticsQueue.current\n\t\tconst allEvents = [...offlineEvents, ...memoryEvents]\n\n\t\tif (allEvents.length === 0) return\n\n\t\t// If offline, queue everything to localStorage and return\n\t\tif (!isOnline) {\n\t\t\tqueueToOfflineStorage(memoryEvents)\n\t\t\tanalyticsQueue.current = []\n\t\t\treturn\n\t\t}\n\n\t\t// Clear both queues optimistically\n\t\tanalyticsQueue.current = []\n\t\tclearOfflineQueue()\n\n\t\ttry {\n\t\t\tawait api.post('/analytics/track', {\n\t\t\t\tevents: allEvents.map(({ type, data }) => ({\n\t\t\t\t\tevent: type,\n\t\t\t\t\tproperties: data,\n\t\t\t\t\ttimestamp: data.timestamp as string | undefined,\n\t\t\t\t})),\n\t\t\t})\n\t\t\tsetAnalyticsError(null)\n\t\t} catch (error) {\n\t\t\tsetAnalyticsError(error instanceof Error ? error : new Error('Failed to send analytics'))\n\t\t\t// Re-queue on failure - to offline storage if we're now offline, otherwise memory\n\t\t\tif (!navigator.onLine) {\n\t\t\t\tqueueToOfflineStorage(allEvents)\n\t\t\t} else {\n\t\t\t\tconst requeued = [...allEvents, ...analyticsQueue.current]\n\t\t\t\tif (requeued.length > ANALYTICS_QUEUE_LIMIT) {\n\t\t\t\t\tanalyticsQueue.current = requeued.slice(-ANALYTICS_QUEUE_LIMIT)\n\t\t\t\t} else {\n\t\t\t\t\tanalyticsQueue.current = requeued\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}, [api, isOnline, getOfflineQueue, clearOfflineQueue, queueToOfflineStorage])\n\n\t// Flush when coming back online\n\tuseEffect(() => {\n\t\tif (isOnline) {\n\t\t\t// Small delay to ensure network is stable\n\t\t\tconst timeout = setTimeout(() => {\n\t\t\t\tflushAnalytics()\n\t\t\t}, 1000)\n\t\t\treturn () => clearTimeout(timeout)\n\t\t}\n\t}, [isOnline, flushAnalytics])\n\n\tconst enqueueAnalytics = useCallback(\n\t\t(type: string, data: Record<string, unknown>, eventId?: string) => {\n\t\t\t// Skip events with no user identifier — prevents empty-anonymousId\n\t\t\t// events during hydration before useEffect populates the real ID\n\t\t\tif (!anonymousId && !authState.user?.id) return\n\n\t\t\t// Deduplicate by eventId if provided\n\t\t\tconst id = eventId || `${type}_${Date.now()}_${Math.random().toString(36).slice(2)}`\n\t\t\tif (trackedEventIds.current.has(id)) {\n\t\t\t\treturn // Already tracked\n\t\t\t}\n\t\t\ttrackedEventIds.current.add(id)\n\n\t\t\t// Clean up old event IDs\n\t\t\tif (trackedEventIds.current.size > ANALYTICS_MAX_TRACKED_EVENT_IDS) {\n\t\t\t\tconst ids = Array.from(trackedEventIds.current)\n\t\t\t\ttrackedEventIds.current = new Set(ids.slice(-ANALYTICS_TRACKED_IDS_KEEP))\n\t\t\t}\n\n\t\t\tif (analyticsQueue.current.length >= ANALYTICS_QUEUE_LIMIT) {\n\t\t\t\tanalyticsQueue.current = analyticsQueue.current.slice(1)\n\t\t\t}\n\n\t\t\tanalyticsQueue.current.push({\n\t\t\t\ttype,\n\t\t\t\tdata: {\n\t\t\t\t\t...data,\n\t\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\t\tuserId: authState.user?.id,\n\t\t\t\t\tanonymousId,\n\t\t\t\t},\n\t\t\t\teventId: id,\n\t\t\t})\n\n\t\t\tif (analyticsQueue.current.length >= 10) {\n\t\t\t\tflushAnalytics()\n\t\t\t} else {\n\t\t\t\tif (flushTimeoutRef.current) {\n\t\t\t\t\tclearTimeout(flushTimeoutRef.current)\n\t\t\t\t}\n\t\t\t\tflushTimeoutRef.current = setTimeout(flushAnalytics, ANALYTICS_FLUSH_TIMEOUT_MS)\n\t\t\t}\n\t\t},\n\t\t[authState.user?.id, anonymousId, flushAnalytics],\n\t)\n\n\tconst track = useCallback(\n\t\tasync (\n\t\t\tevent: string,\n\t\t\tproperties?: Record<string, unknown>,\n\t\t\toptions?: import('./platform-context').TrackOptions,\n\t\t) => {\n\t\t\t// Don't track auto-events if they're disabled\n\t\t\tconst autoEvents = ['$pageview', '$login', '$signup', '$logout', '$purchase']\n\t\t\tif (autoEvents.includes(event)) {\n\t\t\t\tconst configKey = event.slice(1) as keyof typeof autoTrackConfig\n\t\t\t\tif (!autoTrackConfig[configKey]) {\n\t\t\t\t\treturn // Auto-tracking disabled for this event\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Auto-enrich conversion data with click IDs and user info\n\t\t\tlet enrichedConversion = options?.conversion\n\t\t\tif (options?.conversion || options?.destinations) {\n\t\t\t\t// Get current click IDs from storage (in case they were updated)\n\t\t\t\tconst currentClickIds = getStoredClickIds(storage) || clickIds\n\n\t\t\t\tenrichedConversion = {\n\t\t\t\t\t// User-provided conversion data takes precedence\n\t\t\t\t\t...options?.conversion,\n\t\t\t\t\t// Auto-fill click ID if not explicitly provided\n\t\t\t\t\tclickId: options?.conversion?.clickId ?? getPrimaryClickId(currentClickIds),\n\t\t\t\t\t// Auto-fill user data from auth state (use ?? to respect explicit falsy values)\n\t\t\t\t\tuserEmail: options?.conversion?.userEmail ?? authState.user?.email,\n\t\t\t\t\tuserFirstName: options?.conversion?.userFirstName ?? authState.user?.name?.split(' ')[0],\n\t\t\t\t\tuserLastName:\n\t\t\t\t\t\toptions?.conversion?.userLastName ??\n\t\t\t\t\t\t(authState.user?.name?.split(' ').slice(1).join(' ') || undefined),\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tenqueueAnalytics('track', {\n\t\t\t\tevent,\n\t\t\t\tproperties: properties || {},\n\t\t\t\t// Destination options (passed to server)\n\t\t\t\tdestinations: options?.destinations,\n\t\t\t\tskipDestinations: options?.skipDestinations,\n\t\t\t\tconversion: enrichedConversion,\n\t\t\t})\n\t\t},\n\t\t[enqueueAnalytics, autoTrackConfig, storage, clickIds, authState.user],\n\t)\n\n\tconst page = useCallback(\n\t\tasync (name: string, properties?: Record<string, unknown>) => {\n\t\t\tenqueueAnalytics('page', { name, properties: properties || {} })\n\t\t},\n\t\t[enqueueAnalytics],\n\t)\n\n\tconst identify = useCallback(\n\t\tasync (traits?: Record<string, unknown>) => {\n\t\t\tif (!authState.user?.id) return\n\t\t\tenqueueAnalytics('identify', {\n\t\t\t\tuserId: authState.user.id,\n\t\t\t\ttraits: traits || {},\n\t\t\t})\n\t\t},\n\t\t[authState.user?.id, enqueueAnalytics],\n\t)\n\n\tconst queryAnalytics = useCallback(\n\t\tasync (\n\t\t\tanalyticsQuery: import('./platform-context').AnalyticsQuery,\n\t\t): Promise<import('./platform-context').AnalyticsQueryResult> => {\n\t\t\ttry {\n\t\t\t\tconst result = await api.post<import('./platform-context').AnalyticsQueryResult>(\n\t\t\t\t\t'/analytics/query',\n\t\t\t\t\tanalyticsQuery,\n\t\t\t\t)\n\t\t\t\treturn {\n\t\t\t\t\tdata: result.data,\n\t\t\t\t\ttotal: result.total,\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Analytics query failed')\n\t\t\t\tsetAnalyticsError(error)\n\t\t\t\tthrow error\n\t\t\t}\n\t\t},\n\t\t[api],\n\t)\n\n\t// ============================================\n\t// Auto-Instrumented Events (with deduplication)\n\t// ============================================\n\tconst prevAuthStateRef = useRef<AuthState | null>(null)\n\tconst prevSubscriptionRef = useRef<Subscription | null>(null)\n\tconst hasTrackedInitialPageview = useRef(false)\n\n\t// Auto-track $pageview\n\t// Deferred until anonymousId or userId is available (avoids empty-identifier events)\n\tuseEffect(() => {\n\t\tif (!autoTrackConfig.pageview || hasTrackedInitialPageview.current) return\n\t\t// Wait for a stable user identifier before tracking\n\t\tif (!anonymousId && !authState.user?.id) return\n\n\t\thasTrackedInitialPageview.current = true\n\t\tconst pageviewId = `pageview_${window.location.pathname}_${Date.now()}`\n\t\tenqueueAnalytics(\n\t\t\t'page',\n\t\t\t{\n\t\t\t\tname: '$pageview',\n\t\t\t\tproperties: {\n\t\t\t\t\turl: window.location.href,\n\t\t\t\t\tpath: window.location.pathname,\n\t\t\t\t\treferrer: document.referrer,\n\t\t\t\t\ttitle: document.title,\n\t\t\t\t},\n\t\t\t},\n\t\t\tpageviewId,\n\t\t)\n\t}, [autoTrackConfig.pageview, enqueueAnalytics, anonymousId, authState.user?.id])\n\n\t// Auto-track route changes\n\tuseEffect(() => {\n\t\tif (!autoTrackConfig.pageview || typeof window === 'undefined') return\n\n\t\tconst handleRouteChange = () => {\n\t\t\tconst pageviewId = `pageview_${window.location.pathname}_${Date.now()}`\n\t\t\tenqueueAnalytics(\n\t\t\t\t'page',\n\t\t\t\t{\n\t\t\t\t\tname: '$pageview',\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\turl: window.location.href,\n\t\t\t\t\t\tpath: window.location.pathname,\n\t\t\t\t\t\treferrer: document.referrer,\n\t\t\t\t\t\ttitle: document.title,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tpageviewId,\n\t\t\t)\n\t\t}\n\n\t\twindow.addEventListener('popstate', handleRouteChange)\n\t\treturn () => window.removeEventListener('popstate', handleRouteChange)\n\t}, [autoTrackConfig.pageview, enqueueAnalytics])\n\n\t// Auto-track auth events\n\tuseEffect(() => {\n\t\tconst prevState = prevAuthStateRef.current\n\t\tconst currentState = authState\n\n\t\t// Detect sign-in transition\n\t\tif (prevState && !prevState.isSignedIn && currentState.isSignedIn && currentState.user) {\n\t\t\tconst userCreatedAt = currentState.user.createdAt\n\t\t\t\t? new Date(currentState.user.createdAt).getTime()\n\t\t\t\t: 0\n\t\t\tconst isNewUser = Date.now() - userCreatedAt < NEW_USER_THRESHOLD_MS\n\n\t\t\tconst eventId = `auth_${currentState.user.id}_${isNewUser ? 'signup' : 'login'}_${Date.now()}`\n\n\t\t\t// Get click IDs for conversion attribution\n\t\t\tconst currentClickIds = getStoredClickIds(storage) || clickIds\n\n\t\t\tif (isNewUser && autoTrackConfig.signup) {\n\t\t\t\tenqueueAnalytics(\n\t\t\t\t\t'track',\n\t\t\t\t\t{\n\t\t\t\t\t\tevent: '$signup',\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tuserId: currentState.user.id,\n\t\t\t\t\t\t\temail: currentState.user.email,\n\t\t\t\t\t\t\tmethod: 'platform',\n\t\t\t\t\t\t},\n\t\t\t\t\t\t// Auto-forward signups as conversions (common for lead gen campaigns)\n\t\t\t\t\t\tconversion: {\n\t\t\t\t\t\t\tclickId: getPrimaryClickId(currentClickIds),\n\t\t\t\t\t\t\tuserEmail: currentState.user.email,\n\t\t\t\t\t\t\tuserFirstName: currentState.user.name?.split(' ')[0],\n\t\t\t\t\t\t\tuserLastName: currentState.user.name?.split(' ').slice(1).join(' ') || undefined,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\teventId,\n\t\t\t\t)\n\t\t\t} else if (!isNewUser && autoTrackConfig.login) {\n\t\t\t\tenqueueAnalytics(\n\t\t\t\t\t'track',\n\t\t\t\t\t{\n\t\t\t\t\t\tevent: '$login',\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tuserId: currentState.user.id,\n\t\t\t\t\t\t\temail: currentState.user.email,\n\t\t\t\t\t\t\tmethod: 'platform',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\teventId,\n\t\t\t\t)\n\t\t\t}\n\n\t\t\t// Identify user\n\t\t\tenqueueAnalytics('identify', {\n\t\t\t\tuserId: currentState.user.id,\n\t\t\t\ttraits: {\n\t\t\t\t\temail: currentState.user.email,\n\t\t\t\t\tname: currentState.user.name,\n\t\t\t\t\timage: currentState.user.image,\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\n\t\t// Detect sign-out\n\t\tif (prevState?.isSignedIn && !currentState.isSignedIn && autoTrackConfig.logout) {\n\t\t\tconst eventId = `auth_${prevState.user?.id}_logout_${Date.now()}`\n\t\t\tenqueueAnalytics(\n\t\t\t\t'track',\n\t\t\t\t{\n\t\t\t\t\tevent: '$logout',\n\t\t\t\t\tproperties: { userId: prevState.user?.id },\n\t\t\t\t},\n\t\t\t\teventId,\n\t\t\t)\n\t\t}\n\n\t\tprevAuthStateRef.current = currentState\n\t}, [authState, enqueueAnalytics, autoTrackConfig, storage, clickIds])\n\n\t// Auto-track subscription events with conversion data\n\tuseEffect(() => {\n\t\tconst prevSub = prevSubscriptionRef.current\n\t\tconst currentSub = subscription\n\n\t\tif (\n\t\t\tautoTrackConfig.purchase &&\n\t\t\tcurrentSub &&\n\t\t\t(currentSub.status === 'active' || currentSub.status === 'trialing') &&\n\t\t\t(!prevSub || (prevSub.status !== 'active' && prevSub.status !== 'trialing'))\n\t\t) {\n\t\t\tconst eventId = `purchase_${currentSub.id}_${Date.now()}`\n\n\t\t\t// Auto-enrich with conversion data for ad platform attribution\n\t\t\tconst currentClickIds = getStoredClickIds(storage) || clickIds\n\n\t\t\tenqueueAnalytics(\n\t\t\t\t'track',\n\t\t\t\t{\n\t\t\t\t\tevent: '$purchase',\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tplanId: currentSub.planId,\n\t\t\t\t\t\tplanSlug: currentSub.planSlug,\n\t\t\t\t\t\tinterval: currentSub.interval,\n\t\t\t\t\t\tisTrialing: currentSub.status === 'trialing',\n\t\t\t\t\t},\n\t\t\t\t\t// Auto-forward to all configured destinations\n\t\t\t\t\t// (destinations with auto-forward + 'purchase' in event filter will receive this)\n\t\t\t\t\tconversion: {\n\t\t\t\t\t\tclickId: getPrimaryClickId(currentClickIds),\n\t\t\t\t\t\t// Note: Value/currency not in Subscription type - will be enriched server-side if available\n\t\t\t\t\t\torderId: currentSub.id,\n\t\t\t\t\t\tuserEmail: authState.user?.email,\n\t\t\t\t\t\tuserFirstName: authState.user?.name?.split(' ')[0],\n\t\t\t\t\t\tuserLastName: authState.user?.name?.split(' ').slice(1).join(' ') || undefined,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\teventId,\n\t\t\t)\n\t\t}\n\n\t\tprevSubscriptionRef.current = currentSub\n\t}, [subscription, enqueueAnalytics, autoTrackConfig.purchase, storage, clickIds, authState.user])\n\n\t// ============================================\n\t// Push Notification Actions\n\t// ============================================\n\tconst subscribePush = useCallback(async (): Promise<boolean> => {\n\t\tif (!pushSupported || !vapidPublicKey) return false\n\n\t\ttry {\n\t\t\tconst registration = await navigator.serviceWorker.ready\n\t\t\tconst sub = await registration.pushManager.subscribe({\n\t\t\t\tuserVisibleOnly: true,\n\t\t\t\tapplicationServerKey: vapidPublicKey,\n\t\t\t})\n\n\t\t\tconst json = sub.toJSON()\n\n\t\t\tawait api.post('/notifications/register', {\n\t\t\t\tsubscription: {\n\t\t\t\t\tendpoint: json.endpoint!,\n\t\t\t\t\tkeys: {\n\t\t\t\t\t\tp256dh: json.keys?.p256dh ?? '',\n\t\t\t\t\t\tauth: json.keys?.auth ?? '',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t})\n\n\t\t\tsetPushSubscribed(true)\n\t\t\treturn true\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}, [pushSupported, vapidPublicKey, api])\n\n\tconst unsubscribePush = useCallback(async (): Promise<void> => {\n\t\ttry {\n\t\t\tconst registration = await navigator.serviceWorker.ready\n\t\t\tconst sub = await registration.pushManager.getSubscription()\n\n\t\t\tif (sub) {\n\t\t\t\tawait api.post('/notifications/unregister', { endpoint: sub.endpoint })\n\t\t\t\tawait sub.unsubscribe()\n\t\t\t}\n\n\t\t\tsetPushSubscribed(false)\n\t\t} catch {\n\t\t\t// Push unsubscribe is best-effort\n\t\t}\n\t}, [api])\n\n\tconst updatePushPreferences = useCallback(\n\t\tasync (prefs: { enabled?: boolean; categories?: Record<string, boolean> }): Promise<void> => {\n\t\t\t// Web push preference updates are handled by subscribe/unsubscribe\n\t\t\t// Categories are managed via in-app message preferences\n\t\t\tif (prefs.enabled === false) {\n\t\t\t\tawait unsubscribePush()\n\t\t\t}\n\t\t\t// Optimistic update for categories via React Query\n\t\t\tif (prefs.categories && pushPreferences) {\n\t\t\t\tqueryClient.setQueryData<PushPreferences>(['sylphx', appId, 'pushPreferences'], (old) => {\n\t\t\t\t\tif (!old) return old\n\t\t\t\t\treturn { ...old, categories: prefs.categories! }\n\t\t\t\t})\n\t\t\t}\n\t\t},\n\t\t[pushPreferences, unsubscribePush, queryClient, appId],\n\t)\n\n\t// ============================================\n\t// Mobile Push Notification Actions - React Query cache updates\n\t// ============================================\n\tconst mobilePushQueryKey = ['sylphx', appId, 'mobilePush']\n\n\tconst registerMobileDevice = useCallback(\n\t\tasync (options: {\n\t\t\tplatform: MobilePushPlatform\n\t\t\ttoken: string\n\t\t\tdeviceId?: string\n\t\t\tdeviceName?: string\n\t\t\tappVersion?: string\n\t\t\tosVersion?: string\n\t\t}): Promise<{ success: boolean; tokenId: string }> => {\n\t\t\t// Cast platform to the API expected type (web devices are read-only)\n\t\t\tconst result = await api.post<{ success: boolean; tokenId: string }>(\n\t\t\t\t'/notifications/mobile/register',\n\t\t\t\t{\n\t\t\t\t\t...options,\n\t\t\t\t\tplatform: options.platform as 'ios' | 'android',\n\t\t\t\t},\n\t\t\t)\n\t\t\t// Refresh mobile push data via React Query\n\t\t\tvoid queryClient.invalidateQueries({ queryKey: mobilePushQueryKey })\n\t\t\treturn result\n\t\t},\n\t\t// biome-ignore lint/correctness/useExhaustiveDependencies: query key is stable\n\t\t[api, queryClient, mobilePushQueryKey],\n\t)\n\n\tconst unregisterMobileDevice = useCallback(\n\t\tasync (token: string): Promise<void> => {\n\t\t\tawait api.post('/notifications/mobile/unregister', { token })\n\t\t\t// Refresh mobile push data via React Query\n\t\t\tvoid queryClient.invalidateQueries({ queryKey: mobilePushQueryKey })\n\t\t},\n\t\t// biome-ignore lint/correctness/useExhaustiveDependencies: query key is stable\n\t\t[api, queryClient, mobilePushQueryKey],\n\t)\n\n\tconst getMobilePushPreferences = useCallback(async (): Promise<MobilePushPreferences> => {\n\t\t// Trigger refetch via React Query and wait for fresh data\n\t\tawait queryClient.invalidateQueries({ queryKey: mobilePushQueryKey })\n\t\tconst data = queryClient.getQueryData<{\n\t\t\tconfig: MobilePushConfig\n\t\t\tpreferences: MobilePushPreferences\n\t\t}>(mobilePushQueryKey)\n\t\tif (!data?.preferences) {\n\t\t\tthrow new Error('Failed to get mobile push preferences')\n\t\t}\n\t\treturn data.preferences\n\t\t// biome-ignore lint/correctness/useExhaustiveDependencies: query key is stable\n\t}, [queryClient, mobilePushQueryKey])\n\n\t// ============================================\n\t// Referral Actions\n\t// ============================================\n\tconst copyReferralCode = useCallback(async (): Promise<void> => {\n\t\tif (referralCode) {\n\t\t\tawait navigator.clipboard.writeText(referralCode)\n\t\t}\n\t}, [referralCode])\n\n\tconst regenerateReferralCode = useCallback(async (): Promise<string> => {\n\t\tconst data = await api.post<{ code: string }>('/referrals/code/regenerate')\n\t\t// Invalidate referrals query to refetch the new code\n\t\tvoid queryClient.invalidateQueries({\n\t\t\tqueryKey: ['sylphx', appId, 'referrals'],\n\t\t})\n\t\treturn data.code\n\t}, [api, queryClient, appId])\n\n\tconst redeemReferralCode = useCallback(\n\t\tasync (\n\t\t\tcode: string,\n\t\t\t_defaults?: import('../referrals').ReferralRewardDefaults,\n\t\t): Promise<import('../referrals').RedeemResult> => {\n\t\t\t// Note: defaults parameter is for future use when server supports auto-discovery\n\t\t\t// Currently the server uses Console-configured rewards\n\t\t\treturn api.post<import('../referrals').RedeemResult>('/referrals/redeem', { code })\n\t\t},\n\t\t[api],\n\t)\n\n\tconst getReferralLeaderboard = useCallback(\n\t\tasync (options?: {\n\t\t\tlimit?: number\n\t\t\tperiod?: 'all' | 'month' | 'week'\n\t\t}): Promise<{\n\t\t\tperiod: 'all' | 'month' | 'week'\n\t\t\tentries: Array<{\n\t\t\t\trank: number\n\t\t\t\tuserId: string | null\n\t\t\t\t/** Masked username for privacy */\n\t\t\t\tname: string\n\t\t\t\tavatarUrl: string | null\n\t\t\t\t/** Number of successful referrals */\n\t\t\t\treferrals: number\n\t\t\t\ttotalReferrals: number\n\t\t\t\tisCurrentUser: boolean\n\t\t\t}>\n\t\t\tcurrentUserRank: number | null\n\t\t}> => {\n\t\t\treturn api.get('/referrals/leaderboard', {\n\t\t\t\tlimit: options?.limit?.toString(),\n\t\t\t\tperiod: options?.period,\n\t\t\t})\n\t\t},\n\t\t[api],\n\t)\n\n\t// ============================================\n\t// Engagement Actions (Streaks, Leaderboards, Achievements)\n\t// ============================================\n\tconst getStreak = useCallback(\n\t\tasync (\n\t\t\tstreakId: string,\n\t\t\tdefaults?: StreakDefaults,\n\t\t\tuserTimezone?: string,\n\t\t): Promise<StreakState> => {\n\t\t\tif (!authState.user?.id) {\n\t\t\t\tthrow new Error('User must be authenticated to get streak')\n\t\t\t}\n\t\t\treturn api.get<StreakState>(`/engagement/streaks/${streakId}`, {\n\t\t\t\tuserId: authState.user.id,\n\t\t\t\tdefaults: defaults ? JSON.stringify(defaults) : undefined,\n\t\t\t\tuserTimezone,\n\t\t\t})\n\t\t},\n\t\t[api, authState.user?.id],\n\t)\n\n\tconst recordStreakActivity = useCallback(\n\t\tasync (\n\t\t\tstreakId: string,\n\t\t\tmetadata?: Record<string, unknown>,\n\t\t\tdefaults?: StreakDefaults,\n\t\t): Promise<RecordActivityResult> => {\n\t\t\tif (!authState.user?.id) {\n\t\t\t\tthrow new Error('User must be authenticated to record activity')\n\t\t\t}\n\t\t\treturn api.post<RecordActivityResult>(`/engagement/streaks/${streakId}/activity`, {\n\t\t\t\tuserId: authState.user.id,\n\t\t\t\tmetadata,\n\t\t\t\tdefaults,\n\t\t\t})\n\t\t},\n\t\t[api, authState.user?.id],\n\t)\n\n\tconst recoverStreak = useCallback(\n\t\tasync (streakId: string): Promise<{ success: boolean; streak: StreakState }> => {\n\t\t\tif (!authState.user?.id) {\n\t\t\t\tthrow new Error('User must be authenticated to recover streak')\n\t\t\t}\n\t\t\treturn api.post<{ success: boolean; streak: StreakState }>(\n\t\t\t\t`/engagement/streaks/${streakId}/recover`,\n\t\t\t\t{ userId: authState.user.id },\n\t\t\t)\n\t\t},\n\t\t[api, authState.user?.id],\n\t)\n\n\tconst getEngagementLeaderboard = useCallback(\n\t\tasync (\n\t\t\tleaderboardId: string,\n\t\t\toptions?: LeaderboardQueryOptions & {\n\t\t\t\tdefaults?: LeaderboardDefaults\n\t\t\t\tperiod?: string\n\t\t\t},\n\t\t): Promise<LeaderboardResult> => {\n\t\t\treturn api.get<LeaderboardResult>(`/engagement/leaderboards/${leaderboardId}`, {\n\t\t\t\tuserId: authState.user?.id ?? undefined,\n\t\t\t\tlimit: options?.limit?.toString(),\n\t\t\t\toffset: options?.offset?.toString(),\n\t\t\t\tperiod: options?.period,\n\t\t\t})\n\t\t},\n\t\t[api, authState.user?.id],\n\t)\n\n\tconst submitScore = useCallback(\n\t\tasync (\n\t\t\tleaderboardId: string,\n\t\t\tvalue: number,\n\t\t\tmetadata?: Record<string, unknown>,\n\t\t\tdefaults?: LeaderboardDefaults,\n\t\t): Promise<SubmitScoreResult> => {\n\t\t\tif (!authState.user?.id) {\n\t\t\t\tthrow new Error('User must be authenticated to submit score')\n\t\t\t}\n\t\t\treturn api.post<SubmitScoreResult>(`/engagement/leaderboards/${leaderboardId}/score`, {\n\t\t\t\tvalue,\n\t\t\t\tuserId: authState.user.id,\n\t\t\t\tmetadata,\n\t\t\t\tdefaults,\n\t\t\t})\n\t\t},\n\t\t[api, authState.user?.id],\n\t)\n\n\tconst getAchievements = useCallback(async (): Promise<UserAchievement[]> => {\n\t\tif (!authState.user?.id) {\n\t\t\tthrow new Error('User must be authenticated to get achievements')\n\t\t}\n\t\treturn api.get<UserAchievement[]>('/engagement/achievements', {\n\t\t\tuserId: authState.user.id,\n\t\t})\n\t}, [api, authState.user?.id])\n\n\tconst unlockAchievement = useCallback(\n\t\tasync (\n\t\t\tachievementId: string,\n\t\t\tdefaults?: AchievementDefaults,\n\t\t): Promise<AchievementUnlockEvent> => {\n\t\t\tif (!authState.user?.id) {\n\t\t\t\tthrow new Error('User must be authenticated to unlock achievement')\n\t\t\t}\n\t\t\treturn api.post<AchievementUnlockEvent>(`/engagement/achievements/${achievementId}/unlock`, {\n\t\t\t\tuserId: authState.user.id,\n\t\t\t\tdefaults,\n\t\t\t})\n\t\t},\n\t\t[api, authState.user?.id],\n\t)\n\n\tconst incrementAchievementProgress = useCallback(\n\t\tasync (\n\t\t\tachievementId: string,\n\t\t\tamount: number,\n\t\t\tdefaults?: AchievementDefaults,\n\t\t): Promise<UserAchievement> => {\n\t\t\tif (!authState.user?.id) {\n\t\t\t\tthrow new Error('User must be authenticated to increment progress')\n\t\t\t}\n\t\t\treturn api.post<UserAchievement>(`/engagement/achievements/${achievementId}/progress`, {\n\t\t\t\tamount,\n\t\t\t\tuserId: authState.user.id,\n\t\t\t\tdefaults,\n\t\t\t})\n\t\t},\n\t\t[api, authState.user?.id],\n\t)\n\n\t// ============================================\n\t// In-App Messages (Inbox) Actions - React Query optimistic updates\n\t// ============================================\n\ttype InboxQueryData = {\n\t\tmessages: InAppMessageWithReadStatus[]\n\t\tunreadCount: number\n\t\tpreferences: InboxPreferences | null\n\t}\n\tconst inboxQueryKey = ['sylphx', appId, 'inbox']\n\n\tconst refreshInbox = useCallback(async (): Promise<void> => {\n\t\tawait queryClient.invalidateQueries({ queryKey: inboxQueryKey })\n\t\t// biome-ignore lint/correctness/useExhaustiveDependencies: query key is stable\n\t}, [queryClient, inboxQueryKey])\n\n\tconst markInboxMessageAsRead = useCallback(\n\t\tasync (messageId: string): Promise<void> => {\n\t\t\t// Optimistic update via React Query\n\t\t\tconst previousData = queryClient.getQueryData<InboxQueryData>(inboxQueryKey)\n\t\t\tqueryClient.setQueryData<InboxQueryData>(inboxQueryKey, (old) => {\n\t\t\t\tif (!old) return old\n\t\t\t\treturn {\n\t\t\t\t\t...old,\n\t\t\t\t\tmessages: old.messages.map((m) =>\n\t\t\t\t\t\tm.id === messageId ? { ...m, isRead: true, readAt: new Date().toISOString() } : m,\n\t\t\t\t\t),\n\t\t\t\t\tunreadCount: Math.max(0, old.unreadCount - 1),\n\t\t\t\t}\n\t\t\t})\n\t\t\ttry {\n\t\t\t\tawait api.post(`/notifications/messages/${messageId}/read`)\n\t\t\t} catch (err) {\n\t\t\t\t// Rollback on error\n\t\t\t\tif (previousData) queryClient.setQueryData(inboxQueryKey, previousData)\n\t\t\t\tthrow err\n\t\t\t}\n\t\t},\n\t\t// biome-ignore lint/correctness/useExhaustiveDependencies: query key is stable\n\t\t[api, queryClient, inboxQueryKey],\n\t)\n\n\tconst markAllInboxMessagesAsRead = useCallback(async (): Promise<void> => {\n\t\t// Optimistic update via React Query\n\t\tconst previousData = queryClient.getQueryData<InboxQueryData>(inboxQueryKey)\n\t\tqueryClient.setQueryData<InboxQueryData>(inboxQueryKey, (old) => {\n\t\t\tif (!old) return old\n\t\t\treturn {\n\t\t\t\t...old,\n\t\t\t\tmessages: old.messages.map((m) => ({\n\t\t\t\t\t...m,\n\t\t\t\t\tisRead: true,\n\t\t\t\t\treadAt: new Date().toISOString(),\n\t\t\t\t})),\n\t\t\t\tunreadCount: 0,\n\t\t\t}\n\t\t})\n\t\ttry {\n\t\t\tawait api.post('/notifications/messages/mark-all-read')\n\t\t} catch (err) {\n\t\t\t// Rollback on error\n\t\t\tif (previousData) queryClient.setQueryData(inboxQueryKey, previousData)\n\t\t\tthrow err\n\t\t}\n\t\t// biome-ignore lint/correctness/useExhaustiveDependencies: query key is stable\n\t}, [api, queryClient, inboxQueryKey])\n\n\tconst dismissInboxMessage = useCallback(\n\t\tasync (messageId: string): Promise<void> => {\n\t\t\t// Optimistic update via React Query - remove from list\n\t\t\tconst previousData = queryClient.getQueryData<InboxQueryData>(inboxQueryKey)\n\t\t\tqueryClient.setQueryData<InboxQueryData>(inboxQueryKey, (old) => {\n\t\t\t\tif (!old) return old\n\t\t\t\treturn {\n\t\t\t\t\t...old,\n\t\t\t\t\tmessages: old.messages.filter((m) => m.id !== messageId),\n\t\t\t\t}\n\t\t\t})\n\t\t\ttry {\n\t\t\t\tawait api.post(`/notifications/messages/${messageId}/dismiss`)\n\t\t\t} catch (err) {\n\t\t\t\t// Rollback on error\n\t\t\t\tif (previousData) queryClient.setQueryData(inboxQueryKey, previousData)\n\t\t\t\tthrow err\n\t\t\t}\n\t\t},\n\t\t// biome-ignore lint/correctness/useExhaustiveDependencies: query key is stable\n\t\t[api, queryClient, inboxQueryKey],\n\t)\n\n\tconst recordInboxMessageClick = useCallback(\n\t\tasync (messageId: string, action: 'primary' | 'secondary'): Promise<void> => {\n\t\t\t// Optimistic update via React Query - mark as read\n\t\t\tqueryClient.setQueryData<InboxQueryData>(inboxQueryKey, (old) => {\n\t\t\t\tif (!old) return old\n\t\t\t\treturn {\n\t\t\t\t\t...old,\n\t\t\t\t\tmessages: old.messages.map((m) =>\n\t\t\t\t\t\tm.id === messageId ? { ...m, isRead: true, readAt: new Date().toISOString() } : m,\n\t\t\t\t\t),\n\t\t\t\t}\n\t\t\t})\n\t\t\ttry {\n\t\t\t\tawait api.post(`/notifications/messages/${messageId}/click`, {\n\t\t\t\t\taction,\n\t\t\t\t})\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error('Failed to record message click:', err)\n\t\t\t\t// Don't throw - this is a non-critical action\n\t\t\t}\n\t\t},\n\t\t// biome-ignore lint/correctness/useExhaustiveDependencies: query key is stable\n\t\t[api, queryClient, inboxQueryKey],\n\t)\n\n\tconst updateInboxPreferences = useCallback(\n\t\tasync (prefs: {\n\t\t\tenabled?: boolean\n\t\t\tmutedTopics?: string[]\n\t\t\thighPriorityOnly?: boolean\n\t\t}): Promise<void> => {\n\t\t\t// Optimistic update via React Query\n\t\t\tconst previousData = queryClient.getQueryData<InboxQueryData>(inboxQueryKey)\n\t\t\tqueryClient.setQueryData<InboxQueryData>(inboxQueryKey, (old) => {\n\t\t\t\tif (!old) return old\n\t\t\t\treturn {\n\t\t\t\t\t...old,\n\t\t\t\t\tpreferences: old.preferences ? { ...old.preferences, ...prefs } : null,\n\t\t\t\t}\n\t\t\t})\n\t\t\ttry {\n\t\t\t\tawait api.put('/notifications/messages/preferences', prefs)\n\t\t\t} catch (err) {\n\t\t\t\t// Rollback on error\n\t\t\t\tif (previousData) queryClient.setQueryData(inboxQueryKey, previousData)\n\t\t\t\tthrow err\n\t\t\t}\n\t\t},\n\t\t// biome-ignore lint/correctness/useExhaustiveDependencies: query key is stable\n\t\t[api, queryClient, inboxQueryKey],\n\t)\n\n\t// ============================================\n\t// AI Context Value (delegated to factory)\n\t// ============================================\n\tconst aiValue: AIContextValue = useMemo(\n\t\t() => createAIValue({ api, platformUrl, appId }),\n\t\t[api, platformUrl, appId],\n\t)\n\n\t// ============================================\n\t// Jobs Context Value (delegated to factory)\n\t// ============================================\n\tconst tasksValue: TasksContextValue = useMemo(() => createTasksValue({ api }), [api])\n\n\t// ============================================\n\t// Monitoring Context Value (delegated to factory)\n\t// ============================================\n\tconst monitoringValue: MonitoringContextValue = useMemo(\n\t\t() => createMonitoringValue({ api }),\n\t\t[api],\n\t)\n\n\t// ============================================\n\t// Consent Context Value (delegated to factory)\n\t// ============================================\n\tconst consentValue: ConsentContextValue = useMemo(\n\t\t() =>\n\t\t\tcreateConsentValue({\n\t\t\t\tapi,\n\t\t\t\tanonymousId,\n\t\t\t\tuserId: authState.user?.id ?? null,\n\t\t\t\tconfig,\n\t\t\t}),\n\t\t[api, anonymousId, authState.user?.id, config],\n\t)\n\n\t// Storage no longer uses a context value — `useStorage` (ADR-100) builds\n\t// its config directly from `PlatformContext` + `AuthContext` via the\n\t// `useSdkConfig` helper in `storage-hooks.ts`.\n\n\t// ============================================\n\t// Newsletter Context Value (delegated to factory)\n\t// ============================================\n\tconst newsletterValue: NewsletterContextValue = useMemo(\n\t\t() => createNewsletterValue({ api }),\n\t\t[api],\n\t)\n\n\t// ============================================\n\t// Database Context Value (delegated to factory)\n\t// ============================================\n\tconst databaseValue: DatabaseContextValue = useMemo(() => createDatabaseValue(), [])\n\n\t// ============================================\n\t// Email Context Value (delegated to factory)\n\t// ============================================\n\tconst emailValue: EmailContextValue = useMemo(() => createEmailValue({ api }), [api])\n\n\t// ============================================\n\t// Webhooks Context Value (delegated to factory)\n\t// ============================================\n\tconst webhooksValue: WebhooksContextValue = useMemo(() => createWebhooksValue({ api }), [api])\n\n\t// ============================================\n\t// SDK Auth Context Value (for direct API calls)\n\t// ============================================\n\tconst sdkAuthValue: SdkAuthContextValue = useMemo(\n\t\t() => ({\n\t\t\tlogin: async (email, password) => {\n\t\t\t\tconst result = await api.post<{\n\t\t\t\t\trequiresTwoFactor?: boolean\n\t\t\t\t\tuserId?: string\n\t\t\t\t\tuser?: {\n\t\t\t\t\t\tid: string\n\t\t\t\t\t\temail: string\n\t\t\t\t\t\tname?: string | null\n\t\t\t\t\t\timage?: string | null\n\t\t\t\t\t\temailVerified?: boolean\n\t\t\t\t\t}\n\t\t\t\t}>('/auth/login', { email, password })\n\t\t\t\treturn {\n\t\t\t\t\trequiresTwoFactor: result.requiresTwoFactor ?? false,\n\t\t\t\t\tuserId: result.userId,\n\t\t\t\t\tuser: result.user\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tid: result.user.id,\n\t\t\t\t\t\t\t\temail: result.user.email,\n\t\t\t\t\t\t\t\tname: result.user.name ?? null,\n\t\t\t\t\t\t\t\timage: result.user.image ?? null,\n\t\t\t\t\t\t\t\temailVerified: result.user.emailVerified ?? false,\n\t\t\t\t\t\t\t\ttwoFactorEnabled: false, // Get from security settings if needed\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: undefined,\n\t\t\t\t}\n\t\t\t},\n\t\t\tverifyTwoFactor: async (userId, code) => {\n\t\t\t\tconst result = await api.post<{\n\t\t\t\t\taccessToken: string\n\t\t\t\t\trefreshToken: string\n\t\t\t\t\texpiresIn: number\n\t\t\t\t\tuser: {\n\t\t\t\t\t\tid: string\n\t\t\t\t\t\temail: string\n\t\t\t\t\t\tname?: string | null\n\t\t\t\t\t\timage?: string | null\n\t\t\t\t\t\temailVerified?: boolean\n\t\t\t\t\t}\n\t\t\t\t}>('/auth/verify-2fa', { userId, code })\n\t\t\t\t// Save tokens after successful 2FA\n\t\t\t\tsaveTokens({\n\t\t\t\t\taccessToken: result.accessToken,\n\t\t\t\t\trefreshToken: result.refreshToken,\n\t\t\t\t\texpiresIn: result.expiresIn,\n\t\t\t\t\tuser: result.user as User,\n\t\t\t\t})\n\t\t\t\treturn {\n\t\t\t\t\taccessToken: result.accessToken,\n\t\t\t\t\trefreshToken: result.refreshToken,\n\t\t\t\t\texpiresIn: result.expiresIn,\n\t\t\t\t\tuser: {\n\t\t\t\t\t\tid: result.user.id,\n\t\t\t\t\t\temail: result.user.email,\n\t\t\t\t\t\tname: result.user.name ?? null,\n\t\t\t\t\t\timage: result.user.image ?? null,\n\t\t\t\t\t\temailVerified: result.user.emailVerified ?? false,\n\t\t\t\t\t\ttwoFactorEnabled: true, // They just verified 2FA so it must be enabled\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t},\n\t\t\tregister: async (name, email, password, options) => {\n\t\t\t\tconst result = await api.post<{\n\t\t\t\t\tuser: { id: string; email: string; name?: string | null }\n\t\t\t\t}>('/auth/register', {\n\t\t\t\t\temail,\n\t\t\t\t\tpassword,\n\t\t\t\t\tname,\n\t\t\t\t\tcaptchaToken: options?.captchaToken,\n\t\t\t\t\tinvitationToken: options?.invitationToken,\n\t\t\t\t\tmetadata: options?.metadata,\n\t\t\t\t})\n\t\t\t\treturn {\n\t\t\t\t\trequiresVerification: true,\n\t\t\t\t\tmessage: 'Please check your email to verify your account',\n\t\t\t\t\tuser: {\n\t\t\t\t\t\tid: result.user.id,\n\t\t\t\t\t\temail: result.user.email,\n\t\t\t\t\t\tname: result.user.name ?? null,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t},\n\t\t\tforgotPassword: async (email, options) => {\n\t\t\t\tconst redirectUrl = resolveRedirectUrl(options?.redirectUrl ?? '/reset-password')\n\t\t\t\tconst result = await api.post<{ success: boolean }>('/auth/forgot-password', {\n\t\t\t\t\temail,\n\t\t\t\t\t...(redirectUrl ? { redirectUrl } : {}),\n\t\t\t\t})\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: result.success,\n\t\t\t\t\tmessage: 'Password reset email sent',\n\t\t\t\t}\n\t\t\t},\n\t\t\tresetPassword: async (token, password) => {\n\t\t\t\treturn await api.post('/auth/reset-password', {\n\t\t\t\t\ttoken,\n\t\t\t\t\tpassword,\n\t\t\t\t})\n\t\t\t},\n\t\t\tverifyEmail: async (token) => {\n\t\t\t\tawait api.post('/auth/verify-email', { token })\n\t\t\t\treturn { success: true }\n\t\t\t},\n\t\t\tlogout: async (_refreshToken) => {\n\t\t\t\tawait api.post('/auth/logout')\n\t\t\t\tclearTokens()\n\t\t\t\treturn { success: true }\n\t\t\t},\n\t\t\tme: async () => {\n\t\t\t\tconst profile = await api.get<{\n\t\t\t\t\tid: string\n\t\t\t\t\temail: string\n\t\t\t\t\tname?: string | null\n\t\t\t\t\timage?: string | null\n\t\t\t\t\temailVerified?: boolean\n\t\t\t\t\tcreatedAt?: string\n\t\t\t\t}>('/user/profile')\n\t\t\t\t// Get 2FA status from security settings\n\t\t\t\tconst security = await api.get<{ twoFactorEnabled?: boolean }>('/user/security')\n\t\t\t\treturn {\n\t\t\t\t\tid: profile.id,\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\tname: profile.name ?? null,\n\t\t\t\t\timage: profile.image ?? null,\n\t\t\t\t\temailVerified: profile.emailVerified ?? false,\n\t\t\t\t\ttwoFactorEnabled: security.twoFactorEnabled ?? false,\n\t\t\t\t}\n\t\t\t},\n\t\t\tgetOAuthProviders: async () => {\n\t\t\t\tif (!appId) return { providers: [] }\n\t\t\t\t// L-19 (2026-05-02): mirror server-side fetchOAuthProviders fix.\n\t\t\t\t// Path is `/v1/auth/oauth-providers` (not legacy `/api/auth/providers`)\n\t\t\t\t// and projectAuth middleware reads `x-app-secret` (not `X-App-Id`).\n\t\t\t\tconst response = await fetch(`${platformUrl}/v1/auth/oauth-providers`, {\n\t\t\t\t\theaders: { 'x-app-secret': appId },\n\t\t\t\t})\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\treturn { providers: [] }\n\t\t\t\t}\n\t\t\t\tconst data = await response.json()\n\t\t\t\treturn { providers: data.providers || [] }\n\t\t\t},\n\t\t}),\n\t\t[api, platformUrl, appId, saveTokens, clearTokens, resolveRedirectUrl],\n\t)\n\n\t// ============================================\n\t// User Context Value (for profile/session management)\n\t// ============================================\n\t// Type definitions for user API responses\n\ttype ProfileResponse = {\n\t\tid: string\n\t\temail: string\n\t\tname?: string | null\n\t\timage?: string | null\n\t\temailVerified?: boolean\n\t\tcreatedAt?: string\n\t}\n\ttype SecuritySettingsResponse = {\n\t\ttwoFactorEnabled?: boolean\n\t\thasPassword?: boolean\n\t}\n\ttype SessionResponse = {\n\t\tid: string\n\t\tisCurrent: boolean\n\t\tdeviceName?: string\n\t\tbrowser?: string\n\t\tos?: string\n\t\tdeviceType?: string\n\t\tipAddress?: string\n\t\tcountry?: string\n\t\tcity?: string\n\t\tlastActiveAt?: string\n\t\tcreatedAt?: string\n\t}\n\t// biome-ignore lint/correctness/noUnusedVariables: exported for external consumers\n\ttype LoginHistoryEntry = {\n\t\tid?: string\n\t\tipAddress?: string\n\t\tuserAgent?: string\n\t\tcity?: string\n\t\tcountry?: string\n\t\tdevice?: string\n\t\tcreatedAt?: string\n\t\tsuccess?: boolean\n\t}\n\ttype ConnectedAccountResponse = { provider: string; connectedAt?: string }\n\n\tconst userValue: UserContextValue = useMemo(\n\t\t() => ({\n\t\t\tgetProfile: async () => {\n\t\t\t\tconst profile = await api.get<ProfileResponse>('/user/profile')\n\t\t\t\tconst security = await api.get<SecuritySettingsResponse>('/user/security')\n\t\t\t\treturn {\n\t\t\t\t\tid: profile.id,\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\tname: profile.name ?? null,\n\t\t\t\t\timage: profile.image ?? null,\n\t\t\t\t\temailVerified: profile.emailVerified ?? false,\n\t\t\t\t\ttwoFactorEnabled: security.twoFactorEnabled ?? false,\n\t\t\t\t\tcreatedAt: profile.createdAt ? new Date(profile.createdAt) : new Date(),\n\t\t\t\t}\n\t\t\t},\n\t\t\tupdateProfile: async (data) => {\n\t\t\t\tconst profile = await api.put<ProfileResponse>('/user/profile', data)\n\t\t\t\t// Update local auth state if user info changed\n\t\t\t\tif (authState.user) {\n\t\t\t\t\tsetAuthState({\n\t\t\t\t\t\t...authState,\n\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t...authState.user,\n\t\t\t\t\t\t\tname: profile.name ?? authState.user.name,\n\t\t\t\t\t\t\timage: profile.image ?? authState.user.image,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\t// updateProfile returns minimal data, fetch full profile for complete info\n\t\t\t\tconst fullProfile = await api.get<ProfileResponse>('/user/profile')\n\t\t\t\tconst security = await api.get<SecuritySettingsResponse>('/user/security')\n\t\t\t\treturn {\n\t\t\t\t\tid: profile.id,\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\tname: profile.name ?? null,\n\t\t\t\t\timage: profile.image ?? null,\n\t\t\t\t\temailVerified: fullProfile.emailVerified ?? false,\n\t\t\t\t\ttwoFactorEnabled: security.twoFactorEnabled ?? false,\n\t\t\t\t\tcreatedAt: fullProfile.createdAt ? new Date(fullProfile.createdAt) : new Date(),\n\t\t\t\t}\n\t\t\t},\n\t\t\tchangePassword: async (currentPassword, newPassword) => {\n\t\t\t\t// First verify identity with current password\n\t\t\t\tawait api.post('/challenge/verify', {\n\t\t\t\t\tmethod: 'password',\n\t\t\t\t\tvalue: currentPassword,\n\t\t\t\t})\n\t\t\t\t// Then change password\n\t\t\t\treturn await api.post('/user/profile', { password: newPassword })\n\t\t\t},\n\t\t\tgetLoginHistory: async (options) => {\n\t\t\t\tconst history =\n\t\t\t\t\tawait api.get<\n\t\t\t\t\t\tArray<{\n\t\t\t\t\t\t\tid: string\n\t\t\t\t\t\t\tipAddress: string | null\n\t\t\t\t\t\t\tuserAgent: string | null\n\t\t\t\t\t\t\tcountry: string | null\n\t\t\t\t\t\t\tcity: string | null\n\t\t\t\t\t\t\tdevice: string | null\n\t\t\t\t\t\t\tsuccess: boolean\n\t\t\t\t\t\t\tcreatedAt: string\n\t\t\t\t\t\t}>\n\t\t\t\t\t>('/user/login-history')\n\t\t\t\tconst items = options?.limit ? history.slice(0, options.limit) : history\n\t\t\t\treturn items.map((h) => ({\n\t\t\t\t\tid: h.id,\n\t\t\t\t\tipAddress: h.ipAddress,\n\t\t\t\t\tuserAgent: h.userAgent,\n\t\t\t\t\tlocation: h.city && h.country ? `${h.city}, ${h.country}` : (h.country ?? null),\n\t\t\t\t\tdevice: h.device,\n\t\t\t\t\tbrowser: null, // Not available from API\n\t\t\t\t\tos: null, // Not available from API\n\t\t\t\t\tloginAt: new Date(h.createdAt),\n\t\t\t\t\tsuccess: h.success,\n\t\t\t\t}))\n\t\t\t},\n\t\t\tgetSessions: async () => {\n\t\t\t\tconst response = await api.get<SessionResponse[]>('/user/sessions')\n\t\t\t\treturn response.map((s) => ({\n\t\t\t\t\tid: s.id,\n\t\t\t\t\tisCurrent: s.isCurrent,\n\t\t\t\t\tdeviceName: s.deviceName,\n\t\t\t\t\tbrowser: s.browser,\n\t\t\t\t\tos: s.os,\n\t\t\t\t\tdeviceType: s.deviceType,\n\t\t\t\t\tipAddress: s.ipAddress,\n\t\t\t\t\tcountry: s.country,\n\t\t\t\t\tcity: s.city,\n\t\t\t\t\tlastActiveAt: s.lastActiveAt,\n\t\t\t\t\tcreatedAt: s.createdAt,\n\t\t\t\t}))\n\t\t\t},\n\t\t\trevokeSession: async (sessionId) => {\n\t\t\t\treturn await api.del(`/user/sessions/${sessionId}`)\n\t\t\t},\n\t\t\trenameSession: async (sessionId, name) => {\n\t\t\t\treturn await api.put(`/user/sessions/${sessionId}`, { name })\n\t\t\t},\n\t\t\trevokeAllSessions: async () => {\n\t\t\t\treturn await api.post('/user/sessions/revoke-all')\n\t\t\t},\n\t\t\tgetConnectedAccounts: async () => {\n\t\t\t\t// Connected accounts are part of security settings\n\t\t\t\tconst security = await api.get<{\n\t\t\t\t\tconnectedAccounts?: ConnectedAccountResponse[]\n\t\t\t\t}>('/user/security')\n\t\t\t\tconst accounts = security.connectedAccounts ?? []\n\t\t\t\treturn accounts.map((a) => ({\n\t\t\t\t\tprovider: a.provider,\n\t\t\t\t\taccountId: '', // Not available in the API response\n\t\t\t\t\temail: null, // Not available in the API response\n\t\t\t\t\tname: null, // Not available in the API response\n\t\t\t\t\timage: null, // Not available in the API response\n\t\t\t\t\tconnectedAt: a.connectedAt ? new Date(a.connectedAt) : new Date(),\n\t\t\t\t}))\n\t\t\t},\n\t\t\tdeleteAccount: async (password) => {\n\t\t\t\t// Challenge verification handled by user.deleteAccount via challenge system\n\t\t\t\tif (password) {\n\t\t\t\t\tawait api.post('/challenge/verify', {\n\t\t\t\t\t\tmethod: 'password',\n\t\t\t\t\t\tvalue: password,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\treturn await api.del('/user/account')\n\t\t\t},\n\t\t\texportData: async () => {\n\t\t\t\tconst response = await api.get<{\n\t\t\t\t\tdownloadUrl: string\n\t\t\t\t\texpiresAt: string\n\t\t\t\t}>('/user/export')\n\t\t\t\treturn {\n\t\t\t\t\tdownloadUrl: response.downloadUrl,\n\t\t\t\t\texpiresAt: new Date(response.expiresAt),\n\t\t\t\t}\n\t\t\t},\n\t\t}),\n\t\t[api, authState],\n\t)\n\n\t// ============================================\n\t// Security Context Value (for 2FA, passkeys, etc.)\n\t// ============================================\n\t// Type definitions for security API responses\n\ttype PasskeyResponse = {\n\t\tid: string\n\t\t/** Passkey name (user-assigned label) */\n\t\tname: string | null\n\t\tcreatedAt: string\n\t\tlastUsedAt: string | null\n\t}\n\n\ttype SecurityAlertResponse = {\n\t\tid: string\n\t\ttype: string\n\t\ttitle: string\n\t\tdescription: string | null\n\t\tmetadata: Record<string, unknown> | null\n\t\tread: boolean\n\t\tcreatedAt: string\n\t}\n\n\tconst securityValue: SecurityContextValue = useMemo(\n\t\t() => ({\n\t\t\tgetTwoFactorStatus: async () => {\n\t\t\t\tconst settings = await api.get<SecuritySettingsResponse>('/user/security')\n\t\t\t\t// Backup codes count is retrieved separately if needed\n\t\t\t\treturn {\n\t\t\t\t\tenabled: settings.twoFactorEnabled ?? false,\n\t\t\t\t\tbackupCodesRemaining: 0, // Would need separate endpoint to get this\n\t\t\t\t}\n\t\t\t},\n\t\t\ttwoFactorSetup: async () => {\n\t\t\t\treturn await api.post('/security/2fa/setup')\n\t\t\t},\n\t\t\ttwoFactorVerify: async (code) => {\n\t\t\t\treturn await api.post('/security/2fa/verify', { code })\n\t\t\t},\n\t\t\ttwoFactorDisable: async (_code) => {\n\t\t\t\t// Note: Code verification is handled by challenge middleware, not the method itself\n\t\t\t\treturn await api.post('/security/2fa/disable')\n\t\t\t},\n\t\t\tbackupCodesView: async (_code) => {\n\t\t\t\t// Note: Code verification is handled by challenge middleware, not the method itself\n\t\t\t\treturn await api.get('/security/backup-codes')\n\t\t\t},\n\t\t\tbackupCodesRegenerate: async (_code) => {\n\t\t\t\t// Note: Code verification is handled by challenge middleware, not the method itself\n\t\t\t\treturn await api.post('/security/backup-codes/regenerate')\n\t\t\t},\n\t\t\tgetPasswordStatus: async () => {\n\t\t\t\tconst settings = await api.get<SecuritySettingsResponse>('/user/security')\n\t\t\t\treturn { hasPassword: settings.hasPassword ?? true }\n\t\t\t},\n\t\t\tpasswordSet: async (password) => {\n\t\t\t\treturn await api.post('/security/password/set', { password })\n\t\t\t},\n\t\t\temailChangeRequest: async (newEmail) => {\n\t\t\t\treturn await api.post('/security/email/change', { newEmail })\n\t\t\t},\n\t\t\temailChangeConfirm: async (token) => {\n\t\t\t\treturn await api.post('/security/email/confirm', { token })\n\t\t\t},\n\t\t\tpasskeyList: async () => {\n\t\t\t\tconst response = await api.get<{ passkeys: PasskeyResponse[] }>('/security/passkeys')\n\t\t\t\treturn response.passkeys.map((p) => ({\n\t\t\t\t\tid: p.id,\n\t\t\t\t\tname: p.name ?? undefined,\n\t\t\t\t\tdeviceType: undefined, // Not returned by API\n\t\t\t\t\tcreatedAt: new Date(p.createdAt),\n\t\t\t\t\tlastUsedAt: p.lastUsedAt ? new Date(p.lastUsedAt) : null,\n\t\t\t\t}))\n\t\t\t},\n\t\t\tpasskeyRegisterStart: async () => {\n\t\t\t\treturn await api.post('/security/passkeys/register/start')\n\t\t\t},\n\t\t\tpasskeyRegisterVerify: async (credential, name) => {\n\t\t\t\treturn await api.post('/security/passkeys/register/verify', {\n\t\t\t\t\tcredential,\n\t\t\t\t\tdeviceName: name ?? 'Passkey',\n\t\t\t\t})\n\t\t\t},\n\t\t\tpasskeyRename: async (passkeyId: string, name: string) => {\n\t\t\t\treturn await api.put(`/security/passkeys/${passkeyId}`, { name })\n\t\t\t},\n\t\t\tpasskeyDelete: async (passkeyId: string) => {\n\t\t\t\treturn await api.del(`/security/passkeys/${passkeyId}`)\n\t\t\t},\n\t\t\toauthConnect: async (provider) => {\n\t\t\t\tconst redirectUri = window.location.href\n\t\t\t\treturn {\n\t\t\t\t\tredirectUrl: `${platformUrl}/auth/connect/${provider}?client_id=${appId || ''}&redirect_uri=${encodeURIComponent(redirectUri)}`,\n\t\t\t\t}\n\t\t\t},\n\t\t\toauthDisconnect: async (provider) => {\n\t\t\t\treturn await api.post('/security/oauth/disconnect', { provider })\n\t\t\t},\n\t\t\tgetSecurityScore: async () => {\n\t\t\t\treturn await api.get('/security/score')\n\t\t\t},\n\t\t\t// Security Alerts\n\t\t\tgetSecurityAlerts: async (options) => {\n\t\t\t\tconst params = new URLSearchParams()\n\t\t\t\tif (options?.limit) params.set('limit', String(options.limit))\n\t\t\t\tif (options?.unreadOnly) params.set('unreadOnly', 'true')\n\t\t\t\tconst query = params.toString()\n\t\t\t\tconst response = await api.get<{\n\t\t\t\t\talerts: SecurityAlertResponse[]\n\t\t\t\t\ttotal: number\n\t\t\t\t}>(`/security/alerts${query ? `?${query}` : ''}`)\n\t\t\t\treturn {\n\t\t\t\t\talerts: response.alerts.map((a) => ({\n\t\t\t\t\t\tid: a.id,\n\t\t\t\t\t\ttype: a.type,\n\t\t\t\t\t\ttitle: a.title,\n\t\t\t\t\t\tdescription: a.description,\n\t\t\t\t\t\tmetadata: a.metadata,\n\t\t\t\t\t\tread: a.read,\n\t\t\t\t\t\tcreatedAt: new Date(a.createdAt),\n\t\t\t\t\t})),\n\t\t\t\t\ttotal: response.total,\n\t\t\t\t}\n\t\t\t},\n\t\t\tmarkAlertRead: async (alertId: string) => {\n\t\t\t\treturn await api.post(`/security/alerts/${alertId}/read`)\n\t\t\t},\n\t\t\tmarkAllAlertsRead: async () => {\n\t\t\t\treturn await api.post('/security/alerts/read-all')\n\t\t\t},\n\t\t}),\n\t\t[api, platformUrl, appId],\n\t)\n\n\t// ============================================\n\t// Context Values\n\t// ============================================\n\tconst authValue = useMemo(\n\t\t() => ({\n\t\t\t...authState,\n\t\t\tsignIn,\n\t\t\tsignUp,\n\t\t\tsignOut,\n\t\t\tgetToken,\n\t\t\tswitchOrganizationToken,\n\t\t\tresetPassword,\n\t\t\tverifyEmail,\n\t\t\tresendVerificationEmail,\n\t\t\tforgotPassword,\n\t\t\t// OAuth state management\n\t\t\tclearOAuthError,\n\t\t\t// Direct OAuth methods (Firebase/Supabase pattern)\n\t\t\tsignInWithOAuth,\n\t\t\tsignInWithGoogle,\n\t\t\tsignInWithGithub,\n\t\t\tsignInWithApple,\n\t\t\tsignInWithDiscord,\n\t\t\tsignInWithTwitter,\n\t\t\tsignInWithMicrosoft,\n\t\t\t// Magic Link (passwordless)\n\t\t\tsignInWithMagicLink,\n\t\t}),\n\t\t[\n\t\t\tauthState,\n\t\t\tsignIn,\n\t\t\tsignUp,\n\t\t\tsignOut,\n\t\t\tgetToken,\n\t\t\tswitchOrganizationToken,\n\t\t\tresetPassword,\n\t\t\tverifyEmail,\n\t\t\tresendVerificationEmail,\n\t\t\tforgotPassword,\n\t\t\tclearOAuthError,\n\t\t\tsignInWithOAuth,\n\t\t\tsignInWithGoogle,\n\t\t\tsignInWithGithub,\n\t\t\tsignInWithApple,\n\t\t\tsignInWithDiscord,\n\t\t\tsignInWithTwitter,\n\t\t\tsignInWithMicrosoft,\n\t\t\tsignInWithMagicLink,\n\t\t],\n\t)\n\n\tconst platformValue = useMemo(\n\t\t() => ({\n\t\t\tappId,\n\t\t\tplatformUrl,\n\t\t\tauthPrefix,\n\t\t\tslug: resolvedRef,\n\t\t\tref: resolvedRef,\n\t\t\tanonymousId,\n\t\t\tqueryClient,\n\t\t\tclickIds,\n\t\t\tsubscription,\n\t\t\tsubscriptionLoading,\n\t\t\tsubscriptionError,\n\t\t\tplans,\n\t\t\tplansLoading,\n\t\t\tplansError,\n\t\t\tcreateCheckout,\n\t\t\topenPortal,\n\t\t\trefreshSubscription,\n\t\t\ttrack,\n\t\t\tpage,\n\t\t\tidentify,\n\t\t\tqueryAnalytics,\n\t\t\tanalyticsError,\n\t\t\tpushSupported,\n\t\t\tpushSubscribed,\n\t\t\tpushPreferences,\n\t\t\tpushError,\n\t\t\tsubscribePush,\n\t\t\tunsubscribePush,\n\t\t\tupdatePushPreferences,\n\t\t\t// Mobile Push\n\t\t\tmobilePushConfig,\n\t\t\tmobilePushPreferences,\n\t\t\tmobilePushError,\n\t\t\tregisterMobileDevice,\n\t\t\tunregisterMobileDevice,\n\t\t\tgetMobilePushPreferences,\n\t\t\treferralStats,\n\t\t\treferralCode,\n\t\t\treferralLoading,\n\t\t\treferralError,\n\t\t\tcopyReferralCode,\n\t\t\tregenerateReferralCode,\n\t\t\tredeemReferralCode,\n\t\t\tgetReferralLeaderboard,\n\t\t\t// In-App Messages (Inbox)\n\t\t\tinboxMessages,\n\t\t\tinboxUnreadCount,\n\t\t\tinboxLoading,\n\t\t\tinboxError,\n\t\t\tinboxPreferences,\n\t\t\trefreshInbox,\n\t\t\tmarkInboxMessageAsRead,\n\t\t\tmarkAllInboxMessagesAsRead,\n\t\t\tdismissInboxMessage,\n\t\t\trecordInboxMessageClick,\n\t\t\tupdateInboxPreferences,\n\t\t\tgetBillingBalance: async () => {\n\t\t\t\treturn await api.get<{\n\t\t\t\t\tbalance: { current: number; currentFormatted: string }\n\t\t\t\t\tstatus: {\n\t\t\t\t\t\tlevel: string\n\t\t\t\t\t\tisHealthy: boolean\n\t\t\t\t\t\tisLow: boolean\n\t\t\t\t\t\talertThreshold: number\n\t\t\t\t\t}\n\t\t\t\t\tbillingType: string\n\t\t\t\t\ttrustLevel: string\n\t\t\t\t\tspendingCap: number | null\n\t\t\t\t\tcurrentMonthSpend: number\n\t\t\t\t\tspendingCapPercent: number | null\n\t\t\t\t\tgracePeriodEndsAt: string | null\n\t\t\t\t\tisAdminOrg: boolean\n\t\t\t\t}>('/billing/balance')\n\t\t\t},\n\t\t\tgetBillingUsage: async (options?: { month?: string }) => {\n\t\t\t\treturn await api.get<{\n\t\t\t\t\tperiod: { type: string; start: string; end: string }\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\taiCostMicrodollars: number\n\t\t\t\t\t\tstorageBytesUsed: number\n\t\t\t\t\t\tstorageEgressBytes: number\n\t\t\t\t\t\tstorageUploads: number\n\t\t\t\t\t\tdbStorageBytes: number\n\t\t\t\t\t\tdbComputeSeconds: number\n\t\t\t\t\t\temailSentCount: number\n\t\t\t\t\t\tjobInvocationCount: number\n\t\t\t\t\t\tcronActiveCount: number\n\t\t\t\t\t\tpushSentCount?: number\n\t\t\t\t\t\tanalyticsEventCount: number\n\t\t\t\t\t\twebhookDeliveryCount: number\n\t\t\t\t\t\terrorEventCount: number\n\t\t\t\t\t\tauthMau: number\n\t\t\t\t\t} | null\n\t\t\t\t}>('/billing/usage', { month: options?.month })\n\t\t\t},\n\t\t\t// Engagement\n\t\t\tuser: authState.user,\n\t\t\tgetStreak,\n\t\t\trecordStreakActivity,\n\t\t\trecoverStreak,\n\t\t\tgetLeaderboard: getEngagementLeaderboard, // Engagement leaderboard\n\t\t\tsubmitScore,\n\t\t\tgetAchievements,\n\t\t\tunlockAchievement,\n\t\t\tincrementAchievementProgress,\n\t\t}),\n\t\t[\n\t\t\tapi,\n\t\t\tappId,\n\t\t\tplatformUrl,\n\t\t\tauthPrefix,\n\t\t\tanonymousId,\n\t\t\tqueryClient,\n\t\t\tclickIds,\n\t\t\tsubscription,\n\t\t\tsubscriptionLoading,\n\t\t\tsubscriptionError,\n\t\t\tplans,\n\t\t\tcreateCheckout,\n\t\t\topenPortal,\n\t\t\trefreshSubscription,\n\t\t\ttrack,\n\t\t\tpage,\n\t\t\tidentify,\n\t\t\tqueryAnalytics,\n\t\t\tanalyticsError,\n\t\t\tpushSupported,\n\t\t\tpushSubscribed,\n\t\t\tpushPreferences,\n\t\t\tpushError,\n\t\t\tsubscribePush,\n\t\t\tunsubscribePush,\n\t\t\tupdatePushPreferences,\n\t\t\t// Mobile Push deps\n\t\t\tmobilePushConfig,\n\t\t\tmobilePushPreferences,\n\t\t\tmobilePushError,\n\t\t\tregisterMobileDevice,\n\t\t\tunregisterMobileDevice,\n\t\t\tgetMobilePushPreferences,\n\t\t\treferralStats,\n\t\t\treferralCode,\n\t\t\treferralLoading,\n\t\t\treferralError,\n\t\t\tcopyReferralCode,\n\t\t\tregenerateReferralCode,\n\t\t\tredeemReferralCode,\n\t\t\tgetReferralLeaderboard,\n\t\t\t// Inbox deps\n\t\t\tinboxMessages,\n\t\t\tinboxUnreadCount,\n\t\t\tinboxLoading,\n\t\t\tinboxError,\n\t\t\tinboxPreferences,\n\t\t\trefreshInbox,\n\t\t\tmarkInboxMessageAsRead,\n\t\t\tmarkAllInboxMessagesAsRead,\n\t\t\tdismissInboxMessage,\n\t\t\trecordInboxMessageClick,\n\t\t\tupdateInboxPreferences,\n\t\t\t// Engagement deps\n\t\t\tauthState.user,\n\t\t\tgetStreak,\n\t\t\trecordStreakActivity,\n\t\t\trecoverStreak,\n\t\t\tgetEngagementLeaderboard,\n\t\t\tsubmitScore,\n\t\t\tgetAchievements,\n\t\t\tunlockAchievement,\n\t\t\tincrementAchievementProgress,\n\t\t\tresolvedRef,\n\t\t],\n\t)\n\n\t// QueryClientProvider is now provided by the outer SylphxProvider wrapper\n\treturn (\n\t\t<AuthContext.Provider value={authValue}>\n\t\t\t<SdkAuthContext.Provider value={sdkAuthValue}>\n\t\t\t\t<UserContext.Provider value={userValue}>\n\t\t\t\t\t<SecurityContext.Provider value={securityValue}>\n\t\t\t\t\t\t<PlatformContext.Provider value={platformValue}>\n\t\t\t\t\t\t\t<AIContext.Provider value={aiValue}>\n\t\t\t\t\t\t\t\t<TasksContext.Provider value={tasksValue}>\n\t\t\t\t\t\t\t\t\t<MonitoringContext.Provider value={monitoringValue}>\n\t\t\t\t\t\t\t\t\t\t<ConsentContext.Provider value={consentValue}>\n\t\t\t\t\t\t\t\t\t\t\t<DatabaseContext.Provider value={databaseValue}>\n\t\t\t\t\t\t\t\t\t\t\t\t<EmailContext.Provider value={emailValue}>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{/* Newsletter: Marketing/bulk email subscriptions */}\n\t\t\t\t\t\t\t\t\t\t\t\t\t<NewsletterContext.Provider value={newsletterValue}>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<WebhooksContext.Provider value={webhooksValue}>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</WebhooksContext.Provider>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</NewsletterContext.Provider>\n\t\t\t\t\t\t\t\t\t\t\t\t</EmailContext.Provider>\n\t\t\t\t\t\t\t\t\t\t\t</DatabaseContext.Provider>\n\t\t\t\t\t\t\t\t\t\t</ConsentContext.Provider>\n\t\t\t\t\t\t\t\t\t</MonitoringContext.Provider>\n\t\t\t\t\t\t\t\t</TasksContext.Provider>\n\t\t\t\t\t\t\t</AIContext.Provider>\n\t\t\t\t\t\t</PlatformContext.Provider>\n\t\t\t\t\t</SecurityContext.Provider>\n\t\t\t\t</UserContext.Provider>\n\t\t\t</SdkAuthContext.Provider>\n\t\t</AuthContext.Provider>\n\t)\n}\n","/**\n * Consent Functions\n *\n * Pure functions for GDPR/CCPA consent management.\n *\n * ## Architecture (ADR-004)\n *\n * Consent uses **Inline Defaults + Auto-Discovery + Console Override**:\n * - Code provides optional inline defaults when checking consent\n * - Platform auto-discovers/creates consent types when first referenced\n * - Console can override names, descriptions, requirements without deployment\n *\n * Wire-shape types and endpoint paths are re-exported from\n * `@sylphx/contract` (ADR-084). The contract is the single source of truth\n * for `GET /consent/types`, `GET /consent`, `POST /consent`, and friends.\n * This module keeps ergonomic helper inputs only where the public SDK API\n * intentionally differs from the wire shape.\n *\n * @example\n * ```typescript\n * import { hasConsent, getUserConsents, setConsents } from '@sylphx/sdk'\n *\n * // Check consent with inline defaults (auto-discovered if doesn't exist)\n * if (await hasConsent(config, 'analytics', { userId: 'user-123' }, {\n *   name: 'Analytics Cookies',\n *   description: 'Help us understand how visitors use our site',\n *   category: 'analytics',\n *   required: false,\n * })) {\n *   track('pageview')\n * }\n *\n * // Get user's current consents\n * const consents = await getUserConsents(config, { userId: 'user-123' })\n *\n * // Set specific consents\n * await setConsents(config, {\n *   userId: 'user-123',\n *   consents: { analytics: true, marketing: false }\n * })\n * ```\n */\n\n// Type-only imports from @sylphx/contract per ADR-084 Rule 3 — prevents\n// Effect runtime types from leaking into the published .d.ts surface.\nimport type {\n\tConsentHistoryResponse as ContractConsentHistoryResponse,\n\tSdkConsentType as ContractConsentType,\n\tLinkAnonymousConsentsRequest as ContractLinkAnonymousConsentsRequest,\n\tUserConsent as ContractUserConsent,\n} from '@sylphx/contract'\nimport { consentEndpoints } from '@sylphx/contract'\nimport { callApi, type SylphxConfig } from './config'\n\n// ============================================================================\n// Types (re-exported from @sylphx/contract)\n// ============================================================================\n\nexport type ConsentType = ContractConsentType\nexport type UserConsent = ContractUserConsent\n\n// SDK-specific types (not directly from API schema)\n/** Consent category for grouping */\nexport type ConsentCategory = 'necessary' | 'analytics' | 'marketing' | 'functional' | 'preferences'\n\nexport interface SetConsentsInput {\n\t/** User ID (optional for anonymous users) */\n\tuserId?: string\n\t/** Anonymous ID (for guest users) */\n\tanonymousId?: string\n\t/** Consent settings by type slug */\n\tconsents: Record<string, boolean>\n\t/** Source of the consent action (defaults server-side to banner) */\n\tsource?: 'banner' | 'settings' | 'api'\n\t/** User agent to store with the consent audit trail */\n\tuserAgent?: string\n}\n\nexport type LinkAnonymousConsentsInput = ContractLinkAnonymousConsentsRequest\n\nexport interface GetConsentHistoryInput {\n\t/** User ID (for authenticated users) */\n\tuserId?: string\n\t/** Anonymous ID (for anonymous users) */\n\tanonymousId?: string\n\t/** Maximum records to return (default: 50) */\n\tlimit?: number\n\t/**\n\t * Opaque pagination cursor returned by a previous response.\n\t * Omit (or pass undefined) to fetch the first page.\n\t */\n\tcursor?: string\n}\n\nexport type ConsentHistoryEntry = ContractConsentHistoryResponse['entries'][number]\nexport type ConsentHistoryResult = ContractConsentHistoryResponse\n\nexport interface GetConsentsInput {\n\t/** User ID (optional for anonymous users) */\n\tuserId?: string\n\t/** Anonymous ID (for guest users) */\n\tanonymousId?: string\n}\n\n/**\n * Inline defaults for consent purpose auto-discovery\n *\n * @example\n * ```typescript\n * await hasConsent(config, 'analytics', { userId: 'user-123' }, {\n *   name: 'Analytics Cookies',\n *   description: 'Help us understand how visitors use our site',\n *   category: 'analytics',\n *   required: false,\n * })\n * ```\n */\nexport interface ConsentPurposeDefaults {\n\t/** Display name */\n\tname?: string\n\t/** Description */\n\tdescription?: string\n\t/** Category */\n\tcategory?: ConsentCategory\n\t/** Whether consent is required (always granted) */\n\trequired?: boolean\n\t/** Whether enabled by default */\n\tdefaultEnabled?: boolean\n\t/** Sort order in UI */\n\tsortOrder?: number\n}\n\nfunction consentItemsFromRecord(consents: Record<string, boolean>) {\n\treturn Object.entries(consents).map(([slug, granted]) => ({ slug, granted }))\n}\n\n// ============================================================================\n// Functions\n// ============================================================================\n\n/**\n * Get all consent types configured for the app\n *\n * Returns GDPR-standard defaults if none configured.\n *\n * @example\n * ```typescript\n * const types = await getConsentTypes(config)\n * types.forEach(t => console.log(`${t.name}: ${t.required ? 'Required' : 'Optional'}`))\n * ```\n */\nexport async function getConsentTypes(config: SylphxConfig): Promise<ConsentType[]> {\n\tconst endpoint = consentEndpoints.listTypes\n\treturn callApi(config, endpoint.path, { method: endpoint.method })\n}\n\n/**\n * Check if user has granted consent for a specific purpose\n *\n * If the consent type doesn't exist, it will be auto-discovered with the provided defaults.\n * Console can override any values without deployment.\n *\n * @param config - SDK configuration\n * @param purposeSlug - Consent purpose slug (e.g., 'analytics', 'marketing')\n * @param input - User identification (userId or anonymousId)\n * @param defaults - Optional inline defaults for auto-discovery\n * @returns Whether consent is granted\n *\n * @example\n * ```typescript\n * // Check analytics consent with inline defaults\n * if (await hasConsent(config, 'analytics', { userId: 'user-123' }, {\n *   name: 'Analytics Cookies',\n *   description: 'Help us understand how visitors use our site',\n *   category: 'analytics',\n *   required: false,\n * })) {\n *   track('pageview')\n * }\n *\n * // Required consent always returns true\n * const hasNecessary = await hasConsent(config, 'necessary', { userId }, {\n *   name: 'Essential Cookies',\n *   description: 'Required for the website to function',\n *   category: 'necessary',\n *   required: true,\n * })\n * ```\n */\nexport async function hasConsent(\n\tconfig: SylphxConfig,\n\tpurposeSlug: string,\n\tinput: GetConsentsInput,\n\tdefaults?: ConsentPurposeDefaults,\n): Promise<boolean> {\n\tconst consents = await getUserConsents(config, input)\n\tconst consent = consents.find((entry) => entry.slug === purposeSlug)\n\tif (consent) return consent.granted\n\tif (defaults?.required) return true\n\treturn defaults?.defaultEnabled ?? false\n}\n\n/**\n * Get user's current consent settings\n *\n * @example\n * ```typescript\n * // For authenticated user\n * const consents = await getUserConsents(config, { userId: 'user-123' })\n *\n * // For anonymous user\n * const consents = await getUserConsents(config, { anonymousId: 'anon-456' })\n * ```\n */\nexport async function getUserConsents(\n\tconfig: SylphxConfig,\n\tinput: GetConsentsInput,\n): Promise<UserConsent[]> {\n\tconst endpoint = consentEndpoints.listUser\n\treturn callApi(config, endpoint.path, {\n\t\tmethod: endpoint.method,\n\t\tquery: {\n\t\t\tuserId: input.userId,\n\t\t\tanonymousId: input.anonymousId,\n\t\t},\n\t})\n}\n\n/**\n * Set user's consent preferences\n *\n * @example\n * ```typescript\n * await setConsents(config, {\n *   userId: 'user-123',\n *   consents: {\n *     analytics: true,\n *     marketing: false,\n *   },\n * })\n * ```\n */\nexport async function setConsents(config: SylphxConfig, input: SetConsentsInput): Promise<void> {\n\tconst endpoint = consentEndpoints.set\n\tawait callApi(config, endpoint.path, {\n\t\tmethod: endpoint.method,\n\t\tbody: {\n\t\t\tuserId: input.userId,\n\t\t\tanonymousId: input.anonymousId,\n\t\t\tconsents: consentItemsFromRecord(input.consents),\n\t\t\tsource: input.source,\n\t\t\tuserAgent: input.userAgent,\n\t\t},\n\t})\n}\n\n/**\n * Accept all consent types\n *\n * @example\n * ```typescript\n * await acceptAllConsents(config, { userId: 'user-123' })\n * ```\n */\nexport async function acceptAllConsents(\n\tconfig: SylphxConfig,\n\tinput: GetConsentsInput,\n): Promise<void> {\n\tconst endpoint = consentEndpoints.acceptAll\n\tawait callApi(config, endpoint.path, {\n\t\tmethod: endpoint.method,\n\t\tbody: input,\n\t})\n}\n\n/**\n * Decline all optional consent types (keeps required ones)\n *\n * @example\n * ```typescript\n * await declineOptionalConsents(config, { anonymousId: 'anon-456' })\n * ```\n */\nexport async function declineOptionalConsents(\n\tconfig: SylphxConfig,\n\tinput: GetConsentsInput,\n): Promise<void> {\n\tconst endpoint = consentEndpoints.declineOptional\n\tawait callApi(config, endpoint.path, {\n\t\tmethod: endpoint.method,\n\t\tbody: input,\n\t})\n}\n\n/**\n * Link anonymous user's consents to authenticated user\n *\n * Call this after user signs up/logs in to merge their anonymous consent history.\n *\n * @example\n * ```typescript\n * await linkAnonymousConsents(config, {\n *   userId: 'user-123',\n *   anonymousId: 'anon-456',\n * })\n * ```\n */\nexport async function linkAnonymousConsents(\n\tconfig: SylphxConfig,\n\tinput: LinkAnonymousConsentsInput,\n): Promise<void> {\n\tconst endpoint = consentEndpoints.linkAnonymous\n\tawait callApi(config, endpoint.path, {\n\t\tmethod: endpoint.method,\n\t\tbody: input,\n\t})\n}\n\n/**\n * Get consent change history for GDPR audit trail\n *\n * Returns a paginated list of all consent state changes for a user.\n * Required for GDPR compliance - provides complete audit trail of consent decisions.\n *\n * @example\n * ```typescript\n * // Get consent history for authenticated user (first page)\n * const history = await getConsentHistory(config, { userId: 'user-123', limit: 20 })\n * history.entries.forEach(entry => {\n *   console.log(`${entry.consentType}: ${entry.previousGranted} → ${entry.newGranted}`)\n * })\n *\n * // Fetch next page using the cursor\n * if (history.nextCursor) {\n *   const page2 = await getConsentHistory(config, {\n *     userId: 'user-123',\n *     limit: 20,\n *     cursor: history.nextCursor,\n *   })\n * }\n * ```\n */\nexport async function getConsentHistory(\n\tconfig: SylphxConfig,\n\tinput: GetConsentHistoryInput,\n): Promise<ConsentHistoryResult> {\n\tconst endpoint = consentEndpoints.history\n\treturn callApi(config, endpoint.path, {\n\t\tmethod: endpoint.method,\n\t\tquery: {\n\t\t\tuserId: input.userId,\n\t\t\tanonymousId: input.anonymousId,\n\t\t\tlimit: input.limit,\n\t\t\tcursor: input.cursor,\n\t\t},\n\t})\n}\n","/**\n * API Key Validation — Single Source of Truth\n *\n * OAuth 2.0 standard key validation for Sylphx Platform.\n * ALL key validation, sanitization, and environment detection logic lives here.\n *\n * Principles:\n * 1. Fail fast - Invalid input rejected immediately with clear errors\n * 2. Helpful errors - Tell users exactly what's wrong and how to fix it\n * 3. Development warnings - Warn about issues that would fail in production\n * 4. No silent fixes - Transparency over convenience (but warn + continue)\n * 5. Single Source of Truth - All key logic in one place\n *\n * Key Formats (ADR-055):\n * - Publishable key: pk_(dev|stg|prod|prev)_{32hex} — client-safe\n * - Secret Key:      sk_(dev|stg|prod|prev)_{64hex} — server-side only\n * - Legacy compatibility accepts embedded-ref keys from the superseded ADR-021 path.\n *\n * Legacy Key Formats (backward-compat):\n * - App ID (old):    app_(dev|stg|prod|prev)_[identifier] — Public identifier\n *\n * Special Internal Formats (NOT rotated):\n * - Console bootstrap: app_prod_platform_{slug} / sk_prod_platform_{slug}\n */\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/** Environment type derived from key prefix */\nexport type EnvironmentType = 'development' | 'staging' | 'production' | 'preview'\n\n/** Key type - publicKey (pk_*), appId (legacy app_*), or secret (sk_*) */\nexport type KeyType = 'publicKey' | 'appId' | 'secret'\n\n/** Validation result with clear error information */\nexport interface KeyValidationResult {\n\t/** Whether the key is valid (possibly after sanitization) */\n\tvalid: boolean\n\t/** The sanitized key to use (only if valid) */\n\tsanitizedKey: string\n\t/** Detected key type */\n\tkeyType?: KeyType\n\t/** Detected environment */\n\tenvironment?: EnvironmentType\n\t/** Error message if invalid */\n\terror?: string\n\t/** Warning message if key was auto-fixed */\n\twarning?: string\n\t/** Detected issues for debugging */\n\tissues?: string[]\n}\n\n// =============================================================================\n// Patterns — Strict Format Validation\n// =============================================================================\n\n/**\n * Publishable key pattern: pk_(dev|stg|prod|prev)_{32hex} (ADR-055) or\n * pk_(dev|stg|prod|prev)_{ref}_{32hex} (legacy ADR-021).\n * - Prefix: pk_ (publishable key, safe for client)\n * - Environment: dev, stg, prod, or prev\n * - Ref: optional 12-char base36 project ref\n * - Token: 32 hex chars (128-bit random)\n *\n * Example: pk_prod_2dubco39o9so_f19e5cdc3cc54f7ff81bdc26ec5bfbad\n */\nconst PUBLIC_KEY_PATTERN = /^pk_(dev|stg|prod|prev)(?:_[a-z0-9]{12})?_[a-f0-9]{32}$/\n\n/**\n * Legacy App ID pattern: app_(dev|stg|prod|prev)_[identifier]\n * - Prefix: app_ (application identifier, public) — legacy format, backward-compat\n * - Environment: dev, stg, prod, or prev\n * - Suffix: alphanumeric with underscores/hyphens (hex for apps, or internal identifiers)\n *\n\t * Accepts both legacy app_* format and pk_* publishable keys.\n\t * Embedded-ref pk_* values are legacy compatibility; ADR-055 pure entropy\n\t * keys are the current customer format.\n\t */\nconst APP_ID_PATTERN = /^(app|pk)_(dev|stg|prod|prev)_[a-z0-9_-]+$/\n\n/**\n * Secret key pattern: sk_(dev|stg|prod|prev)_[identifier]\n * - Prefix: sk_ (secret key)\n * - Environment: dev, stg, prod, or prev\n * - Suffix: alphanumeric with underscores/hyphens\n *\n * Accepts both old format (sk_prod_{64hex}) and new format (sk_prod_{ref}_{64hex}).\n */\nconst SECRET_KEY_PATTERN = /^sk_(dev|stg|prod|prev)_[a-z0-9_-]+$/\n\n/** Environment prefix to type mapping */\nconst ENV_PREFIX_MAP: Record<string, EnvironmentType> = {\n\tdev: 'development',\n\tstg: 'staging',\n\tprod: 'production',\n\tprev: 'preview',\n}\n\n// =============================================================================\n// Core Validation Functions\n// =============================================================================\n\n/**\n * Detect common issues with a key (whitespace, newlines, etc.)\n */\nfunction detectKeyIssues(key: string): string[] {\n\tconst issues: string[] = []\n\tif (key !== key.trim()) issues.push('whitespace')\n\tif (key.includes('\\n')) issues.push('newline')\n\tif (key.includes('\\r')) issues.push('carriage-return')\n\tif (key.includes(' ')) issues.push('space')\n\tif (key !== key.toLowerCase()) issues.push('uppercase-chars')\n\treturn issues\n}\n\n/**\n * Create a helpful warning message for keys that needed sanitization\n */\nfunction createSanitizationWarning(keyType: KeyType, issues: string[], envVarName: string): string {\n\tconst keyTypeName = keyType === 'appId' ? 'App ID' : 'Secret Key'\n\treturn (\n\t\t`[Sylphx] ${keyTypeName} contains ${issues.join(', ')}. ` +\n\t\t`This is commonly caused by Vercel CLI's 'env pull' command.\\n\\n` +\n\t\t`To fix permanently:\\n` +\n\t\t`1. Go to Vercel Dashboard → Your Project → Settings → Environment Variables\\n` +\n\t\t`2. Edit ${envVarName}\\n` +\n\t\t`3. Remove any trailing whitespace or newline characters\\n` +\n\t\t`4. Redeploy your application\\n\\n` +\n\t\t`The SDK will automatically sanitize the key, but fixing the source is recommended.`\n\t)\n}\n\n/**\n * Create a helpful error message for invalid keys\n */\nfunction createInvalidKeyError(keyType: KeyType, key: string, envVarName: string): string {\n\tconst maskedKey = key.length > 20 ? `${key.slice(0, 20)}...` : key\n\tconst formatHint =\n\t\tkeyType === 'appId'\n\t\t\t? 'pk_(dev|stg|prod|prev)_{ref}_{hex} or app_(dev|stg|prod|prev)_[id]'\n\t\t\t: 'sk_(dev|stg|prod|prev)_{ref}_{hex}'\n\tconst keyTypeName = keyType === 'appId' ? 'App ID' : 'Secret Key'\n\n\treturn (\n\t\t`[Sylphx] Invalid ${keyTypeName} format.\\n\\n` +\n\t\t`Expected format: ${formatHint}\\n` +\n\t\t`Received: \"${maskedKey}\"\\n\\n` +\n\t\t`Please check your ${envVarName} environment variable.\\n` +\n\t\t`You can find your keys in the Sylphx Console → API Keys.\\n\\n` +\n\t\t`Common issues:\\n` +\n\t\t`• Key has uppercase characters (must be lowercase)\\n` +\n\t\t`• Key has wrong prefix (App ID: pk_ or app_, Secret Key: sk_)\\n` +\n\t\t`• Key has invalid environment (must be dev, stg, prod, or prev)\\n` +\n\t\t`• Key was copied with extra whitespace`\n\t)\n}\n\n/**\n * Extract environment from a validated key\n */\nfunction extractEnvironment(key: string): EnvironmentType | undefined {\n\t// Match pk_, app_, or sk_ prefix followed by environment\n\tconst match = key.match(/^(?:app|pk|sk)_(dev|stg|prod|prev)_/)\n\tif (!match) return undefined\n\treturn ENV_PREFIX_MAP[match[1]]\n}\n\n/**\n * Internal: Generic key validation logic for specific key types\n */\nfunction validateKeyForType(\n\tkey: string | undefined | null,\n\tkeyType: KeyType,\n\tpattern: RegExp,\n\tenvVarName: string,\n): KeyValidationResult {\n\tconst keyTypeName = keyType === 'appId' ? 'App ID' : 'Secret Key'\n\n\t// Check if key is provided\n\tif (!key) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tsanitizedKey: '',\n\t\t\terror:\n\t\t\t\t`[Sylphx] ${keyTypeName} is required. ` +\n\t\t\t\t`Set ${envVarName} in your environment variables.`,\n\t\t\tissues: ['missing'],\n\t\t}\n\t}\n\n\t// Detect issues before validation\n\tconst issues = detectKeyIssues(key)\n\n\t// Check if key matches expected format exactly\n\tif (pattern.test(key)) {\n\t\treturn {\n\t\t\tvalid: true,\n\t\t\tsanitizedKey: key,\n\t\t\tkeyType,\n\t\t\tenvironment: extractEnvironment(key),\n\t\t\tissues: [],\n\t\t}\n\t}\n\n\t// Key doesn't match - try sanitization (trim + lowercase)\n\tconst sanitized = key.trim().toLowerCase()\n\n\tif (pattern.test(sanitized)) {\n\t\t// Sanitization fixes the issue\n\t\treturn {\n\t\t\tvalid: true,\n\t\t\tsanitizedKey: sanitized,\n\t\t\tkeyType,\n\t\t\tenvironment: extractEnvironment(sanitized),\n\t\t\twarning: createSanitizationWarning(keyType, issues, envVarName),\n\t\t\tissues,\n\t\t}\n\t}\n\n\t// Sanitization doesn't fix it - key format is genuinely wrong\n\treturn {\n\t\tvalid: false,\n\t\tsanitizedKey: '',\n\t\terror: createInvalidKeyError(keyType, key, envVarName),\n\t\tissues: [...issues, 'invalid-format'],\n\t}\n}\n\n// =============================================================================\n// Public API — Publishable Key (ADR-055: pk_*) and legacy App ID (app_*)\n// =============================================================================\n\n/**\n * Validate an ADR-055 publishable key (pk_*).\n *\n * @example\n * ```typescript\n * const result = validatePublicKey('pk_prod_...')\n * if (!result.valid) throw new Error(result.error)\n * ```\n */\nexport function validatePublicKey(key: string | undefined | null): KeyValidationResult {\n\treturn validateKeyForType(key, 'publicKey', PUBLIC_KEY_PATTERN, 'publishable credential')\n}\n\n/**\n * Validate and sanitize a publishable key, throwing on invalid input.\n */\nexport function validateAndSanitizePublicKey(key: string | undefined | null): string {\n\tconst result = validatePublicKey(key)\n\tif (!result.valid) throw new Error(result.error)\n\tif (result.warning) console.warn(result.warning)\n\treturn result.sanitizedKey\n}\n\n/**\n * Validate a legacy App ID (app_*) and return detailed results.\n *\n * @deprecated Use validatePublicKey() for ADR-055 pk_* keys.\n *\n * @example\n * ```typescript\n * const result = validateAppId(process.env.NEXT_PUBLIC_SYLPHX_APP_ID)\n * if (!result.valid) {\n *   throw new Error(result.error)\n * }\n * if (result.warning) {\n *   console.warn(result.warning)\n * }\n * ```\n */\nexport function validateAppId(key: string | undefined | null): KeyValidationResult {\n\treturn validateKeyForType(key, 'appId', APP_ID_PATTERN, 'NEXT_PUBLIC_SYLPHX_APP_ID')\n}\n\n/**\n * Validate and sanitize App ID, logging warnings.\n *\n * @deprecated Use validateAndSanitizePublicKey() for ADR-055 pk_* keys.\n * @throws Error if the key is invalid and cannot be sanitized\n * @returns The sanitized App ID\n */\nexport function validateAndSanitizeAppId(key: string | undefined | null): string {\n\tconst result = validateAppId(key)\n\n\tif (!result.valid) {\n\t\tthrow new Error(result.error)\n\t}\n\n\tif (result.warning) {\n\t\tconsole.warn(result.warning)\n\t}\n\n\treturn result.sanitizedKey\n}\n\n// =============================================================================\n// Public API — Secret Keys\n// =============================================================================\n\n/**\n * Validate a secret key and return detailed results\n *\n * @example\n * ```typescript\n * const result = validateSecretKey('sk_prod_...')\n * if (!result.valid) {\n *   throw new Error(result.error)\n * }\n * ```\n */\nexport function validateSecretKey(key: string | undefined | null): KeyValidationResult {\n\treturn validateKeyForType(key, 'secret', SECRET_KEY_PATTERN, 'secret credential')\n}\n\n/**\n * Validate and sanitize secret key, logging warnings\n *\n * @throws Error if the key is invalid and cannot be sanitized\n * @returns The sanitized secret key\n */\nexport function validateAndSanitizeSecretKey(key: string | undefined | null): string {\n\tconst result = validateSecretKey(key)\n\n\tif (!result.valid) {\n\t\tthrow new Error(result.error)\n\t}\n\n\tif (result.warning) {\n\t\tconsole.warn(result.warning)\n\t}\n\n\treturn result.sanitizedKey\n}\n\n// =============================================================================\n// Public API — Environment Detection (SSOT)\n// =============================================================================\n\n/**\n * Detect environment type from any key (App ID or Secret Key)\n *\n * @example\n * ```typescript\n * detectEnvironment('sk_dev_abc123')   // 'development'\n * detectEnvironment('app_prod_xyz789') // 'production'\n * detectEnvironment('sk_stg_qwe456')   // 'staging'\n * ```\n *\n * @throws Error if key format is invalid\n */\nexport function detectEnvironment(key: string): EnvironmentType {\n\t// Validate and sanitize first\n\tconst sanitized = key.trim().toLowerCase()\n\n\t// Check all key types (ADR-055 plus legacy compatibility)\n\tif (sanitized.startsWith('pk_')) {\n\t\tconst result = validatePublicKey(sanitized)\n\t\tif (!result.valid) throw new Error(result.error)\n\t\treturn result.environment!\n\t}\n\n\tif (sanitized.startsWith('sk_')) {\n\t\tconst result = validateSecretKey(sanitized)\n\t\tif (!result.valid) throw new Error(result.error)\n\t\treturn result.environment!\n\t}\n\n\tif (sanitized.startsWith('app_')) {\n\t\tconst result = validateAppId(sanitized)\n\t\tif (!result.valid) throw new Error(result.error)\n\t\treturn result.environment!\n\t}\n\n\tthrow new Error(\n\t\t`[Sylphx] Invalid key format. Key must start with 'pk_' (publishable), 'sk_' (secret), or 'app_' (legacy App ID).`,\n\t)\n}\n\n/**\n * Check if running in development environment based on key\n */\nexport function isDevelopmentKey(key: string): boolean {\n\treturn detectEnvironment(key) === 'development'\n}\n\n/**\n * Check if running in production environment based on key\n */\nexport function isProductionKey(key: string): boolean {\n\treturn detectEnvironment(key) === 'production'\n}\n\n// =============================================================================\n// Public API — Cookie Namespace (SSOT)\n// =============================================================================\n\n/**\n * Get the cookie namespace for a given secret key\n *\n * Used by auth middleware to namespace cookies per environment.\n * This prevents dev/staging/prod cookies from conflicting.\n *\n * @example\n * ```typescript\n * getCookieNamespace('sk_dev_abc123')  // 'sylphx_dev'\n * getCookieNamespace('sk_prod_xyz789') // 'sylphx_prod'\n * ```\n */\nexport function getCookieNamespace(secretKey: string): string {\n\tconst env = detectEnvironment(secretKey)\n\tconst shortEnv =\n\t\tenv === 'development' ? 'dev' : env === 'staging' ? 'stg' : env === 'preview' ? 'prev' : 'prod'\n\treturn `sylphx_${shortEnv}`\n}\n\n// =============================================================================\n// Public API — Key Type Detection\n// =============================================================================\n\n/**\n * Detect the type of key.\n *\n * @returns 'publicKey' (pk_*), 'appId' (legacy app_*), 'secret' (sk_*), or null if unknown\n */\nexport function detectKeyType(key: string): KeyType | null {\n\tconst sanitized = key.trim().toLowerCase()\n\tif (sanitized.startsWith('pk_')) return 'publicKey'\n\tif (sanitized.startsWith('app_')) return 'appId'\n\tif (sanitized.startsWith('sk_')) return 'secret'\n\treturn null\n}\n\n/**\n * Check if a key is a publishable/public key (pk_* or legacy app_*)\n */\nexport function isPublishableKey(key: string): boolean {\n\tconst t = detectKeyType(key)\n\treturn t === 'publicKey' || t === 'appId'\n}\n\n/**\n * Check if a key is an App ID (legacy app_* format)\n *\n * @deprecated Use isPublishableKey() to also accept new pk_* keys\n */\nexport function isAppId(key: string): boolean {\n\treturn detectKeyType(key) === 'appId'\n}\n\n/**\n * Check if a key is a secret key (sk_*)\n */\nexport function isSecretKey(key: string): boolean {\n\treturn detectKeyType(key) === 'secret'\n}\n\n/**\n * Validate any key (auto-detects type)\n *\n * Use this when you accept either App ID or Secret Key.\n * The function auto-detects the key type and validates accordingly.\n *\n * @example\n * ```typescript\n * const result = validateKey('sk_prod_...')\n * if (!result.valid) {\n *   throw new Error(result.error)\n * }\n * const sanitizedKey = result.sanitizedKey\n * ```\n */\nexport function validateKey(key: string | undefined | null): KeyValidationResult {\n\tconst keyType = key ? detectKeyType(key) : null\n\n\tif (keyType === 'publicKey') {\n\t\treturn validatePublicKey(key)\n\t}\n\tif (keyType === 'appId') {\n\t\treturn validateAppId(key)\n\t}\n\tif (keyType === 'secret') {\n\t\treturn validateSecretKey(key)\n\t}\n\n\t// Unknown key type - return detailed error\n\treturn {\n\t\tvalid: false,\n\t\tsanitizedKey: '',\n\t\terror: key\n\t\t\t? `Invalid key format. Keys must start with 'pk_' (publishable), 'app_' (legacy), or 'sk_' (secret), followed by environment (dev/stg/prod/prev). Got: ${key.slice(0, 20)}...`\n\t\t\t: 'API key is required but was not provided.',\n\t\tissues: key ? ['invalid_format'] : ['missing'],\n\t}\n}\n\n/**\n * Validate any key and return sanitized version (throws on error)\n *\n * Use this when you need the key value and want to throw on invalid input.\n */\nexport function validateAndSanitizeKey(key: string | undefined | null): string {\n\tconst result = validateKey(key)\n\tif (!result.valid) {\n\t\tthrow new Error(result.error)\n\t}\n\tif (result.warning) {\n\t\tconsole.warn(`[Sylphx] ${result.warning}`)\n\t}\n\treturn result.sanitizedKey\n}\n\n// =============================================================================\n// Public API — Runtime Environment Detection\n// =============================================================================\n\n/**\n * Check if we're in development mode (based on NODE_ENV or hostname)\n */\nexport function isDevelopmentRuntime(): boolean {\n\tif (typeof process !== 'undefined' && process.env) {\n\t\treturn process.env.NODE_ENV === 'development'\n\t}\n\tif (typeof window !== 'undefined') {\n\t\treturn window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1'\n\t}\n\treturn false\n}\n","/**\n * AI Context Value Factory\n *\n * Creates the AI context value for the SylphxProvider.\n * Provides OpenAI-compatible API access with chat, completion, embedding, and vision.\n */\n\nimport { DEFAULT_CONTEXT_WINDOW } from '../../constants'\nimport type { RestApiClient } from '../rest-client'\nimport type { AIContextValue } from '../services-context'\nimport type { AIProvider } from '../types'\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface CreateAIValueConfig {\n\t/** REST API client */\n\tapi: RestApiClient\n\t/** Platform URL */\n\tplatformUrl: string\n\t/** App ID for authentication */\n\tappId?: string\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\n/**\n * Infer AI provider from model ID\n */\nexport function inferProviderFromModelId(modelId: string): AIProvider {\n\tif (modelId.startsWith('gpt-') || modelId.includes('openai')) return 'openai'\n\tif (modelId.startsWith('claude-') || modelId.includes('anthropic')) return 'anthropic'\n\tif (modelId.startsWith('gemini-') || modelId.includes('google')) return 'google'\n\tif (modelId.startsWith('mistral-') || modelId.includes('mistral')) return 'mistral'\n\tif (modelId.includes('groq')) return 'groq'\n\tif (modelId.includes('together')) return 'together'\n\treturn 'openai' // Default\n}\n\n// =============================================================================\n// Factory\n// =============================================================================\n\n/**\n * Create AI context value.\n *\n * Uses OpenAI-compatible /api/v1/* endpoints for:\n * - Chat completions\n * - Streaming chat\n * - Text completion\n * - Embeddings\n * - Vision\n */\nexport function createAIValue(config: CreateAIValueConfig): AIContextValue {\n\tconst { api, platformUrl, appId } = config\n\n\t/**\n\t * AI API call helper with app ID authentication\n\t */\n\tconst aiApiCall = async <T>(endpoint: string, options: RequestInit = {}): Promise<T> => {\n\t\tconst response = await fetch(`${platformUrl}${endpoint}`, {\n\t\t\t...options,\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\tAuthorization: `Bearer ${appId}`,\n\t\t\t\t...options.headers,\n\t\t\t},\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.json().catch(() => ({ error: { message: 'API call failed' } }))\n\t\t\tthrow new Error(error.error?.message || 'API call failed')\n\t\t}\n\n\t\treturn response.json()\n\t}\n\n\treturn {\n\t\tchat: async (input) => {\n\t\t\tconst response = await aiApiCall<{\n\t\t\t\tid: string\n\t\t\t\tmodel: string\n\t\t\t\tchoices: Array<{\n\t\t\t\t\tindex: number\n\t\t\t\t\tmessage: { role: 'assistant'; content: string }\n\t\t\t\t\tfinish_reason: string\n\t\t\t\t}>\n\t\t\t\tusage: {\n\t\t\t\t\tprompt_tokens: number\n\t\t\t\t\tcompletion_tokens: number\n\t\t\t\t\ttotal_tokens: number\n\t\t\t\t}\n\t\t\t}>('/api/v1/chat/completions', {\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tmodel: input.model,\n\t\t\t\t\tmessages: input.messages,\n\t\t\t\t\ttemperature: input.temperature,\n\t\t\t\t\tmax_tokens: input.maxTokens,\n\t\t\t\t\ttop_p: input.topP,\n\t\t\t\t\tfrequency_penalty: input.frequencyPenalty,\n\t\t\t\t\tpresence_penalty: input.presencePenalty,\n\t\t\t\t\tstop: input.stop,\n\t\t\t\t\ttools: input.tools,\n\t\t\t\t}),\n\t\t\t})\n\n\t\t\treturn {\n\t\t\t\tid: response.id,\n\t\t\t\tmodel: response.model,\n\t\t\t\tchoices: response.choices.map((c) => ({\n\t\t\t\t\tindex: c.index,\n\t\t\t\t\tmessage: {\n\t\t\t\t\t\trole: c.message.role,\n\t\t\t\t\t\tcontent: c.message.content,\n\t\t\t\t\t},\n\t\t\t\t\tfinishReason: c.finish_reason as\n\t\t\t\t\t\t| 'stop'\n\t\t\t\t\t\t| 'length'\n\t\t\t\t\t\t| 'tool_calls'\n\t\t\t\t\t\t| 'content_filter'\n\t\t\t\t\t\t| null,\n\t\t\t\t})),\n\t\t\t\tusage: {\n\t\t\t\t\tpromptTokens: response.usage.prompt_tokens,\n\t\t\t\t\tcompletionTokens: response.usage.completion_tokens,\n\t\t\t\t\ttotalTokens: response.usage.total_tokens,\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\n\t\tchatStream: (input) => {\n\t\t\tconst controller = new AbortController()\n\n\t\t\treturn {\n\t\t\t\t[Symbol.asyncIterator]: async function* () {\n\t\t\t\t\tconst response = await fetch(`${platformUrl}/api/v1/chat/completions`, {\n\t\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t\t\t\tAuthorization: `Bearer ${appId}`,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\t\t\tmodel: input.model,\n\t\t\t\t\t\t\tmessages: input.messages,\n\t\t\t\t\t\t\ttemperature: input.temperature,\n\t\t\t\t\t\t\tmax_tokens: input.maxTokens,\n\t\t\t\t\t\t\ttop_p: input.topP,\n\t\t\t\t\t\t\tfrequency_penalty: input.frequencyPenalty,\n\t\t\t\t\t\t\tpresence_penalty: input.presencePenalty,\n\t\t\t\t\t\t\tstop: input.stop,\n\t\t\t\t\t\t\ttools: input.tools,\n\t\t\t\t\t\t\tstream: true,\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\t})\n\n\t\t\t\t\tif (!response.ok) {\n\t\t\t\t\t\tconst error = await response\n\t\t\t\t\t\t\t.json()\n\t\t\t\t\t\t\t.catch(() => ({ error: { message: 'Stream request failed' } }))\n\t\t\t\t\t\tthrow new Error(error.error?.message || 'Stream request failed')\n\t\t\t\t\t}\n\n\t\t\t\t\tconst reader = response.body?.getReader()\n\t\t\t\t\tif (!reader) {\n\t\t\t\t\t\tthrow new Error('No response body')\n\t\t\t\t\t}\n\n\t\t\t\t\tconst decoder = new TextDecoder()\n\t\t\t\t\tlet buffer = ''\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\twhile (true) {\n\t\t\t\t\t\t\tconst { done, value } = await reader.read()\n\t\t\t\t\t\t\tif (done) break\n\n\t\t\t\t\t\t\tbuffer += decoder.decode(value, { stream: true })\n\t\t\t\t\t\t\tconst lines = buffer.split('\\n')\n\t\t\t\t\t\t\tbuffer = lines.pop() || ''\n\n\t\t\t\t\t\t\tfor (const line of lines) {\n\t\t\t\t\t\t\t\tif (line.startsWith('data: ')) {\n\t\t\t\t\t\t\t\t\tconst data = line.slice(6).trim()\n\t\t\t\t\t\t\t\t\tif (data === '[DONE]') {\n\t\t\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tconst chunk = JSON.parse(data)\n\n\t\t\t\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\t\t\t\tid: chunk.id || '',\n\t\t\t\t\t\t\t\t\t\t\tmodel: chunk.model || input.model,\n\t\t\t\t\t\t\t\t\t\t\tchoices: (chunk.choices || []).map((c: Record<string, unknown>) => ({\n\t\t\t\t\t\t\t\t\t\t\t\tindex: typeof c.index === 'number' ? c.index : 0,\n\t\t\t\t\t\t\t\t\t\t\t\tdelta: {\n\t\t\t\t\t\t\t\t\t\t\t\t\trole: (c.delta as Record<string, unknown>)?.role as\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t| 'assistant'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t| undefined,\n\t\t\t\t\t\t\t\t\t\t\t\t\tcontent: (c.delta as Record<string, unknown>)?.content as\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t| string\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t| undefined,\n\t\t\t\t\t\t\t\t\t\t\t\t\ttoolCalls: (c.delta as Record<string, unknown>)?.tool_calls as\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t| unknown[]\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t| undefined,\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tfinishReason:\n\t\t\t\t\t\t\t\t\t\t\t\t\t(c.finish_reason as\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t| 'stop'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t| 'length'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t| 'tool_calls'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t| 'content_filter') || null,\n\t\t\t\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t\t\t// Skip malformed JSON lines\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\treader.releaseLock()\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\n\t\tcomplete: async (input) => {\n\t\t\tconst response = await aiApiCall<{\n\t\t\t\tid: string\n\t\t\t\tmodel: string\n\t\t\t\tchoices: Array<{\n\t\t\t\t\tmessage: { content: string }\n\t\t\t\t\tfinish_reason: string\n\t\t\t\t}>\n\t\t\t\tusage: {\n\t\t\t\t\tprompt_tokens: number\n\t\t\t\t\tcompletion_tokens: number\n\t\t\t\t\ttotal_tokens: number\n\t\t\t\t}\n\t\t\t}>('/api/v1/chat/completions', {\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tmodel: input.model,\n\t\t\t\t\tmessages: [{ role: 'user', content: input.prompt }],\n\t\t\t\t\ttemperature: input.temperature,\n\t\t\t\t\tmax_tokens: input.maxTokens,\n\t\t\t\t\tstop: input.stop,\n\t\t\t\t}),\n\t\t\t})\n\n\t\t\treturn {\n\t\t\t\tid: response.id,\n\t\t\t\tmodel: response.model,\n\t\t\t\tchoices: [\n\t\t\t\t\t{\n\t\t\t\t\t\tindex: 0,\n\t\t\t\t\t\ttext: response.choices[0]?.message.content ?? '',\n\t\t\t\t\t\tfinishReason: response.choices[0]?.finish_reason as 'stop' | 'length' | null,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tusage: {\n\t\t\t\t\tpromptTokens: response.usage.prompt_tokens,\n\t\t\t\t\tcompletionTokens: response.usage.completion_tokens,\n\t\t\t\t\ttotalTokens: response.usage.total_tokens,\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\n\t\tembed: async (input) => {\n\t\t\tconst response = await aiApiCall<{\n\t\t\t\tmodel: string\n\t\t\t\tdata: Array<{ index: number; embedding: number[] }>\n\t\t\t\tusage: { prompt_tokens: number; total_tokens: number }\n\t\t\t}>('/api/v1/embeddings', {\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tmodel: input.model,\n\t\t\t\t\tinput: input.input,\n\t\t\t\t\tdimensions: input.dimensions,\n\t\t\t\t}),\n\t\t\t})\n\n\t\t\treturn {\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tmodel: response.model,\n\t\t\t\tembeddings: response.data.map((d) => d.embedding),\n\t\t\t\tdata: response.data,\n\t\t\t\tusage: {\n\t\t\t\t\tpromptTokens: response.usage.prompt_tokens,\n\t\t\t\t\ttotalTokens: response.usage.total_tokens,\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\n\t\tvision: async (input) => {\n\t\t\tconst response = await aiApiCall<{\n\t\t\t\tid: string\n\t\t\t\tmodel: string\n\t\t\t\tchoices: Array<{\n\t\t\t\t\tindex: number\n\t\t\t\t\tmessage: { role: 'assistant'; content: string }\n\t\t\t\t\tfinish_reason: string\n\t\t\t\t}>\n\t\t\t\tusage: {\n\t\t\t\t\tprompt_tokens: number\n\t\t\t\t\tcompletion_tokens: number\n\t\t\t\t\ttotal_tokens: number\n\t\t\t\t}\n\t\t\t}>('/api/v1/chat/completions', {\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tmodel: input.model,\n\t\t\t\t\tmessages: input.messages,\n\t\t\t\t\tmax_tokens: input.maxTokens,\n\t\t\t\t}),\n\t\t\t})\n\n\t\t\treturn {\n\t\t\t\tid: response.id,\n\t\t\t\tmodel: response.model,\n\t\t\t\tchoices: response.choices.map((c) => ({\n\t\t\t\t\tindex: c.index,\n\t\t\t\t\tmessage: {\n\t\t\t\t\t\trole: c.message.role,\n\t\t\t\t\t\tcontent: c.message.content,\n\t\t\t\t\t},\n\t\t\t\t\tfinishReason: c.finish_reason as\n\t\t\t\t\t\t| 'stop'\n\t\t\t\t\t\t| 'length'\n\t\t\t\t\t\t| 'tool_calls'\n\t\t\t\t\t\t| 'content_filter'\n\t\t\t\t\t\t| null,\n\t\t\t\t})),\n\t\t\t\tusage: {\n\t\t\t\t\tpromptTokens: response.usage.prompt_tokens,\n\t\t\t\t\tcompletionTokens: response.usage.completion_tokens,\n\t\t\t\t\ttotalTokens: response.usage.total_tokens,\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\n\t\tgetUsage: async (period) => {\n\t\t\treturn await api.get('/ai/usage', { period })\n\t\t},\n\n\t\tgetRateLimitStatus: async () => {\n\t\t\treturn await api.get('/ai/rate-limit')\n\t\t},\n\n\t\tlistModels: async (options) => {\n\t\t\tconst response = await api.get<{\n\t\t\t\tmodels: Array<{\n\t\t\t\t\tid: string\n\t\t\t\t\tname?: string\n\t\t\t\t\tcontextWindow?: number\n\t\t\t\t\tcapabilities?: string[]\n\t\t\t\t\tinputCostPer1M?: number\n\t\t\t\t\toutputCostPer1M?: number\n\t\t\t\t\tdescription?: string\n\t\t\t\t}>\n\t\t\t\ttotal: number\n\t\t\t\thasMore: boolean\n\t\t\t}>('/ai/models', {\n\t\t\t\tcapability: options?.capability,\n\t\t\t\tsearch: options?.search,\n\t\t\t\tlimit: options?.limit?.toString(),\n\t\t\t\toffset: options?.offset?.toString(),\n\t\t\t})\n\n\t\t\treturn {\n\t\t\t\tmodels: response.models.map((m) => ({\n\t\t\t\t\tid: m.id,\n\t\t\t\t\tname: m.name || m.id,\n\t\t\t\t\tprovider: inferProviderFromModelId(m.id),\n\t\t\t\t\tcontextWindow: m.contextWindow || 0,\n\t\t\t\t\tmaxOutputTokens: Math.floor((m.contextWindow || DEFAULT_CONTEXT_WINDOW) / 4),\n\t\t\t\t\tcapabilities: m.capabilities || ['chat'],\n\t\t\t\t\tinputCostPer1M: m.inputCostPer1M ?? 0,\n\t\t\t\t\toutputCostPer1M: m.outputCostPer1M ?? 0,\n\t\t\t\t\tdescription: m.description || '',\n\t\t\t\t})),\n\t\t\t\ttotal: response.total,\n\t\t\t\thasMore: response.hasMore,\n\t\t\t}\n\t\t},\n\t}\n}\n","/**\n * Consent Context Value Factory\n *\n * Creates the Consent context value for the SylphxProvider.\n * Provides GDPR consent management.\n */\n\nimport type { AppConfig } from '../../types'\nimport type { RestApiClient } from '../rest-client'\nimport type { ConsentContextValue } from '../services-context'\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface CreateConsentValueConfig {\n\t/** REST API client */\n\tapi: RestApiClient\n\t/** Anonymous ID for unauthenticated users */\n\tanonymousId: string\n\t/** User ID (if authenticated) */\n\tuserId: string | null\n\t/** App configuration containing consent types */\n\tconfig: AppConfig\n}\n\n// =============================================================================\n// Factory\n// =============================================================================\n\n/**\n * Create Consent context value.\n */\nexport function createConsentValue(config: CreateConsentValueConfig): ConsentContextValue {\n\tconst { api, anonymousId, userId, config: appConfig } = config\n\n\treturn {\n\t\tanonymousId,\n\t\tuserId,\n\t\t// Consent types from server-fetched config\n\t\tinitialConsentTypes: appConfig.consentTypes,\n\n\t\tgetConsentTypes: async () => {\n\t\t\t// Return types from server-fetched config (no client fetch needed)\n\t\t\treturn appConfig.consentTypes\n\t\t},\n\n\t\tgetUserConsents: async () => {\n\t\t\t// API returns UserConsent shape: slug, category, name, required, granted, grantedAt, version\n\t\t\tconst consents = await api.get<\n\t\t\t\tArray<{\n\t\t\t\t\tslug: string\n\t\t\t\t\tcategory: 'necessary' | 'analytics' | 'marketing' | 'preferences' | 'functional'\n\t\t\t\t\tname: string\n\t\t\t\t\trequired: boolean\n\t\t\t\t\tgranted: boolean\n\t\t\t\t\tgrantedAt: string | null\n\t\t\t\t\tversion: number | null\n\t\t\t\t}>\n\t\t\t>('/consent', {\n\t\t\t\t// Only include userId if truthy (Zod optional doesn't accept null)\n\t\t\t\t...(userId && { userId }),\n\t\t\t\tanonymousId,\n\t\t\t})\n\t\t\t// Return consents as-is (matches UserConsent type from generated/api.d.ts)\n\t\t\treturn consents\n\t\t},\n\n\t\tsetConsents: async (consents) => {\n\t\t\treturn await api.post('/consent', {\n\t\t\t\t// Only include userId if it's truthy (Zod optional doesn't accept null)\n\t\t\t\t...(userId && { userId }),\n\t\t\t\tanonymousId,\n\t\t\t\tconsents,\n\t\t\t\tsource: 'banner',\n\t\t\t})\n\t\t},\n\n\t\tacceptAll: async () => {\n\t\t\treturn await api.post('/consent/accept-all', {\n\t\t\t\t// Only include userId if it's truthy (Zod optional doesn't accept null)\n\t\t\t\t...(userId && { userId }),\n\t\t\t\tanonymousId,\n\t\t\t\tsource: 'banner',\n\t\t\t})\n\t\t},\n\n\t\tdeclineOptional: async () => {\n\t\t\treturn await api.post('/consent/decline-optional', {\n\t\t\t\t// Only include userId if it's truthy (Zod optional doesn't accept null)\n\t\t\t\t...(userId && { userId }),\n\t\t\t\tanonymousId,\n\t\t\t\tsource: 'banner',\n\t\t\t})\n\t\t},\n\n\t\tcheckConsent: async (purposeSlug, defaults) => {\n\t\t\ttry {\n\t\t\t\tconst consents = await api.get<Array<{ slug: string; granted: boolean }>>('/consent', {\n\t\t\t\t\t// Only include userId if truthy (Zod optional doesn't accept null)\n\t\t\t\t\t...(userId && { userId }),\n\t\t\t\t\tanonymousId,\n\t\t\t\t})\n\t\t\t\t// Find consent for this purpose\n\t\t\t\tconst consent = consents.find((c) => c.slug === purposeSlug)\n\t\t\t\tif (consent) {\n\t\t\t\t\treturn consent.granted\n\t\t\t\t}\n\t\t\t\t// Purpose not found - use default if provided, otherwise false\n\t\t\t\treturn defaults?.defaultEnabled ?? false\n\t\t\t} catch {\n\t\t\t\t// On error, use default if provided\n\t\t\t\treturn defaults?.defaultEnabled ?? false\n\t\t\t}\n\t\t},\n\n\t\tgetHistory: async (options) => {\n\t\t\treturn await api.get('/consent/history', {\n\t\t\t\t// Only include userId if truthy (Zod optional doesn't accept null)\n\t\t\t\t...(userId && { userId }),\n\t\t\t\tanonymousId,\n\t\t\t\tlimit: options?.limit?.toString(),\n\t\t\t\tcursor: options?.cursor,\n\t\t\t})\n\t\t},\n\t}\n}\n","/**\n * Database Context Value Factory\n *\n * Creates the Database context value for the SylphxProvider.\n * NOTE: Database uses direct Neon connection, not SDK API.\n */\n\nimport type { DatabaseContextValue } from '../services-context'\n\n// =============================================================================\n// Factory\n// =============================================================================\n\n/**\n * Create Database context value.\n *\n * Note: Database queries through SDK hooks are not supported.\n * Users should use @sylphx/platform-sdk/db with DATABASE_URL from Console.\n */\nexport function createDatabaseValue(): DatabaseContextValue {\n\tconst errorMessage = (action: string) =>\n\t\t`Database ${action} through SDK hooks are not supported. ` +\n\t\t'Use @sylphx/platform-sdk/db with DATABASE_URL from the Console instead. ' +\n\t\t'See: https://sylphx.com/docs/database'\n\n\treturn {\n\t\tquery: async () => {\n\t\t\tthrow new Error(errorMessage('queries'))\n\t\t},\n\t\texecute: async () => {\n\t\t\tthrow new Error(errorMessage('mutations'))\n\t\t},\n\t\ttransaction: async () => {\n\t\t\tthrow new Error(errorMessage('transactions'))\n\t\t},\n\t}\n}\n","/**\n * Email Context Value Factory\n *\n * Creates the Email context value for the SylphxProvider.\n * Provides transactional email and newsletter management.\n */\n\nimport type { RestApiClient } from '../rest-client'\nimport type { EmailContextValue } from '../services-context'\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface CreateEmailValueConfig {\n\t/** REST API client */\n\tapi: RestApiClient\n}\n\n// =============================================================================\n// Factory\n// =============================================================================\n\n/**\n * Create Email context value.\n */\nexport function createEmailValue(config: CreateEmailValueConfig): EmailContextValue {\n\tconst { api } = config\n\n\treturn {\n\t\t// Transactional Email\n\t\tsend: async (options) => {\n\t\t\treturn await api.post('/email/send', options)\n\t\t},\n\t\tsendTemplated: async (options) => {\n\t\t\t// Cast template to expected type - SDK accepts any string, API has fixed set\n\t\t\tconst result = await api.post<{ success: boolean }>('/email/send-templated', {\n\t\t\t\t...options,\n\t\t\t\ttemplate: options.template as\n\t\t\t\t\t| 'welcome'\n\t\t\t\t\t| 'verification'\n\t\t\t\t\t| 'password_reset'\n\t\t\t\t\t| 'security_alert',\n\t\t\t})\n\t\t\treturn { success: result.success, template: options.template }\n\t\t},\n\t\tsendToUser: async (options) => {\n\t\t\treturn await api.post('/email/send-to-user', options)\n\t\t},\n\t\t// Marketing Email (Newsletter)\n\t\tnewsletter: {\n\t\t\tsubscribe: async (options) => {\n\t\t\t\treturn await api.post('/newsletter/subscribe', options)\n\t\t\t},\n\t\t\tverify: async (token) => {\n\t\t\t\treturn await api.post('/newsletter/verify', { token })\n\t\t\t},\n\t\t\tunsubscribe: async (email, token) => {\n\t\t\t\treturn await api.post('/newsletter/unsubscribe', { email, token })\n\t\t\t},\n\t\t\tresendVerification: async (email) => {\n\t\t\t\treturn await api.post('/newsletter/resend-verification', { email })\n\t\t\t},\n\t\t\tgetUnsubscribeInfo: async (token) => {\n\t\t\t\treturn await api.get('/newsletter/unsubscribe-info', { token })\n\t\t\t},\n\t\t\tupdatePreferences: async (email, preferences) => {\n\t\t\t\treturn await api.put('/newsletter/preferences', { email, preferences })\n\t\t\t},\n\t\t\tgetPreferences: async (email) => {\n\t\t\t\treturn await api.get('/newsletter/preferences', { email })\n\t\t\t},\n\t\t},\n\t}\n}\n","/**\n * Tasks Context Value Factory\n *\n * Creates the Tasks context value for the SylphxProvider.\n * Provides job scheduling, cron management, and job status checking.\n */\n\nimport type { RestApiClient } from '../rest-client'\nimport type { TasksContextValue } from '../services-context'\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface CreateTasksValueConfig {\n\t/** REST API client */\n\tapi: RestApiClient\n}\n\n// =============================================================================\n// Factory\n// =============================================================================\n\n/**\n * Create Tasks context value.\n */\nexport function createTasksValue(config: CreateTasksValueConfig): TasksContextValue {\n\tconst { api } = config\n\n\treturn {\n\t\tcheckStatus: async () => {\n\t\t\treturn await api.get('/tasks/status')\n\t\t},\n\t\tschedule: async (options) => {\n\t\t\treturn await api.post('/tasks/schedule', options)\n\t\t},\n\t\tcreateCron: async (options) => {\n\t\t\treturn await api.post('/tasks/cron', options)\n\t\t},\n\t\tpauseCron: async (scheduleId) => {\n\t\t\tconst result = await api.post<{ success: boolean }>(`/tasks/cron/${scheduleId}/pause`)\n\t\t\treturn result.success\n\t\t},\n\t\tresumeCron: async (scheduleId) => {\n\t\t\tconst result = await api.post<{ success: boolean }>(`/tasks/cron/${scheduleId}/resume`)\n\t\t\treturn result.success\n\t\t},\n\t\tdeleteCron: async (scheduleId) => {\n\t\t\tconst result = await api.del<{ success: boolean }>(`/tasks/cron/${scheduleId}`)\n\t\t\treturn result.success\n\t\t},\n\t\tgetJob: async (jobId) => {\n\t\t\treturn await api.get(`/tasks/${jobId}`)\n\t\t},\n\t\tlistTasks: async (options = {}) => {\n\t\t\tconst status = options.status === 'cancelled' ? undefined : options.status\n\t\t\treturn await api.get('/tasks', {\n\t\t\t\tstatus,\n\t\t\t\tlimit: options.limit?.toString(),\n\t\t\t\toffset: options.offset?.toString(),\n\t\t\t})\n\t\t},\n\t\tlistJobs: async (options = {}) => {\n\t\t\tconst status = options.status === 'cancelled' ? undefined : options.status\n\t\t\treturn await api.get('/tasks', {\n\t\t\t\tstatus,\n\t\t\t\tlimit: options.limit?.toString(),\n\t\t\t\toffset: options.offset?.toString(),\n\t\t\t})\n\t\t},\n\t\tcancelJob: async (jobId) => {\n\t\t\tconst result = await api.post<{ success: boolean }>(`/tasks/${jobId}/cancel`)\n\t\t\treturn result.success\n\t\t},\n\t}\n}\n","/**\n * Monitoring Context Value Factory\n *\n * Creates the Monitoring context value for the SylphxProvider.\n * Provides error tracking and message capture.\n */\n\nimport type { RestApiClient } from '../rest-client'\nimport type { MonitoringContextValue } from '../services-context'\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface CreateMonitoringValueConfig {\n\t/** REST API client */\n\tapi: RestApiClient\n}\n\n// =============================================================================\n// Factory\n// =============================================================================\n\n/**\n * Create Monitoring context value.\n */\nexport function createMonitoringValue(config: CreateMonitoringValueConfig): MonitoringContextValue {\n\tconst { api } = config\n\n\treturn {\n\t\tcaptureException: async (error, options = {}) => {\n\t\t\t// Transform Error object into structured format for API\n\t\t\tconst frames: Array<{\n\t\t\t\tfilename?: string\n\t\t\t\tfunction?: string\n\t\t\t\tlineno?: number\n\t\t\t\tcolno?: number\n\t\t\t\tin_app?: boolean\n\t\t\t}> = []\n\n\t\t\tif (error.stack) {\n\t\t\t\tconst lines = error.stack.split('\\n').slice(1)\n\t\t\t\tfor (const line of lines) {\n\t\t\t\t\tconst match = line.match(/^\\s*at\\s+(?:(.+?)\\s+)?(?:\\()?(.+?):(\\d+):(\\d+)\\)?$/)\n\t\t\t\t\tif (match) {\n\t\t\t\t\t\tframes.push({\n\t\t\t\t\t\t\tfunction: match[1] || '<anonymous>',\n\t\t\t\t\t\t\tfilename: match[2],\n\t\t\t\t\t\t\tlineno: Number.parseInt(match[3] ?? '0', 10),\n\t\t\t\t\t\t\tcolno: Number.parseInt(match[4] ?? '0', 10),\n\t\t\t\t\t\t\tin_app: !match[2]?.includes('node_modules'),\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn await api.post('/monitoring/exception', {\n\t\t\t\texception: {\n\t\t\t\t\tvalues: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: error.name || 'Error',\n\t\t\t\t\t\t\tvalue: error.message,\n\t\t\t\t\t\t\tstacktrace: frames.length > 0 ? { frames } : undefined,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\tlevel: options.level,\n\t\t\t\ttags: options.tags,\n\t\t\t\textra: options.extra,\n\t\t\t\tfingerprint: options.fingerprint,\n\t\t\t\troute: options.route,\n\t\t\t\tuserAgent: options.userAgent,\n\t\t\t})\n\t\t},\n\n\t\tcaptureMessage: async (message, options = {}) => {\n\t\t\treturn await api.post('/monitoring/message', {\n\t\t\t\tmessage,\n\t\t\t\tlevel: options.level,\n\t\t\t\ttags: options.tags,\n\t\t\t\textra: options.extra,\n\t\t\t\troute: options.route,\n\t\t\t})\n\t\t},\n\t}\n}\n","/**\n * Newsletter Context Value Factory\n *\n * Creates the Newsletter context value for the SylphxProvider.\n * Provides newsletter subscription management.\n */\n\nimport type { RestApiClient } from '../rest-client'\nimport type { NewsletterContextValue } from '../services-context'\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface CreateNewsletterValueConfig {\n\t/** REST API client */\n\tapi: RestApiClient\n}\n\n// =============================================================================\n// Factory\n// =============================================================================\n\n/**\n * Create Newsletter context value.\n */\nexport function createNewsletterValue(config: CreateNewsletterValueConfig): NewsletterContextValue {\n\tconst { api } = config\n\n\treturn {\n\t\tsubscribe: async (options) => {\n\t\t\treturn await api.post('/newsletter/subscribe', options)\n\t\t},\n\t\tverify: async (token) => {\n\t\t\treturn await api.post('/newsletter/verify', { token })\n\t\t},\n\t\tunsubscribe: async (email, token) => {\n\t\t\treturn await api.post('/newsletter/unsubscribe', { email, token })\n\t\t},\n\t\tresendVerification: async (email) => {\n\t\t\treturn await api.post('/newsletter/resend-verification', { email })\n\t\t},\n\t\tgetUnsubscribeInfo: async (token) => {\n\t\t\treturn await api.get('/newsletter/unsubscribe-info', { token })\n\t\t},\n\t\tupdatePreferences: async (email, preferences) => {\n\t\t\treturn await api.put('/newsletter/preferences', { email, preferences })\n\t\t},\n\t\tgetPreferences: async (email) => {\n\t\t\treturn await api.get('/newsletter/preferences', { email })\n\t\t},\n\t}\n}\n","/**\n * Webhooks Context Value Factory\n *\n * Creates the Webhooks context value for the SylphxProvider.\n * Provides webhook configuration and delivery management.\n */\n\nimport type { RestApiClient } from '../rest-client'\nimport type { WebhooksContextValue } from '../services-context'\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface CreateWebhooksValueConfig {\n\t/** REST API client */\n\tapi: RestApiClient\n}\n\n// =============================================================================\n// Factory\n// =============================================================================\n\n/**\n * Create Webhooks context value.\n */\nexport function createWebhooksValue(config: CreateWebhooksValueConfig): WebhooksContextValue {\n\tconst { api } = config\n\n\treturn {\n\t\tgetConfig: async () => {\n\t\t\treturn await api.get('/webhooks/config')\n\t\t},\n\t\tupdateConfig: async (options) => {\n\t\t\treturn await api.put('/webhooks/config', options)\n\t\t},\n\t\tgetDeliveries: async (options = {}) => {\n\t\t\treturn await api.get('/webhooks/deliveries', {\n\t\t\t\tlimit: options.limit?.toString(),\n\t\t\t\toffset: options.offset?.toString(),\n\t\t\t\tstatus: options.status,\n\t\t\t})\n\t\t},\n\t\treplayDelivery: async (deliveryId) => {\n\t\t\treturn await api.post(`/webhooks/deliveries/${deliveryId}/replay`)\n\t\t},\n\t\tgetStats: async (period) => {\n\t\t\treturn await api.get('/webhooks/stats', { period })\n\t\t},\n\t}\n}\n","/**\n * REST API Client — cookie BFF (ADR-3457)\n *\n * Browser authenticated calls use the same-origin BaaS proxy\n * (`baasPrefix`, default `/sylphx`) with `credentials: 'include'`.\n * Middleware attaches the HttpOnly session bearer upstream. JavaScript\n * never holds a Platform session JWT.\n */\n\nimport { SDK_PLATFORM, SDK_VERSION } from '../constants'\nimport type { TokenManager } from './token-manager'\n\n/** Must match `DEFAULT_BAAS_PREFIX` in nextjs/middleware-helpers (ADR-3457). */\nconst DEFAULT_BAAS_PREFIX = '/sylphx'\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Configuration for the authenticated REST client (client-side)\n *\n * Note: This is different from RestClientConfig in /rest-client.ts which is\n * for server-side usage with secret keys. This one uses cookie BFF for\n * authenticated browser requests.\n */\nexport interface AuthenticatedRestClientConfig {\n\t/**\n\t * @deprecated Ignored for browser BFF. Upstream `x-app-secret` is set by\n\t * middleware from server credentials, never from browser JS.\n\t */\n\tappId?: string\n\t/**\n\t * @deprecated Cross-origin `platformUrl` + bearer is forbidden for browser\n\t * session traffic. Prefer `baasPrefix` same-origin proxy.\n\t */\n\tplatformUrl?: string\n\t/** Same-origin BaaS proxy prefix (default `/sylphx`) */\n\tbaasPrefix?: string\n\t/** Session keep-alive (cookie refresh only; never returns a bearer) */\n\ttokenManager: TokenManager\n\t/** Auth prefix for session keep-alive (default `/auth`) */\n\tauthPrefix?: string\n}\n\nexport interface RestApiClient {\n\tget: <T>(path: string, query?: Record<string, string | undefined>) => Promise<T>\n\tpost: <T>(path: string, body?: unknown) => Promise<T>\n\tput: <T>(path: string, body?: unknown) => Promise<T>\n\tdel: <T>(path: string) => Promise<T>\n}\n\n// =============================================================================\n// Factory\n// =============================================================================\n\n/**\n * Create a REST API client that uses same-origin cookie BFF.\n *\n * @example\n * ```ts\n * const api = createRestApi({\n *   baasPrefix: '/sylphx',\n *   tokenManager,\n * })\n *\n * const profile = await api.get('/user/profile')\n * await api.post('/analytics/track', { event: 'click' })\n * ```\n */\nexport function createRestApi(config: AuthenticatedRestClientConfig): RestApiClient {\n\tconst baasPrefix = (config.baasPrefix ?? DEFAULT_BAAS_PREFIX).replace(/\\/+$/u, '') || '/sylphx'\n\tconst authPrefix = (config.authPrefix ?? '/auth').replace(/\\/+$/u, '') || '/auth'\n\n\tconst buildHeaders = (): Record<string, string> => ({\n\t\t'Content-Type': 'application/json',\n\t\t'X-SDK-Version': SDK_VERSION,\n\t\t'X-SDK-Platform': SDK_PLATFORM,\n\t})\n\n\tconst fetchWithAuth = async (\n\t\turl: string,\n\t\tmethod: string,\n\t\tbody?: unknown,\n\t\tretryOn401 = true,\n\t): Promise<Response> => {\n\t\tconst options: RequestInit = {\n\t\t\tmethod,\n\t\t\theaders: buildHeaders(),\n\t\t\tcredentials: 'include',\n\t\t\tcache: 'no-store',\n\t\t\t...(body !== undefined && { body: JSON.stringify(body) }),\n\t\t}\n\n\t\tconst res = await fetch(url, options)\n\n\t\t// 401 — best-effort cookie refresh then single retry (no JS bearer).\n\t\tif (res.status === 401 && retryOn401) {\n\t\t\tconfig.tokenManager.invalidate()\n\t\t\tconst refreshed = await config.tokenManager.ensureSession()\n\t\t\tif (!refreshed) {\n\t\t\t\treturn res\n\t\t\t}\n\t\t\treturn fetchWithAuth(url, method, body, false)\n\t\t}\n\n\t\treturn res\n\t}\n\n\tasync function handleResponse<T>(res: Response): Promise<T> {\n\t\tif (!res.ok) {\n\t\t\tconst err = await res.json().catch(() => ({ error: { message: 'Request failed' } }))\n\t\t\tthrow new Error(err.error?.message ?? err.message ?? 'Request failed')\n\t\t}\n\t\treturn res.json()\n\t}\n\n\tfunction resolveUrl(path: string, query?: Record<string, string | undefined>): string {\n\t\tconst normalized = path.startsWith('/') ? path : `/${path}`\n\t\t// Same-origin relative path only — never cross-origin platformUrl + bearer.\n\t\tconst url = new URL(`${baasPrefix}${normalized}`, 'http://bff.local')\n\t\tif (query) {\n\t\t\tObject.entries(query).forEach(([k, v]) => {\n\t\t\t\tif (v) url.searchParams.set(k, v)\n\t\t\t})\n\t\t}\n\t\treturn `${url.pathname}${url.search}`\n\t}\n\n\tasync function get<T>(path: string, query?: Record<string, string | undefined>): Promise<T> {\n\t\tconst res = await fetchWithAuth(resolveUrl(path, query), 'GET')\n\t\treturn handleResponse<T>(res)\n\t}\n\n\tasync function post<T>(path: string, body?: unknown): Promise<T> {\n\t\tconst res = await fetchWithAuth(resolveUrl(path), 'POST', body)\n\t\treturn handleResponse<T>(res)\n\t}\n\n\tasync function put<T>(path: string, body?: unknown): Promise<T> {\n\t\tconst res = await fetchWithAuth(resolveUrl(path), 'PUT', body)\n\t\treturn handleResponse<T>(res)\n\t}\n\n\tasync function del<T>(path: string): Promise<T> {\n\t\tconst res = await fetchWithAuth(resolveUrl(path), 'DELETE')\n\t\treturn handleResponse<T>(res)\n\t}\n\n\t// Silence unused authPrefix if tree-shaken — used for docs / future absolute fallbacks\n\tvoid authPrefix\n\n\treturn { get, post, put, del }\n}\n","/**\n * Storage Utilities — Non-Auth Data Only\n *\n * Namespaced localStorage utilities for client-side data.\n *\n * IMPORTANT: Auth tokens are NOT stored in localStorage.\n * All auth state lives in HttpOnly cookies (see nextjs/cookies.ts).\n *\n * This module handles:\n * - Anonymous ID (for analytics before sign-in)\n * - Click IDs (for ad conversion attribution)\n * - Consent preferences\n * - Organization selection\n */\n\nimport { CLICK_ID_EXPIRY_MS, STORAGE_KEY_PREFIX } from '../constants'\nimport type { UserCookieData } from '../types'\nimport type { ClickIds } from './platform-context'\n\n// Re-export for convenience\nexport type { ClickIds, UserCookieData }\n\n// =============================================================================\n// Storage Keys (Non-Auth Only)\n// =============================================================================\n\n/**\n * Storage key constants - all prefixed with appId\n *\n * NOTE: Auth tokens are NOT in localStorage.\n * They are stored in HttpOnly cookies for security.\n */\nexport const STORAGE_KEYS = {\n\t// Analytics\n\tANONYMOUS_ID: 'anonymous_id',\n\t/** Offline analytics queue (Segment pattern) - events queued when offline */\n\tOFFLINE_ANALYTICS_QUEUE: 'offline_queue',\n\n\t// Organization selection\n\tCURRENT_ORG: 'current_org',\n\n\t// Consent management\n\tCONSENT: 'consent',\n\tCONSENT_TIMESTAMP: 'consent_at',\n\n\t// Click IDs for conversion attribution (gclid, fbclid, ttclid)\n\tCLICK_IDS: 'click_ids',\n\tCLICK_IDS_CAPTURED_AT: 'click_ids_at',\n} as const\n\nexport type StorageKey = (typeof STORAGE_KEYS)[keyof typeof STORAGE_KEYS]\n\n// =============================================================================\n// Storage Manager\n// =============================================================================\n\n/**\n * Create namespaced storage key\n * Format: sylphx_{appId}_{key}\n */\nfunction createStorageKey(appId: string, key: StorageKey): string {\n\treturn `${STORAGE_KEY_PREFIX}${appId}_${key}`\n}\n\n/**\n * Storage manager with app-specific namespacing\n */\nexport class SylphxStorage {\n\tprivate appId: string\n\n\tconstructor(appId: string) {\n\t\tthis.appId = appId\n\t}\n\n\tprivate key(k: StorageKey): string {\n\t\treturn createStorageKey(this.appId, k)\n\t}\n\n\tget(key: StorageKey): string | null {\n\t\tif (typeof window === 'undefined') return null\n\t\ttry {\n\t\t\treturn localStorage.getItem(this.key(key))\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\tset(key: StorageKey, value: string): void {\n\t\tif (typeof window === 'undefined') return\n\t\ttry {\n\t\t\tlocalStorage.setItem(this.key(key), value)\n\t\t} catch {\n\t\t\t// Ignore storage errors (quota exceeded, etc.)\n\t\t}\n\t}\n\n\tremove(key: StorageKey): void {\n\t\tif (typeof window === 'undefined') return\n\t\ttry {\n\t\t\tlocalStorage.removeItem(this.key(key))\n\t\t} catch {\n\t\t\t// Ignore\n\t\t}\n\t}\n\n\tgetJSON<T>(key: StorageKey): T | null {\n\t\tconst value = this.get(key)\n\t\tif (!value) return null\n\t\ttry {\n\t\t\treturn JSON.parse(value) as T\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\tsetJSON<T>(key: StorageKey, value: T): void {\n\t\ttry {\n\t\t\tthis.set(key, JSON.stringify(value))\n\t\t} catch {\n\t\t\t// Ignore\n\t\t}\n\t}\n\n\t/**\n\t * Check if a key exists\n\t */\n\thas(key: StorageKey): boolean {\n\t\treturn this.get(key) !== null\n\t}\n\n\t/**\n\t * Clear all Sylphx storage for this app\n\t */\n\tclear(): void {\n\t\tif (typeof window === 'undefined') return\n\t\ttry {\n\t\t\tconst prefix = `${STORAGE_KEY_PREFIX}${this.appId}_`\n\t\t\tconst keysToRemove: string[] = []\n\n\t\t\tfor (let i = 0; i < localStorage.length; i++) {\n\t\t\t\tconst key = localStorage.key(i)\n\t\t\t\tif (key?.startsWith(prefix)) {\n\t\t\t\t\tkeysToRemove.push(key)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const key of keysToRemove) {\n\t\t\t\tlocalStorage.removeItem(key)\n\t\t\t}\n\t\t} catch {\n\t\t\t// Storage access failed (private browsing, iframe restrictions, etc.)\n\t\t}\n\t}\n}\n\n// =============================================================================\n// Anonymous ID\n// =============================================================================\n\n/**\n * Generate a unique anonymous ID (UUIDv4)\n */\nfunction generateAnonymousId(): string {\n\tif (typeof crypto !== 'undefined' && crypto.randomUUID) {\n\t\treturn crypto.randomUUID()\n\t}\n\t// Fallback for older browsers\n\treturn 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n\t\tconst r = (Math.random() * 16) | 0\n\t\tconst v = c === 'x' ? r : (r & 0x3) | 0x8\n\t\treturn v.toString(16)\n\t})\n}\n\n/**\n * Get or create anonymous ID\n */\nexport function getOrCreateAnonymousId(storage: SylphxStorage): string {\n\tlet anonymousId = storage.get(STORAGE_KEYS.ANONYMOUS_ID)\n\tif (!anonymousId) {\n\t\tanonymousId = generateAnonymousId()\n\t\tstorage.set(STORAGE_KEYS.ANONYMOUS_ID, anonymousId)\n\t}\n\treturn anonymousId\n}\n\n// =============================================================================\n// Click ID Utilities for Conversion Attribution\n// =============================================================================\n\n/** Click ID expiry from constants (90 days - standard attribution window) */\n\n/**\n * Capture click IDs from URL parameters\n *\n * Call this on page load to capture ad platform click IDs (gclid, fbclid, ttclid)\n * from URL query parameters. These are used for conversion attribution.\n *\n * @returns Captured click IDs (may be empty if none present)\n */\nfunction captureClickIdsFromUrl(): ClickIds {\n\tif (typeof window === 'undefined') return {}\n\n\tconst params = new URLSearchParams(window.location.search)\n\tconst clickIds: ClickIds = {}\n\n\tconst gclid = params.get('gclid')\n\tconst fbclid = params.get('fbclid')\n\tconst ttclid = params.get('ttclid')\n\n\tif (gclid) clickIds.gclid = gclid\n\tif (fbclid) clickIds.fbclid = fbclid\n\tif (ttclid) clickIds.ttclid = ttclid\n\n\treturn clickIds\n}\n\n/**\n * Get stored click IDs (if not expired)\n */\nexport function getStoredClickIds(storage: SylphxStorage): ClickIds | null {\n\tconst capturedAtStr = storage.get(STORAGE_KEYS.CLICK_IDS_CAPTURED_AT)\n\tif (!capturedAtStr) return null\n\n\tconst capturedAt = Number.parseInt(capturedAtStr, 10)\n\n\t// Handle corrupted data (NaN) or expired\n\tif (Number.isNaN(capturedAt) || Date.now() - capturedAt > CLICK_ID_EXPIRY_MS) {\n\t\t// Invalid or expired - clear and return null\n\t\tstorage.remove(STORAGE_KEYS.CLICK_IDS)\n\t\tstorage.remove(STORAGE_KEYS.CLICK_IDS_CAPTURED_AT)\n\t\treturn null\n\t}\n\n\treturn storage.getJSON<ClickIds>(STORAGE_KEYS.CLICK_IDS)\n}\n\n/**\n * Store click IDs with timestamp\n */\nfunction storeClickIds(storage: SylphxStorage, clickIds: ClickIds): void {\n\tif (Object.keys(clickIds).length === 0) return\n\n\t// Merge with existing (new values take precedence)\n\tconst existing = getStoredClickIds(storage) || {}\n\tconst merged = { ...existing, ...clickIds }\n\n\tstorage.setJSON(STORAGE_KEYS.CLICK_IDS, merged)\n\tstorage.set(STORAGE_KEYS.CLICK_IDS_CAPTURED_AT, Date.now().toString())\n}\n\n/**\n * Auto-capture click IDs from URL and store them\n *\n * This should be called once on provider mount to capture any click IDs\n * from the current URL. New click IDs override stored ones.\n *\n * @returns The merged click IDs (stored + new)\n */\nexport function autoCaptureClickIds(storage: SylphxStorage): ClickIds {\n\tconst urlClickIds = captureClickIdsFromUrl()\n\tconst storedClickIds = getStoredClickIds(storage) || {}\n\n\t// If we have new click IDs in URL, store them\n\tif (Object.keys(urlClickIds).length > 0) {\n\t\tstoreClickIds(storage, urlClickIds)\n\t\treturn { ...storedClickIds, ...urlClickIds }\n\t}\n\n\treturn storedClickIds\n}\n\n/**\n * Get the primary click ID for conversion attribution\n *\n * Returns the most relevant click ID based on priority:\n * gclid (Google) > fbclid (Meta) > ttclid (TikTok)\n */\nexport function getPrimaryClickId(clickIds: ClickIds | null): string | undefined {\n\tif (!clickIds) return undefined\n\treturn clickIds.gclid || clickIds.fbclid || clickIds.ttclid\n}\n\n// =============================================================================\n// User Cookie Reading (Client-Side)\n// =============================================================================\n\n/**\n * Derive cookie namespace from app ID (matching server-side logic)\n *\n * Server uses getCookieNamespace(secretKey) which returns sylphx_{env}\n * Both sk_prod_xxx and app_prod_xxx should map to sylphx_prod\n */\nfunction getCookieNamespaceFromAppId(appId: string): string {\n\t// Extract environment from appId (e.g., 'app_prod_xxx' → 'prod')\n\tconst parts = appId.split('_')\n\tif (parts.length < 2) return 'sylphx'\n\n\tconst envPart = parts[1] // 'dev', 'stg', or 'prod'\n\tconst shortEnv = envPart === 'development' ? 'dev' : envPart === 'staging' ? 'stg' : envPart\n\n\t// Match server-side format: sylphx_{shortEnv}\n\treturn `sylphx_${shortEnv}`\n}\n\n/**\n * Get user data from JS-readable cookie (set by server after OAuth)\n *\n * This enables client-side hydration after server-side OAuth callback:\n * 1. Server callback exchanges OAuth code for tokens\n * 2. Server sets HttpOnly token cookies + JS-readable user cookie\n * 3. Client reads user cookie on mount for immediate auth state\n *\n * @param appId - App ID used to namespace the cookie\n * @returns User data or null if not found/expired\n */\nexport function getUserFromCookie(appId: string): UserCookieData | null {\n\tif (typeof document === 'undefined') return null\n\n\ttry {\n\t\t// Cookie name format: __{namespace}_user\n\t\t// Namespace derived from appId to match server-side logic\n\t\tconst namespace = getCookieNamespaceFromAppId(appId)\n\t\tconst cookieName = `__${namespace}_user`\n\n\t\t// Parse cookies\n\t\tconst cookies = document.cookie.split(';')\n\t\tfor (const cookie of cookies) {\n\t\t\tconst [name, ...valueParts] = cookie.trim().split('=')\n\t\t\tif (name === cookieName) {\n\t\t\t\tconst value = valueParts.join('=') // Handle values with = in them\n\t\t\t\tconst decoded = decodeURIComponent(value)\n\t\t\t\tconst userData: UserCookieData = JSON.parse(decoded)\n\n\t\t\t\t// Check if session is expired\n\t\t\t\tif (userData.expiresAt && userData.expiresAt < Date.now()) {\n\t\t\t\t\treturn null\n\t\t\t\t}\n\n\t\t\t\treturn userData\n\t\t\t}\n\t\t}\n\t\treturn null\n\t} catch {\n\t\treturn null\n\t}\n}\n\n/**\n * Clear the user cookie (client-side)\n *\n * Call this on sign out to remove the user cookie.\n * Note: This only clears the JS-readable cookie.\n * The HttpOnly session/refresh cookies can only be cleared server-side.\n */\nexport function clearUserCookie(appId: string): void {\n\tif (typeof document === 'undefined') return\n\n\ttry {\n\t\tconst namespace = getCookieNamespaceFromAppId(appId)\n\t\tconst cookieName = `__${namespace}_user`\n\t\t// Set cookie with expired date to delete it.\n\t\t// biome-ignore lint/suspicious/noDocumentCookie: SDK runs in the browser and ships to 3rd-party apps; the async Cookie Store API is not universally available on the target browsers and breaks on Safari 16. Direct document.cookie is the portable path.\n\t\tdocument.cookie = `${cookieName}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`\n\t} catch {\n\t\t// Ignore errors\n\t}\n}\n","/**\n * Session keep-alive manager (ADR-3457).\n *\n * Historical `TokenManager` fetched GET `{authPrefix}/token` and cached the\n * session JWT in JavaScript memory for `Authorization` headers. That was\n * token exfiltration, not BFF.\n *\n * Contract now:\n * - Never returns a session bearer to callers (`getToken()` → always `null`)\n * - May ping GET `{authPrefix}/token` to refresh HttpOnly cookies only\n * - Authenticated browser API calls use same-origin `baasPrefix` + cookies\n *\n * @deprecated Prefer same-origin BaaS proxy (`credentials: 'include'`). The\n * `getToken` name remains for type compatibility and always returns `null`.\n */\n\nimport { BASE_RETRY_DELAY_MS, MAX_RETRIES } from '../constants'\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface TokenManagerConfig {\n\t/** Check if user is signed in */\n\tisSignedIn: () => boolean\n\t/** Called when session refresh fails (e.g., session expired) */\n\tonSessionExpired?: () => void\n\t/** Auth route prefix (e.g., '/auth') */\n\tauthPrefix: string\n}\n\n// =============================================================================\n// Token Manager Class (session keep-alive only)\n// =============================================================================\n\nexport class TokenManager {\n\tprivate fetchPromise: Promise<boolean> | null = null\n\tprivate config: TokenManagerConfig\n\n\tconstructor(config: TokenManagerConfig) {\n\t\tthis.config = config\n\t}\n\n\t/**\n\t * @deprecated ADR-3457 — session bearers are never returned to browser JS.\n\t * Always returns `null`. Use same-origin BaaS proxy with cookies instead.\n\t */\n\tasync getToken(): Promise<string | null> {\n\t\tif (!this.config.isSignedIn()) {\n\t\t\treturn null\n\t\t}\n\t\t// Best-effort cookie refresh; never return bearer material.\n\t\tawait this.ensureSession()\n\t\treturn null\n\t}\n\n\t/**\n\t * Ensure HttpOnly session cookies are still valid (refresh if needed).\n\t * Does not return or cache any bearer token.\n\t */\n\tasync ensureSession(): Promise<boolean> {\n\t\tif (!this.config.isSignedIn()) {\n\t\t\treturn false\n\t\t}\n\t\tif (this.fetchPromise) {\n\t\t\treturn this.fetchPromise\n\t\t}\n\t\tthis.fetchPromise = this.refreshSessionCookiesWithRetry()\n\t\ttry {\n\t\t\treturn await this.fetchPromise\n\t\t} finally {\n\t\t\tthis.fetchPromise = null\n\t\t}\n\t}\n\n\t/**\n\t * No-op: no in-memory bearer is cached after ADR-3457.\n\t */\n\tinvalidate(): void {\n\t\t// Intentionally empty — no JS-held token to invalidate.\n\t}\n\n\t/**\n\t * Clear in-flight keep-alive work (call on sign out).\n\t */\n\tclear(): void {\n\t\tthis.fetchPromise = null\n\t}\n\n\tprivate async refreshSessionCookiesWithRetry(): Promise<boolean> {\n\t\tfor (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(`${this.config.authPrefix}/token`, {\n\t\t\t\t\tmethod: 'GET',\n\t\t\t\t\tcredentials: 'include',\n\t\t\t\t\tcache: 'no-store',\n\t\t\t\t})\n\n\t\t\t\tif (response.ok) {\n\t\t\t\t\t// Body is safe session metadata only — never parse for a bearer.\n\t\t\t\t\treturn true\n\t\t\t\t}\n\n\t\t\t\tif (response.status === 401) {\n\t\t\t\t\tthis.config.onSessionExpired?.()\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Network error — retry with backoff\n\t\t\t}\n\n\t\t\tif (attempt < MAX_RETRIES - 1) {\n\t\t\t\tawait new Promise((r) => setTimeout(r, BASE_RETRY_DELAY_MS * 2 ** attempt))\n\t\t\t}\n\t\t}\n\n\t\treturn false\n\t}\n}\n","/**\n * RBAC Hooks\n *\n * React hooks for permissions and roles management.\n *\n * ## Hook Types\n *\n * - **usePermissions()** — List project permissions (admin, React Query)\n * - **useRoles()** — List project roles (admin, React Query)\n * - **useMemberPermissions(orgIdOrSlug, memberId)** — Get member's resolved permissions\n * - **useHasPermission(permissions, required)** — Pure client-side permission check\n *\n * ## Architecture\n *\n * Admin hooks (usePermissions, useRoles) call the SDK pure functions with a\n * config derived from PlatformContext, wrapped in React Query for caching.\n *\n * useHasPermission is a pure synchronous check — no API call, no context needed.\n * It operates on a permissions array (from JWT claims or getMemberPermissions).\n */\n\n'use client'\n\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useCallback, useContext, useMemo } from 'react'\nimport { createConfig, withToken } from '../config'\nimport type { Permission } from '../permissions'\nimport * as PermissionFunctions from '../permissions'\nimport type { Role } from '../roles'\nimport * as RoleFunctions from '../roles'\nimport { AuthContext } from './context'\nimport { PlatformContext } from './platform-context'\n\n// Re-export types for convenience\nexport type { CreatePermissionInput, MemberPermissionsResult, Permission } from '../permissions'\nexport type { CreateRoleInput, Role, UpdateRoleInput } from '../roles'\n\n// ============================================================================\n// Internal Helpers\n// ============================================================================\n\n/**\n * Build a SylphxConfig from PlatformContext + AuthContext.\n * Returns null if platform context is not available.\n */\nfunction useSdkConfig() {\n\tconst platform = useContext(PlatformContext)\n\tconst auth = useContext(AuthContext)\n\n\treturn useMemo(() => {\n\t\tif (!platform?.slug) return null\n\n\t\tlet config = createConfig({\n\t\t\tsecretKey: platform.appId,\n\t\t\tslug: platform.slug,\n\t\t})\n\n\t\t// Attach access token for authenticated endpoints\n\t\tif (auth?.accessToken) {\n\t\t\tconfig = withToken(config, auth.accessToken)\n\t\t}\n\n\t\treturn config\n\t}, [platform?.slug, platform?.appId, auth?.accessToken])\n}\n\n// ============================================================================\n// Query Key Factories\n// ============================================================================\n\nconst rbacKeys = {\n\tall: ['rbac'] as const,\n\tpermissions: () => [...rbacKeys.all, 'permissions'] as const,\n\troles: () => [...rbacKeys.all, 'roles'] as const,\n\tmemberPermissions: (orgIdOrSlug: string, memberId: string) =>\n\t\t[...rbacKeys.all, 'memberPermissions', orgIdOrSlug, memberId] as const,\n}\n\n// ============================================================================\n// usePermissions\n// ============================================================================\n\nexport interface UsePermissionsReturn {\n\t/** All permissions for the current project */\n\tpermissions: Permission[]\n\t/** Whether permissions are loading */\n\tisLoading: boolean\n\t/** Loading error */\n\terror: Error | null\n\t/** Refresh the permissions list */\n\trefresh: () => Promise<void>\n}\n\n/**\n * Hook to list all permissions for the current project.\n *\n * Uses React Query for caching and deduplication. Requires the SDK\n * to be configured with a secret key (admin operation).\n *\n * @example\n * ```tsx\n * function PermissionList() {\n *   const { permissions, isLoading } = usePermissions()\n *\n *   if (isLoading) return <Spinner />\n *\n *   return (\n *     <ul>\n *       {permissions.map(p => (\n *         <li key={p.key}>\n *           {p.name} ({p.key})\n *           {p.isSystem && <Badge>System</Badge>}\n *         </li>\n *       ))}\n *     </ul>\n *   )\n * }\n * ```\n */\nexport function usePermissions(): UsePermissionsReturn {\n\tconst config = useSdkConfig()\n\tconst queryClient = useQueryClient()\n\n\tconst { data, isLoading, error } = useQuery({\n\t\tqueryKey: rbacKeys.permissions(),\n\t\tqueryFn: async () => {\n\t\t\tif (!config) throw new Error('SDK not configured — wrap your app in SylphxProvider')\n\t\t\treturn PermissionFunctions.listPermissions(config)\n\t\t},\n\t\tenabled: !!config,\n\t\tstaleTime: 30_000, // 30s — permissions change rarely\n\t})\n\n\tconst refresh = useCallback(async () => {\n\t\tawait queryClient.invalidateQueries({ queryKey: rbacKeys.permissions() })\n\t}, [queryClient])\n\n\treturn {\n\t\tpermissions: data?.permissions ?? [],\n\t\tisLoading,\n\t\terror: error as Error | null,\n\t\trefresh,\n\t}\n}\n\n// ============================================================================\n// useRoles\n// ============================================================================\n\nexport interface UseRolesReturn {\n\t/** All roles for the current project (with permission keys) */\n\troles: Role[]\n\t/** Whether roles are loading */\n\tisLoading: boolean\n\t/** Loading error */\n\terror: Error | null\n\t/** Refresh the roles list */\n\trefresh: () => Promise<void>\n}\n\n/**\n * Hook to list all roles for the current project.\n *\n * Returns both system-defined and custom roles, each with their\n * assigned permission keys. Uses React Query for caching.\n *\n * @example\n * ```tsx\n * function RoleList() {\n *   const { roles, isLoading } = useRoles()\n *\n *   if (isLoading) return <Spinner />\n *\n *   return (\n *     <ul>\n *       {roles.map(r => (\n *         <li key={r.key}>\n *           {r.name} — {r.permissions.length} permissions\n *           {r.isDefault && <Badge>Default</Badge>}\n *         </li>\n *       ))}\n *     </ul>\n *   )\n * }\n * ```\n */\nexport function useRoles(): UseRolesReturn {\n\tconst config = useSdkConfig()\n\tconst queryClient = useQueryClient()\n\n\tconst { data, isLoading, error } = useQuery({\n\t\tqueryKey: rbacKeys.roles(),\n\t\tqueryFn: async () => {\n\t\t\tif (!config) throw new Error('SDK not configured — wrap your app in SylphxProvider')\n\t\t\treturn RoleFunctions.listRoles(config)\n\t\t},\n\t\tenabled: !!config,\n\t\tstaleTime: 30_000, // 30s — roles change rarely\n\t})\n\n\tconst refresh = useCallback(async () => {\n\t\tawait queryClient.invalidateQueries({ queryKey: rbacKeys.roles() })\n\t}, [queryClient])\n\n\treturn {\n\t\troles: data?.roles ?? [],\n\t\tisLoading,\n\t\terror: error as Error | null,\n\t\trefresh,\n\t}\n}\n\n// ============================================================================\n// useMemberPermissions\n// ============================================================================\n\nexport interface UseMemberPermissionsReturn {\n\t/** Prefixed user ID of the member */\n\tmemberId: string | null\n\t/** Assigned role info (null if no role or still loading) */\n\trole: { key: string; name: string } | null\n\t/** Resolved permission keys for the member */\n\tpermissions: string[]\n\t/** Whether data is loading */\n\tisLoading: boolean\n\t/** Loading error */\n\terror: Error | null\n\t/** Refresh member permissions */\n\trefresh: () => Promise<void>\n}\n\n/**\n * Hook to get a member's resolved permissions within an organization.\n *\n * Returns the flattened, deduplicated set of permission keys from all\n * roles assigned to the member. Requires the caller to be a member\n * of the same organization.\n *\n * @example\n * ```tsx\n * function MemberPermissions({ orgSlug, memberId }: Props) {\n *   const { permissions, role, isLoading } = useMemberPermissions(orgSlug, memberId)\n *\n *   if (isLoading) return <Spinner />\n *\n *   return (\n *     <div>\n *       <p>Role: {role?.name ?? 'None'}</p>\n *       <ul>\n *         {permissions.map(p => <li key={p}>{p}</li>)}\n *       </ul>\n *     </div>\n *   )\n * }\n * ```\n */\nexport function useMemberPermissions(\n\torgIdOrSlug: string | undefined,\n\tmemberId: string | undefined,\n): UseMemberPermissionsReturn {\n\tconst config = useSdkConfig()\n\tconst queryClient = useQueryClient()\n\n\tconst enabled = !!config && !!orgIdOrSlug && !!memberId\n\n\tconst { data, isLoading, error } = useQuery({\n\t\tqueryKey: rbacKeys.memberPermissions(orgIdOrSlug ?? '', memberId ?? ''),\n\t\tqueryFn: async () => {\n\t\t\tif (!config || !orgIdOrSlug || !memberId) {\n\t\t\t\tthrow new Error('Missing required parameters')\n\t\t\t}\n\t\t\treturn PermissionFunctions.getMemberPermissions(config, orgIdOrSlug, memberId)\n\t\t},\n\t\tenabled,\n\t\tstaleTime: 15_000, // 15s — member permissions may change more frequently\n\t})\n\n\tconst refresh = useCallback(async () => {\n\t\tif (orgIdOrSlug && memberId) {\n\t\t\tawait queryClient.invalidateQueries({\n\t\t\t\tqueryKey: rbacKeys.memberPermissions(orgIdOrSlug, memberId),\n\t\t\t})\n\t\t}\n\t}, [queryClient, orgIdOrSlug, memberId])\n\n\treturn {\n\t\tmemberId: data?.memberId ?? null,\n\t\trole: data?.role ?? null,\n\t\tpermissions: data?.permissions ?? [],\n\t\tisLoading: enabled ? isLoading : false,\n\t\terror: error as Error | null,\n\t\trefresh,\n\t}\n}\n\n// ============================================================================\n// useHasPermission\n// ============================================================================\n\nexport interface UseHasPermissionReturn {\n\t/** Whether the required permission(s) are satisfied */\n\tallowed: boolean\n\t/** Whether any of the required permissions are satisfied (OR logic) */\n\tallowedAny: boolean\n\t/** Whether all of the required permissions are satisfied (AND logic) */\n\tallowedAll: boolean\n}\n\n/**\n * Pure client-side permission check hook.\n *\n * Operates on a permissions array — no API call. Use with:\n * - Permissions array from useMemberPermissions() hook\n * - Any string[] of permission keys from your application state\n *\n * Accepts a single permission string or an array. When given an array,\n * returns both OR (`allowedAny`) and AND (`allowedAll`) results.\n *\n * @example\n * ```tsx\n * function PayrollButton({ permissions }: { permissions: string[] }) {\n *   const { allowed } = useHasPermission(permissions, 'payroll:approve')\n *\n *   if (!allowed) return null\n *\n *   return <button>Approve Payroll</button>\n * }\n * ```\n *\n * @example\n * ```tsx\n * function AdminPanel({ permissions }: { permissions: string[] }) {\n *   const { allowedAll } = useHasPermission(permissions, [\n *     'org:settings:manage',\n *     'org:members:manage',\n *   ])\n *\n *   if (!allowedAll) return <AccessDenied />\n *\n *   return <AdminSettings />\n * }\n * ```\n */\nexport function useHasPermission(\n\tpermissions: string[],\n\trequired: string | string[],\n): UseHasPermissionReturn {\n\treturn useMemo(() => {\n\t\tconst requiredArray = Array.isArray(required) ? required : [required]\n\n\t\treturn {\n\t\t\tallowed: Array.isArray(required)\n\t\t\t\t? PermissionFunctions.hasAllPermissions(permissions, requiredArray)\n\t\t\t\t: PermissionFunctions.hasPermission(permissions, required),\n\t\t\tallowedAny: PermissionFunctions.hasAnyPermission(permissions, requiredArray),\n\t\t\tallowedAll: PermissionFunctions.hasAllPermissions(permissions, requiredArray),\n\t\t}\n\t}, [permissions, required])\n}\n","/**\n * Permission Functions\n *\n * Pure functions for permission management — no hidden state.\n * Each function takes config as the first parameter.\n *\n * Uses REST API at /permissions/* for project-scoped operations.\n * Uses REST API at /orgs/{orgId}/members/{memberId}/permissions for member checks.\n *\n * Types are self-contained (not dependent on generated OpenAPI spec) because\n * the RBAC routes were added after the last spec generation.\n */\n\nimport { callApi, type SylphxConfig } from './config'\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * A permission definition within a project.\n *\n * Permissions are the atomic building blocks of RBAC roles.\n * They use colon-separated keys (e.g. \"org:members:read\", \"payroll:approve\").\n */\nexport interface Permission {\n\t/** Prefixed permission ID (e.g. \"perm_xxx\") */\n\tid: string\n\t/** Unique key within the project (e.g. \"org:members:read\") */\n\tkey: string\n\t/** Human-readable name */\n\tname: string\n\t/** Optional description */\n\tdescription: string | null\n\t/** Whether this is a system-defined permission (immutable) */\n\tisSystem: boolean\n\t/** ISO 8601 creation timestamp */\n\tcreatedAt: string\n}\n\n/**\n * Input for creating a custom permission.\n */\nexport interface CreatePermissionInput {\n\t/** Unique key — colon-separated lowercase segments (e.g. \"org:leave:approve\") */\n\tkey: string\n\t/** Human-readable name */\n\tname: string\n\t/** Optional description */\n\tdescription?: string\n}\n\n/**\n * Resolved permissions for a member, including their assigned role.\n */\nexport interface MemberPermissionsResult {\n\t/** Prefixed user ID of the member */\n\tmemberId: string\n\t/** Assigned role (null if no role assigned) */\n\trole: { key: string; name: string } | null\n\t/** Flattened, deduplicated permission keys from all assigned roles */\n\tpermissions: string[]\n}\n\n// ============================================================================\n// Permission CRUD (project-scoped, requires secretKey)\n// ============================================================================\n\n/**\n * List all permissions for the current project.\n *\n * Returns both system-defined and custom permissions.\n * Requires a secret key (server-side only).\n *\n * @example\n * ```typescript\n * const { permissions } = await listPermissions(config)\n * console.log(permissions.map(p => p.key))\n * // ['org:members:read', 'org:members:manage', 'payroll:view', ...]\n * ```\n */\nexport async function listPermissions(\n\tconfig: SylphxConfig,\n): Promise<{ permissions: Permission[] }> {\n\treturn callApi<{ permissions: Permission[] }>(config, '/permissions')\n}\n\n/**\n * Create a custom permission for the project.\n *\n * Permission keys must be colon-separated lowercase segments\n * (e.g. \"org:leave:approve\", \"payroll:run\").\n * Requires a secret key (server-side only).\n *\n * @example\n * ```typescript\n * const { permission } = await createPermission(config, {\n *   key: 'payroll:approve',\n *   name: 'Approve Payroll',\n *   description: 'Can approve payroll runs for the organization',\n * })\n * ```\n */\nexport async function createPermission(\n\tconfig: SylphxConfig,\n\tinput: CreatePermissionInput,\n): Promise<{ permission: Permission }> {\n\treturn callApi<{ permission: Permission }>(config, '/permissions', {\n\t\tmethod: 'POST',\n\t\tbody: input,\n\t})\n}\n\n/**\n * Delete a custom permission by key.\n *\n * System permissions cannot be deleted.\n * Role-permission assignments are removed automatically via cascading delete.\n * Requires a secret key (server-side only).\n *\n * @example\n * ```typescript\n * const { success } = await deletePermission(config, 'payroll:approve')\n * ```\n */\nexport async function deletePermission(\n\tconfig: SylphxConfig,\n\tpermissionKey: string,\n): Promise<{ success: boolean }> {\n\treturn callApi<{ success: boolean }>(config, `/permissions/${permissionKey}`, {\n\t\tmethod: 'DELETE',\n\t})\n}\n\n// ============================================================================\n// Member Permissions (org-scoped, requires accessToken)\n// ============================================================================\n\n/**\n * Get a member's resolved permissions within an organization.\n *\n * Returns the flattened, deduplicated set of permission keys from all\n * roles assigned to the member. Also returns their current role info.\n * Requires the caller to be a member of the same organization.\n *\n * @example\n * ```typescript\n * const result = await getMemberPermissions(config, 'my-org', 'usr_abc123')\n * console.log(result.permissions)\n * // ['org:members:read', 'payroll:view', 'payroll:approve']\n * console.log(result.role)\n * // { key: 'hr_manager', name: 'HR Manager' }\n * ```\n */\nexport async function getMemberPermissions(\n\tconfig: SylphxConfig,\n\torgIdOrSlug: string,\n\tmemberId: string,\n): Promise<MemberPermissionsResult> {\n\treturn callApi<MemberPermissionsResult>(\n\t\tconfig,\n\t\t`/orgs/${orgIdOrSlug}/members/${memberId}/permissions`,\n\t)\n}\n\n// ============================================================================\n// Pure Helpers (no API calls — client-side permission checks)\n// ============================================================================\n\n/**\n * Check if a permission set includes a specific permission.\n *\n * Pure function — no API call. Use with permissions from JWT claims\n * (org_permissions) or from getMemberPermissions().\n *\n * @example\n * ```typescript\n * const permissions = ['org:members:read', 'payroll:view']\n * hasPermission(permissions, 'payroll:view')    // true\n * hasPermission(permissions, 'payroll:approve') // false\n * ```\n */\nexport function hasPermission(permissions: string[], required: string): boolean {\n\treturn permissions.includes(required)\n}\n\n/**\n * Check if a permission set includes ANY of the required permissions.\n *\n * Pure function — no API call. Returns true if at least one of the\n * required permissions is present.\n *\n * @example\n * ```typescript\n * const permissions = ['org:members:read', 'payroll:view']\n * hasAnyPermission(permissions, ['payroll:view', 'payroll:approve']) // true\n * hasAnyPermission(permissions, ['admin:full', 'super:admin'])       // false\n * ```\n */\nexport function hasAnyPermission(permissions: string[], required: string[]): boolean {\n\treturn required.some((perm) => permissions.includes(perm))\n}\n\n/**\n * Check if a permission set includes ALL of the required permissions.\n *\n * Pure function — no API call. Returns true only if every required\n * permission is present.\n *\n * @example\n * ```typescript\n * const permissions = ['org:members:read', 'payroll:view', 'payroll:approve']\n * hasAllPermissions(permissions, ['payroll:view', 'payroll:approve']) // true\n * hasAllPermissions(permissions, ['payroll:view', 'admin:full'])      // false\n * ```\n */\nexport function hasAllPermissions(permissions: string[], required: string[]): boolean {\n\treturn required.every((perm) => permissions.includes(perm))\n}\n","/**\n * Role Functions\n *\n * Pure functions for role management — no hidden state.\n * Each function takes config as the first parameter.\n *\n * Uses REST API at /roles/* for project-scoped operations.\n * Uses REST API at /orgs/{orgId}/members/{memberId}/assign-role for assignment.\n *\n * Types are self-contained (not dependent on generated OpenAPI spec) because\n * the RBAC routes were added after the last spec generation.\n */\n\nimport { callApi, type SylphxConfig } from './config'\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * A role definition within a project.\n *\n * Roles bundle permissions into named groups that can be assigned to\n * organization members (e.g. \"HR Manager\", \"Payroll Admin\").\n */\nexport interface Role {\n\t/** Prefixed role ID (e.g. \"role_xxx\") */\n\tid: string\n\t/** Unique key within the project (e.g. \"hr_manager\") */\n\tkey: string\n\t/** Human-readable name */\n\tname: string\n\t/** Optional description */\n\tdescription: string | null\n\t/** Whether this is a system-defined role (metadata immutable) */\n\tisSystem: boolean\n\t/** Whether this role is automatically assigned to new org members */\n\tisDefault: boolean\n\t/** Display order (lower = higher priority) */\n\tsortOrder: number\n\t/** Permission keys assigned to this role */\n\tpermissions: string[]\n\t/** ISO 8601 creation timestamp */\n\tcreatedAt: string\n\t/** ISO 8601 update timestamp (present on roles route response) */\n\tupdatedAt?: string\n}\n\n/**\n * Input for creating a custom role.\n */\nexport interface CreateRoleInput {\n\t/** Unique key — lowercase alphanumeric with underscores (e.g. \"hr_manager\") */\n\tkey: string\n\t/** Human-readable name */\n\tname: string\n\t/** Optional description */\n\tdescription?: string\n\t/** Permission keys to assign to this role */\n\tpermissions?: string[]\n\t/** Whether to auto-assign to new org members */\n\tisDefault?: boolean\n\t/** Display order (lower = higher priority) */\n\tsortOrder?: number\n}\n\n/**\n * Input for updating an existing role.\n *\n * System role metadata (name, description) is immutable, but their\n * permissions can be changed.\n */\nexport interface UpdateRoleInput {\n\t/** Human-readable name (ignored for system roles) */\n\tname?: string\n\t/** Description (ignored for system roles) */\n\tdescription?: string | null\n\t/** Permission keys to assign (replaces existing) */\n\tpermissions?: string[]\n\t/** Whether to auto-assign to new org members */\n\tisDefault?: boolean\n\t/** Display order */\n\tsortOrder?: number\n}\n\n// ============================================================================\n// Role CRUD (project-scoped, requires secretKey)\n// ============================================================================\n\n/**\n * List all roles for the current project.\n *\n * Returns both system-defined and custom roles, each with their\n * assigned permission keys. Requires a secret key (server-side only).\n *\n * @example\n * ```typescript\n * const { roles } = await listRoles(config)\n * for (const role of roles) {\n *   console.log(`${role.name}: ${role.permissions.join(', ')}`)\n * }\n * ```\n */\nexport async function listRoles(config: SylphxConfig): Promise<{ roles: Role[] }> {\n\treturn callApi<{ roles: Role[] }>(config, '/roles')\n}\n\n/**\n * Get a single role by key, including its assigned permission keys.\n *\n * Requires a secret key (server-side only).\n *\n * @example\n * ```typescript\n * const { role } = await getRole(config, 'hr_manager')\n * console.log(role.permissions)\n * // ['org:members:read', 'payroll:view', 'payroll:approve']\n * ```\n */\nexport async function getRole(config: SylphxConfig, roleKey: string): Promise<{ role: Role }> {\n\treturn callApi<{ role: Role }>(config, `/roles/${roleKey}`)\n}\n\n/**\n * Create a custom role with optional permission assignments.\n *\n * Role keys must be lowercase alphanumeric with underscores\n * (e.g. \"hr_manager\", \"payroll_admin\").\n * Requires a secret key (server-side only).\n *\n * @example\n * ```typescript\n * const { role } = await createRole(config, {\n *   key: 'hr_manager',\n *   name: 'HR Manager',\n *   description: 'Can manage employees and approve leave',\n *   permissions: ['org:members:read', 'leave:approve', 'payroll:view'],\n * })\n * ```\n */\nexport async function createRole(\n\tconfig: SylphxConfig,\n\tinput: CreateRoleInput,\n): Promise<{ role: Role }> {\n\t// Map SDK field names to API field names\n\tconst body: Record<string, unknown> = {\n\t\tkey: input.key,\n\t\tname: input.name,\n\t}\n\tif (input.description !== undefined) body.description = input.description\n\tif (input.permissions !== undefined) body.permissionKeys = input.permissions\n\tif (input.isDefault !== undefined) body.isDefault = input.isDefault\n\tif (input.sortOrder !== undefined) body.sortOrder = input.sortOrder\n\n\treturn callApi<{ role: Role }>(config, '/roles', {\n\t\tmethod: 'POST',\n\t\tbody,\n\t})\n}\n\n/**\n * Update a role's metadata and/or permission assignments.\n *\n * System role metadata (name, description) is immutable, but their\n * permissions can be changed. Passing `permissions` replaces the\n * entire permission set for the role.\n * Requires a secret key (server-side only).\n *\n * @example\n * ```typescript\n * const { role } = await updateRole(config, 'hr_manager', {\n *   permissions: ['org:members:read', 'org:members:manage', 'leave:approve'],\n * })\n * ```\n */\nexport async function updateRole(\n\tconfig: SylphxConfig,\n\troleKey: string,\n\tinput: UpdateRoleInput,\n): Promise<{ role: Role }> {\n\t// Map SDK field names to API field names\n\tconst body: Record<string, unknown> = {}\n\tif (input.name !== undefined) body.name = input.name\n\tif (input.description !== undefined) body.description = input.description\n\tif (input.permissions !== undefined) body.permissionKeys = input.permissions\n\tif (input.isDefault !== undefined) body.isDefault = input.isDefault\n\tif (input.sortOrder !== undefined) body.sortOrder = input.sortOrder\n\n\treturn callApi<{ role: Role }>(config, `/roles/${roleKey}`, {\n\t\tmethod: 'PUT',\n\t\tbody,\n\t})\n}\n\n/**\n * Delete a custom role by key.\n *\n * System roles cannot be deleted. Roles with active member assignments\n * cannot be deleted — reassign members first.\n * Requires a secret key (server-side only).\n *\n * @example\n * ```typescript\n * const { success } = await deleteRole(config, 'hr_manager')\n * ```\n */\nexport async function deleteRole(\n\tconfig: SylphxConfig,\n\troleKey: string,\n): Promise<{ success: boolean }> {\n\treturn callApi<{ success: boolean }>(config, `/roles/${roleKey}`, {\n\t\tmethod: 'DELETE',\n\t})\n}\n\n// ============================================================================\n// Member Role Assignment (org-scoped, requires accessToken)\n// ============================================================================\n\n/**\n * Assign an RBAC role to an organization member.\n *\n * Replaces any existing role assignment (single-role mode).\n * Requires admin access to the organization.\n *\n * @example\n * ```typescript\n * const { success } = await assignMemberRole(config, 'my-org', 'usr_abc123', 'hr_manager')\n * ```\n */\nexport async function assignMemberRole(\n\tconfig: SylphxConfig,\n\torgIdOrSlug: string,\n\tmemberId: string,\n\troleKey: string,\n): Promise<{ success: boolean }> {\n\treturn callApi<{ success: boolean }>(\n\t\tconfig,\n\t\t`/orgs/${orgIdOrSlug}/members/${memberId}/assign-role`,\n\t\t{\n\t\t\tmethod: 'PUT',\n\t\t\tbody: { roleKey },\n\t\t},\n\t)\n}\n","/**\n * Storage hooks — ADR-100.\n *\n * Surface (3 hooks, no legacy):\n *\n * - `useStorage()` — `{ upload, files, isUploading, isLoadingFiles, error, refetch }`\n * - `useFile(fileId)` — `{ file, isLoading, error }`\n * - `useFileList(options?)` — `{ files, nextCursor, isLoading, loadMore }`\n *\n * Built on TanStack Query (peer dep). The pure functional surface comes\n * from `@sylphx/sdk` → `storage.uploads.*` / `storage.files.*`.\n */\n\n'use client'\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useCallback, useContext, useMemo, useState } from 'react'\nimport { createConfig, type SylphxConfig, withToken } from '../config'\nimport {\n\ttype FileId,\n\ttype ListFilesOptions,\n\ttype File as StorageFile,\n\tstorage,\n\ttype UploadCreateOptions,\n} from '../storage'\nimport { AuthContext } from './context'\nimport { PlatformContext } from './platform-context'\n\nexport type { StorageFile, FileId, ListFilesOptions, UploadCreateOptions }\n\n// ============================================================================\n// Internal: build SylphxConfig from PlatformContext + AuthContext\n// ============================================================================\n\nfunction useSdkConfig(): SylphxConfig | null {\n\tconst platform = useContext(PlatformContext)\n\tconst auth = useContext(AuthContext)\n\n\treturn useMemo(() => {\n\t\tif (!platform?.slug) return null\n\t\tlet cfg = createConfig({\n\t\t\tsecretKey: platform.appId,\n\t\t\tslug: platform.slug,\n\t\t})\n\t\tif (auth?.accessToken) cfg = withToken(cfg, auth.accessToken)\n\t\treturn cfg\n\t}, [platform?.slug, platform?.appId, auth?.accessToken])\n}\n\n// ============================================================================\n// Query keys\n// ============================================================================\n\nconst storageKeys = {\n\tall: ['storage'] as const,\n\tlists: () => [...storageKeys.all, 'list'] as const,\n\tlist: (opts: ListFilesOptions) => [...storageKeys.lists(), opts] as const,\n\tfiles: () => [...storageKeys.all, 'file'] as const,\n\tfile: (id: string) => [...storageKeys.files(), id] as const,\n}\n\n// ============================================================================\n// useStorage — composite (upload mutation + list query)\n// ============================================================================\n\nexport interface UseStorageReturn {\n\tupload(file: Blob | File, options?: UploadCreateOptions): Promise<StorageFile>\n\tuploadAvatar(file: Blob | File, options?: UploadCreateOptions): Promise<StorageFile>\n\tfiles: StorageFile[] | undefined\n\tisUploading: boolean\n\tisLoadingFiles: boolean\n\tprogress: number\n\terror: Error | null\n\tuploadError: Error | null\n\trefetch(): Promise<void>\n}\n\n/**\n * Composite storage hook — exposes a one-shot `upload` mutation plus a\n * cached file list. For finer-grained control reach for `useFileList`\n * (paginated) or `useFile` (single resource).\n *\n * @example\n * ```tsx\n * const { upload, files, isUploading } = useStorage()\n * await upload(blob, { folder: 'docs' })\n * ```\n */\nexport function useStorage(): UseStorageReturn {\n\tconst config = useSdkConfig()\n\tconst queryClient = useQueryClient()\n\tconst [progress, setProgress] = useState(0)\n\n\tconst listQuery = useQuery({\n\t\tqueryKey: storageKeys.list({}),\n\t\tqueryFn: async () => {\n\t\t\tif (!config) throw new Error('SDK not configured — wrap your app in SylphxProvider')\n\t\t\treturn storage.files.list(config).fetchPage()\n\t\t},\n\t\tenabled: Boolean(config),\n\t\tstaleTime: 60_000,\n\t})\n\n\tconst uploadMutation = useMutation({\n\t\tmutationFn: async (input: { blob: Blob | File; options?: UploadCreateOptions }) => {\n\t\t\tif (!config) throw new Error('SDK not configured — wrap your app in SylphxProvider')\n\t\t\tsetProgress(0)\n\t\t\treturn storage.uploads.create(config, input.blob, {\n\t\t\t\t...(input.options ?? {}),\n\t\t\t\tonProgress: (event) => {\n\t\t\t\t\tconst nextProgress =\n\t\t\t\t\t\tevent.total > 0 ? Math.min(100, Math.round((event.loaded / event.total) * 100)) : 0\n\t\t\t\t\tsetProgress(nextProgress)\n\t\t\t\t\tinput.options?.onProgress?.(event)\n\t\t\t\t},\n\t\t\t})\n\t\t},\n\t\tonSuccess: () => {\n\t\t\tsetProgress(100)\n\t\t\tvoid queryClient.invalidateQueries({ queryKey: storageKeys.lists() })\n\t\t},\n\t\tonError: () => {\n\t\t\tsetProgress(0)\n\t\t},\n\t})\n\n\tconst upload = useCallback(\n\t\t(blob: Blob | File, options?: UploadCreateOptions) =>\n\t\t\tuploadMutation.mutateAsync({ blob, options }),\n\t\t[uploadMutation],\n\t)\n\n\tconst uploadAvatar = useCallback(\n\t\t(blob: Blob | File, options?: UploadCreateOptions) =>\n\t\t\tupload(blob, { visibility: 'public', folder: 'avatars', ...options }),\n\t\t[upload],\n\t)\n\n\tconst refetch = useCallback(async () => {\n\t\tawait listQuery.refetch()\n\t}, [listQuery])\n\n\tconst error = (uploadMutation.error as Error | null) ?? (listQuery.error as Error | null)\n\tconst uploadError = uploadMutation.error as Error | null\n\n\treturn {\n\t\tupload,\n\t\tuploadAvatar,\n\t\tfiles: listQuery.data?.files,\n\t\tisUploading: uploadMutation.isPending,\n\t\tisLoadingFiles: listQuery.isLoading,\n\t\tprogress,\n\t\terror,\n\t\tuploadError,\n\t\trefetch,\n\t}\n}\n\n// ============================================================================\n// useFile — single resource\n// ============================================================================\n\nexport interface UseFileReturn {\n\tfile: StorageFile | undefined\n\tisLoading: boolean\n\terror: Error | null\n}\n\n/**\n * Fetch a single file by id (cached).\n */\nexport function useFile(fileId: FileId | string): UseFileReturn {\n\tconst config = useSdkConfig()\n\n\tconst query = useQuery({\n\t\tqueryKey: storageKeys.file(String(fileId)),\n\t\tqueryFn: async () => {\n\t\t\tif (!config) throw new Error('SDK not configured — wrap your app in SylphxProvider')\n\t\t\treturn storage.files.get(config, fileId as FileId)\n\t\t},\n\t\tenabled: Boolean(config && fileId),\n\t\tstaleTime: 60_000,\n\t})\n\n\treturn {\n\t\tfile: query.data,\n\t\tisLoading: query.isLoading,\n\t\terror: query.error as Error | null,\n\t}\n}\n\n// ============================================================================\n// useFileList — paginated (cursor-based)\n// ============================================================================\n\nexport interface UseFileListReturn {\n\tfiles: StorageFile[]\n\tnextCursor: string | null\n\tisLoading: boolean\n\tloadMore(): Promise<void>\n}\n\n/**\n * Paginated, cursor-based file listing. Call `loadMore()` to append the\n * next page; `nextCursor` is `null` when exhausted.\n */\nexport function useFileList(options: ListFilesOptions = {}): UseFileListReturn {\n\tconst config = useSdkConfig()\n\tconst [pages, setPages] = useState<{ files: StorageFile[]; nextCursor: string | null } | null>(\n\t\tnull,\n\t)\n\n\tconst query = useQuery({\n\t\tqueryKey: storageKeys.list(options),\n\t\tqueryFn: async () => {\n\t\t\tif (!config) throw new Error('SDK not configured — wrap your app in SylphxProvider')\n\t\t\tconst page = await storage.files.list(config, options).fetchPage(options.cursor)\n\t\t\tsetPages({ files: [...page.files], nextCursor: page.nextCursor })\n\t\t\treturn page\n\t\t},\n\t\tenabled: Boolean(config),\n\t\tstaleTime: 60_000,\n\t})\n\n\tconst loadMore = useCallback(async () => {\n\t\tif (!config) return\n\t\tconst cursor = pages?.nextCursor\n\t\tif (!cursor) return\n\t\tconst page = await storage.files.list(config, options).fetchPage(cursor)\n\t\tsetPages((prev) => ({\n\t\t\tfiles: [...(prev?.files ?? []), ...page.files],\n\t\t\tnextCursor: page.nextCursor,\n\t\t}))\n\t}, [config, options, pages?.nextCursor])\n\n\treturn {\n\t\tfiles: pages?.files ?? query.data?.files ?? [],\n\t\tnextCursor: pages?.nextCursor ?? query.data?.nextCursor ?? null,\n\t\tisLoading: query.isLoading,\n\t\tloadMore,\n\t}\n}\n","/**\n * Storage SDK — pure functional, namespaced. Per ADR-100.\n *\n * Wire is the contract in `@sylphx/contract` (`schemas/storage.ts` +\n * `endpoints/storage.ts`). This module is the only public surface for\n * uploads / files; consumers import the `storage` namespace.\n *\n * Features (built-in defaults, ADR-100 §2.8):\n * - Idempotency-Key auto-generated (UUIDv7) on every POST\n * - Single-part PUT or multipart, picked server-side from `size`\n * - Streaming SHA-256 via the Web Crypto API\n * - Resumable: persists `(uploadId, completedParts[])` to localStorage when available\n * - AbortSignal cancellation; auto-DELETE upload session on abort\n * - Exponential backoff with full jitter (5 retries, 1s base, 30s cap)\n * - Progress: byte-accurate via XHR (browser) or stream sampling (node)\n *\n * No vendor SDKs. Pure `fetch` + `XMLHttpRequest`.\n */\n\nimport type {\n\tFile as ContractFile,\n\tCopyFileRequest,\n\tFileId,\n\tFileVersion,\n\tFileVersionId,\n\tListFilesQuery,\n\tSignedUrlRequest,\n\tTakedownFileRequest,\n\tTakedownFileResult,\n\tUploadCompleteResult,\n\tUploadCreateRequest,\n\tUploadCreateResult,\n\tUploadId,\n} from '@sylphx/contract'\nimport { storageEndpoints } from '@sylphx/contract'\nimport { callApi, type SylphxConfig } from './config'\nimport { interpolatePath } from './contract-http'\nimport { SylphxError } from './errors'\nimport {\n\tcalculateBackoffDelay,\n\tisAbortError,\n\tisRetryableError,\n\tsleep,\n\ttoAbortError,\n\tuuidv7,\n\twithRetry,\n} from './lib/retry'\n\n// ============================================================================\n// Public types — sourced from contract (ADR-084 / ADR-100)\n// ============================================================================\n\nexport type {\n\tCopyFileRequest,\n\tFile,\n\tFileId,\n\tFileVersion,\n\tFileVersionId,\n\tFileVisibility,\n\tListFilesQuery,\n\tSignedUrlDisposition,\n\tSignedUrlRequest,\n\tSignedUrlResult,\n\tStorageTakedownReason,\n\tTakedownFileRequest,\n\tTakedownFileResult,\n\tUploadId,\n} from '@sylphx/contract'\n\n// SDK-local helper types (input shapes — not on the wire)\n\nexport interface UploadProgressEvent {\n\tloaded: number\n\ttotal: number\n\tpartsCompleted: number\n\tpartsTotal: number\n}\n\nexport interface UploadCreateOptions {\n\t/** Logical name; preserved as metadata. Defaults to `blob.name` if `File`. */\n\tfilename?: string\n\t/** MIME type override; defaults to `blob.type` or `application/octet-stream`. */\n\tcontentType?: string\n\t/** Logical folder path within the project namespace. */\n\tfolder?: string\n\t/** Defaults to `'private'`. */\n\tvisibility?: 'public' | 'private'\n\t/** Arbitrary user-attached metadata. */\n\tmetadata?: Record<string, unknown>\n\t/** Pre-computed SHA-256 (hex). If absent, the SDK computes it. */\n\tchecksumSha256?: string\n\t/** Fail when a file already exists at `(folder, filename)`. */\n\tifNoneMatch?: '*'\n\t/** Cancellation. Aborts in-flight PUTs and triggers `DELETE /uploads/{id}`. */\n\tsignal?: AbortSignal\n\t/** Override the auto-generated UUIDv7 idempotency key. */\n\tidempotencyKey?: string\n\t/** Progress callback. */\n\tonProgress?: (event: UploadProgressEvent) => void\n}\n\nexport interface ListFilesOptions {\n\tfolder?: string\n\tcursor?: string\n\tlimit?: number\n\tincludeDeleted?: boolean\n}\n\nexport interface SignedUrlOptions {\n\texpiresIn?: number\n\tdisposition?: 'attachment' | 'inline'\n\tuserId?: string\n}\n\nexport interface CopyFileOptions {\n\tfolder?: string\n\tfilename?: string\n\tvisibility?: 'public' | 'private'\n\tmetadata?: Record<string, unknown>\n}\n\nexport type TakedownFileOptions = TakedownFileRequest\n\n// ============================================================================\n// Endpoints (path builders)\n// ============================================================================\n\nconst PATHS = {\n\tuploads: storageEndpoints.createUpload.path,\n\tupload: (id: UploadId | string) =>\n\t\tinterpolatePath(storageEndpoints.abortUpload.path, { uploadId: String(id) }),\n\tuploadComplete: (id: UploadId | string) =>\n\t\tinterpolatePath(storageEndpoints.completeUpload.path, { uploadId: String(id) }),\n\tuploadPart: (id: UploadId | string, n: number) =>\n\t\tinterpolatePath(storageEndpoints.presignUploadPart.path, {\n\t\t\tuploadId: String(id),\n\t\t\tpartNumber: String(n),\n\t\t}),\n\tfiles: storageEndpoints.listFiles.path,\n\tfile: (id: FileId | string) =>\n\t\tinterpolatePath(storageEndpoints.getFile.path, { fileId: String(id) }),\n\tfileTakedown: (id: FileId | string) =>\n\t\tinterpolatePath(storageEndpoints.takedownFile.path, { fileId: String(id) }),\n\tfileRestore: (id: FileId | string) =>\n\t\tinterpolatePath(storageEndpoints.restoreFile.path, { fileId: String(id) }),\n\tfileSignedUrl: (id: FileId | string) =>\n\t\tinterpolatePath(storageEndpoints.signFileUrl.path, { fileId: String(id) }),\n\tfileCopy: (id: FileId | string) =>\n\t\tinterpolatePath(storageEndpoints.copyFile.path, { fileId: String(id) }),\n\tversions: (id: FileId | string) =>\n\t\tinterpolatePath(storageEndpoints.listFileVersions.path, { fileId: String(id) }),\n\tversionRestore: (id: FileId | string, vid: FileVersionId | string) =>\n\t\tinterpolatePath(storageEndpoints.restoreFileVersion.path, {\n\t\t\tfileId: String(id),\n\t\t\tversionId: String(vid),\n\t\t}),\n} as const\n\n// ============================================================================\n// Runtime feature detection\n// ============================================================================\n\nconst hasXhr = (): boolean =>\n\ttypeof (globalThis as { XMLHttpRequest?: unknown }).XMLHttpRequest !== 'undefined'\n\nconst hasLocalStorage = (): boolean => {\n\ttry {\n\t\tconst ls = (globalThis as { localStorage?: Storage }).localStorage\n\t\treturn Boolean(ls && typeof ls.getItem === 'function')\n\t} catch {\n\t\treturn false\n\t}\n}\n\n// ============================================================================\n// SHA-256 (streaming)\n// ============================================================================\n\nasync function computeSha256Hex(blob: Blob): Promise<string> {\n\tconst subtle = (globalThis as { crypto?: { subtle?: { digest?: SubtleCrypto['digest'] } } })\n\t\t.crypto?.subtle\n\tif (!subtle?.digest) {\n\t\tthrow new SylphxError('Web Crypto SHA-256 support is required for storage uploads', {\n\t\t\tcode: 'NOT_IMPLEMENTED',\n\t\t})\n\t}\n\n\tconst buf = await blob.arrayBuffer()\n\tconst digest = await subtle.digest('SHA-256', buf)\n\treturn bytesToHex(new Uint8Array(digest))\n}\n\nfunction bytesToHex(b: Uint8Array): string {\n\tlet s = ''\n\tfor (let i = 0; i < b.length; i++) s += b[i].toString(16).padStart(2, '0')\n\treturn s\n}\n\n// ============================================================================\n// Resume persistence\n// ============================================================================\n\ninterface ResumeRecord {\n\tuploadId: string\n\tcompletedParts: Array<{ partNumber: number; etag: string }>\n\tupdatedAt: number\n}\n\nconst RESUME_KEY_PREFIX = 'sylphx_upload_'\n\nfunction resumeKey(uploadId: string): string {\n\treturn `${RESUME_KEY_PREFIX}${uploadId}`\n}\n\nfunction persistResume(rec: ResumeRecord): void {\n\tif (hasLocalStorage()) {\n\t\ttry {\n\t\t\tlocalStorage.setItem(resumeKey(rec.uploadId), JSON.stringify(rec))\n\t\t} catch {\n\t\t\t/* quota or sandbox; ignore */\n\t\t}\n\t}\n}\n\nfunction clearResume(uploadId: string): void {\n\tif (hasLocalStorage()) {\n\t\ttry {\n\t\t\tlocalStorage.removeItem(resumeKey(uploadId))\n\t\t} catch {\n\t\t\t/* ignore */\n\t\t}\n\t}\n}\n\n// ============================================================================\n// Low-level HTTP helpers (PUT to presigned URLs)\n// ============================================================================\n\ninterface PutResult {\n\tetag: string\n\tstatus: number\n}\n\n/**\n * PUT a blob (or slice) to a presigned URL. Captures `ETag` from the\n * response. Uses XHR when available (browser progress) and falls back\n * to `fetch` (node).\n */\nfunction putBlob(\n\turl: string,\n\tbody: Blob,\n\theaders: Record<string, string>,\n\tsignal: AbortSignal | undefined,\n\tonProgress: ((bytes: number) => void) | undefined,\n): Promise<PutResult> {\n\tif (hasXhr()) return putBlobXhr(url, body, headers, signal, onProgress)\n\treturn putBlobFetch(url, body, headers, signal, onProgress)\n}\n\nfunction putBlobXhr(\n\turl: string,\n\tbody: Blob,\n\theaders: Record<string, string>,\n\tsignal: AbortSignal | undefined,\n\tonProgress: ((bytes: number) => void) | undefined,\n): Promise<PutResult> {\n\treturn new Promise<PutResult>((resolve, reject) => {\n\t\tconst xhr = new XMLHttpRequest()\n\n\t\tconst handleAbort = () => {\n\t\t\ttry {\n\t\t\t\txhr.abort()\n\t\t\t} catch {\n\t\t\t\t/* ignore */\n\t\t\t}\n\t\t\treject(toAbortError('Upload aborted'))\n\t\t}\n\n\t\tif (signal?.aborted) {\n\t\t\treject(toAbortError('Upload aborted'))\n\t\t\treturn\n\t\t}\n\t\tsignal?.addEventListener('abort', handleAbort, { once: true })\n\n\t\tif (onProgress) {\n\t\t\txhr.upload.addEventListener('progress', (e) => {\n\t\t\t\tif (e.lengthComputable) onProgress(e.loaded)\n\t\t\t})\n\t\t}\n\n\t\txhr.addEventListener('load', () => {\n\t\t\tsignal?.removeEventListener('abort', handleAbort)\n\t\t\tif (xhr.status >= 200 && xhr.status < 300) {\n\t\t\t\tconst etag = resolveXhrEtag(xhr)\n\t\t\t\tresolve({ etag: stripQuotes(etag), status: xhr.status })\n\t\t\t} else {\n\t\t\t\tconst err = new Error(`PUT failed with status ${xhr.status}`) as Error & {\n\t\t\t\t\tstatus: number\n\t\t\t\t}\n\t\t\t\terr.status = xhr.status\n\t\t\t\treject(err)\n\t\t\t}\n\t\t})\n\t\txhr.addEventListener('error', () => {\n\t\t\tsignal?.removeEventListener('abort', handleAbort)\n\t\t\treject(new TypeError('Network error during upload'))\n\t\t})\n\t\txhr.addEventListener('abort', () => {\n\t\t\tsignal?.removeEventListener('abort', handleAbort)\n\t\t\treject(toAbortError('Upload aborted'))\n\t\t})\n\n\t\txhr.open('PUT', url)\n\t\tfor (const [k, v] of Object.entries(headers)) {\n\t\t\ttry {\n\t\t\t\txhr.setRequestHeader(k, v)\n\t\t\t} catch {\n\t\t\t\t/* unsafe header — ignore */\n\t\t\t}\n\t\t}\n\t\txhr.send(body)\n\t})\n}\n\nfunction resolveXhrEtag(xhr: XMLHttpRequest): string {\n\tconst canonical = xhr.getResponseHeader('ETag')\n\tif (canonical !== null) return canonical\n\treturn xhr.getResponseHeader('etag') ?? ''\n}\n\nasync function putBlobFetch(\n\turl: string,\n\tbody: Blob,\n\theaders: Record<string, string>,\n\tsignal: AbortSignal | undefined,\n\tonProgress: ((bytes: number) => void) | undefined,\n): Promise<PutResult> {\n\t// Sample progress via TransformStream byte counter where available.\n\tlet stream: BodyInit = body\n\tif (onProgress && typeof TransformStream !== 'undefined' && typeof body.stream === 'function') {\n\t\tlet loaded = 0\n\t\tconst counter = new TransformStream<Uint8Array, Uint8Array>({\n\t\t\ttransform(chunk, controller) {\n\t\t\t\tloaded += chunk.byteLength\n\t\t\t\tonProgress(loaded)\n\t\t\t\tcontroller.enqueue(chunk)\n\t\t\t},\n\t\t})\n\t\tstream = body.stream().pipeThrough(counter) as unknown as BodyInit\n\t}\n\n\tconst res = await fetch(url, {\n\t\tmethod: 'PUT',\n\t\tbody: stream,\n\t\theaders,\n\t\tsignal,\n\t\t// Required when streaming a request body in Chromium / undici.\n\t\t// Cast: TS lib lacks `duplex`.\n\t\t...({ duplex: 'half' } as Record<string, unknown>),\n\t})\n\tif (!res.ok) {\n\t\tconst err = new Error(`PUT failed with status ${res.status}`) as Error & { status: number }\n\t\terr.status = res.status\n\t\tthrow err\n\t}\n\tconst etag = resolveFetchEtag(res.headers)\n\tif (onProgress) onProgress(body.size)\n\treturn { etag: stripQuotes(etag), status: res.status }\n}\n\nfunction resolveFetchEtag(headers: Headers): string {\n\tconst lowerCase = headers.get('etag')\n\tif (lowerCase !== null) return lowerCase\n\treturn headers.get('ETag') ?? ''\n}\n\nfunction stripQuotes(s: string): string {\n\tif (s.length >= 2 && s.startsWith('\"') && s.endsWith('\"')) return s.slice(1, -1)\n\treturn s\n}\n\n// ============================================================================\n// Upload retry wrapper around PUT\n// ============================================================================\n\nasync function putWithRetry(\n\turl: string,\n\tbody: Blob,\n\theaders: Record<string, string>,\n\tsignal: AbortSignal | undefined,\n\tonProgress: ((bytes: number) => void) | undefined,\n): Promise<PutResult> {\n\tlet lastErr: unknown\n\tconst maxRetries = 5\n\tfor (let attempt = 0; attempt <= maxRetries; attempt++) {\n\t\tif (signal?.aborted) throw toAbortError()\n\t\ttry {\n\t\t\treturn await putBlob(url, body, headers, signal, onProgress)\n\t\t} catch (err) {\n\t\t\tif (isAbortError(err)) throw err\n\t\t\tlastErr = err\n\t\t\tif (attempt === maxRetries || !isRetryableError(err)) throw err\n\t\t\tawait sleep(calculateBackoffDelay(attempt), signal)\n\t\t}\n\t}\n\tthrow lastErr\n}\n\n// ============================================================================\n// uploads.create — the main flow\n// ============================================================================\n\n/**\n * Build the File from the upload-complete response + the create options, instead of a\n * separate \\`GET /files/:id\\` (which is serverAuth/sk_ and 403s on the project/pk_ credential the\n * upload uses). The completion already carries id/url/size/etag/checksum; the rest comes from\n * the options; createdAt/updatedAt are the completion moment (the file was just created).\n */\nfunction fileFromCompletion(\n\tcompletion: UploadCompleteResult,\n\toptions: UploadCreateOptions,\n\tblob: Blob | File,\n): ContractFile {\n\tconst now = new Date()\n\treturn {\n\t\tid: completion.fileId,\n\t\tfilename: options.filename ?? (isFile(blob) ? blob.name : undefined) ?? 'upload.bin',\n\t\tcontentType: options.contentType ?? (blob.type || 'application/octet-stream'),\n\t\tsize: completion.size,\n\t\tchecksumSha256: completion.checksumSha256,\n\t\tetag: completion.etag,\n\t\tvisibility: options.visibility ?? 'private',\n\t\tfolder: options.folder ?? null,\n\t\tmetadata: options.metadata ?? {},\n\t\turl: completion.url,\n\t\tisDeleted: false,\n\t\tcreatedAt: now,\n\t\tupdatedAt: now,\n\t}\n}\n\nasync function uploadsCreate(\n\tconfig: SylphxConfig,\n\tblob: Blob | File,\n\toptions: UploadCreateOptions,\n): Promise<ContractFile> {\n\tconst signal = options.signal\n\tif (signal?.aborted) throw toAbortError()\n\n\tconst filename = options.filename ?? (isFile(blob) ? blob.name : undefined) ?? 'upload.bin'\n\tconst contentType =\n\t\toptions.contentType ??\n\t\t(blob.type && blob.type.length > 0 ? blob.type : 'application/octet-stream')\n\tconst size = blob.size\n\n\tconst checksumSha256 = options.checksumSha256 ?? (await computeSha256Hex(blob))\n\n\tconst idempotencyKey = options.idempotencyKey ?? uuidv7()\n\n\tconst createBody: UploadCreateRequest = {\n\t\tfilename,\n\t\tcontentType,\n\t\tsize,\n\t\tfolder: options.folder,\n\t\tvisibility: options.visibility,\n\t\tmetadata: options.metadata as Record<string, unknown> | undefined,\n\t\tchecksumSha256,\n\t\tifNoneMatch: options.ifNoneMatch,\n\t}\n\n\t// 1. Mint upload session.\n\tconst session = await callApi<UploadCreateResult>(config, PATHS.uploads, {\n\t\tmethod: storageEndpoints.createUpload.method,\n\t\tbody: createBody,\n\t\tidempotencyKey,\n\t\tsignal,\n\t})\n\n\tconst uploadId = session.uploadId\n\n\t// Helper: abort the session on cancellation, then propagate.\n\tconst onAborted = async () => {\n\t\ttry {\n\t\t\tawait callApi(config, PATHS.upload(uploadId), { method: storageEndpoints.abortUpload.method })\n\t\t} catch {\n\t\t\t/* best-effort */\n\t\t}\n\t\tclearResume(String(uploadId))\n\t}\n\n\ttry {\n\t\tif (session.method === 'PUT') {\n\t\t\treturn await runSinglePart(config, blob, session, options, idempotencyKey)\n\t\t}\n\t\treturn await runMultipart(config, blob, session, options, idempotencyKey)\n\t} catch (err) {\n\t\tif (isAbortError(err)) {\n\t\t\tawait onAborted()\n\t\t}\n\t\tthrow err\n\t}\n}\n\nfunction isFile(b: Blob | File): b is File {\n\treturn typeof (b as File).name === 'string'\n}\n\nasync function runSinglePart(\n\tconfig: SylphxConfig,\n\tblob: Blob,\n\tsession: Extract<UploadCreateResult, { method: 'PUT' }>,\n\toptions: UploadCreateOptions,\n\tidempotencyKey: string,\n): Promise<ContractFile> {\n\tconst { onProgress, signal } = options\n\tconst total = blob.size\n\n\tconst trackProgress = onProgress\n\t\t? (loaded: number) => {\n\t\t\t\tonProgress({ loaded, total, partsCompleted: 0, partsTotal: 1 })\n\t\t\t}\n\t\t: undefined\n\n\tconst put = await putWithRetry(session.url, blob, session.headers, signal, trackProgress)\n\n\tif (onProgress) onProgress({ loaded: total, total, partsCompleted: 1, partsTotal: 1 })\n\n\tconst completion = await callApi<UploadCompleteResult>(\n\t\tconfig,\n\t\tPATHS.uploadComplete(session.uploadId),\n\t\t{\n\t\t\tmethod: storageEndpoints.completeUpload.method,\n\t\t\tbody: { parts: [{ partNumber: 1, etag: put.etag }] },\n\t\t\tidempotencyKey: `${idempotencyKey}:complete`,\n\t\t\tsignal,\n\t\t},\n\t)\n\n\tclearResume(String(session.uploadId))\n\treturn fileFromCompletion(completion, options, blob)\n}\n\nasync function runMultipart(\n\tconfig: SylphxConfig,\n\tblob: Blob,\n\tsession: Extract<UploadCreateResult, { method: 'MULTIPART' }>,\n\toptions: UploadCreateOptions,\n\tidempotencyKey: string,\n): Promise<ContractFile> {\n\tconst { onProgress, signal } = options\n\tconst partSize = session.partSize\n\tconst total = blob.size\n\tconst partsTotal = session.partCount\n\tconst completedParts: Array<{ partNumber: number; etag: string }> = []\n\tconst partLoaded = new Map<number, number>()\n\n\tconst reportProgress = () => {\n\t\tif (!onProgress) return\n\t\tlet loaded = 0\n\t\tfor (const v of partLoaded.values()) loaded += v\n\t\tonProgress({ loaded, total, partsCompleted: completedParts.length, partsTotal })\n\t}\n\n\tfor (const part of session.parts) {\n\t\tif (signal?.aborted) throw toAbortError()\n\t\tconst offset = (part.partNumber - 1) * partSize\n\t\tconst end = Math.min(offset + partSize, total)\n\t\tconst slice = blob.slice(offset, end)\n\n\t\tconst trackProgress = onProgress\n\t\t\t? (loaded: number) => {\n\t\t\t\t\tpartLoaded.set(part.partNumber, loaded)\n\t\t\t\t\treportProgress()\n\t\t\t\t}\n\t\t\t: undefined\n\n\t\tconst result = await putWithRetry(part.url, slice, {}, signal, trackProgress)\n\t\tcompletedParts.push({ partNumber: part.partNumber, etag: result.etag })\n\t\tpartLoaded.set(part.partNumber, slice.size)\n\t\treportProgress()\n\n\t\t// Persist after each part for resume.\n\t\tpersistResume({\n\t\t\tuploadId: String(session.uploadId),\n\t\t\tcompletedParts: [...completedParts],\n\t\t\tupdatedAt: Date.now(),\n\t\t})\n\t}\n\n\tconst completion = await callApi<UploadCompleteResult>(\n\t\tconfig,\n\t\tPATHS.uploadComplete(session.uploadId),\n\t\t{\n\t\t\tmethod: storageEndpoints.completeUpload.method,\n\t\t\tbody: { parts: completedParts },\n\t\t\tidempotencyKey: `${idempotencyKey}:complete`,\n\t\t\tsignal,\n\t\t},\n\t)\n\n\tclearResume(String(session.uploadId))\n\treturn fileFromCompletion(completion, options, blob)\n}\n\n// ============================================================================\n// uploads.abort\n// ============================================================================\n\nasync function uploadsAbort(config: SylphxConfig, uploadId: UploadId | string): Promise<void> {\n\tawait withRetry(\n\t\t() => callApi(config, PATHS.upload(uploadId), { method: storageEndpoints.abortUpload.method }),\n\t\t{\n\t\t\tmaxRetries: 3,\n\t\t},\n\t)\n\tclearResume(String(uploadId))\n}\n\n// ============================================================================\n// files.* — list / get / delete / restore / signedUrl / copy\n// ============================================================================\n\ninterface ListPage {\n\tfiles: ContractFile[]\n\tnextCursor: string | null\n}\n\nfunction filesListPage(\n\tconfig: SylphxConfig,\n\toptions: ListFilesOptions,\n\tcursor: string | undefined,\n): Promise<ListPage> {\n\tconst query: ListFilesQuery = {\n\t\tfolder: options.folder,\n\t\tcursor: cursor ?? options.cursor,\n\t\tlimit: options.limit,\n\t\tincludeDeleted: options.includeDeleted,\n\t}\n\treturn callApi<ListPage>(config, PATHS.files, {\n\t\tmethod: storageEndpoints.listFiles.method,\n\t\tquery: {\n\t\t\tfolder: query.folder,\n\t\t\tcursor: query.cursor,\n\t\t\tlimit: query.limit,\n\t\t\tincludeDeleted: query.includeDeleted,\n\t\t},\n\t})\n}\n\nfunction filesList(\n\tconfig: SylphxConfig,\n\toptions: ListFilesOptions = {},\n): AsyncIterable<ContractFile> & {\n\tfetchPage: (cursor?: string) => Promise<ListPage>\n} {\n\tconst fetchPage = (cursor?: string) => filesListPage(config, options, cursor)\n\tconst iter: AsyncIterable<ContractFile> = {\n\t\t[Symbol.asyncIterator]: async function* () {\n\t\t\tlet cursor: string | null | undefined = options.cursor\n\t\t\tdo {\n\t\t\t\tconst page = await fetchPage(cursor ?? undefined)\n\t\t\t\tfor (const f of page.files) yield f\n\t\t\t\tcursor = page.nextCursor\n\t\t\t} while (cursor)\n\t\t},\n\t}\n\treturn Object.assign(iter, { fetchPage })\n}\n\nasync function filesGet(config: SylphxConfig, fileId: FileId | string): Promise<ContractFile> {\n\treturn callApi<ContractFile>(config, PATHS.file(fileId), {\n\t\tmethod: storageEndpoints.getFile.method,\n\t})\n}\n\nasync function filesDelete(\n\tconfig: SylphxConfig,\n\tfileId: FileId | string,\n): Promise<{ id: FileId; isDeleted: true }> {\n\treturn callApi(config, PATHS.file(fileId), { method: storageEndpoints.deleteFile.method })\n}\n\nasync function filesTakedown(\n\tconfig: SylphxConfig,\n\tfileId: FileId | string,\n\toptions: TakedownFileOptions,\n): Promise<TakedownFileResult> {\n\treturn callApi<TakedownFileResult>(config, PATHS.fileTakedown(fileId), {\n\t\tmethod: storageEndpoints.takedownFile.method,\n\t\tbody: options,\n\t})\n}\n\nasync function filesRestore(config: SylphxConfig, fileId: FileId | string): Promise<ContractFile> {\n\treturn callApi<ContractFile>(config, PATHS.fileRestore(fileId), {\n\t\tmethod: storageEndpoints.restoreFile.method,\n\t})\n}\n\nasync function filesSignedUrl(\n\tconfig: SylphxConfig,\n\tfileId: FileId | string,\n\toptions: SignedUrlOptions = {},\n): Promise<{ url: string; expiresAt: string; file: ContractFile }> {\n\tconst body: SignedUrlRequest = {\n\t\texpiresIn: options.expiresIn,\n\t\tdisposition: options.disposition,\n\t\tuserId: options.userId,\n\t}\n\treturn callApi(config, PATHS.fileSignedUrl(fileId), {\n\t\tmethod: storageEndpoints.signFileUrl.method,\n\t\tbody,\n\t})\n}\n\nasync function filesCopy(\n\tconfig: SylphxConfig,\n\tfileId: FileId | string,\n\toptions: CopyFileOptions,\n): Promise<ContractFile> {\n\tconst body: CopyFileRequest = {\n\t\tfolder: options.folder,\n\t\tfilename: options.filename,\n\t\tvisibility: options.visibility,\n\t\tmetadata: options.metadata as Record<string, unknown> | undefined,\n\t}\n\treturn callApi<ContractFile>(config, PATHS.fileCopy(fileId), {\n\t\tmethod: storageEndpoints.copyFile.method,\n\t\tbody,\n\t})\n}\n\nasync function filesVersionsList(\n\tconfig: SylphxConfig,\n\tfileId: FileId | string,\n): Promise<FileVersion[]> {\n\tconst data = await callApi<{ versions: FileVersion[] }>(config, PATHS.versions(fileId), {\n\t\tmethod: storageEndpoints.listFileVersions.method,\n\t})\n\treturn data.versions\n}\n\nasync function filesVersionsRestore(\n\tconfig: SylphxConfig,\n\tfileId: FileId | string,\n\tversionId: FileVersionId | string,\n): Promise<{ file: ContractFile; version: FileVersion }> {\n\treturn callApi(config, PATHS.versionRestore(fileId, versionId), {\n\t\tmethod: storageEndpoints.restoreFileVersion.method,\n\t})\n}\n\n// ============================================================================\n// Public namespace\n// ============================================================================\n\n/**\n * `storage` namespace — the only public surface for storage in `@sylphx/sdk`.\n *\n * @example\n * ```ts\n * import { storage } from '@sylphx/sdk'\n *\n * const file = await storage.uploads.create(config, blob, {\n *   filename: 'report.pdf',\n *   folder: 'documents',\n *   onProgress: (e) => console.log(`${e.loaded}/${e.total}`),\n * })\n *\n * for await (const f of storage.files.list(config, { folder: 'documents' })) {\n *   console.log(f.id, f.filename)\n * }\n * ```\n */\nexport const storage = {\n\tuploads: {\n\t\tcreate: uploadsCreate,\n\t\tabort: uploadsAbort,\n\t},\n\tfiles: {\n\t\tlist: filesList,\n\t\tget: filesGet,\n\t\tdelete: filesDelete,\n\t\ttakedown: filesTakedown,\n\t\trestore: filesRestore,\n\t\tsignedUrl: filesSignedUrl,\n\t\tcopy: filesCopy,\n\t\tversions: {\n\t\t\tlist: filesVersionsList,\n\t\t\trestore: filesVersionsRestore,\n\t\t},\n\t},\n} as const\n\n// Re-export `SylphxError` for catch-handlers in user code.\nexport { SylphxError }\n","/**\n * Internal helpers for SDK modules that derive transport paths from\n * `@sylphx/contract` endpoint metadata.\n */\n\nexport function baseUrl(url: string): string {\n\treturn url.replace(/\\/$/, '')\n}\n\nexport function interpolatePath(template: string, params: Record<string, string>): string {\n\tlet path = template\n\tfor (const [key, value] of Object.entries(params)) {\n\t\tpath = path.replace(`:${key}`, encodeURIComponent(value))\n\t}\n\treturn path\n}\n\nexport function buildEndpointUrl(\n\tbase: string,\n\tpath: string,\n\tquery?: Record<string, string | undefined>,\n): string {\n\tconst url = new URL(`${baseUrl(base)}${path}`)\n\tfor (const [key, value] of Object.entries(query ?? {})) {\n\t\tif (value !== undefined) url.searchParams.set(key, value)\n\t}\n\treturn url.toString()\n}\n","/**\n * Retry & idempotency primitives — shared across SDK modules.\n *\n * Per ADR-100 §2.8, every BaaS write is retried with exponential backoff\n * + full jitter (AWS S3 pattern), respects `Retry-After`, and carries an\n * auto-generated UUIDv7 `Idempotency-Key`. Pulled out of `storage.ts`\n * into a shared module so other features can opt in.\n */\n\nimport { BASE_RETRY_DELAY_MS, MAX_RETRY_DELAY_MS } from '../constants'\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\nexport interface RetryConfig {\n\t/** Maximum retry attempts (initial attempt + retries). Default: 5 (AWS S3). */\n\tmaxRetries: number\n\t/** Base delay in milliseconds. Default: `BASE_RETRY_DELAY_MS` (1s). */\n\tbaseDelayMs: number\n\t/** Maximum delay cap in milliseconds. Default: `MAX_RETRY_DELAY_MS` (30s). */\n\tmaxDelayMs: number\n}\n\nexport const DEFAULT_RETRY_CONFIG: RetryConfig = {\n\tmaxRetries: 5,\n\tbaseDelayMs: BASE_RETRY_DELAY_MS,\n\tmaxDelayMs: MAX_RETRY_DELAY_MS,\n}\n\n// ============================================================================\n// Backoff\n// ============================================================================\n\n/**\n * Full-jitter exponential backoff (AWS recommended).\n * Formula: random(0, min(cap, base * 2^attempt))\n */\nexport function calculateBackoffDelay(\n\tattempt: number,\n\tconfig: RetryConfig = DEFAULT_RETRY_CONFIG,\n): number {\n\tconst exp = config.baseDelayMs * 2 ** attempt\n\tconst capped = Math.min(exp, config.maxDelayMs)\n\treturn Math.random() * capped\n}\n\n/** Sleep for `ms`, respecting an optional `AbortSignal`. */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tif (signal?.aborted) {\n\t\t\treject(toAbortError())\n\t\t\treturn\n\t\t}\n\t\tconst timer = setTimeout(resolve, ms)\n\t\tsignal?.addEventListener(\n\t\t\t'abort',\n\t\t\t() => {\n\t\t\t\tclearTimeout(timer)\n\t\t\t\treject(toAbortError())\n\t\t\t},\n\t\t\t{ once: true },\n\t\t)\n\t})\n}\n\n// ============================================================================\n// Retry classification\n// ============================================================================\n\n/** HTTP status codes that should be retried (per ADR-100 §2.8). */\nexport const RETRYABLE_STATUSES: ReadonlySet<number> = new Set([408, 425, 429])\n\n/**\n * Should this error trigger a retry?\n * - `AbortError`: never (user cancelled)\n * - `TypeError` / fetch network error: yes\n * - HTTP status: 408, 425, 429, 500–599\n */\nexport function isRetryableError(error: unknown): boolean {\n\tif (isAbortError(error)) return false\n\tif (error instanceof TypeError) return true\n\tif (error instanceof Error && 'status' in error) {\n\t\tconst status = (error as { status: number }).status\n\t\treturn status >= 500 || RETRYABLE_STATUSES.has(status)\n\t}\n\treturn false\n}\n\n/** True if the error is an `AbortError` (DOMException or named Error). */\nexport function isAbortError(error: unknown): boolean {\n\tif (error instanceof DOMException && error.name === 'AbortError') return true\n\tif (error instanceof Error && error.name === 'AbortError') return true\n\treturn false\n}\n\n/** Build a portable AbortError that works in node and browser. */\nexport function toAbortError(message = 'Aborted'): Error {\n\tif (typeof DOMException !== 'undefined') {\n\t\treturn new DOMException(message, 'AbortError')\n\t}\n\tconst err = new Error(message)\n\terr.name = 'AbortError'\n\treturn err\n}\n\n// ============================================================================\n// Retry wrapper\n// ============================================================================\n\nexport interface RetryOptions extends Partial<RetryConfig> {\n\tsignal?: AbortSignal\n\t/** Hook fired before each retry; receives 0-based attempt count + delay (ms). */\n\tonRetry?: (attempt: number, delayMs: number, error: unknown) => void\n}\n\n/**\n * Run `fn` with full-jitter exponential backoff. Honours `Retry-After`\n * if the thrown error carries it (e.g. `SylphxError`).\n *\n * `fn` should throw on error; the retry loop inspects and re-runs.\n */\nexport async function withRetry<T>(fn: () => Promise<T>, options: RetryOptions = {}): Promise<T> {\n\tconst cfg: RetryConfig = {\n\t\tmaxRetries: options.maxRetries ?? DEFAULT_RETRY_CONFIG.maxRetries,\n\t\tbaseDelayMs: options.baseDelayMs ?? DEFAULT_RETRY_CONFIG.baseDelayMs,\n\t\tmaxDelayMs: options.maxDelayMs ?? DEFAULT_RETRY_CONFIG.maxDelayMs,\n\t}\n\tlet lastError: unknown\n\n\tfor (let attempt = 0; attempt <= cfg.maxRetries; attempt++) {\n\t\tif (options.signal?.aborted) throw toAbortError('Aborted')\n\t\ttry {\n\t\t\treturn await fn()\n\t\t} catch (err) {\n\t\t\tlastError = err\n\t\t\tif (isAbortError(err)) throw err\n\t\t\tif (attempt === cfg.maxRetries) break\n\t\t\tif (!isRetryableError(err)) throw err\n\n\t\t\tconst retryAfter = extractRetryAfter(err)\n\t\t\tconst delay = retryAfter ?? calculateBackoffDelay(attempt, cfg)\n\t\t\toptions.onRetry?.(attempt, delay, err)\n\t\t\tawait sleep(delay, options.signal)\n\t\t}\n\t}\n\tthrow lastError\n}\n\nfunction extractRetryAfter(err: unknown): number | undefined {\n\tif (err && typeof err === 'object' && 'retryAfter' in err) {\n\t\tconst v = (err as { retryAfter?: number }).retryAfter\n\t\tif (typeof v === 'number' && v > 0) return v * 1000\n\t}\n\treturn undefined\n}\n\n// ============================================================================\n// Idempotency keys (UUIDv7)\n// ============================================================================\n\n/**\n * Generate a UUIDv7 — 48-bit Unix-ms timestamp prefix + random tail.\n * Time-sortable, monotonic-ish; matches Stripe/RFC 9562. Falls back to\n * v4 randomness via `crypto.randomUUID` if available; final fallback is\n * a tiny PRNG-based generator for environments without WebCrypto.\n *\n * Spec: https://www.rfc-editor.org/rfc/rfc9562#section-5.7\n */\nexport function uuidv7(): string {\n\tconst ms = BigInt(Date.now())\n\t// 16 random bytes\n\tconst bytes = randomBytes(16)\n\t// Time hi/lo: 48 bits → bytes 0-5\n\tbytes[0] = Number((ms >> 40n) & 0xffn)\n\tbytes[1] = Number((ms >> 32n) & 0xffn)\n\tbytes[2] = Number((ms >> 24n) & 0xffn)\n\tbytes[3] = Number((ms >> 16n) & 0xffn)\n\tbytes[4] = Number((ms >> 8n) & 0xffn)\n\tbytes[5] = Number(ms & 0xffn)\n\t// Version 7 in upper nibble of byte 6\n\tbytes[6] = (bytes[6] & 0x0f) | 0x70\n\t// Variant (RFC 9562) in upper bits of byte 8\n\tbytes[8] = (bytes[8] & 0x3f) | 0x80\n\n\tconst hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('')\n\treturn `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`\n}\n\nfunction randomBytes(n: number): Uint8Array {\n\tconst out = new Uint8Array(n)\n\tconst c = (globalThis as { crypto?: { getRandomValues?: (a: Uint8Array) => Uint8Array } }).crypto\n\tif (c?.getRandomValues) {\n\t\tc.getRandomValues(out)\n\t\treturn out\n\t}\n\tfor (let i = 0; i < n; i++) out[i] = Math.floor(Math.random() * 256)\n\treturn out\n}\n","/**\n * Background Task Hooks\n *\n * React hooks for Sylphx Platform background tasks.\n * Schedule one-time or cron jobs via the platform.\n *\n * Uses proper React Context pattern (no module singletons).\n */\n\n'use client'\n\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { JOB_POLL_INTERVAL_MS } from '../constants'\nimport { type Job, type JobStatus, type JobStatusFilter, useTasksContext } from './services-context'\nimport type {\n\tCreateCronInput,\n\tCreateCronResult,\n\tScheduleJobInput as ScheduleTaskInput,\n\tScheduleJobResult as ScheduleTaskResult,\n} from './types'\n\ntype Task = Job\ntype TaskStatus = JobStatus\ntype TaskStatusFilter = JobStatusFilter\n\n// Re-export types for convenience\nexport type {\n\tTaskStatus,\n\tTaskStatusFilter,\n\tTask,\n\tScheduleTaskInput,\n\tScheduleTaskResult,\n\tCreateCronInput,\n\tCreateCronResult,\n}\n\n// ============================================\n// useTasks\n// ============================================\n\nexport interface UseTasksReturn {\n\t/** Check if background tasks are available */\n\tisAvailable: () => Promise<boolean>\n\t/** Schedule a one-time job */\n\tschedule: (options: ScheduleTaskInput) => Promise<ScheduleTaskResult>\n\t/** Create a recurring cron job */\n\tcreateCron: (options: CreateCronInput) => Promise<CreateCronResult>\n\t/** Pause a cron job */\n\tpauseCron: (scheduleId: string) => Promise<boolean>\n\t/** Resume a paused cron job */\n\tresumeCron: (scheduleId: string) => Promise<boolean>\n\t/** Delete a cron job */\n\tdeleteCron: (scheduleId: string) => Promise<boolean>\n\t/** Get job status */\n\tgetJob: (jobId: string) => Promise<Job>\n\t/** List jobs */\n\tlistJobs: (options?: {\n\t\tstatus?: JobStatusFilter\n\t\ttype?: 'one-time' | 'cron'\n\t\tlimit?: number\n\t\toffset?: number\n\t}) => Promise<Job[]>\n\t/** Cancel a pending, running, waiting, or failed task run */\n\tcancelJob: (jobId: string) => Promise<boolean>\n\t/** Whether a job operation is in progress */\n\tisLoading: boolean\n\t/** Last error */\n\terror: Error | null\n}\n\n/**\n * Hook for background job management\n *\n * @example\n * ```tsx\n * function JobScheduler() {\n *   const { schedule, createCron, isLoading } = useTasks()\n *\n *   const handleSchedule = async () => {\n *     // Schedule a job to run in 1 hour\n *     const result = await schedule({\n *       callbackUrl: 'https://myapp.com/api/process',\n *       payload: { orderId: '123' },\n *       delay: 3600, // 1 hour\n *       name: 'process-order',\n *     })\n *     console.log('Scheduled job:', result.jobId)\n *   }\n *\n *   const handleCron = async () => {\n *     // Create a job that runs every day at 9am\n *     const result = await createCron({\n *       callbackUrl: 'https://myapp.com/api/daily-report',\n *       cron: '0 9 * * *',\n *       name: 'daily-report',\n *     })\n *     console.log('Created cron:', result.scheduleId)\n *   }\n *\n *   return (\n *     <div>\n *       <button onClick={handleSchedule} disabled={isLoading}>\n *         Schedule Job\n *       </button>\n *       <button onClick={handleCron} disabled={isLoading}>\n *         Create Cron\n *       </button>\n *     </div>\n *   )\n * }\n * ```\n */\nexport function useTasks(): UseTasksReturn {\n\tconst ctx = useTasksContext()\n\tconst [isLoading, setIsLoading] = useState(false)\n\tconst [error, setError] = useState<Error | null>(null)\n\n\tconst isAvailable = useCallback(async (): Promise<boolean> => {\n\t\ttry {\n\t\t\tconst status = await ctx.checkStatus()\n\t\t\treturn status.available\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}, [ctx])\n\n\tconst schedule = useCallback(\n\t\tasync (options: ScheduleTaskInput): Promise<ScheduleTaskResult> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\treturn await ctx.schedule(options)\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to schedule job')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst createCron = useCallback(\n\t\tasync (options: CreateCronInput): Promise<CreateCronResult> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\treturn await ctx.createCron(options)\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to create cron job')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst pauseCron = useCallback(\n\t\tasync (scheduleId: string): Promise<boolean> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\treturn await ctx.pauseCron(scheduleId)\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to pause cron')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst resumeCron = useCallback(\n\t\tasync (scheduleId: string): Promise<boolean> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\treturn await ctx.resumeCron(scheduleId)\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to resume cron')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst deleteCron = useCallback(\n\t\tasync (scheduleId: string): Promise<boolean> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\treturn await ctx.deleteCron(scheduleId)\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to delete cron')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst getJob = useCallback(\n\t\tasync (jobId: string): Promise<Job> => {\n\t\t\ttry {\n\t\t\t\treturn await ctx.getJob(jobId)\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to get job')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst listJobs = useCallback(\n\t\tasync (\n\t\t\toptions: {\n\t\t\t\tstatus?: JobStatusFilter\n\t\t\t\ttype?: 'one-time' | 'cron'\n\t\t\t\tlimit?: number\n\t\t\t\toffset?: number\n\t\t\t} = {},\n\t\t): Promise<Job[]> => {\n\t\t\ttry {\n\t\t\t\tconst result = await ctx.listJobs(options)\n\t\t\t\treturn result.tasks\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to list jobs')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst cancelJob = useCallback(\n\t\tasync (jobId: string): Promise<boolean> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\treturn await ctx.cancelJob(jobId)\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to cancel job')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\treturn {\n\t\tisAvailable,\n\t\tschedule,\n\t\tcreateCron,\n\t\tpauseCron,\n\t\tresumeCron,\n\t\tdeleteCron,\n\t\tgetJob,\n\t\tlistJobs,\n\t\tcancelJob,\n\t\tisLoading,\n\t\terror,\n\t}\n}\n\n// ============================================\n// useJobProgress\n// ============================================\n\ntype JobPhase = 'pending' | 'queued' | 'running' | 'completed' | 'failed' | 'cancelled'\n\ninterface JobProgress {\n\t/** Current phase of the job */\n\tphase: JobPhase\n\t/** Progress percentage (0-100), estimated based on phase */\n\tprogress: number\n\t/** Whether the job is still in progress */\n\tisInProgress: boolean\n\t/** Whether the job completed successfully */\n\tisComplete: boolean\n\t/** Whether the job failed */\n\tisFailed: boolean\n\t/** Time elapsed since job was scheduled (ms) */\n\telapsedMs: number\n\t/** Estimated time remaining (ms), null if unknown */\n\testimatedRemainingMs: number | null\n}\n\ninterface UseJobProgressOptions {\n\t/** Polling interval in ms (default: 2000) */\n\tpollInterval?: number\n\t/** Stop polling when job completes (default: true) */\n\tstopOnComplete?: boolean\n\t/** Maximum poll attempts before stopping (default: 100) */\n\tmaxPolls?: number\n\t/** Callback when job completes successfully */\n\tonComplete?: (job: Job) => void\n\t/** Callback when job fails */\n\tonFailed?: (job: Job, error: string | null) => void\n\t/** Callback when job status changes */\n\tonStatusChange?: (job: Job, previousStatus: JobStatus | null) => void\n}\n\ninterface UseJobProgressReturn {\n\t/** Current job data (null until first fetch) */\n\tjob: Job | null\n\t/** Progress information */\n\tprogress: JobProgress\n\t/** Whether currently fetching job status */\n\tisPolling: boolean\n\t/** Last error */\n\terror: Error | null\n\t/** Start polling for job progress */\n\tstart: () => void\n\t/** Stop polling */\n\tstop: () => void\n\t/** Manually refresh job status */\n\trefresh: () => Promise<void>\n}\n\n/**\n * Hook for tracking job progress with polling\n *\n * Uses React Query for automatic polling with configurable interval.\n * Automatically stops polling when job completes, fails, or is cancelled.\n *\n * @example\n * ```tsx\n * function JobTracker({ jobId }: { jobId: string }) {\n *   const { job, progress, isPolling, error } = useJobProgress(jobId, {\n *     pollInterval: 1000,\n *     onComplete: (job) => console.log('Job completed!', job),\n *     onFailed: (job, error) => console.error('Job failed:', error),\n *   })\n *\n *   if (error) return <div>Error: {error.message}</div>\n *   if (!job) return <div>Loading...</div>\n *\n *   return (\n *     <div>\n *       <p>Status: {progress.phase}</p>\n *       <progress value={progress.progress} max={100} />\n *       <p>{progress.progress}% complete</p>\n *       {progress.isInProgress && (\n *         <p>Elapsed: {Math.round(progress.elapsedMs / 1000)}s</p>\n *       )}\n *     </div>\n *   )\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With schedule + tracking\n * function ScheduleAndTrack() {\n *   const { schedule } = useTasks()\n *   const [jobId, setJobId] = useState<string | null>(null)\n *\n *   // Only start tracking when we have a jobId\n *   const { progress, job } = useJobProgress(jobId, {\n *     onComplete: () => toast.success('Job completed!'),\n *   })\n *\n *   const handleSchedule = async () => {\n *     const result = await schedule({\n *       callbackUrl: '/api/process',\n *       payload: { data: 'test' },\n *     })\n *     setJobId(result.jobId)\n *   }\n *\n *   return (\n *     <div>\n *       <button onClick={handleSchedule}>Schedule Job</button>\n *       {jobId && (\n *         <div>\n *           <p>Progress: {progress.progress}%</p>\n *           {progress.isComplete && <p>✓ Done!</p>}\n *         </div>\n *       )}\n *     </div>\n *   )\n * }\n * ```\n */\nfunction useJobProgress(\n\tjobId: string | null | undefined,\n\toptions: UseJobProgressOptions = {},\n): UseJobProgressReturn {\n\tconst {\n\t\tpollInterval = JOB_POLL_INTERVAL_MS,\n\t\tstopOnComplete = true,\n\t\tmaxPolls = 100,\n\t\tonComplete,\n\t\tonFailed,\n\t\tonStatusChange,\n\t} = options\n\n\tconst ctx = useTasksContext()\n\tconst queryClient = useQueryClient()\n\n\t// Track whether we should continue polling\n\tconst [shouldPoll, setShouldPoll] = useState(!!jobId)\n\tconst pollCountRef = useRef(0)\n\tconst previousStatusRef = useRef<JobStatus | null>(null)\n\tconst startTimeRef = useRef<number>(Date.now())\n\tconst callbacksFiredRef = useRef<{ complete: boolean; failed: boolean }>({\n\t\tcomplete: false,\n\t\tfailed: false,\n\t})\n\n\t// Reset state when jobId changes\n\tuseEffect(() => {\n\t\tif (jobId) {\n\t\t\tsetShouldPoll(true)\n\t\t\tpollCountRef.current = 0\n\t\t\tstartTimeRef.current = Date.now()\n\t\t\tpreviousStatusRef.current = null\n\t\t\tcallbacksFiredRef.current = { complete: false, failed: false }\n\t\t} else {\n\t\t\tsetShouldPoll(false)\n\t\t}\n\t}, [jobId])\n\n\t// React Query for job polling\n\tconst jobQuery = useQuery({\n\t\tqueryKey: ['sylphx', 'job', 'progress', jobId],\n\t\tqueryFn: () => ctx.getJob(jobId!),\n\t\tenabled: !!jobId && shouldPoll,\n\t\tstaleTime: 0, // Always refetch for progress tracking\n\t\trefetchInterval: shouldPoll ? pollInterval : false,\n\t})\n\n\tconst job = jobQuery.data ?? null\n\n\t// Handle status changes and callbacks\n\tuseEffect(() => {\n\t\tif (!job) return\n\n\t\tconst currentStatus = job.status as JobStatus\n\t\tpollCountRef.current++\n\n\t\t// Fire status change callback\n\t\tif (previousStatusRef.current !== currentStatus) {\n\t\t\tonStatusChange?.(job, previousStatusRef.current)\n\t\t\tpreviousStatusRef.current = currentStatus\n\t\t}\n\n\t\t// Handle terminal states\n\t\tconst isTerminal = ['completed', 'failed', 'cancelled'].includes(currentStatus)\n\n\t\tif (currentStatus === 'completed' && !callbacksFiredRef.current.complete) {\n\t\t\tcallbacksFiredRef.current.complete = true\n\t\t\tonComplete?.(job)\n\t\t} else if (currentStatus === 'failed' && !callbacksFiredRef.current.failed) {\n\t\t\tcallbacksFiredRef.current.failed = true\n\t\t\tonFailed?.(job, job.lastError ?? null)\n\t\t}\n\n\t\t// Stop polling on terminal state or max polls reached\n\t\tif ((isTerminal && stopOnComplete) || pollCountRef.current >= maxPolls) {\n\t\t\tsetShouldPoll(false)\n\t\t}\n\t}, [job, stopOnComplete, maxPolls, onComplete, onFailed, onStatusChange])\n\n\t// Calculate progress based on job status\n\tconst calculateProgress = useCallback((job: Job | null): JobProgress => {\n\t\tconst now = Date.now()\n\t\tconst startTime = startTimeRef.current\n\n\t\tif (!job) {\n\t\t\treturn {\n\t\t\t\tphase: 'pending',\n\t\t\t\tprogress: 0,\n\t\t\t\tisInProgress: false,\n\t\t\t\tisComplete: false,\n\t\t\t\tisFailed: false,\n\t\t\t\telapsedMs: 0,\n\t\t\t\testimatedRemainingMs: null,\n\t\t\t}\n\t\t}\n\n\t\tconst status = job.status as JobStatus\n\t\tconst elapsedMs = now - startTime\n\n\t\t// Map status to phase and progress\n\t\tlet phase: JobPhase\n\t\tlet progress: number\n\t\tlet isInProgress: boolean\n\t\tlet isComplete: boolean\n\t\tlet isFailed: boolean\n\n\t\tswitch (status) {\n\t\t\tcase 'pending':\n\t\t\t\tphase = 'pending'\n\t\t\t\tprogress = 10\n\t\t\t\tisInProgress = true\n\t\t\t\tisComplete = false\n\t\t\t\tisFailed = false\n\t\t\t\tbreak\n\t\t\tcase 'queued':\n\t\t\t\tphase = 'queued'\n\t\t\t\tprogress = 25\n\t\t\t\tisInProgress = true\n\t\t\t\tisComplete = false\n\t\t\t\tisFailed = false\n\t\t\t\tbreak\n\t\t\tcase 'running':\n\t\t\t\tphase = 'running'\n\t\t\t\tprogress = 50 // Could be enhanced with actual progress from job metadata\n\t\t\t\tisInProgress = true\n\t\t\t\tisComplete = false\n\t\t\t\tisFailed = false\n\t\t\t\tbreak\n\t\t\tcase 'completed':\n\t\t\t\tphase = 'completed'\n\t\t\t\tprogress = 100\n\t\t\t\tisInProgress = false\n\t\t\t\tisComplete = true\n\t\t\t\tisFailed = false\n\t\t\t\tbreak\n\t\t\tcase 'failed':\n\t\t\t\tphase = 'failed'\n\t\t\t\tprogress = 0\n\t\t\t\tisInProgress = false\n\t\t\t\tisComplete = false\n\t\t\t\tisFailed = true\n\t\t\t\tbreak\n\t\t\tcase 'cancelled':\n\t\t\t\tphase = 'cancelled'\n\t\t\t\tprogress = 0\n\t\t\t\tisInProgress = false\n\t\t\t\tisComplete = false\n\t\t\t\tisFailed = false\n\t\t\t\tbreak\n\t\t\tdefault:\n\t\t\t\tphase = 'pending'\n\t\t\t\tprogress = 0\n\t\t\t\tisInProgress = true\n\t\t\t\tisComplete = false\n\t\t\t\tisFailed = false\n\t\t}\n\n\t\t// Estimate remaining time based on average completion time\n\t\tlet estimatedRemainingMs: number | null = null\n\t\tif (isInProgress && elapsedMs > 0 && progress > 0 && progress < 100) {\n\t\t\tconst progressRate = progress / elapsedMs\n\t\t\tconst remainingProgress = 100 - progress\n\t\t\testimatedRemainingMs = Math.round(remainingProgress / progressRate)\n\t\t}\n\n\t\treturn {\n\t\t\tphase,\n\t\t\tprogress,\n\t\t\tisInProgress,\n\t\t\tisComplete,\n\t\t\tisFailed,\n\t\t\telapsedMs,\n\t\t\testimatedRemainingMs,\n\t\t}\n\t}, [])\n\n\t// Start polling\n\tconst start = useCallback(() => {\n\t\tif (!jobId) return\n\t\tpollCountRef.current = 0\n\t\tstartTimeRef.current = Date.now()\n\t\tcallbacksFiredRef.current = { complete: false, failed: false }\n\t\tsetShouldPoll(true)\n\t}, [jobId])\n\n\t// Stop polling\n\tconst stop = useCallback(() => {\n\t\tsetShouldPoll(false)\n\t}, [])\n\n\t// Manual refresh via React Query invalidation\n\tconst refresh = useCallback(async () => {\n\t\tawait queryClient.invalidateQueries({\n\t\t\tqueryKey: ['sylphx', 'job', 'progress', jobId],\n\t\t})\n\t}, [queryClient, jobId])\n\n\tconst progress = calculateProgress(job)\n\n\treturn {\n\t\tjob,\n\t\tprogress,\n\t\tisPolling: shouldPoll && jobQuery.isFetching,\n\t\terror: jobQuery.error as Error | null,\n\t\tstart,\n\t\tstop,\n\t\trefresh,\n\t}\n}\n\n// ============================================\n// useScheduleWithProgress\n// ============================================\n\ninterface UseScheduleWithProgressOptions extends UseJobProgressOptions {\n\t/** Auto-start tracking after scheduling */\n\tautoStart?: boolean\n}\n\ninterface UseScheduleWithProgressReturn {\n\t/** Schedule a job and start tracking */\n\tscheduleAndTrack: (options: ScheduleTaskInput) => Promise<ScheduleTaskResult>\n\t/** Current job being tracked */\n\tjob: Job | null\n\t/** Progress information */\n\tprogress: JobProgress\n\t/** Job ID of the scheduled job */\n\tjobId: string | null\n\t/** Whether scheduling is in progress */\n\tisScheduling: boolean\n\t/** Whether polling job status */\n\tisPolling: boolean\n\t/** Last error */\n\terror: Error | null\n\t/** Reset the tracker to initial state */\n\treset: () => void\n}\n\n/**\n * Convenience hook that combines scheduling and progress tracking\n *\n * @example\n * ```tsx\n * function ProcessOrder({ orderId }: { orderId: string }) {\n *   const {\n *     scheduleAndTrack,\n *     progress,\n *     isScheduling,\n *     isPolling,\n *     reset,\n *   } = useScheduleWithProgress({\n *     onComplete: () => toast.success('Order processed!'),\n *     onFailed: (job, error) => toast.error(`Failed: ${error}`),\n *   })\n *\n *   const handleProcess = async () => {\n *     await scheduleAndTrack({\n *       callbackUrl: '/api/process-order',\n *       payload: { orderId },\n *       name: `process-order-${orderId}`,\n *     })\n *   }\n *\n *   return (\n *     <div>\n *       <button onClick={handleProcess} disabled={isScheduling || isPolling}>\n *         {isScheduling ? 'Scheduling...' : isPolling ? 'Processing...' : 'Process Order'}\n *       </button>\n *\n *       {progress.isInProgress && (\n *         <div>\n *           <progress value={progress.progress} max={100} />\n *           <span>{progress.phase}</span>\n *         </div>\n *       )}\n *\n *       {progress.isComplete && (\n *         <div>\n *           <p>✓ Order processed successfully!</p>\n *           <button onClick={reset}>Process Another</button>\n *         </div>\n *       )}\n *\n *       {progress.isFailed && (\n *         <div>\n *           <p>❌ Processing failed</p>\n *           <button onClick={reset}>Try Again</button>\n *         </div>\n *       )}\n *     </div>\n *   )\n * }\n * ```\n */\nfunction _useScheduleWithProgress(\n\toptions: UseScheduleWithProgressOptions = {},\n): UseScheduleWithProgressReturn {\n\tconst { autoStart = true, ...progressOptions } = options\n\n\tconst { schedule } = useTasks()\n\tconst [jobId, setJobId] = useState<string | null>(null)\n\tconst [isScheduling, setIsScheduling] = useState(false)\n\tconst [scheduleError, setScheduleError] = useState<Error | null>(null)\n\n\tconst {\n\t\tjob,\n\t\tprogress,\n\t\tisPolling,\n\t\terror: progressError,\n\t\tstart,\n\t} = useJobProgress(autoStart ? jobId : null, progressOptions)\n\n\tconst scheduleAndTrack = useCallback(\n\t\tasync (scheduleOptions: ScheduleTaskInput): Promise<ScheduleTaskResult> => {\n\t\t\tsetIsScheduling(true)\n\t\t\tsetScheduleError(null)\n\n\t\t\ttry {\n\t\t\t\tconst result = await schedule(scheduleOptions)\n\t\t\t\tsetJobId(result.jobId)\n\n\t\t\t\t// If autoStart is false, manually start polling\n\t\t\t\tif (!autoStart) {\n\t\t\t\t\tstart()\n\t\t\t\t}\n\n\t\t\t\treturn result\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to schedule job')\n\t\t\t\tsetScheduleError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsScheduling(false)\n\t\t\t}\n\t\t},\n\t\t[schedule, autoStart, start],\n\t)\n\n\tconst reset = useCallback(() => {\n\t\tsetJobId(null)\n\t\tsetIsScheduling(false)\n\t\tsetScheduleError(null)\n\t}, [])\n\n\treturn {\n\t\tscheduleAndTrack,\n\t\tjob,\n\t\tprogress,\n\t\tjobId,\n\t\tisScheduling,\n\t\tisPolling,\n\t\terror: scheduleError ?? progressError,\n\t\treset,\n\t}\n}\n","/**\n * Webhooks Hooks\n *\n * React hooks for Sylphx Platform webhooks service.\n * Configure webhooks, view deliveries, and replay failed attempts.\n *\n * ## React Query Integration\n *\n * All hooks use React Query for:\n * - Automatic caching and deduplication\n * - Stale-while-revalidate updates\n * - Background refetching with refetchInterval\n * - Infinite query for paginated deliveries\n */\n\n'use client'\n\nimport { useInfiniteQuery, useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useCallback } from 'react'\nimport { STALE_TIME_MODERATE_MS, STALE_TIME_STABLE_MS, STALE_TIME_STATS_MS } from '../constants'\nimport type { WebhookDelivery, WebhookEnvironment, WebhookStats } from '../types'\nimport { useWebhooksContext } from './services-context'\nimport type { WebhookDeliveryStatus, WebhookStatsPeriod } from './types'\n\n// ============================================\n// useWebhooks\n// ============================================\n\nexport interface UseWebhooksReturn {\n\t/** Webhook configuration by environment */\n\tenvironments: WebhookEnvironment[]\n\t/** Supported event types */\n\tsupportedEvents: string[]\n\t/** Whether config is loading */\n\tisLoading: boolean\n\t/** Last error */\n\terror: Error | null\n\t/** Update webhook config for an environment */\n\tupdateConfig: (options: {\n\t\tenvironmentId: string\n\t\twebhookUrl: string | null\n\t\tregenerateSecret?: boolean\n\t}) => Promise<{\n\t\tsuccess: boolean\n\t\twebhookUrl: string | null\n\t\tsecretGenerated: boolean\n\t\twebhookSecretPrefix?: string\n\t}>\n\t/** Refresh the configuration */\n\trefresh: () => Promise<void>\n}\n\n/**\n * Hook for managing webhook configuration\n *\n * @example\n * ```tsx\n * function WebhookConfig() {\n *   const {\n *     environments,\n *     supportedEvents,\n *     updateConfig,\n *     isLoading,\n *   } = useWebhooks()\n *\n *   const handleUpdate = async (envId: string, url: string) => {\n *     const result = await updateConfig({\n *       environmentId: envId,\n *       webhookUrl: url,\n *       regenerateSecret: true,\n *     })\n *     if (result.webhookSecretPrefix) {\n *       alert(`New secret prefix: ${result.webhookSecretPrefix}`)\n *     }\n *   }\n *\n *   return (\n *     <div>\n *       {environments.map(env => (\n *         <div key={env.id}>\n *           <h3>{env.name}</h3>\n *           <input\n *             defaultValue={env.webhookUrl ?? ''}\n *             onBlur={(e) => handleUpdate(env.id, e.target.value)}\n *           />\n *         </div>\n *       ))}\n *     </div>\n *   )\n * }\n * ```\n */\nexport function useWebhooks(): UseWebhooksReturn {\n\tconst ctx = useWebhooksContext()\n\tconst queryClient = useQueryClient()\n\n\t// React Query for webhook config\n\tconst configQuery = useQuery({\n\t\tqueryKey: ['sylphx', 'webhooks', 'config'],\n\t\tqueryFn: () => ctx.getConfig(),\n\t\tstaleTime: STALE_TIME_STABLE_MS, // 5 min - config rarely changes\n\t})\n\n\tconst config = configQuery.data\n\n\t// Update config\n\tconst updateConfig = useCallback(\n\t\tasync (options: {\n\t\t\tenvironmentId: string\n\t\t\twebhookUrl: string | null\n\t\t\tregenerateSecret?: boolean\n\t\t}) => {\n\t\t\tconst result = await ctx.updateConfig(options)\n\t\t\t// Invalidate to get updated state\n\t\t\tawait queryClient.invalidateQueries({\n\t\t\t\tqueryKey: ['sylphx', 'webhooks', 'config'],\n\t\t\t})\n\t\t\treturn result\n\t\t},\n\t\t[ctx, queryClient],\n\t)\n\n\t// Refresh via React Query invalidation\n\tconst refresh = useCallback(async () => {\n\t\tawait queryClient.invalidateQueries({\n\t\t\tqueryKey: ['sylphx', 'webhooks', 'config'],\n\t\t})\n\t}, [queryClient])\n\n\treturn {\n\t\tenvironments: config?.environments ?? [],\n\t\tsupportedEvents: config?.supportedEvents ?? [],\n\t\tisLoading: configQuery.isLoading,\n\t\terror: configQuery.error as Error | null,\n\t\tupdateConfig,\n\t\trefresh,\n\t}\n}\n\n// ============================================\n// useWebhookDeliveries\n// ============================================\n\nexport interface UseWebhookDeliveriesOptions {\n\t/** Filter by status */\n\tstatus?: WebhookDeliveryStatus\n\t/** Filter by event type */\n\tevent?: string\n\t/** Number of deliveries to fetch per page */\n\tlimit?: number\n\t/** Whether to skip initial fetch */\n\tskip?: boolean\n\t/** Refetch interval in ms (uses React Query's refetchInterval) */\n\trefetchInterval?: number\n}\n\nexport interface UseWebhookDeliveriesReturn {\n\t/** Webhook deliveries (all loaded pages) */\n\tdeliveries: WebhookDelivery[]\n\t/** Total count of matching deliveries */\n\ttotal: number\n\t/** Whether deliveries are loading */\n\tisLoading: boolean\n\t/** Whether fetching next page */\n\tisFetchingNextPage: boolean\n\t/** Last error */\n\terror: Error | null\n\t/** Replay a delivery */\n\treplay: (deliveryId: string) => Promise<{ success: boolean; newDeliveryId?: string }>\n\t/** Refresh deliveries */\n\trefresh: () => Promise<void>\n\t/** Load more deliveries */\n\tloadMore: () => Promise<void>\n\t/** Whether there are more deliveries to load */\n\thasMore: boolean\n}\n\n/**\n * Hook for viewing webhook delivery history\n *\n * Uses React Query's useInfiniteQuery for efficient pagination.\n *\n * @example\n * ```tsx\n * function WebhookDeliveries() {\n *   const { deliveries, isLoading, replay, refresh, loadMore, hasMore } = useWebhookDeliveries({\n *     status: 'failed',\n *     limit: 50,\n *     refetchInterval: 30000, // Auto-refresh every 30s\n *   })\n *\n *   return (\n *     <div>\n *       <button onClick={refresh}>Refresh</button>\n *       <table>\n *         <thead>\n *           <tr>\n *             <th>Event</th>\n *             <th>Status</th>\n *             <th>Actions</th>\n *           </tr>\n *         </thead>\n *         <tbody>\n *           {deliveries.map(delivery => (\n *             <tr key={delivery.id}>\n *               <td>{delivery.event}</td>\n *               <td>{delivery.status}</td>\n *               <td>\n *                 {delivery.status === 'failed' && (\n *                   <button onClick={() => replay(delivery.id)}>Retry</button>\n *                 )}\n *               </td>\n *             </tr>\n *           ))}\n *         </tbody>\n *       </table>\n *       {hasMore && (\n *         <button onClick={loadMore}>Load More</button>\n *       )}\n *     </div>\n *   )\n * }\n * ```\n */\nexport function useWebhookDeliveries(\n\toptions: UseWebhookDeliveriesOptions = {},\n): UseWebhookDeliveriesReturn {\n\tconst { status, event, limit = 50, skip = false, refetchInterval } = options\n\tconst ctx = useWebhooksContext()\n\tconst queryClient = useQueryClient()\n\n\t// React Query infinite query for paginated deliveries\n\tconst deliveriesQuery = useInfiniteQuery({\n\t\tqueryKey: ['sylphx', 'webhooks', 'deliveries', { status, event, limit }],\n\t\tqueryFn: async ({ pageParam = 0 }) => {\n\t\t\treturn ctx.getDeliveries({ status, event, limit, offset: pageParam })\n\t\t},\n\t\tinitialPageParam: 0,\n\t\tgetNextPageParam: (lastPage, allPages) => {\n\t\t\tconst loadedCount = allPages.reduce((sum, page) => sum + page.deliveries.length, 0)\n\t\t\tif (loadedCount >= lastPage.total) {\n\t\t\t\treturn undefined // No more pages\n\t\t\t}\n\t\t\treturn loadedCount // Next offset\n\t\t},\n\t\tenabled: !skip,\n\t\tstaleTime: STALE_TIME_STATS_MS, // 30 sec - deliveries change moderately\n\t\trefetchInterval: refetchInterval ?? false,\n\t})\n\n\t// Flatten all pages into single deliveries array\n\tconst deliveries = deliveriesQuery.data?.pages.flatMap((page) => page.deliveries) ?? []\n\tconst total = deliveriesQuery.data?.pages[0]?.total ?? 0\n\n\t// Replay delivery\n\tconst replay = useCallback(\n\t\tasync (deliveryId: string): Promise<{ success: boolean; newDeliveryId?: string }> => {\n\t\t\tconst result = await ctx.replayDelivery(deliveryId)\n\t\t\t// Invalidate to get updated status\n\t\t\tawait queryClient.invalidateQueries({\n\t\t\t\tqueryKey: ['sylphx', 'webhooks', 'deliveries'],\n\t\t\t})\n\t\t\treturn result\n\t\t},\n\t\t[ctx, queryClient],\n\t)\n\n\t// Refresh via React Query invalidation\n\tconst refresh = useCallback(async () => {\n\t\tawait queryClient.invalidateQueries({\n\t\t\tqueryKey: ['sylphx', 'webhooks', 'deliveries'],\n\t\t})\n\t}, [queryClient])\n\n\t// Load more via fetchNextPage\n\tconst loadMore = useCallback(async () => {\n\t\tif (deliveriesQuery.hasNextPage && !deliveriesQuery.isFetchingNextPage) {\n\t\t\tawait deliveriesQuery.fetchNextPage()\n\t\t}\n\t}, [deliveriesQuery])\n\n\treturn {\n\t\tdeliveries,\n\t\ttotal,\n\t\tisLoading: deliveriesQuery.isLoading,\n\t\tisFetchingNextPage: deliveriesQuery.isFetchingNextPage,\n\t\terror: deliveriesQuery.error as Error | null,\n\t\treplay,\n\t\trefresh,\n\t\tloadMore,\n\t\thasMore: deliveriesQuery.hasNextPage ?? false,\n\t}\n}\n\n// ============================================\n// useWebhookStats\n// ============================================\n\nexport interface UseWebhookStatsReturn {\n\t/** Webhook statistics */\n\tstats: WebhookStats | null\n\t/** Whether stats are loading */\n\tisLoading: boolean\n\t/** Last error */\n\terror: Error | null\n\t/** Refresh stats */\n\trefresh: () => Promise<void>\n}\n\n/**\n * Hook for webhook delivery statistics\n *\n * @example\n * ```tsx\n * function WebhookDashboard() {\n *   const { stats, isLoading, refresh } = useWebhookStats('week')\n *\n *   if (isLoading) return <Spinner />\n *\n *   return (\n *     <div>\n *       <p>Delivery Rate: {stats?.totals.deliveryRate}</p>\n *       <p>Total: {stats?.totals.total}</p>\n *       <button onClick={refresh}>Refresh</button>\n *     </div>\n *   )\n * }\n * ```\n */\nexport function useWebhookStats(period: WebhookStatsPeriod = 'week'): UseWebhookStatsReturn {\n\tconst ctx = useWebhooksContext()\n\tconst queryClient = useQueryClient()\n\n\t// React Query for webhook stats\n\tconst statsQuery = useQuery({\n\t\tqueryKey: ['sylphx', 'webhooks', 'stats', period],\n\t\tqueryFn: () => ctx.getStats(period),\n\t\tstaleTime: STALE_TIME_MODERATE_MS, // 2 min - stats aggregate data\n\t})\n\n\t// Refresh via React Query invalidation\n\tconst refresh = useCallback(async () => {\n\t\tawait queryClient.invalidateQueries({\n\t\t\tqueryKey: ['sylphx', 'webhooks', 'stats', period],\n\t\t})\n\t}, [queryClient, period])\n\n\treturn {\n\t\tstats: statsQuery.data ?? null,\n\t\tisLoading: statsQuery.isLoading,\n\t\terror: statsQuery.error as Error | null,\n\t\trefresh,\n\t}\n}\n","/**\n * Account Section Component\n *\n * Account management: email change, data export, account deletion.\n * Self-contained with CSS-in-JS styles.\n */\n\n'use client'\n\nimport { useCallback, useEffect, useId, useState } from 'react'\nimport { UI_NOTIFICATION_MS, UI_SUCCESS_REDIRECT_MS } from '../../constants'\nimport { RequireSdk, useAuth, useUser } from '../hooks'\nimport { useSecurityContext, useUserContext } from '../services-context'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\nexport interface AccountSectionProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Called on successful action */\n\tonSuccess?: (message: string) => void\n\t/** Called on error */\n\tonError?: (error: string) => void\n\t/** Custom class name */\n\tclassName?: string\n\t/** Show email change option */\n\tshowEmailChange?: boolean\n\t/** Show data export option */\n\tshowDataExport?: boolean\n\t/** Show account deletion option */\n\tshowDeleteAccount?: boolean\n\t/** URL to redirect after account deletion */\n\tafterDeleteUrl?: string\n}\n\n/**\n * Account management section\n *\n * @example\n * ```tsx\n * <AccountSection\n *   onSuccess={(msg) => toast.success(msg)}\n *   afterDeleteUrl=\"/\"\n * />\n * ```\n */\nexport function AccountSection(props: AccountSectionProps) {\n\treturn (\n\t\t<RequireSdk services={['auth']} componentType=\"account\" theme={props.theme}>\n\t\t\t<AccountSectionInner {...props} />\n\t\t</RequireSdk>\n\t)\n}\n\n/** Inner component that safely uses platform hooks */\nfunction AccountSectionInner({\n\ttheme = defaultTheme,\n\tonSuccess,\n\tonError,\n\tclassName,\n\tshowEmailChange = true,\n\tshowDataExport = true,\n\tshowDeleteAccount = true,\n\tafterDeleteUrl = '/',\n}: AccountSectionProps) {\n\tconst { user } = useUser()\n\tconst { signOut } = useAuth()\n\tconst userContext = useUserContext()\n\tconst securityContext = useSecurityContext()\n\tconst styles = baseStyles(theme)\n\tconst newEmailId = useId()\n\tconst emailPasswordId = useId()\n\n\t// State\n\tconst [error, setError] = useState<string | null>(null)\n\tconst [success, setSuccess] = useState<string | null>(null)\n\n\t// Email change state\n\tconst [showEmailChangeForm, setShowEmailChangeForm] = useState(false)\n\tconst [newEmail, setNewEmail] = useState('')\n\tconst [emailPassword, setEmailPassword] = useState('')\n\tconst [isChangingEmail, setIsChangingEmail] = useState(false)\n\n\t// Data export state\n\tconst [isExporting, setIsExporting] = useState(false)\n\tconst [exportUrl, setExportUrl] = useState<string | null>(null)\n\n\t// Delete account state\n\tconst [showDeleteConfirm, setShowDeleteConfirm] = useState(false)\n\tconst [deleteConfirmText, setDeleteConfirmText] = useState('')\n\tconst [deletePassword, setDeletePassword] = useState('')\n\tconst [delete2FACode, setDelete2FACode] = useState('')\n\tconst [isDeleting, setIsDeleting] = useState(false)\n\tconst [deleteStep, setDeleteStep] = useState<'confirm' | 'password' | '2fa'>('confirm')\n\tconst [has2FAEnabled, setHas2FAEnabled] = useState(false)\n\tconst [isChecking2FA, setIsChecking2FA] = useState(false)\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// Clear messages after timeout\n\tuseEffect(() => {\n\t\tif (success || error) {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tsetSuccess(null)\n\t\t\t\tsetError(null)\n\t\t\t}, UI_NOTIFICATION_MS)\n\t\t\treturn () => clearTimeout(timer)\n\t\t}\n\t}, [success, error])\n\n\t// Handle email change request\n\tconst handleEmailChange = async (e: React.FormEvent) => {\n\t\te.preventDefault()\n\n\t\tif (!newEmail || !newEmail.includes('@')) {\n\t\t\tsetError('Please enter a valid email address')\n\t\t\treturn\n\t\t}\n\n\t\tsetIsChangingEmail(true)\n\t\tsetError(null)\n\n\t\ttry {\n\t\t\tconst result = await securityContext.emailChangeRequest(newEmail)\n\t\t\tsetShowEmailChangeForm(false)\n\t\t\tsetNewEmail('')\n\t\t\tsetEmailPassword('')\n\t\t\tsetSuccess(\n\t\t\t\tresult.message || 'Verification email sent to your new address. Please check your inbox.',\n\t\t\t)\n\t\t\tonSuccess?.('Verification email sent')\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to change email'\n\t\t\tsetError(message)\n\t\t\tonError?.(message)\n\t\t} finally {\n\t\t\tsetIsChangingEmail(false)\n\t\t}\n\t}\n\n\t// Handle data export\n\tconst handleDataExport = async () => {\n\t\tsetIsExporting(true)\n\t\tsetError(null)\n\n\t\ttry {\n\t\t\tconst data = await userContext.exportData()\n\t\t\tsetExportUrl(data.downloadUrl)\n\t\t\tsetSuccess('Your data export is ready for download')\n\t\t\tonSuccess?.('Data export ready')\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to export data'\n\t\t\tsetError(message)\n\t\t\tonError?.(message)\n\t\t} finally {\n\t\t\tsetIsExporting(false)\n\t\t}\n\t}\n\n\t// Check 2FA status when delete confirmation is shown (industry best practice)\n\tconst checkSecurityStatus = useCallback(async () => {\n\t\tsetIsChecking2FA(true)\n\t\ttry {\n\t\t\tconst status = await securityContext.getTwoFactorStatus()\n\t\t\tsetHas2FAEnabled(status.enabled)\n\t\t} catch {\n\t\t\t// If we can't check 2FA, assume it's not enabled\n\t\t\tsetHas2FAEnabled(false)\n\t\t} finally {\n\t\t\tsetIsChecking2FA(false)\n\t\t}\n\t}, [securityContext])\n\n\t// Handle delete confirmation step\n\tconst handleDeleteConfirmStep = async () => {\n\t\tif (deleteConfirmText !== 'DELETE') {\n\t\t\tsetError('Please type DELETE to confirm')\n\t\t\treturn\n\t\t}\n\n\t\t// Check 2FA status before proceeding\n\t\tawait checkSecurityStatus()\n\n\t\t// Move to password step\n\t\tsetDeleteStep('password')\n\t}\n\n\t// Handle password verification step\n\tconst handlePasswordStep = () => {\n\t\tif (!deletePassword) {\n\t\t\tsetError('Please enter your password')\n\t\t\treturn\n\t\t}\n\n\t\tif (has2FAEnabled) {\n\t\t\t// Move to 2FA step\n\t\t\tsetDeleteStep('2fa')\n\t\t} else {\n\t\t\t// No 2FA, proceed with deletion\n\t\t\thandleDeleteAccount()\n\t\t}\n\t}\n\n\t// Handle 2FA verification step (industry standard: verify 2FA before destructive actions)\n\tconst handle2FAStep = () => {\n\t\tif (!delete2FACode || delete2FACode.length !== 6) {\n\t\t\tsetError('Please enter a valid 6-digit code')\n\t\t\treturn\n\t\t}\n\t\thandleDeleteAccount()\n\t}\n\n\t// Handle account deletion with password and optional 2FA\n\tconst handleDeleteAccount = async () => {\n\t\tsetIsDeleting(true)\n\t\tsetError(null)\n\n\t\ttry {\n\t\t\t// If 2FA is enabled, verify the code first\n\t\t\tif (has2FAEnabled && delete2FACode) {\n\t\t\t\tawait securityContext.twoFactorVerify(delete2FACode)\n\t\t\t}\n\n\t\t\t// Proceed with deletion (pass password for re-authentication)\n\t\t\tawait userContext.deleteAccount(deletePassword)\n\t\t\tsetSuccess('Account deleted. Redirecting...')\n\t\t\tonSuccess?.('Account deleted')\n\n\t\t\t// Sign out and redirect\n\t\t\tsetTimeout(async () => {\n\t\t\t\tawait signOut({ redirectUrl: afterDeleteUrl })\n\t\t\t}, UI_SUCCESS_REDIRECT_MS)\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to delete account'\n\t\t\tsetError(message)\n\t\t\tonError?.(message)\n\t\t\tsetIsDeleting(false)\n\t\t}\n\t}\n\n\t// Reset delete state\n\tconst resetDeleteState = () => {\n\t\tsetShowDeleteConfirm(false)\n\t\tsetDeleteConfirmText('')\n\t\tsetDeletePassword('')\n\t\tsetDelete2FACode('')\n\t\tsetDeleteStep('confirm')\n\t\tsetHas2FAEnabled(false)\n\t}\n\n\tconst cardStyles: React.CSSProperties = mergeStyles(styles.card, {\n\t\tpadding: '1rem',\n\t\tmarginBottom: '1rem',\n\t})\n\n\treturn (\n\t\t<div className={className}>\n\t\t\t{/* Alerts */}\n\t\t\t{success && (\n\t\t\t\t<div style={mergeStyles(styles.alert, styles.alertSuccess, styles.mb4)}>{success}</div>\n\t\t\t)}\n\t\t\t{error && <div style={mergeStyles(styles.alert, styles.alertError, styles.mb4)}>{error}</div>}\n\n\t\t\t{/* Email Change */}\n\t\t\t{showEmailChange && (\n\t\t\t\t<div style={cardStyles}>\n\t\t\t\t\t<div style={styles.flexBetween}>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<h4 style={{ margin: 0, fontWeight: 500 }}>Email Address</h4>\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{user?.email}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t{!showEmailChangeForm && (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={() => setShowEmailChangeForm(true)}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tChange\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{showEmailChangeForm && (\n\t\t\t\t\t\t<form\n\t\t\t\t\t\t\tonSubmit={handleEmailChange}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t\t\t\t\tpaddingTop: '1rem',\n\t\t\t\t\t\t\t\tborderTop: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div style={styles.formGroup}>\n\t\t\t\t\t\t\t\t<label htmlFor={newEmailId} style={styles.label}>\n\t\t\t\t\t\t\t\t\tNew Email Address\n\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\tid={newEmailId}\n\t\t\t\t\t\t\t\t\ttype=\"email\"\n\t\t\t\t\t\t\t\t\tvalue={newEmail}\n\t\t\t\t\t\t\t\t\tonChange={(e) => setNewEmail(e.target.value)}\n\t\t\t\t\t\t\t\t\tplaceholder=\"new@example.com\"\n\t\t\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t\t\t\tstyle={styles.input}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div style={styles.formGroup}>\n\t\t\t\t\t\t\t\t<label htmlFor={emailPasswordId} style={styles.label}>\n\t\t\t\t\t\t\t\t\tCurrent Password\n\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\tid={emailPasswordId}\n\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\tvalue={emailPassword}\n\t\t\t\t\t\t\t\t\tonChange={(e) => setEmailPassword(e.target.value)}\n\t\t\t\t\t\t\t\t\tplaceholder=\"Enter your password to confirm\"\n\t\t\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t\t\t\tstyle={styles.input}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div style={mergeStyles(styles.flexRow, { gap: '0.5rem' })}>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\t\tdisabled={isChangingEmail}\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\t\t\t\t\tstyles.buttonPrimary,\n\t\t\t\t\t\t\t\t\t\tisChangingEmail ? styles.buttonDisabled : {},\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{isChangingEmail ? (\n\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t\t\t\t\t\t\tSending...\n\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t'Send Verification'\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\tsetShowEmailChangeForm(false)\n\t\t\t\t\t\t\t\t\t\tsetNewEmail('')\n\t\t\t\t\t\t\t\t\t\tsetEmailPassword('')\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</form>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Data Export */}\n\t\t\t{showDataExport && (\n\t\t\t\t<div style={cardStyles}>\n\t\t\t\t\t<div style={styles.flexBetween}>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<h4 style={{ margin: 0, fontWeight: 500 }}>Export Your Data</h4>\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tDownload a copy of all your data\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t{!exportUrl ? (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={handleDataExport}\n\t\t\t\t\t\t\t\tdisabled={isExporting}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\t\t\t\tstyles.buttonOutline,\n\t\t\t\t\t\t\t\t\tisExporting ? styles.buttonDisabled : {},\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{isExporting ? (\n\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t\t\t\t\t\tPreparing...\n\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t<DownloadIcon size={16} />\n\t\t\t\t\t\t\t\t\t\tExport\n\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<a href={exportUrl} download style={mergeStyles(styles.button, styles.buttonPrimary)}>\n\t\t\t\t\t\t\t\t<DownloadIcon size={16} />\n\t\t\t\t\t\t\t\tDownload\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Delete Account */}\n\t\t\t{showDeleteAccount && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={mergeStyles(cardStyles, {\n\t\t\t\t\t\tborderColor: theme.colorDestructive,\n\t\t\t\t\t\tbackgroundColor: `${theme.colorDestructive}05`,\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\t<div style={styles.flexBetween}>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<h4\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\t\tcolor: theme.colorDestructive,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tDelete Account\n\t\t\t\t\t\t\t</h4>\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tPermanently delete your account and all data\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t{!showDeleteConfirm && (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={() => setShowDeleteConfirm(true)}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonDestructive)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<TrashIcon size={16} />\n\t\t\t\t\t\t\t\tDelete Account\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{showDeleteConfirm && (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t\t\t\t\tpaddingTop: '1rem',\n\t\t\t\t\t\t\t\tborderTop: `1px solid ${theme.colorDestructive}30`,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{/* Step indicator */}\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textXs, styles.textMuted, {\n\t\t\t\t\t\t\t\t\tmarginBottom: '1rem',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tStep {deleteStep === 'confirm' ? '1' : deleteStep === 'password' ? '2' : '3'} of{' '}\n\t\t\t\t\t\t\t\t{has2FAEnabled ? '3' : '2'}\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t{/* Step 1: Confirm with DELETE text */}\n\t\t\t\t\t\t\t{deleteStep === 'confirm' && (\n\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.alert, styles.alertError, {\n\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: `${theme.colorDestructive}10`,\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<strong>Warning:</strong> This action cannot be undone. All your data will be\n\t\t\t\t\t\t\t\t\t\tpermanently deleted.\n\t\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\t\t\t\tmargin: '1rem 0 0.5rem',\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tType <strong>DELETE</strong> to confirm:\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\tvalue={deleteConfirmText}\n\t\t\t\t\t\t\t\t\t\tonChange={(e) => setDeleteConfirmText(e.target.value)}\n\t\t\t\t\t\t\t\t\t\tplaceholder=\"DELETE\"\n\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.input, { marginBottom: '1rem' })}\n\t\t\t\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t\t\t\t<div style={mergeStyles(styles.flexRow, { gap: '0.5rem' })}>\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={handleDeleteConfirmStep}\n\t\t\t\t\t\t\t\t\t\t\tdisabled={isChecking2FA || deleteConfirmText !== 'DELETE'}\n\t\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\t\t\t\t\t\t\tstyles.buttonDestructive,\n\t\t\t\t\t\t\t\t\t\t\t\tisChecking2FA || deleteConfirmText !== 'DELETE'\n\t\t\t\t\t\t\t\t\t\t\t\t\t? styles.buttonDisabled\n\t\t\t\t\t\t\t\t\t\t\t\t\t: {},\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{isChecking2FA ? (\n\t\t\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t\t\t\t\t\t\t\t\tChecking...\n\t\t\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t\t'Continue'\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={resetDeleteState}\n\t\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline)}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{/* Step 2: Password verification */}\n\t\t\t\t\t\t\t{deleteStep === 'password' && (\n\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\t\t\t\tmargin: '0 0 0.5rem',\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tEnter your password to verify your identity:\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\t\tvalue={deletePassword}\n\t\t\t\t\t\t\t\t\t\tonChange={(e) => setDeletePassword(e.target.value)}\n\t\t\t\t\t\t\t\t\t\tplaceholder=\"Enter your password\"\n\t\t\t\t\t\t\t\t\t\tautoComplete=\"current-password\"\n\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.input, { marginBottom: '1rem' })}\n\t\t\t\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t\t\t\t<div style={mergeStyles(styles.flexRow, { gap: '0.5rem' })}>\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={handlePasswordStep}\n\t\t\t\t\t\t\t\t\t\t\tdisabled={!deletePassword}\n\t\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\t\t\t\t\t\t\tstyles.buttonDestructive,\n\t\t\t\t\t\t\t\t\t\t\t\t!deletePassword ? styles.buttonDisabled : {},\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{has2FAEnabled ? 'Continue' : 'Delete Account'}\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => setDeleteStep('confirm')}\n\t\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline)}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\tBack\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{/* Step 3: 2FA verification (only if 2FA is enabled) */}\n\t\t\t\t\t\t\t{deleteStep === '2fa' && (\n\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.flexCenter, {\n\t\t\t\t\t\t\t\t\t\t\twidth: '3rem',\n\t\t\t\t\t\t\t\t\t\t\theight: '3rem',\n\t\t\t\t\t\t\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: `${theme.colorDestructive}15`,\n\t\t\t\t\t\t\t\t\t\t\tmargin: '0 auto 1rem',\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<ShieldIcon size={24} color={theme.colorDestructive} />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, styles.textCenter, {\n\t\t\t\t\t\t\t\t\t\t\tmargin: '0 0 1rem',\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tEnter your two-factor authentication code to confirm:\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\tvalue={delete2FACode}\n\t\t\t\t\t\t\t\t\t\tonChange={(e) =>\n\t\t\t\t\t\t\t\t\t\t\tsetDelete2FACode(e.target.value.replace(/\\D/g, '').slice(0, 6))\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tplaceholder=\"000000\"\n\t\t\t\t\t\t\t\t\t\tmaxLength={6}\n\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.input, {\n\t\t\t\t\t\t\t\t\t\t\tmarginBottom: '1rem',\n\t\t\t\t\t\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\t\t\t\t\t\tletterSpacing: '0.5em',\n\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeLg,\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.flexRow, {\n\t\t\t\t\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\t\t\t\t\tjustifyContent: 'center',\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={handle2FAStep}\n\t\t\t\t\t\t\t\t\t\t\tdisabled={isDeleting || delete2FACode.length !== 6}\n\t\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\t\t\t\t\t\t\tstyles.buttonDestructive,\n\t\t\t\t\t\t\t\t\t\t\t\tisDeleting || delete2FACode.length !== 6 ? styles.buttonDisabled : {},\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{isDeleting ? (\n\t\t\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t\t\t\t\t\t\t\t\tDeleting...\n\t\t\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t\t'Permanently Delete'\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => setDeleteStep('password')}\n\t\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline)}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\tBack\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n// Icons\nfunction DownloadIcon({ size = 24 }: { size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n\t\t\t<polyline points=\"7 10 12 15 17 10\" />\n\t\t\t<line x1=\"12\" y1=\"15\" x2=\"12\" y2=\"3\" />\n\t\t</svg>\n\t)\n}\n\nfunction TrashIcon({ size = 24 }: { size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<polyline points=\"3 6 5 6 21 6\" />\n\t\t\t<path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n\t\t</svg>\n\t)\n}\n\nfunction ShieldIcon({ size = 24, color = 'currentColor' }: { size?: number; color?: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z\" />\n\t\t</svg>\n\t)\n}\n","/**\n * Analytics Dashboard Components\n *\n * Event viewer, stats cards, and basic analytics visualization.\n */\n\n'use client'\n\nimport { type CSSProperties, useEffect, useState } from 'react'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles } from './styles'\n\n// ============================================\n// Types\n// ============================================\n\nexport interface AnalyticsEvent {\n\tid: string\n\tname: string\n\ttimestamp: string\n\tuserId?: string\n\tproperties?: Record<string, unknown>\n\tsessionId?: string\n}\n\nexport interface AnalyticsStat {\n\tlabel: string\n\tvalue: number | string\n\tchange?: number // percentage change\n\tchangeLabel?: string\n\ticon?: 'users' | 'pageviews' | 'events' | 'sessions' | 'custom'\n}\n\nexport interface TimeSeriesData {\n\tlabel: string\n\tvalue: number\n}\n\n// ============================================\n// EventViewer\n// ============================================\n\nexport interface EventViewerProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Custom class name */\n\tclassName?: string\n\t/** Events to display */\n\tevents?: AnalyticsEvent[]\n\t/** Whether loading */\n\tisLoading?: boolean\n\t/** Called when event is clicked */\n\tonEventClick?: (event: AnalyticsEvent) => void\n\t/** Show search/filter */\n\tshowSearch?: boolean\n\t/** Show timestamps */\n\tshowTimestamps?: boolean\n\t/** Max events to show */\n\tmaxEvents?: number\n\t/** Empty state message */\n\temptyMessage?: string\n\t/** Title */\n\ttitle?: string\n}\n\n/**\n * Real-time event viewer\n *\n * @example\n * ```tsx\n * <EventViewer\n *   events={events}\n *   onEventClick={(e) => console.log(e)}\n *   showSearch\n * />\n * ```\n */\nexport function EventViewer({\n\ttheme = defaultTheme,\n\tclassName,\n\tevents = [],\n\tisLoading = false,\n\tonEventClick,\n\tshowSearch = true,\n\tshowTimestamps = true,\n\tmaxEvents = 100,\n\temptyMessage = 'No events recorded yet',\n\ttitle = 'Recent Events',\n}: EventViewerProps) {\n\tconst [search, setSearch] = useState('')\n\tconst [expandedId, setExpandedId] = useState<string | null>(null)\n\tconst styles = baseStyles(theme)\n\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tconst filteredEvents = events\n\t\t.filter((e) => !search || e.name.toLowerCase().includes(search.toLowerCase()))\n\t\t.slice(0, maxEvents)\n\n\tconst containerStyle: CSSProperties = {\n\t\tfontFamily: theme.fontFamily,\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t\toverflow: 'hidden',\n\t}\n\n\tconst headerStyle: CSSProperties = {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'space-between',\n\t\tpadding: '1rem',\n\t\tbackgroundColor: theme.colorMuted,\n\t\tborderBottom: `1px solid ${theme.colorBorder}`,\n\t}\n\n\tconst eventItemStyle: CSSProperties = {\n\t\tpadding: '0.75rem 1rem',\n\t\tborderBottom: `1px solid ${theme.colorBorder}`,\n\t\tcursor: onEventClick ? 'pointer' : 'default',\n\t\ttransition: 'background-color 0.15s ease',\n\t}\n\n\treturn (\n\t\t<div style={containerStyle} className={className}>\n\t\t\t<div style={headerStyle}>\n\t\t\t\t<h3\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\tfontSize: theme.fontSizeLg,\n\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<EventIcon color={theme.colorPrimary} />\n\t\t\t\t\t{title}\n\t\t\t\t</h3>\n\t\t\t\t{showSearch && (\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tvalue={search}\n\t\t\t\t\t\tonChange={(e) => setSearch(e.target.value)}\n\t\t\t\t\t\tplaceholder=\"Filter events...\"\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tpadding: '0.5rem 0.75rem',\n\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\tbackgroundColor: theme.colorBackground,\n\t\t\t\t\t\t\tcolor: theme.colorForeground,\n\t\t\t\t\t\t\twidth: '200px',\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t<div style={{ maxHeight: '400px', overflowY: 'auto' }}>\n\t\t\t\t{isLoading ? (\n\t\t\t\t\t<div style={{ padding: '2rem', textAlign: 'center' }}>\n\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t</div>\n\t\t\t\t) : filteredEvents.length === 0 ? (\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tpadding: '3rem',\n\t\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<EventIcon color={theme.colorMuted} size={48} />\n\t\t\t\t\t\t<p style={{ margin: '1rem 0 0' }}>{emptyMessage}</p>\n\t\t\t\t\t</div>\n\t\t\t\t) : (\n\t\t\t\t\tfilteredEvents.map((event, i) => (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tkey={event.id}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\tsetExpandedId(expandedId === event.id ? null : event.id)\n\t\t\t\t\t\t\t\tonEventClick?.(event)\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\taria-expanded={expandedId === event.id}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t...eventItemStyle,\n\t\t\t\t\t\t\t\tborderBottom:\n\t\t\t\t\t\t\t\t\ti === filteredEvents.length - 1 ? 'none' : eventItemStyle.borderBottom,\n\t\t\t\t\t\t\t\ttextAlign: 'left',\n\t\t\t\t\t\t\t\tfont: 'inherit',\n\t\t\t\t\t\t\t\tcolor: 'inherit',\n\t\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\tgap: '0.75rem',\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\twidth: 8,\n\t\t\t\t\t\t\t\t\t\t\theight: 8,\n\t\t\t\t\t\t\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: theme.colorPrimary,\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t<span style={{ fontWeight: 500, fontSize: theme.fontSizeSm }}>{event.name}</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t{showTimestamps && (\n\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{new Date(event.timestamp).toLocaleString()}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t{/* Expanded details */}\n\t\t\t\t\t\t\t{expandedId === event.id &&\n\t\t\t\t\t\t\t\tevent.properties &&\n\t\t\t\t\t\t\t\tObject.keys(event.properties).length > 0 && (\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tmarginTop: '0.75rem',\n\t\t\t\t\t\t\t\t\t\t\tpadding: '0.75rem',\n\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<pre\n\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\t\t\t\t\t\t\tfontFamily: 'monospace',\n\t\t\t\t\t\t\t\t\t\t\t\twhiteSpace: 'pre-wrap',\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{JSON.stringify(event.properties, null, 2)}\n\t\t\t\t\t\t\t\t\t\t</pre>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t))\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n// ============================================\n// StatsCard\n// ============================================\n\nexport interface StatsCardProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Custom class name */\n\tclassName?: string\n\t/** Stat label */\n\tlabel: string\n\t/** Stat value */\n\tvalue: number | string\n\t/** Percentage change */\n\tchange?: number\n\t/** Change label (e.g., \"vs last week\") */\n\tchangeLabel?: string\n\t/** Icon type */\n\ticon?: 'users' | 'pageviews' | 'events' | 'sessions' | 'revenue' | 'custom'\n\t/** Custom icon */\n\tcustomIcon?: React.ReactNode\n\t/** Whether loading */\n\tisLoading?: boolean\n}\n\n/**\n * Single stat card\n *\n * @example\n * ```tsx\n * <StatsCard\n *   label=\"Total Users\"\n *   value={1234}\n *   change={12.5}\n *   changeLabel=\"vs last month\"\n *   icon=\"users\"\n * />\n * ```\n */\nexport function StatsCard({\n\ttheme = defaultTheme,\n\tclassName,\n\tlabel,\n\tvalue,\n\tchange,\n\tchangeLabel = 'vs last period',\n\ticon = 'custom',\n\tcustomIcon,\n\tisLoading = false,\n}: StatsCardProps) {\n\tconst styles = baseStyles(theme)\n\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tconst containerStyle: CSSProperties = {\n\t\tfontFamily: theme.fontFamily,\n\t\tpadding: '1.25rem',\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t\tbackgroundColor: theme.colorBackground,\n\t}\n\n\tconst getIcon = () => {\n\t\tif (customIcon) return customIcon\n\t\tswitch (icon) {\n\t\t\tcase 'users':\n\t\t\t\treturn <UsersIcon color={theme.colorPrimary} />\n\t\t\tcase 'pageviews':\n\t\t\t\treturn <PageviewsIcon color={theme.colorPrimary} />\n\t\t\tcase 'events':\n\t\t\t\treturn <EventIcon color={theme.colorPrimary} />\n\t\t\tcase 'sessions':\n\t\t\t\treturn <SessionsIcon color={theme.colorPrimary} />\n\t\t\tcase 'revenue':\n\t\t\t\treturn <RevenueIcon color={theme.colorPrimary} />\n\t\t\tdefault:\n\t\t\t\treturn <ChartIcon color={theme.colorPrimary} />\n\t\t}\n\t}\n\n\tconst formatValue = (val: number | string) => {\n\t\tif (typeof val === 'number') {\n\t\t\tif (val >= 1000000) return `${(val / 1000000).toFixed(1)}M`\n\t\t\tif (val >= 1000) return `${(val / 1000).toFixed(1)}K`\n\t\t\treturn val.toLocaleString()\n\t\t}\n\t\treturn val\n\t}\n\n\treturn (\n\t\t<div style={containerStyle} className={className}>\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\talignItems: 'center',\n\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\tmarginBottom: '0.75rem',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<span\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{label}\n\t\t\t\t</span>\n\t\t\t\t{getIcon()}\n\t\t\t</div>\n\n\t\t\t{isLoading ? (\n\t\t\t\t<div style={{ height: '2rem' }}>\n\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tfontSize: theme.fontSizeXl,\n\t\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{formatValue(value)}\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{change !== undefined && (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\tgap: '0.25rem',\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tcolor: change >= 0 ? theme.colorSuccess : theme.colorDestructive,\n\t\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{change >= 0 ? '↑' : '↓'} {Math.abs(change).toFixed(1)}%\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<span style={{ color: theme.colorMutedForeground }}>{changeLabel}</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n// ============================================\n// StatsGrid\n// ============================================\n\nexport interface StatsGridProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Custom class name */\n\tclassName?: string\n\t/** Stats to display */\n\tstats: AnalyticsStat[]\n\t/** Number of columns */\n\tcolumns?: 2 | 3 | 4\n\t/** Whether loading */\n\tisLoading?: boolean\n}\n\n/**\n * Grid of stat cards\n *\n * @example\n * ```tsx\n * <StatsGrid\n *   stats={[\n *     { label: 'Users', value: 1234, change: 12 },\n *     { label: 'Sessions', value: 5678, change: -5 },\n *   ]}\n *   columns={4}\n * />\n * ```\n */\nexport function StatsGrid({\n\ttheme = defaultTheme,\n\tclassName,\n\tstats,\n\tcolumns = 4,\n\tisLoading = false,\n}: StatsGridProps) {\n\tconst gridStyle: CSSProperties = {\n\t\tdisplay: 'grid',\n\t\tgridTemplateColumns: `repeat(${columns}, 1fr)`,\n\t\tgap: '1rem',\n\t}\n\n\treturn (\n\t\t<div style={gridStyle} className={className}>\n\t\t\t{stats.map((stat, i) => (\n\t\t\t\t<StatsCard\n\t\t\t\t\tkey={i}\n\t\t\t\t\ttheme={theme}\n\t\t\t\t\tlabel={stat.label}\n\t\t\t\t\tvalue={stat.value}\n\t\t\t\t\tchange={stat.change}\n\t\t\t\t\tchangeLabel={stat.changeLabel}\n\t\t\t\t\ticon={stat.icon}\n\t\t\t\t\tisLoading={isLoading}\n\t\t\t\t/>\n\t\t\t))}\n\t\t</div>\n\t)\n}\n\n// ============================================\n// SimpleChart (Bar Chart)\n// ============================================\n\nexport interface SimpleChartProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Custom class name */\n\tclassName?: string\n\t/** Data points */\n\tdata: TimeSeriesData[]\n\t/** Chart title */\n\ttitle?: string\n\t/** Y-axis label */\n\tyAxisLabel?: string\n\t/** Bar color */\n\tbarColor?: string\n\t/** Height of chart area */\n\theight?: number\n\t/** Whether loading */\n\tisLoading?: boolean\n}\n\n/**\n * Simple bar chart for time series data\n *\n * @example\n * ```tsx\n * <SimpleChart\n *   title=\"Daily Active Users\"\n *   data={[\n *     { label: 'Mon', value: 100 },\n *     { label: 'Tue', value: 150 },\n *     { label: 'Wed', value: 120 },\n *   ]}\n * />\n * ```\n */\nexport function SimpleChart({\n\ttheme = defaultTheme,\n\tclassName,\n\tdata,\n\ttitle,\n\tyAxisLabel,\n\tbarColor,\n\theight = 200,\n\tisLoading = false,\n}: SimpleChartProps) {\n\tconst styles = baseStyles(theme)\n\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tconst maxValue = Math.max(...data.map((d) => d.value), 1)\n\tconst color = barColor ?? theme.colorPrimary\n\n\tconst containerStyle: CSSProperties = {\n\t\tfontFamily: theme.fontFamily,\n\t\tpadding: '1.25rem',\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t\tbackgroundColor: theme.colorBackground,\n\t}\n\n\treturn (\n\t\t<div style={containerStyle} className={className}>\n\t\t\t{title && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t\tmarginBottom: '1rem',\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<h3 style={{ margin: 0, fontSize: theme.fontSizeLg, fontWeight: 600 }}>{title}</h3>\n\t\t\t\t\t{yAxisLabel && (\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{yAxisLabel}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{isLoading ? (\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\theight,\n\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\tjustifyContent: 'center',\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t</div>\n\t\t\t) : data.length === 0 ? (\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\theight,\n\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\tjustifyContent: 'center',\n\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\tNo data available\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<div style={{ height }}>\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\talignItems: 'flex-end',\n\t\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t\t\theight: '100%',\n\t\t\t\t\t\t\tgap: '4px',\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{data.map((d, i) => {\n\t\t\t\t\t\t\tconst barHeight = (d.value / maxValue) * 100\n\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tflex: 1,\n\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\tflexDirection: 'column',\n\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\theight: '100%',\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tflex: 1,\n\t\t\t\t\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\t\talignItems: 'flex-end',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\t\t\t\t\t\theight: `${barHeight}%`,\n\t\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: color,\n\t\t\t\t\t\t\t\t\t\t\t\tborderRadius: '4px 4px 0 0',\n\t\t\t\t\t\t\t\t\t\t\t\tminHeight: '4px',\n\t\t\t\t\t\t\t\t\t\t\t\ttransition: 'height 0.3s ease',\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\ttitle={`${d.label}: ${d.value.toLocaleString()}`}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tmarginTop: '0.5rem',\n\t\t\t\t\t\t\t\t\t\t\tfontSize: '0.625rem',\n\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t\t\twhiteSpace: 'nowrap',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{d.label}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t})}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n// ============================================\n// AnalyticsDashboard (Combined)\n// ============================================\n\nexport interface AnalyticsDashboardProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Custom class name */\n\tclassName?: string\n\t/** Stats to display */\n\tstats?: AnalyticsStat[]\n\t/** Chart data */\n\tchartData?: TimeSeriesData[]\n\t/** Chart title */\n\tchartTitle?: string\n\t/** Recent events */\n\tevents?: AnalyticsEvent[]\n\t/** Whether loading */\n\tisLoading?: boolean\n\t/** Time period label */\n\tperiod?: string\n}\n\n/**\n * Complete analytics dashboard\n *\n * @example\n * ```tsx\n * <AnalyticsDashboard\n *   stats={stats}\n *   chartData={dailyData}\n *   chartTitle=\"Daily Active Users\"\n *   events={recentEvents}\n *   period=\"Last 7 days\"\n * />\n * ```\n */\nexport function AnalyticsDashboard({\n\ttheme = defaultTheme,\n\tclassName,\n\tstats = [],\n\tchartData = [],\n\tchartTitle = 'Activity',\n\tevents = [],\n\tisLoading = false,\n\tperiod,\n}: AnalyticsDashboardProps) {\n\tconst containerStyle: CSSProperties = {\n\t\tfontFamily: theme.fontFamily,\n\t\tdisplay: 'flex',\n\t\tflexDirection: 'column',\n\t\tgap: '1.5rem',\n\t}\n\n\treturn (\n\t\t<div style={containerStyle} className={className}>\n\t\t\t{period && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<h2 style={{ margin: 0, fontSize: theme.fontSizeXl, fontWeight: 600 }}>Analytics</h2>\n\t\t\t\t\t<span\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{period}\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{stats.length > 0 && (\n\t\t\t\t<StatsGrid\n\t\t\t\t\ttheme={theme}\n\t\t\t\t\tstats={stats}\n\t\t\t\t\tcolumns={Math.min(stats.length, 4) as 2 | 3 | 4}\n\t\t\t\t\tisLoading={isLoading}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{chartData.length > 0 && (\n\t\t\t\t<SimpleChart theme={theme} data={chartData} title={chartTitle} isLoading={isLoading} />\n\t\t\t)}\n\n\t\t\t{events.length > 0 && (\n\t\t\t\t<EventViewer theme={theme} events={events} isLoading={isLoading} maxEvents={10} />\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n// ============================================\n// Icons\n// ============================================\n\nfunction EventIcon({ color, size = 20 }: { color: string; size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<circle cx=\"12\" cy=\"12\" r=\"10\" />\n\t\t\t<polyline points=\"12 6 12 12 16 14\" />\n\t\t</svg>\n\t)\n}\n\nfunction UsersIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"20\"\n\t\t\theight=\"20\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2\" />\n\t\t\t<circle cx=\"9\" cy=\"7\" r=\"4\" />\n\t\t\t<path d=\"M23 21v-2a4 4 0 0 0-3-3.87\" />\n\t\t\t<path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\n\t\t</svg>\n\t)\n}\n\nfunction PageviewsIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"20\"\n\t\t\theight=\"20\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\" />\n\t\t\t<circle cx=\"12\" cy=\"12\" r=\"3\" />\n\t\t</svg>\n\t)\n}\n\nfunction SessionsIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"20\"\n\t\t\theight=\"20\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\" />\n\t\t\t<line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\" />\n\t\t</svg>\n\t)\n}\n\nfunction RevenueIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"20\"\n\t\t\theight=\"20\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<line x1=\"12\" y1=\"1\" x2=\"12\" y2=\"23\" />\n\t\t\t<path d=\"M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6\" />\n\t\t</svg>\n\t)\n}\n\nfunction ChartIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"20\"\n\t\t\theight=\"20\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<line x1=\"18\" y1=\"20\" x2=\"18\" y2=\"10\" />\n\t\t\t<line x1=\"12\" y1=\"20\" x2=\"12\" y2=\"4\" />\n\t\t\t<line x1=\"6\" y1=\"20\" x2=\"6\" y2=\"14\" />\n\t\t</svg>\n\t)\n}\n","/**\n * API Key Manager Components\n *\n * Create, view, and revoke API keys.\n */\n\n'use client'\n\nimport { type CSSProperties, type FormEvent, useEffect, useId, useState } from 'react'\nimport {\n\tAPI_KEY_EXPIRY_1_DAY,\n\tAPI_KEY_EXPIRY_1_YEAR,\n\tAPI_KEY_EXPIRY_7_DAYS,\n\tAPI_KEY_EXPIRY_30_DAYS,\n\tAPI_KEY_EXPIRY_90_DAYS,\n\tUI_COPY_FEEDBACK_MS,\n} from '../../constants'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\n// ============================================\n// Types\n// ============================================\n\nexport interface APIKey {\n\tid: string\n\tname: string\n\tprefix: string // First few chars for identification (e.g., \"sk_live_abc\")\n\tcreatedAt: string\n\tlastUsedAt?: string\n\texpiresAt?: string\n\tscopes?: string[]\n\tenvironment?: 'development' | 'staging' | 'production'\n}\n\nexport interface NewAPIKey extends APIKey {\n\t/** Full key (only shown once at creation) */\n\tkey: string\n}\n\n// ============================================\n// APIKeyManager\n// ============================================\n\nexport interface APIKeyManagerProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Custom class name */\n\tclassName?: string\n\t/** API keys to display */\n\tapiKeys?: APIKey[]\n\t/** Available scopes */\n\tavailableScopes?: string[]\n\t/** Called when key is created */\n\tonCreate?: (data: { name: string; scopes: string[]; expiresIn?: number }) => Promise<NewAPIKey>\n\t/** Called when key is revoked */\n\tonRevoke?: (keyId: string) => Promise<void>\n\t/** Whether loading */\n\tisLoading?: boolean\n\t/** Title */\n\ttitle?: string\n\t/** Empty state message */\n\temptyMessage?: string\n\t/** Show environment badge */\n\tshowEnvironment?: boolean\n}\n\nconst DEFAULT_SCOPES = [\n\t'read:users',\n\t'write:users',\n\t'read:billing',\n\t'write:billing',\n\t'read:analytics',\n\t'admin',\n]\n\n/**\n * API key management UI\n *\n * @example\n * ```tsx\n * <APIKeyManager\n *   apiKeys={keys}\n *   onCreate={async (data) => createKey(data)}\n *   onRevoke={async (id) => revokeKey(id)}\n * />\n * ```\n */\nexport function APIKeyManager({\n\ttheme = defaultTheme,\n\tclassName,\n\tapiKeys = [],\n\tavailableScopes = DEFAULT_SCOPES,\n\tonCreate,\n\tonRevoke,\n\tisLoading = false,\n\ttitle = 'API Keys',\n\temptyMessage = 'No API keys created',\n\tshowEnvironment = true,\n}: APIKeyManagerProps) {\n\tconst keyNameId = useId()\n\tconst expirationId = useId()\n\tconst [showCreate, setShowCreate] = useState(false)\n\tconst [name, setName] = useState('')\n\tconst [selectedScopes, setSelectedScopes] = useState<string[]>([])\n\tconst [expiresIn, setExpiresIn] = useState<number | undefined>(undefined)\n\tconst [isCreating, setIsCreating] = useState(false)\n\tconst [error, setError] = useState<string | null>(null)\n\tconst [newKey, setNewKey] = useState<NewAPIKey | null>(null)\n\tconst [revokingId, setRevokingId] = useState<string | null>(null)\n\tconst [copied, setCopied] = useState(false)\n\n\tconst styles = baseStyles(theme)\n\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tuseEffect(() => {\n\t\tif (copied) {\n\t\t\tconst timer = setTimeout(() => setCopied(false), UI_COPY_FEEDBACK_MS)\n\t\t\treturn () => clearTimeout(timer)\n\t\t}\n\t}, [copied])\n\n\tconst handleCreate = async (e: FormEvent) => {\n\t\te.preventDefault()\n\t\tif (!onCreate || !name) return\n\n\t\tsetIsCreating(true)\n\t\tsetError(null)\n\n\t\ttry {\n\t\t\tconst key = await onCreate({\n\t\t\t\tname,\n\t\t\t\tscopes: selectedScopes,\n\t\t\t\texpiresIn,\n\t\t\t})\n\t\t\tsetNewKey(key)\n\t\t\tsetShowCreate(false)\n\t\t\tsetName('')\n\t\t\tsetSelectedScopes([])\n\t\t\tsetExpiresIn(undefined)\n\t\t} catch (err) {\n\t\t\tsetError(err instanceof Error ? err.message : 'Failed to create API key')\n\t\t} finally {\n\t\t\tsetIsCreating(false)\n\t\t}\n\t}\n\n\tconst handleRevoke = async (keyId: string) => {\n\t\tif (!onRevoke) return\n\t\tsetRevokingId(keyId)\n\t\ttry {\n\t\t\tawait onRevoke(keyId)\n\t\t} finally {\n\t\t\tsetRevokingId(null)\n\t\t}\n\t}\n\n\tconst copyToClipboard = async (text: string) => {\n\t\ttry {\n\t\t\tawait navigator.clipboard.writeText(text)\n\t\t\tsetCopied(true)\n\t\t} catch {\n\t\t\t// Fallback\n\t\t\tconst textarea = document.createElement('textarea')\n\t\t\ttextarea.value = text\n\t\t\tdocument.body.appendChild(textarea)\n\t\t\ttextarea.select()\n\t\t\tdocument.execCommand('copy')\n\t\t\tdocument.body.removeChild(textarea)\n\t\t\tsetCopied(true)\n\t\t}\n\t}\n\n\tconst toggleScope = (scope: string) => {\n\t\tsetSelectedScopes((prev) =>\n\t\t\tprev.includes(scope) ? prev.filter((s) => s !== scope) : [...prev, scope],\n\t\t)\n\t}\n\n\tconst envColors: Record<string, { bg: string; text: string }> = {\n\t\tdevelopment: { bg: `${theme.colorWarning}20`, text: theme.colorWarning },\n\t\tstaging: { bg: `${theme.colorPrimary}20`, text: theme.colorPrimary },\n\t\tproduction: { bg: `${theme.colorSuccess}20`, text: theme.colorSuccess },\n\t}\n\n\tconst containerStyle: CSSProperties = {\n\t\tfontFamily: theme.fontFamily,\n\t}\n\n\tconst keyCardStyle: CSSProperties = {\n\t\tpadding: '1rem',\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t\tmarginBottom: '0.75rem',\n\t}\n\n\tconst inputStyle: CSSProperties = {\n\t\twidth: '100%',\n\t\tpadding: '0.75rem',\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t\tbackgroundColor: theme.colorBackground,\n\t\tcolor: theme.colorForeground,\n\t\tfontSize: theme.fontSizeSm,\n\t\tfontFamily: theme.fontFamily,\n\t}\n\n\treturn (\n\t\t<div style={containerStyle} className={className}>\n\t\t\t{/* Header */}\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\talignItems: 'center',\n\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\tmarginBottom: '1.5rem',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div>\n\t\t\t\t\t<h3 style={{ margin: 0, fontSize: theme.fontSizeLg, fontWeight: 600 }}>{title}</h3>\n\t\t\t\t\t<p\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tManage your API keys for programmatic access\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={() => setShowCreate(true)}\n\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary)}\n\t\t\t\t>\n\t\t\t\t\t<PlusIcon color={theme.colorPrimaryForeground} /> Create Key\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t{/* New Key Display (shown once after creation) */}\n\t\t\t{newKey && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\t...keyCardStyle,\n\t\t\t\t\t\tbackgroundColor: `${theme.colorSuccess}10`,\n\t\t\t\t\t\tborderColor: theme.colorSuccess,\n\t\t\t\t\t\tmarginBottom: '1.5rem',\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\tmarginBottom: '0.75rem',\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<CheckIcon color={theme.colorSuccess} />\n\t\t\t\t\t\t<span style={{ fontWeight: 600, color: theme.colorSuccess }}>API Key Created</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<p\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tmargin: '0 0 0.75rem',\n\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tCopy this key now. You won't be able to see it again.\n\t\t\t\t\t</p>\n\t\t\t\t\t<div style={{ display: 'flex', gap: '0.5rem' }}>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\tvalue={newKey.key}\n\t\t\t\t\t\t\treadOnly\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t...inputStyle,\n\t\t\t\t\t\t\t\tflex: 1,\n\t\t\t\t\t\t\t\tfontFamily: 'monospace',\n\t\t\t\t\t\t\t\tbackgroundColor: theme.colorBackground,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={() => copyToClipboard(newKey.key)}\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{copied ? 'Copied!' : 'Copy'}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={() => setNewKey(null)}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tmarginTop: '0.75rem',\n\t\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t\ttextDecoration: 'underline',\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tDismiss\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Create Form */}\n\t\t\t{showCreate && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\t...keyCardStyle,\n\t\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\t\tmarginBottom: '1.5rem',\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<h4\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tmargin: '0 0 1rem',\n\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tNew API Key\n\t\t\t\t\t</h4>\n\n\t\t\t\t\t{error && (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.alert, styles.alertError, {\n\t\t\t\t\t\t\t\tmarginBottom: '1rem',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{error}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\n\t\t\t\t\t<form onSubmit={handleCreate}>\n\t\t\t\t\t\t<div style={{ marginBottom: '1rem' }}>\n\t\t\t\t\t\t\t<label\n\t\t\t\t\t\t\t\thtmlFor={keyNameId}\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tKey Name *\n\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\tid={keyNameId}\n\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\tvalue={name}\n\t\t\t\t\t\t\t\tonChange={(e) => setName(e.target.value)}\n\t\t\t\t\t\t\t\tstyle={inputStyle}\n\t\t\t\t\t\t\t\tplaceholder=\"My API Key\"\n\t\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tA friendly name to identify this key\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<fieldset style={{ marginBottom: '1rem', border: 'none', padding: 0, margin: 0 }}>\n\t\t\t\t\t\t\t<legend\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tScopes\n\t\t\t\t\t\t\t</legend>\n\t\t\t\t\t\t\t<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.5rem' }}>\n\t\t\t\t\t\t\t\t{availableScopes.map((scope) => (\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\tkey={scope}\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => toggleScope(scope)}\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tpadding: '0.375rem 0.75rem',\n\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\tborder: `1px solid ${selectedScopes.includes(scope) ? theme.colorPrimary : theme.colorBorder}`,\n\t\t\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: selectedScopes.includes(scope)\n\t\t\t\t\t\t\t\t\t\t\t\t? `${theme.colorPrimary}10`\n\t\t\t\t\t\t\t\t\t\t\t\t: 'transparent',\n\t\t\t\t\t\t\t\t\t\t\tcolor: selectedScopes.includes(scope)\n\t\t\t\t\t\t\t\t\t\t\t\t? theme.colorPrimary\n\t\t\t\t\t\t\t\t\t\t\t\t: theme.colorForeground,\n\t\t\t\t\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{scope}\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tLeave empty for full access\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t</fieldset>\n\n\t\t\t\t\t\t<div style={{ marginBottom: '1.5rem' }}>\n\t\t\t\t\t\t\t<label\n\t\t\t\t\t\t\t\thtmlFor={expirationId}\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tExpiration\n\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t<select\n\t\t\t\t\t\t\t\tid={expirationId}\n\t\t\t\t\t\t\t\tvalue={expiresIn ?? ''}\n\t\t\t\t\t\t\t\tonChange={(e) =>\n\t\t\t\t\t\t\t\t\tsetExpiresIn(e.target.value ? Number.parseInt(e.target.value, 10) : undefined)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tstyle={inputStyle}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<option value=\"\">Never expires</option>\n\t\t\t\t\t\t\t\t<option value={API_KEY_EXPIRY_1_DAY}>1 day</option>\n\t\t\t\t\t\t\t\t<option value={API_KEY_EXPIRY_7_DAYS}>7 days</option>\n\t\t\t\t\t\t\t\t<option value={API_KEY_EXPIRY_30_DAYS}>30 days</option>\n\t\t\t\t\t\t\t\t<option value={API_KEY_EXPIRY_90_DAYS}>90 days</option>\n\t\t\t\t\t\t\t\t<option value={API_KEY_EXPIRY_1_YEAR}>1 year</option>\n\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<div style={{ display: 'flex', gap: '0.75rem' }}>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\tsetShowCreate(false)\n\t\t\t\t\t\t\t\t\tsetName('')\n\t\t\t\t\t\t\t\t\tsetSelectedScopes([])\n\t\t\t\t\t\t\t\t\tsetExpiresIn(undefined)\n\t\t\t\t\t\t\t\t\tsetError(null)\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\tdisabled={isCreating || !name}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{isCreating ? <span style={styles.spinner} /> : 'Create API Key'}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</form>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Key List */}\n\t\t\t{isLoading ? (\n\t\t\t\t<div style={{ padding: '2rem', textAlign: 'center' }}>\n\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t</div>\n\t\t\t) : apiKeys.length === 0 ? (\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tpadding: '3rem',\n\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<KeyIcon color={theme.colorMuted} size={48} />\n\t\t\t\t\t<p style={{ margin: '1rem 0 0' }}>{emptyMessage}</p>\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\tapiKeys.map((key) => (\n\t\t\t\t\t<div key={key.id} style={keyCardStyle}>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\talignItems: 'flex-start',\n\t\t\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div style={{ flex: 1, minWidth: 0 }}>\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span style={{ fontWeight: 600, fontSize: theme.fontSizeSm }}>{key.name}</span>\n\t\t\t\t\t\t\t\t\t{showEnvironment && key.environment && (\n\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\tpadding: '0.125rem 0.375rem',\n\t\t\t\t\t\t\t\t\t\t\t\tfontSize: '0.625rem',\n\t\t\t\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: envColors[key.environment]?.bg ?? theme.colorMuted,\n\t\t\t\t\t\t\t\t\t\t\t\tcolor: envColors[key.environment]?.text ?? theme.colorForeground,\n\t\t\t\t\t\t\t\t\t\t\t\ttextTransform: 'capitalize',\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{key.environment}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tfontFamily: 'monospace',\n\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{key.prefix}...\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t{key.scopes && key.scopes.length > 0 && (\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\t\tflexWrap: 'wrap',\n\t\t\t\t\t\t\t\t\t\t\tgap: '0.25rem',\n\t\t\t\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{key.scopes.map((scope) => (\n\t\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\t\tkey={scope}\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\tpadding: '0.125rem 0.375rem',\n\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: '0.625rem',\n\t\t\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{scope}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tCreated {new Date(key.createdAt).toLocaleDateString()}\n\t\t\t\t\t\t\t\t\t{key.lastUsedAt && ` • Last used ${new Date(key.lastUsedAt).toLocaleString()}`}\n\t\t\t\t\t\t\t\t\t{key.expiresAt && (\n\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\tcolor:\n\t\t\t\t\t\t\t\t\t\t\t\t\tnew Date(key.expiresAt) < new Date() ? theme.colorDestructive : 'inherit',\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t\t\t\t•{' '}\n\t\t\t\t\t\t\t\t\t\t\t{new Date(key.expiresAt) < new Date()\n\t\t\t\t\t\t\t\t\t\t\t\t? 'Expired'\n\t\t\t\t\t\t\t\t\t\t\t\t: `Expires ${new Date(key.expiresAt).toLocaleDateString()}`}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{onRevoke && (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tonClick={() => handleRevoke(key.id)}\n\t\t\t\t\t\t\t\t\tdisabled={revokingId === key.id}\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\tborder: `1px solid ${theme.colorDestructive}`,\n\t\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\t\t\tcolor: theme.colorDestructive,\n\t\t\t\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t\t\t\t\tmarginLeft: '1rem',\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{revokingId === key.id ? <span style={styles.spinner} /> : 'Revoke'}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t))\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n// ============================================\n// Icons\n// ============================================\n\nfunction KeyIcon({ color, size = 24 }: { color: string; size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4\" />\n\t\t</svg>\n\t)\n}\n\nfunction PlusIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tstyle={{ marginRight: '0.25rem' }}\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n\t\t\t<line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n\t\t</svg>\n\t)\n}\n\nfunction CheckIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<polyline points=\"20 6 9 17 4 12\" />\n\t\t</svg>\n\t)\n}\n","/**\n * Billing Management Components\n *\n * Invoice history, payment method management, and usage tracking.\n */\n\n'use client'\n\nimport { type CSSProperties, useEffect, useState } from 'react'\nimport { formatCurrency } from '../../formatting'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\n// ============================================\n// Types\n// ============================================\n\nexport interface Invoice {\n\tid: string\n\tnumber: string\n\tdate: string\n\tdueDate?: string\n\tamount: number\n\tcurrency: string\n\tstatus: 'paid' | 'pending' | 'overdue' | 'void'\n\tpdfUrl?: string\n\tdescription?: string\n}\n\nexport interface PaymentMethod {\n\tid: string\n\ttype: 'card' | 'bank_account' | 'paypal'\n\tlast4: string\n\tbrand?: string // visa, mastercard, amex\n\texpiryMonth?: number\n\texpiryYear?: number\n\tisDefault: boolean\n}\n\n// ============================================\n// InvoiceHistory\n// ============================================\n\nexport interface InvoiceHistoryProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Custom class name */\n\tclassName?: string\n\t/** Title */\n\ttitle?: string\n\t/** Invoices to display (if not using hook) */\n\tinvoices?: Invoice[]\n\t/** Called when download is clicked */\n\tonDownload?: (invoice: Invoice) => void\n\t/** Show pagination */\n\tshowPagination?: boolean\n\t/** Items per page */\n\tpageSize?: number\n\t/** Empty state message */\n\temptyMessage?: string\n}\n\n/**\n * Invoice history list with download links\n *\n * @example\n * ```tsx\n * <InvoiceHistory\n *   title=\"Billing History\"\n *   onDownload={(invoice) => window.open(invoice.pdfUrl)}\n * />\n * ```\n */\nexport function InvoiceHistory({\n\ttheme = defaultTheme,\n\tclassName,\n\ttitle = 'Invoice History',\n\tinvoices: propInvoices,\n\tonDownload,\n\tshowPagination = true,\n\tpageSize = 10,\n\temptyMessage = 'No invoices yet',\n}: InvoiceHistoryProps) {\n\tconst [invoices] = useState<Invoice[]>(propInvoices ?? [])\n\tconst [currentPage, setCurrentPage] = useState(1)\n\tconst styles = baseStyles(theme)\n\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tconst totalPages = Math.ceil(invoices.length / pageSize)\n\tconst paginatedInvoices = invoices.slice((currentPage - 1) * pageSize, currentPage * pageSize)\n\n\t// Invoice amounts arrive in minor units (cents) — divide before passing\n\t// into the SSOT helper which expects major units. Currency code per row.\n\tconst formatInvoice = (amountCents: number, currency: string) =>\n\t\tformatCurrency(amountCents / 100, { currency })\n\n\tconst formatDate = (dateStr: string) => {\n\t\treturn new Date(dateStr).toLocaleDateString('en-US', {\n\t\t\tyear: 'numeric',\n\t\t\tmonth: 'short',\n\t\t\tday: 'numeric',\n\t\t})\n\t}\n\n\tconst statusColors: Record<Invoice['status'], { bg: string; text: string }> = {\n\t\tpaid: { bg: `${theme.colorSuccess}20`, text: theme.colorSuccess },\n\t\tpending: { bg: `${theme.colorWarning}20`, text: theme.colorWarning },\n\t\toverdue: {\n\t\t\tbg: `${theme.colorDestructive}20`,\n\t\t\ttext: theme.colorDestructive,\n\t\t},\n\t\tvoid: { bg: theme.colorMuted, text: theme.colorMutedForeground },\n\t}\n\n\tconst containerStyle: CSSProperties = {\n\t\tfontFamily: theme.fontFamily,\n\t}\n\n\tconst tableStyle: CSSProperties = {\n\t\twidth: '100%',\n\t\tborderCollapse: 'collapse',\n\t\tfontSize: theme.fontSizeSm,\n\t}\n\n\tconst thStyle: CSSProperties = {\n\t\tpadding: '0.75rem 1rem',\n\t\ttextAlign: 'left',\n\t\tfontWeight: 500,\n\t\tcolor: theme.colorMutedForeground,\n\t\tborderBottom: `1px solid ${theme.colorBorder}`,\n\t\tfontSize: theme.fontSizeXs,\n\t\ttextTransform: 'uppercase',\n\t\tletterSpacing: '0.05em',\n\t}\n\n\tconst tdStyle: CSSProperties = {\n\t\tpadding: '0.75rem 1rem',\n\t\tborderBottom: `1px solid ${theme.colorBorder}`,\n\t}\n\n\treturn (\n\t\t<div style={containerStyle} className={className}>\n\t\t\t<h3\n\t\t\t\tstyle={{\n\t\t\t\t\tmargin: '0 0 1rem',\n\t\t\t\t\tfontSize: theme.fontSizeLg,\n\t\t\t\t\tfontWeight: 600,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{title}\n\t\t\t</h3>\n\n\t\t\t{invoices.length === 0 ? (\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tpadding: '3rem',\n\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<InvoiceIcon color={theme.colorMuted} size={48} />\n\t\t\t\t\t<p style={{ margin: '1rem 0 0' }}>{emptyMessage}</p>\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\toverflowX: 'auto',\n\t\t\t\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<table style={tableStyle}>\n\t\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t<th style={thStyle}>Invoice</th>\n\t\t\t\t\t\t\t\t\t<th style={thStyle}>Date</th>\n\t\t\t\t\t\t\t\t\t<th style={thStyle}>Amount</th>\n\t\t\t\t\t\t\t\t\t<th style={thStyle}>Status</th>\n\t\t\t\t\t\t\t\t\t<th style={{ ...thStyle, textAlign: 'right' }}>Actions</th>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t\t{paginatedInvoices.map((invoice) => (\n\t\t\t\t\t\t\t\t\t<tr key={invoice.id}>\n\t\t\t\t\t\t\t\t\t\t<td style={tdStyle}>\n\t\t\t\t\t\t\t\t\t\t\t<div style={{ fontWeight: 500 }}>{invoice.number}</div>\n\t\t\t\t\t\t\t\t\t\t\t{invoice.description && (\n\t\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{invoice.description}\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t<td style={tdStyle}>{formatDate(invoice.date)}</td>\n\t\t\t\t\t\t\t\t\t\t<td style={tdStyle}>\n\t\t\t\t\t\t\t\t\t\t\t<span style={{ fontWeight: 500 }}>\n\t\t\t\t\t\t\t\t\t\t\t\t{formatInvoice(invoice.amount, invoice.currency)}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t<td style={tdStyle}>\n\t\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\tdisplay: 'inline-block',\n\t\t\t\t\t\t\t\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: statusColors[invoice.status].bg,\n\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: statusColors[invoice.status].text,\n\t\t\t\t\t\t\t\t\t\t\t\t\ttextTransform: 'capitalize',\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{invoice.status}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t<td style={{ ...tdStyle, textAlign: 'right' }}>\n\t\t\t\t\t\t\t\t\t\t\t{invoice.pdfUrl && (\n\t\t\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => onDownload?.(invoice)}\n\t\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorForeground,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisplay: 'inline-flex',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tgap: '0.25rem',\n\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<DownloadIcon color={theme.colorForeground} />\n\t\t\t\t\t\t\t\t\t\t\t\t\tPDF\n\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</tbody>\n\t\t\t\t\t\t</table>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{showPagination && totalPages > 1 && (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\tShowing {(currentPage - 1) * pageSize + 1}-\n\t\t\t\t\t\t\t\t{Math.min(currentPage * pageSize, invoices.length)} of {invoices.length}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<div style={{ display: 'flex', gap: '0.5rem' }}>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tdisabled={currentPage === 1}\n\t\t\t\t\t\t\t\t\tonClick={() => setCurrentPage((p) => p - 1)}\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline, {\n\t\t\t\t\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\topacity: currentPage === 1 ? 0.5 : 1,\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tPrevious\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tdisabled={currentPage === totalPages}\n\t\t\t\t\t\t\t\t\tonClick={() => setCurrentPage((p) => p + 1)}\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline, {\n\t\t\t\t\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\topacity: currentPage === totalPages ? 0.5 : 1,\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tNext\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n// ============================================\n// PaymentMethodManager\n// ============================================\n\nexport interface PaymentMethodManagerProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Custom class name */\n\tclassName?: string\n\t/** Title */\n\ttitle?: string\n\t/** Payment methods to display */\n\tpaymentMethods?: PaymentMethod[]\n\t/** Called when add is clicked */\n\tonAdd?: () => void\n\t/** Called when remove is clicked */\n\tonRemove?: (method: PaymentMethod) => void\n\t/** Called when set default is clicked */\n\tonSetDefault?: (method: PaymentMethod) => void\n\t/** Empty state message */\n\temptyMessage?: string\n\t/** Whether adding is in progress */\n\tisAddingPaymentMethod?: boolean\n}\n\n/**\n * Payment method management card\n *\n * @example\n * ```tsx\n * <PaymentMethodManager\n *   onAdd={() => openStripeModal()}\n *   onRemove={(method) => removePaymentMethod(method.id)}\n * />\n * ```\n */\nexport function PaymentMethodManager({\n\ttheme = defaultTheme,\n\tclassName,\n\ttitle = 'Payment Methods',\n\tpaymentMethods = [],\n\tonAdd,\n\tonRemove,\n\tonSetDefault,\n\temptyMessage = 'No payment methods added',\n\tisAddingPaymentMethod = false,\n}: PaymentMethodManagerProps) {\n\tconst styles = baseStyles(theme)\n\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tconst getBrandIcon = (brand?: string) => {\n\t\tswitch (brand?.toLowerCase()) {\n\t\t\tcase 'visa':\n\t\t\t\treturn '💳'\n\t\t\tcase 'mastercard':\n\t\t\t\treturn '💳'\n\t\t\tcase 'amex':\n\t\t\t\treturn '💳'\n\t\t\tdefault:\n\t\t\t\treturn '💳'\n\t\t}\n\t}\n\n\tconst containerStyle: CSSProperties = {\n\t\tfontFamily: theme.fontFamily,\n\t}\n\n\tconst cardStyle: CSSProperties = {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'space-between',\n\t\tpadding: '1rem',\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t\tmarginBottom: '0.75rem',\n\t}\n\n\treturn (\n\t\t<div style={containerStyle} className={className}>\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\talignItems: 'center',\n\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\tmarginBottom: '1rem',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<h3 style={{ margin: 0, fontSize: theme.fontSizeLg, fontWeight: 600 }}>{title}</h3>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={onAdd}\n\t\t\t\t\tdisabled={isAddingPaymentMethod}\n\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary, {\n\t\t\t\t\t\tpadding: '0.5rem 1rem',\n\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\t{isAddingPaymentMethod ? (\n\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<PlusIcon color={theme.colorPrimaryForeground} /> Add\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t{paymentMethods.length === 0 ? (\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tpadding: '3rem',\n\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<CreditCardIcon color={theme.colorMuted} size={48} />\n\t\t\t\t\t<p style={{ margin: '1rem 0 0' }}>{emptyMessage}</p>\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<div>\n\t\t\t\t\t{paymentMethods.map((method) => (\n\t\t\t\t\t\t<div key={method.id} style={cardStyle}>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\tgap: '0.75rem',\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span style={{ fontSize: '1.5rem' }}>{getBrandIcon(method.brand)}</span>\n\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{method.brand && (\n\t\t\t\t\t\t\t\t\t\t\t<span style={{ textTransform: 'capitalize' }}>{method.brand}</span>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t<span>•••• {method.last4}</span>\n\t\t\t\t\t\t\t\t\t\t{method.isDefault && (\n\t\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\t\t\tpadding: '0.125rem 0.375rem',\n\t\t\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: theme.colorPrimary,\n\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorPrimaryForeground,\n\t\t\t\t\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\tDefault\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t{method.expiryMonth && method.expiryYear && (\n\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\tExpires {method.expiryMonth.toString().padStart(2, '0')}/{method.expiryYear}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div style={{ display: 'flex', gap: '0.5rem' }}>\n\t\t\t\t\t\t\t\t{!method.isDefault && onSetDefault && (\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => onSetDefault(method)}\n\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline, {\n\t\t\t\t\t\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tSet Default\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{onRemove && (\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => onRemove(method)}\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\tborder: `1px solid ${theme.colorDestructive}`,\n\t\t\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorDestructive,\n\t\t\t\t\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tRemove\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n// ============================================\n// UsageOverview\n// ============================================\n\nexport interface UsageItem {\n\tservice: string\n\tused: number\n\tlimit: number\n\tunit: string\n\tcost?: number\n}\n\nexport interface UsageOverviewProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Custom class name */\n\tclassName?: string\n\t/** Title */\n\ttitle?: string\n\t/** Usage items */\n\titems?: UsageItem[]\n\t/** Current period */\n\tperiod?: string\n\t/** Total cost */\n\ttotalCost?: number\n\t/** Currency */\n\tcurrency?: string\n}\n\n/**\n * Usage overview with progress bars\n *\n * @example\n * ```tsx\n * <UsageOverview\n *   items={[\n *     { service: 'API Requests', used: 8500, limit: 10000, unit: 'requests' },\n *     { service: 'Storage', used: 2.5, limit: 5, unit: 'GB' },\n *   ]}\n *   totalCost={29.99}\n * />\n * ```\n */\nexport function UsageOverview({\n\ttheme = defaultTheme,\n\tclassName,\n\ttitle = 'Current Usage',\n\titems = [],\n\tperiod,\n\ttotalCost,\n\tcurrency = 'USD',\n}: UsageOverviewProps) {\n\tconst _styles = baseStyles(theme)\n\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// Local alias closes over the prop `currency` so call sites read\n\t// naturally. The actual formatting lives in the SDK SSOT helper.\n\tconst format = (amount: number) => formatCurrency(amount, { currency })\n\n\tconst containerStyle: CSSProperties = {\n\t\tfontFamily: theme.fontFamily,\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t\toverflow: 'hidden',\n\t}\n\n\treturn (\n\t\t<div style={containerStyle} className={className}>\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\talignItems: 'center',\n\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\tpadding: '1rem',\n\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\tborderBottom: `1px solid ${theme.colorBorder}`,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div>\n\t\t\t\t\t<h3 style={{ margin: 0, fontSize: theme.fontSizeLg, fontWeight: 600 }}>{title}</h3>\n\t\t\t\t\t{period && (\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{period}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t{totalCost !== undefined && (\n\t\t\t\t\t<div style={{ textAlign: 'right' }}>\n\t\t\t\t\t\t<div style={{ fontSize: theme.fontSizeXl, fontWeight: 600 }}>{format(totalCost)}</div>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tCurrent bill\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t<div style={{ padding: '1rem' }}>\n\t\t\t\t{items.length === 0 ? (\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\tpadding: '2rem',\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tNo usage data available\n\t\t\t\t\t</div>\n\t\t\t\t) : (\n\t\t\t\t\t<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>\n\t\t\t\t\t\t{items.map((item, i) => {\n\t\t\t\t\t\t\tconst percentage = Math.min((item.used / item.limit) * 100, 100)\n\t\t\t\t\t\t\tconst isNearLimit = percentage >= 80\n\t\t\t\t\t\t\tconst isOverLimit = percentage >= 100\n\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<div key={i}>\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<span style={{ fontWeight: 500, fontSize: theme.fontSizeSm }}>\n\t\t\t\t\t\t\t\t\t\t\t{item.service}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{item.used.toLocaleString()} / {item.limit.toLocaleString()} {item.unit}\n\t\t\t\t\t\t\t\t\t\t\t{item.cost !== undefined && ` • ${format(item.cost)}`}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\theight: '8px',\n\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\t\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\t\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\theight: '100%',\n\t\t\t\t\t\t\t\t\t\t\t\twidth: `${percentage}%`,\n\t\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: isOverLimit\n\t\t\t\t\t\t\t\t\t\t\t\t\t? theme.colorDestructive\n\t\t\t\t\t\t\t\t\t\t\t\t\t: isNearLimit\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? theme.colorWarning\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: theme.colorPrimary,\n\t\t\t\t\t\t\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\t\t\t\t\t\t\ttransition: 'width 0.3s ease',\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t})}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n// ============================================\n// Icons\n// ============================================\n\nfunction InvoiceIcon({ color, size = 24 }: { color: string; size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\" />\n\t\t\t<polyline points=\"14 2 14 8 20 8\" />\n\t\t\t<line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\" />\n\t\t\t<line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\" />\n\t\t\t<polyline points=\"10 9 9 9 8 9\" />\n\t\t</svg>\n\t)\n}\n\nfunction DownloadIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"14\"\n\t\t\theight=\"14\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n\t\t\t<polyline points=\"7 10 12 15 17 10\" />\n\t\t\t<line x1=\"12\" y1=\"15\" x2=\"12\" y2=\"3\" />\n\t\t</svg>\n\t)\n}\n\nfunction CreditCardIcon({ color, size = 24 }: { color: string; size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<rect x=\"1\" y=\"4\" width=\"22\" height=\"16\" rx=\"2\" ry=\"2\" />\n\t\t\t<line x1=\"1\" y1=\"10\" x2=\"23\" y2=\"10\" />\n\t\t</svg>\n\t)\n}\n\nfunction PlusIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tstyle={{ marginRight: '0.25rem' }}\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n\t\t\t<line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n\t\t</svg>\n\t)\n}\n","/**\n * Formatting Utilities\n *\n * Shared formatting functions for consistent display across the project.\n */\n\n// ==========================================\n// Number Formatting\n// ==========================================\n\n/**\n * Calculate percentage with consistent rounding.\n * SSOT for all success rate, completion rate calculations.\n *\n * @param count - The numerator (e.g., successful count)\n * @param total - The denominator (e.g., total count)\n * @param decimals - Number of decimal places (default: 2)\n * @returns Percentage value (0-100)\n *\n * @example\n * ```ts\n * calculatePercentage(75, 100) // 75\n * calculatePercentage(1, 3)    // 33.33\n * calculatePercentage(0, 0)    // 100 (safe division)\n * ```\n */\nexport function calculatePercentage(count: number, total: number, decimals = 2): number {\n\tif (total === 0) return 100 // Default to 100% when no data\n\tconst multiplier = 10 ** (decimals + 2)\n\treturn Math.round((count / total) * multiplier) / 10 ** decimals\n}\n\n// ==========================================\n// Currency Formatting\n// ==========================================\n\n/**\n * Format microdollars to currency string\n * @param microdollars Amount in microdollars (1 dollar = 1,000,000 microdollars)\n * @param options Intl.NumberFormat options\n */\nexport function formatMicrodollars(\n\tmicrodollars: number,\n\toptions?: Intl.NumberFormatOptions,\n): string {\n\treturn new Intl.NumberFormat('en-US', {\n\t\tstyle: 'currency',\n\t\tcurrency: 'USD',\n\t\t...options,\n\t}).format(microdollars / 1_000_000)\n}\n\n/**\n * Format cents to currency string\n * @param cents Amount in cents (100 cents = 1 dollar)\n *\n * @example\n * ```ts\n * formatCents(1999)  // \"$19.99\"\n * formatCents(100)   // \"$1.00\"\n * ```\n */\nexport function formatCents(cents: number): string {\n\treturn new Intl.NumberFormat('en-US', {\n\t\tstyle: 'currency',\n\t\tcurrency: 'USD',\n\t}).format(cents / 100)\n}\n\n/**\n * Format dollars to currency string with optional compact notation\n * @param amount Amount in dollars\n * @param compact Use compact notation for large amounts (default: false)\n *\n * @example\n * ```ts\n * formatCurrency(1999.99)              // \"$1,999.99\"\n * formatCurrency(1999.99, true)        // \"$2.0K\"\n * formatCurrency(1999.99, { currency: 'EUR' }) // \"€1,999.99\"\n * formatCurrency(1999.99, { compact: true })   // \"$2.0K\"\n * ```\n *\n * Second argument accepts either a bare `boolean` (back-compat for\n * the historical `compact` flag) or an options object with\n * `{ currency, compact }`. The options form is required for any UI\n * surface that displays multi-currency amounts (billing, invoices,\n * usage statements) — previously two local copies of this function\n * lived in `billing-management.tsx` to work around the missing\n * currency parameter.\n */\nexport function formatCurrency(\n\tamount: number,\n\toptsOrCompact: boolean | { compact?: boolean; currency?: string; decimals?: number } = false,\n): string {\n\tconst opts = typeof optsOrCompact === 'boolean' ? { compact: optsOrCompact } : optsOrCompact\n\tconst currency = (opts.currency ?? 'USD').toUpperCase()\n\tconst decimals = opts.decimals ?? 2\n\tif (opts.compact && Math.abs(amount) >= 1000) {\n\t\treturn new Intl.NumberFormat('en-US', {\n\t\t\tstyle: 'currency',\n\t\t\tcurrency,\n\t\t\tnotation: 'compact',\n\t\t\tminimumFractionDigits: 1,\n\t\t\tmaximumFractionDigits: 1,\n\t\t}).format(amount)\n\t}\n\treturn new Intl.NumberFormat('en-US', {\n\t\tstyle: 'currency',\n\t\tcurrency,\n\t\tminimumFractionDigits: decimals,\n\t\tmaximumFractionDigits: decimals,\n\t}).format(amount)\n}\n\n/**\n * Format percentage with sign for trend display\n * @param value Percentage value (not multiplied by 100)\n *\n * @example\n * ```ts\n * formatPercent(12.5)   // \"+12.5%\"\n * formatPercent(-5.2)   // \"-5.2%\"\n * formatPercent(0)      // \"+0.0%\"\n * ```\n */\nexport function formatPercent(value: number): string {\n\treturn `${value >= 0 ? '+' : ''}${value.toFixed(1)}%`\n}\n\n/**\n * Format number with abbreviated suffix (K, M, B) or compact notation\n * @param num Number to format\n * @param compact Use Intl compact notation (default: false, uses K/M/B suffix)\n *\n * @example\n * ```ts\n * formatNumber(1234)           // \"1,234\"\n * formatNumber(1234567)        // \"1.2M\"\n * formatNumber(1234, true)     // \"1.2K\" (Intl compact)\n * ```\n */\nexport function formatNumber(num: number, compact = false): string {\n\tif (compact && num >= 1000) {\n\t\treturn new Intl.NumberFormat('en-US', {\n\t\t\tnotation: 'compact',\n\t\t\tmaximumFractionDigits: 1,\n\t\t}).format(num)\n\t}\n\tif (num >= 1_000_000_000) return `${(num / 1_000_000_000).toFixed(1)}B`\n\tif (num >= 1_000_000) return `${(num / 1_000_000).toFixed(1)}M`\n\tif (num >= 1_000) return `${(num / 1_000).toFixed(1)}K`\n\treturn num.toLocaleString()\n}\n\n/**\n * Format duration in milliseconds to human-readable string.\n * SSOT for latency display in traces, performance, and monitoring.\n *\n * @param ms Duration in milliseconds\n * @returns Formatted string (e.g., \"<1ms\", \"42ms\", \"1.23s\")\n *\n * @example\n * ```ts\n * formatDuration(0.5)    // \"<1ms\"\n * formatDuration(42)     // \"42ms\"\n * formatDuration(1500)   // \"1.50s\"\n * ```\n */\nexport function formatDuration(ms: number): string {\n\tif (ms < 1) return '<1ms'\n\tif (ms < 1000) return `${Math.round(ms)}ms`\n\treturn `${(ms / 1000).toFixed(2)}s`\n}\n\n/**\n * Format bytes to human-readable string\n * @param bytes Number of bytes\n * @param decimals Number of decimal places (default: 1)\n */\nexport function formatBytes(bytes: number | null | undefined, decimals = 1): string {\n\tif (bytes == null || bytes === 0 || Number.isNaN(bytes)) return '0 B'\n\tconst k = 1024\n\tconst sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']\n\tconst i = Math.floor(Math.log(bytes) / Math.log(k))\n\treturn `${Number.parseFloat((bytes / k ** i).toFixed(decimals))} ${sizes[i]}`\n}\n\n// ==========================================\n// Status Badge Variants (Declarative)\n// ==========================================\n\n/** Badge variant type for consistency */\ntype BadgeVariant = 'default' | 'secondary' | 'success' | 'warning' | 'error' | 'outline'\n\n/**\n * Billing status to badge variant mapping.\n * Declarative configuration — add new statuses here.\n */\nconst BILLING_STATUS_VARIANTS: ReadonlyMap<string, BadgeVariant> = new Map([\n\t// Active/healthy states\n\t['healthy', 'default'],\n\t['active', 'default'],\n\t// Pending/low states\n\t['low', 'secondary'],\n\t['pending', 'secondary'],\n\t// Success states\n\t['paid', 'success'],\n\t['completed', 'success'],\n\t// Warning states\n\t['grace_period', 'warning'],\n\t['overdue', 'warning'],\n\t// Error states\n\t['critical', 'error'],\n\t['blocked', 'error'],\n\t['suspended', 'error'],\n\t['failed', 'error'],\n])\n\n/**\n * Get billing status badge variant.\n * Pure function — no side effects, deterministic output.\n *\n * @param status Billing account status\n * @returns Badge variant for display\n */\nexport function getBillingStatusVariant(status: string): BadgeVariant {\n\treturn BILLING_STATUS_VARIANTS.get(status) ?? 'outline'\n}\n\n/**\n * Invoice status to badge variant mapping.\n * Declarative configuration — add new statuses here.\n */\nconst INVOICE_STATUS_VARIANTS: ReadonlyMap<string, BadgeVariant> = new Map([\n\t['draft', 'secondary'],\n\t['pending', 'default'],\n\t['paid', 'success'],\n\t['overdue', 'warning'],\n\t['failed', 'error'],\n\t['cancelled', 'error'],\n])\n\n/**\n * Get invoice status badge variant.\n * Pure function — no side effects, deterministic output.\n *\n * @param status Invoice status\n * @returns Badge variant for display\n */\nexport function getInvoiceStatusVariant(status: string): BadgeVariant {\n\treturn INVOICE_STATUS_VARIANTS.get(status) ?? 'outline'\n}\n\n/**\n * Safely parse a date value, returning null for invalid dates.\n */\nfunction parseDate(date: Date | string): Date | null {\n\tconst d = typeof date === 'string' ? new Date(date) : date\n\t// Check for invalid date (NaN check on timestamp)\n\treturn Number.isNaN(d.getTime()) ? null : d\n}\n\n/**\n * Format date for display\n * @param date Date to format (null returns fallback)\n * @param options Intl.DateTimeFormat options\n * @param fallback Value to return when date is null (default: '-')\n */\nexport function formatDate(\n\tdate: Date | string | null,\n\toptions?: Intl.DateTimeFormatOptions,\n\tfallback = '-',\n): string {\n\tif (!date) return fallback\n\tconst d = parseDate(date)\n\tif (!d) return fallback\n\treturn d.toLocaleDateString('en-US', {\n\t\tmonth: 'short',\n\t\tday: 'numeric',\n\t\tyear: 'numeric',\n\t\t...options,\n\t})\n}\n\n/**\n * Format date with time for display\n * @param date Date to format (null returns fallback)\n * @param options Override options\n * @param fallback Value to return when date is null (default: '-')\n */\nexport function formatDateTime(\n\tdate: Date | string | null,\n\toptions?: Intl.DateTimeFormatOptions,\n\tfallback = '-',\n): string {\n\tif (!date) return fallback\n\tconst d = parseDate(date)\n\tif (!d) return fallback\n\treturn d.toLocaleString('en-US', {\n\t\tmonth: 'short',\n\t\tday: 'numeric',\n\t\thour: '2-digit',\n\t\tminute: '2-digit',\n\t\t...options,\n\t})\n}\n\n/** Relative time formatter using native Intl API */\nconst relativeTimeFormatter = new Intl.RelativeTimeFormat('en', {\n\tnumeric: 'auto',\n})\n\n/** Time divisions for relative time calculation */\nconst TIME_DIVISIONS: { amount: number; unit: Intl.RelativeTimeFormatUnit }[] = [\n\t{ amount: 60, unit: 'second' },\n\t{ amount: 60, unit: 'minute' },\n\t{ amount: 24, unit: 'hour' },\n\t{ amount: 7, unit: 'day' },\n\t{ amount: 4.34524, unit: 'week' },\n\t{ amount: 12, unit: 'month' },\n\t{ amount: Number.POSITIVE_INFINITY, unit: 'year' },\n]\n\n/**\n * Format relative time (e.g., \"2 hours ago\")\n *\n * Uses native Intl.RelativeTimeFormat for proper localization.\n *\n * @param date Date to format (null returns 'Never')\n */\nexport function formatRelativeTime(date: Date | string | null): string {\n\tif (!date) return 'Never'\n\tconst d = parseDate(date)\n\tif (!d) return 'Never'\n\tlet seconds = (d.getTime() - Date.now()) / 1000\n\n\tfor (const { amount, unit } of TIME_DIVISIONS) {\n\t\tif (Math.abs(seconds) < amount) {\n\t\t\treturn relativeTimeFormatter.format(Math.round(seconds), unit)\n\t\t}\n\t\tseconds /= amount\n\t}\n\n\t// Fallback (shouldn't reach here)\n\treturn formatDate(d)\n}\n\n/**\n * Format relative time in compact form (e.g., \"2h ago\", \"3d ago\").\n * SSOT for dense UI contexts: tables, feeds, badges.\n *\n * Uses short suffixes (s/m/h/d/w) instead of Intl.RelativeTimeFormat words.\n * For prose contexts, use {@link formatRelativeTime} instead.\n *\n * @param date Date to format (null returns 'Never')\n *\n * @example\n * ```ts\n * formatRelativeTimeShort(new Date())               // \"Just now\"\n * formatRelativeTimeShort('2024-01-01T00:00:00Z')   // \"3d ago\"\n * formatRelativeTimeShort(null)                      // \"Never\"\n * ```\n */\nexport function formatRelativeTimeShort(date: Date | string | null): string {\n\tif (!date) return 'Never'\n\tconst d = parseDate(date)\n\tif (!d) return 'Never'\n\tconst diffMs = Date.now() - d.getTime()\n\tconst diffSecs = Math.floor(diffMs / 1000)\n\tconst diffMins = Math.floor(diffMs / 60_000)\n\tconst diffHours = Math.floor(diffMs / 3_600_000)\n\tconst diffDays = Math.floor(diffMs / 86_400_000)\n\n\tif (diffSecs < 10) return 'Just now'\n\tif (diffSecs < 60) return `${diffSecs}s ago`\n\tif (diffMins < 60) return `${diffMins}m ago`\n\tif (diffHours < 24) return `${diffHours}h ago`\n\tif (diffDays === 1) return 'Yesterday'\n\tif (diffDays < 7) return `${diffDays}d ago`\n\tif (diffDays < 30) return `${Math.floor(diffDays / 7)}w ago`\n\treturn d.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })\n}\n\n/**\n * Format month and year (e.g., \"January 2024\")\n * SSOT for billing period display, invoice headers.\n * @param date Date to format (null returns fallback)\n * @param fallback Value to return when date is null\n */\nexport function formatMonthYear(date: Date | string | null, fallback = '-'): string {\n\tif (!date) return fallback\n\tconst d = parseDate(date)\n\tif (!d) return fallback\n\treturn d.toLocaleDateString('en-US', { month: 'long', year: 'numeric' })\n}\n\n/**\n * Format time only (e.g., \"2:30 PM\")\n * SSOT for log timestamps, activity feeds.\n * @param date Date to format (null returns fallback)\n * @param fallback Value to return when date is null\n */\nexport function formatTime(date: Date | string | null, fallback = '-'): string {\n\tif (!date) return fallback\n\tconst d = parseDate(date)\n\tif (!d) return fallback\n\treturn d.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' })\n}\n","/**\n * Billing Section Component\n *\n * Current subscription display, plan management, and billing history.\n * Self-contained with CSS-in-JS styles.\n */\n\n'use client'\n\nimport { useEffect, useState } from 'react'\nimport { UI_NOTIFICATION_MS } from '../../constants'\nimport { RequireSdk } from '../hooks'\nimport { useBilling } from '../platform-hooks'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\nexport interface BillingSectionProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Called on successful action */\n\tonSuccess?: (message: string) => void\n\t/** Called on error */\n\tonError?: (error: string) => void\n\t/** Custom class name */\n\tclassName?: string\n\t/** Currency symbol */\n\tcurrencySymbol?: string\n\t/** Show current plan section */\n\tshowCurrentPlan?: boolean\n\t/** Show available plans */\n\tshowPlans?: boolean\n\t/** Allow plan changes */\n\tallowPlanChange?: boolean\n}\n\n/**\n * Complete billing management section\n *\n * @example\n * ```tsx\n * <BillingSection\n *   onSuccess={(msg) => toast.success(msg)}\n *   showHistory={true}\n * />\n * ```\n */\nexport function BillingSection(props: BillingSectionProps) {\n\treturn (\n\t\t<RequireSdk services={['billing']} componentType=\"billing\" theme={props.theme}>\n\t\t\t<BillingSectionInner {...props} />\n\t\t</RequireSdk>\n\t)\n}\n\n/** Inner component that safely uses platform hooks */\nfunction BillingSectionInner({\n\ttheme = defaultTheme,\n\tonSuccess,\n\tonError,\n\tclassName,\n\tcurrencySymbol = '$',\n\tshowCurrentPlan = true,\n\tshowPlans = true,\n\tallowPlanChange = true,\n}: BillingSectionProps) {\n\tconst {\n\t\tsubscription,\n\t\tplans,\n\t\tisLoading,\n\t\terror: billingError,\n\t\tisPremium: _isPremium,\n\t\tisTrialing: _isTrialing,\n\t\tcreateCheckout,\n\t\topenPortal,\n\t\trefresh: _refresh,\n\t} = useBilling()\n\tconst styles = baseStyles(theme)\n\n\tconst [selectedInterval, setSelectedInterval] = useState<'monthly' | 'annual'>('monthly')\n\tconst [processingPlan, setProcessingPlan] = useState<string | null>(null)\n\tconst [error, setError] = useState<string | null>(null)\n\tconst [success, setSuccess] = useState<string | null>(null)\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// Clear messages after timeout\n\tuseEffect(() => {\n\t\tif (success || error) {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tsetSuccess(null)\n\t\t\t\tsetError(null)\n\t\t\t}, UI_NOTIFICATION_MS)\n\t\t\treturn () => clearTimeout(timer)\n\t\t}\n\t}, [success, error])\n\n\t// Format price\n\tconst formatPrice = (cents: number | null | undefined) => {\n\t\tif (!cents) return 'Free'\n\t\treturn `${currencySymbol}${(cents / 100).toFixed(2)}`\n\t}\n\n\t// Handle checkout\n\tconst handleCheckout = async (planSlug: string) => {\n\t\tsetProcessingPlan(planSlug)\n\t\tsetError(null)\n\n\t\ttry {\n\t\t\tconst url = await createCheckout(planSlug, selectedInterval)\n\t\t\twindow.location.href = url\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to start checkout'\n\t\t\tsetError(message)\n\t\t\tonError?.(message)\n\t\t} finally {\n\t\t\tsetProcessingPlan(null)\n\t\t}\n\t}\n\n\t// Handle manage billing\n\tconst handleManageBilling = async () => {\n\t\ttry {\n\t\t\tawait openPortal()\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to open billing portal'\n\t\t\tsetError(message)\n\t\t\tonError?.(message)\n\t\t}\n\t}\n\n\tconst cardStyles: React.CSSProperties = mergeStyles(styles.card, {\n\t\tpadding: '1.25rem',\n\t\tmarginBottom: '1rem',\n\t})\n\n\tif (isLoading) {\n\t\treturn (\n\t\t\t<div style={mergeStyles(styles.flexCenter, { padding: '3rem' })} className={className}>\n\t\t\t\t<span style={mergeStyles(styles.spinner, { width: '2rem', height: '2rem' })} />\n\t\t\t</div>\n\t\t)\n\t}\n\n\treturn (\n\t\t<div className={className}>\n\t\t\t{/* Alerts */}\n\t\t\t{success && (\n\t\t\t\t<div style={mergeStyles(styles.alert, styles.alertSuccess, styles.mb4)}>{success}</div>\n\t\t\t)}\n\t\t\t{(error || billingError) && (\n\t\t\t\t<div style={mergeStyles(styles.alert, styles.alertError, styles.mb4)}>\n\t\t\t\t\t{error || billingError?.message}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Current Subscription */}\n\t\t\t{showCurrentPlan && (\n\t\t\t\t<div style={cardStyles}>\n\t\t\t\t\t<div style={styles.flexBetween}>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<h4\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeLg,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{subscription ? subscription.planSlug : 'Free Plan'}\n\t\t\t\t\t\t\t</h4>\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{subscription ? (\n\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t{subscription.status === 'active' && 'Active subscription'}\n\t\t\t\t\t\t\t\t\t\t{subscription.status === 'trialing' && (\n\t\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t\tTrial ends{' '}\n\t\t\t\t\t\t\t\t\t\t\t\t{subscription.currentPeriodEnd &&\n\t\t\t\t\t\t\t\t\t\t\t\t\tnew Date(subscription.currentPeriodEnd).toLocaleDateString()}\n\t\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{subscription.status === 'past_due' && (\n\t\t\t\t\t\t\t\t\t\t\t<span style={{ color: theme.colorDestructive }}>Payment past due</span>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{subscription.cancelAtPeriodEnd && (\n\t\t\t\t\t\t\t\t\t\t\t<span style={{ color: theme.colorWarning }}>\n\t\t\t\t\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t\t\t\t\t· Cancels{' '}\n\t\t\t\t\t\t\t\t\t\t\t\t{subscription.currentPeriodEnd &&\n\t\t\t\t\t\t\t\t\t\t\t\t\tnew Date(subscription.currentPeriodEnd).toLocaleDateString()}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t'Upgrade to unlock premium features'\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.flexRow, {\n\t\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{subscription && (\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\t\t\tstyles.badge,\n\t\t\t\t\t\t\t\t\t\tsubscription.status === 'active'\n\t\t\t\t\t\t\t\t\t\t\t? styles.badgeSuccess\n\t\t\t\t\t\t\t\t\t\t\t: subscription.status === 'trialing'\n\t\t\t\t\t\t\t\t\t\t\t\t? styles.badgePrimary\n\t\t\t\t\t\t\t\t\t\t\t\t: subscription.status === 'past_due'\n\t\t\t\t\t\t\t\t\t\t\t\t\t? styles.badgeDestructive\n\t\t\t\t\t\t\t\t\t\t\t\t\t: styles.badgeWarning,\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{subscription.status === 'trialing' ? 'Trial' : subscription.status}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{subscription && (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t\t\t\t\tpaddingTop: '1rem',\n\t\t\t\t\t\t\t\tborderTop: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tdisplay: 'grid',\n\t\t\t\t\t\t\t\t\tgridTemplateColumns: 'repeat(3, 1fr)',\n\t\t\t\t\t\t\t\t\tgap: '1rem',\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t<div style={mergeStyles(styles.textXs, styles.textMuted)}>Billing Cycle</div>\n\t\t\t\t\t\t\t\t\t<div style={{ fontWeight: 500, marginTop: '0.25rem' }}>\n\t\t\t\t\t\t\t\t\t\t{subscription.interval === 'monthly'\n\t\t\t\t\t\t\t\t\t\t\t? 'Monthly'\n\t\t\t\t\t\t\t\t\t\t\t: subscription.interval === 'annual'\n\t\t\t\t\t\t\t\t\t\t\t\t? 'Annual'\n\t\t\t\t\t\t\t\t\t\t\t\t: 'Lifetime'}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t<div style={mergeStyles(styles.textXs, styles.textMuted)}>Next Billing</div>\n\t\t\t\t\t\t\t\t\t<div style={{ fontWeight: 500, marginTop: '0.25rem' }}>\n\t\t\t\t\t\t\t\t\t\t{subscription.cancelAtPeriodEnd\n\t\t\t\t\t\t\t\t\t\t\t? 'N/A'\n\t\t\t\t\t\t\t\t\t\t\t: subscription.currentPeriodEnd\n\t\t\t\t\t\t\t\t\t\t\t\t? new Date(subscription.currentPeriodEnd).toLocaleDateString()\n\t\t\t\t\t\t\t\t\t\t\t\t: 'N/A'}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t<div style={mergeStyles(styles.textXs, styles.textMuted)}>Amount</div>\n\t\t\t\t\t\t\t\t\t<div style={{ fontWeight: 500, marginTop: '0.25rem' }}>\n\t\t\t\t\t\t\t\t\t\t{formatPrice(\n\t\t\t\t\t\t\t\t\t\t\tsubscription.interval === 'monthly'\n\t\t\t\t\t\t\t\t\t\t\t\t? plans.find((p) => p.slug === subscription.planSlug)?.monthlyPrice\n\t\t\t\t\t\t\t\t\t\t\t\t: plans.find((p) => p.slug === subscription.planSlug)?.annualPrice,\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{subscription.interval !== 'lifetime' &&\n\t\t\t\t\t\t\t\t\t\t\t`/${subscription.interval === 'monthly' ? 'mo' : 'yr'}`}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={handleManageBilling}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline, {\n\t\t\t\t\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<CreditCardIcon size={16} />\n\t\t\t\t\t\t\t\tManage Billing\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Available Plans */}\n\t\t\t{showPlans && allowPlanChange && plans.length > 0 && (\n\t\t\t\t<div style={{ marginBottom: '1.5rem' }}>\n\t\t\t\t\t<div style={styles.flexBetween}>\n\t\t\t\t\t\t<h4 style={{ margin: '0 0 1rem', fontWeight: 500 }}>\n\t\t\t\t\t\t\t{subscription ? 'Change Plan' : 'Choose a Plan'}\n\t\t\t\t\t\t</h4>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.tabs, {\n\t\t\t\t\t\t\t\tmarginBottom: 0,\n\t\t\t\t\t\t\t\tpadding: '0.125rem',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={() => setSelectedInterval('monthly')}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\t\tstyles.tab,\n\t\t\t\t\t\t\t\t\t{ padding: '0.375rem 0.75rem' },\n\t\t\t\t\t\t\t\t\tselectedInterval === 'monthly' ? styles.tabActive : {},\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tMonthly\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={() => setSelectedInterval('annual')}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\t\tstyles.tab,\n\t\t\t\t\t\t\t\t\t{ padding: '0.375rem 0.75rem' },\n\t\t\t\t\t\t\t\t\tselectedInterval === 'annual' ? styles.tabActive : {},\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tAnnual\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tmarginLeft: '0.25rem',\n\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\tcolor: theme.colorSuccess,\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tSave 20%\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tdisplay: 'grid',\n\t\t\t\t\t\t\tgridTemplateColumns: `repeat(${Math.min(plans.length, 3)}, 1fr)`,\n\t\t\t\t\t\t\tgap: '1rem',\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{plans.map((plan) => {\n\t\t\t\t\t\t\tconst isCurrentPlan = subscription?.planSlug === plan.slug\n\t\t\t\t\t\t\tconst price = selectedInterval === 'monthly' ? plan.monthlyPrice : plan.annualPrice\n\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tkey={plan.id}\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(cardStyles, {\n\t\t\t\t\t\t\t\t\t\tmarginBottom: 0,\n\t\t\t\t\t\t\t\t\t\tborder: isCurrentPlan\n\t\t\t\t\t\t\t\t\t\t\t? `2px solid ${theme.colorPrimary}`\n\t\t\t\t\t\t\t\t\t\t\t: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{isCurrentPlan && (\n\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\tmarginBottom: '0.75rem',\n\t\t\t\t\t\t\t\t\t\t\t\tpaddingBottom: '0.75rem',\n\t\t\t\t\t\t\t\t\t\t\t\tborderBottom: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<span style={mergeStyles(styles.badge, styles.badgePrimary)}>\n\t\t\t\t\t\t\t\t\t\t\t\tCurrent Plan\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t<h5\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeLg,\n\t\t\t\t\t\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{plan.name}\n\t\t\t\t\t\t\t\t\t</h5>\n\n\t\t\t\t\t\t\t\t\t<div style={{ marginTop: '0.5rem' }}>\n\t\t\t\t\t\t\t\t\t\t<span style={{ fontSize: '2rem', fontWeight: 700 }}>{formatPrice(price)}</span>\n\t\t\t\t\t\t\t\t\t\t{price && (\n\t\t\t\t\t\t\t\t\t\t\t<span style={mergeStyles(styles.textSm, styles.textMuted)}>\n\t\t\t\t\t\t\t\t\t\t\t\t/{selectedInterval === 'monthly' ? 'mo' : 'yr'}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t\t{plan.description && (\n\t\t\t\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\t\t\t\t\tmargin: '0.5rem 0',\n\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{plan.description}\n\t\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t{plan.features && plan.features.length > 0 && (\n\t\t\t\t\t\t\t\t\t\t<ul\n\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\tmargin: '1rem 0',\n\t\t\t\t\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\t\t\t\t\tlistStyle: 'none',\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{plan.features.map((feature: string, i: number) => (\n\t\t\t\t\t\t\t\t\t\t\t\t<li\n\t\t\t\t\t\t\t\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.flexRow, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\talignItems: 'flex-start',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<CheckIcon color={theme.colorSuccess} />\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span>{feature}</span>\n\t\t\t\t\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t{!isCurrentPlan && price && (\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleCheckout(plan.slug)}\n\t\t\t\t\t\t\t\t\t\t\tdisabled={processingPlan === plan.slug}\n\t\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\t\t\t\t\t\t\tstyles.buttonPrimary,\n\t\t\t\t\t\t\t\t\t\t\t\tstyles.buttonFullWidth,\n\t\t\t\t\t\t\t\t\t\t\t\tprocessingPlan === plan.slug ? styles.buttonDisabled : {},\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{processingPlan === plan.slug ? (\n\t\t\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t\t\t\t\t\t\t\t\tProcessing...\n\t\t\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t\t\t) : subscription ? (\n\t\t\t\t\t\t\t\t\t\t\t\t'Switch Plan'\n\t\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t\t'Subscribe'\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t{isCurrentPlan && (\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={handleManageBilling}\n\t\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\t\t\t\t\t\t\tstyles.buttonOutline,\n\t\t\t\t\t\t\t\t\t\t\t\tstyles.buttonFullWidth,\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\tManage\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t})}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Empty state for no subscription and no plans */}\n\t\t\t{!subscription && plans.length === 0 && (\n\t\t\t\t<div style={mergeStyles(styles.textCenter, { padding: '2rem' })}>\n\t\t\t\t\t<p style={styles.textMuted}>No subscription plans available</p>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n// Icons\nfunction CreditCardIcon({ size = 24 }: { size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t>\n\t\t\t<rect x=\"1\" y=\"4\" width=\"22\" height=\"16\" rx=\"2\" ry=\"2\" />\n\t\t\t<line x1=\"1\" y1=\"10\" x2=\"23\" y2=\"10\" />\n\t\t</svg>\n\t)\n}\n\nfunction CheckIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tstyle={{ flexShrink: 0, marginTop: '2px' }}\n\t\t>\n\t\t\t<polyline points=\"20 6 9 17 4 12\" />\n\t\t</svg>\n\t)\n}\n","/**\n * AI Chat Interface Component\n *\n * Full-featured chat UI that integrates with useChat hook.\n * Supports markdown rendering, code blocks, and streaming.\n */\n\n'use client'\n\nimport {\n\ttype CSSProperties,\n\ttype FormEvent,\n\ttype KeyboardEvent,\n\ttype ReactNode,\n\tuseEffect,\n\tuseRef,\n\tuseState,\n} from 'react'\nimport { type UseChatOptions, useChat } from '../ai-hooks'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\n// ============================================\n// Types\n// ============================================\n\nexport interface ChatInterfaceProps extends UseChatOptions {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Custom class name */\n\tclassName?: string\n\t/** Title shown in header */\n\ttitle?: string\n\t/** Placeholder text for input */\n\tplaceholder?: string\n\t/** Whether to show the header */\n\tshowHeader?: boolean\n\t/** Whether to show timestamps */\n\tshowTimestamps?: boolean\n\t/** Whether to auto-scroll to bottom */\n\tautoScroll?: boolean\n\t/** Maximum height (CSS value) */\n\tmaxHeight?: string\n\t/** Render custom message bubble */\n\trenderMessage?: (message: ChatMessage, index: number) => ReactNode\n\t/** Render custom empty state */\n\trenderEmpty?: () => ReactNode\n\t/** Render custom loading indicator */\n\trenderLoading?: () => ReactNode\n\t/** Custom send button content */\n\tsendButtonContent?: ReactNode\n\t/** Called when user sends a message */\n\tonSend?: (content: string) => void\n\t/** Show suggested prompts when empty */\n\tsuggestedPrompts?: string[]\n\t/** Enable voice input (future) */\n\tenableVoice?: boolean\n\t/** Show model selector */\n\tshowModelSelector?: boolean\n\t/** Available models */\n\tmodels?: { id: string; name: string }[]\n\t/** Selected model */\n\tselectedModel?: string\n\t/** Model change callback */\n\tonModelChange?: (modelId: string) => void\n}\n\n// ChatMessage re-exported from ai.ts (SSOT)\nexport type { ChatMessage } from '../../ai'\n\nimport type { ChatMessage } from '../../ai'\n\n// ============================================\n// ChatInterface Component\n// ============================================\n\n/**\n * Full-featured AI chat interface\n *\n * @example\n * ```tsx\n * // Basic usage\n * <ChatInterface\n *   systemMessage=\"You are a helpful assistant.\"\n *   placeholder=\"Ask me anything...\"\n * />\n *\n * // With custom styling\n * <ChatInterface\n *   theme={darkTheme}\n *   title=\"AI Assistant\"\n *   suggestedPrompts={[\n *     \"What can you help me with?\",\n *     \"Tell me a joke\",\n *     \"Explain quantum computing\"\n *   ]}\n * />\n * ```\n */\nexport function ChatInterface({\n\ttheme = defaultTheme,\n\tclassName,\n\ttitle = 'Chat',\n\tplaceholder = 'Type a message...',\n\tshowHeader = true,\n\tshowTimestamps = false,\n\tautoScroll = true,\n\tmaxHeight = '600px',\n\trenderMessage,\n\trenderEmpty,\n\trenderLoading,\n\tsendButtonContent,\n\tonSend,\n\tsuggestedPrompts = [],\n\tshowModelSelector = false,\n\tmodels = [],\n\tselectedModel,\n\tonModelChange,\n\t...chatOptions\n}: ChatInterfaceProps) {\n\tconst { messages, send, isLoading, error, clear, retry } = useChat(chatOptions)\n\tconst [input, setInput] = useState('')\n\tconst messagesEndRef = useRef<HTMLDivElement>(null)\n\tconst inputRef = useRef<HTMLTextAreaElement>(null)\n\tconst styles = baseStyles(theme)\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// Auto-scroll to bottom\n\tuseEffect(() => {\n\t\tif (autoScroll && messagesEndRef.current) {\n\t\t\tmessagesEndRef.current.scrollIntoView({ behavior: 'smooth' })\n\t\t}\n\t}, [autoScroll])\n\n\t// Auto-resize textarea\n\tuseEffect(() => {\n\t\tif (inputRef.current) {\n\t\t\tinputRef.current.style.height = 'auto'\n\t\t\tinputRef.current.style.height = `${Math.min(inputRef.current.scrollHeight, 150)}px`\n\t\t}\n\t}, [])\n\n\tconst handleSubmit = async (e?: FormEvent) => {\n\t\te?.preventDefault()\n\t\tif (!input.trim() || isLoading) return\n\n\t\tconst content = input.trim()\n\t\tsetInput('')\n\t\tonSend?.(content)\n\t\tawait send(content)\n\t}\n\n\tconst handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {\n\t\tif (e.key === 'Enter' && !e.shiftKey) {\n\t\t\te.preventDefault()\n\t\t\thandleSubmit()\n\t\t}\n\t}\n\n\tconst handleSuggestedPrompt = (prompt: string) => {\n\t\tsetInput(prompt)\n\t\tinputRef.current?.focus()\n\t}\n\n\t// Styles\n\tconst containerStyle: CSSProperties = {\n\t\tdisplay: 'flex',\n\t\tflexDirection: 'column',\n\t\theight: '100%',\n\t\tmaxHeight,\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t\tbackgroundColor: theme.colorBackground,\n\t\tfontFamily: theme.fontFamily,\n\t\toverflow: 'hidden',\n\t}\n\n\tconst headerStyle: CSSProperties = {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'space-between',\n\t\tpadding: '0.75rem 1rem',\n\t\tborderBottom: `1px solid ${theme.colorBorder}`,\n\t\tbackgroundColor: theme.colorMuted,\n\t}\n\n\tconst messagesContainerStyle: CSSProperties = {\n\t\tflex: 1,\n\t\toverflowY: 'auto',\n\t\tpadding: '1rem',\n\t\tdisplay: 'flex',\n\t\tflexDirection: 'column',\n\t\tgap: '1rem',\n\t}\n\n\tconst inputContainerStyle: CSSProperties = {\n\t\tpadding: '1rem',\n\t\tborderTop: `1px solid ${theme.colorBorder}`,\n\t\tbackgroundColor: theme.colorBackground,\n\t}\n\n\tconst textareaStyle: CSSProperties = {\n\t\twidth: '100%',\n\t\tpadding: '0.75rem 1rem',\n\t\tpaddingRight: '3rem',\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t\tbackgroundColor: theme.colorBackground,\n\t\tcolor: theme.colorForeground,\n\t\tfontSize: theme.fontSizeSm,\n\t\tfontFamily: theme.fontFamily,\n\t\tresize: 'none',\n\t\toutline: 'none',\n\t\tminHeight: '44px',\n\t\tmaxHeight: '150px',\n\t}\n\n\tconst sendButtonStyle: CSSProperties = {\n\t\tposition: 'absolute',\n\t\tright: '0.5rem',\n\t\tbottom: '0.5rem',\n\t\tpadding: '0.5rem',\n\t\tborder: 'none',\n\t\tborderRadius: theme.borderRadiusSm,\n\t\tbackgroundColor: isLoading || !input.trim() ? theme.colorMuted : theme.colorPrimary,\n\t\tcolor: isLoading || !input.trim() ? theme.colorMutedForeground : theme.colorPrimaryForeground,\n\t\tcursor: isLoading || !input.trim() ? 'not-allowed' : 'pointer',\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'center',\n\t\ttransition: 'all 0.15s ease',\n\t}\n\n\treturn (\n\t\t<div style={containerStyle} className={className}>\n\t\t\t{/* Header */}\n\t\t\t{showHeader && (\n\t\t\t\t<div style={headerStyle}>\n\t\t\t\t\t<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>\n\t\t\t\t\t\t<ChatIcon color={theme.colorPrimary} />\n\t\t\t\t\t\t<span style={{ fontWeight: 600, fontSize: theme.fontSizeSm }}>{title}</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>\n\t\t\t\t\t\t{showModelSelector && models.length > 0 && (\n\t\t\t\t\t\t\t<select\n\t\t\t\t\t\t\t\tvalue={selectedModel}\n\t\t\t\t\t\t\t\tonChange={(e) => onModelChange?.(e.target.value)}\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t\tbackgroundColor: theme.colorBackground,\n\t\t\t\t\t\t\t\t\tcolor: theme.colorForeground,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{models.map((m) => (\n\t\t\t\t\t\t\t\t\t<option key={m.id} value={m.id}>\n\t\t\t\t\t\t\t\t\t\t{m.name}\n\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{messages.length > 0 && (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={clear}\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tClear\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Messages */}\n\t\t\t<div style={messagesContainerStyle}>\n\t\t\t\t{messages.length === 0 ? (\n\t\t\t\t\t(renderEmpty?.() ?? (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tflex: 1,\n\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\tflexDirection: 'column',\n\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\tjustifyContent: 'center',\n\t\t\t\t\t\t\t\tgap: '1rem',\n\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\t\t\tpadding: '2rem',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<ChatIcon color={theme.colorMuted} size={48} />\n\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t<p style={{ margin: 0, fontWeight: 500 }}>Start a conversation</p>\n\t\t\t\t\t\t\t\t<p style={{ margin: '0.25rem 0 0', fontSize: theme.fontSizeXs }}>\n\t\t\t\t\t\t\t\t\tSend a message to begin chatting\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{suggestedPrompts.length > 0 && (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\tflexWrap: 'wrap',\n\t\t\t\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\t\t\t\tmarginTop: '0.5rem',\n\t\t\t\t\t\t\t\t\t\tjustifyContent: 'center',\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{suggestedPrompts.map((prompt, i) => (\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleSuggestedPrompt(prompt)}\n\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\tpadding: '0.5rem 0.75rem',\n\t\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: theme.colorBackground,\n\t\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorForeground,\n\t\t\t\t\t\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t\t\t\t\t\t\ttransition: 'all 0.15s ease',\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{prompt}\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))\n\t\t\t\t) : (\n\t\t\t\t\t<>\n\t\t\t\t\t\t{messages\n\t\t\t\t\t\t\t.filter((m) => m.role !== 'system')\n\t\t\t\t\t\t\t.map((message, index) =>\n\t\t\t\t\t\t\t\trenderMessage ? (\n\t\t\t\t\t\t\t\t\trenderMessage({ ...message, timestamp: new Date() }, index)\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<MessageBubble\n\t\t\t\t\t\t\t\t\t\tkey={index}\n\t\t\t\t\t\t\t\t\t\tmessage={message}\n\t\t\t\t\t\t\t\t\t\ttheme={theme}\n\t\t\t\t\t\t\t\t\t\tshowTimestamp={showTimestamps}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t{isLoading &&\n\t\t\t\t\t\t\t(renderLoading?.() ?? (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t\t\t\t\t<span>Thinking...</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t\t<div ref={messagesEndRef} />\n\t\t\t</div>\n\n\t\t\t{/* Error */}\n\t\t\t{error && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={mergeStyles(styles.alert, styles.alertError, {\n\t\t\t\t\t\tmargin: '0 1rem',\n\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\t<span>{error.message}</span>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={retry}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tmarginLeft: 'auto',\n\t\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\tborder: `1px solid ${theme.colorDestructive}`,\n\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\tcolor: theme.colorDestructive,\n\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tRetry\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Input */}\n\t\t\t<div style={inputContainerStyle}>\n\t\t\t\t<form onSubmit={handleSubmit} style={{ position: 'relative' }}>\n\t\t\t\t\t<textarea\n\t\t\t\t\t\tref={inputRef}\n\t\t\t\t\t\tvalue={input}\n\t\t\t\t\t\tonChange={(e) => setInput(e.target.value)}\n\t\t\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\trows={1}\n\t\t\t\t\t\tstyle={textareaStyle}\n\t\t\t\t\t/>\n\t\t\t\t\t<button type=\"submit\" disabled={isLoading || !input.trim()} style={sendButtonStyle}>\n\t\t\t\t\t\t{sendButtonContent ?? <SendIcon color=\"currentColor\" />}\n\t\t\t\t\t</button>\n\t\t\t\t</form>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n// ============================================\n// MessageBubble Component\n// ============================================\n\ninterface MessageBubbleProps {\n\tmessage: { role: string; content: string }\n\ttheme: ThemeVariables\n\tshowTimestamp?: boolean\n}\n\nfunction MessageBubble({ message, theme, showTimestamp }: MessageBubbleProps) {\n\tconst isUser = message.role === 'user'\n\n\tconst bubbleStyle: CSSProperties = {\n\t\tmaxWidth: '80%',\n\t\tpadding: '0.75rem 1rem',\n\t\tborderRadius: theme.borderRadius,\n\t\tbackgroundColor: isUser ? theme.colorPrimary : theme.colorMuted,\n\t\tcolor: isUser ? theme.colorPrimaryForeground : theme.colorForeground,\n\t\talignSelf: isUser ? 'flex-end' : 'flex-start',\n\t\tfontSize: theme.fontSizeSm,\n\t\tlineHeight: 1.5,\n\t\twordBreak: 'break-word',\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tstyle={{\n\t\t\t\tdisplay: 'flex',\n\t\t\t\tflexDirection: 'column',\n\t\t\t\talignItems: isUser ? 'flex-end' : 'flex-start',\n\t\t\t\tgap: '0.25rem',\n\t\t\t}}\n\t\t>\n\t\t\t<div style={bubbleStyle}>\n\t\t\t\t<MessageContent content={message.content} theme={theme} isUser={isUser} />\n\t\t\t</div>\n\t\t\t{showTimestamp && (\n\t\t\t\t<span\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tfontSize: '0.625rem',\n\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{new Date().toLocaleTimeString()}\n\t\t\t\t</span>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n// ============================================\n// MessageContent (with code block support)\n// ============================================\n\nfunction MessageContent({\n\tcontent,\n\ttheme,\n\tisUser,\n}: {\n\tcontent: string\n\ttheme: ThemeVariables\n\tisUser: boolean\n}) {\n\t// Simple markdown-like parsing for code blocks\n\tconst parts = content.split(/(```[\\s\\S]*?```)/g)\n\n\treturn (\n\t\t<>\n\t\t\t{parts.map((part, i) => {\n\t\t\t\tif (part.startsWith('```') && part.endsWith('```')) {\n\t\t\t\t\tconst lines = part.slice(3, -3).split('\\n')\n\t\t\t\t\tconst language = lines[0] || 'text'\n\t\t\t\t\tconst code = lines.slice(1).join('\\n')\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<pre\n\t\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tmargin: '0.5rem 0',\n\t\t\t\t\t\t\t\tpadding: '0.75rem',\n\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\tbackgroundColor: isUser ? 'rgba(0,0,0,0.2)' : 'rgba(0,0,0,0.05)',\n\t\t\t\t\t\t\t\toverflow: 'auto',\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\tfontFamily: 'monospace',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<code>{code || language}</code>\n\t\t\t\t\t\t</pre>\n\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t\t// Handle inline code\n\t\t\t\tconst inlineParts = part.split(/(`[^`]+`)/g)\n\t\t\t\treturn (\n\t\t\t\t\t<span key={i}>\n\t\t\t\t\t\t{inlineParts.map((inline, j) => {\n\t\t\t\t\t\t\tif (inline.startsWith('`') && inline.endsWith('`')) {\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<code\n\t\t\t\t\t\t\t\t\t\tkey={j}\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tpadding: '0.125rem 0.25rem',\n\t\t\t\t\t\t\t\t\t\t\tborderRadius: '3px',\n\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: isUser ? 'rgba(0,0,0,0.2)' : 'rgba(0,0,0,0.05)',\n\t\t\t\t\t\t\t\t\t\t\tfontFamily: 'monospace',\n\t\t\t\t\t\t\t\t\t\t\tfontSize: '0.9em',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{inline.slice(1, -1)}\n\t\t\t\t\t\t\t\t\t</code>\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn inline\n\t\t\t\t\t\t})}\n\t\t\t\t\t</span>\n\t\t\t\t)\n\t\t\t})}\n\t\t</>\n\t)\n}\n\n// ============================================\n// ChatBubble (standalone export)\n// ============================================\n\nexport interface ChatBubbleProps {\n\t/** Message content */\n\tcontent: string\n\t/** Message role */\n\trole: 'user' | 'assistant'\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Show avatar */\n\tshowAvatar?: boolean\n\t/** Avatar URL or initials */\n\tavatar?: string\n\t/** Show timestamp */\n\ttimestamp?: Date\n}\n\nexport function ChatBubble({\n\tcontent,\n\trole,\n\ttheme = defaultTheme,\n\tshowAvatar = false,\n\tavatar,\n\ttimestamp,\n}: ChatBubbleProps) {\n\treturn <MessageBubble message={{ role, content }} theme={theme} showTimestamp={!!timestamp} />\n}\n\n// ============================================\n// ChatInput (standalone export)\n// ============================================\n\nexport interface ChatInputProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Placeholder text */\n\tplaceholder?: string\n\t/** Whether input is disabled */\n\tdisabled?: boolean\n\t/** Called when user submits */\n\tonSubmit: (content: string) => void\n\t/** Whether loading */\n\tisLoading?: boolean\n}\n\nexport function ChatInput({\n\ttheme = defaultTheme,\n\tplaceholder = 'Type a message...',\n\tdisabled = false,\n\tonSubmit,\n\tisLoading = false,\n}: ChatInputProps) {\n\tconst [input, setInput] = useState('')\n\tconst inputRef = useRef<HTMLTextAreaElement>(null)\n\n\tconst handleSubmit = (e?: FormEvent) => {\n\t\te?.preventDefault()\n\t\tif (!input.trim() || disabled || isLoading) return\n\t\tonSubmit(input.trim())\n\t\tsetInput('')\n\t}\n\n\tconst handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {\n\t\tif (e.key === 'Enter' && !e.shiftKey) {\n\t\t\te.preventDefault()\n\t\t\thandleSubmit()\n\t\t}\n\t}\n\n\treturn (\n\t\t<form onSubmit={handleSubmit} style={{ position: 'relative' }}>\n\t\t\t<textarea\n\t\t\t\tref={inputRef}\n\t\t\t\tvalue={input}\n\t\t\t\tonChange={(e) => setInput(e.target.value)}\n\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\tplaceholder={placeholder}\n\t\t\t\tdisabled={disabled || isLoading}\n\t\t\t\trows={1}\n\t\t\t\tstyle={{\n\t\t\t\t\twidth: '100%',\n\t\t\t\t\tpadding: '0.75rem 1rem',\n\t\t\t\t\tpaddingRight: '3rem',\n\t\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\tbackgroundColor: theme.colorBackground,\n\t\t\t\t\tcolor: theme.colorForeground,\n\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\tfontFamily: theme.fontFamily,\n\t\t\t\t\tresize: 'none',\n\t\t\t\t\toutline: 'none',\n\t\t\t\t}}\n\t\t\t/>\n\t\t\t<button\n\t\t\t\ttype=\"submit\"\n\t\t\t\tdisabled={disabled || isLoading || !input.trim()}\n\t\t\t\tstyle={{\n\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\tright: '0.5rem',\n\t\t\t\t\tbottom: '0.5rem',\n\t\t\t\t\tpadding: '0.5rem',\n\t\t\t\t\tborder: 'none',\n\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\tbackgroundColor:\n\t\t\t\t\t\tdisabled || isLoading || !input.trim() ? theme.colorMuted : theme.colorPrimary,\n\t\t\t\t\tcolor:\n\t\t\t\t\t\tdisabled || isLoading || !input.trim()\n\t\t\t\t\t\t\t? theme.colorMutedForeground\n\t\t\t\t\t\t\t: theme.colorPrimaryForeground,\n\t\t\t\t\tcursor: disabled || isLoading || !input.trim() ? 'not-allowed' : 'pointer',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{isLoading ? (\n\t\t\t\t\t<span style={{ width: 16, height: 16 }} className=\"sylphx-spinner\" />\n\t\t\t\t) : (\n\t\t\t\t\t<SendIcon color=\"currentColor\" />\n\t\t\t\t)}\n\t\t\t</button>\n\t\t</form>\n\t)\n}\n\n// ============================================\n// Icons\n// ============================================\n\nfunction ChatIcon({ color, size = 20 }: { color: string; size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n\t\t</svg>\n\t)\n}\n\nfunction SendIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\" />\n\t\t\t<polygon points=\"22 2 15 22 11 13 2 9 22 2\" />\n\t\t</svg>\n\t)\n}\n","/**\n * Consent Preferences Component\n *\n * Full consent preference management panel/modal.\n * Can be embedded in settings pages or triggered from footer link.\n */\n\n'use client'\n\nimport { type CSSProperties, useEffect, useState } from 'react'\nimport { UI_FORM_SUCCESS_MS } from '../../constants'\nimport { type ConsentCategory, type ConsentType, useConsent } from '../consent-hooks'\nimport { Modal } from './modal'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\nexport interface ConsentPreferencesProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Display as modal or embedded panel */\n\tmode?: 'modal' | 'embedded'\n\t/** Whether modal is open (only for modal mode) */\n\topen?: boolean\n\t/** Called when modal is closed */\n\tonClose?: () => void\n\t/** Called when preferences are saved */\n\tonSave?: () => void\n\t/** Title */\n\ttitle?: string\n\t/** Description */\n\tdescription?: string\n\t/** Privacy policy URL */\n\tprivacyPolicyUrl?: string\n\t/** Custom class name */\n\tclassName?: string\n\t/** Show category descriptions */\n\tshowDescriptions?: boolean\n\t/** Group by category */\n\tgroupByCategory?: boolean\n}\n\n// Category info\nconst CATEGORY_INFO: Record<ConsentCategory, { name: string; description: string; icon: string }> =\n\t{\n\t\tnecessary: {\n\t\t\tname: 'Necessary',\n\t\t\tdescription: 'Essential for the website to function properly. Cannot be disabled.',\n\t\t\ticon: '🔒',\n\t\t},\n\t\tfunctional: {\n\t\t\tname: 'Functional',\n\t\t\tdescription: 'Enable enhanced functionality and personalization.',\n\t\t\ticon: '⚙️',\n\t\t},\n\t\tpreferences: {\n\t\t\tname: 'Preferences',\n\t\t\tdescription: 'Remember your settings and preferences for a better experience.',\n\t\t\ticon: '🎛️',\n\t\t},\n\t\tanalytics: {\n\t\t\tname: 'Analytics',\n\t\t\tdescription: 'Help us understand how visitors interact with our website.',\n\t\t\ticon: '📊',\n\t\t},\n\t\tmarketing: {\n\t\t\tname: 'Marketing',\n\t\t\tdescription: 'Used to deliver personalized advertisements.',\n\t\t\ticon: '📢',\n\t\t},\n\t}\n\n/**\n * Consent preferences panel\n *\n * @example\n * ```tsx\n * // Embedded in settings page\n * <ConsentPreferences mode=\"embedded\" />\n *\n * // As a modal\n * const [open, setOpen] = useState(false)\n * <button onClick={() => setOpen(true)}>Cookie Settings</button>\n * <ConsentPreferences\n *   mode=\"modal\"\n *   open={open}\n *   onClose={() => setOpen(false)}\n * />\n * ```\n */\nexport function ConsentPreferences({\n\ttheme = defaultTheme,\n\tmode = 'embedded',\n\topen = false,\n\tonClose,\n\tonSave,\n\ttitle = 'Privacy Preferences',\n\tdescription = 'Manage your cookie and privacy preferences. You can change these settings at any time.',\n\tprivacyPolicyUrl,\n\tclassName,\n\tshowDescriptions = true,\n\tgroupByCategory = true,\n}: ConsentPreferencesProps) {\n\tconst {\n\t\ttypes,\n\t\tconsents,\n\t\tsetConsent,\n\t\tsetConsents,\n\t\tacceptAll,\n\t\tdeclineOptional,\n\t\tsaveConsents,\n\t\thasConsented,\n\t} = useConsent()\n\n\tconst [isSaving, setIsSaving] = useState(false)\n\tconst [saveSuccess, setSaveSuccess] = useState(false)\n\tconst styles = baseStyles(theme)\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// Clear success message\n\tuseEffect(() => {\n\t\tif (saveSuccess) {\n\t\t\tconst timer = setTimeout(() => setSaveSuccess(false), UI_FORM_SUCCESS_MS)\n\t\t\treturn () => clearTimeout(timer)\n\t\t}\n\t}, [saveSuccess])\n\n\t// Handle save\n\tconst handleSave = async () => {\n\t\tsetIsSaving(true)\n\t\ttry {\n\t\t\tawait saveConsents()\n\t\t\tsetSaveSuccess(true)\n\t\t\tonSave?.()\n\t\t\tif (mode === 'modal') {\n\t\t\t\tonClose?.()\n\t\t\t}\n\t\t} finally {\n\t\t\tsetIsSaving(false)\n\t\t}\n\t}\n\n\t// Handle accept all\n\tconst handleAcceptAll = async () => {\n\t\tsetIsSaving(true)\n\t\ttry {\n\t\t\tawait acceptAll()\n\t\t\tsetSaveSuccess(true)\n\t\t\tonSave?.()\n\t\t\tif (mode === 'modal') {\n\t\t\t\tonClose?.()\n\t\t\t}\n\t\t} finally {\n\t\t\tsetIsSaving(false)\n\t\t}\n\t}\n\n\t// Handle decline optional\n\tconst handleDeclineOptional = async () => {\n\t\tsetIsSaving(true)\n\t\ttry {\n\t\t\tawait declineOptional()\n\t\t\tsetSaveSuccess(true)\n\t\t\tonSave?.()\n\t\t\tif (mode === 'modal') {\n\t\t\t\tonClose?.()\n\t\t\t}\n\t\t} finally {\n\t\t\tsetIsSaving(false)\n\t\t}\n\t}\n\n\t// Group types by category\n\tconst typesByCategory: Record<string, ConsentType[]> = groupByCategory\n\t\t? types.reduce<Record<string, ConsentType[]>>((acc, type) => {\n\t\t\t\tconst category = type.category || 'functional'\n\t\t\t\tif (!acc[category]) acc[category] = []\n\t\t\t\tacc[category].push(type)\n\t\t\t\treturn acc\n\t\t\t}, {})\n\t\t: { all: types }\n\n\tconst content = (\n\t\t<div style={{ fontFamily: theme.fontFamily }}>\n\t\t\t{/* Header */}\n\t\t\t<div style={{ marginBottom: '1.5rem' }}>\n\t\t\t\t<h2\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\tfontSize: theme.fontSizeXl,\n\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{title}\n\t\t\t\t</h2>\n\t\t\t\t<p style={mergeStyles(styles.textSm, styles.textMuted, { margin: 0 })}>\n\t\t\t\t\t{description}\n\t\t\t\t\t{privacyPolicyUrl && (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\thref={privacyPolicyUrl}\n\t\t\t\t\t\t\t\tstyle={styles.link}\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tLearn more\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t</p>\n\t\t\t</div>\n\n\t\t\t{/* Success message */}\n\t\t\t{saveSuccess && (\n\t\t\t\t<div style={mergeStyles(styles.alert, styles.alertSuccess)}>\n\t\t\t\t\t<CheckIcon color={theme.colorSuccess} /> Preferences saved successfully\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Quick actions */}\n\t\t\t<div\n\t\t\t\tstyle={mergeStyles(styles.flexRow, {\n\t\t\t\t\tgap: '0.75rem',\n\t\t\t\t\tmarginBottom: '1.5rem',\n\t\t\t\t})}\n\t\t\t>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={handleAcceptAll}\n\t\t\t\t\tdisabled={isSaving}\n\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary)}\n\t\t\t\t>\n\t\t\t\t\tAccept All\n\t\t\t\t</button>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={handleDeclineOptional}\n\t\t\t\t\tdisabled={isSaving}\n\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline)}\n\t\t\t\t>\n\t\t\t\t\tNecessary Only\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t{/* Categories */}\n\t\t\t<div style={{ marginBottom: '1.5rem' }}>\n\t\t\t\t{Object.entries(typesByCategory).map(([category, categoryTypes]) => {\n\t\t\t\t\tconst info = CATEGORY_INFO[category as ConsentCategory]\n\t\t\t\t\tconst isNecessary = category === 'necessary'\n\n\t\t\t\t\t// Count enabled in this category\n\t\t\t\t\tconst enabledCount = categoryTypes.filter(\n\t\t\t\t\t\t(t) => consents[t.slug] ?? t.defaultEnabled,\n\t\t\t\t\t).length\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tkey={category}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tmarginBottom: '1rem',\n\t\t\t\t\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{/* Category header */}\n\t\t\t\t\t\t\t{groupByCategory && info && (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t\t\t\t\t\tpadding: '1rem',\n\t\t\t\t\t\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\t\t\t\t\t\tborderBottom: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\t\tgap: '0.75rem',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<span style={{ fontSize: '1.25rem' }}>{info.icon}</span>\n\t\t\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t\t\t<div style={{ fontWeight: 600, fontSize: theme.fontSizeSm }}>{info.name}</div>\n\t\t\t\t\t\t\t\t\t\t\t{showDescriptions && (\n\t\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{info.description}\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\t\tgap: '0.75rem',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{enabledCount}/{categoryTypes.length} enabled\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t{!isNecessary && (\n\t\t\t\t\t\t\t\t\t\t\t<CategoryToggle\n\t\t\t\t\t\t\t\t\t\t\t\tenabled={enabledCount === categoryTypes.length}\n\t\t\t\t\t\t\t\t\t\t\t\tonChange={(enabled) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst updates: Record<string, boolean> = {}\n\t\t\t\t\t\t\t\t\t\t\t\t\tcategoryTypes.forEach((t) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!t.required) updates[t.slug] = enabled\n\t\t\t\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t\t\t\tsetConsents(updates)\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\ttheme={theme}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{/* Individual consent types */}\n\t\t\t\t\t\t\t<div style={{ padding: '0.5rem 0' }}>\n\t\t\t\t\t\t\t\t{categoryTypes.map((type, index) => (\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tkey={type.id}\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t\t\t\t\t\t\tpadding: '0.75rem 1rem',\n\t\t\t\t\t\t\t\t\t\t\tborderBottom:\n\t\t\t\t\t\t\t\t\t\t\t\tindex < categoryTypes.length - 1\n\t\t\t\t\t\t\t\t\t\t\t\t\t? `1px solid ${theme.colorBorder}`\n\t\t\t\t\t\t\t\t\t\t\t\t\t: 'none',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<div style={{ flex: 1, minWidth: 0 }}>\n\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{type.name}\n\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t{type.required && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: '0.625rem',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tpadding: '0.125rem 0.375rem',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttextTransform: 'uppercase',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tRequired\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t{showDescriptions && type.description && (\n\t\t\t\t\t\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{type.description}\n\t\t\t\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t<Toggle\n\t\t\t\t\t\t\t\t\t\t\tchecked={consents[type.slug] ?? type.defaultEnabled}\n\t\t\t\t\t\t\t\t\t\t\tonChange={(checked) => setConsent(type.slug, checked)}\n\t\t\t\t\t\t\t\t\t\t\tdisabled={type.required}\n\t\t\t\t\t\t\t\t\t\t\ttheme={theme}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)\n\t\t\t\t})}\n\t\t\t</div>\n\n\t\t\t{/* Save button */}\n\t\t\t<div\n\t\t\t\tstyle={mergeStyles(styles.flexRow, {\n\t\t\t\t\tgap: '0.75rem',\n\t\t\t\t\tjustifyContent: 'flex-end',\n\t\t\t\t})}\n\t\t\t>\n\t\t\t\t{mode === 'modal' && (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={onClose}\n\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline)}\n\t\t\t\t\t>\n\t\t\t\t\t\tCancel\n\t\t\t\t\t</button>\n\t\t\t\t)}\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={handleSave}\n\t\t\t\t\tdisabled={isSaving}\n\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary)}\n\t\t\t\t>\n\t\t\t\t\t{isSaving ? <span style={styles.spinner} /> : 'Save Preferences'}\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t{/* Last updated */}\n\t\t\t{hasConsented && (\n\t\t\t\t<p\n\t\t\t\t\tstyle={mergeStyles(styles.textXs, styles.textMuted, {\n\t\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\tYou can update your preferences at any time.\n\t\t\t\t</p>\n\t\t\t)}\n\t\t</div>\n\t)\n\n\tif (mode === 'modal') {\n\t\treturn (\n\t\t\t<Modal open={open} onClose={onClose ?? (() => {})} theme={theme}>\n\t\t\t\t<div style={{ padding: '1.5rem', maxWidth: '600px' }} className={className}>\n\t\t\t\t\t{content}\n\t\t\t\t</div>\n\t\t\t</Modal>\n\t\t)\n\t}\n\n\treturn (\n\t\t<div style={mergeStyles(styles.card, { padding: '1.5rem' })} className={className}>\n\t\t\t{content}\n\t\t</div>\n\t)\n}\n\n// Toggle component\ninterface ToggleProps {\n\tchecked: boolean\n\tonChange: (checked: boolean) => void\n\tdisabled?: boolean\n\ttheme: ThemeVariables\n}\n\nfunction Toggle({ checked, onChange, disabled, theme }: ToggleProps) {\n\tconst style: CSSProperties = {\n\t\tposition: 'relative',\n\t\twidth: '40px',\n\t\theight: '22px',\n\t\tbackgroundColor: checked ? theme.colorPrimary : theme.colorMuted,\n\t\tborderRadius: '11px',\n\t\tcursor: disabled ? 'not-allowed' : 'pointer',\n\t\ttransition: 'background-color 0.2s ease',\n\t\topacity: disabled ? 0.6 : 1,\n\t\tborder: 'none',\n\t\tpadding: 0,\n\t\tflexShrink: 0,\n\t}\n\n\tconst knobStyle: CSSProperties = {\n\t\tposition: 'absolute',\n\t\ttop: '2px',\n\t\tleft: checked ? '20px' : '2px',\n\t\twidth: '18px',\n\t\theight: '18px',\n\t\tbackgroundColor: '#fff',\n\t\tborderRadius: '50%',\n\t\tboxShadow: '0 1px 3px rgba(0, 0, 0, 0.2)',\n\t\ttransition: 'left 0.2s ease',\n\t}\n\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\trole=\"switch\"\n\t\t\taria-checked={checked}\n\t\t\tdisabled={disabled}\n\t\t\tonClick={() => !disabled && onChange(!checked)}\n\t\t\tstyle={style}\n\t\t>\n\t\t\t<span style={knobStyle} />\n\t\t</button>\n\t)\n}\n\n// Category toggle (larger)\nfunction CategoryToggle({\n\tenabled,\n\tonChange,\n\ttheme,\n}: {\n\tenabled: boolean\n\tonChange: (enabled: boolean) => void\n\ttheme: ThemeVariables\n}) {\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tonClick={() => onChange(!enabled)}\n\t\t\tstyle={{\n\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\tfontWeight: 500,\n\t\t\t\tbackgroundColor: enabled ? theme.colorPrimary : 'transparent',\n\t\t\t\tcolor: enabled ? theme.colorPrimaryForeground : theme.colorMutedForeground,\n\t\t\t\tborder: `1px solid ${enabled ? theme.colorPrimary : theme.colorBorder}`,\n\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\tcursor: 'pointer',\n\t\t\t\ttransition: 'all 0.15s ease',\n\t\t\t}}\n\t\t>\n\t\t\t{enabled ? 'All On' : 'All Off'}\n\t\t</button>\n\t)\n}\n\n// Check icon\nfunction CheckIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tstyle={{ marginRight: '0.5rem' }}\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<polyline points=\"20 6 9 17 4 12\" />\n\t\t</svg>\n\t)\n}\n","/**\n * Cookie Banner Component\n *\n * GDPR/CCPA compliant cookie consent banner.\n * Appears at bottom or top of page, with Accept All / Customize options.\n */\n\n'use client'\n\nimport { type CSSProperties, useEffect, useState } from 'react'\nimport { Z_INDEX_OVERLAY } from '../../constants'\nimport { useConsent } from '../consent-hooks'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\nexport interface CookieBannerProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Position of the banner */\n\tposition?: 'bottom' | 'top' | 'bottom-left' | 'bottom-right'\n\t/** Banner title */\n\ttitle?: string\n\t/** Banner description */\n\tdescription?: string\n\t/** Accept all button text */\n\tacceptAllText?: string\n\t/** Decline optional button text */\n\tdeclineText?: string\n\t/** Customize button text */\n\tcustomizeText?: string\n\t/** Privacy policy link */\n\tprivacyPolicyUrl?: string\n\t/** Privacy policy link text */\n\tprivacyPolicyText?: string\n\t/** Called when preferences are saved */\n\tonSave?: () => void\n\t/** Custom class name */\n\tclassName?: string\n\t/** Show the banner even if user has consented (for testing) */\n\tforceShow?: boolean\n\t/** Variant style */\n\tvariant?: 'bar' | 'popup' | 'modal'\n}\n\n/**\n * Cookie consent banner\n *\n * @example\n * ```tsx\n * // Basic usage - auto shows when needed\n * <CookieBanner />\n *\n * // With custom text\n * <CookieBanner\n *   title=\"We value your privacy\"\n *   description=\"We use cookies to improve your experience.\"\n *   privacyPolicyUrl=\"/privacy\"\n * />\n *\n * // Popup variant in corner\n * <CookieBanner variant=\"popup\" position=\"bottom-right\" />\n * ```\n */\nexport function CookieBanner({\n\ttheme = defaultTheme,\n\tposition = 'bottom',\n\ttitle = 'Cookie Preferences',\n\tdescription = 'We use cookies to enhance your browsing experience, serve personalized content, and analyze our traffic. By clicking \"Accept All\", you consent to our use of cookies.',\n\tacceptAllText = 'Accept All',\n\tdeclineText = 'Decline Optional',\n\tcustomizeText = 'Customize',\n\tprivacyPolicyUrl,\n\tprivacyPolicyText = 'Privacy Policy',\n\tonSave,\n\tclassName,\n\tforceShow = false,\n\tvariant = 'bar',\n}: CookieBannerProps) {\n\tconst {\n\t\tshowBanner,\n\t\ttypes,\n\t\tconsents,\n\t\tacceptAll,\n\t\tdeclineOptional,\n\t\tsetConsent,\n\t\tsaveConsents,\n\t\tisLoading,\n\t} = useConsent()\n\n\tconst [showCustomize, setShowCustomize] = useState(false)\n\tconst [isVisible, setIsVisible] = useState(false)\n\tconst styles = baseStyles(theme)\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// Animate in\n\tuseEffect(() => {\n\t\tif (showBanner || forceShow) {\n\t\t\tconst timer = setTimeout(() => setIsVisible(true), 50)\n\t\t\treturn () => clearTimeout(timer)\n\t\t} else {\n\t\t\tsetIsVisible(false)\n\t\t}\n\t}, [showBanner, forceShow])\n\n\t// Handle accept all\n\tconst handleAcceptAll = async () => {\n\t\tawait acceptAll()\n\t\tonSave?.()\n\t}\n\n\t// Handle decline optional\n\tconst handleDeclineOptional = async () => {\n\t\tawait declineOptional()\n\t\tonSave?.()\n\t}\n\n\t// Handle save preferences\n\tconst handleSavePreferences = async () => {\n\t\tawait saveConsents()\n\t\tsetShowCustomize(false)\n\t\tonSave?.()\n\t}\n\n\tif (!showBanner && !forceShow) {\n\t\treturn null\n\t}\n\n\t// Position styles\n\tconst positionStyles: Record<string, CSSProperties> = {\n\t\tbottom: {\n\t\t\tposition: 'fixed',\n\t\t\tbottom: 0,\n\t\t\tleft: 0,\n\t\t\tright: 0,\n\t\t\tzIndex: Z_INDEX_OVERLAY,\n\t\t},\n\t\ttop: {\n\t\t\tposition: 'fixed',\n\t\t\ttop: 0,\n\t\t\tleft: 0,\n\t\t\tright: 0,\n\t\t\tzIndex: Z_INDEX_OVERLAY,\n\t\t},\n\t\t'bottom-left': {\n\t\t\tposition: 'fixed',\n\t\t\tbottom: '1rem',\n\t\t\tleft: '1rem',\n\t\t\tzIndex: Z_INDEX_OVERLAY,\n\t\t\tmaxWidth: '400px',\n\t\t},\n\t\t'bottom-right': {\n\t\t\tposition: 'fixed',\n\t\t\tbottom: '1rem',\n\t\t\tright: '1rem',\n\t\t\tzIndex: Z_INDEX_OVERLAY,\n\t\t\tmaxWidth: '400px',\n\t\t},\n\t}\n\n\tconst containerStyle: CSSProperties = mergeStyles(\n\t\t{\n\t\t\tfontFamily: theme.fontFamily,\n\t\t\tbackgroundColor: theme.colorBackground,\n\t\t\tborderTop:\n\t\t\t\tposition === 'bottom' || position === 'top' ? `1px solid ${theme.colorBorder}` : 'none',\n\t\t\tboxShadow: '0 -4px 20px rgba(0, 0, 0, 0.1)',\n\t\t\ttransform: isVisible\n\t\t\t\t? 'translateY(0)'\n\t\t\t\t: position.includes('top')\n\t\t\t\t\t? 'translateY(-100%)'\n\t\t\t\t\t: 'translateY(100%)',\n\t\t\topacity: isVisible ? 1 : 0,\n\t\t\ttransition: 'transform 0.3s ease-out, opacity 0.3s ease-out',\n\t\t},\n\t\tpositionStyles[position],\n\t\tvariant === 'popup'\n\t\t\t? {\n\t\t\t\t\tborderRadius: theme.borderRadiusLg,\n\t\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\tboxShadow: '0 10px 40px rgba(0, 0, 0, 0.15)',\n\t\t\t\t}\n\t\t\t: {},\n\t)\n\n\tconst contentStyle: CSSProperties = {\n\t\tpadding: variant === 'bar' ? '1rem 1.5rem' : '1.5rem',\n\t\tmaxWidth: variant === 'bar' ? '1200px' : 'none',\n\t\tmargin: variant === 'bar' ? '0 auto' : 0,\n\t}\n\n\t// Optional categories (non-required)\n\tconst optionalTypes = types.filter((t) => !t.required)\n\n\treturn (\n\t\t<div style={containerStyle} className={className} role=\"dialog\" aria-label=\"Cookie consent\">\n\t\t\t<div style={contentStyle}>\n\t\t\t\t{!showCustomize ? (\n\t\t\t\t\t// Main banner view\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={\n\t\t\t\t\t\t\tvariant === 'bar'\n\t\t\t\t\t\t\t\t? mergeStyles(styles.flexBetween, {\n\t\t\t\t\t\t\t\t\t\tgap: '2rem',\n\t\t\t\t\t\t\t\t\t\tflexWrap: 'wrap',\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t: {}\n\t\t\t\t\t\t}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div style={{ flex: 1, minWidth: '200px' }}>\n\t\t\t\t\t\t\t<h3\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeLg,\n\t\t\t\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{title}\n\t\t\t\t\t\t\t</h3>\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\t\t\t\tlineHeight: 1.6,\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{description}\n\t\t\t\t\t\t\t\t{privacyPolicyUrl && (\n\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\t\t\thref={privacyPolicyUrl}\n\t\t\t\t\t\t\t\t\t\t\tstyle={styles.link}\n\t\t\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{privacyPolicyText}\n\t\t\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.flexRow, {\n\t\t\t\t\t\t\t\tgap: '0.75rem',\n\t\t\t\t\t\t\t\tflexWrap: 'wrap',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{optionalTypes.length > 0 && (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tonClick={() => setShowCustomize(true)}\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{customizeText}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={handleDeclineOptional}\n\t\t\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonSecondary)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{declineText}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={handleAcceptAll}\n\t\t\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{isLoading ? <span style={styles.spinner} /> : acceptAllText}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t) : (\n\t\t\t\t\t// Customize view\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<div style={mergeStyles(styles.flexBetween, { marginBottom: '1rem' })}>\n\t\t\t\t\t\t\t<h3\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeLg,\n\t\t\t\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tCustomize Preferences\n\t\t\t\t\t\t\t</h3>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={() => setShowCustomize(false)}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonGhost, {\n\t\t\t\t\t\t\t\t\tpadding: '0.25rem',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\taria-label=\"Close\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<CloseIcon />\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<div style={{ marginBottom: '1.5rem' }}>\n\t\t\t\t\t\t\t{/* Required (always on) */}\n\t\t\t\t\t\t\t{types\n\t\t\t\t\t\t\t\t.filter((t) => t.required)\n\t\t\t\t\t\t\t\t.map((type) => (\n\t\t\t\t\t\t\t\t\t<ConsentToggle\n\t\t\t\t\t\t\t\t\t\tkey={type.id}\n\t\t\t\t\t\t\t\t\t\tname={type.name}\n\t\t\t\t\t\t\t\t\t\tdescription={type.description}\n\t\t\t\t\t\t\t\t\t\tchecked={true}\n\t\t\t\t\t\t\t\t\t\tdisabled={true}\n\t\t\t\t\t\t\t\t\t\trequired={true}\n\t\t\t\t\t\t\t\t\t\ttheme={theme}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t))}\n\n\t\t\t\t\t\t\t{/* Optional */}\n\t\t\t\t\t\t\t{optionalTypes.map((type) => (\n\t\t\t\t\t\t\t\t<ConsentToggle\n\t\t\t\t\t\t\t\t\tkey={type.id}\n\t\t\t\t\t\t\t\t\tname={type.name}\n\t\t\t\t\t\t\t\t\tdescription={type.description}\n\t\t\t\t\t\t\t\t\tchecked={consents[type.slug] ?? type.defaultEnabled}\n\t\t\t\t\t\t\t\t\tonChange={(checked) => setConsent(type.slug, checked)}\n\t\t\t\t\t\t\t\t\ttheme={theme}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.flexRow, {\n\t\t\t\t\t\t\t\tgap: '0.75rem',\n\t\t\t\t\t\t\t\tjustifyContent: 'flex-end',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={() => setShowCustomize(false)}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={handleSavePreferences}\n\t\t\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{isLoading ? <span style={styles.spinner} /> : 'Save Preferences'}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n// Consent toggle component\ninterface ConsentToggleProps {\n\tname: string\n\tdescription?: string\n\tchecked: boolean\n\tonChange?: (checked: boolean) => void\n\tdisabled?: boolean\n\trequired?: boolean\n\ttheme: ThemeVariables\n}\n\nfunction ConsentToggle({\n\tname,\n\tdescription,\n\tchecked,\n\tonChange,\n\tdisabled,\n\trequired,\n\ttheme,\n}: ConsentToggleProps) {\n\tconst toggleStyle: CSSProperties = {\n\t\tposition: 'relative',\n\t\twidth: '44px',\n\t\theight: '24px',\n\t\tbackgroundColor: checked ? theme.colorPrimary : theme.colorMuted,\n\t\tborderRadius: '12px',\n\t\tcursor: disabled ? 'not-allowed' : 'pointer',\n\t\ttransition: 'background-color 0.2s ease',\n\t\topacity: disabled ? 0.6 : 1,\n\t\tflexShrink: 0,\n\t}\n\n\tconst knobStyle: CSSProperties = {\n\t\tposition: 'absolute',\n\t\ttop: '2px',\n\t\tleft: checked ? '22px' : '2px',\n\t\twidth: '20px',\n\t\theight: '20px',\n\t\tbackgroundColor: '#fff',\n\t\tborderRadius: '50%',\n\t\tboxShadow: '0 1px 3px rgba(0, 0, 0, 0.2)',\n\t\ttransition: 'left 0.2s ease',\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tstyle={{\n\t\t\t\tdisplay: 'flex',\n\t\t\t\talignItems: 'flex-start',\n\t\t\t\tgap: '1rem',\n\t\t\t\tpadding: '0.75rem 0',\n\t\t\t\tborderBottom: `1px solid ${theme.colorBorder}`,\n\t\t\t}}\n\t\t>\n\t\t\t<div style={{ flex: 1 }}>\n\t\t\t\t<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>\n\t\t\t\t\t<span style={{ fontWeight: 500, fontSize: theme.fontSizeSm }}>{name}</span>\n\t\t\t\t\t{required && (\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\t\t\t\tpadding: '0.125rem 0.375rem',\n\t\t\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tRequired\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t{description && (\n\t\t\t\t\t<p\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{description}\n\t\t\t\t\t</p>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\trole=\"switch\"\n\t\t\t\taria-checked={checked}\n\t\t\t\taria-label={`Toggle ${name}`}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tonClick={() => !disabled && onChange?.(!checked)}\n\t\t\t\tstyle={toggleStyle}\n\t\t\t>\n\t\t\t\t<span style={knobStyle} />\n\t\t\t</button>\n\t\t</div>\n\t)\n}\n\n// Close icon\nfunction CloseIcon() {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"20\"\n\t\t\theight=\"20\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n\t\t\t<line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n\t\t</svg>\n\t)\n}\n","/**\n * Error Boundary Components\n *\n * Pre-built error boundary with automatic error reporting.\n * Includes fallback UI and user feedback collection.\n */\n\n'use client'\n\nimport {\n\tComponent,\n\ttype CSSProperties,\n\ttype ErrorInfo,\n\ttype ReactNode,\n\tuseEffect,\n\tuseState,\n} from 'react'\nimport { UI_FORM_SUCCESS_MS, Z_INDEX_OVERLAY } from '../../constants'\nimport { useErrorBoundary as useErrorBoundaryHook, useErrorTracking } from '../monitoring-hooks'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\n// ============================================\n// SylphxErrorBoundary (Class Component)\n// ============================================\n\nexport interface ErrorBoundaryFallbackProps {\n\terror: Error\n\terrorInfo?: ErrorInfo\n\teventId: string | null\n\tresetError: () => void\n\ttheme: ThemeVariables\n}\n\nexport interface SylphxErrorBoundaryProps {\n\t/** Child components */\n\tchildren: ReactNode\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Custom fallback component */\n\tfallback?: ReactNode | ((props: ErrorBoundaryFallbackProps) => ReactNode)\n\t/** Called when error is caught */\n\tonError?: (error: Error, errorInfo: ErrorInfo, eventId: string | null) => void\n\t/** Called when error is reset */\n\tonReset?: () => void\n\t/** Component name for context */\n\tcomponentName?: string\n\t/** Show detailed error info in development */\n\tshowDetails?: boolean\n}\n\ninterface ErrorBoundaryState {\n\thasError: boolean\n\terror: Error | null\n\terrorInfo: ErrorInfo | null\n\teventId: string | null\n}\n\n/**\n * Error Boundary with automatic error reporting\n *\n * @example\n * ```tsx\n * <SylphxErrorBoundary\n *   componentName=\"Dashboard\"\n *   onError={(error, info, eventId) => {\n *     console.log('Error captured:', eventId)\n *   }}\n * >\n *   <Dashboard />\n * </SylphxErrorBoundary>\n *\n * // With custom fallback\n * <SylphxErrorBoundary\n *   fallback={({ error, resetError }) => (\n *     <div>\n *       <p>Something went wrong: {error.message}</p>\n *       <button onClick={resetError}>Try again</button>\n *     </div>\n *   )}\n * >\n *   <App />\n * </SylphxErrorBoundary>\n * ```\n */\nexport class SylphxErrorBoundary extends Component<SylphxErrorBoundaryProps, ErrorBoundaryState> {\n\tconstructor(props: SylphxErrorBoundaryProps) {\n\t\tsuper(props)\n\t\tthis.state = {\n\t\t\thasError: false,\n\t\t\terror: null,\n\t\t\terrorInfo: null,\n\t\t\teventId: null,\n\t\t}\n\t}\n\n\tstatic getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState> {\n\t\treturn { hasError: true, error }\n\t}\n\n\tcomponentDidCatch(error: Error, errorInfo: ErrorInfo) {\n\t\tthis.setState({ errorInfo })\n\n\t\t// Report error using the context wrapper\n\t\t// This will be handled by ErrorBoundaryContextWrapper\n\t\tthis.props.onError?.(error, errorInfo, null)\n\t}\n\n\tresetError = () => {\n\t\tthis.setState({\n\t\t\thasError: false,\n\t\t\terror: null,\n\t\t\terrorInfo: null,\n\t\t\teventId: null,\n\t\t})\n\t\tthis.props.onReset?.()\n\t}\n\n\trender() {\n\t\tconst { hasError, error, errorInfo, eventId } = this.state\n\t\tconst { children, fallback, theme = defaultTheme, showDetails } = this.props\n\n\t\tif (hasError && error) {\n\t\t\t// Custom fallback\n\t\t\tif (fallback) {\n\t\t\t\tif (typeof fallback === 'function') {\n\t\t\t\t\treturn fallback({\n\t\t\t\t\t\terror,\n\t\t\t\t\t\terrorInfo: errorInfo || undefined,\n\t\t\t\t\t\teventId,\n\t\t\t\t\t\tresetError: this.resetError,\n\t\t\t\t\t\ttheme,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\treturn fallback\n\t\t\t}\n\n\t\t\t// Default fallback\n\t\t\treturn (\n\t\t\t\t<DefaultErrorFallback\n\t\t\t\t\terror={error}\n\t\t\t\t\terrorInfo={errorInfo || undefined}\n\t\t\t\t\teventId={eventId}\n\t\t\t\t\tresetError={this.resetError}\n\t\t\t\t\ttheme={theme}\n\t\t\t\t\tshowDetails={showDetails}\n\t\t\t\t/>\n\t\t\t)\n\t\t}\n\n\t\treturn children\n\t}\n}\n\n// ============================================\n// ErrorBoundary with Context (Functional Wrapper)\n// ============================================\n\nexport interface ErrorBoundaryProps extends Omit<SylphxErrorBoundaryProps, 'onError'> {\n\t/** Called when error is caught (with eventId) */\n\tonError?: (error: Error, errorInfo: ErrorInfo, eventId: string | null) => void\n}\n\n/**\n * Error Boundary that automatically reports to Sylphx Platform\n *\n * @example\n * ```tsx\n * // In your app root\n * <SylphxProvider>\n *   <ErrorBoundary>\n *     <App />\n *   </ErrorBoundary>\n * </SylphxProvider>\n * ```\n */\nexport function ErrorBoundary(props: ErrorBoundaryProps) {\n\tconst { handleError } = useErrorBoundaryHook({\n\t\tcomponentName: props.componentName,\n\t\tonError: (error, eventId) => {\n\t\t\t// Get errorInfo from state if available\n\t\t\tprops.onError?.(error, {} as ErrorInfo, eventId)\n\t\t},\n\t})\n\n\treturn (\n\t\t<SylphxErrorBoundary\n\t\t\t{...props}\n\t\t\tonError={(error, errorInfo, _eventId) => {\n\t\t\t\t// Use the hook's handleError which reports to platform\n\t\t\t\thandleError(error, {\n\t\t\t\t\tcomponentStack: errorInfo.componentStack ?? undefined,\n\t\t\t\t})\n\t\t\t}}\n\t\t/>\n\t)\n}\n\n// ============================================\n// Default Error Fallback\n// ============================================\n\ninterface DefaultErrorFallbackProps {\n\terror: Error\n\terrorInfo?: ErrorInfo\n\teventId: string | null\n\tresetError: () => void\n\ttheme: ThemeVariables\n\tshowDetails?: boolean\n}\n\nfunction DefaultErrorFallback({\n\terror,\n\terrorInfo,\n\teventId,\n\tresetError,\n\ttheme,\n\tshowDetails = process.env.NODE_ENV === 'development',\n}: DefaultErrorFallbackProps) {\n\tconst styles = baseStyles(theme)\n\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tconst containerStyle: CSSProperties = mergeStyles(styles.container, {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'center',\n\t\tminHeight: '300px',\n\t\tpadding: '2rem',\n\t})\n\n\tconst cardStyle: CSSProperties = mergeStyles(styles.card, {\n\t\tmaxWidth: '500px',\n\t\twidth: '100%',\n\t\tpadding: '2rem',\n\t\ttextAlign: 'center',\n\t})\n\n\treturn (\n\t\t<div style={containerStyle}>\n\t\t\t<div style={cardStyle}>\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\twidth: '64px',\n\t\t\t\t\t\theight: '64px',\n\t\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\t\tbackgroundColor: `${theme.colorDestructive}15`,\n\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\tjustifyContent: 'center',\n\t\t\t\t\t\tmargin: '0 auto 1.5rem',\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<ErrorIcon color={theme.colorDestructive} />\n\t\t\t\t</div>\n\n\t\t\t\t<h2\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tmargin: '0 0 0.5rem',\n\t\t\t\t\t\tfontSize: theme.fontSizeXl,\n\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\tSomething went wrong\n\t\t\t\t</h2>\n\t\t\t\t<p\n\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\tmarginBottom: '1.5rem',\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\tWe've been notified and are working to fix the issue.\n\t\t\t\t</p>\n\n\t\t\t\t{eventId && (\n\t\t\t\t\t<p\n\t\t\t\t\t\tstyle={mergeStyles(styles.textXs, styles.textMuted, {\n\t\t\t\t\t\t\tmarginBottom: '1.5rem',\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\tError ID: <code style={{ fontFamily: 'monospace' }}>{eventId}</code>\n\t\t\t\t\t</p>\n\t\t\t\t)}\n\n\t\t\t\t{showDetails && (\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\ttextAlign: 'left',\n\t\t\t\t\t\t\tpadding: '1rem',\n\t\t\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\t\t\tmarginBottom: '1.5rem',\n\t\t\t\t\t\t\toverflow: 'auto',\n\t\t\t\t\t\t\tmaxHeight: '200px',\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tmargin: '0 0 0.5rem',\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\t\t\tcolor: theme.colorDestructive,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{error.name}: {error.message}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t{errorInfo?.componentStack && (\n\t\t\t\t\t\t\t<pre\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\t\t\t\tfontSize: '10px',\n\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\twhiteSpace: 'pre-wrap',\n\t\t\t\t\t\t\t\t\twordBreak: 'break-word',\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{errorInfo.componentStack}\n\t\t\t\t\t\t\t</pre>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t<div style={{ display: 'flex', gap: '0.75rem', justifyContent: 'center' }}>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={() => window.location.reload()}\n\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline)}\n\t\t\t\t\t>\n\t\t\t\t\t\tRefresh Page\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={resetError}\n\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary)}\n\t\t\t\t\t>\n\t\t\t\t\t\tTry Again\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n// ============================================\n// FeedbackWidget\n// ============================================\n\nexport interface FeedbackWidgetProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Widget title */\n\ttitle?: string\n\t/** Widget description */\n\tdescription?: string\n\t/** Placeholder text */\n\tplaceholder?: string\n\t/** Submit button text */\n\tsubmitText?: string\n\t/** Success message */\n\tsuccessMessage?: string\n\t/** Called when feedback is submitted */\n\tonSubmit?: (feedback: { message: string; email?: string; eventId?: string }) => Promise<void>\n\t/** Associated error event ID */\n\teventId?: string\n\t/** Custom class name */\n\tclassName?: string\n\t/** Show email field */\n\tshowEmail?: boolean\n\t/** Position */\n\tposition?: 'bottom-right' | 'bottom-left'\n\t/** Initially open */\n\tdefaultOpen?: boolean\n}\n\n/**\n * Feedback widget for collecting user feedback\n *\n * @example\n * ```tsx\n * // Floating feedback button\n * <FeedbackWidget\n *   position=\"bottom-right\"\n *   onSubmit={async (feedback) => {\n *     await reportFeedback(feedback)\n *   }}\n * />\n *\n * // After error, collect context\n * <FeedbackWidget\n *   eventId={errorEventId}\n *   title=\"Help us fix this\"\n *   description=\"What were you trying to do when this error occurred?\"\n * />\n * ```\n */\nexport function FeedbackWidget({\n\ttheme = defaultTheme,\n\ttitle = 'Send Feedback',\n\tdescription = 'Help us improve by sharing your thoughts.',\n\tplaceholder = 'Describe your issue or suggestion...',\n\tsubmitText = 'Submit',\n\tsuccessMessage = 'Thank you for your feedback!',\n\tonSubmit,\n\teventId,\n\tclassName,\n\tshowEmail = true,\n\tposition = 'bottom-right',\n\tdefaultOpen = false,\n}: FeedbackWidgetProps) {\n\tconst [isOpen, setIsOpen] = useState(defaultOpen)\n\tconst [message, setMessage] = useState('')\n\tconst [email, setEmail] = useState('')\n\tconst [isSubmitting, setIsSubmitting] = useState(false)\n\tconst [isSuccess, setIsSuccess] = useState(false)\n\tconst [error, setError] = useState<string | null>(null)\n\tconst { captureMessage } = useErrorTracking()\n\tconst styles = baseStyles(theme)\n\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tconst handleSubmit = async (e: React.FormEvent) => {\n\t\te.preventDefault()\n\t\tif (!message.trim()) return\n\n\t\tsetIsSubmitting(true)\n\t\tsetError(null)\n\n\t\ttry {\n\t\t\t// Report to Sylphx Platform\n\t\t\tawait captureMessage(`User Feedback: ${message}`, {\n\t\t\t\tlevel: 'info',\n\t\t\t\ttags: { type: 'feedback' },\n\t\t\t\textra: { email, eventId },\n\t\t\t})\n\n\t\t\t// Call custom handler\n\t\t\tawait onSubmit?.({\n\t\t\t\tmessage,\n\t\t\t\temail: showEmail ? email : undefined,\n\t\t\t\teventId,\n\t\t\t})\n\n\t\t\tsetIsSuccess(true)\n\t\t\tsetMessage('')\n\t\t\tsetEmail('')\n\n\t\t\t// Auto-close after success\n\t\t\tsetTimeout(() => {\n\t\t\t\tsetIsOpen(false)\n\t\t\t\tsetIsSuccess(false)\n\t\t\t}, UI_FORM_SUCCESS_MS)\n\t\t} catch (_err) {\n\t\t\tsetError('Failed to submit feedback. Please try again.')\n\t\t} finally {\n\t\t\tsetIsSubmitting(false)\n\t\t}\n\t}\n\n\tconst positionStyles: Record<string, CSSProperties> = {\n\t\t'bottom-right': { bottom: '1rem', right: '1rem' },\n\t\t'bottom-left': { bottom: '1rem', left: '1rem' },\n\t}\n\n\tconst containerStyle: CSSProperties = {\n\t\tposition: 'fixed',\n\t\tzIndex: Z_INDEX_OVERLAY,\n\t\tfontFamily: theme.fontFamily,\n\t\t...positionStyles[position],\n\t}\n\n\tconst buttonStyle: CSSProperties = mergeStyles(styles.button, styles.buttonPrimary, {\n\t\tpadding: '0.75rem 1rem',\n\t\tborderRadius: '9999px',\n\t\tboxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',\n\t})\n\n\tconst panelStyle: CSSProperties = mergeStyles(styles.card, {\n\t\twidth: '320px',\n\t\tanimation: 'sylphx-scale-in 0.2s ease',\n\t})\n\n\tif (!isOpen) {\n\t\treturn (\n\t\t\t<div style={containerStyle} className={className}>\n\t\t\t\t<button type=\"button\" onClick={() => setIsOpen(true)} style={buttonStyle}>\n\t\t\t\t\t<FeedbackIcon />\n\t\t\t\t\tFeedback\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t)\n\t}\n\n\treturn (\n\t\t<div style={containerStyle} className={className}>\n\t\t\t<div style={panelStyle}>\n\t\t\t\t{/* Header */}\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t\tpadding: '1rem',\n\t\t\t\t\t\tborderBottom: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<h3 style={{ margin: 0, fontSize: theme.fontSizeSm, fontWeight: 600 }}>{title}</h3>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={() => setIsOpen(false)}\n\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonGhost, {\n\t\t\t\t\t\t\tpadding: '0.25rem',\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t<CloseIcon />\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\n\t\t\t\t{/* Content */}\n\t\t\t\t<div style={{ padding: '1rem' }}>\n\t\t\t\t\t{isSuccess ? (\n\t\t\t\t\t\t<div style={{ textAlign: 'center', padding: '1rem 0' }}>\n\t\t\t\t\t\t\t<CheckCircleIcon color={theme.colorSuccess} />\n\t\t\t\t\t\t\t<p style={mergeStyles(styles.textSm, { marginTop: '0.5rem' })}>{successMessage}</p>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<form onSubmit={handleSubmit}>\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textXs, styles.textMuted, {\n\t\t\t\t\t\t\t\t\tmarginBottom: '1rem',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{description}\n\t\t\t\t\t\t\t</p>\n\n\t\t\t\t\t\t\t{error && (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.alert, styles.alertError, {\n\t\t\t\t\t\t\t\t\t\tmarginBottom: '1rem',\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{error}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t<div style={styles.formGroup}>\n\t\t\t\t\t\t\t\t<textarea\n\t\t\t\t\t\t\t\t\tvalue={message}\n\t\t\t\t\t\t\t\t\tonChange={(e) => setMessage(e.target.value)}\n\t\t\t\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\t\t\t\trows={4}\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.input, {\n\t\t\t\t\t\t\t\t\t\tresize: 'vertical',\n\t\t\t\t\t\t\t\t\t\tminHeight: '80px',\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t{showEmail && (\n\t\t\t\t\t\t\t\t<div style={styles.formGroup}>\n\t\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\t\ttype=\"email\"\n\t\t\t\t\t\t\t\t\t\tvalue={email}\n\t\t\t\t\t\t\t\t\t\tonChange={(e) => setEmail(e.target.value)}\n\t\t\t\t\t\t\t\t\t\tplaceholder=\"Email (optional)\"\n\t\t\t\t\t\t\t\t\t\tstyle={styles.input}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{eventId && (\n\t\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textXs, styles.textMuted, {\n\t\t\t\t\t\t\t\t\t\tmarginBottom: '1rem',\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tError ID: <code>{eventId}</code>\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\tdisabled={isSubmitting || !message.trim()}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\t\t\t\tstyles.buttonPrimary,\n\t\t\t\t\t\t\t\t\tstyles.buttonFullWidth,\n\t\t\t\t\t\t\t\t\tisSubmitting || !message.trim() ? styles.buttonDisabled : undefined,\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{isSubmitting ? <span style={styles.spinner} /> : submitText}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</form>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n// ============================================\n// Icons\n// ============================================\n\nfunction ErrorIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"32\"\n\t\t\theight=\"32\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<circle cx=\"12\" cy=\"12\" r=\"10\" />\n\t\t\t<line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n\t\t\t<line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n\t\t</svg>\n\t)\n}\n\nfunction FeedbackIcon() {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstyle={{ marginRight: '0.5rem' }}\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M21 11.5a8.38 8.38 0 01-.9 3.8 8.5 8.5 0 01-7.6 4.7 8.38 8.38 0 01-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 01-.9-3.8 8.5 8.5 0 014.7-7.6 8.38 8.38 0 013.8-.9h.5a8.48 8.48 0 018 8v.5z\" />\n\t\t</svg>\n\t)\n}\n\nfunction CloseIcon() {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n\t\t\t<line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n\t\t</svg>\n\t)\n}\n\nfunction CheckCircleIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"48\"\n\t\t\theight=\"48\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M22 11.08V12a10 10 0 11-5.93-9.14\" />\n\t\t\t<polyline points=\"22 4 12 14.01 9 11.01\" />\n\t\t</svg>\n\t)\n}\n","/**\n * Feature Gate Component\n *\n * Declarative component for showing/hiding content based on feature flags.\n * Supports loading states, fallbacks, and A/B test variants.\n */\n\n'use client'\n\nimport { type CSSProperties, type ReactNode, useContext, useState } from 'react'\nimport { Z_INDEX_CRITICAL_OVERLAY } from '../../constants'\nimport {\n\ttype FeatureFlag,\n\tFeatureFlagContext,\n\ttype FlagValue,\n\tuseFeatureFlag,\n} from '../feature-flag-hooks'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, mergeStyles } from './styles'\n\n// ============================================\n// FeatureGate\n// ============================================\n\nexport interface FeatureGateProps {\n\t/** Feature flag key */\n\tflag: string\n\t/** Content to show when flag is enabled */\n\tchildren: ReactNode\n\t/** Content to show when flag is disabled */\n\tfallback?: ReactNode\n\t/** Content to show while loading */\n\tloadingFallback?: ReactNode\n\t/** Show loading state */\n\tshowLoading?: boolean\n\t/** Invert the gate (show children when flag is OFF) */\n\tinvert?: boolean\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n}\n\n/**\n * Feature Gate component\n *\n * @example\n * ```tsx\n * // Basic usage\n * <FeatureGate flag=\"new-dashboard\">\n *   <NewDashboard />\n * </FeatureGate>\n *\n * // With fallback\n * <FeatureGate\n *   flag=\"new-checkout\"\n *   fallback={<OldCheckout />}\n * >\n *   <NewCheckout />\n * </FeatureGate>\n *\n * // Inverted (show when flag is OFF)\n * <FeatureGate flag=\"maintenance-mode\" invert>\n *   <NormalContent />\n * </FeatureGate>\n * ```\n */\nexport function FeatureGate({\n\tflag,\n\tchildren,\n\tfallback = null,\n\tloadingFallback,\n\tshowLoading = false,\n\tinvert = false,\n\ttheme = defaultTheme,\n}: FeatureGateProps) {\n\tconst { isEnabled, isLoading } = useFeatureFlag(flag)\n\n\t// Show loading state\n\tif (isLoading && showLoading) {\n\t\tif (loadingFallback) {\n\t\t\treturn <>{loadingFallback}</>\n\t\t}\n\t\treturn <FeatureGateLoading theme={theme} />\n\t}\n\n\t// Determine if gate should be open\n\tconst shouldShow = invert ? !isEnabled : isEnabled\n\n\tif (shouldShow) {\n\t\treturn <>{children}</>\n\t}\n\n\treturn <>{fallback}</>\n}\n\n// ============================================\n// FeatureVariant\n// ============================================\n\nexport interface FeatureVariantProps {\n\t/** Feature flag key */\n\tflag: string\n\t/** Map of variant name to component */\n\tvariants: Record<string, ReactNode>\n\t/** Default content if no variant matches */\n\tdefaultVariant?: ReactNode\n\t/** Content to show while loading */\n\tloadingFallback?: ReactNode\n\t/** Show loading state */\n\tshowLoading?: boolean\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n}\n\n/**\n * Feature Variant component for A/B testing\n *\n * @example\n * ```tsx\n * <FeatureVariant\n *   flag=\"checkout-experiment\"\n *   variants={{\n *     control: <OriginalCheckout />,\n *     'variant-a': <NewCheckoutA />,\n *     'variant-b': <NewCheckoutB />,\n *   }}\n *   defaultVariant={<OriginalCheckout />}\n * />\n * ```\n */\nexport function FeatureVariant({\n\tflag,\n\tvariants,\n\tdefaultVariant = null,\n\tloadingFallback,\n\tshowLoading = false,\n\ttheme = defaultTheme,\n}: FeatureVariantProps) {\n\tconst { variant, isLoading } = useFeatureFlag(flag)\n\n\t// Show loading state\n\tif (isLoading && showLoading) {\n\t\tif (loadingFallback) {\n\t\t\treturn <>{loadingFallback}</>\n\t\t}\n\t\treturn <FeatureGateLoading theme={theme} />\n\t}\n\n\t// Find matching variant\n\tif (variant && variant in variants) {\n\t\treturn <>{variants[variant]}</>\n\t}\n\n\treturn <>{defaultVariant}</>\n}\n\n// ============================================\n// FeatureValue\n// ============================================\n\nexport interface FeatureValueProps<T extends FlagValue = string> {\n\t/** Feature flag key */\n\tflag: string\n\t/** Render function that receives the flag value */\n\tchildren: (value: T, isLoading: boolean) => ReactNode\n\t/** Default value if flag not found */\n\tdefaultValue?: T\n}\n\n/**\n * Feature Value component for non-boolean flags\n *\n * @example\n * ```tsx\n * // String value\n * <FeatureValue flag=\"hero-title\" defaultValue=\"Welcome\">\n *   {(title) => <h1>{title}</h1>}\n * </FeatureValue>\n *\n * // Number value\n * <FeatureValue flag=\"max-items\" defaultValue={10}>\n *   {(maxItems) => <ItemList max={maxItems} />}\n * </FeatureValue>\n *\n * // Object value\n * <FeatureValue flag=\"theme-config\" defaultValue={{ primary: '#000' }}>\n *   {(config) => <ThemedComponent colors={config} />}\n * </FeatureValue>\n * ```\n */\nexport function FeatureValue<T extends FlagValue = string>({\n\tflag,\n\tchildren,\n\tdefaultValue,\n}: FeatureValueProps<T>) {\n\tconst { value, isLoading } = useFeatureFlag<T>(flag, { defaultValue })\n\treturn <>{children(value, isLoading)}</>\n}\n\n// ============================================\n// Loading Component\n// ============================================\n\nfunction FeatureGateLoading({ theme }: { theme: ThemeVariables }) {\n\tconst styles = baseStyles(theme)\n\n\tconst containerStyle: CSSProperties = {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'center',\n\t\tpadding: '1rem',\n\t}\n\n\treturn (\n\t\t<div style={containerStyle}>\n\t\t\t<span style={styles.spinner} />\n\t\t</div>\n\t)\n}\n\n// ============================================\n// FlagDevTools\n// ============================================\n\nexport interface FlagDevToolsProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Position on screen */\n\tposition?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'\n\t/** Initially collapsed */\n\tdefaultCollapsed?: boolean\n\t/** Custom class name */\n\tclassName?: string\n}\n\n/**\n * Development tools for feature flags\n * Shows all flags and allows overriding values\n *\n * @example\n * ```tsx\n * // Only show in development\n * {process.env.NODE_ENV === 'development' && (\n *   <FlagDevTools position=\"bottom-right\" />\n * )}\n * ```\n */\nexport function FlagDevTools({\n\ttheme = defaultTheme,\n\tposition = 'bottom-right',\n\tdefaultCollapsed = true,\n\tclassName,\n}: FlagDevToolsProps) {\n\tconst [isCollapsed, setIsCollapsed] = useState(defaultCollapsed)\n\tconst context = useContext(FeatureFlagContext)\n\tconst styles = baseStyles(theme)\n\n\tif (!context) {\n\t\treturn null\n\t}\n\n\tconst { flags, overrides, setOverride, clearOverrides, isLoading } = context\n\n\tconst positionStyles: Record<string, CSSProperties> = {\n\t\t'bottom-right': { bottom: '1rem', right: '1rem' },\n\t\t'bottom-left': { bottom: '1rem', left: '1rem' },\n\t\t'top-right': { top: '1rem', right: '1rem' },\n\t\t'top-left': { top: '1rem', left: '1rem' },\n\t}\n\n\tconst containerStyle: CSSProperties = mergeStyles(\n\t\t{\n\t\t\tposition: 'fixed',\n\t\t\tzIndex: Z_INDEX_CRITICAL_OVERLAY,\n\t\t\tfontFamily: theme.fontFamily,\n\t\t\tfontSize: theme.fontSizeSm,\n\t\t},\n\t\tpositionStyles[position],\n\t)\n\n\tconst panelStyle: CSSProperties = mergeStyles(styles.card, {\n\t\twidth: '320px',\n\t\tmaxHeight: '400px',\n\t\toverflow: 'auto',\n\t})\n\n\tconst headerStyle: CSSProperties = {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'space-between',\n\t\tpadding: '0.75rem 1rem',\n\t\tborderBottom: `1px solid ${theme.colorBorder}`,\n\t\tbackgroundColor: theme.colorMuted,\n\t}\n\n\tconst flagListStyle: CSSProperties = {\n\t\tpadding: '0.5rem',\n\t}\n\n\tconst flagItemStyle: CSSProperties = {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'space-between',\n\t\tpadding: '0.5rem',\n\t\tborderRadius: theme.borderRadiusSm,\n\t}\n\n\tif (isCollapsed) {\n\t\treturn (\n\t\t\t<div style={containerStyle} className={className}>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={() => setIsCollapsed(false)}\n\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary, {\n\t\t\t\t\t\tpadding: '0.5rem 0.75rem',\n\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\t<FlagIcon /> Flags\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t)\n\t}\n\n\tconst flagEntries: [string, FeatureFlag][] = Array.from(flags.entries())\n\n\treturn (\n\t\t<div style={containerStyle} className={className}>\n\t\t\t<div style={panelStyle}>\n\t\t\t\t<div style={headerStyle}>\n\t\t\t\t\t<span\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<FlagIcon /> Feature Flags\n\t\t\t\t\t</span>\n\t\t\t\t\t<div style={{ display: 'flex', gap: '0.5rem' }}>\n\t\t\t\t\t\t{Object.keys(overrides).length > 0 && (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={clearOverrides}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonGhost, {\n\t\t\t\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tClear\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={() => setIsCollapsed(true)}\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonGhost, {\n\t\t\t\t\t\t\t\tpadding: '0.25rem',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<CloseIcon />\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t\t{isLoading ? (\n\t\t\t\t\t<div style={{ padding: '2rem', textAlign: 'center' }}>\n\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t</div>\n\t\t\t\t) : flagEntries.length === 0 ? (\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tpadding: '2rem',\n\t\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tNo flags loaded\n\t\t\t\t\t</div>\n\t\t\t\t) : (\n\t\t\t\t\t<div style={flagListStyle}>\n\t\t\t\t\t\t{flagEntries.map(([key, flag]) => {\n\t\t\t\t\t\t\tconst hasOverride = key in overrides\n\t\t\t\t\t\t\tconst currentValue = hasOverride ? overrides[key] : flag.enabled\n\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tkey={key}\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(flagItemStyle, {\n\t\t\t\t\t\t\t\t\t\tbackgroundColor: hasOverride ? `${theme.colorWarning}15` : 'transparent',\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<div style={{ flex: 1, minWidth: 0 }}>\n\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\t\t\t\t\t\t\t\ttextOverflow: 'ellipsis',\n\t\t\t\t\t\t\t\t\t\t\t\twhiteSpace: 'nowrap',\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{key}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t{flag.variant && (\n\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\tVariant: {flag.variant}\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t<Toggle\n\t\t\t\t\t\t\t\t\t\tchecked={Boolean(currentValue)}\n\t\t\t\t\t\t\t\t\t\tonChange={(checked) => setOverride(key, checked)}\n\t\t\t\t\t\t\t\t\t\ttheme={theme}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t})}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n// ============================================\n// Helper Components\n// ============================================\n\ninterface ToggleProps {\n\tchecked: boolean\n\tonChange: (checked: boolean) => void\n\ttheme: ThemeVariables\n}\n\nfunction Toggle({ checked, onChange, theme }: ToggleProps) {\n\tconst style: CSSProperties = {\n\t\tposition: 'relative',\n\t\twidth: '36px',\n\t\theight: '20px',\n\t\tbackgroundColor: checked ? theme.colorPrimary : theme.colorMuted,\n\t\tborderRadius: '10px',\n\t\tcursor: 'pointer',\n\t\ttransition: 'background-color 0.2s ease',\n\t\tborder: 'none',\n\t\tpadding: 0,\n\t\tflexShrink: 0,\n\t}\n\n\tconst knobStyle: CSSProperties = {\n\t\tposition: 'absolute',\n\t\ttop: '2px',\n\t\tleft: checked ? '18px' : '2px',\n\t\twidth: '16px',\n\t\theight: '16px',\n\t\tbackgroundColor: '#fff',\n\t\tborderRadius: '50%',\n\t\tboxShadow: '0 1px 3px rgba(0, 0, 0, 0.2)',\n\t\ttransition: 'left 0.2s ease',\n\t}\n\n\treturn (\n\t\t<button type=\"button\" onClick={() => onChange(!checked)} style={style}>\n\t\t\t<span style={knobStyle} />\n\t\t</button>\n\t)\n}\n\nfunction FlagIcon() {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"14\"\n\t\t\theight=\"14\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z\" />\n\t\t\t<line x1=\"4\" y1=\"22\" x2=\"4\" y2=\"15\" />\n\t\t</svg>\n\t)\n}\n\nfunction CloseIcon() {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n\t\t\t<line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n\t\t</svg>\n\t)\n}\n","/**\n * File Upload Components\n *\n * Pre-built file upload components with drag-and-drop, progress tracking,\n * and validation. Uses the ADR-100 `storage.uploads.create` flow under\n * the hood (via the `useStorage` React Query mutation).\n */\n\n'use client'\n\nimport { type CSSProperties, type DragEvent, useCallback, useEffect, useRef, useState } from 'react'\nimport { STORAGE_AVATAR_MAX_SIZE_BYTES, STORAGE_DEFAULT_MAX_SIZE_BYTES } from '../../constants'\nimport type { File as StorageFile } from '../../storage'\nimport { RequireSdk } from '../hooks'\nimport { useStorage } from '../storage-hooks'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\n// ============================================\n// Internal: small upload adapter (legacy DX surface)\n// ============================================\n\ninterface UseUploadAdapterOptions {\n\taccept?: string[]\n\tmaxSize?: number\n\tfolder?: string\n\tonError?: (err: Error) => void\n}\n\ninterface UseUploadAdapter {\n\t/** Upload a file. Resolves to the `StorageFile.url` (or empty string when private). */\n\tupload: (file: File) => Promise<string>\n\tisUploading: boolean\n\tprogress: number\n\terror: Error | null\n}\n\n/**\n * Wrap the new `useStorage()` mutation in the legacy ergonomic surface\n * the UI components were built against.\n */\nfunction useUploadAdapter(options: UseUploadAdapterOptions = {}): UseUploadAdapter {\n\tconst { upload: doUpload, isUploading } = useStorage()\n\tconst [progress, setProgress] = useState(0)\n\tconst [error, setError] = useState<Error | null>(null)\n\n\tconst upload = useCallback(\n\t\tasync (file: File): Promise<string> => {\n\t\t\tsetError(null)\n\t\t\tsetProgress(0)\n\n\t\t\t// Type validation\n\t\t\tif (options.accept && options.accept.length > 0) {\n\t\t\t\tconst accepted = options.accept.some((t) =>\n\t\t\t\t\tt.endsWith('/*') ? file.type.startsWith(t.slice(0, -2)) : file.type === t,\n\t\t\t\t)\n\t\t\t\tif (!accepted) {\n\t\t\t\t\tconst e = new Error(`File type ${file.type} not accepted`)\n\t\t\t\t\tsetError(e)\n\t\t\t\t\toptions.onError?.(e)\n\t\t\t\t\tthrow e\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Size validation\n\t\t\tif (options.maxSize && file.size > options.maxSize) {\n\t\t\t\tconst mb = (options.maxSize / 1024 / 1024).toFixed(1)\n\t\t\t\tconst e = new Error(`File size exceeds ${mb}MB limit`)\n\t\t\t\tsetError(e)\n\t\t\t\toptions.onError?.(e)\n\t\t\t\tthrow e\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst result: StorageFile = await doUpload(file, {\n\t\t\t\t\tfolder: options.folder,\n\t\t\t\t\tonProgress: (e) => {\n\t\t\t\t\t\tsetProgress(e.total > 0 ? Math.round((e.loaded / e.total) * 100) : 0)\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\tsetProgress(100)\n\t\t\t\treturn result.url ?? ''\n\t\t\t} catch (err) {\n\t\t\t\tconst e = err instanceof Error ? err : new Error('Upload failed')\n\t\t\t\tsetError(e)\n\t\t\t\toptions.onError?.(e)\n\t\t\t\tthrow e\n\t\t\t}\n\t\t},\n\t\t[doUpload, options.accept, options.maxSize, options.folder, options.onError],\n\t)\n\n\treturn { upload, isUploading, progress, error }\n}\n\n// ============================================\n// FileUpload\n// ============================================\n\nexport interface FileUploadProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Allowed file types (MIME types) */\n\taccept?: string[]\n\t/** Max file size in bytes */\n\tmaxSize?: number\n\t/** Allow multiple files */\n\tmultiple?: boolean\n\t/** Called when files are uploaded successfully */\n\tonUpload?: (urls: string[]) => void\n\t/** Called when upload fails */\n\tonError?: (error: Error) => void\n\t/** Custom class name */\n\tclassName?: string\n\t/** Disabled state */\n\tdisabled?: boolean\n\t/** Placeholder text */\n\tplaceholder?: string\n\t/** Show file list */\n\tshowFileList?: boolean\n}\n\n/**\n * File Upload component with drag and drop\n *\n * @example\n * ```tsx\n * <FileUpload\n *   accept={['application/pdf', 'image/*']}\n *   maxSize={10 * 1024 * 1024}\n *   onUpload={(urls) => console.log('Uploaded:', urls)}\n * />\n * ```\n */\nexport function FileUpload(props: FileUploadProps) {\n\treturn (\n\t\t<RequireSdk services={['storage']} componentType=\"storage\" theme={props.theme}>\n\t\t\t<FileUploadInner {...props} />\n\t\t</RequireSdk>\n\t)\n}\n\n/** Inner component that safely uses storage hooks */\nfunction FileUploadInner({\n\ttheme = defaultTheme,\n\taccept,\n\tmaxSize,\n\tmultiple = false,\n\tonUpload,\n\tonError,\n\tclassName,\n\tdisabled = false,\n\tplaceholder = 'Drop files here or click to upload',\n\tshowFileList = true,\n}: FileUploadProps) {\n\tconst [isDragging, setIsDragging] = useState(false)\n\tconst [uploadedFiles, setUploadedFiles] = useState<{ name: string; url: string }[]>([])\n\tconst inputRef = useRef<HTMLInputElement>(null)\n\tconst { upload, isUploading, progress, error } = useUploadAdapter({\n\t\taccept,\n\t\tmaxSize,\n\t\tonError,\n\t})\n\tconst styles = baseStyles(theme)\n\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tconst handleFiles = useCallback(\n\t\tasync (files: FileList | null) => {\n\t\t\tif (!files || files.length === 0) return\n\n\t\t\tconst fileArray = Array.from(files)\n\t\t\tconst urls: string[] = []\n\n\t\t\tfor (const file of fileArray) {\n\t\t\t\ttry {\n\t\t\t\t\tconst url = await upload(file)\n\t\t\t\t\turls.push(url)\n\t\t\t\t\tsetUploadedFiles((prev) => [...prev, { name: file.name, url }])\n\t\t\t\t} catch (_err) {\n\t\t\t\t\t// Error surfaced via adapter\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (urls.length > 0) {\n\t\t\t\tonUpload?.(urls)\n\t\t\t}\n\t\t},\n\t\t[upload, onUpload],\n\t)\n\n\tconst handleDrop = useCallback(\n\t\t(e: DragEvent<HTMLElement>) => {\n\t\t\te.preventDefault()\n\t\t\te.stopPropagation()\n\t\t\tsetIsDragging(false)\n\n\t\t\tif (disabled) return\n\t\t\thandleFiles(e.dataTransfer.files)\n\t\t},\n\t\t[handleFiles, disabled],\n\t)\n\n\tconst handleDragOver = useCallback(\n\t\t(e: DragEvent<HTMLElement>) => {\n\t\t\te.preventDefault()\n\t\t\te.stopPropagation()\n\t\t\tif (!disabled) setIsDragging(true)\n\t\t},\n\t\t[disabled],\n\t)\n\n\tconst handleDragLeave = useCallback((e: DragEvent<HTMLElement>) => {\n\t\te.preventDefault()\n\t\te.stopPropagation()\n\t\tsetIsDragging(false)\n\t}, [])\n\n\tconst handleClick = () => {\n\t\tif (!disabled && inputRef.current) {\n\t\t\tinputRef.current.click()\n\t\t}\n\t}\n\n\tconst handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n\t\thandleFiles(e.target.files)\n\t\tif (inputRef.current) {\n\t\t\tinputRef.current.value = ''\n\t\t}\n\t}\n\n\tconst removeFile = (index: number) => {\n\t\tsetUploadedFiles((prev) => prev.filter((_, i) => i !== index))\n\t}\n\n\tconst dropZoneStyle: CSSProperties = mergeStyles(\n\t\t{\n\t\t\tborder: `2px dashed ${isDragging ? theme.colorPrimary : theme.colorBorder}`,\n\t\t\tborderRadius: theme.borderRadiusLg,\n\t\t\tpadding: '2rem',\n\t\t\ttextAlign: 'center',\n\t\t\tcursor: disabled ? 'not-allowed' : 'pointer',\n\t\t\ttransition: 'all 0.2s ease',\n\t\t\tbackgroundColor: isDragging ? `${theme.colorPrimary}08` : theme.colorBackground,\n\t\t\topacity: disabled ? 0.6 : 1,\n\t\t},\n\t\tisUploading ? { pointerEvents: 'none' } : undefined,\n\t)\n\n\tconst acceptString = accept?.join(',')\n\n\treturn (\n\t\t<div className={className} style={{ fontFamily: theme.fontFamily }}>\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tonDrop={handleDrop}\n\t\t\t\tonDragOver={handleDragOver}\n\t\t\t\tonDragLeave={handleDragLeave}\n\t\t\t\tonClick={handleClick}\n\t\t\t\tdisabled={disabled || isUploading}\n\t\t\t\taria-label=\"Upload files\"\n\t\t\t\tstyle={{\n\t\t\t\t\t...dropZoneStyle,\n\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\tfont: 'inherit',\n\t\t\t\t\tcolor: 'inherit',\n\t\t\t\t\twidth: '100%',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<input\n\t\t\t\t\tref={inputRef}\n\t\t\t\t\ttype=\"file\"\n\t\t\t\t\taccept={acceptString}\n\t\t\t\t\tmultiple={multiple}\n\t\t\t\t\tonChange={handleInputChange}\n\t\t\t\t\tstyle={{ display: 'none' }}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t/>\n\n\t\t\t\t{isUploading ? (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\tmarginTop: '0.5rem',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tUploading... {progress}%\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<ProgressBar progress={progress} theme={theme} />\n\t\t\t\t\t</div>\n\t\t\t\t) : (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<UploadIcon color={theme.colorMutedForeground} />\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\tmarginTop: '0.5rem',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{placeholder}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t{maxSize && (\n\t\t\t\t\t\t\t<p style={mergeStyles(styles.textXs, styles.textMuted)}>\n\t\t\t\t\t\t\t\tMax size: {formatFileSize(maxSize)}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</button>\n\n\t\t\t{error && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={mergeStyles(styles.alert, styles.alertError, {\n\t\t\t\t\t\tmarginTop: '0.75rem',\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\t{error.message}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{showFileList && uploadedFiles.length > 0 && (\n\t\t\t\t<div style={{ marginTop: '1rem' }}>\n\t\t\t\t\t{uploadedFiles.map((file, index) => (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tkey={index}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t\t\t\tpadding: '0.5rem 0.75rem',\n\t\t\t\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\t\t\t\t\ttextOverflow: 'ellipsis',\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{file.name}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={() => removeFile(index)}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonGhost, {\n\t\t\t\t\t\t\t\t\tpadding: '0.25rem',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<CloseIcon />\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n// ============================================\n// ImageUploader\n// ============================================\n\nexport interface ImageUploaderProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Max file size in bytes */\n\tmaxSize?: number\n\t/** Current image URL */\n\tvalue?: string | null\n\t/** Called when image is uploaded */\n\tonChange?: (url: string | null) => void\n\t/** Called when upload fails */\n\tonError?: (error: Error) => void\n\t/** Custom class name */\n\tclassName?: string\n\t/** Disabled state */\n\tdisabled?: boolean\n\t/** Aspect ratio (e.g., \"1:1\", \"16:9\") */\n\taspectRatio?: string\n\t/** Placeholder text */\n\tplaceholder?: string\n}\n\n/**\n * Image uploader with preview\n *\n * @example\n * ```tsx\n * const [coverImage, setCoverImage] = useState<string | null>(null)\n *\n * <ImageUploader\n *   value={coverImage}\n *   onChange={setCoverImage}\n *   aspectRatio=\"16:9\"\n *   maxSize={5 * 1024 * 1024}\n * />\n * ```\n */\nexport function ImageUploader(props: ImageUploaderProps) {\n\treturn (\n\t\t<RequireSdk services={['storage']} componentType=\"storage\" theme={props.theme}>\n\t\t\t<ImageUploaderInner {...props} />\n\t\t</RequireSdk>\n\t)\n}\n\n/** Inner component that safely uses storage hooks */\nfunction ImageUploaderInner({\n\ttheme = defaultTheme,\n\tmaxSize = STORAGE_DEFAULT_MAX_SIZE_BYTES,\n\tvalue,\n\tonChange,\n\tonError,\n\tclassName,\n\tdisabled = false,\n\taspectRatio = '1:1',\n\tplaceholder = 'Click to upload image',\n}: ImageUploaderProps) {\n\tconst [previewUrl, setPreviewUrl] = useState<string | null>(value || null)\n\tconst inputRef = useRef<HTMLInputElement>(null)\n\tconst { upload, isUploading, progress, error } = useUploadAdapter({\n\t\taccept: ['image/*'],\n\t\tmaxSize,\n\t\tonError,\n\t})\n\tconst styles = baseStyles(theme)\n\n\tuseEffect(() => {\n\t\tsetPreviewUrl(value || null)\n\t}, [value])\n\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tconst handleFile = async (file: File) => {\n\t\ttry {\n\t\t\t// Create local preview\n\t\t\tconst localUrl = URL.createObjectURL(file)\n\t\t\tsetPreviewUrl(localUrl)\n\n\t\t\t// Upload\n\t\t\tconst url = await upload(file)\n\t\t\tsetPreviewUrl(url)\n\t\t\tonChange?.(url)\n\n\t\t\t// Cleanup local URL\n\t\t\tURL.revokeObjectURL(localUrl)\n\t\t} catch (_err) {\n\t\t\tsetPreviewUrl(value || null)\n\t\t}\n\t}\n\n\tconst handleClick = () => {\n\t\tif (!disabled && inputRef.current) {\n\t\t\tinputRef.current.click()\n\t\t}\n\t}\n\n\tconst handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n\t\tconst file = e.target.files?.[0]\n\t\tif (file) handleFile(file)\n\t\tif (inputRef.current) inputRef.current.value = ''\n\t}\n\n\tconst handleRemove = (e: React.MouseEvent) => {\n\t\te.stopPropagation()\n\t\tsetPreviewUrl(null)\n\t\tonChange?.(null)\n\t}\n\n\t// Calculate aspect ratio\n\tconst [ratioW, ratioH] = aspectRatio.split(':').map(Number)\n\tconst paddingBottom = `${(ratioH / ratioW) * 100}%`\n\n\tconst containerStyle: CSSProperties = {\n\t\tposition: 'relative',\n\t\twidth: '100%',\n\t\tpaddingBottom,\n\t\tborderRadius: theme.borderRadiusLg,\n\t\toverflow: 'hidden',\n\t\tcursor: disabled ? 'not-allowed' : 'pointer',\n\t\topacity: disabled ? 0.6 : 1,\n\t}\n\n\tconst innerStyle: CSSProperties = {\n\t\tposition: 'absolute',\n\t\tinset: 0,\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'center',\n\t\tborder: `2px dashed ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadiusLg,\n\t\tbackgroundColor: theme.colorMuted,\n\t\ttransition: 'all 0.2s ease',\n\t}\n\n\treturn (\n\t\t<div className={className} style={{ fontFamily: theme.fontFamily }}>\n\t\t\t<div style={containerStyle}>\n\t\t\t\t<input\n\t\t\t\t\tref={inputRef}\n\t\t\t\t\ttype=\"file\"\n\t\t\t\t\taccept=\"image/*\"\n\t\t\t\t\tonChange={handleInputChange}\n\t\t\t\t\tstyle={{ display: 'none' }}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t/>\n\n\t\t\t\t{previewUrl && !isUploading ? (\n\t\t\t\t\t<div style={innerStyle} className=\"sylphx-upload-hover\">\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tsrc={previewUrl}\n\t\t\t\t\t\t\talt=\"Preview\"\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\t\theight: '100%',\n\t\t\t\t\t\t\t\tobjectFit: 'cover',\n\t\t\t\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\t\t\t\tinset: 0,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName=\"sylphx-upload-hover__overlay\"\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\t\t\t\tinset: 0,\n\t\t\t\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0.4)',\n\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\tjustifyContent: 'center',\n\t\t\t\t\t\t\t\topacity: 0,\n\t\t\t\t\t\t\t\ttransition: 'opacity 0.2s ease',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={handleRemove}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonDestructive, {\n\t\t\t\t\t\t\t\t\tmarginRight: '0.5rem',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tRemove\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={handleClick}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tReplace\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t) : (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={handleClick}\n\t\t\t\t\t\tdisabled={disabled || isUploading}\n\t\t\t\t\t\taria-label=\"Upload image\"\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t...innerStyle,\n\t\t\t\t\t\t\tfont: 'inherit',\n\t\t\t\t\t\t\tcolor: 'inherit',\n\t\t\t\t\t\t\tcursor: disabled || isUploading ? 'not-allowed' : 'pointer',\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{isUploading ? (\n\t\t\t\t\t\t\t<div style={{ textAlign: 'center' }}>\n\t\t\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\t\t\tmarginTop: '0.5rem',\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{progress}%\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<div style={{ textAlign: 'center' }}>\n\t\t\t\t\t\t\t\t<ImageIcon color={theme.colorMutedForeground} />\n\t\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\t\t\tmarginTop: '0.5rem',\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{placeholder}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</button>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{error && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={mergeStyles(styles.alert, styles.alertError, {\n\t\t\t\t\t\tmarginTop: '0.75rem',\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\t{error.message}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n// ============================================\n// AvatarUpload\n// ============================================\n\nexport interface AvatarUploadProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Max file size in bytes */\n\tmaxSize?: number\n\t/** Current avatar URL */\n\tvalue?: string | null\n\t/** Called when avatar is uploaded */\n\tonChange?: (url: string | null) => void\n\t/** Called when upload fails */\n\tonError?: (error: Error) => void\n\t/** Custom class name */\n\tclassName?: string\n\t/** Disabled state */\n\tdisabled?: boolean\n\t/** Avatar size in pixels */\n\tsize?: number\n\t/** Placeholder initials or name */\n\tplaceholder?: string\n}\n\n/**\n * Circular avatar upload component\n *\n * @example\n * ```tsx\n * const { user, updateProfile } = useUser()\n *\n * <AvatarUpload\n *   value={user.avatarUrl}\n *   onChange={(url) => updateProfile({ avatarUrl: url })}\n *   placeholder={user.name}\n *   size={120}\n * />\n * ```\n */\nexport function AvatarUpload(props: AvatarUploadProps) {\n\treturn (\n\t\t<RequireSdk services={['storage']} componentType=\"storage\" theme={props.theme}>\n\t\t\t<AvatarUploadInner {...props} />\n\t\t</RequireSdk>\n\t)\n}\n\n/** Inner component that safely uses storage hooks */\nfunction AvatarUploadInner({\n\ttheme = defaultTheme,\n\tmaxSize = STORAGE_AVATAR_MAX_SIZE_BYTES,\n\tvalue,\n\tonChange,\n\tonError,\n\tclassName,\n\tdisabled = false,\n\tsize = 96,\n\tplaceholder = '',\n}: AvatarUploadProps) {\n\tconst [previewUrl, setPreviewUrl] = useState<string | null>(value || null)\n\tconst inputRef = useRef<HTMLInputElement>(null)\n\tconst { upload, isUploading, error } = useUploadAdapter({\n\t\taccept: ['image/*'],\n\t\tmaxSize,\n\t\tfolder: 'avatars',\n\t\tonError,\n\t})\n\tconst styles = baseStyles(theme)\n\n\tuseEffect(() => {\n\t\tsetPreviewUrl(value || null)\n\t}, [value])\n\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tconst handleFile = async (file: File) => {\n\t\ttry {\n\t\t\t// Create local preview\n\t\t\tconst localUrl = URL.createObjectURL(file)\n\t\t\tsetPreviewUrl(localUrl)\n\n\t\t\t// Upload\n\t\t\tconst url = await upload(file)\n\t\t\tsetPreviewUrl(url)\n\t\t\tonChange?.(url)\n\n\t\t\t// Cleanup local URL\n\t\t\tURL.revokeObjectURL(localUrl)\n\t\t} catch (err) {\n\t\t\tsetPreviewUrl(value || null)\n\t\t\tonError?.(err instanceof Error ? err : new Error('Upload failed'))\n\t\t}\n\t}\n\n\tconst handleClick = () => {\n\t\tif (!disabled && inputRef.current) {\n\t\t\tinputRef.current.click()\n\t\t}\n\t}\n\n\tconst handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n\t\tconst file = e.target.files?.[0]\n\t\tif (file) handleFile(file)\n\t\tif (inputRef.current) inputRef.current.value = ''\n\t}\n\n\t// Get initials from placeholder\n\tconst initials = placeholder\n\t\t.split(' ')\n\t\t.map((n) => n[0])\n\t\t.join('')\n\t\t.toUpperCase()\n\t\t.slice(0, 2)\n\n\tconst containerStyle: CSSProperties = {\n\t\tposition: 'relative',\n\t\twidth: size,\n\t\theight: size,\n\t\tborderRadius: '50%',\n\t\toverflow: 'hidden',\n\t\tcursor: disabled ? 'not-allowed' : 'pointer',\n\t\topacity: disabled ? 0.6 : 1,\n\t\tflexShrink: 0,\n\t}\n\n\tconst innerStyle: CSSProperties = {\n\t\twidth: '100%',\n\t\theight: '100%',\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'center',\n\t\tbackgroundColor: theme.colorMuted,\n\t\tcolor: theme.colorMutedForeground,\n\t\tfontSize: size * 0.35,\n\t\tfontWeight: 600,\n\t}\n\n\treturn (\n\t\t<div className={className} style={{ fontFamily: theme.fontFamily }}>\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tonClick={handleClick}\n\t\t\t\tdisabled={disabled || isUploading}\n\t\t\t\taria-label=\"Upload avatar\"\n\t\t\t\tclassName=\"sylphx-upload-hover\"\n\t\t\t\tstyle={{\n\t\t\t\t\t...containerStyle,\n\t\t\t\t\tborder: 'none',\n\t\t\t\t\tpadding: 0,\n\t\t\t\t\tbackground: 'transparent',\n\t\t\t\t\tcursor: disabled || isUploading ? 'not-allowed' : 'pointer',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<input\n\t\t\t\t\tref={inputRef}\n\t\t\t\t\ttype=\"file\"\n\t\t\t\t\taccept=\"image/*\"\n\t\t\t\t\tonChange={handleInputChange}\n\t\t\t\t\tstyle={{ display: 'none' }}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t/>\n\n\t\t\t\t<div style={innerStyle}>\n\t\t\t\t\t{isUploading ? (\n\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t) : previewUrl ? (\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tsrc={previewUrl}\n\t\t\t\t\t\t\talt=\"Avatar\"\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\t\theight: '100%',\n\t\t\t\t\t\t\t\tobjectFit: 'cover',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : initials ? (\n\t\t\t\t\t\tinitials\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<UserIcon color={theme.colorMutedForeground} size={size * 0.4} />\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\n\t\t\t\t{/* Hover overlay */}\n\t\t\t\t<div\n\t\t\t\t\tclassName=\"sylphx-upload-hover__overlay\"\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\t\tinset: 0,\n\t\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0.5)',\n\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\tjustifyContent: 'center',\n\t\t\t\t\t\topacity: 0,\n\t\t\t\t\t\ttransition: 'opacity 0.2s ease',\n\t\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<CameraIcon color=\"#fff\" />\n\t\t\t\t</div>\n\t\t\t</button>\n\n\t\t\t{error && (\n\t\t\t\t<p\n\t\t\t\t\tstyle={mergeStyles(styles.textXs, {\n\t\t\t\t\t\tcolor: theme.colorDestructive,\n\t\t\t\t\t\tmarginTop: '0.5rem',\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\t{error.message}\n\t\t\t\t</p>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n// ============================================\n// Helper Components\n// ============================================\n\nfunction ProgressBar({ progress, theme }: { progress: number; theme: ThemeVariables }) {\n\treturn (\n\t\t<div\n\t\t\tstyle={{\n\t\t\t\twidth: '100%',\n\t\t\t\theight: '4px',\n\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\tborderRadius: '2px',\n\t\t\t\tmarginTop: '0.5rem',\n\t\t\t\toverflow: 'hidden',\n\t\t\t}}\n\t\t>\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\twidth: `${progress}%`,\n\t\t\t\t\theight: '100%',\n\t\t\t\t\tbackgroundColor: theme.colorPrimary,\n\t\t\t\t\ttransition: 'width 0.2s ease',\n\t\t\t\t}}\n\t\t\t/>\n\t\t</div>\n\t)\n}\n\nfunction formatFileSize(bytes: number): string {\n\tif (bytes < 1024) return `${bytes} B`\n\tif (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\n// Icons\nfunction UploadIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"40\"\n\t\t\theight=\"40\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"1.5\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4\" />\n\t\t\t<polyline points=\"17 8 12 3 7 8\" />\n\t\t\t<line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\" />\n\t\t</svg>\n\t)\n}\n\nfunction ImageIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"40\"\n\t\t\theight=\"40\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"1.5\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\" />\n\t\t\t<circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\" />\n\t\t\t<polyline points=\"21 15 16 10 5 21\" />\n\t\t</svg>\n\t)\n}\n\nfunction UserIcon({ color, size = 24 }: { color: string; size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"1.5\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2\" />\n\t\t\t<circle cx=\"12\" cy=\"7\" r=\"4\" />\n\t\t</svg>\n\t)\n}\n\nfunction CameraIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"24\"\n\t\t\theight=\"24\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M23 19a2 2 0 01-2 2H3a2 2 0 01-2-2V8a2 2 0 012-2h4l2-3h6l2 3h4a2 2 0 012 2z\" />\n\t\t\t<circle cx=\"12\" cy=\"13\" r=\"4\" />\n\t\t</svg>\n\t)\n}\n\nfunction CloseIcon() {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n\t\t\t<line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n\t\t</svg>\n\t)\n}\n","/**\n * Job Scheduler UI Components\n *\n * UI for scheduling and managing background jobs.\n */\n\n'use client'\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport { type CSSProperties, type FormEvent, useCallback, useEffect, useState } from 'react'\nimport {\n\tSECONDS_PER_HOUR,\n\tSECONDS_PER_MINUTE,\n\tSTALE_TIME_STATS_MS,\n\tUI_FORM_SUCCESS_MS,\n} from '../../constants'\nimport { type Job, type JobStatusFilter, useJobs } from '../job-hooks'\nimport { useJobsContext } from '../services-context'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\n// ============================================\n// Types\n// ============================================\n\nexport interface JobSchedulerProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Custom class name */\n\tclassName?: string\n\t/** Called when job is scheduled */\n\tonSchedule?: (job: Job) => void\n\t/** Default callback URL */\n\tdefaultCallbackUrl?: string\n\t/** Show cron tab */\n\tshowCronTab?: boolean\n}\n\nexport interface JobListProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Custom class name */\n\tclassName?: string\n\t/** Jobs to display */\n\tjobs?: Job[]\n\t/** Called when job is cancelled */\n\tonCancel?: (jobId: string) => void\n\t/** Called when job is retried */\n\tonRetry?: (job: Job) => void\n\t/** Show filters */\n\tshowFilters?: boolean\n\t/** Auto-refresh interval in ms (0 to disable) */\n\trefreshInterval?: number\n\t/** Empty state message */\n\temptyMessage?: string\n}\n\nexport interface CronBuilderProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Custom class name */\n\tclassName?: string\n\t/** Called when cron is created */\n\tonCreate?: (expression: string, callbackUrl: string, name: string) => void\n\t/** Default callback URL */\n\tdefaultCallbackUrl?: string\n}\n\n// ============================================\n// JobScheduler\n// ============================================\n\n/**\n * Schedule a one-time or cron job\n *\n * @example\n * ```tsx\n * <JobScheduler\n *   onSchedule={(job) => console.log('Scheduled:', job)}\n *   defaultCallbackUrl=\"https://api.example.com/webhook\"\n * />\n * ```\n */\nexport function JobScheduler({\n\ttheme = defaultTheme,\n\tclassName,\n\tonSchedule,\n\tdefaultCallbackUrl = '',\n\tshowCronTab = true,\n}: JobSchedulerProps) {\n\tconst { schedule, createCron, isLoading, error } = useJobs()\n\tconst [activeTab, setActiveTab] = useState<'one-time' | 'cron'>('one-time')\n\tconst [name, setName] = useState('')\n\tconst [callbackUrl, setCallbackUrl] = useState(defaultCallbackUrl)\n\tconst [payload, setPayload] = useState('{}')\n\tconst [delay, setDelay] = useState(60)\n\tconst [delayUnit, setDelayUnit] = useState<'seconds' | 'minutes' | 'hours'>('seconds')\n\tconst [cronExpression, setCronExpression] = useState('0 9 * * *')\n\tconst [scheduleSuccess, setScheduleSuccess] = useState(false)\n\n\tconst styles = baseStyles(theme)\n\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tuseEffect(() => {\n\t\tif (scheduleSuccess) {\n\t\t\tconst timer = setTimeout(() => setScheduleSuccess(false), UI_FORM_SUCCESS_MS)\n\t\t\treturn () => clearTimeout(timer)\n\t\t}\n\t}, [scheduleSuccess])\n\n\tconst handleSchedule = async (e: FormEvent) => {\n\t\te.preventDefault()\n\t\tif (!callbackUrl) return\n\n\t\tlet parsedPayload = {}\n\t\ttry {\n\t\t\tparsedPayload = JSON.parse(payload)\n\t\t} catch {\n\t\t\t// Keep empty object\n\t\t}\n\n\t\tconst delaySeconds =\n\t\t\tdelay *\n\t\t\t(delayUnit === 'minutes' ? SECONDS_PER_MINUTE : delayUnit === 'hours' ? SECONDS_PER_HOUR : 1)\n\n\t\tconst result = await schedule({\n\t\t\tcallbackUrl,\n\t\t\tpayload: parsedPayload,\n\t\t\tdelay: delaySeconds,\n\t\t\tname: name || undefined,\n\t\t})\n\n\t\tif (result.jobId) {\n\t\t\tsetScheduleSuccess(true)\n\t\t\tonSchedule?.({\n\t\t\t\tid: result.jobId,\n\t\t\t\tname: name || null,\n\t\t\t\ttype: 'one-time',\n\t\t\t\tstatus: 'pending',\n\t\t\t\tscheduledFor: result.scheduledFor ?? null,\n\t\t\t\tcallbackUrl,\n\t\t\t\tretries: 0,\n\t\t\t\tmaxRetries: 3,\n\t\t\t\tcreatedAt: new Date().toISOString(),\n\t\t\t})\n\t\t}\n\t}\n\n\tconst handleCron = async (e: FormEvent) => {\n\t\te.preventDefault()\n\t\tif (!callbackUrl || !cronExpression) return\n\n\t\tlet parsedPayload = {}\n\t\ttry {\n\t\t\tparsedPayload = JSON.parse(payload)\n\t\t} catch {\n\t\t\t// Keep empty object\n\t\t}\n\n\t\tconst result = await createCron({\n\t\t\tcallbackUrl,\n\t\t\tcron: cronExpression,\n\t\t\tpayload: parsedPayload,\n\t\t\tname: name || `Cron Job ${Date.now()}`,\n\t\t})\n\n\t\tif (result.scheduleId) {\n\t\t\tsetScheduleSuccess(true)\n\t\t}\n\t}\n\n\tconst containerStyle: CSSProperties = {\n\t\tfontFamily: theme.fontFamily,\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t\toverflow: 'hidden',\n\t}\n\n\tconst tabStyle = (isActive: boolean): CSSProperties => ({\n\t\tflex: 1,\n\t\tpadding: '0.75rem',\n\t\tborder: 'none',\n\t\tbackgroundColor: isActive ? theme.colorBackground : theme.colorMuted,\n\t\tcolor: isActive ? theme.colorForeground : theme.colorMutedForeground,\n\t\tfontWeight: isActive ? 600 : 400,\n\t\tfontSize: theme.fontSizeSm,\n\t\tcursor: 'pointer',\n\t\ttransition: 'all 0.15s ease',\n\t})\n\n\tconst inputStyle: CSSProperties = {\n\t\twidth: '100%',\n\t\tpadding: '0.75rem',\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t\tbackgroundColor: theme.colorBackground,\n\t\tcolor: theme.colorForeground,\n\t\tfontSize: theme.fontSizeSm,\n\t\tfontFamily: theme.fontFamily,\n\t}\n\n\treturn (\n\t\t<div style={containerStyle} className={className}>\n\t\t\t{/* Tabs */}\n\t\t\t{showCronTab && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\tborderBottom: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={() => setActiveTab('one-time')}\n\t\t\t\t\t\tstyle={tabStyle(activeTab === 'one-time')}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ClockIcon\n\t\t\t\t\t\t\tcolor={activeTab === 'one-time' ? theme.colorPrimary : theme.colorMutedForeground}\n\t\t\t\t\t\t/>{' '}\n\t\t\t\t\t\tOne-time Job\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={() => setActiveTab('cron')}\n\t\t\t\t\t\tstyle={tabStyle(activeTab === 'cron')}\n\t\t\t\t\t>\n\t\t\t\t\t\t<RepeatIcon\n\t\t\t\t\t\t\tcolor={activeTab === 'cron' ? theme.colorPrimary : theme.colorMutedForeground}\n\t\t\t\t\t\t/>{' '}\n\t\t\t\t\t\tRecurring (Cron)\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t<div style={{ padding: '1.5rem' }}>\n\t\t\t\t{scheduleSuccess && (\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={mergeStyles(styles.alert, styles.alertSuccess, {\n\t\t\t\t\t\t\tmarginBottom: '1rem',\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\tJob scheduled successfully!\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{error && (\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={mergeStyles(styles.alert, styles.alertError, {\n\t\t\t\t\t\t\tmarginBottom: '1rem',\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t{error.message}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t<form onSubmit={activeTab === 'one-time' ? handleSchedule : handleCron}>\n\t\t\t\t\t<div style={{ marginBottom: '1rem' }}>\n\t\t\t\t\t\t{/* biome-ignore lint/a11y/noLabelWithoutControl: legacy UI component */}\n\t\t\t\t\t\t<label\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tJob Name (optional)\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\tvalue={name}\n\t\t\t\t\t\t\tonChange={(e) => setName(e.target.value)}\n\t\t\t\t\t\t\tstyle={inputStyle}\n\t\t\t\t\t\t\tplaceholder=\"send-welcome-email\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div style={{ marginBottom: '1rem' }}>\n\t\t\t\t\t\t{/* biome-ignore lint/a11y/noLabelWithoutControl: legacy UI component */}\n\t\t\t\t\t\t<label\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tCallback URL *\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\ttype=\"url\"\n\t\t\t\t\t\t\tvalue={callbackUrl}\n\t\t\t\t\t\t\tonChange={(e) => setCallbackUrl(e.target.value)}\n\t\t\t\t\t\t\tstyle={inputStyle}\n\t\t\t\t\t\t\tplaceholder=\"https://api.example.com/jobs/callback\"\n\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tWe'll send a POST request to this URL when the job runs\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{activeTab === 'one-time' ? (\n\t\t\t\t\t\t<div style={{ marginBottom: '1rem' }}>\n\t\t\t\t\t\t\t{/* biome-ignore lint/a11y/noLabelWithoutControl: legacy UI component */}\n\t\t\t\t\t\t\t<label\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tDelay\n\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t<div style={{ display: 'flex', gap: '0.5rem' }}>\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t\t\t\t\tvalue={delay}\n\t\t\t\t\t\t\t\t\tonChange={(e) => setDelay(Number.parseInt(e.target.value, 10) || 0)}\n\t\t\t\t\t\t\t\t\tmin={0}\n\t\t\t\t\t\t\t\t\tstyle={{ ...inputStyle, flex: 1 }}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<select\n\t\t\t\t\t\t\t\t\tvalue={delayUnit}\n\t\t\t\t\t\t\t\t\tonChange={(e) => setDelayUnit(e.target.value as 'seconds' | 'minutes' | 'hours')}\n\t\t\t\t\t\t\t\t\tstyle={{ ...inputStyle, flex: 1 }}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<option value=\"seconds\">Seconds</option>\n\t\t\t\t\t\t\t\t\t<option value=\"minutes\">Minutes</option>\n\t\t\t\t\t\t\t\t\t<option value=\"hours\">Hours</option>\n\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<div style={{ marginBottom: '1rem' }}>\n\t\t\t\t\t\t\t{/* biome-ignore lint/a11y/noLabelWithoutControl: legacy UI component */}\n\t\t\t\t\t\t\t<label\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tCron Expression\n\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\tvalue={cronExpression}\n\t\t\t\t\t\t\t\tonChange={(e) => setCronExpression(e.target.value)}\n\t\t\t\t\t\t\t\tstyle={inputStyle}\n\t\t\t\t\t\t\t\tplaceholder=\"0 9 * * *\"\n\t\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tFormat: minute hour day month weekday (e.g., \"0 9 * * *\" = 9:00 AM daily)\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\n\t\t\t\t\t<div style={{ marginBottom: '1.5rem' }}>\n\t\t\t\t\t\t{/* biome-ignore lint/a11y/noLabelWithoutControl: legacy UI component */}\n\t\t\t\t\t\t<label\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tPayload (JSON)\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<textarea\n\t\t\t\t\t\t\tvalue={payload}\n\t\t\t\t\t\t\tonChange={(e) => setPayload(e.target.value)}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t...inputStyle,\n\t\t\t\t\t\t\t\tminHeight: '80px',\n\t\t\t\t\t\t\t\tfontFamily: 'monospace',\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tplaceholder='{\"key\": \"value\"}'\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\tdisabled={isLoading || !callbackUrl}\n\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary, {\n\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t{isLoading ? (\n\t\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t\t) : activeTab === 'one-time' ? (\n\t\t\t\t\t\t\t'Schedule Job'\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t'Create Cron Job'\n\t\t\t\t\t\t)}\n\t\t\t\t\t</button>\n\t\t\t\t</form>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n// ============================================\n// JobList\n// ============================================\n\n/**\n * List of scheduled jobs with status\n *\n * @example\n * ```tsx\n * <JobList\n *   onCancel={(jobId) => cancelJob(jobId)}\n *   showFilters\n *   refreshInterval={5000}\n * />\n * ```\n */\nexport function JobList({\n\ttheme = defaultTheme,\n\tclassName,\n\tjobs: propJobs,\n\tonCancel,\n\tonRetry,\n\tshowFilters = true,\n\trefreshInterval = 0,\n\temptyMessage = 'No jobs scheduled',\n}: JobListProps) {\n\tconst ctx = useJobsContext()\n\tconst queryClient = useQueryClient()\n\t// UI filter includes 'cancelled' for display filtering, but API doesn't support it as a filter\n\tconst [filter, setFilter] = useState<JobStatusFilter | 'cancelled' | 'all'>('all')\n\n\tconst styles = baseStyles(theme)\n\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// React Query for fetching jobs with automatic refresh via refetchInterval\n\tconst jobsQuery = useQuery({\n\t\tqueryKey: ['sylphx', 'jobs', 'list', filter],\n\t\tqueryFn: async () => {\n\t\t\t// API doesn't support 'cancelled' filter, so fetch all and filter client-side\n\t\t\tconst apiStatus = filter === 'all' || filter === 'cancelled' ? undefined : filter\n\t\t\tconst result = await ctx.listJobs({ status: apiStatus })\n\t\t\treturn result.tasks\n\t\t},\n\t\tenabled: !propJobs, // Only fetch if jobs not provided as prop\n\t\tstaleTime: STALE_TIME_STATS_MS, // 30 seconds\n\t\trefetchInterval: !propJobs && refreshInterval > 0 ? refreshInterval : undefined,\n\t})\n\n\t// Use prop jobs if provided, otherwise use query data\n\tconst jobs: Job[] = propJobs ?? jobsQuery.data ?? []\n\tconst isLoading = !propJobs && jobsQuery.isLoading\n\n\tconst filteredJobs = filter === 'all' ? jobs : jobs.filter((j) => j.status === filter)\n\n\t// Mutation for cancelling jobs\n\tconst cancelMutation = useMutation({\n\t\tmutationFn: (jobId: string) => ctx.cancelJob(jobId),\n\t\tonSuccess: () => {\n\t\t\tqueryClient.invalidateQueries({ queryKey: ['sylphx', 'jobs', 'list'] })\n\t\t},\n\t})\n\n\tconst handleCancel = useCallback(\n\t\tasync (jobId: string) => {\n\t\t\tif (onCancel) {\n\t\t\t\tonCancel(jobId)\n\t\t\t} else {\n\t\t\t\tawait cancelMutation.mutateAsync(jobId)\n\t\t\t}\n\t\t},\n\t\t[onCancel, cancelMutation],\n\t)\n\n\tconst statusColors: Record<string, { bg: string; text: string }> = {\n\t\tpending: { bg: `${theme.colorWarning}20`, text: theme.colorWarning },\n\t\tqueued: { bg: `${theme.colorPrimary}20`, text: theme.colorPrimary },\n\t\trunning: { bg: `${theme.colorPrimary}20`, text: theme.colorPrimary },\n\t\tcompleted: { bg: `${theme.colorSuccess}20`, text: theme.colorSuccess },\n\t\tfailed: { bg: `${theme.colorDestructive}20`, text: theme.colorDestructive },\n\t\tscheduled: { bg: `${theme.colorPrimary}20`, text: theme.colorPrimary },\n\t\tpaused: { bg: theme.colorMuted, text: theme.colorMutedForeground },\n\t\tcancelled: { bg: theme.colorMuted, text: theme.colorMutedForeground },\n\t\tdeleted: { bg: theme.colorMuted, text: theme.colorMutedForeground },\n\t}\n\tconst defaultStatusColor = {\n\t\tbg: theme.colorMuted,\n\t\ttext: theme.colorMutedForeground,\n\t}\n\n\tconst containerStyle: CSSProperties = {\n\t\tfontFamily: theme.fontFamily,\n\t}\n\n\tconst jobItemStyle: CSSProperties = {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'space-between',\n\t\tpadding: '1rem',\n\t\tborderBottom: `1px solid ${theme.colorBorder}`,\n\t}\n\n\treturn (\n\t\t<div style={containerStyle} className={className}>\n\t\t\t{showFilters && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\tmarginBottom: '1rem',\n\t\t\t\t\t\tflexWrap: 'wrap',\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{(\n\t\t\t\t\t\t['all', 'pending', 'queued', 'running', 'completed', 'failed', 'cancelled'] as const\n\t\t\t\t\t).map((status) => (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tkey={status}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={() => setFilter(status)}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tpadding: '0.375rem 0.75rem',\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\tborder: `1px solid ${filter === status ? theme.colorPrimary : theme.colorBorder}`,\n\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\tbackgroundColor: filter === status ? `${theme.colorPrimary}10` : 'transparent',\n\t\t\t\t\t\t\t\tcolor: filter === status ? theme.colorPrimary : theme.colorMutedForeground,\n\t\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t\t\ttextTransform: 'capitalize',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{status}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{isLoading && jobs.length === 0 ? (\n\t\t\t\t\t<div style={{ padding: '2rem', textAlign: 'center' }}>\n\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t</div>\n\t\t\t\t) : filteredJobs.length === 0 ? (\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tpadding: '3rem',\n\t\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<JobIcon color={theme.colorMuted} size={48} />\n\t\t\t\t\t\t<p style={{ margin: '1rem 0 0' }}>{emptyMessage}</p>\n\t\t\t\t\t</div>\n\t\t\t\t) : (\n\t\t\t\t\tfilteredJobs.map((job, i) => (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tkey={job.id}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t...jobItemStyle,\n\t\t\t\t\t\t\t\tborderBottom: i === filteredJobs.length - 1 ? 'none' : jobItemStyle.borderBottom,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div style={{ flex: 1, minWidth: 0 }}>\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\t\t\t\tmarginBottom: '0.25rem',\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span style={{ fontWeight: 500, fontSize: theme.fontSizeSm }}>\n\t\t\t\t\t\t\t\t\t\t{job.name || job.id}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\tpadding: '0.125rem 0.375rem',\n\t\t\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: (statusColors[job.status] ?? defaultStatusColor).bg,\n\t\t\t\t\t\t\t\t\t\t\tcolor: (statusColors[job.status] ?? defaultStatusColor).text,\n\t\t\t\t\t\t\t\t\t\t\ttextTransform: 'capitalize',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{job.status}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{job.scheduledFor && `Scheduled: ${new Date(job.scheduledFor).toLocaleString()}`}\n\t\t\t\t\t\t\t\t\t{job.completedAt && ` • Completed: ${new Date(job.completedAt).toLocaleString()}`}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div style={{ display: 'flex', gap: '0.5rem' }}>\n\t\t\t\t\t\t\t\t{job.status === 'pending' && (\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => handleCancel(job.id)}\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\tborder: `1px solid ${theme.colorDestructive}`,\n\t\t\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorDestructive,\n\t\t\t\t\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{job.status === 'failed' && onRetry && (\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => onRetry(job)}\n\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline, {\n\t\t\t\t\t\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tRetry\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n// ============================================\n// CronBuilder (Visual Cron Expression Builder)\n// ============================================\n\nconst CRON_PRESETS = [\n\t{ label: 'Every minute', value: '* * * * *' },\n\t{ label: 'Every hour', value: '0 * * * *' },\n\t{ label: 'Every day at 9am', value: '0 9 * * *' },\n\t{ label: 'Every Monday at 9am', value: '0 9 * * 1' },\n\t{ label: 'First of month at 9am', value: '0 9 1 * *' },\n]\n\n/**\n * Visual cron expression builder\n *\n * @example\n * ```tsx\n * <CronBuilder\n *   onCreate={(cron, url, name) => createCronJob(cron, url, name)}\n * />\n * ```\n */\nexport function CronBuilder({\n\ttheme = defaultTheme,\n\tclassName,\n\tonCreate,\n\tdefaultCallbackUrl = '',\n}: CronBuilderProps) {\n\tconst [expression, setExpression] = useState('0 9 * * *')\n\tconst [callbackUrl, setCallbackUrl] = useState(defaultCallbackUrl)\n\tconst [name, setName] = useState('')\n\n\tconst styles = baseStyles(theme)\n\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tconst handleSubmit = (e: FormEvent) => {\n\t\te.preventDefault()\n\t\tif (expression && callbackUrl) {\n\t\t\tonCreate?.(expression, callbackUrl, name)\n\t\t}\n\t}\n\n\tconst containerStyle: CSSProperties = {\n\t\tfontFamily: theme.fontFamily,\n\t\tpadding: '1.5rem',\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t}\n\n\tconst inputStyle: CSSProperties = {\n\t\twidth: '100%',\n\t\tpadding: '0.75rem',\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t\tbackgroundColor: theme.colorBackground,\n\t\tcolor: theme.colorForeground,\n\t\tfontSize: theme.fontSizeSm,\n\t\tfontFamily: theme.fontFamily,\n\t}\n\n\treturn (\n\t\t<div style={containerStyle} className={className}>\n\t\t\t<h3\n\t\t\t\tstyle={{\n\t\t\t\t\tmargin: '0 0 1rem',\n\t\t\t\t\tfontSize: theme.fontSizeLg,\n\t\t\t\t\tfontWeight: 600,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\tCron Job Builder\n\t\t\t</h3>\n\n\t\t\t{/* Presets */}\n\t\t\t<div style={{ marginBottom: '1.5rem' }}>\n\t\t\t\t{/* biome-ignore lint/a11y/noLabelWithoutControl: legacy UI component */}\n\t\t\t\t<label\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\tQuick Presets\n\t\t\t\t</label>\n\t\t\t\t<div style={{ display: 'flex', gap: '0.5rem', flexWrap: 'wrap' }}>\n\t\t\t\t\t{CRON_PRESETS.map((preset) => (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tkey={preset.value}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={() => setExpression(preset.value)}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tpadding: '0.375rem 0.75rem',\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\tborder: `1px solid ${expression === preset.value ? theme.colorPrimary : theme.colorBorder}`,\n\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\tbackgroundColor:\n\t\t\t\t\t\t\t\t\texpression === preset.value ? `${theme.colorPrimary}10` : 'transparent',\n\t\t\t\t\t\t\t\tcolor: expression === preset.value ? theme.colorPrimary : theme.colorForeground,\n\t\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{preset.label}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<form onSubmit={handleSubmit}>\n\t\t\t\t<div style={{ marginBottom: '1rem' }}>\n\t\t\t\t\t{/* biome-ignore lint/a11y/noLabelWithoutControl: legacy UI component */}\n\t\t\t\t\t<label\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tCron Expression\n\t\t\t\t\t</label>\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tvalue={expression}\n\t\t\t\t\t\tonChange={(e) => setExpression(e.target.value)}\n\t\t\t\t\t\tstyle={{ ...inputStyle, fontFamily: 'monospace' }}\n\t\t\t\t\t\tplaceholder=\"* * * * *\"\n\t\t\t\t\t\trequired\n\t\t\t\t\t/>\n\t\t\t\t\t<p\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tminute (0-59) | hour (0-23) | day (1-31) | month (1-12) | weekday (0-6, Sun=0)\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\n\t\t\t\t<div style={{ marginBottom: '1rem' }}>\n\t\t\t\t\t{/* biome-ignore lint/a11y/noLabelWithoutControl: legacy UI component */}\n\t\t\t\t\t<label\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tName\n\t\t\t\t\t</label>\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tvalue={name}\n\t\t\t\t\t\tonChange={(e) => setName(e.target.value)}\n\t\t\t\t\t\tstyle={inputStyle}\n\t\t\t\t\t\tplaceholder=\"daily-report\"\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\n\t\t\t\t<div style={{ marginBottom: '1.5rem' }}>\n\t\t\t\t\t{/* biome-ignore lint/a11y/noLabelWithoutControl: legacy UI component */}\n\t\t\t\t\t<label\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tCallback URL\n\t\t\t\t\t</label>\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"url\"\n\t\t\t\t\t\tvalue={callbackUrl}\n\t\t\t\t\t\tonChange={(e) => setCallbackUrl(e.target.value)}\n\t\t\t\t\t\tstyle={inputStyle}\n\t\t\t\t\t\tplaceholder=\"https://api.example.com/cron/daily-report\"\n\t\t\t\t\t\trequired\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\n\t\t\t\t<button\n\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\tdisabled={!expression || !callbackUrl}\n\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary, {\n\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\tCreate Cron Job\n\t\t\t\t</button>\n\t\t\t</form>\n\t\t</div>\n\t)\n}\n\n// ============================================\n// Icons\n// ============================================\n\nfunction ClockIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\trole=\"img\"\n\t\t\taria-label=\"Icon\"\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tstyle={{ verticalAlign: 'middle' }}\n\t\t>\n\t\t\t<circle cx=\"12\" cy=\"12\" r=\"10\" />\n\t\t\t<polyline points=\"12 6 12 12 16 14\" />\n\t\t</svg>\n\t)\n}\n\nfunction RepeatIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\trole=\"img\"\n\t\t\taria-label=\"Icon\"\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tstyle={{ verticalAlign: 'middle' }}\n\t\t>\n\t\t\t<polyline points=\"17 1 21 5 17 9\" />\n\t\t\t<path d=\"M3 11V9a4 4 0 0 1 4-4h14\" />\n\t\t\t<polyline points=\"7 23 3 19 7 15\" />\n\t\t\t<path d=\"M21 13v2a4 4 0 0 1-4 4H3\" />\n\t\t</svg>\n\t)\n}\n\nfunction JobIcon({ color, size = 24 }: { color: string; size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\trole=\"img\"\n\t\t\taria-label=\"Task\"\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t>\n\t\t\t<rect x=\"2\" y=\"7\" width=\"20\" height=\"14\" rx=\"2\" ry=\"2\" />\n\t\t\t<path d=\"M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16\" />\n\t\t</svg>\n\t)\n}\n\n/** @deprecated Use TaskScheduler instead */\nexport const TaskScheduler = JobScheduler\n/** @deprecated Use TaskSchedulerProps instead */\nexport type TaskSchedulerProps = JobSchedulerProps\n","/**\n * Background Job Hooks\n *\n * React hooks for Sylphx Platform background jobs.\n * Schedule one-time or cron jobs via the platform.\n *\n * Uses proper React Context pattern (no module singletons).\n */\n\n'use client'\n\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { JOB_POLL_INTERVAL_MS } from '../constants'\nimport { type Job, type JobStatus, type JobStatusFilter, useJobsContext } from './services-context'\nimport type {\n\tCreateCronInput,\n\tCreateCronResult,\n\tScheduleJobInput,\n\tScheduleJobResult,\n} from './types'\n\n// Re-export types for convenience\nexport type {\n\tJobStatus,\n\tJobStatusFilter,\n\tJob,\n\tScheduleJobInput,\n\tScheduleJobResult,\n\tCreateCronInput,\n\tCreateCronResult,\n}\n\n// ============================================\n// useJobs\n// ============================================\n\nexport interface UseJobsReturn {\n\t/** Check if background jobs are available */\n\tisAvailable: () => Promise<boolean>\n\t/** Schedule a one-time job */\n\tschedule: (options: ScheduleJobInput) => Promise<ScheduleJobResult>\n\t/** Create a recurring cron job */\n\tcreateCron: (options: CreateCronInput) => Promise<CreateCronResult>\n\t/** Pause a cron job */\n\tpauseCron: (scheduleId: string) => Promise<boolean>\n\t/** Resume a paused cron job */\n\tresumeCron: (scheduleId: string) => Promise<boolean>\n\t/** Delete a cron job */\n\tdeleteCron: (scheduleId: string) => Promise<boolean>\n\t/** Get job status */\n\tgetJob: (jobId: string) => Promise<Job>\n\t/** List jobs */\n\tlistJobs: (options?: {\n\t\tstatus?: JobStatusFilter\n\t\ttype?: 'one-time' | 'cron'\n\t\tlimit?: number\n\t\toffset?: number\n\t}) => Promise<Job[]>\n\t/** Cancel a pending, running, waiting, or failed task run */\n\tcancelJob: (jobId: string) => Promise<boolean>\n\t/** Whether a job operation is in progress */\n\tisLoading: boolean\n\t/** Last error */\n\terror: Error | null\n}\n\n/**\n * Hook for background job management\n *\n * @example\n * ```tsx\n * function JobScheduler() {\n *   const { schedule, createCron, isLoading } = useJobs()\n *\n *   const handleSchedule = async () => {\n *     // Schedule a job to run in 1 hour\n *     const result = await schedule({\n *       callbackUrl: 'https://myapp.com/api/process',\n *       payload: { orderId: '123' },\n *       delay: 3600, // 1 hour\n *       name: 'process-order',\n *     })\n *     console.log('Scheduled job:', result.jobId)\n *   }\n *\n *   const handleCron = async () => {\n *     // Create a job that runs every day at 9am\n *     const result = await createCron({\n *       callbackUrl: 'https://myapp.com/api/daily-report',\n *       cron: '0 9 * * *',\n *       name: 'daily-report',\n *     })\n *     console.log('Created cron:', result.scheduleId)\n *   }\n *\n *   return (\n *     <div>\n *       <button onClick={handleSchedule} disabled={isLoading}>\n *         Schedule Job\n *       </button>\n *       <button onClick={handleCron} disabled={isLoading}>\n *         Create Cron\n *       </button>\n *     </div>\n *   )\n * }\n * ```\n */\nexport function useJobs(): UseJobsReturn {\n\tconst ctx = useJobsContext()\n\tconst [isLoading, setIsLoading] = useState(false)\n\tconst [error, setError] = useState<Error | null>(null)\n\n\tconst isAvailable = useCallback(async (): Promise<boolean> => {\n\t\ttry {\n\t\t\tconst status = await ctx.checkStatus()\n\t\t\treturn status.available\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}, [ctx])\n\n\tconst schedule = useCallback(\n\t\tasync (options: ScheduleJobInput): Promise<ScheduleJobResult> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\treturn await ctx.schedule(options)\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to schedule job')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst createCron = useCallback(\n\t\tasync (options: CreateCronInput): Promise<CreateCronResult> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\treturn await ctx.createCron(options)\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to create cron job')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst pauseCron = useCallback(\n\t\tasync (scheduleId: string): Promise<boolean> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\treturn await ctx.pauseCron(scheduleId)\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to pause cron')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst resumeCron = useCallback(\n\t\tasync (scheduleId: string): Promise<boolean> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\treturn await ctx.resumeCron(scheduleId)\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to resume cron')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst deleteCron = useCallback(\n\t\tasync (scheduleId: string): Promise<boolean> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\treturn await ctx.deleteCron(scheduleId)\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to delete cron')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst getJob = useCallback(\n\t\tasync (jobId: string): Promise<Job> => {\n\t\t\ttry {\n\t\t\t\treturn await ctx.getJob(jobId)\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to get job')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst listJobs = useCallback(\n\t\tasync (\n\t\t\toptions: {\n\t\t\t\tstatus?: JobStatusFilter\n\t\t\t\ttype?: 'one-time' | 'cron'\n\t\t\t\tlimit?: number\n\t\t\t\toffset?: number\n\t\t\t} = {},\n\t\t): Promise<Job[]> => {\n\t\t\ttry {\n\t\t\t\tconst result = await ctx.listJobs(options)\n\t\t\t\treturn result.tasks\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to list jobs')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\tconst cancelJob = useCallback(\n\t\tasync (jobId: string): Promise<boolean> => {\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\treturn await ctx.cancelJob(jobId)\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to cancel job')\n\t\t\t\tsetError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[ctx],\n\t)\n\n\treturn {\n\t\tisAvailable,\n\t\tschedule,\n\t\tcreateCron,\n\t\tpauseCron,\n\t\tresumeCron,\n\t\tdeleteCron,\n\t\tgetJob,\n\t\tlistJobs,\n\t\tcancelJob,\n\t\tisLoading,\n\t\terror,\n\t}\n}\n\n// ============================================\n// useJobProgress\n// ============================================\n\ntype JobPhase = 'pending' | 'queued' | 'running' | 'completed' | 'failed' | 'cancelled'\n\ninterface JobProgress {\n\t/** Current phase of the job */\n\tphase: JobPhase\n\t/** Progress percentage (0-100), estimated based on phase */\n\tprogress: number\n\t/** Whether the job is still in progress */\n\tisInProgress: boolean\n\t/** Whether the job completed successfully */\n\tisComplete: boolean\n\t/** Whether the job failed */\n\tisFailed: boolean\n\t/** Time elapsed since job was scheduled (ms) */\n\telapsedMs: number\n\t/** Estimated time remaining (ms), null if unknown */\n\testimatedRemainingMs: number | null\n}\n\ninterface UseJobProgressOptions {\n\t/** Polling interval in ms (default: 2000) */\n\tpollInterval?: number\n\t/** Stop polling when job completes (default: true) */\n\tstopOnComplete?: boolean\n\t/** Maximum poll attempts before stopping (default: 100) */\n\tmaxPolls?: number\n\t/** Callback when job completes successfully */\n\tonComplete?: (job: Job) => void\n\t/** Callback when job fails */\n\tonFailed?: (job: Job, error: string | null) => void\n\t/** Callback when job status changes */\n\tonStatusChange?: (job: Job, previousStatus: JobStatus | null) => void\n}\n\ninterface UseJobProgressReturn {\n\t/** Current job data (null until first fetch) */\n\tjob: Job | null\n\t/** Progress information */\n\tprogress: JobProgress\n\t/** Whether currently fetching job status */\n\tisPolling: boolean\n\t/** Last error */\n\terror: Error | null\n\t/** Start polling for job progress */\n\tstart: () => void\n\t/** Stop polling */\n\tstop: () => void\n\t/** Manually refresh job status */\n\trefresh: () => Promise<void>\n}\n\n/**\n * Hook for tracking job progress with polling\n *\n * Uses React Query for automatic polling with configurable interval.\n * Automatically stops polling when job completes, fails, or is cancelled.\n *\n * @example\n * ```tsx\n * function JobTracker({ jobId }: { jobId: string }) {\n *   const { job, progress, isPolling, error } = useJobProgress(jobId, {\n *     pollInterval: 1000,\n *     onComplete: (job) => console.log('Job completed!', job),\n *     onFailed: (job, error) => console.error('Job failed:', error),\n *   })\n *\n *   if (error) return <div>Error: {error.message}</div>\n *   if (!job) return <div>Loading...</div>\n *\n *   return (\n *     <div>\n *       <p>Status: {progress.phase}</p>\n *       <progress value={progress.progress} max={100} />\n *       <p>{progress.progress}% complete</p>\n *       {progress.isInProgress && (\n *         <p>Elapsed: {Math.round(progress.elapsedMs / 1000)}s</p>\n *       )}\n *     </div>\n *   )\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With schedule + tracking\n * function ScheduleAndTrack() {\n *   const { schedule } = useJobs()\n *   const [jobId, setJobId] = useState<string | null>(null)\n *\n *   // Only start tracking when we have a jobId\n *   const { progress, job } = useJobProgress(jobId, {\n *     onComplete: () => toast.success('Job completed!'),\n *   })\n *\n *   const handleSchedule = async () => {\n *     const result = await schedule({\n *       callbackUrl: '/api/process',\n *       payload: { data: 'test' },\n *     })\n *     setJobId(result.jobId)\n *   }\n *\n *   return (\n *     <div>\n *       <button onClick={handleSchedule}>Schedule Job</button>\n *       {jobId && (\n *         <div>\n *           <p>Progress: {progress.progress}%</p>\n *           {progress.isComplete && <p>✓ Done!</p>}\n *         </div>\n *       )}\n *     </div>\n *   )\n * }\n * ```\n */\nfunction useJobProgress(\n\tjobId: string | null | undefined,\n\toptions: UseJobProgressOptions = {},\n): UseJobProgressReturn {\n\tconst {\n\t\tpollInterval = JOB_POLL_INTERVAL_MS,\n\t\tstopOnComplete = true,\n\t\tmaxPolls = 100,\n\t\tonComplete,\n\t\tonFailed,\n\t\tonStatusChange,\n\t} = options\n\n\tconst ctx = useJobsContext()\n\tconst queryClient = useQueryClient()\n\n\t// Track whether we should continue polling\n\tconst [shouldPoll, setShouldPoll] = useState(!!jobId)\n\tconst pollCountRef = useRef(0)\n\tconst previousStatusRef = useRef<JobStatus | null>(null)\n\tconst startTimeRef = useRef<number>(Date.now())\n\tconst callbacksFiredRef = useRef<{ complete: boolean; failed: boolean }>({\n\t\tcomplete: false,\n\t\tfailed: false,\n\t})\n\n\t// Reset state when jobId changes\n\tuseEffect(() => {\n\t\tif (jobId) {\n\t\t\tsetShouldPoll(true)\n\t\t\tpollCountRef.current = 0\n\t\t\tstartTimeRef.current = Date.now()\n\t\t\tpreviousStatusRef.current = null\n\t\t\tcallbacksFiredRef.current = { complete: false, failed: false }\n\t\t} else {\n\t\t\tsetShouldPoll(false)\n\t\t}\n\t}, [jobId])\n\n\t// React Query for job polling\n\tconst jobQuery = useQuery({\n\t\tqueryKey: ['sylphx', 'job', 'progress', jobId],\n\t\tqueryFn: () => ctx.getJob(jobId!),\n\t\tenabled: !!jobId && shouldPoll,\n\t\tstaleTime: 0, // Always refetch for progress tracking\n\t\trefetchInterval: shouldPoll ? pollInterval : false,\n\t})\n\n\tconst job = jobQuery.data ?? null\n\n\t// Handle status changes and callbacks\n\tuseEffect(() => {\n\t\tif (!job) return\n\n\t\tconst currentStatus = job.status as JobStatus\n\t\tpollCountRef.current++\n\n\t\t// Fire status change callback\n\t\tif (previousStatusRef.current !== currentStatus) {\n\t\t\tonStatusChange?.(job, previousStatusRef.current)\n\t\t\tpreviousStatusRef.current = currentStatus\n\t\t}\n\n\t\t// Handle terminal states\n\t\tconst isTerminal = ['completed', 'failed', 'cancelled'].includes(currentStatus)\n\n\t\tif (currentStatus === 'completed' && !callbacksFiredRef.current.complete) {\n\t\t\tcallbacksFiredRef.current.complete = true\n\t\t\tonComplete?.(job)\n\t\t} else if (currentStatus === 'failed' && !callbacksFiredRef.current.failed) {\n\t\t\tcallbacksFiredRef.current.failed = true\n\t\t\tonFailed?.(job, job.lastError ?? null)\n\t\t}\n\n\t\t// Stop polling on terminal state or max polls reached\n\t\tif ((isTerminal && stopOnComplete) || pollCountRef.current >= maxPolls) {\n\t\t\tsetShouldPoll(false)\n\t\t}\n\t}, [job, stopOnComplete, maxPolls, onComplete, onFailed, onStatusChange])\n\n\t// Calculate progress based on job status\n\tconst calculateProgress = useCallback((job: Job | null): JobProgress => {\n\t\tconst now = Date.now()\n\t\tconst startTime = startTimeRef.current\n\n\t\tif (!job) {\n\t\t\treturn {\n\t\t\t\tphase: 'pending',\n\t\t\t\tprogress: 0,\n\t\t\t\tisInProgress: false,\n\t\t\t\tisComplete: false,\n\t\t\t\tisFailed: false,\n\t\t\t\telapsedMs: 0,\n\t\t\t\testimatedRemainingMs: null,\n\t\t\t}\n\t\t}\n\n\t\tconst status = job.status as JobStatus\n\t\tconst elapsedMs = now - startTime\n\n\t\t// Map status to phase and progress\n\t\tlet phase: JobPhase\n\t\tlet progress: number\n\t\tlet isInProgress: boolean\n\t\tlet isComplete: boolean\n\t\tlet isFailed: boolean\n\n\t\tswitch (status) {\n\t\t\tcase 'pending':\n\t\t\t\tphase = 'pending'\n\t\t\t\tprogress = 10\n\t\t\t\tisInProgress = true\n\t\t\t\tisComplete = false\n\t\t\t\tisFailed = false\n\t\t\t\tbreak\n\t\t\tcase 'queued':\n\t\t\t\tphase = 'queued'\n\t\t\t\tprogress = 25\n\t\t\t\tisInProgress = true\n\t\t\t\tisComplete = false\n\t\t\t\tisFailed = false\n\t\t\t\tbreak\n\t\t\tcase 'running':\n\t\t\t\tphase = 'running'\n\t\t\t\tprogress = 50 // Could be enhanced with actual progress from job metadata\n\t\t\t\tisInProgress = true\n\t\t\t\tisComplete = false\n\t\t\t\tisFailed = false\n\t\t\t\tbreak\n\t\t\tcase 'completed':\n\t\t\t\tphase = 'completed'\n\t\t\t\tprogress = 100\n\t\t\t\tisInProgress = false\n\t\t\t\tisComplete = true\n\t\t\t\tisFailed = false\n\t\t\t\tbreak\n\t\t\tcase 'failed':\n\t\t\t\tphase = 'failed'\n\t\t\t\tprogress = 0\n\t\t\t\tisInProgress = false\n\t\t\t\tisComplete = false\n\t\t\t\tisFailed = true\n\t\t\t\tbreak\n\t\t\tcase 'cancelled':\n\t\t\t\tphase = 'cancelled'\n\t\t\t\tprogress = 0\n\t\t\t\tisInProgress = false\n\t\t\t\tisComplete = false\n\t\t\t\tisFailed = false\n\t\t\t\tbreak\n\t\t\tdefault:\n\t\t\t\tphase = 'pending'\n\t\t\t\tprogress = 0\n\t\t\t\tisInProgress = true\n\t\t\t\tisComplete = false\n\t\t\t\tisFailed = false\n\t\t}\n\n\t\t// Estimate remaining time based on average completion time\n\t\tlet estimatedRemainingMs: number | null = null\n\t\tif (isInProgress && elapsedMs > 0 && progress > 0 && progress < 100) {\n\t\t\tconst progressRate = progress / elapsedMs\n\t\t\tconst remainingProgress = 100 - progress\n\t\t\testimatedRemainingMs = Math.round(remainingProgress / progressRate)\n\t\t}\n\n\t\treturn {\n\t\t\tphase,\n\t\t\tprogress,\n\t\t\tisInProgress,\n\t\t\tisComplete,\n\t\t\tisFailed,\n\t\t\telapsedMs,\n\t\t\testimatedRemainingMs,\n\t\t}\n\t}, [])\n\n\t// Start polling\n\tconst start = useCallback(() => {\n\t\tif (!jobId) return\n\t\tpollCountRef.current = 0\n\t\tstartTimeRef.current = Date.now()\n\t\tcallbacksFiredRef.current = { complete: false, failed: false }\n\t\tsetShouldPoll(true)\n\t}, [jobId])\n\n\t// Stop polling\n\tconst stop = useCallback(() => {\n\t\tsetShouldPoll(false)\n\t}, [])\n\n\t// Manual refresh via React Query invalidation\n\tconst refresh = useCallback(async () => {\n\t\tawait queryClient.invalidateQueries({\n\t\t\tqueryKey: ['sylphx', 'job', 'progress', jobId],\n\t\t})\n\t}, [queryClient, jobId])\n\n\tconst progress = calculateProgress(job)\n\n\treturn {\n\t\tjob,\n\t\tprogress,\n\t\tisPolling: shouldPoll && jobQuery.isFetching,\n\t\terror: jobQuery.error as Error | null,\n\t\tstart,\n\t\tstop,\n\t\trefresh,\n\t}\n}\n\n// ============================================\n// useScheduleWithProgress\n// ============================================\n\ninterface UseScheduleWithProgressOptions extends UseJobProgressOptions {\n\t/** Auto-start tracking after scheduling */\n\tautoStart?: boolean\n}\n\ninterface UseScheduleWithProgressReturn {\n\t/** Schedule a job and start tracking */\n\tscheduleAndTrack: (options: ScheduleJobInput) => Promise<ScheduleJobResult>\n\t/** Current job being tracked */\n\tjob: Job | null\n\t/** Progress information */\n\tprogress: JobProgress\n\t/** Job ID of the scheduled job */\n\tjobId: string | null\n\t/** Whether scheduling is in progress */\n\tisScheduling: boolean\n\t/** Whether polling job status */\n\tisPolling: boolean\n\t/** Last error */\n\terror: Error | null\n\t/** Reset the tracker to initial state */\n\treset: () => void\n}\n\n/**\n * Convenience hook that combines scheduling and progress tracking\n *\n * @example\n * ```tsx\n * function ProcessOrder({ orderId }: { orderId: string }) {\n *   const {\n *     scheduleAndTrack,\n *     progress,\n *     isScheduling,\n *     isPolling,\n *     reset,\n *   } = useScheduleWithProgress({\n *     onComplete: () => toast.success('Order processed!'),\n *     onFailed: (job, error) => toast.error(`Failed: ${error}`),\n *   })\n *\n *   const handleProcess = async () => {\n *     await scheduleAndTrack({\n *       callbackUrl: '/api/process-order',\n *       payload: { orderId },\n *       name: `process-order-${orderId}`,\n *     })\n *   }\n *\n *   return (\n *     <div>\n *       <button onClick={handleProcess} disabled={isScheduling || isPolling}>\n *         {isScheduling ? 'Scheduling...' : isPolling ? 'Processing...' : 'Process Order'}\n *       </button>\n *\n *       {progress.isInProgress && (\n *         <div>\n *           <progress value={progress.progress} max={100} />\n *           <span>{progress.phase}</span>\n *         </div>\n *       )}\n *\n *       {progress.isComplete && (\n *         <div>\n *           <p>✓ Order processed successfully!</p>\n *           <button onClick={reset}>Process Another</button>\n *         </div>\n *       )}\n *\n *       {progress.isFailed && (\n *         <div>\n *           <p>❌ Processing failed</p>\n *           <button onClick={reset}>Try Again</button>\n *         </div>\n *       )}\n *     </div>\n *   )\n * }\n * ```\n */\nfunction _useScheduleWithProgress(\n\toptions: UseScheduleWithProgressOptions = {},\n): UseScheduleWithProgressReturn {\n\tconst { autoStart = true, ...progressOptions } = options\n\n\tconst { schedule } = useJobs()\n\tconst [jobId, setJobId] = useState<string | null>(null)\n\tconst [isScheduling, setIsScheduling] = useState(false)\n\tconst [scheduleError, setScheduleError] = useState<Error | null>(null)\n\n\tconst {\n\t\tjob,\n\t\tprogress,\n\t\tisPolling,\n\t\terror: progressError,\n\t\tstart,\n\t} = useJobProgress(autoStart ? jobId : null, progressOptions)\n\n\tconst scheduleAndTrack = useCallback(\n\t\tasync (scheduleOptions: ScheduleJobInput): Promise<ScheduleJobResult> => {\n\t\t\tsetIsScheduling(true)\n\t\t\tsetScheduleError(null)\n\n\t\t\ttry {\n\t\t\t\tconst result = await schedule(scheduleOptions)\n\t\t\t\tsetJobId(result.jobId)\n\n\t\t\t\t// If autoStart is false, manually start polling\n\t\t\t\tif (!autoStart) {\n\t\t\t\t\tstart()\n\t\t\t\t}\n\n\t\t\t\treturn result\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error('Failed to schedule job')\n\t\t\t\tsetScheduleError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tsetIsScheduling(false)\n\t\t\t}\n\t\t},\n\t\t[schedule, autoStart, start],\n\t)\n\n\tconst reset = useCallback(() => {\n\t\tsetJobId(null)\n\t\tsetIsScheduling(false)\n\t\tsetScheduleError(null)\n\t}, [])\n\n\treturn {\n\t\tscheduleAndTrack,\n\t\tjob,\n\t\tprogress,\n\t\tjobId,\n\t\tisScheduling,\n\t\tisPolling,\n\t\terror: scheduleError ?? progressError,\n\t\treset,\n\t}\n}\n","/**\n * AI Model Selector Component\n *\n * Browse and select from available AI models.\n * Supports filtering by capability and search.\n */\n\n'use client'\n\nimport { useEffect, useRef, useState } from 'react'\nimport { useModels } from '../ai-hooks'\nimport type { AIModelInfo } from '../types'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\nexport interface ModelSelectorProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Called when a model is selected */\n\tonSelect: (model: AIModelInfo) => void\n\t/** Currently selected model ID */\n\tvalue?: string\n\t/** Filter by capability */\n\tcapability?: 'chat' | 'vision' | 'tool' | 'embedding'\n\t/** Placeholder text */\n\tplaceholder?: string\n\t/** Whether the selector is disabled */\n\tdisabled?: boolean\n\t/** Custom class name */\n\tclassName?: string\n\t/** Show pricing info */\n\tshowPricing?: boolean\n\t/** Show context window */\n\tshowContextWindow?: boolean\n\t/** Compact mode (for inline use) */\n\tcompact?: boolean\n}\n\n/**\n * AI Model Selector\n *\n * @example\n * ```tsx\n * function ChatConfig() {\n *   const [model, setModel] = useState<AIModelInfo | null>(null)\n *\n *   return (\n *     <ModelSelector\n *       capability=\"chat\"\n *       onSelect={setModel}\n *       value={model?.id}\n *       showPricing\n *       showContextWindow\n *     />\n *   )\n * }\n * ```\n */\nexport function ModelSelector({\n\ttheme = defaultTheme,\n\tonSelect,\n\tvalue,\n\tcapability,\n\tplaceholder = 'Select a model...',\n\tdisabled = false,\n\tclassName,\n\tshowPricing = true,\n\tshowContextWindow = true,\n\tcompact = false,\n}: ModelSelectorProps) {\n\tconst styles = baseStyles(theme)\n\tconst [isOpen, setIsOpen] = useState(false)\n\tconst [searchValue, setSearchValue] = useState('')\n\tconst containerRef = useRef<HTMLDivElement>(null)\n\tconst inputRef = useRef<HTMLInputElement>(null)\n\n\tconst { models, isLoading, error, setSearch, hasMore, loadMore } = useModels({\n\t\tcapability,\n\t\tfetchOnMount: true,\n\t\tpageSize: 50,\n\t})\n\n\t// Find selected model\n\tconst selectedModel = models.find((m) => m.id === value)\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// Close on outside click\n\tuseEffect(() => {\n\t\tconst handleClickOutside = (event: MouseEvent) => {\n\t\t\tif (containerRef.current && !containerRef.current.contains(event.target as Node)) {\n\t\t\t\tsetIsOpen(false)\n\t\t\t}\n\t\t}\n\n\t\tdocument.addEventListener('mousedown', handleClickOutside)\n\t\treturn () => document.removeEventListener('mousedown', handleClickOutside)\n\t}, [])\n\n\t// Handle search input\n\tconst handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n\t\tconst value = e.target.value\n\t\tsetSearchValue(value)\n\t\tsetSearch(value)\n\t}\n\n\t// Handle model selection\n\tconst handleSelect = (model: AIModelInfo) => {\n\t\tonSelect(model)\n\t\tsetIsOpen(false)\n\t\tsetSearchValue('')\n\t\tsetSearch('')\n\t}\n\n\t// Handle scroll for infinite loading\n\tconst handleScroll = (e: React.UIEvent<HTMLDivElement>) => {\n\t\tconst target = e.target as HTMLDivElement\n\t\tconst bottom = target.scrollHeight - target.scrollTop <= target.clientHeight + 50\n\t\tif (bottom && hasMore && !isLoading) {\n\t\t\tloadMore()\n\t\t}\n\t}\n\n\t// Format context window\n\tconst formatContext = (tokens: number) => {\n\t\tif (tokens >= 1000000) {\n\t\t\treturn `${(tokens / 1000000).toFixed(1)}M`\n\t\t}\n\t\tif (tokens >= 1000) {\n\t\t\treturn `${(tokens / 1000).toFixed(0)}K`\n\t\t}\n\t\treturn tokens.toString()\n\t}\n\n\t// Format price\n\tconst formatPrice = (pricePerMillion: number) => {\n\t\tif (pricePerMillion === 0) return 'Free'\n\t\tif (pricePerMillion < 0.01) return `$${pricePerMillion.toFixed(4)}`\n\t\tif (pricePerMillion < 1) return `$${pricePerMillion.toFixed(2)}`\n\t\treturn `$${pricePerMillion.toFixed(1)}`\n\t}\n\n\t// Get capability badge color\n\tconst getCapabilityColor = (cap: string) => {\n\t\tswitch (cap) {\n\t\t\tcase 'chat':\n\t\t\t\treturn theme.colorPrimary\n\t\t\tcase 'vision':\n\t\t\t\treturn '#9333ea' // purple\n\t\t\tcase 'tool':\n\t\t\t\treturn '#059669' // green\n\t\t\tcase 'embedding':\n\t\t\t\treturn '#d97706' // amber\n\t\t\tdefault:\n\t\t\t\treturn theme.colorMuted\n\t\t}\n\t}\n\n\tconst containerStyles: React.CSSProperties = {\n\t\tposition: 'relative',\n\t\twidth: '100%',\n\t}\n\n\tconst triggerStyles: React.CSSProperties = mergeStyles(styles.input, {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'space-between',\n\t\tcursor: disabled ? 'not-allowed' : 'pointer',\n\t\topacity: disabled ? 0.5 : 1,\n\t\tpadding: compact ? '0.5rem 0.75rem' : '0.75rem 1rem',\n\t\ttextAlign: 'left',\n\t\tfont: 'inherit',\n\t\tcolor: 'inherit',\n\t})\n\n\tconst dropdownStyles: React.CSSProperties = {\n\t\tposition: 'absolute',\n\t\ttop: '100%',\n\t\tleft: 0,\n\t\tright: 0,\n\t\tmarginTop: '0.25rem',\n\t\tbackgroundColor: theme.colorBackground,\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t\tboxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',\n\t\tzIndex: 50,\n\t\tmaxHeight: '400px',\n\t\toverflow: 'hidden',\n\t\tdisplay: 'flex',\n\t\tflexDirection: 'column',\n\t}\n\n\tconst searchInputStyles: React.CSSProperties = mergeStyles(styles.input, {\n\t\tmargin: '0.5rem',\n\t\tmarginBottom: 0,\n\t\twidth: 'calc(100% - 1rem)',\n\t})\n\n\tconst listStyles: React.CSSProperties = {\n\t\toverflowY: 'auto',\n\t\tmaxHeight: '340px',\n\t\tpadding: '0.5rem',\n\t}\n\n\tconst itemStyles = (isSelected: boolean): React.CSSProperties => ({\n\t\tdisplay: 'flex',\n\t\tflexDirection: 'column',\n\t\tpadding: '0.75rem',\n\t\tborderRadius: theme.borderRadius,\n\t\tcursor: 'pointer',\n\t\tbackgroundColor: isSelected ? `${theme.colorPrimary}10` : 'transparent',\n\t\tborder: isSelected ? `1px solid ${theme.colorPrimary}30` : '1px solid transparent',\n\t\tmarginBottom: '0.25rem',\n\t\ttransition: 'background-color 0.15s',\n\t})\n\n\tconst badgeStyles = (color: string): React.CSSProperties => ({\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\tpadding: '0.125rem 0.375rem',\n\t\tborderRadius: '9999px',\n\t\tfontSize: '0.625rem',\n\t\tfontWeight: 500,\n\t\tbackgroundColor: `${color}15`,\n\t\tcolor,\n\t\ttextTransform: 'uppercase',\n\t\tletterSpacing: '0.05em',\n\t})\n\n\treturn (\n\t\t<div ref={containerRef} style={containerStyles} className={className}>\n\t\t\t{/* Trigger */}\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tstyle={triggerStyles}\n\t\t\t\tonClick={() => !disabled && setIsOpen(!isOpen)}\n\t\t\t\tdisabled={disabled}\n\t\t\t\taria-haspopup=\"listbox\"\n\t\t\t\taria-expanded={isOpen}\n\t\t\t>\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\tflex: 1,\n\t\t\t\t\t\tminWidth: 0,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{selectedModel ? (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\t\t\t\t\ttextOverflow: 'ellipsis',\n\t\t\t\t\t\t\t\t\twhiteSpace: 'nowrap',\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{selectedModel.name}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t{!compact && showContextWindow && (\n\t\t\t\t\t\t\t\t<span style={mergeStyles(styles.textXs, styles.textMuted)}>\n\t\t\t\t\t\t\t\t\t{formatContext(selectedModel.contextWindow)} tokens\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<span style={styles.textMuted}>{placeholder}</span>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<ChevronIcon direction={isOpen ? 'up' : 'down'} />\n\t\t\t</button>\n\n\t\t\t{/* Dropdown */}\n\t\t\t{isOpen && (\n\t\t\t\t<div style={dropdownStyles}>\n\t\t\t\t\t{/* Search input */}\n\t\t\t\t\t<input\n\t\t\t\t\t\tref={inputRef}\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tvalue={searchValue}\n\t\t\t\t\t\tonChange={handleSearchChange}\n\t\t\t\t\t\tplaceholder=\"Search models...\"\n\t\t\t\t\t\tstyle={searchInputStyles}\n\t\t\t\t\t/>\n\n\t\t\t\t\t{/* Model list */}\n\t\t\t\t\t<div role=\"listbox\" style={listStyles} onScroll={handleScroll}>\n\t\t\t\t\t\t{error && (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.alert, styles.alertError, {\n\t\t\t\t\t\t\t\t\tmargin: '0.5rem',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{error.message}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{models.length === 0 && !isLoading && (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textCenter, styles.textMuted, {\n\t\t\t\t\t\t\t\t\tpadding: '2rem',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tNo models found\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{models.map((model) => (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\tkey={model.id}\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\trole=\"option\"\n\t\t\t\t\t\t\t\taria-selected={model.id === value}\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t...itemStyles(model.id === value),\n\t\t\t\t\t\t\t\t\ttextAlign: 'left',\n\t\t\t\t\t\t\t\t\tfont: 'inherit',\n\t\t\t\t\t\t\t\t\tcolor: 'inherit',\n\t\t\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tonClick={() => handleSelect(model)}\n\t\t\t\t\t\t\t\tonMouseEnter={(e) => {\n\t\t\t\t\t\t\t\t\tif (model.id !== value) {\n\t\t\t\t\t\t\t\t\t\te.currentTarget.style.backgroundColor = theme.colorMuted\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tonMouseLeave={(e) => {\n\t\t\t\t\t\t\t\t\tif (model.id !== value) {\n\t\t\t\t\t\t\t\t\t\te.currentTarget.style.backgroundColor = 'transparent'\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{/* Model name and ID */}\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t\t\t\t\t\tmarginBottom: '0.25rem',\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span style={{ fontWeight: 500 }}>{model.name}</span>\n\t\t\t\t\t\t\t\t\t{showContextWindow && (\n\t\t\t\t\t\t\t\t\t\t<span style={mergeStyles(styles.textXs, styles.textMuted)}>\n\t\t\t\t\t\t\t\t\t\t\t{formatContext(model.contextWindow)} tokens\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t{/* Model ID */}\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textXs, styles.textMuted, {\n\t\t\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\t\t\tfontFamily: 'monospace',\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{model.id}\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t{/* Capabilities and pricing */}\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{/* Capabilities */}\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\t\tgap: '0.25rem',\n\t\t\t\t\t\t\t\t\t\t\tflexWrap: 'wrap',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{model.capabilities.map((cap) => (\n\t\t\t\t\t\t\t\t\t\t\t<span key={cap} style={badgeStyles(getCapabilityColor(cap))}>\n\t\t\t\t\t\t\t\t\t\t\t\t{cap}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t\t{/* Pricing */}\n\t\t\t\t\t\t\t\t\t{showPricing && (\n\t\t\t\t\t\t\t\t\t\t<div style={mergeStyles(styles.textXs, styles.textMuted)}>\n\t\t\t\t\t\t\t\t\t\t\t{formatPrice(model.inputCostPer1M ?? 0)}/\n\t\t\t\t\t\t\t\t\t\t\t{formatPrice(model.outputCostPer1M ?? 0)} per 1M\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t{/* Description */}\n\t\t\t\t\t\t\t\t{model.description && (\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textXs, styles.textMuted, {\n\t\t\t\t\t\t\t\t\t\t\tmarginTop: '0.5rem',\n\t\t\t\t\t\t\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\t\t\t\t\t\t\ttextOverflow: 'ellipsis',\n\t\t\t\t\t\t\t\t\t\t\tdisplay: '-webkit-box',\n\t\t\t\t\t\t\t\t\t\t\tWebkitLineClamp: 2,\n\t\t\t\t\t\t\t\t\t\t\tWebkitBoxOrient: 'vertical',\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{model.description}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t))}\n\n\t\t\t\t\t\t{/* Loading indicator */}\n\t\t\t\t\t\t{isLoading && (\n\t\t\t\t\t\t\t<div style={mergeStyles(styles.flexCenter, { padding: '1rem' })}>\n\t\t\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n// Icons\nfunction ChevronIcon({ direction }: { direction: 'up' | 'down' }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tstyle={{ transform: direction === 'up' ? 'rotate(180deg)' : undefined }}\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<polyline points=\"6 9 12 15 18 9\" />\n\t\t</svg>\n\t)\n}\n\n/**\n * Model Card Component\n *\n * Display a single model in a card format.\n */\nexport interface ModelCardProps {\n\tmodel: AIModelInfo\n\ttheme?: ThemeVariables\n\tonSelect?: () => void\n\tselected?: boolean\n\tshowPricing?: boolean\n\tclassName?: string\n}\n\nexport function ModelCard({\n\tmodel,\n\ttheme = defaultTheme,\n\tonSelect,\n\tselected = false,\n\tshowPricing = true,\n\tclassName,\n}: ModelCardProps) {\n\tconst styles = baseStyles(theme)\n\n\t// Format context window\n\tconst formatContext = (tokens: number) => {\n\t\tif (tokens >= 1000000) return `${(tokens / 1000000).toFixed(1)}M`\n\t\tif (tokens >= 1000) return `${(tokens / 1000).toFixed(0)}K`\n\t\treturn tokens.toString()\n\t}\n\n\t// Format price\n\tconst formatPrice = (pricePerMillion: number) => {\n\t\tif (pricePerMillion === 0) return 'Free'\n\t\tif (pricePerMillion < 0.01) return `$${pricePerMillion.toFixed(4)}`\n\t\tif (pricePerMillion < 1) return `$${pricePerMillion.toFixed(2)}`\n\t\treturn `$${pricePerMillion.toFixed(1)}`\n\t}\n\n\t// Get capability badge color\n\tconst getCapabilityColor = (cap: string) => {\n\t\tswitch (cap) {\n\t\t\tcase 'chat':\n\t\t\t\treturn theme.colorPrimary\n\t\t\tcase 'vision':\n\t\t\t\treturn '#9333ea'\n\t\t\tcase 'tool':\n\t\t\t\treturn '#059669'\n\t\t\tcase 'embedding':\n\t\t\t\treturn '#d97706'\n\t\t\tdefault:\n\t\t\t\treturn theme.colorMuted\n\t\t}\n\t}\n\n\tconst cardStyles: React.CSSProperties = mergeStyles(styles.card, {\n\t\tpadding: '1rem',\n\t\tcursor: onSelect ? 'pointer' : 'default',\n\t\tborder: selected ? `2px solid ${theme.colorPrimary}` : `1px solid ${theme.colorBorder}`,\n\t\ttransition: 'border-color 0.15s, box-shadow 0.15s',\n\t})\n\n\tconst badgeStyles = (color: string): React.CSSProperties => ({\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\tpadding: '0.125rem 0.375rem',\n\t\tborderRadius: '9999px',\n\t\tfontSize: '0.625rem',\n\t\tfontWeight: 500,\n\t\tbackgroundColor: `${color}15`,\n\t\tcolor,\n\t\ttextTransform: 'uppercase',\n\t\tletterSpacing: '0.05em',\n\t})\n\n\tconst CardTag = onSelect ? 'button' : 'div'\n\tconst cardInteractiveProps = onSelect\n\t\t? {\n\t\t\t\ttype: 'button' as const,\n\t\t\t\tonClick: onSelect,\n\t\t\t\t'aria-pressed': selected,\n\t\t\t}\n\t\t: {}\n\n\treturn (\n\t\t<CardTag\n\t\t\t{...cardInteractiveProps}\n\t\t\tstyle={{\n\t\t\t\t...cardStyles,\n\t\t\t\t...(onSelect\n\t\t\t\t\t? {\n\t\t\t\t\t\t\ttextAlign: 'left',\n\t\t\t\t\t\t\tfont: 'inherit',\n\t\t\t\t\t\t\tcolor: 'inherit',\n\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t}}\n\t\t\tclassName={className}\n\t\t\tonMouseEnter={(e) => {\n\t\t\t\tif (onSelect && !selected) {\n\t\t\t\t\te.currentTarget.style.borderColor = theme.colorPrimary\n\t\t\t\t}\n\t\t\t}}\n\t\t\tonMouseLeave={(e) => {\n\t\t\t\tif (!selected) {\n\t\t\t\t\te.currentTarget.style.borderColor = theme.colorBorder\n\t\t\t\t}\n\t\t\t}}\n\t\t>\n\t\t\t{/* Header */}\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\talignItems: 'flex-start',\n\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div>\n\t\t\t\t\t<h4 style={{ margin: 0, fontSize: theme.fontSizeBase, fontWeight: 600 }}>{model.name}</h4>\n\t\t\t\t\t<p\n\t\t\t\t\t\tstyle={mergeStyles(styles.textXs, styles.textMuted, {\n\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\tfontFamily: 'monospace',\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t{model.id}\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t\t<span style={mergeStyles(styles.textSm, styles.textMuted)}>\n\t\t\t\t\t{formatContext(model.contextWindow)} tokens\n\t\t\t\t</span>\n\t\t\t</div>\n\n\t\t\t{/* Capabilities */}\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\tgap: '0.25rem',\n\t\t\t\t\tmarginBottom: '0.75rem',\n\t\t\t\t\tflexWrap: 'wrap',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{model.capabilities.map((cap) => (\n\t\t\t\t\t<span key={cap} style={badgeStyles(getCapabilityColor(cap))}>\n\t\t\t\t\t\t{cap}\n\t\t\t\t\t</span>\n\t\t\t\t))}\n\t\t\t</div>\n\n\t\t\t{/* Description */}\n\t\t\t{model.description && (\n\t\t\t\t<p\n\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\tmargin: '0 0 0.75rem',\n\t\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\t\ttextOverflow: 'ellipsis',\n\t\t\t\t\t\tdisplay: '-webkit-box',\n\t\t\t\t\t\tWebkitLineClamp: 2,\n\t\t\t\t\t\tWebkitBoxOrient: 'vertical',\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\t{model.description}\n\t\t\t\t</p>\n\t\t\t)}\n\n\t\t\t{/* Pricing */}\n\t\t\t{showPricing && (\n\t\t\t\t<div style={{ display: 'flex', gap: '1rem' }}>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<span style={mergeStyles(styles.textXs, styles.textMuted)}>Input</span>\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tmargin: '0.125rem 0 0',\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{formatPrice(model.inputCostPer1M ?? 0)}/1M\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<span style={mergeStyles(styles.textXs, styles.textMuted)}>Output</span>\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tmargin: '0.125rem 0 0',\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{formatPrice(model.outputCostPer1M ?? 0)}/1M\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</CardTag>\n\t)\n}\n\n/**\n * Model Grid Component\n *\n * Display models in a grid layout with filtering.\n */\nexport interface ModelGridProps {\n\ttheme?: ThemeVariables\n\tonSelect: (model: AIModelInfo) => void\n\tvalue?: string\n\tcapability?: 'chat' | 'vision' | 'tool' | 'embedding'\n\tshowPricing?: boolean\n\tcolumns?: 1 | 2 | 3 | 4\n\tclassName?: string\n}\n\nexport function ModelGrid({\n\ttheme = defaultTheme,\n\tonSelect,\n\tvalue,\n\tcapability,\n\tshowPricing = true,\n\tcolumns = 3,\n\tclassName,\n}: ModelGridProps) {\n\tconst styles = baseStyles(theme)\n\tconst { models, isLoading, error, setSearch, setCapability, hasMore, loadMore, total } =\n\t\tuseModels({\n\t\t\tcapability,\n\t\t\tfetchOnMount: true,\n\t\t\tpageSize: 24,\n\t\t})\n\n\tconst [searchValue, setSearchValue] = useState('')\n\tconst [filterCapability, setFilterCapability] = useState(capability)\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// Handle search\n\tconst handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n\t\tconst value = e.target.value\n\t\tsetSearchValue(value)\n\t\tsetSearch(value)\n\t}\n\n\t// Handle capability filter\n\tconst handleCapabilityChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n\t\tconst value = e.target.value as 'chat' | 'vision' | 'tool' | 'embedding' | ''\n\t\tsetFilterCapability(value || undefined)\n\t\tsetCapability(value || undefined)\n\t}\n\n\tconst gridStyles: React.CSSProperties = {\n\t\tdisplay: 'grid',\n\t\tgridTemplateColumns: `repeat(${columns}, 1fr)`,\n\t\tgap: '1rem',\n\t}\n\n\treturn (\n\t\t<div className={className}>\n\t\t\t{/* Filters */}\n\t\t\t<div\n\t\t\t\tstyle={mergeStyles(styles.flexRow, {\n\t\t\t\t\tgap: '1rem',\n\t\t\t\t\tmarginBottom: '1.5rem',\n\t\t\t\t\tflexWrap: 'wrap',\n\t\t\t\t})}\n\t\t\t>\n\t\t\t\t<div style={{ flex: 1, minWidth: '200px' }}>\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tvalue={searchValue}\n\t\t\t\t\t\tonChange={handleSearchChange}\n\t\t\t\t\t\tplaceholder=\"Search models...\"\n\t\t\t\t\t\tstyle={mergeStyles(styles.input, { width: '100%' })}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t\t<select\n\t\t\t\t\tvalue={filterCapability || ''}\n\t\t\t\t\tonChange={handleCapabilityChange}\n\t\t\t\t\tstyle={mergeStyles(styles.input, { minWidth: '150px' })}\n\t\t\t\t>\n\t\t\t\t\t<option value=\"\">All capabilities</option>\n\t\t\t\t\t<option value=\"chat\">Chat</option>\n\t\t\t\t\t<option value=\"vision\">Vision</option>\n\t\t\t\t\t<option value=\"tool\">Tool Use</option>\n\t\t\t\t\t<option value=\"embedding\">Embedding</option>\n\t\t\t\t</select>\n\t\t\t\t<span\n\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\talignSelf: 'center',\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\t{total} models\n\t\t\t\t</span>\n\t\t\t</div>\n\n\t\t\t{/* Error */}\n\t\t\t{error && (\n\t\t\t\t<div style={mergeStyles(styles.alert, styles.alertError, styles.mb4)}>{error.message}</div>\n\t\t\t)}\n\n\t\t\t{/* Grid */}\n\t\t\t<div style={gridStyles}>\n\t\t\t\t{models.map((model) => (\n\t\t\t\t\t<ModelCard\n\t\t\t\t\t\tkey={model.id}\n\t\t\t\t\t\tmodel={model}\n\t\t\t\t\t\ttheme={theme}\n\t\t\t\t\t\tonSelect={() => onSelect(model)}\n\t\t\t\t\t\tselected={model.id === value}\n\t\t\t\t\t\tshowPricing={showPricing}\n\t\t\t\t\t/>\n\t\t\t\t))}\n\t\t\t</div>\n\n\t\t\t{/* Loading / Load more */}\n\t\t\t{isLoading ? (\n\t\t\t\t<div style={mergeStyles(styles.flexCenter, { padding: '2rem' })}>\n\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t</div>\n\t\t\t) : hasMore ? (\n\t\t\t\t<div style={mergeStyles(styles.flexCenter, { padding: '1.5rem' })}>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={loadMore}\n\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline)}\n\t\t\t\t\t>\n\t\t\t\t\t\tLoad more models\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t) : null}\n\n\t\t\t{/* Empty state */}\n\t\t\t{!isLoading && models.length === 0 && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={mergeStyles(styles.textCenter, styles.textMuted, {\n\t\t\t\t\t\tpadding: '3rem',\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\tNo models found matching your criteria\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n","/**\n * Newsletter Form Component (Part of Email Service)\n *\n * Email capture form with validation and double opt-in support.\n * Self-contained with CSS-in-JS styles.\n *\n * Newsletter is a sub-feature of the Email service for marketing/bulk emails.\n */\n\n'use client'\n\nimport { EMAIL_REGEX } from '@sylphx/contract'\nimport { useEffect, useState } from 'react'\nimport { useSubscriberForm } from '../newsletter-hooks'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\nexport interface NewsletterFormProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Called on successful subscription */\n\tonSuccess?: (email: string) => void\n\t/** Called on error */\n\tonError?: (error: string) => void\n\t/** Custom class name */\n\tclassName?: string\n\t/** Form title */\n\ttitle?: string\n\t/** Form description */\n\tdescription?: string\n\t/** Placeholder text */\n\tplaceholder?: string\n\t/** Submit button text */\n\tbuttonText?: string\n\t/** Success message */\n\tsuccessMessage?: string\n\t/** Available preference options */\n\tpreferenceOptions?: Array<{\n\t\tid: string\n\t\tlabel: string\n\t\tdescription?: string\n\t}>\n\t/** Show preference checkboxes */\n\tshowPreferences?: boolean\n\t/** Require at least one preference */\n\trequirePreference?: boolean\n\t/** Show privacy policy link */\n\tshowPrivacy?: boolean\n\t/** Privacy policy URL */\n\tprivacyUrl?: string\n\t/** Layout style */\n\tlayout?: 'inline' | 'stacked'\n}\n\n/**\n * Newsletter subscription form\n *\n * @example\n * ```tsx\n * <NewsletterForm\n *   title=\"Stay Updated\"\n *   description=\"Get the latest news and updates\"\n *   preferenceOptions={[\n *     { id: 'product', label: 'Product Updates' },\n *     { id: 'blog', label: 'Blog Posts' },\n *   ]}\n * />\n * ```\n */\nexport function NewsletterForm({\n\ttheme = defaultTheme,\n\tonSuccess,\n\tonError,\n\tclassName,\n\ttitle,\n\tdescription = 'Subscribe to our newsletter',\n\tplaceholder = 'Enter your email',\n\tbuttonText = 'Subscribe',\n\tsuccessMessage = 'Thanks for subscribing! Please check your email to confirm.',\n\tpreferenceOptions = [],\n\tshowPreferences = false,\n\trequirePreference = false,\n\tshowPrivacy = false,\n\tprivacyUrl = '/privacy',\n\tlayout = 'stacked',\n}: NewsletterFormProps) {\n\tconst {\n\t\temail,\n\t\tsetEmail,\n\t\tpreferences,\n\t\ttogglePreference,\n\t\tsubmit,\n\t\tisLoading,\n\t\terror: formError,\n\t\tsuccess,\n\t\treset,\n\t} = useSubscriberForm()\n\n\tconst styles = baseStyles(theme)\n\tconst [localError, setLocalError] = useState<string | null>(null)\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// Handle success callback\n\tuseEffect(() => {\n\t\tif (success && onSuccess) {\n\t\t\tonSuccess(email)\n\t\t}\n\t}, [success, email, onSuccess])\n\n\t// Handle error callback\n\tuseEffect(() => {\n\t\tif (formError && onError) {\n\t\t\tonError(formError.message)\n\t\t}\n\t}, [formError, onError])\n\n\tconst handleSubmit = async (e: React.FormEvent) => {\n\t\te.preventDefault()\n\t\tsetLocalError(null)\n\n\t\t// Validate email\n\t\tif (!email || !EMAIL_REGEX.test(email)) {\n\t\t\tsetLocalError('Please enter a valid email address')\n\t\t\treturn\n\t\t}\n\n\t\t// Validate preferences if required\n\t\tif (\n\t\t\trequirePreference &&\n\t\t\tshowPreferences &&\n\t\t\tObject.values(preferences).filter(Boolean).length === 0\n\t\t) {\n\t\t\tsetLocalError('Please select at least one preference')\n\t\t\treturn\n\t\t}\n\n\t\tawait submit()\n\t}\n\n\tconst errorMessage = localError || (formError ? formError.message : null)\n\n\tif (success) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName={className}\n\t\t\t\tstyle={mergeStyles(styles.card, {\n\t\t\t\t\ttextAlign: 'center' as const,\n\t\t\t\t\tpadding: '2rem',\n\t\t\t\t})}\n\t\t\t>\n\t\t\t\t<div style={{ color: theme.colorSuccess }}>\n\t\t\t\t\t<svg\n\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\twidth=\"48\"\n\t\t\t\t\t\theight=\"48\"\n\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\tfocusable=\"false\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\" />\n\t\t\t\t\t\t<polyline points=\"22 4 12 14.01 9 11.01\" />\n\t\t\t\t\t</svg>\n\t\t\t\t</div>\n\t\t\t\t<p\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t\t\tcolor: theme.colorSuccess,\n\t\t\t\t\t\tfontSize: theme.fontSizeBase,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{successMessage}\n\t\t\t\t</p>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={reset}\n\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonSecondary, {\n\t\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\tSubscribe another email\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t)\n\t}\n\n\treturn (\n\t\t<div className={className} style={mergeStyles(styles.card, { padding: '1.5rem' })}>\n\t\t\t{title && <h3 style={styles.cardTitle}>{title}</h3>}\n\t\t\t{description && <p style={styles.cardDescription}>{description}</p>}\n\n\t\t\t<form onSubmit={handleSubmit} style={{ marginTop: '1rem' }}>\n\t\t\t\t<div style={layout === 'inline' ? { display: 'flex', gap: '0.5rem' } : undefined}>\n\t\t\t\t\t<div style={layout === 'inline' ? { flex: 1 } : { marginBottom: '1rem' }}>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\ttype=\"email\"\n\t\t\t\t\t\t\tvalue={email}\n\t\t\t\t\t\t\tonChange={(e) => setEmail(e.target.value)}\n\t\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.input, errorMessage ? styles.inputError : {})}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\t\tstyles.buttonPrimary,\n\t\t\t\t\t\t\tisLoading ? styles.buttonDisabled : {},\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{isLoading ? <span style={styles.spinner} /> : buttonText}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\n\t\t\t\t{showPreferences && preferenceOptions.length > 0 && (\n\t\t\t\t\t<div style={{ marginTop: '1rem' }}>\n\t\t\t\t\t\t<p style={mergeStyles(styles.label, { marginBottom: '0.5rem' })}>\n\t\t\t\t\t\t\tEmail preferences{' '}\n\t\t\t\t\t\t\t{requirePreference && <span style={{ color: theme.colorDestructive }}>*</span>}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t{preferenceOptions.map((option) => (\n\t\t\t\t\t\t\t<label\n\t\t\t\t\t\t\t\tkey={option.id}\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\talignItems: 'flex-start',\n\t\t\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\t\tchecked={preferences[option.id] ?? false}\n\t\t\t\t\t\t\t\t\tonChange={() => togglePreference(option.id)}\n\t\t\t\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\t\t\t\tstyle={{ marginTop: '0.25rem' }}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t<span style={{ fontSize: theme.fontSizeBase }}>{option.label}</span>\n\t\t\t\t\t\t\t\t\t{option.description && (\n\t\t\t\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\t\t\t\t\tmarginTop: '0.125rem',\n\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{option.description}\n\t\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{errorMessage && (\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={mergeStyles(styles.alert, styles.alertError, {\n\t\t\t\t\t\t\tmarginTop: '0.5rem',\n\t\t\t\t\t\t\tmarginBottom: 0,\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t{errorMessage}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{showPrivacy && (\n\t\t\t\t\t<p\n\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\tBy subscribing, you agree to our{' '}\n\t\t\t\t\t\t<a href={privacyUrl} style={styles.link} target=\"_blank\" rel=\"noopener noreferrer\">\n\t\t\t\t\t\t\tPrivacy Policy\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</p>\n\t\t\t\t)}\n\t\t\t</form>\n\t\t</div>\n\t)\n}\n","/**\n * Notification Settings Component\n *\n * Push and email notification preferences management.\n * Self-contained with CSS-in-JS styles.\n */\n\n'use client'\n\nimport { useEffect, useState } from 'react'\nimport { UI_NOTIFICATION_MS } from '../../constants'\nimport { useNotifications } from '../platform-hooks'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\nexport interface NotificationSettingsProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Called on successful update */\n\tonSuccess?: (message: string) => void\n\t/** Called on error */\n\tonError?: (error: string) => void\n\t/** Custom class name */\n\tclassName?: string\n\t/** Show push notification settings */\n\tshowPush?: boolean\n\t/** Show email notification settings */\n\tshowEmail?: boolean\n}\n\n/**\n * Notification preferences component\n *\n * @example\n * ```tsx\n * <NotificationSettings\n *   onSuccess={(msg) => toast.success(msg)}\n *   onError={(msg) => toast.error(msg)}\n * />\n * ```\n */\nexport function NotificationSettings({\n\ttheme = defaultTheme,\n\tonSuccess,\n\tonError,\n\tclassName,\n\tshowPush = true,\n\tshowEmail = true,\n}: NotificationSettingsProps) {\n\tconst {\n\t\tisSupported,\n\t\tisSubscribed,\n\t\tpreferences,\n\t\terror: pushError,\n\t\tsubscribe,\n\t\tunsubscribe,\n\t\tupdatePreferences,\n\t} = useNotifications()\n\tconst styles = baseStyles(theme)\n\n\tconst [error, setError] = useState<string | null>(null)\n\tconst [success, setSuccess] = useState<string | null>(null)\n\tconst [isTogglingPush, setIsTogglingPush] = useState(false)\n\tconst [localPrefs, setLocalPrefs] = useState<Record<string, boolean>>(\n\t\t() => preferences?.categories ?? {},\n\t)\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// Sync preferences\n\tuseEffect(() => {\n\t\tif (preferences?.categories) {\n\t\t\tsetLocalPrefs(preferences.categories)\n\t\t}\n\t}, [preferences])\n\n\t// Clear messages after timeout\n\tuseEffect(() => {\n\t\tif (success || error) {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tsetSuccess(null)\n\t\t\t\tsetError(null)\n\t\t\t}, UI_NOTIFICATION_MS)\n\t\t\treturn () => clearTimeout(timer)\n\t\t}\n\t}, [success, error])\n\n\t// Toggle push notifications\n\tconst handleTogglePush = async () => {\n\t\tsetIsTogglingPush(true)\n\t\tsetError(null)\n\n\t\ttry {\n\t\t\tif (isSubscribed) {\n\t\t\t\tawait unsubscribe()\n\t\t\t\tsetSuccess('Push notifications disabled')\n\t\t\t\tonSuccess?.('Push notifications disabled')\n\t\t\t} else {\n\t\t\t\tconst result = await subscribe()\n\t\t\t\tif (result) {\n\t\t\t\t\tsetSuccess('Push notifications enabled')\n\t\t\t\t\tonSuccess?.('Push notifications enabled')\n\t\t\t\t} else {\n\t\t\t\t\tsetError('Failed to enable push notifications. Please check your browser permissions.')\n\t\t\t\t\tonError?.('Failed to enable push notifications')\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to toggle push notifications'\n\t\t\tsetError(message)\n\t\t\tonError?.(message)\n\t\t} finally {\n\t\t\tsetIsTogglingPush(false)\n\t\t}\n\t}\n\n\t// Update email preferences\n\tconst handlePreferenceChange = async (key: string, value: boolean) => {\n\t\tconst newPrefs = { ...localPrefs, [key]: value }\n\t\tsetLocalPrefs(newPrefs)\n\n\t\ttry {\n\t\t\tawait updatePreferences({ categories: newPrefs })\n\t\t\tsetSuccess('Preferences updated')\n\t\t\tonSuccess?.('Preferences updated')\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to update preferences'\n\t\t\tsetError(message)\n\t\t\tonError?.(message)\n\t\t\t// Revert on error\n\t\t\tsetLocalPrefs(localPrefs)\n\t\t}\n\t}\n\n\tconst cardStyles: React.CSSProperties = mergeStyles(styles.card, {\n\t\tpadding: '1rem',\n\t\tmarginBottom: '1rem',\n\t})\n\n\treturn (\n\t\t<div className={className}>\n\t\t\t{/* Alerts */}\n\t\t\t{success && (\n\t\t\t\t<div style={mergeStyles(styles.alert, styles.alertSuccess, styles.mb4)}>{success}</div>\n\t\t\t)}\n\t\t\t{(error || pushError) && (\n\t\t\t\t<div style={mergeStyles(styles.alert, styles.alertError, styles.mb4)}>\n\t\t\t\t\t{error || pushError?.message}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Push Notifications */}\n\t\t\t{showPush && (\n\t\t\t\t<div style={cardStyles}>\n\t\t\t\t\t<div style={styles.flexBetween}>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<h4 style={{ margin: 0, fontWeight: 500 }}>Push Notifications</h4>\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{isSupported\n\t\t\t\t\t\t\t\t\t? isSubscribed\n\t\t\t\t\t\t\t\t\t\t? 'Receive instant notifications in your browser'\n\t\t\t\t\t\t\t\t\t\t: 'Enable browser push notifications'\n\t\t\t\t\t\t\t\t\t: 'Push notifications are not supported in this browser'}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<ToggleSwitch\n\t\t\t\t\t\t\tchecked={isSubscribed}\n\t\t\t\t\t\t\tdisabled={!isSupported || isTogglingPush}\n\t\t\t\t\t\t\tonChange={handleTogglePush}\n\t\t\t\t\t\t\ttheme={theme}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{!isSupported && (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.alert, styles.alertWarning, {\n\t\t\t\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t\t\t\t\tmarginBottom: 0,\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<BellOffIcon size={16} />\n\t\t\t\t\t\t\t<span style={{ marginLeft: '0.5rem' }}>\n\t\t\t\t\t\t\t\tYour browser doesn't support push notifications\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Email Notifications */}\n\t\t\t{showEmail && (\n\t\t\t\t<div style={cardStyles}>\n\t\t\t\t\t<h4 style={{ margin: '0 0 1rem', fontWeight: 500 }}>Email Notifications</h4>\n\n\t\t\t\t\t{/* Marketing emails */}\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={mergeStyles(styles.flexBetween, {\n\t\t\t\t\t\t\tpadding: '0.75rem 0',\n\t\t\t\t\t\t\tborderBottom: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<div style={{ fontWeight: 500, fontSize: theme.fontSizeSm }}>\n\t\t\t\t\t\t\t\tMarketing & Promotions\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div style={mergeStyles(styles.textXs, styles.textMuted)}>\n\t\t\t\t\t\t\t\tNew features, tips, and special offers\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<ToggleSwitch\n\t\t\t\t\t\t\tchecked={localPrefs.emailMarketing ?? true}\n\t\t\t\t\t\t\tonChange={(checked) => handlePreferenceChange('emailMarketing', checked)}\n\t\t\t\t\t\t\ttheme={theme}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Weekly summary */}\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={mergeStyles(styles.flexBetween, {\n\t\t\t\t\t\t\tpadding: '0.75rem 0',\n\t\t\t\t\t\t\tborderBottom: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<div style={{ fontWeight: 500, fontSize: theme.fontSizeSm }}>Weekly Summary</div>\n\t\t\t\t\t\t\t<div style={mergeStyles(styles.textXs, styles.textMuted)}>\n\t\t\t\t\t\t\t\tWeekly digest of your activity\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<ToggleSwitch\n\t\t\t\t\t\t\tchecked={localPrefs.emailWeeklySummary ?? true}\n\t\t\t\t\t\t\tonChange={(checked) => handlePreferenceChange('emailWeeklySummary', checked)}\n\t\t\t\t\t\t\ttheme={theme}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Daily reminder */}\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={mergeStyles(styles.flexBetween, {\n\t\t\t\t\t\t\tpadding: '0.75rem 0',\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<div style={{ fontWeight: 500, fontSize: theme.fontSizeSm }}>Daily Reminders</div>\n\t\t\t\t\t\t\t<div style={mergeStyles(styles.textXs, styles.textMuted)}>\n\t\t\t\t\t\t\t\tPush notifications for daily reminders\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<ToggleSwitch\n\t\t\t\t\t\t\tchecked={localPrefs.pushDailyReminder ?? true}\n\t\t\t\t\t\t\tonChange={(checked) => handlePreferenceChange('pushDailyReminder', checked)}\n\t\t\t\t\t\t\ttheme={theme}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Notification Types Legend */}\n\t\t\t<div style={mergeStyles(styles.textXs, styles.textMuted, styles.textCenter)}>\n\t\t\t\t<p style={{ margin: 0 }}>\n\t\t\t\t\tSecurity notifications cannot be fully disabled to keep your account safe.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n// Toggle switch component\nfunction ToggleSwitch({\n\tchecked,\n\tonChange,\n\tdisabled = false,\n\ttheme,\n}: {\n\tchecked: boolean\n\tonChange: (checked: boolean) => void\n\tdisabled?: boolean\n\ttheme: ThemeVariables\n}) {\n\tconst trackStyle: React.CSSProperties = {\n\t\twidth: '2.75rem',\n\t\theight: '1.5rem',\n\t\tborderRadius: '9999px',\n\t\tbackgroundColor: checked ? theme.colorPrimary : theme.colorMuted,\n\t\tpadding: '0.125rem',\n\t\tcursor: disabled ? 'not-allowed' : 'pointer',\n\t\ttransition: 'background-color 0.15s ease-in-out',\n\t\topacity: disabled ? 0.5 : 1,\n\t\tborder: checked ? 'none' : `1px solid ${theme.colorBorder}`,\n\t}\n\n\tconst thumbStyle: React.CSSProperties = {\n\t\twidth: '1.25rem',\n\t\theight: '1.25rem',\n\t\tborderRadius: '50%',\n\t\tbackgroundColor: '#fff',\n\t\tboxShadow: '0 1px 3px rgba(0,0,0,0.15)',\n\t\ttransform: checked ? 'translateX(1.25rem)' : 'translateX(0)',\n\t\ttransition: 'transform 0.15s ease-in-out',\n\t}\n\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\trole=\"switch\"\n\t\t\taria-checked={checked}\n\t\t\tdisabled={disabled}\n\t\t\tonClick={() => !disabled && onChange(!checked)}\n\t\t\tstyle={trackStyle}\n\t\t>\n\t\t\t<div style={thumbStyle} />\n\t\t</button>\n\t)\n}\n\n// Icons\nfunction BellOffIcon({ size = 24 }: { size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tstyle={{ flexShrink: 0 }}\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M13.73 21a2 2 0 0 1-3.46 0\" />\n\t\t\t<path d=\"M18.63 13A17.89 17.89 0 0 1 18 8\" />\n\t\t\t<path d=\"M6.26 6.26A5.86 5.86 0 0 0 6 8c0 7-3 9-3 9h14\" />\n\t\t\t<path d=\"M18 8a6 6 0 0 0-9.33-5\" />\n\t\t\t<line x1=\"1\" y1=\"1\" x2=\"23\" y2=\"23\" />\n\t\t</svg>\n\t)\n}\n","/**\n * Organization Management Components\n *\n * OrganizationProfile, CreateOrganization, OrganizationList\n */\n\n'use client'\n\nimport { type CSSProperties, type FormEvent, useEffect, useId, useState } from 'react'\nimport { UI_FORM_SUCCESS_MS } from '../../constants'\nimport { type Organization, RequireSdk, useOrganization } from '../hooks'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\n// ============================================\n// OrganizationProfile\n// ============================================\n\nexport interface OrganizationProfileProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Custom class name */\n\tclassName?: string\n\t/** Organization to display (uses hook if not provided) */\n\torganization?: Organization\n\t/** Whether user can edit */\n\tcanEdit?: boolean\n\t/** Called when save is clicked */\n\tonSave?: (data: { name: string; slug?: string; logoUrl?: string }) => Promise<void>\n\t/** Called when delete is clicked */\n\tonDelete?: () => Promise<void>\n\t/** Show danger zone */\n\tshowDangerZone?: boolean\n\t/** Show members section */\n\tshowMembers?: boolean\n}\n\n/**\n * Organization profile settings\n *\n * @example\n * ```tsx\n * <OrganizationProfile\n *   onSave={async (data) => updateOrg(data)}\n *   showDangerZone\n * />\n * ```\n */\nexport function OrganizationProfile(props: OrganizationProfileProps) {\n\treturn (\n\t\t<RequireSdk services={['organization']} componentType=\"organization\" theme={props.theme}>\n\t\t\t<OrganizationProfileInner {...props} />\n\t\t</RequireSdk>\n\t)\n}\n\n/** Inner component that safely uses platform hooks */\nfunction OrganizationProfileInner({\n\ttheme = defaultTheme,\n\tclassName,\n\torganization: propOrg,\n\tcanEdit = true,\n\tonSave,\n\tonDelete,\n\tshowDangerZone = true,\n\tshowMembers = true,\n}: OrganizationProfileProps) {\n\tconst hookResult = useOrganization()\n\tconst org = propOrg ?? hookResult.organization\n\tconst members = hookResult.members\n\n\tconst nameId = useId()\n\tconst slugId = useId()\n\tconst deleteConfirmId = useId()\n\tconst [name, setName] = useState(org?.name ?? '')\n\tconst [slug, setSlug] = useState(org?.slug ?? '')\n\tconst [isSaving, setIsSaving] = useState(false)\n\tconst [isDeleting, setIsDeleting] = useState(false)\n\tconst [saveSuccess, setSaveSuccess] = useState(false)\n\tconst [deleteConfirm, setDeleteConfirm] = useState('')\n\n\tconst styles = baseStyles(theme)\n\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tuseEffect(() => {\n\t\tif (org) {\n\t\t\tsetName(org.name)\n\t\t\tsetSlug(org.slug ?? '')\n\t\t}\n\t}, [org])\n\n\tuseEffect(() => {\n\t\tif (saveSuccess) {\n\t\t\tconst timer = setTimeout(() => setSaveSuccess(false), UI_FORM_SUCCESS_MS)\n\t\t\treturn () => clearTimeout(timer)\n\t\t}\n\t}, [saveSuccess])\n\n\tconst handleSave = async (e: FormEvent) => {\n\t\te.preventDefault()\n\t\tif (!onSave || !name.trim()) return\n\n\t\tsetIsSaving(true)\n\t\ttry {\n\t\t\tawait onSave({ name: name.trim(), slug: slug.trim() || undefined })\n\t\t\tsetSaveSuccess(true)\n\t\t} finally {\n\t\t\tsetIsSaving(false)\n\t\t}\n\t}\n\n\tconst handleDelete = async () => {\n\t\tif (!onDelete || deleteConfirm !== org?.name) return\n\n\t\tsetIsDeleting(true)\n\t\ttry {\n\t\t\tawait onDelete()\n\t\t} finally {\n\t\t\tsetIsDeleting(false)\n\t\t}\n\t}\n\n\tconst containerStyle: CSSProperties = {\n\t\tfontFamily: theme.fontFamily,\n\t}\n\n\tconst sectionStyle: CSSProperties = {\n\t\tmarginBottom: '2rem',\n\t\tpadding: '1.5rem',\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t}\n\n\tconst inputStyle: CSSProperties = {\n\t\twidth: '100%',\n\t\tpadding: '0.75rem',\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t\tbackgroundColor: theme.colorBackground,\n\t\tcolor: theme.colorForeground,\n\t\tfontSize: theme.fontSizeSm,\n\t\tfontFamily: theme.fontFamily,\n\t}\n\n\tif (!org) {\n\t\treturn (\n\t\t\t<div style={containerStyle} className={className}>\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\tpadding: '3rem',\n\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\tNo organization selected\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t)\n\t}\n\n\treturn (\n\t\t<div style={containerStyle} className={className}>\n\t\t\t{/* General Settings */}\n\t\t\t<div style={sectionStyle}>\n\t\t\t\t<h3\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tmargin: '0 0 1.5rem',\n\t\t\t\t\t\tfontSize: theme.fontSizeLg,\n\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\tOrganization Settings\n\t\t\t\t</h3>\n\n\t\t\t\t{saveSuccess && (\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={mergeStyles(styles.alert, styles.alertSuccess, {\n\t\t\t\t\t\t\tmarginBottom: '1rem',\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\tSettings saved successfully\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t<form onSubmit={handleSave}>\n\t\t\t\t\t<div style={{ marginBottom: '1rem' }}>\n\t\t\t\t\t\t<label\n\t\t\t\t\t\t\thtmlFor={nameId}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tOrganization Name\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\tid={nameId}\n\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\tvalue={name}\n\t\t\t\t\t\t\tonChange={(e) => setName(e.target.value)}\n\t\t\t\t\t\t\tdisabled={!canEdit}\n\t\t\t\t\t\t\tstyle={inputStyle}\n\t\t\t\t\t\t\tplaceholder=\"My Organization\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div style={{ marginBottom: '1.5rem' }}>\n\t\t\t\t\t\t<label\n\t\t\t\t\t\t\thtmlFor={slugId}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tURL Slug\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\tid={slugId}\n\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\tvalue={slug}\n\t\t\t\t\t\t\tonChange={(e) => setSlug(e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, ''))}\n\t\t\t\t\t\t\tdisabled={!canEdit}\n\t\t\t\t\t\t\tstyle={inputStyle}\n\t\t\t\t\t\t\tplaceholder=\"my-organization\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tUsed in URLs: /org/{slug || 'my-organization'}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{canEdit && onSave && (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\tdisabled={isSaving || !name.trim()}\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{isSaving ? <span style={styles.spinner} /> : 'Save Changes'}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t)}\n\t\t\t\t</form>\n\t\t\t</div>\n\n\t\t\t{/* Members */}\n\t\t\t{showMembers && members.length > 0 && (\n\t\t\t\t<div style={sectionStyle}>\n\t\t\t\t\t<h3\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tmargin: '0 0 1rem',\n\t\t\t\t\t\t\tfontSize: theme.fontSizeLg,\n\t\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tMembers ({members.length})\n\t\t\t\t\t</h3>\n\t\t\t\t\t<div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem' }}>\n\t\t\t\t\t\t{members.slice(0, 5).map((member) => (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tkey={member.userId}\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t\t\t\t\tpadding: '0.75rem',\n\t\t\t\t\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\tgap: '0.75rem',\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\twidth: 32,\n\t\t\t\t\t\t\t\t\t\t\theight: 32,\n\t\t\t\t\t\t\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: theme.colorPrimary,\n\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorPrimaryForeground,\n\t\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\t\tjustifyContent: 'center',\n\t\t\t\t\t\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{member.name?.charAt(0).toUpperCase() ??\n\t\t\t\t\t\t\t\t\t\t\tmember.email?.charAt(0).toUpperCase() ??\n\t\t\t\t\t\t\t\t\t\t\t'?'}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t\t<div style={{ fontWeight: 500, fontSize: theme.fontSizeSm }}>\n\t\t\t\t\t\t\t\t\t\t\t{member.name ?? member.email}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t{member.name && member.email && (\n\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{member.email}\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t\t\t\t\t\tbackgroundColor:\n\t\t\t\t\t\t\t\t\t\t\tmember.role === 'super_admin' ? theme.colorPrimary : theme.colorBackground,\n\t\t\t\t\t\t\t\t\t\tcolor:\n\t\t\t\t\t\t\t\t\t\t\tmember.role === 'super_admin'\n\t\t\t\t\t\t\t\t\t\t\t\t? theme.colorPrimaryForeground\n\t\t\t\t\t\t\t\t\t\t\t\t: theme.colorForeground,\n\t\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t\t\ttextTransform: 'capitalize',\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{member.role}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t))}\n\t\t\t\t\t\t{members.length > 5 && (\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tmargin: '0.5rem 0 0',\n\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t+{members.length - 5} more members\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Danger Zone */}\n\t\t\t{showDangerZone && onDelete && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\t...sectionStyle,\n\t\t\t\t\t\tborderColor: theme.colorDestructive,\n\t\t\t\t\t\tbackgroundColor: `${theme.colorDestructive}08`,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<h3\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tmargin: '0 0 0.5rem',\n\t\t\t\t\t\t\tfontSize: theme.fontSizeLg,\n\t\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\t\tcolor: theme.colorDestructive,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tDanger Zone\n\t\t\t\t\t</h3>\n\t\t\t\t\t<p\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tmargin: '0 0 1rem',\n\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tDeleting this organization will remove all data, members, and settings. This action\n\t\t\t\t\t\tcannot be undone.\n\t\t\t\t\t</p>\n\n\t\t\t\t\t<div style={{ marginBottom: '1rem' }}>\n\t\t\t\t\t\t<label\n\t\t\t\t\t\t\thtmlFor={deleteConfirmId}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tType <strong>{org.name}</strong> to confirm\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\tid={deleteConfirmId}\n\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\tvalue={deleteConfirm}\n\t\t\t\t\t\t\tonChange={(e) => setDeleteConfirm(e.target.value)}\n\t\t\t\t\t\t\tstyle={inputStyle}\n\t\t\t\t\t\t\tplaceholder={org.name}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={handleDelete}\n\t\t\t\t\t\tdisabled={isDeleting || deleteConfirm !== org.name}\n\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonDestructive, {\n\t\t\t\t\t\t\topacity: deleteConfirm !== org.name ? 0.5 : 1,\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t{isDeleting ? <span style={styles.spinner} /> : 'Delete Organization'}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n// ============================================\n// CreateOrganization\n// ============================================\n\nexport interface CreateOrganizationProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Custom class name */\n\tclassName?: string\n\t/** Title */\n\ttitle?: string\n\t/** Description */\n\tdescription?: string\n\t/** Called when organization is created */\n\tonCreate: (data: { name: string; slug?: string }) => Promise<void>\n\t/** Called when cancelled */\n\tonCancel?: () => void\n\t/** Show cancel button */\n\tshowCancel?: boolean\n}\n\n/**\n * Create organization form\n *\n * @example\n * ```tsx\n * <CreateOrganization\n *   onCreate={async (data) => {\n *     await createOrg(data)\n *     router.push(`/org/${data.slug}`)\n *   }}\n * />\n * ```\n */\nexport function CreateOrganization({\n\ttheme = defaultTheme,\n\tclassName,\n\ttitle = 'Create Organization',\n\tdescription = 'Organizations let you collaborate with team members and manage shared resources.',\n\tonCreate,\n\tonCancel,\n\tshowCancel = true,\n}: CreateOrganizationProps) {\n\tconst createNameId = useId()\n\tconst createSlugId = useId()\n\tconst [name, setName] = useState('')\n\tconst [slug, setSlug] = useState('')\n\tconst [isCreating, setIsCreating] = useState(false)\n\tconst [error, setError] = useState<string | null>(null)\n\n\tconst styles = baseStyles(theme)\n\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// Auto-generate slug from name\n\tuseEffect(() => {\n\t\tif (name && !slug) {\n\t\t\tconst generatedSlug = name\n\t\t\t\t.toLowerCase()\n\t\t\t\t.replace(/[^a-z0-9]+/g, '-')\n\t\t\t\t.replace(/^-|-$/g, '')\n\t\t\tsetSlug(generatedSlug)\n\t\t}\n\t}, [name, slug])\n\n\tconst handleSubmit = async (e: FormEvent) => {\n\t\te.preventDefault()\n\t\tif (!name.trim()) return\n\n\t\tsetIsCreating(true)\n\t\tsetError(null)\n\n\t\ttry {\n\t\t\tawait onCreate({ name: name.trim(), slug: slug.trim() || undefined })\n\t\t} catch (err) {\n\t\t\tsetError(err instanceof Error ? err.message : 'Failed to create organization')\n\t\t} finally {\n\t\t\tsetIsCreating(false)\n\t\t}\n\t}\n\n\tconst containerStyle: CSSProperties = {\n\t\tfontFamily: theme.fontFamily,\n\t\tmaxWidth: '400px',\n\t\tmargin: '0 auto',\n\t}\n\n\tconst inputStyle: CSSProperties = {\n\t\twidth: '100%',\n\t\tpadding: '0.75rem',\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t\tbackgroundColor: theme.colorBackground,\n\t\tcolor: theme.colorForeground,\n\t\tfontSize: theme.fontSizeSm,\n\t\tfontFamily: theme.fontFamily,\n\t}\n\n\treturn (\n\t\t<div style={containerStyle} className={className}>\n\t\t\t<div style={{ textAlign: 'center', marginBottom: '2rem' }}>\n\t\t\t\t<OrgIcon color={theme.colorPrimary} size={48} />\n\t\t\t\t<h2\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tmargin: '1rem 0 0.5rem',\n\t\t\t\t\t\tfontSize: theme.fontSizeXl,\n\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{title}\n\t\t\t\t</h2>\n\t\t\t\t<p\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{description}\n\t\t\t\t</p>\n\t\t\t</div>\n\n\t\t\t{error && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={mergeStyles(styles.alert, styles.alertError, {\n\t\t\t\t\t\tmarginBottom: '1rem',\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\t{error}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t<form onSubmit={handleSubmit}>\n\t\t\t\t<div style={{ marginBottom: '1rem' }}>\n\t\t\t\t\t<label\n\t\t\t\t\t\thtmlFor={createNameId}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tOrganization Name *\n\t\t\t\t\t</label>\n\t\t\t\t\t<input\n\t\t\t\t\t\tid={createNameId}\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tvalue={name}\n\t\t\t\t\t\tonChange={(e) => setName(e.target.value)}\n\t\t\t\t\t\tstyle={inputStyle}\n\t\t\t\t\t\tplaceholder=\"Acme Inc.\"\n\t\t\t\t\t\trequired\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\n\t\t\t\t<div style={{ marginBottom: '1.5rem' }}>\n\t\t\t\t\t<label\n\t\t\t\t\t\thtmlFor={createSlugId}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tURL Slug\n\t\t\t\t\t</label>\n\t\t\t\t\t<input\n\t\t\t\t\t\tid={createSlugId}\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tvalue={slug}\n\t\t\t\t\t\tonChange={(e) => setSlug(e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, ''))}\n\t\t\t\t\t\tstyle={inputStyle}\n\t\t\t\t\t\tplaceholder=\"acme-inc\"\n\t\t\t\t\t/>\n\t\t\t\t\t<p\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tLetters, numbers, and hyphens only\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\n\t\t\t\t<div style={{ display: 'flex', gap: '0.75rem' }}>\n\t\t\t\t\t{showCancel && onCancel && (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={onCancel}\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline, {\n\t\t\t\t\t\t\t\tflex: 1,\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t</button>\n\t\t\t\t\t)}\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\tdisabled={isCreating || !name.trim()}\n\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary, {\n\t\t\t\t\t\t\tflex: 1,\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t{isCreating ? <span style={styles.spinner} /> : 'Create Organization'}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</form>\n\t\t</div>\n\t)\n}\n\n// ============================================\n// OrganizationList\n// ============================================\n\nexport interface OrganizationListProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Custom class name */\n\tclassName?: string\n\t/** Organizations to display */\n\torganizations: Organization[]\n\t/** Currently selected organization ID */\n\tselectedId?: string\n\t/** Called when organization is selected */\n\tonSelect?: (org: Organization) => void\n\t/** Called when create is clicked */\n\tonCreate?: () => void\n\t/** Show create button */\n\tshowCreateButton?: boolean\n\t/** Empty state message */\n\temptyMessage?: string\n}\n\n/**\n * List of organizations\n *\n * @example\n * ```tsx\n * <OrganizationList\n *   organizations={orgs}\n *   selectedId={currentOrg.id}\n *   onSelect={(org) => switchOrg(org.id)}\n *   onCreate={() => router.push('/create-org')}\n * />\n * ```\n */\nexport function OrganizationList({\n\ttheme = defaultTheme,\n\tclassName,\n\torganizations,\n\tselectedId,\n\tonSelect,\n\tonCreate,\n\tshowCreateButton = true,\n\temptyMessage = 'No organizations',\n}: OrganizationListProps) {\n\tconst styles = baseStyles(theme)\n\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tconst containerStyle: CSSProperties = {\n\t\tfontFamily: theme.fontFamily,\n\t}\n\n\tconst itemStyle = (isSelected: boolean): CSSProperties => ({\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tgap: '0.75rem',\n\t\tpadding: '0.75rem 1rem',\n\t\tborder: `1px solid ${isSelected ? theme.colorPrimary : theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t\tbackgroundColor: isSelected ? `${theme.colorPrimary}10` : theme.colorBackground,\n\t\tcursor: 'pointer',\n\t\ttransition: 'all 0.15s ease',\n\t})\n\n\treturn (\n\t\t<div style={containerStyle} className={className}>\n\t\t\t{organizations.length === 0 ? (\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tpadding: '3rem',\n\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<OrgIcon color={theme.colorMuted} size={48} />\n\t\t\t\t\t<p style={{ margin: '1rem 0' }}>{emptyMessage}</p>\n\t\t\t\t\t{showCreateButton && onCreate && (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={onCreate}\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tCreate Organization\n\t\t\t\t\t\t</button>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem' }}>\n\t\t\t\t\t\t{organizations.map((org) => (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\tkey={org.id}\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={() => onSelect?.(org)}\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t...itemStyle(org.id === selectedId),\n\t\t\t\t\t\t\t\t\ttextAlign: 'left',\n\t\t\t\t\t\t\t\t\tfont: 'inherit',\n\t\t\t\t\t\t\t\t\tcolor: 'inherit',\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\twidth: 40,\n\t\t\t\t\t\t\t\t\t\theight: 40,\n\t\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t\t\tbackgroundColor: theme.colorPrimary,\n\t\t\t\t\t\t\t\t\t\tcolor: theme.colorPrimaryForeground,\n\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\tjustifyContent: 'center',\n\t\t\t\t\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeLg,\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{org.name.charAt(0).toUpperCase()}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div style={{ flex: 1, minWidth: 0 }}>\n\t\t\t\t\t\t\t\t\t<div style={{ fontWeight: 500, fontSize: theme.fontSizeSm }}>{org.name}</div>\n\t\t\t\t\t\t\t\t\t{org.slug && (\n\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t/{org.slug}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t{org.id === selectedId && <CheckIcon color={theme.colorPrimary} />}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{showCreateButton && onCreate && (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={onCreate}\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline, {\n\t\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<PlusIcon color={theme.colorForeground} /> Create Organization\n\t\t\t\t\t\t</button>\n\t\t\t\t\t)}\n\t\t\t\t</>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n// ============================================\n// Icons\n// ============================================\n\nfunction OrgIcon({ color, size = 24 }: { color: string; size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2\" />\n\t\t\t<circle cx=\"9\" cy=\"7\" r=\"4\" />\n\t\t\t<path d=\"M23 21v-2a4 4 0 0 0-3-3.87\" />\n\t\t\t<path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\n\t\t</svg>\n\t)\n}\n\nfunction CheckIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<polyline points=\"20 6 9 17 4 12\" />\n\t\t</svg>\n\t)\n}\n\nfunction PlusIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tstyle={{ marginRight: '0.25rem' }}\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n\t\t\t<line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n\t\t</svg>\n\t)\n}\n","/**\n * Push Notification Components\n *\n * Pre-built components for push notification management.\n * Includes permission prompt, notification bell, and notification list.\n */\n\n'use client'\n\nimport { type CSSProperties, useEffect, useState } from 'react'\nimport {\n\tMS_PER_DAY,\n\tMS_PER_HOUR,\n\tMS_PER_MINUTE,\n\tUI_PROMPT_DELAY_MS,\n\tZ_INDEX_OVERLAY,\n} from '../../constants'\nimport { useNotifications } from '../platform-hooks'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\n// ============================================\n// PushPrompt\n// ============================================\n\nexport interface PushPromptProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Title text */\n\ttitle?: string\n\t/** Description text */\n\tdescription?: string\n\t/** Enable button text */\n\tenableText?: string\n\t/** Maybe later button text */\n\tlaterText?: string\n\t/** Called when enabled */\n\tonEnabled?: () => void\n\t/** Called when dismissed */\n\tonDismissed?: () => void\n\t/** Custom class name */\n\tclassName?: string\n\t/** Position */\n\tposition?: 'top' | 'bottom' | 'center'\n\t/** Variant */\n\tvariant?: 'banner' | 'card' | 'modal'\n\t/** Auto-show when notifications not enabled */\n\tautoShow?: boolean\n\t/** Delay before showing (ms) */\n\tshowDelay?: number\n}\n\n/**\n * Push notification permission prompt\n *\n * @example\n * ```tsx\n * // Simple banner\n * <PushPrompt\n *   variant=\"banner\"\n *   position=\"top\"\n *   onEnabled={() => console.log('Notifications enabled!')}\n * />\n *\n * // Card variant\n * <PushPrompt\n *   variant=\"card\"\n *   title=\"Stay Updated\"\n *   description=\"Get notified when something important happens\"\n * />\n * ```\n */\nexport function PushPrompt({\n\ttheme = defaultTheme,\n\ttitle = 'Enable Notifications',\n\tdescription = \"We'll notify you about important updates and activity.\",\n\tenableText = 'Enable',\n\tlaterText = 'Not Now',\n\tonEnabled,\n\tonDismissed,\n\tclassName,\n\tposition = 'bottom',\n\tvariant = 'banner',\n\tautoShow = true,\n\tshowDelay = UI_PROMPT_DELAY_MS,\n}: PushPromptProps) {\n\tconst [isVisible, setIsVisible] = useState(false)\n\tconst [isAnimatingOut, setIsAnimatingOut] = useState(false)\n\tconst { isSupported, isSubscribed, subscribe, error } = useNotifications()\n\tconst styles = baseStyles(theme)\n\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// Auto-show logic\n\tuseEffect(() => {\n\t\tif (!autoShow || !isSupported || isSubscribed) return\n\n\t\tconst timer = setTimeout(() => {\n\t\t\tsetIsVisible(true)\n\t\t}, showDelay)\n\n\t\treturn () => clearTimeout(timer)\n\t}, [autoShow, isSupported, isSubscribed, showDelay])\n\n\tconst handleEnable = async () => {\n\t\tconst success = await subscribe()\n\t\tif (success) {\n\t\t\thandleClose()\n\t\t\tonEnabled?.()\n\t\t}\n\t}\n\n\tconst handleDismiss = () => {\n\t\thandleClose()\n\t\tonDismissed?.()\n\t}\n\n\tconst handleClose = () => {\n\t\tsetIsAnimatingOut(true)\n\t\tsetTimeout(() => {\n\t\t\tsetIsVisible(false)\n\t\t\tsetIsAnimatingOut(false)\n\t\t}, 200)\n\t}\n\n\tif (!isSupported || isSubscribed || !isVisible) {\n\t\treturn null\n\t}\n\n\tconst positionStyles: Record<string, CSSProperties> = {\n\t\ttop: { top: '1rem', left: '50%', transform: 'translateX(-50%)' },\n\t\tbottom: { bottom: '1rem', left: '50%', transform: 'translateX(-50%)' },\n\t\tcenter: { top: '50%', left: '50%', transform: 'translate(-50%, -50%)' },\n\t}\n\n\tconst containerStyle: CSSProperties = mergeStyles(\n\t\t{\n\t\t\tposition: 'fixed',\n\t\t\tzIndex: Z_INDEX_OVERLAY,\n\t\t\tfontFamily: theme.fontFamily,\n\t\t\tanimation: isAnimatingOut ? 'sylphx-fade-out 0.2s ease' : 'sylphx-slide-up 0.3s ease',\n\t\t},\n\t\tpositionStyles[position],\n\t)\n\n\tif (variant === 'banner') {\n\t\tconst bannerStyle: CSSProperties = mergeStyles(\n\t\t\t{\n\t\t\t\tdisplay: 'flex',\n\t\t\t\talignItems: 'center',\n\t\t\t\tgap: '1rem',\n\t\t\t\tpadding: '1rem 1.5rem',\n\t\t\t\tbackgroundColor: theme.colorBackground,\n\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\tborderRadius: theme.borderRadiusLg,\n\t\t\t\tboxShadow: '0 10px 40px rgba(0, 0, 0, 0.15)',\n\t\t\t\tmaxWidth: '480px',\n\t\t\t},\n\t\t\tcontainerStyle,\n\t\t)\n\n\t\treturn (\n\t\t\t<div style={bannerStyle} className={className}>\n\t\t\t\t<BellIcon color={theme.colorPrimary} />\n\t\t\t\t<div style={{ flex: 1 }}>\n\t\t\t\t\t<p style={{ margin: 0, fontWeight: 600, fontSize: theme.fontSizeSm }}>{title}</p>\n\t\t\t\t\t<p style={mergeStyles(styles.textXs, styles.textMuted, { margin: 0 })}>{description}</p>\n\t\t\t\t</div>\n\t\t\t\t<div style={{ display: 'flex', gap: '0.5rem' }}>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={handleDismiss}\n\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonGhost, {\n\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t{laterText}\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={handleEnable}\n\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary, {\n\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t{enableText}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t)\n\t}\n\n\t// Card variant\n\tconst cardStyle: CSSProperties = mergeStyles(styles.card, containerStyle, {\n\t\tpadding: '1.5rem',\n\t\ttextAlign: 'center',\n\t\tmaxWidth: '320px',\n\t})\n\n\treturn (\n\t\t<div style={cardStyle} className={className}>\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\twidth: '56px',\n\t\t\t\t\theight: '56px',\n\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\tbackgroundColor: `${theme.colorPrimary}15`,\n\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\talignItems: 'center',\n\t\t\t\t\tjustifyContent: 'center',\n\t\t\t\t\tmargin: '0 auto 1rem',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<BellIcon color={theme.colorPrimary} size={28} />\n\t\t\t</div>\n\t\t\t<h3\n\t\t\t\tstyle={{\n\t\t\t\t\tmargin: '0 0 0.5rem',\n\t\t\t\t\tfontSize: theme.fontSizeLg,\n\t\t\t\t\tfontWeight: 600,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{title}\n\t\t\t</h3>\n\t\t\t<p\n\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\tmargin: '0 0 1.5rem',\n\t\t\t\t})}\n\t\t\t>\n\t\t\t\t{description}\n\t\t\t</p>\n\t\t\t{error && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={mergeStyles(styles.alert, styles.alertError, {\n\t\t\t\t\t\tmarginBottom: '1rem',\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\t{error.message}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<div style={{ display: 'flex', gap: '0.75rem' }}>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={handleDismiss}\n\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline, styles.buttonFullWidth)}\n\t\t\t\t>\n\t\t\t\t\t{laterText}\n\t\t\t\t</button>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={handleEnable}\n\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary, styles.buttonFullWidth)}\n\t\t\t\t>\n\t\t\t\t\t{enableText}\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n// ============================================\n// NotificationBell\n// ============================================\n\nexport interface NotificationBellProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Unread notification count */\n\tcount?: number\n\t/** Max count to display */\n\tmaxCount?: number\n\t/** Called when clicked */\n\tonClick?: () => void\n\t/** Custom class name */\n\tclassName?: string\n\t/** Size */\n\tsize?: 'sm' | 'md' | 'lg'\n\t/** Show dot instead of count */\n\tshowDot?: boolean\n\t/** Custom icon color */\n\tcolor?: string\n}\n\n/**\n * Notification bell icon with badge\n *\n * @example\n * ```tsx\n * const [showPanel, setShowPanel] = useState(false)\n * const { unreadCount } = useNotifications()\n *\n * <NotificationBell\n *   count={unreadCount}\n *   onClick={() => setShowPanel(true)}\n * />\n * ```\n */\nexport function NotificationBell({\n\ttheme = defaultTheme,\n\tcount = 0,\n\tmaxCount = 99,\n\tonClick,\n\tclassName,\n\tsize = 'md',\n\tshowDot = false,\n\tcolor,\n}: NotificationBellProps) {\n\tconst sizes = {\n\t\tsm: { button: '32px', icon: 18, badge: '14px', badgeFont: '9px' },\n\t\tmd: { button: '40px', icon: 22, badge: '18px', badgeFont: '11px' },\n\t\tlg: { button: '48px', icon: 26, badge: '22px', badgeFont: '12px' },\n\t}\n\n\tconst s = sizes[size]\n\tconst displayCount = count > maxCount ? `${maxCount}+` : count\n\n\tconst buttonStyle: CSSProperties = {\n\t\tposition: 'relative',\n\t\twidth: s.button,\n\t\theight: s.button,\n\t\tborderRadius: '50%',\n\t\tborder: 'none',\n\t\tbackgroundColor: 'transparent',\n\t\tcursor: 'pointer',\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'center',\n\t\ttransition: 'background-color 0.2s ease',\n\t}\n\n\tconst badgeStyle: CSSProperties = {\n\t\tposition: 'absolute',\n\t\ttop: '-2px',\n\t\tright: '-2px',\n\t\tminWidth: s.badge,\n\t\theight: s.badge,\n\t\tpadding: showDot ? 0 : '0 4px',\n\t\tborderRadius: '9999px',\n\t\tbackgroundColor: theme.colorDestructive,\n\t\tcolor: theme.colorDestructiveForeground,\n\t\tfontSize: s.badgeFont,\n\t\tfontWeight: 600,\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'center',\n\t}\n\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tonClick={onClick}\n\t\t\tstyle={buttonStyle}\n\t\t\tclassName={className}\n\t\t\tonMouseEnter={(e) => {\n\t\t\t\te.currentTarget.style.backgroundColor = theme.colorMuted\n\t\t\t}}\n\t\t\tonMouseLeave={(e) => {\n\t\t\t\te.currentTarget.style.backgroundColor = 'transparent'\n\t\t\t}}\n\t\t>\n\t\t\t<BellIcon color={color || theme.colorForeground} size={s.icon} />\n\t\t\t{count > 0 && <span style={badgeStyle}>{showDot ? null : displayCount}</span>}\n\t\t</button>\n\t)\n}\n\n// ============================================\n// NotificationList\n// ============================================\n\nexport interface Notification {\n\tid: string\n\ttitle: string\n\tbody?: string\n\ticon?: string\n\turl?: string\n\tread: boolean\n\tcreatedAt: string | Date\n\tcategory?: string\n}\n\nexport interface NotificationListProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Notifications to display */\n\tnotifications: Notification[]\n\t/** Called when notification is clicked */\n\tonNotificationClick?: (notification: Notification) => void\n\t/** Called when notification is marked as read */\n\tonMarkAsRead?: (id: string) => void\n\t/** Called when all notifications are marked as read */\n\tonMarkAllAsRead?: () => void\n\t/** Called when notification is deleted */\n\tonDelete?: (id: string) => void\n\t/** Called when all notifications are cleared */\n\tonClearAll?: () => void\n\t/** Custom class name */\n\tclassName?: string\n\t/** Empty state message */\n\temptyMessage?: string\n\t/** Show mark all as read button */\n\tshowMarkAllAsRead?: boolean\n\t/** Show clear all button */\n\tshowClearAll?: boolean\n\t/** Max height */\n\tmaxHeight?: string\n}\n\n/**\n * Notification list component\n *\n * @example\n * ```tsx\n * <NotificationList\n *   notifications={notifications}\n *   onNotificationClick={(n) => router.push(n.url)}\n *   onMarkAsRead={(id) => markAsRead(id)}\n *   onMarkAllAsRead={() => markAllAsRead()}\n * />\n * ```\n */\nexport function NotificationList({\n\ttheme = defaultTheme,\n\tnotifications,\n\tonNotificationClick,\n\tonMarkAsRead,\n\tonMarkAllAsRead,\n\tonDelete,\n\tonClearAll,\n\tclassName,\n\temptyMessage = 'No notifications',\n\tshowMarkAllAsRead = true,\n\tshowClearAll = false,\n\tmaxHeight = '400px',\n}: NotificationListProps) {\n\tconst styles = baseStyles(theme)\n\tconst unreadCount = notifications.filter((n) => !n.read).length\n\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tconst containerStyle: CSSProperties = {\n\t\tfontFamily: theme.fontFamily,\n\t\tbackgroundColor: theme.colorBackground,\n\t\tborderRadius: theme.borderRadiusLg,\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\toverflow: 'hidden',\n\t}\n\n\tconst headerStyle: CSSProperties = {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'space-between',\n\t\tpadding: '0.75rem 1rem',\n\t\tborderBottom: `1px solid ${theme.colorBorder}`,\n\t\tbackgroundColor: theme.colorMuted,\n\t}\n\n\tconst listStyle: CSSProperties = {\n\t\tmaxHeight,\n\t\toverflowY: 'auto',\n\t}\n\n\treturn (\n\t\t<div style={containerStyle} className={className}>\n\t\t\t<div style={headerStyle}>\n\t\t\t\t<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>\n\t\t\t\t\t<span style={{ fontWeight: 600, fontSize: theme.fontSizeSm }}>Notifications</span>\n\t\t\t\t\t{unreadCount > 0 && (\n\t\t\t\t\t\t<span style={mergeStyles(styles.badge, styles.badgePrimary)}>{unreadCount} new</span>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<div style={{ display: 'flex', gap: '0.5rem' }}>\n\t\t\t\t\t{showMarkAllAsRead && unreadCount > 0 && (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={onMarkAllAsRead}\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonGhost, {\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tMark all read\n\t\t\t\t\t\t</button>\n\t\t\t\t\t)}\n\t\t\t\t\t{showClearAll && notifications.length > 0 && (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={onClearAll}\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonGhost, {\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tClear all\n\t\t\t\t\t\t</button>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div style={listStyle}>\n\t\t\t\t{notifications.length === 0 ? (\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tpadding: '3rem 1rem',\n\t\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<BellOffIcon color={theme.colorMutedForeground} />\n\t\t\t\t\t\t<p style={{ marginTop: '0.5rem', fontSize: theme.fontSizeSm }}>{emptyMessage}</p>\n\t\t\t\t\t</div>\n\t\t\t\t) : (\n\t\t\t\t\tnotifications.map((notification) => (\n\t\t\t\t\t\t<NotificationItem\n\t\t\t\t\t\t\tkey={notification.id}\n\t\t\t\t\t\t\tnotification={notification}\n\t\t\t\t\t\t\ttheme={theme}\n\t\t\t\t\t\t\tonClick={() => onNotificationClick?.(notification)}\n\t\t\t\t\t\t\tonMarkAsRead={() => onMarkAsRead?.(notification.id)}\n\t\t\t\t\t\t\tonDelete={() => onDelete?.(notification.id)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n// ============================================\n// NotificationItem\n// ============================================\n\ninterface NotificationItemProps {\n\tnotification: Notification\n\ttheme: ThemeVariables\n\tonClick?: () => void\n\tonMarkAsRead?: () => void\n\tonDelete?: () => void\n}\n\nfunction NotificationItem({\n\tnotification,\n\ttheme,\n\tonClick,\n\tonMarkAsRead,\n\tonDelete,\n}: NotificationItemProps) {\n\tconst styles = baseStyles(theme)\n\tconst [showActions, setShowActions] = useState(false)\n\n\tconst itemStyle: CSSProperties = {\n\t\tposition: 'relative',\n\t\tdisplay: 'flex',\n\t\talignItems: 'flex-start',\n\t\tgap: '0.75rem',\n\t\tpadding: '0.75rem 1rem',\n\t\tborderBottom: `1px solid ${theme.colorBorder}`,\n\t\ttransition: 'background-color 0.15s ease',\n\t\tbackgroundColor: notification.read ? 'transparent' : `${theme.colorPrimary}08`,\n\t}\n\n\tconst formatTime = (date: string | Date) => {\n\t\tconst d = new Date(date)\n\t\tconst now = new Date()\n\t\tconst diff = now.getTime() - d.getTime()\n\t\tconst minutes = Math.floor(diff / MS_PER_MINUTE)\n\t\tconst hours = Math.floor(diff / MS_PER_HOUR)\n\t\tconst days = Math.floor(diff / MS_PER_DAY)\n\n\t\tif (minutes < 1) return 'Just now'\n\t\tif (minutes < 60) return `${minutes}m ago`\n\t\tif (hours < 24) return `${hours}h ago`\n\t\tif (days < 7) return `${days}d ago`\n\t\treturn d.toLocaleDateString()\n\t}\n\n\treturn (\n\t\t<div className=\"sylphx-notification-item\" style={itemStyle}>\n\t\t\t{onClick && (\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={onClick}\n\t\t\t\t\taria-label={notification.title}\n\t\t\t\t\tonMouseEnter={() => setShowActions(true)}\n\t\t\t\t\tonMouseLeave={() => setShowActions(false)}\n\t\t\t\t\tonFocus={() => setShowActions(true)}\n\t\t\t\t\tonBlur={() => setShowActions(false)}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\t\tinset: 0,\n\t\t\t\t\t\tbackground: 'transparent',\n\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\tzIndex: 1,\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t{/* Icon/Avatar */}\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\twidth: '40px',\n\t\t\t\t\theight: '40px',\n\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\talignItems: 'center',\n\t\t\t\t\tjustifyContent: 'center',\n\t\t\t\t\tflexShrink: 0,\n\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{notification.icon ? (\n\t\t\t\t\t<img\n\t\t\t\t\t\tsrc={notification.icon}\n\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\tstyle={{ width: '100%', height: '100%', objectFit: 'cover' }}\n\t\t\t\t\t/>\n\t\t\t\t) : (\n\t\t\t\t\t<BellIcon color={theme.colorMutedForeground} size={20} />\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{/* Content */}\n\t\t\t<div style={{ flex: 1, minWidth: 0 }}>\n\t\t\t\t<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>\n\t\t\t\t\t<span\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tfontWeight: notification.read ? 400 : 600,\n\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\t\t\ttextOverflow: 'ellipsis',\n\t\t\t\t\t\t\twhiteSpace: 'nowrap',\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{notification.title}\n\t\t\t\t\t</span>\n\t\t\t\t\t{!notification.read && (\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\twidth: '8px',\n\t\t\t\t\t\t\t\theight: '8px',\n\t\t\t\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\t\t\t\tbackgroundColor: theme.colorPrimary,\n\t\t\t\t\t\t\t\tflexShrink: 0,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t{notification.body && (\n\t\t\t\t\t<p\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\t\t\ttextOverflow: 'ellipsis',\n\t\t\t\t\t\t\twhiteSpace: 'nowrap',\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{notification.body}\n\t\t\t\t\t</p>\n\t\t\t\t)}\n\t\t\t\t<p\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{formatTime(notification.createdAt)}\n\t\t\t\t</p>\n\t\t\t</div>\n\n\t\t\t{/* Actions */}\n\t\t\t{showActions && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\tgap: '0.25rem',\n\t\t\t\t\t\tflexShrink: 0,\n\t\t\t\t\t\tposition: 'relative',\n\t\t\t\t\t\tzIndex: 2,\n\t\t\t\t\t}}\n\t\t\t\t\trole=\"toolbar\"\n\t\t\t\t\taria-label=\"Notification actions\"\n\t\t\t\t>\n\t\t\t\t\t{!notification.read && onMarkAsRead && (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={onMarkAsRead}\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonGhost, {\n\t\t\t\t\t\t\t\tpadding: '0.25rem',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\ttitle=\"Mark as read\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<CheckIcon color={theme.colorMutedForeground} />\n\t\t\t\t\t\t</button>\n\t\t\t\t\t)}\n\t\t\t\t\t{onDelete && (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={onDelete}\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonGhost, {\n\t\t\t\t\t\t\t\tpadding: '0.25rem',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\ttitle=\"Delete\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<TrashIcon color={theme.colorMutedForeground} />\n\t\t\t\t\t\t</button>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n// ============================================\n// Icons\n// ============================================\n\nfunction BellIcon({ color, size = 24 }: { color: string; size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M18 8A6 6 0 006 8c0 7-3 9-3 9h18s-3-2-3-9\" />\n\t\t\t<path d=\"M13.73 21a2 2 0 01-3.46 0\" />\n\t\t</svg>\n\t)\n}\n\nfunction BellOffIcon({ color, size = 40 }: { color: string; size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"1.5\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M8.56 2.9A7 7 0 0119 9v4m-2 4H2s3-2 3-9a4.67 4.67 0 01.3-1.7\" />\n\t\t\t<path d=\"M13.73 21a2 2 0 01-3.46 0\" />\n\t\t\t<line x1=\"1\" y1=\"1\" x2=\"23\" y2=\"23\" />\n\t\t</svg>\n\t)\n}\n\nfunction CheckIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<polyline points=\"20 6 9 17 4 12\" />\n\t\t</svg>\n\t)\n}\n\nfunction TrashIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<polyline points=\"3 6 5 6 21 6\" />\n\t\t\t<path d=\"M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2\" />\n\t\t</svg>\n\t)\n}\n","/**\n * Referral Card Component\n *\n * Display referral program stats and share link.\n * Self-contained with CSS-in-JS styles.\n */\n\n'use client'\n\nimport { useEffect, useId, useState } from 'react'\nimport { UI_COPY_FEEDBACK_MS } from '../../constants'\nimport { RequireSdk } from '../hooks'\nimport { useReferral } from '../platform-hooks'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\nexport interface ReferralCardProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Called on successful action */\n\tonSuccess?: (message: string) => void\n\t/** Called on error */\n\tonError?: (error: string) => void\n\t/** Custom class name */\n\tclassName?: string\n\t/** Card title */\n\ttitle?: string\n\t/** Card description */\n\tdescription?: string\n\t/** Show referral stats */\n\tshowStats?: boolean\n\t/** Show share buttons */\n\tshowShare?: boolean\n\t/** Reward description */\n\trewardDescription?: string\n}\n\n/**\n * Referral program card\n *\n * @example\n * ```tsx\n * <ReferralCard\n *   title=\"Invite Friends\"\n *   description=\"Earn rewards for each friend who signs up\"\n *   rewardDescription=\"Get 1 month free for each referral\"\n * />\n * ```\n */\nexport function ReferralCard(props: ReferralCardProps) {\n\treturn (\n\t\t<RequireSdk services={['analytics']} componentType=\"referral\" theme={props.theme}>\n\t\t\t<ReferralCardInner {...props} />\n\t\t</RequireSdk>\n\t)\n}\n\n/** Inner component that safely uses platform hooks */\nfunction ReferralCardInner({\n\ttheme = defaultTheme,\n\tonSuccess,\n\tonError,\n\tclassName,\n\ttitle = 'Refer a Friend',\n\tdescription = 'Share your referral link and earn rewards',\n\tshowStats = true,\n\tshowShare = true,\n\trewardDescription = 'Earn rewards for each successful referral',\n}: ReferralCardProps) {\n\tconst {\n\t\tstats,\n\t\tcode,\n\t\tlink,\n\t\tisLoading,\n\t\terror: referralError,\n\t\tcopyLink,\n\t\tcopyCode,\n\t\tregenerateCode,\n\t} = useReferral()\n\tconst styles = baseStyles(theme)\n\tconst linkId = useId()\n\n\tconst [copied, setCopied] = useState<'link' | 'code' | null>(null)\n\tconst [isRegenerating, setIsRegenerating] = useState(false)\n\tconst [error, setError] = useState<string | null>(null)\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// Clear copied state\n\tuseEffect(() => {\n\t\tif (copied) {\n\t\t\tconst timer = setTimeout(() => setCopied(null), UI_COPY_FEEDBACK_MS)\n\t\t\treturn () => clearTimeout(timer)\n\t\t}\n\t}, [copied])\n\n\t// Handle copy link\n\tconst handleCopyLink = async () => {\n\t\ttry {\n\t\t\tawait copyLink()\n\t\t\tsetCopied('link')\n\t\t\tonSuccess?.('Link copied to clipboard')\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to copy link'\n\t\t\tsetError(message)\n\t\t\tonError?.(message)\n\t\t}\n\t}\n\n\t// Handle copy code\n\tconst handleCopyCode = async () => {\n\t\ttry {\n\t\t\tawait copyCode()\n\t\t\tsetCopied('code')\n\t\t\tonSuccess?.('Code copied to clipboard')\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to copy code'\n\t\t\tsetError(message)\n\t\t\tonError?.(message)\n\t\t}\n\t}\n\n\t// Handle regenerate code\n\tconst handleRegenerateCode = async () => {\n\t\tif (!confirm('Are you sure? Your existing referral link will stop working.')) {\n\t\t\treturn\n\t\t}\n\n\t\tsetIsRegenerating(true)\n\t\ttry {\n\t\t\tawait regenerateCode()\n\t\t\tonSuccess?.('Referral code regenerated')\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to regenerate code'\n\t\t\tsetError(message)\n\t\t\tonError?.(message)\n\t\t} finally {\n\t\t\tsetIsRegenerating(false)\n\t\t}\n\t}\n\n\t// Share on Twitter/X\n\tconst shareOnTwitter = () => {\n\t\tconst text = encodeURIComponent(`Check this out! ${link}`)\n\t\twindow.open(`https://twitter.com/intent/tweet?text=${text}`, '_blank')\n\t}\n\n\t// Share on LinkedIn\n\tconst shareOnLinkedIn = () => {\n\t\twindow.open(\n\t\t\t`https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(link || '')}`,\n\t\t\t'_blank',\n\t\t)\n\t}\n\n\t// Share via email\n\tconst shareViaEmail = () => {\n\t\tconst subject = encodeURIComponent('Check this out!')\n\t\tconst body = encodeURIComponent(`I thought you might be interested in this: ${link}`)\n\t\twindow.location.href = `mailto:?subject=${subject}&body=${body}`\n\t}\n\n\tconst cardStyles: React.CSSProperties = mergeStyles(styles.card, {\n\t\tpadding: '1.5rem',\n\t})\n\n\tif (isLoading) {\n\t\treturn (\n\t\t\t<div style={cardStyles} className={className}>\n\t\t\t\t<div style={mergeStyles(styles.flexCenter, { padding: '2rem' })}>\n\t\t\t\t\t<span\n\t\t\t\t\t\tstyle={mergeStyles(styles.spinner, {\n\t\t\t\t\t\t\twidth: '2rem',\n\t\t\t\t\t\t\theight: '2rem',\n\t\t\t\t\t\t})}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t)\n\t}\n\n\treturn (\n\t\t<div style={cardStyles} className={className}>\n\t\t\t{/* Header */}\n\t\t\t<div style={{ marginBottom: '1.5rem' }}>\n\t\t\t\t<h3 style={{ margin: 0, fontSize: theme.fontSizeLg, fontWeight: 600 }}>{title}</h3>\n\t\t\t\t<p\n\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\t{description}\n\t\t\t\t</p>\n\t\t\t</div>\n\n\t\t\t{/* Alerts */}\n\t\t\t{(error || referralError) && (\n\t\t\t\t<div style={mergeStyles(styles.alert, styles.alertError, styles.mb4)}>\n\t\t\t\t\t{error || referralError?.message}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Referral Link */}\n\t\t\t{link && (\n\t\t\t\t<div style={{ marginBottom: '1.5rem' }}>\n\t\t\t\t\t<label htmlFor={linkId} style={styles.label}>\n\t\t\t\t\t\tYour Referral Link\n\t\t\t\t\t</label>\n\t\t\t\t\t<div style={mergeStyles(styles.flexRow, { gap: '0.5rem' })}>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\tid={linkId}\n\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\tvalue={link}\n\t\t\t\t\t\t\treadOnly\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.input, {\n\t\t\t\t\t\t\t\tflex: 1,\n\t\t\t\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={handleCopyLink}\n\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\t\t\tcopied === 'link' ? styles.buttonPrimary : styles.buttonOutline,\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{copied === 'link' ? (\n\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t<CheckIcon size={16} />\n\t\t\t\t\t\t\t\t\tCopied!\n\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t<CopyIcon size={16} />\n\t\t\t\t\t\t\t\t\tCopy\n\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Referral Code */}\n\t\t\t{code && (\n\t\t\t\t<fieldset style={{ marginBottom: '1.5rem', border: 'none', padding: 0, margin: 0 }}>\n\t\t\t\t\t<legend style={mergeStyles(styles.label, { padding: 0 })}>Your Referral Code</legend>\n\t\t\t\t\t<div style={mergeStyles(styles.flexRow, { gap: '0.5rem' })}>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tflex: 1,\n\t\t\t\t\t\t\t\tpadding: '0.5rem 1rem',\n\t\t\t\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\t\t\t\tfontFamily: 'monospace',\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeLg,\n\t\t\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\t\t\tletterSpacing: '0.05em',\n\t\t\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{code}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={handleCopyCode}\n\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\t\t\tcopied === 'code' ? styles.buttonPrimary : styles.buttonOutline,\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{copied === 'code' ? <CheckIcon size={16} /> : <CopyIcon size={16} />}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={handleRegenerateCode}\n\t\t\t\t\t\t\tdisabled={isRegenerating}\n\t\t\t\t\t\t\ttitle=\"Regenerate code\"\n\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\t\t\tstyles.buttonOutline,\n\t\t\t\t\t\t\t\tisRegenerating ? styles.buttonDisabled : {},\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{isRegenerating ? <span style={styles.spinner} /> : <RefreshIcon size={16} />}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</fieldset>\n\t\t\t)}\n\n\t\t\t{/* Reward Info */}\n\t\t\t{rewardDescription && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tpadding: '1rem',\n\t\t\t\t\t\tbackgroundColor: `${theme.colorPrimary}10`,\n\t\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\t\tmarginBottom: '1.5rem',\n\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\tgap: '0.75rem',\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<GiftIcon color={theme.colorPrimary} />\n\t\t\t\t\t<span style={{ fontSize: theme.fontSizeSm, color: theme.colorForeground }}>\n\t\t\t\t\t\t{rewardDescription}\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Stats */}\n\t\t\t{showStats && stats && (\n\t\t\t\t<div style={{ marginBottom: '1.5rem' }}>\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tdisplay: 'grid',\n\t\t\t\t\t\t\tgridTemplateColumns: 'repeat(3, 1fr)',\n\t\t\t\t\t\t\tgap: '1rem',\n\t\t\t\t\t\t\tpadding: '1rem',\n\t\t\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div style={styles.textCenter}>\n\t\t\t\t\t\t\t<div style={{ fontSize: '1.5rem', fontWeight: 700 }}>{stats.totalReferrals || 0}</div>\n\t\t\t\t\t\t\t<div style={mergeStyles(styles.textXs, styles.textMuted)}>Total Referrals</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div style={styles.textCenter}>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tfontSize: '1.5rem',\n\t\t\t\t\t\t\t\t\tfontWeight: 700,\n\t\t\t\t\t\t\t\t\tcolor: theme.colorSuccess,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{stats.completedReferrals || 0}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div style={mergeStyles(styles.textXs, styles.textMuted)}>Successful</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div style={styles.textCenter}>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tfontSize: '1.5rem',\n\t\t\t\t\t\t\t\t\tfontWeight: 700,\n\t\t\t\t\t\t\t\t\tcolor: theme.colorPrimary,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{stats.pendingReferrals || 0}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div style={mergeStyles(styles.textXs, styles.textMuted)}>Pending</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Share Buttons */}\n\t\t\t{showShare && link && (\n\t\t\t\t<fieldset style={{ border: 'none', padding: 0, margin: 0 }}>\n\t\t\t\t\t<legend style={mergeStyles(styles.label, { padding: 0 })}>Share via</legend>\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={mergeStyles(styles.flexRow, {\n\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\tflexWrap: 'wrap',\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={shareOnTwitter}\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, {\n\t\t\t\t\t\t\t\tbackgroundColor: '#1DA1F2',\n\t\t\t\t\t\t\t\tcolor: '#fff',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<TwitterIcon size={16} />\n\t\t\t\t\t\t\tTwitter\n\t\t\t\t\t\t</button>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={shareOnLinkedIn}\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, {\n\t\t\t\t\t\t\t\tbackgroundColor: '#0077B5',\n\t\t\t\t\t\t\t\tcolor: '#fff',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<LinkedInIcon size={16} />\n\t\t\t\t\t\t\tLinkedIn\n\t\t\t\t\t\t</button>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={shareViaEmail}\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<EmailIcon size={16} />\n\t\t\t\t\t\t\tEmail\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</fieldset>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n// Icons\nfunction CopyIcon({ size = 24 }: { size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\" />\n\t\t\t<path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\" />\n\t\t</svg>\n\t)\n}\n\nfunction CheckIcon({ size = 24 }: { size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<polyline points=\"20 6 9 17 4 12\" />\n\t\t</svg>\n\t)\n}\n\nfunction RefreshIcon({ size = 24 }: { size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\" />\n\t\t\t<path d=\"M21 3v5h-5\" />\n\t\t\t<path d=\"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16\" />\n\t\t\t<path d=\"M8 16H3v5\" />\n\t\t</svg>\n\t)\n}\n\nfunction GiftIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"20\"\n\t\t\theight=\"20\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<polyline points=\"20 12 20 22 4 22 4 12\" />\n\t\t\t<rect x=\"2\" y=\"7\" width=\"20\" height=\"5\" />\n\t\t\t<line x1=\"12\" y1=\"22\" x2=\"12\" y2=\"7\" />\n\t\t\t<path d=\"M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z\" />\n\t\t\t<path d=\"M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z\" />\n\t\t</svg>\n\t)\n}\n\nfunction TwitterIcon({ size = 24 }: { size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"currentColor\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z\" />\n\t\t</svg>\n\t)\n}\n\nfunction LinkedInIcon({ size = 24 }: { size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"currentColor\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z\" />\n\t\t</svg>\n\t)\n}\n\nfunction EmailIcon({ size = 24 }: { size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z\" />\n\t\t\t<polyline points=\"22,6 12,13 2,6\" />\n\t\t</svg>\n\t)\n}\n","/**\n * Security Settings Component\n *\n * Full security management: 2FA setup, password change, active sessions, login history.\n * Self-contained with CSS-in-JS styles.\n */\n\n'use client'\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useCallback, useEffect, useId, useState } from 'react'\nimport {\n\tMS_PER_DAY,\n\tMS_PER_HOUR,\n\tMS_PER_MINUTE,\n\tSTALE_TIME_FREQUENT_MS,\n\tSTALE_TIME_STABLE_MS,\n\tUI_NOTIFICATION_MS,\n} from '../../constants'\nimport { useSecurityContext, useUserContext } from '../services-context'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\nexport interface TwoFactorStatus {\n\tenabled: boolean\n\tenabledAt?: string\n\tmethod?: 'totp' | 'sms'\n}\n\ninterface ActiveSession {\n\tid: string\n\tcurrent: boolean\n\tdevice: string\n\tbrowser: string\n\tip: string\n\tlocation?: string\n\tlastActive?: string\n\tcreatedAt?: string\n}\n\nexport interface LoginHistoryEntry {\n\tid: string\n\tip: string\n\tdevice: string\n\tbrowser: string\n\tlocation?: string\n\tsuccess: boolean\n\tcreatedAt: string\n}\n\nexport interface SecuritySettingsProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Called on successful update */\n\tonSuccess?: (message: string) => void\n\t/** Called on error */\n\tonError?: (error: string) => void\n\t/** Custom class name */\n\tclassName?: string\n\t/** Show 2FA section */\n\tshow2FA?: boolean\n\t/** Show password section */\n\tshowPassword?: boolean\n\t/** Show sessions section */\n\tshowSessions?: boolean\n\t/** Show login history */\n\tshowLoginHistory?: boolean\n}\n\n/**\n * Full security settings component\n *\n * @example\n * ```tsx\n * <SecuritySettings\n *   onSuccess={(msg) => toast.success(msg)}\n *   onError={(msg) => toast.error(msg)}\n * />\n * ```\n */\nexport function SecuritySettings({\n\ttheme = defaultTheme,\n\tonSuccess,\n\tonError,\n\tclassName,\n\tshow2FA = true,\n\tshowPassword = true,\n\tshowSessions = true,\n\tshowLoginHistory = true,\n}: SecuritySettingsProps) {\n\tconst userContext = useUserContext()\n\tconst securityContext = useSecurityContext()\n\tconst queryClient = useQueryClient()\n\tconst styles = baseStyles(theme)\n\tconst verifyCodeId = useId()\n\tconst currentPasswordId = useId()\n\tconst newPasswordId = useId()\n\tconst confirmPasswordId = useId()\n\n\t// UI state for messages\n\tconst [error, setError] = useState<string | null>(null)\n\tconst [success, setSuccess] = useState<string | null>(null)\n\n\t// 2FA setup UI state\n\tconst [showSetup2FA, setShowSetup2FA] = useState(false)\n\tconst [totpSecret, setTotpSecret] = useState<string | null>(null)\n\tconst [totpQrCode, setTotpQrCode] = useState<string | null>(null)\n\tconst [verifyCode, setVerifyCode] = useState('')\n\n\t// Password change UI state\n\tconst [showPasswordChange, setShowPasswordChange] = useState(false)\n\tconst [currentPassword, setCurrentPassword] = useState('')\n\tconst [newPassword, setNewPassword] = useState('')\n\tconst [confirmPassword, setConfirmPassword] = useState('')\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// React Query for 2FA status\n\tconst twoFactorQuery = useQuery({\n\t\tqueryKey: ['sylphx', 'security', '2fa-status'],\n\t\tqueryFn: async () => {\n\t\t\tconst data = await securityContext.getTwoFactorStatus()\n\t\t\treturn {\n\t\t\t\tenabled: data.enabled,\n\t\t\t\tmethod: data.enabled ? ('totp' as const) : undefined,\n\t\t\t}\n\t\t},\n\t\tenabled: show2FA,\n\t\tstaleTime: STALE_TIME_STABLE_MS, // 5 min\n\t})\n\n\t// React Query for sessions\n\tconst sessionsQuery = useQuery({\n\t\tqueryKey: ['sylphx', 'security', 'sessions'],\n\t\tqueryFn: async () => {\n\t\t\tconst data = await userContext.getSessions()\n\t\t\treturn data.map((s) => ({\n\t\t\t\tid: s.id,\n\t\t\t\tcurrent: s.isCurrent ?? false,\n\t\t\t\tdevice: s.deviceType || s.device || 'Unknown',\n\t\t\t\tbrowser: s.browser || 'Unknown',\n\t\t\t\tip: s.ipAddress || 'Unknown',\n\t\t\t\tlocation:\n\t\t\t\t\ts.city && s.country ? `${s.city}, ${s.country}` : s.location || s.country || undefined,\n\t\t\t\tlastActive: s.lastActiveAt || s.createdAt,\n\t\t\t\tcreatedAt: s.createdAt,\n\t\t\t}))\n\t\t},\n\t\tenabled: showSessions,\n\t\tstaleTime: STALE_TIME_FREQUENT_MS, // 1 min - sessions can change\n\t})\n\n\t// React Query for login history\n\tconst loginHistoryQuery = useQuery({\n\t\tqueryKey: ['sylphx', 'security', 'login-history'],\n\t\tqueryFn: async () => {\n\t\t\tconst data = await userContext.getLoginHistory({ limit: 10 })\n\t\t\treturn data.map((h) => ({\n\t\t\t\tid: h.id,\n\t\t\t\tip: h.ipAddress || 'Unknown',\n\t\t\t\tdevice: h.device || 'Unknown',\n\t\t\t\tbrowser: h.browser || 'Unknown',\n\t\t\t\tlocation: h.location ?? undefined,\n\t\t\t\tsuccess: h.success,\n\t\t\t\tcreatedAt: h.loginAt.toISOString(),\n\t\t\t}))\n\t\t},\n\t\tenabled: showLoginHistory,\n\t\tstaleTime: STALE_TIME_FREQUENT_MS, // 1 min\n\t})\n\n\t// Derived state from queries\n\tconst twoFactor = twoFactorQuery.data ?? { enabled: false }\n\tconst sessions = sessionsQuery.data ?? []\n\tconst loginHistory = loginHistoryQuery.data ?? []\n\tconst isLoading =\n\t\ttwoFactorQuery.isLoading || sessionsQuery.isLoading || loginHistoryQuery.isLoading\n\n\t// Combined query error\n\tconst queryError = twoFactorQuery.error || sessionsQuery.error || loginHistoryQuery.error\n\tuseEffect(() => {\n\t\tif (queryError) {\n\t\t\tconst message =\n\t\t\t\tqueryError instanceof Error ? queryError.message : 'Failed to load security settings'\n\t\t\tsetError(message)\n\t\t\tonError?.(message)\n\t\t}\n\t}, [queryError, onError])\n\n\t// Clear messages after timeout\n\tuseEffect(() => {\n\t\tif (success || error) {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tsetSuccess(null)\n\t\t\t\tsetError(null)\n\t\t\t}, UI_NOTIFICATION_MS)\n\t\t\treturn () => clearTimeout(timer)\n\t\t}\n\t}, [success, error])\n\n\t// Mutation: Start 2FA setup\n\tconst setup2FAMutation = useMutation({\n\t\tmutationFn: () => securityContext.twoFactorSetup(),\n\t\tonSuccess: (data) => {\n\t\t\tsetTotpSecret(data.secret)\n\t\t\tsetTotpQrCode((data as { uri?: string }).uri ?? null)\n\t\t\tsetShowSetup2FA(true)\n\t\t},\n\t\tonError: (err) => {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to start 2FA setup'\n\t\t\tsetError(message)\n\t\t\tonError?.(message)\n\t\t},\n\t})\n\n\t// Mutation: Enable 2FA (verify code)\n\tconst enable2FAMutation = useMutation({\n\t\tmutationFn: (code: string) => securityContext.twoFactorVerify(code),\n\t\tonSuccess: () => {\n\t\t\tqueryClient.setQueryData(['sylphx', 'security', '2fa-status'], {\n\t\t\t\tenabled: true,\n\t\t\t\tmethod: 'totp',\n\t\t\t})\n\t\t\tsetShowSetup2FA(false)\n\t\t\tsetVerifyCode('')\n\t\t\tsetSuccess('Two-factor authentication enabled')\n\t\t\tonSuccess?.('Two-factor authentication enabled')\n\t\t},\n\t\tonError: (err) => {\n\t\t\tconst message = err instanceof Error ? err.message : 'Invalid verification code'\n\t\t\tsetError(message)\n\t\t\tonError?.(message)\n\t\t},\n\t})\n\n\t// Mutation: Disable 2FA\n\tconst disable2FAMutation = useMutation({\n\t\tmutationFn: (code: string) => securityContext.twoFactorDisable(code),\n\t\tonSuccess: () => {\n\t\t\tqueryClient.setQueryData(['sylphx', 'security', '2fa-status'], {\n\t\t\t\tenabled: false,\n\t\t\t})\n\t\t\tsetSuccess('Two-factor authentication disabled')\n\t\t\tonSuccess?.('Two-factor authentication disabled')\n\t\t},\n\t\tonError: (err) => {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to disable 2FA'\n\t\t\tsetError(message)\n\t\t\tonError?.(message)\n\t\t},\n\t})\n\n\t// Mutation: Change password\n\tconst changePasswordMutation = useMutation({\n\t\tmutationFn: ({ current, newPwd }: { current: string; newPwd: string }) =>\n\t\t\tuserContext.changePassword(current, newPwd),\n\t\tonSuccess: () => {\n\t\t\tsetShowPasswordChange(false)\n\t\t\tsetCurrentPassword('')\n\t\t\tsetNewPassword('')\n\t\t\tsetConfirmPassword('')\n\t\t\tsetSuccess('Password changed successfully')\n\t\t\tonSuccess?.('Password changed successfully')\n\t\t},\n\t\tonError: (err) => {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to change password'\n\t\t\tsetError(message)\n\t\t\tonError?.(message)\n\t\t},\n\t})\n\n\t// Mutation: Revoke session\n\tconst revokeSessionMutation = useMutation({\n\t\tmutationFn: (sessionId: string) => userContext.revokeSession(sessionId),\n\t\tonSuccess: (_data, sessionId) => {\n\t\t\tqueryClient.setQueryData<ActiveSession[]>(\n\t\t\t\t['sylphx', 'security', 'sessions'],\n\t\t\t\t(prev) => prev?.filter((s) => s.id !== sessionId) ?? [],\n\t\t\t)\n\t\t\tsetSuccess('Session revoked')\n\t\t\tonSuccess?.('Session revoked')\n\t\t},\n\t\tonError: (err) => {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to revoke session'\n\t\t\tsetError(message)\n\t\t\tonError?.(message)\n\t\t},\n\t})\n\n\t// Mutation: Revoke all sessions\n\tconst revokeAllSessionsMutation = useMutation({\n\t\tmutationFn: () => userContext.revokeAllSessions(),\n\t\tonSuccess: () => {\n\t\t\tqueryClient.setQueryData<ActiveSession[]>(\n\t\t\t\t['sylphx', 'security', 'sessions'],\n\t\t\t\t(prev) => prev?.filter((s) => s.current) ?? [],\n\t\t\t)\n\t\t\tsetSuccess('All other sessions revoked')\n\t\t\tonSuccess?.('All other sessions revoked')\n\t\t},\n\t\tonError: (err) => {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to revoke sessions'\n\t\t\tsetError(message)\n\t\t\tonError?.(message)\n\t\t},\n\t})\n\n\t// Handler: Start 2FA setup\n\tconst handleStart2FASetup = useCallback(() => {\n\t\tsetup2FAMutation.mutate()\n\t}, [setup2FAMutation])\n\n\t// Handler: Enable 2FA\n\tconst handleEnable2FA = useCallback(\n\t\t(e: React.FormEvent) => {\n\t\t\te.preventDefault()\n\t\t\tif (!verifyCode || verifyCode.length !== 6) {\n\t\t\t\tsetError('Please enter a 6-digit code')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tenable2FAMutation.mutate(verifyCode)\n\t\t},\n\t\t[verifyCode, enable2FAMutation],\n\t)\n\n\t// Handler: Disable 2FA\n\tconst handleDisable2FA = useCallback(() => {\n\t\tconst code = prompt('Enter your 2FA code to disable two-factor authentication:')\n\t\tif (!code) return\n\t\tdisable2FAMutation.mutate(code)\n\t}, [disable2FAMutation])\n\n\t// Handler: Change password\n\tconst handlePasswordChange = useCallback(\n\t\t(e: React.FormEvent) => {\n\t\t\te.preventDefault()\n\n\t\t\tif (newPassword !== confirmPassword) {\n\t\t\t\tsetError('Passwords do not match')\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (newPassword.length < 12) {\n\t\t\t\tsetError('Password must be at least 12 characters')\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tchangePasswordMutation.mutate({\n\t\t\t\tcurrent: currentPassword,\n\t\t\t\tnewPwd: newPassword,\n\t\t\t})\n\t\t},\n\t\t[newPassword, confirmPassword, currentPassword, changePasswordMutation],\n\t)\n\n\t// Handler: Revoke session\n\tconst handleRevokeSession = useCallback(\n\t\t(sessionId: string) => {\n\t\t\trevokeSessionMutation.mutate(sessionId)\n\t\t},\n\t\t[revokeSessionMutation],\n\t)\n\n\t// Handler: Revoke all sessions\n\tconst handleRevokeAllSessions = useCallback(() => {\n\t\tif (!confirm('Are you sure you want to sign out all other devices?')) {\n\t\t\treturn\n\t\t}\n\t\trevokeAllSessionsMutation.mutate()\n\t}, [revokeAllSessionsMutation])\n\n\t// Derived loading states for UI\n\tconst isEnabling2FA = enable2FAMutation.isPending\n\tconst isChangingPassword = changePasswordMutation.isPending\n\n\tconst cardStyles: React.CSSProperties = mergeStyles(styles.card, {\n\t\tpadding: '1rem',\n\t\tmarginBottom: '1rem',\n\t})\n\n\tif (isLoading) {\n\t\treturn (\n\t\t\t<div style={mergeStyles(styles.flexCenter, { padding: '3rem' })} className={className}>\n\t\t\t\t<span style={mergeStyles(styles.spinner, { width: '2rem', height: '2rem' })} />\n\t\t\t</div>\n\t\t)\n\t}\n\n\treturn (\n\t\t<div className={className}>\n\t\t\t{/* Alerts */}\n\t\t\t{success && (\n\t\t\t\t<div style={mergeStyles(styles.alert, styles.alertSuccess, styles.mb4)}>{success}</div>\n\t\t\t)}\n\t\t\t{error && <div style={mergeStyles(styles.alert, styles.alertError, styles.mb4)}>{error}</div>}\n\n\t\t\t{/* Two-Factor Authentication */}\n\t\t\t{show2FA && (\n\t\t\t\t<div style={cardStyles}>\n\t\t\t\t\t<div style={styles.flexBetween}>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<h4 style={{ margin: 0, fontWeight: 500 }}>Two-Factor Authentication</h4>\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tAdd an extra layer of security to your account\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t{twoFactor.enabled ? (\n\t\t\t\t\t\t\t<span style={mergeStyles(styles.badge, styles.badgeSuccess)}>Enabled</span>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.badge, {\n\t\t\t\t\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tNot enabled\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{!twoFactor.enabled && !showSetup2FA && (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={handleStart2FASetup}\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary, {\n\t\t\t\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<ShieldIcon size={16} />\n\t\t\t\t\t\t\tEnable 2FA\n\t\t\t\t\t\t</button>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{twoFactor.enabled && (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={handleDisable2FA}\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonDestructive, {\n\t\t\t\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tDisable 2FA\n\t\t\t\t\t\t</button>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* 2FA Setup Flow */}\n\t\t\t\t\t{showSetup2FA && totpQrCode && (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tmarginTop: '1.5rem',\n\t\t\t\t\t\t\t\tpaddingTop: '1rem',\n\t\t\t\t\t\t\t\tborderTop: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<h5 style={{ margin: '0 0 0.5rem', fontWeight: 500 }}>Setup Instructions</h5>\n\t\t\t\t\t\t\t<ol\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, {\n\t\t\t\t\t\t\t\t\tpaddingLeft: '1.25rem',\n\t\t\t\t\t\t\t\t\tmargin: '0 0 1rem',\n\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<li>Download an authenticator app (Google Authenticator, Authy, etc.)</li>\n\t\t\t\t\t\t\t\t<li>Scan the QR code below or enter the secret key</li>\n\t\t\t\t\t\t\t\t<li>Enter the 6-digit code from the app</li>\n\t\t\t\t\t\t\t</ol>\n\n\t\t\t\t\t\t\t<div style={mergeStyles(styles.flexCenter, { marginBottom: '1rem' })}>\n\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\tsrc={totpQrCode}\n\t\t\t\t\t\t\t\t\talt=\"2FA QR Code\"\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\twidth: '160px',\n\t\t\t\t\t\t\t\t\t\theight: '160px',\n\t\t\t\t\t\t\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t{totpSecret && (\n\t\t\t\t\t\t\t\t<div style={{ marginBottom: '1rem' }}>\n\t\t\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\t\t\t\tmargin: '0 0 0.25rem',\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tOr enter this secret manually:\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t\t<code\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\t\t\t\t\t\tpadding: '0.5rem',\n\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\t\t\t\tfontFamily: 'monospace',\n\t\t\t\t\t\t\t\t\t\t\twordBreak: 'break-all',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{totpSecret}\n\t\t\t\t\t\t\t\t\t</code>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t<form onSubmit={handleEnable2FA}>\n\t\t\t\t\t\t\t\t<div style={styles.formGroup}>\n\t\t\t\t\t\t\t\t\t<label htmlFor={verifyCodeId} style={styles.label}>\n\t\t\t\t\t\t\t\t\t\tVerification Code\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\t\tid={verifyCodeId}\n\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\tvalue={verifyCode}\n\t\t\t\t\t\t\t\t\t\tonChange={(e) => setVerifyCode(e.target.value.replace(/\\D/g, '').slice(0, 6))}\n\t\t\t\t\t\t\t\t\t\tplaceholder=\"000000\"\n\t\t\t\t\t\t\t\t\t\tmaxLength={6}\n\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.input, {\n\t\t\t\t\t\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\t\t\t\t\t\tletterSpacing: '0.5em',\n\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeLg,\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div style={mergeStyles(styles.flexRow, { gap: '0.5rem' })}>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\t\t\tdisabled={isEnabling2FA || verifyCode.length !== 6}\n\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\t\t\t\t\t\tstyles.buttonPrimary,\n\t\t\t\t\t\t\t\t\t\t\tisEnabling2FA || verifyCode.length !== 6 ? styles.buttonDisabled : {},\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{isEnabling2FA ? (\n\t\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t\t\t\t\t\t\t\tVerifying...\n\t\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t'Verify & Enable'\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\tsetShowSetup2FA(false)\n\t\t\t\t\t\t\t\t\t\t\tsetVerifyCode('')\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline)}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Password */}\n\t\t\t{showPassword && (\n\t\t\t\t<div style={cardStyles}>\n\t\t\t\t\t<div style={styles.flexBetween}>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<h4 style={{ margin: 0, fontWeight: 500 }}>Password</h4>\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tChange your account password\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t{!showPasswordChange && (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={() => setShowPasswordChange(true)}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tChange\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{showPasswordChange && (\n\t\t\t\t\t\t<form\n\t\t\t\t\t\t\tonSubmit={handlePasswordChange}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t\t\t\t\tpaddingTop: '1rem',\n\t\t\t\t\t\t\t\tborderTop: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div style={styles.formGroup}>\n\t\t\t\t\t\t\t\t<label htmlFor={currentPasswordId} style={styles.label}>\n\t\t\t\t\t\t\t\t\tCurrent Password\n\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\tid={currentPasswordId}\n\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\tvalue={currentPassword}\n\t\t\t\t\t\t\t\t\tonChange={(e) => setCurrentPassword(e.target.value)}\n\t\t\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t\t\t\tstyle={styles.input}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div style={styles.formGroup}>\n\t\t\t\t\t\t\t\t<label htmlFor={newPasswordId} style={styles.label}>\n\t\t\t\t\t\t\t\t\tNew Password\n\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\tid={newPasswordId}\n\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\tvalue={newPassword}\n\t\t\t\t\t\t\t\t\tonChange={(e) => setNewPassword(e.target.value)}\n\t\t\t\t\t\t\t\t\tminLength={12}\n\t\t\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t\t\t\tstyle={styles.input}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div style={styles.formGroup}>\n\t\t\t\t\t\t\t\t<label htmlFor={confirmPasswordId} style={styles.label}>\n\t\t\t\t\t\t\t\t\tConfirm New Password\n\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\tid={confirmPasswordId}\n\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\tvalue={confirmPassword}\n\t\t\t\t\t\t\t\t\tonChange={(e) => setConfirmPassword(e.target.value)}\n\t\t\t\t\t\t\t\t\tminLength={12}\n\t\t\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t\t\t\tstyle={styles.input}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div style={mergeStyles(styles.flexRow, { gap: '0.5rem' })}>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\t\tdisabled={isChangingPassword}\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\t\t\t\t\tstyles.buttonPrimary,\n\t\t\t\t\t\t\t\t\t\tisChangingPassword ? styles.buttonDisabled : {},\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{isChangingPassword ? (\n\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t\t\t\t\t\t\tChanging...\n\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t'Change Password'\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\tsetShowPasswordChange(false)\n\t\t\t\t\t\t\t\t\t\tsetCurrentPassword('')\n\t\t\t\t\t\t\t\t\t\tsetNewPassword('')\n\t\t\t\t\t\t\t\t\t\tsetConfirmPassword('')\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</form>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Active Sessions */}\n\t\t\t{showSessions && (\n\t\t\t\t<div style={cardStyles}>\n\t\t\t\t\t<div style={styles.flexBetween}>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<h4 style={{ margin: 0, fontWeight: 500 }}>Active Sessions</h4>\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{sessions.length} active session\n\t\t\t\t\t\t\t\t{sessions.length !== 1 ? 's' : ''}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t{sessions.length > 1 && (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={handleRevokeAllSessions}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tSign Out All Others\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div style={{ marginTop: '1rem' }}>\n\t\t\t\t\t\t{sessions.map((session) => (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tkey={session.id}\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tpadding: '0.75rem',\n\t\t\t\t\t\t\t\t\tbackgroundColor: session.current ? `${theme.colorPrimary}08` : 'transparent',\n\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\t\tborder: session.current\n\t\t\t\t\t\t\t\t\t\t? `1px solid ${theme.colorPrimary}30`\n\t\t\t\t\t\t\t\t\t\t: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<div style={styles.flexBetween}>\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.flexRow, {\n\t\t\t\t\t\t\t\t\t\t\tgap: '0.75rem',\n\t\t\t\t\t\t\t\t\t\t\talignItems: 'flex-start',\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<DeviceIcon device={session.device} theme={theme} />\n\t\t\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.flexRow, {\n\t\t\t\t\t\t\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{session.browser} on {session.device}\n\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t{session.current && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span style={mergeStyles(styles.badge, styles.badgePrimary)}>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tCurrent\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textXs, styles.textMuted, {\n\t\t\t\t\t\t\t\t\t\t\t\t\tmarginTop: '0.25rem',\n\t\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{session.location && `${session.location} · `}\n\t\t\t\t\t\t\t\t\t\t\t\t{session.ip} · Last active{' '}\n\t\t\t\t\t\t\t\t\t\t\t\t{session.lastActive ? formatTimeAgo(session.lastActive) : 'Unknown'}\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t{!session.current && (\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleRevokeSession(session.id)}\n\t\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonGhost, {\n\t\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorDestructive,\n\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\tRevoke\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Login History */}\n\t\t\t{showLoginHistory && loginHistory.length > 0 && (\n\t\t\t\t<div style={cardStyles}>\n\t\t\t\t\t<h4 style={{ margin: '0 0 1rem', fontWeight: 500 }}>Recent Login Activity</h4>\n\t\t\t\t\t<div style={{ maxHeight: '300px', overflowY: 'auto' }}>\n\t\t\t\t\t\t{loginHistory.slice(0, 10).map((entry) => (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tkey={entry.id}\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tpadding: '0.5rem 0',\n\t\t\t\t\t\t\t\t\tborderBottom: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\tgap: '0.75rem',\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\twidth: '8px',\n\t\t\t\t\t\t\t\t\t\theight: '8px',\n\t\t\t\t\t\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\t\t\t\t\t\tbackgroundColor: entry.success ? theme.colorSuccess : theme.colorDestructive,\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<div style={{ flex: 1 }}>\n\t\t\t\t\t\t\t\t\t<div style={{ fontSize: theme.fontSizeSm }}>\n\t\t\t\t\t\t\t\t\t\t{entry.browser} on {entry.device}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t<div style={mergeStyles(styles.textXs, styles.textMuted)}>\n\t\t\t\t\t\t\t\t\t\t{entry.location && `${entry.location} · `}\n\t\t\t\t\t\t\t\t\t\t{entry.ip} · {formatTimeAgo(entry.createdAt)}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\t\t\tstyles.badge,\n\t\t\t\t\t\t\t\t\t\tentry.success ? styles.badgeSuccess : styles.badgeDestructive,\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{entry.success ? 'Success' : 'Failed'}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n// Helper functions\nfunction formatTimeAgo(dateString: string): string {\n\tconst date = new Date(dateString)\n\tconst now = new Date()\n\tconst diffMs = now.getTime() - date.getTime()\n\tconst diffMins = Math.floor(diffMs / MS_PER_MINUTE)\n\tconst diffHours = Math.floor(diffMs / MS_PER_HOUR)\n\tconst diffDays = Math.floor(diffMs / MS_PER_DAY)\n\n\tif (diffMins < 1) return 'just now'\n\tif (diffMins < 60) return `${diffMins}m ago`\n\tif (diffHours < 24) return `${diffHours}h ago`\n\tif (diffDays < 7) return `${diffDays}d ago`\n\treturn date.toLocaleDateString()\n}\n\n// Icons\nfunction ShieldIcon({ size = 24 }: { size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z\" />\n\t\t</svg>\n\t)\n}\n\nfunction DeviceIcon({ device, theme }: { device: string; theme: ThemeVariables }) {\n\tconst isMobile = device.toLowerCase().includes('mobile') || device.toLowerCase().includes('phone')\n\n\tif (isMobile) {\n\t\treturn (\n\t\t\t<svg\n\t\t\t\twidth=\"20\"\n\t\t\t\theight=\"20\"\n\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\tfill=\"none\"\n\t\t\t\tstroke={theme.colorMutedForeground}\n\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\taria-hidden=\"true\"\n\t\t\t\tfocusable=\"false\"\n\t\t\t>\n\t\t\t\t<rect x=\"5\" y=\"2\" width=\"14\" height=\"20\" rx=\"2\" ry=\"2\" />\n\t\t\t\t<line x1=\"12\" y1=\"18\" x2=\"12.01\" y2=\"18\" />\n\t\t\t</svg>\n\t\t)\n\t}\n\n\treturn (\n\t\t<svg\n\t\t\twidth=\"20\"\n\t\t\theight=\"20\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={theme.colorMutedForeground}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<rect x=\"2\" y=\"3\" width=\"20\" height=\"14\" rx=\"2\" ry=\"2\" />\n\t\t\t<line x1=\"8\" y1=\"21\" x2=\"16\" y2=\"21\" />\n\t\t\t<line x1=\"12\" y1=\"17\" x2=\"12\" y2=\"21\" />\n\t\t</svg>\n\t)\n}\n","/**\n * Subscriber Preferences Component\n *\n * Allow users to manage their newsletter subscription preferences.\n * Self-contained with CSS-in-JS styles.\n */\n\n'use client'\n\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useEffect, useState } from 'react'\nimport { STALE_TIME_STABLE_MS } from '../../constants'\nimport { useNewsletter } from '../newsletter-hooks'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\nexport interface PreferenceOption {\n\tid: string\n\tlabel: string\n\tdescription?: string\n\tcategory?: string\n}\n\nexport interface SubscriberPreferencesProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Email address (required for preference lookup) */\n\temail: string\n\t/** Called on successful update */\n\tonSuccess?: (preferences: string[]) => void\n\t/** Called on error */\n\tonError?: (error: string) => void\n\t/** Custom class name */\n\tclassName?: string\n\t/** Component title */\n\ttitle?: string\n\t/** Component description */\n\tdescription?: string\n\t/** Available preference options */\n\toptions: PreferenceOption[]\n\t/** Show category groups */\n\tshowCategories?: boolean\n\t/** Show unsubscribe all option */\n\tshowUnsubscribeAll?: boolean\n\t/** Save button text */\n\tsaveButtonText?: string\n\t/** Unsubscribe button text */\n\tunsubscribeButtonText?: string\n}\n\n/**\n * Newsletter preference management\n *\n * @example\n * ```tsx\n * <SubscriberPreferences\n *   email=\"user@example.com\"\n *   title=\"Email Preferences\"\n *   options={[\n *     { id: 'product', label: 'Product Updates', category: 'Updates' },\n *     { id: 'blog', label: 'Blog Posts', category: 'Content' },\n *     { id: 'promo', label: 'Promotions', category: 'Marketing' },\n *   ]}\n * />\n * ```\n */\nexport function SubscriberPreferences({\n\ttheme = defaultTheme,\n\temail,\n\tonSuccess,\n\tonError,\n\tclassName,\n\ttitle = 'Email Preferences',\n\tdescription = \"Choose which emails you'd like to receive\",\n\toptions,\n\tshowCategories = false,\n\tshowUnsubscribeAll = true,\n\tsaveButtonText = 'Save Preferences',\n\tunsubscribeButtonText = 'Unsubscribe from All',\n}: SubscriberPreferencesProps) {\n\tconst { getPreferences, updatePreferences } = useNewsletter()\n\tconst queryClient = useQueryClient()\n\n\tconst styles = baseStyles(theme)\n\tconst [selectedPreferences, setSelectedPreferences] = useState<string[]>([])\n\tconst [saving, setSaving] = useState(false)\n\tconst [unsubscribing, setUnsubscribing] = useState(false)\n\tconst [error, setError] = useState<string | null>(null)\n\tconst [success, setSuccess] = useState<string | null>(null)\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// Fetch subscriber preferences with React Query\n\tconst prefsQuery = useQuery({\n\t\tqueryKey: ['sylphx', 'newsletter', 'preferences', email],\n\t\tqueryFn: async () => {\n\t\t\tconst prefs = await getPreferences(email)\n\t\t\t// Convert Record<string, boolean> to string[]\n\t\t\treturn Object.entries(prefs)\n\t\t\t\t.filter(([, enabled]) => enabled)\n\t\t\t\t.map(([key]) => key)\n\t\t},\n\t\tstaleTime: STALE_TIME_STABLE_MS, // 5 min\n\t})\n\n\t// Sync selectedPreferences with query data when it loads\n\tuseEffect(() => {\n\t\tif (prefsQuery.data) {\n\t\t\tsetSelectedPreferences(prefsQuery.data)\n\t\t}\n\t}, [prefsQuery.data])\n\n\tconst fetchLoading = prefsQuery.isLoading\n\n\tconst togglePreference = (id: string) => {\n\t\tsetSelectedPreferences((prev) =>\n\t\t\tprev.includes(id) ? prev.filter((p) => p !== id) : [...prev, id],\n\t\t)\n\t\tsetSuccess(null)\n\t\tsetError(null)\n\t}\n\n\tconst handleSave = async () => {\n\t\tsetSaving(true)\n\t\tsetError(null)\n\t\tsetSuccess(null)\n\n\t\ttry {\n\t\t\t// Convert string[] to Record<string, boolean>\n\t\t\tconst prefsRecord = options.reduce(\n\t\t\t\t(acc, opt) => {\n\t\t\t\t\tacc[opt.id] = selectedPreferences.includes(opt.id)\n\t\t\t\t\treturn acc\n\t\t\t\t},\n\t\t\t\t{} as Record<string, boolean>,\n\t\t\t)\n\n\t\t\tawait updatePreferences(email, prefsRecord)\n\t\t\t// Invalidate cache to refresh data\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: ['sylphx', 'newsletter', 'preferences', email],\n\t\t\t})\n\t\t\tsetSuccess('Preferences updated successfully')\n\t\t\tonSuccess?.(selectedPreferences)\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to update preferences'\n\t\t\tsetError(message)\n\t\t\tonError?.(message)\n\t\t} finally {\n\t\t\tsetSaving(false)\n\t\t}\n\t}\n\n\tconst handleUnsubscribeAll = async () => {\n\t\tif (!confirm('Are you sure you want to unsubscribe from all emails?')) {\n\t\t\treturn\n\t\t}\n\n\t\tsetUnsubscribing(true)\n\t\tsetError(null)\n\t\tsetSuccess(null)\n\n\t\ttry {\n\t\t\t// Disable all preferences by setting them to false\n\t\t\tconst prefsRecord = options.reduce(\n\t\t\t\t(acc, opt) => {\n\t\t\t\t\tacc[opt.id] = false\n\t\t\t\t\treturn acc\n\t\t\t\t},\n\t\t\t\t{} as Record<string, boolean>,\n\t\t\t)\n\t\t\tawait updatePreferences(email, prefsRecord)\n\t\t\t// Invalidate cache to refresh data\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: ['sylphx', 'newsletter', 'preferences', email],\n\t\t\t})\n\t\t\tsetSelectedPreferences([])\n\t\t\tsetSuccess('You have been unsubscribed from all emails')\n\t\t\tonSuccess?.([])\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to unsubscribe'\n\t\t\tsetError(message)\n\t\t\tonError?.(message)\n\t\t} finally {\n\t\t\tsetUnsubscribing(false)\n\t\t}\n\t}\n\n\t// Group options by category if enabled\n\tconst groupedOptions = showCategories\n\t\t? options.reduce(\n\t\t\t\t(groups, option) => {\n\t\t\t\t\tconst category = option.category || 'General'\n\t\t\t\t\tif (!groups[category]) groups[category] = []\n\t\t\t\t\tgroups[category].push(option)\n\t\t\t\t\treturn groups\n\t\t\t\t},\n\t\t\t\t{} as Record<string, PreferenceOption[]>,\n\t\t\t)\n\t\t: { '': options }\n\n\tconst loading = fetchLoading || saving || unsubscribing\n\n\treturn (\n\t\t<div className={className} style={mergeStyles(styles.card, { padding: '1.5rem' })}>\n\t\t\t{title && <h3 style={styles.cardTitle}>{title}</h3>}\n\t\t\t{description && <p style={styles.cardDescription}>{description}</p>}\n\n\t\t\t{fetchLoading ? (\n\t\t\t\t<div style={{ textAlign: 'center', padding: '2rem' }}>\n\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t<p\n\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t\t\t})}\n\t\t\t\t\t>\n\t\t\t\t\t\tLoading preferences...\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<div style={{ marginTop: '1.5rem' }}>\n\t\t\t\t\t\t{Object.entries(groupedOptions).map(([category, categoryOptions]) => (\n\t\t\t\t\t\t\t<div key={category} style={{ marginBottom: '1.5rem' }}>\n\t\t\t\t\t\t\t\t{showCategories && category && (\n\t\t\t\t\t\t\t\t\t<h4\n\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.label, {\n\t\t\t\t\t\t\t\t\t\t\tmarginBottom: '0.75rem',\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{category}\n\t\t\t\t\t\t\t\t\t</h4>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{categoryOptions.map((option) => (\n\t\t\t\t\t\t\t\t\t<label\n\t\t\t\t\t\t\t\t\t\tkey={option.id}\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\t\talignItems: 'flex-start',\n\t\t\t\t\t\t\t\t\t\t\tgap: '0.75rem',\n\t\t\t\t\t\t\t\t\t\t\tpadding: '0.75rem',\n\t\t\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: selectedPreferences.includes(option.id)\n\t\t\t\t\t\t\t\t\t\t\t\t? `${theme.colorPrimary}10`\n\t\t\t\t\t\t\t\t\t\t\t\t: 'transparent',\n\t\t\t\t\t\t\t\t\t\t\tborder: `1px solid ${selectedPreferences.includes(option.id) ? theme.colorPrimary : theme.colorBorder}`,\n\t\t\t\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\t\t\t\tcursor: loading ? 'not-allowed' : 'pointer',\n\t\t\t\t\t\t\t\t\t\t\ttransition: 'all 0.2s ease',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\t\t\t\tchecked={selectedPreferences.includes(option.id)}\n\t\t\t\t\t\t\t\t\t\t\tonChange={() => togglePreference(option.id)}\n\t\t\t\t\t\t\t\t\t\t\tdisabled={loading}\n\t\t\t\t\t\t\t\t\t\t\tstyle={{ marginTop: '0.25rem' }}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t<div style={{ flex: 1 }}>\n\t\t\t\t\t\t\t\t\t\t\t<span style={{ fontSize: theme.fontSizeBase }}>{option.label}</span>\n\t\t\t\t\t\t\t\t\t\t\t{option.description && (\n\t\t\t\t\t\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tmarginTop: '0.25rem',\n\t\t\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{option.description}\n\t\t\t\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{error && (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.alert, styles.alertError, {\n\t\t\t\t\t\t\t\tmarginBottom: '1rem',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{error}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{success && (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.alert, styles.alertSuccess, {\n\t\t\t\t\t\t\t\tmarginBottom: '1rem',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{success}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\n\t\t\t\t\t<div style={{ display: 'flex', gap: '1rem', marginTop: '1rem' }}>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={handleSave}\n\t\t\t\t\t\t\tdisabled={loading}\n\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\t\t\tstyles.buttonPrimary,\n\t\t\t\t\t\t\t\t{ flex: 1 },\n\t\t\t\t\t\t\t\tloading ? styles.buttonDisabled : {},\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{saving ? <span style={styles.spinner} /> : saveButtonText}\n\t\t\t\t\t\t</button>\n\n\t\t\t\t\t\t{showUnsubscribeAll && (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={handleUnsubscribeAll}\n\t\t\t\t\t\t\t\tdisabled={loading}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\t\t\t\t\tstyles.button,\n\t\t\t\t\t\t\t\t\tstyles.buttonDestructive,\n\t\t\t\t\t\t\t\t\tloading ? styles.buttonDisabled : {},\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{unsubscribing ? <span style={styles.spinner} /> : unsubscribeButtonText}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t</>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n","/**\n * Unsubscribe Confirm Component\n *\n * Standalone unsubscribe page component with confirmation flow.\n * Self-contained with CSS-in-JS styles.\n */\n\n'use client'\n\nimport { useEffect, useId, useState } from 'react'\nimport { UI_REDIRECT_DELAY_MS } from '../../constants'\nimport { useNewsletter } from '../newsletter-hooks'\nimport { safeRedirect } from '../security-utils'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\nexport interface UnsubscribeConfirmProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Email address from URL token */\n\temail: string\n\t/** Unsubscribe token from URL */\n\ttoken?: string\n\t/** Called on successful unsubscribe */\n\tonSuccess?: () => void\n\t/** Called on error */\n\tonError?: (error: string) => void\n\t/** Custom class name */\n\tclassName?: string\n\t/** Page title */\n\ttitle?: string\n\t/** Confirmation message */\n\tconfirmMessage?: string\n\t/** Success message */\n\tsuccessMessage?: string\n\t/** Show resubscribe option */\n\tshowResubscribe?: boolean\n\t/** Show reason selector */\n\tshowReasonSelector?: boolean\n\t/** Custom unsubscribe reasons */\n\treasons?: Array<{ id: string; label: string }>\n\t/** Redirect URL after unsubscribe */\n\tredirectUrl?: string\n\t/** Redirect delay in ms */\n\tredirectDelay?: number\n}\n\nconst DEFAULT_REASONS = [\n\t{ id: 'too_many', label: 'Too many emails' },\n\t{ id: 'not_relevant', label: 'Content not relevant to me' },\n\t{ id: 'never_signed_up', label: 'I never signed up' },\n\t{ id: 'other', label: 'Other reason' },\n]\n\n/**\n * Unsubscribe confirmation page\n *\n * @example\n * ```tsx\n * // In your /unsubscribe page\n * export default function UnsubscribePage({ searchParams }) {\n *   return (\n *     <UnsubscribeConfirm\n *       email={searchParams.email}\n *       token={searchParams.token}\n *       showReasonSelector\n *       redirectUrl=\"/\"\n *     />\n *   )\n * }\n * ```\n */\nexport function UnsubscribeConfirm({\n\ttheme = defaultTheme,\n\temail,\n\ttoken,\n\tonSuccess,\n\tonError,\n\tclassName,\n\ttitle = 'Unsubscribe',\n\tconfirmMessage = 'Are you sure you want to unsubscribe from our newsletter?',\n\tsuccessMessage = 'You have been successfully unsubscribed.',\n\tshowResubscribe = true,\n\tshowReasonSelector = false,\n\treasons = DEFAULT_REASONS,\n\tredirectUrl,\n\tredirectDelay = UI_REDIRECT_DELAY_MS,\n}: UnsubscribeConfirmProps) {\n\tconst { unsubscribe, subscribe } = useNewsletter()\n\tconst styles = baseStyles(theme)\n\tconst reasonId = useId()\n\n\tconst [status, setStatus] = useState<\n\t\t'pending' | 'processing' | 'success' | 'error' | 'resubscribed' | 'missing_token'\n\t>(() => (token ? 'pending' : 'missing_token'))\n\tconst [selectedReason, setSelectedReason] = useState<string>('')\n\tconst [error, setError] = useState<string | null>(null)\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// Handle redirect after success\n\tuseEffect(() => {\n\t\tif (status === 'success' && redirectUrl) {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tsafeRedirect(redirectUrl, { fallback: '/' })\n\t\t\t}, redirectDelay)\n\t\t\treturn () => clearTimeout(timer)\n\t\t}\n\t}, [status, redirectUrl, redirectDelay])\n\n\tconst handleUnsubscribe = async () => {\n\t\tif (!token) {\n\t\t\tsetError('Missing unsubscribe token')\n\t\t\tsetStatus('missing_token')\n\t\t\treturn\n\t\t}\n\n\t\tsetStatus('processing')\n\t\tsetError(null)\n\n\t\ttry {\n\t\t\tawait unsubscribe(email, token)\n\t\t\tsetStatus('success')\n\t\t\tonSuccess?.()\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to unsubscribe'\n\t\t\tsetError(message)\n\t\t\tsetStatus('error')\n\t\t\tonError?.(message)\n\t\t}\n\t}\n\n\tconst handleResubscribe = async () => {\n\t\tsetStatus('processing')\n\t\tsetError(null)\n\n\t\ttry {\n\t\t\tawait subscribe({ email })\n\t\t\tsetStatus('resubscribed')\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : 'Failed to resubscribe'\n\t\t\tsetError(message)\n\t\t\tsetStatus('error')\n\t\t}\n\t}\n\n\tconst renderContent = () => {\n\t\tswitch (status) {\n\t\t\tcase 'pending':\n\t\t\t\treturn (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<div style={{ color: theme.colorWarning }}>\n\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\twidth=\"48\"\n\t\t\t\t\t\t\t\theight=\"48\"\n\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\tfocusable=\"false\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<circle cx=\"12\" cy=\"12\" r=\"10\" />\n\t\t\t\t\t\t\t\t<line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n\t\t\t\t\t\t\t\t<line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t\t\t\t\tmarginBottom: '1.5rem',\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeBase,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{confirmMessage}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\tmarginBottom: '1.5rem',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tEmail: <strong>{email}</strong>\n\t\t\t\t\t\t</p>\n\n\t\t\t\t\t\t{showReasonSelector && (\n\t\t\t\t\t\t\t<div style={{ marginBottom: '1.5rem', textAlign: 'left' }}>\n\t\t\t\t\t\t\t\t<label\n\t\t\t\t\t\t\t\t\thtmlFor={reasonId}\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.label, {\n\t\t\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tWhy are you unsubscribing? (Optional)\n\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t<select\n\t\t\t\t\t\t\t\t\tid={reasonId}\n\t\t\t\t\t\t\t\t\tvalue={selectedReason}\n\t\t\t\t\t\t\t\t\tonChange={(e) => setSelectedReason(e.target.value)}\n\t\t\t\t\t\t\t\t\tstyle={styles.input}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<option value=\"\">Select a reason...</option>\n\t\t\t\t\t\t\t\t\t{reasons.map((reason) => (\n\t\t\t\t\t\t\t\t\t\t<option key={reason.id} value={reason.id}>\n\t\t\t\t\t\t\t\t\t\t\t{reason.label}\n\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t<div style={{ display: 'flex', gap: '1rem', justifyContent: 'center' }}>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={handleUnsubscribe}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonDestructive)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tUnsubscribe\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t{redirectUrl && (\n\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\thref={redirectUrl}\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonSecondary, {\n\t\t\t\t\t\t\t\t\t\ttextDecoration: 'none',\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</>\n\t\t\t\t)\n\n\t\t\tcase 'processing':\n\t\t\t\treturn (\n\t\t\t\t\t<div style={{ textAlign: 'center', padding: '2rem' }}>\n\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t\t<p style={{ marginTop: '1rem', fontSize: theme.fontSizeBase }}>Processing...</p>\n\t\t\t\t\t</div>\n\t\t\t\t)\n\n\t\t\tcase 'success':\n\t\t\t\treturn (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<div style={{ color: theme.colorSuccess }}>\n\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\twidth=\"48\"\n\t\t\t\t\t\t\t\theight=\"48\"\n\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\tfocusable=\"false\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\" />\n\t\t\t\t\t\t\t\t<polyline points=\"22 4 12 14.01 9 11.01\" />\n\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t\t\t\t\tcolor: theme.colorSuccess,\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeBase,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{successMessage}\n\t\t\t\t\t\t</p>\n\n\t\t\t\t\t\t{showResubscribe && (\n\t\t\t\t\t\t\t<div style={{ marginTop: '1.5rem' }}>\n\t\t\t\t\t\t\t\t<p style={mergeStyles(styles.textSm, styles.textMuted)}>Changed your mind?</p>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tonClick={handleResubscribe}\n\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonSecondary, {\n\t\t\t\t\t\t\t\t\t\tmarginTop: '0.5rem',\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tResubscribe\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{redirectUrl && (\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\t\tmarginTop: '1.5rem',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tRedirecting in {Math.ceil(redirectDelay / 1000)} seconds...\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</>\n\t\t\t\t)\n\n\t\t\tcase 'resubscribed':\n\t\t\t\treturn (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<div style={{ color: theme.colorSuccess }}>\n\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\twidth=\"48\"\n\t\t\t\t\t\t\t\theight=\"48\"\n\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\tfocusable=\"false\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\" />\n\t\t\t\t\t\t\t\t<polyline points=\"22 4 12 14.01 9 11.01\" />\n\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t\t\t\t\tcolor: theme.colorSuccess,\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeBase,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tWelcome back! You have been resubscribed.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t{redirectUrl && (\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\thref={redirectUrl}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary, {\n\t\t\t\t\t\t\t\t\tmarginTop: '1.5rem',\n\t\t\t\t\t\t\t\t\tdisplay: 'inline-block',\n\t\t\t\t\t\t\t\t\ttextDecoration: 'none',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tContinue\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</>\n\t\t\t\t)\n\n\t\t\tcase 'error':\n\t\t\t\treturn (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<div style={{ color: theme.colorDestructive }}>\n\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\twidth=\"48\"\n\t\t\t\t\t\t\t\theight=\"48\"\n\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\tfocusable=\"false\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<circle cx=\"12\" cy=\"12\" r=\"10\" />\n\t\t\t\t\t\t\t\t<line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\" />\n\t\t\t\t\t\t\t\t<line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\" />\n\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t\t\t\t\tcolor: theme.colorDestructive,\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeBase,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{error || 'Something went wrong'}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={() => setStatus('pending')}\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonSecondary, {\n\t\t\t\t\t\t\t\tmarginTop: '1.5rem',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tTry Again\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</>\n\t\t\t\t)\n\n\t\t\tcase 'missing_token':\n\t\t\t\treturn (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<div style={{ color: theme.colorDestructive }}>\n\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\twidth=\"48\"\n\t\t\t\t\t\t\t\theight=\"48\"\n\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\tfocusable=\"false\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<circle cx=\"12\" cy=\"12\" r=\"10\" />\n\t\t\t\t\t\t\t\t<line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\" />\n\t\t\t\t\t\t\t\t<line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\" />\n\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tmarginTop: '1rem',\n\t\t\t\t\t\t\t\tcolor: theme.colorDestructive,\n\t\t\t\t\t\t\t\tfontSize: theme.fontSizeBase,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tInvalid unsubscribe link\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.textSm, styles.textMuted, {\n\t\t\t\t\t\t\t\tmarginTop: '0.5rem',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tThe unsubscribe link is missing or expired. Please use the link from your email.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t{redirectUrl && (\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\thref={redirectUrl}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonSecondary, {\n\t\t\t\t\t\t\t\t\tmarginTop: '1.5rem',\n\t\t\t\t\t\t\t\t\tdisplay: 'inline-block',\n\t\t\t\t\t\t\t\t\ttextDecoration: 'none',\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tGo Back\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</>\n\t\t\t\t)\n\t\t}\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tclassName={className}\n\t\t\tstyle={mergeStyles(styles.card, {\n\t\t\t\tmaxWidth: '480px',\n\t\t\t\tmargin: '0 auto',\n\t\t\t\ttextAlign: 'center' as const,\n\t\t\t\tpadding: '2rem',\n\t\t\t})}\n\t\t>\n\t\t\t<h2 style={styles.cardTitle}>{title}</h2>\n\t\t\t{renderContent()}\n\t\t</div>\n\t)\n}\n","/**\n * User Profile Component\n *\n * Full user profile management with avatar, name, and settings.\n * Self-contained with CSS-in-JS styles.\n */\n\n'use client'\n\nimport { type FormEvent, useCallback, useEffect, useId, useRef, useState } from 'react'\nimport { STORAGE_DEFAULT_MAX_SIZE_BYTES, UI_NOTIFICATION_MS } from '../../constants'\nimport { RequireSdk, useUser } from '../hooks'\nimport { useUserContext } from '../services-context'\nimport { useStorage } from '../storage-hooks'\nimport { AccountSection } from './account-section'\nimport { BillingSection } from './billing-section'\nimport { NotificationSettings } from './notification-settings'\nimport { ReferralCard } from './referral-card'\nimport { SecuritySettings } from './security-settings'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\nexport type ProfileSection =\n\t| 'profile'\n\t| 'security'\n\t| 'billing'\n\t| 'notifications'\n\t| 'account'\n\t| 'referrals'\n\t| 'connected-accounts'\n\nexport interface UserProfileProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Sections to show */\n\tsections?: ProfileSection[]\n\t/** Called on successful update */\n\tonSuccess?: (message: string) => void\n\t/** Called on error */\n\tonError?: (error: string) => void\n\t/** Show the card wrapper (default: true) */\n\tshowCard?: boolean\n\t/** Custom header content */\n\theader?: React.ReactNode\n\t/** Custom footer content */\n\tfooter?: React.ReactNode\n\t/** Whether this is in a modal */\n\tisModal?: boolean\n\t/** Called when close is requested (modal mode) */\n\tonClose?: () => void\n}\n\ninterface ProfileFormState {\n\tname: string\n\timage: string\n}\n\n/**\n * User profile management component\n */\nexport function UserProfile(props: UserProfileProps) {\n\treturn (\n\t\t<RequireSdk services={['auth', 'storage']} componentType=\"user\" theme={props.theme}>\n\t\t\t<UserProfileInner {...props} />\n\t\t</RequireSdk>\n\t)\n}\n\n/** Inner component that safely uses platform hooks */\nfunction UserProfileInner({\n\ttheme = defaultTheme,\n\tsections = ['profile', 'security', 'notifications'],\n\tonSuccess,\n\tonError,\n\tshowCard = true,\n\theader,\n\tfooter,\n\tisModal = false,\n\tonClose,\n}: UserProfileProps) {\n\tconst { user, isLoading: isUserLoading, refresh: refreshUser } = useUser()\n\tconst userContext = useUserContext()\n\tconst { upload: uploadFile, isUploading: isUploadingAvatar } = useStorage()\n\tconst styles = baseStyles(theme)\n\tconst nameId = useId()\n\tconst emailId = useId()\n\n\tconst [activeSection, setActiveSection] = useState<ProfileSection>(sections[0])\n\tconst [form, setForm] = useState<ProfileFormState>({ name: '', image: '' })\n\tconst [error, setError] = useState<string | null>(null)\n\tconst [success, setSuccess] = useState<string | null>(null)\n\tconst [isLoading, setIsLoading] = useState(false)\n\tconst fileInputRef = useRef<HTMLInputElement>(null)\n\n\t// Inject global styles\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\t// Populate form with user data\n\tuseEffect(() => {\n\t\tif (user) {\n\t\t\tsetForm({\n\t\t\t\tname: user.name || '',\n\t\t\t\timage: user.image || '',\n\t\t\t})\n\t\t}\n\t}, [user])\n\n\t// Clear messages after timeout\n\tuseEffect(() => {\n\t\tif (success || error) {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tsetSuccess(null)\n\t\t\t\tsetError(null)\n\t\t\t}, UI_NOTIFICATION_MS)\n\t\t\treturn () => clearTimeout(timer)\n\t\t}\n\t}, [success, error])\n\n\t// Handle profile update\n\tconst handleProfileUpdate = useCallback(\n\t\tasync (e: FormEvent) => {\n\t\t\te.preventDefault()\n\t\t\tsetIsLoading(true)\n\t\t\tsetError(null)\n\t\t\tsetSuccess(null)\n\n\t\t\ttry {\n\t\t\t\tawait userContext.updateProfile({\n\t\t\t\t\tname: form.name,\n\t\t\t\t\timage: form.image,\n\t\t\t\t})\n\n\t\t\t\tsetSuccess('Profile updated successfully')\n\t\t\t\tonSuccess?.('Profile updated successfully')\n\t\t\t\trefreshUser()\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : 'Failed to update profile'\n\t\t\t\tsetError(message)\n\t\t\t\tonError?.(message)\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false)\n\t\t\t}\n\t\t},\n\t\t[form, userContext, refreshUser, onSuccess, onError],\n\t)\n\n\t// Handle avatar upload\n\tconst handleAvatarUpload = useCallback(\n\t\tasync (file: File) => {\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tconst result = await uploadFile(file, { folder: 'avatars' })\n\t\t\t\tconst imageUrl = result.url ?? ''\n\t\t\t\tsetForm((prev) => ({ ...prev, image: imageUrl }))\n\t\t\t\tsetSuccess('Avatar uploaded')\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : 'Failed to upload avatar'\n\t\t\t\tsetError(message)\n\t\t\t\tonError?.(message)\n\t\t\t}\n\t\t},\n\t\t[uploadFile, onError],\n\t)\n\n\t// Handle file input change\n\tconst handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n\t\tconst file = e.target.files?.[0]\n\t\tif (file) {\n\t\t\tif (file.size > STORAGE_DEFAULT_MAX_SIZE_BYTES) {\n\t\t\t\tsetError('File size must be less than 5MB')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!file.type.startsWith('image/')) {\n\t\t\t\tsetError('File must be an image')\n\t\t\t\treturn\n\t\t\t}\n\t\t\thandleAvatarUpload(file)\n\t\t}\n\t}\n\n\t// Render avatar\n\tconst renderAvatar = () => {\n\t\tconst avatarStyle: React.CSSProperties = {\n\t\t\twidth: '6rem',\n\t\t\theight: '6rem',\n\t\t\tborderRadius: '50%',\n\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\tdisplay: 'flex',\n\t\t\talignItems: 'center',\n\t\t\tjustifyContent: 'center',\n\t\t\toverflow: 'hidden',\n\t\t\tposition: 'relative',\n\t\t\tcursor: 'pointer',\n\t\t\tborder: `2px solid ${theme.colorBorder}`,\n\t\t}\n\n\t\tconst overlayStyle: React.CSSProperties = {\n\t\t\tposition: 'absolute',\n\t\t\tinset: 0,\n\t\t\tbackgroundColor: 'rgba(0,0,0,0.5)',\n\t\t\tdisplay: 'flex',\n\t\t\talignItems: 'center',\n\t\t\tjustifyContent: 'center',\n\t\t\topacity: 0,\n\t\t\ttransition: 'opacity 0.15s ease-in-out',\n\t\t}\n\n\t\treturn (\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tonClick={() => fileInputRef.current?.click()}\n\t\t\t\taria-label=\"Upload avatar\"\n\t\t\t\tclassName=\"sylphx-upload-hover\"\n\t\t\t\tstyle={{\n\t\t\t\t\t...avatarStyle,\n\t\t\t\t\tborder: 'none',\n\t\t\t\t\tpadding: 0,\n\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\tfont: 'inherit',\n\t\t\t\t\tcolor: 'inherit',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{form.image ? (\n\t\t\t\t\t<img\n\t\t\t\t\t\tsrc={form.image}\n\t\t\t\t\t\talt=\"Avatar\"\n\t\t\t\t\t\tstyle={{ width: '100%', height: '100%', objectFit: 'cover' }}\n\t\t\t\t\t/>\n\t\t\t\t) : (\n\t\t\t\t\t<span style={{ fontSize: '2rem', color: theme.colorMutedForeground }}>\n\t\t\t\t\t\t{form.name?.charAt(0)?.toUpperCase() || '?'}\n\t\t\t\t\t</span>\n\t\t\t\t)}\n\t\t\t\t<div className=\"sylphx-upload-hover__overlay\" style={overlayStyle}>\n\t\t\t\t\t{isUploadingAvatar ? (\n\t\t\t\t\t\t<span style={mergeStyles(styles.spinner, { color: '#fff' })} />\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<CameraIcon color=\"#fff\" />\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<input\n\t\t\t\t\tref={fileInputRef}\n\t\t\t\t\ttype=\"file\"\n\t\t\t\t\taccept=\"image/*\"\n\t\t\t\t\tonChange={handleFileChange}\n\t\t\t\t\tstyle={{ display: 'none' }}\n\t\t\t\t/>\n\t\t\t</button>\n\t\t)\n\t}\n\n\t// Render section tabs\n\tconst renderSectionTabs = () => {\n\t\tif (sections.length <= 1) return null\n\n\t\tconst sectionLabels: Record<ProfileSection, string> = {\n\t\t\tprofile: 'Profile',\n\t\t\tsecurity: 'Security',\n\t\t\tbilling: 'Billing',\n\t\t\tnotifications: 'Notifications',\n\t\t\taccount: 'Account',\n\t\t\treferrals: 'Referrals',\n\t\t\t'connected-accounts': 'Connections',\n\t\t}\n\n\t\treturn (\n\t\t\t<div style={styles.tabs}>\n\t\t\t\t{sections.map((section) => (\n\t\t\t\t\t<button\n\t\t\t\t\t\tkey={section}\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={() => setActiveSection(section)}\n\t\t\t\t\t\tstyle={mergeStyles(styles.tab, activeSection === section ? styles.tabActive : {})}\n\t\t\t\t\t>\n\t\t\t\t\t\t{sectionLabels[section]}\n\t\t\t\t\t</button>\n\t\t\t\t))}\n\t\t\t</div>\n\t\t)\n\t}\n\n\t// Render profile section\n\tconst renderProfileSection = () => (\n\t\t<form onSubmit={handleProfileUpdate}>\n\t\t\t{/* Avatar */}\n\t\t\t<div style={mergeStyles(styles.flexCenter, styles.mb6)}>{renderAvatar()}</div>\n\n\t\t\t{/* Name field */}\n\t\t\t<div style={styles.formGroup}>\n\t\t\t\t<label htmlFor={nameId} style={styles.label}>\n\t\t\t\t\tName\n\t\t\t\t</label>\n\t\t\t\t<input\n\t\t\t\t\tid={nameId}\n\t\t\t\t\ttype=\"text\"\n\t\t\t\t\tvalue={form.name}\n\t\t\t\t\tonChange={(e) => setForm((prev) => ({ ...prev, name: e.target.value }))}\n\t\t\t\t\tplaceholder=\"Your name\"\n\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\tstyle={mergeStyles(styles.input, isLoading ? styles.inputDisabled : {})}\n\t\t\t\t/>\n\t\t\t</div>\n\n\t\t\t{/* Email (read-only) */}\n\t\t\t<div style={styles.formGroup}>\n\t\t\t\t<label htmlFor={emailId} style={styles.label}>\n\t\t\t\t\tEmail\n\t\t\t\t</label>\n\t\t\t\t<input\n\t\t\t\t\tid={emailId}\n\t\t\t\t\ttype=\"email\"\n\t\t\t\t\tvalue={user?.email || ''}\n\t\t\t\t\tdisabled\n\t\t\t\t\treadOnly\n\t\t\t\t\tstyle={mergeStyles(styles.input, styles.inputDisabled)}\n\t\t\t\t/>\n\t\t\t\t<p style={mergeStyles(styles.textXs, styles.textMuted, styles.mt1)}>\n\t\t\t\t\tEmail cannot be changed\n\t\t\t\t</p>\n\t\t\t</div>\n\n\t\t\t{/* Save button */}\n\t\t\t<button\n\t\t\t\ttype=\"submit\"\n\t\t\t\tdisabled={isLoading}\n\t\t\t\tstyle={mergeStyles(\n\t\t\t\t\tstyles.button,\n\t\t\t\t\tstyles.buttonPrimary,\n\t\t\t\t\tstyles.buttonFullWidth,\n\t\t\t\t\tisLoading ? styles.buttonDisabled : {},\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{isLoading ? (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t\tSaving...\n\t\t\t\t\t</>\n\t\t\t\t) : (\n\t\t\t\t\t'Save Changes'\n\t\t\t\t)}\n\t\t\t</button>\n\t\t</form>\n\t)\n\n\t// Render security section using SecuritySettings component\n\tconst renderSecuritySection = () => (\n\t\t<SecuritySettings theme={theme} onSuccess={onSuccess} onError={onError} />\n\t)\n\n\t// Render billing section using BillingSection component\n\tconst renderBillingSection = () => (\n\t\t<BillingSection theme={theme} onSuccess={onSuccess} onError={onError} />\n\t)\n\n\t// Render account section using AccountSection component\n\tconst renderAccountSection = () => (\n\t\t<AccountSection theme={theme} onSuccess={onSuccess} onError={onError} />\n\t)\n\n\t// Render referrals section using ReferralCard component\n\tconst renderReferralsSection = () => (\n\t\t<ReferralCard theme={theme} onSuccess={onSuccess} onError={onError} />\n\t)\n\n\t// Render notifications section using NotificationSettings component\n\tconst renderNotificationsSection = () => (\n\t\t<NotificationSettings theme={theme} onSuccess={onSuccess} onError={onError} />\n\t)\n\n\t// Render connected accounts section\n\tconst renderConnectedAccountsSection = () => (\n\t\t<div>\n\t\t\t<p style={mergeStyles(styles.textMuted, styles.textSm, styles.mb4)}>\n\t\t\t\tManage connected third-party accounts.\n\t\t\t</p>\n\n\t\t\t<div\n\t\t\t\tstyle={mergeStyles(styles.card, {\n\t\t\t\t\tpadding: '1rem',\n\t\t\t\t})}\n\t\t\t>\n\t\t\t\t<p style={mergeStyles(styles.textMuted, styles.textSm, styles.textCenter)}>\n\t\t\t\t\tNo connected accounts\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</div>\n\t)\n\n\t// Render active section content\n\tconst renderSectionContent = () => {\n\t\tswitch (activeSection) {\n\t\t\tcase 'profile':\n\t\t\t\treturn renderProfileSection()\n\t\t\tcase 'security':\n\t\t\t\treturn renderSecuritySection()\n\t\t\tcase 'billing':\n\t\t\t\treturn renderBillingSection()\n\t\t\tcase 'notifications':\n\t\t\t\treturn renderNotificationsSection()\n\t\t\tcase 'account':\n\t\t\t\treturn renderAccountSection()\n\t\t\tcase 'referrals':\n\t\t\t\treturn renderReferralsSection()\n\t\t\tcase 'connected-accounts':\n\t\t\t\treturn renderConnectedAccountsSection()\n\t\t\tdefault:\n\t\t\t\treturn renderProfileSection()\n\t\t}\n\t}\n\n\t// Loading state\n\tif (isUserLoading) {\n\t\treturn (\n\t\t\t<div style={showCard ? styles.card : {}}>\n\t\t\t\t<div\n\t\t\t\t\tstyle={mergeStyles(styles.cardContent, styles.flexCenter, {\n\t\t\t\t\t\tminHeight: '12rem',\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\t<div style={styles.flexCol}>\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.spinner, {\n\t\t\t\t\t\t\t\twidth: '2rem',\n\t\t\t\t\t\t\t\theight: '2rem',\n\t\t\t\t\t\t\t\tmargin: '0 auto 1rem',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<p style={styles.textMuted}>Loading profile...</p>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t)\n\t}\n\n\t// Not authenticated\n\tif (!user) {\n\t\treturn (\n\t\t\t<div style={showCard ? styles.card : {}}>\n\t\t\t\t<div style={mergeStyles(styles.cardContent, styles.textCenter)}>\n\t\t\t\t\t<p style={styles.textMuted}>Please sign in to view your profile.</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t)\n\t}\n\n\t// Main content\n\tconst content = (\n\t\t<div style={styles.container}>\n\t\t\t{/* Header */}\n\t\t\t{header || (\n\t\t\t\t<div\n\t\t\t\t\tstyle={mergeStyles(styles.cardHeader, isModal ? styles.flexBetween : styles.textCenter)}\n\t\t\t\t>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<h2 style={styles.cardTitle}>Your Profile</h2>\n\t\t\t\t\t\t<p style={styles.cardDescription}>Manage your account settings</p>\n\t\t\t\t\t</div>\n\t\t\t\t\t{isModal && onClose && (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={onClose}\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonGhost)}\n\t\t\t\t\t\t\taria-label=\"Close\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<CloseIcon color={theme.colorMutedForeground} />\n\t\t\t\t\t\t</button>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Content */}\n\t\t\t<div style={styles.cardContent}>\n\t\t\t\t{/* Alerts */}\n\t\t\t\t{success && (\n\t\t\t\t\t<div style={mergeStyles(styles.alert, styles.alertSuccess, styles.mb4)}>{success}</div>\n\t\t\t\t)}\n\t\t\t\t{error && (\n\t\t\t\t\t<div style={mergeStyles(styles.alert, styles.alertError, styles.mb4)}>{error}</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Section tabs */}\n\t\t\t\t{renderSectionTabs()}\n\n\t\t\t\t{/* Section content */}\n\t\t\t\t{renderSectionContent()}\n\n\t\t\t\t{/* Footer */}\n\t\t\t\t{footer}\n\t\t\t</div>\n\t\t</div>\n\t)\n\n\tif (showCard) {\n\t\treturn <div style={styles.card}>{content}</div>\n\t}\n\n\treturn content\n}\n\n// Icons\nfunction CameraIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"24\"\n\t\t\theight=\"24\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z\" />\n\t\t\t<circle cx=\"12\" cy=\"13\" r=\"3\" />\n\t\t</svg>\n\t)\n}\n\nfunction CloseIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 16 16\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M4 4L12 12M12 4L4 12\" />\n\t\t</svg>\n\t)\n}\n","/**\n * Webhook Manager Components\n *\n * Create, manage, and test webhooks.\n */\n\n'use client'\n\nimport { type CSSProperties, type FormEvent, useEffect, useId, useState } from 'react'\nimport type { ThemeVariables } from './styles'\nimport { baseStyles, defaultTheme, injectGlobalStyles, mergeStyles } from './styles'\n\n// ============================================\n// Types\n// ============================================\n\nexport interface Webhook {\n\tid: string\n\turl: string\n\tevents: string[]\n\tsecret?: string\n\tenabled: boolean\n\tcreatedAt: string\n\tlastTriggeredAt?: string\n\tfailureCount?: number\n}\n\nexport interface WebhookDelivery {\n\tid: string\n\twebhookId: string\n\tevent: string\n\tstatus: 'success' | 'failed' | 'pending'\n\tstatusCode?: number\n\ttimestamp: string\n\tpayload?: Record<string, unknown>\n\tresponse?: string\n\tduration?: number\n}\n\n// ============================================\n// WebhookManager\n// ============================================\n\nexport interface WebhookManagerProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Custom class name */\n\tclassName?: string\n\t/** Webhooks to display */\n\twebhooks?: Webhook[]\n\t/** Available events */\n\tavailableEvents?: string[]\n\t/** Called when webhook is created */\n\tonCreate?: (data: { url: string; events: string[] }) => Promise<Webhook>\n\t/** Called when webhook is deleted */\n\tonDelete?: (webhookId: string) => Promise<void>\n\t/** Called when webhook is toggled */\n\tonToggle?: (webhookId: string, enabled: boolean) => Promise<void>\n\t/** Called when webhook is tested */\n\tonTest?: (webhookId: string) => Promise<void>\n\t/** Whether loading */\n\tisLoading?: boolean\n\t/** Empty state message */\n\temptyMessage?: string\n}\n\nconst DEFAULT_EVENTS = [\n\t'user.created',\n\t'user.updated',\n\t'user.deleted',\n\t'subscription.created',\n\t'subscription.updated',\n\t'subscription.cancelled',\n\t'payment.succeeded',\n\t'payment.failed',\n\t'invoice.created',\n\t'invoice.paid',\n]\n\n/**\n * Webhook management UI\n *\n * @example\n * ```tsx\n * <WebhookManager\n *   webhooks={webhooks}\n *   onCreate={async (data) => createWebhook(data)}\n *   onDelete={async (id) => deleteWebhook(id)}\n *   onTest={async (id) => testWebhook(id)}\n * />\n * ```\n */\nexport function WebhookManager({\n\ttheme = defaultTheme,\n\tclassName,\n\twebhooks = [],\n\tavailableEvents = DEFAULT_EVENTS,\n\tonCreate,\n\tonDelete,\n\tonToggle,\n\tonTest,\n\tisLoading = false,\n\temptyMessage = 'No webhooks configured',\n}: WebhookManagerProps) {\n\tconst urlId = useId()\n\tconst [showCreate, setShowCreate] = useState(false)\n\tconst [url, setUrl] = useState('')\n\tconst [selectedEvents, setSelectedEvents] = useState<string[]>([])\n\tconst [isCreating, setIsCreating] = useState(false)\n\tconst [error, setError] = useState<string | null>(null)\n\tconst [testingId, setTestingId] = useState<string | null>(null)\n\tconst [deletingId, setDeletingId] = useState<string | null>(null)\n\n\tconst styles = baseStyles(theme)\n\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tconst handleCreate = async (e: FormEvent) => {\n\t\te.preventDefault()\n\t\tif (!onCreate || !url || selectedEvents.length === 0) return\n\n\t\tsetIsCreating(true)\n\t\tsetError(null)\n\n\t\ttry {\n\t\t\tawait onCreate({ url, events: selectedEvents })\n\t\t\tsetShowCreate(false)\n\t\t\tsetUrl('')\n\t\t\tsetSelectedEvents([])\n\t\t} catch (err) {\n\t\t\tsetError(err instanceof Error ? err.message : 'Failed to create webhook')\n\t\t} finally {\n\t\t\tsetIsCreating(false)\n\t\t}\n\t}\n\n\tconst handleDelete = async (webhookId: string) => {\n\t\tif (!onDelete) return\n\t\tsetDeletingId(webhookId)\n\t\ttry {\n\t\t\tawait onDelete(webhookId)\n\t\t} finally {\n\t\t\tsetDeletingId(null)\n\t\t}\n\t}\n\n\tconst handleTest = async (webhookId: string) => {\n\t\tif (!onTest) return\n\t\tsetTestingId(webhookId)\n\t\ttry {\n\t\t\tawait onTest(webhookId)\n\t\t} finally {\n\t\t\tsetTestingId(null)\n\t\t}\n\t}\n\n\tconst toggleEvent = (event: string) => {\n\t\tsetSelectedEvents((prev) =>\n\t\t\tprev.includes(event) ? prev.filter((e) => e !== event) : [...prev, event],\n\t\t)\n\t}\n\n\tconst containerStyle: CSSProperties = {\n\t\tfontFamily: theme.fontFamily,\n\t}\n\n\tconst webhookCardStyle: CSSProperties = {\n\t\tpadding: '1rem',\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t\tmarginBottom: '0.75rem',\n\t}\n\n\tconst inputStyle: CSSProperties = {\n\t\twidth: '100%',\n\t\tpadding: '0.75rem',\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t\tbackgroundColor: theme.colorBackground,\n\t\tcolor: theme.colorForeground,\n\t\tfontSize: theme.fontSizeSm,\n\t\tfontFamily: theme.fontFamily,\n\t}\n\n\treturn (\n\t\t<div style={containerStyle} className={className}>\n\t\t\t{/* Header */}\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\talignItems: 'center',\n\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\tmarginBottom: '1.5rem',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div>\n\t\t\t\t\t<h3 style={{ margin: 0, fontSize: theme.fontSizeLg, fontWeight: 600 }}>Webhooks</h3>\n\t\t\t\t\t<p\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tmargin: '0.25rem 0 0',\n\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tReceive HTTP callbacks when events occur\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={() => setShowCreate(true)}\n\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary)}\n\t\t\t\t>\n\t\t\t\t\t<PlusIcon color={theme.colorPrimaryForeground} /> Add Webhook\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t{/* Create Form */}\n\t\t\t{showCreate && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\t...webhookCardStyle,\n\t\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\t\tmarginBottom: '1.5rem',\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<h4\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tmargin: '0 0 1rem',\n\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tNew Webhook\n\t\t\t\t\t</h4>\n\n\t\t\t\t\t{error && (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={mergeStyles(styles.alert, styles.alertError, {\n\t\t\t\t\t\t\t\tmarginBottom: '1rem',\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{error}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\n\t\t\t\t\t<form onSubmit={handleCreate}>\n\t\t\t\t\t\t<div style={{ marginBottom: '1rem' }}>\n\t\t\t\t\t\t\t<label\n\t\t\t\t\t\t\t\thtmlFor={urlId}\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tEndpoint URL *\n\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\tid={urlId}\n\t\t\t\t\t\t\t\ttype=\"url\"\n\t\t\t\t\t\t\t\tvalue={url}\n\t\t\t\t\t\t\t\tonChange={(e) => setUrl(e.target.value)}\n\t\t\t\t\t\t\t\tstyle={inputStyle}\n\t\t\t\t\t\t\t\tplaceholder=\"https://api.example.com/webhooks\"\n\t\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<fieldset style={{ marginBottom: '1.5rem', border: 'none', padding: 0, margin: 0 }}>\n\t\t\t\t\t\t\t<legend\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tEvents to listen for *\n\t\t\t\t\t\t\t</legend>\n\t\t\t\t\t\t\t<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.5rem' }}>\n\t\t\t\t\t\t\t\t{availableEvents.map((event) => (\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\tkey={event}\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => toggleEvent(event)}\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tpadding: '0.375rem 0.75rem',\n\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\tborder: `1px solid ${selectedEvents.includes(event) ? theme.colorPrimary : theme.colorBorder}`,\n\t\t\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: selectedEvents.includes(event)\n\t\t\t\t\t\t\t\t\t\t\t\t? `${theme.colorPrimary}10`\n\t\t\t\t\t\t\t\t\t\t\t\t: 'transparent',\n\t\t\t\t\t\t\t\t\t\t\tcolor: selectedEvents.includes(event)\n\t\t\t\t\t\t\t\t\t\t\t\t? theme.colorPrimary\n\t\t\t\t\t\t\t\t\t\t\t\t: theme.colorForeground,\n\t\t\t\t\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{event}\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</fieldset>\n\n\t\t\t\t\t\t<div style={{ display: 'flex', gap: '0.75rem' }}>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\tsetShowCreate(false)\n\t\t\t\t\t\t\t\t\tsetUrl('')\n\t\t\t\t\t\t\t\t\tsetSelectedEvents([])\n\t\t\t\t\t\t\t\t\tsetError(null)\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\tdisabled={isCreating || !url || selectedEvents.length === 0}\n\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonPrimary)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{isCreating ? <span style={styles.spinner} /> : 'Create Webhook'}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</form>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Webhook List */}\n\t\t\t{isLoading ? (\n\t\t\t\t<div style={{ padding: '2rem', textAlign: 'center' }}>\n\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t</div>\n\t\t\t) : webhooks.length === 0 ? (\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tpadding: '3rem',\n\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\tborderRadius: theme.borderRadius,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<WebhookIcon color={theme.colorMuted} size={48} />\n\t\t\t\t\t<p style={{ margin: '1rem 0 0' }}>{emptyMessage}</p>\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\twebhooks.map((webhook) => (\n\t\t\t\t\t<div key={webhook.id} style={webhookCardStyle}>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\talignItems: 'flex-start',\n\t\t\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div style={{ flex: 1, minWidth: 0 }}>\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\tgap: '0.5rem',\n\t\t\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\twidth: 8,\n\t\t\t\t\t\t\t\t\t\t\theight: 8,\n\t\t\t\t\t\t\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: webhook.enabled\n\t\t\t\t\t\t\t\t\t\t\t\t? theme.colorSuccess\n\t\t\t\t\t\t\t\t\t\t\t\t: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tfontFamily: 'monospace',\n\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeSm,\n\t\t\t\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\t\t\t\t\t\t\ttextOverflow: 'ellipsis',\n\t\t\t\t\t\t\t\t\t\t\twhiteSpace: 'nowrap',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{webhook.url}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\tflexWrap: 'wrap',\n\t\t\t\t\t\t\t\t\t\tgap: '0.25rem',\n\t\t\t\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{webhook.events.map((event) => (\n\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\tkey={event}\n\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\tpadding: '0.125rem 0.375rem',\n\t\t\t\t\t\t\t\t\t\t\t\tfontSize: '0.625rem',\n\t\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{event}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tCreated {new Date(webhook.createdAt).toLocaleDateString()}\n\t\t\t\t\t\t\t\t\t{webhook.lastTriggeredAt &&\n\t\t\t\t\t\t\t\t\t\t` • Last triggered ${new Date(webhook.lastTriggeredAt).toLocaleString()}`}\n\t\t\t\t\t\t\t\t\t{webhook.failureCount !== undefined && webhook.failureCount > 0 && (\n\t\t\t\t\t\t\t\t\t\t<span style={{ color: theme.colorDestructive }}>\n\t\t\t\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t\t\t\t• {webhook.failureCount} failures\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div style={{ display: 'flex', gap: '0.5rem', marginLeft: '1rem' }}>\n\t\t\t\t\t\t\t\t{onToggle && (\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => onToggle(webhook.id, !webhook.enabled)}\n\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline, {\n\t\t\t\t\t\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{webhook.enabled ? 'Disable' : 'Enable'}\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{onTest && (\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => handleTest(webhook.id)}\n\t\t\t\t\t\t\t\t\t\tdisabled={testingId === webhook.id}\n\t\t\t\t\t\t\t\t\t\tstyle={mergeStyles(styles.button, styles.buttonOutline, {\n\t\t\t\t\t\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{testingId === webhook.id ? <span style={styles.spinner} /> : 'Test'}\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{onDelete && (\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => handleDelete(webhook.id)}\n\t\t\t\t\t\t\t\t\t\tdisabled={deletingId === webhook.id}\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tpadding: '0.25rem 0.5rem',\n\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\tborder: `1px solid ${theme.colorDestructive}`,\n\t\t\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorDestructive,\n\t\t\t\t\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{deletingId === webhook.id ? <span style={styles.spinner} /> : 'Delete'}\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t))\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n// ============================================\n// WebhookDeliveryLog\n// ============================================\n\nexport interface WebhookDeliveryLogProps {\n\t/** Theme variables */\n\ttheme?: ThemeVariables\n\t/** Custom class name */\n\tclassName?: string\n\t/** Deliveries to display */\n\tdeliveries?: WebhookDelivery[]\n\t/** Whether loading */\n\tisLoading?: boolean\n\t/** Title */\n\ttitle?: string\n\t/** Empty state message */\n\temptyMessage?: string\n\t/** Max deliveries to show */\n\tmaxDeliveries?: number\n}\n\n/**\n * Webhook delivery history log\n *\n * @example\n * ```tsx\n * <WebhookDeliveryLog\n *   deliveries={deliveries}\n *   title=\"Recent Deliveries\"\n * />\n * ```\n */\nexport function WebhookDeliveryLog({\n\ttheme = defaultTheme,\n\tclassName,\n\tdeliveries = [],\n\tisLoading = false,\n\ttitle = 'Delivery Log',\n\temptyMessage = 'No deliveries yet',\n\tmaxDeliveries = 50,\n}: WebhookDeliveryLogProps) {\n\tconst [expandedId, setExpandedId] = useState<string | null>(null)\n\tconst styles = baseStyles(theme)\n\n\tuseEffect(() => {\n\t\tinjectGlobalStyles()\n\t}, [])\n\n\tconst displayedDeliveries = deliveries.slice(0, maxDeliveries)\n\n\tconst statusColors: Record<WebhookDelivery['status'], { bg: string; text: string }> = {\n\t\tsuccess: { bg: `${theme.colorSuccess}20`, text: theme.colorSuccess },\n\t\tfailed: { bg: `${theme.colorDestructive}20`, text: theme.colorDestructive },\n\t\tpending: { bg: `${theme.colorWarning}20`, text: theme.colorWarning },\n\t}\n\n\tconst containerStyle: CSSProperties = {\n\t\tfontFamily: theme.fontFamily,\n\t\tborder: `1px solid ${theme.colorBorder}`,\n\t\tborderRadius: theme.borderRadius,\n\t\toverflow: 'hidden',\n\t}\n\n\treturn (\n\t\t<div style={containerStyle} className={className}>\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\tpadding: '1rem',\n\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\tborderBottom: `1px solid ${theme.colorBorder}`,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<h3 style={{ margin: 0, fontSize: theme.fontSizeLg, fontWeight: 600 }}>{title}</h3>\n\t\t\t</div>\n\n\t\t\t<div style={{ maxHeight: '400px', overflowY: 'auto' }}>\n\t\t\t\t{isLoading ? (\n\t\t\t\t\t<div style={{ padding: '2rem', textAlign: 'center' }}>\n\t\t\t\t\t\t<span style={styles.spinner} />\n\t\t\t\t\t</div>\n\t\t\t\t) : displayedDeliveries.length === 0 ? (\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tpadding: '3rem',\n\t\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{emptyMessage}\n\t\t\t\t\t</div>\n\t\t\t\t) : (\n\t\t\t\t\tdisplayedDeliveries.map((delivery, i) => (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tkey={delivery.id}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\taria-expanded={expandedId === delivery.id}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tpadding: '0.75rem 1rem',\n\t\t\t\t\t\t\t\tborderBottom:\n\t\t\t\t\t\t\t\t\ti === displayedDeliveries.length - 1 ? 'none' : `1px solid ${theme.colorBorder}`,\n\t\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t\t\ttextAlign: 'left',\n\t\t\t\t\t\t\t\tfont: 'inherit',\n\t\t\t\t\t\t\t\tcolor: 'inherit',\n\t\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\t\tbackground: 'transparent',\n\t\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\t\tborderBottomStyle: 'solid',\n\t\t\t\t\t\t\t\tborderBottomWidth: i === displayedDeliveries.length - 1 ? 0 : 1,\n\t\t\t\t\t\t\t\tborderBottomColor: theme.colorBorder,\n\t\t\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tonClick={() => setExpandedId(expandedId === delivery.id ? null : delivery.id)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\t\t\t\tgap: '0.75rem',\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tpadding: '0.125rem 0.375rem',\n\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: statusColors[delivery.status].bg,\n\t\t\t\t\t\t\t\t\t\t\tcolor: statusColors[delivery.status].text,\n\t\t\t\t\t\t\t\t\t\t\ttextTransform: 'capitalize',\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{delivery.status}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t<span style={{ fontWeight: 500, fontSize: theme.fontSizeSm }}>\n\t\t\t\t\t\t\t\t\t\t{delivery.event}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t{delivery.statusCode && (\n\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\tHTTP {delivery.statusCode}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\tcolor: theme.colorMutedForeground,\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{new Date(delivery.timestamp).toLocaleString()}\n\t\t\t\t\t\t\t\t\t{delivery.duration && ` • ${delivery.duration}ms`}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t{expandedId === delivery.id && (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tmarginTop: '0.75rem',\n\t\t\t\t\t\t\t\t\t\tpadding: '0.75rem',\n\t\t\t\t\t\t\t\t\t\tbackgroundColor: theme.colorMuted,\n\t\t\t\t\t\t\t\t\t\tborderRadius: theme.borderRadiusSm,\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{delivery.payload && (\n\t\t\t\t\t\t\t\t\t\t<div style={{ marginBottom: '0.75rem' }}>\n\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\t\t\t\t\t\tmarginBottom: '0.25rem',\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\tPayload\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t<pre\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: '0.625rem',\n\t\t\t\t\t\t\t\t\t\t\t\t\tfontFamily: 'monospace',\n\t\t\t\t\t\t\t\t\t\t\t\t\twhiteSpace: 'pre-wrap',\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{JSON.stringify(delivery.payload, null, 2)}\n\t\t\t\t\t\t\t\t\t\t\t</pre>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t{delivery.response && (\n\t\t\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: theme.fontSizeXs,\n\t\t\t\t\t\t\t\t\t\t\t\t\tfontWeight: 500,\n\t\t\t\t\t\t\t\t\t\t\t\t\tmarginBottom: '0.25rem',\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\tResponse\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t<pre\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: '0.625rem',\n\t\t\t\t\t\t\t\t\t\t\t\t\tfontFamily: 'monospace',\n\t\t\t\t\t\t\t\t\t\t\t\t\twhiteSpace: 'pre-wrap',\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{delivery.response}\n\t\t\t\t\t\t\t\t\t\t\t</pre>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t))\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n// ============================================\n// Icons\n// ============================================\n\nfunction WebhookIcon({ color, size = 24 }: { color: string; size?: number }) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<path d=\"M18 16.98h-5.99c-1.1 0-1.95.94-2.48 1.9A4 4 0 0 1 2 17c.01-.7.2-1.4.57-2\" />\n\t\t\t<path d=\"m6 17 3.13-5.78c.53-.97.1-2.18-.5-3.1a4 4 0 1 1 6.89-4.06\" />\n\t\t\t<path d=\"m12 6 3.13 5.73C15.66 12.7 16.9 13 18 13a4 4 0 0 1 0 8\" />\n\t\t</svg>\n\t)\n}\n\nfunction PlusIcon({ color }: { color: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tstyle={{ marginRight: '0.25rem' }}\n\t\t\taria-hidden=\"true\"\n\t\t\tfocusable=\"false\"\n\t\t>\n\t\t\t<line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n\t\t\t<line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n\t\t</svg>\n\t)\n}\n","/**\n * Automatic Breadcrumb Collection\n *\n * Captures user actions leading to errors:\n * - UI interactions (clicks, inputs)\n * - Network requests (fetch, XHR)\n * - Console logs\n * - Navigation changes\n */\n\nimport { LOG_MESSAGE_MAX_LENGTH } from '../../../constants'\nimport { onFetchEnd, onXHREnd, type UnsubscribeFn } from '../network-interceptor'\nimport { sanitizeForLogging, sanitizeUrl } from '../session-replay/privacy'\nimport type { Breadcrumb, ErrorLevel } from './types'\n\n// ==========================================\n// Breadcrumb Store\n// ==========================================\n\nlet breadcrumbs: Breadcrumb[] = []\nlet maxBreadcrumbs = 100\n\n/**\n * Configure max breadcrumbs\n */\nexport function setMaxBreadcrumbs(max: number): void {\n\tmaxBreadcrumbs = max\n\ttrimBreadcrumbs()\n}\n\n/**\n * Add a breadcrumb\n */\nexport function addBreadcrumb(breadcrumb: Breadcrumb): void {\n\tbreadcrumbs.push({\n\t\t...breadcrumb,\n\t\ttimestamp: breadcrumb.timestamp ?? Date.now(),\n\t})\n\ttrimBreadcrumbs()\n}\n\n/**\n * Get all breadcrumbs\n */\nexport function getBreadcrumbs(): Breadcrumb[] {\n\treturn [...breadcrumbs]\n}\n\n/**\n * Clear all breadcrumbs\n */\nexport function clearBreadcrumbs(): void {\n\tbreadcrumbs = []\n}\n\n/**\n * Trim breadcrumbs to max size\n */\nfunction trimBreadcrumbs(): void {\n\tif (breadcrumbs.length > maxBreadcrumbs) {\n\t\tbreadcrumbs = breadcrumbs.slice(-maxBreadcrumbs)\n\t}\n}\n\n// ==========================================\n// Click Capture\n// ==========================================\n\nlet clickCaptureEnabled = false\n\n/**\n * Enable click capture\n */\nfunction enableClickCapture(): void {\n\tif (clickCaptureEnabled || typeof document === 'undefined') return\n\tclickCaptureEnabled = true\n\n\tdocument.addEventListener(\n\t\t'click',\n\t\t(event) => {\n\t\t\tconst target = event.target as Element\n\t\t\tif (!target) return\n\n\t\t\tconst breadcrumb: Breadcrumb = {\n\t\t\t\ttype: 'ui',\n\t\t\t\tcategory: 'ui.click',\n\t\t\t\tmessage: getElementDescription(target),\n\t\t\t\tdata: {\n\t\t\t\t\tselector: getElementSelector(target),\n\t\t\t\t},\n\t\t\t\tlevel: 'info',\n\t\t\t}\n\n\t\t\taddBreadcrumb(breadcrumb)\n\t\t},\n\t\t{ capture: true, passive: true },\n\t)\n}\n\n/**\n * Get human-readable description of clicked element\n */\nfunction getElementDescription(element: Element): string {\n\tconst tag = element.tagName.toLowerCase()\n\tconst text = element.textContent?.trim().slice(0, 50) || ''\n\tconst id = element.id ? `#${element.id}` : ''\n\tconst role = element.getAttribute('role')\n\tconst ariaLabel = element.getAttribute('aria-label')\n\n\tif (ariaLabel) {\n\t\treturn `${tag}[${ariaLabel}]`\n\t}\n\tif (role) {\n\t\treturn `${tag}[role=${role}]`\n\t}\n\tif (id) {\n\t\treturn `${tag}${id}`\n\t}\n\tif (text) {\n\t\treturn `${tag}[${text}]`\n\t}\n\treturn tag\n}\n\n/**\n * Get CSS selector for element\n */\nfunction getElementSelector(element: Element): string {\n\tif (element.id) {\n\t\treturn `#${CSS.escape(element.id)}`\n\t}\n\n\tconst tag = element.tagName.toLowerCase()\n\tconst classes = Array.from(element.classList)\n\t\t.slice(0, 2)\n\t\t.map((c) => `.${CSS.escape(c)}`)\n\t\t.join('')\n\n\treturn classes ? `${tag}${classes}` : tag\n}\n\n// ==========================================\n// Input Capture\n// ==========================================\n\nlet inputCaptureEnabled = false\n\n/**\n * Enable input capture (captures input events without values)\n */\nfunction enableInputCapture(): void {\n\tif (inputCaptureEnabled || typeof document === 'undefined') return\n\tinputCaptureEnabled = true\n\n\tdocument.addEventListener(\n\t\t'input',\n\t\t(event) => {\n\t\t\tconst target = event.target as HTMLInputElement | HTMLTextAreaElement\n\t\t\tif (!target) return\n\n\t\t\t// Don't capture the actual value for privacy\n\t\t\tconst breadcrumb: Breadcrumb = {\n\t\t\t\ttype: 'ui',\n\t\t\t\tcategory: 'ui.input',\n\t\t\t\tmessage: `Input: ${getElementDescription(target)}`,\n\t\t\t\tdata: {\n\t\t\t\t\tselector: getElementSelector(target),\n\t\t\t\t\ttype: target.type || 'text',\n\t\t\t\t},\n\t\t\t\tlevel: 'info',\n\t\t\t}\n\n\t\t\taddBreadcrumb(breadcrumb)\n\t\t},\n\t\t{ capture: true, passive: true },\n\t)\n}\n\n// ==========================================\n// Network Capture\n// ==========================================\n\nlet networkCaptureEnabled = false\nlet networkUnsubscribers: UnsubscribeFn[] = []\n\n/**\n * Enable network request capture via shared interceptor.\n *\n * Uses the centralized network interceptor instead of independently\n * monkey-patching fetch/XHR. This prevents the fragile chain problem\n * where multiple modules each wrap the previous patch.\n */\nfunction enableNetworkCapture(): void {\n\tif (networkCaptureEnabled || typeof window === 'undefined') return\n\tnetworkCaptureEnabled = true\n\n\tnetworkUnsubscribers.push(\n\t\tonFetchEnd((event) => {\n\t\t\tconst failed = event.status === 0 && event.error\n\t\t\taddBreadcrumb({\n\t\t\t\ttype: 'http',\n\t\t\t\tcategory: 'fetch',\n\t\t\t\tmessage: `${event.method} ${sanitizeUrl(event.url)}${failed ? ' (failed)' : ''}`,\n\t\t\t\tdata: {\n\t\t\t\t\tmethod: event.method,\n\t\t\t\t\turl: sanitizeUrl(event.url),\n\t\t\t\t\tstatus_code: event.status,\n\t\t\t\t\tduration_ms: event.duration,\n\t\t\t\t\t...(event.error ? { error: event.error } : {}),\n\t\t\t\t},\n\t\t\t\tlevel: event.ok ? 'info' : 'error',\n\t\t\t})\n\t\t}),\n\t)\n\n\tnetworkUnsubscribers.push(\n\t\tonXHREnd((event) => {\n\t\t\taddBreadcrumb({\n\t\t\t\ttype: 'http',\n\t\t\t\tcategory: 'xhr',\n\t\t\t\tmessage: `${event.method} ${sanitizeUrl(event.url)}`,\n\t\t\t\tdata: {\n\t\t\t\t\tmethod: event.method,\n\t\t\t\t\turl: sanitizeUrl(event.url),\n\t\t\t\t\tstatus_code: event.status,\n\t\t\t\t\tduration_ms: event.duration,\n\t\t\t\t},\n\t\t\t\tlevel: event.status >= 400 ? 'error' : 'info',\n\t\t\t})\n\t\t}),\n\t)\n}\n\n/**\n * Unregister network capture listeners (for testing)\n */\nfunction _disableNetworkCapture(): void {\n\tif (!networkCaptureEnabled) return\n\tnetworkCaptureEnabled = false\n\n\tfor (const unsub of networkUnsubscribers) {\n\t\tunsub()\n\t}\n\tnetworkUnsubscribers = []\n}\n\n// ==========================================\n// Console Capture\n// ==========================================\n\nlet consoleCaptureEnabled = false\nconst originalConsole: Partial<\n\tRecord<'log' | 'info' | 'warn' | 'error' | 'debug', (...args: unknown[]) => void>\n> = {}\n\n/**\n * Enable console log capture\n */\nfunction enableConsoleCapture(): void {\n\tif (consoleCaptureEnabled || typeof console === 'undefined') return\n\tconsoleCaptureEnabled = true\n\n\tconst levels: Array<'log' | 'info' | 'warn' | 'error' | 'debug'> = [\n\t\t'log',\n\t\t'info',\n\t\t'warn',\n\t\t'error',\n\t\t'debug',\n\t]\n\n\tconst levelMap: Record<string, ErrorLevel> = {\n\t\tlog: 'info',\n\t\tinfo: 'info',\n\t\twarn: 'warning',\n\t\terror: 'error',\n\t\tdebug: 'debug',\n\t}\n\n\tlevels.forEach((level) => {\n\t\t// biome-ignore lint/suspicious/noConsole: breadcrumb recorder patches console.* to capture user calls; the original is preserved + re-invoked so the patch is transparent.\n\t\toriginalConsole[level] = console[level]\n\n\t\tconsole[level] = (...args: unknown[]) => {\n\t\t\tconst message = args.map((arg) => String(arg)).join(' ')\n\n\t\t\taddBreadcrumb({\n\t\t\t\ttype: 'debug',\n\t\t\t\tcategory: `console.${level}`,\n\t\t\t\tmessage: sanitizeForLogging(message).slice(0, LOG_MESSAGE_MAX_LENGTH),\n\t\t\t\tlevel: levelMap[level],\n\t\t\t})\n\n\t\t\toriginalConsole[level]?.apply(console, args)\n\t\t}\n\t})\n}\n\n/**\n * Restore original console (for testing)\n */\nfunction _disableConsoleCapture(): void {\n\tif (!consoleCaptureEnabled) return\n\tconsoleCaptureEnabled = false\n\n\tconst levels: Array<'log' | 'info' | 'warn' | 'error' | 'debug'> = [\n\t\t'log',\n\t\t'info',\n\t\t'warn',\n\t\t'error',\n\t\t'debug',\n\t]\n\n\tlevels.forEach((level) => {\n\t\tif (originalConsole[level]) {\n\t\t\tconsole[level] = originalConsole[level]!\n\t\t}\n\t})\n}\n\n// ==========================================\n// Navigation Capture\n// ==========================================\n\nlet navigationCaptureEnabled = false\nlet lastUrl: string | null = null\n\n/**\n * Enable navigation capture\n */\nfunction enableNavigationCapture(): void {\n\tif (navigationCaptureEnabled || typeof window === 'undefined') return\n\tnavigationCaptureEnabled = true\n\n\tlastUrl = window.location.href\n\n\t// History API\n\tconst originalPushState = history.pushState\n\tconst originalReplaceState = history.replaceState\n\n\thistory.pushState = function (...args) {\n\t\tconst result = originalPushState.apply(this, args)\n\t\thandleNavigationChange()\n\t\treturn result\n\t}\n\n\thistory.replaceState = function (...args) {\n\t\tconst result = originalReplaceState.apply(this, args)\n\t\thandleNavigationChange()\n\t\treturn result\n\t}\n\n\t// Popstate (back/forward)\n\twindow.addEventListener('popstate', handleNavigationChange)\n}\n\nfunction handleNavigationChange(): void {\n\tconst newUrl = window.location.href\n\n\tif (newUrl !== lastUrl) {\n\t\taddBreadcrumb({\n\t\t\ttype: 'navigation',\n\t\t\tcategory: 'navigation',\n\t\t\tmessage: `Navigated`,\n\t\t\tdata: {\n\t\t\t\tfrom: lastUrl ? sanitizeUrl(lastUrl) : undefined,\n\t\t\t\tto: sanitizeUrl(newUrl),\n\t\t\t},\n\t\t\tlevel: 'info',\n\t\t})\n\n\t\tlastUrl = newUrl\n\t}\n}\n\n// ==========================================\n// All-in-One Setup\n// ==========================================\n\nexport interface AutoCaptureOptions {\n\tclicks?: boolean\n\tinputs?: boolean\n\tnetwork?: boolean\n\tconsole?: boolean\n\tnavigation?: boolean\n}\n\n/**\n * Enable all automatic breadcrumb capture\n */\nexport function enableAutoCapture(options: AutoCaptureOptions = {}): void {\n\tconst {\n\t\tclicks = true,\n\t\tinputs = true,\n\t\tnetwork = true,\n\t\tconsole = true,\n\t\tnavigation = true,\n\t} = options\n\n\tif (clicks) enableClickCapture()\n\tif (inputs) enableInputCapture()\n\tif (network) enableNetworkCapture()\n\tif (console) enableConsoleCapture()\n\tif (navigation) enableNavigationCapture()\n}\n","/**\n * Shared Network Interceptor\n *\n * Single point of monkey-patching for fetch and XMLHttpRequest.\n * All monitoring modules (breadcrumbs, session replay, dead click detection)\n * register listeners here instead of independently patching globals.\n *\n * This eliminates the fragile chain where each module wraps the previous\n * module's patched version, and restoring one breaks the others.\n *\n * Architecture:\n *   breadcrumbs.ts ──┐\n *   recorder.ts   ───┤──► NetworkInterceptor (patches once) ──► window.fetch / XHR\n *   detectors.ts  ───┘\n */\n\n// ==========================================\n// Types\n// ==========================================\n\nexport interface FetchStartEvent {\n\turl: string\n\tmethod: string\n\tstartTime: number\n}\n\nexport interface FetchEndEvent {\n\turl: string\n\tmethod: string\n\tstartTime: number\n\tduration: number\n\tstatus: number\n\tok: boolean\n\terror?: string\n}\n\nexport interface XHRStartEvent {\n\turl: string\n\tmethod: string\n\tstartTime: number\n}\n\nexport interface XHREndEvent {\n\turl: string\n\tmethod: string\n\tstartTime: number\n\tduration: number\n\tstatus: number\n}\n\nexport type FetchStartListener = (event: FetchStartEvent) => void\nexport type FetchEndListener = (event: FetchEndEvent) => void\nexport type XHRStartListener = (event: XHRStartEvent) => void\nexport type XHREndListener = (event: XHREndEvent) => void\n\ninterface ListenerSet {\n\tfetchStart: Set<FetchStartListener>\n\tfetchEnd: Set<FetchEndListener>\n\txhrStart: Set<XHRStartListener>\n\txhrEnd: Set<XHREndListener>\n}\n\n// ==========================================\n// Singleton State\n// ==========================================\n\nlet installed = false\nlet originalFetch: typeof window.fetch | undefined\nlet originalXHROpen: typeof XMLHttpRequest.prototype.open | undefined\nlet originalXHRSend: typeof XMLHttpRequest.prototype.send | undefined\n\nconst listeners: ListenerSet = {\n\tfetchStart: new Set(),\n\tfetchEnd: new Set(),\n\txhrStart: new Set(),\n\txhrEnd: new Set(),\n}\n\n// ==========================================\n// Installation\n// ==========================================\n\n/**\n * Install the global network interceptor.\n *\n * Safe to call multiple times -- patches are applied exactly once.\n * Patching happens on first listener registration, not eagerly.\n */\nfunction ensureInstalled(): void {\n\tif (installed) return\n\tif (typeof window === 'undefined') return\n\n\tinstalled = true\n\n\t// Capture the true originals before any patching\n\toriginalFetch = window.fetch.bind(window) as typeof window.fetch\n\n\tif (typeof XMLHttpRequest !== 'undefined') {\n\t\toriginalXHROpen = XMLHttpRequest.prototype.open\n\t\toriginalXHRSend = XMLHttpRequest.prototype.send\n\t}\n\n\tpatchFetch()\n\tpatchXHR()\n}\n\n/**\n * Extract URL string from any fetch input type.\n * Handles string, Request, and URL objects.\n */\nfunction extractUrl(input: RequestInfo | URL): string {\n\tif (typeof input === 'string') return input\n\tif (input instanceof URL) return input.href\n\treturn (input as Request).url\n}\n\n/**\n * Notify all listeners in a set, guarding against:\n * - Listeners throwing (one failure must not break others)\n * - Set mutation during iteration (snapshot before iterating)\n */\nfunction notify<T>(set: Set<(event: T) => void>, event: T): void {\n\tconst snapshot = Array.from(set)\n\tfor (const listener of snapshot) {\n\t\ttry {\n\t\t\tlistener(event)\n\t\t} catch {\n\t\t\t// Listener errors must not break the interceptor or other listeners\n\t\t}\n\t}\n}\n\nfunction patchFetch(): void {\n\tif (!originalFetch) return\n\n\t// window.fetch is read-only in TypeScript; cast through unknown to reassign the callable\n\tconst patchedFetch = async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n\t\tconst startTime = Date.now()\n\t\tconst url = extractUrl(input)\n\t\tconst method = init?.method || (input instanceof Request ? input.method : 'GET')\n\n\t\tnotify(listeners.fetchStart, {\n\t\t\turl,\n\t\t\tmethod,\n\t\t\tstartTime,\n\t\t} satisfies FetchStartEvent)\n\n\t\ttry {\n\t\t\tconst response = await originalFetch!(input, init)\n\t\t\tconst duration = Date.now() - startTime\n\n\t\t\tnotify(listeners.fetchEnd, {\n\t\t\t\turl,\n\t\t\t\tmethod,\n\t\t\t\tstartTime,\n\t\t\t\tduration,\n\t\t\t\tstatus: response.status,\n\t\t\t\tok: response.ok,\n\t\t\t} satisfies FetchEndEvent)\n\n\t\t\treturn response\n\t\t} catch (error) {\n\t\t\tconst duration = Date.now() - startTime\n\n\t\t\tnotify(listeners.fetchEnd, {\n\t\t\t\turl,\n\t\t\t\tmethod,\n\t\t\t\tstartTime,\n\t\t\t\tduration,\n\t\t\t\tstatus: 0,\n\t\t\t\tok: false,\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t} satisfies FetchEndEvent)\n\n\t\t\tthrow error\n\t\t}\n\t}\n\t// Assign via Object.defineProperty to bypass TypeScript's read-only fetch type\n\tObject.defineProperty(window, 'fetch', {\n\t\tvalue: patchedFetch,\n\t\twritable: true,\n\t\tconfigurable: true,\n\t})\n}\n\nfunction patchXHR(): void {\n\tif (!originalXHROpen || !originalXHRSend) return\n\n\tXMLHttpRequest.prototype.open = function (\n\t\tmethod: string,\n\t\turl: string | URL,\n\t\tasync?: boolean,\n\t\tusername?: string | null,\n\t\tpassword?: string | null,\n\t) {\n\t\tconst xhr = this as XMLHttpRequest & { _niMethod: string; _niUrl: string }\n\t\txhr._niMethod = method\n\t\txhr._niUrl = typeof url === 'string' ? url : url.href\n\t\treturn originalXHROpen!.call(this, method, url, async ?? true, username, password)\n\t}\n\n\tXMLHttpRequest.prototype.send = function (body?: XMLHttpRequestBodyInit | null) {\n\t\tconst xhr = this as XMLHttpRequest & {\n\t\t\t_niMethod: string\n\t\t\t_niUrl: string\n\t\t\t_niStart: number\n\t\t}\n\t\txhr._niStart = Date.now()\n\n\t\tnotify(listeners.xhrStart, {\n\t\t\turl: xhr._niUrl,\n\t\t\tmethod: xhr._niMethod,\n\t\t\tstartTime: xhr._niStart,\n\t\t} satisfies XHRStartEvent)\n\n\t\tthis.addEventListener('loadend', () => {\n\t\t\tconst duration = Date.now() - xhr._niStart\n\n\t\t\tnotify(listeners.xhrEnd, {\n\t\t\t\turl: xhr._niUrl,\n\t\t\t\tmethod: xhr._niMethod,\n\t\t\t\tstartTime: xhr._niStart,\n\t\t\t\tduration,\n\t\t\t\tstatus: this.status,\n\t\t\t} satisfies XHREndEvent)\n\t\t})\n\n\t\treturn originalXHRSend!.call(this, body)\n\t}\n}\n\n// ==========================================\n// Public API\n// ==========================================\n\nexport type UnsubscribeFn = () => void\n\n/**\n * Register a listener for fetch request completion.\n *\n * Automatically installs the interceptor on first call.\n * Returns an unsubscribe function.\n */\nexport function onFetchEnd(listener: FetchEndListener): UnsubscribeFn {\n\tensureInstalled()\n\tlisteners.fetchEnd.add(listener)\n\treturn () => {\n\t\tlisteners.fetchEnd.delete(listener)\n\t}\n}\n\n/**\n * Register a listener for fetch request start.\n *\n * Automatically installs the interceptor on first call.\n * Returns an unsubscribe function.\n */\nexport function onFetchStart(listener: FetchStartListener): UnsubscribeFn {\n\tensureInstalled()\n\tlisteners.fetchStart.add(listener)\n\treturn () => {\n\t\tlisteners.fetchStart.delete(listener)\n\t}\n}\n\n/**\n * Register a listener for XHR request start.\n *\n * Automatically installs the interceptor on first call.\n * Returns an unsubscribe function.\n */\nexport function onXHRStart(listener: XHRStartListener): UnsubscribeFn {\n\tensureInstalled()\n\tlisteners.xhrStart.add(listener)\n\treturn () => {\n\t\tlisteners.xhrStart.delete(listener)\n\t}\n}\n\n/**\n * Register a listener for XHR request completion.\n *\n * Automatically installs the interceptor on first call.\n * Returns an unsubscribe function.\n */\nexport function onXHREnd(listener: XHREndListener): UnsubscribeFn {\n\tensureInstalled()\n\tlisteners.xhrEnd.add(listener)\n\treturn () => {\n\t\tlisteners.xhrEnd.delete(listener)\n\t}\n}\n\n/**\n * Remove all listeners and restore original globals.\n *\n * Intended for testing teardown. After calling this,\n * new listener registrations will re-install the patches.\n */\nexport function resetNetworkInterceptor(): void {\n\tlisteners.fetchStart.clear()\n\tlisteners.fetchEnd.clear()\n\tlisteners.xhrStart.clear()\n\tlisteners.xhrEnd.clear()\n\n\tif (!installed) return\n\tinstalled = false\n\n\tif (originalFetch && typeof window !== 'undefined') {\n\t\twindow.fetch = originalFetch\n\t}\n\tif (originalXHROpen && typeof XMLHttpRequest !== 'undefined') {\n\t\tXMLHttpRequest.prototype.open = originalXHROpen\n\t}\n\tif (originalXHRSend && typeof XMLHttpRequest !== 'undefined') {\n\t\tXMLHttpRequest.prototype.send = originalXHRSend\n\t}\n\n\toriginalFetch = undefined\n\toriginalXHROpen = undefined\n\toriginalXHRSend = undefined\n}\n","/**\n * Session Replay Privacy Controls\n *\n * SOTA privacy features:\n * - Automatic PII detection\n * - Sensitive field pattern matching\n * - GDPR/CCPA compliant masking\n * - Smart content categorization\n */\n\nimport type { PrivacyMode } from './types'\n\n// ==========================================\n// Sensitive Field Patterns\n// ==========================================\n\n/**\n * Patterns that indicate sensitive data in field names/labels\n */\nconst SENSITIVE_PATTERNS = {\n\tpassword: [/password/i, /passwd/i, /pwd/i, /secret/i],\n\tfinancial: [\n\t\t/credit.?card/i,\n\t\t/card.?number/i,\n\t\t/cvv/i,\n\t\t/cvc/i,\n\t\t/expir/i,\n\t\t/bank.?account/i,\n\t\t/routing.?number/i,\n\t\t/iban/i,\n\t\t/swift/i,\n\t\t/account.?number/i,\n\t],\n\tidentity: [\n\t\t/ssn/i,\n\t\t/social.?security/i,\n\t\t/tax.?id/i,\n\t\t/passport/i,\n\t\t/driver.?license/i,\n\t\t/national.?id/i,\n\t\t/id.?number/i,\n\t],\n\tpersonal: [/birth.?date/i, /dob/i, /date.?of.?birth/i, /mother.?maiden/i, /maiden.?name/i],\n\thealth: [/health/i, /medical/i, /diagnosis/i, /prescription/i, /insurance.?id/i, /patient.?id/i],\n\tauthentication: [/api.?key/i, /token/i, /auth/i, /bearer/i, /access.?key/i, /private.?key/i],\n} as const\n\n/**\n * Input types that should always be masked\n */\nconst SENSITIVE_INPUT_TYPES = new Set(['password', 'tel', 'email'])\n\n/**\n * Autocomplete values that indicate sensitive data\n */\nconst SENSITIVE_AUTOCOMPLETE = new Set([\n\t'cc-name',\n\t'cc-number',\n\t'cc-exp',\n\t'cc-exp-month',\n\t'cc-exp-year',\n\t'cc-csc',\n\t'cc-type',\n\t'new-password',\n\t'current-password',\n\t'one-time-code',\n\t'tel',\n\t'tel-country-code',\n\t'tel-national',\n\t'email',\n])\n\n// ==========================================\n// Detection Functions\n// ==========================================\n\n/**\n * Check if text contains sensitive patterns\n */\nfunction _containsSensitivePattern(text: string): boolean {\n\tconst allPatterns = Object.values(SENSITIVE_PATTERNS).flat()\n\treturn allPatterns.some((pattern) => pattern.test(text))\n}\n\n/**\n * Get sensitivity category for an element\n */\nfunction getSensitivityCategory(element: Element): string | null {\n\tconst text = [\n\t\telement.getAttribute('name'),\n\t\telement.getAttribute('id'),\n\t\telement.getAttribute('aria-label'),\n\t\telement.getAttribute('placeholder'),\n\t\t(element as HTMLInputElement).type,\n\t]\n\t\t.filter(Boolean)\n\t\t.join(' ')\n\n\tfor (const [category, patterns] of Object.entries(SENSITIVE_PATTERNS)) {\n\t\tif (patterns.some((pattern) => pattern.test(text))) {\n\t\t\treturn category\n\t\t}\n\t}\n\n\treturn null\n}\n\n/**\n * Check if element should be masked based on its attributes\n */\nfunction shouldMaskElement(element: Element): boolean {\n\t// Check input type\n\tif (element instanceof HTMLInputElement) {\n\t\tif (SENSITIVE_INPUT_TYPES.has(element.type)) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\t// Check autocomplete attribute\n\tconst autocomplete = element.getAttribute('autocomplete')\n\tif (autocomplete && SENSITIVE_AUTOCOMPLETE.has(autocomplete)) {\n\t\treturn true\n\t}\n\n\t// Check data attribute for explicit masking\n\tif (element.hasAttribute('data-mask') || element.hasAttribute('data-private')) {\n\t\treturn true\n\t}\n\n\t// Check name/id/label for sensitive patterns\n\treturn getSensitivityCategory(element) !== null\n}\n\n// ==========================================\n// Public API\n// ==========================================\n\n/**\n * Detect all sensitive fields in the document\n * Returns CSS selectors for masking\n */\nexport function detectSensitiveFields(): string[] {\n\tconst selectors: string[] = []\n\tconst inputs = document.querySelectorAll('input, textarea, select')\n\n\tinputs.forEach((element) => {\n\t\tif (shouldMaskElement(element)) {\n\t\t\t// Build most specific selector possible\n\t\t\tif (element.id) {\n\t\t\t\tselectors.push(`#${CSS.escape(element.id)}`)\n\t\t\t} else if (element.getAttribute('name')) {\n\t\t\t\tconst name = element.getAttribute('name')!\n\t\t\t\tselectors.push(`[name=\"${CSS.escape(name)}\"]`)\n\t\t\t} else {\n\t\t\t\t// Fallback to nth-child selector\n\t\t\t\tconst parent = element.parentElement\n\t\t\t\tif (parent) {\n\t\t\t\t\tconst index = Array.from(parent.children).indexOf(element) + 1\n\t\t\t\t\tconst tagName = element.tagName.toLowerCase()\n\t\t\t\t\tselectors.push(`${tagName}:nth-child(${index})`)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n\n\treturn [...new Set(selectors)] // Dedupe\n}\n\n/**\n * Get rrweb masking options based on privacy mode\n */\nexport function getPrivacyOptions(mode: PrivacyMode, customMaskSelectors: string[] = []) {\n\tconst autoDetectedSelectors = detectSensitiveFields()\n\tconst allMaskSelectors = [...autoDetectedSelectors, ...customMaskSelectors]\n\n\tswitch (mode) {\n\t\tcase 'strict':\n\t\t\treturn {\n\t\t\t\tmaskAllInputs: true,\n\t\t\t\tmaskTextSelector: '*', // Mask all text\n\t\t\t\tmaskInputOptions: {\n\t\t\t\t\tpassword: true,\n\t\t\t\t\ttext: true,\n\t\t\t\t\temail: true,\n\t\t\t\t\ttel: true,\n\t\t\t\t\turl: true,\n\t\t\t\t\tnumber: true,\n\t\t\t\t\tsearch: true,\n\t\t\t\t\ttextarea: true,\n\t\t\t\t\tselect: true,\n\t\t\t\t},\n\t\t\t\tslimDOMOptions: {\n\t\t\t\t\tscript: true,\n\t\t\t\t\tcomment: true,\n\t\t\t\t\theadFavicon: true,\n\t\t\t\t\theadWhitespace: true,\n\t\t\t\t\theadMetaDescKeywords: true,\n\t\t\t\t\theadMetaSocial: true,\n\t\t\t\t\theadMetaRobots: true,\n\t\t\t\t\theadMetaHttpEquiv: true,\n\t\t\t\t\theadMetaAuthorship: true,\n\t\t\t\t\theadMetaVerification: true,\n\t\t\t\t},\n\t\t\t}\n\n\t\tcase 'balanced':\n\t\t\treturn {\n\t\t\t\tmaskAllInputs: false,\n\t\t\t\tmaskTextSelector: allMaskSelectors.join(', ') || undefined,\n\t\t\t\tmaskInputOptions: {\n\t\t\t\t\tpassword: true,\n\t\t\t\t\temail: true,\n\t\t\t\t\ttel: true,\n\t\t\t\t},\n\t\t\t\tslimDOMOptions: {\n\t\t\t\t\tscript: true,\n\t\t\t\t\tcomment: true,\n\t\t\t\t\theadFavicon: true,\n\t\t\t\t\theadWhitespace: true,\n\t\t\t\t},\n\t\t\t}\n\n\t\tcase 'minimal':\n\t\t\treturn {\n\t\t\t\tmaskAllInputs: false,\n\t\t\t\tmaskTextSelector: customMaskSelectors.join(', ') || undefined,\n\t\t\t\tmaskInputOptions: {\n\t\t\t\t\tpassword: true,\n\t\t\t\t},\n\t\t\t\tslimDOMOptions: {\n\t\t\t\t\tscript: true,\n\t\t\t\t\tcomment: true,\n\t\t\t\t},\n\t\t\t}\n\t}\n}\n\n/**\n * Sanitize a string for logging (redact PII)\n */\nexport function sanitizeForLogging(text: string): string {\n\t// Email pattern\n\ttext = text.replace(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/g, '[EMAIL_REDACTED]')\n\n\t// Phone pattern (various formats)\n\ttext = text.replace(\n\t\t/(\\+?1?[-.\\s]?)?\\(?[0-9]{3}\\)?[-.\\s]?[0-9]{3}[-.\\s]?[0-9]{4}/g,\n\t\t'[PHONE_REDACTED]',\n\t)\n\n\t// Credit card pattern\n\ttext = text.replace(/\\b(?:\\d{4}[-\\s]?){3}\\d{4}\\b/g, '[CARD_REDACTED]')\n\n\t// SSN pattern\n\ttext = text.replace(/\\b\\d{3}[-\\s]?\\d{2}[-\\s]?\\d{4}\\b/g, '[SSN_REDACTED]')\n\n\t// IP address pattern\n\ttext = text.replace(/\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b/g, '[IP_REDACTED]')\n\n\treturn text\n}\n\n/**\n * Check if URL contains sensitive query parameters\n */\nexport function sanitizeUrl(url: string): string {\n\ttry {\n\t\tconst parsed = new URL(url)\n\t\tconst sensitiveParams = ['token', 'key', 'password', 'secret', 'auth', 'api_key', 'apikey']\n\n\t\tsensitiveParams.forEach((param) => {\n\t\t\tif (parsed.searchParams.has(param)) {\n\t\t\t\tparsed.searchParams.set(param, '[REDACTED]')\n\t\t\t}\n\t\t})\n\n\t\treturn parsed.toString()\n\t} catch {\n\t\treturn url\n\t}\n}\n\n/**\n * Generate a privacy report for the current page\n */\nexport function generatePrivacyReport(): {\n\tsensitiveFields: Array<{ selector: string; category: string }>\n\ttotalInputs: number\n\tmaskedInputs: number\n\trecommendations: string[]\n} {\n\tconst inputs = document.querySelectorAll('input, textarea, select')\n\tconst sensitiveFields: Array<{ selector: string; category: string }> = []\n\tconst recommendations: string[] = []\n\n\tinputs.forEach((element) => {\n\t\tconst category = getSensitivityCategory(element)\n\t\tif (category) {\n\t\t\tconst selector = element.id\n\t\t\t\t? `#${element.id}`\n\t\t\t\t: element.getAttribute('name') || element.tagName\n\n\t\t\tsensitiveFields.push({ selector, category })\n\t\t}\n\n\t\t// Check for common privacy issues\n\t\tif (element instanceof HTMLInputElement) {\n\t\t\tif (element.type === 'password' && !element.autocomplete) {\n\t\t\t\trecommendations.push(\n\t\t\t\t\t`Add autocomplete=\"current-password\" or \"new-password\" to password field: ${element.name || element.id}`,\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t})\n\n\treturn {\n\t\tsensitiveFields,\n\t\ttotalInputs: inputs.length,\n\t\tmaskedInputs: sensitiveFields.length,\n\t\trecommendations,\n\t}\n}\n","/**\n * PII Scrubber\n *\n * Automatic detection and redaction of Personally Identifiable Information (PII)\n * before sending error reports to the server.\n *\n * Follows Sentry's data scrubbing patterns with additional coverage.\n *\n * ## Detected PII Types\n * - Email addresses\n * - Credit card numbers (Visa, MasterCard, Amex, etc.)\n * - Social Security Numbers (SSN)\n * - Phone numbers (international formats)\n * - IP addresses (IPv4 and IPv6)\n * - API keys and tokens\n * - Passwords in URLs or data\n * - AWS credentials\n * - JWT tokens\n */\n\n// ==========================================\n// PII Detection Patterns\n// ==========================================\n\n/**\n * Regex patterns for detecting PII\n * Each pattern is designed for high precision to avoid false positives\n */\nconst PII_PATTERNS: { name: string; pattern: RegExp; replacement: string }[] = [\n\t// Email addresses\n\t{\n\t\tname: 'email',\n\t\tpattern: /\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b/gi,\n\t\treplacement: '[EMAIL]',\n\t},\n\n\t// Credit card numbers (with or without spaces/dashes)\n\t// Covers: Visa, MasterCard, Amex, Discover, Diners, JCB\n\t{\n\t\tname: 'credit_card',\n\t\tpattern: /\\b(?:\\d{4}[-\\s]?){3}\\d{4}\\b|\\b\\d{15,16}\\b/g,\n\t\treplacement: '[CREDIT_CARD]',\n\t},\n\n\t// US Social Security Numbers\n\t{\n\t\tname: 'ssn',\n\t\tpattern: /\\b\\d{3}[-\\s]?\\d{2}[-\\s]?\\d{4}\\b/g,\n\t\treplacement: '[SSN]',\n\t},\n\n\t// Phone numbers (international formats)\n\t{\n\t\tname: 'phone',\n\t\tpattern: /\\b(?:\\+?1[-.\\s]?)?(?:\\(?[0-9]{3}\\)?[-.\\s]?)?[0-9]{3}[-.\\s]?[0-9]{4}\\b/g,\n\t\treplacement: '[PHONE]',\n\t},\n\n\t// IPv4 addresses\n\t{\n\t\tname: 'ipv4',\n\t\tpattern: /\\b(?:(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\b/g,\n\t\treplacement: '[IP_ADDRESS]',\n\t},\n\n\t// IPv6 addresses (simplified)\n\t{\n\t\tname: 'ipv6',\n\t\tpattern: /\\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\\b/g,\n\t\treplacement: '[IP_ADDRESS]',\n\t},\n\n\t// API keys and tokens (generic patterns)\n\t{\n\t\tname: 'api_key',\n\t\tpattern:\n\t\t\t/\\b(?:api[_-]?key|apikey|api_secret|secret_key)[\"\\s:=]+[\"']?([a-zA-Z0-9_-]{20,})[\"']?/gi,\n\t\treplacement: '[API_KEY]',\n\t},\n\n\t// Bearer tokens\n\t{\n\t\tname: 'bearer_token',\n\t\tpattern: /\\b(?:Bearer\\s+)([a-zA-Z0-9._-]{20,})\\b/gi,\n\t\treplacement: 'Bearer [TOKEN]',\n\t},\n\n\t// JWT tokens (three base64 segments separated by dots)\n\t{\n\t\tname: 'jwt',\n\t\tpattern: /\\beyJ[a-zA-Z0-9_-]*\\.eyJ[a-zA-Z0-9_-]*\\.[a-zA-Z0-9_-]+\\b/g,\n\t\treplacement: '[JWT_TOKEN]',\n\t},\n\n\t// Password in URLs\n\t{\n\t\tname: 'password_url',\n\t\tpattern: /:\\/\\/([^:]+):([^@]+)@/g,\n\t\treplacement: '://[USER]:[PASSWORD]@',\n\t},\n\n\t// Password in query strings or form data\n\t{\n\t\tname: 'password_param',\n\t\tpattern: /(?:password|passwd|pwd|secret)[\"\\s:=]+[\"']?([^\"'\\s&]+)[\"']?/gi,\n\t\treplacement: '[PASSWORD_FIELD]',\n\t},\n\n\t// AWS Access Key IDs\n\t{\n\t\tname: 'aws_key',\n\t\tpattern: /\\b(AKIA[0-9A-Z]{16})\\b/g,\n\t\treplacement: '[AWS_ACCESS_KEY]',\n\t},\n\n\t// AWS Secret Access Keys (40 character base64)\n\t{\n\t\tname: 'aws_secret',\n\t\tpattern: /\\b([a-zA-Z0-9/+=]{40})\\b/g,\n\t\t// Only replace if near AWS context - use beforeSend for complex cases\n\t\treplacement: '[AWS_SECRET_KEY]',\n\t},\n\n\t// Stripe API keys\n\t{\n\t\tname: 'stripe_key',\n\t\tpattern: /\\b(sk_(?:live|test)_[a-zA-Z0-9]{24,})\\b/g,\n\t\treplacement: '[STRIPE_KEY]',\n\t},\n\n\t// Generic auth tokens (32+ hex chars)\n\t{\n\t\tname: 'auth_token',\n\t\tpattern: /\\b(?:token|auth)[\"\\s:=]+[\"']?([a-fA-F0-9]{32,})[\"']?/gi,\n\t\treplacement: '[AUTH_TOKEN]',\n\t},\n]\n\n// ==========================================\n// Sensitive Field Names (for object scrubbing)\n// ==========================================\n\nconst SENSITIVE_FIELD_NAMES = new Set([\n\t'password',\n\t'passwd',\n\t'pwd',\n\t'secret',\n\t'token',\n\t'api_key',\n\t'apikey',\n\t'api-key',\n\t'auth',\n\t'authorization',\n\t'credentials',\n\t'credit_card',\n\t'creditcard',\n\t'card_number',\n\t'cardnumber',\n\t'cvv',\n\t'cvc',\n\t'ssn',\n\t'social_security',\n\t'private_key',\n\t'privatekey',\n\t'access_token',\n\t'refresh_token',\n\t'session_id',\n\t'sessionid',\n\t'cookie',\n])\n\n// ==========================================\n// Scrubbing Functions\n// ==========================================\n\n/**\n * Scrub PII from a string\n *\n * @param text - Text to scrub\n * @returns Scrubbed text with PII redacted\n */\nexport function scrubString(text: string): string {\n\tif (!text || typeof text !== 'string') return text\n\n\tlet scrubbed = text\n\n\tfor (const { pattern, replacement } of PII_PATTERNS) {\n\t\tscrubbed = scrubbed.replace(pattern, replacement)\n\t}\n\n\treturn scrubbed\n}\n\n/**\n * Check if a field name is sensitive\n */\nfunction isSensitiveField(fieldName: string): boolean {\n\tconst normalized = fieldName.toLowerCase().replace(/[-_]/g, '')\n\treturn SENSITIVE_FIELD_NAMES.has(normalized) || SENSITIVE_FIELD_NAMES.has(fieldName.toLowerCase())\n}\n\n/**\n * Recursively scrub PII from an object\n *\n * @param obj - Object to scrub\n * @param depth - Current recursion depth (prevents infinite recursion)\n * @returns Scrubbed object\n */\nexport function scrubObject<T>(obj: T, depth = 0): T {\n\t// Prevent infinite recursion\n\tif (depth > 10) return obj\n\n\tif (obj === null || obj === undefined) return obj\n\n\t// Handle strings\n\tif (typeof obj === 'string') {\n\t\treturn scrubString(obj) as T\n\t}\n\n\t// Handle arrays\n\tif (Array.isArray(obj)) {\n\t\treturn obj.map((item) => scrubObject(item, depth + 1)) as T\n\t}\n\n\t// Handle objects\n\tif (typeof obj === 'object') {\n\t\tconst scrubbed: Record<string, unknown> = {}\n\n\t\tfor (const [key, value] of Object.entries(obj)) {\n\t\t\t// If field name is sensitive, redact entirely\n\t\t\tif (isSensitiveField(key)) {\n\t\t\t\tscrubbed[key] = '[REDACTED]'\n\t\t\t} else if (typeof value === 'string') {\n\t\t\t\tscrubbed[key] = scrubString(value)\n\t\t\t} else if (typeof value === 'object' && value !== null) {\n\t\t\t\tscrubbed[key] = scrubObject(value, depth + 1)\n\t\t\t} else {\n\t\t\t\tscrubbed[key] = value\n\t\t\t}\n\t\t}\n\n\t\treturn scrubbed as T\n\t}\n\n\treturn obj\n}\n\n/**\n * Error event structure for scrubbing (subset of full ErrorEvent)\n */\ninterface ScrubableErrorEvent {\n\texception?: { values?: Array<{ value?: string; type?: string }> }\n\tmessage?: { formatted?: string; message?: string }\n\textra?: Record<string, unknown>\n\ttags?: Record<string, string>\n\tbreadcrumbs?: { values?: Array<{ message?: string; data?: unknown }> }\n\trequest?: {\n\t\turl?: string\n\t\tquery_string?: string\n\t\theaders?: Record<string, string>\n\t}\n\tuser?: { email?: string; username?: string }\n}\n\n/**\n * Scrub PII from error event before sending\n *\n * This is the main entry point for scrubbing error events.\n * Call this in the beforeSend hook or before upload.\n */\nexport function scrubErrorEvent<T extends ScrubableErrorEvent>(event: T): T {\n\t// Deep clone to avoid mutating original\n\tconst cloned = JSON.parse(JSON.stringify(event)) as T\n\n\t// Scrub exception values\n\tif (cloned.exception?.values) {\n\t\tfor (const value of cloned.exception.values) {\n\t\t\tif (value.value) {\n\t\t\t\tvalue.value = scrubString(value.value)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Scrub message\n\tif (cloned.message) {\n\t\tif (cloned.message.formatted) cloned.message.formatted = scrubString(cloned.message.formatted)\n\t\tif (cloned.message.message) cloned.message.message = scrubString(cloned.message.message)\n\t}\n\n\t// Scrub extra data\n\tif (cloned.extra) {\n\t\tcloned.extra = scrubObject(cloned.extra)\n\t}\n\n\t// Scrub tags\n\tif (cloned.tags) {\n\t\tcloned.tags = scrubObject(cloned.tags) as Record<string, string>\n\t}\n\n\t// Scrub breadcrumbs\n\tif (cloned.breadcrumbs?.values) {\n\t\tfor (const crumb of cloned.breadcrumbs.values) {\n\t\t\tif (crumb.message) crumb.message = scrubString(crumb.message)\n\t\t\tif (crumb.data) crumb.data = scrubObject(crumb.data)\n\t\t}\n\t}\n\n\t// Scrub request URL (may contain tokens or auth)\n\tif (cloned.request) {\n\t\tif (cloned.request.url) cloned.request.url = scrubString(cloned.request.url)\n\t\tif (cloned.request.query_string)\n\t\t\tcloned.request.query_string = scrubString(cloned.request.query_string)\n\t\tif (cloned.request.headers) {\n\t\t\t// Remove sensitive headers entirely\n\t\t\tconst sensitiveHeaders = ['authorization', 'cookie', 'x-api-key', 'x-auth-token']\n\t\t\tfor (const header of sensitiveHeaders) {\n\t\t\t\tif (cloned.request.headers[header]) {\n\t\t\t\t\tcloned.request.headers[header] = '[REDACTED]'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Scrub user data (keep ID but redact email if needed)\n\tif (cloned.user) {\n\t\t// Note: We keep user.id as it's needed for issue grouping\n\t\t// But email should already be [EMAIL] from pattern matching\n\t\tif (cloned.user.email) cloned.user.email = scrubString(cloned.user.email)\n\t\tif (cloned.user.username) cloned.user.username = scrubString(cloned.user.username)\n\t}\n\n\treturn cloned\n}\n\n// ==========================================\n// Configuration\n// ==========================================\n\nexport interface PIIScrubberConfig {\n\t/** Enable/disable scrubbing (default: true) */\n\tenabled?: boolean\n\t/** Additional patterns to match */\n\tadditionalPatterns?: Array<{ pattern: RegExp; replacement: string }>\n\t/** Additional sensitive field names */\n\tadditionalSensitiveFields?: string[]\n\t/** Fields to never scrub (allowlist) */\n\tallowedFields?: string[]\n}\n\n/**\n * Create a configured scrubber\n */\nexport function createScrubber(config: PIIScrubberConfig = {}) {\n\tconst { enabled = true, additionalPatterns = [], additionalSensitiveFields = [] } = config\n\n\t// Add additional sensitive fields\n\tfor (const field of additionalSensitiveFields) {\n\t\tSENSITIVE_FIELD_NAMES.add(field.toLowerCase())\n\t}\n\n\t// Merge additional patterns\n\tconst allPatterns = [...PII_PATTERNS, ...additionalPatterns]\n\n\treturn {\n\t\tscrubString: (text: string) => {\n\t\t\tif (!enabled) return text\n\t\t\tlet scrubbed = text\n\t\t\tfor (const { pattern, replacement } of allPatterns) {\n\t\t\t\tscrubbed = scrubbed.replace(pattern, replacement)\n\t\t\t}\n\t\t\treturn scrubbed\n\t\t},\n\t\tscrubObject: <T>(obj: T) => (enabled ? scrubObject(obj) : obj),\n\t\tscrubErrorEvent: <T extends Record<string, unknown>>(event: T) =>\n\t\t\tenabled ? scrubErrorEvent(event) : event,\n\t}\n}\n","/**\n * Error Tracking Types\n *\n * Sentry-compatible types for error tracking.\n */\n\n// ==========================================\n// Core Types\n// ==========================================\n\n/**\n * Error severity levels (Sentry-compatible)\n */\nexport type ErrorLevel = 'fatal' | 'error' | 'warning' | 'info' | 'debug'\n\n/**\n * Breadcrumb types (Sentry-compatible)\n */\nexport type BreadcrumbType =\n\t| 'default'\n\t| 'navigation'\n\t| 'http'\n\t| 'ui'\n\t| 'user'\n\t| 'error'\n\t| 'info'\n\t| 'debug'\n\n/**\n * Breadcrumb for tracking user actions leading to an error\n */\nexport interface Breadcrumb {\n\ttype?: BreadcrumbType\n\tcategory?: string\n\tmessage?: string\n\tdata?: Record<string, unknown>\n\tlevel?: ErrorLevel\n\ttimestamp?: number\n}\n\n/**\n * Stack frame (Sentry-compatible)\n */\nexport interface StackFrame {\n\tfilename?: string\n\tfunction?: string\n\tmodule?: string\n\tlineno?: number\n\tcolno?: number\n\tabs_path?: string\n\tcontext_line?: string\n\tpre_context?: string[]\n\tpost_context?: string[]\n\tin_app?: boolean\n\tvars?: Record<string, unknown>\n}\n\n/**\n * Parsed exception (Sentry-compatible)\n */\nexport interface ExceptionValue {\n\ttype: string\n\tvalue: string\n\tmodule?: string\n\tthread_id?: number\n\tstacktrace?: {\n\t\tframes: StackFrame[]\n\t}\n\tmechanism?: {\n\t\ttype: string\n\t\thandled: boolean\n\t\tdata?: Record<string, unknown>\n\t}\n}\n\n// ==========================================\n// Event Types\n// ==========================================\n\n/**\n * Error event to send to server (Sentry-compatible)\n */\nexport interface ErrorEvent {\n\tevent_id: string\n\ttimestamp: number\n\tplatform: string\n\tlevel: ErrorLevel\n\tlogger?: string\n\ttransaction?: string\n\tserver_name?: string\n\trelease?: string\n\tdist?: string\n\tenvironment?: string\n\tmessage?: {\n\t\tformatted?: string\n\t\tmessage?: string\n\t\tparams?: unknown[]\n\t}\n\texception?: {\n\t\tvalues: ExceptionValue[]\n\t}\n\tthreads?: {\n\t\tvalues: Array<{\n\t\t\tid: number\n\t\t\tname?: string\n\t\t\tcrashed?: boolean\n\t\t\tcurrent?: boolean\n\t\t\tstacktrace?: { frames: StackFrame[] }\n\t\t}>\n\t}\n\ttags?: Record<string, string>\n\textra?: Record<string, unknown>\n\tcontexts?: {\n\t\tdevice?: {\n\t\t\tname?: string\n\t\t\tfamily?: string\n\t\t\tmodel?: string\n\t\t\tmodel_id?: string\n\t\t\tarch?: string\n\t\t\tbattery_level?: number\n\t\t\torientation?: string\n\t\t\tmanufacturer?: string\n\t\t\tbrand?: string\n\t\t\tscreen_resolution?: string\n\t\t\tscreen_density?: number\n\t\t\tscreen_dpi?: number\n\t\t\tonline?: boolean\n\t\t\tcharging?: boolean\n\t\t\tlow_memory?: boolean\n\t\t\tsimulator?: boolean\n\t\t\tmemory_size?: number\n\t\t\tfree_memory?: number\n\t\t\tusable_memory?: number\n\t\t\tstorage_size?: number\n\t\t\tfree_storage?: number\n\t\t\texternal_storage_size?: number\n\t\t\texternal_free_storage?: number\n\t\t}\n\t\tos?: {\n\t\t\tname?: string\n\t\t\tversion?: string\n\t\t\tbuild?: string\n\t\t\tkernel_version?: string\n\t\t\trooted?: boolean\n\t\t}\n\t\tbrowser?: {\n\t\t\tname?: string\n\t\t\tversion?: string\n\t\t}\n\t\truntime?: {\n\t\t\tname?: string\n\t\t\tversion?: string\n\t\t}\n\t\tapp?: {\n\t\t\tapp_name?: string\n\t\t\tapp_version?: string\n\t\t\tapp_identifier?: string\n\t\t\tapp_build?: string\n\t\t\tapp_start_time?: string\n\t\t\tdevice_app_hash?: string\n\t\t}\n\t\ttrace?: {\n\t\t\ttrace_id?: string\n\t\t\tspan_id?: string\n\t\t\tparent_span_id?: string\n\t\t\top?: string\n\t\t\tstatus?: string\n\t\t}\n\t\t// Session Replay integration\n\t\treplay?: {\n\t\t\tsession_id?: string\n\t\t\terror_timestamp?: number\n\t\t}\n\t}\n\tuser?: {\n\t\tid?: string\n\t\temail?: string\n\t\tusername?: string\n\t\tip_address?: string\n\t\tgeo?: {\n\t\t\tcountry_code?: string\n\t\t\tcity?: string\n\t\t\tregion?: string\n\t\t}\n\t}\n\trequest?: {\n\t\turl?: string\n\t\tmethod?: string\n\t\tquery_string?: string\n\t\theaders?: Record<string, string>\n\t\tdata?: unknown\n\t\tcookies?: string\n\t\tenv?: Record<string, string>\n\t}\n\tbreadcrumbs?: {\n\t\tvalues: Breadcrumb[]\n\t}\n\tfingerprint?: string[]\n\tsdk?: {\n\t\tname: string\n\t\tversion: string\n\t\tpackages?: Array<{ name: string; version: string }>\n\t\tintegrations?: string[]\n\t}\n}\n\n// ==========================================\n// Configuration\n// ==========================================\n\n/**\n * Source map configuration for server-side processing\n * Follows Sentry's source map artifact pattern\n */\nexport interface SourceMapConfig {\n\t/**\n\t * URL prefix for matching stack trace URLs to source maps\n\t * @example '~/' for relative paths, 'https://example.com/static/' for absolute\n\t */\n\turlPrefix?: string\n\t/**\n\t * Include source map references in error events\n\t * Server will use these to resolve original source locations\n\t */\n\tincludeSourceMapReferences?: boolean\n\t/**\n\t * Artifact bundle ID (set automatically when source maps are uploaded)\n\t * Links error events to the correct source map version\n\t */\n\tartifactBundleId?: string\n\t/**\n\t * Debug IDs mapping for specific files\n\t * Used for more precise source map matching\n\t */\n\tdebugIds?: Record<string, string>\n}\n\n/**\n * Error tracking configuration\n */\nexport interface ErrorTrackingConfig {\n\t/** Enable/disable error tracking */\n\tenabled: boolean\n\t/** Environment slug or type, for example production or a customer-created environment. */\n\tenvironment?: string\n\t/** App release version */\n\trelease?: string\n\t/**\n\t * Distribution identifier (e.g., build number)\n\t * Used with release for precise source map matching\n\t */\n\tdist?: string\n\t/** DSN for uploading (if using external Sentry) */\n\tdsn?: string\n\t/** Sample rate (0-1) */\n\tsampleRate: number\n\t/** Capture unhandled errors */\n\tcaptureUnhandledErrors: boolean\n\t/** Capture unhandled promise rejections */\n\tcaptureUnhandledRejections: boolean\n\t/** Max breadcrumbs to keep */\n\tmaxBreadcrumbs: number\n\t/** Attach session replay ID to errors */\n\tattachReplay: boolean\n\t/** Automatically capture clicks */\n\tautoCaptureClicks: boolean\n\t/** Automatically capture network requests */\n\tautoCaptureNetwork: boolean\n\t/** Automatically capture console logs */\n\tautoCaptureConsole: boolean\n\t/** Automatically capture navigation */\n\tautoCaptureNavigation: boolean\n\t/** Before send hook for filtering/modifying events */\n\tbeforeSend?: (event: ErrorEvent) => ErrorEvent | null\n\t/** Tags to add to all events */\n\ttags?: Record<string, string>\n\t/**\n\t * Source map configuration for server-side stack trace processing\n\t * Server uses source maps to show original file names, line numbers, and code context\n\t */\n\tsourceMap?: SourceMapConfig\n\t/**\n\t * Enable automatic PII scrubbing (default: true)\n\t *\n\t * Automatically detects and redacts:\n\t * - Email addresses\n\t * - Credit card numbers\n\t * - Social Security Numbers\n\t * - Phone numbers\n\t * - IP addresses\n\t * - API keys and tokens\n\t * - Passwords\n\t * - JWT tokens\n\t *\n\t * Set to false to disable (not recommended for GDPR compliance)\n\t */\n\tscrubPII?: boolean\n}\n\n/**\n * Default configuration\n */\nexport const DEFAULT_ERROR_CONFIG: ErrorTrackingConfig = {\n\tenabled: true,\n\tsampleRate: 1.0,\n\tcaptureUnhandledErrors: true,\n\tcaptureUnhandledRejections: true,\n\tmaxBreadcrumbs: 100,\n\tattachReplay: true,\n\tautoCaptureClicks: true,\n\tautoCaptureNetwork: true,\n\tautoCaptureConsole: true,\n\tautoCaptureNavigation: true,\n\tsourceMap: {\n\t\tincludeSourceMapReferences: true,\n\t},\n}\n\n// ==========================================\n// Capture Options\n// ==========================================\n\n/**\n * Options for capturing an exception\n */\nexport interface CaptureExceptionOptions {\n\tlevel?: ErrorLevel\n\ttags?: Record<string, string>\n\textra?: Record<string, unknown>\n\tfingerprint?: string[]\n\tuser?: ErrorEvent['user']\n\tcontexts?: ErrorEvent['contexts']\n\t/** Attach specific replay session */\n\treplaySessionId?: string\n}\n\n/**\n * Options for capturing a message\n */\nexport interface CaptureMessageOptions {\n\tlevel?: ErrorLevel\n\ttags?: Record<string, string>\n\textra?: Record<string, unknown>\n}\n\n// ==========================================\n// Callback Types\n// ==========================================\n\n/**\n * Upload callback\n */\nexport type UploadCallback = (event: ErrorEvent) => Promise<UploadResult>\n\n/**\n * Upload result from server\n */\nexport interface UploadResult {\n\teventId: string\n\t/** Whether this is a new unique error (vs duplicate) */\n\tisNewError?: boolean\n\t/** Server-recommended sample rate based on quota usage (0-1) */\n\trecommendedSampleRate?: number\n\t/** Current quota usage percentage (0-100+) */\n\tquotaUsage?: number\n}\n\n/**\n * Capture result\n */\nexport interface CaptureResult {\n\teventId: string\n\treplaySessionId?: string\n}\n","/**\n * Error Tracker\n *\n * Core error tracking engine with:\n * - Sentry-compatible event format\n * - Session Replay integration\n * - Automatic breadcrumb collection\n * - Stack trace parsing\n */\n\nimport {\n\taddBreadcrumb,\n\tclearBreadcrumbs,\n\tenableAutoCapture,\n\tgetBreadcrumbs,\n\tsetMaxBreadcrumbs,\n} from './breadcrumbs'\nimport { scrubErrorEvent } from './pii-scrubber'\nimport type {\n\tBreadcrumb,\n\tCaptureExceptionOptions,\n\tCaptureMessageOptions,\n\tCaptureResult,\n\tErrorEvent,\n\tErrorTrackingConfig,\n\tExceptionValue,\n\tStackFrame,\n\tUploadCallback,\n} from './types'\nimport { DEFAULT_ERROR_CONFIG } from './types'\n\n// ==========================================\n// Error Tracker Class\n// ==========================================\n\n/**\n * Error Tracker\n *\n * Captures errors with full context including:\n * - Stack traces with source mapping support\n * - Breadcrumbs (automatic + manual)\n * - Session replay correlation\n * - Device/browser context\n */\nexport class ErrorTracker {\n\tprivate config: ErrorTrackingConfig\n\tprivate uploadCallback: UploadCallback | null = null\n\tprivate sessionReplayId: string | null = null\n\tprivate userId: string | null = null\n\tprivate userEmail: string | null = null\n\tprivate userName: string | null = null\n\n\t// Adaptive sampling - server-recommended rate overrides config\n\tprivate serverRecommendedSampleRate: number | null = null\n\tprivate enableAdaptiveSampling = true\n\n\tconstructor(config: Partial<ErrorTrackingConfig> = {}) {\n\t\tthis.config = { ...DEFAULT_ERROR_CONFIG, ...config }\n\t}\n\n\t// ==========================================\n\t// Initialization\n\t// ==========================================\n\n\t/**\n\t * Initialize error tracking\n\t */\n\tinit(): void {\n\t\tif (!this.config.enabled) return\n\t\tif (typeof window === 'undefined') return\n\n\t\t// Setup max breadcrumbs\n\t\tsetMaxBreadcrumbs(this.config.maxBreadcrumbs)\n\n\t\t// Setup auto capture\n\t\tenableAutoCapture({\n\t\t\tclicks: this.config.autoCaptureClicks,\n\t\t\tinputs: this.config.autoCaptureClicks, // Same as clicks for now\n\t\t\tnetwork: this.config.autoCaptureNetwork,\n\t\t\tconsole: this.config.autoCaptureConsole,\n\t\t\tnavigation: this.config.autoCaptureNavigation,\n\t\t})\n\n\t\t// Setup global error handlers\n\t\tif (this.config.captureUnhandledErrors) {\n\t\t\twindow.addEventListener('error', (event) => {\n\t\t\t\tif (event.error instanceof Error) {\n\t\t\t\t\tvoid this.captureException(event.error, {\n\t\t\t\t\t\ttags: { source: 'window.onerror' },\n\t\t\t\t\t\textra: {\n\t\t\t\t\t\t\tfilename: event.filename,\n\t\t\t\t\t\t\tlineno: event.lineno,\n\t\t\t\t\t\t\tcolno: event.colno,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\n\t\tif (this.config.captureUnhandledRejections) {\n\t\t\twindow.addEventListener('unhandledrejection', (event) => {\n\t\t\t\tconst error = event.reason instanceof Error ? event.reason : new Error(String(event.reason))\n\n\t\t\t\tvoid this.captureException(error, {\n\t\t\t\t\ttags: { source: 'unhandledrejection' },\n\t\t\t\t})\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Set upload callback\n\t */\n\tonUpload(callback: UploadCallback): void {\n\t\tthis.uploadCallback = callback\n\t}\n\n\t// ==========================================\n\t// Adaptive Sampling\n\t// ==========================================\n\n\t/**\n\t * Enable/disable adaptive sampling based on server recommendations\n\t * When enabled, server's recommendedSampleRate takes precedence over config\n\t */\n\tsetAdaptiveSampling(enabled: boolean): void {\n\t\tthis.enableAdaptiveSampling = enabled\n\t\tif (!enabled) {\n\t\t\tthis.serverRecommendedSampleRate = null\n\t\t}\n\t}\n\n\t/**\n\t * Update sample rate based on server recommendation\n\t * Called by upload callback when server returns quota feedback\n\t */\n\tupdateServerRecommendedSampleRate(rate: number | null): void {\n\t\tif (this.enableAdaptiveSampling && rate !== null) {\n\t\t\tthis.serverRecommendedSampleRate = Math.max(0, Math.min(1, rate))\n\t\t}\n\t}\n\n\t/**\n\t * Get effective sample rate (server recommendation takes precedence)\n\t */\n\tgetEffectiveSampleRate(): number {\n\t\tif (this.enableAdaptiveSampling && this.serverRecommendedSampleRate !== null) {\n\t\t\treturn this.serverRecommendedSampleRate\n\t\t}\n\t\treturn this.config.sampleRate\n\t}\n\n\t// ==========================================\n\t// User & Session Context\n\t// ==========================================\n\n\t/**\n\t * Set session replay ID for correlation\n\t */\n\tsetSessionReplayId(sessionId: string): void {\n\t\tthis.sessionReplayId = sessionId\n\t}\n\n\t/**\n\t * Set user information\n\t */\n\tsetUser(user: { id?: string; email?: string; username?: string }): void {\n\t\tthis.userId = user.id ?? null\n\t\tthis.userEmail = user.email ?? null\n\t\tthis.userName = user.username ?? null\n\t}\n\n\t/**\n\t * Clear user information\n\t */\n\tclearUser(): void {\n\t\tthis.userId = null\n\t\tthis.userEmail = null\n\t\tthis.userName = null\n\t}\n\n\t// ==========================================\n\t// Breadcrumbs\n\t// ==========================================\n\n\t/**\n\t * Add a breadcrumb\n\t */\n\taddBreadcrumb(breadcrumb: Breadcrumb): void {\n\t\taddBreadcrumb(breadcrumb)\n\t}\n\n\t// ==========================================\n\t// Capture Methods\n\t// ==========================================\n\n\t/**\n\t * Capture an exception\n\t */\n\tasync captureException(\n\t\terror: Error,\n\t\toptions: CaptureExceptionOptions = {},\n\t): Promise<CaptureResult> {\n\t\tif (!this.config.enabled) {\n\t\t\treturn { eventId: '' }\n\t\t}\n\n\t\t// Sample rate check (uses server-recommended rate if adaptive sampling is enabled)\n\t\tconst effectiveSampleRate = this.getEffectiveSampleRate()\n\t\tif (Math.random() > effectiveSampleRate) {\n\t\t\treturn { eventId: '' }\n\t\t}\n\n\t\tconst eventId = this.generateEventId()\n\t\tconst timestamp = Date.now()\n\n\t\t// Build event\n\t\tconst event: ErrorEvent = {\n\t\t\tevent_id: eventId,\n\t\t\ttimestamp: timestamp / 1000, // Sentry uses seconds\n\t\t\tplatform: 'javascript',\n\t\t\tlevel: options.level ?? 'error',\n\t\t\tenvironment: this.config.environment,\n\t\t\trelease: this.config.release,\n\t\t\tdist: this.config.dist, // Distribution for source map matching\n\t\t\texception: {\n\t\t\t\tvalues: [this.parseException(error)],\n\t\t\t},\n\t\t\ttags: {\n\t\t\t\t...this.config.tags,\n\t\t\t\t...options.tags,\n\t\t\t\t// Include source map metadata for server-side processing\n\t\t\t\t...(this.config.sourceMap?.artifactBundleId\n\t\t\t\t\t? { artifact_bundle_id: this.config.sourceMap.artifactBundleId }\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t\textra: {\n\t\t\t\t...options.extra,\n\t\t\t\t// Include source map config for server-side processing\n\t\t\t\t...(this.config.sourceMap?.urlPrefix\n\t\t\t\t\t? { _sourcemap_url_prefix: this.config.sourceMap.urlPrefix }\n\t\t\t\t\t: {}),\n\t\t\t\t...(this.config.sourceMap?.debugIds\n\t\t\t\t\t? { _sourcemap_debug_ids: this.config.sourceMap.debugIds }\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t\tfingerprint: options.fingerprint,\n\t\t\tcontexts: {\n\t\t\t\t...this.getDeviceContext(),\n\t\t\t\t...options.contexts,\n\t\t\t\t...(this.config.attachReplay && this.sessionReplayId\n\t\t\t\t\t? {\n\t\t\t\t\t\t\treplay: {\n\t\t\t\t\t\t\t\tsession_id: options.replaySessionId ?? this.sessionReplayId,\n\t\t\t\t\t\t\t\terror_timestamp: timestamp,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t\tuser: options.user ?? this.getUserContext(),\n\t\t\trequest: this.getRequestContext(),\n\t\t\tbreadcrumbs: {\n\t\t\t\tvalues: getBreadcrumbs(),\n\t\t\t},\n\t\t\tsdk: {\n\t\t\t\tname: 'sylphx-runtime',\n\t\t\t\tversion: '0.5.0',\n\t\t\t\tintegrations: this.getIntegrations(),\n\t\t\t},\n\t\t}\n\n\t\t// Before send hook - explicitly check for null to allow suppression\n\t\tconst processedEvent = this.config.beforeSend ? this.config.beforeSend(event) : event\n\n\t\tif (processedEvent === null) {\n\t\t\treturn { eventId: '' }\n\t\t}\n\n\t\t// PII Scrubbing - automatically redact sensitive data (GDPR/privacy compliance)\n\t\t// This runs AFTER beforeSend to ensure user transformations are also scrubbed\n\t\tconst scrubbedEvent =\n\t\t\tthis.config.scrubPII !== false ? scrubErrorEvent(processedEvent) : processedEvent\n\n\t\t// Upload\n\t\ttry {\n\t\t\tif (this.uploadCallback) {\n\t\t\t\tconst uploadResult = await this.uploadCallback(scrubbedEvent)\n\n\t\t\t\t// Update adaptive sampling based on server feedback\n\t\t\t\tif (uploadResult.recommendedSampleRate !== undefined) {\n\t\t\t\t\tthis.updateServerRecommendedSampleRate(uploadResult.recommendedSampleRate)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Clear breadcrumbs after successful send\n\t\t\tclearBreadcrumbs()\n\n\t\t\treturn {\n\t\t\t\teventId,\n\t\t\t\treplaySessionId: this.sessionReplayId ?? undefined,\n\t\t\t}\n\t\t} catch (uploadError) {\n\t\t\tconsole.error('[Sylphx] Failed to upload error event:', uploadError)\n\t\t\treturn { eventId }\n\t\t}\n\t}\n\n\t/**\n\t * Capture a message\n\t */\n\tasync captureMessage(\n\t\tmessage: string,\n\t\toptions: CaptureMessageOptions = {},\n\t): Promise<CaptureResult> {\n\t\tif (!this.config.enabled) {\n\t\t\treturn { eventId: '' }\n\t\t}\n\n\t\tconst eventId = this.generateEventId()\n\n\t\tconst event: ErrorEvent = {\n\t\t\tevent_id: eventId,\n\t\t\ttimestamp: Date.now() / 1000,\n\t\t\tplatform: 'javascript',\n\t\t\tlevel: options.level ?? 'info',\n\t\t\tenvironment: this.config.environment,\n\t\t\trelease: this.config.release,\n\t\t\tmessage: {\n\t\t\t\tformatted: message,\n\t\t\t\tmessage,\n\t\t\t},\n\t\t\ttags: {\n\t\t\t\t...this.config.tags,\n\t\t\t\t...options.tags,\n\t\t\t},\n\t\t\textra: options.extra,\n\t\t\tcontexts: this.getDeviceContext(),\n\t\t\tuser: this.getUserContext(),\n\t\t\trequest: this.getRequestContext(),\n\t\t\tbreadcrumbs: {\n\t\t\t\tvalues: getBreadcrumbs(),\n\t\t\t},\n\t\t\tsdk: {\n\t\t\t\tname: 'sylphx-runtime',\n\t\t\t\tversion: '0.5.0',\n\t\t\t},\n\t\t}\n\n\t\t// Before send hook - explicitly check for null to allow suppression\n\t\tconst processedEvent = this.config.beforeSend ? this.config.beforeSend(event) : event\n\n\t\tif (processedEvent === null) {\n\t\t\treturn { eventId: '' }\n\t\t}\n\n\t\t// PII Scrubbing - automatically redact sensitive data (GDPR/privacy compliance)\n\t\tconst scrubbedEvent =\n\t\t\tthis.config.scrubPII !== false ? scrubErrorEvent(processedEvent) : processedEvent\n\n\t\ttry {\n\t\t\tif (this.uploadCallback) {\n\t\t\t\tawait this.uploadCallback(scrubbedEvent)\n\t\t\t}\n\n\t\t\treturn { eventId }\n\t\t} catch (uploadError) {\n\t\t\tconsole.error('[Sylphx] Failed to upload message event:', uploadError)\n\t\t\treturn { eventId }\n\t\t}\n\t}\n\n\t// ==========================================\n\t// Private Methods\n\t// ==========================================\n\n\tprivate generateEventId(): string {\n\t\t// Sentry uses 32-char hex IDs (16 bytes = 32 hex chars)\n\t\tconst bytes = new Uint8Array(16)\n\t\tcrypto.getRandomValues(bytes)\n\t\treturn Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('')\n\t}\n\n\tprivate parseException(error: Error): ExceptionValue {\n\t\tconst frames: StackFrame[] = []\n\t\tconst urlPrefix = this.config.sourceMap?.urlPrefix\n\t\tconst debugIds = this.config.sourceMap?.debugIds\n\n\t\tif (error.stack) {\n\t\t\tconst lines = error.stack.split('\\n').slice(1) // Skip first line (error message)\n\n\t\t\tfor (const line of lines) {\n\t\t\t\t// Chrome/Edge format: \"    at functionName (file:line:col)\"\n\t\t\t\t// Firefox format: \"functionName@file:line:col\"\n\t\t\t\tconst chromeMatch = line.match(/^\\s*at\\s+(?:(.+?)\\s+)?(?:\\()?(.+?):(\\d+):(\\d+)\\)?$/)\n\t\t\t\tconst firefoxMatch = line.match(/^(.*)@(.+?):(\\d+):(\\d+)$/)\n\n\t\t\t\tconst match = chromeMatch || firefoxMatch\n\t\t\t\tif (match) {\n\t\t\t\t\tconst [, fn, filename, lineno, colno] = match\n\t\t\t\t\tconst isInApp = !filename?.includes('node_modules') && !filename?.includes('vendor')\n\n\t\t\t\t\t// Build abs_path for source map resolution\n\t\t\t\t\t// If urlPrefix is set, prepend it to relative paths for matching\n\t\t\t\t\tlet absPath = filename\n\t\t\t\t\tif (urlPrefix && filename && !filename.startsWith('http')) {\n\t\t\t\t\t\tabsPath = `${urlPrefix.replace(/\\/$/, '')}/${filename.replace(/^\\.?\\//, '')}`\n\t\t\t\t\t}\n\n\t\t\t\t\t// Look up debug ID for this file (Sentry debug ID pattern)\n\t\t\t\t\tconst debugId = debugIds?.[filename ?? '']\n\n\t\t\t\t\tframes.push({\n\t\t\t\t\t\tfunction: fn || '<anonymous>',\n\t\t\t\t\t\tfilename,\n\t\t\t\t\t\tabs_path: absPath, // Full path for source map lookup\n\t\t\t\t\t\tlineno: Number.parseInt(lineno ?? '0', 10),\n\t\t\t\t\t\tcolno: Number.parseInt(colno ?? '0', 10),\n\t\t\t\t\t\tin_app: isInApp,\n\t\t\t\t\t\t// Include debug ID if available (used for precise source map matching)\n\t\t\t\t\t\t...(debugId ? { vars: { debug_id: debugId } } : {}),\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\ttype: error.name || 'Error',\n\t\t\tvalue: error.message,\n\t\t\tstacktrace: frames.length > 0 ? { frames: frames.reverse() } : undefined, // Sentry wants frames bottom-to-top\n\t\t\tmechanism: {\n\t\t\t\ttype: 'generic',\n\t\t\t\thandled: true,\n\t\t\t},\n\t\t}\n\t}\n\n\tprivate getDeviceContext(): ErrorEvent['contexts'] {\n\t\tif (typeof window === 'undefined') return {}\n\n\t\tconst ua = navigator.userAgent\n\t\tconst browserMatch = ua.match(/(Chrome|Firefox|Safari|Edge|Opera)\\/(\\d+)/)\n\t\tconst osMatch = ua.match(/(Windows|Mac OS X|Linux|Android|iOS)[^\\d]*(\\d+[\\d._]*)?/)\n\n\t\tconst screen = typeof window !== 'undefined' ? window.screen : null\n\t\tconst nav = typeof navigator !== 'undefined' ? navigator : null\n\n\t\treturn {\n\t\t\tdevice: {\n\t\t\t\tscreen_resolution: screen != null ? `${screen.width}x${screen.height}` : 'unknown',\n\t\t\t\tscreen_density: typeof window !== 'undefined' ? window.devicePixelRatio : undefined,\n\t\t\t\torientation: screen?.orientation?.type.includes('landscape') ? 'landscape' : 'portrait',\n\t\t\t\tonline: nav?.onLine,\n\t\t\t},\n\t\t\tbrowser: {\n\t\t\t\tname: browserMatch?.[1],\n\t\t\t\tversion: browserMatch?.[2],\n\t\t\t},\n\t\t\tos: {\n\t\t\t\tname: osMatch?.[1]?.replace('Mac OS X', 'macOS'),\n\t\t\t\tversion: osMatch?.[2]?.replace(/_/g, '.'),\n\t\t\t},\n\t\t\truntime: {\n\t\t\t\tname: 'browser',\n\t\t\t},\n\t\t}\n\t}\n\n\tprivate getUserContext(): ErrorEvent['user'] | undefined {\n\t\tif (!this.userId && !this.userEmail && !this.userName) {\n\t\t\treturn undefined\n\t\t}\n\n\t\treturn {\n\t\t\tid: this.userId ?? undefined,\n\t\t\temail: this.userEmail ?? undefined,\n\t\t\tusername: this.userName ?? undefined,\n\t\t}\n\t}\n\n\tprivate getRequestContext(): ErrorEvent['request'] | undefined {\n\t\tif (typeof window === 'undefined' || window.location == null) return undefined\n\n\t\treturn {\n\t\t\turl: window.location.href,\n\t\t\tquery_string: window.location.search.slice(1),\n\t\t\theaders: {\n\t\t\t\t'User-Agent': navigator.userAgent,\n\t\t\t},\n\t\t}\n\t}\n\n\tprivate getIntegrations(): string[] {\n\t\tconst integrations: string[] = []\n\n\t\tif (this.config.captureUnhandledErrors) integrations.push('GlobalErrorHandler')\n\t\tif (this.config.captureUnhandledRejections) integrations.push('UnhandledRejectionHandler')\n\t\tif (this.config.autoCaptureClicks) integrations.push('ClickCapture')\n\t\tif (this.config.autoCaptureNetwork) integrations.push('NetworkCapture')\n\t\tif (this.config.autoCaptureConsole) integrations.push('ConsoleCapture')\n\t\tif (this.config.autoCaptureNavigation) integrations.push('NavigationCapture')\n\t\tif (this.config.attachReplay) integrations.push('SessionReplay')\n\n\t\treturn integrations\n\t}\n}\n\n// ==========================================\n// Singleton Instance\n// ==========================================\n\nlet trackerInstance: ErrorTracker | null = null\n\n/**\n * Get or create the error tracker instance\n */\nexport function getTracker(config?: Partial<ErrorTrackingConfig>): ErrorTracker {\n\tif (!trackerInstance) {\n\t\ttrackerInstance = new ErrorTracker(config)\n\t}\n\treturn trackerInstance\n}\n\n/**\n * Initialize error tracking\n */\nexport function initErrorTracking(config?: Partial<ErrorTrackingConfig>): ErrorTracker {\n\tconst tracker = getTracker(config)\n\ttracker.init()\n\treturn tracker\n}\n\n/**\n * Reset the singleton instance (for testing)\n */\nexport function resetTracker(): void {\n\ttrackerInstance = null\n}\n","/**\n * Session Replay Detectors\n *\n * SOTA user frustration detection:\n * - Rage clicks (repeated rapid clicking)\n * - Dead clicks (clicks with no effect)\n * - Error clicks (clicks causing errors)\n * - Scroll thrashing (rapid scrolling)\n */\n\nimport {\n\tDOM_SNAPSHOT_MAX_LENGTH,\n\tSESSION_REPLAY_DEAD_CLICK_TIMEOUT_MS,\n\tSESSION_REPLAY_RAGE_CLICK_WINDOW_MS,\n\tSESSION_REPLAY_SCROLL_HEAT_WINDOW_MS,\n} from '../../../constants'\nimport { onFetchStart, onXHRStart, type UnsubscribeFn } from '../network-interceptor'\nimport type { DeadClick, RageClick } from './types'\n\n// ==========================================\n// Types\n// ==========================================\n\ninterface ClickEvent {\n\ttimestamp: number\n\tx: number\n\ty: number\n\ttarget: Element | null\n\tselector: string\n}\n\ninterface ScrollEvent {\n\ttimestamp: number\n\tscrollY: number\n\tdirection: 'up' | 'down'\n}\n\n// ==========================================\n// Rage Click Detection\n// ==========================================\n\n/**\n * Rage click detector\n *\n * Detects when users click rapidly on the same element,\n * indicating frustration or confusion.\n */\nexport class RageClickDetector {\n\tprivate clickHistory: ClickEvent[] = []\n\tprivate readonly threshold: number\n\tprivate readonly windowMs: number\n\tprivate readonly proximityPx: number\n\tprivate callback: ((rageClick: RageClick) => void) | null = null\n\n\tconstructor(\n\t\toptions: {\n\t\t\tthreshold?: number\n\t\t\twindowMs?: number\n\t\t\tproximityPx?: number\n\t\t} = {},\n\t) {\n\t\tthis.threshold = options.threshold ?? 3\n\t\tthis.windowMs = options.windowMs ?? SESSION_REPLAY_RAGE_CLICK_WINDOW_MS\n\t\tthis.proximityPx = options.proximityPx ?? 30\n\t}\n\n\t/**\n\t * Set callback for rage click detection\n\t */\n\tonRageClick(callback: (rageClick: RageClick) => void): void {\n\t\tthis.callback = callback\n\t}\n\n\t/**\n\t * Record a click event\n\t */\n\trecordClick(event: MouseEvent): RageClick | null {\n\t\tconst now = Date.now()\n\t\tconst target = event.target as Element | null\n\n\t\t// Build selector for target\n\t\tconst selector = this.buildSelector(target)\n\n\t\tconst clickEvent: ClickEvent = {\n\t\t\ttimestamp: now,\n\t\t\tx: event.clientX,\n\t\t\ty: event.clientY,\n\t\t\ttarget,\n\t\t\tselector,\n\t\t}\n\n\t\t// Clean old clicks outside window\n\t\tthis.clickHistory = this.clickHistory.filter((c) => now - c.timestamp < this.windowMs)\n\n\t\t// Add new click\n\t\tthis.clickHistory.push(clickEvent)\n\n\t\t// Check for rage click\n\t\tconst rageClick = this.detectRageClick(clickEvent)\n\t\tif (rageClick && this.callback) {\n\t\t\tthis.callback(rageClick)\n\t\t}\n\n\t\treturn rageClick\n\t}\n\n\t/**\n\t * Check if recent clicks constitute a rage click\n\t */\n\tprivate detectRageClick(latestClick: ClickEvent): RageClick | null {\n\t\t// Filter clicks near the latest click\n\t\tconst nearbyClicks = this.clickHistory.filter((c) => {\n\t\t\tconst dx = Math.abs(c.x - latestClick.x)\n\t\t\tconst dy = Math.abs(c.y - latestClick.y)\n\t\t\tconst distance = Math.sqrt(dx * dx + dy * dy)\n\t\t\treturn distance < this.proximityPx\n\t\t})\n\n\t\tif (nearbyClicks.length >= this.threshold) {\n\t\t\tconst firstClick = nearbyClicks[0]!\n\t\t\tconst lastClick = nearbyClicks[nearbyClicks.length - 1]!\n\n\t\t\treturn {\n\t\t\t\ttimestamp: latestClick.timestamp,\n\t\t\t\telement: this.getElementDescription(latestClick.target),\n\t\t\t\tselector: latestClick.selector,\n\t\t\t\tclickCount: nearbyClicks.length,\n\t\t\t\tduration: lastClick.timestamp - firstClick.timestamp,\n\t\t\t}\n\t\t}\n\n\t\treturn null\n\t}\n\n\t/**\n\t * Build a CSS selector for an element\n\t */\n\tprivate buildSelector(element: Element | null): string {\n\t\tif (!element) return 'unknown'\n\n\t\tif (element.id) {\n\t\t\treturn `#${CSS.escape(element.id)}`\n\t\t}\n\n\t\tconst classes = Array.from(element.classList)\n\t\t\t.slice(0, 2)\n\t\t\t.map((c) => `.${CSS.escape(c)}`)\n\t\t\t.join('')\n\n\t\tconst tag = element.tagName.toLowerCase()\n\n\t\tif (classes) {\n\t\t\treturn `${tag}${classes}`\n\t\t}\n\n\t\treturn tag\n\t}\n\n\t/**\n\t * Get human-readable description of element\n\t */\n\tprivate getElementDescription(element: Element | null): string {\n\t\tif (!element) return 'unknown element'\n\n\t\tconst tag = element.tagName.toLowerCase()\n\t\tconst text = element.textContent?.slice(0, 50).trim() || ''\n\t\tconst role = element.getAttribute('role') || ''\n\n\t\tif (text) {\n\t\t\treturn `${tag}[${text}]`\n\t\t}\n\n\t\tif (role) {\n\t\t\treturn `${tag}[role=${role}]`\n\t\t}\n\n\t\treturn tag\n\t}\n\n\t/**\n\t * Reset detector state\n\t */\n\treset(): void {\n\t\tthis.clickHistory = []\n\t}\n}\n\n// ==========================================\n// Dead Click Detection\n// ==========================================\n\n/**\n * Dead click detector\n *\n * Detects clicks that had no visible effect:\n * - No navigation\n * - No DOM change\n * - No network request\n */\nexport class DeadClickDetector {\n\tprivate pendingClick: {\n\t\tevent: MouseEvent\n\t\ttimestamp: number\n\t\tdomSnapshot: string\n\t\turl: string\n\t} | null = null\n\n\tprivate observer: MutationObserver | null = null\n\tprivate networkActivity = false\n\tprivate readonly timeout: number\n\tprivate callback: ((deadClick: DeadClick) => void) | null = null\n\tprivate networkUnsubscribers: UnsubscribeFn[] = []\n\n\tconstructor(options: { timeout?: number } = {}) {\n\t\tthis.timeout = options.timeout ?? SESSION_REPLAY_DEAD_CLICK_TIMEOUT_MS\n\t\tthis.setupNetworkMonitor()\n\t}\n\n\t/**\n\t * Set callback for dead click detection\n\t */\n\tonDeadClick(callback: (deadClick: DeadClick) => void): void {\n\t\tthis.callback = callback\n\t}\n\n\t/**\n\t * Record a click and monitor for effects\n\t */\n\trecordClick(event: MouseEvent): void {\n\t\tconst target = event.target as Element\n\t\tif (!target) return\n\n\t\t// Skip if element is inherently non-interactive\n\t\tif (this.isNonInteractive(target)) return\n\n\t\tthis.pendingClick = {\n\t\t\tevent,\n\t\t\ttimestamp: Date.now(),\n\t\t\tdomSnapshot: document.body.innerHTML.slice(0, DOM_SNAPSHOT_MAX_LENGTH),\n\t\t\turl: window.location.href,\n\t\t}\n\n\t\tthis.networkActivity = false\n\t\tthis.startMutationObserver()\n\n\t\t// Check after timeout\n\t\tsetTimeout(() => this.checkForDeadClick(), this.timeout)\n\t}\n\n\t/**\n\t * Check if the click had any effect\n\t */\n\tprivate checkForDeadClick(): void {\n\t\tif (!this.pendingClick) return\n\n\t\tconst click = this.pendingClick\n\t\tconst target = click.event.target as Element\n\n\t\t// Check for navigation\n\t\tif (window.location.href !== click.url) {\n\t\t\tthis.pendingClick = null\n\t\t\treturn\n\t\t}\n\n\t\t// Check for DOM changes\n\t\tconst currentSnapshot = document.body.innerHTML.slice(0, DOM_SNAPSHOT_MAX_LENGTH)\n\t\tif (currentSnapshot !== click.domSnapshot) {\n\t\t\tthis.pendingClick = null\n\t\t\treturn\n\t\t}\n\n\t\t// Check for network activity\n\t\tif (this.networkActivity) {\n\t\t\tthis.pendingClick = null\n\t\t\treturn\n\t\t}\n\n\t\t// This was a dead click\n\t\tconst deadClick: DeadClick = {\n\t\t\ttimestamp: click.timestamp,\n\t\t\telement: this.getElementDescription(target),\n\t\t\tselector: this.buildSelector(target),\n\t\t\texpectedAction: this.inferExpectedAction(target),\n\t\t}\n\n\t\tif (this.callback) {\n\t\t\tthis.callback(deadClick)\n\t\t}\n\n\t\tthis.pendingClick = null\n\t}\n\n\t/**\n\t * Check if element is naturally non-interactive\n\t */\n\tprivate isNonInteractive(element: Element): boolean {\n\t\tconst nonInteractiveTags = new Set([\n\t\t\t'div',\n\t\t\t'span',\n\t\t\t'p',\n\t\t\t'section',\n\t\t\t'article',\n\t\t\t'header',\n\t\t\t'footer',\n\t\t\t'main',\n\t\t\t'aside',\n\t\t\t'nav',\n\t\t])\n\n\t\tconst tag = element.tagName.toLowerCase()\n\n\t\t// Interactive elements\n\t\tif (\n\t\t\t['a', 'button', 'input', 'select', 'textarea'].includes(tag) ||\n\t\t\telement.hasAttribute('onclick') ||\n\t\t\telement.getAttribute('role') === 'button' ||\n\t\t\telement.hasAttribute('tabindex')\n\t\t) {\n\t\t\treturn false\n\t\t}\n\n\t\t// Check for cursor style\n\t\tconst style = window.getComputedStyle(element)\n\t\tif (style.cursor === 'pointer') {\n\t\t\treturn false\n\t\t}\n\n\t\treturn nonInteractiveTags.has(tag)\n\t}\n\n\t/**\n\t * Infer what action the user expected\n\t */\n\tprivate inferExpectedAction(element: Element): string {\n\t\tconst tag = element.tagName.toLowerCase()\n\t\tconst role = element.getAttribute('role')\n\n\t\tif (tag === 'a' || role === 'link') {\n\t\t\treturn 'navigation'\n\t\t}\n\n\t\tif (tag === 'button' || role === 'button') {\n\t\t\treturn 'action'\n\t\t}\n\n\t\tif (tag === 'input' || tag === 'select') {\n\t\t\treturn 'input focus'\n\t\t}\n\n\t\tconst text = element.textContent?.slice(0, 30).toLowerCase() || ''\n\n\t\tif (text.includes('submit') || text.includes('save')) {\n\t\t\treturn 'form submission'\n\t\t}\n\n\t\tif (text.includes('close') || text.includes('cancel')) {\n\t\t\treturn 'close/cancel'\n\t\t}\n\n\t\treturn 'interaction'\n\t}\n\n\t/**\n\t * Setup mutation observer\n\t */\n\tprivate startMutationObserver(): void {\n\t\tthis.stopMutationObserver()\n\n\t\tthis.observer = new MutationObserver(() => {\n\t\t\t// DOM changed, not a dead click\n\t\t\tthis.pendingClick = null\n\t\t})\n\n\t\tthis.observer.observe(document.body, {\n\t\t\tchildList: true,\n\t\t\tsubtree: true,\n\t\t\tattributes: true,\n\t\t\tcharacterData: true,\n\t\t})\n\t}\n\n\t/**\n\t * Stop mutation observer\n\t */\n\tprivate stopMutationObserver(): void {\n\t\tif (this.observer) {\n\t\t\tthis.observer.disconnect()\n\t\t\tthis.observer = null\n\t\t}\n\t}\n\n\t/**\n\t * Monitor network activity via shared interceptor.\n\t *\n\t * Uses the centralized network interceptor instead of independently\n\t * monkey-patching fetch/XHR. Only needs to know that a request started\n\t * (not the details), so listens to start events only.\n\t */\n\tprivate setupNetworkMonitor(): void {\n\t\tthis.networkUnsubscribers.push(\n\t\t\tonFetchStart(() => {\n\t\t\t\tthis.networkActivity = true\n\t\t\t}),\n\t\t)\n\n\t\tthis.networkUnsubscribers.push(\n\t\t\tonXHRStart(() => {\n\t\t\t\tthis.networkActivity = true\n\t\t\t}),\n\t\t)\n\t}\n\n\tprivate buildSelector(element: Element | null): string {\n\t\tif (!element) return 'unknown'\n\n\t\tif (element.id) {\n\t\t\treturn `#${CSS.escape(element.id)}`\n\t\t}\n\n\t\tconst classes = Array.from(element.classList)\n\t\t\t.slice(0, 2)\n\t\t\t.map((c) => `.${CSS.escape(c)}`)\n\t\t\t.join('')\n\n\t\tconst tag = element.tagName.toLowerCase()\n\t\treturn classes ? `${tag}${classes}` : tag\n\t}\n\n\tprivate getElementDescription(element: Element | null): string {\n\t\tif (!element) return 'unknown element'\n\n\t\tconst tag = element.tagName.toLowerCase()\n\t\tconst text = element.textContent?.slice(0, 50).trim() || ''\n\t\tconst role = element.getAttribute('role') || ''\n\n\t\tif (text) return `${tag}[${text}]`\n\t\tif (role) return `${tag}[role=${role}]`\n\t\treturn tag\n\t}\n\n\t/**\n\t * Cleanup\n\t */\n\tdestroy(): void {\n\t\tthis.stopMutationObserver()\n\t\tfor (const unsub of this.networkUnsubscribers) {\n\t\t\tunsub()\n\t\t}\n\t\tthis.networkUnsubscribers = []\n\t}\n}\n\n// ==========================================\n// Scroll Thrashing Detection\n// ==========================================\n\n/**\n * Scroll thrashing detector\n *\n * Detects rapid up-down scrolling indicating user confusion\n */\nexport class ScrollThrashingDetector {\n\tprivate scrollHistory: ScrollEvent[] = []\n\tprivate lastScrollY = 0\n\tprivate readonly threshold: number\n\tprivate readonly windowMs: number\n\tprivate callback: ((event: { timestamp: number; reversals: number }) => void) | null = null\n\n\tconstructor(options: { threshold?: number; windowMs?: number } = {}) {\n\t\tthis.threshold = options.threshold ?? 4\n\t\tthis.windowMs = options.windowMs ?? SESSION_REPLAY_SCROLL_HEAT_WINDOW_MS\n\t}\n\n\tonThrashing(callback: (event: { timestamp: number; reversals: number }) => void): void {\n\t\tthis.callback = callback\n\t}\n\n\trecordScroll(scrollY: number): void {\n\t\tconst now = Date.now()\n\t\tconst direction: 'up' | 'down' = scrollY > this.lastScrollY ? 'down' : 'up'\n\n\t\t// Clean old events\n\t\tthis.scrollHistory = this.scrollHistory.filter((e) => now - e.timestamp < this.windowMs)\n\n\t\t// Only record direction changes\n\t\tconst lastEvent = this.scrollHistory[this.scrollHistory.length - 1]\n\t\tif (!lastEvent || lastEvent.direction !== direction) {\n\t\t\tthis.scrollHistory.push({ timestamp: now, scrollY, direction })\n\t\t}\n\n\t\tthis.lastScrollY = scrollY\n\n\t\t// Check for thrashing (direction reversals)\n\t\tif (this.scrollHistory.length >= this.threshold) {\n\t\t\tif (this.callback) {\n\t\t\t\tthis.callback({\n\t\t\t\t\ttimestamp: now,\n\t\t\t\t\treversals: this.scrollHistory.length,\n\t\t\t\t})\n\t\t\t}\n\t\t\tthis.scrollHistory = []\n\t\t}\n\t}\n\n\treset(): void {\n\t\tthis.scrollHistory = []\n\t}\n}\n","/**\n * Session Replay Recorder\n *\n * Core recording engine built on rrweb with SOTA enhancements.\n * Handles recording lifecycle, event batching, and uploads.\n */\n\nimport type { eventWithTime } from '@rrweb/types'\nimport {\n\tLOG_MESSAGE_MAX_LENGTH,\n\tSESSION_REPLAY_MAX_DURATION_MS,\n\tSESSION_REPLAY_UPLOAD_INTERVAL_MS,\n\tSTACK_TRACE_MAX_LENGTH,\n} from '../../../constants'\nimport { onFetchEnd, onXHREnd, type UnsubscribeFn } from '../network-interceptor'\nimport { DeadClickDetector, RageClickDetector, ScrollThrashingDetector } from './detectors'\nimport { getPrivacyOptions, sanitizeForLogging, sanitizeUrl } from './privacy'\nimport type {\n\tConsoleLog,\n\tDeadClick,\n\tNetworkRequest,\n\tRageClick,\n\tRecorderState,\n\tRecorderStatus,\n\tSessionData,\n\tSessionMarker,\n\tSessionMetadata,\n\tSessionReplayConfig,\n\tUploadCallback,\n} from './types'\n\n// ==========================================\n// Types\n// ==========================================\n\ntype StopFn = () => void\n\n/** rrweb module type — lets us type the lazily-loaded `record` fn without a static runtime import. */\ntype RrwebModule = typeof import('rrweb')\n\n/**\n * Lazily-loaded rrweb `record` fn. rrweb is heavy (~hundreds of KB) and only\n * needed once a replay actually starts, so it is dynamically imported and kept\n * external from the react entry (see `tsup.config.ts`) — it lands in a separate\n * async chunk in the consumer's bundle and is fetched only when recording\n * begins. Mirrors the `@opentelemetry/api` lazy-load pattern in `health/otel.ts`.\n */\nlet cachedRecord: RrwebModule['record'] | null = null\nlet rrwebRecordLoader: () => Promise<RrwebModule['record']> = async () =>\n\t(await import('rrweb')).record\n\nasync function loadRrwebRecord(): Promise<RrwebModule['record']> {\n\tif (!cachedRecord) {\n\t\tcachedRecord = await rrwebRecordLoader()\n\t}\n\treturn cachedRecord\n}\n\n/** @internal Test-only seam for lazy rrweb lifecycle races. Not re-exported by package barrels. */\nexport function __setRrwebRecordLoaderForTest(\n\tloader?: () => Promise<RrwebModule['record']>,\n): void {\n\tcachedRecord = null\n\trrwebRecordLoader = loader ?? (async () => (await import('rrweb')).record)\n}\n\n// ==========================================\n// Session Recorder\n// ==========================================\n\n/**\n * Session Replay Recorder\n *\n * Manages the full lifecycle of session recording with:\n * - Privacy-aware DOM recording\n * - Network/console capture\n * - Frustration detection (rage clicks, dead clicks)\n * - Efficient batching and compression\n */\nexport class SessionRecorder {\n\tprivate config: SessionReplayConfig\n\tprivate state: RecorderState = 'idle'\n\tprivate sessionId: string | null = null\n\tprivate startTime: number | null = null\n\n\t// Event storage\n\tprivate events: eventWithTime[] = []\n\tprivate markers: SessionMarker[] = []\n\tprivate rageClicks: RageClick[] = []\n\tprivate deadClicks: DeadClick[] = []\n\tprivate networkRequests: NetworkRequest[] = []\n\tprivate consoleLogs: ConsoleLog[] = []\n\n\t// rrweb handles\n\tprivate stopFn: StopFn | null = null\n\tprivate rrwebRecordingEpoch = 0\n\n\t// Detectors\n\tprivate rageClickDetector: RageClickDetector | null = null\n\tprivate deadClickDetector: DeadClickDetector | null = null\n\tprivate scrollThrashingDetector: ScrollThrashingDetector | null = null\n\n\t// Callbacks\n\tprivate uploadCallback: UploadCallback | null = null\n\tprivate eventCallback: ((event: eventWithTime) => void) | null = null\n\tprivate errorCallback: ((error: Error) => void) | null = null\n\n\t// Timers\n\tprivate uploadTimer: ReturnType<typeof setInterval> | null = null\n\tprivate durationTimer: ReturnType<typeof setTimeout> | null = null\n\n\t// Network interceptor cleanup\n\tprivate networkUnsubscribers: UnsubscribeFn[] = []\n\n\t// Stats\n\tprivate bytesRecorded = 0\n\n\tconstructor(config: Partial<SessionReplayConfig> = {}) {\n\t\tthis.config = { ...this.getDefaultConfig(), ...config }\n\t}\n\n\tprivate getDefaultConfig(): SessionReplayConfig {\n\t\treturn {\n\t\t\tenabled: true,\n\t\t\tsampling: { rate: 100, alwaysRecordErrors: true },\n\t\t\tmaxDuration: SESSION_REPLAY_MAX_DURATION_MS,\n\t\t\tprivacyMode: 'balanced',\n\t\t\tmaskSelectors: [],\n\t\t\tblockSelectors: [],\n\t\t\tignoreSelectors: [],\n\t\t\terrorCorrelation: true,\n\t\t\trageClickDetection: true,\n\t\t\tdeadClickDetection: true,\n\t\t\taiSummary: false,\n\t\t\theatmaps: true,\n\t\t\tnetworkCapture: true,\n\t\t\tconsoleCapture: true,\n\t\t\tcompress: true,\n\t\t\tbatchSize: 50,\n\t\t\tuploadInterval: SESSION_REPLAY_UPLOAD_INTERVAL_MS,\n\t\t}\n\t}\n\n\t// ==========================================\n\t// Lifecycle\n\t// ==========================================\n\n\t/**\n\t * Start recording a new session\n\t */\n\tstart(): string {\n\t\tif (this.state === 'recording') {\n\t\t\treturn this.sessionId!\n\t\t}\n\n\t\tif (!this.config.enabled) {\n\t\t\tthrow new Error('Session replay is disabled')\n\t\t}\n\n\t\t// Check sampling\n\t\tif (!this.shouldSample()) {\n\t\t\tthrow new Error('Session not sampled for recording')\n\t\t}\n\n\t\t// Generate session ID\n\t\tthis.sessionId = this.generateSessionId()\n\t\tthis.startTime = Date.now()\n\t\tthis.state = 'recording'\n\n\t\t// Reset storage\n\t\tthis.events = []\n\t\tthis.markers = []\n\t\tthis.rageClicks = []\n\t\tthis.deadClicks = []\n\t\tthis.networkRequests = []\n\t\tthis.consoleLogs = []\n\t\tthis.bytesRecorded = 0\n\n\t\t// Start rrweb recording. rrweb is lazy-loaded (dynamic import) so it stays\n\t\t// out of the eager bundle for consumers that never record; the session is\n\t\t// already \"started\" synchronously here and rrweb attaches once its async\n\t\t// chunk resolves a few ms later.\n\t\tvoid this.startRrwebRecording().catch((error) => {\n\t\t\tthis.errorCallback?.(error instanceof Error ? error : new Error(String(error)))\n\t\t})\n\n\t\t// Setup detectors\n\t\tthis.setupDetectors()\n\n\t\t// Setup network/console capture\n\t\tif (this.config.networkCapture) {\n\t\t\tthis.setupNetworkCapture()\n\t\t}\n\t\tif (this.config.consoleCapture) {\n\t\t\tthis.setupConsoleCapture()\n\t\t}\n\n\t\t// Start upload timer\n\t\tthis.startUploadTimer()\n\n\t\t// Set max duration timeout\n\t\tthis.durationTimer = setTimeout(() => {\n\t\t\tthis.stop()\n\t\t}, this.config.maxDuration)\n\n\t\treturn this.sessionId\n\t}\n\n\t/**\n\t * Pause recording\n\t */\n\tpause(): void {\n\t\tif (this.state !== 'recording') return\n\n\t\tthis.state = 'paused'\n\t\tthis.rrwebRecordingEpoch += 1\n\n\t\tif (this.stopFn) {\n\t\t\tthis.stopFn()\n\t\t\tthis.stopFn = null\n\t\t}\n\t}\n\n\t/**\n\t * Resume recording\n\t */\n\tresume(): void {\n\t\tif (this.state !== 'paused') return\n\n\t\tthis.state = 'recording'\n\t\tvoid this.startRrwebRecording().catch((error) => {\n\t\t\tthis.errorCallback?.(error instanceof Error ? error : new Error(String(error)))\n\t\t})\n\t}\n\n\t/**\n\t * Stop recording and upload final batch\n\t */\n\tasync stop(): Promise<void> {\n\t\tif (this.state === 'stopped' || this.state === 'idle') return\n\n\t\tthis.state = 'stopped'\n\t\tthis.rrwebRecordingEpoch += 1\n\n\t\t// Stop rrweb\n\t\tif (this.stopFn) {\n\t\t\tthis.stopFn()\n\t\t\tthis.stopFn = null\n\t\t}\n\n\t\t// Clear timers\n\t\tif (this.uploadTimer) {\n\t\t\tclearInterval(this.uploadTimer)\n\t\t\tthis.uploadTimer = null\n\t\t}\n\t\tif (this.durationTimer) {\n\t\t\tclearTimeout(this.durationTimer)\n\t\t\tthis.durationTimer = null\n\t\t}\n\n\t\t// Cleanup detectors\n\t\tthis.deadClickDetector?.destroy()\n\t\tthis.rageClickDetector?.reset()\n\t\tthis.scrollThrashingDetector?.reset()\n\n\t\t// Cleanup network interceptor listeners\n\t\tfor (const unsub of this.networkUnsubscribers) {\n\t\t\tunsub()\n\t\t}\n\t\tthis.networkUnsubscribers = []\n\n\t\t// Final upload\n\t\tawait this.upload()\n\t}\n\n\t/**\n\t * Get current status\n\t */\n\tgetStatus(): RecorderStatus {\n\t\treturn {\n\t\t\tstate: this.state,\n\t\t\tsessionId: this.sessionId,\n\t\t\teventCount: this.events.length,\n\t\t\tstartTime: this.startTime,\n\t\t\tduration: this.startTime ? Date.now() - this.startTime : 0,\n\t\t\tbytesRecorded: this.bytesRecorded,\n\t\t}\n\t}\n\n\t// ==========================================\n\t// Event Marking\n\t// ==========================================\n\n\t/**\n\t * Add a custom marker to the session timeline\n\t */\n\taddMarker(type: SessionMarker['type'], payload: Record<string, unknown> = {}): void {\n\t\tif (this.state !== 'recording') return\n\n\t\tthis.markers.push({\n\t\t\ttype,\n\t\t\ttimestamp: Date.now(),\n\t\t\tpayload,\n\t\t})\n\t}\n\n\t/**\n\t * Mark an error in the session\n\t * Used for error correlation feature\n\t */\n\tmarkError(errorId: string, error: Error, metadata: Record<string, unknown> = {}): void {\n\t\tif (!this.config.errorCorrelation) return\n\n\t\tthis.addMarker('error', {\n\t\t\terrorId,\n\t\t\tmessage: sanitizeForLogging(error.message),\n\t\t\tstack: error.stack?.slice(0, STACK_TRACE_MAX_LENGTH),\n\t\t\t...metadata,\n\t\t})\n\t}\n\n\t/**\n\t * Mark a navigation event\n\t */\n\tmarkNavigation(from: string, to: string): void {\n\t\tthis.addMarker('navigation', {\n\t\t\tfrom: sanitizeUrl(from),\n\t\t\tto: sanitizeUrl(to),\n\t\t})\n\t}\n\n\t/**\n\t * Mark a conversion event\n\t */\n\tmarkConversion(name: string, value?: number): void {\n\t\tthis.addMarker('conversion', { name, value })\n\t}\n\n\t// ==========================================\n\t// Callbacks\n\t// ==========================================\n\n\t/**\n\t * Set upload callback for sending data to server\n\t */\n\tonUpload(callback: UploadCallback): void {\n\t\tthis.uploadCallback = callback\n\t}\n\n\t/**\n\t * Set event callback for custom processing\n\t */\n\tonEvent(callback: (event: eventWithTime) => void): void {\n\t\tthis.eventCallback = callback\n\t}\n\n\t/**\n\t * Set error callback\n\t */\n\tonError(callback: (error: Error) => void): void {\n\t\tthis.errorCallback = callback\n\t}\n\n\t// ==========================================\n\t// Private Methods\n\t// ==========================================\n\n\tprivate shouldSample(): boolean {\n\t\tconst { sampling } = this.config\n\t\treturn Math.random() * 100 < sampling.rate\n\t}\n\n\tprivate generateSessionId(): string {\n\t\treturn `sr_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`\n\t}\n\n\tprivate async startRrwebRecording(): Promise<void> {\n\t\tconst epoch = ++this.rrwebRecordingEpoch\n\t\tconst record = await loadRrwebRecord()\n\n\t\t// Recording may have been paused/stopped while rrweb's chunk was loading.\n\t\tif (this.state !== 'recording' || epoch !== this.rrwebRecordingEpoch) return\n\n\t\tconst privacyOptions = getPrivacyOptions(this.config.privacyMode, this.config.maskSelectors)\n\n\t\t// rrweb supports ignoreSelector at runtime (added post-1.1.3) but the\n\t\t// installed @types don't declare it yet. Merge it into typed options.\n\t\t// The options type is instantiated at `eventWithTime` from the lazily-loaded\n\t\t// `record` value (a module-level alias can't carry the type arg).\n\t\tconst options: NonNullable<Parameters<typeof record<eventWithTime>>[0]> & {\n\t\t\tignoreSelector?: string\n\t\t} = {\n\t\t\temit: (event: eventWithTime) => {\n\t\t\t\tthis.handleEvent(event)\n\t\t\t},\n\t\t\t...privacyOptions,\n\t\t\tblockSelector: this.config.blockSelectors.join(', ') || undefined,\n\t\t\tignoreSelector: this.config.ignoreSelectors.join(', ') || undefined,\n\t\t\tsampling: {\n\t\t\t\tmousemove: true,\n\t\t\t\tmouseInteraction: true,\n\t\t\t\tscroll: 150,\n\t\t\t\tmedia: 800,\n\t\t\t\tinput: 'last',\n\t\t\t},\n\t\t\trecordCanvas: false,\n\t\t\tcollectFonts: false,\n\t\t\tinlineStylesheet: true,\n\t\t\tplugins: [],\n\t\t}\n\t\tconst stopFn = record(options)\n\n\t\tif (!stopFn) {\n\t\t\tthrow new Error('Failed to start rrweb recording')\n\t\t}\n\n\t\tif (this.state !== 'recording' || epoch !== this.rrwebRecordingEpoch) {\n\t\t\tstopFn()\n\t\t\treturn\n\t\t}\n\n\t\tthis.stopFn = stopFn\n\t}\n\n\tprivate handleEvent(event: eventWithTime): void {\n\t\tthis.events.push(event)\n\t\tthis.bytesRecorded += JSON.stringify(event).length\n\n\t\tif (this.eventCallback) {\n\t\t\tthis.eventCallback(event)\n\t\t}\n\n\t\t// Check batch size for early upload\n\t\tif (this.events.length >= this.config.batchSize) {\n\t\t\tvoid this.upload()\n\t\t}\n\t}\n\n\tprivate setupDetectors(): void {\n\t\t// Rage click detector\n\t\tif (this.config.rageClickDetection) {\n\t\t\tthis.rageClickDetector = new RageClickDetector()\n\t\t\tthis.rageClickDetector.onRageClick((rageClick) => {\n\t\t\t\tthis.rageClicks.push(rageClick)\n\t\t\t\tthis.addMarker('rage-click', { ...rageClick })\n\t\t\t})\n\n\t\t\tdocument.addEventListener('click', (e) => {\n\t\t\t\tthis.rageClickDetector?.recordClick(e)\n\t\t\t})\n\t\t}\n\n\t\t// Dead click detector\n\t\tif (this.config.deadClickDetection) {\n\t\t\tthis.deadClickDetector = new DeadClickDetector()\n\t\t\tthis.deadClickDetector.onDeadClick((deadClick) => {\n\t\t\t\tthis.deadClicks.push(deadClick)\n\t\t\t\tthis.addMarker('dead-click', { ...deadClick })\n\t\t\t})\n\n\t\t\tdocument.addEventListener('click', (e) => {\n\t\t\t\tthis.deadClickDetector?.recordClick(e)\n\t\t\t})\n\t\t}\n\n\t\t// Scroll thrashing detector\n\t\tthis.scrollThrashingDetector = new ScrollThrashingDetector()\n\t\tthis.scrollThrashingDetector.onThrashing((event) => {\n\t\t\tthis.addMarker('custom', { type: 'scroll-thrashing', ...event })\n\t\t})\n\n\t\twindow.addEventListener('scroll', () => {\n\t\t\tthis.scrollThrashingDetector?.recordScroll(window.scrollY)\n\t\t})\n\t}\n\n\t/**\n\t * Capture network requests via shared interceptor.\n\t *\n\t * Uses the centralized network interceptor instead of independently\n\t * monkey-patching fetch/XHR. Records request metadata for session replay.\n\t */\n\tprivate setupNetworkCapture(): void {\n\t\tthis.networkUnsubscribers.push(\n\t\t\tonFetchEnd((event) => {\n\t\t\t\tthis.networkRequests.push({\n\t\t\t\t\ttimestamp: event.startTime,\n\t\t\t\t\tmethod: event.method,\n\t\t\t\t\turl: sanitizeUrl(event.url),\n\t\t\t\t\tstatus: event.status,\n\t\t\t\t\tduration: event.duration,\n\t\t\t\t})\n\t\t\t}),\n\t\t)\n\n\t\tthis.networkUnsubscribers.push(\n\t\t\tonXHREnd((event) => {\n\t\t\t\tthis.networkRequests.push({\n\t\t\t\t\ttimestamp: event.startTime,\n\t\t\t\t\tmethod: event.method,\n\t\t\t\t\turl: sanitizeUrl(event.url),\n\t\t\t\t\tstatus: event.status,\n\t\t\t\t\tduration: event.duration,\n\t\t\t\t})\n\t\t\t}),\n\t\t)\n\t}\n\n\tprivate setupConsoleCapture(): void {\n\t\tconst levels = ['log', 'info', 'warn', 'error'] as const\n\t\tconst originalConsole: Partial<Record<(typeof levels)[number], (...args: unknown[]) => void>> =\n\t\t\t{}\n\n\t\tlevels.forEach((level) => {\n\t\t\t// biome-ignore lint/suspicious/noConsole: session-replay recorder patches console.* to capture user logs; originals preserved.\n\t\t\toriginalConsole[level] = console[level]\n\n\t\t\tconsole[level] = (...args: unknown[]) => {\n\t\t\t\tconst message = args.map((arg) => String(arg)).join(' ')\n\n\t\t\t\tthis.consoleLogs.push({\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\tlevel,\n\t\t\t\t\tmessage: sanitizeForLogging(message).slice(0, LOG_MESSAGE_MAX_LENGTH),\n\t\t\t\t\tstack:\n\t\t\t\t\t\tlevel === 'error' ? new Error().stack?.slice(0, STACK_TRACE_MAX_LENGTH) : undefined,\n\t\t\t\t})\n\n\t\t\t\toriginalConsole[level]?.apply(console, args)\n\t\t\t}\n\t\t})\n\t}\n\n\tprivate startUploadTimer(): void {\n\t\tthis.uploadTimer = setInterval(() => {\n\t\t\tvoid this.upload()\n\t\t}, this.config.uploadInterval)\n\t}\n\n\tprivate async upload(): Promise<void> {\n\t\tif (this.events.length === 0 || !this.uploadCallback) return\n\n\t\tconst data: SessionData = {\n\t\t\tmetadata: this.getMetadata(),\n\t\t\tevents: this.events,\n\t\t\tmarkers: this.markers,\n\t\t\trageClicks: this.rageClicks,\n\t\t\tdeadClicks: this.deadClicks,\n\t\t\tnetworkRequests: this.networkRequests,\n\t\t\tconsoleLogs: this.consoleLogs,\n\t\t}\n\n\t\t// Clear uploaded data\n\t\tthis.events = []\n\t\tthis.markers = []\n\t\tthis.rageClicks = []\n\t\tthis.deadClicks = []\n\t\tthis.networkRequests = []\n\t\tthis.consoleLogs = []\n\n\t\ttry {\n\t\t\tawait this.uploadCallback(data)\n\t\t} catch (error) {\n\t\t\t// Restore events on failure\n\t\t\tthis.events = [...data.events, ...this.events]\n\n\t\t\tif (this.errorCallback) {\n\t\t\t\tthis.errorCallback(error instanceof Error ? error : new Error(String(error)))\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate getMetadata(): SessionMetadata {\n\t\treturn {\n\t\t\tsessionId: this.sessionId!,\n\t\t\tstartTime: this.startTime!,\n\t\t\turl: sanitizeUrl(window.location.href),\n\t\t\tuserAgent: navigator.userAgent,\n\t\t\tscreenWidth: window.screen.width,\n\t\t\tscreenHeight: window.screen.height,\n\t\t\tdevicePixelRatio: window.devicePixelRatio,\n\t\t\ttimezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n\t\t\tlanguage: navigator.language,\n\t\t}\n\t}\n}\n\n// ==========================================\n// Singleton Instance\n// ==========================================\n\nlet recorderInstance: SessionRecorder | null = null\n\n/**\n * Get or create the session recorder instance\n */\nexport function getRecorder(config?: Partial<SessionReplayConfig>): SessionRecorder {\n\tif (!recorderInstance) {\n\t\trecorderInstance = new SessionRecorder(config)\n\t}\n\treturn recorderInstance\n}\n\n/**\n * Reset the singleton instance\n */\nexport function resetRecorder(): void {\n\tif (recorderInstance) {\n\t\tvoid recorderInstance.stop()\n\t\trecorderInstance = null\n\t}\n}\n","/**\n * Session Replay Types\n *\n * Type definitions for the session replay system.\n * Built on rrweb with SOTA enhancements.\n */\n\nimport type { eventWithTime } from '@rrweb/types'\nimport {\n\tSESSION_REPLAY_MAX_DURATION_MS,\n\tSESSION_REPLAY_UPLOAD_INTERVAL_MS,\n} from '../../../constants'\n\n// ==========================================\n// Configuration Types\n// ==========================================\n\n/**\n * Privacy modes for session replay\n *\n * - `strict`: Mask all text, inputs, and images\n * - `balanced`: Mask inputs and sensitive fields only\n * - `minimal`: Only mask explicitly marked fields\n */\nexport type PrivacyMode = 'strict' | 'balanced' | 'minimal'\n\n/**\n * Sampling strategy for controlling recording volume\n */\nexport interface SamplingStrategy {\n\t/** Percentage of sessions to record (0-100) */\n\trate: number\n\t/** Always record sessions with errors */\n\talwaysRecordErrors: boolean\n\t/** Always record sessions matching these user segments */\n\tsegments?: string[]\n}\n\n/**\n * Session replay configuration\n */\nexport interface SessionReplayConfig {\n\t/** Enable/disable session replay */\n\tenabled: boolean\n\t/** Sampling configuration */\n\tsampling: SamplingStrategy\n\t/** Maximum session duration in milliseconds (default: 60 min) */\n\tmaxDuration: number\n\t/** Privacy mode */\n\tprivacyMode: PrivacyMode\n\t/** Custom CSS selectors to always mask */\n\tmaskSelectors: string[]\n\t/** Custom CSS selectors to always block (remove from recording) */\n\tblockSelectors: string[]\n\t/** Custom CSS selectors to ignore (don't record interactions) */\n\tignoreSelectors: string[]\n\n\t// SOTA Features\n\t/** Correlate with error tracking */\n\terrorCorrelation: boolean\n\t/** Enable rage click detection */\n\trageClickDetection: boolean\n\t/** Enable dead click detection */\n\tdeadClickDetection: boolean\n\t/** Enable AI session summary */\n\taiSummary: boolean\n\t/** Enable click heatmaps */\n\theatmaps: boolean\n\t/** Enable network request capture */\n\tnetworkCapture: boolean\n\t/** Enable console log capture */\n\tconsoleCapture: boolean\n\n\t// Performance\n\t/** Compress events before sending */\n\tcompress: boolean\n\t/** Batch size for uploading events */\n\tbatchSize: number\n\t/** Upload interval in milliseconds */\n\tuploadInterval: number\n}\n\n/**\n * Default configuration\n */\nexport const DEFAULT_CONFIG: SessionReplayConfig = {\n\tenabled: true,\n\tsampling: {\n\t\trate: 100,\n\t\talwaysRecordErrors: true,\n\t},\n\tmaxDuration: SESSION_REPLAY_MAX_DURATION_MS, // 60 minutes\n\tprivacyMode: 'balanced',\n\tmaskSelectors: [],\n\tblockSelectors: [],\n\tignoreSelectors: [],\n\terrorCorrelation: true,\n\trageClickDetection: true,\n\tdeadClickDetection: true,\n\taiSummary: false, // Opt-in for AI features\n\theatmaps: true,\n\tnetworkCapture: true,\n\tconsoleCapture: true,\n\tcompress: true,\n\tbatchSize: 50,\n\tuploadInterval: SESSION_REPLAY_UPLOAD_INTERVAL_MS,\n}\n\n// ==========================================\n// Event Types\n// ==========================================\n\n/**\n * Custom event marker types\n */\nexport type MarkerType =\n\t| 'error'\n\t| 'rage-click'\n\t| 'dead-click'\n\t| 'navigation'\n\t| 'user-feedback'\n\t| 'conversion'\n\t| 'custom'\n\n/**\n * Custom event marker for session timeline\n */\nexport interface SessionMarker {\n\ttype: MarkerType\n\ttimestamp: number\n\tpayload: Record<string, unknown>\n}\n\n/**\n * Rage click detection result\n */\nexport interface RageClick {\n\ttimestamp: number\n\telement: string\n\tselector: string\n\tclickCount: number\n\tduration: number\n}\n\n/**\n * Dead click detection result (click with no effect)\n */\nexport interface DeadClick {\n\ttimestamp: number\n\telement: string\n\tselector: string\n\texpectedAction: string\n}\n\n/**\n * Network request capture\n */\nexport interface NetworkRequest {\n\ttimestamp: number\n\tmethod: string\n\turl: string\n\tstatus: number\n\tduration: number\n\trequestSize?: number\n\tresponseSize?: number\n}\n\n/**\n * Console log capture\n */\nexport interface ConsoleLog {\n\ttimestamp: number\n\tlevel: 'log' | 'info' | 'warn' | 'error'\n\tmessage: string\n\tstack?: string\n}\n\n// ==========================================\n// Session Types\n// ==========================================\n\n/**\n * Session metadata\n */\nexport interface SessionMetadata {\n\tsessionId: string\n\tuserId?: string\n\tstartTime: number\n\tendTime?: number\n\turl: string\n\tuserAgent: string\n\tscreenWidth: number\n\tscreenHeight: number\n\tdevicePixelRatio: number\n\ttimezone: string\n\tlanguage: string\n}\n\n/**\n * Session data for upload\n */\nexport interface SessionData {\n\tmetadata: SessionMetadata\n\tevents: eventWithTime[]\n\tmarkers: SessionMarker[]\n\trageClicks: RageClick[]\n\tdeadClicks: DeadClick[]\n\tnetworkRequests: NetworkRequest[]\n\tconsoleLogs: ConsoleLog[]\n}\n\n/**\n * Session summary generated by AI\n */\nexport interface SessionSummary {\n\tsessionId: string\n\tsummary: string\n\tkeyEvents: string[]\n\tuserIntent: string\n\tissues: string[]\n\tsentiment: 'positive' | 'neutral' | 'frustrated'\n\tgeneratedAt: number\n}\n\n// ==========================================\n// Callback Types\n// ==========================================\n\n/**\n * Event callback for custom processing\n */\nexport type EventCallback = (event: eventWithTime) => void\n\n/**\n * Upload callback for custom transport\n */\nexport type UploadCallback = (data: SessionData) => Promise<void>\n\n/**\n * Error callback\n */\nexport type ErrorCallback = (error: Error) => void\n\n// ==========================================\n// Recorder State\n// ==========================================\n\nexport type RecorderState = 'idle' | 'recording' | 'paused' | 'stopped'\n\n/**\n * Recorder status\n */\nexport interface RecorderStatus {\n\tstate: RecorderState\n\tsessionId: string | null\n\teventCount: number\n\tstartTime: number | null\n\tduration: number\n\tbytesRecorded: number\n}\n","let e=-1;const t=t=>{addEventListener(\"pageshow\",(n=>{n.persisted&&(e=n.timeStamp,t(n))}),!0)},n=(e,t,n,i)=>{let s,o;return r=>{t.value>=0&&(r||i)&&(o=t.value-(s??0),(o||void 0===s)&&(s=t.value,t.delta=o,t.rating=((e,t)=>e>t[1]?\"poor\":e>t[0]?\"needs-improvement\":\"good\")(t.value,n),e(t)))}},i=e=>{requestAnimationFrame((()=>requestAnimationFrame((()=>e()))))},s=()=>{const e=performance.getEntriesByType(\"navigation\")[0];if(e&&e.responseStart>0&&e.responseStart<performance.now())return e},o=()=>{const e=s();return e?.activationStart??0},r=(t,n=-1)=>{const i=s();let r=\"navigate\";e>=0?r=\"back-forward-cache\":i&&(document.prerendering||o()>0?r=\"prerender\":document.wasDiscarded?r=\"restore\":i.type&&(r=i.type.replace(/_/g,\"-\")));return{name:t,value:n,rating:\"good\",delta:0,entries:[],id:`v5-${Date.now()}-${Math.floor(8999999999999*Math.random())+1e12}`,navigationType:r}},c=new WeakMap;function a(e,t){return c.get(e)||c.set(e,new t),c.get(e)}class d{t;i=0;o=[];h(e){if(e.hadRecentInput)return;const t=this.o[0],n=this.o.at(-1);this.i&&t&&n&&e.startTime-n.startTime<1e3&&e.startTime-t.startTime<5e3?(this.i+=e.value,this.o.push(e)):(this.i=e.value,this.o=[e]),this.t?.(e)}}const h=(e,t,n={})=>{try{if(PerformanceObserver.supportedEntryTypes.includes(e)){const i=new PerformanceObserver((e=>{Promise.resolve().then((()=>{t(e.getEntries())}))}));return i.observe({type:e,buffered:!0,...n}),i}}catch{}},f=e=>{let t=!1;return()=>{t||(e(),t=!0)}};let u=-1;const l=new Set,m=()=>\"hidden\"!==document.visibilityState||document.prerendering?1/0:0,p=e=>{if(\"hidden\"===document.visibilityState){if(\"visibilitychange\"===e.type)for(const e of l)e();isFinite(u)||(u=\"visibilitychange\"===e.type?e.timeStamp:0,removeEventListener(\"prerenderingchange\",p,!0))}},v=()=>{if(u<0){const e=o(),n=document.prerendering?void 0:globalThis.performance.getEntriesByType(\"visibility-state\").filter((t=>\"hidden\"===t.name&&t.startTime>e))[0]?.startTime;u=n??m(),addEventListener(\"visibilitychange\",p,!0),addEventListener(\"prerenderingchange\",p,!0),t((()=>{setTimeout((()=>{u=m()}))}))}return{get firstHiddenTime(){return u},onHidden(e){l.add(e)}}},g=e=>{document.prerendering?addEventListener(\"prerenderingchange\",(()=>e()),!0):e()},y=[1800,3e3],E=(e,s={})=>{g((()=>{const c=v();let a,d=r(\"FCP\");const f=h(\"paint\",(e=>{for(const t of e)\"first-contentful-paint\"===t.name&&(f.disconnect(),t.startTime<c.firstHiddenTime&&(d.value=Math.max(t.startTime-o(),0),d.entries.push(t),a(!0)))}));f&&(a=n(e,d,y,s.reportAllChanges),t((t=>{d=r(\"FCP\"),a=n(e,d,y,s.reportAllChanges),i((()=>{d.value=performance.now()-t.timeStamp,a(!0)}))})))}))},b=[.1,.25],L=(e,s={})=>{const o=v();E(f((()=>{let c,f=r(\"CLS\",0);const u=a(s,d),l=e=>{for(const t of e)u.h(t);u.i>f.value&&(f.value=u.i,f.entries=u.o,c())},m=h(\"layout-shift\",l);m&&(c=n(e,f,b,s.reportAllChanges),o.onHidden((()=>{l(m.takeRecords()),c(!0)})),t((()=>{u.i=0,f=r(\"CLS\",0),c=n(e,f,b,s.reportAllChanges),i((()=>c()))})),setTimeout(c))})))};let P=0,T=1/0,_=0;const M=e=>{for(const t of e)t.interactionId&&(T=Math.min(T,t.interactionId),_=Math.max(_,t.interactionId),P=_?(_-T)/7+1:0)};let w;const C=()=>w?P:performance.interactionCount??0,I=()=>{\"interactionCount\"in performance||w||(w=h(\"event\",M,{type:\"event\",buffered:!0,durationThreshold:0}))};let F=0;class k{u=[];l=new Map;m;p;v(){F=C(),this.u.length=0,this.l.clear()}L(){const e=Math.min(this.u.length-1,Math.floor((C()-F)/50));return this.u[e]}h(e){if(this.m?.(e),!e.interactionId&&\"first-input\"!==e.entryType)return;const t=this.u.at(-1);let n=this.l.get(e.interactionId);if(n||this.u.length<10||e.duration>t.P){if(n?e.duration>n.P?(n.entries=[e],n.P=e.duration):e.duration===n.P&&e.startTime===n.entries[0].startTime&&n.entries.push(e):(n={id:e.interactionId,entries:[e],P:e.duration},this.l.set(n.id,n),this.u.push(n)),this.u.sort(((e,t)=>t.P-e.P)),this.u.length>10){const e=this.u.splice(10);for(const t of e)this.l.delete(t.id)}this.p?.(n)}}}const A=e=>{const t=globalThis.requestIdleCallback||setTimeout;\"hidden\"===document.visibilityState?e():(e=f(e),addEventListener(\"visibilitychange\",e,{once:!0,capture:!0}),t((()=>{e(),removeEventListener(\"visibilitychange\",e,{capture:!0})})))},B=[200,500],S=(e,i={})=>{if(!globalThis.PerformanceEventTiming||!(\"interactionId\"in PerformanceEventTiming.prototype))return;const s=v();g((()=>{I();let o,c=r(\"INP\");const d=a(i,k),f=e=>{A((()=>{for(const t of e)d.h(t);const t=d.L();t&&t.P!==c.value&&(c.value=t.P,c.entries=t.entries,o())}))},u=h(\"event\",f,{durationThreshold:i.durationThreshold??40});o=n(e,c,B,i.reportAllChanges),u&&(u.observe({type:\"first-input\",buffered:!0}),s.onHidden((()=>{f(u.takeRecords()),o(!0)})),t((()=>{d.v(),c=r(\"INP\"),o=n(e,c,B,i.reportAllChanges)})))}))};class N{m;h(e){this.m?.(e)}}const q=[2500,4e3],x=(e,s={})=>{g((()=>{const c=v();let d,u=r(\"LCP\");const l=a(s,N),m=e=>{s.reportAllChanges||(e=e.slice(-1));for(const t of e)l.h(t),t.startTime<c.firstHiddenTime&&(u.value=Math.max(t.startTime-o(),0),u.entries=[t],d())},p=h(\"largest-contentful-paint\",m);if(p){d=n(e,u,q,s.reportAllChanges);const o=f((()=>{m(p.takeRecords()),p.disconnect(),d(!0)})),c=e=>{e.isTrusted&&(A(o),removeEventListener(e.type,c,{capture:!0}))};for(const e of[\"keydown\",\"click\",\"visibilitychange\"])addEventListener(e,c,{capture:!0});t((t=>{u=r(\"LCP\"),d=n(e,u,q,s.reportAllChanges),i((()=>{u.value=performance.now()-t.timeStamp,d(!0)}))}))}}))},H=[800,1800],O=e=>{document.prerendering?g((()=>O(e))):\"complete\"!==document.readyState?addEventListener(\"load\",(()=>O(e)),!0):setTimeout(e)},$=(e,i={})=>{let c=r(\"TTFB\"),a=n(e,c,H,i.reportAllChanges);O((()=>{const d=s();d&&(c.value=Math.max(d.responseStart-o(),0),c.entries=[d],a(!0),t((()=>{c=r(\"TTFB\",0),a=n(e,c,H,i.reportAllChanges),a(!0)})))}))};export{b as CLSThresholds,y as FCPThresholds,B as INPThresholds,q as LCPThresholds,H as TTFBThresholds,L as onCLS,E as onFCP,S as onINP,x as onLCP,$ as onTTFB};\n","/**\n * Web Vitals Monitoring\n *\n * State-of-the-art Core Web Vitals measurement with automatic reporting\n * and analytics integration.\n *\n * ## Metrics Captured\n *\n * **Core Web Vitals (CWV)**:\n * - **LCP** (Largest Contentful Paint): Loading performance\n * - **INP** (Interaction to Next Paint): Interactivity (replaced FID)\n * - **CLS** (Cumulative Layout Shift): Visual stability\n *\n * **Additional Metrics**:\n * - **TTFB** (Time to First Byte): Server response time\n * - **FCP** (First Contentful Paint): First render time\n *\n * ## Usage\n *\n * @example\n * ```typescript\n * import { initWebVitals, getWebVitalsReport } from '@sylphx/platform-sdk'\n *\n * // Initialize with automatic reporting\n * initWebVitals({\n *   reportUrl: '/api/v1/monitoring/vitals',\n *   onReport: (metric) => console.log(metric),\n *   debug: process.env.NODE_ENV === 'development',\n * })\n *\n * // Get current metrics\n * const report = getWebVitalsReport()\n * ```\n *\n * @see https://web.dev/articles/vitals\n */\n\nimport {\n\ttype CLSMetric,\n\ttype FCPMetric,\n\ttype INPMetric,\n\ttype LCPMetric,\n\ttype Metric,\n\tonCLS,\n\tonFCP,\n\tonINP,\n\tonLCP,\n\tonTTFB,\n\ttype TTFBMetric,\n} from 'web-vitals'\nimport {\n\tWEB_VITALS_FCP_GOOD_MS,\n\tWEB_VITALS_FCP_POOR_MS,\n\tWEB_VITALS_INP_GOOD_MS,\n\tWEB_VITALS_INP_POOR_MS,\n\tWEB_VITALS_LCP_GOOD_MS,\n\tWEB_VITALS_LCP_POOR_MS,\n\tWEB_VITALS_TTFB_GOOD_MS,\n\tWEB_VITALS_TTFB_POOR_MS,\n} from '../../../constants'\n\n// ============================================\n// Types\n// ============================================\n\n/** Core Web Vital metric names */\nexport type CoreWebVitalName = 'CLS' | 'INP' | 'LCP'\n\n/** All tracked metric names */\nexport type WebVitalName = CoreWebVitalName | 'FCP' | 'TTFB'\n\n/** Metric rating thresholds */\nexport type MetricRating = 'good' | 'needs-improvement' | 'poor'\n\n/** Enhanced metric with additional context */\nexport interface WebVitalMetric {\n\t/** Metric name (e.g., 'LCP', 'CLS', 'INP') */\n\tname: WebVitalName\n\t/** Metric value */\n\tvalue: number\n\t/** Metric rating based on thresholds */\n\trating: MetricRating\n\t/** Delta from previous value */\n\tdelta: number\n\t/** Unique metric ID */\n\tid: string\n\t/** Navigation type */\n\tnavigationType:\n\t\t| 'navigate'\n\t\t| 'reload'\n\t\t| 'back-forward'\n\t\t| 'back-forward-cache'\n\t\t| 'prerender'\n\t\t| 'restore'\n\t/** Attribution data for debugging */\n\tattribution?: WebVitalAttribution\n\t/** Timestamp when metric was captured */\n\ttimestamp: number\n}\n\n/** Attribution data for debugging metrics */\nexport interface WebVitalAttribution {\n\t/** Element contributing to the metric (for LCP, CLS) */\n\telement?: string\n\t/** Target element for INP */\n\teventTarget?: string\n\t/** Event type for INP */\n\teventType?: string\n\t/** Event time for INP */\n\teventTime?: number\n\t/** Time to first byte breakdown (for TTFB) */\n\twaitingDuration?: number\n\tcacheDuration?: number\n\tdnsDuration?: number\n\tconnectionDuration?: number\n\trequestDuration?: number\n\t/** LCP resource info */\n\tlcpResourceEntry?: string\n\t/** Largest shift sources for CLS */\n\tlargestShiftSources?: string[]\n}\n\n/** Report containing all captured metrics */\nexport interface WebVitalsReport {\n\t/** Core Web Vitals */\n\tlcp?: WebVitalMetric\n\tinp?: WebVitalMetric\n\tcls?: WebVitalMetric\n\t/** Additional metrics */\n\tfcp?: WebVitalMetric\n\tttfb?: WebVitalMetric\n\t/** Overall score (0-100) */\n\tscore: number\n\t/** Page URL */\n\turl: string\n\t/** User agent */\n\tuserAgent: string\n\t/** Report timestamp */\n\ttimestamp: number\n}\n\n/** Web Vitals configuration */\nexport interface WebVitalsConfig {\n\t/** URL to report metrics to (POST request) */\n\treportUrl?: string\n\t/** Callback for each metric */\n\tonReport?: (metric: WebVitalMetric) => void\n\t/** Report all metrics at once (on page unload) */\n\tonReportAll?: (report: WebVitalsReport) => void\n\t/** Enable debug logging */\n\tdebug?: boolean\n\t/** Custom headers for reporting */\n\theaders?: Record<string, string>\n\t/** Report immediately or batch (default: immediate) */\n\treportingMode?: 'immediate' | 'batch'\n\t/** Attribution level: 'basic' or 'detailed' */\n\tattribution?: 'basic' | 'detailed'\n\t/** Sampling rate (0-1, default: 1.0) */\n\tsamplingRate?: number\n}\n\n// ============================================\n// Thresholds\n// ============================================\n\n/**\n * Core Web Vitals thresholds (from web.dev)\n * @see https://web.dev/articles/vitals\n */\nexport const WEB_VITALS_THRESHOLDS = {\n\t// Core Web Vitals\n\tLCP: { good: WEB_VITALS_LCP_GOOD_MS, poor: WEB_VITALS_LCP_POOR_MS }, // ms\n\tINP: { good: WEB_VITALS_INP_GOOD_MS, poor: WEB_VITALS_INP_POOR_MS }, // ms\n\tCLS: { good: 0.1, poor: 0.25 }, // score (not time-based)\n\n\t// Additional metrics\n\tFCP: { good: WEB_VITALS_FCP_GOOD_MS, poor: WEB_VITALS_FCP_POOR_MS }, // ms\n\tTTFB: { good: WEB_VITALS_TTFB_GOOD_MS, poor: WEB_VITALS_TTFB_POOR_MS }, // ms\n} as const\n\n/** Default configuration */\nexport const DEFAULT_WEB_VITALS_CONFIG: Required<WebVitalsConfig> = {\n\treportUrl: '',\n\tonReport: () => {},\n\tonReportAll: () => {},\n\tdebug: false,\n\theaders: {},\n\treportingMode: 'immediate',\n\tattribution: 'basic',\n\tsamplingRate: 1.0,\n}\n\n// ============================================\n// State\n// ============================================\n\nlet config: Required<WebVitalsConfig> = { ...DEFAULT_WEB_VITALS_CONFIG }\nlet initialized = false\nlet metrics: Partial<Record<WebVitalName, WebVitalMetric>> = {}\n\n// ============================================\n// Utilities\n// ============================================\n\n/**\n * Get metric rating based on thresholds\n */\nfunction getRating(name: WebVitalName, value: number): MetricRating {\n\tconst threshold = WEB_VITALS_THRESHOLDS[name]\n\tif (value <= threshold.good) return 'good'\n\tif (value <= threshold.poor) return 'needs-improvement'\n\treturn 'poor'\n}\n\n/**\n * Calculate overall score (0-100)\n */\nfunction calculateScore(report: Partial<Record<WebVitalName, WebVitalMetric>>): number {\n\tconst weights = {\n\t\tLCP: 25,\n\t\tINP: 30,\n\t\tCLS: 25,\n\t\tFCP: 10,\n\t\tTTFB: 10,\n\t}\n\n\tlet totalWeight = 0\n\tlet weightedScore = 0\n\n\tfor (const [name, weight] of Object.entries(weights)) {\n\t\tconst metric = report[name as WebVitalName]\n\t\tif (metric) {\n\t\t\ttotalWeight += weight\n\t\t\tconst metricScore =\n\t\t\t\tmetric.rating === 'good' ? 100 : metric.rating === 'needs-improvement' ? 50 : 0\n\t\t\tweightedScore += metricScore * weight\n\t\t}\n\t}\n\n\treturn totalWeight > 0 ? Math.round(weightedScore / totalWeight) : 0\n}\n\n/**\n * Extract attribution data from metric\n */\nfunction extractAttribution(metric: Metric): WebVitalAttribution | undefined {\n\tif (config.attribution === 'basic') return undefined\n\n\tconst attribution: WebVitalAttribution = {}\n\n\t// Type-safe attribution extraction\n\tconst entries = metric.entries\n\tif (entries.length > 0) {\n\t\tconst entry = entries[0]\n\n\t\t// LCP attribution\n\t\tif ('element' in entry && entry.element instanceof Element) {\n\t\t\tattribution.element = entry.element.tagName.toLowerCase()\n\t\t\tif (entry.element.id) attribution.element += `#${entry.element.id}`\n\t\t\tif (entry.element.className && typeof entry.element.className === 'string') {\n\t\t\t\tattribution.element += `.${entry.element.className.split(' ')[0]}`\n\t\t\t}\n\t\t}\n\n\t\t// INP attribution\n\t\tif ('target' in entry && entry.target instanceof Element) {\n\t\t\tattribution.eventTarget = entry.target.tagName?.toLowerCase()\n\t\t}\n\t\tif ('name' in entry && typeof entry.name === 'string') {\n\t\t\tattribution.eventType = entry.name\n\t\t}\n\n\t\t// TTFB attribution (from navigation timing)\n\t\tif ('serverTiming' in entry) {\n\t\t\t// Navigation timing entry has detailed breakdown\n\t\t\tconst navEntry = entry as PerformanceNavigationTiming\n\t\t\tattribution.dnsDuration = navEntry.domainLookupEnd - navEntry.domainLookupStart\n\t\t\tattribution.connectionDuration = navEntry.connectEnd - navEntry.connectStart\n\t\t\tattribution.requestDuration = navEntry.responseStart - navEntry.requestStart\n\t\t\tattribution.waitingDuration = navEntry.responseEnd - navEntry.responseStart\n\t\t}\n\t}\n\n\treturn Object.keys(attribution).length > 0 ? attribution : undefined\n}\n\n/**\n * Convert web-vitals metric to our enhanced type\n */\nfunction toWebVitalMetric(metric: Metric): WebVitalMetric {\n\treturn {\n\t\tname: metric.name as WebVitalName,\n\t\tvalue: metric.value,\n\t\trating: getRating(metric.name as WebVitalName, metric.value),\n\t\tdelta: metric.delta,\n\t\tid: metric.id,\n\t\tnavigationType: metric.navigationType as WebVitalMetric['navigationType'],\n\t\tattribution: extractAttribution(metric),\n\t\ttimestamp: Date.now(),\n\t}\n}\n\n/**\n * Report a metric\n */\nasync function reportMetric(metric: WebVitalMetric): Promise<void> {\n\t// Store metric\n\tmetrics[metric.name] = metric\n\n\t// Debug logging\n\tif (config.debug) {\n\t}\n\n\t// Call callback\n\tconfig.onReport(metric)\n\n\t// Send to server (immediate mode)\n\tif (config.reportUrl && config.reportingMode === 'immediate') {\n\t\ttry {\n\t\t\t// Use sendBeacon for reliability\n\t\t\tconst data = JSON.stringify(metric)\n\t\t\tif (navigator.sendBeacon) {\n\t\t\t\tconst blob = new Blob([data], { type: 'application/json' })\n\t\t\t\tnavigator.sendBeacon(config.reportUrl, blob)\n\t\t\t} else {\n\t\t\t\tawait fetch(config.reportUrl, {\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t\t\t...config.headers,\n\t\t\t\t\t},\n\t\t\t\t\tbody: data,\n\t\t\t\t\tkeepalive: true,\n\t\t\t\t})\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (config.debug) {\n\t\t\t\tconsole.error('[Web Vitals] Failed to report metric:', error)\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Report all metrics (batch mode, on page unload)\n */\nasync function reportAllMetrics(): Promise<void> {\n\tconst report = getWebVitalsReport()\n\n\t// Call callback\n\tconfig.onReportAll(report)\n\n\t// Send to server\n\tif (config.reportUrl && config.reportingMode === 'batch') {\n\t\ttry {\n\t\t\tconst data = JSON.stringify(report)\n\t\t\tif (navigator.sendBeacon) {\n\t\t\t\tconst blob = new Blob([data], { type: 'application/json' })\n\t\t\t\tnavigator.sendBeacon(config.reportUrl, blob)\n\t\t\t} else {\n\t\t\t\tawait fetch(config.reportUrl, {\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t\t\t...config.headers,\n\t\t\t\t\t},\n\t\t\t\t\tbody: data,\n\t\t\t\t\tkeepalive: true,\n\t\t\t\t})\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (config.debug) {\n\t\t\t\tconsole.error('[Web Vitals] Failed to report all metrics:', error)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// ============================================\n// Public API\n// ============================================\n\n/**\n * Initialize Web Vitals monitoring\n *\n * @param userConfig - Configuration options\n *\n * @example\n * ```typescript\n * initWebVitals({\n *   reportUrl: '/api/v1/monitoring/vitals',\n *   debug: process.env.NODE_ENV === 'development',\n *   attribution: 'detailed',\n *   onReport: (metric) => {\n *     console.log(`${metric.name}: ${metric.value}`)\n *   },\n * })\n * ```\n */\nexport function initWebVitals(userConfig: WebVitalsConfig = {}): void {\n\tif (typeof window === 'undefined') return\n\tif (initialized) return\n\n\t// Apply sampling\n\tconst samplingRate = userConfig.samplingRate ?? DEFAULT_WEB_VITALS_CONFIG.samplingRate\n\tif (Math.random() > samplingRate) {\n\t\tif (userConfig.debug) {\n\t\t}\n\t\treturn\n\t}\n\n\tconfig = { ...DEFAULT_WEB_VITALS_CONFIG, ...userConfig }\n\tinitialized = true\n\tmetrics = {}\n\n\t// Report options\n\tconst reportOpts = {\n\t\treportAllChanges: false,\n\t}\n\n\t// Register metric handlers\n\tonCLS((metric: CLSMetric) => reportMetric(toWebVitalMetric(metric)), reportOpts)\n\tonINP((metric: INPMetric) => reportMetric(toWebVitalMetric(metric)), reportOpts)\n\tonLCP((metric: LCPMetric) => reportMetric(toWebVitalMetric(metric)), reportOpts)\n\tonFCP((metric: FCPMetric) => reportMetric(toWebVitalMetric(metric)), reportOpts)\n\tonTTFB((metric: TTFBMetric) => reportMetric(toWebVitalMetric(metric)), reportOpts)\n\n\t// Report all on page unload (for batch mode)\n\tif (config.reportingMode === 'batch') {\n\t\twindow.addEventListener('visibilitychange', () => {\n\t\t\tif (document.visibilityState === 'hidden') {\n\t\t\t\treportAllMetrics()\n\t\t\t}\n\t\t})\n\t}\n\n\tif (config.debug) {\n\t}\n}\n\n/**\n * Get current Web Vitals report\n *\n * @returns Current metrics report\n *\n * @example\n * ```typescript\n * const report = getWebVitalsReport()\n * console.log(`Overall score: ${report.score}`)\n * if (report.lcp) console.log(`LCP: ${report.lcp.value}ms`)\n * ```\n */\nexport function getWebVitalsReport(): WebVitalsReport {\n\treturn {\n\t\tlcp: metrics.LCP,\n\t\tinp: metrics.INP,\n\t\tcls: metrics.CLS,\n\t\tfcp: metrics.FCP,\n\t\tttfb: metrics.TTFB,\n\t\tscore: calculateScore(metrics),\n\t\turl: typeof window !== 'undefined' && window.location ? window.location.href : '',\n\t\tuserAgent: typeof navigator !== 'undefined' ? navigator.userAgent : '',\n\t\ttimestamp: Date.now(),\n\t}\n}\n\n/**\n * Get a specific metric value\n *\n * @param name - Metric name\n * @returns Metric value or undefined\n */\nexport function getMetric(name: WebVitalName): WebVitalMetric | undefined {\n\treturn metrics[name]\n}\n\n/**\n * Check if Web Vitals are passing thresholds\n *\n * @returns Object with pass/fail status for each metric\n */\nexport function checkCoreWebVitals(): {\n\tlcp: boolean\n\tinp: boolean\n\tcls: boolean\n\tpassing: boolean\n} {\n\tconst lcp = metrics.LCP?.rating === 'good' || metrics.LCP?.rating === 'needs-improvement'\n\tconst inp = metrics.INP?.rating === 'good' || metrics.INP?.rating === 'needs-improvement'\n\tconst cls = metrics.CLS?.rating === 'good' || metrics.CLS?.rating === 'needs-improvement'\n\n\treturn {\n\t\tlcp: lcp ?? false,\n\t\tinp: inp ?? false,\n\t\tcls: cls ?? false,\n\t\tpassing: (lcp ?? false) && (inp ?? false) && (cls ?? false),\n\t}\n}\n\n/**\n * Reset Web Vitals tracking\n */\nexport function resetWebVitals(): void {\n\tmetrics = {}\n\tinitialized = false\n\tconfig = { ...DEFAULT_WEB_VITALS_CONFIG }\n}\n\n/**\n * Check if Web Vitals are initialized\n */\nexport function isWebVitalsInitialized(): boolean {\n\treturn initialized\n}\n\n// Note: ReportOpts is intentionally not re-exported (not part of public API)\n","/**\n * Session Replay React Hook\n *\n * Easy integration of session replay with React applications.\n * Automatically manages recording lifecycle and error correlation.\n *\n * When used within SylphxProvider, automatically uploads to the backend.\n * Otherwise, you can provide a custom upload handler or endpoint.\n *\n * @example\n * ```tsx\n * // With SylphxProvider (automatic backend integration)\n * function App() {\n *   return (\n *     <SylphxProvider appId=\"...\">\n *       <SessionReplayRecorder />\n *       <YourApp />\n *     </SylphxProvider>\n *   )\n * }\n *\n * // Manual usage\n * function MyComponent() {\n *   const { sessionId, isRecording, markError } = useSessionReplay({\n *     privacyMode: 'balanced',\n *     errorCorrelation: true,\n *   })\n *\n *   return <div>Session: {sessionId}</div>\n * }\n * ```\n */\n\n'use client'\n\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { SESSION_REPLAY_CHECK_INTERVAL_MS, STACK_TRACE_MAX_LENGTH } from '../../constants'\nimport {\n\ttype RecorderStatus,\n\ttype SessionData,\n\tSessionRecorder,\n\ttype SessionReplayConfig,\n} from '../../lib/monitoring'\n\n/** REST API client interface for session replay */\ninterface SessionReplayAPI {\n\tupload: (data: {\n\t\tmetadata: SessionData['metadata']\n\t\tevents: SessionData['events']\n\t\tmarkers: SessionData['markers']\n\t\trageClicks: SessionData['rageClicks']\n\t\tdeadClicks: SessionData['deadClicks']\n\t\tnetworkRequests: SessionData['networkRequests']\n\t\tconsoleLogs: SessionData['consoleLogs']\n\t}) => Promise<void>\n\tendSession: (sessionId: string, duration: number) => Promise<void>\n}\n\n// ==========================================\n// Types\n// ==========================================\n\nexport interface UseSessionReplayOptions extends Partial<SessionReplayConfig> {\n\t/**\n\t * Start recording automatically on mount\n\t * @default true\n\t */\n\tautoStart?: boolean\n\n\t/**\n\t * Stop recording on unmount\n\t * @default true\n\t */\n\tstopOnUnmount?: boolean\n\n\t/**\n\t * Upload endpoint path (fallback if not using api)\n\t * @default '/api/session-replay'\n\t */\n\tuploadEndpoint?: string\n\n\t/**\n\t * Custom upload handler (overrides API and endpoint)\n\t */\n\tonUpload?: (data: SessionData) => Promise<void>\n\n\t/**\n\t * Error callback\n\t */\n\tonError?: (error: Error) => void\n\n\t/**\n\t * User ID to associate with session\n\t */\n\tuserId?: string\n\n\t/**\n\t * SDK API client for automatic backend integration\n\t * Pass an object with upload and endSession methods\n\t *\n\t * @example\n\t * ```tsx\n\t * const { sessionId } = useSessionReplay({ api: sessionReplayApi })\n\t * ```\n\t */\n\tapi?: SessionReplayAPI\n}\n\nexport interface UseSessionReplayReturn {\n\t/** Current session ID */\n\tsessionId: string | null\n\t/** Whether recording is active */\n\tisRecording: boolean\n\t/** Recorder status */\n\tstatus: RecorderStatus\n\t/** Start recording */\n\tstart: () => string\n\t/** Pause recording */\n\tpause: () => void\n\t/** Resume recording */\n\tresume: () => void\n\t/** Stop recording */\n\tstop: () => Promise<void>\n\t/** Mark an error in the timeline */\n\tmarkError: (errorId: string, error: Error, metadata?: Record<string, unknown>) => void\n\t/** Mark a navigation event */\n\tmarkNavigation: (from: string, to: string) => void\n\t/** Mark a conversion event */\n\tmarkConversion: (name: string, value?: number) => void\n\t/** Add a custom marker */\n\taddMarker: (type: string, payload?: Record<string, unknown>) => void\n}\n\n// ==========================================\n// Hook\n// ==========================================\n\n/**\n * React hook for session replay\n *\n * Provides easy integration with automatic lifecycle management,\n * error correlation, and server upload.\n *\n * When api is provided, automatically uploads to the backend.\n * Otherwise, falls back to the uploadEndpoint or custom onUpload handler.\n */\nexport function useSessionReplay(options: UseSessionReplayOptions = {}): UseSessionReplayReturn {\n\tconst {\n\t\tautoStart = true,\n\t\tstopOnUnmount = true,\n\t\tuploadEndpoint = '/api/session-replay',\n\t\tonUpload: customUpload,\n\t\tonError,\n\t\tuserId,\n\t\tapi,\n\t\t...recorderConfig\n\t} = options\n\n\t// Store API in ref for async access\n\tconst apiRef = useRef<SessionReplayAPI | undefined>(api)\n\n\t// Update API ref when it changes\n\tuseEffect(() => {\n\t\tapiRef.current = api\n\t}, [api])\n\n\t// Recorder instance\n\tconst recorderRef = useRef<SessionRecorder | null>(null)\n\tconst currentSessionIdRef = useRef<string | null>(null)\n\n\t// State\n\tconst [sessionId, setSessionId] = useState<string | null>(null)\n\tconst [status, setStatus] = useState<RecorderStatus>({\n\t\tstate: 'idle',\n\t\tsessionId: null,\n\t\teventCount: 0,\n\t\tstartTime: null,\n\t\tduration: 0,\n\t\tbytesRecorded: 0,\n\t})\n\n\t// Initialize recorder\n\tuseEffect(() => {\n\t\tif (typeof window === 'undefined') return\n\n\t\trecorderRef.current = new SessionRecorder(recorderConfig)\n\n\t\t// Setup upload handler with priority:\n\t\t// 1. Custom upload handler\n\t\t// 2. API client if provided\n\t\t// 3. Fallback to fetch endpoint\n\t\tconst uploadHandler = customUpload\n\t\t\t? customUpload\n\t\t\t: api\n\t\t\t\t? createApiUploadHandler(apiRef)\n\t\t\t\t: createDefaultUploadHandler(uploadEndpoint)\n\n\t\trecorderRef.current.onUpload(uploadHandler)\n\n\t\t// Setup error handler\n\t\tif (onError) {\n\t\t\trecorderRef.current.onError(onError)\n\t\t}\n\n\t\t// Auto start\n\t\tif (autoStart) {\n\t\t\ttry {\n\t\t\t\tconst id = recorderRef.current.start()\n\t\t\t\tsetSessionId(id)\n\t\t\t\tcurrentSessionIdRef.current = id\n\t\t\t} catch (error) {\n\t\t\t\t// Sampling may prevent recording\n\t\t\t\tif (onError && error instanceof Error) {\n\t\t\t\t\tonError(error)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Status update interval\n\t\tconst statusInterval = setInterval(() => {\n\t\t\tif (recorderRef.current) {\n\t\t\t\tsetStatus(recorderRef.current.getStatus())\n\t\t\t}\n\t\t}, SESSION_REPLAY_CHECK_INTERVAL_MS)\n\n\t\t// Cleanup\n\t\treturn () => {\n\t\t\tclearInterval(statusInterval)\n\n\t\t\tif (stopOnUnmount && recorderRef.current) {\n\t\t\t\t// End session on backend\n\t\t\t\tif (currentSessionIdRef.current && apiRef.current) {\n\t\t\t\t\tvoid apiRef.current.endSession(\n\t\t\t\t\t\tcurrentSessionIdRef.current,\n\t\t\t\t\t\trecorderRef.current.getStatus().duration,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tvoid recorderRef.current.stop()\n\t\t\t}\n\t\t}\n\t}, [api, autoStart, customUpload, onError, stopOnUnmount, uploadEndpoint])\n\n\t// Update userId when it changes\n\tuseEffect(() => {\n\t\tif (userId && recorderRef.current) {\n\t\t\trecorderRef.current.addMarker('custom', {\n\t\t\t\ttype: 'user-identified',\n\t\t\t\tuserId,\n\t\t\t})\n\t\t}\n\t}, [userId])\n\n\t// ==========================================\n\t// Actions\n\t// ==========================================\n\n\tconst start = useCallback((): string => {\n\t\tif (!recorderRef.current) {\n\t\t\tthrow new Error('Recorder not initialized')\n\t\t}\n\t\tconst id = recorderRef.current.start()\n\t\tsetSessionId(id)\n\t\treturn id\n\t}, [])\n\n\tconst pause = useCallback((): void => {\n\t\trecorderRef.current?.pause()\n\t}, [])\n\n\tconst resume = useCallback((): void => {\n\t\trecorderRef.current?.resume()\n\t}, [])\n\n\tconst stop = useCallback(async (): Promise<void> => {\n\t\tawait recorderRef.current?.stop()\n\t\tsetSessionId(null)\n\t}, [])\n\n\tconst markError = useCallback(\n\t\t(errorId: string, error: Error, metadata?: Record<string, unknown>): void => {\n\t\t\trecorderRef.current?.markError(errorId, error, metadata)\n\t\t},\n\t\t[],\n\t)\n\n\tconst markNavigation = useCallback((from: string, to: string): void => {\n\t\trecorderRef.current?.markNavigation(from, to)\n\t}, [])\n\n\tconst markConversion = useCallback((name: string, value?: number): void => {\n\t\trecorderRef.current?.markConversion(name, value)\n\t}, [])\n\n\tconst addMarker = useCallback((type: string, payload?: Record<string, unknown>): void => {\n\t\trecorderRef.current?.addMarker(type as 'custom', payload)\n\t}, [])\n\n\treturn {\n\t\tsessionId,\n\t\tisRecording: status.state === 'recording',\n\t\tstatus,\n\t\tstart,\n\t\tpause,\n\t\tresume,\n\t\tstop,\n\t\tmarkError,\n\t\tmarkNavigation,\n\t\tmarkConversion,\n\t\taddMarker,\n\t}\n}\n\n// ==========================================\n// Helpers\n// ==========================================\n\n/**\n * Create upload handler that uses the SDK API client\n */\nfunction createApiUploadHandler(\n\tapiRef: React.MutableRefObject<SessionReplayAPI | undefined>,\n): (data: SessionData) => Promise<void> {\n\treturn async (data: SessionData) => {\n\t\tconst api = apiRef.current\n\t\tif (!api) {\n\t\t\tthrow new Error('API client not available')\n\t\t}\n\n\t\tawait api.upload({\n\t\t\tmetadata: data.metadata,\n\t\t\tevents: data.events,\n\t\t\tmarkers: data.markers,\n\t\t\trageClicks: data.rageClicks,\n\t\t\tdeadClicks: data.deadClicks,\n\t\t\tnetworkRequests: data.networkRequests,\n\t\t\tconsoleLogs: data.consoleLogs,\n\t\t})\n\t}\n}\n\n/**\n * Create default upload handler (fallback to fetch)\n */\nfunction createDefaultUploadHandler(endpoint: string): (data: SessionData) => Promise<void> {\n\treturn async (data: SessionData) => {\n\t\tconst response = await fetch(endpoint, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t},\n\t\t\tbody: JSON.stringify(data),\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(`Upload failed: ${response.status}`)\n\t\t}\n\t}\n}\n\n// ==========================================\n// Context Integration\n// ==========================================\n\n/**\n * Hook for marking errors from the error boundary\n */\nexport function useSessionReplayErrorMarker(): {\n\tmarkError: (error: Error, errorInfo?: { componentStack?: string }) => string\n} {\n\tconst recorderRef = useRef<SessionRecorder | null>(null)\n\n\t// Get recorder instance\n\tuseEffect(() => {\n\t\t// Access global recorder if it exists\n\t\tif (\n\t\t\ttypeof window !== 'undefined' &&\n\t\t\t(window as unknown as { __sylphxRecorder?: SessionRecorder }).__sylphxRecorder\n\t\t) {\n\t\t\trecorderRef.current = (\n\t\t\t\twindow as unknown as { __sylphxRecorder: SessionRecorder }\n\t\t\t).__sylphxRecorder\n\t\t}\n\t}, [])\n\n\tconst markError = useCallback((error: Error, errorInfo?: { componentStack?: string }): string => {\n\t\tconst errorId = `err_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`\n\n\t\trecorderRef.current?.markError(errorId, error, {\n\t\t\tcomponentStack: errorInfo?.componentStack?.slice(0, STACK_TRACE_MAX_LENGTH),\n\t\t})\n\n\t\treturn errorId\n\t}, [])\n\n\treturn { markError }\n}\n\n// ==========================================\n// HOC for automatic recording\n// ==========================================\n\nexport interface WithSessionReplayProps {\n\tsessionReplay: UseSessionReplayReturn\n}\n\n/**\n * HOC to inject session replay into a component\n */\nexport function withSessionReplay<P extends object>(\n\tComponent: React.ComponentType<P & WithSessionReplayProps>,\n\toptions?: UseSessionReplayOptions,\n): (props: P) => React.ReactElement {\n\tfunction WithSessionReplayWrapper(props: P): React.ReactElement {\n\t\tconst sessionReplay = useSessionReplay(options)\n\t\treturn <Component {...props} sessionReplay={sessionReplay} />\n\t}\n\n\tWithSessionReplayWrapper.displayName = `withSessionReplay(${Component.displayName || Component.name || 'Component'})`\n\n\treturn WithSessionReplayWrapper\n}\n","/**\n * Web Vitals React Hook\n *\n * React integration for Core Web Vitals monitoring with automatic\n * initialization and reporting.\n *\n * @example\n * ```tsx\n * function App() {\n *   const { report, score, isGood } = useWebVitals({\n *     onReport: (metric) => analytics.track('web_vital', metric),\n *   })\n *\n *   return (\n *     <div>\n *       <h1>Performance Score: {score}</h1>\n *       {!isGood && <p>Performance needs improvement</p>}\n *     </div>\n *   )\n * }\n * ```\n */\n\n'use client'\n\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport {\n\tgetWebVitalsReport,\n\tinitWebVitals,\n\tresetWebVitals,\n\tWEB_VITALS_THRESHOLDS,\n\ttype WebVitalMetric,\n\ttype WebVitalsConfig,\n\ttype WebVitalsReport,\n} from '../../lib/monitoring/web-vitals'\n\n// ============================================\n// Types\n// ============================================\n\nexport interface UseWebVitalsOptions extends WebVitalsConfig {\n\t/** Initialize automatically (default: true) */\n\tautoInit?: boolean\n}\n\nexport interface UseWebVitalsReturn {\n\t/** Current Web Vitals report */\n\treport: WebVitalsReport | null\n\t/** Overall performance score (0-100) */\n\tscore: number\n\t/** Whether all Core Web Vitals are passing */\n\tisGood: boolean\n\t/** Individual metric values */\n\tmetrics: {\n\t\tlcp: number | null\n\t\tinp: number | null\n\t\tcls: number | null\n\t\tfcp: number | null\n\t\tttfb: number | null\n\t}\n\t/** Individual metric ratings */\n\tratings: {\n\t\tlcp: 'good' | 'needs-improvement' | 'poor' | null\n\t\tinp: 'good' | 'needs-improvement' | 'poor' | null\n\t\tcls: 'good' | 'needs-improvement' | 'poor' | null\n\t\tfcp: 'good' | 'needs-improvement' | 'poor' | null\n\t\tttfb: 'good' | 'needs-improvement' | 'poor' | null\n\t}\n\t/** Manually trigger refresh */\n\trefresh: () => void\n\t/** Reset tracking */\n\treset: () => void\n}\n\n// ============================================\n// Hook\n// ============================================\n\n/**\n * Hook for monitoring Core Web Vitals\n *\n * Automatically initializes Web Vitals monitoring and provides\n * reactive access to metrics.\n *\n * @param options - Configuration options\n * @returns Web Vitals data and utilities\n *\n * @example\n * ```tsx\n * function PerformanceMonitor() {\n *   const { metrics, ratings, score, isGood } = useWebVitals({\n *     debug: process.env.NODE_ENV === 'development',\n *     onReport: (metric) => {\n *       // Send to analytics\n *       analytics.track('web_vital', {\n *         name: metric.name,\n *         value: metric.value,\n *         rating: metric.rating,\n *       })\n *     },\n *   })\n *\n *   if (metrics.lcp && ratings.lcp === 'poor') {\n *     console.warn(`LCP is poor: ${metrics.lcp}ms`)\n *   }\n *\n *   return <div>Score: {score}/100</div>\n * }\n * ```\n */\nexport function useWebVitals(options: UseWebVitalsOptions = {}): UseWebVitalsReturn {\n\tconst { autoInit = true, onReport, ...config } = options\n\tconst [report, setReport] = useState<WebVitalsReport | null>(null)\n\tconst initRef = useRef(false)\n\n\t// Initialize on mount\n\tuseEffect(() => {\n\t\tif (!autoInit || initRef.current) return\n\t\tif (typeof window === 'undefined') return\n\n\t\tinitRef.current = true\n\n\t\t// Wrap onReport to update state\n\t\tinitWebVitals({\n\t\t\t...config,\n\t\t\tonReport: (metric: WebVitalMetric) => {\n\t\t\t\t// Update local state\n\t\t\t\tsetReport(getWebVitalsReport())\n\t\t\t\t// Call user callback\n\t\t\t\tonReport?.(metric)\n\t\t\t},\n\t\t})\n\n\t\t// Initial report\n\t\tsetReport(getWebVitalsReport())\n\n\t\treturn () => {\n\t\t\t// Don't reset on unmount - metrics should persist\n\t\t}\n\t}, [autoInit, onReport])\n\n\t// Refresh report\n\tconst refresh = useCallback(() => {\n\t\tsetReport(getWebVitalsReport())\n\t}, [])\n\n\t// Reset tracking\n\tconst reset = useCallback(() => {\n\t\tresetWebVitals()\n\t\tsetReport(null)\n\t\tinitRef.current = false\n\t}, [])\n\n\t// Extract individual metrics\n\tconst metrics = {\n\t\tlcp: report?.lcp?.value ?? null,\n\t\tinp: report?.inp?.value ?? null,\n\t\tcls: report?.cls?.value ?? null,\n\t\tfcp: report?.fcp?.value ?? null,\n\t\tttfb: report?.ttfb?.value ?? null,\n\t}\n\n\tconst ratings = {\n\t\tlcp: report?.lcp?.rating ?? null,\n\t\tinp: report?.inp?.rating ?? null,\n\t\tcls: report?.cls?.rating ?? null,\n\t\tfcp: report?.fcp?.rating ?? null,\n\t\tttfb: report?.ttfb?.rating ?? null,\n\t}\n\n\t// Check if all Core Web Vitals are passing\n\tconst isGood =\n\t\t(ratings.lcp === 'good' || ratings.lcp === null) &&\n\t\t(ratings.inp === 'good' || ratings.inp === null) &&\n\t\t(ratings.cls === 'good' || ratings.cls === null)\n\n\treturn {\n\t\treport,\n\t\tscore: report?.score ?? 0,\n\t\tisGood,\n\t\tmetrics,\n\t\tratings,\n\t\trefresh,\n\t\treset,\n\t}\n}\n\n// ============================================\n// Utility Hook\n// ============================================\n\nexport interface UseWebVitalOptions {\n\t/** Metric name to track */\n\tmetric: 'LCP' | 'INP' | 'CLS' | 'FCP' | 'TTFB'\n}\n\nexport interface UseWebVitalReturn {\n\t/** Metric value */\n\tvalue: number | null\n\t/** Metric rating */\n\trating: 'good' | 'needs-improvement' | 'poor' | null\n\t/** Threshold for 'good' rating */\n\tgoodThreshold: number\n\t/** Threshold for 'poor' rating */\n\tpoorThreshold: number\n\t/** Whether metric is passing */\n\tisPassing: boolean\n}\n\n/**\n * Hook for tracking a single Web Vital metric\n *\n * @param options - Options with metric name\n * @returns Single metric data\n *\n * @example\n * ```tsx\n * function LCPIndicator() {\n *   const { value, rating, isPassing } = useWebVital({ metric: 'LCP' })\n *\n *   if (value === null) return <span>Measuring...</span>\n *\n *   return (\n *     <span style={{ color: isPassing ? 'green' : 'red' }}>\n *       LCP: {value.toFixed(0)}ms ({rating})\n *     </span>\n *   )\n * }\n * ```\n */\nexport function useWebVital({ metric }: UseWebVitalOptions): UseWebVitalReturn {\n\tconst { report } = useWebVitals({ autoInit: true })\n\n\tconst metricData = report?.[metric.toLowerCase() as keyof WebVitalsReport] as\n\t\t| WebVitalMetric\n\t\t| undefined\n\tconst threshold = WEB_VITALS_THRESHOLDS[metric]\n\n\treturn {\n\t\tvalue: metricData?.value ?? null,\n\t\trating: metricData?.rating ?? null,\n\t\tgoodThreshold: threshold.good,\n\t\tpoorThreshold: threshold.poor,\n\t\tisPassing: metricData?.rating === 'good' || metricData?.rating === 'needs-improvement',\n\t}\n}\n\n// ============================================\n// Analytics Integration Hook\n// ============================================\n\nexport interface UseWebVitalsAnalyticsOptions {\n\t/** Track function from useAnalytics */\n\ttrack: (event: string, properties?: Record<string, unknown>) => void\n\t/** Event name prefix (default: 'web_vital') */\n\teventPrefix?: string\n\t/** Send report on page hide */\n\treportOnHide?: boolean\n}\n\n/**\n * Hook for Web Vitals with automatic analytics tracking\n *\n * Integrates Web Vitals with your analytics system automatically.\n *\n * @param options - Analytics integration options\n * @returns Web Vitals data\n *\n * @example\n * ```tsx\n * function App() {\n *   const { track } = useAnalytics()\n *\n *   useWebVitalsAnalytics({\n *     track,\n *     eventPrefix: 'performance',\n *     reportOnHide: true,\n *   })\n *\n *   return <YourApp />\n * }\n * ```\n */\nexport function useWebVitalsAnalytics(options: UseWebVitalsAnalyticsOptions): UseWebVitalsReturn {\n\tconst { track, eventPrefix = 'web_vital', reportOnHide = true } = options\n\tconst reportedRef = useRef(false)\n\n\tconst webVitals = useWebVitals({\n\t\tonReport: (metric) => {\n\t\t\ttrack(`${eventPrefix}_${metric.name.toLowerCase()}`, {\n\t\t\t\tmetric_name: metric.name,\n\t\t\t\tmetric_value: metric.value,\n\t\t\t\tmetric_rating: metric.rating,\n\t\t\t\tmetric_delta: metric.delta,\n\t\t\t\tmetric_id: metric.id,\n\t\t\t\tnavigation_type: metric.navigationType,\n\t\t\t})\n\t\t},\n\t})\n\n\t// Report summary on page hide\n\tuseEffect(() => {\n\t\tif (!reportOnHide) return\n\n\t\tconst handleVisibilityChange = () => {\n\t\t\tif (document.visibilityState === 'hidden' && !reportedRef.current && webVitals.report) {\n\t\t\t\treportedRef.current = true\n\t\t\t\ttrack(`${eventPrefix}_summary`, {\n\t\t\t\t\tscore: webVitals.score,\n\t\t\t\t\tlcp_value: webVitals.metrics.lcp,\n\t\t\t\t\tlcp_rating: webVitals.ratings.lcp,\n\t\t\t\t\tinp_value: webVitals.metrics.inp,\n\t\t\t\t\tinp_rating: webVitals.ratings.inp,\n\t\t\t\t\tcls_value: webVitals.metrics.cls,\n\t\t\t\t\tcls_rating: webVitals.ratings.cls,\n\t\t\t\t\tfcp_value: webVitals.metrics.fcp,\n\t\t\t\t\tfcp_rating: webVitals.ratings.fcp,\n\t\t\t\t\tttfb_value: webVitals.metrics.ttfb,\n\t\t\t\t\tttfb_rating: webVitals.ratings.ttfb,\n\t\t\t\t\tis_passing: webVitals.isGood,\n\t\t\t\t\turl: window.location.href,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tdocument.addEventListener('visibilitychange', handleVisibilityChange)\n\t\treturn () => document.removeEventListener('visibilitychange', handleVisibilityChange)\n\t}, [track, eventPrefix, reportOnHide, webVitals])\n\n\treturn webVitals\n}\n\n// Re-export types from module\n","/**\n * Enhanced Error Tracking Hook\n *\n * React hook with Session Replay integration.\n * Automatically correlates errors with replay sessions.\n *\n * @example\n * ```tsx\n * function App() {\n *   const { captureException, addBreadcrumb } = useEnhancedErrorTracking({\n *     attachReplay: true,\n *   })\n *\n *   const handleClick = async () => {\n *     try {\n *       await riskyOperation()\n *     } catch (error) {\n *       const { eventId, replayUrl } = await captureException(error)\n *       console.log(`Error ${eventId} - Replay: ${replayUrl}`)\n *     }\n *   }\n *\n *   return <button onClick={handleClick}>Do Something</button>\n * }\n * ```\n */\n\n'use client'\n\nimport { useCallback, useEffect, useRef } from 'react'\nimport { SESSION_REPLAY_STATUS_CHECK_MS } from '../../constants'\nimport {\n\ttype Breadcrumb,\n\ttype CaptureExceptionOptions,\n\ttype CaptureMessageOptions,\n\ttype CaptureResult,\n\t// Error tracking\n\ttype ErrorTracker,\n\ttype ErrorTrackingConfig,\n\t// Session replay\n\tgetRecorder,\n\tgetTracker,\n} from '../../lib/monitoring'\n\n// ==========================================\n// Types\n// ==========================================\n\nexport interface UseEnhancedErrorTrackingOptions extends Partial<ErrorTrackingConfig> {\n\t/**\n\t * Automatically link with session replay\n\t * @default true\n\t */\n\tattachReplay?: boolean\n\n\t/**\n\t * Upload endpoint path\n\t * @default '/api/monitoring/error'\n\t */\n\tuploadEndpoint?: string\n\n\t/**\n\t * Custom upload handler\n\t */\n\tonUpload?: (event: unknown) => Promise<{ eventId: string }>\n\n\t/**\n\t * Called when an error is captured\n\t */\n\tonCapture?: (result: CaptureResult) => void\n\n\t/**\n\t * Initialize on mount\n\t * @default true\n\t */\n\tautoInit?: boolean\n}\n\nexport interface UseEnhancedErrorTrackingReturn {\n\t/** Capture an exception with replay correlation */\n\tcaptureException: (\n\t\terror: Error,\n\t\toptions?: CaptureExceptionOptions,\n\t) => Promise<CaptureResult & { replayUrl?: string }>\n\t/** Capture a message */\n\tcaptureMessage: (message: string, options?: CaptureMessageOptions) => Promise<CaptureResult>\n\t/** Add a breadcrumb */\n\taddBreadcrumb: (breadcrumb: Breadcrumb) => void\n\t/** Set current user */\n\tsetUser: (user: { id?: string; email?: string; username?: string }) => void\n\t/** Clear current user */\n\tclearUser: () => void\n\t/** Manually link a replay session */\n\tlinkReplaySession: (sessionId: string) => void\n\t/** Get current replay session ID */\n\tgetReplaySessionId: () => string | null\n}\n\n// ==========================================\n// Hook\n// ==========================================\n\n/**\n * Enhanced error tracking hook with Session Replay integration\n */\nexport function useEnhancedErrorTracking(\n\toptions: UseEnhancedErrorTrackingOptions = {},\n): UseEnhancedErrorTrackingReturn {\n\tconst {\n\t\tattachReplay = true,\n\t\tuploadEndpoint = '/api/monitoring/error',\n\t\tonUpload: customUpload,\n\t\tonCapture,\n\t\tautoInit = true,\n\t\t...trackerConfig\n\t} = options\n\n\tconst trackerRef = useRef<ErrorTracker | null>(null)\n\tconst replaySessionIdRef = useRef<string | null>(null)\n\n\t// Initialize tracker\n\tuseEffect(() => {\n\t\tif (typeof window === 'undefined') return\n\n\t\tconst tracker = getTracker({\n\t\t\t...trackerConfig,\n\t\t\tattachReplay,\n\t\t})\n\n\t\t// Setup upload handler\n\t\tconst uploadHandler = customUpload ?? createDefaultUploadHandler(uploadEndpoint)\n\t\ttracker.onUpload(async (event) => {\n\t\t\tconst result = await uploadHandler(event)\n\t\t\treturn result\n\t\t})\n\n\t\t// Link with session replay if enabled\n\t\tif (attachReplay) {\n\t\t\ttry {\n\t\t\t\tconst recorder = getRecorder()\n\t\t\t\tconst status = recorder.getStatus()\n\t\t\t\tif (status.sessionId) {\n\t\t\t\t\ttracker.setSessionReplayId(status.sessionId)\n\t\t\t\t\treplaySessionIdRef.current = status.sessionId\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Recorder might not be initialized\n\t\t\t}\n\t\t}\n\n\t\t// Auto init\n\t\tif (autoInit) {\n\t\t\ttracker.init()\n\t\t}\n\n\t\ttrackerRef.current = tracker\n\t}, [attachReplay, autoInit, customUpload, uploadEndpoint])\n\n\t// Keep replay session in sync\n\tuseEffect(() => {\n\t\tif (!attachReplay || typeof window === 'undefined') return\n\n\t\tconst checkReplaySession = () => {\n\t\t\ttry {\n\t\t\t\tconst recorder = getRecorder()\n\t\t\t\tconst status = recorder.getStatus()\n\t\t\t\tif (status.sessionId && status.sessionId !== replaySessionIdRef.current) {\n\t\t\t\t\treplaySessionIdRef.current = status.sessionId\n\t\t\t\t\ttrackerRef.current?.setSessionReplayId(status.sessionId)\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Ignore\n\t\t\t}\n\t\t}\n\n\t\tconst interval = setInterval(checkReplaySession, SESSION_REPLAY_STATUS_CHECK_MS)\n\t\treturn () => clearInterval(interval)\n\t}, [attachReplay])\n\n\t// ==========================================\n\t// Actions\n\t// ==========================================\n\n\tconst captureException = useCallback(\n\t\tasync (\n\t\t\terror: Error,\n\t\t\topts: CaptureExceptionOptions = {},\n\t\t): Promise<CaptureResult & { replayUrl?: string }> => {\n\t\t\tif (!trackerRef.current) {\n\t\t\t\treturn { eventId: '' }\n\t\t\t}\n\n\t\t\t// Mark error in session replay if available\n\t\t\tif (attachReplay && replaySessionIdRef.current) {\n\t\t\t\ttry {\n\t\t\t\t\tconst recorder = getRecorder()\n\t\t\t\t\trecorder.markError(`err_${Date.now()}`, error)\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst result = await trackerRef.current.captureException(error, {\n\t\t\t\t...opts,\n\t\t\t\treplaySessionId: replaySessionIdRef.current ?? undefined,\n\t\t\t})\n\n\t\t\t// Build replay URL if we have a session\n\t\t\tlet replayUrl: string | undefined\n\t\t\tif (result.replaySessionId) {\n\t\t\t\treplayUrl = `/console/replay/${result.replaySessionId}?event=${result.eventId}`\n\t\t\t}\n\n\t\t\tonCapture?.(result)\n\n\t\t\treturn {\n\t\t\t\t...result,\n\t\t\t\treplayUrl,\n\t\t\t}\n\t\t},\n\t\t[attachReplay, onCapture],\n\t)\n\n\tconst captureMessage = useCallback(\n\t\tasync (message: string, opts: CaptureMessageOptions = {}): Promise<CaptureResult> => {\n\t\t\tif (!trackerRef.current) {\n\t\t\t\treturn { eventId: '' }\n\t\t\t}\n\n\t\t\tconst result = await trackerRef.current.captureMessage(message, opts)\n\t\t\tonCapture?.(result)\n\n\t\t\treturn result\n\t\t},\n\t\t[onCapture],\n\t)\n\n\tconst addBreadcrumb = useCallback((breadcrumb: Breadcrumb): void => {\n\t\ttrackerRef.current?.addBreadcrumb(breadcrumb)\n\t}, [])\n\n\tconst setUser = useCallback((user: { id?: string; email?: string; username?: string }): void => {\n\t\ttrackerRef.current?.setUser(user)\n\t}, [])\n\n\tconst clearUser = useCallback((): void => {\n\t\ttrackerRef.current?.clearUser()\n\t}, [])\n\n\tconst linkReplaySession = useCallback((sessionId: string): void => {\n\t\treplaySessionIdRef.current = sessionId\n\t\ttrackerRef.current?.setSessionReplayId(sessionId)\n\t}, [])\n\n\tconst getReplaySessionId = useCallback((): string | null => {\n\t\treturn replaySessionIdRef.current\n\t}, [])\n\n\treturn {\n\t\tcaptureException,\n\t\tcaptureMessage,\n\t\taddBreadcrumb,\n\t\tsetUser,\n\t\tclearUser,\n\t\tlinkReplaySession,\n\t\tgetReplaySessionId,\n\t}\n}\n\n// ==========================================\n// Helpers\n// ==========================================\n\ninterface UploadResponse {\n\teventId: string\n\tisNewError?: boolean\n\trecommendedSampleRate?: number\n\tquotaUsage?: number\n}\n\nfunction createDefaultUploadHandler(endpoint: string): (event: unknown) => Promise<UploadResponse> {\n\treturn async (event: unknown) => {\n\t\tconst response = await fetch(endpoint, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t},\n\t\t\tbody: JSON.stringify(event),\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\t// Try to extract quota feedback from error response\n\t\t\ttry {\n\t\t\t\tconst errorData = (await response.json()) as {\n\t\t\t\t\terror?: { message: string }\n\t\t\t\t\trecommendedSampleRate?: number\n\t\t\t\t\tquotaUsage?: number\n\t\t\t\t}\n\t\t\t\t// Return with quota feedback for adaptive sampling even on error\n\t\t\t\tif (errorData.recommendedSampleRate !== undefined) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\teventId: '',\n\t\t\t\t\t\trecommendedSampleRate: errorData.recommendedSampleRate,\n\t\t\t\t\t\tquotaUsage: errorData.quotaUsage,\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Ignore JSON parse error\n\t\t\t}\n\t\t\tthrow new Error(`Upload failed: ${response.status}`)\n\t\t}\n\n\t\tconst data = (await response.json()) as UploadResponse\n\t\treturn {\n\t\t\teventId: data.eventId,\n\t\t\tisNewError: data.isNewError,\n\t\t\trecommendedSampleRate: data.recommendedSampleRate,\n\t\t\tquotaUsage: data.quotaUsage,\n\t\t}\n\t}\n}\n\n// ==========================================\n// Combined Hook\n// ==========================================\n\nexport interface UseCombinedMonitoringOptions extends UseEnhancedErrorTrackingOptions {\n\t/** Session replay config (passed to useSessionReplay) */\n\treplayConfig?: Record<string, unknown>\n}\n\n/**\n * Combined hook for error tracking + session replay\n * Use this as a single integration point\n */\nexport function useCombinedMonitoring(options: UseCombinedMonitoringOptions = {}) {\n\tconst errorTracking = useEnhancedErrorTracking(options)\n\n\t// The session replay is handled by the error tracking hook via getRecorder()\n\t// This hook just provides a unified interface\n\n\treturn {\n\t\t// Error tracking\n\t\t...errorTracking,\n\n\t\t// Helper to capture and mark in replay\n\t\tcaptureWithReplay: async (\n\t\t\terror: Error,\n\t\t\topts: CaptureExceptionOptions = {},\n\t\t): Promise<CaptureResult & { replayUrl?: string }> => {\n\t\t\treturn errorTracking.captureException(error, opts)\n\t\t},\n\t}\n}\n","/**\n * Local Flag Evaluator\n *\n * Zero-latency client-side flag evaluation with:\n * - In-memory caching with TTL\n * - Consistent bucketing\n * - Targeting rules evaluation\n * - Offline support with localStorage fallback\n */\n\nimport { FLAGS_CACHE_TTL_MS, FLAGS_STALE_WHILE_REVALIDATE_MS } from '../../constants'\nimport { getUserBucket, isInPercentage, selectVariant } from './hash'\nimport { findMatchingRule, mergeContext } from './targeting'\nimport type {\n\tEvaluationContext,\n\tEvaluationResult,\n\tFeatureFlagsConfig,\n\tFlagDefinition,\n\tFlagValue,\n} from './types'\n\n// ==========================================\n// Cache Types\n// ==========================================\n\ninterface CachedEvaluation {\n\tresult: EvaluationResult\n\ttimestamp: number\n\tcontextHash: string\n}\n\ninterface FlagsState {\n\tflags: Map<string, FlagDefinition>\n\tfetchedAt: number\n\tversion: number\n}\n\n// ==========================================\n// Local Evaluator\n// ==========================================\n\n/**\n * Local Flag Evaluator\n *\n * Evaluates feature flags entirely on the client with zero network latency.\n * Syncs flag definitions via SSE for real-time updates.\n */\nexport class LocalEvaluator {\n\tprivate state: FlagsState = {\n\t\tflags: new Map(),\n\t\tfetchedAt: 0,\n\t\tversion: 0,\n\t}\n\n\tprivate evaluationCache: Map<string, CachedEvaluation> = new Map()\n\tprivate context: EvaluationContext = {}\n\tprivate config: FeatureFlagsConfig\n\n\tconstructor(config: FeatureFlagsConfig = {}) {\n\t\tthis.config = config\n\n\t\t// Load persisted flags on init\n\t\tif (config.offlineSupport !== false) {\n\t\t\tthis.loadFromStorage()\n\t\t}\n\t}\n\n\t// ==========================================\n\t// Flag Management\n\t// ==========================================\n\n\t/**\n\t * Set flags from server response\n\t */\n\tsetFlags(flags: FlagDefinition[]): void {\n\t\tconst now = Date.now()\n\n\t\tthis.state.flags.clear()\n\t\tfor (const flag of flags) {\n\t\t\tthis.state.flags.set(flag.key, flag)\n\t\t}\n\t\tthis.state.fetchedAt = now\n\t\tthis.state.version++\n\n\t\t// Clear evaluation cache\n\t\tthis.evaluationCache.clear()\n\n\t\t// Persist for offline use\n\t\tthis.saveToStorage()\n\n\t\t// Notify listener\n\t\tthis.config.onFlagsUpdated?.(flags)\n\n\t\tthis.debug('Flags updated', {\n\t\t\tcount: flags.length,\n\t\t\tversion: this.state.version,\n\t\t})\n\t}\n\n\t/**\n\t * Update a single flag\n\t */\n\tupdateFlag(flag: FlagDefinition): void {\n\t\tthis.state.flags.set(flag.key, flag)\n\t\tthis.state.version++\n\n\t\t// Clear cache for this flag\n\t\t// Use Array.from to avoid iterator invalidation when deleting during iteration\n\t\t// Use exact prefix match with delimiter to avoid matching similar flag keys\n\t\t// (e.g., \"flag\" vs \"flag-v2\" - we use \"flag:\" as prefix so \"flag-v2:\" won't match)\n\t\tconst cachePrefix = `${flag.key}:`\n\t\tconst keysToDelete = Array.from(this.evaluationCache.keys()).filter((key) =>\n\t\t\tkey.startsWith(cachePrefix),\n\t\t)\n\t\tfor (const key of keysToDelete) {\n\t\t\tthis.evaluationCache.delete(key)\n\t\t}\n\n\t\tthis.saveToStorage()\n\t\tthis.config.onFlagsUpdated?.(Array.from(this.state.flags.values()))\n\n\t\tthis.debug('Flag updated', {\n\t\t\tkey: flag.key,\n\t\t\tcacheEntriesCleared: keysToDelete.length,\n\t\t})\n\t}\n\n\t/**\n\t * Remove a flag\n\t */\n\tremoveFlag(key: string): void {\n\t\tthis.state.flags.delete(key)\n\t\tthis.state.version++\n\n\t\t// Clear cache for this flag\n\t\t// Use Array.from to avoid iterator invalidation when deleting during iteration\n\t\tconst cachePrefix = `${key}:`\n\t\tconst keysToDelete = Array.from(this.evaluationCache.keys()).filter((cacheKey) =>\n\t\t\tcacheKey.startsWith(cachePrefix),\n\t\t)\n\t\tfor (const cacheKey of keysToDelete) {\n\t\t\tthis.evaluationCache.delete(cacheKey)\n\t\t}\n\n\t\tthis.saveToStorage()\n\t\tthis.config.onFlagsUpdated?.(Array.from(this.state.flags.values()))\n\n\t\tthis.debug('Flag removed', {\n\t\t\tkey,\n\t\t\tcacheEntriesCleared: keysToDelete.length,\n\t\t})\n\t}\n\n\t/**\n\t * Get all flag definitions\n\t */\n\tgetFlags(): FlagDefinition[] {\n\t\treturn Array.from(this.state.flags.values())\n\t}\n\n\t/**\n\t * Get a specific flag definition\n\t */\n\tgetFlag(key: string): FlagDefinition | undefined {\n\t\treturn this.state.flags.get(key)\n\t}\n\n\t// ==========================================\n\t// Context Management\n\t// ==========================================\n\n\t/**\n\t * Set evaluation context\n\t */\n\tsetContext(context: EvaluationContext): void {\n\t\tthis.context = context\n\t\t// Clear cache when context changes\n\t\tthis.evaluationCache.clear()\n\t\tthis.debug('Context updated', context)\n\t}\n\n\t/**\n\t * Update context (merge with existing)\n\t */\n\tupdateContext(partial: Partial<EvaluationContext>): void {\n\t\tthis.context = mergeContext(this.context, partial)\n\t\tthis.evaluationCache.clear()\n\t\tthis.debug('Context merged', partial)\n\t}\n\n\t/**\n\t * Get current context\n\t */\n\tgetContext(): EvaluationContext {\n\t\treturn { ...this.context }\n\t}\n\n\t// ==========================================\n\t// Evaluation\n\t// ==========================================\n\n\t/**\n\t * Evaluate a boolean flag\n\t */\n\tisEnabled(flagKey: string, defaultValue = false): boolean {\n\t\tconst result = this.evaluate<boolean>(flagKey, defaultValue)\n\t\treturn result.value\n\t}\n\n\t/**\n\t * Evaluate a string flag\n\t */\n\tgetString(flagKey: string, defaultValue = ''): string {\n\t\tconst result = this.evaluate<string>(flagKey, defaultValue)\n\t\treturn result.value\n\t}\n\n\t/**\n\t * Evaluate a number flag\n\t */\n\tgetNumber(flagKey: string, defaultValue = 0): number {\n\t\tconst result = this.evaluate<number>(flagKey, defaultValue)\n\t\treturn result.value\n\t}\n\n\t/**\n\t * Evaluate a JSON flag\n\t */\n\tgetJSON<T extends Record<string, unknown>>(flagKey: string, defaultValue: T): T {\n\t\tconst result = this.evaluate<T>(flagKey, defaultValue)\n\t\treturn result.value\n\t}\n\n\t/**\n\t * Full evaluation with metadata\n\t */\n\tevaluate<T = FlagValue>(\n\t\tflagKey: string,\n\t\tdefaultValue: T,\n\t\tcontextOverride?: EvaluationContext,\n\t): EvaluationResult<T> {\n\t\tconst context = contextOverride ? mergeContext(this.context, contextOverride) : this.context\n\n\t\t// Check cache first\n\t\tconst cacheKey = this.getCacheKey(flagKey, context)\n\t\tconst cached = this.evaluationCache.get(cacheKey)\n\n\t\tif (cached && Date.now() - cached.timestamp < (this.config.cacheTtl ?? FLAGS_CACHE_TTL_MS)) {\n\t\t\tthis.debug('Cache hit', { flagKey })\n\t\t\treturn cached.result as EvaluationResult<T>\n\t\t}\n\n\t\t// Evaluate\n\t\tconst result = this.evaluateFlag<T>(flagKey, defaultValue, context)\n\n\t\t// Cache result\n\t\tthis.evaluationCache.set(cacheKey, {\n\t\t\tresult: result as EvaluationResult,\n\t\t\ttimestamp: Date.now(),\n\t\t\tcontextHash: this.hashContext(context),\n\t\t})\n\n\t\t// Notify listener\n\t\tthis.config.onEvaluation?.(flagKey, result as EvaluationResult)\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Evaluate multiple flags at once\n\t */\n\tevaluateAll(\n\t\tflagKeys: string[],\n\t\tcontextOverride?: EvaluationContext,\n\t): Map<string, EvaluationResult> {\n\t\tconst results = new Map<string, EvaluationResult>()\n\n\t\tfor (const key of flagKeys) {\n\t\t\tresults.set(key, this.evaluate(key, null, contextOverride))\n\t\t}\n\n\t\treturn results\n\t}\n\n\t// ==========================================\n\t// Private Evaluation Logic\n\t// ==========================================\n\n\tprivate evaluateFlag<T = FlagValue>(\n\t\tflagKey: string,\n\t\tdefaultValue: T,\n\t\tcontext: EvaluationContext,\n\t): EvaluationResult<T> {\n\t\tconst flag = this.state.flags.get(flagKey)\n\n\t\t// Flag not found\n\t\tif (!flag) {\n\t\t\tthis.debug('Flag not found', { flagKey })\n\t\t\treturn {\n\t\t\t\tvalue: defaultValue,\n\t\t\t\tvariant: 'default',\n\t\t\t\tenabled: false,\n\t\t\t\treason: 'error',\n\t\t\t}\n\t\t}\n\n\t\t// Flag disabled\n\t\tif (!flag.enabled) {\n\t\t\tconst variant = flag.variants.find((v) => v.key === flag.defaultVariant)\n\t\t\treturn {\n\t\t\t\tvalue: (variant?.value as T) ?? defaultValue,\n\t\t\t\tvariant: flag.defaultVariant,\n\t\t\t\tenabled: false,\n\t\t\t\treason: 'flag_disabled',\n\t\t\t}\n\t\t}\n\n\t\t// Evaluate targeting rules\n\t\tconst matchedRule = findMatchingRule(flag.rules, context)\n\n\t\tif (matchedRule) {\n\t\t\t// Check percentage rollout within rule\n\t\t\tif (matchedRule.percentage !== undefined && matchedRule.percentage < 100) {\n\t\t\t\tconst bucket = getUserBucket(flagKey, context.userId, context.anonymousId, flag.salt)\n\n\t\t\t\tif (!isInPercentage(bucket, matchedRule.percentage)) {\n\t\t\t\t\t// Not in rollout percentage, use default\n\t\t\t\t\tconst variant = flag.variants.find((v) => v.key === flag.defaultVariant)\n\t\t\t\t\treturn {\n\t\t\t\t\t\tvalue: (variant?.value as T) ?? defaultValue,\n\t\t\t\t\t\tvariant: flag.defaultVariant,\n\t\t\t\t\t\tenabled: true,\n\t\t\t\t\t\tmatchedRule: matchedRule.id,\n\t\t\t\t\t\treason: 'percentage_rollout',\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Return rule's variant\n\t\t\tconst variant = flag.variants.find((v) => v.key === matchedRule.variant)\n\t\t\treturn {\n\t\t\t\tvalue: (variant?.value as T) ?? defaultValue,\n\t\t\t\tvariant: matchedRule.variant,\n\t\t\t\tenabled: true,\n\t\t\t\tmatchedRule: matchedRule.id,\n\t\t\t\treason: 'rule_match',\n\t\t\t}\n\t\t}\n\n\t\t// No rules matched - use weighted variant selection\n\t\tif (flag.variants.length > 1) {\n\t\t\tconst bucket = getUserBucket(flagKey, context.userId, context.anonymousId, flag.salt)\n\t\t\tconst variantsWithWeights = flag.variants.map((v) => ({\n\t\t\t\tkey: v.key,\n\t\t\t\tweight: v.weight ?? 100 / flag.variants.length,\n\t\t\t}))\n\n\t\t\tconst selectedKey = selectVariant(variantsWithWeights, bucket)\n\t\t\tconst variant = flag.variants.find((v) => v.key === selectedKey)\n\n\t\t\treturn {\n\t\t\t\tvalue: (variant?.value as T) ?? defaultValue,\n\t\t\t\tvariant: selectedKey,\n\t\t\t\tenabled: true,\n\t\t\t\treason: 'percentage_rollout',\n\t\t\t}\n\t\t}\n\n\t\t// Single variant or default\n\t\tconst variant = flag.variants.find((v) => v.key === flag.defaultVariant)\n\t\treturn {\n\t\t\tvalue: (variant?.value as T) ?? defaultValue,\n\t\t\tvariant: flag.defaultVariant,\n\t\t\tenabled: true,\n\t\t\treason: 'default',\n\t\t}\n\t}\n\n\t// ==========================================\n\t// Persistence\n\t// ==========================================\n\n\tprivate loadFromStorage(): void {\n\t\tif (typeof window === 'undefined' || typeof localStorage === 'undefined') return\n\n\t\ttry {\n\t\t\tconst key = this.config.storageKey ?? 'sylphx_flags'\n\t\t\tconst stored = localStorage.getItem(key)\n\n\t\t\tif (stored) {\n\t\t\t\tconst data = JSON.parse(stored) as {\n\t\t\t\t\tflags: FlagDefinition[]\n\t\t\t\t\tfetchedAt: number\n\t\t\t\t\tversion: number\n\t\t\t\t}\n\n\t\t\t\tfor (const flag of data.flags) {\n\t\t\t\t\tthis.state.flags.set(flag.key, flag)\n\t\t\t\t}\n\t\t\t\tthis.state.fetchedAt = data.fetchedAt\n\t\t\t\tthis.state.version = data.version\n\n\t\t\t\tthis.debug('Loaded from storage', { count: data.flags.length })\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.debug('Failed to load from storage', { error })\n\t\t}\n\t}\n\n\tprivate saveToStorage(): void {\n\t\tif (typeof window === 'undefined' || typeof localStorage === 'undefined') return\n\t\tif (this.config.offlineSupport === false) return\n\n\t\ttry {\n\t\t\tconst key = this.config.storageKey ?? 'sylphx_flags'\n\t\t\tconst data = {\n\t\t\t\tflags: Array.from(this.state.flags.values()),\n\t\t\t\tfetchedAt: this.state.fetchedAt,\n\t\t\t\tversion: this.state.version,\n\t\t\t}\n\n\t\t\tlocalStorage.setItem(key, JSON.stringify(data))\n\t\t} catch (error) {\n\t\t\tthis.debug('Failed to save to storage', { error })\n\t\t}\n\t}\n\n\t// ==========================================\n\t// Utilities\n\t// ==========================================\n\n\tprivate getCacheKey(flagKey: string, context: EvaluationContext): string {\n\t\treturn `${flagKey}:${this.hashContext(context)}`\n\t}\n\n\tprivate hashContext(context: EvaluationContext): string {\n\t\t// Simple hash based on key identifiers\n\t\tconst parts = [\n\t\t\tcontext.userId ?? '',\n\t\t\tcontext.anonymousId ?? '',\n\t\t\tcontext.email ?? '',\n\t\t\tJSON.stringify(context.attributes ?? {}),\n\t\t]\n\t\treturn parts.join(':')\n\t}\n\n\tprivate debug(message: string, data?: unknown): void {\n\t\tif (this.config.debug) {\n\t\t}\n\t}\n\n\t/**\n\t * Get evaluator state for debugging\n\t */\n\tgetState(): {\n\t\tflagCount: number\n\t\tcacheSize: number\n\t\tfetchedAt: number\n\t\tversion: number\n\t\tisStale: boolean\n\t} {\n\t\tconst staleThreshold =\n\t\t\t(this.config.cacheTtl ?? FLAGS_CACHE_TTL_MS) +\n\t\t\t(this.config.staleWhileRevalidate ?? FLAGS_STALE_WHILE_REVALIDATE_MS)\n\t\tconst isStale = Date.now() - this.state.fetchedAt > staleThreshold\n\n\t\treturn {\n\t\t\tflagCount: this.state.flags.size,\n\t\t\tcacheSize: this.evaluationCache.size,\n\t\t\tfetchedAt: this.state.fetchedAt,\n\t\t\tversion: this.state.version,\n\t\t\tisStale,\n\t\t}\n\t}\n\n\t/**\n\t * Clear all caches\n\t */\n\tclearCache(): void {\n\t\tthis.evaluationCache.clear()\n\t}\n\n\t/**\n\t * Reset evaluator state\n\t */\n\treset(): void {\n\t\tthis.state.flags.clear()\n\t\tthis.state.fetchedAt = 0\n\t\tthis.state.version = 0\n\t\tthis.evaluationCache.clear()\n\t\tthis.context = {}\n\n\t\tif (\n\t\t\ttypeof window !== 'undefined' &&\n\t\t\ttypeof localStorage !== 'undefined' &&\n\t\t\tthis.config.offlineSupport !== false\n\t\t) {\n\t\t\tconst key = this.config.storageKey ?? 'sylphx_flags'\n\t\t\tlocalStorage.removeItem(key)\n\t\t}\n\t}\n}\n\n// ==========================================\n// Singleton Instance\n// ==========================================\n\nlet evaluatorInstance: LocalEvaluator | null = null\n\n/**\n * Get or create the evaluator instance\n */\nexport function getEvaluator(config?: FeatureFlagsConfig): LocalEvaluator {\n\tif (!evaluatorInstance) {\n\t\tevaluatorInstance = new LocalEvaluator(config)\n\t}\n\treturn evaluatorInstance\n}\n\n/**\n * Initialize feature flags with configuration\n */\nexport function initFeatureFlags(config?: FeatureFlagsConfig): LocalEvaluator {\n\tevaluatorInstance = new LocalEvaluator(config)\n\treturn evaluatorInstance\n}\n\n/**\n * Reset the singleton instance (for testing)\n */\nexport function resetEvaluator(): void {\n\tevaluatorInstance?.reset()\n\tevaluatorInstance = null\n}\n","/**\n * Consistent Hashing for Feature Flags\n *\n * Uses MurmurHash3 for fast, consistent bucketing.\n * Ensures users always get the same variant.\n */\n\n// ==========================================\n// MurmurHash3 Implementation\n// ==========================================\n\n/**\n * MurmurHash3 (x86 32-bit)\n *\n * Fast, non-cryptographic hash with excellent distribution.\n * Used by most feature flag systems for consistent bucketing.\n */\nexport function murmurHash3(key: string, seed = 0): number {\n\tconst remainder = key.length & 3 // key.length % 4\n\tconst bytes = key.length - remainder\n\tlet h1 = seed\n\n\tconst c1 = 0xcc9e2d51\n\tconst c2 = 0x1b873593\n\n\tlet i = 0\n\tlet k1: number\n\n\twhile (i < bytes) {\n\t\tk1 =\n\t\t\t(key.charCodeAt(i) & 0xff) |\n\t\t\t((key.charCodeAt(++i) & 0xff) << 8) |\n\t\t\t((key.charCodeAt(++i) & 0xff) << 16) |\n\t\t\t((key.charCodeAt(++i) & 0xff) << 24)\n\t\t++i\n\n\t\tk1 = ((k1 & 0xffff) * c1 + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff\n\t\tk1 = (k1 << 15) | (k1 >>> 17)\n\t\tk1 = ((k1 & 0xffff) * c2 + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff\n\n\t\th1 ^= k1\n\t\th1 = (h1 << 13) | (h1 >>> 19)\n\t\tconst h1b = ((h1 & 0xffff) * 5 + ((((h1 >>> 16) * 5) & 0xffff) << 16)) & 0xffffffff\n\t\th1 = (h1b & 0xffff) + 0x6b64 + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16)\n\t}\n\n\tk1 = 0\n\n\tswitch (remainder) {\n\t\t// biome-ignore lint/suspicious/noFallthroughSwitchClause: MurmurHash3 tail mixing requires intentional fallthrough\n\t\tcase 3:\n\t\t\tk1 ^= (key.charCodeAt(i + 2) & 0xff) << 16\n\t\t// biome-ignore lint/suspicious/noFallthroughSwitchClause: MurmurHash3 tail mixing requires intentional fallthrough\n\t\tcase 2:\n\t\t\tk1 ^= (key.charCodeAt(i + 1) & 0xff) << 8\n\t\t// fallthrough\n\t\tcase 1:\n\t\t\tk1 ^= key.charCodeAt(i) & 0xff\n\t\t\tk1 = ((k1 & 0xffff) * c1 + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff\n\t\t\tk1 = (k1 << 15) | (k1 >>> 17)\n\t\t\tk1 = ((k1 & 0xffff) * c2 + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff\n\t\t\th1 ^= k1\n\t}\n\n\th1 ^= key.length\n\n\th1 ^= h1 >>> 16\n\th1 = ((h1 & 0xffff) * 0x85ebca6b + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff\n\th1 ^= h1 >>> 13\n\th1 = ((h1 & 0xffff) * 0xc2b2ae35 + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16)) & 0xffffffff\n\th1 ^= h1 >>> 16\n\n\treturn h1 >>> 0\n}\n\n// ==========================================\n// Bucketing\n// ==========================================\n\n/**\n * Generate a bucket value (0-99) for consistent assignment\n *\n * @param key - Unique key for bucketing (usually flagKey + userId)\n * @param salt - Optional salt for different distributions\n * @returns Number between 0 and 99\n */\nexport function getBucket(key: string, salt = ''): number {\n\tconst hash = murmurHash3(salt + key)\n\treturn hash % 100\n}\n\n/**\n * Check if a bucket falls within a percentage range\n *\n * @param bucket - Bucket value (0-99)\n * @param percentage - Target percentage (0-100)\n * @returns Whether the bucket is within the percentage\n */\nexport function isInPercentage(bucket: number, percentage: number): boolean {\n\treturn bucket < percentage\n}\n\n/**\n * Get consistent user bucket for a flag\n *\n * Combines userId/anonymousId with flag key and salt for consistent bucketing.\n */\nexport function getUserBucket(\n\tflagKey: string,\n\tuserId: string | undefined,\n\tanonymousId: string | undefined,\n\tsalt = '',\n): number {\n\tconst identifier = userId || anonymousId || 'anonymous'\n\treturn getBucket(`${flagKey}:${identifier}`, salt)\n}\n\n// ==========================================\n// Variant Selection\n// ==========================================\n\ninterface VariantWeight {\n\tkey: string\n\tweight: number\n}\n\n/**\n * Select a variant based on weighted distribution\n *\n * @param variants - Array of variants with weights\n * @param bucket - Bucket value (0-99)\n * @returns Selected variant key\n */\nexport function selectVariant(variants: VariantWeight[], bucket: number): string {\n\tif (variants.length === 0) {\n\t\tthrow new Error('No variants provided')\n\t}\n\n\tif (variants.length === 1) {\n\t\treturn variants[0]!.key\n\t}\n\n\t// Normalize weights to sum to 100\n\tconst totalWeight = variants.reduce((sum, v) => sum + (v.weight ?? 0), 0)\n\tlet normalizedBucket = bucket\n\n\tif (totalWeight !== 100 && totalWeight > 0) {\n\t\t// Scale bucket to match total weight\n\t\tnormalizedBucket = (bucket / 100) * totalWeight\n\t}\n\n\t// Find which variant the bucket falls into\n\tlet cumulative = 0\n\tfor (const variant of variants) {\n\t\tcumulative += variant.weight ?? 0\n\t\tif (normalizedBucket < cumulative) {\n\t\t\treturn variant.key\n\t\t}\n\t}\n\n\t// Fallback to last variant (shouldn't happen with proper weights)\n\treturn variants[variants.length - 1]!.key\n}\n\n/**\n * Generate a consistent random number for a user+flag combination\n *\n * Useful for secondary randomization within rules\n */\nfunction _getConsistentRandom(flagKey: string, userId: string | undefined, seed = ''): number {\n\tconst identifier = userId || 'anonymous'\n\tconst hash = murmurHash3(`${seed}:${flagKey}:${identifier}`)\n\treturn (hash >>> 0) / 0xffffffff // Normalize to 0-1\n}\n","/**\n * Targeting Rules Evaluation\n *\n * Evaluates targeting conditions against user context.\n * Supports various operators for flexible targeting.\n */\n\nimport type {\n\tEvaluationContext,\n\tTargetingCondition,\n\tTargetingOperator,\n\tTargetingRule,\n} from './types'\n\n// ==========================================\n// Condition Evaluation\n// ==========================================\n\n/**\n * Evaluate a single targeting condition\n */\nfunction evaluateCondition(condition: TargetingCondition, context: EvaluationContext): boolean {\n\tconst attributeValue = getAttributeValue(condition.attribute, context)\n\n\t// Handle null/undefined attribute\n\tif (attributeValue === null || attributeValue === undefined) {\n\t\t// Only 'not_in' and 'not_contains' can match when attribute is missing\n\t\tif (condition.operator === 'not_in' || condition.operator === 'not_contains') {\n\t\t\treturn true\n\t\t}\n\t\treturn false\n\t}\n\n\treturn evaluateOperator(condition.operator, attributeValue, condition.value)\n}\n\n/**\n * Evaluate all conditions in a rule (AND logic)\n */\nfunction evaluateRule(rule: TargetingRule, context: EvaluationContext): boolean {\n\tif (rule.conditions.length === 0) {\n\t\treturn true // No conditions = always match\n\t}\n\n\treturn rule.conditions.every((condition) => evaluateCondition(condition, context))\n}\n\n/**\n * Find the first matching rule from a list\n */\nexport function findMatchingRule(\n\trules: TargetingRule[],\n\tcontext: EvaluationContext,\n): TargetingRule | null {\n\tfor (const rule of rules) {\n\t\tif (evaluateRule(rule, context)) {\n\t\t\treturn rule\n\t\t}\n\t}\n\treturn null\n}\n\n// ==========================================\n// Attribute Resolution\n// ==========================================\n\n/**\n * Get attribute value from context using dot notation\n *\n * Supports paths like:\n * - \"userId\"\n * - \"device.type\"\n * - \"attributes.plan\"\n * - \"geo.country\"\n */\nfunction getAttributeValue(path: string, context: EvaluationContext): unknown {\n\t// Handle top-level attributes first\n\tif (path in context && !path.includes('.')) {\n\t\treturn context[path]\n\t}\n\n\t// Handle nested paths\n\tconst parts = path.split('.')\n\tlet value: unknown = context\n\n\tfor (const part of parts) {\n\t\tif (value === null || value === undefined) {\n\t\t\treturn undefined\n\t\t}\n\t\tif (typeof value !== 'object') {\n\t\t\treturn undefined\n\t\t}\n\t\tvalue = (value as Record<string, unknown>)[part]\n\t}\n\n\treturn value\n}\n\n// ==========================================\n// Operator Evaluation\n// ==========================================\n\n/**\n * Evaluate a comparison operator\n */\nfunction evaluateOperator(\n\toperator: TargetingOperator,\n\tactual: unknown,\n\texpected: unknown,\n): boolean {\n\tswitch (operator) {\n\t\tcase 'eq':\n\t\t\treturn equals(actual, expected)\n\n\t\tcase 'neq':\n\t\t\treturn !equals(actual, expected)\n\n\t\tcase 'gt':\n\t\t\treturn compare(actual, expected) > 0\n\n\t\tcase 'gte':\n\t\t\treturn compare(actual, expected) >= 0\n\n\t\tcase 'lt':\n\t\t\treturn compare(actual, expected) < 0\n\n\t\tcase 'lte':\n\t\t\treturn compare(actual, expected) <= 0\n\n\t\tcase 'contains':\n\t\t\treturn contains(actual, expected)\n\n\t\tcase 'not_contains':\n\t\t\treturn !contains(actual, expected)\n\n\t\tcase 'starts_with':\n\t\t\treturn startsWith(actual, expected)\n\n\t\tcase 'ends_with':\n\t\t\treturn endsWith(actual, expected)\n\n\t\tcase 'in':\n\t\t\treturn isIn(actual, expected)\n\n\t\tcase 'not_in':\n\t\t\treturn !isIn(actual, expected)\n\n\t\tcase 'regex':\n\t\t\treturn matchesRegex(actual, expected)\n\n\t\tcase 'semver_gt':\n\t\t\treturn compareSemver(actual, expected) > 0\n\n\t\tcase 'semver_gte':\n\t\t\treturn compareSemver(actual, expected) >= 0\n\n\t\tcase 'semver_lt':\n\t\t\treturn compareSemver(actual, expected) < 0\n\n\t\tcase 'semver_lte':\n\t\t\treturn compareSemver(actual, expected) <= 0\n\n\t\tdefault:\n\t\t\treturn false\n\t}\n}\n\n// ==========================================\n// Comparison Helpers\n// ==========================================\n\nfunction equals(actual: unknown, expected: unknown): boolean {\n\t// Type coercion for common cases\n\tif (typeof actual === 'string' && typeof expected === 'number') {\n\t\treturn actual === String(expected)\n\t}\n\tif (typeof actual === 'number' && typeof expected === 'string') {\n\t\treturn String(actual) === expected\n\t}\n\tif (typeof actual === 'boolean' && typeof expected === 'string') {\n\t\treturn actual === (expected === 'true')\n\t}\n\n\treturn actual === expected\n}\n\nfunction compare(actual: unknown, expected: unknown): number {\n\tconst numActual = Number(actual)\n\tconst numExpected = Number(expected)\n\n\tif (!Number.isNaN(numActual) && !Number.isNaN(numExpected)) {\n\t\treturn numActual - numExpected\n\t}\n\n\t// Fallback to string comparison\n\tconst strActual = String(actual)\n\tconst strExpected = String(expected)\n\treturn strActual.localeCompare(strExpected)\n}\n\nfunction contains(actual: unknown, expected: unknown): boolean {\n\tif (typeof actual === 'string' && typeof expected === 'string') {\n\t\treturn actual.toLowerCase().includes(expected.toLowerCase())\n\t}\n\tif (Array.isArray(actual)) {\n\t\treturn actual.some((item) => equals(item, expected))\n\t}\n\treturn false\n}\n\nfunction startsWith(actual: unknown, expected: unknown): boolean {\n\tif (typeof actual === 'string' && typeof expected === 'string') {\n\t\treturn actual.toLowerCase().startsWith(expected.toLowerCase())\n\t}\n\treturn false\n}\n\nfunction endsWith(actual: unknown, expected: unknown): boolean {\n\tif (typeof actual === 'string' && typeof expected === 'string') {\n\t\treturn actual.toLowerCase().endsWith(expected.toLowerCase())\n\t}\n\treturn false\n}\n\nfunction isIn(actual: unknown, expected: unknown): boolean {\n\tif (!Array.isArray(expected)) {\n\t\treturn false\n\t}\n\treturn expected.some((item) => equals(actual, item))\n}\n\nfunction matchesRegex(actual: unknown, expected: unknown): boolean {\n\tif (typeof actual !== 'string' || typeof expected !== 'string') {\n\t\treturn false\n\t}\n\ttry {\n\t\tconst regex = new RegExp(expected, 'i')\n\t\treturn regex.test(actual)\n\t} catch {\n\t\treturn false\n\t}\n}\n\n// ==========================================\n// Semver Comparison\n// ==========================================\n\ninterface SemverParts {\n\tmajor: number\n\tminor: number\n\tpatch: number\n\tprerelease: string[]\n}\n\nfunction parseSemver(version: unknown): SemverParts | null {\n\tif (typeof version !== 'string') return null\n\n\tconst match = version.match(/^v?(\\d+)\\.(\\d+)\\.(\\d+)(?:-(.+))?$/)\n\tif (!match) return null\n\n\treturn {\n\t\tmajor: Number.parseInt(match[1]!, 10),\n\t\tminor: Number.parseInt(match[2]!, 10),\n\t\tpatch: Number.parseInt(match[3]!, 10),\n\t\tprerelease: match[4] ? match[4].split('.') : [],\n\t}\n}\n\nfunction compareSemver(actual: unknown, expected: unknown): number {\n\tconst actualParts = parseSemver(actual)\n\tconst expectedParts = parseSemver(expected)\n\n\tif (!actualParts || !expectedParts) return 0\n\n\t// Compare major.minor.patch\n\tif (actualParts.major !== expectedParts.major) {\n\t\treturn actualParts.major - expectedParts.major\n\t}\n\tif (actualParts.minor !== expectedParts.minor) {\n\t\treturn actualParts.minor - expectedParts.minor\n\t}\n\tif (actualParts.patch !== expectedParts.patch) {\n\t\treturn actualParts.patch - expectedParts.patch\n\t}\n\n\t// Prerelease versions have lower precedence\n\tif (actualParts.prerelease.length === 0 && expectedParts.prerelease.length > 0) {\n\t\treturn 1 // Actual is release, expected is prerelease\n\t}\n\tif (actualParts.prerelease.length > 0 && expectedParts.prerelease.length === 0) {\n\t\treturn -1 // Actual is prerelease, expected is release\n\t}\n\n\t// Compare prerelease identifiers\n\tconst maxLen = Math.max(actualParts.prerelease.length, expectedParts.prerelease.length)\n\tfor (let i = 0; i < maxLen; i++) {\n\t\tconst actualPre = actualParts.prerelease[i]\n\t\tconst expectedPre = expectedParts.prerelease[i]\n\n\t\tif (actualPre === undefined) return -1\n\t\tif (expectedPre === undefined) return 1\n\n\t\tconst numActual = Number.parseInt(actualPre, 10)\n\t\tconst numExpected = Number.parseInt(expectedPre, 10)\n\n\t\tif (!Number.isNaN(numActual) && !Number.isNaN(numExpected)) {\n\t\t\tif (numActual !== numExpected) return numActual - numExpected\n\t\t} else if (!Number.isNaN(numActual)) {\n\t\t\treturn -1 // Numbers have lower precedence than strings\n\t\t} else if (!Number.isNaN(numExpected)) {\n\t\t\treturn 1\n\t\t} else {\n\t\t\tconst cmp = actualPre.localeCompare(expectedPre)\n\t\t\tif (cmp !== 0) return cmp\n\t\t}\n\t}\n\n\treturn 0\n}\n\n// ==========================================\n// Context Utilities\n// ==========================================\n\n/**\n * Merge context objects, with later objects taking precedence\n */\nexport function mergeContext(...contexts: (EvaluationContext | undefined)[]): EvaluationContext {\n\tconst result: EvaluationContext = {}\n\n\tfor (const ctx of contexts) {\n\t\tif (!ctx) continue\n\n\t\tfor (const [key, value] of Object.entries(ctx)) {\n\t\t\tif (value === undefined) continue\n\n\t\t\tif (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n\t\t\t\t// Deep merge objects\n\t\t\t\tresult[key] = {\n\t\t\t\t\t...(result[key] as Record<string, unknown> | undefined),\n\t\t\t\t\t...value,\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tresult[key] = value\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result\n}\n\n/**\n * Validate that required context fields are present\n */\nfunction _validateContext(context: EvaluationContext): string[] {\n\tconst errors: string[] = []\n\n\t// Must have at least one identifier\n\tif (!context.userId && !context.anonymousId) {\n\t\terrors.push('Context must have either userId or anonymousId for consistent bucketing')\n\t}\n\n\treturn errors\n}\n","/**\n * A/B Testing & Experiments\n *\n * Built on top of feature flags for controlled experiments.\n * Tracks exposures and integrates with analytics.\n */\n\nimport { FLAGS_EXPOSURE_DEDUPE_WINDOW_MS } from '../../constants'\nimport type { LocalEvaluator } from './evaluator'\nimport type { EvaluationContext, EvaluationResult, Experiment, ExperimentExposure } from './types'\n\n// ==========================================\n// Types\n// ==========================================\n\ninterface ExperimentResult {\n\t/** Experiment key */\n\texperimentKey: string\n\t/** Assigned variant */\n\tvariant: string\n\t/** Variant payload (if any) */\n\tpayload?: Record<string, unknown>\n\t/** Whether user is in experiment */\n\tinExperiment: boolean\n\t/** Flag evaluation result */\n\tevaluation: EvaluationResult\n}\n\ninterface ExperimentConfig {\n\t/** Callback for exposure tracking */\n\tonExposure?: (exposure: ExperimentExposure) => void\n\t/** Deduplication window in ms (default: 1 hour) */\n\texposureDedupeWindow?: number\n\t/** Enable debug logging */\n\tdebug?: boolean\n}\n\n// ==========================================\n// Experiment Manager\n// ==========================================\n\n/**\n * Experiment Manager\n *\n * Manages A/B tests built on feature flags.\n * Handles exposure tracking and deduplication.\n */\nexport class ExperimentManager {\n\tprivate evaluator: LocalEvaluator\n\tprivate config: ExperimentConfig\n\tprivate experiments: Map<string, Experiment> = new Map()\n\tprivate exposureCache: Map<string, number> = new Map() // key -> timestamp\n\n\tconstructor(evaluator: LocalEvaluator, config: ExperimentConfig = {}) {\n\t\tthis.evaluator = evaluator\n\t\tthis.config = {\n\t\t\texposureDedupeWindow: FLAGS_EXPOSURE_DEDUPE_WINDOW_MS,\n\t\t\t...config,\n\t\t}\n\t}\n\n\t// ==========================================\n\t// Experiment Management\n\t// ==========================================\n\n\t/**\n\t * Register experiments\n\t */\n\tsetExperiments(experiments: Experiment[]): void {\n\t\tthis.experiments.clear()\n\t\tfor (const exp of experiments) {\n\t\t\tthis.experiments.set(exp.key, exp)\n\t\t}\n\t\tthis.debug('Experiments registered', { count: experiments.length })\n\t}\n\n\t/**\n\t * Get experiment by key\n\t */\n\tgetExperiment(key: string): Experiment | undefined {\n\t\treturn this.experiments.get(key)\n\t}\n\n\t/**\n\t * Get all running experiments\n\t */\n\tgetRunningExperiments(): Experiment[] {\n\t\treturn Array.from(this.experiments.values()).filter((e) => e.status === 'running')\n\t}\n\n\t// ==========================================\n\t// Variant Assignment\n\t// ==========================================\n\n\t/**\n\t * Get variant assignment for an experiment\n\t *\n\t * Automatically tracks exposure if user is in experiment.\n\t */\n\tgetVariant(experimentKey: string, context?: EvaluationContext): ExperimentResult {\n\t\tconst experiment = this.experiments.get(experimentKey)\n\n\t\tif (!experiment) {\n\t\t\treturn {\n\t\t\t\texperimentKey,\n\t\t\t\tvariant: 'control',\n\t\t\t\tinExperiment: false,\n\t\t\t\tevaluation: {\n\t\t\t\t\tvalue: false,\n\t\t\t\t\tvariant: 'control',\n\t\t\t\t\tenabled: false,\n\t\t\t\t\treason: 'error',\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\t// Evaluate the experiment's feature flag\n\t\tconst evaluation = this.evaluator.evaluate<boolean>(experiment.flagKey, false, context)\n\n\t\tconst result: ExperimentResult = {\n\t\t\texperimentKey,\n\t\t\tvariant: evaluation.variant,\n\t\t\tinExperiment: evaluation.enabled && experiment.status === 'running',\n\t\t\tevaluation,\n\t\t}\n\n\t\t// Get variant payload if available\n\t\tconst flag = this.evaluator.getFlag(experiment.flagKey)\n\t\tif (flag) {\n\t\t\tconst variantDef = flag.variants.find((v) => v.key === evaluation.variant)\n\t\t\tif (variantDef?.payload) {\n\t\t\t\tresult.payload = variantDef.payload\n\t\t\t}\n\t\t}\n\n\t\t// Track exposure if in experiment\n\t\tif (result.inExperiment) {\n\t\t\tthis.trackExposure(experiment, result.variant, context)\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Check if user is in experiment variant\n\t */\n\tisInVariant(experimentKey: string, variant: string, context?: EvaluationContext): boolean {\n\t\tconst result = this.getVariant(experimentKey, context)\n\t\treturn result.inExperiment && result.variant === variant\n\t}\n\n\t/**\n\t * Check if user is in treatment (any non-control variant)\n\t */\n\tisInTreatment(experimentKey: string, context?: EvaluationContext): boolean {\n\t\tconst result = this.getVariant(experimentKey, context)\n\t\treturn result.inExperiment && result.variant !== 'control'\n\t}\n\n\t// ==========================================\n\t// Exposure Tracking\n\t// ==========================================\n\n\tprivate trackExposure(\n\t\texperiment: Experiment,\n\t\tvariant: string,\n\t\tcontext?: EvaluationContext,\n\t): void {\n\t\tconst ctx = context ?? this.evaluator.getContext()\n\t\tconst userId = ctx.userId\n\t\tconst anonymousId = ctx.anonymousId\n\n\t\t// Check deduplication\n\t\tconst cacheKey = `${experiment.key}:${userId ?? anonymousId ?? 'anon'}:${variant}`\n\t\tconst lastExposure = this.exposureCache.get(cacheKey)\n\t\tconst now = Date.now()\n\n\t\tif (\n\t\t\tlastExposure &&\n\t\t\tnow - lastExposure < (this.config.exposureDedupeWindow ?? FLAGS_EXPOSURE_DEDUPE_WINDOW_MS)\n\t\t) {\n\t\t\tthis.debug('Exposure deduplicated', {\n\t\t\t\texperimentKey: experiment.key,\n\t\t\t\tvariant,\n\t\t\t})\n\t\t\treturn\n\t\t}\n\n\t\t// Record exposure\n\t\tthis.exposureCache.set(cacheKey, now)\n\n\t\tconst exposure: ExperimentExposure = {\n\t\t\texperimentId: experiment.id,\n\t\t\texperimentKey: experiment.key,\n\t\t\tvariant,\n\t\t\tuserId,\n\t\t\tanonymousId,\n\t\t\ttimestamp: now,\n\t\t\tcontext: ctx.attributes,\n\t\t}\n\n\t\tthis.debug('Exposure tracked', exposure)\n\t\tthis.config.onExposure?.(exposure)\n\t}\n\n\t/**\n\t * Manually track exposure (for deferred exposure tracking)\n\t */\n\ttrackManualExposure(experimentKey: string, variant: string, context?: EvaluationContext): void {\n\t\tconst experiment = this.experiments.get(experimentKey)\n\t\tif (experiment && experiment.status === 'running') {\n\t\t\tthis.trackExposure(experiment, variant, context)\n\t\t}\n\t}\n\n\t// ==========================================\n\t// Utilities\n\t// ==========================================\n\n\t/**\n\t * Clear exposure cache (for testing)\n\t */\n\tclearExposureCache(): void {\n\t\tthis.exposureCache.clear()\n\t}\n\n\t/**\n\t * Get all exposure events (for debugging)\n\t */\n\tgetExposureStats(): {\n\t\texperimentKey: string\n\t\tvariant: string\n\t\ttimestamp: number\n\t}[] {\n\t\tconst stats: {\n\t\t\texperimentKey: string\n\t\t\tvariant: string\n\t\t\ttimestamp: number\n\t\t}[] = []\n\n\t\tfor (const [key, timestamp] of this.exposureCache) {\n\t\t\tconst [experimentKey, , variant] = key.split(':')\n\t\t\tstats.push({\n\t\t\t\texperimentKey: experimentKey!,\n\t\t\t\tvariant: variant!,\n\t\t\t\ttimestamp,\n\t\t\t})\n\t\t}\n\n\t\treturn stats\n\t}\n\n\tprivate debug(message: string, data?: unknown): void {\n\t\tif (this.config.debug) {\n\t\t}\n\t}\n}\n\n// ==========================================\n// Helper Functions\n// ==========================================\n\n/**\n * Create an experiment from a feature flag\n *\n * Convenience function for creating experiment definitions.\n */\nexport function createExperiment(params: {\n\tid: string\n\tkey: string\n\tname: string\n\tflagKey: string\n\thypothesis?: string\n\tmetrics: string[]\n}): Experiment {\n\treturn {\n\t\t...params,\n\t\tstatus: 'draft',\n\t}\n}\n\n/**\n * Calculate experiment sample size\n *\n * Based on:\n * - Baseline conversion rate\n * - Minimum detectable effect (MDE)\n * - Statistical significance (default 95%)\n * - Statistical power (default 80%)\n */\nexport function calculateSampleSize(params: {\n\tbaselineRate: number\n\tminimumEffect: number // relative, e.g., 0.1 = 10% lift\n\tsignificance?: number // default 0.95\n\tpower?: number // default 0.8\n}): number {\n\tconst { baselineRate, minimumEffect, significance = 0.95, power = 0.8 } = params\n\n\t// Z-scores for significance and power\n\tconst zAlpha = significance === 0.95 ? 1.96 : significance === 0.99 ? 2.576 : 1.645\n\tconst zBeta = power === 0.8 ? 0.84 : power === 0.9 ? 1.28 : 0.84\n\n\t// Expected treatment rate\n\tconst treatmentRate = baselineRate * (1 + minimumEffect)\n\n\t// Pooled variance\n\tconst pooledRate = (baselineRate + treatmentRate) / 2\n\tconst variance = 2 * pooledRate * (1 - pooledRate)\n\n\t// Effect size\n\tconst effectSize = Math.abs(treatmentRate - baselineRate)\n\n\t// Sample size per variant\n\tconst n = Math.ceil(((zAlpha + zBeta) ** 2 * variance) / effectSize ** 2)\n\n\treturn n\n}\n\n/**\n * Calculate experiment duration\n *\n * Based on sample size and expected daily traffic.\n */\nexport function calculateExperimentDuration(params: {\n\tsampleSizePerVariant: number\n\tnumberOfVariants: number\n\tdailyVisitors: number\n\ttrafficPercentage?: number // default 100%\n}): number {\n\tconst { sampleSizePerVariant, numberOfVariants, dailyVisitors, trafficPercentage = 100 } = params\n\n\tconst totalSampleNeeded = sampleSizePerVariant * numberOfVariants\n\tconst dailyParticipants = dailyVisitors * (trafficPercentage / 100)\n\n\treturn Math.ceil(totalSampleNeeded / dailyParticipants)\n}\n\n// ==========================================\n// Singleton\n// ==========================================\n\nlet experimentManagerInstance: ExperimentManager | null = null\n\nexport function getExperimentManager(\n\tevaluator: LocalEvaluator,\n\tconfig?: ExperimentConfig,\n): ExperimentManager {\n\tif (!experimentManagerInstance) {\n\t\texperimentManagerInstance = new ExperimentManager(evaluator, config)\n\t}\n\treturn experimentManagerInstance\n}\n\nfunction _resetExperimentManager(): void {\n\texperimentManagerInstance = null\n}\n","/**\n * SSE Streaming for Feature Flags\n *\n * Real-time flag updates via Server-Sent Events.\n * Supports automatic reconnection with exponential backoff.\n */\n\nimport {\n\tFLAGS_HTTP_POLLING_INTERVAL_MS,\n\tFLAGS_STREAM_HEARTBEAT_TIMEOUT_MS,\n\tFLAGS_STREAM_INITIAL_RECONNECT_MS,\n\tFLAGS_STREAM_MAX_RECONNECT_MS,\n} from '../../constants'\nimport type { LocalEvaluator } from './evaluator'\nimport type {\n\tErrorMessage,\n\tFlagClientEvent,\n\tFlagDefinition,\n\tFlagDeleteMessage,\n\tFlagsMessage,\n\tFlagUpdateMessage,\n\tStreamMessage,\n} from './types'\n\n// ==========================================\n// Types\n// ==========================================\n\ntype ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'reconnecting'\n\ninterface StreamingOptions {\n\t/** SSE endpoint */\n\tendpoint: string\n\t/** Environment key for authentication */\n\tenvironmentKey?: string\n\t/** Initial reconnection delay in ms */\n\tinitialReconnectDelay?: number\n\t/** Maximum reconnection delay in ms */\n\tmaxReconnectDelay?: number\n\t/** Maximum reconnection attempts (0 = infinite) */\n\tmaxReconnectAttempts?: number\n\t/** Heartbeat timeout in ms (consider connection dead if no ping) */\n\theartbeatTimeout?: number\n\t/** Debug mode */\n\tdebug?: boolean\n}\n\nconst DEFAULT_STREAMING_OPTIONS: Required<Omit<StreamingOptions, 'endpoint' | 'environmentKey'>> = {\n\tinitialReconnectDelay: FLAGS_STREAM_INITIAL_RECONNECT_MS,\n\tmaxReconnectDelay: FLAGS_STREAM_MAX_RECONNECT_MS,\n\tmaxReconnectAttempts: 0, // Infinite\n\theartbeatTimeout: FLAGS_STREAM_HEARTBEAT_TIMEOUT_MS,\n\tdebug: false,\n}\n\n// ==========================================\n// Flag Stream\n// ==========================================\n\n/**\n * SSE Stream Manager\n *\n * Manages real-time flag updates via Server-Sent Events.\n * Automatically reconnects on disconnection.\n */\nexport class FlagStream {\n\tprivate options: Required<Omit<StreamingOptions, 'environmentKey'>> &\n\t\tPick<StreamingOptions, 'environmentKey'>\n\tprivate evaluator: LocalEvaluator\n\tprivate eventSource: EventSource | null = null\n\tprivate state: ConnectionState = 'disconnected'\n\tprivate reconnectAttempts = 0\n\tprivate reconnectTimeout: ReturnType<typeof setTimeout> | null = null\n\tprivate heartbeatTimeout: ReturnType<typeof setTimeout> | null = null\n\tprivate listeners: Set<(event: FlagClientEvent) => void> = new Set()\n\n\tconstructor(evaluator: LocalEvaluator, options: StreamingOptions) {\n\t\tthis.evaluator = evaluator\n\t\tthis.options = {\n\t\t\t...DEFAULT_STREAMING_OPTIONS,\n\t\t\t...options,\n\t\t}\n\t}\n\n\t// ==========================================\n\t// Connection Management\n\t// ==========================================\n\n\t/**\n\t * Connect to the SSE stream\n\t */\n\tconnect(): void {\n\t\tif (typeof window === 'undefined') return\n\t\tif (this.state === 'connected' || this.state === 'connecting') return\n\n\t\tthis.state = 'connecting'\n\t\tthis.debug('Connecting to stream', { endpoint: this.options.endpoint })\n\n\t\t// Build URL with auth\n\t\tconst url = new URL(this.options.endpoint, window.location.origin)\n\t\tif (this.options.environmentKey) {\n\t\t\turl.searchParams.set('key', this.options.environmentKey)\n\t\t}\n\n\t\ttry {\n\t\t\tthis.eventSource = new EventSource(url.toString())\n\n\t\t\tthis.eventSource.onopen = () => {\n\t\t\t\tthis.state = 'connected'\n\t\t\t\tthis.reconnectAttempts = 0\n\t\t\t\tthis.debug('Connected to stream')\n\t\t\t\tthis.startHeartbeatMonitor()\n\t\t\t}\n\n\t\t\tthis.eventSource.onmessage = (event) => {\n\t\t\t\tthis.handleMessage(event)\n\t\t\t}\n\n\t\t\tthis.eventSource.onerror = (error) => {\n\t\t\t\tthis.debug('Stream error', { error })\n\t\t\t\tthis.handleDisconnect()\n\t\t\t}\n\n\t\t\t// Listen for specific event types\n\t\t\tthis.eventSource.addEventListener('flags', (event) => {\n\t\t\t\tthis.handleFlagsMessage(event)\n\t\t\t})\n\n\t\t\tthis.eventSource.addEventListener('flag_update', (event) => {\n\t\t\t\tthis.handleFlagUpdate(event)\n\t\t\t})\n\n\t\t\tthis.eventSource.addEventListener('flag_delete', (event) => {\n\t\t\t\tthis.handleFlagDelete(event)\n\t\t\t})\n\n\t\t\tthis.eventSource.addEventListener('ping', () => {\n\t\t\t\tthis.resetHeartbeatMonitor()\n\t\t\t})\n\t\t} catch (error) {\n\t\t\tthis.debug('Failed to create EventSource', { error })\n\t\t\tthis.handleDisconnect()\n\t\t}\n\t}\n\n\t/**\n\t * Disconnect from the stream\n\t */\n\tdisconnect(): void {\n\t\tthis.debug('Disconnecting from stream')\n\n\t\tif (this.eventSource) {\n\t\t\tthis.eventSource.close()\n\t\t\tthis.eventSource = null\n\t\t}\n\n\t\tif (this.reconnectTimeout) {\n\t\t\tclearTimeout(this.reconnectTimeout)\n\t\t\tthis.reconnectTimeout = null\n\t\t}\n\n\t\tif (this.heartbeatTimeout) {\n\t\t\tclearTimeout(this.heartbeatTimeout)\n\t\t\tthis.heartbeatTimeout = null\n\t\t}\n\n\t\tthis.state = 'disconnected'\n\t\tthis.reconnectAttempts = 0\n\t}\n\n\t/**\n\t * Get current connection state\n\t */\n\tgetState(): ConnectionState {\n\t\treturn this.state\n\t}\n\n\t/**\n\t * Check if connected\n\t */\n\tisConnected(): boolean {\n\t\treturn this.state === 'connected'\n\t}\n\n\t// ==========================================\n\t// Event Listeners\n\t// ==========================================\n\n\t/**\n\t * Subscribe to flag events\n\t */\n\tsubscribe(listener: (event: FlagClientEvent) => void): () => void {\n\t\tthis.listeners.add(listener)\n\t\treturn () => this.listeners.delete(listener)\n\t}\n\n\tprivate emit(event: FlagClientEvent): void {\n\t\tfor (const listener of this.listeners) {\n\t\t\ttry {\n\t\t\t\tlistener(event)\n\t\t\t} catch (error) {\n\t\t\t\tthis.debug('Listener error', { error })\n\t\t\t}\n\t\t}\n\t}\n\n\t// ==========================================\n\t// Message Handlers\n\t// ==========================================\n\n\tprivate handleMessage(event: MessageEvent): void {\n\t\tthis.resetHeartbeatMonitor()\n\n\t\ttry {\n\t\t\tconst message = JSON.parse(event.data) as StreamMessage\n\n\t\t\tswitch (message.type) {\n\t\t\t\tcase 'flags':\n\t\t\t\t\tthis.handleFlagsData((message as FlagsMessage).data)\n\t\t\t\t\tbreak\n\t\t\t\tcase 'flag_update':\n\t\t\t\t\tthis.handleFlagUpdateData((message as FlagUpdateMessage).data)\n\t\t\t\t\tbreak\n\t\t\t\tcase 'flag_delete':\n\t\t\t\t\tthis.handleFlagDeleteData((message as FlagDeleteMessage).data)\n\t\t\t\t\tbreak\n\t\t\t\tcase 'ping':\n\t\t\t\t\t// Just reset heartbeat (already done above)\n\t\t\t\t\tbreak\n\t\t\t\tcase 'error':\n\t\t\t\t\tthis.emit({ type: 'error', error: (message as ErrorMessage).data })\n\t\t\t\t\tbreak\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.debug('Failed to parse message', { error, data: event.data })\n\t\t}\n\t}\n\n\tprivate handleFlagsMessage(event: MessageEvent): void {\n\t\tthis.resetHeartbeatMonitor()\n\t\ttry {\n\t\t\tconst flags = JSON.parse(event.data) as FlagDefinition[]\n\t\t\tthis.handleFlagsData(flags)\n\t\t} catch (error) {\n\t\t\tthis.debug('Failed to parse flags message', { error })\n\t\t}\n\t}\n\n\tprivate handleFlagsData(flags: FlagDefinition[]): void {\n\t\tthis.evaluator.setFlags(flags)\n\t\tthis.emit({ type: 'ready', flags })\n\t\tthis.debug('Received initial flags', { count: flags.length })\n\t}\n\n\tprivate handleFlagUpdate(event: MessageEvent): void {\n\t\tthis.resetHeartbeatMonitor()\n\t\ttry {\n\t\t\tconst flag = JSON.parse(event.data) as FlagDefinition\n\t\t\tthis.handleFlagUpdateData(flag)\n\t\t} catch (error) {\n\t\t\tthis.debug('Failed to parse flag update', { error })\n\t\t}\n\t}\n\n\tprivate handleFlagUpdateData(flag: FlagDefinition): void {\n\t\tthis.evaluator.updateFlag(flag)\n\t\tthis.emit({ type: 'updated', flags: this.evaluator.getFlags() })\n\t\tthis.debug('Flag updated', { key: flag.key })\n\t}\n\n\tprivate handleFlagDelete(event: MessageEvent): void {\n\t\tthis.resetHeartbeatMonitor()\n\t\ttry {\n\t\t\tconst data = JSON.parse(event.data) as { key: string }\n\t\t\tthis.handleFlagDeleteData(data)\n\t\t} catch (error) {\n\t\t\tthis.debug('Failed to parse flag delete', { error })\n\t\t}\n\t}\n\n\tprivate handleFlagDeleteData(data: { key: string }): void {\n\t\tthis.evaluator.removeFlag(data.key)\n\t\tthis.emit({ type: 'updated', flags: this.evaluator.getFlags() })\n\t\tthis.debug('Flag deleted', { key: data.key })\n\t}\n\n\t// ==========================================\n\t// Reconnection\n\t// ==========================================\n\n\tprivate handleDisconnect(): void {\n\t\tif (this.eventSource) {\n\t\t\tthis.eventSource.close()\n\t\t\tthis.eventSource = null\n\t\t}\n\n\t\tthis.stopHeartbeatMonitor()\n\n\t\tif (\n\t\t\tthis.options.maxReconnectAttempts > 0 &&\n\t\t\tthis.reconnectAttempts >= this.options.maxReconnectAttempts\n\t\t) {\n\t\t\tthis.state = 'disconnected'\n\t\t\tthis.emit({\n\t\t\t\ttype: 'error',\n\t\t\t\terror: {\n\t\t\t\t\tcode: 'NETWORK_ERROR',\n\t\t\t\t\tmessage: 'Max reconnection attempts reached',\n\t\t\t\t},\n\t\t\t})\n\t\t\treturn\n\t\t}\n\n\t\tthis.state = 'reconnecting'\n\t\tthis.scheduleReconnect()\n\t}\n\n\tprivate scheduleReconnect(): void {\n\t\t// Calculate delay with exponential backoff + jitter\n\t\tconst baseDelay = Math.min(\n\t\t\tthis.options.initialReconnectDelay * 2 ** this.reconnectAttempts,\n\t\t\tthis.options.maxReconnectDelay,\n\t\t)\n\t\tconst jitter = Math.random() * baseDelay * 0.3\n\t\tconst delay = Math.floor(baseDelay + jitter)\n\n\t\tthis.debug('Scheduling reconnect', {\n\t\t\tattempt: this.reconnectAttempts + 1,\n\t\t\tdelay,\n\t\t})\n\n\t\tthis.reconnectTimeout = setTimeout(() => {\n\t\t\tthis.reconnectAttempts++\n\t\t\tthis.connect()\n\t\t}, delay)\n\t}\n\n\t// ==========================================\n\t// Heartbeat Monitoring\n\t// ==========================================\n\n\tprivate startHeartbeatMonitor(): void {\n\t\tthis.resetHeartbeatMonitor()\n\t}\n\n\tprivate resetHeartbeatMonitor(): void {\n\t\tif (this.heartbeatTimeout) {\n\t\t\tclearTimeout(this.heartbeatTimeout)\n\t\t}\n\n\t\tthis.heartbeatTimeout = setTimeout(() => {\n\t\t\tthis.debug('Heartbeat timeout - reconnecting')\n\t\t\tthis.emit({ type: 'stale' })\n\t\t\tthis.handleDisconnect()\n\t\t}, this.options.heartbeatTimeout)\n\t}\n\n\tprivate stopHeartbeatMonitor(): void {\n\t\tif (this.heartbeatTimeout) {\n\t\t\tclearTimeout(this.heartbeatTimeout)\n\t\t\tthis.heartbeatTimeout = null\n\t\t}\n\t}\n\n\t// ==========================================\n\t// Utilities\n\t// ==========================================\n\n\tprivate debug(message: string, data?: unknown): void {\n\t\tif (this.options.debug) {\n\t\t}\n\t}\n}\n\n// ==========================================\n// Factory\n// ==========================================\n\n/**\n * Create a flag stream connected to an evaluator\n */\nexport function createFlagStream(evaluator: LocalEvaluator, options: StreamingOptions): FlagStream {\n\treturn new FlagStream(evaluator, options)\n}\n\n// ==========================================\n// HTTP Fetching (Fallback)\n// ==========================================\n\n/**\n * Fetch flags via HTTP (fallback when SSE not available)\n */\nexport async function fetchFlags(\n\tendpoint: string,\n\tenvironmentKey?: string,\n): Promise<FlagDefinition[]> {\n\tconst url = new URL(endpoint)\n\tif (environmentKey) {\n\t\turl.searchParams.set('key', environmentKey)\n\t}\n\n\tconst response = await fetch(url.toString(), {\n\t\theaders: {\n\t\t\tAccept: 'application/json',\n\t\t},\n\t})\n\n\tif (!response.ok) {\n\t\tthrow new Error(`Failed to fetch flags: ${response.status}`)\n\t}\n\n\treturn response.json()\n}\n\n/**\n * Sync flags via HTTP polling\n */\nexport function pollFlags(\n\tevaluator: LocalEvaluator,\n\tendpoint: string,\n\toptions: {\n\t\tenvironmentKey?: string\n\t\tinterval?: number\n\t\tonError?: (error: Error) => void\n\t} = {},\n): () => void {\n\tconst { environmentKey, interval = FLAGS_HTTP_POLLING_INTERVAL_MS, onError } = options\n\n\tconst poll = async () => {\n\t\ttry {\n\t\t\tconst flags = await fetchFlags(endpoint, environmentKey)\n\t\t\tevaluator.setFlags(flags)\n\t\t} catch (error) {\n\t\t\tonError?.(error as Error)\n\t\t}\n\t}\n\n\t// Initial fetch\n\tvoid poll()\n\n\t// Set up polling\n\tconst intervalId = setInterval(poll, interval)\n\n\t// Return cleanup function\n\treturn () => clearInterval(intervalId)\n}\n","/**\n * Feature Flags Types\n *\n * Type definitions for client-side feature flag evaluation.\n * Supports percentage rollouts, user targeting, and A/B testing.\n */\n\nimport {\n\tFLAGS_CACHE_TTL_MS,\n\tFLAGS_STALE_WHILE_REVALIDATE_MS,\n\tFLAGS_STORAGE_KEY,\n} from '../../constants'\n\n// ==========================================\n// Core Types\n// ==========================================\n\n/** Flag value types */\nexport type FlagValue = boolean | string | number | Record<string, unknown> | null\n\n/** Flag value variant */\nexport interface FlagVariant {\n\tkey: string\n\tvalue: FlagValue\n\t/** Percentage weight (0-100) */\n\tweight?: number\n\t/** Optional payload for A/B tests */\n\tpayload?: Record<string, unknown>\n}\n\n/** Targeting operator */\nexport type TargetingOperator =\n\t| 'eq'\n\t| 'neq'\n\t| 'gt'\n\t| 'gte'\n\t| 'lt'\n\t| 'lte'\n\t| 'contains'\n\t| 'not_contains'\n\t| 'starts_with'\n\t| 'ends_with'\n\t| 'in'\n\t| 'not_in'\n\t| 'regex'\n\t| 'semver_gt'\n\t| 'semver_gte'\n\t| 'semver_lt'\n\t| 'semver_lte'\n\n/** Targeting condition */\nexport interface TargetingCondition {\n\tattribute: string\n\toperator: TargetingOperator\n\tvalue: unknown\n}\n\n/** Targeting rule with conditions */\nexport interface TargetingRule {\n\tid: string\n\t/** All conditions must match (AND) */\n\tconditions: TargetingCondition[]\n\t/** Variant to serve if rule matches */\n\tvariant: string\n\t/** Optional percentage rollout within this rule */\n\tpercentage?: number\n}\n\n/** Feature flag definition */\nexport interface FlagDefinition {\n\tkey: string\n\t/** Flag is active */\n\tenabled: boolean\n\t/** Default variant when no rules match */\n\tdefaultVariant: string\n\t/** All possible variants */\n\tvariants: FlagVariant[]\n\t/** Targeting rules (evaluated in order) */\n\trules: TargetingRule[]\n\t/** Optional salt for consistent hashing */\n\tsalt?: string\n\t/** Last updated timestamp */\n\tupdatedAt: number\n\t/** Optional metadata */\n\tmetadata?: Record<string, unknown>\n}\n\n// ==========================================\n// Evaluation Types\n// ==========================================\n\n/** Context for flag evaluation */\nexport interface EvaluationContext {\n\t/** User ID for consistent bucketing */\n\tuserId?: string\n\t/** Anonymous ID for pre-auth bucketing */\n\tanonymousId?: string\n\t/** User email */\n\temail?: string\n\t/** User attributes for targeting */\n\tattributes?: Record<string, unknown>\n\t/** Device/platform info */\n\tdevice?: {\n\t\ttype?: 'mobile' | 'tablet' | 'desktop'\n\t\tos?: string\n\t\tbrowser?: string\n\t}\n\t/** Geographic info */\n\tgeo?: {\n\t\tcountry?: string\n\t\tregion?: string\n\t\tcity?: string\n\t}\n\t/** App version for semver targeting */\n\tappVersion?: string\n\t/** Custom properties */\n\t[key: string]: unknown\n}\n\n/** Evaluation result */\nexport interface EvaluationResult<T = FlagValue> {\n\t/** The evaluated value */\n\tvalue: T\n\t/** Variant key that was selected */\n\tvariant: string\n\t/** Whether the flag is enabled */\n\tenabled: boolean\n\t/** Rule that matched (if any) */\n\tmatchedRule?: string\n\t/** Reason for the evaluation result */\n\treason: EvaluationReason\n\t/** Flag definition version */\n\tversion?: number\n}\n\n/** Why a particular value was returned */\nexport type EvaluationReason =\n\t| 'flag_disabled'\n\t| 'flag_not_found'\n\t| 'default'\n\t| 'default_value'\n\t| 'rule_match'\n\t| 'percentage_rollout'\n\t| 'targeting_match'\n\t| 'error'\n\t| 'cache_hit'\n\t| 'stale'\n\t// Extended reason with debug info\n\t| { rolloutBucket?: number; [key: string]: unknown }\n\n/** Evaluation error */\nexport interface EvaluationError {\n\tcode: 'FLAG_NOT_FOUND' | 'INVALID_CONTEXT' | 'EVALUATION_ERROR' | 'NETWORK_ERROR'\n\tmessage: string\n\tflagKey?: string\n}\n\n// ==========================================\n// A/B Testing Types\n// ==========================================\n\n/** Experiment definition */\nexport interface Experiment {\n\tid: string\n\tkey: string\n\tname: string\n\t/** Feature flag controlling this experiment */\n\tflagKey: string\n\t/** Hypothesis being tested */\n\thypothesis?: string\n\t/** Metric keys to track */\n\tmetrics: string[]\n\t/** Experiment status */\n\tstatus: 'draft' | 'running' | 'paused' | 'concluded'\n\t/** Start/end dates */\n\tstartedAt?: number\n\tendedAt?: number\n\t/** Winning variant (if concluded) */\n\twinner?: string\n}\n\n/** Experiment exposure event */\nexport interface ExperimentExposure {\n\texperimentId: string\n\texperimentKey: string\n\tvariant: string\n\tuserId?: string\n\tanonymousId?: string\n\ttimestamp: number\n\tcontext?: Record<string, unknown>\n}\n\n// ==========================================\n// Streaming Types\n// ==========================================\n\n/** SSE message types */\nexport type StreamMessageType = 'flags' | 'flag_update' | 'flag_delete' | 'ping' | 'error'\n\n/** SSE message */\nexport interface StreamMessage {\n\ttype: StreamMessageType\n\tdata: unknown\n\ttimestamp: number\n}\n\n/** Flag update message */\nexport interface FlagUpdateMessage {\n\ttype: 'flag_update'\n\tdata: FlagDefinition\n\ttimestamp: number\n}\n\n/** Flag delete message */\nexport interface FlagDeleteMessage {\n\ttype: 'flag_delete'\n\tdata: { key: string }\n\ttimestamp: number\n}\n\n/** Initial flags message */\nexport interface FlagsMessage {\n\ttype: 'flags'\n\tdata: FlagDefinition[]\n\ttimestamp: number\n}\n\n/** Error message from stream */\nexport interface ErrorMessage {\n\ttype: 'error'\n\tdata: EvaluationError\n\ttimestamp: number\n}\n\n// ==========================================\n// Configuration\n// ==========================================\n\n/** Feature flags client configuration */\nexport interface FeatureFlagsConfig {\n\t/** API endpoint for fetching flags */\n\tapiEndpoint?: string\n\t/** SSE endpoint for streaming updates */\n\tstreamEndpoint?: string\n\t/** Environment key */\n\tenvironmentKey?: string\n\t/** Cache TTL in ms (default: 5 minutes) */\n\tcacheTtl?: number\n\t/** Stale-while-revalidate window in ms (default: 1 minute) */\n\tstaleWhileRevalidate?: number\n\t/** Enable offline support */\n\tofflineSupport?: boolean\n\t/** localStorage key for persistence */\n\tstorageKey?: string\n\t/** Enable debug logging */\n\tdebug?: boolean\n\t/** Callback when flags are updated */\n\tonFlagsUpdated?: (flags: FlagDefinition[]) => void\n\t/** Callback when evaluation happens */\n\tonEvaluation?: (flagKey: string, result: EvaluationResult) => void\n\t/** Callback for experiment exposures */\n\tonExposure?: (exposure: ExperimentExposure) => void\n\t/** Initial context */\n\tinitialContext?: EvaluationContext\n}\n\n/** Default configuration */\nexport const DEFAULT_FLAGS_CONFIG: Required<\n\tPick<\n\t\tFeatureFlagsConfig,\n\t\t'cacheTtl' | 'staleWhileRevalidate' | 'offlineSupport' | 'storageKey' | 'debug'\n\t>\n> = {\n\tcacheTtl: FLAGS_CACHE_TTL_MS,\n\tstaleWhileRevalidate: FLAGS_STALE_WHILE_REVALIDATE_MS,\n\tofflineSupport: true,\n\tstorageKey: FLAGS_STORAGE_KEY,\n\tdebug: false,\n}\n\n// ==========================================\n// Event Types\n// ==========================================\n\n/** Client events */\nexport type FlagClientEvent =\n\t| { type: 'ready'; flags: FlagDefinition[] }\n\t| { type: 'updated'; flags: FlagDefinition[] }\n\t| { type: 'error'; error: EvaluationError }\n\t| { type: 'stale' }\n\t| { type: 'reconnected' }\n","/**\n * useFlagStatus — Feature flag hook with loading/error state and polling.\n *\n * Complements the simpler `useFlag` (returns `boolean`) from use-flags.tsx by\n * adding explicit loading state, error propagation, and manual refetch.\n *\n * Evaluates via the local `LocalEvaluator` for zero-latency reads, and polls\n * the remote flag service on a configurable interval to stay fresh.\n *\n * @example\n * ```tsx\n * function Banner() {\n *   const { enabled, loading, error, refetch } = useFlagStatus('show-banner', {\n *     userId: user.id,\n *     attributes: { plan: 'pro' },\n *     pollInterval: 60_000,\n *   })\n *\n *   if (loading) return <Skeleton />\n *   if (error)   return <button onClick={refetch}>Retry</button>\n *   return enabled ? <Banner /> : null\n * }\n * ```\n */\n\n'use client'\n\nimport { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'\nimport { SylphxError } from '../../errors'\nimport type { EvaluationContext } from '../../lib/flags/types'\nimport { FeatureFlagsContext } from './use-flags'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface UseFlagStatusOptions {\n\t/** User ID forwarded to the evaluation context */\n\tuserId?: string\n\t/** Custom attributes merged into the evaluation context */\n\tattributes?: Record<string, unknown>\n\t/**\n\t * Polling interval in ms.\n\t * Default: 30 000 (30 s). Set to 0 to disable automatic refresh.\n\t */\n\tpollInterval?: number\n\t/** Full evaluation context override (takes precedence over userId/attributes) */\n\tcontext?: EvaluationContext\n}\n\nexport interface UseFlagStatusResult {\n\t/** Whether the flag is enabled for the current context */\n\tenabled: boolean\n\t/** True on the initial load before any evaluation has completed */\n\tloading: boolean\n\t/** Non-null when the flag service is unreachable */\n\terror: SylphxError | null\n\t/** Manually trigger a remote flag sync and re-evaluate */\n\trefetch: () => Promise<void>\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_POLL_INTERVAL_MS = 30_000\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\n/**\n * Feature flag hook with full loading / error / refetch lifecycle.\n *\n * @param key  - Feature flag key\n * @param options - Evaluation and polling options\n */\nexport function useFlagStatus(key: string, options?: UseFlagStatusOptions): UseFlagStatusResult {\n\tconst {\n\t\tuserId,\n\t\tattributes,\n\t\tpollInterval = DEFAULT_POLL_INTERVAL_MS,\n\t\tcontext: contextOverride,\n\t} = options ?? {}\n\n\tconst ctx = useContext(FeatureFlagsContext)\n\n\tconst [enabled, setEnabled] = useState(false)\n\tconst [loading, setLoading] = useState(!ctx?.isReady)\n\tconst [error, setError] = useState<SylphxError | null>(null)\n\n\tconst mountedRef = useRef(true)\n\n\t// Build evaluation context from options\n\tconst evalContext = useMemo<EvaluationContext | undefined>(() => {\n\t\tif (contextOverride) return contextOverride\n\t\tif (userId || attributes) return { userId, ...attributes }\n\t\treturn undefined\n\t}, [contextOverride, userId, attributes])\n\n\t// Evaluate locally (zero-latency read from cached flags)\n\tconst evaluateLocally = useCallback((): boolean => {\n\t\tif (!ctx?.evaluator) return false\n\t\t// Use evaluate() which supports an optional context override.\n\t\t// evaluate() returns EvaluationResult<T> — pull out .value.\n\t\tconst result = ctx.evaluator.evaluate<boolean>(key, false, evalContext)\n\t\treturn result.value\n\t}, [ctx, key, evalContext])\n\n\t// Re-sync flags from the server (best-effort; local evaluation still works)\n\tconst refetch = useCallback(async (): Promise<void> => {\n\t\tif (!mountedRef.current) return\n\t\tsetError(null)\n\t\ttry {\n\t\t\t// If a FlagStream is connected, trigger reconnect to get fresh flags.\n\t\t\t// For evaluator-only setups, just re-read from local cache.\n\t\t\tif (ctx?.stream) {\n\t\t\t\tctx.stream.connect()\n\t\t\t}\n\t\t\tif (mountedRef.current) {\n\t\t\t\tsetEnabled(evaluateLocally())\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tif (mountedRef.current) {\n\t\t\t\tsetError(\n\t\t\t\t\terr instanceof SylphxError\n\t\t\t\t\t\t? err\n\t\t\t\t\t\t: new SylphxError('Flag refetch failed', { code: 'SERVICE_UNAVAILABLE' }),\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}, [ctx, evaluateLocally])\n\n\t// Initial evaluation once the provider signals isReady\n\tuseEffect(() => {\n\t\tmountedRef.current = true\n\t\treturn () => {\n\t\t\tmountedRef.current = false\n\t\t}\n\t}, [])\n\n\t// Track provider's ready state\n\tuseEffect(() => {\n\t\tif (ctx?.isReady) {\n\t\t\tsetEnabled(evaluateLocally())\n\t\t\tsetLoading(false)\n\t\t} else if (!ctx) {\n\t\t\t// No provider — resolve immediately with default\n\t\t\tsetLoading(false)\n\t\t}\n\t}, [ctx?.isReady, evaluateLocally, ctx])\n\n\t// Re-evaluate whenever flags are updated in the provider (updateVersion increments)\n\tuseEffect(() => {\n\t\tif (!ctx?.isReady) return\n\t\tsetEnabled(evaluateLocally())\n\t}, [evaluateLocally, ctx?.isReady])\n\n\t// Propagate provider errors\n\tuseEffect(() => {\n\t\tif (ctx?.error) {\n\t\t\tsetError(\n\t\t\t\tctx.error instanceof SylphxError\n\t\t\t\t\t? ctx.error\n\t\t\t\t\t: new SylphxError(ctx.error.message, { code: 'SERVICE_UNAVAILABLE' }),\n\t\t\t)\n\t\t}\n\t}, [ctx?.error])\n\n\t// Polling — periodic remote sync\n\tuseEffect(() => {\n\t\tif (!pollInterval || pollInterval <= 0) return\n\n\t\tconst id = setInterval(() => {\n\t\t\tif (mountedRef.current) {\n\t\t\t\trefetch().catch(() => {\n\t\t\t\t\t// Errors surface via the `error` state — no need to throw here\n\t\t\t\t})\n\t\t\t}\n\t\t}, pollInterval)\n\n\t\treturn () => clearInterval(id)\n\t}, [pollInterval, refetch])\n\n\treturn { enabled, loading, error, refetch }\n}\n\n/** Alias for consumers who prefer a descriptive name */\nexport { useFlagStatus as useFlagWithStatus }\n","/**\n * Feature Flags React Hooks (SOTA - State of the Art)\n *\n * Production-grade feature flags with:\n * - SSE streaming for real-time updates\n * - Local evaluation with complex targeting rules\n * - Consistent bucketing for A/B tests\n * - ExperimentManager for experiment tracking\n *\n * ## When to Use This vs Simple Flags\n *\n * USE THIS (SOTA):\n * - Real-time flag updates via SSE streaming\n * - Complex targeting rules and segments\n * - A/B testing with ExperimentManager\n * - Local evaluation with consistent bucketing\n *\n * USE SIMPLE FLAGS (feature-flag-hooks.tsx):\n * - Simple flag checks without complex targeting\n * - Apps that prefer polling over streaming\n * - When React Query is already your data layer\n *\n * @see feature-flag-hooks.tsx for simple polling implementation\n *\n * @example\n * ```tsx\n * // 1. Wrap your app with the provider\n * function App() {\n *   return (\n *     <FeatureFlagsProvider\n *       config={{\n *         streamEndpoint: '/api/flags/stream',\n *       }}\n *       context={{\n *         userId: user?.id,\n *         email: user?.email,\n *       }}\n *     >\n *       <YourApp />\n *     </FeatureFlagsProvider>\n *   )\n * }\n *\n * // 2. Use flags in components\n * function MyComponent() {\n *   const { isEnabled, getString } = useFeatureFlags()\n *\n *   if (isEnabled('new-feature')) {\n *     return <NewFeature />\n *   }\n *\n *   const variant = getString('button-text', 'Click me')\n *   return <button>{variant}</button>\n * }\n *\n * // 3. Or use individual flag hooks\n * function OtherComponent() {\n *   const showBanner = useFlag('show-banner', false)\n *   const theme = useFlagString('theme', 'light')\n *\n *   return showBanner ? <Banner theme={theme} /> : null\n * }\n * ```\n */\n\n'use client'\n\nimport type React from 'react'\nimport { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'\nimport {\n\tcreateFlagStream,\n\ttype ExperimentManager,\n\ttype FlagStream,\n\tgetExperimentManager,\n\tinitFeatureFlags,\n\ttype LocalEvaluator,\n} from '../../lib/flags'\nimport type {\n\tEvaluationContext,\n\tEvaluationResult,\n\tFeatureFlagsConfig,\n\tFlagClientEvent,\n\tFlagDefinition,\n\tFlagValue,\n} from '../../lib/flags/types'\n\n// ==========================================\n// Context Types\n// ==========================================\n\nexport interface FeatureFlagsContextValue {\n\t/** The evaluator instance */\n\tevaluator: LocalEvaluator\n\t/** The stream instance (if streaming enabled) */\n\tstream: FlagStream | null\n\t/** The experiment manager */\n\texperiments: ExperimentManager\n\t/** Whether flags are ready */\n\tisReady: boolean\n\t/** Whether currently loading */\n\tisLoading: boolean\n\t/** Current error (if any) */\n\terror: Error | null\n\t/** All flag definitions */\n\tflags: FlagDefinition[]\n\t/** Update version (increments on flag updates) */\n\tupdateVersion: number\n}\n\nexport const FeatureFlagsContext = createContext<FeatureFlagsContextValue | null>(null)\n\n// ==========================================\n// Provider Props\n// ==========================================\n\nexport interface FeatureFlagsProviderProps {\n\tchildren: React.ReactNode\n\t/** Feature flags configuration */\n\tconfig?: FeatureFlagsConfig\n\t/** Initial evaluation context */\n\tcontext?: EvaluationContext\n\t/** Initial flags (for SSR) */\n\tinitialFlags?: FlagDefinition[]\n\t/** Enable SSE streaming (default: true) */\n\tenableStreaming?: boolean\n\t/** Callback when flags are ready */\n\tonReady?: (flags: FlagDefinition[]) => void\n\t/** Callback on error */\n\tonError?: (error: Error) => void\n}\n\n// ==========================================\n// Provider Component\n// ==========================================\n\n/**\n * Feature Flags Provider\n *\n * Provides feature flag context to your app.\n * Handles initialization, streaming, and context updates.\n */\nexport function FeatureFlagsProvider({\n\tchildren,\n\tconfig = {},\n\tcontext,\n\tinitialFlags,\n\tenableStreaming = true,\n\tonReady,\n\tonError,\n}: FeatureFlagsProviderProps) {\n\tconst [isReady, setIsReady] = useState(!!initialFlags?.length)\n\tconst [isLoading, setIsLoading] = useState(!initialFlags?.length)\n\tconst [error, setError] = useState<Error | null>(null)\n\tconst [updateVersion, setUpdateVersion] = useState(0)\n\n\tconst evaluatorRef = useRef<LocalEvaluator | null>(null)\n\tconst streamRef = useRef<FlagStream | null>(null)\n\tconst experimentsRef = useRef<ExperimentManager | null>(null)\n\n\t// Initialize evaluator\n\tconst handleStreamEvent = useCallback(\n\t\t(event: FlagClientEvent) => {\n\t\t\tswitch (event.type) {\n\t\t\t\tcase 'ready':\n\t\t\t\t\tsetIsReady(true)\n\t\t\t\t\tsetIsLoading(false)\n\t\t\t\t\tsetError(null)\n\t\t\t\t\tonReady?.(event.flags)\n\t\t\t\t\tbreak\n\n\t\t\t\tcase 'updated':\n\t\t\t\t\tsetUpdateVersion((v) => v + 1)\n\t\t\t\t\tbreak\n\n\t\t\t\tcase 'error': {\n\t\t\t\t\tconst err = new Error(event.error.message)\n\t\t\t\t\tsetError(err)\n\t\t\t\t\tonError?.(err)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\n\t\t\t\tcase 'stale':\n\t\t\t\t\t// Could show a warning to user\n\t\t\t\t\tbreak\n\n\t\t\t\tcase 'reconnected':\n\t\t\t\t\tsetError(null)\n\t\t\t\t\tbreak\n\t\t\t}\n\t\t},\n\t\t[onReady, onError],\n\t)\n\n\tuseEffect(() => {\n\t\tif (evaluatorRef.current) return\n\n\t\tconst evaluator = initFeatureFlags({\n\t\t\t...config,\n\t\t\tonFlagsUpdated: (flags) => {\n\t\t\t\tsetUpdateVersion((v) => v + 1)\n\t\t\t\tconfig.onFlagsUpdated?.(flags)\n\t\t\t},\n\t\t})\n\n\t\t// Set initial context\n\t\tif (context) {\n\t\t\tevaluator.setContext(context)\n\t\t}\n\n\t\t// Set initial flags if provided (SSR)\n\t\tif (initialFlags?.length) {\n\t\t\tevaluator.setFlags(initialFlags)\n\t\t}\n\n\t\tevaluatorRef.current = evaluator\n\t\texperimentsRef.current = getExperimentManager(evaluator, {\n\t\t\tonExposure: config.onExposure,\n\t\t\tdebug: config.debug,\n\t\t})\n\n\t\t// Setup streaming if enabled\n\t\tif (enableStreaming && config.streamEndpoint) {\n\t\t\tconst stream = createFlagStream(evaluator, {\n\t\t\t\tendpoint: config.streamEndpoint,\n\t\t\t\tenvironmentKey: config.environmentKey,\n\t\t\t\tdebug: config.debug,\n\t\t\t})\n\n\t\t\tconst unsubscribe = stream.subscribe((event) => {\n\t\t\t\thandleStreamEvent(event)\n\t\t\t})\n\n\t\t\tstream.connect()\n\t\t\tstreamRef.current = stream\n\n\t\t\treturn () => {\n\t\t\t\tunsubscribe()\n\t\t\t\tstream.disconnect()\n\t\t\t}\n\t\t} else {\n\t\t\t// No streaming - just mark as ready\n\t\t\tsetIsReady(true)\n\t\t\tsetIsLoading(false)\n\t\t}\n\t}, [config, context, enableStreaming, handleStreamEvent, initialFlags])\n\n\t// Update context when it changes\n\tuseEffect(() => {\n\t\tif (context && evaluatorRef.current) {\n\t\t\tevaluatorRef.current.setContext(context)\n\t\t}\n\t}, [context])\n\n\t// Handle stream events\n\t// Build context value\n\tconst value = useMemo<FeatureFlagsContextValue>(\n\t\t() => ({\n\t\t\tevaluator: evaluatorRef.current!,\n\t\t\tstream: streamRef.current,\n\t\t\texperiments: experimentsRef.current!,\n\t\t\tisReady,\n\t\t\tisLoading,\n\t\t\terror,\n\t\t\tflags: evaluatorRef.current?.getFlags() ?? [],\n\t\t\tupdateVersion,\n\t\t}),\n\t\t[isReady, isLoading, error, updateVersion],\n\t)\n\n\t// Don't render until evaluator is initialized\n\tif (!evaluatorRef.current) {\n\t\treturn null\n\t}\n\n\treturn <FeatureFlagsContext.Provider value={value}>{children}</FeatureFlagsContext.Provider>\n}\n\n// ==========================================\n// Main Hook\n// ==========================================\n\nexport interface UseFeatureFlagsReturn {\n\t/** Check if a boolean flag is enabled */\n\tisEnabled: (flagKey: string, defaultValue?: boolean) => boolean\n\t/** Get a string flag value */\n\tgetString: (flagKey: string, defaultValue?: string) => string\n\t/** Get a number flag value */\n\tgetNumber: (flagKey: string, defaultValue?: number) => number\n\t/** Get a JSON flag value */\n\tgetJSON: <T extends Record<string, unknown>>(flagKey: string, defaultValue: T) => T\n\t/** Full evaluation with metadata */\n\tevaluate: <T = FlagValue>(\n\t\tflagKey: string,\n\t\tdefaultValue: T,\n\t\tcontextOverride?: EvaluationContext,\n\t) => EvaluationResult<T>\n\t/** Whether flags are ready */\n\tisReady: boolean\n\t/** Whether currently loading */\n\tisLoading: boolean\n\t/** Current error */\n\terror: Error | null\n\t/** All flag definitions */\n\tflags: FlagDefinition[]\n\t/** Update context */\n\tsetContext: (context: EvaluationContext) => void\n\t/** Update context (merge) */\n\tupdateContext: (partial: Partial<EvaluationContext>) => void\n}\n\n/**\n * Main feature flags hook\n *\n * Provides access to flag evaluation and status.\n */\nexport function useFeatureFlags(): UseFeatureFlagsReturn {\n\tconst ctx = useContext(FeatureFlagsContext)\n\n\tif (!ctx) {\n\t\tthrow new Error('useFeatureFlags must be used within a FeatureFlagsProvider')\n\t}\n\n\tconst { evaluator, isReady, isLoading, error, flags, updateVersion } = ctx\n\n\t// Create stable callbacks that re-evaluate when flags update\n\tconst isEnabled = useCallback(\n\t\t(flagKey: string, defaultValue = false) => {\n\t\t\t// updateVersion ensures re-evaluation on flag changes\n\t\t\tvoid updateVersion\n\t\t\treturn evaluator.isEnabled(flagKey, defaultValue)\n\t\t},\n\t\t[evaluator, updateVersion],\n\t)\n\n\tconst getString = useCallback(\n\t\t(flagKey: string, defaultValue = '') => {\n\t\t\tvoid updateVersion\n\t\t\treturn evaluator.getString(flagKey, defaultValue)\n\t\t},\n\t\t[evaluator, updateVersion],\n\t)\n\n\tconst getNumber = useCallback(\n\t\t(flagKey: string, defaultValue = 0) => {\n\t\t\tvoid updateVersion\n\t\t\treturn evaluator.getNumber(flagKey, defaultValue)\n\t\t},\n\t\t[evaluator, updateVersion],\n\t)\n\n\tconst getJSON = useCallback(\n\t\t<T extends Record<string, unknown>>(flagKey: string, defaultValue: T) => {\n\t\t\tvoid updateVersion\n\t\t\treturn evaluator.getJSON(flagKey, defaultValue)\n\t\t},\n\t\t[evaluator, updateVersion],\n\t)\n\n\tconst evaluate = useCallback(\n\t\t<T = FlagValue>(flagKey: string, defaultValue: T, contextOverride?: EvaluationContext) => {\n\t\t\tvoid updateVersion\n\t\t\treturn evaluator.evaluate(flagKey, defaultValue, contextOverride)\n\t\t},\n\t\t[evaluator, updateVersion],\n\t)\n\n\tconst setContext = useCallback(\n\t\t(context: EvaluationContext) => {\n\t\t\tevaluator.setContext(context)\n\t\t},\n\t\t[evaluator],\n\t)\n\n\tconst updateContext = useCallback(\n\t\t(partial: Partial<EvaluationContext>) => {\n\t\t\tevaluator.updateContext(partial)\n\t\t},\n\t\t[evaluator],\n\t)\n\n\treturn {\n\t\tisEnabled,\n\t\tgetString,\n\t\tgetNumber,\n\t\tgetJSON,\n\t\tevaluate,\n\t\tisReady,\n\t\tisLoading,\n\t\terror,\n\t\tflags,\n\t\tsetContext,\n\t\tupdateContext,\n\t}\n}\n\n// ==========================================\n// Individual Flag Hooks\n// ==========================================\n\n/**\n * Hook for a single boolean flag\n */\nexport function useFlag(flagKey: string, defaultValue = false): boolean {\n\t// biome-ignore lint/correctness/noUnusedVariables: triggers re-render on flag changes\n\tconst { isEnabled, updateVersion } = useFeatureFlagsContext()\n\t// Include updateVersion in deps to trigger re-render on flag changes\n\treturn useMemo(() => isEnabled(flagKey, defaultValue), [flagKey, defaultValue, isEnabled])\n}\n\n/**\n * Hook for a single string flag\n */\nexport function useFlagString(flagKey: string, defaultValue = ''): string {\n\t// biome-ignore lint/correctness/noUnusedVariables: triggers re-render on flag changes\n\tconst { getString, updateVersion } = useFeatureFlagsContext()\n\treturn useMemo(() => getString(flagKey, defaultValue), [flagKey, defaultValue, getString])\n}\n\n/**\n * Hook for a single number flag\n */\nexport function useFlagNumber(flagKey: string, defaultValue = 0): number {\n\t// biome-ignore lint/correctness/noUnusedVariables: triggers re-render on flag changes\n\tconst { getNumber, updateVersion } = useFeatureFlagsContext()\n\treturn useMemo(() => getNumber(flagKey, defaultValue), [flagKey, defaultValue, getNumber])\n}\n\n/**\n * Hook for a single JSON flag\n */\nexport function useFlagJSON<T extends Record<string, unknown>>(\n\tflagKey: string,\n\tdefaultValue: T,\n): T {\n\t// biome-ignore lint/correctness/noUnusedVariables: triggers re-render on flag changes\n\tconst { getJSON, updateVersion } = useFeatureFlagsContext()\n\treturn useMemo(() => getJSON(flagKey, defaultValue), [flagKey, defaultValue, getJSON])\n}\n\n/**\n * Hook for full flag evaluation result\n */\nexport function useFlagEvaluation<T = FlagValue>(\n\tflagKey: string,\n\tdefaultValue: T,\n\tcontextOverride?: EvaluationContext,\n): EvaluationResult<T> {\n\t// biome-ignore lint/correctness/noUnusedVariables: triggers re-render on flag changes\n\tconst { evaluate, updateVersion } = useFeatureFlagsContext()\n\treturn useMemo(\n\t\t() => evaluate(flagKey, defaultValue, contextOverride),\n\t\t[flagKey, defaultValue, contextOverride, evaluate],\n\t)\n}\n\n// ==========================================\n// Experiment Hooks\n// ==========================================\n\ninterface UseExperimentReturn {\n\t/** Assigned variant */\n\tvariant: string\n\t/** Whether user is in the experiment */\n\tinExperiment: boolean\n\t/** Variant payload (if any) */\n\tpayload?: Record<string, unknown>\n}\n\n/**\n * Hook for A/B test experiments\n */\nexport function useExperiment(experimentKey: string): UseExperimentReturn {\n\tconst ctx = useContext(FeatureFlagsContext)\n\n\tif (!ctx) {\n\t\tthrow new Error('useExperiment must be used within a FeatureFlagsProvider')\n\t}\n\n\t// biome-ignore lint/correctness/noUnusedVariables: triggers re-render on flag changes\n\tconst { experiments, updateVersion } = ctx\n\n\treturn useMemo(() => {\n\t\tconst result = experiments.getVariant(experimentKey)\n\t\treturn {\n\t\t\tvariant: result.variant,\n\t\t\tinExperiment: result.inExperiment,\n\t\t\tpayload: result.payload,\n\t\t}\n\t}, [experiments, experimentKey])\n}\n\n/**\n * Check if user is in a specific variant\n */\nexport function useIsInVariant(experimentKey: string, variant: string): boolean {\n\tconst { variant: assignedVariant, inExperiment } = useExperiment(experimentKey)\n\treturn inExperiment && assignedVariant === variant\n}\n\n/**\n * Check if user is in treatment (any non-control variant)\n */\nexport function useIsInTreatment(experimentKey: string): boolean {\n\tconst { variant, inExperiment } = useExperiment(experimentKey)\n\treturn inExperiment && variant !== 'control'\n}\n\n// ==========================================\n// Utility Hooks\n// ==========================================\n\n/**\n * Low-level context access (for advanced use)\n */\nfunction useFeatureFlagsContext() {\n\tconst ctx = useContext(FeatureFlagsContext)\n\n\tif (!ctx) {\n\t\tthrow new Error('Feature flags hooks must be used within a FeatureFlagsProvider')\n\t}\n\n\tconst { evaluator, updateVersion } = ctx\n\n\treturn {\n\t\tisEnabled: (key: string, defaultValue: boolean) => evaluator.isEnabled(key, defaultValue),\n\t\tgetString: (key: string, defaultValue: string) => evaluator.getString(key, defaultValue),\n\t\tgetNumber: (key: string, defaultValue: number) => evaluator.getNumber(key, defaultValue),\n\t\tgetJSON: <T extends Record<string, unknown>>(key: string, defaultValue: T) =>\n\t\t\tevaluator.getJSON(key, defaultValue),\n\t\tevaluate: <T = FlagValue>(key: string, defaultValue: T, contextOverride?: EvaluationContext) =>\n\t\t\tevaluator.evaluate(key, defaultValue, contextOverride),\n\t\tupdateVersion,\n\t}\n}\n\n/**\n * Hook to track flag loading state\n */\nexport function useFlagsReady(): {\n\tisReady: boolean\n\tisLoading: boolean\n\terror: Error | null\n} {\n\tconst ctx = useContext(FeatureFlagsContext)\n\n\tif (!ctx) {\n\t\treturn { isReady: false, isLoading: true, error: null }\n\t}\n\n\treturn {\n\t\tisReady: ctx.isReady,\n\t\tisLoading: ctx.isLoading,\n\t\terror: ctx.error,\n\t}\n}\n\n// ==========================================\n// Types Export\n// ==========================================\n","/**\n * Smart Element Naming\n *\n * Generates human-readable names for captured elements.\n * Uses hierarchy of identifiers for stable, meaningful names.\n *\n * Priority:\n * 1. data-analytics / data-track attribute\n * 2. aria-label\n * 3. id\n * 4. name\n * 5. Text content\n * 6. Placeholder / value\n * 7. Generated from hierarchy\n */\n\nimport type { ElementData } from './types'\n\n// ==========================================\n// Name Generation\n// ==========================================\n\n/**\n * Generate a human-readable name for an element\n *\n * @param element - Element to name\n * @param ancestors - Parent elements (for context)\n * @returns Human-readable name\n */\nexport function generateElementName(element: Element, ancestors?: Element[]): string {\n\t// 1. Explicit analytics attribute\n\tconst analyticsName = getAnalyticsAttribute(element)\n\tif (analyticsName) return analyticsName\n\n\t// 2. ARIA label\n\tconst ariaLabel = element.getAttribute('aria-label')\n\tif (ariaLabel) return sanitizeText(ariaLabel)\n\n\t// 3. ID (if meaningful)\n\tconst id = element.id\n\tif (id && isMeaningfulId(id)) return humanizeId(id)\n\n\t// 4. Name attribute\n\tconst name = element.getAttribute('name')\n\tif (name) return humanizeName(name)\n\n\t// 5. Text content\n\tconst text = getVisibleText(element)\n\tif (text) return sanitizeText(text)\n\n\t// 6. Placeholder / value\n\tconst placeholder = element.getAttribute('placeholder')\n\tif (placeholder) return `${getElementType(element)} - ${sanitizeText(placeholder)}`\n\n\tconst value = (element as HTMLInputElement).value\n\tif (value && element.tagName === 'BUTTON') return sanitizeText(value)\n\n\t// 7. Build from context\n\treturn generateContextualName(element, ancestors)\n}\n\n/**\n * Generate an event name from element interaction\n *\n * @param element - Interacted element\n * @param eventType - Type of interaction\n * @returns Event name\n */\nexport function generateEventName(element: Element, eventType: string): string {\n\tconst elementName = generateElementName(element)\n\tconst action = getActionVerb(eventType, element)\n\n\t// Clean up the element name for event naming\n\tconst cleanName = elementName\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9\\s-]/g, '')\n\t\t.replace(/\\s+/g, '_')\n\t\t.replace(/-+/g, '_')\n\t\t.replace(/^_+|_+$/g, '')\n\n\t// Format: action_element\n\t// e.g., \"clicked_signup_button\", \"submitted_contact_form\", \"changed_email_input\"\n\treturn `${action}_${cleanName}`\n}\n\n// ==========================================\n// Attribute Helpers\n// ==========================================\n\nfunction getAnalyticsAttribute(element: Element): string | null {\n\t// Check various analytics attributes\n\tconst attrs = [\n\t\t'data-analytics',\n\t\t'data-track',\n\t\t'data-event',\n\t\t'data-analytics-id',\n\t\t'data-testid', // Often meaningful for analytics\n\t]\n\n\tfor (const attr of attrs) {\n\t\tconst value = element.getAttribute(attr)\n\t\tif (value) return value\n\t}\n\n\treturn null\n}\n\nfunction isMeaningfulId(id: string): boolean {\n\t// Filter out auto-generated IDs\n\tif (/^[a-f0-9]{8,}$/i.test(id)) return false // UUID-like\n\tif (/^:r[0-9]+:$/i.test(id)) return false // React auto-generated\n\tif (/^[a-z]+-[0-9]+$/i.test(id)) return false // component-123 pattern\n\tif (/^radix-/.test(id)) return false // Radix UI auto IDs\n\tif (/^headlessui-/.test(id)) return false // Headless UI auto IDs\n\tif (id.length > 50) return false // Too long = probably generated\n\n\treturn true\n}\n\nfunction humanizeId(id: string): string {\n\t// Convert camelCase/snake_case/kebab-case to readable text\n\treturn id\n\t\t.replace(/([a-z])([A-Z])/g, '$1 $2')\n\t\t.replace(/[_-]/g, ' ')\n\t\t.replace(/\\s+/g, ' ')\n\t\t.trim()\n}\n\nfunction humanizeName(name: string): string {\n\t// Similar to humanizeId but for form field names\n\treturn name\n\t\t.replace(/\\[\\]/g, '') // Remove array notation\n\t\t.replace(/\\[(\\d+)\\]/g, ' $1') // Convert [0] to 0\n\t\t.replace(/([a-z])([A-Z])/g, '$1 $2')\n\t\t.replace(/[_-]/g, ' ')\n\t\t.replace(/\\s+/g, ' ')\n\t\t.trim()\n}\n\n// ==========================================\n// Text Extraction\n// ==========================================\n\nfunction getVisibleText(element: Element): string | null {\n\t// For buttons, links, etc. - get the visible text\n\tconst tagName = element.tagName.toLowerCase()\n\n\t// For inputs, get label text\n\tif (tagName === 'input' || tagName === 'select' || tagName === 'textarea') {\n\t\treturn getLabelText(element as HTMLInputElement)\n\t}\n\n\t// For other elements, get direct text content\n\tlet text = ''\n\n\tconst childNodes = Array.from(element.childNodes)\n\tfor (const node of childNodes) {\n\t\tif (node.nodeType === Node.TEXT_NODE) {\n\t\t\ttext += node.textContent?.trim() || ''\n\t\t}\n\t}\n\n\t// If no direct text, try innerText but limited\n\tif (!text) {\n\t\tconst innerText = (element as HTMLElement).innerText\n\t\tif (innerText && innerText.length < 100) {\n\t\t\ttext = innerText.trim()\n\t\t}\n\t}\n\n\treturn text || null\n}\n\nfunction getLabelText(input: HTMLInputElement): string | null {\n\t// 1. Check for explicit label\n\tconst id = input.id\n\tif (id) {\n\t\tconst label = document.querySelector(`label[for=\"${id}\"]`)\n\t\tif (label) return (label as HTMLElement).innerText?.trim() || null\n\t}\n\n\t// 2. Check for wrapping label\n\tconst parentLabel = input.closest('label')\n\tif (parentLabel) {\n\t\tconst labelText = parentLabel.innerText?.trim()\n\t\tif (labelText) return labelText\n\t}\n\n\t// 3. Check for aria-labelledby\n\tconst labelledBy = input.getAttribute('aria-labelledby')\n\tif (labelledBy) {\n\t\tconst label = document.getElementById(labelledBy)\n\t\tif (label) return label.innerText?.trim() || null\n\t}\n\n\treturn null\n}\n\n// ==========================================\n// Context Generation\n// ==========================================\n\nfunction generateContextualName(element: Element, ancestors?: Element[]): string {\n\tconst _tagName = element.tagName.toLowerCase()\n\tconst type = getElementType(element)\n\n\t// Try to find context from ancestors\n\tif (ancestors && ancestors.length > 0) {\n\t\tfor (const ancestor of ancestors) {\n\t\t\tconst ancestorName = getContextFromAncestor(ancestor)\n\t\t\tif (ancestorName) {\n\t\t\t\treturn `${type} in ${ancestorName}`\n\t\t\t}\n\t\t}\n\t}\n\n\t// Try to find context from surrounding elements\n\tconst form = element.closest('form')\n\tif (form) {\n\t\tconst formName = getFormName(form)\n\t\tif (formName) {\n\t\t\treturn `${type} in ${formName}`\n\t\t}\n\t}\n\n\tconst section = element.closest('section, article, aside, nav, header, footer, main')\n\tif (section) {\n\t\tconst sectionName = getSectionName(section)\n\t\tif (sectionName) {\n\t\t\treturn `${type} in ${sectionName}`\n\t\t}\n\t}\n\n\t// Fallback to just the type with position\n\tconst index = getElementIndex(element)\n\tif (index > 0) {\n\t\treturn `${type} ${index}`\n\t}\n\n\treturn type\n}\n\nfunction getContextFromAncestor(ancestor: Element): string | null {\n\tconst analyticsName = getAnalyticsAttribute(ancestor)\n\tif (analyticsName) return analyticsName\n\n\tconst ariaLabel = ancestor.getAttribute('aria-label')\n\tif (ariaLabel) return sanitizeText(ariaLabel)\n\n\tconst id = ancestor.id\n\tif (id && isMeaningfulId(id)) return humanizeId(id)\n\n\treturn null\n}\n\nfunction getFormName(form: HTMLFormElement): string | null {\n\tconst name = form.getAttribute('name')\n\tif (name) return `${humanizeName(name)} form`\n\n\tconst id = form.id\n\tif (id && isMeaningfulId(id)) return `${humanizeId(id)} form`\n\n\tconst ariaLabel = form.getAttribute('aria-label')\n\tif (ariaLabel) return `${sanitizeText(ariaLabel)} form`\n\n\t// Try to infer from heading or legend\n\tconst legend = form.querySelector('legend')\n\tif (legend) return `${sanitizeText(legend.innerText)} form`\n\n\tconst heading = form.querySelector('h1, h2, h3, h4, h5, h6')\n\tif (heading) return `${sanitizeText((heading as HTMLElement).innerText)} form`\n\n\treturn 'form'\n}\n\nfunction getSectionName(section: Element): string | null {\n\tconst ariaLabel = section.getAttribute('aria-label')\n\tif (ariaLabel) return sanitizeText(ariaLabel)\n\n\tconst id = section.id\n\tif (id && isMeaningfulId(id)) return humanizeId(id)\n\n\tconst role = section.getAttribute('role')\n\tif (role) return role\n\n\tconst heading = section.querySelector('h1, h2, h3, h4, h5, h6')\n\tif (heading) return sanitizeText((heading as HTMLElement).innerText)\n\n\treturn section.tagName.toLowerCase()\n}\n\n// ==========================================\n// Element Type Helpers\n// ==========================================\n\nfunction getElementType(element: Element): string {\n\tconst tagName = element.tagName.toLowerCase()\n\tconst type = element.getAttribute('type')\n\tconst role = element.getAttribute('role')\n\n\t// Role-based naming\n\tif (role) {\n\t\tconst roleMap: Record<string, string> = {\n\t\t\tbutton: 'button',\n\t\t\tlink: 'link',\n\t\t\tcheckbox: 'checkbox',\n\t\t\tradio: 'radio',\n\t\t\tswitch: 'switch',\n\t\t\ttab: 'tab',\n\t\t\tmenuitem: 'menu item',\n\t\t\toption: 'option',\n\t\t\ttextbox: 'input',\n\t\t\tsearchbox: 'search',\n\t\t\tcombobox: 'dropdown',\n\t\t\tlistbox: 'list',\n\t\t\tslider: 'slider',\n\t\t}\n\t\tif (roleMap[role]) return roleMap[role]\n\t}\n\n\t// Tag-based naming\n\tconst tagMap: Record<string, string> = {\n\t\ta: 'link',\n\t\tbutton: 'button',\n\t\tselect: 'dropdown',\n\t\ttextarea: 'text area',\n\t\timg: 'image',\n\t\tvideo: 'video',\n\t\taudio: 'audio',\n\t}\n\tif (tagMap[tagName]) return tagMap[tagName]\n\n\t// Input type-based naming\n\tif (tagName === 'input') {\n\t\tconst typeMap: Record<string, string> = {\n\t\t\tsubmit: 'submit button',\n\t\t\tbutton: 'button',\n\t\t\tcheckbox: 'checkbox',\n\t\t\tradio: 'radio',\n\t\t\ttext: 'text input',\n\t\t\temail: 'email input',\n\t\t\tpassword: 'password input',\n\t\t\tsearch: 'search input',\n\t\t\ttel: 'phone input',\n\t\t\turl: 'URL input',\n\t\t\tnumber: 'number input',\n\t\t\tdate: 'date input',\n\t\t\ttime: 'time input',\n\t\t\tfile: 'file input',\n\t\t\tcolor: 'color picker',\n\t\t\trange: 'slider',\n\t\t}\n\t\treturn typeMap[type || ''] || 'input'\n\t}\n\n\treturn tagName\n}\n\nfunction getActionVerb(eventType: string, element: Element): string {\n\tconst tagName = element.tagName.toLowerCase()\n\tconst type = element.getAttribute('type')\n\n\t// Event type based\n\tconst actionMap: Record<string, string> = {\n\t\tclick: 'clicked',\n\t\tsubmit: 'submitted',\n\t\tchange: 'changed',\n\t\tfocus: 'focused',\n\t\tblur: 'left',\n\t\tinput: 'updated',\n\t}\n\n\t// Special cases for toggle elements\n\tif (eventType === 'change') {\n\t\tif (tagName === 'input' && (type === 'checkbox' || type === 'radio')) {\n\t\t\treturn 'toggled'\n\t\t}\n\t\tif (tagName === 'select') {\n\t\t\treturn 'selected'\n\t\t}\n\t}\n\n\treturn actionMap[eventType] || eventType\n}\n\nfunction getElementIndex(element: Element): number {\n\tconst parent = element.parentElement\n\tif (!parent) return 0\n\n\tconst siblings = Array.from(parent.children).filter((child) => child.tagName === element.tagName)\n\n\tif (siblings.length <= 1) return 0\n\treturn siblings.indexOf(element) + 1\n}\n\n// ==========================================\n// Text Sanitization\n// ==========================================\n\nfunction sanitizeText(text: string): string {\n\treturn text\n\t\t.replace(/\\s+/g, ' ')\n\t\t.trim()\n\t\t.slice(0, 100) // Limit length\n\t\t.replace(/[<>]/g, '') // Remove potential HTML\n}\n\n// ==========================================\n// Element Data Builder\n// ==========================================\n\n/**\n * Build element data from a DOM element\n */\nexport function buildElementData(element: Element): ElementData {\n\tconst data: ElementData = {\n\t\ttag_name: element.tagName.toLowerCase(),\n\t}\n\n\t// Text content\n\tconst text = getVisibleText(element)\n\tif (text) {\n\t\tdata.$el_text = sanitizeText(text)\n\t}\n\n\t// Standard attributes\n\tconst attrs = [\n\t\t'id',\n\t\t'class',\n\t\t'href',\n\t\t'name',\n\t\t'type',\n\t\t'value',\n\t\t'placeholder',\n\t\t'role',\n\t\t'aria-label',\n\t\t'data-testid',\n\t\t'data-analytics',\n\t]\n\n\tfor (const attr of attrs) {\n\t\tconst value = element.getAttribute(attr)\n\t\tif (value) {\n\t\t\tconst key = `attr__${attr.replace(/-/g, '_')}` as `attr__${string}`\n\t\t\tdata[key] = value.slice(0, 200) // Limit attribute length\n\t\t}\n\t}\n\n\t// Position in parent\n\tconst parent = element.parentElement\n\tif (parent) {\n\t\tconst siblings = Array.from(parent.children)\n\t\tconst sameTagSiblings = siblings.filter((s) => s.tagName === element.tagName)\n\n\t\tdata.nth_child = siblings.indexOf(element) + 1\n\t\tif (sameTagSiblings.length > 1) {\n\t\t\tdata.nth_of_type = sameTagSiblings.indexOf(element) + 1\n\t\t}\n\t}\n\n\treturn data\n}\n\n/**\n * Build element chain (element + ancestors)\n */\nexport function buildElementChain(element: Element, maxDepth = 5): ElementData[] {\n\tconst chain: ElementData[] = []\n\tlet current: Element | null = element\n\tlet depth = 0\n\n\twhile (current && depth < maxDepth) {\n\t\t// Skip html and body\n\t\tif (current.tagName === 'HTML' || current.tagName === 'BODY') {\n\t\t\tbreak\n\t\t}\n\n\t\tchain.push(buildElementData(current))\n\t\tcurrent = current.parentElement\n\t\tdepth++\n\t}\n\n\treturn chain\n}\n","/**\n * Analytics Types\n *\n * Type definitions for client-side analytics.\n * PostHog-compatible event format with smart autocapture.\n */\n\nimport {\n\tANALYTICS_FLUSH_INTERVAL_MS,\n\tANALYTICS_SESSION_KEY,\n\tANALYTICS_SESSION_TIMEOUT_MS,\n\tSDK_API_PATH,\n} from '../../constants'\n\n// ==========================================\n// Core Types\n// ==========================================\n\n/** Event property value types */\nexport type PropertyValue =\n\t| string\n\t| number\n\t| boolean\n\t| null\n\t| undefined\n\t| PropertyValue[]\n\t| { [key: string]: PropertyValue }\n\n/** Event properties */\nexport type EventProperties = Record<string, PropertyValue>\n\n/** User properties */\nexport type UserProperties = Record<string, PropertyValue>\n\n/** Group properties */\nexport type GroupProperties = Record<string, PropertyValue>\n\n// ==========================================\n// Event Types\n// ==========================================\n\n/** Standard event (from PostHog) */\nexport interface AnalyticsEvent {\n\t/** Event name */\n\tevent: string\n\t/** Event properties */\n\tproperties: EventProperties\n\t/** User distinct ID */\n\tdistinct_id: string\n\t/** Timestamp (ISO 8601) */\n\ttimestamp: string\n\t/** Library info */\n\t$lib?: string\n\t$lib_version?: string\n\t/** Set user properties */\n\t$set?: UserProperties\n\t/** Set user properties once */\n\t$set_once?: UserProperties\n}\n\n/** Autocaptured event */\nexport interface AutocaptureEvent extends AnalyticsEvent {\n\tevent: '$autocapture'\n\tproperties: EventProperties & {\n\t\t$event_type: 'click' | 'submit' | 'change' | 'focus' | 'blur'\n\t\t$elements: ElementData[]\n\t\t$element_name?: string\n\t\t$element_text?: string\n\t\t$element_href?: string\n\t}\n}\n\n/** Page view event */\nexport interface PageViewEvent extends AnalyticsEvent {\n\tevent: '$pageview'\n\tproperties: EventProperties & {\n\t\t$current_url: string\n\t\t$host: string\n\t\t$pathname: string\n\t\t$referrer?: string\n\t\t$referring_domain?: string\n\t}\n}\n\n/** Page leave event */\nexport interface PageLeaveEvent extends AnalyticsEvent {\n\tevent: '$pageleave'\n\tproperties: EventProperties & {\n\t\t$current_url: string\n\t\t$time_on_page?: number\n\t\t$scroll_depth?: number\n\t}\n}\n\n// ==========================================\n// Element Data\n// ==========================================\n\n/** Captured element data */\nexport interface ElementData {\n\ttag_name: string\n\t$el_text?: string\n\tattr__id?: string\n\tattr__class?: string\n\tattr__href?: string\n\tattr__name?: string\n\tattr__type?: string\n\tattr__value?: string\n\tattr__placeholder?: string\n\tattr__role?: string\n\tattr__aria_label?: string\n\tattr__data_testid?: string\n\tattr__data_analytics?: string\n\tnth_child?: number\n\tnth_of_type?: number\n\t[key: `attr__${string}`]: string | undefined\n}\n\n// ==========================================\n// Configuration\n// ==========================================\n\n/** Analytics configuration */\nexport interface AnalyticsConfig {\n\t/** API endpoint */\n\tapiEndpoint?: string\n\t/** API key (optional, for server-side validation) */\n\tapiKey?: string\n\t/** Enable autocapture */\n\tautocapture?: boolean | AutocaptureConfig\n\t/** Enable pageview tracking */\n\tcapturePageviews?: boolean\n\t/** Enable SPA navigation tracking */\n\tcaptureSpaNavigation?: boolean\n\t/** Enable page leave tracking */\n\tcapturePageleave?: boolean\n\t/** Enable scroll depth tracking */\n\tcaptureScrollDepth?: boolean\n\t/** Enable form tracking */\n\tcaptureForms?: boolean\n\t/** Enable error tracking */\n\tcaptureErrors?: boolean\n\t/** Capture UTM parameters */\n\tcaptureUtm?: boolean\n\t/** Capture referrer */\n\tcaptureReferrer?: boolean\n\t/** Capture device info */\n\tcaptureDevice?: boolean\n\t/** Session ID cookie name */\n\tsessionCookieName?: string\n\t/** Session timeout in ms (default: 30 min) */\n\tsessionTimeout?: number\n\t/** Properties to add to every event */\n\tdefaultProperties?: EventProperties\n\t/** Properties to never capture */\n\tpropertyDenylist?: string[]\n\t/** Sanitize properties before sending */\n\tsanitize?: (properties: EventProperties) => EventProperties\n\t/** Called before sending events */\n\tbeforeSend?: (event: AnalyticsEvent) => AnalyticsEvent | null\n\t/** Enable debug logging */\n\tdebug?: boolean\n\t/** Batch events */\n\tbatchSize?: number\n\t/** Batch flush interval in ms */\n\tflushInterval?: number\n\t/**\n\t * Enable persistence\n\t *\n\t * Note: sessionStorage is NOT supported (data lost on tab close = lost analytics).\n\t * Use localStorage for persistent identity or 'none' for ephemeral sessions.\n\t */\n\tpersistence?: 'localStorage' | 'cookie' | 'none'\n}\n\n/** Autocapture configuration */\nexport interface AutocaptureConfig {\n\t/** CSS selectors to capture */\n\tincludeSelectors?: string[]\n\t/** CSS selectors to exclude */\n\texcludeSelectors?: string[]\n\t/** Capture text content */\n\tcaptureText?: boolean\n\t/** Max text length */\n\tmaxTextLength?: number\n\t/** Capture attributes */\n\tcaptureAttributes?: string[]\n\t/** Elements to include (default: button, a, input, select, textarea) */\n\telements?: string[]\n\t/** Event types to capture */\n\teventTypes?: ('click' | 'submit' | 'change' | 'focus' | 'blur')[]\n}\n\n/** Default configuration */\nexport const DEFAULT_ANALYTICS_CONFIG: AnalyticsConfig = {\n\tapiEndpoint: `${SDK_API_PATH}/analytics/track`,\n\tautocapture: true,\n\tcapturePageviews: true,\n\tcaptureSpaNavigation: true,\n\tcapturePageleave: true,\n\tcaptureScrollDepth: true,\n\tcaptureForms: true,\n\tcaptureErrors: false, // Use error-tracking module instead\n\tcaptureUtm: true,\n\tcaptureReferrer: true,\n\tcaptureDevice: true,\n\tsessionCookieName: ANALYTICS_SESSION_KEY,\n\tsessionTimeout: ANALYTICS_SESSION_TIMEOUT_MS, // 30 minutes\n\tdebug: false,\n\tbatchSize: 10,\n\tflushInterval: ANALYTICS_FLUSH_INTERVAL_MS,\n\tpersistence: 'localStorage',\n}\n\n/** Default autocapture configuration */\nexport const DEFAULT_AUTOCAPTURE_CONFIG: AutocaptureConfig = {\n\tcaptureText: true,\n\tmaxTextLength: 100,\n\tcaptureAttributes: [\n\t\t'id',\n\t\t'class',\n\t\t'href',\n\t\t'name',\n\t\t'type',\n\t\t'role',\n\t\t'aria-label',\n\t\t'data-testid',\n\t\t'data-analytics',\n\t\t'data-track',\n\t],\n\telements: ['button', 'a', 'input', 'select', 'textarea', '[role=\"button\"]', '[data-track]'],\n\teventTypes: ['click', 'submit', 'change'],\n}\n\n// ==========================================\n// UTM & Attribution\n// ==========================================\n\n/** UTM parameters */\nexport interface UtmParams {\n\tutm_source?: string\n\tutm_medium?: string\n\tutm_campaign?: string\n\tutm_term?: string\n\tutm_content?: string\n}\n\n/** Referrer data */\nexport interface ReferrerData {\n\t$referrer?: string\n\t$referring_domain?: string\n\t$referrer_source?: 'organic' | 'social' | 'paid' | 'email' | 'direct' | 'unknown'\n}\n\n/** Attribution data */\nexport interface AttributionData extends UtmParams, ReferrerData {\n\t$initial_referrer?: string\n\t$initial_referring_domain?: string\n\t$initial_utm_source?: string\n\t$initial_utm_medium?: string\n\t$initial_utm_campaign?: string\n}\n\n// ==========================================\n// Device & Context\n// ==========================================\n\n/** Device context */\nexport interface DeviceContext {\n\t$device_type?: 'Desktop' | 'Mobile' | 'Tablet' | 'Bot'\n\t$os?: string\n\t$os_version?: string\n\t$browser?: string\n\t$browser_version?: string\n\t$browser_language?: string\n\t$screen_height?: number\n\t$screen_width?: number\n\t$viewport_height?: number\n\t$viewport_width?: number\n\t$device_pixel_ratio?: number\n\t$timezone?: string\n}\n\n/** Page context */\nexport interface PageContext {\n\t$current_url: string\n\t$host: string\n\t$pathname: string\n\t$search?: string\n\t$hash?: string\n\t$title?: string\n}\n\n// ==========================================\n// Queue & Batch\n// ==========================================\n\n/** Queued event */\nexport interface QueuedEvent {\n\tevent: AnalyticsEvent\n\ttimestamp: number\n\tretries: number\n\t/** Unix timestamp when this event can be retried (exponential backoff) */\n\tnextRetryAt?: number\n}\n\n// ==========================================\n// User-Agent Client Hints API Types\n// ==========================================\n\n/**\n * Brand info from User-Agent Client Hints API\n * @see https://developer.mozilla.org/en-US/docs/Web/API/NavigatorUAData/brands\n */\nexport interface UABrand {\n\tbrand: string\n\tversion: string\n}\n\n/**\n * Low-entropy hints from User-Agent Client Hints API\n * Available synchronously without permission\n * @see https://developer.mozilla.org/en-US/docs/Web/API/NavigatorUAData\n */\nexport interface NavigatorUAData {\n\t/** Array of brand/version objects */\n\tbrands: UABrand[]\n\t/** Whether device is mobile */\n\tmobile: boolean\n\t/** Operating system name */\n\tplatform: string\n\t/**\n\t * Get high-entropy values (requires permission on some platforms)\n\t * @see https://developer.mozilla.org/en-US/docs/Web/API/NavigatorUAData/getHighEntropyValues\n\t */\n\tgetHighEntropyValues?: (hints: string[]) => Promise<UAHighEntropyValues>\n}\n\n/**\n * High-entropy hints from User-Agent Client Hints API\n * Requires explicit permission or Permissions-Policy header\n */\nexport interface UAHighEntropyValues {\n\tarchitecture?: string\n\tbitness?: string\n\tbrands?: UABrand[]\n\tfullVersionList?: UABrand[]\n\tmobile?: boolean\n\tmodel?: string\n\tplatform?: string\n\tplatformVersion?: string\n\tuaFullVersion?: string\n}\n\n/**\n * Navigator with User-Agent Client Hints API\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgentData\n */\nexport interface NavigatorWithUAData extends Navigator {\n\tuserAgentData?: NavigatorUAData\n}\n","/**\n * Smart Autocapture\n *\n * Automatic event capture with intelligent element targeting.\n * Captures clicks, form submissions, and other interactions.\n */\n\nimport { buildElementChain, generateElementName, generateEventName } from './element-naming'\nimport type { AutocaptureConfig, ElementData } from './types'\nimport { DEFAULT_AUTOCAPTURE_CONFIG } from './types'\n\n// ==========================================\n// Types\n// ==========================================\n\nexport interface AutocaptureEvent {\n\teventType: 'click' | 'submit' | 'change' | 'focus' | 'blur'\n\ttarget: Element\n\telements: ElementData[]\n\telementName: string\n\teventName: string\n\ttimestamp: number\n\tproperties: Record<string, unknown>\n}\n\ntype AutocaptureCallback = (event: AutocaptureEvent) => void\n\n// ==========================================\n// Autocapture Class\n// ==========================================\n\n/**\n * Smart Autocapture\n *\n * Captures user interactions with meaningful event names.\n */\nexport class Autocapture {\n\tprivate config: AutocaptureConfig\n\tprivate callback: AutocaptureCallback\n\tprivate isEnabled = false\n\tprivate boundHandlers: Map<string, EventListener> = new Map()\n\n\tconstructor(callback: AutocaptureCallback, config: Partial<AutocaptureConfig> = {}) {\n\t\tthis.config = { ...DEFAULT_AUTOCAPTURE_CONFIG, ...config }\n\t\tthis.callback = callback\n\t}\n\n\t// ==========================================\n\t// Lifecycle\n\t// ==========================================\n\n\t/**\n\t * Start autocapture\n\t */\n\tstart(): void {\n\t\tif (typeof window === 'undefined') return\n\t\tif (this.isEnabled) return\n\n\t\tthis.isEnabled = true\n\t\tthis.attachListeners()\n\t}\n\n\t/**\n\t * Stop autocapture\n\t */\n\tstop(): void {\n\t\tif (!this.isEnabled) return\n\n\t\tthis.isEnabled = false\n\t\tthis.detachListeners()\n\t}\n\n\t/**\n\t * Check if autocapture is enabled\n\t */\n\tisActive(): boolean {\n\t\treturn this.isEnabled\n\t}\n\n\t// ==========================================\n\t// Event Listeners\n\t// ==========================================\n\n\tprivate attachListeners(): void {\n\t\tconst eventTypes = this.config.eventTypes || ['click', 'submit', 'change']\n\n\t\tfor (const eventType of eventTypes) {\n\t\t\tconst handler = this.createHandler(eventType)\n\t\t\tthis.boundHandlers.set(eventType, handler)\n\n\t\t\t// Use capture phase to catch events before they might be stopped\n\t\t\tdocument.addEventListener(eventType, handler, true)\n\t\t}\n\t}\n\n\tprivate detachListeners(): void {\n\t\tfor (const [eventType, handler] of this.boundHandlers) {\n\t\t\tdocument.removeEventListener(eventType, handler, true)\n\t\t}\n\t\tthis.boundHandlers.clear()\n\t}\n\n\tprivate createHandler(eventType: string): EventListener {\n\t\treturn (event: Event) => {\n\t\t\tif (!this.isEnabled) return\n\n\t\t\tconst target = event.target as Element | null\n\t\t\tif (!target) return\n\n\t\t\t// Check if we should capture this element\n\t\t\tif (!this.shouldCapture(target, eventType)) return\n\n\t\t\t// Find the meaningful element (button inside a link, etc.)\n\t\t\tconst meaningfulElement = this.findMeaningfulElement(target, eventType)\n\t\t\tif (!meaningfulElement) return\n\n\t\t\t// Build the autocapture event\n\t\t\tconst autocaptureEvent = this.buildEvent(\n\t\t\t\tmeaningfulElement,\n\t\t\t\teventType as AutocaptureEvent['eventType'],\n\t\t\t\tevent,\n\t\t\t)\n\n\t\t\t// Dispatch to callback\n\t\t\tthis.callback(autocaptureEvent)\n\t\t}\n\t}\n\n\t// ==========================================\n\t// Element Filtering\n\t// ==========================================\n\n\tprivate shouldCapture(element: Element, eventType: string): boolean {\n\t\t// Check exclude selectors first\n\t\tif (this.config.excludeSelectors) {\n\t\t\tfor (const selector of this.config.excludeSelectors) {\n\t\t\t\tif (element.matches(selector) || element.closest(selector)) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check for sensitive elements\n\t\tif (this.isSensitiveElement(element)) {\n\t\t\treturn false\n\t\t}\n\n\t\t// Check for autocapture disabled attribute\n\t\tif (this.hasDisabledAttribute(element)) {\n\t\t\treturn false\n\t\t}\n\n\t\t// Check if element is in allowed list\n\t\tif (this.config.elements) {\n\t\t\tconst isAllowed = this.config.elements.some((selector) => {\n\t\t\t\ttry {\n\t\t\t\t\treturn element.matches(selector) || !!element.closest(selector)\n\t\t\t\t} catch {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t})\n\n\t\t\t// For click events, be more permissive\n\t\t\tif (!isAllowed && eventType === 'click') {\n\t\t\t\t// Allow clickable elements\n\t\t\t\treturn this.isClickable(element)\n\t\t\t}\n\n\t\t\treturn isAllowed\n\t\t}\n\n\t\treturn true\n\t}\n\n\tprivate isSensitiveElement(element: Element): boolean {\n\t\tconst tagName = element.tagName.toLowerCase()\n\t\tconst type = element.getAttribute('type')?.toLowerCase()\n\n\t\t// Password fields\n\t\tif (tagName === 'input' && type === 'password') return true\n\n\t\t// Credit card fields (common patterns)\n\t\tconst name = element.getAttribute('name')?.toLowerCase() || ''\n\t\tconst id = element.id?.toLowerCase() || ''\n\t\tconst autocomplete = element.getAttribute('autocomplete')?.toLowerCase() || ''\n\n\t\tconst sensitivePatterns = [\n\t\t\t'card',\n\t\t\t'credit',\n\t\t\t'cvv',\n\t\t\t'cvc',\n\t\t\t'ccv',\n\t\t\t'security-code',\n\t\t\t'expir',\n\t\t\t'ssn',\n\t\t\t'social-security',\n\t\t\t'tax-id',\n\t\t\t'pin',\n\t\t]\n\n\t\tfor (const pattern of sensitivePatterns) {\n\t\t\tif (name.includes(pattern) || id.includes(pattern) || autocomplete.includes(pattern)) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\n\t\t// Check for data-sensitive attribute\n\t\tif (element.hasAttribute('data-sensitive') || element.hasAttribute('data-no-capture')) {\n\t\t\treturn true\n\t\t}\n\n\t\treturn false\n\t}\n\n\tprivate hasDisabledAttribute(element: Element): boolean {\n\t\t// Check element and ancestors for disabled autocapture\n\t\tlet current: Element | null = element\n\t\twhile (current) {\n\t\t\tif (\n\t\t\t\tcurrent.hasAttribute('data-autocapture-disabled') ||\n\t\t\t\tcurrent.hasAttribute('data-no-track')\n\t\t\t) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tcurrent = current.parentElement\n\t\t}\n\t\treturn false\n\t}\n\n\tprivate isClickable(element: Element): boolean {\n\t\tconst tagName = element.tagName.toLowerCase()\n\n\t\t// Standard clickable elements\n\t\tif (['a', 'button', 'input', 'select', 'textarea'].includes(tagName)) {\n\t\t\treturn true\n\t\t}\n\n\t\t// Role-based clickable\n\t\tconst role = element.getAttribute('role')\n\t\tif (role && ['button', 'link', 'tab', 'menuitem', 'option'].includes(role)) {\n\t\t\treturn true\n\t\t}\n\n\t\t// Has click handler (check for event listeners or onclick)\n\t\tif (element.hasAttribute('onclick')) {\n\t\t\treturn true\n\t\t}\n\n\t\t// Check cursor style\n\t\tconst style = window.getComputedStyle(element)\n\t\tif (style.cursor === 'pointer') {\n\t\t\treturn true\n\t\t}\n\n\t\treturn false\n\t}\n\n\t// ==========================================\n\t// Element Resolution\n\t// ==========================================\n\n\tprivate findMeaningfulElement(target: Element, eventType: string): Element | null {\n\t\t// For submit events, the form is the meaningful element\n\t\tif (eventType === 'submit') {\n\t\t\tconst form = target.closest('form')\n\t\t\treturn form || target\n\t\t}\n\n\t\t// For change/focus/blur, the input itself is meaningful\n\t\tif (['change', 'focus', 'blur'].includes(eventType)) {\n\t\t\treturn target\n\t\t}\n\n\t\t// For click, find the most meaningful ancestor\n\t\tlet current: Element | null = target\n\t\tlet bestMatch: Element | null = null\n\n\t\twhile (current && current !== document.body) {\n\t\t\t// Stop at form boundaries\n\t\t\tif (current.tagName === 'FORM') break\n\n\t\t\t// Check if this is a good match\n\t\t\tif (this.isMeaningfulClickTarget(current)) {\n\t\t\t\tbestMatch = current\n\t\t\t\t// Keep looking for a better match (e.g., the button's link parent)\n\t\t\t}\n\n\t\t\tcurrent = current.parentElement\n\t\t}\n\n\t\treturn bestMatch || target\n\t}\n\n\tprivate isMeaningfulClickTarget(element: Element): boolean {\n\t\tconst tagName = element.tagName.toLowerCase()\n\n\t\t// Standard interactive elements\n\t\tif (['a', 'button'].includes(tagName)) {\n\t\t\treturn true\n\t\t}\n\n\t\t// Input elements (buttons, etc.)\n\t\tif (tagName === 'input') {\n\t\t\tconst type = element.getAttribute('type')\n\t\t\tif (['button', 'submit', 'reset'].includes(type || '')) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\n\t\t// Role-based\n\t\tconst role = element.getAttribute('role')\n\t\tif (role && ['button', 'link', 'tab', 'menuitem'].includes(role)) {\n\t\t\treturn true\n\t\t}\n\n\t\t// Has explicit analytics attribute\n\t\tif (element.hasAttribute('data-analytics') || element.hasAttribute('data-track')) {\n\t\t\treturn true\n\t\t}\n\n\t\treturn false\n\t}\n\n\t// ==========================================\n\t// Event Building\n\t// ==========================================\n\n\tprivate buildEvent(\n\t\telement: Element,\n\t\teventType: AutocaptureEvent['eventType'],\n\t\toriginalEvent: Event,\n\t): AutocaptureEvent {\n\t\tconst elementName = generateElementName(element)\n\t\tconst eventName = generateEventName(element, eventType)\n\t\tconst elements = buildElementChain(element)\n\n\t\tconst properties: Record<string, unknown> = {\n\t\t\t$event_type: eventType,\n\t\t\t$element_name: elementName,\n\t\t}\n\n\t\t// Add element-specific properties\n\t\tif (element.tagName === 'A') {\n\t\t\tconst href = element.getAttribute('href')\n\t\t\tif (href) {\n\t\t\t\tproperties.$element_href = href\n\t\t\t\t// Check if external link\n\t\t\t\ttry {\n\t\t\t\t\tconst url = new URL(href, window.location.origin)\n\t\t\t\t\tproperties.$external_link = url.origin !== window.location.origin\n\t\t\t\t} catch {\n\t\t\t\t\t// Invalid URL\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Form submission data\n\t\tif (eventType === 'submit' && element.tagName === 'FORM') {\n\t\t\tproperties.$form_name = element.getAttribute('name') || element.id || undefined\n\t\t\tproperties.$form_action = element.getAttribute('action') || undefined\n\t\t\tproperties.$form_method = element.getAttribute('method') || 'GET'\n\t\t}\n\n\t\t// Input change data (without values for privacy)\n\t\tif (eventType === 'change') {\n\t\t\tconst input = element as HTMLInputElement\n\t\t\tproperties.$input_type = input.type || element.tagName.toLowerCase()\n\t\t\tproperties.$input_name = input.name || undefined\n\n\t\t\t// For checkboxes/radios, we can capture checked state\n\t\t\tif (input.type === 'checkbox' || input.type === 'radio') {\n\t\t\t\tproperties.$input_checked = input.checked\n\t\t\t}\n\n\t\t\t// For select, capture selected option text (not value)\n\t\t\tif (element.tagName === 'SELECT') {\n\t\t\t\tconst select = element as HTMLSelectElement\n\t\t\t\tconst selectedOption = select.options[select.selectedIndex]\n\t\t\t\tif (selectedOption && this.config.captureText) {\n\t\t\t\t\tproperties.$selected_text = selectedOption.text?.slice(0, 100)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\teventType,\n\t\t\ttarget: element,\n\t\t\telements,\n\t\t\telementName,\n\t\t\teventName,\n\t\t\ttimestamp: Date.now(),\n\t\t\tproperties,\n\t\t}\n\t}\n}\n\n// ==========================================\n// Factory\n// ==========================================\n\nlet autocaptureInstance: Autocapture | null = null\n\n/**\n * Initialize autocapture\n */\nexport function initAutocapture(\n\tcallback: AutocaptureCallback,\n\tconfig?: Partial<AutocaptureConfig>,\n): Autocapture {\n\tautocaptureInstance = new Autocapture(callback, config)\n\treturn autocaptureInstance\n}\n\n/**\n * Get autocapture instance\n */\nfunction _getAutocapture(): Autocapture | null {\n\treturn autocaptureInstance\n}\n\n/**\n * Start autocapture\n */\nfunction _startAutocapture(): void {\n\tautocaptureInstance?.start()\n}\n\n/**\n * Stop autocapture\n */\nfunction _stopAutocapture(): void {\n\tautocaptureInstance?.stop()\n}\n","/**\n * Analytics Destination Routing\n *\n * Route analytics events to multiple destinations with unified API.\n * Supports native Sylphx, Google Analytics 4, Mixpanel, Segment, PostHog,\n * and custom destinations.\n *\n * ## Features\n *\n * - **Multi-destination**: Send events to multiple platforms simultaneously\n * - **Consent-aware**: Respect user consent preferences per destination\n * - **Event transformation**: Transform events to destination-specific formats\n * - **Selective routing**: Route specific events to specific destinations\n * - **Fallback handling**: Queue events if destination is unavailable\n *\n * ## Usage\n *\n * @example\n * ```typescript\n * import { createDestinationRouter, GA4Destination, MixpanelDestination } from '@sylphx/sdk'\n *\n * const router = createDestinationRouter({\n *   destinations: [\n *     // Native Sylphx (always enabled)\n *     { type: 'sylphx', config: { apiEndpoint: '/api/v1/analytics/track' } },\n *     // Google Analytics 4\n *     { type: 'ga4', config: { measurementId: 'G-XXXXXX' }, consentRequired: 'analytics' },\n *     // Mixpanel\n *     { type: 'mixpanel', config: { token: 'xxx' }, consentRequired: 'analytics' },\n *   ],\n * })\n *\n * // Track to all destinations\n * router.track('purchase', { amount: 99.99 })\n *\n * // Track to specific destination\n * router.trackTo('ga4', 'conversion', { value: 99.99 })\n * ```\n */\n\nimport type { AnalyticsEvent, EventProperties, UserProperties } from './types'\n\n// ============================================\n// Types\n// ============================================\n\n/** Supported destination types */\nexport type DestinationType =\n\t| 'sylphx'\n\t| 'ga4'\n\t| 'gtm'\n\t| 'mixpanel'\n\t| 'segment'\n\t| 'posthog'\n\t| 'amplitude'\n\t| 'custom'\n\n/** Consent categories (matches consent module) */\nexport type ConsentCategory = 'necessary' | 'analytics' | 'marketing' | 'functional' | 'preferences'\n\n/** Base destination configuration */\nexport interface BaseDestinationConfig {\n\t/** Destination type */\n\ttype: DestinationType\n\t/** Human-readable name */\n\tname?: string\n\t/** Required consent category (if any) */\n\tconsentRequired?: ConsentCategory\n\t/** Enable/disable destination */\n\tenabled?: boolean\n\t/** Event filter - return true to send event */\n\tfilter?: (event: AnalyticsEvent) => boolean\n\t/** Transform event before sending */\n\ttransform?: (event: AnalyticsEvent) => AnalyticsEvent | null\n}\n\n/** Sylphx destination config */\nexport interface SylphxDestinationConfig extends BaseDestinationConfig {\n\ttype: 'sylphx'\n\tconfig: {\n\t\tapiEndpoint: string\n\t\tapiKey?: string\n\t\tbatchSize?: number\n\t\tflushInterval?: number\n\t}\n}\n\n/** Google Analytics 4 destination config */\nexport interface GA4DestinationConfig extends BaseDestinationConfig {\n\ttype: 'ga4'\n\tconfig: {\n\t\tmeasurementId: string\n\t\tdebug?: boolean\n\t}\n}\n\n/** Google Tag Manager destination config */\nexport interface GTMDestinationConfig extends BaseDestinationConfig {\n\ttype: 'gtm'\n\tconfig: {\n\t\tcontainerId?: string // Optional - GTM already loaded\n\t\tdataLayerName?: string\n\t}\n}\n\n/** Mixpanel destination config */\nexport interface MixpanelDestinationConfig extends BaseDestinationConfig {\n\ttype: 'mixpanel'\n\tconfig: {\n\t\ttoken: string\n\t\tdebug?: boolean\n\t\ttrackPageview?: boolean\n\t}\n}\n\n/** Segment destination config */\nexport interface SegmentDestinationConfig extends BaseDestinationConfig {\n\ttype: 'segment'\n\tconfig: {\n\t\twriteKey: string\n\t\tcdnUrl?: string\n\t}\n}\n\n/** PostHog destination config */\nexport interface PostHogDestinationConfig extends BaseDestinationConfig {\n\ttype: 'posthog'\n\tconfig: {\n\t\tapiKey: string\n\t\tapiHost?: string\n\t\tcapturePageview?: boolean\n\t\tcapturePageleave?: boolean\n\t}\n}\n\n/** Amplitude destination config */\nexport interface AmplitudeDestinationConfig extends BaseDestinationConfig {\n\ttype: 'amplitude'\n\tconfig: {\n\t\tapiKey: string\n\t\tserverUrl?: string\n\t}\n}\n\n/** Custom destination config */\nexport interface CustomDestinationConfig extends BaseDestinationConfig {\n\ttype: 'custom'\n\tconfig: {\n\t\t/** Custom track function */\n\t\ttrack: (event: string, properties: EventProperties) => void | Promise<void>\n\t\t/** Custom identify function */\n\t\tidentify?: (userId: string, traits: UserProperties) => void | Promise<void>\n\t\t/** Custom page function */\n\t\tpage?: (name: string, properties: EventProperties) => void | Promise<void>\n\t}\n}\n\n/** All destination configs */\nexport type DestinationConfig =\n\t| SylphxDestinationConfig\n\t| GA4DestinationConfig\n\t| GTMDestinationConfig\n\t| MixpanelDestinationConfig\n\t| SegmentDestinationConfig\n\t| PostHogDestinationConfig\n\t| AmplitudeDestinationConfig\n\t| CustomDestinationConfig\n\n/** Router configuration */\nexport interface DestinationRouterConfig {\n\t/** Destinations to route to */\n\tdestinations: DestinationConfig[]\n\t/** Check consent function (from consent module) */\n\tcheckConsent?: (category: ConsentCategory) => boolean\n\t/** Default consent (if no checkConsent provided) */\n\tdefaultConsent?: boolean\n\t/** Debug mode */\n\tdebug?: boolean\n\t/** Distinct ID for user identification */\n\tdistinctId?: string\n}\n\n/** Destination router interface */\nexport interface DestinationRouter {\n\t/** Track event to all enabled destinations */\n\ttrack: (event: string, properties?: EventProperties) => void\n\t/** Track event to specific destination */\n\ttrackTo: (destinationType: DestinationType, event: string, properties?: EventProperties) => void\n\t/** Identify user across destinations */\n\tidentify: (userId: string, traits?: UserProperties) => void\n\t/** Track page view */\n\tpage: (name?: string, properties?: EventProperties) => void\n\t/** Get enabled destinations */\n\tgetEnabledDestinations: () => DestinationConfig[]\n\t/** Enable/disable a destination */\n\tsetDestinationEnabled: (type: DestinationType, enabled: boolean) => void\n\t/** Update consent function */\n\tsetConsentChecker: (fn: (category: ConsentCategory) => boolean) => void\n\t/** Set distinct ID */\n\tsetDistinctId: (id: string) => void\n}\n\ntype VendorCallArgs = readonly unknown[]\n\ninterface MixpanelBootstrap {\n\t_i: Array<[string, Record<string, unknown>, Window['mixpanel']?]>\n\tinit: (token: string, config?: Record<string, unknown>) => void\n\ttrack: (...args: VendorCallArgs) => void\n\tidentify: (...args: VendorCallArgs) => void\n\tpeople: {\n\t\tset: (...args: VendorCallArgs) => void\n\t}\n}\n\ninterface SegmentAnalyticsQueue extends NonNullable<Window['analytics']> {\n\tinitialize?: boolean\n\tinvoked?: boolean\n\tmethods: string[]\n\tfactory: (method: string) => (...args: unknown[]) => SegmentAnalyticsQueue\n\tpush: (...items: unknown[]) => number\n\t_loadOptions?: Record<string, unknown>\n\t_writeKey?: string\n\tSNIPPET_VERSION?: string\n}\n\ninterface PostHogBootstrap {\n\t__loaded?: boolean\n\t__load_queue: Array<[string, unknown]>\n\t_i: Array<[string, Record<string, unknown>]>\n\tpeople: {\n\t\tset: (...args: VendorCallArgs) => void\n\t}\n\tinit: (apiKey: string, config: Record<string, unknown>) => void\n\t[key: string]: unknown\n}\n\ninterface AmplitudeBootstrap {\n\t_q: Array<[string, unknown[]]>\n\ttrack: (...args: VendorCallArgs) => void\n\tidentify: (...args: VendorCallArgs) => void\n\tsetUserId: (...args: VendorCallArgs) => void\n\tinit: (apiKey: string, options?: Record<string, unknown>) => void\n}\n\n// ============================================\n// Destination Handlers\n// ============================================\n\ntype TrackHandler = (\n\tevent: string,\n\tproperties: EventProperties,\n\tconfig: DestinationConfig['config'],\n) => void\ntype IdentifyHandler = (\n\tuserId: string,\n\ttraits: UserProperties,\n\tconfig: DestinationConfig['config'],\n) => void\ntype PageHandler = (\n\tname: string,\n\tproperties: EventProperties,\n\tconfig: DestinationConfig['config'],\n) => void\n\ninterface DestinationHandler {\n\ttrack: TrackHandler\n\tidentify: IdentifyHandler\n\tpage: PageHandler\n\tinit?: (config: DestinationConfig['config']) => void\n}\n\n/**\n * Sylphx handler - sends to native API\n */\nconst sylphxHandler: DestinationHandler = {\n\ttrack: async (event, properties, config) => {\n\t\tconst { apiEndpoint, apiKey } = config as SylphxDestinationConfig['config']\n\t\ttry {\n\t\t\tconst headers: Record<string, string> = {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t}\n\t\t\tif (apiKey) headers.Authorization = `Bearer ${apiKey}`\n\n\t\t\tnavigator.sendBeacon?.(\n\t\t\t\tapiEndpoint,\n\t\t\t\tJSON.stringify({\n\t\t\t\t\tevent,\n\t\t\t\t\tproperties,\n\t\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\t}),\n\t\t\t)\n\t\t} catch (error) {\n\t\t\tconsole.error('[Sylphx] Track error:', error)\n\t\t}\n\t},\n\tidentify: async (userId, traits, config) => {\n\t\tconst { apiEndpoint, apiKey } = config as SylphxDestinationConfig['config']\n\t\ttry {\n\t\t\tconst headers: Record<string, string> = {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t}\n\t\t\tif (apiKey) headers.Authorization = `Bearer ${apiKey}`\n\n\t\t\tawait fetch(apiEndpoint, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders,\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tevent: '$identify',\n\t\t\t\t\tdistinct_id: userId,\n\t\t\t\t\t$set: traits,\n\t\t\t\t}),\n\t\t\t})\n\t\t} catch (error) {\n\t\t\tconsole.error('[Sylphx] Identify error:', error)\n\t\t}\n\t},\n\tpage: async (name, properties, config) => {\n\t\tconst { apiEndpoint, apiKey } = config as SylphxDestinationConfig['config']\n\t\ttry {\n\t\t\tconst headers: Record<string, string> = {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t}\n\t\t\tif (apiKey) headers.Authorization = `Bearer ${apiKey}`\n\n\t\t\tnavigator.sendBeacon?.(\n\t\t\t\tapiEndpoint,\n\t\t\t\tJSON.stringify({\n\t\t\t\t\tevent: '$pageview',\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\t$current_url: window.location.href,\n\t\t\t\t\t\t$title: name || document.title,\n\t\t\t\t\t\t...properties,\n\t\t\t\t\t},\n\t\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\t}),\n\t\t\t)\n\t\t} catch (error) {\n\t\t\tconsole.error('[Sylphx] Page error:', error)\n\t\t}\n\t},\n}\n\n/**\n * GA4 handler - uses gtag\n */\nconst ga4Handler: DestinationHandler = {\n\tinit: (config) => {\n\t\tconst { measurementId } = config as GA4DestinationConfig['config']\n\t\t// Initialize dataLayer if not exists\n\t\twindow.dataLayer = window.dataLayer || []\n\t\tfunction gtag(...args: unknown[]) {\n\t\t\twindow.dataLayer.push(args)\n\t\t}\n\t\twindow.gtag = gtag\n\t\tgtag('js', new Date())\n\t\tgtag('config', measurementId)\n\t},\n\ttrack: (event, properties, config) => {\n\t\tconst { debug } = config as GA4DestinationConfig['config']\n\t\tif (!window.gtag) {\n\t\t\tif (debug) console.warn('[GA4] gtag not available')\n\t\t\treturn\n\t\t}\n\n\t\t// Transform to GA4 format\n\t\t// Reserved names: https://developers.google.com/analytics/devguides/collection/ga4/reference/events\n\t\tconst ga4Event = event.replace(/[^a-zA-Z0-9_]/g, '_')\n\t\twindow.gtag('event', ga4Event, properties)\n\t},\n\tidentify: (userId, _traits, config) => {\n\t\tconst { debug } = config as GA4DestinationConfig['config']\n\t\tif (!window.gtag) {\n\t\t\tif (debug) console.warn('[GA4] gtag not available')\n\t\t\treturn\n\t\t}\n\t\twindow.gtag('config', (config as GA4DestinationConfig['config']).measurementId, {\n\t\t\tuser_id: userId,\n\t\t})\n\t},\n\tpage: (_name, _properties, config) => {\n\t\tconst { debug } = config as GA4DestinationConfig['config']\n\t\tif (!window.gtag) {\n\t\t\tif (debug) console.warn('[GA4] gtag not available')\n\t\t\treturn\n\t\t}\n\t\twindow.gtag('event', 'page_view')\n\t},\n}\n\n/**\n * GTM handler - pushes to dataLayer\n */\nconst gtmHandler: DestinationHandler = {\n\tinit: (config) => {\n\t\tconst { dataLayerName = 'dataLayer' } = config as GTMDestinationConfig['config']\n\t\twindow[dataLayerName as 'dataLayer'] = window[dataLayerName as 'dataLayer'] || []\n\t},\n\ttrack: (event, properties, config) => {\n\t\tconst { dataLayerName = 'dataLayer' } = config as GTMDestinationConfig['config']\n\t\tconst layer = window[dataLayerName as 'dataLayer']\n\t\tif (!layer) return\n\n\t\tlayer.push({\n\t\t\tevent,\n\t\t\t...properties,\n\t\t})\n\t},\n\tidentify: (userId, traits, config) => {\n\t\tconst { dataLayerName = 'dataLayer' } = config as GTMDestinationConfig['config']\n\t\tconst layer = window[dataLayerName as 'dataLayer']\n\t\tif (!layer) return\n\n\t\tlayer.push({\n\t\t\tevent: 'user_identify',\n\t\t\tuser_id: userId,\n\t\t\t...traits,\n\t\t})\n\t},\n\tpage: (name, properties, config) => {\n\t\tconst { dataLayerName = 'dataLayer' } = config as GTMDestinationConfig['config']\n\t\tconst layer = window[dataLayerName as 'dataLayer']\n\t\tif (!layer) return\n\n\t\tlayer.push({\n\t\t\tevent: 'virtual_page_view',\n\t\t\tpage_title: name || document.title,\n\t\t\tpage_location: window.location.href,\n\t\t\t...properties,\n\t\t})\n\t},\n}\n\n/**\n * Mixpanel handler\n */\nconst mixpanelHandler: DestinationHandler = {\n\tinit: (config) => {\n\t\tconst { token, debug } = config as MixpanelDestinationConfig['config']\n\t\t// Mixpanel snippet (minified)\n\t\t;((f: Window, b: Document) => {\n\t\t\tif (!b) return\n\t\t\tconst c: MixpanelBootstrap = {\n\t\t\t\t_i: [],\n\t\t\t\tinit: (token, options = {}) => {\n\t\t\t\t\tc._i.push([token, options])\n\t\t\t\t},\n\t\t\t\ttrack: (...args) => {\n\t\t\t\t\tc._i[0]?.[2]?.track?.(String(args[0] ?? ''), args[1] as Record<string, unknown>)\n\t\t\t\t},\n\t\t\t\tidentify: (...args) => {\n\t\t\t\t\tc._i[0]?.[2]?.identify?.(String(args[0] ?? ''))\n\t\t\t\t},\n\t\t\t\tpeople: {\n\t\t\t\t\tset: (...args) => {\n\t\t\t\t\t\tc._i[0]?.[2]?.people?.set?.(args[0] as Record<string, unknown>)\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\tc._i = []\n\t\t\tconst a = b.createElement('script')\n\t\t\ta.type = 'text/javascript'\n\t\t\ta.async = true\n\t\t\ta.src = 'https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js'\n\t\t\tconst g = b.getElementsByTagName('script')[0]\n\t\t\tg.parentNode?.insertBefore(a, g)\n\t\t\tf.mixpanel = c\n\t\t})(window, document)\n\n\t\twindow.mixpanel?.init(token, { debug })\n\t},\n\ttrack: (event, properties) => {\n\t\twindow.mixpanel?.track(event, properties)\n\t},\n\tidentify: (userId, traits) => {\n\t\twindow.mixpanel?.identify(userId)\n\t\tif (traits) {\n\t\t\twindow.mixpanel?.people?.set(traits)\n\t\t}\n\t},\n\tpage: (name, properties) => {\n\t\twindow.mixpanel?.track('$mp_web_page_view', {\n\t\t\tpage_name: name,\n\t\t\t...properties,\n\t\t})\n\t},\n}\n\n/**\n * Segment handler\n */\nconst segmentHandler: DestinationHandler = {\n\tinit: (config) => {\n\t\tconst { writeKey, cdnUrl = 'https://cdn.segment.com' } =\n\t\t\tconfig as SegmentDestinationConfig['config']\n\t\t// Segment Analytics.js snippet\n\t\tlet analytics = window.analytics as SegmentAnalyticsQueue | undefined\n\t\tif (!analytics) {\n\t\t\tanalytics = [] as unknown as SegmentAnalyticsQueue\n\t\t\twindow.analytics = analytics\n\t\t}\n\t\tif (!analytics.initialize) {\n\t\t\tif (analytics.invoked) return\n\t\t\tanalytics.invoked = true\n\t\t\tanalytics.methods = [\n\t\t\t\t'trackSubmit',\n\t\t\t\t'trackClick',\n\t\t\t\t'trackLink',\n\t\t\t\t'trackForm',\n\t\t\t\t'pageview',\n\t\t\t\t'identify',\n\t\t\t\t'reset',\n\t\t\t\t'group',\n\t\t\t\t'track',\n\t\t\t\t'ready',\n\t\t\t\t'alias',\n\t\t\t\t'debug',\n\t\t\t\t'page',\n\t\t\t\t'once',\n\t\t\t\t'off',\n\t\t\t\t'on',\n\t\t\t\t'addSourceMiddleware',\n\t\t\t\t'addIntegrationMiddleware',\n\t\t\t\t'setAnonymousId',\n\t\t\t\t'addDestinationMiddleware',\n\t\t\t]\n\t\t\tanalytics.factory = (method: string) => {\n\t\t\t\treturn (...args: unknown[]) => {\n\t\t\t\t\targs.unshift(method)\n\t\t\t\t\tanalytics.push(args)\n\t\t\t\t\treturn analytics\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (let e = 0; e < analytics.methods.length; e++) {\n\t\t\t\tconst key = analytics.methods[e]\n\t\t\t\tif (!key) continue\n\t\t\t\tanalytics[key] = analytics.factory(key)\n\t\t\t}\n\t\t\tanalytics.load = (key: string, e?: Record<string, unknown>) => {\n\t\t\t\tconst t = document.createElement('script')\n\t\t\t\tt.type = 'text/javascript'\n\t\t\t\tt.async = true\n\t\t\t\tt.src = `${cdnUrl}/analytics.js/v1/${key}/analytics.min.js`\n\t\t\t\tconst n = document.getElementsByTagName('script')[0]\n\t\t\t\tn.parentNode?.insertBefore(t, n)\n\t\t\t\tanalytics._loadOptions = e\n\t\t\t}\n\t\t\tanalytics._writeKey = writeKey\n\t\t\tanalytics.SNIPPET_VERSION = '5.2.1'\n\t\t\tanalytics.load(writeKey)\n\t\t}\n\t},\n\ttrack: (event, properties) => {\n\t\twindow.analytics?.track(event, properties)\n\t},\n\tidentify: (userId, traits) => {\n\t\twindow.analytics?.identify(userId, traits)\n\t},\n\tpage: (name, properties) => {\n\t\twindow.analytics?.page(name, properties)\n\t},\n}\n\n/**\n * PostHog handler\n */\nconst posthogHandler: DestinationHandler = {\n\tinit: (config) => {\n\t\tconst { apiKey, apiHost = 'https://us.i.posthog.com' } =\n\t\t\tconfig as PostHogDestinationConfig['config']\n\t\t// PostHog snippet\n\t\t;((t: Window, e: Document) => {\n\t\t\tif (!e) return\n\t\t\tconst o: PostHogBootstrap = {\n\t\t\t\t__load_queue: [],\n\t\t\t\t_i: [],\n\t\t\t\tpeople: {\n\t\t\t\t\tset: (...args) => {\n\t\t\t\t\t\to.__load_queue.push(['people.set', args])\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tinit: (apiKey, config) => {\n\t\t\t\t\to._i.push([apiKey, config])\n\t\t\t\t\tconst r = e.createElement('script')\n\t\t\t\t\tr.type = 'text/javascript'\n\t\t\t\t\tr.async = true\n\t\t\t\t\tr.src = 'https://us-assets.i.posthog.com/static/array.js'\n\t\t\t\t\tconst s = e.getElementsByTagName('script')[0]\n\t\t\t\t\ts.parentNode?.insertBefore(r, s)\n\t\t\t\t},\n\t\t\t}\n\t\t\tlet n: string\n\t\t\tconst p = [\n\t\t\t\t'snapshot',\n\t\t\t\t'capture',\n\t\t\t\t'identify',\n\t\t\t\t'alias',\n\t\t\t\t'people',\n\t\t\t\t'onFeatureFlags',\n\t\t\t\t'reloadFeatureFlags',\n\t\t\t\t'register',\n\t\t\t\t'unregister',\n\t\t\t\t'set_config',\n\t\t\t\t'opt_in_capturing',\n\t\t\t\t'opt_out_capturing',\n\t\t\t\t'has_opted_in_capturing',\n\t\t\t\t'has_opted_out_capturing',\n\t\t\t\t'clear_opt_in_out_capturing',\n\t\t\t\t'get_distinct_id',\n\t\t\t\t'get_property',\n\t\t\t\t'reset',\n\t\t\t\t'debug',\n\t\t\t]\n\t\t\tfor (n of p) {\n\t\t\t\to[n] = (\n\t\t\t\t\t(n: string): ((...args: unknown[]) => void) =>\n\t\t\t\t\t(...args: unknown[]) => {\n\t\t\t\t\t\tif (!o.__loaded) {\n\t\t\t\t\t\t\to.__load_queue.push([n, args])\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t)(n)\n\t\t\t}\n\t\t\tt.posthog = o as unknown as NonNullable<Window['posthog']>\n\t\t})(window, document)\n\n\t\twindow.posthog?.init(apiKey, { api_host: apiHost })\n\t},\n\ttrack: (event, properties) => {\n\t\twindow.posthog?.capture(event, properties)\n\t},\n\tidentify: (userId, traits) => {\n\t\twindow.posthog?.identify(userId, traits)\n\t},\n\tpage: (_name, properties) => {\n\t\twindow.posthog?.capture('$pageview', properties)\n\t},\n}\n\n/**\n * Amplitude handler\n */\nconst amplitudeHandler: DestinationHandler = {\n\tinit: (config) => {\n\t\tconst { apiKey, serverUrl } = config as AmplitudeDestinationConfig['config']\n\t\t// Amplitude snippet\n\t\t;((e: Window, t: Document) => {\n\t\t\tif (!t) return\n\t\t\tconst r: AmplitudeBootstrap = {\n\t\t\t\t_q: [],\n\t\t\t\ttrack: (...args) => {\n\t\t\t\t\tr._q.push(['track', [...args]])\n\t\t\t\t},\n\t\t\t\tidentify: (...args) => {\n\t\t\t\t\tr._q.push(['identify', [...args]])\n\t\t\t\t},\n\t\t\t\tsetUserId: (...args) => {\n\t\t\t\t\tr._q.push(['setUserId', [...args]])\n\t\t\t\t},\n\t\t\t\tinit: (apiKey, options) => {\n\t\t\t\t\tr._q.push(['init', [apiKey, options]])\n\t\t\t\t\tconst n = t.createElement('script')\n\t\t\t\t\tn.type = 'text/javascript'\n\t\t\t\t\tn.async = true\n\t\t\t\t\tn.src = 'https://cdn.amplitude.com/libs/analytics-browser-2.0.0-min.js.gz'\n\t\t\t\t\tconst o = t.getElementsByTagName('script')[0]\n\t\t\t\t\to.parentNode?.insertBefore(n, o)\n\t\t\t\t},\n\t\t\t}\n\t\t\te.amplitude = r as NonNullable<Window['amplitude']>\n\t\t})(window, document)\n\n\t\twindow.amplitude?.init(apiKey, serverUrl ? { serverUrl } : undefined)\n\t},\n\ttrack: (event, properties) => {\n\t\twindow.amplitude?.track(event, properties)\n\t},\n\tidentify: (userId, traits) => {\n\t\twindow.amplitude?.setUserId(userId)\n\t\tif (traits) {\n\t\t\twindow.amplitude?.identify(traits)\n\t\t}\n\t},\n\tpage: (name, properties) => {\n\t\twindow.amplitude?.track('[Amplitude] Page Viewed', {\n\t\t\tpage_name: name,\n\t\t\t...properties,\n\t\t})\n\t},\n}\n\n/** Handler registry */\nconst handlers: Record<DestinationType, DestinationHandler> = {\n\tsylphx: sylphxHandler,\n\tga4: ga4Handler,\n\tgtm: gtmHandler,\n\tmixpanel: mixpanelHandler,\n\tsegment: segmentHandler,\n\tposthog: posthogHandler,\n\tamplitude: amplitudeHandler,\n\tcustom: {\n\t\ttrack: () => {},\n\t\tidentify: () => {},\n\t\tpage: () => {},\n\t},\n}\n\n// ============================================\n// Router Implementation\n// ============================================\n\n/**\n * Create a destination router\n *\n * @param config - Router configuration\n * @returns Destination router instance\n *\n * @example\n * ```typescript\n * const router = createDestinationRouter({\n *   destinations: [\n *     { type: 'sylphx', config: { apiEndpoint: '/api/v1/analytics/track' } },\n *     { type: 'ga4', config: { measurementId: 'G-XXXXXX' }, consentRequired: 'analytics' },\n *   ],\n *   checkConsent: (category) => hasConsent(category),\n * })\n *\n * router.track('purchase', { amount: 99.99 })\n * ```\n */\nexport function createDestinationRouter(config: DestinationRouterConfig): DestinationRouter {\n\tconst { destinations, defaultConsent = false, debug = false } = config\n\tlet checkConsent = config.checkConsent || (() => defaultConsent)\n\tlet distinctId = config.distinctId || ''\n\tconst enabledMap = new Map<DestinationType, boolean>()\n\n\t// Initialize destinations\n\tfor (const dest of destinations) {\n\t\tenabledMap.set(dest.type, dest.enabled !== false)\n\n\t\t// Skip initialization if disabled\n\t\tif (dest.enabled === false) continue\n\n\t\t// Initialize handler\n\t\tconst handler = handlers[dest.type]\n\t\tif (handler.init && dest.type !== 'custom') {\n\t\t\ttry {\n\t\t\t\thandler.init(dest.config)\n\t\t\t\t// biome-ignore lint/suspicious/noConsole: SDK is framework-agnostic client code; debug logging goes through console — no server logger available in the browser.\n\t\t\t\tif (debug) console.log(`[Router] Initialized ${dest.type}`)\n\t\t\t} catch (error) {\n\t\t\t\t// biome-ignore lint/suspicious/noConsole: SDK error reporting goes through console — no server logger in browser.\n\t\t\t\tconsole.error(`[Router] Failed to initialize ${dest.type}:`, error)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Check if destination should receive event\n\t */\n\tfunction shouldRoute(dest: DestinationConfig): boolean {\n\t\t// Check if enabled\n\t\tif (!enabledMap.get(dest.type)) return false\n\n\t\t// Check consent\n\t\tif (dest.consentRequired && !checkConsent(dest.consentRequired)) {\n\t\t\t// biome-ignore lint/suspicious/noConsole: SDK debug logging to console — no server logger in browser.\n\t\t\tif (debug)\n\t\t\t\tconsole.log(`[Router] Consent not granted for ${dest.type} (${dest.consentRequired})`)\n\t\t\treturn false\n\t\t}\n\n\t\treturn true\n\t}\n\n\t/**\n\t * Build event for routing\n\t */\n\tfunction buildEvent(event: string, properties: EventProperties = {}): AnalyticsEvent {\n\t\treturn {\n\t\t\tevent,\n\t\t\tproperties: {\n\t\t\t\t...properties,\n\t\t\t\t$lib: '@sylphx/sdk',\n\t\t\t\t$lib_version: '0.5.0',\n\t\t\t},\n\t\t\tdistinct_id: distinctId,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t}\n\t}\n\n\treturn {\n\t\ttrack: (event, properties = {}) => {\n\t\t\tconst analyticsEvent = buildEvent(event, properties)\n\n\t\t\tfor (const dest of destinations) {\n\t\t\t\tif (!shouldRoute(dest)) continue\n\n\t\t\t\t// Apply filter\n\t\t\t\tif (dest.filter && !dest.filter(analyticsEvent)) continue\n\n\t\t\t\t// Apply transform\n\t\t\t\tconst finalEvent = dest.transform ? dest.transform(analyticsEvent) : analyticsEvent\n\t\t\t\tif (!finalEvent) continue\n\n\t\t\t\t// Route to handler\n\t\t\t\ttry {\n\t\t\t\t\tif (dest.type === 'custom') {\n\t\t\t\t\t\tconst customConfig = dest.config as CustomDestinationConfig['config']\n\t\t\t\t\t\tcustomConfig.track(finalEvent.event, finalEvent.properties)\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandlers[dest.type].track(finalEvent.event, finalEvent.properties, dest.config)\n\t\t\t\t\t}\n\t\t\t\t\t// biome-ignore lint/suspicious/noConsole: SDK debug logging to console — no server logger in browser.\n\t\t\t\t\tif (debug) console.log(`[Router] Tracked \"${event}\" to ${dest.type}`)\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// biome-ignore lint/suspicious/noConsole: SDK error reporting to console — no server logger in browser.\n\t\t\t\t\tconsole.error(`[Router] Failed to track to ${dest.type}:`, error)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\ttrackTo: (destinationType, event, properties = {}) => {\n\t\t\tconst dest = destinations.find((d) => d.type === destinationType)\n\t\t\tif (!dest) {\n\t\t\t\t// biome-ignore lint/suspicious/noConsole: SDK warning surface — no server logger in browser.\n\t\t\t\tconsole.warn(`[Router] Destination not found: ${destinationType}`)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (!shouldRoute(dest)) return\n\n\t\t\tconst analyticsEvent = buildEvent(event, properties)\n\n\t\t\ttry {\n\t\t\t\tif (dest.type === 'custom') {\n\t\t\t\t\tconst customConfig = dest.config as CustomDestinationConfig['config']\n\t\t\t\t\tcustomConfig.track(analyticsEvent.event, analyticsEvent.properties)\n\t\t\t\t} else {\n\t\t\t\t\thandlers[dest.type].track(analyticsEvent.event, analyticsEvent.properties, dest.config)\n\t\t\t\t}\n\t\t\t\t// biome-ignore lint/suspicious/noConsole: SDK debug logging to console — no server logger in browser.\n\t\t\t\tif (debug) console.log(`[Router] Tracked \"${event}\" to ${destinationType}`)\n\t\t\t} catch (error) {\n\t\t\t\t// biome-ignore lint/suspicious/noConsole: SDK error reporting to console.\n\t\t\t\tconsole.error(`[Router] Failed to track to ${destinationType}:`, error)\n\t\t\t}\n\t\t},\n\n\t\tidentify: (userId, traits = {}) => {\n\t\t\tdistinctId = userId\n\n\t\t\tfor (const dest of destinations) {\n\t\t\t\tif (!shouldRoute(dest)) continue\n\n\t\t\t\ttry {\n\t\t\t\t\tif (dest.type === 'custom') {\n\t\t\t\t\t\tconst customConfig = dest.config as CustomDestinationConfig['config']\n\t\t\t\t\t\tcustomConfig.identify?.(userId, traits)\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandlers[dest.type].identify(userId, traits, dest.config)\n\t\t\t\t\t}\n\t\t\t\t\t// biome-ignore lint/suspicious/noConsole: SDK debug logging to console.\n\t\t\t\t\tif (debug) console.log(`[Router] Identified user to ${dest.type}`)\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// biome-ignore lint/suspicious/noConsole: SDK error reporting to console.\n\t\t\t\t\tconsole.error(`[Router] Failed to identify to ${dest.type}:`, error)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tpage: (name, properties = {}) => {\n\t\t\tfor (const dest of destinations) {\n\t\t\t\tif (!shouldRoute(dest)) continue\n\n\t\t\t\ttry {\n\t\t\t\t\tif (dest.type === 'custom') {\n\t\t\t\t\t\tconst customConfig = dest.config as CustomDestinationConfig['config']\n\t\t\t\t\t\tcustomConfig.page?.(name || document.title, properties)\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandlers[dest.type].page(name || document.title, properties, dest.config)\n\t\t\t\t\t}\n\t\t\t\t\t// biome-ignore lint/suspicious/noConsole: SDK debug logging to console.\n\t\t\t\t\tif (debug) console.log(`[Router] Paged to ${dest.type}`)\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// biome-ignore lint/suspicious/noConsole: SDK error reporting to console.\n\t\t\t\t\tconsole.error(`[Router] Failed to page to ${dest.type}:`, error)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tgetEnabledDestinations: () => {\n\t\t\treturn destinations.filter((d) => shouldRoute(d))\n\t\t},\n\n\t\tsetDestinationEnabled: (type, enabled) => {\n\t\t\tenabledMap.set(type, enabled)\n\t\t},\n\n\t\tsetConsentChecker: (fn) => {\n\t\t\tcheckConsent = fn\n\t\t},\n\n\t\tsetDistinctId: (id) => {\n\t\t\tdistinctId = id\n\t\t},\n\t}\n}\n\n// ============================================\n// Type Declarations\n// ============================================\n\ndeclare global {\n\tinterface Window {\n\t\t// Mixpanel\n\t\tmixpanel?: {\n\t\t\tinit: (token: string, config?: Record<string, unknown>) => void\n\t\t\ttrack: (event: string, properties?: Record<string, unknown>) => void\n\t\t\tidentify: (userId: string) => void\n\t\t\tpeople?: {\n\t\t\t\tset: (properties: Record<string, unknown>) => void\n\t\t\t}\n\t\t}\n\t\t// Segment\n\t\tanalytics?: {\n\t\t\tload: (writeKey: string) => void\n\t\t\ttrack: (event: string, properties?: Record<string, unknown>) => void\n\t\t\tidentify: (userId: string, traits?: Record<string, unknown>) => void\n\t\t\tpage: (name?: string, properties?: Record<string, unknown>) => void\n\t\t\t[key: string]: unknown\n\t\t}\n\t\t// PostHog\n\t\tposthog?: {\n\t\t\tinit: (apiKey: string, config?: Record<string, unknown>) => void\n\t\t\tcapture: (event: string, properties?: Record<string, unknown>) => void\n\t\t\tidentify: (userId: string, properties?: Record<string, unknown>) => void\n\t\t}\n\t\t// Amplitude\n\t\tamplitude?: {\n\t\t\tinit: (apiKey: string, options?: Record<string, unknown>) => void\n\t\t\ttrack: (event: string, properties?: Record<string, unknown>) => void\n\t\t\tidentify: (properties?: Record<string, unknown>) => void\n\t\t\tsetUserId: (userId: string) => void\n\t\t}\n\t}\n}\n","/**\n * SPA Navigation Tracking\n *\n * Tracks page views and navigation in single-page applications.\n * Works with pushState, replaceState, and popstate events.\n */\n\nimport type { DeviceContext, PageContext, ReferrerData, UtmParams } from './types'\n\n// ==========================================\n// Types\n// ==========================================\n\nexport interface PageViewEvent {\n\turl: string\n\tpath: string\n\ttitle: string\n\treferrer?: string\n\tcontext: PageContext\n\tutm?: UtmParams\n\tdevice?: DeviceContext\n\ttimestamp: number\n\t/** Time spent on previous page (ms) */\n\tpreviousPageTime?: number\n\t/** Scroll depth on previous page (0-100) */\n\tpreviousScrollDepth?: number\n}\n\nexport interface PageLeaveEvent {\n\turl: string\n\tpath: string\n\ttimeOnPage: number\n\tscrollDepth: number\n\ttimestamp: number\n}\n\ntype PageViewCallback = (event: PageViewEvent) => void\ntype PageLeaveCallback = (event: PageLeaveEvent) => void\n\n// ==========================================\n// Navigation Tracker\n// ==========================================\n\n/**\n * SPA Navigation Tracker\n *\n * Tracks page views and time on page for single-page applications.\n */\nexport class NavigationTracker {\n\tprivate pageViewCallback: PageViewCallback\n\tprivate pageLeaveCallback?: PageLeaveCallback\n\tprivate isEnabled = false\n\tprivate currentPage: {\n\t\turl: string\n\t\tpath: string\n\t\tenteredAt: number\n\t\tmaxScrollDepth: number\n\t} | null = null\n\tprivate cleanupFns: (() => void)[] = []\n\n\tconstructor(onPageView: PageViewCallback, onPageLeave?: PageLeaveCallback) {\n\t\tthis.pageViewCallback = onPageView\n\t\tthis.pageLeaveCallback = onPageLeave\n\t}\n\n\t// ==========================================\n\t// Lifecycle\n\t// ==========================================\n\n\t/**\n\t * Start tracking navigation\n\t */\n\tstart(): void {\n\t\tif (typeof window === 'undefined') return\n\t\tif (this.isEnabled) return\n\n\t\tthis.isEnabled = true\n\n\t\t// Track initial page view\n\t\tthis.trackPageView()\n\n\t\t// Hook into History API\n\t\tthis.hookHistoryApi()\n\n\t\t// Listen for popstate (back/forward)\n\t\tconst popstateHandler = () => this.handleNavigation('popstate')\n\t\twindow.addEventListener('popstate', popstateHandler)\n\t\tthis.cleanupFns.push(() => window.removeEventListener('popstate', popstateHandler))\n\n\t\t// Track scroll depth\n\t\tthis.trackScrollDepth()\n\n\t\t// Track page visibility changes\n\t\tthis.trackVisibility()\n\n\t\t// Track page unload\n\t\tconst beforeUnloadHandler = () => this.handlePageLeave()\n\t\twindow.addEventListener('beforeunload', beforeUnloadHandler)\n\t\tthis.cleanupFns.push(() => window.removeEventListener('beforeunload', beforeUnloadHandler))\n\t}\n\n\t/**\n\t * Stop tracking navigation\n\t */\n\tstop(): void {\n\t\tif (!this.isEnabled) return\n\n\t\tthis.isEnabled = false\n\n\t\t// Run cleanup functions\n\t\tfor (const cleanup of this.cleanupFns) {\n\t\t\tcleanup()\n\t\t}\n\t\tthis.cleanupFns = []\n\n\t\t// Fire page leave for current page\n\t\tif (this.currentPage) {\n\t\t\tthis.handlePageLeave()\n\t\t}\n\t}\n\n\t/**\n\t * Manually track a page view\n\t */\n\ttrackPageView(customUrl?: string): void {\n\t\tif (!this.isEnabled && !customUrl) return\n\n\t\tconst previousPage = this.currentPage\n\t\tconst now = Date.now()\n\n\t\t// Calculate previous page metrics\n\t\tlet previousPageTime: number | undefined\n\t\tlet previousScrollDepth: number | undefined\n\n\t\tif (previousPage) {\n\t\t\tpreviousPageTime = now - previousPage.enteredAt\n\t\t\tpreviousScrollDepth = previousPage.maxScrollDepth\n\n\t\t\t// Fire page leave for previous page\n\t\t\tif (this.pageLeaveCallback) {\n\t\t\t\tthis.pageLeaveCallback({\n\t\t\t\t\turl: previousPage.url,\n\t\t\t\t\tpath: previousPage.path,\n\t\t\t\t\ttimeOnPage: previousPageTime,\n\t\t\t\t\tscrollDepth: previousScrollDepth,\n\t\t\t\t\ttimestamp: now,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\t// Set current page\n\t\tconst url = customUrl || window.location.href\n\t\tconst path = window.location.pathname\n\n\t\tthis.currentPage = {\n\t\t\turl,\n\t\t\tpath,\n\t\t\tenteredAt: now,\n\t\t\tmaxScrollDepth: 0,\n\t\t}\n\n\t\t// Build page view event\n\t\tconst event: PageViewEvent = {\n\t\t\turl,\n\t\t\tpath,\n\t\t\ttitle: document.title,\n\t\t\treferrer: previousPage?.url || document.referrer || undefined,\n\t\t\tcontext: this.getPageContext(),\n\t\t\tutm: this.getUtmParams(),\n\t\t\tdevice: this.getDeviceContext(),\n\t\t\ttimestamp: now,\n\t\t\tpreviousPageTime,\n\t\t\tpreviousScrollDepth,\n\t\t}\n\n\t\tthis.pageViewCallback(event)\n\t}\n\n\t// ==========================================\n\t// History API Hooks\n\t// ==========================================\n\n\tprivate hookHistoryApi(): void {\n\t\t// Store original methods\n\t\tconst originalPushState = history.pushState.bind(history)\n\t\tconst originalReplaceState = history.replaceState.bind(history)\n\n\t\t// Override pushState\n\t\thistory.pushState = (...args) => {\n\t\t\tconst result = originalPushState(...args)\n\t\t\tthis.handleNavigation('pushState')\n\t\t\treturn result\n\t\t}\n\n\t\t// Override replaceState\n\t\thistory.replaceState = (...args) => {\n\t\t\tconst result = originalReplaceState(...args)\n\t\t\tthis.handleNavigation('replaceState')\n\t\t\treturn result\n\t\t}\n\n\t\t// Cleanup: restore original methods\n\t\tthis.cleanupFns.push(() => {\n\t\t\thistory.pushState = originalPushState\n\t\t\thistory.replaceState = originalReplaceState\n\t\t})\n\t}\n\n\tprivate handleNavigation(source: string): void {\n\t\tif (!this.isEnabled) return\n\n\t\t// Debounce rapid navigations\n\t\tsetTimeout(() => {\n\t\t\tconst currentUrl = window.location.href\n\n\t\t\t// Only track if URL actually changed\n\t\t\tif (this.currentPage?.url !== currentUrl) {\n\t\t\t\tthis.trackPageView()\n\t\t\t}\n\t\t}, 0)\n\t}\n\n\t// ==========================================\n\t// Scroll Tracking\n\t// ==========================================\n\n\tprivate trackScrollDepth(): void {\n\t\tlet ticking = false\n\n\t\tconst scrollHandler = () => {\n\t\t\tif (!ticking) {\n\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\tthis.updateScrollDepth()\n\t\t\t\t\tticking = false\n\t\t\t\t})\n\t\t\t\tticking = true\n\t\t\t}\n\t\t}\n\n\t\twindow.addEventListener('scroll', scrollHandler, { passive: true })\n\t\tthis.cleanupFns.push(() => window.removeEventListener('scroll', scrollHandler))\n\n\t\t// Also track on resize (content height may change)\n\t\twindow.addEventListener('resize', scrollHandler, { passive: true })\n\t\tthis.cleanupFns.push(() => window.removeEventListener('resize', scrollHandler))\n\t}\n\n\tprivate updateScrollDepth(): void {\n\t\tif (!this.currentPage) return\n\n\t\tconst scrollTop = window.scrollY || document.documentElement.scrollTop\n\t\tconst windowHeight = window.innerHeight\n\t\tconst documentHeight = Math.max(\n\t\t\tdocument.body.scrollHeight,\n\t\t\tdocument.documentElement.scrollHeight,\n\t\t)\n\n\t\t// Calculate scroll percentage\n\t\tconst maxScroll = documentHeight - windowHeight\n\t\tconst scrollPercent = maxScroll > 0 ? Math.round((scrollTop / maxScroll) * 100) : 100\n\n\t\t// Update max scroll depth\n\t\tif (scrollPercent > this.currentPage.maxScrollDepth) {\n\t\t\tthis.currentPage.maxScrollDepth = Math.min(scrollPercent, 100)\n\t\t}\n\t}\n\n\t// ==========================================\n\t// Visibility Tracking\n\t// ==========================================\n\n\tprivate trackVisibility(): void {\n\t\tconst visibilityHandler = () => {\n\t\t\tif (document.hidden) {\n\t\t\t\t// Page became hidden - could pause timer\n\t\t\t} else {\n\t\t\t\t// Page became visible - could resume timer\n\t\t\t}\n\t\t}\n\n\t\tdocument.addEventListener('visibilitychange', visibilityHandler)\n\t\tthis.cleanupFns.push(() => document.removeEventListener('visibilitychange', visibilityHandler))\n\t}\n\n\t// ==========================================\n\t// Page Leave\n\t// ==========================================\n\n\tprivate handlePageLeave(): void {\n\t\tif (!this.currentPage || !this.pageLeaveCallback) return\n\n\t\tconst now = Date.now()\n\t\tconst timeOnPage = now - this.currentPage.enteredAt\n\n\t\tthis.pageLeaveCallback({\n\t\t\turl: this.currentPage.url,\n\t\t\tpath: this.currentPage.path,\n\t\t\ttimeOnPage,\n\t\t\tscrollDepth: this.currentPage.maxScrollDepth,\n\t\t\ttimestamp: now,\n\t\t})\n\t}\n\n\t// ==========================================\n\t// Context Helpers\n\t// ==========================================\n\n\tprivate getPageContext(): PageContext {\n\t\treturn {\n\t\t\t$current_url: window.location.href,\n\t\t\t$host: window.location.host,\n\t\t\t$pathname: window.location.pathname,\n\t\t\t$search: window.location.search || undefined,\n\t\t\t$hash: window.location.hash || undefined,\n\t\t\t$title: document.title,\n\t\t}\n\t}\n\n\tprivate getUtmParams(): UtmParams | undefined {\n\t\tconst params = new URLSearchParams(window.location.search)\n\t\tconst utm: UtmParams = {}\n\n\t\tconst utmKeys = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content'] as const\n\n\t\tlet hasUtm = false\n\t\tfor (const key of utmKeys) {\n\t\t\tconst value = params.get(key)\n\t\t\tif (value) {\n\t\t\t\tutm[key] = value\n\t\t\t\thasUtm = true\n\t\t\t}\n\t\t}\n\n\t\treturn hasUtm ? utm : undefined\n\t}\n\n\tprivate getDeviceContext(): DeviceContext {\n\t\tconst ua = navigator.userAgent\n\n\t\treturn {\n\t\t\t$device_type: this.detectDeviceType(ua),\n\t\t\t$os: this.detectOS(ua),\n\t\t\t$browser: this.detectBrowser(ua),\n\t\t\t$browser_language: navigator.language,\n\t\t\t$screen_height: window.screen.height,\n\t\t\t$screen_width: window.screen.width,\n\t\t\t$viewport_height: window.innerHeight,\n\t\t\t$viewport_width: window.innerWidth,\n\t\t\t$device_pixel_ratio: window.devicePixelRatio,\n\t\t\t$timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n\t\t}\n\t}\n\n\tprivate detectDeviceType(ua: string): DeviceContext['$device_type'] {\n\t\tif (/bot|crawler|spider|crawling/i.test(ua)) return 'Bot'\n\t\tif (/mobile/i.test(ua)) return 'Mobile'\n\t\tif (/tablet|ipad/i.test(ua)) return 'Tablet'\n\t\treturn 'Desktop'\n\t}\n\n\tprivate detectOS(ua: string): string | undefined {\n\t\tconst osPatterns: [RegExp, string][] = [\n\t\t\t[/Windows NT 10/i, 'Windows 10'],\n\t\t\t[/Windows NT 6.3/i, 'Windows 8.1'],\n\t\t\t[/Windows NT 6.2/i, 'Windows 8'],\n\t\t\t[/Windows/i, 'Windows'],\n\t\t\t[/Mac OS X ([0-9_]+)/i, 'macOS'],\n\t\t\t[/iPhone|iPad|iPod/i, 'iOS'],\n\t\t\t[/Android ([0-9.]+)/i, 'Android'],\n\t\t\t[/Linux/i, 'Linux'],\n\t\t\t[/CrOS/i, 'Chrome OS'],\n\t\t]\n\n\t\tfor (const [pattern, name] of osPatterns) {\n\t\t\tif (pattern.test(ua)) {\n\t\t\t\treturn name\n\t\t\t}\n\t\t}\n\n\t\treturn undefined\n\t}\n\n\tprivate detectBrowser(ua: string): string | undefined {\n\t\tconst browserPatterns: [RegExp, string][] = [\n\t\t\t[/Edg\\//i, 'Edge'],\n\t\t\t[/OPR\\//i, 'Opera'],\n\t\t\t[/Chrome\\/([0-9.]+)/i, 'Chrome'],\n\t\t\t[/Safari\\/([0-9.]+)/i, 'Safari'],\n\t\t\t[/Firefox\\/([0-9.]+)/i, 'Firefox'],\n\t\t]\n\n\t\tfor (const [pattern, name] of browserPatterns) {\n\t\t\tif (pattern.test(ua)) {\n\t\t\t\treturn name\n\t\t\t}\n\t\t}\n\n\t\treturn undefined\n\t}\n}\n\n// ==========================================\n// Referrer Analysis\n// ==========================================\n\n/**\n * Analyze referrer to determine traffic source\n */\nexport function analyzeReferrer(referrer: string): ReferrerData {\n\tif (!referrer) {\n\t\treturn {\n\t\t\t$referrer_source: 'direct',\n\t\t}\n\t}\n\n\ttry {\n\t\tconst url = new URL(referrer)\n\t\tconst domain = url.hostname.replace('www.', '')\n\n\t\tconst result: ReferrerData = {\n\t\t\t$referrer: referrer,\n\t\t\t$referring_domain: domain,\n\t\t}\n\n\t\t// Categorize traffic source\n\t\tconst searchEngines = ['google', 'bing', 'yahoo', 'duckduckgo', 'baidu', 'yandex']\n\t\tconst socialNetworks = [\n\t\t\t'facebook',\n\t\t\t'twitter',\n\t\t\t'linkedin',\n\t\t\t'instagram',\n\t\t\t'tiktok',\n\t\t\t'reddit',\n\t\t\t'pinterest',\n\t\t\t'youtube',\n\t\t]\n\n\t\tif (searchEngines.some((se) => domain.includes(se))) {\n\t\t\tresult.$referrer_source = 'organic'\n\t\t} else if (socialNetworks.some((sn) => domain.includes(sn))) {\n\t\t\tresult.$referrer_source = 'social'\n\t\t} else if (domain.includes('mail') || domain.includes('outlook')) {\n\t\t\tresult.$referrer_source = 'email'\n\t\t} else {\n\t\t\tresult.$referrer_source = 'unknown'\n\t\t}\n\n\t\treturn result\n\t} catch {\n\t\treturn {\n\t\t\t$referrer: referrer,\n\t\t\t$referrer_source: 'unknown',\n\t\t}\n\t}\n}\n\n// ==========================================\n// Factory\n// ==========================================\n\nlet navigationTrackerInstance: NavigationTracker | null = null\n\n/**\n * Initialize navigation tracker\n */\nexport function initNavigationTracker(\n\tonPageView: PageViewCallback,\n\tonPageLeave?: PageLeaveCallback,\n): NavigationTracker {\n\tnavigationTrackerInstance = new NavigationTracker(onPageView, onPageLeave)\n\treturn navigationTrackerInstance\n}\n\n/**\n * Get navigation tracker instance\n */\nfunction _getNavigationTracker(): NavigationTracker | null {\n\treturn navigationTrackerInstance\n}\n","/**\n * Analytics Tracker\n *\n * Core analytics engine with:\n * - Smart autocapture\n * - SPA navigation tracking\n * - Event batching & queuing\n * - User identification\n * - Session management\n */\n\nimport {\n\tANALYTICS_FLUSH_INTERVAL_MS,\n\tANALYTICS_MAX_RETRIES,\n\tANALYTICS_RETRY_BASE_DELAY_MS,\n\tANALYTICS_RETRY_JITTER,\n\tANALYTICS_RETRY_MAX_DELAY_MS,\n\tANALYTICS_SESSION_TIMEOUT_MS,\n\tSDK_API_PATH,\n} from '../../constants'\nimport { Autocapture, type AutocaptureEvent } from './autocapture'\nimport {\n\tanalyzeReferrer,\n\tNavigationTracker,\n\ttype PageLeaveEvent,\n\ttype PageViewEvent,\n} from './navigation'\nimport type {\n\tAnalyticsConfig,\n\tAnalyticsEvent,\n\tAttributionData,\n\tDeviceContext,\n\tEventProperties,\n\tGroupProperties,\n\tPageContext,\n\tPropertyValue,\n\tQueuedEvent,\n\tUserProperties,\n} from './types'\nimport {\n\tDEFAULT_ANALYTICS_CONFIG,\n\tDEFAULT_AUTOCAPTURE_CONFIG,\n\ttype NavigatorWithUAData,\n} from './types'\n\n// ==========================================\n// Analytics Tracker\n// ==========================================\n\n/**\n * Analytics Tracker\n *\n * Comprehensive client-side analytics with automatic event capture.\n */\nexport class AnalyticsTracker {\n\tprivate config: AnalyticsConfig\n\tprivate distinctId: string | null = null\n\tprivate anonymousId: string\n\tprivate sessionId: string\n\tprivate queue: QueuedEvent[] = []\n\tprivate flushTimeout: ReturnType<typeof setTimeout> | null = null\n\tprivate autocapture: Autocapture | null = null\n\tprivate navigationTracker: NavigationTracker | null = null\n\tprivate attribution: AttributionData = {}\n\tprivate superProperties: EventProperties = {}\n\tprivate isInitialized = false\n\n\tconstructor(config: Partial<AnalyticsConfig> = {}) {\n\t\tthis.config = { ...DEFAULT_ANALYTICS_CONFIG, ...config }\n\t\tthis.anonymousId = this.getOrCreateAnonymousId()\n\t\tthis.sessionId = this.getOrCreateSessionId()\n\t}\n\n\t// ==========================================\n\t// Initialization\n\t// ==========================================\n\n\t/**\n\t * Initialize analytics\n\t */\n\tinit(): void {\n\t\tif (typeof window === 'undefined') return\n\t\tif (this.isInitialized) return\n\n\t\tthis.isInitialized = true\n\n\t\t// Capture initial attribution data\n\t\tthis.captureAttribution()\n\n\t\t// Setup autocapture\n\t\tif (this.config.autocapture) {\n\t\t\tconst autocaptureConfig =\n\t\t\t\ttypeof this.config.autocapture === 'object'\n\t\t\t\t\t? this.config.autocapture\n\t\t\t\t\t: DEFAULT_AUTOCAPTURE_CONFIG\n\n\t\t\tthis.autocapture = new Autocapture(\n\t\t\t\t(event) => this.handleAutocaptureEvent(event),\n\t\t\t\tautocaptureConfig,\n\t\t\t)\n\t\t\tthis.autocapture.start()\n\t\t}\n\n\t\t// Setup navigation tracking\n\t\tif (this.config.capturePageviews || this.config.captureSpaNavigation) {\n\t\t\tthis.navigationTracker = new NavigationTracker(\n\t\t\t\t(event) => this.handlePageView(event),\n\t\t\t\tthis.config.capturePageleave ? (event) => this.handlePageLeave(event) : undefined,\n\t\t\t)\n\t\t\tthis.navigationTracker.start()\n\t\t}\n\n\t\t// Load persisted queue\n\t\tthis.loadQueue()\n\n\t\t// Start flush interval\n\t\tthis.startFlushInterval()\n\n\t\t// Handle page unload - flush remaining events\n\t\twindow.addEventListener('beforeunload', () => this.flush())\n\n\t\tthis.debug('Analytics initialized', {\n\t\t\tanonymousId: this.anonymousId,\n\t\t\tsessionId: this.sessionId,\n\t\t})\n\t}\n\n\t/**\n\t * Shutdown analytics\n\t */\n\tshutdown(): void {\n\t\tthis.autocapture?.stop()\n\t\tthis.navigationTracker?.stop()\n\t\tthis.stopFlushInterval()\n\t\tthis.flush()\n\t\tthis.isInitialized = false\n\t}\n\n\t// ==========================================\n\t// Identification\n\t// ==========================================\n\n\t/**\n\t * Identify a user\n\t *\n\t * Automatically aliases the previous anonymous ID to the new user ID\n\t * following the Segment/Mixpanel identity merge pattern.\n\t * This ensures anonymous activity is linked to the authenticated user.\n\t */\n\tidentify(userId: string, properties?: UserProperties): void {\n\t\tconst previousId = this.distinctId || this.anonymousId\n\t\tconst wasAnonymous = !this.distinctId && this.anonymousId !== userId\n\n\t\tthis.distinctId = userId\n\n\t\t// Track identify event\n\t\tthis.track('$identify', {\n\t\t\t$user_id: userId,\n\t\t\t$anon_distinct_id: previousId,\n\t\t\t...(properties && { $set: properties }),\n\t\t})\n\n\t\t// Auto-alias: Link anonymous ID to authenticated user (Segment/Mixpanel pattern)\n\t\t// This ensures all anonymous activity is associated with the user\n\t\tif (wasAnonymous && previousId !== userId) {\n\t\t\tthis.track('$create_alias', {\n\t\t\t\talias: userId,\n\t\t\t\tdistinct_id: previousId,\n\t\t\t})\n\t\t\tthis.debug('Auto-aliased anonymous ID to user', {\n\t\t\t\tanonymousId: previousId,\n\t\t\t\tuserId,\n\t\t\t})\n\t\t}\n\n\t\t// Persist distinct ID\n\t\tthis.persistDistinctId(userId)\n\n\t\tthis.debug('User identified', { userId, previousId })\n\t}\n\n\t/**\n\t * Reset identity (logout)\n\t */\n\treset(): void {\n\t\tthis.distinctId = null\n\t\tthis.anonymousId = this.generateId()\n\t\tthis.sessionId = this.generateId()\n\t\tthis.superProperties = {}\n\n\t\tthis.persistAnonymousId(this.anonymousId)\n\t\tthis.clearDistinctId()\n\n\t\tthis.debug('Identity reset', { anonymousId: this.anonymousId })\n\t}\n\n\t/**\n\t * Alias an identity\n\t */\n\talias(alias: string): void {\n\t\tthis.track('$create_alias', {\n\t\t\talias,\n\t\t\tdistinct_id: this.getDistinctId(),\n\t\t})\n\t}\n\n\t/**\n\t * Get current distinct ID\n\t */\n\tgetDistinctId(): string {\n\t\treturn this.distinctId || this.anonymousId\n\t}\n\n\t// ==========================================\n\t// User Properties\n\t// ==========================================\n\n\t/**\n\t * Set user properties\n\t */\n\tsetUserProperties(properties: UserProperties): void {\n\t\tthis.track('$set', {\n\t\t\t$set: properties,\n\t\t})\n\t}\n\n\t/**\n\t * Set user properties once (only if not already set)\n\t */\n\tsetUserPropertiesOnce(properties: UserProperties): void {\n\t\tthis.track('$set_once', {\n\t\t\t$set_once: properties,\n\t\t})\n\t}\n\n\t/**\n\t * Increment numeric user property\n\t */\n\tincrementUserProperty(property: string, value = 1): void {\n\t\tthis.track('$set', {\n\t\t\t$add: { [property]: value },\n\t\t})\n\t}\n\n\t// ==========================================\n\t// Groups\n\t// ==========================================\n\n\t/**\n\t * Associate user with a group\n\t */\n\tgroup(groupType: string, groupKey: string, properties?: GroupProperties): void {\n\t\tthis.track('$groupidentify', {\n\t\t\t$group_type: groupType,\n\t\t\t$group_key: groupKey,\n\t\t\t...(properties && { $group_set: properties }),\n\t\t})\n\t}\n\n\t// ==========================================\n\t// Event Tracking\n\t// ==========================================\n\n\t/**\n\t * Track a custom event\n\t */\n\ttrack(eventName: string, properties: EventProperties = {}): void {\n\t\tconst event = this.buildEvent(eventName, properties)\n\n\t\t// Apply beforeSend hook\n\t\tif (this.config.beforeSend) {\n\t\t\tconst processedEvent = this.config.beforeSend(event)\n\t\t\tif (!processedEvent) return\n\t\t\tthis.enqueue(processedEvent)\n\t\t} else {\n\t\t\tthis.enqueue(event)\n\t\t}\n\n\t\tthis.debug('Event tracked', { event: eventName, properties })\n\t}\n\n\t/**\n\t * Register super properties (added to all events)\n\t */\n\tregister(properties: EventProperties): void {\n\t\tthis.superProperties = {\n\t\t\t...this.superProperties,\n\t\t\t...properties,\n\t\t}\n\t}\n\n\t/**\n\t * Register super properties once\n\t */\n\tregisterOnce(properties: EventProperties): void {\n\t\tfor (const [key, value] of Object.entries(properties)) {\n\t\t\tif (!(key in this.superProperties)) {\n\t\t\t\tthis.superProperties[key] = value\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Unregister a super property\n\t */\n\tunregister(propertyName: string): void {\n\t\tdelete this.superProperties[propertyName]\n\t}\n\n\t// ==========================================\n\t// Event Building\n\t// ==========================================\n\n\tprivate buildEvent(eventName: string, properties: EventProperties): AnalyticsEvent {\n\t\tconst timestamp = new Date().toISOString()\n\n\t\t// Merge properties\n\t\tlet mergedProperties: EventProperties = {\n\t\t\t...this.config.defaultProperties,\n\t\t\t...this.superProperties,\n\t\t\t...this.attribution,\n\t\t\t...this.getDeviceContext(),\n\t\t\t...this.getPageContext(),\n\t\t\t...properties,\n\t\t\t$session_id: this.sessionId,\n\t\t}\n\n\t\t// Apply denylist\n\t\tif (this.config.propertyDenylist) {\n\t\t\tfor (const key of this.config.propertyDenylist) {\n\t\t\t\tdelete mergedProperties[key]\n\t\t\t}\n\t\t}\n\n\t\t// Apply sanitization\n\t\tif (this.config.sanitize) {\n\t\t\tmergedProperties = this.config.sanitize(mergedProperties)\n\t\t}\n\n\t\treturn {\n\t\t\tevent: eventName,\n\t\t\tproperties: mergedProperties,\n\t\t\tdistinct_id: this.getDistinctId(),\n\t\t\ttimestamp,\n\t\t\t$lib: 'sylphx-runtime',\n\t\t\t$lib_version: '0.5.0',\n\t\t}\n\t}\n\n\t// ==========================================\n\t// Autocapture Handling\n\t// ==========================================\n\n\tprivate handleAutocaptureEvent(event: AutocaptureEvent): void {\n\t\tthis.track('$autocapture', {\n\t\t\t$event_type: event.eventType,\n\t\t\t// ElementData[] is semantically compatible with PropertyValue (array of objects)\n\t\t\t// but TypeScript requires explicit cast due to index signature differences\n\t\t\t// between ElementData's `attr__*` keys and PropertyValue's `[key: string]`\n\t\t\t$elements: event.elements as unknown as PropertyValue,\n\t\t\t$element_name: event.elementName,\n\t\t\t...event.properties,\n\t\t})\n\n\t\t// Also track as a named event for easier querying\n\t\tthis.track(event.eventName, {\n\t\t\t$autocaptured: true,\n\t\t\t$element_name: event.elementName,\n\t\t\t...event.properties,\n\t\t})\n\t}\n\n\t// ==========================================\n\t// Navigation Handling\n\t// ==========================================\n\n\tprivate handlePageView(event: PageViewEvent): void {\n\t\tthis.track('$pageview', {\n\t\t\t...event.context,\n\t\t\t...(event.utm || {}),\n\t\t\t$title: event.title,\n\t\t\t$referrer: event.referrer,\n\t\t\t...(event.previousPageTime !== undefined && {\n\t\t\t\t$previous_page_time: event.previousPageTime,\n\t\t\t}),\n\t\t\t...(event.previousScrollDepth !== undefined && {\n\t\t\t\t$previous_scroll_depth: event.previousScrollDepth,\n\t\t\t}),\n\t\t})\n\t}\n\n\tprivate handlePageLeave(event: PageLeaveEvent): void {\n\t\tthis.track('$pageleave', {\n\t\t\t$current_url: event.url,\n\t\t\t$pathname: event.path,\n\t\t\t$time_on_page: event.timeOnPage,\n\t\t\t$scroll_depth: event.scrollDepth,\n\t\t})\n\t}\n\n\t// ==========================================\n\t// Queue Management\n\t// ==========================================\n\n\tprivate enqueue(event: AnalyticsEvent): void {\n\t\tthis.queue.push({\n\t\t\tevent,\n\t\t\ttimestamp: Date.now(),\n\t\t\tretries: 0,\n\t\t})\n\n\t\tthis.persistQueue()\n\n\t\t// Check if we should flush\n\t\tif (this.queue.length >= (this.config.batchSize ?? 10)) {\n\t\t\tthis.flush()\n\t\t}\n\t}\n\n\t/**\n\t * Flush queued events to the server\n\t *\n\t * Implements exponential backoff with jitter (Segment pattern):\n\t * - Base delay: 1 second\n\t * - Max delay: 30 seconds\n\t * - Jitter: ±20% to prevent thundering herd\n\t * - Max retries: 10\n\t */\n\tasync flush(): Promise<void> {\n\t\tif (this.queue.length === 0) return\n\n\t\tconst now = Date.now()\n\n\t\t// Filter to only events ready for retry (backoff elapsed)\n\t\tconst readyEvents: QueuedEvent[] = []\n\t\tconst pendingEvents: QueuedEvent[] = []\n\n\t\tfor (const item of this.queue) {\n\t\t\tif (!item.nextRetryAt || item.nextRetryAt <= now) {\n\t\t\t\treadyEvents.push(item)\n\t\t\t} else {\n\t\t\t\tpendingEvents.push(item)\n\t\t\t}\n\t\t}\n\n\t\tif (readyEvents.length === 0) {\n\t\t\tthis.debug('No events ready for flush (backoff pending)', {\n\t\t\t\tpendingCount: pendingEvents.length,\n\t\t\t})\n\t\t\treturn\n\t\t}\n\n\t\t// Take batch from ready events\n\t\tconst batchSize = this.config.batchSize ?? 10\n\t\tconst batch = readyEvents.splice(0, batchSize)\n\n\t\t// Update queue: remaining ready events + pending events\n\t\tthis.queue = [...readyEvents, ...pendingEvents]\n\n\t\ttry {\n\t\t\tawait this.sendBatch(batch.map((q) => q.event))\n\t\t\tthis.persistQueue()\n\t\t} catch (error) {\n\t\t\t// Put failed events back with exponential backoff\n\t\t\tfor (const item of batch) {\n\t\t\t\tif (item.retries < ANALYTICS_MAX_RETRIES) {\n\t\t\t\t\tconst nextRetry = item.retries + 1\n\t\t\t\t\tconst delay = this.calculateBackoffDelay(nextRetry)\n\t\t\t\t\tthis.queue.unshift({\n\t\t\t\t\t\t...item,\n\t\t\t\t\t\tretries: nextRetry,\n\t\t\t\t\t\tnextRetryAt: now + delay,\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\t// Max retries exceeded - drop event\n\t\t\t\t\tthis.debug('Event dropped after max retries', {\n\t\t\t\t\t\tevent: item.event.event,\n\t\t\t\t\t\tretries: item.retries,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.persistQueue()\n\t\t\tthis.debug('Flush failed, scheduling retry with backoff', {\n\t\t\t\terror,\n\t\t\t\tretriesRemaining: ANALYTICS_MAX_RETRIES - (batch[0]?.retries ?? 0),\n\t\t\t\tnextRetryIn: this.calculateBackoffDelay((batch[0]?.retries ?? 0) + 1),\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Calculate exponential backoff delay with jitter\n\t *\n\t * Formula: min(base * 2^retries, maxDelay) * (1 ± jitter)\n\t * This prevents thundering herd when multiple clients fail simultaneously.\n\t */\n\tprivate calculateBackoffDelay(retryCount: number): number {\n\t\t// Exponential: base * 2^retries\n\t\tconst exponentialDelay = ANALYTICS_RETRY_BASE_DELAY_MS * 2 ** (retryCount - 1)\n\n\t\t// Cap at max delay\n\t\tconst cappedDelay = Math.min(exponentialDelay, ANALYTICS_RETRY_MAX_DELAY_MS)\n\n\t\t// Add jitter: ±JITTER%\n\t\tconst jitterRange = cappedDelay * ANALYTICS_RETRY_JITTER\n\t\tconst jitter = (Math.random() * 2 - 1) * jitterRange\n\n\t\treturn Math.round(cappedDelay + jitter)\n\t}\n\n\tprivate async sendBatch(events: AnalyticsEvent[]): Promise<void> {\n\t\tconst endpoint = this.config.apiEndpoint ?? `${SDK_API_PATH}/analytics/track`\n\n\t\tconst payload = {\n\t\t\tevents: events,\n\t\t}\n\n\t\tconst headers: Record<string, string> = {\n\t\t\t'Content-Type': 'application/json',\n\t\t}\n\t\tif (this.config.apiKey) {\n\t\t\theaders['x-app-secret'] = this.config.apiKey\n\t\t}\n\n\t\tconst response = await fetch(endpoint, {\n\t\t\tmethod: 'POST',\n\t\t\theaders,\n\t\t\tbody: JSON.stringify(payload),\n\t\t\tkeepalive: true, // Allow request to complete on page unload\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(`Analytics send failed: ${response.status}`)\n\t\t}\n\t}\n\n\t// ==========================================\n\t// Flush Interval\n\t// ==========================================\n\n\tprivate startFlushInterval(): void {\n\t\tif (this.flushTimeout) return\n\n\t\tconst interval = this.config.flushInterval ?? ANALYTICS_FLUSH_INTERVAL_MS\n\n\t\tconst scheduleFlush = () => {\n\t\t\tthis.flushTimeout = setTimeout(() => {\n\t\t\t\tvoid this.flush()\n\t\t\t\tscheduleFlush()\n\t\t\t}, interval)\n\t\t}\n\n\t\tscheduleFlush()\n\t}\n\n\tprivate stopFlushInterval(): void {\n\t\tif (this.flushTimeout) {\n\t\t\tclearTimeout(this.flushTimeout)\n\t\t\tthis.flushTimeout = null\n\t\t}\n\t}\n\n\t// ==========================================\n\t// Context Helpers\n\t// ==========================================\n\n\t/**\n\t * Get device context with User-Agent Client Hints API support\n\t *\n\t * Uses the modern Client Hints API when available, falls back to\n\t * basic detection for older browsers.\n\t *\n\t * @see https://developer.mozilla.org/en-US/docs/Web/API/User-Agent_Client_Hints_API\n\t */\n\tprivate getDeviceContext(): DeviceContext {\n\t\tif (typeof window === 'undefined') return {}\n\n\t\tlet screenHeight: number | undefined\n\t\tlet screenWidth: number | undefined\n\t\ttry {\n\t\t\tscreenHeight = window.screen?.height\n\t\t\tscreenWidth = window.screen?.width\n\t\t} catch {\n\t\t\t// screen not available in non-browser environments\n\t\t}\n\n\t\tconst context: DeviceContext = {\n\t\t\t$screen_height: screenHeight,\n\t\t\t$screen_width: screenWidth,\n\t\t\t$viewport_height: window.innerHeight,\n\t\t\t$viewport_width: window.innerWidth,\n\t\t\t$device_pixel_ratio: window.devicePixelRatio,\n\t\t\t$browser_language: typeof navigator !== 'undefined' ? navigator.language : undefined,\n\t\t\t$timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n\t\t}\n\n\t\t// Use User-Agent Client Hints API if available (Chromium browsers)\n\t\t// @see https://developer.mozilla.org/en-US/docs/Web/API/NavigatorUAData\n\t\tconst uaData =\n\t\t\ttypeof navigator !== 'undefined'\n\t\t\t\t? (navigator as NavigatorWithUAData).userAgentData\n\t\t\t\t: undefined\n\t\tif (uaData) {\n\t\t\t// Sync properties (low entropy, always available)\n\t\t\tcontext.$device_type = uaData.mobile ? 'Mobile' : 'Desktop'\n\t\t\tcontext.$os = uaData.platform\n\n\t\t\t// Get browser from brands (use first significant brand)\n\t\t\tconst brand = uaData.brands?.find((b) => !b.brand.includes('Not') && b.brand !== 'Chromium')\n\t\t\tif (brand) {\n\t\t\t\tcontext.$browser = brand.brand\n\t\t\t\tcontext.$browser_version = brand.version\n\t\t\t}\n\t\t} else {\n\t\t\t// Fallback: Basic detection from user agent string\n\t\t\tcontext.$device_type = this.detectDeviceType()\n\t\t\tconst browserInfo = this.detectBrowser()\n\t\t\tcontext.$browser = browserInfo.name\n\t\t\tcontext.$browser_version = browserInfo.version\n\t\t\tcontext.$os = this.detectOS()\n\t\t}\n\n\t\treturn context\n\t}\n\n\t/**\n\t * Detect device type from screen size (fallback when Client Hints unavailable)\n\t */\n\tprivate detectDeviceType(): DeviceContext['$device_type'] {\n\t\tif (typeof window === 'undefined') return undefined\n\n\t\tlet width: number | undefined\n\t\ttry {\n\t\t\twidth = window.screen?.width\n\t\t} catch {\n\t\t\t/* non-browser env */\n\t\t}\n\t\tconst isTouchDevice =\n\t\t\t'ontouchstart' in window || (typeof navigator !== 'undefined' && navigator.maxTouchPoints > 0)\n\n\t\tif (!isTouchDevice) return 'Desktop'\n\t\tif (width !== undefined && width < 768) return 'Mobile'\n\t\tif (width !== undefined && width < 1024) return 'Tablet'\n\t\treturn 'Desktop'\n\t}\n\n\t/**\n\t * Detect browser from user agent (fallback when Client Hints unavailable)\n\t */\n\tprivate detectBrowser(): { name?: string; version?: string } {\n\t\tif (typeof navigator === 'undefined') return {}\n\n\t\tconst ua = navigator.userAgent\n\t\tlet name: string | undefined\n\t\tlet version: string | undefined\n\n\t\t// Order matters - check specific browsers first\n\t\tif (ua.includes('Firefox/')) {\n\t\t\tname = 'Firefox'\n\t\t\tversion = ua.match(/Firefox\\/(\\d+\\.\\d+)/)?.[1]\n\t\t} else if (ua.includes('Edg/')) {\n\t\t\tname = 'Edge'\n\t\t\tversion = ua.match(/Edg\\/(\\d+\\.\\d+)/)?.[1]\n\t\t} else if (ua.includes('Chrome/')) {\n\t\t\tname = 'Chrome'\n\t\t\tversion = ua.match(/Chrome\\/(\\d+\\.\\d+)/)?.[1]\n\t\t} else if (ua.includes('Safari/') && !ua.includes('Chrome')) {\n\t\t\tname = 'Safari'\n\t\t\tversion = ua.match(/Version\\/(\\d+\\.\\d+)/)?.[1]\n\t\t}\n\n\t\treturn { name, version }\n\t}\n\n\t/**\n\t * Detect OS from user agent (fallback when Client Hints unavailable)\n\t */\n\tprivate detectOS(): string | undefined {\n\t\tif (typeof navigator === 'undefined') return undefined\n\n\t\tconst ua = navigator.userAgent\n\n\t\tif (ua.includes('Windows')) return 'Windows'\n\t\tif (ua.includes('Mac OS X')) return 'macOS'\n\t\tif (ua.includes('Linux')) return 'Linux'\n\t\tif (ua.includes('Android')) return 'Android'\n\t\tif (ua.includes('iPhone') || ua.includes('iPad')) return 'iOS'\n\n\t\treturn undefined\n\t}\n\n\tprivate getPageContext(): PageContext {\n\t\tif (typeof window === 'undefined') {\n\t\t\treturn {\n\t\t\t\t$current_url: '',\n\t\t\t\t$host: '',\n\t\t\t\t$pathname: '',\n\t\t\t}\n\t\t}\n\n\t\tif (!window.location) {\n\t\t\treturn { $current_url: '', $host: '', $pathname: '' }\n\t\t}\n\n\t\treturn {\n\t\t\t$current_url: window.location.href,\n\t\t\t$host: window.location.host,\n\t\t\t$pathname: window.location.pathname,\n\t\t}\n\t}\n\n\t// ==========================================\n\t// Attribution\n\t// ==========================================\n\n\tprivate captureAttribution(): void {\n\t\tif (typeof window === 'undefined') return\n\n\t\t// UTM params\n\t\tif (!window.location) return\n\t\tconst params = new URLSearchParams(window.location.search)\n\t\tconst utmKeys = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content'] as const\n\n\t\tfor (const key of utmKeys) {\n\t\t\tconst value = params.get(key)\n\t\t\tif (value) {\n\t\t\t\t;(this.attribution as Record<string, string | undefined>)[key] = value\n\n\t\t\t\t// Also store as initial if not already set\n\t\t\t\tconst initialKey = `$initial_${key}`\n\t\t\t\tif (!this.loadInitialAttribution(initialKey as keyof AttributionData)) {\n\t\t\t\t\t;(this.attribution as Record<string, string | undefined>)[initialKey] = value\n\t\t\t\t\tthis.persistInitialAttribution(initialKey as keyof AttributionData, value)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Referrer\n\t\tconst referrer = document.referrer\n\t\tif (referrer) {\n\t\t\tconst referrerData = analyzeReferrer(referrer)\n\t\t\tthis.attribution = { ...this.attribution, ...referrerData }\n\n\t\t\t// Store initial referrer\n\t\t\tif (!this.loadInitialAttribution('$initial_referrer')) {\n\t\t\t\tthis.attribution.$initial_referrer = referrer\n\t\t\t\tthis.attribution.$initial_referring_domain = referrerData.$referring_domain\n\t\t\t\tthis.persistInitialAttribution('$initial_referrer', referrer)\n\t\t\t\tif (referrerData.$referring_domain) {\n\t\t\t\t\tthis.persistInitialAttribution(\n\t\t\t\t\t\t'$initial_referring_domain',\n\t\t\t\t\t\treferrerData.$referring_domain,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// ==========================================\n\t// Persistence\n\t// ==========================================\n\n\tprivate getStorageKey(suffix: string): string {\n\t\treturn `sylphx_analytics_${suffix}`\n\t}\n\n\tprivate getStorage(): Storage | null {\n\t\tif (typeof window === 'undefined' || typeof localStorage === 'undefined') return null\n\n\t\tswitch (this.config.persistence) {\n\t\t\tcase 'localStorage':\n\t\t\t\treturn localStorage\n\t\t\tcase 'cookie':\n\t\t\t\t// Cookie storage handled separately via document.cookie\n\t\t\t\t// Fall back to localStorage for compatibility\n\t\t\t\treturn localStorage\n\t\t\tcase 'none':\n\t\t\t\treturn null\n\t\t\tdefault:\n\t\t\t\treturn localStorage\n\t\t}\n\t}\n\n\tprivate getOrCreateAnonymousId(): string {\n\t\tconst storage = this.getStorage()\n\t\tif (storage) {\n\t\t\tconst stored = storage.getItem(this.getStorageKey('anon_id'))\n\t\t\tif (stored) return stored\n\t\t}\n\n\t\tconst id = this.generateId()\n\t\tthis.persistAnonymousId(id)\n\t\treturn id\n\t}\n\n\tprivate persistAnonymousId(id: string): void {\n\t\tconst storage = this.getStorage()\n\t\tif (storage) {\n\t\t\tstorage.setItem(this.getStorageKey('anon_id'), id)\n\t\t}\n\t}\n\n\tprivate persistDistinctId(id: string): void {\n\t\tconst storage = this.getStorage()\n\t\tif (storage) {\n\t\t\tstorage.setItem(this.getStorageKey('distinct_id'), id)\n\t\t}\n\t}\n\n\tprivate clearDistinctId(): void {\n\t\tconst storage = this.getStorage()\n\t\tif (storage) {\n\t\t\tstorage.removeItem(this.getStorageKey('distinct_id'))\n\t\t}\n\t}\n\n\tprivate getOrCreateSessionId(): string {\n\t\tconst storage = this.getStorage()\n\t\tif (storage) {\n\t\t\tconst stored = storage.getItem(this.getStorageKey('session_id'))\n\t\t\tconst timestamp = storage.getItem(this.getStorageKey('session_ts'))\n\n\t\t\tif (stored && timestamp) {\n\t\t\t\tconst lastActivity = Number.parseInt(timestamp, 10)\n\t\t\t\tconst timeout = this.config.sessionTimeout ?? ANALYTICS_SESSION_TIMEOUT_MS\n\n\t\t\t\tif (Date.now() - lastActivity < timeout) {\n\t\t\t\t\t// Update timestamp\n\t\t\t\t\tstorage.setItem(this.getStorageKey('session_ts'), Date.now().toString())\n\t\t\t\t\treturn stored\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst id = this.generateId()\n\t\tthis.persistSessionId(id)\n\t\treturn id\n\t}\n\n\tprivate persistSessionId(id: string): void {\n\t\tconst storage = this.getStorage()\n\t\tif (storage) {\n\t\t\tstorage.setItem(this.getStorageKey('session_id'), id)\n\t\t\tstorage.setItem(this.getStorageKey('session_ts'), Date.now().toString())\n\t\t}\n\t}\n\n\tprivate loadQueue(): void {\n\t\tconst storage = this.getStorage()\n\t\tif (storage) {\n\t\t\tconst stored = storage.getItem(this.getStorageKey('queue'))\n\t\t\tif (stored) {\n\t\t\t\ttry {\n\t\t\t\t\tthis.queue = JSON.parse(stored)\n\t\t\t\t} catch {\n\t\t\t\t\tthis.queue = []\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate persistQueue(): void {\n\t\tconst storage = this.getStorage()\n\t\tif (storage) {\n\t\t\tstorage.setItem(this.getStorageKey('queue'), JSON.stringify(this.queue))\n\t\t}\n\t}\n\n\tprivate loadInitialAttribution(key: keyof AttributionData): string | null {\n\t\tconst storage = this.getStorage()\n\t\tif (storage) {\n\t\t\treturn storage.getItem(this.getStorageKey(key))\n\t\t}\n\t\treturn null\n\t}\n\n\tprivate persistInitialAttribution(key: keyof AttributionData, value: string): void {\n\t\tconst storage = this.getStorage()\n\t\tif (storage) {\n\t\t\tstorage.setItem(this.getStorageKey(key), value)\n\t\t}\n\t}\n\n\t// ==========================================\n\t// Utilities\n\t// ==========================================\n\n\tprivate generateId(): string {\n\t\t// Use crypto.randomUUID if available, otherwise fallback to manual UUID v4\n\t\tif (typeof crypto !== 'undefined' && crypto.randomUUID) {\n\t\t\treturn crypto.randomUUID()\n\t\t}\n\t\treturn 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n\t\t\tconst r = (Math.random() * 16) | 0\n\t\t\tconst v = c === 'x' ? r : (r & 0x3) | 0x8\n\t\t\treturn v.toString(16)\n\t\t})\n\t}\n\n\tprivate debug(message: string, data?: unknown): void {\n\t\tif (this.config.debug) {\n\t\t}\n\t}\n}\n\n// ==========================================\n// Singleton\n// ==========================================\n\nlet trackerInstance: AnalyticsTracker | null = null\n\n/**\n * Get or create analytics tracker\n */\nexport function getAnalyticsTracker(config?: Partial<AnalyticsConfig>): AnalyticsTracker {\n\tif (!trackerInstance) {\n\t\ttrackerInstance = new AnalyticsTracker(config)\n\t}\n\treturn trackerInstance\n}\n\n/**\n * Initialize analytics\n */\nexport function initAnalytics(config?: Partial<AnalyticsConfig>): AnalyticsTracker {\n\tconst tracker = getAnalyticsTracker(config)\n\ttracker.init()\n\treturn tracker\n}\n\n/**\n * Reset analytics instance (for testing)\n */\nexport function resetAnalyticsTracker(): void {\n\ttrackerInstance?.shutdown()\n\ttrackerInstance = null\n}\n","/**\n * Analytics React Hooks\n *\n * React hooks for analytics with:\n * - Context provider for app-wide configuration\n * - Automatic user identification\n * - Page view tracking\n * - Custom event tracking\n *\n * @example\n * ```tsx\n * // 1. Wrap your app with the provider\n * function App() {\n *   return (\n *     <AnalyticsProvider\n *       config={{\n *         apiEndpoint: '/api/sdk/v1/analytics/track',\n *         autocapture: true,\n *       }}\n *     >\n *       <YourApp />\n *     </AnalyticsProvider>\n *   )\n * }\n *\n * // 2. Use analytics in components\n * function CheckoutButton() {\n *   const { track } = useAnalytics()\n *\n *   const handleClick = () => {\n *     track('checkout_started', { cart_value: 99.99 })\n *   }\n *\n *   return <button onClick={handleClick}>Checkout</button>\n * }\n *\n * // 3. Identify users after login\n * function LoginForm() {\n *   const { identify } = useAnalytics()\n *\n *   const onLogin = (user) => {\n *     identify(user.id, { email: user.email })\n *   }\n * }\n * ```\n */\n\n'use client'\n\nimport React, { createContext, useCallback, useContext, useEffect, useMemo, useRef } from 'react'\nimport { ANALYTICS_INTERVAL_CHECK_MS } from '../../constants'\nimport { type AnalyticsTracker, initAnalytics } from '../../lib/analytics'\nimport type {\n\tAnalyticsConfig,\n\tEventProperties,\n\tGroupProperties,\n\tUserProperties,\n} from '../../lib/analytics/types'\n\n// ==========================================\n// Context Types\n// ==========================================\n\ninterface AnalyticsContextValue {\n\t/** The tracker instance */\n\ttracker: AnalyticsTracker\n\t/** Whether analytics is ready */\n\tisReady: boolean\n}\n\nconst AnalyticsContext = createContext<AnalyticsContextValue | null>(null)\n\n// ==========================================\n// Provider Props\n// ==========================================\n\nexport interface AnalyticsProviderProps {\n\tchildren: React.ReactNode\n\t/** Analytics configuration */\n\tconfig?: Partial<AnalyticsConfig>\n\t/** User to identify on mount */\n\tuser?: {\n\t\tid: string\n\t\tproperties?: UserProperties\n\t}\n\t/** Disable analytics (e.g., for testing) */\n\tdisabled?: boolean\n}\n\n// ==========================================\n// Provider Component\n// ==========================================\n\n/**\n * Analytics Provider\n *\n * Provides analytics context to your app.\n */\nexport function AnalyticsProvider({\n\tchildren,\n\tconfig = {},\n\tuser,\n\tdisabled = false,\n}: AnalyticsProviderProps) {\n\tconst trackerRef = useRef<AnalyticsTracker | null>(null)\n\tconst [isReady, setIsReady] = React.useState(false)\n\n\t// Initialize tracker\n\tuseEffect(() => {\n\t\tif (disabled || typeof window === 'undefined') return\n\n\t\tconst tracker = initAnalytics(config)\n\t\ttrackerRef.current = tracker\n\t\tsetIsReady(true)\n\n\t\treturn () => {\n\t\t\ttracker.shutdown()\n\t\t}\n\t}, [disabled, config])\n\n\t// Identify user when provided\n\tuseEffect(() => {\n\t\tif (user && trackerRef.current) {\n\t\t\ttrackerRef.current.identify(user.id, user.properties)\n\t\t}\n\t}, [user])\n\n\t// Build context value\n\tconst value = useMemo<AnalyticsContextValue | null>(() => {\n\t\tif (!trackerRef.current || disabled) return null\n\n\t\treturn {\n\t\t\ttracker: trackerRef.current,\n\t\t\tisReady,\n\t\t}\n\t}, [isReady, disabled])\n\n\tif (disabled) {\n\t\treturn <>{children}</>\n\t}\n\n\treturn <AnalyticsContext.Provider value={value}>{children}</AnalyticsContext.Provider>\n}\n\n// ==========================================\n// Main Hook\n// ==========================================\n\nexport interface UseAnalyticsReturn {\n\t/** Track a custom event */\n\ttrack: (eventName: string, properties?: EventProperties) => void\n\t/** Identify a user */\n\tidentify: (userId: string, properties?: UserProperties) => void\n\t/** Reset identity (logout) */\n\treset: () => void\n\t/** Set user properties */\n\tsetUserProperties: (properties: UserProperties) => void\n\t/** Set user properties once */\n\tsetUserPropertiesOnce: (properties: UserProperties) => void\n\t/** Increment a numeric user property */\n\tincrementUserProperty: (property: string, value?: number) => void\n\t/** Associate user with a group */\n\tgroup: (groupType: string, groupKey: string, properties?: GroupProperties) => void\n\t/** Register super properties (added to all events) */\n\tregister: (properties: EventProperties) => void\n\t/** Get current distinct ID */\n\tgetDistinctId: () => string | null\n\t/** Whether analytics is ready */\n\tisReady: boolean\n\t/** Flush pending events */\n\tflush: () => Promise<void>\n}\n\n/**\n * Main analytics hook\n *\n * All hooks run unconditionally; callbacks no-op safely when the context\n * is absent, so consumers outside an AnalyticsProvider still get a stable\n * implementation.\n */\nexport function useAnalyticsHook(): UseAnalyticsReturn {\n\tconst ctx = useContext(AnalyticsContext)\n\tconst tracker = ctx?.tracker ?? null\n\tconst isReady = ctx?.isReady ?? false\n\n\tconst track = useCallback(\n\t\t(eventName: string, properties?: EventProperties) => {\n\t\t\ttracker?.track(eventName, properties)\n\t\t},\n\t\t[tracker],\n\t)\n\tconst identify = useCallback(\n\t\t(userId: string, properties?: UserProperties) => {\n\t\t\ttracker?.identify(userId, properties)\n\t\t},\n\t\t[tracker],\n\t)\n\tconst reset = useCallback(() => {\n\t\ttracker?.reset()\n\t}, [tracker])\n\tconst setUserProperties = useCallback(\n\t\t(properties: UserProperties) => {\n\t\t\ttracker?.setUserProperties(properties)\n\t\t},\n\t\t[tracker],\n\t)\n\tconst setUserPropertiesOnce = useCallback(\n\t\t(properties: UserProperties) => {\n\t\t\ttracker?.setUserPropertiesOnce(properties)\n\t\t},\n\t\t[tracker],\n\t)\n\tconst incrementUserProperty = useCallback(\n\t\t(property: string, value?: number) => {\n\t\t\ttracker?.incrementUserProperty(property, value)\n\t\t},\n\t\t[tracker],\n\t)\n\tconst group = useCallback(\n\t\t(groupType: string, groupKey: string, properties?: GroupProperties) => {\n\t\t\ttracker?.group(groupType, groupKey, properties)\n\t\t},\n\t\t[tracker],\n\t)\n\tconst register = useCallback(\n\t\t(properties: EventProperties) => {\n\t\t\ttracker?.register(properties)\n\t\t},\n\t\t[tracker],\n\t)\n\tconst getDistinctId = useCallback(() => {\n\t\treturn tracker?.getDistinctId() ?? null\n\t}, [tracker])\n\tconst flush = useCallback(async () => {\n\t\tawait tracker?.flush()\n\t}, [tracker])\n\n\treturn {\n\t\ttrack,\n\t\tidentify,\n\t\treset,\n\t\tsetUserProperties,\n\t\tsetUserPropertiesOnce,\n\t\tincrementUserProperty,\n\t\tgroup,\n\t\tregister,\n\t\tgetDistinctId,\n\t\tisReady,\n\t\tflush,\n\t}\n}\n\n// ==========================================\n// Utility Hooks\n// ==========================================\n\n/**\n * Hook to track page views manually\n */\nexport function usePageView(pageName?: string, properties?: EventProperties): void {\n\tconst { track, isReady } = useAnalyticsHook()\n\tconst hasTracked = useRef(false)\n\n\tuseEffect(() => {\n\t\tif (!isReady || hasTracked.current) return\n\n\t\thasTracked.current = true\n\t\ttrack('$pageview', {\n\t\t\t$pathname: pageName || window.location.pathname,\n\t\t\t...properties,\n\t\t})\n\t}, [isReady, track, pageName, properties])\n}\n\n/**\n * Hook to track component renders\n */\nexport function useComponentTracking(componentName: string, properties?: EventProperties): void {\n\tconst { track, isReady } = useAnalyticsHook()\n\tconst mountTime = useRef(Date.now())\n\tconst hasTracked = useRef(false)\n\n\tuseEffect(() => {\n\t\tif (!isReady || hasTracked.current) return\n\n\t\thasTracked.current = true\n\t\ttrack('component_viewed', {\n\t\t\tcomponent: componentName,\n\t\t\t...properties,\n\t\t})\n\n\t\treturn () => {\n\t\t\tconst timeVisible = Date.now() - mountTime.current\n\t\t\ttrack('component_hidden', {\n\t\t\t\tcomponent: componentName,\n\t\t\t\ttime_visible_ms: timeVisible,\n\t\t\t})\n\t\t}\n\t}, [isReady, track, componentName, properties])\n}\n\n/**\n * Hook to track feature usage\n */\nexport function useFeatureTracking(featureName: string): {\n\ttrackUsed: (properties?: EventProperties) => void\n\ttrackError: (error: Error, properties?: EventProperties) => void\n} {\n\tconst { track } = useAnalyticsHook()\n\n\tconst trackUsed = useCallback(\n\t\t(properties?: EventProperties) => {\n\t\t\ttrack('feature_used', {\n\t\t\t\tfeature: featureName,\n\t\t\t\t...properties,\n\t\t\t})\n\t\t},\n\t\t[track, featureName],\n\t)\n\n\tconst trackError = useCallback(\n\t\t(error: Error, properties?: EventProperties) => {\n\t\t\ttrack('feature_error', {\n\t\t\t\tfeature: featureName,\n\t\t\t\terror_message: error.message,\n\t\t\t\terror_name: error.name,\n\t\t\t\t...properties,\n\t\t\t})\n\t\t},\n\t\t[track, featureName],\n\t)\n\n\treturn { trackUsed, trackError }\n}\n\n/**\n * Hook to track form interactions\n */\nexport function useFormTracking(formName: string): {\n\ttrackStarted: () => void\n\ttrackCompleted: (properties?: EventProperties) => void\n\ttrackAbandoned: () => void\n\ttrackFieldFilled: (fieldName: string) => void\n\ttrackError: (fieldName: string, error: string) => void\n} {\n\tconst { track } = useAnalyticsHook()\n\tconst startTime = useRef<number | null>(null)\n\tconst fieldsFilledRef = useRef<Set<string>>(new Set())\n\n\tconst trackStarted = useCallback(() => {\n\t\tstartTime.current = Date.now()\n\t\ttrack('form_started', { form: formName })\n\t}, [track, formName])\n\n\tconst trackCompleted = useCallback(\n\t\t(properties?: EventProperties) => {\n\t\t\tconst duration = startTime.current ? Date.now() - startTime.current : undefined\n\t\t\ttrack('form_completed', {\n\t\t\t\tform: formName,\n\t\t\t\tduration_ms: duration,\n\t\t\t\tfields_filled: fieldsFilledRef.current.size,\n\t\t\t\t...properties,\n\t\t\t})\n\t\t},\n\t\t[track, formName],\n\t)\n\n\tconst trackAbandoned = useCallback(() => {\n\t\tconst duration = startTime.current ? Date.now() - startTime.current : undefined\n\t\ttrack('form_abandoned', {\n\t\t\tform: formName,\n\t\t\tduration_ms: duration,\n\t\t\tfields_filled: fieldsFilledRef.current.size,\n\t\t})\n\t}, [track, formName])\n\n\tconst trackFieldFilled = useCallback(\n\t\t(fieldName: string) => {\n\t\t\tif (!fieldsFilledRef.current.has(fieldName)) {\n\t\t\t\tfieldsFilledRef.current.add(fieldName)\n\t\t\t\ttrack('form_field_filled', {\n\t\t\t\t\tform: formName,\n\t\t\t\t\tfield: fieldName,\n\t\t\t\t})\n\t\t\t}\n\t\t},\n\t\t[track, formName],\n\t)\n\n\tconst trackError = useCallback(\n\t\t(fieldName: string, error: string) => {\n\t\t\ttrack('form_field_error', {\n\t\t\t\tform: formName,\n\t\t\t\tfield: fieldName,\n\t\t\t\terror,\n\t\t\t})\n\t\t},\n\t\t[track, formName],\n\t)\n\n\treturn {\n\t\ttrackStarted,\n\t\ttrackCompleted,\n\t\ttrackAbandoned,\n\t\ttrackFieldFilled,\n\t\ttrackError,\n\t}\n}\n\n/**\n * Hook to track time spent on a page/component\n */\nexport function useTimeTracking(\n\tname: string,\n\toptions?: {\n\t\ttrackOnUnmount?: boolean\n\t\ttrackIntervals?: number[]\n\t},\n): {\n\tgetTimeSpent: () => number\n\ttrackNow: () => void\n} {\n\tconst { track } = useAnalyticsHook()\n\tconst startTime = useRef(Date.now())\n\tconst trackedIntervals = useRef<Set<number>>(new Set())\n\n\tconst getTimeSpent = useCallback(() => {\n\t\treturn Date.now() - startTime.current\n\t}, [])\n\n\tconst trackNow = useCallback(() => {\n\t\ttrack('time_spent', {\n\t\t\tname,\n\t\t\tduration_ms: getTimeSpent(),\n\t\t})\n\t}, [track, name, getTimeSpent])\n\n\tuseEffect(() => {\n\t\tif (!options?.trackIntervals) return\n\n\t\tconst checkIntervals = () => {\n\t\t\tconst elapsed = getTimeSpent()\n\n\t\t\tfor (const interval of options.trackIntervals!) {\n\t\t\t\tif (elapsed >= interval && !trackedIntervals.current.has(interval)) {\n\t\t\t\t\ttrackedIntervals.current.add(interval)\n\t\t\t\t\ttrack('time_milestone', {\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tmilestone_ms: interval,\n\t\t\t\t\t\tactual_ms: elapsed,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst intervalId = setInterval(checkIntervals, ANALYTICS_INTERVAL_CHECK_MS)\n\t\treturn () => clearInterval(intervalId)\n\t}, [track, name, getTimeSpent, options?.trackIntervals])\n\n\tuseEffect(() => {\n\t\tif (!options?.trackOnUnmount) return\n\n\t\treturn () => {\n\t\t\ttrack('time_spent', {\n\t\t\t\tname,\n\t\t\t\tduration_ms: getTimeSpent(),\n\t\t\t})\n\t\t}\n\t}, [track, name, getTimeSpent, options?.trackOnUnmount])\n\n\treturn { getTimeSpent, trackNow }\n}\n\n// ==========================================\n// Export Types\n// ==========================================\n","/**\n * Destination Router React Hook\n *\n * React integration for analytics destination routing.\n * Automatically syncs with consent state.\n *\n * @example\n * ```tsx\n * function App() {\n *   const router = useDestinationRouter({\n *     destinations: [\n *       { type: 'sylphx', config: { apiEndpoint: '/api/sdk/v1/analytics/track' } },\n *       { type: 'ga4', config: { measurementId: 'G-XXXXXX' }, consentRequired: 'analytics' },\n *     ],\n *   })\n *\n *   return (\n *     <button onClick={() => router.track('button_click', { label: 'CTA' })}>\n *       Click me\n *     </button>\n *   )\n * }\n * ```\n */\n\n'use client'\n\nimport { useCallback, useEffect, useMemo, useRef } from 'react'\nimport {\n\tcreateDestinationRouter,\n\ttype DestinationConfig,\n\ttype DestinationRouter,\n\ttype DestinationRouterConfig,\n\ttype DestinationType,\n\ttype EventProperties,\n\ttype UserProperties,\n} from '../../lib/analytics'\nimport { type ConsentCategory, useConsent } from '../consent-hooks'\nimport { useUser } from '../hooks'\n\n// ============================================\n// Types\n// ============================================\n\nexport interface UseDestinationRouterOptions\n\textends Omit<DestinationRouterConfig, 'checkConsent' | 'distinctId'> {\n\t/** Auto-sync with consent state (default: true) */\n\tsyncConsent?: boolean\n\t/** Auto-sync distinct ID with user (default: true) */\n\tsyncUser?: boolean\n\t/** Initialize on mount (default: true) */\n\tautoInit?: boolean\n}\n\nexport interface UseDestinationRouterReturn extends DestinationRouter {\n\t/** Whether router is initialized */\n\tisInitialized: boolean\n\t/** Current enabled destinations */\n\tenabledDestinations: DestinationConfig[]\n}\n\n// ============================================\n// Hook\n// ============================================\n\n/**\n * Hook for multi-destination analytics routing\n *\n * Automatically syncs with consent state and user identification.\n *\n * @param options - Router configuration\n * @returns Destination router with React integration\n *\n * @example\n * ```tsx\n * function Analytics() {\n *   const router = useDestinationRouter({\n *     destinations: [\n *       { type: 'sylphx', config: { apiEndpoint: '/api/sdk/v1/analytics/track' } },\n *       { type: 'ga4', config: { measurementId: 'G-XXXXXX' }, consentRequired: 'analytics' },\n *       { type: 'mixpanel', config: { token: 'xxx' }, consentRequired: 'analytics' },\n *     ],\n *   })\n *\n *   // Track to all destinations\n *   const handlePurchase = () => {\n *     router.track('purchase', { amount: 99.99 })\n *   }\n *\n *   // Track to specific destination only\n *   const handleConversion = () => {\n *     router.trackTo('ga4', 'conversion', { value: 99.99 })\n *   }\n *\n *   return <button onClick={handlePurchase}>Buy Now</button>\n * }\n * ```\n */\nexport function useDestinationRouter(\n\toptions: UseDestinationRouterOptions,\n): UseDestinationRouterReturn {\n\tconst {\n\t\tdestinations,\n\t\tsyncConsent = true,\n\t\tsyncUser = true,\n\t\tautoInit = true,\n\t\tdebug = false,\n\t} = options\n\n\tconst routerRef = useRef<DestinationRouter | null>(null)\n\tconst initializedRef = useRef(false)\n\n\t// Get consent state\n\tconst { hasConsent: checkConsent } = useConsent()\n\n\t// Get user\n\tconst { user } = useUser()\n\n\t// Create router once\n\tconst router = useMemo(() => {\n\t\tif (!autoInit || typeof window === 'undefined') return null\n\n\t\tconst newRouter = createDestinationRouter({\n\t\t\tdestinations,\n\t\t\tcheckConsent: syncConsent ? (category: ConsentCategory) => checkConsent(category) : undefined,\n\t\t\tdefaultConsent: !syncConsent,\n\t\t\tdebug,\n\t\t\tdistinctId: syncUser && user?.id ? user.id : undefined,\n\t\t})\n\n\t\trouterRef.current = newRouter\n\t\tinitializedRef.current = true\n\n\t\treturn newRouter\n\t}, [destinations, autoInit, syncConsent, checkConsent, debug, syncUser, user?.id])\n\n\t// Sync consent changes\n\tuseEffect(() => {\n\t\tif (!syncConsent || !routerRef.current) return\n\t\trouterRef.current.setConsentChecker((category) => checkConsent(category))\n\t}, [syncConsent, checkConsent])\n\n\t// Sync user changes\n\tuseEffect(() => {\n\t\tif (!syncUser || !routerRef.current || !user?.id) return\n\t\trouterRef.current.setDistinctId(user.id)\n\t\t// Optionally identify across destinations\n\t\trouterRef.current.identify(user.id, {\n\t\t\temail: user.email,\n\t\t\tname: user.name,\n\t\t})\n\t}, [syncUser, user?.id, user?.email, user?.name])\n\n\t// Memoized methods to prevent unnecessary re-renders\n\tconst track = useCallback(\n\t\t(event: string, properties?: EventProperties) => {\n\t\t\trouter?.track(event, properties)\n\t\t},\n\t\t[router],\n\t)\n\n\tconst trackTo = useCallback(\n\t\t(destinationType: DestinationType, event: string, properties?: EventProperties) => {\n\t\t\trouter?.trackTo(destinationType, event, properties)\n\t\t},\n\t\t[router],\n\t)\n\n\tconst identify = useCallback(\n\t\t(userId: string, traits?: UserProperties) => {\n\t\t\trouter?.identify(userId, traits)\n\t\t},\n\t\t[router],\n\t)\n\n\tconst page = useCallback(\n\t\t(name?: string, properties?: EventProperties) => {\n\t\t\trouter?.page(name, properties)\n\t\t},\n\t\t[router],\n\t)\n\n\tconst getEnabledDestinations = useCallback(() => {\n\t\treturn router?.getEnabledDestinations() || []\n\t}, [router])\n\n\tconst setDestinationEnabled = useCallback(\n\t\t(type: DestinationType, enabled: boolean) => {\n\t\t\trouter?.setDestinationEnabled(type, enabled)\n\t\t},\n\t\t[router],\n\t)\n\n\tconst setConsentChecker = useCallback(\n\t\t(fn: (category: ConsentCategory) => boolean) => {\n\t\t\trouter?.setConsentChecker(fn)\n\t\t},\n\t\t[router],\n\t)\n\n\tconst setDistinctId = useCallback(\n\t\t(id: string) => {\n\t\t\trouter?.setDistinctId(id)\n\t\t},\n\t\t[router],\n\t)\n\n\treturn {\n\t\tisInitialized: initializedRef.current,\n\t\tenabledDestinations: router?.getEnabledDestinations() || [],\n\t\ttrack,\n\t\ttrackTo,\n\t\tidentify,\n\t\tpage,\n\t\tgetEnabledDestinations,\n\t\tsetDestinationEnabled,\n\t\tsetConsentChecker,\n\t\tsetDistinctId,\n\t}\n}\n\n// ============================================\n// Context Hook\n// ============================================\n\nimport { createContext, type ReactNode, useContext } from 'react'\n\nconst DestinationRouterContext = createContext<DestinationRouter | null>(null)\n\nexport interface DestinationRouterProviderProps extends UseDestinationRouterOptions {\n\tchildren: ReactNode\n}\n\n/**\n * Provider for destination router context\n *\n * @example\n * ```tsx\n * <DestinationRouterProvider\n *   destinations={[\n *     { type: 'sylphx', config: { apiEndpoint: '/api/sdk/v1/analytics/track' } },\n *     { type: 'ga4', config: { measurementId: 'G-XXXXXX' } },\n *   ]}\n * >\n *   <App />\n * </DestinationRouterProvider>\n * ```\n */\nexport function DestinationRouterProvider({\n\tchildren,\n\t...options\n}: DestinationRouterProviderProps) {\n\tconst router = useDestinationRouter(options)\n\n\treturn (\n\t\t<DestinationRouterContext.Provider value={router}>{children}</DestinationRouterContext.Provider>\n\t)\n}\n\n/**\n * Hook to access router from context\n *\n * @example\n * ```tsx\n * function MyComponent() {\n *   const router = useRouterContext()\n *   router?.track('event', { property: 'value' })\n * }\n * ```\n */\nexport function useRouterContext(): DestinationRouter | null {\n\treturn useContext(DestinationRouterContext)\n}\n\n// Re-export types\n","/**\n * Tasks Handler\n *\n * Server-side endpoint factory for user task definitions.\n * Implements the Sylphx stateless-replay model:\n *\n *   1. Platform dispatches POST to the app's /api/tasks endpoint.\n *   2. The handler replays from the beginning.\n *   3. Completed steps hit a cache and return immediately.\n *   4. The first uncached step executes, then throws StepCompleteSignal.\n *   5. The platform saves the result and re-dispatches.\n *   6. After all steps complete the handler returns normally.\n *\n * @example\n * ```typescript\n * // app/api/tasks/route.ts\n * import { sylphx } from '@/lib/sylphx'\n *\n * const sendEmail = sylphx.tasks.define('send-email', async (payload, { step }) => {\n *   const validated = await step.run('validate', () => validateEmail(payload.to))\n *   await step.sleep('cool-down', '5 minutes')\n *   return step.run('send', () => sendEmail(validated))\n * })\n *\n * export const { GET, POST } = sylphx.tasks.handler([sendEmail])\n * ```\n */\n\nimport { createHmac, timingSafeEqual } from 'node:crypto'\nimport type {\n\tNativeSideEffectOutcome,\n\tNativeSideEffectReceipt,\n\tNativeStepContext,\n\tNativeTaskDefinition,\n} from './types'\n\n// ============================================================================\n// Signals (control flow via throw)\n// ============================================================================\n\n/**\n * Thrown by step.run() when a step's result is not yet cached.\n * The handler aborts; the platform saves the result and re-dispatches.\n */\nexport class StepCompleteSignal {\n\treadonly _isStepCompleteSignal = true\n\n\tconstructor(\n\t\tpublic readonly stepName: string,\n\t\tpublic readonly result: unknown,\n\t) {}\n}\n\nexport class StepSideEffectStartSignal {\n\treadonly _isStepSideEffectStartSignal = true\n\n\tconstructor(\n\t\tpublic readonly stepName: string,\n\t\tpublic readonly effectKey: string,\n\t\tpublic readonly externalService: string,\n\t) {}\n}\n\nexport class StepSideEffectCompleteSignal {\n\treadonly _isStepSideEffectCompleteSignal = true\n\n\tconstructor(\n\t\tpublic readonly stepName: string,\n\t\tpublic readonly effectKey: string,\n\t\tpublic readonly handle: string | undefined,\n\t\tpublic readonly result: unknown,\n\t) {}\n}\n\n/**\n * Thrown by step.sleep() when the sleep is not yet resolved.\n * The handler aborts; the platform waits and re-dispatches.\n */\nexport class StepSleepSignal {\n\treadonly _isStepSleepSignal = true\n\n\tconstructor(\n\t\tpublic readonly stepName: string,\n\t\tpublic readonly duration: string,\n\t) {}\n}\n\n/**\n * Thrown by step.waitForEvent() when the event has not yet been received.\n * The handler aborts; the platform persists the wait record.\n * When the event arrives (via TriggersClient.publishEvent()), the platform\n * resolves the wait and re-dispatches with the event payload in context.waits.\n */\nexport class StepWaitEventSignal {\n\treadonly _isStepWaitEventSignal = true\n\n\tconstructor(\n\t\tpublic readonly stepName: string,\n\t\tpublic readonly eventName: string,\n\t\tpublic readonly options: {\n\t\t\t/** Timeout duration, e.g. '24h', '7d'. Task fails if event not received in time. */\n\t\t\ttimeout?: string\n\t\t\t/** Optional JSON filter — only resolve if event payload matches */\n\t\t\tfilter?: Record<string, unknown>\n\t\t} = {},\n\t) {}\n}\n\n// ============================================================================\n// Step context factory\n// ============================================================================\n\n/**\n * Build the step proxy for a single handler invocation.\n *\n * @param completedSteps  Map of stepName → cached result\n * @param resolvedWaits   Map of stepName → wait result (sleep = undefined, event = event payload)\n */\nexport function createStepContext(\n\tcompletedSteps: Map<string, unknown>,\n\tresolvedWaits: Map<string, unknown>,\n\tsideEffectReceipts: Map<string, NativeSideEffectReceipt> = new Map(),\n): NativeStepContext {\n\treturn {\n\t\t/**\n\t\t * Execute a named step.\n\t\t *\n\t\t * - If cached: return the cached value immediately (replay).\n\t\t * - If not cached: execute fn, then throw StepCompleteSignal with the result.\n\t\t */\n\t\tasync run<T>(name: string, fn: () => T | Promise<T>): Promise<T> {\n\t\t\tif (completedSteps.has(name)) {\n\t\t\t\treturn completedSteps.get(name) as T\n\t\t\t}\n\n\t\t\tconst result = await fn()\n\t\t\tthrow new StepCompleteSignal(name, result)\n\t\t},\n\n\t\tasync sideEffect<T>(\n\t\t\tstepName: string,\n\t\t\teffectKey: string,\n\t\t\texternalService: string,\n\t\t\tfn: (\n\t\t\t\tidempotencyKey: string,\n\t\t\t) => NativeSideEffectOutcome<T> | Promise<NativeSideEffectOutcome<T>>,\n\t\t): Promise<T> {\n\t\t\tconst receipt = sideEffectReceipts.get(sideEffectReceiptKey(stepName, effectKey))\n\t\t\tif (!receipt) {\n\t\t\t\tthrow new StepSideEffectStartSignal(stepName, effectKey, externalService)\n\t\t\t}\n\n\t\t\tif (receipt.externalService !== externalService) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Side-effect external service mismatch for ${stepName}/${effectKey}: receipt=${receipt.externalService} handler=${externalService}`,\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tif (receipt.completedAt) {\n\t\t\t\treturn receipt.result as T\n\t\t\t}\n\n\t\t\tconst outcome = await fn(receipt.idempotencyKey)\n\t\t\tthrow new StepSideEffectCompleteSignal(\n\t\t\t\tstepName,\n\t\t\t\teffectKey,\n\t\t\t\tnormalizeOptionalStepKey(outcome.handle),\n\t\t\t\toutcome.result,\n\t\t\t)\n\t\t},\n\n\t\t/**\n\t\t * Sleep for the given duration.\n\t\t *\n\t\t * - If resolved (platform woke us up): return immediately.\n\t\t * - If not resolved: throw StepSleepSignal to pause execution.\n\t\t */\n\t\tasync sleep(name: string, duration: string): Promise<void> {\n\t\t\tif (resolvedWaits.has(name)) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthrow new StepSleepSignal(name, duration)\n\t\t},\n\n\t\t/**\n\t\t * Pause execution until a named event is published via TriggersClient.publishEvent().\n\t\t *\n\t\t * - If event already arrived (platform re-dispatched with result): return event payload.\n\t\t * - If not yet arrived: throw StepWaitEventSignal to pause execution.\n\t\t *\n\t\t * @param name      Step identifier (unique within handler).\n\t\t * @param eventName The event name to listen for (e.g. 'user.approved').\n\t\t * @param options   Optional timeout ('24h', '7d') and payload filter.\n\t\t *\n\t\t * @example Human-in-the-loop approval\n\t\t * ```typescript\n\t\t * const approval = await step.waitForEvent('wait-approval', 'order.approved', {\n\t\t *   timeout: '48h',\n\t\t *   filter: { orderId: payload.orderId },\n\t\t * })\n\t\t * if (!approval) throw new Error('Approval timed out')\n\t\t * await sendConfirmation(approval.approvedBy)\n\t\t * ```\n\t\t */\n\t\tasync waitForEvent<T = unknown>(\n\t\t\tname: string,\n\t\t\teventName: string,\n\t\t\toptions: { timeout?: string; filter?: Record<string, unknown> } = {},\n\t\t): Promise<T | null> {\n\t\t\tif (resolvedWaits.has(name)) {\n\t\t\t\t// Platform resolved the wait — return the event payload (null if timed out)\n\t\t\t\treturn (resolvedWaits.get(name) as T | null) ?? null\n\t\t\t}\n\n\t\t\tthrow new StepWaitEventSignal(name, eventName, options)\n\t\t},\n\t}\n}\n\nfunction normalizeOptionalStepKey(value: string | undefined): string | undefined {\n\tconst trimmed = value?.trim()\n\treturn trimmed ? trimmed.slice(0, 500) : undefined\n}\n\nfunction sideEffectReceiptKey(stepName: string, effectKey: string): string {\n\treturn `${stepName}\\u0000${effectKey}`\n}\n\n// ============================================================================\n// Signature verification\n// ============================================================================\n\n/**\n * Constant-time HMAC-SHA256 signature verification.\n * Accepts both raw hex and 'sha256={hex}' formats.\n */\nexport function verifySignature(body: string, signature: string, secret: string): boolean {\n\ttry {\n\t\tconst hmac = createHmac('sha256', secret).update(body, 'utf8').digest('hex')\n\t\tconst normalised = signature.replace(/^sha256=/, '')\n\n\t\tconst expected = Buffer.from(hmac, 'hex')\n\t\tconst provided = Buffer.from(normalised, 'hex')\n\n\t\tif (expected.length !== provided.length) return false\n\t\treturn timingSafeEqual(expected, provided)\n\t} catch {\n\t\treturn false\n\t}\n}\n\n// ============================================================================\n// Request / response types\n// ============================================================================\n\ninterface DispatchStepEntry {\n\tname: string\n\tresult: unknown\n\tcompletedAt: string\n}\n\ninterface DispatchWaitEntry {\n\tname: string\n\tresolvedAt: string\n\tresult?: unknown\n}\n\ninterface DispatchContext {\n\tattempt: number\n\tsteps: DispatchStepEntry[]\n\twaits: DispatchWaitEntry[]\n\tsideEffects?: NativeSideEffectReceipt[]\n}\n\ninterface DispatchBody {\n\ttaskRunId: string\n\ttaskName: string\n\tpayload: unknown\n\tcontext: DispatchContext\n}\n\n// ============================================================================\n// Handler factory\n// ============================================================================\n\nexport interface TasksHandlerOptions {\n\t/** Platform signing secret. If not set, signature verification is skipped. */\n\tsigningSecret?: string\n}\n\nexport interface TasksHandlerResult {\n\tGET: (req: Request) => Promise<Response>\n\tPOST: (req: Request) => Promise<Response>\n}\n\n/**\n * Create a Next.js-compatible route handler for a list of task definitions.\n *\n * @example\n * ```typescript\n * export const { GET, POST } = createTasksHandler([sendEmail, processOrder])\n * ```\n */\nexport function createTasksHandler(\n\ttaskDefs: NativeTaskDefinition[],\n\toptions: TasksHandlerOptions = {},\n): TasksHandlerResult {\n\tconst taskMap = new Map<string, NativeTaskDefinition>()\n\tfor (const def of taskDefs) {\n\t\ttaskMap.set(def.name, def)\n\t}\n\n\t// GET: health/discovery — returns registered task names\n\tconst GET = async (_req: Request): Promise<Response> => {\n\t\treturn Response.json({\n\t\t\tok: true,\n\t\t\ttasks: Array.from(taskMap.keys()),\n\t\t})\n\t}\n\n\t// POST: dispatch handler\n\tconst POST = async (req: Request): Promise<Response> => {\n\t\t// ------------------------------------------------------------------\n\t\t// 1. Read raw body as text\n\t\t// ------------------------------------------------------------------\n\t\tlet rawBody: string\n\t\ttry {\n\t\t\trawBody = await req.text()\n\t\t} catch {\n\t\t\treturn Response.json(\n\t\t\t\t{ status: 'error', message: 'Failed to read request body' },\n\t\t\t\t{ status: 400 },\n\t\t\t)\n\t\t}\n\n\t\t// ------------------------------------------------------------------\n\t\t// 2. Verify signature if configured\n\t\t// ------------------------------------------------------------------\n\t\tconst signingSecret = options.signingSecret ?? process.env.SYLPHX_SIGNING_SECRET ?? ''\n\n\t\tif (signingSecret) {\n\t\t\tconst signature = req.headers.get('x-sylphx-signature') ?? ''\n\t\t\tif (!signature) {\n\t\t\t\treturn Response.json(\n\t\t\t\t\t{ status: 'error', message: 'Missing X-Sylphx-Signature header' },\n\t\t\t\t\t{ status: 401 },\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tif (!verifySignature(rawBody, signature, signingSecret)) {\n\t\t\t\treturn Response.json({ status: 'error', message: 'Invalid signature' }, { status: 401 })\n\t\t\t}\n\t\t}\n\n\t\t// ------------------------------------------------------------------\n\t\t// 3. Parse body\n\t\t// ------------------------------------------------------------------\n\t\tlet dispatch: DispatchBody\n\t\ttry {\n\t\t\tdispatch = JSON.parse(rawBody) as DispatchBody\n\t\t} catch {\n\t\t\treturn Response.json(\n\t\t\t\t{ status: 'error', message: 'Request body is not valid JSON' },\n\t\t\t\t{ status: 400 },\n\t\t\t)\n\t\t}\n\n\t\tconst { taskName, payload, context } = dispatch\n\n\t\tif (!taskName || typeof taskName !== 'string') {\n\t\t\treturn Response.json(\n\t\t\t\t{ status: 'error', message: 'Missing or invalid \"taskName\" field' },\n\t\t\t\t{ status: 400 },\n\t\t\t)\n\t\t}\n\n\t\t// ------------------------------------------------------------------\n\t\t// 4. Find task definition\n\t\t// ------------------------------------------------------------------\n\t\tconst taskDef = taskMap.get(taskName)\n\t\tif (!taskDef) {\n\t\t\treturn Response.json(\n\t\t\t\t{\n\t\t\t\t\tstatus: 'error',\n\t\t\t\t\tmessage: `Task \"${taskName}\" not found. Registered tasks: ${Array.from(taskMap.keys()).join(', ')}`,\n\t\t\t\t},\n\t\t\t\t{ status: 404 },\n\t\t\t)\n\t\t}\n\n\t\t// ------------------------------------------------------------------\n\t\t// 5. Build step context from dispatch context\n\t\t// ------------------------------------------------------------------\n\t\tconst completedSteps = new Map<string, unknown>()\n\t\tfor (const step of context?.steps ?? []) {\n\t\t\tcompletedSteps.set(step.name, step.result)\n\t\t}\n\n\t\t// resolvedWaits: stepName → result (sleep=undefined, event=payload, timeout=null)\n\t\tconst resolvedWaits = new Map<string, unknown>()\n\t\tfor (const wait of context?.waits ?? []) {\n\t\t\tresolvedWaits.set(wait.name, wait.result ?? undefined)\n\t\t}\n\n\t\tconst sideEffectReceipts = new Map<string, NativeSideEffectReceipt>()\n\t\tfor (const receipt of context?.sideEffects ?? []) {\n\t\t\tsideEffectReceipts.set(sideEffectReceiptKey(receipt.stepName, receipt.effectKey), receipt)\n\t\t}\n\n\t\tconst stepCtx = createStepContext(completedSteps, resolvedWaits, sideEffectReceipts)\n\n\t\t// ------------------------------------------------------------------\n\t\t// 6. Invoke the handler\n\t\t// ------------------------------------------------------------------\n\t\ttry {\n\t\t\tconst result = await taskDef.handler(payload, { step: stepCtx })\n\n\t\t\t// Handler returned normally → task is complete\n\t\t\treturn Response.json({ status: 'complete', result })\n\t\t} catch (err: unknown) {\n\t\t\t// ------------------------------------------------------------------\n\t\t\t// 7a. Step completed — save result and re-dispatch\n\t\t\t// ------------------------------------------------------------------\n\t\t\tif (err instanceof StepCompleteSignal || (err as StepCompleteSignal)?._isStepCompleteSignal) {\n\t\t\t\tconst signal = err as StepCompleteSignal\n\t\t\t\treturn Response.json({\n\t\t\t\t\tstatus: 'step_complete',\n\t\t\t\t\tstepName: signal.stepName,\n\t\t\t\t\tresult: signal.result,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\terr instanceof StepSideEffectStartSignal ||\n\t\t\t\t(err as StepSideEffectStartSignal)?._isStepSideEffectStartSignal\n\t\t\t) {\n\t\t\t\tconst signal = err as StepSideEffectStartSignal\n\t\t\t\treturn Response.json({\n\t\t\t\t\tstatus: 'side_effect_start',\n\t\t\t\t\tstepName: signal.stepName,\n\t\t\t\t\teffectKey: signal.effectKey,\n\t\t\t\t\texternalService: signal.externalService,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\terr instanceof StepSideEffectCompleteSignal ||\n\t\t\t\t(err as StepSideEffectCompleteSignal)?._isStepSideEffectCompleteSignal\n\t\t\t) {\n\t\t\t\tconst signal = err as StepSideEffectCompleteSignal\n\t\t\t\treturn Response.json({\n\t\t\t\t\tstatus: 'side_effect_complete',\n\t\t\t\t\tstepName: signal.stepName,\n\t\t\t\t\teffectKey: signal.effectKey,\n\t\t\t\t\thandle: signal.handle ?? null,\n\t\t\t\t\tresult: signal.result,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\t// ------------------------------------------------------------------\n\t\t\t// 7b. Step sleep — create wait record\n\t\t\t// ------------------------------------------------------------------\n\t\t\tif (err instanceof StepSleepSignal || (err as StepSleepSignal)?._isStepSleepSignal) {\n\t\t\t\tconst signal = err as StepSleepSignal\n\t\t\t\treturn Response.json({\n\t\t\t\t\tstatus: 'step_sleep',\n\t\t\t\t\tstepName: signal.stepName,\n\t\t\t\t\tduration: signal.duration,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\t// ------------------------------------------------------------------\n\t\t\t// 7c. Step waitForEvent — suspend until named event arrives\n\t\t\t// ------------------------------------------------------------------\n\t\t\tif (\n\t\t\t\terr instanceof StepWaitEventSignal ||\n\t\t\t\t(err as StepWaitEventSignal)?._isStepWaitEventSignal\n\t\t\t) {\n\t\t\t\tconst signal = err as StepWaitEventSignal\n\t\t\t\treturn Response.json({\n\t\t\t\t\tstatus: 'step_wait_event',\n\t\t\t\t\tstepName: signal.stepName,\n\t\t\t\t\teventName: signal.eventName,\n\t\t\t\t\ttimeout: signal.options.timeout ?? null,\n\t\t\t\t\tfilter: signal.options.filter ?? null,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\t// ------------------------------------------------------------------\n\t\t\t// 7d. Unexpected error\n\t\t\t// ------------------------------------------------------------------\n\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\tconsole.error(`[sylphx/tasks] Task \"${taskName}\" threw an error:`, err)\n\t\t\treturn Response.json(\n\t\t\t\t{\n\t\t\t\t\tstatus: 'error',\n\t\t\t\t\tmessage,\n\t\t\t\t\tretriable: true,\n\t\t\t\t},\n\t\t\t\t{ status: 500 },\n\t\t\t)\n\t\t}\n\t}\n\n\treturn { GET, POST }\n}\n","/**\n * Tasks Types\n *\n * Type definitions for background job scheduling and workflows.\n * Supports durable execution, retries, and workflow composition.\n */\n\nimport {\n\tBASE_RETRY_DELAY_MS,\n\tDEFAULT_RETRY_DELAYS_MS,\n\tJOB_DEFAULT_TIMEOUT_MS,\n\tJOBS_DLQ_MAX_AGE_MS,\n\tMAX_RETRY_DELAY_MS,\n} from '../../constants'\n\n// ==========================================\n// Core Types\n// ==========================================\n\n/** Task status */\nexport type TaskStatus =\n\t| 'pending'\n\t| 'scheduled'\n\t| 'running'\n\t| 'completed'\n\t| 'failed'\n\t| 'cancelled'\n\t| 'retrying'\n\t| 'dead' // In DLQ\n\n/** Job priority */\nexport type TaskPriority = 'low' | 'normal' | 'high' | 'critical'\n\n/** Job payload - must be JSON serializable */\nexport type TaskPayload = Record<string, unknown>\n\n/** Job result */\nexport type TaskResult = unknown\n\n// ==========================================\n// Job Definition\n// ==========================================\n\n/** Job definition */\nexport interface TaskDefinition<TPayload extends TaskPayload = TaskPayload, TResult = TaskResult> {\n\t/** Unique job type identifier */\n\ttype: string\n\t/** Human-readable name */\n\tname?: string\n\t/** Description */\n\tdescription?: string\n\t/** Job handler (server-side) */\n\thandler?: (payload: TPayload, context: TaskContext) => Promise<TResult>\n\t/** Default options */\n\tdefaults?: TaskOptions\n\t/** Validation schema */\n\tvalidate?: (payload: TPayload) => boolean | string\n}\n\n/** Job options */\nexport interface TaskOptions {\n\t/** Priority */\n\tpriority?: TaskPriority\n\t/** Max retry attempts */\n\tmaxRetries?: number\n\t/** Retry delay strategy */\n\tretryDelay?: RetryDelayStrategy\n\t/** Timeout in ms */\n\ttimeout?: number\n\t/** Delay execution */\n\tdelay?: number | Date\n\t/** Cron schedule */\n\tcron?: string\n\t/** Unique job ID (for deduplication) */\n\tuniqueId?: string\n\t/** Unique key TTL in ms (how long to prevent duplicates) */\n\tuniqueTtl?: number\n\t/** Dead letter queue options */\n\tdlq?: DLQOptions\n\t/** Tags for filtering */\n\ttags?: string[]\n\t/** Custom metadata */\n\tmetadata?: Record<string, unknown>\n}\n\n/** Retry delay strategy */\nexport type RetryDelayStrategy =\n\t| { type: 'fixed'; delay: number }\n\t| { type: 'exponential'; base: number; maxDelay?: number }\n\t| { type: 'linear'; initial: number; increment: number; maxDelay?: number }\n\t| { type: 'custom'; delays: number[] }\n\n/** DLQ options */\nexport interface DLQOptions {\n\t/** Enable DLQ */\n\tenabled?: boolean\n\t/** Max age before auto-discard (ms) */\n\tmaxAge?: number\n\t/** Auto-retry from DLQ */\n\tautoRetry?: boolean\n\t/** Auto-retry interval (ms) */\n\tautoRetryInterval?: number\n\t/** Max auto-retry attempts from DLQ */\n\tmaxAutoRetries?: number\n}\n\n// ==========================================\n// Job Instance\n// ==========================================\n\n/** Job instance */\nexport interface TaskInstance<TPayload extends TaskPayload = TaskPayload, TResult = TaskResult> {\n\t/** Unique job ID */\n\tid: string\n\t/** Job type */\n\ttype: string\n\t/** Job payload */\n\tpayload: TPayload\n\t/** Current status */\n\tstatus: TaskStatus\n\t/** Priority */\n\tpriority: TaskPriority\n\t/** Created timestamp */\n\tcreatedAt: number\n\t/** Scheduled execution time */\n\tscheduledAt?: number\n\t/** Started timestamp */\n\tstartedAt?: number\n\t/** Completed timestamp */\n\tcompletedAt?: number\n\t/** Current attempt number */\n\tattempt: number\n\t/** Max retry attempts */\n\tmaxRetries: number\n\t/** Job result (if completed) */\n\tresult?: TResult\n\t/** Error message (if failed) */\n\terror?: string\n\t/** Error stack trace */\n\terrorStack?: string\n\t/** Progress (0-100) */\n\tprogress?: number\n\t/** Progress message */\n\tprogressMessage?: string\n\t/** Tags */\n\ttags?: string[]\n\t/** Custom metadata */\n\tmetadata?: Record<string, unknown>\n\t/** Parent job ID (for workflows) */\n\tparentId?: string\n\t/** Workflow step name (for workflows) */\n\tstepName?: string\n}\n\n/** Job context passed to handlers */\nexport interface TaskContext {\n\t/** Job ID */\n\tjobId: string\n\t/** Current attempt number */\n\tattempt: number\n\t/** Signal for cancellation */\n\tsignal?: AbortSignal\n\t/** Update progress */\n\tsetProgress: (progress: number, message?: string) => void\n\t/** Log message */\n\tlog: (message: string, level?: 'info' | 'warn' | 'error') => void\n\t/** Check if should continue (for long-running jobs) */\n\tshouldContinue: () => boolean\n\t/** Schedule a child job */\n\tscheduleChild: <T extends TaskPayload>(\n\t\ttype: string,\n\t\tpayload: T,\n\t\toptions?: TaskOptions,\n\t) => Promise<string>\n\t/** Sleep (durable) */\n\tsleep: (ms: number) => Promise<void>\n}\n\n// ==========================================\n// Workflow Types\n// ==========================================\n\n/** Workflow definition */\nexport interface WorkflowDefinition<\n\t__TInput extends TaskPayload = TaskPayload,\n\tTOutput = TaskResult,\n> {\n\t/** Unique workflow type */\n\ttype: string\n\t/** Human-readable name */\n\tname?: string\n\t/** Description */\n\tdescription?: string\n\t/** Workflow steps */\n\tsteps: WorkflowStep[]\n\t/** Default options */\n\tdefaults?: WorkflowOptions\n\t/** On complete callback */\n\tonComplete?: (result: TOutput) => void\n\t/** On error callback */\n\tonError?: (error: Error, step: string) => void\n}\n\n/** Workflow options */\nexport interface WorkflowOptions extends TaskOptions {\n\t/** Continue on step failure */\n\tcontinueOnFailure?: boolean\n\t/** Max concurrent steps (for parallel) */\n\tmaxConcurrency?: number\n}\n\n/** Workflow step */\nexport type WorkflowStep =\n\t| TaskStep\n\t| ConditionalStep\n\t| ParallelStep\n\t| LoopStep\n\t| WaitStep\n\t| SubworkflowStep\n\n/** Job step */\nexport interface TaskStep {\n\ttype: 'job'\n\tname: string\n\t/** Job type to execute */\n\tjobType: string\n\t/** Payload transform (receives workflow input + previous results) */\n\tpayload?: (context: StepContext) => TaskPayload\n\t/** Step options */\n\toptions?: TaskOptions\n\t/** Condition to run this step */\n\tif?: (context: StepContext) => boolean\n\t/** On complete transform */\n\tonComplete?: (result: TaskResult, context: StepContext) => unknown\n}\n\n/** Conditional step */\nexport interface ConditionalStep {\n\ttype: 'conditional'\n\tname: string\n\t/** Condition function */\n\tcondition: (context: StepContext) => boolean\n\t/** Steps if condition is true */\n\tthen: WorkflowStep[]\n\t/** Steps if condition is false */\n\telse?: WorkflowStep[]\n}\n\n/** Parallel step */\nexport interface ParallelStep {\n\ttype: 'parallel'\n\tname: string\n\t/** Steps to run in parallel */\n\tsteps: WorkflowStep[]\n\t/** Wait for all or any */\n\twaitFor?: 'all' | 'any'\n\t/** Max concurrent */\n\tmaxConcurrency?: number\n}\n\n/** Loop step */\nexport interface LoopStep {\n\ttype: 'loop'\n\tname: string\n\t/** Array to iterate over, or function to get items */\n\titems: unknown[] | ((context: StepContext) => unknown[])\n\t/** Step to execute for each item */\n\tstep: WorkflowStep\n\t/** Max concurrent iterations */\n\tmaxConcurrency?: number\n\t/** Break condition */\n\tbreakIf?: (item: unknown, index: number, context: StepContext) => boolean\n}\n\n/** Wait step */\nexport interface WaitStep {\n\ttype: 'wait'\n\tname: string\n\t/** Duration in ms, Date, or function */\n\tuntil: number | Date | ((context: StepContext) => number | Date)\n}\n\n/** Sub-workflow step */\nexport interface SubworkflowStep {\n\ttype: 'subworkflow'\n\tname: string\n\t/** Workflow type to execute */\n\tworkflowType: string\n\t/** Payload transform */\n\tpayload?: (context: StepContext) => TaskPayload\n\t/** Options */\n\toptions?: WorkflowOptions\n}\n\n/** Step context */\nexport interface StepContext {\n\t/** Workflow input */\n\tinput: TaskPayload\n\t/** Results from previous steps */\n\tresults: Record<string, TaskResult>\n\t/** Current step name */\n\tcurrentStep: string\n\t/** Workflow metadata */\n\tmetadata: Record<string, unknown>\n}\n\n// ==========================================\n// Workflow Instance\n// ==========================================\n\n/** Workflow instance */\nexport interface Workflow<_TInput extends TaskPayload = TaskPayload, TOutput = TaskResult> {\n\t/** Unique workflow ID */\n\tid: string\n\t/** Workflow type */\n\ttype: string\n\t/** Input payload */\n\tinput: _TInput\n\t/** Current status */\n\tstatus: TaskStatus\n\t/** Created timestamp */\n\tcreatedAt: number\n\t/** Started timestamp */\n\tstartedAt?: number\n\t/** Completed timestamp */\n\tcompletedAt?: number\n\t/** Current step name */\n\tcurrentStep?: string\n\t/** Step results */\n\tstepResults: Record<string, TaskResult>\n\t/** Step statuses */\n\tstepStatuses: Record<string, TaskStatus>\n\t/** Final output */\n\toutput?: TOutput\n\t/** Error */\n\terror?: string\n\t/** Metadata */\n\tmetadata?: Record<string, unknown>\n}\n\n// ==========================================\n// Scheduling\n// ==========================================\n\n/** Cron schedule */\nexport interface CronSchedule {\n\t/** Cron expression */\n\texpression: string\n\t/** Timezone */\n\ttimezone?: string\n\t/** Start date */\n\tstartAt?: Date\n\t/** End date */\n\tendAt?: Date\n\t/** Max runs */\n\tmaxRuns?: number\n}\n\n/** Scheduled job */\nexport interface ScheduledTask {\n\t/** Schedule ID */\n\tid: string\n\t/** Job type */\n\ttype: string\n\t/** Job payload */\n\tpayload: TaskPayload\n\t/** Cron schedule */\n\tcron: CronSchedule\n\t/** Current status */\n\tstatus: 'active' | 'paused' | 'completed'\n\t/** Run count */\n\trunCount: number\n\t/** Next run timestamp */\n\tnextRunAt?: number\n\t/** Last run timestamp */\n\tlastRunAt?: number\n\t/** Created timestamp */\n\tcreatedAt: number\n}\n\n// ==========================================\n// Events\n// ==========================================\n\n/** Job event */\nexport type TaskEvent =\n\t| { type: 'job:created'; job: Job }\n\t| { type: 'job:started'; job: Job }\n\t| { type: 'job:progress'; job: Job; progress: number; message?: string }\n\t| { type: 'job:completed'; job: Job; result: TaskResult }\n\t| { type: 'job:failed'; job: Job; error: string }\n\t| { type: 'job:retrying'; job: Job; attempt: number }\n\t| { type: 'job:dead'; job: Job }\n\t| { type: 'job:cancelled'; job: Job }\n\n/** Workflow event */\nexport type WorkflowEvent =\n\t| { type: 'workflow:started'; workflow: Workflow }\n\t| { type: 'workflow:step:started'; workflow: Workflow; step: string }\n\t| {\n\t\t\ttype: 'workflow:step:completed'\n\t\t\tworkflow: Workflow\n\t\t\tstep: string\n\t\t\tresult: TaskResult\n\t  }\n\t| {\n\t\t\ttype: 'workflow:step:failed'\n\t\t\tworkflow: Workflow\n\t\t\tstep: string\n\t\t\terror: string\n\t  }\n\t| { type: 'workflow:completed'; workflow: Workflow; output: TaskResult }\n\t| { type: 'workflow:failed'; workflow: Workflow; error: string }\n\n// ==========================================\n// Configuration\n// ==========================================\n\n/** Jobs client configuration */\nexport interface TasksConfig {\n\t/** API endpoint */\n\tapiEndpoint?: string\n\t/** API key */\n\tapiKey?: string\n\t/** Default job options */\n\tdefaultOptions?: TaskOptions\n\t/** Enable debug logging */\n\tdebug?: boolean\n\t/** Event callbacks */\n\tonTaskEvent?: (event: TaskEvent) => void\n\tonWorkflowEvent?: (event: WorkflowEvent) => void\n}\n\n/** Default configuration */\nexport const DEFAULT_JOBS_CONFIG: Required<Pick<TasksConfig, 'defaultOptions' | 'debug'>> = {\n\tdefaultOptions: {\n\t\tpriority: 'normal',\n\t\tmaxRetries: 3,\n\t\tretryDelay: {\n\t\t\ttype: 'exponential',\n\t\t\tbase: BASE_RETRY_DELAY_MS,\n\t\t\tmaxDelay: MAX_RETRY_DELAY_MS,\n\t\t},\n\t\ttimeout: JOB_DEFAULT_TIMEOUT_MS,\n\t\tdlq: {\n\t\t\tenabled: true,\n\t\t\tmaxAge: JOBS_DLQ_MAX_AGE_MS, // 7 days\n\t\t},\n\t},\n\tdebug: false,\n}\n\n/** Default retry delays (ms) */\nexport const DEFAULT_RETRY_DELAYS = DEFAULT_RETRY_DELAYS_MS\n\n// ============================================================================\n// Backward-compat type aliases (Jobs → Tasks rename)\n// ============================================================================\nexport type Job<TPayload extends TaskPayload = TaskPayload, TResult = TaskResult> = TaskInstance<\n\tTPayload,\n\tTResult\n>\nexport type JobContext = TaskContext\nexport type JobDefinition<\n\tTPayload extends TaskPayload = TaskPayload,\n\tTResult = TaskResult,\n> = TaskDefinition<TPayload, TResult>\nexport type JobEvent = TaskEvent\nexport type JobOptions = TaskOptions\nexport type JobPayload = TaskPayload\nexport type JobPriority = TaskPriority\nexport type JobResult = TaskResult\n/** @deprecated use TaskStatus */\nexport type JobStatus = TaskStatus\nexport type JobStep = TaskStep\nexport type ScheduledJob = ScheduledTask\n/** Jobs status check result */\nexport type TasksStatusResult = {\n\tavailable: boolean\n}\n/** @deprecated Use TasksConfig.onTaskEvent */\nexport type onJobEvent = TasksConfig['onTaskEvent']\n\n// ============================================================================\n// Native Task Engine — Handler API Types\n// ============================================================================\n\n/**\n * Step execution context injected into every task handler.\n * Methods implement the stateless-replay model:\n *   - Completed steps return from cache immediately.\n *   - Uncached steps execute and signal the platform.\n */\nexport type NativeStepContext = {\n\t/**\n\t * Execute a named step with automatic checkpointing.\n\t *\n\t * On first run: executes fn and signals the platform to save the result.\n\t * On replay: returns the cached result without re-running fn.\n\t */\n\trun<T>(name: string, fn: () => T | Promise<T>): Promise<T>\n\n\t/**\n\t * Execute an external side effect with a durable idempotency key.\n\t *\n\t * First encounter: signals Platform to persist a side-effect receipt before\n\t * the external call. Replay then invokes fn with that persisted key. If the\n\t * handler crashes after the external call but before completion settles, the\n\t * next replay reuses the same key so the downstream service suppresses duplicates.\n\t */\n\tsideEffect<T>(\n\t\tstepName: string,\n\t\teffectKey: string,\n\t\texternalService: string,\n\t\tfn: (\n\t\t\tidempotencyKey: string,\n\t\t) => NativeSideEffectOutcome<T> | Promise<NativeSideEffectOutcome<T>>,\n\t): Promise<T>\n\n\t/**\n\t * Pause execution for the given duration.\n\t *\n\t * On first encounter: signals the platform to wait; stops execution.\n\t * After the wait resolves: returns immediately (no-op on replay).\n\t *\n\t * @param name      Step identifier (must be unique within the handler).\n\t * @param duration  Human-readable duration: '5s', '30m', '2h', '1d'.\n\t */\n\tsleep(name: string, duration: string): Promise<void>\n\n\t/**\n\t * Pause execution until a named event is published via TriggersClient.publishEvent().\n\t *\n\t * On first encounter: signals the platform to wait for the event; stops execution.\n\t * After the event arrives: returns the event payload.\n\t * If timeout expires before event arrives: returns null.\n\t *\n\t * @param name      Step identifier (must be unique within the handler).\n\t * @param eventName The event name to listen for (e.g. 'user.approved').\n\t * @param options   Optional timeout ('24h', '7d') and payload filter.\n\t *\n\t * @example Human-in-the-loop approval\n\t * ```typescript\n\t * const approval = await step.waitForEvent<{ approvedBy: string }>(\n\t *   'wait-approval',\n\t *   'order.approved',\n\t *   { timeout: '48h', filter: { orderId: payload.orderId } },\n\t * )\n\t * if (!approval) throw new Error('Approval timed out')\n\t * await notifyCustomer(approval.approvedBy)\n\t * ```\n\t */\n\twaitForEvent<T = unknown>(\n\t\tname: string,\n\t\teventName: string,\n\t\toptions?: { timeout?: string; filter?: Record<string, unknown> },\n\t): Promise<T | null>\n}\n\nexport interface NativeSideEffectOutcome<T = unknown> {\n\treadonly handle?: string\n\treadonly result: T\n}\n\nexport interface NativeSideEffectReceipt {\n\treadonly stepName: string\n\treadonly effectKey: string\n\treadonly externalService: string\n\treadonly idempotencyKey: string\n\treadonly handle: string | null\n\treadonly result: unknown\n\treadonly completedAt: string | null\n\treadonly createdAt: string\n}\n\n/**\n * A named task definition registered with sylphx.tasks.define().\n */\nexport interface NativeTaskDefinition<TPayload = unknown, TResult = unknown> {\n\t/** Unique task identifier — must match the taskName used in .trigger() */\n\tname: string\n\t/** The task handler function. Runs with stateless-replay semantics. */\n\thandler: (payload: TPayload, ctx: { step: NativeStepContext }) => Promise<TResult>\n\t/** Optional task-level configuration */\n\toptions?: {\n\t\t/** Cron expression for scheduled tasks, e.g. '0 9 * * 1-5' */\n\t\tcron?: string\n\t\t/** Maximum execution attempts (default: 3) */\n\t\tmaxAttempts?: number\n\t\t/** Execution timeout, e.g. '5m', '1h' */\n\t\ttimeout?: string\n\t}\n}\n\n/**\n * The shape returned by GET/POST /tasks/:runId in the platform API.\n */\nexport type TaskRunDispatchLeaseState = 'active' | 'expired' | 'legacy'\n\nexport interface TaskRunDispatchLease {\n\t/**\n\t * Customer-safe dispatch claim state. Raw claim tokens and controller\n\t * identities are intentionally not exposed through the public SDK.\n\t */\n\tstate: TaskRunDispatchLeaseState\n\tclaimedAt: string | null\n\texpiresAt: string | null\n}\n\nexport interface TaskRunStatus {\n\tid: string\n\ttaskName: string\n\tstatus: 'pending' | 'running' | 'waiting' | 'completed' | 'failed' | 'cancelled'\n\tpayload?: unknown\n\tresult?: unknown\n\terror?: string\n\tattempt: number\n\tmaxAttempts: number\n\tscheduledFor?: string\n\tstartedAt?: string\n\tcompletedAt?: string\n\tdispatchLease?: TaskRunDispatchLease | null\n\tdefinition?: {\n\t\tid: string\n\t\tversion: number | null\n\t\thash: string | null\n\t\tsource: string | null\n\t} | null\n\tcreatedAt: string\n\tupdatedAt: string\n}\n","/**\n * Tasks Legacy Client\n *\n * @deprecated Use task() / taskStub() / serve() from the tasks module instead.\n *\n * This file preserves backward compatibility for consumers of the old TasksClient API.\n * The TasksClient class is unchanged — it is imported by ./index.ts under the 'legacy' export group.\n */\n\nimport { createTasksHandler, type TasksHandlerOptions, type TasksHandlerResult } from './handler'\nimport type {\n\tCronSchedule,\n\tJob,\n\tJobEvent,\n\tJobOptions,\n\tJobPayload,\n\tJobResult,\n\tNativeStepContext,\n\tNativeTaskDefinition,\n\tScheduledJob,\n\tTaskRunStatus,\n\tTasksConfig,\n\tWorkflow,\n\tWorkflowDefinition,\n\tWorkflowEvent,\n} from './types'\nimport { DEFAULT_JOBS_CONFIG } from './types'\n\n/**\n * Jobs Client\n *\n * Client for scheduling jobs and workflows via the Sylph API.\n */\nexport class TasksClient {\n\tprivate config: TasksConfig\n\tprivate eventHandlers: {\n\t\tjob: ((event: JobEvent) => void)[]\n\t\tworkflow: ((event: WorkflowEvent) => void)[]\n\t} = { job: [], workflow: [] }\n\n\tconstructor(config: TasksConfig) {\n\t\tthis.config = {\n\t\t\t...config,\n\t\t\tdefaultOptions: {\n\t\t\t\t...DEFAULT_JOBS_CONFIG.defaultOptions,\n\t\t\t\t...config.defaultOptions,\n\t\t\t},\n\t\t}\n\n\t\t// Register initial event handlers\n\t\tif (config.onTaskEvent) {\n\t\t\tthis.eventHandlers.job.push(config.onTaskEvent)\n\t\t}\n\t\tif (config.onWorkflowEvent) {\n\t\t\tthis.eventHandlers.workflow.push(config.onWorkflowEvent)\n\t\t}\n\t}\n\n\t// =========================================================================\n\t// Job Scheduling\n\t// =========================================================================\n\n\t/**\n\t * Schedule a job for execution\n\t */\n\tasync schedule<TPayload extends JobPayload = JobPayload>(\n\t\ttype: string,\n\t\tpayload: TPayload,\n\t\toptions?: JobOptions,\n\t): Promise<Job<TPayload>> {\n\t\tconst response = await this.fetch<{ job: Job<TPayload> }>('/jobs', {\n\t\t\tmethod: 'POST',\n\t\t\tbody: JSON.stringify({\n\t\t\t\ttype,\n\t\t\t\tpayload,\n\t\t\t\toptions: {\n\t\t\t\t\t...this.config.defaultOptions,\n\t\t\t\t\t...options,\n\t\t\t\t},\n\t\t\t}),\n\t\t})\n\n\t\treturn response.job\n\t}\n\n\t/**\n\t * Schedule a job with delay\n\t */\n\tasync scheduleDelayed<TPayload extends JobPayload = JobPayload>(\n\t\ttype: string,\n\t\tpayload: TPayload,\n\t\tdelay: number | Date,\n\t\toptions?: JobOptions,\n\t): Promise<Job<TPayload>> {\n\t\treturn this.schedule(type, payload, {\n\t\t\t...options,\n\t\t\tdelay: delay instanceof Date ? delay.getTime() - Date.now() : delay,\n\t\t})\n\t}\n\n\t/**\n\t * Schedule a recurring job (cron)\n\t */\n\tasync scheduleCron<TPayload extends JobPayload = JobPayload>(\n\t\ttype: string,\n\t\tpayload: TPayload,\n\t\tcron: string | CronSchedule,\n\t\toptions?: JobOptions,\n\t): Promise<ScheduledJob> {\n\t\tconst response = await this.fetch<{ scheduled: ScheduledJob }>('/jobs/scheduled', {\n\t\t\tmethod: 'POST',\n\t\t\tbody: JSON.stringify({\n\t\t\t\ttype,\n\t\t\t\tpayload,\n\t\t\t\tcron: typeof cron === 'string' ? { expression: cron } : cron,\n\t\t\t\toptions: {\n\t\t\t\t\t...this.config.defaultOptions,\n\t\t\t\t\t...options,\n\t\t\t\t},\n\t\t\t}),\n\t\t})\n\n\t\treturn response.scheduled\n\t}\n\n\t// =========================================================================\n\t// Job Management\n\t// =========================================================================\n\n\t/**\n\t * Get a job by ID\n\t */\n\tasync getJob<TPayload extends JobPayload = JobPayload, TResult = JobResult>(\n\t\tjobId: string,\n\t): Promise<Job<TPayload, TResult> | null> {\n\t\tconst response = await this.fetch<{ job: Job<TPayload, TResult> | null }>(`/jobs/${jobId}`)\n\t\treturn response.job\n\t}\n\n\t/**\n\t * Cancel a job\n\t */\n\tasync cancelJob(jobId: string): Promise<boolean> {\n\t\tconst response = await this.fetch<{ cancelled: boolean }>(`/jobs/${jobId}/cancel`, {\n\t\t\tmethod: 'POST',\n\t\t})\n\t\treturn response.cancelled\n\t}\n\n\t/**\n\t * Retry a failed job\n\t */\n\tasync retryJob(jobId: string): Promise<Job> {\n\t\tconst response = await this.fetch<{ job: Job }>(`/jobs/${jobId}/retry`, {\n\t\t\tmethod: 'POST',\n\t\t})\n\t\treturn response.job\n\t}\n\n\t/**\n\t * List jobs with filters\n\t */\n\tasync listJobs(options?: {\n\t\ttype?: string\n\t\tstatus?: string\n\t\tlimit?: number\n\t\toffset?: number\n\t}): Promise<{ jobs: Job[]; total: number }> {\n\t\tconst params = new URLSearchParams()\n\t\tif (options?.type) params.set('type', options.type)\n\t\tif (options?.status) params.set('status', options.status)\n\t\tif (options?.limit) params.set('limit', String(options.limit))\n\t\tif (options?.offset) params.set('offset', String(options.offset))\n\n\t\tconst response = await this.fetch<{ jobs: Job[]; total: number }>(`/jobs?${params.toString()}`)\n\t\treturn { jobs: response.jobs, total: response.total }\n\t}\n\n\t// =========================================================================\n\t// Dead Letter Queue\n\t// =========================================================================\n\n\t/**\n\t * List DLQ entries\n\t */\n\tasync listDLQ(options?: {\n\t\tlimit?: number\n\t\toffset?: number\n\t}): Promise<{ entries: Job[]; total: number }> {\n\t\tconst params = new URLSearchParams()\n\t\tif (options?.limit) params.set('limit', String(options.limit))\n\t\tif (options?.offset) params.set('offset', String(options.offset))\n\n\t\tconst response = await this.fetch<{ entries: Job[]; total: number }>(\n\t\t\t`/jobs/dlq?${params.toString()}`,\n\t\t)\n\t\treturn { entries: response.entries, total: response.total }\n\t}\n\n\t/**\n\t * Retry a DLQ entry\n\t */\n\tasync retryDLQEntry(entryId: string): Promise<Job> {\n\t\tconst response = await this.fetch<{ job: Job }>(`/jobs/dlq/${entryId}/retry`, {\n\t\t\tmethod: 'POST',\n\t\t})\n\t\treturn response.job\n\t}\n\n\t/**\n\t * Discard a DLQ entry\n\t */\n\tasync discardDLQEntry(entryId: string): Promise<boolean> {\n\t\tconst response = await this.fetch<{ discarded: boolean }>(`/jobs/dlq/${entryId}`, {\n\t\t\tmethod: 'DELETE',\n\t\t})\n\t\treturn response.discarded\n\t}\n\n\t// =========================================================================\n\t// Workflows\n\t// =========================================================================\n\n\t/**\n\t * Start a workflow\n\t */\n\tasync startWorkflow<TInput extends JobPayload = JobPayload, TOutput = JobResult>(\n\t\tworkflow: WorkflowDefinition<TInput, TOutput>,\n\t\tinput: TInput,\n\t\toptions?: JobOptions,\n\t): Promise<Workflow<TInput, TOutput>> {\n\t\tconst response = await this.fetch<{ workflow: Workflow<TInput, TOutput> }>('/workflows', {\n\t\t\tmethod: 'POST',\n\t\t\tbody: JSON.stringify({\n\t\t\t\tworkflow,\n\t\t\t\tinput,\n\t\t\t\toptions: {\n\t\t\t\t\t...this.config.defaultOptions,\n\t\t\t\t\t...options,\n\t\t\t\t},\n\t\t\t}),\n\t\t})\n\n\t\treturn response.workflow\n\t}\n\n\t/**\n\t * Get a workflow by ID\n\t */\n\tasync getWorkflow<TInput extends JobPayload = JobPayload, TOutput = JobResult>(\n\t\tworkflowId: string,\n\t): Promise<Workflow<TInput, TOutput> | null> {\n\t\tconst response = await this.fetch<{ workflow: Workflow<TInput, TOutput> | null }>(\n\t\t\t`/workflows/${workflowId}`,\n\t\t)\n\t\treturn response.workflow\n\t}\n\n\t/**\n\t * Cancel a workflow\n\t */\n\tasync cancelWorkflow(workflowId: string): Promise<boolean> {\n\t\tconst response = await this.fetch<{ cancelled: boolean }>(`/workflows/${workflowId}/cancel`, {\n\t\t\tmethod: 'POST',\n\t\t})\n\t\treturn response.cancelled\n\t}\n\n\t/**\n\t * List workflows\n\t */\n\tasync listWorkflows(options?: {\n\t\ttype?: string\n\t\tstatus?: string\n\t\tlimit?: number\n\t\toffset?: number\n\t}): Promise<{ workflows: Workflow[]; total: number }> {\n\t\tconst params = new URLSearchParams()\n\t\tif (options?.type) params.set('type', options.type)\n\t\tif (options?.status) params.set('status', options.status)\n\t\tif (options?.limit) params.set('limit', String(options.limit))\n\t\tif (options?.offset) params.set('offset', String(options.offset))\n\n\t\tconst response = await this.fetch<{ workflows: Workflow[]; total: number }>(\n\t\t\t`/workflows?${params.toString()}`,\n\t\t)\n\t\treturn { workflows: response.workflows, total: response.total }\n\t}\n\n\t// =========================================================================\n\t// Scheduled Jobs\n\t// =========================================================================\n\n\t/**\n\t * List scheduled jobs\n\t */\n\tasync listScheduledJobs(options?: {\n\t\tstatus?: 'active' | 'paused' | 'completed'\n\t\tlimit?: number\n\t\toffset?: number\n\t}): Promise<{ scheduled: ScheduledJob[]; total: number }> {\n\t\tconst params = new URLSearchParams()\n\t\tif (options?.status) params.set('status', options.status)\n\t\tif (options?.limit) params.set('limit', String(options.limit))\n\t\tif (options?.offset) params.set('offset', String(options.offset))\n\n\t\tconst response = await this.fetch<{ scheduled: ScheduledJob[]; total: number }>(\n\t\t\t`/jobs/scheduled?${params.toString()}`,\n\t\t)\n\t\treturn { scheduled: response.scheduled, total: response.total }\n\t}\n\n\t/**\n\t * Pause a scheduled job\n\t */\n\tasync pauseScheduledJob(scheduleId: string): Promise<ScheduledJob> {\n\t\tconst response = await this.fetch<{ scheduled: ScheduledJob }>(\n\t\t\t`/jobs/scheduled/${scheduleId}/pause`,\n\t\t\t{\n\t\t\t\tmethod: 'POST',\n\t\t\t},\n\t\t)\n\t\treturn response.scheduled\n\t}\n\n\t/**\n\t * Resume a scheduled job\n\t */\n\tasync resumeScheduledJob(scheduleId: string): Promise<ScheduledJob> {\n\t\tconst response = await this.fetch<{ scheduled: ScheduledJob }>(\n\t\t\t`/jobs/scheduled/${scheduleId}/resume`,\n\t\t\t{\n\t\t\t\tmethod: 'POST',\n\t\t\t},\n\t\t)\n\t\treturn response.scheduled\n\t}\n\n\t/**\n\t * Delete a scheduled job\n\t */\n\tasync deleteScheduledJob(scheduleId: string): Promise<boolean> {\n\t\tconst response = await this.fetch<{ deleted: boolean }>(`/jobs/scheduled/${scheduleId}`, {\n\t\t\tmethod: 'DELETE',\n\t\t})\n\t\treturn response.deleted\n\t}\n\n\t// =========================================================================\n\t// Events\n\t// =========================================================================\n\n\t/**\n\t * Subscribe to job events\n\t */\n\tonJobEvent(handler: (event: JobEvent) => void): () => void {\n\t\tthis.eventHandlers.job.push(handler)\n\t\treturn () => {\n\t\t\tconst index = this.eventHandlers.job.indexOf(handler)\n\t\t\tif (index !== -1) {\n\t\t\t\tthis.eventHandlers.job.splice(index, 1)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Subscribe to workflow events\n\t */\n\tonWorkflowEvent(handler: (event: WorkflowEvent) => void): () => void {\n\t\tthis.eventHandlers.workflow.push(handler)\n\t\treturn () => {\n\t\t\tconst index = this.eventHandlers.workflow.indexOf(handler)\n\t\t\tif (index !== -1) {\n\t\t\t\tthis.eventHandlers.workflow.splice(index, 1)\n\t\t\t}\n\t\t}\n\t}\n\n\t// =========================================================================\n\t// Internal\n\t// =========================================================================\n\n\tprivate async fetch<TResponse>(path: string, options?: RequestInit): Promise<TResponse> {\n\t\tconst url = `${this.config.apiEndpoint}${path}`\n\t\tconst response = await fetch(url, {\n\t\t\t...options,\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t...(this.config.apiKey && {\n\t\t\t\t\tAuthorization: `Bearer ${this.config.apiKey}`,\n\t\t\t\t}),\n\t\t\t\t...options?.headers,\n\t\t\t},\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tconst errorPayload: unknown = await response\n\t\t\t\t.json()\n\t\t\t\t.catch(() => ({ message: response.statusText }))\n\t\t\tconst message =\n\t\t\t\ttypeof errorPayload === 'object' &&\n\t\t\t\terrorPayload !== null &&\n\t\t\t\t'message' in errorPayload &&\n\t\t\t\ttypeof errorPayload.message === 'string'\n\t\t\t\t\t? errorPayload.message\n\t\t\t\t\t: response.statusText\n\t\t\tthrow new Error(message || `HTTP ${response.status}`)\n\t\t}\n\n\t\tconst payload: unknown = await response.json()\n\t\treturn payload as TResponse\n\t}\n\n\t// =========================================================================\n\t// Native Task Engine — Handler API\n\t// =========================================================================\n\n\t/**\n\t * Define a named task handler.\n\t *\n\t * Returns a TaskDefinition that can be passed to tasks.handler([...]).\n\t * The handler runs with stateless-replay semantics — each dispatch\n\t * replays from the beginning with completed steps injected from cache.\n\t *\n\t * @example\n\t * ```typescript\n\t * const sendEmail = sylphx.tasks.define('send-email', async (payload, { step }) => {\n\t *   const validated = await step.run('validate', () => validate(payload.to))\n\t *   await step.sleep('cool-down', '5 minutes')\n\t *   return step.run('send', () => send(validated))\n\t * })\n\t * ```\n\t */\n\tdefine<TPayload = unknown, TResult = unknown>(\n\t\tname: string,\n\t\tfn: (payload: TPayload, ctx: { step: NativeStepContext }) => Promise<TResult>,\n\t\toptions?: NativeTaskDefinition<TPayload, TResult>['options'],\n\t): NativeTaskDefinition<TPayload, TResult> {\n\t\treturn { name, handler: fn, options }\n\t}\n\n\t/**\n\t * Create a Next.js / Web-API-compatible route handler for a set of task definitions.\n\t *\n\t * @example\n\t * ```typescript\n\t * // app/api/tasks/route.ts\n\t * export const { GET, POST } = sylphx.tasks.handler([sendEmail, processOrder])\n\t * ```\n\t */\n\thandler(tasks: NativeTaskDefinition[], handlerOptions?: TasksHandlerOptions): TasksHandlerResult {\n\t\treturn createTasksHandler(tasks, handlerOptions)\n\t}\n\n\t/**\n\t * Trigger a task run on the Sylphx platform.\n\t *\n\t * The platform will dispatch the task to the app's handler endpoint.\n\t * Returns the taskRunId which can be used to poll status.\n\t */\n\tasync trigger<TPayload = unknown>(\n\t\ttaskName: string,\n\t\tpayload?: TPayload,\n\t\toptions?: {\n\t\t\tdelay?: string\n\t\t\tscheduledFor?: Date\n\t\t\tidempotencyKey?: string\n\t\t\tmaxAttempts?: number\n\t\t},\n\t): Promise<{ taskRunId: string; status: string; createdAt: string }> {\n\t\tconst response = await this.fetch<{ taskRunId: string; status: string; createdAt: string }>(\n\t\t\t'/tasks/trigger',\n\t\t\t{\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\ttaskName,\n\t\t\t\t\tpayload,\n\t\t\t\t\tdelay: options?.delay,\n\t\t\t\t\tscheduledFor: options?.scheduledFor?.toISOString(),\n\t\t\t\t\tidempotencyKey: options?.idempotencyKey,\n\t\t\t\t\tmaxAttempts: options?.maxAttempts,\n\t\t\t\t}),\n\t\t\t},\n\t\t)\n\t\treturn response\n\t}\n\n\t/**\n\t * Fetch the current status of a task run.\n\t */\n\tasync getTaskRun(taskRunId: string): Promise<TaskRunStatus> {\n\t\treturn this.fetch<TaskRunStatus>(`/tasks/${taskRunId}`)\n\t}\n\n\t/**\n\t * Cancel a pending, running, waiting, or failed task run.\n\t */\n\tasync cancelTaskRun(taskRunId: string): Promise<boolean> {\n\t\tconst response = await this.fetch<{ success: boolean }>(`/tasks/${taskRunId}/cancel`, {\n\t\t\tmethod: 'POST',\n\t\t})\n\t\treturn response.success\n\t}\n\n\t/**\n\t * List task runs for the current project/environment.\n\t */\n\tasync listTaskRuns(options?: {\n\t\ttaskName?: string\n\t\tstatus?: TaskRunStatus['status']\n\t\tlimit?: number\n\t\toffset?: number\n\t}): Promise<{ runs: TaskRunStatus[]; total: number }> {\n\t\tconst params = new URLSearchParams()\n\t\tif (options?.taskName) params.set('taskName', options.taskName)\n\t\tif (options?.status) params.set('status', options.status)\n\t\tif (options?.limit) params.set('limit', String(options.limit))\n\t\tif (options?.offset) params.set('offset', String(options.offset))\n\n\t\treturn this.fetch<{ runs: TaskRunStatus[]; total: number }>(`/tasks?${params.toString()}`)\n\t}\n}\n\n/**\n * Create a Jobs client instance\n */\nexport function createTasksClient(config: TasksConfig): TasksClient {\n\treturn new TasksClient(config)\n}\n\n// Backward-compat aliases (Jobs → Tasks rename)\n/** @deprecated Use TasksClient */\nexport class JobsClient extends TasksClient {}\n/** @deprecated Use createTasksClient */\nexport const createJobsClient = createTasksClient\nexport type { TasksConfig as JobsConfig }\n","/**\n * Workflow Builder DSL\n *\n * Fluent API for defining workflows with type safety.\n *\n * @example\n * ```typescript\n * const workflow = createWorkflow('onboarding')\n *   .name('User Onboarding')\n *   .step('create-account', task('create-user'))\n *   .step('send-welcome', task('send-email', (ctx) => ({\n *     to: ctx.results['create-account'].email,\n *     template: 'welcome',\n *   })))\n *   .step('wait-verification', wait(24 * 60 * 60 * 1000))\n *   .step('check-verified', conditional(\n *     (ctx) => ctx.results['create-account'].verified,\n *     [task('activate-account')],\n *     [task('send-reminder')]\n *   ))\n *   .build()\n * ```\n */\n\nimport type {\n\tConditionalStep,\n\tLoopStep,\n\tParallelStep,\n\tStepContext,\n\tSubworkflowStep,\n\tTaskOptions,\n\tTaskPayload,\n\tTaskResult,\n\tTaskStep,\n\tWaitStep,\n\tWorkflowDefinition,\n\tWorkflowOptions,\n\tWorkflowStep,\n} from './types'\n\n// ==========================================\n// Workflow Builder\n// ==========================================\n\n/**\n * Create a new workflow builder\n */\nexport function createWorkflow<TInput extends TaskPayload = TaskPayload, TOutput = TaskResult>(\n\ttype: string,\n): WorkflowBuilder<TInput, TOutput> {\n\treturn new WorkflowBuilder<TInput, TOutput>(type)\n}\n\n/**\n * Workflow Builder\n *\n * Fluent API for building workflow definitions.\n */\nexport class WorkflowBuilder<TInput extends TaskPayload = TaskPayload, TOutput = TaskResult> {\n\tprivate definition: Partial<WorkflowDefinition<TInput, TOutput>> = {}\n\tprivate _steps: WorkflowStep[] = []\n\n\tconstructor(type: string) {\n\t\tthis.definition.type = type\n\t}\n\n\t/**\n\t * Set workflow name\n\t */\n\tname(name: string): this {\n\t\tthis.definition.name = name\n\t\treturn this\n\t}\n\n\t/**\n\t * Set workflow description\n\t */\n\tdescription(description: string): this {\n\t\tthis.definition.description = description\n\t\treturn this\n\t}\n\n\t/**\n\t * Set default options\n\t */\n\tdefaults(options: WorkflowOptions): this {\n\t\tthis.definition.defaults = options\n\t\treturn this\n\t}\n\n\t/**\n\t * Add a step to the workflow\n\t */\n\tstep(name: string, step: WorkflowStep): this {\n\t\t// Override step name\n\t\tconst namedStep = { ...step, name }\n\t\tthis._steps.push(namedStep)\n\t\treturn this\n\t}\n\n\t/**\n\t * Add multiple steps\n\t */\n\tsteps(...steps: Array<[string, WorkflowStep]>): this {\n\t\tfor (const [name, step] of steps) {\n\t\t\tthis.step(name, step)\n\t\t}\n\t\treturn this\n\t}\n\n\t/**\n\t * Add on complete callback\n\t */\n\tonComplete(callback: (result: TOutput) => void): this {\n\t\tthis.definition.onComplete = callback\n\t\treturn this\n\t}\n\n\t/**\n\t * Add on error callback\n\t */\n\tonError(callback: (error: Error, step: string) => void): this {\n\t\tthis.definition.onError = callback\n\t\treturn this\n\t}\n\n\t/**\n\t * Build the workflow definition\n\t */\n\tbuild(): WorkflowDefinition<TInput, TOutput> {\n\t\treturn {\n\t\t\ttype: this.definition.type!,\n\t\t\tname: this.definition.name,\n\t\t\tdescription: this.definition.description,\n\t\t\tsteps: this._steps,\n\t\t\tdefaults: this.definition.defaults,\n\t\t\tonComplete: this.definition.onComplete,\n\t\t\tonError: this.definition.onError,\n\t\t}\n\t}\n}\n\n// ==========================================\n// Step Builders\n// ==========================================\n\n/**\n * Create a job step\n */\nexport function task(\n\ttaskType: string,\n\tpayload?: TaskPayload | ((context: StepContext) => TaskPayload),\n\toptions?: TaskOptions,\n): TaskStep {\n\treturn {\n\t\ttype: 'job',\n\t\tname: taskType,\n\t\tjobType: taskType,\n\t\tpayload: typeof payload === 'function' ? payload : payload ? () => payload : undefined,\n\t\toptions,\n\t}\n}\n\n/**\n * Create a conditional step\n */\nexport function conditional(\n\tcondition: (context: StepContext) => boolean,\n\tthenSteps: WorkflowStep[],\n\telseSteps?: WorkflowStep[],\n): ConditionalStep {\n\treturn {\n\t\ttype: 'conditional',\n\t\tname: 'conditional',\n\t\tcondition,\n\t\t// biome-ignore lint/suspicious/noThenProperty: workflow step field name\n\t\tthen: thenSteps,\n\t\telse: elseSteps,\n\t}\n}\n\n/**\n * Create a parallel step\n */\nexport function parallel(\n\tsteps: WorkflowStep[],\n\toptions?: { waitFor?: 'all' | 'any'; maxConcurrency?: number },\n): ParallelStep {\n\treturn {\n\t\ttype: 'parallel',\n\t\tname: 'parallel',\n\t\tsteps,\n\t\twaitFor: options?.waitFor || 'all',\n\t\tmaxConcurrency: options?.maxConcurrency,\n\t}\n}\n\n/**\n * Create a loop step\n */\nexport function loop(\n\titems: unknown[] | ((context: StepContext) => unknown[]),\n\tstep: WorkflowStep,\n\toptions?: {\n\t\tmaxConcurrency?: number\n\t\tbreakIf?: (item: unknown, index: number, context: StepContext) => boolean\n\t},\n): LoopStep {\n\treturn {\n\t\ttype: 'loop',\n\t\tname: 'loop',\n\t\titems,\n\t\tstep,\n\t\tmaxConcurrency: options?.maxConcurrency,\n\t\tbreakIf: options?.breakIf,\n\t}\n}\n\n/**\n * Create a wait step\n */\nexport function wait(until: number | Date | ((context: StepContext) => number | Date)): WaitStep {\n\treturn {\n\t\ttype: 'wait',\n\t\tname: 'wait',\n\t\tuntil,\n\t}\n}\n\n/**\n * Create a sub-workflow step\n */\nexport function subworkflow(\n\tworkflowType: string,\n\tpayload?: TaskPayload | ((context: StepContext) => TaskPayload),\n\toptions?: WorkflowOptions,\n): SubworkflowStep {\n\treturn {\n\t\ttype: 'subworkflow',\n\t\tname: workflowType,\n\t\tworkflowType,\n\t\tpayload: typeof payload === 'function' ? payload : payload ? () => payload : undefined,\n\t\toptions,\n\t}\n}\n\n// ==========================================\n// Step Helpers\n// ==========================================\n\n/**\n * Create a job step with conditional execution\n */\nexport function jobIf(\n\tcondition: (context: StepContext) => boolean,\n\ttaskType: string,\n\tpayload?: TaskPayload | ((context: StepContext) => TaskPayload),\n\toptions?: TaskOptions,\n): TaskStep {\n\tconst step = task(taskType, payload, options)\n\treturn {\n\t\t...step,\n\t\tif: condition,\n\t}\n}\n\n/**\n * Create a delay step (alias for wait)\n */\nexport function delay(ms: number): WaitStep {\n\treturn wait(ms)\n}\n\n/**\n * Create a step that sleeps until a specific time\n */\nexport function sleepUntil(date: Date | ((context: StepContext) => Date)): WaitStep {\n\treturn wait(date)\n}\n\n/**\n * Create a retry wrapper for a step\n */\nexport function withRetry(\n\tstep: TaskStep,\n\toptions: { maxRetries: number; retryDelay?: number },\n): TaskStep {\n\treturn {\n\t\t...step,\n\t\toptions: {\n\t\t\t...step.options,\n\t\t\tmaxRetries: options.maxRetries,\n\t\t\tretryDelay: options.retryDelay ? { type: 'fixed', delay: options.retryDelay } : undefined,\n\t\t},\n\t}\n}\n\n/**\n * Create a timeout wrapper for a step\n */\nexport function withTimeout(step: TaskStep, timeoutMs: number): TaskStep {\n\treturn {\n\t\t...step,\n\t\toptions: {\n\t\t\t...step.options,\n\t\t\ttimeout: timeoutMs,\n\t\t},\n\t}\n}\n\n// ==========================================\n// Workflow Composition\n// ==========================================\n\n/**\n * Compose multiple workflows sequentially\n */\nexport function sequence(...workflows: WorkflowDefinition[]): WorkflowStep[] {\n\treturn workflows.map((workflow, index) => ({\n\t\ttype: 'subworkflow' as const,\n\t\tname: `sequence-${index}-${workflow.type}`,\n\t\tworkflowType: workflow.type,\n\t}))\n}\n\n/**\n * Fan-out pattern: Execute same job for multiple items\n */\nexport function fanOut(\n\titems: unknown[] | ((context: StepContext) => unknown[]),\n\ttaskType: string,\n\tpayloadMapper: (item: unknown, index: number) => TaskPayload,\n\toptions?: { maxConcurrency?: number },\n): LoopStep {\n\treturn loop(\n\t\titems,\n\t\t{\n\t\t\ttype: 'job',\n\t\t\tname: `fanout-${taskType}`,\n\t\t\tjobType: taskType,\n\t\t\tpayload: (ctx) => {\n\t\t\t\t// This is a simplified version - real implementation needs item context\n\t\t\t\treturn {} as TaskPayload\n\t\t\t},\n\t\t},\n\t\t{ maxConcurrency: options?.maxConcurrency },\n\t)\n}\n\n/**\n * Saga pattern: Define compensating actions for each step\n */\nexport interface SagaStep {\n\tforward: TaskStep\n\tcompensate: TaskStep\n}\n\nexport function saga(steps: SagaStep[]): WorkflowStep[] {\n\t// Build forward steps with compensation tracking\n\tconst workflowSteps: WorkflowStep[] = []\n\n\tfor (let i = 0; i < steps.length; i++) {\n\t\tconst step = steps[i]!\n\n\t\t// Add forward step with error handling\n\t\tconst forwardStep: TaskStep = {\n\t\t\t...step.forward,\n\t\t\tname: `saga-forward-${i}-${step.forward.jobType}`,\n\t\t\tonComplete: (result, ctx) => {\n\t\t\t\t// Track completed step for potential compensation\n\t\t\t\tctx.metadata.completedSagaSteps = [\n\t\t\t\t\t...((ctx.metadata.completedSagaSteps as number[]) || []),\n\t\t\t\t\ti,\n\t\t\t\t]\n\t\t\t\treturn result\n\t\t\t},\n\t\t}\n\n\t\tworkflowSteps.push(forwardStep)\n\t}\n\n\t// Note: Actual saga compensation logic would be handled by the executor\n\t// This is a simplified client-side representation\n\n\treturn workflowSteps\n}\n\n// ==========================================\n// Validation\n// ==========================================\n\n/**\n * Validate a workflow definition\n */\nexport function validateWorkflow(workflow: WorkflowDefinition): string[] {\n\tconst errors: string[] = []\n\n\tif (!workflow.type) {\n\t\terrors.push('Workflow type is required')\n\t}\n\n\tif (!workflow.steps || workflow.steps.length === 0) {\n\t\terrors.push('Workflow must have at least one step')\n\t}\n\n\t// Check for duplicate step names\n\tconst stepNames = new Set<string>()\n\tconst checkSteps = (steps: WorkflowStep[]) => {\n\t\tfor (const step of steps) {\n\t\t\tif (stepNames.has(step.name)) {\n\t\t\t\terrors.push(`Duplicate step name: ${step.name}`)\n\t\t\t}\n\t\t\tstepNames.add(step.name)\n\n\t\t\t// Recursively check nested steps\n\t\t\tif (step.type === 'conditional') {\n\t\t\t\tcheckSteps(step.then)\n\t\t\t\tif (step.else) checkSteps(step.else)\n\t\t\t} else if (step.type === 'parallel') {\n\t\t\t\tcheckSteps(step.steps)\n\t\t\t} else if (step.type === 'loop') {\n\t\t\t\tcheckSteps([step.step])\n\t\t\t}\n\t\t}\n\t}\n\n\tif (workflow.steps) {\n\t\tcheckSteps(workflow.steps)\n\t}\n\n\treturn errors\n}\n\n// Backward-compat aliases\n/** @deprecated Use task() instead */\nexport const job = task\n","/**\n * Real-time Streaming Hooks\n *\n * SSE-based real-time subscriptions for managed durable streams.\n * Automatic reconnection, message history, and optimistic updates.\n *\n * @example\n * ```tsx\n * function Chat({ roomId }) {\n *   const { messages, emit, status } = useRealtime<ChatMessage>(`chat:${roomId}`, {\n *     events: ['message', 'typing'],\n *     history: 50,\n *     onMessage: (msg) => console.log('New:', msg),\n *   })\n *\n *   return (\n *     <div>\n *       <div>Status: {status}</div>\n *       {messages.map(msg => <Message key={msg.id} {...msg} />)}\n *       <button onClick={() => emit('message', { text: 'Hello!' })}>\n *         Send\n *       </button>\n *     </div>\n *   )\n * }\n * ```\n */\n\n'use client'\n\nimport { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'\nimport { DEFAULT_SDK_API_HOST, SDK_API_PATH, SDK_PLATFORM, SDK_VERSION } from '../../constants'\nimport type { SylphxErrorCode } from '../../errors'\nimport { RateLimitError, SylphxError } from '../../errors'\nimport type { StreamMessage } from '../../realtime-types'\nimport { PlatformContext } from '../platform-context'\n\n// Re-export shared type for consumers who import from react\nexport type { StreamMessage }\n\n/** Connection status */\nexport type RealtimeStatus = 'connecting' | 'connected' | 'reconnecting' | 'disconnected'\n\n/** Options for useRealtime hook */\nexport interface UseRealtimeOptions<T> {\n\t/** Events to listen for (if empty, listens to all events) */\n\tevents?: string[]\n\t/** Number of historical messages to load on connect, or options object */\n\thistory?: number | { start?: string; limit?: number }\n\t/** Callback when connected */\n\tonConnect?: (channel: string) => void\n\t/** Callback on new message */\n\tonMessage?: (message: StreamMessage<T>) => void\n\t/** Callback on reconnect signal */\n\tonReconnect?: () => void\n\t/** Callback on error */\n\tonError?: (error: Error) => void\n\t/** Whether to auto-connect (default: true) */\n\tenabled?: boolean\n\t/** Platform URL (uses provider config if not specified) */\n\tplatformUrl?: string\n}\n\n/** Return type for useRealtime hook */\nexport interface UseRealtimeReturn<T> {\n\t/** Messages in chronological order */\n\tmessages: StreamMessage<T>[]\n\t/** Connection state */\n\tstatus: RealtimeStatus\n\t/** Emit to this channel */\n\temit: (event: string, data: T) => Promise<string>\n\t/** Clear local messages */\n\tclear: () => void\n\t/** Manually connect */\n\tconnect: () => void\n\t/** Manually disconnect */\n\tdisconnect: () => void\n}\n\n/** Options for useRealtimeChannels hook */\nexport interface UseRealtimeChannelsOptions<T> extends Omit<UseRealtimeOptions<T>, 'history'> {\n\t/** History options per channel, or single value for all */\n\thistory?: number | Record<string, number | { start?: string; limit?: number }>\n}\n\n// ============================================\n// useRealtime Hook\n// ============================================\n\n/**\n * Subscribe to real-time events via SSE\n *\n * @param channel - Channel name to subscribe to\n * @param options - Configuration options\n * @returns Messages, status, and control functions\n *\n * @example\n * ```tsx\n * function Chat({ roomId }) {\n *   const { messages, emit, status } = useRealtime<ChatMessage>(`chat:${roomId}`, {\n *     events: ['message', 'typing'],\n *     history: 50,\n *     onMessage: (msg) => console.log('New:', msg),\n *   })\n *\n *   return (\n *     <div>\n *       <div>Status: {status}</div>\n *       {messages.map(msg => <Message key={msg.id} {...msg} />)}\n *       <button onClick={() => emit('message', { text: 'Hello!' })}>\n *         Send\n *       </button>\n *     </div>\n *   )\n * }\n * ```\n */\nexport function useRealtime<T = unknown>(\n\tchannel: string,\n\toptions: UseRealtimeOptions<T> = {},\n): UseRealtimeReturn<T> {\n\tconst {\n\t\tevents,\n\t\thistory,\n\t\tonConnect,\n\t\tonMessage,\n\t\tonReconnect,\n\t\tonError,\n\t\tenabled = true,\n\t\tplatformUrl: customPlatformUrl,\n\t} = options\n\n\tconst [messages, setMessages] = useState<StreamMessage<T>[]>([])\n\tconst [status, setStatus] = useState<RealtimeStatus>('disconnected')\n\n\t// Get platform context for API key and URL\n\tconst platformContext = useContext(PlatformContext)\n\tconst appId = platformContext?.appId || ''\n\n\t// Refs to avoid stale closures\n\tconst lastAckRef = useRef<string>('0')\n\tconst eventSourceRef = useRef<EventSource | null>(null)\n\tconst reconnectTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\tconst reconnectAttemptRef = useRef(0)\n\tconst mountedRef = useRef(true)\n\n\t// Determine platform URL\n\tconst platformUrl =\n\t\tcustomPlatformUrl || platformContext?.platformUrl || `https://${DEFAULT_SDK_API_HOST}`\n\n\t// Build subscription URL\n\tconst buildUrl = useCallback(() => {\n\t\tconst url = new URL(`${platformUrl}${SDK_API_PATH}/realtime/subscribe`)\n\t\turl.searchParams.set('channel', channel)\n\n\t\t// Add last acknowledged ID for resumption\n\t\tif (lastAckRef.current !== '0') {\n\t\t\turl.searchParams.set(`last_ack_${channel}`, lastAckRef.current)\n\t\t}\n\n\t\treturn url.toString()\n\t}, [platformUrl, channel])\n\n\t// SDK headers for fetch calls\n\tconst sdkHeaders = useMemo(\n\t\t() => ({\n\t\t\t'Content-Type': 'application/json',\n\t\t\t'x-app-secret': appId,\n\t\t\t'X-SDK-Version': SDK_VERSION,\n\t\t\t'X-SDK-Platform': SDK_PLATFORM,\n\t\t}),\n\t\t[appId],\n\t)\n\n\t// Fetch history\n\tconst fetchHistory = useCallback(async () => {\n\t\tif (!history) return\n\n\t\tconst historyLimit = typeof history === 'number' ? history : (history.limit ?? 100)\n\t\tconst historyStart = typeof history === 'object' ? history.start : undefined\n\n\t\ttry {\n\t\t\tconst response = await fetch(`${platformUrl}${SDK_API_PATH}/realtime/history`, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: sdkHeaders,\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tchannel,\n\t\t\t\t\tstart: historyStart,\n\t\t\t\t\tlimit: historyLimit,\n\t\t\t\t}),\n\t\t\t})\n\n\t\t\tif (!response.ok) return\n\n\t\t\tconst result = (await response.json()) as {\n\t\t\t\tmessages: StreamMessage<T>[]\n\t\t\t}\n\t\t\tif (!mountedRef.current) return\n\n\t\t\tif (result.messages.length > 0) {\n\t\t\t\tsetMessages(result.messages)\n\t\t\t\t// Update last ack to latest message\n\t\t\t\tlastAckRef.current = result.messages[result.messages.length - 1].id\n\t\t\t}\n\t\t} catch {\n\t\t\t// History fetch is best-effort, don't fail the connection\n\t\t}\n\t}, [platformUrl, sdkHeaders, channel, history])\n\n\t// Connect to SSE stream\n\tconst connect = useCallback(() => {\n\t\tif (!enabled || !appId) return\n\n\t\t// Clean up existing connection\n\t\tif (eventSourceRef.current) {\n\t\t\teventSourceRef.current.close()\n\t\t}\n\n\t\tsetStatus('connecting')\n\n\t\t// EventSource doesn't support custom headers, so we use query params\n\t\tconst url = new URL(buildUrl())\n\t\turl.searchParams.set('app_id', appId)\n\n\t\tconst es = new EventSource(url.toString())\n\t\teventSourceRef.current = es\n\n\t\tes.onopen = () => {\n\t\t\tif (!mountedRef.current) return\n\t\t\treconnectAttemptRef.current = 0 // Reset backoff on successful connect\n\t\t\tsetStatus('connected')\n\t\t\tfetchHistory()\n\t\t\tonConnect?.(channel)\n\t\t}\n\n\t\tes.onmessage = (event) => {\n\t\t\tif (!mountedRef.current) return\n\n\t\t\ttry {\n\t\t\t\tconst data = JSON.parse(event.data) as StreamMessage<T> & {\n\t\t\t\t\ttype?: string\n\t\t\t\t}\n\n\t\t\t\t// Handle special message types\n\t\t\t\tif (data.type === 'connected') {\n\t\t\t\t\tsetStatus('connected')\n\t\t\t\t\tonConnect?.(channel)\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif (data.type === 'reconnect') {\n\t\t\t\t\tsetStatus('reconnecting')\n\t\t\t\t\tonReconnect?.()\n\t\t\t\t\tes.close()\n\t\t\t\t\t// Reconnect after small delay\n\t\t\t\t\treconnectTimeoutRef.current = setTimeout(() => {\n\t\t\t\t\t\tif (mountedRef.current) connect()\n\t\t\t\t\t}, 100)\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif (data.type === 'heartbeat') {\n\t\t\t\t\t// Heartbeat - just keep connection alive\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// Regular message - check event filter\n\t\t\t\tif (events && events.length > 0 && !events.includes(data.event)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// Add message to state\n\t\t\t\tsetMessages((prev) => [...prev, data as StreamMessage<T>])\n\t\t\t\tlastAckRef.current = data.id\n\t\t\t\tonMessage?.(data as StreamMessage<T>)\n\t\t\t} catch {\n\t\t\t\t// Invalid JSON - ignore\n\t\t\t}\n\t\t}\n\n\t\tes.onerror = () => {\n\t\t\tif (!mountedRef.current) return\n\n\t\t\tsetStatus('reconnecting')\n\t\t\tes.close()\n\n\t\t\t// Reconnect with exponential backoff: 1s, 2s, 4s, 8s, ... up to 30s\n\t\t\tconst attempt = reconnectAttemptRef.current\n\t\t\treconnectAttemptRef.current = attempt + 1\n\t\t\tconst delay = Math.min(1000 * 2 ** attempt, 30000)\n\t\t\treconnectTimeoutRef.current = setTimeout(() => {\n\t\t\t\tif (mountedRef.current && enabled) connect()\n\t\t\t}, delay)\n\n\t\t\tonError?.(new Error('SSE connection error'))\n\t\t}\n\t}, [\n\t\tenabled,\n\t\tappId,\n\t\tbuildUrl,\n\t\tfetchHistory,\n\t\tchannel,\n\t\tevents,\n\t\tonConnect,\n\t\tonMessage,\n\t\tonReconnect,\n\t\tonError,\n\t])\n\n\t// Disconnect\n\tconst disconnect = useCallback(() => {\n\t\tif (eventSourceRef.current) {\n\t\t\teventSourceRef.current.close()\n\t\t\teventSourceRef.current = null\n\t\t}\n\t\tif (reconnectTimeoutRef.current) {\n\t\t\tclearTimeout(reconnectTimeoutRef.current)\n\t\t\treconnectTimeoutRef.current = null\n\t\t}\n\t\tsetStatus('disconnected')\n\t}, [])\n\n\t// Emit message with SylphxError wrapping\n\tconst emit = useCallback(\n\t\tasync (event: string, data: T): Promise<string> => {\n\t\t\tconst response = await fetch(`${platformUrl}${SDK_API_PATH}/realtime/emit`, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: sdkHeaders,\n\t\t\t\tbody: JSON.stringify({ channel, event, data }),\n\t\t\t})\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst errorBody = await response.json().catch(() => ({ error: 'Emit failed' }))\n\t\t\t\tconst message = typeof errorBody.error === 'string' ? errorBody.error : 'Emit failed'\n\n\t\t\t\tif (response.status === 429) {\n\t\t\t\t\tthrow new RateLimitError(message, {\n\t\t\t\t\t\tretryAfter: Number(response.headers.get('Retry-After')) || undefined,\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tconst codeMap: Record<number, SylphxErrorCode> = {\n\t\t\t\t\t400: 'BAD_REQUEST',\n\t\t\t\t\t401: 'UNAUTHORIZED',\n\t\t\t\t\t403: 'FORBIDDEN',\n\t\t\t\t\t404: 'NOT_FOUND',\n\t\t\t\t\t500: 'INTERNAL_SERVER_ERROR',\n\t\t\t\t}\n\t\t\t\tthrow new SylphxError(message, {\n\t\t\t\t\tcode: codeMap[response.status] ?? 'UNKNOWN',\n\t\t\t\t\tstatus: response.status,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tconst result = (await response.json()) as { id: string }\n\t\t\treturn result.id\n\t\t},\n\t\t[platformUrl, sdkHeaders, channel],\n\t)\n\n\t// Clear messages\n\tconst clear = useCallback(() => {\n\t\tsetMessages([])\n\t\tlastAckRef.current = '0'\n\t}, [])\n\n\t// Effect: Connect on mount, disconnect on unmount\n\tuseEffect(() => {\n\t\tmountedRef.current = true\n\n\t\tif (enabled && appId) {\n\t\t\tconnect()\n\t\t}\n\n\t\treturn () => {\n\t\t\tmountedRef.current = false\n\t\t\tdisconnect()\n\t\t}\n\t}, [enabled, appId, connect, disconnect]) // Reconnect when channel changes\n\n\treturn {\n\t\tmessages,\n\t\tstatus,\n\t\temit,\n\t\tclear,\n\t\tconnect,\n\t\tdisconnect,\n\t}\n}\n\n// ============================================\n// useRealtimeChannels Hook\n// ============================================\n\n/**\n * Subscribe to multiple channels at once\n *\n * @param channels - Array of channel names to subscribe to\n * @param options - Configuration options\n * @returns Combined messages, status, and control functions\n *\n * @example\n * ```tsx\n * function MultiChat({ roomIds }) {\n *   const { messages, emit, status } = useRealtimeChannels(\n *     roomIds.map(id => `chat:${id}`),\n *     {\n *       events: ['message'],\n *       history: 20,\n *     }\n *   )\n *\n *   // Messages from all channels combined\n *   return messages.map(msg => (\n *     <Message key={msg.id} channel={msg.channel} {...msg} />\n *   ))\n * }\n * ```\n */\nexport function useRealtimeChannels<T = unknown>(\n\tchannels: string[],\n\toptions: UseRealtimeChannelsOptions<T> = {},\n): UseRealtimeReturn<T> {\n\tconst {\n\t\tevents,\n\t\tonConnect,\n\t\tonMessage,\n\t\tonReconnect,\n\t\tonError,\n\t\tenabled = true,\n\t\tplatformUrl: customPlatformUrl,\n\t} = options\n\n\tconst [messages, setMessages] = useState<StreamMessage<T>[]>([])\n\tconst [statuses, setStatuses] = useState<Record<string, RealtimeStatus>>({})\n\n\t// Get platform context for API key and URL\n\tconst platformContext = useContext(PlatformContext)\n\tconst appId = platformContext?.appId || ''\n\tconst platformUrl =\n\t\tcustomPlatformUrl || platformContext?.platformUrl || `https://${DEFAULT_SDK_API_HOST}`\n\n\t// Refs\n\tconst lastAcksRef = useRef<Record<string, string>>({})\n\tconst eventSourcesRef = useRef<Record<string, EventSource>>({})\n\tconst mountedRef = useRef(true)\n\n\t// Computed overall status\n\tconst status: RealtimeStatus = (() => {\n\t\tconst statusValues = Object.values(statuses)\n\t\tif (statusValues.length === 0) return 'disconnected'\n\t\tif (statusValues.some((s) => s === 'connecting')) return 'connecting'\n\t\tif (statusValues.some((s) => s === 'reconnecting')) return 'reconnecting'\n\t\tif (statusValues.every((s) => s === 'connected')) return 'connected'\n\t\treturn 'disconnected'\n\t})()\n\n\t// Connect to a single channel\n\tconst connectChannel = useCallback(\n\t\t(channel: string) => {\n\t\t\tif (!enabled || !appId) return\n\n\t\t\t// Clean up existing\n\t\t\tif (eventSourcesRef.current[channel]) {\n\t\t\t\teventSourcesRef.current[channel].close()\n\t\t\t}\n\n\t\t\tsetStatuses((prev) => ({ ...prev, [channel]: 'connecting' }))\n\n\t\t\tconst url = new URL(`${platformUrl}${SDK_API_PATH}/realtime/subscribe`)\n\t\t\turl.searchParams.set('channel', channel)\n\t\t\turl.searchParams.set('app_id', appId)\n\n\t\t\tconst lastAck = lastAcksRef.current[channel]\n\t\t\tif (lastAck && lastAck !== '0') {\n\t\t\t\turl.searchParams.set(`last_ack_${channel}`, lastAck)\n\t\t\t}\n\n\t\t\tconst es = new EventSource(url.toString())\n\t\t\teventSourcesRef.current[channel] = es\n\n\t\t\tes.onopen = () => {\n\t\t\t\tif (!mountedRef.current) return\n\t\t\t\tsetStatuses((prev) => ({ ...prev, [channel]: 'connected' }))\n\t\t\t\tonConnect?.(channel)\n\t\t\t}\n\n\t\t\tes.onmessage = (event) => {\n\t\t\t\tif (!mountedRef.current) return\n\n\t\t\t\ttry {\n\t\t\t\t\tconst data = JSON.parse(event.data) as StreamMessage<T> & {\n\t\t\t\t\t\ttype?: string\n\t\t\t\t\t}\n\n\t\t\t\t\tif (data.type === 'connected' || data.type === 'heartbeat') return\n\t\t\t\t\tif (data.type === 'reconnect') {\n\t\t\t\t\t\tsetStatuses((prev) => ({ ...prev, [channel]: 'reconnecting' }))\n\t\t\t\t\t\tonReconnect?.()\n\t\t\t\t\t\tes.close()\n\t\t\t\t\t\tsetTimeout(() => mountedRef.current && connectChannel(channel), 100)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\tif (events && events.length > 0 && !events.includes(data.event)) return\n\n\t\t\t\t\tsetMessages((prev) => [...prev, data as StreamMessage<T>])\n\t\t\t\t\tlastAcksRef.current[channel] = data.id\n\t\t\t\t\tonMessage?.(data as StreamMessage<T>)\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore invalid JSON\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tes.onerror = () => {\n\t\t\t\tif (!mountedRef.current) return\n\t\t\t\tsetStatuses((prev) => ({ ...prev, [channel]: 'reconnecting' }))\n\t\t\t\tes.close()\n\t\t\t\tsetTimeout(() => mountedRef.current && enabled && connectChannel(channel), 1000)\n\t\t\t\tonError?.(new Error(`SSE connection error for channel: ${channel}`))\n\t\t\t}\n\t\t},\n\t\t[enabled, appId, platformUrl, events, onConnect, onMessage, onReconnect, onError],\n\t)\n\n\t// Connect all channels\n\tconst connect = useCallback(() => {\n\t\tchannels.forEach(connectChannel)\n\t}, [channels, connectChannel])\n\n\t// Disconnect all\n\tconst disconnect = useCallback(() => {\n\t\tObject.values(eventSourcesRef.current).forEach((es) => {\n\t\t\tes.close()\n\t\t})\n\t\teventSourcesRef.current = {}\n\t\tsetStatuses({})\n\t}, [])\n\n\t// SDK headers for multi-channel emit\n\tconst sdkHeaders = useMemo(\n\t\t() => ({\n\t\t\t'Content-Type': 'application/json',\n\t\t\t'x-app-secret': appId,\n\t\t\t'X-SDK-Version': SDK_VERSION,\n\t\t\t'X-SDK-Platform': SDK_PLATFORM,\n\t\t}),\n\t\t[appId],\n\t)\n\n\t// Emit to a specific channel with SylphxError wrapping\n\tconst emit = useCallback(\n\t\tasync (event: string, data: T, targetChannel?: string): Promise<string> => {\n\t\t\tconst channel = targetChannel || channels[0]\n\t\t\tif (!channel) throw new SylphxError('No channel specified', { code: 'BAD_REQUEST' })\n\n\t\t\tconst response = await fetch(`${platformUrl}${SDK_API_PATH}/realtime/emit`, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: sdkHeaders,\n\t\t\t\tbody: JSON.stringify({ channel, event, data }),\n\t\t\t})\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst errorBody = await response.json().catch(() => ({ error: 'Emit failed' }))\n\t\t\t\tconst message = typeof errorBody.error === 'string' ? errorBody.error : 'Emit failed'\n\n\t\t\t\tif (response.status === 429) {\n\t\t\t\t\tthrow new RateLimitError(message, {\n\t\t\t\t\t\tretryAfter: Number(response.headers.get('Retry-After')) || undefined,\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tthrow new SylphxError(message, {\n\t\t\t\t\tcode:\n\t\t\t\t\t\tresponse.status === 401\n\t\t\t\t\t\t\t? 'UNAUTHORIZED'\n\t\t\t\t\t\t\t: response.status === 403\n\t\t\t\t\t\t\t\t? 'FORBIDDEN'\n\t\t\t\t\t\t\t\t: 'UNKNOWN',\n\t\t\t\t\tstatus: response.status,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tconst result = (await response.json()) as { id: string }\n\t\t\treturn result.id\n\t\t},\n\t\t[channels, platformUrl, sdkHeaders],\n\t)\n\n\t// Clear all messages\n\tconst clear = useCallback(() => {\n\t\tsetMessages([])\n\t\tlastAcksRef.current = {}\n\t}, [])\n\n\t// Effect: Connect on mount\n\tuseEffect(() => {\n\t\tmountedRef.current = true\n\n\t\tif (enabled && appId && channels.length > 0) {\n\t\t\tconnect()\n\t\t}\n\n\t\treturn () => {\n\t\t\tmountedRef.current = false\n\t\t\tdisconnect()\n\t\t}\n\t}, [enabled, appId, channels.length, connect, disconnect]) // Reconnect when channels change\n\n\treturn {\n\t\tmessages,\n\t\tstatus,\n\t\temit: (event: string, data: T) => emit(event, data),\n\t\tclear,\n\t\tconnect,\n\t\tdisconnect,\n\t}\n}\n","/**\n * KV (Key-Value Store) React Hooks\n *\n * Client-side hooks for managed key-value operations.\n * Provides React Query integration for caching and state management.\n *\n * @example\n * ```tsx\n * function UserProfile({ userId }) {\n *   const { get, set } = useKv()\n *   const [profile, setProfile] = useState(null)\n *   const [loading, setLoading] = useState(true)\n *\n *   useEffect(() => {\n *     get(`user:${userId}:profile`)\n *       .then(({ value }) => setProfile(value))\n *       .finally(() => setLoading(false))\n *   }, [userId, get])\n *\n *   const updateProfile = async (data) => {\n *     await set(`user:${userId}:profile`, data, { ex: 3600 })\n *     setProfile(data)\n *   }\n *\n *   if (loading) return <Spinner />\n *   return profile ? <Profile data={profile} onUpdate={updateProfile} /> : null\n * }\n * ```\n */\n\n'use client'\n\nimport { useCallback, useContext, useMemo } from 'react'\nimport {\n\tDEFAULT_SDK_API_HOST,\n\tMAX_RETRIES,\n\tSDK_API_PATH,\n\tSDK_PLATFORM,\n\tSDK_VERSION,\n} from '../../constants'\nimport type { SylphxErrorCode } from '../../errors'\nimport { exponentialBackoff, RateLimitError, SylphxError } from '../../errors'\nimport type { KvRateLimitResult, KvSetOptions, KvZMember } from '../../kv-types'\nimport { PlatformContext } from '../platform-context'\n\n// Re-export shared types for consumer convenience\nexport type {\n\tKvRateLimitResult,\n\tKvSetOptions,\n\tKvZMember,\n} from '../../kv-types'\n\n// ============================================\n// Types\n// ============================================\n\n/** Options for useKv hook */\nexport interface UseKvOptions {\n\t/** Platform URL (uses provider config if not specified) */\n\tplatformUrl?: string\n}\n\n/** Return type for useKv hook */\nexport interface UseKvReturn {\n\t// Basic Operations\n\t/** Get a value by key */\n\tget<T = unknown>(key: string): Promise<{ value: T | null; ttl: number | null }>\n\t/** Set a value */\n\tset<T = unknown>(key: string, value: T, options?: KvSetOptions): Promise<boolean>\n\t/** Delete a key */\n\tdel(key: string): Promise<number>\n\t/** Check if a key exists */\n\texists(key: string): Promise<boolean>\n\n\t// Multiple Key Operations\n\t/** Get multiple values */\n\tmget<T = unknown>(keys: string[]): Promise<Record<string, T | null>>\n\t/** Set multiple values */\n\tmset<T = unknown>(\n\t\tentries: Array<{ key: string; value: T }>,\n\t\toptions?: Pick<KvSetOptions, 'ex' | 'px'>,\n\t): Promise<void>\n\n\t// Counter Operations\n\t/** Increment a numeric value atomically */\n\tincr(key: string, by?: number): Promise<number>\n\n\t// Expiration\n\t/** Set key expiration */\n\texpire(key: string, seconds: number): Promise<boolean>\n\n\t// Rate Limiting\n\t/** Check rate limit using sliding window algorithm */\n\tratelimit(key: string, options: { limit: number; window: string }): Promise<KvRateLimitResult>\n\n\t// Hash Operations\n\t/** Set hash fields */\n\thset<T = unknown>(key: string, fields: Record<string, T>): Promise<number>\n\t/** Get a hash field */\n\thget<T = unknown>(key: string, field: string): Promise<T | null>\n\t/** Get all hash fields */\n\thgetall<T = unknown>(key: string): Promise<Record<string, T> | null>\n\n\t// List Operations\n\t/** Push values to the left of a list */\n\tlpush<T = unknown>(key: string, ...values: T[]): Promise<number>\n\t/** Get a range of elements from a list */\n\tlrange<T = unknown>(key: string, start?: number, stop?: number): Promise<T[]>\n\n\t// Sorted Set Operations\n\t/** Add members with scores to a sorted set */\n\tzadd(key: string, ...members: Array<{ score: number; member: string }>): Promise<number>\n\t/** Get members from a sorted set by rank range */\n\tzrange(\n\t\tkey: string,\n\t\tstart?: number,\n\t\tstop?: number,\n\t\toptions?: { withScores?: boolean; rev?: boolean },\n\t): Promise<KvZMember[]>\n}\n\n// ============================================\n// useKv Hook\n// ============================================\n\n/**\n * KV (Key-Value Store) hook for client-side operations\n *\n * @param options - Configuration options\n * @returns KV client methods\n *\n * @example\n * ```tsx\n * function Counter({ id }) {\n *   const { incr } = useKv()\n *   const [count, setCount] = useState(0)\n *\n *   const increment = async () => {\n *     const newCount = await incr(`counter:${id}`)\n *     setCount(newCount)\n *   }\n *\n *   return (\n *     <button onClick={increment}>\n *       Count: {count}\n *     </button>\n *   )\n * }\n * ```\n */\nexport function useKv(options: UseKvOptions = {}): UseKvReturn {\n\tconst { platformUrl: customPlatformUrl } = options\n\n\t// Get platform context\n\tconst platformContext = useContext(PlatformContext)\n\tconst appId = platformContext?.appId || ''\n\tconst platformUrl =\n\t\tcustomPlatformUrl || platformContext?.platformUrl || `https://${DEFAULT_SDK_API_HOST}`\n\n\t// Build headers - x-app-secret is the standard SDK auth header, plus SDK identification\n\tconst headers = useMemo(\n\t\t() => ({\n\t\t\t'Content-Type': 'application/json',\n\t\t\t'x-app-secret': appId,\n\t\t\t'X-SDK-Version': SDK_VERSION,\n\t\t\t'X-SDK-Platform': SDK_PLATFORM,\n\t\t}),\n\t\t[appId],\n\t)\n\n\t// Helper for API calls with retry logic and SylphxError wrapping\n\tconst request = useCallback(\n\t\tasync <T>(method: string, path: string, body?: unknown): Promise<T> => {\n\t\t\tlet lastError: Error | undefined\n\n\t\t\tfor (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {\n\t\t\t\ttry {\n\t\t\t\t\tconst response = await fetch(`${platformUrl}${SDK_API_PATH}/kv${path}`, {\n\t\t\t\t\t\tmethod,\n\t\t\t\t\t\theaders,\n\t\t\t\t\t\tbody: body ? JSON.stringify(body) : undefined,\n\t\t\t\t\t})\n\n\t\t\t\t\tif (!response.ok) {\n\t\t\t\t\t\tconst errorBody = await response.json().catch(() => ({ error: 'Request failed' }))\n\t\t\t\t\t\tconst message =\n\t\t\t\t\t\t\ttypeof errorBody.error === 'string'\n\t\t\t\t\t\t\t\t? errorBody.error\n\t\t\t\t\t\t\t\t: (errorBody.error?.message ?? 'Request failed')\n\n\t\t\t\t\t\t// Rate limit — throw with metadata\n\t\t\t\t\t\tif (response.status === 429) {\n\t\t\t\t\t\t\tconst retryAfter = Number(response.headers.get('Retry-After')) || undefined\n\t\t\t\t\t\t\tthrow new RateLimitError(message, {\n\t\t\t\t\t\t\t\tretryAfter,\n\t\t\t\t\t\t\t\tlimit: Number(response.headers.get('X-RateLimit-Limit')) || undefined,\n\t\t\t\t\t\t\t\tremaining: Number(response.headers.get('X-RateLimit-Remaining')) || undefined,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Map HTTP status to error code\n\t\t\t\t\t\tconst codeMap: Record<number, SylphxErrorCode> = {\n\t\t\t\t\t\t\t400: 'BAD_REQUEST',\n\t\t\t\t\t\t\t401: 'UNAUTHORIZED',\n\t\t\t\t\t\t\t403: 'FORBIDDEN',\n\t\t\t\t\t\t\t404: 'NOT_FOUND',\n\t\t\t\t\t\t\t409: 'CONFLICT',\n\t\t\t\t\t\t\t422: 'UNPROCESSABLE_ENTITY',\n\t\t\t\t\t\t\t500: 'INTERNAL_SERVER_ERROR',\n\t\t\t\t\t\t\t502: 'BAD_GATEWAY',\n\t\t\t\t\t\t\t503: 'SERVICE_UNAVAILABLE',\n\t\t\t\t\t\t\t504: 'GATEWAY_TIMEOUT',\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow new SylphxError(message, {\n\t\t\t\t\t\t\tcode: codeMap[response.status] ?? 'UNKNOWN',\n\t\t\t\t\t\t\tstatus: response.status,\n\t\t\t\t\t\t\tdata: errorBody.data,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\n\t\t\t\t\treturn response.json() as Promise<T>\n\t\t\t\t} catch (error) {\n\t\t\t\t\tlastError = error instanceof Error ? error : new Error(String(error))\n\n\t\t\t\t\t// Only auto-retry on server errors (5xx) and network failures.\n\t\t\t\t\t// Never auto-retry client errors (4xx) including 429 — callers should\n\t\t\t\t\t// handle rate limits using the RateLimitError.retryAfter value.\n\t\t\t\t\tconst isServerOrNetworkError =\n\t\t\t\t\t\terror instanceof SylphxError\n\t\t\t\t\t\t\t? error.isRetryable && error.code !== 'TOO_MANY_REQUESTS'\n\t\t\t\t\t\t\t: error instanceof TypeError // fetch network errors\n\t\t\t\t\tif (!isServerOrNetworkError || attempt >= MAX_RETRIES) {\n\t\t\t\t\t\tthrow error instanceof SylphxError\n\t\t\t\t\t\t\t? error\n\t\t\t\t\t\t\t: new SylphxError(lastError.message, {\n\t\t\t\t\t\t\t\t\tcode: 'NETWORK_ERROR',\n\t\t\t\t\t\t\t\t\tcause: lastError,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t}\n\n\t\t\t\t\t// Wait with exponential backoff before retrying\n\t\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, exponentialBackoff(attempt)))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow lastError ?? new SylphxError('Request failed', { code: 'UNKNOWN' })\n\t\t},\n\t\t[platformUrl, headers],\n\t)\n\n\t// ==========================================\n\t// Implementation\n\t// ==========================================\n\n\tconst get = useCallback(\n\t\tasync <T>(key: string): Promise<{ value: T | null; ttl: number | null }> => {\n\t\t\treturn request<{ value: T | null; ttl: number | null }>('GET', `/${encodeURIComponent(key)}`)\n\t\t},\n\t\t[request],\n\t)\n\n\tconst set = useCallback(\n\t\tasync <T>(key: string, value: T, options?: KvSetOptions): Promise<boolean> => {\n\t\t\tconst result = await request<{ success: boolean }>('POST', '', {\n\t\t\t\tkey,\n\t\t\t\tvalue,\n\t\t\t\t...options,\n\t\t\t})\n\t\t\treturn result.success\n\t\t},\n\t\t[request],\n\t)\n\n\tconst del = useCallback(\n\t\tasync (key: string): Promise<number> => {\n\t\t\tconst result = await request<{ deleted: number }>('DELETE', `/${encodeURIComponent(key)}`)\n\t\t\treturn result.deleted\n\t\t},\n\t\t[request],\n\t)\n\n\tconst exists = useCallback(\n\t\tasync (key: string): Promise<boolean> => {\n\t\t\tconst result = await request<{ exists: boolean }>('GET', `/exists/${encodeURIComponent(key)}`)\n\t\t\treturn result.exists\n\t\t},\n\t\t[request],\n\t)\n\n\tconst mget = useCallback(\n\t\tasync <T>(keys: string[]): Promise<Record<string, T | null>> => {\n\t\t\tconst result = await request<{ values: Record<string, T | null> }>('POST', '/mget', { keys })\n\t\t\treturn result.values\n\t\t},\n\t\t[request],\n\t)\n\n\tconst mset = useCallback(\n\t\tasync <T>(\n\t\t\tentries: Array<{ key: string; value: T }>,\n\t\t\toptions?: Pick<KvSetOptions, 'ex' | 'px'>,\n\t\t): Promise<void> => {\n\t\t\tawait request<{ success: boolean }>('POST', '/mset', {\n\t\t\t\tentries,\n\t\t\t\t...options,\n\t\t\t})\n\t\t},\n\t\t[request],\n\t)\n\n\tconst incr = useCallback(\n\t\tasync (key: string, by = 1): Promise<number> => {\n\t\t\tconst result = await request<{ value: number }>('POST', '/incr', {\n\t\t\t\tkey,\n\t\t\t\tby,\n\t\t\t})\n\t\t\treturn result.value\n\t\t},\n\t\t[request],\n\t)\n\n\tconst expire = useCallback(\n\t\tasync (key: string, seconds: number): Promise<boolean> => {\n\t\t\tconst result = await request<{ success: boolean }>('POST', '/expire', {\n\t\t\t\tkey,\n\t\t\t\tseconds,\n\t\t\t})\n\t\t\treturn result.success\n\t\t},\n\t\t[request],\n\t)\n\n\tconst ratelimit = useCallback(\n\t\tasync (key: string, options: { limit: number; window: string }): Promise<KvRateLimitResult> => {\n\t\t\treturn request<KvRateLimitResult>('POST', '/ratelimit', {\n\t\t\t\tkey,\n\t\t\t\t...options,\n\t\t\t})\n\t\t},\n\t\t[request],\n\t)\n\n\tconst hset = useCallback(\n\t\tasync <T>(key: string, fields: Record<string, T>): Promise<number> => {\n\t\t\tconst result = await request<{ created: number }>('POST', '/hset', {\n\t\t\t\tkey,\n\t\t\t\tfields,\n\t\t\t})\n\t\t\treturn result.created\n\t\t},\n\t\t[request],\n\t)\n\n\tconst hget = useCallback(\n\t\tasync <T>(key: string, field: string): Promise<T | null> => {\n\t\t\tconst result = await request<{ value: T | null }>('POST', '/hget', {\n\t\t\t\tkey,\n\t\t\t\tfield,\n\t\t\t})\n\t\t\treturn result.value\n\t\t},\n\t\t[request],\n\t)\n\n\tconst hgetall = useCallback(\n\t\tasync <T>(key: string): Promise<Record<string, T> | null> => {\n\t\t\tconst result = await request<{ fields: Record<string, T> | null }>('POST', '/hgetall', {\n\t\t\t\tkey,\n\t\t\t})\n\t\t\treturn result.fields\n\t\t},\n\t\t[request],\n\t)\n\n\tconst lpush = useCallback(\n\t\tasync <T>(key: string, ...values: T[]): Promise<number> => {\n\t\t\tconst result = await request<{ length: number }>('POST', '/lpush', {\n\t\t\t\tkey,\n\t\t\t\tvalues,\n\t\t\t})\n\t\t\treturn result.length\n\t\t},\n\t\t[request],\n\t)\n\n\tconst lrange = useCallback(\n\t\tasync <T>(key: string, start = 0, stop = -1): Promise<T[]> => {\n\t\t\tconst result = await request<{ values: T[] }>('POST', '/lrange', {\n\t\t\t\tkey,\n\t\t\t\tstart,\n\t\t\t\tstop,\n\t\t\t})\n\t\t\treturn result.values\n\t\t},\n\t\t[request],\n\t)\n\n\tconst zadd = useCallback(\n\t\tasync (key: string, ...members: Array<{ score: number; member: string }>): Promise<number> => {\n\t\t\tconst result = await request<{ added: number }>('POST', '/zadd', {\n\t\t\t\tkey,\n\t\t\t\tmembers,\n\t\t\t})\n\t\t\treturn result.added\n\t\t},\n\t\t[request],\n\t)\n\n\tconst zrange = useCallback(\n\t\tasync (\n\t\t\tkey: string,\n\t\t\tstart = 0,\n\t\t\tstop = 9,\n\t\t\toptions?: { withScores?: boolean; rev?: boolean },\n\t\t): Promise<KvZMember[]> => {\n\t\t\tconst result = await request<{ members: KvZMember[] }>('POST', '/zrange', {\n\t\t\t\tkey,\n\t\t\t\tstart,\n\t\t\t\tstop,\n\t\t\t\twithScores: options?.withScores ?? false,\n\t\t\t\trev: options?.rev ?? false,\n\t\t\t})\n\t\t\treturn result.members\n\t\t},\n\t\t[request],\n\t)\n\n\treturn useMemo(\n\t\t() => ({\n\t\t\tget,\n\t\t\tset,\n\t\t\tdel,\n\t\t\texists,\n\t\t\tmget,\n\t\t\tmset,\n\t\t\tincr,\n\t\t\texpire,\n\t\t\tratelimit,\n\t\t\thset,\n\t\t\thget,\n\t\t\thgetall,\n\t\t\tlpush,\n\t\t\tlrange,\n\t\t\tzadd,\n\t\t\tzrange,\n\t\t}),\n\t\t[\n\t\t\tget,\n\t\t\tset,\n\t\t\tdel,\n\t\t\texists,\n\t\t\tmget,\n\t\t\tmset,\n\t\t\tincr,\n\t\t\texpire,\n\t\t\tratelimit,\n\t\t\thset,\n\t\t\thget,\n\t\t\thgetall,\n\t\t\tlpush,\n\t\t\tlrange,\n\t\t\tzadd,\n\t\t\tzrange,\n\t\t],\n\t)\n}\n","/**\n * useSearch — Debounced search hook\n *\n * Client-side hook for real-time search with debouncing, loading states,\n * and optional click tracking.\n *\n * @example\n * ```tsx\n * import { useSearch } from '@sylphx/sdk/react'\n *\n * function SearchBox({ config }) {\n *   const { results, loading, error, setQuery } = useSearch(config, {\n *     namespace: 'products',\n *     searchType: 'hybrid',\n *     debounceMs: 250,\n *   })\n *\n *   return (\n *     <div>\n *       <input onChange={e => setQuery(e.target.value)} />\n *       {loading && <Spinner />}\n *       {results.map(r => <SearchResult key={r.id} item={r} />)}\n *     </div>\n *   )\n * }\n * ```\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport type { SylphxConfig } from '../../config'\nimport type { SearchInput, SearchResponse, SearchResultItem } from '../../search'\nimport { search } from '../../search'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface UseSearchOptions extends Omit<SearchInput, 'query'> {\n\t/** Debounce delay in milliseconds (default: 300) */\n\tdebounceMs?: number\n\t/** Minimum query length before searching (default: 2) */\n\tminLength?: number\n\t/** Automatically track clicks on results (default: true) */\n\tautoTrackClicks?: boolean\n\t/** Initial query (optional) */\n\tinitialQuery?: string\n}\n\nexport interface UseSearchReturn {\n\t/** Current search results */\n\tresults: SearchResultItem[]\n\t/** Total number of matching results */\n\ttotal: number\n\t/** True while a search request is in flight */\n\tloading: boolean\n\t/** Error if the last search failed */\n\terror: Error | null\n\t/** Current query string */\n\tquery: string\n\t/** Set the search query (triggers debounced search) */\n\tsetQuery: (query: string) => void\n\t/** Clear the search (resets query and results) */\n\tclear: () => void\n\t/** Manually trigger a search with the current query */\n\trefetch: () => void\n\t/** Track a click on a result (updates click-through data) */\n\ttrackResultClick: (documentId: string, resultRank: number) => void\n\t/** Full API response (including facets, metadata) */\n\tresponse: SearchResponse | null\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * useSearch — Debounced real-time search hook.\n *\n * @param config  SDK config (appId for client-side, secretKey for server-rendered)\n * @param options Search options and configuration\n */\nexport function useSearch(config: SylphxConfig, options: UseSearchOptions = {}): UseSearchReturn {\n\tconst {\n\t\tdebounceMs = 300,\n\t\tminLength = 2,\n\t\tautoTrackClicks = true,\n\t\tinitialQuery = '',\n\t\t...searchOptions\n\t} = options\n\n\tconst [query, setQueryState] = useState(initialQuery)\n\tconst [results, setResults] = useState<SearchResultItem[]>([])\n\tconst [total, setTotal] = useState(0)\n\tconst [loading, setLoading] = useState(false)\n\tconst [error, setError] = useState<Error | null>(null)\n\tconst [response, setResponse] = useState<SearchResponse | null>(null)\n\n\tconst debounceTimer = useRef<ReturnType<typeof setTimeout> | null>(null)\n\tconst abortController = useRef<AbortController | null>(null)\n\n\t// Capture searchOptions as a stable ref so we don't need JSON.stringify as dep\n\tconst searchOptionsRef = useRef(searchOptions)\n\tuseEffect(() => {\n\t\tsearchOptionsRef.current = searchOptions\n\t})\n\n\tconst executeSearch = useCallback(\n\t\tasync (q: string) => {\n\t\t\tif (!q || q.length < minLength) {\n\t\t\t\tsetResults([])\n\t\t\t\tsetTotal(0)\n\t\t\t\tsetResponse(null)\n\t\t\t\tsetLoading(false)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Cancel previous in-flight request\n\t\t\tabortController.current?.abort()\n\t\t\tabortController.current = new AbortController()\n\n\t\t\tsetLoading(true)\n\t\t\tsetError(null)\n\n\t\t\ttry {\n\t\t\t\tconst res = await search(config, {\n\t\t\t\t\t...searchOptionsRef.current,\n\t\t\t\t\tquery: q,\n\t\t\t\t})\n\n\t\t\t\tsetResults(res.results)\n\t\t\t\tsetTotal(res.total)\n\t\t\t\tsetResponse(res)\n\t\t\t} catch (err) {\n\t\t\t\t// Ignore abort errors\n\t\t\t\tif (err instanceof Error && err.name === 'AbortError') return\n\t\t\t\tsetError(err instanceof Error ? err : new Error(String(err)))\n\t\t\t\tsetResults([])\n\t\t\t\tsetTotal(0)\n\t\t\t} finally {\n\t\t\t\tsetLoading(false)\n\t\t\t}\n\t\t},\n\t\t[config, minLength],\n\t)\n\n\t// Set query with debouncing\n\tconst setQuery = useCallback(\n\t\t(q: string) => {\n\t\t\tsetQueryState(q)\n\n\t\t\tif (debounceTimer.current) {\n\t\t\t\tclearTimeout(debounceTimer.current)\n\t\t\t}\n\n\t\t\tif (!q || q.length < minLength) {\n\t\t\t\tsetResults([])\n\t\t\t\tsetTotal(0)\n\t\t\t\tsetResponse(null)\n\t\t\t\tsetLoading(false)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tsetLoading(true) // Show spinner immediately\n\n\t\t\tdebounceTimer.current = setTimeout(() => {\n\t\t\t\texecuteSearch(q)\n\t\t\t}, debounceMs)\n\t\t},\n\t\t[executeSearch, debounceMs, minLength],\n\t)\n\n\tconst clear = useCallback(() => {\n\t\tif (debounceTimer.current) clearTimeout(debounceTimer.current)\n\t\tabortController.current?.abort()\n\t\tsetQueryState('')\n\t\tsetResults([])\n\t\tsetTotal(0)\n\t\tsetResponse(null)\n\t\tsetLoading(false)\n\t\tsetError(null)\n\t}, [])\n\n\tconst refetch = useCallback(() => {\n\t\texecuteSearch(query)\n\t}, [executeSearch, query])\n\n\tconst trackResultClick = useCallback((_documentId: string, _resultRank: number) => {\n\t\t// Click tracking requires a queryId from the search response.\n\t\t// Implement manually using trackClick() from '@sylphx/sdk' with\n\t\t// response.queryId when the search API returns one.\n\t}, [])\n\n\t// Run initial search if initialQuery is provided (once on mount)\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: intentionally run only on mount\n\tuseEffect(() => {\n\t\tif (initialQuery && initialQuery.length >= minLength) {\n\t\t\texecuteSearch(initialQuery)\n\t\t}\n\t}, []) // Empty deps = mount only\n\n\t// Cleanup on unmount\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tif (debounceTimer.current) clearTimeout(debounceTimer.current)\n\t\t\tabortController.current?.abort()\n\t\t}\n\t}, [])\n\n\treturn {\n\t\tresults,\n\t\ttotal,\n\t\tloading,\n\t\terror,\n\t\tquery,\n\t\tsetQuery,\n\t\tclear,\n\t\trefetch,\n\t\ttrackResultClick,\n\t\tresponse,\n\t}\n}\n","/**\n * Search SDK\n *\n * State-of-the-art search with full-text, semantic, and hybrid modes.\n * Powered by PostgreSQL tsvector + pgvector.\n *\n * @example\n * ```typescript\n * import { createConfig, indexDocument, search, batchIndex } from '@sylphx/sdk'\n *\n * const config = createConfig({\n *   secretKey: createServerClient(process.env.SYLPHX_SECRET_URL!).secretKey!,\n * })\n *\n * // Index a document\n * await indexDocument(config, {\n *   content: 'How to reset your password...',\n *   title: 'Password Reset Guide',\n *   namespace: 'help-articles',\n *   category: 'account',\n *   tags: ['password', 'security'],\n * })\n *\n * // Search (hybrid mode by default)\n * const results = await search(config, {\n *   query: 'forgot my login credentials',\n *   namespace: 'help-articles',\n *   searchType: 'hybrid',\n *   highlight: true,\n * })\n *\n * results.results.forEach(r => console.log(r.title, r.score, r.highlight))\n * ```\n */\n\nimport { callApi, type SylphxConfig } from './config'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface IndexDocumentInput {\n\t/** Document title (weighted higher in search) */\n\ttitle?: string\n\t/** Document content to index */\n\tcontent: string\n\t/** Namespace for data isolation (e.g., 'products', 'articles') */\n\tnamespace?: string\n\t/** External document ID (your system's ID) */\n\texternalId?: string\n\t/** URL or path */\n\turl?: string\n\t/** Searchable metadata */\n\tmetadata?: Record<string, unknown>\n\t/** Category facet for filtering */\n\tcategory?: string\n\t/** Type facet for filtering */\n\ttype?: string\n\t/** Tags facet for filtering */\n\ttags?: string[]\n\t/** Language for full-text search (default: english) */\n\tlanguage?: string\n\t/** Skip embedding generation (for keyword-only search) */\n\tskipEmbedding?: boolean\n\t/** Embedding model to use */\n\tembeddingModel?: string\n}\n\nexport interface IndexDocumentResult {\n\t/** Generated document ID */\n\tid: string\n\t/** External ID if provided */\n\texternalId: string | null\n\t/** Namespace */\n\tnamespace: string\n}\n\nexport interface BatchIndexInput {\n\t/** Documents to index (max 100) */\n\tdocuments: Array<{\n\t\ttitle?: string\n\t\tcontent: string\n\t\texternalId?: string\n\t\turl?: string\n\t\tmetadata?: Record<string, unknown>\n\t\tcategory?: string\n\t\ttype?: string\n\t\ttags?: string[]\n\t}>\n\t/** Namespace for all documents */\n\tnamespace?: string\n\t/** Language for full-text search */\n\tlanguage?: string\n\t/** Skip embedding generation */\n\tskipEmbedding?: boolean\n\t/** Embedding model to use */\n\tembeddingModel?: string\n}\n\nexport interface BatchIndexResult {\n\t/** Number of documents indexed */\n\tindexed: number\n\t/** Generated document IDs */\n\tids: string[]\n}\n\nexport type SearchType = 'keyword' | 'semantic' | 'hybrid'\n\nexport interface SearchInput {\n\t/** Search query text */\n\tquery: string\n\t/** Namespace to search within */\n\tnamespace?: string\n\t/** Search type: keyword, semantic, or hybrid (default) */\n\tsearchType?: SearchType\n\t/** Maximum results to return (default: 10, max: 100) */\n\tlimit?: number\n\t/** Offset for pagination */\n\toffset?: number\n\t/** Minimum similarity threshold (0-1) for semantic search */\n\tminSimilarity?: number\n\t/** Enable typo tolerance (default: true) */\n\ttypoTolerance?: boolean\n\t/** Language for full-text search */\n\tlanguage?: string\n\t/** Facet filters */\n\tfilters?: {\n\t\tcategory?: string\n\t\ttype?: string\n\t\ttags?: string[]\n\t\tmetadata?: Record<string, unknown>\n\t}\n\t/** Include highlighted snippets (default: true) */\n\thighlight?: boolean\n\t/** Embedding model for semantic search */\n\tembeddingModel?: string\n\t/** Track this query for analytics (default: true) */\n\ttrackQuery?: boolean\n\t/** Session ID for analytics */\n\tsessionId?: string\n\t/** User ID for analytics */\n\tuserId?: string\n}\n\nexport interface SearchResultItem {\n\t/** Document ID */\n\tid: string\n\t/** External ID if set */\n\texternalId: string | null\n\t/** Document title */\n\ttitle: string | null\n\t/** Document content */\n\tcontent: string\n\t/** Document URL */\n\turl: string | null\n\t/** Document metadata */\n\tmetadata: Record<string, unknown> | null\n\t/** Category facet */\n\tcategory: string | null\n\t/** Type facet */\n\ttype: string | null\n\t/** Tags facet */\n\ttags: string[] | null\n\t/** Combined score */\n\tscore: number\n\t/** Keyword search score (if hybrid) */\n\tkeywordScore?: number\n\t/** Semantic search score (if hybrid) */\n\tsemanticScore?: number\n\t/** Highlighted snippet (if enabled) */\n\thighlight?: string\n}\n\nexport interface SearchResponse {\n\t/** Search results */\n\tresults: SearchResultItem[]\n\t/** Total results found */\n\ttotal: number\n\t/** Original query */\n\tquery: string\n\t/** Search type used */\n\tsearchType: SearchType\n\t/** Query processing time in ms */\n\tlatencyMs: number\n}\n\nexport interface GetFacetsInput {\n\t/** Namespace to get facets from */\n\tnamespace?: string\n\t/** Facets to retrieve */\n\tfacets?: Array<'category' | 'type' | 'tags'>\n\t/** Filter facets by category or type */\n\tfilters?: {\n\t\tcategory?: string\n\t\ttype?: string\n\t}\n}\n\nexport interface FacetsResponse {\n\tfacets: {\n\t\tcategory?: Array<{ value: string; count: number }>\n\t\ttype?: Array<{ value: string; count: number }>\n\t\ttags?: Array<{ value: string; count: number }>\n\t}\n}\n\nexport interface DeleteDocumentInput {\n\t/** Document ID to delete */\n\tid?: string\n\t/** Or delete by external ID */\n\texternalId?: string\n\t/** Namespace (required if using externalId) */\n\tnamespace?: string\n}\n\nexport interface UpsertDocumentInput extends IndexDocumentInput {\n\t/** External ID is required for upsert */\n\texternalId: string\n}\n\nexport interface UpsertDocumentResult extends IndexDocumentResult {\n\t/** Whether the document was created (true) or updated (false) */\n\tcreated: boolean\n}\n\nexport interface SearchStatsResult {\n\t/** Total documents indexed */\n\ttotalDocuments: number\n\t/** Documents with embeddings */\n\tdocumentsWithEmbedding: number\n\t/** Documents by namespace */\n\tbyNamespace: Array<{ namespace: string; count: number }>\n}\n\nexport interface TrackClickInput {\n\t/** Search query ID */\n\tqueryId: string\n\t/** Clicked document ID */\n\tdocumentId: string\n\t/** Position in results (1-indexed) */\n\tposition: number\n}\n\n// ============================================================================\n// Functions\n// ============================================================================\n\n/**\n * Index a document for search.\n *\n * Automatically generates tsvector for full-text search and\n * optional embedding for semantic search.\n *\n * @param config - SDK configuration\n * @param input - Document to index\n * @returns Indexed document info\n *\n * @example\n * ```typescript\n * const result = await indexDocument(config, {\n *   title: 'Getting Started Guide',\n *   content: 'Welcome to our platform...',\n *   namespace: 'docs',\n *   category: 'tutorials',\n *   tags: ['beginner', 'setup'],\n * })\n * ```\n */\nexport async function indexDocument(\n\tconfig: SylphxConfig,\n\tinput: IndexDocumentInput,\n): Promise<IndexDocumentResult> {\n\treturn callApi<IndexDocumentResult>(config, '/search/index', {\n\t\tmethod: 'POST',\n\t\tbody: {\n\t\t\ttitle: input.title,\n\t\t\tcontent: input.content,\n\t\t\tnamespace: input.namespace ?? 'default',\n\t\t\texternalId: input.externalId,\n\t\t\turl: input.url,\n\t\t\tmetadata: input.metadata,\n\t\t\tcategory: input.category,\n\t\t\ttype: input.type,\n\t\t\ttags: input.tags,\n\t\t\tlanguage: input.language ?? 'english',\n\t\t\tskipEmbedding: input.skipEmbedding ?? false,\n\t\t\tembeddingModel: input.embeddingModel ?? 'openai/text-embedding-3-small',\n\t\t},\n\t})\n}\n\n/**\n * Index multiple documents in a single batch.\n *\n * More efficient than multiple indexDocument calls.\n * Max 100 documents per batch.\n *\n * @param config - SDK configuration\n * @param input - Documents to index\n * @returns Batch index result\n *\n * @example\n * ```typescript\n * const result = await batchIndex(config, {\n *   namespace: 'products',\n *   documents: products.map(p => ({\n *     title: p.name,\n *     content: p.description,\n *     externalId: p.id,\n *     category: p.category,\n *   }))\n * })\n * console.log(`Indexed ${result.indexed} products`)\n * ```\n */\nexport async function batchIndex(\n\tconfig: SylphxConfig,\n\tinput: BatchIndexInput,\n): Promise<BatchIndexResult> {\n\treturn callApi<BatchIndexResult>(config, '/search/batchIndex', {\n\t\tmethod: 'POST',\n\t\tbody: {\n\t\t\tdocuments: input.documents,\n\t\t\tnamespace: input.namespace ?? 'default',\n\t\t\tlanguage: input.language ?? 'english',\n\t\t\tskipEmbedding: input.skipEmbedding ?? false,\n\t\t\tembeddingModel: input.embeddingModel ?? 'openai/text-embedding-3-small',\n\t\t},\n\t})\n}\n\n/**\n * Search documents.\n *\n * Supports three search modes:\n * - `keyword`: Full-text search with typo tolerance\n * - `semantic`: AI-powered vector search\n * - `hybrid`: Combined ranking (default, best results)\n *\n * @param config - SDK configuration\n * @param input - Search query and options\n * @returns Search results with scores\n *\n * @example\n * ```typescript\n * // Hybrid search (recommended)\n * const results = await search(config, {\n *   query: 'how to change email address',\n *   namespace: 'help',\n *   searchType: 'hybrid',\n *   highlight: true,\n * })\n *\n * results.results.forEach(r => {\n *   console.log(`[${r.score.toFixed(3)}] ${r.title}`)\n *   console.log(r.highlight)\n * })\n * ```\n */\nexport async function search(config: SylphxConfig, input: SearchInput): Promise<SearchResponse> {\n\treturn callApi<SearchResponse>(config, '/search/search', {\n\t\tmethod: 'POST',\n\t\tbody: {\n\t\t\tquery: input.query,\n\t\t\tnamespace: input.namespace ?? 'default',\n\t\t\tsearchType: input.searchType ?? 'hybrid',\n\t\t\tlimit: input.limit ?? 10,\n\t\t\toffset: input.offset ?? 0,\n\t\t\tminSimilarity: input.minSimilarity,\n\t\t\ttypoTolerance: input.typoTolerance ?? true,\n\t\t\tlanguage: input.language ?? 'english',\n\t\t\tfilters: input.filters,\n\t\t\thighlight: input.highlight ?? true,\n\t\t\tembeddingModel: input.embeddingModel ?? 'openai/text-embedding-3-small',\n\t\t\ttrackQuery: input.trackQuery ?? true,\n\t\t\tsessionId: input.sessionId,\n\t\t\tuserId: input.userId,\n\t\t},\n\t})\n}\n\n/**\n * Get facet counts for filtering.\n *\n * Returns counts of documents by category, type, and tags.\n *\n * @param config - SDK configuration\n * @param input - Facet options\n * @returns Facet counts\n *\n * @example\n * ```typescript\n * const facets = await getFacets(config, {\n *   namespace: 'products',\n *   facets: ['category', 'type'],\n * })\n *\n * facets.facets.category?.forEach(f => {\n *   console.log(`${f.value}: ${f.count} products`)\n * })\n * ```\n */\nexport async function getFacets(\n\tconfig: SylphxConfig,\n\tinput: GetFacetsInput = {},\n): Promise<FacetsResponse> {\n\treturn callApi<FacetsResponse>(config, '/search/getFacets', {\n\t\tmethod: 'POST',\n\t\tbody: {\n\t\t\tnamespace: input.namespace ?? 'default',\n\t\t\tfacets: input.facets ?? ['category', 'type'],\n\t\t\tfilters: input.filters,\n\t\t},\n\t})\n}\n\n/**\n * Delete a document from the search index.\n *\n * @param config - SDK configuration\n * @param input - Document ID or external ID\n * @returns Deletion result\n *\n * @example\n * ```typescript\n * // Delete by internal ID\n * await deleteDocument(config, { id: 'doc-uuid-123' })\n *\n * // Delete by external ID\n * await deleteDocument(config, {\n *   externalId: 'product-456',\n *   namespace: 'products'\n * })\n * ```\n */\nexport async function deleteDocument(\n\tconfig: SylphxConfig,\n\tinput: DeleteDocumentInput,\n): Promise<{ deleted: number }> {\n\treturn callApi<{ deleted: number }>(config, '/search/delete', {\n\t\tmethod: 'POST',\n\t\tbody: {\n\t\t\tid: input.id,\n\t\t\texternalId: input.externalId,\n\t\t\tnamespace: input.namespace ?? 'default',\n\t\t},\n\t})\n}\n\n/**\n * Upsert a document (insert or update by externalId).\n *\n * If a document with the same externalId exists, it will be replaced.\n * Otherwise, a new document is created.\n *\n * @param config - SDK configuration\n * @param input - Document to upsert (externalId required)\n * @returns Upsert result\n *\n * @example\n * ```typescript\n * const result = await upsertDocument(config, {\n *   externalId: 'product-123',\n *   title: 'Updated Product Name',\n *   content: 'New description...',\n *   namespace: 'products',\n * })\n * console.log(result.created ? 'Created' : 'Updated')\n * ```\n */\nexport async function upsertDocument(\n\tconfig: SylphxConfig,\n\tinput: UpsertDocumentInput,\n): Promise<UpsertDocumentResult> {\n\treturn callApi<UpsertDocumentResult>(config, '/search/upsert', {\n\t\tmethod: 'POST',\n\t\tbody: {\n\t\t\ttitle: input.title,\n\t\t\tcontent: input.content,\n\t\t\tnamespace: input.namespace ?? 'default',\n\t\t\texternalId: input.externalId,\n\t\t\turl: input.url,\n\t\t\tmetadata: input.metadata,\n\t\t\tcategory: input.category,\n\t\t\ttype: input.type,\n\t\t\ttags: input.tags,\n\t\t\tlanguage: input.language ?? 'english',\n\t\t\tskipEmbedding: input.skipEmbedding ?? false,\n\t\t\tembeddingModel: input.embeddingModel ?? 'openai/text-embedding-3-small',\n\t\t},\n\t})\n}\n\n/**\n * Get search index statistics.\n *\n * @param config - SDK configuration\n * @param namespace - Optional namespace filter\n * @returns Index statistics\n *\n * @example\n * ```typescript\n * const stats = await getSearchStats(config)\n * console.log(`Total docs: ${stats.totalDocuments}`)\n * console.log(`With embeddings: ${stats.documentsWithEmbedding}`)\n * ```\n */\nexport async function getSearchStats(\n\tconfig: SylphxConfig,\n\tnamespace?: string,\n): Promise<SearchStatsResult> {\n\treturn callApi<SearchStatsResult>(config, '/search/getStats', {\n\t\tmethod: 'POST',\n\t\tbody: { namespace },\n\t})\n}\n\n/**\n * Track a click on a search result.\n *\n * Use this to improve search quality over time.\n *\n * @param config - SDK configuration\n * @param input - Click information\n * @returns Success status\n *\n * @example\n * ```typescript\n * await trackClick(config, {\n *   queryId: searchResponse.queryId,\n *   documentId: clickedResult.id,\n *   position: 3,\n * })\n * ```\n */\nexport async function trackClick(\n\tconfig: SylphxConfig,\n\tinput: TrackClickInput,\n): Promise<{ success: boolean }> {\n\treturn callApi<{ success: boolean }>(config, '/search/trackClick', {\n\t\tmethod: 'POST',\n\t\tbody: input,\n\t})\n}\n","/**\n * WebAnalytics React Component\n *\n * Drop-in component that auto-tracks page views. Works with Next.js App Router,\n * Pages Router, and any React SPA. Add to your root layout once.\n *\n * @example\n * ```tsx\n * // app/layout.tsx\n * import { WebAnalytics } from '@sylphx/platform-sdk/react'\n *\n * export default function Layout({ children }) {\n *   return (\n *     <html>\n *       <body>\n *         {children}\n *         <WebAnalytics appKey={process.env.NEXT_PUBLIC_SYLPHX_APP_KEY} />\n *       </body>\n *     </html>\n *   )\n * }\n * ```\n */\n\n'use client'\n\nimport { useEffect } from 'react'\nimport { getWebAnalyticsTracker, type WebAnalyticsOptions } from '../../lib/analytics/web-analytics'\n\nexport interface WebAnalyticsProps {\n\t/** App key (NEXT_PUBLIC_SYLPHX_APP_KEY) */\n\tappKey?: string\n\t/** API endpoint base URL (default: empty = same-origin) */\n\tendpoint?: string\n\t/** Auto-track page views (default: true) */\n\ttrackPageViews?: boolean\n\t/** SPA hash-routing mode (default: false) */\n\thashMode?: boolean\n\t/** Debug logging (default: false in prod) */\n\tdebug?: boolean\n}\n\n/**\n * WebAnalytics Component\n *\n * Auto-tracks page views, handles Next.js soft navigation,\n * and integrates with the Sylphx Analytics backend.\n */\nexport function WebAnalytics({\n\tappKey,\n\tendpoint = '',\n\ttrackPageViews = true,\n\thashMode = false,\n\tdebug = false,\n}: WebAnalyticsProps) {\n\tuseEffect(() => {\n\t\tif (!appKey) {\n\t\t\tif (debug) {\n\t\t\t\tconsole.warn('[WebAnalytics] No appKey provided, tracking disabled')\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tconst options: WebAnalyticsOptions = {\n\t\t\tappKey,\n\t\t\tendpoint,\n\t\t\ttrackPageViews,\n\t\t\thashMode,\n\t\t\tdebug,\n\t\t}\n\n\t\tconst tracker = getWebAnalyticsTracker()\n\t\ttracker.init(options)\n\n\t\t// Cleanup on unmount (rare in layout components)\n\t\treturn () => {\n\t\t\t// Don't destroy — it would break navigations. Tracker is a singleton.\n\t\t}\n\t}, [appKey, endpoint, trackPageViews, hashMode, debug])\n\n\t// Render nothing\n\treturn null\n}\n\n// ============================================\n// useWebAnalytics hook\n// ============================================\n\nexport interface UseWebAnalyticsReturn {\n\t/** Manually track a page view */\n\ttrackPageView: (path?: string) => void\n\t/** Identify a user */\n\tidentify: (userId: string, traits?: Record<string, unknown>) => void\n}\n\n/**\n * Hook for manual web analytics tracking\n *\n * @example\n * ```tsx\n * function CheckoutSuccess() {\n *   const { trackPageView, identify } = useWebAnalytics()\n *\n *   useEffect(() => {\n *     identify(user.id, { plan: 'pro' })\n *   }, [user.id])\n * }\n * ```\n */\nexport function useWebAnalytics(): UseWebAnalyticsReturn {\n\tconst tracker = getWebAnalyticsTracker()\n\n\treturn {\n\t\ttrackPageView: (path?: string) => tracker.trackPageView(path),\n\t\tidentify: (userId: string, traits?: Record<string, unknown>) =>\n\t\t\ttracker.identify(userId, traits),\n\t}\n}\n","/**\n * Web Analytics Tracker\n *\n * Lightweight page-view analytics tracker for Sylphx Platform SDK.\n * Automatically tracks page views, bounce rate, and session data.\n *\n * @example\n * ```typescript\n * import { SDK_API_PATH } from \"../../constants\";\nimport { WebAnalyticsTracker } from '@sylphx/platform-sdk/web-analytics'\n *\n * const tracker = new WebAnalyticsTracker()\n * tracker.init({\n *   appKey: 'app_prod_xxx',\n *   endpoint: 'https://your-app.com',\n * })\n * ```\n */\n\nimport { SDK_API_PATH } from '../../constants'\n\n// ============================================\n// Types\n// ============================================\n\nexport interface WebAnalyticsOptions {\n\t/** App key for authentication */\n\tappKey: string\n\t/** Base endpoint URL (without trailing slash) */\n\tendpoint: string\n\t/** Auto-track page views (default: true) */\n\ttrackPageViews?: boolean\n\t/** Track bounce rate (sessions with only 1 page view) (default: true) */\n\ttrackBounce?: boolean\n\t/** SPA hash routing mode (tracks hash changes) (default: false) */\n\thashMode?: boolean\n\t/** Debug logging (default: false) */\n\tdebug?: boolean\n}\n\nexport interface PageViewPayload {\n\t/** URL path (e.g. /about) */\n\tpath: string\n\t/** Document referrer */\n\treferrer: string\n\t/** Navigator user agent */\n\tuserAgent: string\n\t/** Screen width in pixels */\n\tscreenWidth: number\n\t/** Session ID (UUID stored in sessionStorage) */\n\tsessionId: string\n\t/** Unix timestamp (ms) */\n\ttimestamp: number\n}\n\nexport interface IdentifyPayload {\n\t/** User ID */\n\tuserId: string\n\t/** User traits/properties */\n\ttraits?: Record<string, unknown>\n\t/** Session ID */\n\tsessionId: string\n}\n\n// ============================================\n// Utilities\n// ============================================\n\nfunction generateSessionId(): string {\n\tif (typeof crypto !== 'undefined' && crypto.randomUUID) {\n\t\treturn crypto.randomUUID()\n\t}\n\t// Fallback for older environments\n\treturn 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n\t\tconst r = (Math.random() * 16) | 0\n\t\tconst v = c === 'x' ? r : (r & 0x3) | 0x8\n\t\treturn v.toString(16)\n\t})\n}\n\nfunction getOrCreateSessionId(): string {\n\tif (typeof sessionStorage === 'undefined') return generateSessionId()\n\tconst key = '_sylphx_sid'\n\tlet id = sessionStorage.getItem(key)\n\tif (!id) {\n\t\tid = generateSessionId()\n\t\tsessionStorage.setItem(key, id)\n\t}\n\treturn id\n}\n\nfunction getCurrentPath(hashMode: boolean): string {\n\tif (typeof window === 'undefined' || !window.location) return '/'\n\tif (hashMode) {\n\t\treturn window.location.hash.replace(/^#/, '') || '/'\n\t}\n\treturn window.location.pathname + window.location.search\n}\n\n// ============================================\n// WebAnalyticsTracker\n// ============================================\n\nexport class WebAnalyticsTracker {\n\tprivate options: Required<WebAnalyticsOptions> | null = null\n\tprivate initialized = false\n\tprivate lastPath: string | null = null\n\t// biome-ignore lint/correctness/noUnusedPrivateClassMembers: used in trackPageView\n\tprivate pageViewCount = 0\n\tprivate cleanupFns: Array<() => void> = []\n\n\t/**\n\t * Initialize the tracker and start auto-tracking page views\n\t */\n\tinit(options: WebAnalyticsOptions): void {\n\t\tif (typeof window === 'undefined') return\n\t\tif (this.initialized) return\n\n\t\tthis.options = {\n\t\t\ttrackPageViews: true,\n\t\t\ttrackBounce: true,\n\t\t\thashMode: false,\n\t\t\tdebug: false,\n\t\t\t...options,\n\t\t}\n\n\t\tthis.initialized = true\n\n\t\tif (this.options.trackPageViews) {\n\t\t\t// Track current page view\n\t\t\tthis.trackPageView()\n\n\t\t\t// Track Next.js router events (soft navigation)\n\t\t\tthis._hookNextRouter()\n\n\t\t\t// Track hash changes (for hash-mode SPAs)\n\t\t\tif (this.options.hashMode) {\n\t\t\t\tconst onHashChange = () => this.trackPageView()\n\t\t\t\twindow.addEventListener('hashchange', onHashChange)\n\t\t\t\tthis.cleanupFns.push(() => window.removeEventListener('hashchange', onHashChange))\n\t\t\t}\n\n\t\t\t// Track History API (pushState / replaceState)\n\t\t\tthis._hookHistoryApi()\n\t\t}\n\n\t\tif (this.options.debug) {\n\t\t}\n\t}\n\n\t/**\n\t * Manually track a page view\n\t */\n\ttrackPageView(path?: string): void {\n\t\tif (!this.options) return\n\t\tif (typeof window === 'undefined') return\n\n\t\tconst currentPath = path ?? getCurrentPath(this.options.hashMode)\n\n\t\t// Avoid duplicate tracking on same path\n\t\tif (currentPath === this.lastPath) return\n\t\tthis.lastPath = currentPath\n\t\tthis.pageViewCount++\n\n\t\tconst payload: PageViewPayload = {\n\t\t\tpath: currentPath,\n\t\t\treferrer: typeof document !== 'undefined' ? document.referrer || '' : '',\n\t\t\tuserAgent: typeof navigator !== 'undefined' ? navigator.userAgent : '',\n\t\t\tscreenWidth: window.screen?.width,\n\t\t\tsessionId: getOrCreateSessionId(),\n\t\t\ttimestamp: Date.now(),\n\t\t}\n\n\t\tif (this.options.debug) {\n\t\t}\n\n\t\tthis._send(`${SDK_API_PATH}/analytics/pageview`, payload)\n\t}\n\n\t/**\n\t * Identify a user\n\t */\n\tidentify(userId: string, traits?: Record<string, unknown>): void {\n\t\tif (!this.options) return\n\t\tif (typeof window === 'undefined') return\n\n\t\tconst payload: IdentifyPayload = {\n\t\t\tuserId,\n\t\t\ttraits,\n\t\t\tsessionId: getOrCreateSessionId(),\n\t\t}\n\n\t\tif (this.options.debug) {\n\t\t}\n\n\t\tthis._send(`${SDK_API_PATH}/analytics/identify`, payload)\n\t}\n\n\t/**\n\t * Destroy the tracker and remove event listeners\n\t */\n\tdestroy(): void {\n\t\tfor (const fn of this.cleanupFns) {\n\t\t\tfn()\n\t\t}\n\t\tthis.cleanupFns = []\n\t\tthis.initialized = false\n\t\tthis.options = null\n\t\tthis.lastPath = null\n\t\tthis.pageViewCount = 0\n\t}\n\n\t// ==========================================\n\t// Private helpers\n\t// ==========================================\n\n\tprivate _send(path: string, payload: unknown): void {\n\t\tif (!this.options) return\n\n\t\tconst url = `${this.options.endpoint}${path}`\n\t\tconst data = JSON.stringify(payload)\n\n\t\ttry {\n\t\t\tif (typeof navigator !== 'undefined' && navigator.sendBeacon) {\n\t\t\t\tconst blob = new Blob([data], { type: 'application/json' })\n\t\t\t\tconst sent = navigator.sendBeacon(url, blob)\n\t\t\t\tif (!sent && this.options.debug) {\n\t\t\t\t\tconsole.warn('[WebAnalytics] sendBeacon failed, falling back to fetch')\n\t\t\t\t}\n\t\t\t\tif (sent) return\n\t\t\t}\n\n\t\t\t// Fallback: fetch with keepalive\n\t\t\tfetch(url, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t\t'x-app-key': this.options.appKey,\n\t\t\t\t},\n\t\t\t\tbody: data,\n\t\t\t\tkeepalive: true,\n\t\t\t}).catch((err) => {\n\t\t\t\tif (this.options?.debug) {\n\t\t\t\t\tconsole.error('[WebAnalytics] Failed to send:', err)\n\t\t\t\t}\n\t\t\t})\n\t\t} catch (err) {\n\t\t\tif (this.options?.debug) {\n\t\t\t\tconsole.error('[WebAnalytics] Send error:', err)\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _hookHistoryApi(): void {\n\t\tif (typeof window === 'undefined') return\n\n\t\tconst originalPush = window.history.pushState.bind(window.history)\n\t\tconst originalReplace = window.history.replaceState.bind(window.history)\n\n\t\twindow.history.pushState = (...args) => {\n\t\t\toriginalPush(...args)\n\t\t\t// Small delay to allow URL to update\n\t\t\tsetTimeout(() => this.trackPageView(), 0)\n\t\t}\n\n\t\twindow.history.replaceState = (...args) => {\n\t\t\toriginalReplace(...args)\n\t\t\t// Don't track replaceState (usually internal SPA navigation)\n\t\t}\n\n\t\tconst onPopState = () => setTimeout(() => this.trackPageView(), 0)\n\t\twindow.addEventListener('popstate', onPopState)\n\n\t\tthis.cleanupFns.push(() => {\n\t\t\twindow.history.pushState = originalPush\n\t\t\twindow.history.replaceState = originalReplace\n\t\t\twindow.removeEventListener('popstate', onPopState)\n\t\t})\n\t}\n\n\tprivate _hookNextRouter(): void {\n\t\t// Next.js App Router: listen to route-change events dispatched on document\n\t\tif (typeof document === 'undefined') return\n\n\t\t// Next.js 13+ soft navigation events\n\t\tconst onRouteAnnounced = () => setTimeout(() => this.trackPageView(), 0)\n\t\tdocument.addEventListener('nextjs:route-announced', onRouteAnnounced as EventListener)\n\n\t\tthis.cleanupFns.push(() => {\n\t\t\tdocument.removeEventListener('nextjs:route-announced', onRouteAnnounced as EventListener)\n\t\t})\n\t}\n}\n\n// ============================================\n// Singleton instance\n// ============================================\n\nlet _tracker: WebAnalyticsTracker | null = null\n\n/**\n * Get or create the global WebAnalyticsTracker singleton\n */\nexport function getWebAnalyticsTracker(): WebAnalyticsTracker {\n\tif (!_tracker) {\n\t\t_tracker = new WebAnalyticsTracker()\n\t}\n\treturn _tracker\n}\n\n/**\n * Initialize global web analytics tracker\n */\nexport function initWebAnalytics(options: WebAnalyticsOptions): void {\n\tgetWebAnalyticsTracker().init(options)\n}\n","/**\n * SpeedInsights React Component\n *\n * Auto-collects Core Web Vitals (LCP, CLS, INP, FCP, TTFB) and reports\n * them to the Sylphx analytics backend. Add to your root layout once.\n *\n * @example\n * ```tsx\n * // app/layout.tsx\n * import { SpeedInsights } from '@sylphx/platform-sdk/react'\n *\n * export default function Layout({ children }) {\n *   return (\n *     <html>\n *       <body>\n *         {children}\n *         <SpeedInsights appKey={process.env.NEXT_PUBLIC_SYLPHX_APP_KEY} />\n *       </body>\n *     </html>\n *   )\n * }\n * ```\n */\n\n'use client'\n\nimport { useEffect } from 'react'\nimport { initWebVitals, type WebVitalMetric } from '../../lib/monitoring/web-vitals'\n\nexport interface SpeedInsightsProps {\n\t/** App key (NEXT_PUBLIC_SYLPHX_APP_KEY) */\n\tappKey?: string\n\t/** API endpoint base URL (default: empty = same-origin) */\n\tendpoint?: string\n\t/** Sampling rate 0–1 (default: 1.0 = 100%) */\n\tsamplingRate?: number\n\t/** Debug logging */\n\tdebug?: boolean\n\t/** Report on every metric update, or only final values (default: false = final only) */\n\treportAllChanges?: boolean\n}\n\nexport interface VitalReportPayload {\n\tname: 'LCP' | 'CLS' | 'INP' | 'FCP' | 'TTFB'\n\tvalue: number\n\trating: 'good' | 'needs-improvement' | 'poor'\n\tdelta: number\n\tid: string\n\tnavigationType: string\n\tpath: string\n}\n\nfunction sendVital(url: string, appKey: string, payload: VitalReportPayload): void {\n\tconst data = JSON.stringify(payload)\n\tconst headers: Record<string, string> = {\n\t\t'Content-Type': 'application/json',\n\t}\n\tif (appKey) headers['x-app-key'] = appKey\n\n\ttry {\n\t\tif (typeof navigator !== 'undefined' && navigator.sendBeacon) {\n\t\t\tconst blob = new Blob([data], { type: 'application/json' })\n\t\t\tif (navigator.sendBeacon(url, blob)) return\n\t\t}\n\t\t// Fire-and-forget web-vitals beacon — the request fires during `pagehide` /\n\t\t// `visibilitychange`, so there is no meaningful caller to propagate to and\n\t\t// the document is about to unload. `keepalive: true` + silent failure is\n\t\t// the standard SDK pattern (matches Vercel Speed Insights, GA4 beacons).\n\t\tfetch(url, {\n\t\t\tmethod: 'POST',\n\t\t\theaders,\n\t\t\tbody: data,\n\t\t\tkeepalive: true,\n\t\t}).catch((err) => {\n\t\t\tif (typeof console !== 'undefined' && console.debug) {\n\t\t\t\tconsole.debug('[sylphx:speed-insights] vitals beacon failed', err)\n\t\t\t}\n\t\t})\n\t} catch (err) {\n\t\t// Browser denied Blob/sendBeacon (CSP / privacy extension). Non-fatal.\n\t\tif (typeof console !== 'undefined' && console.debug) {\n\t\t\tconsole.debug('[sylphx:speed-insights] beacon setup failed', err)\n\t\t}\n\t}\n}\n\n/**\n * SpeedInsights Component\n *\n * Automatically collects Core Web Vitals and reports them to\n * `POST /api/sdk/v1/analytics/vitals`.\n */\nexport function SpeedInsights({\n\tappKey,\n\tendpoint = '',\n\tsamplingRate = 1.0,\n\tdebug = false,\n\treportAllChanges = false,\n}: SpeedInsightsProps) {\n\tuseEffect(() => {\n\t\tif (typeof window === 'undefined') return\n\n\t\tconst reportUrl = `${endpoint}/api/sdk/v1/analytics/vitals`\n\n\t\tinitWebVitals({\n\t\t\tsamplingRate,\n\t\t\tdebug,\n\t\t\treportingMode: 'immediate',\n\t\t\tonReport: (metric: WebVitalMetric) => {\n\t\t\t\tconst path = window.location.pathname + window.location.search\n\n\t\t\t\tconst payload: VitalReportPayload = {\n\t\t\t\t\tname: metric.name as VitalReportPayload['name'],\n\t\t\t\t\tvalue: metric.value,\n\t\t\t\t\trating: metric.rating,\n\t\t\t\t\tdelta: metric.delta,\n\t\t\t\t\tid: metric.id,\n\t\t\t\t\tnavigationType: metric.navigationType,\n\t\t\t\t\tpath,\n\t\t\t\t}\n\n\t\t\t\tif (appKey) {\n\t\t\t\t\tsendVital(reportUrl, appKey, payload)\n\t\t\t\t} else if (debug) {\n\t\t\t\t\tconsole.warn('[SpeedInsights] No appKey provided, not reporting')\n\t\t\t\t}\n\t\t\t},\n\t\t})\n\t}, [appKey, endpoint, samplingRate, debug])\n\n\treturn null\n}\n"],"mappings":"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","names":["i","a","b","error","prompt","d","search","fetch","useCallback","useEffect","useState","useCallback","useContext","useEffect","useRef","useState","createContext","createContext","config","k","v","config","config","config","createContext","useContext","config","useOAuthProviders","config","p","useCallback","useContext","useEffect","useMemo","useState","useState","styles","useState","jsx","useState","useContext","useEffect","useMemo","s","useCallback","useContext","useContext","useCallback","useState","useRef","config","useEffect","organizations","o","hasPermission","m","i","useQueryClient","useCallback","useContext","useContext","config","useCallback","useQueryClient","m","Fragment","jsx","jsxs","styles","useState","useEffect","useCallback","config","p","i","CheckIcon","AlertIcon","useCallback","useEffect","useState","Fragment","jsx","jsxs","styles","useState","useEffect","useCallback","p","CheckIcon","useCallback","useEffect","useState","useEffect","useRef","useCallback","useState","jsx","jsxs","useRef","useEffect","e","Fragment","jsx","jsxs","styles","useState","useEffect","useCallback","e","useCallback","useEffect","useId","useState","Fragment","jsx","jsxs","hasPermission","styles","useId","useState","useEffect","e","useCallback","CheckIcon","useCallback","useEffect","useRef","useState","Fragment","jsx","jsxs","hasPermission","styles","useState","useEffect","useRef","useCallback","m","useCallback","useEffect","useRef","useState","Fragment","jsx","jsxs","createOrganization","styles","useState","useRef","useEffect","e","useCallback","CheckIcon","PlusIcon","SettingsIcon","useCallback","useEffect","useState","Fragment","jsx","jsxs","styles","useState","useEffect","useCallback","CheckIcon","p","XIcon","useCallback","useEffect","useId","useState","Fragment","jsx","jsxs","styles","useId","useState","useEffect","useCallback","e","CheckIcon","useState","useEffect","useCallback","useContext","useState","useContext","useState","useCallback","e","useState","jsx","jsxs","Fragment","jsx","jsxs","useState","styles","Fragment","jsx","jsxs","styles","useEffect","e","MailIcon","useEffect","useCallback","useContext","useEffect","useMemo","useState","useContext","useState","useMemo","useEffect","useCallback","e","Fragment","jsx","jsxs","styles","useEffect","e","CheckIcon","v","MailIcon","Fragment","jsx","jsxs","useState","useState","Fragment","jsx","jsxs","useState","useEffect","useRef","useState","jsx","jsxs","useState","useRef","useEffect","n","e","useCallback","useEffect","useState","Fragment","jsx","jsxs","styles","useState","useEffect","c","useCallback","e","CheckIcon","XIcon","MailIcon","useContext","Fragment","jsx","useContext","jsx","useQuery","useQueryClient","useCallback","useContext","useEffect","useState","useQueryClient","useState","initialized","useQuery","useEffect","types","useCallback","t","noopAsync","useContext","createContext","useCallback","useContext","useEffect","useMemo","useRef","useState","jsx","jsxs","createContext","useState","useCallback","s","useContext","useRef","useEffect","useMemo","config","n","i","useCallback","useState","useState","useCallback","error","useQuery","useCallback","useContext","useMemo","useState","useContext","useQuery","useCallback","useState","useMemo","a","useQuery","useQueryClient","createContext","useCallback","useContext","useEffect","useMemo","useState","jsx","value","useCallback","useContext","useState","useContext","useState","useCallback","e","useCallback","useContext","useMemo","useState","useContext","useState","useMemo","useCallback","e","useCallback","useContext","useEffect","useMemo","useRef","useState","useContext","useState","useRef","useMemo","useCallback","useEffect","useCallback","useEffect","useRef","useRef","useCallback","addBreadcrumb","useEffect","useCallback","useState","useState","useCallback","error","e","Fragment","jsx","useQuery","useCallback","useEffect","useMemo","useRef","useState","config","config","c","d","m","config","c","config","config","config","config","config","config","buildHeaders","k","v","k","i","c","r","v","storage","config","r","jsx","config","useState","storage","useMemo","useEffect","useRef","useQuery","useCallback","resolveRedirectUrl","generatePKCE","storePKCEVerifier","clearPKCEVerifier","m","history","h","s","a","p","useQuery","useQueryClient","useCallback","useContext","useMemo","config","config","config","useContext","useMemo","config","useQueryClient","useQuery","useCallback","useMutation","useQuery","useQueryClient","useCallback","useContext","useMemo","useState","config","delay","v","b","n","c","i","n","b","s","i","e","k","v","config","f","useSdkConfig","useContext","useMemo","config","useQueryClient","useState","useQuery","useMutation","useCallback","useQuery","useQueryClient","useCallback","useEffect","useRef","useState","useState","useCallback","error","useInfiniteQuery","useQuery","useQueryClient","useCallback","useQueryClient","useQuery","config","useCallback","useInfiniteQuery","useCallback","useEffect","useId","useState","Fragment","jsx","jsxs","styles","useId","useState","useEffect","e","useCallback","TrashIcon","useEffect","useState","Fragment","jsx","jsxs","search","useState","styles","useEffect","e","i","d","useEffect","useId","useState","jsx","jsxs","useId","useState","styles","useEffect","e","s","PlusIcon","CheckIcon","useEffect","useState","Fragment","jsx","jsxs","useState","styles","useEffect","DownloadIcon","p","PlusIcon","i","useEffect","useState","Fragment","jsx","jsxs","styles","useState","useEffect","p","CreditCardIcon","i","CheckIcon","useEffect","useRef","useState","Fragment","jsx","jsxs","useState","useRef","styles","useEffect","e","prompt","m","i","SendIcon","useEffect","useState","Fragment","jsx","jsxs","useState","styles","useEffect","CheckIcon","t","useEffect","useState","Fragment","jsx","jsxs","useState","styles","useEffect","t","CloseIcon","useEffect","useState","jsx","jsxs","styles","useEffect","useState","e","CloseIcon","useContext","useState","Fragment","jsx","jsxs","styles","useState","useContext","CloseIcon","Toggle","useCallback","useEffect","useRef","useState","Fragment","jsx","jsxs","useState","useCallback","t","e","useRef","styles","useEffect","_","i","CloseIcon","n","useMutation","useQuery","useQueryClient","useCallback","useEffect","useState","useQuery","useQueryClient","useCallback","useEffect","useRef","useState","useState","useCallback","error","jsx","jsxs","useState","delay","styles","useEffect","e","ClockIcon","useQueryClient","useQuery","useMutation","useCallback","job","i","useEffect","useRef","useState","Fragment","jsx","jsxs","styles","useState","useRef","m","useEffect","e","value","ChevronIcon","useEffect","useState","jsx","jsxs","styles","useState","useEffect","e","useEffect","useState","jsx","jsxs","styles","useState","useEffect","useEffect","useId","useState","Fragment","jsx","jsxs","useId","useState","styles","useEffect","e","CheckIcon","PlusIcon","useEffect","useState","jsx","jsxs","useState","styles","useEffect","s","e","n","BellOffIcon","d","CheckIcon","TrashIcon","useEffect","useId","useState","Fragment","jsx","jsxs","styles","useId","useState","useEffect","CheckIcon","CopyIcon","RefreshIcon","TwitterIcon","LinkedInIcon","useMutation","useQuery","useQueryClient","useCallback","useEffect","useId","useState","Fragment","jsx","jsxs","useQueryClient","styles","useId","useState","useEffect","useQuery","s","h","useMutation","useCallback","e","ShieldIcon","useQuery","useQueryClient","useEffect","useState","Fragment","jsx","jsxs","useQueryClient","styles","useState","useEffect","useQuery","p","useEffect","useId","useState","Fragment","jsx","jsxs","styles","useId","useState","useEffect","e","useCallback","useEffect","useId","useRef","useState","Fragment","jsx","jsxs","styles","useId","useState","useRef","useEffect","useCallback","e","CameraIcon","CloseIcon","useEffect","useId","useState","jsx","jsxs","useId","useState","styles","useEffect","e","PlusIcon","i","sanitizeUrl","c","sanitizeUrl","sanitizeUrl","console","config","b","c","e","config","sanitizeUrl","e","originalConsole","t","n","e","i","s","o","r","c","a","d","f","u","l","m","p","useCallback","useEffect","useRef","useState","jsx","useRef","useEffect","useState","useCallback","Component","useCallback","useEffect","useRef","useState","config","useState","useRef","useEffect","useCallback","metrics","useCallback","useEffect","useRef","useRef","useEffect","createDefaultUploadHandler","useCallback","addBreadcrumb","i","v","i","config","variant","v","config","e","v","n","delay","useCallback","useContext","useEffect","useMemo","useRef","useState","createContext","useCallback","useContext","useEffect","useMemo","useRef","useState","jsx","createContext","config","useState","useRef","useCallback","v","useEffect","useMemo","useFeatureFlags","useContext","DEFAULT_POLL_INTERVAL_MS","useContext","useState","useRef","useMemo","useCallback","useEffect","s","config","config","f","b","c","token","a","g","e","t","n","o","apiKey","r","s","p","d","config","q","delay","b","storage","c","r","v","trackerInstance","createContext","useCallback","useContext","useEffect","useMemo","useRef","Fragment","jsx","createContext","config","useRef","useEffect","useMemo","useContext","useCallback","useCallback","useEffect","useMemo","useRef","createContext","useContext","jsx","useRef","useMemo","useEffect","useCallback","timingSafeEqual","wait","config","delay","withRetry","i","useCallback","useContext","useEffect","useMemo","useRef","useState","history","useState","useContext","useRef","useCallback","useMemo","delay","useEffect","s","useCallback","useContext","useMemo","useContext","useMemo","useCallback","options","useCallback","useEffect","useRef","useState","config","config","useState","useRef","useEffect","useCallback","q","useEffect","c","r","v","useEffect","useEffect","useEffect"]}