feat: SiteLayout template + World menu with 5 new pages (Lore, World, Characters, Music, Gallery)

- SiteLayout.tsx: shared layout component with nav dropdown, mobile hamburger drawer, full footer
- Nav: World dropdown menu (Lore, World, Characters, Music, Gallery) + Follow link
- Footer: 3-column (World links, Social links, Legal links) + tagline
- pages/lore.tsx: lore entry grid with placeholder canon entries
- pages/world.tsx: location/setting cards with worldbuilding teaser
- pages/characters.tsx: character roster with locked/revealed states
- pages/music.tsx: soundtrack page with Patreon CTA (inspired by silmaai.com music page)
- pages/gallery.tsx: tabbed Official / Fan Art gallery with empty states and social tag CTAs
- styles/Layout.module.css: shared nav, dropdown, footer, page hero, coming-soon styles
- styles/World.module.css: lore, location, character, music styles
- styles/Gallery.module.css: tabs, grid, card, empty state styles
- All pages: SEO meta, canonical URLs, OG tags
This commit is contained in:
2026-04-11 10:46:24 -05:00
parent b04d65f062
commit 8afb112eee
14 changed files with 2070 additions and 710 deletions
+77
View File
@@ -0,0 +1,77 @@
import SiteLayout from "./components/SiteLayout";
import layoutStyles from "@/styles/Layout.module.css";
import styles from "@/styles/World.module.css";
const CHARACTERS = [
{
emoji: "🦴",
name: "Bone Lord Bob",
role: "The Protagonist",
desc: "A man cursed to walk between worlds — carrying the weight of the dead and the rage of the living. He answers to no one. He owes everyone.",
revealed: true,
},
{
emoji: "🔥",
name: "???",
role: "Coming Soon",
desc: "A figure from the oldest part of the war. Their allegiance changes everything.",
revealed: false,
},
{
emoji: "⚔️",
name: "???",
role: "Coming Soon",
desc: "Every legend needs its foil. Every bone lord needs someone willing to break them.",
revealed: false,
},
{
emoji: "🌑",
name: "???",
role: "Coming Soon",
desc: "They were there at the beginning. They will be there at the end. What happens in between is the story.",
revealed: false,
},
];
export default function Characters() {
return (
<SiteLayout
title="Characters"
description="Meet the characters of Bone Lord Bob — heroes, villains, and everything in between."
keywords="Bone Lord Bob characters, BLB cast, dark fantasy characters, anime characters"
canonical="/characters"
>
{/* Hero */}
<div className={layoutStyles.pageHero}>
<span className={layoutStyles.pageEyebrow}>The Cast</span>
<h1 className={layoutStyles.pageTitle}>Characters</h1>
<p className={layoutStyles.pageSub}>
Every soul in this world has a price. Meet the ones who pay it.
</p>
</div>
<div className={layoutStyles.pageContent}>
<div className={styles.characterGrid}>
{CHARACTERS.map((c, i) => (
<div key={i} className={`${styles.characterCard} ${!c.revealed ? styles.characterCardLocked : ""}`}>
<div className={styles.characterArt}>
<span className={styles.characterEmoji}>{c.emoji}</span>
{!c.revealed && <div className={styles.characterLockedOverlay}>?</div>}
</div>
<div className={styles.characterInfo}>
<span className={styles.characterRole}>{c.role}</span>
<h2 className={styles.characterName}>{c.name}</h2>
<p className={styles.characterDesc}>{c.desc}</p>
</div>
</div>
))}
</div>
<div className={layoutStyles.comingSoon}>
<span className={layoutStyles.comingSoonSkull}>👤</span>
<p className={layoutStyles.comingSoonText}>Full character profiles reveal with each episode</p>
</div>
</div>
</SiteLayout>
);
}
+178
View File
@@ -0,0 +1,178 @@
import Head from "next/head";
import Link from "next/link";
import { useRouter } from "next/router";
import { useState } from "react";
import styles from "@/styles/Layout.module.css";
export interface SiteLayoutProps {
title?: string;
description?: string;
keywords?: string;
canonical?: string;
children: React.ReactNode;
}
const WORLD_LINKS = [
{ href: "/lore", label: "Lore" },
{ href: "/world", label: "World" },
{ href: "/characters", label: "Characters" },
{ href: "/music", label: "Music" },
{ href: "/gallery", label: "Gallery" },
];
export default function SiteLayout({
title = "Bone Lord Bob — American Anime",
description = "Bone Lord Bob is an original American Anime series — dark, brutal, beautiful.",
keywords = "Bone Lord Bob, American Anime, indie animation, dark fantasy",
canonical,
children,
}: SiteLayoutProps) {
const router = useRouter();
const [worldOpen, setWorldOpen] = useState(false);
const [mobileOpen, setMobileOpen] = useState(false);
const canonicalUrl = canonical
? `https://www.bonelordbob.com${canonical}`
: `https://www.bonelordbob.com${router.asPath.split("?")[0]}`;
const isActive = (href: string) =>
href === "/" ? router.pathname === "/" : router.pathname.startsWith(href);
const isWorldActive = WORLD_LINKS.some((l) => router.pathname.startsWith(l.href));
return (
<>
<Head>
<title>{title === "Bone Lord Bob — American Anime" ? title : `${title} | Bone Lord Bob`}</title>
<meta name="description" content={description} />
<meta name="keywords" content={keywords} />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="canonical" href={canonicalUrl} />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:url" content={canonicalUrl} />
<meta property="og:image" content="https://www.bonelordbob.com/og-image.png" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
</Head>
<div className={styles.site}>
{/* ── Nav ── */}
<nav className={styles.nav}>
<Link href="/" className={styles.navLogo}>
Bone Lord <span>Bob</span>
</Link>
{/* Desktop nav */}
<ul className={styles.navLinks}>
<li className={styles.navItem}>
<Link
href="/"
className={`${styles.navLink} ${isActive("/") ? styles.navLinkActive : ""}`}
>
Home
</Link>
</li>
{/* World dropdown */}
<li
className={styles.navItem}
onMouseEnter={() => setWorldOpen(true)}
onMouseLeave={() => setWorldOpen(false)}
>
<button
className={`${styles.navLink} ${styles.navDropdownTrigger} ${isWorldActive ? styles.navLinkActive : ""}`}
aria-haspopup="true"
aria-expanded={worldOpen}
>
World <span className={styles.chevron}></span>
</button>
{worldOpen && (
<div className={styles.dropdown}>
{WORLD_LINKS.map((l) => (
<Link
key={l.href}
href={l.href}
className={`${styles.dropdownItem} ${router.pathname === l.href ? styles.dropdownItemActive : ""}`}
onClick={() => setWorldOpen(false)}
>
{l.label}
</Link>
))}
</div>
)}
</li>
<li className={styles.navItem}>
<Link href="/#follow" className={styles.navLink}>
Follow
</Link>
</li>
</ul>
{/* Mobile hamburger */}
<button
className={styles.hamburger}
onClick={() => setMobileOpen(!mobileOpen)}
aria-label="Toggle menu"
>
<span /><span /><span />
</button>
</nav>
{/* Mobile drawer */}
{mobileOpen && (
<div className={styles.mobileDrawer}>
<Link href="/" className={styles.mobileLink} onClick={() => setMobileOpen(false)}>Home</Link>
<div className={styles.mobileSectionLabel}>World</div>
{WORLD_LINKS.map((l) => (
<Link key={l.href} href={l.href} className={styles.mobileLinkIndent} onClick={() => setMobileOpen(false)}>
{l.label}
</Link>
))}
<Link href="/#follow" className={styles.mobileLink} onClick={() => setMobileOpen(false)}>Follow</Link>
</div>
)}
{/* ── Page content ── */}
<main className={styles.main}>{children}</main>
{/* ── Footer ── */}
<footer className={styles.footer}>
<div className={styles.footerTop}>
<div className={styles.footerBrand}>
<span className={styles.footerLogo}>Bone Lord <span>Bob</span></span>
<p className={styles.footerTagline}>American Anime. Dark. Brutal. Beautiful.</p>
</div>
<div className={styles.footerColumns}>
<div className={styles.footerCol}>
<span className={styles.footerColTitle}>World</span>
{WORLD_LINKS.map((l) => (
<Link key={l.href} href={l.href} className={styles.footerLink}>{l.label}</Link>
))}
</div>
<div className={styles.footerCol}>
<span className={styles.footerColTitle}>Follow</span>
<a href="https://www.youtube.com/@bonelordbob" target="_blank" rel="noopener noreferrer" className={styles.footerLink}>YouTube</a>
<a href="https://x.com/bonelordbob" target="_blank" rel="noopener noreferrer" className={styles.footerLink}>X / Twitter</a>
<a href="https://www.instagram.com/bonelordbob" target="_blank" rel="noopener noreferrer" className={styles.footerLink}>Instagram</a>
<a href="https://www.facebook.com/profile.php?id=61580718487639" target="_blank" rel="noopener noreferrer" className={styles.footerLink}>Facebook</a>
<a href="https://www.tiktok.com/@bonelordbob" target="_blank" rel="noopener noreferrer" className={styles.footerLink}>TikTok</a>
<a href="https://www.patreon.com/BoneLordBob" target="_blank" rel="noopener noreferrer" className={styles.footerLink}>Patreon</a>
</div>
<div className={styles.footerCol}>
<span className={styles.footerColTitle}>Legal</span>
<Link href="/privacy" className={styles.footerLink}>Privacy Policy</Link>
<Link href="/terms" className={styles.footerLink}>Terms &amp; Conditions</Link>
</div>
</div>
</div>
<div className={styles.footerBottom}>
<span>© {new Date().getFullYear()} Mathison Projects Inc. All rights reserved.</span>
</div>
</footer>
</div>
</>
);
}
+136
View File
@@ -0,0 +1,136 @@
import { useState } from "react";
import SiteLayout from "./components/SiteLayout";
import layoutStyles from "@/styles/Layout.module.css";
import styles from "@/styles/Gallery.module.css";
type GalleryTab = "official" | "fan";
// Placeholder art items — swap src for real image paths when assets are ready
const OFFICIAL_ART: { src: string; alt: string; caption?: string }[] = [
// { src: "/gallery/official/blb-key-art.jpg", alt: "Bone Lord Bob key art", caption: "Key Art — Season 1" },
];
const FAN_ART: { src: string; alt: string; artist?: string; artistUrl?: string }[] = [
// { src: "/gallery/fan/fan-art-1.jpg", alt: "Fan art by ...", artist: "Artist Name", artistUrl: "https://..." },
];
export default function Gallery() {
const [tab, setTab] = useState<GalleryTab>("official");
return (
<SiteLayout
title="Gallery"
description="Official art and fan creations from the world of Bone Lord Bob."
keywords="Bone Lord Bob art, BLB gallery, fan art, official art, anime art, dark fantasy art"
canonical="/gallery"
>
{/* Hero */}
<div className={layoutStyles.pageHero}>
<span className={layoutStyles.pageEyebrow}>Art of the Bone Kingdom</span>
<h1 className={layoutStyles.pageTitle}>Gallery</h1>
<p className={layoutStyles.pageSub}>
Official art from the series and the community that&apos;s building around it.
</p>
</div>
<div className={layoutStyles.pageContent}>
{/* Tab switcher */}
<div className={styles.tabs}>
<button
className={`${styles.tab} ${tab === "official" ? styles.tabActive : ""}`}
onClick={() => setTab("official")}
>
Official Art
</button>
<button
className={`${styles.tab} ${tab === "fan" ? styles.tabActive : ""}`}
onClick={() => setTab("fan")}
>
Fan Art
</button>
</div>
{/* Official art */}
{tab === "official" && (
<div className={styles.section}>
{OFFICIAL_ART.length > 0 ? (
<div className={styles.grid}>
{OFFICIAL_ART.map((item, i) => (
<div key={i} className={styles.card}>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src={item.src} alt={item.alt} className={styles.cardImg} loading="lazy" />
{item.caption && <p className={styles.cardCaption}>{item.caption}</p>}
</div>
))}
</div>
) : (
<div className={styles.empty}>
<span className={styles.emptyIcon}>🎨</span>
<p className={styles.emptyTitle}>Official art gallery coming soon</p>
<p className={styles.emptyText}>
Character sheets, key art, and episode stills will live here.
</p>
</div>
)}
</div>
)}
{/* Fan art */}
{tab === "fan" && (
<div className={styles.section}>
{FAN_ART.length > 0 ? (
<div className={styles.grid}>
{FAN_ART.map((item, i) => (
<div key={i} className={styles.card}>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src={item.src} alt={item.alt} className={styles.cardImg} loading="lazy" />
{item.artist && (
<p className={styles.cardCaption}>
Art by{" "}
{item.artistUrl ? (
<a href={item.artistUrl} target="_blank" rel="noopener noreferrer">
{item.artist}
</a>
) : (
item.artist
)}
</p>
)}
</div>
))}
</div>
) : (
<div className={styles.empty}>
<span className={styles.emptyIcon}>💀</span>
<p className={styles.emptyTitle}>Fan art gallery coming soon</p>
<p className={styles.emptyText}>
Create something. Tag us on social with{" "}
<strong style={{ color: "var(--bone)" }}>#BoneLordBob</strong> and we&apos;ll feature
it here.
</p>
<div className={styles.emptyLinks}>
<a
href="https://x.com/bonelordbob"
target="_blank"
rel="noopener noreferrer"
className={styles.emptyBtn}
>
Tag us on X
</a>
<a
href="https://www.instagram.com/bonelordbob"
target="_blank"
rel="noopener noreferrer"
className={styles.emptyBtn}
>
Tag us on Instagram
</a>
</div>
</div>
)}
</div>
)}
</div>
</SiteLayout>
);
}
+18 -126
View File
@@ -1,7 +1,6 @@
import Head from "next/head";
import Image from "next/image";
import Link from "next/link";
import styles from "@/styles/Home.module.css";
import SiteLayout from "@/pages/components/SiteLayout";
const SOCIALS = [
{
@@ -50,64 +49,13 @@ const SOCIALS = [
export default function Home() {
return (
<>
<Head>
<title>Bone Lord Bob American Anime</title>
<meta
name="description"
content="Bone Lord Bob is an American Anime project — dark, brutal, beautiful. Coming soon."
/>
<meta
name="keywords"
content="Bone Lord Bob, BLB, American Anime, indie anime, dark fantasy anime, original anime series, animated series, dark fantasy, American animation, independent animation, bone kingdom"
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" sizes="any" />
<link rel="icon" href="/icon-192.png" type="image/png" sizes="192x192" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
{/* Open Graph */}
<meta property="og:title" content="Bone Lord Bob" />
<meta
property="og:description"
content="American Anime. Dark. Brutal. Beautiful."
/>
<meta property="og:type" content="website" />
<meta property="og:url" content="https://www.bonelordbob.com" />
<meta property="og:image" content="/og-image.png" />
<meta property="og:image:width" content="1536" />
<meta property="og:image:height" content="1024" />
{/* Twitter Card */}
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@BoneLordBob" />
<meta name="twitter:title" content="Bone Lord Bob" />
<meta
name="twitter:description"
content="American Anime. Dark. Brutal. Beautiful."
/>
<meta name="twitter:image" content="/og-image.png" />
</Head>
<SiteLayout
title="Bone Lord Bob — American Anime"
description="Bone Lord Bob is an American Anime project — dark, brutal, beautiful. Coming soon."
keywords="Bone Lord Bob, BLB, American Anime, indie anime, dark fantasy anime, original anime series, animated series, dark fantasy, American animation, independent animation, bone kingdom"
canonical="/"
>
<div className={styles.page}>
{/* ── Nav ─────────────────────────────────────────────────────── */}
<nav className={styles.nav}>
<span className={styles.navLogo}>
Bone Lord <span>Bob</span>
</span>
<ul className={styles.navLinks}>
<li>
<a href="#about">About</a>
</li>
<li>
<a href="#characters">Characters</a>
</li>
<li>
<a href="#follow">Follow</a>
</li>
</ul>
</nav>
{/* ── Hero ────────────────────────────────────────────────────── */}
<section className={styles.hero}>
<div className={styles.heroBg} />
@@ -133,21 +81,13 @@ export default function Home() {
{/* ── Divider ─────────────────────────────────────────────────── */}
<div className={styles.divider}>
{["💀", "💀", "💀", "💀", "💀", "💀", "💀", "💀", "💀", "💀"].map(
(s, i) => (
<span key={i} className={styles.dividerSkull}>
{s}
</span>
)
)}
{Array.from({ length: 10 }).map((_, i) => (
<span key={`l${i}`} className={styles.dividerSkull}>💀</span>
))}
<span className={styles.dividerText}>Coming Soon</span>
{["💀", "💀", "💀", "💀", "💀", "💀", "💀", "💀", "💀", "💀"].map(
(s, i) => (
<span key={i} className={styles.dividerSkull}>
{s}
</span>
)
)}
{Array.from({ length: 10 }).map((_, i) => (
<span key={`r${i}`} className={styles.dividerSkull}>💀</span>
))}
</div>
{/* ── About ───────────────────────────────────────────────────── */}
@@ -263,16 +203,12 @@ export default function Home() {
transition: "border-color 0.2s, background 0.2s",
}}
onMouseEnter={(e) => {
(e.currentTarget as HTMLAnchorElement).style.borderColor =
s.color;
(e.currentTarget as HTMLAnchorElement).style.background =
"#231e18";
(e.currentTarget as HTMLAnchorElement).style.borderColor = s.color;
(e.currentTarget as HTMLAnchorElement).style.background = "#231e18";
}}
onMouseLeave={(e) => {
(e.currentTarget as HTMLAnchorElement).style.borderColor =
"rgba(232,220,200,0.12)";
(e.currentTarget as HTMLAnchorElement).style.background =
"#1a1510";
(e.currentTarget as HTMLAnchorElement).style.borderColor = "rgba(232,220,200,0.12)";
(e.currentTarget as HTMLAnchorElement).style.background = "#1a1510";
}}
>
<span
@@ -316,51 +252,7 @@ export default function Home() {
</div>
</div>
</section>
{/* ── Footer ──────────────────────────────────────────────────── */}
<footer className={styles.footer}>
<span className={styles.footerLogo}>
Bone Lord <span>Bob</span>
</span>
<div
style={{
display: "flex",
flexWrap: "wrap",
alignItems: "center",
justifyContent: "center",
gap: "16px",
marginTop: "8px",
}}
>
<span className={styles.footerNote}>
© {new Date().getFullYear()} Mathison Projects Inc. All rights
reserved.
</span>
<span style={{ color: "rgba(232,220,200,0.2)" }}>|</span>
<Link
href="/privacy"
style={{
color: "#9e9080",
fontSize: "0.82rem",
textDecoration: "none",
}}
>
Privacy Policy
</Link>
<span style={{ color: "rgba(232,220,200,0.2)" }}>|</span>
<Link
href="/terms"
style={{
color: "#9e9080",
fontSize: "0.82rem",
textDecoration: "none",
}}
>
Terms &amp; Conditions
</Link>
</div>
</footer>
</div>
</>
</SiteLayout>
);
}
+63
View File
@@ -0,0 +1,63 @@
import SiteLayout from "./components/SiteLayout";
import layoutStyles from "@/styles/Layout.module.css";
import styles from "@/styles/World.module.css";
export default function Lore() {
return (
<SiteLayout
title="Lore"
description="The mythology and deep lore of Bone Lord Bob — a world built on bone, blood, and ancient power."
keywords="Bone Lord Bob lore, BLB mythology, dark fantasy lore, anime worldbuilding"
canonical="/lore"
>
{/* Hero */}
<div className={layoutStyles.pageHero}>
<span className={layoutStyles.pageEyebrow}>The Deep Canon</span>
<h1 className={layoutStyles.pageTitle}>Lore</h1>
<p className={layoutStyles.pageSub}>
Every world has rules. Every myth has teeth. Here begins the canon of Bone Lord Bob.
</p>
</div>
<div className={layoutStyles.pageContent}>
{/* Placeholder lore entries */}
<div className={styles.loreGrid}>
<div className={styles.loreCard}>
<span className={styles.loreIcon}>💀</span>
<h2 className={styles.loreTitle}>The Bone Covenant</h2>
<p className={styles.loreText}>
In the beginning there was only the great silence and then the crack. From that first
fracture, the Bone Kingdom was born. Those who heard it gained dominion over death itself.
</p>
<span className={styles.loreLocked}>More coming soon</span>
</div>
<div className={styles.loreCard}>
<span className={styles.loreIcon}>🔥</span>
<h2 className={styles.loreTitle}>The Cursed Tongue</h2>
<p className={styles.loreText}>
There is a language older than memory. Those who speak it fluently enough can unmake a
living thing or bind the dead to their will. Very few have lived long enough to master it.
</p>
<span className={styles.loreLocked}>More coming soon</span>
</div>
<div className={styles.loreCard}>
<span className={styles.loreIcon}></span>
<h2 className={styles.loreTitle}>The Three Kingdoms</h2>
<p className={styles.loreText}>
The world is divided not by geography, but by allegiance to one of three ancient powers.
The war between them has lasted longer than any living creature can remember.
</p>
<span className={styles.loreLocked}>More coming soon</span>
</div>
</div>
<div className={layoutStyles.comingSoon}>
<span className={layoutStyles.comingSoonSkull}>📜</span>
<p className={layoutStyles.comingSoonText}>Full lore archive unlocking as the series releases</p>
</div>
</div>
</SiteLayout>
);
}
+82
View File
@@ -0,0 +1,82 @@
import SiteLayout from "./components/SiteLayout";
import layoutStyles from "@/styles/Layout.module.css";
import styles from "@/styles/World.module.css";
// Placeholder — tracks will be added when official BLB soundtrack assets are available
const TRACKS: { title: string; vibe: string; file?: string }[] = [
// { title: "Bone Kingdom Theme", vibe: "Dark orchestral", file: "/music/bone-kingdom-theme.mp3" },
];
export default function Music() {
return (
<SiteLayout
title="Music"
description="The official soundtrack of Bone Lord Bob — dark, atmospheric, and alive with the energy of the Bone Kingdom."
keywords="Bone Lord Bob music, BLB soundtrack, dark fantasy music, anime music, original soundtrack"
canonical="/music"
>
{/* Hero */}
<div className={layoutStyles.pageHero}>
<span className={layoutStyles.pageEyebrow}>The Soundtrack</span>
<h1 className={layoutStyles.pageTitle}>Music</h1>
<p className={layoutStyles.pageSub}>
The Bone Kingdom has a sound. Dark. Relentless. Yours.
</p>
</div>
<div className={layoutStyles.pageContent}>
{TRACKS.length > 0 ? (
<div className={styles.tracklist}>
{TRACKS.map((t, i) => (
<div key={i} className={styles.track}>
<span className={styles.trackNum}>{String(i + 1).padStart(2, "0")}</span>
<div className={styles.trackInfo}>
<span className={styles.trackTitle}>{t.title}</span>
<span className={styles.trackVibe}>{t.vibe}</span>
</div>
{t.file && (
<a href={t.file} className={styles.trackPlay} download>
</a>
)}
</div>
))}
</div>
) : null}
{/* YouTube playlist embed placeholder */}
<div className={styles.musicEmbed}>
<div className={styles.musicEmbedPlaceholder}>
<span className={styles.musicEmbedIcon}>🎵</span>
<p className={styles.musicEmbedText}>Official soundtrack coming with Episode 1</p>
<a
href="https://www.youtube.com/@bonelordbob"
target="_blank"
rel="noopener noreferrer"
className={styles.musicEmbedBtn}
>
Subscribe on YouTube for updates
</a>
</div>
</div>
{/* Patreon CTA */}
<div className={styles.musicPatreon}>
<h2 className={styles.musicPatreonTitle}>Support the Soundtrack</h2>
<p className={styles.musicPatreonText}>
Patrons get early access to music, behind-the-scenes production content, and
the full score as it&apos;s composed.
</p>
<a
href="https://www.patreon.com/BoneLordBob"
target="_blank"
rel="noopener noreferrer"
className={styles.musicPatreonBtn}
>
Support on Patreon
</a>
</div>
</div>
</SiteLayout>
);
}
+197 -329
View File
@@ -1,38 +1,7 @@
import Head from "next/head";
import SiteLayout from "@/pages/components/SiteLayout";
import Link from "next/link";
const s = {
page: {
minHeight: "100vh",
background: "#0a0806",
color: "#e8dcc8",
fontFamily: "'Segoe UI', system-ui, -apple-system, sans-serif",
lineHeight: 1.7 as const,
} as React.CSSProperties,
nav: {
display: "flex",
alignItems: "center",
justifyContent: "space-between",
padding: "20px 32px",
borderBottom: "1px solid rgba(232,220,200,0.1)",
} as React.CSSProperties,
logo: {
fontFamily: "'Georgia', 'Times New Roman', serif",
fontSize: "1.2rem",
fontWeight: 700,
letterSpacing: "0.04em",
textDecoration: "none",
color: "#e8dcc8",
} as React.CSSProperties,
logoSpan: { color: "#c0392b" } as React.CSSProperties,
backLink: {
fontSize: "0.88rem",
color: "#9e9080",
textDecoration: "none",
display: "inline-flex",
alignItems: "center",
gap: "4px",
} as React.CSSProperties,
main: {
maxWidth: "780px",
margin: "0 auto",
@@ -88,318 +57,217 @@ const s = {
color: "#c0392b",
textDecoration: "underline",
} as React.CSSProperties,
footer: {
borderTop: "1px solid rgba(232,220,200,0.1)",
padding: "28px 32px",
textAlign: "center" as const,
fontSize: "0.82rem",
color: "#9e9080",
} as React.CSSProperties,
};
import React from "react";
export default function Privacy() {
return (
<>
<Head>
<title>Privacy Policy Bone Lord Bob</title>
<meta
name="description"
content="Privacy Policy for Bone Lord Bob — how we collect, use, and protect your data."
/>
<meta
name="keywords"
content="Bone Lord Bob, privacy policy, cookies, GDPR, CCPA, CASL, American Anime"
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" sizes="any" />
<meta property="og:title" content="Privacy Policy — Bone Lord Bob" />
<meta
property="og:description"
content="Privacy Policy for Bone Lord Bob."
/>
<meta property="og:type" content="website" />
<meta
property="og:url"
content="https://www.bonelordbob.com/privacy"
/>
<meta property="og:image" content="/og-image.png" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:site" content="@BoneLordBob" />
<meta name="twitter:title" content="Privacy Policy — Bone Lord Bob" />
</Head>
<SiteLayout
title="Privacy Policy"
description="Privacy Policy for Bone Lord Bob — how we collect, use, and protect your data."
keywords="Bone Lord Bob, privacy policy, cookies, GDPR, CCPA, CASL, American Anime"
>
<main style={s.main}>
<span style={s.eyebrow}>Legal</span>
<h1 style={s.h1}>Privacy Policy</h1>
<p style={s.updated}>Last updated: April 2026</p>
<div style={s.page}>
{/* Nav */}
<nav style={s.nav}>
<Link href="/" style={s.logo}>
Bone Lord <span style={s.logoSpan}>Bob</span>
</Link>
<Link href="/" style={s.backLink}>
Back to Home
</Link>
</nav>
<p style={s.p}>
Bone Lord Bob (&quot;we&quot;, &quot;us&quot;, &quot;our&quot;) is
operated by Mathison Projects Inc. We respect your privacy and are
committed to protecting any personal data we collect. This policy
explains what we collect, how we use it, and your rights.
</p>
{/* Content */}
<main style={s.main}>
<span style={s.eyebrow}>Legal</span>
<h1 style={s.h1}>Privacy Policy</h1>
<p style={s.updated}>Last updated: April 2026</p>
<p style={s.p}>
Bone Lord Bob (&quot;we&quot;, &quot;us&quot;, &quot;our&quot;) is
operated by Mathison Projects Inc. We respect your privacy and are
committed to protecting any personal data we collect. This policy
explains what we collect, how we use it, and your rights.
</p>
<h2 style={s.h2}>1. Information We Collect</h2>
<p style={s.p}>
We collect limited information when you visit{" "}
<strong>www.bonelordbob.com</strong>:
</p>
<ul style={s.ul}>
<li style={s.li}>
<strong>Usage data</strong> pages visited, browser type,
device, IP address, and referral source, collected automatically
via analytics tools.
</li>
<li style={s.li}>
<strong>Cookie consent preference</strong> stored locally in
your browser&apos;s localStorage.
</li>
<li style={s.li}>
<strong>Contact information</strong> only if you email us
directly at{" "}
<a href="mailto:hello@bonelordbob.com" style={s.a}>
hello@bonelordbob.com
</a>
.
</li>
</ul>
<h2 style={s.h2}>2. Cookies &amp; Analytics</h2>
<p style={s.p}>
We use <strong>Google Analytics</strong> to understand how visitors
interact with our site. Google Analytics places cookies on your
device to collect anonymized data about your visit (e.g., pages
viewed, session duration, geographic region).
</p>
<p style={s.p}>
You can opt out of Google Analytics tracking by installing the{" "}
<a
href="https://tools.google.com/dlpage/gaoptout"
target="_blank"
rel="noopener noreferrer"
style={s.a}
>
Google Analytics Opt-out Browser Add-on
</a>
.
</p>
<p style={s.p}>
We also use a localStorage key (<code>blb_cookie_consent</code>) to
remember your cookie consent choice. This is not transmitted to any
server.
</p>
<h2 style={s.h2}>3. Third-Party Services</h2>
<p style={s.p}>
Our site links to and embeds content from third-party platforms.
Each has its own privacy policy:
</p>
<ul style={s.ul}>
<li style={s.li}>
<strong>YouTube</strong> {" "}
<a
href="https://policies.google.com/privacy"
target="_blank"
rel="noopener noreferrer"
style={s.a}
>
Google Privacy Policy
</a>
</li>
<li style={s.li}>
<strong>Instagram</strong> {" "}
<a
href="https://privacycenter.instagram.com/policy"
target="_blank"
rel="noopener noreferrer"
style={s.a}
>
Meta Privacy Policy
</a>
</li>
<li style={s.li}>
<strong>X (Twitter)</strong> {" "}
<a
href="https://twitter.com/en/privacy"
target="_blank"
rel="noopener noreferrer"
style={s.a}
>
X Privacy Policy
</a>
</li>
<li style={s.li}>
<strong>Facebook</strong> {" "}
<a
href="https://www.facebook.com/privacy/policy"
target="_blank"
rel="noopener noreferrer"
style={s.a}
>
Meta Privacy Policy
</a>
</li>
<li style={s.li}>
<strong>Patreon</strong> {" "}
<a
href="https://www.patreon.com/policy/privacy"
target="_blank"
rel="noopener noreferrer"
style={s.a}
>
Patreon Privacy Policy
</a>
</li>
<li style={s.li}>
<strong>TikTok</strong> {" "}
<a
href="https://www.tiktok.com/legal/page/us/privacy-policy/en"
target="_blank"
rel="noopener noreferrer"
style={s.a}
>
TikTok Privacy Policy
</a>
</li>
</ul>
<p style={s.p}>
We are not responsible for the privacy practices of these
third-party platforms. Visiting their links is subject to their
respective policies.
</p>
<h2 style={s.h2}>4. How We Use Your Information</h2>
<p style={s.p}>
We use the data we collect to:
</p>
<ul style={s.ul}>
<li style={s.li}>Analyze and improve site performance</li>
<li style={s.li}>Understand audience demographics and interests</li>
<li style={s.li}>
Respond to inquiries you send via email
</li>
</ul>
<p style={s.p}>
We do <strong>not</strong> sell, rent, or trade your personal
information to third parties.
</p>
<h2 style={s.h2}>5. Your Rights</h2>
<p style={s.p}>
<strong>GDPR (European Union):</strong> If you are located in the
EU/EEA, you have the right to access, rectify, erase, restrict, or
object to processing of your personal data. You also have the right
to data portability. To exercise these rights, contact us at{" "}
<h2 style={s.h2}>1. Information We Collect</h2>
<p style={s.p}>
We collect limited information when you visit{" "}
<strong>www.bonelordbob.com</strong>:
</p>
<ul style={s.ul}>
<li style={s.li}>
<strong>Usage data</strong> pages visited, browser type, device,
IP address, and referral source, collected automatically via
analytics tools.
</li>
<li style={s.li}>
<strong>Cookie consent preference</strong> stored locally in
your browser&apos;s localStorage.
</li>
<li style={s.li}>
<strong>Contact information</strong> only if you email us
directly at{" "}
<a href="mailto:hello@bonelordbob.com" style={s.a}>
hello@bonelordbob.com
</a>
.
</p>
</li>
</ul>
<p style={s.p}>
<strong>CCPA (California, USA):</strong> California residents have
the right to know what personal information we collect, to request
deletion of that information, and to opt out of the sale of personal
information. We do not sell personal information. To submit a
request, contact{" "}
<a href="mailto:hello@bonelordbob.com" style={s.a}>
hello@bonelordbob.com
<h2 style={s.h2}>2. Cookies &amp; Analytics</h2>
<p style={s.p}>
We use <strong>Google Analytics</strong> to understand how visitors
interact with our site. Google Analytics places cookies on your device
to collect anonymized data about your visit (e.g., pages viewed,
session duration, geographic region).
</p>
<p style={s.p}>
You can opt out of Google Analytics tracking by installing the{" "}
<a
href="https://tools.google.com/dlpage/gaoptout"
target="_blank"
rel="noopener noreferrer"
style={s.a}
>
Google Analytics Opt-out Browser Add-on
</a>
.
</p>
<p style={s.p}>
We also use a localStorage key (<code>blb_cookie_consent</code>) to
remember your cookie consent choice. This is not transmitted to any
server.
</p>
<h2 style={s.h2}>3. Third-Party Services</h2>
<p style={s.p}>
Our site links to and embeds content from third-party platforms. Each has
its own privacy policy:
</p>
<ul style={s.ul}>
<li style={s.li}>
<strong>YouTube</strong> {" "}
<a href="https://policies.google.com/privacy" target="_blank" rel="noopener noreferrer" style={s.a}>
Google Privacy Policy
</a>
.
</p>
<p style={s.p}>
<strong>CASL (Canada):</strong> We do not send commercial electronic
messages unless you have given express or implied consent. If you
wish to withdraw consent or unsubscribe from any communications,
contact us at{" "}
<a href="mailto:hello@bonelordbob.com" style={s.a}>
hello@bonelordbob.com
</li>
<li style={s.li}>
<strong>Instagram</strong> {" "}
<a href="https://privacycenter.instagram.com/policy" target="_blank" rel="noopener noreferrer" style={s.a}>
Meta Privacy Policy
</a>
.
</p>
<h2 style={s.h2}>6. Data Retention</h2>
<p style={s.p}>
Analytics data is retained by Google Analytics per their default
retention settings (26 months). We do not store personal data on
our own servers beyond what is needed to respond to direct inquiries.
</p>
<h2 style={s.h2}>7. Children&apos;s Privacy</h2>
<p style={s.p}>
Bone Lord Bob is intended for mature audiences. We do not knowingly
collect personal information from children under 13. If you believe
a child has provided us with personal data, please contact us
immediately.
</p>
<h2 style={s.h2}>8. Changes to This Policy</h2>
<p style={s.p}>
We may update this Privacy Policy from time to time. We will post
the updated version on this page with a revised &quot;Last
updated&quot; date. Continued use of the site after changes
constitutes acceptance.
</p>
<h2 style={s.h2}>9. Contact</h2>
<p style={s.p}>
For any privacy-related questions, requests, or concerns, contact
us at:
</p>
<p style={s.p}>
<strong>Mathison Projects Inc.</strong>
<br />
Email:{" "}
<a href="mailto:hello@bonelordbob.com" style={s.a}>
hello@bonelordbob.com
</li>
<li style={s.li}>
<strong>X (Twitter)</strong> {" "}
<a href="https://twitter.com/en/privacy" target="_blank" rel="noopener noreferrer" style={s.a}>
X Privacy Policy
</a>
<br />
Website:{" "}
<a
href="https://www.bonelordbob.com"
target="_blank"
rel="noopener noreferrer"
style={s.a}
>
www.bonelordbob.com
</li>
<li style={s.li}>
<strong>Facebook</strong> {" "}
<a href="https://www.facebook.com/privacy/policy" target="_blank" rel="noopener noreferrer" style={s.a}>
Meta Privacy Policy
</a>
</p>
</main>
</li>
<li style={s.li}>
<strong>Patreon</strong> {" "}
<a href="https://www.patreon.com/policy/privacy" target="_blank" rel="noopener noreferrer" style={s.a}>
Patreon Privacy Policy
</a>
</li>
<li style={s.li}>
<strong>TikTok</strong> {" "}
<a href="https://www.tiktok.com/legal/page/us/privacy-policy/en" target="_blank" rel="noopener noreferrer" style={s.a}>
TikTok Privacy Policy
</a>
</li>
</ul>
<p style={s.p}>
We are not responsible for the privacy practices of these third-party
platforms. Visiting their links is subject to their respective
policies.
</p>
<footer style={s.footer}>
<div>
© {new Date().getFullYear()} Mathison Projects Inc. All rights
reserved. &nbsp;|&nbsp;{" "}
<Link href="/" style={{ color: "#9e9080", textDecoration: "none" }}>
Home
</Link>{" "}
&nbsp;|&nbsp;{" "}
<Link
href="/terms"
style={{ color: "#9e9080", textDecoration: "none" }}
>
Terms &amp; Conditions
</Link>
</div>
</footer>
</div>
</>
<h2 style={s.h2}>4. How We Use Your Information</h2>
<p style={s.p}>We use the data we collect to:</p>
<ul style={s.ul}>
<li style={s.li}>Analyze and improve site performance</li>
<li style={s.li}>Understand audience demographics and interests</li>
<li style={s.li}>Respond to inquiries you send via email</li>
</ul>
<p style={s.p}>
We do <strong>not</strong> sell, rent, or trade your personal
information to third parties.
</p>
<h2 style={s.h2}>5. Your Rights</h2>
<p style={s.p}>
<strong>GDPR (European Union):</strong> If you are located in the
EU/EEA, you have the right to access, rectify, erase, restrict, or
object to processing of your personal data. You also have the right to
data portability. To exercise these rights, contact us at{" "}
<a href="mailto:hello@bonelordbob.com" style={s.a}>
hello@bonelordbob.com
</a>
.
</p>
<p style={s.p}>
<strong>CCPA (California, USA):</strong> California residents have the
right to know what personal information we collect, to request deletion
of that information, and to opt out of the sale of personal
information. We do not sell personal information. To submit a request,
contact{" "}
<a href="mailto:hello@bonelordbob.com" style={s.a}>
hello@bonelordbob.com
</a>
.
</p>
<p style={s.p}>
<strong>CASL (Canada):</strong> We do not send commercial electronic
messages unless you have given express or implied consent. If you wish
to withdraw consent, contact us at{" "}
<a href="mailto:hello@bonelordbob.com" style={s.a}>
hello@bonelordbob.com
</a>
.
</p>
<h2 style={s.h2}>6. Data Retention</h2>
<p style={s.p}>
Analytics data is retained by Google Analytics per their default
retention settings (26 months). We do not store personal data on our
own servers beyond what is needed to respond to direct inquiries.
</p>
<h2 style={s.h2}>7. Children&apos;s Privacy</h2>
<p style={s.p}>
Bone Lord Bob is intended for mature audiences. We do not knowingly
collect personal information from children under 13. If you believe a
child has provided us with personal data, please contact us
immediately.
</p>
<h2 style={s.h2}>8. Changes to This Policy</h2>
<p style={s.p}>
We may update this Privacy Policy from time to time. We will post the
updated version on this page with a revised &quot;Last updated&quot;
date. Continued use of the site after changes constitutes acceptance.
</p>
<h2 style={s.h2}>9. Contact</h2>
<p style={s.p}>
For any privacy-related questions, requests, or concerns, contact us
at:
</p>
<p style={s.p}>
<strong>Mathison Projects Inc.</strong>
<br />
Email:{" "}
<a href="mailto:hello@bonelordbob.com" style={s.a}>
hello@bonelordbob.com
</a>
<br />
Website:{" "}
<a href="https://www.bonelordbob.com" target="_blank" rel="noopener noreferrer" style={s.a}>
www.bonelordbob.com
</a>
</p>
<p style={{ ...s.p, marginTop: "40px" }}>
<Link href="/terms" style={s.a}>Terms &amp; Conditions</Link>
{" "}·{" "}
<Link href="/" style={s.a}>Back to Home</Link>
</p>
</main>
</SiteLayout>
);
}
+151 -255
View File
@@ -1,39 +1,7 @@
import Head from "next/head";
import SiteLayout from "@/pages/components/SiteLayout";
import Link from "next/link";
import React from "react";
const s = {
page: {
minHeight: "100vh",
background: "#0a0806",
color: "#e8dcc8",
fontFamily: "'Segoe UI', system-ui, -apple-system, sans-serif",
lineHeight: 1.7 as const,
} as React.CSSProperties,
nav: {
display: "flex",
alignItems: "center",
justifyContent: "space-between",
padding: "20px 32px",
borderBottom: "1px solid rgba(232,220,200,0.1)",
} as React.CSSProperties,
logo: {
fontFamily: "'Georgia', 'Times New Roman', serif",
fontSize: "1.2rem",
fontWeight: 700,
letterSpacing: "0.04em",
textDecoration: "none",
color: "#e8dcc8",
} as React.CSSProperties,
logoSpan: { color: "#c0392b" } as React.CSSProperties,
backLink: {
fontSize: "0.88rem",
color: "#9e9080",
textDecoration: "none",
display: "inline-flex",
alignItems: "center",
gap: "4px",
} as React.CSSProperties,
main: {
maxWidth: "780px",
margin: "0 auto",
@@ -89,243 +57,171 @@ const s = {
color: "#c0392b",
textDecoration: "underline",
} as React.CSSProperties,
footer: {
borderTop: "1px solid rgba(232,220,200,0.1)",
padding: "28px 32px",
textAlign: "center" as const,
fontSize: "0.82rem",
color: "#9e9080",
} as React.CSSProperties,
};
export default function Terms() {
return (
<>
<Head>
<title>Terms &amp; Conditions Bone Lord Bob</title>
<meta
name="description"
content="Terms and Conditions for Bone Lord Bob — your rights and responsibilities when using this site."
/>
<meta
name="keywords"
content="Bone Lord Bob, terms and conditions, terms of use, legal, American Anime"
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" sizes="any" />
<meta
property="og:title"
content="Terms &amp; Conditions — Bone Lord Bob"
/>
<meta
property="og:description"
content="Terms and Conditions for Bone Lord Bob."
/>
<meta property="og:type" content="website" />
<meta
property="og:url"
content="https://www.bonelordbob.com/terms"
/>
<meta property="og:image" content="/og-image.png" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:site" content="@BoneLordBob" />
<meta
name="twitter:title"
content="Terms &amp; Conditions — Bone Lord Bob"
/>
</Head>
<SiteLayout
title="Terms & Conditions"
description="Terms and Conditions for Bone Lord Bob — your rights and responsibilities when using this site."
keywords="Bone Lord Bob, terms and conditions, terms of use, legal, American Anime"
>
<main style={s.main}>
<span style={s.eyebrow}>Legal</span>
<h1 style={s.h1}>Terms &amp; Conditions</h1>
<p style={s.updated}>Last updated: April 2026</p>
<div style={s.page}>
{/* Nav */}
<nav style={s.nav}>
<Link href="/" style={s.logo}>
Bone Lord <span style={s.logoSpan}>Bob</span>
</Link>
<Link href="/" style={s.backLink}>
Back to Home
</Link>
</nav>
<p style={s.p}>
Please read these Terms &amp; Conditions (&quot;Terms&quot;) carefully
before using <strong>www.bonelordbob.com</strong> (the &quot;Site&quot;),
operated by Mathison Projects Inc. (&quot;we&quot;, &quot;us&quot;,
&quot;our&quot;). By accessing or using the Site, you agree to be
bound by these Terms.
</p>
{/* Content */}
<main style={s.main}>
<span style={s.eyebrow}>Legal</span>
<h1 style={s.h1}>Terms &amp; Conditions</h1>
<p style={s.updated}>Last updated: April 2026</p>
<h2 style={s.h2}>1. Acceptance of Terms</h2>
<p style={s.p}>
By accessing this Site, you confirm that you are at least 13 years of
age (or the minimum legal age in your jurisdiction) and agree to these
Terms. If you do not agree, please do not use the Site.
</p>
<p style={s.p}>
We reserve the right to update these Terms at any time. Changes will
be effective upon posting to this page with a revised &quot;Last
updated&quot; date. Continued use of the Site after changes
constitutes acceptance of the new Terms.
</p>
<p style={s.p}>
Please read these Terms &amp; Conditions (&quot;Terms&quot;)
carefully before using <strong>www.bonelordbob.com</strong> (the
&quot;Site&quot;), operated by Mathison Projects Inc.
(&quot;we&quot;, &quot;us&quot;, &quot;our&quot;). By accessing or
using the Site, you agree to be bound by these Terms.
</p>
<h2 style={s.h2}>2. Intellectual Property</h2>
<p style={s.p}>
All content on this Site including but not limited to text, artwork,
logos, character designs, animations, names, slogans, and the &quot;Bone
Lord Bob&quot; brand is the exclusive property of{" "}
<strong>Mathison Projects Inc.</strong> and is protected by United
States and international copyright, trademark, and other intellectual
property laws.
</p>
<p style={s.p}>
© {new Date().getFullYear()} Mathison Projects Inc. All rights
reserved.
</p>
<p style={s.p}>
You may not reproduce, distribute, modify, create derivative works
from, publicly display, or commercially exploit any content from this
Site without our prior written permission.
</p>
<h2 style={s.h2}>1. Acceptance of Terms</h2>
<p style={s.p}>
By accessing this Site, you confirm that you are at least 13 years
of age (or the minimum legal age in your jurisdiction) and agree to
these Terms. If you do not agree, please do not use the Site.
</p>
<p style={s.p}>
We reserve the right to update these Terms at any time. Changes
will be effective upon posting to this page with a revised
&quot;Last updated&quot; date. Continued use of the Site after
changes constitutes acceptance of the new Terms.
</p>
<h2 style={s.h2}>3. Permitted Use</h2>
<p style={s.p}>
You may access and view the Site for personal, non-commercial purposes.
You may share links to the Site on social media or other platforms,
provided you do not misrepresent the content or the Bone Lord Bob
brand.
</p>
<p style={s.p}>You may not:</p>
<ul style={s.ul}>
<li style={s.li}>
Use the Site for any unlawful purpose or in violation of any
applicable laws or regulations
</li>
<li style={s.li}>
Scrape, data-mine, or systematically extract content from the Site
without permission
</li>
<li style={s.li}>
Attempt to gain unauthorized access to any part of the Site or its
related systems
</li>
<li style={s.li}>
Impersonate Bone Lord Bob, Mathison Projects Inc., or any of their
representatives
</li>
<li style={s.li}>
Use our trademarks or brand assets without written authorization
</li>
</ul>
<h2 style={s.h2}>2. Intellectual Property</h2>
<p style={s.p}>
All content on this Site including but not limited to text,
artwork, logos, character designs, animations, names, slogans, and
the &quot;Bone Lord Bob&quot; brand is the exclusive property of{" "}
<strong>Mathison Projects Inc.</strong> and is protected by United
States and international copyright, trademark, and other
intellectual property laws.
</p>
<p style={s.p}>
© {new Date().getFullYear()} Mathison Projects Inc. All rights
reserved.
</p>
<p style={s.p}>
You may not reproduce, distribute, modify, create derivative works
from, publicly display, or commercially exploit any content from
this Site without our prior written permission.
</p>
<h2 style={s.h2}>4. User Conduct</h2>
<p style={s.p}>
When interacting with us via email or social media, you agree not to
send harassing, abusive, defamatory, obscene, or threatening content.
We reserve the right to block users who violate this policy.
</p>
<h2 style={s.h2}>3. Permitted Use</h2>
<p style={s.p}>
You may access and view the Site for personal, non-commercial
purposes. You may share links to the Site on social media or other
platforms, provided you do not misrepresent the content or the
Bone Lord Bob brand.
</p>
<p style={s.p}>
You may not:
</p>
<ul style={s.ul}>
<li style={s.li}>
Use the Site for any unlawful purpose or in violation of any
applicable laws or regulations
</li>
<li style={s.li}>
Scrape, data-mine, or systematically extract content from the
Site without permission
</li>
<li style={s.li}>
Attempt to gain unauthorized access to any part of the Site or
its related systems
</li>
<li style={s.li}>
Impersonate Bone Lord Bob, Mathison Projects Inc., or any of
their representatives
</li>
<li style={s.li}>
Use our trademarks or brand assets without written authorization
</li>
</ul>
<h2 style={s.h2}>5. Third-Party Links</h2>
<p style={s.p}>
The Site contains links to third-party platforms (YouTube, Instagram, X,
Facebook, Patreon, TikTok). These links are provided for convenience.
We have no control over the content or practices of these platforms
and are not responsible for their content, privacy policies, or terms
of service.
</p>
<h2 style={s.h2}>4. User Conduct</h2>
<p style={s.p}>
When interacting with us via email or social media, you agree not
to send harassing, abusive, defamatory, obscene, or threatening
content. We reserve the right to block users who violate this policy.
</p>
<h2 style={s.h2}>6. Disclaimers</h2>
<p style={s.p}>
THE SITE AND ALL CONTENT ARE PROVIDED &quot;AS IS&quot; AND &quot;AS
AVAILABLE&quot; WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
</p>
<p style={s.p}>
We do not warrant that the Site will be uninterrupted, error-free, or
free of viruses or other harmful components. We may modify, suspend,
or discontinue the Site at any time without notice.
</p>
<h2 style={s.h2}>5. Third-Party Links</h2>
<p style={s.p}>
The Site contains links to third-party platforms (YouTube,
Instagram, X, Facebook, Patreon, TikTok). These links are provided
for convenience. We have no control over the content or practices
of these platforms and are not responsible for their content,
privacy policies, or terms of service.
</p>
<h2 style={s.h2}>7. Limitation of Liability</h2>
<p style={s.p}>
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, MATHISON PROJECTS
INC. AND ITS OFFICERS, DIRECTORS, EMPLOYEES, AND AGENTS SHALL NOT BE
LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR
PUNITIVE DAMAGES ARISING FROM YOUR USE OF (OR INABILITY TO USE) THE
SITE, EVEN IF WE HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
</p>
<p style={s.p}>
OUR TOTAL LIABILITY TO YOU FOR ANY CLAIM ARISING FROM THESE TERMS OR
YOUR USE OF THE SITE SHALL NOT EXCEED $100 USD.
</p>
<h2 style={s.h2}>6. Disclaimers</h2>
<p style={s.p}>
THE SITE AND ALL CONTENT ARE PROVIDED &quot;AS IS&quot; AND
&quot;AS AVAILABLE&quot; WITHOUT WARRANTIES OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
NON-INFRINGEMENT.
</p>
<p style={s.p}>
We do not warrant that the Site will be uninterrupted, error-free,
or free of viruses or other harmful components. We may modify,
suspend, or discontinue the Site at any time without notice.
</p>
<h2 style={s.h2}>8. Governing Law</h2>
<p style={s.p}>
These Terms are governed by and construed in accordance with the laws
of the State of <strong>Nebraska, United States of America</strong>,
without regard to its conflict of law principles. Any disputes arising
from these Terms or your use of the Site shall be resolved exclusively
in the courts located in Douglas County, Nebraska.
</p>
<h2 style={s.h2}>7. Limitation of Liability</h2>
<p style={s.p}>
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, MATHISON
PROJECTS INC. AND ITS OFFICERS, DIRECTORS, EMPLOYEES, AND AGENTS
SHALL NOT BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
CONSEQUENTIAL, OR PUNITIVE DAMAGES ARISING FROM YOUR USE OF (OR
INABILITY TO USE) THE SITE, EVEN IF WE HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
</p>
<p style={s.p}>
OUR TOTAL LIABILITY TO YOU FOR ANY CLAIM ARISING FROM THESE TERMS
OR YOUR USE OF THE SITE SHALL NOT EXCEED $100 USD.
</p>
<h2 style={s.h2}>9. Severability</h2>
<p style={s.p}>
If any provision of these Terms is found to be unenforceable or
invalid, that provision will be limited or eliminated to the minimum
extent necessary, and the remaining provisions will continue in full
force and effect.
</p>
<h2 style={s.h2}>8. Governing Law</h2>
<p style={s.p}>
These Terms are governed by and construed in accordance with the
laws of the State of <strong>Nebraska, United States of America</strong>,
without regard to its conflict of law principles. Any disputes
arising from these Terms or your use of the Site shall be resolved
exclusively in the courts located in Douglas County, Nebraska.
</p>
<h2 style={s.h2}>10. Contact</h2>
<p style={s.p}>For questions about these Terms, contact:</p>
<p style={s.p}>
<strong>Mathison Projects Inc.</strong>
<br />
Email:{" "}
<a href="mailto:hello@bonelordbob.com" style={s.a}>
hello@bonelordbob.com
</a>
<br />
Website:{" "}
<a href="https://www.bonelordbob.com" target="_blank" rel="noopener noreferrer" style={s.a}>
www.bonelordbob.com
</a>
</p>
<h2 style={s.h2}>9. Severability</h2>
<p style={s.p}>
If any provision of these Terms is found to be unenforceable or
invalid, that provision will be limited or eliminated to the
minimum extent necessary, and the remaining provisions will continue
in full force and effect.
</p>
<h2 style={s.h2}>10. Contact</h2>
<p style={s.p}>
For questions about these Terms, contact:
</p>
<p style={s.p}>
<strong>Mathison Projects Inc.</strong>
<br />
Email:{" "}
<a href="mailto:hello@bonelordbob.com" style={s.a}>
hello@bonelordbob.com
</a>
<br />
Website:{" "}
<a
href="https://www.bonelordbob.com"
target="_blank"
rel="noopener noreferrer"
style={s.a}
>
www.bonelordbob.com
</a>
</p>
</main>
<footer style={s.footer}>
<div>
© {new Date().getFullYear()} Mathison Projects Inc. All rights
reserved. &nbsp;|&nbsp;{" "}
<Link href="/" style={{ color: "#9e9080", textDecoration: "none" }}>
Home
</Link>{" "}
&nbsp;|&nbsp;{" "}
<Link
href="/privacy"
style={{ color: "#9e9080", textDecoration: "none" }}
>
Privacy Policy
</Link>
</div>
</footer>
</div>
</>
<p style={{ ...s.p, marginTop: "40px" }}>
<Link href="/privacy" style={s.a}>Privacy Policy</Link>
{" "}·{" "}
<Link href="/" style={s.a}>Back to Home</Link>
</p>
</main>
</SiteLayout>
);
}
+79
View File
@@ -0,0 +1,79 @@
import SiteLayout from "./components/SiteLayout";
import layoutStyles from "@/styles/Layout.module.css";
import styles from "@/styles/World.module.css";
export default function WorldPage() {
return (
<SiteLayout
title="World"
description="Explore the world of Bone Lord Bob — its kingdoms, landscapes, and forgotten places."
keywords="Bone Lord Bob world, BLB setting, dark fantasy world, anime setting, bone kingdom"
canonical="/world"
>
{/* Hero */}
<div className={layoutStyles.pageHero}>
<span className={layoutStyles.pageEyebrow}>The Setting</span>
<h1 className={layoutStyles.pageTitle}>
The <em>World</em>
</h1>
<p className={layoutStyles.pageSub}>
Not a land you&apos;d want to be born into. But one you won&apos;t be able to look away from.
</p>
</div>
<div className={layoutStyles.pageContent}>
<div className={styles.worldIntro}>
<p className={styles.worldText}>
The world of Bone Lord Bob exists somewhere between myth and memory a place where
the rules of death are more like suggestions, and the landscape itself remembers every
war ever fought on it.
</p>
<p className={styles.worldText}>
There are no safe cities. Only cities that haven&apos;t fallen yet.
</p>
</div>
{/* Location cards */}
<div className={styles.locationGrid}>
<div className={styles.locationCard}>
<div className={styles.locationHeader}>
<span className={styles.locationIcon}>🦴</span>
<h2 className={styles.locationName}>The Bonefield</h2>
</div>
<p className={styles.locationDesc}>
A vast plain where the remains of an ancient battle stretch beyond the horizon.
Travelers say you can still hear the war if you press your ear to the ground at midnight.
</p>
</div>
<div className={styles.locationCard}>
<div className={styles.locationHeader}>
<span className={styles.locationIcon}>🏰</span>
<h2 className={styles.locationName}>The Throne of Ash</h2>
</div>
<p className={styles.locationDesc}>
No one sits there now. No one has for a hundred years. But something still answers
when the right name is spoken in its hall.
</p>
</div>
<div className={styles.locationCard}>
<div className={styles.locationHeader}>
<span className={styles.locationIcon}>🌑</span>
<h2 className={styles.locationName}>The Hollow Dark</h2>
</div>
<p className={styles.locationDesc}>
Below every kingdom is the Hollow Dark the underworld that isn&apos;t quite the afterlife.
Bob knows this place better than anyone alive.
</p>
</div>
</div>
<div className={layoutStyles.comingSoon}>
<span className={layoutStyles.comingSoonSkull}>🗺</span>
<p className={layoutStyles.comingSoonText}>World map and full region guide coming with Episode 1</p>
</div>
</div>
</SiteLayout>
);
}
+182
View File
@@ -0,0 +1,182 @@
import SiteLayout from "@/pages/components/SiteLayout";
const s = {
page: {
maxWidth: "860px",
margin: "0 auto",
padding: "64px 32px 96px",
} as React.CSSProperties,
hero: {
marginBottom: "64px",
textAlign: "center" as const,
} as React.CSSProperties,
eyebrow: {
display: "block",
fontSize: "0.75rem",
fontWeight: 700,
letterSpacing: "0.18em",
textTransform: "uppercase" as const,
color: "#c0392b",
marginBottom: "16px",
} as React.CSSProperties,
h1: {
fontFamily: "'Georgia', 'Times New Roman', serif",
fontSize: "clamp(2.4rem, 6vw, 4rem)",
fontWeight: 700,
color: "#e8dcc8",
lineHeight: 1.1,
marginBottom: "20px",
} as React.CSSProperties,
heroSub: {
fontSize: "1.05rem",
color: "#9e9080",
maxWidth: "560px",
margin: "0 auto",
lineHeight: 1.7,
} as React.CSSProperties,
divider: {
display: "flex",
alignItems: "center",
justifyContent: "center",
gap: "12px",
margin: "48px 0",
fontSize: "1.2rem",
opacity: 0.4,
} as React.CSSProperties,
section: {
marginBottom: "56px",
} as React.CSSProperties,
sectionLabel: {
display: "block",
fontSize: "0.72rem",
fontWeight: 700,
letterSpacing: "0.14em",
textTransform: "uppercase" as const,
color: "#c0392b",
marginBottom: "12px",
} as React.CSSProperties,
h2: {
fontFamily: "'Georgia', 'Times New Roman', serif",
fontSize: "clamp(1.6rem, 3vw, 2.2rem)",
fontWeight: 700,
color: "#e8dcc8",
marginBottom: "20px",
lineHeight: 1.2,
} as React.CSSProperties,
p: {
fontSize: "1rem",
color: "#c8bfae",
lineHeight: 1.8,
marginBottom: "16px",
maxWidth: "680px",
} as React.CSSProperties,
comingSoon: {
background: "#1a1510",
border: "1px solid rgba(232,220,200,0.1)",
borderRadius: "8px",
padding: "40px 32px",
textAlign: "center" as const,
marginTop: "16px",
} as React.CSSProperties,
comingSoonIcon: {
fontSize: "2rem",
marginBottom: "12px",
display: "block",
opacity: 0.4,
} as React.CSSProperties,
comingSoonText: {
fontSize: "0.88rem",
color: "#9e9080",
letterSpacing: "0.08em",
textTransform: "uppercase" as const,
fontWeight: 600,
} as React.CSSProperties,
};
export default function Lore() {
return (
<SiteLayout
title="Lore"
description="The mythology and history of the Bone Kingdom — the world of Bone Lord Bob."
keywords="Bone Lord Bob, lore, mythology, bone kingdom, dark fantasy, American Anime, worldbuilding"
>
<div style={s.page}>
{/* Hero */}
<div style={s.hero}>
<span style={s.eyebrow}>The Mythology</span>
<h1 style={s.h1}>The Lore</h1>
<p style={s.heroSub}>
Death is not the end in this world. It is the beginning of debt.
</p>
</div>
{/* Section: Bone Kingdom */}
<div style={s.section}>
<span style={s.sectionLabel}>Foundation</span>
<h2 style={s.h2}>The Bone Kingdom</h2>
<p style={s.p}>
A land where death is currency and the living are guests. The Bone
Kingdom does not welcome the breathing it merely tolerates them,
for now, until their ledger comes due. Every step taken on its soil
is a transaction. Every breath drawn is borrowed.
</p>
<p style={s.p}>
Its borders are not marked by walls or rivers, but by a feeling: the
moment the air turns cold and the light goes gray, you have arrived.
The dead know. The living learn too late.
</p>
</div>
<div style={s.divider}>
<span>💀</span><span>💀</span><span>💀</span>
</div>
{/* Section: The Ledger */}
<div style={s.section}>
<span style={s.sectionLabel}>The Accounting</span>
<h2 style={s.h2}>The Ledger</h2>
<p style={s.p}>
Every soul has a price. The Bone Lord keeps the account. From the
moment of first breath, your name is inscribed not in ink, but in
marrow. The record does not forget. It does not forgive. It only
waits.
</p>
<p style={s.p}>
Heroes have tried to destroy the Ledger. Warlords have tried to
steal it. Gods have tried to rewrite it. None have succeeded. The
book endures because it is not made of paper. It is made of
consequence.
</p>
</div>
<div style={s.divider}>
<span>💀</span><span>💀</span><span>💀</span>
</div>
{/* Section: Origins — coming soon */}
<div style={s.section}>
<span style={s.sectionLabel}>History</span>
<h2 style={s.h2}>Origins</h2>
<div style={s.comingSoon}>
<span style={s.comingSoonIcon}>💀</span>
<p style={s.comingSoonText}>Coming Soon</p>
</div>
</div>
<div style={s.divider}>
<span>💀</span><span>💀</span><span>💀</span>
</div>
{/* Section: Prophecy — coming soon */}
<div style={s.section}>
<span style={s.sectionLabel}>The Foretelling</span>
<h2 style={s.h2}>Prophecy</h2>
<div style={s.comingSoon}>
<span style={s.comingSoonIcon}>💀</span>
<p style={s.comingSoonText}>Coming Soon</p>
</div>
</div>
</div>
</SiteLayout>
);
}
+146
View File
@@ -0,0 +1,146 @@
import SiteLayout from "@/pages/components/SiteLayout";
const s = {
page: {
maxWidth: "1000px",
margin: "0 auto",
padding: "64px 32px 96px",
} as React.CSSProperties,
hero: {
marginBottom: "64px",
textAlign: "center" as const,
} as React.CSSProperties,
eyebrow: {
display: "block",
fontSize: "0.75rem",
fontWeight: 700,
letterSpacing: "0.18em",
textTransform: "uppercase" as const,
color: "#c0392b",
marginBottom: "16px",
} as React.CSSProperties,
h1: {
fontFamily: "'Georgia', 'Times New Roman', serif",
fontSize: "clamp(2.4rem, 6vw, 4rem)",
fontWeight: 700,
color: "#e8dcc8",
lineHeight: 1.1,
marginBottom: "20px",
} as React.CSSProperties,
heroSub: {
fontSize: "1.05rem",
color: "#9e9080",
maxWidth: "520px",
margin: "0 auto",
lineHeight: 1.7,
} as React.CSSProperties,
sectionLabel: {
display: "block",
fontSize: "0.72rem",
fontWeight: 700,
letterSpacing: "0.14em",
textTransform: "uppercase" as const,
color: "#c0392b",
marginBottom: "12px",
textAlign: "center" as const,
} as React.CSSProperties,
grid: {
display: "grid",
gridTemplateColumns: "repeat(auto-fit, minmax(280px, 1fr))",
gap: "20px",
marginTop: "32px",
marginBottom: "48px",
} as React.CSSProperties,
card: {
background: "#1a1510",
border: "1px solid rgba(232,220,200,0.12)",
borderRadius: "8px",
padding: "32px 28px",
transition: "border-color 0.2s",
} as React.CSSProperties,
cardIcon: {
fontSize: "2rem",
marginBottom: "16px",
display: "block",
} as React.CSSProperties,
cardName: {
fontFamily: "'Georgia', 'Times New Roman', serif",
fontSize: "1.25rem",
fontWeight: 700,
color: "#e8dcc8",
marginBottom: "12px",
} as React.CSSProperties,
cardDesc: {
fontSize: "0.92rem",
color: "#9e9080",
lineHeight: 1.65,
} as React.CSSProperties,
more: {
textAlign: "center" as const,
padding: "32px",
background: "#120f0a",
border: "1px solid rgba(232,220,200,0.08)",
borderRadius: "8px",
fontSize: "0.9rem",
color: "#9e9080",
fontStyle: "italic",
letterSpacing: "0.04em",
} as React.CSSProperties,
};
const REGIONS = [
{
icon: "🏴",
name: "The Bone Kingdom",
desc: "Where the dead outnumber the living. The seat of the Bone Lord's power — a realm that does not distinguish between conqueror and conquered. All serve, eventually.",
},
{
icon: "🌑",
name: "The Bonefield",
desc: "An endless plain of ash and silence. Nothing grows. Nothing dies. Those who wander into the Bonefield are neither living nor dead — just lost.",
},
{
icon: "🔥",
name: "The Pyre Gates",
desc: "The boundary between worlds. Cross it once. You won't cross back. The Gates do not open for the living — but they have been known to open for the desperate.",
},
];
export default function WorldPage() {
return (
<SiteLayout
title="The World"
description="Explore the world of Bone Lord Bob — the Bone Kingdom, the Bonefield, the Pyre Gates, and beyond."
keywords="Bone Lord Bob, world, bone kingdom, bonefield, pyre gates, dark fantasy, geography, factions, American Anime"
>
<div style={s.page}>
{/* Hero */}
<div style={s.hero}>
<span style={s.eyebrow}>Geography &amp; Factions</span>
<h1 style={s.h1}>The World</h1>
<p style={s.heroSub}>
Every territory has a cost. Every border is written in bone. Know
where you are before it&apos;s too late.
</p>
</div>
{/* Region cards */}
<span style={s.sectionLabel}>Regions</span>
<div style={s.grid}>
{REGIONS.map((r) => (
<div key={r.name} style={s.card}>
<span style={s.cardIcon}>{r.icon}</span>
<div style={s.cardName}>{r.name}</div>
<p style={s.cardDesc}>{r.desc}</p>
</div>
))}
</div>
{/* Placeholder */}
<div style={s.more}>
More regions revealed as the story unfolds...
</div>
</div>
</SiteLayout>
);
}
+138
View File
@@ -0,0 +1,138 @@
/* ── Tabs ──────────────────────────────────────────────────────────────────── */
.tabs {
display: flex;
gap: 0;
border-bottom: 1px solid var(--border);
margin-bottom: 3rem;
}
.tab {
padding: 0.75rem 2rem;
background: none;
border: none;
border-bottom: 2px solid transparent;
font-size: 0.78rem;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--bone-dim);
cursor: pointer;
transition: color 0.2s, border-color 0.2s;
font-family: inherit;
margin-bottom: -1px;
}
.tab:hover { color: var(--bone); }
.tabActive {
color: var(--bone);
border-bottom-color: var(--red);
}
/* ── Section ───────────────────────────────────────────────────────────────── */
.section {}
/* ── Grid ──────────────────────────────────────────────────────────────────── */
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
margin-bottom: 3rem;
}
.card {
background: var(--dark-card);
border: 1px solid var(--border);
overflow: hidden;
transition: border-color 0.2s, transform 0.2s;
}
.card:hover {
border-color: rgba(232,220,200,0.25);
transform: translateY(-2px);
}
.cardImg {
width: 100%;
aspect-ratio: 4/3;
object-fit: cover;
display: block;
}
.cardCaption {
padding: 0.65rem 1rem;
font-size: 0.78rem;
color: var(--bone-dim);
opacity: 0.7;
border-top: 1px solid var(--border);
}
.cardCaption a {
color: var(--red);
text-decoration: underline;
}
/* ── Empty state ───────────────────────────────────────────────────────────── */
.empty {
text-align: center;
padding: 6rem 2rem;
border: 1px dashed var(--border);
background: var(--dark-card);
}
.emptyIcon {
display: block;
font-size: 3.5rem;
margin-bottom: 1.25rem;
opacity: 0.25;
}
.emptyTitle {
font-family: var(--font-display);
font-size: 1.1rem;
color: var(--bone);
margin-bottom: 0.65rem;
}
.emptyText {
font-size: 0.88rem;
color: var(--bone-dim);
max-width: 440px;
margin: 0 auto 2rem;
line-height: 1.75;
}
.emptyLinks {
display: flex;
gap: 0.75rem;
justify-content: center;
flex-wrap: wrap;
}
.emptyBtn {
display: inline-flex;
padding: 0.6rem 1.4rem;
background: transparent;
color: var(--bone-dim);
border: 1px solid var(--border);
font-size: 0.75rem;
letter-spacing: 0.1em;
text-transform: uppercase;
transition: border-color 0.2s, color 0.2s;
}
.emptyBtn:hover {
border-color: var(--red);
color: var(--bone);
}
/* ── Responsive ────────────────────────────────────────────────────────────── */
@media (max-width: 768px) {
.tabs { overflow-x: auto; }
.tab { padding: 0.65rem 1.25rem; white-space: nowrap; }
.grid { grid-template-columns: 1fr 1fr; }
.empty { padding: 3rem 1.25rem; }
}
@media (max-width: 480px) {
.grid { grid-template-columns: 1fr; }
}
+295
View File
@@ -0,0 +1,295 @@
/* ─────────────────────────────────────────────────────────────────
Layout.module.css — Bone Lord Bob shared site layout
───────────────────────────────────────────────────────────────── */
/* Site wrapper */
.site {
min-height: 100vh;
background: var(--dark, #0a0806);
color: var(--bone, #e8dcc8);
font-family: var(--font-body, 'Segoe UI', system-ui, -apple-system, sans-serif);
display: flex;
flex-direction: column;
}
/* ── NAV ───────────────────────────────────────────────────────── */
.nav {
position: sticky;
top: 0;
z-index: 100;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 40px;
height: 64px;
background: rgba(10, 8, 6, 0.95);
border-bottom: 1px solid var(--border, rgba(232, 220, 200, 0.12));
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
}
.navLogo {
font-family: var(--font-display, Georgia, 'Times New Roman', serif);
font-size: 1.15rem;
font-weight: 700;
letter-spacing: 0.06em;
color: var(--bone, #e8dcc8);
text-decoration: none;
transition: opacity 0.2s;
}
.navLogo:hover { opacity: 0.85; }
.navLogo span { color: var(--red, #c0392b); }
/* Desktop nav list */
.navLinks {
display: flex;
align-items: center;
gap: 4px;
list-style: none;
margin: 0;
padding: 0;
}
.navItem {
position: relative;
}
.navLink {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 8px 14px;
font-size: 0.88rem;
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--bone-dim, #9e9080);
text-decoration: none;
background: none;
border: none;
cursor: pointer;
border-radius: 4px;
transition: color 0.2s, background 0.2s;
font-family: inherit;
}
.navLink:hover { color: var(--bone, #e8dcc8); background: rgba(232,220,200,0.06); }
.navLinkActive {
color: var(--red, #c0392b) !important;
}
.navDropdownTrigger {
/* same as navLink, handled above */
}
.chevron {
font-size: 0.7rem;
opacity: 0.7;
transition: transform 0.2s;
}
/* ── DROPDOWN ──────────────────────────────────────────────────── */
.dropdown {
position: absolute;
top: calc(100% + 8px);
left: 50%;
transform: translateX(-50%);
min-width: 160px;
background: var(--dark-card, #1a1510);
border: 1px solid var(--border, rgba(232,220,200,0.12));
border-radius: 6px;
padding: 6px 0;
box-shadow: 0 8px 32px rgba(0,0,0,0.6);
animation: dropdownIn 0.15s ease;
z-index: 200;
}
@keyframes dropdownIn {
from { opacity: 0; transform: translateX(-50%) translateY(-6px); }
to { opacity: 1; transform: translateX(-50%) translateY(0); }
}
.dropdownItem {
display: block;
padding: 9px 18px;
font-size: 0.87rem;
font-weight: 500;
color: var(--bone-dim, #9e9080);
text-decoration: none;
transition: color 0.15s, background 0.15s;
white-space: nowrap;
}
.dropdownItem:hover { color: var(--bone, #e8dcc8); background: rgba(232,220,200,0.06); }
.dropdownItemActive { color: var(--red, #c0392b) !important; }
/* ── HAMBURGER ─────────────────────────────────────────────────── */
.hamburger {
display: none;
flex-direction: column;
justify-content: center;
gap: 5px;
width: 36px;
height: 36px;
background: none;
border: none;
cursor: pointer;
padding: 4px;
border-radius: 4px;
transition: background 0.2s;
}
.hamburger:hover { background: rgba(232,220,200,0.08); }
.hamburger span {
display: block;
width: 22px;
height: 2px;
background: var(--bone, #e8dcc8);
border-radius: 2px;
transition: opacity 0.2s;
}
/* ── MOBILE DRAWER ─────────────────────────────────────────────── */
.mobileDrawer {
display: none;
flex-direction: column;
background: var(--dark-mid, #120f0a);
border-bottom: 1px solid var(--border, rgba(232,220,200,0.12));
padding: 12px 0 20px;
z-index: 99;
}
.mobileLink {
display: block;
padding: 12px 28px;
font-size: 0.9rem;
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--bone, #e8dcc8);
text-decoration: none;
transition: color 0.2s, background 0.2s;
}
.mobileLink:hover { color: var(--red, #c0392b); background: rgba(232,220,200,0.04); }
.mobileSectionLabel {
padding: 12px 28px 6px;
font-size: 0.7rem;
font-weight: 700;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--red, #c0392b);
}
.mobileLinkIndent {
display: block;
padding: 9px 28px 9px 42px;
font-size: 0.87rem;
color: var(--bone-dim, #9e9080);
text-decoration: none;
transition: color 0.2s;
}
.mobileLinkIndent:hover { color: var(--bone, #e8dcc8); }
/* ── MAIN ──────────────────────────────────────────────────────── */
.main {
flex: 1;
}
/* ── FOOTER ────────────────────────────────────────────────────── */
.footer {
background: var(--dark-mid, #120f0a);
border-top: 1px solid var(--border, rgba(232,220,200,0.12));
}
.footerTop {
display: flex;
gap: 48px;
max-width: 1100px;
margin: 0 auto;
padding: 56px 40px 48px;
flex-wrap: wrap;
}
.footerBrand {
flex: 1;
min-width: 200px;
max-width: 280px;
}
.footerLogo {
font-family: var(--font-display, Georgia, serif);
font-size: 1.2rem;
font-weight: 700;
letter-spacing: 0.06em;
color: var(--bone, #e8dcc8);
}
.footerLogo span { color: var(--red, #c0392b); }
.footerTagline {
margin-top: 10px;
font-size: 0.85rem;
color: var(--bone-dim, #9e9080);
line-height: 1.5;
}
.footerColumns {
display: flex;
gap: 48px;
flex-wrap: wrap;
}
.footerCol {
display: flex;
flex-direction: column;
gap: 8px;
min-width: 120px;
}
.footerColTitle {
font-size: 0.72rem;
font-weight: 700;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--red, #c0392b);
margin-bottom: 4px;
}
.footerLink {
font-size: 0.875rem;
color: var(--bone-dim, #9e9080);
text-decoration: none;
transition: color 0.2s;
}
.footerLink:hover { color: var(--bone, #e8dcc8); }
.footerBottom {
border-top: 1px solid var(--border, rgba(232,220,200,0.08));
padding: 20px 40px;
text-align: center;
font-size: 0.8rem;
color: rgba(158, 144, 128, 0.6);
max-width: 100%;
}
/* ── MOBILE RESPONSIVE ─────────────────────────────────────────── */
@media (max-width: 768px) {
.nav { padding: 0 20px; }
.navLinks { display: none; }
.hamburger { display: flex; }
.mobileDrawer { display: flex; }
.footerTop {
flex-direction: column;
gap: 32px;
padding: 40px 20px 32px;
}
.footerBrand { max-width: 100%; }
.footerColumns { gap: 28px; }
.footerBottom { padding: 16px 20px; }
}
+328
View File
@@ -0,0 +1,328 @@
/* ── Lore page ─────────────────────────────────────────────────────────────── */
.loreGrid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
margin-bottom: 4rem;
}
.loreCard {
background: var(--dark-card);
border: 1px solid var(--border);
padding: 2rem 1.75rem;
position: relative;
overflow: hidden;
transition: border-color 0.2s;
}
.loreCard:hover { border-color: rgba(232,220,200,0.25); }
.loreCard::before {
content: '';
position: absolute;
top: 0; left: 0; right: 0;
height: 2px;
background: var(--red);
transform: scaleX(0);
transform-origin: left;
transition: transform 0.3s;
}
.loreCard:hover::before { transform: scaleX(1); }
.loreIcon {
display: block;
font-size: 2rem;
margin-bottom: 1rem;
}
.loreTitle {
font-family: var(--font-display);
font-size: 1.1rem;
color: var(--bone);
margin-bottom: 0.75rem;
}
.loreText {
font-size: 0.88rem;
color: var(--bone-dim);
line-height: 1.75;
margin-bottom: 1rem;
}
.loreLocked {
font-size: 0.68rem;
letter-spacing: 0.15em;
text-transform: uppercase;
color: var(--red);
opacity: 0.7;
}
/* ── World page ────────────────────────────────────────────────────────────── */
.worldIntro {
max-width: 640px;
margin: 0 auto 4rem;
text-align: center;
}
.worldText {
font-size: 1rem;
color: var(--bone-dim);
line-height: 1.8;
margin-bottom: 1rem;
}
.locationGrid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 1.5rem;
margin-bottom: 4rem;
}
.locationCard {
background: var(--dark-card);
border: 1px solid var(--border);
padding: 2rem 1.75rem;
transition: border-color 0.2s, transform 0.2s;
}
.locationCard:hover {
border-color: rgba(232,220,200,0.25);
transform: translateY(-2px);
}
.locationHeader {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 0.85rem;
}
.locationIcon { font-size: 1.5rem; }
.locationName {
font-family: var(--font-display);
font-size: 1.1rem;
color: var(--bone);
}
.locationDesc {
font-size: 0.88rem;
color: var(--bone-dim);
line-height: 1.75;
}
/* ── Characters page ───────────────────────────────────────────────────────── */
.characterGrid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
gap: 1.5rem;
margin-bottom: 4rem;
}
.characterCard {
background: var(--dark-card);
border: 1px solid var(--border);
overflow: hidden;
transition: border-color 0.2s, transform 0.2s;
}
.characterCard:hover {
border-color: rgba(232,220,200,0.25);
transform: translateY(-3px);
}
.characterCardLocked { opacity: 0.6; }
.characterArt {
position: relative;
aspect-ratio: 1;
background: var(--dark);
border-bottom: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: center;
}
.characterEmoji {
font-size: 5rem;
opacity: 0.15;
}
.characterLockedOverlay {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
font-family: var(--font-display);
font-size: 6rem;
color: var(--bone-dim);
opacity: 0.08;
}
.characterInfo {
padding: 1.5rem;
}
.characterRole {
display: block;
font-size: 0.68rem;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--red);
margin-bottom: 0.4rem;
}
.characterName {
font-family: var(--font-display);
font-size: 1.15rem;
color: var(--bone);
margin-bottom: 0.65rem;
}
.characterDesc {
font-size: 0.85rem;
color: var(--bone-dim);
line-height: 1.7;
}
/* ── Music page ────────────────────────────────────────────────────────────── */
.tracklist {
margin-bottom: 3rem;
border: 1px solid var(--border);
}
.track {
display: flex;
align-items: center;
gap: 1rem;
padding: 1rem 1.25rem;
border-bottom: 1px solid var(--border);
transition: background 0.15s;
}
.track:last-child { border-bottom: none; }
.track:hover { background: rgba(232,220,200,0.04); }
.trackNum {
font-size: 0.75rem;
color: var(--bone-dim);
opacity: 0.5;
min-width: 2rem;
font-variant-numeric: tabular-nums;
}
.trackInfo {
flex: 1;
display: flex;
flex-direction: column;
gap: 0.2rem;
}
.trackTitle {
font-size: 0.9rem;
color: var(--bone);
}
.trackVibe {
font-size: 0.75rem;
color: var(--bone-dim);
opacity: 0.6;
}
.trackPlay {
font-size: 0.8rem;
color: var(--red);
opacity: 0.7;
transition: opacity 0.2s;
cursor: pointer;
}
.trackPlay:hover { opacity: 1; }
.musicEmbed {
margin-bottom: 3rem;
}
.musicEmbedPlaceholder {
border: 1px dashed var(--border);
padding: 4rem 2rem;
text-align: center;
background: var(--dark-card);
}
.musicEmbedIcon {
display: block;
font-size: 3rem;
margin-bottom: 1rem;
opacity: 0.3;
}
.musicEmbedText {
font-size: 0.85rem;
color: var(--bone-dim);
opacity: 0.6;
margin-bottom: 1.5rem;
}
.musicEmbedBtn {
display: inline-flex;
padding: 0.65rem 1.5rem;
background: var(--red);
color: var(--bone);
font-size: 0.78rem;
letter-spacing: 0.1em;
text-transform: uppercase;
font-weight: 600;
transition: background 0.2s;
}
.musicEmbedBtn:hover { background: #a93226; }
.musicPatreon {
text-align: center;
padding: 3rem 2rem;
border: 1px solid var(--border);
background: var(--dark-card);
}
.musicPatreonTitle {
font-family: var(--font-display);
font-size: 1.4rem;
color: var(--bone);
margin-bottom: 0.75rem;
}
.musicPatreonText {
font-size: 0.88rem;
color: var(--bone-dim);
line-height: 1.7;
max-width: 480px;
margin: 0 auto 1.5rem;
}
.musicPatreonBtn {
display: inline-flex;
padding: 0.7rem 1.75rem;
background: transparent;
color: var(--bone);
border: 1px solid var(--border);
font-size: 0.78rem;
letter-spacing: 0.1em;
text-transform: uppercase;
transition: border-color 0.2s, color 0.2s;
}
.musicPatreonBtn:hover {
border-color: var(--bone-dim);
color: var(--bone);
}
/* ── Responsive ────────────────────────────────────────────────────────────── */
@media (max-width: 768px) {
.loreGrid,
.locationGrid,
.characterGrid { grid-template-columns: 1fr; }
.musicEmbedPlaceholder { padding: 2.5rem 1.25rem; }
}