← back to Epstein Card
app/page.tsx
724 lines
"use client";
import VaporizeTextCycle, { Tag } from "@/components/ui/vapour-text-effect";
import { EnhancedDropdown } from "@/components/ui/enhanced-dropdown";
import { MainDropdown } from "@/components/ui/main-dropdown";
import { useState, useEffect, FormEvent } from "react";
export default function Home() {
const [isMobile, setIsMobile] = useState(false);
const [showDocument, setShowDocument] = useState(false);
const [slideToDropdowns, setSlideToDropdowns] = useState(false);
const [bgColor, setBgColor] = useState("black");
const [selectedCategory, setSelectedCategory] = useState("");
const [selectedDocument, setSelectedDocument] = useState("");
const [documentContent, setDocumentContent] = useState("");
const [interactionCount, setInteractionCount] = useState(0);
const [showStopSign, setShowStopSign] = useState(false);
const [showPoliceAlert, setShowPoliceAlert] = useState(false);
const [userIP, setUserIP] = useState("███.███.███.███");
const [userLocation, setUserLocation] = useState({
city: "████████",
state: "██",
country: "███",
police: "████████ Police Department"
});
const [redactedSelections, setRedactedSelections] = useState<Record<string, string>>({});
// Detect mobile device on mount
useEffect(() => {
setIsMobile(/iPhone|iPad|iPod|Android/i.test(navigator.userAgent));
}, []);
// Fetch user IP and location on mount
useEffect(() => {
// Auto-fetch IP and location
fetch('https://ipapi.co/json/')
.then(res => res.json())
.then(data => {
setUserIP(data.ip || "███.███.███.███");
setUserLocation({
city: data.city || "████████",
state: data.region_code || "██",
country: data.country_code || "███",
police: `${data.city || "████████"} Police Department`
});
})
.catch(() => {
// Fallback to redacted values if API fails
});
}, []);
// Remove duplicate showDocument timer since it's now handled in flash effect
// Flash red then slide to dropdowns
useEffect(() => {
const flashTimer = setTimeout(() => {
setBgColor("red");
setTimeout(() => {
setBgColor("black");
setShowDocument(true);
// Wait 1 second then auto-scroll to document section
setTimeout(() => {
setSlideToDropdowns(true);
const documentSection = document.getElementById('document-section');
if (documentSection) {
// Use instant scroll on mobile to avoid performance issues
documentSection.scrollIntoView({
behavior: isMobile ? 'instant' : 'smooth',
block: 'center'
});
}
}, 1000);
}, 500);
}, isMobile ? 2000 : 3000); // Shorter delay on mobile
return () => clearTimeout(flashTimer);
}, []);
// Track user interactions and show warnings
useEffect(() => {
if (interactionCount === 3) {
// Show stop sign after 3 interactions
setShowStopSign(true);
setTimeout(() => {
setShowStopSign(false);
setTimeout(() => {
setShowPoliceAlert(true);
setTimeout(() => {
setShowPoliceAlert(false);
}, 2000);
}, 500);
}, 500);
}
}, [interactionCount]);
const redactedOptions = {
"names": ["Prince Andrew", "Bill Clinton", "Donald Trump", "Bill Gates", "Alan Dershowitz", "Kevin Spacey", "Chris Tucker", "Stephen Hawking"],
"locations": ["Little St. James", "Palm Beach Estate", "Manhattan Mansion", "New Mexico Ranch", "Paris Apartment"],
"ages": ["14", "15", "16", "17", "barely 18"],
"amounts": ["$500,000", "$2 million", "$50 million", "$100,000", "$1 billion"],
"activities": ["massage", "entertainment", "modeling", "companionship", "tutoring"],
"organizations": ["MIT", "Clinton Foundation", "Victoria's Secret", "Harvard", "Mar-a-Lago", "Mossad", "CIA"],
"years": ["2002", "2005", "2018", "1999", "2001", "2004", "2019"],
"counts": ["26", "47", "over 100", "7", "12"]
};
const documentCategories = {
"Flight Logs (Released 2024)": [
"Lolita Express Log - Page 73 of 118",
"Passenger Manifest - Clinton Africa Trip 2002"
],
"Maxwell Trial Exhibits": [
"Government Exhibit 52 - Little Black Book",
"Exhibit 358 - Palm Beach Message Pads"
],
"Court Unsealed Jan 2024": [
"Doe v. Epstein - Deposition Pages 117-145",
"Jane Doe #3 Sworn Statement"
],
"FBI Vault Release": [
"Part 22 of 40 - Celebrity Names",
"Part 31 - Financial Transfers"
]
};
const generateFilledDocument = (template: string) => {
let filled = template;
filled = filled.replace(/████████ Express/g, redactedSelections.aircraft || "████████ Express");
filled = filled.replace(/Private Island ████████/g, `Private Island ${redactedSelections.destination || "████████"}`);
filled = filled.replace(/Ms\. ████████/g, `Ms. ${redactedSelections.person || "████████"}`);
filled = filled.replace(/Age ██/g, `Age ${redactedSelections.age || "██"}`);
filled = filled.replace(/██ cases/g, `${redactedSelections.timeframe || "██"} cases`);
filled = filled.replace(/████████ champagne/g, `${redactedSelections.substance || "████████"} champagne`);
filled = filled.replace(/████████ Communications/g, `${redactedSelections.company || "████████"} Communications`);
filled = filled.replace(/Multiple ████████/g, `Multiple ${redactedSelections.activity || "████████"}`);
filled = filled.replace(/████████ favors/g, `${redactedSelections.payment || "████████"} favors`);
filled = filled.replace(/Same day ████████/g, `Same day ${redactedSelections.service || "████████"}`);
return filled;
};
const documentContents = {
"Lolita Express Log - Page 73 of 118": `
DEPOSITION - JANE DOE #3
Case No: 18-cv-████████
Q: Who else was present during these visits?
A: I saw ████████ [TECH CEO], ████████ [POLITICIAN],
and ████████ [CELEBRITY] on different occasions.
Q: What services were you asked to provide?
A: ████████ massages and other ████████ activities.
EXHIBIT A: Flight manifest showing ██ trips
EXHIBIT B: Photos with ████████ individuals
IP: ${userIP} | Location: ${userLocation.city}
`,
"N908JE Tail Number - Caribbean Routes 2001-2005": `
FBI INTERVIEW SUMMARY - VIRGINIA GIUFFRE
Date: ██/██/2018
File #: ████████-302
SUBJECT stated she was recruited at age ██ while working
at ████████ Resort by Ghislaine Maxwell.
VICTIM identified the following individuals at
Epstein properties:
• Prince ████████ of UK - ██ encounters
• ████████ [Former President] - Seen on island
• ████████ [Law Professor] - Legal adviser
• ████████ [Modeling Agent] - Supplied girls
SUBJECT provided massage services to ████████
individuals between ages ██ and ██.
Payments received: $████████ total via ████████ accounts
Locations: NYC mansion, Palm Beach, ████████ Island,
New Mexico ranch, ████████ [FOREIGN LOCATION]
[ONGOING INVESTIGATION - DETAILS SEALED]
Access logged: ${userIP}
`,
"Passenger Manifest - Clinton Africa Trip 2002": `
PALM BEACH REPORT #████████
EVIDENCE COLLECTED:
• Message pads with ████████ girls' numbers
• Photos of ████████ minors
• School uniforms from ████████ Academy
SUSPECT'S ASSOCIATES PRESENT:
• ████████ Maxwell - Recruiter
• ████████ [POLITICIAN] - Witnessed at property
• ████████ [CELEBRITY] - Regular visitor
[CASE FORWARDED TO FBI]
`,
"Government Exhibit 52 - Little Black Book": `
BLACK BOOK ENTRY - PAGE ██
████████ [TECH BILLIONAIRE]
Island Visits: ██ confirmed
████████ [ROYAL FAMILY MEMBER]
Special Requests: Girls from ████████
████████ [FORMER PRESIDENT]
Flight Count: ██ trips on tail #████████
████████ [HOLLYWOOD DIRECTOR]
Girls supplied: ██ "actresses" aged ██-██
Total contacts in book: ████ individuals
[FBI EVIDENCE TAG #████████]
`,
"Exhibit 670 - Victim Photos (Sealed)": `
SEALED COURT DOCUMENT - CASE ██-████
Released: January 2024
DEPOSITION OF PILOT ████████
Q: Who did you fly to Epstein's properties?
A: I flew ████████ [PRESIDENT #42] at least ██ times.
████████ [BRITISH ROYAL] approximately ██ times.
████████ [ISRAELI PM] on ██ occasions.
████████ [SENATOR] regularly to ████████.
Q: Were minors present on flights?
A: Girls who appeared to be ages ██ to ██ were
frequently onboard to ████████ destinations.
Q: What did you observe?
A: ████████ activities in the cabin. Mr. Epstein
would go to the bedroom with ████████ girls.
Q: Did anyone try to stop this?
A: ████████ [SECRET SERVICE] were told to ████████.
Flight logs subpoenaed showing ████ total flights
between 1997-████.
[GRAND JURY MATERIAL - RESTRICTED]
`,
"Exhibit 358 - Palm Beach Message Pads": `
MESSAGE PAD FROM PALM BEACH ESTATE
10:30am - ████████ called, needs "massage"
Girl: ████████, Age ██
11:15am - ████████ [PRINCE] arriving
Wants ████████ type, ██ years
3:30pm - Maxwell says ████████ [PRESIDENT] needs
"Young looking" for fundraiser
7:30pm - ██ new girls from ████████ High School
recruited. Pay $████ each.
[EVIDENCE TAG #05-████████]
`
};
// Add new document content for the new categories
documentContents["Doe v. Epstein - Deposition Pages 117-145"] = `
DEPOSITION - SEALED UNTIL 2024
Q: Were you asked to recruit other girls?
A: Yes. I was paid $████ for each girl.
They had to be between ██ and ██ years old.
Q: Can you identify who participated?
A: ████████ [TECH CEO] - At least ██ times
████████ [PRINCE] - London and NYC
████████ [PRIME MINISTER] - ████████ Embassy
[CONTINUED ON SEALED PAGES]
`;
documentContents["Giuffre v. Maxwell - Settlement Details"] = `
SETTLEMENT AGREEMENT - PARTIALLY UNSEALED
Giuffre v. Maxwell, 15-cv-████████
CONFIDENTIAL SETTLEMENT TERMS:
1. Defendant ████████ Maxwell agrees to pay
$████████ to Virginia Giuffre.
2. Plaintiff identifies the following co-conspirators:
• ████████ [RETAILER CEO] - ██ incidents
• ████████ [GOVERNOR] - ████████ Island visits
• ████████ [AMBASSADOR] - Supplied ████████
• ████████ [HOLLYWOOD MOGUL] - Casting parties
3. Sealed photographs showing:
• ████████ [ROYAL] with minor at ████████
• ████████ [PRESIDENT] at Epstein mansion with ██
• ████████ [BILLIONAIRE] on island with girls aged ██-██
4. NDA covers ████████ individuals listed in Exhibit A
including but not limited to ████████ [JUSTICE],
████████ [SENATOR], and ████████ [CEO].
5. Maxwell admits facilitating meetings between Epstein
and ██ underage girls for ████████ purposes.
[FINANCIAL DETAILS REMAIN UNDER SEAL]
`;
documentContents["Jane Doe #3 Sworn Statement"] = `
SWORN AFFIDAVIT - JANE DOE #3
"I swear the following is true:
1. I was trafficked by Jeffrey Epstein from age ██ to ██.
2. I was forced to have relations with:
• ████████ [POLITICIAN] - DC and Florida
• ████████ [FOREIGN LEADER] - ████████ Embassy
3. I personally witnessed:
• ████████ [PRESIDENT] at NYC townhouse
• ████████ [PRINCE] with minors aged ██
4. Epstein recorded everything.
[SWORN BEFORE NOTARY]"
`;
documentContents["Part 22 of 40 - Celebrity Names"] = `
FBI VAULT - EPSTEIN FILE PART 22
CELEBRITY VISITORS:
████████ [A-LIST ACTOR] - ██ visits
- With girls aged ██-██ years
████████ [DIRECTOR] - ██ visits
- "Audition parties" for ████████
████████ [MUSICIAN] - ██ visits
- Private concerts for minors
[SURVEILLANCE PHOTOS CLASSIFIED]
`;
documentContents["Part 7 - Politicians & Royalty"] = `
FBI VAULT - EPSTEIN FILE PART 7 OF 40
CLASSIFIED/NOFORN
POLITICAL FIGURES UNDER INVESTIGATION:
████████ [SENATOR - D]
- ██ flights on Epstein aircraft
- Present during ████████ with minors
- Received ████████ in campaign donations
████████ [SENATOR - R]
- Island visits: ██ confirmed
- Photographed with ████████, age ██
- ████████ payments through shell company
████████ [CABINET MEMBER]
- Introduced Epstein to ████████ [WORLD LEADER]
- Facilitated visa for ████████ victims
- Received ████████ artwork as payment
████████ [ROYAL FAMILY]
- ██ documented visits to properties
- Used alias "████████" on flight logs
- Diplomatic immunity invoked ██ times
████████ [PRIME MINISTER]
- Secret meeting at ████████ Embassy
- Discussed ████████ age of consent laws
- Transferred $████████ to Epstein account
[ONGOING INVESTIGATION - NO FURTHER DISCLOSURE]
`;
documentContents["Part 31 - Financial Transfers"] = `
FBI VAULT - EPSTEIN FILE PART 31
SUSPICIOUS TRANSFERS:
$████████ from ████████ [HEDGE FUND]
Actual: Payment for ██ minors
$████████ to ████████ [MODELING AGENCY]
Actual: Recruiting girls aged ██-██
$████████ from ████████ [FOUNDATION]
Actual: Hush money for victims
TOTAL: $████████████
[TREASURY DEPT COORDINATING]
`;
const handleCategoryChange = (category: string) => {
setSelectedCategory(category);
setSelectedDocument("");
setDocumentContent("");
setInteractionCount(prev => prev + 1);
};
const handleDocumentChange = (doc: string) => {
setSelectedDocument(doc);
const content = documentContents[doc as keyof typeof documentContents] || "CLASSIFIED - ACCESS DENIED";
setDocumentContent(content);
setInteractionCount(prev => prev + 1);
};
const handleRedactedChange = (field: string, value: string) => {
setRedactedSelections(prev => ({ ...prev, [field]: value }));
if (selectedDocument) {
const updatedContent = generateFilledDocument(documentContents[selectedDocument as keyof typeof documentContents] || "");
setDocumentContent(updatedContent);
}
};
const handleGoClick = (field: string) => {
setInteractionCount(prev => prev + 1);
// Each GO button can trigger specific actions
console.log(`GO clicked for field: ${field}`);
};
const handleFormSubmit = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
setInteractionCount(prev => prev + 1);
const formData = new FormData(e.currentTarget);
try {
const response = await fetch('/api/submit', {
method: 'POST',
body: formData
});
const result = await response.json();
console.log('Form submitted:', result);
// Flash success
setBgColor("green");
setTimeout(() => setBgColor("black"), 500);
} catch (error) {
console.error('Submit error:', error);
setBgColor("red");
setTimeout(() => setBgColor("black"), 500);
}
};
const benefits = [
"Access to █████ Island",
"Private jet miles",
"VIP access to ██████ parties",
"██% off all purchases"
];
const renderDocumentWithDropdowns = (content: string) => {
// Determine which options to show based on context
const getOptionsForContext = (beforeText: string, afterText: string) => {
const context = beforeText.toLowerCase() + afterText.toLowerCase();
if (context.includes('age') || context.includes('years old') || context.includes('aged')) {
return redactedOptions.ages;
}
if (context.includes('$') || context.includes('payment') || context.includes('paid') || context.includes('money')) {
return redactedOptions.amounts;
}
if (context.includes('flight') || context.includes('times') || context.includes('visits') || context.includes('occasions')) {
return redactedOptions.counts;
}
if (context.includes('year') || context.includes('date') || /20\d\d|19\d\d/.test(context)) {
return redactedOptions.years;
}
if (context.includes('island') || context.includes('mansion') || context.includes('property') || context.includes('location')) {
return redactedOptions.locations;
}
if (context.includes('massage') || context.includes('service') || context.includes('activity')) {
return redactedOptions.activities;
}
if (context.includes('foundation') || context.includes('university') || context.includes('agency')) {
return redactedOptions.organizations;
}
// Default to names for people references
return redactedOptions.names;
};
const parts = content.split(/(████+|██)/g);
return parts.map((part, index, array) => {
if (part.match(/████+|██/)) {
const fieldKey = `field_${index}`;
const beforeText = array.slice(Math.max(0, index - 3), index).join('');
const afterText = array.slice(index + 1, Math.min(array.length, index + 4)).join('');
const options = getOptionsForContext(beforeText, afterText);
return (
<EnhancedDropdown
key={index}
options={options}
redactedText={part}
onSelect={(value) => handleRedactedChange(fieldKey, value)}
/>
);
}
return <span key={index}>{part}</span>;
});
};
return (
<main className="min-h-screen bg-black text-white overflow-x-hidden" style={{ backgroundColor: bgColor }}>
{/* Stop Sign Flash */}
{showStopSign && (
<div className="fixed inset-0 bg-red-600 z-50 flex items-center justify-center">
<div className="text-white text-[200px] font-bold animate-pulse">
🛑 STOP
</div>
</div>
)}
{/* Police Alert */}
{showPoliceAlert && (
<div className="fixed inset-0 bg-blue-900 z-50 flex items-center justify-center">
<div className="text-white text-6xl font-bold text-center animate-flash">
🚔 POLICE HAVE BEEN NOTIFIED 🚔<br/>
<span className="text-4xl">{userLocation.police}</span><br/>
<span className="text-3xl">YOUR IP: {userIP}</span>
</div>
</div>
)}
{/* Vapor Text Header */}
<div className="h-screen flex items-center justify-center relative">
<div className="absolute inset-0 bg-gradient-to-b from-black via-purple-950/20 to-black" />
<div className="relative z-10 w-full max-w-4xl px-4">
{isMobile ? (
// Simple text for mobile
<h1 className="text-6xl md:text-8xl font-extrabold text-center text-white animate-pulse">
Epstein Files
</h1>
) : (
// VaporizeTextCycle for desktop
<VaporizeTextCycle
texts={["Epstein Files"]}
font={{
fontFamily: "system-ui, -apple-system, sans-serif",
fontSize: "120px",
fontWeight: 800
}}
color="rgb(255, 255, 255)"
spread={6}
density={7}
animation={{
vaporizeDuration: 2.5,
fadeInDuration: 1.2,
waitDuration: 0.8
}}
direction="left-to-right"
alignment="center"
tag={Tag.H1}
/>
)}
<div className="mt-12 text-center">
<div className="text-4xl font-bold text-red-500 animate-pulse">
CALL NOW: 888-EPSTEIN
</div>
<div className="text-2xl text-purple-400 mt-2">
24/7 Confidential Hotline
</div>
</div>
</div>
</div>
{/* Document Section */}
{showDocument && (
<section id="document-section" className="py-20 px-4">
<div className="max-w-4xl mx-auto">
<h2 className="text-5xl font-bold text-center mb-12 text-purple-300">
Declassified File #{Math.floor(Math.random() * 9000) + 1000}
</h2>
<div className="text-center mb-8 p-4 bg-red-900/20 border-2 border-red-500 rounded-lg">
<div className="text-3xl font-bold text-red-400">
📞 888-EPSTEIN
</div>
<div className="text-xl text-gray-300">
Report Suspicious Activity
</div>
</div>
<form onSubmit={handleFormSubmit} method="POST" action="/api/submit">
<div className="mb-8 space-y-6">
<div className="flex flex-wrap gap-4 justify-center items-end">
<MainDropdown
options={Object.keys(documentCategories)}
placeholder="Select Category..."
value={selectedCategory}
onChange={handleCategoryChange}
label="📁 CLASSIFIED CATEGORIES"
/>
<button
type="button"
className="bg-gradient-to-r from-purple-600 to-pink-600 text-white px-8 py-3 rounded-lg font-bold text-xl hover:scale-105 transition-transform shadow-xl hover:shadow-purple-500/50"
onClick={() => handleGoClick('category')}
>
🔓 ACCESS
</button>
</div>
{selectedCategory && (
<div className="flex flex-wrap gap-4 justify-center items-end animate-fade-in">
<MainDropdown
options={documentCategories[selectedCategory as keyof typeof documentCategories]}
placeholder="Select Document..."
value={selectedDocument}
onChange={handleDocumentChange}
label="📄 DECLASSIFIED FILES"
/>
<button
type="button"
className="bg-gradient-to-r from-red-600 to-orange-600 text-white px-8 py-3 rounded-lg font-bold text-xl hover:scale-105 transition-transform shadow-xl hover:shadow-red-500/50"
onClick={() => handleGoClick('document')}
>
🔥 REVEAL
</button>
</div>
)}
</div>
{documentContent && (
<div className="bg-gradient-to-br from-gray-900 to-gray-800 border border-gray-700 rounded-lg p-8 shadow-2xl">
<div className="border-b border-gray-600 pb-4 mb-6">
<div className="flex justify-between items-center">
<h3 className="text-3xl font-bold text-red-400 font-mono">
CLASSIFIED DOCUMENT
</h3>
<span className="text-xl text-red-500 font-mono">
[REDACTED-{Math.floor(Math.random() * 900) + 100}]
</span>
</div>
</div>
<div className="font-mono text-xl leading-relaxed whitespace-pre-line text-gray-300">
{renderDocumentWithDropdowns(documentContent)}
</div>
<div className="mt-8 pt-4 border-t border-gray-600">
<div className="flex justify-between items-center text-xl text-gray-500">
<div>
<span>Document ID: EP-████-████-████</span>
<br />
<span>Classification: ████████</span>
</div>
<div className="flex flex-col items-end gap-3">
<button
type="submit"
className="bg-gradient-to-r from-red-600 to-red-800 text-white px-10 py-4 rounded-lg font-bold text-2xl hover:scale-105 transition-transform shadow-xl"
>
SUBMIT REPORT
</button>
<div className="text-xl text-yellow-400">
Call: 888-EPSTEIN
</div>
</div>
</div>
</div>
</div>
)}
</form>
</div>
</section>
)}
{/* Footer */}
{showDocument && (
<footer className="py-6 px-4 bg-black border-t border-purple-900/30">
<div className="max-w-4xl mx-auto text-center">
<div className="text-2xl font-bold text-yellow-500 mb-2">
HOTLINE: 888-EPSTEIN
</div>
<p className="text-sm text-gray-600">
SATIRICAL PARODY - NOT REAL DOCUMENTS
</p>
</div>
</footer>
)}
<style jsx>{`
@keyframes fade-in {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes flash {
0%, 100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
.animate-fade-in {
animation: fade-in 1s ease-out;
}
.animate-flash {
animation: flash 0.5s ease-in-out infinite;
}
`}</style>
</main>
);
}