<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Dynamic SEO Meta Tags -->
<title>MMC Creative Group | Digital Innovation</title>
<meta name="description" content="MMC Creative Group is a strategic digital agency specializing in web design, video production, and creative systems.">
<!-- Social Media Thumbnails (Open Graph) -->
<!-- Replace the content URL below with the actual URL of your website's screenshot/thumbnail image -->
<meta property="og:type" content="website">
<meta property="og:url" content="https://www.mmccreative.com/">
<meta property="og:title" content="MMC Creative Group | Digital Innovation">
<meta property="og:description" content="MMC Creative Group is a strategic digital agency specializing in web design, video production, and creative systems.">
<meta property="og:image" content="https://placehold.co/1200x630/0b2e3b/48C9B0?text=MMC+Creative+Group">
<!-- Twitter Card Data -->
<meta name="twitter:card" content="summary_large_image">
<meta property="twitter:url" content="https://www.mmccreative.com/">
<meta name="twitter:title" content="MMC Creative Group | Digital Innovation">
<meta name="twitter:description" content="MMC Creative Group is a strategic digital agency specializing in web design, video production, and creative systems.">
<meta name="twitter:image" content="https://placehold.co/1200x630/0b2e3b/48C9B0?text=MMC+Creative+Group">
<!-- Favicon (Browser Tab Icon) -->
<link rel="icon" type="image/png" href="https://placehold.co/32x32/48C9B0/0b2e3b?text=M">
<!-- Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Three.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;700;900&display=swap" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
colors: {
'brand-dark': '#0b2e3b',
'brand-darker': '#051820',
'brand-light': '#E0F2F1',
'brand-accent': '#48C9B0',
'brand-text': '#212529',
'brand-secondary': '#6C757D',
},
fontFamily: {
sans: ['Inter', 'sans-serif'],
}
}
}
}
</script>
<style>
html, body {
margin: 0;
padding: 0;
width: 100%;
overflow-x: hidden; /* Allow vertical scroll, prevent horizontal */
background-color: #0b2e3b; /* Fallback */
}
/* Fixed 3D Background */
#canvas-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
background: linear-gradient(to bottom, #0b2e3b, #051820);
pointer-events: none;
}
/* Content Wrapper */
#app-content {
position: relative;
z-index: 10;
min-height: 100vh;
display: flex;
flex-direction: column;
}
/* Navigation */
.glass-nav {
background: rgba(11, 46, 59, 0.85);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
height: 70px; /* Fixed height for calculations */
}
.nav-link {
position: relative;
}
.nav-link::after {
content: '';
position: absolute;
width: 0;
height: 2px;
bottom: -4px;
left: 0;
background-color: #48C9B0;
transition: width 0.3s ease;
}
.nav-link:hover::after, .nav-link.active::after {
width: 100%;
}
/* Page Transitions & Layout */
.page-view {
display: none;
opacity: 0;
transition: opacity 0.5s ease-in-out;
min-height: 100vh;
padding-top: 70px; /* Match nav height */
padding-bottom: 40px;
}
.page-view.active {
display: block;
opacity: 1;
animation: fadeIn 0.6s ease-out forwards;
}
/* Container for "One Screen" feel */
.screen-container {
min-height: calc(100vh - 70px);
display: flex;
flex-direction: column;
justify-content: center; /* Center content vertically */
padding: 1rem 1.5rem; /* Minimal padding */
}
/* Ensure content doesn't get hidden under nav on short screens */
@media (max-height: 700px) {
.screen-container {
justify-content: flex-start;
padding-top: 2rem;
}
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
/* 3D Tilt Card */
.tilt-card {
transition: transform 0.1s ease, box-shadow 0.3s ease;
transform-style: preserve-3d;
perspective: 1000px;
}
.tilt-card:hover {
z-index: 20;
box-shadow: 0 20px 40px rgba(0,0,0,0.2);
}
/* Form Styling */
.form-input {
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
color: white;
transition: all 0.3s ease;
}
.form-input:focus {
background: rgba(255, 255, 255, 0.1);
border-color: #48C9B0;
outline: none;
box-shadow: 0 0 10px rgba(72, 201, 176, 0.2);
}
/* Custom Scrollbar */
::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { background: #0b2e3b; }
::-webkit-scrollbar-thumb { background: #48C9B0; border-radius: 4px; }
</style>
</head>
<body class="antialiased text-brand-text">
<!-- 3D Background (Fixed) -->
<div id="canvas-container"></div>
<!-- Navigation (Fixed) -->
<nav class="fixed w-full z-50 glass-nav transition-all duration-300" id="navbar">
<div class="container mx-auto px-6 py-4 flex justify-between items-center h-full">
<a href="#home" class="text-2xl font-black text-white tracking-tight group">
MMC <span class="text-brand-accent group-hover:text-white transition-colors">CREATIVE</span>
</a>
<!-- Desktop Menu -->
<div class="hidden md:flex space-x-8">
<a href="#home" class="nav-link text-white/80 hover:text-white font-medium text-sm tracking-wide transition-colors">HOME</a>
<a href="#services" class="nav-link text-white/80 hover:text-white font-medium text-sm tracking-wide transition-colors">SERVICES</a>
<a href="#about" class="nav-link text-white/80 hover:text-white font-medium text-sm tracking-wide transition-colors">ABOUT</a>
<a href="#contact" class="px-5 py-2 bg-brand-accent text-brand-dark font-bold rounded-full hover:bg-white transition-all duration-300 text-sm">GET IN TOUCH</a>
</div>
<!-- Mobile Menu Button -->
<button class="md:hidden text-white" onclick="document.getElementById('mobile-menu').classList.toggle('hidden')">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path></svg>
</button>
</div>
<!-- Mobile Menu Dropdown -->
<div id="mobile-menu" class="hidden md:hidden bg-brand-darker border-t border-white/10">
<div class="flex flex-col p-4 space-y-4">
<a href="#home" class="text-white block py-2" onclick="document.getElementById('mobile-menu').classList.add('hidden')">Home</a>
<a href="#services" class="text-white block py-2" onclick="document.getElementById('mobile-menu').classList.add('hidden')">Services</a>
<a href="#about" class="text-white block py-2" onclick="document.getElementById('mobile-menu').classList.add('hidden')">About</a>
<a href="#contact" class="text-brand-accent block py-2 font-bold" onclick="document.getElementById('mobile-menu').classList.add('hidden')">Contact</a>
</div>
</div>
</nav>
<!-- Main Application Content -->
<div id="app-content">
<!-- ==================== VIEW: HOME ==================== -->
<div id="view-home" class="page-view">
<div class="screen-container container mx-auto max-w-7xl md:flex-row md:gap-12 px-6">
<!-- Flex container handles vertical centering -->
<div class="flex flex-col md:flex-row items-center justify-center gap-12 w-full">
<!-- Left: Hero Text -->
<div class="md:w-1/2 text-center md:text-left z-10">
<span class="inline-block py-1 px-3 rounded-full bg-brand-accent/10 border border-brand-accent/30 text-brand-accent text-xs font-semibold tracking-widest mb-4 uppercase backdrop-blur-sm">
Digital Development Agency
</span>
<h1 class="text-5xl md:text-7xl lg:text-8xl font-black text-white tracking-tighter mb-4 drop-shadow-2xl leading-none">
BUILDING <br/><span class="text-transparent bg-clip-text bg-gradient-to-r from-brand-accent to-emerald-300">TOMORROW</span>
</h1>
<p class="text-lg text-brand-light/90 max-w-lg mb-8 leading-relaxed">
We design and build high-performance digital ecosystems. Websites, Mobile Apps, & Scalable Platforms.
</p>
</div>
<!-- Right: Quick Intro Panel -->
<div class="md:w-1/2 w-full bg-white/5 backdrop-blur-md border border-white/10 p-8 rounded-2xl">
<h2 class="text-2xl font-bold text-white mb-4">Strategic Code.<br>Modern Design.</h2>
<p class="text-brand-light/70 mb-6 text-sm leading-relaxed">
MMC Creative Group partners with ambitious brands to build digital products that scale. We don't just make things look good; we engineer them to perform.
</p>
<div class="grid grid-cols-2 gap-4">
<div class="flex items-center text-white text-sm font-medium"><span class="w-1.5 h-1.5 bg-brand-accent rounded-full mr-2"></span>Custom Websites</div>
<div class="flex items-center text-white text-sm font-medium"><span class="w-1.5 h-1.5 bg-brand-accent rounded-full mr-2"></span>Mobile Apps</div>
<div class="flex items-center text-white text-sm font-medium"><span class="w-1.5 h-1.5 bg-brand-accent rounded-full mr-2"></span>Web Applications</div>
<div class="flex items-center text-white text-sm font-medium"><span class="w-1.5 h-1.5 bg-brand-accent rounded-full mr-2"></span>UI/UX Design</div>
</div>
</div>
</div>
</div>
</div>
<!-- ==================== VIEW: SERVICES ==================== -->
<div id="view-services" class="page-view">
<div class="screen-container container mx-auto max-w-7xl px-6">
<!-- Header Section -->
<div class="text-center mb-6">
<span class="text-brand-accent font-bold tracking-widest uppercase text-xs">Capabilities</span>
<h2 class="text-3xl md:text-4xl font-bold text-white mt-1">What We Build</h2>
</div>
<!-- Cards Grid - Tighter gap, limited height -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-2 gap-5 w-full max-w-5xl mx-auto">
<!-- Card 1 -->
<div class="tilt-card group bg-white p-6 rounded-xl shadow-xl hover:shadow-2xl border border-transparent hover:border-brand-accent/20 relative overflow-hidden transition-all duration-300">
<div class="absolute top-4 right-4 p-2 opacity-10 group-hover:opacity-20 transition-opacity">
<svg class="w-10 h-10 text-brand-dark" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path></svg>
</div>
<h3 class="text-lg font-bold text-brand-dark mb-2 group-hover:text-brand-accent transition-colors">Custom Websites</h3>
<p class="text-brand-secondary text-sm mb-3 leading-snug">Responsive, blazing-fast websites using modern frameworks. Immersive landing pages to complex corporate sites.</p>
<ul class="text-xs text-brand-dark space-y-1 font-medium">
<li class="flex items-center"><span class="w-1.5 h-1.5 bg-brand-accent rounded-full mr-2"></span>React / Next.js</li>
<li class="flex items-center"><span class="w-1.5 h-1.5 bg-brand-accent rounded-full mr-2"></span>Tailwind CSS</li>
</ul>
</div>
<!-- Card 2 -->
<div class="tilt-card group bg-white p-6 rounded-xl shadow-xl hover:shadow-2xl border border-transparent hover:border-brand-accent/20 relative overflow-hidden transition-all duration-300">
<div class="absolute top-4 right-4 p-2 opacity-10 group-hover:opacity-20 transition-opacity">
<svg class="w-10 h-10 text-brand-dark" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z"></path></svg>
</div>
<h3 class="text-lg font-bold text-brand-dark mb-2 group-hover:text-brand-accent transition-colors">Mobile Applications</h3>
<p class="text-brand-secondary text-sm mb-3 leading-snug">Native and cross-platform mobile apps designed for iOS and Android. Focused on performance and user retention.</p>
<ul class="text-xs text-brand-dark space-y-1 font-medium">
<li class="flex items-center"><span class="w-1.5 h-1.5 bg-brand-accent rounded-full mr-2"></span>iOS & Android</li>
<li class="flex items-center"><span class="w-1.5 h-1.5 bg-brand-accent rounded-full mr-2"></span>React Native</li>
</ul>
</div>
<!-- Card 3 -->
<div class="tilt-card group bg-white p-6 rounded-xl shadow-xl hover:shadow-2xl border border-transparent hover:border-brand-accent/20 relative overflow-hidden transition-all duration-300">
<div class="absolute top-4 right-4 p-2 opacity-10 group-hover:opacity-20 transition-opacity">
<svg class="w-10 h-10 text-brand-dark" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"></path></svg>
</div>
<h3 class="text-lg font-bold text-brand-dark mb-2 group-hover:text-brand-accent transition-colors">Web Applications</h3>
<p class="text-brand-secondary text-sm mb-3 leading-snug">Scalable SaaS platforms and custom dashboards. We build the engine that powers your digital business.</p>
<ul class="text-xs text-brand-dark space-y-1 font-medium">
<li class="flex items-center"><span class="w-1.5 h-1.5 bg-brand-accent rounded-full mr-2"></span>SaaS Development</li>
<li class="flex items-center"><span class="w-1.5 h-1.5 bg-brand-accent rounded-full mr-2"></span>Database Architecture</li>
</ul>
</div>
<!-- Card 4 -->
<div class="tilt-card group bg-white p-6 rounded-xl shadow-xl hover:shadow-2xl border border-transparent hover:border-brand-accent/20 relative overflow-hidden transition-all duration-300">
<div class="absolute top-4 right-4 p-2 opacity-10 group-hover:opacity-20 transition-opacity">
<svg class="w-10 h-10 text-brand-dark" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01"></path></svg>
</div>
<h3 class="text-lg font-bold text-brand-dark mb-2 group-hover:text-brand-accent transition-colors">UI/UX Design</h3>
<p class="text-brand-secondary text-sm mb-3 leading-snug">User-centric design is at the core of our development. We ensure your app looks as good as it functions.</p>
<ul class="text-xs text-brand-dark space-y-1 font-medium">
<li class="flex items-center"><span class="w-1.5 h-1.5 bg-brand-accent rounded-full mr-2"></span>Wireframing</li>
<li class="flex items-center"><span class="w-1.5 h-1.5 bg-brand-accent rounded-full mr-2"></span>Interactive Prototypes</li>
</ul>
</div>
</div>
</div>
</div>
<!-- ==================== VIEW: ABOUT ==================== -->
<div id="view-about" class="page-view">
<div class="screen-container container mx-auto max-w-7xl px-6">
<div class="flex flex-col md:flex-row items-center gap-12 justify-center w-full">
<!-- Left: Text -->
<div class="md:w-1/2 text-white">
<span class="text-brand-accent font-bold tracking-widest uppercase text-xs mb-2 block">About Us</span>
<h1 class="text-4xl md:text-5xl font-black mb-6">Forward thinking,<br>Code driven.</h1>
<div class="text-brand-light/80 leading-relaxed space-y-4 text-sm md:text-base">
<p class="border-l-4 border-brand-accent pl-4">
In a rapidly evolving digital landscape, you need a partner who builds for tomorrow, not just for today.
</p>
<p>
MMC Creative Group is a modern development agency dedicated to crafting exceptional web and mobile experiences. As digital natives, we are untethered by legacy systems and fueled by the latest technologies. We bridge the gap between creative ambition and technical execution, ensuring every line of code serves a strategic purpose.
</p>
<p>
Whether you are launching a new product or scaling an existing platform, our team is ready to turn your vision into a robust, deployed reality.
</p>
</div>
</div>
<!-- Right: Core Values Grid -->
<div class="md:w-1/2 grid grid-cols-2 gap-4 w-full max-w-lg">
<div class="p-8 bg-white/5 backdrop-blur-sm rounded-lg border border-white/10 text-center hover:bg-white/10 transition-colors">
<h3 class="text-xl font-bold text-brand-accent mb-1">Modern</h3>
<p class="text-xs text-brand-light uppercase tracking-wide">Tech Stack</p>
</div>
<div class="p-8 bg-white/5 backdrop-blur-sm rounded-lg border border-white/10 text-center hover:bg-white/10 transition-colors">
<h3 class="text-xl font-bold text-brand-accent mb-1">Agile</h3>
<p class="text-xs text-brand-light uppercase tracking-wide">Development</p>
</div>
<div class="p-8 bg-white/5 backdrop-blur-sm rounded-lg border border-white/10 text-center hover:bg-white/10 transition-colors">
<h3 class="text-xl font-bold text-brand-accent mb-1">Scalable</h3>
<p class="text-xs text-brand-light uppercase tracking-wide">Architecture</p>
</div>
<div class="p-8 bg-white/5 backdrop-blur-sm rounded-lg border border-white/10 text-center hover:bg-white/10 transition-colors">
<h3 class="text-xl font-bold text-brand-accent mb-1">Client</h3>
<p class="text-xs text-brand-light uppercase tracking-wide">Focused</p>
</div>
</div>
</div>
</div>
</div>
<!-- ==================== VIEW: CONTACT ==================== -->
<div id="view-contact" class="page-view">
<div class="screen-container container mx-auto max-w-6xl px-6">
<div class="flex flex-col md:flex-row items-center justify-center gap-12 w-full">
<!-- Contact Info -->
<div class="text-white md:w-1/2">
<span class="text-brand-accent font-bold tracking-widest uppercase text-xs mb-2 block">Get In Touch</span>
<h1 class="text-3xl md:text-5xl font-black mb-4">Let's build something<br>extraordinary.</h1>
<p class="text-brand-light/70 text-base mb-8 max-w-md">
Ready to start your next project? We're currently accepting new partnerships.
</p>
<div class="space-y-4">
<!-- Block 1: Availability -->
<div class="flex items-center p-4 bg-white/5 rounded-lg border border-white/5">
<div class="w-10 h-10 bg-brand-accent/20 rounded-full flex items-center justify-center mr-4 text-brand-accent">
<!-- Calendar/Check icon -->
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path></svg>
</div>
<div>
<h4 class="text-sm font-bold">Availability</h4>
<p class="text-brand-light text-sm">Accepting new projects for Q2</p>
</div>
</div>
<!-- Block 2: Response Time -->
<div class="flex items-center p-4 bg-white/5 rounded-lg border border-white/5">
<div class="w-10 h-10 bg-brand-accent/20 rounded-full flex items-center justify-center mr-4 text-brand-accent">
<!-- Chat icon -->
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"></path></svg>
</div>
<div>
<h4 class="text-sm font-bold">Response Time</h4>
<p class="text-brand-light text-sm">We reply within 24 hours</p>
</div>
</div>
</div>
</div>
<!-- Compact Contact Form -->
<div class="md:w-1/2 w-full bg-brand-darker/60 backdrop-blur-md p-6 rounded-2xl border border-white/10 shadow-2xl">
<form id="contact-form" action="https://formspree.io/f/meeabgaj" method="POST" class="space-y-4">
<div class="grid grid-cols-2 gap-4">
<div>
<label class="block text-brand-secondary text-xs font-bold mb-1">First Name</label>
<input type="text" name="firstName" class="w-full px-3 py-2 rounded text-sm form-input" placeholder="John" required>
</div>
<div>
<label class="block text-brand-secondary text-xs font-bold mb-1">Last Name</label>
<input type="text" name="lastName" class="w-full px-3 py-2 rounded text-sm form-input" placeholder="Doe">
</div>
</div>
<div>
<label class="block text-brand-secondary text-xs font-bold mb-1">Email</label>
<input type="email" name="email" class="w-full px-3 py-2 rounded text-sm form-input" placeholder="john@company.com" required>
</div>
<div>
<label class="block text-brand-secondary text-xs font-bold mb-1">Project</label>
<select name="projectType" class="w-full px-3 py-2 rounded text-sm form-input">
<option class="bg-brand-dark" value="Web Design & Dev">Website Development</option>
<option class="bg-brand-dark" value="Mobile App">Mobile App Development</option>
<option class="bg-brand-dark" value="Web Application">Web Application (SaaS)</option>
</select>
</div>
<div>
<label class="block text-brand-secondary text-xs font-bold mb-1">Message</label>
<textarea name="message" rows="3" class="w-full px-3 py-2 rounded text-sm form-input" placeholder="Tell us about your project..." required></textarea>
</div>
<button type="submit" class="w-full py-3 bg-brand-accent text-brand-dark font-bold rounded-lg hover:bg-white transition-all duration-300 shadow-lg hover:shadow-brand-accent/20 text-sm uppercase tracking-wide">
Send Message
</button>
</form>
<div id="contact-status" class="text-center mt-4"></div>
</div>
</div>
</div>
</div>
</div>
<!-- JAVASCRIPT LOGIC -->
<script>
// --- SPA ROUTER & SEO ---
const routes = {
'home': {
title: 'MMC Creative Group | Digital Innovation',
desc: 'MMC Creative Group is a strategic digital agency specializing in web design, video production, and creative systems.'
},
'services': {
title: 'Services | MMC Creative Group',
desc: 'Explore our services: Web Design, Video Editing, Digital Products, and Creative Systems.'
},
'about': {
title: 'About Us | MMC Creative Group',
desc: 'We are a multidisciplinary team of designers and developers building the future of digital.'
},
'contact': {
title: 'Contact | MMC Creative Group',
desc: 'Get in touch with MMC Creative Group to start your next project.'
}
};
const handleRoute = () => {
// Get hash or default to home
let hash = window.location.hash.slice(1) || 'home';
if (!routes[hash]) hash = 'home';
// Update Title & Meta
document.title = routes[hash].title;
const metaDesc = document.querySelector('meta[name="description"]');
if(metaDesc) metaDesc.setAttribute('content', routes[hash].desc);
// Hide all views
document.querySelectorAll('.page-view').forEach(el => {
el.classList.remove('active');
});
// Show current view
const activeView = document.getElementById(`view-${hash}`);
if (activeView) {
activeView.classList.add('active');
window.scrollTo(0, 0);
}
// Update Nav Active State
document.querySelectorAll('.nav-link').forEach(link => {
link.classList.remove('active');
if(link.getAttribute('href') === `#${hash}`) {
link.classList.add('active');
}
});
};
// Listen for hash changes
window.addEventListener('hashchange', handleRoute);
// Initial load
window.addEventListener('DOMContentLoaded', handleRoute);
// --- CONTACT FORM HANDLING ---
const contactForm = document.getElementById('contact-form');
if (contactForm) {
contactForm.addEventListener('submit', async function(event) {
event.preventDefault();
const status = document.getElementById('contact-status');
const data = new FormData(event.target);
status.innerHTML = "Sending...";
status.className = "text-brand-accent text-sm mt-2"; // Styling
fetch(event.target.action, {
method: contactForm.method,
body: data,
headers: {
'Accept': 'application/json'
}
}).then(response => {
if (response.ok) {
status.innerHTML = "Thanks for your submission!";
contactForm.reset();
} else {
response.json().then(data => {
if (Object.hasOwn(data, 'errors')) {
status.innerHTML = data["errors"].map(error => error["message"]).join(", ");
} else {
status.innerHTML = "Oops! There was a problem submitting your form";
}
})
}
}).catch(error => {
status.innerHTML = "Oops! There was a problem submitting your form";
});
});
}
// --- THREE.JS 3D SCENE SETUP ---
const init3D = () => {
const container = document.getElementById('canvas-container');
if (!container) return;
// Scene setup
const scene = new THREE.Scene();
// Fog to blend objects into background
scene.fog = new THREE.FogExp2(0x0b2e3b, 0.002);
// Camera setup
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 30;
// Renderer setup
const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
container.appendChild(renderer.domElement);
// Objects: Floating Shapes
const geometryGroup = new THREE.Group();
scene.add(geometryGroup);
// Create many floating particles/shapes
const particleCount = 60;
const shapes = [];
// Geometries
const geomIco = new THREE.IcosahedronGeometry(1, 0);
const geomTetra = new THREE.TetrahedronGeometry(1, 0);
// Material - Wireframe style with brand colors
const materialAccent = new THREE.MeshBasicMaterial({
color: 0x48C9B0,
wireframe: true,
transparent: true,
opacity: 0.4
});
const materialWhite = new THREE.MeshBasicMaterial({
color: 0xffffff,
wireframe: true,
transparent: true,
opacity: 0.1
});
for (let i = 0; i < particleCount; i++) {
const isAccent = Math.random() > 0.7;
const mesh = new THREE.Mesh(
Math.random() > 0.5 ? geomIco : geomTetra,
isAccent ? materialAccent : materialWhite
);
// Random position spread
mesh.position.x = (Math.random() - 0.5) * 100;
mesh.position.y = (Math.random() - 0.5) * 60;
mesh.position.z = (Math.random() - 0.5) * 40;
// Random scale
const scale = Math.random() * 2 + 0.5;
mesh.scale.set(scale, scale, scale);
// Store rotation speed and movement speed
mesh.userData = {
rotSpeedX: (Math.random() - 0.5) * 0.02,
rotSpeedY: (Math.random() - 0.5) * 0.02,
velY: (Math.random() * 0.05) + 0.01, // Move up slowly
initialY: mesh.position.y
};
geometryGroup.add(mesh);
shapes.push(mesh);
}
// Interactive Mouse Movement
let mouseX = 0;
let mouseY = 0;
let targetX = 0;
let targetY = 0;
const windowHalfX = window.innerWidth / 2;
const windowHalfY = window.innerHeight / 2;
document.addEventListener('mousemove', (event) => {
mouseX = (event.clientX - windowHalfX);
mouseY = (event.clientY - windowHalfY);
});
// Animation Loop
const animate = () => {
requestAnimationFrame(animate);
targetX = mouseX * 0.001;
targetY = mouseY * 0.001;
// Smooth rotation of the entire group based on mouse
geometryGroup.rotation.y += 0.05 * (targetX - geometryGroup.rotation.y);
geometryGroup.rotation.x += 0.05 * (targetY - geometryGroup.rotation.x);
// Animate individual shapes
shapes.forEach(mesh => {
mesh.rotation.x += mesh.userData.rotSpeedX;
mesh.rotation.y += mesh.userData.rotSpeedY;
// Float Upwards effect
mesh.position.y += mesh.userData.velY;
// Reset if too high
if (mesh.position.y > 40) {
mesh.position.y = -40;
}
});
renderer.render(scene, camera);
};
animate();
// Resize Handler
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
};
// --- 3D TILT EFFECT FOR CARDS (Vanilla JS) ---
const initTilt = () => {
const cards = document.querySelectorAll('.tilt-card');
cards.forEach(card => {
card.addEventListener('mousemove', (e) => {
const rect = card.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const centerX = rect.width / 2;
const centerY = rect.height / 2;
const rotateX = ((y - centerY) / centerY) * -5; // Max -5deg to 5deg
const rotateY = ((x - centerX) / centerX) * 5;
card.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale3d(1.02, 1.02, 1.02)`;
});
card.addEventListener('mouseleave', () => {
card.style.transform = 'perspective(1000px) rotateX(0) rotateY(0) scale3d(1, 1, 1)';
});
});
};
// Run Inits on Load
window.addEventListener('DOMContentLoaded', () => {
init3D();
initTilt();
});
</script>
</body>
</html>