/* —- todo el CSS va con prefijo #quiniela-root para no chocar con WordPress —- */
#quiniela-root{
–bg:#07140D; –bg2:#0B2417; –card:#0F2D1C; –card2:#13392550;
–line:#1F4D34; –text:#F3FBF6; –chalk:#CFE8D8; –muted:#7FA38D;
–gold:#F4C95D; –gold-deep:#D9A93B; –teal:#23C4A8; –red:#E2574C;
–silver:#C9D2D6; –bronze:#CC8B58;
–r:16px;
font-family:’Outfit’,system-ui,-apple-system,Segoe UI,Roboto,sans-serif;
color:var(–text);
max-width:580px; margin:0 auto; padding:0 14px 60px;
-webkit-font-smoothing:antialiased; line-height:1.45;
}
#quiniela-root *{box-sizing:border-box;}
#quiniela-root .qbg{
position:fixed; inset:0; z-index:-1;
background:
radial-gradient(120% 60% at 50% -10%, #14492E 0%, transparent 60%),
linear-gradient(180deg, var(–bg2) 0%, var(–bg) 55%);
}
#quiniela-root h1,#quiniela-root h2,#quiniela-root h3{margin:0; font-weight:400;}
#quiniela-root button{font-family:inherit; cursor:pointer; border:none;}
#quiniela-root input{font-family:inherit;}
/* —- HERO —- */
#quiniela-root .hero{position:relative; text-align:center; padding:26px 0 16px; overflow:hidden;}
#quiniela-root .hero .circle{
position:absolute; left:50%; top:6px; transform:translateX(-50%);
width:230px; height:230px; border:1.5px solid var(–line); border-radius:50%;
opacity:.5; pointer-events:none;
}
#quiniela-root .hero .circle:after{
content:””; position:absolute; left:50%; top:0; transform:translateX(-50%);
width:1.5px; height:230px; background:var(–line);
}
#quiniela-root .eyebrow{
font-size:12px; letter-spacing:.32em; color:var(–gold); font-weight:700;
text-transform:uppercase; position:relative;
}
#quiniela-root .hero h1{
font-family:’Anton’,sans-serif; font-size:clamp(40px,13vw,68px); line-height:.9;
letter-spacing:.01em; position:relative; margin-top:2px;
}
#quiniela-root .hero h1 .yr{color:var(–gold); display:block;}
#quiniela-root .hero .sub{color:var(–chalk); font-size:13.5px; margin-top:8px; position:relative;}
/* —- user chip —- */
#quiniela-root .me{
display:flex; align-items:center; justify-content:space-between; gap:10px;
background:var(–card); border:1px solid var(–line); border-radius:var(–r);
padding:11px 14px; margin-top:14px;
}
#quiniela-root .me .who{display:flex; align-items:center; gap:9px; min-width:0;}
#quiniela-root .me .av{
width:34px;height:34px;border-radius:50%;flex:none;
background:linear-gradient(135deg,var(–teal),#0E8C7A);
display:grid;place-items:center;font-weight:800;font-size:15px;color:#04221C;
}
#quiniela-root .me .nm{font-weight:700; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
#quiniela-root .me .pts{text-align:right; flex:none;}
#quiniela-root .me .pts b{font-family:’Anton’;font-size:24px;color:var(–gold);line-height:1;display:block;}
#quiniela-root .me .pts span{font-size:10px;color:var(–muted);letter-spacing:.12em;text-transform:uppercase;}
/* —- tabs —- */
#quiniela-root .tabs{
display:flex; gap:6px; margin:16px 0 4px; position:sticky; top:0; z-index:5;
padding:8px 0; background:linear-gradient(180deg,var(–bg) 70%, transparent);
}
#quiniela-root .tabs button{
flex:1; padding:11px 6px; border-radius:11px; font-weight:700; font-size:13.5px;
background:var(–card); color:var(–chalk); border:1px solid var(–line);
transition:.15s;
}
#quiniela-root .tabs button.on{background:var(–gold); color:#1A1206; border-color:var(–gold);}
/* —- banner —- */
#quiniela-root .banner{
border-radius:12px; padding:11px 14px; font-size:13px; margin:10px 0; font-weight:500;
display:flex; gap:9px; align-items:flex-start;
}
#quiniela-root .banner.warn{background:#3A2A0E; border:1px solid var(–gold-deep); color:#FBE7B6;}
#quiniela-root .banner.demo{background:#0E2C3A; border:1px solid var(–teal); color:#BBEFE6;}
#quiniela-root .banner.lock{background:#3A1714; border:1px solid var(–red); color:#F6C9C4;}
/* —- group + match card —- */
#quiniela-root .grp{margin-top:18px;}
#quiniela-root .grp-h{display:flex;align-items:center;gap:10px;margin:0 2px 9px;}
#quiniela-root .grp-h .tag{
font-family:’Anton’; font-size:15px; background:var(–card2); color:var(–gold);
border:1px solid var(–line); width:30px;height:30px;border-radius:9px;
display:grid;place-items:center;
}
#quiniela-root .grp-h .lbl{font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:var(–muted);font-weight:700;}
#quiniela-root .jor{font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(–muted);margin:12px 4px 6px;font-weight:700;}
#quiniela-root .match{
background:var(–card); border:1px solid var(–line); border-radius:14px;
padding:12px 12px; margin-bottom:9px;
}
#quiniela-root .match.done{border-color:var(–gold-deep);}
#quiniela-root .row{display:grid; grid-template-columns:1fr auto 1fr; align-items:center; gap:8px;}
#quiniela-root .team{display:flex; align-items:center; gap:8px; min-width:0;}
#quiniela-root .team.r{flex-direction:row-reverse; text-align:right;}
#quiniela-root .team .fl{font-size:23px; line-height:1; flex:none;}
#quiniela-root .team .tn{font-size:14px; font-weight:600; line-height:1.1;}
#quiniela-root .score{display:flex; align-items:center; gap:7px;}
#quiniela-root .score input{
width:44px; height:46px; text-align:center; font-family:’Anton’; font-size:24px;
background:var(–bg); color:var(–text); border:1.5px solid var(–line);
border-radius:10px; padding:0; -moz-appearance:textfield;
}
#quiniela-root .score input::-webkit-outer-spin-button,
#quiniela-root .score input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0;}
#quiniela-root .score input:focus{outline:none; border-color:var(–gold); box-shadow:0 0 0 3px #F4C95D33;}
#quiniela-root .score input:disabled{opacity:.85; border-color:var(–line); background:var(–card2);}
#quiniela-root .score .dash{color:var(–muted); font-weight:800;}
/* resultado real + puntos ganados */
#quiniela-root .res{
display:flex; align-items:center; justify-content:space-between; gap:10px;
margin-top:9px; padding-top:9px; border-top:1px dashed var(–line); font-size:12px;
}
#quiniela-root .res .real{color:var(–chalk);}
#quiniela-root .res .real b{color:var(–gold);}
#quiniela-root .pill{font-weight:800; font-size:12px; padding:3px 9px; border-radius:20px;}
#quiniela-root .pill.p5{background:var(–gold); color:#1A1206;}
#quiniela-root .pill.p2{background:#16463B; color:var(–teal); border:1px solid var(–teal);}
#quiniela-root .pill.p0{background:#2A1310; color:#E89B92; border:1px solid #6B302A;}
/* —- save bar —- */
#quiniela-root .savebar{position:sticky; bottom:0; padding:12px 0 6px; background:linear-gradient(0deg,var(–bg) 65%, transparent); z-index:5;}
#quiniela-root .btn{
width:100%; padding:15px; border-radius:13px; font-weight:800; font-size:15.5px;
background:var(–gold); color:#1A1206; transition:.15s; letter-spacing:.01em;
}
#quiniela-root .btn:active{transform:translateY(1px);}
#quiniela-root .btn.ghost{background:transparent; color:var(–gold); border:1.5px solid var(–gold-deep);}
#quiniela-root .btn:disabled{opacity:.45;}
#quiniela-root .btn.sm{width:auto; padding:9px 16px; font-size:13px;}
/* —- leaderboard —- */
#quiniela-root .podium{display:grid; grid-template-columns:1fr 1.15fr 1fr; gap:8px; align-items:end; margin:6px 0 14px;}
#quiniela-root .pod{background:var(–card); border:1px solid var(–line); border-radius:13px; padding:13px 8px; text-align:center;}
#quiniela-root .pod .medal{font-size:22px;}
#quiniela-root .pod .pn{font-weight:700; font-size:13px; margin-top:4px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
#quiniela-root .pod .pp{font-family:’Anton’; font-size:26px; line-height:1; margin-top:3px;}
#quiniela-root .pod.g1{border-color:var(–gold); padding-top:20px;}
#quiniela-root .pod.g1 .pp{color:var(–gold);}
#quiniela-root .pod.g2 .pp{color:var(–silver);}
#quiniela-root .pod.g3 .pp{color:var(–bronze);}
#quiniela-root .lbrow{
display:flex; align-items:center; gap:11px; padding:11px 13px; border-radius:11px;
background:var(–card); border:1px solid var(–line); margin-bottom:7px;
}
#quiniela-root .lbrow.me-row{border-color:var(–teal); background:#0E2C28;}
#quiniela-root .lbrow .rk{font-family:’Anton’; font-size:17px; color:var(–muted); width:24px; text-align:center; flex:none;}
#quiniela-root .lbrow .lname{flex:1; font-weight:600; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
#quiniela-root .lbrow .lx{font-size:11px; color:var(–muted);}
#quiniela-root .lbrow .lp{font-family:’Anton’; font-size:20px; color:var(–gold); flex:none;}
#quiniela-root .empty{text-align:center; color:var(–muted); padding:36px 16px; font-size:14px;}
/* —- rules —- */
#quiniela-root .rule{display:flex; gap:13px; align-items:center; background:var(–card); border:1px solid var(–line); border-radius:13px; padding:14px; margin-bottom:10px;}
#quiniela-root .rule .num{font-family:’Anton’; font-size:30px; flex:none; width:54px; text-align:center;}
#quiniela-root .rule.r5 .num{color:var(–gold);} #quiniela-root .rule.r2 .num{color:var(–teal);} #quiniela-root .rule.r0 .num{color:#E89B92;}
#quiniela-root .rule .rt b{display:block; font-size:15px; margin-bottom:2px;}
#quiniela-root .rule .rt span{font-size:13px; color:var(–chalk);}
/* —- registro / modal —- */
#quiniela-root .gate{background:var(–card); border:1px solid var(–line); border-radius:18px; padding:22px; margin-top:18px;}
#quiniela-root .gate h2{font-family:’Anton’; font-size:24px; margin-bottom:4px;}
#quiniela-root .gate p{color:var(–chalk); font-size:13.5px; margin:0 0 16px;}
#quiniela-root .field{margin-bottom:13px;}
#quiniela-root .field label{display:block; font-size:12px; color:var(–muted); margin-bottom:6px; font-weight:600; letter-spacing:.04em;}
#quiniela-root .field input{
width:100%; padding:13px 14px; border-radius:11px; font-size:15px;
background:var(–bg); color:var(–text); border:1.5px solid var(–line);
}
#quiniela-root .field input:focus{outline:none; border-color:var(–teal);}
#quiniela-root .err{color:#F1A39B; font-size:12.5px; margin-top:8px; min-height:16px;}
#quiniela-root .footlink{text-align:center; margin-top:30px; color:var(–muted); font-size:11.5px;}
#quiniela-root .footlink a{color:var(–muted); cursor:pointer; text-decoration:underline;}
/* —- admin —- */
#quiniela-root .amrow{display:grid; grid-template-columns:1fr auto; gap:10px; align-items:center; background:var(–card); border:1px solid var(–line); border-radius:11px; padding:9px 11px; margin-bottom:7px;}
#quiniela-root .amrow .at{font-size:12.5px; font-weight:600; line-height:1.2;}
#quiniela-root .amrow .at small{color:var(–muted); font-weight:500;}
#quiniela-root .amrow .ai{display:flex; gap:5px; align-items:center;}
#quiniela-root .amrow .ai input{width:38px; height:38px; text-align:center; font-family:’Anton’; font-size:18px; background:var(–bg); color:var(–text); border:1.5px solid var(–line); border-radius:9px;}
#quiniela-root .amrow .ai button{padding:0 12px; height:38px; border-radius:9px; background:var(–teal); color:#04221C; font-weight:800; font-size:13px;}
#quiniela-root .amrow.saved{border-color:var(–gold-deep);}
#quiniela-root .toggle{display:flex; gap:10px; align-items:center; justify-content:space-between; background:var(–card); border:1px solid var(–line); border-radius:13px; padding:14px; margin-bottom:12px;}
#quiniela-root .toggle .tl b{display:block;} #quiniela-root .toggle .tl span{font-size:12px; color:var(–muted);}
#quiniela-root .toast{
position:fixed; left:50%; bottom:26px; transform:translateX(-50%) translateY(20px);
background:var(–gold); color:#1A1206; font-weight:700; padding:13px 22px; border-radius:30px;
font-size:14px; opacity:0; transition:.25s; z-index:50; box-shadow:0 8px 30px #0008; pointer-events:none;
}
#quiniela-root .toast.show{opacity:1; transform:translateX(-50%) translateY(0);}
#quiniela-root .hidden{display:none !important;}
@media (prefers-reduced-motion:reduce){#quiniela-root *{transition:none !important;}}
(function(){
/* ============================================================
1) CONFIG — EDITA ESTAS 3 LÍNEAS
============================================================ */
const SUPABASE_URL = “TU_SUPABASE_URL”; // ej: https://abcd.supabase.co
const SUPABASE_ANON = “TU_SUPABASE_ANON_KEY”; // la clave “anon public”
const ADMIN_PASS = “cambia-esta-clave”; // clave para que SOLO tú cargues resultados
/* ============================================================ */
const root = document.getElementById(‘quiniela-root’);
const $ = s => root.querySelector(s);
const DEMO = !SUPABASE_URL || SUPABASE_URL.indexOf(‘TU_’)===0;
/* —- almacenamiento seguro (no rompe dentro de la vista previa) —- */
const mem = {};
const store = {
get(k){ try{ const v=localStorage.getItem(k); return v==null?(k in mem?mem[k]:null):v; }catch(e){ return k in mem?mem[k]:null; } },
set(k,v){ try{ localStorage.setItem(k,v); }catch(e){ mem[k]=v; } }
};
/* —- datos: grupos del sorteo oficial (5 dic 2025) —- */
const GRUPOS = {
A:[‘México’,’Sudáfrica’,’Corea del Sur’,’Chequia’],
B:[‘Canadá’,’Bosnia y Herzegovina’,’Catar’,’Suiza’],
C:[‘Brasil’,’Marruecos’,’Haití’,’Escocia’],
D:[‘Estados Unidos’,’Paraguay’,’Australia’,’Turquía’],
E:[‘Alemania’,’Curazao’,’Costa de Marfil’,’Ecuador’],
F:[‘Países Bajos’,’Japón’,’Suecia’,’Túnez’],
G:[‘Bélgica’,’Egipto’,’Irán’,’Nueva Zelanda’],
H:[‘España’,’Cabo Verde’,’Arabia Saudí’,’Uruguay’],
I:[‘Francia’,’Senegal’,’Irak’,’Noruega’],
J:[‘Argentina’,’Argelia’,’Austria’,’Jordania’],
K:[‘Portugal’,’RD Congo’,’Uzbekistán’,’Colombia’],
L:[‘Inglaterra’,’Croacia’,’Ghana’,’Panamá’]
};
const FLAG = {
‘México’:’🇲🇽’,’Sudáfrica’:’🇿🇦’,’Corea del Sur’:’🇰🇷’,’Chequia’:’🇨🇿’,
‘Canadá’:’🇨🇦’,’Bosnia y Herzegovina’:’🇧🇦’,’Catar’:’🇶🇦’,’Suiza’:’🇨🇭’,
‘Brasil’:’🇧🇷’,’Marruecos’:’🇲🇦’,’Haití’:’🇭🇹’,’Escocia’:’🏴’,
‘Estados Unidos’:’🇺🇸’,’Paraguay’:’🇵🇾’,’Australia’:’🇦🇺’,’Turquía’:’🇹🇷’,
‘Alemania’:’🇩🇪’,’Curazao’:’🇨🇼’,’Costa de Marfil’:’🇨🇮’,’Ecuador’:’🇪🇨’,
‘Países Bajos’:’🇳🇱’,’Japón’:’🇯🇵’,’Suecia’:’🇸🇪’,’Túnez’:’🇹🇳’,
‘Bélgica’:’🇧🇪’,’Egipto’:’🇪🇬’,’Irán’:’🇮🇷’,’Nueva Zelanda’:’🇳🇿’,
‘España’:’🇪🇸’,’Cabo Verde’:’🇨🇻’,’Arabia Saudí’:’🇸🇦’,’Uruguay’:’🇺🇾’,
‘Francia’:’🇫🇷’,’Senegal’:’🇸🇳’,’Irak’:’🇮🇶’,’Noruega’:’🇳🇴’,
‘Argentina’:’🇦🇷’,’Argelia’:’🇩🇿’,’Austria’:’🇦🇹’,’Jordania’:’🇯🇴’,
‘Portugal’:’🇵🇹’,’RD Congo’:’🇨🇩’,’Uzbekistán’:’🇺🇿’,’Colombia’:’🇨🇴’,
‘Inglaterra’:’🏴’,’Croacia’:’🇭🇷’,’Ghana’:’🇬🇭’,’Panamá’:’🇵🇦’
};
const fl = n => FLAG[n] || ‘⚽’;
/* —- generar los 72 partidos de fase de grupos (round-robin) —- */
const PAIRS=[[0,1],[2,3],[0,2],[3,1],[3,0],[1,2]], JOR=[1,1,2,2,3,3];
function buildMatches(){
const out=[]; let gi=0;
for(const g in GRUPOS){ const t=GRUPOS[g];
PAIRS.forEach((p,i)=>out.push({
id: gi*6+i+1, grupo:g, jornada:JOR[i], local:t[p[0]], visitante:t[p[1]],
goles_local:null, goles_visitante:null, finalizado:false
}));
gi++;
}
return out;
}
/* —- puntaje: marcador exacto = 5, solo ganador/empate = 2, falla = 0 —- */
function puntos(pl,pv,m){
if(m.goles_local==null||m.goles_visitante==null) return null;
if(pl===m.goles_local && pv===m.goles_visitante) return 5;
if(Math.sign(pl-pv)===Math.sign(m.goles_local-m.goles_visitante)) return 2;
return 0;
}
/* ============================================================
2) CAPA DE DATOS (Demo = este navegador / Real = Supabase)
============================================================ */
let DB;
const LocalDB = {
async init(){ if(!store.get(‘q_matches’)) store.set(‘q_matches’, JSON.stringify(buildMatches())); },
async ensureSeed(){ store.set(‘q_matches’, JSON.stringify(buildMatches())); },
async getConfig(){ const v=store.get(‘q_config’); return v?JSON.parse(v):{abiertas:true}; },
async setConfig(ab){ store.set(‘q_config’, JSON.stringify({abiertas:ab})); },
async getMatches(){ const v=store.get(‘q_matches’); return v?JSON.parse(v):buildMatches(); },
async setResult(id,gl,gv){ const ms=await this.getMatches(); const m=ms.find(x=>x.id===id);
if(m){ m.goles_local=gl; m.goles_visitante=gv; m.finalizado=true; } store.set(‘q_matches’,JSON.stringify(ms)); },
async registerParticipant(nombre,tel){ const ps=this._parts(); const id=’d’+Date.now();
ps.push({id,nombre,tel}); store.set(‘q_parts’,JSON.stringify(ps)); return {id,nombre}; },
_parts(){ const v=store.get(‘q_parts’); return v?JSON.parse(v):[]; },
async getMyPredictions(pid){ const v=store.get(‘q_pred_’+pid); return v?JSON.parse(v):{}; },
async savePredictions(pid,obj){ store.set(‘q_pred_’+pid, JSON.stringify(obj)); },
async getLeaderboard(){
const ps=this._parts(), ms=await this.getMatches();
const byId={}; ms.forEach(m=>byId[m.id]=m);
return ps.map(p=>{ const pr=JSON.parse(store.get(‘q_pred_’+p.id)||'{}’); let pts=0,ex=0;
for(const mid in pr){ const m=byId[mid]; if(!m) continue;
const s=puntos(pr[mid].pl,pr[mid].pv,m); if(s===5)ex++; if(s) pts+=s; }
return {participant_id:p.id, nombre:p.nombre, puntos:pts, exactos:ex};
}).sort((a,b)=> b.puntos-a.puntos || b.exactos-a.exactos);
}
};
const SupaDB = (sb)=>({
async init(){},
async ensureSeed(){
await sb.from(‘matches’).upsert(buildMatches().map(m=>({
id:m.id,grupo:m.grupo,jornada:m.jornada,local:m.local,visitante:m.visitante
})),{onConflict:’id’,ignoreDuplicates:true});
await sb.from(‘config’).upsert({id:1,abiertas:true},{onConflict:’id’,ignoreDuplicates:true});
},
async getConfig(){ const {data}=await sb.from(‘config’).select(‘abiertas’).eq(‘id’,1).maybeSingle();
return {abiertas: data? data.abiertas : true}; },
async setConfig(ab){ await sb.from(‘config’).upsert({id:1,abiertas:ab},{onConflict:’id’}); },
async getMatches(){ const {data}=await sb.from(‘matches’).select(‘*’).order(‘id’); return data||[]; },
async setResult(id,gl,gv){ await sb.from(‘matches’).update({goles_local:gl,goles_visitante:gv,finalizado:true}).eq(‘id’,id); },
async registerParticipant(nombre,tel){ const {data}=await sb.from(‘participants’).insert({nombre,telefono:tel}).select().single(); return data; },
async getMyPredictions(pid){ const {data}=await sb.from(‘predictions’).select(‘match_id,pred_local,pred_visitante’).eq(‘participant_id’,pid);
const o={}; (data||[]).forEach(r=>o[r.match_id]={pl:r.pred_local,pv:r.pred_visitante}); return o; },
async savePredictions(pid,obj){
const rows=Object.keys(obj).map(mid=>({participant_id:pid,match_id:+mid,pred_local:obj[mid].pl,pred_visitante:obj[mid].pv}));
if(rows.length) await sb.from(‘predictions’).upsert(rows,{onConflict:’participant_id,match_id’});
},
async getLeaderboard(){ const {data}=await sb.from(‘leaderboard’).select(‘*’); return data||[]; }
});
function loadSupabaseLib(){
return new Promise((res,rej)=>{ if(window.supabase) return res();
const s=document.createElement(‘script’); s.src=’https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2′;
s.onload=res; s.onerror=()=>rej(new Error(‘No se pudo cargar Supabase’)); document.head.appendChild(s); });
}
/* ============================================================
3) ESTADO + ARRANQUE
============================================================ */
const S = { me:null, matches:[], config:{abiertas:true}, myPred:{}, admin:false };
function toast(msg){ const t=$(‘#toast’); t.textContent=msg; t.classList.add(‘show’); setTimeout(()=>t.classList.remove(‘show’),2200); }
async function boot(){
if(DEMO){ DB=LocalDB; }
else{
try{ await loadSupabaseLib(); const sb=window.supabase.createClient(SUPABASE_URL,SUPABASE_ANON); DB=SupaDB(sb); }
catch(e){ DB=LocalDB; }
}
await DB.init();
S.config = await DB.getConfig();
S.matches = await DB.getMatches();
if(!S.matches.length && DEMO){ await DB.ensureSeed(); S.matches=await DB.getMatches(); }
const saved = store.get(‘q_me’);
if(saved){ S.me=JSON.parse(saved); await afterLogin(); }
else{ $(‘#gate’).classList.remove(‘hidden’); }
}
async function afterLogin(){
$(‘#gate’).classList.add(‘hidden’);
$(‘#app’).classList.remove(‘hidden’);
$(‘#me-nm’).textContent = S.me.nombre;
$(‘#me-av’).textContent = S.me.nombre.trim().charAt(0).toUpperCase()||’?’;
S.myPred = await DB.getMyPredictions(S.me.id);
renderPron(); renderTabla(); renderReglas(); refreshMyPoints();
}
/* —- registro —- */
$(‘#g-enter’).addEventListener(‘click’, async ()=>{
const nombre = $(‘#g-nombre’).value.trim();
const tel = $(‘#g-tel’).value.trim();
if(nombre.length b.addEventListener(‘click’, ()=>{
root.querySelectorAll(‘.tabs button’).forEach(x=>x.classList.remove(‘on’)); b.classList.add(‘on’);
[‘pron’,’tabla’,’reglas’].forEach(t=> $(‘#view-‘+t).classList.toggle(‘hidden’, t!==b.dataset.tab));
if(b.dataset.tab===’tabla’) renderTabla();
}));
/* ============================================================
4) VISTA: PRONÓSTICOS
============================================================ */
function locked(m){ return !S.config.abiertas || m.finalizado; }
function renderPron(){
const v=$(‘#view-pron’); v.innerHTML=”;
if(DEMO){ v.insertAdjacentHTML(‘beforeend’,
``); }
if(!S.config.abiertas){ v.insertAdjacentHTML(‘beforeend’,
``); }
else { v.insertAdjacentHTML(‘beforeend’,
``); }
for(const g in GRUPOS){
const ms = S.matches.filter(m=>m.grupo===g);
const wrap=document.createElement(‘div’); wrap.className=’grp’;
wrap.innerHTML=`Polla Mundialista · Premio al líder
QUINIELAMUNDIAL 2026
Pronostica los marcadores · Suma puntos · Llévate el premio
${g}
Grupo ${g}
Jornada ${m.jornada}
`); }
const pr = S.myPred[m.id]||{};
const dis = locked(m)?’disabled’:”;
const card=document.createElement(‘div’); card.className=’match’+(m.finalizado?’ done’:”);
card.innerHTML=`
${fl(m.local)}${m.local}
–
${fl(m.visitante)}${m.visitante}
Resultado real: ${m.goles_local}–${m.goles_visitante} · ${mine}
${txt}
Cargando tabla…
‘;
let lb=[]; try{ lb=await DB.getLeaderboard(); }catch(e){ lb=[]; }
v.innerHTML=”;
if(!lb.length){ v.innerHTML=’Aún no hay participantes. ¡Sé el primero en llenar tu quiniela!
‘; return; }
const top=lb.slice(0,3);
if(lb.some(x=>x.puntos>0)){
const order=[1,0,2], cls=[‘g1′,’g2′,’g3’], med=[‘🥇’,’🥈’,’🥉’];
const pod=document.createElement(‘div’); pod.className=’podium’;
order.forEach(i=>{ const p=top[i]; if(!p){ pod.appendChild(document.createElement(‘div’)); return; }
const d=document.createElement(‘div’); d.className=’pod ‘+cls[i];
d.innerHTML=`${med[i]}
${esc(p.nombre)}
${p.puntos}
`;
pod.appendChild(d);
});
v.appendChild(pod);
}
lb.forEach((p,i)=>{
const meRow = String(p.participant_id)===String(S.me.id);
const row=document.createElement(‘div’); row.className=’lbrow’+(meRow?’ me-row’:”);
row.innerHTML=`${i+1}
${esc(p.nombre)}${meRow?’ · tú’:”} · ${p.exactos||0} exactos
${p.puntos}
`;
v.appendChild(row);
});
}
const esc = s => String(s).replace(/[&”]/g,c=>({‘&’:’&’,”:’>’,'”‘:’"’}[c]));
/* ============================================================
6) VISTA: REGLAS
============================================================ */
function renderReglas(){
$(‘#view-reglas’).innerHTML=`
5
Marcador exactoAciertas los goles de los dos equipos (ej. 2–1 y quedó 2–1).
2
Solo el ganadorAciertas quién ganó o que fue empate, pero no el marcador exacto.
0
Sin aciertoEl resultado fue distinto al que pronosticaste.
Pronósticos ${S.config.abiertas?’abiertos’:’cerrados’}${S.config.abiertas?’Los jugadores aún pueden editar’:’Ya nadie puede editar’}
${g}
Grupo ${g}
${fl(m.local)} ${m.local} vs ${m.visitante} ${fl(m.visitante)}
J${m.jornada}${m.finalizado?` · final: ${m.goles_local}–${m.goles_visitante}`:”}
J${m.jornada}${m.finalizado?` · final: ${m.goles_local}–${m.goles_visitante}`:”}
Comentarios recientes