;(function(){
// ============================================================
// POKENAV R1 — game-data.jsx v0.3
// ============================================================

const C = {
  bg:'#0a0a0a',panel:'#111111',orange:'#FF6B00',orangeDim:'#CC5500',
  green:'#22C55E',yellow:'#FACC15',red:'#EF4444',blue:'#3B82F6',
  text:'#F0F0F0',dim:'#555555',border:'#222222',
};
const TYPE_COL = {
  grass:'#22C55E',fire:'#EF4444',water:'#3B82F6',poison:'#A855F7',
  normal:'#9CA3AF',electric:'#FACC15',flying:'#7DD3FC',psychic:'#EC4899',
  bug:'#84CC16',rock:'#A8A29E',ground:'#D97706',ice:'#BAE6FD',
  ghost:'#7C3AED',dragon:'#6D28D9',fighting:'#B45309',steel:'#94A3B8',
};

// ── 20 Escenarios ──────────────────────────────────────────
const SCENARIOS = [
  {id:0, name:'RUTA 1',         accent:'#22C55E',minLv:1 },
  {id:1, name:'BOSQUE JADE',    accent:'#16A34A',minLv:3 },
  {id:2, name:'CUEVA ROCA',     accent:'#92400E',minLv:6 },
  {id:3, name:'RUTA FUEGO',     accent:'#DC2626',minLv:10},
  {id:4, name:'COSTA AZUL',     accent:'#2563EB',minLv:14},
  {id:5, name:'ARRECIFE',       accent:'#0891B2',minLv:18},
  {id:6, name:'SABANA',         accent:'#CA8A04',minLv:22},
  {id:7, name:'CIUDAD LILA',    accent:'#9333EA',minLv:27},
  {id:8, name:'MONTE LUNAR',    accent:'#6366F1',minLv:33},
  {id:9, name:'LIGA POKÉMON',   accent:'#FF6B00',minLv:40},
  {id:10,name:'TORRE FANTASMA', accent:'#A855F7',minLv:45},
  {id:11,name:'CAÑÓN ÁRIDO',    accent:'#D97706',minLv:50},
  {id:12,name:'TUNDRA HELADA',  accent:'#BAE6FD',minLv:55},
  {id:13,name:'SELVA VENENOSA', accent:'#84CC16',minLv:60},
  {id:14,name:'VOLCÁN ACTIVO',  accent:'#EF4444',minLv:65},
  {id:15,name:'MAR PROFUNDO',   accent:'#06B6D4',minLv:70},
  {id:16,name:'MONTE DRAGÓN',   accent:'#7C3AED',minLv:75},
  {id:17,name:'CIELO TORMENTA', accent:'#FACC15',minLv:80},
  {id:18,name:'RUINAS ANTIGUAS',accent:'#A8A29E',minLv:85},
  {id:19,name:'SANTUARIO LVL',  accent:'#F9A8D4',minLv:90},
];

const SCENARIO_POOLS = [
  [16,19,10,13,41],
  [10,11,12,13,43,69,46],
  [74,66,95,41,104,27],
  [58,37,77,136,78],
  [54,60,72,79,118,129],
  [98,116,120,86,90,140],
  [83,84,111,115,128,102],
  [92,93,96,122,109,110],
  [100,101,137,82,81,95],
  [130,131,142,143,149,58],
  [92,93,94,109,110,41,42],
  [27,28,50,51,74,75,111,104,105],
  [86,87,124,90,91,131,144],
  [43,44,45,46,47,48,49,69,70,71],
  [37,38,58,59,77,78,126,146],
  [72,73,79,80,116,117,120,121,131],
  [147,148,149,95,111,112],
  [125,82,100,101,123,142,145],
  [63,64,65,96,97,138,139,140,141],
  [144,145,146,147,148,149,150,130,143],
];

// ── Gimnasios (uno por escenario) ──────────────────────────
const GYMS = [
  {id:0, leader:'BROCK',    title:'Maestro Roca',     badge:'ROCA',     color:'#A8A29E',team:[{id:74,lv:12},{id:95,lv:14},{id:76,lv:16}],  reward:{pokeballs:3,berries:2}},
  {id:1, leader:'MISTY',    title:'Maestra Agua',     badge:'CASCADA',  color:'#3B82F6',team:[{id:54,lv:18},{id:55,lv:21}],                 reward:{greatballs:1,berries:3}},
  {id:2, leader:'LT.SURGE', title:'Maestro Eléctrico',badge:'TRUENO',   color:'#FACC15',team:[{id:100,lv:21},{id:25,lv:24},{id:26,lv:28}], reward:{greatballs:2,berries:2}},
  {id:3, leader:'ERIKA',    title:'Maestra Planta',   badge:'ARCO',     color:'#22C55E',team:[{id:43,lv:29},{id:70,lv:31},{id:45,lv:32}],  reward:{greatballs:2,berries:4}},
  {id:4, leader:'KOGA',     title:'Maestro Veneno',   badge:'ALMA',     color:'#A855F7',team:[{id:109,lv:37},{id:89,lv:39},{id:110,lv:43}],reward:{ultraballs:1,berries:3}},
  {id:5, leader:'SABRINA',  title:'Maestra Psíquica', badge:'CARMÍN',   color:'#EC4899',team:[{id:64,lv:38},{id:122,lv:42},{id:65,lv:46}], reward:{ultraballs:1,greatballs:2}},
  {id:6, leader:'BLAINE',   title:'Maestro Fuego',    badge:'VOLCÁN',   color:'#EF4444',team:[{id:58,lv:42},{id:77,lv:40},{id:59,lv:47}],  reward:{ultraballs:2,berries:2}},
  {id:7, leader:'GIOVANNI', title:'Líder Team Rocket', badge:'TIERRA',   color:'#D97706',team:[{id:111,lv:50},{id:112,lv:53},{id:34,lv:55}],reward:{ultraballs:2,revivals:1}},
  {id:8, leader:'LORELEI',  title:'Elite 4 · Hielo',  badge:'ÉLITE I',  color:'#BAE6FD',team:[{id:87,lv:54},{id:91,lv:54},{id:131,lv:58},{id:124,lv:60}],reward:{ultraballs:3,revivals:1}},
  {id:9, leader:'LANCE',    title:'Campeón Dragón',   badge:'CAMPEÓN',  color:'#FF6B00',team:[{id:148,lv:58},{id:148,lv:60},{id:149,lv:64}],reward:{masterballs:1,revivals:2}},
  {id:10,leader:'AGATHA',   title:'Elite 4 Fantasma', badge:'SOMBRA',   color:'#7C3AED',team:[{id:92,lv:56},{id:93,lv:58},{id:94,lv:62}],  reward:{ultraballs:3,revivals:1}},
  {id:11,leader:'BRUNO',    title:'Elite 4 Lucha',    badge:'PUÑO',     color:'#B45309',team:[{id:106,lv:55},{id:107,lv:57},{id:68,lv:60}], reward:{ultraballs:3,berries:3}},
  {id:12,leader:'ARTICUNO', title:'Ave Legendaria',   badge:'HIELO',    color:'#BAE6FD',team:[{id:144,lv:62}],                              reward:{masterballs:1,revivals:2}},
  {id:13,leader:'VENUSAUR', title:'Maestro Planta',   badge:'PETAL',    color:'#22C55E',team:[{id:3,lv:65},{id:45,lv:63},{id:71,lv:64}],   reward:{ultraballs:3,berries:5}},
  {id:14,leader:'ZAPDOS',   title:'Ave Legendaria',   badge:'RAYO',     color:'#FACC15',team:[{id:145,lv:70}],                              reward:{masterballs:1,revivals:2}},
  {id:15,leader:'CHARIZARD',title:'Maestro Fuego',    badge:'LLAMA',    color:'#EF4444',team:[{id:6,lv:72},{id:59,lv:70},{id:126,lv:74}],  reward:{masterballs:1,revivals:3}},
  {id:16,leader:'MOLTRES',  title:'Ave Legendaria',   badge:'BRASA',    color:'#EF4444',team:[{id:146,lv:78}],                              reward:{masterballs:1,revivals:3}},
  {id:17,leader:'DRAGONITE',title:'Maestro Dragón',   badge:'DRAGÓN',   color:'#6D28D9',team:[{id:149,lv:82},{id:148,lv:80},{id:130,lv:84}],reward:{masterballs:2,revivals:2}},
  {id:18,leader:'BLASTOISE',title:'Maestro Agua',     badge:'OLA',      color:'#3B82F6',team:[{id:9,lv:87},{id:131,lv:85},{id:55,lv:84}],  reward:{masterballs:2,revivals:3}},
  {id:19,leader:'MEWTWO',   title:'El Más Poderoso',  badge:'MAESTRO',  color:'#EC4899',team:[{id:150,lv:100}],                             reward:{masterballs:3,revivals:5}},
];

// ── Tipos Gen I ────────────────────────────────────────────
const PTYPE = {
  1:'grass',2:'grass',3:'grass',4:'fire',5:'fire',6:'fire',
  7:'water',8:'water',9:'water',10:'bug',11:'bug',12:'bug',
  13:'bug',14:'bug',15:'bug',16:'normal',17:'normal',18:'normal',
  19:'normal',20:'normal',21:'normal',22:'normal',23:'poison',24:'poison',
  25:'electric',26:'electric',27:'normal',28:'normal',29:'poison',30:'poison',
  31:'poison',32:'poison',33:'poison',34:'poison',35:'normal',36:'normal',
  37:'fire',38:'fire',39:'normal',40:'normal',41:'poison',42:'poison',
  43:'grass',44:'grass',45:'grass',46:'bug',47:'bug',48:'bug',49:'bug',
  50:'ground',51:'ground',52:'normal',53:'normal',54:'water',55:'water',
  56:'fighting',57:'fighting',58:'fire',59:'fire',60:'water',61:'water',
  62:'water',63:'psychic',64:'psychic',65:'psychic',66:'fighting',
  67:'fighting',68:'fighting',69:'grass',70:'grass',71:'grass',
  72:'water',73:'water',74:'rock',75:'rock',76:'rock',77:'fire',
  78:'fire',79:'water',80:'water',81:'electric',82:'electric',
  83:'normal',84:'normal',85:'normal',86:'water',87:'water',
  88:'poison',89:'poison',90:'water',91:'water',92:'ghost',
  93:'ghost',94:'ghost',95:'rock',96:'psychic',97:'psychic',
  98:'water',99:'water',100:'electric',101:'electric',102:'grass',
  103:'grass',104:'ground',105:'ground',106:'fighting',107:'fighting',
  108:'normal',109:'poison',110:'poison',111:'ground',112:'ground',
  113:'normal',114:'grass',115:'normal',116:'water',117:'water',
  118:'water',119:'water',120:'water',121:'water',122:'psychic',
  123:'bug',124:'ice',125:'electric',126:'fire',127:'bug',128:'normal',
  129:'water',130:'water',131:'water',132:'normal',133:'normal',
  134:'water',135:'electric',136:'fire',137:'normal',138:'rock',
  139:'rock',140:'rock',141:'rock',142:'rock',143:'normal',
  144:'ice',145:'electric',146:'fire',147:'dragon',148:'dragon',
  149:'dragon',150:'psychic',
};

// ── Nombres Gen I ──────────────────────────────────────────
const PNAMES = {
  1:'Bulbasaur',2:'Ivysaur',3:'Venusaur',4:'Charmander',5:'Charmeleon',
  6:'Charizard',7:'Squirtle',8:'Wartortle',9:'Blastoise',10:'Caterpie',
  11:'Metapod',12:'Butterfree',13:'Weedle',14:'Kakuna',15:'Beedrill',
  16:'Pidgey',17:'Pidgeotto',18:'Pidgeot',19:'Rattata',20:'Raticate',
  21:'Spearow',22:'Fearow',23:'Ekans',24:'Arbok',25:'Pikachu',
  26:'Raichu',27:'Sandshrew',28:'Sandslash',29:'NidoranF',30:'Nidorina',
  31:'Nidoqueen',32:'NidoranM',33:'Nidorino',34:'Nidoking',35:'Clefairy',
  36:'Clefable',37:'Vulpix',38:'Ninetales',39:'Jigglypuff',40:'Wigglytuff',
  41:'Zubat',42:'Golbat',43:'Oddish',44:'Gloom',45:'Vileplume',
  46:'Paras',47:'Parasect',48:'Venonat',49:'Venomoth',50:'Diglett',
  51:'Dugtrio',52:'Meowth',53:'Persian',54:'Psyduck',55:'Golduck',
  56:'Mankey',57:'Primeape',58:'Growlithe',59:'Arcanine',60:'Poliwag',
  61:'Poliwhirl',62:'Poliwrath',63:'Abra',64:'Kadabra',65:'Alakazam',
  66:'Machop',67:'Machoke',68:'Machamp',69:'Bellsprout',70:'Weepinbell',
  71:'Victreebel',72:'Tentacool',73:'Tentacruel',74:'Geodude',75:'Graveler',
  76:'Golem',77:'Ponyta',78:'Rapidash',79:'Slowpoke',80:'Slowbro',
  81:'Magnemite',82:'Magneton',83:"Farfetch'd",84:'Doduo',85:'Dodrio',
  86:'Seel',87:'Dewgong',88:'Grimer',89:'Muk',90:'Shellder',91:'Cloyster',
  92:'Gastly',93:'Haunter',94:'Gengar',95:'Onix',96:'Drowzee',97:'Hypno',
  98:'Krabby',99:'Kingler',100:'Voltorb',101:'Electrode',102:'Exeggcute',
  103:'Exeggutor',104:'Cubone',105:'Marowak',106:'Hitmonlee',107:'Hitmonchan',
  108:'Lickitung',109:'Koffing',110:'Weezing',111:'Rhyhorn',112:'Rhydon',
  113:'Chansey',114:'Tangela',115:'Kangaskhan',116:'Horsea',117:'Seadra',
  118:'Goldeen',119:'Seaking',120:'Staryu',121:'Starmie',122:'Mr.Mime',
  123:'Scyther',124:'Jynx',125:'Electabuzz',126:'Magmar',127:'Pinsir',
  128:'Tauros',129:'Magikarp',130:'Gyarados',131:'Lapras',132:'Ditto',
  133:'Eevee',134:'Vaporeon',135:'Jolteon',136:'Flareon',137:'Porygon',
  138:'Omanyte',139:'Omastar',140:'Kabuto',141:'Kabutops',142:'Aerodactyl',
  143:'Snorlax',144:'Articuno',145:'Zapdos',146:'Moltres',147:'Dratini',
  148:'Dragonair',149:'Dragonite',150:'Mewtwo',
};

const STARTERS = [
  {id:1, name:'Bulbasaur', type:'grass',hp:45,atk:49,def:49,spd:45},
  {id:4, name:'Charmander',type:'fire', hp:39,atk:52,def:43,spd:65},
  {id:7, name:'Squirtle',  type:'water',hp:44,atk:48,def:65,spd:43},
];

// ── Cadenas de evolución ────────────────────────────────────
const EVOLUTIONS = {
  1:{to:2,level:16},2:{to:3,level:32},4:{to:5,level:16},5:{to:6,level:36},
  7:{to:8,level:16},8:{to:9,level:36},10:{to:11,level:7},11:{to:12,level:10},
  13:{to:14,level:7},14:{to:15,level:10},16:{to:17,level:18},17:{to:18,level:36},
  19:{to:20,level:20},21:{to:22,level:20},23:{to:24,level:22},27:{to:28,level:22},
  29:{to:30,level:16},30:{to:31,level:36},32:{to:33,level:16},33:{to:34,level:36},
  41:{to:42,level:22},43:{to:44,level:21},44:{to:45,level:36},46:{to:47,level:24},
  48:{to:49,level:31},50:{to:51,level:26},52:{to:53,level:28},54:{to:55,level:33},
  56:{to:57,level:28},60:{to:61,level:25},61:{to:62,level:45},63:{to:64,level:16},
  64:{to:65,level:42},66:{to:67,level:28},67:{to:68,level:42},69:{to:70,level:21},
  70:{to:71,level:36},72:{to:73,level:30},74:{to:75,level:25},75:{to:76,level:42},
  77:{to:78,level:40},79:{to:80,level:37},81:{to:82,level:30},84:{to:85,level:31},
  86:{to:87,level:34},88:{to:89,level:38},92:{to:93,level:25},93:{to:94,level:36},
  96:{to:97,level:26},98:{to:99,level:28},100:{to:101,level:30},104:{to:105,level:28},
  109:{to:110,level:35},111:{to:112,level:42},116:{to:117,level:32},
  118:{to:119,level:33},129:{to:130,level:20},147:{to:148,level:30},148:{to:149,level:55},
};

// ── Pokéballs ──────────────────────────────────────────────
const BALL_TYPES = [
  {id:'pokeballs',  name:'Pokéball',  mult:1.0, color:'#EF4444',
   sprite:'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/items/poke-ball.png'},
  {id:'greatballs', name:'Superball', mult:1.5, color:'#3B82F6',
   sprite:'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/items/great-ball.png'},
  {id:'ultraballs', name:'Ultraball', mult:2.0, color:'#FACC15',
   sprite:'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/items/ultra-ball.png'},
  {id:'masterballs',name:'Masterball',mult:255, color:'#A855F7',
   sprite:'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/items/master-ball.png'},
];

const CATCH_RATES = {
  1:45,2:45,3:45,4:45,5:45,6:45,7:45,8:45,9:45,10:255,11:120,12:45,13:255,14:120,15:45,
  16:255,17:120,18:45,19:255,20:127,21:255,22:100,23:190,24:90,25:190,26:75,27:255,28:90,
  29:235,30:120,31:45,32:235,33:120,34:45,35:150,36:25,37:190,38:75,39:170,40:50,
  41:255,42:90,43:255,44:120,45:45,46:190,47:75,48:190,49:75,50:255,51:50,
  52:255,53:90,54:190,55:75,56:190,57:75,58:190,59:75,60:255,61:120,62:45,
  63:200,64:100,65:50,66:180,67:90,68:45,69:255,70:120,71:45,72:190,73:100,
  74:255,75:120,76:45,77:190,78:60,79:190,80:75,81:190,82:60,83:45,
  84:190,85:75,86:190,87:75,88:190,89:75,90:190,91:60,92:190,93:90,94:45,
  95:45,96:190,97:75,98:225,99:60,100:190,101:60,102:90,103:45,104:190,105:75,
  106:45,107:45,108:45,109:190,110:60,111:120,112:60,113:30,114:45,115:45,
  116:225,117:75,118:225,119:60,120:225,121:60,122:45,123:45,124:45,
  125:45,126:45,127:45,128:45,129:255,130:45,131:45,132:35,
  133:45,134:45,135:45,136:45,137:45,138:45,139:45,140:45,141:45,142:45,143:25,
  144:3,145:3,146:3,147:45,148:45,149:45,150:3,
};

const calcCatchChance = (pokemonId,ballMult,hpLeft,maxHp,level) => {
  const base=CATCH_RATES[pokemonId]||45;
  const hpFactor=(3*maxHp-2*hpLeft)/(3*maxHp);
  const lvFactor=Math.max(0.08,1-level*0.007);
  return Math.min(0.97,Math.max(0.02,(base*ballMult*hpFactor*lvFactor)/255));
};

// ── Stats ──────────────────────────────────────────────────
const calcMaxHp  = (base,lv) => Math.floor((2*base*lv)/100+lv+10);
const calcAtk    = (base,lv) => Math.floor((2*base*lv)/100+5);
const calcDef    = (base,lv) => Math.floor((2*base*lv)/100+5);
const calcSpd    = (base,lv) => Math.floor((2*base*lv)/100+5);
const xpForLevel = (lv)      => Math.floor(lv*lv*100);
const xpGain     = (enemyLv) => Math.floor(enemyLv*40+50);

const getBaseStats = (id) => {
  const t=id-1;
  return {
    hp: 40+Math.floor(t*0.35),
    atk:38+Math.floor(t*0.30),
    def:35+Math.floor(t*0.25),
    spd:30+Math.floor(t*0.28),
  };
};

// ── Hora del día ───────────────────────────────────────────
const getDayPhase = () => {
  const h=new Date().getHours();
  if(h>=6&&h<8)   return 'dawn';
  if(h>=8&&h<18)  return 'day';
  if(h>=18&&h<21) return 'dusk';
  return 'night';
};
const DAY_TINTS = {
  dawn: 'rgba(255,160,50,0.16)',
  day:  'rgba(0,0,0,0)',
  dusk: 'rgba(220,80,20,0.20)',
  night:'rgba(10,10,60,0.35)',
};
const DAY_LABELS = { dawn:'🌅 Amanecer', day:'☀️ Día', dusk:'🌇 Atardecer', night:'🌙 Noche' };

// ── SFX: Web Audio API ─────────────────────────────────────
const SFX = (() => {
  let ctx=null;
  const getCtx=()=>{
    if(!ctx) try{ ctx=new(window.AudioContext||window.webkitAudioContext)(); }catch(e){}
    return ctx;
  };
  const tone=(freq,dur,type='square',vol=0.12,delay=0)=>{
    try{
      const c=getCtx(); if(!c) return;
      const osc=c.createOscillator();
      const gain=c.createGain();
      osc.connect(gain); gain.connect(c.destination);
      osc.type=type; osc.frequency.value=freq;
      const t=c.currentTime+delay;
      gain.gain.setValueAtTime(vol,t);
      gain.gain.exponentialRampToValueAtTime(0.001,t+dur);
      osc.start(t); osc.stop(t+dur);
    }catch(e){}
  };
  return {
    hit:    ()=>{ tone(160,0.07,'square',0.10); },
    miss:   ()=>{ tone(80,0.12,'triangle',0.07); },
    menu:   ()=>{ tone(440,0.04,'square',0.07); },
    capture:()=>{ tone(440,0.09,undefined,undefined,0); tone(554,0.09,undefined,undefined,0.11); tone(659,0.18,undefined,undefined,0.22); },
    fail:   ()=>{ [300,220,180].forEach((f,i)=>tone(f,0.08,'triangle',0.08,i*0.09)); },
    levelUp:()=>{ [523,659,784,1047].forEach((f,i)=>tone(f,0.13,'triangle',0.10,i*0.09)); },
    evolution:()=>{ [262,330,392,523,659,784,1047].forEach((f,i)=>tone(f,0.10,'sine',0.09,i*0.07)); },
    gymWin: ()=>{ [523,523,523,659,523,659,784].forEach((f,i)=>tone(f,0.13,'square',0.10,i*0.10)); },
    faint:  ()=>{ [440,350,280,220].forEach((f,i)=>tone(f,0.09,'triangle',0.07,i*0.08)); },
    ball:   ()=>{ tone(300,0.04,undefined,undefined,0); tone(200,0.08,'triangle',0.06,0.06); },
    start:  ()=>{ [330,392,523].forEach((f,i)=>tone(f,0.12,'triangle',0.10,i*0.08)); },
  };
})();

// ── Sprites ────────────────────────────────────────────────
const spriteAnimated = id =>
  `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-v/black-white/animated/${id}.gif`;
const spriteStatic = id =>
  `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${id}.png`;
const spriteBack = id =>
  `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/back/${id}.png`;

const createPlayerPokemon = (id,name,type,baseHp,baseAtk,baseDef,level=5) => {
  const bs=getBaseStats(id);
  const maxHp=calcMaxHp(baseHp,level);
  return {
    uid:`${id}_${Date.now()}_${Math.random().toString(36).slice(2)}`,
    id,name,type,level,baseHp,baseAtk,baseDef,baseSpd:bs.spd,
    hp:maxHp,maxHp,xp:0,xpNeeded:xpForLevel(level+1),faintedAt:null,
  };
};

const COOLDOWN_MS=6*60*60*1000;
const ACTIVE_TEAM_SIZE=3;
const BOX_CAPACITY=100;
const ITEM_XP_GAIN=100;

const sameIndexList=(a,b)=>
  Array.isArray(a)&&Array.isArray(b)&&a.length===b.length&&a.every((v,i)=>v===b[i]);

const uniqueValidTeam=(team,total)=>{
  const out=[];
  (Array.isArray(team)?team:[]).forEach(i=>{
    if(Number.isInteger(i)&&i>=0&&i<total&&!out.includes(i)&&out.length<ACTIVE_TEAM_SIZE) out.push(i);
  });
  return out;
};

const getActiveTeamIndexes=state=>{
  const total=state?.pokemon?.length||0;
  if(total<=0) return [];
  let active=Number.isInteger(state.activePkmIndex)?state.activePkmIndex:0;
  if(active<0||active>=total) active=0;
  let team=uniqueValidTeam(state.activeTeam,total);
  if(team.length===0) team=[active];
  if(!team.includes(active)) team=[active,...team].filter((i,pos,arr)=>arr.indexOf(i)===pos).slice(0,ACTIVE_TEAM_SIZE);
  return team;
};

const normalizeState=(state,now=Date.now())=>{
  if(!state) return state;
  let changed=false;
  let pokemon=Array.isArray(state.pokemon)?state.pokemon:[];
  if(pokemon.length!==(state.pokemon?.length||0)) changed=true;
  pokemon=pokemon.map(p=>{
    if(!p) return p;
    const bs=getBaseStats(p.id);
    const maxHp=p.maxHp||calcMaxHp(p.baseHp||bs.hp,p.level||5);
    let next=p;
    if(maxHp!==p.maxHp){ next={...next,maxHp}; changed=true; }
    if(p.faintedAt&&now-p.faintedAt>=COOLDOWN_MS){
      next={...next,hp:maxHp,faintedAt:null};
      changed=true;
    }else if(p.hp===undefined||p.hp===null||p.hp>maxHp){
      next={...next,hp:Math.min(maxHp,p.hp??maxHp)};
      changed=true;
    }
    return next;
  });
  let activePkmIndex=Number.isInteger(state.activePkmIndex)?state.activePkmIndex:0;
  if(pokemon.length===0){
    if(activePkmIndex!==0){ activePkmIndex=0; changed=true; }
  }else if(activePkmIndex<0||activePkmIndex>=pokemon.length){
    activePkmIndex=0;
    changed=true;
  }
  const activeTeam=getActiveTeamIndexes({...state,pokemon,activePkmIndex});
  if(!sameIndexList(activeTeam,state.activeTeam||[])) changed=true;
  if(!changed) return state;
  return{...state,pokemon,activePkmIndex,activeTeam};
};

const grantTeamExperience=(state,gained,opts={})=>{
  const now=opts.now||Date.now();
  const activeTeam=getActiveTeamIndexes(state);
  const activeHpByIndex=opts.activeHpByIndex||{};
  const newList=[...(state.pokemon||[])];
  const messages=[];
  let pendingEvolution=state.pendingEvolution||null;
  activeTeam.forEach(idx=>{
    const p=newList[idx];
    if(!p) return;
    let next={...p};
    if(Object.prototype.hasOwnProperty.call(activeHpByIndex,idx)) next.hp=activeHpByIndex[idx];
    next.xp=(next.xp||0)+gained;
    next.xpNeeded=next.xpNeeded||xpForLevel((next.level||1)+1);
    while(next.xp>=next.xpNeeded){
      next.level+=1;
      next.xp-=next.xpNeeded;
      next.xpNeeded=xpForLevel(next.level+1);
      next.maxHp=calcMaxHp(next.baseHp,next.level);
      const cooling=next.faintedAt&&now-next.faintedAt<COOLDOWN_MS;
      if(!cooling) next.hp=Math.min((next.hp||0)+10,next.maxHp);
      messages.push(`${next.name} sube a Lv.${next.level}`);
      SFX.levelUp();
      const evo=EVOLUTIONS[next.id];
      if(evo&&next.level>=evo.level&&!pendingEvolution)
        pendingEvolution={fromId:next.id,toId:evo.to,pkmIndex:idx};
    }
    newList[idx]=next;
  });
  return{state:{...state,pokemon:newList,activeTeam,pendingEvolution},messages};
};

// ── Estado inicial ─────────────────────────────────────────
const SAVE_KEY='pokenav_r1_v03';
const INITIAL_STATE={
  screen:'splash',lobbyMenuIndex:0,
  pokemon:[],activePkmIndex:0,activeTeam:[],
  inventory:{pokeballs:5,greatballs:2,ultraballs:1,masterballs:0,berries:3,revivals:0},
  scenario:0,
  exploreLog:['Caminando...'],
  exploring:false,
  combat:null,
  pendingEvolution:null,
  badges:[],
  defeatedGyms:[],
  statsTarget:null, // índice del Pokemon para ver stats
  statsReturnScreen:null,
};

const loadState=()=>{
  try{
    const raw=localStorage.getItem(SAVE_KEY);
    if(raw){
      const s=JSON.parse(raw);
      if(!s.pokemon||s.pokemon.length===0) return{...INITIAL_STATE};
      const inv={...INITIAL_STATE.inventory,...s.inventory};
      return normalizeState({...INITIAL_STATE,...s,inventory:inv,screen:'lobby',combat:null,pendingEvolution:null});
    }
  }catch(e){}
  return{...INITIAL_STATE};
};
const saveState=state=>{
  try{
    const{combat,pendingEvolution,...t}=state;
    localStorage.setItem(SAVE_KEY,JSON.stringify(t));
  }catch(e){}
};

// ── REDUCER ────────────────────────────────────────────────
function gameReducer(state,action){
  state=normalizeState(state);
  switch(action.type){

    case 'START_GAME':{
      const s=action.starter;
      const pkm=createPlayerPokemon(s.id,s.name,s.type,s.hp,s.atk,s.def,5);
      SFX.start();
      return{...state,screen:'lobby',pokemon:[pkm],activePkmIndex:0,activeTeam:[0]};
    }

    case 'TICK_COOLDOWNS': return state;

    case 'LOBBY_SCROLL':{
      const next=(state.lobbyMenuIndex+action.delta+5)%5;
      SFX.menu();
      return{...state,lobbyMenuIndex:next};
    }

    case 'START_EXPLORE':{
      const pkm=state.pokemon[state.activePkmIndex];
      if(!pkm||pkm.hp<=0||(pkm.faintedAt&&Date.now()-pkm.faintedAt<COOLDOWN_MS)) return state;
      return{...state,screen:'explore',exploring:true,exploreLog:['Explorando...']};
    }
    case 'STOP_EXPLORE':  return{...state,screen:'lobby',exploring:false};

    case 'EXPLORE_EVENT':{
      const pkm=state.pokemon[state.activePkmIndex];
      if(!pkm) return state;
      const r=Math.random();
      const grantItem=(nextState,msg)=>{
        const xp=grantTeamExperience(nextState,ITEM_XP_GAIN);
        return{...xp.state,exploreLog:[...state.exploreLog,msg,`Equipo PKM +${ITEM_XP_GAIN} XP`,...xp.messages]};
      };
      // Probabilidades: bayas 40%, pokeballs 13%, superball 5%, ultraball 3%, masterball 0.2%, revivir 8%, combate 30.8%
      if(r<0.40){
        const n=1+Math.floor(Math.random()*3);
        return grantItem({...state,inventory:{...state.inventory,berries:(state.inventory.berries||0)+n}},
          `Encontraste ${n} Baya${n>1?'s':''}`);
      }else if(r<0.53){
        const n=1+Math.floor(Math.random()*2);
        return grantItem({...state,inventory:{...state.inventory,pokeballs:(state.inventory.pokeballs||0)+n}},
          `${n} Pokeball${n>1?'s':''}`);
      }else if(r<0.58){
        return grantItem({...state,inventory:{...state.inventory,greatballs:(state.inventory.greatballs||0)+1}},
          'Una Superball');
      }else if(r<0.61){
        return grantItem({...state,inventory:{...state.inventory,ultraballs:(state.inventory.ultraballs||0)+1}},
          'Una Ultraball');
      }else if(r<0.612){
        return grantItem({...state,inventory:{...state.inventory,masterballs:(state.inventory.masterballs||0)+1}},
          'MASTERBALL');
      }else if(r<0.692){
        return grantItem({...state,inventory:{...state.inventory,revivals:(state.inventory.revivals||0)+1}},
          'Un Revivir');
      }else{
        const pool=SCENARIO_POOLS[state.scenario]||SCENARIO_POOLS[0];
        const enemyId=pool[Math.floor(Math.random()*pool.length)];
        const sc=SCENARIOS[state.scenario];
        const minLv=sc?sc.minLv:1;
        const enemyLv=Math.max(1,minLv+Math.floor(Math.random()*10));
        const bs=getBaseStats(enemyId);
        const enemy={id:enemyId,name:PNAMES[enemyId]||`#${enemyId}`,level:enemyLv,
          hp:bs.hp,atk:bs.atk,def:bs.def,maxHp:calcMaxHp(bs.hp,enemyLv)};
        return{...state,screen:'combat',exploring:false,
          exploreLog:[...state.exploreLog,`¡${enemy.name} Lv${enemyLv}!`],
          combat:{enemy,playerHp:pkm.hp,enemyHp:enemy.maxHp,
            log:[`¡${enemy.name} salvaje!`,'Auto-combate...'],
            particles:[],phase:'idle',turn:0,captureSuccess:null,isGymBattle:false}};
      }
    }

    case 'COMBAT_TICK':{
      if(!state.combat) return state;
      const{combat}=state;
      if(['victory','capture_anim','player_fainted','gym_victory'].includes(combat.phase)) return state;
      const pkm=state.pokemon[state.activePkmIndex];
      const isPlayerTurn=(combat.turn%2===0);
      let newPlayerHp=combat.playerHp;
      let newEnemyHp=combat.enemyHp;
      const newLog=[...combat.log];

      const lvDiff=isPlayerTurn?(pkm.level-combat.enemy.level):(combat.enemy.level-pkm.level);
      const lvMult=Math.max(0.5,Math.min(2.5,1+lvDiff*0.05));

      if(isPlayerTurn){
        const atk=calcAtk(pkm.baseAtk||49,pkm.level);
        const def=calcDef(combat.enemy.def,combat.enemy.level);
        const dmg=Math.max(1,Math.floor((Math.max(1,atk-def*0.4)+Math.random()*6)*lvMult));
        newEnemyHp=Math.max(0,newEnemyHp-dmg);
        newLog.push(`${pkm.name}: -${dmg} HP`);
        SFX.hit();
      }else{
        const atk=calcAtk(combat.enemy.atk,combat.enemy.level);
        const def=calcDef(pkm.baseDef||49,pkm.level);
        const dmg=Math.max(1,Math.floor((Math.max(1,atk-def*0.4)+Math.random()*6)*lvMult));
        newPlayerHp=Math.max(0,newPlayerHp-dmg);
        newLog.push(`${combat.enemy.name}: -${dmg} HP`);
        SFX.hit();
      }

      const atkType=isPlayerTurn?(pkm.type||'normal'):(PTYPE[combat.enemy.id]||'normal');
      const particles=Array.from({length:6},(_,i)=>({
        id:`${combat.turn}_${i}`,
        x:isPlayerTurn?(80+Math.random()*80):(20+Math.random()*80),
        y:40+Math.random()*80,
        color:TYPE_COL[atkType]||'#FFF',
      }));

      // Victoria
      if(newEnemyHp<=0){
        const gained=xpGain(combat.enemy.level);
        const xp=grantTeamExperience(state,gained,{activeHpByIndex:{[state.activePkmIndex]:newPlayerHp}});
        const rewardedState=xp.state;
        const xpLog=[`Equipo PKM +${gained} XP`,...xp.messages];
        const rewardedPlayerHp=rewardedState.pokemon[state.activePkmIndex]?.hp??newPlayerHp;
        if(combat.isGymBattle){
          const gym=GYMS[combat.gymId];
          const nextIdx=(combat.gymPokemonIndex||0)+1;
          if(nextIdx<gym.team.length){
            const next=gym.team[nextIdx];
            const bs=getBaseStats(next.id);
            const nextEnemy={id:next.id,name:PNAMES[next.id]||`#${next.id}`,level:next.lv,
              hp:bs.hp,atk:bs.atk,def:bs.def,maxHp:calcMaxHp(bs.hp,next.lv)};
            return{...rewardedState,combat:{...combat,enemy:nextEnemy,enemyHp:nextEnemy.maxHp,
              playerHp:rewardedPlayerHp,log:[...xpLog.slice(-2),`${gym.leader} lanza a ${nextEnemy.name}`],
              particles:[],phase:'idle',turn:0,gymPokemonIndex:nextIdx}};
          }else{
            SFX.gymWin();
            return{...rewardedState,combat:{...combat,enemyHp:0,playerHp:rewardedPlayerHp,xpLog,
              log:[...newLog.slice(-2),...xpLog,'GIMNASIO SUPERADO'],phase:'gym_victory',particles:[]}};
          }
        }
        return{...rewardedState,combat:{...combat,enemyHp:0,playerHp:rewardedPlayerHp,xpLog,
          log:[...newLog.slice(-2),...xpLog,'Enemigo derrotado'],phase:'victory',particles:[],captureSuccess:null}};
      }

      // Derrota del jugador
      if(newPlayerHp<=0){
        const now=Date.now();
        const team=getActiveTeamIndexes(state);
        const hasBackup=team.some(idx=>{
          const p=state.pokemon[idx];
          return idx!==state.activePkmIndex&&p?.hp>0&&(!p.faintedAt||now-p.faintedAt>=COOLDOWN_MS);
        });
        SFX.faint();
        if(hasBackup){
          return{...state,combat:{...combat,playerHp:0,
            log:[...newLog.slice(-4),`¡${pkm.name} debilitado!`,'¡Elige otro!'],
            phase:'player_fainted',particles:[]}};
        }else{
          const newList=[...state.pokemon];
          newList[state.activePkmIndex]={...newList[state.activePkmIndex],hp:0,faintedAt:Date.now()};
          return{...state,screen:'lobby',pokemon:newList,combat:null,
            exploreLog:[`¡${pkm.name} fue debilitado!`,`Cooldown 6h...`]};
        }
      }

      return{...state,combat:{...combat,playerHp:newPlayerHp,enemyHp:newEnemyHp,
        log:newLog.slice(-4),particles,phase:isPlayerTurn?'player_attack':'enemy_attack',turn:combat.turn+1}};
    }

    // ── Victoria salvaje: reclamar XP ──────────────────────
    case 'CLAIM_VICTORY':{
      if(!state.combat||state.combat.phase!=='victory') return state;
      const xpLog=state.combat.xpLog||[];
      return{...state,screen:'lobby',combat:null,exploreLog:['Victoria',...xpLog]};
    }

    // ── Lanzar Pokéball ────────────────────────────────────
    case 'THROW_BALL':{
      if(!state.combat||state.combat.phase!=='victory') return state;
      const ball=BALL_TYPES.find(b=>b.id===action.ballId);
      if(!ball) return state;
      const inv={...state.inventory};
      if((inv[action.ballId]||0)<=0) return state;
      inv[action.ballId]-=1;
      const{combat}=state;
      const chance=calcCatchChance(combat.enemy.id,ball.mult,combat.enemyHp,combat.enemy.maxHp,combat.enemy.level);
      const success=Math.random()<chance;
      SFX.ball();
      return{...state,inventory:inv,
        combat:{...combat,phase:'capture_anim',captureSuccess:success,captureBall:action.ballId}};
    }

    case 'FINISH_CAPTURE':{
      if(!state.combat) return state;
      const{combat}=state;
      if(combat.captureSuccess){
        SFX.capture();
        const bs=getBaseStats(combat.enemy.id);
        const cap=createPlayerPokemon(combat.enemy.id,combat.enemy.name,
          PTYPE[combat.enemy.id]||'normal',bs.hp,bs.atk,bs.def,combat.enemy.level);
        const newList=[...state.pokemon];
        const xpLog=combat.xpLog||[];
        if(newList.length>=BOX_CAPACITY){
          return{...state,screen:'lobby',combat:null,
            exploreLog:['Caja llena: captura perdida',...xpLog]};
        }
        newList.push(cap);
        return{...state,screen:'lobby',pokemon:newList,combat:null,
          exploreLog:[`${combat.enemy.name} capturado`,...xpLog]};
      }else{
        SFX.fail();
        return{...state,combat:{...combat,phase:'victory',captureSuccess:null,
          log:[...combat.log,'Escapo']}};
      }
    }

    case 'FLEE_COMBAT':{
      const newList=[...state.pokemon];
      const oldActive=newList[state.activePkmIndex];
      const finalHp=state.combat?.playerHp??oldActive.hp;
      const active=finalHp<=0?{...oldActive,hp:0,faintedAt:Date.now()}:{...oldActive,hp:finalHp};
      newList[state.activePkmIndex]=active;
      return{...state,screen:'lobby',pokemon:newList,combat:null,exploreLog:['Huiste del combate.']};
    }

    // ── Cambio de Pokémon en combate ──────────────────────
    case 'SWITCH_POKEMON':{
      const{index}=action;
      const p=state.pokemon[index];
      const team=getActiveTeamIndexes(state);
      if(!team.includes(index)||!p||p.hp<=0||(p.faintedAt&&Date.now()-p.faintedAt<COOLDOWN_MS)) return state;
      const newList=[...state.pokemon];
      // Debilitar al Pokémon actual
      newList[state.activePkmIndex]={...newList[state.activePkmIndex],hp:0,faintedAt:Date.now()};
      SFX.menu();
      return{...state,activePkmIndex:index,pokemon:newList,
        combat:{...state.combat,playerHp:p.hp,phase:'idle',
          log:[...state.combat.log,`¡${p.name} al frente!`]}};
    }

    // ── Gimnasio ───────────────────────────────────────────
    case 'START_GYM':{
      const gymId=state.scenario;
      const gym=GYMS[gymId];
      if(!gym) return state;
      const pkm=state.pokemon[state.activePkmIndex];
      if(!pkm||pkm.hp<=0||(pkm.faintedAt&&Date.now()-pkm.faintedAt<COOLDOWN_MS)) return state;
      const boss=gym.team[0];
      const bs=getBaseStats(boss.id);
      const enemy={id:boss.id,name:PNAMES[boss.id]||`#${boss.id}`,level:boss.lv,
        hp:bs.hp,atk:bs.atk,def:bs.def,maxHp:calcMaxHp(bs.hp,boss.lv)};
      SFX.start();
      return{...state,screen:'combat',
        combat:{enemy,playerHp:pkm.hp,enemyHp:enemy.maxHp,
          log:[`¡${gym.leader} quiere combatir!`,`¡${enemy.name} Lv${boss.lv}!`],
          particles:[],phase:'idle',turn:0,captureSuccess:null,
          isGymBattle:true,gymId,gymPokemonIndex:0}};
    }

    case 'CLAIM_GYM_VICTORY':{
      if(!state.combat?.isGymBattle) return state;
      const{gymId,playerHp}=state.combat;
      const gym=GYMS[gymId];
      const newInv={...state.inventory};
      if(gym.reward) Object.entries(gym.reward).forEach(([k,v])=>{newInv[k]=(newInv[k]||0)+v;});
      const defeatedGyms=[...(state.defeatedGyms||[])];
      if(!defeatedGyms.includes(gymId)) defeatedGyms.push(gymId);
      const newBadges=[...(state.badges||[])];
      if(!newBadges.includes(gym.badge)) newBadges.push(gym.badge);
      // Aplicar HP final al Pokémon activo
      const newList=[...state.pokemon];
      newList[state.activePkmIndex]={...newList[state.activePkmIndex],hp:playerHp};
      const xpLog=state.combat.xpLog||[];
      return{...state,screen:'lobby',combat:null,inventory:newInv,pokemon:newList,
        badges:newBadges,defeatedGyms,
        exploreLog:[`${gym.leader} derrotado`,`Medalla ${gym.badge}`,...xpLog]};
    }

    // ── Evolución ──────────────────────────────────────────
    case 'CONFIRM_EVOLUTION':{
      if(!state.pendingEvolution) return state;
      const{toId,pkmIndex}=state.pendingEvolution;
      const newList=[...state.pokemon];
      const old=newList[pkmIndex];
      const bs=getBaseStats(toId);
      const newMaxHp=calcMaxHp(bs.hp,old.level);
      newList[pkmIndex]={...old,id:toId,name:PNAMES[toId]||`#${toId}`,
        type:PTYPE[toId]||old.type,baseHp:bs.hp,baseAtk:bs.atk,baseDef:bs.def,baseSpd:bs.spd,
        maxHp:newMaxHp,hp:Math.min(old.hp+25,newMaxHp)};
      return{...state,pokemon:newList,pendingEvolution:null,
        exploreLog:[`¡${old.name} → ${PNAMES[toId]}!`]};
    }
    case 'CANCEL_EVOLUTION': return{...state,pendingEvolution:null};

    // ── Items ──────────────────────────────────────────────
    case 'USE_BERRY':{
      if(state.inventory.berries<=0) return state;
      const pkm=state.pokemon[state.activePkmIndex];
      if(!pkm) return state;
      if(pkm.faintedAt&&Date.now()-pkm.faintedAt<COOLDOWN_MS) return state;
      const newList=[...state.pokemon];
      newList[state.activePkmIndex]={...pkm,hp:Math.min(pkm.maxHp,pkm.hp+30)};
      return{...state,pokemon:newList,inventory:{...state.inventory,berries:state.inventory.berries-1}};
    }

    case 'USE_REVIVE':{
      const idx=action.index!==undefined?action.index:state.activePkmIndex;
      const p=state.pokemon[idx];
      if(!p||!p.faintedAt||(state.inventory.revivals||0)<=0) return state;
      const newList=[...state.pokemon];
      newList[idx]={...p,hp:Math.floor(p.maxHp*0.5),faintedAt:null};
      return{...state,pokemon:newList,
        inventory:{...state.inventory,revivals:(state.inventory.revivals||0)-1},
        exploreLog:[`¡${p.name} revivido!`]};
    }

    // ── Navegación ─────────────────────────────────────────
    case 'OPEN_BOX':        return{...state,screen:'box'};
    case 'CLOSE_BOX':       return{...state,screen:'lobby'};
    case 'OPEN_INVENTORY':  return{...state,screen:'inventory'};
    case 'CLOSE_INVENTORY': return{...state,screen:'lobby'};
    case 'OPEN_STATS':      return{...state,screen:'stats',
      statsTarget:action.index!==undefined?action.index:state.activePkmIndex,
      statsReturnScreen:state.screen==='stats'?'lobby':state.screen};
    case 'CLOSE_STATS':     return{...state,screen:state.statsReturnScreen||'lobby',statsReturnScreen:null};

    case 'SET_ACTIVE':{
      const p=state.pokemon[action.index];
      const team=getActiveTeamIndexes(state);
      if(!p) return state;
      if(!team.includes(action.index)||p.hp<=0||(p.faintedAt&&Date.now()-p.faintedAt<COOLDOWN_MS)) return state;
      return{...state,activePkmIndex:action.index,screen:'lobby'};
    }
    case 'ADD_TO_TEAM':{
      const idx=action.index;
      if(!state.pokemon[idx]) return state;
      const team=getActiveTeamIndexes(state);
      if(team.includes(idx)||team.length>=ACTIVE_TEAM_SIZE) return state;
      return{...state,activeTeam:[...team,idx],screen:'box'};
    }
    case 'REMOVE_FROM_TEAM':{
      const idx=action.index;
      const team=getActiveTeamIndexes(state);
      if(!team.includes(idx)||team.length<=1) return state;
      const nextTeam=team.filter(i=>i!==idx);
      const activePkmIndex=state.activePkmIndex===idx?nextTeam[0]:state.activePkmIndex;
      return{...state,activeTeam:nextTeam,activePkmIndex,screen:'box'};
    }
    case 'SET_TEAM_SLOT':{
      const idx=action.index;
      const slot=Math.max(0,Math.min(ACTIVE_TEAM_SIZE-1,action.slot||0));
      if(!state.pokemon[idx]) return state;
      const team=getActiveTeamIndexes(state);
      const nextTeam=[...team];
      if(nextTeam.includes(idx)){
        const oldSlot=nextTeam.indexOf(idx);
        const oldValue=nextTeam[slot];
        nextTeam[slot]=idx;
        nextTeam[oldSlot]=oldValue;
      }else{
        nextTeam[slot]=idx;
      }
      const clean=uniqueValidTeam(nextTeam,state.pokemon.length);
      const activePkmIndex=clean.includes(state.activePkmIndex)?state.activePkmIndex:clean[0];
      return{...state,activeTeam:clean,activePkmIndex,screen:'box'};
    }
    case 'DELETE_POKEMON':{
      const idx=action.index;
      if(!state.pokemon[idx]||state.pokemon.length<=1) return state;
      const deleted=state.pokemon[idx];
      const newList=state.pokemon.filter((_,i)=>i!==idx);
      const shift=i=>i>idx?i-1:i;
      let activeTeam=getActiveTeamIndexes(state).filter(i=>i!==idx).map(shift);
      let activePkmIndex=state.activePkmIndex===idx?(activeTeam[0]??0):shift(state.activePkmIndex);
      if(activeTeam.length===0) activeTeam=[activePkmIndex];
      if(!activeTeam.includes(activePkmIndex)) activeTeam=[activePkmIndex,...activeTeam].slice(0,ACTIVE_TEAM_SIZE);
      return normalizeState({...state,pokemon:newList,activeTeam,activePkmIndex,
        screen:'box',statsTarget:null,statsReturnScreen:null,
        exploreLog:[`${deleted.name} borrado`]});
    }
    case 'UNLOCK_SCENARIO': return state;
    case 'SET_SCENARIO':{
      const pkm=state.pokemon[state.activePkmIndex];
      const s=SCENARIOS[action.id];
      if(!s||!pkm||pkm.level<s.minLv) return state;
      return{...state,scenario:action.id};
    }
    case 'RESET_GAME':{
      try{localStorage.removeItem(SAVE_KEY);}catch(e){}
      return{...INITIAL_STATE};
    }

    default: return state;
  }
}

Object.assign(window,{
  C,TYPE_COL,SCENARIOS,SCENARIO_POOLS,PTYPE,PNAMES,STARTERS,
  EVOLUTIONS,BALL_TYPES,CATCH_RATES,calcCatchChance,GYMS,
  calcMaxHp,calcAtk,calcDef,calcSpd,xpForLevel,xpGain,getBaseStats,
  getDayPhase,DAY_TINTS,DAY_LABELS,SFX,
  spriteAnimated,spriteStatic,spriteBack,createPlayerPokemon,
  loadState,saveState,SAVE_KEY,INITIAL_STATE,gameReducer,COOLDOWN_MS,
  ACTIVE_TEAM_SIZE,BOX_CAPACITY,ITEM_XP_GAIN,getActiveTeamIndexes,normalizeState,grantTeamExperience,
});
})();
