Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ const nextConfig: NextConfig = {
const contentSecurityPolicy = [
"default-src 'self'",
"script-src 'self' 'unsafe-inline' https://www.googletagmanager.com https://www.google-analytics.com",
"style-src 'self' https://fonts.googleapis.com",
// 'unsafe-inline' for style-src: server-rendered style attributes (safe-area
// insets, next/image sizing, animation stagger delays) and Next.js-injected
// <style> tags are otherwise blocked by a static policy. Same trade-off as
// script-src above; the site renders no user-supplied HTML.
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
"img-src 'self' data: https://placehold.co",
"connect-src 'self' https://www.google-analytics.com https://www.googletagmanager.com",
"font-src 'self' data: https://fonts.gstatic.com",
Expand Down
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
},
"dependencies": {
"@fontsource-variable/inter": "^5.2.8",
"@fontsource-variable/space-grotesk": "^5.2.10",
"@hookform/resolvers": "^5.2.2",
"@radix-ui/react-accordion": "^1.2.12",
"@radix-ui/react-alert-dialog": "^1.1.15",
Expand Down
Binary file added src/app/fonts/SpaceGroteskVariable.woff2
Binary file not shown.
123 changes: 119 additions & 4 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -995,19 +995,25 @@

/* Typography Enhancement Classes */
.heading-hero {
@apply text-4xl font-bold tracking-tighter sm:text-5xl xl:text-6xl/none text-foreground;
@apply font-display text-4xl font-bold tracking-tighter sm:text-5xl xl:text-6xl/none text-foreground;
}

.heading-section {
@apply text-3xl font-bold sm:text-4xl text-foreground;
@apply font-display text-3xl font-bold sm:text-4xl text-foreground;
}

.heading-card {
@apply text-2xl font-bold text-foreground;
@apply font-display text-2xl font-bold text-foreground;
}

.heading-subsection {
@apply text-xl font-bold text-foreground;
@apply font-display text-xl font-bold text-foreground;
}

/* Display font for all landing headings */
h1,
h2 {
@apply font-display;
}

.text-body-lg {
Expand Down Expand Up @@ -1104,3 +1110,112 @@
.grid-hero {
@apply grid lg:grid-cols-2 gap-12 lg:gap-20 items-center;
}

/* ==========================================================================
VISUAL REVAMP UTILITIES - Patterns, glows and premium accents
========================================================================== */

/* Dotted backdrop, fades out toward the edges */
.bg-dot-pattern {
background-image: radial-gradient(hsl(var(--foreground) / 0.09) 1px, transparent 1px);
background-size: 24px 24px;
mask-image: radial-gradient(ellipse 80% 70% at 50% 40%, black 30%, transparent 75%);
-webkit-mask-image: radial-gradient(ellipse 80% 70% at 50% 40%, black 30%, transparent 75%);
}

/* Fine grid backdrop for section accents */
.bg-grid-pattern {
background-image:
linear-gradient(hsl(var(--border) / 0.6) 1px, transparent 1px),
linear-gradient(90deg, hsl(var(--border) / 0.6) 1px, transparent 1px);
background-size: 44px 44px;
mask-image: radial-gradient(ellipse 90% 80% at 50% 30%, black 20%, transparent 75%);
-webkit-mask-image: radial-gradient(ellipse 90% 80% at 50% 30%, black 20%, transparent 75%);
}

/* Gradient border that lights up on hover (works on cards with overflow-hidden removed) */
.card-glow-border {
position: relative;
border: 1px solid hsl(var(--border) / 0.6);
transition: border-color 0.3s ease, box-shadow 0.3s ease, transform 0.3s ease;
}

.card-glow-border:hover {
border-color: hsl(var(--primary) / 0.45);
box-shadow:
0 0 0 1px hsl(var(--primary) / 0.25),
0 18px 40px -16px hsl(var(--primary) / 0.35);
}

/* Sweeping sheen used by the premium CTA button */
.btn-shine-overlay::after {
content: "";
position: absolute;
inset: 0;
width: 40%;
background: linear-gradient(
100deg,
transparent 20%,
hsl(0 0% 100% / 0.35) 50%,
transparent 80%
);
transform: translateX(-150%) skewX(-15deg);
pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
.btn-shine-overlay::after {
animation: shine-sweep 2.75s ease-in-out infinite;
}
}

@keyframes shine-sweep {
0% {
transform: translateX(-150%) skewX(-15deg);
}

60%,
100% {
transform: translateX(350%) skewX(-15deg);
}
}

/* Underline slide-in for nav links */
.nav-link-underline {
position: relative;
}

.nav-link-underline::after {
content: "";
position: absolute;
left: 0;
right: 100%;
bottom: -4px;
height: 2px;
border-radius: 9999px;
background: hsl(var(--primary));
transition: right 0.25s ease-out;
}

.nav-link-underline:hover::after,
.nav-link-underline:focus-visible::after {
right: 0;
}

/* Soft ambient orb for hero backgrounds */
.hero-orb {
position: absolute;
border-radius: 9999px;
background: radial-gradient(circle, hsl(var(--primary) / 0.28) 0%, transparent 70%);
filter: blur(60px);
pointer-events: none;
}

/* Disable decorative motion for users who prefer reduced motion */
@media (prefers-reduced-motion: reduce) {
.animate-float,
.animate-pulse-glow,
.animate-gradient-x {
animation: none !important;
}
}
9 changes: 8 additions & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ const inter = localFont({
display: "swap",
});

const spaceGrotesk = localFont({
src: "./fonts/SpaceGroteskVariable.woff2",
variable: "--font-display",
weight: "300 700",
display: "swap",
});

export default function RootLayout({
children,
}: Readonly<{
Expand Down Expand Up @@ -123,7 +130,7 @@ export default function RootLayout({
}}
/>
</head>
<body className={`${inter.variable} font-body antialiased`}>
<body className={`${inter.variable} ${spaceGrotesk.variable} font-body antialiased`}>
<Providers gaMeasurementId={GA_MEASUREMENT_ID}>
{children}
</Providers>
Expand Down
2 changes: 2 additions & 0 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { EnhancedHomeHeroSection } from '@/components/landing/EnhancedHomeHeroSe
import { EducationalSection } from '@/components/landing/EducationalSection';
import { AboutSection } from '@/components/landing/AboutSection';
import { TestimonialsSection } from '@/components/landing/TestimonialsSection';
import { FinalCtaSection } from '@/components/landing/FinalCtaSection';
import { Footer } from '@/components/landing/Footer';
import { PrivacyPolicyModal } from '@/components/landing/PrivacyPolicyModal';
import { TermsOfServiceModal } from '@/components/landing/TermsOfServiceModal';
Expand All @@ -26,6 +27,7 @@ export default function Home() {
<EducationalSection />
<TestimonialsSection />
<AboutSection />
<FinalCtaSection />
</main>
<Footer onPrivacyClick={openPrivacyModal} onTermsClick={openTermsModal} />
<PrivacyPolicyModal isOpen={activeModal === 'privacy'} onOpenChange={handlePrivacyChange} />
Expand Down
13 changes: 7 additions & 6 deletions src/components/landing/AboutSection.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { BackgroundBeams } from "@/components/ui/background-beams";
import Image from "next/image";
import { ValueBadge } from "@/components/ui/value-badge";
import { Reveal } from "@/components/ui/reveal";
import { Eye, Shield, Bitcoin, Users } from "lucide-react";

export function AboutSection() {
Expand All @@ -10,7 +11,7 @@ export function AboutSection() {
<div className="container max-w-7xl mx-auto px-4 md:px-6 relative z-10">
<div className="grid lg:grid-cols-2 gap-12 lg:gap-20 items-center">
{/* Image Side */}
<div className="relative order-2 lg:order-1">
<Reveal from="left" className="relative order-2 lg:order-1">
<div className="relative rounded-2xl overflow-hidden shadow-2xl shadow-primary/5 aspect-4/3">
<div className="absolute inset-0 bg-linear-to-tr from-primary/10 to-transparent mix-blend-overlay z-10" />
<Image
Expand All @@ -21,18 +22,18 @@ export function AboutSection() {
/>
</div>
{/* Decorative elements */}
<div className="absolute -bottom-6 -right-6 w-24 h-24 bg-primary/10 rounded-full blur-2xl" />
<div className="absolute -bottom-6 -right-6 w-24 h-24 bg-primary/15 rounded-full blur-2xl motion-safe:animate-pulse-glow" />
<div className="absolute -top-6 -left-6 w-32 h-32 bg-primary/10 rounded-full blur-3xl" />
</div>
</Reveal>

{/* Content Side */}
<div className="space-y-8 order-1 lg:order-2 text-center lg:text-left">
<Reveal from="right" className="space-y-8 order-1 lg:order-2 text-center lg:text-left">
<div className="inline-flex items-center px-4 py-2 rounded-full bg-background border border-border shadow-xs mb-2">
<Users className="mr-2 h-4 w-4 text-primary" />
<span className="text-sm font-medium">Our Mission</span>
</div>

<h2 className="text-3xl md:text-4xl lg:text-5xl font-bold tracking-tight">
<h2 className="font-display text-3xl md:text-4xl lg:text-5xl font-bold tracking-tight">
Built for Bitcoiners, <br />
<span className="text-primary">By Bitcoiners.</span>
</h2>
Expand All @@ -53,7 +54,7 @@ export function AboutSection() {
<ValueBadge icon={Shield} text="Privacy Focused" variant="primary" />
<ValueBadge icon={Bitcoin} text="Bitcoin Native" variant="primary" />
</div>
</div>
</Reveal>
</div>
</div>
</section>
Expand Down
11 changes: 6 additions & 5 deletions src/components/landing/AnalyzerAboutSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { BackgroundBeams } from "@/components/ui/background-beams";
import Image from "next/image";
import { ValueBadge } from "@/components/ui/value-badge";
import { Reveal } from "@/components/ui/reveal";
import { Bitcoin, Shield, Blocks } from "lucide-react";

export function AnalyzerAboutSection() {
Expand All @@ -11,7 +12,7 @@ export function AnalyzerAboutSection() {
<div className="container max-w-7xl mx-auto px-4 md:px-6 relative z-10">
<div className="grid lg:grid-cols-2 gap-12 lg:gap-20 items-center">
{/* Image Side */}
<div className="relative order-2 lg:order-1">
<Reveal from="left" className="relative order-2 lg:order-1">
<div className="relative rounded-2xl overflow-hidden shadow-2xl shadow-primary/5 aspect-4/3">
<div className="absolute inset-0 bg-linear-to-tr from-primary/10 to-transparent mix-blend-overlay z-10" />
<Image
Expand All @@ -24,11 +25,11 @@ export function AnalyzerAboutSection() {
{/* Decorative elements */}
<div className="absolute -bottom-6 -right-6 w-24 h-24 bg-primary/10 rounded-full blur-2xl" />
<div className="absolute -top-6 -left-6 w-32 h-32 bg-primary/10 rounded-full blur-3xl" />
</div>
</Reveal>

{/* Content Side */}
<div className="space-y-8 order-1 lg:order-2 text-center lg:text-left">
<h2 className="text-3xl md:text-4xl lg:text-5xl font-bold tracking-tight text-foreground">
<Reveal from="right" className="space-y-8 order-1 lg:order-2 text-center lg:text-left">
<h2 className="font-display text-3xl md:text-4xl lg:text-5xl font-bold tracking-tight text-foreground">
About <span className="text-primary">BitSleuth Analyzer</span>
</h2>
<p className="text-lg text-muted-foreground leading-relaxed">
Expand All @@ -51,7 +52,7 @@ export function AnalyzerAboutSection() {
<ValueBadge icon={Blocks} text="On-Chain Transparency" variant="primary" />
<ValueBadge icon={Shield} text="Privacy Tools" variant="primary" />
</div>
</div>
</Reveal>
</div>
</div>
</section>
Expand Down
24 changes: 8 additions & 16 deletions src/components/landing/DemoPreviewSection.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Button } from "@/components/ui/button";
import { BackgroundBeams } from "@/components/ui/background-beams";
import { Reveal } from "@/components/ui/reveal";
import Image from "next/image";

export function DemoPreviewSection() {
Expand All @@ -8,9 +9,9 @@ export function DemoPreviewSection() {
<BackgroundBeams intensity="subtle" className="opacity-20" />
<div className="container max-w-6xl mx-auto relative z-10">
<div className="grid md:grid-cols-2 gap-12 items-center">
<div className="text-left space-y-6">
<Reveal from="left" className="text-left space-y-6">
<div>
<h2 className="text-3xl font-bold mb-4 text-foreground">
<h2 className="font-display text-3xl font-bold sm:text-4xl mb-4 text-foreground">
Try It <span className="text-primary">Yourself</span>
</h2>
<p className="text-lg text-muted-foreground font-normal">
Expand All @@ -19,26 +20,17 @@ export function DemoPreviewSection() {
</p>
</div>
<div className="flex flex-wrap gap-4">
<Button
asChild
size="lg"
className="bg-primary hover:bg-primary/90 text-primary-foreground shadow-none"
>
<Button asChild variant="shine" size="xl">
<a href="https://app.bitsleuth.ai/">Try Live App</a>
</Button>
<Button
asChild
variant="outline"
size="lg"
className="hover:border-primary hover:text-primary"
>
<Button asChild variant="outline" size="xl">
<a href="https://app.bitsleuth.ai/transactions/7247020e42abe2cc3730f277f7f14579db63f0b3c68dfbaf4626d4d4c11704e8">
See Example Wallet
</a>
</Button>
</div>
</div>
<div className="rounded-lg border shadow-2xl overflow-hidden transform hover:scale-105 transition-transform duration-500 shadow-primary/10 hover:border-primary/50">
</Reveal>
<Reveal from="right" className="rounded-lg card-glow-border shadow-2xl overflow-hidden transform hover:scale-[1.03] transition-transform duration-500 shadow-primary/10">
<Image
src="/images/interactive-preview.png"
width={1200}
Expand All @@ -48,7 +40,7 @@ export function DemoPreviewSection() {
data-ai-hint="bitcoin transaction"
className="w-full"
/>
</div>
</Reveal>
</div>
</div>
</section>
Expand Down
Loading