Pokelike Save Editor

Advanced save editor

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name         Pokelike Save Editor
// @namespace    http://tampermonkey.net/
// @version      2.3.1
// @description  Advanced save editor
// @match        https://pokelike.xyz/*
// @grant        none
// @run-at       document-idle
// @license      MIT
// ==/UserScript==

(function () {
  'use strict';

  // ─── State ───────────────────────────────────────────────────────────────────
  const STATE = {
    currentView: 'home',
    searchQuery: '',
    editingHofIndex: null,
    editingTeamIndex: null,
  };

  // ─── Pokemon Data ────────────────────────────────────────────────────────────
  const POKEMON_LIST = [
    { id: 1, name: 'Bulbasaur' }, { id: 2, name: 'Ivysaur' }, { id: 3, name: 'Venusaur' },
    { id: 4, name: 'Charmander' }, { id: 5, name: 'Charmeleon' }, { id: 6, name: 'Charizard' },
    { id: 7, name: 'Squirtle' }, { id: 8, name: 'Wartortle' }, { id: 9, name: 'Blastoise' },
    { id: 10, name: 'Caterpie' }, { id: 11, name: 'Metapod' }, { id: 12, name: 'Butterfree' },
    { id: 13, name: 'Weedle' }, { id: 14, name: 'Kakuna' }, { id: 15, name: 'Beedrill' },
    { id: 16, name: 'Pidgey' }, { id: 17, name: 'Pidgeotto' }, { id: 18, name: 'Pidgeot' },
    { id: 19, name: 'Rattata' }, { id: 20, name: 'Raticate' }, { id: 21, name: 'Spearow' },
    { id: 22, name: 'Fearow' }, { id: 23, name: 'Ekans' }, { id: 24, name: 'Arbok' },
    { id: 25, name: 'Pikachu' }, { id: 26, name: 'Raichu' }, { id: 27, name: 'Sandshrew' },
    { id: 28, name: 'Sandslash' }, { id: 29, name: 'Nidoran-f' }, { id: 30, name: 'Nidorina' },
    { id: 31, name: 'Nidoqueen' }, { id: 32, name: 'Nidoran-m' }, { id: 33, name: 'Nidorino' },
    { id: 34, name: 'Nidoking' }, { id: 35, name: 'Clefairy' }, { id: 36, name: 'Clefable' },
    { id: 37, name: 'Vulpix' }, { id: 38, name: 'Ninetales' }, { id: 39, name: 'Jigglypuff' },
    { id: 40, name: 'Wigglytuff' }, { id: 41, name: 'Zubat' }, { id: 42, name: 'Golbat' },
    { id: 43, name: 'Oddish' }, { id: 44, name: 'Gloom' }, { id: 45, name: 'Vileplume' },
    { id: 46, name: 'Paras' }, { id: 47, name: 'Parasect' }, { id: 48, name: 'Venonat' },
    { id: 49, name: 'Venomoth' }, { id: 50, name: 'Diglett' }, { id: 51, name: 'Dugtrio' },
    { id: 52, name: 'Meowth' }, { id: 53, name: 'Persian' }, { id: 54, name: 'Psyduck' },
    { id: 55, name: 'Golduck' }, { id: 56, name: 'Mankey' }, { id: 57, name: 'Primeape' },
    { id: 58, name: 'Growlithe' }, { id: 59, name: 'Arcanine' }, { id: 60, name: 'Poliwag' },
    { id: 61, name: 'Poliwhirl' }, { id: 62, name: 'Poliwrath' }, { id: 63, name: 'Abra' },
    { id: 64, name: 'Kadabra' }, { id: 65, name: 'Alakazam' }, { id: 66, name: 'Machop' },
    { id: 67, name: 'Machoke' }, { id: 68, name: 'Machamp' }, { id: 69, name: 'Bellsprout' },
    { id: 70, name: 'Weepinbell' }, { id: 71, name: 'Victreebel' }, { id: 72, name: 'Tentacool' },
    { id: 73, name: 'Tentacruel' }, { id: 74, name: 'Geodude' }, { id: 75, name: 'Graveler' },
    { id: 76, name: 'Golem' }, { id: 77, name: 'Ponyta' }, { id: 78, name: 'Rapidash' },
    { id: 79, name: 'Slowpoke' }, { id: 80, name: 'Slowbro' }, { id: 81, name: 'Magnemite' },
    { id: 82, name: 'Magneton' }, { id: 83, name: 'Farfetchd' }, { id: 84, name: 'Doduo' },
    { id: 85, name: 'Dodrio' }, { id: 86, name: 'Seel' }, { id: 87, name: 'Dewgong' },
    { id: 88, name: 'Grimer' }, { id: 89, name: 'Muk' }, { id: 90, name: 'Shellder' },
    { id: 91, name: 'Cloyster' }, { id: 92, name: 'Gastly' }, { id: 93, name: 'Haunter' },
    { id: 94, name: 'Gengar' }, { id: 95, name: 'Onix' }, { id: 96, name: 'Drowzee' },
    { id: 97, name: 'Hypno' }, { id: 98, name: 'Krabby' }, { id: 99, name: 'Kingler' },
    { id: 100, name: 'Voltorb' }, { id: 101, name: 'Electrode' }, { id: 102, name: 'Exeggcute' },
    { id: 103, name: 'Exeggutor' }, { id: 104, name: 'Cubone' }, { id: 105, name: 'Marowak' },
    { id: 106, name: 'Hitmonlee' }, { id: 107, name: 'Hitmonchan' }, { id: 108, name: 'Lickitung' },
    { id: 109, name: 'Koffing' }, { id: 110, name: 'Weezing' }, { id: 111, name: 'Rhyhorn' },
    { id: 112, name: 'Rhydon' }, { id: 113, name: 'Chansey' }, { id: 114, name: 'Tangela' },
    { id: 115, name: 'Kangaskhan' }, { id: 116, name: 'Horsea' }, { id: 117, name: 'Seadra' },
    { id: 118, name: 'Goldeen' }, { id: 119, name: 'Seaking' }, { id: 120, name: 'Staryu' },
    { id: 121, name: 'Starmie' }, { id: 122, name: 'Mr-mime' }, { id: 123, name: 'Scyther' },
    { id: 124, name: 'Jynx' }, { id: 125, name: 'Electabuzz' }, { id: 126, name: 'Magmar' },
    { id: 127, name: 'Pinsir' }, { id: 128, name: 'Tauros' }, { id: 129, name: 'Magikarp' },
    { id: 130, name: 'Gyarados' }, { id: 131, name: 'Lapras' }, { id: 132, name: 'Ditto' },
    { id: 133, name: 'Eevee' }, { id: 134, name: 'Vaporeon' }, { id: 135, name: 'Jolteon' },
    { id: 136, name: 'Flareon' }, { id: 137, name: 'Porygon' }, { id: 138, name: 'Omanyte' },
    { id: 139, name: 'Omastar' }, { id: 140, name: 'Kabuto' }, { id: 141, name: 'Kabutops' },
    { id: 142, name: 'Aerodactyl' }, { id: 143, name: 'Snorlax' }, { id: 144, name: 'Articuno' },
    { id: 145, name: 'Zapdos' }, { id: 146, name: 'Moltres' }, { id: 147, name: 'Dratini' },
    { id: 148, name: 'Dragonair' }, { id: 149, name: 'Dragonite' }, { id: 150, name: 'Mewtwo' },
    { id: 151, name: 'Mew' },
    // Gen 2
    { id: 152, name: 'Chikorita' }, { id: 153, name: 'Bayleef' }, { id: 154, name: 'Meganium' },
    { id: 155, name: 'Cyndaquil' }, { id: 156, name: 'Quilava' }, { id: 157, name: 'Typhlosion' },
    { id: 158, name: 'Totodile' }, { id: 159, name: 'Croconaw' }, { id: 160, name: 'Feraligatr' },
    { id: 161, name: 'Sentret' }, { id: 162, name: 'Furret' }, { id: 163, name: 'Hoothoot' },
    { id: 164, name: 'Noctowl' }, { id: 165, name: 'Ledyba' }, { id: 166, name: 'Ledian' },
    { id: 167, name: 'Spinarak' }, { id: 168, name: 'Ariados' }, { id: 169, name: 'Crobat' },
    { id: 170, name: 'Chinchou' }, { id: 171, name: 'Lanturn' }, { id: 172, name: 'Pichu' },
    { id: 173, name: 'Cleffa' }, { id: 174, name: 'Igglybuff' }, { id: 175, name: 'Togepi' },
    { id: 176, name: 'Togetic' }, { id: 177, name: 'Natu' }, { id: 178, name: 'Xatu' },
    { id: 179, name: 'Mareep' }, { id: 180, name: 'Flaaffy' }, { id: 181, name: 'Ampharos' },
    { id: 182, name: 'Bellossom' }, { id: 183, name: 'Marill' }, { id: 184, name: 'Azumarill' },
    { id: 185, name: 'Sudowoodo' }, { id: 186, name: 'Politoed' }, { id: 187, name: 'Hoppip' },
    { id: 188, name: 'Skiploom' }, { id: 189, name: 'Jumpluff' }, { id: 190, name: 'Aipom' },
    { id: 191, name: 'Sunkern' }, { id: 192, name: 'Sunflora' }, { id: 193, name: 'Yanma' },
    { id: 194, name: 'Wooper' }, { id: 195, name: 'Quagsire' }, { id: 196, name: 'Espeon' },
    { id: 197, name: 'Umbreon' }, { id: 198, name: 'Murkrow' }, { id: 199, name: 'Slowking' },
    { id: 200, name: 'Misdreavus' }, { id: 201, name: 'Unown' }, { id: 202, name: 'Wobbuffet' },
    { id: 203, name: 'Girafarig' }, { id: 204, name: 'Pineco' }, { id: 205, name: 'Forretress' },
    { id: 206, name: 'Dunsparce' }, { id: 207, name: 'Gligar' }, { id: 208, name: 'Steelix' },
    { id: 209, name: 'Snubbull' }, { id: 210, name: 'Granbull' }, { id: 211, name: 'Qwilfish' },
    { id: 212, name: 'Scizor' }, { id: 213, name: 'Shuckle' }, { id: 214, name: 'Heracross' },
    { id: 215, name: 'Sneasel' }, { id: 216, name: 'Teddiursa' }, { id: 217, name: 'Ursaring' },
    { id: 218, name: 'Slugma' }, { id: 219, name: 'Magcargo' }, { id: 220, name: 'Swinub' },
    { id: 221, name: 'Piloswine' }, { id: 222, name: 'Corsola' }, { id: 223, name: 'Remoraid' },
    { id: 224, name: 'Octillery' }, { id: 225, name: 'Delibird' }, { id: 226, name: 'Mantine' },
    { id: 227, name: 'Skarmory' }, { id: 228, name: 'Houndour' }, { id: 229, name: 'Houndoom' },
    { id: 230, name: 'Kingdra' }, { id: 231, name: 'Phanpy' }, { id: 232, name: 'Donphan' },
    { id: 233, name: 'Porygon2' }, { id: 234, name: 'Stantler' }, { id: 235, name: 'Smeargle' },
    { id: 236, name: 'Tyrogue' }, { id: 237, name: 'Hitmontop' }, { id: 238, name: 'Smoochum' },
    { id: 239, name: 'Elekid' }, { id: 240, name: 'Magby' }, { id: 241, name: 'Miltank' },
    { id: 242, name: 'Blissey' }, { id: 243, name: 'Raikou' }, { id: 244, name: 'Entei' },
    { id: 245, name: 'Suicune' }, { id: 246, name: 'Larvitar' }, { id: 247, name: 'Pupitar' },
    { id: 248, name: 'Tyranitar' }, { id: 249, name: 'Lugia' }, { id: 250, name: 'Ho-oh' },
    { id: 251, name: 'Celebi' },
    // Gen 3
    { id: 252, name: 'Treecko' }, { id: 253, name: 'Grovyle' }, { id: 254, name: 'Sceptile' },
    { id: 255, name: 'Torchic' }, { id: 256, name: 'Combusken' }, { id: 257, name: 'Blaziken' },
    { id: 258, name: 'Mudkip' }, { id: 259, name: 'Marshtomp' }, { id: 260, name: 'Swampert' },
    { id: 261, name: 'Poochyena' }, { id: 262, name: 'Mightyena' }, { id: 263, name: 'Zigzagoon' },
    { id: 264, name: 'Linoone' }, { id: 265, name: 'Wurmple' }, { id: 266, name: 'Silcoon' },
    { id: 267, name: 'Beautifly' }, { id: 268, name: 'Cascoon' }, { id: 269, name: 'Dustox' },
    { id: 270, name: 'Lotad' }, { id: 271, name: 'Lombre' }, { id: 272, name: 'Ludicolo' },
    { id: 273, name: 'Seedot' }, { id: 274, name: 'Nuzleaf' }, { id: 275, name: 'Shiftry' },
    { id: 276, name: 'Taillow' }, { id: 277, name: 'Swellow' }, { id: 278, name: 'Wingull' },
    { id: 279, name: 'Pelipper' }, { id: 280, name: 'Ralts' }, { id: 281, name: 'Kirlia' },
    { id: 282, name: 'Gardevoir' }, { id: 283, name: 'Surskit' }, { id: 284, name: 'Masquerain' },
    { id: 285, name: 'Shroomish' }, { id: 286, name: 'Breloom' }, { id: 287, name: 'Slakoth' },
    { id: 288, name: 'Vigoroth' }, { id: 289, name: 'Slaking' }, { id: 290, name: 'Nincada' },
    { id: 291, name: 'Ninjask' }, { id: 292, name: 'Shedinja' }, { id: 293, name: 'Whismur' },
    { id: 294, name: 'Loudred' }, { id: 295, name: 'Exploud' }, { id: 296, name: 'Makuhita' },
    { id: 297, name: 'Hariyama' }, { id: 298, name: 'Azurill' }, { id: 299, name: 'Nosepass' },
    { id: 300, name: 'Skitty' }, { id: 301, name: 'Delcatty' }, { id: 302, name: 'Sableye' },
    { id: 303, name: 'Mawile' }, { id: 304, name: 'Aron' }, { id: 305, name: 'Lairon' },
    { id: 306, name: 'Aggron' }, { id: 307, name: 'Meditite' }, { id: 308, name: 'Medicham' },
    { id: 309, name: 'Electrike' }, { id: 310, name: 'Manectric' }, { id: 311, name: 'Plusle' },
    { id: 312, name: 'Minun' }, { id: 313, name: 'Volbeat' }, { id: 314, name: 'Illumise' },
    { id: 315, name: 'Roselia' }, { id: 316, name: 'Gulpin' }, { id: 317, name: 'Swalot' },
    { id: 318, name: 'Carvanha' }, { id: 319, name: 'Sharpedo' }, { id: 320, name: 'Wailmer' },
    { id: 321, name: 'Wailord' }, { id: 322, name: 'Numel' }, { id: 323, name: 'Camerupt' },
    { id: 324, name: 'Torkoal' }, { id: 325, name: 'Spoink' }, { id: 326, name: 'Grumpig' },
    { id: 327, name: 'Spinda' }, { id: 328, name: 'Trapinch' }, { id: 329, name: 'Vibrava' },
    { id: 330, name: 'Flygon' }, { id: 331, name: 'Cacnea' }, { id: 332, name: 'Cacturne' },
    { id: 333, name: 'Swablu' }, { id: 334, name: 'Altaria' }, { id: 335, name: 'Zangoose' },
    { id: 336, name: 'Seviper' }, { id: 337, name: 'Lunatone' }, { id: 338, name: 'Solrock' },
    { id: 339, name: 'Barboach' }, { id: 340, name: 'Whiscash' }, { id: 341, name: 'Corphish' },
    { id: 342, name: 'Crawdaunt' }, { id: 343, name: 'Baltoy' }, { id: 344, name: 'Claydol' },
    { id: 345, name: 'Lileep' }, { id: 346, name: 'Cradily' }, { id: 347, name: 'Anorith' },
    { id: 348, name: 'Armaldo' }, { id: 349, name: 'Feebas' }, { id: 350, name: 'Milotic' },
    { id: 351, name: 'Castform' }, { id: 352, name: 'Kecleon' }, { id: 353, name: 'Shuppet' },
    { id: 354, name: 'Banette' }, { id: 355, name: 'Duskull' }, { id: 356, name: 'Dusclops' },
    { id: 357, name: 'Tropius' }, { id: 358, name: 'Chimecho' }, { id: 359, name: 'Absol' },
    { id: 360, name: 'Wynaut' }, { id: 361, name: 'Snorunt' }, { id: 362, name: 'Glalie' },
    { id: 363, name: 'Spheal' }, { id: 364, name: 'Sealeo' }, { id: 365, name: 'Walrein' },
    { id: 366, name: 'Clamperl' }, { id: 367, name: 'Huntail' }, { id: 368, name: 'Gorebyss' },
    { id: 369, name: 'Relicanth' }, { id: 370, name: 'Luvdisc' }, { id: 371, name: 'Bagon' },
    { id: 372, name: 'Shelgon' }, { id: 373, name: 'Salamence' }, { id: 374, name: 'Beldum' },
    { id: 375, name: 'Metang' }, { id: 376, name: 'Metagross' }, { id: 377, name: 'Regirock' },
    { id: 378, name: 'Regice' }, { id: 379, name: 'Registeel' }, { id: 380, name: 'Latias' },
    { id: 381, name: 'Latios' }, { id: 382, name: 'Kyogre' }, { id: 383, name: 'Groudon' },
    { id: 384, name: 'Rayquaza' }, { id: 385, name: 'Jirachi' }, { id: 386, name: 'Deoxys' },
    // Gen 4
    { id: 387, name: 'Turtwig' }, { id: 388, name: 'Grotle' }, { id: 389, name: 'Torterra' },
    { id: 390, name: 'Chimchar' }, { id: 391, name: 'Monferno' }, { id: 392, name: 'Infernape' },
    { id: 393, name: 'Piplup' }, { id: 394, name: 'Prinplup' }, { id: 395, name: 'Empoleon' },
    { id: 396, name: 'Starly' }, { id: 397, name: 'Staravia' }, { id: 398, name: 'Staraptor' },
    { id: 399, name: 'Bidoof' }, { id: 400, name: 'Bibarel' }, { id: 401, name: 'Kricketot' },
    { id: 402, name: 'Kricketune' }, { id: 403, name: 'Shinx' }, { id: 404, name: 'Luxio' },
    { id: 405, name: 'Luxray' }, { id: 406, name: 'Budew' }, { id: 407, name: 'Roserade' },
    { id: 408, name: 'Cranidos' }, { id: 409, name: 'Rampardos' }, { id: 410, name: 'Shieldon' },
    { id: 411, name: 'Bastiodon' }, { id: 412, name: 'Burmy' }, { id: 413, name: 'Wormadam' },
    { id: 414, name: 'Mothim' }, { id: 415, name: 'Combee' }, { id: 416, name: 'Vespiquen' },
    { id: 417, name: 'Pachirisu' }, { id: 418, name: 'Buizel' }, { id: 419, name: 'Floatzel' },
    { id: 420, name: 'Cherubi' }, { id: 421, name: 'Cherrim' }, { id: 422, name: 'Shellos' },
    { id: 423, name: 'Gastrodon' }, { id: 424, name: 'Ambipom' }, { id: 425, name: 'Drifloon' },
    { id: 426, name: 'Drifblim' }, { id: 427, name: 'Buneary' }, { id: 428, name: 'Lopunny' },
    { id: 429, name: 'Mismagius' }, { id: 430, name: 'Honchkrow' }, { id: 431, name: 'Glameow' },
    { id: 432, name: 'Purugly' }, { id: 433, name: 'Chingling' }, { id: 434, name: 'Stunky' },
    { id: 435, name: 'Skuntank' }, { id: 436, name: 'Bronzor' }, { id: 437, name: 'Bronzong' },
    { id: 438, name: 'Bonsly' }, { id: 439, name: 'Mime-jr' }, { id: 440, name: 'Happiny' },
    { id: 441, name: 'Chatot' }, { id: 442, name: 'Spiritomb' }, { id: 443, name: 'Gible' },
    { id: 444, name: 'Gabite' }, { id: 445, name: 'Garchomp' }, { id: 446, name: 'Munchlax' },
    { id: 447, name: 'Riolu' }, { id: 448, name: 'Lucario' }, { id: 449, name: 'Hippopotas' },
    { id: 450, name: 'Hippowdon' }, { id: 451, name: 'Skorupi' }, { id: 452, name: 'Drapion' },
    { id: 453, name: 'Croagunk' }, { id: 454, name: 'Toxicroak' }, { id: 455, name: 'Carnivine' },
    { id: 456, name: 'Finneon' }, { id: 457, name: 'Lumineon' }, { id: 458, name: 'Mantyke' },
    { id: 459, name: 'Snover' }, { id: 460, name: 'Abomasnow' }, { id: 461, name: 'Weavile' },
    { id: 462, name: 'Magnezone' }, { id: 463, name: 'Lickilicky' }, { id: 464, name: 'Rhyperior' },
    { id: 465, name: 'Tangrowth' }, { id: 466, name: 'Electivire' }, { id: 467, name: 'Magmortar' },
    { id: 468, name: 'Togekiss' }, { id: 469, name: 'Yanmega' }, { id: 470, name: 'Leafeon' },
    { id: 471, name: 'Glaceon' }, { id: 472, name: 'Gliscor' }, { id: 473, name: 'Mamoswine' },
    { id: 474, name: 'Porygon-z' }, { id: 475, name: 'Gallade' }, { id: 476, name: 'Probopass' },
    { id: 477, name: 'Dusknoir' }, { id: 478, name: 'Froslass' }, { id: 479, name: 'Rotom' },
    { id: 480, name: 'Uxie' }, { id: 481, name: 'Mesprit' }, { id: 482, name: 'Azelf' },
    { id: 483, name: 'Dialga' }, { id: 484, name: 'Palkia' }, { id: 485, name: 'Heatran' },
    { id: 486, name: 'Regigigas' }, { id: 487, name: 'Giratina' }, { id: 488, name: 'Cresselia' },
    { id: 489, name: 'Phione' }, { id: 490, name: 'Manaphy' }, { id: 491, name: 'Darkrai' },
    { id: 492, name: 'Shaymin' }, { id: 493, name: 'Arceus' },
    // Gen 5
    { id: 494, name: 'Victini' }, { id: 495, name: 'Snivy' }, { id: 496, name: 'Servine' },
    { id: 497, name: 'Serperior' }, { id: 498, name: 'Tepig' }, { id: 499, name: 'Pignite' },
    { id: 500, name: 'Emboar' }, { id: 501, name: 'Oshawott' }, { id: 502, name: 'Dewott' },
    { id: 503, name: 'Samurott' }, { id: 504, name: 'Patrat' }, { id: 505, name: 'Watchog' },
    { id: 506, name: 'Lillipup' }, { id: 507, name: 'Herdier' }, { id: 508, name: 'Stoutland' },
    { id: 509, name: 'Purrloin' }, { id: 510, name: 'Liepard' }, { id: 511, name: 'Pansage' },
    { id: 512, name: 'Simisage' }, { id: 513, name: 'Pansear' }, { id: 514, name: 'Simisear' },
    { id: 515, name: 'Panpour' }, { id: 516, name: 'Simipour' }, { id: 517, name: 'Munna' },
    { id: 518, name: 'Musharna' }, { id: 519, name: 'Pidove' }, { id: 520, name: 'Tranquill' },
    { id: 521, name: 'Unfezant' }, { id: 522, name: 'Blitzle' }, { id: 523, name: 'Zebstrika' },
    { id: 524, name: 'Roggenrola' }, { id: 525, name: 'Boldore' }, { id: 526, name: 'Gigalith' },
    { id: 527, name: 'Woobat' }, { id: 528, name: 'Swoobat' }, { id: 529, name: 'Drilbur' },
    { id: 530, name: 'Excadrill' }, { id: 531, name: 'Audino' }, { id: 532, name: 'Timburr' },
    { id: 533, name: 'Gurdurr' }, { id: 534, name: 'Conkeldurr' }, { id: 535, name: 'Tympole' },
    { id: 536, name: 'Palpitoad' }, { id: 537, name: 'Seismitoad' }, { id: 538, name: 'Throh' },
    { id: 539, name: 'Sawk' }, { id: 540, name: 'Sewaddle' }, { id: 541, name: 'Swadloon' },
    { id: 542, name: 'Leavanny' }, { id: 543, name: 'Venipede' }, { id: 544, name: 'Whirlipede' },
    { id: 545, name: 'Scolipede' }, { id: 546, name: 'Cottonee' }, { id: 547, name: 'Whimsicott' },
    { id: 548, name: 'Petilil' }, { id: 549, name: 'Lilligant' }, { id: 550, name: 'Basculin' },
    { id: 551, name: 'Sandile' }, { id: 552, name: 'Krokorok' }, { id: 553, name: 'Krookodile' },
    { id: 554, name: 'Darumaka' }, { id: 555, name: 'Darmanitan' }, { id: 556, name: 'Maractus' },
    { id: 557, name: 'Dwebble' }, { id: 558, name: 'Crustle' }, { id: 559, name: 'Scraggy' },
    { id: 560, name: 'Scrafty' }, { id: 561, name: 'Sigilyph' }, { id: 562, name: 'Yamask' },
    { id: 563, name: 'Cofagrigus' }, { id: 564, name: 'Tirtouga' }, { id: 565, name: 'Carracosta' },
    { id: 566, name: 'Archen' }, { id: 567, name: 'Archeops' }, { id: 568, name: 'Trubbish' },
    { id: 569, name: 'Garbodor' }, { id: 570, name: 'Zorua' }, { id: 571, name: 'Zoroark' },
    { id: 572, name: 'Minccino' }, { id: 573, name: 'Cinccino' }, { id: 574, name: 'Gothita' },
    { id: 575, name: 'Gothorita' }, { id: 576, name: 'Gothitelle' }, { id: 577, name: 'Solosis' },
    { id: 578, name: 'Duosion' }, { id: 579, name: 'Reuniclus' }, { id: 580, name: 'Ducklett' },
    { id: 581, name: 'Swanna' }, { id: 582, name: 'Vanillite' }, { id: 583, name: 'Vanillish' },
    { id: 584, name: 'Vanilluxe' }, { id: 585, name: 'Deerling' }, { id: 586, name: 'Sawsbuck' },
    { id: 587, name: 'Emolga' }, { id: 588, name: 'Karrablast' }, { id: 589, name: 'Escavalier' },
    { id: 590, name: 'Foongus' }, { id: 591, name: 'Amoonguss' }, { id: 592, name: 'Frillish' },
    { id: 593, name: 'Jellicent' }, { id: 594, name: 'Alomomola' }, { id: 595, name: 'Joltik' },
    { id: 596, name: 'Galvantula' }, { id: 597, name: 'Ferroseed' }, { id: 598, name: 'Ferrothorn' },
    { id: 599, name: 'Klink' }, { id: 600, name: 'Klang' }, { id: 601, name: 'Klinklang' },
    { id: 602, name: 'Tynamo' }, { id: 603, name: 'Eelektrik' }, { id: 604, name: 'Eelektross' },
    { id: 605, name: 'Elgyem' }, { id: 606, name: 'Beheeyem' }, { id: 607, name: 'Litwick' },
    { id: 608, name: 'Lampent' }, { id: 609, name: 'Chandelure' }, { id: 610, name: 'Axew' },
    { id: 611, name: 'Fraxure' }, { id: 612, name: 'Haxorus' }, { id: 613, name: 'Cubchoo' },
    { id: 614, name: 'Beartic' }, { id: 615, name: 'Cryogonal' }, { id: 616, name: 'Shelmet' },
    { id: 617, name: 'Accelgor' }, { id: 618, name: 'Stunfisk' }, { id: 619, name: 'Mienfoo' },
    { id: 620, name: 'Mienshao' }, { id: 621, name: 'Druddigon' }, { id: 622, name: 'Golett' },
    { id: 623, name: 'Golurk' }, { id: 624, name: 'Pawniard' }, { id: 625, name: 'Bisharp' },
    { id: 626, name: 'Bouffalant' }, { id: 627, name: 'Rufflet' }, { id: 628, name: 'Braviary' },
    { id: 629, name: 'Vullaby' }, { id: 630, name: 'Mandibuzz' }, { id: 631, name: 'Heatmor' },
    { id: 632, name: 'Durant' }, { id: 633, name: 'Deino' }, { id: 634, name: 'Zweilous' },
    { id: 635, name: 'Hydreigon' }, { id: 636, name: 'Larvesta' }, { id: 637, name: 'Volcarona' },
    { id: 638, name: 'Cobalion' }, { id: 639, name: 'Terrakion' }, { id: 640, name: 'Virizion' },
    { id: 641, name: 'Tornadus' }, { id: 642, name: 'Thundurus' }, { id: 643, name: 'Reshiram' },
    { id: 644, name: 'Zekrom' }, { id: 645, name: 'Landorus' }, { id: 646, name: 'Kyurem' },
    { id: 647, name: 'Keldeo' }, { id: 648, name: 'Meloetta' }, { id: 649, name: 'Genesect' },
  ];

  const ITEMS = [
    // Stat boost items
    { id: 'choice_band', name: 'Choice Band', icon: '🎀', desc: '+40% physical damage, -20% DEF' },
    { id: 'choice_specs', name: 'Choice Specs', icon: '👓', desc: '+40% special damage, -20% Sp.Def' },
    { id: 'wise_glasses', name: 'Wise Glasses', icon: '🔬', desc: '+20% special damage' },
    { id: 'muscle_band', name: 'Muscle Band', icon: '💪', desc: '+20% physical damage' },
    { id: 'eviolite', name: 'Eviolite', icon: '💎', desc: '+50% DEF & Sp.Def if holder is not fully evolved' },
    { id: 'lucky_egg', name: 'Lucky Egg', icon: '🥚', desc: '30% chance: holder gains +1 extra level after each battle', minMap: 4 },
    { id: 'scope_lens', name: 'Scope Lens', icon: '🔭', desc: '20% crit chance (+50% damage on crit)' },
    { id: 'life_orb', name: 'Life Orb', icon: '🔮', desc: '+30% damage on all moves' },
    { id: 'rocky_helmet', name: 'Rocky Helmet', icon: '⛑️', desc: 'Attacker takes 12% of their max HP on each hit' },
    { id: 'shell_bell', name: 'Shell Bell', icon: '🐚', desc: 'Heal 15% of damage dealt' },
    // Type-boosting items
    { id: 'sharp_beak', name: 'Sharp Beak', icon: '🦅', desc: '+50% Flying move damage' },
    { id: 'charcoal', name: 'Charcoal', icon: '🔥', desc: '+50% Fire move damage' },
    { id: 'mystic_water', name: 'Mystic Water', icon: '💧', desc: '+50% Water move damage' },
    { id: 'magnet', name: 'Magnet', icon: '🧲', desc: '+50% Electric move damage', minMap: 4 },
    { id: 'miracle_seed', name: 'Miracle Seed', icon: '🌱', desc: '+50% Grass move damage' },
    { id: 'twisted_spoon', name: 'Twisted Spoon', icon: '🥄', desc: '+50% Psychic move damage', minMap: 4 },
    { id: 'black_belt', name: 'Black Belt', icon: '🥋', desc: '+50% Fighting move damage' },
    { id: 'soft_sand', name: 'Soft Sand', icon: '🏖️', desc: '+50% Ground move damage', minMap: 4 },
    { id: 'silver_powder', name: 'Silver Powder', icon: '🐛', desc: '+50% Bug move damage' },
    { id: 'hard_stone', name: 'Hard Stone', icon: '🪨', desc: '+50% Rock move damage', minMap: 4 },
    { id: 'dragon_fang', name: 'Dragon Fang', icon: '🐉', desc: '+50% Dragon move damage', minMap: 6 },
    { id: 'poison_barb', name: 'Poison Barb', icon: '☠️', desc: '+50% Poison move damage', minMap: 4 },
    { id: 'spell_tag', name: 'Spell Tag', icon: '👻', desc: '+50% Ghost move damage', minMap: 4 },
    { id: 'silk_scarf', name: 'Silk Scarf', icon: '🤍', desc: '+50% Normal move damage' },
    // Stat items
    { id: 'assault_vest', name: 'Assault Vest', icon: '🦺', desc: '+50% Sp.Def' },
    { id: 'choice_scarf', name: 'Choice Scarf', icon: '🧣', desc: '+50% Speed' },
    // Battle effect items
    { id: 'leftovers', name: 'Leftovers', icon: '🍃', desc: 'Restore 10% max HP each round' },
    { id: 'expert_belt', name: 'Expert Belt', icon: '🥊', desc: '+30% damage on super effective hits' },
    { id: 'focus_band', name: 'Focus Band', icon: '🩹', desc: '20% chance to survive a KO with 1 HP' },
    { id: 'focus_sash', name: 'Focus Sash', icon: '🎗️', desc: 'If at full HP, guaranteed to survive any hit with 1 HP' },
    { id: 'wide_lens', name: 'Wide Lens', icon: '🔎', desc: '+20% damage on all moves' },
    { id: 'air_balloon', name: 'Air Balloon', icon: '🎈', desc: 'Immune to Ground-type moves' },
  ];

  // ─── Evolution Data & Helper ─────────────────────────────────────────────────
  // Legendary Pokemon (excluded from Battle Tower starters)
  const LEGENDARY_IDS = [
    144,145,146,150,151,                                             // Gen 1: Articuno, Zapdos, Moltres, Mewtwo, Mew
    243,244,245,249,250,251,                                         // Gen 2: Raikou, Entei, Suicune, Lugia, Ho-oh, Celebi
    377,378,379,380,381,382,383,384,385,386,                         // Gen 3
    480,481,482,483,484,485,486,487,488,489,490,491,492,493,         // Gen 4
    494,638,639,640,641,642,643,644,645,646,647,648,649,             // Gen 5
  ];
  const LEGENDARY_ID_SET = new Set(LEGENDARY_IDS);
  
  // Simplified evolution mapping - maps evolved form ID to base form ID
  const EVOLUTION_ROOTS = {};
  
  // Build the evolution roots map from the game's evolution data
  function buildEvolutionRoots() {
    // Gen 1-5 evolution chains (base -> stage1 -> stage2)
    const chains = {
      // Kanto starters
      1: [2, 3], 4: [5, 6], 7: [8, 9],
      // Johto starters  
      152: [153, 154], 155: [156, 157], 158: [159, 160],
      // Hoenn starters
      252: [253, 254], 255: [256, 257], 258: [259, 260],
      // Sinnoh starters
      387: [388, 389], 390: [391, 392], 393: [394, 395],
      // Unova starters
      495: [496, 497], 498: [499, 500], 501: [502, 503],
      // Other common chains
      10: [11, 12], 13: [14, 15], 16: [17, 18], 19: [20], 21: [22], 23: [24], 25: [26],
      27: [28], 29: [30, 31], 32: [33, 34], 35: [36], 37: [38], 39: [40], 41: [42, 169],
      43: [44, 45], 46: [47], 48: [49], 50: [51], 52: [53], 54: [55], 56: [57], 58: [59],
      60: [61, 62], 63: [64, 65], 66: [67, 68], 69: [70, 71], 72: [73], 74: [75, 76],
      77: [78], 79: [80, 199], 81: [82, 462], 84: [85], 86: [87], 88: [89], 90: [91],
      92: [93, 94], 95: [208], 96: [97], 98: [99], 100: [101], 102: [103], 104: [105],
      109: [110], 111: [112, 464], 116: [117, 230], 118: [119], 120: [121], 123: [212],
      129: [130], 133: [134, 135, 136, 196, 197, 470, 471], 138: [139], 140: [141],
      147: [148, 149], 161: [162], 163: [164], 165: [166], 167: [168], 170: [171],
      172: [25], 173: [35], 174: [39], 175: [176, 468], 177: [178], 179: [180, 181],
      183: [184], 187: [188, 189], 191: [192], 194: [195], 204: [205], 209: [210],
      215: [461], 216: [217], 218: [219], 220: [221, 473], 223: [224], 228: [229],
      231: [232], 236: [106, 107, 237], 238: [124], 239: [125, 466], 240: [126, 467],
      246: [247, 248], 261: [262], 263: [264], 265: [266, 267], 268: [269], 270: [271, 272],
      273: [274, 275], 276: [277], 278: [279], 280: [281, 282, 475], 283: [284], 285: [286],
      287: [288, 289], 290: [291, 292], 293: [294, 295], 296: [297], 298: [183], 300: [301],
      304: [305, 306], 307: [308], 309: [310], 316: [317], 318: [319], 320: [321],
      322: [323], 325: [326], 328: [329, 330], 331: [332], 333: [334], 339: [340],
      341: [342], 343: [344], 345: [346], 347: [348], 349: [350], 353: [354], 355: [356, 477],
      360: [202], 361: [362], 363: [364, 365], 371: [372, 373], 374: [375, 376],
      396: [397, 398], 399: [400], 401: [402], 403: [404, 405], 406: [315, 407],
      408: [409], 410: [411], 415: [416], 418: [419], 420: [421], 422: [423], 425: [426],
      427: [428], 431: [432], 434: [435], 436: [437], 443: [444, 445], 446: [143],
      447: [448], 449: [450], 451: [452], 453: [454], 456: [457], 459: [460],
      504: [505], 506: [507, 508], 509: [510], 517: [518], 519: [520, 521], 522: [523],
      524: [525, 526], 527: [528], 529: [530], 532: [533, 534], 535: [536, 537],
      540: [541, 542], 543: [544, 545], 546: [547], 548: [549], 551: [552, 553],
      554: [555], 557: [558], 559: [560], 562: [563], 564: [565], 566: [567], 568: [569],
      570: [571], 572: [573], 574: [575, 576], 577: [578, 579], 580: [581], 582: [583, 584],
      585: [586], 588: [589], 590: [591], 592: [593], 595: [596], 597: [598], 599: [600, 601],
      602: [603, 604], 605: [606], 607: [608, 609], 610: [611, 612], 613: [614], 616: [617],
      619: [620], 622: [623], 624: [625], 627: [628], 629: [630], 633: [634, 635], 636: [637]
    };
    
    // Build reverse mapping
    for (const [baseId, evolutions] of Object.entries(chains)) {
      const base = parseInt(baseId);
      EVOLUTION_ROOTS[base] = base; // Base maps to itself
      evolutions.forEach(evoId => {
        EVOLUTION_ROOTS[evoId] = base;
      });
    }
  }
  
  // Get the base form (evolution line root) for any Pokemon ID
  function getEvoLineRoot(speciesId) {
    if (Object.keys(EVOLUTION_ROOTS).length === 0) {
      buildEvolutionRoots();
    }
    return EVOLUTION_ROOTS[speciesId] || speciesId;
  }

  // ─── Styles ──────────────────────────────────────────────────────────────────
  const style = document.createElement('style');
  style.textContent = `
    * { box-sizing: border-box; }
    
    #pse-gui {
      position: fixed !important; top: 20px !important; right: 20px !important;
      width: 900px !important; height: 90vh !important; max-height: 800px !important;
      background: rgba(18, 18, 24, 0.98) !important;
      backdrop-filter: blur(40px) !important;
      border: 0.5px solid rgba(255, 255, 255, 0.1) !important;
      border-radius: 20px !important;
      box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6) !important;
      z-index: 999999 !important;
      display: flex !important;
      flex-direction: column !important;
      font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', sans-serif !important;
      color: rgba(235, 235, 245, 0.9) !important;
      overflow: hidden !important;
    }
    #pse-gui.hidden { display: none !important; }
    
    #pse-toggle-btn {
      position: fixed !important;
      bottom: 20px !important;
      right: 20px !important;
      width: 50px !important;
      height: 50px !important;
      background: rgba(139, 92, 246, 0.95) !important;
      backdrop-filter: blur(10px) !important;
      border: 0.5px solid rgba(255, 255, 255, 0.2) !important;
      border-radius: 999px !important;
      box-shadow: 0 8px 24px rgba(139, 92, 246, 0.4) !important;
      z-index: 999998 !important;
      cursor: pointer !important;
      display: flex !important;
      align-items: center !important;
      justify-content: center !important;
      font-size: 24px !important;
      transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
      color: white !important;
      font-family: -apple-system, BlinkMacSystemFont, sans-serif !important;
    }
    #pse-toggle-btn:hover {
      transform: scale(1.1) !important;
      box-shadow: 0 12px 32px rgba(139, 92, 246, 0.6) !important;
      background: rgba(139, 92, 246, 1) !important;
    }
    #pse-toggle-btn:active {
      transform: scale(0.95) !important;
    }
    
    .pse-header {
      padding: 16px 20px;
      border-bottom: 0.5px solid rgba(255, 255, 255, 0.08);
      display: flex;
      align-items: center;
      justify-content: space-between;
      flex-shrink: 0;
    }
    .pse-title {
      font-size: 16px;
      font-weight: 600;
      color: rgba(139, 92, 246, 1);
    }
    .pse-close {
      width: 28px;
      height: 28px;
      border-radius: 50%;
      background: rgba(255, 95, 87, 0.2);
      border: none;
      color: #ff5f57;
      cursor: pointer;
      font-size: 16px;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .pse-close:hover {
      background: rgba(255, 95, 87, 0.3);
    }
    
    .pse-nav {
      display: flex;
      gap: 4px;
      padding: 12px 20px;
      border-bottom: 0.5px solid rgba(255, 255, 255, 0.08);
      flex-shrink: 0;
    }
    .pse-nav-btn {
      padding: 8px 16px;
      border-radius: 8px;
      border: none;
      background: transparent;
      color: rgba(235, 235, 245, 0.6);
      font-size: 13px;
      font-weight: 500;
      cursor: pointer;
      transition: all 0.2s;
    }
    .pse-nav-btn:hover {
      background: rgba(255, 255, 255, 0.05);
      color: rgba(235, 235, 245, 0.9);
    }
    .pse-nav-btn.active {
      background: rgba(139, 92, 246, 0.15);
      color: rgba(139, 92, 246, 1);
    }
    
    .pse-content {
      flex: 1;
      overflow-y: auto;
      padding: 20px;
    }
    .pse-content::-webkit-scrollbar { width: 6px; }
    .pse-content::-webkit-scrollbar-thumb {
      background: rgba(255, 255, 255, 0.1);
      border-radius: 10px;
    }
    
    .pse-search {
      width: 100%;
      padding: 10px 16px;
      background: rgba(255, 255, 255, 0.04);
      border: 0.5px solid rgba(255, 255, 255, 0.1);
      border-radius: 999px;
      color: rgba(235, 235, 245, 0.9);
      font-size: 14px;
      outline: none;
      margin-bottom: 16px;
    }
    .pse-search:focus {
      border-color: rgba(139, 92, 246, 0.5);
      box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.1);
    }
    
    .pse-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
      gap: 12px;
    }
    
    .pse-card {
      background: rgba(255, 255, 255, 0.03);
      border: 0.5px solid rgba(255, 255, 255, 0.08);
      border-radius: 12px;
      padding: 12px;
      cursor: pointer;
      transition: all 0.2s;
      text-align: center;
    }
    .pse-card:hover {
      background: rgba(255, 255, 255, 0.06);
      border-color: rgba(139, 92, 246, 0.3);
      transform: translateY(-2px);
    }
    .pse-card.owned {
      border-color: rgba(139, 92, 246, 0.5);
      background: rgba(139, 92, 246, 0.08);
    }
    .pse-card img {
      width: 80px;
      height: 80px;
      image-rendering: pixelated;
    }
    .pse-card-name {
      font-size: 12px;
      margin-top: 8px;
      color: rgba(235, 235, 245, 0.8);
    }
    
    .pse-modal {
      position: fixed;
      inset: 0;
      background: rgba(0, 0, 0, 0.7);
      backdrop-filter: blur(8px);
      z-index: 9999999;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .pse-modal-box {
      background: rgba(18, 18, 24, 0.98);
      border: 0.5px solid rgba(255, 255, 255, 0.1);
      border-radius: 16px;
      padding: 24px;
      width: 600px;
      max-width: 90vw;
      max-height: 80vh;
      overflow-y: auto;
    }
    .pse-modal-title {
      font-size: 18px;
      font-weight: 600;
      margin-bottom: 20px;
      color: rgba(235, 235, 245, 0.95);
    }
    .pse-modal-actions {
      display: flex;
      gap: 8px;
      margin-top: 20px;
      justify-content: flex-end;
    }
    
    .pse-btn {
      padding: 10px 20px;
      border-radius: 999px;
      border: none;
      font-size: 13px;
      font-weight: 600;
      cursor: pointer;
      transition: all 0.2s;
    }
    .pse-btn-primary {
      background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);
      color: #fff;
    }
    .pse-btn-primary:hover {
      box-shadow: 0 4px 12px rgba(139, 92, 246, 0.4);
    }
    .pse-btn-secondary {
      background: rgba(255, 255, 255, 0.04);
      border: 0.5px solid rgba(255, 255, 255, 0.1);
      color: rgba(235, 235, 245, 0.7);
    }
    .pse-btn-danger {
      background: rgba(239, 68, 68, 0.15);
      color: #ef4444;
      border: 0.5px solid rgba(239, 68, 68, 0.3);
    }
    
    .pse-hof-item {
      background: rgba(255, 255, 255, 0.03);
      border: 0.5px solid rgba(255, 255, 255, 0.08);
      border-radius: 12px;
      padding: 16px;
      margin-bottom: 12px;
      cursor: pointer;
      transition: all 0.2s;
    }
    .pse-hof-item:hover {
      background: rgba(255, 255, 255, 0.06);
      border-color: rgba(139, 92, 246, 0.3);
    }
    .pse-hof-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 12px;
    }
    .pse-hof-title {
      font-size: 14px;
      font-weight: 600;
    }
    .pse-hof-team {
      display: flex;
      gap: 8px;
    }
    .pse-hof-team img {
      width: 48px;
      height: 48px;
      image-rendering: pixelated;
    }
  `;
  document.head.appendChild(style);

  // ─── GUI ─────────────────────────────────────────────────────────────────────
  const gui = document.createElement('div');
  gui.id = 'pse-gui';
  gui.className = 'hidden';
  gui.innerHTML = `
    <div class="pse-header">
      <div class="pse-title">Save Editor - by neol1no</div>
      <div style="display: flex; gap: 8px; align-items: center;">
        <button class="pse-btn pse-btn-primary" id="pse-save-reload" style="padding: 8px 16px; font-size: 12px;">Save & Reload</button>
        <button class="pse-close" onclick="document.getElementById('pse-gui').classList.add('hidden')">✕</button>
      </div>
    </div>
    <div class="pse-nav">
      <button class="pse-nav-btn active" data-view="pokedex">Pokédex</button>
      <button class="pse-nav-btn" data-view="shiny-dex">Shiny Dex</button>
      <button class="pse-nav-btn" data-view="hall-of-fame">Hall of Fame</button>
      <button class="pse-nav-btn" data-view="stat-buffs">Stat Buffs</button>
      <button class="pse-nav-btn" data-view="achievements">Achievements</button>
      <button class="pse-nav-btn" data-view="settings">Settings</button>
    </div>
    <div class="pse-content" id="pse-content"></div>
  `;
  document.body.appendChild(gui);

  // ─── Toggle Button ───────────────────────────────────────────────────────────
  const toggleBtn = document.createElement('div');
  toggleBtn.id = 'pse-toggle-btn';
  toggleBtn.innerHTML = '⚙️';
  toggleBtn.title = 'Toggle Save Editor (Ctrl+Shift+E)';
  document.body.appendChild(toggleBtn);
  
  toggleBtn.addEventListener('click', () => {
    gui.classList.toggle('hidden');
    if (!gui.classList.contains('hidden')) {
      renderContent();
    }
  });

  // ─── Navigation ──────────────────────────────────────────────────────────────
  document.querySelectorAll('.pse-nav-btn').forEach(btn => {
    btn.addEventListener('click', () => {
      document.querySelectorAll('.pse-nav-btn').forEach(b => b.classList.remove('active'));
      btn.classList.add('active');
      STATE.currentView = btn.dataset.view;
      renderContent();
    });
  });

  // ─── Render Content ──────────────────────────────────────────────────────────
  function renderContent() {
    const content = document.getElementById('pse-content');
    
    if (STATE.currentView === 'pokedex') {
      renderPokedex(content);
    } else if (STATE.currentView === 'shiny-dex') {
      renderShinyDex(content);
    } else if (STATE.currentView === 'hall-of-fame') {
      renderHallOfFame(content);
    } else if (STATE.currentView === 'stat-buffs') {
      renderStatBuffs(content);
    } else if (STATE.currentView === 'achievements') {
      renderAchievements(content);
    } else if (STATE.currentView === 'settings') {
      renderSettings(content);
    }
  }

  function renderPokedex(container) {
    const dex = JSON.parse(localStorage.getItem('poke_dex') || '{}');
    
    container.innerHTML = `
      <input type="text" class="pse-search" placeholder="Search Pokémon..." id="pse-search-dex">
      <div class="pse-grid" id="pse-dex-grid"></div>
    `;
    
    const grid = document.getElementById('pse-dex-grid');
    const search = document.getElementById('pse-search-dex');
    
    function renderGrid(query = '') {
      const filtered = POKEMON_LIST.filter(p => 
        p.name.toLowerCase().includes(query.toLowerCase())
      );
      
      grid.innerHTML = filtered.map(p => {
        const owned = dex[p.id]?.caught;
        return `
          <div class="pse-card ${owned ? 'owned' : ''}" data-id="${p.id}">
            <img src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${p.id}.png" alt="${p.name}">
            <div class="pse-card-name">${p.name}</div>
          </div>
        `;
      }).join('');
      
      grid.querySelectorAll('.pse-card').forEach(card => {
        card.addEventListener('click', () => {
          const id = card.dataset.id;
          toggleDex(id);
        });
      });
    }
    
    search.addEventListener('input', e => renderGrid(e.target.value));
    renderGrid();
  }

  function toggleDex(id) {
    const dex = JSON.parse(localStorage.getItem('poke_dex') || '{}');
    const pokemon = POKEMON_LIST.find(p => p.id == id);
    
    if (dex[id] && dex[id].caught) {
      // If already caught, remove it completely
      delete dex[id];
    } else {
      // Add or update with caught: true
      dex[id] = {
        id: parseInt(id),
        name: pokemon.name,
        types: ['Normal'],
        spriteUrl: `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${id}.png`,
        caught: true
      };
    }
    
    localStorage.setItem('poke_dex', JSON.stringify(dex));
    renderContent();
  }

  function renderShinyDex(container) {
    const shinyDex = JSON.parse(localStorage.getItem('poke_shiny_dex') || '{}');
    
    container.innerHTML = `
      <input type="text" class="pse-search" placeholder="Search Pokémon..." id="pse-search-shiny">
      <div class="pse-grid" id="pse-shiny-grid"></div>
    `;
    
    const grid = document.getElementById('pse-shiny-grid');
    const search = document.getElementById('pse-search-shiny');
    
    function renderGrid(query = '') {
      const filtered = POKEMON_LIST.filter(p => 
        p.name.toLowerCase().includes(query.toLowerCase())
      );
      
      grid.innerHTML = filtered.map(p => {
        const owned = shinyDex[p.id];
        return `
          <div class="pse-card ${owned ? 'owned' : ''}" data-id="${p.id}">
            <img src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/shiny/${p.id}.png" alt="${p.name}">
            <div class="pse-card-name">${p.name}</div>
          </div>
        `;
      }).join('');
      
      grid.querySelectorAll('.pse-card').forEach(card => {
        card.addEventListener('click', () => {
          const id = card.dataset.id;
          toggleShiny(id);
        });
      });
    }
    
    search.addEventListener('input', e => renderGrid(e.target.value));
    renderGrid();
  }

  function toggleShiny(id) {
    const shinyDex = JSON.parse(localStorage.getItem('poke_shiny_dex') || '{}');
    const pokemon = POKEMON_LIST.find(p => p.id == id);
    
    if (shinyDex[id]) {
      delete shinyDex[id];
    } else {
      shinyDex[id] = {
        id: parseInt(id),
        name: pokemon.name,
        types: ['Normal'], // You'd need to add type data
        shinySpriteUrl: `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/shiny/${id}.png`
      };
    }
    
    localStorage.setItem('poke_shiny_dex', JSON.stringify(shinyDex));
    renderContent();
  }

  function renderHallOfFame(container) {
    const hof = JSON.parse(localStorage.getItem('poke_hall_of_fame') || '[]');
    
    container.innerHTML = `
      <button class="pse-btn pse-btn-primary" id="pse-add-hof" style="margin-bottom: 16px;">+ Add New Run</button>
      <div id="pse-hof-list"></div>
    `;
    
    const list = document.getElementById('pse-hof-list');
    // Reverse to show newest first
    const reversed = [...hof].reverse();
    list.innerHTML = reversed.map((run, reversedIdx) => {
      const idx = hof.length - 1 - reversedIdx; // Get original index
      let modeText = '';
      if (run.endless) {
        const regions = ['Kanto', 'Johto', 'Hoenn', 'Sinnoh', 'Unova'];
        const region = regions[(run.stageNumber || 1) - 1] || 'Unknown';
        modeText = `Battle Tower - ${region}`;
      } else {
        modeText = 'Championship';
      }
      if (run.hardMode) modeText += ' (Nuzlocke)';
      
      return `
        <div class="pse-hof-item" data-idx="${idx}">
          <div class="pse-hof-header">
            <div class="pse-hof-title">Run #${run.runNumber} - ${run.date} - ${modeText}</div>
            <button class="pse-btn pse-btn-danger pse-btn-sm" onclick="deleteHofRun(${idx})">Delete</button>
          </div>
          <div class="pse-hof-team">
            ${run.team.map(p => `<img src="${p.spriteUrl}" alt="${p.name}" title="${p.name} Lv.${p.level}">`).join('')}
          </div>
        </div>
      `;
    }).join('');
    
    list.querySelectorAll('.pse-hof-item').forEach(item => {
      item.addEventListener('click', e => {
        if (!e.target.classList.contains('pse-btn-danger')) {
          editHofRun(parseInt(item.dataset.idx));
        }
      });
    });
    
    document.getElementById('pse-add-hof').addEventListener('click', () => {
      addNewHofRun();
    });
  }

  window.deleteHofRun = function(idx) {
    if (!confirm('Are you sure you want to delete this Hall of Fame entry?')) {
      return;
    }
    const hof = JSON.parse(localStorage.getItem('poke_hall_of_fame') || '[]');
    hof.splice(idx, 1);
    localStorage.setItem('poke_hall_of_fame', JSON.stringify(hof));
    // Sync to cloud immediately to prevent cloud from restoring deleted entry
    if (typeof syncToCloud === 'function') syncToCloud();
    // Force immediate re-render
    renderContent();
  };

  function addNewHofRun() {
    const hof = JSON.parse(localStorage.getItem('poke_hall_of_fame') || '[]');
    const newRun = {
      runNumber: hof.length + 1,
      hardMode: false,
      endless: false,
      date: new Date().toLocaleDateString(),
      team: []
    };
    hof.push(newRun);
    localStorage.setItem('poke_hall_of_fame', JSON.stringify(hof));
    editHofRun(hof.length - 1);
  }

  function editHofRun(idx) {
    const hof = JSON.parse(localStorage.getItem('poke_hall_of_fame') || '[]');
    const run = hof[idx];
    
    const modal = document.createElement('div');
    modal.className = 'pse-modal';
    modal.innerHTML = `
      <div class="pse-modal-box">
        <div class="pse-modal-title">Edit Run #${run.runNumber}</div>
        <div style="margin-bottom: 16px;">
          <label style="display: block; margin-bottom: 8px; font-size: 13px; color: rgba(235, 235, 245, 0.7);">
            <input type="radio" name="pse-mode" value="championship" ${!run.endless ? 'checked' : ''}> Championship
          </label>
          <label style="display: block; margin-bottom: 8px; font-size: 13px; color: rgba(235, 235, 245, 0.7);">
            <input type="radio" name="pse-mode" value="battle-tower" ${run.endless ? 'checked' : ''}> Battle Tower
          </label>
          <div id="pse-region-select" style="margin-left: 24px; margin-top: 8px; ${run.endless ? '' : 'display: none;'}">
            <label style="display: block; margin-bottom: 4px; font-size: 12px; color: rgba(235, 235, 245, 0.6);">Region:</label>
            <select id="pse-stage" style="padding: 6px 10px; background: rgba(255, 255, 255, 0.04); border: 0.5px solid rgba(255, 255, 255, 0.1); border-radius: 6px; color: #000; font-size: 13px; cursor: pointer;">
              <option value="1" ${run.stageNumber === 1 ? 'selected' : ''}>Kanto</option>
              <option value="2" ${run.stageNumber === 2 ? 'selected' : ''}>Johto</option>
              <option value="3" ${run.stageNumber === 3 ? 'selected' : ''}>Hoenn</option>
              <option value="4" ${run.stageNumber === 4 ? 'selected' : ''}>Sinnoh</option>
              <option value="5" ${run.stageNumber === 5 ? 'selected' : ''}>Unova</option>
            </select>
          </div>
        </div>
        <div id="pse-nuzlocke-container" style="margin-bottom: 16px; ${run.endless ? 'display: none;' : ''}">
          <label style="display: block; margin-bottom: 8px; font-size: 13px; color: rgba(235, 235, 245, 0.7);">
            <input type="checkbox" id="pse-nuzlocke" ${run.hardMode ? 'checked' : ''}> Nuzlocke Mode
          </label>
        </div>
        <div style="margin-bottom: 16px;">
          <div style="font-size: 13px; margin-bottom: 8px; color: rgba(235, 235, 245, 0.7);">Team (${run.team.length}/6)</div>
          <div id="pse-team-list" style="display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px;">
            ${run.team.map((p, i) => `
              <div style="position: relative; cursor: pointer;" onclick="editTeamMember(${idx}, ${i})">
                <img src="${p.spriteUrl}" style="width: 64px; height: 64px; image-rendering: pixelated;" title="${p.nickname || p.name} Lv.${p.level}${p.isShiny ? ' ✨' : ''}${p.heldItem ? ' • ' + p.heldItem.icon : ''}">
                ${p.isShiny ? '<div style="position: absolute; top: 2px; left: 2px; font-size: 16px;">✨</div>' : ''}
                ${p.heldItem ? `<div style="position: absolute; bottom: 2px; right: 2px; font-size: 14px;">${p.heldItem.icon}</div>` : ''}
              </div>
            `).join('')}
          </div>
          <button class="pse-btn pse-btn-secondary" id="pse-add-team">+ Add Pokémon</button>
        </div>
        <div class="pse-modal-actions">
          <button class="pse-btn pse-btn-secondary" id="pse-cancel">Cancel</button>
          <button class="pse-btn pse-btn-primary" id="pse-save">Save</button>
        </div>
      </div>
    `;
    document.body.appendChild(modal);
    
    // Toggle region select and nuzlocke visibility
    const modeRadios = modal.querySelectorAll('input[name="pse-mode"]');
    const regionSelect = document.getElementById('pse-region-select');
    const nuzlockeContainer = document.getElementById('pse-nuzlocke-container');
    modeRadios.forEach(radio => {
      radio.addEventListener('change', () => {
        const isBattleTower = radio.value === 'battle-tower';
        regionSelect.style.display = isBattleTower ? 'block' : 'none';
        nuzlockeContainer.style.display = isBattleTower ? 'none' : 'block';
      });
    });
    
    modal.querySelector('#pse-cancel').addEventListener('click', () => modal.remove());
    modal.querySelector('#pse-save').addEventListener('click', () => {
      // Reload from localStorage to get the latest data (in case team was modified)
      const latestHof = JSON.parse(localStorage.getItem('poke_hall_of_fame') || '[]');
      const latestRun = latestHof[idx];
      
      const mode = modal.querySelector('input[name="pse-mode"]:checked').value;
      latestRun.endless = mode === 'battle-tower';
      
      if (latestRun.endless) {
        latestRun.stageNumber = parseInt(document.getElementById('pse-stage').value);
        latestRun.hardMode = false; // Battle Tower can't be Nuzlocke
      } else {
        latestRun.hardMode = document.getElementById('pse-nuzlocke').checked;
        delete latestRun.stageNumber;
      }
      
      localStorage.setItem('poke_hall_of_fame', JSON.stringify(latestHof));
      modal.remove();
      renderContent();
    });
    
    modal.querySelector('#pse-add-team').addEventListener('click', () => {
      if (run.team.length >= 6) {
        alert('Team is full (6/6)');
        return;
      }
      showPokemonPicker(idx);
    });
    
    modal.addEventListener('click', e => {
      if (e.target === modal) modal.remove();
    });
  }

  window.removeTeamMember = function(runIdx, teamIdx) {
    const hof = JSON.parse(localStorage.getItem('poke_hall_of_fame') || '[]');
    hof[runIdx].team.splice(teamIdx, 1);
    localStorage.setItem('poke_hall_of_fame', JSON.stringify(hof));
    document.querySelector('.pse-modal').remove();
    editHofRun(runIdx);
  };

  window.editTeamMember = function(runIdx, teamIdx) {
    editTeamMember(runIdx, teamIdx);
  };

  function showPokemonPicker(runIdx) {
    const modal = document.createElement('div');
    modal.className = 'pse-modal';
    modal.innerHTML = `
      <div class="pse-modal-box">
        <div class="pse-modal-title">Add Pokémon to Team</div>
        <input type="text" class="pse-search" placeholder="Search Pokémon..." id="pse-search-picker">
        <div class="pse-grid" id="pse-picker-grid" style="max-height: 400px; overflow-y: auto;"></div>
      </div>
    `;
    document.body.appendChild(modal);
    
    const grid = document.getElementById('pse-picker-grid');
    const search = document.getElementById('pse-search-picker');
    
    function renderPicker(query = '') {
      const filtered = POKEMON_LIST.filter(p => 
        p.name.toLowerCase().includes(query.toLowerCase())
      );
      
      grid.innerHTML = filtered.map(p => `
        <div class="pse-card" data-id="${p.id}">
          <img src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${p.id}.png" alt="${p.name}">
          <div class="pse-card-name">${p.name}</div>
        </div>
      `).join('');
      
      grid.querySelectorAll('.pse-card').forEach(card => {
        card.addEventListener('click', () => {
          addPokemonToTeam(runIdx, parseInt(card.dataset.id));
          modal.remove();
        });
      });
    }
    
    search.addEventListener('input', e => renderPicker(e.target.value));
    renderPicker();
    
    modal.addEventListener('click', e => {
      if (e.target === modal) modal.remove();
    });
  }

  function addPokemonToTeam(runIdx, pokemonId) {
    const hof = JSON.parse(localStorage.getItem('poke_hall_of_fame') || '[]');
    const pokemon = POKEMON_LIST.find(p => p.id === pokemonId);
    
    // Add the Pokemon to the team
    hof[runIdx].team.push({
      speciesId: pokemonId,
      name: pokemon.name,
      nickname: null,
      level: 50,
      types: ['Normal'],
      spriteUrl: `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${pokemonId}.png`,
      isShiny: false,
      heldItem: null
    });
    
    // Save immediately
    localStorage.setItem('poke_hall_of_fame', JSON.stringify(hof));
    
    // Update the team list in the existing modal
    updateTeamListUI(runIdx);
  }
  
  function updateTeamListUI(runIdx) {
    // Reload from localStorage to get the latest data
    const hof = JSON.parse(localStorage.getItem('poke_hall_of_fame') || '[]');
    const run = hof[runIdx];
    
    const teamList = document.getElementById('pse-team-list');
    if (teamList) {
      teamList.innerHTML = run.team.map((p, i) => `
        <div style="position: relative; cursor: pointer;" onclick="editTeamMember(${runIdx}, ${i})">
          <img src="${p.spriteUrl}" style="width: 64px; height: 64px; image-rendering: pixelated;" title="${p.nickname || p.name} Lv.${p.level}${p.isShiny ? ' ✨' : ''}${p.heldItem ? ' • ' + p.heldItem.icon : ''}">
          ${p.isShiny ? '<div style="position: absolute; top: 2px; left: 2px; font-size: 16px;">✨</div>' : ''}
          ${p.heldItem ? `<div style="position: absolute; bottom: 2px; right: 2px; font-size: 14px;">${p.heldItem.icon}</div>` : ''}
        </div>
      `).join('');
      
      // Update team count
      const teamCountLabel = teamList.previousElementSibling;
      if (teamCountLabel) {
        teamCountLabel.textContent = `Team (${run.team.length}/6)`;
      }
    }
  }

  function editTeamMember(runIdx, teamIdx) {
    const hof = JSON.parse(localStorage.getItem('poke_hall_of_fame') || '[]');
    const member = hof[runIdx].team[teamIdx];
    
    const modal = document.createElement('div');
    modal.className = 'pse-modal';
    modal.innerHTML = `
      <div class="pse-modal-box">
        <div class="pse-modal-title">Edit ${member.name}</div>
        <div style="text-align: center; margin-bottom: 20px;">
          <img src="${member.spriteUrl}" style="width: 96px; height: 96px; image-rendering: pixelated;">
        </div>
        
        <div style="margin-bottom: 16px;">
          <label style="display: block; margin-bottom: 8px; font-size: 13px; color: rgba(235, 235, 245, 0.7);">Nickname (optional)</label>
          <input type="text" id="pse-nickname" value="${member.nickname || ''}" placeholder="${member.name}" style="width: 100%; padding: 10px; background: rgba(255, 255, 255, 0.04); border: 0.5px solid rgba(255, 255, 255, 0.1); border-radius: 8px; color: rgba(235, 235, 245, 0.9); font-size: 14px;">
        </div>
        
        <div style="margin-bottom: 16px;">
          <label style="display: block; margin-bottom: 8px; font-size: 13px; color: rgba(235, 235, 245, 0.7);">Level</label>
          <input type="number" id="pse-level" value="${member.level}" min="1" max="100" style="width: 100%; padding: 10px; background: rgba(255, 255, 255, 0.04); border: 0.5px solid rgba(255, 255, 255, 0.1); border-radius: 8px; color: rgba(235, 235, 245, 0.9); font-size: 14px;">
        </div>
        
        <div style="margin-bottom: 16px;">
          <label style="display: block; margin-bottom: 8px; font-size: 13px; color: rgba(235, 235, 245, 0.7);">
            <input type="checkbox" id="pse-is-shiny" ${member.isShiny ? 'checked' : ''}> Shiny
          </label>
        </div>
        
        <div style="margin-bottom: 16px;">
          <label style="display: block; margin-bottom: 8px; font-size: 13px; color: rgba(235, 235, 245, 0.7);">Held Item</label>
          <select id="pse-held-item" style="width: 100%; padding: 10px; background: rgba(255, 255, 255, 0.04); border: 0.5px solid rgba(255, 255, 255, 0.1); border-radius: 8px; color: #000; font-size: 14px; cursor: pointer;">
            <option value="">None</option>
            ${ITEMS.map(item => `
              <option value="${item.id}" ${member.heldItem?.id === item.id ? 'selected' : ''}>
                ${item.icon} ${item.name}
              </option>
            `).join('')}
          </select>
        </div>
        
        <div class="pse-modal-actions">
          <button class="pse-btn pse-btn-danger" id="pse-delete-member">Delete</button>
          <button class="pse-btn pse-btn-secondary" id="pse-cancel-member">Cancel</button>
          <button class="pse-btn pse-btn-primary" id="pse-save-member">Save</button>
        </div>
      </div>
    `;
    document.body.appendChild(modal);
    
    modal.querySelector('#pse-cancel-member').addEventListener('click', () => modal.remove());
    
    modal.querySelector('#pse-save-member').addEventListener('click', () => {
      const nickname = document.getElementById('pse-nickname').value.trim();
      const level = parseInt(document.getElementById('pse-level').value);
      const isShiny = document.getElementById('pse-is-shiny').checked;
      const itemId = document.getElementById('pse-held-item').value;
      
      // Reload from localStorage to ensure we have the latest data
      const hof = JSON.parse(localStorage.getItem('poke_hall_of_fame') || '[]');
      const member = hof[runIdx].team[teamIdx];
      
      member.nickname = nickname || null;
      member.level = level;
      member.isShiny = isShiny;
      
      // Update sprite URL based on shiny status
      member.spriteUrl = isShiny 
        ? `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/shiny/${member.speciesId}.png`
        : `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${member.speciesId}.png`;
      
      // Update held item
      if (itemId) {
        const item = ITEMS.find(i => i.id === itemId);
        member.heldItem = {
          id: item.id,
          name: item.name,
          icon: item.icon,
          desc: item.desc || ''
        };
      } else {
        member.heldItem = null;
      }
      
      localStorage.setItem('poke_hall_of_fame', JSON.stringify(hof));
      modal.remove();
      
      // Update the team list UI
      updateTeamListUI(runIdx);
    });
    
    modal.querySelector('#pse-delete-member').addEventListener('click', () => {
      // Reload from localStorage to ensure we have the latest data
      const hof = JSON.parse(localStorage.getItem('poke_hall_of_fame') || '[]');
      hof[runIdx].team.splice(teamIdx, 1);
      localStorage.setItem('poke_hall_of_fame', JSON.stringify(hof));
      modal.remove();
      
      // Update the team list UI
      updateTeamListUI(runIdx);
    });
    
    modal.addEventListener('click', e => {
      if (e.target === modal) modal.remove();
    });
  }

  // ─── Stat Buffs ──────────────────────────────────────────────────────────────
  function renderStatBuffs(container) {
    const statBuffs = JSON.parse(localStorage.getItem('poke_stat_buffs') || '{}');
    const hofData = JSON.parse(localStorage.getItem('poke_hall_of_fame') || '[]');
    
    // Get filter state from localStorage
    const filterLegendaries = localStorage.getItem('pse_filter_legendaries') === 'true';
    
    // Get unique Pokémon from Hall of Fame, mapped to their BASE FORMS
    const hofPokemonMap = new Map();
    hofData.forEach(run => {
      if (run.team && Array.isArray(run.team)) {
        run.team.forEach(member => {
          const evolvedId = member.speciesId;
          const baseId = getEvoLineRoot(evolvedId); // Map to base form
          
          // Skip legendaries if filter is enabled
          if (filterLegendaries && LEGENDARY_ID_SET.has(baseId)) {
            return;
          }
          
          if (!hofPokemonMap.has(baseId)) {
            const pokemon = POKEMON_LIST.find(p => p.id === baseId);
            hofPokemonMap.set(baseId, {
              id: baseId,
              name: pokemon?.name || `#${baseId}`,
              isShiny: member.isShiny || false,
              spriteUrl: member.isShiny 
                ? `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/shiny/${baseId}.png`
                : `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${baseId}.png`
            });
          } else if (member.isShiny && !hofPokemonMap.get(baseId).isShiny) {
            // Prioritize shiny sprite if found
            hofPokemonMap.get(baseId).isShiny = true;
            hofPokemonMap.get(baseId).spriteUrl = `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/shiny/${baseId}.png`;
          }
        });
      }
    });
    
    // Separate into buffed and unbuffed arrays
    const buffedPokemon = [];
    const unbuffedPokemon = [];
    
    hofPokemonMap.forEach((poke, id) => {
      if (statBuffs[id]) {
        buffedPokemon.push({ ...poke, buffs: statBuffs[id] });
      } else {
        unbuffedPokemon.push(poke);
      }
    });
    
    container.innerHTML = `
      <div style="margin-bottom: 16px; padding: 12px; background: rgba(139, 92, 246, 0.1); border: 0.5px solid rgba(139, 92, 246, 0.3); border-radius: 8px;">
        <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;">
          <div>
            <div style="font-size: 13px; color: rgba(235, 235, 245, 0.8);">Showing base forms of Pokémon from Hall of Fame</div>
            <div style="font-size: 11px; color: rgba(235, 235, 245, 0.6); margin-top: 4px;">Click any Pokémon to edit their stat buffs (buffs apply to entire evolution line)</div>
          </div>
          <label style="display: flex; align-items: center; gap: 8px; cursor: pointer; user-select: none;">
            <input type="checkbox" id="pse-filter-legendaries" ${filterLegendaries ? 'checked' : ''} 
              style="width: 16px; height: 16px; cursor: pointer; accent-color: rgba(139, 92, 246, 1);">
            <span style="font-size: 12px; color: rgba(235, 235, 245, 0.8); white-space: nowrap;">Battle Tower only</span>
          </label>
        </div>
      </div>
      <div class="pse-grid" id="pse-buff-grid"></div>
    `;
    
    const grid = document.getElementById('pse-buff-grid');
    
    if (hofPokemonMap.size === 0) {
      const message = filterLegendaries 
        ? 'No non-legendary Pokémon in Hall of Fame. Uncheck "Battle Tower only" to see all Pokémon.'
        : 'No Pokémon in Hall of Fame yet. Complete a run to see Pokémon here.';
      grid.innerHTML = `<div style="text-align: center; padding: 40px; color: rgba(235, 235, 245, 0.5);">${message}</div>`;
      
      // Add event listener for the checkbox
      const checkbox = document.getElementById('pse-filter-legendaries');
      if (checkbox) {
        checkbox.addEventListener('change', (e) => {
          localStorage.setItem('pse_filter_legendaries', e.target.checked);
          renderContent();
        });
      }
      return;
    }
    
    // Render buffed first, then unbuffed
    const allPokemon = [...buffedPokemon, ...unbuffedPokemon];
    
    grid.innerHTML = allPokemon.map(poke => {
      const totalBuffs = poke.buffs 
        ? (poke.buffs.hp || 0) + Math.max(poke.buffs.atk || 0, poke.buffs.special || 0) + (poke.buffs.def || 0) + (poke.buffs.speed || 0) + (poke.buffs.spdef || 0)
        : 0;
      
      return `
        <div class="pse-card ${poke.buffs ? 'owned' : ''}" data-id="${poke.id}" style="cursor: pointer;">
          <img src="${poke.spriteUrl}" alt="${poke.name}">
          <div class="pse-card-name">${poke.isShiny ? '✨ ' : ''}${poke.name}</div>
          ${totalBuffs > 0 ? `<div style="font-size: 11px; color: rgba(139, 92, 246, 1); margin-top: 4px;">${totalBuffs} buff points</div>` : ''}
        </div>
      `;
    }).join('');
    
    grid.querySelectorAll('.pse-card').forEach(card => {
      card.addEventListener('click', () => {
        editStatBuffs(parseInt(card.dataset.id));
      });
    });
    
    // Add event listener for the checkbox
    const checkbox = document.getElementById('pse-filter-legendaries');
    if (checkbox) {
      checkbox.addEventListener('change', (e) => {
        localStorage.setItem('pse_filter_legendaries', e.target.checked);
        renderContent();
      });
    }
  }
  
  
  async function editStatBuffs(pokemonId) {
    const statBuffs = JSON.parse(localStorage.getItem('poke_stat_buffs') || '{}');
    const buffs = statBuffs[pokemonId] || { hp: 0, atk: 0, def: 0, speed: 0, special: 0, spdef: 0 };
    const pokemon = POKEMON_LIST.find(p => p.id === pokemonId);
    
    // Calculate max buff points based on user's stage progress
    const hofData = JSON.parse(localStorage.getItem('poke_hall_of_fame') || '[]');
    const maxCompletedStage = hofData
      .filter(e => e.endless && e.stageNumber)
      .reduce((max, e) => Math.max(max, e.stageNumber), 0);
    const unlockedStage = Math.max(1, maxCompletedStage + 1);
    const legitMaxPoints = Math.min(unlockedStage * 10, 50);
    
    // Check if cheat mode is enabled
    const cheatMode = localStorage.getItem('pse_cheat_mode') === 'true';
    const maxPoints = cheatMode ? 50 : legitMaxPoints;
    
    // Try to get base stats from cached localStorage data (game already fetches this)
    let baseStats = null;
    let isSpecialAttacker = null;
    let hiddenAttackStat = null;
    
    const cachedKey = `pkrl_poke_${pokemonId}`;
    const cachedData = localStorage.getItem(cachedKey);
    
    if (cachedData) {
      try {
        const parsed = JSON.parse(cachedData);
        if (parsed.baseStats && parsed.baseStats.special !== undefined && parsed.baseStats.atk !== undefined) {
          baseStats = {
            atk: parsed.baseStats.atk,
            special: parsed.baseStats.special,
          };
          isSpecialAttacker = baseStats.special >= baseStats.atk;
          hiddenAttackStat = isSpecialAttacker ? 'atk' : 'special';
        }
      } catch (e) {
        console.warn('Failed to parse cached Pokemon data', e);
      }
    }
    
    // If no cached data, show both attack stats as fallback
    if (!baseStats) {
      console.warn(`No cached data found for Pokemon ${pokemonId}, showing both attack stats`);
    }
    
    // Calculate current total buff points
    const getCurrentTotal = () => {
      const getVal = (id, fallback) => {
        const el = document.getElementById(id);
        if (!el) return fallback ?? 0;
        const val = parseInt(el.value);
        return isNaN(val) ? 0 : val;
      };
      
      const hp = getVal('pse-buff-hp', buffs.hp);
      const atk = getVal('pse-buff-atk', buffs.atk);
      const def = getVal('pse-buff-def', buffs.def);
      const speed = getVal('pse-buff-speed', buffs.speed);
      const special = getVal('pse-buff-special', buffs.special);
      const spdef = getVal('pse-buff-spdef', buffs.spdef);
      const atkPts = Math.max(atk, special);
      return hp + atkPts + def + speed + spdef;
    };
    
    const initialTotal = (buffs.hp || 0) + Math.max(buffs.atk || 0, buffs.special || 0) + (buffs.def || 0) + (buffs.speed || 0) + (buffs.spdef || 0);
    
    const modal = document.createElement('div');
    modal.className = 'pse-modal';
    
    // Build stats list, filtering out the hidden attack stat if we know it
    const allStats = ['hp', 'atk', 'special', 'def', 'speed', 'spdef'];
    const visibleStats = hiddenAttackStat 
      ? allStats.filter(s => s !== hiddenAttackStat)
      : allStats;
    
    modal.innerHTML = `
      <div class="pse-modal-box">
        <div class="pse-modal-title">Stat Buffs - ${pokemon?.name || `#${pokemonId}`}</div>
        <div style="text-align: center; margin-bottom: 20px;">
          <img src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${pokemonId}.png" style="width: 96px; height: 96px; image-rendering: pixelated;">
        </div>
        
        <div style="margin-bottom: 12px; padding: 12px; background: rgba(139, 92, 246, 0.1); border: 0.5px solid rgba(139, 92, 246, 0.3); border-radius: 8px;">
          <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;">
            <div style="font-size: 13px; color: rgba(235, 235, 245, 0.9); font-weight: 600;">
              <span id="pse-buff-total">${initialTotal}</span>${cheatMode ? '' : ` / ${maxPoints}`} points used
            </div>
            <label style="display: flex; align-items: center; gap: 8px; cursor: pointer; user-select: none;">
              <input type="checkbox" id="pse-cheat-mode-toggle" ${cheatMode ? 'checked' : ''} 
                style="width: 16px; height: 16px; cursor: pointer; accent-color: rgba(255, 100, 100, 1);">
              <span style="font-size: 11px; color: rgba(255, 100, 100, 1); white-space: nowrap;">Cheat Mode</span>
            </label>
          </div>
          <div style="font-size: 11px; color: rgba(235, 235, 245, 0.6); margin-bottom: 4px;">Each stat: 0-10 buffs (+10% per buff)</div>
          ${hiddenAttackStat ? `<div style="font-size: 11px; color: rgba(235, 235, 245, 0.6);">This Pokémon is a ${isSpecialAttacker ? 'Special' : 'Physical'} attacker</div>` : '<div style="font-size: 11px; color: rgba(235, 235, 245, 0.6);">ATK and Special mirror each other</div>'}
          ${!cheatMode && maxPoints < 50 ? `<div style="font-size: 11px; color: rgba(255, 180, 0, 0.8); margin-top: 4px;">Complete Stage ${Math.min(5, unlockedStage)} to unlock more points (max 50)</div>` : ''}
          ${cheatMode ? `<div style="font-size: 11px; color: rgba(255, 100, 100, 0.8); margin-top: 4px;">⚠️ All caps removed</div>` : ''}
        </div>
        
        ${visibleStats.map(stat => {
          const labels = { hp: 'HP', atk: 'ATK', def: 'DEF', speed: 'SPE', special: 'SPA', spdef: 'SPD' };
          return `
            <div style="margin-bottom: 16px;">
              <label style="display: block; margin-bottom: 8px; font-size: 13px; color: rgba(235, 235, 245, 0.7);">
                <span id="pse-buff-${stat}-label">${labels[stat]} (${buffs[stat] || 0}/10) - +${(buffs[stat] || 0) * 10}%</span>
              </label>
              <div style="display: flex; gap: 8px; align-items: center;">
                <input type="range" id="pse-buff-${stat}" min="0" max="10" value="${buffs[stat] || 0}" 
                  style="flex: 1; accent-color: rgba(139, 92, 246, 1);">
                <input type="number" id="pse-buff-${stat}-num" min="0" max="10" value="${buffs[stat] || 0}"
                  style="width: 60px; padding: 6px; background: rgba(255, 255, 255, 0.04); border: 0.5px solid rgba(255, 255, 255, 0.1); border-radius: 6px; color: rgba(235, 235, 245, 0.9); font-size: 13px; text-align: center;">
              </div>
            </div>
          `;
        }).join('')}
        
        <div class="pse-modal-actions">
          <button class="pse-btn pse-btn-danger" id="pse-delete-buffs">Delete</button>
          <button class="pse-btn pse-btn-secondary" id="pse-cancel-buffs">Cancel</button>
          <button class="pse-btn pse-btn-primary" id="pse-save-buffs">Save</button>
        </div>
      </div>
    `;
    document.body.appendChild(modal);
    
    const totalDisplay = document.getElementById('pse-buff-total');
    const cheatModeToggle = document.getElementById('pse-cheat-mode-toggle');
    let currentCheatMode = cheatMode;
    
    // Update total display and enforce cap
    const updateTotal = () => {
      const total = getCurrentTotal();
      const newTotalDisplay = document.getElementById('pse-buff-total');
      if (newTotalDisplay) {
        newTotalDisplay.textContent = total;
        
        // Use the checkbox state directly to ensure we have the latest value
        const isCheatMode = document.getElementById('pse-cheat-mode-toggle').checked;
        const currentMaxPoints = isCheatMode ? Infinity : maxPoints;
        
        // Color code based on cap
        if (!isCheatMode && total > currentMaxPoints) {
          newTotalDisplay.style.color = 'rgba(255, 100, 100, 1)';
        } else if (!isCheatMode && total === currentMaxPoints) {
          newTotalDisplay.style.color = 'rgba(255, 215, 0, 1)';
        } else {
          newTotalDisplay.style.color = 'rgba(235, 235, 245, 0.9)';
        }
      }
    };
    
    // Handle cheat mode toggle
    cheatModeToggle.addEventListener('change', (e) => {
      currentCheatMode = e.target.checked;
      localStorage.setItem('pse_cheat_mode', currentCheatMode ? 'true' : 'false');
      
      // Update the total display text properly
      const currentTotal = getCurrentTotal();
      const newTotalDisplay = document.getElementById('pse-buff-total');
      if (newTotalDisplay) {
        newTotalDisplay.textContent = currentTotal;
      }
      
      // Find the header div and update the text after the total span
      const headerDiv = totalDisplay.parentElement;
      
      // Remove all text nodes after the total span
      Array.from(headerDiv.childNodes).forEach(node => {
        if (node.nodeType === Node.TEXT_NODE) {
          node.remove();
        }
      });
      
      // Add the correct text after the total span
      const totalSpan = document.getElementById('pse-buff-total');
      if (totalSpan) {
        const textToAdd = currentCheatMode 
          ? ' points used'
          : ` / ${maxPoints} points used`;
        totalSpan.insertAdjacentText('afterend', textToAdd);
      }
      
      // Update info messages
      const infoBox = headerDiv.closest('div[style*="background: rgba(139, 92, 246, 0.1)"]');
      const lastChild = infoBox.lastElementChild;
      
      if (currentCheatMode) {
        // Remove any existing warning and add cheat mode message
        if (lastChild && (lastChild.textContent.includes('Complete Stage') || lastChild.textContent === '')) {
          lastChild.remove();
        }
        if (!infoBox.textContent.includes('All caps removed')) {
          const cheatMsg = document.createElement('div');
          cheatMsg.style.cssText = 'font-size: 11px; color: rgba(255, 100, 100, 0.8); margin-top: 4px;';
          cheatMsg.textContent = '⚠️ All caps removed';
          infoBox.appendChild(cheatMsg);
        }
      } else {
        // Remove cheat mode message and add stage warning if needed
        if (lastChild && lastChild.textContent.includes('All caps removed')) {
          lastChild.remove();
        }
        if (maxPoints < 50 && !infoBox.textContent.includes('Complete Stage')) {
          const stageMsg = document.createElement('div');
          stageMsg.style.cssText = 'font-size: 11px; color: rgba(255, 180, 0, 0.8); margin-top: 4px;';
          stageMsg.textContent = `Complete Stage ${Math.min(5, unlockedStage)} to unlock more points (max 50)`;
          infoBox.appendChild(stageMsg);
        }
      }
      
      // Update max values on sliders and inputs WITHOUT resetting values
      visibleStats.forEach(stat => {
        const numInput = document.getElementById(`pse-buff-${stat}-num`);
        const slider = document.getElementById(`pse-buff-${stat}`);
        const label = document.getElementById(`pse-buff-${stat}-label`);
        const labels = { hp: 'HP', atk: 'ATK', def: 'DEF', speed: 'SPE', special: 'SPA', spdef: 'SPD' };
        
        // Don't read the value - it causes reset. Just update the max attributes
        if (currentCheatMode) {
          numInput.removeAttribute('max');
          slider.setAttribute('max', '999');
        } else {
          numInput.setAttribute('max', '10');
          slider.setAttribute('max', '10');
          // Clamp values to 10 if they exceed
          const currentVal = parseInt(slider.value);
          if (currentVal > 10) {
            slider.value = 10;
            numInput.value = 10;
          }
        }
        
        // Update label with current value from slider (don't reset)
        const val = parseInt(slider.value);
        label.textContent = `${labels[stat]} (${val}/${currentCheatMode ? '∞' : '10'}) - +${val * 10}%`;
      });
      
      updateTotal();
    });
    
    // Sync sliders with number inputs
    visibleStats.forEach(stat => {
      const slider = document.getElementById(`pse-buff-${stat}`);
      const numInput = document.getElementById(`pse-buff-${stat}-num`);
      const label = document.getElementById(`pse-buff-${stat}-label`);
      const labels = { hp: 'HP', atk: 'ATK', def: 'DEF', speed: 'SPE', special: 'SPA', spdef: 'SPD' };
      
      // Set initial max based on cheat mode
      if (currentCheatMode) {
        numInput.removeAttribute('max');
        slider.setAttribute('max', '999');
      }
      
      slider.addEventListener('input', () => {
        // Use the checkbox state directly to ensure we have the latest value
        const isCheatMode = document.getElementById('pse-cheat-mode-toggle').checked;
        
        if (!isCheatMode) {
          const newVal = parseInt(slider.value);
          
          // Calculate total by reading all current values from DOM
          let total = 0;
          visibleStats.forEach(s => {
            const sInput = document.getElementById(`pse-buff-${s}-num`);
            if (s === stat) {
              // Use the new value for this stat
              total += newVal;
            } else {
              total += parseInt(sInput?.value || 0);
            }
          });
          
          // For ATK/Special, only count the max of the two
          if (visibleStats.includes('atk') && visibleStats.includes('special')) {
            const atkVal = stat === 'atk' ? newVal : parseInt(document.getElementById('pse-buff-atk-num')?.value || 0);
            const specVal = stat === 'special' ? newVal : parseInt(document.getElementById('pse-buff-special-num')?.value || 0);
            total = total - atkVal - specVal + Math.max(atkVal, specVal);
          } else if (!visibleStats.includes('atk') && stat === 'special') {
            // Special is visible but ATK is hidden - they mirror
            // Already counted correctly
          } else if (!visibleStats.includes('special') && stat === 'atk') {
            // ATK is visible but Special is hidden - they mirror
            // Already counted correctly
          }
          
          if (total > maxPoints) {
            // Don't allow the change
            slider.value = numInput.value;
            return;
          }
        }
        
        numInput.value = slider.value;
        label.textContent = `${labels[stat]} (${slider.value}/${isCheatMode ? '∞' : '10'}) - +${slider.value * 10}%`;
        updateTotal();
      });
      
      numInput.addEventListener('input', () => {
        // Use the checkbox state directly to ensure we have the latest value
        const isCheatMode = document.getElementById('pse-cheat-mode-toggle').checked;
        const maxVal = isCheatMode ? 999 : 10;
        let val = Math.max(0, Math.min(maxVal, parseInt(numInput.value) || 0));
        
        // Check if this would exceed total cap (only if not in cheat mode)
        if (!isCheatMode) {
          // Calculate total by reading all current values from DOM
          let total = 0;
          visibleStats.forEach(s => {
            const sInput = document.getElementById(`pse-buff-${s}-num`);
            if (s === stat) {
              // Use the new value for this stat
              total += val;
            } else {
              total += parseInt(sInput?.value || 0);
            }
          });
          
          // For ATK/Special, only count the max of the two
          if (visibleStats.includes('atk') && visibleStats.includes('special')) {
            const atkVal = stat === 'atk' ? val : parseInt(document.getElementById('pse-buff-atk-num')?.value || 0);
            const specVal = stat === 'special' ? val : parseInt(document.getElementById('pse-buff-special-num')?.value || 0);
            total = total - atkVal - specVal + Math.max(atkVal, specVal);
          }
          
          if (total > maxPoints) {
            // Calculate how much we can actually add
            const currentWithoutThis = total - val;
            val = Math.max(0, maxPoints - currentWithoutThis);
          }
        }
        
        numInput.value = val;
        slider.value = Math.min(val, parseInt(slider.max));
        label.textContent = `${labels[stat]} (${val}/${isCheatMode ? '∞' : '10'}) - +${val * 10}%`;
        updateTotal();
      });
    });
    
    modal.querySelector('#pse-cancel-buffs').addEventListener('click', () => modal.remove());
    
    modal.querySelector('#pse-save-buffs').addEventListener('click', () => {
      const total = getCurrentTotal();
      
      // Use the checkbox state directly to ensure we have the latest value
      const isCheatMode = document.getElementById('pse-cheat-mode-toggle').checked;
      
      // Enforce cap (unless cheat mode)
      if (!isCheatMode && total > maxPoints) {
        alert(`Total buff points (${total}) exceeds your cap (${maxPoints}). Complete more Battle Tower stages to increase your cap, or enable Cheat Mode.`);
        return;
      }
      
      // Helper to safely get value from DOM (never fall back to old buffs)
      const getVal = (id) => {
        const el = document.getElementById(id);
        if (!el) return 0;
        const val = parseInt(el.value);
        return isNaN(val) ? 0 : val;
      };
      
      let newBuffs = {
        hp: getVal('pse-buff-hp'),
        atk: getVal('pse-buff-atk'),
        def: getVal('pse-buff-def'),
        speed: getVal('pse-buff-speed'),
        special: getVal('pse-buff-special'),
        spdef: getVal('pse-buff-spdef'),
      };
      
      // If NOT in cheat mode, clamp all values to 10 (game's max per stat)
      if (!isCheatMode) {
        Object.keys(newBuffs).forEach(key => {
          newBuffs[key] = Math.min(10, newBuffs[key]);
        });
      }
      
      // Mirror ATK and Special (game mechanic - they always stay in sync)
      const maxAttack = Math.max(newBuffs.atk, newBuffs.special);
      newBuffs.atk = maxAttack;
      newBuffs.special = maxAttack;
      
      statBuffs[pokemonId] = newBuffs;
      localStorage.setItem('poke_stat_buffs', JSON.stringify(statBuffs));
      modal.remove();
      renderContent();
    });
    
    modal.querySelector('#pse-delete-buffs').addEventListener('click', () => {
      delete statBuffs[pokemonId];
      localStorage.setItem('poke_stat_buffs', JSON.stringify(statBuffs));
      modal.remove();
      renderContent();
    });
    
    modal.addEventListener('click', e => {
      if (e.target === modal) modal.remove();
    });
  }

  // ─── Achievements Data ───────────────────────────────────────────────────────
  const ACHIEVEMENTS = [
    { id: 'gym_0', name: 'Boulder Basher', desc: 'Clear Map 1 and defeat Brock', icon: '🪨', category: 'normal' },
    { id: 'gym_1', name: 'Cascade Crusher', desc: 'Clear Map 2 and defeat Misty', icon: '💧', category: 'normal' },
    { id: 'gym_2', name: 'Thunder Tamer', desc: 'Clear Map 3 and defeat Lt. Surge', icon: '⚡', category: 'normal' },
    { id: 'gym_3', name: 'Rainbow Ranger', desc: 'Clear Map 4 and defeat Erika', icon: '🌿', category: 'normal' },
    { id: 'gym_4', name: 'Soul Crusher', desc: 'Clear Map 5 and defeat Koga', icon: '💜', category: 'normal' },
    { id: 'gym_5', name: 'Mind Breaker', desc: 'Clear Map 6 and defeat Sabrina', icon: '🔮', category: 'normal' },
    { id: 'gym_6', name: 'Volcano Victor', desc: 'Clear Map 7 and defeat Blaine', icon: '🌋', category: 'normal' },
    { id: 'gym_7', name: 'Earth Shaker', desc: 'Clear Map 8 and defeat Giovanni', icon: '🌍', category: 'normal' },
    { id: 'elite_four', name: 'Pokemon Master', desc: 'Defeat all 4 Elite Four members and the Champion to beat the game', icon: '👑', category: 'normal' },
    { id: 'elite_10', name: 'Champion League', desc: 'Beat the game 10 times total', icon: '🏆', category: 'normal' },
    { id: 'elite_100', name: 'Immortal Champion', desc: 'Beat the game 100 times total', icon: '💎', category: 'normal' },
    { id: 'starter_1', name: 'Grass Champion', desc: 'Choose Bulbasaur as your starter and beat the game', icon: '🌱', category: 'normal' },
    { id: 'starter_4', name: 'Fire Champion', desc: 'Choose Charmander as your starter and beat the game', icon: '🔥', category: 'normal' },
    { id: 'starter_7', name: 'Water Champion', desc: 'Choose Squirtle as your starter and beat the game', icon: '🌊', category: 'normal' },
    { id: 'solo_run', name: 'One is Enough', desc: 'Beat the game while keeping only 1 Pokémon on your team', icon: '⭐', category: 'normal' },
    { id: 'nuzlocke_win', name: 'True Master', desc: 'Enable Nuzlocke Mode in Settings, then beat the game — if any Pokémon faints, it\'s gone for good', icon: '☠️', category: 'normal' },
    { id: 'three_birds', name: 'Bird Keeper', desc: 'Beat the game with Articuno, Zapdos, and Moltres all on your team', icon: '🦅', category: 'normal' },
    { id: 'no_pokecenter', name: 'No Rest for the Wicked', desc: 'Beat the game without stopping at a Pokémon Center', icon: '🏃', category: 'normal' },
    { id: 'no_items', name: 'Minimalist', desc: 'Beat the game without picking up a single item', icon: '🎒', category: 'normal' },
    { id: 'type_quartet', name: 'Type Supremacy', desc: 'Beat the game with at least 4 of your 6 Pokémon sharing the same type', icon: '🔣', category: 'normal' },
    { id: 'all_shiny_win', name: 'Shiny Squad', desc: 'Beat the game with every Pokémon on your team being shiny (minimum 3)', icon: '💫', category: 'normal' },
    { id: 'back_to_back', name: 'On a Roll', desc: 'Beat the game twice in a row without losing a run in between', icon: '🔁', category: 'normal' },
    { id: 'back_3_back', name: 'Hat Trick', desc: 'Beat the game three times in a row without losing a run in between', icon: '🎩', category: 'normal' },
    { id: 'endless_stage_1', name: 'Kanto Champion', desc: 'Defeat Ash Ketchum and clear Stage 1 of Battle Tower', icon: '🌀', category: 'tower' },
    { id: 'endless_stage_2', name: 'Johto Champion', desc: 'Defeat Lance and clear Stage 2 of Battle Tower', icon: '🌊', category: 'tower' },
    { id: 'endless_stage_3', name: 'Hoenn Champion', desc: 'Defeat Steven Stone and clear Stage 3 of Battle Tower', icon: '⚔️', category: 'tower' },
    { id: 'endless_stage_4', name: 'Sinnoh Champion', desc: 'Defeat Cynthia and clear Stage 4 of Battle Tower', icon: '💎', category: 'tower' },
    { id: 'endless_stage_5', name: 'Unova Champion', desc: 'Defeat N and clear Stage 5 of Battle Tower', icon: '🏅', category: 'tower' },
    { id: 'starters_stage_1', name: 'Kanto Trio', desc: 'Win a Stage 1 run starting with each of Bulbasaur, Charmander, and Squirtle', icon: '🌿', category: 'tower' },
    { id: 'starters_stage_2', name: 'Johto Trio', desc: 'Win a Stage 2 run starting with each of Chikorita, Cyndaquil, and Totodile', icon: '🍃', category: 'tower' },
    { id: 'starters_stage_3', name: 'Hoenn Trio', desc: 'Win a Stage 3 run starting with each of Treecko, Torchic, and Mudkip', icon: '🌊', category: 'tower' },
    { id: 'starters_stage_4', name: 'Sinnoh Trio', desc: 'Win a Stage 4 run starting with each of Turtwig, Chimchar, and Piplup', icon: '⛰️', category: 'tower' },
    { id: 'starters_stage_5', name: 'Unova Trio', desc: 'Win a Stage 5 run starting with each of Snivy, Tepig, and Oshawott', icon: '🌀', category: 'tower' },
    { id: 'pokedex_complete', name: 'Gotta Catch \'Em All', desc: 'Catch all Gen 1 Pokémon across any number of runs', icon: '📖', category: 'general' },
    { id: 'shinydex_complete', name: 'Shiny Hunter', desc: 'Catch a shiny version of every Gen 1 Pokémon', icon: '✨', category: 'general' },
    { id: 'shinydex_all', name: 'Ultimate Shiny Hunter', desc: 'Catch a shiny version of every Pokémon across all gens', icon: '🌟', category: 'general' },
    { id: 'pokedex_gen2', name: 'Johto Completionist', desc: 'Catch all Gen 2 Pokémon across any number of runs', icon: '📗', category: 'general' },
    { id: 'pokedex_gen3', name: 'Hoenn Completionist', desc: 'Catch all Gen 3 Pokémon across any number of runs', icon: '📘', category: 'general' },
    { id: 'pokedex_gen4', name: 'Sinnoh Completionist', desc: 'Catch all Gen 4 Pokémon across any number of runs', icon: '📙', category: 'general' },
    { id: 'pokedex_gen5', name: 'Unova Completionist', desc: 'Catch all Gen 5 Pokémon across any number of runs', icon: '📕', category: 'general' },
    { id: 'max_stats_1', name: 'First Peak', desc: 'Max out 1 stat on a single Pokémon', icon: '📈', category: 'general' },
    { id: 'max_stats_2', name: 'Double Peak', desc: 'Max out 2 stats on a single Pokémon', icon: '📊', category: 'general' },
    { id: 'max_stats_3', name: 'Triple Peak', desc: 'Max out 3 stats on a single Pokémon', icon: '🔝', category: 'general' },
    { id: 'max_stats_4', name: 'Quad Peak', desc: 'Max out 4 stats on a single Pokémon', icon: '💪', category: 'general' },
    { id: 'max_stats_all', name: 'Perfect Specimen', desc: 'Max out all 6 stats on a single Pokémon', icon: '🏅', category: 'general' },
    { id: 'shinydex_100', name: 'Shiny Spark', desc: 'Catch 100 different shiny Pokémon', icon: '⭐', category: 'general' },
    { id: 'shinydex_200', name: 'Shiny Flash', desc: 'Catch 200 different shiny Pokémon', icon: '💥', category: 'general' },
    { id: 'shinydex_300', name: 'Shiny Blaze', desc: 'Catch 300 different shiny Pokémon', icon: '🔥', category: 'general' },
    { id: 'shinydex_400', name: 'Shiny Storm', desc: 'Catch 400 different shiny Pokémon', icon: '⚡', category: 'general' },
    { id: 'shinydex_500', name: 'Shiny Legend', desc: 'Catch 500 different shiny Pokémon', icon: '💎', category: 'general' },
    { id: 'shinydex_600', name: 'Shiny Immortal', desc: 'Catch 600 different shiny Pokémon', icon: '👑', category: 'general' },
  ];

  function renderAchievements(container) {
    const unlocked = new Set(JSON.parse(localStorage.getItem('poke_achievements') || '[]'));
    
    const categories = {
      normal: ACHIEVEMENTS.filter(a => a.category === 'normal'),
      tower: ACHIEVEMENTS.filter(a => a.category === 'tower'),
      general: ACHIEVEMENTS.filter(a => a.category === 'general'),
    };
    
    const unlockedCount = unlocked.size;
    const totalCount = ACHIEVEMENTS.length;
    
    container.innerHTML = `
      <div style="margin-bottom: 20px; text-align: center;">
        <div style="font-size: 24px; font-weight: 600; color: rgba(139, 92, 246, 1); margin-bottom: 8px;">
          ${unlockedCount} / ${totalCount}
        </div>
        <div style="font-size: 13px; color: rgba(235, 235, 245, 0.6);">Achievements Unlocked</div>
      </div>
      
      <div style="margin-bottom: 24px;">
        <div style="font-size: 14px; font-weight: 600; margin-bottom: 12px; color: rgba(235, 235, 245, 0.9);">🏆 Championship</div>
        <div class="pse-grid" style="grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));">
          ${categories.normal.map(ach => renderAchievementCard(ach, unlocked.has(ach.id))).join('')}
        </div>
      </div>
      
      <div style="margin-bottom: 24px;">
        <div style="font-size: 14px; font-weight: 600; margin-bottom: 12px; color: rgba(235, 235, 245, 0.9);">🗼 Battle Tower</div>
        <div class="pse-grid" style="grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));">
          ${categories.tower.map(ach => renderAchievementCard(ach, unlocked.has(ach.id))).join('')}
        </div>
      </div>
      
      <div style="margin-bottom: 24px;">
        <div style="font-size: 14px; font-weight: 600; margin-bottom: 12px; color: rgba(235, 235, 245, 0.9);">📚 General</div>
        <div class="pse-grid" style="grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));">
          ${categories.general.map(ach => renderAchievementCard(ach, unlocked.has(ach.id))).join('')}
        </div>
      </div>
    `;
    
    // Add click handlers
    container.querySelectorAll('.pse-achievement-card').forEach(card => {
      card.addEventListener('click', () => {
        const id = card.dataset.id;
        const isUnlocked = unlocked.has(id);
        
        if (isUnlocked) {
          unlocked.delete(id);
        } else {
          unlocked.add(id);
        }
        
        localStorage.setItem('poke_achievements', JSON.stringify([...unlocked]));
        renderContent();
      });
    });
  }
  
  function renderAchievementCard(achievement, isUnlocked) {
    return `
      <div class="pse-achievement-card ${isUnlocked ? 'unlocked' : 'locked'}" data-id="${achievement.id}" style="
        padding: 16px;
        background: ${isUnlocked ? 'rgba(139, 92, 246, 0.1)' : 'rgba(255, 255, 255, 0.02)'};
        border: 0.5px solid ${isUnlocked ? 'rgba(139, 92, 246, 0.3)' : 'rgba(255, 255, 255, 0.05)'};
        border-radius: 12px;
        cursor: pointer;
        transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
        opacity: ${isUnlocked ? '1' : '0.5'};
      " onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 8px 16px rgba(0,0,0,0.3)';" onmouseout="this.style.transform=''; this.style.boxShadow='';">
        <div style="font-size: 32px; text-align: center; margin-bottom: 8px;">${achievement.icon}</div>
        <div style="font-size: 13px; font-weight: 600; text-align: center; margin-bottom: 4px; color: ${isUnlocked ? 'rgba(139, 92, 246, 1)' : 'rgba(235, 235, 245, 0.7)'};">
          ${achievement.name}
        </div>
        <div style="font-size: 11px; text-align: center; color: rgba(235, 235, 245, 0.5); line-height: 1.4;">
          ${achievement.desc}
        </div>
        ${isUnlocked ? '<div style="text-align: center; margin-top: 8px; font-size: 16px;">✓</div>' : ''}
      </div>
    `;
  }

  function renderSettings(container) {
    const eliteWins = localStorage.getItem('poke_elite_wins') || '0';
    const winStreak = localStorage.getItem('poke_win_streak') || '0';
    const lastRunWon = localStorage.getItem('poke_last_run_won') || 'false';
    
    container.innerHTML = `
      <div style="max-width: 500px;">
        <div style="margin-bottom: 20px;">
          <label style="display: block; margin-bottom: 8px; font-size: 13px; color: rgba(235, 235, 245, 0.7);">Elite Wins</label>
          <input type="number" id="pse-elite-wins" value="${eliteWins}" style="width: 100%; padding: 10px; background: rgba(255, 255, 255, 0.04); border: 0.5px solid rgba(255, 255, 255, 0.1); border-radius: 8px; color: rgba(235, 235, 245, 0.9); font-size: 14px;">
        </div>
        <div style="margin-bottom: 20px;">
          <label style="display: block; margin-bottom: 8px; font-size: 13px; color: rgba(235, 235, 245, 0.7);">Win Streak</label>
          <input type="number" id="pse-win-streak" value="${winStreak}" style="width: 100%; padding: 10px; background: rgba(255, 255, 255, 0.04); border: 0.5px solid rgba(255, 255, 255, 0.1); border-radius: 8px; color: rgba(235, 235, 245, 0.9); font-size: 14px;">
        </div>
        <div style="margin-bottom: 20px;">
          <label style="display: flex; align-items: center; gap: 8px; font-size: 13px; color: rgba(235, 235, 245, 0.7); cursor: pointer;">
            <input type="checkbox" id="pse-last-run-won" ${lastRunWon === 'true' ? 'checked' : ''} style="width: 16px; height: 16px; cursor: pointer;">
            Last Run Won
          </label>
        </div>
        <button class="pse-btn pse-btn-primary" id="pse-save-settings">Save Settings</button>
      </div>
    `;
    
    document.getElementById('pse-save-settings').addEventListener('click', () => {
      localStorage.setItem('poke_elite_wins', document.getElementById('pse-elite-wins').value);
      localStorage.setItem('poke_win_streak', document.getElementById('pse-win-streak').value);
      localStorage.setItem('poke_last_run_won', document.getElementById('pse-last-run-won').checked ? 'true' : 'false');
      alert('Settings saved!');
    });
  }

  // ─── Keyboard shortcut ────────────────────────────────────────────────────────
  document.addEventListener('keydown', e => {
    if (e.ctrlKey && e.shiftKey && e.key === 'E') {
      e.preventDefault();
      gui.classList.toggle('hidden');
      if (!gui.classList.contains('hidden')) {
        renderContent();
      }
    }
  });

  // ─── Save & Reload button ─────────────────────────────────────────────────────
  document.getElementById('pse-save-reload').addEventListener('click', () => {
    location.reload();
  });

  // ─── Init ─────────────────────────────────────────────────────────────────────
  renderContent();

  // ─── Stage Complete Message Modifier ──────────────────────────────────────────
  const observer = new MutationObserver(() => {
    const stageCompleteScreen = document.getElementById('endless-stage-complete');
    if (stageCompleteScreen && stageCompleteScreen.classList.contains('active')) {
      const msgEl = document.getElementById('stage-complete-msg');
      const unlockEl = document.getElementById('stage-complete-unlock');
      
      if (msgEl && !msgEl.textContent.includes('- Save Editor Loaded')) {
        msgEl.textContent = msgEl.textContent.replace('Complete!', 'Complete! - Save Editor Loaded');
      }
      
      if (unlockEl && unlockEl.textContent && !unlockEl.textContent.includes('- Save Editor Loaded')) {
        unlockEl.textContent = unlockEl.textContent.replace('unlocked!', 'unlocked! - Save Editor Loaded');
      }
    }
  });
  
  observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['class'] });
})();