/* LIBRANCY — Parent Dashboard v2 (premium brand redesign)
 * Navy brand header with the real logo · rank-coloured child identity ·
 * certificate showcase (the aspiration artifact) · gradient Beacons economy ·
 * styled leaderboards · the Celebrate loop. Same API, same routes.
 */
const { useState, useEffect, useCallback } = React;
const API = "";

const T = {
  navy:"#101450", navy2:"#1B2270", navy3:"#26307E", coral:"#FF6B6B", teal:"#02B5AA",
  tealDeep:"#00715E", tealTint:"#E6F7F3", yellow:"#FEC323", yellowTint:"#FFF6DC",
  gold:"#B8860B", purple:"#6C5CE7", purpleDeep:"#4C3FD1", purpleTint:"#EEEBFD",
  pink:"#FF6B9D", pinkTint:"#FFEDF3", blue:"#1C6BF6", blueTint:"#E8F0FF",
  ink:"#1B2733", slate:"#5C6B7A", mist:"#8597A6", line:"#E4EAF0", paper:"#FFFFFF", cloud:"#F5F8FB",
};
const FONT = `"Poppins","Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif`;
const NGN = (k) => "₦" + Math.round(k/100).toLocaleString("en-NG");
const REGIONS = ["Lagos","Abuja (FCT)","Rivers","Oyo","Kano","Enugu","Anambra","Delta","Kaduna",
  "Other Nigeria","Diaspora — UK","Diaspora — US/Canada","Diaspora — Other"];
const RANKS = {
  Explorer:{ icon:"✦" },
  Builder:{ icon:"🚀" },
  Creator:{ icon:"★" },
  Founder:{ icon:"👑" },
};
const AVATARS = ["🦁","🐘","🦋","🚀","🌟","🎨"];

const store = {
  get:(k)=>{ try{ return JSON.parse(localStorage.getItem("lbrp_"+k)); }catch{ return null; } },
  set:(k,v)=>localStorage.setItem("lbrp_"+k, JSON.stringify(v)),
  del:(k)=>localStorage.removeItem("lbrp_"+k),
};
async function api(path, opts={}) {
  const token = store.get("token");
  const res = await fetch(API+"/api"+path, {
    method: opts.method||"GET",
    headers:{ "Content-Type":"application/json", ...(token?{Authorization:"Bearer "+token}:{}) },
    body: opts.body ? JSON.stringify(opts.body) : undefined,
  });
  const j = await res.json().catch(()=>({}));
  if (!res.ok) throw new Error(j.error||"Something went wrong");
  return j;
}

const btnS=(bg,extra={})=>({ border:"none", borderRadius:14, padding:"14px 18px", width:"100%",
  cursor:"pointer", background:bg, color:"#fff", fontSize:15, fontWeight:600, fontFamily:FONT, ...extra });
const chip=(bg,c)=>({ display:"inline-flex", alignItems:"center", gap:5, background:bg, color:c,
  fontSize:11.5, fontWeight:700, padding:"4px 11px", borderRadius:20 });
const inputS={ width:"100%", padding:"14px 15px", borderRadius:13, border:`2px solid ${T.line}`,
  fontSize:15.5, fontFamily:FONT, boxSizing:"border-box", background:"#fff" };
function Card({children,style}){ return <div style={{ background:T.paper, border:`1px solid ${T.line}`,
  borderRadius:20, padding:18, boxShadow:"0 2px 12px rgba(0,31,63,.04)", ...style }}>{children}</div>; }

/* ── Auth ── */
function Login({ onDone }) {
  const params = new URLSearchParams(location.search);
  const resetToken = params.get("reset");
  const [mode,setMode] = useState(resetToken ? "reset" : "login");
  const [email,setEmail]=useState(""); const [pw,setPw]=useState("");
  const [msg,setMsg]=useState(""); const [busy,setBusy]=useState(false);

  const run = async () => {
    setBusy(true); setMsg("");
    try {
      if (mode==="login") {
        const r = await api("/auth/login",{method:"POST",body:{email,password:pw}});
        store.set("token", r.token); onDone();
      } else if (mode==="forgot") {
        await api("/auth/forgot",{method:"POST",body:{email}});
        setMsg("If that email has an account, a reset link is on its way. Check your inbox (and spam).");
      } else {
        const r = await api("/auth/reset",{method:"POST",body:{token:resetToken,password:pw}});
        store.set("token", r.token); history.replaceState(null,"","/parent/"); onDone();
      }
    } catch(e){ setMsg(e.message); } finally { setBusy(false); }
  };

  return (
    <div>
      <div style={{ background:`linear-gradient(140deg, ${T.navy} 0%, ${T.navy2} 60%, ${T.navy3} 100%)`,
        padding:"46px 24px 40px", textAlign:"center" }}>
        <img src="/assets/cert/logo-white.png" alt="Librancy AI" style={{ height:38 }} />
        <div style={{ color:"#BFD3E6", fontSize:13.5, marginTop:14, letterSpacing:.3 }}>
          The Future is Built by Curious Minds
        </div>
      </div>
      <div style={{ padding:"30px 24px", textAlign:"center" }}>
        <h1 style={{ fontSize:22, color:T.navy, margin:"0 0 6px" }}>
          {mode==="login"?"Parent dashboard":mode==="forgot"?"Reset your password":"Choose a new password"}
        </h1>
        <p style={{ fontSize:13.5, color:T.slate, margin:"0 0 22px", lineHeight:1.55 }}>
          {mode==="login"?"See your child’s progress, celebrate their wins, and grow your Beacons."
           :mode==="forgot"?"Enter your account email and we’ll send a reset link."
           :"Enter a new password for your account."}
        </p>
        {mode!=="reset" && <input value={email} onChange={e=>setEmail(e.target.value)} type="email"
          placeholder="Parent email" style={{...inputS, marginBottom:12}} />}
        {mode!=="forgot" && <input value={pw} onChange={e=>setPw(e.target.value)} type="password"
          placeholder={mode==="reset"?"New password (8+ characters)":"Password"}
          onKeyDown={e=>e.key==="Enter"&&run()} style={{...inputS, marginBottom:12}} />}
        {msg && <div style={{ fontSize:13, color:msg.includes("way")?T.tealDeep:"#C0392B", marginBottom:10 }}>{msg}</div>}
        <button style={{...btnS(T.coral), boxShadow:"0 8px 20px rgba(255,107,107,.3)"}} disabled={busy} onClick={run}>
          {busy?"Working…":mode==="login"?"Sign in":mode==="forgot"?"Send reset link":"Set new password"}
        </button>
        {mode==="login" && <button onClick={()=>{setMode("forgot");setMsg("");}}
          style={{...btnS("transparent",{color:T.teal, fontSize:13.5, marginTop:8})}}>Forgot password?</button>}
        {mode==="forgot" && <button onClick={()=>{setMode("login");setMsg("");}}
          style={{...btnS("transparent",{color:T.slate, fontSize:13.5, marginTop:8})}}>Back to sign in</button>}
      </div>
    </div>
  );
}

/* ── Child card ── */
function ChildCard({ c, i, onCelebrate, onOpen, refLink }) {
  const [sent,setSent]=useState(false); const [msg,setMsg]=useState("");
  const R = RANKS[c.rank] || RANKS.Explorer;
  const shareAchievement = async (child) => {
    // Use the parent's REAL affiliate link (loaded by Dash). Falls back to the
    // plain site if it hasn't loaded yet — never shares a broken empty ?ref=.
    const url = refLink || "https://librancy.com";
    const text = `${child.firstName} just scored an A on Librancy AI! 🚀 My child is learning to build with AI — yours can too. Join with my link: ${url}`;
    try {
      if (navigator.share) { await navigator.share({ title: "Librancy AI", text, url }); return; }
    } catch (e) { /* fell through to WhatsApp */ }
    window.open("https://wa.me/?text=" + encodeURIComponent(text), "_blank");
  };

  const celebrate = async () => {
    await onCelebrate(c.id, msg || undefined); setSent(true); setMsg("");
    setTimeout(()=>setSent(false), 3500);
  };
  const earned = c.courses.filter(co=>co.percent>=100).length;
  return (
    <Card style={{ marginBottom:14, padding:0, overflow:"hidden" }}>
      {/* identity band */}
      <div style={{ background:`linear-gradient(135deg, ${T.navy}, ${T.navy2})`, padding:"16px 18px",
        display:"flex", alignItems:"center", gap:13 }}>
        <div style={{ width:52, height:52, borderRadius:"50%", background:"rgba(255,255,255,.12)",
          border:`2.5px solid ${T.yellow}`, display:"grid", placeItems:"center", fontSize:27, flexShrink:0 }}>
          {c.avatar || AVATARS[i % AVATARS.length]}
        </div>
        <div style={{ flex:1, minWidth:0 }}>
          <div style={{ fontWeight:700, color:"#fff", fontSize:17.5 }}>{c.firstName}</div>
          <div style={{ display:"flex", gap:6, marginTop:5, flexWrap:"wrap" }}>
            <span style={chip("rgba(255,255,255,.14)", "#FFD98A")}>{R.icon} {c.rank}</span>
            <span style={chip("rgba(255,255,255,.14)", "#9FE8D6")}>⚡ {c.sparks.toLocaleString()}</span>
            <span style={chip("rgba(255,255,255,.14)", "#FFB3B3")}>🔥 {c.streak}-day</span>
          </div>
        </div>
      </div>

      <div style={{ padding:"16px 18px" }}>
        {/* stat tiles */}
        <div style={{ display:"grid", gridTemplateColumns:"1fr 1fr 1fr", gap:9 }}>
          {[["✅", c.lessonsThisWeek, "lessons this week", T.tealTint, T.tealDeep],
            ["🅰️", c.aGrades, "A-grades", T.yellowTint, T.gold],
            ["🎨", c.creations, "creations", T.pinkTint, "#C2185B"]].map(([ic,v,k,bg,cc])=>(
            <div key={k} style={{ background:bg, borderRadius:14, padding:"12px 8px", textAlign:"center" }}>
              <div style={{ fontSize:15 }}>{ic}</div>
              <div style={{ fontSize:19, fontWeight:800, color:cc, marginTop:2 }}>{v}</div>
              <div style={{ fontSize:10, color:T.slate, fontWeight:600, marginTop:1 }}>{k}</div>
            </div>
          ))}
        </div>

        {c.latestCreation && (
          <div style={{ background:T.cloud, borderLeft:`3px solid ${T.pink}`, borderRadius:"0 12px 12px 0",
            padding:"11px 13px", margin:"13px 0 0" }}>
            <div style={{ fontSize:10.5, fontWeight:700, color:T.mist, letterSpacing:.5 }}>
              LATEST CREATION · {c.latestCreation.lesson.toUpperCase()}
            </div>
            <div style={{ fontSize:13.5, color:T.ink, marginTop:3, fontStyle:"italic" }}>“{c.latestCreation.text}”</div>
          </div>
        )}

        {/* course → certificate progress */}
        <div style={{ marginTop:15 }}>
          {c.courses.map(co=>{
            const full = co.percent>=100;
            return (
              <div key={co.title} style={{ marginBottom:10, padding:full?"9px 12px":"0",
                background:full?T.yellowTint:"transparent", borderRadius:12,
                border:full?`1px solid #F2DFA4`:"none" }}>
                <div style={{ display:"flex", justifyContent:"space-between", fontSize:12.5, alignItems:"center" }}>
                  <span style={{ color:T.ink, fontWeight:600 }}>{co.title}</span>
                  <span style={{ color:full?T.gold:T.tealDeep, fontWeight:700 }}>
                    {full ? "🏆 Certificate earned" : co.percent+"% to certificate"}
                  </span>
                </div>
                {!full && (
                  <div style={{ height:6, borderRadius:4, background:T.line, marginTop:5 }}>
                    <div style={{ height:"100%", width:`${co.percent}%`, borderRadius:4,
                      background:`linear-gradient(90deg, ${T.teal}, ${T.yellow})` }} />
                  </div>
                )}
              </div>
            );
          })}
        </div>

        {earned>0 && (
          <div style={{ display:"flex", alignItems:"center", gap:12, marginTop:4, marginBottom:2 }}>
            <img src="/parent/assets/certificate.jpg" alt="Librancy certificate"
              style={{ width:104, borderRadius:10, boxShadow:"0 4px 14px rgba(0,31,63,.18)" }} />
            <div>
              <div style={{ fontWeight:700, color:T.navy, fontSize:13.5 }}>
                {c.firstName} has earned {earned} certificate{earned>1?"s":""} 🎉
              </div>
              <div style={{ fontSize:11.5, color:T.slate, marginTop:2, lineHeight:1.5 }}>
                A frame-worthy award — share the pride from {c.firstName}’s A-card in the learning space.
              </div>
            </div>
          </div>
        )}

        {/* Parent shares the child's achievement — carries the parent's referral link. */}
        {c.aGrades > 0 && (
          <button onClick={()=>shareAchievement(c)} style={{ ...btnS("#25D366",{ marginTop:12, padding:"12px", fontSize:13.5 }) }}>
            📣 Share {c.firstName}'s A — and earn when a friend joins
          </button>
        )}

        {/* celebrate */}
        <div style={{ display:"flex", gap:8, marginTop:14 }}>
          <input value={msg} onChange={e=>setMsg(e.target.value)} maxLength={140}
            placeholder={`Say something to ${c.firstName}…`}
            style={{...inputS, padding:"12px 13px", fontSize:13.5, background:T.cloud, border:`1.5px solid ${T.line}`}} />
          <button onClick={celebrate} style={btnS(sent?T.tealDeep:T.coral,{ width:"auto", whiteSpace:"nowrap",
            padding:"12px 16px", fontSize:13.5, boxShadow:sent?"none":"0 6px 16px rgba(255,107,107,.3)" })}>
            {sent?"Sent 💛":"🎉 Celebrate"}
          </button>
        </div>
        <div style={{ fontSize:11, color:T.mist, marginTop:6 }}>They’ll see it next time they open Librancy.</div>

        <button onClick={onOpen} style={{ ...btnS("transparent",{ marginTop:12, padding:"12px",
          color:T.navy, border:`1.5px solid ${T.line}`, fontSize:13.5 }) }}>
          View full progress &amp; PIN →</button>
      </div>
    </Card>
  );
}

/* ── Leaderboards ── */
function Boards() {
  const [scope,setScope]=useState("family"); const [period,setPeriod]=useState("month");
  const [data,setData]=useState(null);
  useEffect(()=>{ setData(null);
    api(`/leaderboard?scope=${scope}&period=${period}`).then(setData).catch(()=>setData({rows:[]}));
  },[scope,period]);
  return (
    <Card style={{ marginTop:14 }}>
      <div style={{ display:"flex", justifyContent:"space-between", alignItems:"center", marginBottom:12, flexWrap:"wrap", gap:8 }}>
        <span style={{ fontWeight:700, color:T.navy, fontSize:15 }}>🏆 Leaderboards</span>
        <div style={{ display:"flex", gap:6, flexWrap:"wrap" }}>
          {[["family","Families"],["region","Regions"]].map(([k,l])=>(
            <button key={k} onClick={()=>setScope(k)} style={{...chip(scope===k?T.navy:T.cloud, scope===k?"#fff":T.slate),
              border:"none", cursor:"pointer", fontFamily:FONT}}>{l}</button>
          ))}
          {[["month","Monthly race"],["all","All-time"]].map(([k,l])=>(
            <button key={k} onClick={()=>setPeriod(k)} style={{...chip(period===k?T.teal:T.cloud, period===k?"#fff":T.slate),
              border:"none", cursor:"pointer", fontFamily:FONT}}>{l}</button>
          ))}
        </div>
      </div>
      {!data ? <div style={{ color:T.mist, fontSize:13, padding:"10px 0" }}>Loading…</div> :
        data.rows.length===0 ? <div style={{ color:T.mist, fontSize:13 }}>No activity yet this period — be the first family on the board!</div> :
        data.rows.map((r,i)=>(
          <div key={i} style={{ display:"flex", alignItems:"center", gap:10, padding:"9px 10px",
            background:r.me?T.tealTint:"transparent", borderRadius:12, border:r.me?`1px solid #BFE7DD`:"none",
            marginBottom:2 }}>
            <span style={{ width:26, fontWeight:800, fontSize:14,
              color:r.rank===1?T.gold:r.rank===2?"#8C9BAB":r.rank===3?"#B87333":T.mist }}>
              {r.rank===1?"🥇":r.rank===2?"🥈":r.rank===3?"🥉":(r.rank??"—")}
            </span>
            <span style={{ flex:1, fontSize:13.5, fontWeight:r.me?700:600, color:T.ink }}>{r.name}{r.me?" · you":""}</span>
            <span style={{ fontSize:12.5, fontWeight:700, color:T.slate }}>{Number(r.pts).toLocaleString()} ⚡</span>
          </div>
        ))}
    </Card>
  );
}

/* ── Read-only deep view of one child + Reset PIN (parent-facing) ── */
function ChildDetail({ childId, onBack }) {
  const [d,setD] = useState(null); const [err,setErr] = useState("");
  const [pinOpen,setPinOpen] = useState(false);
  const [pin,setPin] = useState(""); const [pin2,setPin2] = useState("");
  const [pinMsg,setPinMsg] = useState(""); const [busy,setBusy] = useState(false);
  const [copied,setCopied] = useState(false);
  const [loginCode,setLoginCode] = useState(null);
  useEffect(()=>{ api(`/parent/child/${childId}/code`).then(r=>setLoginCode(r.loginCode)).catch(()=>{}); },[childId]);
  const load = useCallback(()=>api(`/parent/child/${childId}`).then(setD).catch(e=>setErr(e.message)),[childId]);
  useEffect(()=>{ load(); },[load]);

  const savePin = async () => {
    setPinMsg("");
    if (!/^\d{4}$/.test(pin)) { setPinMsg("PIN must be exactly 4 digits."); return; }
    if (pin !== pin2) { setPinMsg("The two PINs don't match."); return; }
    setBusy(true);
    try {
      await api(`/parent/child/${childId}/pin`, { method:"POST", body:{ pin } });
      setPinMsg("✓ New PIN saved. Your child can sign in with it now.");
      setPin(""); setPin2(""); setTimeout(()=>{ setPinOpen(false); setPinMsg(""); load(); }, 1400);
    } catch(e){ setPinMsg(e.message); } finally { setBusy(false); }
  };

  if (err) return <div style={{ padding:24 }}>
    <button onClick={onBack} style={{ ...btnS("transparent",{ color:T.slate, width:"auto", padding:0, marginBottom:12 }) }}>← Back</button>
    <Card>{err}</Card></div>;
  if (!d) return <div style={{ textAlign:"center", padding:"70px 0", color:T.mist }}>Loading…</div>;

  const c = d.child; const R = RANKS[c.rank] || RANKS.Explorer;
  return (
    <div>
      {/* header */}
      <div style={{ background:`linear-gradient(135deg, ${T.navy}, ${T.navy2})`, padding:"18px 20px 22px" }}>
        <button onClick={onBack} style={{ background:"none", border:"none", color:"#9FB3C8", fontSize:13.5,
          cursor:"pointer", fontFamily:FONT, padding:0 }}>← All children</button>
        <div style={{ display:"flex", alignItems:"center", gap:13, marginTop:14 }}>
          <div style={{ width:56, height:56, borderRadius:"50%", background:"rgba(255,255,255,.12)",
            border:`2.5px solid ${T.yellow}`, display:"grid", placeItems:"center", fontSize:29 }}>
            {c.avatar || "🌟"}</div>
          <div>
            <div style={{ fontWeight:700, color:"#fff", fontSize:20 }}>{c.firstName}</div>
            <div style={{ display:"flex", gap:6, marginTop:5, flexWrap:"wrap" }}>
              <span style={chip("rgba(255,255,255,.14)","#FFD98A")}>{R.icon} {c.rank}</span>
              <span style={chip("rgba(255,255,255,.14)","#9FE8D6")}>⚡ {c.sparks.toLocaleString()}</span>
              <span style={chip("rgba(255,255,255,.14)","#FFB3B3")}>🔥 {c.streak}-day</span>
            </div>
          </div>
        </div>
      </div>

      <div style={{ padding:"18px 20px 44px" }}>
        {/* Reset PIN card */}
        <Card style={{ marginBottom:14 }}>
          <div style={{ display:"flex", justifyContent:"space-between", alignItems:"center" }}>
            <div>
              <div style={{ fontWeight:700, color:T.navy, fontSize:14.5 }}>🔐 Login PIN</div>
              <div style={{ fontSize:12.5, color:T.slate, marginTop:3 }}>
                {c.hasPin ? "A PIN is set. Forgot it? Set a new one — the old one can't be shown for safety."
                          : "No PIN set yet. Create one so only your child opens their space."}</div>
            </div>
            {!pinOpen && <button onClick={()=>setPinOpen(true)}
              style={{ ...btnS(T.navy,{ width:"auto", padding:"10px 14px", fontSize:13 }) }}>
              {c.hasPin ? "Reset PIN" : "Set PIN"}</button>}
          </div>
          {pinOpen && (
            <div style={{ marginTop:12 }}>
              <input value={pin} onChange={e=>setPin(e.target.value.replace(/\D/g,"").slice(0,4))}
                placeholder="New 4-digit PIN" inputMode="numeric" type="password"
                style={{ ...inputS, marginBottom:8, letterSpacing:6, textAlign:"center" }} />
              <input value={pin2} onChange={e=>setPin2(e.target.value.replace(/\D/g,"").slice(0,4))}
                placeholder="Confirm PIN" inputMode="numeric" type="password"
                style={{ ...inputS, letterSpacing:6, textAlign:"center" }} />
              {pinMsg && <div style={{ fontSize:12.5, marginTop:8,
                color: pinMsg[0]==="✓"?T.tealDeep:T.coral }}>{pinMsg}</div>}
              <div style={{ display:"flex", gap:8, marginTop:10 }}>
                <button onClick={savePin} disabled={busy} style={{ ...btnS(T.teal,{ padding:"11px" }) }}>
                  {busy?"Saving…":"Save new PIN"}</button>
                <button onClick={()=>{ setPinOpen(false); setPin(""); setPin2(""); setPinMsg(""); }}
                  style={{ ...btnS("transparent",{ padding:"11px", color:T.slate, border:`1.5px solid ${T.line}` }) }}>Cancel</button>
              </div>
            </div>
          )}
        </Card>

        {/* Login code — child signs in from any device with code + PIN */}
        <Card style={{ marginBottom:14 }}>
          <div style={{ fontWeight:700, color:T.navy, fontSize:14.5 }}>🎟️ Login code</div>
          <div style={{ fontSize:12.5, color:T.slate, margin:"3px 0 10px" }}>
            {c.firstName} can sign in at <b>librancy.com/learn</b> from any device with this
            code and their PIN — no email needed. Perfect if they’re on another device or in another city.
          </div>
          {loginCode ? (
            <>
              <div style={{ fontFamily:"ui-monospace,Menlo,monospace", fontSize:24, fontWeight:800,
                letterSpacing:3, color:T.navy, background:T.yellowTint, border:`2px dashed ${T.gold}`,
                borderRadius:12, padding:"13px", textAlign:"center" }}>{loginCode}</div>
              <div style={{ display:"flex", gap:8, marginTop:10 }}>
                <button onClick={()=>{ navigator.clipboard?.writeText(loginCode);
                    setCopied(true); setTimeout(()=>setCopied(false),1500); }}
                  style={{ ...btnS(T.navy,{ padding:"11px", fontSize:13 }) }}>
                  {copied ? "✓ Copied" : "📋 Copy code"}</button>
                <button onClick={()=>{
                    const msg = `Hi! Here’s your Librancy login 🎟️\nGo to librancy.com/learn\nCode: ${loginCode}\nThen enter your PIN. Have fun learning! 🚀`;
                    window.open("https://wa.me/?text="+encodeURIComponent(msg), "_blank"); }}
                  style={{ ...btnS("#25D366",{ padding:"11px", fontSize:13 }) }}>
                  📲 Send on WhatsApp</button>
              </div>
              <div style={{ fontSize:11.5, color:T.mist, marginTop:9 }}>
                🔒 Send the code and PIN separately for safety. The code alone can’t sign in.
              </div>
            </>
          ) : (
            <div style={{ fontSize:12.5, color:T.mist }}>
              No code yet — run the code migration once and it appears here.
            </div>
          )}
        </Card>

        {/* Course-by-course lesson breakdown */}
        {d.courses.map((co,ci)=>(
          <Card key={ci} style={{ marginBottom:14 }}>
            <div style={{ display:"flex", justifyContent:"space-between", alignItems:"baseline" }}>
              <div style={{ fontWeight:700, color:T.navy, fontSize:15 }}>{co.title}</div>
              <span style={{ fontSize:12.5, color:T.tealDeep, fontWeight:700 }}>{co.done}/{co.total} · {co.percent}%</span>
            </div>
            <div style={{ height:6, borderRadius:4, background:T.line, margin:"9px 0 12px" }}>
              <div style={{ height:"100%", width:`${co.percent}%`, background:T.teal, borderRadius:4 }} /></div>
            {co.lessons.map((l,li)=>(
              <div key={li} style={{ display:"flex", alignItems:"center", gap:9, padding:"7px 0",
                borderBottom: li<co.lessons.length-1?`1px solid ${T.cloud}`:"none" }}>
                <span style={{ fontSize:15, width:20, textAlign:"center" }}>
                  {l.completed ? "✅" : l.videoDone ? "▶️" : "⬜"}</span>
                <span style={{ flex:1, fontSize:13, color: l.completed?T.ink:T.slate }}>{l.title}</span>
                {l.grade && <span style={chip(l.grade==="A"?T.tealTint:T.yellowTint, l.grade==="A"?T.tealDeep:T.gold)}>{l.grade}</span>}
              </div>
            ))}
          </Card>
        ))}

        {/* All creations, full text */}
        <Card>
          <div style={{ fontWeight:700, color:T.navy, fontSize:15, marginBottom:10 }}>
            🎨 All creations ({d.creations.length})</div>
          {d.creations.length===0
            ? <div style={{ fontSize:13, color:T.mist }}>No creations yet — they'll appear here as {c.firstName} builds.</div>
            : d.creations.map((cr,i)=>(
              <div key={i} style={{ background:T.cloud, borderLeft:`3px solid ${T.pink}`, borderRadius:"0 12px 12px 0",
                padding:"11px 13px", marginBottom:9 }}>
                <div style={{ fontSize:10.5, fontWeight:700, color:T.mist, letterSpacing:.5 }}>
                  {(cr.lesson||"").toUpperCase()}{cr.source==="ai_build"?" · ✨ AI BUILD":""}</div>
                <div style={{ fontSize:13.5, color:T.ink, marginTop:3, fontStyle:"italic", whiteSpace:"pre-wrap" }}>"{cr.text}"</div>
              </div>
            ))}
        </Card>
      </div>
    </div>
  );
}

/* ── Dashboard ── */
/* ── Partner earnings: parent's affiliate link + balance, in-dashboard ── */
function PartnerEarnings() {
  const [a,setA] = useState(null); const [err,setErr] = useState("");
  const [detail,setDetail] = useState(""); const [msg,setMsg] = useState(""); const [busy,setBusy] = useState(false);
  const load = useCallback(()=>api("/parent/affiliate").then(setA).catch(e=>setErr(e.message)),[]);
  useEffect(()=>{ load(); },[load]);

  if (err) return null;                         // fail quietly — never break the dashboard
  if (!a)  return null;                          // still loading
  const s = a.stats, cfg = a.config, link = a.affiliate.link;
  const canWithdraw = s.payableMinor >= cfg.minPayoutMinor && a.affiliate.payoutSet;

  const copy = (e)=>{ navigator.clipboard.writeText(link);
    const b=e.target, t=b.textContent; b.textContent="Copied!"; setTimeout(()=>b.textContent=t,1200); };
  const shareWA = ()=>{ const m="I found Librancy — it teaches kids to build with AI. Join with my link: "+link;
    window.open("https://wa.me/?text="+encodeURIComponent(m),"_blank"); };
  const savePayout = async ()=>{ setMsg("");
    if(detail.trim().length<6){ setMsg("Enter your bank name + account number"); return; }
    setBusy(true);
    try{ await api("/affiliate/payout-detail",{method:"POST",body:{detail}}); setMsg("✓ Payout details saved"); setDetail(""); load(); }
    catch(e){ setMsg(e.message); } finally{ setBusy(false); }
  };
  const withdraw = async ()=>{ setMsg(""); setBusy(true);
    try{ const r=await api("/affiliate/request-payout",{method:"POST"}); setMsg("✓ Payout requested: "+NGN(r.amountMinor)); load(); }
    catch(e){ setMsg(e.message); } finally{ setBusy(false); }
  };

  return (
    <div style={{ marginTop:14, borderRadius:20, padding:20, color:"#fff",
      background:`linear-gradient(140deg, ${T.tealDeep} 0%, ${T.teal} 75%, #35D0BE 100%)`,
      boxShadow:"0 10px 26px rgba(0,113,94,.26)" }}>
      <div style={{ display:"flex", justifyContent:"space-between", alignItems:"baseline" }}>
        <div style={{ fontSize:15, fontWeight:700 }}>💚 Earn cash as a partner</div>
        <span style={chip("rgba(255,255,255,.16)","#DFF7F1")}>{cfg.ratePct}% per sale</span>
      </div>
      <div style={{ fontSize:12.5, color:"#DFF7F1", lineHeight:1.6, margin:"8px 0 12px" }}>
        Share Librancy with other parents and teachers. Earn <b>{cfg.ratePct}%</b> of every course they buy —
        paid out {cfg.matureDays} days after each sale.
      </div>

      <div style={{ display:"flex", gap:12, marginBottom:12 }}>
        <div style={{ flex:1, background:"rgba(255,255,255,.14)", borderRadius:12, padding:"10px 12px" }}>
          <div style={{ fontSize:22, fontWeight:800 }}>{NGN(s.payableMinor)}</div>
          <div style={{ fontSize:10.5, color:"#DFF7F1", fontWeight:700, letterSpacing:.04 }}>READY TO WITHDRAW</div>
        </div>
        <div style={{ flex:1, background:"rgba(255,255,255,.14)", borderRadius:12, padding:"10px 12px" }}>
          <div style={{ fontSize:22, fontWeight:800 }}>{NGN(s.pendingMinor)}</div>
          <div style={{ fontSize:10.5, color:"#DFF7F1", fontWeight:700, letterSpacing:.04 }}>MATURING</div>
        </div>
        <div style={{ flex:1, background:"rgba(255,255,255,.14)", borderRadius:12, padding:"10px 12px" }}>
          <div style={{ fontSize:22, fontWeight:800 }}>{s.conversions}</div>
          <div style={{ fontSize:10.5, color:"#DFF7F1", fontWeight:700, letterSpacing:.04 }}>SALES</div>
        </div>
      </div>

      <div style={{ display:"flex", gap:8 }}>
        <input readOnly value={link} style={{ flex:1, padding:"11px 12px", borderRadius:10, border:"none",
          fontSize:12.5, background:"rgba(255,255,255,.92)", color:T.navy, fontFamily:FONT }} />
        <button onClick={copy} style={{ ...btnS("#fff",{ color:T.tealDeep, width:"auto", padding:"11px 14px", fontSize:13 }) }}>Copy</button>
      </div>
      <button onClick={shareWA} style={{ ...btnS("rgba(255,255,255,.16)",{ color:"#fff", marginTop:8, padding:"11px", fontSize:13.5,
        border:"1.5px solid rgba(255,255,255,.35)" }) }}>📲 Share on WhatsApp</button>

      {!a.affiliate.payoutSet && (
        <div style={{ marginTop:12 }}>
          <input value={detail} onChange={e=>setDetail(e.target.value)}
            placeholder="Bank name + account number (to get paid)"
            style={{ width:"100%", boxSizing:"border-box", padding:"11px 12px", borderRadius:10, border:"none",
              fontSize:13, fontFamily:FONT }} />
          <button onClick={savePayout} disabled={busy} style={{ ...btnS("#fff",{ color:T.tealDeep, marginTop:8, padding:"11px", fontSize:13.5 }) }}>
            Save payout details</button>
        </div>
      )}
      {a.affiliate.payoutSet && (
        <button onClick={withdraw} disabled={!canWithdraw||busy}
          style={{ ...btnS("#fff",{ color:T.tealDeep, marginTop:10, padding:"12px", fontSize:14,
            opacity:(canWithdraw&&!busy)?1:.55 }) }}>
          {s.payableMinor >= cfg.minPayoutMinor ? "Request payout" : "Min "+NGN(cfg.minPayoutMinor)+" to withdraw"}
        </button>
      )}
      {msg && <div style={{ fontSize:12.5, marginTop:8, color:"#EAFBF6", fontWeight:600 }}>{msg}</div>}
    </div>
  );
}

function Dash({ onLogout }) {
  const [d,setD]=useState(null); const [err,setErr]=useState("");
  const [showAccount,setShowAccount]=useState(false);
  const [openChildId,setOpenChildId]=useState(null);
  const [refLink,setRefLink]=useState("");        // parent's real affiliate link (single source of truth)
  const load = useCallback(()=>api("/parent/overview").then(setD).catch(e=>setErr(e.message)),[]);
  useEffect(()=>{ load(); },[load]);
  useEffect(()=>{ api("/parent/affiliate").then(a=>setRefLink(a.affiliate.link)).catch(()=>{}); },[]);

  if (err) return <div style={{ padding:24 }}><Card>{err}</Card>
    <button style={btnS(T.navy,{marginTop:12})} onClick={onLogout}>Sign in again</button></div>;
  if (!d) return <div style={{ textAlign:"center", padding:"70px 0", color:T.mist }}>Loading your family…</div>;

  const celebrate = (childId, message)=>api("/parent/celebrate",{method:"POST",body:{childId,message}});
  const family = (d.parent.name||"").split(" ")[0];

  if (openChildId) return <ChildDetail childId={openChildId} onBack={()=>{ setOpenChildId(null); load(); }} />;

  return (
    <div>
      {/* Brand header */}
      <div style={{ background:`linear-gradient(140deg, ${T.navy} 0%, ${T.navy2} 60%, ${T.navy3} 100%)`,
        padding:"20px 20px 22px" }}>
        <div style={{ display:"flex", justifyContent:"space-between", alignItems:"center" }}>
          <img src="/assets/cert/logo-white.png" alt="Librancy AI" style={{ height:26 }} />
          <span style={chip("rgba(255,255,255,.14)","#D8C9FF")}>🔥 {d.beacons.balance} Beacons</span>
        </div>
        <div style={{ marginTop:16 }}>
          <div style={{ fontSize:12.5, color:"#8FA6BC", letterSpacing:.4 }}>PARENT DASHBOARD</div>
          <div style={{ fontSize:24, fontWeight:700, color:"#fff", marginTop:2 }}>The {family} family</div>
        </div>
      </div>

      <div style={{ padding:"18px 20px 40px" }}>
        <div className="grid-auto">
          {d.children.map((c,i)=><ChildCard key={c.id} c={c} i={i} onCelebrate={celebrate} onOpen={()=>setOpenChildId(c.id)} refLink={refLink} />)}
        </div>

        <div className="grid-2col" style={{ marginTop:14 }}>
        {/* Beacons economy — gradient card */}
        <div style={{ borderRadius:20, padding:20, color:"#fff",
          background:`linear-gradient(140deg, ${T.purpleDeep} 0%, ${T.purple} 70%, #8A7DF0 100%)`,
          boxShadow:"0 10px 26px rgba(76,63,209,.28)" }}>
          <div style={{ display:"flex", justifyContent:"space-between", alignItems:"baseline" }}>
            <div style={{ fontSize:15, fontWeight:700 }}>Your Beacons</div>
            <img src="/assets/cert/logo-white.png" alt="" style={{ height:16, opacity:.7 }} />
          </div>
          <div style={{ display:"flex", alignItems:"baseline", gap:10, margin:"10px 0 2px" }}>
            <span style={{ fontSize:38, fontWeight:800 }}>{d.beacons.balance}</span>
            <span style={{ fontSize:15, fontWeight:600, color:"#E4DEFF" }}>= {NGN(d.beacons.creditMinor)} credit</span>
          </div>
          <div style={{ fontSize:12.5, color:"#E4DEFF", lineHeight:1.6, marginTop:6 }}>
            Earned from <b>{d.beacons.referrals}</b> famil{d.beacons.referrals===1?"y":"ies"} who joined through
            your child’s shared wins ({d.beacons.shares} shares). Credit auto-applies up to {d.beacons.capPct}%
            at your next checkout — perfect for the next course or a sibling.
          </div>
          <a href="/" style={{ textDecoration:"none" }}>
            <button style={{...btnS("#fff",{ color:T.purpleDeep, marginTop:14, padding:"13px", fontSize:14,
              fontWeight:700 })}}>Enrol another child →</button>
          </a>
        </div>

        <Boards />
        </div>

        <PartnerEarnings />

        {/* Region */}
        <Card style={{ marginTop:14 }}>
          <div style={{ fontWeight:700, color:T.navy, fontSize:14, marginBottom:8 }}>📍 Your region (for the leaderboard)</div>
          <select defaultValue={d.parent.region||""} onChange={async e=>{
            if(e.target.value){ await api("/parent/region",{method:"POST",body:{region:e.target.value}}); }}}
            style={{...inputS, padding:"12px 13px"}}>
            <option value="" disabled>Choose your region…</option>
            {REGIONS.map(r=><option key={r} value={r}>{r}</option>)}
          </select>
        </Card>

        {/* Account */}
        <Card style={{ marginTop:14 }}>
          <button onClick={()=>setShowAccount(!showAccount)} style={{...btnS("transparent",{color:T.navy,
            textAlign:"left", padding:0, fontSize:14, fontWeight:700, width:"100%"})}}>
            ⚙️ Account {showAccount?"▴":"▾"}
          </button>
          {showAccount && <AccountPanel email={d.parent.email} onLogout={onLogout} />}
        </Card>
      </div>
    </div>
  );
}

function AccountPanel({ email, onLogout }) {
  const [cur,setCur]=useState(""); const [nw,setNw]=useState(""); const [msg,setMsg]=useState("");
  const change = async ()=>{ setMsg("");
    try { await api("/auth/change-password",{method:"POST",body:{current:cur,new:nw}});
      setMsg("Password changed ✓"); setCur(""); setNw(""); }
    catch(e){ setMsg(e.message); } };
  return (
    <div style={{ marginTop:12 }}>
      <div style={{ fontSize:12.5, color:T.mist, marginBottom:10 }}>Signed in as {email}</div>
      <input value={cur} onChange={e=>setCur(e.target.value)} type="password" placeholder="Current password"
        style={{...inputS, marginBottom:8, padding:"11px 13px", fontSize:13.5}} />
      <input value={nw} onChange={e=>setNw(e.target.value)} type="password" placeholder="New password (8+)"
        style={{...inputS, marginBottom:8, padding:"11px 13px", fontSize:13.5}} />
      {msg && <div style={{ fontSize:12.5, color:msg.includes("✓")?T.tealDeep:"#C0392B", marginBottom:8 }}>{msg}</div>}
      <div style={{ display:"flex", gap:8 }}>
        <button onClick={change} style={btnS(T.navy,{padding:"11px", fontSize:13.5})}>Change password</button>
        <button onClick={onLogout} style={btnS("#8597A6",{padding:"11px", fontSize:13.5})}>Log out</button>
      </div>
    </div>
  );
}

/* ── App ── */
function App(){
  const [authed,setAuthed]=useState(!!store.get("token"));
  return (
    <div style={{ minHeight:"100vh", background:T.cloud, fontFamily:FONT }}>
      <style>{`*{box-sizing:border-box} button:active{transform:scale(.985)}`}</style>
      <div className="lbr-shell parent">
        {authed ? <Dash onLogout={()=>{store.del("token");setAuthed(false);}} />
                : <Login onDone={()=>setAuthed(true)} />}
      </div>
    </div>
  );
}
ReactDOM.createRoot(document.getElementById("root")).render(<App />);
