/* ===== หน้าบ้าน (ผู้ใช้) — ค้นหา → ผลลัพธ์ → ดาวน์โหลด (เชื่อม API) ===== */

function PublicHeader({ onAdmin }) {
  return (
    <header style={{ position: "sticky", top: 0, zIndex: 40, background: "oklch(1 0 0 / 0.85)",
      backdropFilter: "blur(10px)", borderBottom: "1px solid var(--c-line-soft)" }}>
      <div style={{ maxWidth: 1080, margin: "0 auto", padding: "13px 22px",
        display: "flex", alignItems: "center", gap: 13 }}>
        <Logo size={38} />
        <div style={{ lineHeight: 1.25, whiteSpace: "nowrap" }}>
          <div style={{ fontWeight: 700, fontSize: 16 }}>ระบบเกียรติบัตรออนไลน์</div>
          <div className="muted" style={{ fontSize: 12.5 }}>กลุ่มโรงเรียนบ้านด่าน 2</div>
        </div>
        <div style={{ flex: 1 }} />
        <button className="btn btn-ghost btn-sm" onClick={onAdmin}>
          <Icon.lock size={16} /> <span style={{ marginLeft: 2 }}>สำหรับผู้ดูแล</span>
        </button>
      </div>
    </header>
  );
}

function ResultCard({ hit, idx, onOpen }) {
  const { event, rec } = hit;
  const toneClass = rec.tone === "gold" ? "chip-gold" : rec.tone === "muted" ? "chip-muted" : "chip";
  return (
    <div className="card anim-up" style={{ padding: 0, overflow: "hidden", animationDelay: `${idx * 60}ms`,
      display: "flex", flexDirection: "column" }}>
      <div style={{ display: "flex", alignItems: "stretch", gap: 0 }}>
        {/* mini cert thumbnail */}
        <div style={{ width: 132, flex: "none", background: "var(--c-bg-deep)", position: "relative",
          display: "grid", placeItems: "center", borderRight: "1px solid var(--c-line-soft)", overflow: "hidden" }}>
          <div style={{ transform: "scale(0.93)" }}>
            <Certificate event={event} rec={rec} scale={0.132} />
          </div>
        </div>
        <div style={{ padding: "15px 17px", flex: 1, minWidth: 0 }}>
          <div style={{ display: "flex", gap: 8, flexWrap: "wrap", marginBottom: 7 }}>
            <span className={"chip " + toneClass}>
              {rec.tone === "gold" && <Icon.trophy size={13} />}{rec.role}
            </span>
          </div>
          <div style={{ fontWeight: 700, fontSize: 16.5, lineHeight: 1.35, marginBottom: 3,
            display: "-webkit-box", WebkitLineClamp: 2, WebkitBoxOrient: "vertical", overflow: "hidden" }}>
            {event.title}
          </div>
          <div className="muted" style={{ fontSize: 13, display: "flex", alignItems: "center", gap: 13, flexWrap: "wrap" }}>
            <span style={{ display: "inline-flex", alignItems: "center", gap: 5 }}><Icon.cal size={14} />{event.date}</span>
            <span style={{ display: "inline-flex", alignItems: "center", gap: 5 }}><Icon.school size={14} />{rec.school}</span>
          </div>
        </div>
      </div>
      <div style={{ padding: "0 17px 15px", display: "flex", gap: 9 }}>
        <button className="btn btn-gold btn-sm" style={{ flex: 1 }} onClick={() => onOpen(hit, "download")}>
          <Icon.download size={16} /> ดาวน์โหลด PDF
        </button>
        <button className="btn btn-ghost btn-sm" onClick={() => onOpen(hit, "preview")}>
          <Icon.eye size={16} /> ดูตัวอย่าง
        </button>
      </div>
    </div>
  );
}

function CertModal({ hit, mode, onClose }) {
  const { event, rec } = hit;
  const [phase, setPhase] = React.useState("view"); // view | gen | done | error
  const [errMsg, setErrMsg] = React.useState("");
  const [share, setShare] = React.useState(false);
  const [copied, setCopied] = React.useState(false);
  const boxRef = React.useRef(null);
  const [scale, setScale] = React.useState(0.5);
  const verifyUrl = location.origin + "/verify/" + rec.id;

  React.useEffect(() => {
    function fit() {
      const w = boxRef.current ? boxRef.current.clientWidth : 600;
      setScale(Math.min((w - 4) / CERT_W, 0.62));
    }
    fit(); window.addEventListener("resize", fit);
    return () => window.removeEventListener("resize", fit);
  }, []);

  async function doDownload() {
    setPhase("gen"); setErrMsg("");
    try {
      await api.downloadCert(rec.id, `เกียรติบัตร_${(rec.name || "").replace(/\s+/g, "_")}.pdf`);
      setPhase("done");
    } catch (e) {
      setErrMsg(e.message || "ดาวน์โหลดไม่สำเร็จ");
      setPhase("error");
    }
  }

  // เริ่มดาวน์โหลดทันทีถ้าเปิดมาในโหมด download
  React.useEffect(() => { if (mode === "download") doDownload(); }, []);

  return (
    <Modal open onClose={onClose} maxW={780} pad={false}>
      <div style={{ padding: "18px 22px", borderBottom: "1px solid var(--c-line-soft)",
        display: "flex", alignItems: "center", gap: 12 }}>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontWeight: 700, fontSize: 16, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{event.title}</div>
          <div className="muted" style={{ fontSize: 13 }}>{rec.name} · เลขที่ {rec.no}</div>
        </div>
        <button className="btn btn-ghost btn-sm" onClick={onClose} style={{ padding: 9 }}><Icon.x size={18} /></button>
      </div>

      <div ref={boxRef} style={{ padding: 22, background: "var(--c-bg-deep)", display: "grid", placeItems: "center", position: "relative" }}>
        <div style={{ boxShadow: "var(--sh-lg)", borderRadius: 2, overflow: "hidden", position: "relative" }}>
          <Certificate event={event} rec={rec} scale={scale} />
          {phase === "gen" && (
            <div style={{ position: "absolute", inset: 0, background: "oklch(1 0 0 / 0.72)", backdropFilter: "blur(2px)",
              display: "grid", placeItems: "center", gap: 10 }}>
              <div style={{ display: "grid", placeItems: "center", gap: 12, color: "var(--c-primary)" }}>
                <Spinner size={34} />
                <div style={{ fontWeight: 600, fontSize: 14.5 }}>กำลังสร้างไฟล์ PDF…</div>
              </div>
            </div>
          )}
        </div>
      </div>

      <div style={{ padding: "16px 22px", borderTop: "1px solid var(--c-line-soft)" }}>
        {phase === "done" && (
          <div className="anim-in" style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 14,
            background: "var(--c-ok-soft)", color: "var(--c-ok)", padding: "11px 15px", borderRadius: "var(--r-md)" }}>
            <Icon.checkCircle size={20} />
            <div style={{ fontWeight: 600, fontSize: 14.5 }}>ดาวน์โหลดเรียบร้อย — บันทึกเป็น <code style={{ fontFamily: "var(--font-ui)" }}>เกียรติบัตร_{rec.name.replace(" ", "_")}.pdf</code></div>
          </div>
        )}
        {phase === "error" && (
          <div className="anim-in" style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 14,
            background: "var(--c-danger-soft)", color: "var(--c-danger)", padding: "11px 15px", borderRadius: "var(--r-md)" }}>
            <Icon.info size={20} />
            <div style={{ fontWeight: 600, fontSize: 14.5 }}>{errMsg}</div>
          </div>
        )}
        {!share ? (
          <div style={{ display: "flex", gap: 9, flexWrap: "wrap" }}>
            <button className="btn btn-gold" style={{ flex: "1 1 200px" }} onClick={doDownload} disabled={phase === "gen"}>
              <Icon.download size={18} /> {phase === "gen" ? "กำลังสร้าง…" : "ดาวน์โหลด PDF"}
            </button>
            <button className="btn btn-ghost" onClick={() => window.open(api.certUrl(rec.id), "_blank")}>
              <Icon.print size={18} /> เปิด / พิมพ์
            </button>
            <button className="btn btn-ghost" onClick={() => setShare(true)}>
              <Icon.share size={18} /> แชร์ / ตรวจสอบ
            </button>
          </div>
        ) : (
          <div className="anim-in" style={{ display: "flex", gap: 16, alignItems: "center" }}>
            <div style={{ width: 92, height: 92, flex: "none", background: "#fff", border: "1px solid var(--c-line)",
              borderRadius: 10, display: "grid", placeItems: "center", overflow: "hidden" }}>
              <img alt="QR ตรวจสอบ" width={84} height={84}
                src={"https://api.qrserver.com/v1/create-qr-code/?size=140x140&margin=0&data=" + encodeURIComponent(verifyUrl)} />
            </div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontWeight: 700, fontSize: 14.5, marginBottom: 3 }}>ลิงก์ตรวจสอบความถูกต้อง</div>
              <div className="muted" style={{ fontSize: 13, marginBottom: 9 }}>สแกน QR หรือเปิดลิงก์เพื่อยืนยันว่าเกียรติบัตรออกโดยกลุ่มโรงเรียนบ้านด่าน 2 จริง</div>
              <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
                <code style={{ fontFamily: "var(--font-ui)", fontSize: 12, background: "var(--c-bg-deep)", padding: "7px 11px",
                  borderRadius: 8, flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                  {verifyUrl}
                </code>
                <button className="btn btn-soft btn-sm" onClick={() => {
                  navigator.clipboard && navigator.clipboard.writeText(verifyUrl);
                  setCopied(true); setTimeout(() => setCopied(false), 1500);
                }}>{copied ? "คัดลอกแล้ว" : "คัดลอก"}</button>
                <button className="btn btn-ghost btn-sm" onClick={() => setShare(false)}>กลับ</button>
              </div>
            </div>
          </div>
        )}
      </div>
    </Modal>
  );
}

function PublicApp({ onAdmin }) {
  const [query, setQuery] = React.useState("");
  const [submitted, setSubmitted] = React.useState(false);
  const [results, setResults] = React.useState([]);
  const [searching, setSearching] = React.useState(false);
  const [open, setOpen] = React.useState(null);
  const [published, setPublished] = React.useState([]);
  const [loadingEvents, setLoadingEvents] = React.useState(true);
  const [selEvent, setSelEvent] = React.useState(null);
  const [recips, setRecips] = React.useState([]);
  const [loadingRecips, setLoadingRecips] = React.useState(false);
  const inputRef = React.useRef(null);

  React.useEffect(() => {
    api.listEvents(false)
      .then(d => {
        const evs = d.events || [];
        setPublished(evs);
        if (evs.length) openEvent(evs[0]);
      })
      .catch(() => setPublished([]))
      .finally(() => setLoadingEvents(false));
  }, []);

  function openEvent(ev) {
    setSelEvent(ev);
    setRecips([]); setLoadingRecips(true);
    api.getEvent(ev.id)
      .then(d => setRecips(d.recipients || []))
      .catch(() => setRecips([]))
      .finally(() => setLoadingRecips(false));
  }

  async function run(q) {
    const qq = (q ?? query).trim();
    setQuery(qq);
    if (!qq) return;
    setSearching(true); setSubmitted(true);
    try {
      const d = await api.search(qq);
      setResults(d.results || []);
    } catch (e) {
      setResults([]);
    } finally {
      setSearching(false);
    }
  }

  return (
    <div style={{ minHeight: "100vh", display: "flex", flexDirection: "column" }}>
      <PublicHeader onAdmin={onAdmin} />

      {/* hero */}
      <div style={{ background: "linear-gradient(180deg, var(--c-primary-soft) 0%, transparent 70%)", paddingBottom: 8 }}>
        <div style={{ maxWidth: 720, margin: "0 auto", padding: "clamp(34px,7vw,64px) 22px 30px", textAlign: "center" }}>
          <div className="chip" style={{ marginBottom: 16 }}><Icon.sparkle size={14} /> ค้นหาเกียรติบัตรของคุณได้ทันที</div>
          <h1 className="display" style={{ fontSize: "clamp(30px,6vw,46px)", fontWeight: 600, lineHeight: 1.15, letterSpacing: 0.2 }}>
            พิมพ์ชื่อ–นามสกุล<br />ดาวน์โหลดเกียรติบัตรได้เลย
          </h1>
          <p className="muted" style={{ fontSize: "clamp(15px,2.5vw,17px)", marginTop: 12, maxWidth: 480, marginInline: "auto" }}>
            ไม่ต้องไล่หาชื่อในตารางยาว ๆ — คนหนึ่งคนเห็นเกียรติบัตรทุกกิจกรรมรวมในที่เดียว
          </p>

          <form onSubmit={(e) => { e.preventDefault(); run(); }}
            style={{ marginTop: 26, display: "flex", gap: 9, maxWidth: 540, marginInline: "auto" }}>
            <div style={{ position: "relative", flex: 1 }}>
              <Icon.search size={20} style={{ position: "absolute", left: 15, top: "50%", transform: "translateY(-50%)", color: "var(--c-muted)" }} />
              <input ref={inputRef} className="input" value={query} onChange={(e) => setQuery(e.target.value)}
                placeholder="เช่น นายสราวุธ"
                style={{ paddingLeft: 44, height: 54, fontSize: 16.5, borderRadius: "var(--r-lg)", boxShadow: "var(--sh-sm)" }} />
            </div>
            <button type="submit" className="btn btn-primary btn-lg" style={{ height: 54 }} disabled={searching}>
              {searching ? <Spinner size={19} color="#fff" /> : <Icon.search size={19} />} <span className="hide-sm">ค้นหา</span>
            </button>
          </form>
          <div style={{ marginTop: 13, display: "flex", gap: 8, justifyContent: "center", alignItems: "center", flexWrap: "wrap" }}>
            <span className="faint" style={{ fontSize: 13 }}>ลองค้นหา:</span>
            <button className="btn btn-soft btn-sm" onClick={() => run(DEMO_PERSON)}>{DEMO_PERSON}</button>
          </div>
        </div>
      </div>

      {/* body */}
      <div style={{ maxWidth: 1080, margin: "0 auto", padding: "8px 22px 60px", width: "100%", flex: 1 }}>
        {!submitted ? (
          loadingEvents ? (
            <div style={{ display: "grid", placeItems: "center", padding: "60px 0", color: "var(--c-muted)" }}><Spinner size={28} /></div>
          ) : published.length === 0 ? (
            <div className="muted" style={{ fontSize: 14.5, padding: "40px 2px", textAlign: "center" }}>ยังไม่มีกิจกรรมที่เผยแพร่</div>
          ) : (
            <div className="anim-in browse-grid" style={{ display: "grid", gridTemplateColumns: "300px 1fr", gap: 18, alignItems: "start", marginTop: 18 }}>
              {/* left: event menu */}
              <div className="card" style={{ overflow: "hidden", position: "sticky", top: 78 }}>
                <div style={{ padding: "13px 16px", borderBottom: "1px solid var(--c-line-soft)", display: "flex", alignItems: "center", gap: 8 }}>
                  <Icon.cal size={17} style={{ color: "var(--c-muted)" }} />
                  <span style={{ fontWeight: 700, fontSize: 14.5 }}>กิจกรรมทั้งหมด</span>
                  <span className="chip chip-muted">{published.length}</span>
                </div>
                <div style={{ maxHeight: 540, overflowY: "auto" }}>
                  {published.map(e => {
                    const active = selEvent?.id === e.id;
                    return (
                      <button key={e.id} onClick={() => openEvent(e)}
                        style={{ width: "100%", textAlign: "left", padding: "12px 15px", display: "flex", gap: 11, alignItems: "center",
                          borderBottom: "1px solid var(--c-line-soft)", borderLeft: `3px solid ${active ? "var(--c-primary)" : "transparent"}`,
                          background: active ? "var(--c-primary-soft)" : "transparent" }}>
                        <div style={{ width: 34, height: 34, borderRadius: 9, flex: "none", display: "grid", placeItems: "center",
                          background: active ? "var(--c-primary)" : "var(--c-primary-soft)", color: active ? "#fff" : "var(--c-primary)" }}><Icon.cert size={18} /></div>
                        <div style={{ minWidth: 0 }}>
                          <div style={{ fontWeight: 600, fontSize: 13.5, lineHeight: 1.3, color: active ? "var(--c-primary-700)" : "var(--c-ink)",
                            display: "-webkit-box", WebkitLineClamp: 2, WebkitBoxOrient: "vertical", overflow: "hidden" }}>{e.title}</div>
                          <div className="muted" style={{ fontSize: 12, marginTop: 1 }}>{e.date} · {e.count} คน</div>
                        </div>
                      </button>
                    );
                  })}
                </div>
              </div>

              {/* right: recipients of selected event */}
              <div>
                {!selEvent ? (
                  <div className="muted" style={{ padding: "60px 0", textAlign: "center" }}>เลือกกิจกรรมทางซ้ายเพื่อดูรายชื่อ</div>
                ) : (
                  <div className="card" style={{ overflow: "hidden" }}>
                    <div style={{ padding: "15px 18px", borderBottom: "1px solid var(--c-line-soft)" }}>
                      <div style={{ fontWeight: 700, fontSize: 16.5, lineHeight: 1.3 }}>{selEvent.title}</div>
                      <div className="muted" style={{ fontSize: 13, marginTop: 3, display: "flex", gap: 13, flexWrap: "wrap" }}>
                        <span style={{ display: "inline-flex", alignItems: "center", gap: 5 }}><Icon.cal size={14} />{selEvent.date}</span>
                        <span style={{ display: "inline-flex", alignItems: "center", gap: 5 }}><Icon.users size={14} />{selEvent.count} คน</span>
                      </div>
                    </div>
                    {loadingRecips ? (
                      <div style={{ display: "grid", placeItems: "center", padding: "50px 0", color: "var(--c-muted)" }}><Spinner size={26} /></div>
                    ) : recips.length === 0 ? (
                      <div className="muted" style={{ padding: "40px 0", textAlign: "center", fontSize: 14 }}>ยังไม่มีรายชื่อ</div>
                    ) : (
                      <div style={{ maxHeight: 560, overflowY: "auto" }}>
                        {recips.map((r, i) => {
                          const toneClass = r.tone === "gold" ? "chip-gold" : r.tone === "muted" ? "chip-muted" : "chip";
                          return (
                            <div key={r.id} style={{ padding: "12px 18px", borderTop: i ? "1px solid var(--c-line-soft)" : "none",
                              display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap" }}>
                              <div style={{ minWidth: 0, flex: "1 1 200px" }}>
                                <div style={{ fontWeight: 600, fontSize: 14.5 }}>{r.name}</div>
                                <div className="muted" style={{ fontSize: 12.5, display: "flex", gap: 10, flexWrap: "wrap", marginTop: 2 }}>
                                  <span style={{ display: "inline-flex", alignItems: "center", gap: 4 }}><Icon.school size={13} />{r.school}</span>
                                  <span className={"chip " + toneClass} style={{ padding: "2px 8px", fontSize: 11.5 }}>
                                    {r.tone === "gold" && <Icon.trophy size={11} />}{r.role}
                                  </span>
                                </div>
                              </div>
                              <div style={{ display: "flex", gap: 8, flex: "none" }}>
                                <button className="btn btn-gold btn-sm" onClick={() => setOpen({ hit: { event: selEvent, rec: r }, mode: "download" })}>
                                  <Icon.download size={15} /> ดาวน์โหลด
                                </button>
                                <button className="btn btn-ghost btn-sm" onClick={() => setOpen({ hit: { event: selEvent, rec: r }, mode: "preview" })}>
                                  <Icon.eye size={15} />
                                </button>
                              </div>
                            </div>
                          );
                        })}
                      </div>
                    )}
                  </div>
                )}
              </div>
            </div>
          )
        ) : searching ? (
          <div style={{ display: "grid", placeItems: "center", padding: "70px 0", color: "var(--c-muted)" }}><Spinner size={30} /></div>
        ) : results.length > 0 ? (
          <div>
            <button className="btn btn-ghost btn-sm" style={{ margin: "16px 2px 4px" }}
              onClick={() => { setSubmitted(false); setQuery(""); setResults([]); }}>
              <Icon.arrowL size={16} /> กลับหากิจกรรมทั้งหมด
            </button>
            <div style={{ display: "flex", alignItems: "baseline", gap: 8, margin: "8px 2px 16px", flexWrap: "wrap" }}>
              <h2 style={{ fontSize: 18, fontWeight: 700 }}>พบ {results.length} เกียรติบัตร</h2>
              <span className="muted" style={{ fontSize: 14 }}>สำหรับ “{query}”</span>
            </div>
            <div style={{ display: "grid", gap: 15, gridTemplateColumns: "repeat(auto-fill,minmax(330px,1fr))" }}>
              {results.map((h, i) => <ResultCard key={h.rec.id} hit={h} idx={i} onOpen={(hit, m) => setOpen({ hit, mode: m })} />)}
            </div>
          </div>
        ) : (
          <div className="anim-in" style={{ textAlign: "center", padding: "56px 20px", maxWidth: 420, margin: "0 auto" }}>
            <div style={{ width: 70, height: 70, borderRadius: 18, background: "var(--c-bg-deep)", display: "grid", placeItems: "center", margin: "0 auto 16px", color: "var(--c-faint)" }}>
              <Icon.search size={32} />
            </div>
            <h3 style={{ fontSize: 18, fontWeight: 700, marginBottom: 6 }}>ไม่พบเกียรติบัตรของ “{query}”</h3>
            <p className="muted" style={{ fontSize: 14.5, marginBottom: 18 }}>ลองตรวจสอบการสะกดชื่อ–นามสกุล หรือพิมพ์เพียงบางส่วนของชื่อ</p>
            <button className="btn btn-ghost" onClick={() => { setSubmitted(false); setQuery(""); setResults([]); }}>
              <Icon.arrowL size={17} /> กลับหากิจกรรมทั้งหมด
            </button>
          </div>
        )}
      </div>

      <footer style={{ borderTop: "1px solid var(--c-line-soft)", background: "var(--c-surface)" }}>
        <div style={{ maxWidth: 1080, margin: "0 auto", padding: "20px 22px", display: "flex", gap: 12,
          alignItems: "center", flexWrap: "wrap", fontSize: 13, color: "var(--c-muted)" }}>
          <Logo size={28} />
          <span>กลุ่มโรงเรียนบ้านด่าน 2 · สพป.บุรีรัมย์ เขต 1 · พัฒนาโดย S.directorkachai</span>
          <span style={{ flex: 1 }} />
          <span className="faint">ระบบเกียรติบัตรออนไลน์</span>
        </div>
      </footer>

      {open && <CertModal hit={open.hit} mode={open.mode} onClose={() => setOpen(null)} />}

      <style>{`
        @media (max-width: 520px){ .hide-sm{ display:none; } }
        @media (max-width: 760px){ .browse-grid{ grid-template-columns: 1fr !important; } .browse-grid > .card:first-child{ position: static !important; } }
      `}</style>
    </div>
  );
}

/* ===== หน้าตรวจสอบความถูกต้อง (public) — /verify/:id ===== */
function VerifyPage({ id, onHome }) {
  const [state, setState] = React.useState({ loading: true });
  const boxRef = React.useRef(null);
  const [scale, setScale] = React.useState(0.5);

  React.useEffect(() => {
    api.getRecipient(id)
      .then(d => setState({ loading: false, data: d }))
      .catch(e => setState({ loading: false, error: e.message || "ไม่พบเกียรติบัตร" }));
  }, [id]);

  React.useEffect(() => {
    function fit() { const w = boxRef.current ? boxRef.current.clientWidth : 600; setScale(Math.min((w - 4) / CERT_W, 0.62)); }
    fit(); window.addEventListener("resize", fit); return () => window.removeEventListener("resize", fit);
  });

  const ok = state.data && state.data.verified;

  return (
    <div style={{ minHeight: "100vh", display: "flex", flexDirection: "column" }}>
      <PublicHeader onAdmin={onHome} />
      <div style={{ maxWidth: 820, margin: "0 auto", padding: "28px 22px 60px", width: "100%", flex: 1 }}>
        <button className="btn btn-ghost btn-sm" onClick={onHome} style={{ marginBottom: 18 }}>
          <Icon.arrowL size={16} /> กลับหน้าค้นหา
        </button>

        {state.loading ? (
          <div style={{ display: "grid", placeItems: "center", padding: "80px 0", color: "var(--c-muted)" }}><Spinner size={30} /></div>
        ) : state.error || !ok ? (
          <div className="card" style={{ padding: 34, textAlign: "center", maxWidth: 480, margin: "20px auto" }}>
            <div style={{ width: 64, height: 64, borderRadius: 18, background: "var(--c-danger-soft)", color: "var(--c-danger)",
              display: "grid", placeItems: "center", margin: "0 auto 16px" }}><Icon.x size={32} /></div>
            <h2 style={{ fontSize: 19, fontWeight: 700, marginBottom: 6 }}>ไม่พบเกียรติบัตรนี้</h2>
            <p className="muted" style={{ fontSize: 14.5 }}>ลิงก์อาจไม่ถูกต้อง หรือเกียรติบัตรนี้ยังไม่ถูกเผยแพร่</p>
          </div>
        ) : (
          <div className="anim-up">
            <div className="card" style={{ padding: "18px 20px", display: "flex", alignItems: "center", gap: 14, marginBottom: 18,
              background: "var(--c-ok-soft)", border: "1px solid oklch(0.58 0.11 155 / 0.25)" }}>
              <div style={{ width: 48, height: 48, borderRadius: 12, background: "var(--c-ok)", color: "#fff",
                display: "grid", placeItems: "center", flex: "none" }}><Icon.checkCircle size={28} /></div>
              <div>
                <div style={{ fontWeight: 700, fontSize: 16.5, color: "var(--c-ok)" }}>เกียรติบัตรนี้เป็นของจริง ✓</div>
                <div className="muted" style={{ fontSize: 13.5 }}>ออกโดยกลุ่มโรงเรียนบ้านด่าน 2 · สพป.บุรีรัมย์ เขต 1</div>
              </div>
            </div>

            <div className="card" style={{ overflow: "hidden" }}>
              <div ref={boxRef} style={{ padding: 22, background: "var(--c-bg-deep)", display: "grid", placeItems: "center" }}>
                <div style={{ boxShadow: "var(--sh-lg)", borderRadius: 2, overflow: "hidden" }}>
                  <Certificate event={state.data.event} rec={state.data.recipient} scale={scale} />
                </div>
              </div>
              <div style={{ padding: "16px 20px", display: "grid", gap: 6 }}>
                {[["ผู้รับ", state.data.recipient.name],
                  ["เลขที่", state.data.recipient.no],
                  ["ประเภท", state.data.recipient.role],
                  ["โรงเรียน/สังกัด", state.data.recipient.school],
                  ["กิจกรรม", state.data.event.title],
                  ["วันที่", state.data.event.date]].map(([k, v]) => v ? (
                  <div key={k} style={{ display: "flex", gap: 12, fontSize: 14 }}>
                    <span className="muted" style={{ width: 120, flex: "none" }}>{k}</span>
                    <span style={{ fontWeight: 600 }}>{v}</span>
                  </div>
                ) : null)}
                <button className="btn btn-gold" style={{ marginTop: 10, justifySelf: "start" }}
                  onClick={() => api.downloadCert(state.data.recipient.id, `เกียรติบัตร_${state.data.recipient.name.replace(/\s+/g, "_")}.pdf`)}>
                  <Icon.download size={18} /> ดาวน์โหลด PDF
                </button>
              </div>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { PublicApp, VerifyPage });
