// nyashelf-mascot.jsx // SVG ghost-kitten mascot + ambient decor (stars, petals, hearts, moon). // ─── Ghost Kitten ────────────────────────────────────────────────────────── // Animated pixel-art sleepy cat sticker from Tenor (replaces the SVG mascot). // All variants render the same GIF — kept the prop signature for backward compat // with existing callers (empty/loading/error/profile/dashboard). const NYA_CAT_GIF = 'https://media1.tenor.com/m/aSPVJF7EmCYAAAAC/cat-cat-sleep.gif'; function GhostKitten({ size = 96, variant = 'default', glow = true, style = {} }) { const radius = Math.max(12, size * 0.22); return (
{glow && (
)} sleepy cat
); } // ─── Moon ──────────────────────────────────────────────────────────────────── function Moon({ size = 60, style = {} }) { return (
); } // ─── Decor sprites ─────────────────────────────────────────────────────────── const Sparkle = ({ size = 10, color = '#fff', opacity = .8 }) => ( ); const Petal = ({ size = 12, color = '#ffb3d9', opacity = .7, rot = 0 }) => ( ); const Heart = ({ size = 10, color = '#ff9ecd', opacity = .7 }) => ( ); const PawPrint = ({ size = 12, color = '#c89bf0', opacity = .55 }) => ( ); const Star4 = ({ size = 8, color = '#fff', opacity = .8 }) => ( ); // ─── DecorLayer — sprinkles ambient decor over a screen ────────────────────── // density 0–100; positions are deterministic (seeded by id) so they don't reshuffle on rerender function DecorLayer({ density = 50, seed = 'a', includeMoon = false, palette }) { const items = React.useMemo(() => { // simple seeded rng let s = 0; for (let i = 0; i < seed.length; i++) s = (s * 31 + seed.charCodeAt(i)) >>> 0; const rng = () => { s = (s * 1103515245 + 12345) & 0x7fffffff; return s / 0x7fffffff; }; const count = Math.round(8 + (density / 100) * 28); const kinds = ['sparkle', 'sparkle', 'sparkle', 'petal', 'heart', 'paw', 'star4', 'star4']; return Array.from({ length: count }, (_, i) => { const kind = kinds[Math.floor(rng() * kinds.length)]; return { kind, key: i, x: rng() * 100, y: rng() * 100, size: 6 + rng() * 12, rot: rng() * 360, opacity: 0.35 + rng() * 0.5, delay: rng() * 4, dur: 3 + rng() * 4, }; }); }, [density, seed]); const palCol = palette === 'sakura' ? ['#ffd9eb', '#ffb3d9', '#e8a3f0'] : palette === 'moonlit' ? ['#c4e4ff', '#b3c8ff', '#f5e6a8'] : palette === 'twilight' ? ['#a5c3f5', '#c89bf0', '#f5e6a8'] : ['#ff9ecd', '#c89bf0', '#f5e6a8']; return (
{includeMoon && (
)} {items.map(it => { const col = palCol[it.key % palCol.length]; const sprite = it.kind === 'sparkle' ? : it.kind === 'petal' ? : it.kind === 'heart' ? : it.kind === 'paw' ? : ; return (
{sprite}
); })}
); } Object.assign(window, { GhostKitten, Moon, Sparkle, Petal, Heart, PawPrint, Star4, DecorLayer });