Files
padelnomics/scratch/padelnomics-supplier-signup (1).jsx
Deeman bc7fbcd595 chore: commit pending changes — logo, base template, scratch designs, changelog
- favicon.svg: pending logo tweaks
- base.html: pending template changes
- CHANGELOG.md: add waitlist mode and logo redesign entries missed in prior commits
- scratch/: add design prototype HTML/JSX files, remove old markdown notes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 23:45:42 +01:00

246 lines
26 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useState, useEffect } from "react";
const PLANS = [
{ id: "starter", name: "Starter", price: 0, period: "forever", credits: 10, tagline: "Test the waters", features: ["Basic supplier profile", "10 lead credits included", "Browse anonymized lead feed", "Email notifications for matching leads"] },
{ id: "growth", name: "Growth", price: 149, period: "/mo", credits: 30, tagline: "For active suppliers", popular: true, features: ["Everything in Starter", "30 lead credits/month", "Directory listing included", "Company logo on profile", "Priority in search results", "Monthly market report"] },
{ id: "pro", name: "Pro", price: 399, period: "/mo", credits: 100, tagline: "Dominate your market", features: ["Everything in Growth", "100 lead credits/month", "Verified supplier badge", "Featured in newsletter", "Custom brand color listing", "Quarterly strategy call", "Auto-unlock hot leads"] },
];
const ADDONS = [
{ id: "directory", name: "Directory Listing", description: "Appear in the Padelnomics supplier directory", price: 49, period: "/mo", boost: "+120% discoverability", icon: "📍", includedIn: ["growth", "pro"] },
{ id: "logo", name: "Logo Display", description: "Show your company logo on your listing and lead responses", price: 29, period: "/mo", boost: "+40% more clicks", icon: "🏷", includedIn: ["growth", "pro"] },
{ id: "highlight", name: "Highlighted Listing", description: "Stand out with a colored background in search results", price: 39, period: "/mo", boost: "+65% more views", icon: "✦", includedIn: [] },
{ id: "verified", name: "Verified Badge", description: "Earn trust with a verified supplier checkmark", price: 49, period: "/mo", boost: "+55% more inquiries", icon: "✓", includedIn: ["pro"] },
{ id: "sticky_week", name: "Sticky Top — 1 Week", description: "Pin your listing to the top of the directory for 7 days", price: 79, period: "one-time", boost: "2× more views", icon: "📌", includedIn: [] },
{ id: "sticky_month", name: "Sticky Top — 1 Month", description: "Pin to the top for 30 days", price: 199, period: "one-time", boost: "6× more views", icon: "🔝", includedIn: [] },
{ id: "newsletter", name: "Newsletter Feature", description: "Featured in our weekly newsletter to 2,400+ padel entrepreneurs", price: 99, period: "/mo", boost: "+120 impressions/wk", icon: "📨", includedIn: ["pro"] },
{ id: "brand_color", name: "Custom Brand Color", description: "Replace default highlight with your brand color", price: 59, period: "/mo", boost: "+80% brand recall", icon: "🎨", includedIn: ["pro"] },
];
const CREDIT_PACKS = [
{ amount: 25, price: 99, perCredit: "€3.96" },
{ amount: 50, price: 179, perCredit: "€3.58", popular: true },
{ amount: 100, price: 329, perCredit: "€3.29" },
{ amount: 250, price: 749, perCredit: "€3.00" },
];
const CATEGORIES = ["Court Construction", "Court Surfaces", "Lighting Systems", "Steel Structures", "Glass Walls", "Flooring", "Full Turnkey", "Consulting", "Architecture", "Financing"];
export default function App() {
const [step, setStep] = useState(1);
const [plan, setPlan] = useState("growth");
const [addons, setAddons] = useState(new Set());
const [credits, setCredits] = useState(null);
const [form, setForm] = useState({ company: "", name: "", email: "", country: "", categories: [] });
const [anim, setAnim] = useState(true);
useEffect(() => { setAnim(false); const t = setTimeout(() => setAnim(true), 50); return () => clearTimeout(t); }, [step]);
const toggle = (id) => { if (ADDONS.find(a => a.id === id).includedIn.includes(plan)) return; setAddons(p => { const n = new Set(p); n.has(id) ? n.delete(id) : n.add(id); return n; }); };
const incl = (id) => ADDONS.find(a => a.id === id).includedIn.includes(plan);
const active = (id) => incl(id) || addons.has(id);
const monthly = () => { let t = PLANS.find(p => p.id === plan).price; addons.forEach(id => { const a = ADDONS.find(x => x.id === id); if (a?.period === "/mo" && !a.includedIn.includes(plan)) t += a.price; }); return t; };
const oneTime = () => { let t = 0; addons.forEach(id => { const a = ADDONS.find(x => x.id === id); if (a?.period === "one-time" && !a.includedIn.includes(plan)) t += a.price; }); if (credits) t += CREDIT_PACKS.find(p => p.amount === credits)?.price || 0; return t; };
const totalCr = () => { let c = PLANS.find(p => p.id === plan).credits; if (credits) c += credits; return c; };
const vis = () => { let m = 1; ["directory","logo","highlight","verified","newsletter","brand_color","sticky_week","sticky_month"].forEach((id, i) => { if (active(id)) m += [0.5,0.3,0.6,0.4,0.8,0.5,0.8,2.0][i]; }); return m; };
const $ = {
bg: "#FFFFFF", soft: "#F8FAFC", muted: "#F1F5F9",
border: "#E2E8F0", borderDark: "#CBD5E1",
text: "#0F172A", sub: "#334155", dim: "#64748B", faint: "#94A3B8",
blue: "#1D4ED8", blueLight: "#3B82F6", bluePale: "#DBEAFE", blueGhost: "#EFF6FF", blueDark: "#1E40AF",
green: "#16A34A", greenPale: "#DCFCE7",
gold: "#D97706", goldPale: "#FEF3C7",
};
const font = "'Inter', -apple-system, BlinkMacSystemFont, sans-serif";
const mono = "'JetBrains Mono', 'SF Mono', monospace";
return (
<div style={{ minHeight: "100vh", background: $.soft, color: $.text, fontFamily: font }}>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
<div style={{ maxWidth: "960px", margin: "0 auto", padding: "32px 20px 80px" }}>
{/* Header */}
<div style={{ textAlign: "center", marginBottom: "36px" }}>
<div style={{ display: "inline-flex", alignItems: "center", gap: "10px", marginBottom: "14px" }}>
<div style={{ width: "34px", height: "34px", borderRadius: "10px", background: $.blue, display: "flex", alignItems: "center", justifyContent: "center", fontSize: "18px", fontWeight: 700, color: "#fff" }}>P</div>
<span style={{ fontSize: "20px", fontWeight: 700, letterSpacing: "-0.02em" }}>padelnomics</span>
</div>
<h1 style={{ fontSize: "clamp(24px, 4vw, 34px)", fontWeight: 700, letterSpacing: "-0.03em", margin: "12px 0 8px" }}>Supplier Platform</h1>
<p style={{ color: $.dim, fontSize: "16px", maxWidth: "440px", margin: "0 auto" }}>Get discovered by padel entrepreneurs. Unlock verified leads. Grow your business.</p>
</div>
{/* Progress */}
<div style={{ display: "flex", justifyContent: "center", marginBottom: "36px", alignItems: "center" }}>
{["Plan", "Boost", "Credits", "Account"].map((label, i) => {
const n = i + 1, on = step === n, done = step > n;
return (
<div key={label} style={{ display: "flex", alignItems: "center" }}>
<div onClick={() => done && setStep(n)} style={{ display: "flex", alignItems: "center", gap: "7px", cursor: done ? "pointer" : "default", padding: "6px 14px", borderRadius: "999px", background: on ? $.blueGhost : "transparent", border: `1.5px solid ${on ? $.blue : done ? $.blueLight : $.border}` }}>
<div style={{ width: "22px", height: "22px", borderRadius: "50%", background: done || on ? $.blue : "transparent", border: `2px solid ${done || on ? $.blue : $.borderDark}`, display: "flex", alignItems: "center", justifyContent: "center", fontSize: "11px", fontWeight: 700, color: done || on ? "#fff" : $.faint }}>{done ? "✓" : n}</div>
<span style={{ fontSize: "13px", fontWeight: on ? 600 : 400, color: on ? $.blue : done ? $.sub : $.faint }}>{label}</span>
</div>
{i < 3 && <div style={{ width: "28px", height: "2px", background: step > n ? $.blue : $.border }} />}
</div>
);
})}
</div>
<div style={{ opacity: anim ? 1 : 0, transform: anim ? "translateY(0)" : "translateY(10px)", transition: "all 0.3s cubic-bezier(0.16,1,0.3,1)" }}>
{/* STEP 1 */}
{step === 1 && (<div>
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(260px, 1fr))", gap: "16px", marginBottom: "28px" }}>
{PLANS.map(p => {
const sel = plan === p.id;
return (
<div key={p.id} onClick={() => setPlan(p.id)} style={{ position: "relative", background: sel ? $.blueGhost : $.bg, border: `2px solid ${sel ? $.blue : $.border}`, borderRadius: "16px", padding: "26px 22px", cursor: "pointer", boxShadow: sel ? "0 4px 20px rgba(29,78,216,0.10)" : "0 1px 3px rgba(0,0,0,0.04)" }}>
{p.popular && <div style={{ position: "absolute", top: "-1px", left: "50%", transform: "translateX(-50%)", background: $.blue, color: "#fff", fontSize: "10px", fontWeight: 700, padding: "3px 14px", borderRadius: "0 0 8px 8px", textTransform: "uppercase", letterSpacing: "0.04em" }}>Most Popular</div>}
<div style={{ fontSize: "12px", color: $.dim, marginBottom: "4px" }}>{p.tagline}</div>
<div style={{ fontSize: "20px", fontWeight: 700, marginBottom: "14px" }}>{p.name}</div>
<div style={{ display: "flex", alignItems: "baseline", gap: "3px", marginBottom: "6px" }}>
<span style={{ fontSize: "34px", fontWeight: 700, letterSpacing: "-0.03em" }}>{p.price === 0 ? "Free" : `${p.price}`}</span>
{p.price > 0 && <span style={{ fontSize: "14px", color: $.dim }}>{p.period}</span>}
</div>
<div style={{ display: "inline-flex", alignItems: "center", gap: "5px", background: $.bluePale, borderRadius: "999px", padding: "4px 12px", marginBottom: "18px" }}>
<span style={{ fontSize: "13px" }}></span>
<span style={{ fontSize: "13px", fontWeight: 600, color: $.blue, fontFamily: mono }}>{p.credits} credits{p.id !== "starter" ? "/mo" : ""}</span>
</div>
<div style={{ display: "flex", flexDirection: "column", gap: "8px" }}>
{p.features.map((f, i) => <div key={i} style={{ display: "flex", gap: "7px", fontSize: "13px" }}><span style={{ color: $.green, fontWeight: 700 }}></span><span style={{ color: $.dim, lineHeight: 1.4 }}>{f}</span></div>)}
</div>
<div style={{ position: "absolute", top: "22px", right: "22px", width: "20px", height: "20px", borderRadius: "50%", border: `2px solid ${sel ? $.blue : $.borderDark}`, background: sel ? $.blue : "transparent", display: "flex", alignItems: "center", justifyContent: "center" }}>{sel && <span style={{ fontSize: "11px", color: "#fff", fontWeight: 700 }}></span>}</div>
</div>
);
})}
</div>
<div style={{ display: "flex", justifyContent: "flex-end" }}>
<button onClick={() => setStep(2)} style={{ background: $.blue, color: "#fff", border: "none", borderRadius: "10px", padding: "12px 24px", fontSize: "14px", fontWeight: 600, cursor: "pointer", fontFamily: font, boxShadow: "0 2px 8px rgba(29,78,216,0.25)" }}>Continue with {PLANS.find(p => p.id === plan).name} </button>
</div>
</div>)}
{/* STEP 2 */}
{step === 2 && (<div>
<div style={{ textAlign: "center", marginBottom: "24px" }}>
<h2 style={{ fontSize: "22px", fontWeight: 700, margin: "0 0 6px" }}>Boost your visibility</h2>
<p style={{ color: $.dim, fontSize: "14px" }}>Add-ons to maximize your reach. Items in your plan show as included.</p>
</div>
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(280px, 1fr))", gap: "12px", marginBottom: "20px" }}>
{ADDONS.map(a => {
const inc = incl(a.id), act = active(a.id);
return (
<div key={a.id} onClick={() => toggle(a.id)} style={{ background: act ? $.blueGhost : $.bg, border: `1.5px solid ${act ? (inc ? $.blueLight : $.blue) : $.border}`, borderRadius: "14px", padding: "16px", cursor: inc ? "default" : "pointer", opacity: inc ? 0.6 : 1, position: "relative", boxShadow: "0 1px 3px rgba(0,0,0,0.04)" }}>
{inc && <div style={{ position: "absolute", top: "10px", right: "10px", background: $.bluePale, color: $.blue, fontSize: "10px", fontWeight: 700, padding: "2px 8px", borderRadius: "999px", textTransform: "uppercase" }}>Included</div>}
<div style={{ display: "flex", gap: "12px" }}>
<div style={{ width: "20px", height: "20px", borderRadius: "6px", border: `2px solid ${act ? $.blue : $.borderDark}`, background: act ? $.blue : "transparent", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, marginTop: "2px" }}>{act && <span style={{ fontSize: "11px", color: "#fff", fontWeight: 700 }}></span>}</div>
<div style={{ flex: 1 }}>
<div style={{ display: "flex", alignItems: "center", gap: "6px", marginBottom: "3px" }}><span style={{ fontSize: "14px" }}>{a.icon}</span><span style={{ fontSize: "14px", fontWeight: 600 }}>{a.name}</span></div>
<p style={{ fontSize: "12px", color: $.dim, lineHeight: 1.4, margin: "0 0 8px" }}>{a.description}</p>
<div style={{ display: "flex", alignItems: "center", gap: "10px" }}>
<span style={{ fontSize: "13px", fontWeight: 600, fontFamily: mono, color: inc ? $.faint : $.text, textDecoration: inc ? "line-through" : "none" }}>{a.price}<span style={{ fontSize: "11px", color: $.faint, marginLeft: "2px" }}>{a.period}</span></span>
<span style={{ fontSize: "11px", fontWeight: 600, color: $.blue, background: $.bluePale, padding: "2px 8px", borderRadius: "999px" }}>{a.boost}</span>
</div>
</div>
</div>
</div>
);
})}
</div>
<div style={{ background: $.bg, border: `1px solid ${$.border}`, borderRadius: "14px", padding: "16px 20px", marginBottom: "24px", display: "flex", alignItems: "center", justifyContent: "space-between", flexWrap: "wrap", gap: "12px", boxShadow: "0 1px 3px rgba(0,0,0,0.04)" }}>
<div>
<div style={{ fontSize: "12px", color: $.dim, marginBottom: "3px" }}>Your visibility multiplier</div>
<div style={{ display: "flex", alignItems: "baseline", gap: "5px" }}><span style={{ fontSize: "26px", fontWeight: 700, fontFamily: mono, color: vis() > 3 ? $.gold : $.blue }}>{vis().toFixed(1)}×</span><span style={{ fontSize: "12px", color: $.faint }}>vs. basic profile</span></div>
</div>
<div style={{ height: "8px", flex: "1 1 200px", maxWidth: "260px", background: $.muted, borderRadius: "999px", overflow: "hidden" }}>
<div style={{ height: "100%", width: `${Math.min((vis() / 7) * 100, 100)}%`, background: vis() > 3 ? `linear-gradient(90deg, ${$.blue}, ${$.gold})` : $.blue, borderRadius: "999px", transition: "width 0.4s ease-out" }} />
</div>
</div>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<button onClick={() => setStep(1)} style={{ background: $.bg, color: $.dim, border: `1px solid ${$.border}`, borderRadius: "10px", padding: "12px 22px", fontSize: "14px", fontWeight: 500, cursor: "pointer", fontFamily: font }}> Back</button>
<button onClick={() => setStep(3)} style={{ background: $.blue, color: "#fff", border: "none", borderRadius: "10px", padding: "12px 24px", fontSize: "14px", fontWeight: 600, cursor: "pointer", fontFamily: font, boxShadow: "0 2px 8px rgba(29,78,216,0.25)" }}>Continue </button>
</div>
</div>)}
{/* STEP 3 */}
{step === 3 && (<div>
<div style={{ textAlign: "center", marginBottom: "24px" }}>
<h2 style={{ fontSize: "22px", fontWeight: 700, margin: "0 0 6px" }}>Need more lead credits?</h2>
<p style={{ color: $.dim, fontSize: "14px", maxWidth: "440px", margin: "0 auto" }}>Your plan includes <strong style={{ color: $.blue }}>{PLANS.find(p => p.id === plan).credits} credits{plan !== "starter" ? "/mo" : ""}</strong>. Buy extra at volume discount.</p>
</div>
<div style={{ background: $.bg, border: `1px solid ${$.border}`, borderRadius: "14px", padding: "16px 20px", marginBottom: "20px", boxShadow: "0 1px 3px rgba(0,0,0,0.04)" }}>
<div style={{ fontSize: "11px", fontWeight: 700, color: $.faint, textTransform: "uppercase", letterSpacing: "0.05em", marginBottom: "12px" }}>How credits work</div>
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(150px, 1fr))", gap: "14px" }}>
{[["🏠", "Small project", "2-court residential", "58 credits"], ["🏢", "Medium project", "46 court club", "1525 credits"], ["🏟", "Large project", "8+ court complex", "3040 credits"]].map(([e, l, d, c]) => (
<div key={l} style={{ display: "flex", gap: "10px" }}><span style={{ fontSize: "20px" }}>{e}</span><div><div style={{ fontSize: "13px", fontWeight: 600 }}>{l}</div><div style={{ fontSize: "12px", color: $.dim }}>{d}</div><div style={{ fontSize: "12px", fontFamily: mono, color: $.blue, marginTop: "3px" }}>{c}</div></div></div>
))}
</div>
</div>
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(190px, 1fr))", gap: "12px", marginBottom: "24px" }}>
{CREDIT_PACKS.map(pk => {
const sel = credits === pk.amount;
return (
<div key={pk.amount} onClick={() => setCredits(sel ? null : pk.amount)} style={{ position: "relative", background: sel ? $.blueGhost : $.bg, border: `2px solid ${sel ? $.blue : $.border}`, borderRadius: "14px", padding: "20px", cursor: "pointer", textAlign: "center", boxShadow: sel ? "0 4px 16px rgba(29,78,216,0.10)" : "0 1px 3px rgba(0,0,0,0.04)" }}>
{pk.popular && <div style={{ position: "absolute", top: "-1px", left: "50%", transform: "translateX(-50%)", background: $.gold, color: "#fff", fontSize: "10px", fontWeight: 700, padding: "2px 10px", borderRadius: "0 0 6px 6px", textTransform: "uppercase" }}>Best Value</div>}
<div style={{ fontSize: "28px", fontWeight: 700, fontFamily: mono }}>{pk.amount}</div>
<div style={{ fontSize: "12px", color: $.dim, marginBottom: "10px" }}>credits</div>
<div style={{ fontSize: "20px", fontWeight: 700 }}>{pk.price}</div>
<div style={{ fontSize: "12px", color: $.dim }}>{pk.perCredit}/credit</div>
</div>
);
})}
</div>
<div style={{ textAlign: "center", marginBottom: "24px", fontSize: "13px", color: $.faint }}>You can always buy more later. Skip to start with plan credits only.</div>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<button onClick={() => setStep(2)} style={{ background: $.bg, color: $.dim, border: `1px solid ${$.border}`, borderRadius: "10px", padding: "12px 22px", fontSize: "14px", cursor: "pointer", fontFamily: font }}> Back</button>
<button onClick={() => setStep(4)} style={{ background: $.blue, color: "#fff", border: "none", borderRadius: "10px", padding: "12px 24px", fontSize: "14px", fontWeight: 600, cursor: "pointer", fontFamily: font, boxShadow: "0 2px 8px rgba(29,78,216,0.25)" }}>{credits ? "Continue →" : "Skip, continue →"}</button>
</div>
</div>)}
{/* STEP 4 */}
{step === 4 && (<div style={{ display: "grid", gridTemplateColumns: "1fr 320px", gap: "24px", alignItems: "start" }}>
<div>
<h2 style={{ fontSize: "22px", fontWeight: 700, marginBottom: "22px" }}>Create your account</h2>
<div style={{ display: "flex", flexDirection: "column", gap: "16px" }}>
{[["company", "Company name", "e.g. PadelCourt GmbH"], ["name", "Your name", "Full name"], ["email", "Email", "you@company.com"]].map(([k, l, p]) => (
<div key={k}><label style={{ display: "block", fontSize: "13px", fontWeight: 500, color: $.dim, marginBottom: "6px" }}>{l}</label><input placeholder={p} value={form[k]} onChange={e => setForm(f => ({ ...f, [k]: e.target.value }))} style={{ width: "100%", background: $.bg, border: `1.5px solid ${$.border}`, borderRadius: "10px", padding: "11px 14px", fontSize: "14px", color: $.text, fontFamily: font, outline: "none", boxSizing: "border-box" }} onFocus={e => e.target.style.borderColor = $.blue} onBlur={e => e.target.style.borderColor = $.border} /></div>
))}
<div><label style={{ display: "block", fontSize: "13px", fontWeight: 500, color: $.dim, marginBottom: "6px" }}>Country</label>
<select value={form.country} onChange={e => setForm(f => ({ ...f, country: e.target.value }))} style={{ width: "100%", background: $.bg, border: `1.5px solid ${$.border}`, borderRadius: "10px", padding: "11px 14px", fontSize: "14px", color: form.country ? $.text : $.faint, fontFamily: font, outline: "none", boxSizing: "border-box" }}>
<option value="">Select country</option>{["Germany", "Netherlands", "France", "Italy", "Spain", "UK", "Sweden", "Belgium", "Austria", "Switzerland", "Portugal", "UAE", "USA", "Other"].map(c => <option key={c}>{c}</option>)}
</select>
</div>
<div><label style={{ display: "block", fontSize: "13px", fontWeight: 500, color: $.dim, marginBottom: "8px" }}>Service categories</label>
<div style={{ display: "flex", flexWrap: "wrap", gap: "8px" }}>
{CATEGORIES.map(cat => { const a = form.categories.includes(cat); return <button key={cat} onClick={() => setForm(f => ({ ...f, categories: a ? f.categories.filter(c => c !== cat) : [...f.categories, cat] }))} style={{ background: a ? $.blueGhost : $.bg, border: `1.5px solid ${a ? $.blue : $.border}`, borderRadius: "999px", padding: "6px 14px", fontSize: "13px", fontWeight: a ? 600 : 400, color: a ? $.blue : $.dim, cursor: "pointer", fontFamily: font }}>{cat}</button>; })}
</div>
</div>
</div>
<button onClick={() => setStep(3)} style={{ background: $.bg, color: $.dim, border: `1px solid ${$.border}`, borderRadius: "10px", padding: "10px 20px", fontSize: "14px", cursor: "pointer", fontFamily: font, marginTop: "20px" }}> Back</button>
</div>
{/* Summary */}
<div style={{ background: $.bg, border: `1px solid ${$.border}`, borderRadius: "16px", padding: "22px", position: "sticky", top: "24px", boxShadow: "0 1px 6px rgba(0,0,0,0.06)" }}>
<div style={{ fontSize: "15px", fontWeight: 700, marginBottom: "16px", paddingBottom: "12px", borderBottom: `1px solid ${$.border}` }}>Order Summary</div>
<div style={{ marginBottom: "14px" }}>
<div style={{ display: "flex", justifyContent: "space-between", marginBottom: "2px" }}><span style={{ fontSize: "14px", fontWeight: 600 }}>{PLANS.find(p => p.id === plan).name}</span><span style={{ fontSize: "14px", fontFamily: mono }}>{PLANS.find(p => p.id === plan).price === 0 ? "Free" : `${PLANS.find(p => p.id === plan).price}/mo`}</span></div>
<div style={{ fontSize: "12px", color: $.dim }}>Includes {PLANS.find(p => p.id === plan).credits} credits{plan !== "starter" ? "/mo" : ""}</div>
</div>
{addons.size > 0 && <div style={{ marginBottom: "14px" }}><div style={{ fontSize: "10px", fontWeight: 700, color: $.faint, textTransform: "uppercase", letterSpacing: "0.05em", marginBottom: "6px" }}>Add-ons</div>{Array.from(addons).map(id => { const a = ADDONS.find(x => x.id === id); return <div key={id} style={{ display: "flex", justifyContent: "space-between", fontSize: "13px", marginBottom: "4px" }}><span style={{ color: $.dim }}>{a.icon} {a.name}</span><span style={{ fontFamily: mono, fontSize: "12px" }}>{a.price}<span style={{ color: $.faint }}>{a.period}</span></span></div>; })}</div>}
{credits && <div style={{ marginBottom: "14px" }}><div style={{ fontSize: "10px", fontWeight: 700, color: $.faint, textTransform: "uppercase", letterSpacing: "0.05em", marginBottom: "6px" }}>Extra Credits</div><div style={{ display: "flex", justifyContent: "space-between", fontSize: "13px" }}><span style={{ color: $.dim }}> {credits} credits</span><span style={{ fontFamily: mono, fontSize: "12px" }}>{CREDIT_PACKS.find(p => p.amount === credits)?.price}</span></div></div>}
<div style={{ borderTop: `1px solid ${$.border}`, paddingTop: "12px", marginTop: "4px" }}>
<div style={{ display: "flex", justifyContent: "space-between", marginBottom: "8px", fontSize: "13px" }}><span style={{ color: $.dim }}>Total credits</span><span style={{ fontFamily: mono, fontWeight: 600, color: $.blue }}> {totalCr()}</span></div>
<div style={{ display: "flex", justifyContent: "space-between", marginBottom: "12px", fontSize: "13px" }}><span style={{ color: $.dim }}>Visibility boost</span><span style={{ fontFamily: mono, fontWeight: 600, color: vis() > 3 ? $.gold : $.blue }}>{vis().toFixed(1)}×</span></div>
<div style={{ display: "flex", justifyContent: "space-between", marginBottom: "3px" }}><span style={{ fontSize: "14px", fontWeight: 600 }}>Monthly</span><span style={{ fontSize: "18px", fontWeight: 700, fontFamily: mono }}>{monthly()}</span></div>
{oneTime() > 0 && <div style={{ display: "flex", justifyContent: "space-between" }}><span style={{ fontSize: "13px", color: $.dim }}>Due today (one-time)</span><span style={{ fontSize: "14px", fontWeight: 600, fontFamily: mono, color: $.dim }}>{oneTime()}</span></div>}
</div>
<button style={{ width: "100%", background: $.blue, color: "#fff", border: "none", borderRadius: "10px", padding: "13px", fontSize: "15px", fontWeight: 700, cursor: "pointer", fontFamily: font, marginTop: "14px", boxShadow: "0 2px 10px rgba(29,78,216,0.25)" }}>{monthly() === 0 && oneTime() === 0 ? "Create Free Account" : "Start Subscription →"}</button>
<div style={{ textAlign: "center", fontSize: "11px", color: $.faint, marginTop: "10px" }}>{monthly() > 0 ? "Cancel anytime. No lock-in." : "No credit card required."}</div>
</div>
</div>)}
</div>
</div>
</div>
);
}