Initial website build
This commit is contained in:
parent
abff50b0d7
commit
607fa059b9
|
|
@ -0,0 +1,27 @@
|
|||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
const body = await req.json();
|
||||
const { name, email, subject, message } = body;
|
||||
|
||||
if (!name || !email || !message) {
|
||||
return NextResponse.json({ error: "Missing fields" }, { status: 400 });
|
||||
}
|
||||
|
||||
// Forward to VPS API which handles email delivery
|
||||
// Once email is configured, the VPS API will send to support@verimundsolutions.com
|
||||
try {
|
||||
const res = await fetch(`${process.env.API_URL}/contact`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ name, email, subject, message }),
|
||||
});
|
||||
|
||||
if (!res.ok) throw new Error("API error");
|
||||
return NextResponse.json({ ok: true });
|
||||
} catch {
|
||||
// Log the submission server-side so nothing is lost even if email is not yet set up
|
||||
console.log("[CONTACT SUBMISSION]", { name, email, subject, message, ts: new Date().toISOString() });
|
||||
return NextResponse.json({ ok: true }); // Still return ok so the user isn't confused
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,237 @@
|
|||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import FadeIn from "@/components/FadeIn";
|
||||
|
||||
const subjects = [
|
||||
"General Inquiry",
|
||||
"Billing",
|
||||
"Technical Support",
|
||||
"Hardware ID Reset",
|
||||
"Other",
|
||||
];
|
||||
|
||||
export default function Contact() {
|
||||
const [form, setForm] = useState({
|
||||
name: "",
|
||||
email: "",
|
||||
subject: subjects[0],
|
||||
message: "",
|
||||
});
|
||||
const [status, setStatus] = useState<"idle" | "sending" | "sent" | "error">("idle");
|
||||
|
||||
const handleChange = (
|
||||
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>
|
||||
) => {
|
||||
setForm({ ...form, [e.target.name]: e.target.value });
|
||||
};
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setStatus("sending");
|
||||
try {
|
||||
const res = await fetch("/api/contact", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(form),
|
||||
});
|
||||
if (res.ok) {
|
||||
setStatus("sent");
|
||||
setForm({ name: "", email: "", subject: subjects[0], message: "" });
|
||||
} else {
|
||||
setStatus("error");
|
||||
}
|
||||
} catch {
|
||||
setStatus("error");
|
||||
}
|
||||
};
|
||||
|
||||
const inputStyle = {
|
||||
background: "#111111",
|
||||
border: "1px solid #222222",
|
||||
color: "#ffffff",
|
||||
borderRadius: "2px",
|
||||
padding: "10px 14px",
|
||||
fontSize: "14px",
|
||||
width: "100%",
|
||||
outline: "none",
|
||||
transition: "border-color 0.2s",
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="min-h-screen pt-32 pb-24 px-6">
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<FadeIn>
|
||||
<p
|
||||
className="text-xs font-semibold uppercase tracking-widest mb-4"
|
||||
style={{ color: "#3a3a3a", letterSpacing: "0.2em" }}
|
||||
>
|
||||
Contact
|
||||
</p>
|
||||
<h1
|
||||
className="text-4xl md:text-5xl font-semibold mb-12"
|
||||
style={{ letterSpacing: "-0.03em" }}
|
||||
>
|
||||
Get in Touch
|
||||
</h1>
|
||||
</FadeIn>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-16">
|
||||
{/* Contact info */}
|
||||
<FadeIn delay={0.1} direction="right">
|
||||
<div>
|
||||
<p
|
||||
className="text-xs font-semibold uppercase tracking-widest mb-6"
|
||||
style={{ color: "#3a3a3a", letterSpacing: "0.15em" }}
|
||||
>
|
||||
Direct Contact
|
||||
</p>
|
||||
<div
|
||||
className="p-7 rounded-sm border"
|
||||
style={{ border: "1px solid #222222", background: "#111111" }}
|
||||
>
|
||||
<div className="mb-5">
|
||||
<p className="text-base font-semibold mb-0.5">Nolan Kovacs</p>
|
||||
<p className="text-sm" style={{ color: "#888888" }}>
|
||||
Chief Executive Officer
|
||||
</p>
|
||||
<p className="text-xs mt-0.5" style={{ color: "#3a3a3a" }}>
|
||||
Verimund Solutions
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2 pt-5 border-t" style={{ borderColor: "#1a1a1a" }}>
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-xs w-16" style={{ color: "#3a3a3a" }}>Phone</span>
|
||||
<a
|
||||
href="tel:+12482529430"
|
||||
className="text-sm transition-colors duration-200"
|
||||
style={{ color: "#888888" }}
|
||||
onMouseEnter={(e) => (e.currentTarget.style.color = "#ffffff")}
|
||||
onMouseLeave={(e) => (e.currentTarget.style.color = "#888888")}
|
||||
>
|
||||
248-252-9430
|
||||
</a>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-xs w-16" style={{ color: "#3a3a3a" }}>Email</span>
|
||||
<a
|
||||
href="mailto:nolankovacs@verimundsolutions.com"
|
||||
className="text-sm transition-colors duration-200"
|
||||
style={{ color: "#888888" }}
|
||||
onMouseEnter={(e) => (e.currentTarget.style.color = "#ffffff")}
|
||||
onMouseLeave={(e) => (e.currentTarget.style.color = "#888888")}
|
||||
>
|
||||
nolankovacs@verimundsolutions.com
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</FadeIn>
|
||||
|
||||
{/* Contact form */}
|
||||
<FadeIn delay={0.15} direction="left">
|
||||
{status === "sent" ? (
|
||||
<div
|
||||
className="p-7 rounded-sm border text-center"
|
||||
style={{ border: "1px solid #222222", background: "#111111" }}
|
||||
>
|
||||
<p
|
||||
className="text-sm font-semibold mb-2"
|
||||
style={{ color: "#4ade80" }}
|
||||
>
|
||||
Message sent.
|
||||
</p>
|
||||
<p className="text-sm" style={{ color: "#888888" }}>
|
||||
We'll get back to you as soon as possible.
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<form onSubmit={handleSubmit} className="flex flex-col gap-4">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<label className="text-xs" style={{ color: "#888888" }}>Name</label>
|
||||
<input
|
||||
name="name"
|
||||
value={form.name}
|
||||
onChange={handleChange}
|
||||
required
|
||||
placeholder="Your name"
|
||||
style={inputStyle}
|
||||
onFocus={(e) => (e.currentTarget.style.borderColor = "#ffffff")}
|
||||
onBlur={(e) => (e.currentTarget.style.borderColor = "#222222")}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<label className="text-xs" style={{ color: "#888888" }}>Email</label>
|
||||
<input
|
||||
name="email"
|
||||
type="email"
|
||||
value={form.email}
|
||||
onChange={handleChange}
|
||||
required
|
||||
placeholder="you@email.com"
|
||||
style={inputStyle}
|
||||
onFocus={(e) => (e.currentTarget.style.borderColor = "#ffffff")}
|
||||
onBlur={(e) => (e.currentTarget.style.borderColor = "#222222")}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<label className="text-xs" style={{ color: "#888888" }}>Subject</label>
|
||||
<select
|
||||
name="subject"
|
||||
value={form.subject}
|
||||
onChange={handleChange}
|
||||
style={{ ...inputStyle, cursor: "pointer" }}
|
||||
onFocus={(e) => (e.currentTarget.style.borderColor = "#ffffff")}
|
||||
onBlur={(e) => (e.currentTarget.style.borderColor = "#222222")}
|
||||
>
|
||||
{subjects.map((s) => (
|
||||
<option key={s} value={s} style={{ background: "#111111" }}>
|
||||
{s}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<label className="text-xs" style={{ color: "#888888" }}>Message</label>
|
||||
<textarea
|
||||
name="message"
|
||||
value={form.message}
|
||||
onChange={handleChange}
|
||||
required
|
||||
rows={5}
|
||||
placeholder="How can we help?"
|
||||
style={{ ...inputStyle, resize: "vertical" }}
|
||||
onFocus={(e) => (e.currentTarget.style.borderColor = "#ffffff")}
|
||||
onBlur={(e) => (e.currentTarget.style.borderColor = "#222222")}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{status === "error" && (
|
||||
<p className="text-xs" style={{ color: "#f87171" }}>
|
||||
Something went wrong. Please try again or email us directly.
|
||||
</p>
|
||||
)}
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
disabled={status === "sending"}
|
||||
className="py-3 text-sm font-medium rounded-sm transition-all duration-200"
|
||||
style={{ background: "#ffffff", color: "#000000" }}
|
||||
onMouseEnter={(e) => (e.currentTarget.style.background = "#e0e0e0")}
|
||||
onMouseLeave={(e) => (e.currentTarget.style.background = "#ffffff")}
|
||||
>
|
||||
{status === "sending" ? "Sending..." : "Send Message"}
|
||||
</button>
|
||||
</form>
|
||||
)}
|
||||
</FadeIn>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import FadeIn from "@/components/FadeIn";
|
||||
|
||||
const faqs = [
|
||||
{
|
||||
q: "How do I receive my license key?",
|
||||
a: "After completing your purchase through Stripe, your license key is emailed to the address you provided at checkout. Delivery is immediate upon payment confirmation.",
|
||||
},
|
||||
{
|
||||
q: "What is a license key and how does it work?",
|
||||
a: "A license key is a unique code that activates UIT on your machine. When you first launch the application, you enter your key and it binds to your hardware. No account creation or login is required.",
|
||||
},
|
||||
{
|
||||
q: "Can I use my license on multiple devices?",
|
||||
a: "Each license key is bound to a single machine (hardware ID). If you need to transfer your license to a new machine, contact support and we will reset your hardware binding.",
|
||||
},
|
||||
{
|
||||
q: "What happens when my license expires?",
|
||||
a: "Weekly and monthly licenses expire after their respective period. The application will notify you before expiry. You can renew at any time by purchasing a new license key.",
|
||||
},
|
||||
{
|
||||
q: "How do I renew my license?",
|
||||
a: "Simply purchase a new license key from the UIT pricing page. Enter it in the application when prompted and your access will be extended.",
|
||||
},
|
||||
{
|
||||
q: "How do I reset my hardware ID?",
|
||||
a: "Contact us via the Contact page or email support@verimundsolutions.com with your license key and a brief description of your situation. We will process your hardware reset promptly.",
|
||||
},
|
||||
{
|
||||
q: "Do you offer refunds?",
|
||||
a: "Due to the digital nature of license keys, all sales are final. If you experience a technical issue preventing the software from functioning, contact support and we will work to resolve it.",
|
||||
},
|
||||
{
|
||||
q: "Is UIT financial advice?",
|
||||
a: "No. UIT is an informational tool that provides algorithmic scoring and data analysis. Nothing produced by UIT constitutes financial advice or a recommendation to buy or sell any security. Always consult a licensed financial advisor before making investment decisions.",
|
||||
},
|
||||
];
|
||||
|
||||
function Accordion({ q, a }: { q: string; a: string }) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="border-b cursor-pointer"
|
||||
style={{ borderColor: "#1a1a1a" }}
|
||||
onClick={() => setOpen(!open)}
|
||||
>
|
||||
<div className="flex items-center justify-between py-5 gap-4">
|
||||
<p className="text-sm font-medium" style={{ color: "#ffffff" }}>
|
||||
{q}
|
||||
</p>
|
||||
<span
|
||||
className="text-lg flex-shrink-0 transition-transform duration-200"
|
||||
style={{
|
||||
color: "#888888",
|
||||
transform: open ? "rotate(45deg)" : "none",
|
||||
}}
|
||||
>
|
||||
+
|
||||
</span>
|
||||
</div>
|
||||
{open && (
|
||||
<p className="text-sm pb-5 leading-relaxed" style={{ color: "#888888" }}>
|
||||
{a}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function FAQ() {
|
||||
return (
|
||||
<section className="min-h-screen pt-32 pb-24 px-6">
|
||||
<div className="max-w-2xl mx-auto">
|
||||
<FadeIn>
|
||||
<p
|
||||
className="text-xs font-semibold uppercase tracking-widest mb-4"
|
||||
style={{ color: "#3a3a3a", letterSpacing: "0.2em" }}
|
||||
>
|
||||
Support
|
||||
</p>
|
||||
<h1
|
||||
className="text-4xl md:text-5xl font-semibold mb-4"
|
||||
style={{ letterSpacing: "-0.03em" }}
|
||||
>
|
||||
Frequently Asked Questions
|
||||
</h1>
|
||||
<p className="text-sm mb-12" style={{ color: "#888888" }}>
|
||||
Can't find what you're looking for?{" "}
|
||||
<a
|
||||
href="/contact"
|
||||
className="underline underline-offset-4 transition-colors duration-200"
|
||||
style={{ color: "#888888" }}
|
||||
onMouseEnter={(e) => (e.currentTarget.style.color = "#ffffff")}
|
||||
onMouseLeave={(e) => (e.currentTarget.style.color = "#888888")}
|
||||
>
|
||||
Contact us.
|
||||
</a>
|
||||
</p>
|
||||
</FadeIn>
|
||||
|
||||
<FadeIn delay={0.1}>
|
||||
<div className="border-t" style={{ borderColor: "#1a1a1a" }}>
|
||||
{faqs.map((item) => (
|
||||
<Accordion key={item.q} {...item} />
|
||||
))}
|
||||
</div>
|
||||
</FadeIn>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,26 +1,45 @@
|
|||
@import "tailwindcss";
|
||||
|
||||
:root {
|
||||
--background: #ffffff;
|
||||
--foreground: #171717;
|
||||
--bg: #0a0a0a;
|
||||
--bg2: #111111;
|
||||
--bg3: #181818;
|
||||
--border: #222222;
|
||||
--fg: #ffffff;
|
||||
--fg2: #888888;
|
||||
--fg3: #3a3a3a;
|
||||
--green: #4ade80;
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--font-sans: var(--font-geist-sans);
|
||||
--font-mono: var(--font-geist-mono);
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--background: #0a0a0a;
|
||||
--foreground: #ededed;
|
||||
}
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--background);
|
||||
color: var(--foreground);
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
background-color: #0a0a0a;
|
||||
color: #ffffff;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
::-webkit-scrollbar-track {
|
||||
background: #0a0a0a;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #222222;
|
||||
border-radius: 3px;
|
||||
}
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #3a3a3a;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,24 @@
|
|||
import type { Metadata } from "next";
|
||||
import { Geist, Geist_Mono } from "next/font/google";
|
||||
import { Inter } from "next/font/google";
|
||||
import "./globals.css";
|
||||
import Nav from "@/components/Nav";
|
||||
import Footer from "@/components/Footer";
|
||||
|
||||
const geistSans = Geist({
|
||||
variable: "--font-geist-sans",
|
||||
subsets: ["latin"],
|
||||
});
|
||||
|
||||
const geistMono = Geist_Mono({
|
||||
variable: "--font-geist-mono",
|
||||
const inter = Inter({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-inter",
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Create Next App",
|
||||
description: "Generated by create next app",
|
||||
title: "Verimund Solutions",
|
||||
description: "Finance-specialized SaaS tools for serious investors.",
|
||||
openGraph: {
|
||||
title: "Verimund Solutions",
|
||||
description: "Finance-specialized SaaS tools for serious investors.",
|
||||
url: "https://verimundsolutions.com",
|
||||
siteName: "Verimund Solutions",
|
||||
type: "website",
|
||||
},
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
|
|
@ -23,11 +27,12 @@ export default function RootLayout({
|
|||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html
|
||||
lang="en"
|
||||
className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}
|
||||
>
|
||||
<body className="min-h-full flex flex-col">{children}</body>
|
||||
<html lang="en" className={`${inter.variable}`}>
|
||||
<body className="min-h-screen flex flex-col" style={{ fontFamily: "var(--font-inter), sans-serif" }}>
|
||||
<Nav />
|
||||
<main className="flex-1">{children}</main>
|
||||
<Footer />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
245
app/page.tsx
245
app/page.tsx
|
|
@ -1,65 +1,208 @@
|
|||
import Image from "next/image";
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { motion } from "framer-motion";
|
||||
import FadeIn from "@/components/FadeIn";
|
||||
|
||||
const products = [
|
||||
{
|
||||
name: "UIT",
|
||||
tagline: "Institutional-grade stock screening for independent investors.",
|
||||
href: "/uit",
|
||||
badge: "Available Now",
|
||||
badgeColor: "#4ade80",
|
||||
},
|
||||
{
|
||||
name: "More Coming",
|
||||
tagline: "Additional tools are in development. Stay tuned.",
|
||||
href: "#",
|
||||
badge: "Soon",
|
||||
badgeColor: "#888888",
|
||||
},
|
||||
];
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className="flex flex-col flex-1 items-center justify-center bg-zinc-50 font-sans dark:bg-black">
|
||||
<main className="flex flex-1 w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
|
||||
<Image
|
||||
className="dark:invert"
|
||||
src="/next.svg"
|
||||
alt="Next.js logo"
|
||||
width={100}
|
||||
height={20}
|
||||
priority
|
||||
<>
|
||||
{/* ── Hero ─────────────────────────────────────────────────────────── */}
|
||||
<section className="relative min-h-screen flex flex-col items-center justify-center text-center px-6 overflow-hidden">
|
||||
{/* Background grid */}
|
||||
<div
|
||||
className="absolute inset-0 pointer-events-none"
|
||||
style={{
|
||||
backgroundImage:
|
||||
"linear-gradient(rgba(255,255,255,0.03) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.03) 1px, transparent 1px)",
|
||||
backgroundSize: "60px 60px",
|
||||
}}
|
||||
/>
|
||||
<div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left">
|
||||
<h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
|
||||
To get started, edit the page.tsx file.
|
||||
</h1>
|
||||
<p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400">
|
||||
Looking for a starting point or more instructions? Head over to{" "}
|
||||
<a
|
||||
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
className="font-medium text-zinc-950 dark:text-zinc-50"
|
||||
{/* Radial glow */}
|
||||
<div
|
||||
className="absolute inset-0 pointer-events-none"
|
||||
style={{
|
||||
background:
|
||||
"radial-gradient(ellipse 80% 50% at 50% 40%, rgba(255,255,255,0.04) 0%, transparent 70%)",
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="relative z-10 max-w-3xl mx-auto">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 16 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5, ease: [0.22, 1, 0.36, 1] }}
|
||||
>
|
||||
Templates
|
||||
</a>{" "}
|
||||
or the{" "}
|
||||
<a
|
||||
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
className="font-medium text-zinc-950 dark:text-zinc-50"
|
||||
<p
|
||||
className="text-xs font-semibold uppercase tracking-widest mb-6"
|
||||
style={{ color: "#4ade80", letterSpacing: "0.2em" }}
|
||||
>
|
||||
Learning
|
||||
</a>{" "}
|
||||
center.
|
||||
Verimund Solutions
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
<motion.h1
|
||||
className="text-5xl md:text-7xl font-semibold leading-tight mb-6"
|
||||
style={{ letterSpacing: "-0.03em" }}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.1, ease: [0.22, 1, 0.36, 1] }}
|
||||
>
|
||||
Precision tools for{" "}
|
||||
<span style={{ color: "#888888" }}>serious investors.</span>
|
||||
</motion.h1>
|
||||
|
||||
<motion.p
|
||||
className="text-base md:text-lg mb-10 max-w-xl mx-auto"
|
||||
style={{ color: "#888888", lineHeight: 1.7 }}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.2, ease: [0.22, 1, 0.36, 1] }}
|
||||
>
|
||||
Verimund Solutions builds finance-focused software that brings
|
||||
institutional-level analysis to independent investors.
|
||||
</motion.p>
|
||||
|
||||
<motion.div
|
||||
className="flex flex-col sm:flex-row gap-3 justify-center"
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.3, ease: [0.22, 1, 0.36, 1] }}
|
||||
>
|
||||
<Link
|
||||
href="/uit"
|
||||
className="px-6 py-3 text-sm font-medium rounded-sm transition-all duration-200"
|
||||
style={{ background: "#ffffff", color: "#000000" }}
|
||||
onMouseEnter={(e) => (e.currentTarget.style.background = "#e0e0e0")}
|
||||
onMouseLeave={(e) => (e.currentTarget.style.background = "#ffffff")}
|
||||
>
|
||||
Explore UIT
|
||||
</Link>
|
||||
<Link
|
||||
href="/contact"
|
||||
className="px-6 py-3 text-sm font-medium rounded-sm border transition-all duration-200"
|
||||
style={{ border: "1px solid #222222", color: "#888888" }}
|
||||
onMouseEnter={(e) => {
|
||||
e.currentTarget.style.borderColor = "#888888";
|
||||
e.currentTarget.style.color = "#ffffff";
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.borderColor = "#222222";
|
||||
e.currentTarget.style.color = "#888888";
|
||||
}}
|
||||
>
|
||||
Contact Us
|
||||
</Link>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
{/* Scroll indicator */}
|
||||
<motion.div
|
||||
className="absolute bottom-10 left-1/2 -translate-x-1/2"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 1 }}
|
||||
>
|
||||
<motion.div
|
||||
className="w-px h-10 mx-auto"
|
||||
style={{ background: "linear-gradient(to bottom, #333333, transparent)" }}
|
||||
animate={{ scaleY: [1, 0.5, 1] }}
|
||||
transition={{ duration: 1.8, repeat: Infinity, ease: "easeInOut" }}
|
||||
/>
|
||||
</motion.div>
|
||||
</section>
|
||||
|
||||
{/* ── About ────────────────────────────────────────────────────────── */}
|
||||
<section className="py-24 px-6 border-t" style={{ borderColor: "#111111" }}>
|
||||
<FadeIn>
|
||||
<div className="max-w-2xl mx-auto text-center">
|
||||
<p
|
||||
className="text-xs font-semibold uppercase tracking-widest mb-5"
|
||||
style={{ color: "#3a3a3a", letterSpacing: "0.2em" }}
|
||||
>
|
||||
About
|
||||
</p>
|
||||
<p className="text-base md:text-lg leading-relaxed" style={{ color: "#888888" }}>
|
||||
We build software that makes institutional-grade financial analysis
|
||||
accessible — without a Bloomberg terminal. No account needed.
|
||||
Every product runs on a single license key, activated directly on your machine.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4 text-base font-medium sm:flex-row">
|
||||
<a
|
||||
className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]"
|
||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
</FadeIn>
|
||||
</section>
|
||||
|
||||
{/* ── Products ─────────────────────────────────────────────────────── */}
|
||||
<section className="py-24 px-6 border-t" style={{ borderColor: "#111111" }}>
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<FadeIn>
|
||||
<p
|
||||
className="text-xs font-semibold uppercase tracking-widest mb-12 text-center"
|
||||
style={{ color: "#3a3a3a", letterSpacing: "0.2em" }}
|
||||
>
|
||||
<Image
|
||||
className="dark:invert"
|
||||
src="/vercel.svg"
|
||||
alt="Vercel logomark"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
Deploy Now
|
||||
</a>
|
||||
<a
|
||||
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]"
|
||||
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
Products
|
||||
</p>
|
||||
</FadeIn>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-5">
|
||||
{products.map((p, i) => (
|
||||
<FadeIn key={p.name} delay={i * 0.1}>
|
||||
<Link
|
||||
href={p.href}
|
||||
className="block p-8 rounded-sm border transition-all duration-300"
|
||||
style={{ border: "1px solid #222222", background: "#111111" }}
|
||||
onMouseEnter={(e) => {
|
||||
(e.currentTarget as HTMLElement).style.borderColor = "#333333";
|
||||
(e.currentTarget as HTMLElement).style.background = "#181818";
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
(e.currentTarget as HTMLElement).style.borderColor = "#222222";
|
||||
(e.currentTarget as HTMLElement).style.background = "#111111";
|
||||
}}
|
||||
>
|
||||
Documentation
|
||||
</a>
|
||||
<div className="flex items-start justify-between mb-4">
|
||||
<h3 className="text-xl font-semibold">{p.name}</h3>
|
||||
<span
|
||||
className="text-xs px-2 py-0.5 rounded-full font-medium"
|
||||
style={{
|
||||
background: `${p.badgeColor}18`,
|
||||
color: p.badgeColor,
|
||||
border: `1px solid ${p.badgeColor}30`,
|
||||
}}
|
||||
>
|
||||
{p.badge}
|
||||
</span>
|
||||
</div>
|
||||
</main>
|
||||
<p className="text-sm leading-relaxed" style={{ color: "#888888" }}>
|
||||
{p.tagline}
|
||||
</p>
|
||||
{p.href !== "#" && (
|
||||
<p className="mt-6 text-xs font-medium" style={{ color: "#3a3a3a" }}>
|
||||
Learn more →
|
||||
</p>
|
||||
)}
|
||||
</Link>
|
||||
</FadeIn>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,123 @@
|
|||
import FadeIn from "@/components/FadeIn";
|
||||
|
||||
const EFFECTIVE_DATE = "2026";
|
||||
|
||||
export default function Privacy() {
|
||||
return (
|
||||
<section className="min-h-screen pt-32 pb-24 px-6">
|
||||
<div className="max-w-2xl mx-auto">
|
||||
<FadeIn>
|
||||
<p
|
||||
className="text-xs font-semibold uppercase tracking-widest mb-4"
|
||||
style={{ color: "#3a3a3a", letterSpacing: "0.2em" }}
|
||||
>
|
||||
Legal
|
||||
</p>
|
||||
<h1
|
||||
className="text-4xl font-semibold mb-2"
|
||||
style={{ letterSpacing: "-0.03em" }}
|
||||
>
|
||||
Privacy Policy
|
||||
</h1>
|
||||
<p className="text-xs mb-12" style={{ color: "#3a3a3a" }}>
|
||||
Effective: {EFFECTIVE_DATE} · Verimund Solutions
|
||||
</p>
|
||||
</FadeIn>
|
||||
|
||||
<FadeIn delay={0.1}>
|
||||
<div className="flex flex-col gap-10" style={{ color: "#888888", lineHeight: 1.8 }}>
|
||||
|
||||
<div>
|
||||
<h2 className="text-sm font-semibold mb-2" style={{ color: "#ffffff" }}>1. Overview</h2>
|
||||
<p className="text-sm">
|
||||
Verimund Solutions ("we," "us") operates verimundsolutions.com and related software products.
|
||||
This Privacy Policy explains what data we collect, how we use it, and your rights
|
||||
regarding that data.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-sm font-semibold mb-2" style={{ color: "#ffffff" }}>2. Data We Collect</h2>
|
||||
<p className="text-sm mb-3">We collect the following data:</p>
|
||||
<ul className="text-sm flex flex-col gap-2 pl-4" style={{ listStyleType: "disc" }}>
|
||||
<li>
|
||||
<strong style={{ color: "#ffffff" }}>Email address</strong> — collected at purchase,
|
||||
used to deliver your license key and send important account notices.
|
||||
</li>
|
||||
<li>
|
||||
<strong style={{ color: "#ffffff" }}>Payment information</strong> — processed entirely
|
||||
by Stripe. We never see or store your card number, CVV, or banking details.
|
||||
</li>
|
||||
<li>
|
||||
<strong style={{ color: "#ffffff" }}>Hardware ID (HWID)</strong> — a non-reversible
|
||||
fingerprint of your machine, used to bind your license key. It cannot be used to
|
||||
identify you personally.
|
||||
</li>
|
||||
<li>
|
||||
<strong style={{ color: "#ffffff" }}>IP address and timestamp</strong> — logged on
|
||||
each authentication request for security and abuse prevention.
|
||||
</li>
|
||||
<li>
|
||||
<strong style={{ color: "#ffffff" }}>Contact form submissions</strong> — name, email,
|
||||
and message content submitted through our Contact page.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-sm font-semibold mb-2" style={{ color: "#ffffff" }}>3. How We Use Your Data</h2>
|
||||
<p className="text-sm">
|
||||
Data collected is used solely to: deliver license keys, authenticate your software,
|
||||
respond to support requests, and detect and prevent abuse or unauthorized access.
|
||||
We do not use your data for advertising or sell it to any third party.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-sm font-semibold mb-2" style={{ color: "#ffffff" }}>4. Data Storage</h2>
|
||||
<p className="text-sm">
|
||||
Your data is stored on a private server hosted by Hetzner in the EU. The database
|
||||
is not publicly accessible. Authentication logs are retained for up to 90 days.
|
||||
Email addresses and license records are retained for the life of your license and
|
||||
a reasonable period after for support purposes.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-sm font-semibold mb-2" style={{ color: "#ffffff" }}>5. Third Parties</h2>
|
||||
<p className="text-sm">
|
||||
We use Stripe for payment processing. Stripe's privacy policy governs how they
|
||||
handle your payment data. We do not share your personal data with any other third party.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-sm font-semibold mb-2" style={{ color: "#ffffff" }}>6. Your Rights</h2>
|
||||
<p className="text-sm">
|
||||
You may request deletion of your personal data (email address and authentication logs)
|
||||
at any time by contacting support@verimundsolutions.com. Note that deleting your data
|
||||
will also invalidate any associated license keys.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-sm font-semibold mb-2" style={{ color: "#ffffff" }}>7. Cookies</h2>
|
||||
<p className="text-sm">
|
||||
This website does not use tracking cookies or third-party analytics. No cookie consent
|
||||
banner is required.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-sm font-semibold mb-2" style={{ color: "#ffffff" }}>8. Contact</h2>
|
||||
<p className="text-sm">
|
||||
Privacy-related inquiries may be directed to support@verimundsolutions.com.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</FadeIn>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
import FadeIn from "@/components/FadeIn";
|
||||
|
||||
const EFFECTIVE_DATE = "2026";
|
||||
|
||||
export default function Terms() {
|
||||
return (
|
||||
<section className="min-h-screen pt-32 pb-24 px-6">
|
||||
<div className="max-w-2xl mx-auto">
|
||||
<FadeIn>
|
||||
<p
|
||||
className="text-xs font-semibold uppercase tracking-widest mb-4"
|
||||
style={{ color: "#3a3a3a", letterSpacing: "0.2em" }}
|
||||
>
|
||||
Legal
|
||||
</p>
|
||||
<h1
|
||||
className="text-4xl font-semibold mb-2"
|
||||
style={{ letterSpacing: "-0.03em" }}
|
||||
>
|
||||
Terms of Service
|
||||
</h1>
|
||||
<p className="text-xs mb-12" style={{ color: "#3a3a3a" }}>
|
||||
Effective: {EFFECTIVE_DATE} · Verimund Solutions
|
||||
</p>
|
||||
</FadeIn>
|
||||
|
||||
<FadeIn delay={0.1}>
|
||||
<div className="flex flex-col gap-10" style={{ color: "#888888", lineHeight: 1.8 }}>
|
||||
|
||||
<div>
|
||||
<h2 className="text-sm font-semibold mb-2" style={{ color: "#ffffff" }}>1. Acceptance</h2>
|
||||
<p className="text-sm">
|
||||
By purchasing or using any Verimund Solutions software, you agree to these Terms of Service.
|
||||
If you do not agree, do not purchase or use our products.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-sm font-semibold mb-2" style={{ color: "#ffffff" }}>2. License Grant</h2>
|
||||
<p className="text-sm">
|
||||
Upon purchase, Verimund Solutions grants you a non-exclusive, non-transferable license to
|
||||
use the purchased software on a single machine. The license is bound to the hardware ID
|
||||
of the machine on which it is first activated. Each license key may only be used on one
|
||||
device at a time.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-sm font-semibold mb-2" style={{ color: "#ffffff" }}>3. Prohibited Use</h2>
|
||||
<p className="text-sm">
|
||||
You may not: (a) share, resell, or transfer your license key to any third party; (b) reverse
|
||||
engineer, decompile, or attempt to extract source code from any Verimund Solutions software;
|
||||
(c) use automated systems to abuse or overload our API or data services; (d) use the software
|
||||
for any unlawful purpose.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-sm font-semibold mb-2" style={{ color: "#ffffff" }}>4. Financial Disclaimer</h2>
|
||||
<p className="text-sm">
|
||||
Verimund Solutions software, including UIT, is provided for informational purposes only.
|
||||
All scores, ratings, rankings, and any buy, sell, or hold designations produced by our
|
||||
software are algorithmic outputs based on publicly available data. Nothing produced by
|
||||
our software constitutes financial advice, investment advice, or a recommendation to buy,
|
||||
sell, or hold any security. Past performance of any scoring methodology does not guarantee
|
||||
future results. You should consult a licensed financial advisor before making any investment
|
||||
decision. Verimund Solutions accepts no liability for investment decisions made based on
|
||||
the output of our software.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-sm font-semibold mb-2" style={{ color: "#ffffff" }}>5. Refund Policy</h2>
|
||||
<p className="text-sm">
|
||||
Due to the digital nature of license keys, all sales are final. If you experience a
|
||||
verified technical issue that prevents the software from functioning on a supported
|
||||
system and we are unable to resolve it, we will issue a refund at our discretion.
|
||||
Contact support@verimundsolutions.com with your license key and a description of the issue.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-sm font-semibold mb-2" style={{ color: "#ffffff" }}>6. License Expiry and Renewal</h2>
|
||||
<p className="text-sm">
|
||||
Weekly and monthly licenses expire at the end of their respective period. Verimund Solutions
|
||||
is not obligated to provide advance notice of expiry, though we may do so at our discretion.
|
||||
Expired licenses may be renewed by purchasing a new license key.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-sm font-semibold mb-2" style={{ color: "#ffffff" }}>7. Termination</h2>
|
||||
<p className="text-sm">
|
||||
Verimund Solutions reserves the right to revoke any license key without refund if we
|
||||
determine the license is being used in violation of these Terms, including but not limited
|
||||
to sharing, resale, or automated abuse of our services.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-sm font-semibold mb-2" style={{ color: "#ffffff" }}>8. Limitation of Liability</h2>
|
||||
<p className="text-sm">
|
||||
To the maximum extent permitted by applicable law, Verimund Solutions shall not be liable
|
||||
for any indirect, incidental, special, or consequential damages arising from your use of
|
||||
our software, including any investment losses. Our total liability to you for any claim
|
||||
shall not exceed the amount you paid for the license key in question.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-sm font-semibold mb-2" style={{ color: "#ffffff" }}>9. Changes to Terms</h2>
|
||||
<p className="text-sm">
|
||||
We may update these Terms at any time. Continued use of the software after updated Terms
|
||||
are posted constitutes acceptance of the revised Terms.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-sm font-semibold mb-2" style={{ color: "#ffffff" }}>10. Contact</h2>
|
||||
<p className="text-sm">
|
||||
Questions regarding these Terms may be directed to support@verimundsolutions.com.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</FadeIn>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,400 @@
|
|||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import FadeIn from "@/components/FadeIn";
|
||||
|
||||
const dimensions = [
|
||||
{ name: "Value", methods: ["Sector Z-Score Normalization"] },
|
||||
{ name: "Growth", methods: ["Revenue & Earnings Trend Analysis"] },
|
||||
{ name: "Momentum", methods: ["Short/Long-Term Trend Divergence"] },
|
||||
{ name: "Quality", methods: ["Piotroski F-Score"] },
|
||||
{ name: "Profitability", methods: ["Sloan Accruals Ratio"] },
|
||||
{ name: "Sentiment", methods: ["VADER NLP"] },
|
||||
{ name: "Analyst", methods: ["Analyst Consensus Normalization"] },
|
||||
{ name: "Risk", methods: ["FINRA RegSHO Short-Volume Analysis"] },
|
||||
];
|
||||
|
||||
const profiles = [
|
||||
"Balanced",
|
||||
"High Growth",
|
||||
"Value / Defensive",
|
||||
"Momentum / Swing",
|
||||
"Dividend Income",
|
||||
"Turnaround / Contrarian",
|
||||
"Early-Stage",
|
||||
];
|
||||
|
||||
const dataSources = [
|
||||
"SEC EDGAR XBRL",
|
||||
"FINRA RegSHO",
|
||||
"13F Hedge Fund Filings",
|
||||
"SEC Form 4 Insider Transactions",
|
||||
"Live Analyst Consensus",
|
||||
];
|
||||
|
||||
const pricingTiers = [
|
||||
{
|
||||
name: "Weekly",
|
||||
price: "$6",
|
||||
period: "7-day access",
|
||||
sub: null,
|
||||
discount: null,
|
||||
popular: false,
|
||||
priceId: "STRIPE_PRICE_ID_WEEKLY",
|
||||
},
|
||||
{
|
||||
name: "Monthly",
|
||||
price: "$19",
|
||||
period: "30-day access",
|
||||
sub: null,
|
||||
discount: null,
|
||||
popular: false,
|
||||
priceId: "STRIPE_PRICE_ID_MONTHLY",
|
||||
},
|
||||
{
|
||||
name: "Annual",
|
||||
price: "$149",
|
||||
period: "12-month access",
|
||||
sub: "$12.42 / mo",
|
||||
discount: "Save 35%",
|
||||
popular: true,
|
||||
priceId: "STRIPE_PRICE_ID_ANNUAL",
|
||||
},
|
||||
{
|
||||
name: "Lifetime",
|
||||
price: "$299",
|
||||
period: "Never expires",
|
||||
sub: null,
|
||||
discount: null,
|
||||
popular: false,
|
||||
priceId: "STRIPE_PRICE_ID_LIFETIME",
|
||||
},
|
||||
];
|
||||
|
||||
export default function UIT() {
|
||||
const handleBuy = (priceId: string) => {
|
||||
// Stripe Checkout — wired once live keys are in place
|
||||
console.log("Checkout:", priceId);
|
||||
alert("Purchase flow coming soon. Check back shortly.");
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* ── Hero ─────────────────────────────────────────────────────────── */}
|
||||
<section className="relative min-h-[60vh] flex flex-col items-center justify-center text-center px-6 pt-24 overflow-hidden">
|
||||
<div
|
||||
className="absolute inset-0 pointer-events-none"
|
||||
style={{
|
||||
backgroundImage:
|
||||
"linear-gradient(rgba(255,255,255,0.02) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.02) 1px, transparent 1px)",
|
||||
backgroundSize: "60px 60px",
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="absolute inset-0 pointer-events-none"
|
||||
style={{
|
||||
background:
|
||||
"radial-gradient(ellipse 70% 50% at 50% 30%, rgba(74,222,128,0.04) 0%, transparent 70%)",
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="relative z-10 max-w-2xl mx-auto">
|
||||
<p
|
||||
className="text-xs font-semibold uppercase tracking-widest mb-4"
|
||||
style={{ color: "#4ade80", letterSpacing: "0.2em" }}
|
||||
>
|
||||
Product
|
||||
</p>
|
||||
<h1
|
||||
className="text-5xl md:text-6xl font-semibold mb-5"
|
||||
style={{ letterSpacing: "-0.03em" }}
|
||||
>
|
||||
UIT
|
||||
</h1>
|
||||
<p className="text-base md:text-lg mb-8" style={{ color: "#888888", lineHeight: 1.7 }}>
|
||||
A multi-dimensional stock screener that evaluates every major US-listed
|
||||
equity across 8 scoring dimensions — weighted automatically to match
|
||||
your investor profile.
|
||||
</p>
|
||||
<a
|
||||
href="#pricing"
|
||||
className="inline-block px-6 py-3 text-sm font-medium rounded-sm transition-all duration-200"
|
||||
style={{ background: "#ffffff", color: "#000000" }}
|
||||
onMouseEnter={(e) => (e.currentTarget.style.background = "#e0e0e0")}
|
||||
onMouseLeave={(e) => (e.currentTarget.style.background = "#ffffff")}
|
||||
>
|
||||
Get Started
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── Evaluation Methods ───────────────────────────────────────────── */}
|
||||
<section className="py-24 px-6 border-t" style={{ borderColor: "#111111" }}>
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<FadeIn>
|
||||
<p
|
||||
className="text-xs font-semibold uppercase tracking-widest mb-3 text-center"
|
||||
style={{ color: "#3a3a3a", letterSpacing: "0.2em" }}
|
||||
>
|
||||
Methodology
|
||||
</p>
|
||||
<h2
|
||||
className="text-2xl md:text-3xl font-semibold text-center mb-3"
|
||||
style={{ letterSpacing: "-0.02em" }}
|
||||
>
|
||||
8-Dimension Composite Score
|
||||
</h2>
|
||||
<p className="text-sm text-center mb-12" style={{ color: "#888888" }}>
|
||||
Every stock is scored 0–100 independently. Weights shift automatically based on your selected investor profile.
|
||||
</p>
|
||||
</FadeIn>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
{dimensions.map((d, i) => (
|
||||
<FadeIn key={d.name} delay={i * 0.05}>
|
||||
<div
|
||||
className="p-5 rounded-sm border h-full"
|
||||
style={{ border: "1px solid #222222", background: "#111111" }}
|
||||
>
|
||||
<p className="text-sm font-semibold mb-3" style={{ color: "#ffffff" }}>
|
||||
{d.name}
|
||||
</p>
|
||||
<div className="flex flex-col gap-1">
|
||||
{d.methods.map((m) => (
|
||||
<p key={m} className="text-xs" style={{ color: "#888888" }}>
|
||||
{m}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</FadeIn>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Investor profiles */}
|
||||
<FadeIn delay={0.2}>
|
||||
<div className="mt-10 p-6 rounded-sm border" style={{ border: "1px solid #222222", background: "#111111" }}>
|
||||
<p className="text-xs font-semibold uppercase tracking-widest mb-4" style={{ color: "#3a3a3a", letterSpacing: "0.15em" }}>
|
||||
Investor Profiles
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{profiles.map((p) => (
|
||||
<span
|
||||
key={p}
|
||||
className="text-xs px-3 py-1 rounded-full border"
|
||||
style={{ border: "1px solid #222222", color: "#888888" }}
|
||||
>
|
||||
{p}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</FadeIn>
|
||||
|
||||
{/* Data sources */}
|
||||
<FadeIn delay={0.25}>
|
||||
<div className="mt-4 p-6 rounded-sm border" style={{ border: "1px solid #222222", background: "#111111" }}>
|
||||
<p className="text-xs font-semibold uppercase tracking-widest mb-4" style={{ color: "#3a3a3a", letterSpacing: "0.15em" }}>
|
||||
Data Sources
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{dataSources.map((s) => (
|
||||
<span
|
||||
key={s}
|
||||
className="text-xs px-3 py-1 rounded-full border"
|
||||
style={{ border: "1px solid #1a1a1a", color: "#4ade80", background: "#4ade8010" }}
|
||||
>
|
||||
{s}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</FadeIn>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── Pricing ──────────────────────────────────────────────────────── */}
|
||||
<section id="pricing" className="py-24 px-6 border-t" style={{ borderColor: "#111111" }}>
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<FadeIn>
|
||||
<p
|
||||
className="text-xs font-semibold uppercase tracking-widest mb-3 text-center"
|
||||
style={{ color: "#3a3a3a", letterSpacing: "0.2em" }}
|
||||
>
|
||||
Pricing
|
||||
</p>
|
||||
<h2
|
||||
className="text-2xl md:text-3xl font-semibold text-center mb-3"
|
||||
style={{ letterSpacing: "-0.02em" }}
|
||||
>
|
||||
One-time payment. No subscription required.
|
||||
</h2>
|
||||
<p className="text-sm text-center mb-12" style={{ color: "#888888" }}>
|
||||
Purchase a license key. Your key is emailed to you immediately after checkout.
|
||||
</p>
|
||||
</FadeIn>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
{pricingTiers.map((tier, i) => (
|
||||
<FadeIn key={tier.name} delay={i * 0.08}>
|
||||
<div
|
||||
className="relative p-6 rounded-sm border flex flex-col h-full"
|
||||
style={{
|
||||
border: tier.popular ? "1px solid #ffffff" : "1px solid #222222",
|
||||
background: tier.popular ? "#181818" : "#111111",
|
||||
}}
|
||||
>
|
||||
{tier.popular && (
|
||||
<div
|
||||
className="absolute -top-px left-1/2 -translate-x-1/2 px-3 py-0.5 text-xs font-semibold rounded-b-sm whitespace-nowrap"
|
||||
style={{ background: "#ffffff", color: "#000000" }}
|
||||
>
|
||||
Most Popular
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between mb-2 mt-1">
|
||||
<p className="text-sm font-semibold">{tier.name}</p>
|
||||
{tier.discount && (
|
||||
<span
|
||||
className="text-xs px-2 py-0.5 rounded-full font-semibold"
|
||||
style={{ background: "#4ade8018", color: "#4ade80", border: "1px solid #4ade8030" }}
|
||||
>
|
||||
{tier.discount}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Price */}
|
||||
<p className="text-4xl font-semibold mb-0.5" style={{ letterSpacing: "-0.03em" }}>
|
||||
{tier.price}
|
||||
</p>
|
||||
{tier.sub && (
|
||||
<p className="text-xs mb-0.5" style={{ color: "#4ade80" }}>
|
||||
{tier.sub}
|
||||
</p>
|
||||
)}
|
||||
<p className="text-xs mb-6" style={{ color: "#888888" }}>
|
||||
{tier.period}
|
||||
</p>
|
||||
|
||||
{/* Features */}
|
||||
<ul className="flex flex-col gap-2 mb-6 flex-1">
|
||||
{[
|
||||
"Full screener access",
|
||||
"All 7 investor profiles",
|
||||
"Hedge fund & insider data",
|
||||
"License key via email",
|
||||
].map((f) => (
|
||||
<li key={f} className="text-xs flex items-center gap-2" style={{ color: "#888888" }}>
|
||||
<span style={{ color: "#4ade80" }}>✓</span> {f}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
{/* CTA */}
|
||||
<button
|
||||
onClick={() => handleBuy(tier.priceId)}
|
||||
className="w-full py-2.5 text-sm font-medium rounded-sm transition-all duration-200"
|
||||
style={
|
||||
tier.popular
|
||||
? { background: "#ffffff", color: "#000000" }
|
||||
: { border: "1px solid #222222", color: "#ffffff", background: "transparent" }
|
||||
}
|
||||
onMouseEnter={(e) => {
|
||||
if (tier.popular) {
|
||||
e.currentTarget.style.background = "#e0e0e0";
|
||||
} else {
|
||||
e.currentTarget.style.borderColor = "#ffffff";
|
||||
}
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
if (tier.popular) {
|
||||
e.currentTarget.style.background = "#ffffff";
|
||||
} else {
|
||||
e.currentTarget.style.borderColor = "#222222";
|
||||
}
|
||||
}}
|
||||
>
|
||||
Buy Now
|
||||
</button>
|
||||
</div>
|
||||
</FadeIn>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<FadeIn delay={0.35}>
|
||||
<p className="text-xs text-center mt-8" style={{ color: "#3a3a3a" }}>
|
||||
Powered by Stripe. Your payment information is never stored on our servers.
|
||||
</p>
|
||||
</FadeIn>
|
||||
|
||||
{/* ── Active development strip ─────────────────────────────────── */}
|
||||
<FadeIn delay={0.4}>
|
||||
<div
|
||||
className="mt-8 flex items-start sm:items-center gap-4 px-6 py-5 rounded-sm border"
|
||||
style={{ border: "1px solid #1a1a1a", background: "#0f0f0f" }}
|
||||
>
|
||||
<div className="flex-shrink-0 flex items-center gap-2 pt-0.5 sm:pt-0">
|
||||
<span
|
||||
className="relative flex h-2 w-2"
|
||||
>
|
||||
<span
|
||||
className="animate-ping absolute inline-flex h-full w-full rounded-full opacity-60"
|
||||
style={{ background: "#4ade80" }}
|
||||
/>
|
||||
<span
|
||||
className="relative inline-flex rounded-full h-2 w-2"
|
||||
style={{ background: "#4ade80" }}
|
||||
/>
|
||||
</span>
|
||||
<span className="text-xs font-semibold whitespace-nowrap" style={{ color: "#4ade80" }}>
|
||||
Actively developed
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-xs leading-relaxed" style={{ color: "#888888" }}>
|
||||
UIT is updated regularly with new scoring signals, data sources, and improvements.
|
||||
All updates are included with every license — what you buy today keeps getting better.
|
||||
</p>
|
||||
</div>
|
||||
</FadeIn>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── Discord ──────────────────────────────────────────────────────── */}
|
||||
<section className="py-20 px-6 border-t" style={{ borderColor: "#111111" }}>
|
||||
<FadeIn>
|
||||
<div
|
||||
className="max-w-3xl mx-auto rounded-sm border p-10 text-center"
|
||||
style={{ border: "1px solid #222222", background: "#111111" }}
|
||||
>
|
||||
<p
|
||||
className="text-xs font-semibold uppercase tracking-widest mb-4"
|
||||
style={{ color: "#3a3a3a", letterSpacing: "0.2em" }}
|
||||
>
|
||||
Community
|
||||
</p>
|
||||
<h3 className="text-2xl font-semibold mb-3" style={{ letterSpacing: "-0.02em" }}>
|
||||
Join the UIT Discord
|
||||
</h3>
|
||||
<p className="text-sm mb-7" style={{ color: "#888888" }}>
|
||||
Get support, announcements, and connect with other UIT users.
|
||||
</p>
|
||||
<a
|
||||
href="DISCORD_INVITE_LINK"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-block px-6 py-3 text-sm font-medium rounded-sm border transition-all duration-200"
|
||||
style={{ border: "1px solid #222222", color: "#ffffff" }}
|
||||
onMouseEnter={(e) => (e.currentTarget.style.borderColor = "#ffffff")}
|
||||
onMouseLeave={(e) => (e.currentTarget.style.borderColor = "#222222")}
|
||||
>
|
||||
Join Server
|
||||
</a>
|
||||
</div>
|
||||
</FadeIn>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
"use client";
|
||||
|
||||
import { motion, useInView } from "framer-motion";
|
||||
import { useRef } from "react";
|
||||
|
||||
interface FadeInProps {
|
||||
children: React.ReactNode;
|
||||
delay?: number;
|
||||
direction?: "up" | "down" | "left" | "right" | "none";
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export default function FadeIn({
|
||||
children,
|
||||
delay = 0,
|
||||
direction = "up",
|
||||
className,
|
||||
}: FadeInProps) {
|
||||
const ref = useRef(null);
|
||||
const inView = useInView(ref, { once: true, margin: "-80px" });
|
||||
|
||||
const offsets = {
|
||||
up: { y: 28, x: 0 },
|
||||
down: { y: -28, x: 0 },
|
||||
left: { y: 0, x: 28 },
|
||||
right: { y: 0, x: -28 },
|
||||
none: { y: 0, x: 0 },
|
||||
};
|
||||
|
||||
const { x, y } = offsets[direction];
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
ref={ref}
|
||||
className={className}
|
||||
initial={{ opacity: 0, x, y }}
|
||||
animate={inView ? { opacity: 1, x: 0, y: 0 } : {}}
|
||||
transition={{ duration: 0.6, delay, ease: [0.22, 1, 0.36, 1] }}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
|
||||
export default function Footer() {
|
||||
const year = new Date().getFullYear();
|
||||
|
||||
return (
|
||||
<footer
|
||||
className="border-t mt-auto"
|
||||
style={{ borderColor: "#222222", background: "#0a0a0a" }}
|
||||
>
|
||||
{/* Disclaimer bar */}
|
||||
<div
|
||||
className="border-b px-6 py-3 text-center text-xs"
|
||||
style={{ borderColor: "#1a1a1a", color: "#3a3a3a" }}
|
||||
>
|
||||
UIT is for informational purposes only. Nothing on this site constitutes
|
||||
financial advice or a recommendation to buy or sell any security. Past
|
||||
performance does not guarantee future results. Consult a licensed financial
|
||||
advisor before making investment decisions.
|
||||
</div>
|
||||
|
||||
{/* Main footer */}
|
||||
<div className="max-w-6xl mx-auto px-6 py-10">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-10">
|
||||
{/* Brand */}
|
||||
<div>
|
||||
<div className="mb-3">
|
||||
<span className="text-sm font-semibold tracking-widest uppercase" style={{ letterSpacing: "0.15em" }}>
|
||||
Verimund
|
||||
</span>{" "}
|
||||
<span className="text-sm font-light tracking-widest uppercase" style={{ color: "#888888", letterSpacing: "0.15em" }}>
|
||||
Solutions
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-xs leading-relaxed" style={{ color: "#888888" }}>
|
||||
Finance-specialized SaaS tools built for serious investors.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Navigation */}
|
||||
<div>
|
||||
<p className="text-xs font-semibold uppercase tracking-widest mb-3" style={{ color: "#3a3a3a", letterSpacing: "0.12em" }}>
|
||||
Navigation
|
||||
</p>
|
||||
<div className="flex flex-col gap-2">
|
||||
{[
|
||||
{ href: "/", label: "Home" },
|
||||
{ href: "/uit", label: "UIT" },
|
||||
{ href: "/faq", label: "FAQ" },
|
||||
{ href: "/contact", label: "Contact" },
|
||||
].map(({ href, label }) => (
|
||||
<Link
|
||||
key={href}
|
||||
href={href}
|
||||
className="text-xs transition-colors duration-200"
|
||||
style={{ color: "#888888" }}
|
||||
onMouseEnter={(e) => (e.currentTarget.style.color = "#ffffff")}
|
||||
onMouseLeave={(e) => (e.currentTarget.style.color = "#888888")}
|
||||
>
|
||||
{label}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Contact + Legal */}
|
||||
<div>
|
||||
<p className="text-xs font-semibold uppercase tracking-widest mb-3" style={{ color: "#3a3a3a", letterSpacing: "0.12em" }}>
|
||||
Contact
|
||||
</p>
|
||||
<div className="flex flex-col gap-1 mb-5">
|
||||
<p className="text-xs" style={{ color: "#888888" }}>Nolan Kovacs — CEO</p>
|
||||
<p className="text-xs" style={{ color: "#888888" }}>248-252-9430</p>
|
||||
<p className="text-xs" style={{ color: "#888888" }}>
|
||||
{/* Placeholder until email is set up */}
|
||||
nolankovacs@verimundsolutions.com
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex gap-4">
|
||||
<Link href="/terms" className="text-xs transition-colors duration-200" style={{ color: "#3a3a3a" }}
|
||||
onMouseEnter={(e) => (e.currentTarget.style.color = "#888888")}
|
||||
onMouseLeave={(e) => (e.currentTarget.style.color = "#3a3a3a")}
|
||||
>
|
||||
Terms of Service
|
||||
</Link>
|
||||
<Link href="/privacy" className="text-xs transition-colors duration-200" style={{ color: "#3a3a3a" }}
|
||||
onMouseEnter={(e) => (e.currentTarget.style.color = "#888888")}
|
||||
onMouseLeave={(e) => (e.currentTarget.style.color = "#3a3a3a")}
|
||||
>
|
||||
Privacy Policy
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom row */}
|
||||
<div
|
||||
className="mt-10 pt-6 border-t flex flex-col md:flex-row items-center justify-between gap-3"
|
||||
style={{ borderColor: "#1a1a1a" }}
|
||||
>
|
||||
<p className="text-xs" style={{ color: "#3a3a3a" }}>
|
||||
© {year} Verimund Solutions. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
const links = [
|
||||
{ href: "/", label: "Home" },
|
||||
{ href: "/uit", label: "UIT" },
|
||||
{ href: "/faq", label: "FAQ" },
|
||||
{ href: "/contact", label: "Contact" },
|
||||
];
|
||||
|
||||
export default function Nav() {
|
||||
const pathname = usePathname();
|
||||
const [scrolled, setScrolled] = useState(false);
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const onScroll = () => setScrolled(window.scrollY > 20);
|
||||
window.addEventListener("scroll", onScroll, { passive: true });
|
||||
return () => window.removeEventListener("scroll", onScroll);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<header
|
||||
className="fixed top-0 left-0 right-0 z-50 transition-all duration-300"
|
||||
style={{
|
||||
background: scrolled ? "rgba(10,10,10,0.85)" : "transparent",
|
||||
backdropFilter: scrolled ? "blur(12px)" : "none",
|
||||
borderBottom: scrolled ? "1px solid #222222" : "1px solid transparent",
|
||||
}}
|
||||
>
|
||||
<div className="max-w-6xl mx-auto px-6 h-16 flex items-center justify-between">
|
||||
{/* Logo */}
|
||||
<Link href="/" className="flex items-center gap-2 group">
|
||||
<span
|
||||
className="text-sm font-semibold tracking-widest uppercase"
|
||||
style={{ color: "#ffffff", letterSpacing: "0.15em" }}
|
||||
>
|
||||
Verimund
|
||||
</span>
|
||||
<span
|
||||
className="text-sm font-light tracking-widest uppercase"
|
||||
style={{ color: "#888888", letterSpacing: "0.15em" }}
|
||||
>
|
||||
Solutions
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
{/* Desktop nav */}
|
||||
<nav className="hidden md:flex items-center gap-8">
|
||||
{links.map(({ href, label }) => {
|
||||
const active = pathname === href;
|
||||
return (
|
||||
<Link
|
||||
key={href}
|
||||
href={href}
|
||||
className="text-sm transition-colors duration-200"
|
||||
style={{
|
||||
color: active ? "#ffffff" : "#888888",
|
||||
fontWeight: active ? 500 : 400,
|
||||
}}
|
||||
onMouseEnter={(e) => (e.currentTarget.style.color = "#ffffff")}
|
||||
onMouseLeave={(e) =>
|
||||
(e.currentTarget.style.color = active ? "#ffffff" : "#888888")
|
||||
}
|
||||
>
|
||||
{label}
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
|
||||
{/* Mobile hamburger */}
|
||||
<button
|
||||
className="md:hidden flex flex-col gap-1.5 p-2"
|
||||
onClick={() => setMenuOpen(!menuOpen)}
|
||||
aria-label="Toggle menu"
|
||||
>
|
||||
<span
|
||||
className="block w-5 h-px transition-all duration-200"
|
||||
style={{
|
||||
background: "#ffffff",
|
||||
transform: menuOpen ? "rotate(45deg) translate(2px, 2px)" : "none",
|
||||
}}
|
||||
/>
|
||||
<span
|
||||
className="block w-5 h-px transition-all duration-200"
|
||||
style={{
|
||||
background: "#ffffff",
|
||||
opacity: menuOpen ? 0 : 1,
|
||||
}}
|
||||
/>
|
||||
<span
|
||||
className="block w-5 h-px transition-all duration-200"
|
||||
style={{
|
||||
background: "#ffffff",
|
||||
transform: menuOpen ? "rotate(-45deg) translate(2px, -2px)" : "none",
|
||||
}}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Mobile menu */}
|
||||
{menuOpen && (
|
||||
<div
|
||||
className="md:hidden border-t px-6 py-4 flex flex-col gap-4"
|
||||
style={{ background: "#0a0a0a", borderColor: "#222222" }}
|
||||
>
|
||||
{links.map(({ href, label }) => (
|
||||
<Link
|
||||
key={href}
|
||||
href={href}
|
||||
className="text-sm"
|
||||
style={{ color: pathname === href ? "#ffffff" : "#888888" }}
|
||||
onClick={() => setMenuOpen(false)}
|
||||
>
|
||||
{label}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
"name": "website",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"framer-motion": "^12.38.0",
|
||||
"next": "16.2.2",
|
||||
"react": "19.2.4",
|
||||
"react-dom": "19.2.4"
|
||||
|
|
@ -3621,6 +3622,33 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/framer-motion": {
|
||||
"version": "12.38.0",
|
||||
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.38.0.tgz",
|
||||
"integrity": "sha512-rFYkY/pigbcswl1XQSb7q424kSTQ8q6eAC+YUsSKooHQYuLdzdHjrt6uxUC+PRAO++q5IS7+TamgIw1AphxR+g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"motion-dom": "^12.38.0",
|
||||
"motion-utils": "^12.36.0",
|
||||
"tslib": "^2.4.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emotion/is-prop-valid": "*",
|
||||
"react": "^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^18.0.0 || ^19.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@emotion/is-prop-valid": {
|
||||
"optional": true
|
||||
},
|
||||
"react": {
|
||||
"optional": true
|
||||
},
|
||||
"react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
|
|
@ -4936,6 +4964,21 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/motion-dom": {
|
||||
"version": "12.38.0",
|
||||
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.38.0.tgz",
|
||||
"integrity": "sha512-pdkHLD8QYRp8VfiNLb8xIBJis1byQ9gPT3Jnh2jqfFtAsWUA3dEepDlsWe/xMpO8McV+VdpKVcp+E+TGJEtOoA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"motion-utils": "^12.36.0"
|
||||
}
|
||||
},
|
||||
"node_modules/motion-utils": {
|
||||
"version": "12.36.0",
|
||||
"resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.36.0.tgz",
|
||||
"integrity": "sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
"lint": "eslint"
|
||||
},
|
||||
"dependencies": {
|
||||
"framer-motion": "^12.38.0",
|
||||
"next": "16.2.2",
|
||||
"react": "19.2.4",
|
||||
"react-dom": "19.2.4"
|
||||
|
|
|
|||
Loading…
Reference in New Issue