mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 06:06:37 +03:00
* Add design-aware detector rules * Fix design-aware detector noise * Unify CLI and hook detector ignores * Fix remaining design-system review findings * Add detector ignore CLI * Fix design detector review findings * Fix design color source false positives * Fix core test suite registration * Add design-aware detector docs * Fix font priority design-system parsing * Fix color ignore value matching
125 lines
4.2 KiB
Plaintext
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@400;500;600;700&family=Alumni+Sans+Pinstripe&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>
|