feat: implement premium eco-futurism climate tech portal

This commit is contained in:
mstfyldz
2026-05-30 00:53:45 +03:00
parent c3944b3056
commit 44e75e50ac
22 changed files with 1920 additions and 83 deletions
+30
View File
@@ -0,0 +1,30 @@
"use client";
import React from "react";
export default function GridBackground() {
return (
<div className="absolute inset-0 w-full h-full overflow-hidden pointer-events-none z-[0]">
{/* Dynamic Ambient Glows */}
<div className="absolute top-[10%] left-[20%] w-[35vw] h-[35vw] bg-accent-emerald-dim rounded-full blur-[120px] animate-pulse-slow opacity-60" />
<div className="absolute bottom-[20%] right-[10%] w-[45vw] h-[45vw] bg-accent-cyan-dim rounded-full blur-[150px] animate-pulse-slow opacity-50" style={{ animationDelay: "2s" }} />
{/* Grid Pattern */}
<div
className="absolute inset-0 w-full h-full"
style={{
backgroundImage: `
linear-gradient(to right, rgba(13, 242, 147, 0.03) 1px, transparent 1px),
linear-gradient(to bottom, rgba(13, 242, 147, 0.03) 1px, transparent 1px)
`,
backgroundSize: "60px 60px",
}}
/>
{/* Decorative vertical lines */}
<div className="absolute left-[15%] top-0 bottom-0 w-[1px] bg-gradient-to-b from-transparent via-accent-emerald/5 to-transparent" />
<div className="absolute left-[50%] top-0 bottom-0 w-[1px] bg-gradient-to-b from-transparent via-accent-cyan/5 to-transparent" />
<div className="absolute right-[15%] top-0 bottom-0 w-[1px] bg-gradient-to-b from-transparent via-accent-emerald/5 to-transparent" />
</div>
);
}
+43
View File
@@ -0,0 +1,43 @@
"use client";
import React, { useEffect, useRef } from "react";
import Lenis from "lenis";
export default function LenisProvider({
children,
}: {
children: React.ReactNode;
}) {
const lenisRef = useRef<Lenis | null>(null);
useEffect(() => {
// Initialize Lenis
const lenis = new Lenis({
duration: 1.2,
easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
orientation: "vertical",
gestureOrientation: "vertical",
smoothWheel: true,
wheelMultiplier: 1,
touchMultiplier: 1.5,
});
lenisRef.current = lenis;
// RAF loop
function raf(time: number) {
lenis.raf(time);
requestAnimationFrame(raf);
}
requestAnimationFrame(raf);
// Bind clean-up
return () => {
lenis.destroy();
lenisRef.current = null;
};
}, []);
return <>{children}</>;
}
+15
View File
@@ -0,0 +1,15 @@
"use client";
import React from "react";
export default function NoiseOverlay() {
return (
<div
className="fixed inset-0 w-full h-full pointer-events-none z-[99999] opacity-[0.025]"
style={{
backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E")`,
backgroundRepeat: "repeat",
}}
/>
);
}
+119
View File
@@ -0,0 +1,119 @@
"use client";
import React, { useEffect, useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
const DIAGNOSTICS = [
"SOLAR PANEL DİZİLERİ SENKRONİZE EDİLİYOR...",
"RÜZGAR TRÜBİN KOMPANSATÖRLERİ DENGELENİYOR...",
"KOJENERASYON OPTİMİZASYON KATI AKTİFLEŞTİRİLİYOR...",
"YEŞİL DÖNÜŞÜM KARBON AĞI YAPILANDIRILIYOR...",
"SCENERJİ ENERJİ AKIŞI STABİL DURUMA GETİRİLDİ.",
];
export default function Preloader({ onComplete }: { onComplete: () => void }) {
const [progress, setProgress] = useState(0);
const [diagnosticText, setDiagnosticText] = useState(DIAGNOSTICS[0]);
const [isVisible, setIsVisible] = useState(true);
useEffect(() => {
let currentProgress = 0;
const duration = 2400; // 2.4 seconds total preloader time
const intervalTime = 20;
const step = 100 / (duration / intervalTime);
const timer = setInterval(() => {
currentProgress += step;
if (currentProgress >= 100) {
currentProgress = 100;
clearInterval(timer);
setTimeout(() => {
setIsVisible(false);
setTimeout(onComplete, 800); // Allow curtain reveal animation to complete
}, 500);
}
setProgress(Math.floor(currentProgress));
// Update diagnostic text based on progress
const diagIndex = Math.min(
Math.floor((currentProgress / 100) * DIAGNOSTICS.length),
DIAGNOSTICS.length - 1
);
setDiagnosticText(DIAGNOSTICS[diagIndex]);
}, intervalTime);
return () => clearInterval(timer);
}, [onComplete]);
return (
<AnimatePresence>
{isVisible && (
<motion.div
initial={{ opacity: 1 }}
exit={{
clipPath: "polygon(0 0, 100% 0, 100% 0, 0 0)",
transition: { duration: 0.8, ease: [0.76, 0, 0.24, 1] }
}}
className="fixed inset-0 w-full h-full bg-[#03070b] z-[99999] flex flex-col items-center justify-center p-6 select-none"
>
{/* Subtle decorative grid in preloader */}
<div
className="absolute inset-0 w-full h-full opacity-10 pointer-events-none"
style={{
backgroundImage: `
linear-gradient(to right, rgba(13, 242, 147, 0.05) 1px, transparent 1px),
linear-gradient(to bottom, rgba(13, 242, 147, 0.05) 1px, transparent 1px)
`,
backgroundSize: "40px 40px",
}}
/>
<div className="w-full max-w-xl flex flex-col relative z-10">
{/* Tech Logo / Icon */}
<div className="flex items-center gap-3 mb-10">
<div className="w-6 h-6 border border-accent-emerald flex items-center justify-center rounded-sm animate-spin-slow">
<div className="w-2.5 h-2.5 bg-accent-emerald" />
</div>
<span className="font-space text-lg font-bold tracking-[0.2em] text-accent-emerald uppercase">
SCENERJİ SYSTEM
</span>
<span className="ml-auto text-[10px] font-mono text-text-dim px-2 py-0.5 border border-text-dim/20 rounded-sm">
v2.6.0
</span>
</div>
{/* Diagnostic Logs */}
<div className="h-16 font-mono text-xs text-text-secondary border-l border-accent-emerald/20 pl-4 mb-8 flex flex-col justify-center">
<span className="text-[10px] text-accent-cyan tracking-wider uppercase mb-1">
[SİSTEM TEŞHİS KÜTÜPHANESİ]
</span>
<span className="animate-pulse">{diagnosticText}</span>
</div>
{/* Progress Counter & Bar */}
<div className="flex items-end justify-between font-space mb-3">
<span className="text-sm font-light text-text-secondary tracking-widest uppercase">
ENERJİ AĞI KALİBRASYONU
</span>
<span className="text-3xl font-bold text-accent-emerald tabular-nums">
{progress}%
</span>
</div>
<div className="w-full h-[2px] bg-bg-tertiary relative overflow-hidden rounded-full">
<motion.div
className="h-full bg-gradient-to-r from-accent-cyan to-accent-emerald"
style={{ width: `${progress}%` }}
/>
</div>
<div className="mt-8 flex justify-between font-mono text-[9px] text-text-dim uppercase tracking-wider">
<span>KURULUM: AYRIS TECH</span>
<span>LOKASYON: TÜRKİYE</span>
</div>
</div>
</motion.div>
)}
</AnimatePresence>
);
}