2026-03-02 22:21:19 +03:00
|
|
|
<!--
|
|
|
|
|
Component: Layout
|
|
|
|
|
Application shell with providers and page wrapper
|
|
|
|
|
-->
|
2026-01-02 16:09:03 +03:00
|
|
|
<script lang="ts">
|
2026-03-02 22:21:19 +03:00
|
|
|
import { themeManager } from '$features/ChangeAppTheme';
|
2026-04-22 13:00:29 +03:00
|
|
|
import G from '$shared/assets/G.svg';
|
2026-02-06 14:20:32 +03:00
|
|
|
import { ResponsiveProvider } from '$shared/lib';
|
2026-04-23 09:48:32 +03:00
|
|
|
import { cn } from '$shared/lib';
|
2026-04-22 13:01:46 +03:00
|
|
|
import { Footer } from '$widgets/Footer';
|
|
|
|
|
|
2026-06-01 10:06:12 +03:00
|
|
|
/*
|
|
|
|
|
Preload the two render-critical interface faces (primary + secondary).
|
|
|
|
|
`?url` resolves to the content-hashed path Vite emits, so the binary is
|
|
|
|
|
fetched immediately rather than waiting for CSS @font-face discovery.
|
|
|
|
|
*/
|
|
|
|
|
import interWoff2 from '../assets/fonts/inter-latin-opsz-normal.woff2?url';
|
|
|
|
|
import spaceGroteskWoff2 from '../assets/fonts/space-grotesk-latin-wght-normal.woff2?url';
|
|
|
|
|
|
2026-02-10 13:08:07 +03:00
|
|
|
import {
|
|
|
|
|
type Snippet,
|
2026-02-27 12:23:31 +03:00
|
|
|
onDestroy,
|
2026-02-10 13:08:07 +03:00
|
|
|
onMount,
|
|
|
|
|
} from 'svelte';
|
2026-01-24 15:32:01 +03:00
|
|
|
|
|
|
|
|
interface Props {
|
2026-03-02 22:21:19 +03:00
|
|
|
/**
|
|
|
|
|
* Content snippet
|
|
|
|
|
*/
|
2026-01-24 15:32:01 +03:00
|
|
|
children: Snippet;
|
|
|
|
|
}
|
2026-01-02 16:09:03 +03:00
|
|
|
|
2026-01-24 15:32:01 +03:00
|
|
|
let { children }: Props = $props();
|
2026-03-02 22:21:19 +03:00
|
|
|
let fontsReady = $state(true);
|
2026-02-27 12:23:31 +03:00
|
|
|
const theme = $derived(themeManager.value);
|
2026-02-10 13:08:07 +03:00
|
|
|
|
2026-02-27 12:23:31 +03:00
|
|
|
onMount(() => themeManager.init());
|
|
|
|
|
onDestroy(() => themeManager.destroy());
|
2026-01-02 16:09:03 +03:00
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<svelte:head>
|
2026-04-22 13:00:29 +03:00
|
|
|
<link rel="icon" href={G} type="image/svg+xml" />
|
2026-02-10 13:08:07 +03:00
|
|
|
|
2026-06-01 10:06:12 +03:00
|
|
|
<!-- Self-hosted interface fonts (see src/app/styles/fonts/fonts.css). Preload the two critical faces. -->
|
2026-02-18 17:39:24 +03:00
|
|
|
<link
|
2026-06-01 10:06:12 +03:00
|
|
|
rel="preload"
|
|
|
|
|
as="font"
|
|
|
|
|
type="font/woff2"
|
|
|
|
|
href={interWoff2}
|
2026-02-18 17:39:24 +03:00
|
|
|
crossorigin="anonymous"
|
|
|
|
|
/>
|
2026-01-22 15:31:59 +03:00
|
|
|
<link
|
2026-02-10 13:08:07 +03:00
|
|
|
rel="preload"
|
2026-06-01 10:06:12 +03:00
|
|
|
as="font"
|
|
|
|
|
type="font/woff2"
|
|
|
|
|
href={spaceGroteskWoff2}
|
|
|
|
|
crossorigin="anonymous"
|
2026-02-18 17:39:24 +03:00
|
|
|
/>
|
2026-03-02 22:21:19 +03:00
|
|
|
<title>GlyphDiff | Typography & Typefaces</title>
|
2026-04-19 19:15:46 +03:00
|
|
|
<meta
|
|
|
|
|
name="description"
|
|
|
|
|
content="Compare typefaces side by side. Adjust size, weight, leading, and tracking to find the perfect typographic pairing."
|
|
|
|
|
/>
|
2026-01-02 16:09:03 +03:00
|
|
|
</svelte:head>
|
|
|
|
|
|
2026-02-06 14:20:32 +03:00
|
|
|
<ResponsiveProvider>
|
2026-02-27 12:23:31 +03:00
|
|
|
<div
|
|
|
|
|
id="app-root"
|
2026-04-23 09:48:32 +03:00
|
|
|
class={cn(
|
2026-05-25 10:20:40 +03:00
|
|
|
'min-h-dvh w-auto flex flex-col surface-canvas relative',
|
2026-02-27 12:23:31 +03:00
|
|
|
theme === 'dark' ? 'dark' : '',
|
|
|
|
|
)}
|
|
|
|
|
>
|
2026-04-17 13:20:01 +03:00
|
|
|
{#if fontsReady}
|
|
|
|
|
{@render children?.()}
|
|
|
|
|
{/if}
|
2026-04-22 13:01:46 +03:00
|
|
|
|
|
|
|
|
<Footer />
|
2026-02-06 14:20:32 +03:00
|
|
|
</div>
|
|
|
|
|
</ResponsiveProvider>
|