94 lines
2.7 KiB
Plaintext
94 lines
2.7 KiB
Plaintext
---
|
|
import BaseHead from '../components/BaseHead.astro';
|
|
import Footer from '../components/Footer.astro';
|
|
import GridOverlay from '../components/GridOverlay.astro';
|
|
import Navigation from '../components/Navigation.astro';
|
|
import CustomCursor from '../components/CustomCursor';
|
|
import { SITE_TITLE, SITE_DESCRIPTION } from '../consts';
|
|
|
|
interface Props {
|
|
title?: string;
|
|
description?: string;
|
|
usePadding?: boolean;
|
|
}
|
|
|
|
const { title = SITE_TITLE, description = SITE_DESCRIPTION, usePadding = true } = Astro.props;
|
|
---
|
|
|
|
<!DOCTYPE html>
|
|
<html lang="en" class="scroll-smooth">
|
|
<head>
|
|
<BaseHead title={title} description={description} />
|
|
</head>
|
|
<body class="antialiased selection:bg-brand-accent selection:text-brand-dark bg-brand-dark text-white">
|
|
<CustomCursor client:load />
|
|
<GridOverlay />
|
|
<Navigation />
|
|
|
|
<main class:list={["relative z-10 min-h-screen pb-24", { "pt-32 lg:pt-48": usePadding }]}>
|
|
<slot />
|
|
</main>
|
|
|
|
<Footer />
|
|
|
|
<script>
|
|
// Initialize Lucide icons
|
|
// @ts-ignore
|
|
if (window.lucide) {
|
|
// @ts-ignore
|
|
window.lucide.createIcons();
|
|
}
|
|
|
|
// ===== SCROLL ANIMATION SYSTEM =====
|
|
|
|
// Observer for scroll-triggered animations
|
|
const scrollObserverOptions = {
|
|
threshold: 0.15,
|
|
rootMargin: "0px 0px -50px 0px"
|
|
};
|
|
|
|
const scrollObserver = new IntersectionObserver((entries) => {
|
|
entries.forEach(entry => {
|
|
if (entry.isIntersecting) {
|
|
entry.target.classList.add('is-visible');
|
|
// Optionally unobserve after animation
|
|
// scrollObserver.unobserve(entry.target);
|
|
}
|
|
});
|
|
}, scrollObserverOptions);
|
|
|
|
// Observe all animate-on-scroll elements
|
|
document.querySelectorAll('.animate-on-scroll').forEach(el => {
|
|
scrollObserver.observe(el);
|
|
});
|
|
|
|
// Observer for legacy reveal-text animations
|
|
const revealObserverOptions = {
|
|
threshold: 0.1,
|
|
rootMargin: "0px"
|
|
};
|
|
|
|
const revealObserver = new IntersectionObserver((entries) => {
|
|
entries.forEach(entry => {
|
|
if (entry.isIntersecting) {
|
|
entry.target.classList.add('active');
|
|
}
|
|
});
|
|
}, revealObserverOptions);
|
|
|
|
document.querySelectorAll('.reveal-text').forEach(el => {
|
|
revealObserver.observe(el);
|
|
});
|
|
|
|
// Auto-stagger children in containers with .stagger-children class
|
|
document.querySelectorAll('.stagger-children').forEach(container => {
|
|
const children = container.querySelectorAll('.animate-on-scroll');
|
|
children.forEach((child, index) => {
|
|
child.classList.add(`stagger-${Math.min(index + 1, 8)}`);
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|
|
|