const { useState, useEffect, useCallback, useRef } = React;

const SK_GAMES = "jar-games-v4";
const SK_LOGO  = "jar-logo-v3";
const SK_FAVS  = "jar-favs-v1";
const SK_PLAYS = "jar-plays-v1";

const SAMPLE = [
  { id:"1", title:"Asphalt Urban GT", synopsis:"Corridas de rua pelas mais famosas metrópoles do mundo. Pilote carros exóticos, desvie do tráfego e ultrapasse seus rivais.", content:"Asphalt Urban GT marcou a fase em que jogos de corrida começaram a parecer mais ambiciosos nos celulares Java. Esta página reúne informações para catalogação, memória afetiva e preservação histórica: estilo de jogo, ano aproximado, gênero, observações de compatibilidade e espaço para imagens do acervo. Antes de publicar um arquivo jogável, confirme se você possui direito de distribuição ou se ele foi liberado oficialmente.", jarUrl:"", coverBase64:"", genre:"Corrida", year:"2004", gallery:[] },
  { id:"2", title:"Bomberman",         synopsis:"O lendário Bomberman chegou ao celular! Posicione bombas para eliminar inimigos e abrir passagens nos labirintos.", content:"Bomberman é lembrado por partidas rápidas, labirintos simples e decisões de posicionamento. No celular, a experiência dependia muito do teclado numérico e da resolução da tela. Use este espaço para registrar versão, fabricante, controles, idioma, resolução recomendada e observações sobre desempenho no emulador.", jarUrl:"", coverBase64:"", genre:"Ação",    year:"2003", gallery:[] },
  { id:"3", title:"Snake II",           synopsis:"O eterno clássico do Nokia. Guie sua cobra para devorar pontos sem colidir com as paredes ou com seu próprio corpo.", content:"Snake II representa uma das formas mais reconhecíveis de jogo mobile clássico: regras simples, dificuldade crescente e partidas curtas. Esta entrada pode servir como ficha histórica, com descrição de mecânicas, curiosidades, pontuação, versões conhecidas e diferenças entre aparelhos.", jarUrl:"", coverBase64:"", genre:"Clássico",year:"2002", gallery:[] },
  { id:"4", title:"Real Football 2006", synopsis:"Futebol completo na palma da mão. Jogos, ligas, campeonatos e times reais numa experiência incrível para celular.", content:"Real Football 2006 faz parte de uma geração de jogos esportivos Java que tentava adaptar campeonatos, passes, chutes e escalações para telas pequenas. Ao cadastrar uma versão, inclua informações sobre resolução, idioma, modo de jogo, compatibilidade e origem autorizada do arquivo.", jarUrl:"", coverBase64:"", genre:"Esporte", year:"2005", gallery:[] },
  { id:"5", title:"Zuma",               synopsis:"Atire esferas coloridas para eliminar cadeias antes que cheguem ao fim. Viciante e cheio de fases desafiadoras.", content:"Zuma combina raciocínio rápido, mira e combinação de cores. Em celulares antigos, jogos desse tipo se destacavam por sessões curtas e controles simples. Esta ficha pode reunir dicas, descrição de fases, observações de jogabilidade e imagens próprias enviadas pelo administrador.", jarUrl:"", coverBase64:"", genre:"Puzzle",  year:"2005", gallery:[] },
];

const LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
const NUMS    = "0123456789".split("");
const ALPHA   = ["TODOS",...LETTERS,"0-9","#"];
const GCOLORS = { Corrida:"#e52020",Ação:"#e52020",Clássico:"#ffd23f",RPG:"#a78bfa",Esporte:"#34d399",Puzzle:"#60a5fa",Aventura:"#f97316",Luta:"#fb7185",Estratégia:"#22d3ee",Outro:"#94a3b8" };
const GENRES  = Object.keys(GCOLORS);
const R="#e52020", R2="#b81818";
const ra = o=>`rgba(229,32,32,${o})`;
const gc = g=>GCOLORS[g]||GCOLORS.Outro;
const uid= ()=>Math.random().toString(36).slice(2,10);
const fl = t=>(t?.[0]||"?").toUpperCase();

function charGroup(t){
  const c=fl(t);
  if(LETTERS.includes(c)) return c;
  if(NUMS.includes(c)) return "0-9";
  return "#";
}
async function uploadFile(file){
  if(window.uploadAsset) return window.uploadAsset(file);
  return new Promise((res,rej)=>{const r=new FileReader();r.onload=()=>res(r.result);r.onerror=rej;r.readAsDataURL(file);});
}

const inp={width:"100%",background:"rgba(255,255,255,0.03)",border:`1px solid ${ra(0.15)}`,borderRadius:8,padding:"10px 12px",color:"#e2e8f0",fontSize:12,outline:"none",boxSizing:"border-box",fontFamily:"'IBM Plex Mono',monospace"};
const lbl={fontSize:9,letterSpacing:"0.2em",color:R,marginBottom:6,display:"block"};

function UploadBtn({accept,onFile,children}){
  const ref=useRef();
  return(<><input ref={ref} type="file" accept={accept} style={{display:"none"}} onChange={async e=>{if(e.target.files[0]){try{const b=await uploadFile(e.target.files[0]);onFile(b);}catch(err){alert(err.message||"Nao foi possivel enviar o arquivo.");}e.target.value="";}}}/><button type="button" onClick={()=>ref.current.click()} style={{background:ra(0.08),border:`1px dashed ${ra(0.3)}`,color:R,padding:"10px 16px",borderRadius:8,cursor:"pointer",fontSize:11,width:"100%",transition:"all 0.2s"}} onMouseEnter={e=>e.currentTarget.style.background=ra(0.14)} onMouseLeave={e=>e.currentTarget.style.background=ra(0.08)}>{children}</button></>);
}

// ── HEADER ─────────────────────────────────────────────────────────────────
const DEFAULT_LOGO="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";

function Header({logo,onAdmin,onHome,favCount}){
  const src=logo||`data:image/png;base64,${DEFAULT_LOGO}`;
  return(
    <header style={{position:"relative",zIndex:10,borderBottom:`1px solid ${ra(0.2)}`,background:"rgba(6,6,14,0.95)",backdropFilter:"blur(12px)",padding:"0 24px"}}>
      <div style={{maxWidth:1200,margin:"0 auto",display:"flex",alignItems:"center",justifyContent:"space-between",height:64}}>
        <button type="button" onClick={onHome} aria-label="Voltar para a página inicial" title="Voltar para a página inicial" style={{display:"flex",alignItems:"center",gap:10,background:"transparent",border:"none",padding:0,cursor:"pointer"}}>
          <img src={src} alt=".Jar" style={{width:40,height:40,mixBlendMode:"screen",imageRendering:"pixelated"}}/>
          <span style={{fontFamily:"'Press Start 2P',monospace",fontSize:14,color:R,textShadow:`0 0 10px ${ra(0.6)}`}}>.Jar</span>
        </button>
        <div style={{display:"flex",alignItems:"center",gap:10}}>
          {favCount>0&&<div style={{background:ra(0.1),border:`1px solid ${ra(0.2)}`,borderRadius:20,padding:"4px 12px",fontSize:10,color:R}}>♥ {favCount}</div>}
          <button onClick={onAdmin} style={{background:"transparent",border:`1px solid ${ra(0.3)}`,color:R,padding:"6px 14px",borderRadius:6,cursor:"pointer",fontSize:11,letterSpacing:"0.1em",transition:"all 0.2s"}}
            onMouseEnter={e=>{e.currentTarget.style.background=ra(0.1);}} onMouseLeave={e=>{e.currentTarget.style.background="transparent";}}>⚙ GERENCIAR</button>
        </div>
      </div>
    </header>
  );
}

// ── GAME CARD ──────────────────────────────────────────────────────────────
function Card({game,onClick,isFav,onToggleFav,playCount}){
  const [hov,setHov]=useState(false);
  const c=gc(game.genre);
  return(
    <div onMouseEnter={()=>setHov(true)} onMouseLeave={()=>setHov(false)}
      style={{cursor:"pointer",background:hov?ra(0.06):"rgba(255,255,255,0.02)",border:`1px solid ${hov?ra(0.4):"rgba(255,255,255,0.07)"}`,borderRadius:12,overflow:"hidden",transition:"all 0.25s",transform:hov?"translateY(-3px)":"none",boxShadow:hov?`0 8px 32px ${ra(0.15)}`:"none",position:"relative"}}>
      <div onClick={()=>onClick(game)} style={{height:140,background:`linear-gradient(135deg,${ra(0.08)},rgba(6,6,14,0.9))`,display:"flex",alignItems:"center",justifyContent:"center",position:"relative",borderBottom:"1px solid rgba(255,255,255,0.05)"}}>
        {game.coverBase64?<img src={game.coverBase64} alt={game.title} style={{width:"100%",height:"100%",objectFit:"cover",position:"absolute",inset:0}}/>
          :<div style={{fontSize:48,fontFamily:"'Press Start 2P',monospace",color:ra(0.15),userSelect:"none"}}>{fl(game.title)}</div>}
        {game.genre&&<div style={{position:"absolute",top:10,left:10,background:`${c}22`,border:`1px solid ${c}55`,color:c,fontSize:8,padding:"2px 7px",borderRadius:20}}>{game.genre.toUpperCase()}</div>}
        {playCount>0&&<div style={{position:"absolute",bottom:10,left:10,background:"rgba(0,0,0,0.6)",border:"1px solid rgba(255,255,255,0.1)",color:"#94a3b8",fontSize:8,padding:"2px 7px",borderRadius:20}}>▶ {playCount}x</div>}
        {game.year&&<div style={{position:"absolute",bottom:10,right:10,color:"#475569",fontSize:8}}>{game.year}</div>}
      </div>
      <button onClick={e=>{e.stopPropagation();onToggleFav(game.id);}}
        style={{position:"absolute",top:8,right:8,background:isFav?"rgba(229,32,32,0.2)":"rgba(0,0,0,0.5)",border:`1px solid ${isFav?R:"rgba(255,255,255,0.15)"}`,borderRadius:"50%",width:28,height:28,cursor:"pointer",color:isFav?R:"#64748b",fontSize:13,display:"flex",alignItems:"center",justifyContent:"center",transition:"all 0.2s",zIndex:2}}>
        {isFav?"♥":"♡"}
      </button>
      <div onClick={()=>onClick(game)} style={{padding:"12px 14px 14px"}}>
        <div style={{fontSize:11,fontWeight:700,color:hov?R:"#e2e8f0",letterSpacing:"0.04em",marginBottom:5,transition:"color 0.2s",whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"}}>{game.title}</div>
        <div style={{fontSize:10,color:"#64748b",lineHeight:1.6,display:"-webkit-box",WebkitLineClamp:2,WebkitBoxOrient:"vertical",overflow:"hidden"}}>{game.synopsis||"Sem sinopse."}</div>
        <div style={{marginTop:10,display:"flex",alignItems:"center",gap:6,color:R,fontSize:9,letterSpacing:"0.15em"}}>
          <span style={{width:5,height:5,borderRadius:"50%",background:R,boxShadow:`0 0 5px ${R}`,flexShrink:0}}/>VER JOGO
        </div>
      </div>
    </div>
  );
}

// ── HORIZONTAL SCROLL ROW ──────────────────────────────────────────────────
function HScroll({games,onClick,favs,onToggleFav,plays}){
  return(
    <div style={{display:"flex",gap:12,overflowX:"auto",paddingBottom:8,scrollbarWidth:"thin",scrollbarColor:`${ra(0.3)} transparent`}}>
      {games.map(g=>(
        <div key={g.id} style={{flexShrink:0,width:160}}>
          <Card game={g} onClick={onClick} isFav={favs.includes(g.id)} onToggleFav={onToggleFav} playCount={plays[g.id]||0}/>
        </div>
      ))}
    </div>
  );
}

// ── LIBRARY ────────────────────────────────────────────────────────────────
function Library({games,favs,plays,onSelect,onToggleFav}){
  const [q,setQ]=useState("");
  const [letter,setLetter]=useState("TODOS");
  const [showFilters,setShowFilters]=useState(false);
  const [genreFilter,setGenreFilter]=useState("TODOS");
  const [sortBy,setSortBy]=useState("az");
  const [yearFrom,setYearFrom]=useState("");
  const [yearTo,setYearTo]=useState("");
  const [showFavs,setShowFavs]=useState(false);

  // Most played top 5
  const topPlayed=[...games].filter(g=>(plays[g.id]||0)>0).sort((a,b)=>(plays[b.id]||0)-(plays[a.id]||0)).slice(0,8);
  // By genre groups for featured section
  const featuredGenres=[...new Set(games.map(g=>g.genre).filter(Boolean))].slice(0,6);

  const activeFilters=[genreFilter!=="TODOS",yearFrom,yearTo,showFavs,q].filter(Boolean).length;

  let filtered=[...games];
  if(showFavs) filtered=filtered.filter(g=>favs.includes(g.id));
  if(q) filtered=filtered.filter(g=>g.title.toLowerCase().includes(q.toLowerCase())||g.genre?.toLowerCase().includes(q.toLowerCase())||g.synopsis?.toLowerCase().includes(q.toLowerCase()));
  if(letter!=="TODOS") filtered=filtered.filter(g=>charGroup(g.title)===letter);
  if(genreFilter!=="TODOS") filtered=filtered.filter(g=>g.genre===genreFilter);
  if(yearFrom) filtered=filtered.filter(g=>parseInt(g.year||0)>=parseInt(yearFrom));
  if(yearTo) filtered=filtered.filter(g=>parseInt(g.year||9999)<=parseInt(yearTo));

  filtered.sort((a,b)=>{
    if(sortBy==="az") return a.title.localeCompare(b.title);
    if(sortBy==="za") return b.title.localeCompare(a.title);
    if(sortBy==="popular") return (plays[b.id]||0)-(plays[a.id]||0);
    if(sortBy==="recent") return parseInt(b.year||0)-parseInt(a.year||0);
    if(sortBy==="old") return parseInt(a.year||0)-parseInt(b.year||0);
    if(sortBy==="favs") return favs.includes(b.id)?1:favs.includes(a.id)?-1:0;
    return 0;
  });

  const grouped=filtered.reduce((acc,g)=>{
    const l=charGroup(g.title);if(!acc[l])acc[l]=[];acc[l].push(g);return acc;
  },{});
  const sortedGroups=Object.keys(grouped).sort((a,b)=>{
    if(sortBy!=="az"&&sortBy!=="za") return 0;
    if(a=="#")return 1;if(b=="#")return -1;
    if(a==="0-9")return b=="#"?-1:1;if(b==="0-9")return a=="#"?1:-1;
    return a.localeCompare(b);
  });

  const resetFilters=()=>{setGenreFilter("TODOS");setYearFrom("");setYearTo("");setShowFavs(false);setSortBy("az");setLetter("TODOS");setQ("");};

  return(
    <div style={{position:"relative",zIndex:1,maxWidth:1200,margin:"0 auto",padding:"40px 24px"}}>

      {/* HERO */}
      <div style={{textAlign:"center",marginBottom:40}}>
        <div style={{fontSize:10,letterSpacing:"0.4em",color:R,marginBottom:14,textShadow:`0 0 8px ${ra(0.5)}`}}>● ONLINE ● {games.length} JOGOS DISPONÍVEIS</div>
        <h1 style={{fontFamily:"'Press Start 2P',monospace",fontSize:"clamp(18px,4vw,30px)",color:"#fff",margin:0,lineHeight:1.4,textShadow:`0 0 40px ${ra(0.3)}`}}>BIBLIOTECA<br/><span style={{color:R}}>.Jar</span></h1>
        <p style={{color:"#475569",fontSize:11,marginTop:12,letterSpacing:"0.1em"}}>JOGOS CLÁSSICOS DE CELULAR EM SEU NAVEGADOR</p>
      </div>

      {/* MAIS POPULARES */}
      {topPlayed.length>0&&(
        <div style={{marginBottom:40}}>
          <div style={{display:"flex",alignItems:"center",gap:16,marginBottom:16}}>
            <div style={{fontFamily:"'Press Start 2P',monospace",fontSize:11,color:R,textShadow:`0 0 10px ${ra(0.4)}`}}>🔥 MAIS JOGADOS</div>
            <div style={{flex:1,height:1,background:`linear-gradient(90deg,${ra(0.3)},transparent)`}}/>
          </div>
          <HScroll games={topPlayed} onClick={onSelect} favs={favs} onToggleFav={onToggleFav} plays={plays}/>
        </div>
      )}

      {/* CATEGORIAS EM DESTAQUE */}
      {featuredGenres.length>0&&!showFavs&&!q&&letter==="TODOS"&&genreFilter==="TODOS"&&(
        <div style={{marginBottom:40}}>
          <div style={{display:"flex",alignItems:"center",gap:16,marginBottom:16}}>
            <div style={{fontFamily:"'Press Start 2P',monospace",fontSize:11,color:R}}>🎮 CATEGORIAS</div>
            <div style={{flex:1,height:1,background:`linear-gradient(90deg,${ra(0.3)},transparent)`}}/>
          </div>
          <div style={{display:"flex",flexWrap:"wrap",gap:8}}>
            {featuredGenres.map(g=>{
              const c=gc(g);
              const count=games.filter(gm=>gm.genre===g).length;
              return(
                <button key={g} onClick={()=>setGenreFilter(g)}
                  style={{background:`${c}11`,border:`1px solid ${c}33`,color:c,padding:"8px 16px",borderRadius:20,cursor:"pointer",fontSize:10,letterSpacing:"0.05em",transition:"all 0.2s",display:"flex",alignItems:"center",gap:8}}
                  onMouseEnter={e=>{e.currentTarget.style.background=`${c}22`;e.currentTarget.style.boxShadow=`0 0 12px ${c}33`;}}
                  onMouseLeave={e=>{e.currentTarget.style.background=`${c}11`;e.currentTarget.style.boxShadow="none";}}>
                  {g} <span style={{opacity:0.6,fontSize:9}}>{count}</span>
                </button>
              );
            })}
          </div>
        </div>
      )}

      {/* SEARCH + FILTERS */}
      <div style={{marginBottom:24}}>
        <div style={{display:"flex",gap:10,marginBottom:10}}>
          <div style={{position:"relative",flex:1}}>
            <span style={{position:"absolute",left:14,top:"50%",transform:"translateY(-50%)",color:R,fontSize:14,opacity:0.6}}>⌕</span>
            <input value={q} onChange={e=>setQ(e.target.value)} placeholder="Buscar por nome, gênero, descrição..."
              style={{...inp,padding:"11px 14px 11px 38px"}}
              onFocus={e=>e.target.style.borderColor=ra(0.5)} onBlur={e=>e.target.style.borderColor=ra(0.15)}/>
          </div>
          <button onClick={()=>setShowFavs(!showFavs)}
            style={{background:showFavs?ra(0.15):"transparent",border:`1px solid ${showFavs?R:ra(0.2)}`,color:showFavs?R:"#64748b",padding:"0 16px",borderRadius:8,cursor:"pointer",fontSize:13,transition:"all 0.2s",whiteSpace:"nowrap"}}>
            {showFavs?"♥":"♡"} {favs.length}
          </button>
          <button onClick={()=>setShowFilters(!showFilters)}
            style={{background:activeFilters>0?ra(0.15):"transparent",border:`1px solid ${activeFilters>0?R:ra(0.2)}`,color:activeFilters>0?R:"#64748b",padding:"0 16px",borderRadius:8,cursor:"pointer",fontSize:10,letterSpacing:"0.08em",transition:"all 0.2s",whiteSpace:"nowrap"}}>
            ⚡ FILTROS{activeFilters>0?` (${activeFilters})`:""}
          </button>
        </div>

        {/* Advanced filters panel */}
        {showFilters&&(
          <div style={{background:"rgba(255,255,255,0.02)",border:`1px solid ${ra(0.15)}`,borderRadius:10,padding:16,display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(180px,1fr))",gap:12}}>
            <div>
              <label style={lbl}>// GÊNERO</label>
              <select value={genreFilter} onChange={e=>setGenreFilter(e.target.value)} style={{...inp,appearance:"none",fontSize:11}}>
                <option value="TODOS">Todos os gêneros</option>
                {GENRES.map(g=><option key={g} value={g}>{g} ({games.filter(gm=>gm.genre===g).length})</option>)}
              </select>
            </div>
            <div>
              <label style={lbl}>// ORDENAR POR</label>
              <select value={sortBy} onChange={e=>setSortBy(e.target.value)} style={{...inp,appearance:"none",fontSize:11}}>
                <option value="az">A → Z</option>
                <option value="za">Z → A</option>
                <option value="popular">Mais jogados</option>
                <option value="recent">Mais recentes</option>
                <option value="old">Mais antigos</option>
                <option value="favs">Favoritos primeiro</option>
              </select>
            </div>
            <div>
              <label style={lbl}>// ANO DE</label>
              <input value={yearFrom} onChange={e=>setYearFrom(e.target.value)} placeholder="Ex: 2000" style={{...inp,fontSize:11}}/>
            </div>
            <div>
              <label style={lbl}>// ANO ATÉ</label>
              <input value={yearTo} onChange={e=>setYearTo(e.target.value)} placeholder="Ex: 2010" style={{...inp,fontSize:11}}/>
            </div>
            {activeFilters>0&&(
              <div style={{display:"flex",alignItems:"flex-end"}}>
                <button onClick={resetFilters} style={{width:"100%",background:"transparent",border:`1px solid ${ra(0.2)}`,color:"#64748b",padding:"10px",borderRadius:8,cursor:"pointer",fontSize:10,letterSpacing:"0.1em"}}>✕ LIMPAR FILTROS</button>
              </div>
            )}
          </div>
        )}
      </div>

      {/* ALPHABET FILTER */}
      <div style={{display:"flex",flexWrap:"wrap",gap:4,justifyContent:"center",marginBottom:36,alignItems:"center"}}>
        {ALPHA.map((l,i)=>(
          <span key={l} style={{display:"contents"}}>
            {l==="0-9"&&<span style={{width:1,height:16,background:ra(0.2),margin:"0 4px",display:"inline-block",verticalAlign:"middle"}}/>}
            <button onClick={()=>setLetter(l)}
              style={{background:letter===l?R:"transparent",border:`1px solid ${letter===l?R:ra(0.12)}`,color:letter===l?"#06060e":"#64748b",padding:l==="TODOS"?"4px 12px":"4px 7px",borderRadius:5,cursor:"pointer",fontSize:9,fontFamily:"'IBM Plex Mono',monospace",fontWeight:letter===l?700:400,transition:"all 0.15s",boxShadow:letter===l?`0 0 10px ${ra(0.4)}`:"none"}}>{l}</button>
          </span>
        ))}
      </div>

      {/* RESULTS HEADER */}
      <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:20}}>
        <div style={{fontSize:10,color:"#475569",letterSpacing:"0.08em"}}>
          {filtered.length} jogo{filtered.length!==1?"s":""} encontrado{filtered.length!==1?"s":""}
          {showFavs?" · ♥ favoritos":""}
          {genreFilter!=="TODOS"?` · ${genreFilter}`:""}
        </div>
        {activeFilters>0&&<button onClick={resetFilters} style={{background:"transparent",border:"none",color:R,cursor:"pointer",fontSize:10,letterSpacing:"0.08em"}}>✕ limpar</button>}
      </div>

      {/* GAMES GRID */}
      {filtered.length===0
        ?<div style={{textAlign:"center",color:"#334155",padding:"60px 0"}}>
            <div style={{fontFamily:"'Press Start 2P',monospace",fontSize:24,marginBottom:12}}>?</div>
            <div style={{fontSize:11,letterSpacing:"0.2em",marginBottom:16}}>NENHUM JOGO ENCONTRADO</div>
            <button onClick={resetFilters} style={{background:"transparent",border:`1px solid ${ra(0.2)}`,color:R,padding:"8px 20px",borderRadius:8,cursor:"pointer",fontSize:10}}>LIMPAR FILTROS</button>
          </div>
        :(sortBy==="az"||sortBy==="za"
          ?sortedGroups.map(l=>(
              <div key={l} style={{marginBottom:36}}>
                <div style={{display:"flex",alignItems:"center",gap:16,marginBottom:16}}>
                  <div style={{fontFamily:"'Press Start 2P',monospace",fontSize:18,color:R,textShadow:`0 0 14px ${ra(0.4)}`,minWidth:40}}>{l}</div>
                  <div style={{flex:1,height:1,background:`linear-gradient(90deg,${ra(0.3)},transparent)`}}/>
                </div>
                <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(190px,1fr))",gap:14}}>
                  {grouped[l].map(g=><Card key={g.id} game={g} onClick={onSelect} isFav={favs.includes(g.id)} onToggleFav={onToggleFav} playCount={plays[g.id]||0}/>)}
                </div>
              </div>
            ))
          :<div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(190px,1fr))",gap:14}}>
              {filtered.map(g=><Card key={g.id} game={g} onClick={onSelect} isFav={favs.includes(g.id)} onToggleFav={onToggleFav} playCount={plays[g.id]||0}/>)}
            </div>
        )
      }
    </div>
  );
}

// ── DETAIL ─────────────────────────────────────────────────────────────────
function Detail({game,onPlay,onBack,isFav,onToggleFav,playCount}){
  const c=gc(game.genre);
  return(
    <div style={{position:"relative",zIndex:1,maxWidth:860,margin:"0 auto",padding:"40px 24px"}}>
      <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:28}}>
        <button onClick={onBack} style={{background:"transparent",border:"none",color:"#64748b",cursor:"pointer",fontSize:11,letterSpacing:"0.15em",display:"flex",alignItems:"center",gap:8}}
          onMouseEnter={e=>e.currentTarget.style.color=R} onMouseLeave={e=>e.currentTarget.style.color="#64748b"}>← VOLTAR À BIBLIOTECA</button>
        <button onClick={()=>onToggleFav(game.id)}
          style={{background:isFav?ra(0.15):"transparent",border:`1px solid ${isFav?R:ra(0.2)}`,color:isFav?R:"#64748b",padding:"6px 14px",borderRadius:20,cursor:"pointer",fontSize:12,transition:"all 0.2s"}}>
          {isFav?"♥ FAVORITO":"♡ FAVORITAR"}
        </button>
      </div>
      <div style={{background:"rgba(255,255,255,0.02)",border:"1px solid rgba(255,255,255,0.07)",borderRadius:16,overflow:"hidden"}}>
        <div style={{height:220,background:`linear-gradient(135deg,${ra(0.12)},rgba(6,6,14,0.95))`,display:"flex",alignItems:"center",justifyContent:"center",position:"relative",borderBottom:"1px solid rgba(255,255,255,0.06)"}}>
          {game.coverBase64&&<img src={game.coverBase64} alt={game.title} style={{width:"100%",height:"100%",objectFit:"cover",position:"absolute",inset:0,opacity:0.45}}/>}
          <div style={{position:"relative",zIndex:1,fontFamily:"'Press Start 2P',monospace",fontSize:"clamp(28px,6vw,52px)",color:ra(0.18),fontWeight:900,userSelect:"none"}}>{fl(game.title)}</div>
          {game.genre&&<div style={{position:"absolute",top:16,right:16,background:`${c}22`,border:`1px solid ${c}55`,color:c,fontSize:10,padding:"4px 12px",borderRadius:20}}>{game.genre.toUpperCase()}</div>}
          <div style={{position:"absolute",bottom:16,left:20,display:"flex",gap:12,alignItems:"center"}}>
            {game.year&&<span style={{color:"#475569",fontSize:10}}>{game.year}</span>}
            {playCount>0&&<span style={{background:"rgba(0,0,0,0.5)",border:"1px solid rgba(255,255,255,0.1)",color:"#94a3b8",fontSize:9,padding:"2px 8px",borderRadius:20}}>▶ {playCount} vezes jogado</span>}
          </div>
        </div>
        <div style={{padding:28}}>
          <h2 style={{fontFamily:"'Press Start 2P',monospace",fontSize:"clamp(13px,2.5vw,20px)",color:"#fff",margin:"0 0 20px",lineHeight:1.5}}>{game.title}</h2>
          <div style={{background:ra(0.04),border:`1px solid ${ra(0.1)}`,borderRadius:10,padding:18,marginBottom:20}}>
            <div style={{fontSize:9,letterSpacing:"0.25em",color:R,marginBottom:10}}>// SINOPSE</div>
            <p style={{fontSize:13,color:"#94a3b8",lineHeight:1.85,margin:0,whiteSpace:"pre-wrap"}}>{game.synopsis||"Sem sinopse."}</p>
          </div>
          {game.content&&(
            <div style={{background:"rgba(255,255,255,0.02)",border:"1px solid rgba(255,255,255,0.06)",borderRadius:10,padding:18,marginBottom:20}}>
              <div style={{fontSize:9,letterSpacing:"0.25em",color:R,marginBottom:10}}>// SOBRE O JOGO</div>
              <p style={{fontSize:13,color:"#94a3b8",lineHeight:1.85,margin:0,whiteSpace:"pre-wrap"}}>{game.content}</p>
            </div>
          )}
          {game.gallery?.length>0&&(
            <div style={{marginBottom:20}}>
              <div style={{fontSize:9,letterSpacing:"0.25em",color:R,marginBottom:10}}>// GALERIA</div>
              <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(160px,1fr))",gap:8}}>
                {game.gallery.map((img,i)=><img key={i} src={img} alt={`ss${i}`} style={{width:"100%",height:110,objectFit:"cover",borderRadius:8,border:`1px solid ${ra(0.15)}`}}/>)}
              </div>
            </div>
          )}
          {!game.jarUrl
            ?<div style={{background:ra(0.06),border:`1px solid ${ra(0.2)}`,borderRadius:10,padding:16,fontSize:11,color:R,textAlign:"center"}}>⚠ URL do .JAR não configurada — adicione via painel</div>
            :<button onClick={()=>onPlay(game)} style={{width:"100%",background:`linear-gradient(135deg,${R},${R2})`,border:"none",borderRadius:10,padding:"16px",color:"#fff",fontSize:13,fontFamily:"'IBM Plex Mono',monospace",letterSpacing:"0.15em",fontWeight:700,cursor:"pointer",boxShadow:`0 4px 24px ${ra(0.4)}`,transition:"all 0.2s"}}
                onMouseEnter={e=>{e.target.style.transform="translateY(-2px)";e.target.style.boxShadow=`0 8px 32px ${ra(0.5)}`;}}
                onMouseLeave={e=>{e.target.style.transform="none";e.target.style.boxShadow=`0 4px 24px ${ra(0.4)}`;}}>▶ JOGAR AGORA</button>
          }
        </div>
      </div>
    </div>
  );
}

// ── EMULATOR ───────────────────────────────────────────────────────────────
function Emulator({game,onBack}){
  return(
    <div style={{position:"relative",zIndex:1,maxWidth:900,margin:"0 auto",padding:"24px"}}>
      <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:20}}>
        <button onClick={onBack} style={{background:"transparent",border:"none",color:"#64748b",cursor:"pointer",fontSize:11,letterSpacing:"0.15em",display:"flex",alignItems:"center",gap:8}}
          onMouseEnter={e=>e.currentTarget.style.color=R} onMouseLeave={e=>e.currentTarget.style.color="#64748b"}>← VOLTAR</button>
        <div style={{fontFamily:"'Press Start 2P',monospace",fontSize:10,color:R}}>{game.title}</div>
        <div style={{width:80}}/>
      </div>
      <div style={{display:"flex",justifyContent:"center"}}>
        <div style={{width:"min(420px,100%)",background:"#111118",border:`2px solid ${ra(0.3)}`,borderRadius:24,padding:"12px 12px 20px",boxShadow:`0 0 60px ${ra(0.12)},inset 0 0 30px rgba(0,0,0,0.5)`}}>
          <div style={{display:"flex",justifyContent:"center",gap:3,marginBottom:10}}>{[...Array(6)].map((_,i)=><div key={i} style={{width:4,height:4,background:"#1e293b",borderRadius:"50%"}}/>)}</div>
          <div style={{background:"#000",borderRadius:12,overflow:"hidden",border:`1px solid ${ra(0.1)}`}}>
            {game.jarUrl
              ?<iframe src={`https://j2me.online/emulator?jar=${encodeURIComponent(new URL(game.jarUrl, window.location.href).href)}`} title={game.title} width="100%" height="480" frameBorder="0" style={{display:"block"}} allow="fullscreen"/>
              :<div style={{height:480,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:12}}>
                  <div style={{fontFamily:"'Press Start 2P',monospace",fontSize:24,color:ra(0.15)}}>⚙</div>
                  <div style={{fontSize:10,color:"#334155"}}>SEM JAR CONFIGURADO</div>
                </div>}
          </div>
          <div style={{display:"flex",justifyContent:"center",gap:8,marginTop:14}}>
            <div style={{width:8,height:8,borderRadius:"50%",border:`1px solid ${ra(0.3)}`}}/>
            <div style={{width:20,height:8,borderRadius:4,background:ra(0.2),border:`1px solid ${ra(0.3)}`}}/>
            <div style={{width:8,height:8,borderRadius:"50%",border:`1px solid ${ra(0.3)}`}}/>
          </div>
        </div>
      </div>
    </div>
  );
}

// ── ADMIN ──────────────────────────────────────────────────────────────────
// ── INSTITUTIONAL PAGES ─────────────────────────────────────────────────────
const pageWrap={position:"relative",zIndex:1,maxWidth:940,margin:"0 auto",padding:"56px 24px 72px",lineHeight:1.8};
const pageTitle={fontFamily:"'Press Start 2P',monospace",fontSize:24,color:R,lineHeight:1.45,margin:"0 0 22px"};
const pageCard={background:"rgba(255,255,255,0.025)",border:"1px solid rgba(255,255,255,0.08)",borderRadius:12,padding:24,marginBottom:18};
const pageP={fontSize:13,color:"#94a3b8",margin:"0 0 14px"};
const pageH={fontSize:11,color:R,letterSpacing:"0.14em",margin:"22px 0 8px"};

function StaticPage({page,onNavigate}){
  const pages={
    about:{title:"Sobre o .Jar",body:[
      ["Nossa proposta","O .Jar é um catálogo dedicado à memória dos jogos Java para celular. A ideia é organizar fichas, imagens, informações de compatibilidade, curiosidades e registros de uma fase importante dos jogos mobile."],
      ["Preservação e contexto","Cada página de jogo foi pensada como uma ficha editorial. O administrador pode incluir descrição, ano, gênero, dicas, observações de controles, resolução recomendada e imagens próprias do acervo."],
      ["Responsabilidade","O site deve priorizar arquivos com autorização de distribuição, jogos homebrew, demos liberadas, projetos independentes ou materiais cujo uso seja permitido. Se algum conteúdo precisar ser removido, use a página de contato."]
    ]},
    contact:{title:"Contato",body:[
      ["Fale com o projeto","Para pedidos de remoção, correções de informações, sugestões de jogos homebrew ou parcerias, envie uma mensagem para: contato@seudominio.com."],
      ["Pedidos de remoção","Se você representa o titular de algum conteúdo publicado, informe o link da página, o material questionado e uma forma de comprovar a titularidade. O objetivo é manter o acervo organizado e respeitoso."],
      ["Sugestões","Também aceitamos sugestões de fichas, capas autorizadas, informações históricas, versões independentes e jogos Java criados pela comunidade."]
    ]},
    privacy:{title:"Política de Privacidade",body:[
      ["Dados locais","Favoritos e contagem de partidas podem ser salvos no navegador do visitante para melhorar a experiência. Esses dados ficam no próprio dispositivo e não identificam diretamente o usuário."],
      ["Uploads e administração","O painel administrativo salva no servidor as informações cadastradas pelo administrador, como fichas de jogos, imagens, logo e arquivos enviados."],
      ["Cookies e anúncios","Caso o site use Google AdSense ou ferramentas semelhantes, parceiros podem utilizar cookies, identificadores e tecnologias parecidas para medir anúncios e personalizar experiências conforme suas próprias políticas."],
      ["Contato","Solicitações sobre privacidade, correção ou remoção de informações podem ser enviadas para contato@seudominio.com."]
    ]},
    terms:{title:"Termos de Uso",body:[
      ["Uso do site","O .Jar oferece informações, fichas e acesso a conteúdo publicado pelo administrador. O visitante deve usar o site de forma lícita e respeitar direitos autorais, marcas e regras aplicáveis."],
      ["Conteúdo de jogos","Arquivos jogáveis devem ser publicados apenas quando houver autorização, licença adequada, domínio público, distribuição oficial ou permissão clara. O administrador é responsável por validar a origem do material antes da publicação."],
      ["Emulação","O site pode abrir jogos em um emulador externo. A disponibilidade, compatibilidade e funcionamento do emulador dependem do serviço de terceiros e do arquivo utilizado."],
      ["Alterações","Estes termos podem ser atualizados conforme o projeto evolui, especialmente se forem adicionados login, favoritos em nuvem ou novas formas de monetização."]
    ]}
  };
  const data=pages[page]||pages.about;
  return(
    <section style={pageWrap}>
      <a href="#home" onClick={e=>{e.preventDefault();onNavigate("library");}} style={{display:"inline-block",textDecoration:"none",background:"transparent",border:`1px solid ${ra(0.25)}`,color:R,borderRadius:8,padding:"8px 12px",fontSize:10,cursor:"pointer",marginBottom:24}}>← VOLTAR</a>
      <h1 style={pageTitle}>{data.title}</h1>
      <div style={pageCard}>
        {data.body.map(([title,text])=>(
          <section key={title}>
            <h2 style={pageH}>{title.toUpperCase()}</h2>
            <p style={pageP}>{text}</p>
          </section>
        ))}
      </div>
      <p style={{...pageP,fontSize:11,color:"#64748b"}}>Antes de solicitar AdSense, substitua emails, domínio e textos genéricos pelas informações reais do seu projeto.</p>
    </section>
  );
}

function Footer({onNavigate}){
  const links=[["about","Sobre"],["contact","Contato"],["privacy","Privacidade"],["terms","Termos"]];
  return(
    <footer style={{position:"relative",zIndex:1,borderTop:"1px solid rgba(255,255,255,0.06)",padding:"28px 24px 34px",background:"rgba(6,6,14,0.92)"}}>
      <div style={{maxWidth:1200,margin:"0 auto",display:"flex",alignItems:"center",justifyContent:"space-between",gap:18,flexWrap:"wrap"}}>
        <div>
          <div style={{fontFamily:"'Press Start 2P',monospace",fontSize:11,color:R,marginBottom:8}}>.Jar</div>
          <div style={{fontSize:10,color:"#64748b",maxWidth:520,lineHeight:1.7}}>Catálogo editorial de jogos Java mobile, com foco em memória, organização de acervo e distribuição responsável.</div>
        </div>
        <nav style={{display:"flex",gap:8,flexWrap:"wrap"}}>
          {links.map(([id,label])=>(
            <a key={id} href={`#${id}`} onClick={e=>{e.preventDefault();onNavigate(id);}} style={{textDecoration:"none",background:"transparent",border:`1px solid ${ra(0.18)}`,color:"#94a3b8",borderRadius:8,padding:"8px 10px",fontSize:10,cursor:"pointer"}}>{label}</a>
          ))}
        </nav>
      </div>
    </footer>
  );
}

function Admin({games,logo,onSave,onSaveLogo,onClose}){
  const EMPTY={title:"",synopsis:"",content:"",jarUrl:"",coverBase64:"",genre:"",year:"",gallery:[]};
  const [form,setForm]=useState(EMPTY);
  const [editId,setEditId]=useState(null);
  const [tab,setTab]=useState("list");
  const [del,setDel]=useState(null);
  const [logoPreview,setLogoPreview]=useState(logo||"");

  const startEdit=g=>{setForm({title:g.title,synopsis:g.synopsis,content:g.content||"",jarUrl:g.jarUrl,coverBase64:g.coverBase64||"",genre:g.genre,year:g.year,gallery:g.gallery||[]});setEditId(g.id);setTab("add");};
  const save=async()=>{
    if(!form.title.trim())return;
    const up=editId?games.map(g=>g.id===editId?{...g,...form}:g):[...games,{id:uid(),...form}];
    await onSave(up);setForm(EMPTY);setEditId(null);setTab("list");
  };

  return(
    <div style={{position:"fixed",inset:0,zIndex:100,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(0,0,0,0.88)",backdropFilter:"blur(8px)",padding:16}}>
      <div style={{background:"#0c0c16",border:`1px solid ${ra(0.2)}`,borderRadius:16,width:"min(720px,100%)",maxHeight:"92vh",display:"flex",flexDirection:"column",boxShadow:`0 0 80px ${ra(0.1)}`}}>
        <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"18px 24px",borderBottom:"1px solid rgba(255,255,255,0.05)"}}>
          <div style={{fontFamily:"'Press Start 2P',monospace",fontSize:11,color:R}}>⚙ PAINEL</div>
          <button onClick={onClose} style={{background:"transparent",border:"none",color:"#64748b",cursor:"pointer",fontSize:18}}>✕</button>
        </div>
        <div style={{display:"flex",borderBottom:"1px solid rgba(255,255,255,0.05)",overflowX:"auto"}}>
          {[["list",`📋 JOGOS (${games.length})`],["add",editId?"✏ EDITAR":"➕ NOVO"],["logo","🖼 LOGO"]].map(([t,label])=>(
            <button key={t} onClick={()=>{setTab(t);if(t!=="add"){setEditId(null);setForm(EMPTY);}}}
              style={{flexShrink:0,background:"transparent",border:"none",borderBottom:`2px solid ${tab===t?R:"transparent"}`,color:tab===t?R:"#475569",padding:"12px 20px",cursor:"pointer",fontSize:10,letterSpacing:"0.1em",fontFamily:"'IBM Plex Mono',monospace"}}>{label}</button>
          ))}
        </div>
        <div style={{flex:1,overflowY:"auto",padding:24}}>
          {tab==="logo"&&(
            <div style={{display:"flex",flexDirection:"column",gap:20}}>
              <div style={{textAlign:"center"}}>
                <div style={{fontSize:9,letterSpacing:"0.2em",color:R,marginBottom:14}}>// LOGO ATUAL</div>
                <div style={{display:"inline-block",background:"#06060e",padding:20,borderRadius:12,border:`1px solid ${ra(0.15)}`}}>
                  <img src={logoPreview||`data:image/png;base64,${DEFAULT_LOGO}`} alt="logo" style={{width:80,height:80,mixBlendMode:"screen",imageRendering:"pixelated"}}/>
                </div>
              </div>
              <UploadBtn accept="image/*" onFile={b=>setLogoPreview(b)}>📁 SELECIONAR NOVA LOGO</UploadBtn>
              {logoPreview&&logoPreview!==logo&&(
                <button onClick={()=>onSaveLogo(logoPreview)} style={{background:`linear-gradient(135deg,${R},${R2})`,border:"none",borderRadius:10,padding:14,color:"#fff",fontSize:11,fontFamily:"'IBM Plex Mono',monospace",letterSpacing:"0.15em",fontWeight:700,cursor:"pointer"}}>✓ SALVAR LOGO</button>
              )}
              <p style={{fontSize:10,color:"#475569",lineHeight:1.8,background:"rgba(255,255,255,0.02)",borderRadius:8,padding:14,margin:0}}>💡 Recomendado: PNG com fundo preto e imagem colorida. O fundo preto some automaticamente no header.</p>
            </div>
          )}
          {tab==="list"&&(
            <div style={{display:"flex",flexDirection:"column",gap:8}}>
              {[...games].sort((a,b)=>a.title.localeCompare(b.title)).map(g=>(
                <div key={g.id} style={{display:"flex",alignItems:"center",gap:12,background:"rgba(255,255,255,0.02)",border:"1px solid rgba(255,255,255,0.05)",borderRadius:8,padding:"10px 14px"}}>
                  <div style={{width:36,height:36,background:g.coverBase64?"transparent":ra(0.1),borderRadius:6,overflow:"hidden",border:`1px solid ${ra(0.2)}`,flexShrink:0}}>
                    {g.coverBase64?<img src={g.coverBase64} alt="" style={{width:"100%",height:"100%",objectFit:"cover"}}/>
                      :<div style={{width:"100%",height:"100%",display:"flex",alignItems:"center",justifyContent:"center",fontSize:12,color:R,fontFamily:"'Press Start 2P',monospace"}}>{fl(g.title)}</div>}
                  </div>
                  <div style={{flex:1,minWidth:0}}>
                    <div style={{fontSize:11,color:"#e2e8f0",fontWeight:600,whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"}}>{g.title}</div>
                    <div style={{fontSize:9,color:"#475569"}}>{g.genre||"—"} · {g.year||"—"} · {g.jarUrl?"✓ JAR":"⚠ sem JAR"} · {g.gallery?.length||0} imgs</div>
                  </div>
                  <div style={{display:"flex",gap:6,flexShrink:0}}>
                    <button onClick={()=>startEdit(g)} style={{background:"transparent",border:`1px solid ${ra(0.2)}`,color:R,padding:"4px 10px",borderRadius:6,cursor:"pointer",fontSize:10}}>✏</button>
                    {del===g.id
                      ?<button onClick={()=>{onSave(games.filter(x=>x.id!==g.id));setDel(null);}} style={{background:R2,border:"none",color:"#fff",padding:"4px 10px",borderRadius:6,cursor:"pointer",fontSize:10}}>CONFIRMAR</button>
                      :<button onClick={()=>setDel(g.id)} style={{background:"transparent",border:`1px solid ${ra(0.2)}`,color:R,padding:"4px 10px",borderRadius:6,cursor:"pointer",fontSize:10}}>🗑</button>}
                  </div>
                </div>
              ))}
              {games.length===0&&<div style={{textAlign:"center",color:"#334155",padding:40,fontSize:11}}>NENHUM JOGO CADASTRADO</div>}
            </div>
          )}
          {tab==="add"&&(
            <div style={{display:"flex",flexDirection:"column",gap:16}}>
              <div>
                <label style={lbl}>// CAPA DO JOGO</label>
                <div style={{display:"flex",gap:12,alignItems:"flex-start"}}>
                  <div style={{width:90,height:90,background:"rgba(255,255,255,0.03)",border:`1px solid ${ra(0.15)}`,borderRadius:8,overflow:"hidden",flexShrink:0}}>
                    {form.coverBase64?<img src={form.coverBase64} alt="capa" style={{width:"100%",height:"100%",objectFit:"cover"}}/>
                      :<div style={{width:"100%",height:"100%",display:"flex",alignItems:"center",justifyContent:"center",color:"#334155",fontSize:9}}>SEM CAPA</div>}
                  </div>
                  <div style={{flex:1,display:"flex",flexDirection:"column",gap:8}}>
                    <UploadBtn accept="image/*" onFile={b=>setForm(f=>({...f,coverBase64:b}))}>📁 UPLOAD DA CAPA</UploadBtn>
                    {form.coverBase64&&<button onClick={()=>setForm(f=>({...f,coverBase64:""}))} style={{background:"transparent",border:`1px solid ${ra(0.2)}`,color:"#94a3b8",padding:"8px",borderRadius:8,cursor:"pointer",fontSize:10}}>✕ REMOVER</button>}
                  </div>
                </div>
              </div>
              <div><label style={lbl}>// TÍTULO *</label><input value={form.title} onChange={e=>setForm({...form,title:e.target.value})} placeholder="Ex: Snake II" style={inp}/></div>
              <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:12}}>
                <div><label style={lbl}>// GÊNERO</label>
                  <select value={form.genre} onChange={e=>setForm({...form,genre:e.target.value})} style={{...inp,appearance:"none"}}>
                    <option value="">Selecionar...</option>
                    {GENRES.map(g=><option key={g} value={g}>{g}</option>)}
                  </select>
                </div>
                <div><label style={lbl}>// ANO</label><input value={form.year} onChange={e=>setForm({...form,year:e.target.value})} placeholder="2004" style={inp}/></div>
              </div>
              <div><label style={lbl}>// SINOPSE</label><textarea value={form.synopsis} onChange={e=>setForm({...form,synopsis:e.target.value})} rows={3} placeholder="Breve descrição..." style={{...inp,resize:"vertical"}}/></div>
              <div><label style={lbl}>// CONTEÚDO EXTRA (história, controles, dicas...)</label><textarea value={form.content} onChange={e=>setForm({...form,content:e.target.value})} rows={4} placeholder="Texto longo, curiosidades, como jogar..." style={{...inp,resize:"vertical"}}/></div>
              <div>
                <label style={lbl}>// GALERIA ({form.gallery.length} imagem{form.gallery.length!==1?"s":""})</label>
                {form.gallery.length>0&&(
                  <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(90px,1fr))",gap:6,marginBottom:8}}>
                    {form.gallery.map((img,i)=>(
                      <div key={i} style={{position:"relative"}}>
                        <img src={img} alt="" style={{width:"100%",height:70,objectFit:"cover",borderRadius:6,border:`1px solid ${ra(0.15)}`}}/>
                        <button onClick={()=>setForm(f=>({...f,gallery:f.gallery.filter((_,j)=>j!==i)}))} style={{position:"absolute",top:3,right:3,background:"rgba(0,0,0,0.7)",border:"none",color:"#fff",borderRadius:"50%",width:18,height:18,cursor:"pointer",fontSize:9,padding:0}}>✕</button>
                      </div>
                    ))}
                  </div>
                )}
                <UploadBtn accept="image/*" onFile={async b=>setForm(f=>({...f,gallery:[...f.gallery,b]}))}>📁 ADICIONAR À GALERIA</UploadBtn>
              </div>
              <div>
                <label style={lbl}>// ARQUIVO .JAR</label>
                <UploadBtn accept=".jar,application/java-archive" onFile={url=>setForm(f=>({...f,jarUrl:url}))}>📁 UPLOAD DO .JAR</UploadBtn>
                {form.jarUrl&&<div style={{marginTop:8,fontSize:9,color:"#64748b",wordBreak:"break-all"}}>{form.jarUrl}</div>}
              </div>
              <div><label style={lbl}>// URL DO ARQUIVO .JAR</label><input value={form.jarUrl} onChange={e=>setForm({...form,jarUrl:e.target.value})} placeholder="https://seusite.com/uploads/games/jogo.jar" style={inp}/></div>
              <button onClick={save} disabled={!form.title.trim()}
                style={{background:form.title.trim()?`linear-gradient(135deg,${R},${R2})`:"rgba(255,255,255,0.05)",border:"none",borderRadius:10,padding:"14px",color:form.title.trim()?"#fff":"#334155",fontSize:11,fontFamily:"'IBM Plex Mono',monospace",letterSpacing:"0.15em",fontWeight:700,cursor:form.title.trim()?"pointer":"default"}}>
                {editId?"✓ SALVAR ALTERAÇÕES":"✓ PUBLICAR JOGO"}
              </button>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

// ── ROOT ───────────────────────────────────────────────────────────────────
function App(){
  const [games,setGames]=useState([]);
  const [logo,setLogo]=useState("");
  const [favs,setFavs]=useState([]);
  const [plays,setPlays]=useState({});
  const [view,setView]=useState("library");
  const [sel,setSel]=useState(null);
  const [admin,setAdmin]=useState(false);

  useEffect(()=>{
    const l=document.createElement("link");
    l.rel="stylesheet";
    l.href="https://fonts.googleapis.com/css2?family=Press+Start+2P&family=IBM+Plex+Mono:wght@400;600;700&display=swap";
    document.head.appendChild(l);
  },[]);

  useEffect(()=>{
    (async()=>{
      try{
        const rg=await window.storage.get(SK_GAMES); setGames(rg?JSON.parse(rg.value):SAMPLE); if(!rg)await window.storage.set(SK_GAMES,JSON.stringify(SAMPLE));
        const rl=await window.storage.get(SK_LOGO);  if(rl)setLogo(rl.value);
        const rf=await window.storage.get(SK_FAVS);  if(rf)setFavs(JSON.parse(rf.value));
        const rp=await window.storage.get(SK_PLAYS); if(rp)setPlays(JSON.parse(rp.value));
      }catch{setGames(SAMPLE);}
    })();
  },[]);

  useEffect(()=>{
    const syncHash=()=>{
      const page=window.location.hash.replace("#","");
      if(["about","contact","privacy","terms"].includes(page)){setSel(null);setView(page);}
      if(page==="home"||page===""){setSel(null);setView("library");}
    };
    syncHash();
    window.addEventListener("hashchange",syncHash);
    return()=>window.removeEventListener("hashchange",syncHash);
  },[]);

  const saveGames=useCallback(async up=>{
    const previous=games;
    setGames(up);
    try{await window.storage.set(SK_GAMES,JSON.stringify(up));}
    catch(err){setGames(previous);alert(err.message||"Nao foi possivel salvar os jogos.");throw err;}
  },[games]);
  const saveLogo =useCallback(async b=>{
    const previous=logo;
    setLogo(b);
    try{await window.storage.set(SK_LOGO,b);}
    catch(err){setLogo(previous);alert(err.message||"Nao foi possivel salvar a logo.");throw err;}
  },[logo]);

  const toggleFav=useCallback(async id=>{
    setFavs(prev=>{
      const next=prev.includes(id)?prev.filter(x=>x!==id):[...prev,id];
      window.storage.set(SK_FAVS,JSON.stringify(next)).catch(()=>{});
      return next;
    });
  },[]);

  const registerPlay=useCallback(async id=>{
    setPlays(prev=>{
      const next={...prev,[id]:(prev[id]||0)+1};
      window.storage.set(SK_PLAYS,JSON.stringify(next)).catch(()=>{});
      return next;
    });
  },[]);

  const handleSelect=g=>{setSel(g);setView("detail");};
  const handlePlay=g=>{registerPlay(g.id);setSel(g);setView("emulator");};
  const handleHome=()=>{setSel(null);setView("library");window.location.hash="home";window.scrollTo({top:0,behavior:"smooth"});};
  const handleNavigate=page=>{setSel(null);setView(page);window.location.hash=page==="library"?"home":page;window.scrollTo({top:0,behavior:"smooth"});};

  return(
    <div style={{fontFamily:"'IBM Plex Mono','Courier New',monospace",background:"#06060e",minHeight:"100vh",color:"#e2e8f0",overflowX:"hidden",position:"relative"}}>
      <div style={{position:"fixed",inset:0,zIndex:0,pointerEvents:"none",backgroundImage:`linear-gradient(${ra(0.03)} 1px,transparent 1px),linear-gradient(90deg,${ra(0.03)} 1px,transparent 1px)`,backgroundSize:"40px 40px"}}/>
      <div style={{position:"fixed",inset:0,zIndex:0,pointerEvents:"none",backgroundImage:"repeating-linear-gradient(0deg,transparent,transparent 2px,rgba(0,0,0,0.15) 2px,rgba(0,0,0,0.15) 4px)",opacity:0.4}}/>
      <div style={{position:"fixed",top:"10%",left:"50%",transform:"translateX(-50%)",width:600,height:300,background:`radial-gradient(ellipse,${ra(0.06)} 0%,transparent 70%)`,pointerEvents:"none",zIndex:0}}/>
      <Header logo={logo} onAdmin={()=>setAdmin(true)} onHome={handleHome} favCount={favs.length}/>
      <main>
        {view==="library"&&<Library games={games} favs={favs} plays={plays} onSelect={handleSelect} onToggleFav={toggleFav}/>}
        {view==="detail"&&sel&&<Detail game={sel} onPlay={handlePlay} onBack={()=>setView("library")} isFav={favs.includes(sel.id)} onToggleFav={toggleFav} playCount={plays[sel.id]||0}/>}
        {view==="emulator"&&sel&&<Emulator game={sel} onBack={()=>setView("detail")}/>}
        {["about","contact","privacy","terms"].includes(view)&&<StaticPage page={view} onNavigate={handleNavigate}/>}
      </main>
      <Footer onNavigate={handleNavigate}/>
      {admin&&<Admin games={games} logo={logo} onSave={saveGames} onSaveLogo={saveLogo} onClose={()=>setAdmin(false)}/>}
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
