Language:
🎂 Birthday
Pizza Beat × Bacci Kid: La Famiglia Edition
Il menù segreto per la tua anima — The secret menu for your soul
Claim Free Coloring Page
Ecco Cosa Succede — What Happens
Let’s play! — Giochiamo!
Scan, tap a question, share a story — everything changes.
- The quiet guest becomes the table comedian
- Someone shares a story that surprises everyone
- Conversations flow easier than they have in years
- Everyone leaves feeling more connected
Giochi da Tavolo — Table Games — La Famiglia — The Family Edition
Ready to play, laugh & connect?
Scan the QR at your table or tap below to start your first Bacci Kid game — free for guests this month!
Learn an Italian Word — Una parola al giorno — One word a day
Emotion Mirror — How are you feeling?
Bacci Emotion Wheel — Tap how you feel — Ti senti…?
Tap a bubble (or the middle) to see Bacci’s coping skills & a quick pep talk.
Italian Fun Facts — Did you know?
Tap to play optional café/accordion ambience.
Via Italia — Our little street of stories
It starts with famiglia — familyAt Pizza Beat × Bacci Kid, every table is a little piazza for stories.
🐱👓
🦋
The Butterfly PrincessShe flutters in to spark courage, kindness, and curiosity.
Welcome to the familyPlay a game, share a memory, laugh louder. You’re home.
Wish Wall — Birthday wishes (anonymous)
We rotate a few wishes so everyone gets a smile. 💖
Design a Bacci Kid Pizza — Per il nostro supereroe — For our superhero
🍅 Tomato
🧀 Mozzarella
🌿 Basil
🍄 Mushroom
🫑 Peppers
🍖 Pepperoni
🧅 Onion
🫒 Olives
🌶️ Chili
🧄 Garlic
Drag toppings onto the pizza. Double-click a topping to remove it.
Bonus Downloads — Giochi extra & coloring — Extra games & coloring
Scan to Play
Point your camera to jump into the Bacci Kid game. Buon divertimento! — Have fun!
🎉 Celebrate a Win
Share one little win from today, then high-five the table.
📸 Pizza Beat × Bacci Kid — Photo Booth
Tip: Cameras require HTTPS on mobile. If blocked, use Upload.
Friendly ideas, not medical advice. If you’re struggling, please reach out to someone you trust or a professional.
Filter by age • or mood
🦋
✅ Bonus on the way! Check your inbox.
Level 1
Target 20
Feeds 0 / 0
⭐ 0
Benvenuti! Tap butterflies to feed them. 💛
© 2025 Jamie Karia / Bacci Kid. Original character art & simple, generic SVG shapes are non-infringing. This experience is for general well-being and play—no medical claims.
Who’s playing today?
This sets speed, points, and story depth.
Sound & Captions
Choose how you want to play. No audio will play unless you turn it on.
Choose Butterfly Colors
Tap a palette to apply instantly.
Level Complete!
Nonna Bacci Amore: Bravissimi! 💖
Reflection…
Congratulazioni! / Congratulations!
Nonna Bacci Amore: You did it, tesoro — your kindness grew a garden! 🌟
Mindful Breath
Nonna Bacci Amore: Let’s take 20 seconds to breathe together. In… out… 🌬️
Did you know? A few slow breaths can help the body feel calmer for a moment.
For well-being and play. Not medical advice. Tip: Turn on “Audio” above for voice prompts.
Grazie / Thank you ✨
You’re part of the Bacci Kid family. Your kindness helps butterflies (and people) bloom. 💛
/* ----------------------------
* GAME LOOP & BUTTERFLIES
* ---------------------------- */
function COLORS(){ return [
{id:'love',color:css('--love'),points:1},
{id:'joy',color:css('--joy'),points:2},
{id:'calm',color:css('--calm'),points:2},
{id:'imagination',color:css('--imagine'),points:3},
{id:'courage',color:css('--courage'),points:3},
{id:'empathy',color:css('--empathy'),points:2},
{id:'gratitude',color:css('--gratitude'),points:4}
]}
function bfySVG(c,golden=false){
const glow=golden?'filter: drop-shadow(0 0 6px rgba(255,214,76,.9));':'';
return `
`;
}
function spawnButterfly(){
if(!RUNNING) return; active++;
const side=Math.random()<.5?'left':'right';
const y=40+Math.random()*(arena.clientHeight-80);
const startX=side==='left'?-40:arena.clientWidth+40;
const endX=side==='left'?arena.clientWidth+40:-40;
const golden=Math.random()<(0.010+level*0.0008);
const col=golden?{id:'gold',color:'#ffd64c',points:10}:COLORS()[Math.floor(Math.random()*COLORS().length)];
// Base duration from difficulty, softened a bit in Calm so it doesn’t feel “stuck”
let dur=speedFor(level)*(0.92+Math.random()*0.42);
if(calm) dur*=0.78; // speed up Calm so it feels gently alive
const el=document.createElement('div');
el.className='bfy'; el.style.left=startX+'px'; el.style.top=y+'px';
el.innerHTML=bfySVG(col.color,golden);
arena.appendChild(el);
const start=performance.now();
const baseBias=pauseBias;
let raf;
function tick(t){
if(!RUNNING){ el.remove(); return; }
if(PAUSED){ raf=requestAnimationFrame(tick); return; }
const pausedSinceSpawn=pauseBias-baseBias;
const p=Math.min(1, Math.max(0,(t-start-pausedSinceSpawn)/(dur*1000)));
const x=startX+(endX-startX)*p;
const wave=Math.sin(p*6)*(calm?2.2:9);
el.style.transform=`translate(${x}px, ${-50+wave}px)`;
// cute trail
if(Math.random()<0.10){
const tr=document.createElement('div');
tr.className='trail';
tr.style.left=(x+arena.getBoundingClientRect().left)+'px';
tr.style.top=(arena.getBoundingClientRect().top-50+wave+y)+'px';
document.body.appendChild(tr);
tr.animate(
[{opacity:.9,transform:'translate(-50%,-50%) scale(1)'},{opacity:0,transform:'translate(-50%,-60%) scale(0.6)'}],
{duration:480}
).onfinish=()=>tr.remove();
}
if(p<1){ raf=requestAnimationFrame(tick); }
else { vanish(el,false); removeSelf(); }
}
raf=requestAnimationFrame(tick);
el.addEventListener('pointerdown', e=>{
cancelAnimationFrame(raf);
collect(col.points, e.clientX, e.clientY);
if(col.id==='gold'){ if(fxOn) puffConfetti(e.clientX,e.clientY,24); cheer('goodTap'); }
vanish(el,true,e.clientX,e.clientY);
removeSelf();
}, {once:true});
function vanish(node,byTap,x=0,y=0){
node.animate(
[{transform:node.style.transform+' scale(1)',opacity:1},{transform:node.style.transform+' scale(0.5)',opacity:0}],
{duration:260,easing:'ease-out'}
);
if(!fxOn) return;
if(byTap){ puffAt(x,y); }
else{
const r=node.getBoundingClientRect();
puffAt(r.left+r.width/2,r.top+r.height/2);
puffConfetti(r.left+r.width/2,r.top+r.height/2,6);
}
}
function removeSelf(){
if(!el.isConnected) return;
setTimeout(()=>{
el.remove(); active--;
if(RUNNING){
const base= calm ? 260 : 340; // slightly brisker cadence in Calm
setTimeout(spawnButterfly, base+Math.random()*520);
}
}, 240);
}
}
/* ----------------------------
* OPTIONAL FOCUS DISTRACTORS
* ---------------------------- */
const EMOJI=['🐢','🐇','🍄','🐝','🐞','🎈','🌈','✨','🍃','🪄','🧁','🍓'];
function spawnDistractor(){
const d=document.createElement('div'); d.className='distract';
const span=document.createElement('span'); span.className='emo';
span.textContent=EMOJI[Math.floor(Math.random()*EMOJI.length)];
d.appendChild(span);
const y=60+Math.random()*(arena.clientHeight-120);
const start=-20, end=arena.clientWidth+20;
d.style.top=y+'px'; d.style.left='-20px';
arena.appendChild(d);
const startT=performance.now();
const dur=9000+Math.random()*4000;
let raf;
function tick(t){
if(!RUNNING){ d.remove(); return; }
if(PAUSED){ raf=requestAnimationFrame(tick); return; }
const p=Math.min(1,(t-startT)/dur);
const x=start+(end-start)*p;
d.style.transform=`translate(${x}px, -50%)`;
if(p<1) raf=requestAnimationFrame(tick); else d.remove();
}
raf=requestAnimationFrame(tick);
d.addEventListener('pointerdown',()=>{
const r=d.getBoundingClientRect();
puffAt(r.left+r.width/2,r.top+r.height/2);
d.remove();
},{once:true});
}
/* ----------------------------
* TAP FX / SCORING
* ---------------------------- */
function popAt(x,y,txt){
const d=document.createElement('div');
d.textContent=txt;
document.body.appendChild(d);
d.style.cssText=`position:fixed;left:${x}px;top:${y}px;transform:translate(-50%,-80%);font-weight:900;color:#000;text-shadow:0 2px 0 #fff;pointer-events:none`;
d.animate(
[{opacity:1,transform:'translate(-50%,-80%)'},{opacity:0,transform:'translate(-50%,-140%)'}],
{duration:700}
).onfinish=()=>d.remove();
}
function nectarAt(x,y){
const r=arena.getBoundingClientRect();
const rx=Math.max(0,Math.min(r.width,x-r.left));
const ry=Math.max(0,Math.min(r.height,y-r.top));
const dot=document.createElement('div'); dot.className='nectar';
dot.style.left=rx+'px'; dot.style.top=ry+'px'; dot.style.transform='translate(-50%,-50%)';
arena.appendChild(dot);
dot.animate(
[{transform:'translate(-50%,-50%) scale(1)',opacity:1},{transform:'translate(-50%,-80%) scale(0.6)',opacity:0}],
{duration:600,easing:'ease-out'}
).onfinish=()=>dot.remove();
}
function puffAt(x,y){
const r=arena.getBoundingClientRect();
const rx=Math.max(0,Math.min(r.width,x-r.left));
const ry=Math.max(0,Math.min(r.height,y-r.top));
const ring=document.createElement('div'); ring.className='puff';
ring.style.left=rx+'px'; ring.style.top=ry+'px'; ring.style.transform='translate(-50%,-50%)';
arena.appendChild(ring);
ring.animate(
[{transform:'translate(-50%,-50%) scale(1)',opacity:.6},{transform:'translate(-50%,-50%) scale(2.6)',opacity:0}],
{duration:620,easing:'ease-out'}
).onfinish=()=>ring.remove();
}
function collect(pts,x,y){
const now=performance.now();
feedStreak=(now-lastFeedAt<=STREAK_WINDOW)?(feedStreak+1):1;
lastFeedAt=now;
totalScore+=pts; levelScore+=pts; feeds+=1;
scoreEl.textContent=totalScore; scoreFloat.textContent=totalScore;
localStorage.setItem('bkbg_score',totalScore);
feedsEl.textContent=feeds;
// Co-Play bookkeeping
if(CO_PLAY){
playerScores[playerIdx]+=pts; updatePlayersUI(); feedsSinceSwitch++;
if(feedsSinceSwitch>=TURN_FEEDS){
feedsSinceSwitch=0; playerIdx=1-playerIdx; updatePlayersUI();
turnHint.textContent=t('Switch!','Cambia!'); turnHint.style.display='inline-flex';
setTimeout(()=>turnHint.style.display='none',1200);
if(TURN_TIMER_ON) startTurnTimer();
if(audioOn) chime(500,.07);
}
}
nectarAt(x,y);
if(!calm) popAt(x,y,'+'+pts);
if(audioOn) chime(calm?420:740,.04);
// Garden progress
if(calm){
const pseudoTarget=12; // 3 flowers * 4 stages
updateGarden(Math.min(pseudoTarget, Math.floor(feeds * (12/pseudoTarget))), pseudoTarget);
} else {
updateGarden(levelScore, TARGET);
}
// Gentle confetti milestones
if(fxOn){
if(!firstCelebrate){ firstCelebrate=true; puffConfetti(x,y,14); }
if(feeds===5){ puffConfetti(x,y,18); }
else if(!calm && feeds>5 && (feeds-5)%10===0){ launchConfetti(); }
if(feedStreak===15) launchConfetti();
}
if(!calm){
const p=levelScore/TARGET;
if(p>0.75 && lastStage!=='near'){ cheer('near'); lastStage='near'; }
else if(p>0.4 && lastStage==='start'){ cheer('start'); lastStage='mid'; }
if(levelScore>=TARGET && feeds>=minFeeds(TARGET)) win();
}
if(feeds % 3 === 0) cheer('goodTap');
}
/* ----------------------------
* WIN / BADGE / ART
* ---------------------------- */
function win(){
RUNNING=false; clearInterval(coachTimer);
if(fxOn) launchConfetti();
setTimeout(openBadge, 480);
if(audioOn){ chime(740,.08); setTimeout(()=>chime(880,.08),120); setTimeout(()=>chime(988,.1),260); }
cheer('win');
}
function openBadge(){
const idx=(level-1)%BADGES.length;
badgeImg.src=BADGES[idx];
badgeTitle.textContent=t(`Level ${level} complete!`,`Livello ${level} completato!`);
badgeAffirm.textContent=`${NONNA}: `+t('Your kindness took flight.','La tua gentilezza è volata.');
badgeReflect.textContent=t('Reflect: ','Riflessione: ')+t('What helped you keep going?','Cosa ti ha aiutato a continuare?');
badgeBackdrop.style.display='flex';
}
nextLevelBtn.addEventListener('click',()=>{
badgeBackdrop.style.display='none';
level++; localStorage.setItem('bkbg_level',level); levelEl.textContent=level;
startLevel(true);
});
badgeClose.addEventListener('click',()=>{
badgeBackdrop.style.display='none';
startLevel(true);
});
// Art modal
viewArtBtn.addEventListener('click',()=>{
artImg.src=FULL_ART_URL;
artTitle.textContent=t('Congratulations!','Congratulazioni!');
artLine.textContent=`${NONNA}: `+t('You grew a garden of care.','Hai fatto crescere un giardino di cura.');
artBackdrop.style.display='flex';
makeSparkles();
});
artClose.addEventListener('click',()=>artBackdrop.style.display='none');
artContinue.addEventListener('click',()=>{
artBackdrop.style.display='none';
badgeBackdrop.style.display='none';
level++; localStorage.setItem('bkbg_level',level); levelEl.textContent=level;
startLevel(true);
});
function makeSparkles(){
const box=sparkles; box.innerHTML='';
const W=box.clientWidth||600, H=box.clientHeight||360, N=calm?14:26;
for(let i=0;i
p.remove();
}
}
function puffConfetti(x,y,n=10){
if(!fxOn) return;
const r=arena.getBoundingClientRect();
const rx=Math.max(0,Math.min(r.width,x-r.left));
const ry=Math.max(0,Math.min(r.height,y-r.top));
const colors=[css('--joy'),css('--love'),css('--calm'),css('--gratitude')];
for(let i=0;ip.remove();
}
}
/* ----------------------------
* TOAST & MISC
* ---------------------------- */
function toast(msg){
const d=document.createElement('div'); d.className='toast'; d.textContent=msg;
document.body.appendChild(d);
d.animate(
[{opacity:0,transform:'translate(-50%,-8px)'},{opacity:1,transform:'translate(-50%,0)'},{opacity:1},{opacity:0}],
{duration:1800,easing:'ease-out'}
).onfinish=()=>d.remove();
}
// Phoenix logo halo ping
const brand=$('#bk-brand');
if(brand){
brand.addEventListener('click',()=>{
brand.animate(
[{filter:'drop-shadow(0 0 0 rgba(255,215,0,0))'},{filter:'drop-shadow(0 0 10px rgba(255,215,0,.8))'},{filter:'drop-shadow(0 0 0 rgba(255,215,0,0))'}],
{duration:900,easing:'ease-out'}
);
});
}
/* ----------------------------
* MINDFULNESS — video layout polish
* ---------------------------- */
// Hide image while video plays; restore with a kind line
function playMind(src){
const v=mindVideo;
const img=$('#mindImg');
if(img) img.style.display='none';
v.src=src; v.style.display='block'; v.currentTime=0;
v.muted=(mindMute.getAttribute('aria-pressed')==='true');
v.play().catch(()=>{});
if(!PAUSED) togglePause();
v.onended=()=>{
v.style.display='none';
if(img) img.style.display='block';
$('#mindLine').textContent = `${NONNA}: `+t('Thank you for breathing with me. Notice how your body feels.','Grazie per aver respirato con me. Nota come si sente il tuo corpo.');
};
}
if($('#mindPlayMusic')) $('#mindPlayMusic').addEventListener('click',()=>playMind(MEDITATE_MP4_MUSIC));
if($('#mindPlaySilent')) $('#mindPlaySilent').addEventListener('click',()=>playMind(MEDITATE_MP4_SILENT));
if($('#mindMute')) $('#mindMute').addEventListener('click',()=>{
const on=!(mindMute.getAttribute('aria-pressed')==='true');
mindMute.setAttribute('aria-pressed',String(on));
mindMute.textContent = on? '🔇 Mute: On' : '🔊 Mute: Off';
if(mindVideo) mindVideo.muted=on;
});
/* ----------------------------
* AMBIENT CHIME LOOP (muted by default)
* ---------------------------- */
if(typeof CHIME_ON==='undefined') var CHIME_ON=false;
let chimeTick=null;
function startChimeLoop(){
stopChimeLoop();
if(!CHIME_ON) return;
// very gentle pulses; respect Calm by spacing a bit wider
chimeTick=setInterval(()=>{
if(audioOn && !PAUSED) chime(calm?420:520, .06);
}, calm? 2600 : 2000);
}
function stopChimeLoop(){ if(chimeTick){ clearInterval(chimeTick); chimeTick=null; } }
// If the UI has a Chime toggle, wire it up here
const chimeToggle=$('#chimeToggle');
if(chimeToggle){
chimeToggle.addEventListener('click',()=>{
CHIME_ON=!CHIME_ON;
chimeToggle.setAttribute('aria-pressed',String(CHIME_ON));
chimeToggle.textContent = CHIME_ON ? '🔔 Chime: On' : '🔕 Chime: Off';
if(CHIME_ON) startChimeLoop(); else stopChimeLoop();
});
}
/* ----------------------------
* THANKS MODAL
* ---------------------------- */
thanksClose.addEventListener('click',()=>{ thanksBackdrop.style.display='none'; });
thanksRestart.addEventListener('click',()=>{ thanksBackdrop.style.display='none'; startLevel(true); });
/* ----------------------------
* BOOT
* ---------------------------- */
scoreEl.textContent=totalScore;
scoreFloat.textContent=totalScore;
levelEl.textContent=level;
coachImg.alt=NONNA;
showCoach(`${NONNA}: `+t('Welcome! Choose Calm if you like, then press Start.','Benvenuti! Scegli Calma se vuoi, poi premi Start.'));
updateUI();
startChimeLoop(); // will do nothing unless CHIME_ON is true
})();