import type { Metadata, Viewport } from "next"; import localFont from "next/font/local"; import { NextIntlClientProvider } from "next-intl"; import { getLocale } from "next-intl/server"; import { BRAND, BRAND_ASSETS, BRAND_COLORS } from "@/lib/brand"; import "./globals.css"; // Inter (Brandbook §11.5), selbst gehostet über next/font/local — kein Google-Fonts-Fetch // zur Build- oder Laufzeit (DSGVO, reproduzierbarer Offline-Build). Variable Font // (Gewichte 100–900 in einer Datei). TODO(brand): auf woff2-Subsets umstellen (kleiner). const inter = localFont({ variable: "--font-inter", display: "swap", src: [{ path: "./fonts/inter-variable.ttf", weight: "100 900", style: "normal" }], }); export const metadata: Metadata = { // Untertitel-Muster: Unterseiten setzen nur ihren eigenen Titel, die Marke hängt an. title: { default: `${BRAND.name} — ${BRAND.tagline}`, template: `%s · ${BRAND.name}` }, description: BRAND.description, applicationName: BRAND.name, manifest: "/site.webmanifest", // Icons aus dem Craftvia-Signet erzeugt (scripts/generate-brand-icons.ts). icons: { icon: [ { url: "/favicon.ico", sizes: "any" }, { url: BRAND_ASSETS.favicon, type: "image/svg+xml" }, { url: "/favicon/icon-32.png", type: "image/png", sizes: "32x32" }, ], apple: [{ url: BRAND_ASSETS.appleTouchIcon, sizes: "180x180" }], }, appleWebApp: { capable: true, title: BRAND.name, statusBarStyle: "default" }, openGraph: { type: "website", siteName: BRAND.name, title: `${BRAND.name} — ${BRAND.tagline}`, description: BRAND.description, images: [{ url: BRAND_ASSETS.ogImage, width: 512, height: 512 }], }, }; export const viewport: Viewport = { themeColor: BRAND_COLORS.lotsenblau, }; export default async function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { const locale = await getLocale(); return (