Files
bztmon-site/src/layouts/Layout.astro
T
jwright f6d92e5c87
build-and-deploy / build (push) Failing after 14m48s
ui: Motion-driven animation layer (motion.dev)
Unify scroll reveals, hero entrance, nav active-underline, button springs,
the scroll-progress bar and backdrop parallax under one Motion system
(src/scripts/anim.ts), bundled into a self-hosted /_astro module so CSP
script-src 'self' holds. Progress bar + parallax now scroll()-driven and
cross-browser (was Chromium-only animation-timeline). Fail-open, reduced-motion
aware, content fully visible with JS off.
2026-06-28 23:23:58 +10:00

81 lines
2.8 KiB
Plaintext

---
import "../styles/global.css";
import Nav from "../components/Nav.astro";
import Footer from "../components/Footer.astro";
import { site } from "../data/site";
interface Props {
title?: string;
description?: string;
/** Path to the page, e.g. "/projects" — used for canonical + OG url. */
path?: string;
}
const {
title,
description = site.positioning,
path = "/",
} = Astro.props;
const pageTitle = title ? `${title} — ${site.name}` : `${site.name} · ${site.role}`;
const canonical = new URL(path, site.url).href;
const ogImage = new URL(site.ogImage, site.url).href;
---
<!doctype html>
<html lang={site.locale}>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg?v=2" />
<link rel="canonical" href={canonical} />
<title>{pageTitle}</title>
<meta name="description" content={description} />
<meta name="author" content={site.name} />
<!-- Open Graph -->
<meta property="og:type" content="website" />
<meta property="og:title" content={pageTitle} />
<meta property="og:description" content={description} />
<meta property="og:url" content={canonical} />
<meta property="og:image" content={ogImage} />
<meta property="og:site_name" content={site.name} />
<!-- Twitter -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={pageTitle} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={ogImage} />
<meta name="theme-color" content="#090c14" />
<!-- Single external script: pre-paint theme + toggle + scroll reveal.
Blocking in <head> so the theme is set before first paint (no flash).
No inline JS anywhere on the site → strict CSP script-src 'self'. -->
<script is:inline src="/site.js"></script>
</head>
<body>
<!-- PRO scroll UI (CSS-only, CSP-safe): a top progress line + a page-wide
flowing aurora that drifts continuously and parallaxes on scroll. -->
<div class="scroll-progress" aria-hidden="true"></div>
<div class="site-bg" aria-hidden="true">
<img class="site-bg__img site-bg__img--dark" src="/batcore-dark.webp" alt="" decoding="async" />
<img class="site-bg__img site-bg__img--light" src="/batcore-light.webp" alt="" decoding="async" />
<div class="site-bg__scrim"></div>
</div>
<a class="skip-link" href="#main">Skip to content</a>
<Nav />
<main id="main">
<slot />
</main>
<Footer />
<!-- Motion (motion.dev) animation layer. NOT is:inline → Astro/Vite bundles
it to a self-hosted /_astro/[hash].js (has src=) → strict CSP holds. -->
<script>
import "../scripts/anim.ts";
</script>
</body>
</html>