diff --git a/src/app/layout.tsx b/src/app/layout.tsx new file mode 100644 index 0000000..62ad259 --- /dev/null +++ b/src/app/layout.tsx @@ -0,0 +1,49 @@ +import type { Metadata } from "next"; +import { Bricolage_Grotesque, Instrument_Sans, JetBrains_Mono } from "next/font/google"; +import "./globals.css"; +import { Providers } from "@/app/providers"; + +const fontDisplay = Bricolage_Grotesque({ + subsets: ["latin"], + variable: "--font-display", + display: "swap", +}); + +const fontSans = Instrument_Sans({ + subsets: ["latin"], + variable: "--font-sans", + display: "swap", +}); + +const fontMono = JetBrains_Mono({ + subsets: ["latin"], + variable: "--font-mono", + display: "swap", +}); + +export const metadata: Metadata = { + title: "CoaxysPanel — Server Hosting Control Center", + description: "A frontend-only hosting control center for CoaxysPanel.", + icons: [{ rel: "icon", url: "/favicon.svg" }], +}; + +// Applies persisted appearance preferences before first paint to avoid a +// flash of the wrong theme. Mirrors the logic in Providers. +const themeInitScript = `(function(){try{var s=(JSON.parse(localStorage.getItem("coaxyspanel-ui")||"{}").state)||{};var r=document.documentElement;var t=s.theme||"dark";r.classList.toggle("dark",t==="dark"||(t==="system"&&matchMedia("(prefers-color-scheme: dark)").matches));r.dataset.accent=s.accent||"azure";r.dataset.glass=s.glass||"subtle";r.dataset.radius=s.radius||"rounded";r.dataset.ambiance=s.ambiance===true?"on":"off";r.classList.add("density-"+(s.density||"compact"));}catch(e){document.documentElement.classList.add("dark");document.documentElement.dataset.glass="subtle";document.documentElement.dataset.ambiance="off";}})();`; + +export default function RootLayout({ children }: { children: React.ReactNode }) { + return ( + +
+ + + +