// Map + About + Review pages
function MapPage({ onNav }) {
  const [activeId, setActiveId] = React.useState("lianhua");
  const currentHotspot = window.MAP_HOTSPOTS.find(h => h.id === activeId) || window.MAP_HOTSPOTS[0];
  const linkedDeer = currentHotspot.deer
    .map(id => window.DEER_DATA.find(d => d.id === id))
    .filter(Boolean);

  return (
    <div className="page">
      <section style={{ padding: "56px 0 40px", borderBottom: "1px solid var(--rule)" }}>
        <div className="app">
          <div className="kicker mb-4"><span className="dot">●</span>MAP / 交互地图 · Interactive</div>
          <div style={{ display: "grid", gridTemplateColumns: "1.3fr 1fr", gap: 64, alignItems: "end" }}>
            <h1 className="serif" style={{ fontSize: 56, lineHeight: 1.1 }}>
              大连的野生动物，<br />在这些<span style={{ color: "var(--accent)" }}>边缘地带</span>生活。
            </h1>
            <p style={{ fontSize: 14, color: "var(--ink-soft)", lineHeight: 1.7 }}>
              热点聚合了该区域的活跃个体、物种线索与最近观察。为保护野生动物，地图仅显示聚类区域——精确坐标仅对认证审核员可见。
              <br /><span className="mono" style={{ fontSize: 11, color: "var(--muted)", letterSpacing: ".1em", marginTop: 8, display: "inline-block" }}>OPENSTREETMAP · LIVE TILES · PROTECTED COORDINATES</span>
            </p>
          </div>
        </div>
      </section>

      <section style={{ padding: "40px 0" }}>
        <div className="app">
          <div style={{ display: "grid", gridTemplateColumns: "1.6fr 1fr", gap: 32 }}>
            <div>
              <InteractiveMap
                activeId={activeId}
                setActiveId={setActiveId}
              />
              <div className="mono" style={{ fontSize: 10.5, color: "var(--muted)", letterSpacing: ".12em", marginTop: 12, display: "flex", justifyContent: "space-between" }}>
                <span>— 真实地图 · OpenStreetMap · 坐标已模糊化保护野生动物 —</span>
                <span>OSM · LIVE TILES · INTERACTIVE</span>
              </div>
            </div>
            <aside>
              <div style={{ border: "1px solid var(--ink)", padding: 24 }}>
                <div className="kicker"><span className="dot">●</span>HOTSPOT / 当前选中</div>
                <h2 className="serif" style={{ fontSize: 30, marginTop: 12, marginBottom: 4 }}>{currentHotspot.name}</h2>
                <div className="mono" style={{ fontSize: 10.5, color: "var(--muted)", letterSpacing: ".14em", textTransform: "uppercase" }}>
                  {currentHotspot.en} · {currentHotspot.obs} OBS · LAST {currentHotspot.freshness}d
                </div>
                <hr className="rule" style={{ margin: "18px 0" }} />
                <div style={{ fontSize: 13, color: "var(--ink-soft)", lineHeight: 1.7, marginBottom: 18 }}>
                  {currentHotspot.note}
                </div>
                <div className="form-label">关联档案 · Linked records ({linkedDeer.length})</div>
                <div style={{ display: "grid", gap: 8 }}>
                  {linkedDeer.length === 0 && (
                    <div style={{ padding: "14px 10px", fontSize: 12, color: "var(--muted)", background: "var(--paper-2)", textAlign: "center" }}>
                      该区域暂无已归档动物档案
                    </div>
                  )}
                  {linkedDeer.map(d => (
                    <div key={d.id} onClick={() => onNav("deer:" + d.id)} style={{ display: "flex", gap: 12, alignItems: "center", padding: 8, cursor: "pointer", border: "1px solid var(--rule-soft)", transition: "all .15s" }}
                      onMouseEnter={e => e.currentTarget.style.background = "var(--paper-2)"}
                      onMouseLeave={e => e.currentTarget.style.background = "transparent"}>
                      <div style={{ width: 44, height: 44, backgroundImage: d.photo ? `url(${d.photo})` : "none", backgroundColor: !d.photo ? d.palette[1] : undefined, backgroundSize: "cover", backgroundPosition: "center", filter: d.photoTone || "none", border: "1px solid var(--rule)" }}></div>
                      <div style={{ flex: 1 }}>
                        <div className="serif" style={{ fontSize: 14 }}>{d.name}</div>
                        <div className="mono" style={{ fontSize: 10, color: "var(--muted)", letterSpacing: ".1em" }}>{d.species} · {d.id} · {d.sightings} obs</div>
                      </div>
                      <span style={{ color: "var(--muted)" }}>→</span>
                    </div>
                  ))}
                </div>
                <div style={{ marginTop: 22, padding: 14, background: "var(--paper-2)", fontSize: 12, color: "var(--ink-soft)", lineHeight: 1.6, borderLeft: "3px solid var(--moss)" }}>
                  该区域建议以步行观察为主，保持安静；不推荐在黄昏后单独前往。
                </div>
              </div>
              <div style={{ marginTop: 18, display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 }}>
                <div className="stat"><div className="stat-n">{window.MAP_HOTSPOTS.reduce((a, h) => a + h.obs, 0)}</div><div className="stat-l">TOTAL OBS</div></div>
                <div className="stat"><div className="stat-n">{window.MAP_HOTSPOTS.length}</div><div className="stat-l">HOTSPOTS</div></div>
              </div>
            </aside>
          </div>
        </div>
      </section>
    </div>
  );
}

function AboutPage({ onNav }) {
  return (
    <div className="page">
      <section style={{ padding: "72px 0 48px", borderBottom: "1px solid var(--rule)" }}>
        <div className="app">
          <div className="kicker mb-4"><span className="dot">●</span>PARTICIPATE / 参与·科普</div>
          <h1 className="serif" style={{ fontSize: 64, lineHeight: 1.08, maxWidth: 960 }}>
            认识它们，<br />
            <span style={{ color: "var(--accent)" }}>比记录它们</span>更重要。
          </h1>
        </div>
      </section>

      <section className="section">
        <div className="app">
          <div style={{ display: "grid", gridTemplateColumns: "1.2fr 1fr", gap: 72 }}>
            <div>
              <div className="kicker mb-4"><span className="dot">●</span>WHY THIS MATTERS</div>
              <h2 style={{ fontSize: 34, lineHeight: 1.2, marginBottom: 22 }}>为什么需要给野生动物建立档案？</h2>
              <p style={{ fontSize: 15, color: "var(--ink-soft)", lineHeight: 1.8, marginBottom: 20 }}>
                在大连，梅花鹿已经成为具有高度城市辨识度的在地生命形象；狐狸、斑海豹、海岸猛禽等记录也不断出现在市民手机与社交平台里。人们主动拍摄、谈论它们，却常常停留在把野生动物看作“一个抽象对象”，而非可被识别、可被再次遇见、可被长期观察的具体生命。
              </p>
              <p style={{ fontSize: 15, color: "var(--ink-soft)", lineHeight: 1.8 }}>
                大量的照片与观察散落在个人手机、朋友圈与短视频平台。这个项目想做的事很简单：把那些短暂、偶然、分散的相遇，沉淀为可以被连接、被传播、被守护的数字化公共记忆。
              </p>
            </div>
            <div>
              <div style={{ padding: "28px 26px", background: "var(--paper-2)", borderLeft: "3px solid var(--accent)", fontFamily: "Noto Serif SC, serif", fontSize: 17, lineHeight: 1.8, color: "var(--ink)" }}>
                "当一个生命被赋予档案，它就不再只是'我见过'；当一次相遇被留下，它就能被很多人，在不同时间，共同核对、记住与守护。"
                <div className="mono" style={{ fontSize: 10.5, color: "var(--muted)", letterSpacing: ".14em", marginTop: 18, textTransform: "uppercase" }}>
                  — 项目结语 · CLOSING STATEMENT
                </div>
              </div>
            </div>
          </div>
        </div>
      </section>

      <section className="section" style={{ background: "var(--paper-2)" }}>
        <div className="app">
          <div className="section-head">
            <div>
              <div className="kicker mb-4"><span className="dot">●</span>HOW TO WATCH / 文明观察</div>
              <h2>看到野生动物，<br />请这样对待它。</h2>
            </div>
            <div className="side">
              所有上传内容默认按“文明观察原则”审核。对狐狸、猛禽、海豹等敏感物种，平台会进一步隐藏精确地点与繁殖/停歇线索。
            </div>
          </div>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(5, 1fr)", gap: 0, border: "1px solid var(--rule)" }}>
            {[
              ["保持距离", "Keep distance", "不靠近、不合照，不阻断动物行进路线；海岸观察使用长焦。"],
              ["不投喂", "No feeding", "人类食物会改变动物觅食习惯，并可能带来疾病传播。"],
              ["不追逐", "No chasing", "不为了拍照改变其行为，不奔跑、不围堵、不呼喊、不诱拍。"],
              ["不惊扰", "No disturbance", "关闭闪光灯，保持安静；遇到幼体、巢区或登岸点请主动后退。"],
              ["不公开精确位置", "No exact GPS", "分享照片时只提大致区域，避免招致聚集、拍摄或捕猎。"],
            ].map((r, i) => (
              <div key={i} style={{ padding: 22, borderRight: i < 4 ? "1px solid var(--rule)" : 0, background: "var(--paper)" }}>
                <div className="mono" style={{ fontSize: 13, color: "var(--accent)", letterSpacing: ".14em", fontWeight: 600 }}>R/{String(i + 1).padStart(2, "0")}</div>
                <div className="serif" style={{ fontSize: 19, marginTop: 12 }}>{r[0]}</div>
                <div className="mono" style={{ fontSize: 10, color: "var(--muted)", letterSpacing: ".14em", textTransform: "uppercase", marginTop: 2 }}>{r[1]}</div>
                <p style={{ fontSize: 12.5, color: "var(--ink-soft)", marginTop: 14, lineHeight: 1.65 }}>{r[2]}</p>
              </div>
            ))}
          </div>
        </div>
      </section>

      <section className="section">
        <div className="app">
          <div className="section-head">
            <div>
              <div className="kicker mb-4"><span className="dot">●</span>ROLES / 你可以是谁</div>
              <h2>不是所有参与者，<br />都要拍到动物。</h2>
            </div>
            <div className="side">
              项目采用"青年社区理念引领 + 组织承接 + 技术支撑 + 志愿审核 + 社会资源共建"的多方共建模式。总有一个角色适合你。
            </div>
          </div>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 16 }}>
            {[
              { r: "上传者", e: "Contributor", d: "任何市民、游客、摄影师。看见过、拍到过，愿意上传一次，就够了。", cta: "上传一张照片", go: "upload" },
              { r: "志愿审核员", e: "Volunteer reviewer", d: "每周 2 小时左右。协助 AI 纠偏、合并重复个体、核对档案特征。", cta: "申请成为志愿审核员", go: "review" },
              { r: "故事共创者", e: "Story contributor", d: "为既有档案补充一段相遇、一张补位照片、一条长期观察的记录。", cta: "浏览动物档案", go: "archive" },
              { r: "生态观察顾问", e: "Ecology advisor", d: "来自动保、观鸟、自然教育等领域的朋友，为项目提供识别常识与伦理边界建议。", cta: "联系项目组", go: "about" },
              { r: "青年社群合作者", e: "Youth community", d: "高校社团、青年自组织、读书会、徒步俱乐部——带来理念表达与传播共创能力。", cta: "发起一次联合活动", go: "about" },
              { r: "企业与机构合作方", e: "Partner", d: "提供云服务、算力、设备、场地、设计、传播资源。支持不限于现金赞助。", cta: "查看合作方式", go: "about" },
            ].map(role => (
              <div key={role.r} className="card" style={{ display: "flex", flexDirection: "column", gap: 14 }}>
                <div>
                  <div className="serif" style={{ fontSize: 22 }}>{role.r}</div>
                  <div className="mono" style={{ fontSize: 10.5, color: "var(--muted)", letterSpacing: ".14em", textTransform: "uppercase", marginTop: 2 }}>{role.e}</div>
                </div>
                <p style={{ fontSize: 13, color: "var(--ink-soft)", lineHeight: 1.65, flex: 1 }}>{role.d}</p>
                <button className="btn btn-sm btn-ghost" onClick={() => onNav(role.go)} style={{ alignSelf: "flex-start" }}>{role.cta} →</button>
              </div>
            ))}
          </div>
        </div>
      </section>

      <section className="section" style={{ background: "var(--paper-2)" }}>
        <div className="app">
          <div className="section-head">
            <div>
              <div className="kicker mb-4"><span className="dot">●</span>FAQ / 常见疑问</div>
              <h2>关于项目，<br />你可能想问。</h2>
            </div>
            <div className="side" />
          </div>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 40 }}>
            {[
              ["上传需要登录吗？", "浏览和基础上传不需要登录。只有在持续贡献、参与积分、命名提名与志愿审核时，才需要最简化的登录（手机号 / 社交账号）。"],
              ["AI 识别准确吗？", "第一阶段明确为'AI 辅助 + 人工纠偏'，不作科研级精度承诺。AI 只负责给出 Top-3 候选和特征摘要，最终归档由志愿者判断。"],
              ["我的照片会被公开吗？", "经过审核且授权的照片会出现在对应动物档案页和近期观察流中。你保留署名权，可以选择昵称或匿名。"],
              ["为什么不显示精确位置？", "避免引发聚集、过度拍摄或干扰行为。项目遵循'文明观察'原则，只公开大致区域；精确坐标仅留存在审核后台。"],
              ["命名是先到先得吗？", "不是。新个体需先被多次可靠观察、形成基础识别特征后，才开放命名。命名以提案 + 共识为主，避免随意命名和档案混乱。"],
              ["除了梅花鹿还会做别的动物吗？", "会。当前已经扩展到狐狸线索、斑海豹、白尾海雕等首批多物种档案；敏感物种以物种级记录和人工复核为主。"],
            ].map(([q, a], i) => (
              <details key={i} open={i < 2} style={{ background: "var(--paper)", padding: "20px 22px", border: "1px solid var(--rule)", cursor: "pointer" }}>
                <summary style={{ listStyle: "none", fontFamily: "Noto Serif SC, serif", fontSize: 17, color: "var(--ink)", display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                  {q}
                  <span style={{ color: "var(--accent)", fontSize: 18 }}>＋</span>
                </summary>
                <p style={{ fontSize: 13, color: "var(--ink-soft)", lineHeight: 1.7, marginTop: 12 }}>{a}</p>
              </details>
            ))}
          </div>
        </div>
      </section>
    </div>
  );
}

function ReviewPage({ onNav }) {
  const session = window.dzAuth ? window.dzAuth.getSession() : null;
  const isAuthorized = session && (session.role === "admin" || session.role === "volunteer");

  if (!isAuthorized) {
    return (
      <div className="page" style={{ background: "var(--paper-2)", minHeight: "calc(100vh - 60px)" }}>
        <section style={{ padding: "120px 0" }}>
          <div className="app" style={{ maxWidth: 640 }}>
            <div style={{ background: "var(--paper)", border: "1px solid var(--rule)", padding: "56px 48px", textAlign: "center" }}>
              <div className="review-lock-mark">LOCKED</div>
              <div className="kicker mb-3" style={{ justifyContent: "center" }}><span className="dot">●</span>CERTIFIED REVIEWERS ONLY</div>
              <h1 className="serif" style={{ fontSize: 30, lineHeight: 1.25, marginBottom: 16 }}>
                志愿审核台
                <br />
                <span style={{ fontSize: 20, color: "var(--muted)", fontWeight: 400 }}>仅对已认证审核员开放</span>
              </h1>
              <p style={{ fontSize: 14.5, lineHeight: 1.8, color: "var(--ink-soft)", marginBottom: 32, textAlign: "left" }}>
                审核台是“达里尼动物城 · 野生动物档案”里最关键的一环——决定一条观察是否归档到某个动物档案、是否合并进已有个体或物种线索、是否因证据不足需要补拍。为保护数据质量与野生动物本身的安全（例如隐藏敏感地点坐标），审核权限仅授予 <b>完成认证的审核员</b>。
              </p>
              <div style={{ display: "flex", gap: 12, justifyContent: "center", flexWrap: "wrap", marginBottom: 28 }}>
                <button className="btn btn-accent" onClick={() => onNav("admin")}>审核员登录 →</button>
                <button className="btn btn-ghost" onClick={() => onNav("about")}>了解如何成为审核员</button>
              </div>
              <div style={{ paddingTop: 24, borderTop: "1px dashed var(--rule)", fontSize: 12.5, color: "var(--muted)", lineHeight: 1.7, textAlign: "left" }}>
                <b style={{ color: "var(--ink)" }}>认证流程概览：</b>
                <ol style={{ marginTop: 8, marginLeft: 18 }}>
                  <li>累计 10+ 条有效观察上传，AI 初审通过率 ≥ 80%</li>
                  <li>在「参与 · 科普」页提交审核员申请表</li>
                  <li>参加一次线下/视频培训，并签署《文明观察公约》</li>
                  <li>由项目组审核后授予初始片区与试审资格</li>
                </ol>
              </div>
            </div>
          </div>
        </section>
      </div>
    );
  }

  return <ReviewPageInner onNav={onNav} session={session} />;
}

function ReviewPageInner({ onNav, session }) {
  const [active, setActive] = React.useState(0);
  const [activeMedia, setActiveMedia] = React.useState(0);
  const s = window.useStore();
  const queue = s.sightings.filter(o => o.status === "AI 初审" || o.status === "志愿者审核中");
  const cur = queue[Math.min(active, Math.max(0, queue.length - 1))];
  const curDeer = cur?.deerId ? s.deer.find(d => d.id === cur.deerId) : null;
  const curMedia = cur ? getSightingMedia(cur, curDeer) : [];
  const currentMedia = curMedia[Math.min(activeMedia, Math.max(0, curMedia.length - 1))];
  const top3Deer = cur
    ? (cur.aiCandidates?.length
        ? cur.aiCandidates.map(c => ({ deer: s.deer.find(d => d.id === c.id), score: (c.score || 0) / 100, reason: c.reason })).filter(x => x.deer)
        : [curDeer, ...s.deer.filter(d => d.verified && d.id !== cur?.deerId).slice(0, 2)].filter(Boolean).map((d, i) => ({ deer: d, score: [0.82, 0.58, 0.39][i], reason: i === 0 ? "当前归属" : d.tags.slice(0, 2).join(" · ") })))
    : [];

  React.useEffect(() => setActiveMedia(0), [cur?.id]);

  if (!cur) {
    return (
      <div className="page" style={{ background: "var(--paper-2)" }}>
        <section style={{ padding: "96px 0" }}>
          <div className="app" style={{ textAlign: "center" }}>
            <div className="kicker mb-3" style={{ justifyContent: "center" }}><span className="dot">●</span>REVIEW / 队列为空</div>
            <h1 className="serif" style={{ fontSize: 38 }}>当前没有待审核观察。</h1>
            <button className="btn btn-ghost" style={{ marginTop: 24 }} onClick={() => onNav("home")}>返回首页</button>
          </div>
        </section>
      </div>
    );
  }

  return (
    <div className="page" style={{ background: "var(--paper-2)" }}>
      <section style={{ padding: "36px 0 24px", borderBottom: "1px solid var(--rule)", background: "var(--paper)" }}>
        <div className="app">
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", gap: 24, flexWrap: "wrap" }}>
            <div>
              <div className="kicker mb-2"><span className="dot">●</span>ADMIN / 志愿审核台</div>
              <h1 className="serif" style={{ fontSize: 36, lineHeight: 1.15 }}>审核队列 · Queue</h1>
            </div>
            <div style={{ display: "flex", gap: 24, alignItems: "center" }}>
              <div className="stat"><div className="stat-n" style={{ fontSize: 26 }}>{queue.length}</div><div className="stat-l">PENDING</div></div>
              <div className="stat"><div className="stat-n" style={{ fontSize: 26 }}>7</div><div className="stat-l">TODAY</div></div>
              <div className="stat"><div className="stat-n" style={{ fontSize: 26 }}>{s.volunteers.filter(v => v.active).length}</div><div className="stat-l">REVIEWERS</div></div>
              <div style={{ paddingLeft: 16, borderLeft: "1px solid var(--rule)", display: "flex", alignItems: "center", gap: 10 }}>
                <div style={{ textAlign: "right" }}>
                  <div className="mono" style={{ fontSize: 10, color: "var(--muted)", letterSpacing: ".14em" }}>SIGNED IN · {session.role.toUpperCase()}</div>
                  <div style={{ fontSize: 13, fontWeight: 600 }}>{session.username}</div>
                </div>
                <button className="btn btn-ghost btn-sm" onClick={() => onNav("home")}>退出 ←</button>
              </div>
            </div>
          </div>
        </div>
      </section>

      <section style={{ padding: "32px 0" }}>
        <div className="app">
          <div style={{ display: "grid", gridTemplateColumns: "320px 1fr", gap: 24 }}>
            {/* QUEUE */}
            <aside style={{ background: "var(--paper)", border: "1px solid var(--rule)" }}>
              <div style={{ padding: "14px 18px", borderBottom: "1px solid var(--rule)", display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                <span className="mono" style={{ fontSize: 10.5, color: "var(--muted)", letterSpacing: ".14em", textTransform: "uppercase" }}>待处理 / {queue.length} items</span>
                <select className="form-select" style={{ width: "auto", padding: "4px 8px", fontSize: 11 }}>
                  <option>全部</option><option>AI 初审</option><option>志愿者审核中</option>
                </select>
              </div>
              {queue.map((q, i) => (
                <div key={q.id} onClick={() => setActive(i)}
                  style={{ padding: "14px 18px", borderBottom: "1px solid var(--rule-soft)", cursor: "pointer", background: active === i ? "var(--paper-2)" : "transparent", borderLeft: active === i ? "3px solid var(--accent)" : "3px solid transparent" }}>
                  <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
                    <span className="mono" style={{ fontSize: 11, color: "var(--ink)", letterSpacing: ".1em", fontWeight: 600 }}>{q.id}</span>
                    <span className={"chip " + (q.status === "AI 初审" ? "warn" : "candidate")} style={{ fontSize: 10, padding: "2px 8px" }}>
                      {q.status === "AI 初审" ? "AI 初审" : "待人工审"}
                    </span>
                  </div>
                  <div style={{ fontSize: 12.5, color: "var(--ink)", marginTop: 6 }}>{q.loc}</div>
                  <div className="mono" style={{ fontSize: 10.5, color: "var(--muted)", letterSpacing: ".08em", marginTop: 2 }}>
                    {q.time} · {q.contributor}
                  </div>
                  <div style={{ display: "flex", alignItems: "center", gap: 6, marginTop: 8 }}>
                    {(() => {
                      const score = (q.aiCandidates?.[0]?.score || Math.round((q.score || .62) * 100)) / 100;
                      return (
                        <>
                    <div style={{ flex: 1, height: 3, background: "var(--rule-soft)" }}>
                      <div style={{ width: (score * 100) + "%", height: "100%", background: score > .8 ? "var(--ok)" : score > .5 ? "var(--warn)" : "var(--candidate)" }}></div>
                    </div>
                    <span className="mono" style={{ fontSize: 10, color: "var(--muted)" }}>{(score * 100).toFixed(0)}%</span>
                        </>
                      );
                    })()}
                  </div>
                </div>
              ))}
            </aside>

            {/* INSPECTOR */}
            <main style={{ background: "var(--paper)", border: "1px solid var(--rule)", padding: 28 }}>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 20 }}>
                <div>
                  <span className="mono" style={{ fontSize: 11, letterSpacing: ".12em", color: "var(--ink)", fontWeight: 600 }}>{cur.id}</span>
                  <span className="mono" style={{ fontSize: 11, letterSpacing: ".08em", color: "var(--muted)", marginLeft: 14 }}>submitted {cur.time}</span>
                </div>
                <div style={{ display: "flex", gap: 6 }}>
                  <button className="btn btn-ghost btn-sm">上一个</button>
                  <button className="btn btn-ghost btn-sm">下一个 →</button>
                </div>
              </div>

              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 24 }}>
                <div>
                  <div className="form-label">上传图像 · Submitted</div>
                  <MediaPreview media={currentMedia} tone={cur.photoTone || curDeer?.photoTone} aspect="4 / 5" label={cur.loc} />
                  <MediaStrip media={curMedia} active={activeMedia} onPick={setActiveMedia} tone={cur.photoTone || curDeer?.photoTone} />
                  <div className="mt-4" style={{ padding: 14, background: "var(--paper-2)", fontSize: 12.5, color: "var(--ink-soft)", lineHeight: 1.65 }}>
                    <div className="form-label">AI 特征摘要 · Feature summary</div>
                    {cur.aiFeatures?.length ? cur.aiFeatures.join(" · ") : cur.note}
                  </div>
                </div>
                <div>
                  <div className="form-label">Top-3 候选 · Similar individuals</div>
                  <div style={{ display: "grid", gap: 10 }}>
                    {top3Deer.map((item, i) => {
                      const d = item.deer;
                      const score = item.score || [0.78, 0.54, 0.38][i];
                      return (
                        <div key={d.id} style={{ display: "flex", gap: 12, padding: 10, border: "1px solid var(--rule)", background: i === 0 ? "var(--paper-2)" : "transparent" }}>
                          <div style={{ width: 64 }}><MediaPreview media={{ type: "image", url: d.photo, role: "档案主图" }} tone={d.photoTone} aspect="4 / 5" compact /></div>
                          <div style={{ flex: 1 }}>
                            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
                              <div className="serif" style={{ fontSize: 16 }}>{d.name}</div>
                              <div className="mono" style={{ fontSize: 14, color: i === 0 ? "var(--accent)" : "var(--ink)", fontWeight: 600 }}>{(score * 100).toFixed(0)}%</div>
                            </div>
                            <div className="mono" style={{ fontSize: 10, color: "var(--muted)", letterSpacing: ".1em" }}>{d.species || "野生动物"} · {d.id} · {d.sightings} obs</div>
                            <div style={{ fontSize: 11.5, color: "var(--ink-soft)", marginTop: 6 }}>{item.reason || d.tags.slice(0, 2).join(" · ")}</div>
                            <div style={{ display: "flex", gap: 6, marginTop: 8 }}>
                              <button className="btn btn-sm" style={{ fontSize: 10.5, padding: "4px 10px" }} onClick={() => window.dzStore.mergeSighting(cur.id, d.id, session.username)}>合并</button>
                              <button className="btn btn-sm btn-ghost" style={{ fontSize: 10.5, padding: "4px 10px" }} onClick={() => onNav("deer:" + d.id)}>查看档案</button>
                            </div>
                          </div>
                        </div>
                      );
                    })}
                  </div>
                </div>
              </div>

              <hr className="rule" style={{ margin: "28px 0 22px" }} />

              <div className="form-label">审核决定 · Decision</div>
              <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 10 }}>
                {[
                  ["合并到 Top-1", "Merge to top-1", "ok"],
                  ["创建新个体档案", "Create new", "accent"],
                  ["请求补位照片", "Request more", "warn"],
                  ["驳回（无效）", "Reject", "candidate"],
                ].map((a, i) => (
                  <button key={i} className="card" style={{ cursor: "pointer", textAlign: "left", padding: 14 }}>
                    <div className={"status-dot " + a[2]} style={{ marginBottom: 8 }}></div>
                    <div className="serif" style={{ fontSize: 15 }}>{a[0]}</div>
                    <div className="mono" style={{ fontSize: 10, color: "var(--muted)", letterSpacing: ".12em", marginTop: 2 }}>{a[1]}</div>
                  </button>
                ))}
              </div>

              <div style={{ marginTop: 20, padding: 14, fontSize: 12, color: "var(--ink-soft)", lineHeight: 1.6, background: "var(--paper-2)", borderLeft: "3px solid var(--moss)" }}>
                <strong style={{ color: "var(--ink)" }}>审核规则提醒：</strong>人工判断是最终权威。AI 候选仅供参考。如特征模糊或分辨率不足，优先选择"请求补位照片"，不要轻率新建个体。
              </div>
            </main>
          </div>
        </div>
      </section>
    </div>
  );
}

Object.assign(window, { MapPage, AboutPage, ReviewPage });
