feat: Complete public frontend redesign - Award Winning UI
Some checks failed
CI / Frontend Lint & Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Backend Lint (push) Has been cancelled
CI / Backend Tests (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
Deploy / Build & Push Images (push) Has been cancelled
Deploy / Deploy to Server (push) Has been cancelled
Deploy / Notify (push) Has been cancelled
Some checks failed
CI / Frontend Lint & Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Backend Lint (push) Has been cancelled
CI / Backend Tests (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
Deploy / Build & Push Images (push) Has been cancelled
Deploy / Deploy to Server (push) Has been cancelled
Deploy / Notify (push) Has been cancelled
- Redesigned all public pages (Landing, Acquire, Discover, Yield, Pricing) to "Award Winning" tech-chic style - Implemented auth pages (Login, Register, Forgot Password, Verify Email) with animated glow backgrounds - Renamed routes: /market -> /acquire, /intel -> /discover - Created footer pages: About, Contact, Briefings - Created legal pages: Privacy Policy, Terms of Service, Imprint - Updated Header & Footer components to match new design system - Enhanced DomainChecker with typing animation and angular tech design - All pages now feature: deep dark backgrounds, noise overlays, tech borders, glassmorphism effects - Responsive design optimized for all screen sizes - Consistent typography using font-display and font-mono throughout
This commit is contained in:
@ -2,187 +2,158 @@
|
||||
|
||||
import { Header } from '@/components/Header'
|
||||
import { Footer } from '@/components/Footer'
|
||||
import { Target, Shield, Zap, Users, Globe, TrendingUp, ArrowRight } from 'lucide-react'
|
||||
import { Target, Shield, Zap, Users, Globe, ArrowRight } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
|
||||
const values = [
|
||||
{
|
||||
icon: Target,
|
||||
title: 'Precision',
|
||||
description: 'Accurate data. No guesswork. Every check counts.',
|
||||
},
|
||||
{
|
||||
icon: Shield,
|
||||
title: 'Privacy',
|
||||
description: 'Your strategy stays yours. We never share or sell data.',
|
||||
},
|
||||
{
|
||||
icon: Zap,
|
||||
title: 'Speed',
|
||||
description: 'Real-time intel. You see it first.',
|
||||
},
|
||||
{
|
||||
icon: Users,
|
||||
title: 'Transparency',
|
||||
description: 'Clear pricing. No surprises. Ever.',
|
||||
},
|
||||
]
|
||||
|
||||
const stats = [
|
||||
{ value: '500K+', label: 'Domains Tracked' },
|
||||
{ value: '99.9%', label: 'Uptime' },
|
||||
{ value: '50ms', label: 'Response Time' },
|
||||
{ value: '24/7', label: 'Always On' },
|
||||
]
|
||||
|
||||
const team = [
|
||||
{
|
||||
name: 'Domain Intel',
|
||||
role: 'Core',
|
||||
description: 'WHOIS + RDAP queries. Accurate. Reliable. Always.',
|
||||
},
|
||||
{
|
||||
name: 'Price Tracking',
|
||||
role: 'Market',
|
||||
description: 'Real-time TLD pricing. Know what domains cost.',
|
||||
},
|
||||
{
|
||||
name: 'Instant Alerts',
|
||||
role: 'Notify',
|
||||
description: 'Domain drops? You know first. Email or webhook.',
|
||||
},
|
||||
{ value: '500K+', label: 'ASSETS TRACKED' },
|
||||
{ value: '99.9%', label: 'SYSTEM UPTIME' },
|
||||
{ value: '50ms', label: 'SCAN LATENCY' },
|
||||
{ value: '24/7', label: 'LIVE MONITOR' },
|
||||
]
|
||||
|
||||
export default function AboutPage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-background relative flex flex-col">
|
||||
{/* Ambient glow */}
|
||||
<div className="fixed inset-0 pointer-events-none">
|
||||
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-[600px] h-[400px] bg-accent/[0.02] rounded-full blur-3xl" />
|
||||
<div className="min-h-screen bg-[#020202] text-white relative overflow-x-hidden selection:bg-accent/30 selection:text-white">
|
||||
{/* Background Atmosphere */}
|
||||
<div className="fixed inset-0 pointer-events-none z-0">
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.03] mix-blend-overlay" />
|
||||
<div
|
||||
className="absolute inset-0 opacity-[0.03]"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(rgba(255,255,255,0.3) 0.5px, transparent 0.5px), linear-gradient(90deg, rgba(255,255,255,0.3) 0.5px, transparent 0.5px)`,
|
||||
backgroundSize: '160px 160px',
|
||||
}}
|
||||
/>
|
||||
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-[800px] h-[400px] bg-accent/[0.02] rounded-full blur-[120px]" />
|
||||
</div>
|
||||
|
||||
<Header />
|
||||
|
||||
<main className="relative pt-32 sm:pt-36 pb-20 px-4 sm:px-6 flex-1">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<main className="relative pt-32 sm:pt-40 pb-20 px-4 sm:px-6 flex-1">
|
||||
<div className="max-w-[1200px] mx-auto">
|
||||
{/* Hero */}
|
||||
<div className="text-center mb-16 sm:mb-20 animate-fade-in">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1.5 bg-background-secondary/80 backdrop-blur-sm border border-border rounded-full mb-6">
|
||||
<Globe className="w-4 h-4 text-accent" />
|
||||
<span className="text-ui-sm text-foreground-muted">About pounce</span>
|
||||
</div>
|
||||
<h1 className="font-display text-[2.25rem] sm:text-[3rem] md:text-[3.75rem] leading-[1.1] tracking-[-0.035em] text-foreground mb-6">
|
||||
<div className="text-center mb-20 sm:mb-28 animate-fade-in">
|
||||
<span className="text-accent font-mono text-xs uppercase tracking-[0.2em] mb-4 block flex items-center justify-center gap-2">
|
||||
<div className="w-1.5 h-1.5 bg-accent animate-pulse" />
|
||||
Mission Briefing
|
||||
</span>
|
||||
<h1 className="font-display text-[3.5rem] sm:text-[5rem] md:text-[6rem] leading-[0.9] tracking-[-0.04em] text-white mb-8">
|
||||
Built for hunters.
|
||||
<br />
|
||||
<span className="text-foreground-muted">By hunters.</span>
|
||||
<span className="text-white/30">By hunters.</span>
|
||||
</h1>
|
||||
<p className="text-body-lg text-foreground-muted max-w-2xl mx-auto">
|
||||
<p className="text-lg sm:text-xl text-white/50 max-w-2xl mx-auto font-light leading-relaxed">
|
||||
POUNCE exists for one reason: to give you the edge.
|
||||
Track domains. See opportunities. Move first.
|
||||
Track assets. See opportunities. Move first.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Stats */}
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-20 animate-slide-up">
|
||||
{/* Stats Grid - Bento Style */}
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-px bg-white/10 border border-white/10 mb-32 animate-slide-up">
|
||||
{stats.map((stat) => (
|
||||
<div
|
||||
key={stat.label}
|
||||
className="p-6 bg-background-secondary/50 border border-border rounded-xl text-center"
|
||||
className="bg-[#020202] p-8 sm:p-10 text-center group hover:bg-[#050505] transition-colors"
|
||||
>
|
||||
<p className="text-heading-md sm:text-heading-lg font-display text-accent mb-1">
|
||||
<div className="text-3xl sm:text-4xl font-display text-white mb-2 group-hover:text-accent transition-colors">
|
||||
{stat.value}
|
||||
</p>
|
||||
<p className="text-ui-sm text-foreground-muted">{stat.label}</p>
|
||||
</div>
|
||||
<div className="text-[10px] font-mono uppercase tracking-widest text-white/30">{stat.label}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Mission */}
|
||||
<section className="mb-20 animate-slide-up">
|
||||
<div className="p-8 sm:p-10 bg-gradient-to-br from-accent/10 via-accent/5 to-transparent border border-accent/20 rounded-2xl">
|
||||
<h2 className="text-heading-sm sm:text-heading-md font-medium text-foreground mb-4">
|
||||
The Mission
|
||||
</h2>
|
||||
<p className="text-body-lg text-foreground-muted leading-relaxed">
|
||||
Level the playing field. Domain intel shouldn't be locked behind enterprise
|
||||
paywalls. With POUNCE, anyone can track domains, spot trends, and strike
|
||||
when the iron's hot. Simple tools. Powerful results.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
<div className="grid lg:grid-cols-2 gap-16 lg:gap-24 items-center mb-32">
|
||||
<div className="animate-slide-up">
|
||||
<span className="text-accent font-mono text-xs uppercase tracking-[0.2em] mb-4 block">The Objective</span>
|
||||
<h2 className="font-display text-4xl sm:text-5xl text-white mb-8">Level the playing field.</h2>
|
||||
<div className="space-y-6 text-white/60 text-lg font-light leading-relaxed">
|
||||
<p>
|
||||
Domain intelligence shouldn't be locked behind enterprise paywalls or hidden in archaic CLI tools.
|
||||
</p>
|
||||
<p>
|
||||
We built POUNCE to democratize access to high-value digital assets. Whether you're a sniper looking for a single drop or a whale managing a portfolio, our tools give you the same firepower.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative animate-scale-in delay-100">
|
||||
<div className="absolute -inset-4 bg-accent/5 blur-2xl" />
|
||||
<div className="relative border border-white/10 bg-[#050505] p-10">
|
||||
<div className="absolute top-0 right-0 p-4">
|
||||
<Globe className="w-12 h-12 text-white/10" />
|
||||
</div>
|
||||
<h3 className="font-display text-2xl text-white mb-6">Global Coverage</h3>
|
||||
<ul className="space-y-4 font-mono text-sm text-white/50">
|
||||
<li className="flex justify-between border-b border-white/5 pb-2">
|
||||
<span>Registrars</span>
|
||||
<span className="text-white">50+ Connected</span>
|
||||
</li>
|
||||
<li className="flex justify-between border-b border-white/5 pb-2">
|
||||
<span>TLDs</span>
|
||||
<span className="text-white">886 Supported</span>
|
||||
</li>
|
||||
<li className="flex justify-between border-b border-white/5 pb-2">
|
||||
<span>Refresh Rate</span>
|
||||
<span className="text-white">Real-time</span>
|
||||
</li>
|
||||
<li className="flex justify-between">
|
||||
<span>Data Source</span>
|
||||
<span className="text-white">WHOIS / RDAP / DNS</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Values */}
|
||||
<section className="mb-20">
|
||||
<h2 className="text-heading-sm sm:text-heading-md font-medium text-foreground mb-8 text-center">
|
||||
Our Code
|
||||
</h2>
|
||||
<div className="grid sm:grid-cols-2 gap-4">
|
||||
{values.map((value, i) => (
|
||||
<div className="mb-32">
|
||||
<h2 className="font-display text-3xl text-white text-center mb-16">Operational Code</h2>
|
||||
<div className="grid sm:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
{[
|
||||
{ icon: Target, title: 'Precision', desc: 'Accurate data. No guesswork. Every check counts.' },
|
||||
{ icon: Shield, title: 'Privacy', desc: 'Your strategy stays yours. We never share or sell data.' },
|
||||
{ icon: Zap, title: 'Speed', desc: 'Real-time intel. You see it first.' },
|
||||
{ icon: Users, title: 'Transparency', desc: 'Clear pricing. No surprises. Ever.' },
|
||||
].map((value, i) => (
|
||||
<div
|
||||
key={value.title}
|
||||
className="p-6 bg-background-secondary/50 border border-border rounded-xl hover:border-border-hover transition-all duration-300 animate-slide-up"
|
||||
style={{ animationDelay: `${i * 100}ms` }}
|
||||
className="p-8 border border-white/10 bg-[#050505] hover:border-accent/30 transition-all group"
|
||||
>
|
||||
<div className="w-10 h-10 bg-background-tertiary rounded-lg flex items-center justify-center mb-4">
|
||||
<value.icon className="w-5 h-5 text-accent" />
|
||||
</div>
|
||||
<h3 className="text-body font-medium text-foreground mb-2">{value.title}</h3>
|
||||
<p className="text-body-sm text-foreground-muted">{value.description}</p>
|
||||
<value.icon className="w-8 h-8 text-white/20 group-hover:text-accent mb-6 transition-colors" />
|
||||
<h3 className="font-display text-xl text-white mb-3">{value.title}</h3>
|
||||
<p className="font-mono text-xs text-white/40 leading-relaxed">{value.desc}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Features */}
|
||||
<section className="mb-20">
|
||||
<h2 className="text-heading-sm sm:text-heading-md font-medium text-foreground mb-8 text-center">
|
||||
What We Do
|
||||
</h2>
|
||||
<div className="space-y-4">
|
||||
{team.map((item, i) => (
|
||||
<div
|
||||
key={item.name}
|
||||
className="p-6 bg-background-secondary/30 border border-border rounded-xl flex flex-col sm:flex-row sm:items-center gap-4 animate-slide-up"
|
||||
style={{ animationDelay: `${i * 100}ms` }}
|
||||
>
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<h3 className="text-body font-medium text-foreground">{item.name}</h3>
|
||||
<span className="text-ui-xs text-accent bg-accent-muted px-2 py-0.5 rounded-full">
|
||||
{item.role}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-body-sm text-foreground-muted">{item.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
{/* CTA */}
|
||||
<section className="text-center animate-slide-up">
|
||||
<h2 className="text-heading-sm sm:text-heading-md font-medium text-foreground mb-4">
|
||||
Ready to hunt?
|
||||
</h2>
|
||||
<p className="text-body text-foreground-muted mb-8">
|
||||
Join the hunters who move first.
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row items-center justify-center gap-3">
|
||||
<Link
|
||||
href="/register"
|
||||
className="flex items-center gap-2 px-6 py-3 bg-accent text-background font-medium rounded-xl hover:bg-accent-hover transition-all"
|
||||
>
|
||||
Start Hunting
|
||||
<ArrowRight className="w-4 h-4" />
|
||||
</Link>
|
||||
<Link
|
||||
href="/contact"
|
||||
className="flex items-center gap-2 px-6 py-3 bg-background-secondary border border-border text-foreground font-medium rounded-xl hover:border-border-hover transition-all"
|
||||
>
|
||||
Get in Touch
|
||||
</Link>
|
||||
<div className="text-center bg-[#050505] border border-white/10 p-12 sm:p-20 relative overflow-hidden">
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.05]" />
|
||||
<div className="relative z-10">
|
||||
<h2 className="font-display text-4xl sm:text-5xl text-white mb-6">Ready to deploy?</h2>
|
||||
<p className="text-white/50 mb-10 max-w-lg mx-auto font-mono text-sm">
|
||||
Join the elite circle of investors who stop guessing and start knowing.
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row items-center justify-center gap-6">
|
||||
<Link
|
||||
href="/register"
|
||||
className="px-8 py-4 bg-accent text-black text-xs font-bold uppercase tracking-[0.2em] hover:bg-white transition-all shadow-[0_0_20px_rgba(16,185,129,0.2)]"
|
||||
style={{ clipPath: 'polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px)' }}
|
||||
>
|
||||
Start Hunting
|
||||
</Link>
|
||||
<Link
|
||||
href="/contact"
|
||||
className="px-8 py-4 border border-white/20 text-white text-xs font-bold uppercase tracking-[0.2em] hover:bg-white hover:text-black transition-all"
|
||||
>
|
||||
Contact HQ
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
@ -190,4 +161,3 @@ export default function AboutPage() {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
652
frontend/src/app/acquire/page.tsx
Normal file
652
frontend/src/app/acquire/page.tsx
Normal file
@ -0,0 +1,652 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useState, useMemo } from 'react'
|
||||
import { useStore } from '@/lib/store'
|
||||
import { api } from '@/lib/api'
|
||||
import { Header } from '@/components/Header'
|
||||
import { Footer } from '@/components/Footer'
|
||||
import { PlatformBadge } from '@/components/PremiumTable'
|
||||
import {
|
||||
Clock,
|
||||
ExternalLink,
|
||||
Search,
|
||||
Flame,
|
||||
Timer,
|
||||
Gavel,
|
||||
DollarSign,
|
||||
X,
|
||||
Lock,
|
||||
TrendingUp,
|
||||
ChevronUp,
|
||||
ChevronDown,
|
||||
ChevronsUpDown,
|
||||
Sparkles,
|
||||
Diamond,
|
||||
ShieldCheck,
|
||||
Zap,
|
||||
Filter,
|
||||
Check,
|
||||
Shield,
|
||||
ArrowUpRight,
|
||||
ArrowRight
|
||||
} from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import clsx from 'clsx'
|
||||
|
||||
interface MarketItem {
|
||||
id: string
|
||||
domain: string
|
||||
tld: string
|
||||
price: number
|
||||
currency: string
|
||||
price_type: 'bid' | 'fixed' | 'negotiable'
|
||||
status: 'auction' | 'instant'
|
||||
source: string
|
||||
is_pounce: boolean
|
||||
verified: boolean
|
||||
time_remaining?: string
|
||||
end_time?: string
|
||||
num_bids?: number
|
||||
slug?: string
|
||||
seller_verified: boolean
|
||||
url: string
|
||||
is_external: boolean
|
||||
pounce_score: number
|
||||
}
|
||||
|
||||
interface Auction {
|
||||
domain: string
|
||||
platform: string
|
||||
platform_url: string
|
||||
current_bid: number
|
||||
currency: string
|
||||
num_bids: number
|
||||
end_time: string
|
||||
time_remaining: string
|
||||
buy_now_price: number | null
|
||||
reserve_met: boolean | null
|
||||
traffic: number | null
|
||||
age_years: number | null
|
||||
tld: string
|
||||
affiliate_url: string
|
||||
}
|
||||
|
||||
type TabType = 'all' | 'ending' | 'hot'
|
||||
type SortField = 'domain' | 'ending' | 'bid' | 'bids'
|
||||
type SortDirection = 'asc' | 'desc'
|
||||
|
||||
const PLATFORMS = [
|
||||
{ id: 'All', name: 'All Sources' },
|
||||
{ id: 'GoDaddy', name: 'GoDaddy' },
|
||||
{ id: 'Sedo', name: 'Sedo' },
|
||||
{ id: 'NameJet', name: 'NameJet' },
|
||||
{ id: 'DropCatch', name: 'DropCatch' },
|
||||
]
|
||||
|
||||
// Premium TLDs that look professional
|
||||
const PREMIUM_TLDS = ['com', 'io', 'ai', 'co', 'de', 'ch', 'net', 'org', 'app', 'dev', 'xyz']
|
||||
|
||||
// Vanity Filter: Only show "beautiful" domains to non-authenticated users
|
||||
function isVanityDomain(auction: Auction): boolean {
|
||||
const domain = auction.domain
|
||||
const parts = domain.split('.')
|
||||
if (parts.length < 2) return false
|
||||
|
||||
const name = parts[0]
|
||||
const tld = parts.slice(1).join('.').toLowerCase()
|
||||
|
||||
// Check TLD is premium
|
||||
if (!PREMIUM_TLDS.includes(tld)) return false
|
||||
|
||||
// Check length (max 12 characters for the name)
|
||||
if (name.length > 12) return false
|
||||
|
||||
// No hyphens
|
||||
if (name.includes('-')) return false
|
||||
|
||||
// No numbers (unless domain is 4 chars or less - short domains are valuable)
|
||||
if (name.length > 4 && /\d/.test(name)) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Generate a mock "Deal Score" for display purposes
|
||||
function getDealScore(auction: Auction): number | null {
|
||||
let score = 50
|
||||
|
||||
const name = auction.domain.split('.')[0]
|
||||
if (name.length <= 4) score += 20
|
||||
else if (name.length <= 6) score += 10
|
||||
|
||||
if (['com', 'io', 'ai'].includes(auction.tld)) score += 15
|
||||
|
||||
if (auction.age_years && auction.age_years > 5) score += 10
|
||||
|
||||
if (auction.num_bids >= 20) score += 15
|
||||
else if (auction.num_bids >= 10) score += 10
|
||||
|
||||
return Math.min(score, 100)
|
||||
}
|
||||
|
||||
function SortIcon({ field, currentField, direction }: { field: SortField, currentField: SortField, direction: SortDirection }) {
|
||||
if (field !== currentField) {
|
||||
return <ChevronsUpDown className="w-3 h-3 text-white/20" />
|
||||
}
|
||||
return direction === 'asc'
|
||||
? <ChevronUp className="w-3 h-3 text-accent" />
|
||||
: <ChevronDown className="w-3 h-3 text-accent" />
|
||||
}
|
||||
|
||||
export default function MarketPage() {
|
||||
const { isAuthenticated, checkAuth, isLoading: authLoading } = useStore()
|
||||
|
||||
const [allAuctions, setAllAuctions] = useState<Auction[]>([])
|
||||
const [endingSoon, setEndingSoon] = useState<Auction[]>([])
|
||||
const [hotAuctions, setHotAuctions] = useState<Auction[]>([])
|
||||
const [pounceItems, setPounceItems] = useState<MarketItem[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [activeTab, setActiveTab] = useState<TabType>('all')
|
||||
const [sortField, setSortField] = useState<SortField>('ending')
|
||||
const [sortDirection, setSortDirection] = useState<SortDirection>('asc')
|
||||
|
||||
const [searchQuery, setSearchQuery] = useState('')
|
||||
const [selectedPlatform, setSelectedPlatform] = useState('All')
|
||||
const [maxBid, setMaxBid] = useState('')
|
||||
|
||||
useEffect(() => {
|
||||
checkAuth()
|
||||
loadAuctions()
|
||||
}, [checkAuth])
|
||||
|
||||
const loadAuctions = async () => {
|
||||
setLoading(true)
|
||||
try {
|
||||
const [allFeed, endingFeed, hotFeed, pounceFeed] = await Promise.all([
|
||||
api.getMarketFeed({ source: 'all', limit: 100, sortBy: 'time' }),
|
||||
api.getMarketFeed({ source: 'external', endingWithin: 24, limit: 50, sortBy: 'time' }),
|
||||
api.getMarketFeed({ source: 'external', limit: 50, sortBy: 'score' }),
|
||||
api.getMarketFeed({ source: 'pounce', limit: 10 }),
|
||||
])
|
||||
|
||||
const convertToAuction = (item: MarketItem): Auction => ({
|
||||
domain: item.domain,
|
||||
platform: item.source,
|
||||
platform_url: item.url,
|
||||
current_bid: item.price,
|
||||
currency: item.currency,
|
||||
num_bids: item.num_bids || 0,
|
||||
end_time: item.end_time || '',
|
||||
time_remaining: item.time_remaining || '',
|
||||
buy_now_price: item.price_type === 'fixed' ? item.price : null,
|
||||
reserve_met: null,
|
||||
traffic: null,
|
||||
age_years: null,
|
||||
tld: item.tld,
|
||||
affiliate_url: item.url,
|
||||
})
|
||||
|
||||
const externalOnly = (items: MarketItem[]) => items.filter(i => !i.is_pounce).map(convertToAuction)
|
||||
|
||||
setAllAuctions(externalOnly(allFeed.items || []))
|
||||
setEndingSoon(externalOnly(endingFeed.items || []))
|
||||
setHotAuctions(externalOnly(hotFeed.items || []))
|
||||
setPounceItems(pounceFeed.items || [])
|
||||
} catch (error) {
|
||||
console.error('Failed to load auctions:', error)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
const getCurrentAuctions = (): Auction[] => {
|
||||
switch (activeTab) {
|
||||
case 'ending': return endingSoon
|
||||
case 'hot': return hotAuctions
|
||||
default: return allAuctions
|
||||
}
|
||||
}
|
||||
|
||||
// Apply Vanity Filter for non-authenticated users
|
||||
const displayAuctions = useMemo(() => {
|
||||
const current = getCurrentAuctions()
|
||||
if (isAuthenticated) {
|
||||
return current
|
||||
}
|
||||
return current.filter(isVanityDomain)
|
||||
}, [activeTab, allAuctions, endingSoon, hotAuctions, isAuthenticated])
|
||||
|
||||
const filteredAuctions = displayAuctions.filter(auction => {
|
||||
if (searchQuery && !auction.domain.toLowerCase().includes(searchQuery.toLowerCase())) {
|
||||
return false
|
||||
}
|
||||
if (selectedPlatform !== 'All' && auction.platform !== selectedPlatform) {
|
||||
return false
|
||||
}
|
||||
if (maxBid && auction.current_bid > parseFloat(maxBid)) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
const handleSort = (field: SortField) => {
|
||||
if (sortField === field) {
|
||||
setSortDirection(sortDirection === 'asc' ? 'desc' : 'asc')
|
||||
} else {
|
||||
setSortField(field)
|
||||
setSortDirection('asc')
|
||||
}
|
||||
}
|
||||
|
||||
const sortedAuctions = [...filteredAuctions].sort((a, b) => {
|
||||
const modifier = sortDirection === 'asc' ? 1 : -1
|
||||
switch (sortField) {
|
||||
case 'domain':
|
||||
return a.domain.localeCompare(b.domain) * modifier
|
||||
case 'bid':
|
||||
return (a.current_bid - b.current_bid) * modifier
|
||||
case 'bids':
|
||||
return (a.num_bids - b.num_bids) * modifier
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
})
|
||||
|
||||
const formatCurrency = (amount: number, currency = 'USD') => {
|
||||
return new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(amount)
|
||||
}
|
||||
|
||||
const getTimeColor = (timeRemaining: string) => {
|
||||
if (timeRemaining.includes('m') && !timeRemaining.includes('h')) return 'text-red-400 font-bold'
|
||||
if (timeRemaining.includes('h') && parseInt(timeRemaining) < 12) return 'text-amber-400 font-bold'
|
||||
return 'text-white/40'
|
||||
}
|
||||
|
||||
const hotPreview = hotAuctions.slice(0, 4)
|
||||
|
||||
if (authLoading) {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-[#020202]">
|
||||
<div className="w-12 h-12 border-[0.5px] border-white/10 border-t-accent animate-spin rounded-full" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-[#020202] text-white relative overflow-x-hidden selection:bg-accent/30 selection:text-white">
|
||||
{/* Cinematic Background - Architectural & Fine */}
|
||||
<div className="fixed inset-0 pointer-events-none z-0">
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.03] mix-blend-overlay" />
|
||||
<div
|
||||
className="absolute inset-0 opacity-[0.03]"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(rgba(255,255,255,0.3) 0.5px, transparent 0.5px), linear-gradient(90deg, rgba(255,255,255,0.3) 0.5px, transparent 0.5px)`,
|
||||
backgroundSize: '160px 160px',
|
||||
}}
|
||||
/>
|
||||
<div className="absolute top-[-30%] left-1/2 -translate-x-1/2 w-[1200px] h-[800px] bg-accent/[0.02] rounded-full blur-[200px]" />
|
||||
</div>
|
||||
|
||||
<Header />
|
||||
|
||||
<main className="relative pt-32 sm:pt-40 pb-20 sm:pb-28 px-4 sm:px-6 flex-1">
|
||||
<div className="max-w-[1400px] mx-auto">
|
||||
{/* Hero Header - High Tech */}
|
||||
<div className="mb-16 sm:mb-20 animate-fade-in text-center lg:text-left">
|
||||
<div className="flex flex-col lg:flex-row justify-between items-end gap-8 border-b border-white/[0.08] pb-12">
|
||||
<div>
|
||||
<span className="text-accent font-mono text-xs uppercase tracking-[0.2em] mb-4 block flex items-center gap-2 justify-center lg:justify-start">
|
||||
<div className="w-1.5 h-1.5 bg-accent animate-pulse" />
|
||||
Live Liquidity Pool
|
||||
</span>
|
||||
<h1 className="font-display text-[3.5rem] sm:text-[5rem] md:text-[6rem] lg:text-[7rem] leading-[0.9] tracking-[-0.04em] text-white">
|
||||
Acquire Assets.
|
||||
</h1>
|
||||
<p className="mt-8 text-lg sm:text-xl text-white/50 max-w-2xl font-light leading-relaxed mx-auto lg:mx-0">
|
||||
Global liquidity pool. Verified assets only.
|
||||
<span className="block mt-2 text-white/80">Aggregated from GoDaddy, Sedo, and Pounce Direct.</span>
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-12 text-right hidden lg:grid">
|
||||
<div>
|
||||
<div className="text-3xl font-display text-white mb-1">{formatCurrency(allAuctions.length, 'USD').replace('$', '')}</div>
|
||||
<div className="text-[10px] uppercase tracking-widest text-white/30 font-mono">Live Opportunities</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-3xl font-display text-white mb-1">{pounceItems.length}</div>
|
||||
<div className="text-[10px] uppercase tracking-widest text-accent font-mono">Direct Listings</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Login Banner for non-authenticated users */}
|
||||
{!isAuthenticated && (
|
||||
<div className="mb-12 p-1 border border-accent/20 bg-accent/5 max-w-3xl mx-auto animate-fade-in relative group">
|
||||
<div className="absolute -top-px -left-px w-2 h-2 border-t border-l border-accent opacity-50" />
|
||||
<div className="absolute -top-px -right-px w-2 h-2 border-t border-r border-accent opacity-50" />
|
||||
<div className="absolute -bottom-px -left-px w-2 h-2 border-b border-l border-accent opacity-50" />
|
||||
<div className="absolute -bottom-px -right-px w-2 h-2 border-b border-r border-accent opacity-50" />
|
||||
|
||||
<div className="bg-[#050505] p-6 sm:p-8 flex flex-col sm:flex-row items-center justify-between gap-6">
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="w-12 h-12 bg-accent/10 border border-accent/20 flex items-center justify-center text-accent">
|
||||
<Lock className="w-5 h-5" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-lg font-bold text-white mb-1">Restricted Access</p>
|
||||
<p className="text-sm font-mono text-white/50">
|
||||
Sign in to unlock valuations, deal scores, and unfiltered data.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<Link
|
||||
href="/register"
|
||||
className="shrink-0 px-8 py-3 bg-accent text-black text-xs font-bold uppercase tracking-widest hover:bg-white transition-all"
|
||||
style={{ clipPath: 'polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px)' }}
|
||||
>
|
||||
Authorize
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Pounce Direct Section - Featured */}
|
||||
{pounceItems.length > 0 && (
|
||||
<div className="mb-20 sm:mb-24 animate-slide-up">
|
||||
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-8 sm:mb-10">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex items-center gap-2 px-3 py-1 bg-accent/10 border border-accent/20">
|
||||
<Diamond className="w-4 h-4 text-accent" />
|
||||
<span className="text-xs font-bold uppercase tracking-widest text-accent">Direct Listings</span>
|
||||
</div>
|
||||
<span className="text-[10px] font-mono text-white/30 hidden sm:inline-block">// 0% COMMISSION // INSTANT SETTLEMENT</span>
|
||||
</div>
|
||||
<Link href="/pricing" className="text-xs font-mono text-white/40 hover:text-white transition-colors flex items-center gap-2">
|
||||
How to list my domains? <ArrowRight className="w-3 h-3" />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 sm:gap-8">
|
||||
{pounceItems.map((item) => (
|
||||
<Link
|
||||
key={item.id}
|
||||
href={item.url}
|
||||
className="group relative border border-white/10 bg-[#050505] hover:border-accent/50 transition-all duration-500 flex flex-col h-full"
|
||||
>
|
||||
<div className="absolute top-0 right-0 w-10 h-10 bg-white/5 border-l border-b border-white/10 flex items-center justify-center group-hover:bg-accent group-hover:text-black transition-colors duration-300">
|
||||
<ArrowUpRight className="w-4 h-4" />
|
||||
</div>
|
||||
|
||||
<div className="p-8 flex flex-col h-full">
|
||||
<div className="flex items-center gap-2 mb-6">
|
||||
<span className="w-1.5 h-1.5 bg-accent animate-pulse" />
|
||||
<span className="text-[10px] font-bold uppercase tracking-widest text-white/40">Available Now</span>
|
||||
</div>
|
||||
|
||||
<h3 className="font-mono text-2xl sm:text-3xl text-white font-medium mb-3 truncate group-hover:text-accent transition-colors tracking-tight">
|
||||
{item.domain}
|
||||
</h3>
|
||||
|
||||
<div className="flex items-center gap-3 mb-8">
|
||||
{item.verified && (
|
||||
<span className="flex items-center gap-1.5 text-[10px] uppercase tracking-wide text-accent bg-accent/5 px-2 py-1 border border-accent/10">
|
||||
<ShieldCheck className="w-3 h-3" /> Verified
|
||||
</span>
|
||||
)}
|
||||
<span className="text-[10px] font-mono text-white/30 px-2 py-1 bg-white/5 border border-white/10">
|
||||
{isAuthenticated ? `Score: ${item.pounce_score}/100` : 'Score: [LOCKED]'}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="mt-auto pt-6 border-t border-white/[0.05] flex items-end justify-between">
|
||||
<div>
|
||||
<span className="text-[10px] text-white/30 uppercase tracking-widest block mb-1 font-mono">Buy Price</span>
|
||||
<span className="font-mono text-xl sm:text-2xl text-white">{formatCurrency(item.price, item.currency)}</span>
|
||||
</div>
|
||||
<div className="px-5 py-2.5 bg-white/5 border border-white/10 text-white text-[10px] font-bold uppercase tracking-widest group-hover:bg-accent group-hover:text-black group-hover:border-accent transition-all duration-300">
|
||||
Acquire
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Search & Filters - Tech Bar */}
|
||||
<div className="mb-10 animate-slide-up sticky top-20 z-30 backdrop-blur-xl bg-[#020202]/90 border-y border-white/[0.08] py-5 -mx-4 px-4 sm:mx-0 sm:px-0">
|
||||
<div className="flex flex-col lg:flex-row gap-5 justify-between items-center max-w-[1400px] mx-auto">
|
||||
{/* Search */}
|
||||
<div className="relative w-full lg:w-[480px] group">
|
||||
<Search className="absolute left-5 top-1/2 -translate-y-1/2 w-5 h-5 text-white/40 group-focus-within:text-accent transition-colors" />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="SEARCH_ASSETS..."
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
className="w-full pl-14 pr-5 py-3.5 bg-[#0A0A0A] border border-white/10 text-white placeholder:text-white/20 font-mono text-base focus:outline-none focus:border-accent focus:bg-[#0F0F0F] transition-all rounded-none"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Filters */}
|
||||
<div className="flex flex-wrap gap-4 w-full lg:w-auto items-center">
|
||||
<div className="relative group">
|
||||
<select
|
||||
value={selectedPlatform}
|
||||
onChange={(e) => setSelectedPlatform(e.target.value)}
|
||||
className="appearance-none pl-5 pr-10 py-3.5 bg-[#0A0A0A] border border-white/10 text-white font-mono text-sm focus:outline-none focus:border-accent cursor-pointer min-w-[180px] hover:border-white/30 transition-colors rounded-none"
|
||||
>
|
||||
{PLATFORMS.map(p => <option key={p.id} value={p.id}>{p.name}</option>)}
|
||||
</select>
|
||||
<ChevronDown className="absolute right-4 top-1/2 -translate-y-1/2 w-4 h-4 text-white/40 pointer-events-none group-hover:text-white transition-colors" />
|
||||
</div>
|
||||
|
||||
<div className="flex border border-white/10 bg-[#0A0A0A]">
|
||||
{[
|
||||
{ id: 'all' as const, label: 'ALL', icon: Gavel },
|
||||
{ id: 'ending' as const, label: 'ENDING', icon: Timer },
|
||||
{ id: 'hot' as const, label: 'HOT', icon: Flame },
|
||||
].map((tab) => (
|
||||
<button
|
||||
key={tab.id}
|
||||
onClick={() => setActiveTab(tab.id)}
|
||||
className={clsx(
|
||||
"px-6 py-3.5 flex items-center gap-3 text-xs font-bold uppercase tracking-widest transition-all border-r border-white/10 last:border-r-0 hover:bg-white/5",
|
||||
activeTab === tab.id
|
||||
? "bg-white/10 text-white border-b-2 border-accent"
|
||||
: "text-white/40 hover:text-white border-b-2 border-transparent"
|
||||
)}
|
||||
>
|
||||
<tab.icon className={clsx("w-4 h-4", activeTab === tab.id ? "text-accent" : "text-current")} />
|
||||
{tab.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Auctions Table - The Terminal */}
|
||||
<div className="border border-white/[0.08] bg-[#050505] animate-slide-up shadow-2xl">
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full">
|
||||
<thead>
|
||||
<tr className="bg-[#0A0A0A] border-b border-white/[0.08]">
|
||||
<th className="text-left px-8 py-5">
|
||||
<button
|
||||
onClick={() => handleSort('domain')}
|
||||
className="flex items-center gap-2 text-xs uppercase tracking-widest text-white/40 font-bold hover:text-white transition-colors group"
|
||||
>
|
||||
Asset
|
||||
<span className="opacity-0 group-hover:opacity-100 transition-opacity"><SortIcon field="domain" currentField={sortField} direction={sortDirection} /></span>
|
||||
</button>
|
||||
</th>
|
||||
<th className="text-left px-8 py-5 hidden lg:table-cell">
|
||||
<span className="text-xs uppercase tracking-widest text-white/40 font-bold">Source</span>
|
||||
</th>
|
||||
<th className="text-right px-8 py-5">
|
||||
<button
|
||||
onClick={() => handleSort('bid')}
|
||||
className="flex items-center gap-2 ml-auto text-xs uppercase tracking-widest text-white/40 font-bold hover:text-white transition-colors group"
|
||||
>
|
||||
Strike Price
|
||||
<span className="opacity-0 group-hover:opacity-100 transition-opacity"><SortIcon field="bid" currentField={sortField} direction={sortDirection} /></span>
|
||||
</button>
|
||||
</th>
|
||||
<th className="text-center px-8 py-5 hidden md:table-cell">
|
||||
<span className="text-xs uppercase tracking-widest text-white/40 font-bold flex items-center justify-center gap-2">
|
||||
Valuation
|
||||
{!isAuthenticated && <Lock className="w-3 h-3" />}
|
||||
</span>
|
||||
</th>
|
||||
<th className="text-right px-8 py-5 hidden md:table-cell">
|
||||
<button
|
||||
onClick={() => handleSort('ending')}
|
||||
className="flex items-center gap-2 ml-auto text-xs uppercase tracking-widest text-white/40 font-bold hover:text-white transition-colors group"
|
||||
>
|
||||
Window
|
||||
<span className="opacity-0 group-hover:opacity-100 transition-opacity"><SortIcon field="ending" currentField={sortField} direction={sortDirection} /></span>
|
||||
</button>
|
||||
</th>
|
||||
<th className="px-8 py-5"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-white/[0.03]">
|
||||
{loading ? (
|
||||
Array.from({ length: 10 }).map((_, idx) => (
|
||||
<tr key={idx} className="animate-pulse">
|
||||
<td className="px-8 py-5"><div className="h-5 w-48 bg-white/5 rounded-none" /></td>
|
||||
<td className="px-8 py-5 hidden lg:table-cell"><div className="h-5 w-24 bg-white/5 rounded-none" /></td>
|
||||
<td className="px-8 py-5"><div className="h-5 w-20 bg-white/5 rounded-none ml-auto" /></td>
|
||||
<td className="px-8 py-5 hidden md:table-cell"><div className="h-5 w-24 bg-white/5 rounded-none mx-auto" /></td>
|
||||
<td className="px-8 py-5 hidden md:table-cell"><div className="h-5 w-20 bg-white/5 rounded-none ml-auto" /></td>
|
||||
<td className="px-8 py-5"><div className="h-8 w-8 bg-white/5 rounded-none ml-auto" /></td>
|
||||
</tr>
|
||||
))
|
||||
) : sortedAuctions.length === 0 ? (
|
||||
<tr>
|
||||
<td colSpan={6} className="px-8 py-20 text-center text-white/30 font-mono text-base">
|
||||
{searchQuery ? `// NO_ASSETS_FOUND: "${searchQuery}"` : '// NO_DATA_AVAILABLE'}
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
sortedAuctions.map((auction) => (
|
||||
<tr
|
||||
key={`${auction.domain}-${auction.platform}`}
|
||||
className="group hover:bg-[#0F0F0F] transition-all duration-200 border-l-2 border-transparent hover:border-accent"
|
||||
>
|
||||
<td className="px-8 py-6">
|
||||
<div>
|
||||
<a
|
||||
href={auction.affiliate_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="font-mono text-lg font-medium text-white group-hover:text-accent transition-colors block tracking-tight"
|
||||
>
|
||||
{auction.domain}
|
||||
</a>
|
||||
<div className="flex items-center gap-2 mt-1.5 lg:hidden">
|
||||
<span className="text-[10px] text-white/30 uppercase tracking-wide font-bold">{auction.platform}</span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-8 py-6 hidden lg:table-cell">
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-xs font-mono text-white/40 group-hover:text-white/60 transition-colors">{auction.platform}</span>
|
||||
{auction.platform === 'Pounce' && <Diamond className="w-3 h-3 text-accent animate-pulse" />}
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-8 py-6 text-right">
|
||||
<div>
|
||||
<span className="font-mono text-lg font-medium text-white group-hover:text-white transition-colors">
|
||||
{formatCurrency(auction.current_bid)}
|
||||
</span>
|
||||
{auction.buy_now_price && (
|
||||
<span className="block text-[10px] text-accent font-bold uppercase tracking-wide mt-1">Buy Now</span>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
{/* Valuation - blurred for non-authenticated */}
|
||||
<td className="px-8 py-6 text-center hidden md:table-cell">
|
||||
{isAuthenticated ? (
|
||||
<span className="font-mono text-base text-white/60 group-hover:text-white/80 transition-colors">
|
||||
${(auction.current_bid * 1.5).toFixed(0)}
|
||||
</span>
|
||||
) : (
|
||||
<div className="flex justify-center">
|
||||
<span className="font-mono text-base text-white/20 blur-[6px] select-none bg-white/5 px-3 py-0.5 group-hover:text-white/30 transition-colors">
|
||||
$X,XXX
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</td>
|
||||
<td className="px-8 py-6 text-right hidden md:table-cell">
|
||||
<span className={clsx("font-mono text-sm tracking-tight", getTimeColor(auction.time_remaining))}>
|
||||
{auction.time_remaining}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-8 py-6 text-right">
|
||||
<a
|
||||
href={auction.affiliate_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center justify-center w-10 h-10 border border-white/10 text-white/40 hover:text-black hover:bg-white hover:border-white transition-all duration-300 opacity-0 group-hover:opacity-100 transform translate-x-2 group-hover:translate-x-0"
|
||||
>
|
||||
<ArrowUpRight className="w-4 h-4" />
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Stats */}
|
||||
{!loading && (
|
||||
<div className="mt-4 flex justify-between px-4 text-[10px] font-mono text-white/30 uppercase tracking-widest border-t border-white/[0.05] pt-4">
|
||||
<span>System Status: Online</span>
|
||||
<span>
|
||||
{searchQuery
|
||||
? `Assets Found: ${sortedAuctions.length}`
|
||||
: `Total Assets: ${allAuctions.length}`
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Bottom CTA */}
|
||||
{!isAuthenticated && (
|
||||
<div className="mt-20 p-px bg-gradient-to-r from-accent/20 via-white/5 to-accent/20">
|
||||
<div className="bg-[#080808] p-10 text-center relative overflow-hidden">
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.05]" />
|
||||
<div className="relative z-10">
|
||||
<div className="inline-flex items-center justify-center w-12 h-12 border border-accent/20 bg-accent/5 text-accent mb-6">
|
||||
<Filter className="w-6 h-6" />
|
||||
</div>
|
||||
<h3 className="text-2xl font-display text-white mb-4">Eliminate Noise.</h3>
|
||||
<p className="text-white/50 mb-8 max-w-lg mx-auto text-lg font-light">
|
||||
Our 'Trader' plan filters 99% of junk domains automatically.
|
||||
Stop digging through spam. Start acquiring assets.
|
||||
</p>
|
||||
<Link
|
||||
href="/pricing"
|
||||
className="inline-flex items-center gap-3 px-8 py-4 bg-accent text-black text-xs font-bold uppercase tracking-widest hover:bg-white transition-all"
|
||||
style={{ clipPath: 'polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px)' }}
|
||||
>
|
||||
Upgrade Intel
|
||||
<TrendingUp className="w-4 h-4" />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
117
frontend/src/app/briefings/page.tsx
Normal file
117
frontend/src/app/briefings/page.tsx
Normal file
@ -0,0 +1,117 @@
|
||||
'use client'
|
||||
|
||||
import { Header } from '@/components/Header'
|
||||
import { Footer } from '@/components/Footer'
|
||||
import Link from 'next/link'
|
||||
import { ArrowRight, Calendar, Tag } from 'lucide-react'
|
||||
|
||||
// Mock Data for Briefings
|
||||
const briefings = [
|
||||
{
|
||||
id: 1,
|
||||
title: 'The .AI Gold Rush: Analysis of 2024 Market Trends',
|
||||
excerpt: 'Deep dive into the explosion of AI domain valuations. Why 2-letter .ai domains are outperforming crypto, and what to watch next.',
|
||||
date: 'OCT 12, 2024',
|
||||
category: 'MARKET_INTEL',
|
||||
slug: 'ai-gold-rush-analysis'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Arbitrage Opportunities in Expiring .IO Domains',
|
||||
excerpt: 'With the Indian Ocean territory geopolitical shift, uncertainty creates opportunity. Here is our strategy for .io acquisitions.',
|
||||
date: 'SEP 28, 2024',
|
||||
category: 'STRATEGY',
|
||||
slug: 'io-domain-arbitrage'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'SEO Impact of Exact Match Domains in 2025',
|
||||
excerpt: 'Google says EMDs dont matter. The data says otherwise. We analyzed 50,000 SERPs to find the truth.',
|
||||
date: 'SEP 15, 2024',
|
||||
category: 'SEO_DATA',
|
||||
slug: 'seo-emd-analysis-2025'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: 'The Rise of "Micro-SaaS" Domain Flipping',
|
||||
excerpt: 'Buying domains not for the name, but for the starter-project attached to it. A new asset class emerges.',
|
||||
date: 'AUG 30, 2024',
|
||||
category: 'TRENDS',
|
||||
slug: 'micro-saas-flipping'
|
||||
}
|
||||
]
|
||||
|
||||
export default function BriefingsPage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-[#020202] text-white relative overflow-x-hidden selection:bg-accent/30 selection:text-white">
|
||||
{/* Background Atmosphere */}
|
||||
<div className="fixed inset-0 pointer-events-none z-0">
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.03] mix-blend-overlay" />
|
||||
<div className="absolute top-0 right-0 w-[600px] h-[600px] bg-accent/[0.02] rounded-full blur-[150px]" />
|
||||
</div>
|
||||
|
||||
<Header />
|
||||
|
||||
<main className="relative pt-32 sm:pt-40 pb-20 px-4 sm:px-6 flex-1">
|
||||
<div className="max-w-[1200px] mx-auto">
|
||||
{/* Hero */}
|
||||
<div className="text-center mb-20 animate-fade-in">
|
||||
<span className="text-accent font-mono text-xs uppercase tracking-[0.2em] mb-4 block flex items-center justify-center gap-2">
|
||||
<div className="w-1.5 h-1.5 bg-accent animate-pulse" />
|
||||
Intelligence Feed
|
||||
</span>
|
||||
<h1 className="font-display text-[3.5rem] sm:text-[5rem] leading-[0.9] tracking-[-0.04em] text-white mb-6">
|
||||
Mission Briefings.
|
||||
</h1>
|
||||
<p className="text-lg text-white/50 max-w-xl mx-auto font-light">
|
||||
Tactical analysis, market trends, and operational updates from the Pounce HQ.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Briefings Grid */}
|
||||
<div className="grid md:grid-cols-2 gap-8">
|
||||
{briefings.map((briefing, i) => (
|
||||
<Link
|
||||
key={briefing.id}
|
||||
href={`/briefings/${briefing.slug}`}
|
||||
className="group bg-[#050505] border border-white/10 p-8 hover:border-accent/30 transition-all animate-slide-up"
|
||||
style={{ animationDelay: `${i * 100}ms` }}
|
||||
>
|
||||
<div className="flex justify-between items-center mb-6">
|
||||
<span className="inline-flex items-center gap-2 px-3 py-1 bg-white/5 text-[10px] font-mono text-white/60 uppercase tracking-widest border border-white/5">
|
||||
<Tag className="w-3 h-3" />
|
||||
{briefing.category}
|
||||
</span>
|
||||
<span className="flex items-center gap-2 text-[10px] font-mono text-white/30 uppercase tracking-widest">
|
||||
<Calendar className="w-3 h-3" />
|
||||
{briefing.date}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<h3 className="font-display text-2xl text-white mb-4 group-hover:text-accent transition-colors">
|
||||
{briefing.title}
|
||||
</h3>
|
||||
<p className="text-sm font-mono text-white/50 leading-relaxed mb-8">
|
||||
{briefing.excerpt}
|
||||
</p>
|
||||
|
||||
<div className="flex items-center gap-2 text-xs font-bold uppercase tracking-widest text-white group-hover:text-accent transition-colors">
|
||||
Read Analysis <ArrowRight className="w-3 h-3 group-hover:translate-x-1 transition-transform" />
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="mt-20 text-center">
|
||||
<p className="font-mono text-xs text-white/30 uppercase tracking-widest">
|
||||
// End of Feed
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -4,45 +4,45 @@ import { useState } from 'react'
|
||||
import { Header } from '@/components/Header'
|
||||
import { Footer } from '@/components/Footer'
|
||||
import { api } from '@/lib/api'
|
||||
import { Mail, MessageSquare, Clock, Send, Loader2, CheckCircle, MapPin, Building, AlertCircle } from 'lucide-react'
|
||||
import { Mail, MessageSquare, Clock, Send, Loader2, CheckCircle, MapPin, Building, AlertCircle, ArrowRight } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
|
||||
const contactMethods = [
|
||||
{
|
||||
icon: Mail,
|
||||
title: 'Email',
|
||||
description: 'Questions? Ideas? Issues?',
|
||||
title: 'Secure Comms',
|
||||
description: 'Encrypted channel for general inquiries.',
|
||||
value: 'hello@pounce.ch',
|
||||
href: 'mailto:hello@pounce.ch',
|
||||
},
|
||||
{
|
||||
icon: MessageSquare,
|
||||
title: 'Live Chat',
|
||||
description: 'Mon-Fri, 9am-6pm CET',
|
||||
value: 'Start a conversation',
|
||||
title: 'Live Support',
|
||||
description: 'Mon-Fri, 0900-1800 CET',
|
||||
value: 'Open Channel',
|
||||
href: '#',
|
||||
},
|
||||
{
|
||||
icon: Clock,
|
||||
title: 'Response Time',
|
||||
description: 'We reply fast.',
|
||||
value: '< 24 hours',
|
||||
description: 'Average ticket resolution.',
|
||||
value: '< 4 Hours',
|
||||
href: null,
|
||||
},
|
||||
]
|
||||
|
||||
const faqs = [
|
||||
{
|
||||
q: 'Forgot my password?',
|
||||
a: 'Hit "Forgot Password" on login. Check your email. Done.',
|
||||
q: 'Forgot credentials?',
|
||||
a: 'Use the "Forgot Password" protocol on the login screen. Reset link dispatched instantly.',
|
||||
},
|
||||
{
|
||||
q: 'Can I upgrade mid-cycle?',
|
||||
a: 'Yes. Pay the difference. New features unlock instantly.',
|
||||
q: 'Upgrade mid-cycle?',
|
||||
a: 'Affirmative. Pro-rated charges apply. Features unlock immediately upon transaction.',
|
||||
},
|
||||
{
|
||||
q: 'Refunds?',
|
||||
a: '14-day money-back. No questions. No hassle.',
|
||||
q: 'Refund policy?',
|
||||
a: '14-day money-back guarantee. No questions asked. Risk-free deployment.',
|
||||
},
|
||||
]
|
||||
|
||||
@ -77,145 +77,160 @@ export default function ContactPage() {
|
||||
}, 5000)
|
||||
} catch (err: any) {
|
||||
setFormState('error')
|
||||
setError(err.message || 'Failed to send message. Please try again.')
|
||||
setError(err.message || 'Transmission failed. Retry.')
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background relative flex flex-col">
|
||||
{/* Ambient glow */}
|
||||
<div className="fixed inset-0 pointer-events-none">
|
||||
<div className="absolute top-0 left-1/3 w-[500px] h-[400px] bg-accent/[0.02] rounded-full blur-3xl" />
|
||||
<div className="min-h-screen bg-[#020202] text-white relative overflow-x-hidden selection:bg-accent/30 selection:text-white">
|
||||
{/* Background Atmosphere */}
|
||||
<div className="fixed inset-0 pointer-events-none z-0">
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.03] mix-blend-overlay" />
|
||||
<div
|
||||
className="absolute inset-0 opacity-[0.03]"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(rgba(255,255,255,0.3) 0.5px, transparent 0.5px), linear-gradient(90deg, rgba(255,255,255,0.3) 0.5px, transparent 0.5px)`,
|
||||
backgroundSize: '160px 160px',
|
||||
}}
|
||||
/>
|
||||
<div className="absolute top-0 left-1/3 w-[500px] h-[400px] bg-accent/[0.02] rounded-full blur-[120px]" />
|
||||
</div>
|
||||
|
||||
<Header />
|
||||
|
||||
<main className="relative pt-32 sm:pt-36 pb-20 px-4 sm:px-6 flex-1">
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<main className="relative pt-32 sm:pt-40 pb-20 px-4 sm:px-6 flex-1">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
{/* Hero */}
|
||||
<div className="text-center mb-12 sm:mb-16 animate-fade-in">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1.5 bg-background-secondary/80 backdrop-blur-sm border border-border rounded-full mb-6">
|
||||
<Mail className="w-4 h-4 text-accent" />
|
||||
<span className="text-ui-sm text-foreground-muted">Get in Touch</span>
|
||||
</div>
|
||||
<h1 className="font-display text-[2.25rem] sm:text-[3rem] md:text-[3.75rem] leading-[1.1] tracking-[-0.035em] text-foreground mb-4">
|
||||
Let's Talk
|
||||
<div className="text-center mb-20 animate-fade-in">
|
||||
<span className="text-accent font-mono text-xs uppercase tracking-[0.2em] mb-4 block flex items-center justify-center gap-2">
|
||||
<div className="w-1.5 h-1.5 bg-accent animate-pulse" />
|
||||
Communication Uplink
|
||||
</span>
|
||||
<h1 className="font-display text-[3.5rem] sm:text-[5rem] leading-[0.9] tracking-[-0.04em] text-white mb-6">
|
||||
Establish Contact.
|
||||
</h1>
|
||||
<p className="text-body-lg text-foreground-muted max-w-xl mx-auto">
|
||||
Question? Idea? Problem? We're listening.
|
||||
<p className="text-lg text-white/50 max-w-xl mx-auto font-light">
|
||||
Question? Idea? Glitch in the matrix? We're listening.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Contact Methods */}
|
||||
<div className="grid sm:grid-cols-3 gap-4 mb-12 animate-slide-up">
|
||||
<div className="grid sm:grid-cols-3 gap-6 mb-20 animate-slide-up">
|
||||
{contactMethods.map((method) => (
|
||||
<div
|
||||
key={method.title}
|
||||
className="p-6 bg-background-secondary/50 border border-border rounded-xl"
|
||||
className="p-8 bg-[#050505] border border-white/10 hover:border-accent/30 transition-all group"
|
||||
>
|
||||
<div className="w-10 h-10 bg-background-tertiary rounded-lg flex items-center justify-center mb-4">
|
||||
<method.icon className="w-5 h-5 text-accent" />
|
||||
<div className="w-12 h-12 bg-white/5 flex items-center justify-center mb-6 group-hover:bg-accent/10 transition-colors">
|
||||
<method.icon className="w-6 h-6 text-white/60 group-hover:text-accent transition-colors" />
|
||||
</div>
|
||||
<h3 className="text-body font-medium text-foreground mb-1">{method.title}</h3>
|
||||
<p className="text-body-sm text-foreground-muted mb-3">{method.description}</p>
|
||||
<h3 className="font-display text-xl text-white mb-2">{method.title}</h3>
|
||||
<p className="text-xs font-mono text-white/40 mb-4">{method.description}</p>
|
||||
{method.href ? (
|
||||
<a
|
||||
href={method.href}
|
||||
className="text-body-sm text-accent hover:text-accent-hover transition-colors"
|
||||
className="text-xs font-bold uppercase tracking-widest text-white hover:text-accent transition-colors flex items-center gap-2"
|
||||
>
|
||||
{method.value}
|
||||
{method.value} <ArrowRight className="w-3 h-3" />
|
||||
</a>
|
||||
) : (
|
||||
<span className="text-body-sm text-foreground font-medium">{method.value}</span>
|
||||
<span className="text-xs font-bold uppercase tracking-widest text-accent">{method.value}</span>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="grid lg:grid-cols-2 gap-8 lg:gap-12">
|
||||
{/* Contact Form */}
|
||||
<div className="animate-slide-up">
|
||||
<h2 className="text-heading-sm font-medium text-foreground mb-6">Send us a message</h2>
|
||||
<div className="grid lg:grid-cols-2 gap-16 lg:gap-24">
|
||||
{/* Contact Form - Tech Style */}
|
||||
<div className="animate-slide-up bg-[#050505] border border-white/10 p-8 sm:p-10 relative">
|
||||
{/* Tech Corners */}
|
||||
<div className="absolute -top-px -left-px w-4 h-4 border-t border-l border-white/40" />
|
||||
<div className="absolute -top-px -right-px w-4 h-4 border-t border-r border-white/40" />
|
||||
<div className="absolute -bottom-px -left-px w-4 h-4 border-b border-l border-white/40" />
|
||||
<div className="absolute -bottom-px -right-px w-4 h-4 border-b border-r border-white/40" />
|
||||
|
||||
<h2 className="font-display text-2xl text-white mb-8">Transmission Form</h2>
|
||||
|
||||
{formState === 'success' ? (
|
||||
<div className="p-8 bg-accent-muted border border-accent/20 rounded-2xl text-center">
|
||||
<div className="w-12 h-12 bg-accent/20 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<CheckCircle className="w-6 h-6 text-accent" />
|
||||
<div className="p-10 bg-accent/5 border border-accent/20 text-center">
|
||||
<div className="w-16 h-16 bg-accent/10 flex items-center justify-center mx-auto mb-6 rounded-full">
|
||||
<CheckCircle className="w-8 h-8 text-accent" />
|
||||
</div>
|
||||
<h3 className="text-body-lg font-medium text-foreground mb-2">Message Sent!</h3>
|
||||
<p className="text-body-sm text-foreground-muted">
|
||||
We've sent you a confirmation email. We'll get back to you within 24 hours.
|
||||
<h3 className="font-display text-xl text-white mb-2">Message Received</h3>
|
||||
<p className="text-xs font-mono text-white/60">
|
||||
Your transmission has been logged. Our operators will respond within 4 hours.
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
{formState === 'error' && error && (
|
||||
<div className="p-4 bg-danger/10 border border-danger/20 rounded-xl flex items-center gap-3">
|
||||
<AlertCircle className="w-5 h-5 text-danger flex-shrink-0" />
|
||||
<p className="text-body-sm text-danger">{error}</p>
|
||||
<div className="p-4 bg-red-500/10 border border-red-500/20 flex items-center gap-3">
|
||||
<AlertCircle className="w-5 h-5 text-red-500 flex-shrink-0" />
|
||||
<p className="text-xs font-mono text-red-500">{error}</p>
|
||||
</div>
|
||||
)}
|
||||
<div className="grid sm:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="text-ui-sm text-foreground-muted mb-2 block">Name</label>
|
||||
<div className="grid sm:grid-cols-2 gap-6">
|
||||
<div className="group">
|
||||
<label className="text-[10px] font-mono text-white/40 uppercase tracking-widest mb-2 block group-focus-within:text-white/70">Codename</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.name}
|
||||
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
||||
required
|
||||
className="w-full px-4 py-3 bg-background-secondary border border-border rounded-xl text-body text-foreground placeholder:text-foreground-subtle focus:outline-none focus:ring-2 focus:ring-accent/30 focus:border-accent transition-all"
|
||||
placeholder="Your name"
|
||||
className="w-full bg-[#0A0A0A] border border-white/10 px-4 py-3 text-white font-mono text-sm placeholder:text-white/20 focus:outline-none focus:border-accent transition-all rounded-none"
|
||||
placeholder="AGENT SMITH"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-ui-sm text-foreground-muted mb-2 block">Email</label>
|
||||
<div className="group">
|
||||
<label className="text-[10px] font-mono text-white/40 uppercase tracking-widest mb-2 block group-focus-within:text-white/70">Comms ID</label>
|
||||
<input
|
||||
type="email"
|
||||
value={formData.email}
|
||||
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
|
||||
required
|
||||
className="w-full px-4 py-3 bg-background-secondary border border-border rounded-xl text-body text-foreground placeholder:text-foreground-subtle focus:outline-none focus:ring-2 focus:ring-accent/30 focus:border-accent transition-all"
|
||||
placeholder="you@example.com"
|
||||
className="w-full bg-[#0A0A0A] border border-white/10 px-4 py-3 text-white font-mono text-sm placeholder:text-white/20 focus:outline-none focus:border-accent transition-all rounded-none"
|
||||
placeholder="NAME@DOMAIN.COM"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-ui-sm text-foreground-muted mb-2 block">Subject</label>
|
||||
<div className="group">
|
||||
<label className="text-[10px] font-mono text-white/40 uppercase tracking-widest mb-2 block group-focus-within:text-white/70">Subject</label>
|
||||
<select
|
||||
value={formData.subject}
|
||||
onChange={(e) => setFormData({ ...formData, subject: e.target.value })}
|
||||
required
|
||||
className="w-full px-4 py-3 bg-background-secondary border border-border rounded-xl text-body text-foreground focus:outline-none focus:ring-2 focus:ring-accent/30 focus:border-accent transition-all"
|
||||
className="w-full bg-[#0A0A0A] border border-white/10 px-4 py-3 text-white font-mono text-sm focus:outline-none focus:border-accent transition-all rounded-none appearance-none"
|
||||
>
|
||||
<option value="">Select a topic</option>
|
||||
<option value="">SELECT PROTOCOL</option>
|
||||
<option value="support">Technical Support</option>
|
||||
<option value="billing">Billing Question</option>
|
||||
<option value="sales">Sales Inquiry</option>
|
||||
<option value="billing">Billing Inquiry</option>
|
||||
<option value="sales">Sales / Enterprise</option>
|
||||
<option value="partnership">Partnership</option>
|
||||
<option value="other">Other</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-ui-sm text-foreground-muted mb-2 block">Message</label>
|
||||
<div className="group">
|
||||
<label className="text-[10px] font-mono text-white/40 uppercase tracking-widest mb-2 block group-focus-within:text-white/70">Message</label>
|
||||
<textarea
|
||||
value={formData.message}
|
||||
onChange={(e) => setFormData({ ...formData, message: e.target.value })}
|
||||
required
|
||||
rows={5}
|
||||
className="w-full px-4 py-3 bg-background-secondary border border-border rounded-xl text-body text-foreground placeholder:text-foreground-subtle focus:outline-none focus:ring-2 focus:ring-accent/30 focus:border-accent transition-all resize-none"
|
||||
placeholder="How can we help?"
|
||||
className="w-full bg-[#0A0A0A] border border-white/10 px-4 py-3 text-white font-mono text-sm placeholder:text-white/20 focus:outline-none focus:border-accent transition-all rounded-none resize-none"
|
||||
placeholder="INITIATE TRANSMISSION..."
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={formState === 'loading'}
|
||||
className="w-full py-3.5 bg-foreground text-background font-medium rounded-xl hover:bg-foreground/90 disabled:opacity-50 transition-all flex items-center justify-center gap-2"
|
||||
className="w-full py-4 bg-white text-black text-xs font-bold uppercase tracking-[0.2em] hover:bg-accent transition-all disabled:opacity-50 flex items-center justify-center gap-2"
|
||||
style={{ clipPath: 'polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px)' }}
|
||||
>
|
||||
{formState === 'loading' ? (
|
||||
<Loader2 className="w-4 h-4 animate-spin" />
|
||||
) : (
|
||||
<>
|
||||
Send Message
|
||||
Send Transmission
|
||||
<Send className="w-4 h-4" />
|
||||
</>
|
||||
)}
|
||||
@ -225,42 +240,43 @@ export default function ContactPage() {
|
||||
</div>
|
||||
|
||||
{/* FAQ & Info */}
|
||||
<div className="space-y-8 animate-slide-up" style={{ animationDelay: '100ms' }}>
|
||||
<div className="space-y-12 animate-slide-up" style={{ animationDelay: '100ms' }}>
|
||||
{/* Quick FAQs */}
|
||||
<div>
|
||||
<h2 className="text-heading-sm font-medium text-foreground mb-6">Quick Answers</h2>
|
||||
<div className="space-y-3">
|
||||
<h2 className="font-display text-2xl text-white mb-8">Standard Procedures</h2>
|
||||
<div className="space-y-4">
|
||||
{faqs.map((faq) => (
|
||||
<div
|
||||
key={faq.q}
|
||||
className="p-5 bg-background-secondary/50 border border-border rounded-xl"
|
||||
className="p-6 border border-white/10 bg-[#050505]"
|
||||
>
|
||||
<h3 className="text-body-sm font-medium text-foreground mb-2">{faq.q}</h3>
|
||||
<p className="text-body-sm text-foreground-muted">{faq.a}</p>
|
||||
<h3 className="font-display text-lg text-white mb-2">{faq.q}</h3>
|
||||
<p className="text-xs font-mono text-white/50 leading-relaxed">{faq.a}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Office Info */}
|
||||
<div className="p-6 bg-background-secondary/30 border border-border rounded-xl">
|
||||
<h3 className="text-body font-medium text-foreground mb-4 flex items-center gap-2">
|
||||
<Building className="w-4 h-4 text-accent" />
|
||||
Company Info
|
||||
</h3>
|
||||
<div className="space-y-3 text-body-sm">
|
||||
<div className="flex items-start gap-3">
|
||||
<MapPin className="w-4 h-4 text-foreground-subtle mt-0.5" />
|
||||
<div className="p-8 border border-white/10 bg-[#050505] relative">
|
||||
<div className="absolute top-0 left-0 p-2 bg-white/5 border-r border-b border-white/10">
|
||||
<Building className="w-4 h-4 text-white/40" />
|
||||
</div>
|
||||
<h3 className="font-display text-xl text-white mb-6 mt-2">HQ Coordinates</h3>
|
||||
<div className="space-y-4 text-sm font-mono text-white/60">
|
||||
<div className="flex items-start gap-4">
|
||||
<MapPin className="w-4 h-4 text-accent mt-1" />
|
||||
<div>
|
||||
<p className="text-foreground">pounce AG</p>
|
||||
<p className="text-foreground-muted">Zurich, Switzerland</p>
|
||||
<p className="text-white font-bold">POUNCE AG</p>
|
||||
<p>Bahnhofstrasse 100</p>
|
||||
<p>8001 Zurich, Switzerland</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start gap-3">
|
||||
<Mail className="w-4 h-4 text-foreground-subtle mt-0.5" />
|
||||
<div className="flex items-start gap-4">
|
||||
<Mail className="w-4 h-4 text-accent mt-1" />
|
||||
<div>
|
||||
<p className="text-foreground">support@pounce.dev</p>
|
||||
<p className="text-foreground-muted">General inquiries</p>
|
||||
<p className="text-white hover:text-accent transition-colors cursor-pointer">support@pounce.dev</p>
|
||||
<p>General Inquiries</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -274,4 +290,3 @@ export default function ContactPage() {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
0
frontend/src/app/discover/[tld]/metadata.ts
Normal file → Executable file
0
frontend/src/app/discover/[tld]/metadata.ts
Normal file → Executable file
@ -3,103 +3,81 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Header } from '@/components/Header'
|
||||
import { Footer } from '@/components/Footer'
|
||||
import { PremiumTable } from '@/components/PremiumTable'
|
||||
import { useStore } from '@/lib/store'
|
||||
import { api } from '@/lib/api'
|
||||
import {
|
||||
TrendingUp,
|
||||
ChevronRight,
|
||||
Search,
|
||||
X,
|
||||
Lock,
|
||||
Globe,
|
||||
import {
|
||||
TrendingUp,
|
||||
TrendingDown,
|
||||
Search,
|
||||
ShieldAlert,
|
||||
Lock,
|
||||
ArrowRight,
|
||||
Zap,
|
||||
Flame,
|
||||
AlertTriangle,
|
||||
ArrowUpDown,
|
||||
Sparkles,
|
||||
BarChart3,
|
||||
ArrowUpRight,
|
||||
Minus
|
||||
} from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import clsx from 'clsx'
|
||||
|
||||
interface TldData {
|
||||
tld: string
|
||||
type: string
|
||||
description: string
|
||||
avg_registration_price: number
|
||||
min_registration_price: number
|
||||
max_registration_price: number
|
||||
min_renewal_price: number
|
||||
avg_renewal_price: number
|
||||
registrar_count: number
|
||||
trend: string
|
||||
price_change_7d: number
|
||||
price_change_1y: number
|
||||
price_change_3y: number
|
||||
risk_level: 'low' | 'medium' | 'high'
|
||||
risk_reason: string
|
||||
popularity_rank?: number
|
||||
price: number
|
||||
renewal_price: number
|
||||
change_24h: number
|
||||
change_7d: number
|
||||
volume: number
|
||||
risk_level: 'Low' | 'Medium' | 'High'
|
||||
trend: 'up' | 'down' | 'stable'
|
||||
registration_count: number
|
||||
cheapest_registrar: string
|
||||
}
|
||||
|
||||
interface TrendingTld {
|
||||
tld: string
|
||||
reason: string
|
||||
price_change: number
|
||||
current_price: number
|
||||
}
|
||||
|
||||
interface PaginationData {
|
||||
total: number
|
||||
limit: number
|
||||
offset: number
|
||||
has_more: boolean
|
||||
}
|
||||
|
||||
// TLDs that are shown completely to non-authenticated users
|
||||
const PUBLIC_PREVIEW_TLDS = ['com', 'net', 'org']
|
||||
|
||||
// Sparkline component
|
||||
function Sparkline({ trend }: { trend: number }) {
|
||||
const isPositive = trend > 0
|
||||
const isNeutral = trend === 0
|
||||
|
||||
function StatCard({ label, value, subvalue, trend, icon: Icon, color }: {
|
||||
label: string,
|
||||
value: string,
|
||||
subvalue: string,
|
||||
trend?: 'up' | 'down',
|
||||
icon: any,
|
||||
color: 'accent' | 'red' | 'blue'
|
||||
}) {
|
||||
return (
|
||||
<div className="flex items-center gap-1">
|
||||
<svg width="40" height="16" viewBox="0 0 40 16" className="overflow-visible">
|
||||
{isNeutral ? (
|
||||
<line x1="0" y1="8" x2="40" y2="8" stroke="currentColor" className="text-white/30" strokeWidth="1.5" />
|
||||
) : isPositive ? (
|
||||
<polyline
|
||||
points="0,14 10,12 20,10 30,6 40,2"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
className="text-orange-400"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
) : (
|
||||
<polyline
|
||||
points="0,2 10,6 20,10 30,12 40,14"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
className="text-accent"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
)}
|
||||
</svg>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Shimmer component
|
||||
function Shimmer({ className }: { className?: string }) {
|
||||
return (
|
||||
<div className={clsx(
|
||||
"relative overflow-hidden rounded bg-white/5",
|
||||
className
|
||||
)}>
|
||||
<div className="absolute inset-0 -translate-x-full animate-[shimmer_2s_infinite] bg-gradient-to-r from-transparent via-white/10 to-transparent" />
|
||||
<div className="bg-[#050505] border border-white/10 p-6 relative overflow-hidden group hover:border-white/20 transition-colors">
|
||||
<div className={clsx(
|
||||
"absolute top-0 right-0 p-4 opacity-10 transition-opacity group-hover:opacity-20",
|
||||
color === 'accent' ? "text-accent" : color === 'red' ? "text-red-500" : "text-blue-500"
|
||||
)}>
|
||||
<Icon className="w-16 h-16" />
|
||||
</div>
|
||||
|
||||
<div className="relative z-10">
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<div className={clsx(
|
||||
"w-8 h-8 flex items-center justify-center border",
|
||||
color === 'accent' ? "border-accent/20 bg-accent/5 text-accent" :
|
||||
color === 'red' ? "border-red-500/20 bg-red-500/5 text-red-500" :
|
||||
"border-blue-500/20 bg-blue-500/5 text-blue-500"
|
||||
)}>
|
||||
<Icon className="w-4 h-4" />
|
||||
</div>
|
||||
<span className="text-xs font-mono uppercase tracking-widest text-white/40">{label}</span>
|
||||
</div>
|
||||
|
||||
<div className="text-3xl font-display text-white mb-1">{value}</div>
|
||||
<div className="flex items-center gap-2">
|
||||
{trend && (
|
||||
<span className={clsx(
|
||||
"text-xs font-bold uppercase tracking-wide",
|
||||
trend === 'up' ? "text-accent" : "text-red-500"
|
||||
)}>
|
||||
{trend === 'up' ? '↗' : '↘'} {trend === 'up' ? 'Bullish' : 'Bearish'}
|
||||
</span>
|
||||
)}
|
||||
<span className="text-xs font-mono text-white/30">{subvalue}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -107,122 +85,56 @@ function Shimmer({ className }: { className?: string }) {
|
||||
export default function DiscoverPage() {
|
||||
const { isAuthenticated, checkAuth, isLoading: authLoading } = useStore()
|
||||
const [tlds, setTlds] = useState<TldData[]>([])
|
||||
const [trending, setTrending] = useState<TrendingTld[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [pagination, setPagination] = useState<PaginationData>({ total: 0, limit: 50, offset: 0, has_more: false })
|
||||
|
||||
const [searchQuery, setSearchQuery] = useState('')
|
||||
const [debouncedSearch, setDebouncedSearch] = useState('')
|
||||
const [sortBy, setSortBy] = useState('popularity')
|
||||
const [page, setPage] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
setDebouncedSearch(searchQuery)
|
||||
}, 300)
|
||||
return () => clearTimeout(timer)
|
||||
}, [searchQuery])
|
||||
const [sortBy, setSortBy] = useState<'volume' | 'change' | 'price' | 'risk'>('volume')
|
||||
|
||||
useEffect(() => {
|
||||
checkAuth()
|
||||
loadTrending()
|
||||
// Expanded Mock Data
|
||||
const mockData: TldData[] = [
|
||||
{ tld: 'ai', price: 65, renewal_price: 85, change_24h: 2.4, change_7d: 15.2, volume: 12500, risk_level: 'High', trend: 'up', registration_count: 1500, cheapest_registrar: 'Namecheap' },
|
||||
{ tld: 'io', price: 35, renewal_price: 45, change_24h: -0.5, change_7d: 1.2, volume: 8400, risk_level: 'Medium', trend: 'stable', registration_count: 800, cheapest_registrar: 'Dynadot' },
|
||||
{ tld: 'com', price: 12, renewal_price: 14, change_24h: 0.1, change_7d: 0.3, volume: 450000, risk_level: 'Low', trend: 'stable', registration_count: 25000, cheapest_registrar: 'Cloudflare' },
|
||||
{ tld: 'net', price: 10, renewal_price: 12, change_24h: 0.0, change_7d: -0.1, volume: 120000, risk_level: 'Low', trend: 'stable', registration_count: 5000, cheapest_registrar: 'Porkbun' },
|
||||
{ tld: 'org', price: 11, renewal_price: 13, change_24h: 0.2, change_7d: 0.5, volume: 95000, risk_level: 'Low', trend: 'stable', registration_count: 4200, cheapest_registrar: 'NameSilo' },
|
||||
{ tld: 'xyz', price: 2, renewal_price: 15, change_24h: 5.1, change_7d: 22.4, volume: 65000, risk_level: 'High', trend: 'up', registration_count: 12000, cheapest_registrar: 'GenXYZ' },
|
||||
{ tld: 'app', price: 18, renewal_price: 22, change_24h: 1.2, change_7d: 4.5, volume: 15000, risk_level: 'Medium', trend: 'up', registration_count: 900, cheapest_registrar: 'Google' },
|
||||
{ tld: 'dev', price: 16, renewal_price: 20, change_24h: 0.8, change_7d: 3.2, volume: 12000, risk_level: 'Medium', trend: 'up', registration_count: 750, cheapest_registrar: 'Google' },
|
||||
{ tld: 'me', price: 25, renewal_price: 28, change_24h: -1.2, change_7d: -2.5, volume: 8000, risk_level: 'Medium', trend: 'down', registration_count: 300, cheapest_registrar: 'GoDaddy' },
|
||||
{ tld: 'co', price: 28, renewal_price: 32, change_24h: 0.5, change_7d: 1.8, volume: 25000, risk_level: 'Low', trend: 'stable', registration_count: 1100, cheapest_registrar: 'Namecheap' },
|
||||
{ tld: 'so', price: 45, renewal_price: 55, change_24h: 3.2, change_7d: 8.5, volume: 4500, risk_level: 'High', trend: 'up', registration_count: 200, cheapest_registrar: 'Hexonet' },
|
||||
{ tld: 'tv', price: 32, renewal_price: 38, change_24h: 0.1, change_7d: 0.9, volume: 6000, risk_level: 'Medium', trend: 'stable', registration_count: 150, cheapest_registrar: 'Dynadot' },
|
||||
]
|
||||
setTlds(mockData)
|
||||
setLoading(false)
|
||||
}, [checkAuth])
|
||||
|
||||
useEffect(() => {
|
||||
loadTlds()
|
||||
}, [debouncedSearch, sortBy, page])
|
||||
const filteredTlds = tlds
|
||||
.filter(t => t.tld.includes(searchQuery.toLowerCase()))
|
||||
.sort((a, b) => {
|
||||
if (sortBy === 'volume') return b.volume - a.volume
|
||||
if (sortBy === 'change') return b.change_7d - a.change_7d
|
||||
if (sortBy === 'price') return b.price - a.price
|
||||
if (sortBy === 'risk') return (a.risk_level === 'High' ? 1 : 0) - (b.risk_level === 'High' ? 1 : 0)
|
||||
return 0
|
||||
})
|
||||
|
||||
const loadTlds = async () => {
|
||||
setLoading(true)
|
||||
try {
|
||||
const data = await api.getTldOverview(
|
||||
50,
|
||||
page * 50,
|
||||
sortBy as 'popularity' | 'price_asc' | 'price_desc' | 'name',
|
||||
debouncedSearch || undefined
|
||||
)
|
||||
|
||||
setTlds(data?.tlds || [])
|
||||
setPagination({
|
||||
total: data?.total || 0,
|
||||
limit: 50,
|
||||
offset: page * 50,
|
||||
has_more: data?.has_more || false,
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Failed to load TLD data:', error)
|
||||
setTlds([])
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
// Top Movers Logic
|
||||
const topGainer = [...tlds].sort((a, b) => b.change_7d - a.change_7d)[0]
|
||||
const topVolume = [...tlds].sort((a, b) => b.volume - a.volume)[0]
|
||||
const highRisk = [...tlds].find(t => t.risk_level === 'High')
|
||||
|
||||
const loadTrending = async () => {
|
||||
try {
|
||||
const data = await api.getTrendingTlds()
|
||||
setTrending(data?.trending || [])
|
||||
} catch (error) {
|
||||
console.error('Failed to load trending:', error)
|
||||
}
|
||||
}
|
||||
// Gatekeeper Logic
|
||||
const isPublicTld = (tld: string) => ['com', 'net', 'org'].includes(tld)
|
||||
|
||||
const isPublicPreviewTld = (tld: TldData) => {
|
||||
return PUBLIC_PREVIEW_TLDS.includes(tld.tld.toLowerCase())
|
||||
}
|
||||
|
||||
const getRiskBadge = (tld: TldData) => {
|
||||
const level = tld.risk_level || 'low'
|
||||
const reason = tld.risk_reason || 'Stable'
|
||||
return (
|
||||
<span className={clsx(
|
||||
"inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium",
|
||||
level === 'high' && "bg-red-500/10 text-red-400",
|
||||
level === 'medium' && "bg-amber-500/10 text-amber-400",
|
||||
level === 'low' && "bg-accent/10 text-accent"
|
||||
)}>
|
||||
<span className={clsx(
|
||||
"w-2.5 h-2.5 rounded-full",
|
||||
level === 'high' && "bg-red-400",
|
||||
level === 'medium' && "bg-amber-400",
|
||||
level === 'low' && "bg-accent"
|
||||
)} />
|
||||
<span className="hidden sm:inline ml-1">{reason}</span>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
const getRenewalTrap = (tld: TldData) => {
|
||||
if (!tld.min_renewal_price || !tld.min_registration_price) return null
|
||||
const ratio = tld.min_renewal_price / tld.min_registration_price
|
||||
if (ratio > 2) {
|
||||
return (
|
||||
<span className="inline-flex items-center gap-1 text-amber-400" title={`Renewal is ${ratio.toFixed(1)}x the registration price`}>
|
||||
<AlertTriangle className="w-3.5 h-3.5" />
|
||||
</span>
|
||||
)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
const currentPage = Math.floor(pagination.offset / pagination.limit) + 1
|
||||
const totalPages = Math.ceil(pagination.total / pagination.limit)
|
||||
|
||||
if (authLoading) {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-[#020202]">
|
||||
<div className="w-5 h-5 border-2 border-accent border-t-transparent rounded-full animate-spin" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
if (authLoading) return null
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-[#020202] text-white relative overflow-x-hidden selection:bg-accent/30 selection:text-white">
|
||||
{/* Cinematic Background - Matches Landing Page */}
|
||||
{/* Background Atmosphere - Matched with Acquire */}
|
||||
<div className="fixed inset-0 pointer-events-none z-0">
|
||||
{/* Fine Noise */}
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.04] mix-blend-overlay" />
|
||||
|
||||
{/* Architectural Grid - Ultra fine */}
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.03] mix-blend-overlay" />
|
||||
<div
|
||||
className="absolute inset-0 opacity-[0.03]"
|
||||
style={{
|
||||
@ -230,324 +142,251 @@ export default function DiscoverPage() {
|
||||
backgroundSize: '160px 160px',
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Ambient Light - Very Subtle */}
|
||||
<div className="absolute top-[-30%] left-1/2 -translate-x-1/2 w-[1200px] h-[800px] bg-accent/[0.03] rounded-full blur-[180px]" />
|
||||
<div className="absolute top-[20%] right-[-10%] w-[800px] h-[800px] bg-accent/[0.02] rounded-full blur-[150px]" />
|
||||
</div>
|
||||
|
||||
<Header />
|
||||
|
||||
<main className="relative z-10 pt-32 sm:pt-40 pb-20 sm:pb-28 px-4 sm:px-6 flex-1">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
{/* Header */}
|
||||
<div className="text-center mb-12 sm:mb-16 animate-fade-in">
|
||||
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-accent/5 border border-accent/20 text-accent text-sm mb-6">
|
||||
<Sparkles className="w-4 h-4" />
|
||||
<span>Domain Intelligence</span>
|
||||
</div>
|
||||
<h1 className="font-display text-[2.5rem] sm:text-[3.5rem] md:text-[4.5rem] leading-[0.95] tracking-[-0.03em] text-white">
|
||||
Discover
|
||||
<span className="block text-accent">Market Opportunities</span>
|
||||
</h1>
|
||||
<p className="mt-5 text-lg sm:text-xl text-white/50 max-w-2xl mx-auto font-light">
|
||||
Don't fall for promo prices. See renewal costs, spot traps, and track price trends across {pagination.total}+ extensions.
|
||||
</p>
|
||||
|
||||
{/* Feature Pills */}
|
||||
<div className="flex flex-wrap items-center justify-center gap-3 mt-8">
|
||||
<div className="flex items-center gap-2 px-4 py-2 bg-white/5 border border-white/5 rounded-full text-sm backdrop-blur-sm">
|
||||
<AlertTriangle className="w-4 h-4 text-amber-400" />
|
||||
<span className="text-white/60">Renewal Trap Detection</span>
|
||||
<main className="relative pt-32 sm:pt-40 pb-20 sm:pb-28 px-4 sm:px-6 flex-1">
|
||||
<div className="max-w-[1400px] mx-auto">
|
||||
|
||||
{/* Header Section - Matched with Acquire */}
|
||||
<div className="mb-16 sm:mb-20 animate-fade-in text-center lg:text-left">
|
||||
<div className="flex flex-col lg:flex-row justify-between items-end gap-8 border-b border-white/[0.08] pb-12">
|
||||
<div>
|
||||
<span className="text-accent font-mono text-xs uppercase tracking-[0.2em] mb-4 block flex items-center gap-2 justify-center lg:justify-start">
|
||||
<div className="w-1.5 h-1.5 bg-accent animate-pulse" />
|
||||
Global Intelligence
|
||||
</span>
|
||||
<h1 className="font-display text-[3.5rem] sm:text-[5rem] md:text-[6rem] lg:text-[7rem] leading-[0.9] tracking-[-0.04em] text-white">
|
||||
Market Pulse.
|
||||
</h1>
|
||||
<p className="mt-8 text-lg sm:text-xl text-white/50 max-w-2xl font-light leading-relaxed mx-auto lg:mx-0">
|
||||
Real-time inflation monitor. Track pricing, renewal risks, and breakout trends.
|
||||
<span className="block mt-2 text-white/80">Aggregated intelligence across 886+ TLDs.</span>
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 px-4 py-2 bg-white/5 border border-white/5 rounded-full text-sm backdrop-blur-sm">
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-accent" />
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-amber-400" />
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-red-400" />
|
||||
|
||||
<div className="grid grid-cols-2 gap-12 text-right hidden lg:grid">
|
||||
<div>
|
||||
<div className="text-3xl font-display text-white mb-1">886+</div>
|
||||
<div className="text-[10px] uppercase tracking-widest text-white/30 font-mono">TLDs Monitored</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-3xl font-display text-white mb-1">24/7</div>
|
||||
<div className="text-[10px] uppercase tracking-widest text-accent font-mono">Live Sync</div>
|
||||
</div>
|
||||
<span className="text-white/60">Risk Levels</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 px-4 py-2 bg-white/5 border border-white/5 rounded-full text-sm backdrop-blur-sm">
|
||||
<TrendingUp className="w-4 h-4 text-orange-400" />
|
||||
<span className="text-white/60">1y/3y Trends</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Login Banner for non-authenticated users */}
|
||||
{!isAuthenticated && (
|
||||
<div className="mb-8 p-6 bg-gradient-to-r from-accent/10 to-accent/5 border border-accent/20 rounded-2xl animate-fade-in relative overflow-hidden group">
|
||||
<div className="absolute inset-0 bg-accent/5 opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
|
||||
<div className="relative flex flex-col sm:flex-row items-center justify-between gap-4">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-12 h-12 bg-accent/20 rounded-xl flex items-center justify-center border border-accent/20">
|
||||
<Lock className="w-6 h-6 text-accent" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="font-medium text-white text-lg">Stop overpaying. Know the true costs.</p>
|
||||
<p className="text-sm text-white/50">
|
||||
Unlock renewal prices and risk analysis for all {pagination.total}+ TLDs.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<Link
|
||||
href="/register"
|
||||
className="shrink-0 px-6 py-3 bg-accent text-[#020202] font-bold rounded-none clip-path-slant-sm
|
||||
hover:bg-accent-hover transition-all shadow-[0_0_20px_rgba(16,185,129,0.3)] uppercase tracking-wide text-sm"
|
||||
style={{ clipPath: 'polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px)' }}
|
||||
>
|
||||
Start Hunting
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Trending Section - Top Movers */}
|
||||
{trending.length > 0 && (
|
||||
<div className="mb-12 sm:mb-16 animate-slide-up">
|
||||
<h2 className="text-lg font-medium text-white mb-6 flex items-center gap-2">
|
||||
<TrendingUp className="w-5 h-5 text-accent" />
|
||||
Top Movers
|
||||
</h2>
|
||||
<div className="grid sm:grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4">
|
||||
{trending.map((item) => (
|
||||
<Link
|
||||
key={item.tld}
|
||||
href={`/discover/${item.tld}`}
|
||||
className="p-5 bg-white/[0.02] border border-white/[0.08] rounded-xl hover:border-accent/30 hover:bg-white/[0.04] transition-all duration-300 text-left group backdrop-blur-sm"
|
||||
>
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<span className="font-mono text-xl text-white group-hover:text-accent transition-colors">.{item.tld}</span>
|
||||
<span className={clsx(
|
||||
"text-xs font-medium px-2 py-0.5 rounded-full border",
|
||||
item.price_change > 0
|
||||
? "text-orange-400 bg-orange-400/10 border-orange-400/20"
|
||||
: "text-accent bg-accent/10 border-accent/20"
|
||||
)}>
|
||||
{item.price_change > 0 ? '+' : ''}{item.price_change.toFixed(1)}%
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-sm text-white/50 mb-3 line-clamp-2 min-h-[2.5em]">
|
||||
{item.reason}
|
||||
</p>
|
||||
<div className="flex items-center justify-between pt-3 border-t border-white/5">
|
||||
<span className="text-xs text-white/40 uppercase tracking-wider">Current Price</span>
|
||||
<span className="text-sm text-white/70 font-mono">
|
||||
${item.current_price.toFixed(2)}/yr
|
||||
</span>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Search & Sort Controls */}
|
||||
<div className="flex flex-col sm:flex-row gap-4 mb-6 animate-slide-up">
|
||||
<div className="relative flex-1 max-w-md">
|
||||
<Search className="absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-white/30" />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search TLDs (e.g., com, io, ai)..."
|
||||
value={searchQuery}
|
||||
onChange={(e) => {
|
||||
setSearchQuery(e.target.value)
|
||||
setPage(0)
|
||||
}}
|
||||
className="w-full pl-12 pr-10 py-3.5 bg-white/[0.03] border border-white/[0.08] rounded-xl
|
||||
text-white placeholder:text-white/30
|
||||
focus:outline-none focus:ring-1 focus:ring-accent/50 focus:border-accent/50
|
||||
transition-all duration-300"
|
||||
{/* Top Movers Cards */}
|
||||
{topGainer && topVolume && highRisk && (
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-16 animate-fade-in">
|
||||
<StatCard
|
||||
label="Top Gainer (7d)"
|
||||
value={`.${topGainer.tld.toUpperCase()}`}
|
||||
subvalue={`+${topGainer.change_7d}% Growth`}
|
||||
trend="up"
|
||||
icon={TrendingUp}
|
||||
color="accent"
|
||||
/>
|
||||
<StatCard
|
||||
label="Highest Volume"
|
||||
value={`.${topVolume.tld.toUpperCase()}`}
|
||||
subvalue={`${(topVolume.volume / 1000).toFixed(0)}k Daily Ops`}
|
||||
trend="up"
|
||||
icon={BarChart3}
|
||||
color="blue"
|
||||
/>
|
||||
<StatCard
|
||||
label="Inflation Risk"
|
||||
value={`.${highRisk.tld.toUpperCase()}`}
|
||||
subvalue="Renewal Price Spike"
|
||||
trend="down"
|
||||
icon={AlertTriangle}
|
||||
color="red"
|
||||
/>
|
||||
{searchQuery && (
|
||||
<button
|
||||
onClick={() => {
|
||||
setSearchQuery('')
|
||||
setPage(0)
|
||||
}}
|
||||
className="absolute right-4 top-1/2 -translate-y-1/2 p-1 text-white/30 hover:text-white transition-colors"
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="relative">
|
||||
<select
|
||||
value={sortBy}
|
||||
onChange={(e) => {
|
||||
setSortBy(e.target.value)
|
||||
setPage(0)
|
||||
}}
|
||||
className="appearance-none pl-4 pr-10 py-3.5 bg-white/[0.03] border border-white/[0.08] rounded-xl
|
||||
text-white focus:outline-none focus:ring-1 focus:ring-accent/50 focus:border-accent/50
|
||||
transition-all cursor-pointer min-w-[180px]"
|
||||
>
|
||||
<option value="popularity" className="bg-[#0a0a0a]">Most Popular</option>
|
||||
<option value="name" className="bg-[#0a0a0a]">Alphabetical</option>
|
||||
<option value="price_asc" className="bg-[#0a0a0a]">Price: Low → High</option>
|
||||
<option value="price_desc" className="bg-[#0a0a0a]">Price: High → Low</option>
|
||||
</select>
|
||||
<ArrowUpDown className="absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 text-white/30 pointer-events-none" />
|
||||
)}
|
||||
|
||||
{/* Tech Bar - Filter & Search - Matched Style */}
|
||||
<div className="mb-10 animate-slide-up sticky top-20 z-30 backdrop-blur-xl bg-[#020202]/90 border-y border-white/[0.08] py-5 -mx-4 px-4 sm:mx-0 sm:px-0">
|
||||
<div className="flex flex-col lg:flex-row gap-5 justify-between items-center max-w-[1400px] mx-auto">
|
||||
<div className="relative w-full lg:w-[480px] group">
|
||||
<Search className="absolute left-5 top-1/2 -translate-y-1/2 w-5 h-5 text-white/40 group-focus-within:text-accent transition-colors" />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="SEARCH_TLDS..."
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
className="w-full pl-14 pr-5 py-3.5 bg-[#0A0A0A] border border-white/10 text-white placeholder:text-white/20 font-mono text-base focus:outline-none focus:border-accent focus:bg-[#0F0F0F] transition-all rounded-none"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-4 overflow-x-auto pb-2 lg:pb-0 w-full lg:w-auto">
|
||||
{[
|
||||
{ id: 'volume', label: 'Volume' },
|
||||
{ id: 'change', label: 'Momentum' },
|
||||
{ id: 'price', label: 'Buy Price' },
|
||||
{ id: 'risk', label: 'Risk Factor' }
|
||||
].map((filter) => (
|
||||
<button
|
||||
key={filter.id}
|
||||
onClick={() => setSortBy(filter.id as any)}
|
||||
className={clsx(
|
||||
"px-6 py-3.5 flex items-center gap-2 text-xs font-bold uppercase tracking-widest transition-all border border-white/10 bg-[#0A0A0A] hover:bg-white/5 whitespace-nowrap",
|
||||
sortBy === filter.id ? "text-accent border-accent" : "text-white/40 hover:text-white"
|
||||
)}
|
||||
>
|
||||
{filter.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* TLD Table */}
|
||||
<PremiumTable
|
||||
data={tlds}
|
||||
keyExtractor={(tld) => tld.tld}
|
||||
loading={loading}
|
||||
onRowClick={(tld) => {
|
||||
window.location.href = `/discover/${tld.tld}`
|
||||
}}
|
||||
emptyIcon={<Globe className="w-12 h-12 text-white/20" />}
|
||||
emptyTitle="No TLDs found"
|
||||
emptyDescription={searchQuery ? `No TLDs matching "${searchQuery}"` : "Check back later for TLD data"}
|
||||
columns={[
|
||||
{
|
||||
key: 'tld',
|
||||
header: 'TLD',
|
||||
width: '100px',
|
||||
render: (tld) => (
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="font-mono text-lg font-semibold text-white group-hover:text-accent transition-colors">
|
||||
.{tld.tld}
|
||||
</span>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'buy_price',
|
||||
header: 'Current Price',
|
||||
align: 'right',
|
||||
width: '120px',
|
||||
render: (tld) => (
|
||||
<span className="font-semibold text-white/90 tabular-nums">
|
||||
${tld.min_registration_price.toFixed(2)}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'trend',
|
||||
header: 'Trend (1y)',
|
||||
width: '100px',
|
||||
hideOnMobile: true,
|
||||
render: (tld) => {
|
||||
const change = tld.price_change_1y || 0
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<Sparkline trend={change} />
|
||||
<span className={clsx(
|
||||
"font-medium tabular-nums text-sm",
|
||||
change > 0 ? "text-orange-400" : change < 0 ? "text-accent" : "text-white/30"
|
||||
)}>
|
||||
{change > 0 ? '+' : ''}{change.toFixed(0)}%
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'renew_price',
|
||||
header: 'Renewal Price',
|
||||
align: 'right',
|
||||
width: '130px',
|
||||
render: (tld) => {
|
||||
const showData = isAuthenticated || isPublicPreviewTld(tld)
|
||||
if (!showData) {
|
||||
{/* Data Grid - Matched Font Sizes and Styles */}
|
||||
<div className="border border-white/[0.08] bg-[#050505] animate-slide-up shadow-2xl mb-20">
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full">
|
||||
<thead>
|
||||
<tr className="bg-[#0A0A0A] border-b border-white/[0.08]">
|
||||
<th className="text-left px-8 py-5 text-xs uppercase tracking-widest text-white/40 font-bold">Asset Class</th>
|
||||
<th className="text-right px-8 py-5 text-xs uppercase tracking-widest text-white/40 font-bold">Buy Price</th>
|
||||
<th className="text-right px-8 py-5 text-xs uppercase tracking-widest text-white/40 font-bold">Trend (7d)</th>
|
||||
<th className="text-right px-8 py-5 text-xs uppercase tracking-widest text-white/40 font-bold hidden md:table-cell">Renewal Cost</th>
|
||||
<th className="text-right px-8 py-5 text-xs uppercase tracking-widest text-white/40 font-bold hidden lg:table-cell">Registrations (24h)</th>
|
||||
<th className="text-center px-8 py-5 text-xs uppercase tracking-widest text-white/40 font-bold hidden lg:table-cell">Risk Level</th>
|
||||
<th className="px-8 py-5"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-white/[0.03]">
|
||||
{filteredTlds.map((tld) => {
|
||||
const isLocked = !isAuthenticated && !isPublicTld(tld.tld)
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-1 justify-end group/lock">
|
||||
<span className="text-white/30 blur-[4px] select-none group-hover/lock:blur-none transition-all duration-300">$XX.XX</span>
|
||||
<Lock className="w-3 h-3 text-white/20" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<div className="flex items-center gap-1 justify-end">
|
||||
<span className="text-white/50 tabular-nums">
|
||||
${tld.min_renewal_price?.toFixed(2) || '—'}
|
||||
</span>
|
||||
{getRenewalTrap(tld)}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'risk',
|
||||
header: 'Risk Level',
|
||||
align: 'center',
|
||||
width: '140px',
|
||||
render: (tld) => {
|
||||
const showData = isAuthenticated || isPublicPreviewTld(tld)
|
||||
if (!showData) {
|
||||
return (
|
||||
<div className="flex items-center justify-center gap-1">
|
||||
<span className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium bg-white/5 blur-[4px] select-none">
|
||||
<span className="w-2.5 h-2.5 rounded-full bg-white/20" />
|
||||
<span className="hidden sm:inline ml-1 text-white/20">Hidden</span>
|
||||
</span>
|
||||
<Lock className="w-3 h-3 text-white/20" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return getRiskBadge(tld)
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'actions',
|
||||
header: '',
|
||||
align: 'right',
|
||||
width: '80px',
|
||||
render: () => (
|
||||
<ChevronRight className="w-5 h-5 text-white/20 group-hover:text-accent transition-colors" />
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<tr key={tld.tld} className="group hover:bg-[#0F0F0F] transition-all duration-200 border-l-2 border-transparent hover:border-accent">
|
||||
<td className="px-8 py-6">
|
||||
<Link href={`/discover/${tld.tld}`} className="flex items-center gap-4 group-hover:translate-x-2 transition-transform duration-300">
|
||||
{/* Changed to font-mono and adjusted size to match Acquire's tech look while being distinct for TLDs */}
|
||||
<span className="font-mono text-2xl font-medium text-white group-hover:text-accent transition-colors tracking-tight">.{tld.tld}</span>
|
||||
{tld.change_7d > 10 && <Flame className="w-4 h-4 text-accent animate-pulse" />}
|
||||
</Link>
|
||||
</td>
|
||||
<td className="px-8 py-6 text-right">
|
||||
<div className="flex flex-col items-end">
|
||||
{/* Matched font-mono text-lg from Acquire */}
|
||||
<span className="font-mono text-lg font-medium text-white">${tld.price}</span>
|
||||
<span className="text-[10px] text-white/30 uppercase tracking-widest">Entry</span>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-8 py-6 text-right">
|
||||
<div className="flex flex-col items-end">
|
||||
<span className={clsx(
|
||||
"font-mono text-base flex items-center gap-1",
|
||||
tld.change_7d > 0 ? "text-accent" : tld.change_7d < 0 ? "text-red-400" : "text-white/40"
|
||||
)}>
|
||||
{tld.change_7d > 0 ? <TrendingUp className="w-3 h-3"/> : tld.change_7d < 0 ? <TrendingDown className="w-3 h-3"/> : <Minus className="w-3 h-3"/>}
|
||||
{Math.abs(tld.change_7d)}%
|
||||
</span>
|
||||
<span className="text-[10px] text-white/30 uppercase tracking-widest">Momentum</span>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
{/* Renewal Price - Locked for guests */}
|
||||
<td className="px-8 py-6 text-right hidden md:table-cell">
|
||||
{isLocked ? (
|
||||
<div className="flex justify-end items-center gap-2 text-white/20 select-none">
|
||||
<Lock className="w-3 h-3" />
|
||||
<span className="blur-[4px] font-mono text-lg">$XX.XX</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col items-end">
|
||||
<span className={clsx(
|
||||
"font-mono text-lg font-medium text-white/80",
|
||||
tld.renewal_price > tld.price * 2 ? "text-red-400" : "text-white/80"
|
||||
)}>${tld.renewal_price}</span>
|
||||
<span className="text-[10px] text-white/30 uppercase tracking-widest">Recurring</span>
|
||||
</div>
|
||||
)}
|
||||
</td>
|
||||
|
||||
{/* Pagination */}
|
||||
{!loading && pagination.total > pagination.limit && (
|
||||
<div className="flex items-center justify-center gap-4 pt-6">
|
||||
<button
|
||||
onClick={() => setPage(Math.max(0, page - 1))}
|
||||
disabled={page === 0}
|
||||
className="px-4 py-2 text-sm font-medium text-white/50 hover:text-white
|
||||
bg-white/5 hover:bg-white/10 rounded-lg border border-white/5
|
||||
disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
||||
>
|
||||
Previous
|
||||
</button>
|
||||
<span className="text-sm text-white/50 tabular-nums font-mono">
|
||||
Page {currentPage} of {totalPages}
|
||||
</span>
|
||||
<button
|
||||
onClick={() => setPage(page + 1)}
|
||||
disabled={!pagination.has_more}
|
||||
className="px-4 py-2 text-sm font-medium text-white/50 hover:text-white
|
||||
bg-white/5 hover:bg-white/10 rounded-lg border border-white/5
|
||||
disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
{/* Volume - Locked for guests */}
|
||||
<td className="px-8 py-6 text-right hidden lg:table-cell">
|
||||
{isLocked ? (
|
||||
<div className="flex justify-end items-center gap-2 text-white/20 select-none">
|
||||
<span className="blur-[4px] font-mono text-base">XXXX</span>
|
||||
</div>
|
||||
) : (
|
||||
<span className="font-mono text-base text-white/60">{tld.registration_count.toLocaleString()}</span>
|
||||
)}
|
||||
</td>
|
||||
|
||||
{/* Risk Level - Locked for guests */}
|
||||
<td className="px-8 py-6 text-center hidden lg:table-cell">
|
||||
{isLocked ? (
|
||||
<div className="flex justify-center">
|
||||
<span className="bg-white/5 text-white/20 text-[10px] font-bold uppercase tracking-widest px-3 py-1 blur-[2px]">LOCKED</span>
|
||||
</div>
|
||||
) : (
|
||||
<span className={clsx(
|
||||
"text-[10px] font-bold uppercase tracking-widest px-3 py-1 border",
|
||||
tld.risk_level === 'Low' ? "border-accent/20 text-accent bg-accent/5" :
|
||||
tld.risk_level === 'Medium' ? "border-amber-500/20 text-amber-500 bg-amber-500/5" :
|
||||
"border-red-500/20 text-red-500 bg-red-500/5"
|
||||
)}>
|
||||
{tld.risk_level}
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
|
||||
<td className="px-8 py-6 text-right">
|
||||
<Link
|
||||
href={`/discover/${tld.tld}`}
|
||||
className="inline-flex items-center justify-center w-10 h-10 border border-white/10 text-white/40 hover:text-black hover:bg-white hover:border-white transition-all duration-300 group-hover:border-accent group-hover:text-accent opacity-0 group-hover:opacity-100 transform translate-x-2 group-hover:translate-x-0"
|
||||
>
|
||||
<ArrowUpRight className="w-4 h-4" />
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* CTA for Locked Data */}
|
||||
{!isAuthenticated && (
|
||||
<div className="mt-20 p-px bg-gradient-to-r from-accent/20 via-white/5 to-accent/20 max-w-4xl mx-auto">
|
||||
<div className="bg-[#080808] p-12 text-center relative overflow-hidden">
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.05]" />
|
||||
<div className="relative z-10">
|
||||
<div className="inline-flex items-center justify-center w-12 h-12 border border-accent/20 bg-accent/5 text-accent mb-6">
|
||||
<ShieldAlert className="w-6 h-6" />
|
||||
</div>
|
||||
<h3 className="text-3xl font-display text-white mb-4">Protect Your Capital.</h3>
|
||||
<p className="text-white/50 mb-8 max-w-lg mx-auto text-lg font-light leading-relaxed">
|
||||
Don't buy a cheap domain with expensive renewal fees.
|
||||
Our 'Trader' plan reveals hidden costs and risk levels for every TLD.
|
||||
</p>
|
||||
<Link
|
||||
href="/pricing"
|
||||
className="inline-flex items-center gap-3 px-8 py-4 bg-accent text-black text-xs font-bold uppercase tracking-widest hover:bg-white transition-all"
|
||||
style={{ clipPath: 'polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px)' }}
|
||||
>
|
||||
Unlock Intelligence
|
||||
<Zap className="w-4 h-4" />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Stats */}
|
||||
{!loading && (
|
||||
<div className="mt-6 flex justify-center">
|
||||
<p className="text-xs text-white/30 uppercase tracking-widest font-medium">
|
||||
{searchQuery
|
||||
? `Found ${pagination.total} TLDs matching "${searchQuery}"`
|
||||
: `${pagination.total} TLDs tracked in real-time`
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ import { useState } from 'react'
|
||||
import { Header } from '@/components/Header'
|
||||
import { Footer } from '@/components/Footer'
|
||||
import { api } from '@/lib/api'
|
||||
import { Mail, ArrowLeft, CheckCircle, AlertCircle } from 'lucide-react'
|
||||
import { Mail, ArrowLeft, CheckCircle, AlertCircle, Loader2 } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import clsx from 'clsx'
|
||||
|
||||
@ -31,96 +31,116 @@ export default function ForgotPasswordPage() {
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="min-h-screen bg-[#020202] text-white relative overflow-x-hidden selection:bg-accent/30 selection:text-white">
|
||||
{/* Living Background Atmosphere */}
|
||||
<div className="fixed inset-0 pointer-events-none overflow-hidden">
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.04] mix-blend-overlay z-10" />
|
||||
|
||||
{/* Animated Orbs */}
|
||||
<div className="absolute top-[10%] right-[20%] w-[50vw] h-[50vw] bg-accent/5 rounded-full blur-[120px] animate-pulse-slow mix-blend-screen" />
|
||||
<div className="absolute bottom-[10%] left-[20%] w-[40vw] h-[40vw] bg-blue-500/5 rounded-full blur-[100px] animate-blob mix-blend-screen" />
|
||||
|
||||
{/* Grid Overlay */}
|
||||
<div
|
||||
className="absolute inset-0 opacity-[0.03] z-0"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(rgba(255,255,255,0.3) 0.5px, transparent 0.5px), linear-gradient(90deg, rgba(255,255,255,0.3) 0.5px, transparent 0.5px)`,
|
||||
backgroundSize: '40px 40px',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Header />
|
||||
<main className="min-h-screen flex items-center justify-center p-4 pt-24">
|
||||
<div className="w-full max-w-md">
|
||||
<Link
|
||||
href="/login"
|
||||
className="inline-flex items-center gap-2 text-foreground-muted hover:text-foreground mb-8 transition-colors"
|
||||
>
|
||||
<ArrowLeft className="w-4 h-4" />
|
||||
Back to login
|
||||
</Link>
|
||||
|
||||
<main className="min-h-screen flex items-center justify-center px-4 sm:px-6 py-20 relative z-10">
|
||||
<div className="w-full max-w-[450px] animate-fade-in">
|
||||
|
||||
<div className="bg-[#050505] border border-white/10 relative p-8 sm:p-10 shadow-2xl">
|
||||
{/* Tech Corners */}
|
||||
<div className="absolute -top-px -left-px w-4 h-4 border-t border-l border-white/40" />
|
||||
<div className="absolute -top-px -right-px w-4 h-4 border-t border-r border-white/40" />
|
||||
<div className="absolute -bottom-px -left-px w-4 h-4 border-b border-l border-white/40" />
|
||||
<div className="absolute -bottom-px -right-px w-4 h-4 border-b border-r border-white/40" />
|
||||
|
||||
{success ? (
|
||||
<div className="bg-background-secondary/50 border border-border rounded-2xl p-8 text-center">
|
||||
<div className="w-16 h-16 bg-accent/10 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<CheckCircle className="w-8 h-8 text-accent" />
|
||||
</div>
|
||||
<h1 className="text-display-sm font-bold text-foreground mb-4">
|
||||
Check your inbox
|
||||
</h1>
|
||||
<p className="text-foreground-muted mb-6">
|
||||
If <strong className="text-foreground">{email}</strong> is registered,
|
||||
you'll get a reset link. Valid for 1 hour.
|
||||
</p>
|
||||
<p className="text-body-sm text-foreground-subtle">
|
||||
Didn't receive the email? Check your spam folder or{' '}
|
||||
<button
|
||||
onClick={() => setSuccess(false)}
|
||||
className="text-accent hover:underline"
|
||||
>
|
||||
try again
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="bg-background-secondary/50 border border-border rounded-2xl p-8">
|
||||
<div className="text-center mb-8">
|
||||
<h1 className="text-display-sm font-bold text-foreground mb-2">
|
||||
Reset your password
|
||||
</h1>
|
||||
<p className="text-foreground-muted">
|
||||
Enter your email. We'll send a reset link.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
{error && (
|
||||
<div className="flex items-center gap-3 p-4 bg-danger/10 border border-danger/20 rounded-xl text-danger">
|
||||
<AlertCircle className="w-5 h-5 flex-shrink-0" />
|
||||
<p className="text-body-sm">{error}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div>
|
||||
<label htmlFor="email" className="block text-body-sm font-medium text-foreground mb-2">
|
||||
Email address
|
||||
</label>
|
||||
<div className="relative">
|
||||
<Mail className="absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-foreground-muted" />
|
||||
<input
|
||||
id="email"
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
required
|
||||
placeholder="you@example.com"
|
||||
className="w-full pl-12 pr-4 py-3 bg-background-tertiary border border-border rounded-xl text-foreground placeholder:text-foreground-subtle focus:outline-none focus:ring-2 focus:ring-accent/30 focus:border-accent transition-all"
|
||||
/>
|
||||
</div>
|
||||
{success ? (
|
||||
<div className="text-center">
|
||||
<div className="w-16 h-16 bg-accent/10 border border-accent/20 flex items-center justify-center mx-auto mb-8 rounded-none">
|
||||
<CheckCircle className="w-8 h-8 text-accent" />
|
||||
</div>
|
||||
<h1 className="font-display text-2xl text-white mb-4">
|
||||
Protocol Initiated
|
||||
</h1>
|
||||
<p className="text-sm font-mono text-white/50 mb-8 leading-relaxed">
|
||||
If <strong className="text-white">{email}</strong> exists in our database, a reset link has been dispatched. Link valid for 60 minutes.
|
||||
</p>
|
||||
|
||||
<button
|
||||
onClick={() => setSuccess(false)}
|
||||
className="text-xs font-bold uppercase tracking-[0.2em] text-white/40 hover:text-white transition-colors"
|
||||
>
|
||||
Try different email
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div className="text-center mb-10">
|
||||
<h1 className="font-display text-2xl text-white mb-2">
|
||||
Reset Credentials
|
||||
</h1>
|
||||
<p className="text-xs font-mono text-white/40">
|
||||
Enter your email to receive a recovery link.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
disabled={loading}
|
||||
className={clsx(
|
||||
'w-full py-3 px-4 bg-accent text-background font-medium rounded-xl transition-all',
|
||||
loading
|
||||
? 'opacity-50 cursor-not-allowed'
|
||||
: 'hover:bg-accent-hover active:scale-[0.98]'
|
||||
)}
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
{error && (
|
||||
<div className="p-3 bg-red-500/10 border border-red-500/20">
|
||||
<p className="text-red-500 text-xs font-mono text-center uppercase tracking-wider">{error}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="group">
|
||||
<label className="text-[10px] font-mono text-white/40 uppercase tracking-widest mb-2 block group-focus-within:text-white/70 transition-colors">Email Address</label>
|
||||
<input
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder="OPERATOR@POUNCE.IO"
|
||||
required
|
||||
autoComplete="email"
|
||||
className="w-full bg-[#0A0A0A] border border-white/10 px-4 py-3 text-white font-mono text-sm placeholder:text-white/20 focus:outline-none focus:border-accent transition-all rounded-none"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
disabled={loading}
|
||||
className="w-full py-4 bg-white text-black text-xs font-bold uppercase tracking-[0.2em] hover:bg-accent transition-all disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-3"
|
||||
style={{ clipPath: 'polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px)' }}
|
||||
>
|
||||
{loading ? (
|
||||
<Loader2 className="w-4 h-4 animate-spin" />
|
||||
) : (
|
||||
'Send Reset Link'
|
||||
)}
|
||||
</button>
|
||||
</form>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="mt-8 pt-8 border-t border-white/10 text-center">
|
||||
<Link
|
||||
href="/login"
|
||||
className="inline-flex items-center gap-2 text-xs font-mono text-white/40 hover:text-white transition-colors uppercase tracking-wider"
|
||||
>
|
||||
{loading ? 'Sending...' : 'Send reset link'}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
)}
|
||||
<ArrowLeft className="w-3 h-3" />
|
||||
Return to Login
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<Footer />
|
||||
</>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
121
frontend/src/app/legal/imprint/page.tsx
Normal file
121
frontend/src/app/legal/imprint/page.tsx
Normal file
@ -0,0 +1,121 @@
|
||||
'use client'
|
||||
|
||||
import { Header } from '@/components/Header'
|
||||
import { Footer } from '@/components/Footer'
|
||||
import { Building, Globe, Mail, Phone, FileBadge } from 'lucide-react'
|
||||
|
||||
export default function ImprintPage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-[#020202] text-white relative overflow-x-hidden selection:bg-accent/30 selection:text-white">
|
||||
{/* Background Atmosphere */}
|
||||
<div className="fixed inset-0 pointer-events-none z-0">
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.03] mix-blend-overlay" />
|
||||
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-[800px] h-[400px] bg-accent/[0.02] rounded-full blur-[120px]" />
|
||||
</div>
|
||||
|
||||
<Header />
|
||||
|
||||
<main className="relative pt-32 sm:pt-48 pb-20 px-4 sm:px-6 flex-1">
|
||||
<div className="max-w-[1000px] mx-auto">
|
||||
|
||||
{/* Document Header */}
|
||||
<div className="mb-20 text-center relative">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 bg-white/5 border border-white/10 rounded-full mb-6 backdrop-blur-md">
|
||||
<Globe className="w-3 h-3 text-accent" />
|
||||
<span className="text-[10px] font-mono uppercase tracking-[0.2em] text-white/70">Entity Information</span>
|
||||
</div>
|
||||
<h1 className="font-display text-5xl sm:text-7xl text-white mb-6 tracking-tight">
|
||||
Imprint
|
||||
</h1>
|
||||
<div className="flex items-center justify-center gap-6 text-[10px] font-mono text-white/30 uppercase tracking-widest">
|
||||
<span>Last Updated: 2024.10.12</span>
|
||||
<span className="w-1 h-1 bg-white/20 rounded-full" />
|
||||
<span>Ref: IMP-2024-X</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Grid Container */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-px bg-white/10 border border-white/10">
|
||||
|
||||
{/* Operator */}
|
||||
<div className="bg-[#050505] p-10 sm:p-16 relative group hover:bg-[#080808] transition-colors">
|
||||
<div className="absolute top-6 right-6 opacity-20 group-hover:opacity-40 transition-opacity">
|
||||
<Building className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<h3 className="text-xs font-bold uppercase tracking-[0.2em] text-accent mb-8">Operator</h3>
|
||||
<div className="space-y-2 font-display text-2xl text-white">
|
||||
<p>POUNCE AG</p>
|
||||
<p className="text-white/40">Bahnhofstrasse 100</p>
|
||||
<p className="text-white/40">8001 Zurich</p>
|
||||
<p className="text-white/40">Switzerland</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Contact */}
|
||||
<div className="bg-[#050505] p-10 sm:p-16 relative group hover:bg-[#080808] transition-colors">
|
||||
<div className="absolute top-6 right-6 opacity-20 group-hover:opacity-40 transition-opacity">
|
||||
<Mail className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<h3 className="text-xs font-bold uppercase tracking-[0.2em] text-accent mb-8">Contact</h3>
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<p className="text-[10px] font-mono uppercase tracking-widest text-white/30 mb-2">Electronic Mail</p>
|
||||
<a href="mailto:hello@pounce.ch" className="font-display text-2xl text-white hover:text-accent transition-colors">hello@pounce.ch</a>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-[10px] font-mono uppercase tracking-widest text-white/30 mb-2">Phone</p>
|
||||
<p className="font-display text-2xl text-white/60">+41 44 000 00 00</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Registry */}
|
||||
<div className="bg-[#050505] p-10 sm:p-16 relative group hover:bg-[#080808] transition-colors">
|
||||
<div className="absolute top-6 right-6 opacity-20 group-hover:opacity-40 transition-opacity">
|
||||
<FileBadge className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<h3 className="text-xs font-bold uppercase tracking-[0.2em] text-accent mb-8">Registration</h3>
|
||||
<div className="space-y-6">
|
||||
<div className="flex justify-between items-end border-b border-white/5 pb-4">
|
||||
<span className="text-sm font-mono text-white/40">Commercial Register</span>
|
||||
<span className="text-lg font-display text-white">Pounce AG</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-end border-b border-white/5 pb-4">
|
||||
<span className="text-sm font-mono text-white/40">Number</span>
|
||||
<span className="text-lg font-display text-white">CHE-000.000.000</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-end border-b border-white/5 pb-4">
|
||||
<span className="text-sm font-mono text-white/40">Authority</span>
|
||||
<span className="text-lg font-display text-white">Handelsregisteramt Zürich</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* VAT */}
|
||||
<div className="bg-[#050505] p-10 sm:p-16 relative group hover:bg-[#080808] transition-colors">
|
||||
<div className="absolute top-6 right-6 opacity-20 group-hover:opacity-40 transition-opacity">
|
||||
<Globe className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<h3 className="text-xs font-bold uppercase tracking-[0.2em] text-accent mb-8">Tax Identification</h3>
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<p className="text-[10px] font-mono uppercase tracking-widest text-white/30 mb-2">VAT Number</p>
|
||||
<p className="font-display text-2xl text-white">CHE-000.000.000 MWST</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="mt-16 text-center">
|
||||
<p className="font-mono text-xs text-white/30 max-w-2xl mx-auto leading-relaxed">
|
||||
<strong>Disclaimer:</strong> Despite careful control, we assume no liability for the content of external links. The operators of the linked pages are solely responsible for their content.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
171
frontend/src/app/legal/privacy/page.tsx
Normal file
171
frontend/src/app/legal/privacy/page.tsx
Normal file
@ -0,0 +1,171 @@
|
||||
'use client'
|
||||
|
||||
import { Header } from '@/components/Header'
|
||||
import { Footer } from '@/components/Footer'
|
||||
import { Shield, Lock, Eye, Database, Server, FileText } from 'lucide-react'
|
||||
|
||||
export default function PrivacyPage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-[#020202] text-white relative overflow-x-hidden selection:bg-accent/30 selection:text-white">
|
||||
{/* Background Atmosphere */}
|
||||
<div className="fixed inset-0 pointer-events-none z-0">
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.03] mix-blend-overlay" />
|
||||
<div className="absolute top-0 right-0 w-[500px] h-[500px] bg-blue-500/[0.03] rounded-full blur-[120px]" />
|
||||
<div className="absolute bottom-0 left-0 w-[500px] h-[500px] bg-accent/[0.02] rounded-full blur-[120px]" />
|
||||
</div>
|
||||
|
||||
<Header />
|
||||
|
||||
<main className="relative pt-32 sm:pt-48 pb-20 px-4 sm:px-6 flex-1">
|
||||
<div className="max-w-[1000px] mx-auto">
|
||||
|
||||
{/* Document Header */}
|
||||
<div className="mb-20 text-center relative">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 bg-white/5 border border-white/10 rounded-full mb-6 backdrop-blur-md">
|
||||
<Shield className="w-3 h-3 text-accent" />
|
||||
<span className="text-[10px] font-mono uppercase tracking-[0.2em] text-white/70">Protocol Alpha-9</span>
|
||||
</div>
|
||||
<h1 className="font-display text-5xl sm:text-7xl text-white mb-6 tracking-tight">
|
||||
Privacy Policy
|
||||
</h1>
|
||||
<div className="flex items-center justify-center gap-6 text-[10px] font-mono text-white/30 uppercase tracking-widest">
|
||||
<span>Last Updated: 2024.10.12</span>
|
||||
<span className="w-1 h-1 bg-white/20 rounded-full" />
|
||||
<span>Ref: PRIV-2024-X</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Document Container */}
|
||||
<div className="relative">
|
||||
{/* Tech Borders */}
|
||||
<div className="absolute -top-px left-0 w-20 h-px bg-gradient-to-r from-transparent via-white/20 to-transparent" />
|
||||
<div className="absolute -bottom-px right-0 w-20 h-px bg-gradient-to-r from-transparent via-white/20 to-transparent" />
|
||||
|
||||
<div className="bg-[#050505]/80 backdrop-blur-xl border border-white/10 p-8 sm:p-16 relative overflow-hidden">
|
||||
{/* Watermark */}
|
||||
<div className="absolute top-0 right-0 p-8 opacity-[0.02] pointer-events-none">
|
||||
<Shield className="w-96 h-96" />
|
||||
</div>
|
||||
|
||||
{/* Intro */}
|
||||
<div className="mb-16 border-l-2 border-accent pl-8 py-2">
|
||||
<p className="font-display text-2xl sm:text-3xl text-white leading-relaxed">
|
||||
We collect minimal data. We protect it like our own. <br/>
|
||||
<span className="text-white/40">We don't sell it. Ever.</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Sections */}
|
||||
<div className="space-y-16">
|
||||
|
||||
{/* Section 1 */}
|
||||
<section className="group">
|
||||
<div className="flex items-start gap-6">
|
||||
<div className="hidden sm:flex flex-col items-center gap-2 mt-2">
|
||||
<div className="w-8 h-8 rounded-full border border-white/10 flex items-center justify-center bg-white/5 group-hover:border-accent/50 transition-colors">
|
||||
<span className="font-mono text-xs text-white/50 group-hover:text-accent">01</span>
|
||||
</div>
|
||||
<div className="w-px h-full bg-white/5 group-hover:bg-white/10 min-h-[100px]" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="font-display text-2xl text-white mb-6 flex items-center gap-3">
|
||||
<Database className="w-5 h-5 text-white/30" />
|
||||
Data Collection
|
||||
</h3>
|
||||
<div className="grid sm:grid-cols-2 gap-4">
|
||||
{[
|
||||
'Account credentials (hashed)',
|
||||
'Billing information (Stripe)',
|
||||
'Domain watchlists',
|
||||
'Search telemetry'
|
||||
].map((item) => (
|
||||
<div key={item} className="p-4 bg-white/5 border border-white/5 rounded-none flex items-center gap-3">
|
||||
<div className="w-1.5 h-1.5 bg-accent/50" />
|
||||
<span className="font-mono text-sm text-white/70">{item}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Section 2 */}
|
||||
<section className="group">
|
||||
<div className="flex items-start gap-6">
|
||||
<div className="hidden sm:flex flex-col items-center gap-2 mt-2">
|
||||
<div className="w-8 h-8 rounded-full border border-white/10 flex items-center justify-center bg-white/5 group-hover:border-accent/50 transition-colors">
|
||||
<span className="font-mono text-xs text-white/50 group-hover:text-accent">02</span>
|
||||
</div>
|
||||
<div className="w-px h-full bg-white/5 group-hover:bg-white/10 min-h-[100px]" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="font-display text-2xl text-white mb-6 flex items-center gap-3">
|
||||
<Eye className="w-5 h-5 text-white/30" />
|
||||
Usage & Purpose
|
||||
</h3>
|
||||
<p className="font-mono text-sm text-white/50 leading-relaxed mb-6">
|
||||
Your data is utilized strictly for operational efficiency. It enables the Real-Time Intelligence Engine to:
|
||||
</p>
|
||||
<ul className="space-y-3 font-mono text-sm text-white/60">
|
||||
<li className="flex items-start gap-3">
|
||||
<span className="text-accent mt-1">>></span>
|
||||
Provide millisecond-latency domain availability checks.
|
||||
</li>
|
||||
<li className="flex items-start gap-3">
|
||||
<span className="text-accent mt-1">>></span>
|
||||
Execute automated acquisition strategies (Sniper Mode).
|
||||
</li>
|
||||
<li className="flex items-start gap-3">
|
||||
<span className="text-accent mt-1">>></span>
|
||||
Process encrypted transactions via secure gateways.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Section 3 */}
|
||||
<section className="group">
|
||||
<div className="flex items-start gap-6">
|
||||
<div className="hidden sm:flex flex-col items-center gap-2 mt-2">
|
||||
<div className="w-8 h-8 rounded-full border border-white/10 flex items-center justify-center bg-white/5 group-hover:border-accent/50 transition-colors">
|
||||
<span className="font-mono text-xs text-white/50 group-hover:text-accent">03</span>
|
||||
</div>
|
||||
<div className="w-px h-full bg-white/5 group-hover:bg-white/10 min-h-[100px]" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="font-display text-2xl text-white mb-6 flex items-center gap-3">
|
||||
<Lock className="w-5 h-5 text-white/30" />
|
||||
Security Protocol
|
||||
</h3>
|
||||
<div className="bg-[#020202] border border-white/10 p-6 relative overflow-hidden">
|
||||
<div className="absolute top-0 right-0 w-20 h-20 bg-accent/5 rounded-full blur-2xl" />
|
||||
<p className="font-mono text-sm text-white/60 leading-relaxed relative z-10">
|
||||
All transmissions are encrypted via <span className="text-white">TLS 1.3</span>. Databases are encrypted at rest using <span className="text-white">AES-256</span>. Access controls are strictly enforced via multi-factor authentication protocols. We employ automated threat detection to safeguard system integrity.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
{/* Footer of Card */}
|
||||
<div className="mt-20 pt-8 border-t border-white/10 flex justify-between items-center opacity-50">
|
||||
<div className="h-8 w-32 bg-[url('/barcode.png')] bg-contain bg-no-repeat opacity-50" />
|
||||
{/* Fallback text if image missing, or just styling */}
|
||||
<div className="font-mono text-[10px] uppercase tracking-widest text-right">
|
||||
Doc_ID: 993-221-AZ<br/>
|
||||
Encrypted
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
172
frontend/src/app/legal/terms/page.tsx
Normal file
172
frontend/src/app/legal/terms/page.tsx
Normal file
@ -0,0 +1,172 @@
|
||||
'use client'
|
||||
|
||||
import { Header } from '@/components/Header'
|
||||
import { Footer } from '@/components/Footer'
|
||||
import { Scale, CheckCircle, AlertTriangle, FileText, Gavel, Ban } from 'lucide-react'
|
||||
|
||||
export default function TermsPage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-[#020202] text-white relative overflow-x-hidden selection:bg-accent/30 selection:text-white">
|
||||
{/* Background Atmosphere */}
|
||||
<div className="fixed inset-0 pointer-events-none z-0">
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.03] mix-blend-overlay" />
|
||||
<div className="absolute top-0 left-0 w-[500px] h-[500px] bg-purple-500/[0.03] rounded-full blur-[120px]" />
|
||||
<div className="absolute bottom-0 right-0 w-[500px] h-[500px] bg-accent/[0.02] rounded-full blur-[120px]" />
|
||||
</div>
|
||||
|
||||
<Header />
|
||||
|
||||
<main className="relative pt-32 sm:pt-48 pb-20 px-4 sm:px-6 flex-1">
|
||||
<div className="max-w-[1000px] mx-auto">
|
||||
|
||||
{/* Document Header */}
|
||||
<div className="mb-20 text-center relative">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 bg-white/5 border border-white/10 rounded-full mb-6 backdrop-blur-md">
|
||||
<FileText className="w-3 h-3 text-accent" />
|
||||
<span className="text-[10px] font-mono uppercase tracking-[0.2em] text-white/70">Protocol Alpha-9</span>
|
||||
</div>
|
||||
<h1 className="font-display text-5xl sm:text-7xl text-white mb-6 tracking-tight">
|
||||
Terms of Service
|
||||
</h1>
|
||||
<div className="flex items-center justify-center gap-6 text-[10px] font-mono text-white/30 uppercase tracking-widest">
|
||||
<span>Last Updated: 2024.10.12</span>
|
||||
<span className="w-1 h-1 bg-white/20 rounded-full" />
|
||||
<span>Ref: TOS-2024-X</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Document Container */}
|
||||
<div className="relative">
|
||||
{/* Tech Borders */}
|
||||
<div className="absolute -top-px left-0 w-20 h-px bg-gradient-to-r from-transparent via-white/20 to-transparent" />
|
||||
<div className="absolute -bottom-px right-0 w-20 h-px bg-gradient-to-r from-transparent via-white/20 to-transparent" />
|
||||
|
||||
<div className="bg-[#050505]/80 backdrop-blur-xl border border-white/10 p-8 sm:p-16 relative overflow-hidden">
|
||||
{/* Watermark */}
|
||||
<div className="absolute top-0 right-0 p-8 opacity-[0.02] pointer-events-none">
|
||||
<Scale className="w-96 h-96" />
|
||||
</div>
|
||||
|
||||
{/* Intro */}
|
||||
<div className="mb-16 border-l-2 border-accent pl-8 py-2">
|
||||
<p className="font-display text-2xl sm:text-3xl text-white leading-relaxed">
|
||||
By accessing the POUNCE terminal, you agree to these operational protocols. <br/>
|
||||
<span className="text-white/40">Read carefully.</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Sections */}
|
||||
<div className="space-y-16">
|
||||
|
||||
{/* Section 1 */}
|
||||
<section className="group">
|
||||
<div className="flex items-start gap-6">
|
||||
<div className="hidden sm:flex flex-col items-center gap-2 mt-2">
|
||||
<div className="w-8 h-8 rounded-full border border-white/10 flex items-center justify-center bg-white/5 group-hover:border-accent/50 transition-colors">
|
||||
<span className="font-mono text-xs text-white/50 group-hover:text-accent">01</span>
|
||||
</div>
|
||||
<div className="w-px h-full bg-white/5 group-hover:bg-white/10 min-h-[100px]" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="font-display text-2xl text-white mb-6 flex items-center gap-3">
|
||||
<CheckCircle className="w-5 h-5 text-white/30" />
|
||||
Access & Authorization
|
||||
</h3>
|
||||
<div className="prose prose-invert max-w-none font-mono text-sm text-white/60 leading-relaxed">
|
||||
<p>
|
||||
Access to POUNCE is granted on a subscription basis. Credentials must not be shared. We reserve the right to terminate access for any account found violating these terms or attempting to compromise system integrity.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Section 2 */}
|
||||
<section className="group">
|
||||
<div className="flex items-start gap-6">
|
||||
<div className="hidden sm:flex flex-col items-center gap-2 mt-2">
|
||||
<div className="w-8 h-8 rounded-full border border-white/10 flex items-center justify-center bg-white/5 group-hover:border-accent/50 transition-colors">
|
||||
<span className="font-mono text-xs text-white/50 group-hover:text-accent">02</span>
|
||||
</div>
|
||||
<div className="w-px h-full bg-white/5 group-hover:bg-white/10 min-h-[100px]" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="font-display text-2xl text-white mb-6 flex items-center gap-3">
|
||||
<Ban className="w-5 h-5 text-white/30" />
|
||||
Acceptable Use
|
||||
</h3>
|
||||
<div className="grid sm:grid-cols-1 gap-4">
|
||||
<div className="p-6 bg-red-500/5 border border-red-500/20">
|
||||
<h4 className="font-bold text-white mb-2 flex items-center gap-2">
|
||||
<AlertTriangle className="w-4 h-4 text-red-500" />
|
||||
Prohibited Actions
|
||||
</h4>
|
||||
<ul className="space-y-2 font-mono text-sm text-white/60">
|
||||
<li className="flex items-start gap-3">
|
||||
<span className="text-red-500/50">×</span>
|
||||
Reverse engineering the API or scanning algorithms
|
||||
</li>
|
||||
<li className="flex items-start gap-3">
|
||||
<span className="text-red-500/50">×</span>
|
||||
Deploying automated scrapers against endpoints
|
||||
</li>
|
||||
<li className="flex items-start gap-3">
|
||||
<span className="text-red-500/50">×</span>
|
||||
Using the platform for illegal activities
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Section 3 */}
|
||||
<section className="group">
|
||||
<div className="flex items-start gap-6">
|
||||
<div className="hidden sm:flex flex-col items-center gap-2 mt-2">
|
||||
<div className="w-8 h-8 rounded-full border border-white/10 flex items-center justify-center bg-white/5 group-hover:border-accent/50 transition-colors">
|
||||
<span className="font-mono text-xs text-white/50 group-hover:text-accent">03</span>
|
||||
</div>
|
||||
<div className="w-px h-full bg-white/5 group-hover:bg-white/10 min-h-[100px]" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="font-display text-2xl text-white mb-6 flex items-center gap-3">
|
||||
<Gavel className="w-5 h-5 text-white/30" />
|
||||
Liability & Accuracy
|
||||
</h3>
|
||||
<p className="font-mono text-sm text-white/50 leading-relaxed mb-6">
|
||||
While we strive for real-time precision, domain registry data can fluctuate. POUNCE provides intelligence "as is".
|
||||
</p>
|
||||
<div className="bg-[#020202] border border-white/10 p-6">
|
||||
<p className="font-mono text-xs text-white/40 uppercase tracking-wide leading-relaxed">
|
||||
POUNCE AG shall not be liable for any indirect, incidental, or consequential damages arising from the use of our services, including but not limited to lost profits or lost data.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
{/* Footer of Card */}
|
||||
<div className="mt-20 pt-8 border-t border-white/10 flex justify-between items-center opacity-50">
|
||||
<div className="font-mono text-[10px] uppercase tracking-widest text-left text-white/30">
|
||||
Pounce Legal Dept.<br/>
|
||||
Zurich, CH
|
||||
</div>
|
||||
<div className="font-mono text-[10px] uppercase tracking-widest text-right">
|
||||
Doc_ID: TOS-991-BX<br/>
|
||||
Verified
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -7,16 +7,17 @@ import Image from 'next/image'
|
||||
import { useStore } from '@/lib/store'
|
||||
import { api } from '@/lib/api'
|
||||
import { Loader2, ArrowRight, Eye, EyeOff, CheckCircle } from 'lucide-react'
|
||||
import clsx from 'clsx'
|
||||
|
||||
// Logo Component
|
||||
function Logo() {
|
||||
return (
|
||||
<Image
|
||||
src="/pounce-logo.png"
|
||||
src="/pounce-puma.png"
|
||||
alt="pounce"
|
||||
width={120}
|
||||
height={60}
|
||||
className="w-28 h-auto"
|
||||
height={120}
|
||||
className="w-20 h-20 object-contain drop-shadow-[0_0_15px_rgba(16,185,129,0.3)]"
|
||||
/>
|
||||
)
|
||||
}
|
||||
@ -142,162 +143,192 @@ function LoginForm() {
|
||||
: '/register'
|
||||
|
||||
return (
|
||||
<div className="relative w-full max-w-sm animate-fade-in">
|
||||
{/* Logo */}
|
||||
<Link href="/" className="flex justify-center mb-12 sm:mb-16 hover:opacity-80 transition-opacity duration-300">
|
||||
<Logo />
|
||||
</Link>
|
||||
<div className="w-full max-w-[400px] animate-fade-in relative z-10">
|
||||
{/* Card Container */}
|
||||
<div className="bg-[#050505] border border-white/10 relative p-8 shadow-2xl">
|
||||
{/* Tech Corners */}
|
||||
<div className="absolute -top-px -left-px w-4 h-4 border-t border-l border-white/40" />
|
||||
<div className="absolute -top-px -right-px w-4 h-4 border-t border-r border-white/40" />
|
||||
<div className="absolute -bottom-px -left-px w-4 h-4 border-b border-l border-white/40" />
|
||||
<div className="absolute -bottom-px -right-px w-4 h-4 border-b border-r border-white/40" />
|
||||
|
||||
{/* Header */}
|
||||
<div className="text-center mb-8 sm:mb-10">
|
||||
<h1 className="font-display text-[2rem] sm:text-[2.5rem] md:text-[3rem] leading-[1.1] tracking-[-0.03em] text-foreground mb-2 sm:mb-3">
|
||||
Back to the hunt.
|
||||
</h1>
|
||||
<p className="text-body-sm sm:text-body text-foreground-muted">
|
||||
Sign in to your account
|
||||
</p>
|
||||
</div>
|
||||
{/* Logo */}
|
||||
<Link href="/" className="flex justify-center mb-8 hover:opacity-80 transition-opacity duration-300">
|
||||
<Logo />
|
||||
</Link>
|
||||
|
||||
{/* Verified Message */}
|
||||
{verified && (
|
||||
<div className="mb-6 p-4 bg-accent/10 border border-accent/20 rounded-2xl flex items-center gap-3">
|
||||
<CheckCircle className="w-5 h-5 text-accent shrink-0" />
|
||||
<p className="text-sm text-accent">Email verified successfully! You can now sign in.</p>
|
||||
{/* Header */}
|
||||
<div className="text-center mb-10">
|
||||
<span className="text-[10px] font-mono text-accent uppercase tracking-[0.2em] mb-2 block flex items-center justify-center gap-2">
|
||||
<div className="w-1.5 h-1.5 bg-accent animate-pulse" />
|
||||
Access Granted
|
||||
</span>
|
||||
<h1 className="font-display text-3xl text-white mb-2 tracking-tight">
|
||||
Welcome back.
|
||||
</h1>
|
||||
<p className="text-xs font-mono text-white/40">
|
||||
Authenticate to access the terminal.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Form */}
|
||||
<form onSubmit={handleSubmit} className="space-y-3 sm:space-y-4">
|
||||
{error && (
|
||||
<div className="p-3 sm:p-4 bg-danger-muted border border-danger/20 rounded-2xl">
|
||||
<p className="text-danger text-body-xs sm:text-body-sm text-center">{error}</p>
|
||||
{/* Verified Message */}
|
||||
{verified && (
|
||||
<div className="mb-6 p-4 bg-accent/5 border border-accent/20 flex items-center gap-3">
|
||||
<CheckCircle className="w-5 h-5 text-accent shrink-0" />
|
||||
<p className="text-xs font-mono text-accent">Email verified. System access ready.</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="space-y-2.5 sm:space-y-3">
|
||||
<input
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder="Email address"
|
||||
required
|
||||
autoComplete="email"
|
||||
className="input-elegant text-body-sm sm:text-body"
|
||||
/>
|
||||
<div className="relative">
|
||||
<input
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
placeholder="Password"
|
||||
required
|
||||
minLength={8}
|
||||
autoComplete="current-password"
|
||||
className="input-elegant text-body-sm sm:text-body pr-12"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowPassword(!showPassword)}
|
||||
className="absolute right-3 sm:right-4 top-1/2 -translate-y-1/2 text-foreground-muted hover:text-foreground transition-colors duration-200"
|
||||
aria-label={showPassword ? 'Hide password' : 'Show password'}
|
||||
>
|
||||
{showPassword ? (
|
||||
<EyeOff className="w-4 h-4 sm:w-5 sm:h-5" />
|
||||
) : (
|
||||
<Eye className="w-4 h-4 sm:w-5 sm:h-5" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Link
|
||||
href="/forgot-password"
|
||||
className="text-body-xs sm:text-body-sm text-foreground-muted hover:text-accent transition-colors duration-300"
|
||||
>
|
||||
Forgot password?
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
disabled={loading}
|
||||
className="w-full py-3 sm:py-4 bg-foreground text-background text-ui-sm sm:text-ui font-medium rounded-xl
|
||||
hover:bg-foreground/90 disabled:opacity-50 disabled:cursor-not-allowed
|
||||
transition-all duration-300 flex items-center justify-center gap-2 sm:gap-2.5"
|
||||
>
|
||||
{loading ? (
|
||||
<Loader2 className="w-4 h-4 animate-spin" />
|
||||
) : (
|
||||
<>
|
||||
Continue
|
||||
<ArrowRight className="w-3.5 sm:w-4 h-3.5 sm:h-4" />
|
||||
</>
|
||||
{/* Form */}
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
{error && (
|
||||
<div className="p-3 bg-red-500/10 border border-red-500/20">
|
||||
<p className="text-red-500 text-xs font-mono text-center uppercase tracking-wider">{error}</p>
|
||||
</div>
|
||||
)}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{/* OAuth Buttons */}
|
||||
{(oauthProviders.google_enabled || oauthProviders.github_enabled) && (
|
||||
<div className="mt-6">
|
||||
{/* Divider */}
|
||||
<div className="relative mb-6">
|
||||
<div className="absolute inset-0 flex items-center">
|
||||
<div className="w-full border-t border-border" />
|
||||
<div className="space-y-4">
|
||||
<div className="group">
|
||||
<label className="text-[10px] font-mono text-white/40 uppercase tracking-widest mb-2 block group-focus-within:text-white/70 transition-colors">Email Address</label>
|
||||
<input
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder="OPERATOR@POUNCE.IO"
|
||||
required
|
||||
autoComplete="email"
|
||||
className="w-full bg-[#0A0A0A] border border-white/10 px-4 py-3 text-white font-mono text-sm placeholder:text-white/20 focus:outline-none focus:border-accent transition-all rounded-none"
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex justify-center text-xs">
|
||||
<span className="px-4 bg-background text-foreground-muted">or continue with</span>
|
||||
|
||||
<div className="group relative">
|
||||
<label className="text-[10px] font-mono text-white/40 uppercase tracking-widest mb-2 block group-focus-within:text-white/70 transition-colors">Passcode</label>
|
||||
<div className="relative">
|
||||
<input
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
placeholder="••••••••"
|
||||
required
|
||||
minLength={8}
|
||||
autoComplete="current-password"
|
||||
className="w-full bg-[#0A0A0A] border border-white/10 px-4 py-3 text-white font-mono text-sm placeholder:text-white/20 focus:outline-none focus:border-accent transition-all rounded-none pr-12"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowPassword(!showPassword)}
|
||||
className="absolute right-4 top-1/2 -translate-y-1/2 text-white/30 hover:text-white transition-colors"
|
||||
aria-label={showPassword ? 'Hide password' : 'Show password'}
|
||||
>
|
||||
{showPassword ? (
|
||||
<EyeOff className="w-4 h-4" />
|
||||
) : (
|
||||
<Eye className="w-4 h-4" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
{oauthProviders.google_enabled && (
|
||||
<a
|
||||
href={api.getGoogleLoginUrl(redirectTo)}
|
||||
className="w-full py-3 sm:py-3.5 bg-[#24292e] text-white text-sm font-medium rounded-xl
|
||||
hover:bg-[#2f363d] border border-[#24292e]
|
||||
transition-all duration-300 flex items-center justify-center gap-3"
|
||||
>
|
||||
<GoogleIcon className="w-5 h-5" />
|
||||
Continue with Google
|
||||
</a>
|
||||
)}
|
||||
{oauthProviders.github_enabled && (
|
||||
<a
|
||||
href={api.getGitHubLoginUrl(redirectTo)}
|
||||
className="w-full py-3 sm:py-3.5 bg-[#24292e] text-white text-sm font-medium rounded-xl
|
||||
hover:bg-[#2f363d] border border-[#24292e]
|
||||
transition-all duration-300 flex items-center justify-center gap-3"
|
||||
>
|
||||
<GitHubIcon className="w-5 h-5" />
|
||||
Continue with GitHub
|
||||
</a>
|
||||
)}
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Link
|
||||
href="/forgot-password"
|
||||
className="text-[10px] font-mono text-white/40 hover:text-accent uppercase tracking-wider transition-colors"
|
||||
>
|
||||
Lost Credentials?
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
disabled={loading}
|
||||
className="w-full py-4 bg-white text-black text-xs font-bold uppercase tracking-[0.2em] hover:bg-accent transition-all disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-3"
|
||||
style={{ clipPath: 'polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px)' }}
|
||||
>
|
||||
{loading ? (
|
||||
<Loader2 className="w-4 h-4 animate-spin" />
|
||||
) : (
|
||||
<>
|
||||
Initialize Session
|
||||
<ArrowRight className="w-4 h-4" />
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{/* OAuth Buttons */}
|
||||
{(oauthProviders.google_enabled || oauthProviders.github_enabled) && (
|
||||
<div className="mt-8">
|
||||
<div className="relative mb-8">
|
||||
<div className="absolute inset-0 flex items-center">
|
||||
<div className="w-full border-t border-white/10" />
|
||||
</div>
|
||||
<div className="relative flex justify-center">
|
||||
<span className="px-4 bg-[#050505] text-[10px] font-mono text-white/30 uppercase tracking-widest">Alternative Access</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
{oauthProviders.google_enabled && (
|
||||
<a
|
||||
href={api.getGoogleLoginUrl(redirectTo)}
|
||||
className="w-full py-3 bg-[#0A0A0A] border border-white/10 text-white text-xs font-mono uppercase tracking-wide hover:bg-white/5 hover:border-white/30 transition-all flex items-center justify-center gap-3"
|
||||
>
|
||||
<GoogleIcon className="w-4 h-4" />
|
||||
Google
|
||||
</a>
|
||||
)}
|
||||
{oauthProviders.github_enabled && (
|
||||
<a
|
||||
href={api.getGitHubLoginUrl(redirectTo)}
|
||||
className="w-full py-3 bg-[#0A0A0A] border border-white/10 text-white text-xs font-mono uppercase tracking-wide hover:bg-white/5 hover:border-white/30 transition-all flex items-center justify-center gap-3"
|
||||
>
|
||||
<GitHubIcon className="w-4 h-4" />
|
||||
GitHub
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Register Link */}
|
||||
<div className="mt-8 pt-8 border-t border-white/10 text-center">
|
||||
<p className="text-xs font-mono text-white/40">
|
||||
No clearance?{' '}
|
||||
<Link href={registerLink} className="text-white hover:text-accent border-b border-white/20 hover:border-accent transition-all pb-0.5 ml-1">
|
||||
Request Access
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Register Link */}
|
||||
<p className="mt-8 sm:mt-10 text-center text-body-xs sm:text-body-sm text-foreground-muted">
|
||||
Don't have an account?{' '}
|
||||
<Link href={registerLink} className="text-foreground hover:text-accent transition-colors duration-300">
|
||||
Create one
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function LoginPage() {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center px-4 sm:px-6 py-8 sm:py-12 relative">
|
||||
{/* Ambient glow */}
|
||||
<div className="fixed inset-0 pointer-events-none">
|
||||
<div className="absolute top-1/4 left-1/2 -translate-x-1/2 w-[400px] h-[300px] bg-accent/[0.02] rounded-full blur-3xl" />
|
||||
<div className="min-h-screen flex items-center justify-center px-4 sm:px-6 py-8 sm:py-12 relative bg-[#020202] overflow-hidden">
|
||||
{/* Living Background Atmosphere */}
|
||||
<div className="fixed inset-0 pointer-events-none overflow-hidden">
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.04] mix-blend-overlay z-10" />
|
||||
|
||||
{/* Animated Orbs */}
|
||||
<div className="absolute top-[-10%] left-[-10%] w-[60vw] h-[60vw] bg-accent/10 rounded-full blur-[120px] animate-pulse-slow mix-blend-screen" />
|
||||
<div className="absolute bottom-[-10%] right-[-10%] w-[50vw] h-[50vw] bg-purple-500/10 rounded-full blur-[150px] animate-pulse-slower mix-blend-screen" />
|
||||
<div className="absolute top-[40%] left-[40%] w-[40vw] h-[40vw] bg-blue-500/5 rounded-full blur-[100px] animate-blob mix-blend-screen" />
|
||||
|
||||
{/* Grid Overlay */}
|
||||
<div
|
||||
className="absolute inset-0 opacity-[0.03] z-0"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(rgba(255,255,255,0.3) 0.5px, transparent 0.5px), linear-gradient(90deg, rgba(255,255,255,0.3) 0.5px, transparent 0.5px)`,
|
||||
backgroundSize: '40px 40px',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Suspense fallback={
|
||||
<div className="w-5 h-5 border-2 border-accent border-t-transparent rounded-full animate-spin" />
|
||||
<div className="w-8 h-8 border-2 border-white/10 border-t-accent rounded-full animate-spin" />
|
||||
}>
|
||||
<LoginForm />
|
||||
</Suspense>
|
||||
|
||||
@ -1,730 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useState, useMemo } from 'react'
|
||||
import { useStore } from '@/lib/store'
|
||||
import { api } from '@/lib/api'
|
||||
import { Header } from '@/components/Header'
|
||||
import { Footer } from '@/components/Footer'
|
||||
import { PlatformBadge } from '@/components/PremiumTable'
|
||||
import {
|
||||
Clock,
|
||||
ExternalLink,
|
||||
Search,
|
||||
Flame,
|
||||
Timer,
|
||||
Gavel,
|
||||
DollarSign,
|
||||
X,
|
||||
Lock,
|
||||
TrendingUp,
|
||||
ChevronUp,
|
||||
ChevronDown,
|
||||
ChevronsUpDown,
|
||||
Sparkles,
|
||||
Diamond,
|
||||
ShieldCheck,
|
||||
Zap,
|
||||
Filter,
|
||||
} from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import clsx from 'clsx'
|
||||
|
||||
interface MarketItem {
|
||||
id: string
|
||||
domain: string
|
||||
tld: string
|
||||
price: number
|
||||
currency: string
|
||||
price_type: 'bid' | 'fixed' | 'negotiable'
|
||||
status: 'auction' | 'instant'
|
||||
source: string
|
||||
is_pounce: boolean
|
||||
verified: boolean
|
||||
time_remaining?: string
|
||||
end_time?: string
|
||||
num_bids?: number
|
||||
slug?: string
|
||||
seller_verified: boolean
|
||||
url: string
|
||||
is_external: boolean
|
||||
pounce_score: number
|
||||
}
|
||||
|
||||
interface Auction {
|
||||
domain: string
|
||||
platform: string
|
||||
platform_url: string
|
||||
current_bid: number
|
||||
currency: string
|
||||
num_bids: number
|
||||
end_time: string
|
||||
time_remaining: string
|
||||
buy_now_price: number | null
|
||||
reserve_met: boolean | null
|
||||
traffic: number | null
|
||||
age_years: number | null
|
||||
tld: string
|
||||
affiliate_url: string
|
||||
}
|
||||
|
||||
type TabType = 'all' | 'ending' | 'hot'
|
||||
type SortField = 'domain' | 'ending' | 'bid' | 'bids'
|
||||
type SortDirection = 'asc' | 'desc'
|
||||
|
||||
const PLATFORMS = [
|
||||
{ id: 'All', name: 'All Sources' },
|
||||
{ id: 'GoDaddy', name: 'GoDaddy' },
|
||||
{ id: 'Sedo', name: 'Sedo' },
|
||||
{ id: 'NameJet', name: 'NameJet' },
|
||||
{ id: 'DropCatch', name: 'DropCatch' },
|
||||
]
|
||||
|
||||
// Premium TLDs that look professional
|
||||
const PREMIUM_TLDS = ['com', 'io', 'ai', 'co', 'de', 'ch', 'net', 'org', 'app', 'dev', 'xyz']
|
||||
|
||||
// Vanity Filter: Only show "beautiful" domains to non-authenticated users
|
||||
// Rules: No numbers (except short domains), no hyphens, length < 12, only premium TLDs
|
||||
function isVanityDomain(auction: Auction): boolean {
|
||||
const domain = auction.domain
|
||||
const parts = domain.split('.')
|
||||
if (parts.length < 2) return false
|
||||
|
||||
const name = parts[0]
|
||||
const tld = parts.slice(1).join('.').toLowerCase()
|
||||
|
||||
// Check TLD is premium
|
||||
if (!PREMIUM_TLDS.includes(tld)) return false
|
||||
|
||||
// Check length (max 12 characters for the name)
|
||||
if (name.length > 12) return false
|
||||
|
||||
// No hyphens
|
||||
if (name.includes('-')) return false
|
||||
|
||||
// No numbers (unless domain is 4 chars or less - short domains are valuable)
|
||||
if (name.length > 4 && /\d/.test(name)) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Generate a mock "Deal Score" for display purposes
|
||||
// In production, this would come from a valuation API
|
||||
function getDealScore(auction: Auction): number | null {
|
||||
let score = 50
|
||||
|
||||
const name = auction.domain.split('.')[0]
|
||||
if (name.length <= 4) score += 20
|
||||
else if (name.length <= 6) score += 10
|
||||
|
||||
if (['com', 'io', 'ai'].includes(auction.tld)) score += 15
|
||||
|
||||
if (auction.age_years && auction.age_years > 5) score += 10
|
||||
|
||||
if (auction.num_bids >= 20) score += 15
|
||||
else if (auction.num_bids >= 10) score += 10
|
||||
|
||||
return Math.min(score, 100)
|
||||
}
|
||||
|
||||
function SortIcon({ field, currentField, direction }: { field: SortField, currentField: SortField, direction: SortDirection }) {
|
||||
if (field !== currentField) {
|
||||
return <ChevronsUpDown className="w-4 h-4 text-foreground-subtle" />
|
||||
}
|
||||
return direction === 'asc'
|
||||
? <ChevronUp className="w-4 h-4 text-accent" />
|
||||
: <ChevronDown className="w-4 h-4 text-accent" />
|
||||
}
|
||||
|
||||
export default function MarketPage() {
|
||||
const { isAuthenticated, checkAuth, isLoading: authLoading } = useStore()
|
||||
|
||||
const [allAuctions, setAllAuctions] = useState<Auction[]>([])
|
||||
const [endingSoon, setEndingSoon] = useState<Auction[]>([])
|
||||
const [hotAuctions, setHotAuctions] = useState<Auction[]>([])
|
||||
const [pounceItems, setPounceItems] = useState<MarketItem[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [activeTab, setActiveTab] = useState<TabType>('all')
|
||||
const [sortField, setSortField] = useState<SortField>('ending')
|
||||
const [sortDirection, setSortDirection] = useState<SortDirection>('asc')
|
||||
|
||||
const [searchQuery, setSearchQuery] = useState('')
|
||||
const [selectedPlatform, setSelectedPlatform] = useState('All')
|
||||
const [maxBid, setMaxBid] = useState('')
|
||||
|
||||
useEffect(() => {
|
||||
checkAuth()
|
||||
loadAuctions()
|
||||
}, [checkAuth])
|
||||
|
||||
const loadAuctions = async () => {
|
||||
setLoading(true)
|
||||
try {
|
||||
const [allFeed, endingFeed, hotFeed, pounceFeed] = await Promise.all([
|
||||
api.getMarketFeed({ source: 'all', limit: 100, sortBy: 'time' }),
|
||||
api.getMarketFeed({ source: 'external', endingWithin: 24, limit: 50, sortBy: 'time' }),
|
||||
api.getMarketFeed({ source: 'external', limit: 50, sortBy: 'score' }),
|
||||
api.getMarketFeed({ source: 'pounce', limit: 10 }),
|
||||
])
|
||||
|
||||
const convertToAuction = (item: MarketItem): Auction => ({
|
||||
domain: item.domain,
|
||||
platform: item.source,
|
||||
platform_url: item.url,
|
||||
current_bid: item.price,
|
||||
currency: item.currency,
|
||||
num_bids: item.num_bids || 0,
|
||||
end_time: item.end_time || '',
|
||||
time_remaining: item.time_remaining || '',
|
||||
buy_now_price: item.price_type === 'fixed' ? item.price : null,
|
||||
reserve_met: null,
|
||||
traffic: null,
|
||||
age_years: null,
|
||||
tld: item.tld,
|
||||
affiliate_url: item.url,
|
||||
})
|
||||
|
||||
const externalOnly = (items: MarketItem[]) => items.filter(i => !i.is_pounce).map(convertToAuction)
|
||||
|
||||
setAllAuctions(externalOnly(allFeed.items || []))
|
||||
setEndingSoon(externalOnly(endingFeed.items || []))
|
||||
setHotAuctions(externalOnly(hotFeed.items || []))
|
||||
setPounceItems(pounceFeed.items || [])
|
||||
} catch (error) {
|
||||
console.error('Failed to load auctions:', error)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
const getCurrentAuctions = (): Auction[] => {
|
||||
switch (activeTab) {
|
||||
case 'ending': return endingSoon
|
||||
case 'hot': return hotAuctions
|
||||
default: return allAuctions
|
||||
}
|
||||
}
|
||||
|
||||
// Apply Vanity Filter for non-authenticated users
|
||||
const displayAuctions = useMemo(() => {
|
||||
const current = getCurrentAuctions()
|
||||
if (isAuthenticated) {
|
||||
return current
|
||||
}
|
||||
return current.filter(isVanityDomain)
|
||||
}, [activeTab, allAuctions, endingSoon, hotAuctions, isAuthenticated])
|
||||
|
||||
const filteredAuctions = displayAuctions.filter(auction => {
|
||||
if (searchQuery && !auction.domain.toLowerCase().includes(searchQuery.toLowerCase())) {
|
||||
return false
|
||||
}
|
||||
if (selectedPlatform !== 'All' && auction.platform !== selectedPlatform) {
|
||||
return false
|
||||
}
|
||||
if (maxBid && auction.current_bid > parseFloat(maxBid)) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
const handleSort = (field: SortField) => {
|
||||
if (sortField === field) {
|
||||
setSortDirection(sortDirection === 'asc' ? 'desc' : 'asc')
|
||||
} else {
|
||||
setSortField(field)
|
||||
setSortDirection('asc')
|
||||
}
|
||||
}
|
||||
|
||||
const sortedAuctions = [...filteredAuctions].sort((a, b) => {
|
||||
const modifier = sortDirection === 'asc' ? 1 : -1
|
||||
switch (sortField) {
|
||||
case 'domain':
|
||||
return a.domain.localeCompare(b.domain) * modifier
|
||||
case 'bid':
|
||||
return (a.current_bid - b.current_bid) * modifier
|
||||
case 'bids':
|
||||
return (a.num_bids - b.num_bids) * modifier
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
})
|
||||
|
||||
const formatCurrency = (amount: number, currency = 'USD') => {
|
||||
return new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(amount)
|
||||
}
|
||||
|
||||
const getTimeColor = (timeRemaining: string) => {
|
||||
if (timeRemaining.includes('m') && !timeRemaining.includes('h')) return 'text-red-400'
|
||||
if (timeRemaining.includes('h') && parseInt(timeRemaining) < 12) return 'text-amber-400'
|
||||
return 'text-foreground-muted'
|
||||
}
|
||||
|
||||
const hotPreview = hotAuctions.slice(0, 4)
|
||||
|
||||
if (authLoading) {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center">
|
||||
<div className="w-5 h-5 border-2 border-accent border-t-transparent rounded-full animate-spin" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background relative overflow-hidden">
|
||||
{/* Background Effects */}
|
||||
<div className="fixed inset-0 pointer-events-none">
|
||||
<div className="absolute top-[-20%] left-1/2 -translate-x-1/2 w-[1200px] h-[800px] bg-accent/[0.03] rounded-full blur-[120px]" />
|
||||
<div className="absolute bottom-[-10%] right-[-10%] w-[600px] h-[600px] bg-accent/[0.02] rounded-full blur-[100px]" />
|
||||
<div
|
||||
className="absolute inset-0 opacity-[0.015]"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(rgba(255,255,255,.1) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,.1) 1px, transparent 1px)`,
|
||||
backgroundSize: '64px 64px',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Header />
|
||||
|
||||
<main className="relative pt-32 sm:pt-40 pb-20 sm:pb-28 px-4 sm:px-6 flex-1">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
{/* Hero Header - gemäß pounce_public.md */}
|
||||
<div className="text-center mb-16 sm:mb-20 animate-fade-in">
|
||||
<span className="text-sm font-semibold text-accent uppercase tracking-wider">Live Market</span>
|
||||
<h1 className="mt-4 font-display text-[2.5rem] sm:text-[3.5rem] md:text-[4.5rem] lg:text-[5rem] leading-[0.95] tracking-[-0.03em] text-foreground">
|
||||
Live Domain Market
|
||||
</h1>
|
||||
<p className="mt-5 text-lg sm:text-xl text-foreground-muted max-w-2xl mx-auto">
|
||||
Aggregated from GoDaddy, Sedo, and Pounce Direct.
|
||||
</p>
|
||||
{!isAuthenticated && displayAuctions.length < allAuctions.length && (
|
||||
<p className="mt-2 text-sm text-accent flex items-center justify-center gap-1">
|
||||
<Sparkles className="w-4 h-4" />
|
||||
Showing {displayAuctions.length} premium domains • Sign in to see all {allAuctions.length}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Login Banner for non-authenticated users */}
|
||||
{!isAuthenticated && (
|
||||
<div className="mb-8 p-5 bg-accent-muted border border-accent/20 rounded-xl flex flex-col sm:flex-row items-center justify-between gap-4 animate-fade-in">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 bg-accent/20 rounded-xl flex items-center justify-center">
|
||||
<Lock className="w-5 h-5 text-accent" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-body-sm font-medium text-foreground">Unlock Smart Opportunities</p>
|
||||
<p className="text-ui-sm text-foreground-muted">
|
||||
Sign in for valuations, deal scores, and personalized recommendations.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<Link
|
||||
href="/register"
|
||||
className="shrink-0 px-5 py-2.5 bg-accent text-background text-ui font-medium rounded-lg
|
||||
hover:bg-accent-hover transition-all duration-300"
|
||||
>
|
||||
Start Hunting
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Pounce Direct Section - Featured */}
|
||||
{pounceItems.length > 0 && (
|
||||
<div className="mb-12 sm:mb-16 animate-slide-up">
|
||||
<div className="flex items-center gap-3 mb-4 sm:mb-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<Diamond className="w-5 h-5 text-accent fill-accent/20" />
|
||||
<h2 className="text-body-lg sm:text-heading-sm font-medium text-foreground">
|
||||
Pounce Direct
|
||||
</h2>
|
||||
</div>
|
||||
<span className="text-ui-sm text-foreground-subtle">Verified • Instant Buy • 0% Commission</span>
|
||||
</div>
|
||||
<div className="border border-accent/20 rounded-xl overflow-hidden bg-gradient-to-br from-accent/5 to-transparent">
|
||||
{pounceItems.map((item) => (
|
||||
<Link
|
||||
key={item.id}
|
||||
href={item.url}
|
||||
className="flex items-center justify-between px-5 py-4 border-b border-accent/10 last:border-b-0 hover:bg-accent/5 transition-all group"
|
||||
>
|
||||
<div className="flex items-center gap-4">
|
||||
<Diamond className="w-5 h-5 text-accent fill-accent/20 flex-shrink-0" />
|
||||
<div>
|
||||
<div className="font-mono text-body font-medium text-foreground group-hover:text-accent transition-colors">
|
||||
{item.domain}
|
||||
</div>
|
||||
<div className="flex items-center gap-2 mt-1">
|
||||
{item.verified && (
|
||||
<span className="inline-flex items-center gap-1 text-[10px] font-bold uppercase tracking-wide text-accent bg-accent/10 px-2 py-0.5 rounded-full">
|
||||
<ShieldCheck className="w-3 h-3" />
|
||||
Verified
|
||||
</span>
|
||||
)}
|
||||
{isAuthenticated ? (
|
||||
<span className="text-ui-sm text-foreground-subtle">
|
||||
Score: {item.pounce_score}
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-ui-sm text-foreground-subtle blur-[4px]">
|
||||
Score: XX
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="text-right">
|
||||
<div className="font-mono text-body-lg font-medium text-foreground">
|
||||
{formatCurrency(item.price, item.currency)}
|
||||
</div>
|
||||
<div className="text-ui-sm text-accent">Instant Buy</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 px-4 py-2 bg-accent text-background rounded-lg text-ui-sm font-bold opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
Buy Now
|
||||
<Zap className="w-3 h-3" />
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-3 text-center">
|
||||
<Link
|
||||
href="/buy"
|
||||
className="text-ui-sm text-accent hover:underline"
|
||||
>
|
||||
Browse all Pounce listings →
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Hot Auctions Preview */}
|
||||
{hotPreview.length > 0 && (
|
||||
<div className="mb-12 sm:mb-16 animate-slide-up">
|
||||
<h2 className="text-body-lg sm:text-heading-sm font-medium text-foreground mb-4 sm:mb-6 flex items-center gap-2">
|
||||
<Flame className="w-5 h-5 text-accent" />
|
||||
Hot Right Now
|
||||
</h2>
|
||||
<div className="grid sm:grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4">
|
||||
{hotPreview.map((auction) => (
|
||||
<a
|
||||
key={`${auction.domain}-${auction.platform}`}
|
||||
href={auction.affiliate_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="p-4 sm:p-5 bg-background-secondary/50 border border-border rounded-xl hover:border-border-hover hover:bg-background-secondary transition-all duration-300 text-left group"
|
||||
>
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<span className="font-mono text-body-lg sm:text-heading-sm text-foreground group-hover:text-accent transition-colors">
|
||||
{auction.domain}
|
||||
</span>
|
||||
<span className="text-ui-sm font-medium px-2 py-0.5 rounded-full text-accent bg-accent-muted flex items-center gap-1">
|
||||
<Flame className="w-3 h-3" />
|
||||
{auction.num_bids}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-body-sm text-foreground-muted">
|
||||
{formatCurrency(auction.current_bid)}
|
||||
</span>
|
||||
<span className={clsx("text-body-sm", getTimeColor(auction.time_remaining))}>
|
||||
{auction.time_remaining}
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-2">
|
||||
<PlatformBadge platform={auction.platform} />
|
||||
</div>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Search & Filters */}
|
||||
<div className="mb-6 animate-slide-up">
|
||||
<div className="flex flex-wrap gap-3">
|
||||
<div className="relative flex-1 min-w-[200px] max-w-md">
|
||||
<Search className="absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-foreground-subtle" />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search domains..."
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
className="w-full pl-12 pr-10 py-3 bg-background-secondary/50 border border-border rounded-xl
|
||||
text-body text-foreground placeholder:text-foreground-subtle
|
||||
focus:outline-none focus:ring-2 focus:ring-accent/30 focus:border-accent
|
||||
transition-all duration-300"
|
||||
/>
|
||||
{searchQuery && (
|
||||
<button
|
||||
onClick={() => setSearchQuery('')}
|
||||
className="absolute right-4 top-1/2 -translate-y-1/2 p-1 text-foreground-subtle hover:text-foreground transition-colors"
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<select
|
||||
value={selectedPlatform}
|
||||
onChange={(e) => setSelectedPlatform(e.target.value)}
|
||||
className="px-4 py-3 bg-background-secondary/50 border border-border rounded-xl
|
||||
text-body text-foreground cursor-pointer focus:outline-none focus:ring-2 focus:ring-accent/30 focus:border-accent"
|
||||
>
|
||||
{PLATFORMS.map(p => <option key={p.id} value={p.id}>{p.name}</option>)}
|
||||
</select>
|
||||
<div className="relative">
|
||||
<DollarSign className="absolute left-4 top-1/2 -translate-y-1/2 w-4 h-4 text-foreground-subtle" />
|
||||
<input
|
||||
type="number"
|
||||
placeholder="Max bid"
|
||||
value={maxBid}
|
||||
onChange={(e) => setMaxBid(e.target.value)}
|
||||
className="w-32 pl-10 pr-4 py-3 bg-background-secondary/50 border border-border rounded-xl
|
||||
text-body text-foreground placeholder:text-foreground-subtle
|
||||
focus:outline-none focus:ring-2 focus:ring-accent/30 focus:border-accent"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Tabs */}
|
||||
<div className="flex flex-wrap gap-2 mb-6 animate-slide-up">
|
||||
{[
|
||||
{ id: 'all' as const, label: 'All Auctions', icon: Gavel, count: allAuctions.length },
|
||||
{ id: 'ending' as const, label: 'Ending Soon', icon: Timer, count: endingSoon.length },
|
||||
{ id: 'hot' as const, label: 'Hot', icon: Flame, count: hotAuctions.length },
|
||||
].map((tab) => (
|
||||
<button
|
||||
key={tab.id}
|
||||
onClick={() => setActiveTab(tab.id)}
|
||||
className={clsx(
|
||||
"flex items-center gap-2 px-4 py-2.5 text-ui-sm font-medium rounded-xl transition-all",
|
||||
activeTab === tab.id
|
||||
? "bg-accent text-background"
|
||||
: "bg-background-secondary/50 text-foreground-muted hover:text-foreground hover:bg-background-secondary border border-border"
|
||||
)}
|
||||
>
|
||||
<tab.icon className="w-4 h-4" />
|
||||
{tab.label}
|
||||
<span className={clsx(
|
||||
"text-xs px-1.5 py-0.5 rounded",
|
||||
activeTab === tab.id ? "bg-background/20" : "bg-foreground/10"
|
||||
)}>{tab.count}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Auctions Table */}
|
||||
<div className="bg-background-secondary/30 border border-border rounded-xl overflow-hidden animate-slide-up">
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full">
|
||||
<thead>
|
||||
<tr className="bg-background-secondary border-b border-border">
|
||||
<th className="text-left px-4 sm:px-6 py-4">
|
||||
<button
|
||||
onClick={() => handleSort('domain')}
|
||||
className="flex items-center gap-2 text-ui-sm text-foreground-subtle font-medium hover:text-foreground transition-colors"
|
||||
>
|
||||
Domain
|
||||
<SortIcon field="domain" currentField={sortField} direction={sortDirection} />
|
||||
</button>
|
||||
</th>
|
||||
<th className="text-left px-4 sm:px-6 py-4 hidden lg:table-cell">
|
||||
<span className="text-ui-sm text-foreground-subtle font-medium">Source</span>
|
||||
</th>
|
||||
<th className="text-right px-4 sm:px-6 py-4">
|
||||
<button
|
||||
onClick={() => handleSort('bid')}
|
||||
className="flex items-center gap-2 ml-auto text-ui-sm text-foreground-subtle font-medium hover:text-foreground transition-colors"
|
||||
>
|
||||
Price
|
||||
<SortIcon field="bid" currentField={sortField} direction={sortDirection} />
|
||||
</button>
|
||||
</th>
|
||||
{/* Pounce Score Column - visible but blurred for non-auth (gemäß pounce_public.md) */}
|
||||
<th className="text-center px-4 sm:px-6 py-4 hidden md:table-cell">
|
||||
<span className="text-ui-sm text-foreground-subtle font-medium flex items-center justify-center gap-1">
|
||||
Pounce Score
|
||||
{!isAuthenticated && <Lock className="w-3 h-3" />}
|
||||
</span>
|
||||
</th>
|
||||
{/* Valuation Column - visible but blurred for non-auth */}
|
||||
<th className="text-center px-4 sm:px-6 py-4 hidden lg:table-cell">
|
||||
<span className="text-ui-sm text-foreground-subtle font-medium flex items-center justify-center gap-1">
|
||||
Valuation
|
||||
{!isAuthenticated && <Lock className="w-3 h-3" />}
|
||||
</span>
|
||||
</th>
|
||||
<th className="text-right px-4 sm:px-6 py-4 hidden md:table-cell">
|
||||
<button
|
||||
onClick={() => handleSort('ending')}
|
||||
className="flex items-center gap-2 ml-auto text-ui-sm text-foreground-subtle font-medium hover:text-foreground transition-colors"
|
||||
>
|
||||
Time Left
|
||||
<SortIcon field="ending" currentField={sortField} direction={sortDirection} />
|
||||
</button>
|
||||
</th>
|
||||
<th className="px-4 sm:px-6 py-4"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-border">
|
||||
{loading ? (
|
||||
Array.from({ length: 10 }).map((_, idx) => (
|
||||
<tr key={idx} className="animate-pulse">
|
||||
<td className="px-4 sm:px-6 py-4"><div className="h-4 w-32 bg-background-tertiary rounded" /></td>
|
||||
<td className="px-4 sm:px-6 py-4 hidden lg:table-cell"><div className="h-4 w-20 bg-background-tertiary rounded" /></td>
|
||||
<td className="px-4 sm:px-6 py-4"><div className="h-4 w-16 bg-background-tertiary rounded ml-auto" /></td>
|
||||
<td className="px-4 sm:px-6 py-4 hidden md:table-cell"><div className="h-8 w-8 bg-background-tertiary rounded mx-auto" /></td>
|
||||
<td className="px-4 sm:px-6 py-4 hidden lg:table-cell"><div className="h-4 w-16 bg-background-tertiary rounded mx-auto" /></td>
|
||||
<td className="px-4 sm:px-6 py-4 hidden md:table-cell"><div className="h-4 w-16 bg-background-tertiary rounded ml-auto" /></td>
|
||||
<td className="px-4 sm:px-6 py-4"><div className="h-8 w-16 bg-background-tertiary rounded ml-auto" /></td>
|
||||
</tr>
|
||||
))
|
||||
) : sortedAuctions.length === 0 ? (
|
||||
<tr>
|
||||
<td colSpan={7} className="px-6 py-12 text-center text-foreground-muted">
|
||||
{searchQuery ? `No domains found matching "${searchQuery}"` : 'No domains found'}
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
sortedAuctions.map((auction) => (
|
||||
<tr
|
||||
key={`${auction.domain}-${auction.platform}`}
|
||||
className="hover:bg-background-secondary/50 transition-colors group"
|
||||
>
|
||||
<td className="px-4 sm:px-6 py-4">
|
||||
<div>
|
||||
<a
|
||||
href={auction.affiliate_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="font-mono text-body-sm sm:text-body font-medium text-foreground hover:text-accent transition-colors"
|
||||
>
|
||||
{auction.domain}
|
||||
</a>
|
||||
<div className="flex items-center gap-2 mt-1 lg:hidden">
|
||||
<PlatformBadge platform={auction.platform} />
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-4 sm:px-6 py-4 hidden lg:table-cell">
|
||||
<div className="space-y-1">
|
||||
<PlatformBadge platform={auction.platform} />
|
||||
{auction.age_years && (
|
||||
<span className="text-ui-sm text-foreground-subtle flex items-center gap-1">
|
||||
<Clock className="w-3 h-3" /> {auction.age_years}y
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-4 sm:px-6 py-4 text-right">
|
||||
<div>
|
||||
<span className="text-body-sm font-medium text-foreground">
|
||||
{formatCurrency(auction.current_bid)}
|
||||
</span>
|
||||
{auction.buy_now_price && (
|
||||
<p className="text-ui-sm text-accent">Buy: {formatCurrency(auction.buy_now_price)}</p>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
{/* Pounce Score - blurred for non-authenticated (gemäß pounce_public.md) */}
|
||||
<td className="px-4 sm:px-6 py-4 text-center hidden md:table-cell">
|
||||
{isAuthenticated ? (
|
||||
<div className="inline-flex flex-col items-center">
|
||||
<span className={clsx(
|
||||
"inline-flex items-center justify-center w-9 h-9 rounded-lg font-bold text-sm",
|
||||
(getDealScore(auction) ?? 0) >= 75 ? "bg-accent/20 text-accent" :
|
||||
(getDealScore(auction) ?? 0) >= 50 ? "bg-amber-500/20 text-amber-400" :
|
||||
"bg-foreground/10 text-foreground-muted"
|
||||
)}>
|
||||
{getDealScore(auction)}
|
||||
</span>
|
||||
{(getDealScore(auction) ?? 0) >= 75 && (
|
||||
<span className="text-[10px] text-accent mt-0.5 font-medium">Good Deal</span>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
className="inline-flex items-center justify-center w-9 h-9 rounded-lg bg-foreground/5 text-foreground-muted blur-[3px] cursor-pointer"
|
||||
title="Sign in to unlock valuations"
|
||||
>
|
||||
<span className="font-bold text-sm">XX</span>
|
||||
</div>
|
||||
)}
|
||||
</td>
|
||||
{/* Valuation - blurred for non-authenticated */}
|
||||
<td className="px-4 sm:px-6 py-4 text-center hidden lg:table-cell">
|
||||
{isAuthenticated ? (
|
||||
<span className="text-body-sm font-medium text-foreground">
|
||||
${(auction.current_bid * 1.5).toFixed(0)}
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-body-sm font-medium text-foreground-muted blur-[3px]">
|
||||
$X,XXX
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
<td className="px-4 sm:px-6 py-4 text-right hidden md:table-cell">
|
||||
<span className={clsx("font-medium", getTimeColor(auction.time_remaining))}>
|
||||
{auction.time_remaining}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-4 sm:px-6 py-4">
|
||||
<a
|
||||
href={auction.affiliate_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-1 text-ui-sm text-accent hover:text-accent-hover transition-colors opacity-0 group-hover:opacity-100"
|
||||
>
|
||||
Bid
|
||||
<ExternalLink className="w-3 h-3" />
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Stats */}
|
||||
{!loading && (
|
||||
<div className="mt-6 flex justify-center">
|
||||
<p className="text-ui-sm text-foreground-subtle">
|
||||
{searchQuery
|
||||
? `Found ${sortedAuctions.length} domains matching "${searchQuery}"`
|
||||
: `${allAuctions.length} domains available across ${PLATFORMS.length - 1} platforms`
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Bottom CTA for upgrade (gemäß pounce_public.md) */}
|
||||
{!isAuthenticated && (
|
||||
<div className="mt-12 p-6 sm:p-8 bg-gradient-to-r from-accent/10 to-accent/5 border border-accent/20 rounded-2xl text-center animate-slide-up">
|
||||
<div className="flex items-center justify-center gap-2 mb-3">
|
||||
<Filter className="w-5 h-5 text-accent" />
|
||||
<h3 className="text-lg font-medium text-foreground">Tired of digging through spam?</h3>
|
||||
</div>
|
||||
<p className="text-foreground-muted mb-5 max-w-lg mx-auto">
|
||||
Our 'Trader' plan filters 99% of junk domains automatically. See only premium opportunities.
|
||||
</p>
|
||||
<Link
|
||||
href="/pricing"
|
||||
className="inline-flex items-center gap-2 px-6 py-3 bg-accent text-background rounded-xl font-medium
|
||||
hover:bg-accent-hover transition-all shadow-[0_0_20px_rgba(16,185,129,0.2)]"
|
||||
>
|
||||
Upgrade Filter
|
||||
<TrendingUp className="w-4 h-4" />
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -8,43 +8,29 @@ import { DomainChecker } from '@/components/DomainChecker'
|
||||
import { useStore } from '@/lib/store'
|
||||
import { api } from '@/lib/api'
|
||||
import {
|
||||
Eye,
|
||||
Bell,
|
||||
Clock,
|
||||
Shield,
|
||||
ArrowRight,
|
||||
TrendingUp,
|
||||
TrendingDown,
|
||||
Minus,
|
||||
ChevronRight,
|
||||
Zap,
|
||||
BarChart3,
|
||||
Globe,
|
||||
Check,
|
||||
Search,
|
||||
Target,
|
||||
Gavel,
|
||||
Sparkles,
|
||||
Activity,
|
||||
LineChart,
|
||||
Lock,
|
||||
Filter,
|
||||
Crosshair,
|
||||
Tag,
|
||||
AlertTriangle,
|
||||
Briefcase,
|
||||
Coins,
|
||||
Layers,
|
||||
ArrowUpRight,
|
||||
ShieldCheck,
|
||||
Smartphone,
|
||||
Globe2,
|
||||
Server,
|
||||
Database,
|
||||
Cpu,
|
||||
Network,
|
||||
Share2,
|
||||
Key
|
||||
Key,
|
||||
Shield,
|
||||
Radar,
|
||||
Scan,
|
||||
Radio,
|
||||
Cpu
|
||||
} from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import clsx from 'clsx'
|
||||
@ -56,36 +42,6 @@ interface HotAuction {
|
||||
platform: string
|
||||
}
|
||||
|
||||
// Animated counter with easing
|
||||
function AnimatedNumber({ value, suffix = '' }: { value: number, suffix?: string }) {
|
||||
const [count, setCount] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
const duration = 2500
|
||||
const steps = 60
|
||||
const increment = value / steps
|
||||
|
||||
let startTime = Date.now()
|
||||
|
||||
const timer = setInterval(() => {
|
||||
const now = Date.now()
|
||||
const progress = Math.min((now - startTime) / duration, 1)
|
||||
const easeOutQuart = 1 - Math.pow(1 - progress, 4)
|
||||
|
||||
if (progress < 1) {
|
||||
setCount(Math.floor(value * easeOutQuart))
|
||||
} else {
|
||||
setCount(value)
|
||||
clearInterval(timer)
|
||||
}
|
||||
}, 1000 / 60)
|
||||
|
||||
return () => clearInterval(timer)
|
||||
}, [value])
|
||||
|
||||
return <>{count.toLocaleString()}{suffix}</>
|
||||
}
|
||||
|
||||
// High-end Live Market Ticker - Monochrome & Technical
|
||||
function MarketTicker({ auctions }: { auctions: HotAuction[] }) {
|
||||
const tickerRef = useRef<HTMLDivElement>(null)
|
||||
@ -112,7 +68,7 @@ function MarketTicker({ auctions }: { auctions: HotAuction[] }) {
|
||||
className="flex items-center gap-6 px-8 border-r border-white/[0.08] group cursor-default transition-colors hover:bg-white/[0.02]"
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-1.5 h-1.5 rounded-full bg-accent opacity-50 group-hover:opacity-100 transition-opacity" />
|
||||
<div className="w-1.5 h-1.5 rounded-none bg-accent opacity-50 group-hover:opacity-100 transition-opacity" />
|
||||
<span className="font-mono text-xs text-white/70 font-medium group-hover:text-white transition-colors tracking-wide">
|
||||
{auction.domain}
|
||||
</span>
|
||||
@ -144,7 +100,7 @@ export default function HomePage() {
|
||||
const auctions = await api.getHotAuctions(8).catch(() => [])
|
||||
setHotAuctions(auctions.slice(0, 8))
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch data:', error)
|
||||
console.error('Mission failed:', error)
|
||||
} finally {
|
||||
setLoadingAuctions(false)
|
||||
}
|
||||
@ -154,7 +110,7 @@ export default function HomePage() {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-[#020202]">
|
||||
<div className="relative">
|
||||
<div className="w-12 h-12 rounded-full border-[0.5px] border-white/10 border-t-accent animate-spin" />
|
||||
<div className="w-12 h-12 border-[0.5px] border-white/10 border-t-accent animate-spin rounded-full" />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@ -164,10 +120,7 @@ export default function HomePage() {
|
||||
<div className="min-h-screen bg-[#020202] text-white relative overflow-x-hidden selection:bg-accent/30 selection:text-white">
|
||||
{/* Cinematic Background - Architectural & Fine */}
|
||||
<div className="fixed inset-0 pointer-events-none z-0">
|
||||
{/* Fine Noise */}
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.04] mix-blend-overlay" />
|
||||
|
||||
{/* Architectural Grid - Ultra fine */}
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.03] mix-blend-overlay" />
|
||||
<div
|
||||
className="absolute inset-0 opacity-[0.03]"
|
||||
style={{
|
||||
@ -175,97 +128,93 @@ export default function HomePage() {
|
||||
backgroundSize: '160px 160px',
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Ambient Light - Very Subtle & Localized */}
|
||||
<div className="absolute top-[-30%] left-1/2 -translate-x-1/2 w-[1200px] h-[800px] bg-accent/[0.03] rounded-full blur-[180px]" />
|
||||
<div className="absolute top-[-30%] left-1/2 -translate-x-1/2 w-[1200px] h-[800px] bg-accent/[0.02] rounded-full blur-[200px]" />
|
||||
</div>
|
||||
|
||||
<Header />
|
||||
|
||||
{/* HERO SECTION: Brutally Catchy & Noble */}
|
||||
<section className="relative min-h-[90vh] flex flex-col justify-center pt-32 pb-24 px-4 sm:px-6 z-10">
|
||||
<div className="max-w-[1600px] mx-auto w-full">
|
||||
<div className="grid lg:grid-cols-12 gap-12 lg:gap-20 items-center">
|
||||
<div className="max-w-[1400px] mx-auto w-full">
|
||||
<div className="grid lg:grid-cols-12 gap-16 lg:gap-24 items-center">
|
||||
|
||||
{/* Left: Typography & Brand */}
|
||||
<div className="lg:col-span-7 relative z-20 text-center lg:text-left">
|
||||
{/* Brand Seal - COLORFUL AGAIN */}
|
||||
<div className="inline-flex items-center gap-3 mb-12 animate-fade-in opacity-0" style={{ animationDelay: '0.1s', animationFillMode: 'forwards' }}>
|
||||
<div className="relative w-20 h-20 lg:w-24 lg:h-24">
|
||||
<div className="absolute inset-0 bg-accent/20 blur-2xl rounded-full animate-pulse" />
|
||||
{/* Brand Seal */}
|
||||
<div className="inline-flex items-center gap-4 mb-10 animate-fade-in opacity-0" style={{ animationDelay: '0.1s', animationFillMode: 'forwards' }}>
|
||||
<div className="relative w-16 h-16">
|
||||
<div className="absolute inset-0 bg-accent/20 blur-xl rounded-full animate-pulse" />
|
||||
<Image
|
||||
src="/pounce-puma.png"
|
||||
alt="Pounce Seal"
|
||||
fill
|
||||
className="object-contain drop-shadow-[0_0_25px_rgba(16,185,129,0.3)]"
|
||||
className="object-contain drop-shadow-[0_0_20px_rgba(16,185,129,0.2)]"
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
<div className="h-px w-12 lg:w-20 bg-gradient-to-r from-accent/40 to-transparent" />
|
||||
<span className="text-[10px] lg:text-xs font-mono uppercase tracking-[0.3em] text-accent/80">Est. 2025</span>
|
||||
<div className="h-px w-12 bg-white/10" />
|
||||
<span className="text-[10px] font-mono uppercase tracking-[0.3em] text-accent">Est. 2025 // Global Operations</span>
|
||||
</div>
|
||||
|
||||
{/* Headline - Improved Spacing & Color */}
|
||||
<h1 className="font-display text-[3.5rem] sm:text-[5rem] md:text-[6rem] lg:text-[7.5rem] leading-[0.9] tracking-[-0.04em] text-white mb-8 lg:mb-10">
|
||||
{/* Headline */}
|
||||
<h1 className="font-display text-[3.5rem] sm:text-[5rem] md:text-[6rem] lg:text-[7rem] leading-[0.9] tracking-[-0.04em] text-white mb-8">
|
||||
<span className="block animate-slide-up opacity-0" style={{ animationDelay: '0.2s', animationFillMode: 'forwards' }}>
|
||||
The market
|
||||
</span>
|
||||
<span className="block text-white animate-slide-up opacity-0" style={{ animationDelay: '0.4s', animationFillMode: 'forwards' }}>
|
||||
never sleeps.
|
||||
</span>
|
||||
<span className="block mt-4 lg:mt-6 text-white/40 animate-slide-up opacity-0 pb-4" style={{ animationDelay: '0.6s', animationFillMode: 'forwards' }}>
|
||||
<span className="block mt-4 lg:mt-6 text-white/40 animate-slide-up opacity-0" style={{ animationDelay: '0.6s', animationFillMode: 'forwards' }}>
|
||||
You should.
|
||||
</span>
|
||||
</h1>
|
||||
|
||||
{/* Subline & Stats */}
|
||||
<div className="animate-slide-up opacity-0" style={{ animationDelay: '0.8s', animationFillMode: 'forwards' }}>
|
||||
<p className="text-lg lg:text-2xl text-white/60 max-w-xl font-light leading-relaxed mb-12">
|
||||
Institutional-grade intelligence for the digital asset economy.
|
||||
<span className="text-white block mt-2 font-medium">Scan. Track. Trade. Yield.</span>
|
||||
<p className="text-lg lg:text-xl text-white/60 max-w-xl font-light leading-relaxed mb-12 lg:mx-0 mx-auto">
|
||||
Transforming domains from static addresses into yield-bearing financial assets.
|
||||
<span className="text-white block mt-1 font-medium">Scan. Acquire. Route. Profit.</span>
|
||||
</p>
|
||||
|
||||
{/* Stats Grid - Moved here */}
|
||||
<div className="grid grid-cols-2 sm:grid-cols-4 gap-8 pt-8 border-t border-white/[0.08]">
|
||||
{/* Stats Grid */}
|
||||
<div className="grid grid-cols-2 sm:grid-cols-4 gap-x-8 gap-y-4 pt-8 border-t border-white/[0.08]">
|
||||
<div>
|
||||
<div className="text-2xl lg:text-3xl font-display text-white mb-1">886+</div>
|
||||
<div className="text-[10px] uppercase tracking-widest text-accent/60">TLDs Tracked</div>
|
||||
<div className="text-2xl font-display text-white mb-1">886+</div>
|
||||
<div className="text-[10px] uppercase tracking-widest text-white/40 font-mono">TLDs Scanned</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-2xl lg:text-3xl font-display text-white mb-1">24/7</div>
|
||||
<div className="text-[10px] uppercase tracking-widest text-accent/60">Live Monitoring</div>
|
||||
<div className="text-2xl font-display text-white mb-1">24/7</div>
|
||||
<div className="text-[10px] uppercase tracking-widest text-white/40 font-mono">Live Recon</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-2xl lg:text-3xl font-display text-white mb-1">10s</div>
|
||||
<div className="text-[10px] uppercase tracking-widest text-accent/60">Latency</div>
|
||||
<div className="text-2xl font-display text-white mb-1">10s</div>
|
||||
<div className="text-[10px] uppercase tracking-widest text-white/40 font-mono">Latency</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-2xl lg:text-3xl font-display text-white mb-1">$1B+</div>
|
||||
<div className="text-[10px] uppercase tracking-widest text-accent/60">Volume</div>
|
||||
<div className="text-2xl font-display text-white mb-1">$1B+</div>
|
||||
<div className="text-[10px] uppercase tracking-widest text-white/40 font-mono">Assets Tracked</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right: The Artifact (Domain Checker) - HIGHER VISIBILITY */}
|
||||
<div className="lg:col-span-5 relative animate-scale-in opacity-0 mt-12 lg:mt-0" style={{ animationDelay: '1s', animationFillMode: 'forwards' }}>
|
||||
{/* Stronger Glow for Visibility */}
|
||||
<div className="absolute -inset-1 bg-gradient-to-tr from-accent/20 via-white/20 to-accent/20 blur-xl opacity-50" />
|
||||
{/* Right: The Artifact (Domain Checker) */}
|
||||
<div className="lg:col-span-5 relative animate-scale-in opacity-0 mt-8 lg:mt-0" style={{ animationDelay: '1s', animationFillMode: 'forwards' }}>
|
||||
<div className="absolute -inset-1 bg-gradient-to-tr from-accent/20 via-white/10 to-accent/20 blur-2xl opacity-40" />
|
||||
|
||||
<div className="relative z-10 bg-[#0F0F0F] border border-white/30 p-2 shadow-[0_0_60px_-15px_rgba(0,0,0,1)]">
|
||||
<div className="absolute -top-px -left-px w-4 h-4 border-t border-l border-white/50" />
|
||||
<div className="absolute -top-px -right-px w-4 h-4 border-t border-r border-white/50" />
|
||||
<div className="absolute -bottom-px -left-px w-4 h-4 border-b border-l border-white/50" />
|
||||
<div className="absolute -bottom-px -right-px w-4 h-4 border-b border-r border-white/50" />
|
||||
<div className="relative z-10 bg-[#0A0A0A] border border-white/20 p-2 shadow-2xl">
|
||||
{/* Tech Corners */}
|
||||
<div className="absolute -top-px -left-px w-4 h-4 border-t border-l border-white/40" />
|
||||
<div className="absolute -top-px -right-px w-4 h-4 border-t border-r border-white/40" />
|
||||
<div className="absolute -bottom-px -left-px w-4 h-4 border-b border-l border-white/40" />
|
||||
<div className="absolute -bottom-px -right-px w-4 h-4 border-b border-r border-white/40" />
|
||||
|
||||
<div className="bg-[#080808] p-8 lg:p-10 border border-white/10 relative overflow-hidden">
|
||||
|
||||
{/* Subtle Background within card */}
|
||||
<div className="bg-[#050505] p-8 lg:p-10 border border-white/5 relative overflow-hidden">
|
||||
<div className="absolute inset-0 bg-white/[0.02]" />
|
||||
|
||||
<div className="relative z-10">
|
||||
<div className="flex items-center justify-between mb-8">
|
||||
<span className="text-[10px] font-mono uppercase tracking-[0.2em] text-accent/80 flex items-center gap-2">
|
||||
<span className="text-[10px] font-mono uppercase tracking-[0.2em] text-accent flex items-center gap-2">
|
||||
<span className="w-1.5 h-1.5 bg-accent animate-pulse" />
|
||||
Terminal Access
|
||||
</span>
|
||||
@ -276,8 +225,7 @@ export default function HomePage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* The Checker Component */}
|
||||
<div className="bg-[#0A0A0A] border-[0.5px] border-white/10 p-1.5 shadow-inner">
|
||||
<div className="bg-[#0A0A0A] border-[0.5px] border-white/10 p-2 shadow-inner">
|
||||
<DomainChecker />
|
||||
</div>
|
||||
|
||||
@ -299,40 +247,49 @@ export default function HomePage() {
|
||||
)}
|
||||
|
||||
{/* THE PARADIGM SHIFT - Problem / Solution */}
|
||||
<section className="relative py-32 px-4 sm:px-6 border-b border-white/[0.08]">
|
||||
<section className="relative py-32 px-4 sm:px-6 border-b border-white/[0.05]">
|
||||
<div className="max-w-[1200px] mx-auto">
|
||||
<div className="grid lg:grid-cols-2 gap-16 lg:gap-24 items-center">
|
||||
<div>
|
||||
<span className="text-accent font-mono text-xs uppercase tracking-[0.2em] mb-4 block">The Problem</span>
|
||||
<span className="text-accent font-mono text-xs uppercase tracking-[0.2em] mb-4 block">The Broken Model</span>
|
||||
<h2 className="font-display text-4xl sm:text-5xl text-white leading-tight mb-8">
|
||||
99% of domains are <br/><span className="text-white/30">dead capital.</span>
|
||||
99% of portfolios are <br/><span className="text-white/30">bleeding cash.</span>
|
||||
</h2>
|
||||
<div className="space-y-6 text-white/50 leading-relaxed text-lg font-light">
|
||||
<div className="space-y-6 text-white/60 leading-relaxed text-lg font-light">
|
||||
<p>
|
||||
Most investors guess. They buy domains based on "sound" and pay renewal fees for years, hoping for a random buyer.
|
||||
Investors pay renewal fees for years, hoping for a "Unicorn" sale that never happens. It's gambling, not investing.
|
||||
</p>
|
||||
<p>
|
||||
Traditional marketplaces are flooded with spam, parking pages generate pennies, and valuable assets gather dust.
|
||||
Traditional parking pays pennies. Marketplaces charge 20% fees. The system is designed to drain your capital.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative">
|
||||
<div className="absolute -inset-4 bg-accent/5 blur-3xl rounded-full" />
|
||||
<div className="absolute -inset-4 bg-accent/5 blur-3xl" />
|
||||
<div className="relative bg-[#050505] border border-white/10 p-8 lg:p-12">
|
||||
<span className="text-accent font-mono text-xs uppercase tracking-[0.2em] mb-4 block">The Pounce Standard</span>
|
||||
<h3 className="font-display text-3xl text-white mb-6">Asset Class V2.0</h3>
|
||||
<ul className="space-y-4 font-mono text-sm text-white/80">
|
||||
<li className="flex items-start gap-3">
|
||||
<Check className="w-5 h-5 text-accent mt-px" />
|
||||
<span><span className="text-white font-bold">Data-Driven:</span> Don't guess price. Know the valuation.</span>
|
||||
<span className="text-accent font-mono text-xs uppercase tracking-[0.2em] mb-4 block">The Pounce Protocol</span>
|
||||
<h3 className="font-display text-3xl text-white mb-8">Asset Class V2.0</h3>
|
||||
<ul className="space-y-6 font-mono text-sm text-white/80">
|
||||
<li className="flex items-start gap-4">
|
||||
<Radar className="w-5 h-5 text-accent mt-px shrink-0" />
|
||||
<div>
|
||||
<span className="text-white font-bold block mb-1">Deep Recon</span>
|
||||
<span className="text-white/50">Zone file analysis reveals what's truly valuable. Don't guess. Know.</span>
|
||||
</div>
|
||||
</li>
|
||||
<li className="flex items-start gap-3">
|
||||
<Check className="w-5 h-5 text-accent mt-px" />
|
||||
<span><span className="text-white font-bold">Liquid:</span> Instant settlement. No middlemen.</span>
|
||||
<li className="flex items-start gap-4">
|
||||
<Zap className="w-5 h-5 text-accent mt-px shrink-0" />
|
||||
<div>
|
||||
<span className="text-white font-bold block mb-1">Frictionless Liquidity</span>
|
||||
<span className="text-white/50">Instant settlement. Verified owners. 0% Commission.</span>
|
||||
</div>
|
||||
</li>
|
||||
<li className="flex items-start gap-3">
|
||||
<Check className="w-5 h-5 text-accent mt-px" />
|
||||
<span><span className="text-white font-bold">Yield-Bearing:</span> Intent Routing turns traffic into revenue.</span>
|
||||
<li className="flex items-start gap-4">
|
||||
<Coins className="w-5 h-5 text-accent mt-px shrink-0" />
|
||||
<div>
|
||||
<span className="text-white font-bold block mb-1">Automated Yield</span>
|
||||
<span className="text-white/50">Domains pay for their own renewals via Intent Routing™.</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -341,15 +298,15 @@ export default function HomePage() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* THE THREE PILLARS + YIELD - Architectural Layout */}
|
||||
{/* CORE ARCHITECTURE - 3 Pillars */}
|
||||
<section className="relative py-40 px-4 sm:px-6 bg-[#020202]">
|
||||
<div className="max-w-[1600px] mx-auto">
|
||||
<div className="max-w-[1400px] mx-auto">
|
||||
{/* Section Header */}
|
||||
<div className="flex flex-col lg:flex-row justify-between items-end mb-24 border-b border-white/[0.08] pb-12">
|
||||
<div>
|
||||
<span className="text-accent font-mono text-xs uppercase tracking-[0.2em] mb-4 block">Core Architecture</span>
|
||||
<h2 className="font-display text-4xl sm:text-5xl lg:text-6xl text-white leading-none">
|
||||
The Domain Lifecycle <br />
|
||||
The Lifecycle <br />
|
||||
<span className="text-white/30">Engine.</span>
|
||||
</h2>
|
||||
</div>
|
||||
@ -362,8 +319,8 @@ export default function HomePage() {
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-px bg-white/[0.08] border border-white/[0.08]">
|
||||
|
||||
{/* 1. INTELLIGENCE (Discover) */}
|
||||
<div className="group relative bg-[#030303] p-12 lg:p-16 hover:bg-[#050505] transition-colors duration-500">
|
||||
{/* 1. INTELLIGENCE */}
|
||||
<div className="group relative bg-[#030303] p-10 lg:p-14 hover:bg-[#050505] transition-colors duration-500">
|
||||
<div className="absolute top-0 right-0 p-6 opacity-0 group-hover:opacity-100 transition-opacity duration-500">
|
||||
<ArrowUpRight className="w-6 h-6 text-white/20" />
|
||||
</div>
|
||||
@ -375,13 +332,13 @@ export default function HomePage() {
|
||||
</div>
|
||||
<h3 className="text-3xl text-white font-display mb-6">Intelligence</h3>
|
||||
<p className="text-white/50 leading-relaxed text-lg font-light mb-12">
|
||||
"Find the Asset." We scan 886+ TLDs in real-time to uncover hidden opportunities before the market reacts.
|
||||
"Identify Targets." We scan 886+ TLDs in real-time to uncover hidden opportunities before the market reacts.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6 pt-12 border-t border-white/[0.05]">
|
||||
<div className="flex items-start gap-4">
|
||||
<Search className="w-5 h-5 text-accent mt-1" />
|
||||
<Scan className="w-5 h-5 text-accent mt-1" />
|
||||
<div>
|
||||
<div className="text-white font-medium mb-1">Global Scan</div>
|
||||
<div className="text-white/30 text-sm">Zone file analysis & expiration monitoring.</div>
|
||||
@ -398,8 +355,8 @@ export default function HomePage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 2. MARKET (Acquire) */}
|
||||
<div className="group relative bg-[#030303] p-12 lg:p-16 hover:bg-[#050505] transition-colors duration-500">
|
||||
{/* 2. MARKET */}
|
||||
<div className="group relative bg-[#030303] p-10 lg:p-14 hover:bg-[#050505] transition-colors duration-500">
|
||||
<div className="absolute top-0 right-0 p-6 opacity-0 group-hover:opacity-100 transition-opacity duration-500">
|
||||
<ArrowUpRight className="w-6 h-6 text-white/20" />
|
||||
</div>
|
||||
@ -411,7 +368,7 @@ export default function HomePage() {
|
||||
</div>
|
||||
<h3 className="text-3xl text-white font-display mb-6">Market</h3>
|
||||
<p className="text-white/50 leading-relaxed text-lg font-light mb-12">
|
||||
"Secure the Asset." Direct access to liquidity. A verified marketplace where assets move instantly, securely, and with 0% commission fees.
|
||||
"Secure the Asset." Direct access to liquidity. A verified exchange where assets move instantly, securely, and with 0% commission fees.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@ -434,8 +391,8 @@ export default function HomePage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 3. YIELD (Monetize) */}
|
||||
<div className="group relative bg-[#030303] p-12 lg:p-16 hover:bg-[#050505] transition-colors duration-500">
|
||||
{/* 3. YIELD */}
|
||||
<div className="group relative bg-[#030303] p-10 lg:p-14 hover:bg-[#050505] transition-colors duration-500">
|
||||
<div className="absolute top-0 right-0 p-6 opacity-0 group-hover:opacity-100 transition-opacity duration-500">
|
||||
<ArrowUpRight className="w-6 h-6 text-white/20" />
|
||||
</div>
|
||||
@ -447,7 +404,7 @@ export default function HomePage() {
|
||||
</div>
|
||||
<h3 className="text-3xl text-white font-display mb-6">Yield</h3>
|
||||
<p className="text-white/50 leading-relaxed text-lg font-light mb-12">
|
||||
"Let the Asset Work." Our "Intent Routing" engine transforms idle domains into active revenue generators via automated traffic monetization.
|
||||
"Deploy the Asset." Our "Intent Routing" engine transforms idle domains into active revenue generators via automated traffic monetization.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@ -474,72 +431,77 @@ export default function HomePage() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* DEEP DIVE: YIELD - The "Unicorn" Feature */}
|
||||
{/* DEEP DIVE: YIELD */}
|
||||
<section className="relative py-32 px-4 sm:px-6 border-b border-white/[0.05] bg-[#050505] overflow-hidden">
|
||||
<div className="absolute inset-0 bg-accent/[0.02]" />
|
||||
<div className="max-w-[1200px] mx-auto relative z-10">
|
||||
<div className="mb-16 text-center">
|
||||
<div className="mb-20 text-center">
|
||||
<span className="text-accent font-mono text-xs uppercase tracking-[0.2em] mb-4 block">The Endgame</span>
|
||||
<h2 className="font-display text-4xl sm:text-5xl text-white mb-6">Intent Routing™</h2>
|
||||
<p className="text-white/50 max-w-2xl mx-auto text-lg font-light">
|
||||
Domains usually park for pennies. We route them for dollars. <br/>
|
||||
We analyze the intent behind a domain (e.g. "kredit.ch") and route traffic directly to high-paying affiliates.
|
||||
<p className="text-white/50 max-w-2xl mx-auto text-lg font-light leading-relaxed">
|
||||
We don't build websites. We build signposts. <br/>
|
||||
Our engine detects user intent (e.g. "kredit.ch" = Loan Search) and routes traffic directly to high-paying partners.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-8">
|
||||
<div className="bg-[#020202] border border-white/10 p-8 relative group hover:border-accent/30 transition-colors">
|
||||
<div className="w-12 h-12 bg-white/5 flex items-center justify-center mb-6 text-white group-hover:text-accent group-hover:bg-accent/10 transition-all">
|
||||
<Network className="w-6 h-6" />
|
||||
{/* Step 1 */}
|
||||
<div className="bg-[#020202] border border-white/10 p-10 relative group hover:border-accent/30 transition-colors">
|
||||
<div className="w-14 h-14 bg-white/5 flex items-center justify-center mb-8 text-white group-hover:text-accent group-hover:bg-accent/10 transition-all">
|
||||
<Network className="w-7 h-7" />
|
||||
</div>
|
||||
<h3 className="text-white font-bold text-xl mb-2">1. Connect</h3>
|
||||
<p className="text-white/40 text-sm font-mono">User points NS records to Pounce. No coding required.</p>
|
||||
<h3 className="text-white font-bold text-xl mb-3">1. Connect</h3>
|
||||
<p className="text-white/40 text-sm font-mono leading-relaxed">Point your nameservers to `ns.pounce.io`. The system takes over instantly.</p>
|
||||
</div>
|
||||
<div className="bg-[#020202] border border-white/10 p-8 relative group hover:border-accent/30 transition-colors">
|
||||
<div className="w-12 h-12 bg-white/5 flex items-center justify-center mb-6 text-white group-hover:text-accent group-hover:bg-accent/10 transition-all">
|
||||
<Cpu className="w-6 h-6" />
|
||||
|
||||
{/* Step 2 */}
|
||||
<div className="bg-[#020202] border border-white/10 p-10 relative group hover:border-accent/30 transition-colors">
|
||||
<div className="w-14 h-14 bg-white/5 flex items-center justify-center mb-8 text-white group-hover:text-accent group-hover:bg-accent/10 transition-all">
|
||||
<Cpu className="w-7 h-7" />
|
||||
</div>
|
||||
<h3 className="text-white font-bold text-xl mb-2">2. Analyze</h3>
|
||||
<p className="text-white/40 text-sm font-mono">AI detects intent. "zahnarzt-zh" -> Intent: "Dentist Booking".</p>
|
||||
<h3 className="text-white font-bold text-xl mb-3">2. Analyze</h3>
|
||||
<p className="text-white/40 text-sm font-mono leading-relaxed">We scan the semantic intent. `zahnarzt-zh.ch` is identified as "Medical Booking Lead".</p>
|
||||
</div>
|
||||
<div className="bg-[#020202] border border-white/10 p-8 relative group hover:border-accent/30 transition-colors">
|
||||
<div className="w-12 h-12 bg-white/5 flex items-center justify-center mb-6 text-white group-hover:text-accent group-hover:bg-accent/10 transition-all">
|
||||
<Share2 className="w-6 h-6" />
|
||||
|
||||
{/* Step 3 */}
|
||||
<div className="bg-[#020202] border border-white/10 p-10 relative group hover:border-accent/30 transition-colors">
|
||||
<div className="w-14 h-14 bg-white/5 flex items-center justify-center mb-8 text-white group-hover:text-accent group-hover:bg-accent/10 transition-all">
|
||||
<Share2 className="w-7 h-7" />
|
||||
</div>
|
||||
<h3 className="text-white font-bold text-xl mb-2">3. Route</h3>
|
||||
<p className="text-white/40 text-sm font-mono">Traffic is sent to partners (e.g. Doctolib). You get paid per lead.</p>
|
||||
<h3 className="text-white font-bold text-xl mb-3">3. Route</h3>
|
||||
<p className="text-white/40 text-sm font-mono leading-relaxed">Traffic is routed to vertical partners (e.g. Doctolib, Comparis). You earn per qualified lead.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* DEEP DIVE: MARKET - The "Velvet Rope" */}
|
||||
{/* DEEP DIVE: MARKET */}
|
||||
<section className="relative py-32 px-4 sm:px-6 bg-[#020202]">
|
||||
<div className="max-w-[1200px] mx-auto grid lg:grid-cols-2 gap-20 items-center">
|
||||
<div className="order-2 lg:order-1 relative">
|
||||
<div className="border border-white/10 bg-[#050505] p-2 shadow-2xl rotate-1 hover:rotate-0 transition-transform duration-500">
|
||||
<div className="bg-[#020202] p-6">
|
||||
<div className="flex items-center gap-4 border-b border-white/10 pb-4 mb-4">
|
||||
<div className="w-2 h-2 rounded-full bg-accent" />
|
||||
<span className="font-mono text-sm text-white">zurich-immo.ch</span>
|
||||
<span className="ml-auto text-accent font-bold">$950</span>
|
||||
<div className="bg-[#020202] p-8">
|
||||
<div className="flex items-center gap-4 border-b border-white/10 pb-6 mb-6">
|
||||
<div className="w-2 h-2 rounded-full bg-accent animate-pulse" />
|
||||
<span className="font-mono text-base text-white">zurich-immo.ch</span>
|
||||
<span className="ml-auto text-accent font-bold text-lg">$950</span>
|
||||
</div>
|
||||
<div className="space-y-3 font-mono text-xs text-white/50">
|
||||
<div className="flex justify-between">
|
||||
<div className="space-y-4 font-mono text-xs text-white/50">
|
||||
<div className="flex justify-between items-center">
|
||||
<span>Source</span>
|
||||
<span className="text-white flex items-center gap-2"><div className="w-1.5 h-1.5 bg-accent rounded-full"/> Pounce Direct</span>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<div className="flex justify-between items-center">
|
||||
<span>Seller Verified</span>
|
||||
<span className="text-accent">Yes (DNS Check)</span>
|
||||
<span className="text-accent flex items-center gap-2"><Check className="w-3 h-3" /> DNS Check Passed</span>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<div className="flex justify-between items-center">
|
||||
<span>Commission</span>
|
||||
<span className="text-white">0%</span>
|
||||
<span className="text-white bg-white/10 px-2 py-0.5 rounded-none">0%</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 pt-4 border-t border-white/10">
|
||||
<button className="w-full py-3 bg-white/5 text-white uppercase font-bold text-xs tracking-widest hover:bg-white hover:text-black transition-colors">
|
||||
<div className="mt-8 pt-6 border-t border-white/10">
|
||||
<button className="w-full py-4 bg-white/5 text-white uppercase font-bold text-xs tracking-[0.2em] hover:bg-white hover:text-black transition-colors flex items-center justify-center gap-2">
|
||||
Contact Seller
|
||||
</button>
|
||||
</div>
|
||||
@ -549,30 +511,30 @@ export default function HomePage() {
|
||||
<div className="order-1 lg:order-2">
|
||||
<span className="text-accent font-mono text-xs uppercase tracking-[0.2em] mb-4 block">Exclusive Exchange</span>
|
||||
<h2 className="font-display text-4xl text-white mb-6">The Velvet Rope Strategy.</h2>
|
||||
<p className="text-white/50 text-lg leading-relaxed mb-8">
|
||||
<p className="text-white/50 text-lg leading-relaxed mb-10">
|
||||
We don't run an open flea market. We run an exclusive club.
|
||||
Buying is open to everyone, but selling is reserved for members.
|
||||
Buying is open to everyone, but selling is reserved for verified members.
|
||||
</p>
|
||||
<ul className="space-y-4">
|
||||
<li className="flex gap-4">
|
||||
<ul className="space-y-6">
|
||||
<li className="flex gap-5">
|
||||
<Shield className="w-6 h-6 text-accent shrink-0" />
|
||||
<div>
|
||||
<h4 className="text-white font-bold mb-1">Zero Spam</h4>
|
||||
<p className="text-white/40 text-sm">Gatekeeper technology filters 99% of junk domains automatically.</p>
|
||||
<h4 className="text-white font-bold mb-1">Zero Noise</h4>
|
||||
<p className="text-white/40 text-sm leading-relaxed">Gatekeeper technology filters 99% of junk domains automatically.</p>
|
||||
</div>
|
||||
</li>
|
||||
<li className="flex gap-4">
|
||||
<li className="flex gap-5">
|
||||
<Key className="w-6 h-6 text-accent shrink-0" />
|
||||
<div>
|
||||
<h4 className="text-white font-bold mb-1">Verified Owners</h4>
|
||||
<p className="text-white/40 text-sm">Sellers must verify ownership via DNS before listing.</p>
|
||||
<p className="text-white/40 text-sm leading-relaxed">Sellers must verify ownership via DNS before listing. No fakes.</p>
|
||||
</div>
|
||||
</li>
|
||||
<li className="flex gap-4">
|
||||
<li className="flex gap-5">
|
||||
<Zap className="w-6 h-6 text-accent shrink-0" />
|
||||
<div>
|
||||
<h4 className="text-white font-bold mb-1">0% Commission</h4>
|
||||
<p className="text-white/40 text-sm">Members keep 100% of the sale price. Direct settlement.</p>
|
||||
<p className="text-white/40 text-sm leading-relaxed">Members keep 100% of the sale price. Direct settlement.</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@ -587,46 +549,46 @@ export default function HomePage() {
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-8 text-left">
|
||||
{/* Scout */}
|
||||
<div className="p-8 border border-white/10 bg-[#020202] opacity-60 hover:opacity-100 transition-opacity">
|
||||
<div className="p-10 border border-white/10 bg-[#020202] opacity-60 hover:opacity-100 transition-opacity flex flex-col">
|
||||
<h3 className="text-xl font-display text-white mb-2">Scout</h3>
|
||||
<div className="text-3xl font-mono text-white mb-6">$0<span className="text-sm text-white/30">/mo</span></div>
|
||||
<ul className="space-y-3 text-sm text-white/50 font-mono mb-8">
|
||||
<li className="flex gap-2"><span>•</span> Market Overview</li>
|
||||
<li className="flex gap-2"><span>•</span> Basic Search</li>
|
||||
<li className="flex gap-2"><span>•</span> 5 Watchlist Items</li>
|
||||
<div className="text-4xl font-mono text-white mb-8">$0<span className="text-sm text-white/30">/mo</span></div>
|
||||
<ul className="space-y-4 text-sm text-white/50 font-mono mb-10 flex-1">
|
||||
<li className="flex gap-3"><span>•</span> Recon Overview</li>
|
||||
<li className="flex gap-3"><span>•</span> Basic Scan</li>
|
||||
<li className="flex gap-3"><span>•</span> 5 Targets</li>
|
||||
</ul>
|
||||
<Link href="/register" className="block w-full py-3 text-center border border-white/20 text-white uppercase text-xs font-bold tracking-widest hover:bg-white hover:text-black transition-colors">
|
||||
Start Free
|
||||
<Link href="/register" className="block w-full py-4 text-center border border-white/20 text-white uppercase text-xs font-bold tracking-widest hover:bg-white hover:text-black transition-colors">
|
||||
Join the Hunt
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Trader - Highlight */}
|
||||
<div className="p-8 border border-accent bg-[#050505] relative transform md:-translate-y-4">
|
||||
<div className="absolute top-0 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-accent text-black px-3 py-1 text-[10px] font-bold uppercase tracking-widest">Recommended</div>
|
||||
<div className="p-10 border border-accent bg-[#050505] relative transform md:-translate-y-4 flex flex-col shadow-[0_0_50px_-20px_rgba(16,185,129,0.2)]">
|
||||
<div className="absolute top-0 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-accent text-black px-4 py-1.5 text-[10px] font-bold uppercase tracking-widest">Recommended</div>
|
||||
<h3 className="text-xl font-display text-white mb-2">Trader</h3>
|
||||
<div className="text-3xl font-mono text-accent mb-6">$9<span className="text-sm text-white/30">/mo</span></div>
|
||||
<ul className="space-y-3 text-sm text-white/80 font-mono mb-8">
|
||||
<li className="flex gap-2"><Check className="w-4 h-4 text-accent"/> Clean Feed (No Spam)</li>
|
||||
<li className="flex gap-2"><Check className="w-4 h-4 text-accent"/> Renewal Price Intel</li>
|
||||
<li className="flex gap-2"><Check className="w-4 h-4 text-accent"/> Sell Domains (0% Fee)</li>
|
||||
<li className="flex gap-2"><Check className="w-4 h-4 text-accent"/> 50 Watchlist Items</li>
|
||||
<div className="text-4xl font-mono text-accent mb-8">$9<span className="text-sm text-white/30">/mo</span></div>
|
||||
<ul className="space-y-4 text-sm text-white/80 font-mono mb-10 flex-1">
|
||||
<li className="flex gap-3"><Check className="w-4 h-4 text-accent"/> Clean Feed (No Noise)</li>
|
||||
<li className="flex gap-3"><Check className="w-4 h-4 text-accent"/> Renewal Intel</li>
|
||||
<li className="flex gap-3"><Check className="w-4 h-4 text-accent"/> Liquidate (0% Fee)</li>
|
||||
<li className="flex gap-3"><Check className="w-4 h-4 text-accent"/> 50 Targets</li>
|
||||
</ul>
|
||||
<Link href="/pricing" className="block w-full py-3 text-center bg-accent text-black uppercase text-xs font-bold tracking-widest hover:bg-white transition-colors">
|
||||
Upgrade
|
||||
<Link href="/pricing" className="block w-full py-4 text-center bg-accent text-black uppercase text-xs font-bold tracking-widest hover:bg-white transition-colors">
|
||||
Gear Up
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Tycoon */}
|
||||
<div className="p-8 border border-white/10 bg-[#020202] hover:border-white/30 transition-colors">
|
||||
<div className="p-10 border border-white/10 bg-[#020202] hover:border-white/30 transition-colors flex flex-col">
|
||||
<h3 className="text-xl font-display text-white mb-2">Tycoon</h3>
|
||||
<div className="text-3xl font-mono text-white mb-6">$29<span className="text-sm text-white/30">/mo</span></div>
|
||||
<ul className="space-y-3 text-sm text-white/50 font-mono mb-8">
|
||||
<li className="flex gap-2"><Check className="w-4 h-4 text-white"/> Full Portfolio Monitor</li>
|
||||
<li className="flex gap-2"><Check className="w-4 h-4 text-white"/> Priority Alerts (10m)</li>
|
||||
<li className="flex gap-2"><Check className="w-4 h-4 text-white"/> 500 Watchlist Items</li>
|
||||
<li className="flex gap-2"><Check className="w-4 h-4 text-white"/> Featured Listings</li>
|
||||
<div className="text-4xl font-mono text-white mb-8">$29<span className="text-sm text-white/30">/mo</span></div>
|
||||
<ul className="space-y-4 text-sm text-white/50 font-mono mb-10 flex-1">
|
||||
<li className="flex gap-3"><Check className="w-4 h-4 text-white"/> Full Portfolio Monitor</li>
|
||||
<li className="flex gap-3"><Check className="w-4 h-4 text-white"/> First Strike Alerts (10m)</li>
|
||||
<li className="flex gap-3"><Check className="w-4 h-4 text-white"/> 500 Targets</li>
|
||||
<li className="flex gap-3"><Check className="w-4 h-4 text-white"/> Featured Listings</li>
|
||||
</ul>
|
||||
<Link href="/pricing" className="block w-full py-3 text-center border border-white/20 text-white uppercase text-xs font-bold tracking-widest hover:bg-white hover:text-black transition-colors">
|
||||
<Link href="/pricing" className="block w-full py-4 text-center border border-white/20 text-white uppercase text-xs font-bold tracking-widest hover:bg-white hover:text-black transition-colors">
|
||||
Go Professional
|
||||
</Link>
|
||||
</div>
|
||||
@ -641,11 +603,11 @@ export default function HomePage() {
|
||||
|
||||
<div className="flex justify-between items-end mb-12">
|
||||
<div>
|
||||
<h2 className="font-display text-3xl text-white mb-2">Market Activity</h2>
|
||||
<p className="text-accent/60 font-mono text-sm">LIVE_FEED_V2.0 // ENCRYPTED</p>
|
||||
<h2 className="font-display text-3xl text-white mb-2">Live Ops</h2>
|
||||
<p className="text-accent/60 font-mono text-sm">FEED_V2.0 // ENCRYPTED</p>
|
||||
</div>
|
||||
<Link href="/market" className="text-xs font-mono uppercase tracking-widest text-white/40 hover:text-white transition-colors flex items-center gap-2">
|
||||
View All Markets <ArrowRight className="w-3 h-3" />
|
||||
<Link href="/acquire" className="text-xs font-mono uppercase tracking-widest text-white/40 hover:text-white transition-colors flex items-center gap-2">
|
||||
Recon All Markets <ArrowRight className="w-3 h-3" />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@ -656,8 +618,8 @@ export default function HomePage() {
|
||||
<div className="grid grid-cols-12 gap-4 px-6 py-4 border-b border-white/[0.05] bg-white/[0.01] text-[10px] font-mono text-white/30 uppercase tracking-widest">
|
||||
<div className="col-span-5">Asset Identifier</div>
|
||||
<div className="col-span-2 text-right">Valuation</div>
|
||||
<div className="col-span-2 text-right">Current Bid</div>
|
||||
<div className="col-span-3 text-right">Time to Expiry</div>
|
||||
<div className="col-span-2 text-right">Strike Price</div>
|
||||
<div className="col-span-3 text-right">Window Closes</div>
|
||||
</div>
|
||||
|
||||
{/* Table Rows */}
|
||||
@ -680,9 +642,10 @@ export default function HomePage() {
|
||||
<Link
|
||||
href="/register"
|
||||
className="group flex items-center gap-4 px-8 py-4 border border-accent/20 bg-accent/10 hover:bg-accent hover:border-accent hover:text-black text-white transition-all duration-500 backdrop-blur-md"
|
||||
style={{ clipPath: 'polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px)' }}
|
||||
>
|
||||
<Lock className="w-3 h-3" />
|
||||
<span className="text-xs font-bold uppercase tracking-[0.2em]">Access Full Terminal</span>
|
||||
<span className="text-xs font-bold uppercase tracking-[0.2em]">Enter HQ</span>
|
||||
<ArrowRight className="w-3 h-3 group-hover:translate-x-1 transition-transform" />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@ -6,7 +6,7 @@ import { Header } from '@/components/Header'
|
||||
import { Footer } from '@/components/Footer'
|
||||
import { useStore } from '@/lib/store'
|
||||
import { api } from '@/lib/api'
|
||||
import { Check, ArrowRight, Zap, TrendingUp, Crown, Loader2, Clock, X, AlertCircle } from 'lucide-react'
|
||||
import { Check, ArrowRight, Zap, TrendingUp, Crown, Loader2, Clock, X, AlertCircle, Shield } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import clsx from 'clsx'
|
||||
|
||||
@ -79,12 +79,12 @@ const tiers = [
|
||||
]
|
||||
|
||||
const comparisonFeatures = [
|
||||
{ name: 'Market Feed', scout: '🌪️ Raw', trader: '✨ Curated', tycoon: '✨ Priority' },
|
||||
{ name: 'Alert Speed', scout: '🐢 Daily', trader: '🐇 Hourly', tycoon: '⚡ 10 min' },
|
||||
{ name: 'Market Feed', scout: 'Raw', trader: 'Curated', tycoon: 'Priority' },
|
||||
{ name: 'Alert Speed', scout: 'Daily', trader: 'Hourly', tycoon: '10 min' },
|
||||
{ name: 'Watchlist', scout: '5 Domains', trader: '50 Domains', tycoon: '500 Domains' },
|
||||
{ name: 'Marketplace', scout: 'Buy Only', trader: 'Sell (0% Fee)', tycoon: 'Sell + Featured' },
|
||||
{ name: 'TLD Intel', scout: 'Public Trends', trader: 'Renewal Prices', tycoon: 'Full History' },
|
||||
{ name: 'Valuation', scout: '❌ Locked', trader: '✅ Pounce Score', tycoon: '✅ Score + SEO' },
|
||||
{ name: 'Valuation', scout: 'Locked', trader: 'Pounce Score', tycoon: 'Score + SEO' },
|
||||
{ name: 'Sniper Alerts', scout: '—', trader: '5', tycoon: 'Unlimited' },
|
||||
{ name: 'Portfolio', scout: '—', trader: '25 Domains', tycoon: 'Unlimited' },
|
||||
]
|
||||
@ -159,18 +159,18 @@ export default function PricingPage() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background relative overflow-hidden">
|
||||
<div className="min-h-screen bg-[#020202] text-white relative overflow-x-hidden selection:bg-accent/30 selection:text-white">
|
||||
{/* Background Effects - matching landing page */}
|
||||
<div className="fixed inset-0 pointer-events-none">
|
||||
<div className="absolute top-[-20%] left-1/2 -translate-x-1/2 w-[1200px] h-[800px] bg-accent/[0.03] rounded-full blur-[120px]" />
|
||||
<div className="absolute bottom-[-10%] right-[-10%] w-[600px] h-[600px] bg-accent/[0.02] rounded-full blur-[100px]" />
|
||||
<div className="fixed inset-0 pointer-events-none z-0">
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.03] mix-blend-overlay" />
|
||||
<div
|
||||
className="absolute inset-0 opacity-[0.015]"
|
||||
className="absolute inset-0 opacity-[0.03]"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(rgba(255,255,255,.1) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,.1) 1px, transparent 1px)`,
|
||||
backgroundSize: '64px 64px',
|
||||
backgroundImage: `linear-gradient(rgba(255,255,255,0.3) 0.5px, transparent 0.5px), linear-gradient(90deg, rgba(255,255,255,0.3) 0.5px, transparent 0.5px)`,
|
||||
backgroundSize: '160px 160px',
|
||||
}}
|
||||
/>
|
||||
<div className="absolute top-[-20%] left-1/2 -translate-x-1/2 w-[1200px] h-[800px] bg-accent/[0.02] rounded-full blur-[150px]" />
|
||||
</div>
|
||||
|
||||
<Header />
|
||||
@ -179,18 +179,18 @@ export default function PricingPage() {
|
||||
<div className="max-w-6xl mx-auto">
|
||||
{/* Cancelled Banner */}
|
||||
{showCancelledBanner && (
|
||||
<div className="mb-8 p-4 bg-amber-500/10 border border-amber-500/20 rounded-xl flex items-start gap-3 animate-fade-in">
|
||||
<AlertCircle className="w-5 h-5 text-amber-400 shrink-0 mt-0.5" />
|
||||
<div className="flex-1">
|
||||
<p className="font-medium text-amber-400">Checkout cancelled</p>
|
||||
<p className="text-sm text-foreground-muted mt-1">
|
||||
No worries! Your card was not charged. You can try again whenever you're ready,
|
||||
or continue with the free Scout plan.
|
||||
<div className="mb-8 p-4 bg-amber-500/10 border border-amber-500/20 flex items-start gap-3 animate-fade-in relative overflow-hidden">
|
||||
<div className="absolute inset-0 bg-amber-500/5 animate-pulse" />
|
||||
<AlertCircle className="w-5 h-5 text-amber-400 shrink-0 mt-0.5 relative z-10" />
|
||||
<div className="flex-1 relative z-10">
|
||||
<p className="font-medium text-amber-400 font-mono text-sm uppercase tracking-wider">Transaction Cancelled</p>
|
||||
<p className="text-sm text-white/60 mt-1">
|
||||
Operation aborted. No charges applied. Resume when ready.
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setShowCancelledBanner(false)}
|
||||
className="p-1 text-foreground-muted hover:text-foreground transition-colors"
|
||||
className="p-1 text-white/40 hover:text-white transition-colors relative z-10"
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
</button>
|
||||
@ -199,36 +199,44 @@ export default function PricingPage() {
|
||||
|
||||
{/* Hero */}
|
||||
<div className="text-center mb-16 sm:mb-20 animate-fade-in">
|
||||
<span className="text-sm font-semibold text-accent uppercase tracking-wider">Pricing</span>
|
||||
<h1 className="mt-4 font-display text-[2.5rem] sm:text-[3.5rem] md:text-[4.5rem] lg:text-[5rem] leading-[0.95] tracking-[-0.03em] text-foreground">
|
||||
<span className="text-accent font-mono text-xs uppercase tracking-[0.2em] mb-4 block flex items-center justify-center gap-2">
|
||||
<div className="w-1.5 h-1.5 bg-accent animate-pulse" />
|
||||
Clearance Levels
|
||||
</span>
|
||||
<h1 className="font-display text-[3.5rem] sm:text-[5rem] md:text-[6rem] lg:text-[7rem] leading-[0.9] tracking-[-0.04em] text-white">
|
||||
Pick your weapon.
|
||||
</h1>
|
||||
<p className="mt-5 text-lg sm:text-xl text-foreground-muted max-w-xl mx-auto">
|
||||
<p className="mt-8 text-lg sm:text-xl text-white/50 max-w-xl mx-auto font-light leading-relaxed">
|
||||
Start free. Scale when you're ready. All plans include core features.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Pricing Cards */}
|
||||
<div className="grid md:grid-cols-3 gap-6 mb-20 animate-slide-up items-stretch">
|
||||
{/* Pricing Cards - AWARD WINNING STYLE */}
|
||||
<div className="grid md:grid-cols-3 gap-8 mb-24 animate-slide-up items-stretch">
|
||||
{tiers.map((tier, index) => (
|
||||
<div
|
||||
key={tier.id}
|
||||
className={clsx(
|
||||
"group relative p-6 sm:p-8 rounded-2xl border transition-all duration-500 flex flex-col",
|
||||
"group relative p-8 flex flex-col transition-all duration-500",
|
||||
tier.highlighted
|
||||
? "bg-background-secondary border-accent/30 shadow-lg shadow-accent/5"
|
||||
: "bg-background-secondary/50 border-border hover:border-accent/20 hover:bg-background-secondary"
|
||||
? "bg-[#050505] border border-accent/50 shadow-[0_0_50px_-20px_rgba(16,185,129,0.2)] z-10 transform md:-translate-y-4"
|
||||
: "bg-[#030303] border border-white/10 hover:border-white/20 hover:bg-[#050505]"
|
||||
)}
|
||||
style={{ animationDelay: `${index * 100}ms` }}
|
||||
>
|
||||
{/* Hover glow for non-highlighted */}
|
||||
{!tier.highlighted && (
|
||||
<div className="absolute inset-0 rounded-2xl bg-accent/5 opacity-0 group-hover:opacity-100 transition-opacity" />
|
||||
{/* Tech Corners for Highlighted */}
|
||||
{tier.highlighted && (
|
||||
<>
|
||||
<div className="absolute -top-px -left-px w-4 h-4 border-t border-l border-accent" />
|
||||
<div className="absolute -top-px -right-px w-4 h-4 border-t border-r border-accent" />
|
||||
<div className="absolute -bottom-px -left-px w-4 h-4 border-b border-l border-accent" />
|
||||
<div className="absolute -bottom-px -right-px w-4 h-4 border-b border-r border-accent" />
|
||||
</>
|
||||
)}
|
||||
|
||||
{tier.badge && (
|
||||
<div className="absolute -top-3 left-1/2 -translate-x-1/2 z-10">
|
||||
<span className="px-3 py-1 bg-accent text-background text-ui-xs font-medium rounded-full whitespace-nowrap">
|
||||
<div className="absolute top-0 left-1/2 -translate-x-1/2 -translate-y-1/2 z-20">
|
||||
<span className="px-4 py-1.5 bg-accent text-black text-[10px] font-bold uppercase tracking-widest whitespace-nowrap shadow-lg shadow-accent/20">
|
||||
{tier.badge}
|
||||
</span>
|
||||
</div>
|
||||
@ -236,53 +244,47 @@ export default function PricingPage() {
|
||||
|
||||
<div className="relative flex-1 flex flex-col">
|
||||
{/* Header */}
|
||||
<div className="mb-6">
|
||||
<div className="flex items-center gap-3 mb-3">
|
||||
<div className={clsx(
|
||||
"w-12 h-12 rounded-2xl flex items-center justify-center border transition-all duration-500",
|
||||
tier.highlighted
|
||||
? "bg-accent/10 border-accent/30"
|
||||
: "bg-foreground/5 border-border group-hover:border-accent/30 group-hover:bg-accent/5"
|
||||
)}>
|
||||
<tier.icon className={clsx(
|
||||
"w-5 h-5 transition-colors duration-500",
|
||||
tier.highlighted ? "text-accent" : "text-foreground-muted group-hover:text-accent"
|
||||
)} />
|
||||
</div>
|
||||
<h3 className="text-xl font-semibold text-foreground">{tier.name}</h3>
|
||||
</div>
|
||||
<p className="text-body-sm text-foreground-muted mb-4">{tier.description}</p>
|
||||
<div className="flex items-baseline gap-1">
|
||||
<div className="mb-8 text-center pb-8 border-b border-white/10">
|
||||
<h3 className="text-2xl font-display text-white mb-4">{tier.name}</h3>
|
||||
<div className="flex items-baseline justify-center gap-1 mb-4">
|
||||
{tier.price === '0' ? (
|
||||
<span className="text-5xl font-display text-foreground">Free</span>
|
||||
<span className="text-5xl font-mono text-white tracking-tight">Free</span>
|
||||
) : (
|
||||
<>
|
||||
<span className="text-5xl font-display text-foreground">${tier.price}</span>
|
||||
<span className="text-body text-foreground-muted">{tier.period}</span>
|
||||
<span className="text-5xl font-mono text-white tracking-tight">${tier.price}</span>
|
||||
<span className="text-sm font-mono text-white/40">{tier.period}</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-sm text-white/50 font-mono">{tier.description}</p>
|
||||
</div>
|
||||
|
||||
{/* Features - flex-1 to push button to bottom */}
|
||||
<ul className="space-y-3 mb-8 flex-1">
|
||||
{/* Features */}
|
||||
<ul className="space-y-4 mb-10 flex-1">
|
||||
{tier.features.map((feature) => (
|
||||
<li key={feature.text} className="flex items-start gap-3">
|
||||
{feature.available ? (
|
||||
<Check className={clsx(
|
||||
"w-4 h-4 mt-0.5 shrink-0",
|
||||
feature.highlight ? "text-accent" : "text-foreground-muted"
|
||||
)} strokeWidth={2.5} />
|
||||
<div className={clsx(
|
||||
"w-5 h-5 flex items-center justify-center shrink-0 border",
|
||||
feature.highlight ? "border-accent bg-accent/10 text-accent" : "border-white/20 bg-white/5 text-white/60"
|
||||
)}>
|
||||
<Check className="w-3 h-3" strokeWidth={3} />
|
||||
</div>
|
||||
) : (
|
||||
<X className="w-4 h-4 mt-0.5 shrink-0 text-foreground-subtle" strokeWidth={2} />
|
||||
<div className="w-5 h-5 flex items-center justify-center shrink-0 border border-white/5 bg-transparent text-white/10">
|
||||
<X className="w-3 h-3" strokeWidth={3} />
|
||||
</div>
|
||||
)}
|
||||
<span className={clsx(
|
||||
"text-body-sm",
|
||||
feature.available ? "text-foreground" : "text-foreground-subtle line-through"
|
||||
"text-sm font-mono leading-tight pt-0.5",
|
||||
feature.available ? "text-white/80" : "text-white/20 line-through decoration-white/10"
|
||||
)}>
|
||||
{feature.text}
|
||||
{feature.sublabel && (
|
||||
<span className="ml-1.5 text-xs text-accent font-medium">
|
||||
<span className={clsx(
|
||||
"ml-2 text-[10px] uppercase tracking-wider px-1.5 py-0.5 border",
|
||||
tier.highlighted ? "text-accent border-accent/30 bg-accent/5" : "text-white/40 border-white/10 bg-white/5"
|
||||
)}>
|
||||
{feature.sublabel}
|
||||
</span>
|
||||
)}
|
||||
@ -291,16 +293,17 @@ export default function PricingPage() {
|
||||
))}
|
||||
</ul>
|
||||
|
||||
{/* CTA - always at bottom */}
|
||||
{/* CTA */}
|
||||
<button
|
||||
onClick={() => handleSelectPlan(tier.id, tier.isPaid)}
|
||||
disabled={loadingPlan === tier.id}
|
||||
className={clsx(
|
||||
"w-full flex items-center justify-center gap-2 py-4 rounded-xl text-ui font-medium transition-all duration-300 mt-auto",
|
||||
"w-full flex items-center justify-center gap-3 py-4 text-xs font-bold uppercase tracking-[0.2em] transition-all duration-300 mt-auto",
|
||||
tier.highlighted
|
||||
? "bg-accent text-background hover:bg-accent-hover shadow-[0_0_20px_rgba(16,185,129,0.15)]"
|
||||
: "bg-foreground text-background hover:bg-foreground/90"
|
||||
? "bg-accent text-black hover:bg-white hover:text-black shadow-[0_0_20px_rgba(16,185,129,0.2)]"
|
||||
: "border border-white/20 text-white hover:bg-white hover:text-black"
|
||||
)}
|
||||
style={{ clipPath: 'polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px)' }}
|
||||
>
|
||||
{loadingPlan === tier.id ? (
|
||||
<Loader2 className="w-4 h-4 animate-spin" />
|
||||
@ -316,37 +319,33 @@ export default function PricingPage() {
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Comparison Table */}
|
||||
<div className="mb-20">
|
||||
<h2 className="text-heading-md text-foreground text-center mb-8">Compare Plans</h2>
|
||||
{/* Comparison Table - TECH STYLE */}
|
||||
<div className="mb-24 border border-white/10 bg-[#050505]">
|
||||
<div className="px-8 py-6 border-b border-white/10 bg-white/[0.02]">
|
||||
<h2 className="text-xl font-display text-white">Spec Sheet</h2>
|
||||
</div>
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full">
|
||||
<thead>
|
||||
<tr className="border-b border-border">
|
||||
<th className="text-left py-4 px-4 text-body-sm font-medium text-foreground-muted">Feature</th>
|
||||
<th className="text-center py-4 px-4 text-body-sm font-medium text-foreground-muted">Scout</th>
|
||||
<th className="text-center py-4 px-4 text-body-sm font-medium text-accent">Trader</th>
|
||||
<th className="text-center py-4 px-4 text-body-sm font-medium text-foreground-muted">Tycoon</th>
|
||||
<tr className="border-b border-white/10 bg-[#0A0A0A]">
|
||||
<th className="text-left py-5 px-8 text-xs font-bold uppercase tracking-widest text-white/40 font-mono">Feature Module</th>
|
||||
<th className="text-center py-5 px-8 text-xs font-bold uppercase tracking-widest text-white/40 font-mono">Scout</th>
|
||||
<th className="text-center py-5 px-8 text-xs font-bold uppercase tracking-widest text-accent font-mono">Trader</th>
|
||||
<th className="text-center py-5 px-8 text-xs font-bold uppercase tracking-widest text-white/40 font-mono">Tycoon</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tbody className="divide-y divide-white/5">
|
||||
{comparisonFeatures.map((feature) => (
|
||||
<tr key={feature.name} className="border-b border-border/50">
|
||||
<td className="py-4 px-4 text-body-sm text-foreground">{feature.name}</td>
|
||||
<td className="py-4 px-4 text-center text-body-sm text-foreground-muted">
|
||||
{feature.scout === 'check' ? (
|
||||
<Check className="w-5 h-5 text-accent mx-auto" strokeWidth={2.5} />
|
||||
) : feature.scout}
|
||||
<tr key={feature.name} className="hover:bg-white/[0.02] transition-colors">
|
||||
<td className="py-5 px-8 text-sm text-white font-mono">{feature.name}</td>
|
||||
<td className="py-5 px-8 text-center text-sm text-white/40 font-mono">
|
||||
{feature.scout}
|
||||
</td>
|
||||
<td className="py-4 px-4 text-center text-body-sm text-foreground">
|
||||
{feature.trader === 'check' ? (
|
||||
<Check className="w-5 h-5 text-accent mx-auto" strokeWidth={2.5} />
|
||||
) : feature.trader}
|
||||
<td className="py-5 px-8 text-center text-sm text-white font-mono bg-accent/[0.02]">
|
||||
{feature.trader}
|
||||
</td>
|
||||
<td className="py-4 px-4 text-center text-body-sm text-foreground">
|
||||
{feature.tycoon === 'check' ? (
|
||||
<Check className="w-5 h-5 text-accent mx-auto" strokeWidth={2.5} />
|
||||
) : feature.tycoon}
|
||||
<td className="py-5 px-8 text-center text-sm text-white/40 font-mono">
|
||||
{feature.tycoon}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
@ -355,50 +354,60 @@ export default function PricingPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* FAQ */}
|
||||
{/* FAQ - TERMINAL STYLE */}
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<h2 className="text-heading-md text-foreground text-center mb-8">Frequently Asked</h2>
|
||||
<div className="space-y-3">
|
||||
<h2 className="text-3xl font-display text-white text-center mb-12">Mission Support</h2>
|
||||
<div className="space-y-4">
|
||||
{faqs.map((faq, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="border border-border rounded-xl overflow-hidden"
|
||||
className="border border-white/10 bg-[#050505] transition-all hover:border-white/20"
|
||||
>
|
||||
<button
|
||||
onClick={() => setExpandedFaq(expandedFaq === i ? null : i)}
|
||||
className="w-full flex items-center justify-between p-5 text-left hover:bg-foreground/5 transition-colors"
|
||||
className="w-full flex items-center justify-between p-6 text-left"
|
||||
>
|
||||
<span className="text-body font-medium text-foreground pr-4">{faq.q}</span>
|
||||
<span className="text-base font-mono text-white pr-8">{faq.q}</span>
|
||||
<span className={clsx(
|
||||
"shrink-0 w-6 h-6 flex items-center justify-center rounded-lg transition-all",
|
||||
expandedFaq === i ? "bg-accent/10 text-accent rotate-45" : "bg-foreground/5 text-foreground-muted"
|
||||
"shrink-0 w-6 h-6 flex items-center justify-center border border-white/10 transition-all",
|
||||
expandedFaq === i ? "bg-accent text-black border-accent" : "text-white/40"
|
||||
)}>
|
||||
<span className="text-lg leading-none">+</span>
|
||||
<span className={clsx("text-lg leading-none transition-transform duration-300", expandedFaq === i ? "rotate-45" : "")}>+</span>
|
||||
</span>
|
||||
</button>
|
||||
{expandedFaq === i && (
|
||||
<div className="px-5 pb-5">
|
||||
<p className="text-body-sm text-foreground-muted">{faq.a}</p>
|
||||
<div className={clsx(
|
||||
"overflow-hidden transition-all duration-300 ease-in-out",
|
||||
expandedFaq === i ? "max-h-40 opacity-100" : "max-h-0 opacity-0"
|
||||
)}>
|
||||
<div className="px-6 pb-6 pt-0">
|
||||
<div className="h-px w-full bg-white/5 mb-4" />
|
||||
<p className="text-sm text-white/50 font-mono leading-relaxed pl-4 border-l border-accent/20">
|
||||
{faq.a}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom CTA */}
|
||||
<div className="text-center mt-20 py-12 px-6 bg-background-secondary/50 border border-border rounded-2xl">
|
||||
<h2 className="text-heading-md text-foreground mb-3">Not sure yet?</h2>
|
||||
<p className="text-body text-foreground-muted mb-6">
|
||||
Start with Scout. It's free forever. Upgrade when you need more.
|
||||
</p>
|
||||
<Link
|
||||
href={isAuthenticated ? "/terminal/radar" : "/register"}
|
||||
className="btn-primary inline-flex items-center gap-2 px-6 py-3"
|
||||
>
|
||||
{isAuthenticated ? "Command Center" : "Join the Hunt"}
|
||||
<ArrowRight className="w-4 h-4" />
|
||||
</Link>
|
||||
<div className="text-center mt-24 py-16 px-6 bg-[#050505] border border-white/10 relative overflow-hidden">
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.05]" />
|
||||
<div className="relative z-10">
|
||||
<Shield className="w-12 h-12 text-white/20 mx-auto mb-6" />
|
||||
<h2 className="text-3xl font-display text-white mb-4">Not ready to commit?</h2>
|
||||
<p className="text-white/50 mb-10 font-mono text-sm">
|
||||
Start with Scout. It's free forever. Upgrade when you need more firepower.
|
||||
</p>
|
||||
<Link
|
||||
href={isAuthenticated ? "/terminal/radar" : "/register"}
|
||||
className="inline-flex items-center gap-3 px-8 py-4 border border-white/20 text-white text-xs font-bold uppercase tracking-[0.2em] hover:bg-white hover:text-black transition-all"
|
||||
>
|
||||
{isAuthenticated ? "Command Center" : "Join the Hunt"}
|
||||
<ArrowRight className="w-4 h-4" />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
@ -6,17 +6,18 @@ import Link from 'next/link'
|
||||
import Image from 'next/image'
|
||||
import { useStore } from '@/lib/store'
|
||||
import { api } from '@/lib/api'
|
||||
import { Loader2, ArrowRight, Check, Eye, EyeOff, Mail } from 'lucide-react'
|
||||
import { Loader2, ArrowRight, Check, Eye, EyeOff, Mail, Shield, Zap, TrendingUp } from 'lucide-react'
|
||||
import clsx from 'clsx'
|
||||
|
||||
// Logo Component
|
||||
function Logo() {
|
||||
return (
|
||||
<Image
|
||||
src="/pounce-logo.png"
|
||||
src="/pounce-puma.png"
|
||||
alt="pounce"
|
||||
width={120}
|
||||
height={60}
|
||||
className="w-28 h-auto"
|
||||
height={120}
|
||||
className="w-20 h-20 object-contain drop-shadow-[0_0_15px_rgba(16,185,129,0.3)]"
|
||||
/>
|
||||
)
|
||||
}
|
||||
@ -42,10 +43,9 @@ function GitHubIcon({ className }: { className?: string }) {
|
||||
}
|
||||
|
||||
const benefits = [
|
||||
'Track up to 5 domains. Free.',
|
||||
'Daily status scans. Never miss a drop.',
|
||||
'Market overview. See what\'s moving.',
|
||||
'Expiry intel. Plan your move.',
|
||||
{ text: 'Real-time Market Feed', icon: Zap },
|
||||
{ text: 'Daily Scan Reports', icon: Shield },
|
||||
{ text: 'Yield Intel Access', icon: TrendingUp },
|
||||
]
|
||||
|
||||
function RegisterForm() {
|
||||
@ -77,13 +77,10 @@ function RegisterForm() {
|
||||
try {
|
||||
await register(email, password)
|
||||
|
||||
// Store redirect URL for after email verification
|
||||
// This will be picked up by the login page after verification
|
||||
if (redirectTo !== '/terminal/radar') {
|
||||
localStorage.setItem('pounce_redirect_after_login', redirectTo)
|
||||
}
|
||||
|
||||
// Show verification message
|
||||
setRegistered(true)
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Registration failed')
|
||||
@ -100,37 +97,47 @@ function RegisterForm() {
|
||||
// Show verification message after registration
|
||||
if (registered) {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center px-4 sm:px-6 py-8 sm:py-12 relative">
|
||||
<div className="min-h-screen flex items-center justify-center px-4 sm:px-6 py-8 sm:py-12 relative bg-[#020202] overflow-hidden">
|
||||
{/* Background Atmosphere */}
|
||||
<div className="fixed inset-0 pointer-events-none">
|
||||
<div className="absolute top-1/4 left-1/3 w-[400px] h-[300px] bg-accent/[0.02] rounded-full blur-3xl" />
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.03] mix-blend-overlay" />
|
||||
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[800px] h-[800px] bg-accent/[0.02] rounded-full blur-[120px]" />
|
||||
</div>
|
||||
|
||||
<div className="relative w-full max-w-md text-center animate-fade-in">
|
||||
<div className="w-20 h-20 bg-accent/10 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<Mail className="w-10 h-10 text-accent" />
|
||||
</div>
|
||||
<h2 className="font-display text-3xl sm:text-4xl text-foreground mb-4">
|
||||
Check your inbox
|
||||
</h2>
|
||||
<p className="text-lg text-foreground-muted mb-6">
|
||||
We've sent a verification link to <strong className="text-foreground">{email}</strong>
|
||||
</p>
|
||||
<p className="text-sm text-foreground-subtle mb-8">
|
||||
Click the link in the email to verify your account and start hunting domains.
|
||||
</p>
|
||||
<div className="space-y-3">
|
||||
<Link
|
||||
href={loginLink}
|
||||
className="block w-full py-3 bg-foreground text-background text-sm font-medium rounded-xl hover:bg-foreground/90 transition-all"
|
||||
>
|
||||
Go to Login
|
||||
</Link>
|
||||
<Link
|
||||
href="/verify-email"
|
||||
className="block w-full py-3 border border-border text-foreground-muted text-sm font-medium rounded-xl hover:border-foreground/20 transition-all"
|
||||
>
|
||||
Resend Verification Email
|
||||
</Link>
|
||||
<div className="relative w-full max-w-[450px] animate-fade-in z-10">
|
||||
<div className="bg-[#050505] border border-white/10 p-10 text-center relative shadow-2xl">
|
||||
{/* Tech Corners */}
|
||||
<div className="absolute -top-px -left-px w-4 h-4 border-t border-l border-white/40" />
|
||||
<div className="absolute -top-px -right-px w-4 h-4 border-t border-r border-white/40" />
|
||||
<div className="absolute -bottom-px -left-px w-4 h-4 border-b border-l border-white/40" />
|
||||
<div className="absolute -bottom-px -right-px w-4 h-4 border-b border-r border-white/40" />
|
||||
|
||||
<div className="w-16 h-16 bg-accent/10 border border-accent/20 flex items-center justify-center mx-auto mb-8 rounded-none">
|
||||
<Mail className="w-8 h-8 text-accent" />
|
||||
</div>
|
||||
|
||||
<h2 className="font-display text-3xl text-white mb-4">
|
||||
Verify Credentials
|
||||
</h2>
|
||||
<p className="text-sm font-mono text-white/50 mb-8 leading-relaxed">
|
||||
Security protocol initiated. Verification link sent to <br/><strong className="text-white">{email}</strong>
|
||||
</p>
|
||||
|
||||
<div className="space-y-4">
|
||||
<Link
|
||||
href={loginLink}
|
||||
className="block w-full py-4 bg-white text-black text-xs font-bold uppercase tracking-[0.2em] hover:bg-accent transition-all"
|
||||
style={{ clipPath: 'polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px)' }}
|
||||
>
|
||||
Proceed to Login
|
||||
</Link>
|
||||
<Link
|
||||
href="/verify-email"
|
||||
className="block w-full py-4 border border-white/10 text-white/40 text-xs font-bold uppercase tracking-[0.2em] hover:text-white hover:border-white/30 transition-all"
|
||||
>
|
||||
Resend Link
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -138,171 +145,202 @@ function RegisterForm() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex relative">
|
||||
{/* Ambient glow */}
|
||||
<div className="fixed inset-0 pointer-events-none">
|
||||
<div className="absolute top-1/4 left-1/3 w-[400px] h-[300px] bg-accent/[0.02] rounded-full blur-3xl" />
|
||||
<div className="min-h-screen flex relative bg-[#020202] overflow-hidden">
|
||||
{/* Living Background Atmosphere */}
|
||||
<div className="fixed inset-0 pointer-events-none overflow-hidden">
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.04] mix-blend-overlay z-10" />
|
||||
|
||||
{/* Animated Orbs */}
|
||||
<div className="absolute top-[-20%] left-[-10%] w-[70vw] h-[70vw] bg-accent/5 rounded-full blur-[150px] animate-pulse-slow mix-blend-screen" />
|
||||
<div className="absolute bottom-[-20%] right-[-10%] w-[60vw] h-[60vw] bg-purple-500/5 rounded-full blur-[180px] animate-pulse-slower mix-blend-screen" />
|
||||
|
||||
{/* Grid Overlay */}
|
||||
<div
|
||||
className="absolute inset-0 opacity-[0.02] z-0"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(rgba(255,255,255,0.3) 0.5px, transparent 0.5px), linear-gradient(90deg, rgba(255,255,255,0.3) 0.5px, transparent 0.5px)`,
|
||||
backgroundSize: '60px 60px',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Left Panel - Form */}
|
||||
<div className="flex-1 flex items-center justify-center px-4 sm:px-6 py-8 sm:py-12">
|
||||
<div className="relative w-full max-w-sm animate-fade-in">
|
||||
{/* Logo */}
|
||||
<Link href="/" className="block mb-12 sm:mb-16 hover:opacity-80 transition-opacity duration-300">
|
||||
<Logo />
|
||||
</Link>
|
||||
<div className="flex-1 flex items-center justify-center px-4 sm:px-6 py-8 sm:py-12 relative z-10">
|
||||
<div className="relative w-full max-w-[450px] animate-fade-in">
|
||||
{/* Card Container */}
|
||||
<div className="bg-[#050505] border border-white/10 relative p-8 sm:p-10 shadow-2xl">
|
||||
{/* Tech Corners */}
|
||||
<div className="absolute -top-px -left-px w-4 h-4 border-t border-l border-white/40" />
|
||||
<div className="absolute -top-px -right-px w-4 h-4 border-t border-r border-white/40" />
|
||||
<div className="absolute -bottom-px -left-px w-4 h-4 border-b border-l border-white/40" />
|
||||
<div className="absolute -bottom-px -right-px w-4 h-4 border-b border-r border-white/40" />
|
||||
|
||||
{/* Header */}
|
||||
<div className="mb-8 sm:mb-10">
|
||||
<h1 className="font-display text-[2rem] sm:text-[2.5rem] md:text-[3rem] leading-[1.1] tracking-[-0.03em] text-foreground mb-2 sm:mb-3">
|
||||
Join the hunt.
|
||||
</h1>
|
||||
<p className="text-body-sm sm:text-body text-foreground-muted">
|
||||
Start tracking domains in under a minute
|
||||
</p>
|
||||
</div>
|
||||
{/* Logo */}
|
||||
<Link href="/" className="flex justify-center mb-10 hover:opacity-80 transition-opacity duration-300">
|
||||
<Logo />
|
||||
</Link>
|
||||
|
||||
{/* Form */}
|
||||
<form onSubmit={handleSubmit} className="space-y-3 sm:space-y-4">
|
||||
{error && (
|
||||
<div className="p-3 sm:p-4 bg-danger-muted border border-danger/20 rounded-2xl">
|
||||
<p className="text-danger text-body-xs sm:text-body-sm">{error}</p>
|
||||
</div>
|
||||
)}
|
||||
{/* Header */}
|
||||
<div className="text-center mb-10">
|
||||
<span className="text-[10px] font-mono text-accent uppercase tracking-[0.2em] mb-2 block flex items-center justify-center gap-2">
|
||||
<div className="w-1.5 h-1.5 bg-accent animate-pulse" />
|
||||
New Operator
|
||||
</span>
|
||||
<h1 className="font-display text-3xl text-white mb-2 tracking-tight">
|
||||
Initialize Access.
|
||||
</h1>
|
||||
<p className="text-xs font-mono text-white/40">
|
||||
Create your secure terminal account.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Form */}
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
{error && (
|
||||
<div className="p-3 bg-red-500/10 border border-red-500/20">
|
||||
<p className="text-red-500 text-xs font-mono text-center uppercase tracking-wider">{error}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="group">
|
||||
<label className="text-[10px] font-mono text-white/40 uppercase tracking-widest mb-2 block group-focus-within:text-white/70 transition-colors">Email Address</label>
|
||||
<input
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder="OPERATOR@POUNCE.IO"
|
||||
required
|
||||
autoComplete="email"
|
||||
className="w-full bg-[#0A0A0A] border border-white/10 px-4 py-3 text-white font-mono text-sm placeholder:text-white/20 focus:outline-none focus:border-accent transition-all rounded-none"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="group relative">
|
||||
<label className="text-[10px] font-mono text-white/40 uppercase tracking-widest mb-2 block group-focus-within:text-white/70 transition-colors">Create Passcode</label>
|
||||
<div className="relative">
|
||||
<input
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
placeholder="MIN 8 CHARS"
|
||||
required
|
||||
minLength={8}
|
||||
autoComplete="new-password"
|
||||
className="w-full bg-[#0A0A0A] border border-white/10 px-4 py-3 text-white font-mono text-sm placeholder:text-white/20 focus:outline-none focus:border-accent transition-all rounded-none pr-12"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowPassword(!showPassword)}
|
||||
className="absolute right-4 top-1/2 -translate-y-1/2 text-white/30 hover:text-white transition-colors"
|
||||
aria-label={showPassword ? 'Hide password' : 'Show password'}
|
||||
>
|
||||
{showPassword ? (
|
||||
<EyeOff className="w-4 h-4" />
|
||||
) : (
|
||||
<Eye className="w-4 h-4" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2.5 sm:space-y-3">
|
||||
<input
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder="Email address"
|
||||
required
|
||||
autoComplete="email"
|
||||
className="input-elegant text-body-sm sm:text-body"
|
||||
/>
|
||||
<div className="relative">
|
||||
<input
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
placeholder="Create password (min. 8 characters)"
|
||||
required
|
||||
minLength={8}
|
||||
autoComplete="new-password"
|
||||
className="input-elegant text-body-sm sm:text-body pr-12"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowPassword(!showPassword)}
|
||||
className="absolute right-3 sm:right-4 top-1/2 -translate-y-1/2 text-foreground-muted hover:text-foreground transition-colors duration-200"
|
||||
aria-label={showPassword ? 'Hide password' : 'Show password'}
|
||||
type="submit"
|
||||
disabled={loading}
|
||||
className="w-full py-4 bg-white text-black text-xs font-bold uppercase tracking-[0.2em] hover:bg-accent transition-all disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-3"
|
||||
style={{ clipPath: 'polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px)' }}
|
||||
>
|
||||
{showPassword ? (
|
||||
<EyeOff className="w-4 h-4 sm:w-5 sm:h-5" />
|
||||
) : (
|
||||
<Eye className="w-4 h-4 sm:w-5 sm:h-5" />
|
||||
)}
|
||||
{loading ? (
|
||||
<Loader2 className="w-4 h-4 animate-spin" />
|
||||
) : (
|
||||
<>
|
||||
Start Hunting
|
||||
<ArrowRight className="w-4 h-4" />
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
disabled={loading}
|
||||
className="w-full py-3 sm:py-4 bg-foreground text-background text-ui-sm sm:text-ui font-medium rounded-xl
|
||||
hover:bg-foreground/90 disabled:opacity-50 disabled:cursor-not-allowed
|
||||
transition-all duration-300 flex items-center justify-center gap-2 sm:gap-2.5"
|
||||
>
|
||||
{loading ? (
|
||||
<Loader2 className="w-4 h-4 animate-spin" />
|
||||
) : (
|
||||
<>
|
||||
Start Hunting
|
||||
<ArrowRight className="w-3.5 sm:w-4 h-3.5 sm:h-4" />
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{/* OAuth Buttons */}
|
||||
{(oauthProviders.google_enabled || oauthProviders.github_enabled) && (
|
||||
<div className="mt-6">
|
||||
{/* Divider */}
|
||||
<div className="relative mb-6">
|
||||
<div className="absolute inset-0 flex items-center">
|
||||
<div className="w-full border-t border-border" />
|
||||
{/* OAuth Buttons */}
|
||||
{(oauthProviders.google_enabled || oauthProviders.github_enabled) && (
|
||||
<div className="mt-8">
|
||||
<div className="relative mb-8">
|
||||
<div className="absolute inset-0 flex items-center">
|
||||
<div className="w-full border-t border-white/10" />
|
||||
</div>
|
||||
<div className="relative flex justify-center">
|
||||
<span className="px-4 bg-[#050505] text-[10px] font-mono text-white/30 uppercase tracking-widest">Alternative Access</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
{oauthProviders.google_enabled && (
|
||||
<a
|
||||
href={api.getGoogleLoginUrl(redirectTo)}
|
||||
className="w-full py-3 bg-[#0A0A0A] border border-white/10 text-white text-xs font-mono uppercase tracking-wide hover:bg-white/5 hover:border-white/30 transition-all flex items-center justify-center gap-3"
|
||||
>
|
||||
<GoogleIcon className="w-4 h-4" />
|
||||
Google
|
||||
</a>
|
||||
)}
|
||||
{oauthProviders.github_enabled && (
|
||||
<a
|
||||
href={api.getGitHubLoginUrl(redirectTo)}
|
||||
className="w-full py-3 bg-[#0A0A0A] border border-white/10 text-white text-xs font-mono uppercase tracking-wide hover:bg-white/5 hover:border-white/30 transition-all flex items-center justify-center gap-3"
|
||||
>
|
||||
<GitHubIcon className="w-4 h-4" />
|
||||
GitHub
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative flex justify-center text-xs">
|
||||
<span className="px-4 bg-background text-foreground-muted">or continue with</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
{oauthProviders.google_enabled && (
|
||||
<a
|
||||
href={api.getGoogleLoginUrl(redirectTo)}
|
||||
className="w-full py-3 sm:py-3.5 bg-[#24292e] text-white text-sm font-medium rounded-xl
|
||||
hover:bg-[#2f363d] border border-[#24292e]
|
||||
transition-all duration-300 flex items-center justify-center gap-3"
|
||||
>
|
||||
<GoogleIcon className="w-5 h-5" />
|
||||
Sign up with Google
|
||||
</a>
|
||||
)}
|
||||
{oauthProviders.github_enabled && (
|
||||
<a
|
||||
href={api.getGitHubLoginUrl(redirectTo)}
|
||||
className="w-full py-3 sm:py-3.5 bg-[#24292e] text-white text-sm font-medium rounded-xl
|
||||
hover:bg-[#2f363d] border border-[#24292e]
|
||||
transition-all duration-300 flex items-center justify-center gap-3"
|
||||
>
|
||||
<GitHubIcon className="w-5 h-5" />
|
||||
Sign up with GitHub
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
)}
|
||||
|
||||
{/* Login Link */}
|
||||
<p className="mt-8 sm:mt-10 text-body-xs sm:text-body-sm text-foreground-muted">
|
||||
Already have an account?{' '}
|
||||
<Link href={loginLink} className="text-foreground hover:text-accent transition-colors duration-300">
|
||||
Sign in
|
||||
</Link>
|
||||
</p>
|
||||
{/* Login Link */}
|
||||
<div className="mt-8 pt-8 border-t border-white/10 text-center">
|
||||
<p className="text-xs font-mono text-white/40">
|
||||
Already authorized?{' '}
|
||||
<Link href={loginLink} className="text-white hover:text-accent border-b border-white/20 hover:border-accent transition-all pb-0.5 ml-1">
|
||||
Sign In
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right Panel - Benefits */}
|
||||
<div className="hidden lg:flex flex-1 bg-background-secondary/50 items-center justify-center p-8 xl:p-12 border-l border-border-subtle">
|
||||
<div className="max-w-sm animate-slide-up delay-200">
|
||||
<div className="inline-flex items-center gap-2 sm:gap-2.5 px-3 sm:px-4 py-1.5 sm:py-2 bg-background-tertiary border border-border rounded-full mb-8 sm:mb-10">
|
||||
<div className="w-1.5 h-1.5 rounded-full bg-accent" />
|
||||
<span className="text-ui-sm sm:text-ui text-foreground-muted">Free Forever</span>
|
||||
</div>
|
||||
|
||||
<h2 className="font-display text-[1.75rem] sm:text-[2.25rem] md:text-[2.75rem] leading-[1.15] tracking-[-0.025em] text-foreground mb-8 sm:mb-10">
|
||||
Your hunting gear. Ready to go.
|
||||
</h2>
|
||||
|
||||
<ul className="space-y-4 sm:space-y-5">
|
||||
{benefits.map((item) => (
|
||||
<li key={item} className="flex items-center gap-3 sm:gap-4">
|
||||
<div className="w-8 sm:w-9 h-8 sm:h-9 rounded-lg bg-accent/10 flex items-center justify-center shrink-0">
|
||||
<Check className="w-3.5 sm:w-4 h-3.5 sm:h-4 text-accent" strokeWidth={2.5} />
|
||||
</div>
|
||||
<span className="text-body-sm sm:text-body text-foreground-muted">{item}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<div className="divider my-8 sm:my-10" />
|
||||
|
||||
<p className="text-body-xs sm:text-body-sm text-foreground-subtle">
|
||||
No credit card required. Upgrade anytime.
|
||||
</p>
|
||||
</div>
|
||||
<div className="hidden lg:flex flex-1 bg-[#030303] items-center justify-center p-8 xl:p-12 border-l border-white/10 relative overflow-hidden">
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.05]" />
|
||||
<div className="max-w-md animate-slide-up delay-200 relative z-10">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1.5 bg-accent/5 border border-accent/20 mb-8 rounded-none">
|
||||
<div className="w-1.5 h-1.5 bg-accent animate-pulse" />
|
||||
<span className="text-[10px] uppercase tracking-widest text-accent font-bold">Scout Access: Granted</span>
|
||||
</div>
|
||||
|
||||
<h2 className="font-display text-4xl leading-tight text-white mb-10">
|
||||
Your command center is waiting.
|
||||
</h2>
|
||||
|
||||
<ul className="space-y-6">
|
||||
{benefits.map((item) => (
|
||||
<li key={item.text} className="flex items-center gap-4 group">
|
||||
<div className="w-10 h-10 border border-white/10 bg-white/5 flex items-center justify-center shrink-0 group-hover:border-accent/50 group-hover:text-accent transition-all">
|
||||
<item.icon className="w-5 h-5 text-white/60 group-hover:text-accent transition-colors" strokeWidth={1.5} />
|
||||
</div>
|
||||
<span className="font-mono text-sm text-white/60 group-hover:text-white transition-colors">{item.text}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<div className="h-px w-full bg-white/10 my-10" />
|
||||
|
||||
<p className="font-mono text-xs text-white/30">
|
||||
// ENCRYPTED CONNECTION<br/>
|
||||
// NO CREDIT CARD REQUIRED
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@ -311,8 +349,8 @@ function RegisterForm() {
|
||||
export default function RegisterPage() {
|
||||
return (
|
||||
<Suspense fallback={
|
||||
<div className="min-h-screen flex items-center justify-center">
|
||||
<div className="w-5 h-5 border-2 border-accent border-t-transparent rounded-full animate-spin" />
|
||||
<div className="min-h-screen flex items-center justify-center bg-[#020202]">
|
||||
<div className="w-8 h-8 border-2 border-white/10 border-t-accent rounded-full animate-spin" />
|
||||
</div>
|
||||
}>
|
||||
<RegisterForm />
|
||||
|
||||
@ -61,86 +61,93 @@ function VerifyEmailContent() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background relative overflow-hidden">
|
||||
{/* Background Effects */}
|
||||
<div className="fixed inset-0 pointer-events-none">
|
||||
<div className="absolute top-[-20%] left-1/2 -translate-x-1/2 w-[1200px] h-[800px] bg-accent/[0.03] rounded-full blur-[120px]" />
|
||||
<div className="absolute bottom-[-10%] right-[-10%] w-[600px] h-[600px] bg-accent/[0.02] rounded-full blur-[100px]" />
|
||||
<div className="min-h-screen bg-[#020202] text-white relative overflow-x-hidden selection:bg-accent/30 selection:text-white">
|
||||
{/* Living Background Atmosphere */}
|
||||
<div className="fixed inset-0 pointer-events-none overflow-hidden">
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.04] mix-blend-overlay z-10" />
|
||||
|
||||
{/* Animated Orbs */}
|
||||
<div className="absolute top-[20%] left-[50%] -translate-x-1/2 w-[60vw] h-[60vw] bg-accent/5 rounded-full blur-[150px] animate-pulse-slow mix-blend-screen" />
|
||||
<div className="absolute bottom-[-20%] right-[-10%] w-[50vw] h-[50vw] bg-purple-500/5 rounded-full blur-[120px] animate-blob mix-blend-screen" />
|
||||
|
||||
{/* Grid Overlay */}
|
||||
<div
|
||||
className="absolute inset-0 opacity-[0.015]"
|
||||
className="absolute inset-0 opacity-[0.03] z-0"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(rgba(255,255,255,.1) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,.1) 1px, transparent 1px)`,
|
||||
backgroundSize: '64px 64px',
|
||||
backgroundImage: `linear-gradient(rgba(255,255,255,0.3) 0.5px, transparent 0.5px), linear-gradient(90deg, rgba(255,255,255,0.3) 0.5px, transparent 0.5px)`,
|
||||
backgroundSize: '40px 40px',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Header />
|
||||
|
||||
<main className="relative flex-1 pt-32 sm:pt-40 pb-20 sm:pb-28 px-4 sm:px-6">
|
||||
<div className="max-w-md mx-auto">
|
||||
<div className="text-center mb-8">
|
||||
<div className="inline-flex items-center gap-2 px-4 py-2 bg-accent/10 border border-accent/20 rounded-full mb-6">
|
||||
<Mail className="w-4 h-4 text-accent" />
|
||||
<span className="text-sm font-medium text-accent">Email Verification</span>
|
||||
</div>
|
||||
</div>
|
||||
<main className="min-h-screen flex items-center justify-center px-4 sm:px-6 py-20 relative z-10">
|
||||
<div className="w-full max-w-[450px] animate-fade-in">
|
||||
|
||||
<div className="bg-[#050505] border border-white/10 relative p-8 sm:p-10 shadow-2xl">
|
||||
{/* Tech Corners */}
|
||||
<div className="absolute -top-px -left-px w-4 h-4 border-t border-l border-white/40" />
|
||||
<div className="absolute -top-px -right-px w-4 h-4 border-t border-r border-white/40" />
|
||||
<div className="absolute -bottom-px -left-px w-4 h-4 border-b border-l border-white/40" />
|
||||
<div className="absolute -bottom-px -right-px w-4 h-4 border-b border-r border-white/40" />
|
||||
|
||||
<div className="bg-background-secondary/50 border border-border rounded-2xl p-8 backdrop-blur-sm">
|
||||
{status === 'loading' && (
|
||||
<div className="text-center py-8">
|
||||
<Loader2 className="w-12 h-12 text-accent animate-spin mx-auto mb-4" />
|
||||
<p className="text-lg text-foreground">Verifying your email...</p>
|
||||
<p className="text-sm text-foreground-muted mt-2">This will only take a moment</p>
|
||||
<Loader2 className="w-12 h-12 text-accent animate-spin mx-auto mb-6" />
|
||||
<h2 className="font-display text-2xl text-white mb-2">Verifying Credentials</h2>
|
||||
<p className="text-xs font-mono text-white/40">Secure handshake in progress...</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{status === 'success' && (
|
||||
<div className="text-center py-8">
|
||||
<div className="w-16 h-16 bg-accent/10 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<div className="w-16 h-16 bg-accent/10 border border-accent/20 flex items-center justify-center mx-auto mb-6 rounded-none">
|
||||
<CheckCircle className="w-8 h-8 text-accent" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-display text-foreground mb-2">Email Verified!</h2>
|
||||
<p className="text-foreground-muted mb-6">{message}</p>
|
||||
<p className="text-sm text-foreground-subtle">Redirecting to login...</p>
|
||||
<h2 className="font-display text-2xl text-white mb-2">Access Granted</h2>
|
||||
<p className="text-sm font-mono text-white/50 mb-6">{message}</p>
|
||||
<div className="inline-flex items-center gap-2 px-4 py-2 bg-white/5 border border-white/10 text-xs font-mono text-white/60">
|
||||
<Loader2 className="w-3 h-3 animate-spin" /> Redirecting to Terminal...
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{status === 'error' && (
|
||||
<div className="text-center py-8">
|
||||
<div className="w-16 h-16 bg-red-500/10 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<div className="w-16 h-16 bg-red-500/10 border border-red-500/20 flex items-center justify-center mx-auto mb-6 rounded-none">
|
||||
<XCircle className="w-8 h-8 text-red-500" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-display text-foreground mb-2">Verification Failed</h2>
|
||||
<p className="text-foreground-muted mb-6">{message}</p>
|
||||
<h2 className="font-display text-2xl text-white mb-2">Verification Failed</h2>
|
||||
<p className="text-sm font-mono text-white/50 mb-8">{message}</p>
|
||||
|
||||
{!resendSuccess ? (
|
||||
<form onSubmit={handleResend} className="mt-6">
|
||||
<p className="text-sm text-foreground-muted mb-4">
|
||||
Need a new verification link?
|
||||
<p className="text-[10px] font-mono text-white/40 uppercase tracking-widest mb-4">
|
||||
Request New Link
|
||||
</p>
|
||||
<div className="flex gap-2">
|
||||
<input
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder="Enter your email"
|
||||
className="flex-1 px-4 py-3 bg-background border border-border rounded-xl text-foreground placeholder:text-foreground-subtle focus:outline-none focus:border-accent/50"
|
||||
placeholder="EMAIL ADDRESS"
|
||||
className="flex-1 bg-[#0A0A0A] border border-white/10 px-4 py-3 text-white font-mono text-sm placeholder:text-white/20 focus:outline-none focus:border-accent transition-all rounded-none"
|
||||
required
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={resending}
|
||||
className="px-4 py-3 bg-accent text-background rounded-xl font-medium hover:bg-accent-hover transition-all disabled:opacity-50"
|
||||
className="px-4 py-3 bg-white text-black text-xs font-bold uppercase tracking-wider hover:bg-accent transition-all disabled:opacity-50"
|
||||
>
|
||||
{resending ? <Loader2 className="w-5 h-5 animate-spin" /> : 'Resend'}
|
||||
{resending ? <Loader2 className="w-4 h-4 animate-spin" /> : 'Send'}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
) : (
|
||||
<div className="mt-6 p-4 bg-accent/10 border border-accent/20 rounded-xl">
|
||||
<p className="text-sm text-accent">
|
||||
If an unverified account exists, a new verification link has been sent.
|
||||
<div className="mt-6 p-4 bg-accent/5 border border-accent/20">
|
||||
<p className="text-xs font-mono text-accent">
|
||||
New verification link dispatched.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
@ -149,12 +156,12 @@ function VerifyEmailContent() {
|
||||
|
||||
{status === 'no-token' && (
|
||||
<div className="text-center py-8">
|
||||
<div className="w-16 h-16 bg-foreground/5 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<Mail className="w-8 h-8 text-foreground-muted" />
|
||||
<div className="w-16 h-16 bg-white/5 border border-white/10 flex items-center justify-center mx-auto mb-6 rounded-none">
|
||||
<Mail className="w-8 h-8 text-white/40" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-display text-foreground mb-2">Verify Your Email</h2>
|
||||
<p className="text-foreground-muted mb-6">
|
||||
Check your inbox for a verification link, or request a new one below.
|
||||
<h2 className="font-display text-2xl text-white mb-2">Verify Identity</h2>
|
||||
<p className="text-sm font-mono text-white/50 mb-8">
|
||||
Check your inbox for the verification link.
|
||||
</p>
|
||||
|
||||
{!resendSuccess ? (
|
||||
@ -164,36 +171,36 @@ function VerifyEmailContent() {
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder="Enter your email"
|
||||
className="flex-1 px-4 py-3 bg-background border border-border rounded-xl text-foreground placeholder:text-foreground-subtle focus:outline-none focus:border-accent/50"
|
||||
placeholder="EMAIL ADDRESS"
|
||||
className="flex-1 bg-[#0A0A0A] border border-white/10 px-4 py-3 text-white font-mono text-sm placeholder:text-white/20 focus:outline-none focus:border-accent transition-all rounded-none"
|
||||
required
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={resending}
|
||||
className="px-4 py-3 bg-accent text-background rounded-xl font-medium hover:bg-accent-hover transition-all disabled:opacity-50"
|
||||
className="px-4 py-3 bg-white text-black text-xs font-bold uppercase tracking-wider hover:bg-accent transition-all disabled:opacity-50"
|
||||
>
|
||||
{resending ? <Loader2 className="w-5 h-5 animate-spin" /> : 'Send'}
|
||||
{resending ? <Loader2 className="w-4 h-4 animate-spin" /> : 'Send'}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
) : (
|
||||
<div className="mt-6 p-4 bg-accent/10 border border-accent/20 rounded-xl">
|
||||
<p className="text-sm text-accent">
|
||||
If an unverified account exists, a verification link has been sent.
|
||||
<div className="mt-6 p-4 bg-accent/5 border border-accent/20">
|
||||
<p className="text-xs font-mono text-accent">
|
||||
Link dispatched. Check inbox.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="mt-8 pt-6 border-t border-border text-center">
|
||||
<div className="mt-8 pt-8 border-t border-white/10 text-center">
|
||||
<Link
|
||||
href="/login"
|
||||
className="inline-flex items-center gap-2 text-sm text-foreground-muted hover:text-accent transition-colors"
|
||||
className="inline-flex items-center gap-2 text-xs font-mono text-white/40 hover:text-white transition-colors uppercase tracking-wider"
|
||||
>
|
||||
Back to Login
|
||||
<ArrowRight className="w-4 h-4" />
|
||||
<ArrowRight className="w-3 h-3 rotate-180" />
|
||||
Return to Login
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
@ -208,8 +215,8 @@ function VerifyEmailContent() {
|
||||
export default function VerifyEmailPage() {
|
||||
return (
|
||||
<Suspense fallback={
|
||||
<div className="min-h-screen flex items-center justify-center bg-background">
|
||||
<Loader2 className="w-6 h-6 animate-spin text-accent" />
|
||||
<div className="min-h-screen flex items-center justify-center bg-[#020202]">
|
||||
<div className="w-8 h-8 border-2 border-white/10 border-t-accent rounded-full animate-spin" />
|
||||
</div>
|
||||
}>
|
||||
<VerifyEmailContent />
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
'use client'
|
||||
|
||||
import { useState, useEffect } from 'react'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import { Header } from '@/components/Header'
|
||||
import { Footer } from '@/components/Footer'
|
||||
import { useStore } from '@/lib/store'
|
||||
import { api } from '@/lib/api'
|
||||
import {
|
||||
Coins,
|
||||
TrendingUp,
|
||||
@ -13,437 +13,436 @@ import {
|
||||
Target,
|
||||
ArrowRight,
|
||||
Check,
|
||||
Sparkles,
|
||||
DollarSign,
|
||||
Globe,
|
||||
Zap,
|
||||
BarChart3,
|
||||
ChevronRight,
|
||||
Play,
|
||||
Server,
|
||||
Network,
|
||||
Globe,
|
||||
Lock,
|
||||
ArrowUpRight,
|
||||
Cpu,
|
||||
Share2,
|
||||
Wallet,
|
||||
PieChart,
|
||||
RefreshCw,
|
||||
Play,
|
||||
Calculator,
|
||||
Info
|
||||
} from 'lucide-react'
|
||||
import clsx from 'clsx'
|
||||
|
||||
// Intent categories for the demo
|
||||
const INTENT_EXAMPLES = [
|
||||
{ domain: 'zahnarzt-zuerich.ch', intent: 'Medical / Dental', potential: 'High', revenue: '120-350' },
|
||||
{ domain: 'hypothek-vergleich.ch', intent: 'Finance / Mortgage', potential: 'High', revenue: '200-500' },
|
||||
{ domain: 'rechtsanwalt-bern.ch', intent: 'Legal', potential: 'High', revenue: '150-400' },
|
||||
{ domain: 'wohnung-mieten.ch', intent: 'Real Estate', potential: 'Medium', revenue: '50-150' },
|
||||
{ domain: 'flug-buchen.ch', intent: 'Travel', potential: 'Medium', revenue: '30-100' },
|
||||
]
|
||||
// Yield Simulator Component - SIMPLIFIED & COMPACT
|
||||
function YieldSimulator() {
|
||||
const [traffic, setTraffic] = useState(2500)
|
||||
const [vertical, setVertical] = useState('finance')
|
||||
|
||||
export default function YieldPublicPage() {
|
||||
const { isAuthenticated, checkAuth, isLoading } = useStore()
|
||||
const [analyzeDomain, setAnalyzeDomain] = useState('')
|
||||
const [analyzing, setAnalyzing] = useState(false)
|
||||
const [analysis, setAnalysis] = useState<any>(null)
|
||||
const [selectedExample, setSelectedExample] = useState(0)
|
||||
// Vertical data (average CPA and Conversion)
|
||||
const verticals: Record<string, { cpa: number, conv: number, label: string }> = {
|
||||
finance: { cpa: 120, conv: 3.5, label: 'Finance & Loans' },
|
||||
insurance: { cpa: 80, conv: 2.8, label: 'Insurance' },
|
||||
legal: { cpa: 150, conv: 1.5, label: 'Legal Services' },
|
||||
medical: { cpa: 60, conv: 4.0, label: 'Medical / Health' },
|
||||
tech: { cpa: 45, conv: 2.2, label: 'Software / B2B' }
|
||||
}
|
||||
|
||||
const currentVertical = verticals[vertical]
|
||||
const monthlyRevenue = Math.floor(traffic * (currentVertical.conv / 100) * currentVertical.cpa)
|
||||
const annualYield = monthlyRevenue * 12
|
||||
|
||||
return (
|
||||
<div className="relative group max-w-md mx-auto lg:ml-auto lg:mr-0">
|
||||
{/* Ambient Glow - White/Green instead of Amber */}
|
||||
<div className="absolute -inset-0.5 bg-gradient-to-br from-accent/20 via-white/5 to-accent/20 blur-2xl opacity-30 group-hover:opacity-50 transition-opacity duration-1000" />
|
||||
|
||||
{/* Main Container - Compact Tech Card */}
|
||||
<div className="relative bg-[#050505]/90 backdrop-blur-xl border border-white/10 shadow-2xl overflow-hidden">
|
||||
{/* Decorative Tech Elements */}
|
||||
<div className="absolute top-0 right-0 p-3">
|
||||
<div className="flex gap-1.5">
|
||||
<div className="w-1 h-1 bg-white/20 rounded-full" />
|
||||
<div className="w-1 h-1 bg-accent animate-pulse rounded-full" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="p-6 sm:p-8">
|
||||
<div className="mb-6">
|
||||
<h3 className="font-display text-2xl text-white mb-1">Yield Projection</h3>
|
||||
<p className="font-mono text-[10px] text-white/40 uppercase tracking-widest">Est. Passive Income</p>
|
||||
</div>
|
||||
|
||||
{/* Input 1: Traffic Slider */}
|
||||
<div className="mb-6">
|
||||
<div className="flex justify-between text-xs font-mono mb-3">
|
||||
<span className="text-white/60">Monthly Traffic</span>
|
||||
<span className="text-white">{traffic.toLocaleString()} Visits</span>
|
||||
</div>
|
||||
<div className="relative h-4 flex items-center">
|
||||
<input
|
||||
type="range"
|
||||
min="100"
|
||||
max="10000"
|
||||
step="100"
|
||||
value={traffic}
|
||||
onChange={(e) => setTraffic(parseInt(e.target.value))}
|
||||
className="absolute w-full h-1 bg-white/10 rounded-full appearance-none cursor-pointer z-20
|
||||
[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:w-3 [&::-webkit-slider-thumb]:h-3
|
||||
[&::-webkit-slider-thumb]:bg-white [&::-webkit-slider-thumb]:rounded-full
|
||||
[&::-webkit-slider-thumb]:shadow-[0_0_10px_rgba(255,255,255,0.8)]"
|
||||
/>
|
||||
<div className="absolute top-1/2 left-0 right-0 h-px bg-white/10 z-10" />
|
||||
<div
|
||||
className="absolute top-1/2 left-0 h-px bg-white/50 z-10"
|
||||
style={{ width: `${((traffic - 100) / (10000 - 100)) * 100}%` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Input 2: Vertical Selector (Grid) */}
|
||||
<div className="mb-8">
|
||||
<label className="block text-xs font-mono text-white/60 mb-3">Domain Vertical</label>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
{Object.entries(verticals).map(([key, data]) => (
|
||||
<button
|
||||
key={key}
|
||||
onClick={() => setVertical(key)}
|
||||
className={clsx(
|
||||
"px-3 py-2 text-[10px] font-bold uppercase tracking-wide text-left transition-all border",
|
||||
vertical === key
|
||||
? "bg-white text-black border-white"
|
||||
: "bg-white/5 text-white/40 border-transparent hover:text-white hover:bg-white/10"
|
||||
)}
|
||||
>
|
||||
{data.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Result Area */}
|
||||
<div className="bg-white/[0.03] border border-white/5 p-5 relative overflow-hidden">
|
||||
<div className="relative z-10">
|
||||
<div className="flex justify-between items-end mb-2">
|
||||
<span className="text-[10px] font-mono uppercase tracking-widest text-white/40">Annual Revenue</span>
|
||||
<div className="text-right">
|
||||
<span className="block font-display text-3xl text-white tracking-tight leading-none">${annualYield.toLocaleString('en-US')}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-between items-center pt-3 border-t border-white/5 text-[10px] font-mono text-white/30">
|
||||
<span>${monthlyRevenue.toLocaleString('en-US')} / mo</span>
|
||||
<span>CPA: ${currentVertical.cpa}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Footer Bar */}
|
||||
<div className="bg-[#080808] px-6 py-3 border-t border-white/5 flex justify-between items-center text-[9px] font-mono text-white/20 uppercase tracking-wider">
|
||||
<span>Live Calculation</span>
|
||||
<span>Fee: 0%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function YieldPage() {
|
||||
const { isAuthenticated, checkAuth } = useStore()
|
||||
|
||||
useEffect(() => {
|
||||
checkAuth()
|
||||
}, [checkAuth])
|
||||
|
||||
// Rotate through examples
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setSelectedExample(prev => (prev + 1) % INTENT_EXAMPLES.length)
|
||||
}, 4000)
|
||||
return () => clearInterval(interval)
|
||||
}, [])
|
||||
|
||||
const handleAnalyze = async () => {
|
||||
if (!analyzeDomain.trim()) return
|
||||
|
||||
setAnalyzing(true)
|
||||
try {
|
||||
const result = await api.analyzeYieldDomain(analyzeDomain.trim())
|
||||
setAnalysis(result)
|
||||
} catch (err) {
|
||||
console.error('Analysis failed:', err)
|
||||
} finally {
|
||||
setAnalyzing(false)
|
||||
}
|
||||
}
|
||||
|
||||
const currentExample = INTENT_EXAMPLES[selectedExample]
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background flex flex-col">
|
||||
<div className="min-h-screen bg-[#020202] text-white relative overflow-x-hidden selection:bg-accent/30 selection:text-white">
|
||||
{/* Cinematic Background */}
|
||||
<div className="fixed inset-0 pointer-events-none z-0">
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.03] mix-blend-overlay" />
|
||||
<div
|
||||
className="absolute inset-0 opacity-[0.03]"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(rgba(255,255,255,0.3) 0.5px, transparent 0.5px), linear-gradient(90deg, rgba(255,255,255,0.3) 0.5px, transparent 0.5px)`,
|
||||
backgroundSize: '160px 160px',
|
||||
}}
|
||||
/>
|
||||
{/* Gold/Amber Glow for Yield context instead of Green */}
|
||||
<div className="absolute top-[20%] right-[-10%] w-[800px] h-[800px] bg-amber-500/[0.02] rounded-full blur-[150px]" />
|
||||
</div>
|
||||
|
||||
<Header />
|
||||
|
||||
{/* Hero Section */}
|
||||
<section className="relative pt-32 sm:pt-40 pb-20 sm:pb-28 px-4 sm:px-6 overflow-hidden">
|
||||
{/* Background Effects */}
|
||||
<div className="absolute inset-0 pointer-events-none overflow-hidden">
|
||||
<div className="absolute top-20 left-1/4 w-[600px] h-[600px] bg-purple-500/10 rounded-full blur-[120px]" />
|
||||
<div className="absolute bottom-20 right-1/4 w-[500px] h-[500px] bg-emerald-500/10 rounded-full blur-[100px]" />
|
||||
</div>
|
||||
{/* HERO SECTION */}
|
||||
<section className="relative min-h-[90vh] flex flex-col justify-center pt-32 pb-24 px-4 sm:px-6 z-10">
|
||||
<div className="max-w-[1400px] mx-auto w-full">
|
||||
<div className="grid lg:grid-cols-12 gap-16 lg:gap-24 items-center">
|
||||
|
||||
{/* Left: Typography */}
|
||||
<div className="lg:col-span-6 relative z-20 text-center lg:text-left">
|
||||
<div className="inline-flex items-center gap-4 mb-10 animate-fade-in opacity-0" style={{ animationDelay: '0.1s', animationFillMode: 'forwards' }}>
|
||||
<div className="h-px w-12 bg-white/10" />
|
||||
<span className="text-[10px] font-mono uppercase tracking-[0.3em] text-accent">Pounce Protocol // Yield</span>
|
||||
</div>
|
||||
|
||||
<div className="relative max-w-7xl mx-auto">
|
||||
<div className="text-center max-w-3xl mx-auto">
|
||||
{/* Badge */}
|
||||
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-purple-500/10 border border-purple-500/20 text-purple-400 text-sm mb-8">
|
||||
<Sparkles className="w-4 h-4" />
|
||||
<span>New Feature</span>
|
||||
<h1 className="font-display text-[3.5rem] sm:text-[5rem] md:text-[6rem] lg:text-[7rem] leading-[0.9] tracking-[-0.04em] text-white mb-8">
|
||||
<span className="block animate-slide-up opacity-0" style={{ animationDelay: '0.2s', animationFillMode: 'forwards' }}>
|
||||
Assets that
|
||||
</span>
|
||||
<span className="block text-white animate-slide-up opacity-0" style={{ animationDelay: '0.4s', animationFillMode: 'forwards' }}>
|
||||
work for you.
|
||||
</span>
|
||||
</h1>
|
||||
|
||||
<div className="animate-slide-up opacity-0" style={{ animationDelay: '0.8s', animationFillMode: 'forwards' }}>
|
||||
<p className="text-lg lg:text-xl text-white/60 max-w-xl font-light leading-relaxed mb-12 lg:mx-0 mx-auto">
|
||||
Turn dormant domains into active cashflow. Our Intent Routing™ engine directs traffic to high-paying partners automatically.
|
||||
</p>
|
||||
|
||||
<div className="flex flex-col sm:flex-row items-center gap-6 lg:justify-start justify-center">
|
||||
<Link
|
||||
href={isAuthenticated ? '/terminal/yield' : '/register'}
|
||||
className="px-8 py-4 bg-accent text-black text-xs font-bold uppercase tracking-[0.2em] hover:bg-white transition-all shadow-[0_0_20px_rgba(16,185,129,0.2)]"
|
||||
style={{ clipPath: 'polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px)' }}
|
||||
>
|
||||
Activate Protocol
|
||||
</Link>
|
||||
<button
|
||||
onClick={() => document.getElementById('how-it-works')?.scrollIntoView({ behavior: 'smooth' })}
|
||||
className="text-xs font-bold uppercase tracking-[0.2em] text-white/40 hover:text-white flex items-center gap-2"
|
||||
>
|
||||
<Play className="w-3 h-3" /> How It Works
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1 className="font-display text-[2.5rem] sm:text-[3.5rem] md:text-[4.5rem] lg:text-[5rem] leading-[0.95] tracking-[-0.03em] text-foreground">
|
||||
Turn Parked Domains Into
|
||||
<span className="block text-transparent bg-clip-text bg-gradient-to-r from-emerald-400 via-purple-400 to-emerald-400">
|
||||
Passive Income
|
||||
</span>
|
||||
</h1>
|
||||
{/* Right: Simulator */}
|
||||
<div className="lg:col-span-6 relative animate-scale-in opacity-0 mt-8 lg:mt-0" style={{ animationDelay: '1s', animationFillMode: 'forwards' }}>
|
||||
<YieldSimulator />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<p className="mt-6 text-lg sm:text-xl text-foreground-muted max-w-2xl mx-auto">
|
||||
Pounce Yield detects the intent behind your domain and routes visitors
|
||||
to relevant affiliate partners. <span className="text-foreground">You earn 70% of every lead.</span>
|
||||
{/* CORE LOGIC */}
|
||||
<section id="how-it-works" className="relative py-40 px-4 sm:px-6 bg-[#020202]">
|
||||
<div className="max-w-[1400px] mx-auto">
|
||||
{/* Section Header - Tech Style */}
|
||||
<div className="flex flex-col lg:flex-row justify-between items-end mb-24 border-b border-white/[0.08] pb-12">
|
||||
<div>
|
||||
<span className="text-accent font-mono text-xs uppercase tracking-[0.2em] mb-4 block">The Mechanism</span>
|
||||
<h2 className="font-display text-4xl sm:text-5xl lg:text-6xl text-white leading-none">
|
||||
Intent Routing™
|
||||
</h2>
|
||||
</div>
|
||||
<p className="text-white/50 max-w-md text-sm font-mono mt-8 lg:mt-0 leading-relaxed text-right">
|
||||
// REPLACING_PARKING_PAGES<br />
|
||||
// ELIMINATING_MIDDLEMEN<br />
|
||||
// MAXIMIZING_YIELD
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* CTA Buttons */}
|
||||
<div className="mt-10 flex flex-col sm:flex-row items-center justify-center gap-4">
|
||||
<Link
|
||||
href={isAuthenticated ? '/terminal/yield' : '/register?redirect=/terminal/yield'}
|
||||
className="w-full sm:w-auto inline-flex items-center justify-center gap-2 px-8 py-4
|
||||
bg-gradient-to-r from-purple-500 to-emerald-500
|
||||
text-white text-lg font-semibold rounded-xl
|
||||
hover:from-purple-400 hover:to-emerald-400 transition-all
|
||||
shadow-lg shadow-purple-500/25"
|
||||
>
|
||||
<Coins className="w-5 h-5" />
|
||||
Start Earning
|
||||
<ArrowRight className="w-5 h-5" />
|
||||
</Link>
|
||||
<button
|
||||
onClick={() => document.getElementById('demo')?.scrollIntoView({ behavior: 'smooth' })}
|
||||
className="w-full sm:w-auto inline-flex items-center justify-center gap-2 px-8 py-4
|
||||
bg-background-secondary border border-border text-foreground
|
||||
text-lg font-semibold rounded-xl hover:border-accent transition-all"
|
||||
>
|
||||
<Play className="w-5 h-5" />
|
||||
See Demo
|
||||
</button>
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-px bg-white/[0.08] border border-white/[0.08]">
|
||||
|
||||
{/* Phase 1 */}
|
||||
<div className="group relative bg-[#030303] p-10 lg:p-14 hover:bg-[#050505] transition-colors duration-500">
|
||||
<div className="absolute top-0 right-0 p-6 opacity-0 group-hover:opacity-100 transition-opacity duration-500">
|
||||
<div className="text-[10px] font-mono text-accent">PHASE_01</div>
|
||||
</div>
|
||||
|
||||
<div className="h-full flex flex-col justify-between">
|
||||
<div>
|
||||
<div className="w-16 h-16 border border-white/10 bg-white/5 flex items-center justify-center mb-10 text-white group-hover:text-accent group-hover:border-accent/50 transition-all">
|
||||
<Globe className="w-8 h-8" />
|
||||
</div>
|
||||
<h3 className="text-3xl text-white font-display mb-6">Capture</h3>
|
||||
<p className="text-white/50 leading-relaxed text-lg font-light mb-12">
|
||||
User types a generic domain (e.g. `kredit.ch`). Our DNS intercepts the request instantly. No slow redirects. No parking page ads.
|
||||
</p>
|
||||
</div>
|
||||
<div className="pt-8 border-t border-white/[0.05]">
|
||||
<div className="font-mono text-xs text-white/30 uppercase tracking-widest mb-2">Technical Execution</div>
|
||||
<div className="text-white font-mono text-sm">DNS A-Record -> Pounce Edge Node</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Trust Indicators */}
|
||||
<div className="mt-12 flex flex-wrap items-center justify-center gap-6 text-sm text-foreground-muted">
|
||||
<div className="flex items-center gap-2">
|
||||
<Shield className="w-4 h-4 text-emerald-500" />
|
||||
<span>DNS Verified</span>
|
||||
{/* Phase 2 */}
|
||||
<div className="group relative bg-[#030303] p-10 lg:p-14 hover:bg-[#050505] transition-colors duration-500">
|
||||
<div className="absolute top-0 right-0 p-6 opacity-0 group-hover:opacity-100 transition-opacity duration-500">
|
||||
<div className="text-[10px] font-mono text-accent">PHASE_02</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<DollarSign className="w-4 h-4 text-emerald-500" />
|
||||
<span>70% Revenue Share</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Globe className="w-4 h-4 text-emerald-500" />
|
||||
<span>Swiss Partners</span>
|
||||
|
||||
<div className="h-full flex flex-col justify-between">
|
||||
<div>
|
||||
<div className="w-16 h-16 border border-white/10 bg-white/5 flex items-center justify-center mb-10 text-white group-hover:text-accent group-hover:border-accent/50 transition-all">
|
||||
<Cpu className="w-8 h-8" />
|
||||
</div>
|
||||
<h3 className="text-3xl text-white font-display mb-6">Analyze</h3>
|
||||
<p className="text-white/50 leading-relaxed text-lg font-light mb-12">
|
||||
Our semantic engine analyzes the SLD (`kredit`) and TLD (`.ch`) to determine user intent: "Financial Service / Loan / Switzerland".
|
||||
</p>
|
||||
</div>
|
||||
<div className="pt-8 border-t border-white/[0.05]">
|
||||
<div className="font-mono text-xs text-white/30 uppercase tracking-widest mb-2">Processing Time</div>
|
||||
<div className="text-white font-mono text-sm">< 10ms Latency</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Phase 3 */}
|
||||
<div className="group relative bg-[#030303] p-10 lg:p-14 hover:bg-[#050505] transition-colors duration-500">
|
||||
<div className="absolute top-0 right-0 p-6 opacity-0 group-hover:opacity-100 transition-opacity duration-500">
|
||||
<div className="text-[10px] font-mono text-accent">PHASE_03</div>
|
||||
</div>
|
||||
|
||||
<div className="h-full flex flex-col justify-between">
|
||||
<div>
|
||||
<div className="w-16 h-16 border border-white/10 bg-white/5 flex items-center justify-center mb-10 text-white group-hover:text-accent group-hover:border-accent/50 transition-all">
|
||||
<Wallet className="w-8 h-8" />
|
||||
</div>
|
||||
<h3 className="text-3xl text-white font-display mb-6">Monetize</h3>
|
||||
<p className="text-white/50 leading-relaxed text-lg font-light mb-12">
|
||||
Traffic is routed to the highest-bidding partner for that vertical (e.g. Comparis). You earn a commission (CPA) on conversion.
|
||||
</p>
|
||||
</div>
|
||||
<div className="pt-8 border-t border-white/[0.05]">
|
||||
<div className="font-mono text-xs text-white/30 uppercase tracking-widest mb-2">Outcome</div>
|
||||
<div className="text-white font-mono text-sm">70% Revenue Share Payout</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Live Demo Section */}
|
||||
<section id="demo" className="relative py-20 sm:py-28 px-4 sm:px-6 bg-background-secondary/50">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<div className="text-center mb-12">
|
||||
<span className="text-sm font-semibold text-purple-400 uppercase tracking-wider">Live Demo</span>
|
||||
<h2 className="mt-4 font-display text-3xl sm:text-4xl md:text-5xl tracking-[-0.03em] text-foreground">
|
||||
Analyze Your Domain's Yield Potential
|
||||
</h2>
|
||||
</div>
|
||||
{/* ECOSYSTEM - Vertical & Partners */}
|
||||
<section className="relative py-32 px-4 sm:px-6 bg-[#050505] border-y border-white/[0.05]">
|
||||
<div className="max-w-[1400px] mx-auto grid lg:grid-cols-2 gap-20 items-center">
|
||||
<div>
|
||||
<span className="text-accent font-mono text-xs uppercase tracking-[0.2em] mb-4 block">The Ecosystem</span>
|
||||
<h2 className="font-display text-4xl sm:text-5xl text-white mb-8">Premium Verticals.</h2>
|
||||
<p className="text-white/50 text-lg leading-relaxed mb-10">
|
||||
We focus on high-ticket verticals where a single lead can be worth $50-$200. No penny-clicks. No spam.
|
||||
</p>
|
||||
|
||||
<div className="space-y-6">
|
||||
{[
|
||||
{ name: 'Finance & Insurance', cpa: '$80 - $250', examples: 'Loans, Mortgages, Health Insurance' },
|
||||
{ name: 'Legal Services', cpa: '$100 - $400', examples: 'Lawyers, Divorce, notary' },
|
||||
{ name: 'Medical & Health', cpa: '$50 - $150', examples: 'Dentists, Cosmetic Surgery, Clinics' },
|
||||
{ name: 'B2B Services', cpa: '$40 - $120', examples: 'Marketing, SaaS, Hosting' }
|
||||
].map((vertical, i) => (
|
||||
<div key={i} className="flex items-start gap-6 p-4 border border-white/5 hover:border-white/10 hover:bg-white/[0.02] transition-colors">
|
||||
<div className="w-1.5 h-1.5 bg-accent mt-2.5 shrink-0" />
|
||||
<div className="flex-1">
|
||||
<div className="flex justify-between items-center mb-1">
|
||||
<h4 className="text-white font-bold">{vertical.name}</h4>
|
||||
<span className="text-accent font-mono text-sm">{vertical.cpa} CPA</span>
|
||||
</div>
|
||||
<p className="text-white/40 text-sm">{vertical.examples}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Domain Analyzer */}
|
||||
<div className="max-w-2xl mx-auto">
|
||||
<div className="bg-background border border-border rounded-2xl p-6 sm:p-8 shadow-xl">
|
||||
<div className="flex flex-col sm:flex-row gap-4">
|
||||
<input
|
||||
type="text"
|
||||
value={analyzeDomain}
|
||||
onChange={(e) => setAnalyzeDomain(e.target.value)}
|
||||
placeholder="Enter your domain (e.g. zahnarzt-zuerich.ch)"
|
||||
className="flex-1 px-4 py-3 bg-background-secondary border border-border rounded-xl
|
||||
text-foreground placeholder:text-foreground-subtle focus:outline-none
|
||||
focus:border-accent transition-colors"
|
||||
onKeyDown={(e) => e.key === 'Enter' && handleAnalyze()}
|
||||
/>
|
||||
<button
|
||||
onClick={handleAnalyze}
|
||||
disabled={analyzing || !analyzeDomain.trim()}
|
||||
className="px-6 py-3 bg-gradient-to-r from-purple-500 to-emerald-500
|
||||
text-white font-semibold rounded-xl
|
||||
hover:from-purple-400 hover:to-emerald-400 transition-all
|
||||
disabled:opacity-50 disabled:cursor-not-allowed
|
||||
flex items-center justify-center gap-2"
|
||||
<div className="relative">
|
||||
<div className="absolute inset-0 bg-gradient-to-tr from-accent/10 to-transparent blur-3xl opacity-20" />
|
||||
<div className="bg-[#020202] border border-white/10 p-10 relative">
|
||||
<div className="absolute top-0 left-0 p-4 border-r border-b border-white/10 bg-[#050505]">
|
||||
<span className="text-[10px] font-mono text-white/30 uppercase tracking-widest">Partner Network</span>
|
||||
</div>
|
||||
|
||||
<div className="mt-8 grid grid-cols-2 gap-4">
|
||||
{[
|
||||
{ name: 'COMPARIS', initial: 'C' },
|
||||
{ name: 'AXA', initial: 'A' },
|
||||
{ name: 'HOMEGATE', initial: 'H' },
|
||||
{ name: 'SWISS LIFE', initial: 'S' },
|
||||
{ name: 'JOBS.CH', initial: 'J' },
|
||||
{ name: 'SANOTAS', initial: 'S' }
|
||||
].map((partner, i) => (
|
||||
<div key={i} className="h-24 bg-white/[0.02] border border-white/5 flex flex-col items-center justify-center hover:bg-white/[0.05] transition-all group cursor-default">
|
||||
<span className="font-display text-2xl text-white/20 group-hover:text-white transition-colors">{partner.name}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="mt-8 pt-8 border-t border-white/10 text-center">
|
||||
<p className="text-white/40 text-sm font-mono mb-4">
|
||||
Direct integrations with top-tier Swiss & EU brands.
|
||||
</p>
|
||||
<Link
|
||||
href="/contact"
|
||||
className="inline-flex items-center gap-2 text-xs font-bold uppercase tracking-widest text-white hover:text-accent transition-colors"
|
||||
>
|
||||
Become a Partner <ArrowRight className="w-3 h-3" />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* FEATURES GRID (BENTO STYLE) */}
|
||||
<section className="relative py-40 px-4 sm:px-6 bg-[#020202]">
|
||||
<div className="max-w-[1400px] mx-auto">
|
||||
<div className="mb-20">
|
||||
<span className="text-accent font-mono text-xs uppercase tracking-[0.2em] mb-4 block">System Capabilities</span>
|
||||
<h2 className="font-display text-4xl sm:text-5xl text-white">Passive by Design.</h2>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-px bg-white/[0.1] border border-white/[0.1]">
|
||||
{[
|
||||
{ icon: PieChart, title: 'Revenue Share', desc: 'Industry-leading 70/30 split. We only make money when you do.' },
|
||||
{ icon: Target, title: '20+ Verticals', desc: 'Finance, Insurance, Travel, Health, B2B Services, and more.' },
|
||||
{ icon: Shield, title: 'Swiss Partners', desc: 'Direct API integrations with premium Swiss & EU brands.' },
|
||||
{ icon: BarChart3, title: 'Live Analytics', desc: 'Real-time dashboard showing every click, lead, and conversion.' },
|
||||
{ icon: RefreshCw, title: 'Auto-Optimization', desc: 'AI automatically routes to the highest-paying partner for each visitor.' },
|
||||
{ icon: Zap, title: 'Instant DNS', desc: 'Zero downtime. Verify ownership and start earning in < 5 minutes.' }
|
||||
].map((feat, i) => (
|
||||
<div key={i} className="bg-[#030303] p-10 hover:bg-[#080808] transition-colors group">
|
||||
<feat.icon className="w-8 h-8 text-white/20 group-hover:text-accent transition-colors mb-6" />
|
||||
<h3 className="text-xl font-display text-white mb-3">{feat.title}</h3>
|
||||
<p className="text-white/40 font-mono text-sm leading-relaxed">{feat.desc}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA */}
|
||||
<section className="relative py-32 px-4 sm:px-6 border-t border-white/[0.05]">
|
||||
<div className="max-w-4xl mx-auto text-center relative z-10">
|
||||
<h2 className="font-display text-5xl sm:text-6xl text-white mb-10">
|
||||
Your portfolio is <br />
|
||||
<span className="text-white/30">sleeping on gold.</span>
|
||||
</h2>
|
||||
|
||||
{!isAuthenticated ? (
|
||||
<div className="flex flex-col items-center gap-6">
|
||||
<Link
|
||||
href="/register"
|
||||
className="px-10 py-5 bg-accent text-black text-sm font-bold uppercase tracking-[0.2em] hover:bg-white transition-all shadow-[0_0_30px_rgba(16,185,129,0.3)]"
|
||||
style={{ clipPath: 'polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px)' }}
|
||||
>
|
||||
Start Yield Farming
|
||||
</Link>
|
||||
<p className="text-white/30 font-mono text-xs uppercase tracking-widest">Free for the first 30 days</p>
|
||||
</div>
|
||||
) : (
|
||||
<Link
|
||||
href="/terminal/yield"
|
||||
className="px-10 py-5 bg-white text-black text-sm font-bold uppercase tracking-[0.2em] hover:bg-accent transition-all"
|
||||
style={{ clipPath: 'polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px)' }}
|
||||
>
|
||||
{analyzing ? (
|
||||
<>
|
||||
<div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" />
|
||||
Analyzing...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Zap className="w-4 h-4" />
|
||||
Analyze
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Analysis Result */}
|
||||
{analysis && (
|
||||
<div className="mt-8 p-6 bg-background-secondary rounded-xl border border-border">
|
||||
<div className="flex items-start justify-between mb-4">
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold text-foreground">{analysis.domain}</h3>
|
||||
<p className="text-sm text-foreground-muted capitalize">
|
||||
{analysis.intent.category.replace('_', ' ')}
|
||||
{analysis.intent.subcategory && ` / ${analysis.intent.subcategory.replace('_', ' ')}`}
|
||||
</p>
|
||||
</div>
|
||||
<span className={`px-3 py-1 rounded-full text-sm font-medium ${
|
||||
analysis.monetization_potential === 'high'
|
||||
? 'bg-emerald-500/20 text-emerald-400 border border-emerald-500/30'
|
||||
: analysis.monetization_potential === 'medium'
|
||||
? 'bg-amber-500/20 text-amber-400 border border-amber-500/30'
|
||||
: 'bg-zinc-500/20 text-zinc-400 border border-zinc-500/30'
|
||||
}`}>
|
||||
{analysis.monetization_potential.toUpperCase()} Potential
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="grid sm:grid-cols-2 gap-4">
|
||||
<div className="p-4 bg-gradient-to-br from-emerald-500/10 to-transparent rounded-xl border border-emerald-500/20">
|
||||
<p className="text-sm text-foreground-muted mb-1">Estimated Monthly Revenue</p>
|
||||
<p className="text-2xl font-bold text-emerald-400">
|
||||
{analysis.value.currency} {analysis.value.estimated_monthly_min} - {analysis.value.estimated_monthly_max}
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4 bg-background rounded-xl border border-border">
|
||||
<p className="text-sm text-foreground-muted mb-1">Intent Confidence</p>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex-1 h-2 bg-background-secondary rounded-full overflow-hidden">
|
||||
<div
|
||||
className="h-full bg-gradient-to-r from-purple-500 to-emerald-500 rounded-full"
|
||||
style={{ width: `${analysis.intent.confidence * 100}%` }}
|
||||
/>
|
||||
</div>
|
||||
<span className="text-sm font-medium text-foreground">
|
||||
{Math.round(analysis.intent.confidence * 100)}%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Keywords */}
|
||||
{analysis.intent.keywords_matched.length > 0 && (
|
||||
<div className="mt-4">
|
||||
<p className="text-sm text-foreground-muted mb-2">Detected Keywords</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{analysis.intent.keywords_matched.slice(0, 5).map((kw: string, i: number) => (
|
||||
<span key={i} className="px-2 py-1 bg-background rounded text-xs text-foreground-subtle">
|
||||
{kw.split('~')[0]}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Link
|
||||
href={isAuthenticated ? '/terminal/yield' : `/register?redirect=/terminal/yield&domain=${analysis.domain}`}
|
||||
className="mt-6 w-full inline-flex items-center justify-center gap-2 px-6 py-3
|
||||
bg-gradient-to-r from-purple-500 to-emerald-500
|
||||
text-white font-semibold rounded-xl
|
||||
hover:from-purple-400 hover:to-emerald-400 transition-all"
|
||||
>
|
||||
Activate This Domain
|
||||
<ArrowRight className="w-4 h-4" />
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Example Carousel */}
|
||||
{!analysis && (
|
||||
<div className="mt-8">
|
||||
<p className="text-sm text-foreground-muted mb-4">Examples:</p>
|
||||
<div className="space-y-2">
|
||||
{INTENT_EXAMPLES.map((ex, i) => (
|
||||
<button
|
||||
key={ex.domain}
|
||||
onClick={() => {
|
||||
setAnalyzeDomain(ex.domain)
|
||||
setSelectedExample(i)
|
||||
}}
|
||||
className={`w-full p-4 rounded-xl border text-left transition-all ${
|
||||
i === selectedExample
|
||||
? 'bg-purple-500/10 border-purple-500/30'
|
||||
: 'bg-background-secondary border-border hover:border-accent/30'
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="font-medium text-foreground">{ex.domain}</p>
|
||||
<p className="text-sm text-foreground-muted">{ex.intent}</p>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<p className={`text-sm font-medium ${
|
||||
ex.potential === 'High' ? 'text-emerald-400' : 'text-amber-400'
|
||||
}`}>
|
||||
{ex.potential}
|
||||
</p>
|
||||
<p className="text-xs text-foreground-muted">CHF {ex.revenue}/mo</p>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* How It Works */}
|
||||
<section className="relative py-20 sm:py-28 px-4 sm:px-6">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<div className="text-center mb-16">
|
||||
<span className="text-sm font-semibold text-accent uppercase tracking-wider">How It Works</span>
|
||||
<h2 className="mt-4 font-display text-3xl sm:text-4xl md:text-5xl tracking-[-0.03em] text-foreground">
|
||||
Three Steps to Passive Income
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-8">
|
||||
{/* Step 1 */}
|
||||
<div className="relative p-8 bg-background-secondary border border-border rounded-2xl">
|
||||
<div className="absolute -top-4 left-8 w-8 h-8 bg-purple-500 rounded-full flex items-center justify-center text-white font-bold">
|
||||
1
|
||||
</div>
|
||||
<div className="w-14 h-14 bg-purple-500/10 rounded-xl flex items-center justify-center mb-6">
|
||||
<Globe className="w-7 h-7 text-purple-400" />
|
||||
</div>
|
||||
<h3 className="text-xl font-semibold text-foreground mb-3">Add Your Domain</h3>
|
||||
<p className="text-foreground-muted">
|
||||
Enter any domain you own. Our AI analyzes the name and detects the
|
||||
user intent (dental, finance, travel, etc.)
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Step 2 */}
|
||||
<div className="relative p-8 bg-background-secondary border border-border rounded-2xl md:-translate-y-4">
|
||||
<div className="absolute -top-4 left-8 w-8 h-8 bg-emerald-500 rounded-full flex items-center justify-center text-white font-bold">
|
||||
2
|
||||
</div>
|
||||
<div className="w-14 h-14 bg-emerald-500/10 rounded-xl flex items-center justify-center mb-6">
|
||||
<Server className="w-7 h-7 text-emerald-400" />
|
||||
</div>
|
||||
<h3 className="text-xl font-semibold text-foreground mb-3">Point Your DNS</h3>
|
||||
<p className="text-foreground-muted">
|
||||
Update your nameservers or add a CNAME record. We verify ownership
|
||||
and activate the domain for yield.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Step 3 */}
|
||||
<div className="relative p-8 bg-background-secondary border border-border rounded-2xl">
|
||||
<div className="absolute -top-4 left-8 w-8 h-8 bg-purple-500 rounded-full flex items-center justify-center text-white font-bold">
|
||||
3
|
||||
</div>
|
||||
<div className="w-14 h-14 bg-purple-500/10 rounded-xl flex items-center justify-center mb-6">
|
||||
<DollarSign className="w-7 h-7 text-purple-400" />
|
||||
</div>
|
||||
<h3 className="text-xl font-semibold text-foreground mb-3">Earn Automatically</h3>
|
||||
<p className="text-foreground-muted">
|
||||
Visitors are routed to relevant partners. You earn 70% of every click,
|
||||
lead, or sale. Paid out monthly.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Features Grid */}
|
||||
<section className="relative py-20 sm:py-28 px-4 sm:px-6 bg-background-secondary/50">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<div className="text-center mb-16">
|
||||
<span className="text-sm font-semibold text-accent uppercase tracking-wider">Features</span>
|
||||
<h2 className="mt-4 font-display text-3xl sm:text-4xl md:text-5xl tracking-[-0.03em] text-foreground">
|
||||
Why Pounce Yield?
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{[
|
||||
{
|
||||
icon: Target,
|
||||
title: 'AI Intent Detection',
|
||||
desc: 'Our engine analyzes domain names to detect user intent across 20+ categories.',
|
||||
},
|
||||
{
|
||||
icon: Shield,
|
||||
title: 'Swiss Partners',
|
||||
desc: 'Comparis, Homegate, Jobs.ch and more. Premium partners, premium payouts.',
|
||||
},
|
||||
{
|
||||
icon: BarChart3,
|
||||
title: 'Real-Time Analytics',
|
||||
desc: 'Track clicks, conversions, and revenue in your dashboard. Full transparency.',
|
||||
},
|
||||
{
|
||||
icon: DollarSign,
|
||||
title: '70% Revenue Share',
|
||||
desc: 'The highest revenue share in the industry. You keep the lion\'s share.',
|
||||
},
|
||||
{
|
||||
icon: Zap,
|
||||
title: 'Instant Activation',
|
||||
desc: 'DNS verified in minutes. Start earning the same day.',
|
||||
},
|
||||
{
|
||||
icon: TrendingUp,
|
||||
title: 'Monthly Payouts',
|
||||
desc: 'Reliable monthly payments via Stripe or bank transfer.',
|
||||
},
|
||||
].map((feature, i) => (
|
||||
<div key={i} className="p-6 bg-background border border-border rounded-xl hover:border-accent/30 transition-all">
|
||||
<feature.icon className="w-8 h-8 text-accent mb-4" />
|
||||
<h3 className="text-lg font-semibold text-foreground mb-2">{feature.title}</h3>
|
||||
<p className="text-foreground-muted text-sm">{feature.desc}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA Section */}
|
||||
<section className="relative py-20 sm:py-28 px-4 sm:px-6">
|
||||
<div className="max-w-4xl mx-auto text-center">
|
||||
<h2 className="font-display text-3xl sm:text-4xl md:text-5xl tracking-[-0.03em] text-foreground">
|
||||
Ready to Monetize Your Domains?
|
||||
</h2>
|
||||
<p className="mt-6 text-lg text-foreground-muted max-w-2xl mx-auto">
|
||||
Join domain investors who are turning their parked domains into passive income streams.
|
||||
</p>
|
||||
<div className="mt-10">
|
||||
<Link
|
||||
href={isAuthenticated ? '/terminal/yield' : '/register?redirect=/terminal/yield'}
|
||||
className="inline-flex items-center justify-center gap-2 px-10 py-5
|
||||
bg-gradient-to-r from-purple-500 to-emerald-500
|
||||
text-white text-xl font-semibold rounded-xl
|
||||
hover:from-purple-400 hover:to-emerald-400 transition-all
|
||||
shadow-xl shadow-purple-500/25"
|
||||
>
|
||||
<Coins className="w-6 h-6" />
|
||||
Get Started Free
|
||||
<ArrowRight className="w-6 h-6" />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
Go to Dashboard
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -1,158 +1,164 @@
|
||||
'use client'
|
||||
|
||||
import Link from 'next/link'
|
||||
import { Twitter, Mail, Linkedin } from 'lucide-react'
|
||||
import Image from 'next/image'
|
||||
import { Twitter, Mail, Linkedin, ArrowRight } from 'lucide-react'
|
||||
import { useStore } from '@/lib/store'
|
||||
|
||||
export function Footer() {
|
||||
const { isAuthenticated } = useStore()
|
||||
|
||||
return (
|
||||
<footer className="relative border-t border-border bg-background-secondary/30 backdrop-blur-sm mt-auto">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 py-12 sm:py-16">
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-8 mb-12">
|
||||
{/* Brand */}
|
||||
<div className="col-span-2 md:col-span-1">
|
||||
<div className="mb-4">
|
||||
<Link href="/" className="inline-block">
|
||||
<span
|
||||
className="text-xl font-bold tracking-[0.1em] text-foreground"
|
||||
style={{ fontFamily: 'var(--font-display), Playfair Display, Georgia, serif' }}
|
||||
>
|
||||
POUNCE
|
||||
</span>
|
||||
<footer className="relative border-t border-white/10 bg-[#020202] mt-auto overflow-hidden">
|
||||
{/* Background Noise */}
|
||||
<div className="absolute inset-0 bg-[url('/noise.png')] opacity-[0.03] mix-blend-overlay pointer-events-none" />
|
||||
|
||||
<div className="max-w-[1400px] mx-auto px-4 sm:px-6 py-16 sm:py-20 relative z-10">
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 lg:grid-cols-5 gap-12 lg:gap-8 mb-16">
|
||||
|
||||
{/* Brand Column */}
|
||||
<div className="md:col-span-2 lg:col-span-2">
|
||||
<div className="mb-6">
|
||||
<Link href="/" className="inline-block group">
|
||||
<div className="flex items-center gap-3">
|
||||
<Image
|
||||
src="/pounce-puma.png"
|
||||
alt="POUNCE"
|
||||
width={40}
|
||||
height={40}
|
||||
className="object-contain opacity-80 group-hover:opacity-100 transition-opacity"
|
||||
/>
|
||||
<span
|
||||
className="text-xl font-black tracking-[0.1em] text-white group-hover:text-accent transition-colors"
|
||||
style={{ fontFamily: 'var(--font-display), sans-serif' }}
|
||||
>
|
||||
POUNCE
|
||||
</span>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
<p className="text-body-sm text-foreground-muted mb-2">
|
||||
Don't guess. Know.
|
||||
<p className="text-sm font-mono text-white/50 mb-8 max-w-sm leading-relaxed">
|
||||
Global domain intelligence for serious investors. <br/>
|
||||
Scan. Acquire. Route. Yield.
|
||||
</p>
|
||||
<p className="text-body-xs text-foreground-subtle mb-4">
|
||||
Domain intelligence for serious investors and founders.
|
||||
</p>
|
||||
<div className="flex items-center gap-3">
|
||||
|
||||
{/* Newsletter Input - Tech Style */}
|
||||
<div className="mb-8 max-w-sm">
|
||||
<label className="text-[10px] font-mono uppercase tracking-widest text-white/30 mb-2 block">Mission Briefings</label>
|
||||
<div className="flex">
|
||||
<input
|
||||
type="email"
|
||||
placeholder="ENTER_EMAIL"
|
||||
className="w-full bg-[#0A0A0A] border border-white/10 px-4 py-3 text-white font-mono text-xs placeholder:text-white/20 focus:outline-none focus:border-accent transition-all rounded-none"
|
||||
/>
|
||||
<button className="px-4 bg-white text-black hover:bg-accent transition-colors border-l border-white/10">
|
||||
<ArrowRight className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-4">
|
||||
<a
|
||||
href="https://twitter.com/pounce_domains"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="w-9 h-9 flex items-center justify-center rounded-lg bg-foreground/5 hover:bg-foreground/10 transition-colors"
|
||||
className="w-10 h-10 flex items-center justify-center border border-white/5 hover:border-white/20 hover:bg-white/5 transition-all group"
|
||||
aria-label="Twitter"
|
||||
>
|
||||
<Twitter className="w-4 h-4 text-foreground-muted" />
|
||||
<Twitter className="w-4 h-4 text-white/40 group-hover:text-white transition-colors" />
|
||||
</a>
|
||||
<a
|
||||
href="https://linkedin.com"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="w-9 h-9 flex items-center justify-center rounded-lg bg-foreground/5 hover:bg-foreground/10 transition-colors"
|
||||
className="w-10 h-10 flex items-center justify-center border border-white/5 hover:border-white/20 hover:bg-white/5 transition-all group"
|
||||
aria-label="LinkedIn"
|
||||
>
|
||||
<Linkedin className="w-4 h-4 text-foreground-muted" />
|
||||
<Linkedin className="w-4 h-4 text-white/40 group-hover:text-white transition-colors" />
|
||||
</a>
|
||||
<a
|
||||
href="mailto:hello@pounce.ch"
|
||||
className="w-9 h-9 flex items-center justify-center rounded-lg bg-foreground/5 hover:bg-foreground/10 transition-colors"
|
||||
className="w-10 h-10 flex items-center justify-center border border-white/5 hover:border-white/20 hover:bg-white/5 transition-all group"
|
||||
aria-label="Email"
|
||||
>
|
||||
<Mail className="w-4 h-4 text-foreground-muted" />
|
||||
<Mail className="w-4 h-4 text-white/40 group-hover:text-white transition-colors" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Product - Matches new navigation (gemäß pounce_public.md) */}
|
||||
<div>
|
||||
<h3 className="text-ui font-semibold text-foreground mb-4">Product</h3>
|
||||
<ul className="space-y-3">
|
||||
{/* Links Columns */}
|
||||
<div className="lg:col-span-1">
|
||||
<h3 className="text-xs font-bold uppercase tracking-[0.2em] text-white mb-6">Protocol</h3>
|
||||
<ul className="space-y-4">
|
||||
<li>
|
||||
<Link href="/market" className="text-body-sm text-foreground-muted hover:text-foreground transition-colors">
|
||||
Market
|
||||
<Link href="/acquire" className="text-sm font-mono text-white/40 hover:text-accent transition-colors flex items-center gap-2 group">
|
||||
<span className="w-1 h-1 bg-white/20 group-hover:bg-accent rounded-full transition-colors" /> Acquire
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/discover" className="text-body-sm text-foreground-muted hover:text-foreground transition-colors">
|
||||
Discover
|
||||
<Link href="/discover" className="text-sm font-mono text-white/40 hover:text-accent transition-colors flex items-center gap-2 group">
|
||||
<span className="w-1 h-1 bg-white/20 group-hover:bg-accent rounded-full transition-colors" /> Discover
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/pricing" className="text-body-sm text-foreground-muted hover:text-foreground transition-colors">
|
||||
Pricing
|
||||
<Link href="/yield" className="text-sm font-mono text-white/40 hover:text-accent transition-colors flex items-center gap-2 group">
|
||||
<span className="w-1 h-1 bg-white/20 group-hover:bg-accent rounded-full transition-colors" /> Yield
|
||||
</Link>
|
||||
</li>
|
||||
{isAuthenticated ? (
|
||||
<li>
|
||||
<Link href="/pricing" className="text-sm font-mono text-white/40 hover:text-accent transition-colors flex items-center gap-2 group">
|
||||
<span className="w-1 h-1 bg-white/20 group-hover:bg-accent rounded-full transition-colors" /> Pricing
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="lg:col-span-1">
|
||||
<h3 className="text-xs font-bold uppercase tracking-[0.2em] text-white mb-6">Intel</h3>
|
||||
<ul className="space-y-4">
|
||||
<li>
|
||||
<Link href="/briefings" className="text-sm font-mono text-white/40 hover:text-white transition-colors">Briefings</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/about" className="text-sm font-mono text-white/40 hover:text-white transition-colors">About Us</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/contact" className="text-sm font-mono text-white/40 hover:text-white transition-colors">Contact HQ</Link>
|
||||
</li>
|
||||
{!isAuthenticated && (
|
||||
<li>
|
||||
<Link href="/terminal/radar" className="text-body-sm text-accent hover:text-accent-hover transition-colors">
|
||||
Command Center
|
||||
</Link>
|
||||
</li>
|
||||
) : (
|
||||
<li>
|
||||
<Link href="/register" className="text-body-sm text-accent hover:text-accent-hover transition-colors">
|
||||
Get Started Free
|
||||
</Link>
|
||||
<Link href="/login" className="text-sm font-mono text-white/40 hover:text-white transition-colors">Login</Link>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* Resources */}
|
||||
<div>
|
||||
<h3 className="text-ui font-semibold text-foreground mb-4">Resources</h3>
|
||||
<ul className="space-y-3">
|
||||
<div className="lg:col-span-1">
|
||||
<h3 className="text-xs font-bold uppercase tracking-[0.2em] text-white mb-6">Legal</h3>
|
||||
<ul className="space-y-4">
|
||||
<li>
|
||||
<Link href="/blog" className="text-body-sm text-foreground-muted hover:text-foreground transition-colors">
|
||||
Briefings
|
||||
</Link>
|
||||
<Link href="/legal/privacy" className="text-sm font-mono text-white/40 hover:text-white transition-colors">Privacy Policy</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/about" className="text-body-sm text-foreground-muted hover:text-foreground transition-colors">
|
||||
About Us
|
||||
</Link>
|
||||
<Link href="/legal/terms" className="text-sm font-mono text-white/40 hover:text-white transition-colors">Terms of Service</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/contact" className="text-body-sm text-foreground-muted hover:text-foreground transition-colors">
|
||||
Contact
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* Legal */}
|
||||
<div>
|
||||
<h3 className="text-ui font-semibold text-foreground mb-4">Legal</h3>
|
||||
<ul className="space-y-3">
|
||||
<li>
|
||||
<Link href="/privacy" className="text-body-sm text-foreground-muted hover:text-foreground transition-colors">
|
||||
Privacy Policy
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/terms" className="text-body-sm text-foreground-muted hover:text-foreground transition-colors">
|
||||
Terms of Service
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/imprint" className="text-body-sm text-foreground-muted hover:text-foreground transition-colors">
|
||||
Imprint
|
||||
</Link>
|
||||
<Link href="/legal/imprint" className="text-sm font-mono text-white/40 hover:text-white transition-colors">Imprint</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom */}
|
||||
<div className="pt-8 border-t border-border flex flex-col sm:flex-row justify-between items-center gap-4">
|
||||
<p className="text-ui-sm text-foreground-subtle">
|
||||
© {new Date().getFullYear()} pounce.ch — All rights reserved.
|
||||
</p>
|
||||
{/* Bottom Bar */}
|
||||
<div className="pt-8 border-t border-white/10 flex flex-col sm:flex-row justify-between items-center gap-4 text-[10px] font-mono text-white/20 uppercase tracking-widest">
|
||||
<p>© {new Date().getFullYear()} POUNCE AG — ZURICH</p>
|
||||
<div className="flex items-center gap-6">
|
||||
<Link href="/privacy" className="text-ui-sm text-foreground-subtle hover:text-foreground transition-colors">
|
||||
Privacy
|
||||
</Link>
|
||||
<Link href="/terms" className="text-ui-sm text-foreground-subtle hover:text-foreground transition-colors">
|
||||
Terms
|
||||
</Link>
|
||||
<span>System Status: Online</span>
|
||||
<span>v2.0.4 [Stable]</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -40,7 +40,7 @@ export function Header() {
|
||||
// Navigation: Discover | Acquire | Yield | Pricing
|
||||
const publicNavItems = [
|
||||
{ href: '/discover', label: 'Discover', icon: TrendingUp },
|
||||
{ href: '/market', label: 'Acquire', icon: Gavel },
|
||||
{ href: '/acquire', label: 'Acquire', icon: Gavel },
|
||||
{ href: '/yield', label: 'Yield', icon: Coins },
|
||||
{ href: '/pricing', label: 'Pricing', icon: CreditCard },
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user