404lab 2.0.2 → 2.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,24 +1,34 @@
1
1
  "use client";
2
2
 
3
- import { motion } from "framer-motion";
3
+ import { useEffect, useState } from "react";
4
4
  import Link from "next/link";
5
+ import { Arvo } from "next/font/google";
5
6
  import { cn } from "@/components/ui/cn";
6
7
 
8
+ const arvo = Arvo({
9
+ weight: ["400", "700"],
10
+ subsets: ["latin"],
11
+ display: "swap",
12
+ });
13
+
7
14
  const StoneAge = ({ className }: { className?: string }) => {
15
+ const [mounted, setMounted] = useState(false);
16
+
17
+ useEffect(() => {
18
+ setMounted(true);
19
+ }, []);
20
+
21
+ if (!mounted) return null;
22
+
8
23
  return (
9
24
  <div
10
25
  className={cn(
11
- "min-h-screen bg-[#fcf8f0] flex flex-col items-center justify-center p-8 overflow-hidden relative font-serif",
26
+ "min-h-screen w-full bg-[#fcf8f0] flex flex-col items-center justify-center p-8 overflow-hidden relative",
27
+ arvo.className,
12
28
  className
13
29
  )}
14
30
  >
15
31
  <style jsx global>{`
16
- @import url('https://fonts.googleapis.com/css2?family=Arvo:wght@400;700&display=swap');
17
-
18
- .stone-age-font {
19
- font-family: 'Arvo', serif;
20
- }
21
-
22
32
  .paper-texture {
23
33
  background-image: url("https://www.transparenttextures.com/patterns/natural-paper.png");
24
34
  }
@@ -28,57 +38,89 @@ const StoneAge = ({ className }: { className?: string }) => {
28
38
  }
29
39
  `}</style>
30
40
 
41
+ <style jsx global>{`
42
+ @keyframes floatUp {
43
+ 0%, 100% { transform: translateY(0); }
44
+ 50% { transform: translateY(-10px); }
45
+ }
46
+
47
+ @keyframes floatUpLarge {
48
+ 0%, 100% { transform: translateY(0); }
49
+ 50% { transform: translateY(-15px); }
50
+ }
51
+
52
+ @keyframes rock {
53
+ 0%, 100% { transform: rotate(-2deg); }
54
+ 50% { transform: rotate(2deg); }
55
+ }
56
+
57
+ @keyframes fadeInUp {
58
+ from { opacity: 0; transform: translateY(30px); }
59
+ to { opacity: 1; transform: translateY(0); }
60
+ }
61
+
62
+ .animate-float-up {
63
+ animation: floatUp 6s ease-in-out infinite;
64
+ }
65
+
66
+ .animate-float-up-large {
67
+ animation: floatUpLarge 8s ease-in-out infinite;
68
+ animation-delay: 1s;
69
+ }
70
+
71
+ .animate-rock {
72
+ animation: rock 4s ease-in-out infinite;
73
+ }
74
+
75
+ .animate-fade-in-up {
76
+ animation: fadeInUp 0.8s ease-out forwards;
77
+ opacity: 0;
78
+ }
79
+ `}</style>
80
+
31
81
  <div className="absolute inset-0 paper-texture opacity-40 pointer-events-none" />
32
82
 
33
- <motion.div
34
- animate={{ y: [0, -10, 0] }}
35
- transition={{ duration: 6, repeat: Infinity, ease: "easeInOut" }}
36
- className="absolute top-20 right-[15%] opacity-10 select-none"
83
+ <div
84
+ className="absolute top-20 right-[15%] opacity-10 select-none animate-float-up"
37
85
  >
38
86
  <svg width="200" height="200" viewBox="0 0 200 200">
39
87
  <path d="M40 160 L80 40 L120 180 L160 80 L180 160 Z" fill="#4a3b2a" />
40
88
  </svg>
41
- </motion.div>
89
+ </div>
42
90
 
43
- <motion.div
44
- animate={{ y: [0, -15, 0] }}
45
- transition={{ duration: 8, repeat: Infinity, ease: "easeInOut", delay: 1 }}
46
- className="absolute bottom-20 left-[10%] opacity-10 select-none"
91
+ <div
92
+ className="absolute bottom-20 left-[10%] opacity-10 select-none animate-float-up-large"
47
93
  >
48
94
  <svg width="250" height="250" viewBox="0 0 200 200">
49
95
  <path d="M50 180 L100 20 L150 160 Z" fill="#4a3b2a" />
50
96
  </svg>
51
- </motion.div>
97
+ </div>
52
98
 
53
- <motion.div
54
- initial={{ opacity: 0, y: 30 }}
55
- animate={{ opacity: 1, y: 0 }}
56
- className="relative z-10 w-full max-w-4xl flex flex-col items-center text-center"
99
+ <div
100
+ className="relative z-10 w-full max-w-4xl flex flex-col items-center text-center animate-fade-in-up"
57
101
  >
58
102
  <div className="relative mb-8">
59
- <motion.div
60
- animate={{ rotate: [-2, 2, -2] }}
61
- transition={{ duration: 4, repeat: Infinity, ease: "easeInOut" }}
62
- className="relative z-20"
103
+ <div
104
+ className="relative z-20 animate-rock"
63
105
  >
64
106
  <img
65
107
  src="https://cdn.dribbble.com/users/285475/screenshots/2083086/dribbble_1.gif"
66
108
  alt="Stone Age Illustration"
67
- className="w-full max-w-[450px] h-auto rock-shadow rounded-3xl"
109
+ className="w-full max-w-[320px] sm:max-w-[450px] h-auto rock-shadow rounded-3xl"
68
110
  />
69
- </motion.div>
111
+ </div>
70
112
 
71
113
  <div className="absolute -bottom-6 left-1/2 -translate-x-1/2 w-[80%] h-6 bg-black opacity-[0.05] blur-xl rounded-full" />
72
114
  </div>
73
115
 
74
- <div className="stone-age-font">
75
- <h1 className="text-4xl md:text-6xl font-black text-[#4a3b2a] mb-4 uppercase tracking-tighter">
116
+ <div className="px-4">
117
+ <h1 className="text-3xl sm:text-4xl md:text-6xl font-black text-[#4a3b2a] mb-4 uppercase tracking-tighter">
76
118
  Prehistoric 404
77
119
  </h1>
78
- <p className="text-[#6b5844] text-xl md:text-2xl mb-12 max-w-xl mx-auto font-medium">
120
+ <p className="text-[#6b5844] text-lg sm:text-xl md:text-2xl mb-8 sm:mb-12 max-w-xl mx-auto font-medium">
79
121
  This endpoint hasn&apos;t been discovered yet. It&apos;s still in the early Jurassic.
80
122
  </p>
81
-
123
+
82
124
  <div className="flex flex-col sm:flex-row gap-6 items-center justify-center">
83
125
  <Link
84
126
  href="/"
@@ -91,7 +133,7 @@ const StoneAge = ({ className }: { className?: string }) => {
91
133
  </button>
92
134
  </div>
93
135
  </div>
94
- </motion.div>
136
+ </div>
95
137
 
96
138
  <div className="absolute bottom-10 w-full px-8 flex justify-between items-center text-[#4a3b2a]/20 font-bold uppercase tracking-[0.2em] text-[10px] sm:text-xs">
97
139
  <span>Pleistocene Era</span>
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { cn } from "@/components/ui/cn";
4
4
 
5
- // import Link from "next/link"; // UNCOMMENT THIS when using in your project
5
+ import Link from "next/link";
6
6
 
7
7
  const StrangerThings = ({ className }: { className?: string }) => {
8
8
  return (
@@ -88,14 +88,19 @@ const StrangerThings = ({ className }: { className?: string }) => {
88
88
  animation: slideUpFadeIn 1.5s cubic-bezier(0.16, 1, 0.3, 1) 2.5s forwards;
89
89
  }
90
90
 
91
- .quote-top { font-size: 0.875rem; font-weight: 500; }
91
+ .quote-top { font-size: 0.75rem; font-weight: 500; }
92
92
  .quote-bottom {
93
- font-size: 1.5rem;
93
+ font-size: 1.125rem;
94
94
  font-weight: 700;
95
95
  opacity: 0;
96
96
  animation: slideUpFadeIn 1.5s cubic-bezier(0.16, 1, 0.3, 1) 3s forwards;
97
97
  }
98
98
 
99
+ @media (min-width: 640px) {
100
+ .quote-top { font-size: 0.875rem; }
101
+ .quote-bottom { font-size: 1.5rem; }
102
+ }
103
+
99
104
  .cta {
100
105
  margin-top: 32px;
101
106
  padding: 12px 32px;
@@ -132,7 +137,7 @@ const StrangerThings = ({ className }: { className?: string }) => {
132
137
  >
133
138
  <svg
134
139
  className="w-[90%] sm:w-[500px] md:w-[636px] h-auto"
135
- viewBox="-100 0 536 190"
140
+ viewBox="-110 0 556 190"
136
141
  xmlns="http://www.w3.org/2000/svg"
137
142
  >
138
143
  <defs>
@@ -311,13 +316,9 @@ const StrangerThings = ({ className }: { className?: string }) => {
311
316
  </div>
312
317
 
313
318
  <div className="flex justify-center">
314
- {/* UNCOMMENT THIS when using in your project */}
315
- {/* <Link href="/" className="cta" aria-label="Go to right side up">
316
- Go to right side up
317
- </Link> */}
318
- <button className="cta" aria-label="Go to right side up">
319
+ <Link href="/" className="cta" aria-label="Go to right side up">
319
320
  Go to right side up
320
- </button>
321
+ </Link>
321
322
  </div>
322
323
  </main>
323
324
  </div>
@@ -2,10 +2,10 @@
2
2
 
3
3
  import { useEffect, useRef, useState } from "react";
4
4
  import Link from "next/link";
5
- import { motion, AnimatePresence } from "framer-motion";
5
+
6
6
  import { cn } from "@/components/ui/cn";
7
7
 
8
- const Terminal404 = ({ className }: { className?: string }) => {
8
+ const Terminal = ({ className }: { className?: string }) => {
9
9
  const canvasRef = useRef<HTMLCanvasElement>(null);
10
10
  const [displayText, setDisplayText] = useState("");
11
11
  const [isDecrypted, setIsDecrypted] = useState(false);
@@ -88,6 +88,18 @@ const Terminal404 = ({ className }: { className?: string }) => {
88
88
  className
89
89
  )}
90
90
  >
91
+ <style jsx global>{`
92
+ @keyframes fadeInScale {
93
+ from { opacity: 0; transform: scale(0.9); }
94
+ to { opacity: 1; transform: scale(1); }
95
+ }
96
+
97
+ .animate-fade-in-scale {
98
+ animation: fadeInScale 0.6s ease-out forwards;
99
+ opacity: 0;
100
+ }
101
+ `}</style>
102
+
91
103
  <canvas
92
104
  ref={canvasRef}
93
105
  className="absolute inset-0 z-0 opacity-20 pointer-events-none"
@@ -95,10 +107,8 @@ const Terminal404 = ({ className }: { className?: string }) => {
95
107
 
96
108
  <div className="absolute inset-0 z-1 pointer-events-none bg-[radial-gradient(circle_at_center,_transparent_0%,_rgba(0,0,0,0.8)_100%)]" />
97
109
 
98
- <motion.div
99
- initial={{ opacity: 0, scale: 0.9 }}
100
- animate={{ opacity: 1, scale: 1 }}
101
- className="z-10 w-full max-w-4xl bg-black/40 backdrop-blur-sm border border-[#0f0]/20 p-8 sm:p-12 rounded-lg shadow-[0_0_50px_rgba(0,255,0,0.1)] relative overflow-hidden group"
110
+ <div
111
+ className="z-10 w-full max-w-4xl bg-black/40 backdrop-blur-sm border border-[#0f0]/20 p-8 sm:p-12 rounded-lg shadow-[0_0_50px_rgba(0,255,0,0.1)] relative overflow-hidden group animate-fade-in-scale"
102
112
  >
103
113
  <div className="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-transparent via-[#0f0]/40 to-transparent" />
104
114
 
@@ -107,11 +117,11 @@ const Terminal404 = ({ className }: { className?: string }) => {
107
117
  System Status: Breach Detected
108
118
  </div>
109
119
 
110
- <h1 className="text-3xl sm:text-6xl font-bold text-[#0f0] mb-6 tracking-tighter drop-shadow-[0_0_15px_rgba(0,255,0,0.5)] min-h-[1.2em]">
120
+ <h1 className="text-2xl xs:text-3xl sm:text-6xl font-bold text-[#0f0] mb-4 sm:mb-6 tracking-tighter drop-shadow-[0_0_15px_rgba(0,255,0,0.5)] min-h-[1.2em] break-all">
111
121
  {displayText}
112
122
  </h1>
113
123
 
114
- <p className="text-[#0f0]/80 text-lg sm:text-xl md:text-2xl mb-12 max-w-2xl leading-relaxed">
124
+ <p className="text-[#0f0]/80 text-base sm:text-lg md:text-xl lg:text-2xl mb-8 sm:mb-12 max-w-2xl leading-relaxed">
115
125
  The node you are attempting to ping is non-responsive.
116
126
  The packets have been lost in the digital aether.
117
127
  </p>
@@ -137,7 +147,7 @@ const Terminal404 = ({ className }: { className?: string }) => {
137
147
  </div>
138
148
 
139
149
  <div className="absolute bottom-0 left-0 w-full h-[1px] bg-gradient-to-r from-transparent via-[#0f0]/20 to-transparent" />
140
- </motion.div>
150
+ </div>
141
151
 
142
152
  <div className="absolute bottom-6 right-6 text-[#0f0]/20 text-sm italic pointer-events-none">
143
153
  root@void:/# _
@@ -146,5 +156,5 @@ const Terminal404 = ({ className }: { className?: string }) => {
146
156
  );
147
157
  };
148
158
 
149
- export default Terminal404;
159
+ export default Terminal;
150
160
 
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { motion } from "framer-motion";
3
+
4
4
  import Link from "next/link";
5
5
  import { cn } from "@/components/ui/cn";
6
6
  import { useEffect, useState } from "react";
@@ -13,7 +13,7 @@ const allLogs = [
13
13
  ];
14
14
 
15
15
  const Vercel = ({ className }: { className?: string }) => {
16
- const [logs, setLogs] = useState<{ text: string, time: string }[]>([]);
16
+ const [logs, setLogs] = useState<{ text: string; time: string }[]>([]);
17
17
  const [mounted, setMounted] = useState(false);
18
18
 
19
19
  useEffect(() => {
@@ -21,8 +21,11 @@ const Vercel = ({ className }: { className?: string }) => {
21
21
  let i = 0;
22
22
  const interval = setInterval(() => {
23
23
  if (i < allLogs.length) {
24
- const time = new Date().toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' });
25
- setLogs(prev => [...prev, { text: allLogs[i], time }]);
24
+ const now = new Date();
25
+ const time = now.getHours().toString().padStart(2, '0') + ':' +
26
+ now.getMinutes().toString().padStart(2, '0') + ':' +
27
+ now.getSeconds().toString().padStart(2, '0');
28
+ setLogs((prev) => [...prev, { text: allLogs[i], time }]);
26
29
  i++;
27
30
  } else {
28
31
  clearInterval(interval);
@@ -31,43 +34,90 @@ const Vercel = ({ className }: { className?: string }) => {
31
34
  return () => clearInterval(interval);
32
35
  }, []);
33
36
 
37
+ if (!mounted) return null;
38
+
34
39
  return (
35
40
  <div
36
41
  className={cn(
37
- "min-h-screen bg-black text-white flex flex-col items-center justify-center p-8 overflow-hidden font-sans relative",
42
+ "min-h-screen w-full bg-black text-white flex flex-col items-center justify-center p-8 overflow-hidden font-sans relative",
38
43
  className
39
44
  )}
40
45
  >
46
+ <style jsx global>{`
47
+ @keyframes fadeIn {
48
+ from { opacity: 0; }
49
+ to { opacity: 1; }
50
+ }
51
+
52
+ @keyframes fadeInUp {
53
+ from { opacity: 0; transform: translateY(10px); }
54
+ to { opacity: 1; transform: translateY(0); }
55
+ }
56
+
57
+ @keyframes fadeInRight {
58
+ from { opacity: 0; transform: translateX(-5px); }
59
+ to { opacity: 1; transform: translateX(0); }
60
+ }
61
+
62
+ @keyframes scaleIn {
63
+ from { opacity: 0; transform: scale(0.8); }
64
+ to { opacity: 1; transform: scale(1); }
65
+ }
66
+
67
+ @keyframes blink {
68
+ 0%, 100% { opacity: 1; }
69
+ 50% { opacity: 0; }
70
+ }
71
+
72
+ .animate-fade-in {
73
+ animation: fadeIn 0.5s ease-out forwards;
74
+ }
75
+
76
+ .animate-fade-in-up {
77
+ animation: fadeInUp 0.5s ease-out forwards;
78
+ opacity: 0;
79
+ }
80
+
81
+ .animate-fade-in-right {
82
+ animation: fadeInRight 0.3s ease-out forwards;
83
+ opacity: 0;
84
+ }
85
+
86
+ .animate-scale-in {
87
+ animation: scaleIn 0.5s ease-out forwards;
88
+ opacity: 0;
89
+ }
90
+
91
+ .animate-blink {
92
+ animation: blink 0.8s infinite;
93
+ }
94
+
95
+ .delay-200 { animation-delay: 200ms; }
96
+ `}</style>
97
+
41
98
  <div className="absolute inset-0 z-0 opacity-20 [background-image:radial-gradient(#333_1px,transparent_1px)] [background-size:40px_40px]" />
42
99
 
43
100
  <div className="relative z-10 w-full max-w-2xl flex flex-col items-center">
44
- <motion.div
45
- initial={{ opacity: 0, scale: 0.8 }}
46
- animate={{ opacity: 1, scale: 1 }}
47
- transition={{ duration: 0.5 }}
48
- className="mb-16"
101
+ <div
102
+ className="mb-16 animate-scale-in"
49
103
  >
50
104
  <svg width="80" height="80" viewBox="0 0 75 65" fill="none">
51
105
  <path d="M37.5 0L75 65H0L37.5 0Z" fill="white" />
52
106
  </svg>
53
- </motion.div>
107
+ </div>
54
108
 
55
- <div className="text-center mb-16">
56
- <motion.h1
57
- initial={{ opacity: 0, y: 10 }}
58
- animate={{ opacity: 1, y: 0 }}
59
- className="text-8xl sm:text-9xl font-bold tracking-tighter mb-4"
109
+ <div className="text-center mb-8 sm:mb-16">
110
+ <h1
111
+ className="text-7xl sm:text-9xl font-bold tracking-tighter mb-4 animate-fade-in-up"
60
112
  >
61
113
  404
62
- </motion.h1>
63
- <motion.p
64
- initial={{ opacity: 0 }}
65
- animate={{ opacity: 1 }}
66
- transition={{ delay: 0.2 }}
67
- className="text-gray-400 text-lg sm:text-xl font-medium"
114
+ </h1>
115
+ <p
116
+ className="text-gray-400 text-base sm:text-xl font-medium animate-fade-in delay-200 px-4"
117
+ style={{ opacity: 0, animationFillMode: 'forwards' }}
68
118
  >
69
119
  This deployment could not be found.
70
- </motion.p>
120
+ </p>
71
121
  </div>
72
122
 
73
123
  <div className="w-full bg-[#111] border border-white/10 rounded-lg p-6 font-mono text-sm mb-12 shadow-2xl">
@@ -78,23 +128,19 @@ const Vercel = ({ className }: { className?: string }) => {
78
128
  </div>
79
129
  <div className="space-y-2">
80
130
  {logs.map((log, i) => (
81
- <motion.div
131
+ <div
82
132
  key={i}
83
- initial={{ opacity: 0, x: -5 }}
84
- animate={{ opacity: 1, x: 0 }}
85
133
  className={cn(
86
- "flex gap-4",
134
+ "flex gap-4 animate-fade-in-right",
87
135
  log.text.includes("Error") || log.text.includes("failed") ? "text-red-400" : "text-gray-400"
88
136
  )}
89
137
  >
90
138
  <span className="text-gray-600">[{log.time}]</span>
91
139
  <span>{log.text}</span>
92
- </motion.div>
140
+ </div>
93
141
  ))}
94
- <motion.span
95
- animate={{ opacity: [1, 0] }}
96
- transition={{ repeat: Infinity, duration: 0.8 }}
97
- className="inline-block w-2 h-4 bg-white/40 ml-1"
142
+ <span
143
+ className="inline-block w-2 h-4 bg-white/40 ml-1 animate-blink"
98
144
  />
99
145
  </div>
100
146
  </div>