/* global React */
// Pixel-art card — canvas background + chamfered SVG panels + bitmap fonts.
// Card is 400×512 final, painted at 100×128 native and upscaled 4× pixelated.
const { useRef, useEffect, useMemo } = React;
// ============ Palettes (limited, per-rarity) ============
const RARITIES = {
comum: {
label: "COMUM",
bgImage: "assets/bg-comum.png",
frameOuter: "#2e2e34",
frameGold: "#c8c8d0",
frameInner: "#5a5a64",
namePlateBg:"#f4ecd8",
namePlateEdge:"#2e2e34",
nameText: "#2a2a32",
statPanelBg:"#22222a",
statPanelEdge:"#0e0e14",
panelLine: "#c8c8d0",
statLabel: "#c8c8d0",
value: "#f4f4f8",
icon: "#f4ecd8",
divider: "#0e0e14",
badgeBg: "#22222a",
badgeBorder:"#c8c8d0",
badgeText: "#f4ecd8",
panelBg: "#22222a",
panelEdge: "#0e0e14",
},
raro: {
label: "RARO",
bgImage: "assets/bg-raro.png",
frameOuter: "#062448",
frameGold: "#f8d860",
frameInner: "#1a52b8",
namePlateBg:"#f4ecd8",
namePlateEdge:"#062448",
nameText: "#0a2068",
statPanelBg:"#0c2a78",
statPanelEdge:"#04143a",
panelLine: "#f8d860",
statLabel: "#f8d860",
value: "#fff8d0",
icon: "#f8d860",
divider: "#04143a",
badgeBg: "#0c2a78",
badgeBorder:"#f8d860",
badgeText: "#fff8d0",
panelBg: "#0c2a78",
panelEdge: "#04143a",
},
epico: {
label: "ÉPICO",
bgImage: "assets/bg-epico.png",
frameOuter: "#1e0438",
frameGold: "#f4d060",
frameInner: "#5a1c92",
namePlateBg:"#f4ecd8",
namePlateEdge:"#1e0438",
nameText: "#2a0a55",
statPanelBg:"#2a0a55",
statPanelEdge:"#0a0218",
panelLine: "#f4d060",
statLabel: "#f4d060",
value: "#fff8e0",
icon: "#f4d060",
divider: "#0a0218",
badgeBg: "#2a0a55",
badgeBorder:"#f4d060",
badgeText: "#fff8e0",
panelBg: "#2a0a55",
panelEdge: "#0a0218",
},
lendario: {
label: "LENDÁRIO",
bgImage: "assets/bg-lendario.png",
frameOuter: "#2a1404",
frameGold: "#f8d860",
frameInner: "#a06820",
namePlateBg:"#f4ecd8",
namePlateEdge:"#2a1404",
nameText: "#3a2008",
statPanelBg:"#3a2008",
statPanelEdge:"#150804",
panelLine: "#f8d860",
statLabel: "#f8d860",
value: "#fff8d0",
icon: "#f8d860",
divider: "#150804",
badgeBg: "#3a2008",
badgeBorder:"#f8d860",
badgeText: "#fff8d0",
panelBg: "#3a2008",
panelEdge: "#150804",
},
};
// ============ Background (uses static images) ============
function PixelBackground({ rarity }) {
const p = RARITIES[rarity];
return (
);
}
// ============ Pixel-art icons (12×12 grid) ============
// Each icon is a bitmap as array of strings. '.' = transparent, '#' = filled
const ICON_BITMAPS = {
trophy: [
"............",
"..########..",
"..#......#..",
".##......##.",
".#.######.#.",
".#.######.#.",
".##......##.",
"..#.####.#..",
"...#....#...",
"...######...",
"..########..",
"............",
],
star: [
"............",
".....##.....",
".....##.....",
"....####....",
".##########.",
"..########..",
"...######...",
"..##....##..",
".##......##.",
"............",
"............",
"............",
],
ball: [
"............",
"...######...",
"..#.####.#..",
".##.####.##.",
".#..####..#.",
".########.#.",
".#.######.#.",
".##.####.##.",
"..#.####.#..",
"...######...",
"............",
"............",
],
crown: [
"............",
".#..........",
".##....##..#",
".#.#..#..#.#",
".#..##.#..##",
".#######..#.",
".##########.",
".##.####.##.",
".##########.",
"............",
"............",
"............",
],
people: [
"............",
"...##....##.",
"..####..####",
"..####..####",
"...##....##.",
"............",
".########..#",
"##......####",
"##......##.#",
"##......##.#",
"############",
"............",
],
shield: [
"............",
"..########..",
".##########.",
".##########.",
".##.....###.",
".###...###..",
".####.####..",
"..########..",
"...######...",
"....####....",
".....##.....",
"............",
],
calendar: [
"............",
"..##....##..",
"..##....##..",
"############",
"#..........#",
"############",
"#..#..#..#.#",
"#..#..#..#.#",
"#..........#",
"############",
"............",
"............",
],
flag: [
"............",
".#..........",
".#######....",
".#.....##...",
".#......#...",
".#.....##...",
".#######....",
".#..........",
".#..........",
".#..........",
"............",
"............",
],
boot: [
"............",
"............",
"....#####...",
"...##...##..",
"..##.....##.",
"..#.......##",
"..#.......##",
"############",
".##########.",
"............",
"............",
"............",
],
whistle: [
"............",
"............",
"...####.....",
"..######.###",
".#####.#.###",
".#####.#####",
"..######.###",
"...####.....",
"............",
"............",
"............",
"............",
],
position: [
"............",
"....####....",
"..########..",
".##......##.",
".#...##...#.",
".#..####..#.",
".#...##...#.",
".##......##.",
"..########..",
"....####....",
"............",
"............",
],
bolt: [
"............",
"......###...",
".....####...",
"....####....",
"...####.....",
"..########..",
"...#####....",
"...####.....",
"..####......",
".####.......",
"############",
"............",
],
goal: [
"............",
"############",
"#..#..#..#.#",
"#..#..#..#.#",
"############",
"#..#..#..#.#",
"#..#..#..#.#",
"############",
"#..........#",
"############",
"............",
"............",
],
cards: [
"............",
"..######....",
".#......#...",
".#......#...",
".#......#.##",
".#......##.#",
".#######.#.#",
"..####...#.#",
".......#..##",
".......####.",
"............",
"............",
],
};
const ICON_NAMES = Object.keys(ICON_BITMAPS);
// Renders a pixel icon at a given pixel size (each '#' becomes a SIZE×SIZE square)
function PixelIcon({ name, color, pixelSize = 2 }) {
const map = ICON_BITMAPS[name] || ICON_BITMAPS.star;
const w = map[0].length * pixelSize;
const h = map.length * pixelSize;
return (
);
}
// ============ Pixel frame (chunky gold, double-line) ============
function PixelFrame({ rarity }) {
const p = RARITIES[rarity];
// Native 100×128 viewBox, pixel-perfect rings.
// Frame layers from outermost to innermost:
// 0-1: outer dark line (1 native px)
// 1-5: thick gold band (4 native px)
// 5-6: inner dark line (1 native px)
// Total: 6 native px = 24 upscaled px
const outer = "M0,0 H100 V128 H0 Z";
const r1 = "M1,1 H99 V127 H1 Z";
const r5 = "M5,5 H95 V123 H5 Z";
const r6 = "M6,6 H94 V122 H6 Z";
return (
);
}
// ============ Pixel corner brackets (simple L, like reference) ============
function PixelCornerOrnaments({ rarity }) {
const p = RARITIES[rarity];
// Simple 4×4 native L-bracket: just a corner accent
const Bracket = () => (