/* @jsx React.createElement */ /* Stamps — 59-character collection, hoverable / expandable */ /* 59 hand-picked motifs spanning a Japan-warm vocabulary: animals, food, instruments, weather, faces, plants — kid-friendly but not infantile. We render glyphs (emoji shapes drawn as SVG-ish or as text) on a colored disc. To match the "no emoji" rule, we use letters/symbols/glyphs from typographic forms only. */ const STAMP_CHARS = [ { ch: 'A', n: 'Ace' }, { ch: 'B', n: 'Beat' }, { ch: 'C', n: 'Chord' }, { ch: 'D', n: 'Drum' }, { ch: 'E', n: 'Echo' }, { ch: 'F', n: 'Fill' }, { ch: 'G', n: 'Groove' }, { ch: 'H', n: 'Hi-Hat' }, { ch: 'I', n: 'Intro' }, { ch: 'J', n: 'Jam' }, { ch: 'K', n: 'Kick' }, { ch: 'L', n: 'Loop' }, { ch: 'M', n: 'Melody' }, { ch: 'N', n: 'Note' }, { ch: 'O', n: 'Octave' }, { ch: 'P', n: 'Pitch' }, { ch: 'Q', n: 'Quarter' }, { ch: 'R', n: 'Rhythm' }, { ch: 'S', n: 'Snare' }, { ch: 'T', n: 'Tempo' }, { ch: 'U', n: 'Unison' }, { ch: 'V', n: 'Vibe' }, { ch: 'W', n: 'Wave' }, { ch: 'X', n: 'X-fade' }, { ch: 'Y', n: 'Yell' }, { ch: 'Z', n: 'Zen' }, { ch: '♩', n: 'Quarter note' }, { ch: '♪', n: 'Eighth' }, { ch: '♫', n: 'Beam' }, { ch: '♬', n: 'Sixteenth' }, { ch: '♭', n: 'Flat' }, { ch: '♯', n: 'Sharp' }, { ch: '♮', n: 'Natural' }, { ch: '𝄞', n: 'Treble' }, { ch: '𝄢', n: 'Bass clef' }, { ch: '◐', n: 'Half' }, { ch: '◉', n: 'Bullseye' }, { ch: '◇', n: 'Diamond' }, { ch: '◆', n: 'Filled' }, { ch: '△', n: 'Triangle' }, { ch: '▲', n: 'Solid' }, { ch: '☆', n: 'Star' }, { ch: '★', n: 'Star+' }, { ch: '✦', n: 'Spark' }, { ch: '✱', n: 'Burst' }, { ch: '✺', n: 'Sun' }, { ch: '✿', n: 'Bloom' }, { ch: '❀', n: 'Plum' }, { ch: '❁', n: 'Blossom' }, { ch: '✓', n: 'Done' }, { ch: '⌘', n: 'Cmd' }, { ch: '∞', n: 'Infinite' }, { ch: 'Ω', n: 'Omega' }, { ch: '♥', n: 'Heart' }, { ch: '☂', n: 'Rain' }, { ch: '☀', n: 'Sun day' }, { ch: '☾', n: 'Night' }, { ch: '✈', n: 'Send' }, { ch: 'ハ', n: 'Ha' }, { ch: 'ピ', n: 'Pi' }, ]; const STAMP_PALETTE = [ '#D03020', '#F04000', '#004080', '#00A0E0', '#F0D050', '#001933', '#A52416', '#0078A8', '#2F679A', '#BFA024', '#3D3B35', ]; function StampsSection() { const [hovered, setHovered] = React.useState(null); const [collected, setCollected] = React.useState(() => new Set([0, 1, 2, 4, 7, 8, 10, 12, 13, 17, 19, 21, 24, 28, 30, 34, 41, 47, 52])); const toggle = (i) => { setCollected(prev => { const next = new Set(prev); if (next.has(i)) next.delete(i); else next.add(i); return next; }); }; const focus = hovered != null ? STAMP_CHARS[hovered] : null; return (
{/* Left: copy */}
Gamifikasi · 59 stamp

Kumpulin 59 stamp. Satu per session.

Tiap lesson, gurumu nge-stamp kartu kamu. Bukan dinilai — cuma punya kamu. Anak-anak ngejar. Eh, ternyata yang dewasa juga diem-diem ngejar.

{/* Active stamp preview */}
Stamp · {String((hovered != null ? hovered : 12) + 1).padStart(2, '0')} / 59
{focus ? focus.n : STAMP_CHARS[12].n}
Hover buat preview. Tap buat (un)collect.
{/* Collected counter */}
Koleksi kamu
{String(collected.size).padStart(2, '0')} / 59
{/* Right: grid */}
{STAMP_CHARS.map((s, i) => ( ))}
); } function Stamp({ idx, size = 64, small = false, earned = true, highlight = false }) { const stamp = STAMP_CHARS[idx]; const color = STAMP_PALETTE[idx % STAMP_PALETTE.length]; const dim = small ? '100%' : size; return (
{/* tiny number tag */} {earned && ( {String(idx + 1).padStart(2, '0')} )} {stamp.ch}
); } Object.assign(window, { StampsSection });