import Link from "next/link"; import type { CSSProperties, ReactNode } from "react"; import { THEMES, type ThemeId } from "@/themes/registry"; import { getSettings } from "@/lib/settings"; import { isAdmin } from "@/lib/auth"; import ThemeSwitcher from "./ThemeSwitcher"; import Clock from "./Clock"; // Shared, theme-agnostic page chrome. Every theme restyles these `rb-` classes // to look like its own OS/console. The HTML skeleton never changes. export default async function Shell({ theme, title, children, }: { theme: ThemeId; title: string; children: ReactNode; }) { const settings = getSettings(); const admin = await isAdmin(); // Admins always get the switcher with every skin; the public only sees it when // enabled, and only the allowed skins. const showSwitcher = admin || settings.publicThemeToggle; const switcherThemes = admin ? THEMES : THEMES.filter((t) => settings.allowedThemes.includes(t.id)); return (
{/* Decorative background field. Hidden by default; themes opt in (PS2 uses it for the BIOS bobbing-cube field). */}
{Array.from({ length: 15 * 13 }).map((_, i) => { // deterministic pseudo-random thickness + bob phase per cube const h = 34 + ((i * 53) % 78); const delay = (((i * 37) % 100) / 100) * 4; return ( ); })}
{title} — {settings.title}
{children}
Ready {settings.footer}
); }