Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save VarunBatraIT/216a7d13b8f0a56b8aa86801483d9e2b to your computer and use it in GitHub Desktop.

Select an option

Save VarunBatraIT/216a7d13b8f0a56b8aa86801483d9e2b to your computer and use it in GitHub Desktop.
superhero-lichess
// ==UserScript==
// @name Lichess Game Play for Kids - Chess Superhero Academy ⚡
// @namespace vm-lichess-game-play-kids-3
// @version 1.0
// @description Your child is a superhero-in-training! Activate superpowers, fill the energy bar, and transform into a super hero before making each move. Choose Captain Checkmate, Wonder Knight, Pawn Power, or Bishop Wizard.
// @match https://lichess.org/*
// @run-at document-start
// @grant none
// ==/UserScript==
"use strict";
(() => {
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
// src/shared/utils.ts
function randomItem(array) {
return array[Math.floor(Math.random() * array.length)];
}
__name(randomItem, "randomItem");
// src/shared/kids-font-config.ts
var KIDS_FONT_FAMILY = "'Nunito', 'Segoe UI', 'Verdana', sans-serif";
var BASE = {
characterEmoji: 48,
speechBubble: 15,
title: 18,
subtitle: 14,
tip: 14,
timer: 20,
button: 14,
smallLabel: 12,
sectionEmoji: 28,
pickerTitle: 24,
pickerEmoji: 38,
pickerName: 14,
pickerSubtext: 12
};
function computeScale() {
const vh = window.innerHeight || 900;
return Math.max(0.7, Math.min(1.15, vh / 900));
}
__name(computeScale, "computeScale");
var _cache = null;
var _cacheVh = 0;
function getKidsFontSizes() {
const vh = window.innerHeight || 900;
if (_cache && _cacheVh === vh)
return _cache;
const s = computeScale();
const px = /* @__PURE__ */ __name((b) => `${Math.round(b * s)}px`, "px");
_cache = {
characterEmoji: px(BASE.characterEmoji),
speechBubble: px(BASE.speechBubble),
title: px(BASE.title),
subtitle: px(BASE.subtitle),
tip: px(BASE.tip),
timer: px(BASE.timer),
button: px(BASE.button),
smallLabel: px(BASE.smallLabel),
sectionEmoji: px(BASE.sectionEmoji),
pickerTitle: px(BASE.pickerTitle),
pickerEmoji: px(BASE.pickerEmoji),
pickerName: px(BASE.pickerName),
pickerSubtext: px(BASE.pickerSubtext)
};
_cacheVh = vh;
return _cache;
}
__name(getKidsFontSizes, "getKidsFontSizes");
function injectKidsFont(prefix) {
const id = `${prefix}-font-link`;
if (document.getElementById(id))
return;
const link = document.createElement("link");
link.id = id;
link.rel = "stylesheet";
link.href = "https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800;900&display=swap";
document.head.appendChild(link);
}
__name(injectKidsFont, "injectKidsFont");
function getKidsSpeechBubbleCSS(prefix) {
return `
/* Zero-height wrapper keeps bubble out of layout flow */
.${prefix}-bubble-wrapper {
position: relative;
width: 100%;
height: 0;
overflow: visible;
z-index: 50;
}
.${prefix}-comic-bubble {
position: absolute;
top: 2px;
left: 0;
right: 0;
background: rgba(15, 23, 42, 0.95);
border: 2px solid rgba(255, 255, 255, 0.25);
border-radius: 14px;
padding: 8px 12px;
backdrop-filter: blur(10px);
box-shadow: 0 4px 20px rgba(0,0,0,0.5);
opacity: 0;
transform: translateY(-4px) scale(0.96);
transition: opacity 0.25s ease, transform 0.25s ease;
pointer-events: none;
}
.${prefix}-comic-bubble.visible {
opacity: 1;
transform: translateY(0) scale(1);
pointer-events: auto;
}
.${prefix}-comic-bubble::before {
content: '';
position: absolute;
top: -10px;
left: 28px;
width: 0; height: 0;
border-left: 8px solid transparent;
border-right: 8px solid transparent;
border-bottom: 10px solid rgba(255, 255, 255, 0.25);
}
.${prefix}-comic-bubble::after {
content: '';
position: absolute;
top: -8px;
left: 29px;
width: 0; height: 0;
border-left: 7px solid transparent;
border-right: 7px solid transparent;
border-bottom: 8px solid rgba(15, 23, 42, 0.95);
}
`;
}
__name(getKidsSpeechBubbleCSS, "getKidsSpeechBubbleCSS");
// src/game-play-for-kids-3/config.ts
var HERO_CHARACTERS = [
{
id: "captain",
name: "Captain Checkmate",
emoji: "\u{1F9B8}",
transformedEmoji: "\u{1F9B8}\u200D\u2642\uFE0F\u26A1",
color: "#dc2626",
bgGradient: "linear-gradient(135deg, #1a0000 0%, #2d0a0a 50%, #4a1111 100%)",
superpower: "Tactical Vision",
battleCries: [
"HERO TIME! Let's protect the board! \u{1F9B8}",
"Captain Checkmate reporting for duty! \u2B50",
"Time to use our superpowers! \u{1F4AA}",
"With great pawns comes great responsibility! \u{1F3AF}"
],
powerUpLines: [
"POWER ACTIVATED! You're getting stronger! \u26A1",
"Energy rising! Keep going, hero! \u{1F50B}",
"Another power unlocked! AMAZING! \u{1F4AB}",
"Your hero energy is building! \u{1F31F}"
],
transformLines: [
"\u{1F31F} FULL POWER! You're UNSTOPPABLE! \u{1F31F}",
"\u26A1 SUPER CHESS HERO MODE ACTIVATED! \u26A1",
"\u{1F4A5} ALL POWERS READY! Make your SUPER MOVE! \u{1F4A5}",
"\u{1F3C6} HERO TRANSFORMATION COMPLETE! GO! \u{1F3C6}"
],
defeatLines: [
"Even heroes have setbacks! We'll rise again! \u{1F4AA}",
"A true hero never gives up! Let's go! \u{1F9B8}",
"Recharging... heroes always come back stronger! \u26A1",
"That's OK! Every hero has an origin story! \u{1F4D6}"
],
quickMoveWarnings: [
"WAIT! A hero always scans for danger first! \u{1F6E1}\uFE0F",
"HOLD ON! Use your superpowers before moving! \u26A1",
"Heroes don't rush! Activate your powers first! \u{1F9B8}",
"Careful! Check your hero checklist first! \u{1F4CB}"
]
},
{
id: "knight",
name: "Wonder Knight",
emoji: "\u{1F434}",
transformedEmoji: "\u{1F434}\u{1F451}",
color: "#7c3aed",
bgGradient: "linear-gradient(135deg, #0f0024 0%, #1a0a3e 50%, #2d1b69 100%)",
superpower: "Jump Vision",
battleCries: [
"NEIGH! Wonder Knight gallops into action! \u{1F434}",
"Time to jump into the battle! \u265E",
"My knight senses are tingling! \u{1F31F}",
"Let's leap to victory! \u{1F49C}"
],
powerUpLines: [
"LEAP POWER growing! Amazing! \u{1F434}\u26A1",
"Your knight energy is rising! \u265E\u{1F4AB}",
"Another power! You're becoming unstoppable! \u{1F31F}",
"Wonder Knight is getting STRONGER! \u{1F4AA}"
],
transformLines: [
"\u{1F31F} FULL KNIGHT POWER! L-SHAPED DOMINATION! \u{1F31F}",
"\u26A1 WONDER KNIGHT ULTIMATE FORM! \u26A1",
"\u{1F4A5} ALL POWERS READY! GALLOP TO VICTORY! \u{1F4A5}",
"\u{1F3C6} KNIGHT CHAMPION MODE! Make your move! \u{1F3C6}"
],
defeatLines: [
"Even knights stumble sometimes! Mount up again! \u{1F434}",
"A true knight never surrenders! \u{1F49C}",
"Recharging horse power... back in action! \u26A1",
"Knights always find another path! Keep going! \u265E"
],
quickMoveWarnings: [
"WHOA! A knight looks before leaping! \u{1F434}",
"HALT! Activate your powers first, knight! \u26A1",
"Wait! Even Wonder Knight checks the board! \u{1F6E1}\uFE0F",
"Don't gallop too fast! Use your vision first! \u{1F440}"
]
},
{
id: "pawn",
name: "Pawn Power",
emoji: "\u265F\uFE0F",
transformedEmoji: "\u265F\uFE0F\u{1F478}",
color: "#16a34a",
bgGradient: "linear-gradient(135deg, #001a0a 0%, #0a2e1a 50%, #144d2e 100%)",
superpower: "Promotion Dream",
battleCries: [
"Small but MIGHTY! Pawn Power is here! \u265F\uFE0F",
"Every champion starts as a pawn! Let's go! \u{1F331}",
"I may be small but I dream BIG! \u{1F451}",
"Pawn Power ACTIVATE! \u{1F49A}"
],
powerUpLines: [
"Growing stronger! One step at a time! \u265F\uFE0F\u26A1",
"Pawn Power increasing! You're amazing! \u{1F49A}",
"Another power! Getting closer to promotion! \u{1F451}",
"Your pawn energy is GLOWING! \u{1F31F}"
],
transformLines: [
"\u{1F31F} FULL PAWN POWER! PROMOTION TIME! \u{1F451}",
"\u26A1 PAWN HERO ULTIMATE FORM! YOU'RE A QUEEN! \u26A1",
"\u{1F4A5} ALL POWERS READY! Make your CHAMPION move! \u{1F4A5}",
"\u{1F3C6} FROM PAWN TO QUEEN! UNSTOPPABLE! \u{1F3C6}"
],
defeatLines: [
"Even pawns step back to step forward! \u265F\uFE0F",
"Remember: pawns become QUEENS! Keep going! \u{1F451}",
"Small setback, BIG comeback! \u{1F49A}",
"A pawn's journey is never easy, but always worth it! \u{1F31F}"
],
quickMoveWarnings: [
"WAIT! Even brave pawns look before advancing! \u265F\uFE0F",
"HOLD! Use your powers first, little hero! \u26A1",
"Careful! Check the path ahead! \u{1F440}",
"Pawns move carefully! Scan first! \u{1F6E1}\uFE0F"
]
},
{
id: "wizard",
name: "Bishop Wizard",
emoji: "\u{1F9D9}",
transformedEmoji: "\u{1F9D9}\u2728",
color: "#0ea5e9",
bgGradient: "linear-gradient(135deg, #000a1a 0%, #0a1e3d 50%, #0d2b52 100%)",
superpower: "Diagonal Magic",
battleCries: [
"ABRACACHESS! The Wizard enters the game! \u{1F9D9}",
"My crystal ball shows the way! \u{1F52E}",
"Time for some diagonal MAGIC! \u2728",
"The chess wizard casts a spell of thinking! \u{1F31F}"
],
powerUpLines: [
"MAGICAL power growing! Fantastic! \u{1F9D9}\u26A1",
"Your wizard energy sparkles! \u2728",
"Another spell learned! You're brilliant! \u{1F52E}",
"The magic is getting STRONGER! \u{1F4AB}"
],
transformLines: [
"\u{1F31F} FULL WIZARD POWER! ULTIMATE MAGIC! \u{1F31F}",
"\u26A1 ARCH-WIZARD MODE! DIAGONAL MASTERY! \u26A1",
"\u{1F4A5} ALL SPELLS READY! Cast your BEST move! \u{1F4A5}",
"\u{1F3C6} GRAND WIZARD! The board bows to you! \u{1F3C6}"
],
defeatLines: [
"Even wizards miscast sometimes! Try again! \u{1F9D9}",
"The magic will return! Never give up! \u2728",
"Recharging mana... wizards are resilient! \u{1F52E}",
"A true wizard learns from every spell! \u{1F4DA}"
],
quickMoveWarnings: [
"WAIT! A wizard always checks the omens first! \u{1F9D9}",
"HOLD! Cast your scanning spells first! \u{1F52E}",
"Don't rush the magic! Think first! \u2728",
"Wise wizards are patient wizards! \u{1F31F}"
]
}
];
var STORAGE_KEY = "vm-game-play-kids-3-hero";
var SUPERPOWERS = [
{
id: "danger_sense",
name: "Spot Immediate Threats",
emoji: "\u{1F6E1}\uFE0F",
description: "Scan for threats & undefended material!",
heroShout: "DANGER SENSE ACTIVATED! Can any enemy piece capture yours? SCAN for undefended material! \u{1F6E1}\uFE0F",
color: "#ef4444",
energyCost: 1,
timer: 10
},
{
id: "guardian_shield",
name: "Find Hanging Pieces",
emoji: "\u{1F530}",
description: "Check if all your pieces have defenders!",
heroShout: "SHIELD UP! Find hanging pieces with NO protection! Every piece needs a defender! \u{1F530}",
color: "#f97316",
energyCost: 1,
timer: 10
},
{
id: "royal_guard",
name: "King's Safety & Check Angles",
emoji: "\u{1F451}",
description: "Is your King safe? Can you check theirs?",
heroShout: "ROYAL GUARD POWER! Is your King safe? Look for check angles on THEIR King! \u{1F451}",
color: "#eab308",
energyCost: 2,
timer: 10
},
{
id: "fork_fury",
name: "Forks (Double Attack)",
emoji: "\u2694\uFE0F",
description: "Find a move that attacks TWO pieces at once!",
heroShout: "FORK FURY! Can any of your pieces attack TWO enemies at once? That's a FORK \u2014 DOUBLE DAMAGE! \u2694\uFE0F",
color: "#22c55e",
energyCost: 2,
timer: 12
},
{
id: "xray_vision",
name: "Pins & Skewers",
emoji: "\u{1F441}\uFE0F",
description: "See through pieces! Find pins and skewers!",
heroShout: "X-RAY VISION ON! Look THROUGH pieces! Find PINS (piece stuck guarding) and SKEWERS (attack in a line)! \u{1F441}\uFE0F",
color: "#06b6d4",
energyCost: 2,
timer: 12
},
{
id: "safe_landing",
name: "Safe Square Check",
emoji: "\u{1F3E0}",
description: "Make sure your landing zone is safe!",
heroShout: "SAFE LANDING CHECK! Where will your piece land? Is that square SAFE from enemy fire? Check! \u{1F3E0}",
color: "#8b5cf6",
energyCost: 1,
timer: 10
},
{
id: "future_sight",
name: "Opponent's Plan (Prophylaxis)",
emoji: "\u{1F52E}",
description: "Predict what your opponent will do next!",
heroShout: "FUTURE SIGHT! If you move there, what will THEY do? This is called PROPHYLAXIS \u2014 seeing the FUTURE! \u{1F52E}",
color: "#ec4899",
energyCost: 3,
timer: 12
},
{
id: "ultimate_move",
name: "Best Move (Checks, Captures, Threats)",
emoji: "\u{1F4A5}",
description: "Choose your BEST and STRONGEST move!",
heroShout: "ULTIMATE MOVE TIME! Think: Checks first, then Captures, then Threats! Pick the STRONGEST! GO! \u{1F4A5}",
color: "#f59e0b",
energyCost: 3,
timer: 14
}
];
var HERO_TIPS = [
"\u{1F9B8} Always scan for Immediate Threats BEFORE acting!",
"\u26A1 Use ALL your powers before making a move!",
"\u{1F6E1}\uFE0F Protect your pieces! Don't leave Hanging Pieces!",
"\u{1F451} King's Safety is #1! Always keep the King safe!",
"\u2694\uFE0F Forks (Double Attacks) are a hero's best weapon!",
"\u{1F441}\uFE0F Look for Pins & Skewers \u2014 X-Ray power!",
"\u{1F3E0} Safe Square: always check the landing zone!",
"\u{1F52E} Prophylaxis: predict your opponent's next move!",
"\u{1F4AA} Heroes are PATIENT! Think before you act!",
"\u{1F3AF} Control the CENTER \u2014 Open Files & Ranks!",
"\u{1F434} Knights love Outposts! They jump over walls!",
"\u{1F3F0} Castle early \u2014 build your FORTRESS!",
"\u{1F4D0} Bishops love Long Diagonals for attack lines!",
"\u{1F5FC} Rooks need Open Files to be powerful!",
"\u{1F91D} Coordinate your pieces! Teamwork = power!",
"\u26A0\uFE0F Count attackers vs defenders before capturing!",
"\u{1F9E0} Checks, Captures, Threats \u2014 hero scanning order!",
"\u{1F4A1} A Passed Pawn dreams of becoming a Queen!"
];
var ENERGY_LEVELS = [
{ percent: 0, label: "No Power", color: "#475569", emoji: "\u{1F50B}" },
{ percent: 20, label: "Warming Up", color: "#ef4444", emoji: "\u{1F534}" },
{ percent: 40, label: "Getting Strong", color: "#f97316", emoji: "\u{1F7E0}" },
{ percent: 60, label: "Power Rising!", color: "#eab308", emoji: "\u{1F7E1}" },
{ percent: 80, label: "Almost Ready!", color: "#22c55e", emoji: "\u{1F7E2}" },
{ percent: 100, label: "FULL POWER!", color: "#8b5cf6", emoji: "\u26A1" }
];
function getEnergyLevel(percent) {
let result = ENERGY_LEVELS[0];
for (const level of ENERGY_LEVELS) {
if (percent >= level.percent)
result = level;
}
return result;
}
__name(getEnergyLevel, "getEnergyLevel");
var TIMER_QUOTES_HERO = [
"Heroes take their time! Think carefully! \u{1F9B8}",
"With great power comes great thinking! \u{1F9E0}",
"A hero's best weapon is patience! \u23F0",
"Power up your brain before your move! \u26A1",
"Scan the board like a true hero! \u{1F440}",
"Heroes don't rush into danger! \u{1F6E1}\uFE0F",
"Take a deep breath and focus your powers! \u{1F4AB}",
"Every great hero thinks before they act! \u{1F31F}"
];
var _sizeMap = {
heroEmoji: "characterEmoji",
speechBubble: "speechBubble",
powerName: "title",
powerDescription: "subtitle",
tip: "tip",
timer: "timer",
button: "button",
energyLabel: "smallLabel"
};
var FONT_SIZES = new Proxy({}, {
get(_, key) {
const mapped = _sizeMap[key];
return mapped ? getKidsFontSizes()[mapped] : "";
}
});
var FONT_FAMILY = KIDS_FONT_FAMILY;
var TIMING = {
powerAutoSeconds: 10,
tipAutoSeconds: 8,
speechDuration: 4e3,
transformDuration: 3e3
};
// src/game-play-for-kids-3/state.ts
var _HeroState = class _HeroState {
constructor() {
// Character
this.selectedHero = HERO_CHARACTERS[0];
this.characterPickerShown = false;
// Power state
this.currentPower = 0;
this.powerTimerInterval = null;
this.powerTimeRemaining = 0;
this.powersActivated = 0;
this.energyPercent = 0;
// Tip state
this.currentTip = 0;
this.tipInterval = null;
this.tipSecondsLeft = TIMING.tipAutoSeconds;
// Timer state
this.timerInterval = null;
this.timerElapsed = 0;
// Move tracking
this.lastActiveMove = "";
// Speech
this.speechTimeout = null;
// Stats
this.totalTransformations = 0;
this.totalPowersUsed = 0;
}
loadHero() {
try {
const saved = localStorage.getItem(STORAGE_KEY);
if (saved) {
const data = JSON.parse(saved);
const hero = HERO_CHARACTERS.find((h) => h.id === data.id);
if (hero) {
this.selectedHero = hero;
this.characterPickerShown = true;
this.totalTransformations = data.transforms || 0;
this.totalPowersUsed = data.powers || 0;
}
}
} catch {
}
}
saveHero(heroId) {
try {
const hero = HERO_CHARACTERS.find((h) => h.id === heroId);
if (hero) {
this.selectedHero = hero;
this.characterPickerShown = true;
}
this.persistStats();
} catch {
}
}
persistStats() {
try {
localStorage.setItem(
STORAGE_KEY,
JSON.stringify({
id: this.selectedHero.id,
transforms: this.totalTransformations,
powers: this.totalPowersUsed
})
);
} catch {
}
}
getRandomQuote() {
return randomItem(TIMER_QUOTES_HERO);
}
getBattleCry() {
return randomItem(this.selectedHero.battleCries);
}
getPowerUpLine() {
return randomItem(this.selectedHero.powerUpLines);
}
getTransformLine() {
return randomItem(this.selectedHero.transformLines);
}
getDefeatLine() {
return randomItem(this.selectedHero.defeatLines);
}
getQuickMoveWarning() {
return randomItem(this.selectedHero.quickMoveWarnings);
}
nextPower() {
this.currentPower++;
if (this.currentPower >= SUPERPOWERS.length) {
this.currentPower = SUPERPOWERS.length;
}
}
prevPower() {
if (this.currentPower > 0) {
this.currentPower--;
}
}
nextTip() {
this.currentTip = (this.currentTip + 1) % HERO_TIPS.length;
}
prevTip() {
this.currentTip = (this.currentTip - 1 + HERO_TIPS.length) % HERO_TIPS.length;
}
resetPowers() {
this.currentPower = 0;
this.powerTimeRemaining = 0;
this.powersActivated = 0;
this.energyPercent = 0;
}
activatePower() {
this.powersActivated++;
this.totalPowersUsed++;
this.energyPercent = Math.min(
100,
Math.round(this.powersActivated / SUPERPOWERS.length * 100)
);
}
isFullyPowered() {
return this.powersActivated >= SUPERPOWERS.length;
}
resetTimer() {
this.timerElapsed = 0;
}
resetTipTimer() {
this.tipSecondsLeft = TIMING.tipAutoSeconds;
}
};
__name(_HeroState, "HeroState");
var HeroState = _HeroState;
var state = new HeroState();
// src/game-play-for-kids-3/timers.ts
function showHeroSpeech(msg) {
const speechEl = document.getElementById("vmk3-hero-speech");
if (speechEl) {
speechEl.textContent = `${state.selectedHero.emoji} ${msg}`;
speechEl.classList.add("visible");
if (state.speechTimeout)
clearTimeout(state.speechTimeout);
state.speechTimeout = setTimeout(() => {
speechEl.classList.remove("visible");
}, TIMING.speechDuration);
}
}
__name(showHeroSpeech, "showHeroSpeech");
function startTimer(tDiv) {
if (state.timerInterval)
clearInterval(state.timerInterval);
state.timerElapsed = 0;
tDiv.textContent = "\u26A1 0s";
tDiv.style.color = "#ef4444";
state.timerInterval = setInterval(() => {
state.timerElapsed++;
tDiv.textContent = `\u26A1 ${state.timerElapsed}s`;
if (state.timerElapsed < 5) {
tDiv.style.color = "#ef4444";
} else if (state.timerElapsed < 10) {
tDiv.style.color = "#fde047";
} else {
tDiv.style.color = "#10b981";
}
if (state.timerElapsed === 10) {
showHeroSpeech("Your hero brain is CHARGING! Keep thinking! \u{1F9E0}\u26A1");
} else if (state.timerElapsed === 20) {
showHeroSpeech("INCREDIBLE focus! A true hero! \u{1F9B8}\u{1F31F}");
}
}, 1e3);
}
__name(startTimer, "startTimer");
function startPowerTimer() {
if (state.powerTimerInterval)
clearInterval(state.powerTimerInterval);
const power = SUPERPOWERS[state.currentPower];
if (!power)
return;
state.powerTimeRemaining = power.timer;
showHeroSpeech(power.heroShout);
const activateBtn = document.getElementById("vmk3-activate-btn");
if (activateBtn) {
activateBtn.textContent = `Power Up! \u26A1 (${state.powerTimeRemaining}s)`;
}
state.powerTimerInterval = setInterval(() => {
state.powerTimeRemaining--;
if (activateBtn) {
activateBtn.textContent = `Power Up! \u26A1 (${state.powerTimeRemaining}s)`;
}
if (state.powerTimeRemaining <= 0) {
clearInterval(state.powerTimerInterval);
state.powerTimerInterval = null;
state.activatePower();
state.currentPower++;
updateEnergyBar();
if (state.currentPower >= SUPERPOWERS.length) {
showTransformation();
} else {
updatePowerDisplay();
startPowerTimer();
}
}
}, 1e3);
}
__name(startPowerTimer, "startPowerTimer");
function stopPowerTimer() {
if (state.powerTimerInterval) {
clearInterval(state.powerTimerInterval);
state.powerTimerInterval = null;
}
}
__name(stopPowerTimer, "stopPowerTimer");
function showTransformation() {
state.totalTransformations++;
state.persistStats();
const powerText = document.getElementById("vmk3-power-text");
const activateBtn = document.getElementById("vmk3-activate-btn");
const hero = state.selectedHero;
if (powerText) {
powerText.innerHTML = `<div style="text-align:center;">
<div style="font-size:44px; margin-bottom:6px; animation: vmk3-transform 1s ease-out;">
${hero.transformedEmoji}
</div>
<div style="font-size:22px; color:#fef3c7; font-weight:800; text-shadow:2px 2px 4px rgba(0,0,0,0.5);">
FULL POWER!
</div>
<div style="font-size:16px; color:#86efac; margin-top:4px; font-weight:700;">
Make your SUPER MOVE! \u{1F4A5}
</div>
<div style="font-size:13px; color:#94a3b8; margin-top:6px; font-weight:600;">
Transformations: ${state.totalTransformations} \u26A1
</div>
</div>`;
}
if (activateBtn)
activateBtn.style.display = "none";
stopPowerTimer();
showHeroSpeech(state.getTransformLine());
const heroEmoji = document.querySelector(
"#vmk3-custom-sidebar .vmk3-hero-hover"
);
if (heroEmoji) {
heroEmoji.textContent = hero.transformedEmoji;
heroEmoji.style.animation = "vmk3-transform 1s ease-out, vmk3-hero-glow 2s ease-in-out infinite";
}
}
__name(showTransformation, "showTransformation");
function updatePowerDisplay() {
const power = SUPERPOWERS[state.currentPower];
if (!power)
return;
const powerText = document.getElementById("vmk3-power-text");
if (powerText) {
const energyDots = "\u26A1".repeat(power.energyCost) + "\u25CB".repeat(3 - power.energyCost);
powerText.innerHTML = `
<div style="font-size:30px; margin-bottom:4px;">${power.emoji}</div>
<div style="font-size:${FONT_SIZES.powerName}; font-weight:800; color:${power.color}; text-shadow:1px 1px 3px rgba(0,0,0,0.5);">
${power.name}
</div>
<div style="font-size:${FONT_SIZES.powerDescription}; color:#cbd5e1; margin-top:4px; font-weight:600; line-height:1.4;">${power.description}</div>
<div style="font-size:12px; color:#64748b; margin-top:4px; font-weight:600;">Energy: ${energyDots}</div>
`;
}
const powerNumEl = document.getElementById("vmk3-power-number");
if (powerNumEl) {
powerNumEl.textContent = `Power ${state.currentPower + 1}/${SUPERPOWERS.length}`;
}
const backBtn = document.getElementById("vmk3-back-btn");
if (backBtn) {
backBtn.style.visibility = state.currentPower === 0 ? "hidden" : "visible";
}
}
__name(updatePowerDisplay, "updatePowerDisplay");
function updateEnergyBar() {
const energyFill = document.getElementById("vmk3-energy-fill");
const energyLabel = document.getElementById("vmk3-energy-label");
if (energyFill) {
energyFill.style.width = `${state.energyPercent}%`;
const level = getEnergyLevel(state.energyPercent);
energyFill.style.background = `linear-gradient(90deg, ${level.color}, ${level.color}aa)`;
}
if (energyLabel) {
const level = getEnergyLevel(state.energyPercent);
energyLabel.textContent = `${level.emoji} ${state.energyPercent}% - ${level.label}`;
energyLabel.style.color = level.color;
}
}
__name(updateEnergyBar, "updateEnergyBar");
function startTipAutoAdvance() {
if (state.tipInterval)
clearInterval(state.tipInterval);
state.tipSecondsLeft = TIMING.tipAutoSeconds;
const tipTextEl = document.getElementById("vmk3-tip-text");
const nextBtn = document.getElementById("vmk3-tip-next-btn");
if (nextBtn) {
nextBtn.textContent = `Next (${state.tipSecondsLeft}s) \u2192`;
}
state.tipInterval = setInterval(() => {
state.tipSecondsLeft--;
if (nextBtn) {
nextBtn.textContent = `Next (${state.tipSecondsLeft}s) \u2192`;
}
if (state.tipSecondsLeft <= 0) {
state.currentTip = (state.currentTip + 1) % HERO_TIPS.length;
if (tipTextEl) {
tipTextEl.textContent = HERO_TIPS[state.currentTip];
}
state.tipSecondsLeft = TIMING.tipAutoSeconds;
if (nextBtn) {
nextBtn.textContent = `Next (${state.tipSecondsLeft}s) \u2192`;
}
}
}, 1e3);
}
__name(startTipAutoAdvance, "startTipAutoAdvance");
// src/game-play-for-kids-3/ui.ts
function injectStyles() {
if (document.getElementById("vmk3-styles"))
return;
injectKidsFont("vmk3");
const style = document.createElement("style");
style.id = "vmk3-styles";
style.textContent = `
${getKidsSpeechBubbleCSS("vmk3")}
@keyframes vmk3-hero-float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-6px); }
}
@keyframes vmk3-transform {
0% { transform: scale(0.3) rotate(-180deg); opacity: 0; }
50% { transform: scale(1.3) rotate(10deg); opacity: 1; }
100% { transform: scale(1) rotate(0deg); opacity: 1; }
}
@keyframes vmk3-hero-glow {
0%, 100% { filter: drop-shadow(0 0 5px rgba(255,215,0,0.3)); }
50% { filter: drop-shadow(0 0 15px rgba(255,215,0,0.8)); }
}
@keyframes vmk3-energy-pulse {
0%, 100% { box-shadow: 0 0 5px rgba(139, 92, 246, 0.3); }
50% { box-shadow: 0 0 15px rgba(139, 92, 246, 0.7); }
}
@keyframes vmk3-power-activate {
0% { opacity: 0; transform: scale(0.5) rotate(-10deg); }
60% { transform: scale(1.1) rotate(3deg); }
100% { opacity: 1; transform: scale(1) rotate(0deg); }
}
@keyframes vmk3-float-power {
0% { opacity: 1; transform: translateY(0) scale(1); }
100% { opacity: 0; transform: translateY(-50px) scale(1.5); }
}
@keyframes vmk3-energy-shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
@keyframes vmk3-shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-3px); }
75% { transform: translateX(3px); }
}
.vmk3-hero-hover:hover {
animation: vmk3-shake 0.4s ease-in-out !important;
cursor: pointer;
}
.vmk3-btn {
font-family: ${FONT_FAMILY};
letter-spacing: 0.5px;
font-weight: 700;
cursor: pointer;
transition: all 0.2s;
text-transform: uppercase;
}
.vmk3-btn:hover {
transform: scale(1.08);
filter: brightness(1.2);
}
.vmk3-power-card {
animation: vmk3-power-activate 0.4s ease-out;
}
`;
document.head.appendChild(style);
}
__name(injectStyles, "injectStyles");
function createCharacterPicker() {
const container = document.createElement("div");
container.id = "vmk3-character-picker";
container.style.cssText = `
width: 100%; margin-top: 16px; padding: 20px;
background: linear-gradient(135deg, #0f0024 0%, #1a0a3e 50%, #2d1b69 100%);
border-radius: 16px; box-shadow: 0 8px 32px rgba(0,0,0,0.5);
border: 2px solid #7c3aed40; box-sizing: border-box;
font-family: ${FONT_FAMILY};
text-align: center;
`.replace(/\s+/g, " ").trim();
container.innerHTML = `
<div style="font-size: 26px; color: #fef3c7; font-weight: 800; margin-bottom: 4px; text-shadow: 2px 2px 4px rgba(0,0,0,0.5); letter-spacing: 1px;">
\u{1F9B8} CHOOSE YOUR HERO! \u{1F9B8}
</div>
<div style="font-size: 14px; color: #c4b5fd; margin-bottom: 16px; font-weight: 600;">
Pick your superhero to train with!
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;">
${HERO_CHARACTERS.map(
(h) => `
<div class="vmk3-hero-option" data-hero-id="${h.id}" style="
padding: 12px 8px; border-radius: 14px; cursor: pointer;
background: ${h.bgGradient}; border: 3px solid transparent;
transition: all 0.3s; text-align: center;
" onmouseover="this.style.border='3px solid ${h.color}'; this.style.transform='scale(1.05)';"
onmouseout="this.style.border='3px solid transparent'; this.style.transform='scale(1)';">
<div style="font-size: 40px; margin-bottom: 2px;">${h.emoji}</div>
<div style="font-size: 14px; font-weight: 700; color: ${h.color};">${h.name}</div>
<div style="font-size: 12px; color: #94a3b8; margin-top: 2px; font-weight: 600;">\u26A1 ${h.superpower}</div>
</div>
`
).join("")}
</div>
`;
setTimeout(() => {
const options = container.querySelectorAll(".vmk3-hero-option");
options.forEach((opt) => {
opt.addEventListener("click", () => {
const heroId = opt.dataset.heroId;
if (heroId) {
state.saveHero(heroId);
const picker = document.getElementById("vmk3-character-picker");
if (picker)
picker.remove();
injectMainUI();
}
});
});
}, 100);
return container;
}
__name(createCharacterPicker, "createCharacterPicker");
function injectMainUI() {
if (document.getElementById("vmk3-custom-sidebar"))
return;
const gameMeta = document.querySelector(".game__meta");
if (!gameMeta)
return;
const hero = state.selectedHero;
const customDiv = document.createElement("div");
customDiv.id = "vmk3-custom-sidebar";
customDiv.style.cssText = `
width: 100%; margin-top: 16px; padding: 16px;
background: ${hero.bgGradient};
border-radius: 16px; box-shadow: 0 8px 32px rgba(0,0,0,0.5);
border: 2px solid ${hero.color}40;
box-sizing: border-box; position: relative; overflow: visible;
font-family: ${FONT_FAMILY};
`.replace(/\s+/g, " ").trim();
const heroSection = document.createElement("div");
heroSection.style.cssText = `
display: flex; align-items: center; gap: 10px;
margin-bottom: 10px;
`.replace(/\s+/g, " ").trim();
const heroEmoji = document.createElement("div");
heroEmoji.className = "vmk3-hero-hover";
heroEmoji.style.cssText = `
font-size: ${FONT_SIZES.heroEmoji}; cursor: pointer;
animation: vmk3-hero-float 2.5s ease-in-out infinite;
filter: drop-shadow(0 4px 8px rgba(0,0,0,0.3));
`.replace(/\s+/g, " ").trim();
heroEmoji.textContent = hero.emoji;
heroEmoji.title = "Click to change hero!";
heroEmoji.onclick = () => {
state.characterPickerShown = false;
const sidebar = document.getElementById("vmk3-custom-sidebar");
if (sidebar)
sidebar.remove();
const picker = createCharacterPicker();
const gm = document.querySelector(".game__meta");
if (gm)
gm.parentNode?.insertBefore(picker, gm.nextSibling);
};
const heroInfo = document.createElement("div");
heroInfo.style.cssText = "flex: 1;";
heroInfo.innerHTML = `
<div style="font-size: 17px; font-weight: 800; color: ${hero.color}; text-shadow: 1px 1px 3px rgba(0,0,0,0.5); letter-spacing: 0.5px;">
${hero.name}
</div>
<div style="font-size: 13px; color: #94a3b8; font-weight: 700;">
\u26A1 ${hero.superpower}
</div>
<div style="font-size: 12px; color: #64748b; margin-top: 2px; font-weight: 600;">
Transformations: ${state.totalTransformations} | Powers: ${state.totalPowersUsed}
</div>
`;
heroSection.appendChild(heroEmoji);
heroSection.appendChild(heroInfo);
const bubbleWrapper = document.createElement("div");
bubbleWrapper.className = "vmk3-bubble-wrapper";
const speechBubble = document.createElement("div");
speechBubble.id = "vmk3-hero-speech";
speechBubble.className = "vmk3-comic-bubble visible";
speechBubble.style.cssText = `
font-size: ${FONT_SIZES.speechBubble}; color: #e2e8f0;
text-align: center; line-height: 1.5; font-weight: 600;
text-shadow: 1px 1px 2px rgba(0,0,0,0.3);
`.replace(/\s+/g, " ").trim();
speechBubble.textContent = `${hero.emoji} ${state.getBattleCry()}`;
bubbleWrapper.appendChild(speechBubble);
setTimeout(
() => speechBubble.classList.remove("visible"),
TIMING.speechDuration
);
const energySection = document.createElement("div");
energySection.style.cssText = `
width: 100%; margin-bottom: 10px;
`.replace(/\s+/g, " ").trim();
const energyLabel = document.createElement("div");
energyLabel.id = "vmk3-energy-label";
energyLabel.style.cssText = `
font-size: ${FONT_SIZES.energyLabel}; color: #475569;
text-align: center; margin-bottom: 4px;
font-weight: 700;
`.replace(/\s+/g, " ").trim();
energyLabel.textContent = "\u{1F50B} 0% - No Power";
const energyBarOuter = document.createElement("div");
energyBarOuter.style.cssText = `
width: 100%; height: 12px; background: rgba(255,255,255,0.08);
border-radius: 6px; overflow: hidden;
border: 1px solid rgba(255,255,255,0.1);
animation: vmk3-energy-pulse 3s ease-in-out infinite;
`.replace(/\s+/g, " ").trim();
const energyFill = document.createElement("div");
energyFill.id = "vmk3-energy-fill";
energyFill.style.cssText = `
width: 0%; height: 100%; border-radius: 6px;
background: linear-gradient(90deg, #475569, #47556999);
transition: width 0.5s ease, background 0.5s ease;
background-size: 200% 100%;
animation: vmk3-energy-shimmer 2s linear infinite;
`.replace(/\s+/g, " ").trim();
energyBarOuter.appendChild(energyFill);
energySection.appendChild(energyLabel);
energySection.appendChild(energyBarOuter);
const timerDiv = document.createElement("div");
timerDiv.id = "vmk3-timer";
timerDiv.textContent = "\u26A1 0s";
timerDiv.style.cssText = `
width: 100%; margin-bottom: 10px; font-size: ${FONT_SIZES.timer};
font-weight: 800; color: #ef4444; text-align: center;
padding: 6px; background: rgba(0,0,0,0.3); border-radius: 8px;
box-sizing: border-box;
`.replace(/\s+/g, " ").trim();
const powerSection = createPowerSection();
const tipsSection = createTipsSection();
const quoteDiv = document.createElement("div");
quoteDiv.id = "vmk3-quote";
quoteDiv.textContent = state.getRandomQuote();
quoteDiv.style.cssText = `
width: 100%; font-style: italic; font-size: 14px;
color: #64748b; text-align: center; box-sizing: border-box;
font-weight: 600; line-height: 1.4;
`.replace(/\s+/g, " ").trim();
const effectsContainer = document.createElement("div");
effectsContainer.id = "vmk3-effects";
effectsContainer.style.cssText = `
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
pointer-events: none; overflow: hidden; z-index: 10;
`.replace(/\s+/g, " ").trim();
customDiv.appendChild(effectsContainer);
customDiv.appendChild(heroSection);
customDiv.appendChild(bubbleWrapper);
customDiv.appendChild(energySection);
customDiv.appendChild(timerDiv);
customDiv.appendChild(powerSection);
customDiv.appendChild(tipsSection);
customDiv.appendChild(quoteDiv);
gameMeta.parentNode?.insertBefore(customDiv, gameMeta.nextSibling);
startTimer(timerDiv);
startTipAutoAdvance();
startPowerTimer();
}
__name(injectMainUI, "injectMainUI");
function createPowerSection() {
const power = SUPERPOWERS[state.currentPower];
const energyDots = "\u26A1".repeat(power.energyCost) + "\u25CB".repeat(3 - power.energyCost);
const powerDiv = document.createElement("div");
powerDiv.id = "vmk3-power-section";
powerDiv.className = "vmk3-power-card";
powerDiv.style.cssText = `
width: 100%; margin-bottom: 12px; padding: 14px;
background: rgba(15, 23, 42, 0.6); border-radius: 14px;
border: 2px solid ${power.color}50;
box-sizing: border-box; position: relative;
`.replace(/\s+/g, " ").trim();
const powerHeader = document.createElement("div");
powerHeader.style.cssText = `
display: flex; justify-content: space-between; align-items: center;
margin-bottom: 8px; padding-bottom: 6px; border-bottom: 1px solid rgba(255,255,255,0.1);
`.replace(/\s+/g, " ").trim();
powerHeader.innerHTML = `
<div style="font-size:13px; color:#fbbf24; font-weight:800; letter-spacing:1px;">\u26A1 HERO POWERS</div>
<div id="vmk3-power-number" style="font-size:12px; color:#64748b; font-weight:600;">
Power ${state.currentPower + 1}/${SUPERPOWERS.length}
</div>
`;
const powerText = document.createElement("div");
powerText.id = "vmk3-power-text";
powerText.style.cssText = `
width: 100%; text-align: center; min-height: 70px;
margin-bottom: 10px;
`.replace(/\s+/g, " ").trim();
powerText.innerHTML = `
<div style="font-size:30px; margin-bottom:4px;">${power.emoji}</div>
<div style="font-size:${FONT_SIZES.powerName}; font-weight:800; color:${power.color}; text-shadow:1px 1px 3px rgba(0,0,0,0.5); letter-spacing:0.5px;">
${power.name}
</div>
<div style="font-size:${FONT_SIZES.powerDescription}; color:#cbd5e1; margin-top:4px; font-weight:600; line-height:1.4;">
${power.description}
</div>
<div style="font-size:12px; color:#64748b; margin-top:4px; font-weight:600;">Energy: ${energyDots}</div>
`;
const btnContainer = document.createElement("div");
btnContainer.style.cssText = "width: 100%; display: flex; justify-content: space-between; gap: 10px;";
const backBtn = document.createElement("button");
backBtn.id = "vmk3-back-btn";
backBtn.textContent = "\u2190 BACK";
backBtn.className = "vmk3-btn";
backBtn.style.cssText = `
background: rgba(71, 85, 105, 0.5); color: #e2e8f0;
font-size: ${FONT_SIZES.button}; visibility: hidden;
border: 1px solid rgba(255,255,255,0.2);
padding: 7px 12px; border-radius: 10px;
font-family: ${FONT_FAMILY};
cursor: pointer; transition: all 0.2s; letter-spacing: 0.5px;
`.replace(/\s+/g, " ").trim();
backBtn.onmouseover = () => {
backBtn.style.transform = "scale(1.06)";
};
backBtn.onmouseout = () => {
backBtn.style.transform = "scale(1)";
};
backBtn.onclick = () => {
if (state.currentPower > 0) {
state.currentPower--;
updatePowerUI();
startPowerTimer();
}
};
const activateBtn = document.createElement("button");
activateBtn.id = "vmk3-activate-btn";
activateBtn.textContent = "Power Up! \u26A1";
activateBtn.className = "vmk3-btn";
activateBtn.style.cssText = `
background: linear-gradient(135deg, ${power.color}, ${power.color}cc);
color: #ffffff; font-size: ${FONT_SIZES.button};
border: 2px solid rgba(255,255,255,0.3);
padding: 7px 16px; border-radius: 10px;
font-family: ${FONT_FAMILY};
cursor: pointer; transition: all 0.2s; letter-spacing: 0.5px;
box-shadow: 0 4px 12px ${power.color}40;
`.replace(/\s+/g, " ").trim();
activateBtn.onmouseover = () => {
activateBtn.style.transform = "scale(1.08)";
};
activateBtn.onmouseout = () => {
activateBtn.style.transform = "scale(1)";
};
activateBtn.onclick = () => {
state.activatePower();
state.currentPower++;
state.persistStats();
backBtn.style.visibility = "visible";
spawnPowerEffect();
updateEnergyBar2();
showHeroSpeech(state.getPowerUpLine());
if (state.currentPower >= SUPERPOWERS.length) {
state.totalTransformations++;
state.persistStats();
const powerTextEl = document.getElementById("vmk3-power-text");
if (powerTextEl) {
powerTextEl.innerHTML = `<div style="text-align:center;">
<div style="font-size:44px; margin-bottom:6px; animation: vmk3-transform 1s ease-out;">
${state.selectedHero.transformedEmoji}
</div>
<div style="font-size:22px; color:#fef3c7; font-weight:800; text-shadow:2px 2px 4px rgba(0,0,0,0.5); letter-spacing:1px;">
FULL POWER!
</div>
<div style="font-size:16px; color:#86efac; margin-top:4px; font-weight:700;">
Make your SUPER MOVE! \u{1F4A5}
</div>
</div>`;
}
activateBtn.style.display = "none";
stopPowerTimer();
showHeroSpeech(state.getTransformLine());
const heroEmoji = document.querySelector(
"#vmk3-custom-sidebar .vmk3-hero-hover"
);
if (heroEmoji) {
heroEmoji.textContent = state.selectedHero.transformedEmoji;
heroEmoji.style.animation = "vmk3-transform 1s ease-out, vmk3-hero-glow 2s ease-in-out infinite";
}
} else {
updatePowerUI();
startPowerTimer();
}
};
btnContainer.appendChild(backBtn);
btnContainer.appendChild(activateBtn);
powerDiv.appendChild(powerHeader);
powerDiv.appendChild(powerText);
powerDiv.appendChild(btnContainer);
return powerDiv;
}
__name(createPowerSection, "createPowerSection");
function updatePowerUI() {
const power = SUPERPOWERS[state.currentPower];
if (!power)
return;
const energyDots = "\u26A1".repeat(power.energyCost) + "\u25CB".repeat(3 - power.energyCost);
const powerText = document.getElementById("vmk3-power-text");
if (powerText) {
powerText.innerHTML = `
<div style="font-size:30px; margin-bottom:4px;">${power.emoji}</div>
<div style="font-size:${FONT_SIZES.powerName}; font-weight:800; color:${power.color}; text-shadow:1px 1px 3px rgba(0,0,0,0.5); letter-spacing:0.5px;">
${power.name}
</div>
<div style="font-size:${FONT_SIZES.powerDescription}; color:#cbd5e1; margin-top:4px; font-weight:600; line-height:1.4;">
${power.description}
</div>
<div style="font-size:12px; color:#64748b; margin-top:4px; font-weight:600;">Energy: ${energyDots}</div>
`;
}
const powerNumEl = document.getElementById("vmk3-power-number");
if (powerNumEl) {
powerNumEl.textContent = `Power ${state.currentPower + 1}/${SUPERPOWERS.length}`;
}
const activateBtn = document.getElementById("vmk3-activate-btn");
if (activateBtn) {
activateBtn.style.background = `linear-gradient(135deg, ${power.color}, ${power.color}cc)`;
activateBtn.style.boxShadow = `0 4px 12px ${power.color}40`;
}
const powerSection = document.getElementById("vmk3-power-section");
if (powerSection) {
powerSection.style.borderColor = `${power.color}50`;
}
const backBtn = document.getElementById("vmk3-back-btn");
if (backBtn) {
backBtn.style.visibility = state.currentPower === 0 ? "hidden" : "visible";
}
}
__name(updatePowerUI, "updatePowerUI");
function updateEnergyBar2() {
const energyFill = document.getElementById("vmk3-energy-fill");
const energyLabel = document.getElementById("vmk3-energy-label");
if (energyFill) {
energyFill.style.width = `${state.energyPercent}%`;
const level = getEnergyLevel(state.energyPercent);
energyFill.style.background = `linear-gradient(90deg, ${level.color}, ${level.color}aa)`;
}
if (energyLabel) {
const level = getEnergyLevel(state.energyPercent);
energyLabel.textContent = `${level.emoji} ${state.energyPercent}% - ${level.label}`;
energyLabel.style.color = level.color;
}
}
__name(updateEnergyBar2, "updateEnergyBar");
function createTipsSection() {
const tipsDiv = document.createElement("div");
tipsDiv.id = "vmk3-tips";
tipsDiv.style.cssText = `
width: 100%; margin-bottom: 8px; padding: 8px;
background: rgba(100, 116, 139, 0.1); border: 1px solid rgba(255,255,255,0.08);
border-radius: 8px; color: #94a3b8; box-sizing: border-box; opacity: 0.85;
`.replace(/\s+/g, " ").trim();
const tipTextDiv = document.createElement("div");
tipTextDiv.style.cssText = `
width: 100%; font-size: ${FONT_SIZES.tip}; line-height: 1.4;
min-height: 36px; margin-bottom: 6px; text-align: center;
font-weight: 600;
`.replace(/\s+/g, " ").trim();
const tipText = document.createElement("span");
tipText.id = "vmk3-tip-text";
tipText.textContent = HERO_TIPS[state.currentTip];
tipTextDiv.appendChild(tipText);
const btnContainer = document.createElement("div");
btnContainer.style.cssText = "width:100%; display:flex; justify-content:space-between; gap:8px; height:22px;";
const backBtn = document.createElement("button");
backBtn.textContent = "\u2190 BACK";
backBtn.style.cssText = `
background: #475569; border: none; color: #e2e8f0;
padding: 3px 8px; border-radius: 4px; cursor: pointer;
font-size: 11px; transition: all 0.2s;
font-family: ${FONT_FAMILY}; font-weight: 700;
`.replace(/\s+/g, " ").trim();
backBtn.onmouseover = () => {
backBtn.style.transform = "scale(1.05)";
};
backBtn.onmouseout = () => {
backBtn.style.transform = "scale(1)";
};
backBtn.onclick = () => {
state.prevTip();
tipText.textContent = HERO_TIPS[state.currentTip];
startTipAutoAdvance();
};
const nextBtn = document.createElement("button");
nextBtn.id = "vmk3-tip-next-btn";
nextBtn.textContent = `NEXT (${TIMING.tipAutoSeconds}s) \u2192`;
nextBtn.style.cssText = `
background: #475569; border: none; color: #e2e8f0;
padding: 3px 8px; border-radius: 4px; cursor: pointer;
font-size: 11px; transition: all 0.2s;
font-family: ${FONT_FAMILY}; font-weight: 700;
`.replace(/\s+/g, " ").trim();
nextBtn.onmouseover = () => {
nextBtn.style.transform = "scale(1.05)";
};
nextBtn.onmouseout = () => {
nextBtn.style.transform = "scale(1)";
};
nextBtn.onclick = () => {
state.nextTip();
tipText.textContent = HERO_TIPS[state.currentTip];
startTipAutoAdvance();
};
btnContainer.appendChild(backBtn);
btnContainer.appendChild(nextBtn);
tipsDiv.appendChild(tipTextDiv);
tipsDiv.appendChild(btnContainer);
return tipsDiv;
}
__name(createTipsSection, "createTipsSection");
function spawnPowerEffect() {
const container = document.getElementById("vmk3-effects");
if (!container)
return;
const emojis = ["\u26A1", "\u{1F4A5}", "\u2728", "\u{1F31F}", "\u{1F4AB}", "\u{1F525}", "\u2B50", "\u{1F9B8}"];
for (let i = 0; i < 3; i++) {
const emoji = randomItem(emojis);
const el = document.createElement("div");
el.textContent = emoji;
el.style.cssText = `
position: absolute; font-size: 20px; pointer-events: none;
left: ${10 + Math.random() * 80}%; top: ${30 + Math.random() * 40}%;
animation: vmk3-float-power 1.5s ease-out forwards;
animation-delay: ${i * 0.15}s;
`.replace(/\s+/g, " ").trim();
container.appendChild(el);
setTimeout(() => el.remove(), 2e3);
}
}
__name(spawnPowerEffect, "spawnPowerEffect");
function checkMoveChange() {
const activeMove = document.querySelector("kwdb.a1t");
if (!activeMove)
return false;
const moveAttr = activeMove.getAttribute("p") || activeMove.className || "";
const moveText = activeMove.textContent?.trim() || "";
const currentMove = moveAttr + moveText;
if (currentMove && currentMove !== state.lastActiveMove) {
state.lastActiveMove = currentMove;
return true;
}
return false;
}
__name(checkMoveChange, "checkMoveChange");
function resetPowerState() {
state.resetPowers();
state.currentPower = 0;
updatePowerUI();
updateEnergyBar2();
const activateBtn = document.getElementById("vmk3-activate-btn");
if (activateBtn)
activateBtn.style.display = "";
const heroEmoji = document.querySelector(
"#vmk3-custom-sidebar .vmk3-hero-hover"
);
if (heroEmoji) {
heroEmoji.textContent = state.selectedHero.emoji;
heroEmoji.style.animation = "vmk3-hero-float 2.5s ease-in-out infinite";
}
showHeroSpeech(state.getBattleCry());
startPowerTimer();
const tDiv = document.getElementById("vmk3-timer");
if (tDiv) {
tDiv.style.color = "#ef4444";
startTimer(tDiv);
}
if (state.timerElapsed < 3) {
setTimeout(() => {
showHeroSpeech(state.getQuickMoveWarning());
}, 1e3);
}
const quoteDiv = document.getElementById("vmk3-quote");
if (quoteDiv)
quoteDiv.textContent = state.getRandomQuote();
}
__name(resetPowerState, "resetPowerState");
function injectCustomSidebarDiv() {
if (document.getElementById("vmk3-custom-sidebar") || document.getElementById("vmk3-character-picker")) {
if (checkMoveChange()) {
resetPowerState();
}
return;
}
const gameMeta = document.querySelector(".game__meta");
if (!gameMeta)
return;
injectStyles();
state.loadHero();
if (!state.characterPickerShown) {
const picker = createCharacterPicker();
gameMeta.parentNode?.insertBefore(picker, gameMeta.nextSibling);
} else {
injectMainUI();
}
}
__name(injectCustomSidebarDiv, "injectCustomSidebarDiv");
// src/game-play-for-kids-3/index.ts
function init() {
const observer = new MutationObserver(() => {
injectCustomSidebarDiv();
});
observer.observe(document.documentElement, {
childList: true,
subtree: true
});
let retryCount = 0;
const maxRetries = 50;
const retryInterval = setInterval(() => {
retryCount++;
injectCustomSidebarDiv();
if (document.getElementById("vmk3-custom-sidebar") || document.getElementById("vmk3-character-picker") || retryCount >= maxRetries) {
clearInterval(retryInterval);
}
}, 200);
}
__name(init, "init");
init();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment