← back to Nineoh Guide

apps/web/app/layout.tsx

94 lines

import type { Metadata } from "next";
import { Playfair_Display, Inter } from "next/font/google";
import { APP, SITE_URL } from "@nineoh/core";
import "./globals.css";

const display = Playfair_Display({
  subsets: ["latin"],
  weight: ["600", "700"],
  variable: "--font-display",
  display: "swap",
});
const body = Inter({
  subsets: ["latin"],
  variable: "--font-body",
  display: "swap",
});

export const metadata: Metadata = {
  metadataBase: new URL(SITE_URL),
  title: {
    default: `${APP.displayName} — Unofficial Episode & Cast Guide`,
    template: `%s · ${APP.displayName}`,
  },
  description:
    "An unofficial, fan-made guide to the 90210 series: original episode recaps, cast bios, and news. Not affiliated with the show's producers, network, or cast.",
  robots: { index: true, follow: true },
};

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" className={`${display.variable} ${body.variable}`}>
      <body>
        <header className="site-header">
          <div className="bar">
            <a className="brand" href="/" aria-label={APP.displayName}>
              <Mark />
              <strong style={{ fontFamily: "var(--font-display)", fontSize: 19 }}>
                90210 Guide
              </strong>
              <span className="badge">Unofficial</span>
            </a>
            <input type="checkbox" id="navtoggle" className="nav-toggle" aria-hidden="true" />
            <label htmlFor="navtoggle" className="hamburger" aria-label="Open menu">
              ☰
            </label>
            <nav className="nav">
              <a href="/show">Series</a>
              <a href="/episodes">Episodes</a>
              <a href="/cast">Cast</a>
              <a href="/characters">Characters</a>
              <a href="/news">News</a>
              <a href="/games">Games</a>
              <a href="/community">Community</a>
              <a href="/search">Search</a>
            </nav>
          </div>
        </header>

        <main className="wrap">{children}</main>

        <footer className="site-footer">
          {APP.disclaimerShort}{" "}
          <a href="/legal/disclaimer">Disclaimer</a> ·{" "}
          <a href="/legal/dmca">Copyright/DMCA</a> ·{" "}
          <a href="/legal/privacy">Privacy</a>
        </footer>
      </body>
    </html>
  );
}

/* Original art-deco sun mark — our brand glyph, not the show's. */
function Mark() {
  return (
    <svg width="26" height="26" viewBox="0 0 40 40" aria-hidden="true">
      <circle cx="20" cy="24" r="10" fill="#c19a3e" />
      <g stroke="#c19a3e" strokeWidth="2" strokeLinecap="round">
        {Array.from({ length: 7 }).map((_, i) => {
          const a = Math.PI - (Math.PI / 6) * i;
          return (
            <line
              key={i}
              x1={20 + Math.cos(a) * 13}
              y1={24 - Math.sin(a) * 13}
              x2={20 + Math.cos(a) * 18}
              y2={24 - Math.sin(a) * 18}
            />
          );
        })}
      </g>
    </svg>
  );
}