| <!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> |