// 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 && (
)}
);
}
// ─── 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 });