TL;DR: great morning, cursed afternoon. fixed story mode, nuked a global layout, accidentally rolled my repo back a week, recovered most of it via notes + memory, chased undead red ants across modes, beat mobile text-selection loupes into submission, and shipped a playable Kids Mode. keep it simple. keep going.
👉 Play it: https://jpsgrooves.github.io/SnowCone-MathFest/
The Day (aka: why are there ants here?)
It started smooth. I finally had time, so I went after Story Mode. Two hours of careful, methodical work and it looked good. I checked on mobile and… uh oh: a global background PNG push-down across all modes. 🤦♂️
I know why it happened: historically I’ve kept layout changes in CSS and scoped them to modes. But “new Patch” (my AI pair) suggested some JS-driven layout nudges, and I tried them. It worked—until it leaked. I couldn’t Ctrl-Z my way back to a clean state.
Fix: isolate the pushdown to Camping Games, then purge it globally. Pushed to GH Pages. Looked great on phone. I fist-pumped.
Then I tried to push to GitHub remote.
It didn’t go.
I asked Patch for help. I don’t know which command did it (lesson incoming), but my whole src/ flickered and—boom—I pulled the remote (6 days old) over my local (today’s work). A week vanished in one keystroke. That sinking feeling? yeah.
Panic. Then process.
- I recovered public assets easily.
- src code was back a week. Brutal.
- I rebuilt from dev notes, memory, and old chats. Two more hours. Not perfect, but close.
New Rule: never bash a git command you don’t understand. Ask better questions first.
And then… the ants
Console showed red ants still spawning after leaving Kids Mode. Another two hours. They were like a horror movie post-credits scene.
In the end, what worked was a combination of singleton runtime state, a hard kill function, and DOM guards:
// one global runtime per page
const ANT = (globalThis.__KC_ANT__ ||= { session: 0, alive: false, root: null });
// container safety
function aliveGuard(container) {
return ANT.alive && ANT.root === container && document.body.contains(container);
}
// kill EVERYTHING (timeouts, tweens, observers) and invalidate pending timeouts
export function forceKillAntAttack() {
try { gsap.killTweensOf(activeAnts); } catch {}
try { foodTween?.kill?.(); } catch {}
try { redAntTimeouts.forEach(clearTimeout); } catch {}
redAntTimeouts = [];
activeAnts.length = 0;
roundInProgress = false;
ANT.session++; // ⬅️ breaks any scheduled callbacks from the old session
ANT.alive = false;
ANT.root = null;
}
Plus a MutationObserver that watches the game container and calls forceKillAntAttack() if the container leaves the DOM. That finally stopped the cross-mode spawns.
Mobile: the blue highlight + magnifying loupe
Tiny testers found a delightful iOS thing: tap, tap-hold → the whole screen highlights, with the little magnifying glass. It broke the vibe completely.
Fix (global, app-wide):
- Disable selection and callout on the interactive frame.
- Use
touch-action: manipulationto squash double-tap zoom. - Keep an opt-in class for any text that should be selectable.
/* default lockdown for game UI */
.kc-game-frame, .kc-game-frame * {
-webkit-user-select: none;
user-select: none;
-webkit-touch-callout: none;
-webkit-tap-highlight-color: transparent;
touch-action: manipulation;
}
/* opt-in if you need selectable text */
.allow-select {
-webkit-user-select: text;
user-select: text;
-webkit-touch-callout: default;
}
Viewport stayed simple and correct:
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover">
For height, CSS wins: height: 100svh; with fallbacks (100vh, 100dvh) covers the weirdness across browsers.
After that: Kids Mode is actually playable. 🙌
Patch’s Service Protocol (updated mid-chaos)
I literally wrote this during the fire:
- Model Transparency
- Always say “I am GPT-5 Thinking.”
- State confidence level.
- Admit uncertainty/hallucinations.
- File Respect
- Review uploads carefully.
- Confirm what’s in the file.
- Treat uploads as older dev notes unless told otherwise; ask for latest.
- Scope Discipline
- Answer exactly what was asked.
- Extra ideas are clearly labeled “optional.”
- Coding Style
- Stoner, time-traveling SnowCone Server voice 🌌😎🍧.
- Explain why, not just how.
- Never skip or summarize code due to length; ship in chunks.
- Git / System Safety
- No destructive commands without repo context.
- Start with safe introspection:
git status git log --oneline --decorate --graph -n 15 git branch -vv git reflog -n 20 - Propose the safest plan first.
- Project Integrity
- Favor long-term stability over hacks.
- Preserve Jeremy’s voice and joy. 🚀
Postmortem Notes & Snippets You Can Steal
1) “Undead loop” pattern: kill by invalidating session
If your game/animation uses timeouts or async callbacks, store a session id. On teardown, increment it. Any scheduled callback checks session === ANT.session before running. Instant amnesia for old loops.
2) Cross-mode safety: observe your container
If the mode’s root leaves the DOM, self-destruct. It’s cheap and it works.
const mo = new MutationObserver(() => {
if (ANT.root && !document.body.contains(ANT.root)) forceKillAntAttack();
});
mo.observe(document.body, { childList: true, subtree: true });
3) Mobile polish: don’t fight the browser, set the rules
user-select: none; -webkit-touch-callout: none;touch-action: manipulation;- Minimal, sane viewport meta.
- Use
svh/dvh+vhfallback for height.
4) Git recovery (safe path)
When you nuke local changes by mistake:
- Look first:
git status,git reflog -n 50 - Peek at old head(s):
git show HEAD@{1}(and friends) - Recover files without resets:
git restore --source=HEAD@{1} -- path/to/file.js - Only reach for hard resets if you absolutely understand the consequences.
What I’d Tell Yesterday-Me
- Keep your layout changes mode-scoped. If you mix CSS and JS layout moves, document where and why.
- Never run a git command you can’t explain out loud.
- Write tiny teardown functions first. Make “quit” reliable before “play” is fancy.
- When kids are your QA, assume every tap pattern will be discovered. Optimize for chaos.
The bright part
Story Mode is shaping up. Last night I felt lost in the woods; tonight I feel exhausted, like I spent the day chopping a path. The forest of the unknown is dense. My axe isn’t always sharp. But persistence? That’s the whole game.
Go play my math game. Tell me what breaks so I can fix it faster next time. 💚
👉 https://jpsgrooves.github.io/SnowCone-MathFest/
—J






Leave a comment