99 lines
2.5 KiB
Plaintext
99 lines
2.5 KiB
Plaintext
---
|
|
import { ClientRouter } from 'astro:transitions';
|
|
|
|
import Navigation from '../components/Navigation.astro';
|
|
import Footer from '../components/Footer.astro';
|
|
import Background from '../components/Background.astro';
|
|
|
|
import '../styles/global.css';
|
|
|
|
interface Props {
|
|
title?: string | undefined;
|
|
description?: string | undefined;
|
|
}
|
|
|
|
const { title, description } = Astro.props;
|
|
---
|
|
|
|
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width" />
|
|
<link rel="icon" type="image/svg+xml" href="/favicon.png" />
|
|
<meta name="generator" content={Astro.generator} />
|
|
<meta name="description" content={description} />
|
|
<title>{title}</title>
|
|
<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;600;700&display=swap"
|
|
rel="stylesheet"
|
|
/>
|
|
<!-- Load theme early to prevent flashes between light and dark modes -->
|
|
<script is:inline>
|
|
const theme = (() => {
|
|
if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
|
|
return localStorage.getItem('theme');
|
|
}
|
|
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
|
return 'dark';
|
|
}
|
|
return 'light';
|
|
})();
|
|
|
|
if (theme === 'light') {
|
|
document.documentElement.classList.remove('dark');
|
|
} else {
|
|
document.documentElement.classList.add('dark');
|
|
}
|
|
window.localStorage.setItem('theme', theme);
|
|
</script>
|
|
<ClientRouter />
|
|
</head>
|
|
<body
|
|
class="flex min-h-screen flex-col bg-white text-zinc-900 dark:bg-zinc-900 dark:text-zinc-100"
|
|
>
|
|
<Background />
|
|
|
|
<div class="mx-auto w-full max-w-3xl grow px-4 sm:px-6">
|
|
<Navigation />
|
|
<main class="py-12">
|
|
<slot />
|
|
</main>
|
|
</div>
|
|
<Footer />
|
|
</body>
|
|
</html>
|
|
|
|
<style>
|
|
/* Content entrance animation */
|
|
main {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
transition:
|
|
opacity 0.5s ease,
|
|
transform 0.5s ease;
|
|
}
|
|
|
|
main.content-entering {
|
|
animation: content-fade-in 0.6s ease forwards;
|
|
}
|
|
|
|
@keyframes content-fade-in {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(10px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
/* Theme transition effect */
|
|
body.theme-transitioning * {
|
|
transition-duration: 0.3s !important;
|
|
}
|
|
</style>
|