|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>Luminous Portfolio</title> |
|
|
<script src="https://cdn.tailwindcss.com"></script> |
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> |
|
|
<script src="https://cdn.jsdelivr.net/npm/gsap@3.11.4/dist/gsap.min.js"></script> |
|
|
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script> |
|
|
<style> |
|
|
@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700&family=Inter:wght@300;400;600&display=swap'); |
|
|
|
|
|
:root { |
|
|
--primary-bg: linear-gradient(135deg, #fff9f0 0%, #f0fff9 100%); |
|
|
--text-primary: #333; |
|
|
--text-secondary: #555; |
|
|
} |
|
|
|
|
|
body { |
|
|
font-family: 'Inter', sans-serif; |
|
|
background: var(--primary-bg); |
|
|
color: var(--text-primary); |
|
|
margin: 0; |
|
|
padding: 0; |
|
|
overflow-x: hidden; |
|
|
cursor: default; |
|
|
min-height: 100vh; |
|
|
} |
|
|
|
|
|
.hero-text { |
|
|
font-family: 'Playfair Display', serif; |
|
|
text-shadow: 0 2px 10px rgba(0,0,0,0.1); |
|
|
font-size: clamp(2.5rem, 8vw, 4.5rem); |
|
|
line-height: 1.2; |
|
|
} |
|
|
|
|
|
.glass-card { |
|
|
backdrop-filter: blur(16px); |
|
|
background: rgba(255, 255, 255, 0.2); |
|
|
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.1); |
|
|
border: 1px solid rgba(255, 255, 255, 0.18); |
|
|
} |
|
|
|
|
|
.floating { |
|
|
animation: floating 6s ease-in-out infinite; |
|
|
} |
|
|
|
|
|
@keyframes floating { |
|
|
0% { transform: translateY(0px); } |
|
|
50% { transform: translateY(-15px); } |
|
|
100% { transform: translateY(0px); } |
|
|
} |
|
|
|
|
|
#canvas-container { |
|
|
position: fixed; |
|
|
top: 0; |
|
|
left: 0; |
|
|
width: 100%; |
|
|
height: 100%; |
|
|
z-index: -1; |
|
|
pointer-events: none; |
|
|
} |
|
|
|
|
|
.project-tile { |
|
|
transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); |
|
|
transform-style: preserve-3d; |
|
|
} |
|
|
|
|
|
.project-tile:hover { |
|
|
transform: translateY(-10px) rotateX(5deg); |
|
|
box-shadow: 0 20px 40px rgba(0,0,0,0.1); |
|
|
} |
|
|
|
|
|
.nav-sphere { |
|
|
transition: all 0.3s ease; |
|
|
box-shadow: 0 0 0 0 rgba(255,255,255,0.7); |
|
|
} |
|
|
|
|
|
.nav-sphere:hover { |
|
|
transform: scale(1.1); |
|
|
box-shadow: 0 0 0 8px rgba(255,255,255,0.3); |
|
|
} |
|
|
|
|
|
.btn-spring { |
|
|
transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); |
|
|
} |
|
|
|
|
|
.btn-spring:hover { |
|
|
transform: translateY(-3px); |
|
|
box-shadow: 0 10px 20px rgba(0,0,0,0.1); |
|
|
} |
|
|
|
|
|
.ribbon-text { |
|
|
background: linear-gradient(90deg, #ffd6e0 0%, #c8f7f4 100%); |
|
|
-webkit-background-clip: text; |
|
|
-webkit-text-fill-color: transparent; |
|
|
} |
|
|
|
|
|
|
|
|
@media (max-width: 768px) { |
|
|
.nav-spheres { |
|
|
bottom: 20px; |
|
|
right: 50%; |
|
|
transform: translateX(50%); |
|
|
flex-direction: row; |
|
|
gap: 12px; |
|
|
} |
|
|
|
|
|
.nav-sphere { |
|
|
width: 10vw; |
|
|
height: 10vw; |
|
|
min-width: 40px; |
|
|
min-height: 40px; |
|
|
} |
|
|
|
|
|
.project-tile { |
|
|
max-width: 100%; |
|
|
} |
|
|
|
|
|
#hero { |
|
|
padding-top: 20vh; |
|
|
padding-bottom: 20vh; |
|
|
} |
|
|
|
|
|
.hero-subtext { |
|
|
font-size: clamp(1rem, 4vw, 1.5rem); |
|
|
} |
|
|
|
|
|
.section-padding { |
|
|
padding: 5rem 1.5rem; |
|
|
} |
|
|
|
|
|
.contact-form { |
|
|
padding: 1.5rem; |
|
|
} |
|
|
} |
|
|
|
|
|
@media (max-width: 480px) { |
|
|
.keyword-tag { |
|
|
font-size: 0.8rem; |
|
|
padding: 0.4rem 0.8rem; |
|
|
} |
|
|
|
|
|
.project-tile h3 { |
|
|
font-size: 1.2rem; |
|
|
} |
|
|
|
|
|
.project-tile p { |
|
|
font-size: 0.9rem; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
html { |
|
|
font-size: 16px; |
|
|
} |
|
|
|
|
|
@media (min-width: 600px) { |
|
|
html { |
|
|
font-size: 18px; |
|
|
} |
|
|
} |
|
|
|
|
|
@media (min-width: 900px) { |
|
|
html { |
|
|
font-size: 20px; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@media (hover: none) { |
|
|
.project-tile:hover { |
|
|
transform: none; |
|
|
} |
|
|
|
|
|
.btn-spring:hover { |
|
|
transform: none; |
|
|
} |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body> |
|
|
|
|
|
<div id="canvas-container"></div> |
|
|
|
|
|
|
|
|
<div class="fixed right-8 top-1/2 transform -translate-y-1/2 flex flex-col space-y-4 z-50 nav-spheres md:flex"> |
|
|
<div class="nav-sphere w-12 h-12 rounded-full bg-gradient-to-br from-pink-100 to-teal-100 border border-white cursor-pointer flex items-center justify-center shadow-lg" data-section="hero"></div> |
|
|
<div class="nav-sphere w-12 h-12 rounded-full bg-gradient-to-br from-yellow-100 to-blue-100 border border-white cursor-pointer flex items-center justify-center shadow-lg" data-section="projects"></div> |
|
|
<div class="nav-sphere w-12 h-12 rounded-full bg-gradient-to-br from-purple-100 to-green-100 border border-white cursor-pointer flex items-center justify-center shadow-lg" data-section="gallery"></div> |
|
|
<div class="nav-sphere w-12 h-12 rounded-full bg-gradient-to-br from-red-100 to-indigo-100 border border-white cursor-pointer flex items-center justify-center shadow-lg" data-section="contact"></div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<section id="hero" class="min-h-screen flex flex-col justify-center items-center px-4 sm:px-8 relative overflow-hidden section-padding"> |
|
|
<div class="max-w-4xl mx-auto text-center z-10"> |
|
|
<h1 class="hero-text text-5xl md:text-7xl font-bold mb-4 md:mb-6 text-gray-800">Hello, I'm <span class="ribbon-text">Alex</span></h1> |
|
|
<p class="hero-subtext text-xl md:text-2xl text-gray-600 mb-8 md:mb-12 max-w-2xl mx-auto">Creating digital experiences with <span class="font-semibold">trust</span>, <span class="font-semibold">understanding</span>, and <span class="font-semibold">creativity</span></p> |
|
|
|
|
|
<div class="flex flex-wrap justify-center gap-3 mb-8 md:mb-16"> |
|
|
<div class="px-4 py-2 md:px-6 md:py-3 glass-card rounded-full text-gray-700 font-medium keyword-tag">Hardworking</div> |
|
|
<div class="px-4 py-2 md:px-6 md:py-3 glass-card rounded-full text-gray-700 font-medium keyword-tag">Willingness</div> |
|
|
<div class="px-4 py-2 md:px-6 md:py-3 glass-card rounded-full text-gray-700 font-medium keyword-tag">Dedication</div> |
|
|
</div> |
|
|
|
|
|
<button class="btn-spring px-6 py-3 md:px-8 md:py-4 bg-white rounded-full text-gray-800 font-semibold shadow-lg flex items-center mx-auto"> |
|
|
<span class="text-sm md:text-base">Explore My Work</span> |
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 md:h-5 md:w-5 ml-2" viewBox="0 0 20 20" fill="currentColor"> |
|
|
<path fill-rule="evenodd" d="M10.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L12.586 11H5a1 1 0 110-2h7.586l-2.293-2.293a1 1 0 010-1.414z" clip-rule="evenodd" /> |
|
|
</svg> |
|
|
</button> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div id="keywords-container" class="absolute inset-0 pointer-events-none"></div> |
|
|
</section> |
|
|
|
|
|
|
|
|
<section id="projects" class="min-h-screen py-12 md:py-20 px-4 sm:px-8 relative section-padding"> |
|
|
<div class="max-w-6xl mx-auto"> |
|
|
<h2 class="text-3xl md:text-4xl font-bold text-center mb-8 md:mb-16 text-gray-800">Featured Projects</h2> |
|
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 md:gap-8"> |
|
|
|
|
|
<div class="project-tile bg-white rounded-xl md:rounded-2xl overflow-hidden shadow-lg md:shadow-xl"> |
|
|
<div class="h-40 md:h-48 bg-gradient-to-r from-pink-100 to-purple-100 flex items-center justify-center"> |
|
|
<div class="text-4xl md:text-5xl">🌐</div> |
|
|
</div> |
|
|
<div class="p-4 md:p-6"> |
|
|
<h3 class="text-lg md:text-xl font-bold mb-2">Interactive Web Portal</h3> |
|
|
<p class="text-sm md:text-base text-gray-600 mb-3 md:mb-4">A responsive platform with real-time data visualization and user engagement features.</p> |
|
|
<div class="flex flex-wrap gap-1 md:gap-2 mb-3 md:mb-4"> |
|
|
<span class="text-xs px-2 py-1 md:px-3 md:py-1 bg-pink-100 text-pink-800 rounded-full">React</span> |
|
|
<span class="text-xs px-2 py-1 md:px-3 md:py-1 bg-blue-100 text-blue-800 rounded-full">Three.js</span> |
|
|
<span class="text-xs px-2 py-1 md:px-3 md:py-1 bg-green-100 text-green-800 rounded-full">Node.js</span> |
|
|
</div> |
|
|
<button class="text-xs md:text-sm font-medium text-pink-600 hover:text-pink-800">View Case Study →</button> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="project-tile bg-white rounded-xl md:rounded-2xl overflow-hidden shadow-lg md:shadow-xl"> |
|
|
<div class="h-40 md:h-48 bg-gradient-to-r from-blue-100 to-teal-100 flex items-center justify-center"> |
|
|
<div class="text-4xl md:text-5xl">📱</div> |
|
|
</div> |
|
|
<div class="p-4 md:p-6"> |
|
|
<h3 class="text-lg md:text-xl font-bold mb-2">Mobile Experience</h3> |
|
|
<p class="text-sm md:text-base text-gray-600 mb-3 md:mb-4">An award-winning mobile app with gesture-based navigation and AR features.</p> |
|
|
<div class="flex flex-wrap gap-1 md:gap-2 mb-3 md:mb-4"> |
|
|
<span class="text-xs px-2 py-1 md:px-3 md:py-1 bg-purple-100 text-purple-800 rounded-full">Swift</span> |
|
|
<span class="text-xs px-2 py-1 md:px-3 md:py-1 bg-yellow-100 text-yellow-800 rounded-full">ARKit</span> |
|
|
<span class="text-xs px-2 py-1 md:px-3 md:py-1 bg-red-100 text-red-800 rounded-full">Firebase</span> |
|
|
</div> |
|
|
<button class="text-xs md:text-sm font-medium text-blue-600 hover:text-blue-800">View Case Study →</button> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="project-tile bg-white rounded-xl md:rounded-2xl overflow-hidden shadow-lg md:shadow-xl"> |
|
|
<div class="h-40 md:h-48 bg-gradient-to-r from-yellow-100 to-orange-100 flex items-center justify-center"> |
|
|
<div class="text-4xl md:text-5xl">🎨</div> |
|
|
</div> |
|
|
<div class="p-4 md:p-6"> |
|
|
<h3 class="text-lg md:text-xl font-bold mb-2">Generative Art</h3> |
|
|
<p class="text-sm md:text-base text-gray-600 mb-3 md:mb-4">An interactive installation that creates unique visual patterns based on user input.</p> |
|
|
<div class="flex flex-wrap gap-1 md:gap-2 mb-3 md:mb-4"> |
|
|
<span class="text-xs px-2 py-1 md:px-3 md:py-1 bg-indigo-100 text-indigo-800 rounded-full">p5.js</span> |
|
|
<span class="text-xs px-2 py-1 md:px-3 md:py-1 bg-green-100 text-green-800 rounded-full">WebGL</span> |
|
|
<span class="text-xs px-2 py-1 md:px-3 md:py-1 bg-pink-100 text-pink-800 rounded-full">GSAP</span> |
|
|
</div> |
|
|
<button class="text-xs md:text-sm font-medium text-orange-600 hover:text-orange-800">View Case Study →</button> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</section> |
|
|
|
|
|
|
|
|
<section id="gallery" class="min-h-screen py-12 md:py-20 px-4 sm:px-8 bg-white bg-opacity-50 relative section-padding"> |
|
|
<div class="max-w-6xl mx-auto"> |
|
|
<h2 class="text-3xl md:text-4xl font-bold text-center mb-8 md:mb-16 text-gray-800">Creative Explorations</h2> |
|
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 md:gap-8 mb-8 md:mb-12"> |
|
|
<div class="glass-card rounded-2xl md:rounded-3xl p-4 md:p-8"> |
|
|
<h3 class="text-xl md:text-2xl font-bold mb-3 md:mb-4 text-gray-800">Sculpture Garden</h3> |
|
|
<p class="text-sm md:text-base text-gray-600 mb-4 md:mb-6">Interactive 3D frames that reveal layered illustrations when manipulated. Each piece responds to user interaction with subtle physics and sound.</p> |
|
|
<div class="h-48 md:h-64 bg-gradient-to-r from-green-100 to-blue-100 rounded-xl md:rounded-2xl flex items-center justify-center"> |
|
|
<div class="text-3xl md:text-4xl">🖼️</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="glass-card rounded-2xl md:rounded-3xl p-4 md:p-8"> |
|
|
<h3 class="text-xl md:text-2xl font-bold mb-3 md:mb-4 text-gray-800">Generative Systems</h3> |
|
|
<p class="text-sm md:text-base text-gray-600 mb-4 md:mb-6">Algorithmic compositions that evolve over time, creating unique visual and auditory experiences based on mathematical patterns.</p> |
|
|
<div class="h-48 md:h-64 bg-gradient-to-r from-purple-100 to-pink-100 rounded-xl md:rounded-2xl flex items-center justify-center"> |
|
|
<div class="text-3xl md:text-4xl">🌀</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="text-center mt-8 md:mt-12"> |
|
|
<button class="btn-spring px-6 py-3 md:px-8 md:py-4 bg-white rounded-full text-gray-800 font-semibold shadow-lg flex items-center mx-auto"> |
|
|
<span class="text-sm md:text-base">View Full Gallery</span> |
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 md:h-5 md:w-5 ml-2" viewBox="0 0 20 20" fill="currentColor"> |
|
|
<path fill-rule="evenodd" d="M10.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L12.586 11H5a1 1 0 110-2h7.586l-2.293-2.293a1 1 0 010-1.414z" clip-rule="evenodd" /> |
|
|
</svg> |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
</section> |
|
|
|
|
|
|
|
|
<section id="contact" class="min-h-screen py-12 md:py-20 px-4 sm:px-8 relative section-padding"> |
|
|
<div class="max-w-4xl mx-auto text-center"> |
|
|
<h2 class="text-3xl md:text-4xl font-bold mb-4 md:mb-6 text-gray-800">Let's Build <span class="ribbon-text">Together</span></h2> |
|
|
<p class="text-lg md:text-xl text-gray-600 mb-8 md:mb-12 max-w-2xl mx-auto">I'm always excited to collaborate on meaningful projects that push creative boundaries.</p> |
|
|
|
|
|
<div class="glass-card rounded-2xl md:rounded-3xl p-4 md:p-8 lg:p-12 max-w-2xl mx-auto contact-form"> |
|
|
<form class="space-y-4 md:space-y-6"> |
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 md:gap-6"> |
|
|
<div> |
|
|
<label for="name" class="block text-left text-sm md:text-base text-gray-700 mb-1 md:mb-2">Name</label> |
|
|
<input type="text" id="name" class="w-full px-3 py-2 md:px-4 md:py-3 rounded-lg border border-gray-200 focus:outline-none focus:ring-2 focus:ring-pink-200 text-sm md:text-base"> |
|
|
</div> |
|
|
<div> |
|
|
<label for="email" class="block text-left text-sm md:text-base text-gray-700 mb-1 md:mb-2">Email</label> |
|
|
<input type="email" id="email" class="w-full px-3 py-2 md:px-4 md:py-3 rounded-lg border border-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-200 text-sm md:text-base"> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div> |
|
|
<label for="message" class="block text-left text-sm md:text-base text-gray-700 mb-1 md:mb-2">Message</label> |
|
|
<textarea id="message" rows="4" class="w-full px-3 py-2 md:px-4 md:py-3 rounded-lg border border-gray-200 focus:outline-none focus:ring-2 focus:ring-teal-200 text-sm md:text-base"></textarea> |
|
|
</div> |
|
|
|
|
|
<button type="submit" class="btn-spring w-full md:w-auto px-6 py-3 md:px-8 md:py-4 bg-gradient-to-r from-pink-400 to-blue-400 text-white font-semibold rounded-full shadow-lg text-sm md:text-base"> |
|
|
Send Message |
|
|
</button> |
|
|
</form> |
|
|
</div> |
|
|
|
|
|
<div class="mt-8 md:mt-16 flex justify-center space-x-4 md:space-x-6"> |
|
|
<a href="#" class="text-gray-600 hover:text-pink-500"> |
|
|
<svg class="w-5 h-5 md:w-6 md:h-6" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"> |
|
|
<path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd" /> |
|
|
</svg> |
|
|
</a> |
|
|
<a href="#" class="text-gray-600 hover:text-blue-500"> |
|
|
<svg class="w-5 h-5 md:w-6 md:h-6" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"> |
|
|
<path d="M8.29 20.251c7.547 0 11.675-6.253 11.675-11.675 0-.178 0-.355-.012-.53A8.348 8.348 0 0022 5.92a8.19 8.19 0 01-2.357.646 4.118 4.118 0 001.804-2.27 8.224 8.224 0 01-2.605.996 4.107 4.107 0 00-6.993 3.743 11.65 11.65 0 01-8.457-4.287 4.106 4.106 0 001.27 5.477A4.072 4.072 0 012.8 9.713v.052a4.105 4.105 0 003.292 4.022 4.095 4.095 0 01-1.853.07 4.108 4.108 0 003.834 2.85A8.233 8.233 0 012 18.407a11.616 11.616 0 006.29 1.84" /> |
|
|
</svg> |
|
|
</a> |
|
|
<a href="#" class="text-gray-600 hover:text-orange-500"> |
|
|
<svg class="w-5 h-5 md:w-6 md:h-6" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"> |
|
|
<path fill-rule="evenodd" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10c5.51 0 10-4.48 10-10S17.51 2 12 2zm6.605 4.61a8.502 8.502 0 011.93 5.314c-.281-.054-3.101-.629-5.943-.271-.065-.141-.12-.293-.184-.445a25.416 25.416 0 00-.564-1.236c3.145-1.28 4.577-3.124 4.761-3.362zM12 3.475c2.17 0 4.154.813 5.662 2.148-.152.216-1.443 1.941-4.48 3.08-1.399-2.57-2.95-4.675-3.189-5A8.687 8.687 0 0112 3.475zm-3.633.803a53.896 53.896 0 013.167 4.935c-3.992 1.063-7.517 1.04-7.896 1.04a8.581 8.581 0 014.729-5.975zM3.453 12.01v-.26c.37.01 4.512.065 8.775-1.215.25.477.477.965.694 1.453-.109.033-.228.065-.336.098-4.404 1.42-6.747 5.303-6.942 5.629a8.522 8.522 0 01-2.19-5.705zM12 20.547a8.482 8.482 0 01-5.239-1.8c.152-.315 1.888-3.656 6.703-5.337.022-.01.033-.01.054-.022a35.318 35.318 0 011.823 6.475 8.4 8.4 0 01-3.341.684zm4.761-1.465c-.086-.52-.542-3.015-1.659-6.084 2.679-.423 5.022.271 5.314.369a8.468 8.468 0 01-3.655 5.715z" clip-rule="evenodd" /> |
|
|
</svg> |
|
|
</a> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="absolute bottom-8 left-0 right-0 flex justify-center space-x-8 md:space-x-12 pointer-events-none"> |
|
|
<div class="w-6 h-10 md:w-8 md:h-12 bg-gradient-to-b from-yellow-100 to-yellow-300 rounded-full opacity-80 floating" style="animation-delay: 0s;"></div> |
|
|
<div class="w-6 h-10 md:w-8 md:h-12 bg-gradient-to-b from-pink-100 to-pink-300 rounded-full opacity-80 floating" style="animation-delay: 1s;"></div> |
|
|
<div class="w-6 h-10 md:w-8 md:h-12 bg-gradient-to-b from-blue-100 to-blue-300 rounded-full opacity-80 floating" style="animation-delay: 2s;"></div> |
|
|
</div> |
|
|
</section> |
|
|
|
|
|
<script> |
|
|
|
|
|
let scene, camera, renderer, objects = []; |
|
|
let isMobile = window.matchMedia("(max-width: 768px)").matches; |
|
|
|
|
|
function initThreeJS() { |
|
|
|
|
|
scene = new THREE.Scene(); |
|
|
scene.background = new THREE.Color(0xf9f9f9); |
|
|
|
|
|
|
|
|
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); |
|
|
camera.position.z = isMobile ? 40 : 30; |
|
|
|
|
|
|
|
|
renderer = new THREE.WebGLRenderer({ |
|
|
antialias: true, |
|
|
alpha: true, |
|
|
powerPreference: "high-performance" |
|
|
}); |
|
|
renderer.setSize(window.innerWidth, window.innerHeight); |
|
|
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); |
|
|
document.getElementById('canvas-container').appendChild(renderer.domElement); |
|
|
|
|
|
|
|
|
const ambientLight = new THREE.AmbientLight(0xffffff, isMobile ? 0.8 : 0.6); |
|
|
scene.add(ambientLight); |
|
|
|
|
|
if (!isMobile) { |
|
|
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8); |
|
|
directionalLight.position.set(1, 1, 1); |
|
|
scene.add(directionalLight); |
|
|
} |
|
|
|
|
|
|
|
|
createFloatingObjects(); |
|
|
|
|
|
|
|
|
let resizeTimeout; |
|
|
window.addEventListener('resize', () => { |
|
|
clearTimeout(resizeTimeout); |
|
|
resizeTimeout = setTimeout(onWindowResize, 200); |
|
|
}); |
|
|
|
|
|
|
|
|
animate(); |
|
|
} |
|
|
|
|
|
function createFloatingObjects() { |
|
|
const count = isMobile ? 4 : 8; |
|
|
const geometry = new THREE.SphereGeometry(1, isMobile ? 16 : 32, isMobile ? 16 : 32); |
|
|
|
|
|
const material = new THREE.MeshPhongMaterial({ |
|
|
color: 0xffd6e0, |
|
|
transparent: true, |
|
|
opacity: 0.8, |
|
|
shininess: 100, |
|
|
refractionRatio: 0.8 |
|
|
}); |
|
|
|
|
|
|
|
|
for (let i = 0; i < count; i++) { |
|
|
const sphere = new THREE.Mesh(geometry, material.clone()); |
|
|
sphere.position.x = (Math.random() - 0.5) * (isMobile ? 30 : 40); |
|
|
sphere.position.y = (Math.random() - 0.5) * (isMobile ? 15 : 20); |
|
|
sphere.position.z = (Math.random() - 0.5) * (isMobile ? 15 : 20); |
|
|
sphere.scale.setScalar(0.6 + Math.random() * (isMobile ? 0.4 : 0.5)); |
|
|
|
|
|
|
|
|
sphere.material.color.setHSL( |
|
|
0.6 + Math.random() * 0.1, |
|
|
0.3 + Math.random() * 0.2, |
|
|
0.8 + Math.random() * 0.2 |
|
|
); |
|
|
|
|
|
|
|
|
sphere.userData = { |
|
|
originalY: sphere.position.y, |
|
|
speed: 0.1 + Math.random() * 0.1, |
|
|
angle: Math.random() * Math.PI * 2 |
|
|
}; |
|
|
|
|
|
scene.add(sphere); |
|
|
objects.push(sphere); |
|
|
} |
|
|
|
|
|
|
|
|
if (!isMobile) { |
|
|
const keywords = ['Trust', 'Understanding', 'Hardworking', 'Creativity', 'Willingness']; |
|
|
const container = document.getElementById('keywords-container'); |
|
|
|
|
|
keywords.forEach((word, i) => { |
|
|
const el = document.createElement('div'); |
|
|
el.className = 'absolute text-lg md:text-xl font-bold text-gray-700 opacity-70'; |
|
|
el.style.top = `${30 + Math.random() * 40}%`; |
|
|
el.style.left = `${20 + Math.random() * 60}%`; |
|
|
el.textContent = word; |
|
|
container.appendChild(el); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
function onWindowResize() { |
|
|
isMobile = window.matchMedia("(max-width: 768px)").matches; |
|
|
camera.aspect = window.innerWidth / window.innerHeight; |
|
|
camera.updateProjectionMatrix(); |
|
|
renderer.setSize(window.innerWidth, window.innerHeight); |
|
|
|
|
|
|
|
|
camera.position.z = isMobile ? 40 : 30; |
|
|
} |
|
|
|
|
|
function animate() { |
|
|
requestAnimationFrame(animate); |
|
|
|
|
|
|
|
|
objects.forEach(obj => { |
|
|
obj.userData.angle += obj.userData.speed * (isMobile ? 0.005 : 0.01); |
|
|
obj.position.y = obj.userData.originalY + Math.sin(obj.userData.angle) * (isMobile ? 1 : 2); |
|
|
obj.rotation.x += isMobile ? 0.002 : 0.005; |
|
|
obj.rotation.y += isMobile ? 0.002 : 0.005; |
|
|
}); |
|
|
|
|
|
renderer.render(scene, camera); |
|
|
} |
|
|
|
|
|
|
|
|
document.querySelectorAll('.nav-sphere').forEach(sphere => { |
|
|
sphere.addEventListener('click', () => { |
|
|
const section = document.getElementById(sphere.dataset.section); |
|
|
section.scrollIntoView({ behavior: 'smooth' }); |
|
|
|
|
|
|
|
|
gsap.to(sphere, { |
|
|
scale: 1.3, |
|
|
boxShadow: '0 0 0 12px rgba(255,255,255,0.5)', |
|
|
duration: 0.3, |
|
|
ease: 'power2.out', |
|
|
onComplete: () => { |
|
|
gsap.to(sphere, { |
|
|
scale: 1, |
|
|
boxShadow: '0 0 0 0 rgba(255,255,255,0.7)', |
|
|
duration: 0.5, |
|
|
ease: 'elastic.out(1, 0.5)' |
|
|
}); |
|
|
} |
|
|
}); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', () => { |
|
|
|
|
|
if (!isMobile) { |
|
|
initThreeJS(); |
|
|
} |
|
|
|
|
|
|
|
|
gsap.from('.hero-text', { |
|
|
duration: 1.5, |
|
|
y: 50, |
|
|
opacity: 0, |
|
|
ease: 'power3.out' |
|
|
}); |
|
|
|
|
|
gsap.from('.project-tile', { |
|
|
duration: 1, |
|
|
y: 50, |
|
|
opacity: 0, |
|
|
stagger: 0.1, |
|
|
ease: 'back.out(1.7)', |
|
|
scrollTrigger: { |
|
|
trigger: '#projects', |
|
|
start: 'top 80%' |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
if (isMobile) { |
|
|
const navSpheres = document.querySelector('.nav-spheres'); |
|
|
navSpheres.classList.remove('right-8', 'top-1/2', 'transform', '-translate-y-1/2', 'flex-col', 'space-y-4'); |
|
|
navSpheres.classList.add('bottom-8', 'right-1/2', 'transform', 'translate-x-1/2', 'flex-row', 'space-x-4'); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
if ('ontouchstart' in window) { |
|
|
document.body.classList.add('touch-device'); |
|
|
} |
|
|
</script> |
|
|
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Marv12/2ppp" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
|
|
</html> |