/* ============================================================
   Personal Leagues — screens (built on the real Quantia components)
   Reuses: Icon, Avatar, MiniStrip, Move, initials, toast,
   fireConfetti, MatchCard, fmtDay  (all from ui.jsx / matches.jsx)
   Adds only the handful of glyphs + screens the feature needs.
   ============================================================ */

/* ---- extra glyphs (same Lucide stroke conventions as Icon) ---- */
function LIcon({ name, size = 22, stroke = 2 }) {
  const common = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: stroke, strokeLinecap: "round", strokeLinejoin: "round" };
  const paths = {
    back: <><path d="M15 5l-7 7 7 7" /></>,
    link: <><path d="M9.5 14.5l5-5M8 12l-2 2a3.5 3.5 0 0 0 5 5l2-2M16 12l2-2a3.5 3.5 0 0 0-5-5l-2 2" /></>,
    share: <><path d="M12 3v13M8 7l4-4 4 4" /><path d="M5 12v6a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-6" /></>,
    more: <><circle cx="5" cy="12" r="1.6" /><circle cx="12" cy="12" r="1.6" /><circle cx="19" cy="12" r="1.6" /></>,
    trash: <><path d="M4 7h16M9 7V5a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2M6 7l1 13a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1l1-13" /></>,
    refresh: <><path d="M3 12a9 9 0 0 1 15-6.7L21 8M21 4v4h-4M21 12a9 9 0 0 1-15 6.7L3 16M3 20v-4h4" /></>,
    shieldSm: <><path d="M12 3l8 3v6c0 5-3.5 8-8 9-4.5-1-8-4-8-9V6z" /></>,
    leagues: <><path d="M12 3l7 2.6v5.4c0 4.4-3 7-7 8-4-1-7-3.6-7-8V5.6z" /><path d="M12 8.5v4M10 10.5h4" /></>,
    whatsapp: <><path d="M12 3a9 9 0 0 0-7.7 13.7L3 21l4.5-1.2A9 9 0 1 0 12 3z" /><path d="M8.6 8.3c.2-.5.4-.5.7-.5h.4c.2 0 .4.1.5.5l.6 1.5c.1.2 0 .4-.1.5l-.4.5c-.1.2-.2.3 0 .6.5.8 1.2 1.4 2 1.8.3.1.4.1.6-.1l.4-.5c.2-.2.4-.2.6-.1l1.4.7c.2.1.3.3.3.5 0 .8-.7 1.5-1.5 1.6-.6 0-1.3 0-3.1-.9-2.3-1.3-3.6-3.8-3.7-4-.1-.2-.6-1.2-.6-2.3 0-.1 0-.2.1-.3z" /></>,
  };
  return <svg {...common}>{paths[name]}</svg>;
}

/* ---- responsive hook (correct inside a device-sized iframe) ---- */
function useIsDesktop() {
  const [d, setD] = useState(() => window.matchMedia("(min-width:880px)").matches);
  useEffect(() => {
    const mq = window.matchMedia("(min-width:880px)");
    const fn = () => setD(mq.matches);
    mq.addEventListener ? mq.addEventListener("change", fn) : mq.addListener(fn);
    return () => (mq.removeEventListener ? mq.removeEventListener("change", fn) : mq.removeListener(fn));
  }, []);
  return d;
}

/* ---- small avatar (initials) for stacks / podium reuse ---- */
function MiniAvatar({ name, size = 28 }) {
  return (
    <div style={{ width: size, height: size, borderRadius: "50%", background: "var(--q-gradient)", display: "grid", placeItems: "center", color: "#fff", fontFamily: "var(--font-head)", fontWeight: 800, fontSize: size * 0.38, flex: "none" }}>
      {initials(name)}
    </div>
  );
}
function AvStack({ names, max = 3, onLight }) {
  const shown = names.slice(0, max);
  const extra = names.length - shown.length;
  return (
    <div className={`lg-avstack ${onLight ? "on-light" : ""}`}>
      {shown.map((n, i) => <MiniAvatar key={i} name={n} size={28} />)}
      {extra > 0 && <span className="lg-avmore">+{extra}</span>}
    </div>
  );
}

/* ---- copy / share helpers ---- */
function inviteUrl(code) { return `quiniela.quantia.pe/join/${code}`; }
function copyLink(code) {
  const url = "https://" + inviteUrl(code);
  if (navigator.clipboard) navigator.clipboard.writeText(url).catch(() => {});
  toast("Link copiado", "ok");
}
function shareLink(league) {
  const url = "https://" + inviteUrl(league.code);
  const text = `¡Únete a mi liga "${league.name}" en Polla Quantia! ⚽\n${url}`;
  // share specifically via WhatsApp (wa.me opens the app / WhatsApp Web)
  window.open("https://wa.me/?text=" + encodeURIComponent(text), "_blank", "noopener");
}

/* =========================================================
   Leaderboard row + podium — same .qm-lb / .qm-podium markup,
   league-scoped data, with the commissioner shield the feature adds.
   ========================================================= */
function LeagueRow({ row, predsCount }) {
  const top = row.rank <= 3 ? `top${row.rank}` : "";
  const medal = row.rank === 1 ? "🥇" : row.rank === 2 ? "🥈" : row.rank === 3 ? "🥉" : null;
  return (
    <div className={`qm-lb-row ${row.you ? "me" : ""} ${top}`}>
      <div className="qm-lb-rank">
        {medal ? <span className="qm-medal">{medal}</span> : <span className="pos">{row.rank}</span>}
        <Move delta={row.delta} />
      </div>
      <div className="qm-lb-id">
        <div className="nm">
          {row.commish && <span className="lg-shield-ic" title="Organizador"><LIcon name="shieldSm" size={15} stroke={2.2} /></span>}
          <span className="txt" title={row.name}>{row.name}</span>
          {row.you && <span className="you">TÚ</span>}
        </div>
        {row.area ? <div className="ar">{row.area}</div> : null}
      </div>
      <MiniPreds uid={row.uid} count={predsCount} />
      <div className="qm-lb-pts">
        <div className="p">{row.pts}{row.live && <span title="Incluye puntos provisionales de un partido en juego" style={{ color: "var(--accent)", fontSize: 11, marginLeft: 3, verticalAlign: "super" }}>🔴</span>}</div>
        <div className="pl">pts</div>
      </div>
    </div>
  );
}
function Pod({ row }) {
  const cls = `qm-pod p${row.rank} ${row.you ? "me" : ""}`;
  return (
    <div className={cls}>
      {row.rank === 1 && <span className="crown">👑</span>}
      <div className="av">{initials(row.name)}</div>
      <div className="nm">{row.name}{row.commish ? " " : ""}</div>
      <div className="pp">{row.pts}<small> pts</small></div>
    </div>
  );
}
function LeaguePodium({ rows }) {
  const [first, second, third] = rows;
  if (!third) return null;
  return (
    <div className="qm-podium">
      <Pod row={second} />
      <Pod row={first} />
      <Pod row={third} />
    </div>
  );
}

/* =========================================================
   SCREEN 1 · Mis Ligas
   ========================================================= */
function LeagueCard({ league, onOpen }) {
  const Ql = window.QLeagues;
  const rows = Ql.ranked(league);
  const me = rows.find((r) => r.you);
  const n = Ql.memberCount(league);
  const creator = league.createdByYou ? "Creada por ti" : `Creada por ${league.commishName}`;
  return (
    <div className="qm-card lg-card qm-fadein" onClick={onOpen} role="button" tabIndex={0}>
      <div className="ic"><LIcon name="leagues" size={26} stroke={2.1} /></div>
      <div className="body">
        <div className="row1">
          <div className="nm">
            <b>{league.name}</b>
            {league.createdByYou && <span className="lg-commish"><LIcon name="shieldSm" size={11} stroke={2.4} />Organizador</span>}
          </div>
          <div className="rankbox">
            <div className="r">#{me ? me.rank : "–"}</div>
            <div className="p">{me ? me.pts : 0} pts</div>
          </div>
        </div>
        <div className="meta">{n} miembros · {creator}</div>
      </div>
    </div>
  );
}

function SkeletonCard() {
  const bar = (w, h = 12) => <div style={{ width: w, height: h, borderRadius: 6, background: "var(--bg-3)" }} />;
  return (
    <div className="qm-card lg-card" style={{ cursor: "default", pointerEvents: "none" }}>
      <div className="ic" style={{ background: "var(--bg-3)", boxShadow: "none" }} />
      <div className="body">
        <div className="row1"><div className="nm">{bar(150, 16)}</div><div className="rankbox">{bar(40, 22)}</div></div>
        <div className="meta">{bar(120)}</div>
      </div>
    </div>
  );
}

function MisLigasScreen({ leagues, loading, onOpen, onCreate, hideCreate }) {
  const Ql = window.QLeagues;
  const isDesktop = useIsDesktop();
  const canCreate = Ql.canCreate();   // corporate collaborator + fewer than 2 created
  const [tip, setTip] = useState(false);

  return (
    <div>
      <div className="qm-eyebrow"><img src="assets/asterisk.png" alt="" />Ligas privadas</div>
      <div style={{ display: "flex", alignItems: "flex-end", justifyContent: "space-between", gap: 12 }}>
        <h1 className="qm-h">Mis Ligas</h1>
        {!hideCreate && isDesktop && leagues.length > 0 && (
          <button className="qm-btn qm-btn-grad qm-btn-sm" disabled={!canCreate}
            onClick={onCreate} title={canCreate ? "" : "Límite de 2 ligas creadas"}>
            <Icon name="plus" size={17} stroke={2.4} />Crear liga
          </button>
        )}
      </div>
      <p className="qm-sub">
        {hideCreate
          ? "Tus ligas y su tabla de posiciones. Compite con tu grupo en cada una."
          : "Compite en grupos privados con amigos y familia — además del ranking general de Quantia."}
      </p>

      {loading ? (
        <div className="lg-list">{[0, 1].map((i) => <SkeletonCard key={i} />)}</div>
      ) : leagues.length === 0 ? (
        hideCreate ? (
          <div className="qm-empty qm-fadein">
            <p>Aún no estás en ninguna liga. Pídele a tu organizador el enlace de invitación.</p>
          </div>
        ) : (
          <div className="lg-empty qm-fadein">
            <div className="art">
              <img className="blob" src="assets/blob-purple.png" alt="" />
              <div className="ring"><div><LIcon name="leagues" size={34} stroke={2} /></div></div>
            </div>
            <h2>Crea tu primera liga</h2>
            <p>Invita amigos y familia a competir contigo. Ellos no necesitan ser de Quantia.</p>
            <button className="qm-btn qm-btn-grad qm-btn-block" onClick={onCreate}>
              <Icon name="plus" size={18} stroke={2.4} />Crear liga
            </button>
          </div>
        )
      ) : (
        <div className="lg-list">
          {leagues.map((l) => <LeagueCard key={l.id} league={l} onOpen={() => onOpen(l.id)} />)}
        </div>
      )}

      {/* FAB (mobile) — solo colaborador (el invitado no crea ligas) */}
      {!hideCreate && !loading && leagues.length > 0 && (
        <>
          <button className="lg-fab" disabled={!canCreate}
            onClick={() => { canCreate ? onCreate() : (setTip(true), setTimeout(() => setTip(false), 1800)); }}>
            <Icon name="plus" size={19} stroke={2.6} />Crear liga
          </button>
          {tip && <div className="lg-limit-tip">Límite de 2 ligas creadas</div>}
        </>
      )}
    </div>
  );
}

/* =========================================================
   SCREEN 2 · Create league (bottom sheet / modal)
   ========================================================= */
function Sheet({ onClose, children, maxw }) {
  return (
    <div className="lg-sheet-backdrop" onClick={onClose}>
      <div className="lg-sheet" style={maxw ? { maxWidth: maxw } : null} onClick={(e) => e.stopPropagation()}>
        <div className="handle" />
        {children}
      </div>
    </div>
  );
}

function CreateLeagueSheet({ initialStep, onClose, onGoToLeague }) {
  const [step, setStep] = useState(initialStep || "name");
  const [name, setName] = useState("");
  const [busy, setBusy] = useState(false);
  const [code, setCode] = useState("");
  const [newId, setNewId] = useState(null);
  const MAX = 40;

  const create = async () => {
    if (!name.trim() || busy) return;
    setBusy(true);
    const r = await window.QLeagues.actions.createLeague(name);
    setBusy(false);
    if (!r.ok) { toast(r.error || "No se pudo crear la liga"); return; }
    setCode(r.code); setNewId(r.leagueId); setStep("done"); fireConfetti();
  };

  return (
    <Sheet onClose={onClose}>
      {step === "name" && (
        <>
          <h3>Nueva liga</h3>
          <p className="sub">Dale un nombre que tus invitados reconozcan.</p>
          <div className="qm-field" style={{ marginBottom: 6 }}>
            <input className="qm-input" autoFocus maxLength={MAX} value={name}
              placeholder="Ej: Familia García ⚽" onChange={(e) => setName(e.target.value.slice(0, MAX))}
              onKeyDown={(e) => e.key === "Enter" && create()} />
            <span className="lg-count">{name.length}/{MAX}</span>
          </div>
          <button className="qm-btn qm-btn-primary qm-btn-block" disabled={!name.trim() || busy} onClick={create} style={{ marginTop: 8 }}>
            {busy ? "Creando…" : "Crear liga"}
          </button>
          <button className="lg-textbtn" onClick={onClose}>Cancelar</button>
          <p className="lg-note" style={{ marginTop: 10 }}>Solo los colaboradores de Quantia pueden crear ligas · hasta 2 ligas activas · máx. 30 miembros.</p>
        </>
      )}

      {step === "done" && (
        <>
          <div className="lg-success"><Icon name="check" size={32} stroke={2.6} /></div>
          <h3 style={{ textAlign: "center" }}>¡Liga creada! 🎉</h3>
          <p className="sub" style={{ textAlign: "center", marginBottom: 14 }}>
            <b style={{ color: "var(--fg-1)", fontFamily: "var(--font-head)", fontSize: 16 }}>{name || "Tu liga"}</b><br />ya está lista para recibir jugadores.
          </p>
          <div className="lg-invite">
            <code>{inviteUrl(code)}</code>
            <button className="copyic" title="Copiar" onClick={() => copyLink(code)}><Icon name="copy" size={17} /></button>
          </div>
          <div className="lg-two">
            <button className="qm-btn qm-btn-ghost qm-btn-block" onClick={() => copyLink(code)}><Icon name="copy" size={16} />Copiar link</button>
            <button className="qm-btn qm-btn-primary qm-btn-block" onClick={() => shareLink({ name, code })}><LIcon name="whatsapp" size={16} />WhatsApp</button>
          </div>
          <p className="lg-note">Cualquiera con este link puede unirse — hasta 30 miembros.</p>
          <button className="lg-textbtn accent" onClick={() => onGoToLeague(newId)}>Ir a mi liga →</button>
        </>
      )}
    </Sheet>
  );
}

/* =========================================================
   SCREEN 3 · League View  (Ranking + Partidos)
   ========================================================= */
function LeagueRankingTab({ league }) {
  const Ql = window.QLeagues;
  const rows = Ql.ranked(league);
  const onlyMe = rows.length <= 1;
  const lbRef = useRef(null);
  const predsCount = usePredsCount(lbRef);

  if (onlyMe) {
    const me = rows[0];
    return (
      <div>
        <div className="qm-lb" style={{ marginTop: 14 }} ref={lbRef}>
          <LeagueRow row={me} predsCount={predsCount} />
        </div>
        <div className="lg-callout qm-fadein">
          <div className="em">🫂</div>
          <b>Invita a tus amigos para que aparezcan aquí</b>
          <p>Comparte el link de tu liga y empieza la competencia.</p>
          <button className="qm-btn qm-btn-grad" onClick={() => copyLink(league.code)}><LIcon name="link" size={17} />Copiar link de invitación</button>
        </div>
      </div>
    );
  }

  return (
    <div>
      {rows.some((r) => r.live) && (
        <div className="qm-card" style={{ display: "flex", alignItems: "center", gap: 10, padding: "12px 14px", marginBottom: 12, borderColor: "rgba(221,49,86,.35)", background: "rgba(221,49,86,.06)", fontSize: 13 }}>
          <span style={{ fontSize: 16 }}>🔴</span>
          <span><b>Hay partidos en juego.</b> Los puntos con 🔴 son provisionales y pueden cambiar al finalizar.</span>
        </div>
      )}
      <LeaguePodium rows={rows} />
      <div className="qm-lb" ref={lbRef}>
        {rows.map((r) => <LeagueRow key={r.id} row={r} predsCount={predsCount} />)}
      </div>
    </div>
  );
}

function LeaguePartidosTab() {
  const Q = useStore();
  const all = Q.db.matches.slice().sort((a, b) => a.kickoff - b.kickoff);
  // upcoming first, then recent finals — keep it lively but bounded
  const open = all.filter((m) => { const s = Q.matchStatus(m); return s === "open" || s === "live"; }).slice(0, 4);
  const finals = all.filter((m) => Q.matchStatus(m) === "final").slice(-3).reverse();
  const list = [...open, ...finals];
  const byDay = {};
  list.forEach((m) => { const k = fmtDay(m.kickoff); (byDay[k] = byDay[k] || []).push(m); });

  // MatchCard is now driven by a shared drafts context (see matches.jsx). This
  // tab lives outside MatchesScreen, so give it its own lightweight provider so
  // the inline per-match "Guardar" keeps working here. No batch SaveBar needed.
  const DraftsCtx = window.DraftsCtx;
  const [drafts, setDrafts] = useState({});
  const [flashIds, setFlashIds] = useState(() => new Set());
  const flashTimer = React.useRef(null);
  const setDraft = (id, next) => setDrafts((d) => ({ ...d, [id]: { h: next.h, a: next.a, adv: next.adv || "" } }));
  const clearDraft = (id) => setDrafts((d) => { const n = { ...d }; delete n[id]; return n; });
  const markSaved = (ids) => {
    setFlashIds(new Set(ids));
    clearTimeout(flashTimer.current);
    flashTimer.current = setTimeout(() => setFlashIds(new Set()), 1800);
  };
  useEffect(() => () => clearTimeout(flashTimer.current), []);
  const ctx = { drafts, setDraft, clearDraft, markSaved, flashIds };

  const body = (
    <div>
      <div className="lg-info-note">
        <Icon name="bolt" size={16} stroke={2.2} />
        <span>Tus pronósticos aquí son los mismos que en la liga Quantia.</span>
      </div>
      {Object.entries(byDay).map(([day, ms]) => (
        <div key={day}>
          <div className="qm-groupbar">
            <span className="glabel">{day}</span>
            <span className="gline" />
            <span className="gcount">{ms.length} partido{ms.length > 1 ? "s" : ""}</span>
          </div>
          {ms.map((m) => <MatchCard key={m.id} match={m} variant="detail" />)}
        </div>
      ))}
    </div>
  );

  return DraftsCtx ? <DraftsCtx.Provider value={ctx}>{body}</DraftsCtx.Provider> : body;
}

function LeagueView({ league, persona, onManage, initialTab }) {
  const Ql = window.QLeagues;
  const [tab, setTab] = useState(initialTab || "ranking");
  const n = Ql.memberCount(league);
  const isGuest = persona === "guest";
  const isCommish = !isGuest && league.commishId === Ql.YOU;

  return (
    <div>
      <div className="lg-lv-head">
        <div className="grow">
          <h1 className="qm-h" style={{ fontSize: 26 }}>{league.name}</h1>
          <p className="qm-sub" style={{ marginTop: 6 }}>{n} miembros · Liga de {league.commishName}</p>
          {isGuest && (
            <div style={{ marginTop: 10 }}>
              <span className="lg-powered"><img src="assets/logo-gradient.png" alt="Quantia" />Quiniela oficial del equipo Quantia</span>
            </div>
          )}
        </div>
        {isCommish && (
          <div style={{ display: "flex", gap: 8, flex: "none" }}>
            <button className="qm-btn qm-btn-ghost qm-btn-sm" onClick={() => copyLink(league.code)}><LIcon name="link" size={16} /><span style={{ display: "none" }} className="lbl-wide">Invitar</span></button>
            <button className="qm-btn qm-btn-ghost qm-btn-sm" aria-label="Gestionar liga" onClick={onManage} style={{ padding: "9px 12px" }}><LIcon name="more" size={18} /></button>
          </div>
        )}
      </div>

      {/* pill tabs — same .qm-filters look as the matches screen */}
      <div className="qm-filters lg-tabs">
        <button className={tab === "ranking" ? "on" : ""} onClick={() => setTab("ranking")}>Ranking</button>
        <button className={tab === "partidos" ? "on" : ""} onClick={() => setTab("partidos")}>Partidos</button>
      </div>

      {tab === "ranking" ? <LeagueRankingTab league={league} /> : <LeaguePartidosTab />}
    </div>
  );
}

/* =========================================================
   SCREEN 4 · Commissioner management panel
   ========================================================= */
function Confirm({ title, body, confirmLabel, onConfirm, onCancel }) {
  return (
    <div className="lg-confirm-backdrop" onClick={onCancel}>
      <div className="lg-confirm" onClick={(e) => e.stopPropagation()}>
        <b>{title}</b>
        <p>{body}</p>
        <div className="lg-two">
          <button className="qm-btn qm-btn-ghost qm-btn-block" onClick={onCancel}>Cancelar</button>
          <button className="qm-btn qm-btn-primary qm-btn-block" onClick={onConfirm}>{confirmLabel}</button>
        </div>
      </div>
    </div>
  );
}

function ManagePanel({ league, onClose, onDeleted }) {
  const Ql = window.QLeagues;
  Ql.useLeagues(); useStore();                       // live re-render on league/score changes
  const live = Ql.findLeague(league.id) || league;
  const members = Ql.ranked(live);
  const [name, setName] = useState(live.name);
  const [confirm, setConfirm] = useState(null);
  const code = live.code;

  const removeMember = (m) => setConfirm({
    kind: "remove", title: `¿Eliminar a ${m.name}?`, body: "Perderá su posición en esta liga.",
    confirmLabel: "Eliminar", run: async () => { const r = await Ql.actions.removeMember(live.id, m.id); toast(r.ok ? `${m.name} eliminado` : (r.error || "No se pudo eliminar"), ""); },
  });
  const regen = () => setConfirm({
    kind: "regen", title: "¿Regenerar el link?", body: "El link anterior dejará de funcionar de inmediato.",
    confirmLabel: "Regenerar", run: async () => { const r = await Ql.actions.regenerateCode(live.id); toast(r.ok ? "Nuevo link generado" : "No se pudo regenerar", r.ok ? "ok" : ""); },
  });
  const del = () => setConfirm({
    kind: "del", title: "¿Eliminar esta liga?", body: "Se borrará para todos sus miembros. Esta acción no se puede deshacer.",
    confirmLabel: "Eliminar liga", run: async () => { await Ql.actions.deleteLeague(live.id); toast("Liga eliminada", ""); (onDeleted || onClose)(); },
  });

  return (
    <Sheet onClose={onClose}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 10 }}>
        <h3>Gestionar liga</h3>
        <button className="qm-modal-head close" style={{ width: 30, height: 30, borderRadius: "50%", display: "grid", placeItems: "center", color: "var(--fg-3)" }} onClick={onClose}><Icon name="x" size={18} /></button>
      </div>

      {/* invite link */}
      <div className="lg-sec">
        <div className="h"><LIcon name="link" size={14} stroke={2.2} />Link de invitación</div>
        <div className="lg-invite">
          <code>{inviteUrl(code)}</code>
          <button className="copyic" title="Copiar" onClick={() => copyLink(code)}><Icon name="copy" size={17} /></button>
        </div>
        <div className="lg-two">
          <button className="qm-btn qm-btn-ghost qm-btn-block qm-btn-sm" onClick={() => copyLink(code)}><Icon name="copy" size={15} />Copiar</button>
          <button className="qm-btn qm-btn-primary qm-btn-block qm-btn-sm" onClick={() => shareLink(live)}><LIcon name="whatsapp" size={15} />WhatsApp</button>
        </div>
        <button className="lg-textbtn" onClick={regen} style={{ marginTop: 6 }}><LIcon name="refresh" size={14} stroke={2.2} /> Regenerar link</button>
        <p className="lg-warn">El link anterior dejará de funcionar.</p>
      </div>

      {/* members */}
      <div className="lg-sec">
        <div className="h"><Icon name="users" size={14} stroke={2.2} />Miembros ({members.length} / {Ql.MAX_MEMBERS})</div>
        {members.map((m) => (
          <div className="lg-mem" key={m.id}>
            <Avatar name={m.name} size={34} gold={m.commish} />
            <div className="info">
              <div className="n"><span className="txt">{m.name}</span>{m.commish && <span className="lg-commish"><LIcon name="shieldSm" size={11} stroke={2.4} />Organizador</span>}</div>
            </div>
            <div className="pts">{m.pts} pts</div>
            {!m.commish && <button className="rm" aria-label={`Eliminar a ${m.name}`} onClick={() => removeMember(m)}><LIcon name="trash" size={15} stroke={2.1} /></button>}
          </div>
        ))}
      </div>

      {/* league */}
      <div className="lg-sec">
        <div className="h"><LIcon name="leagues" size={14} stroke={2.2} />Liga</div>
        <label className="qm-mini">Renombrar liga</label>
        <div className="lg-rename-row">
          <input className="qm-input" value={name} maxLength={40} onChange={(e) => setName(e.target.value)} />
          <button className="qm-btn qm-btn-ghost qm-btn-sm" onClick={async () => { const r = await Ql.actions.renameLeague(live.id, name); toast(r.ok ? "Nombre actualizado" : "No se pudo", r.ok ? "ok" : ""); }}><Icon name="check" size={16} /></button>
        </div>
        <button className="lg-danger" onClick={del} style={{ marginTop: 14 }}><LIcon name="trash" size={15} stroke={2.1} /> Eliminar liga</button>
      </div>

      {confirm && (
        <Confirm title={confirm.title} body={confirm.body} confirmLabel={confirm.confirmLabel}
          onCancel={() => setConfirm(null)} onConfirm={() => { confirm.run(); setConfirm(null); }} />
      )}
    </Sheet>
  );
}

/* =========================================================
   SCREEN 5 · Guest join landing  (/join/CODE)
   ========================================================= */
function GuestLanding({ league, active = true, onJoin, onHaveAccount }) {
  const Ql = window.QLeagues;
  const names = active ? (league.members || []).map((m) => m.name) : [];
  const n = active ? (league.memberCount != null ? league.memberCount : Ql.memberCount(league)) : 0;

  return (
    <div className="lg-land">
      <div className="lg-hero">
        <img className="blob" src="assets/blob-white.png" alt="" />
        <div className="toprow">
          <img src="assets/logo-white.png" alt="Quantia" style={{ height: 20 }} />
        </div>
        {active ? (
          <>
            <div className="ball">⚽</div>
            <h1>{league.name}</h1>
            <div className="by">Liga de {league.commishName}</div>
            <div className="members">
              <AvStack names={names} max={3} />
              <span>{n} miembros ya participan</span>
            </div>
          </>
        ) : (
          <>
            <div className="ball">🔒</div>
            <h1>Este link ya no está disponible</h1>
            <div className="by">Pídele al organizador un nuevo link de invitación.</div>
          </>
        )}
      </div>

      {active && (
        <div className="lg-land-card qm-fadein">
          <h2>Únete y pronostica</h2>
          <div className="lg-bullets">
            {[
              "Pronostica todos los partidos del Mundial",
              "Compite en el ranking con tus amigos",
              "Gratis — solo necesitas tu email",
            ].map((t, i) => (
              <div className="lg-bullet" key={i}><span className="bk"><Icon name="check" size={15} stroke={2.6} /></span>{t}</div>
            ))}
          </div>
          <button className="qm-btn qm-btn-grad qm-btn-block" onClick={onJoin}>Unirme a la liga</button>
          <div className="lg-land-foot">
            <img src="assets/logo-gradient.png" alt="Quantia" />Quiniela oficial del equipo Quantia
          </div>
        </div>
      )}
    </div>
  );
}

/* =========================================================
   SCREEN 6 · Guest access — email-first "join" (mirrors the login)
   Single CTA "Unirme a la liga": enter email →
     • existing account → ask password → join (league already active)
     • new email        → send verification link → create profile → join
   ========================================================= */

// demo: who already has a Polla Quantia account (collaborators + a couple guests)
const KNOWN_ACCOUNTS = ["carla.rios@quantia.pe", "diego.salas@quantia.pe", "rosa.salas@gmail.com"];
function accountExists(email) {
  email = (email || "").trim().toLowerCase();
  // Quantia collaborators (corporate domains) always have an account
  return /@(ep\.net\.pe|quantia\.(pe|com\.pe))$/.test(email) || KNOWN_ACCOUNTS.includes(email);
}

function GuestHero({ league, onBack, subtitle }) {
  const names = (league.members || []).map((m) => m.name);
  return (
    <div className="qm-reg-hero">
      <img className="iso2" src="assets/blob-white.png" alt="" />
      <div style={{ maxWidth: 440, margin: "0 auto", position: "relative", zIndex: 2 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 16 }}>
          <button className="lg-back" onClick={onBack} aria-label="Volver"><LIcon name="back" size={18} stroke={2.4} /></button>
          <img src="assets/logo-white.png" alt="Quantia" style={{ height: 18 }} />
        </div>
        <div className="q-display" style={{ fontSize: 30, fontWeight: 900, letterSpacing: "-.02em", color: "#fff", lineHeight: 1.1 }}>{league.name}</div>
        <div style={{ color: "rgba(255,255,255,.78)", fontSize: 14, fontWeight: 600, marginTop: 6 }}>{subtitle || ("Te unes a la liga de " + league.commishName)}</div>
        <div style={{ marginTop: 14 }}><AvStack names={names} max={4} /></div>
      </div>
    </div>
  );
}

function GuestJoin({ league, initialStep, initialEmail, onBack, onDone }) {
  const [step, setStep] = useState(initialStep || "email");
  const [email, setEmail] = useState(initialEmail || "");
  const [pw, setPw] = useState("");
  const [name, setName] = useState("");
  const [mkt, setMkt] = useState(false);
  const [err, setErr] = useState({});
  const [busy, setBusy] = useState(false);
  const [cooldown, setCooldown] = useState(initialStep === "linksent" ? 58 : 0);

  useEffect(() => {
    if (step !== "linksent" || cooldown <= 0) return;
    const t = setTimeout(() => setCooldown((c) => Math.max(0, c - 1)), 1000);
    return () => clearTimeout(t);
  }, [step, cooldown]);

  const Q = window.QStore, Ql = window.QLeagues;

  // returning from the email-verification link → resume at the profile step
  useEffect(() => {
    const ve = Q.verifiedEmail;
    if (ve) { setEmail(ve); setStep("details"); }
    // eslint-disable-next-line
  }, []);

  const join = async () => {
    setBusy(true);
    const r = await Ql.actions.joinLeague(league.id);
    setBusy(false);
    if (!r.ok) { setErr({ join: r.error || "No se pudo unir" }); toast(r.error || "No se pudo unir", ""); return; }
    fireConfetti(); toast(`Te uniste a la liga ${league.name} 🎉`, "gold"); onDone();
  };

  const continueEmail = async () => {
    const e = email.trim().toLowerCase();
    if (!/\S+@\S+\.\S+/.test(e)) { setErr({ email: "Ingresa un email válido" }); return; }
    setErr({});
    if (Q.actions.userExists(e)) { setStep("password"); return; }       // has account → password
    if (Q.isVerified(e)) { setStep("details"); return; }                // already confirmed on this device
    setBusy(true);
    const s = await Q.actions.sendVerificationLink(e, true);            // allowAny: invite authorizes, not the whitelist
    setBusy(false);
    if (!s.ok) { setErr({ email: s.error }); return; }
    setStep("linksent"); setCooldown(58);
  };
  const signIn = async () => {
    if (!pw) { setErr({ pw: "Ingresa tu contraseña" }); return; }
    setBusy(true); const r = await Q.actions.verifyPassword(email.trim().toLowerCase(), pw); setBusy(false);
    if (!r.ok) { setErr({ pw: r.error || "Contraseña incorrecta" }); return; }
    setErr({}); join();
  };
  const createProfile = async () => {
    if (!name.trim()) { setErr({ name: "Ingresa tu nombre" }); return; }
    if (pw.length < 4) { setErr({ pw: "Mínimo 4 caracteres" }); return; }
    setBusy(true); const r = await Q.actions.registerInvitee({ name, email: email.trim().toLowerCase(), password: pw }); setBusy(false);
    if (!r.ok) { setErr({ name: r.error }); return; }
    setErr({}); join();
  };
  const resend = async () => {
    const s = await Q.actions.sendVerificationLink(email.trim().toLowerCase(), true);
    if (s.ok) { setCooldown(58); toast("Enlace reenviado", "ok"); } else setErr({ email: s.error });
  };
  const useAnother = () => { setErr({}); setPw(""); setStep("email"); };

  return (
    <div className="qm-reg-wrap">
      <GuestHero league={league} onBack={onBack} />
      <div className="qm-reg-card-wrap">
        <div className="qm-reg-card qm-fadein">

          {step === "email" && (<>
            <div className="lg-rh">Únete a la liga</div>
            <p className="lg-rp">Ingresa tu correo para unirte a <b>{league.name}</b>. Si ya tienes cuenta, te pediremos tu contraseña.</p>
            <div className="qm-field">
              <label>Correo</label>
              <input className={"qm-input " + (err.email ? "err" : "")} type="email" autoFocus value={email}
                placeholder="tu@email.com" onChange={(e) => setEmail(e.target.value)} onKeyDown={(e) => e.key === "Enter" && continueEmail()} />
              {err.email && <span className="lg-ferr">{err.email}</span>}
            </div>
            <button className="qm-btn qm-btn-grad qm-btn-block" disabled={busy} onClick={continueEmail}>
              {busy ? "Verificando…" : <>Unirme a la liga <Icon name="chevR" size={18} /></>}
            </button>
            <p className="lg-note" style={{ marginTop: 12 }}>Colaboradores de Quantia y miembros de otras ligas: usen su mismo correo.</p>
          </>)}

          {step === "password" && (<>
            <div className="lg-rh">Tu contraseña</div>
            <p className="lg-rp">Ya tienes cuenta en Polla Quantia. Ingresa tu contraseña para unirte a <b>{league.name}</b>.</p>
            <div className="qm-field">
              <label>Correo</label>
              <input className="qm-input" value={email} readOnly />
              <span className="qm-readonly-hint"><Icon name="check" size={13} stroke={2.6} />Cuenta encontrada</span>
            </div>
            <div className="qm-field">
              <label>Contraseña</label>
              <input className={"qm-input " + (err.pw ? "err" : "")} type="password" autoFocus value={pw}
                placeholder="••••••••" onChange={(e) => setPw(e.target.value)} onKeyDown={(e) => e.key === "Enter" && signIn()} />
              {err.pw && <span className="lg-ferr">{err.pw}</span>}
            </div>
            <button className="qm-btn qm-btn-grad qm-btn-block" onClick={signIn}>Unirme a la liga <Icon name="chevR" size={18} /></button>
            <button className="lg-textbtn" onClick={useAnother}>Usar otro correo</button>
          </>)}

          {step === "linksent" && (<>
            <div className="lg-success"><Icon name="mail" size={30} stroke={2.2} /></div>
            <div className="lg-rh" style={{ textAlign: "center" }}>Verifica tu correo</div>
            <p className="lg-rp" style={{ textAlign: "center" }}>Te enviamos un enlace a <b>{email}</b>. Ábrelo desde tu correo para confirmar tu cuenta y entrar a <b>{league.name}</b>.</p>
            <div style={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 8, color: "var(--fg-3)", fontSize: 13, margin: "2px 0 16px" }}>
              <Icon name="mail" size={16} /> Revisa tu bandeja de entrada (y la carpeta de spam).
            </div>
            <button className="qm-btn qm-btn-ghost qm-btn-block" disabled={cooldown > 0} onClick={resend}>
              {cooldown > 0 ? ("Reenviar enlace en " + cooldown + "s") : "Reenviar enlace"}
            </button>
            <button className="lg-textbtn" onClick={useAnother}>Usar otro correo</button>
          </>)}

          {step === "details" && (<>
            <div className="lg-rh">Crea tu cuenta</div>
            <p className="lg-rp">Correo confirmado. Crea tu nombre y contraseña para entrar a <b>{league.name}</b>.</p>
            <div className="qm-field">
              <label>Correo</label>
              <input className="qm-input" value={email} readOnly />
              <span className="qm-readonly-hint"><Icon name="check" size={13} stroke={2.6} />Correo confirmado</span>
            </div>
            <div className="qm-field">
              <label>Nombre completo</label>
              <input className={"qm-input " + (err.name ? "err" : "")} autoFocus value={name}
                placeholder="Ej. Lucía García" onChange={(e) => setName(e.target.value)} />
              {err.name && <span className="lg-ferr">{err.name}</span>}
            </div>
            <div className="qm-field">
              <label>Contraseña</label>
              <input className={"qm-input " + (err.pw ? "err" : "")} type="password" value={pw}
                placeholder="Mín. 4 caracteres" onChange={(e) => setPw(e.target.value)} onKeyDown={(e) => e.key === "Enter" && createProfile()} />
              {err.pw && <span className="lg-ferr">{err.pw}</span>}
            </div>
            <label className="lg-check" style={{ marginBottom: 16 }}>
              <input type="checkbox" checked={mkt} onChange={(e) => setMkt(e.target.checked)} />
              <span className="box">{mkt && <Icon name="check" size={14} stroke={3} />}</span>
              <span className="lbl">Acepto recibir comunicaciones de Quantia.</span>
            </label>
            <button className="qm-btn qm-btn-grad qm-btn-block" onClick={createProfile}>Entrar a la liga <Icon name="chevR" size={18} /></button>
          </>)}

          <div className="lg-land-foot" style={{ marginTop: 16 }}>
            <img src="assets/logo-gradient.png" alt="Quantia" />Quiniela oficial del equipo Quantia
          </div>
        </div>
      </div>
    </div>
  );
}

/* =========================================================
   Orchestrator · public invite (/join/CODE): landing → join → done
   ========================================================= */
function GuestFlow({ code, onJoined }) {
  const Q = window.QStore, Ql = window.QLeagues;
  const [invite, setInvite] = useState(undefined);   // undefined=loading · null=not found
  const [step, setStep] = useState(Q.verifiedEmail ? "join" : "landing");
  useEffect(() => { let on = true; Ql.getInvite(code).then((v) => { if (on) setInvite(v); }); return () => (on = false); }, [code]);

  if (invite === undefined) return <div className="lg-land"><div className="lg-hero" style={{ minHeight: 220 }} /></div>;
  if (!invite) return <GuestLanding league={{ name: "", code, members: [] }} active={false} />;

  const active = invite.active !== false && (invite.memberCount || 0) < Ql.MAX_MEMBERS;
  const league = {
    id: invite.leagueId, name: invite.name, code, commishName: invite.commissionerName,
    members: (invite.memberNames || []).map((n) => ({ name: n })), memberCount: invite.memberCount,
  };
  if (step === "landing") return <GuestLanding league={league} active={active} onJoin={() => setStep("join")} />;
  return <GuestJoin league={league} onBack={() => setStep("landing")} onDone={() => onJoined(invite.leagueId)} />;
}

Object.assign(window, {
  LIcon, useIsDesktop, MiniAvatar, AvStack, inviteUrl, copyLink, shareLink,
  LeagueRow, LeaguePodium, LeagueCard, SkeletonCard, MisLigasScreen,
  Sheet, CreateLeagueSheet, LeagueRankingTab, LeaguePartidosTab, LeagueView,
  Confirm, ManagePanel, GuestLanding, GuestHero, GuestJoin, GuestFlow,
});
