diff --git a/pages/world/characters.tsx b/pages/world/characters.tsx index 37b5532..a342fdd 100644 --- a/pages/world/characters.tsx +++ b/pages/world/characters.tsx @@ -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 (
{/* Hero */} @@ -137,126 +217,76 @@ export default function Characters() {

- {/* Grid */} + {/* BLB — featured protagonist card */} +
+
+ Bone Lord Bob on his throne +
+
+ The Protagonist +
+ Bone Lord Bob +
+
+ Lord of the Bone Kingdom +
+

+ 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. +

+
+
+ + {/* Supporting characters grid */}
- - {/* BLB — full-width featured card */} -
-
- Bone Lord Bob on his throne + {SUPPORTING.map((c, i) => ( +
+
+ {c.image ? ( + {c.imageAlt + ) : ( +
{c.emoji}
+ )} +
+
+
{c.name}
+
{c.role}
+

{c.desc}

+
-
- The Protagonist -
Bone Lord Bob
-
Lord of the Bone Kingdom
-

- 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. -

+ ))} +
+ + {/* Minions group shot banner */} +
+ The minions of the Bone Kingdom +
+
The Bone Kingdom
+
+ The Minions
- - {/* Unknown character 1 — skeleton dragon-thing */} -
-
- Unknown character — identity unrevealed -
-
-
???
-
???
-

- The bone tag around its neck says something. No one has gotten close enough to read it. -

-
-
- - {/* Unknown character 2 — robed scholar */} -
-
- Unknown character — identity unrevealed -
-
-
???
-
???
-

- A robed scholar of the dead. The book glows. The eyes glow brighter. What it reads, it remembers forever. -

-
-
- - {/* Unknown character 3 — horned warrior */} -
-
- Unknown character — identity unrevealed -
-
-
???
-
???
-

- She stands in armor forged from shadow and gold. The horns are not a costume. The sword is not decorative. -

-
-
- - {/* Unknown character 4 — skull knight */} -
-
- Unknown character — identity unrevealed -
-
-
???
-
???
-

- Skull-adorned armor. A blade that has ended things that should not have been ended. He doesn't speak. He doesn't need to. -

-
-
- - {/* Coming Soon placeholder */} -
-
- 🔮 -
???
-
Coming Soon
-

- More characters will be revealed as the story unfolds. The roster goes deeper than you think. -

-
-
-

Character art by Aaron Pressey