455 lines
15 KiB
TypeScript
455 lines
15 KiB
TypeScript
import { createSignal, For, Show } from "solid-js";
|
|
import { Title } from "@solidjs/meta";
|
|
import { A, useSearchParams } from "@solidjs/router";
|
|
import { cn } from "~/lib/utils";
|
|
import { Badge, Button, Card } from "~/components/ui";
|
|
import PageContainer from "~/components/layout/PageContainer";
|
|
|
|
interface Plan {
|
|
name: string;
|
|
price: string;
|
|
period: string;
|
|
description: string;
|
|
features: string[];
|
|
cta: string;
|
|
popular: boolean;
|
|
}
|
|
|
|
interface FAQ {
|
|
q: string;
|
|
a: string;
|
|
}
|
|
|
|
const plans: Plan[] = [
|
|
{
|
|
name: "Basic",
|
|
price: "$9",
|
|
period: "/month",
|
|
description: "Essential identity protection for individuals",
|
|
features: [
|
|
"Dark web monitoring",
|
|
"Email breach alerts",
|
|
"Basic scam call blocking",
|
|
"Monthly reports",
|
|
],
|
|
cta: "Start Free Trial",
|
|
popular: false,
|
|
},
|
|
{
|
|
name: "Plus",
|
|
price: "$19",
|
|
period: "/month",
|
|
description: "Advanced protection for you and your family",
|
|
features: [
|
|
"Everything in Basic",
|
|
"VoicePrint AI detection",
|
|
"HomeTitle fraud alerts",
|
|
"RemoveBrokers automation",
|
|
"Family sharing (up to 5)",
|
|
],
|
|
cta: "Start Free Trial",
|
|
popular: true,
|
|
},
|
|
{
|
|
name: "Premium",
|
|
price: "$39",
|
|
period: "/month",
|
|
description: "Maximum security for the whole household",
|
|
features: [
|
|
"Everything in Plus",
|
|
"Unlimited family members",
|
|
"Priority support 24/7",
|
|
"Real-time alert correlation",
|
|
"Advanced analytics dashboard",
|
|
"Data broker suppression",
|
|
],
|
|
cta: "Start Free Trial",
|
|
popular: false,
|
|
},
|
|
];
|
|
|
|
const faqs: FAQ[] = [
|
|
{
|
|
q: "How does Kordant detect voice clones?",
|
|
a: "VoicePrint analyzes over 200 acoustic features in real-time, including micro-tremors and breathing patterns that AI clones can't replicate accurately.",
|
|
},
|
|
{
|
|
q: "Is my data encrypted?",
|
|
a: "Yes. All data is encrypted at rest using AES-256 and in transit using TLS 1.3. We never share or sell your personal information.",
|
|
},
|
|
{
|
|
q: "Can I protect my whole family?",
|
|
a: "Absolutely. Plus and Premium plans include family sharing with centralized monitoring and alert management for all household members.",
|
|
},
|
|
{
|
|
q: "How does dark web monitoring work?",
|
|
a: "DarkWatch continuously scans dark web forums, marketplaces, and data dumps for your email addresses, phone numbers, and other personal data.",
|
|
},
|
|
{
|
|
q: "What happens after my free trial?",
|
|
a: "Your trial includes Basic features for 14 days. Upgrade anytime during your trial to unlock Plus or Premium features immediately. If you don't upgrade, your account will remain active with Basic features.",
|
|
},
|
|
{
|
|
q: "Can I remove my data from brokers?",
|
|
a: "Yes. RemoveBrokers automates opt-out requests to over 200 data broker sites and verifies removal on your behalf.",
|
|
},
|
|
];
|
|
|
|
const comparisonFeatures = [
|
|
{ feature: "Dark web monitoring", basic: true, plus: true, premium: true },
|
|
{ feature: "Email breach alerts", basic: true, plus: true, premium: true },
|
|
{
|
|
feature: "Basic scam call blocking",
|
|
basic: true,
|
|
plus: true,
|
|
premium: true,
|
|
},
|
|
{ feature: "Monthly reports", basic: true, plus: true, premium: true },
|
|
{
|
|
feature: "VoicePrint AI detection",
|
|
basic: false,
|
|
plus: true,
|
|
premium: true,
|
|
},
|
|
{
|
|
feature: "HomeTitle fraud alerts",
|
|
basic: false,
|
|
plus: true,
|
|
premium: true,
|
|
},
|
|
{
|
|
feature: "RemoveBrokers automation",
|
|
basic: false,
|
|
plus: true,
|
|
premium: true,
|
|
},
|
|
{
|
|
feature: "Family sharing",
|
|
basic: false,
|
|
plus: "Up to 5",
|
|
premium: "Unlimited",
|
|
},
|
|
{
|
|
feature: "Priority support 24/7",
|
|
basic: false,
|
|
plus: false,
|
|
premium: true,
|
|
},
|
|
{
|
|
feature: "Real-time alert correlation",
|
|
basic: false,
|
|
plus: false,
|
|
premium: true,
|
|
},
|
|
{ feature: "Advanced analytics", basic: false, plus: false, premium: true },
|
|
{
|
|
feature: "Data broker suppression",
|
|
basic: false,
|
|
plus: false,
|
|
premium: true,
|
|
},
|
|
];
|
|
|
|
function CheckIcon() {
|
|
return (
|
|
<svg
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 16 16"
|
|
fill="none"
|
|
class="flex-shrink-0"
|
|
>
|
|
<path
|
|
d="M6.5 11.5L3 8l1.1-1.1L6.5 9.3l5.9-5.9L13.5 4.5l-7 7z"
|
|
fill="var(--color-success)"
|
|
/>
|
|
</svg>
|
|
);
|
|
}
|
|
|
|
function XIcon() {
|
|
return (
|
|
<svg
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 16 16"
|
|
fill="none"
|
|
class="flex-shrink-0"
|
|
>
|
|
<path
|
|
d="M4 4l8 8M12 4l-8 8"
|
|
stroke="var(--color-text-muted)"
|
|
stroke-width="1.5"
|
|
stroke-linecap="round"
|
|
/>
|
|
</svg>
|
|
);
|
|
}
|
|
|
|
export default function PricingPage() {
|
|
const [searchParams] = useSearchParams();
|
|
const [openFaq, setOpenFaq] = createSignal<string | null>(null);
|
|
|
|
const signupUrl = () =>
|
|
`/signup${
|
|
searchParams.utm_source
|
|
? `?utm_source=${searchParams.utm_source}&utm_medium=${
|
|
searchParams.utm_medium || ""
|
|
}&utm_campaign=${searchParams.utm_campaign || ""}`
|
|
: ""
|
|
}`;
|
|
|
|
const planToId: Record<string, string> = {
|
|
Basic: "basic",
|
|
Plus: "plus",
|
|
Premium: "premium",
|
|
};
|
|
|
|
return (
|
|
<main>
|
|
<Title>Kordant Pricing — AI-Powered Identity Protection Plans</Title>
|
|
|
|
<section class="relative py-20 md:py-28 overflow-hidden">
|
|
<div class="absolute inset-0 bg-linear-to-b from-(--color-brand-primary)/5 to-transparent" />
|
|
<PageContainer class="relative z-10">
|
|
<div class="text-center max-w-3xl mx-auto">
|
|
<Badge variant="info" class="mb-4">
|
|
Simple Pricing
|
|
</Badge>
|
|
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold text-text-primary mb-6">
|
|
Protection That Fits{" "}
|
|
<span class="text-gradient-primary">Your Budget</span>
|
|
</h1>
|
|
<p class="text-xl text-text-secondary mb-8 max-w-2xl mx-auto">
|
|
Start with a 14-day free trial of Basic features. No credit card
|
|
required. Upgrade anytime to unlock Plus or Premium.
|
|
</p>
|
|
<div class="flex flex-wrap items-center justify-center gap-x-6 gap-y-2 text-sm text-text-tertiary">
|
|
<span class="flex items-center gap-1.5">
|
|
<CheckIcon />
|
|
14-day free trial
|
|
</span>
|
|
<span class="flex items-center gap-1.5">
|
|
<CheckIcon />
|
|
No credit card required
|
|
</span>
|
|
<span class="flex items-center gap-1.5">
|
|
<CheckIcon />
|
|
Cancel anytime
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</PageContainer>
|
|
</section>
|
|
|
|
<section class="py-20 md:py-28">
|
|
<PageContainer>
|
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 max-w-5xl mx-auto">
|
|
<For each={plans}>
|
|
{(plan) => (
|
|
<Card
|
|
class={cn(
|
|
"relative flex flex-col",
|
|
plan.popular &&
|
|
"ring-2 ring-(--color-brand-primary) shadow-glow-primary",
|
|
)}
|
|
>
|
|
<Show when={plan.popular}>
|
|
<div class="absolute -top-3 left-1/2 -translate-x-1/2">
|
|
<Badge variant="info">Most Popular</Badge>
|
|
</div>
|
|
</Show>
|
|
<div class="mb-6">
|
|
<h3 class="text-lg font-semibold text-text-primary mb-1">
|
|
{plan.name}
|
|
</h3>
|
|
<p class="text-sm text-text-secondary mb-4">
|
|
{plan.description}
|
|
</p>
|
|
<div class="flex items-baseline gap-0.5">
|
|
<span class="text-4xl font-bold text-text-primary">
|
|
{plan.price}
|
|
</span>
|
|
<span class="text-sm text-text-tertiary">
|
|
{plan.period}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<ul class="space-y-3 mb-8 flex-1">
|
|
<For each={plan.features}>
|
|
{(feature) => (
|
|
<li class="flex items-start gap-2 text-sm text-text-secondary">
|
|
<CheckIcon />
|
|
{feature}
|
|
</li>
|
|
)}
|
|
</For>
|
|
</ul>
|
|
<A href={`/billing/checkout?plan=${planToId[plan.name]}`}>
|
|
<Button
|
|
variant={plan.popular ? "primary" : "secondary"}
|
|
class="w-full"
|
|
>
|
|
{plan.cta}
|
|
</Button>
|
|
</A>
|
|
</Card>
|
|
)}
|
|
</For>
|
|
</div>
|
|
</PageContainer>
|
|
</section>
|
|
|
|
<section class="py-16 bg-[var(--color-bg-secondary)]">
|
|
<PageContainer>
|
|
<div class="text-center mb-12">
|
|
<h2 class="text-3xl md:text-4xl font-bold text-[var(--color-text-primary)] mb-4">
|
|
Compare Plans
|
|
</h2>
|
|
</div>
|
|
<div class="max-w-4xl mx-auto overflow-x-auto">
|
|
<table class="w-full">
|
|
<thead>
|
|
<tr class="border-b-2 border-[var(--color-border)]">
|
|
<th class="text-left px-4 py-3 text-sm font-medium text-[var(--color-text-secondary)]">
|
|
Feature
|
|
</th>
|
|
<th class="text-center px-4 py-3 text-sm font-medium text-[var(--color-text-secondary)]">
|
|
Basic
|
|
</th>
|
|
<th class="text-center px-4 py-3 text-sm font-semibold text-[var(--color-brand-primary)]">
|
|
Plus
|
|
</th>
|
|
<th class="text-center px-4 py-3 text-sm font-medium text-[var(--color-text-secondary)]">
|
|
Premium
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<For each={comparisonFeatures}>
|
|
{(row) => (
|
|
<tr class="border-b border-[var(--color-border)]">
|
|
<td class="px-4 py-3 text-sm text-[var(--color-text-primary)]">
|
|
{row.feature}
|
|
</td>
|
|
<td class="text-center px-4 py-3">
|
|
{row.basic === true ? (
|
|
<CheckIcon />
|
|
) : row.basic === false ? (
|
|
<XIcon />
|
|
) : (
|
|
<span class="text-xs text-[var(--color-text-secondary)]">
|
|
{row.basic}
|
|
</span>
|
|
)}
|
|
</td>
|
|
<td class="text-center px-4 py-3">
|
|
{row.plus === true ? (
|
|
<CheckIcon />
|
|
) : row.plus === false ? (
|
|
<XIcon />
|
|
) : (
|
|
<span class="text-xs text-[var(--color-text-secondary)]">
|
|
{row.plus}
|
|
</span>
|
|
)}
|
|
</td>
|
|
<td class="text-center px-4 py-3">
|
|
{row.premium === true ? (
|
|
<CheckIcon />
|
|
) : row.premium === false ? (
|
|
<XIcon />
|
|
) : (
|
|
<span class="text-xs text-[var(--color-text-secondary)]">
|
|
{row.premium}
|
|
</span>
|
|
)}
|
|
</td>
|
|
</tr>
|
|
)}
|
|
</For>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</PageContainer>
|
|
</section>
|
|
|
|
<section class="py-20 md:py-28">
|
|
<PageContainer>
|
|
<div class="max-w-3xl mx-auto">
|
|
<div class="text-center mb-12">
|
|
<h2 class="text-3xl md:text-4xl font-bold text-[var(--color-text-primary)] mb-4">
|
|
Frequently Asked Questions
|
|
</h2>
|
|
</div>
|
|
<div class="space-y-3">
|
|
<For each={faqs}>
|
|
{(faq) => {
|
|
const isOpen = () => openFaq() === faq.q;
|
|
return (
|
|
<div class="border border-(--color-border) rounded-xl overflow-hidden">
|
|
<button
|
|
type="button"
|
|
class="w-full flex items-center justify-between px-5 py-4 text-left text-sm font-medium text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)] transition-colors"
|
|
onClick={() => setOpenFaq(isOpen() ? null : faq.q)}
|
|
>
|
|
{faq.q}
|
|
<svg
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 16 16"
|
|
fill="none"
|
|
class={cn(
|
|
"transition-transform duration-200",
|
|
isOpen() && "rotate-180",
|
|
)}
|
|
>
|
|
<path
|
|
d="M4 6l4 4 4-4"
|
|
stroke="currentColor"
|
|
stroke-width="1.5"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
/>
|
|
</svg>
|
|
</button>
|
|
<Show when={isOpen()}>
|
|
<div class="px-5 pb-4 text-sm text-[var(--color-text-secondary)] leading-relaxed">
|
|
{faq.a}
|
|
</div>
|
|
</Show>
|
|
</div>
|
|
);
|
|
}}
|
|
</For>
|
|
</div>
|
|
</div>
|
|
</PageContainer>
|
|
</section>
|
|
|
|
<section class="py-16 bg-(--color-brand-primary)">
|
|
<PageContainer>
|
|
<div class="text-center">
|
|
<h2 class="text-3xl md:text-4xl font-bold text-white mb-4">
|
|
Ready to protect your identity?
|
|
</h2>
|
|
<p class="text-lg text-white/80 mb-8 max-w-2xl mx-auto">
|
|
Join 50,000+ users who trust Kordant for AI-powered identity
|
|
protection.
|
|
</p>
|
|
<A href={signupUrl()}>
|
|
<Button
|
|
variant="primary"
|
|
size="lg"
|
|
class="bg-white text-[var(--color-brand-primary)] hover:bg-white/90 shadow-lg"
|
|
>
|
|
Get Started Free
|
|
</Button>
|
|
</A>
|
|
</div>
|
|
</PageContainer>
|
|
</section>
|
|
</main>
|
|
);
|
|
}
|