feat: public site landing page with header, footer, styles
- Header with fixed navbar, responsive mobile menu, services dropdown - Landing page with hero, services grid, value propositions, testimonials, contact - Comprehensive CSS (1300+ lines): navy/gold brand colors, custom properties, responsive breakpoints, card hover effects, form styles, print & a11y - Footer with 3-column layout, contact info, social links - JS: hamburger toggle, smooth scroll, navbar scroll effect, scroll animations Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1342
assets/css/style.css
Normal file
1342
assets/css/style.css
Normal file
File diff suppressed because it is too large
Load Diff
169
assets/js/main.js
Normal file
169
assets/js/main.js
Normal file
@@ -0,0 +1,169 @@
|
||||
/**
|
||||
* Gestoría LP — Main JavaScript
|
||||
* Handles: mobile menu, smooth scroll, navbar scroll effect, scroll animations
|
||||
*/
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
|
||||
// ---- DOM References ----
|
||||
const navbar = document.getElementById('navbar');
|
||||
const navToggle = document.getElementById('navToggle');
|
||||
const navMenu = document.getElementById('navMenu');
|
||||
const body = document.body;
|
||||
|
||||
// Create overlay element for mobile menu backdrop
|
||||
const overlay = document.createElement('div');
|
||||
overlay.classList.add('navbar__overlay');
|
||||
document.body.appendChild(overlay);
|
||||
|
||||
// ================================================================
|
||||
// 1. Mobile Hamburger Menu Toggle
|
||||
// ================================================================
|
||||
function openMenu() {
|
||||
navToggle.classList.add('active');
|
||||
navMenu.classList.add('active');
|
||||
overlay.classList.add('active');
|
||||
navToggle.setAttribute('aria-expanded', 'true');
|
||||
body.style.overflow = 'hidden';
|
||||
}
|
||||
|
||||
function closeMenu() {
|
||||
navToggle.classList.remove('active');
|
||||
navMenu.classList.remove('active');
|
||||
overlay.classList.remove('active');
|
||||
navToggle.setAttribute('aria-expanded', 'false');
|
||||
body.style.overflow = '';
|
||||
}
|
||||
|
||||
if (navToggle) {
|
||||
navToggle.addEventListener('click', function () {
|
||||
if (navMenu.classList.contains('active')) {
|
||||
closeMenu();
|
||||
} else {
|
||||
openMenu();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Close menu when clicking overlay
|
||||
overlay.addEventListener('click', closeMenu);
|
||||
|
||||
// Close menu when pressing Escape
|
||||
document.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Escape' && navMenu.classList.contains('active')) {
|
||||
closeMenu();
|
||||
}
|
||||
});
|
||||
|
||||
// ================================================================
|
||||
// 2. Mobile Dropdown Toggle
|
||||
// ================================================================
|
||||
var dropdownItems = document.querySelectorAll('.navbar__item--dropdown');
|
||||
dropdownItems.forEach(function (item) {
|
||||
var link = item.querySelector('.navbar__link--dropdown');
|
||||
if (link) {
|
||||
link.addEventListener('click', function (e) {
|
||||
// Only toggle on mobile
|
||||
if (window.innerWidth <= 768) {
|
||||
e.preventDefault();
|
||||
item.classList.toggle('active');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// ================================================================
|
||||
// 3. Smooth Scroll for Anchor Links
|
||||
// ================================================================
|
||||
var anchorLinks = document.querySelectorAll('a[href^="#"]');
|
||||
anchorLinks.forEach(function (link) {
|
||||
link.addEventListener('click', function (e) {
|
||||
var targetId = this.getAttribute('href');
|
||||
if (targetId === '#') return;
|
||||
|
||||
var target = document.querySelector(targetId);
|
||||
if (target) {
|
||||
e.preventDefault();
|
||||
closeMenu();
|
||||
|
||||
var navHeight = navbar ? navbar.offsetHeight : 0;
|
||||
var targetPos = target.getBoundingClientRect().top + window.pageYOffset - navHeight;
|
||||
|
||||
window.scrollTo({
|
||||
top: targetPos,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ================================================================
|
||||
// 4. Navbar Background/Shadow on Scroll
|
||||
// ================================================================
|
||||
var lastScrollY = 0;
|
||||
|
||||
function handleNavbarScroll() {
|
||||
var scrollY = window.pageYOffset || document.documentElement.scrollTop;
|
||||
|
||||
if (scrollY > 20) {
|
||||
navbar.classList.add('navbar--scrolled');
|
||||
} else {
|
||||
navbar.classList.remove('navbar--scrolled');
|
||||
}
|
||||
|
||||
lastScrollY = scrollY;
|
||||
}
|
||||
|
||||
if (navbar) {
|
||||
window.addEventListener('scroll', handleNavbarScroll, { passive: true });
|
||||
// Run once on load
|
||||
handleNavbarScroll();
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 5. Scroll Animations (Testimonials & fade-up elements)
|
||||
// ================================================================
|
||||
function animateOnScroll() {
|
||||
// Testimonial cards
|
||||
var testimonialCards = document.querySelectorAll('.testimonial-card:not(.animate-in)');
|
||||
testimonialCards.forEach(function (card, index) {
|
||||
var rect = card.getBoundingClientRect();
|
||||
var windowHeight = window.innerHeight;
|
||||
|
||||
if (rect.top < windowHeight * 0.88) {
|
||||
// Stagger the animation
|
||||
setTimeout(function () {
|
||||
card.classList.add('animate-in');
|
||||
}, index * 120);
|
||||
}
|
||||
});
|
||||
|
||||
// Generic fade-up elements
|
||||
var fadeElements = document.querySelectorAll('.fade-up:not(.visible)');
|
||||
fadeElements.forEach(function (el) {
|
||||
var rect = el.getBoundingClientRect();
|
||||
var windowHeight = window.innerHeight;
|
||||
|
||||
if (rect.top < windowHeight * 0.88) {
|
||||
el.classList.add('visible');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', animateOnScroll, { passive: true });
|
||||
// Run once on load to catch elements already in viewport
|
||||
animateOnScroll();
|
||||
|
||||
// ================================================================
|
||||
// 6. Close mobile dropdown on window resize to desktop
|
||||
// ================================================================
|
||||
window.addEventListener('resize', function () {
|
||||
if (window.innerWidth > 768) {
|
||||
closeMenu();
|
||||
dropdownItems.forEach(function (item) {
|
||||
item.classList.remove('active');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user