From 7d463a8ec0330155fe03684f39d077c2a8678f34 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 22 Jul 2025 05:18:20 +0000 Subject: [PATCH 1/2] Enhance navbar with scroll effects, active navigation, and responsive design Co-authored-by: lucaswan348 --- script.js | 60 ++++++++++++++++ styles.css | 201 +++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 217 insertions(+), 44 deletions(-) diff --git a/script.js b/script.js index f5902a9..a978c80 100644 --- a/script.js +++ b/script.js @@ -1,10 +1,44 @@ // Mobile Navigation Toggle const hamburger = document.querySelector('.hamburger'); const navMenu = document.querySelector('.nav-menu'); +const navbar = document.querySelector('.navbar'); + +// Add scroll effect to navbar +let lastScrollY = window.scrollY; +let scrollTimer; + +window.addEventListener('scroll', () => { + // Add scrolled class + if (window.scrollY > 50) { + navbar.classList.add('scrolled'); + } else { + navbar.classList.remove('scrolled'); + } + + // Hide/show navbar on mobile while scrolling + if (window.innerWidth <= 768) { + clearTimeout(scrollTimer); + + if (window.scrollY > lastScrollY && window.scrollY > 100) { + // Scrolling down + navbar.classList.add('hide'); + } else { + // Scrolling up + navbar.classList.remove('hide'); + } + + scrollTimer = setTimeout(() => { + navbar.classList.remove('hide'); + }, 1500); + + lastScrollY = window.scrollY; + } +}); hamburger.addEventListener('click', () => { hamburger.classList.toggle('active'); navMenu.classList.toggle('active'); + navbar.classList.remove('hide'); // Ensure navbar is visible when menu opens const expanded = navMenu.classList.contains('active'); hamburger.setAttribute('aria-expanded', expanded); @@ -292,6 +326,32 @@ document.addEventListener('DOMContentLoaded', () => { // createParticles(); }); +// Active navigation highlighting +const sections = document.querySelectorAll('section[id]'); +const navLinks = document.querySelectorAll('.nav-menu a[href^="#"]'); + +function highlightNavigation() { + const scrollY = window.scrollY; + + sections.forEach(section => { + const sectionHeight = section.offsetHeight; + const sectionTop = section.offsetTop - 100; + const sectionId = section.getAttribute('id'); + + if (scrollY > sectionTop && scrollY <= sectionTop + sectionHeight) { + navLinks.forEach(link => { + link.classList.remove('active'); + if (link.getAttribute('href') === `#${sectionId}`) { + link.classList.add('active'); + } + }); + } + }); +} + +window.addEventListener('scroll', highlightNavigation); +document.addEventListener('DOMContentLoaded', highlightNavigation); + // Simple particle effect function createParticles() { const hero = document.querySelector('.hero'); diff --git a/styles.css b/styles.css index e9268f9..ce10577 100644 --- a/styles.css +++ b/styles.css @@ -7,6 +7,15 @@ :root { --header-h: 80px; /* Default header height for desktop and larger screens */ + --header-h-mobile: 60px; /* Header height for mobile screens */ + --primary-orange: #FF8C00; + --primary-pink: #FFB6C1; + --bg-dark: #0a0a0a; + --bg-darker: #000000; + --text-primary: #ffffff; + --text-secondary: #aaaaaa; + --nav-bg: rgba(10, 10, 10, 0.95); + --nav-border: rgba(255, 255, 255, 0.1); } html, body { @@ -16,17 +25,44 @@ html, body { body { font-family: 'Atkinson Hyperlegible', sans-serif; - background-color: #000000; - /* Repeating dotted background pattern */ - background-image: - radial-gradient(rgba(255, 140, 0, 0.3) 1px, transparent 2px), - radial-gradient(rgba(255, 182, 193, 0.3) 1px, transparent 2px); - background-size: 100px 100px; - background-position: 0 0, 50px 50px; + background-color: #0a0a0a; + /* Modern gradient mesh background */ + background-image: + radial-gradient(at 20% 30%, rgba(255, 140, 0, 0.15) 0%, transparent 50%), + radial-gradient(at 80% 20%, rgba(255, 182, 193, 0.12) 0%, transparent 50%), + radial-gradient(at 40% 70%, rgba(255, 140, 0, 0.1) 0%, transparent 50%), + radial-gradient(at 90% 80%, rgba(255, 182, 193, 0.08) 0%, transparent 50%); + background-attachment: fixed; color: #ffffff; line-height: 1.6; overflow-x: hidden; min-height: 100vh; + position: relative; +} + +/* Add subtle animated background particles */ +body::before { + content: ''; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + opacity: 0.03; + z-index: -1; + background-image: + repeating-linear-gradient(45deg, transparent, transparent 35px, rgba(255,255,255,.02) 35px, rgba(255,255,255,.02) 70px); + pointer-events: none; + animation: backgroundMove 60s linear infinite; +} + +@keyframes backgroundMove { + 0% { + transform: translate(0, 0); + } + 100% { + transform: translate(35px, 35px); + } } .container { @@ -41,13 +77,33 @@ body { position: fixed; top: 0; width: 100%; - background: rgba(0, 0, 0, 0.95); - backdrop-filter: blur(10px); + background: var(--nav-bg); + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); z-index: 1000; - height: var(--header-h); /* use the shared header height */ - padding: calc(env(safe-area-inset-top) + 0.5rem) 0 0.5rem; /* safe-area + some breathing room */ - border-bottom: 1px solid #333; - box-shadow: 0 2px 20px rgba(0, 0, 0, 0.3); + height: var(--header-h); + display: flex; + align-items: center; + border-bottom: 1px solid var(--nav-border); + box-shadow: 0 2px 30px rgba(0, 0, 0, 0.5); + transition: all 0.3s ease; +} + +/* Add scroll effect */ +.navbar.scrolled { + background: rgba(10, 10, 10, 0.98); + box-shadow: 0 4px 30px rgba(0, 0, 0, 0.8); +} + +/* Hide/show navbar on scroll for mobile */ +@media (max-width: 768px) { + .navbar { + transition: transform 0.3s ease, background 0.3s ease; + } + + .navbar.hide { + transform: translateY(-100%); + } } .nav-container { @@ -74,12 +130,12 @@ body { } .logo-text .c-letter { - color: #FF8C00; /* Orange */ + color: var(--primary-orange); text-shadow: 0 0 10px rgba(255, 140, 0, 0.3); } .logo-text .n-letter { - color: #FFB6C1; /* Pastel Pink */ + color: var(--primary-pink); text-shadow: 0 0 10px rgba(255, 182, 193, 0.3); } @@ -91,42 +147,67 @@ body { text-transform: uppercase; } +/* Desktop navigation menu */ .nav-menu { - position: fixed; - top: -100%; - left: 0; - right: 0; - background: rgba(0, 0, 0, 0.98); - backdrop-filter: blur(15px); display: flex; - flex-direction: column; list-style: none; - gap: 1rem; + gap: 2rem; align-items: center; - padding: 2rem 0; - transition: top 0.3s cubic-bezier(0.4, 0, 0.2, 1); - border-bottom: 1px solid #333; - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); - z-index: 999; + margin: 0; + padding: 0; } -.nav-menu.active { - top: var(--header-h); - display: flex; +/* Mobile navigation menu - hidden by default */ +@media (max-width: 768px) { + .nav-menu { + position: fixed; + top: -100%; + left: 0; + right: 0; + background: var(--nav-bg); + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + flex-direction: column; + gap: 0; + padding: 2rem 0; + transition: top 0.3s cubic-bezier(0.4, 0, 0.2, 1); + border-bottom: 1px solid var(--nav-border); + box-shadow: 0 4px 30px rgba(0, 0, 0, 0.5); + z-index: 999; + } } +@media (max-width: 768px) { + .nav-menu.active { + top: var(--header-h-mobile); + display: flex; + } +} + +/* Desktop nav links */ .nav-menu a { - color: #ffffff; + color: var(--text-primary); text-decoration: none; font-weight: 500; - font-size: 1.1rem; + font-size: 0.95rem; transition: all 0.3s ease; - padding: 1rem 2rem; + padding: 0.5rem 1rem; border-radius: 6px; position: relative; - display: block; - width: 200px; - text-align: center; + white-space: nowrap; +} + +/* Mobile nav links */ +@media (max-width: 768px) { + .nav-menu a { + font-size: 1.1rem; + padding: 1rem 2rem; + display: block; + width: 90%; + max-width: 300px; + text-align: center; + margin: 0 auto; + } } .nav-menu a:hover { @@ -141,7 +222,7 @@ body { left: 50%; width: 0; height: 2px; - background: linear-gradient(90deg, #FF8C00, #FFB6C1); + background: linear-gradient(90deg, var(--primary-orange), var(--primary-pink)); transition: all 0.3s ease; transform: translateX(-50%); } @@ -151,17 +232,18 @@ body { } .nav-menu a.active { - color: #FF8C00; + color: var(--primary-orange); background: rgba(255, 140, 0, 0.1); } .nav-menu a.active::after { width: 80%; - background: #FF8C00; + background: var(--primary-orange); } +/* Hamburger menu - hidden on desktop */ .hamburger { - display: flex; + display: none; flex-direction: column; cursor: pointer; gap: 4px; @@ -172,6 +254,13 @@ body { background: transparent; } +/* Show hamburger on mobile */ +@media (max-width: 768px) { + .hamburger { + display: flex; + } +} + .hamburger:hover { background: rgba(255, 255, 255, 0.1); } @@ -202,11 +291,22 @@ body { min-height: 100vh; display: flex; align-items: center; - padding-top: var(--header-h); - background: #000000; + padding-top: calc(var(--header-h) + 2rem); + background: transparent; position: relative; } +/* Add smooth scroll behavior */ +html { + scroll-behavior: smooth; + scroll-padding-top: var(--header-h); +} + +/* Common section styles */ +section { + scroll-margin-top: var(--header-h); +} + .hero-container { max-width: 1200px; margin: 0 auto; @@ -866,7 +966,12 @@ body { @media (max-width: 768px) { /* Override the shared header height for small screens */ :root { - --header-h: 60px; + --header-h: var(--header-h-mobile); + } + + .navbar { + height: var(--header-h-mobile); + padding: 0; } /* compact horizontal logo */ @@ -875,6 +980,14 @@ body { align-items: center; gap: .5rem; } + + .logo-text { + font-size: 1.5rem; + } + + .logo-subtitle { + font-size: 0.7rem; + } /* tighten flex spacing to avoid horizontal overflow */ .nav-container { From f06019f1c9cf75c819f5756dcb30982e24a354d1 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 22 Jul 2025 05:38:23 +0000 Subject: [PATCH 2/2] Refactor navigation highlighting and add DOMContentLoaded event listener Co-authored-by: lucaswan348 --- script.js | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/script.js b/script.js index a978c80..8c23e28 100644 --- a/script.js +++ b/script.js @@ -105,6 +105,7 @@ function updateActiveNav() { } window.addEventListener('scroll', updateActiveNav); +document.addEventListener('DOMContentLoaded', updateActiveNav); // Smooth scrolling for navigation links document.querySelectorAll('a[href^="#"]').forEach(anchor => { @@ -326,32 +327,6 @@ document.addEventListener('DOMContentLoaded', () => { // createParticles(); }); -// Active navigation highlighting -const sections = document.querySelectorAll('section[id]'); -const navLinks = document.querySelectorAll('.nav-menu a[href^="#"]'); - -function highlightNavigation() { - const scrollY = window.scrollY; - - sections.forEach(section => { - const sectionHeight = section.offsetHeight; - const sectionTop = section.offsetTop - 100; - const sectionId = section.getAttribute('id'); - - if (scrollY > sectionTop && scrollY <= sectionTop + sectionHeight) { - navLinks.forEach(link => { - link.classList.remove('active'); - if (link.getAttribute('href') === `#${sectionId}`) { - link.classList.add('active'); - } - }); - } - }); -} - -window.addEventListener('scroll', highlightNavigation); -document.addEventListener('DOMContentLoaded', highlightNavigation); - // Simple particle effect function createParticles() { const hero = document.querySelector('.hero');