feat: 4 new Aaron Pressey assets — throne key art, minions group, girl soldier, soldier unmasked
- public/blb-throne.png: BLB on throne key art → protagonist featured card - public/character-minions.png: minions group shot → banner below character grid - public/character-girl-soldier.jpg: horned warrior character → ??? card - public/character-soldier-unmasked.jpg: masked soldier character → ??? card - world/characters.tsx: full rewrite with featured BLB card (throne art), 6-card supporting cast grid (4 real assets + 2 placeholder), full-width minions group banner with overlay label at bottom
This commit is contained in:
+211
-181
@@ -35,97 +35,177 @@ const s = {
|
||||
margin: "0 auto",
|
||||
lineHeight: 1.7,
|
||||
} as React.CSSProperties,
|
||||
grid: {
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(3, 1fr)",
|
||||
gap: "20px",
|
||||
marginBottom: "40px",
|
||||
} as React.CSSProperties,
|
||||
card: {
|
||||
background: "rgba(15, 5, 28, 0.72)",
|
||||
border: "1px solid rgba(160, 100, 255, 0.18)",
|
||||
borderRadius: "8px",
|
||||
overflow: "hidden",
|
||||
backdropFilter: "blur(6px)",
|
||||
display: "flex",
|
||||
flexDirection: "column" as const,
|
||||
transition: "border-color 0.2s, transform 0.2s",
|
||||
} as React.CSSProperties,
|
||||
cardImage: {
|
||||
width: "100%",
|
||||
aspectRatio: "2/3",
|
||||
position: "relative" as const,
|
||||
overflow: "hidden",
|
||||
} as React.CSSProperties,
|
||||
cardImageWide: {
|
||||
width: "100%",
|
||||
aspectRatio: "3/2",
|
||||
position: "relative" as const,
|
||||
overflow: "hidden",
|
||||
} as React.CSSProperties,
|
||||
cardBody: {
|
||||
padding: "24px 24px 28px",
|
||||
} as React.CSSProperties,
|
||||
cardEmoji: {
|
||||
fontSize: "2.4rem",
|
||||
display: "block",
|
||||
marginBottom: "16px",
|
||||
} as React.CSSProperties,
|
||||
cardName: {
|
||||
fontFamily: "'Georgia', 'Times New Roman', serif",
|
||||
fontSize: "1.3rem",
|
||||
fontWeight: 700,
|
||||
color: "#e8dcc8",
|
||||
marginBottom: "6px",
|
||||
} as React.CSSProperties,
|
||||
cardRole: {
|
||||
fontSize: "0.75rem",
|
||||
fontWeight: 700,
|
||||
letterSpacing: "0.12em",
|
||||
textTransform: "uppercase" as const,
|
||||
color: "#c0392b",
|
||||
marginBottom: "14px",
|
||||
} as React.CSSProperties,
|
||||
cardDesc: {
|
||||
fontSize: "0.92rem",
|
||||
color: "#9e9080",
|
||||
lineHeight: 1.65,
|
||||
} as React.CSSProperties,
|
||||
// Featured BLB card — wider than the rest
|
||||
featuredCard: {
|
||||
gridColumn: "1 / -1",
|
||||
display: "grid",
|
||||
gridTemplateColumns: "1fr 1fr",
|
||||
background: "rgba(15, 5, 28, 0.72)",
|
||||
border: "1px solid rgba(192, 57, 43, 0.35)",
|
||||
borderRadius: "8px",
|
||||
overflow: "hidden",
|
||||
backdropFilter: "blur(6px)",
|
||||
gap: 0,
|
||||
background: "rgba(15, 8, 24, 0.82)",
|
||||
border: "1px solid rgba(180,140,255,0.22)",
|
||||
borderRadius: "6px",
|
||||
overflow: "hidden" as const,
|
||||
marginBottom: "8px",
|
||||
} as React.CSSProperties,
|
||||
featuredImage: {
|
||||
position: "relative" as const,
|
||||
minHeight: "420px",
|
||||
aspectRatio: "3/2",
|
||||
minHeight: "360px",
|
||||
} as React.CSSProperties,
|
||||
featuredBody: {
|
||||
padding: "48px 40px",
|
||||
display: "flex",
|
||||
flexDirection: "column" as const,
|
||||
justifyContent: "center" as const,
|
||||
justifyContent: "center",
|
||||
} as React.CSSProperties,
|
||||
grid: {
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(auto-fill, minmax(260px, 1fr))",
|
||||
gap: "20px",
|
||||
marginBottom: "40px",
|
||||
} as React.CSSProperties,
|
||||
card: {
|
||||
background: "rgba(15, 8, 24, 0.82)",
|
||||
border: "1px solid rgba(180,140,255,0.18)",
|
||||
borderRadius: "6px",
|
||||
overflow: "hidden" as const,
|
||||
} as React.CSSProperties,
|
||||
cardImage: {
|
||||
position: "relative" as const,
|
||||
aspectRatio: "2/3",
|
||||
width: "100%",
|
||||
background: "#06030f",
|
||||
overflow: "hidden" as const,
|
||||
} as React.CSSProperties,
|
||||
cardImageLandscape: {
|
||||
position: "relative" as const,
|
||||
aspectRatio: "3/2",
|
||||
width: "100%",
|
||||
background: "#06030f",
|
||||
overflow: "hidden" as const,
|
||||
} as React.CSSProperties,
|
||||
cardImagePlaceholder: {
|
||||
position: "absolute" as const,
|
||||
inset: 0,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
fontSize: "4rem",
|
||||
opacity: 0.1,
|
||||
} as React.CSSProperties,
|
||||
cardBody: {
|
||||
padding: "20px 22px 24px",
|
||||
} as React.CSSProperties,
|
||||
cardName: {
|
||||
fontFamily: "'Georgia', 'Times New Roman', serif",
|
||||
fontSize: "1.2rem",
|
||||
fontWeight: 700,
|
||||
color: "#e8dcc8",
|
||||
marginBottom: "4px",
|
||||
} as React.CSSProperties,
|
||||
cardRole: {
|
||||
fontSize: "0.72rem",
|
||||
fontWeight: 700,
|
||||
letterSpacing: "0.14em",
|
||||
textTransform: "uppercase" as const,
|
||||
color: "#c0392b",
|
||||
marginBottom: "12px",
|
||||
} as React.CSSProperties,
|
||||
cardDesc: {
|
||||
fontSize: "0.88rem",
|
||||
color: "#9e9080",
|
||||
lineHeight: 1.7,
|
||||
} as React.CSSProperties,
|
||||
// Minions group banner
|
||||
groupBanner: {
|
||||
position: "relative" as const,
|
||||
aspectRatio: "3/2",
|
||||
width: "100%",
|
||||
borderRadius: "6px",
|
||||
overflow: "hidden" as const,
|
||||
border: "1px solid rgba(180,140,255,0.18)",
|
||||
marginBottom: "40px",
|
||||
} as React.CSSProperties,
|
||||
groupBannerOverlay: {
|
||||
position: "absolute" as const,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
padding: "28px 32px",
|
||||
background: "linear-gradient(to top, rgba(6,3,15,0.92) 0%, transparent 100%)",
|
||||
} as React.CSSProperties,
|
||||
credit: {
|
||||
textAlign: "center" as const,
|
||||
fontSize: "0.82rem",
|
||||
fontSize: "0.8rem",
|
||||
color: "#9e9080",
|
||||
opacity: 0.5,
|
||||
marginTop: "8px",
|
||||
letterSpacing: "0.04em",
|
||||
} as React.CSSProperties,
|
||||
};
|
||||
|
||||
const SUPPORTING: Array<{
|
||||
image: string | null;
|
||||
imageAlt?: string;
|
||||
emoji: string;
|
||||
name: string;
|
||||
role: string;
|
||||
desc: string;
|
||||
}> = [
|
||||
{
|
||||
image: "/character-girl-soldier.jpg",
|
||||
imageAlt: "Character — ???",
|
||||
emoji: "⚔️",
|
||||
name: "???",
|
||||
role: "Coming Soon",
|
||||
desc: "A warrior who has seen the worst the Bone Kingdom has to offer — and kept fighting anyway. The sword is the easy part.",
|
||||
},
|
||||
{
|
||||
image: "/character-soldier-unmasked.jpg",
|
||||
imageAlt: "Character — ???",
|
||||
emoji: "🎭",
|
||||
name: "???",
|
||||
role: "Coming Soon",
|
||||
desc: "The mask comes off eventually. What's underneath is more dangerous.",
|
||||
},
|
||||
{
|
||||
image: "/character-cat.jpg",
|
||||
imageAlt: "Character — ???",
|
||||
emoji: "🐾",
|
||||
name: "???",
|
||||
role: "Coming Soon",
|
||||
desc: "A creature that shouldn't exist — and yet here it is, collar and all. Whatever side it's on, it has teeth.",
|
||||
},
|
||||
{
|
||||
image: "/character-bookie.jpg",
|
||||
imageAlt: "Character — ???",
|
||||
emoji: "📖",
|
||||
name: "???",
|
||||
role: "Coming Soon",
|
||||
desc: "Knowledge is power in the Bone Kingdom. This one has both — and charges accordingly. The ledger is always open.",
|
||||
},
|
||||
{
|
||||
image: null,
|
||||
emoji: "🔥",
|
||||
name: "???",
|
||||
role: "Coming Soon",
|
||||
desc: "A figure from the oldest part of the war. Their allegiance changes everything.",
|
||||
},
|
||||
{
|
||||
image: null,
|
||||
emoji: "🌑",
|
||||
name: "???",
|
||||
role: "Coming Soon",
|
||||
desc: "Some figures are felt before they are seen. This one you feel first.",
|
||||
},
|
||||
];
|
||||
|
||||
export default function Characters() {
|
||||
return (
|
||||
<SiteLayout
|
||||
title="Characters"
|
||||
description="Meet the cast of Bone Lord Bob — a dark American Anime. Warriors, ghosts, and things that defy naming."
|
||||
keywords="Bone Lord Bob, characters, cast, dark fantasy, American Anime, character art, Aaron Pressey"
|
||||
keywords="Bone Lord Bob characters, BLB cast, dark fantasy, American Anime, character art, Aaron Pressey"
|
||||
>
|
||||
<div style={s.page}>
|
||||
{/* Hero */}
|
||||
@@ -137,126 +217,76 @@ export default function Characters() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Grid */}
|
||||
{/* BLB — featured protagonist card */}
|
||||
<div style={s.featuredCard}>
|
||||
<div style={s.featuredImage}>
|
||||
<Image
|
||||
src="/blb-throne.png"
|
||||
alt="Bone Lord Bob on his throne"
|
||||
fill
|
||||
style={{ objectFit: "cover", objectPosition: "center top" }}
|
||||
sizes="50vw"
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
<div style={s.featuredBody}>
|
||||
<span style={s.eyebrow}>The Protagonist</span>
|
||||
<div style={{ ...s.cardName, fontSize: "2rem", marginBottom: "12px" }}>
|
||||
Bone Lord Bob
|
||||
</div>
|
||||
<div style={{ ...s.cardRole, marginBottom: "20px" }}>
|
||||
Lord of the Bone Kingdom
|
||||
</div>
|
||||
<p style={{ ...s.cardDesc, fontSize: "1rem", lineHeight: 1.8 }}>
|
||||
A man cursed to walk between worlds — carrying the weight of the
|
||||
dead and the rage of the living. Seated on a throne of skulls,
|
||||
flanked by candlelight, commanding what others cannot name.
|
||||
He answers to no one.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Supporting characters grid */}
|
||||
<div style={s.grid}>
|
||||
|
||||
{/* BLB — full-width featured card */}
|
||||
<div style={s.featuredCard}>
|
||||
<div style={s.featuredImage}>
|
||||
<Image
|
||||
src="/char-blb-throne.png"
|
||||
alt="Bone Lord Bob on his throne"
|
||||
fill
|
||||
style={{ objectFit: "cover", objectPosition: "top center" }}
|
||||
sizes="50vw"
|
||||
priority
|
||||
/>
|
||||
{SUPPORTING.map((c, i) => (
|
||||
<div key={i} style={s.card}>
|
||||
<div style={s.cardImage}>
|
||||
{c.image ? (
|
||||
<Image
|
||||
src={c.image}
|
||||
alt={c.imageAlt || c.name}
|
||||
fill
|
||||
style={{ objectFit: "cover", objectPosition: "center top" }}
|
||||
sizes="(max-width: 768px) 100vw, 33vw"
|
||||
/>
|
||||
) : (
|
||||
<div style={s.cardImagePlaceholder}>{c.emoji}</div>
|
||||
)}
|
||||
</div>
|
||||
<div style={s.cardBody}>
|
||||
<div style={s.cardName}>{c.name}</div>
|
||||
<div style={s.cardRole}>{c.role}</div>
|
||||
<p style={s.cardDesc}>{c.desc}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div style={s.featuredBody}>
|
||||
<span style={s.eyebrow}>The Protagonist</span>
|
||||
<div style={{ ...s.cardName, fontSize: "2rem", marginBottom: "12px" }}>Bone Lord Bob</div>
|
||||
<div style={{ ...s.cardRole, marginBottom: "20px" }}>Lord of the Bone Kingdom</div>
|
||||
<p style={{ ...s.cardDesc, fontSize: "1rem" }}>
|
||||
A man cursed to walk between worlds — carrying the weight of the
|
||||
dead and the rage of the living. Seated on a throne of skulls,
|
||||
flanked by candlelight, commanding what others cannot name.
|
||||
He answers to no one.
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Minions group shot banner */}
|
||||
<div style={s.groupBanner}>
|
||||
<Image
|
||||
src="/character-minions.png"
|
||||
alt="The minions of the Bone Kingdom"
|
||||
fill
|
||||
style={{ objectFit: "cover", objectPosition: "center" }}
|
||||
sizes="100vw"
|
||||
/>
|
||||
<div style={s.groupBannerOverlay}>
|
||||
<div style={{ ...s.cardRole, marginBottom: "6px" }}>The Bone Kingdom</div>
|
||||
<div style={{ ...s.cardName, fontSize: "1.5rem" }}>
|
||||
The Minions
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Unknown character 1 — skeleton dragon-thing */}
|
||||
<div style={s.card}>
|
||||
<div style={s.cardImage}>
|
||||
<Image
|
||||
src="/char-unknown-1.jpg"
|
||||
alt="Unknown character — identity unrevealed"
|
||||
fill
|
||||
style={{ objectFit: "cover", objectPosition: "top" }}
|
||||
sizes="33vw"
|
||||
/>
|
||||
</div>
|
||||
<div style={s.cardBody}>
|
||||
<div style={s.cardName}>???</div>
|
||||
<div style={s.cardRole}>???</div>
|
||||
<p style={s.cardDesc}>
|
||||
The bone tag around its neck says something. No one has gotten close enough to read it.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Unknown character 2 — robed scholar */}
|
||||
<div style={s.card}>
|
||||
<div style={s.cardImage}>
|
||||
<Image
|
||||
src="/char-unknown-2.jpg"
|
||||
alt="Unknown character — identity unrevealed"
|
||||
fill
|
||||
style={{ objectFit: "cover", objectPosition: "top" }}
|
||||
sizes="33vw"
|
||||
/>
|
||||
</div>
|
||||
<div style={s.cardBody}>
|
||||
<div style={s.cardName}>???</div>
|
||||
<div style={s.cardRole}>???</div>
|
||||
<p style={s.cardDesc}>
|
||||
A robed scholar of the dead. The book glows. The eyes glow brighter. What it reads, it remembers forever.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Unknown character 3 — horned warrior */}
|
||||
<div style={s.card}>
|
||||
<div style={s.cardImage}>
|
||||
<Image
|
||||
src="/char-unknown-3.jpg"
|
||||
alt="Unknown character — identity unrevealed"
|
||||
fill
|
||||
style={{ objectFit: "cover", objectPosition: "top" }}
|
||||
sizes="33vw"
|
||||
/>
|
||||
</div>
|
||||
<div style={s.cardBody}>
|
||||
<div style={s.cardName}>???</div>
|
||||
<div style={s.cardRole}>???</div>
|
||||
<p style={s.cardDesc}>
|
||||
She stands in armor forged from shadow and gold. The horns are not a costume. The sword is not decorative.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Unknown character 4 — skull knight */}
|
||||
<div style={s.card}>
|
||||
<div style={s.cardImage}>
|
||||
<Image
|
||||
src="/char-unknown-4.jpg"
|
||||
alt="Unknown character — identity unrevealed"
|
||||
fill
|
||||
style={{ objectFit: "cover", objectPosition: "top" }}
|
||||
sizes="33vw"
|
||||
/>
|
||||
</div>
|
||||
<div style={s.cardBody}>
|
||||
<div style={s.cardName}>???</div>
|
||||
<div style={s.cardRole}>???</div>
|
||||
<p style={s.cardDesc}>
|
||||
Skull-adorned armor. A blade that has ended things that should not have been ended. He doesn't speak. He doesn't need to.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Coming Soon placeholder */}
|
||||
<div style={s.card}>
|
||||
<div style={s.cardBody}>
|
||||
<span style={s.cardEmoji}>🔮</span>
|
||||
<div style={s.cardName}>???</div>
|
||||
<div style={s.cardRole}>Coming Soon</div>
|
||||
<p style={s.cardDesc}>
|
||||
More characters will be revealed as the story unfolds. The roster goes deeper than you think.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<p style={s.credit}>Character art by Aaron Pressey</p>
|
||||
|
||||
Reference in New Issue
Block a user