Files
pbakaus_impeccable/site/layouts/Base.astro
T
Paul BakausandClaude Opus 4.8 1fe9c41759 Replace Alumni Sans Pinstripe with Alumni Sans across the type system
The Pinstripe display face was single-weight, so every `font-weight` on it
was inert — the documented h1/h2 weight split never actually rendered.
Switch --ks-font-display (and --ks-font-wordmark) to plain Alumni Sans, which
honors weight, and set the display scale intentionally:

- Display / h1  -> weight 100 (thin hairline hero)
- Headline / h2 -> weight 300 via --ks-type-headline-weight (light anchor)
- Wordmark 400, body 400, title 500 unchanged

Centralize h2 weight: the eight section-title sites that hardcoded 600 now
read var(--ks-type-headline-weight), so h2 weight is a single lever.

Google Fonts now loads Alumni Sans wght@100;300;...;700 and no longer pulls
the Pinstripe family. DESIGN.md, design.json, and the token/CSS comments are
updated to match (family, weights, Two-Face and Weight-Inversion rules).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 17:32:47 -07:00

125 lines
4.2 KiB
Plaintext

---
import Header from '../components/Header.astro';
import Footer from '../components/Footer.astro';
// Site-global CSS: tokens first (defines --ks-*), kit second (consumes them),
// footer styling third. Every page using Base.astro picks these up; no need
// to re-import from page-level stylesheets.
import '../styles/kinpaku-tokens.css';
import '../styles/kinpaku-kit.css';
import '../styles/light-mode.css';
import '../styles/footer.css';
interface Props {
title: string;
description?: string;
activeNav?: 'home' | 'designing' | 'docs' | 'slop' | 'live';
canonicalPath?: string;
bodyClass?: string;
noIndex?: boolean;
mainId?: string;
mainClass?: string;
hideHeader?: boolean;
hideFooter?: boolean;
ogTitle?: string;
ogDescription?: string;
ogImage?: string;
twitterSite?: string;
twitterCreator?: string;
}
const {
title,
description = 'Design fluency for AI-assisted frontend development.',
activeNav,
canonicalPath,
bodyClass,
noIndex = false,
mainId = 'main',
mainClass,
hideHeader = false,
hideFooter = false,
ogTitle,
ogDescription,
ogImage,
twitterSite,
twitterCreator,
} = Astro.props;
const canonical = canonicalPath
? `https://impeccable.style${canonicalPath}`
: undefined;
// Social card defaults. Every page gets the brand card unless it passes its own.
const SITE_OG_IMAGE = 'https://impeccable.style/og-image-v2.jpg';
const ogImageUrl = ogImage || SITE_OG_IMAGE;
const resolvedOgTitle = ogTitle || title;
const resolvedOgDescription = ogDescription || description;
---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{title}</title>
<meta name="description" content={description}>
<meta name="theme-color" content="#010101">
<script is:inline>
(function () {
try {
var t = localStorage.getItem('impeccable-theme');
var root = document.documentElement;
var pref = (t === 'light' || t === 'dark') ? t : 'auto';
var resolved = pref === 'auto'
? (window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark')
: pref;
root.classList.add(resolved);
root.setAttribute('data-theme-pref', pref);
if (resolved === 'light') {
var meta = document.querySelector('meta[name="theme-color"]');
if (meta) meta.setAttribute('content', '#f7f4ef');
}
} catch (e) {}
})();
</script>
{noIndex && <meta name="robots" content="noindex">}
{canonical && <link rel="canonical" href={canonical}>}
<meta property="og:type" content="website">
<meta property="og:url" content={canonical || 'https://impeccable.style'}>
<meta property="og:title" content={resolvedOgTitle}>
<meta property="og:description" content={resolvedOgDescription}>
<meta property="og:image" content={ogImageUrl}>
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta name="twitter:card" content="summary_large_image">
{twitterSite && <meta name="twitter:site" content={twitterSite}>}
{twitterCreator && <meta name="twitter:creator" content={twitterCreator}>}
<meta name="twitter:title" content={resolvedOgTitle}>
<meta name="twitter:description" content={resolvedOgDescription}>
<meta name="twitter:image" content={ogImageUrl}>
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<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=Albert+Sans:wght@300;400;500;600;700&family=Alumni+Sans:wght@100;300;400;500;600;700&display=swap" rel="stylesheet">
<slot name="head" />
</head>
<body class={bodyClass}>
<a href={`#${mainId}`} class="skip-link">Skip to content</a>
<slot name="before-header" />
{!hideHeader && <Header activeNav={activeNav} />}
<slot name="after-header" />
<main id={mainId} class={mainClass}>
<slot />
</main>
{!hideFooter && <Footer />}
<slot name="scripts" />
<script>
import { initThemeToggle } from '../scripts/utils/theme.js';
initThemeToggle();
</script>
</body>
</html>