/* ────────────────────────────────────────────────────────────────
   Tutorials T12–T15 — Complete Game & Publishing Tutorials
   
   T12: Zrób RPG (top-down RPG game tutorial)
   T13: Zrób tower defense (tower defense game tutorial)
   T14: Zrób grę 3D (3D template tutorial)
   T15: Publikacja gry (export PWA, Electron, Capacitor)
──────────────────────────────────────────────────────────────── */
/* ══════════════════════════════════════════════════════════════
   T12 — Zrób RPG
   ══════════════════════════════════════════════════════════════ */
const TUTORIAL_RPG = {
    id: 'build-an-rpg',
    title: {
        en: 'Build a Top-Down RPG',
        pl: 'Zrób RPG z widokiem z góry',
        de: 'Baue ein Top-Down-RPG',
    },
    description: {
        en: 'Create a complete top-down RPG with stats, XP progression, inventory, NPCs, dialogue, and turn-based battles.',
        pl: 'Stwórz kompletne RPG z widokiem z góry: statystyki, progresja XP, ekwipunek, NPC, dialogi i walki turowe.',
        de: 'Erstelle ein komplettes Top-Down-RPG mit Werten, XP-Fortschritt, Inventar, NPCs, Dialogen und rundenbasierten Kämpfen.',
    },
    category: 'game-advanced',
    difficulty: 'advanced',
    estimatedMinutes: 45,
    prerequisites: ['build-a-platformer', 'tilemaps-and-worlds'],
    kidFriendly: true,
    ageRange: { min: 12, max: 99 },
    tags: ['rpg', 'stats', 'inventory', 'npc', 'dialogue', 'turn-based', 'complete-game'],
    steps: [
        // S1: Intro
        {
            id: 'rpg-intro',
            type: 'text',
            title: {
                en: 'Build Your Own RPG! ⚔️',
                pl: 'Zbuduj swoje RPG! ⚔️',
                de: 'Baue dein eigenes RPG! ⚔️',
            },
            content: {
                en: 'In this tutorial you\'ll build a classic top-down RPG!\n\n• Character stats (HP, MP, ATK, DEF, SPD)\n• XP and leveling system\n• Inventory and items\n• NPCs with dialogue\n• Turn-based battle system\n• Tilemap world with warps\n\nReady for an adventure?',
                pl: 'W tym tutorialu zbudujesz klasyczne RPG z widokiem z góry!\n\n• Statystyki postaci (HP, MP, ATK, DEF, SPD)\n• System XP i poziomów\n• Ekwipunek i przedmioty\n• NPC z dialogami\n• System walki turowej\n• Świat z tilemapy z przejściami\n\nGotowy na przygodę?',
                de: 'In diesem Tutorial baust du ein klassisches Top-Down-RPG!\n\n• Charakterwerte (HP, MP, ATK, DEF, SPD)\n• XP- und Levelsystem\n• Inventar und Items\n• NPCs mit Dialogen\n• Rundenbasiertes Kampfsystem\n• Tilemap-Welt mit Warps\n\nBereit für ein Abenteuer?',
            },
            skippable: true,
            tooltipPosition: 'center',
        },
        // S2: Character Stats
        {
            id: 'rpg-stats',
            type: 'code',
            title: {
                en: 'Character Stats & Leveling',
                pl: 'Statystyki postaci i poziomy',
                de: 'Charakterwerte & Leveling',
            },
            content: {
                en: 'Define your hero\'s stats. Use the RPG template config for stat growth curves and XP requirements.',
                pl: 'Zdefiniuj statystyki bohatera. Użyj konfiguracji szablonu RPG dla krzywych wzrostu statystyk i wymogów XP.',
                de: 'Definiere die Werte deines Helden. Verwende die RPG-Template-Konfiguration für Wachstumskurven und XP-Anforderungen.',
            },
            codeTemplate: '// Define hero stats\nconst hero = {\n  name: "Hero",\n  level: 1,\n  xp: 0,\n',
            codeSolution: "const hero = {\n  name: 'Hero',\n  level: 1,\n  xp: 0,\n  stats: {\n    hp: 100, maxHp: 100,\n    mp: 30, maxMp: 30,\n    atk: 12, def: 8,\n    mag: 5, spd: 10,\n    lck: 3,\n  },\n  xpToNextLevel: 100,\n};\n\n// Level up function\nfunction levelUp(hero: typeof hero) {\n  hero.level++;\n  hero.stats.maxHp += 15;\n  hero.stats.hp = hero.stats.maxHp;\n  hero.stats.maxMp += 5;\n  hero.stats.mp = hero.stats.maxMp;\n  hero.stats.atk += 3;\n  hero.stats.def += 2;\n  hero.xpToNextLevel = Math.floor(hero.xpToNextLevel * 1.5);\n}",
            codeValidation: {
                containsAll: ['stats', 'level', 'xp', 'hp', 'atk', 'def'],
            },
            hint: {
                en: 'Define stats object with hp, mp, atk, def. Create a levelUp function.',
                pl: 'Zdefiniuj obiekt stats z hp, mp, atk, def. Stwórz funkcję levelUp.',
                de: 'Definiere stats-Objekt mit hp, mp, atk, def. Erstelle eine levelUp-Funktion.',
            },
        },
        // S3: Inventory System
        {
            id: 'rpg-inventory',
            type: 'code',
            title: {
                en: 'Inventory System',
                pl: 'System ekwipunku',
                de: 'Inventarsystem',
            },
            content: {
                en: 'Build an inventory with item stacking, equipment slots, and consumables. Items have types, stats, and rarity.',
                pl: 'Zbuduj ekwipunek ze stackowaniem przedmiotów, slotami wyposażenia i przedmiotami zużywalnymi.',
                de: 'Baue ein Inventar mit Item-Stacking, Ausrüstungsslots und Verbrauchsgegenständen.',
            },
            codeTemplate: "// Item types\ntype ItemType = 'weapon' | 'armor' | 'consumable' | 'key';\n",
            codeSolution: "type ItemType = 'weapon' | 'armor' | 'consumable' | 'key';\ntype Rarity = 'common' | 'uncommon' | 'rare' | 'legendary';\n\ninterface Item {\n  id: string;\n  name: string;\n  type: ItemType;\n  rarity: Rarity;\n  stats?: { atk?: number; def?: number; mag?: number };\n  healAmount?: number;\n  stackable: boolean;\n}\n\nclass Inventory {\n  private items: Map<string, { item: Item; count: number }> = new Map();\n  readonly maxSlots: number;\n\n  constructor(maxSlots = 20) { this.maxSlots = maxSlots; }\n\n  add(item: Item, count = 1): boolean {\n    const existing = this.items.get(item.id);\n    if (existing && item.stackable) {\n      existing.count += count;\n      return true;\n    }\n    if (this.items.size >= this.maxSlots) return false;\n    this.items.set(item.id, { item, count });\n    return true;\n  }\n\n  remove(itemId: string, count = 1): boolean {\n    const slot = this.items.get(itemId);\n    if (!slot || slot.count < count) return false;\n    slot.count -= count;\n    if (slot.count <= 0) this.items.delete(itemId);\n    return true;\n  }\n}",
            codeValidation: {
                containsAll: ['Inventory', 'Item', 'add', 'remove'],
            },
            hint: {
                en: 'Use a Map for inventory slots. Check stackable before adding.',
                pl: 'Użyj Map dla slotów ekwipunku. Sprawdź stackable przed dodaniem.',
                de: 'Verwende eine Map für Inventarslots. Prüfe stackable vor dem Hinzufügen.',
            },
        },
        // S4: NPC & Dialogue
        {
            id: 'rpg-dialogue',
            type: 'code',
            title: {
                en: 'NPCs & Dialogue System',
                pl: 'NPC i system dialogów',
                de: 'NPCs & Dialogsystem',
            },
            content: {
                en: 'Create NPCs with dialogue trees. Players can choose responses that branch the conversation.',
                pl: 'Stwórz NPC z drzewami dialogów. Gracz może wybierać odpowiedzi, które rozgałęziają rozmowę.',
                de: 'Erstelle NPCs mit Dialogbäumen. Spieler können Antworten wählen, die das Gespräch verzweigen.',
            },
            codeTemplate: "// Dialogue system\ninterface DialogNode {\n  id: string;\n  text: string;\n",
            codeSolution: "interface DialogNode {\n  id: string;\n  text: string;\n  speaker: string;\n  choices?: { text: string; next: string; condition?: string }[];\n  next?: string; // auto-advance to next node\n}\n\nconst innkeeperDialog: DialogNode[] = [\n  {\n    id: 'greet',\n    speaker: 'Innkeeper',\n    text: 'Welcome, traveler! Would you like to rest?',\n    choices: [\n      { text: 'Yes, I need rest. (10 gold)', next: 'rest' },\n      { text: 'No thanks.', next: 'bye' },\n      { text: 'Any rumors?', next: 'rumors' },\n    ],\n  },\n  {\n    id: 'rest',\n    speaker: 'Innkeeper',\n    text: 'Sleep well! *HP and MP fully restored*',\n    next: 'greet',\n  },\n  {\n    id: 'rumors',\n    speaker: 'Innkeeper',\n    text: 'I heard monsters in the eastern cave grew stronger...',\n    next: 'greet',\n  },\n  {\n    id: 'bye',\n    speaker: 'Innkeeper',\n    text: 'Safe travels!',\n  },\n];",
            codeValidation: {
                containsAll: ['DialogNode', 'speaker', 'choices', 'next'],
            },
            hint: {
                en: 'Each node has text + optional choices array. Each choice points to a next node ID.',
                pl: 'Każdy węzeł ma tekst + opcjonalną tablicę wyborów. Każdy wybór wskazuje na ID następnego węzła.',
                de: 'Jeder Knoten hat Text + optionales choices-Array. Jede Wahl zeigt auf eine nächste Knoten-ID.',
            },
        },
        // S5: Turn-Based Battle
        {
            id: 'rpg-battle',
            type: 'code',
            title: {
                en: 'Turn-Based Battle System',
                pl: 'Turowy system walk',
                de: 'Rundenbasiertes Kampfsystem',
            },
            content: {
                en: 'Build a turn-based battle system where heroes and monsters take turns attacking. Speed determines turn order.',
                pl: 'Zbuduj turowy system walk, gdzie bohaterowie i potwory atakują po kolei. Szybkość określa kolejność tur.',
                de: 'Baue ein rundenbasiertes Kampfsystem, in dem Helden und Monster abwechselnd angreifen. Geschwindigkeit bestimmt die Reihenfolge.',
            },
            codeTemplate: "// Battle system\ntype BattleAction = 'attack' | 'magic' | 'defend' | 'item' | 'flee';\n",
            codeSolution: "type BattleAction = 'attack' | 'magic' | 'defend' | 'item' | 'flee';\n\nfunction calculateDamage(attacker: { atk: number }, defender: { def: number }): number {\n  const base = attacker.atk - defender.def * 0.5;\n  const variance = 0.9 + Math.random() * 0.2; // ±10%\n  return Math.max(1, Math.floor(base * variance));\n}\n\nfunction determineTurnOrder(combatants: { name: string; spd: number }[]) {\n  return combatants.slice().sort((a, b) => b.spd - a.spd);\n}\n\nfunction executeTurn(action: BattleAction, actor: any, target: any): string {\n  switch (action) {\n    case 'attack': {\n      const dmg = calculateDamage(actor.stats, target.stats);\n      target.stats.hp = Math.max(0, target.stats.hp - dmg);\n      return `${actor.name} attacks ${target.name} for ${dmg} damage!`;\n    }\n    case 'defend':\n      actor.defending = true;\n      return `${actor.name} defends!`;\n    case 'flee':\n      return Math.random() > 0.5 ? 'Escaped!' : 'Cannot escape!';\n    default:\n      return '';\n  }\n}",
            codeValidation: {
                containsAll: ['calculateDamage', 'determineTurnOrder', 'BattleAction'],
            },
            hint: {
                en: 'Damage = ATK - DEF/2 (with variance). Sort combatants by SPD for turn order.',
                pl: 'Obrażenia = ATK - DEF/2 (z wariancją). Posortuj walczących po SPD dla kolejności tur.',
                de: 'Schaden = ATK - DEF/2 (mit Varianz). Sortiere nach SPD für Reihenfolge.',
            },
        },
        // S6: World Map
        {
            id: 'rpg-world',
            type: 'interactive',
            title: {
                en: 'Build the RPG World Map',
                pl: 'Zbuduj mapę świata RPG',
                de: 'RPG-Weltkarte bauen',
            },
            content: {
                en: 'Create multiple rooms connected by warps. Use tilemaps for each area (town, forest, cave, castle).',
                pl: 'Stwórz wiele pomieszczeń połączonych przejściami. Użyj tilemap dla każdego obszaru (miasteczko, las, jaskinia, zamek).',
                de: 'Erstelle mehrere Räume verbunden durch Warps. Verwende Tilemaps für jeden Bereich (Stadt, Wald, Höhle, Burg).',
            },
            requiredAction: 'create-world-map',
            codeTemplate: "// Define world areas\nconst areas = [\n",
            codeSolution: "const areas = [\n  { id: 'town', name: 'Starter Town', tilemap: 'town-map', npcs: ['innkeeper', 'shopkeeper'] },\n  { id: 'forest', name: 'Dark Forest', tilemap: 'forest-map', enemies: ['wolf', 'slime'] },\n  { id: 'cave', name: 'Crystal Cave', tilemap: 'cave-map', enemies: ['bat', 'golem'] },\n  { id: 'castle', name: 'Demon Castle', tilemap: 'castle-map', enemies: ['skeleton', 'demon-lord'] },\n];\n\nconst warps = [\n  { from: 'town', to: 'forest', x: 19, y: 7 },\n  { from: 'forest', to: 'cave', x: 15, y: 2 },\n  { from: 'forest', to: 'town', x: 0, y: 7 },\n  { from: 'cave', to: 'castle', x: 10, y: 0 },\n];",
            codeValidation: {
                containsAll: ['areas', 'warps', 'tilemap'],
            },
        },
        // S7: Quiz
        {
            id: 'rpg-quiz',
            type: 'quiz',
            title: {
                en: 'RPG Quiz 🧙',
                pl: 'Quiz RPG 🧙',
                de: 'RPG-Quiz 🧙',
            },
            content: {
                en: 'In a turn-based RPG, what stat typically determines the order of actions?',
                pl: 'W turowym RPG, jaka statystyka typowo decyduje o kolejności akcji?',
                de: 'In einem rundenbasierten RPG, welcher Wert bestimmt typischerweise die Aktionsreihenfolge?',
            },
            quizOptions: [
                { id: 'a', text: { en: 'Attack (ATK)', pl: 'Atak (ATK)', de: 'Angriff (ATK)' } },
                { id: 'b', text: { en: 'Defense (DEF)', pl: 'Obrona (DEF)', de: 'Verteidigung (DEF)' } },
                { id: 'c', text: { en: 'Speed (SPD)', pl: 'Szybkość (SPD)', de: 'Geschwindigkeit (SPD)' } },
                { id: 'd', text: { en: 'Luck (LCK)', pl: 'Szczęście (LCK)', de: 'Glück (LCK)' } },
            ],
            quizCorrectId: 'c',
        },
        // S8: Checkpoint
        {
            id: 'rpg-complete',
            type: 'checkpoint',
            title: {
                en: 'RPG Complete! 🏰',
                pl: 'RPG gotowe! 🏰',
                de: 'RPG fertig! 🏰',
            },
            content: {
                en: 'Amazing! You\'ve built a full RPG with:\n• Character stats & leveling\n• Inventory with rarity system\n• NPCs with branching dialogue\n• Turn-based combat\n• Multi-area world map with warps\n\nChallenge: Add a party system with 4 heroes!',
                pl: 'Niesamowite! Zbudowałeś pełne RPG z:\n• Statystyki i poziomy postaci\n• Ekwipunek z systemem rzadkości\n• NPC z rozgałęzionymi dialogami\n• Walki turowe\n• Mapa świata z wieloma obszarami\n\nWyzwanie: Dodaj system drużyny z 4 bohaterami!',
                de: 'Fantastisch! Du hast ein vollständiges RPG gebaut mit:\n• Charakterwerte & Leveling\n• Inventar mit Seltenheitssystem\n• NPCs mit verzweigten Dialogen\n• Rundenbasierter Kampf\n• Weltkarte mit mehreren Bereichen\n\nHerausforderung: Füge ein Gruppensystem mit 4 Helden hinzu!',
            },
        },
    ],
};
/* ══════════════════════════════════════════════════════════════
   T13 — Zrób Tower Defense
   ══════════════════════════════════════════════════════════════ */
const TUTORIAL_TOWER_DEFENSE = {
    id: 'build-tower-defense',
    title: {
        en: 'Build a Tower Defense Game',
        pl: 'Zrób tower defense',
        de: 'Baue ein Tower-Defense-Spiel',
    },
    description: {
        en: 'Build a complete tower defense game with waves, tower types, targeting modes, upgrades, and enemy pathfinding.',
        pl: 'Zbuduj kompletną grę tower defense z falami, typami wież, trybami celowania, ulepszeniami i pathfindingiem wrogów.',
        de: 'Baue ein komplettes Tower-Defense-Spiel mit Wellen, Turmtypen, Zielmodi, Upgrades und Feind-Pathfinding.',
    },
    category: 'game-advanced',
    difficulty: 'intermediate',
    estimatedMinutes: 35,
    prerequisites: ['first-game-bouncing-ball', 'tilemaps-and-worlds'],
    kidFriendly: true,
    ageRange: { min: 10, max: 99 },
    tags: ['tower-defense', 'strategy', 'waves', 'upgrades', 'pathfinding'],
    steps: [
        // S1: Intro
        {
            id: 'td-intro',
            type: 'text',
            title: {
                en: 'Build Tower Defense! 🗼',
                pl: 'Zbuduj Tower Defense! 🗼',
                de: 'Baue Tower Defense! 🗼',
            },
            content: {
                en: 'In this tutorial you\'ll build a tower defense game!\n\n• Map with path for enemies\n• Tower types (arrow, cannon, ice, laser)\n• Enemy waves with scaling difficulty\n• Tower targeting modes\n• Upgrade system\n• Gold & economy\n\nDefend your base!',
                pl: 'W tym tutorialu zbudujesz grę tower defense!\n\n• Mapa ze ścieżką dla wrogów\n• Typy wież (strzały, armata, lód, laser)\n• Fale wrogów ze skalującą się trudnością\n• Tryby celowania wież\n• System ulepszeń\n• Złoto i ekonomia\n\nBroń swojej bazy!',
                de: 'In diesem Tutorial baust du ein Tower-Defense-Spiel!\n\n• Karte mit Feindpfad\n• Turmtypen (Pfeil, Kanone, Eis, Laser)\n• Feindwellen mit steigender Schwierigkeit\n• Turm-Zielmodi\n• Upgrade-System\n• Gold & Wirtschaft\n\nVerteidige deine Basis!',
            },
            skippable: true,
            tooltipPosition: 'center',
        },
        // S2: Tower Types
        {
            id: 'td-towers',
            type: 'code',
            title: {
                en: 'Define Tower Types',
                pl: 'Zdefiniuj typy wież',
                de: 'Turmtypen definieren',
            },
            content: {
                en: 'Define different tower types with damage, range, fire rate, and cost. Each tower targets enemies differently.',
                pl: 'Zdefiniuj różne typy wież z obrażeniami, zasięgiem, szybkostrzelnością i kosztem. Każda wieża celuje inaczej.',
                de: 'Definiere verschiedene Turmtypen mit Schaden, Reichweite, Feuerrate und Kosten. Jeder Turm zielt anders.',
            },
            codeTemplate: "// Tower definitions\ntype TargetMode = 'first' | 'last' | 'closest' | 'strongest';\n",
            codeSolution: "type TargetMode = 'first' | 'last' | 'closest' | 'strongest';\n\ninterface TowerDef {\n  type: string;\n  name: string;\n  damage: number;\n  range: number;\n  fireRate: number; // shots per second\n  cost: number;\n  targetMode: TargetMode;\n  projectileSpeed: number;\n  splash?: number;\n  slow?: number;\n}\n\nconst TOWERS: TowerDef[] = [\n  { type: 'arrow', name: 'Arrow Tower', damage: 10, range: 150, fireRate: 2, cost: 50, targetMode: 'first', projectileSpeed: 400 },\n  { type: 'cannon', name: 'Cannon Tower', damage: 40, range: 120, fireRate: 0.5, cost: 100, targetMode: 'closest', projectileSpeed: 200, splash: 50 },\n  { type: 'ice', name: 'Ice Tower', damage: 5, range: 130, fireRate: 1.5, cost: 75, targetMode: 'first', projectileSpeed: 300, slow: 0.5 },\n  { type: 'laser', name: 'Laser Tower', damage: 25, range: 200, fireRate: 3, cost: 150, targetMode: 'strongest', projectileSpeed: 9999 },\n];",
            codeValidation: {
                containsAll: ['TowerDef', 'damage', 'range', 'fireRate', 'TargetMode'],
            },
            hint: {
                en: 'Define cost, damage, range, fireRate per tower. Add splash/slow for special towers.',
                pl: 'Zdefiniuj koszt, obrażenia, zasięg, fireRate na wieżę. Dodaj splash/slow dla specjalnych.',
                de: 'Definiere cost, damage, range, fireRate pro Turm. Füge splash/slow für Spezialttürme hinzu.',
            },
        },
        // S3: Enemy Path
        {
            id: 'td-path',
            type: 'code',
            title: {
                en: 'Define the Enemy Path',
                pl: 'Zdefiniuj ścieżkę wrogów',
                de: 'Feindpfad definieren',
            },
            content: {
                en: 'Enemies follow a predefined path from start to end. Define waypoints that enemies walk between.',
                pl: 'Wrogowie podążają predefiniowaną ścieżką od startu do końca. Zdefiniuj waypoints, między którymi chodzą wrogowie.',
                de: 'Feinde folgen einem vordefinierten Pfad vom Start zum Ende. Definiere Wegpunkte, zwischen denen Feinde laufen.',
            },
            codeTemplate: '// Enemy path waypoints\nconst path = [\n',
            codeSolution: "const path = [\n  { x: 0, y: 200 },     // start (left edge)\n  { x: 200, y: 200 },   // turn down\n  { x: 200, y: 400 },\n  { x: 400, y: 400 },   // turn up\n  { x: 400, y: 100 },\n  { x: 600, y: 100 },   // final stretch\n  { x: 600, y: 300 },\n  { x: 800, y: 300 },   // end (base)\n];\n\nfunction moveAlongPath(enemy: any, dt: number) {\n  const target = path[enemy.waypointIndex];\n  const dx = target.x - enemy.x;\n  const dy = target.y - enemy.y;\n  const dist = Math.sqrt(dx * dx + dy * dy);\n\n  if (dist < 5) {\n    enemy.waypointIndex++;\n    if (enemy.waypointIndex >= path.length) {\n      // Enemy reached the base!\n      enemy.reachedEnd = true;\n    }\n  } else {\n    enemy.x += (dx / dist) * enemy.speed * dt;\n    enemy.y += (dy / dist) * enemy.speed * dt;\n  }\n}",
            codeValidation: {
                containsAll: ['path', 'waypointIndex', 'moveAlongPath'],
            },
            hint: {
                en: 'Array of {x,y} waypoints. Move toward current waypoint, advance index when close.',
                pl: 'Tablica waypointów {x,y}. Ruszaj się w stronę bieżącego, przesuwaj indeks gdy blisko.',
                de: 'Array von {x,y}-Wegpunkten. Bewege zum aktuellen, erhöhe Index wenn nah.',
            },
        },
        // S4: Wave System
        {
            id: 'td-waves',
            type: 'code',
            title: {
                en: 'Enemy Wave System',
                pl: 'System fal wrogów',
                de: 'Feindwellen-System',
            },
            content: {
                en: 'Use the `WaveGenerator` to create escalating enemy waves. Each wave has more enemies and tougher types.',
                pl: 'Użyj `WaveGenerator` do tworzenia eskalujących fal wrogów. Każda fala ma więcej wrogów i trudniejsze typy.',
                de: 'Verwende den `WaveGenerator` für eskalierende Feindwellen. Jede Welle hat mehr Feinde und härtere Typen.',
            },
            codeTemplate: '// Set up enemy waves\nconst waves = ',
            codeSolution: "const waves = new WaveGenerator({\n  baseEnemyCount: 5,\n  countGrowth: 1.4,\n  typeProbabilities: [\n    { type: 'goblin', weight: 5, minWave: 1 },\n    { type: 'orc', weight: 3, minWave: 3 },\n    { type: 'troll', weight: 1, minWave: 5 },\n    { type: 'dragon', weight: 0.3, minWave: 8 },\n  ],\n  groupSize: [1, 4],\n  groupDelay: [0.5, 1.5],\n});\n\n// Start wave 1\nlet currentWave = 1;\nconst waveData = waves.generateWave(currentWave);\n// waveData contains groups with enemy types, counts, and delays",
            codeValidation: {
                containsAll: ['WaveGenerator', 'generateWave', 'typeProbabilities'],
            },
            hint: {
                en: 'new WaveGenerator(config) → generateWave(waveNumber)',
                pl: 'new WaveGenerator(config) → generateWave(numerFali)',
                de: 'new WaveGenerator(config) → generateWave(wellenNummer)',
            },
        },
        // S5: Targeting & Shooting
        {
            id: 'td-targeting',
            type: 'code',
            title: {
                en: 'Tower Targeting & Shooting',
                pl: 'Celowanie i strzelanie wież',
                de: 'Turm-Zielen & Schießen',
            },
            content: {
                en: 'Each tower selects a target based on its targeting mode, then fires projectiles at the fire rate interval.',
                pl: 'Każda wieża wybiera cel na podstawie trybu celowania, potem strzela pociskami w odstępach fire rate.',
                de: 'Jeder Turm wählt ein Ziel basierend auf dem Zielmodus und feuert Projektile im Feuerraten-Intervall.',
            },
            codeTemplate: '// Tower targeting system\nfunction findTarget(tower: any, enemies: any[], mode: TargetMode) {\n',
            codeSolution: "function findTarget(tower: any, enemies: any[], mode: TargetMode) {\n  const inRange = enemies.filter(e => {\n    const dx = e.x - tower.x;\n    const dy = e.y - tower.y;\n    return Math.sqrt(dx * dx + dy * dy) <= tower.range;\n  });\n\n  if (inRange.length === 0) return null;\n\n  switch (mode) {\n    case 'first':    return inRange.reduce((a, b) => a.waypointIndex > b.waypointIndex ? a : b);\n    case 'last':     return inRange.reduce((a, b) => a.waypointIndex < b.waypointIndex ? a : b);\n    case 'closest': {\n      let best = inRange[0], bestDist = Infinity;\n      for (const e of inRange) {\n        const d = Math.sqrt((e.x - tower.x) ** 2 + (e.y - tower.y) ** 2);\n        if (d < bestDist) { best = e; bestDist = d; }\n      }\n      return best;\n    }\n    case 'strongest': return inRange.reduce((a, b) => a.hp > b.hp ? a : b);\n  }\n}",
            codeValidation: {
                containsAll: ['findTarget', 'inRange', 'TargetMode'],
            },
            hint: {
                en: 'Filter enemies in range, then pick based on targeting mode.',
                pl: 'Filtruj wrogów w zasięgu, potem wybierz na podstawie trybu celowania.',
                de: 'Filtere Feinde in Reichweite, dann wähle basierend auf Zielmodus.',
            },
        },
        // S6: Upgrades & Economy
        {
            id: 'td-upgrades',
            type: 'code',
            title: {
                en: 'Upgrades & Gold Economy',
                pl: 'Ulepszenia i ekonomia złota',
                de: 'Upgrades & Gold-Wirtschaft',
            },
            content: {
                en: 'Towers can be upgraded to increase damage and range. Earn gold from killing enemies. Sell towers for a refund.',
                pl: 'Wieże mogą być ulepszane, zwiększając obrażenia i zasięg. Zarabiaj złoto z zabijania wrogów. Sprzedawaj wieże z częściowym zwrotem.',
                de: 'Türme können aufgewertet werden für mehr Schaden und Reichweite. Verdiene Gold durch Feind-Kills. Verkaufe Türme für Rückerstattung.',
            },
            codeTemplate: '// Upgrade system\nlet gold = 200;\n',
            codeSolution: "let gold = 200;\n\nfunction upgradeTower(tower: any): boolean {\n  const upgradeCost = Math.floor(tower.cost * 0.75 * tower.level);\n  if (gold < upgradeCost) return false;\n\n  gold -= upgradeCost;\n  tower.level++;\n  tower.damage = Math.floor(tower.damage * 1.3);\n  tower.range += 10;\n  tower.fireRate *= 1.1;\n  return true;\n}\n\nfunction sellTower(tower: any): number {\n  const refund = Math.floor(tower.cost * 0.6);\n  gold += refund;\n  return refund;\n}\n\nfunction onEnemyKilled(enemy: any) {\n  gold += enemy.goldReward;\n}",
            codeValidation: {
                containsAll: ['upgradeTower', 'sellTower', 'gold'],
            },
            hint: {
                en: 'Upgrade cost scales with level. Sell returns ~60% of original cost.',
                pl: 'Koszt ulepszenia skaluje się z poziomem. Sprzedaż zwraca ~60% oryginalnego kosztu.',
                de: 'Upgrade-Kosten skalieren mit Level. Verkauf erstattet ~60% des Originalpreises.',
            },
        },
        // S7: Checkpoint
        {
            id: 'td-complete',
            type: 'checkpoint',
            title: {
                en: 'Tower Defense Complete! 🏆',
                pl: 'Tower Defense gotowy! 🏆',
                de: 'Tower Defense fertig! 🏆',
            },
            content: {
                en: 'You\'ve built a full tower defense game!\n• 4 tower types with different targeting\n• Enemy pathfinding along waypoints\n• Escalating wave system\n• Upgrade & sell mechanics\n• Gold economy\n\nChallenge: Add flying enemies that ignore the path!',
                pl: 'Zbudowałeś kompletną grę tower defense!\n• 4 typy wież z różnym celowaniem\n• Pathfinding wrogów po waypointach\n• Eskalujący system fal\n• Mechaniki ulepszania i sprzedaży\n• Ekonomia złota\n\nWyzwanie: Dodaj latających wrogów ignorujących ścieżkę!',
                de: 'Du hast ein komplettes Tower-Defense-Spiel gebaut!\n• 4 Turmtypen mit verschiedenem Zielen\n• Feind-Pathfinding entlang Wegpunkten\n• Eskalierendes Wellensystem\n• Upgrade- & Verkaufsmechaniken\n• Gold-Wirtschaft\n\nHerausforderung: Füge fliegende Feinde hinzu, die den Pfad ignorieren!',
            },
        },
    ],
};
/* ══════════════════════════════════════════════════════════════
   T14 — Zrób grę 3D
   ══════════════════════════════════════════════════════════════ */
const TUTORIAL_3D_GAME = {
    id: 'build-a-3d-game',
    title: {
        en: 'Build a 3D Game',
        pl: 'Zrób grę 3D',
        de: 'Baue ein 3D-Spiel',
    },
    description: {
        en: 'Create your first 3D game: set up a 3D world, add meshes, lights, cameras, physics, and a character controller.',
        pl: 'Stwórz swoją pierwszą grę 3D: skonfiguruj świat 3D, dodaj meshe, światła, kamery, fizykę i kontroler postaci.',
        de: 'Erstelle dein erstes 3D-Spiel: richte eine 3D-Welt ein, füge Meshes, Lichter, Kameras, Physik und einen Character-Controller hinzu.',
    },
    category: 'game-advanced',
    difficulty: 'intermediate',
    estimatedMinutes: 35,
    prerequisites: ['first-game-bouncing-ball'],
    kidFriendly: false,
    ageRange: { min: 14, max: 99 },
    tags: ['3d', 'world3d', 'mesh', 'camera', 'physics3d', 'character-controller'],
    steps: [
        // S1: Intro
        {
            id: '3d-intro',
            type: 'text',
            title: {
                en: 'Welcome to 3D! 🎮',
                pl: 'Witaj w 3D! 🎮',
                de: 'Willkommen in 3D! 🎮',
            },
            content: {
                en: 'In this tutorial you\'ll enter the third dimension!\n\n• Set up a 3D world (World3D)\n• Add meshes (cube, sphere, plane)\n• Lighting (directional, point, spot)\n• Camera controllers (FPS, orbit)\n• 3D physics (rigid bodies, colliders)\n• Character controller (walking, jumping)\n\nLet\'s go 3D!',
                pl: 'W tym tutorialu wejdziesz w trzeci wymiar!\n\n• Skonfiguruj świat 3D (World3D)\n• Dodaj meshe (sześcian, sfera, płaszczyzna)\n• Oświetlenie (kierunkowe, punktowe, spot)\n• Kontrolery kamery (FPS, orbita)\n• Fizyka 3D (rigid body, kolidery)\n• Kontroler postaci (chodzenie, skakanie)\n\nWejdźmy w 3D!',
                de: 'In diesem Tutorial betrittst du die dritte Dimension!\n\n• 3D-Welt einrichten (World3D)\n• Meshes hinzufügen (Würfel, Kugel, Ebene)\n• Beleuchtung (Richtung, Punkt, Spot)\n• Kamera-Controller (FPS, Orbit)\n• 3D-Physik (Starrkörper, Kollider)\n• Character-Controller (Laufen, Springen)\n\nAb in die 3. Dimension!',
            },
            skippable: true,
            tooltipPosition: 'center',
        },
        // S2: World3D Setup
        {
            id: '3d-world-setup',
            type: 'code',
            title: {
                en: 'Create a 3D World',
                pl: 'Utwórz świat 3D',
                de: '3D-Welt erstellen',
            },
            content: {
                en: 'Use `World3D` to create the 3D scene. It manages transforms, meshes, lights, and cameras.',
                pl: 'Użyj `World3D` do stworzenia sceny 3D. Zarządza transformacjami, meshami, światłami i kamerami.',
                de: 'Verwende `World3D` zum Erstellen der 3D-Szene. Es verwaltet Transforms, Meshes, Lichter und Kameras.',
            },
            codeTemplate: '// Create the 3D world\nconst world3d = ',
            codeSolution: "const world3d = new World3D();\n\n// Add a ground plane\nconst ground = world3d.addEntity();\nworld3d.setTransform(ground, { position: { x: 0, y: 0, z: 0 }, scale: { x: 50, y: 1, z: 50 } });\nworld3d.setMesh(ground, { type: 'plane', color: { r: 0.3, g: 0.7, b: 0.3, a: 1 } });\n\n// Add ambient light\nworld3d.setAmbientLight({ r: 0.2, g: 0.2, b: 0.2, a: 1 });",
            codeValidation: {
                containsAll: ['World3D', 'addEntity', 'setTransform'],
            },
            hint: {
                en: 'new World3D() → addEntity() → setTransform() → setMesh()',
                pl: 'new World3D() → addEntity() → setTransform() → setMesh()',
                de: 'new World3D() → addEntity() → setTransform() → setMesh()',
            },
        },
        // S3: Meshes
        {
            id: '3d-meshes',
            type: 'code',
            title: {
                en: 'Add 3D Meshes',
                pl: 'Dodaj meshe 3D',
                de: '3D-Meshes hinzufügen',
            },
            content: {
                en: 'Add primitive meshes to the scene: cubes, spheres, cylinders. Each mesh has position, rotation, and scale.',
                pl: 'Dodaj prymitywne meshe do sceny: sześciany, sfery, cylindry. Każdy mesh ma pozycję, rotację i skalę.',
                de: 'Füge primitive Meshes zur Szene hinzu: Würfel, Kugeln, Zylinder. Jedes Mesh hat Position, Rotation und Skalierung.',
            },
            codeTemplate: '// Add scene objects\nconst cube = world3d.addEntity();\n',
            codeSolution: "const cube = world3d.addEntity();\nworld3d.setTransform(cube, { position: { x: 0, y: 2, z: 0 } });\nworld3d.setMesh(cube, { type: 'cube', color: { r: 0.8, g: 0.2, b: 0.2, a: 1 } });\n\nconst sphere = world3d.addEntity();\nworld3d.setTransform(sphere, { position: { x: 3, y: 1.5, z: 0 } });\nworld3d.setMesh(sphere, { type: 'sphere', color: { r: 0.2, g: 0.5, b: 1, a: 1 } });\n\nconst cylinder = world3d.addEntity();\nworld3d.setTransform(cylinder, { position: { x: -3, y: 1, z: 2 } });\nworld3d.setMesh(cylinder, { type: 'cylinder', color: { r: 0.9, g: 0.8, b: 0.1, a: 1 } });",
            codeValidation: {
                containsAll: ['cube', 'sphere', 'setMesh'],
            },
            hint: {
                en: "Set mesh type to 'cube', 'sphere', 'cylinder', or 'plane'",
                pl: "Ustaw typ mesha na 'cube', 'sphere', 'cylinder' lub 'plane'",
                de: "Setze Mesh-Typ auf 'cube', 'sphere', 'cylinder' oder 'plane'",
            },
        },
        // S4: Lighting
        {
            id: '3d-lighting',
            type: 'code',
            title: {
                en: 'Add Lights to Your Scene',
                pl: 'Dodaj oświetlenie do sceny',
                de: 'Lichter zur Szene hinzufügen',
            },
            content: {
                en: 'Add directional, point, and spot lights to illuminate the scene. Lights have color, intensity, and range.',
                pl: 'Dodaj światła kierunkowe, punktowe i spot do oświetlenia sceny. Światła mają kolor, intensywność i zasięg.',
                de: 'Füge Richtungs-, Punkt- und Spotlichter hinzu. Lichter haben Farbe, Intensität und Reichweite.',
            },
            codeTemplate: '// Add lights\nconst sunLight = world3d.addEntity();\n',
            codeSolution: "const sunLight = world3d.addEntity();\nworld3d.setTransform(sunLight, { rotation: { x: -0.5, y: 0.3, z: 0, w: 1 } });\nworld3d.setLight(sunLight, {\n  type: 'directional',\n  color: { r: 1, g: 0.95, b: 0.8, a: 1 },\n  intensity: 1.2,\n});\n\nconst torch = world3d.addEntity();\nworld3d.setTransform(torch, { position: { x: 5, y: 3, z: 0 } });\nworld3d.setLight(torch, {\n  type: 'point',\n  color: { r: 1, g: 0.6, b: 0.2, a: 1 },\n  intensity: 2,\n  range: 15,\n});",
            codeValidation: {
                containsAll: ['setLight', 'directional', 'intensity'],
            },
            hint: {
                en: "Light types: 'directional', 'point', 'spot', 'hemisphere'",
                pl: "Typy świateł: 'directional', 'point', 'spot', 'hemisphere'",
                de: "Lichttypen: 'directional', 'point', 'spot', 'hemisphere'",
            },
        },
        // S5: Camera Controller
        {
            id: '3d-camera',
            type: 'code',
            title: {
                en: 'Camera Controllers',
                pl: 'Kontrolery kamery',
                de: 'Kamera-Controller',
            },
            content: {
                en: 'Set up a camera with an orbit controller. The player can rotate around and zoom into the scene.',
                pl: 'Skonfiguruj kamerę z kontrolerem orbity. Gracz może obracać się wokół i przybliżać scenę.',
                de: 'Richte eine Kamera mit Orbit-Controller ein. Der Spieler kann sich drehen und in die Szene zoomen.',
            },
            codeTemplate: '// Set up orbit camera\nconst camEntity = world3d.addEntity();\n',
            codeSolution: "const camEntity = world3d.addEntity();\nworld3d.setTransform(camEntity, { position: { x: 0, y: 5, z: 10 } });\nworld3d.setCamera(camEntity, {\n  fov: 60,\n  near: 0.1,\n  far: 1000,\n  controller: 'orbit', // 'fps', 'third-person', 'orbit', 'fly'\n  active: true,\n});\n\n// The orbit controller auto-rotates around target\n// with mouse drag and scroll zoom",
            codeValidation: {
                containsAll: ['setCamera', 'fov', 'controller'],
            },
            hint: {
                en: "Camera controllers: 'fps', 'third-person', 'orbit', 'fly'",
                pl: "Kontrolery kamery: 'fps', 'third-person', 'orbit', 'fly'",
                de: "Kamera-Controller: 'fps', 'third-person', 'orbit', 'fly'",
            },
        },
        // S6: 3D Physics
        {
            id: '3d-physics',
            type: 'code',
            title: {
                en: '3D Physics & Collisions',
                pl: 'Fizyka i kolizje 3D',
                de: '3D-Physik & Kollisionen',
            },
            content: {
                en: 'Add rigid bodies and colliders for 3D physics. Objects fall with gravity and bounce off each other.',
                pl: 'Dodaj ciała sztywne i kolidery dla fizyki 3D. Obiekty spadają z grawitacją i odbijają się od siebie.',
                de: 'Füge Starrkörper und Kollider für 3D-Physik hinzu. Objekte fallen mit Schwerkraft und prallen voneinander ab.',
            },
            codeTemplate: '// Add physics to cube\n',
            codeSolution: "// Make cube a dynamic physics body\nworld3d.setRigidBody(cube, {\n  bodyType: 'dynamic',\n  mass: 1,\n  restitution: 0.5, // bounce\n  friction: 0.3,\n});\nworld3d.setCollider(cube, {\n  shape: 'box',\n  size: { x: 1, y: 1, z: 1 },\n});\n\n// Make ground static\nworld3d.setRigidBody(ground, { bodyType: 'static' });\nworld3d.setCollider(ground, {\n  shape: 'box',\n  size: { x: 50, y: 0.5, z: 50 },\n});\n\n// Apply an impulse to launch the cube!\nworld3d.applyImpulse(cube, { x: 0, y: 10, z: 5 });",
            codeValidation: {
                containsAll: ['setRigidBody', 'setCollider', 'dynamic'],
            },
            hint: {
                en: "bodyType: 'dynamic' (movable), 'static' (fixed), 'kinematic' (scripted)",
                pl: "bodyType: 'dynamic' (ruchomy), 'static' (stały), 'kinematic' (skryptowy)",
                de: "bodyType: 'dynamic' (beweglich), 'static' (fest), 'kinematic' (geskriptet)",
            },
        },
        // S7: Character Controller
        {
            id: '3d-character',
            type: 'code',
            title: {
                en: '3D Character Controller',
                pl: 'Kontroler postaci 3D',
                de: '3D-Character-Controller',
            },
            content: {
                en: 'Use the `CharacterController3D` for a player that walks, jumps, and interacts with the physics world.',
                pl: 'Użyj `CharacterController3D` dla gracza, który chodzi, skacze i wchodzi w interakcję ze światem fizyki.',
                de: 'Verwende den `CharacterController3D` für einen Spieler, der läuft, springt und mit der Physikwelt interagiert.',
            },
            codeTemplate: '// 3D character controller\nconst charCtrl = ',
            codeSolution: "const charCtrl = {\n  moveSpeed: 5,\n  jumpForce: 8,\n  gravity: -20,\n  isGrounded: false,\n  velocityY: 0,\n  position: { x: 0, y: 1, z: 0 },\n};\n\nfunction updateCharacter(input: any, dt: number) {\n  // Movement on XZ plane\n  let moveX = 0, moveZ = 0;\n  if (input.getAction('moveForward')) moveZ -= 1;\n  if (input.getAction('moveBack')) moveZ += 1;\n  if (input.getAction('moveLeft')) moveX -= 1;\n  if (input.getAction('moveRight')) moveX += 1;\n\n  charCtrl.position.x += moveX * charCtrl.moveSpeed * dt;\n  charCtrl.position.z += moveZ * charCtrl.moveSpeed * dt;\n\n  // Gravity + jump\n  if (input.getAction('jump') && charCtrl.isGrounded) {\n    charCtrl.velocityY = charCtrl.jumpForce;\n  }\n  charCtrl.velocityY += charCtrl.gravity * dt;\n  charCtrl.position.y += charCtrl.velocityY * dt;\n\n  // Ground check\n  if (charCtrl.position.y <= 1) {\n    charCtrl.position.y = 1;\n    charCtrl.velocityY = 0;\n    charCtrl.isGrounded = true;\n  } else {\n    charCtrl.isGrounded = false;\n  }\n}",
            codeValidation: {
                containsAll: ['moveSpeed', 'jumpForce', 'gravity', 'isGrounded'],
            },
            hint: {
                en: 'Move on XZ plane, apply gravity on Y axis, ground check when y <= ground level.',
                pl: 'Ruszaj się na płaszczyźnie XZ, stosuj grawitację na osi Y, sprawdź podłoże gdy y <= poziom.',
                de: 'Bewegung auf XZ-Ebene, Gravitation auf Y-Achse, Bodenprüfung wenn y <= Bodenhöhe.',
            },
        },
        // S8: Checkpoint
        {
            id: '3d-complete',
            type: 'checkpoint',
            title: {
                en: '3D Game Complete! 🌟',
                pl: 'Gra 3D gotowa! 🌟',
                de: '3D-Spiel fertig! 🌟',
            },
            content: {
                en: 'You\'ve built your first 3D game!\n• World3D scene with multiple objects\n• Primitive meshes (cube, sphere, plane)\n• Directional and point lighting\n• Orbit camera controller\n• 3D physics with rigid bodies\n• Character controller with jumping\n\nChallenge: Add a skybox and third-person camera!',
                pl: 'Zbudowałeś swoją pierwszą grę 3D!\n• Scena World3D z wieloma obiektami\n• Prymitywne meshe (sześcian, sfera, płaszczyzna)\n• Oświetlenie kierunkowe i punktowe\n• Kontroler kamery orbitalnej\n• Fizyka 3D z ciałami sztywnymi\n• Kontroler postaci ze skakaniem\n\nWyzwanie: Dodaj skybox i kamerę trzeciej osoby!',
                de: 'Du hast dein erstes 3D-Spiel gebaut!\n• World3D-Szene mit mehreren Objekten\n• Primitive Meshes (Würfel, Kugel, Ebene)\n• Richtungs- und Punktbeleuchtung\n• Orbit-Kamera-Controller\n• 3D-Physik mit Starrkörpern\n• Character-Controller mit Springen\n\nHerausforderung: Füge eine Skybox und Third-Person-Kamera hinzu!',
            },
        },
    ],
};
/* ══════════════════════════════════════════════════════════════
   T15 — Publikacja gry
   ══════════════════════════════════════════════════════════════ */
const TUTORIAL_PUBLISHING = {
    id: 'publish-your-game',
    title: {
        en: 'Publish Your Game',
        pl: 'Publikacja gry',
        de: 'Dein Spiel veröffentlichen',
    },
    description: {
        en: 'Export your game as a PWA (web app), Electron desktop app, or Capacitor mobile app. Optimize, bundle, and deploy!',
        pl: 'Wyeksportuj swoją grę jako PWA (web app), aplikację Electron lub Capacitor. Zoptymalizuj, zbundluj i wdróż!',
        de: 'Exportiere dein Spiel als PWA (Web-App), Electron-Desktop-App oder Capacitor-Mobile-App. Optimiere, bundle und deploye!',
    },
    category: 'game-advanced',
    difficulty: 'intermediate',
    estimatedMinutes: 25,
    prerequisites: ['first-game-bouncing-ball'],
    kidFriendly: false,
    ageRange: { min: 14, max: 99 },
    tags: ['publish', 'export', 'pwa', 'electron', 'capacitor', 'deploy', 'build'],
    steps: [
        // S1: Intro
        {
            id: 'pub-intro',
            type: 'text',
            title: {
                en: 'Publish Your Game! 🚀',
                pl: 'Opublikuj swoją grę! 🚀',
                de: 'Veröffentliche dein Spiel! 🚀',
            },
            content: {
                en: 'Your game is ready — now let\'s share it with the world!\n\n• Feature detection (check browser support)\n• Build optimization (minify, tree-shake)\n• PWA export (installable web app)\n• Electron export (Windows/Mac/Linux)\n• Capacitor export (iOS/Android)\n• Performance benchmarking\n\nLet\'s deploy!',
                pl: 'Twoja gra jest gotowa — czas podzielić się nią ze światem!\n\n• Wykrywanie funkcji (sprawdź wsparcie przeglądarki)\n• Optymalizacja buildu (minifikacja, tree-shaking)\n• Eksport PWA (instalowalna web app)\n• Eksport Electron (Windows/Mac/Linux)\n• Eksport Capacitor (iOS/Android)\n• Benchmarkowanie wydajności\n\nWdrażamy!',
                de: 'Dein Spiel ist bereit — teile es mit der Welt!\n\n• Feature-Erkennung (Browser-Support)\n• Build-Optimierung (Minifizierung, Tree-Shaking)\n• PWA-Export (installierbare Web-App)\n• Electron-Export (Windows/Mac/Linux)\n• Capacitor-Export (iOS/Android)\n• Performance-Benchmarking\n\nLos geht\'s!',
            },
            skippable: true,
            tooltipPosition: 'center',
        },
        // S2: Feature Detection
        {
            id: 'pub-features',
            type: 'code',
            title: {
                en: 'Detect Browser Capabilities',
                pl: 'Wykryj możliwości przeglądarki',
                de: 'Browser-Fähigkeiten erkennen',
            },
            content: {
                en: 'Use `detectFeatures()` to check what the current browser supports before running your game.',
                pl: 'Użyj `detectFeatures()` aby sprawdzić, co obsługuje bieżąca przeglądarka przed uruchomieniem gry.',
                de: 'Verwende `detectFeatures()` um die Browser-Unterstützung vor dem Spielstart zu prüfen.',
            },
            codeTemplate: '// Check browser capabilities\nconst features = ',
            codeSolution: "const features = detectFeatures();\n\nconsole.log('WebGL:', features.webgl);\nconsole.log('WebGPU:', features.webgpu);\nconsole.log('WebAudio:', features.webAudio);\nconsole.log('Gamepad:', features.gamepad);\nconsole.log('Touch:', features.touch);\nconsole.log('WebRTC:', features.webrtc);\n\nif (!features.webgl) {\n  alert('Your browser does not support WebGL. Please use a modern browser.');\n}",
            codeValidation: {
                containsAll: ['detectFeatures', 'webgl'],
            },
            hint: {
                en: 'detectFeatures() returns an object with boolean capabilities',
                pl: 'detectFeatures() zwraca obiekt z boolowskimi możliwościami',
                de: 'detectFeatures() gibt ein Objekt mit booleschen Fähigkeiten zurück',
            },
        },
        // S3: Build Config
        {
            id: 'pub-build-config',
            type: 'code',
            title: {
                en: 'Configure Export Build',
                pl: 'Skonfiguruj build eksportu',
                de: 'Export-Build konfigurieren',
            },
            content: {
                en: 'Set up the export configuration for your target platform. Choose between web, PWA, Electron, or Capacitor.',
                pl: 'Skonfiguruj eksport dla docelowej platformy. Wybierz między web, PWA, Electron lub Capacitor.',
                de: 'Richte die Export-Konfiguration für deine Zielplattform ein. Wähle zwischen Web, PWA, Electron oder Capacitor.',
            },
            codeTemplate: '// Export configuration\nconst exportConfig = {\n',
            codeSolution: "const exportConfig = {\n  target: 'pwa',        // 'web' | 'pwa' | 'electron' | 'capacitor'\n  title: 'My Awesome Game',\n  version: '1.0.0',\n  minify: true,\n  treeShake: true,\n  splitChunks: true,\n  sourceMaps: false,\n  pwa: {\n    name: 'My Awesome Game',\n    shortName: 'AwesomeGame',\n    themeColor: '#1a1a2e',\n    backgroundColor: '#1a1a2e',\n    display: 'fullscreen',\n    orientation: 'landscape',\n    icons: [\n      { src: 'icon-192.png', sizes: '192x192' },\n      { src: 'icon-512.png', sizes: '512x512' },\n    ],\n  },\n};",
            codeValidation: {
                containsAll: ['target', 'minify', 'treeShake', 'pwa'],
            },
            hint: {
                en: "Set target to 'pwa' for installable web app with offline support",
                pl: "Ustaw target na 'pwa' dla instalowalnej web app z wsparciem offline",
                de: "Setze target auf 'pwa' für installierbare Web-App mit Offline-Support",
            },
        },
        // S4: Performance Benchmarking
        {
            id: 'pub-benchmark',
            type: 'code',
            title: {
                en: 'Benchmark Your Game',
                pl: 'Zbenchmarkuj swoją grę',
                de: 'Performance-Benchmark',
            },
            content: {
                en: 'Run performance benchmarks before publishing to ensure smooth gameplay. Measure FPS, frame times, and memory usage.',
                pl: 'Uruchom benchmarki wydajności przed publikacją, aby zapewnić płynną rozgrywkę. Mierz FPS, czasy klatek i użycie pamięci.',
                de: 'Führe Performance-Benchmarks vor der Veröffentlichung durch. Messe FPS, Frame-Zeiten und Speicherverbrauch.',
            },
            codeTemplate: '// Run performance benchmark\n',
            codeSolution: "// Measure core loop performance\nconst bench = createBenchmark('Game Loop', 1000);\n\n// Warm up (5 runs)\nbench.warmup(5);\n\n// Run benchmark\nbench.run(() => {\n  // Simulate one game frame\n  world.update(1 / 60);\n});\n\n// Get results\nconst results = bench.getResults();\nconsole.log(`Avg: ${results.avg.toFixed(2)}ms`);\nconsole.log(`Min: ${results.min.toFixed(2)}ms`);\nconsole.log(`Max: ${results.max.toFixed(2)}ms`);\nconsole.log(`Ops/sec: ${results.opsPerSecond.toFixed(0)}`);",
            codeValidation: {
                containsAll: ['createBenchmark', 'run', 'getResults'],
            },
            hint: {
                en: 'createBenchmark(name, iterations) → warmup → run → getResults',
                pl: 'createBenchmark(nazwa, iteracje) → warmup → run → getResults',
                de: 'createBenchmark(name, iterationen) → warmup → run → getResults',
            },
        },
        // S5: Deploy
        {
            id: 'pub-deploy',
            type: 'text',
            title: {
                en: 'Deploy Your Game',
                pl: 'Wdróż swoją grę',
                de: 'Spiel deployen',
            },
            content: {
                en: 'Your game is ready to deploy! Options:\n\n**Web / PWA** → Upload to any static hosting (Netlify, Vercel, GitHub Pages)\n\n**Electron** → Package for Windows (.exe), macOS (.dmg), Linux (.AppImage)\n\n**Capacitor** → Build for iOS (App Store) and Android (Google Play)\n\nAll exports use the same game code — no rewrites needed!',
                pl: 'Twoja gra jest gotowa do wdrożenia! Opcje:\n\n**Web / PWA** → Upload na dowolny hosting statyczny (Netlify, Vercel, GitHub Pages)\n\n**Electron** → Pakietowanie dla Windows (.exe), macOS (.dmg), Linux (.AppImage)\n\n**Capacitor** → Build dla iOS (App Store) i Android (Google Play)\n\nWszystkie eksporty używają tego samego kodu gry — bez przepisywania!',
                de: 'Dein Spiel ist bereit zum Deployen! Optionen:\n\n**Web / PWA** → Upload auf statisches Hosting (Netlify, Vercel, GitHub Pages)\n\n**Electron** → Verpacken für Windows (.exe), macOS (.dmg), Linux (.AppImage)\n\n**Capacitor** → Build für iOS (App Store) und Android (Google Play)\n\nAlle Exporte verwenden denselben Spielcode — kein Umschreiben nötig!',
            },
        },
        // S6: Quiz
        {
            id: 'pub-quiz',
            type: 'quiz',
            title: {
                en: 'Publishing Quiz 📦',
                pl: 'Quiz o publikacji 📦',
                de: 'Veröffentlichungs-Quiz 📦',
            },
            content: {
                en: 'What is a PWA (Progressive Web App)?',
                pl: 'Czym jest PWA (Progressive Web App)?',
                de: 'Was ist eine PWA (Progressive Web App)?',
            },
            quizOptions: [
                { id: 'a', text: { en: 'A native mobile app', pl: 'Natywna aplikacja mobilna', de: 'Eine native mobile App' } },
                { id: 'b', text: { en: 'A web app that can be installed and works offline', pl: 'Web app instalowalna i działająca offline', de: 'Eine Web-App die installierbar ist und offline funktioniert' } },
                { id: 'c', text: { en: 'A special browser plugin', pl: 'Specjalna wtyczka przeglądarki', de: 'Ein spezielles Browser-Plugin' } },
                { id: 'd', text: { en: 'A server-side application', pl: 'Aplikacja serwerowa', de: 'Eine serverseitige Anwendung' } },
            ],
            quizCorrectId: 'b',
        },
        // S7: Checkpoint
        {
            id: 'pub-complete',
            type: 'checkpoint',
            title: {
                en: 'Publication Complete! 🎊',
                pl: 'Publikacja gotowa! 🎊',
                de: 'Veröffentlichung fertig! 🎊',
            },
            content: {
                en: 'Congratulations! You now know how to:\n• Check browser feature support\n• Configure optimized builds\n• Export as PWA, Electron, or Capacitor\n• Run performance benchmarks\n• Deploy to web, desktop, and mobile\n\nYour game is ready for the world! 🌍',
                pl: 'Gratulacje! Teraz wiesz jak:\n• Sprawdzić wsparcie funkcji przeglądarki\n• Konfigurować zoptymalizowane buildy\n• Eksportować jako PWA, Electron lub Capacitor\n• Uruchamiać benchmarki wydajności\n• Wdrażać na web, desktop i mobile\n\nTwoja gra jest gotowa na świat! 🌍',
                de: 'Herzlichen Glückwunsch! Du weißt jetzt wie man:\n• Browser-Feature-Support prüft\n• Optimierte Builds konfiguriert\n• Als PWA, Electron oder Capacitor exportiert\n• Performance-Benchmarks durchführt\n• Auf Web, Desktop und Mobile deployt\n\nDein Spiel ist bereit für die Welt! 🌍',
            },
        },
    ],
};
/* ══════════════════════════════════════════════════════════════
   Convenience export
   ══════════════════════════════════════════════════════════════ */
function getTutorials_T12_T15() {
    return [
        TUTORIAL_RPG,
        TUTORIAL_TOWER_DEFENSE,
        TUTORIAL_3D_GAME,
        TUTORIAL_PUBLISHING,
    ];
}

export { TUTORIAL_3D_GAME, TUTORIAL_PUBLISHING, TUTORIAL_RPG, TUTORIAL_TOWER_DEFENSE, getTutorials_T12_T15 };
//# sourceMappingURL=Tutorials_T12_T15.js.map
