amliq-dashboard 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +3 -0
- package/.env.production +1 -0
- package/Dockerfile +26 -0
- package/QUICK_START.md +267 -0
- package/README.md +161 -0
- package/TESTING_GUIDE.md +322 -0
- package/dist/.well-known/ai-plugin.json +15 -0
- package/dist/_headers +8 -0
- package/dist/_redirects +1 -0
- package/dist/assets/APIKeys-BvwFauIs.js +6 -0
- package/dist/assets/APIKeys-DaMSBZQL.js +1 -0
- package/dist/assets/AdverseMedia-DckXfMzS.js +4 -0
- package/dist/assets/AlertDetailPage-Bc2_zwu_.js +1 -0
- package/dist/assets/AlertQueue-DFtBiRoM.js +8 -0
- package/dist/assets/Analytics-DtruB5lQ.js +1 -0
- package/dist/assets/AuditTrail-BK68ePu0.js +1 -0
- package/dist/assets/AuthDivider-gRHEt7gx.js +1 -0
- package/dist/assets/Badge-B9VFkofy.js +1 -0
- package/dist/assets/BatchJobs-Bz6KFnXD.js +6 -0
- package/dist/assets/BillingPage-R9nQ5nFb.js +11 -0
- package/dist/assets/Card-Cw-T_-oU.js +1 -0
- package/dist/assets/CaseDetail-DYs7Zg_y.js +7 -0
- package/dist/assets/CaseManagement-B1Q4Dp1Y.js +1 -0
- package/dist/assets/ComplianceReport-Dhssqc9T.js +1 -0
- package/dist/assets/Configuration-B92kl9T0.js +1 -0
- package/dist/assets/CryptoScreening-C7yFlskC.js +1 -0
- package/dist/assets/Dashboard-w4-Nhv9q.js +17 -0
- package/dist/assets/DataSources-u3-Ri_5_.js +3 -0
- package/dist/assets/EDDWorkflow-CFzlEO0e.js +1 -0
- package/dist/assets/EmptyState-Do0xJAT9.js +6 -0
- package/dist/assets/ForgotPassword-BPYyQFQp.js +1 -0
- package/dist/assets/LandingPage-CjaP0zw4.js +41 -0
- package/dist/assets/ListsMarketplace-CG6KkT9B.js +6 -0
- package/dist/assets/Login-677LEGP1.js +1 -0
- package/dist/assets/MFASetup-BxqCPvui.js +1 -0
- package/dist/assets/Monitoring-9TN9MK4y.js +1 -0
- package/dist/assets/Onboarding-Cf0Y83lX.js +1 -0
- package/dist/assets/Operations-CcXwc2xw.js +10 -0
- package/dist/assets/Overview-B_Ky0VWV.js +1 -0
- package/dist/assets/PEPScreening-pUQjTH9c.js +1 -0
- package/dist/assets/PageHeader-BObHFn0i.js +1 -0
- package/dist/assets/PrivacyPolicy-DZ2xrKir.js +1 -0
- package/dist/assets/ResetPassword-AtxtpIG1.js +1 -0
- package/dist/assets/RiskAssessment-Dzuh1Usv.js +1 -0
- package/dist/assets/SARForm-D8w2ZGe-.js +1 -0
- package/dist/assets/SanctionsLists-CPA3UH2v.js +1 -0
- package/dist/assets/ScheduledTasks-Dsjk-6UR.js +1 -0
- package/dist/assets/ScreenEntity-D1U0YL7v.js +3 -0
- package/dist/assets/ScreeningProgress-BW49PzoB.js +66 -0
- package/dist/assets/SearchField-CulFKdiI.js +1 -0
- package/dist/assets/Signup-C0FmFOo_.js +1 -0
- package/dist/assets/SystemHealth-B_8u4eva.js +1 -0
- package/dist/assets/TaskHistory-BCmEM89q.js +3 -0
- package/dist/assets/Team-CUo_FlU7.js +1 -0
- package/dist/assets/TenantDetail-CgZQHUY8.js +1 -0
- package/dist/assets/Tenants-RB9E9ick.js +2 -0
- package/dist/assets/TermsOfService-BfL-kndX.js +1 -0
- package/dist/assets/TransactionMonitoring-DGh_T22s.js +14 -0
- package/dist/assets/TxnScreening-B7cm2-eh.js +1 -0
- package/dist/assets/UBOChain-falXAsCo.js +1 -0
- package/dist/assets/Users-Doakpg9c.js +1 -0
- package/dist/assets/Webhooks-BZpAfaxv.js +1 -0
- package/dist/assets/alert-triangle-YCFVm7B_.js +6 -0
- package/dist/assets/alerts-COUnTwWY.js +1 -0
- package/dist/assets/arrow-left-9ApLqP95.js +6 -0
- package/dist/assets/check-VTcvVtIU.js +6 -0
- package/dist/assets/check-circle-2-Dn-lG5YQ.js +6 -0
- package/dist/assets/code-DIJRWFVv.js +6 -0
- package/dist/assets/fingerprint-C0MGVtax.js +6 -0
- package/dist/assets/flag-B8_Gwxh6.js +6 -0
- package/dist/assets/index-CfdYcqRM.js +289 -0
- package/dist/assets/index-HPU_Rhdu.css +1 -0
- package/dist/assets/layers-zHz2o4vo.js +6 -0
- package/dist/assets/loader-B9_dNihg.js +6 -0
- package/dist/assets/mail-BijL2qwp.js +6 -0
- package/dist/assets/plus-i0oBIIPS.js +6 -0
- package/dist/assets/refresh-cw-CSuAwutt.js +6 -0
- package/dist/assets/useAnalytics-Bj8IONcw.js +72 -0
- package/dist/assets/x-circle-DLGKvijE.js +6 -0
- package/dist/favicon.svg +15 -0
- package/dist/index.html +51 -0
- package/dist/llms.txt +28 -0
- package/dist/logo.png +0 -0
- package/dist/logo.svg +17 -0
- package/dist/manifest.json +44 -0
- package/dist/robots.txt +15 -0
- package/dist/schema.json +13 -0
- package/dist/sitemap.xml +28 -0
- package/dist/sw.js +67 -0
- package/e2e/auth-setup.ts +20 -0
- package/e2e/billing.spec.ts +50 -0
- package/e2e/cases.spec.ts +53 -0
- package/e2e/compliance.spec.ts +65 -0
- package/e2e/config.spec.ts +56 -0
- package/e2e/dashboard.spec.ts +47 -0
- package/e2e/fixtures.ts +33 -0
- package/e2e/lists.spec.ts +43 -0
- package/e2e/login.spec.ts +64 -0
- package/e2e/media.spec.ts +48 -0
- package/e2e/mocks.ts +51 -0
- package/e2e/monitoring.spec.ts +44 -0
- package/e2e/navigation.spec.ts +56 -0
- package/e2e/onboarding.spec.ts +49 -0
- package/e2e/responsive.spec.ts +40 -0
- package/e2e/risk.spec.ts +61 -0
- package/e2e/screening.spec.ts +76 -0
- package/e2e/team.spec.ts +53 -0
- package/index.html +50 -0
- package/package.json +47 -0
- package/playwright.config.ts +35 -0
- package/postcss.config.js +6 -0
- package/public/.well-known/ai-plugin.json +15 -0
- package/public/_headers +8 -0
- package/public/_redirects +1 -0
- package/public/favicon.svg +15 -0
- package/public/llms.txt +28 -0
- package/public/logo.png +0 -0
- package/public/logo.svg +17 -0
- package/public/manifest.json +44 -0
- package/public/robots.txt +15 -0
- package/public/schema.json +13 -0
- package/public/sitemap.xml +28 -0
- package/public/sw.js +67 -0
- package/scripts/test-runner.sh +152 -0
- package/src/App.tsx +48 -0
- package/src/api/alerts.ts +19 -0
- package/src/api/analytics.ts +6 -0
- package/src/api/audit.ts +11 -0
- package/src/api/auth.ts +26 -0
- package/src/api/billing.ts +54 -0
- package/src/api/cases.ts +48 -0
- package/src/api/client.ts +50 -0
- package/src/api/config.ts +30 -0
- package/src/api/edd.ts +25 -0
- package/src/api/enforcement.ts +33 -0
- package/src/api/lists.ts +24 -0
- package/src/api/monitoring.ts +82 -0
- package/src/api/pep.ts +30 -0
- package/src/api/risk.ts +26 -0
- package/src/api/screening.ts +37 -0
- package/src/api/team.ts +27 -0
- package/src/api/transactions.ts +37 -0
- package/src/components/admin/TenantCards.tsx +51 -0
- package/src/components/alerts/AlertActions.test.tsx +80 -0
- package/src/components/alerts/AlertActions.tsx +68 -0
- package/src/components/alerts/AlertCard.test.tsx +86 -0
- package/src/components/alerts/AlertCard.tsx +60 -0
- package/src/components/alerts/AlertDetailSidebar.tsx +63 -0
- package/src/components/alerts/AlertFilters.test.tsx +73 -0
- package/src/components/alerts/AlertFilters.tsx +88 -0
- package/src/components/alerts/EntityDetailsCard.test.tsx +61 -0
- package/src/components/alerts/EntityDetailsCard.tsx +37 -0
- package/src/components/alerts/NotesCard.test.tsx +39 -0
- package/src/components/alerts/NotesCard.tsx +28 -0
- package/src/components/auth/AuthDivider.tsx +18 -0
- package/src/components/auth/LoginForm.tsx +62 -0
- package/src/components/auth/LoginLeftPanel.tsx +43 -0
- package/src/components/auth/PasswordStrength.tsx +26 -0
- package/src/components/auth/SignInButtons.tsx +46 -0
- package/src/components/auth/SignupLeftPanel.tsx +35 -0
- package/src/components/auth/countries.ts +17 -0
- package/src/components/charts/AreaChart.tsx +45 -0
- package/src/components/charts/BarChart.tsx +48 -0
- package/src/components/charts/DonutChart.tsx +47 -0
- package/src/components/compliance/CaseActions.tsx +74 -0
- package/src/components/compliance/CaseTimeline.tsx +68 -0
- package/src/components/compliance/MediaResultCard.tsx +87 -0
- package/src/components/compliance/PEPResultCard.tsx +78 -0
- package/src/components/config/MatchingModesCard.test.tsx +75 -0
- package/src/components/config/MatchingModesCard.tsx +40 -0
- package/src/components/config/ScreeningLayersCard.test.tsx +57 -0
- package/src/components/config/ScreeningLayersCard.tsx +36 -0
- package/src/components/config/ThresholdsCard.test.tsx +79 -0
- package/src/components/config/ThresholdsCard.tsx +51 -0
- package/src/components/dashboard/ActivityFeed.tsx +93 -0
- package/src/components/dashboard/DashboardGreeting.tsx +23 -0
- package/src/components/dashboard/DashboardSkeleton.tsx +35 -0
- package/src/components/dashboard/QuickActions.tsx +52 -0
- package/src/components/dashboard/TopEntitiesTable.tsx +63 -0
- package/src/components/data/ComplianceMetrics.test.tsx +32 -0
- package/src/components/data/ComplianceMetrics.tsx +40 -0
- package/src/components/data/ConfidenceScore.test.tsx +62 -0
- package/src/components/data/ConfidenceScore.tsx +27 -0
- package/src/components/data/StatCard.test.tsx +72 -0
- package/src/components/data/StatCard.tsx +63 -0
- package/src/components/data/StatusBadge.test.tsx +63 -0
- package/src/components/data/StatusBadge.tsx +39 -0
- package/src/components/layout/AppShell.tsx +48 -0
- package/src/components/layout/Breadcrumbs.tsx +48 -0
- package/src/components/layout/CommandPalette.tsx +81 -0
- package/src/components/layout/DashboardLayout.tsx +19 -0
- package/src/components/layout/MobileHeader.tsx +30 -0
- package/src/components/layout/NavGroup.test.tsx +63 -0
- package/src/components/layout/NavGroup.tsx +64 -0
- package/src/components/layout/NotificationBell.tsx +89 -0
- package/src/components/layout/PageHeader.test.tsx +61 -0
- package/src/components/layout/PageHeader.tsx +19 -0
- package/src/components/layout/ProtectedRoute.tsx +31 -0
- package/src/components/layout/PublicLayout.tsx +17 -0
- package/src/components/layout/Sidebar.test.tsx +67 -0
- package/src/components/layout/Sidebar.tsx +92 -0
- package/src/components/layout/Toolbar.test.tsx +47 -0
- package/src/components/layout/Toolbar.tsx +68 -0
- package/src/components/layout/navItems.ts +94 -0
- package/src/components/lists/ListCard.tsx +78 -0
- package/src/components/lists/ListMarketplaceCard.tsx +77 -0
- package/src/components/screening/CircularConfidence.tsx +38 -0
- package/src/components/screening/LimitReachedBanner.tsx +31 -0
- package/src/components/screening/ListSelector.tsx +64 -0
- package/src/components/screening/MatchDetailHeader.tsx +64 -0
- package/src/components/screening/MatchEntityInfo.tsx +56 -0
- package/src/components/screening/MatchEvidenceBars.tsx +65 -0
- package/src/components/screening/MatchMetadata.tsx +95 -0
- package/src/components/screening/ScreenResults.tsx +49 -0
- package/src/components/screening/ScreeningForm.test.tsx +83 -0
- package/src/components/screening/ScreeningForm.tsx +100 -0
- package/src/components/screening/ScreeningLayersList.test.tsx +33 -0
- package/src/components/screening/ScreeningLayersList.tsx +46 -0
- package/src/components/screening/ScreeningProgress.tsx +91 -0
- package/src/components/screening/ScreeningQuotaBanner.tsx +64 -0
- package/src/components/screening/ScreeningResultCard.tsx +47 -0
- package/src/components/screening/ScreeningResultRow.tsx +45 -0
- package/src/components/screening/ScreeningResults.test.tsx +37 -0
- package/src/components/screening/ScreeningResults.tsx +33 -0
- package/src/components/screening/ShareResults.tsx +103 -0
- package/src/components/screening/ThresholdSlider.tsx +23 -0
- package/src/components/transactions/WebhookCTA.tsx +63 -0
- package/src/components/ui/Avatar.test.tsx +47 -0
- package/src/components/ui/Avatar.tsx +35 -0
- package/src/components/ui/Badge.test.tsx +49 -0
- package/src/components/ui/Badge.tsx +33 -0
- package/src/components/ui/Button.test.tsx +56 -0
- package/src/components/ui/Button.tsx +46 -0
- package/src/components/ui/Card.test.tsx +61 -0
- package/src/components/ui/Card.tsx +29 -0
- package/src/components/ui/ConfirmModal.tsx +67 -0
- package/src/components/ui/Divider.test.tsx +24 -0
- package/src/components/ui/Divider.tsx +5 -0
- package/src/components/ui/EmptyState.test.tsx +49 -0
- package/src/components/ui/EmptyState.tsx +22 -0
- package/src/components/ui/ErrorBoundary.tsx +44 -0
- package/src/components/ui/ExportMenu.tsx +71 -0
- package/src/components/ui/LanguageSwitcher.tsx +37 -0
- package/src/components/ui/LoadingSpinner.test.tsx +41 -0
- package/src/components/ui/LoadingSpinner.tsx +21 -0
- package/src/components/ui/MetricCard.tsx +63 -0
- package/src/components/ui/ScoreRing.tsx +51 -0
- package/src/components/ui/SearchField.test.tsx +55 -0
- package/src/components/ui/SearchField.tsx +31 -0
- package/src/components/ui/SeverityBadge.tsx +57 -0
- package/src/components/ui/ThemeToggle.tsx +37 -0
- package/src/components/ui/Toast.test.tsx +79 -0
- package/src/components/ui/Toast.tsx +75 -0
- package/src/components/ui/Toggle.test.tsx +85 -0
- package/src/components/ui/Toggle.tsx +46 -0
- package/src/context/AuthContext.tsx +71 -0
- package/src/data/pepProfiles.ts +76 -0
- package/src/data/pepProfilesExtra.ts +58 -0
- package/src/hooks/useAlerts.ts +36 -0
- package/src/hooks/useAnalytics.ts +23 -0
- package/src/hooks/useApi.test.ts +79 -0
- package/src/hooks/useApi.ts +33 -0
- package/src/hooks/useAudit.ts +28 -0
- package/src/hooks/useBilling.ts +38 -0
- package/src/hooks/useConfig.ts +35 -0
- package/src/hooks/useDebounce.test.ts +84 -0
- package/src/hooks/useDebounce.ts +15 -0
- package/src/hooks/useDirection.ts +15 -0
- package/src/hooks/useLists.ts +34 -0
- package/src/hooks/useMediaQuery.test.ts +97 -0
- package/src/hooks/useMediaQuery.ts +28 -0
- package/src/hooks/useScreening.ts +33 -0
- package/src/hooks/useSidebar.ts +18 -0
- package/src/hooks/useUsage.ts +27 -0
- package/src/i18n/config.ts +33 -0
- package/src/i18n/locales/ar/admin.json +19 -0
- package/src/i18n/locales/ar/alerts.json +52 -0
- package/src/i18n/locales/ar/analytics.json +9 -0
- package/src/i18n/locales/ar/audit.json +12 -0
- package/src/i18n/locales/ar/auth.json +60 -0
- package/src/i18n/locales/ar/batch.json +5 -0
- package/src/i18n/locales/ar/billing.json +41 -0
- package/src/i18n/locales/ar/common.json +65 -0
- package/src/i18n/locales/ar/compliance.json +83 -0
- package/src/i18n/locales/ar/config.json +13 -0
- package/src/i18n/locales/ar/dashboard.json +19 -0
- package/src/i18n/locales/ar/errors.json +9 -0
- package/src/i18n/locales/ar/index.ts +29 -0
- package/src/i18n/locales/ar/legal.json +10 -0
- package/src/i18n/locales/ar/lists.json +6 -0
- package/src/i18n/locales/ar/marketing.json +110 -0
- package/src/i18n/locales/ar/monitoring.json +15 -0
- package/src/i18n/locales/ar/nav.json +35 -0
- package/src/i18n/locales/ar/onboarding.json +25 -0
- package/src/i18n/locales/ar/platform.json +23 -0
- package/src/i18n/locales/ar/screening.json +26 -0
- package/src/i18n/locales/ar/team.json +11 -0
- package/src/i18n/locales/en/admin.json +21 -0
- package/src/i18n/locales/en/alerts.json +52 -0
- package/src/i18n/locales/en/analytics.json +9 -0
- package/src/i18n/locales/en/audit.json +12 -0
- package/src/i18n/locales/en/auth.json +60 -0
- package/src/i18n/locales/en/batch.json +5 -0
- package/src/i18n/locales/en/billing.json +87 -0
- package/src/i18n/locales/en/common.json +65 -0
- package/src/i18n/locales/en/compliance.json +83 -0
- package/src/i18n/locales/en/config.json +29 -0
- package/src/i18n/locales/en/dashboard.json +23 -0
- package/src/i18n/locales/en/errors.json +9 -0
- package/src/i18n/locales/en/index.ts +29 -0
- package/src/i18n/locales/en/legal.json +114 -0
- package/src/i18n/locales/en/lists.json +6 -0
- package/src/i18n/locales/en/marketing.json +174 -0
- package/src/i18n/locales/en/monitoring.json +15 -0
- package/src/i18n/locales/en/nav.json +35 -0
- package/src/i18n/locales/en/onboarding.json +31 -0
- package/src/i18n/locales/en/platform.json +25 -0
- package/src/i18n/locales/en/screening.json +26 -0
- package/src/i18n/locales/en/team.json +12 -0
- package/src/i18n/locales/he/admin.json +19 -0
- package/src/i18n/locales/he/alerts.json +52 -0
- package/src/i18n/locales/he/analytics.json +9 -0
- package/src/i18n/locales/he/audit.json +12 -0
- package/src/i18n/locales/he/auth.json +60 -0
- package/src/i18n/locales/he/batch.json +5 -0
- package/src/i18n/locales/he/billing.json +41 -0
- package/src/i18n/locales/he/common.json +65 -0
- package/src/i18n/locales/he/compliance.json +83 -0
- package/src/i18n/locales/he/config.json +13 -0
- package/src/i18n/locales/he/dashboard.json +19 -0
- package/src/i18n/locales/he/errors.json +9 -0
- package/src/i18n/locales/he/index.ts +29 -0
- package/src/i18n/locales/he/legal.json +10 -0
- package/src/i18n/locales/he/lists.json +6 -0
- package/src/i18n/locales/he/marketing.json +110 -0
- package/src/i18n/locales/he/monitoring.json +15 -0
- package/src/i18n/locales/he/nav.json +35 -0
- package/src/i18n/locales/he/onboarding.json +25 -0
- package/src/i18n/locales/he/platform.json +23 -0
- package/src/i18n/locales/he/screening.json +26 -0
- package/src/i18n/locales/he/team.json +11 -0
- package/src/index.css +112 -0
- package/src/main.tsx +15 -0
- package/src/pages/APIKeys.tsx +120 -0
- package/src/pages/AddMonitorModal.tsx +30 -0
- package/src/pages/AdverseMedia.test.tsx +18 -0
- package/src/pages/AdverseMedia.tsx +89 -0
- package/src/pages/AlertDetailPage.tsx +64 -0
- package/src/pages/AlertQueue.test.tsx +48 -0
- package/src/pages/AlertQueue.tsx +63 -0
- package/src/pages/Analytics.tsx +50 -0
- package/src/pages/AuditTrail.tsx +64 -0
- package/src/pages/BatchJobs.tsx +79 -0
- package/src/pages/CaseDetail.tsx +72 -0
- package/src/pages/CaseManagement.test.tsx +31 -0
- package/src/pages/CaseManagement.tsx +92 -0
- package/src/pages/Configuration.test.tsx +96 -0
- package/src/pages/Configuration.tsx +123 -0
- package/src/pages/CryptoScreening.tsx +109 -0
- package/src/pages/Dashboard.test.tsx +51 -0
- package/src/pages/Dashboard.tsx +66 -0
- package/src/pages/EDDWorkflow.test.tsx +29 -0
- package/src/pages/EDDWorkflow.tsx +73 -0
- package/src/pages/ForgotPassword.test.tsx +49 -0
- package/src/pages/ForgotPassword.tsx +67 -0
- package/src/pages/ListsMarketplace.tsx +102 -0
- package/src/pages/Login.test.tsx +100 -0
- package/src/pages/Login.tsx +57 -0
- package/src/pages/MFASetup.tsx +114 -0
- package/src/pages/MonitorProfileCard.tsx +27 -0
- package/src/pages/Monitoring.tsx +68 -0
- package/src/pages/Onboarding.test.tsx +36 -0
- package/src/pages/Onboarding.tsx +60 -0
- package/src/pages/PEPScreening.test.tsx +15 -0
- package/src/pages/PEPScreening.tsx +100 -0
- package/src/pages/ResetPassword.tsx +81 -0
- package/src/pages/RiskAssessment.test.tsx +15 -0
- package/src/pages/RiskAssessment.tsx +108 -0
- package/src/pages/SanctionsLists.tsx +74 -0
- package/src/pages/ScreenEntity.test.tsx +82 -0
- package/src/pages/ScreenEntity.tsx +76 -0
- package/src/pages/Signup.test.tsx +98 -0
- package/src/pages/Signup.tsx +92 -0
- package/src/pages/TaskHistory.tsx +183 -0
- package/src/pages/Team.test.tsx +15 -0
- package/src/pages/Team.tsx +140 -0
- package/src/pages/TransactionMonitoring.test.tsx +18 -0
- package/src/pages/TransactionMonitoring.tsx +118 -0
- package/src/pages/TxnScreening.tsx +125 -0
- package/src/pages/UBOChain.test.tsx +35 -0
- package/src/pages/UBOChain.tsx +65 -0
- package/src/pages/Webhooks.tsx +137 -0
- package/src/pages/admin/DataSources.tsx +230 -0
- package/src/pages/admin/Operations.tsx +103 -0
- package/src/pages/admin/ScheduledTasks.tsx +155 -0
- package/src/pages/admin/SystemHealth.tsx +58 -0
- package/src/pages/admin/TenantDetail.tsx +62 -0
- package/src/pages/admin/Tenants.test.tsx +20 -0
- package/src/pages/admin/Tenants.tsx +63 -0
- package/src/pages/admin/opsRunners.ts +81 -0
- package/src/pages/admin/opsTerminal.tsx +63 -0
- package/src/pages/billing/ActiveSubscriptions.tsx +41 -0
- package/src/pages/billing/AddProductModal.tsx +99 -0
- package/src/pages/billing/BillingPage.test.tsx +30 -0
- package/src/pages/billing/BillingPage.tsx +67 -0
- package/src/pages/billing/CurrentPlan.tsx +50 -0
- package/src/pages/billing/InvoiceList.tsx +104 -0
- package/src/pages/billing/InvoiceRow.tsx +37 -0
- package/src/pages/billing/LemonSqueezySetup.tsx +51 -0
- package/src/pages/billing/PaymentAlert.tsx +33 -0
- package/src/pages/billing/PlanComparison.tsx +53 -0
- package/src/pages/billing/ProductUsage.tsx +43 -0
- package/src/pages/billing/PromoCodeInput.tsx +58 -0
- package/src/pages/billing/SeatManager.tsx +80 -0
- package/src/pages/billing/SeatRow.tsx +32 -0
- package/src/pages/billing/SubscriptionCard.tsx +73 -0
- package/src/pages/billing/UpgradeModal.tsx +53 -0
- package/src/pages/billing/UsageHistory.tsx +37 -0
- package/src/pages/billing/UsageMeter.tsx +26 -0
- package/src/pages/billing/UsageOverview.tsx +38 -0
- package/src/pages/legal/PrivacyPolicy.tsx +25 -0
- package/src/pages/legal/TermsOfService.tsx +25 -0
- package/src/pages/marketing/BundleCallout.tsx +24 -0
- package/src/pages/marketing/CTASection.tsx +48 -0
- package/src/pages/marketing/CaseStudy.tsx +37 -0
- package/src/pages/marketing/ComparisonTable.tsx +66 -0
- package/src/pages/marketing/CompetitiveEdge.tsx +55 -0
- package/src/pages/marketing/DataCoverage.tsx +54 -0
- package/src/pages/marketing/DataRain.tsx +30 -0
- package/src/pages/marketing/EnterpriseCTA.tsx +26 -0
- package/src/pages/marketing/FAQItem.tsx +27 -0
- package/src/pages/marketing/FAQSchema.tsx +43 -0
- package/src/pages/marketing/FAQSection.tsx +19 -0
- package/src/pages/marketing/FeatureDetail.tsx +19 -0
- package/src/pages/marketing/FeaturesGrid.tsx +60 -0
- package/src/pages/marketing/FeaturesSpotlight.tsx +68 -0
- package/src/pages/marketing/FooterSection.tsx +92 -0
- package/src/pages/marketing/GradientOrbs.tsx +26 -0
- package/src/pages/marketing/HeroSearch.tsx +113 -0
- package/src/pages/marketing/HeroSection.tsx +72 -0
- package/src/pages/marketing/LandingPage.tsx +45 -0
- package/src/pages/marketing/LogoCloud.tsx +31 -0
- package/src/pages/marketing/LogoMarquee.tsx +45 -0
- package/src/pages/marketing/MarketingNav.tsx +80 -0
- package/src/pages/marketing/MatchingLayers.tsx +78 -0
- package/src/pages/marketing/MobileMenu.tsx +45 -0
- package/src/pages/marketing/PricingCard.tsx +57 -0
- package/src/pages/marketing/PricingFeatureRow.tsx +16 -0
- package/src/pages/marketing/PricingSection.tsx +103 -0
- package/src/pages/marketing/PricingToggle.tsx +40 -0
- package/src/pages/marketing/ProductPricingCards.tsx +23 -0
- package/src/pages/marketing/ProductShowcase.tsx +81 -0
- package/src/pages/marketing/ProductTabs.tsx +45 -0
- package/src/pages/marketing/QuoteRotator.tsx +56 -0
- package/src/pages/marketing/StatsBar.tsx +81 -0
- package/src/pages/marketing/StatsSection.tsx +44 -0
- package/src/pages/marketing/TestimonialCard.tsx +38 -0
- package/src/pages/marketing/TestimonialsSection.tsx +32 -0
- package/src/pages/marketing/animations.tsx +56 -0
- package/src/pages/onboarding/CountryStep.tsx +38 -0
- package/src/pages/onboarding/ListsStep.tsx +44 -0
- package/src/pages/onboarding/StepIndicator.tsx +34 -0
- package/src/pages/onboarding/ThresholdStep.tsx +49 -0
- package/src/pages/platform/APIKeys.tsx +102 -0
- package/src/pages/platform/Overview.tsx +58 -0
- package/src/pages/platform/Users.tsx +110 -0
- package/src/pages/reporting/ComplianceReport.tsx +99 -0
- package/src/pages/reporting/SARForm.tsx +99 -0
- package/src/routes/appRoutes.tsx +60 -0
- package/src/routes/compliance.tsx +28 -0
- package/src/routes/lazyCompliance.ts +34 -0
- package/src/routes/lazyPages.ts +35 -0
- package/src/routes/lazyPlatform.ts +5 -0
- package/src/routes/platform.tsx +15 -0
- package/src/styles/effects.css +76 -0
- package/src/test/setup.ts +25 -0
- package/src/test/utils.tsx +49 -0
- package/src/types/alert.ts +31 -0
- package/src/types/analytics.ts +16 -0
- package/src/types/audit.ts +11 -0
- package/src/types/billing.ts +60 -0
- package/src/types/common.ts +15 -0
- package/src/types/config.ts +19 -0
- package/src/types/entity.ts +34 -0
- package/src/types/index.ts +8 -0
- package/src/types/list.ts +15 -0
- package/src/types/screening.ts +32 -0
- package/src/vite-env.d.ts +1 -0
- package/tailwind.config.js +65 -0
- package/tsconfig.json +22 -0
- package/vite.config.ts +11 -0
- package/vitest.config.ts +19 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { motion } from 'framer-motion'
|
|
2
|
+
import { FadeUp } from './animations'
|
|
3
|
+
|
|
4
|
+
const regions = [
|
|
5
|
+
{ name: 'Americas', lists: ['US OFAC SDN', 'US OFAC Consolidated', 'Canada OSFI', 'Brazil COAF'], color: '#3B82F6' },
|
|
6
|
+
{ name: 'Europe', lists: ['EU Financial Sanctions', 'UK OFSI', 'Swiss SECO', 'French DG Trésor'], color: '#8B5CF6' },
|
|
7
|
+
{ name: 'Middle East & Africa', lists: ['Israel NBCTF', 'UAE CBUAE', 'Saudi SAMA', 'South Africa FIC'], color: '#F59E0B' },
|
|
8
|
+
{ name: 'Asia Pacific', lists: ['UN Consolidated', 'Japan MOF', 'Singapore MAS', 'Australia DFAT', 'South Korea KoFIU', 'Hong Kong HKMA'], color: '#00B894' },
|
|
9
|
+
{ name: 'Intelligence', lists: ['PEP Database (1M+)', 'Wikidata Politicians', 'RCA Graph', 'FATF Black/Grey Lists', 'ICIJ Offshore Leaks', 'Adverse Media'], color: '#EF4444' },
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
export default function DataCoverage() {
|
|
13
|
+
return (
|
|
14
|
+
<section className="py-28 px-4">
|
|
15
|
+
<div className="max-w-6xl mx-auto">
|
|
16
|
+
<FadeUp>
|
|
17
|
+
<div className="text-center mb-20">
|
|
18
|
+
<p className="text-xs uppercase tracking-[0.2em] text-[#00B894] font-semibold mb-4">Global coverage</p>
|
|
19
|
+
<h2 className="text-3xl sm:text-4xl lg:text-5xl font-bold text-[#0F172A]"
|
|
20
|
+
style={{ letterSpacing: '-0.03em' }}>
|
|
21
|
+
86 lists. 195 countries. 3M+ entities.
|
|
22
|
+
</h2>
|
|
23
|
+
<p className="text-[#64748B] mt-5 max-w-xl mx-auto">
|
|
24
|
+
Updated daily from official sources. Growing to 5M+ with AI-powered entity discovery.
|
|
25
|
+
</p>
|
|
26
|
+
</div>
|
|
27
|
+
</FadeUp>
|
|
28
|
+
|
|
29
|
+
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5">
|
|
30
|
+
{regions.map((r, i) => (
|
|
31
|
+
<FadeUp key={r.name} delay={i * 0.08}>
|
|
32
|
+
<motion.div className="p-6 rounded-2xl"
|
|
33
|
+
style={{ background: '#FAFBFC', border: '1px solid rgba(0,0,0,0.06)' }}
|
|
34
|
+
whileHover={{ y: -3, boxShadow: '0 8px 30px rgba(0,0,0,0.06)' }}
|
|
35
|
+
transition={{ type: 'spring', stiffness: 300, damping: 20 }}>
|
|
36
|
+
<div className="flex items-center gap-2 mb-4">
|
|
37
|
+
<span className="w-2.5 h-2.5 rounded-full" style={{ background: r.color }} />
|
|
38
|
+
<span className="text-sm font-bold text-[#0F172A]">{r.name}</span>
|
|
39
|
+
</div>
|
|
40
|
+
<div className="space-y-1.5">
|
|
41
|
+
{r.lists.map(l => (
|
|
42
|
+
<p key={l} className="text-xs text-[#64748B]">
|
|
43
|
+
<span className="text-[#00B894] mr-1.5 font-bold">+</span>{l}
|
|
44
|
+
</p>
|
|
45
|
+
))}
|
|
46
|
+
</div>
|
|
47
|
+
</motion.div>
|
|
48
|
+
</FadeUp>
|
|
49
|
+
))}
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</section>
|
|
53
|
+
)
|
|
54
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const cols = Array.from({ length: 20 }, (_, i) => i)
|
|
2
|
+
const chars = '01アイウエオカキクケコサシスセソAMLIQ$%#@!&OFAC'
|
|
3
|
+
|
|
4
|
+
function getChar(col: number) {
|
|
5
|
+
return chars[(col * 7 + 3) % chars.length]
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default function DataRain() {
|
|
9
|
+
return (
|
|
10
|
+
<div className="absolute inset-0 overflow-hidden pointer-events-none" aria-hidden="true">
|
|
11
|
+
<div className="relative w-full h-full">
|
|
12
|
+
{cols.map(i => (
|
|
13
|
+
<div
|
|
14
|
+
key={i}
|
|
15
|
+
className="absolute top-0 text-xs font-mono whitespace-pre leading-5"
|
|
16
|
+
style={{
|
|
17
|
+
left: `${(i / cols.length) * 100}%`,
|
|
18
|
+
color: i % 3 === 0 ? '#00FFFF' : '#22C55E',
|
|
19
|
+
opacity: 0.04,
|
|
20
|
+
animation: `rain ${8 + (i % 5) * 2}s linear infinite`,
|
|
21
|
+
animationDelay: `${-(i % 7) * 1.2}s`,
|
|
22
|
+
}}
|
|
23
|
+
>
|
|
24
|
+
{Array.from({ length: 30 }, (_, j) => getChar(i + j)).join('\n')}
|
|
25
|
+
</div>
|
|
26
|
+
))}
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
)
|
|
30
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { useTranslation } from 'react-i18next'
|
|
3
|
+
import { Phone } from 'lucide-react'
|
|
4
|
+
|
|
5
|
+
export default function EnterpriseCTA() {
|
|
6
|
+
const { t } = useTranslation('marketing')
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<div className="bg-gradient-to-r from-indigo-900/50 to-blue-900/50 border border-indigo-800 rounded-xl p-8 text-center">
|
|
10
|
+
<h3 className="text-2xl font-bold text-white mb-2">{t('enterprise.heading')}</h3>
|
|
11
|
+
<p className="text-zinc-400 mb-6">{t('enterprise.description')}</p>
|
|
12
|
+
|
|
13
|
+
<div className="flex flex-col sm:flex-row gap-4 justify-center mb-6">
|
|
14
|
+
<button type="button" className="px-8 py-3 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-lg transition-colors">
|
|
15
|
+
{t('enterprise.cta')}
|
|
16
|
+
</button>
|
|
17
|
+
<a href="tel:+1234567890" className="px-8 py-3 border border-white/10 hover:border-white/20 text-white font-medium rounded-lg transition-colors flex items-center justify-center gap-2">
|
|
18
|
+
<Phone size={16} />
|
|
19
|
+
(855) 924-3447
|
|
20
|
+
</a>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<p className="text-sm text-zinc-400">{t('enterprise.note')}</p>
|
|
24
|
+
</div>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React, { useState } from 'react'
|
|
2
|
+
import { ChevronDown } from 'lucide-react'
|
|
3
|
+
|
|
4
|
+
interface FAQItemProps {
|
|
5
|
+
question: string
|
|
6
|
+
answer: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default function FAQItem({ question, answer }: FAQItemProps) {
|
|
10
|
+
const [open, setOpen] = useState(false)
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<div className="border border-white/[0.06] rounded-xl">
|
|
14
|
+
<button
|
|
15
|
+
type="button"
|
|
16
|
+
onClick={() => setOpen(!open)}
|
|
17
|
+
aria-expanded={open}
|
|
18
|
+
className="w-full px-6 py-4 flex items-center justify-between hover:bg-white/[0.02] transition-colors"
|
|
19
|
+
>
|
|
20
|
+
<span className="text-white font-medium text-left">{question}</span>
|
|
21
|
+
<ChevronDown size={20} className={`text-zinc-400 transition-transform ${open ? 'rotate-180' : ''}`} />
|
|
22
|
+
</button>
|
|
23
|
+
|
|
24
|
+
{open && <div className="px-6 pb-4 text-zinc-400 border-t border-white/[0.06]">{answer}</div>}
|
|
25
|
+
</div>
|
|
26
|
+
)
|
|
27
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const faqs = [
|
|
2
|
+
{
|
|
3
|
+
q: 'What is AMLIQ?',
|
|
4
|
+
a: 'AMLIQ is an AI-powered AML/CFT sanctions screening platform for financial institutions. It screens entities against global sanctions lists including OFAC, UN, EU, and UK with sub-50ms latency.',
|
|
5
|
+
},
|
|
6
|
+
{
|
|
7
|
+
q: 'How does AMLIQ compare to World-Check?',
|
|
8
|
+
a: 'AMLIQ offers 6-layer AI matching (Exact, Fuzzy, Phonetic, Token, Embedding, Graph) at 1/10th the cost of Refinitiv World-Check, with explainable AI showing why each match was found.',
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
q: 'What sanctions lists does AMLIQ screen against?',
|
|
12
|
+
a: 'AMLIQ screens against OFAC SDN, UN Consolidated, EU Financial Sanctions Facility, UK OFSI, Israeli NBCTF, and OpenSanctions — covering 18,699+ sanctioned entities updated continuously.',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
q: 'How fast is AMLIQ screening?',
|
|
16
|
+
a: 'AMLIQ delivers sub-50ms single-entity screening and supports batch processing for bulk portfolios via REST API.',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
q: 'Does AMLIQ have an API?',
|
|
20
|
+
a: 'Yes. AMLIQ provides a REST API with endpoints for single screening, batch screening (CSV/JSON), and alert management. Full API documentation is available at amliq.com/api/docs.',
|
|
21
|
+
},
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
function buildSchema() {
|
|
25
|
+
return {
|
|
26
|
+
'@context': 'https://schema.org',
|
|
27
|
+
'@type': 'FAQPage',
|
|
28
|
+
mainEntity: faqs.map(f => ({
|
|
29
|
+
'@type': 'Question',
|
|
30
|
+
name: f.q,
|
|
31
|
+
acceptedAnswer: { '@type': 'Answer', text: f.a },
|
|
32
|
+
})),
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export default function FAQSchema() {
|
|
37
|
+
return (
|
|
38
|
+
<script
|
|
39
|
+
type="application/ld+json"
|
|
40
|
+
dangerouslySetInnerHTML={{ __html: JSON.stringify(buildSchema()) }}
|
|
41
|
+
/>
|
|
42
|
+
)
|
|
43
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { useTranslation } from 'react-i18next'
|
|
3
|
+
import FAQItem from './FAQItem'
|
|
4
|
+
|
|
5
|
+
export default function FAQSection() {
|
|
6
|
+
const { t } = useTranslation('marketing')
|
|
7
|
+
const items = t('faq.items', { returnObjects: true }) as Array<{ q: string; a: string }>
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<section className="py-20 px-4">
|
|
11
|
+
<div className="max-w-3xl mx-auto">
|
|
12
|
+
<h2 className="text-4xl font-bold text-white text-center mb-12">{t('faq.heading')}</h2>
|
|
13
|
+
<div className="space-y-3">
|
|
14
|
+
{items.map((faq, i) => <FAQItem key={i} question={faq.q} answer={faq.a} />)}
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
</section>
|
|
18
|
+
)
|
|
19
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react'
|
|
2
|
+
|
|
3
|
+
interface FeatureDetailProps {
|
|
4
|
+
icon: ReactNode
|
|
5
|
+
title: string
|
|
6
|
+
description: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default function FeatureDetail({ icon, title, description }: FeatureDetailProps) {
|
|
10
|
+
return (
|
|
11
|
+
<div className="p-6 rounded-xl bg-white/[0.02] hover:bg-white/[0.04] border border-white/[0.06] hover:border-white/[0.12] transition-all">
|
|
12
|
+
<div className="w-12 h-12 rounded-lg bg-gradient-to-br from-indigo-600 to-blue-600 flex items-center justify-center mb-4 text-white">
|
|
13
|
+
{icon}
|
|
14
|
+
</div>
|
|
15
|
+
<h3 className="text-lg font-semibold text-white mb-2">{title}</h3>
|
|
16
|
+
<p className="text-sm text-zinc-400">{description}</p>
|
|
17
|
+
</div>
|
|
18
|
+
)
|
|
19
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Layers, Zap, Globe, Brain, ShieldCheck, Building } from 'lucide-react'
|
|
2
|
+
import type { ReactNode } from 'react'
|
|
3
|
+
|
|
4
|
+
interface Feature {
|
|
5
|
+
icon: ReactNode
|
|
6
|
+
title: string
|
|
7
|
+
desc: string
|
|
8
|
+
code: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const features: Feature[] = [
|
|
12
|
+
{ icon: <Layers size={20} />, title: '6-Layer Matching', desc: 'Exact, Fuzzy, Phonetic, Token, Embedding, and Graph layers in concert.', code: 'engine.match(entity, 6)' },
|
|
13
|
+
{ icon: <Zap size={20} />, title: 'Real-Time Screening', desc: 'Sub-50ms single lookups. Batch processing for bulk portfolios.', code: 'latency: 12ms avg' },
|
|
14
|
+
{ icon: <Globe size={20} />, title: 'Global Coverage', desc: 'OFAC, UN, EU, UK OFSI, Israeli NBCTF lists updated continuously.', code: 'lists: [OFAC,UN,EU,UK]' },
|
|
15
|
+
{ icon: <Brain size={20} />, title: 'AI Intelligence', desc: 'Explainable match reasoning with auto-escalation rules.', code: 'explain(match).reason' },
|
|
16
|
+
{ icon: <ShieldCheck size={20} />, title: 'Enterprise Security', desc: 'SOC 2 Type II. E2E encryption, audit trails, RBAC.', code: 'auth: SOC2 | ISO27001' },
|
|
17
|
+
{ icon: <Building size={20} />, title: 'Multi-Tenant', desc: 'Per-org configuration, custom thresholds, granular RBAC.', code: 'tenant.config(org_id)' },
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
function Card({ icon, title, desc, code }: Feature) {
|
|
21
|
+
return (
|
|
22
|
+
<div className="group relative bg-white/[0.02] rounded-xl p-6 transition-all duration-300 hover:-translate-y-1 overflow-hidden"
|
|
23
|
+
style={{ border: '1px solid rgba(0,255,255,0.08)' }}>
|
|
24
|
+
<div className="absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity duration-500 rounded-xl"
|
|
25
|
+
style={{ background: 'conic-gradient(from var(--angle,0deg), #00FFFF, #3B82F6, #A855F7, #00FFFF)', padding: '1px', mask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)', maskComposite: 'exclude', WebkitMaskComposite: 'xor', animation: 'border-rotate 3s linear infinite' }} />
|
|
26
|
+
<div className="relative z-10">
|
|
27
|
+
<div className="w-10 h-10 rounded-lg bg-cyan-400/10 flex items-center justify-center mb-4 text-cyan-400 group-hover:bg-cyan-400/20 transition-colors"
|
|
28
|
+
style={{ boxShadow: '0 0 10px rgba(0,255,255,0.1)' }}>
|
|
29
|
+
{icon}
|
|
30
|
+
</div>
|
|
31
|
+
<h3 className="text-[#F8FAFC] font-semibold mb-2">{title}</h3>
|
|
32
|
+
<p className="text-sm text-[#94A3B8] leading-relaxed mb-3">{desc}</p>
|
|
33
|
+
<code className="text-[11px] font-mono text-cyan-400/60 bg-cyan-400/[0.05] px-2 py-1 rounded">
|
|
34
|
+
{code}
|
|
35
|
+
</code>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default function FeaturesGrid() {
|
|
42
|
+
return (
|
|
43
|
+
<section id="features" className="py-24 px-4">
|
|
44
|
+
<div className="max-w-6xl mx-auto">
|
|
45
|
+
<p className="text-sm text-cyan-400 font-mono text-center mb-3 uppercase tracking-widest">
|
|
46
|
+
// capabilities
|
|
47
|
+
</p>
|
|
48
|
+
<h2 className="text-3xl sm:text-4xl font-bold text-[#F8FAFC] text-center mb-4">
|
|
49
|
+
Everything you need for compliance
|
|
50
|
+
</h2>
|
|
51
|
+
<p className="text-[#94A3B8] text-center mb-16 max-w-2xl mx-auto">
|
|
52
|
+
Purpose-built screening infrastructure replacing expensive legacy tools.
|
|
53
|
+
</p>
|
|
54
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
55
|
+
{features.map(f => <Card key={f.title} {...f} />)}
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</section>
|
|
59
|
+
)
|
|
60
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { motion } from 'framer-motion'
|
|
2
|
+
import { SlideIn, FadeUp } from './animations'
|
|
3
|
+
|
|
4
|
+
const features = [
|
|
5
|
+
{ label: 'Screening', title: 'Sub-1ms Sanctions Screening',
|
|
6
|
+
desc: 'Screen any entity against 3M+ profiles from 86 lists. 6-layer AI engine with every match explained.',
|
|
7
|
+
code: 'POST /api/v1/screen\n{ "entity_name": "Hassan Ali" }\n\n→ 200 OK (1ms)\n{ "total_matches": 4,\n "confidence": 0.94 }',
|
|
8
|
+
},
|
|
9
|
+
{ label: 'AI Cascade', title: 'Claude AI Disambiguation',
|
|
10
|
+
desc: 'Uncertain matches sent to Claude AI. Reduces false positives by 92%. No other vendor has this.',
|
|
11
|
+
code: 'Score: 0.62 (uncertain)\n→ Claude: "Common Arabic name\n pattern, Hassan is family"\n→ Confidence → 0.85 ✓',
|
|
12
|
+
},
|
|
13
|
+
{ label: 'Crypto', title: 'Wallet Sanctions Screening',
|
|
14
|
+
desc: 'Screen ETH/BTC/TRX wallets against 13,674 sanctioned addresses. Sub-microsecond lookup.',
|
|
15
|
+
code: 'POST /api/v1/crypto/screen\n{ "wallet": "0x7d84...ab4e" }\n\n→ { "decision": "BLOCKED",\n "list": "FBI Lazarus" }',
|
|
16
|
+
},
|
|
17
|
+
{ label: 'Freetext', title: 'Document Screening',
|
|
18
|
+
desc: 'Paste any document. AI extracts names and screens each against sanctions lists automatically.',
|
|
19
|
+
code: 'POST /api/v1/screen/freetext\n{ "text": "Wire to Sberbank\n for HAMAS..." }\n\n→ HAMAS: HIGH (94%)\n Sberbank: HIGH (94%)',
|
|
20
|
+
},
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
export default function FeaturesSpotlight() {
|
|
24
|
+
return (
|
|
25
|
+
<section id="features" className="py-28 px-4">
|
|
26
|
+
<div className="max-w-6xl mx-auto">
|
|
27
|
+
<FadeUp>
|
|
28
|
+
<p className="text-xs uppercase tracking-[0.2em] text-[#00B894] font-semibold text-center mb-3">
|
|
29
|
+
Capabilities
|
|
30
|
+
</p>
|
|
31
|
+
<h2 className="text-3xl sm:text-4xl lg:text-5xl font-bold text-[#0F172A] text-center mb-20"
|
|
32
|
+
style={{ letterSpacing: '-0.03em' }}>
|
|
33
|
+
Everything you need for compliance
|
|
34
|
+
</h2>
|
|
35
|
+
</FadeUp>
|
|
36
|
+
|
|
37
|
+
{features.map((f, i) => {
|
|
38
|
+
const reverse = i % 2 === 1
|
|
39
|
+
return (
|
|
40
|
+
<div key={f.title} className="grid md:grid-cols-2 gap-16 items-center mb-28">
|
|
41
|
+
<SlideIn from={reverse ? 'right' : 'left'}>
|
|
42
|
+
<div className={reverse ? 'md:order-2' : ''}>
|
|
43
|
+
<span className="text-xs uppercase tracking-[0.2em] text-[#00B894] font-semibold">{f.label}</span>
|
|
44
|
+
<h3 className="text-2xl lg:text-3xl font-bold text-[#0F172A] mt-3 mb-4"
|
|
45
|
+
style={{ letterSpacing: '-0.02em' }}>{f.title}</h3>
|
|
46
|
+
<p className="text-[#64748B] leading-relaxed text-[15px]">{f.desc}</p>
|
|
47
|
+
</div>
|
|
48
|
+
</SlideIn>
|
|
49
|
+
<SlideIn from={reverse ? 'left' : 'right'} delay={0.15}>
|
|
50
|
+
<motion.pre
|
|
51
|
+
className={`text-sm leading-relaxed p-6 rounded-2xl overflow-x-auto text-[#334155] ${reverse ? 'md:order-1' : ''}`}
|
|
52
|
+
style={{
|
|
53
|
+
fontFamily: "'JetBrains Mono', monospace",
|
|
54
|
+
background: '#F8FAFC',
|
|
55
|
+
border: '1px solid rgba(0,0,0,0.06)',
|
|
56
|
+
boxShadow: '0 4px 20px rgba(0,0,0,0.04)',
|
|
57
|
+
}}
|
|
58
|
+
whileHover={{ boxShadow: '0 8px 30px rgba(0,0,0,0.08)' }}>
|
|
59
|
+
{f.code}
|
|
60
|
+
</motion.pre>
|
|
61
|
+
</SlideIn>
|
|
62
|
+
</div>
|
|
63
|
+
)
|
|
64
|
+
})}
|
|
65
|
+
</div>
|
|
66
|
+
</section>
|
|
67
|
+
)
|
|
68
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Link } from 'react-router-dom'
|
|
2
|
+
import { ShieldCheck, Twitter, Linkedin } from 'lucide-react'
|
|
3
|
+
|
|
4
|
+
const columns = [
|
|
5
|
+
{ title: 'Product', links: [
|
|
6
|
+
{ label: 'Screening', href: '#screening' },
|
|
7
|
+
{ label: 'Monitoring', href: '#monitoring' },
|
|
8
|
+
{ label: 'API Reference', href: '#api' },
|
|
9
|
+
{ label: 'Pricing', href: '#pricing' },
|
|
10
|
+
]},
|
|
11
|
+
{ title: 'Solutions', links: [
|
|
12
|
+
{ label: 'Banks', href: '#' },
|
|
13
|
+
{ label: 'Fintechs', href: '#' },
|
|
14
|
+
{ label: 'MSBs', href: '#' },
|
|
15
|
+
{ label: 'Crypto', href: '#' },
|
|
16
|
+
]},
|
|
17
|
+
{ title: 'Company', links: [
|
|
18
|
+
{ label: 'About', href: '/about' },
|
|
19
|
+
{ label: 'Blog', href: '/blog' },
|
|
20
|
+
{ label: 'Careers', href: '/careers' },
|
|
21
|
+
{ label: 'Contact', href: 'mailto:info@amliq.finance' },
|
|
22
|
+
]},
|
|
23
|
+
{ title: 'Resources', links: [
|
|
24
|
+
{ label: 'Documentation', href: '/docs' },
|
|
25
|
+
{ label: 'Status', href: '/status' },
|
|
26
|
+
{ label: 'Changelog', href: '/changelog' },
|
|
27
|
+
{ label: 'Security', href: '/security' },
|
|
28
|
+
]},
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
const badges = ['SOC 2 Type II', 'ISO 27001', 'GDPR']
|
|
32
|
+
const socials = [
|
|
33
|
+
{ icon: <Twitter size={16} />, href: '#', label: 'Twitter' },
|
|
34
|
+
{ icon: <Linkedin size={16} />, href: '#', label: 'LinkedIn' },
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
export default function FooterSection() {
|
|
38
|
+
return (
|
|
39
|
+
<footer style={{ borderTop: '1px solid rgba(255,255,255,0.06)' }} className="pt-16 pb-8 px-4">
|
|
40
|
+
<div className="max-w-6xl mx-auto">
|
|
41
|
+
<div className="grid grid-cols-2 md:grid-cols-5 gap-8 mb-12">
|
|
42
|
+
<div className="col-span-2 md:col-span-1">
|
|
43
|
+
<span className="text-lg font-bold text-[#EDEDEF] flex items-center gap-1">
|
|
44
|
+
AMLIQ<span className="w-1.5 h-1.5 rounded-full bg-[#00D4AA] -mt-2" />
|
|
45
|
+
</span>
|
|
46
|
+
<p className="text-sm text-[#7C7C82] leading-relaxed mt-2">
|
|
47
|
+
AI-powered sanctions screening for modern finance.
|
|
48
|
+
</p>
|
|
49
|
+
<div className="flex gap-3 mt-4">
|
|
50
|
+
{socials.map(s => (
|
|
51
|
+
<a key={s.label} href={s.href} aria-label={s.label}
|
|
52
|
+
className="text-[#7C7C82] hover:text-[#EDEDEF] transition-colors">
|
|
53
|
+
{s.icon}
|
|
54
|
+
</a>
|
|
55
|
+
))}
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
{columns.map(col => (
|
|
59
|
+
<div key={col.title}>
|
|
60
|
+
<p className="text-sm font-semibold text-[#EDEDEF] mb-4">{col.title}</p>
|
|
61
|
+
<ul className="space-y-2.5">
|
|
62
|
+
{col.links.map(l => (
|
|
63
|
+
<li key={l.label}>
|
|
64
|
+
<Link to={l.href} className="text-sm text-[#7C7C82] hover:text-[#EDEDEF] transition-colors">
|
|
65
|
+
{l.label}
|
|
66
|
+
</Link>
|
|
67
|
+
</li>
|
|
68
|
+
))}
|
|
69
|
+
</ul>
|
|
70
|
+
</div>
|
|
71
|
+
))}
|
|
72
|
+
</div>
|
|
73
|
+
<div className="pt-6 flex flex-col md:flex-row items-center justify-between gap-4"
|
|
74
|
+
style={{ borderTop: '1px solid rgba(255,255,255,0.06)' }}>
|
|
75
|
+
<p className="text-xs text-[#7C7C82]/60">
|
|
76
|
+
© 2026 AMLIQ. All rights reserved.
|
|
77
|
+
· <Link to="/privacy" className="hover:text-[#EDEDEF]">Privacy</Link>
|
|
78
|
+
· <Link to="/terms" className="hover:text-[#EDEDEF]">Terms</Link>
|
|
79
|
+
</p>
|
|
80
|
+
<div className="flex items-center gap-4">
|
|
81
|
+
{badges.map(b => (
|
|
82
|
+
<div key={b} className="flex items-center gap-1.5 text-xs text-[#7C7C82]/60">
|
|
83
|
+
<ShieldCheck size={12} className="text-[#22C55E]" />
|
|
84
|
+
{b}
|
|
85
|
+
</div>
|
|
86
|
+
))}
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
</footer>
|
|
91
|
+
)
|
|
92
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { motion } from 'framer-motion'
|
|
2
|
+
|
|
3
|
+
export default function GradientOrbs() {
|
|
4
|
+
return (
|
|
5
|
+
<div className="absolute inset-0 overflow-hidden pointer-events-none -z-10">
|
|
6
|
+
<motion.div
|
|
7
|
+
className="absolute w-[600px] h-[600px] rounded-full opacity-[0.07]"
|
|
8
|
+
style={{ background: 'radial-gradient(circle, #00B894, transparent 70%)', top: '-10%', right: '-10%' }}
|
|
9
|
+
animate={{ x: [0, 30, 0], y: [0, -20, 0] }}
|
|
10
|
+
transition={{ duration: 18, repeat: Infinity, ease: 'easeInOut' }}
|
|
11
|
+
/>
|
|
12
|
+
<motion.div
|
|
13
|
+
className="absolute w-[500px] h-[500px] rounded-full opacity-[0.05]"
|
|
14
|
+
style={{ background: 'radial-gradient(circle, #6366F1, transparent 70%)', bottom: '10%', left: '-8%' }}
|
|
15
|
+
animate={{ x: [0, -25, 0], y: [0, 30, 0] }}
|
|
16
|
+
transition={{ duration: 22, repeat: Infinity, ease: 'easeInOut' }}
|
|
17
|
+
/>
|
|
18
|
+
<motion.div
|
|
19
|
+
className="absolute w-[400px] h-[400px] rounded-full opacity-[0.04]"
|
|
20
|
+
style={{ background: 'radial-gradient(circle, #F59E0B, transparent 70%)', top: '40%', right: '20%' }}
|
|
21
|
+
animate={{ x: [0, 20, 0], y: [0, -25, 0] }}
|
|
22
|
+
transition={{ duration: 15, repeat: Infinity, ease: 'easeInOut' }}
|
|
23
|
+
/>
|
|
24
|
+
</div>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { useState } from 'react'
|
|
2
|
+
import { Search, AlertTriangle, CheckCircle } from 'lucide-react'
|
|
3
|
+
|
|
4
|
+
const API_BASE = import.meta.env.VITE_API_URL || 'http://localhost:8080'
|
|
5
|
+
|
|
6
|
+
interface Match {
|
|
7
|
+
entity_name: string; list_id: string; confidence: number;
|
|
8
|
+
layers: { layer: string; score: number }[];
|
|
9
|
+
}
|
|
10
|
+
interface Result {
|
|
11
|
+
total_matches: number; processing_time_ms: number; matches: Match[];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default function HeroSearch() {
|
|
15
|
+
const [query, setQuery] = useState('')
|
|
16
|
+
const [result, setResult] = useState<Result | null>(null)
|
|
17
|
+
const [loading, setLoading] = useState(false)
|
|
18
|
+
|
|
19
|
+
const search = async () => {
|
|
20
|
+
if (!query.trim()) return
|
|
21
|
+
setLoading(true)
|
|
22
|
+
try {
|
|
23
|
+
const resp = await fetch(`${API_BASE}/api/v1/screen/public-demo`, {
|
|
24
|
+
method: 'POST',
|
|
25
|
+
headers: { 'Content-Type': 'application/json' },
|
|
26
|
+
body: JSON.stringify({ name: query.trim() }),
|
|
27
|
+
})
|
|
28
|
+
const json = await resp.json()
|
|
29
|
+
setResult(json.data ?? json)
|
|
30
|
+
} catch {
|
|
31
|
+
setResult(null)
|
|
32
|
+
} finally {
|
|
33
|
+
setLoading(false)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const handleKey = (e: React.KeyboardEvent) => {
|
|
38
|
+
if (e.key === 'Enter') search()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const top = result?.matches?.[0]
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<div className="max-w-2xl mx-auto mt-14 font-mono">
|
|
45
|
+
<div className="relative">
|
|
46
|
+
<Search size={16} className="absolute left-4 top-1/2 -translate-y-1/2 text-cyan-500/60" />
|
|
47
|
+
<input type="text" value={query}
|
|
48
|
+
onChange={e => setQuery(e.target.value)}
|
|
49
|
+
onKeyDown={handleKey}
|
|
50
|
+
placeholder="Try it: Vladimir Putin, HAMAS, Sberbank..."
|
|
51
|
+
className="w-full bg-white/[0.03] border border-cyan-400/20 rounded-lg pl-11 pr-24 py-3 text-cyan-300 text-sm focus:outline-none focus:border-cyan-400/40"
|
|
52
|
+
style={{ boxShadow: '0 0 10px rgba(0,255,255,0.05)' }} />
|
|
53
|
+
<button onClick={search} disabled={loading || !query.trim()}
|
|
54
|
+
className="absolute right-2 top-1/2 -translate-y-1/2 px-4 py-1.5 bg-[#00D4AA] text-[#0A0A0B] text-xs font-semibold rounded-md disabled:opacity-40 cursor-pointer">
|
|
55
|
+
{loading ? '...' : 'Screen'}
|
|
56
|
+
</button>
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
{result && (
|
|
60
|
+
<div className="mt-3 rounded-lg border overflow-hidden"
|
|
61
|
+
style={{ background: 'rgba(255,255,255,0.02)', borderColor: 'rgba(0,255,255,0.15)' }}>
|
|
62
|
+
<div className="px-4 py-2 border-b border-cyan-400/10 flex items-center justify-between">
|
|
63
|
+
<span className="text-[10px] text-cyan-500/60 uppercase tracking-widest">AMLIQ Live</span>
|
|
64
|
+
<span className="text-[10px] text-[#94A3B8] flex items-center gap-1.5">
|
|
65
|
+
<span className="w-1.5 h-1.5 bg-emerald-400 rounded-full" />
|
|
66
|
+
{result.processing_time_ms}ms — {result.total_matches} matches
|
|
67
|
+
</span>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
{top ? (
|
|
71
|
+
<>
|
|
72
|
+
<div className="px-4 pt-3 flex items-center justify-between">
|
|
73
|
+
<div>
|
|
74
|
+
<p className="text-[#F8FAFC] font-semibold text-sm">{top.entity_name}</p>
|
|
75
|
+
<p className="text-cyan-500/50 text-xs mt-0.5">{top.list_id}</p>
|
|
76
|
+
</div>
|
|
77
|
+
<div className="text-right">
|
|
78
|
+
<p className="text-2xl font-bold text-[#22C55E]">
|
|
79
|
+
{Math.round(top.confidence * 100)}%
|
|
80
|
+
</p>
|
|
81
|
+
<p className="text-[10px] text-[#94A3B8]">confidence</p>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
<div className="px-4 pt-3 grid grid-cols-4 gap-1.5">
|
|
85
|
+
{(top.layers ?? []).slice(0, 4).map(l => (
|
|
86
|
+
<div key={l.layer} className="text-center">
|
|
87
|
+
<div className="h-1 rounded-full bg-white/10 mb-1 overflow-hidden">
|
|
88
|
+
<div className="h-full rounded-full"
|
|
89
|
+
style={{ width: `${l.score * 100}%`, background: 'linear-gradient(90deg, #22C55E, #00FFFF)' }} />
|
|
90
|
+
</div>
|
|
91
|
+
<p className="text-[9px] text-[#94A3B8]">{l.layer}</p>
|
|
92
|
+
</div>
|
|
93
|
+
))}
|
|
94
|
+
</div>
|
|
95
|
+
<div className="px-4 py-3 flex items-center justify-between">
|
|
96
|
+
<span className="inline-flex items-center gap-1.5 px-3 py-1 bg-red-500/10 border border-red-500/20 rounded text-xs font-semibold text-[#EF4444]">
|
|
97
|
+
<AlertTriangle size={12} /> HIGH RISK
|
|
98
|
+
</span>
|
|
99
|
+
<span className="text-[10px] text-cyan-500/40">{result.total_matches} total matches</span>
|
|
100
|
+
</div>
|
|
101
|
+
</>
|
|
102
|
+
) : (
|
|
103
|
+
<div className="px-4 py-6 text-center">
|
|
104
|
+
<CheckCircle size={24} className="text-emerald-400 mx-auto mb-2" />
|
|
105
|
+
<p className="text-emerald-400 text-sm font-semibold">No Matches</p>
|
|
106
|
+
<p className="text-[10px] text-[#94A3B8] mt-1">Entity cleared against all lists</p>
|
|
107
|
+
</div>
|
|
108
|
+
)}
|
|
109
|
+
</div>
|
|
110
|
+
)}
|
|
111
|
+
</div>
|
|
112
|
+
)
|
|
113
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { useNavigate } from 'react-router-dom'
|
|
2
|
+
import { motion } from 'framer-motion'
|
|
3
|
+
import GradientOrbs from './GradientOrbs'
|
|
4
|
+
|
|
5
|
+
const words = 'Screen sanctions in milliseconds, not minutes'.split(' ')
|
|
6
|
+
|
|
7
|
+
export default function HeroSection() {
|
|
8
|
+
const navigate = useNavigate()
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<section className="relative pt-32 pb-20 px-4 overflow-hidden">
|
|
12
|
+
<GradientOrbs />
|
|
13
|
+
|
|
14
|
+
<div className="relative max-w-4xl mx-auto text-center z-10">
|
|
15
|
+
<motion.p
|
|
16
|
+
className="flex items-center justify-center gap-2 text-sm text-[#64748B] mb-8"
|
|
17
|
+
initial={{ opacity: 0, y: 12 }}
|
|
18
|
+
animate={{ opacity: 1, y: 0 }}
|
|
19
|
+
transition={{ duration: 0.6, delay: 0.2 }}>
|
|
20
|
+
<span className="w-1.5 h-1.5 rounded-full bg-[#00B894] animate-pulse" />
|
|
21
|
+
AI-powered sanctions screening · Free to start
|
|
22
|
+
</motion.p>
|
|
23
|
+
|
|
24
|
+
<h1 className="text-4xl sm:text-5xl lg:text-[64px] font-bold leading-[1.1] mb-6"
|
|
25
|
+
style={{ letterSpacing: '-0.03em' }}>
|
|
26
|
+
{words.map((word, i) => (
|
|
27
|
+
<motion.span key={i} className="inline-block mr-[0.3em] text-[#0F172A]"
|
|
28
|
+
initial={{ opacity: 0, y: 24, filter: 'blur(4px)' }}
|
|
29
|
+
animate={{ opacity: 1, y: 0, filter: 'blur(0px)' }}
|
|
30
|
+
transition={{ duration: 0.5, delay: 0.3 + i * 0.06, ease: [0.25, 0.4, 0, 1] }}>
|
|
31
|
+
{word}
|
|
32
|
+
</motion.span>
|
|
33
|
+
))}
|
|
34
|
+
</h1>
|
|
35
|
+
|
|
36
|
+
<motion.p
|
|
37
|
+
className="text-lg text-[#64748B] max-w-2xl mx-auto leading-relaxed mb-10"
|
|
38
|
+
initial={{ opacity: 0, y: 16 }}
|
|
39
|
+
animate={{ opacity: 1, y: 0 }}
|
|
40
|
+
transition={{ duration: 0.7, delay: 0.9 }}>
|
|
41
|
+
6-layer AI matching catches what keyword search misses.
|
|
42
|
+
<br className="hidden sm:block" />
|
|
43
|
+
86 global lists — 3M+ entities. Explainable results.
|
|
44
|
+
<br className="hidden sm:block" />
|
|
45
|
+
From first API call to production in under 5 minutes.
|
|
46
|
+
</motion.p>
|
|
47
|
+
|
|
48
|
+
<motion.div
|
|
49
|
+
className="flex flex-col sm:flex-row gap-4 justify-center"
|
|
50
|
+
initial={{ opacity: 0, y: 16 }}
|
|
51
|
+
animate={{ opacity: 1, y: 0 }}
|
|
52
|
+
transition={{ duration: 0.6, delay: 1.1 }}>
|
|
53
|
+
<motion.button type="button" onClick={() => navigate('/signup')}
|
|
54
|
+
className="px-8 py-3.5 bg-[#00B894] text-white font-semibold rounded-xl text-sm cursor-pointer"
|
|
55
|
+
whileHover={{ scale: 1.04, boxShadow: '0 8px 30px rgba(0,184,148,0.3)' }}
|
|
56
|
+
whileTap={{ scale: 0.98 }}
|
|
57
|
+
transition={{ type: 'spring', stiffness: 400, damping: 17 }}>
|
|
58
|
+
Start Free
|
|
59
|
+
</motion.button>
|
|
60
|
+
<motion.button type="button"
|
|
61
|
+
onClick={() => window.open('https://calendly.com/amliq', '_blank')}
|
|
62
|
+
className="px-8 py-3.5 text-[#1A1A2E] font-medium rounded-xl text-sm cursor-pointer border border-[#E2E8F0]"
|
|
63
|
+
whileHover={{ scale: 1.04, backgroundColor: '#F8FAFC' }}
|
|
64
|
+
whileTap={{ scale: 0.98 }}
|
|
65
|
+
transition={{ type: 'spring', stiffness: 400, damping: 17 }}>
|
|
66
|
+
Watch Demo
|
|
67
|
+
</motion.button>
|
|
68
|
+
</motion.div>
|
|
69
|
+
</div>
|
|
70
|
+
</section>
|
|
71
|
+
)
|
|
72
|
+
}
|