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>
 |