/* “后陈经验”知识竞答 · 交互原型
   Screens: start → quiz(10min倒计时) → result(成绩单) → form(信息) → done(抽奖)
   Visual language = 方案A 金华蓝 */
const { useState, useEffect, useRef } = React;

/* ============ Jinhua landmark + scenery helpers ============ */
const AR = { towers: 201/500, pagoda: 288/500, temple: 500/375 };
function LM({ type, h, color, style }) {
  return <img src={`assets/${type}-${color}.png`} alt="" width={h*AR[type]} height={h}
    style={{ display:"block", flex:"none", ...style }} />;
}
function Cloud({ x, y, s=1, o=0.92 }) {
  return (
    <svg width={150*s} height={70*s} viewBox="0 0 150 70" style={{ position:"absolute", left:x, top:y, opacity:o }}>
      <g fill="#ffffff">
        <ellipse cx="45" cy="46" rx="40" ry="23"/><ellipse cx="80" cy="36" rx="34" ry="30"/>
        <ellipse cx="112" cy="48" rx="32" ry="20"/><rect x="28" y="46" width="96" height="20" rx="10"/>
      </g>
    </svg>
  );
}
function Leaf({ x, y, r=0 }) {
  return <div style={{ position:"absolute", left:x, top:y, width:20, height:9, borderRadius:"0 100% 0 100%",
    background:"linear-gradient(135deg,#9BD757,#5FA834)", transform:`rotate(${r}deg)`, opacity:0.9 }} />;
}
/* bottom village + hill + water + skyline scene */
function HillScene({ height=176 }) {
  return (
    <div style={{position:"relative",height,marginTop:6,flex:"none"}}>
      <svg viewBox={`0 0 390 ${height}`} width="100%" height={height} preserveAspectRatio="none" style={{position:"absolute",bottom:0}}>
        <path d={`M0 78 Q70 58 150 72 T300 70 T390 72 L390 ${height} L0 ${height} Z`} fill="#C8EAFB"/>
        <path d={`M0 102 Q90 84 180 98 T390 96 L390 ${height} L0 ${height} Z`} fill="#93CEF1" opacity="0.92"/>
      </svg>
      <div style={{position:"absolute",bottom:44,left:0,right:0,display:"flex",alignItems:"flex-end",justifyContent:"center",gap:2,zIndex:2}}>
        <div style={{width:96,display:"flex",justifyContent:"center",alignItems:"flex-end"}}><LM type="temple" h={60} color="midblue"/></div>
        <div style={{width:64,display:"flex",justifyContent:"center",alignItems:"flex-end"}}><LM type="towers" h={104} color="midblue"/></div>
        <div style={{width:96,display:"flex",justifyContent:"center",alignItems:"flex-end"}}><LM type="pagoda" h={86} color="midblue"/></div>
      </div>
      <svg viewBox={`0 0 390 ${height}`} width="100%" height={height} preserveAspectRatio="none" style={{position:"absolute",bottom:0}}>
        <path d={`M0 120 Q120 88 250 112 T390 106 L390 ${height} L0 ${height} Z`} fill="#86C84E"/>
        <path d={`M0 142 Q140 118 270 136 T390 134 L390 ${height} L0 ${height} Z`} fill="#5FA834"/>
      </svg>
    </div>
  );
}
function SkyDecor({ leaves=true }) {
  return (
    <div style={{position:"absolute",inset:0,overflow:"hidden",zIndex:0,pointerEvents:"none"}}>
      <Cloud x={-34} y={54} s={1.2} o={0.95}/><Cloud x={210} y={28} s={1.45} o={0.85}/>
      <Cloud x={120} y={130} s={1.0} o={0.6}/>
      {leaves && <><Leaf x={300} y={104} r={28}/><Leaf x={66} y={210} r={-20}/></>}
    </div>
  );
}

/* ============ tiny confetti ============ */
function Confetti() {
  const bits = Array.from({length:34});
  const cols = ["#F5B731","#2E8FD8","#5FA834","#E0533D","#7C5CFF","#FFD25A"];
  return (
    <div style={{position:"absolute",inset:0,overflow:"hidden",zIndex:30,pointerEvents:"none"}}>
      {bits.map((_,i)=>{
        const left=Math.random()*100, delay=Math.random()*0.6, dur=2.6+Math.random()*1.3;
        const c=cols[i%cols.length], size=6+Math.random()*6, rot=Math.random()*360;
        return <div key={i} style={{position:"absolute",top:-20,left:`${left}%`,width:size,height:size*0.5,
          background:c,borderRadius:2,transform:`rotate(${rot}deg)`,
          "--confetti-start":`${rot}deg`,
          "--confetti-spin":`${rot + 760 + Math.random()*260}deg`,
          "--confetti-drift":`${Math.round((Math.random()-0.5)*90)}px`,
          animation:`fall ${dur}s ${delay}s ease-in forwards`}}/>;
      })}
    </div>
  );
}

/* ============ utilities ============ */
function pick5() {
  const bank = (window.QUIZ_BANK || []).slice();
  for (let i=bank.length-1;i>0;i--){ const j=Math.floor(Math.random()*(i+1)); [bank[i],bank[j]]=[bank[j],bank[i]]; }
  return bank.slice(0,5);
}
const mmss = s => {
  const n = Math.max(0, Math.floor(Number(s) || 0));
  return `${String(Math.floor(n/60)).padStart(2,"0")}:${String(n%60).padStart(2,"0")}`;
};
const LETTER = ["A","B","C","D"];

/* ============ START ============ */
function StartScreen({ onStart, onRules }) {
  return (
    <div className="screen start-screen" style={{ background:"linear-gradient(180deg,#C2E7FB 0%,#A6D8F6 46%,#90CCF1 100%)" }}>
      <SkyDecor/>
      <div style={{flex:1,display:"flex",flexDirection:"column",padding:"40px 30px 8px",position:"relative",zIndex:3}}>
        <div style={{flex:0.55}}/>
        <h1 className="display-font start-title" style={{textAlign:"center",marginTop:0,lineHeight:1.04,
          background:"linear-gradient(180deg,#2E8FD8,#125FA8)",WebkitBackgroundClip:"text",backgroundClip:"text",color:"transparent",
          filter:"drop-shadow(0 3px 8px rgba(255,255,255,0.6)) drop-shadow(0 6px 10px rgba(20,90,150,0.18))"}}>
          <span className="start-title-line">“后陈经验”</span>
          <span className="start-title-line">知识竞答</span>
        </h1>
        <p style={{textAlign:"center",marginTop:16,fontSize:15,color:"#196299",fontWeight:600,lineHeight:1.7}}>
          《金华市“后陈经验”传承发展条例》<br/>全民答题 · 全对获抽奖资格 · 共赴善治之约</p>

        <div style={{display:"flex",justifyContent:"center",marginTop:24,background:"rgba(255,255,255,0.62)",
          borderRadius:18,padding:"12px 4px",boxShadow:"0 8px 20px rgba(30,120,190,0.14)"}}>
          {[["5","随机抽题"],["10分钟","限时作答"]].map(([n,l],i)=>(
            <div key={i} style={{flex:1,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",borderRight:i<1?"1px solid rgba(30,120,190,0.18)":"none"}}>
              <div className="display-font" style={{fontSize:30,lineHeight:1,height:32,display:"flex",alignItems:"center",color:"#1E86D0"}}>{n}</div>
              <div style={{fontSize:13,color:"#5A87A8",marginTop:5}}>{l}</div>
            </div>
          ))}
        </div>
        <div style={{flex:1,minHeight:30}}/>
        <button className="press" onClick={onStart} style={{margin:"0 0 22px",height:58,borderRadius:30,border:"none",cursor:"pointer",
          background:"linear-gradient(90deg,#FFD25A,#F5B731)",color:"#7A4400",fontWeight:900,fontSize:19,letterSpacing:4,
          boxShadow:"0 8px 16px rgba(214,150,20,0.26)"}}>开 始 答 题</button>
        <div onClick={onRules} style={{textAlign:"center",fontSize:14.5,color:"#2E7AB0",fontWeight:600,cursor:"pointer"}}>
          📋 答题须知 ›</div>
        <div style={{textAlign:"center",fontSize:13,color:"#3D7CAA",marginTop:8}}>
          活动时间：6 月 15 日 10:00 — 6 月 22 日 22:00</div>
        <div style={{textAlign:"center",fontSize:13,color:"#6CA0C4",marginTop:14,lineHeight:1.9}}>
          <div>主办单位：中共金华市委社会工作部</div>
          <div>赞助单位：中国电信股份有限公司金华分公司</div>
        </div>
      </div>
      <HillScene/>
    </div>
  );
}

/* ============ QUIZ ============ */
function QuizScreen({ questions, answers, setAnswers, current, setCurrent, timeLeft, onExit, onSubmit, submitting }) {
  const q = questions[current];
  const picked = answers[current];
  const choose = v => { const a=answers.slice(); a[current]=v; setAnswers(a); };
  const answeredCount = answers.filter(a=>a!==null && a!==undefined).length;
  const low = timeLeft <= 60;

  return (
    <div className="screen" style={{ background:"linear-gradient(180deg,#DCF0FC 0%,#C2E7FB 100%)" }}>
      <SkyDecor leaves={false}/>
      {/* top bar */}
      <div style={{position:"relative",zIndex:5,padding:"40px 20px 0"}}>
        <div style={{position:"relative",height:36,display:"flex",alignItems:"center"}}>
          <div onClick={onExit} className="press" style={{position:"absolute",left:0,width:34,height:34,borderRadius:"50%",background:"rgba(255,255,255,0.8)",
            display:"flex",alignItems:"center",justifyContent:"center",color:"#1E7FD0",fontSize:18,cursor:"pointer",boxShadow:"0 2px 8px rgba(30,120,190,0.18)"}}>✕</div>
          <div style={{position:"absolute",left:0,right:0,textAlign:"center",pointerEvents:"none",fontSize:14.5,color:"#2E7AB0",fontWeight:700}}>
            第 <span style={{color:"#125FA8",fontSize:16}}>{current+1}</span> / {questions.length} 题</div>
          <div style={{position:"absolute",right:0,display:"flex",alignItems:"center",gap:6,background:low?"#FCE4E0":"#fff",color:low?"#D8412B":"#125FA8",
            fontWeight:800,fontSize:15,borderRadius:18,padding:"6px 12px",boxShadow:"0 2px 8px rgba(30,120,190,0.18)",fontVariantNumeric:"tabular-nums"}}>
            <span style={{fontSize:14.5}}>⏱</span>{mmss(timeLeft)}</div>
        </div>
      </div>

      {/* progress dots */}
      <div style={{position:"relative",zIndex:5,display:"flex",gap:6,justifyContent:"center",padding:"14px 20px 0"}}>
        {questions.map((_,i)=>{
          const done = answers[i]!==null && answers[i]!==undefined;
          const cur = i===current;
          return <div key={i} onClick={()=>setCurrent(i)} className="press" style={{height:6,flex:1,maxWidth:46,borderRadius:3,cursor:"pointer",
            background: cur ? "#125FA8" : done ? "#5FB0E8" : "rgba(255,255,255,0.85)"}}/>;
        })}
      </div>

      {/* question card */}
      <div style={{position:"relative",zIndex:5,flex:1,overflowY:"auto",padding:"16px 18px 12px"}}>
        <div style={{background:"#fff",borderRadius:22,padding:"20px 18px 22px",boxShadow:"0 12px 30px rgba(30,110,180,0.16)"}}>
          <div style={{display:"flex",alignItems:"center",gap:8,marginBottom:14}}>
            <span style={{fontSize:13.5,fontWeight:800,color:"#fff",borderRadius:8,padding:"3px 10px",
              background: q.type==="single" ? "linear-gradient(90deg,#3AA0E4,#1E7FD0)" : "linear-gradient(90deg,#34B98A,#1E9E72)"}}>
              {q.type==="single" ? "单选题" : "判断题"}</span>
            <span style={{fontSize:13.5,color:"#9CB4C6"}}>{q.type==="single" ? "请选择唯一正确答案" : "请判断对错"}</span>
          </div>
          <div style={{fontSize:18,lineHeight:1.6,color:"#1B3A52",fontWeight:600,marginBottom:18,textWrap:"pretty"}}>{q.q}</div>

          {q.type==="single" ? (
            <div style={{display:"flex",flexDirection:"column",gap:11}}>
              {q.options.map((opt,i)=>{
                const sel = picked===i;
                return (
                  <div key={i} onClick={()=>choose(i)} className="press opt" style={{display:"flex",alignItems:"center",gap:13,
                    border:`2px solid ${sel?"#1E86D0":"#E2ECF4"}`, background:sel?"#EAF5FE":"#fff",
                    borderRadius:15,padding:"13px 14px",cursor:"pointer",transition:"all .15s"}}>
                    <div style={{width:28,height:28,borderRadius:"50%",flex:"none",display:"flex",alignItems:"center",justifyContent:"center",
                      fontWeight:800,fontSize:15,color:sel?"#fff":"#6E8DA3",background:sel?"#1E86D0":"#EEF3F8"}}>{LETTER[i]}</div>
                    <div style={{fontSize:15,color:"#28435A",lineHeight:1.5,fontWeight:sel?600:400}}>{opt}</div>
                  </div>
                );
              })}
            </div>
          ) : (
            <div style={{display:"flex",gap:14}}>
              {[{v:true,t:"正确",sym:"✓",c:"#1E9E72",bg:"#E7F7F0"},{v:false,t:"错误",sym:"✗",c:"#E0533D",bg:"#FCEBE7"}].map(o=>{
                const sel=picked===o.v;
                return (
                  <div key={String(o.v)} onClick={()=>choose(o.v)} className="press" style={{flex:1,borderRadius:16,cursor:"pointer",
                    border:`2px solid ${sel?o.c:"#E2ECF4"}`, background:sel?o.bg:"#fff", padding:"22px 0", textAlign:"center",transition:"all .15s"}}>
                    <div style={{width:46,height:46,margin:"0 auto 8px",borderRadius:"50%",display:"flex",alignItems:"center",justifyContent:"center",
                      fontSize:24,fontWeight:900,color:"#fff",background:sel?o.c:"#C9D8E4"}}>{o.sym}</div>
                    <div style={{fontSize:16,fontWeight:700,color:sel?o.c:"#5A7B8C"}}>{o.t}</div>
                  </div>
                );
              })}
            </div>
          )}
        </div>
      </div>

      {/* bottom nav */}
      <div style={{position:"relative",zIndex:5,display:"flex",gap:12,padding:"6px 18px 26px",alignItems:"center"}}>
        <button disabled={current===0} onClick={()=>setCurrent(current-1)} className="press" style={{flex:1,height:50,borderRadius:25,
          border:"none",cursor:current===0?"default":"pointer",background:current===0?"rgba(255,255,255,0.5)":"#fff",
          color:current===0?"#A9C2D4":"#1E7FD0",fontWeight:700,fontSize:15,boxShadow:current===0?"none":"0 4px 12px rgba(30,120,190,0.16)"}}>上一题</button>
        {current < questions.length-1 ? (
          <button onClick={()=>setCurrent(current+1)} className="press" style={{flex:1,height:50,borderRadius:25,border:"none",cursor:"pointer",
            background:"linear-gradient(90deg,#3AA0E4,#1E7FD0)",color:"#fff",fontWeight:800,fontSize:16,boxShadow:"0 8px 20px rgba(30,127,208,0.34)"}}>下一题</button>
        ) : (
          <button onClick={()=>onSubmit()} disabled={submitting} className="press" style={{flex:1,height:50,borderRadius:25,border:"none",cursor:submitting?"wait":"pointer",
            background:"linear-gradient(90deg,#FFD25A,#F5B731)",color:"#7A4400",fontWeight:900,fontSize:16,letterSpacing:2,
            opacity:submitting?0.75:1,boxShadow:"0 8px 20px rgba(214,150,20,0.42)"}}>{submitting?"提交中…":`交卷 (${answeredCount}/${questions.length})`}</button>
        )}
      </div>
    </div>
  );
}

/* ============ RESULT (成绩单) ============ */
function ResultScreen({ questions, answers, timeUsed, result, onForm, onRetry, onHome }) {
  const fallbackCorrect = questions.reduce((n,q,i)=> n + (q.answer !== undefined && answers[i]===q.answer ? 1 : 0), 0);
  const correct = result ? result.correct : fallbackCorrect;
  const total = result ? result.total : questions.length;
  const allRight = correct===total;
  const score = result ? result.score : Math.round(correct/total*100);
  const reviewMap = new Map((result && result.review || []).map(r => [r.id, r]));
  const incorrectReviews = questions.map((q,i)=>{
    const review = reviewMap.get(q.id);
    const right = review ? review.right : answers[i]===q.answer;
    return {q,i,review,right};
  }).filter(item => !item.right);
  const eligibilityStatus = result && result.eligibilityStatus || (allRight ? "new" : "none");
  const existingEligibility = allRight && eligibilityStatus==="existing";

  return (
    <div className="screen" style={{ background:"linear-gradient(180deg,#DCF0FC 0%,#C2E7FB 100%)" }}>
      {allRight && <Confetti/>}
      <SkyDecor leaves={false}/>
      <div style={{position:"relative",zIndex:5,flex:1,overflowY:"auto",padding:"44px 18px 24px"}}>
        {/* score hero */}
        <div style={{background:allRight?"linear-gradient(180deg,#2E8FD8,#125FA8)":"linear-gradient(180deg,#5BA7DD,#3E86C0)",
          borderRadius:26,padding:"26px 22px 24px",textAlign:"center",color:"#fff",boxShadow:"0 14px 34px rgba(20,90,150,0.3)",position:"relative",overflow:"hidden"}}>
          <div style={{fontSize:15,fontWeight:600,opacity:0.9,letterSpacing:1}}>{allRight ? "🎉 恭喜！全部答对" : "本次成绩"}</div>
          <div style={{display:"flex",alignItems:"baseline",justifyContent:"center",gap:4,marginTop:6}}>
            <span className="display-font" style={{fontSize:72,lineHeight:1,color:"#FFE08A"}}>{correct}</span>
            <span style={{fontSize:24,fontWeight:700,opacity:0.85}}>/ {total}</span>
          </div>
          <div style={{display:"flex",justifyContent:"center",gap:18,marginTop:14,fontSize:14.5}}>
            <span>得分 <b style={{fontSize:16,color:"#FFE08A"}}>{score}</b></span>
            <span style={{opacity:0.5}}>|</span>
            <span>用时 <b style={{fontSize:16,color:"#FFE08A",fontVariantNumeric:"tabular-nums"}}>{mmss(timeUsed)}</b></span>
          </div>
        </div>

        {/* eligibility / CTA */}
        {allRight && !existingEligibility ? (
          <div style={{marginTop:16,background:"#FFF6E2",border:"1.5px solid #F5D58A",borderRadius:18,padding:"16px 16px"}}>
            <div style={{fontSize:15,fontWeight:800,color:"#9A6800",marginBottom:4}}>🎁 您已获得抽奖资格</div>
            <div style={{fontSize:14,color:"#A77F33",lineHeight:1.6}}>全部答对即可获得抽奖资格。活动截止后，将从全部答对人员中随机抽取 100 名赠送精美小礼品。</div>
            <button onClick={onForm} className="press" style={{width:"100%",height:50,marginTop:14,borderRadius:25,border:"none",cursor:"pointer",
              background:"linear-gradient(90deg,#FFD25A,#F5B731)",color:"#7A4400",fontWeight:900,fontSize:16,letterSpacing:2,
              boxShadow:"0 8px 18px rgba(214,150,20,0.4)"}}>确认获得资格</button>
          </div>
        ) : existingEligibility ? (
          <div style={{marginTop:16,background:"#FFF6E2",border:"1.5px solid #F5D58A",borderRadius:18,padding:"16px"}}>
            <div style={{fontSize:15.5,fontWeight:800,color:"#9A6800",marginBottom:4}}>您已具有抽奖资格</div>
            <div style={{fontSize:14,color:"#A77F33",lineHeight:1.6}}>感谢参与，本次满分记录已保存。本次不再重复计入抽奖池，每个手机号在活动期间最多拥有一次抽奖机会。</div>
            <button onClick={onHome} className="press" style={{width:"100%",height:50,marginTop:14,borderRadius:25,border:"none",cursor:"pointer",
              background:"linear-gradient(90deg,#3AA0E4,#1E7FD0)",color:"#fff",fontWeight:800,fontSize:16,boxShadow:"0 8px 18px rgba(30,127,208,0.32)"}}>感谢参与，返回首页</button>
          </div>
        ) : (
          <div style={{marginTop:16,background:"#fff",borderRadius:18,padding:"16px",boxShadow:"0 8px 20px rgba(30,110,180,0.12)"}}>
            <div style={{fontSize:15.5,fontWeight:700,color:"#28435A",marginBottom:4}}>请明日再来</div>
            <div style={{fontSize:14,color:"#7B95A8",lineHeight:1.6}}>本次未获得抽奖资格。请明日再来，答错题目的正确答案与解析已在下方展示，每人每日可答题 1 次。</div>
            <button onClick={onRetry} className="press" style={{width:"100%",height:50,marginTop:14,borderRadius:25,border:"none",cursor:"pointer",
              background:"linear-gradient(90deg,#3AA0E4,#1E7FD0)",color:"#fff",fontWeight:800,fontSize:16,boxShadow:"0 8px 18px rgba(30,127,208,0.32)"}}>返回主页</button>
          </div>
        )}

        {/* incorrect answers only */}
        {incorrectReviews.length > 0 && (
          <>
            <div style={{marginTop:22,marginBottom:8,display:"flex",alignItems:"center",gap:8}}>
              <div style={{width:4,height:16,borderRadius:2,background:"#1E7FD0"}}/>
              <div style={{fontSize:15,fontWeight:800,color:"#1B3A52"}}>答题情况</div>
            </div>
            <div style={{display:"flex",flexDirection:"column",gap:12}}>
              {incorrectReviews.map(({q,i,review})=>(
                <ReviewItem key={q.id} q={q} idx={i} user={answers[i]}
                  rightOverride={false}
                  correctOverride={review ? review.correctAnswer : undefined}
                  explanationOverride={review ? review.explanation : undefined}/>
              ))}
            </div>
          </>
        )}

        {allRight && !existingEligibility && <div onClick={onHome} className="press" style={{textAlign:"center",marginTop:20,fontSize:14.5,color:"#2E7AB0",fontWeight:600,cursor:"pointer"}}>返回首页</div>}
      </div>
    </div>
  );
}

function ReviewItem({ q, idx, user, rightOverride, correctOverride, explanationOverride }) {
  const right = rightOverride !== undefined ? rightOverride : user===q.answer;
  const showAnalysis = !right;
  const correct = correctOverride !== undefined ? correctOverride : q.answer;
  const explanation = explanationOverride !== undefined ? explanationOverride : (q.src || "");
  const ansText = a => {
    if(a==null) return "未作答";
    if(q.type==="single") return q.options[a] !== undefined ? `${LETTER[a]}. ${q.options[a]}` : `第 ${Number(a)+1} 项`;
    return a ? "正确" : "错误";
  };
  return (
    <div style={{background:"#fff",borderRadius:16,padding:"15px 15px 16px",boxShadow:"0 6px 16px rgba(30,110,180,0.1)",
      borderLeft:`4px solid ${right?"#2EA86A":"#E0533D"}`}}>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:8}}>
        <span style={{fontSize:13.5,color:"#9CB4C6",fontWeight:700}}>第 {idx+1} 题 · {q.type==="single"?"单选":"判断"}</span>
        <span style={{fontSize:13.5,fontWeight:800,color:right?"#2EA86A":"#E0533D",display:"flex",alignItems:"center",gap:4,whiteSpace:"nowrap",flex:"none"}}>
          {right?"✓ 答对":"✗ 答错"}</span>
      </div>
      <div style={{fontSize:15,lineHeight:1.55,color:"#28435A",fontWeight:600,marginBottom:10,textWrap:"pretty"}}>{q.q}</div>
      <div style={{display:"flex",flexDirection:"column",gap:6}}>
        <div style={{background:right?"#F2FBF6":"#FFF4F1",borderRadius:10,padding:"9px 12px",fontSize:14,color:right?"#2E8B5D":"#C7472F",lineHeight:1.55}}>
          你的答案：{ansText(user)}
        </div>
        {showAnalysis && (
          <>
            <div style={{background:"#F2F8FD",borderRadius:10,padding:"9px 12px",fontSize:14,color:"#1E6FA8",lineHeight:1.55,fontWeight:700}}>
              正确答案：{ansText(correct)}
            </div>
            {explanation && (
              <div style={{background:"#FFF9EA",borderRadius:10,padding:"9px 12px",fontSize:14,color:"#8A641B",lineHeight:1.6}}>
                <b>答案解析：</b>{explanation}
              </div>
            )}
          </>
        )}
      </div>
    </div>
  );
}

/* ============ FORM (信息) ============ */
const REGION = {
  "浙江省": {
    "金华市": ["婺城区","金东区","武义县","浦江县","磐安县","兰溪市","义乌市","东阳市","永康市"],
    "杭州市": ["上城区","拱墅区","西湖区","滨江区","萧山区","余杭区","临平区","钱塘区","富阳区","临安区","桐庐县","淳安县","建德市"],
    "宁波市": ["海曙区","江北区","北仑区","镇海区","鄞州区","奉化区","余姚市","慈溪市","宁海县","象山县"],
    "温州市": ["鹿城区","龙湾区","瓯海区","洞头区","永嘉县","平阳县","苍南县","文成县","泰顺县","瑞安市","乐清市","龙港市"],
    "绍兴市": ["越城区","柯桥区","上虞区","新昌县","诸暨市","嵊州市"],
    "台州市": ["椒江区","黄岩区","路桥区","三门县","天台县","仙居县","温岭市","临海市","玉环市"],
    "嘉兴市": ["南湖区","秀洲区","嘉善县","海盐县","海宁市","平湖市","桐乡市"],
    "湖州市": ["吴兴区","南浔区","德清县","长兴县","安吉县"],
    "衢州市": ["柯城区","衢江区","常山县","开化县","龙游县","江山市"],
    "丽水市": ["莲都区","青田县","缙云县","遂昌县","松阳县","云和县","庆元县","景宁县","龙泉市"],
    "舟山市": ["定海区","普陀区","岱山县","嵊泗县"],
  },
  "上海市": { "上海市": ["黄浦区","徐汇区","长宁区","静安区","普陀区","虹口区","杨浦区","闵行区","宝山区","嘉定区","浦东新区","金山区","松江区","青浦区","奉贤区","崇明区"] },
  "江苏省": {
    "南京市": ["玄武区","秦淮区","建邺区","鼓楼区","浦口区","栖霞区","雨花台区","江宁区","六合区","溧水区","高淳区"],
    "苏州市": ["姑苏区","虎丘区","吴中区","相城区","吴江区","昆山市","常熟市","张家港市","太仓市"],
    "无锡市": ["梁溪区","锡山区","惠山区","滨湖区","新吴区","江阴市","宜兴市"],
  },
  "安徽省": {
    "合肥市": ["瑶海区","庐阳区","蜀山区","包河区","长丰县","肥东县","肥西县","庐江县","巢湖市"],
    "黄山市": ["屯溪区","黄山区","徽州区","歙县","休宁县","黟县","祁门县"],
  },
  "北京市": { "北京市": ["东城区","西城区","朝阳区","海淀区","丰台区","石景山区","门头沟区","房山区","通州区","顺义区","昌平区","大兴区","怀柔区","平谷区","密云区","延庆区"] },
};
const USER_PROFILES = ["机关干部","企事业单位人员","村（社区）工作人员","其他人员"];

function FormScreen({ onSubmit, onBack, prefill, onConsumePrefill, onShowDisclaimer }) {
  const [name,setName]=useState(""); const [phone,setPhone]=useState("");
  const [profile,setProfile]=useState("");
  const [prov,setProv]=useState("浙江省"); const [city,setCity]=useState("金华市"); const [dist,setDist]=useState("婺城区");
  const [detail,setDetail]=useState("");
  const [agree,setAgree]=useState(true); const [err,setErr]=useState({});
  const provList = Object.keys(REGION);
  const cityList = Object.keys(REGION[prov] || {});
  const distList = (REGION[prov] && REGION[prov][city]) || [];
  const onProv = v => { setProv(v); const c=Object.keys(REGION[v])[0]; setCity(c); setDist(REGION[v][c][0]); };
  const onCity = v => { setCity(v); setDist(REGION[prov][v][0]); };
  // DEV：开发者面板「填入测试信息」注入 prefill，就地把可见输入框填好（不提交）
  useEffect(()=>{
    if(!prefill) return;
    setName(prefill.name||""); setPhone(prefill.phone||"");
    setProfile(prefill.profile||"");
    if(prefill.prov) setProv(prefill.prov);
    if(prefill.city) setCity(prefill.city);
    if(prefill.dist) setDist(prefill.dist);
    setDetail(prefill.detail||""); setAgree(true); setErr({});
    onConsumePrefill && onConsumePrefill();
  },[prefill]);
  const submit = () => {
    const e={};
    if(!name.trim()) e.name="请填写姓名";
    if(!/^1\d{10}$/.test(phone.trim())) e.phone="请填写11位手机号";
    if(!USER_PROFILES.includes(profile)) e.profile="请选择身份";
    if(detail.trim().length<4) e.detail="请填写详细地址（街道、门牌号等）";
    if(!agree) e.agree="请先同意";
    setErr(e);
    if(Object.keys(e).length===0) onSubmit({name:name.trim(),phone:phone.trim(),profile,prov,city,dist,detail:detail.trim()});
  };
  const field = (label,val,set,key,ph,extra={}) => (
    <div style={{marginBottom:16}}>
      <div style={{fontSize:14.5,fontWeight:700,color:"#28435A",marginBottom:7}}>{label} <span style={{color:"#E0533D"}}>*</span></div>
      <input value={val} onChange={e=>set(e.target.value)} placeholder={ph} {...extra}
        style={{width:"100%",height:48,borderRadius:13,border:`1.5px solid ${err[key]?"#E0533D":"#DCE8F2"}`,
          padding:"0 14px",fontSize:15,color:"#28435A",outline:"none",background:"#F8FBFE",fontFamily:"inherit"}}/>
      {err[key] && <div style={{fontSize:13.5,color:"#E0533D",marginTop:5}}>{err[key]}</div>}
    </div>
  );
  return (
    <div className="screen" style={{ background:"linear-gradient(180deg,#DCF0FC 0%,#C2E7FB 100%)" }}>
      <SkyDecor leaves={false}/>
      <div style={{position:"relative",zIndex:5,padding:"40px 20px 0",display:"flex",alignItems:"center",gap:12}}>
        <div onClick={onBack} className="press" style={{width:34,height:34,borderRadius:"50%",background:"rgba(255,255,255,0.8)",
          display:"flex",alignItems:"center",justifyContent:"center",color:"#1E7FD0",fontSize:20,cursor:"pointer",boxShadow:"0 2px 8px rgba(30,120,190,0.18)"}}>‹</div>
        <div style={{fontSize:16,fontWeight:800,color:"#1B3A52"}}>填写参与信息</div>
      </div>
      <div style={{position:"relative",zIndex:5,flex:1,overflowY:"auto",padding:"18px 18px 24px"}}>
        <div style={{background:"#fff",borderRadius:20,padding:"20px 18px",boxShadow:"0 12px 30px rgba(30,110,180,0.14)"}}>
          <div style={{display:"flex",gap:8,alignItems:"center",background:"#EAF5FE",borderRadius:12,padding:"10px 12px",marginBottom:18}}>
            <span style={{fontSize:16}}>🎁</span>
            <span style={{fontSize:14,color:"#1E6FA8",lineHeight:1.5}}>答题前请准确填写信息，中奖人员将据此邮寄礼品。</span>
          </div>
          {field("姓名",name,setName,"name","请输入真实姓名")}
          {field("手机号",phone,setPhone,"phone","用于中奖通知",{type:"tel",maxLength:11,inputMode:"numeric"})}
          <div style={{marginBottom:16}}>
            <div style={{fontSize:14.5,fontWeight:700,color:"#28435A",marginBottom:7}}>身份 <span style={{color:"#E0533D"}}>*</span></div>
            <div style={{position:"relative"}}>
              <select value={profile} onChange={e=>setProfile(e.target.value)} style={{width:"100%",height:48,borderRadius:13,
                border:`1.5px solid ${err.profile?"#E0533D":"#DCE8F2"}`,background:"#F8FBFE",padding:"0 34px 0 13px",fontSize:15,color:profile?"#28435A":"#A9C2D4",
                outline:"none",appearance:"none",WebkitAppearance:"none",fontFamily:"inherit",cursor:"pointer"}}>
                <option value="">请选择身份</option>
                {USER_PROFILES.map(o=><option key={o} value={o}>{o}</option>)}
              </select>
              <span style={{position:"absolute",right:13,top:"50%",transform:"translateY(-50%)",pointerEvents:"none",color:"#7FA4C0",fontSize:12}}>▼</span>
            </div>
            {err.profile && <div style={{fontSize:13.5,color:"#E0533D",marginTop:5}}>{err.profile}</div>}
          </div>
          {/* 收件地址：省 / 市 / 区 + 详细地址 */}
          <div style={{marginBottom:16}}>
            <div style={{fontSize:14.5,fontWeight:700,color:"#28435A",marginBottom:7}}>收件地址 <span style={{color:"#E0533D"}}>*</span></div>
            <div style={{display:"flex",gap:8,marginBottom:10}}>
              {[{val:prov,on:onProv,list:provList},{val:city,on:onCity,list:cityList},{val:dist,on:setDist,list:distList}].map((s,i)=>(
                <div key={i} style={{flex:1,position:"relative",minWidth:0}}>
                  <select value={s.val} onChange={e=>s.on(e.target.value)} style={{width:"100%",height:48,borderRadius:13,
                    border:"1.5px solid #DCE8F2",background:"#F8FBFE",padding:"0 24px 0 11px",fontSize:15,color:"#28435A",
                    outline:"none",appearance:"none",WebkitAppearance:"none",fontFamily:"inherit",cursor:"pointer"}}>
                    {s.list.map(o=><option key={o} value={o}>{o}</option>)}
                  </select>
                  <span style={{position:"absolute",right:9,top:"50%",transform:"translateY(-50%)",pointerEvents:"none",color:"#7FA4C0",fontSize:11}}>▼</span>
                </div>
              ))}
            </div>
            <input value={detail} onChange={e=>setDetail(e.target.value)} placeholder="街道、门牌号、楼栋等详细地址"
              style={{width:"100%",height:48,borderRadius:13,border:`1.5px solid ${err.detail?"#E0533D":"#DCE8F2"}`,
                padding:"0 14px",fontSize:15,color:"#28435A",outline:"none",background:"#F8FBFE",fontFamily:"inherit"}}/>
            {err.detail && <div style={{fontSize:13.5,color:"#E0533D",marginTop:5}}>{err.detail}</div>}
          </div>
          <div onClick={()=>setAgree(!agree)} style={{display:"flex",alignItems:"flex-start",gap:9,cursor:"pointer",marginTop:4}}>
            <div style={{width:19,height:19,borderRadius:6,flex:"none",marginTop:1,border:`2px solid ${agree?"#1E86D0":"#C2D3E0"}`,
              background:agree?"#1E86D0":"#fff",display:"flex",alignItems:"center",justifyContent:"center",color:"#fff",fontSize:13.5}}>{agree?"✓":""}</div>
            <span style={{fontSize:13.5,color:"#6B8598",lineHeight:1.6}}>我已阅读并同意<span onClick={e=>{e.stopPropagation(); onShowDisclaimer&&onShowDisclaimer();}} style={{color:"#1E7FD0",fontWeight:600}}>《免责声明与个人信息使用须知》</span>，同意活动组织方为本次活动使用上述信息。</span>
          </div>
          {err.agree && <div style={{fontSize:13.5,color:"#E0533D",marginTop:6}}>{err.agree}</div>}
        </div>
        <button onClick={submit} className="press" style={{width:"100%",height:54,marginTop:18,borderRadius:27,border:"none",cursor:"pointer",
          background:"linear-gradient(90deg,#FFD25A,#F5B731)",color:"#7A4400",fontWeight:900,fontSize:17,letterSpacing:2,
          boxShadow:"0 10px 22px rgba(214,150,20,0.42)"}}>提交并开始答题</button>
      </div>
    </div>
  );
}

/* ============ DONE (资格确认) ============ */
function DoneScreen({ onHome }) {
  return (
    <div className="screen" style={{ background:"linear-gradient(180deg,#C2E7FB 0%,#A6D8F6 46%,#90CCF1 100%)" }}>
      <Confetti/>
      <SkyDecor/>
      <div style={{position:"relative",zIndex:5,flex:1,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",padding:"0 30px"}}>
        <div style={{width:150,height:150,borderRadius:"50%",background:"linear-gradient(135deg,#FFD25A,#F5B731)",
          display:"flex",alignItems:"center",justifyContent:"center",boxShadow:"0 18px 40px rgba(30,110,180,0.34)",border:"6px solid #fff",
          animation:"pop 0.4s ease"}}>
          <span style={{fontSize:64}}>🎉</span>
        </div>
        <div className="display-font" style={{fontSize:30,color:"#125FA8",marginTop:28}}>您已获得抽奖资格</div>
        <p style={{textAlign:"center",fontSize:15,color:"#196299",fontWeight:600,lineHeight:1.8,marginTop:12,maxWidth:280}}>
          成绩已提交。活动结束后，中奖名单将统一公布，并陆续邮寄礼品，敬请关注。</p>
        <div style={{marginTop:8,background:"rgba(255,255,255,0.7)",borderRadius:14,padding:"10px 18px",fontSize:14,color:"#2E7AB0",fontWeight:600}}>
          学条例 · 懂监督 · 践初心 · 促善治</div>
        <button onClick={onHome} className="press" style={{marginTop:30,height:50,padding:"0 40px",borderRadius:25,border:"none",cursor:"pointer",
          background:"linear-gradient(90deg,#3AA0E4,#1E7FD0)",color:"#fff",fontWeight:800,fontSize:15,boxShadow:"0 8px 20px rgba(30,127,208,0.34)"}}>返回首页</button>
      </div>
      <HillScene height={150}/>
    </div>
  );
}

/* ============ RULES modal ============ */
function RulesModal({ onClose }) {
  return (
    <div onClick={onClose} style={{position:"absolute",inset:0,zIndex:40,background:"rgba(16,48,80,0.42)",display:"flex",alignItems:"flex-end"}}>
      <div onClick={e=>e.stopPropagation()} style={{background:"#fff",width:"100%",borderRadius:"24px 24px 0 0",padding:"22px 22px 30px",
        animation:"slideUp .28s ease"}}>
        <div style={{width:40,height:4,borderRadius:2,background:"#D8E4EE",margin:"0 auto 16px"}}/>
        <div style={{fontSize:18,fontWeight:800,color:"#1B3A52",marginBottom:14}}>答题须知</div>
        {[
          ["📝","系统随机抽取 5 道题（单选 + 判断），限时 10 分钟。"],
          ["✅","全部答对即可获得抽奖资格。"],
          ["🎁","活动截止后，将从全部答对人员中随机抽取 100 名，赠送精美小礼品一份。"],
          ["📮","答题前请准确填写姓名、手机号、收件地址，以便礼品发放。"],
          ["🔁","每人每日可答题 1 次；每个手机号在活动期间最多获得一次抽奖资格，不重复增加抽奖机会。活动时间 6 月 15 日 10:00 — 6 月 22 日 22:00。"],
        ].map(([e,t],i)=>(
          <div key={i} style={{display:"flex",gap:11,marginBottom:13,alignItems:"flex-start"}}>
            <span style={{fontSize:17,flex:"none"}}>{e}</span>
            <span style={{fontSize:15,color:"#4C6678",lineHeight:1.6}}>{t}</span>
          </div>
        ))}
        <button onClick={onClose} className="press" style={{width:"100%",height:50,marginTop:8,borderRadius:25,border:"none",cursor:"pointer",
          background:"linear-gradient(90deg,#3AA0E4,#1E7FD0)",color:"#fff",fontWeight:800,fontSize:16,boxShadow:"0 8px 18px rgba(30,127,208,0.3)"}}>我知道了</button>
      </div>
    </div>
  );
}

/* ============ DISCLAIMER 免责声明 ============ */
function DisclaimerModal({ onClose }) {
  const clause = (n, t) => (
    <div style={{display:"flex",gap:9,marginBottom:11,alignItems:"flex-start"}}>
      <span style={{flex:"none",width:18,height:18,borderRadius:"50%",background:"#EAF2FA",color:"#1E7FD0",fontSize:13,fontWeight:800,display:"flex",alignItems:"center",justifyContent:"center",marginTop:1}}>{n}</span>
      <span style={{fontSize:14,color:"#4C6678",lineHeight:1.65}}>{t}</span>
    </div>
  );
  return (
    <div onClick={onClose} style={{position:"absolute",inset:0,zIndex:40,background:"rgba(16,48,80,0.42)",display:"flex",alignItems:"flex-end"}}>
      <div onClick={e=>e.stopPropagation()} style={{background:"#fff",width:"100%",borderRadius:"24px 24px 0 0",padding:"22px 22px 26px",animation:"slideUp .28s ease",maxHeight:"86%",display:"flex",flexDirection:"column"}}>
        <div style={{width:40,height:4,borderRadius:2,background:"#D8E4EE",margin:"0 auto 16px",flex:"none"}}/>
        <div style={{fontSize:18,fontWeight:800,color:"#1B3A52",marginBottom:4,flex:"none"}}>免责声明与个人信息使用须知</div>
        <div style={{overflowY:"auto",flex:1,paddingRight:2}}>
          {clause(1,"自愿参与：本次“后陈经验”知识竞答活动由参与者自愿参加，参与即视为已阅读并同意本声明全部内容。")}
          {clause(2,"信息用途：您填写的姓名、手机号、身份、收件地址仅用于本次活动的中奖通知、礼品邮寄与参与情况统计。活动组织方将依法对上述信息予以保密，不用于其他用途、不向无关第三方提供，并在活动结束后按相关规定及时删除或匿名化处理。")}
          {clause(3,"信息真实：请确保所填信息真实、准确、有效。因信息有误、虚假或填写他人信息，导致无法联系、礼品无法送达或资格被取消的，责任由参与者自行承担。")}
          {clause(4,"抽奖规则：活动截止后，中奖结果由系统从抽奖资格池中随机抽取产生。抽奖资格按手机号去重，每个手机号最多获得一次抽奖资格；每人每日限参与一次。")}
          {clause(5,"礼品发放：礼品以实际收到的实物为准，不可折现，仅限邮寄给参与者本人。")}
          {clause(6,"免责条款：因不可抗力（自然灾害、网络故障、设备问题、政策调整等）导致活动延期、变更、中止或无法参与的，活动组织方不承担由此产生的责任。")}
          {clause(7,"解释权：在法律法规允许的范围内，本次活动的最终解释权归活动组织方所有。")}
        </div>
        <button onClick={onClose} className="press" style={{flex:"none",width:"100%",height:50,marginTop:14,borderRadius:25,border:"none",cursor:"pointer",
          background:"linear-gradient(90deg,#3AA0E4,#1E7FD0)",color:"#fff",fontWeight:800,fontSize:16,boxShadow:"0 8px 18px rgba(30,127,208,0.3)"}}>我已阅读</button>
      </div>
    </div>
  );
}

/* ============ APP ============ */
const DAILY_LIMIT = 1;
const todayStr = () => new Date().toLocaleDateString("zh-CN");
const getPlays = () => { try { const o=JSON.parse(localStorage.getItem("hcjy_plays")||"{}"); return o.date===todayStr() ? (o.n||0) : 0; } catch(e){ return 0; } };
const addPlay = () => { try { localStorage.setItem("hcjy_plays", JSON.stringify({date:todayStr(), n:getPlays()+1})); } catch(e){} };
const saveSubmission = (rec) => { try { const a=JSON.parse(localStorage.getItem("hcjy_submissions")||"[]"); a.push(rec); localStorage.setItem("hcjy_submissions", JSON.stringify(a)); } catch(e){} };
/* 今日是否已答题：依据后台存储的手机号判断（同一手机号当天仅一次） */
const playedTodayByPhone = (phone) => {
  if(!phone) return false;
  try {
    const today = new Date().toLocaleDateString("zh-CN");
    return JSON.parse(localStorage.getItem("hcjy_submissions")||"[]")
      .some(d => d.phone===phone && new Date(d.ts).toLocaleDateString("zh-CN")===today);
  } catch(e){ return false; }
};
const todaySubmissionCount = () => {
  try { const today=new Date().toLocaleDateString("zh-CN");
    return JSON.parse(localStorage.getItem("hcjy_submissions")||"[]").filter(d=>new Date(d.ts).toLocaleDateString("zh-CN")===today).length;
  } catch(e){ return 0; }
};
const clearTodaySubmissions = () => {
  try { const today=new Date().toLocaleDateString("zh-CN");
    const kept=JSON.parse(localStorage.getItem("hcjy_submissions")||"[]").filter(d=>new Date(d.ts).toLocaleDateString("zh-CN")!==today);
    localStorage.setItem("hcjy_submissions", JSON.stringify(kept));
  } catch(e){}
};

function Toast({ msg, onDone }) {
  useEffect(()=>{ const t=setTimeout(onDone,2200); return ()=>clearTimeout(t); },[]);
  return (
    <div style={{position:"absolute",inset:0,zIndex:60,display:"flex",alignItems:"center",justifyContent:"center",pointerEvents:"none"}}>
      <div style={{background:"rgba(0,0,0,0.78)",color:"#fff",fontSize:15,fontWeight:600,padding:"16px 26px",
        borderRadius:14,maxWidth:250,textAlign:"center",lineHeight:1.55,animation:"pop .3s ease",
        boxShadow:"0 10px 30px rgba(0,0,0,0.3)"}}>{msg}</div>
    </div>
  );
}

/* ============ DEV 测试面板（手机框外，仅供开发调试） ============ */
function DevPanel({ api, show }) {
  const [open,setOpen]=useState(true);
  const [today,setToday]=useState(todaySubmissionCount());
  const [subs,setSubs]=useState(()=>{ try{return JSON.parse(localStorage.getItem("hcjy_submissions")||"[]").length;}catch(e){return 0;} });
  const sync=()=>{ setToday(todaySubmissionCount()); try{setSubs(JSON.parse(localStorage.getItem("hcjy_submissions")||"[]").length);}catch(e){} };
  useEffect(()=>{ const t=setInterval(sync,800); return ()=>clearInterval(t); },[]);
  const [mobile,setMobile]=useState(typeof window!=="undefined" && window.innerWidth<600);
  useEffect(()=>{ const f=()=>setMobile(window.innerWidth<600); window.addEventListener("resize",f); return ()=>window.removeEventListener("resize",f); },[]);

  if(!show) return null;
  if(!open) return (
    <div style={{position:"fixed",zIndex:9999,fontFamily:'"Noto Sans SC",sans-serif',...(mobile?{right:14,top:"calc(14px + env(safe-area-inset-top))"}:{top:14,left:14})}}>
      <button onClick={()=>setOpen(true)} style={{background:"#11314f",color:"#7FB6E8",border:"none",borderRadius:mobile?24:10,padding:mobile?"11px 16px":"8px 12px",fontSize:mobile?13:12,fontWeight:700,cursor:"pointer",boxShadow:"0 6px 18px rgba(0,0,0,0.3)"}}>🛠 DEV</button>
    </div>
  );
  const Sec=({t})=> <div style={{fontSize:12.5,fontWeight:700,color:"#6E8DA8",letterSpacing:1,margin:mobile?"14px 0 7px":"12px 0 6px",textTransform:"uppercase"}}>{t}</div>;
  const B=({onClick,children,tone})=>{
    const c = tone==="gold"?{bg:"#F5B731",fg:"#5A3D00"}: tone==="green"?{bg:"#2E9E72",fg:"#fff"}: tone==="red"?{bg:"#E0533D",fg:"#fff"}: {bg:"#21507a",fg:"#DCEBFA"};
    return <button onClick={onClick} style={{background:c.bg,color:c.fg,border:"none",borderRadius:8,padding:mobile?"11px 10px":"7px 9px",fontSize:mobile?13:11.5,fontWeight:700,cursor:"pointer",textAlign:"center",width:"100%"}}>{children}</button>;
  };
  const cols = mobile ? "repeat(4, 1fr)" : "1fr 1fr";
  const panelStyle = mobile
    ? {position:"fixed",left:0,right:0,top:0,zIndex:9999,fontFamily:'"Noto Sans SC",sans-serif',background:"#0d2740",
       borderRadius:"0 0 18px 18px",padding:"calc(14px + env(safe-area-inset-top)) 16px 16px",boxShadow:"0 10px 36px rgba(0,0,0,0.4)",
       borderBottom:"1px solid #1d4060",maxHeight:"72vh",overflowY:"auto"}
    : {position:"fixed",top:14,left:14,zIndex:9999,fontFamily:'"Noto Sans SC",sans-serif',width:186,background:"#0d2740",
       borderRadius:14,padding:"12px 13px 14px",boxShadow:"0 12px 36px rgba(0,0,0,0.4)",border:"1px solid #1d4060"};
  return (
    <div style={panelStyle}>
      <div style={{display:"flex",alignItems:"center",justifyContent:"space-between"}}>
        <span style={{fontSize:mobile?14:12.5,fontWeight:800,color:"#fff"}}>🛠 开发者测试</span>
        <span onClick={()=>setOpen(false)} style={{color:"#7FA8CC",cursor:"pointer",fontSize:mobile?22:15,lineHeight:1,padding:"0 4px"}}>×</span>
      </div>
      <div style={{fontSize:mobile?11.5:10.5,color:"#9FBED9",marginTop:5,lineHeight:1.6}}>今日记录 {today} 条 · 后台共 {subs} 条<br/><span style={{color:"#7FA8CC"}}>判断依据：后台手机号（同号每日1次）</span></div>

      <Sec t="跳转页面"/>
      <div style={{display:"grid",gridTemplateColumns:cols,gap:6}}>
        <B onClick={()=>api.go("start")}>开始页</B>
        <B onClick={()=>api.go("form")}>填写信息</B>
        <B onClick={()=>api.startQuiz()}>答题页</B>
        <B onClick={()=>api.go("done")}>抽奖结果</B>
      </div>

      <Sec t="填信息页 · 只填不交卷"/>
      <B tone="gold" onClick={()=>api.fillForm()}>填入测试信息（手机号随机 · 不提交）</B>

      <Sec t="一键直达成绩单"/>
      <div style={{display:"grid",gridTemplateColumns:cols,gap:6}}>
        <B tone="green" onClick={()=>api.devResult(true)}>满分(5/5)</B>
        <B onClick={()=>api.devResult(false)}>未满分</B>
        <B onClick={()=>api.autoFillAnswer()} >自动填表+交卷</B>
        {mobile && <B onClick={()=>api.autoAnswer(true)}>全填正确</B>}
      </div>

      {!mobile && <><Sec t="答题辅助"/>
      <div style={{display:"grid",gridTemplateColumns:cols,gap:6}}>
        <B onClick={()=>api.autoAnswer(true)}>全填正确</B>
        <B onClick={()=>api.skipTime()}>剩 5 秒</B>
      </div></>}
      {mobile && <>
        <Sec t="答题辅助"/>
        <div style={{display:"grid",gridTemplateColumns:cols,gap:6}}>
          <B onClick={()=>api.skipTime()}>剩 5 秒</B>
        </div>
      </>}

      <Sec t="数据"/>
      <div style={{display:"grid",gridTemplateColumns:cols,gap:6}}>
        <B tone="red" onClick={()=>{clearTodaySubmissions(); sync(); api.toast("已清除今日记录（手机号解锁）");}}>解锁今日</B>
        <B tone="red" onClick={()=>{if(confirm("清空后台全部记录？")){try{localStorage.removeItem("hcjy_submissions");}catch(e){} sync(); api.toast("已清空后台记录");}}}>清空记录</B>
        <B onClick={()=>window.open("admin.html","_blank")} >↗ 后台页</B>
      </div>
    </div>
  );
}

function App() {
  const [screen,setScreen]=useState("start");
  const [questions,setQuestions]=useState([]);
  const [answers,setAnswers]=useState([]);
  const [quizId,setQuizId]=useState("");
  const [result,setResult]=useState(null);
  const [submitting,setSubmitting]=useState(false);
  const [current,setCurrent]=useState(0);
  const [timeLeft,setTimeLeft]=useState(600);
  const [timeUsed,setTimeUsed]=useState(0);
  const [showRules,setShowRules]=useState(false);
  const [rulesAccepted,setRulesAccepted]=useState(false);
  const [rulesOrigin,setRulesOrigin]=useState(null);
  const [toast,setToast]=useState(null);
  const [showDisc,setShowDisc]=useState(false);
  const [userInfo,setUserInfo]=useState({});
  const [formPrefill,setFormPrefill]=useState(null);
  const timer=useRef(null);

  const handleStart = () => {
    if(!rulesAccepted){
      setRulesOrigin("start");
      setShowRules(true);
      return;
    }
    setScreen("form");
  };

  const closeRules = () => {
    setRulesAccepted(true);
    setShowRules(false);
    if(rulesOrigin==="start") setScreen("form");
    setRulesOrigin(null);
  };

  const submitForm = async (info) => {
    let blocked = false;
    try { blocked = await HCJY.checkPhone(info.phone); } catch(e) {}
    if(blocked){ setToast("您今日已参与活动，请明日再来"); return; }
    setUserInfo(info);
    await startQuiz();
  };

  const startQuiz = async () => {
    try {
      const session = await HCJY.startQuiz();
      const qs = session.questions && session.questions.length ? session.questions : pick5();
      setQuizId(session.quizId || "");
      setQuestions(qs); setAnswers(new Array(qs.length).fill(null)); setResult(null);
      setCurrent(0); setTimeLeft(session.limitSeconds || 600); setScreen("quiz");
    } catch(e) {
      setToast("题目加载失败，请稍后重试");
    }
  };
  const finish = async (usedOverride) => {
    if(submitting) return;
    const used = usedOverride === undefined ? 600-timeLeft : usedOverride;
    setTimeUsed(used);
    setSubmitting(true);
    try {
      const res = await HCJY.submit({
        name:userInfo.name||"", phone:userInfo.phone||"", profile:userInfo.profile||"",
        prov:userInfo.prov||"", city:userInfo.city||"", dist:userInfo.dist||"", detail:userInfo.detail||"",
        quizId, answers, questions, timeUsed: used,
      });
      setResult(res);
      setScreen("result");
    } catch(e) {
      setToast((e && e.message) || "提交失败，请稍后重试");
      if(e && e.status===409) setScreen("start");
    } finally {
      setSubmitting(false);
    }
  };

  // ---- DEV helpers ----
  const SAMPLE={name:"测试用户",phone:"13800000000",profile:"机关干部",prov:"浙江省",city:"金华市",dist:"婺城区",detail:"测试街道123号"};
  const devResult = (perfect) => {
    const qs = questions.length ? questions : pick5();
    if(!questions.length) setQuestions(qs);
    const ans = qs.map(q => perfect ? q.answer : (q.type==="single" ? (q.answer===0?1:0) : !q.answer));
    setAnswers(ans);
    setUserInfo(u => (u && u.name) ? u : SAMPLE);
    setTimeUsed(120); setScreen("result");
  };
  const autoAnswer = (perfect) => {
    if(!questions.length){ const qs=pick5(); setQuestions(qs); setAnswers(qs.map(q=>perfect?q.answer:(q.type==="single"?(q.answer===0?1:0):!q.answer))); setCurrent(0); setTimeLeft(600); setScreen("quiz"); return; }
    setAnswers(questions.map(q=>perfect?q.answer:(q.type==="single"?(q.answer===0?1:0):!q.answer)));
  };
  const autoFillAnswer = () => { setUserInfo(SAMPLE); const qs=pick5(); setQuestions(qs); setAnswers(qs.map(q=>q.answer)); setCurrent(0); setTimeUsed(95); setScreen("result"); };
  const skipTime = () => setTimeLeft(5);
  const fillForm = () => { const phone="138"+Math.floor(10000000+Math.random()*90000000); setFormPrefill({ ...SAMPLE, phone, _n:Date.now() }); setScreen("form"); };
  const devApi = { go:setScreen, startQuiz, devResult, autoAnswer, autoFillAnswer, skipTime, fillForm, toast:setToast };

  useEffect(()=>{
    if(screen==="quiz"){
      timer.current=setInterval(()=>{
        setTimeLeft(t=>{ if(t<=1){ clearInterval(timer.current); finish(600); return 0; } return t-1; });
      },1000);
      return ()=>clearInterval(timer.current);
    }
  },[screen]);

  const [devAllowed,setDevAllowed]=useState(false);
  useEffect(()=>{ HCJY.getMode().then(m=>setDevAllowed(m!=="api" || new URLSearchParams(location.search).has("dev"))); },[]);
  // 响应式：手机端铺满整屏（无外壳/无缩放）；桌面端居中窄列预览
  const [desktop,setDesktop]=useState(typeof window!=="undefined" && window.innerWidth>768);
  useEffect(()=>{ const f=()=>setDesktop(window.innerWidth>768); window.addEventListener("resize",f); return ()=>window.removeEventListener("resize",f); },[]);

  return (
    <div style={{minHeight:"100dvh",display:"flex",alignItems:"stretch",justifyContent:"center",
      background: desktop ? "radial-gradient(circle at 50% 20%,#E8F1F8,#D2DEE8)" : "#C2E7FB"}}>
      <div onDoubleClick={()=>{clearTodaySubmissions(); setToast("已清除今日记录（手机号解锁）");}}
        style={{width: desktop ? 430 : "100%", maxWidth:"100%", height:"100dvh", position:"relative", overflow:"hidden",
          background:"#C2E7FB", boxShadow: desktop ? "0 0 60px rgba(20,60,100,0.18)" : "none"}}>
          {screen==="start" && <StartScreen onStart={handleStart} onRules={()=>{
            setRulesOrigin("manual");
            setShowRules(true);
          }}/>}
          {screen==="quiz" && <QuizScreen questions={questions} answers={answers} setAnswers={setAnswers}
            current={current} setCurrent={setCurrent} timeLeft={timeLeft} onExit={()=>setScreen("start")} onSubmit={finish} submitting={submitting}/>}
          {screen==="result" && <ResultScreen questions={questions} answers={answers} timeUsed={timeUsed} result={result}
            onForm={()=>setScreen("done")} onRetry={()=>setScreen("start")} onHome={()=>setScreen("start")}/>}
          {screen==="form" && <FormScreen onSubmit={submitForm} onBack={()=>setScreen("start")} prefill={formPrefill} onConsumePrefill={()=>setFormPrefill(null)} onShowDisclaimer={()=>setShowDisc(true)}/>}
          {screen==="done" && <DoneScreen onHome={()=>setScreen("start")}/>}
          {showRules && <RulesModal onClose={closeRules}/>}
          {showDisc && <DisclaimerModal onClose={()=>setShowDisc(false)}/>}
          {toast && <Toast msg={toast} onDone={()=>setToast(null)}/>}
      </div>
      <DevPanel api={devApi} show={devAllowed}/>
    </div>
  );
}
ReactDOM.createRoot(document.getElementById("root")).render(<App/>);
