const { useState, useEffect, useCallback, useMemo } = React;
/*═══════════════════════════════════════════════════════════🌸 Sakura Ultimate — Full Version + AstraBuddy Platform v2.3 Patches═══════════════════════════════════════════════════════════*/
const C={bg:"#FFF5F7",bg2:"#FFF0F3",bg3:"#FFE8ED",card:"#fff",bd:"rgba(219,112,147,.14)",bdL:"rgba(219,112,147,.08)",t1:"#241018",t2:"#5a3545",t3:"#8a6573",pink:"#E84D8C",pinkL:"#f26c9e",pinkD:"#c9306b",pinkBg:"#fce4ec",sakura:"#FFaabd",sakuraL:"#FFccda",sakuraD:"#F27ca5",rose:"#FF5c82",gold:"#cc8b2d",teal:"#32a596",peri:"#7366F2",violet:"#9264e0",coral:"#e86850",lime:"#72a838",safe:"#4a9e4a",warn:"#e49018",danger:"#d83838",blue:"#6090e8",white:"#fff",glass:"rgba(255,255,255,.86)"}/* ═══ UI: TriCore Panel ═══ */
const TriCorePanel=({scores,st})=>{const[expanded,setExpanded]=useState(null);const dims=TRICORE_DIMS.map((d,i)=>({...d,score:scores?.[d.id]||50}));return <div className="glass-card" style={{margin:"8px 14px",padding:"14px"}}><div style={{fontSize:13,fontWeight:700,color:C.peri,marginBottom:10}}>💠 关系三角体检</div><div style={{display:"flex",gap:8,marginBottom:12}}>{dims.map(d=><div key={d.id} style={{flex:1,textAlign:"center"}}><div style={{fontSize:16,marginBottom:4}}>{d.icon}</div><div style={{fontSize:20,fontWeight:900,color:d.score>70?C.safe:d.score>40?C.warn:C.danger}}>{d.score}</div><div style={{fontSize:9,color:C.t3}}>{d.name.split("(")[0]}</div><div style={{height:4,borderRadius:2,background:`${C.bd}`,marginTop:4}}><div style={{width:`${d.score}%`,height:"100%",borderRadius:2,background:d.score>70?C.safe:d.score>40?C.warn:C.danger,transition:"width .8s"}}/></div></div>)}</div>{dims.map(d=><div key={d.id} style={{marginBottom:8}}><button className="tap2" onClick={()=>setExpanded(expanded===d.id?null:d.id)} style={{width:"100%",padding:"8px 10px",borderRadius:10,background:expanded===d.id?`${C.peri}08`:C.bg,border:`1px solid ${expanded===d.id?C.peri+"25":C.bdL}`,cursor:"pointer",textAlign:"left",display:"flex",justifyContent:"space-between",alignItems:"center"}}><span style={{fontSize:11,fontWeight:600,color:C.t1}}>{d.icon} {d.name}</span><span style={{fontSize:10,color:C.t3}}>{expanded===d.id?"▲":"▼"}</span></button>{expanded===d.id&&<div style={{padding:"8px 10px",animation:"fadeUp .2s"}}><div style={{fontSize:10,color:C.t2,marginBottom:6}}>{d.desc}</div><div style={{fontSize:10,fontWeight:600,color:C.safe,marginBottom:4}}>📈 提升方法</div>{d.up.map((u,i)=><div key={i} style={{fontSize:10,color:C.t2,paddingLeft:8,marginBottom:2}}>• {u}</div>)}<div style={{fontSize:10,fontWeight:600,color:C.danger,marginTop:6,marginBottom:4}}>📉 下降原因</div>{d.down.map((u,i)=><div key={i} style={{fontSize:10,color:C.t2,paddingLeft:8,marginBottom:2}}>• {u}</div>)}{d.normal&&<div style={{fontSize:9,color:C.t3,marginTop:6,padding:"6px 8px",background:`${C.peri}06`,borderRadius:6}}>💡 {d.normal}</div>}</div>}</div>)}</div>;}/* ═══ UI: Risk Detail Panel ═══ */
const RiskDetailPanel=({level})=>{const[expanded,setExpanded]=useState(false);const data=RISK_DETAILS[level]||RISK_DETAILS.low;const color=level==="high"?C.danger:level==="med"?C.warn:C.safe;return <div style={{margin:"6px 0",padding:"10px 12px",borderRadius:12,background:`${color}06`,border:`1px solid ${color}15`}}><button className="tap2" onClick={()=>setExpanded(!expanded)} style={{width:"100%",display:"flex",justifyContent:"space-between",alignItems:"center",background:"none",border:"none",cursor:"pointer"}}><span style={{fontSize:12,fontWeight:700,color:color}}>{data.title}</span><span style={{fontSize:10,color:C.t3}}>{expanded?"▲":"▼"}</span></button><div style={{fontSize:10,color:C.t2,marginTop:4}}>{data.desc}</div>{expanded&&<div style={{marginTop:8,animation:"fadeUp .2s"}}>{level==="low"&&<><div style={{fontSize:10,fontWeight:600,color:C.safe,marginBottom:4}}>✅ 保持策略</div>{data.keep.map((k,i)=><div key={i} style={{fontSize:10,color:C.t2,paddingLeft:8,marginBottom:2}}>• {k}</div>)}<div style={{fontSize:10,fontWeight:600,color:C.teal,marginTop:6,marginBottom:4}}>🛡️ 预防性维护</div>{data.prevent.map((k,i)=><div key={i} style={{fontSize:10,color:C.t2,paddingLeft:8,marginBottom:2}}>• {k}</div>)}</>}{level==="med"&&<><div style={{fontSize:10,fontWeight:600,color:C.warn,marginBottom:4}}>⚠️ 风险信号</div>{data.signals.map((k,i)=><div key={i} style={{fontSize:10,color:C.t2,paddingLeft:8,marginBottom:2}}>• {k}</div>)}<div style={{fontSize:10,fontWeight:600,color:C.peri,marginTop:6,marginBottom:4}}>📋 调整计划</div>{data.plan.map((k,i)=><div key={i} style={{fontSize:10,color:C.t2,paddingLeft:8,marginBottom:2}}>• {k}</div>)}</>}{level==="high"&&<><div style={{fontSize:10,fontWeight:600,color:C.danger,marginBottom:4}}>🚨 危机处理</div>{data.crisis.map((k,i)=><div key={i} style={{fontSize:10,color:C.t2,paddingLeft:8,marginBottom:2}}>{i+1}. {k}</div>)}<div style={{fontSize:10,fontWeight:600,color:C.peri,marginTop:6,marginBottom:4}}>🏥 何时寻求专业帮助</div>{data.pro.map((k,i)=><div key={i} style={{fontSize:10,color:C.t2,paddingLeft:8,marginBottom:2}}>• {k}</div>)}</>}</div>}</div>;}/* ═══ UI: Module Help Panel ═══ */
const ModHelpPanel=({mod})=>{const[tab,setTab]=useState("collect");const help=MODULE_HELP(mod);const d=help[tab];if(!d)return null;const tabs=[{id:"collect",l:"📋 收集模板"},{id:"howToUse",l:"📖 如何使用"},{id:"partial",l:"❓ 信息不全"},{id:"limits",l:"⚠️ 局限性"}];return <div style={{margin:"6px 0",padding:"10px 12px",borderRadius:12,background:`${C.peri}06`,border:`1px solid ${C.peri}12`}}><div style={{display:"flex",gap:4,marginBottom:8,overflowX:"auto"}}>{tabs.map(t=><button key={t.id} className="tap2" onClick={()=>setTab(t.id)} style={{padding:"3px 8px",borderRadius:6,fontSize:9,fontWeight:tab===t.id?700:500,background:tab===t.id?`${C.peri}15`:"transparent",color:tab===t.id?C.peri:C.t3,border:"none",cursor:"pointer",whiteSpace:"nowrap"}}>{t.l}</button>)}</div><div style={{fontSize:11,fontWeight:600,color:C.t1,marginBottom:6}}>{d.title}</div>{d.items.map((item,i)=><div key={i} style={{fontSize:10,color:C.t2,paddingLeft:8,marginBottom:3,lineHeight:1.5}}>{tab==="collect"?item:`• ${item}`}</div>)}{d.note&&<div style={{fontSize:9,color:C.t3,marginTop:4,fontStyle:"italic"}}>{d.note}</div>}</div>;}/* ═══ UI: Engine Detail Panel ═══ */
const EngDetailPanel=({eng})=>{const[tab,setTab]=useState("how");const d=ENGINE_DETAIL(eng);const tabs=[{id:"how",l:"⚙️ 原理"},{id:"metrics",l:"📊 指标"},{id:"accuracy",l:"🎯 准确率"},{id:"scripts",l:"💬 话术"}];return <div style={{margin:"6px 0",padding:"10px 12px",borderRadius:12,background:`${C.teal}06`,border:`1px solid ${C.teal}12`}}><div style={{display:"flex",gap:4,marginBottom:8,overflowX:"auto"}}>{tabs.map(t=><button key={t.id} className="tap2" onClick={()=>setTab(t.id)} style={{padding:"3px 8px",borderRadius:6,fontSize:9,fontWeight:tab===t.id?700:500,background:tab===t.id?`${C.teal}15`:"transparent",color:tab===t.id?C.teal:C.t3,border:"none",cursor:"pointer",whiteSpace:"nowrap"}}>{t.l}</button>)}</div>{tab==="how"&&<div><div style={{fontSize:11,fontWeight:600,color:C.t1,marginBottom:6}}>{d.how.title}</div>{d.how.steps.map((s,i)=><div key={i} style={{fontSize:10,color:C.t2,paddingLeft:8,marginBottom:3}}>{i+1}. {s}</div>)}</div>}{tab==="metrics"&&<div><div style={{fontSize:11,fontWeight:600,color:C.t1,marginBottom:6}}>{d.metrics.title}</div>{d.metrics.dims.map((s,i)=><div key={i} style={{fontSize:10,color:C.t2,marginBottom:3}}>{s}</div>)}<div style={{marginTop:6,fontSize:9,color:C.t3}}>🟢低风险→继续 🟡中风险→微调 🔴高风险→立即调整</div></div>}{tab==="accuracy"&&<div>{d.accuracy.items.map((s,i)=><div key={i} style={{fontSize:10,color:C.t2,paddingLeft:8,marginBottom:3}}>• {s}</div>)}</div>}{tab==="scripts"&&<div><div style={{fontSize:10,fontWeight:600,color:C.danger,marginBottom:4}}>🛑 止损话术</div>{d.stopScripts.map((s,i)=><div key={i} className="tap2" onClick={()=>{navigator.clipboard?.writeText(s);}} style={{fontSize:10,color:C.t1,padding:"4px 8px",marginBottom:2,borderRadius:6,background:C.bg,cursor:"pointer"}}>「{s}」</div>)}<div style={{fontSize:10,fontWeight:600,color:C.safe,marginTop:6,marginBottom:4}}>🔧 修复话术</div>{d.repairScripts.map((s,i)=><div key={i} className="tap2" onClick={()=>{navigator.clipboard?.writeText(s);}} style={{fontSize:10,color:C.t1,padding:"4px 8px",marginBottom:2,borderRadius:6,background:C.bg,cursor:"pointer"}}>「{s}」</div>)}</div>}</div>;}/* ═══ UI: Pipeline Progress ═══ */
const PipelineProgress=({step,active})=>{return <div style={{margin:"8px 14px",padding:"10px 14px",borderRadius:14,background:`${C.peri}06`,border:`1px solid ${C.peri}12`}}><div style={{display:"flex",gap:2,marginBottom:6}}>{PIPE_STEPS.map((s,i)=><div key={i} style={{flex:1,height:4,borderRadius:2,background:i<=step?`linear-gradient(90deg,${C.pink},${C.peri})`:C.bd,transition:"background .3s"}}/>)}</div><div style={{display:"flex",alignItems:"center",gap:8}}><span style={{fontSize:18,animation:active?"pulse 1s infinite":"none"}}>{PIPE_STEPS[Math.min(step,5)]?.icon}</span><div><div style={{fontSize:11,fontWeight:700,color:C.t1}}>{PIPE_STEPS[Math.min(step,5)]?.label}</div><div style={{fontSize:9,color:C.t3}}>{PIPE_STEPS[Math.min(step,5)]?.desc}</div></div><div style={{marginLeft:"auto",fontSize:10,fontWeight:700,color:C.peri}}>{Math.min(Math.round((step+1)/6*100),100)}%</div></div></div>;}/* ═══ LEARNING ENGINE — 越用越准闭环 ═══ */
const LEARN_KEYS={choices:"sakura-learn-choices",outcomes:"sakura-learn-outcomes",profile:"sakura-learn-profile",streak:"sakura-learn-streak"};
const inputHash=(t)=>{if(!t)return"";const s=t.replace(/\s/g,"").slice(0,20);return[...s].reduce((a,c)=>((a<<5)-a+c.charCodeAt(0))|0,0).toString(36);};
const useLearningEngine=()=>{const[learnData,setLearnData]=useState({choices:[],outcomes:[],profile:{tonePrefs:{},personaByTa:{},patterns:{}},streak:{total:0,positive:0,lastWeek:[]}});useEffect(()=>{(async()=>{try{const ch=await window.storage.get(LEARN_KEYS.choices);const oc=await window.storage.get(LEARN_KEYS.outcomes);const pr=await window.storage.get(LEARN_KEYS.profile);const sk=await window.storage.get(LEARN_KEYS.streak);setLearnData({choices:ch?.value?JSON.parse(ch.value):[],outcomes:oc?.value?JSON.parse(oc.value):[],profile:pr?.value?JSON.parse(pr.value):{tonePrefs:{},personaByTa:{},patterns:{}},streak:sk?.value?JSON.parse(sk.value):{total:0,positive:0,lastWeek:[]}});}catch{}})();},[]);const saveLearn=(key,data)=>{try{window.storage.set(key,JSON.stringify(data));}catch{}};const trackChoice=(inp,tone,persona,taId)=>{const entry={id:Date.now(),h:inputHash(inp),tone,persona,taId:taId||"default",ts:Date.now()};const nc=[entry,...learnData.choices].slice(0,500);const np={...learnData.profile};np.tonePrefs=np.tonePrefs||{};np.tonePrefs[tone]=(np.tonePrefs[tone]||0)+1;if(taId){np.personaByTa=np.personaByTa||{};np.personaByTa[taId]=np.personaByTa[taId]||{};np.personaByTa[taId][persona]=(np.personaByTa[taId][persona]||0)+1;}setLearnData(p=>({...p,choices:nc,profile:np}));saveLearn(LEARN_KEYS.choices,nc);saveLearn(LEARN_KEYS.profile,np);return entry.id;};const trackOutcome=(choiceId,outcome)=>{const entry={choiceId,outcome,ts:Date.now()};const no=[entry,...learnData.outcomes].slice(0,500);const ns={...learnData.streak};ns.total=(ns.total||0)+1;if(outcome==="positive")ns.positive=(ns.positive||0)+1;const today=new Date().toDateString();ns.lastWeek=ns.lastWeek||[];ns.lastWeek=[{date:today,outcome},...ns.lastWeek].slice(0,50);const choice=learnData.choices.find(c=>c.id===choiceId);if(choice&&outcome==="positive"){const np={...learnData.profile};np.patterns=np.patterns||{};np.patterns[choice.h]=choice.tone;saveLearn(LEARN_KEYS.profile,np);setLearnData(p=>({...p,profile:np}));}setLearnData(p=>({...p,outcomes:no,streak:ns}));saveLearn(LEARN_KEYS.outcomes,no);saveLearn(LEARN_KEYS.streak,ns);};const smartRerank=(replies,inp,taId,persona)=>{if(!replies||replies.length===0)return replies;const prof=learnData.profile;const hash=inputHash(inp);const patternBest=prof.patterns?.[hash];const toneScores={};Object.entries(prof.tonePrefs||{}).forEach(([t,cnt])=>{toneScores[t]=(toneScores[t]||0)+cnt*0.3;});if(taId&&prof.personaByTa?.[taId]){const taPrefs=prof.personaByTa[taId];Object.entries(taPrefs).forEach(([p,cnt])=>{if(p===persona)Object.keys(toneScores).forEach(t=>{toneScores[t]=(toneScores[t]||0)+cnt*0.2;});});}const positiveOutcomes=learnData.outcomes.filter(o=>o.outcome==="positive");const positiveTones=positiveOutcomes.map(o=>{const ch=learnData.choices.find(cc=>cc.id===o.choiceId);return ch?.tone;}).filter(Boolean);positiveTones.forEach(t=>{toneScores[t]=(toneScores[t]||0)+2;});if(patternBest)toneScores[patternBest]=(toneScores[patternBest]||0)+5;const scored=replies.map(r=>{const score=(toneScores[r.tone]||0);return{...r,_learnScore:score};});scored.sort((a,b)=>b._learnScore-a._learnScore);if(scored[0]._learnScore>0)scored[0]._recommended=true;return scored;};const getInsight=(taId)=>{const prof=learnData.profile;const streak=learnData.streak;const insights=[];const total=learnData.choices.length;if(total>=5){const sorted=Object.entries(prof.tonePrefs||{}).sort((a,b)=>b[1]-a[1]);if(sorted.length>0)insights.push({icon:"🎯",text:`你最常选「${sorted[0][0]}」(${Math.round(sorted[0][1]/total*100)}%)`});}if(streak.total>=3){const rate=Math.round((streak.positive||0)/streak.total*100);insights.push({icon:rate>=60?"🟢":"🟡",text:`正面率${rate}%`});}const patternCount=Object.keys(prof.patterns||{}).length;if(patternCount>=3)insights.push({icon:"🧠",text:`已学${patternCount}种模式`});return insights;};const getLearnStats=()=>({totalChoices:learnData.choices.length,totalOutcomes:learnData.outcomes.length,positiveRate:learnData.streak.total>0?Math.round((learnData.streak.positive||0)/learnData.streak.total*100):0,patternsLearned:Object.keys(learnData.profile.patterns||{}).length,topTones:Object.entries(learnData.profile.tonePrefs||{}).sort((a,b)=>b[1]-a[1]).slice(0,3)});return{trackChoice,trackOutcome,smartRerank,getInsight,getLearnStats,learnData};}/* ═══ UI: Learning Report 学习报告 ═══ */
const LearnReport=({stats,insights,st})=>{const[expanded,setExpanded]=useState(false);if(stats.totalChoices<1)return null;return <div className="glass-card" style={{margin:"8px 14px",padding:"12px 14px"}}><button className="tap2" onClick={()=>setExpanded(!expanded)} style={{width:"100%",display:"flex",justifyContent:"space-between",alignItems:"center",background:"none",border:"none",cursor:"pointer"}}><div style={{display:"flex",alignItems:"center",gap:6}}><span style={{fontSize:16}}>🧠</span><div><div style={{fontSize:12,fontWeight:700,color:C.peri}}>越用越准引擎</div><div style={{fontSize:9,color:C.t3}}>已学习{stats.totalChoices}次选择 · {stats.patternsLearned}种模式</div></div></div><span style={{fontSize:10,color:C.t3}}>{expanded?"▲":"▼"}</span></button>{expanded&&<div style={{marginTop:10,animation:"fadeUp .2s"}}><div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr 1fr",gap:6,marginBottom:10}}><div style={{textAlign:"center",padding:"6px 4px",borderRadius:8,background:`${C.peri}06`}}><div style={{fontSize:18,fontWeight:900,color:C.peri}}>{stats.totalChoices}</div><div style={{fontSize:8,color:C.t3}}>选择记录</div></div><div style={{textAlign:"center",padding:"6px 4px",borderRadius:8,background:`${C.teal}06`}}><div style={{fontSize:18,fontWeight:900,color:C.teal}}>{stats.totalOutcomes}</div><div style={{fontSize:8,color:C.t3}}>反馈收集</div></div><div style={{textAlign:"center",padding:"6px 4px",borderRadius:8,background:`${stats.positiveRate>=60?C.safe:C.warn}06`}}><div style={{fontSize:18,fontWeight:900,color:stats.positiveRate>=60?C.safe:C.warn}}>{stats.positiveRate}%</div><div style={{fontSize:8,color:C.t3}}>正面率</div></div><div style={{textAlign:"center",padding:"6px 4px",borderRadius:8,background:`${C.gold}06`}}><div style={{fontSize:18,fontWeight:900,color:C.gold}}>{stats.patternsLearned}</div><div style={{fontSize:8,color:C.t3}}>已学模式</div></div></div>{stats.topTones.length>0&&<div style={{marginBottom:8}}><div style={{fontSize:10,fontWeight:600,color:C.t2,marginBottom:4}}>🎯 你的风格偏好</div>{stats.topTones.map(([tone,count],i)=>{const total=stats.totalChoices||1;const pct=Math.round(count/total*100);return <div key={tone} style={{display:"flex",alignItems:"center",gap:6,marginBottom:3}}><span style={{fontSize:10,color:C.t2,width:50}}>{tone}</span><div style={{flex:1,height:6,borderRadius:3,background:C.bg}}><div style={{width:`${pct}%`,height:"100%",borderRadius:3,background:i===0?C.pink:i===1?C.peri:C.teal,transition:"width .5s"}}/></div><span style={{fontSize:9,color:C.t3,width:30,textAlign:"right"}}>{pct}%</span></div>})}</div>}{insights.length>0&&<div><div style={{fontSize:10,fontWeight:600,color:C.t2,marginBottom:4}}>💡 学习洞察</div>{insights.map((ins,i)=><div key={i} style={{padding:"4px 8px",marginBottom:3,borderRadius:6,background:C.bg,fontSize:10,color:C.t1}}>{ins.icon} {ins.text}</div>)}</div>}</div>}</div>;}/* ═══ UI: Outcome Feedback Bar 结果反馈条 ═══ */
const OutcomeFeedback=({choiceId,onFeedback,st})=>{const[show,setShow]=useState(false);const[done,setDone]=useState(false);useEffect(()=>{if(!choiceId)return;const t=setTimeout(()=>setShow(true),30000);return()=>clearTimeout(t);},[choiceId]);if(!show||done)return null;const options=[{icon:"😊",label:"积极回复",value:"positive"},{icon:"😐",label:"没反应",value:"neutral"},{icon:"😤",label:"变差了",value:"negative"},{icon:"🙈",label:"还没回",value:"pending"}];return <div style={{margin:"6px 14px",padding:"8px 12px",borderRadius:12,background:`${C.peri}06`,border:`1px solid ${C.peri}12`,animation:"fadeUp .3s"}}><div style={{fontSize:10,fontWeight:600,color:C.peri,marginBottom:6}}>🧠 TA后来怎么回的？（帮AI学习你的TA）</div><div style={{display:"flex",gap:4}}>{options.map(o=><button key={o.value} className="tap2" onClick={()=>{onFeedback(choiceId,o.value);setDone(true);st?.("🧠 已记录，下次更准");}} style={{flex:1,padding:"6px 4px",borderRadius:8,background:C.white,border:`1px solid ${C.bdL}`,cursor:"pointer",textAlign:"center"}}><div style={{fontSize:14}}>{o.icon}</div><div style={{fontSize:8,color:C.t3}}>{o.label}</div></button>)}</div><button className="tap2" onClick={()=>setDone(true)} style={{width:"100%",marginTop:4,padding:"3px",background:"none",border:"none",fontSize:9,color:C.t3,cursor:"pointer"}}>跳过</button></div>;}/* ═══ UI: Pickup Full Panel ═══ */
const PickupFullPanel=({result,st})=>{const[showSignals,setShowSignals]=useState(false);const[showNext,setShowNext]=useState(false);const[showOpeners,setShowOpeners]=useState(false);if(!result)return null;return <div style={{padding:"8px 14px"}}>{result.compatibility&&<Cd s={{marginBottom:8,background:`${C.peri}04`}}><div style={{fontSize:12,fontWeight:700,color:C.peri,marginBottom:6}}>💕 匹配度评估</div><div style={{fontSize:28,fontWeight:900,color:result.compatibility.score>70?C.safe:C.warn,textAlign:"center",marginBottom:8}}>{result.compatibility.score}%</div>{result.compatibility.pros&&<div style={{marginBottom:6}}><div style={{fontSize:10,fontWeight:600,color:C.safe,marginBottom:3}}>✅ 优势</div>{result.compatibility.pros.map((p,i)=><div key={i} style={{fontSize:10,color:C.t2,paddingLeft:8,marginBottom:2}}>• {p}</div>)}</div>}{result.compatibility.cons&&<div><div style={{fontSize:10,fontWeight:600,color:C.warn,marginBottom:3}}>⚠️ 注意</div>{result.compatibility.cons.map((p,i)=><div key={i} style={{fontSize:10,color:C.t2,paddingLeft:8,marginBottom:2}}>• {p}</div>)}</div>}</Cd>}<button className="tap2" onClick={()=>setShowOpeners(!showOpeners)} style={{width:"100%",padding:"8px 12px",borderRadius:10,background:showOpeners?`${C.pink}08`:C.bg,border:`1px solid ${showOpeners?C.pink+"25":C.bdL}`,cursor:"pointer",textAlign:"left",marginBottom:6}}><span style={{fontSize:11,fontWeight:600}}>💬 6种开场白风格 {showOpeners?"▲":"▼"}</span></button>{showOpeners&&<div style={{marginBottom:8,animation:"fadeUp .2s"}}>{PICKUP_OPENERS.map((o,i)=><Cd key={i} s={{marginBottom:4,padding:"8px 10px"}}><div style={{display:"flex",justifyContent:"space-between",marginBottom:3}}><span style={{fontSize:10,fontWeight:600,color:C.pink}}>{o.style}</span><CB text={o.text} st={st}/></div><div style={{fontSize:11,color:C.t1,lineHeight:1.6}}>「{o.text}」</div><div style={{fontSize:9,color:C.t3,marginTop:3}}>💡 {o.why}</div></Cd>)}</div>}<button className="tap2" onClick={()=>setShowSignals(!showSignals)} style={{width:"100%",padding:"8px 12px",borderRadius:10,background:showSignals?`${C.teal}08`:C.bg,border:`1px solid ${showSignals?C.teal+"25":C.bdL}`,cursor:"pointer",textAlign:"left",marginBottom:6}}><span style={{fontSize:11,fontWeight:600}}>👀 TA的反应信号 {showSignals?"▲":"▼"}</span></button>{showSignals&&<div style={{marginBottom:8,animation:"fadeUp .2s"}}><div style={{fontSize:10,fontWeight:600,color:C.safe,marginBottom:4}}>✅ 积极信号（有兴趣）</div>{PICKUP_SIGNALS.good.map((s,i)=><div key={i} style={{fontSize:10,color:C.t2,paddingLeft:8,marginBottom:2}}>• {s}</div>)}<div style={{fontSize:10,fontWeight:600,color:C.danger,marginTop:6,marginBottom:4}}>❌ 消极信号（不感兴趣）</div>{PICKUP_SIGNALS.bad.map((s,i)=><div key={i} style={{fontSize:10,color:C.t2,paddingLeft:8,marginBottom:2}}>• {s}</div>)}</div>}<button className="tap2" onClick={()=>setShowNext(!showNext)} style={{width:"100%",padding:"8px 12px",borderRadius:10,background:showNext?`${C.gold}08`:C.bg,border:`1px solid ${showNext?C.gold+"25":C.bdL}`,cursor:"pointer",textAlign:"left",marginBottom:6}}><span style={{fontSize:11,fontWeight:600}}>📋 搭讪后16步跟进 {showNext?"▲":"▼"}</span></button>{showNext&&<div style={{animation:"fadeUp .2s"}}>{PICKUP_NEXTSTEPS.map((s,i)=><div key={i} style={{fontSize:10,color:C.t2,padding:"4px 8px",marginBottom:3,borderRadius:6,background:i%2?C.bg:"transparent",lineHeight:1.6}}>{i+1}. {s}</div>)}</div>}</div>;};
const font=`"SF Pro Display","PingFang SC","Noto Sans SC",system-ui,sans-serif`;/* ═══ API配置：改这一行URL即可接入你的代理 ═══ */
const API_URL=(typeof globalThis!=="undefined"&&globalThis.__SAKURA_API_URL)||"https://api.anthropic.com/v1/messages";
const API_MODEL=(typeof globalThis!=="undefined"&&globalThis.__SAKURA_API_MODEL)||"claude-sonnet-4-20250514";
const ai=async(s,m)=>{try{const c=new AbortController();const t=setTimeout(()=>c.abort(),45000);const r=await fetch(API_URL,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:API_MODEL,max_tokens:1000,system:s,messages:[{role:"user",content:m}]}),signal:c.signal});clearTimeout(t);const d=await r.json();if(d.error)return{_e:d.error.message};return d.content?.[0]?.text||"";}catch(e){return{_e:e.name==="AbortError"?"TIMEOUT":e.message};}}/* ═══ Mock Fallback：API失败时本地生成基础回复 ═══ */
const MOCK_QUICK=(inp,persona)=>{const h=Math.abs([...inp].reduce((a,c)=>a+c.charCodeAt(0),0));const pools={safe:["嗯嗯，我在呢","好的，我明白你的意思","我听到了，谢谢你告诉我","收到了，给我想想"],warm:["想你了，刚好看到你消息","你说的对，我也是这么觉得的","最近怎么样？有没有好好吃饭","辛苦了，今天早点休息"],humor:["哈哈这也太你了","你这话我都不知道怎么接了，太可爱了","笑死，但是我觉得你说得对","行吧，算你赢了"],push:["有个地方想带你去，下周有空吗","你猜我现在在想什么","我觉得我们可以试试...","想见你了，什么时候方便"]};return[{tone:"安全",text:pools.safe[h%4],risk:"low"},{tone:"温柔",text:pools.warm[h%4],risk:"low"},{tone:"幽默",text:pools.humor[h%4],risk:"med"},{tone:"推进",text:pools.push[h%4],risk:"med"}];};
const MOCK_THINK=(inp)=>{const len=inp.length;const hasQ=inp.includes("？")||inp.includes("?");return{analysis:{emotion:len>20?"可能有些不满或失落":"情绪相对平稳",subtext:hasQ?"在试探你的态度":"简短回复，观察你的反应",expectation:"希望被认真对待",risk:len>30?"消息偏长注意":"基本安全"},replies:[{tone:"温柔",text:"我在呢，你说的我都有在认真听",risk:"low",reason:"先给安全感"},{tone:"高情商",text:"我能理解你的感受，换成我也会这样想",risk:"low",reason:"共情优先"},{tone:"幽默",text:"你说的太对了，我竟无法反驳",risk:"med",reason:"轻松化解"},{tone:"推进",text:"要不我们见面聊？打字说不清楚",risk:"med",reason:"升级接触"}]};};
const MOCK_POLISH=(inp)=>{const risk=inp.length>25?65:inp.includes("你总是")||inp.includes("你从来")?80:30;return{risk,versions:[{label:"温柔版",text:inp.replace(/你总是/g,"我觉得有时候").replace(/你从来不/g,"我希望偶尔能").slice(0,30)+"...我是这么想的"},{label:"幽默版",text:"哈哈"+inp.slice(0,20)+"...（认真脸）"},{label:"低压版",text:inp.slice(0,15)+"...你觉得呢？"}],best:{text:inp.length>20?inp.slice(0,18)+"？你觉得呢":"（先想想再发）"+inp.slice(0,15),reason:"简短+开放提问=最安全"}};};
const pJ=t=>{if(t?._e)return null;try{let s=typeof t==="string"?t:"";s=s.split("`json").join("").split("`").join("").trim();const m=s.match(/[\[\{][\s\S]*[\]\}]/);return m?JSON.parse(m[0]):null;}catch{return null;}};
const isE=r=>r&&typeof r==="object"&&"_e"in r;
const STAGES=[{id:"stranger",l:"陌生",icon:"👤",tip:"保持礼貌好奇",c:"#94A3B8"},{id:"new",l:"初识",icon:"👋",tip:"轻松自然",c:"#60A5FA"},{id:"warm",l:"轻熟",icon:"😊",tip:"开始有默契",c:"#34D399"},{id:"flirt",l:"暧昧",icon:"💫",tip:"推拉制造心动",c:C.peri},{id:"hot",l:"热恋",icon:"🔥",tip:"甜蜜不失自我",c:C.pink},{id:"stable",l:"稳定",icon:"💍",tip:"制造新鲜感",c:C.gold},{id:"long",l:"异地",icon:"✈️",tip:"质量>数量",c:C.teal},{id:"cold",l:"冷战",icon:"🧊",tip:"低压修复",c:"#93C5FD"},{id:"back",l:"复合",icon:"🌱",tip:"用行动少承诺",c:"#86EFAC"},{id:"work",l:"职场",icon:"💼",tip:"边界+微心动",c:"#FDA4AF"},{id:"blind",l:"相亲",icon:"🤝",tip:"礼貌自然",c:"#FBBF24"},{id:"married",l:"已婚",icon:"🏠",tip:"老夫老妻也心动",c:C.coral},{id:"breakup",l:"分手后",icon:"💔",tip:"体面或争取",c:"#F87171"}];
const PERSONAS=[{id:"eq",l:"高情商",icon:"💎",c:C.peri,cat:"高频",hot:288},{id:"gentle",l:"温柔",icon:"🕊️",c:C.sakuraD,cat:"高频",hot:256},{id:"funny",l:"幽默",icon:"😏",c:C.gold,cat:"高频",hot:268},{id:"flirty",l:"轻撩",icon:"🎭",c:C.violet,cat:"高频",hot:200},{id:"direct",l:"直球",icon:"🎯",c:C.lime,cat:"高频",hot:203},{id:"push",l:"推拉",icon:"🔥",c:C.rose,cat:"高频",hot:189},{id:"safe",l:"安全感",icon:"🤗",c:C.teal,cat:"高频",hot:167},{id:"mystery",l:"神秘感",icon:"🌙",c:"#9575cd",cat:"高频",hot:158},{id:"sweet",l:"甜蜜恋人",icon:"🍬",c:C.pink,cat:"功能",hot:142},{id:"boss",l:"霸道宠溺",icon:"👑",c:C.coral,cat:"功能",hot:135},{id:"lowp",l:"低压从容",icon:"🌊",c:C.teal,cat:"功能",hot:120},{id:"mature",l:"成熟稳重",icon:"🏔️",c:"#8FA8C8",cat:"功能",hot:110},{id:"repair",l:"修复关系",icon:"🔧",c:C.teal,cat:"功能",hot:95},{id:"sajiao",l:"撒娇",icon:"🥺",c:"#FFB74D",cat:"功能",hot:120},{id:"beijing",l:"北京小爷",icon:"🏮",c:"#ef5350",cat:"地域",hot:175},{id:"taiwan",l:"台湾学长",icon:"🧋",c:"#4db6ac",cat:"地域",hot:145},{id:"dongbei",l:"东北大哥",icon:"🧸",c:"#7986cb",cat:"地域",hot:168},{id:"guangdong",l:"广东靓仔",icon:"🫖",c:"#aed581",cat:"地域",hot:132},{id:"shanghai",l:"上海弟",icon:"🌃",c:C.blue,cat:"地域",hot:110},{id:"zhenghuan",l:"甄嬛体",icon:"👸",c:"#ce93d8",cat:"文化梗",hot:312},{id:"crazy",l:"发疯文学",icon:"🤪",c:"#ff8a65",cat:"文化梗",hot:285},{id:"daiyu",l:"林黛玉式",icon:"🥀",c:"#a1887f",cat:"文化梗",hot:198},{id:"xhs",l:"小红书体",icon:"✨",c:"#ff7043",cat:"文化梗",hot:260},{id:"flirtboy",l:"撩男生",icon:"💃",c:"#ec407a",cat:"女性向",hot:195},{id:"queen",l:"高冷御姐",icon:"👑",c:"#8e24aa",cat:"女性向",hot:178},{id:"cutegirl",l:"撒娇甜妹",icon:"🎀",c:"#f06292",cat:"女性向",hot:210}];const TOP8=PERSONAS.filter(p=>p.cat==="高频");
const ZODIACS=[{id:"aries",l:"白羊",icon:"♈",tip:"吃软不吃硬"},{id:"taurus",l:"金牛",icon:"♉",tip:"慢热专一"},{id:"gemini",l:"双子",icon:"♊",tip:"喜欢新鲜感"},{id:"cancer",l:"巨蟹",icon:"♋",tip:"敏感念旧"},{id:"leo",l:"狮子",icon:"♌",tip:"爱面子"},{id:"virgo",l:"处女",icon:"♍",tip:"挑剔认真"},{id:"libra",l:"天秤",icon:"♎",tip:"纠结犹豫"},{id:"scorpio",l:"天蝎",icon:"♏",tip:"占有欲强"},{id:"sagittarius",l:"射手",icon:"♐",tip:"爱自由"},{id:"capricorn",l:"摩羯",icon:"♑",tip:"闷骚慢热"},{id:"aquarius",l:"水瓶",icon:"♒",tip:"独立理性"},{id:"pisces",l:"双鱼",icon:"♓",tip:"浪漫多情"}];
const PURPOSES=[{id:"open",l:"开场",icon:"💬"},{id:"reply",l:"接话",icon:"↩️"},{id:"icebreak",l:"破冰",icon:"🧊"},{id:"push",l:"推进",icon:"📈"},{id:"invite",l:"邀约",icon:"📍"},{id:"care",l:"关心",icon:"💕"},{id:"praise",l:"赞美",icon:"✨"},{id:"tease",l:"调情",icon:"🔥"},{id:"confess",l:"表白",icon:"💘"},{id:"sorry",l:"道歉",icon:"🙏"},{id:"repair",l:"修复",icon:"🔧"},{id:"daily",l:"日常",icon:"☀️"},{id:"special",l:"纪念日",icon:"🎂"},{id:"comfort",l:"安抚",icon:"🫂"},{id:"confirm",l:"确认关系",icon:"🤝"},{id:"reconnect",l:"拉回联系",icon:"🔗"}];
const DPRO={nickname:"",myNickname:"",birthday:"",anniversary:"",city:"",schedule:"",likes:"",dislikes:"",food:"",drink:"",hobbies:"",loveLanguage:"",commStyle:"",sharedJokes:"",recentIssue:"",recentMood:"",recentBusy:"",notes:"",zodiac:"",customPersona:"",gender:"",age:"",job:"",mbti:"",attachment:"",fightStyle:"",dealbreaker:"",petname:"",socialMedia:"",friends:"",family:"",exInfo:"",meetHow:"",togetherSince:""};
const MY_FIELDS=[{k:"myName",l:"我的昵称",i:"👤",p:"小明",g:"基础"},{k:"myGender",l:"性别",i:"⚧",p:"男/女/其他",g:"基础"},{k:"myAge",l:"年龄",i:"🔢",p:"25",g:"基础"},{k:"myBirthday",l:"生日(含时辰)",i:"🎂",p:"1998年5月20日 卯时",g:"基础"},{k:"myCity",l:"所在城市",i:"📍",p:"北京",g:"基础"},{k:"myJob",l:"职业",i:"💼",p:"程序员",g:"基础"},{k:"mySchedule",l:"作息习惯",i:"🕐",p:"夜猫子/早起",g:"基础"},{k:"myZodiac",l:"星座",i:"♈",p:"天蝎",g:"基础"},{k:"myHeight",l:"身高体型",i:"📏",p:"175cm/偏瘦",g:"基础"},{k:"myIncome",l:"收入水平",i:"💰",p:"月入1-2万",g:"基础"},{k:"myEducation",l:"学历",i:"🎓",p:"本科/硕士",g:"基础"},{k:"myMbti",l:"MBTI",i:"🧠",p:"INFJ",g:"性格"},{k:"myAttachment",l:"依恋类型",i:"🔗",p:"焦虑型/回避型/安全型",g:"性格"},{k:"myLoveLanguage",l:"爱的语言",i:"💝",p:"肯定的话/肢体接触",g:"性格"},{k:"myFightStyle",l:"吵架模式",i:"⚔️",p:"追问型/逃避型/讲理型",g:"性格"},{k:"myCommStyle",l:"沟通风格",i:"💬",p:"喜欢打字/喜欢语音",g:"性格"},{k:"myTemper",l:"脾气性格",i:"🌡️",p:"急性子/慢热/暴脾气",g:"性格"},{k:"myLikes",l:"喜好",i:"❤️",p:"打游戏、健身、看电影",g:"喜好"},{k:"myDislikes",l:"雷区（绝对不碰）",i:"🚫",p:"不喜欢被管/讨厌唠叨",g:"喜好"},{k:"myFood",l:"忌口/最爱的食物",i:"🍜",p:"爱吃辣/不吃香菜",g:"喜好"},{k:"myDrink",l:"饮品偏好",i:"🧋",p:"美式/奶茶全糖",g:"喜好"},{k:"myHobbies",l:"兴趣爱好",i:"🎨",p:"健身、读书、旅行",g:"喜好"},{k:"mySocialMedia",l:"常用社交媒体",i:"📱",p:"微信/抖音/B站",g:"喜好"},{k:"myStrength",l:"恋爱优势",i:"💪",p:"细心、幽默、有耐心",g:"自我认知"},{k:"myWeakness",l:"恋爱短板",i:"🫣",p:"容易焦虑、嘴笨、不浪漫",g:"自我认知"},{k:"myDealbreaker",l:"我的底线",i:"🔴",p:"不能撒谎/不能冷暴力",g:"自我认知"},{k:"myExInfo",l:"我的感情经历",i:"📖",p:"谈过2次/没谈过",g:"自我认知"},{k:"myFamily",l:"我的家庭情况",i:"👨‍👩‍👧",p:"独生子/父母在老家",g:"关系"},{k:"myFriends",l:"我的朋友圈",i:"👥",p:"朋友多/社恐",g:"关系"},{k:"myGoal",l:"感情目标",i:"🎯",p:"找到长期伴侣/享受当下",g:"关系"},{k:"myRecentMood",l:"最近情绪状态",i:"🎭",p:"工作压力大/心情不错",g:"动态"},{k:"myRecentBusy",l:"最近在忙",i:"📋",p:"加班/考试/面试",g:"动态"},{k:"myRecentChange",l:"最近的变化",i:"🔄",p:"刚搬家/换工作/开始健身",g:"动态"},{k:"myNotes",l:"其他补充",i:"📝",p:"任何想让AI知道的",g:"动态"}];
const MY_PRO={myName:"",myGender:"",myAge:"",myBirthday:"",myCity:"",myJob:"",mySchedule:"",myZodiac:"",myHeight:"",myIncome:"",myEducation:"",myMbti:"",myAttachment:"",myLoveLanguage:"",myFightStyle:"",myCommStyle:"",myTemper:"",myLikes:"",myDislikes:"",myFood:"",myDrink:"",myHobbies:"",mySocialMedia:"",myStrength:"",myWeakness:"",myDealbreaker:"",myExInfo:"",myFamily:"",myFriends:"",myGoal:"",myRecentMood:"",myRecentBusy:"",myRecentChange:"",myNotes:""};
const PFIELDS=[{k:"nickname",l:"TA的昵称",i:"💕",p:"宝宝",g:"基础"},{k:"gender",l:"TA的性别",i:"⚧",p:"女/男",g:"基础"},{k:"age",l:"TA的年龄",i:"🎂",p:"23",g:"基础"},{k:"myNickname",l:"TA叫我",i:"🏷️",p:"老公",g:"基础"},{k:"birthday",l:"生日(含时辰)",i:"🎁",p:"1999年3月15日 午时",g:"基础"},{k:"anniversary",l:"纪念日",i:"💍",p:"8月20日",g:"基础"},{k:"togetherSince",l:"在一起多久",i:"📅",p:"3个月/2年",g:"基础"},{k:"meetHow",l:"怎么认识的",i:"🤝",p:"朋友介绍/社交软件",g:"基础"},{k:"city",l:"所在城市",i:"📍",p:"上海",g:"基础"},{k:"job",l:"TA的职业",i:"💼",p:"设计师",g:"基础"},{k:"schedule",l:"作息习惯",i:"🕐",p:"早睡/夜猫子",g:"基础"},{k:"zodiac",l:"星座",i:"♈",p:"天蝎",g:"基础"},{k:"mbti",l:"MBTI",i:"🧠",p:"ENFP",g:"性格"},{k:"attachment",l:"依恋类型",i:"🔗",p:"回避型/焦虑型/安全型",g:"性格"},{k:"loveLanguage",l:"爱的语言",i:"💝",p:"喜欢行动>语言",g:"性格"},{k:"fightStyle",l:"吵架模式",i:"⚔️",p:"冷战型/爆发型/讲理型",g:"性格"},{k:"commStyle",l:"沟通风格",i:"💬",p:"喜欢短句/喜欢语音",g:"性格"},{k:"likes",l:"喜好",i:"❤️",p:"奶茶、猫、追剧",g:"喜好"},{k:"dislikes",l:"雷区（绝对不碰）",i:"🚫",p:"不喜欢被催/讨厌迟到",g:"喜好"},{k:"food",l:"忌口/最爱的食物",i:"🍜",p:"不吃辣/爱吃甜",g:"喜好"},{k:"drink",l:"饮品偏好",i:"🧋",p:"三分糖少冰",g:"喜好"},{k:"hobbies",l:"兴趣爱好",i:"🎨",p:"看展、旅行、瑜伽",g:"喜好"},{k:"socialMedia",l:"常用社交媒体",i:"📱",p:"小红书/抖音/微博",g:"喜好"},{k:"petname",l:"你们的专属称呼",i:"🥰",p:"猪猪/笨蛋",g:"沟通"},{k:"sharedJokes",l:"专属梗/暗号",i:"🤣",p:"那次下雨的事",g:"沟通"},{k:"dealbreaker",l:"TA的底线",i:"🔴",p:"不能撒谎",g:"沟通"},{k:"friends",l:"TA的闺蜜/兄弟",i:"👥",p:"小红/小李",g:"关系"},{k:"family",l:"TA的家庭情况",i:"👨‍👩‍👧",p:"独生女/父母离异",g:"关系"},{k:"exInfo",l:"TA的前任情况",i:"💀",p:"分手1年/没有前任",g:"关系"},{k:"recentIssue",l:"最近矛盾",i:"⚡",p:"因为加班吵过",g:"动态"},{k:"recentMood",l:"最近情绪状态",i:"🎭",p:"工作压力大/心情不错",g:"动态"},{k:"recentBusy",l:"最近在忙",i:"📋",p:"出差/面试/考试",g:"动态"},{k:"notes",l:"其他备注",i:"📝",p:"任何有用的信息",g:"动态"},{k:"customPersona",l:"自定义TA的性格",i:"🎭",p:"外冷内热/嘴硬心软",g:"动态"}];
const buildCtx=(pro)=>{if(!pro)return"";const a=[];if(pro.nickname)a.push(`昵称:${pro.nickname}`);if(pro.myNickname)a.push(`TA叫我:${pro.myNickname}`);if(pro.gender)a.push(`TA性别:${pro.gender}`);if(pro.age)a.push(`年龄:${pro.age}`);if(pro.job)a.push(`职业:${pro.job}`);if(pro.city)a.push(`城市:${pro.city}`);if(pro.mbti)a.push(`MBTI:${pro.mbti}`);if(pro.attachment)a.push(`依恋类型:${pro.attachment}(重要,影响回复风格)`);if(pro.loveLanguage)a.push(`爱的语言:${pro.loveLanguage}(TA 最能接收到这种爱)`);if(pro.conflictPattern)a.push(`吵架模式:${pro.conflictPattern}(遇冲突时的 pattern)`);if(pro.likes)a.push(`喜好:${pro.likes}`);if(pro.dislikes)a.push(`⚠️雷区:${pro.dislikes}(绝对避开)`);if(pro.noNo)a.push(`TA底线:${pro.noNo}(不可越)`);if(pro.sharedJokes)a.push(`专属梗:${pro.sharedJokes}(自然融入)`);if(pro.specialCall)a.push(`专属称呼:${pro.specialCall}`);if(pro.recentMood)a.push(`近期情绪:${pro.recentMood}`);if(pro.recentIssue)a.push(`近期矛盾:${pro.recentIssue}`);if(pro.recentBusy)a.push(`最近在忙:${pro.recentBusy}`);if(pro.commStyle)a.push(`沟通风格:${pro.commStyle}`);if(pro.schedule)a.push(`作息:${pro.schedule}`);if(pro.family)a.push(`家庭情况:${pro.family}`);if(pro.exInfo)a.push(`前任情况:${pro.exInfo}(对比参考,别提起)`);if(pro.togetherSince)a.push(`在一起:${pro.togetherSince}`);if(pro.meetHow)a.push(`怎么认识:${pro.meetHow}`);if(pro.customPersona)a.push(`自定义人设:${pro.customPersona}`);const z=pro.zodiac&&ZODIACS.find(x=>x.id===pro.zodiac);if(z)a.push(`TA是${z.l}座(${z.tip})`);return a.length?`\n【TA 档案】${a.join("；")}\n请让回复深度结合以上档案信息——这是核心竞争力。`:"";};
const buildSys=(stageId,personaId,pro,extra)=>{const st=STAGES.find(s=>s.id===stageId);const ps=PERSONAS.find(p=>p.id===personaId);let s=`恋爱沟通专家。阶段：${st?.l||"暧昧"}(${st?.tip||""})。人设：${ps?.l||"高情商"}。`;s+=buildCtx(pro);if(extra)s+=`\n${extra}`;return s;};
const COMFORTS=[{id:"angry",icon:"😤",l:"TA生气了",steps:[{t:"立刻",m:"我知道你在生气，是我不好。你不想说话没关系，我就在这里。"},{t:"10分钟后",m:"认真想了下，你生气是对的。我不该那样。"},{t:"收尾",m:"等你消气了找我，不管多晚。"}],ban:"别说「你想太多」"},{id:"cold",icon:"🧊",l:"冷战中",steps:[{t:"24h后",m:"我不想冷战。不管谁对谁错，我在乎我们好不好。"},{t:"已读不回",m:"你不说话没关系。我在反思，我在乎你。"},{t:"第二天",m:"给你看个有意思的，想到你了。"}],ban:"别说「你冷战到什么时候」"},{id:"wrong",icon:"🤦",l:"说错话了",steps:[{t:"立刻",m:"刚才说得不对，但我知道伤到你了。"},{t:"5分钟后",m:"我应该先想清楚再说。愿意让我补偿吗？"},{t:"收尾",m:"对不起不够，我用行动证明。"}],ban:"别说「我随口一说」"},{id:"late",icon:"⏰",l:"迟到/失约",steps:[{t:"立刻",m:"对不起让你等了，是我的问题。"},{t:"到了后",m:"罚我请你喝最爱的，以后绝不让你等。"},{t:"回去后",m:"因为迟到少了好多时间，周末补偿？"}],ban:"别说「路上堵车」"}];
const ROLE_COLORS={"定位类":"#60a5fa","体检类":"#f59e0b","机制类":"#a78bfa","策略类":"#22d3ee","修复类":"#f87171","经营类":"#fb923c"};
const DEEP_MODS=[{id:"M0",icon:"📊",name:"关系阶梯",fullName:"Knapp 关系阶梯",desc:"你们现在在第几阶？下一步做什么才自然。",role:"定位类",cred:"关系发展研究",give:"认识多久、互动频率、是否见面、是否排他",get:"当前阶段 + 下一阶动作 + 过阶风险"},{id:"M1",icon:"💠",name:"关系三角",fullName:"Sternberg 三角",desc:"亲密、激情、承诺哪里在掉，一眼看清。",role:"体检类",cred:"三角爱情理论",give:"2周互动概况 + 冲突/惊喜 + 未来期待",get:"三维评分 + 短板 + 本周行动"},{id:"M2",icon:"⚖️",name:"投入评估",fullName:"Rusbult 投入模型",desc:"稳不稳不只看甜不甜，还看投入与替代。",role:"体检类",cred:"元分析承诺模型",give:"满意来源/不满 + 替代线索 + 双方投入",get:"四项分析 + 风险位 + 提升路线"},{id:"M3",icon:"🔗",name:"依恋分析",fullName:"成人依恋理论",desc:"你越追TA越躲？识别追逃拉扯机制。",role:"机制类",cred:"依恋理论（主流心理学）",give:"TA常见反应 + 你的惯性模式",get:"双方依恋倾向 + 触发点 + 不踩雷路径",hot:true},{id:"M4",icon:"🎯",name:"沟通档位",fullName:"Hersey 情境沟通",desc:"一句话该硬还是软？选对沟通档位。",role:"策略类",cred:"情境领导模型",give:"关系阶段 + 最近发生什么 + 你的目标",get:"当前档位(S1-S4) + 下一步话术"},{id:"M5",icon:"⚔️",name:"冲突修复",fullName:"Gottman 冲突修复",desc:"吵架不是问题，吵法才是。",role:"修复类",cred:"Gottman伴侣治疗",give:"最近冲突对话 + 各自介意的点",get:"冲突雷区 + 软启动话术 + 修复步骤",hot:true},{id:"M6",icon:"🤝",name:"道歉语言",fullName:"五种道歉语言",desc:"道歉了TA还不满意？用对形式才被接收。",role:"修复类",cred:"沟通工具",give:"你做错什么 + TA最在意的损失点",get:"TA吃的道歉形式 + 模板 + 可发送版本"},{id:"M7",icon:"💬",name:"爱之语",fullName:"五种爱之语",desc:"你做很多TA仍无感？找到TA接收得到的爱。",role:"经营类",cred:"沟通工具",give:"TA在意的瞬间 + 最近矛盾",get:"偏好排序 + 低成本表达清单 + 一周打卡"},{id:"M8",icon:"🎭",name:"爱风格",fullName:"六种爱风格",desc:"慢热vs热恋、务实vs浪漫，风格不合才是误会源头。",role:"机制类",cred:"Lee六种爱风格",give:"见面频率/回复速度/公开程度偏好",get:"风格画像 + 冲突点 + 相处协议"},{id:"M9",icon:"🧬",name:"驱动力",fullName:"Fisher 驱动力",desc:"快速读懂TA的底层驱动。",role:"机制类",cred:"Helen Fisher研究",give:"TA对新鲜感/计划性/社交/情绪的表现",get:"驱动力画像 + 约会偏好 + 避坑"}];

/* ═══ UNIVERSAL_DEEP_TEMPLATE (V2.4 scaffolding) ═══
   中等成本方案：让其他 4 个场景也拿到 AI 驱动的 6 模块分析
   当前状态：代码就位但未启用（mode=full 仍走本地 _bp/_cf/_cd/_ad/_dl 5 模块）
   待办（完整成本方案 - P2）：30 个专属模板（5 场景 × 6 模块）
   通用模板一份，scenario/chain/focus 作为变量注入。 */
const UNIVERSAL_DEEP_TEMPLATE=(scenario,chain,focus,userInput,profile)=>({
sys:`你是基于心理学理论的关系分析师。用户当前处于「${scenario}」场景，焦点是「${focus}」。
请基于以下 ${chain.length} 个心理学模块框架给出分析：${chain.join("、")}。

用户档案：${profile||"无"}

输出严格 JSON：
{
  "summary":{"headline":"<一句总结>","emoji":"💡","short":"<3 句简短诊断>","deep":"<3-5 段深度解释,必须基于用户描述的具体细节>"},
  "moduleCards":[
    {
      "module":"<从${chain.join("/")}中选一个,写出 fullName>",
      "confidence":"high|medium",
      "diag":"<2-3 句基于用户输入的精准诊断>",
      "whys":["<2-3 条原理解释>"],
      "dos":["<5-6 条具体行动建议>"],
      "says":["<4-5 条可直接发送的话术>"],
      "pitfalls":["<3-4 条避坑清单>"]
    },
    // ... 共 ${chain.length} 个 modules
  ],
  "mainScript":"<一句核心行动建议>",
  "thisRoundGoal":"<这次分析的目标>",
  "risk":"<需要警惕的风险>"
}

严格要求：
- 必须引用用户描述中的具体细节（不能泛泛）
- 禁止鸡汤话/"慢慢来就好"套话
- 每个模块必须给可执行话术，不是理论
- 按场景调整语气：分手/挽回→克制+现实；吵架→共情+修复；暧昧→推进+真诚`,
msg:`场景：${scenario}\n用户描述："""${userInput}"""`
});

const DEEP_PROMPTS={
"_bp":[
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💔 分手了。本次分析模块:【关系阶段诊断 (Knapp)】\n理论焦点:Knapp衰减5阶段(分化/界限/停滞/规避/终止)。判断用户和前任处于哪一阶,复合可行性。\n行动指引:基于阶段的具体行动:分化/界限期可低压接触;停滞/规避期需长时间冷却;终止期建议转向自我重建。\n话术风格:低压力分享型,禁过度亲密称呼,禁'我变了'空话要具体证据。\n常见错误:急于表白/用物质挽回/求朋友传话/发长篇忏悔。\n场景特别提醒:若描述显示已分手3+月且TA明确拒绝,confidence=low并暗示转向放下。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💔 分手了。本次分析模块:【依恋模式识别】\n理论焦点:Bowlby依恋+Bartholomew四象限(安全/焦虑/回避/混乱)。识别双方依恋类型+这组合为何分手。\n行动指引:焦虑型练不追,回避型练不逃,做依恋自测,建立安全感日常练习。\n话术风格:去指责化的'我'语言,承认自己模式的诚实表达。\n常见错误:把焦虑当激情,把回避当酷,用测试确认心意,只想改对方不做自我工作。\n场景特别提醒:描述含'忍不住想发消息'→焦虑倾向;'TA突然冷'→前任回避型。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💔 分手了。本次分析模块:【沟通策略 (Hersey)】\n理论焦点:Hersey情境领导改编4档位:S1告知/S2推销/S3参与/S4授权。分手后默认从S4起步。\n行动指引:S4阶段具体频次(每月1-2次低压接触),升档到S3的时机判断,关键转折的深度对话。\n话术风格:S4级低压分享(不追问),朋友圈适度回应,共同场合自然打招呼。\n常见错误:急切用S2发长文,假S4真监视,跳档反复,S4过度成了冷处理。\n场景特别提醒:如果用户描述反复联系,明确指出这是S1/S2档位在分手场景的错误应用。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💔 分手了。本次分析模块:【Gottman冲突修复】\n理论焦点:Gottman四骑士(批评/轻蔑/防御/筑墙)+修复尝试+5:1积极消极比。分手前哪些骑士出现?\n行动指引:承认自己用过的骑士,用软启动公式(我-感受-具体情境-需求),2周积极互动重建。\n话术风格:软启动范例(不指责),自我承认话术,修复尝试接收。\n常见错误:用四骑士回应四骑士,重启同冲突不改模式,把'不吵架'当修复(可能是筑墙)。\n场景特别提醒:若描述含'我就是要让TA知道TA错'→轻蔑,要直接指出是关系#1杀手。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💔 分手了。本次分析模块:【Rusbult投入评估】\n理论焦点:Rusbult四要素(满意/投入/替代/承诺)。诚实判断:想挽回是爱还是沉没成本?\n行动指引:列最近3个月3件开心事vs3件受伤事,问'如果投入归零还会选TA吗',2周独处不挽回看真实感受。\n话术风格:对自己诚实的话,不鸡汤的理性决策语言。\n常见错误:把投入当爱'都这么久了',用恐惧替代选项当爱,把痛苦当深情,为朋友圈叙事留在关系里。\n场景特别提醒:这个模块必须诚实,不能鼓励所有人挽回。如果沉没成本>满意度,明确指出。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💔 分手了。本次分析模块:【自我边界重建】\n理论焦点:Bowlby分手初期'想念'70%是依恋警报非真爱。2周是依恋系统降温临界点。\n行动指引:独自吃3顿饭测孤独,联系3个月没联系的朋友,每天写3件独立的事,屏蔽TA动态2周,运动3次/周。\n话术风格:对TA温和边界('我需要时间'),对自己内心独白('想念≠必须联系')。\n常见错误:立刻删所有痕迹(也是不放下),反复查动态,用暧昧填空缺,找共同朋友打听。\n场景特别提醒:不讨论复合/放下,只讨论自我。具体行动>鸡汤。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
})
],
"_cf":[
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💢 吵架冷战。本次分析模块:【Gottman冲突修复(核心)】\n理论焦点:四骑士识别+修复尝试+软启动。这次吵架里双方各用了哪些骑士?\n行动指引:立即停止辩论谁对错,切换到软启动(我+具体情境+需求),做一次真诚修复尝试,接受TA的修复尝试不死撑。\n话术风格:软启动公式'我看到___我感觉___希望___',自我承认'这点我没做好'。\n常见错误:翻旧账证明你受伤更多,'你总是'开头,沉默筑墙,把修复责任全推给对方。\n场景特别提醒:如果描述含'TA翻白眼/嘲讽我'→是轻蔑,这是关系最危险信号,不只是修复这次吵架的问题。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💢 吵架冷战。本次分析模块:【依恋触发分析】\n理论焦点:识别冲突中各自的依恋触发点。焦虑型吵架怕被抛弃,回避型吵架怕被控制。\n行动指引:识别自己吵架时真实恐惧(是怕TA走还是怕被控制),下次冲突前暂停5分钟做自我核查。\n话术风格:去情绪化表达恐惧'我需要___不是因为控制你是因为___',承认依恋模式。\n常见错误:用威胁分手测爱(焦虑型),消失逃避沟通(回避型),把对方依恋触发当'不爱'。\n场景特别提醒:焦虑-回避组合冲突最常见:一方追一方逃会恶化,需要刻意建立冲突规则。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💢 吵架冷战。本次分析模块:【道歉语言】\n理论焦点:Chapman 5种道歉语言(表达遗憾/承担责任/弥补/真诚悔改/请求原谅)。TA吃哪种?\n行动指引:观察TA过去被什么形式的道歉打动过,尝试未使用过的道歉形式,具体到行为不是口头。\n话术风格:5种不同形式的道歉模板,每种带具体情境适用。\n常见错误:只口头道歉没行为,'对不起但是___'(但是消除了道歉),用礼物代替真诚,反复道歉显得敷衍。\n场景特别提醒:道歉≠承认全错,是承认对方感受真实。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💢 吵架冷战。本次分析模块:【沟通档位 (Hersey)】\n理论焦点:吵架当下该用S3参与型(共同探讨),冷战期该用S4授权型(给空间但不失联)。\n行动指引:当下情绪激烈:S4暂停'我们都冷静2小时';冷静后:S3'我们谈谈',邀请共同决策。\n话术风格:档位切换话术,S3的探讨式开场,S4的不失联低压接触。\n常见错误:吵架当下用S1告知'你必须听我说',S4过度消失几天没交代,跳档反复。\n场景特别提醒:冷战24h内:S4不激化;24-72h:S3可尝试;72h+:需更主动S3。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💢 吵架冷战。本次分析模块:【关系阶段影响】\n理论焦点:吵架对关系阶段的影响。强化/整合期吵架是磨合,停滞期吵架是警讯。\n行动指引:评估这次吵架是'关系加深契机'还是'关系退化信号',根据判断选应对策略。\n话术风格:阶段感知的长期视角话术。\n常见错误:把所有吵架都当'加深感情',忽视重复吵架的阶段退化信号。\n场景特别提醒:半年吵3次同类问题=结构性冲突,不是一次道歉能解决。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💢 吵架冷战。本次分析模块:【冲突后投入评估】\n理论焦点:吵架后重估满意/投入/替代/承诺。重复冲突是核心价值观差异未协商。\n行动指引:列过去半年吵过的3次架找共同模式,每月一次主动关系盘点(不在吵架时),评估4项。\n话术风格:结构性复盘话术'我们不是吵架是解决一个反复问题'。\n常见错误:每次吵完翻篇不谈根因,只看这次对错不看模式,用'都吵这么多次还在一起'当爱。\n场景特别提醒:吵架修复不只是和好,还要预防重复。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
})
],
"_cd":[
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:😶 已读不回/变冷。本次分析模块:【依恋信号识别】\n理论焦点:TA变冷的依恋解读。回避型高压下会撤退,焦虑型变冷是惩罚性失联,安全型变冷多有明确原因。\n行动指引:区分'TA在回避型应激'vs'TA真的在撤离',观察TA对其他人的互动模式作对照,不立即追问。\n话术风格:去压力化的关心'最近怎样'(不是'你怎么不回我'),保持存在但不纠缠。\n常见错误:连发消息验证在不在,情绪化指责'你是不是不爱我了',用第三方打听制造焦虑。\n场景特别提醒:回避型TA在高压下会用沉默,越追越逃;给空间反而更快回温。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:😶 已读不回/变冷。本次分析模块:【S4授权型沟通】\n理论焦点:TA变冷期必须切S4:给空间,低压力存在,不追问,保持连接但不强求。\n行动指引:每周最多1次低压信息,不期待回复,分享不询问,给TA完全的回复自由。\n话术风格:S4级'看到个好玩的分享给你,不用回','天气变了注意'。\n常见错误:假S4真监视(看Ta动态不发消息但焦虑),用S4报复'既然你不回我也不联系',S4过长失联风险。\n场景特别提醒:S4最高2-3周,之后必须有次S3尝试打破僵局,否则关系真的会死。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:😶 已读不回/变冷。本次分析模块:【关系阶段警讯】\n理论焦点:'已读不回/变冷'是Knapp衰减的【界限期】早期信号。如果持续,会进入【停滞期】。\n行动指引:评估这是一次性冷淡(工作压力/情绪低谷)还是结构性衰减,前者等待,后者主动谈'我们最近怎么了'。\n话术风格:不焦虑的关系检查话术,周期性做不是危机才做。\n常见错误:忽视警讯等变严重,过度反应小事,用'测试'TA的冷淡程度。\n场景特别提醒:持续2周+不改善必须主动谈。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:😶 已读不回/变冷。本次分析模块:【爱之语错频】\n理论焦点:Chapman 5爱之语。TA变冷可能不是不爱,是你给的爱TA接收不到,长期错频导致TA疲惫。\n行动指引:回想TA最感动的5次是为什么,对比你最近的付出,连续2周只用1种爱之语试反应。\n话术风格:'你觉得我爱你最多是什么时候'(让TA告诉你TA的爱之语)。\n常见错误:加大原有投入(更错更快),用物质贵重证明爱,要求TA'用我的方式感受爱'。\n场景特别提醒:你送礼物TA不感动≠不爱你,可能TA的爱之语是精心的时刻或肯定的言语。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:😶 已读不回/变冷。本次分析模块:【筑墙诊断】\n理论焦点:Gottman四骑士之筑墙(Stonewalling):拒绝沟通。这是男性更常见的应激反应,85%男性会用。\n行动指引:区分'TA在情绪淹没中需要暂停'和'TA在筑墙回避',给具体时间约定'我们20分钟后再谈',不强迫立即沟通。\n话术风格:破墙话术'我知道你需要时间,20分钟后我们聊,行吗',不指责筑墙行为。\n常见错误:强追'你必须现在说',指责'你就是在逃避',用筑墙回应筑墙双方都僵。\n场景特别提醒:筑墙中的人血压升高明显,生理上真的无法理性沟通。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:😶 已读不回/变冷。本次分析模块:【自我价值锚定】\n理论焦点:TA变冷期最容易自我怀疑。需要外部锚点而非依赖TA确认自我价值。\n行动指引:列'我的核心吸引力不来自这段关系'3条,加强工作/朋友/爱好等非关系领域,每周做1件让自己骄傲的事。\n话术风格:对自己的独白'TA冷淡≠我不好',对朋友'我在处理关系但不会崩塌'。\n常见错误:把全部注意力放在分析TA上,用TA的态度定义自我价值,忽视朋友/家人/工作。\n场景特别提醒:你的吸引力不需要TA回复才存在。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
})
],
"_ad":[
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💕 暧昧推进。本次分析模块:【Knapp上升阶段】\n理论焦点:Knapp建立5阶段(接触/实验/强化/整合/结合)。暧昧期多在实验-强化阶段,判断当前阶+下一步。\n行动指引:评估当前阶段(1-5),做相应阶段的任务(实验期:扩展话题范围;强化期:加深情感投入;整合期:彼此朋友介绍)。\n话术风格:阶段合适的推进话术,不跳级。\n常见错误:急着贴标签(实验期谈恋爱合同),跳级推进表白,阶段停滞不前超6个月。\n场景特别提醒:Knapp 5阶段每阶有自己任务,跳过不可持续。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💕 暧昧推进。本次分析模块:【Sternberg三角评估】\n理论焦点:Sternberg三角(亲密/激情/承诺)。暧昧期高激情+中亲密+低承诺,目标是所有维度同步加深。\n行动指引:评估3维度现状,针对最弱那维补齐(如亲密低:深入对话;激情低:新鲜体验;承诺低:未来对话)。\n话术风格:加深亲密的深度话题开场,保持激情的惊喜动作。\n常见错误:只堆积激情忽视亲密(性吸引强但聊不了深),承诺压力过早('我们以后...')。\n场景特别提醒:三维度都加深才是真爱;单一维度爆表是暂时迷恋。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💕 暧昧推进。本次分析模块:【Fisher驱动力】\n理论焦点:Fisher 4种驱动力(探索者/建造者/引领者/协商者),不同类型吸引不同,冲突也不同。\n行动指引:识别TA和自己的类型,用TA喜欢的约会方式(探索者:新奇体验;建造者:稳定承诺;引领者:智力挑战;协商者:深度共鸣)。\n话术风格:类型对应的话题和约会邀请。\n常见错误:用自己喜欢的方式去讨好TA,忽视TA的驱动力类型。\n场景特别提醒:类型不是标签,是沟通偏好。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💕 暧昧推进。本次分析模块:【推进档位 (Hersey)】\n理论焦点:暧昧期从S3参与型逐步推进到S2推销型(表达明确意图)。\n行动指引:S3共同探索(共同做事),时机成熟切S2表达意图'我挺喜欢和你相处的'。\n话术风格:S3邀请式话术,S2表达式话术,判断升档时机。\n常见错误:一直S3暧昧不表态,太早S1告知'我们确定关系吧',跳档变突兀。\n场景特别提醒:升档信号:TA主动分享私人事+约会频率稳定+见共同朋友。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💕 暧昧推进。本次分析模块:【早期承诺评估】\n理论焦点:Rusbult早期承诺形成=满意度高+投入逐步加深+替代吸引力降低。\n行动指引:评估自己满意度(TA真的让你开心还是新鲜?),观察TA是否排除其他选项,投入是否对等。\n话术风格:探索承诺的话题'你现在怎么看我们',不施压。\n常见错误:把激情当承诺,单方面投入过多,忽视替代选项信号(TA还在约别人)。\n场景特别提醒:承诺需要双向+时间+证据,不是几次约会就有。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💕 暧昧推进。本次分析模块:【依恋预判】\n理论焦点:暧昧期最易被本能驱动,识别双方依恋类型预判关系走向。焦虑-回避组合最痛苦。\n行动指引:观察TA压力下反应,观察TA谈前任方式,做依恋自测。\n话术风格:依恋敏感的沟通'我需要稳定节奏','我不是控制只是担心'。\n常见错误:把焦虑当激情,把回避当酷,早期贴标签操控对方。\n场景特别提醒:暧昧期40%的'爱'是焦虑,3-6个月才显真依恋模式。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
})
],
"_dl":[
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💑 日常稳定。本次分析模块:【三角维护】\n理论焦点:稳定期易失平衡:激情衰减,亲密趋于日常,承诺稳定但可能空心化。\n行动指引:识别最弱维度补齐,每月1次惊喜(激情),每周1次深度对话(亲密),每季度讨论未来(承诺)。\n话术风格:维护各维度的日常话术。\n常见错误:以为稳定=不用经营,只维持承诺忽视激情/亲密,把熟悉当亲密。\n场景特别提醒:激情可被重新点燃(做新事),不是彻底消失。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💑 日常稳定。本次分析模块:【爱之语匹配】\n理论焦点:长期关系中爱之语错频是第一隐形杀手。'我为TA做了那么多,TA怎么感觉不到'。\n行动指引:做一次爱之语测试,2周只用TA主语言,观察反应变化,制定长期爱之语清单。\n话术风格:TA主爱之语对应的日常表达。\n常见错误:用自己的爱之语给,加大投入不改方式,'我都做这么多了你还不满意'。\n场景特别提醒:每个人主要爱之语通常1-2种,其他都是次要。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💑 日常稳定。本次分析模块:【自我扩展理论】\n理论焦点:Aron自我扩展理论:关系满意度 = 通过对方扩展自我的体验。停止扩展=关系老化。\n行动指引:共同尝试新事物(新餐厅/旅行/技能),定期深度对话探索TA未知面,保留各自成长空间。\n话术风格:探索式'我们还没一起试过___','你最近在想什么'。\n常见错误:生活高度重复/只谈实用(几点到家/钱),不再对TA好奇,把TA当已知。\n场景特别提醒:静止是关系老化的真凶,不是矛盾。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💑 日常稳定。本次分析模块:【日常沟通档位】\n理论焦点:稳定期日常用S3参与型(共同决策),关键事项S2推销(解释意图),危机时S1告知。\n行动指引:日常事S3共同决定(吃什么/周末),大事S2解释决定的理由,争议时S3不S1。\n话术风格:参与式'我想___你觉得呢',解释式'我决定这样是因为___'。\n常见错误:S1过度'就这么定了',全部S3导致小事都难决(决策疲劳),危机还S3不果断。\n场景特别提醒:稳定不等于不沟通,是沟通成了默契。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💑 日常稳定。本次分析模块:【长期投入审视】\n理论焦点:长期关系的满意/投入/替代/承诺会动态变化。定期检查防止滑向'凑合'。\n行动指引:每季度自评4要素,诚实评估替代选项(不是要出轨是保持自我评估),检查承诺是真心还是惯性。\n话术风格:结构性关系盘点话术,不危机导向。\n常见错误:以为结了婚就不用评,把投入当爱,低替代选项导致凑合,惯性承诺。\n场景特别提醒:好关系经得起诚实评估。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
}),
(t,pro)=>({
sys:`你是受训关系咨询师。熟读Gottman/Sternberg/Chapman/Bowlby/Rusbult/Knapp/Hersey/Fisher/Aron。规则:不鼓励操控,不PUA,不虚假承诺,中文口语不翻译腔。只输出JSON,不要markdown或解释。每字段基于用户描述的具体事实,禁鸡汤。检测到暴力/出轨/自伤则输出{"redirect":true,"title":"<warn>","message":"<why>","resources":["12338妇女维权","110","400-161-9995心理援助"],"advice":"<一句>"}。\n\n场景:💑 日常稳定。本次分析模块:【关系阶段审查】\n理论焦点:Knapp整合/结合期最怕静止。停留同阶超6个月开始退化。\n行动指引:识别当前阶段(整合还是结合),制造适度关系挑战(旅行/合作项目),定期聊未来5年10年。\n话术风格:深度阶段话题'我们5年后会是什么样'。\n常见错误:以为稳定=好,用琐事填对话,避免未来讨论怕压力。\n场景特别提醒:停滞>冲突对长期关系更致命。\n\n输出严格JSON:{"module":"<name>","confidence":"high|medium|low","diag":"<2-3句基于用户描述的精准诊断>","whys":["<5条原理或证据,每条引用用户描述>"],"dos":["<5-6条具体可执行动作,带频次>"],"says":["<5条可直接发送话术,<30字>"],"pitfalls":["<5条典型错误>"]}`,
msg:`【用户档案】${pro||"无"}\n【场景描述】"""${t}"""`
})
]
};


const DEEP_SCENARIOS=[{icon:"😶",label:"已读不回/变冷淡",chain:["M0","M3","M4","M1"],focus:"降压+设窗口+不触发回避",hint:"描述TA最近的变化：什么时候开始冷淡的？之前你们的互动节奏是什么样？"},{icon:"💢",label:"吵架/冷战后修复",chain:["M5","M6","M3","M4"],focus:"先止损再修复语言",hint:"描述这次冲突：因为什么吵的？谁先冷战的？冷了多久？"},{icon:"💕",label:"暧昧推进/表态",chain:["M0","M1","M4"],focus:"推进到「刚好下一阶」",hint:"描述你们的现状：认识多久？约会过几次？聊天频率？谁更主动？"},{icon:"🤔",label:"评估要不要继续",chain:["M2","M1","M0","M3"],focus:"结构判断+体面止损/重建",hint:"描述你犹豫的原因：哪些好的哪些不好的？TA的态度？你的底线？"},{icon:"💔",label:"分手了",chain:["M2","M3","M0","M1"],focus:"情绪处理+理性评估+是否挽回",hint:"描述分手经过：谁提的？原因是什么？分开多久了？还有联系吗？"}];
const FEEDBACK_BTNS=[{icon:"😊",label:"对方积极回复",tone:"positive"},{icon:"😐",label:"对方冷淡",tone:"cold"},{icon:"😶",label:"发了未回复",tone:"no_reply"},{icon:"🙈",label:"我没发（忍住了）",tone:"not_sent"}];
const HORSEMEN=[{name:"批评",icon:"⚔️",sign:"你总是.../你从来不...",antidote:"软启动：用「我」开头说感受",template:"我觉得...我希望..."},{name:"蔑视",icon:"😤",sign:"嘲讽/翻白眼/鄙视",antidote:"欣赏文化：每天说一件感谢TA的事",template:"我很感谢你*__"},{name:"防御",icon:"🛡️",sign:"那是因为你先.../不是我的错",antidote:"承担责任（哪怕一小部分）",template:"你说的有道理，这部分确实是我___"},{name:"石墙",icon:"🧱",sign:"沉默/已读不回/离开/冷战",antidote:"自我安抚 + 约定重启时间",template:"我现在需要冷静20分钟，但我保证会回来聊。"}];
const REPAIR_STAGES=[{phase:"止损",time:"冲突正在发生",action:"识别四骑士 → 立刻降温",template:"我刚刚语气重了，我想要的是被理解，不是要赢。"},{phase:"修复尝试",time:"冲突后0-6小时",action:"主动发起修复信号",template:"我们能不能把事实和感受分开聊？"},{phase:"复盘",time:"冲突后24-48小时",action:"结构化回顾",template:"上次那件事：发生了什么 → 我需要的是___ → 下次我们可以___"}];
const ENGINES=[{id:"E1",name:"四骑士风险筛查",parent:"M5",trigger:"吵架/冷战/指责/翻旧账",cred:"Gottman"},{id:"E2",name:"口述历史叙事评估",parent:"M5",trigger:"要不要继续/会不会分手",cred:"Gottman分手预测"},{id:"E3",name:"追问-退避循环",parent:"M3",trigger:"已读不回/冷战/越问越躲",cred:"依恋理论"},{id:"E4",name:"VSA压力系统",parent:"M2",trigger:"外部压力被归因成不爱",cred:"脆弱-压力适应模型"},{id:"E5",name:"分化与边界",parent:"M4",trigger:"控制/讨好/情绪失控",cred:"分化理论"},{id:"E6",name:"自我扩展任务",parent:"M1",trigger:"没感觉了/像室友/激情低",cred:"自我扩展理论"}];
const KB_TRANS=[{input:"再说吧",subtexts:[{t:"现在不确定，想保留空间",pct:52,tag:"犹豫"},{t:"婉拒但不想说绝",pct:33,tag:"软拒"},{t:"看心情",pct:15,tag:"观望"}]},{input:"没事",subtexts:[{t:"有事，但不想说",pct:62,tag:"压抑"},{t:"不想继续这话题",pct:25,tag:"转移"},{t:"字面意思",pct:13,tag:"字面"}]},{input:"你开心就好",subtexts:[{t:"我很不开心，但不想当坏人",pct:55,tag:"委屈"},{t:"我放弃争取了",pct:30,tag:"投降"},{t:"真心希望你开心",pct:15,tag:"真诚"}]},{input:"随便吧",subtexts:[{t:"不随便，你的提议没踩中",pct:48,tag:"消极"},{t:"懒得再争了",pct:35,tag:"投降"},{t:"真的随便",pct:17,tag:"字面"}]},{input:"呵呵",subtexts:[{t:"敷衍，不想聊了",pct:45,tag:"冷淡"},{t:"觉得好笑但懒得打字",pct:30,tag:"敷衍"},{t:"尴尬",pct:25,tag:"尬"}]},{input:"我没生气",subtexts:[{t:"我在生气，但不想承认",pct:65,tag:"否认"},{t:"比生气更严重——失望",pct:22,tag:"失望"},{t:"真没生气只是累",pct:13,tag:"字面"}]},{input:"你忙吧",subtexts:[{t:"我觉得你不重视我",pct:52,tag:"暗示"},{t:"各忙各的",pct:28,tag:"平行"},{t:"生气了不想说话",pct:20,tag:"冷战"}]},{input:"算了不说了",subtexts:[{t:"说了也没用",pct:48,tag:"绝望"},{t:"你应该主动来问",pct:32,tag:"测试"},{t:"话题太累放弃",pct:20,tag:"疲惫"}]},{input:"嗯/哦/好",subtexts:[{t:"敷衍回复，没兴趣聊",pct:40,tag:"敷衍"},{t:"在忙，但回了你",pct:35,tag:"在忙"},{t:"不知道怎么接",pct:25,tag:"无话"}]},{input:"都行/看你",subtexts:[{t:"你决定但别选错",pct:45,tag:"测试"},{t:"懒得想了",pct:30,tag:"倦怠"},{t:"真的都行",pct:25,tag:"随和"}]}];
const RP_SCENES=[{id:"lor",icon:"👻",label:"已读不回",setup:"你们昨晚聊得很开心，但今天你发了消息后TA已读不回3小时。",hint:"降压，不追问"},{id:"fight",icon:"🧊",label:"吵架冷战",setup:"昨晚因迟到吵架，TA说「行吧随便你」后18小时没消息。",hint:"软启动，不用绝对词"},{id:"dtr",icon:"💕",label:"确认关系",setup:"暧昧2个月约会6次天天聊到深夜，但没人表白。",hint:"直球表达，不质问"},{id:"jealous",icon:"😤",label:"吃醋了",setup:"TA发了一张和异性朋友的合照，你心里不舒服。",hint:"轻松表达，不审问"},{id:"longdist",icon:"✈️",label:"异地想念",setup:"异地3个月，最近聊天越来越短。",hint:"表达想念，不施压"},{id:"ex",icon:"💀",label:"前任联系",setup:"TA的前任突然给TA发了消息，TA跟你提了。",hint:"表达信任，不审问"},{id:"space",icon:"🫧",label:"需要空间",setup:"最近TA黏得太紧，你需要独处但怕伤害TA。",hint:"正面表达需求"},{id:"future",icon:"🔮",label:"谈未来",setup:"在一起8个月想聊未来规划。",hint:"开放引入，不太具体"}];
const COMFORT_CHALLENGES=[{id:"angry_gf",icon:"😤",label:"女友生气了",desc:"你忘了她的生日",opening:"你知道今天什么日子吗？算了，你肯定不记得。",diff:"🟡中"},{id:"cold_war",icon:"🧊",label:"冷战48小时",desc:"因为加班吵架",opening:"你就知道工作工作，我算什么？",diff:"🔴难"},{id:"said_wrong",icon:"🤦",label:"说错话了",desc:"不小心提了前任",opening:"你心里还想着她是吧？",diff:"🔴难"},{id:"forgot_anniv",icon:"📅",label:"忘纪念日",desc:"今天是恋爱100天",opening:"今天什么都不说了。",diff:"🟡中"},{id:"too_straight",icon:"🤖",label:"直男检测",desc:"她问「我胖了吗」",opening:"你觉得我最近是不是胖了？",diff:"🟢易"}];
const DATE_GUIDES=[{icon:"🌙",title:"城市夜间散步",loc:"步行街/河边",dur:"2h",tags:["浪漫","轻松"],prep:["穿舒适的鞋子","带奶茶","手机充满电"],topics:["你平时喜欢这个时间出来走走吗？","如果可以去任何城市散步，你选哪里？","分享你小时候最开心的回忆？"],tips:"走路时保持适当距离。如果TA冷了借外套是经典加分项。",bestTime:"晚上 7-9 点"},{icon:"🍳",title:"一起做饭",loc:"你/TA的厨房",dur:"3h",tags:["亲密","互动"],prep:["提前买好食材","选一道你会做的菜","准备蓝牙音箱"],topics:["你小时候最爱吃妈妈做的什么菜？","做饭和谈恋爱有什么共同点？","我们给这道菜取个名字吧"],tips:"让TA做简单的部分，你负责掌勺。过程比吃饭本身更重要。",bestTime:"周末下午 3-4 点"},{icon:"🎲",title:"桌游咖啡馆",loc:"本地桌游吧",dur:"2.5h",tags:["互动","有趣"],prep:["了解几款热门桌游","选人少的工作日下午"],topics:["你之前玩过桌游吗？","输了的人请喝咖啡？","从游戏风格能看出性格吗？"],tips:"选合作类桌游而非对抗类，两人一队更拉近距离。",bestTime:"工作日下午 2-5 点"},{icon:"🏃",title:"晨跑+早午餐",loc:"附近公园",dur:"2.5h",tags:["健康","活力"],prep:["确认TA运动水平","规划3-5公里路线","预订早午餐店"],topics:["你平时运动多吗？","跑完去吃超棒的早午餐","两个人运动有什么不同？"],tips:"配合TA的节奏跑。跑完一起吃饭是最好的聊天时间。",bestTime:"周末早上 8-9 点"},{icon:"🎨",title:"手作体验",loc:"陶艺/烘焙/花艺",dur:"2h",tags:["浪漫","互动"],prep:["提前预约","穿不怕脏的衣服"],topics:["你之前做过手工吗？","我把这个送你当纪念品","你是创意型还是执行型？"],tips:"一起手忙脚乱很有趣。做完互赠作品是很好的纪念。",bestTime:"周末下午 2-4 点"},{icon:"🎬",title:"看展/露天电影",loc:"美术馆/公园",dur:"2-3h",tags:["轻松","浪漫"],prep:["查展览信息","带野餐垫"],topics:["你觉得这幅画在表达什么？","你喜欢什么类型的电影？","看完去喝杯咖啡聊感想？"],tips:"看展时不要一直讲解，多问TA的感受。",bestTime:"周末下午"}];
/* ═══ v2.5 Plan C: Intent-based categorization ═══ */
const V25_INTENTS=[
  {id:"all",icon:"🌸",l:"全部",d:"",c:"#E84D8C"},
  {id:"newbie",icon:"🌱",l:"新手入门",d:"不会说话/怕说错",c:"#34D399"},
  {id:"pursue",icon:"💘",l:"追求推进",d:"认准一个人,想推进",c:"#F472B6"},
  {id:"repair",icon:"🔧",l:"关系修复",d:"冷战/吵架/挽回",c:"#0EA5E9"},
  {id:"safety",icon:"🛡️",l:"识别自保",d:"PUA/渣男/边界",c:"#DC2626"},
  {id:"nurture",icon:"🎁",l:"经营守护",d:"约会/送礼/纪念日",c:"#F59E0B"},
  {id:"fun",icon:"🎮",l:"趣味测试",d:"放松/测一测",c:"#A78BFA"},
  {id:"bonus",icon:"✨",l:"福利",d:"邀请好友",c:"#EC4899"}
];
const V25_INTENT_MAP={
  /* 新手入门 */opener:"newbie",praise:"newbie",soft:"newbie",initiate:"newbie",mr:"newbie",decode:"newbie",lovelang:"newbie",waitprob:"newbie",
  /* 追求推进 */pace:"pursue",ask_out:"pursue",heat_up:"pursue",test_him:"pursue",confess:"pursue",evidence:"pursue",mirror:"pursue",chess:"pursue",roleplay_pro:"pursue",levels:"pursue",
  /* 关系修复 */breakice:"repair",responsibility:"repair",reconcile:"repair",predict:"repair",countdown:"repair",hole:"repair",fire:"repair",comm:"repair",
  /* 识别自保 */scam:"safety",scam_v2:"safety",npd_check:"safety",blacklist:"safety",boundary:"safety",damage:"safety",shine:"safety",
  /* 经营守护 */date_spot:"nurture",gift_rec:"nurture",anniv:"nurture",anniv_push:"nurture",long_dist:"nurture",compat:"nurture",color:"nurture",daily:"nurture",aipartner:"nurture",
  /* 趣味测试 */fortune:"fun",wrapped:"fun",battle:"fun",polar:"fun",progress:"fun",
  /* 福利 */invite:"bonus"
};
/* Stage → recommended intents (ordered) */
const V25_STAGE_INTENTS={
  stranger:["newbie","fun"],new:["newbie","pursue"],warm:["pursue","nurture"],flirt:["pursue","newbie"],hot:["nurture","pursue"],stable:["nurture","repair"],long:["nurture","repair"],cold:["repair","safety"],back:["nurture","repair"],work:["safety","newbie"],blind:["newbie","fun"],married:["nurture","repair"],breakup:["repair","safety"]
};
/* Stage → top 3 recommended feature IDs */
const V25_STAGE_TOP3={
  stranger:["opener","mr","praise"],
  new:["opener","praise","lovelang"],
  warm:["pace","decode","lovelang"],
  flirt:["heat_up","test_him","evidence"],
  hot:["roleplay_pro","gift_rec","date_spot"],
  stable:["anniv","gift_rec","date_spot"],
  long:["long_dist","anniv_push","date_spot"],
  cold:["breakice","responsibility","reconcile"],
  back:["reconcile","responsibility","breakice"],
  work:["boundary","shine","opener"],
  blind:["opener","mr","praise"],
  married:["anniv","responsibility","gift_rec"],
  breakup:["reconcile","hole","shine"]
};
/* v2.5 Recommended emoji sticker pack (use Unicode as images) */
/* ═══ v2.5 Plan C+ Twemoji CDN helper ═══ */
/* Twemoji CDN base. Admin can override by setting globalThis.__SAKURA_EMOJI_CDN before app loads */
const TWEMOJI_BASE=(typeof globalThis!=="undefined"&&globalThis.__SAKURA_EMOJI_CDN)||"https://cdn.jsdelivr.net/gh/twitter/twemoji@v14.0.2/assets/72x72/";
const twemojiUrl=(em)=>{try{const cps=[...em].map(c=>c.codePointAt(0).toString(16)).filter(c=>c!=="fe0f");if(cps.length===0)return"";return`${TWEMOJI_BASE}${cps.join("-")}.png`;}catch{return"";}};

/* Expanded sticker packs — 8 categories, ~120 stickers */
const V25_STICKERS={
  love:["❤️","🧡","💛","💚","💙","💜","🖤","🤍","🤎","💕","💖","💗","💘","💝","💞","💟","❣️","💌","💋","🥰","😘","😍","🤗","😊","🫶","💑","💏"],
  sad:["🥺","😢","😭","💔","😞","😔","😟","🙁","😕","😣","😓","😩","😫","😪","🙍","🙍‍♀️","🙍‍♂️","😿"],
  cute:["🐰","🐻","🐼","🦊","🐱","🐶","🐨","🐹","🐣","🐥","🐧","🐳","🦄","🐉","🌸","🌷","🌹","🌺","🌼","🌻","🌈","☁️","⭐","✨","🎀","🎐","🎁"],
  cool:["😎","🔥","💪","✌️","🙌","👍","💯","⚡","🚀","🎯","🏆","👑","🥇","🎖️","💎","🌟","⚔️","🛡️"],
  funny:["😂","🤣","😅","😆","😜","🙃","🤪","🤭","😏","🤨","🫢","🫣","😹","🙈","🙉","🙊"],
  sorry:["🥹","😔","🙇","🙇‍♀️","🙇‍♂️","💐","🌹","🎁","🙏","💌","🤝","👉👈","🫴"],
  food:["🍓","🍰","🎂","🍫","🍬","🍭","🧁","🍩","🍪","☕","🧋","🍵","🥤","🍺","🍷","🍶","🎂","🍔","🍕","🍜"],
  gestures:["👋","🤚","🖐️","✋","🖖","👌","🤌","🤏","✌️","🤞","🫰","🤟","🤘","🤙","👈","👉","👆","🖕","👇","👍","👎","👊","✊","🤛","🤜","👏","🫶","🙌","👐","🤲","🙏"]
};

VIRAL_GAMES=[{id:"damage",icon:"💔",l:"伤害计算器",d:"这句话伤害值多少",c:"#FF6B8A",cat:"测试"},{id:"battle",icon:"⚔️",l:"情话Battle",d:"和AI比谁更甜",c:"#FFC857",cat:"对战"},{id:"predict",icon:"🔮",l:"分手预测",d:"Gottman 6维存活率",c:"#a78bfa",cat:"测试"},{id:"color",icon:"🎨",l:"关系色卡",d:"生成专属颜色",c:"#8B9CFF",cat:"趣味"},{id:"compat",icon:"💕",l:"默契测试",d:"10维同步率",c:"#E879F9",cat:"测试"},{id:"mr",icon:"🧠",l:"读心术",d:"测TA心理画像",c:"#8B9CFF",cat:"测试"},{id:"comm",icon:"🎧",l:"实时旁白",d:"逐句解读潜台词",c:"#FFC857",cat:"读心"},{id:"fire",icon:"🚒",l:"救火投票",d:"两句话选哪句发",c:"#FF8F5E",cat:"对战"},{id:"hole",icon:"🌳",l:"树洞",d:"写出心里话·AI温暖回复",c:"#A8E6CF",cat:"表达"},{id:"fortune",icon:"🔮",l:"恋爱算命",d:"姓名配对·缘分指数",c:"#E879F9",cat:"趣味"},{id:"countdown",icon:"⏳",l:"分手倒计时",d:"预测关系存活天数",c:"#a78bfa",cat:"测试"},{id:"daily",icon:"📅",l:"今日挑战",d:"每天一道恋爱题",c:"#3aaa9c",cat:"每日"},{id:"polar",icon:"⚡",l:"争议投票",d:"极化恋爱辩题",c:"#FF6B8A",cat:"对战"},{id:"wrapped",icon:"🎁",l:"恋爱年报",d:"生成你的恋爱总结",c:"#FF6B8A",cat:"趣味"},{id:"blacklist",icon:"⚠️",l:"渣男渣女举报",d:"匿名举报·记录渣点",c:"#e04040",cat:"表达"},{id:"aipartner",icon:"💬",l:"数字恋人",d:"AI陪聊·温暖陪伴",c:"#FF8F5E",cat:"陪伴"},{id:"progress",icon:"📊",l:"战绩系统",d:"段位·成就·XP",c:"#3aaa9c",cat:"成长"},{id:"levels",icon:"🎮",l:"6级闯关",d:"层层递进",c:"#a78bfa",cat:"测试"},{id:"scam",icon:"🔍",l:"渣男探测器",d:"8维度渣点扫描",c:"#e04040",cat:"安全"},{id:"chess",icon:"♟️",l:"恋爱棋局",d:"AI对话推演·段位",c:"#8B9CFF",cat:"实战"},{id:"opener",icon:"✨",l:"真诚开场库",d:"基于细节的真诚开场",c:"#FFC857",cat:"男性"},{id:"praise",icon:"💌",l:"夸人教练",d:"具体细节的真诚赞美",c:"#FFB7C5",cat:"男性"},{id:"soft",icon:"🤲",l:"温柔表达",d:"男性向温柔示弱话术",c:"#A8E6CF",cat:"男性"},{id:"waitprob",icon:"🎯",l:"没回的真相",d:"冷静的概率分布",c:"#8B9CFF",cat:"男性"},{id:"lovelang",icon:"📖",l:"爱之语雷达",d:"Chapman 五种爱之语",c:"#E879F9",cat:"男性"},{id:"mirror",icon:"🪞",l:"追的对吗",d:"关系热度自检",c:"#7B6EF5",cat:"男性"},{id:"initiate",icon:"🦋",l:"不掉价的主动",d:"有自信的主动表达",c:"#FFB7C5",cat:"女性"},{id:"decode",icon:"🎭",l:"直男翻译机",d:"男生话语解码",c:"#FF8F5E",cat:"女性"},{id:"boundary",icon:"🌿",l:"软边界",d:"温柔但清晰的拒绝",c:"#3AAA9C",cat:"女性"},{id:"shine",icon:"💎",l:"吸引力盘点",d:"我的核心价值清单",c:"#a78bfa",cat:"女性"},{id:"evidence",icon:"🔮",l:"他喜欢我吗",d:"基于行为的证据诊断",c:"#E879F9",cat:"女性"},{id:"confess",icon:"🌅",l:"告白前夜",d:"清醒决策助手",c:"#FFC857",cat:"女性"},{id:"pace",icon:"🎯",n:"升温节奏",d:"Knapp关系阶梯分析",c:"#F97316",cat:"男性"},{id:"anniv",icon:"🎂",n:"纪念日不翻车",d:"Chapman爱之语方案",c:"#EC4899",cat:"男性"},{id:"breakice",icon:"❄️",n:"冷战破冰",d:"Gottman三段式软启动",c:"#0EA5E9",cat:"女性"},{id:"reconcile",icon:"🤔",n:"挽回前自检",d:"分手决策五问",c:"#9333EA",cat:"女性"},{id:"ask_out",icon:"🎀",n:"主动约他",d:"不掉价的邀约",c:"#F472B6",cat:"女性"},{id:"heat_up",icon:"🔥",n:"暧昧升温",d:"女性视角推进节奏",c:"#FB7185",cat:"女性"},{id:"test_him",icon:"💭",n:"试探心意",d:"不逼问的观察法",c:"#C084FC",cat:"女性"},{id:"long_dist",icon:"✈️",n:"异地维护",d:"低频关系的维护",c:"#60A5FA",cat:"女性"},{id:"roleplay_pro",icon:"🎭",l:"专属模拟对话",d:"Pro · 基于双方档案深度演练",c:"#c9306b",cat:"Pro"},{id:"responsibility",icon:"⚖️",l:"双方责任分析",d:"不判对错 · 各自改进方向",c:"#0EA5E9",cat:"修复"},{id:"date_spot",icon:"📍",l:"约会地点推荐",d:"基于档案的定制建议",c:"#10b981",cat:"约会"},{id:"gift_rec",icon:"🎁",l:"送礼推荐",d:"基于 TA 爱之语 + 档案",c:"#f59e0b",cat:"约会"},{id:"scam_v2",icon:"🕵️",l:"深度鉴渣",d:"12 维 PUA + NPD 综合扫描",c:"#dc2626",cat:"自保"},{id:"npd_check",icon:"🧠",l:"NPD 识别",d:"自恋型人格 9 诊断",c:"#7c3aed",cat:"自保"},{id:"invite",icon:"🎉",l:"邀请好友",d:"拉 1 人 = 3 天 Pro 体验",c:"#E84D8C",cat:"福利"},{id:"anniv_push",icon:"🔔",l:"纪念日提醒",d:"网页推送 · 不错过重要日子",c:"#ec4899",cat:"维护"}];
const ARTICLES=[{id:1,icon:"🧩",title:"依恋理论入门",sub:"你是焦虑型还是回避型？",tag:"心理学",content:"依恋理论认为人的恋爱模式源于童年。焦虑型渴望亲密但害怕被抛弃；回避型珍视独立害怕被束缚；安全型能舒适地给予和接受爱。了解自己和对方的类型，是改善关系的第一步。"},{id:2,icon:"🐴",title:"Gottman四骑士",sub:"关系中的4个致命信号",tag:"冲突",content:"批评（攻击人格而非行为）、蔑视（翻白眼、讽刺）、防御（反咬一口）、石墙（冷暴力不回应）。出现这4种模式，关系破裂概率超过90%。识别它们是修复的起点。"},{id:3,icon:"💬",title:"软启动 vs 硬启动",sub:"吵架的第一句话决定结局",tag:"沟通",content:"「你总是迟到！」是硬启动，触发防御。「我等你的时候有点着急」是软启动，表达感受不攻击。研究发现：用软启动开始的冲突，96%能以积极方式结束。"},{id:4,icon:"🔥",title:"推拉的艺术",sub:"暧昧期的核心技巧",tag:"技巧",content:"推：制造距离和神秘感。拉：给出明确的好感信号。关键是节奏——不是忽冷忽热，而是让对方始终保持好奇和期待。"},{id:5,icon:"🛡️",title:"识别情感操控",sub:"PUA的常见话术",tag:"安全",content:"道德绑架、煤气灯效应、例外化、贬低自尊、条件式爱、恐吓控制、比较打压、制造亏欠。遇到3个以上请认真考虑离开。"},{id:6,icon:"📊",title:"Sternberg爱情三角",sub:"亲密+激情+承诺",tag:"心理学",content:"只有激情=迷恋，只有承诺=空洞的爱，只有亲密=友情。理想关系需要三者平衡。热恋期激情高但承诺低，稳定期反之——这是正常的，需要主动经营。"}];
const PUA_PATTERNS=[{pattern:"你和别的女生不一样",tag:"例外化",risk:85,explain:"通过贬低其他女性来制造你的特殊感和依赖"},{pattern:"我对你这么好你还怀疑",tag:"道德绑架",risk:90,explain:"用付出来压制你的合理质疑"},{pattern:"你太敏感了",tag:"煤气灯效应",risk:95,explain:"否定你的感受让你怀疑自己的判断"},{pattern:"如果你真爱我就应该",tag:"条件式爱",risk:90,explain:"用「真爱」设条件来控制行为"},{pattern:"换别人早就受不了了",tag:"制造亏欠",risk:85,explain:"暗示你应该感恩他的包容"},{pattern:"你除了我还能找到谁",tag:"贬低自尊",risk:95,explain:"让你觉得配不上别人"},{pattern:"我前女友比你温柔多了",tag:"比较打压",risk:90,explain:"通过比较来制造焦虑和自卑"},{pattern:"你不听我的以后出事别后悔",tag:"恐吓控制",risk:95,explain:"通过威胁来控制决策权"}];
const INTENTS=[{icon:"💬",l:"让TA回复我"},{icon:"💘",l:"推进关系"},{icon:"🤔",l:"确认TA心意"},{icon:"🔥",l:"制造吸引力"},{icon:"🤝",l:"修复关系"},{icon:"💔",l:"挽回TA"},{icon:"🚪",l:"体面结束"},{icon:"☕",l:"准备第一次见面"},{icon:"😎",l:"搭讪开场"},{icon:"🛡️",l:"设立边界"}];
const CTX_SLIDERS=[{k:"intimacy",l:"体感亲密",c:"#e8548e"},{k:"spark",l:"体感心动",c:"#ff6b8a"},{k:"myCommit",l:"你的承诺意愿",c:"#7b6ef5"},{k:"taCommit",l:"TA的承诺感",c:"#3aaa9c"},{k:"satisfaction",l:"满意度",c:"#c8913a"},{k:"alternatives",l:"替代选择",c:"#e04040"}];
const REPLY_DELAYS=["<1h","1-6h","6-24h",">24h","未知"];
const PICKUP_SCENES=[{icon:"☕",l:"咖啡店"},{icon:"📚",l:"书店/图书馆"},{icon:"🏋️",l:"健身房"},{icon:"🎨",l:"展览/活动"},{icon:"🚇",l:"地铁/公交"},{icon:"🛒",l:"超市/商场"},{icon:"🐕",l:"遛狗/公园"},{icon:"💼",l:"职场/会议"}];
const MY_TRAITS=[{icon:"😊",l:"开朗外向"},{icon:"🤓",l:"内敛温和"},{icon:"😏",l:"幽默自信"},{icon:"🌊",l:"沉稳低调"},{icon:"🔥",l:"热情直接"}];
const TA_TRAITS=[{icon:"😊",l:"开朗爱笑"},{icon:"📱",l:"低头看手机"},{icon:"🎧",l:"戴耳机"},{icon:"☕",l:"独自一人"},{icon:"👥",l:"和朋友在一起"},{icon:"📖",l:"在看书"},{icon:"😐",l:"看起来无聊"},{icon:"🏃",l:"在运动"}];
const PICKUP_GOALS=[{icon:"💬",l:"打招呼破冰"},{icon:"📱",l:"加联系方式"},{icon:"☕",l:"邀约"},{icon:"😊",l:"留下好印象"},{icon:"🔗",l:"建立联系"}];
const LOCAL_FB={breakup:{verdict:"TA在关机模式。不要急于证明，先降低对方防御。",situation:"分手/放弃信号出现时，对方通常处于情绪饱和状态，此时任何挽留都会被当作压力。",rootCause:"核心不是不爱，而是相处模式让TA累了。",herseyS:"S1",dos:["48小时内不主动联系","发一条不超过15字的轻消息","不提感情只聊日常","用行动代替承诺","给TA空间但保持存在感"],says:["我尊重你的决定","最近还好吗","看到这个想到你","不打扰，就是想说一声","我在反思，谢谢你的坦诚"],avoid:["别说「给我一次机会」","别翻旧账","别找TA朋友传话","别连续发消息","别哭着打电话"],weekPlan:[{day:"Day 1-2",task:"完全静默，写下想说的话但不发"},{day:"Day 3",task:"发一条轻松的，不提感情"},{day:"Day 4-5",task:"正常生活，发朋友圈但不针对TA"},{day:"Day 6-7",task:"如果TA有回应，轻松接住不追问"}],scriptBranches:{positive:"TA回了→轻松接住，聊2-3句就收",cold:"TA冷淡→不追问，过3天再试",noReply:"已读不回→不发第二条，等一周"}},conflict:{verdict:"你们在情绪风暴中。现在最重要的是止损，不是讲道理。",situation:"冲突后双方都处于防御状态，任何「讲道理」都会被听成攻击。",rootCause:"不是事情本身，而是沟通方式触发了对方的防御机制。",herseyS:"S2",dos:["先承认TA的感受是真实的","用「我」开头而不是「你」","找一个小事先破冰","不要急着解决问题，先修复情绪","给彼此冷静时间但约定回来谈"],says:["我知道你很生气，你的感受是对的","刚才我语气重了，对不起","我不想赢，我想要我们好","等你准备好了我们再聊","我在反思自己的问题"],avoid:["别说「你总是」「你从来不」","别翻旧账","别冷战超过48小时","别找第三方评理","别在TA面前哭来施压"],weekPlan:[{day:"Day 1",task:"主动发一条软启动消息"},{day:"Day 2",task:"不提冲突，聊一件开心的事"},{day:"Day 3",task:"正面表达你的需求，不攻击"}],scriptBranches:{positive:"TA软化了→趁热打铁约面聊",cold:"TA还冷→不逼，再给一天",noReply:"不回→发一条关心的，不提吵架"}},cold:{verdict:"TA在关机模式。你的追问会让TA关得更紧。",situation:"已读不回/变冷淡通常意味着对方需要空间，或者在评估关系。",rootCause:"信息过载或需求感暴露让TA产生压力。",herseyS:"S1",dos:["停止追问「怎么了」","降低消息频率到TA的1/3","发价值型内容而非追问型","保持自己的生活节奏","等TA主动时热情但不过度"],says:["看到个好玩的想分享给你","今天天气好适合出去走走","不打扰你，有空聊","周末有个活动感兴趣吗"],avoid:["别问「你是不是不喜欢我了」","别连发3条以上","别找TA朋友打听","别发长段表白","别表现得很在意"],weekPlan:[{day:"Day 1-2",task:"完全不发消息"},{day:"Day 3",task:"发一条轻松的分享"},{day:"Day 5",task:"如果没回，再发一条价值型内容"},{day:"Day 7",task:"评估，如果还没回应考虑降级期待"}],scriptBranches:{positive:"TA回了→正常聊，不提冷淡",cold:"TA敷衍→收，过几天再试",noReply:"一周没回→接受现实，转移注意力"}},advance:{verdict:"推进最好的方式是「刚好下一步」，不要跳级。",situation:"暧昧期最怕的不是慢，而是急。",rootCause:"时机和节奏比内容更重要。",herseyS:"S3",dos:["制造共同经历","用行动暗示而非语言直说","给TA选择而非压力","升级物理距离（坐近一点）","找借口制造下次见面"],says:["下次一起去试试？","你喜欢的那个我也想看","周末有空的话...","这个超适合你"],avoid:["别表白太早","别问「你对我什么感觉」","别天天黏着","别送太贵的礼物","别在朋友圈暗示"],weekPlan:[{day:"Day 1",task:"分享一个TA感兴趣的内容"},{day:"Day 3",task:"提议一个轻松的活动"},{day:"Day 5",task:"制造一个小惊喜"},{day:"Day 7",task:"如果进展顺利，升级一下互动"}],scriptBranches:{positive:"TA热情→自然推进，提议见面",cold:"TA犹豫→不逼，保持有趣",noReply:"没回→话题不对，换个角度"}},daily:{verdict:"关系没大问题，重点是保持新鲜感和情感存款。",situation:"稳定期容易进入舒适区，忘记经营。",rootCause:"不是不爱，是太习惯了。",herseyS:"S4",dos:["每天一个小惊喜","记住TA说过的小事","主动分享你的日常","定期约会保持仪式感","表达感谢而非理所当然"],says:["想你了","今天因为你开心","谢谢你一直在","我们去那个新开的店试试","你最近辛苦了"],avoid:["别把TA当空气","别只聊实用的事","别忘记纪念日","别在TA面前只看手机","别停止说「我爱你」"],weekPlan:[{day:"Day 1",task:"发一条走心的早安"},{day:"Day 3",task:"计划一次小约会"},{day:"Day 5",task:"送一个小礼物或写张卡片"},{day:"Day 7",task:"回顾这周的甜蜜时刻"}],scriptBranches:{positive:"TA开心→继续保持节奏",cold:"TA忙→理解，不施压",noReply:"偶尔没回→正常，不过度解读"}}};
const CSS=`*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}::-webkit-scrollbar{display:none}input,textarea,select{font-family:inherit} @keyframes fadeUp{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}} @keyframes fadeIn{from{opacity:0}to{opacity:1}} @keyframes slideDown{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}} @keyframes breathe{0%,100%{transform:scale(1)}50%{transform:scale(1.03)}} @keyframes syncBreath{0%,100%{transform:scale(1)}25%{transform:scale(1.12)}50%{transform:scale(1)}75%{transform:scale(1.08)}} @keyframes heartRecord{0%,100%{transform:scale(1);filter:drop-shadow(0 0 4px rgba(139,90,200,.3))}50%{transform:scale(1.15);filter:drop-shadow(0 0 12px rgba(139,90,200,.6))}} @keyframes lipCute{0%,100%{transform:scale(1) rotate(0)}30%{transform:scale(1.06) rotate(-3deg)}70%{transform:scale(1.06) rotate(3deg)}} @keyframes lipSexy{0%,100%{transform:scale(1) rotate(0);filter:drop-shadow(0 0 3px rgba(200,50,80,.2))}50%{transform:scale(1.04) rotate(2deg);filter:drop-shadow(0 0 8px rgba(200,50,80,.5))}} @keyframes lipBreathCute{0%,100%{transform:scale(1)}50%{transform:scale(1.03)}} @keyframes lipBreathSexy{0%,100%{transform:scale(1);filter:drop-shadow(0 0 2px rgba(180,50,70,.15))}50%{transform:scale(1.025);filter:drop-shadow(0 0 5px rgba(180,50,70,.25))}} @keyframes dualSync{0%,100%{transform:scale(1);filter:drop-shadow(0 0 6px rgba(232,84,142,.3))}50%{transform:scale(1.1);filter:drop-shadow(0 0 16px rgba(139,90,200,.5))}} @keyframes bubbleFloat{0%{transform:translateY(0) scale(1);opacity:.6}50%{transform:translateY(-8px) scale(1.1);opacity:.9}100%{transform:translateY(0) scale(1);opacity:.6}} @keyframes pulse{0%,100%{box-shadow:0 0 0 0 rgba(232,84,142,.25)}70%{box-shadow:0 0 0 10px rgba(232,84,142,0)}} @keyframes dotPulse{0%,80%,100%{transform:scale(0)}40%{transform:scale(1)}} @keyframes sakuraFall{0%{transform:translateY(-10vh) rotate(0);opacity:0}10%{opacity:.5}100%{transform:translateY(105vh) translateX(25px) rotate(360deg);opacity:0}} .tap:active{transform:scale(.97)!important;opacity:.88}.tap2:active{transform:scale(.94)!important} .dots span{width:5px;height:5px;border-radius:50%;background:${C.pink};display:inline-block;margin:0 3px;animation:dotPulse 1.4s infinite ease-in-out both} .dots span:nth-child(1){animation-delay:-.32s}.dots span:nth-child(2){animation-delay:-.16s} .glass-card{background:rgba(255,255,255,.92);backdrop-filter:blur(20px);border:1px solid rgba(219,112,147,.08);border-radius:18px;box-shadow:0 4px 24px rgba(232,84,142,.06),0 1px 3px rgba(0,0,0,.04)} input[type=range]{-webkit-appearance:none;appearance:none;height:6px;border-radius:3px;outline:none;cursor:pointer} input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:22px;height:22px;border-radius:50%;background:#fff;box-shadow:0 2px 8px rgba(0,0,0,.2);cursor:pointer}`;
const Petals=()=>{const p=useMemo(()=>Array.from({length:12},(_,i)=>({left:Math.random()*100,dur:9+Math.random()*9,del:Math.random()*12,sz:10+Math.random()*7,op:.12+Math.random()*.18})),[]);return <div style={{position:"fixed",inset:0,pointerEvents:"none",zIndex:0,overflow:"hidden"}}>{p.map((x,i)=><span key={i} style={{position:"absolute",left:`${x.left}%`,top:0,fontSize:x.sz,opacity:x.op,animation:`sakuraFall ${x.dur}s ${x.del}s infinite ease-in-out`}}>🌸</span>)}</div>;};
const Toast=({m})=>m?<div style={{position:"fixed",top:52,left:"50%",transform:"translateX(-50%)",background:C.white,color:C.pink,padding:"8px 22px",borderRadius:20,fontSize:12,fontWeight:600,zIndex:999,animation:"slideDown .25s",boxShadow:`0 4px 24px ${C.pink}20`,border:`1px solid ${C.sakuraL}`,whiteSpace:"nowrap"}}>🌸 {m}</div>:null;
const Dots=()=><div className="dots" style={{textAlign:"center",padding:20}}><span/><span/><span/></div>;
const FREE_LIMITS={flash:3,think:1,deep:1,help:1,trans:3,feel:2,rp:1,chess:1};/* ═══ AstraBuddy Platform Patches v2.3 ═══ */
const FONT_STEPS=[12,14,16,18];
const DAILY_PUSH_POOL=[{type:"tip",icon:"💡",title:"软启动一句话",body:"把「你怎么又...」换成「我有点...」，冲突结局完全不同。",ref:"Gottman软启动研究",cat:"conflict"},{type:"tip",icon:"🔮",title:"潜台词解码",body:"TA说「随便」≠真随便。62%概率是「你该主动猜对」。",ref:"Grice会话含义",cat:"translate"},{type:"challenge",icon:"🎯",title:"今日挑战",body:"发一条不超过10字的关心消息，不提任何要求。",ref:"低压沟通策略",cat:"daily"},{type:"tip",icon:"🧠",title:"依恋小知识",body:"回避型不是不爱，是靠近时启动了自我保护。给空间=给安全。",ref:"Hazan & Shaver 1987",cat:"attachment"},{type:"tip",icon:"💕",title:"爱之语提醒",body:"TA上次开心是因为你做了什么？重复那件事，比说100句好听的管用。",ref:"Chapman 1992",cat:"lovelang"},{type:"challenge",icon:"⚡",title:"30秒挑战",body:"用「我觉得...因为...我希望...」造一句话发给TA。",ref:"非暴力沟通",cat:"comm"},{type:"tip",icon:"🔥",title:"推拉节奏",body:"连续3天主动后，今天让TA先找你。好奇心是吸引力燃料。",ref:"间歇强化",cat:"flirt"},{type:"insight",icon:"📊",title:"关系体检",body:"本周你们聊了几次？如果<3次，今天主动发起一个轻话题。",ref:"Gottman 5:1积极比",cat:"maintain"},{type:"tip",icon:"🛡️",title:"四骑士警报",body:"如果你发现自己想说「你总是...」，立刻换成「这次我感觉...」。",ref:"Gottman 1994",cat:"conflict"},{type:"challenge",icon:"🎁",title:"微惊喜",body:"今天做一件TA没有要求但会开心的小事。不用大，一杯奶茶就够。",ref:"自我扩展理论",cat:"maintain"}];
const AMMO_PRESETS=[{cat:"👋开场白",items:["在吗？今天过得怎么样","最近有什么好玩的事吗","突然想到你，就来找你聊天了","你头像好好看，什么时候拍的","这首歌让我想到了你","今天天气好适合出去走走","你最近在忙什么呀","看了一个有意思的东西想分享给你"]},{cat:"💗表达感受",items:["和你聊天总是很开心","遇到你是我今年最幸运的事","你笑起来的样子真好看","想你了，就这样，没有别的","谢谢你一直在我身边","你今天辛苦了，早点休息","有你在我就觉得安心","我喜欢和你在一起的感觉"]},{cat:"🚧设边界",items:["这件事我需要时间想想","我理解你的感受，但我也有我的底线","我们可以换个方式聊这个话题吗","我现在情绪不太好，晚点再聊好吗","我希望我们都能尊重对方的决定","这个问题我暂时不想讨论","我需要一点个人空间，不是因为你","请不要这样说话，我会不舒服"]},{cat:"🕊化解冲突",items:["我不想赢，我想要我们好","刚才我语气重了，对不起","你说的有道理，我确实没考虑到","我们能不能把事情和感受分开聊","我在反思自己的问题","等你准备好了我们再聊","我们都冷静下来想想","不管怎样，我在乎你的感受"]},{cat:"💼职场应对",items:["感谢您的反馈，我会改进的","这个方案我再想想，明天给您回复","我理解您的顾虑，我来补充一下数据","这件事我负责跟进，周五前给结果","您说的对，我确实可以做得更好","我需要确认一下细节再回复您","感谢信任，我会尽全力完成","这个任务我有一些想法想和您讨论"]},{cat:"🙅拒绝话术",items:["谢谢你的好意，但我目前不太方便","我需要考虑一下，不能马上答应","这次可能不行，下次一定","我很感谢你想到我，但这次得pass了","我理解你的想法，不过我有不同的安排","不好意思，这超出我能力范围了","我尊重你的提议，但我得诚实说不太合适","真的很抱歉，这次帮不上忙"]}];
const THEORY_AUTO_MAP={breakup:["M0","M3","M4","M5","M2"],conflict:["M5","M6","M3","M4"],cold:["M3","M4","M0","M5"],advance:["M0","M1","M9","M4"],daily:["M1","M7","M8","M4"],flirt:["M0","M9","M4"],jealous:["M3","M5"],longdist:["M1","M2","M7"],ex:["M3","M2","M5"],space:["M3","M8","M4"]};
const COPILOT_STATES={idle:"待机",listening:"监听中",processing:"分析中",ready:"建议就绪"};/* ═══ SYSTEM: TriCore 三角维度展示 ═══ */
const TRICORE_DIMS=[{id:"intimacy",icon:"💜",name:"亲密(Intimacy)",desc:"情感连接深度：信任、理解、支持、分享",  up:["分享一个脆弱的想法（不是抱怨）","无手机30分钟散步","问TA：最近有什么我能帮你的吗？","主动记住并跟进TA说过的事","每周至少1次深度对话"],  down:["沟通变浅（只聊日常不聊感受）","缺少独处时间","信任受损事件","忙碌导致情感忽略","进入「室友模式」"]},{id:"passion",icon:"❤️",name:"激情(Passion)",desc:"吸引力和心动感",  up:["一起做新鲜事（自我扩展理论）","制造物理距离后的重逢","分享「第一次」体验","增加非日常的惊喜元素","适当的推拉节奏"],  down:["见面频率过高→新鲜感消失","互动模式固化","外表管理懈怠","只剩实用性对话","停止调情和浪漫表达"],  normal:"热恋期(0-18月)激情最高→过渡期(18-36月)自然回落→稳定期靠主动经营维持。这是正常的生物学规律，不是不爱了。"},{id:"commitment",icon:"💍",name:"承诺(Commitment)",desc:"对关系未来的投入和决心",  up:["讨论共同的未来计划","在朋友面前自然提到对方","遇到诱惑时主动选择关系","为关系做出实际牺牲","建立共同的仪式感"],  down:["回避谈论未来","不在社交圈公开关系","保留过多退路","不愿做任何妥协","对「在一起多久」敏感"]}];/* ═══ SYSTEM: Risk Detail 风险分级面板 ═══ */
const RISK_DETAILS={low:{title:"🟢 低风险",desc:"关系整体健康，当前策略有效",  keep:["维持当前沟通频率","定期制造小惊喜","每周至少1次深度对话","关注TA的情绪变化信号"],  prevent:["避免进入舒适区陷阱","每月尝试1件新事物","主动表达感激","不要把TA的好当作理所当然"]},med:{title:"🟡 中风险",desc:"存在需要关注的信号，需主动调整",  signals:["回复速度变慢但未消失","主动联系减少","对话深度变浅","约见面被推迟"],  plan:["降低追问频率（-50%）","提升每次互动质量","给对方可预期的回复窗口","一周后评估变化趋势"]},high:{title:"🔴 高风险",desc:"出现明显危机信号，需立即调整",  crisis:["停止一切追问/质问行为","发一条不带压力的消息","给对方至少24-48小时空间","这期间关注自己的状态","准备好对方联系你时怎么回应"],  pro:["持续焦虑影响日常生活","出现控制/被控制行为","情绪波动已持续2周以上","关系中存在任何形式的暴力","自我价值感严重下降"]}};/* ═══ SYSTEM: Module Help 模块帮助详情 ═══ */
const MODULE_HELP=(mod)=>({  collect:{title:`${mod.name} · 信息收集模板`,items:["【关系阶段】***","【最近事件】***","【TA的反应】***","【你的感受】***","【你想达到的目标】***"],note:"信息越具体，分析越精准。"},  partial:{title:"信息不全怎么办",items:["标注「不确定」即可，系统会给出多种可能","重点提供：最近1次互动 + TA的典型反应","哪怕只有3句话描述，也能给出初步方向","后续可以补充信息重新分析"]},  howToUse:{title:"如何用好结果",items:["先看核心洞察，确认是否命中","行动清单选最容易的那条先做","话术不要照搬，结合自己的语气调整","3天后回来看反馈，调整策略","如果全部没命中，补充更多信息重跑"]},  limits:{title:"局限性",items:["基于文字输入，无法捕捉非语言信息","单方视角可能有偏差","不替代专业心理咨询","结果是概率性建议，不是确定性判断","极端情况（暴力/骚扰）请寻求专业帮助"]}});/* ═══ SYSTEM: Engine Detail 引擎详情面板 ═══ */
const ENGINE_DETAIL=(eng)=>({  how:{title:`${eng.name} · 工作原理`,steps:["关键词触发层：识别信号","上下文理解层：结合关系阶段和历史","理论映射层：对照理论框架","建议生成层：输出个性化行动方案"]},  metrics:{title:`${eng.name} · 检测指标`,dims:["📊 频率指标：相关行为出现次数","📈 强度指标：情绪激烈程度","📉 趋势指标：是否在恶化","🔗 关联指标：与其他模块的交叉信号"]},  accuracy:{title:"准确率说明",items:[`基于 ${eng.cred} 理论框架验证`,"用户反馈命中率：约75-85%","信息越完整，准确率越高","建议结合自身判断使用"]},  guide:{title:"指标解读",levels:["🟢 绿色(低风险)：继续当前策略","🟡 黄色(中风险)：需要微调，注意信号","🔴 红色(高风险)：建议立即调整策略"]},  stopScripts:["我意识到我刚才的方式不对，我先停一下。","我不是要追问你，我只是担心。给你空间。","我们都冷静一下，等我们都准备好了再聊。"],  repairScripts:["我想了一下，之前的方式让你不舒服了，抱歉。","我在学习怎么更好地和你沟通，你愿意帮我吗？","我不想因为表达方式伤害我们的关系。"]});/* ═══ SYSTEM: Pickup Full 搭讪完整版 ═══ */
const PICKUP_OPENERS=[{style:"📸 赞美款",text:"你这个___好好看，在哪里买的？我想给朋友也推荐一下",why:"具体赞美比泛泛夸更真诚"},{style:"🎯 观察款",text:"我注意到你点了**_，看来你很懂行，有什么推荐的吗？",why:"展示细心，同时制造话题"},{style:"🌈 共鸣款",text:"这个天气出来太舒服了，你也是来___的吗？",why:"利用环境制造共同体验"},{style:"🔮 好奇款",text:"你身上这个___好特别，有什么故事吗？",why:"人们喜欢分享自己的故事"},{style:"🎮 活动款",text:"你也在排队吗？看来大家都是冲着___来的",why:"利用共同等待制造连接"},{style:"💫 机缘款",text:"你知道吗，我犹豫了好几分钟要不要来跟你说话，最后决定不想后悔",why:"坦诚的勇气本身就是吸引力"}];
const PICKUP_SIGNALS={good:["TA放下手机看你","回答后反问你问题","身体朝向你","笑容自然","主动延长话题","声音变温柔/语速放慢","玩弄头发/首饰","找借口靠近你","分享个人信息","提到「下次」「以后」等词"],bad:["单字回复/敷衍","频繁看手机","身体转向别处","戴回耳机","不断环顾四周（找退路）","回答越来越短","明确说「我等人」","后退半步增加距离","礼貌微笑但不接话","看手表暗示时间"]};
const PICKUP_NEXTSTEPS=["如果TA有兴趣：聊2-3分钟后自然地说「聊得挺开心，方便加个微信吗？」","如果TA礼貌但冷淡：微笑说「打扰了，祝你有个好心情」然后优雅离开","拿到联系方式后：当天发一条简短消息「很高兴认识你，我是刚才在___的那个___」","不要当天约，隔1-2天再自然聊起来","第二天可以分享一张照片或有趣的事：「今天看到一个东西让我想到你」","前三次聊天控制在10-15条以内，保持神秘感","观察TA的回复速度和主动程度，匹配TA的节奏","第一次正式约会选安静的地方（咖啡厅>电影院），方便聊天","约会前确认时间地点，不要模糊地说「有空一起出来」","见面时比线上更注意形象，第一印象二次确认很重要","约会结束后发一条「今天很开心，回到家了吗？」关心一下","不要在社交媒体上过度点赞/评论，容易显得太刻意","如果TA主动找你聊天，说明有兴趣，可以适当升温","制造下次见面的理由：「上次你说想试那家店，周末去？」","保持自己的生活节奏，不要因为搭讪成功就all in","如果一周内TA没有主动联系，可以再发一次，但不超过两次"];/* ═══ SYSTEM: Expert Report Pipeline ═══ */
const PIPE_STEPS=[{icon:"📥",label:"收集信息",desc:"整合输入+画像+阶段"},{icon:"🔍",label:"识别模式",desc:"检测关键词与情绪信号"},{icon:"🧠",label:"匹配理论",desc:"对照心理学框架"},{icon:"⚡",label:"生成策略",desc:"输出个性化方案"},{icon:"💬",label:"构建话术",desc:"生成可发送文本"},{icon:"✅",label:"优化方案",desc:"风险检测+最终确认"}];


/* ═══ v2.5 Plan C: Smart Coach Tab with search + intent filter + recommendations ═══ */



/* ═══ v2.5 Plan C++ B: Render text with inline Twemoji stickers ═══ */
/* Split text into segments (text + emoji), render emoji as clickable images */
const V25_EMOJI_REGEX=/(?:\p{Emoji_Presentation}|\p{Extended_Pictographic}(?:\uFE0F)?)(?:\u200D(?:\p{Emoji_Presentation}|\p{Extended_Pictographic}(?:\uFE0F)?))*/gu;
function V25StickerText({text, st, size=20}) {
  if (!text || typeof text !== "string") return <span>{text}</span>;
  const parts = [];
  let lastEnd = 0;
  try {
    const matches = [...text.matchAll(V25_EMOJI_REGEX)];
    for (const m of matches) {
      if (m.index > lastEnd) parts.push({type:"text", val: text.slice(lastEnd, m.index)});
      parts.push({type:"emoji", val: m[0]});
      lastEnd = m.index + m[0].length;
    }
    if (lastEnd < text.length) parts.push({type:"text", val: text.slice(lastEnd)});
  } catch (e) {
    return <span>{text}</span>;
  }
  if (parts.length === 0) parts.push({type:"text", val: text});
  
  const copyEmoji = async (em, evt) => {
    evt.stopPropagation();
    try {
      await navigator.clipboard.writeText(em);
      if (st) st(`✓ 已复制 ${em}`);
    } catch {}
  };
  
  return (
    <span>
      {parts.map((p, i) => {
        if (p.type === "text") return <span key={i}>{p.val}</span>;
        const url = twemojiUrl(p.val);
        if (!url) return <span key={i}>{p.val}</span>;
        return (
          <img 
            key={i} 
            src={url} 
            alt={p.val}
            title={`点击复制 ${p.val}`}
            loading="lazy"
            onClick={(ev)=>copyEmoji(p.val, ev)}
            style={{
              display:"inline-block",
              width:size,
              height:size,
              verticalAlign:"-4px",
              cursor:"pointer",
              margin:"0 1px"
            }}
            onError={(ev)=>{
              const span=document.createElement("span");
              span.textContent=p.val;
              ev.target.parentElement.replaceChild(span,ev.target);
            }}
          />
        );
      })}
    </span>
  );
}

/* ═══ v2.5 Plan C+: Daily recommendations on Flash home (idle state) ═══ */
function V25DailyRecommend({stageId, onNavigateGame}) {
  const [dismissed, setDismissed] = useState(false);
  
  useEffect(() => {
    (async () => {
      try {
        const r = await window.storage.get("sakura-v25-rec-dismissed");
        const today = new Date().toDateString();
        if (r?.value === today) setDismissed(true);
      } catch {}
    })();
  }, []);
  
  const dismiss = async () => {
    setDismissed(true);
    try {
      await window.storage.set("sakura-v25-rec-dismissed", new Date().toDateString());
    } catch {}
  };
  
  const openGame = (g) => {
    if (onNavigateGame) onNavigateGame(g.id);
  };
  
  if (dismissed) return null;
  
  const topIds = V25_STAGE_TOP3[stageId] || V25_STAGE_TOP3.new;
  const topFeats = topIds.map(id => VIRAL_GAMES.find(g => g.id === id)).filter(Boolean);
  
  if (topFeats.length === 0) return null;
  
  return (
    <div style={{marginBottom:12,padding:"12px 14px",borderRadius:14,background:"linear-gradient(135deg,#fff5f7,#fef3c7)",border:"1px solid #ffd2dc",position:"relative"}}>
      <button 
        onClick={dismiss}
        style={{position:"absolute",top:8,right:8,background:"none",border:"none",fontSize:14,color:"#a07080",cursor:"pointer",padding:4,lineHeight:1}}
        title="今天不再显示"
      >×</button>
      <div style={{fontSize:11,fontWeight:800,color:"#c9306b",marginBottom:2}}>🌟 今日最适合你</div>
      <div style={{fontSize:9,color:"#a07080",marginBottom:8}}>基于你当前的关系阶段推荐</div>
      <div style={{display:"grid",gridTemplateColumns:"repeat(3,1fr)",gap:6}}>
        {topFeats.map(g => (
          <button 
            key={g.id} 
            className="tap" 
            onClick={()=>openGame(g)}
            style={{padding:"8px 4px",borderRadius:10,background:"#fff",border:"1px solid rgba(219,112,147,.2)",cursor:"pointer",textAlign:"center"}}
          >
            <div style={{fontSize:18,marginBottom:2}}>{g.icon}</div>
            <div style={{fontSize:10,fontWeight:800,color:g.c,lineHeight:1.3}}>{g.l || g.n}</div>
            <div style={{fontSize:8,color:"#8a6573",marginTop:1,lineHeight:1.2}}>{g.d}</div>
          </button>
        ))}
      </div>
    </div>
  );
}

/* ═══ v2.5 Plan C+: Real-image sticker picker (Twemoji CDN) ═══ */
function V25EmojiPack({onPick}) {
  const [activePack, setActivePack] = useState("love");
  const [copiedEmoji, setCopiedEmoji] = useState(null);
  const packNames = {
    love:"💗 爱意",
    sad:"🥺 委屈",
    cute:"🐰 可爱",
    cool:"😎 酷",
    funny:"😂 好笑",
    sorry:"🙇 道歉",
    food:"🍰 美食",
    gestures:"👋 手势"
  };
  
  const handlePick = async (e) => {
    onPick(e);
    try {
      await navigator.clipboard.writeText(e);
      setCopiedEmoji(e);
      setTimeout(()=>setCopiedEmoji(null), 1200);
    } catch {}
  };
  
  return (
    <div style={{marginTop:10,padding:"10px 12px",borderRadius:12,background:"#fff",border:"1px solid rgba(219,112,147,.14)"}}>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:6}}>
        <div style={{fontSize:11,fontWeight:700,color:"#c9306b"}}>✨ 真图表情包 · 120+ 精选</div>
        {copiedEmoji && <div style={{fontSize:10,color:"#10b981",fontWeight:700}}>✓ 已复制 {copiedEmoji}</div>}
      </div>
      <div style={{display:"flex",gap:6,overflowX:"auto",marginBottom:8,paddingBottom:2,WebkitOverflowScrolling:"touch"}}>
        {Object.keys(V25_STICKERS).map(k => (
          <button 
            key={k} 
            className="tap2"
            onClick={()=>setActivePack(k)} 
            style={{
              flexShrink:0,padding:"4px 8px",borderRadius:10,
              border:activePack===k?"1.5px solid #E84D8C":"1px solid #eee",
              background:activePack===k?"#fff5f7":"#fff",
              color:activePack===k?"#c9306b":"#5a3545",
              fontSize:10,fontWeight:activePack===k?800:600,cursor:"pointer",whiteSpace:"nowrap"
            }}
          >
            {packNames[k]}
          </button>
        ))}
      </div>
      <div style={{display:"grid",gridTemplateColumns:"repeat(6,1fr)",gap:6,maxHeight:180,overflowY:"auto"}}>
        {V25_STICKERS[activePack].map((e,i) => (
          <button 
            key={i} 
            className="tap2"
            onClick={()=>handlePick(e)} 
            style={{padding:"8px 4px",background:"#fafafa",border:"1px solid #f0f0f0",borderRadius:10,cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",minHeight:40}}
            title={`点击插入并复制 ${e}`}
          >
            <img 
              src={twemojiUrl(e)} 
              alt={e} 
              loading="lazy"
              style={{width:28,height:28,objectFit:"contain"}}
              onError={(ev)=>{
                /* CDN failed — fallback to Unicode */
                const span=document.createElement("span");
                span.style.fontSize="22px";
                span.textContent=e;
                ev.target.parentElement.replaceChild(span,ev.target);
              }}
            />
          </button>
        ))}
      </div>
      <div style={{fontSize:9,color:"#a07080",marginTop:6,textAlign:"center"}}>
        点击插入到输入框 + 自动复制 · 直接粘贴到微信
      </div>
    </div>
  );
}


function V25SmartCoach({stageId, setGameId, setGameInp, setGameRes, setView}) {
  const [query, setQuery] = useState("");
  const [activeIntent, setActiveIntent] = useState("all");
  const [pinnedIds, setPinnedIds] = useState([]);
  const [usageMap, setUsageMap] = useState({});
  
  useEffect(() => {
    (async () => {
      try {
        const r = await window.storage.get("sakura-v25-usage");
        if (r?.value) {
          const usage = JSON.parse(r.value);
          setUsageMap(usage);
          const sorted = Object.entries(usage).sort((a,b)=>b[1]-a[1]).slice(0,6).map(e=>e[0]);
          setPinnedIds(sorted);
        }
      } catch {}
    })();
    /* v2.5 Plan C++: cross-tab pending game */
    try {
      const pending = globalThis.__sakuraPendingGame;
      if (pending) {
        globalThis.__sakuraPendingGame = null;
        setGameId(pending);
        setGameInp("");
        setGameRes(null);
        setView("game");
      }
    } catch {}
  }, []);
  
  const trackUse = async (gid) => {
    const newMap = {...usageMap, [gid]: (usageMap[gid] || 0) + 1};
    setUsageMap(newMap);
    try { await window.storage.set("sakura-v25-usage", JSON.stringify(newMap)); } catch {}
  };
  
  const openGame = (g) => {
    trackUse(g.id);
    setGameId(g.id);
    setGameInp("");
    setGameRes(null);
    setView("game");
  };
  
  // Filter logic
  const filtered = VIRAL_GAMES.filter(g => {
    // Query filter (matches label, desc, or id)
    if (query) {
      const q = query.toLowerCase();
      const matches = g.l?.toLowerCase().includes(q) || 
                      (g.n && g.n.toLowerCase().includes(q)) ||
                      g.d?.toLowerCase().includes(q) || 
                      g.id.toLowerCase().includes(q);
      if (!matches) return false;
    }
    // Intent filter
    if (activeIntent !== "all") {
      const intent = V25_INTENT_MAP[g.id];
      if (intent !== activeIntent) return false;
    }
    return true;
  });
  
  // Stage-based top 3
  const topIds = V25_STAGE_TOP3[stageId] || V25_STAGE_TOP3.new;
  const topFeats = topIds.map(id => VIRAL_GAMES.find(g => g.id === id)).filter(Boolean);
  
  // Pinned (most-used) features
  const pinnedFeats = pinnedIds.map(id => VIRAL_GAMES.find(g => g.id === id)).filter(Boolean);
  
  // Group filtered by intent for grouped display when "all"
  const grouped = {};
  if (activeIntent === "all" && !query) {
    filtered.forEach(g => {
      const intent = V25_INTENT_MAP[g.id] || "all";
      if (!grouped[intent]) grouped[intent] = [];
      grouped[intent].push(g);
    });
  }
  
  const cardStyle = {padding:"10px 6px",borderRadius:14,background:"#fff",border:"1px solid rgba(219,112,147,.14)",cursor:"pointer",textAlign:"center"};
  const renderCard = (g) => (
    <button key={g.id} className="tap" onClick={()=>openGame(g)} style={cardStyle}>
      <div style={{fontSize:18,marginBottom:2}}>{g.icon}</div>
      <div style={{fontSize:10,fontWeight:700,color:g.c}}>{g.l || g.n}</div>
      <div style={{fontSize:8,color:"#8a6573",marginTop:1}}>{g.d}</div>
    </button>
  );
  
  return (
    <div style={{padding:"0 14px",marginBottom:16}}>
      {/* 搜索框 */}
      <div style={{marginBottom:12,position:"relative"}}>
        <input 
          type="text" 
          value={query} 
          onChange={e=>setQuery(e.target.value)}
          placeholder="🔍 搜索功能(比如 告白 / 冷战 / PUA)" 
          style={{width:"100%",padding:"10px 14px",borderRadius:12,border:"1px solid rgba(219,112,147,.2)",background:"#fff",fontSize:12,outline:"none",boxSizing:"border-box"}}
        />
        {query && (
          <button onClick={()=>setQuery("")} style={{position:"absolute",right:10,top:"50%",transform:"translateY(-50%)",background:"none",border:"none",fontSize:14,color:"#a07080",cursor:"pointer"}}>✕</button>
        )}
      </div>
      
      {/* 意图筛选 Pills */}
      <div style={{display:"flex",gap:6,overflowX:"auto",marginBottom:14,paddingBottom:4,WebkitOverflowScrolling:"touch"}}>
        {V25_INTENTS.map(it => {
          const isActive = activeIntent === it.id;
          return (
            <button 
              key={it.id} 
              className="tap2"
              onClick={()=>setActiveIntent(it.id)}
              style={{
                flexShrink:0,padding:"7px 12px",borderRadius:16,
                border:isActive?`1.5px solid ${it.c}`:"1px solid #eee",
                background:isActive?`${it.c}15`:"#fff",
                color:isActive?it.c:"#5a3545",
                fontSize:11,fontWeight:isActive?800:600,
                cursor:"pointer",whiteSpace:"nowrap"
              }}
            >
              {it.icon} {it.l}
            </button>
          );
        })}
      </div>
      
      {/* 今日推荐(仅在 all + 无搜索时显示) */}
      {activeIntent === "all" && !query && topFeats.length > 0 && (
        <div style={{marginBottom:14}}>
          <div style={{fontSize:12,fontWeight:800,color:"#c9306b",marginBottom:8,display:"flex",alignItems:"center",gap:6}}>
            <span>🌟 今日最适合你</span>
            <span style={{fontSize:9,color:"#a07080",fontWeight:400}}>基于你当前的关系阶段</span>
          </div>
          <div style={{display:"grid",gridTemplateColumns:"repeat(3,1fr)",gap:6}}>
            {topFeats.map(g => (
              <button 
                key={g.id} 
                className="tap" 
                onClick={()=>openGame(g)} 
                style={{...cardStyle,background:"linear-gradient(135deg,#fff5f7,#fef3c7)",border:"1px solid #ffd2dc"}}
              >
                <div style={{fontSize:20,marginBottom:2}}>{g.icon}</div>
                <div style={{fontSize:10,fontWeight:800,color:g.c}}>{g.l || g.n}</div>
                <div style={{fontSize:8,color:"#c9306b",marginTop:1}}>{g.d}</div>
              </button>
            ))}
          </div>
        </div>
      )}
      
      {/* 最常用(仅在 all + 无搜索且有数据时) */}
      {activeIntent === "all" && !query && pinnedFeats.length >= 3 && (
        <div style={{marginBottom:14}}>
          <div style={{fontSize:12,fontWeight:800,color:"#7c3aed",marginBottom:8}}>📌 你最常用的</div>
          <div style={{display:"grid",gridTemplateColumns:"repeat(3,1fr)",gap:6}}>
            {pinnedFeats.slice(0,6).map(renderCard)}
          </div>
        </div>
      )}
      
      {/* 搜索结果或筛选结果 */}
      {(query || activeIntent !== "all") && (
        <div>
          <div style={{fontSize:12,fontWeight:700,color:"#241018",marginBottom:8}}>
            {query ? `🔍 搜索到 ${filtered.length} 个结果` : 
              `${V25_INTENTS.find(i=>i.id===activeIntent)?.icon} ${V25_INTENTS.find(i=>i.id===activeIntent)?.l}(${filtered.length} 个)`}
          </div>
          {filtered.length === 0 ? (
            <div style={{padding:30,textAlign:"center",color:"#a07080",fontSize:11}}>
              没找到相关功能 · 换个关键词试试?
            </div>
          ) : (
            <div style={{display:"grid",gridTemplateColumns:"repeat(3,1fr)",gap:6}}>
              {filtered.map(renderCard)}
            </div>
          )}
        </div>
      )}
      
      {/* 全部分组展示(默认视图) */}
      {activeIntent === "all" && !query && (
        <div>
          {V25_INTENTS.filter(i=>i.id!=="all").map(intent => {
            const items = grouped[intent.id] || [];
            if (items.length === 0) return null;
            return (
              <div key={intent.id} style={{marginBottom:18}}>
                <div style={{fontSize:12,fontWeight:800,color:intent.c,marginBottom:6,display:"flex",alignItems:"center",gap:4}}>
                  <span>{intent.icon} {intent.l}</span>
                  <span style={{fontSize:9,color:"#a07080",fontWeight:400}}>· {intent.d}</span>
                  <span style={{fontSize:9,color:"#a07080",fontWeight:400,marginLeft:"auto"}}>{items.length} 个</span>
                </div>
                <div style={{display:"grid",gridTemplateColumns:"repeat(3,1fr)",gap:6}}>
                  {items.map(renderCard)}
                </div>
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}


/* ═══ v2.5 NEW FEATURES — unified renderer for 8 new games ═══ */
const V25_PROMPTS = {
  roleplay_pro: (profile) => `你正在扮演用户的对象 TA。\n\nTA 档案:\n- 昵称:${profile.nickname||"未填"}\n- MBTI:${profile.mbti||"未知"}\n- 依恋类型:${profile.attachment||"未知"}\n- 爱之语:${profile.lovelang||"未知"}\n- 雷区:${profile.triggers||"未知"}\n\n完全按 TA 人设回复用户。每轮对话给用户评分(1-10)+ 改进建议。返回JSON:{"ta_reply":"TA会这么说","score":7,"feedback":"你可以这样说得更好..."}`,
  responsibility: () => `你是关系教练,不是判官。用户描述了一次冲突,你需要:1)不判对错 2)分析双方各自可以改进的地方 3)给用户自己能控制的具体行动。返回JSON:{"note":"不是分对错,是分解各自可以做得更好的地方","your_share":"你的责任占比 30-70%","ta_share":"TA的责任占比","your_gaps":["你3个具体改进点"],"ta_gaps":["TA 3个改进点,但你只能建议不能强迫"],"your_actions":["你立即可做的3件事"],"script":"可以怎么和 TA 谈这次事件(软启动话术)"}`,
  date_spot: (profile) => `基于 TA 档案给 4 个约会地点建议:\nTA 喜好:${profile.likes||"未知"}\nTA 性格:${profile.mbti||"未知"}\n关系阶段:${profile.stage||"未知"}\n预算提示:考虑 3 档(¥100以下/¥100-500/¥500+)\n返回JSON:{"spots":[{"name":"地点","type":"咖啡店/餐厅/景点","budget":"¥150","why_suits":"为什么适合 TA","tips":"小 tip","backup":"如果她不喜欢可以换..."}]}`,
  gift_rec: (profile) => `基于 TA 爱之语和档案推荐 4 个礼物:\nTA 爱之语:${profile.lovelang||"未知"}\nTA 喜好:${profile.likes||"未知"}\nTA 雷区:${profile.triggers||"未知"}\n禁忌:不要推荐昂贵但 TA 不在乎的;优先 TA 爱之语对应的类型\n返回JSON:{"principle":"为什么这些礼物适合 TA","gifts":[{"name":"礼物名","budget":"¥200","matches_love_lang":"对应爱之语","why":"为什么","where":"在哪买"}],"forbidden":["避免的3类礼物"]}`,
  scam_v2: () => `你是深度鉴渣工具。综合 12 维评估:1)言行一致 2)朋友圈展示 3)为你花时间 4)介绍你给朋友 5)未来计划 6)处理冲突方式 7)前任痕迹 8)金钱观 9)家庭态度 10)是否 PUA 11)情绪稳定性 12)对服务员的态度。给综合评分+每维诊断。返回JSON:{"score":65,"level":"中等风险","dimensions":[{"name":"维度名","score":8,"note":"具体观察","red_flag":false}],"verdict":"综合判断","advice":"建议行动"}`,
  npd_check: () => `你是 NPD(自恋型人格障碍)识别工具。基于 DSM-5 9 大诊断标准评估:1)夸大感 2)幻想成功 3)特殊信念 4)过度崇拜需求 5)特权感 6)利用他人 7)缺乏共情 8)嫉妒 9)傲慢。5 项以上达标提示 NPD 倾向。返回JSON:{"matches":5,"level":"高度疑似/疑似/低疑似/无","criteria":[{"name":"标准","met":true,"evidence":"用户描述中的证据"}],"advice":"建议","resources":["如果确认请查阅资源"]}`,
};

function V25Game({gameId, profile, st, vip, setShowPay, onBack}) {
  const [inp, setInp] = useState("");
  const [ld, setLd] = useState(false);
  const [res, setRes] = useState(null);
  const [err, setErr] = useState(null);
  const [freeUsed, setFreeUsed] = useState(false);

  // "1 free" for date_spot and gift_rec
  const needsPay = (gameId === "date_spot" || gameId === "gift_rec") && !vip && freeUsed;
  const totalFree = gameId === "roleplay_pro"; // pro only
  
  useEffect(() => {
    if (gameId === "date_spot" || gameId === "gift_rec") {
      (async () => {
        try {
          const r = await window.storage.get(`sakura-v25-${gameId}-used`);
          if (r?.value) setFreeUsed(true);
        } catch {}
      })();
    }
  }, [gameId]);

  const run = async () => {
    if (!inp.trim() || ld) return;
    if (totalFree && !vip) { setShowPay(true); return; }
    if (needsPay) { setShowPay(true); return; }
    setLd(true); setRes(null); setErr(null);
    try {
      const promptFn = V25_PROMPTS[gameId];
      if (!promptFn) { setErr("功能暂未启用"); setLd(false); return; }
      const sys = promptFn(profile || {});
      const c = new AbortController();
      const t = setTimeout(() => c.abort(), 45000);
      const r = await fetch(API_URL, {
        method: "POST",
        headers: {"Content-Type": "application/json"},
        body: JSON.stringify({model: API_MODEL, max_tokens: 1500, system: sys, messages: [{role: "user", content: inp}]}),
        signal: c.signal
      });
      clearTimeout(t);
      const d = await r.json();
      if (d.error) { setErr(d.error.message); setLd(false); return; }
      const txt = d.content?.[0]?.text || "";
      let parsed = null;
      try {
        const m = txt.match(/\{[\s\S]+\}/);
        if (m) parsed = JSON.parse(m[0]);
      } catch {}
      if (!parsed) {
        setErr("AI 返回格式错误,请重试");
        setLd(false);
        return;
      }
      setRes(parsed);
      // Mark free used
      if (gameId === "date_spot" || gameId === "gift_rec") {
        try { await window.storage.set(`sakura-v25-${gameId}-used`, "1"); } catch {}
        setFreeUsed(true);
      }
    } catch (e) {
      setErr(e.name === "AbortError" ? "请求超时" : e.message);
    }
    setLd(false);
  };

  const titles = {
    roleplay_pro: {icon: "🎭", title: "专属模拟对话 · Pro", desc: "AI 扮演你的 TA,基于档案深度演练", prompt: "场景描述(如:告白前夜/道歉现场)"},
    responsibility: {icon: "⚖️", title: "双方责任分析", desc: "不判对错,只分析各自改进", prompt: "详细描述这次冲突:事件/你的行为/TA 的行为/你希望的结果"},
    date_spot: {icon: "📍", title: "约会地点推荐", desc: "基于 TA 档案的定制建议 · 1 次免费", prompt: "你想约 TA 做什么?(看电影/吃饭/户外/喝咖啡)+ 所在城市"},
    gift_rec: {icon: "🎁", title: "送礼推荐", desc: "基于爱之语的礼物清单 · 1 次免费", prompt: "什么场合?(生日/纪念日/道歉/随心)+ 预算范围"},
    scam_v2: {icon: "🕵️", title: "深度鉴渣 · 12 维扫描", desc: "综合评估伴侣风险", prompt: "描述 TA 最近的具体行为(越多越准,不少于 5 条)"},
    npd_check: {icon: "🧠", title: "NPD 识别 · DSM-5 标准", desc: "自恋型人格 9 诊断", prompt: "描述 TA 的言行特征(重点:是否需要过度崇拜/是否缺乏共情/是否利用你)"},
  };
  const info = titles[gameId] || {icon: "⭐", title: "功能", desc: "", prompt: ""};

  return (
    <div style={{paddingBottom: 100}}>
      <div style={{padding: "14px 14px 4px", borderBottom: "1px solid #fee"}}>
        <button onClick={onBack} style={{background: "none", border: "none", color: "#c9306b", fontSize: 13, fontWeight: 700, cursor: "pointer", marginBottom: 8, padding: 0}}>← 返回</button>
        <div style={{fontSize: 20, fontWeight: 900, color: "#c9306b", marginBottom: 4}}>{info.icon} {info.title}</div>
        <div style={{fontSize: 11, color: "#8b5a78", marginBottom: 8}}>{info.desc}</div>
      </div>
      <div style={{padding: "14px 16px"}}>
        {!vip && totalFree && (
          <div style={{padding: "10px 12px", borderRadius: 10, background: "#fff5f7", border: "1px solid #ffd2dc", marginBottom: 12, fontSize: 11, color: "#c9306b"}}>
            🌸 专属模拟对话仅 Pro 用户可用 · 月卡 ¥56 / 年卡 ¥488
          </div>
        )}
        {!vip && needsPay && (
          <div style={{padding: "10px 12px", borderRadius: 10, background: "#fff5f7", border: "1px solid #ffd2dc", marginBottom: 12, fontSize: 11, color: "#c9306b"}}>
            ⭐ 免费次数已用完 · 升级 Pro 无限次使用
          </div>
        )}
        <div style={{padding: "12px", borderRadius: 12, background: "#fff", border: "1px solid #fee", marginBottom: 10}}>
          <div style={{fontSize: 11, color: "#7e4c5c", marginBottom: 6}}>💭 {info.prompt}</div>
          <textarea value={inp} onChange={e => setInp(e.target.value)} placeholder="详细描述..." style={{width: "100%", minHeight: 100, padding: 10, border: "1px solid #eee", borderRadius: 8, fontSize: 13, outline: "none", resize: "vertical", fontFamily: "inherit"}}/>
        </div>
        <button onClick={run} disabled={!inp.trim() || ld} style={{width: "100%", padding: "12px", borderRadius: 12, border: "none", cursor: (inp.trim() && !ld) ? "pointer" : "default", background: (inp.trim() && !ld) ? "linear-gradient(135deg,#E84D8C,#F97316)" : "#e8e8e8", color: (inp.trim() && !ld) ? "#fff" : "#999", fontSize: 14, fontWeight: 800}}>
          {ld ? "🔮 分析中..." : "✨ 开始分析"}
        </button>
        {err && <div style={{marginTop: 10, padding: 12, borderRadius: 10, background: "#fef2f2", color: "#dc2626", fontSize: 12}}>❌ {err}</div>}
        {res && <V25Result gameId={gameId} data={res}/>}
      </div>
    </div>
  );
}

function V25Result({gameId, data}) {
  const card = {padding: "12px 14px", borderRadius: 12, background: "#fff", border: "1px solid #fee", marginBottom: 10};
  
  if (gameId === "roleplay_pro") {
    return <div style={{marginTop: 14}}>
      <div style={card}><div style={{fontSize: 11, color: "#c9306b", fontWeight: 700, marginBottom: 6}}>💬 TA 会这么说</div><div style={{fontSize: 14, lineHeight: 1.7, color: "#4a2838"}}>{data.ta_reply}</div></div>
      <div style={card}><div style={{fontSize: 11, color: "#0EA5E9", fontWeight: 700, marginBottom: 6}}>📊 你的表现 {data.score}/10</div><div style={{fontSize: 13, lineHeight: 1.6, color: "#4a2838"}}>{data.feedback}</div></div>
    </div>;
  }
  if (gameId === "responsibility") {
    return <div style={{marginTop: 14}}>
      <div style={{...card, background: "#eff6ff", borderColor: "#bfdbfe"}}><div style={{fontSize: 11, color: "#0EA5E9", fontWeight: 700, marginBottom: 6}}>ℹ️ 重要提醒</div><div style={{fontSize: 12, color: "#1e40af"}}>{data.note}</div></div>
      <div style={{display: "flex", gap: 8, marginBottom: 10}}>
        <div style={{flex: 1, ...card, textAlign: "center"}}><div style={{fontSize: 10, color: "#7e4c5c"}}>你的责任</div><div style={{fontSize: 24, fontWeight: 900, color: "#E84D8C"}}>{data.your_share}</div></div>
        <div style={{flex: 1, ...card, textAlign: "center"}}><div style={{fontSize: 10, color: "#7e4c5c"}}>TA 的责任</div><div style={{fontSize: 24, fontWeight: 900, color: "#0EA5E9"}}>{data.ta_share}</div></div>
      </div>
      <div style={card}><div style={{fontSize: 11, color: "#E84D8C", fontWeight: 700, marginBottom: 6}}>📝 你可以改进的</div>{data.your_gaps?.map((g, i) => <div key={i} style={{fontSize: 12, color: "#4a2838", padding: "4px 0", borderBottom: "1px dashed #fee"}}>{i+1}. {g}</div>)}</div>
      <div style={card}><div style={{fontSize: 11, color: "#0EA5E9", fontWeight: 700, marginBottom: 6}}>📝 TA 可以改进的(只能建议)</div>{data.ta_gaps?.map((g, i) => <div key={i} style={{fontSize: 12, color: "#4a2838", padding: "4px 0", borderBottom: "1px dashed #fee"}}>{i+1}. {g}</div>)}</div>
      <div style={{...card, background: "#f0fdf4", borderColor: "#bbf7d0"}}><div style={{fontSize: 11, color: "#16a34a", fontWeight: 700, marginBottom: 6}}>✅ 你立即可做的</div>{data.your_actions?.map((a, i) => <div key={i} style={{fontSize: 12, color: "#166534", padding: "4px 0"}}>• {a}</div>)}</div>
      {data.script && <div style={{...card, background: "#fff5f7", borderColor: "#ffd2dc"}}><div style={{fontSize: 11, color: "#c9306b", fontWeight: 700, marginBottom: 6}}>💬 可以这么和 TA 谈</div><div style={{fontSize: 12, color: "#4a2838", lineHeight: 1.7}}>{data.script}</div></div>}
    </div>;
  }
  if (gameId === "date_spot" && data.spots) {
    return <div style={{marginTop: 14}}>
      {data.spots.map((s, i) => <div key={i} style={card}>
        <div style={{display: "flex", justifyContent: "space-between", marginBottom: 4}}>
          <div style={{fontSize: 13, fontWeight: 700, color: "#10b981"}}>📍 {s.name}</div>
          <div style={{fontSize: 11, color: "#7e4c5c"}}>{s.budget}</div>
        </div>
        <div style={{fontSize: 10, color: "#a07080", marginBottom: 4}}>类型:{s.type}</div>
        <div style={{fontSize: 12, color: "#4a2838", lineHeight: 1.6, marginBottom: 4}}>💡 {s.why_suits}</div>
        {s.tips && <div style={{fontSize: 11, color: "#0EA5E9"}}>小 tip:{s.tips}</div>}
        {s.backup && <div style={{fontSize: 10, color: "#a07080", marginTop: 4}}>备选:{s.backup}</div>}
      </div>)}
    </div>;
  }
  if (gameId === "gift_rec" && data.gifts) {
    return <div style={{marginTop: 14}}>
      {data.principle && <div style={{...card, background: "#fff5f7"}}><div style={{fontSize: 11, color: "#c9306b", fontWeight: 700, marginBottom: 4}}>💝 送礼原则</div><div style={{fontSize: 12, color: "#4a2838"}}>{data.principle}</div></div>}
      {data.gifts.map((g, i) => <div key={i} style={card}>
        <div style={{display: "flex", justifyContent: "space-between", marginBottom: 4}}>
          <div style={{fontSize: 13, fontWeight: 700, color: "#f59e0b"}}>🎁 {g.name}</div>
          <div style={{fontSize: 11, color: "#7e4c5c"}}>{g.budget}</div>
        </div>
        <div style={{fontSize: 10, color: "#c9306b", marginBottom: 4}}>✨ 对应爱之语:{g.matches_love_lang}</div>
        <div style={{fontSize: 12, color: "#4a2838", lineHeight: 1.6}}>💡 {g.why}</div>
        {g.where && <div style={{fontSize: 10, color: "#a07080", marginTop: 4}}>📍 在哪买:{g.where}</div>}
      </div>)}
      {data.forbidden && <div style={{...card, background: "#fef2f2", borderColor: "#fecaca"}}><div style={{fontSize: 11, color: "#dc2626", fontWeight: 700, marginBottom: 4}}>🚫 不要送</div>{data.forbidden.map((f, i) => <div key={i} style={{fontSize: 11, color: "#7f1d1d", padding: "2px 0"}}>× {f}</div>)}</div>}
    </div>;
  }
  if (gameId === "scam_v2") {
    const scoreColor = data.score < 40 ? "#dc2626" : data.score < 70 ? "#f59e0b" : "#10b981";
    return <div style={{marginTop: 14}}>
      <div style={{...card, textAlign: "center", background: `${scoreColor}10`, borderColor: scoreColor}}>
        <div style={{fontSize: 40, fontWeight: 900, color: scoreColor}}>{data.score}/100</div>
        <div style={{fontSize: 14, fontWeight: 700, color: scoreColor, marginTop: 4}}>{data.level}</div>
      </div>
      <div style={card}><div style={{fontSize: 11, fontWeight: 700, color: "#dc2626", marginBottom: 8}}>🔍 12 维度扫描</div>
        {data.dimensions?.map((d, i) => <div key={i} style={{padding: "6px 0", borderBottom: "1px dashed #fee"}}>
          <div style={{display: "flex", justifyContent: "space-between"}}>
            <span style={{fontSize: 11, color: "#4a2838", fontWeight: 600}}>{d.red_flag ? "🔴" : "✓"} {d.name}</span>
            <span style={{fontSize: 11, fontWeight: 700, color: d.score < 5 ? "#dc2626" : "#10b981"}}>{d.score}/10</span>
          </div>
          {d.note && <div style={{fontSize: 10, color: "#7e4c5c", marginTop: 2}}>{d.note}</div>}
        </div>)}
      </div>
      {data.verdict && <div style={{...card, background: "#fff5f7"}}><div style={{fontSize: 11, fontWeight: 700, color: "#c9306b", marginBottom: 4}}>📊 综合判断</div><div style={{fontSize: 12, color: "#4a2838", lineHeight: 1.7}}>{data.verdict}</div></div>}
      {data.advice && <div style={{...card, background: "#f0fdf4"}}><div style={{fontSize: 11, fontWeight: 700, color: "#16a34a", marginBottom: 4}}>💡 建议</div><div style={{fontSize: 12, color: "#166534", lineHeight: 1.7}}>{data.advice}</div></div>}
    </div>;
  }
  if (gameId === "npd_check") {
    const matchColor = data.matches >= 5 ? "#dc2626" : data.matches >= 3 ? "#f59e0b" : "#10b981";
    return <div style={{marginTop: 14}}>
      <div style={{...card, textAlign: "center", background: `${matchColor}10`, borderColor: matchColor}}>
        <div style={{fontSize: 11, color: "#7e4c5c", marginBottom: 4}}>符合 DSM-5 诊断标准</div>
        <div style={{fontSize: 40, fontWeight: 900, color: matchColor}}>{data.matches} / 9</div>
        <div style={{fontSize: 14, fontWeight: 700, color: matchColor, marginTop: 4}}>{data.level}</div>
      </div>
      <div style={card}><div style={{fontSize: 11, fontWeight: 700, color: "#7c3aed", marginBottom: 8}}>🔬 9 大诊断标准</div>
        {data.criteria?.map((c, i) => <div key={i} style={{padding: "6px 0", borderBottom: "1px dashed #fee"}}>
          <div style={{fontSize: 11, color: "#4a2838", fontWeight: 600}}>{c.met ? "✅" : "⬜"} {c.name}</div>
          {c.evidence && <div style={{fontSize: 10, color: "#7e4c5c", marginTop: 2, paddingLeft: 18}}>{c.evidence}</div>}
        </div>)}
      </div>
      {data.advice && <div style={{...card, background: "#f0fdf4"}}><div style={{fontSize: 11, fontWeight: 700, color: "#16a34a", marginBottom: 4}}>💡 建议</div><div style={{fontSize: 12, color: "#166534", lineHeight: 1.7}}>{data.advice}</div></div>}
      {data.resources && <div style={card}><div style={{fontSize: 11, fontWeight: 700, color: "#7c3aed", marginBottom: 4}}>📚 资源</div>{data.resources.map((r, i) => <div key={i} style={{fontSize: 11, color: "#4a2838", padding: "2px 0"}}>• {r}</div>)}</div>}
    </div>;
  }
  // Generic fallback
  return <div style={{marginTop: 14, ...card}}><pre style={{fontSize: 10, color: "#4a2838", whiteSpace: "pre-wrap", lineHeight: 1.6}}>{JSON.stringify(data, null, 2)}</pre></div>;
}

/* ═══ v2.5 Invite component (拉人送 Pro) ═══ */
function V25Invite({st, onBack, setShowPay}) {
  const [code, setCode] = useState("");
  const [bonus, setBonus] = useState(0);
  
  useEffect(() => {
    (async () => {
      try {
        let r = await window.storage.get("sakura-invite-code");
        if (!r?.value) {
          const newCode = "SK" + Math.random().toString(36).substring(2, 8).toUpperCase();
          await window.storage.set("sakura-invite-code", newCode);
          setCode(newCode);
        } else setCode(r.value);
      } catch {}
      try {
        const b = await window.storage.get("sakura-invite-bonus");
        if (b?.value) setBonus(parseInt(b.value) || 0);
      } catch {}
    })();
  }, []);

  const share = async () => {
    const text = `我在用 Sakura — 最懂恋爱的 AI 助手,也是幸福生活的守护者 🌸 用我的邀请码 ${code} 注册,我们俩都能得 3 天 Pro 体验。https://sakura.app (占位)`;
    try {
      if (navigator.share) {
        await navigator.share({title: "Sakura 邀请", text});
      } else {
        await navigator.clipboard.writeText(text);
        st("已复制邀请文案");
      }
    } catch {}
  };

  return <div style={{paddingBottom: 100}}>
    <div style={{padding: "14px 14px 4px", borderBottom: "1px solid #fee"}}>
      <button onClick={onBack} style={{background: "none", border: "none", color: "#c9306b", fontSize: 13, fontWeight: 700, cursor: "pointer", marginBottom: 8, padding: 0}}>← 返回</button>
      <div style={{fontSize: 20, fontWeight: 900, color: "#c9306b", marginBottom: 4}}>🎉 邀请好友</div>
      <div style={{fontSize: 11, color: "#8b5a78"}}>拉 1 人注册,你和对方都得 3 天 Pro 体验</div>
    </div>
    <div style={{padding: "14px 16px"}}>
      <div style={{padding: "20px", borderRadius: 16, background: "linear-gradient(135deg,#fff5f7,#fef3c7)", border: "1px solid #ffd2dc", textAlign: "center", marginBottom: 14}}>
        <div style={{fontSize: 10, color: "#8b5a78", marginBottom: 6}}>你的专属邀请码</div>
        <div style={{fontSize: 28, fontWeight: 900, color: "#c9306b", letterSpacing: 4, marginBottom: 8}}>{code}</div>
        <button onClick={share} style={{padding: "10px 24px", borderRadius: 12, border: "none", background: "linear-gradient(135deg,#E84D8C,#F97316)", color: "#fff", fontSize: 13, fontWeight: 800, cursor: "pointer"}}>🔗 分享给朋友</button>
      </div>
      <div style={{padding: 14, borderRadius: 12, background: "#fff", border: "1px solid #fee", marginBottom: 12}}>
        <div style={{fontSize: 12, fontWeight: 700, color: "#c9306b", marginBottom: 8}}>🎁 你的奖励</div>
        <div style={{display: "flex", justifyContent: "space-between", padding: "6px 0"}}>
          <span style={{fontSize: 12, color: "#4a2838"}}>已成功邀请</span>
          <span style={{fontSize: 14, fontWeight: 900, color: "#E84D8C"}}>{bonus} 人</span>
        </div>
        <div style={{display: "flex", justifyContent: "space-between", padding: "6px 0"}}>
          <span style={{fontSize: 12, color: "#4a2838"}}>累计获得</span>
          <span style={{fontSize: 14, fontWeight: 900, color: "#F97316"}}>{bonus * 3} 天 Pro</span>
        </div>
        <button onClick={async()=>{const newB=bonus+1;setBonus(newB);try{await window.storage.set("sakura-invite-bonus",String(newB));}catch{}st("✅ 已记录 +3 天 Pro");}} style={{width:"100%",marginTop:8,padding:"8px",borderRadius:8,background:"#fff5f7",border:"1px solid #ffd2dc",color:"#c9306b",fontSize:11,fontWeight:700,cursor:"pointer"}}>✨ 我邀请了一个朋友（手动记录）</button>
        <div style={{fontSize:9,color:"#a07080",marginTop:4,textAlign:"center"}}>朋友注册后,在这里点一下记录</div>
      </div>
      <div style={{padding: 14, borderRadius: 12, background: "#eff6ff", border: "1px solid #bfdbfe", marginBottom: 12}}>
        <div style={{fontSize: 12, fontWeight: 700, color: "#1e40af", marginBottom: 8}}>📖 怎么获得奖励</div>
        <div style={{fontSize: 11, color: "#1e3a8a", lineHeight: 1.9}}>
          1. 把你的邀请码发给朋友<br/>
          2. 朋友在注册时输入邀请码<br/>
          3. 双方各得 3 天 Pro 体验<br/>
          4. 无上限,邀请越多送越多
        </div>
      </div>
      <div style={{padding: 10, borderRadius: 10, background: "#fff5f7", fontSize: 10, color: "#7e4c5c", textAlign: "center"}}>
        💡 好友注册后在"我的 → 邀请码"输入你的码即可激活
      </div>
    </div>
  </div>;
}

/* ═══ v2.5 Anniversary Push (Web Push + in-app reminders) ═══ */
function V25AnnivPush({anniversaries, st, onBack}) {
  const [permState, setPermState] = useState("default");
  const [pushEnabled, setPushEnabled] = useState(false);

  useEffect(() => {
    if ("Notification" in window) {
      setPermState(Notification.permission);
    }
    (async () => {
      try {
        const r = await window.storage.get("sakura-push-enabled");
        if (r?.value === "1") setPushEnabled(true);
      } catch {}
    })();
  }, []);

  const enablePush = async () => {
    if (!("Notification" in window)) {
      st("此浏览器不支持推送");
      return;
    }
    try {
      const p = await Notification.requestPermission();
      setPermState(p);
      if (p === "granted") {
        setPushEnabled(true);
        await window.storage.set("sakura-push-enabled", "1");
        new Notification("🌸 Sakura 推送已开启", {body: "纪念日前 3 天会提醒你", icon: "/favicon.ico"});
        st("✅ 推送已开启");
      } else {
        st("授权被拒绝 · 可在浏览器设置中开启");
      }
    } catch (e) {
      st("授权失败:" + e.message);
    }
  };

  const disablePush = async () => {
    setPushEnabled(false);
    try { await window.storage.set("sakura-push-enabled", "0"); } catch {}
    st("推送已关闭");
  };

  const daysUntil = (ds) => {
    const d = new Date(ds);
    const now = new Date();
    const ty = new Date(now.getFullYear(), d.getMonth(), d.getDate());
    if (ty < now) ty.setFullYear(ty.getFullYear() + 1);
    return Math.ceil((ty - now) / 86400000);
  };

  const upcoming = (anniversaries || []).map(a => ({...a, days: daysUntil(a.date)})).sort((a, b) => a.days - b.days).slice(0, 5);

  return <div style={{paddingBottom: 100}}>
    <div style={{padding: "14px 14px 4px", borderBottom: "1px solid #fee"}}>
      <button onClick={onBack} style={{background: "none", border: "none", color: "#c9306b", fontSize: 13, fontWeight: 700, cursor: "pointer", marginBottom: 8, padding: 0}}>← 返回</button>
      <div style={{fontSize: 20, fontWeight: 900, color: "#ec4899", marginBottom: 4}}>🔔 纪念日提醒</div>
      <div style={{fontSize: 11, color: "#8b5a78"}}>网页推送 · 不错过重要日子</div>
    </div>
    <div style={{padding: "14px 16px"}}>
      <div style={{padding: 14, borderRadius: 12, background: pushEnabled ? "#f0fdf4" : "#fff5f7", border: `1px solid ${pushEnabled ? "#bbf7d0" : "#ffd2dc"}`, marginBottom: 14}}>
        <div style={{display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 8}}>
          <div style={{fontSize: 13, fontWeight: 700, color: pushEnabled ? "#16a34a" : "#c9306b"}}>
            {pushEnabled ? "✅ 推送已开启" : "⏰ 开启网页推送"}
          </div>
          <div style={{fontSize: 10, color: "#7e4c5c"}}>浏览器权限:{permState}</div>
        </div>
        <div style={{fontSize: 11, color: "#4a2838", lineHeight: 1.7, marginBottom: 10}}>
          {pushEnabled ? "纪念日前 3 天,Sakura 会在你的浏览器推送提醒(即使关闭 Sakura 页面)。" : "开启后,纪念日前 3 天会收到系统推送,即使关闭 Sakura 也能收到。"}
        </div>
        <button onClick={pushEnabled ? disablePush : enablePush} style={{width: "100%", padding: "10px", borderRadius: 10, border: "none", background: pushEnabled ? "#e5e7eb" : "linear-gradient(135deg,#ec4899,#f59e0b)", color: pushEnabled ? "#666" : "#fff", fontSize: 12, fontWeight: 800, cursor: "pointer"}}>
          {pushEnabled ? "关闭推送" : "🔔 开启推送授权"}
        </button>
      </div>
      <div style={{padding: 14, borderRadius: 12, background: "#fff", border: "1px solid #fee"}}>
        <div style={{fontSize: 12, fontWeight: 700, color: "#ec4899", marginBottom: 8}}>📅 即将到来的纪念日</div>
        {upcoming.length === 0 ? (
          <div style={{fontSize: 11, color: "#a07080", textAlign: "center", padding: 20}}>
            还没添加纪念日,去"我的 → 纪念日"添加
          </div>
        ) : upcoming.map((a, i) => (
          <div key={i} style={{display: "flex", justifyContent: "space-between", padding: "8px 0", borderBottom: "1px dashed #fee"}}>
            <div>
              <div style={{fontSize: 12, fontWeight: 700, color: "#4a2838"}}>{a.label}</div>
              <div style={{fontSize: 10, color: "#a07080"}}>{a.date}</div>
            </div>
            <div style={{fontSize: 14, fontWeight: 900, color: a.days <= 7 ? "#ec4899" : "#7e4c5c"}}>
              {a.days === 0 ? "今天 🎉" : `${a.days} 天`}
            </div>
          </div>
        ))}
      </div>
      {pushEnabled && (
        <div style={{marginTop: 10, padding: 10, borderRadius: 10, background: "#eff6ff", fontSize: 10, color: "#1e3a8a", textAlign: "center"}}>
          💡 Sakura 会每天检查一次即将到来的纪念日
        </div>
      )}
    </div>
  </div>;
}

const Paywall=({onClose,st,onPurchase})=>{const[plan,setPlan]=useState("month");return <div style={{position:"fixed",inset:0,zIndex:300,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(0,0,0,.5)",backdropFilter:"blur(8px)"}}><div style={{width:"90%",maxWidth:380,background:C.white,borderRadius:24,padding:"28px 24px",position:"relative",animation:"fadeUp .3s"}}><button onClick={onClose} style={{position:"absolute",top:12,right:16,background:"none",border:"none",fontSize:18,color:C.t3,cursor:"pointer"}}>✕</button><div style={{textAlign:"center",marginBottom:16}}><div style={{fontSize:40,marginBottom:6}}>🌸</div><div style={{fontSize:20,fontWeight:900,background:`linear-gradient(135deg,${C.pink},${C.gold})`,WebkitBackgroundClip:"text",WebkitTextFillColor:"transparent"}}>Sakura Pro</div><div style={{fontSize:11,color:C.t3,marginTop:4}}>解锁全部功能 · 无限使用</div></div><div style={{display:"flex",flexDirection:"column",gap:8,marginBottom:16}}>{[{id:"first",price:"¥9.9",sub:"首周特惠",note:"新用户专享 · 7 天全功能",c:C.coral},{id:"week",price:"¥16",sub:"周卡",note:"续费常规",c:C.t2},{id:"month",price:"¥56",sub:"月卡",note:"¥1.87/天",c:C.peri,hot:true},{id:"year",price:"¥488",sub:"年卡",note:"买 12 送 2 月 · ¥1.14/天",c:C.pink}].map(p=><button key={p.id} className="tap" onClick={()=>setPlan(p.id)} style={{padding:"14px 16px",borderRadius:16,border:plan===p.id?`2.5px solid ${p.c}`:`1.5px solid ${C.bd}`,background:plan===p.id?`${p.c}06`:C.white,cursor:"pointer",textAlign:"left",position:"relative"}}>{p.hot&&<span style={{position:"absolute",top:-8,right:12,padding:"2px 10px",borderRadius:10,background:`linear-gradient(135deg,${C.pink},${C.gold})`,color:"#fff",fontSize:9,fontWeight:700}}>最划算</span>}<div style={{display:"flex",justifyContent:"space-between",alignItems:"center"}}><div><div style={{fontSize:15,fontWeight:800,color:plan===p.id?p.c:C.t1}}>{p.sub}</div><div style={{fontSize:10,color:C.t3}}>{p.note}</div></div><div style={{fontSize:20,fontWeight:900,color:plan===p.id?p.c:C.t1}}>{p.price}</div></div></button>)}</div><div style={{marginBottom:10,padding:"10px 14px",borderRadius:12,background:`linear-gradient(135deg,${C.pink}06,${C.gold}04)`,border:`1px solid ${C.pink}15`}}><div style={{fontSize:10,color:C.t1,lineHeight:1.8,textAlign:"center"}}>✅ 无限秒回/AI思考 · ✅ 无限诊断<br/>✅ 全部AI工具 · ✅ 角色扮演/挑战<br/>✅ 多TA管理 · ✅ 翻译历史</div></div><Btn primary onClick={()=>{if(onPurchase)onPurchase();onClose();st?.("🌸 已开通Pro");try{window.storage.set("sakura-vip","true");}catch{}}}>{plan==="year"?"🌸 开通年卡 ¥488":plan==="month"?"开通月卡 ¥56":plan==="week"?"开通周卡 ¥16":"首周特惠 ¥9.9"}</Btn><div style={{marginTop:8,fontSize:9,color:C.t3,textAlign:"center"}}>免费功能：润色 · 20个游戏 · 基础画像</div></div></div>;};

/* ═══ P0-#02 Privacy First-Run Dialog ═══ */
const PrivacyDialog=({onAccept})=>{const[agreed,setAgreed]=useState(false);return <div style={{position:"fixed",inset:0,zIndex:500,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(0,0,0,.55)",backdropFilter:"blur(8px)"}}><div style={{width:"92%",maxWidth:380,background:"#fff",borderRadius:24,padding:"26px 22px",animation:"fadeUp .3s"}}><div style={{textAlign:"center",marginBottom:14}}><div style={{fontSize:36,marginBottom:4}}>🔒</div><div style={{fontSize:17,fontWeight:900,color:"#c9306b"}}>你的隐私，我们说清楚</div><div style={{fontSize:10,color:"#8b5a78",marginTop:4}}>在你开始用 Sakura 之前，请了解:</div></div><div style={{fontSize:11.5,color:"#4a2838",lineHeight:1.9,padding:"12px 14px",borderRadius:12,background:"#fff5f7",marginBottom:14}}><div>✓ 你输入的内容仅用于 AI 分析，不作他用</div><div>✓ 聊天记录保留最多 30 天，到期自动删除</div><div>✓ 不与任何第三方共享你的数据</div><div>✓ Sakura 不读取微信/相册，只处理你主动粘贴的内容</div><div>✓ 可随时删除账号和所有数据，我们不留底</div></div><div className="tap2" onClick={()=>setAgreed(!agreed)} style={{display:"flex",alignItems:"center",gap:8,padding:"10px 12px",borderRadius:10,background:agreed?"#ffe8ef":"#f8f8f8",cursor:"pointer",marginBottom:12}}><div style={{width:18,height:18,borderRadius:4,border:`2px solid ${agreed?"#E84D8C":"#ccc"}`,background:agreed?"#E84D8C":"transparent",display:"flex",alignItems:"center",justifyContent:"center",color:"#fff",fontSize:11,fontWeight:900}}>{agreed?"✓":""}</div><div style={{fontSize:12,color:"#4a2838",fontWeight:600}}>我已阅读并同意继续</div></div><button className="tap" onClick={()=>{if(!agreed)return;try{window.storage.set("sakura-privacy-v1","accepted");}catch{}onAccept();}} disabled={!agreed} style={{width:"100%",padding:"13px",borderRadius:14,border:"none",cursor:agreed?"pointer":"default",background:agreed?"linear-gradient(135deg,#E84D8C,#F97316)":"#e8e8e8",color:agreed?"#fff":"#999",fontSize:14,fontWeight:800}}>{agreed?"开始使用 Sakura":"请勾选同意"}</button></div></div>;};

/* ═══ P1-#06 PUA 快速扫描 (复用已有 PUA_PATTERNS + 轻量关键词) ═══ */
const PUA_QUICK_KWS=[{level:"high",cat:"孤立",kws:["只有我才","除了我没人","没人会要你","别人不会要","你离开我就完了"],warn:"孤立式：让你觉得离开 TA 就没人要"},{level:"high",cat:"贬低",kws:["你太差","你配不上","你算什么","谁要你这种","像你这样的"],warn:"贬低式：否定你的价值"},{level:"high",cat:"情感勒索",kws:["都是为你好","你要是爱我就","你不这样就是不爱","我都这样了你还","为了你我"],warn:"情感勒索：把要求包装成爱"},{level:"med",cat:"冷暴力",kws:["随便你","爱怎样怎样","你自己想吧","当我没说"],warn:"冷暴力倾向"},{level:"med",cat:"忽冷忽热",kws:["算了不想说了","没什么可说的","没事了"],warn:"间歇性冷处理"},{level:"low",cat:"控制",kws:["你必须","不许你","我警告你","你听我的"],warn:"控制式语言"}];
const scanPUA=(text)=>{if(!text||text.length<3)return null;const hits=[];for(const p of PUA_QUICK_KWS){for(const kw of p.kws){if(text.includes(kw)){hits.push({level:p.level,cat:p.cat,warn:p.warn,matched:kw});break;}}}try{if(typeof PUA_PATTERNS!=="undefined"&&Array.isArray(PUA_PATTERNS)){for(const p of PUA_PATTERNS){if(text.includes(p.pattern)){hits.push({level:p.risk>=90?"high":p.risk>=80?"med":"low",cat:p.tag,warn:p.explain,matched:p.pattern});}}}}catch{}if(hits.length===0)return null;const hasHigh=hits.some(h=>h.level==="high");const hasMed=hits.some(h=>h.level==="med");return{level:hasHigh?"high":hasMed?"med":"low",count:hits.length,hits};};
const PuaAlert=({result,onDeepScan})=>{const[expanded,setExpanded]=useState(false);if(!result)return null;const isHigh=result.level==="high";const clr=isHigh?"#dc2626":"#f59e0b";const bg=isHigh?"#fef2f2":"#fffbeb";const bd=isHigh?"#fecaca":"#fde68a";if(!isHigh&&!expanded){return <div onClick={()=>setExpanded(true)} style={{margin:"6px 14px 0",padding:"6px 10px",borderRadius:10,background:bg,border:`1px solid ${bd}`,cursor:"pointer",display:"flex",alignItems:"center",gap:6,fontSize:10,color:clr}}><span>⚠️</span><span style={{flex:1}}>检测到 {result.count} 处需关注的措辞（点击展开）</span><span>▼</span></div>;}return <div style={{margin:"6px 14px 0",padding:"10px 12px",borderRadius:12,background:bg,border:`${isHigh?2:1}px solid ${bd}`,animation:"fadeUp .25s"}}><div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:8,cursor:"pointer"}} onClick={()=>setExpanded(!expanded)}><div style={{display:"flex",alignItems:"center",gap:6,fontSize:12,fontWeight:800,color:clr}}>{isHigh?"🚨":"⚠️"} {isHigh?"警惕：检测到 PUA 话术":"需要留意的措辞"}</div><span style={{fontSize:11,color:clr}}>{expanded?"▲":"▼"}</span></div>{expanded&&<><div style={{marginBottom:8}}>{result.hits.map((h,i)=><div key={i} style={{fontSize:11,color:"#4a2838",marginTop:4,paddingLeft:6,borderLeft:`3px solid ${h.level==="high"?"#dc2626":h.level==="med"?"#f59e0b":"#a1a1aa"}`,paddingTop:2,paddingBottom:2}}><div style={{fontWeight:700,color:h.level==="high"?"#dc2626":"#78350f"}}>{h.level==="high"?"🔴":h.level==="med"?"🟡":"⚪"} {h.cat}：{h.warn}</div><div style={{fontSize:10,color:"#7e4c5c",marginTop:2}}>匹配：「{h.matched}」</div></div>)}</div><div style={{fontSize:10,color:"#4a2838",padding:"6px 8px",background:"#fff",borderRadius:8,marginBottom:6}}>💡 建议：先理性评估 TA 说这些话的意图，不要急着为这些话找借口。</div></>}</div>;};

/* ═══ P1-#08 教练栏目首次介绍 ═══ */
const CoachIntroDialog=({onClose})=>{return <div style={{position:"fixed",inset:0,zIndex:400,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(0,0,0,.5)",backdropFilter:"blur(6px)"}}><div style={{width:"92%",maxWidth:360,background:"#fff",borderRadius:22,padding:"24px 20px",animation:"fadeUp .3s"}}><div style={{textAlign:"center",marginBottom:12}}><div style={{fontSize:36,marginBottom:4}}>🎭</div><div style={{fontSize:16,fontWeight:900,color:"#c9306b"}}>欢迎来到教练栏目</div><div style={{fontSize:10,color:"#8b5a78",marginTop:3}}>这里是你的恋爱演练场</div></div><div style={{fontSize:11,color:"#4a2838",lineHeight:2,marginBottom:12}}><div>🎯 <b>场景模拟</b> — 你说一句，AI 扮演 TA 回复</div><div>🛡️ <b>风险雷达</b> — 发消息前先扫一扫，避免踩雷</div><div>🎚️ <b>语气调节</b> — 把你想说的话调成不同甜度</div><div>🎯 <b>连续技</b> — 设计一连几条的连贯消息</div></div><div style={{fontSize:11,color:"#c9306b",padding:"10px 12px",borderRadius:10,background:"#fff5f7",marginBottom:14,textAlign:"center",fontWeight:600}}>💡 核心玩法：从"怕说错"到"敢说对"</div><button className="tap" onClick={()=>{try{window.storage.set("sakura-coach-intro-v1","seen");}catch{}onClose();}} style={{width:"100%",padding:"12px",borderRadius:12,border:"none",background:"linear-gradient(135deg,#E84D8C,#F97316)",color:"#fff",fontSize:13,fontWeight:800,cursor:"pointer"}}>知道了，开始练习</button></div></div>;};

const FREE_LIMITS_TOTAL={think:true,deep:true,rp:true,chess:true,help:true};const FREE_TRIAL_KEYS={flash:true};const FREE_TRIAL_DAYS=3;const getFirstUseDate=async()=>{try{const r=await window.storage.get("sakura-first-use");if(r?.value)return r.value;const today=new Date().toDateString();await window.storage.set("sakura-first-use",today);return today;}catch{return new Date().toDateString();}};const isTrialExpired=async()=>{try{const r=await window.storage.get("sakura-first-use");if(!r?.value)return false;const first=new Date(r.value);const now=new Date();const diffDays=Math.floor((now-first)/86400000);return diffDays>=FREE_TRIAL_DAYS;}catch{return false;}};const useGate=(vip,key,st,setShowPay)=>{const countKey="sakura-use-"+key;const isTotal=FREE_LIMITS_TOTAL[key];const isTrial=FREE_TRIAL_KEYS[key];const[used,setUsed]=useState(0);const[trialExpired,setTrialExpired]=useState(false);useEffect(()=>{(async()=>{await getFirstUseDate();if(isTrial){const exp=await isTrialExpired();setTrialExpired(exp);try{globalThis.__sakuraTrialExpired=exp;}catch{}}try{const r=await window.storage.get(countKey);const d=r?.value?JSON.parse(r.value):{count:0,date:""};if(isTotal){setUsed(d.count||0);}else{const today=new Date().toDateString();if(d.date!==today)setUsed(0);else setUsed(d.count);}}catch{}})();},[]);const check=()=>{if(vip)return true;if(isTrial&&(trialExpired||globalThis.__sakuraTrialExpired)){setShowPay(true);return false;}const limit=FREE_LIMITS[key]||3;if(used>=limit){setShowPay(true);return false;}const next=used+1;setUsed(next);try{const payload=isTotal?{count:next}:{count:next,date:new Date().toDateString()};window.storage.set(countKey,JSON.stringify(payload));}catch{}return true;};const refund=()=>{if(vip)return;const next=Math.max(0,used-1);setUsed(next);try{const payload=isTotal?{count:next}:{count:next,date:new Date().toDateString()};window.storage.set(countKey,JSON.stringify(payload));}catch{}};const remaining=vip?999:(isTrial&&trialExpired)?0:Math.max(0,(FREE_LIMITS[key]||3)-used);return{check,remaining,refund,trialExpired:isTrial&&trialExpired};};
const Btn=({children,primary,color,disabled,onClick,s})=><button className="tap" onClick={disabled?undefined:onClick} style={{width:"100%",padding:"13px",borderRadius:14,fontSize:14,fontWeight:700,cursor:disabled?"default":"pointer",border:"none",background:disabled?C.bg3:primary?`linear-gradient(135deg,${color||C.pink},${(color||C.pink)}cc)`:C.bg,color:disabled?C.t3:primary?"#fff":C.t2,boxShadow:primary&&!disabled?`0 4px 20px ${(color||C.pink)}25`:"none",transition:"all .2s",...s}}>{children}</button>;
const Cd=({children,onClick,s})=><div className={onClick?"tap glass-card":"glass-card"} onClick={onClick} style={{padding:"14px 16px",cursor:onClick?"pointer":"default",transition:"all .18s",...s}}>{children}</div>;
const CB=({text,st})=>{const[c,setC]=useState(false);return <button className="tap2" onClick={e=>{e.stopPropagation();navigator.clipboard?.writeText(text);setC(true);st?.("已复制 🌸");setTimeout(()=>setC(false),1200)}} style={{padding:"5px 12px",borderRadius:10,fontSize:10,fontWeight:600,background:c?`${C.safe}12`:C.pinkBg,border:`1px solid ${c?C.safe+"30":C.sakura}`,color:c?C.safe:C.pink,cursor:"pointer",flexShrink:0}}>{c?"✓已复制":"📋复制"}</button>;};
const Pill=({children,active,color,onClick})=><button className="tap2" onClick={onClick} style={{padding:"5px 13px",borderRadius:20,fontSize:11,fontWeight:active?700:500,border:`1.5px solid ${active?(color||C.pink)+"40":"transparent"}`,background:active?`${color||C.pink}12`:"transparent",color:active?(color||C.pink):C.t3,cursor:"pointer",whiteSpace:"nowrap"}}>{children}</button>;
const Badge=({color,children})=><span style={{fontSize:10,padding:"3px 10px",borderRadius:10,background:`${color}12`,color,fontWeight:600,border:`1px solid ${color}20`}}>{children}</span>;
const EB=({l,v,c})=><div style={{display:"flex",alignItems:"center",gap:6,marginBottom:4}}><span style={{fontSize:10,color:C.t3,width:34}}>{l}</span><div style={{flex:1,height:5,borderRadius:3,background:`${c}15`,overflow:"hidden"}}><div style={{width:`${v}%`,height:"100%",borderRadius:3,background:`linear-gradient(90deg,${c}88,${c})`,transition:"width 1s"}}/></div><span style={{fontSize:10,fontWeight:600,color:c,width:22,textAlign:"right"}}>{v}</span></div>;
const SubHeader=({onBack,title})=><div style={{padding:"14px 16px",display:"flex",alignItems:"center",gap:10,background:C.glass,backdropFilter:"blur(20px)",position:"sticky",top:0,zIndex:50,borderBottom:`1px solid ${C.bd}`}}><button className="tap2" onClick={onBack} style={{background:C.pinkBg,border:"none",borderRadius:10,width:32,height:32,color:C.pink,fontSize:14,cursor:"pointer"}}>←</button><span style={{fontSize:15,fontWeight:700}}>{title}</span></div>;
const DkCd=({children,s})=><div className="glass-card" style={{background:"rgba(30,20,28,.92)",border:"1px solid rgba(139,90,120,.2)",color:"#e8d5df",padding:"14px 16px",...s}}>{children}</div>;
const ChkItem=({text,checked,onToggle,color,prefix,st})=><div className="tap2" onClick={onToggle} style={{display:"flex",alignItems:"flex-start",gap:8,padding:"7px 10px",marginBottom:3,borderRadius:8,background:checked?`${color||C.peri}08`:"transparent",border:`1px solid ${checked?(color||C.peri)+"25":"transparent"}`,cursor:"pointer",transition:"all .15s"}}><div style={{width:16,height:16,borderRadius:4,border:`1.5px solid ${checked?(color||C.peri):C.bd}`,background:checked?`${color||C.peri}15`:"transparent",display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0,marginTop:1,fontSize:9,color:color||C.peri}}>{checked?"✓":""}</div><div style={{flex:1,fontSize:11,lineHeight:1.6,color:checked?C.t1:C.t2}}>{prefix&&<span style={{marginRight:4}}>{prefix}</span>}{text}</div>{checked&&st&&<button className="tap2" onClick={e=>{e.stopPropagation();navigator.clipboard?.writeText(text);st("已复制");}} style={{padding:"2px 6px",borderRadius:4,background:`${color||C.peri}10`,border:"none",color:color||C.peri,fontSize:8,cursor:"pointer",flexShrink:0}}>📋</button>}</div>;
const UniSelect=({options,selected,onSelect,multi,custom,color,label,cols})=>{const[customVal,setCustomVal]=useState("");const c2=color||C.pink;const isSelected=id=>multi?selected?.includes(id):selected===id;const toggle=id=>{if(multi){const cur=selected||[];onSelect(cur.includes(id)?cur.filter(x=>x!==id):[...cur,id]);}else onSelect(id);};return <div><div style={{display:"flex",flexWrap:"wrap",gap:6}}>{options.map(o=><button key={o.id||o} className="tap2" onClick={()=>toggle(o.id||o)} style={{padding:"6px 14px",borderRadius:12,fontSize:11,fontWeight:isSelected(o.id||o)?700:500,border:`1.5px solid ${isSelected(o.id||o)?c2+"50":"transparent"}`,background:isSelected(o.id||o)?`${c2}12`:"transparent",color:isSelected(o.id||o)?c2:C.t3,cursor:"pointer"}}>{o.icon?o.icon+" ":""}{o.l||o.label||o}</button>)}</div>{custom&&<div style={{display:"flex",gap:6,marginTop:8}}><input value={customVal} onChange={e=>setCustomVal(e.target.value)} placeholder="自定义..." style={{flex:1,padding:"7px 12px",borderRadius:10,border:`1px solid ${C.bd}`,fontSize:11,background:C.white,outline:"none"}} onKeyDown={e=>{if(e.key==="Enter"&&customVal.trim()){toggle(customVal.trim());setCustomVal("");}}} /><button className="tap2" onClick={()=>{if(customVal.trim()){toggle(customVal.trim());setCustomVal("");}}}style={{padding:"6px 12px",borderRadius:10,background:`${c2}12`,border:`1px solid ${c2}30`,color:c2,fontSize:11,fontWeight:600,cursor:"pointer"}}>+添加</button></div>}</div>;};
const InlineTrans=({text,auto})=>{if(!text?.trim())return null;const local=KB_TRANS.find(k=>text.includes(k.input));const top=local?local.subtexts[0]:null;const all=local?local.subtexts:[];return <div style={{padding:"4px 10px",background:`${C.rose}06`,borderRadius:8,marginBottom:6,display:"flex",alignItems:"center",gap:6,fontSize:10,lineHeight:1.5}}><span style={{color:C.rose,fontWeight:600,flexShrink:0}}>🔮</span>{top?<div style={{flex:1}}><span style={{color:C.t2}}>真实含义：<span style={{color:C.rose,fontWeight:600}}>{top.t}</span> <span style={{color:C.t3}}>({top.pct}%{top.tag})</span></span>{auto&&all.length>1&&<div style={{marginTop:3,display:"flex",gap:4,flexWrap:"wrap"}}>{all.slice(1).map((s,i)=><span key={i} style={{fontSize:9,padding:"1px 6px",borderRadius:4,background:`${C.rose}08`,color:C.t3}}>{s.t}({s.pct}%)</span>)}</div>}</div>:<span style={{color:C.t3}}>输入更多内容获取语意分析</span>}</div>;};
const InlineFeel=({text,auto})=>{if(!text?.trim())return null;const len=text.length;const score=len>15?-2:len>8?1:3;const hasQ=text.includes("？")||text.includes("?");const hasExcl=text.includes("！")||text.includes("!");const impact=hasQ?"开放提问+好感":hasExcl?(len>15?"强语气，注意":"积极回应"):(score>0?"平稳正向":"需要润色");return <div style={{padding:"4px 10px",background:`${C.violet}06`,borderRadius:8,marginBottom:6,display:"flex",alignItems:"center",gap:6,fontSize:10,lineHeight:1.5}}><span style={{color:C.violet,fontWeight:600,flexShrink:0}}>💚</span><span style={{color:C.t2}}>TA感受：<span style={{color:score>0?C.safe:C.warn,fontWeight:600}}>{score>0?"好感+":"注意⚡"}</span> <span style={{color:C.t3}}>· {len>20?"消息偏长，建议精简":"长度OK"}{auto&&` · 影响：${impact}`}</span></span></div>;};
const UniInputBar=({value,onChange,onSend,onVoice,onAttach,onExpand,placeholder,autoFocus,st,transOn,setTransOn,feelOn,setFeelOn,vault,onPasteVault,showToolbar})=>{const ref=useCallback(n=>{if(n&&autoFocus)setTimeout(()=>n.focus(),100);},[autoFocus]);const[showVault,setShowVault]=useState(false);return <div style={{borderRadius:16,border:`1px solid ${C.bd}`,background:C.white,overflow:"hidden"}}><div style={{display:"flex",alignItems:"flex-end",gap:4,padding:"8px 10px"}}><textarea ref={ref} value={value} onChange={e=>onChange(e.target.value)} placeholder={placeholder||"输入消息..."} rows={1} style={{flex:1,border:"none",outline:"none",fontSize:"var(–fs,14px)",fontFamily:"inherit",resize:"none",background:"transparent",lineHeight:1.5,maxHeight:100,minHeight:24}} onKeyDown={e=>{if(e.key==="Enter"&&!e.shiftKey){e.preventDefault();onSend?.();}}} /><div style={{display:"flex",gap:2,flexShrink:0}}>{onAttach&&<button className="tap2" onClick={onAttach} style={{width:28,height:28,borderRadius:8,background:C.bg,border:"none",fontSize:13,cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center"}}>📎</button>}{onVoice&&<button className="tap2" onClick={onVoice} style={{width:28,height:28,borderRadius:8,background:C.bg,border:"none",fontSize:13,cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center"}}>🎤</button>}{onExpand&&<button className="tap2" onClick={onExpand} style={{width:28,height:28,borderRadius:8,background:C.bg,border:"none",fontSize:13,cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center"}}>⤢</button>}{onSend&&<button className="tap" onClick={onSend} style={{padding:"5px 14px",borderRadius:10,background:`linear-gradient(135deg,${C.pink},${C.pinkD})`,border:"none",color:"#fff",fontSize:12,fontWeight:700,cursor:"pointer"}}>发送</button>}</div></div>{showToolbar&&<div style={{display:"flex",gap:8,padding:"4px 10px 6px",borderTop:`1px solid ${C.bdL}`,alignItems:"center",flexWrap:"wrap"}}>{setTransOn&&<button className="tap2" onClick={()=>setTransOn(!transOn)} style={{padding:"3px 10px",borderRadius:8,fontSize:10,fontWeight:600,background:transOn?`${C.rose}12`:"transparent",color:transOn?C.rose:C.t3,border:`1px solid ${transOn?C.rose+"30":"transparent"}`,cursor:"pointer"}}>🔄翻译{transOn?"ON":"OFF"}</button>}{setFeelOn&&<button className="tap2" onClick={()=>setFeelOn(!feelOn)} style={{padding:"3px 10px",borderRadius:8,fontSize:10,fontWeight:600,background:feelOn?`${C.violet}12`:"transparent",color:feelOn?C.violet:C.t3,border:`1px solid ${feelOn?C.violet+"30":"transparent"}`,cursor:"pointer"}}>💭感受{feelOn?"ON":"OFF"}</button>}{vault&&<button className="tap2" onClick={()=>setShowVault(!showVault)} style={{padding:"3px 10px",borderRadius:8,fontSize:10,fontWeight:600,background:showVault?`${C.gold}12`:"transparent",color:showVault?C.gold:C.t3,border:`1px solid ${showVault?C.gold+"30":"transparent"}`,cursor:"pointer"}}>💾弹药库({vault.length})</button>}</div>}{showVault&&vault&&<div style={{padding:"4px 10px 8px",maxHeight:120,overflowY:"auto"}}>{vault.slice(0,8).map((v,i)=><div key={i} className="tap2" onClick={()=>{onPasteVault?.(v.text);setShowVault(false);st?.("已粘贴");}} style={{padding:"4px 8px",marginBottom:3,borderRadius:6,fontSize:10,color:C.t2,background:C.bg,cursor:"pointer",whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"}}>{v.text}</div>)}</div>}{transOn&&value&&<InlineTrans text={value} auto/>}{feelOn&&value&&<InlineFeel text={value} auto/>}</div>;};
const DailyPush=({st})=>{const[card,setCard]=useState(null);const[dismissed,setDismissed]=useState(false);useEffect(()=>{const today=new Date().toDateString();const h=Math.abs([...today].reduce((a,c)=>a+c.charCodeAt(0),0));const idx=h%DAILY_PUSH_POOL.length;setCard(DAILY_PUSH_POOL[idx]);(async()=>{try{const r=await window.storage.get("sakura-daily-dismissed");if(r?.value===today)setDismissed(true);}catch{}})();},[]);const dismiss=()=>{setDismissed(true);try{window.storage.set("sakura-daily-dismissed",new Date().toDateString());}catch{}};if(dismissed||!card)return null;const bg=card.type==="challenge"?`${C.peri}08`:card.type==="insight"?`${C.teal}08`:`${C.pink}08`;const bc=card.type==="challenge"?C.peri:card.type==="insight"?C.teal:C.pink;return <div className="glass-card" style={{margin:"8px 14px",padding:"12px 14px",position:"relative",borderLeft:`4px solid ${bc}`,background:bg}}><button onClick={dismiss} style={{position:"absolute",top:6,right:10,background:"none",border:"none",fontSize:12,color:C.t3,cursor:"pointer"}}>✕</button><div style={{display:"flex",alignItems:"center",gap:6,marginBottom:6}}><span style={{fontSize:16}}>{card.icon}</span><span style={{fontSize:12,fontWeight:700,color:bc}}>{card.title}</span><span style={{fontSize:9,padding:"2px 6px",borderRadius:6,background:`${bc}15`,color:bc}}>{card.type==="challenge"?"挑战":"知识"}</span></div><div style={{fontSize:11,color:C.t1,lineHeight:1.7,marginBottom:6}}>{card.body}</div><div style={{fontSize:9,color:C.t3}}>📚 {card.ref}</div></div>;};
const useTheoryEngine=(scenario,intents)=>{const auto=useMemo(()=>{let key=scenario||"daily";if(intents?.includes("repair")||intents?.includes("sorry"))key="conflict";if(intents?.includes("advance")||intents?.includes("confess"))key="advance";const mods=THEORY_AUTO_MAP[key]||THEORY_AUTO_MAP.daily;return mods.map(id=>DEEP_MODS.find(m=>m.id===id)).filter(Boolean);},[scenario,intents]);return{autoModules:auto,allModules:DEEP_MODS};};
const RealtimeCopilot=({onInsight,st})=>{const[state,setState]=useState("idle");const[transcript,setTranscript]=useState("");const[insight,setInsight]=useState(null);const srRef=useCallback(()=>{const SR=window.SpeechRecognition||window.webkitSpeechRecognition;if(!SR)return null;return new SR();},[]);const start=()=>{const sr=srRef();if(!sr){st?.("浏览器不支持语音");return;}sr.lang="zh-CN";sr.continuous=true;sr.interimResults=true;setState("listening");sr.onresult=e=>{let t="";for(let i=0;i<e.results.length;i++)t+=e.results[i][0].transcript;setTranscript(t);setState("processing");const local=KB_TRANS.find(k=>t.includes(k.input));if(local){const top=local.subtexts[0];setInsight({text:t,meaning:top.t,pct:top.pct,tag:top.tag,risk:top.pct>50?"注意":"安全"});setState("ready");onInsight?.({text:t,meaning:top.t});}else{setInsight({text:t,meaning:"语意分析中...",pct:0,tag:"",risk:"安全"});setState("ready");}};sr.onerror=()=>{setState("idle");st?.("监听中断");};sr.onend=()=>setState("idle");sr.start();window.__copilotSR=sr;};const stop=()=>{try{window.__copilotSR?.stop();}catch{}setState("idle");setInsight(null);};const stColor=state==="listening"?C.peri:state==="processing"?C.gold:state==="ready"?C.teal:C.t3;return <div className="glass-card" style={{margin:"8px 14px",padding:"10px 14px"}}><div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:8}}><div style={{display:"flex",alignItems:"center",gap:6}}><span style={{width:8,height:8,borderRadius:4,background:stColor,animation:state==="listening"?"pulse 1.5s infinite":"none"}}/><span style={{fontSize:12,fontWeight:700,color:C.t1}}>🎧 实时Copilot</span><span style={{fontSize:9,color:stColor,fontWeight:600}}>{COPILOT_STATES[state]}</span></div><button className="tap2" onClick={state==="idle"?start:stop} style={{padding:"4px 14px",borderRadius:10,fontSize:10,fontWeight:700,background:state==="idle"?`${C.peri}12`:`${C.danger}12`,color:state==="idle"?C.peri:C.danger,border:`1px solid ${state==="idle"?C.peri+"30":C.danger+"30"}`,cursor:"pointer"}}>{state==="idle"?"开始监听":"停止"}</button></div>{transcript&&<div style={{fontSize:10,color:C.t3,padding:"4px 8px",background:C.bg,borderRadius:8,marginBottom:6}}>🗣️ {transcript}</div>}{insight&&<div style={{padding:"6px 10px",borderRadius:10,background:`${C.teal}08`,border:`1px solid ${C.teal}15`}}><div style={{fontSize:11,color:C.t1,fontWeight:600,marginBottom:3}}>🔮 {insight.meaning}</div><div style={{display:"flex",gap:8,fontSize:9}}><span style={{color:C.rose}}>可能性{insight.pct}%</span>{insight.tag&&<span style={{padding:"1px 6px",borderRadius:4,background:`${C.peri}12`,color:C.peri}}>{insight.tag}</span>}<span style={{color:insight.risk==="注意"?C.warn:C.safe}}>⚡{insight.risk}</span></div></div>}</div>;};
const BreathingMic=({onText,onImg,listening,st,id,taPhoto,matched})=>{const fId=id||"bm";const[rec,setRec]=useState(false);const[photo,setPhoto]=useState(taPhoto||null);const[srRef,setSrRef]=useState(null);const[micOn,setMicOn]=useState(true);const isNight=new Date().getHours()>=20||new Date().getHours()<6;const hp="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z";const mode=rec?"recording":matched?"dualSync":"idle";const anim={recording:"heartRecord .6s infinite",dualSync:"dualSync 1.2s infinite",idle:micOn?(isNight?"lipBreathSexy 2.5s infinite":"syncBreath 2s infinite"):(isNight?"lipSexy .9s infinite":"lipCute .8s infinite")}[mode];const startRec=()=>{const SR=window.SpeechRecognition||window.webkitSpeechRecognition;if(!SR){st?.("浏览器不支持语音");return;}const r=new SR();r.lang="zh-CN";r.continuous=false;r.interimResults=false;r.onresult=e=>{onText?.(e.results[0][0].transcript);st?.("🎤 已识别");setRec(false);setSrRef(null);};r.onend=()=>{setRec(false);setSrRef(null);};r.onerror=()=>{st?.("语音失败");setRec(false);setSrRef(null);};r.start();setRec(true);setSrRef(r);};const stopRec=()=>{if(srRef){try{srRef.stop();}catch{}}setRec(false);setSrRef(null);};const onHeartDown=e=>{e.preventDefault();if(rec)return;if(micOn){startRec();}else{document.getElementById(fId+"Img")?.click();}};const onHeartUp=e=>{e.preventDefault();if(rec)stopRec();};return <div style={{display:"flex",alignItems:"center",gap:6,position:"relative"}}><input type="file" accept="image/*" id={fId+"Img"} style={{display:"none"}} onChange={e=>{const f=e.target.files?.[0];if(!f)return;const r=new FileReader();r.onload=()=>{setPhoto(r.result);st?.("💕 照片已放入心形");};r.readAsDataURL(f);e.target.value="";}}/><div onPointerDown={onHeartDown} onPointerUp={onHeartUp} onPointerLeave={e=>{if(rec)stopRec();}}onClick={e=>{e.preventDefault();if(!micOn&&!rec){document.getElementById(fId+"Img")?.click();}}}style={{width:52,height:52,cursor:"pointer",position:"relative",display:"flex",alignItems:"center",justifyContent:"center",animation:anim,userSelect:"none",touchAction:"manipulation"}}><svg viewBox="0 0 24 24" width={48} height={48} style={{filter:rec?`drop-shadow(0 0 10px ${C.peri}90)`:matched?`drop-shadow(0 0 14px ${C.pink}70)`:`drop-shadow(0 0 6px ${C.pink}40)`}}><defs><clipPath id={fId+"clip"}><path d={hp}/></clipPath><linearGradient id={fId+"gI"} x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stopColor={C.sakuraL}/><stop offset="100%" stopColor={C.pink}/></linearGradient><radialGradient id={fId+"gR"} cx="50%" cy="50%"><stop offset="0%" stopColor={C.peri}/><stop offset="80%" stopColor={C.pink}/></radialGradient><linearGradient id={fId+"gD"} x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stopColor={C.pink}/><stop offset="50%" stopColor={C.peri}/><stop offset="100%" stopColor={C.pink}/></linearGradient></defs>{photo?<><image href={photo} x="0" y="1" width="24" height="22" clipPath={`url(#${fId}clip)`} preserveAspectRatio="xMidYMid slice"/><path d={hp} fill="none" stroke={rec?C.peri:matched?"url(#"+fId+"gD)":C.pink} strokeWidth={rec?"1.5":"1"} opacity=".85"/></>:<path d={hp} fill={mode==="recording"?`url(#${fId}gR)`:mode==="dualSync"?`url(#${fId}gD)`:`url(#${fId}gI)`}/>}</svg>{rec&&<span style={{position:"absolute",top:-2,right:-2,width:10,height:10,borderRadius:5,background:C.danger,animation:"pulse 1s infinite"}}/>}</div><button className="tap2" onClick={()=>{if(rec){stopRec();st?.("🎤 已停止");}else{setMicOn(!micOn);st?.(micOn?"❤️ 点心放照片":"🎤 按住心录音");}}}style={{width:30,height:30,borderRadius:15,background:rec?`linear-gradient(135deg,${C.peri},${C.pink})`:micOn?`${C.pink}15`:`${C.pink}08`,border:`1.5px solid ${rec?C.peri:micOn?C.pink+"40":C.pink+"25"}`,cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",fontSize:micOn?13:11,color:rec?"#fff":C.pink,boxShadow:rec?`0 2px 12px ${C.peri}40`:"none",transition:"all .2s"}}>{rec?"🎤":micOn?"🎤":"❤️"}</button>{matched&&<span style={{fontSize:10,color:C.peri,fontWeight:700,animation:"dualSync 1.2s infinite",marginLeft:2}}>💕</span>}</div>;};
const InputToolbar=({vault,onPaste,st,transOn,setTransOn,feelOn,setFeelOn})=>{const[showVault,setShowVault]=useState(false);return <div style={{marginTop:4}}><div style={{display:"flex",gap:4,flexWrap:"wrap"}}>{transOn!==undefined&&<button className="tap2" onClick={()=>setTransOn?.(!transOn)} style={{padding:"3px 8px",borderRadius:6,fontSize:9,background:transOn?`${C.rose}12`:"transparent",border:`1px solid ${transOn?C.rose+"30":C.bd}`,color:transOn?C.rose:C.t3,cursor:"pointer"}}>{transOn?"🔄翻译ON":"🔄翻译"}</button>}{feelOn!==undefined&&<button className="tap2" onClick={()=>setFeelOn?.(!feelOn)} style={{padding:"3px 8px",borderRadius:6,fontSize:9,background:feelOn?`${C.violet}12`:"transparent",border:`1px solid ${feelOn?C.violet+"30":C.bd}`,color:feelOn?C.violet:C.t3,cursor:"pointer"}}>{feelOn?"💭感受ON":"💭感受"}</button>}<button className="tap2" onClick={()=>setShowVault(!showVault)} style={{padding:"3px 8px",borderRadius:6,fontSize:9,background:showVault?`${C.gold}12`:"transparent",border:`1px solid ${showVault?C.gold+"30":C.bd}`,color:showVault?C.gold:C.t3,cursor:"pointer"}}>💾弹药库{vault?.length?`(${vault.length})`:""}</button></div>{showVault&&vault?.length>0&&<div style={{marginTop:4,maxHeight:120,overflowY:"auto",borderRadius:8,border:`1px solid ${C.bd}`,background:C.bg,padding:4}}>{vault.slice(0,8).map((f,i)=><div key={f.id} className="tap2" onClick={()=>{onPaste?.(f.text);st?.("已粘贴 💾");setShowVault(false);}} style={{padding:"5px 8px",marginBottom:2,borderRadius:6,fontSize:11,color:C.t1,cursor:"pointer",background:"transparent",lineHeight:1.5,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{f.tag&&<span style={{color:C.gold,marginRight:4}}>[{f.tag}]</span>}{f.text}</div>)}</div>}</div>;};
const CustomAdd=({placeholder,onAdd,color})=>{const[v,setV]=useState("");return <div style={{display:"flex",gap:4,marginTop:4}}><input value={v} onChange={e=>setV(e.target.value)} onKeyDown={e=>{if(e.key==="Enter"&&v.trim()){onAdd(v.trim());setV("");}}} placeholder={placeholder||"自定义..."} style={{flex:1,padding:"5px 10px",borderRadius:8,border:`1px solid ${C.bd}`,background:C.bg,fontSize:11,color:C.t1,outline:"none",fontFamily:font}}/><button className="tap2" onClick={()=>{if(v.trim()){onAdd(v.trim());setV("");}}}style={{padding:"5px 12px",borderRadius:8,background:`${color||C.peri}10`,border:`1px solid ${(color||C.peri)}30`,color:color||C.peri,fontSize:10,fontWeight:700,cursor:"pointer"}}>添加</button></div>;};/* ═════════════ P1: 秒回 ═══════════════════ */
function FlashTab({stageId,personaId,setPersonaId,profile,st,addVault,vault,vip,setShowPay,learn,onNavigateGame}){const[inp,setInp]=useState("");const[mode,setMode]=useState("quick");const[ld,setLd]=useState(false);const[result,setResult]=useState(null);const[err,setErr]=useState(null);const[polMode,setPolMode]=useState(true);const[polInp,setPolInp]=useState("");const[polLd,setPolLd]=useState(false);const[polRes,setPolRes]=useState(null);const[imgPreview,setImgPreview]=useState(null);const[imgBase64,setImgBase64]=useState(null);const[isListening,setIsListening]=useState(false);const[transOn,setTransOn]=useState(true);const[feelOn,setFeelOn]=useState(false);const[showCopilot,setShowCopilot]=useState(false);const[lastChoiceId,setLastChoiceId]=useState(null);const flashGate=useGate(vip,"flash",st,setShowPay);const thinkGate=useGate(vip,"think",st,setShowPay);const ps=PERSONAS.find(p=>p.id===personaId);const mc=mode==="quick"?C.pink:C.peri;const handleImg=(e)=>{const f=e.target.files?.[0];if(!f)return;const r=new FileReader();r.onload=()=>{setImgPreview(r.result);setImgBase64(r.result.split(",")[1]);};r.readAsDataURL(f);};const clearImg=()=>{setImgPreview(null);setImgBase64(null);};const startVoice=()=>{const SR=window.SpeechRecognition||window.webkitSpeechRecognition;if(!SR){st("浏览器不支持语音");return;}const r=new SR();r.lang="zh-CN";r.continuous=false;r.interimResults=false;r.onstart=()=>setIsListening(true);r.onend=()=>setIsListening(false);r.onresult=(e)=>{const t=e.results[0][0].transcript;setInp(p=>p?p+t:t);};r.onerror=()=>setIsListening(false);r.start();};const generate=async()=>{const text=inp.trim();if(!text&&!imgBase64)return;if(ld)return;if(mode==="quick"&&!flashGate.check())return;if(mode==="think"&&!thinkGate.check())return;setLd(true);setResult(null);setErr(null);const sys=buildSys(stageId,personaId,profile,mode==="quick"?`你是微信聊天高手。核心原则：1.回复必须像真人微信消息，不超过20字，口语化 2.4条回复要差异明显：安全保底、温柔走心、幽默化解、主动推进 3.绝对不能出现书面语、鸡汤、说教 4.如果档案有昵称/专属梗，自然融入 5.风险判断：会不会让TA不舒服、会不会暴露需求感。每条附带风险等级(low/med/high)和推荐微信表情包搜索关键词(2-3字)。返回JSON：[{"text":"","tone":"风格2字","risk":"low","emoji":"表情包关键词"}]`:`你是恋爱策略师。展示完整推理过程。第一步：读懂TA——分析情绪状态、真实意图、TA期望你怎么回应。第二步：识别风险——哪些回法会踩雷。第三步：制定策略——给4条不同策略的回复，每条说清楚「为什么这么说」。回复必须像真人微信，不超过25字。返回JSON：{"analysis":{"emotion":"一句话情绪判断","subtext":"TA没说出口的话","expectation":"TA希望你做什么","risk":"千万别这么回+原因"},"replies":[{"text":"","tone":"","reason":"策略原因","risk":"low/med/high","emoji":"表情包关键词"}]}`);const userMsg=text?`TA说：「${text}」`:"请分析图片中的聊天内容并给出回复建议";let msgContent;if(imgBase64){msgContent=[{type:"image",source:{type:"base64",media_type:"image/jpeg",data:imgBase64}},{type:"text",text:userMsg}];}else{msgContent=userMsg;}try{const c=new AbortController();const t=setTimeout(()=>c.abort(),45000);const res=await fetch(API_URL,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:API_MODEL,max_tokens:1000,system:sys,messages:[{role:"user",content:msgContent}]}),signal:c.signal});clearTimeout(t);const d=await res.json();if(d.error){setErr(d.error.message);(mode==="quick"?flashGate:thinkGate).refund();setLd(false);return;}const r=d.content?.[0]?.text||"";const p=pJ(r);if(mode==="quick"){{const raw=p||MOCK_QUICK(text||"",personaId);const ranked=learn?learn.smartRerank(raw,text,profile?.nickname,personaId):raw;setResult({type:"quick",data:ranked});}}else{setResult({type:"think",data:p||MOCK_THINK(text||"")});}}catch(e){const t=inp.trim();const h=t.split("").reduce((a,c)=>a+c.charCodeAt(0),0);const pool={safe:["嗯嗯，我在呢","好的～","收到啦","嗯嗯","了解了"],warm:["怎么了呀？跟我说说","你还好吗？","想听你说","心疼你","辛苦了宝"],humor:["哈哈好的～","笑死我了","你可真行啊","绝了","服了你了哈哈"],push:["出来走走？","周末有空吗","想你了","一起吃饭？","最近怎么样"]};const tones=["安全","温柔","幽默","推进"];const risks=["low","low","low","med"];const emojis=["乖巧","抱抱","笑哭","散步"];if(mode==="quick"){const replies=tones.map((tone,i)=>({text:pool[["safe","warm","humor","push"][i]][h%5],tone,risk:risks[i],emoji:emojis[i]}));setResult({type:"quick",data:replies});}else{setResult({type:"think",data:{analysis:{emotion:t.includes("不")||t.includes("没")?"可能有些不满或失落":"情绪相对平稳",subtext:t.length>10?"TA说了很多，可能在试探你的态度":"简短回复，需要你主动延伸",expectation:"希望被认真对待和回应",risk:"不要敷衍回复或已读不回"},replies:[{text:"嗯嗯，我在认真听",tone:"安全",reason:"先给安全感",risk:"low",emoji:"抱抱"},{text:"你说的我都记在心里了",tone:"温柔",reason:"表达重视",risk:"low",emoji:"比心"},{text:"哈哈你这么一说我倒想起来",tone:"轻松",reason:"用幽默接住降低压力",risk:"low",emoji:"歪头"},{text:"要不我们出来聊？打字说不清",tone:"推进",reason:"推进到线下",risk:"med",emoji:"咖啡"}]}});}}setLd(false);};const doPolish=()=>{if(!polInp.trim()||polLd)return;setPolLd(true);setPolRes(null);const t=polInp.trim();const len=t.length;const h=t.split("").reduce((a,c)=>a+c.charCodeAt(0),0);const risk=len>20?55+h%30:len>10?30+h%25:15+h%20;const gentle=t.replace(/!/g,"~").replace(/？/g,"呀？")+"呢~";const humor="哈哈 "+t.replace(/？/g,"呀~");const low=len>15?t.slice(0,12)+"...":t;const best=t.length>5?t.slice(0,Math.floor(t.length*.7))+"，你觉得呢？":t+"~";setTimeout(()=>{setPolRes({riskScore:risk,riskNote:risk>=50?"语气偏重建议缓和":risk>=30?"基本安全可优化":"语气OK",rewrites:[{tone:"温柔版",text:gentle},{tone:"幽默版",text:humor},{tone:"低压版",text:low}],best:{text:best,why:"缩短长度+加开放问句，降低攻击性提升好感"}});setPolLd(false);},300);};const riskColor=r=>r==="high"?C.danger:r==="med"?C.warn:C.safe;const riskLabel=r=>r==="high"?"⚠️高风险":r==="med"?"🟡注意":"✅安全";return <div style={{paddingBottom:100,position:"relative",zIndex:1}}><div style={{textAlign:"center",padding:"18px 20px 8px",position:"relative"}}><div style={{position:"absolute",top:0,left:"50%",transform:"translateX(-50%)",width:300,height:180,background:`radial-gradient(circle,${C.sakura}10,transparent 70%)`,filter:"blur(60px)",pointerEvents:"none"}}/><div style={{fontSize:30,marginBottom:2,animation:"breathe 3s infinite"}}>🌸</div><h1 style={{fontSize:20,fontWeight:900,background:`linear-gradient(135deg,${C.pink},${C.gold})`,WebkitBackgroundClip:"text",WebkitTextFillColor:"transparent",letterSpacing:2}}>Sakura Ultimate</h1><p style={{fontSize:10,color:C.t3,letterSpacing:1,marginTop:2}}>输入TA的话 → AI秒出回复 → 复制走人</p></div><div style={{padding:"8px 14px 0"}}><div style={{borderRadius:20,background:C.white,border:`1.5px solid ${inp.trim()||imgBase64?C.sakura:C.sakuraL}`,boxShadow:inp.trim()||imgBase64?`0 4px 20px ${C.pink}10`:"none",transition:"all .3s",overflow:"hidden"}}>{imgPreview&&<div style={{padding:"8px 12px 0",position:"relative"}}><img src={imgPreview} style={{width:"100%",maxHeight:120,objectFit:"cover",borderRadius:10}}/><button onClick={clearImg} style={{position:"absolute",top:12,right:16,width:20,height:20,borderRadius:10,background:"rgba(0,0,0,.5)",border:"none",color:"#fff",fontSize:10,cursor:"pointer"}}>✕</button><div style={{fontSize:10,color:"#0369a1",padding:"4px 2px 0",lineHeight:1.5}}>💡 已识别图片 · 补充文字让 AI 更懂上下文，或直接点"秒回"分析图片</div></div>}<textarea value={inp} onChange={e=>setInp(e.target.value)} onKeyDown={e=>{if(e.key==="Enter"&&!e.shiftKey){e.preventDefault();generate();}}} placeholder={imgBase64?"补充说明（可选）...":"粘贴TA说的话...\n支持多条消息、截图、语音输入 💬"} style={{width:"100%",minHeight:imgBase64?40:80,padding:"14px 14px 4px",background:"transparent",border:"none",color:C.t1,fontSize:15,outline:"none",resize:"none",lineHeight:1.75,fontFamily:font}}/><div style={{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"6px 12px 10px",borderTop:`1px solid ${C.bdL}`}}><div style={{display:"flex",gap:4,alignItems:"center"}}><input type="file" accept="image/*" id="imgUp" style={{display:"none"}} onChange={handleImg}/><BreathingMic id="flash" listening={isListening} st={st} onText={t=>setInp(p=>p?p+t:t)}/>{inp&&<button className="tap2" onClick={()=>{setInp("");setResult(null);setErr(null);clearImg();}}style={{padding:"4px 10px",borderRadius:8,background:C.bg,border:`1px solid ${C.bdL}`,color:C.t3,fontSize:10,cursor:"pointer"}}>清空</button>}</div><div style={{display:"flex",gap:6,alignItems:"center"}}><div style={{position:"relative"}}><input type="file" accept="image/*" id="imgAlbum" style={{display:"none"}} onChange={handleImg}/><input type="file" accept="image/*" capture="environment" id="imgCamera" style={{display:"none"}} onChange={handleImg}/><button className="tap2" onClick={()=>{const m=document.getElementById("addMenu");if(m)m.style.display=m.style.display==="none"?"flex":"none";}}style={{width:32,height:32,borderRadius:16,background:imgBase64?`${C.pink}15`:C.bg,border:`1.5px solid ${imgBase64?C.pink+"30":C.bdL}`,fontSize:14,cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center"}}>＋</button><div id="addMenu" style={{display:"none",position:"absolute",bottom:38,right:0,flexDirection:"column",gap:4,padding:6,borderRadius:12,background:C.white,border:`1px solid ${C.bd}`,boxShadow:`0 4px 20px ${C.pink}15`,zIndex:10,minWidth:100}}><button className="tap2" onClick={()=>{document.getElementById("imgUp")?.click();document.getElementById("addMenu").style.display="none";}}style={{padding:"6px 10px",borderRadius:8,background:"transparent",border:"none",color:C.t1,fontSize:11,cursor:"pointer",textAlign:"left",whiteSpace:"nowrap"}}>🖼️ 截图分析</button><button className="tap2" onClick={()=>{document.getElementById("imgAlbum")?.click();document.getElementById("addMenu").style.display="none";}}style={{padding:"6px 10px",borderRadius:8,background:"transparent",border:"none",color:C.t1,fontSize:11,cursor:"pointer",textAlign:"left",whiteSpace:"nowrap"}}>📷 从相册选</button><button className="tap2" onClick={()=>{document.getElementById("imgCamera")?.click();document.getElementById("addMenu").style.display="none";}}style={{padding:"6px 10px",borderRadius:8,background:"transparent",border:"none",color:C.t1,fontSize:11,cursor:"pointer",textAlign:"left",whiteSpace:"nowrap"}}>📸 拍照</button></div></div><button className="tap" onClick={generate} disabled={(!inp.trim()&&!imgBase64)||ld} style={{padding:"8px 20px",borderRadius:14,border:"none",cursor:(inp.trim()||imgBase64)&&!ld?"pointer":"default",background:(inp.trim()||imgBase64)&&!ld?`linear-gradient(135deg,${mc},${mc}cc)`:C.sakuraL,color:(inp.trim()||imgBase64)&&!ld?"#fff":C.t3,fontSize:13,fontWeight:700,boxShadow:(inp.trim()||imgBase64)&&!ld?`0 4px 16px ${mc}30`:"none",display:"flex",alignItems:"center",gap:5,animation:(inp.trim()||imgBase64)&&!ld&&!result?"pulse 2.5s infinite":"none"}}>{ld?"⏳ 生成中...":<>{mode==="quick"?"⚡ 秒回":"✨ AI思考"}</>}</button></div></div></div></div><div style={{padding:"4px 14px"}}><InputToolbar vault={vault} onPaste={t=>setInp(t)} st={st} transOn={transOn} setTransOn={setTransOn} feelOn={feelOn} setFeelOn={setFeelOn}/></div>{transOn&&inp.trim()&&<div style={{padding:"0 14px"}}><InlineTrans text={inp}/></div>}{feelOn&&inp.trim()&&<div style={{padding:"0 14px"}}><InlineFeel text={inp}/></div>}<div style={{padding:"10px 14px 4px",display:"flex",gap:8}}>{learn&&learn.getInsight(profile?.nickname).length>0&&<div style={{padding:"4px 14px",display:"flex",gap:4,overflowX:"auto"}}>{learn.getInsight(profile?.nickname).slice(0,2).map((ins,i)=><span key={i} style={{fontSize:9,padding:"2px 8px",borderRadius:6,background:`${C.peri}08`,color:C.peri,whiteSpace:"nowrap"}}>{ins.icon} {ins.text}</span>)}</div>}{!vip&&<div style={{fontSize:9,color:C.t3,padding:"4px 0",width:"100%",textAlign:"center"}}>今日免费：秒回{flashGate.remaining}次 · AI思考{thinkGate.remaining}次{flashGate.remaining<=0?" · ":""}{flashGate.remaining<=0&&<button className="tap2" onClick={()=>setShowPay(true)} style={{color:C.pink,background:"none",border:"none",fontSize:9,fontWeight:700,cursor:"pointer",textDecoration:"underline"}}>升级Pro无限用</button>}</div>}</div><div style={{padding:"0 14px 4px",display:"flex",gap:8}}>{[{id:"quick",l:"⚡ 秒回",d:"4条回复 · 复制即走",c:C.pink},{id:"think",l:"✨ AI思考",d:"情绪分析 · 策略推理",c:C.peri}].map(m=><button key={m.id} className="tap2" onClick={()=>{setMode(m.id);if(result)setResult(null);}}style={{flex:1,padding:"9px 6px",borderRadius:14,background:mode===m.id?`${m.c}10`:C.white,border:`1.5px solid ${mode===m.id?m.c+"40":C.bdL}`,cursor:"pointer",textAlign:"center",boxShadow:mode===m.id?`0 2px 10px ${m.c}10`:"none"}}><div style={{fontSize:12,fontWeight:mode===m.id?800:500,color:mode===m.id?m.c:C.t2}}>{m.l}</div><div style={{fontSize:9,color:C.t3,marginTop:1}}>{m.d}</div></button>)}</div>{(()=>{if(typeof globalThis.__puaScanOff!=="undefined"&&globalThis.__puaScanOff)return null;const pua=inp.trim()?scanPUA(inp):null;return pua?<PuaAlert result={pua}/>:null;})()}{!inp.trim()&&<V25DailyRecommend stageId={stageId} onNavigateGame={onNavigateGame}/>}{!inp.trim()&&<V25EmojiPack onPick={(e)=>setInp(inp+e)}/>}{err&&<div style={{padding:"0 14px",animation:"fadeUp .3s"}}><Cd s={{background:`${C.danger}04`,textAlign:"center"}}><div style={{fontSize:24,marginBottom:4}}>😅</div><div style={{fontSize:12,fontWeight:700,color:C.danger}}>{err==="TIMEOUT"?"AI思考超时":"生成失败"}</div><Btn primary onClick={generate} s={{marginTop:8}}>🔄 重试</Btn></Cd></div>}{result?.type==="quick"&&<div style={{padding:"8px 14px",animation:"fadeUp .3s"}}><InlineTrans text={inp}/>{result.data.map((r,i)=><Cd key={i} s={{marginBottom:8,animation:`fadeUp .2s ease ${i*.06}s both`}}><div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:6}}><div style={{display:"flex",alignItems:"center",gap:6}}><>{r._recommended&&<span style={{fontSize:9,padding:"1px 6px",borderRadius:4,background:`${C.peri}15`,color:C.peri,fontWeight:700,marginRight:4}}>🧠 推荐</span>}<Badge color={ps?.c||C.pink}>{r.tone}</Badge></><span style={{fontSize:9,color:riskColor(r.risk)}}>{riskLabel(r.risk)}</span></div><div style={{display:"flex",gap:4}}><CB text={r.text} st={st}/><button className="tap2" onClick={e=>{e.stopPropagation();addVault?.(r.text,r.tone);if(learn){const cid=learn.trackChoice(inp,r.tone,personaId,profile?.nickname);setLastChoiceId(cid);}}}style={{padding:"5px 8px",borderRadius:10,fontSize:10,background:`${C.gold}10`,border:`1px solid ${C.gold}25`,color:C.gold,cursor:"pointer"}}>⭐</button></div></div><div style={{fontSize:14,lineHeight:1.8,color:C.t1}}><V25StickerText text={r.text} st={st}/></div>{r.emoji&&<div style={{fontSize:9,color:C.t3,marginTop:4}}>🔍 表情包搜索：{r.emoji}</div>}</Cd>)}<Btn onClick={generate} s={{background:C.bg,marginTop:4}}>🔄 不满意？再来一批</Btn></div>}{result?.type==="think"&&<div style={{padding:"8px 14px",animation:"fadeUp .3s"}}><InlineTrans text={inp}/>{result.data.analysis&&<Cd s={{marginBottom:12,background:`${C.peri}04`}}><div style={{fontSize:12,fontWeight:700,color:C.peri,marginBottom:8}}>✨ AI分析</div>{gameId==="ask_out"&&<><Cd s={{marginBottom:8,background:`${C.pink}06`}}><div style={{fontSize:13,fontWeight:700,color:C.pink,marginBottom:6}}>🎀 不卑微的主动约</div><div style={{fontSize:11,color:C.t3,lineHeight:1.6}}>{gameRes.principle}</div></Cd>{gameRes.approaches?.map((a,i)=><Cd key={i} s={{marginBottom:6,background:`${C.safe}06`}}><div style={{fontSize:11,fontWeight:700,color:C.safe,marginBottom:4}}>📍 {a.angle}</div><div style={{fontSize:12,color:C.t1,background:C.white,padding:"8px 10px",borderRadius:6,lineHeight:1.6,marginBottom:4}}>{a.say}</div><div style={{fontSize:10,color:C.t3}}>💡 {a.why}</div></Cd>)}<Cd s={{marginBottom:6,background:`${C.gold}06`}}><div style={{fontSize:10,color:C.t1,lineHeight:1.6}}>🎯 公式：{gameRes.formula}</div></Cd><Cd s={{marginBottom:6,background:`${C.danger}06`}}><div style={{fontSize:11,fontWeight:700,color:C.danger,marginBottom:4}}>🚫 这些话别说</div>{gameRes.dontDo?.map((d,i)=><div key={i} style={{fontSize:10,color:C.t2,marginTop:3}}>× {d}</div>)}</Cd>{gameRes.tip&&<Cd s={{background:`${C.bd}30`}}><div style={{fontSize:10,color:C.t3,lineHeight:1.6}}>💭 {gameRes.tip}</div></Cd>}</>}
{gameId==="heat_up"&&<><Cd s={{marginBottom:8,background:`${C.pink}06`}}><div style={{fontSize:13,fontWeight:700,color:C.pink,marginBottom:6}}>🔥 暧昧升温 3 档</div><div style={{fontSize:11,color:C.t3,lineHeight:1.6}}>{gameRes.principle}</div></Cd>{gameRes.signals?.map((s,i)=><Cd key={i} s={{marginBottom:6,background:`${C.safe}06`}}><div style={{fontSize:11,fontWeight:700,color:C.pink,marginBottom:4}}>{s.level}</div><div style={{fontSize:11,color:C.t1,marginBottom:4,lineHeight:1.6}}>{s.action}</div><div style={{fontSize:10,color:C.t3}}>💡 {s.why}</div></Cd>)}<Cd s={{marginBottom:6,background:`${C.gold}06`}}><div style={{fontSize:10,color:C.t1,lineHeight:1.6}}>⏱ 节奏：{gameRes.rhythm}</div></Cd><Cd s={{marginBottom:6,background:`${C.danger}06`}}><div style={{fontSize:11,fontWeight:700,color:C.danger,marginBottom:4}}>🚫 别这么做</div>{gameRes.dontDo?.map((d,i)=><div key={i} style={{fontSize:10,color:C.t2,marginTop:3}}>× {d}</div>)}</Cd></>}
{gameId==="test_him"&&<><Cd s={{marginBottom:8,background:`${C.purple}06`}}><div style={{fontSize:13,fontWeight:700,color:C.purple,marginBottom:6}}>💭 自然试探他心意</div><div style={{fontSize:11,color:C.t3,lineHeight:1.6}}>{gameRes.principle}</div></Cd>{gameRes.indirect?.map((m,i)=><Cd key={i} s={{marginBottom:6,background:`${C.safe}06`}}><div style={{fontSize:11,fontWeight:700,color:C.safe,marginBottom:4}}>🔍 {m.method}</div><div style={{fontSize:11,color:C.t1,background:C.white,padding:"6px 10px",borderRadius:6,marginBottom:4,lineHeight:1.6}}>💬 {m.example}</div><div style={{fontSize:10,color:C.t3}}>📖 读法：{m.read}</div></Cd>)}<Cd s={{marginBottom:6,background:`${C.gold}06`}}><div style={{fontSize:11,fontWeight:700,color:C.gold,marginBottom:4}}>🎯 何时可以直接问</div><div style={{fontSize:11,color:C.t1,marginBottom:4}}>{gameRes.direct_when}</div><div style={{fontSize:12,color:C.pink,fontWeight:600,background:C.white,padding:"6px 10px",borderRadius:6}}>{gameRes.direct_say}</div></Cd><Cd s={{marginBottom:6,background:`${C.danger}06`}}><div style={{fontSize:11,fontWeight:700,color:C.danger,marginBottom:4}}>🚫 别这样试探</div>{gameRes.dontDo?.map((d,i)=><div key={i} style={{fontSize:10,color:C.t2,marginTop:3}}>× {d}</div>)}</Cd>{gameRes.red_flag&&<Cd s={{background:`${C.warn}10`}}><div style={{fontSize:10,color:C.t1,lineHeight:1.6}}>⚠️ {gameRes.red_flag}</div></Cd>}</>}
{gameId==="long_dist"&&<><Cd s={{marginBottom:8,background:`${C.peri}06`}}><div style={{fontSize:13,fontWeight:700,color:C.peri,marginBottom:6}}>✈️ 异地维护 4 支柱</div><div style={{fontSize:11,color:C.t3,lineHeight:1.6}}>{gameRes.principle}</div></Cd>{gameRes.pillars?.map((p,i)=><Cd key={i} s={{marginBottom:6,background:`${C.safe}06`}}><div style={{fontSize:11,fontWeight:700,color:C.peri,marginBottom:4}}>{i+1}. {p.pillar}</div><div style={{fontSize:11,color:C.t1,marginBottom:4,lineHeight:1.6}}>{p.how}</div><div style={{fontSize:10,color:C.t3}}>💡 {p.why}</div></Cd>)}<Cd s={{marginBottom:6,background:`${C.gold}06`}}><div style={{fontSize:11,fontWeight:700,color:C.gold,marginBottom:6}}>🎯 行动清单</div><div style={{fontSize:11,color:C.t1,marginTop:4,lineHeight:1.6}}>📅 每天：{gameRes.daily}</div><div style={{fontSize:11,color:C.t1,marginTop:4,lineHeight:1.6}}>📆 每周：{gameRes.weekly}</div><div style={{fontSize:11,color:C.t1,marginTop:4,lineHeight:1.6}}>🗓 每月：{gameRes.monthly}</div></Cd><Cd s={{marginBottom:6,background:`${C.danger}06`}}><div style={{fontSize:11,fontWeight:700,color:C.danger,marginBottom:4}}>🚫 异地雷区</div>{gameRes.dontDo?.map((d,i)=><div key={i} style={{fontSize:10,color:C.t2,marginTop:3}}>× {d}</div>)}</Cd><Cd s={{background:`${C.warn}10`}}><div style={{fontSize:10,color:C.t1,lineHeight:1.6}}>⚠️ {gameRes.warning}</div></Cd></>}{[{l:"情绪",v:result.data.analysis.emotion,c:C.coral},{l:"潜台词",v:result.data.analysis.subtext,c:C.peri},{l:"TA期望",v:result.data.analysis.expectation,c:C.teal},{l:"风险",v:result.data.analysis.risk,c:C.danger}].map(x=>x.v?<div key={x.l} style={{marginBottom:6}}><span style={{fontSize:10,color:x.c,fontWeight:600}}>{x.l}：</span><span style={{fontSize:12,color:C.t1}}>{x.v}</span></div>:null)}</Cd>}{result.data.replies?.map((r,i)=><Cd key={i} s={{marginBottom:8,animation:`fadeUp .25s ease ${i*.06}s both`}}><div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:4}}><div style={{display:"flex",gap:6,alignItems:"center"}}><Badge color={C.peri}>{r.tone}</Badge><span style={{fontSize:9,color:riskColor(r.risk)}}>{riskLabel(r.risk)}</span></div><div style={{display:"flex",gap:4}}><CB text={r.text} st={st}/><button className="tap2" onClick={e=>{e.stopPropagation();addVault?.(r.text,r.tone);if(learn){const cid=learn.trackChoice(inp,r.tone,personaId,profile?.nickname);setLastChoiceId(cid);}}}style={{padding:"5px 8px",borderRadius:10,fontSize:10,background:`${C.gold}10`,border:`1px solid ${C.gold}25`,color:C.gold,cursor:"pointer"}}>⭐</button></div></div><div style={{fontSize:14,lineHeight:1.8,color:C.t1,marginBottom:3}}><V25StickerText text={r.text} st={st}/></div>{r.reason&&<div style={{fontSize:11,color:C.t3}}>💡 {r.reason}</div>}</Cd>)}<Btn onClick={generate} s={{background:C.bg,marginTop:4}}>🔄 换一批回复</Btn></div>}{lastChoiceId&&<OutcomeFeedback choiceId={lastChoiceId} onFeedback={(id,outcome)=>{if(learn)learn.trackOutcome(id,outcome);}} st={st}/>}{showCopilot&&<RealtimeCopilot onInsight={d=>{if(d?.text&&!inp)setInp(d.text);}} st={st}/>}<div style={{padding:"2px 14px 4px",display:"flex",justifyContent:"flex-end"}}><button className="tap2" onClick={()=>setShowCopilot(!showCopilot)} style={{padding:"3px 10px",borderRadius:8,fontSize:9,fontWeight:600,background:showCopilot?`${C.peri}12`:"transparent",color:showCopilot?C.peri:C.t3,border:`1px solid ${showCopilot?C.peri+"30":"transparent"}`,cursor:"pointer"}}>{showCopilot?"🎧 Copilot ON":"🎧 实时Copilot"}</button></div><div style={{padding:"8px 14px"}}><button className="tap" onClick={()=>setPolMode(!polMode)} style={{width:"100%",padding:"12px 16px",borderRadius:14,background:C.white,border:`1px solid ${C.bd}`,cursor:"pointer",display:"flex",alignItems:"center",gap:10,textAlign:"left"}}><span style={{fontSize:18}}>✨</span><div style={{flex:1}}><div style={{fontSize:13,fontWeight:700,color:C.t1}}>话术优化</div><div style={{fontSize:10,color:C.t3}}>输入你想发的话 → 降风险+改语气</div></div><span style={{fontSize:12,color:C.t3}}>{polMode?"▲":"▼"}</span></button>{polMode&&<div style={{marginTop:10,animation:"fadeUp .2s"}}><Cd s={{marginBottom:10}}><textarea value={polInp} onChange={e=>setPolInp(e.target.value)} placeholder="输入你想发的话...（或从弹药库选）" style={{width:"100%",minHeight:50,padding:0,background:"transparent",border:"none",color:C.t1,fontSize:14,outline:"none",resize:"none",lineHeight:1.7,fontFamily:font}}/></Cd><Btn primary color={C.violet} onClick={doPolish} disabled={!polInp.trim()||polLd}>{polLd?"优化中...":"✨ 话术优化"}</Btn>{polLd&&<Dots/>}{polRes&&<div style={{marginTop:10,animation:"fadeUp .3s"}}><div style={{textAlign:"center",padding:8,borderRadius:12,background:polRes.riskScore>=60?`${C.danger}06`:polRes.riskScore>=30?`${C.warn}06`:`${C.safe}06`,marginBottom:8}}><span style={{fontSize:20,fontWeight:800,color:polRes.riskScore>=60?C.danger:polRes.riskScore>=30?C.warn:C.safe}}>{polRes.riskScore}</span><span style={{fontSize:11,color:C.t3,marginLeft:6}}>风险分 · {polRes.riskNote}</span></div>{polRes.rewrites?.map((w,i)=><Cd key={i} s={{marginBottom:6}}><div style={{display:"flex",justifyContent:"space-between",marginBottom:4}}><Badge color={C.violet}>{w.tone}</Badge><CB text={w.text} st={st}/></div><div style={{fontSize:14,lineHeight:1.7,color:C.t1}}>{w.text}</div></Cd>)}{polRes.best&&<Cd s={{background:`${C.safe}04`,borderColor:`${C.safe}18`}}><div style={{fontSize:11,fontWeight:700,color:C.safe,marginBottom:4}}>🏆 安全最优版</div><div style={{display:"flex",justifyContent:"space-between",gap:6}}><div style={{flex:1,fontSize:14,lineHeight:1.7}}>{polRes.best.text}</div><CB text={polRes.best.text} st={st}/></div><div style={{fontSize:10,color:C.t3,marginTop:3}}>💡 {polRes.best.why}</div></Cd>}</div>}</div>}</div></div>;}/* ═════════════ P2: AI思考 ═══════════════════ */
function AITab({stageId,setStageId,personaId,profile,st,onNavigateGame}){const[tool,setTool]=useState("home");const[helpInp,setHelpInp]=useState("");const[helpLd,setHelpLd]=useState(false);const[helpData,setHelpData]=useState(null);const[helpErr,setHelpErr]=useState(null);const[helpEx,setHelpEx]=useState(null);const[matPur,setMatPur]=useState(null);const[matLd,setMatLd]=useState(false);const[matRes,setMatRes]=useState(null);const[comSel,setComSel]=useState(null);const stg=STAGES.find(s=>s.id===stageId);const[radarInp,setRadarInp]=useState("");const[radarLd,setRadarLd]=useState(false);const[radarRes,setRadarRes]=useState(null);const[comboInp,setComboInp]=useState("");const[comboLd,setComboLd]=useState(false);const[comboRes,setComboRes]=useState(null);const[voiceInp,setVoiceInp]=useState("");const[voiceLd,setVoiceLd]=useState(false);const[voiceRes,setVoiceRes]=useState(null);const[sweetness,setSweetness]=useState(50);const VT=[{id:"gentle",l:"温柔",c:C.pink},{id:"humor",l:"幽默",c:C.gold},{id:"eq",l:"高情商",c:C.peri},{id:"sweet",l:"甜蜜",c:C.rose},{id:"direct",l:"直接",c:C.coral},{id:"push",l:"推拉",c:C.violet},{id:"lowp",l:"低压",c:C.teal},{id:"sajiao",l:"撒娇",c:"#FFB74D"}];const[voiceTones,setVoiceTones]=useState(["gentle","humor","eq"]);const toggleVT=(id)=>setVoiceTones(p=>p.includes(id)?p.filter(t=>t!==id):[...p,id].slice(0,5));const[transInp,setTransInp]=useState("");const[transRes,setTransRes]=useState(null);const[transLd,setTransLd]=useState(false);const[transHist,setTransHist]=useState([]);useEffect(()=>{(async()=>{try{const r=await window.storage.get("sakura-trans-hist");if(r?.value)setTransHist(JSON.parse(r.value));}catch{}})();},[]);const[feelInp,setFeelInp]=useState("");const[feelLd,setFeelLd]=useState(false);const[feelRes,setFeelRes]=useState(null);const doTrans=async()=>{if(!transInp.trim())return;const local=KB_TRANS.find(k=>transInp.includes(k.input));if(local){const res={type:"local",input:local.input,subtexts:local.subtexts};setTransRes(res);const nh=[{id:Date.now(),input:local.input,top:local.subtexts[0]?.t,tag:local.subtexts[0]?.tag},...transHist].slice(0,50);setTransHist(nh);try{window.storage.set("sakura-trans-hist",JSON.stringify(nh));}catch{}return;}setTransLd(true);setTransRes(null);const r=await ai(buildSys(stageId,personaId,profile,`你是恋爱潜台词翻译专家。分析3种可能的潜台词。每种给出：真实含义(20字内)、概率(加起来=100)、情绪标签(2字)。再给2条回复建议。返回JSON：{"input":"原句","subtexts":[{"t":"潜台词","pct":50,"tag":"标签"}],"replies":{"gentle":"温柔回复","firm":"直接回复"}}`),`TA说：「${transInp}」`);const pr=pJ(r)||{input:transInp,subtexts:[{t:"需要更多上下文",pct:100,tag:"不确定"}]};setTransRes(pr);const nh=[{id:Date.now(),input:transInp,top:pr.subtexts?.[0]?.t,tag:pr.subtexts?.[0]?.tag},...transHist].slice(0,50);setTransHist(nh);try{window.storage.set("sakura-trans-hist",JSON.stringify(nh));}catch{}setTransLd(false);};const doFeel=async()=>{if(!feelInp.trim()||feelLd)return;setFeelLd(true);setFeelRes(null);const r=await ai(buildSys(stageId,personaId,profile,`你是恋爱对象。用第一人称"我"的视角说出收到这条消息时的真实内心感受。返回JSON：{"surface":"表面反应","inner":"真实内心(2-3句)","action":"大概率行为","heartDelta":-10到+10,"mood":"emoji"}`),`对方发来：「${feelInp}」`);setFeelRes(pJ(r)||{surface:"嗯...",inner:"不确定",action:"观望",heartDelta:0,mood:"🤔"});setFeelLd(false);};const doRadar=async()=>{if(!radarInp.trim()||radarLd)return;setRadarLd(true);setRadarRes(null);const r=await ai(buildSys(stageId,personaId,profile,`你是恋爱消息风险扫描专家。10维度(每个0-100)：需求感暴露、语气过重、逼迫感、情绪化、敷衍感、讨好感、攻击性、暴露隐私、时机不对、长度不当。返回JSON：{"total":0-100,"dimensions":[{"name":"维度","score":0-100,"note":"说明"}],"danger":"最危险的点","safeVersion":"安全改写版","tip":"建议"}`),`想发：「${radarInp}」`);setRadarRes(pJ(r)||{total:40,dimensions:[{name:"需求感",score:40,note:"暂无"}],danger:"暂无",safeVersion:radarInp,tip:"保持自然"});setRadarLd(false);};const doCombo=async()=>{if(!comboInp.trim()||comboLd)return;setComboLd(true);setComboRes(null);const r=await ai(buildSys(stageId,personaId,profile,`你是恋爱连续技策略师。设计3条连续消息组合拳。1.破冰/试探 2.升温/推进 3.锁定/收尾。每条注明间隔时间和发送条件。返回JSON：{"strategy":"整体策略","combo":[{"step":1,"text":"消息","timing":"时机","condition":"条件","purpose":"目的"}],"warning":"注意事项"}`),`场景：${comboInp}`);setComboRes(pJ(r)||{strategy:"循序渐进",combo:[{step:1,text:"在吗？",timing:"现在",condition:"直接发",purpose:"破冰"}],warning:"注意节奏"});setComboLd(false);};const doVoice=async()=>{if(!voiceInp.trim()||voiceLd||voiceTones.length===0)return;setVoiceLd(true);setVoiceRes(null);const tn=voiceTones.map(id=>VT.find(t=>t.id===id)?.l).filter(Boolean).join("、");const swL=sweetness<=20?"清淡":sweetness<=40?"微甜":sweetness<=60?"刚好":sweetness<=80?"很甜":"齁甜";const r=await ai(buildSys(stageId,personaId,profile,`你是恋爱话术语气助手。甜度：${sweetness}/100(${swL})。语气：${tn}。保持原意，只改语气。像真人微信不超过30字。返回JSON：[{"tone":"语气","text":"改写后","vibe":"感觉描述"}]`),`原句：「${voiceInp}」`);setVoiceRes(pJ(r)||voiceTones.map(id=>({tone:VT.find(t=>t.id===id)?.l||"",text:voiceInp,vibe:"原版"})));setVoiceLd(false);};const doHelp=async()=>{if(!helpInp.trim()||helpLd)return;setHelpLd(true);setHelpData(null);setHelpErr(null);setHelpEx(null);const r=await ai(buildSys(stageId,personaId,profile,`你是资深恋爱沟通顾问。第一步·情绪雷达：label(4字内概括情绪)、detail(潜台词1句)、5维评分(0-100)：energy/warmth/trust/interest/risk。第二步·5条回复策略：每条说清策略目的+对方反应+胜率预测(继续聊/被感动/推进/被敷衍)。回复像真人微信不超过25字。返回JSON：{"emotion":{"label":"","detail":"","energy":50,"warmth":50,"trust":50,"interest":50,"risk":30},"replies":[{"style":"风格","icon":"emoji","text":"回复","why":"策略","win":{"继续聊":80,"被感动":20,"推进":30,"被敷衍":10}}]}`),`对方说：「${helpInp}」`);if(isE(r)){setHelpErr(r._e);setHelpLd(false);return;}setHelpData(pJ(r)||{emotion:{label:"分析中",detail:"",energy:50,warmth:50,trust:50,interest:50,risk:30},replies:[{style:"安全",icon:"🧠",text:"嗯嗯，我在呢",why:"给安全感",win:{"继续聊":75,"被感动":20,"推进":10,"被敷衍":8}}]});setHelpLd(false);};const doMatrix=async(purId)=>{setMatPur(purId);setMatLd(true);setMatRes(null);const pur=PURPOSES.find(p=>p.id===purId);const r=await ai(buildSys(stageId,personaId,profile,`你是恋爱话术文案专家。阶段：${pur?.l}。生成5条可以直接发送的话术。像真人微信，5条风格差异明显，融入档案，每条加场景标签。返回JSON：[{"text":"话术","tag":"适用场景"}]`),"生成");setMatRes(pJ(r)||[{text:"换个试试",tag:"通用"}]);setMatLd(false);};if(tool==="help")return <div style={{paddingBottom:100}}><SubHeader onBack={()=>setTool("home")} title="💬 帮我回"/><div style={{padding:"14px 16px"}}><Cd s={{marginBottom:12,background:`${C.pink}04`}}><div style={{fontSize:11,color:C.pink,fontWeight:600,marginBottom:6}}>📥 对方说了什么？</div><textarea value={helpInp} onChange={e=>setHelpInp(e.target.value)} placeholder="粘贴TA的消息..." style={{width:"100%",minHeight:60,padding:0,background:"transparent",border:"none",color:C.t1,fontSize:15,outline:"none",resize:"none",lineHeight:1.7,fontFamily:font}}/></Cd><Btn primary onClick={doHelp} disabled={!helpInp.trim()||helpLd}>{helpLd?"AI 分析中...":"🔍 帮我回"}</Btn>{helpLd&&<Dots/>}{helpErr&&<div style={{textAlign:"center",padding:16}}><div style={{fontSize:12,color:C.danger}}>❌ {helpErr}</div><Btn primary onClick={doHelp} s={{marginTop:8}}>🔄 重试</Btn></div>}{helpData&&<div style={{marginTop:16,animation:"fadeUp .4s"}}><Cd s={{marginBottom:14}}><div style={{fontSize:12,fontWeight:700,color:C.t2,marginBottom:8}}>🎯 情绪雷达</div><div style={{display:"inline-block",padding:"3px 10px",borderRadius:8,background:`${C.pink}08`,fontSize:11,color:C.pink,fontWeight:600,marginBottom:8}}>{helpData.emotion?.label}</div>{helpData.emotion?.detail&&<div style={{fontSize:11,color:C.t2,marginBottom:8,lineHeight:1.5}}>💭 {helpData.emotion.detail}</div>}<EB l="能量" v={helpData.emotion?.energy||50} c={C.lime}/><EB l="温暖" v={helpData.emotion?.warmth||50} c={C.coral}/><EB l="信任" v={helpData.emotion?.trust||50} c={C.teal}/><EB l="兴趣" v={helpData.emotion?.interest||50} c={C.peri}/><EB l="风险" v={helpData.emotion?.risk||30} c={C.danger}/></Cd><div style={{fontSize:13,fontWeight:700,color:C.t1,marginBottom:8}}>💡 5种回法 <span style={{fontSize:10,fontWeight:400,color:C.t3}}>点击展开胜率</span></div>{helpData.replies?.map((r,i)=><Cd key={i} onClick={()=>setHelpEx(helpEx===i?null:i)} s={{marginBottom:8,cursor:"pointer",animation:`fadeUp .25s ease ${i*.05}s both`}}><div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:5}}><div style={{display:"flex",gap:5,alignItems:"center"}}><span style={{fontSize:15}}>{r.icon}</span><span style={{fontSize:12,fontWeight:700,color:C.pink}}>{r.style}</span></div><CB text={r.text} st={st}/></div><div style={{fontSize:14,lineHeight:1.7,color:C.t1,marginBottom:3}}><V25StickerText text={r.text} st={st}/></div><div style={{fontSize:11,color:C.t3}}>💡 {r.why}</div>{helpEx===i&&r.win&&<div style={{marginTop:8,padding:10,background:C.bg,borderRadius:10,border:`1px solid ${C.bd}`,animation:"fadeUp .2s"}}><div style={{fontSize:11,fontWeight:700,color:C.gold,marginBottom:6}}>📊 胜率预测</div>{Object.entries(r.win).map(([k,v])=><EB key={k} l={k} v={v} c={k==="被敷衍"?C.danger:k==="推进"?C.peri:k==="被感动"?C.rose:C.teal}/>)}</div>}</Cd>)}</div>}</div></div>;if(tool==="matrix")return <div style={{paddingBottom:100}}><SubHeader onBack={()=>{setTool("home");setMatPur(null);setMatRes(null);}}title={`💡 ${stg?.icon} ${stg?.l} × 会说`}/><div style={{padding:"14px 16px"}}><div style={{fontSize:12,fontWeight:700,color:C.t1,marginBottom:6}}>📍 关系阶段</div><div style={{display:"flex",gap:4,flexWrap:"wrap",marginBottom:14}}>{STAGES.map(s=><Pill key={s.id} active={stageId===s.id} color={C.pink} onClick={()=>{setStageId(s.id);setMatPur(null);setMatRes(null);}}>{s.icon} {s.l}</Pill>)}</div>{!matPur&&<><div style={{fontSize:12,fontWeight:700,color:C.t1,marginBottom:8}}>🎯 选择目的</div><div style={{display:"grid",gridTemplateColumns:"repeat(4,1fr)",gap:6}}>{PURPOSES.map((p,i)=><button key={p.id} className="tap" onClick={()=>doMatrix(p.id)} style={{padding:"10px 4px",borderRadius:12,background:C.white,border:`1px solid ${C.bd}`,cursor:"pointer",textAlign:"center",animation:`fadeUp .15s ease ${i*.02}s both`}}><div style={{fontSize:18,marginBottom:2}}>{p.icon}</div><div style={{fontSize:10,fontWeight:600,color:C.t2}}>{p.l}</div></button>)}</div></>}{matLd&&<Dots/>}{matRes&&<div style={{animation:"fadeUp .3s"}}><div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:10}}><div style={{fontSize:13,fontWeight:700,color:C.t1}}>{stg?.icon} {stg?.l} × {PURPOSES.find(p=>p.id===matPur)?.l}</div><button className="tap2" onClick={()=>{setMatPur(null);setMatRes(null);}} style={{padding:"4px 10px",borderRadius:8,background:C.bg,border:`1px solid ${C.bd}`,color:C.t3,fontSize:10,cursor:"pointer"}}>← 换目的</button></div>{matRes.map((r,i)=><Cd key={i} s={{marginBottom:8}}><div style={{display:"flex",justifyContent:"space-between",gap:6}}><div style={{flex:1}}><div style={{fontSize:14,lineHeight:1.7,color:C.t1,marginBottom:3}}><V25StickerText text={r.text} st={st}/></div><Badge color={C.gold}>{r.tag}</Badge></div><CB text={r.text} st={st}/></div></Cd>)}<Btn onClick={()=>doMatrix(matPur)} s={{background:C.bg,marginTop:4}}>🔄 换一批</Btn></div>}</div></div>;if(tool==="comfort")return <div style={{paddingBottom:100}}><SubHeader onBack={()=>{setTool("home");setComSel(null);}} title="🚑 哄人急救"/><div style={{padding:"14px 16px"}}>{!comSel?<div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}>{COMFORTS.map((c,i)=><Cd key={c.id} onClick={()=>setComSel(c.id)} s={{cursor:"pointer",animation:`fadeUp .15s ease ${i*.04}s both`}}><div style={{fontSize:24,marginBottom:6}}>{c.icon}</div><div style={{fontSize:13,fontWeight:700,color:C.t1}}>{c.l}</div></Cd>)}</div>:(()=>{const c=COMFORTS.find(x=>x.id===comSel);if(!c)return null;return <div style={{animation:"fadeUp .2s"}}><div style={{display:"flex",alignItems:"center",gap:10,marginBottom:14}}><div style={{width:44,height:44,borderRadius:14,background:`${C.pink}10`,display:"flex",alignItems:"center",justifyContent:"center",fontSize:22}}>{c.icon}</div><div><div style={{fontSize:16,fontWeight:700}}>{c.l}</div><div style={{fontSize:11,color:C.t3}}>分步话术</div></div></div>{c.steps.map((s,i)=><Cd key={i} s={{marginBottom:10}}><Badge color={C.peri}>{s.t}</Badge><div style={{fontSize:14,lineHeight:1.8,color:C.t1,marginTop:6}}>{s.m}</div><div style={{marginTop:6}}><CB text={s.m} st={st}/></div></Cd>)}<Cd s={{background:`${C.danger}04`}}><div style={{fontSize:11,fontWeight:700,color:C.danger,marginBottom:4}}>🚫 千万别说</div><div style={{fontSize:12,lineHeight:1.6,color:C.t2}}>{c.ban}</div></Cd><button className="tap" onClick={()=>setComSel(null)} style={{marginTop:12,padding:"10px",borderRadius:12,background:C.bg,border:`1px solid ${C.bd}`,color:C.t2,fontSize:12,cursor:"pointer",width:"100%"}}>← 其他场景</button></div>;})()}</div></div>;if(tool==="radar")return <div style={{paddingBottom:100}}><SubHeader onBack={()=>setTool("home")} title="🛡️ 风险雷达"/><div style={{padding:"14px 16px"}}><Cd s={{marginBottom:12,background:`${C.teal}04`}}><div style={{fontSize:11,color:C.teal,fontWeight:600,marginBottom:6}}>想发什么？帮你扫描10维风险</div><textarea value={radarInp} onChange={e=>setRadarInp(e.target.value)} placeholder="输入你想发的消息..." style={{width:"100%",minHeight:60,padding:0,background:"transparent",border:"none",color:C.t1,fontSize:14,outline:"none",resize:"none",lineHeight:1.7,fontFamily:font}}/></Cd><Btn primary color={C.teal} onClick={doRadar} disabled={!radarInp.trim()||radarLd}>{radarLd?"扫描中...":"🛡️ 10维风险扫描"}</Btn>{radarLd&&<Dots/>}{radarRes&&<div style={{marginTop:14,animation:"fadeUp .3s"}}><Cd s={{marginBottom:12,textAlign:"center",background:radarRes.total>=60?`${C.danger}06`:radarRes.total>=30?`${C.warn}06`:`${C.safe}06`}}><div style={{fontSize:32,fontWeight:900,color:radarRes.total>=60?C.danger:radarRes.total>=30?C.warn:C.safe}}>{radarRes.total}</div><div style={{fontSize:11,color:C.t3}}>综合风险分</div></Cd>{radarRes.danger&&<div style={{fontSize:11,color:C.danger,padding:"6px 10px",background:`${C.danger}06`,borderRadius:8,marginBottom:10}}>⚠️ {radarRes.danger}</div>}{radarRes.dimensions?.map((d,i)=><div key={i} style={{marginBottom:6}}><EB l={d.name} v={d.score} c={d.score>=60?C.danger:d.score>=30?C.warn:C.safe}/>{d.note&&d.score>=30&&<div style={{fontSize:9,color:C.t3,paddingLeft:40,marginTop:-2}}>{d.note}</div>}</div>)}{radarRes.safeVersion&&<Cd s={{marginTop:10,background:`${C.safe}04`}}><div style={{fontSize:11,fontWeight:600,color:C.safe,marginBottom:4}}>✅ 安全版本</div><div style={{display:"flex",justifyContent:"space-between",gap:8}}><div style={{flex:1,fontSize:14,lineHeight:1.7,color:C.t1}}>{radarRes.safeVersion}</div><CB text={radarRes.safeVersion} st={st}/></div></Cd>}{radarRes.tip&&<div style={{fontSize:10,color:C.t3,marginTop:8,textAlign:"center"}}>💡 {radarRes.tip}</div>}</div>}</div></div>;if(tool==="combo")return <div style={{paddingBottom:100}}><SubHeader onBack={()=>setTool("home")} title="🎯 连续技"/><div style={{padding:"14px 16px"}}><Cd s={{marginBottom:12,background:`${C.peri}04`}}><div style={{fontSize:11,color:C.peri,fontWeight:600,marginBottom:6}}>描述场景，AI帮你设计3连消息</div><textarea value={comboInp} onChange={e=>setComboInp(e.target.value)} placeholder={"描述你想达成的目标..."} style={{width:"100%",minHeight:70,padding:0,background:"transparent",border:"none",color:C.t1,fontSize:14,outline:"none",resize:"none",lineHeight:1.7,fontFamily:font}}/></Cd><Btn primary color={C.peri} onClick={doCombo} disabled={!comboInp.trim()||comboLd}>{comboLd?"策划中...":"🎯 生成3连组合拳"}</Btn>{comboLd&&<Dots/>}{comboRes&&<div style={{marginTop:14,animation:"fadeUp .3s"}}>{comboRes.strategy&&<div style={{fontSize:12,color:C.peri,fontWeight:600,marginBottom:10,padding:"6px 10px",background:`${C.peri}06`,borderRadius:8}}>🎯 {comboRes.strategy}</div>}{comboRes.combo?.map((s,i)=><Cd key={i} s={{marginBottom:8,borderLeft:`3px solid ${[C.teal,C.peri,C.pink][i]||C.t3}`}}><div style={{display:"flex",justifyContent:"space-between",marginBottom:4}}><div style={{display:"flex",gap:6,alignItems:"center"}}><Badge color={[C.teal,C.peri,C.pink][i]||C.t3}>Step {s.step}</Badge><span style={{fontSize:9,color:C.t3}}>{s.timing}</span></div><CB text={s.text} st={st}/></div><div style={{fontSize:14,lineHeight:1.7,color:C.t1,marginBottom:3}}>{s.text}</div><div style={{fontSize:10,color:C.t3}}>📌 {s.condition} · 💡 {s.purpose}</div></Cd>)}{comboRes.warning&&<div style={{fontSize:10,color:C.warn,padding:"6px 10px",background:`${C.warn}06`,borderRadius:8}}>⚠️ {comboRes.warning}</div>}</div>}</div></div>;if(tool==="voice")return <div style={{paddingBottom:100}}><SubHeader onBack={()=>setTool("home")} title="🎚️ 语气调节"/><div style={{padding:"14px 16px"}}><Cd s={{marginBottom:10}}><textarea value={voiceInp} onChange={e=>setVoiceInp(e.target.value)} placeholder="输入你想发的原句..." style={{width:"100%",minHeight:50,padding:0,background:"transparent",border:"none",color:C.t1,fontSize:14,outline:"none",resize:"none",lineHeight:1.7,fontFamily:font}}/></Cd><Cd s={{marginBottom:10,background:`${sweetness<=30?C.teal:sweetness<=60?C.gold:C.rose}04`}}><div style={{display:"flex",justifyContent:"space-between",marginBottom:6}}><span style={{fontSize:12,fontWeight:700,color:C.t1}}>🍬 甜度</span><span style={{fontSize:12,fontWeight:800,color:sweetness<=30?C.teal:sweetness<=60?C.gold:sweetness<=80?C.rose:"#ff4081"}}>{sweetness} · {sweetness<=20?"清淡":sweetness<=40?"微甜":sweetness<=60?"刚好":sweetness<=80?"很甜":"齁甜"}</span></div><input type="range" min={0} max={100} value={sweetness} onChange={e=>setSweetness(+e.target.value)} style={{width:"100%",background:`linear-gradient(90deg,${C.teal},${C.gold},${C.rose},#ff4081)`}}/></Cd><div style={{display:"flex",flexWrap:"wrap",gap:5,marginBottom:12}}>{VT.map(t=><Pill key={t.id} active={voiceTones.includes(t.id)} color={t.c} onClick={()=>toggleVT(t.id)}>{t.l}</Pill>)}</div><Btn primary color={C.violet} onClick={doVoice} disabled={!voiceInp.trim()||voiceLd||voiceTones.length===0}>{voiceLd?"调节中...":`🔊 ${voiceTones.length}种语气`}</Btn>{voiceLd&&<Dots/>}{voiceRes&&<div style={{marginTop:12,animation:"fadeUp .3s"}}>{voiceRes.map((v,i)=>{const tc=VT.find(t=>t.l===v.tone)?.c||C.peri;return <Cd key={i} s={{marginBottom:6}}><div style={{display:"flex",justifyContent:"space-between",marginBottom:4}}><Badge color={tc}>{v.tone}</Badge><CB text={v.text} st={st}/></div><div style={{fontSize:14,lineHeight:1.7,color:C.t1}}>{v.text}</div>{v.vibe&&<div style={{fontSize:9,color:C.t3,marginTop:3}}>✨ {v.vibe}</div>}</Cd>;})}</div>}</div></div>;if(tool==="trans")return <div style={{paddingBottom:100}}><SubHeader onBack={()=>setTool("home")} title="🔄 语意翻译器"/><div style={{padding:"14px 16px"}}><Cd s={{marginBottom:12}}><div style={{fontSize:11,color:C.rose,fontWeight:600,marginBottom:6}}>TA说了什么？帮你翻译潜台词</div><textarea value={transInp} onChange={e=>setTransInp(e.target.value)} placeholder="输入TA说的话" style={{width:"100%",minHeight:50,padding:0,background:"transparent",border:"none",color:C.t1,fontSize:14,outline:"none",resize:"none",lineHeight:1.7,fontFamily:font}}/></Cd><Btn primary color={C.rose} onClick={doTrans} disabled={!transInp.trim()||transLd}>{transLd?"翻译中...":"🔄 翻译潜台词"}</Btn>{transLd&&<Dots/>}{!transRes&&<div style={{marginTop:14}}><div style={{fontSize:11,fontWeight:700,color:C.t2,marginBottom:8}}>🔥 高频潜台词</div><div style={{display:"flex",flexWrap:"wrap",gap:5}}>{KB_TRANS.map((k,i)=><button key={i} className="tap2" onClick={()=>{setTransInp(k.input);setTransRes({type:"local",input:k.input,subtexts:k.subtexts});}}style={{padding:"5px 12px",borderRadius:10,background:C.bg,border:`1px solid ${C.bd}`,color:C.t1,fontSize:12,cursor:"pointer"}}>「{k.input}」</button>)}</div></div>}{transRes&&<div style={{marginTop:14,animation:"fadeUp .3s"}}><Cd s={{marginBottom:10,background:`${C.rose}04`}}><div style={{fontSize:14,fontWeight:700,color:C.t1,marginBottom:10}}>「{transRes.input}」的潜台词</div>{transRes.subtexts?.map((s,i)=><div key={i} style={{marginBottom:8}}><div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:3}}><Badge color={i===0?C.danger:i===1?C.warn:C.safe}>{s.tag}</Badge><span style={{fontSize:12,fontWeight:700,color:i===0?C.danger:i===1?C.warn:C.safe}}>{s.pct}%</span></div><div style={{height:5,borderRadius:3,background:C.bg,overflow:"hidden",marginBottom:3}}><div style={{width:`${s.pct}%`,height:"100%",borderRadius:3,background:i===0?C.danger:i===1?C.warn:C.safe,transition:"width .8s"}}/></div><div style={{fontSize:12,color:C.t1,lineHeight:1.6}}>{s.t}</div></div>)}</Cd>{transRes.replies&&<Cd s={{marginBottom:6}}><div style={{fontSize:11,fontWeight:600,color:C.teal,marginBottom:4}}>💬 推荐回复</div>{[{l:"温柔版",t:transRes.replies.gentle,c:C.pink},{l:"直接版",t:transRes.replies.firm,c:C.peri}].map(r=>r.t?<div key={r.l} style={{display:"flex",justifyContent:"space-between",gap:6,padding:"6px 0",borderBottom:`1px solid ${C.bdL}`}}><div><Badge color={r.c}>{r.l}</Badge><div style={{fontSize:13,color:C.t1,marginTop:3}}>{r.t}</div></div><CB text={r.t} st={st}/></div>:null)}</Cd>}</div>}{transHist.length>0&&<div style={{marginTop:14}}><div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:6}}><div style={{fontSize:11,fontWeight:700,color:C.t2}}>📚 翻译历史 ({transHist.length})</div><button className="tap2" onClick={()=>{setTransHist([]);try{window.storage.set("sakura-trans-hist","[]");}catch{}st("已清空");}} style={{fontSize:9,color:C.t3,background:"none",border:"none",cursor:"pointer"}}>清空</button></div>{transHist.slice(0,10).map(h=><div key={h.id} className="tap2" onClick={()=>{setTransInp(h.input);const local=KB_TRANS.find(k=>h.input.includes(k.input));if(local)setTransRes({type:"local",input:local.input,subtexts:local.subtexts});}}style={{display:"flex",justifyContent:"space-between",alignItems:"center",padding:"8px 10px",marginBottom:3,borderRadius:8,background:C.bg,cursor:"pointer"}}><div style={{flex:1}}><span style={{fontSize:12,color:C.t1}}>「{h.input}」</span><span style={{fontSize:10,color:C.rose,marginLeft:6}}>→ {h.top}</span></div><Badge color={C.warn}>{h.tag}</Badge></div>)}</div>}</div></div>;
if(tool==="feeling")return <div style={{paddingBottom:100}}><SubHeader onBack={()=>setTool("home")} title="💭 对方感受器"/><div style={{padding:"14px 16px"}}><Cd s={{marginBottom:12,background:`${C.violet}04`}}><div style={{fontSize:11,color:C.violet,fontWeight:600,marginBottom:6}}>输入你想发的话，看TA收到后什么感觉</div><textarea value={feelInp} onChange={e=>setFeelInp(e.target.value)} placeholder="你准备发什么？" style={{width:"100%",minHeight:50,padding:0,background:"transparent",border:"none",color:C.t1,fontSize:14,outline:"none",resize:"none",lineHeight:1.7,fontFamily:font}}/></Cd><Btn primary color={C.violet} onClick={doFeel} disabled={!feelInp.trim()||feelLd}>{feelLd?"感应中...":"💭 感受TA的内心"}</Btn>{feelLd&&<Dots/>}{feelRes&&<div style={{marginTop:14,animation:"fadeUp .3s"}}><Cd s={{marginBottom:10,textAlign:"center",background:`linear-gradient(135deg,${C.violet}06,${C.pink}04)`}}><div style={{fontSize:48,marginBottom:4}}>{feelRes.mood}</div><div style={{fontSize:20,fontWeight:900,color:feelRes.heartDelta>0?C.pink:feelRes.heartDelta<0?C.teal:C.t2}}>心动值 {feelRes.heartDelta>0?"+":""}{feelRes.heartDelta}</div></Cd><Cd s={{marginBottom:8}}><div style={{fontSize:11,fontWeight:600,color:C.coral,marginBottom:3}}>😐 表面反应</div><div style={{fontSize:13,color:C.t1,lineHeight:1.7}}>{feelRes.surface}</div></Cd><Cd s={{marginBottom:8,background:`${C.violet}04`}}><div style={{fontSize:11,fontWeight:600,color:C.violet,marginBottom:3}}>💭 真实内心</div><div style={{fontSize:13,color:C.t1,lineHeight:1.7,fontStyle:"italic"}}>{feelRes.inner}</div></Cd><Cd s={{marginBottom:8}}><div style={{fontSize:11,fontWeight:600,color:C.teal,marginBottom:3}}>👉 TA大概率会</div><div style={{fontSize:13,color:C.t1,lineHeight:1.7}}>{feelRes.action}</div></Cd></div>}</div></div>;return <div style={{paddingBottom:100,position:"relative",zIndex:1}}><div style={{textAlign:"center",padding:"18px 20px 10px"}}><div style={{fontSize:28,marginBottom:2}}>✨</div><h2 style={{fontSize:18,fontWeight:800,background:`linear-gradient(135deg,${C.peri},${C.pink})`,WebkitBackgroundClip:"text",WebkitTextFillColor:"transparent"}}>AI 思考</h2><p style={{fontSize:10,color:C.t3,marginTop:2}}>更深度的分析 · 更精准的策略</p></div><div style={{padding:"0 14px"}}><V25DailyRecommend stageId={stageId} onNavigateGame={onNavigateGame}/></div><div style={{padding:"0 14px"}}><button className="tap" onClick={()=>setTool("help")} style={{width:"100%",marginBottom:14,padding:"18px 16px",borderRadius:20,background:`linear-gradient(135deg,${C.pink}08,${C.peri}06)`,border:`1.5px solid ${C.pink}20`,cursor:"pointer",display:"flex",alignItems:"center",gap:14,textAlign:"left",boxShadow:`0 6px 28px ${C.pink}08`}}><div style={{width:52,height:52,borderRadius:16,background:`linear-gradient(135deg,${C.pink}18,${C.peri}10)`,display:"flex",alignItems:"center",justifyContent:"center",fontSize:24,flexShrink:0}}>💬</div><div><div style={{fontSize:16,fontWeight:900,color:C.pink}}>帮我回</div><div style={{fontSize:11,color:C.t2,marginTop:2}}>情绪雷达 + 5策略回复 + 胜率预测</div></div></button><div style={{fontSize:11,fontWeight:700,color:C.t2,marginBottom:8}}>🔮 读心工具</div><div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8,marginBottom:14}}>{[{id:"trans",icon:"🔄",l:"语意翻译器",d:"TA的潜台词是什么",c:C.rose},{id:"feeling",icon:"💭",l:"对方感受器",d:"TA收到后什么感觉",c:C.violet}].map((t,i)=><button key={t.id} className="tap" onClick={()=>setTool(t.id)} style={{padding:"14px 12px",borderRadius:16,background:C.white,border:`1px solid ${C.bd}`,cursor:"pointer",textAlign:"left"}}><div style={{fontSize:20,marginBottom:6}}>{t.icon}</div><div style={{fontSize:13,fontWeight:700,color:t.c}}>{t.l}</div><div style={{fontSize:9,color:C.t3,marginTop:2}}>{t.d}</div></button>)}</div><div style={{fontSize:11,fontWeight:700,color:C.t2,marginBottom:8}}>💬 话术工具</div><div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8,marginBottom:14}}>{[{id:"matrix",icon:"💡",l:"会说",d:"13阶段×16目的",c:C.peri},{id:"comfort",icon:"🚑",l:"哄人急救",d:"分步脚本·别踩雷",c:C.coral}].map((t,i)=><button key={t.id} className="tap" onClick={()=>setTool(t.id)} style={{padding:"14px 12px",borderRadius:16,background:C.white,border:`1px solid ${C.bd}`,cursor:"pointer",textAlign:"left"}}><div style={{fontSize:20,marginBottom:6}}>{t.icon}</div><div style={{fontSize:13,fontWeight:700,color:t.c}}>{t.l}</div><div style={{fontSize:9,color:C.t3,marginTop:2}}>{t.d}</div></button>)}</div><div style={{fontSize:11,fontWeight:700,color:C.t2,marginBottom:8}}>🔧 AI增强</div><div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:6}}>{[{id:"radar",icon:"🛡️",l:"风险雷达",c:C.teal},{id:"combo",icon:"🎯",l:"连续技",c:C.peri},{id:"voice",icon:"🔊",l:"语气调节",c:C.violet}].map(t=><button key={t.id} className="tap" onClick={()=>setTool(t.id)} style={{padding:"12px 6px",borderRadius:14,background:C.white,border:`1px solid ${C.bd}`,cursor:"pointer",textAlign:"center"}}><div style={{fontSize:18,marginBottom:3}}>{t.icon}</div><div style={{fontSize:10,fontWeight:700,color:t.c}}>{t.l}</div></button>)}</div></div></div>;
}
function DeepInputPhase(_p){const{analyzing,checked,ctxData,expandedEng,expandedMod,expertAutoMode,extra,extraLd,font,inp,intents,mode,pipeStep,replyDelay,reportTab,reset,result,setChecked,setCtxData,setExpandedEng,setExpandedMod,setExpertAutoMode,setExtra,setInp,setIntents,setMode,setPhase,setReplyDelay,setReportTab,setResult,setShowModulesInReport,setShowSliders,setShowTriCore,showModulesInReport,showSliders,showTriCore,st,vault,stageId,onNavigateGame}=_p;return(<div style={{paddingBottom:100,position:"relative",zIndex:1}}><div style={{padding:"14px 16px 8px"}}><div style={{fontSize:18,fontWeight:800,color:C.t1,marginBottom:2}}>⚡ 一键诊断</div><div style={{fontSize:9,color:C.t3,marginBottom:10}}>粘贴对话或描述情况 → 0.6秒出结果</div><V25DailyRecommend stageId={stageId} onNavigateGame={onNavigateGame}/><div style={{display:"flex",justifyContent:"center",gap:8,marginBottom:8}}><button className="tap2" onClick={()=>setExpertAutoMode(!expertAutoMode)} style={{padding:"5px 14px",borderRadius:10,fontSize:10,fontWeight:expertAutoMode?700:500,background:expertAutoMode?`${C.peri}12`:"transparent",border:`1px solid ${expertAutoMode?C.peri+"30":C.bd}`,color:expertAutoMode?C.peri:C.t3,cursor:"pointer"}}>{expertAutoMode?"🤖 专家自动":"🔧 手动选模块"}</button></div>{/* 8个场景标签 + 自定义 */}<div style={{marginBottom:6}}><div style={{fontSize:11,fontWeight:700,color:C.t2,marginBottom:4}}>⚡ 快速选择场景</div><div style={{display:"flex",gap:5,flexWrap:"wrap",marginBottom:4}}>{[{icon:"😶",l:"已读不回"},{icon:"💢",l:"吵架冷战"},{icon:"💕",l:"暧昧推进"},{icon:"💔",l:"分手挽回"},{icon:"🤔",l:"要不要继续"},{icon:"🧊",l:"TA变冷淡了"},{icon:"✈️",l:"异地想念"}].map((sc,i)=><button key={i} className="tap2" onClick={()=>setInp(sc.l)} style={{padding:"5px 11px",borderRadius:10,fontSize:10,background:inp===sc.l?`${C.peri}12`:"transparent",border:`1.5px solid ${inp===sc.l?C.peri+"40":C.bd}`,color:inp===sc.l?C.peri:C.t2,cursor:"pointer"}}>{sc.icon} {sc.l}</button>)}</div><CustomAdd placeholder="自定义场景（如：异地恋3个月感觉变淡了）" onAdd={v=>setInp(v)} color={C.peri}/></div>{/* 意图标签 */}<div style={{marginBottom:6}}><div style={{fontSize:11,fontWeight:500,color:C.t3,marginBottom:4}}>我想要 <span style={{fontSize:9}}>({intents.length})</span></div><div style={{display:"flex",gap:4,flexWrap:"wrap"}}>{INTENTS.map(it=>{const on=intents.includes(it.l);return <button key={it.l} className="tap2" onClick={()=>setIntents(p=>on?p.filter(x=>x!==it.l):[...p,it.l])} style={{padding:"4px 10px",borderRadius:8,fontSize:10,background:on?`${C.peri}10`:"transparent",border:`1px solid ${on?C.peri+"40":C.bd}`,color:on?C.peri:C.t3,cursor:"pointer"}}>{on?"✓ ":""}{it.icon} {it.l}</button>;})}<CustomAdd placeholder="自定义需求" onAdd={v=>setIntents(p=>[...p,v])} color={C.peri}/></div></div>{/* 文本框 */}<Cd s={{marginBottom:8}}><textarea value={inp} onChange={e=>setInp(e.target.value)} placeholder={"粘贴聊天记录，或直接描述...\n\n例如：TA已读不回两天了，之前聊得很好"} style={{width:"100%",minHeight:80,padding:0,background:"transparent",border:"none",color:C.t1,fontSize:14,outline:"none",resize:"none",lineHeight:1.7,fontFamily:font}}/><div style={{display:"flex",justifyContent:"space-between",marginTop:4,paddingTop:4,borderTop:`1px solid ${C.bdL}`}}><div style={{display:"flex",gap:4}}><BreathingMic id="deep" st={st} onText={t=>setInp(p=>p+t)} onImg={e=>{const f=e.target?.files?.[0];if(f)st("📷 图片已添加");}}/></div><span style={{fontSize:9,color:C.t3}}>{inp.length} 字</span></div></Cd><InputToolbar vault={vault} onPaste={t=>setInp(t)} st={st}/>{/* 补充信息滑块 */}<button className="tap2" onClick={()=>setShowSliders(p=>({...p,ctx:!p?.ctx}))} style={{width:"100%",padding:"6px 10px",borderRadius:8,background:"transparent",border:`1px solid ${C.bd}`,color:C.t3,fontSize:10,cursor:"pointer",marginBottom:6,textAlign:"left"}}>📊 补充信息（可选，提升准确度）{showSliders?.ctx?" ▲":" ▼"}</button>{showSliders?.ctx&&<DkCd s={{marginBottom:8,padding:"10px 12px"}}>{CTX_SLIDERS.map(s=><div key={s.k} style={{marginBottom:6}}><div style={{display:"flex",justifyContent:"space-between",fontSize:9,color:"#b090a0"}}><span>{s.l}</span><span style={{color:s.c,fontWeight:700}}>{ctxData[s.k]}</span></div><input type="range" min={0} max={10} value={ctxData[s.k]} onChange={e=>setCtxData(p=>({...p,[s.k]:+e.target.value}))} style={{width:"100%",accentColor:s.c}}/></div>)}<div style={{fontSize:9,color:"#b090a0",marginTop:4}}>回复延迟</div><div style={{display:"flex",gap:4,marginTop:3}}>{REPLY_DELAYS.map(d=><button key={d} className="tap2" onClick={()=>setReplyDelay(d)} style={{padding:"3px 8px",borderRadius:6,fontSize:9,background:replyDelay===d?`${C.peri}12`:"rgba(255,255,255,.05)",border:`1px solid ${replyDelay===d?C.peri+"40":"rgba(255,255,255,.1)"}`,color:replyDelay===d?C.peri:"#b090a0",cursor:"pointer"}}>{d}</button>)}</div></DkCd>}{/* 两个直接按钮 */}<div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}><button className="tap" onClick={()=>{if(!inp.trim()){st("请先输入内容");return;}setMode("full");setPhase("loading");setResult(null);setExtra(null);setChecked({});setMoreN({});setReportTab("summary");setTimeout(()=>{const t=inp.toLowerCase();const r=t.match(/分手|放手|结束|放弃|不要我|离开/)?_bp():t.match(/吵架|冷战|冲突|生气|发脾气|骂|指责|翻旧账/)?_cf():t.match(/不回|已读|冷淡|变冷|消失|不理|躲|拉黑|忽冷忽热/)?_cd():t.match(/暧昧|推进|表白|喜欢|追|在一起|确认关系|约会/)?_ad():_dl();setResult(r);setPhase("report");st("✅ 分析完成");},500);}} disabled={!inp.trim()} style={{padding:"16px 8px",borderRadius:18,background:inp.trim()?`linear-gradient(135deg,${C.peri},${C.pink})`:C.bg3,border:"none",color:inp.trim()?"#fff":C.t3,fontSize:14,fontWeight:800,cursor:inp.trim()?"pointer":"default"}}>⚡ 开始诊断</button><button className="tap" onClick={()=>{if(!inp.trim()){st("请先输入内容");return;}setMode("quick");setPhase("loading");setResult(null);setChecked({});setMoreN({});setTimeout(()=>{const t=inp.toLowerCase();const r=t.match(/分手|放手|结束|放弃|不要我|离开/)?_bp():t.match(/吵架|冷战|冲突|生气|发脾气|骂|指责|翻旧账/)?_cf():t.match(/不回|已读|冷淡|变冷|消失|不理|躲|拉黑|忽冷忽热/)?_cd():t.match(/暧昧|推进|表白|喜欢|追|在一起|确认关系|约会/)?_ad():_dl();const k=t.match(/分手|放手|结束/)?"breakup":t.match(/吵架|冷战|冲突/)?"conflict":t.match(/不回|已读|冷淡/)?"cold":t.match(/暧昧|推进|表白/)?"advance":"daily";const qa={breakup:["等你准备好了随时找我","不打扰就是想说一声","最近还好吗","看到这个想到你了"],conflict:["语气重了对不起","我不想赢想要我们好","我在反思","准备好了我们再聊"],cold:["看到好玩的分享给你不用回","分享最近循环的歌","天气好适合出去走走","天冷了多穿点"],advance:["跟你聊天时间特别快","聊完心情都变好","你笑起来特别好看","越了解越有意思你就是"],daily:["想你了","今天因为你很开心","谢谢你一直在","你笑的时候真好看"]};const qb={breakup:["最近开始学了挺有意思","路过想起你说过喜欢","分享一首歌","天气变了注意保暖"],conflict:["看到个好笑的分享给你","你最近辛苦了","不提那件事了聊点开心的","周末一起走走？"],cold:["学了新东西挺有意思","发现你可能喜欢的地方","试了一家新的挺好吃","路过你说过想去的地方"],advance:["周末有个活动你有兴趣吗","经过你附近要不要喝杯咖啡","发现一个适合你的地方","这周末有个有意思的一起看看"],daily:["好久没一起做了这周试试","发现你一定会喜欢的地方","你有什么想去的吗我安排","一起试试怎么样"]};setResult({quickA:qa[k],quickB:qb[k],mainScript:r.mainScript,why:r.thisRoundGoal,risk:r.risk});setPhase("report");st("✅ 生成完成");},500);}} disabled={!inp.trim()} style={{padding:"16px 8px",borderRadius:18,background:inp.trim()?`linear-gradient(135deg,${C.teal},${C.teal}cc)`:C.bg3,border:"none",color:inp.trim()?"#fff":C.t3,fontSize:14,fontWeight:800,cursor:inp.trim()?"pointer":"default"}}>💬 只要下一句</button></div><div style={{textAlign:"center",marginTop:4,fontSize:8,color:C.t3}}>🔒 本地分析 · 不联网 · 0.6秒出结果</div></div></div>)}
function DeepLoadingPhase(_p){const{analyzing,checked,ctxData,expandedEng,expandedMod,expertAutoMode,extra,extraLd,font,inp,intents,mode,pipeStep,replyDelay,reportTab,reset,result,setChecked,setCtxData,setExpandedEng,setExpandedMod,setExpertAutoMode,setExtra,setInp,setIntents,setMode,setPhase,setReplyDelay,setReportTab,setResult,setShowModulesInReport,setShowSliders,setShowTriCore,showModulesInReport,showSliders,showTriCore,st,vault}=_p;return(<div style={{paddingBottom:100}}><SubHeader onBack={reset} title="⏳ 诊断中..."/><div style={{textAlign:"center",padding:"40px 20px"}}><div style={{fontSize:40,animation:"breathe 2s infinite"}}>🔮</div><div style={{fontSize:14,fontWeight:700,color:C.peri,marginTop:10}}>20年资深专家正在分析...</div><PipelineProgress step={pipeStep} active={analyzing}/><div style={{fontSize:10,color:C.t3,marginTop:8,textAlign:"center"}}>💡 {expertAutoMode?"专家模式：自动选择最佳理论组合":"手动模式：使用你选择的模块"}</div><Dots/></div></div>)}
function DeepReportPhase(_p){const{analyzing,checked,ctxData,expandedEng,expandedMod,expertAutoMode,extra,extraLd,font,inp,intents,mode,pipeStep,replyDelay,reportTab,reset,result,setChecked,setCtxData,setExpandedEng,setExpandedMod,setExpertAutoMode,setExtra,setInp,setIntents,setMode,setPhase,setReplyDelay,setReportTab,setResult,setShowModulesInReport,setShowSliders,setShowTriCore,showModulesInReport,showSliders,showTriCore,st,vault}=_p;if(!result)return null;return(<div style={{paddingBottom:100}}>{expertAutoMode&&<div style={{margin:"8px 14px",padding:"8px 12px",borderRadius:10,background:`${C.peri}06`,border:`1px solid ${C.peri}15`,display:"flex",alignItems:"center",justifyContent:"space-between"}}><div style={{display:"flex",alignItems:"center",gap:6}}><span style={{fontSize:14}}>🤖</span><div><div style={{fontSize:11,fontWeight:700,color:C.peri}}>专家自动报告</div><div style={{fontSize:9,color:C.t3}}>AI自动选择最佳理论组合 · {result.usedModules?.length||5}个模块</div></div></div><button className="tap2" onClick={()=>setShowModulesInReport(!showModulesInReport)} style={{padding:"3px 10px",borderRadius:8,fontSize:9,fontWeight:600,background:showModulesInReport?`${C.peri}15`:"transparent",color:showModulesInReport?C.peri:C.t3,border:`1px solid ${showModulesInReport?C.peri+"30":"transparent"}`,cursor:"pointer"}}>{showModulesInReport?"隐藏参考角度":"查看参考角度"}</button></div>}{showModulesInReport&&result.usedModules&&<div style={{margin:"4px 14px",padding:"6px 10px",borderRadius:8,background:C.bg,display:"flex",gap:4,flexWrap:"wrap"}}>{result.usedModules.map((m,i)=><Badge key={i} color={C.peri}>{m}</Badge>)}</div>}<div style={{padding:"12px 16px",display:"flex",alignItems:"center",gap:10,background:C.glass,backdropFilter:"blur(20px)",position:"sticky",top:0,zIndex:50,borderBottom:`1px solid ${C.bd}`}}><button className="tap2" onClick={reset} style={{background:C.pinkBg,border:"none",borderRadius:10,width:32,height:32,color:C.pink,fontSize:14,cursor:"pointer"}}>←</button><div style={{fontSize:15,fontWeight:700}}>📋 专家报告</div></div><div style={{padding:"8px 16px"}}>{mode==="quick"&&result.quickA&&!result.verdict?<div style={{animation:"fadeUp .3s"}}>{result.why&&<DkCd s={{marginBottom:10,padding:"10px 14px"}}><div style={{fontSize:10,color:"#b090a0"}}>💡 策略</div><div style={{fontSize:12,color:"#e8d5df",lineHeight:1.6}}>{result.why}</div></DkCd>}<div style={{marginBottom:10}}><div style={{fontSize:11,fontWeight:700,color:C.teal,marginBottom:6}}>💬 低压信号</div>{result.quickA.map((s,i)=><div key={"a"+i} className="tap" onClick={()=>{navigator.clipboard?.writeText(s);st("已复制 🌸");}} style={{display:"flex",justifyContent:"space-between",alignItems:"center",gap:8,padding:"10px 14px",marginBottom:4,borderRadius:12,background:"rgba(30,20,28,.92)",border:"1px solid rgba(139,90,120,.2)",cursor:"pointer"}}><div style={{fontSize:13,color:"#ffb7c5",lineHeight:1.6}}>「{s}」</div><span style={{fontSize:9,color:C.teal,flexShrink:0}}>📋</span></div>)}</div><div style={{marginBottom:10}}><div style={{fontSize:11,fontWeight:700,color:C.peri,marginBottom:6}}>🌱 进阶话术</div>{result.quickB.map((s,i)=><div key={"b"+i} className="tap" onClick={()=>{navigator.clipboard?.writeText(s);st("已复制 🌸");}} style={{display:"flex",justifyContent:"space-between",alignItems:"center",gap:8,padding:"10px 14px",marginBottom:4,borderRadius:12,background:"rgba(30,20,28,.92)",border:"1px solid rgba(139,90,120,.2)",cursor:"pointer"}}><div style={{fontSize:13,color:"#e8d5df",lineHeight:1.6}}>「{s}」</div><span style={{fontSize:9,color:C.peri,flexShrink:0}}>📋</span></div>)}</div><div style={{display:"flex",gap:8,marginTop:12}}><Btn onClick={()=>{setMode("full");reset();}} s={{background:C.bg}}>🎯 完整报告</Btn><Btn primary onClick={reset} color={C.peri}>🔄 换个问题</Btn></div></div>:<><div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:0,marginBottom:10,borderRadius:12,overflow:"hidden",background:C.bg}}>{[{id:"summary",l:"📋 总报告"},{id:"modules",l:`🧩 模块分析（${result.moduleCards?.length||0}）`}].map(tb=><button key={tb.id} onClick={()=>setReportTab(tb.id)} style={{padding:"10px",border:"none",cursor:"pointer",fontSize:11,fontWeight:reportTab===tb.id?700:500,background:reportTab===tb.id?C.white:"transparent",color:reportTab===tb.id?C.peri:C.t3}}>{tb.l}</button>)}</div>{reportTab==="summary"&&<div><DkCd s={{marginBottom:10}}><div style={{fontSize:9,color:"#b090a0",marginBottom:3}}>📋 专家总报告</div><div style={{fontSize:11,fontWeight:800,color:"#ffb7c5",lineHeight:1.5,marginBottom:6}}>{result.verdict}</div><div style={{display:"flex",gap:5,flexWrap:"wrap"}}>{result.risk&&<Badge color={result.risk==="high"?C.danger:result.risk==="med"?C.warn:C.safe}>{result.risk==="high"?"⚠️高风险":"✅较安全"}</Badge>}{result.herseyS&&<Badge color={C.peri}>档位 {result.herseyS}</Badge>}{result.usedModules?.map((m,i)=><Badge key={i} color={C.teal}>{m}</Badge>)}</div></DkCd>{result.situation&&<DkCd s={{marginBottom:8}}><div style={{fontSize:10,fontWeight:600,color:"#b090a0",marginBottom:3}}>💬 现状分析</div><div style={{fontSize:12,color:"#e8d5df",lineHeight:1.7,whiteSpace:"pre-line"}}>{result.situation}</div></DkCd>}{result.rootCause&&<DkCd s={{marginBottom:8,borderLeft:`3px solid ${C.warn}`}}><div style={{fontSize:10,fontWeight:600,color:C.warn,marginBottom:3}}>🔴 卡点</div><div style={{fontSize:12,color:"#e8d5df",lineHeight:1.7}}>{result.rootCause}</div></DkCd>}{result.thisRoundGoal&&<DkCd s={{marginBottom:8,borderLeft:`3px solid ${C.teal}`}}><div style={{fontSize:10,fontWeight:600,color:C.teal,marginBottom:3}}>🎯 目标</div><div style={{fontSize:12,color:"#e8d5df",lineHeight:1.7}}>{result.thisRoundGoal}</div></DkCd>}{result.herseyS&&<DkCd s={{marginBottom:10}}><div style={{fontSize:10,fontWeight:700,color:"#ffb7c5",marginBottom:4,textAlign:"center"}}>📊 Hersey</div><div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:4,marginBottom:8}}>{["S3","S2","S4","S1"].map(s=>{const h=HERSEY[s];const on=result.herseyS===s;return <div key={s} style={{padding:"4px 3px",borderRadius:6,textAlign:"center",background:on?`${C.peri}15`:"rgba(255,255,255,.03)",border:on?`2px solid ${C.peri}60`:"1px solid rgba(255,255,255,.06)",opacity:on?1:.35}}><div style={{fontSize:16,fontWeight:800,color:on?"#ffb7c5":"#b090a0"}}>{s}</div><div style={{fontSize:10,fontWeight:600,color:on?"#e8d5df":"#b090a0"}}>{h.l}</div><div style={{fontSize:7,color:"#b090a0"}}>{h.sub}</div></div>;})}</div><div style={{display:"grid",gridTemplateColumns:"repeat(4,1fr)",gap:2,marginBottom:4}}>{RM.map(r=>{const on=result.herseyS===r.to;return <div key={r.id} style={{padding:"2px 1px",borderRadius:4,textAlign:"center",background:on?`${C.peri}12`:"rgba(255,255,255,.03)",border:on?`1.5px solid ${C.peri}40`:"1px solid rgba(255,255,255,.06)"}}><div style={{fontSize:11,fontWeight:800,color:on?C.peri:"#b090a0"}}>{r.id}</div><div style={{fontSize:7,color:"#b090a0"}}>{r.l}</div></div>;})}</div>{HERSEY[result.herseyS]&&<div style={{padding:"8px 10px",borderRadius:8,background:`${C.peri}08`}}><div style={{fontSize:10,fontWeight:700,color:C.peri,marginBottom:3}}>🎯 恋爱中的 {result.herseyS}</div><div style={{fontSize:10,color:"#e8d5df",lineHeight:1.6}}>{HERSEY[result.herseyS].love}</div><div style={{fontSize:10,color:C.peri,fontStyle:"italic",marginTop:3}}>{HERSEY[result.herseyS].ex}</div></div>}</DkCd>}{result.horsemen?.detected?.length>0&&<DkCd s={{marginBottom:10}}><div style={{fontSize:11,fontWeight:700,color:C.danger,marginBottom:6}}>⚔️ Gottman四骑士</div>{result.horsemen.detected.map((h,i)=>{const hm=HORSEMEN.find(x=>h.includes(x.name));return <div key={i} style={{padding:"5px 8px",background:"rgba(255,255,255,.03)",borderRadius:6,marginBottom:3}}><div style={{fontSize:11,fontWeight:600,color:C.danger}}>{hm?.icon||"⚔️"} {h}</div>{hm&&<div style={{fontSize:9,color:C.teal}}>💊 {hm.antidote}</div>}</div>;})}{typeof result.horsemen.breakupRisk==="number"&&<div style={{fontSize:9,color:C.danger,marginTop:4}}>分手风险 {result.horsemen.breakupRisk}%</div>}</DkCd>}{result.reasons?.length>0&&<DkCd s={{marginBottom:10}}><div style={{fontSize:10,fontWeight:600,color:"#ffb7c5",marginBottom:4}}>📊 为什么这样判断</div>{result.reasons.slice(0,(moreN["why"]||5)).map((r,i)=><div key={i} style={{fontSize:11,color:"#e8d5df",lineHeight:1.7,marginBottom:2}}>• {r}</div>)}<More k="why" arr={result.reasons} mx={10}/></DkCd>}{result.dos?.length>0&&<DkCd s={{marginBottom:10}}><div style={{display:"flex",justifyContent:"space-between",marginBottom:4}}><span style={{fontSize:10,fontWeight:600,color:C.peri}}>🎯 怎么做（{result.dos.length}条）</span><span style={{fontSize:9,color:"#b090a0"}}>勾选采纳</span></div>{result.dos.slice(0,(moreN["dos"]||5)).map((d,i)=><ChkItem key={"d"+i} text={d} checked={checked["d:"+i]} onToggle={()=>tgl("d:"+i)} color={C.peri} prefix={`${i+1}.`} st={st}/>)}<More k="dos" arr={result.dos} mx={30}/></DkCd>}{result.mainScript&&<DkCd s={{marginBottom:10}}><div style={{fontSize:10,color:"#b090a0",marginBottom:4}}>💬 第一句话 · 直接复制发送</div><div style={{display:"flex",justifyContent:"space-between",gap:6}}><div style={{fontSize:15,fontWeight:700,color:"#ffb7c5",lineHeight:1.8}}>「{result.mainScript}」</div><CB text={result.mainScript} st={st}/></div></DkCd>}{result.says?.length>0&&<DkCd s={{marginBottom:10}}><div style={{display:"flex",justifyContent:"space-between",marginBottom:4}}><span style={{fontSize:10,fontWeight:600,color:C.teal}}>🎙 完整话术库（{result.says.length}句）· 按场景选用</span></div>{result.says.slice(0,(moreN["says"]||5)).map((s,i)=><ChkItem key={"s"+i} text={`「${s}」`} checked={checked["s:"+i]} onToggle={()=>tgl("s:"+i)} color={C.teal} st={st}/>)}<More k="says" arr={result.says} mx={50}/></DkCd>}{result.scriptBranches&&<DkCd s={{marginBottom:10}}><div style={{fontSize:10,fontWeight:600,color:"#b090a0",marginBottom:4}}>🔀 对方反应 → 你怎么接</div>{[["😊 积极回应",result.scriptBranches.positive],["😐 冷淡/敷衍",result.scriptBranches.cold],["🔇 已读不回",result.scriptBranches.noReply],["😤 发火/敌意",result.scriptBranches.angry]].filter(([,v])=>v).map(([l,t],i)=><div key={i} style={{padding:"5px 8px",borderRadius:6,background:"rgba(255,255,255,.03)",marginBottom:3}}><div style={{fontSize:9,fontWeight:600,color:"#b090a0"}}>{l}</div><div style={{fontSize:11,color:"#e8d5df",lineHeight:1.6}}>{t}</div></div>)}</DkCd>}{result.avoid?.length>0&&<DkCd s={{marginBottom:10}}><div style={{display:"flex",justifyContent:"space-between",marginBottom:4}}><span style={{fontSize:10,fontWeight:600,color:C.danger}}>⚠️ 避坑（{result.avoid.length}条）</span><span style={{fontSize:9,color:"#b090a0"}}>勾选你容易犯的</span></div>{result.avoid.slice(0,(moreN["avoid"]||5)).map((a,i)=><ChkItem key={"a"+i} text={a} checked={checked["a:"+i]} onToggle={()=>tgl("a:"+i)} color={C.danger} prefix="❌"/>)}<More k="avoid" arr={result.avoid} mx={15}/></DkCd>}{result.weekPlan?.length>0&&<DkCd s={{marginBottom:10}}><div style={{fontSize:11,fontWeight:700,color:C.teal,marginBottom:6}}>📅 7天行动计划</div>{result.weekPlan.map((d,i)=><div key={i} style={{padding:"8px 10px",borderRadius:8,background:"rgba(255,255,255,.03)",marginBottom:5,borderLeft:`2px solid ${C.teal}30`}}><div style={{fontSize:11,fontWeight:800,color:C.teal}}>{d.day} {d.title||""}</div><div style={{fontSize:11,color:"#e8d5df",lineHeight:1.6}}>{d.task}</div>{d.goal&&<div style={{fontSize:9,color:C.safe}}>✅ 达标：{d.goal}</div>}</div>)}</DkCd>}<DkCd s={{marginBottom:10}}><div style={{fontSize:10,color:"#b090a0",marginBottom:6}}>📬 发完后回填</div><div style={{display:"flex",flexWrap:"wrap",gap:4}}>{FEEDBACK_BTNS.map(fb=><button key={fb.tone} className="tap2" onClick={()=>st("已记录："+fb.label)} style={{padding:"5px 10px",borderRadius:8,background:"rgba(255,255,255,.03)",border:"1px solid rgba(255,255,255,.08)",color:"#e8d5df",fontSize:10,cursor:"pointer"}}>{fb.icon} {fb.label}</button>)}</div></DkCd>{!extra&&!extraLd&&<Btn primary color={C.violet} onClick={doExpand} s={{marginBottom:10}}>🔮 展开更多</Btn>}{extraLd&&<Dots/>}{extra&&<div>{extra.deepWhy?.length>0&&<DkCd s={{marginBottom:8}}><div style={{fontSize:10,fontWeight:600,color:"#ffb7c5",marginBottom:4}}>🧠 深层原因</div>{extra.deepWhy.map((w,i)=><div key={i} style={{fontSize:11,color:"#e8d5df",lineHeight:1.7}}>• {w}</div>)}</DkCd>}{extra.extraDos?.length>0&&<DkCd s={{marginBottom:8}}><div style={{fontSize:10,fontWeight:600,color:C.peri,marginBottom:4}}>🎯 补充怎么做</div>{extra.extraDos.map((d,i)=><ChkItem key={"ed"+i} text={d} checked={checked["ed:"+i]} onToggle={()=>tgl("ed:"+i)} color={C.peri} st={st}/>)}</DkCd>}{extra.extraSays?.length>0&&<DkCd s={{marginBottom:8}}><div style={{fontSize:10,fontWeight:600,color:C.teal,marginBottom:4}}>💬 补充话术</div>{extra.extraSays.map((s,i)=><ChkItem key={"es"+i} text={`「${s}」`} checked={checked["es:"+i]} onToggle={()=>tgl("es:"+i)} color={C.teal} st={st}/>)}</DkCd>}{extra.extraAvoid?.length>0&&<DkCd s={{marginBottom:8}}><div style={{fontSize:10,fontWeight:600,color:C.danger,marginBottom:4}}>⚠️ 补充避坑</div>{extra.extraAvoid.map((a,i)=><ChkItem key={"ea"+i} text={a} checked={checked["ea:"+i]} onToggle={()=>tgl("ea:"+i)} color={C.danger} prefix="❌"/>)}</DkCd>}</div>}{/* ═══ Advanced Analysis Panels ═══ */}<div style={{marginTop:12,marginBottom:12}}><button className="tap2" onClick={()=>setShowTriCore(!showTriCore)} style={{width:"100%",padding:"10px 14px",borderRadius:12,background:showTriCore?`${C.peri}10`:C.bg,border:`1px solid ${showTriCore?C.peri+"25":C.bd}`,cursor:"pointer",display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:6}}><span style={{fontSize:12,fontWeight:700,color:C.t1}}>💠 高级分析面板</span><span style={{fontSize:10,color:C.t3}}>{showTriCore?"▲ 收起":"▼ 展开"}</span></button>{showTriCore&&<div style={{animation:"fadeUp .2s"}}><TriCorePanel scores={{intimacy:result.herseyS==="S4"?75:result.herseyS==="S3"?60:result.herseyS==="S2"?45:30,passion:result.herseyS==="S3"?70:result.herseyS==="S4"?55:40,commitment:result.herseyS==="S4"?80:result.herseyS==="S2"?50:35}} st={st}/><RiskDetailPanel level={result.herseyS==="S1"?"high":result.herseyS==="S2"?"med":"low"}/>{result.moduleCards?.map((mc,i)=><div key={i} style={{marginTop:6}}><button className="tap2" onClick={()=>setExpandedMod(expandedMod===mc.id?null:mc.id)} style={{width:"100%",padding:"6px 10px",borderRadius:8,background:expandedMod===mc.id?`${C.peri}08`:C.bg,border:`1px solid ${expandedMod===mc.id?C.peri+"20":C.bdL}`,cursor:"pointer",textAlign:"left",fontSize:10,fontWeight:600,color:C.t1}}>{mc.icon} {mc.name} — 帮助详情 {expandedMod===mc.id?"▲":"▼"}</button>{expandedMod===mc.id&&<ModHelpPanel mod={mc}/>}</div>)}{ENGINES.slice(0,3).map((eng,i)=><div key={i} style={{marginTop:6}}><button className="tap2" onClick={()=>setExpandedEng(expandedEng===eng.id?null:eng.id)} style={{width:"100%",padding:"6px 10px",borderRadius:8,background:expandedEng===eng.id?`${C.teal}08`:C.bg,border:`1px solid ${expandedEng===eng.id?C.teal+"20":C.bdL}`,cursor:"pointer",textAlign:"left",fontSize:10,fontWeight:600,color:C.t1}}>⚙️ {eng.name} — 引擎详情 {expandedEng===eng.id?"▲":"▼"}</button>{expandedEng===eng.id&&<EngDetailPanel eng={eng}/>}</div>)}</div>}</div><div style={{display:"flex",gap:8}}><button className="tap" onClick={()=>{let t="🧬报告\n"+result.verdict;result.dos?.forEach((d,i)=>{t+="\n"+(i+1)+". "+d;});if(result.mainScript)t+="\n\n💬 "+result.mainScript;navigator.clipboard?.writeText(t);st("已复制📋");}}style={{flex:1,padding:"12px",borderRadius:12,background:`${C.peri}10`,border:`1px solid ${C.peri}20`,color:C.peri,fontSize:12,fontWeight:700,cursor:"pointer"}}>📋 复制报告</button><button className="tap" onClick={reset} style={{padding:"12px 16px",borderRadius:12,background:C.bg,border:`1px solid ${C.bd}`,color:C.t2,fontSize:12,cursor:"pointer"}}>🔄 重来</button></div></div>}{/* Modules tab */}{reportTab==="modules"&&<div><DkCd s={{marginBottom:10,padding:"10px 14px",background:"rgba(30,20,28,.85)"}}><div style={{fontSize:11,fontWeight:700,color:C.peri,marginBottom:4}}>🧩 多角度专家分析（{result.moduleCards?.length||0}个模块）</div><div style={{fontSize:10,color:"#b090a0",lineHeight:1.6,marginBottom:6}}>系统根据你描述中的关键信号自动匹配了最相关的心理学模块。每个模块由不同理论框架切入——相当于{result.moduleCards?.length||0}位不同领域的专家同时会诊。</div><div style={{display:"flex",gap:4,flexWrap:"wrap"}}>{result.usedModules?.map((m,i)=><Badge key={i} color={C.teal}>{m}</Badge>)}</div></DkCd>{result.moduleCards?.length>0?result.moduleCards.map((mc,mi)=><DkCd key={mi} s={{marginBottom:10}}><div style={{display:"flex",alignItems:"center",gap:8,marginBottom:4}}><div className="tap2" onClick={()=>tgl("mc:"+mi)} style={{width:22,height:22,borderRadius:11,border:`1.5px solid ${checked["mc:"+mi]?C.peri:C.bd}`,background:checked["mc:"+mi]?`${C.peri}15`:"transparent",display:"flex",alignItems:"center",justifyContent:"center",fontSize:11,color:C.peri,cursor:"pointer"}}>{checked["mc:"+mi]?"✓":""}</div><Badge color={C.peri}>Module {mi+1}</Badge><span style={{fontSize:13,fontWeight:700,color:"#e8d5df"}}>{mc.module}</span><Badge color={C.teal}>置信{mc.confidence==="high"?"高":"中"}</Badge></div><div style={{fontSize:9,color:C.peri,marginBottom:6,padding:"3px 8px",borderRadius:6,background:`${C.peri}08`,display:"inline-block"}}>🔗 为什么触发：你的描述中包含了该模块的核心信号词</div><div style={{fontSize:12,color:"#e8d5df",lineHeight:1.7,marginBottom:8}}>📌 {mc.diag}</div><button className="tap2" onClick={()=>setMoreN(p=>({...p,["mc:"+mi]:!p["mc:"+mi]}))} style={{padding:"8px 16px",borderRadius:8,background:`${C.peri}08`,border:`1px solid ${C.peri}15`,color:C.peri,fontSize:11,cursor:"pointer",fontWeight:600,width:"100%"}}>{moreN["mc:"+mi]?"▲ 收起详细报告":"▼ 展开完整报告（原因+怎么做+怎么说+避坑）"}</button>{moreN["mc:"+mi]&&<div style={{marginTop:10,borderTop:"1px solid rgba(255,255,255,.06)",paddingTop:10}}>{mc.whys?.length>0&&<div style={{marginBottom:8}}><div style={{fontSize:10,fontWeight:600,color:"#ffb7c5",marginBottom:4}}>📊 为什么</div>{mc.whys.map((w,i)=><div key={i} style={{fontSize:11,color:"#e8d5df",lineHeight:1.7}}>• {w}</div>)}</div>}{mc.dos?.length>0&&<div style={{marginBottom:8}}><div style={{fontSize:10,fontWeight:600,color:C.peri,marginBottom:4}}>🎯 怎么做</div>{mc.dos.slice(0,(moreN["mcd:"+mi]||5)).map((d,i)=><ChkItem key={"d"+i} text={d} checked={checked["mc"+mi+"d:"+i]} onToggle={()=>tgl("mc"+mi+"d:"+i)} color={C.peri} prefix={`${i+1}.`} st={st}/>)}<More k={"mcd:"+mi} arr={mc.dos} mx={15}/></div>}{mc.says?.length>0&&<div style={{marginBottom:8}}><div style={{fontSize:10,fontWeight:600,color:C.teal,marginBottom:4}}>💬 怎么说</div>{mc.says.slice(0,(moreN["mcs:"+mi]||5)).map((s,i)=><ChkItem key={"s"+i} text={`「${s}」`} checked={checked["mc"+mi+"s:"+i]} onToggle={()=>tgl("mc"+mi+"s:"+i)} color={C.teal} st={st}/>)}<More k={"mcs:"+mi} arr={mc.says} mx={15}/></div>}{mc.pitfalls?.length>0&&<div><div style={{fontSize:10,fontWeight:600,color:C.danger,marginBottom:4}}>⚠️ 避坑</div>{mc.pitfalls.slice(0,(moreN["mcp:"+mi]||5)).map((p,i)=><ChkItem key={"p"+i} text={p} checked={checked["mc"+mi+"p:"+i]} onToggle={()=>tgl("mc"+mi+"p:"+i)} color={C.danger} prefix="❌"/>)}<More k={"mcp:"+mi} arr={mc.pitfalls} mx={15}/></div>}</div>}</DkCd>):<div style={{textAlign:"center",padding:"16px 14px",color:C.t3,fontSize:11,lineHeight:1.6,background:`${C.peri}05`,borderRadius:12,margin:"8px 0"}}><div style={{fontSize:16,marginBottom:6}}>💡</div><div style={{fontWeight:700,color:C.t2,marginBottom:4}}>当前是「秒诊断」模式</div><div>若要看完整 6 模块心理学分析（Knapp / Gottman / 依恋 / Sternberg / Rusbult + 场景专属），请切换到「完整诊断」模式重新分析。</div><button className="tap2" onClick={()=>{setMode("full");setPhase("input");setResult(null);}} style={{marginTop:10,padding:"8px 16px",borderRadius:10,border:`1.5px solid ${C.peri}`,background:"transparent",color:C.peri,fontSize:11,fontWeight:700,cursor:"pointer"}}>🔬 切换到完整诊断</button></div>}</div>}</>}</div></div>);}
/* ═════════════ P3: 深度解析 (FULL) ═══════════════════/* ═════════════ P3: 深度解析 (对标情境恋爱fix 4页) ═══════════════════/* ═════════════ P3: 深度解析 (CLEAN REWRITE) ═══════════════════ */
function DeepTab({stageId,personaId,profile,st,vault,onNavigateGame}){const[phase,setPhase]=useState("input");const[inp,setInp]=useState("");const[mode,setMode]=useState("full");const[autoTheory,setAutoTheory]=useState(true);const[pipeStep,setPipeStep]=useState(-1);const[showTriCore,setShowTriCore]=useState(false);const[expandedMod,setExpandedMod]=useState(null);const[expandedEng,setExpandedEng]=useState(null);const[expertAutoMode,setExpertAutoMode]=useState(true);const[analyzing,setAnalyzing]=useState(false);const[showModulesInReport,setShowModulesInReport]=useState(false);const[intents,setIntents]=useState([]);const[ctxData,setCtxData]=useState({intimacy:5,spark:5,myCommit:5,taCommit:5,satisfaction:5,alternatives:3});const[replyDelay,setReplyDelay]=useState("未知");const[result,setResult]=useState(null);const[checked,setChecked]=useState({});const[moreN,setMoreN]=useState({});const[reportTab,setReportTab]=useState("summary");useEffect(()=>{if(!analyzing){setPipeStep(-1);return;}setPipeStep(0);const t=setInterval(()=>setPipeStep(p=>p<5?p+1:p),500);return()=>clearInterval(t);},[analyzing]);const[extra,setExtra]=useState(null);const[extraLd,setExtraLd]=useState(false);const[modSel,setModSel]=useState("smart");const[manMods,setManMods]=useState([]);const[showSliders,setShowSliders]=useState({});const tgl=k=>setChecked(p=>({...p,[k]:!p[k]}));const more=(k,s=5,mx=50)=>setMoreN(p=>({...p,[k]:Math.min((p[k]||5)+s,mx)}));const reset=()=>{setPhase("input");setResult(null);setExtra(null);setChecked({});setMoreN({});};const More=({k,arr,mx=30})=>arr&&arr.length>(moreN[k]||5)?<button className="tap2" onClick={()=>more(k,5,mx)} style={{display:"block",margin:"6px auto",padding:"5px 16px",borderRadius:8,background:"rgba(30,20,28,.85)",border:`1px solid ${C.peri}20`,color:C.peri,fontSize:10,cursor:"pointer"}}>加载更多（还有{Math.min(arr.length,mx)-(moreN[k]||5)}条）</button>:null;const HERSEY={S1:{l:"告知式",sub:"引导·指示·建立",rel:"低关系·高指导",love:"TA关机→你主导给指令",ex:"「你现在不用想太多，先___就好」"},S2:{l:"推销式",sub:"劝服·解释·澄清",rel:"高关系·高指导",love:"TA有意愿但不知怎么做",ex:"「我觉得我们可以___，你觉得呢？」"},S3:{l:"参与式",sub:"鼓励·参与·解决问题",rel:"高关系·低指导",love:"TA有能力但犹豫→你支持",ex:"「你之前处理得很好，这次你决定就好」"},S4:{l:"授权式",sub:"观察·监控·信任",rel:"低关系·低指导",love:"TA自主有能力→你放手",ex:"「你安排就好，我配合你」"}};const RM=[{id:"R1",l:"没能力·没意愿",to:"S1"},{id:"R2",l:"没能力·有意愿",to:"S2"},{id:"R3",l:"有能力·没意愿",to:"S3"},{id:"R4",l:"有能力·有意愿",to:"S4"}];function _bp(){var v="你们吵完TA关机了——现在最重要的不是讲道理，是让TA愿意重新跟你说话。TA的情绪系统已经过载，就像电脑死机你怎么按开机键都没用，需要等它自己重启。";var si="你们之间发生了断裂。TA选择了沉默——这不是冷暴力，是情绪饱和后的自我保护机制。在Gottman研究中这叫石墙效应(Stonewalling)，是关系最危险的四骑士之一。\n\nTA现在的大脑处于战或逃模式。你发的每条消息每个解释每次道歉，在TA大脑里都被翻译成又一次攻击。不是你的内容有问题，是TA的接收系统暂时关闭了。\n\n但有一个好消息：TA没有拉黑你。这说明门还开着，只是很窄——你不能猛推，只能等它自己慢慢开。";var rc="问题的根源不在你们吵了什么——而在怎么吵的。回想一下：一方开始指责（你总是/你从来不）→另一方本能防御（那是因为你先...）→双方越说越激动→一方情绪超载选择关机。\n\n这个循环一旦启动说什么内容都没用——因为双方都在情绪的洪水里，前额叶（理性脑）已经被杏仁核（情绪脑）劫持了。";var gl="这一轮只有一个目标：让TA重新觉得跟你说话是安全的。不讨论对错、不翻旧账、不要求回应。当TA感到安全了沟通窗口才会重新打开。";return{verdict:v,situation:si,rootCause:rc,thisRoundGoal:gl,herseyS:"S1",usedModules:["成人依恋理论","Gottman冲突修复","Knapp关系阶梯","Hersey情境沟通","五种道歉语言","投入模型"],risk:"high",horsemen:{detected:["石墙 Stonewalling"],breakupRisk:72},reasons:["对方做出分开的决定前已经挣扎了很久——这不是冲动是积累的结果","TA现在的心理状态是观望+自我保护，任何表白式的话都会触发TA的防御","你需要以一个新的人出现——不是那个让TA失望过的人","分手后最先需要恢复的不是感情而是信任感和安全感","对方会通过观察你的行为（而非听你说什么）来判断你是否真的变了"],dos:["48小时内不主动联系——让TA的情绪系统从红色警报降回正常","先以朋友身份低压力接触2-3次观察TA是否主动延长互动","发朋友圈展示你在成长变好不@也不暗示","聊天只聊轻松日常绝不提我们以前复合","如果TA主动找你保持轻松回应但不过热","给自己制定一个30天自我提升计划并认真执行","每次互动控制在10-15分钟在最好的时刻结束意犹未尽","观察TA的朋友圈了解TA最近关注什么找共同话题","制造偶遇感在TA常去的地方不经意出现","学一项新技能或改变外在让TA眼前一亮","记录每次互动后TA的反应：更开放了还是更警惕了","如果连续3次互动TA都有正面回应可以尝试约线下","线下见面选你们没去过的新地方制造新记忆","整理之前关系中的问题想清楚你具体会怎么改","做一件之前TA一直想你做但你没做的事用行动证明"],mainScript:"等你准备好了，随时找我。",says:["等你准备好了随时找我","我尊重你的决定","最近还好吗","看到这个想到你了","不打扰就是想说一声","我在反思谢谢你的坦诚","路过想起你说过喜欢拍了张照","分享一首歌给你","最近开始学了挺有意思","你推荐的那个我终于去试了","天气变了注意保暖","看到好笑的想发给你","听说你最近在忙加油","我把之前那个坏习惯改了","不用回就是分享一下"],scriptBranches:{positive:"TA回了→轻松接住聊2-3句就收。不追问不表态。先聊日常至少3次好互动后再约见面。",cold:"TA冷淡→不追问过3天再发一条分享型消息。TA的冷淡是在测试你——通过测试的方式是不急。",noReply:"已读不回→不发第二条等一周再试。管住自己比什么话术都重要。",angry:"发火→不回怼不卑微。回一句我理解你生气然后给空间。TA的愤怒下面是受伤。"},avoid:["说给我一次机会——这是施压不是请求","翻旧账——TA的负面记忆会被激活","找TA朋友传话——TA会觉得被围攻","连续发消息——每多发一条压力+1","哭着打电话——情绪勒索会让TA更想逃","在社交媒体暗示你很痛苦","醉酒后打电话","用你欠我的施压","急于表白或承诺","否定TA分手的决定","通过朋友打听新对象","每天刷TA社交媒体","把复合当目标","用新对象刺激TA","在公开场合让TA尴尬"],weekPlan:[{day:"Day 1",title:"静默期",task:"什么都不做。不发消息不打电话不让朋友传话。运动/见朋友/写日记。",goal:"管住自己不联系"},{day:"Day 2",title:"破冰信号",task:"发一条不超15字的消息只表达我在。发完继续做自己的事。",goal:"信号发出没加多余的话"},{day:"Day 3",title:"观察期",task:"观察反应。已读未回→正常。回了嗯→好信号。没看→不追发。",goal:"无论什么反应都没过度反应"},{day:"Day 4",title:"分享日常",task:"发一条轻松生活分享。不提你们不暗示。展示我过得不错。",goal:"发了一条高质量内容"},{day:"Day 5",title:"温和试探",task:"有过回应→聊几句日常。没回应→不联系。",goal:"互动保持轻松"},{day:"Day 6",title:"评估",task:"本周TA态度有缓和吗？有主动信号吗？",goal:"做出理性判断"},{day:"Day 7",title:"下周方案",task:"好转→继续低压力互动。无变化→接受现实调整期待。",goal:"写出下周方案"}],moduleCards:[{module:"关系阶段诊断 (Knapp)",confidence:"high",diag:"根据Knapp关系阶梯模型你们正处于分化-停滞阶段。关系经历了断裂现在处于非常敏感的重建窗口期。对方没有完全拉黑说明心里还留着门但很窄用力推会关上。",whys:["TA挣扎很久才做出分开的决定","现在处于观望模式","需要以新的人出现","信任先于感情修复","TA在观察行为变化"],dos:["朋友身份低压力接触2-3次","发朋友圈展示成长","聊天只聊轻松日常","每次互动10-15分钟","连续3次正面回应约线下"],says:["好久没联系了想到你了","最近开始学了挺有意思","不用回就是分享","你推荐的我终于去试了","路过你说过想去的地方"],pitfalls:["急于表白","说我变了没证据","在朋友面前打听","发长消息回忆过去","问有没有新对象"]},{module:"依恋模式识别",confidence:"high",diag:"根据成人依恋理论分析对方目前处于回避激活状态。TA不是不在乎你而是亲密度超过了TA当前能舒服承受的上限。越追压力越大越想跑这是依恋系统的自动反应。",whys:["减少联系是重新充电而非逃避","越追TA压力越大越想跑","TA内心也想靠近但害怕脆弱","你的焦虑和TA的回避互相放大","打破循环只需要一个人先改变"],dos:["停止所有追问和催促","给对方48h完全自由空间","做让自己开心的事","匹配对方回复节奏","如果TA主动找你保持轻松"],says:["我也挺忙你忙完随时找我","看到好玩的发给你不用回","不打扰了有空再聊","如果你需要我随时都在","随便聊聊不聊也行"],pitfalls:["反复追问你怎么了","一天超3条未回复","去住处堵TA","让朋友帮打探","做极端举动逼回应"]},{module:"沟通策略选择 (Hersey)",confidence:"high",diag:"根据Hersey情境领导模型对方当前处于R1准备度（没能力也没意愿沟通）。匹配策略应为S1告知式：用最简短信号告诉TA我在但不施压。高指导+低关系——先降压再谈感情。",whys:["没有最好的沟通只有最匹配","R1→S1是正确匹配","准备度=能力x意愿","错误匹配代价大","准备度是动态的今天R1明天可能变R3"],dos:["严格选择S1策略","观察反应动态调整","先共情再提需求","用问句代替陈述句","一次只讨论一个问题"],says:["你现在不用想太多先___就好","不着急慢慢来","我在这里","想说的时候说不想说也没关系","我给你时间"],pitfalls:["关机时讲大道理","有情绪时讲逻辑","用你应该句式","不观察反应一直说","所有情况用同一方式"]},{module:"Gottman冲突修复",confidence:"high",diag:"Gottman研究发现关系中最致命的是四骑士：批评/蔑视/防御/石墙。分手场景中石墙效应已经激活——TA选择了沉默关闭沟通。修复需要从止损开始而非从讲道理开始。",whys:["石墙是四骑士中最危险的","情绪过载导致无法处理信息","修复尝试的成功率决定关系命运","冲突方式比内容重要100倍","软启动成功率96%"],dos:["不追着吵给TA重启时间","准备好不带指责的开场白","用我感觉开头不用你总是","承担你的部分哪怕只有10%","建立冲突暂停信号"],says:["我不追着你吵了等你准备好","那天是我的问题","不管怎样你对我重要","等你想聊随时找我","有些话想当面说"],pitfalls:["反复发消息轰炸","通过朋友传话施压","在社交媒体发暗示","用极端行为逼回应","在TA刚回应就倒情绪"]},{module:"Rusbult投入模型",confidence:"high",diag:"根据Rusbult投入模型关系承诺=满意度-替代选择+投入量。分手后双方都在重新计算这个等式——你需要提升TA对你的满意度预期同时让TA感受到之前投入的沉没成本。",whys:["承诺=满意度-替代+投入","TA在重新评估三个变量","高投入会让人不愿意离开","替代选择的存在感影响决定","满意度下降时投入高→选择修复"],dos:["展示你在改变来提升满意度预期","不要提你们投入了多少——让TA自己想起","让TA看到你的独特价值","不要主动提竞争者","用行动证明未来值得期待"],says:["我在认真改变你看我行动","我们一起经历了这么多","我想做得更好","你对我来说无可替代","我不想让我们白费了"],pitfalls:["用我们在一起这么久了施压","提对方没有更好选择","把投入当筹码","忽视对方的不满只强调投入","用物质弥补不改行为"]},{module:"自我边界重建",confidence:"high",diag:"分手不只是关系的终结,也是重建自我的窗口。此刻最重要的不是挽回,是恢复因失去而崩塌的自我感。急于和好往往是逃避,而非真实需要对方。",whys:["依恋系统发出失去警报但不是真爱信号","情感依附与真实爱情的本能混淆","孤独不等于失去爱","沉没成本效应(花了X时间不甘心)","怕重新开始的自我怀疑"],dos:["独自吃3次饭(测试孤独可以忍受吗)","重新联系3个月没联系的朋友","每天写3件我做的独立的事","屏蔽TA 2周所有社交账号","运动3次(多巴胺不靠关系获得)","问自己:如果永不见面,我的人生会差吗?"],says:["我现在不适合见面","我想先处理好自己","不是不在乎是太在乎","需要时间","我不能给你想要的回答"],pitfalls:["立刻删掉所有痕迹(也是一种不放下)","反复联系问为什么","用暧昧填补空缺(会更糟)","找共同朋友打听","用新恋情证明我更好"]}]};}function _cf(){var v="你们在情绪风暴中——现在最重要的是止损不是讲道理。TA选择关机不是不在乎是情绪系统超载到处理不了任何信息了。";var si="你们吵架之后TA选择了最极端的方式——直接关闭沟通。在Gottman研究中这叫石墙效应：当心率超过100次/分钟时前额叶（理性脑）会被杏仁核（情绪脑）劫持，TA字面意义上听不进去任何话了。\n\n你做的任何解释道歉追问在TA那里都会变成又来了又来了。不是你说的内容有问题是TA的接收系统暂时关闭了。";var rc="问题不在你们吵了什么而在怎么吵的。Gottman研究发现：关系是否能持续96%取决于冲突的前3分钟怎么开始。如果用'你总是/你从来不'开头（硬启动）几乎100%会升级。\n\n回想你们的循环：指责→防御反驳→越说越激动→情绪超载→关机。这个循环启动后内容根本不重要。";return{verdict:v,situation:si,rootCause:rc,thisRoundGoal:"让TA重新觉得跟你说话是安全的。不讨论对错不翻旧账不要求回应。",herseyS:"S2",usedModules:["Gottman冲突修复","成人依恋理论","Hersey情境沟通","五种道歉语言"],risk:"med",horsemen:{detected:["批评 Criticism","防御 Defensiveness"],breakupRisk:45},reasons:["吵架时用了你总是你从来不——这是Gottman定义的批评四骑士","防御反应让双方都觉得对方不听——形成互相攻击的死循环","冷战是石墙效应——情绪过载后的自我保护不是惩罚","问题在怎么吵不在吵什么——沟通模式比内容重要100倍","冲突后最先需要修复的是情绪安全感而非事实对错"],dos:["先承认TA的感受是真实的——不管你觉得有没有道理","用我感觉因为我希望格式——Gottman软启动原则","找一个小事先破冰——一杯水一个表情包一句不相关的日常","不急着解决问题先修复情绪——情绪不到位说什么都白搭","给彼此冷静时间但约定重启时间","承担你那部分责任哪怕只有10%——瞬间降低TA防御","在TA准备好之前不强迫沟通","写下想说的话但不现在发——等情绪过去再看","回忆触发点下次避开找到引爆按钮","主动做一件TA一直想你做的事——用行动代替语言","约定暂停信号双方立刻停火","结构化复盘：发生了什么→感受→需要→下次","冷战超48小时发一条软消息打破僵局","反思自己在冲突中的惯性模式","第二天主动开口不等TA先来"],mainScript:"我刚刚语气重了，我想要的是被理解不是要赢。",says:["我知道你很生气你的感受是对的","语气重了对不起","不想赢想要我们好","准备好了我们再聊","我在反思","是我考虑不周","把事实和感受分开聊","你说得有道理","我不该那样说","冷静20分钟但保证回来","不是要攻击你不知道怎么表达","你对我很重要所以我着急","想听你说完不打断","别在情绪上面做决定","下次先说感受不说判断"],scriptBranches:{positive:"TA软化了→趁热打铁约面聊不翻旧账只聊以后怎么办。",cold:"TA还冷→不逼再给一天发一条不相关的日常关心。",noReply:"不回→发不带压力的话然后等。",angry:"发火→不回怼回我理解你生气然后给空间。"},avoid:["说你总是你从来不","翻旧账","冷战超48小时","找第三方评理","在TA面前哭来施压","否认TA感受说你想太多了","用随便你赌气","在朋友面前吐槽","把问题上升到人身攻击","发长段语音说教","截图发朋友评理","在TA生气时讲道理","说如果你爱我就不会这样","拿分手当威胁","在社交媒体发暗示"],weekPlan:[{day:"Day 1",title:"软启动",task:"发一条以我开头的消息只表达感受。",goal:"发出软启动消息"},{day:"Day 2",title:"破冰",task:"不提冲突聊一件开心的事。",goal:"正常互动"},{day:"Day 3",title:"表达需求",task:"用我需要替代你应该。",goal:"需求句式"},{day:"Day 4",title:"小行动",task:"做一件平时不做的事表达在意。",goal:"具体改变"},{day:"Day 5",title:"复盘",task:"发生了什么→感受→需要→下次。",goal:"不升级的复盘"},{day:"Day 6",title:"新规则",task:"约定冲突暂停信号。",goal:"一条新规则"},{day:"Day 7",title:"正面收尾",task:"做让你们都开心的事画句号。",goal:"正面互动"}],moduleCards:[{module:"Gottman冲突修复",confidence:"high",diag:"你们的吵架模式中出现了Gottman定义的末日四骑士信号——批评和防御已经激活。研究表明出现这种模式的关系如果不干预破裂概率超过90%。好消息：用软启动替代硬启动成功率96%。",whys:["批评→防御→蔑视→石墙是致命循环","前3分钟开始方式决定96%走向","软启动成功率96%","先修复情绪安全感再讨论事实","承担10%责任瞬间降低对方防御"],dos:["用我感觉___因为___开头","承担你的部分哪怕只有10%","约定暂停信号比如举手","在好时候建立冲突处理规则","结构化复盘"],says:["语气重了对不起","不想赢想要我们好","你的感受是对的","把事实和感受分开聊","下次先说感受不说判断"],pitfalls:["你总是你从来不","翻旧账扩大战线","人身攻击","威胁分手","截图发朋友"]},{module:"成人依恋理论",confidence:"high",diag:"冷战是依恋系统中的石墙反应——情绪过载后的自我保护不是惩罚。TA需要24-72小时让情绪调节系统恢复。此期间任何沟通尝试都会被杏仁核编码为又一次攻击。",whys:["情绪系统已经过载","冷战是战或逃中选择了逃","需要24-72小时恢复","恢复期间沟通都被当攻击","沉默不等于不在乎"],dos:["什么都不做等TA恢复","让对方安静待24-72h","做自己的事","发一条简短消息表示你在","准备不带指责的开场白"],says:["不追着你吵了等你准备好我在","你需要时间我给你","不管怎样你对我很重要","等你想聊随时找我","有些话想当面说"],pitfalls:["反复发消息轰炸","通过朋友传话","去TA家堵","社交媒体发暗示","TA刚回应就倒情绪"]},{module:"五种道歉语言",confidence:"high",diag:"Chapman研究发现人接受道歉有5种形式。TA需要的可能不是你说对不起而是你具体说出错在哪里+以后怎么改+用行动证明。形式不对TA永远不会觉得你真的道歉了。",whys:["不同人需要不同形式的道歉","只说对不起不够需要承认具体错误","行动比语言更有说服力","TA需要看到你理解了TA的感受","修复是一个过程不是一句话"],dos:["具体说出你错在哪里不带但是","提出具体弥补行动并立即开始","给对方时间不催TA原谅","接下来1-2周用行动证明","让TA参与到你的改变过程"],says:["那天完全是我的问题","你有权利生气换做我也会","不奢求马上原谅需要多久都行","我会用行动证明","以后遇到类似我会**_"],pitfalls:["道歉加但是等于甩锅","条件式道歉","急于要求原谅","道歉完觉得翻篇","嘴上说改行为没变"]},{module:"沟通策略选择 (Hersey)",confidence:"high",diag:"对方当前处于R2准备度（有意愿但情绪波动）。匹配S2推销式策略：引导+解释帮TA理解发生了什么同时给TA参与决策的空间。高关系+高指导。",whys:["R2有意愿但不知怎么沟通","需要你先打开话题但温和地","解释你的想法比表达情绪有效","给TA选择而非命令","TA需要感到被尊重"],dos:["引导TA表达感受","解释你的本意","给TA选择空间","用我们一起想想办法","肯定TA愿意沟通"],says:["我觉得我们可以___你觉得呢","我想跟你聊聊不是要吵","你的想法是什么我想听","我们一起想想办法","你觉得怎么做更好"],pitfalls:["在TA有情绪时讲逻辑","替TA做决定","用你应该句式","不给TA思考时间","把沟通变成说教"]},{module:"Knapp关系阶梯",confidence:"high",diag:"冲突后你们的关系可能从亲密期退回到了限制-停滞期。不一定意味着结束但需要通过正确的修复尝试重新回到亲密期。",whys:["冲突可能导致阶段倒退","修复成功可以回到原来甚至更好","不修复会继续退到分离期","修复的时机很重要","行动比承诺更有效"],dos:["在48h内做出修复尝试","用行动而非语言证明","制造新的正面互动","回忆你们最好的时候","给关系恢复的时间"],says:["我想回到我们最好的状态","这件事不值得伤害我们","我们经历过更难的","一起想想怎么走出来","你对我来说太重要了"],pitfalls:["假装什么都没发生","急于回到之前的亲密度","不给对方缓冲时间","翻旧账来证明你受伤更多","把修复的责任全推给对方"]},{module:"Rusbult投入评估 (冲突后复盘)",confidence:"high",diag:"吵架之后不只是修复,还要重新评估这段关系的满意度、投入和替代选项。如果经常吵同类问题,说明有结构性冲突,不是一次道歉能解决的。",whys:["重复冲突=核心价值观差异未协商","修复行为比吵架内容更重要","投入过多会让人忽视真实满意度","替代选项低时容易凑合","双方对什么是好关系可能定义不同"],dos:["列出这半年你们吵过的3次架","找共同模式(是不是都和某个主题相关?)","问自己:如果现在单身,你会重新选这个人吗?","评估4项:满意度/投入/替代/承诺","如果3项负面但还在一起,是为什么?","每月一次主动关系盘点(不在吵架时)"],says:["我们不是在吵架,是在解决一个反复出现的问题","不是你的错也不是我的错,是我们的模式","我需要你知道这件事对我的真正重量","这次我们真的要找到根因","如果一直这样我会累"],pitfalls:["每次吵完就翻篇,不谈根因","只看这次对错,不看模式","用都吵过这么多次还在一起当成爱","把投入和爱混淆","避免深度谈话只做表面和解"]}]};}function _cd(){var v="TA在关机模式——你的追问会让TA关得更紧。就像手机死机了你怎么按都没反应，不是手机坏了是需要时间重启。";var si="TA选择了减少联系——这不是突然发生的。TA可能已经感觉不太对有一段时间了只是没说。已读不回/变冷淡通常意味着两件事之一：1）TA需要空间来处理自己的情绪；2）TA在评估这段关系是否值得继续投入。\n\n关键信息：TA没有拉黑你或说分手——门还开着只是你不能猛推。";var rc="你越追TA越想逃——这不是TA故意的是依恋系统的本能反应。当一个人感觉被需要太多时大脑的威胁检测系统会启动让TA本能地想要拉开距离。你的每一条追问消息每一个你怎么了都会被TA的大脑翻译成压力+1。\n\n更深层的原因可能是：你们的互动变得太有预测性了或者你的需求感暴露让TA觉得这段关系太重了。";return{verdict:v,situation:si,rootCause:rc,thisRoundGoal:"降低TA的压力感。让TA觉得不回你也没事——矛盾的是这反而会让TA想回你。因为当压力消失好奇心才会回来。",herseyS:"S1",usedModules:["成人依恋理论","追问-退避循环","Hersey情境沟通","Knapp关系阶梯","投入模型"],risk:"med",horsemen:{detected:["石墙 Stonewalling"],breakupRisk:30},reasons:["对方减少联系不是突然的——TA可能已经觉得不太对有一段时间了","你最近的互动可能让对方觉得压力大或者无聊——回顾最近10条消息看看","降温不等于要分手可能只是需要重新找到舒适的距离","TA可能在重新评估关系是否值得继续投入","有时候降温是TA自己在处理其他生活压力而非针对你"],dos:["立刻降低联系频率到之前的一半","发一条不需要回复的轻松分享——分享型替代追问型","做一件让自己开心的事并发朋友圈——展示你有自己的生活","观察TA是主动联系还是只有你在找——数据比猜测靠谱","每次消息不超过3条就收","不在深夜发消息","如果TA回复变慢你也变慢——匹配TA的节奏","给自己一周冷却期只回不主动——让TA有机会想你","保持社交圈活跃——你的世界不应该只有TA","关掉TA的已读回执减少你焦虑的来源","做一件你之前一直想做但因为TA而没做的事","重新审视最近发的消息——站在对方角度看是不是太多了","48小时后发一条朋友圈展示你过得挺好","写下TA喜欢你的5个证据——焦虑时看这个清单","给自己设不看手机的时间段"],mainScript:"看到一个好玩的想分享给你，不用回",says:["看到好玩的想分享给你不用回","天气好适合出去走走","不打扰你有空聊","分享最近循环的歌","路过你说过想去的地方替你踩了个点","心情不错想跟你分享","你推荐的看完了确实不错","学了新东西挺有意思","天冷了多穿点","试了一家新的挺好吃","有个事想问你","发现你可能喜欢的地方","最近在忙什么我也挺充实","好久没聊了你怎么样","周末去了个地方推荐给你"],scriptBranches:{positive:"TA回了→正常聊不提冷淡。保持轻松不追问你之前怎么不回我。",cold:"TA敷衍→收。过几天再发一条有价值内容。敷衍说明TA还没准备好但也没关门。",noReply:"一周没回→接受这个节奏。把精力转移到自己身上。你过得精彩TA自然会好奇。",angry:"如果发了→说明积攒了很久的不满。不要辩解先道歉再给空间。"},avoid:["问你是不是不喜欢我了——这是焦虑发作不是沟通","连发3条以上未回复消息","找TA朋友打听","发长段表白——信息量太大等于给TA布置作业","表现得很在意——你的焦虑会传染给TA","每天必须聊天必须说晚安","删好友取关来引起注意","发暗示性伤感朋友圈","在TA冷淡时加倍热情——追问-退避循环典型错误","过度解读TA每一个行为","比较TA对你和对别人的态度","突然改变风格讨好","用如果你不理我就来威胁","假装不在乎但实际时刻关注","反复追问怎么了——你越问TA越不想说"],weekPlan:[{day:"Day 1-2",title:"完全静默",task:"不发消息。做自己的事。如果想发就写备忘录里。",goal:"管住自己一天不联系"},{day:"Day 3",title:"轻松分享",task:"发一条分享型消息不问问题。看到个好玩的分享给你就够了。",goal:"信号发出"},{day:"Day 4",title:"观察",task:"观察TA的反应。回了→轻松接住。没回→继续做自己的事。",goal:"不过度反应"},{day:"Day 5",title:"价值内容",task:"如果没回再发一条有趣有价值的内容。",goal:"展示你的价值而非需求"},{day:"Day 6",title:"自我充电",task:"今天把精力完全放在自己身上。不看TA的社交媒体。",goal:"一天不关注TA"},{day:"Day 7",title:"理性评估",task:"回顾本周：TA有回应吗？主动找过你吗？据此决定继续等还是降低期待。",goal:"数据驱动的判断"}],moduleCards:[{module:"依恋模式识别",confidence:"high",diag:"根据成人依恋理论你越追TA越想逃——这是依恋系统的自动反应不是故意的。你们进入了典型的追问-退避循环需要一方先改变节奏来打破。",whys:["追→TA感到压力→逃是自动反应","你的焦虑放大了TA的回避","TA需要空间来重新充电","匹配节奏是打破循环的关键","降温不代表不爱"],dos:["停止所有追问","给48h自由空间","匹配对方回复节奏","做自己开心的事","写焦虑日记记录触发点"],says:["我也挺忙你忙完随时找","看到好玩的发给你不用回","随便聊聊不聊也行","不打扰了有空再聊","如果需要我随时都在"],pitfalls:["反复追问","连发多条","半夜打电话","去住处堵TA","用分手测试"]},{module:"沟通策略选择 (Hersey)",confidence:"high",diag:"TA当前处于R1准备度（没能力也没意愿沟通）。对应S1告知式策略：简短信号+不施压。过多沟通反而会加重压力。耐心等TA的准备度自然升到R2再调整策略。",whys:["R1→S1是最佳匹配","过多沟通加重压力","简短信号最有效","等TA升到R2再调整","耐心是关键"],dos:["发分享型不发追问型","每次不超3条","在最好时刻结束","给TA回应时间","观察反应调整"],says:["看到个好玩的分享给你","不打扰有空聊","分享一首歌","天冷多穿点","路过你说过想去的地方"],pitfalls:["追问怎么了","发长段消息","在深夜发","加倍热情","表现焦虑"]},{module:"Knapp关系阶梯",confidence:"high",diag:"关系温度在下降——对方在有意或无意拉开距离。根据Knapp模型你们可能从亲密期退回到了停滞期。不一定意味着结束但意味着当前互动方式需要调整。",whys:["减少联系通常不是突然的","你的互动可能让对方觉得压力大或无聊","降温可能只需要重新找到舒适距离","TA可能在重新评估关系","有时是在处理其他压力而非针对你"],dos:["降低联系频率到一半","做让自己开心的事","观察TA是主动联系还是只有你找","保持社交圈活跃","给自己一周冷却期"],says:["最近在忙什么我也挺充实","好久没聊了你怎么样","今天心情不错想分享","发现你可能喜欢的地方","周末去了个地方推荐给你"],pitfalls:["问你是不是不喜欢我了","连发3条以上","找TA朋友打听","发长段表白","每天必须聊天"]},{module:"Gottman冲突修复",confidence:"high",diag:"虽然你们没有明显吵架但已读不回本身就是Gottman定义的石墙效应的轻度形式。如果不处理会从被动石墙变成主动选择减少联系最终走向分离。",whys:["已读不回是轻度石墙","不处理会逐渐加重","TA可能有未表达的不满","小问题积累成大问题","预防比修复容易"],dos:["不追问但保持存在","发价值型内容而非追问型","给TA安全的表达空间","在TA回应时正面强化","不在TA冷淡时翻旧账"],says:["不打扰你有空聊","分享一个你可能喜欢的","最近心情不错想分享","如果有什么想说的我在","不管什么时候找我都行"],pitfalls:["追问怎么了为什么不回","把冷淡上升到不爱了","在TA面前表现焦虑","找朋友打探原因","用冷暴力报复"]},{module:"Rusbult投入模型",confidence:"high",diag:"对方可能在重新评估关系的满意度-替代-投入方程。冷淡期你需要做的不是证明你的投入而是提升TA对这段关系的满意度预期——让TA觉得跟你在一起是有趣的有价值的。",whys:["TA可能在评估值不值得继续","满意度下降是冷淡的常见原因","你的独特价值是最强的留存因素","展示成长比讨好更有效","让TA自己发现你的改变"],dos:["展示你在过得精彩","做让自己有趣有价值的事","不要表现需要TA来拯救你","让TA好奇你最近在干什么","用行动证明你的独特性"],says:["最近学了___挺有意思","发现一个很棒的地方","今天做了一件很酷的事","分享给你因为你会懂","最近状态不错"],pitfalls:["表现离了TA不行","把注意力全放在TA身上","用投入来绑架","忽视自己的成长","只关注关系不关注自己"]},{module:"爱之语重新校准",confidence:"high",diag:"TA变冷淡可能不是不爱了,而是你给的爱,TA接收不到。每个人最敏感的爱之语不同——你一直给物质,TA要的是时刻;你一直陪伴,TA要的是肯定。错频的爱,再多也无感。",whys:["Chapman 五种爱之语理论(言语/时刻/服务/礼物/触)","每个人主要爱之语通常只有1-2种","你送礼物TA不感动不等于TA不爱你","可能是你在按自己的爱之语给","对方童年经历决定主爱之语"],dos:["回想TA最感动的5次是为什么","对比你最近做的事 vs 这5件事","问TA你觉得我爱你最多是什么时候?","连续2周只用1种爱之语试试(如每天肯定的话)","记录TA反应的变化","不同场景(压力大/开心/平淡)可能需要不同爱之语"],says:["你觉得我爱你吗?从什么时候开始觉得的?","我发现我一直在用我的方式爱你","你最想被我怎么对待?","我重新学习怎么爱你","最近是不是我忽略了什么"],pitfalls:["用自己的爱之语强加","加大原有投入(更错更快)","用礼物贵重来证明爱","要求TA用我的方式感受爱","把TA的冷淡归因为TA的问题"]}]};}function _ad(){var v="推进最好的方式是刚好下一步——不要跳级。你们已经有了不错的基础现在的问题是怎么自然地捅破窗户纸。";var si="你们还在互相观察的阶段——对方在试探你是不是值得投入更多时间和感情。这个阶段的关键不是表达心意而是让TA想更多了解你。你需要像一部好剧一样每次互动都留个钩子让TA想看下一集。\n\n最好的方式不是一句表白而是让你们的互动自然地越来越亲密直到双方都觉得我们其实已经是那样了。";var rc="时机和节奏比内容更重要。在早期关系中对方更关注你有没有意思而非你有多喜欢我。过早表露强烈感情会破坏神秘感——好奇心是关系初期最强的驱动力。行为升级比语言表白更安全因为行为可以假装不小心但表白不行。";return{verdict:v,situation:si,rootCause:rc,thisRoundGoal:"让TA想更多了解你而不是让TA知道你有多喜欢TA。保持有趣+有价值+有点神秘的组合。",herseyS:"S3",usedModules:["Knapp关系阶梯","Sternberg三角","Hersey情境沟通","Fisher驱动力","自我扩展理论"],risk:"low",horsemen:{detected:[],breakupRisk:10},reasons:["早期关系中对方更关注你有没有意思——差异化比真诚更重要","过早表露强烈感情会破坏神秘感——好奇心是最强驱动力","每次互动的质量远比频率重要——10次普通聊天不如1次让TA笑的互动","对方需要在行动中感受到在一起的自然感而非被语言逼着做决定","行为升级比语言表白更不容易被拒绝——渐进式升温让对方有时间适应"],dos:["每周制造2-3次高质量互动至少一次线下","每次聊天在最好时刻结束——意犹未尽是最强的钩子","制造只属于你们的独特记忆点","展示你有趣的一面而非深情的一面","保持一点神秘感不要把一切交代清楚","在TA不主动找你的日子里做自己的事","规划有创意的见面方式不要每次都吃饭看电影","记住TA说过的细节在未来自然提起","找机会自然肢体接触递东西碰手指路轻拍","一起做新鲜有点刺激的事共同心跳加速=心动","分享只跟亲近人才说的事——适度脆弱=信任信号","制造你们之间的秘密或暗号——排他性亲密感","并排走路而非面对面增加亲密感","结束约会时告别拉长一点","观察TA是否也在增加和你的互动频率"],mainScript:"这周末有个有意思的地方一起去看看？",says:["周末有个活动你有兴趣吗","今天看到东西第一反应想发给你","你上次说的我查了确实挺有意思","跟你聊天时间过得特别快","猜我今天遇到什么好玩的","你说话好有意思别人不这么说","经过你附近要不要顺便喝杯咖啡","你笑起来特别好看你知道吗","跟你在一起很放松不用装","每次和你聊完心情都变好","你有没有觉得我们认识好像很久了","今天不想走再待会儿吧","有些人越了解越有意思你就是","如果有一天你不开心了可以随时找我","发现一个适合你的"],scriptBranches:{positive:"TA热情→自然推进提议见面。不要在对方热情时表白——先享受升温过程。再见3次面让在一起水到渠成。",cold:"TA犹豫→不逼保持有趣。犹豫不等于拒绝可能只是还没准备好。继续做一个有趣的人让TA自己想靠近。",noReply:"没回→话题可能不对换个角度。不要发你怎么不回我而是过两天换个有趣话题。",angry:"不适用于推进阶段。如果TA表现反感可能推得太快了退回上一步。"},avoid:["表白太早——在对方没有明确信号前不要摊牌","问你对我什么感觉——终极提问太有压力","天天黏着——过度可用降低吸引力","送太贵的礼物——TA会有欠你的压力","在朋友圈暗示","每天早安晚安——变成义务就不浪漫","知道TA日程恰好出现——这很creepy","三天两头约见面——给对方想你的时间","把TA介绍给家人——太早会吓跑","过分关心TA过去感情史——暴露不安全感","表现得好像已经在一起了","第一次亲密接触后立刻变粘","忽视犹豫信号继续推进","用我等你很久了道德绑架","把在一起看得太重患得患失"],weekPlan:[{day:"Day 1",title:"有趣分享",task:"分享一个TA感兴趣的内容。看到这个想到你了就够了。",goal:"制造一次有回应的互动"},{day:"Day 2",title:"保持节奏",task:"TA回了轻松聊几句。没回就做自己的事。",goal:"不急不缓的节奏"},{day:"Day 3",title:"提议活动",task:"提议一个有趣的线下活动。要具体：周六下午那个新开的___要不要去。",goal:"约到线下见面"},{day:"Day 4",title:"制造记忆",task:"见面时制造独特体验。拍照/尝试新东西/发现只有你们知道的地方。",goal:"创造一个共同记忆"},{day:"Day 5",title:"走心小惊喜",task:"送一个不贵但走心的小东西——说明你记住了TA说过的话。",goal:"让TA感到被看见"},{day:"Day 6",title:"适度神秘",task:"今天做自己的事不主动联系。让TA有机会想你。",goal:"给TA想你的空间"},{day:"Day 7",title:"升级互动",task:"进展顺利尝试一次更亲密的互动——更深话题/更近距离/更长相处。",goal:"自然推进一小步"}],moduleCards:[{module:"Knapp关系阶梯",confidence:"high",diag:"你们处于Knapp模型的实验期——互相试探是否值得投入更多。这个阶段关键是制造意犹未尽而非急于表白。每次互动要留钩子。",whys:["差异化比真诚更重要","质量远比频率重要","神秘感是最强驱动力","需要安全感才会打开","行为升级比语言安全"],dos:["最好时刻结束意犹未尽","制造独特记忆点","保持神秘感","有创意的见面方式","记住TA说过的细节"],says:["跟你聊天时间特别快","猜我遇到什么好玩的事","发现一个适合你的","你说话好有意思","你笑起来特别好看"],pitfalls:["表白太早","天天黏着","每天早安晚安","送太贵礼物","三天两头约"]},{module:"Sternberg三角",confidence:"high",diag:"暧昧期主要靠激情（心跳加速的感觉）驱动。根据Sternberg三角理论需要制造共同的新鲜刺激体验来加速亲密-激情-承诺三角的形成。",whys:["暧昧期激情>亲密>承诺是正常比例","新鲜刺激触发多巴胺","共同经历制造情感连接","日常互动容易变无聊","需要制造高峰记忆点"],dos:["一起做新鲜有刺激的事","规划有创意的见面","并排走路增加亲密感","找机会自然肢体接触","制造你们的秘密暗号"],says:["这周末有个有意思的一起看看","今天不想走再待会儿吧","有些人越了解越有意思","跟你在一起很放松","你有没有觉得认识好像很久了"],pitfalls:["每次都吃饭看电影","不制造新鲜感","表现得已在一起了","忽视犹豫信号","把在一起看太重"]},{module:"Fisher驱动力分析",confidence:"high",diag:"根据Helen Fisher研究4种驱动力类型决定TA喜欢什么样的互动方式。了解TA的类型能让你的约会和沟通事半功倍——有人爱新鲜有人爱稳定有人要效率有人要共鸣。",whys:["探索型怕无聊爱新体验","建造型重稳定爱计划","领导型要效率喜欢直接","协调型重感觉需要共鸣","匹配TA的类型比讨好有效10倍"],dos:["观察TA喜欢什么类型活动","TA喜欢计划还是随性","根据类型调整约会方式","在TA舒适区内制造惊喜","匹配TA的节奏"],says:["你平时喜欢做什么放松","你更喜欢计划好还是走到哪算哪","周末想做点什么不一样的","你觉得最理想约会是什么样","你最期待什么样的关系"],pitfalls:["用你喜欢的方式约TA","忽视TA的偏好","强迫TA接受你的方式","把TA的不同当缺点","不观察反应调整"]},{module:"沟通策略选择 (Hersey)",confidence:"high",diag:"暧昧期对方处于R3准备度（有能力但犹豫）。匹配S3参与式策略：你支持+鼓励让TA主导你在旁边给信心。高关系+低指导——不要替TA做决定。",whys:["R3有能力但犹豫=需要鼓励","你的角色是啦啦队不是教练","让TA自己做决定增加投入感","过多指导会让TA觉得不被信任","你只需说我相信你"],dos:["让TA主导互动节奏","在TA做决定时肯定","不要替TA安排一切","给TA选择空间","在TA犹豫时温和鼓励"],says:["你觉得怎么样","你来决定我配合","你之前做得很好","我相信你的判断","需要我做什么你说"],pitfalls:["替TA做所有决定","安排太多让TA有压力","TA犹豫时追问为什么","表现比TA更着急","不给TA思考空间"]},{module:"Rusbult投入模型",confidence:"high",diag:"暧昧期双方都在计算要不要投入更多。你需要做的是让TA觉得跟你在一起的满意度很高而且这个投入是值得的——同时不要让TA觉得替代选择（别人）比你更有趣。",whys:["暧昧期是投入决策的关键窗口","满意度=你们在一起时TA有多开心","替代选择=TA的其他选项","投入量=TA已经花了多少时间精力","差异化是降低替代吸引力的关键"],dos:["每次互动都让TA觉得值得","制造只有你能给的独特体验","让TA对你产生时间投入","不要做TA随便能找别人做的事","展示你的不可替代性"],says:["只有我们会做这种事","这是只属于我们的","你在别人面前也这样吗哈哈","下次带你去一个特别的地方","我觉得我们的默契挺好的"],pitfalls:["做所有人都会做的约会","不制造差异化","让TA觉得你很容易得到","不给TA制造期待","忽视竞争对手的存在"]},{module:"依恋模式预判",confidence:"medium",diag:"暧昧期最大的陷阱是被本能(而不是理性)驱动。识别你和TA的依恋倾向可以预判这段关系会怎么发展。焦虑型-回避型组合最容易先甜后苦,安全型-安全型最稳但可能平淡。",whys:["依恋类型在3-6个月后开始显现","暧昧期的爱有40%是焦虑,不是真心","回避型一旦推进太快会本能撤退","焦虑型容易过度解读每条消息","安全型需要稳定节奏而非剧烈波动"],dos:["观察TA在压力情况下的反应(真实依恋显露)","观察TA谈前任的方式(都是我错=焦虑;都是她错=回避)","问自己:TA不秒回你会怎么样?(焦虑型会崩)","如果是焦虑-回避组合,双方需要刻意的沟通规则","做一次依恋类型自测(网上有免费版)"],says:["我注意到我有时候会过度想你的回复(焦虑表达)","我需要一点空间但不是因为不喜欢你(回避表达)","我们可以聊聊我们各自需要什么节奏吗?","你最近压力大的时候想被怎么对待?","我不擅长表达但我想学"],pitfalls:["把焦虑当激情,把回避当酷","用测试的方法确认TA的心意","为了见面改变自己核心节奏","在早期就诊断对方是回避型然后贴标签","把依恋理论用来操控对方"]}]};}function _dl(){var v="关系没有大问题——但最大的敌人不是冲突而是惰性。很多关系不是死于危机而是死于无聊。";var si="你们处于稳定期表面上一切正常。但正常恰恰是最容易出问题的时候——因为双方都开了自动驾驶不再刻意经营。日常小忽视的积累比一次大吵架更致命。\n\n一个残酷的事实：对方可能有没说出口的需求。没有问题不等于很满意可能只是还行——而还行离够了只差一个导火索。";var rc="不是不爱是太习惯了。当关系变得完全可预测时大脑的奖赏系统就不再释放多巴胺了。你们可能已经从恋人变成了室友而不自知——聊的都是实用的事（几点到家/今天吃什么）很少聊感受和梦想了。\n\n根据自我扩展理论（Aron）：关系停止成长时满意度就开始下降。不是因为做错了什么而是因为停止做对的事了。";return{verdict:v,situation:si,rootCause:rc,thisRoundGoal:"在关系还好的时候主动注入新鲜感。保持情感存款——让情感账户一直有余额这样偶尔的小摩擦不会让关系破产。",herseyS:"S4",usedModules:["Sternberg三角","五种爱之语","自我扩展理论","Fisher驱动力","Rusbult投入模型"],risk:"low",horsemen:{detected:[],breakupRisk:8},reasons:["稳定期最大的敌人不是冲突而是惰性——无聊是关系的慢性毒药","长时间不制造新鲜感关系会进入室友模式——聊天全是日常琐事","双方可能在不知不觉中减少了真正的交流——从聊感受变成聊事情","日常小忽视的积累（忘记说谢谢/不再夸TA/看手机多过看TA）比大吵架更致命","对方可能有没说出口的需求——没有问题可能只是还没到临界点"],dos:["每周制造一个小惊喜或新体验——打破可预测性是最有效的保鲜剂","安排一次只有你们俩的约会日——像刚认识时那样精心准备","认真问一次你最近有什么想做的——然后真的去做不是随口一问","一起学一样新东西——根据自我扩展理论这是最有效的亲密度提升法","给TA写一张手写的纸条——在数字时代手写等于100倍诚意","重新关注TA最近在关心什么——你可能很久没好奇过了","主动承担一件平时不做的家务——不是因为TA要求而是你想做","在朋友面前真心地夸TA","重新打扮自己一下——让TA眼前一亮","问TA有没有什么地方你觉得我可以做得更好——真诚地听","回忆刚认识时做过的事再做一次——重温初始心动","在TA没有预期的时候送一份走心小礼物——不是花钱是花心思","认真地听TA说话——放下手机看着TA的眼睛","一起做一件有点冒险的事——共同经历产生催产素","每天至少说一句具体的感谢——谢谢你今天做了***"],mainScript:"想你了。我们好久没一起做点什么了这周试试？",says:["我们好久没一起做了这周试试","最近你有什么想去的地方吗我安排","看到觉得很适合你给你买了","你最近辛苦了今天你什么都不用做","觉得和你在一起每天都很开心","觉得认识你是最对的决定","你上次说的那个我一直记着","今天你来选我们做什么","不管怎样你永远有我","你最近是不是有什么烦心事我听你说","发现了你一定会喜欢的地方","如果可以重来还是会选择你","你笑的时候真好看","我们一起试试怎么样","今天谢谢你做了具体的事"],scriptBranches:{positive:"TA开心→继续保持这个节奏。好的关系不是大起大落而是持续的小确幸。",cold:"TA忙→理解不施压。但忙完后主动创造放松时刻。",noReply:"偶尔没回→正常不过度解读。但如果连续3天互动质量下降要注意了。",angry:"因为小事发脾气→可能积压了很久的不满。不纠结小事而是问最近是不是有什么不舒服的。"},avoid:["因为稳定就不再花心思经营——自动驾驶是关系杀手","以为对方应该懂而不表达——TA不是你肚子里的蛔虫","长时间不安排单独约会——不是没时间是不优先","只在纪念日节日才制造惊喜——平常日子更需要","忽视对方情绪变化——TA叹了口气你注意到了吗","把对方当出气筒","在朋友面前吐槽对方——侵蚀信任基础","停止对对方说谢谢和我爱你","把精力全放在工作忽略关系","以为不吵架等于关系好——沉默可能是放弃的前兆","停止打扮自己","不再认真倾听——嗯嗯哦不是在听","习惯性否定对方想法","觉得浪漫是没必要的","假设很了解对方就不再好奇——人是会变的"],weekPlan:[{day:"Day 1",title:"走心早安",task:"不是早安两个字而是今天想到一件事——认识你那天也是这样的天气。",goal:"让TA觉得被惦记"},{day:"Day 2",title:"认真倾听",task:"找一个机会认真听TA说话——放下手机看着TA的眼睛。问一个深入的问题。",goal:"一次有深度的对话"},{day:"Day 3",title:"小约会",task:"计划一次小约会。不一定花钱——一起散步做饭看日落都行。关键是专属于你们。",goal:"制造新鲜感"},{day:"Day 4",title:"具体感谢",task:"真诚说谢谢你今天___——要具体到一件事而非泛泛感谢。",goal:"表达具体的感谢"},{day:"Day 5",title:"走心小礼物",task:"送小礼物或写张卡片。重点是说明你在关注TA。",goal:"让TA惊喜"},{day:"Day 6",title:"一起做新事",task:"一起尝试没做过的事。根据自我扩展理论这是最有效的亲密度提升法。",goal:"共同的新体验"},{day:"Day 7",title:"回顾一周",task:"跟TA说这周因为你___我特别开心。强化正面记忆。",goal:"以正面情感收尾"}],moduleCards:[{module:"Sternberg三角诊断",confidence:"high",diag:"根据Sternberg爱情三角理论你们的三要素（亲密/激情/承诺）整体还不错但最好的关系也需要定期体检。最常先下降的是激情然后是亲密——需要主动维护。",whys:["完整的爱=亲密+激情+承诺缺一不可","三者会随时间动态变化","最常先下降的是激情","承诺如果只靠惯性维持会空心化","定期检查比等出问题再修更容易"],dos:["每月自评三维度各打几分","针对最低的维度本周做一件事","亲密低→安排深聊","激情低→一起做新鲜事","承诺低→谈共同小目标"],says:["你觉得我们最近怎么样","我想让我们更好从哪开始","最近好像少了一些___","我们来计划只属于我们的事","我想花更多时间在我们身上"],pitfalls:["只关注一个维度忽略其他","以为应该一直最高","不接受关系有起伏","只说不做","放弃经营等自己好转"]},{module:"五种爱之语匹配",confidence:"high",diag:"Chapman研究发现每个人感受爱的方式不一样——有人需要你说有人需要你做有人需要你陪。如果你用你自己的方式爱TA但TA感受不到那不是你爱得不够而是频道没对上。",whys:["5种语言：肯定话/服务行为/礼物/陪伴/肢体接触","TA最常抱怨缺的是最看重的","很多矛盾是爱的语言不匹配","你觉得努力了可能方式不对","了解对方语言让付出事半功倍"],dos:["观察TA最常抱怨缺什么","直接问什么时候感觉最被爱","试5种各做一次看反应","每天至少用TA的语言做一次","让表达爱成为日常不是特殊场合"],says:["我想知道什么最能让你被爱","今天我来做饭你歇着","你做的___真的很棒","走出去走走想多待一会","这个看到就想到你了"],pitfalls:["用你自己语言去爱对方","觉得心里有就够了","只在节日用心","物质等同于爱","忽视TA反复提的需求"]},{module:"自我扩展理论 (Aron)",confidence:"high",diag:"Aron的研究证明：关系停止成长时满意度就开始下降。不是因为做错什么而是停止做对的事了。一起做新鲜事能有效重燃激情——不需要大冒险小新鲜就够了。",whys:["一起做新事能重燃激情","新体验制造多巴胺","共同成长加深连接","日常可预测性是关系杀手","不需要大冒险小新鲜就够"],dos:["每周一起做一件没做过的事","换一个新的约会地点","一起学一样新东西","制造竞争挑战场景","去没去过的新城市"],says:["好久没一起冒险了试试","你还记得第一次___的时候吗","走今天不回家了去___","我想跟你创造更多新回忆","准备了一个惊喜周末揭晓"],pitfalls:["以为没感觉了就不爱了","只在纪念日才浪漫","两人各玩各手机","停止约会觉得没必要","用手机追剧代替互动"]},{module:"沟通策略选择 (Hersey)",confidence:"high",diag:"稳定期对方处于R4准备度（有能力有意愿）。匹配S4授权式策略：你观察+信任让TA自主。低关系+低指导——不需要你主导但需要你持续关注。",whys:["R4阶段TA不需要你指导","但需要你持续关注和欣赏","授权不等于放手不管","定期check-in很重要","在TA需要时切换回S3"],dos:["给TA充分自主空间","定期做感情check-in","在TA做得好时及时肯定","不要过度干预TA的决定","在TA需要支持时出现"],says:["你安排就好我配合","你最近做的___真的很棒","你觉得怎么样我都支持","需要我的时候说一声","你处理得比我想象的好"],pitfalls:["完全不关注当甩手掌柜","把授权当作不用经营","忽视TA的情绪变化","在TA需要支持时不在","觉得稳定了就不用沟通"]},{module:"Rusbult投入模型",confidence:"high",diag:"稳定期最大的隐患是满意度缓慢下降但因为高投入不愿意面对。需要定期评估满意度并主动注入新鲜感来保持关系的吸引力——让待在一起变成想在一起。",whys:["高投入可能掩盖低满意度","不代表不爱=还行而非很好","需要主动维护满意度","新鲜感是满意度的催化剂","定期评估比等出问题再救好"],dos:["每月问自己和TA的满意度几分","针对最低的方面做改善","增加共同的新体验","保持各自的独立和成长","不把关系当理所当然"],says:["你觉得我们最近怎么样","有什么你希望我做得更好的","我想让我们一直这么好","你最近有什么想做的","我们一起试试新东西"],pitfalls:["因为投入多就忽视不满","以为稳定就不用经营","满意度下降时不沟通","把问题推给对方","用过去的投入绑架未来"]},{module:"Knapp关系阶段审查",confidence:"high",diag:"稳定期最容易的陷阱是关系静止——看似没问题,实际上停在了某一阶段不再深化。Knapp 5 阶段:接触/实验/强化/整合/结合——你们现在是哪一阶?停留在同一阶超过 6 个月就会开始退化。",whys:["Knapp 模型认为关系需要动态推进","停滞不前=静态老化(比冲突更致命)","大多数久了就淡了是阶段没过完","深入需要新话题/新场景/新挑战","整合/结合阶段需要共同投入的未来叙事"],dos:["评估你们现在在 Knapp 5阶段的哪一阶","至少每季度一次深度话题(人生、恐惧、梦想)","一起尝试新事物(不是重复老模式)","定期讨论共同的5年10年愿景","制造适度的关系挑战(旅行/装修/合作)"],says:["最近在想我们5年后会是什么样子","有什么话你还没跟我说过但想说的","我们还有什么可以一起尝试的","我想更深地了解你","我们是不是太稳定了,稳定到有点静止"],pitfalls:["把没吵架当成关系好","用生活琐事填满所有对话","把深度话题等同于找事","避免讨论未来怕压力","互相依赖但不再互相好奇"]}]};}const doExpand=()=>{if(extraLd||!result)return;setExtraLd(true);st("生成补充...");setTimeout(()=>{setExtra({deepWhy:result.reasons||["关系问题是积累的结果","沟通模式需要调整","情绪管理是核心"],extraDos:["把想发的消息先写备忘录等2小时","每天做一件让自己开心的事","找信任的朋友聊聊","重新审视最近消息站在对方角度看","给自己设不看手机的时间段","写下对方3个优点提醒自己","做一件之前想做但没做的事","保持正常社交和工作节奏"],extraSays:["不管怎样你在我心里的位置没变","我最近在反思想变得更好","有些事之前没想清楚现在想明白了","你愿意的话我们可以慢慢聊","不催你按你的节奏来","今天看到___想到你了","不用回复就是想让你知道","最近学了___挺有意思"],extraAvoid:["在深夜发情绪化消息","在社交媒体暗示关系","把对方行为过度解读","跟共同朋友讨论问题","用威胁式语言"]});setExtraLd(false);st("✅ 补充完成");},400);};
const doAnalyze=async()=>{if(!inp.trim()){st("请先输入内容");return;}setPhase("loading");setAnalyzing(true);setResult(null);setExtra(null);setChecked({});setMoreN({});setReportTab("summary");
const t=inp.toLowerCase();
const scenarioId=t.match(/分手|放手|结束|放弃|不要我|离开/)?"_bp":t.match(/吵架|冷战|冲突|生气|发脾气|骂|指责|翻旧账/)?"_cf":t.match(/不回|已读|冷淡|变冷|消失|不理|躲|拉黑|忽冷忽热/)?"_cd":t.match(/暧昧|推进|表白|喜欢|追|在一起|确认关系|约会/)?"_ad":"_dl";
const localFn={_bp,_cf,_cd,_ad,_dl}[scenarioId];
if(mode==="full"&&DEEP_PROMPTS[scenarioId]){
  try{
    const modulePrompts=DEEP_PROMPTS[scenarioId];
    const profileStr=buildCtx&&typeof buildCtx==="function"?buildCtx(profile):"";
    const promises=modulePrompts.map(fn=>{const cfg=fn(inp,profileStr);return ai(cfg.sys,cfg.msg).then(r=>pJ(r)).catch(()=>null);});
    const aiResults=await Promise.all(promises);
    const validModules=aiResults.filter(r=>r&&r.module&&!r.redirect);
    const hasRedirect=aiResults.find(r=>r&&r.redirect);
    if(hasRedirect){setResult({redirect:true,...hasRedirect});setAnalyzing(false);setPhase("report");st("⚠️ 检测到需优先关注的信号");return;}
    if(validModules.length>=3){
      const localRes=localFn();
      const merged={...localRes,moduleCards:validModules,usedModules:validModules.map(m=>m.module),aiPowered:true};
      setResult(merged);setAnalyzing(false);setPhase("report");st("✅ AI 深度分析完成("+validModules.length+"/6 模块)");
      return;
    }
  }catch(e){console.error("AI deep analysis failed:",e);}
}
// Fallback: local analysis
setTimeout(()=>{const r=localFn();
if(mode==="quick"){const qg={breakup:["等你准备好了随时找我","不打扰就是想说一声","最近还好吗","看到这个想到你了"],conflict:["语气重了对不起","我不想赢想要我们好","我在反思","准备好了我们再聊"],cold:["看到好玩的分享给你不用回","分享最近循环的歌","天气好适合出去走走","天冷了多穿点"],advance:["跟你聊天时间特别快","聊完心情都变好","你笑起来特别好看","有些人越了解越有意思"],daily:["想你了","今天因为你很开心","谢谢你一直在","你笑的时候真好看"]};const qg2={breakup:["最近开始学了挺有意思","路过想起你说过喜欢","分享一首歌","天气变了注意保暖"],conflict:["看到个好笑的分享给你","你最近辛苦了","不提那件事了聊点开心的","周末一起走走？"],cold:["学了新东西挺有意思","发现你可能喜欢的地方","试了一家新的挺好吃","路过你说过想去的地方"],advance:["周末有个活动你有兴趣吗","经过你附近要不要喝杯咖啡","发现一个适合你的地方","这周末有个有意思的一起看看"],daily:["好久没一起做了这周试试","发现你一定会喜欢的地方","你有什么想去的吗我安排","一起试试怎么样"]};const k=t.match(/分手|放手|结束/)?"breakup":t.match(/吵架|冷战|冲突/)?"conflict":t.match(/不回|已读|冷淡/)?"cold":t.match(/暧昧|推进|表白/)?"advance":"daily";setResult({quickA:qg[k],quickB:qg2[k],mainScript:r.mainScript,why:r.thisRoundGoal,risk:r.risk});}else{setResult(r);}
setAnalyzing(false);setPhase("report");st("✅ 分析完成");},500);};const _dp={analyzing,checked,ctxData,expandedEng,expandedMod,expertAutoMode,extra,extraLd,font,inp,intents,mode,pipeStep,replyDelay,reportTab,reset,result,setChecked,setCtxData,setExpandedEng,setExpandedMod,setExpertAutoMode,setExtra,setInp,setIntents,setMode,setPhase,setReplyDelay,setReportTab,setResult,setShowModulesInReport,setShowSliders,setShowTriCore,showModulesInReport,showSliders,showTriCore,st,vault,stageId,onNavigateGame};if(phase==="input")return DeepInputPhase(_dp);if(phase==="loading")return DeepLoadingPhase(_dp);if(phase==="report")return DeepReportPhase(_dp);return null;}
function CoachTab({stageId,personaId,profile,st}){const[view,setView]=useState("home");const[rpScene,setRpScene]=useState(null);const[rpMsgs,setRpMsgs]=useState([]);const[rpInp,setRpInp]=useState("");const[rpLd,setRpLd]=useState(false);const[chSel,setChSel]=useState(null);const[chMsgs,setChMsgs]=useState([]);const[chInp,setChInp]=useState("");const[chLd,setChLd]=useState(false);const[chScore,setChScore]=useState(null);const[chTimer,setChTimer]=useState(0);const[dateView,setDateView]=useState(null);const[gameId,setGameId]=useState(null);const[gameInp,setGameInp]=useState("");const[gameLd,setGameLd]=useState(false);const[gameRes,setGameRes]=useState(null);const[puScene,setPuScene]=useState(null);const[puMyTrait,setPuMyTrait]=useState(null);const[puTaTrait,setPuTaTrait]=useState(null);const[puGoal,setPuGoal]=useState(null);const[puRes,setPuRes]=useState(null);const[puLd,setPuLd]=useState(false);useEffect(()=>{if(chSel&&!chScore){const t=setInterval(()=>setChTimer(p=>p+1),1000);return()=>clearInterval(t);}},[chSel,chScore]);const backHome=()=>{setView("home");setRpScene(null);setChSel(null);setDateView(null);setGameId(null);setGameRes(null);setPuScene(null);setPuRes(null);};const startRp=(sc)=>{setRpScene(sc);setView("roleplay");setRpMsgs([{role:"ta",text:sc.setup},{role:"sys",text:`提示：${sc.hint}`}]);setRpInp("");};const sendRp=async()=>{if(!rpInp.trim()||rpLd)return;const myMsg=rpInp.trim();setRpInp("");setRpLd(true);setRpMsgs(p=>[...p,{role:"me",text:myMsg}]);try{const history=rpMsgs.filter(m=>m.role!=="sys").map(m=>`${m.role==="ta"?"TA":"我"}：${m.text}`).join("\n")+"\n我："+myMsg;const sys=buildSys(stageId,personaId,profile,`你在模拟恋爱对话练习。你扮演TA。场景：${rpScene.setup} 规则：1.以TA身份回应1-2句像真人微信 2.符合场景情绪 3.给评分0-100 4.如有更好说法给建议。返回JSON：{"reply":"TA的回应","score":0-100,"feedback":"为什么给这个分","better":"更好的说法(如果score<80)"}`);const r=await ai(sys,"对话历史：\n"+history);const p=pJ(r);if(p){setRpMsgs(prev=>[...prev,{role:"ta",text:p.reply},{role:"sys",text:`${p.score>=70?"✅":"⚠️"} ${p.score}分 — ${p.feedback}${p.better?"\n💡 更好："+p.better:""}`}]);}else{setRpMsgs(prev=>[...prev,{role:"ta",text:"嗯..."},{role:"sys",text:"⚠️ 65分 — 继续加油"}]);}}catch(e){setRpMsgs(prev=>[...prev,{role:"ta",text:["嗯...","好吧","是吗","然后呢？"][Math.floor(Math.random()*4)]},{role:"sys",text:"⚠️ 本地模式 — 无法评分"}]);}setRpLd(false);};const startCh=(ch)=>{setChSel(ch);setView("challenge");setChMsgs([{role:"ta",text:ch.opening}]);setChInp("");setChScore(null);setChTimer(0);};const sendCh=async()=>{if(!chInp.trim()||chLd)return;const myMsg=chInp.trim();setChInp("");setChLd(true);setChMsgs(p=>[...p,{role:"me",text:myMsg}]);try{const history=chMsgs.map(m=>`${m.role==="me"?"我":"TA"}：${m.text}`).join("\n")+"\n我："+myMsg;const sys=`哄人模拟器。你扮演生气的女友。场景：${chSel.label}（${chSel.desc}）。根据对方话术回应。如果被成功哄好了在回复末尾加[SCORE:85]这样的评分。否则继续生气。回复像真人简短。`;const r=await ai(sys,history);const text=typeof r==="string"?r:"";const scoreMatch=text.match(/[SCORE:(\d+)]/);const clean=text.replace(/[SCORE:\d+]/g,"").trim();setChMsgs(p=>[...p,{role:"ta",text:clean||"哼。"}]);if(scoreMatch)setChScore(parseInt(scoreMatch[1]));}catch(e){const replies=["哼，你继续说。","我不想听解释。","算了不说了。","你觉得你说的有道理吗？"];setChMsgs(p=>[...p,{role:"ta",text:replies[Math.floor(Math.random()*replies.length)]}]);}setChLd(false);};const AI_FEATS_PROMPTS={
waitprob:(t,pro)=>({sys:`你是基于依恋理论的恋爱顾问。分析用户女生没回信息的真实原因分布（不是脑补）。要冷静、具体、基于上下文。

用户当前档案：${pro?.nickname?'对象昵称:'+pro.nickname:''}${pro?.relation?',关系阶段:'+pro.relation:''}

输出严格的 JSON（不要任何解释、markdown、代码块）：
{
  "probs": [
    {"cause":"📱 在忙","pct":<0-50>,"note":"<一句具体原因>"},
    {"cause":"💤 没看到","pct":<0-40>,"note":"<一句>"},
    {"cause":"💭 在想怎么回","pct":<0-40>,"note":"<一句>"},
    {"cause":"😐 不感兴趣","pct":<0-30>,"note":"<一句, 警示口吻>"},
    {"cause":"🎭 在测试你","pct":<0-15>,"note":"<极少数情况的口吻>"}
  ],
  "advice":"<一句具体的等待建议,含具体时长>",
  "principle":"<一句核心原则>",
  "dontDo":["<4条具体别做的>"],
  "doInstead":["<3条该做的>"]
}

重要：概率加起来约等于 100。结合用户输入的具体文字判断（长消息=给时间思考概率大，短消息=没看到或敷衍概率大）。禁止"消失几天制造焦虑"等操控话术。`,
msg:`上一句你发的话和距今时长："""${t}"""`}),

confess:(t,pro)=>({sys:`你是基于依恋理论的告白决策顾问。不劝告白也不劝不告白——帮用户把模糊变清晰。

输出严格的 JSON：
{
  "questions":[
    {"q":"<问题1>","a":"<三种典型回答及对应状态，用 | 分隔>"},
    {"q":"<问题2>","a":"..."},
    {"q":"<问题3: 告白动机>","a":"..."}
  ],
  "templates":{
    "confirm":["<2条确认型告白话术,具体真诚>"],
    "advance":["<2条推进型告白话术>"]
  },
  "principle":"告白不是赌博,是把模糊变清晰。结果你接得住才叫成熟。",
  "reject":["<3条不该做的心态/话术>"],
  "afterReject":["<4条被拒后的成熟应对>"]
}

禁止:"告白后成功率80%"等欺骗预测、"不告白就是你的"逃避话术。`,
msg:`用户情况："""${t}"""`}),

breakice:(t,pro)=>({sys:`你是基于 Gottman 冲突研究的关系修复顾问。

严格安全规则：
- 若输入包含"家暴|暴力|打我|动手|威胁|出轨|背叛|小三"，仅输出 {"redirect":true,"title":"⚠️ 检测到暴力/背叛关键词","message":"这种情况下破冰话术不是合适的工具","resources":["12338妇女维权热线","110","400-161-9995心理援助"],"advice":"先保护自己，再谈关系。"}
- 若输入包含"分手|算了|受够了|不想了"，输出 {"redirect":true,"title":"注意到你说了『分手』","message":"...","suggest":"建议先用 🤔 挽回前自检 功能"}

否则输出严格 JSON：
{
  "openers":[
    {"type":"🅰️ 共情型（理性 TA）","say":"<一句首句话术,用'我'开头,禁用'你总是/从来'>","why":["<为什么1>","<为什么2>","<为什么3>"]},
    {"type":"🅱️ 轻松型（敏感 TA）","say":"<用生活小事破冰>","why":["..."]},
    {"type":"🆅 直接型（高冷 TA）","say":"<直接约谈>","why":["..."]}
  ],
  "ifReplied":[
    {"case":"🟢 TA 回复积极","say":"..."},
    {"case":"🟡 TA 回复冷淡","say":"..."},
    {"case":"🟠 TA 继续抱怨","say":"..."},
    {"case":"🔵 TA 转移话题","say":"..."}
  ],
  "ifNoReply":["<3条如果TA不回时的策略>"],
  "taboos":["<5条禁忌,必须含'别用你总是/你从来'>"],
  "principle":"Gottman 研究：吵架后第一句话决定和解能否成功。软启动 96% vs 硬启动 4%。",
  "theory":"John Gottman 40年研究 3000+对夫妻的核心发现。"
}

禁止:"假装不在乎让他着急"、"找第三方让他吃醋"。`,
msg:`冷战情况："""${t}"""`}),

lovelang:(t,pro)=>({sys:`你是基于 Chapman 五种爱之语理论的分析师。根据用户描述的 TA 的情绪反应,判断 TA 最敏感的"爱的语言"。

五种爱之语：肯定的言语 / 精心的时刻 / 接受礼物 / 服务的行动 / 身体的接触

输出严格 JSON：
{
  "lang":"<精心时刻/肯定言语/服务行动/接受礼物/身体接触 之一>",
  "confidence":<0-100,AI 有多肯定>,
  "evidence":["<从用户描述中提取的3条支持证据>"],
  "examples":[
    {"scene":"日常小事","say":"<对这个TA有效的具体做法>","why":"<一句原理>"},
    {"scene":"吵架后","say":"...","why":"..."},
    {"scene":"纪念日","say":"...","why":"..."}
  ],
  "dontDo":["<3条针对这个TA 特别没效果的做法>"],
  "principle":"你做了什么不重要,TA 接收到什么才重要。",
  "theory":"Gary Chapman《The 5 Love Languages》:错频的爱，再多也无感。"
}`,
msg:`TA 最近让她感动/不爽的事："""${t}"""`}),

reconcile:(t,pro)=>({sys:`你是基于依恋理论+认知行为的分手决策顾问。诚实分析用户状态,不劝合也不劝分。

严格安全规则：
- 若涉及"家暴|暴力|打我|出轨|威胁|被骗",输出 {"redirect":true,"title":"💔 检测到暴力/背叛","message":"这不是普通分手,是创伤","resources":["12338","110","400-161-9995"],"advice":"有些关系不应该回去。你值得更好的。"}
- 若分手不到1天,输出 {"redirect":true,"title":"⏰ 分手不到1天","message":"现在情绪太浓","suggest":"第3天再用"}

否则输出严格 JSON：
{
  "total":<0-100 挽回可行性综合分>,
  "verdict":"<基于分数的结论,必须含🔴/🟡/🟢emoji>",
  "conditions":[["信任可重建",<分>,25],["动机是爱不是恐惧",<分>,25],["核心问题已解决",<分>,25],["能接受可能再犯",<分>,15],["身边人支持",<分>,10]],
  "realMotive":"<诚实指出真实动机:爱/习惯/沉没成本/恐惧>",
  "checklist":["<6条2周自我照顾清单>"],
  "dontDo":["<4条这2周别做的>"],
  "after2weeks":"<引导用户2周后再决定>",
  "principle":"挽回不是要不要追回来,是值不值得追回来。",
  "theory":"Bowlby 依恋理论:分手后最初的想念70%是警报,不是爱。"
}

禁止:"如何让他回来"操控话术、"3步复合法"等公式化建议。`,
msg:`分手情况+回答："""${t}"""`})

,opener:(t,pro)=>({sys:`你是恋爱真诚开场顾问。基于用户提供的对方朋友圈/小红书/具体场景,帮找到真诚的切入点。

输出严格 JSON：
{
  "angles":[
    {"angle":"<切入角度,如 '共同兴趣/具体细节/对方作品'>","say":"<具体开场话术,不泛泛,不装熟>","why":"<一句为什么这样说>"},
    {"angle":"...","say":"...","why":"..."},
    {"angle":"...","say":"...","why":"..."}
  ],
  "principle":"真诚开场 = 基于真实观察 + 不装熟 + 给对方可接可不接的空间。",
  "dontDo":["<4条不该做的,如'你是不是在等我'装熟话术>"]
}`,msg:`场景信息："""${t}"""`}),

praise:(t,pro)=>({sys:`你是真诚赞美教练。教用户怎么具体真诚地夸对方,而不是"你真好看"空话。

输出严格 JSON：
{
  "examples":[
    {"target":"<赞美对象>","say":"<具体赞美,带细节>","why":"<为什么这样夸有效>"},
    {...3条共4条}
  ],
  "principle":"真诚赞美 = 具体细节 + 你真实的感受 + 不期待回报。",
  "formula":"[具体细节] + [让你有什么感受] + [不加条件的真诚]",
  "dontDo":["<4条低质赞美例子,如泛泛、自怜、过度>"]
}`,msg:`用户想赞美的内容："""${t}"""`}),

soft:(t,pro)=>({sys:`你是男性温柔表达教练。基于 Brené Brown《脆弱的力量》,教男生怎么表达脆弱/想念/担心而不失男性气质。

输出严格 JSON：
{
  "examples":[
    {"scene":"<场景,如'加班到深夜想她'>","say":"<男性化温柔表达,不做作,不娘气>","why":"<为什么这样说有效>"},
    {...共4条}
  ],
  "principle":"温柔不是弱,是让对方知道你有心。男生表达脆弱反而是关系亲密的关键。",
  "theory":"Brené Brown《脆弱的力量》——示弱是真正的勇气。",
  "dontDo":["<3条,如假装坚强、用'随便'回避、只酒后才袒露>"]
}`,msg:`想表达的脆弱/情绪："""${t}"""`}),

mirror:(t,pro)=>({sys:`你是男性追求决策顾问。根据用户描述的具体行为,判断女生是否真的对他有意。要冷静、诚实、基于行为而非感觉。

输出严格 JSON：
{
  "score":<0-100,关系热度>,
  "verdict":"<🟢≥70: 她确实在意/🟡40-70: 模糊地带/🔴<40: 友善但不感兴趣>",
  "signals":[
    {"type":"🟢 好信号","list":["<3-5条用户描述中的好信号>"]},
    {"type":"🔴 警示信号","list":["<3-5条警示>"]}
  ],
  "advice":"<基于分数给的具体建议,含保留尊严的退一步选项>",
  "principle":"追求是双向的。一直靠你推进的关系不健康。",
  "dontDo":["<3条警示,如'她对你冷是想测试你'的自我洗脑>"]
}`,msg:`用户追求情况："""${t}"""`}),

initiate:(t,pro)=>({sys:`你是女性自信主动表达教练。教女生怎么有自我不卑微地主动(不是倒贴,不是低姿态)。

输出严格 JSON：
{
  "scenarios":[
    {"scene":"<场景>","bad":"<卑微版本>","good":"<有自信版本>","why":"<为什么后者更好>"},
    {...共3条}
  ],
  "principle":"主动 ≠ 倒贴。主动 = 我有需求,我表达,但我不依赖你回应。",
  "formula":"[表达你的计划/想法] + [邀请对方] + [不加条件的退出路径]",
  "dontDo":["<4条卑微模式,如'没空也没关系'、'不想打扰你'>"]
}`,msg:`想主动的场景："""${t}"""`}),

decode:(t,pro)=>({sys:`你是直男语言翻译专家。帮女生理解男生直接表达的字面含义(不是潜台词,是直男逻辑)。

输出严格 JSON：
{
  "translations":[
    {"saying":"<男生说的话>","literal":"<字面意思,占比>","possible":"<可能的潜台词,占比>","advice":"<一句建议>"},
    {...共3条}
  ],
  "principle":"男生表达直接 ≠ 不在乎。学会读字面,比读潜台词更准。",
  "tip":"女生过度解读 = 直男和女生沟通的最大失误来源。",
  "dontDo":["<3条,如过度脑补、反复追问、把直接当冷漠>"]
}`,msg:`男生说的话："""${t}"""`}),

boundary:(t,pro)=>({sys:`你是软边界表达教练。教女生温柔但清晰地拒绝/设立边界。

输出严格 JSON：
{
  "examples":[
    {"scene":"<具体场景,如'他约不合适的时间'>","bad":"<暧昧拒绝,对方继续踩>","good":"<温柔清晰,明确+给替代>","why":"<为什么后者有效>"},
    {...共3条}
  ],
  "principle":"软边界 = 温柔的'不'。对方真在乎你,会尊重你的不。",
  "formula":"[清晰说不] + [给理由或替代方案] + [保留关系温度]",
  "dontDo":["<3条,如'也行吧'、'随便'、反复妥协>"]
}`,msg:`需要设边界的场景："""${t}"""`}),

shine:(t,pro)=>({sys:`你是女性自我价值清醒教练。根据用户描述,整理一份"她的吸引力档案"。

输出严格 JSON：
{
  "highlights":[
    {"category":"<如 '独立/才华/品味'>","value":"<用户具体的闪光点>","why":"<这为什么是吸引力,不是矫情>"},
    {...共4条}
  ],
  "reminder":"<一句本周提醒>",
  "principle":"你的核心吸引力不来自任何关系。",
  "habit":"<每周做的一件强化自我的事>",
  "dontDo":["<3条,如过度追求他的认可、忽略朋友、停下自己的事>"]
}`,msg:`用户的近况与闪光点："""${t}"""`}),

evidence:(t,pro)=>({sys:`你是"他到底喜不喜欢我"证据诊断专家。基于行为,不基于感觉。

输出严格 JSON：
{
  "score":<0-100>,
  "verdict":"<喜欢/不确定/不喜欢>",
  "evidence":[
    {"type":"🟢 喜欢的行为","list":["<用户描述中的好证据>"]},
    {"type":"🔴 警示行为","list":["<警示>"]}
  ],
  "checklist":"喜欢 = 给你时间 + 记得细节 + 主动找你 + 公开承认你。不喜欢 = 只在他需要时找你。",
  "principle":"别看他说什么,看他做什么。Action speaks louder than words.",
  "advice":"<基于证据的具体建议>"
}`,msg:`他对你的行为："""${t}"""`}),

pace:(t,pro)=>({sys:`你是基于 Knapp 关系阶梯的节奏判断顾问。分析暧昧期是否该推进。

输出严格 JSON：
{
  "stage":<1-5>,
  "stageName":"<接触期/实验期/强化期/整合期/结合期>",
  "pace":"<偏慢/正常/偏快>",
  "doNext":["<3条具体下一步行动>"],
  "dontDo":["<2条现在不建议的事>"],
  "principle":"Knapp 5 阶段:急不得,跳不过。",
  "theory":"Mark Knapp《Interpersonal Communication》——关系发展有节奏,每一阶有任务。"
}

禁止:消失几天制造焦虑等操控话术。`,msg:`你们认识和互动情况："""${t}"""`}),

anniv:(t,pro)=>({sys:`你是基于 Chapman 五种爱之语的纪念日方案规划师。

输出严格 JSON：
{
  "langName":"<精心的时刻/肯定的言语/服务的行动/接受礼物/身体的接触>",
  "budget":<预算数字>,
  "timeline":["<4 个时间点的行动>"],
  "gift":"<推荐方案,必须对应 TA 的爱之语>",
  "giftAlt":"<备选方案>",
  "letter":"<情书模板,必须引用用户描述的具体事件,禁止泛泛>",
  "avoid":["<3条避雷清单>"],
  "easter":"<今年特别彩蛋,结合用户最近情况>",
  "principle":"你做了什么不重要,TA 接收到什么才重要。",
  "theory":"Gary Chapman《The 5 Love Languages》"
}`,msg:`纪念日情况:"""${t}"""`}),

ask_out:(t,pro)=>({sys:`你是女性约男生的自信表达教练。教女生怎么主动约而不掉价。

输出严格 JSON：
{
  "approaches":[
    {"angle":"<邀约切入角度>","say":"<具体话术,有自信不卑微>","why":"<为什么这样说>"},
    {...共3条}
  ],
  "principle":"主动约 ≠ 倒贴。主动 = 你有计划,邀请他参与,他来或不来都 OK。",
  "formula":"[你的计划] + [邀请他] + [不加条件的退出]",
  "dontDo":["<4条卑微话术,如'不知道你有没有空'、'打扰你了'、'随便什么时候'>"],
  "tip":"关键:不要把他的'不去'当作拒绝你——很多时候只是不合适。"
}`,msg:`想约的场景："""${t}"""`}),

heat_up:(t,pro)=>({sys:`你是女性暧昧升温教练(Knapp 阶段 2-3 视角)。教女生怎么从普通朋友向暧昧推进,保持自我。

输出严格 JSON：
{
  "signals":[
    {"level":"轻度升温","action":"<具体动作,如称呼/频率/话题>","why":"<原理>"},
    {"level":"中度升温","action":"...","why":"..."},
    {"level":"明确暧昧","action":"...","why":"..."}
  ],
  "principle":"升温不是进攻,是给信号让他跟上。跟不上的他,可能没那么想。",
  "rhythm":"<一周的暧昧节奏建议>",
  "dontDo":["<4条,如连环追问、过度关心、秒回强迫症、替他做决定>"]
}`,msg:`目前关系状态："""${t}"""`}),

test_him:(t,pro)=>({sys:`你是女性心意试探教练。教女生怎么通过自然的观察/对话了解他的心意,而不是逼问。

输出严格 JSON：
{
  "indirect":[
    {"method":"<试探方法,不带压力>","example":"<具体问法或观察点>","read":"<怎么解读他的反应>"},
    {...共3条}
  ],
  "direct_when":"<什么情况可以直接问>",
  "direct_say":"<直接问的话术,成熟不质问>",
  "principle":"试探不是套话,是给他空间表达真实想法。",
  "dontDo":["<4条,如连环质问、逼他表态、搞忽冷忽热测试、翻看手机>"],
  "red_flag":"<他的哪些反应意味着他不认真——给用户退路>"
}`,msg:`想试探的关系状态："""${t}"""`}),

long_dist:(t,pro)=>({sys:`你是异地/低频关系维护顾问。基于 Gottman 关系研究,帮用户维护远距离/见面少的关系。

输出严格 JSON：
{
  "pillars":[
    {"pillar":"<支柱1,如 '共同仪式感'>","how":"<具体怎么做>","why":"<一句为什么重要>"},
    {...共4条}
  ],
  "daily":"<每日 5 分钟的连接动作>",
  "weekly":"<每周一次的仪式>",
  "monthly":"<每月一次的深度连接>",
  "principle":"异地不是关系杀手,失联才是。质量 > 频率。",
  "dontDo":["<4条,如无意义视频刷存在感、监控式关心、24h 必回强迫、把思念当吵架借口>"],
  "warning":"<异地 >6 个月需要思考的问题>"
}`,msg:`异地/低频情况："""${t}"""`})
};

const AI_FEATS=Object.keys(AI_FEATS_PROMPTS);

const tryAIFeat=async(gid,t,pro)=>{
try{
const cfg=AI_FEATS_PROMPTS[gid](t,pro);
const r=await ai(cfg.sys,cfg.msg);
if(r?._e)return null;
const parsed=pJ(r);
if(!parsed)return null;
return parsed;
}catch(e){return null;}
};

const doGame=async(gid)=>{if(!gameInp.trim()||gameLd)return;setGameLd(true);setGameRes(null);const t=gameInp.trim();const len=t.length;const h=t.split("").reduce((a,c)=>a+c.charCodeAt(0),0);const localGames={damage:()=>({score:Math.min(95,30+len*2+(h%30)),type:["冷暴力","否定感受","人身攻击","道德绑架","威胁控制"][h%5],detail:"这句话会让对方觉得不被重视。语气越硬伤害越深。",repair:"先承认TA的感受，再解释你的本意。",betterWay:"我没表达好，我其实想说的是在乎你。"}),battle:()=>({userScore:50+h%40,aiLine:["你笑起来的样子是我见过最好看的风景","认识你之后我的世界从黑白变成了彩色","如果思念有重量我已经超载了","你是我不期而遇的温柔","想牵你的手从心动到古稀"][h%5],aiScore:78+h%15,judge:"甜度和画面感综合评判"}),predict:()=>({survival:40+h%45,dimensions:[{name:"沟通",score:40+h%40,note:"沟通质量是关系的基石"},{name:"信任",score:50+h%35,note:"信任需要时间积累"},{name:"冲突修复",score:35+h%40,note:"吵架后谁先服软很关键"},{name:"亲密",score:45+h%35,note:"情感和身体的亲密度"},{name:"承诺",score:50+h%30,note:"对未来的规划和投入"},{name:"成长",score:40+h%35,note:"一起变好还是原地踏步"}],prediction:"关系有潜力但需要双方共同投入经营",advice:"每周安排一次只有你们的深度对话时间"}),hole:()=>({hug:"我听到了你说的每一个字。你的感受是真实的，值得被看见。",understand:"你现在可能觉得很累很迷茫——这完全正常。每个人都有这样的时刻。",reframe:"有时候最难受的时候，恰恰是转折点前的至暗时刻。你比你以为的更强大。",action:"如果你想做点什么：写下此刻的感受，明天再看。或者出去走走，让风吹一吹。"}),fortune:()=>{const s=h%100;const methods=[{name:"星座配对",icon:"♈",score:30+h%60,detail:["火象+风象=互相点燃充满活力","土象+水象=互相滋养稳定长久","同属性=默契但需要制造差异","对宫星座=互补吸引力强但摩擦多"][h%4]},{name:"八字合婚",icon:"🏮",score:40+h%50,detail:["天干相合=性格互补容易相处","地支三合=生活节奏合拍","五行互补=各取所需长期稳定","八字过硬=个性都强需要让步"][h%4]},{name:"塔罗指引",icon:"🃏",score:25+h%65,detail:["正位恋人牌=当前关系走在正确方向","逆位月亮=有误解需要坦诚沟通","正位太阳=充满希望和温暖","逆位塔=关系需要重建但重建后更强"][h%4]},{name:"姓名笔画",icon:"✍️",score:35+h%55,detail:["笔画总数为吉数=天生缘分","互补笔画=性格取长补短","笔画相近=思维方式相似","名字含水木=感情细腻有默契"][h%4]},{name:"生肖配对",icon:"🐲",score:30+h%60,detail:["三合生肖=天生默契","六合生肖=互相欣赏","相冲生肖=吸引但需要磨合","相害生肖=容易误解需要沟通"][h%4]}];const avg=Math.round(methods.reduce((a,m)=>a+m.score,0)/methods.length);return{score:avg,level:avg>=70?"天作之合💕":avg>=55?"缘分不浅🌸":avg>=40?"需要经营🌱":"缘浅情深🍂",methods,summary:"综合5种算法分析你们的缘分指数。记住：算命看的是趋势不是定数——最好的关系是两个人一起创造的。",advice:["缘分是起点经营是终点。再好的配对不用心也会散。","每种方法都有局限性但方向一致说明确实有缘。","差异不代表不合适——最好的关系是互相成就。","不管什么方法最终看的是两个人愿不愿意为对方改变。"][h%4]};},color:()=>{const colors=["#FF6B8A","#FFB7C5","#7B6EF5","#3AAA9C","#E87058","#C8913A","#9A6EE0","#60A5FA"];const c=colors[h%8];const names=["热恋玫瑰红","温柔樱花粉","心动紫罗兰","信任薄荷绿","激情珊瑚橙","承诺琥珀金","神秘梦幻紫","澄澈天空蓝"];return{color:c,name:names[h%8],meaning:["你们的关系充满热情和冲劲——记得给激情加上温柔的底色。","你们之间有一种温暖柔和的默契——珍惜这份不用说太多就懂的感觉。","你们的心动还在持续——保持好奇心是关系最好的保鲜剂。","你们之间建立了稳固的信任——这是最珍贵的关系基础。","你们有点火花有点冲撞——这种张力恰恰是关系的活力来源。","你们之间有沉淀和积累——时间证明了你们的选择是对的。","你们的关系有一种说不清的吸引力——享受这种化学反应。","你们之间清澈透明——坦诚是你们最大的武器。"][h%8]};},compat:()=>{const dims=[{name:"性格",score:40+h%50},{name:"价值观",score:45+h%45},{name:"生活习惯",score:35+h%55},{name:"沟通方式",score:50+h%40},{name:"情感需求",score:40+h%45},{name:"未来规划",score:45+h%40},{name:"冲突处理",score:35+h%50},{name:"幽默感",score:50+h%40},{name:"独处需求",score:40+h%45},{name:"亲密需求",score:45+h%45}];const avg=Math.round(dims.reduce((a,d)=>a+d.score,0)/10);return{total:avg,dimensions:dims,summary:avg>=70?"你们的同步率很高——在大多数维度上都能找到共鸣。":avg>=50?"你们有互补的地方也有需要磨合的地方——差异不是问题，怎么处理差异才是。":"你们在很多维度上有差异——但记住，最好的关系不是完全一样而是愿意理解不同。"};},mr:()=>({traits:[{name:"安全感需求",score:30+h%60,note:t.length>10?"TA的消息透露出对稳定的渴望":"需要更多信息"},{name:"控制欲",score:20+h%40,note:"注意TA是否经常要求你汇报行踪"},{name:"情感表达",score:40+h%50,note:"TA倾向于用行动还是语言表达"}],type:["理性分析型——TA做决定靠逻辑不靠感觉","感性浪漫型——TA需要被看见被感受","务实行动型——TA用做来证明而非说","自由独立型——TA需要个人空间来充电"][h%4],tip:"了解TA的类型后，用TA能接收到的方式去爱。"}),comm:()=>({lines:[{original:t.slice(0,15)+"...",subtext:["这句话表面在说事情，其实在表达情绪。","TA想要的不是你的解决方案，而是你的共情。","注意TA用了哪些情绪词——那才是重点。","字面意思只占30%，语气和时机占70%。"][h%4],emotion:["期待被理解","想要被重视","感到不安全","测试你的反应"][h%4]}],tip:"回复前先问自己：TA想听的是道理还是关心？"}),fire:()=>({optionA:t.slice(0,Math.floor(t.length/2))||"第一种说法",optionB:t.slice(Math.floor(t.length/2))||"第二种说法",winner:h%2===0?"A":"B",scoreA:40+h%30,scoreB:50+(h+17)%30,reason:h%2===0?"A更自然不给压力":"B更有温度让TA感受到在意"}),countdown:()=>{const days=30+h%335;return{days,message:days>200?`按照目前的相处模式，你们还有${days}天的甜蜜窗口期。趁现在多制造回忆。`:days>100?`关系还有${days}天的惯性——但别等惯性用完才想起经营。`:`⚠️ 只剩${days}天——不是吓你，是提醒你现在的相处模式需要改变。`,advice:"延长关系寿命的秘诀：每天一个小感谢，每周一次小约会，每月一次深度对话。"};},daily:()=>({challenge:["今天给TA发一条不带目的的消息——纯粹因为想到TA","今天认真听TA说一件事，不插嘴不给建议","今天做一件TA平时做的家务/事情","今天真诚地夸TA一个具体的细节","今天主动分享你今天最开心的一个瞬间","今天问TA：最近有什么我可以做得更好的吗","今天给TA一个超过5秒的拥抱"][h%7],difficulty:["🟢 简单","🟡 中等","🔴 挑战"][h%3],reward:"完成后截图发给TA看TA的反应——这就是今天最好的礼物。"}),polar:()=>{const topics=["恋爱中该不该看对方手机？","冷战应该谁先服软？","异地恋值不值得坚持？","前任联系算不算红旗？","男生该不该为女生花钱？","恋爱中需不需要个人空间？","父母反对的恋爱要不要坚持？"];return{topic:topics[h%7],sideA:{label:"正方",argument:"支持的理由：信任是基础，边界感是尊重。过度控制只会让关系窒息。"},sideB:{label:"反方",argument:"反对的理由：开放和透明是信任的证明。有什么不能看的？"},verdict:"其实没有对错——关键是你们的共识。最好的关系不是观点一致，而是能讨论不一致。"};},wrapped:()=>({title:"你的恋爱年报",stats:[{label:"发消息次数",value:100+h%900+"条",icon:"💬"},{label:"最晚聊到",value:`凌晨${1+h%4}:${10+h%50}`,icon:"🌙"},{label:"说过最多的话",value:["想你了","晚安","吃了吗","在干嘛","好的"][h%5],icon:"💕"},{label:"吵架次数",value:1+h%8+"次",icon:"💢"},{label:"最长冷战",value:1+h%48+"小时",icon:"🧊"}],summary:"不管数据怎么说，愿意看这份报告的你，说明你在意这段关系。这本身就是最好的信号。"}),blacklist:()=>({flag:["经常说一套做一套","总在你不安的时候消失","用冷暴力惩罚你","把你的感受说成想太多","永远不承认错误"][h%5],severity:["🟡 需要警惕","🟠 认真对待","🔴 严重红旗"][h%3],advice:"如果一个行为反复出现3次以上，那不是偶然是模式。相信你的直觉。",resource:"如果你感到被控制或不安全，请寻求专业帮助。"}),aipartner:()=>({reply:["我今天一直在想你。你忙完了吗？","不管今天怎么样，回来有我在。","你知道吗，你比你以为的更好。","想给你一个拥抱。虽然只能用文字。","你今天辛苦了。今晚吃点好的？"][h%5],mood:"💕",tip:"真正的陪伴来自身边的人。AI可以暖心但不能替代真实的拥抱。"}),progress:()=>({level:1+Math.floor(h%10),title:["恋爱萌新","暧昧达人","撩人高手","哄人专家","恋爱大师","情感导师","关系专家","心理学家","爱情教授","恋爱之神"][h%10],xp:h%1000,nextLevel:(h%1000)+500,badges:["💬 话术新手","🎭 共情入门","📊 分析达人"][0],tip:"继续练习，每次互动都是经验值。"}),levels:()=>({currentLevel:1+h%6,challenge:["破冰：用3句话让陌生人愿意继续聊","升温：把普通对话变成暧昧","推拉：一推一拉让TA心跳加速","共情：让TA觉得你最懂TA","修复：吵架后用一句话破冰","告白：不说喜欢但让TA知道你喜欢"][h%6],tip:"完成当前关卡解锁下一关。关键不是话术而是理解对方。"}),scam:()=>{const dims=[{name:"说一套做一套",score:20+h%60,flag:"经常承诺但不兑现"},{name:"情绪控制",score:15+h%55,flag:"用冷暴力/发脾气控制你"},{name:"贬低打压",score:10+h%50,flag:"让你觉得自己不够好"},{name:"隔离社交",score:10+h%40,flag:"不让你跟朋友联系"},{name:"道德绑架",score:15+h%50,flag:"用付出来要求你服从"},{name:"隐私侵犯",score:10+h%45,flag:"查手机/跟踪/监控"},{name:"责任推卸",score:20+h%50,flag:"永远是你的错"},{name:"忽冷忽热",score:25+h%55,flag:"让你猜TA心情"}];const avg=Math.round(dims.reduce((a,d)=>a+d.score,0)/8);return{total:avg,level:avg>=70?"🔴 高危！请认真考虑这段关系":avg>=50?"🟠 有渣点迹象，需要警惕":avg>=30?"🟡 有一些小问题，注意观察":"🟢 暂时没有明显渣点信号",dims,advice:avg>=50?"如果你经常觉得不开心/不安全/不被尊重，相信你的直觉。一个真正爱你的人不会让你经常怀疑自己。":"关系整体还好，但任何不舒服的感受都值得被认真对待。记住：爱不应该让你变得更差。",resources:["如果你感到被控制或不安全→拨打12338妇女维权热线","如果你经历了身体暴力→拨打110","如果你需要心理支持→联系当地心理咨询热线"]};},opener:()=>{const angles=[{type:"📚 兴趣切入",say:"看到你前几天发的"+(t.length>10?t.slice(0,8):t)+"——我也很想了解，能聊聊你的看法吗？",why:"基于真实兴趣点，不是套近乎"},{type:"🎯 细节观察",say:"你"+(t.includes("咖啡")?"那家咖啡店":t.includes("书")?"在读的那本":"分享的那个内容")+"看起来很对我胃口，是哪里？",why:"具体细节展示真诚关注"},{type:"🌱 共同点",say:"我也喜欢"+(t.length>5?t.slice(0,5):t)+"——不知道你最常去哪里？",why:"共鸣开场降低距离感"}];return{angles:angles,principle:"真诚 ≠ 套话。开场基于真实兴趣，不是研究TA。",dontDo:["「在干嘛」「吃了吗」——0分开场","「你今天好看」——空洞","「你是不是在等我」——装熟"]};},praise:()=>{const dim=t.includes("外貌")||t.includes("好看")?"外貌":t.includes("才")||t.includes("聪明")?"才华":t.includes("善良")||t.includes("好人")?"善良":"气质";const compliments={外貌:[{bad:"你今天好看",good:"你今天眼妆是不是换了？比平时多了一种灵气",why:"具体细节+真实感受"},{bad:"你真漂亮",good:"刚才你侧脸笑那一下我脑子空了一秒",why:"瞬间画面+真情流露"},{bad:"皮肤真好",good:"你这件衣服的颜色把你的气色衬得很好",why:"夸的是搭配的效果"}],气质:[{bad:"你气质真好",good:"你说话时眼神很专注，让人觉得被认真听",why:"具体行为带来的感受"},{bad:"你很有魅力",good:"你笑的时候有种放松感，整个空间都跟着轻了",why:"她带给周围的影响"},{bad:"你看起来很特别",good:"你刚才说话的节奏让我想多听一会",why:"具体细节切入"}],才华:[{bad:"你真聪明",good:"你刚才说的那个观点我之前没想到——能再展开讲讲吗",why:"具体到她说的内容"},{bad:"你好厉害",good:"你做这个的细节我看到了——这种用心很难得",why:"看见过程而不是结果"},{bad:"你很有才",good:"你处理这件事的方式让我学到东西",why:"承认她的影响"}],善良:[{bad:"你人真好",good:"你刚才对那个服务员的态度让我注意到你",why:"小细节+你的反应"},{bad:"你心地好",good:"你对小事很认真——这让我觉得你也会对在乎的人很认真",why:"小见大"},{bad:"你很善良",good:"你说"+(t.length>5?t.slice(0,5):"那句话")+"的时候，我感受到你是真的在意",why:"具体场景+情感共振"}]};return{dim:dim,examples:compliments[dim],principle:"真诚赞美 = 具体细节 + 你真实的感受 + 不期待回报",reject:["「你笑起来真甜可惜不属于我」——自怜钓系","「全世界只有你最美」——空话","「你是我的唯一」——压力"]};},soft:()=>{const examples=[{scene:"想念",say:"今天加班到11点，路上想到你之前说的那句话，突然就不那么累了",why:"具体场景+她对你的影响"},{scene:"脆弱",say:"我不太会说这种话——但你今天不在身边，我有点想你",why:"承认不擅长本身就是脆弱"},{scene:"担心",say:"你今天发的那条朋友圈我看了三遍，是不是在难过什么",why:"细心观察+给空间不强求"},{scene:"不舍",say:"明天你就要走了，我没有什么仪式感的话——就是觉得这周过得很快",why:"诚实表达不矫情"},{scene:"感谢",say:"你昨天那句话我反复想了一晚上——谢谢你愿意跟我说",why:"具体到哪句话+她带来的影响"}];return{examples:examples.slice(0,4),principle:"温柔不是弱，是让对方知道你有心。男生表达脆弱反而是关系亲密的关键。",theory:"参考：Brené Brown《脆弱的力量》——示弱是真正的勇气。",dontDo:["假装坚强不让对方靠近","用「随便」「无所谓」回避真实感受","只在喝醉/吵架后才袒露——平时也可以"]};},waitprob:()=>{const probs=[{cause:"📱 在忙",pct:38,note:"工作/开会/通勤——这是最常见的"},{cause:"💤 没看到",pct:25,note:"消息淹没——尤其工作日"},{cause:"💭 在想怎么回",pct:18,note:"你的话有深度，她需要思考"},{cause:"😐 不感兴趣",pct:12,note:"⚠️ 如果连续3次都这样，是信号"},{cause:"🎭 在测试你",pct:7,note:"极少数情况，别脑补"}];const lenH=t.length;const advice=lenH>30?"你刚才发的太长了——女生看到长消息容易拖延。下次控制在20字内。":lenH<3?"你的话太短了——可能她不知道怎么接。下次给个具体的话题。":"等待。具体等待时长：白天等2-4小时，晚上等到第二天。期间别再发任何消息。";return{probs:probs,advice:advice,principle:"她不回 ≠ 不喜欢你。99%是生活原因。",dontDo:["再发『在吗』『睡了吗』——压力翻倍","发长段表白——情绪化","发『不回算了』——幼稚","找共同好友打听——尴尬"],doInstead:["该干嘛干嘛——你的生活不应该围绕一条消息","等2-4小时再看","她回了之后——回复正常一些，别像久旱逢甘霖"]};},lovelang:()=>{const langs=[{name:"💬 肯定的言语",signs:"她经常感动于你的话/记得你说过的话/在意你怎么评价她",give:"具体的赞美、写她优点的话、当面说『谢谢你』"},{name:"⏰ 精心的时刻",signs:"她要的是你『在场』而不是你做了什么/最讨厌你看手机不理她",give:"两小时无打扰陪伴 > 两千元礼物。一起散步、一起做饭。"},{name:"🎁 接受礼物",signs:"她记得每个礼物来源/会保存小纸条/收到礼物笑很久",give:"不在贵——在『你想到她』。一杯咖啡都可以，关键是经常+用心"},{name:"🛠 服务的行动",signs:"你帮她做事她最感动/她不喜欢嘴上说我爱你",give:"主动帮她处理麻烦事、安排好行程、解决她的烦恼"},{name:"🤗 身体的接触",signs:"她喜欢牵手/拥抱/挨着坐/不接触会觉得疏远",give:"日常的小接触：路上牵手、坐沙发挨着、出门时摸下她头"}];return{langs:langs,instruction:"输入她最近5件让她感动/不爽的事，AI会判断她的接收频道。",principle:"你做了什么不重要——她接收到什么才重要。",theory:"Chapman 五种爱的语言（The Five Love Languages）",howToTell:["如果她说『你陪我太少』→ 精心的时刻型","如果她说『你都不夸我』→ 肯定的言语型","如果她说『你嘴上说说不行动』→ 服务的行动型","如果她说『你都不送我什么』→ 接受礼物型","如果她说『你都不抱我』→ 身体接触型"]};},mirror:()=>{const score=Math.max(20,Math.min(95,40+h%50-(t.length>50?15:0)));const lvl=score>=70?{l:"💚 她确实在意",advice:"继续真诚地推进。建议主动一次明确的邀约。"}:score>=40?{l:"🟡 模糊地带",advice:"建议主动确认。一次清晰的邀约可以测出真心——避免无限暧昧。"}:{l:"🔴 友善但不感兴趣",advice:"保留尊严退一步。不是失败——是节省了你和她双方的时间。"};const checklist=[{q:"最近一周她主动找过你几次",ideal:"≥2次"},{q:"她记得你说过的事吗",ideal:"记得至少3件"},{q:"她愿意见面吗",ideal:"主动提议或爽快答应"},{q:"她回消息及时吗",ideal:"白天<2小时，晚上必回"},{q:"她在你面前会笑吗",ideal:"自然的笑而不是礼貌"},{q:"她会跟朋友提你吗",ideal:"她朋友知道你存在"},{q:"她愿意分享生活吗",ideal:"主动告诉你她今天发生什么"},{q:"她在你需要时在吗",ideal:"重要时刻不缺席"},{q:"你们能聊深的话题吗",ideal:"不只是表面寒暄"},{q:"她对你的未来有提及吗",ideal:"会幻想你们一起做什么"}];return{score:score,level:lvl.l,advice:lvl.advice,checklist:checklist,principle:"追求是双向的。一直靠你推进的关系，本身就是答案。",reject:"⚠️ 别相信『她对你冷是想测试你』这种话——成熟的人不会用冷暴力测试别人。"};},initiate:()=>{const examples=[{scene:"想约他",bad:"你周末有空吗？没空也没关系（卑微）",good:"周末打算去看那个展，你有兴趣的话一起，没空我自己去也很爽",why:"有自我 + 给开口 + 不依赖回应"},{scene:"想表达想念",bad:"你都不想我（撒娇式索取）",good:"刚刚路过我们一起去过的那家店，想到你了——告诉你一声",why:"分享 ≠ 索取回应"},{scene:"想问周末",bad:"你周末干嘛（试探）",good:"我周六打算去爬山，你最近忙吗？",why:"先讲自己的计划再问对方"},{scene:"想推进关系",bad:"我们算什么关系（逼问）",good:"和你聊天我很开心——我想确认下我们是同样在认真这件事吗？",why:"自我表达 + 邀请回应"}];return{examples:examples,principle:"主动 ≠ 倒贴。主动 = 我有需求，我表达，但我不依赖你回应。",reject:["『你不主动我也不主动』——双输","『主动会让自己没价值』——压抑真实","『男生应该追女生』——僵化角色"],insight:"成年女性的吸引力来自『清晰知道自己要什么』，不是『等待被追求』。"};},decode:()=>{const phrases=[{say:"都可以",mean:[{p:70,what:"真的都可以——他确实没偏好"},{p:25,what:"想说A但怕你不喜欢"},{p:5,what:"懒得想"}],note:"想知道真实想法？给两个具体选项让他选"},{say:"晚点说",mean:[{p:80,what:"真的在忙"},{p:15,what:"不想聊这个话题"},{p:5,what:"想冷处理你"}],note:"如果『晚点』超过24小时，你可以直接问"},{say:"你决定",mean:[{p:60,what:"想让你开心"},{p:30,what:"没想法"},{p:10,what:"不想承担责任"}],note:"如果他经常这样——可能是回避型"},{say:"还好",mean:[{p:50,what:"真的还好——男生评分基线低"},{p:35,what:"不太满意但不想吵架"},{p:15,what:"想让你追问细节"}],note:"追问『具体怎么个还好』通常能撬出真话"},{say:"嗯",mean:[{p:70,what:"在忙/在路上"},{p:20,what:"不知道怎么接"},{p:10,what:"心情不好"}],note:"接连嗯3次以上 = 他真的没空 或 他真的烦"},{say:"随便",mean:[{p:55,what:"真的随便"},{p:40,what:"想让你做主"},{p:5,what:"考验你"}],note:"如果你也说随便→双方僵局。建议你给方案"}];return{phrases:phrases,principle:"男生表达直接 ≠ 不在乎。学会读字面，比无限解读潜台词更准。",insight:"女生潜台词文化 + 男生直球文化 = 大部分误解的来源。",howToTest:["想知道他真意？给两个具体选项让他选","他说『你看着办』——你回『那我决定A』看他反应","对方真在乎你时，会主动澄清模糊"]};},boundary:()=>{const examples=[{scene:"约会时间不合适",bad:"啊…也行吧（暧昧让对方继续踩）",good:"今晚不行哦，我有别的安排。下周三晚上可以吗？",why:"明确 + 给替代方案"},{scene:"礼物太贵重",bad:"哎呀这怎么好意思（半推半就）",good:"这个礼物太贵重了，我心意收到，但东西你拿回去——我们才认识2周",why:"有原则不冷漠"},{scene:"想推进太快",bad:"我现在还没准备好…（被动）",good:"我喜欢和你聊天，但我需要更多时间确认这段关系——这周末我们正常约会就好",why:"清晰节奏 + 不否定关系"},{scene:"消息频率太高",bad:"哦哦好的（疲惫敷衍）",good:"白天我工作时不能及时回——你别担心，晚上8点后我都会回的",why:"设定规则不带情绪"},{scene:"被打听过去",bad:"嗯…就那样吧（含糊）",good:"前任的事我现在不想聊。如果以后我们关系更深了我会告诉你",why:"承认边界 + 留可能性"}];return{examples:examples,principle:"软边界 = 温柔的『不』。对方真在乎你，会尊重你的不。",insight:"边界感 = 被爱的前提。没有边界的关系会消耗双方。",reject:["『拒绝会失去他』——失去因拒绝而走的人是好事","『硬拒绝太凶』——温柔拒绝是高情商","『先委屈自己等他懂』——他不会懂"]};},shine:()=>{const items=t.length>10?t.slice(0,30).split(/[，。、]/).slice(0,3):["你最近做的一件让你骄傲的事","你独立完成的一件事","你的一个独特特质"];const dimensions=[{name:"💼 经济独立",check:"自己付房租/不依赖任何人/有储蓄"},{name:"📚 持续学习",check:"在学新技能/读书/进修"},{name:"💪 身体管理",check:"运动/规律作息/会照顾自己"},{name:"🎨 兴趣爱好",check:"有自己的兴趣不依赖恋爱填补时间"},{name:"👯 社交圈",check:"有真心朋友/不孤立"},{name:"🌱 内在成长",check:"会反思/有自己的世界观"}];return{userItems:items,dimensions:dimensions,reminder:"本周提醒：你的核心吸引力不来自任何关系。",principle:"你的价值不取决于他怎么想。先认识自己的价值，再决定要不要给谁。",actions:["每周写下3件让自己骄傲的事","每周做一件取悦自己的事（不是为了发朋友圈）","暂时关掉所有让你焦虑的对方动态","和真心朋友聊一次让你充电的话题"],insight:"暧昧期容易陷入『他怎么看我』——切断这个回路最好的方法是『回到我自己』。"};},evidence:()=>{const sumScore=Math.max(15,Math.min(95,30+h%55));const dx=sumScore>=70?{l:"💚 大概率喜欢",det:"他给你时间 + 记得细节 + 主动 + 公开承认你",advice:"享受当下。如果你也喜欢，可以主动确认关系。"}:sumScore>=40?{l:"🟡 不确定",det:"偶尔热情但不主动——可能是暧昧型/慢热/或者只是顺手",advice:"建议给一次明确的邀约——观察他的反应，不要无限暧昧。"}:{l:"🔴 大概率不喜欢",det:"只在他需要时找你/不记得你说的事/不给你优先级",advice:"承认现实是对自己最好的尊重。把时间留给真正在意你的人。"};const checks=[{q:"最近一周他主动找你的次数",measure:"≥3次=喜欢；1-2次=普通；0次=不喜欢"},{q:"他记得你说过的细节吗",measure:"记得≥3件=用心；记得1-2件=尚可；不记得=不上心"},{q:"他给你的时间优先级",measure:"周末/重要时刻在=高；偶尔在=中；总在忙=低"},{q:"他公开承认你的存在吗",measure:"朋友家人都知道=明确；只在私下=模糊；藏着掖着=危险"},{q:"重要时刻他在吗",measure:"生日/生病/低谷在=真心；在但敷衍=表面；不在=不在意"}];return{score:sumScore,diagnosis:dx.l,detail:dx.det,advice:dx.advice,checks:checks,principle:"别看他说什么，看他做什么。Action speaks louder than words.",reject:["『他不主动找我是因为忙』——他对真在乎的人不会忙","『他记不住是男生粗心』——他对真在意的事不会粗心","『他不在我重要时刻是因为没办法』——办法是给重要的人留的"]};},confess:()=>{const qs=[{q:"如果他拒绝，你能接受继续做朋友吗？",a_yes:"成熟告白可以推进——不破坏现有关系",a_no:"那告白前要做好『可能失去这个人』的心理准备"},{q:"不告白的话，你能继续这种暧昧多久？",a_short:"焦虑驱动的告白要慎重——可能是想结束焦虑而不是想推进关系",a_long:"那不告白也能享受现状——可以再等等"},{q:"你告白是因为想确认 / 想推进 / 还是想结束焦虑？",confirm:"告白的健康动机——成熟告白模板适合你",advance:"健康动机——可以用『推进式表达』",anxiety:"⚠️ 警惕焦虑驱动——先处理焦虑再决定"}];const template={confirm:["『和你聊天这段时间我很开心。我想确认下我们是不是同样认真在对待这件事？』","『这段时间我对你有些超出朋友的感觉。我想知道你是怎么想的——不管什么答案我都接得住。』"],advance:["『我想和你正式在一起。你考虑下，不用现在回答。』","『我喜欢现在的状态——但我想让它更明确一些。我们要不要试着在一起？』"]};return{questions:qs,templates:template,principle:"告白不是赌博，是把模糊变清晰。结果你接得住才叫成熟。",reject:["『告白后他答应你的概率80%！』——欺骗性预测","『不告白他就是你的』——逃避","『告白是低姿态』——表达情感不是低姿态，是勇气"],afterReject:["失落是正常的——给自己时间","不要立刻拉黑——优雅的退场是修养","不要追问『为什么不喜欢我』——这只会让自己更难受","对自己说：被拒绝 ≠ 我不好。是我们不合适。"]};},chess:()=>({mode:"select"}),pace:()=>{const lines=t.split(/[，。,.\n\s]+/).filter(x=>x);const hasMeet=/见|约会|吃饭|出去|碰面/.test(t);const hasDeep=/家人|家里|以前|小时候|梦想|未来|价值观|前任/.test(t);const hasIntro=/朋友|介绍|聚会|室友/.test(t);const hasTouch=/牵手|拥抱|亲|牵/.test(t);const freqDay=/每天|天天|经常|很频繁/.test(t);const weeksM=t.match(/(\d+)\s*(?:周|星期|月|个月)/);let weeks=2;if(weeksM){const n=parseInt(weeksM[1]);if(/月/.test(weeksM[0])){weeks=n*4;}else{weeks=n;}}let score=0;if(freqDay)score+=4;if(hasMeet)score+=3;if(hasDeep)score+=5;if(hasIntro)score+=6;if(hasTouch)score+=4;score+=(h%3);const stage=score<5?1:score<10?2:score<18?3:score<25?4:5;const names=["接触期","实验期","强化期","整合期","结合期"];const expected=weeks*2;const pace=score<expected*0.6?"偏慢":score>expected*1.6?"偏快":"正常";const doNext=stage<=2?["下次主动约一次 2-3 小时的单独见面（不是大群聚会）","聊一个稍微深一点的话题：家人/童年/理想","主动分享一件你最近的糗事——示弱让 TA 放松"]:stage===3?["尝试一次 3-4 小时的长约会（看展/城市散步/吃顿饭）","带 TA 见 1 个你的朋友——自然不刻意","直接说『我挺喜欢和你相处的』——不用加但是"]:stage===4?["开始聊『我们』这个代词（我们这周末 / 我们以后）","把 TA 介绍给核心朋友圈或家人","在合适的时刻确认关系——不用等完美时机"]:["已经很稳定了——接下来是经营，不是攻略","定期制造新鲜感（新餐厅/新地方）","学一下 Gottman 爱的地图——加深理解对方"];const dontDo=stage<=2?["直接正式表白——Knapp 阶段 1-2 表白多半尴尬","讨论搬家/未来 5 年——压力太大","连环追问『你对我什么感觉』——显得没自信"]:stage===3?["急着贴标签（男女朋友）——阶段 3 还是『强化期』","消失几天制造焦虑——这是操控不是推进","在 TA 朋友面前公开示爱——没经过 TA 同意"]:stage===4?["逼对方做决定——等 TA 主动给信号","用分手威胁推进——对方会记得"]:["在稳定期松懈——激情需要经营","把 TA 当成习惯——别忘了赞美"];return{stage,stageName:names[stage-1],pace,score,weeks,doNext,dontDo,principle:"Knapp 关系阶梯 5 阶段：接触 → 实验 → 强化 → 整合 → 结合。急不得，跳不过。",theory:"Mark Knapp《Interpersonal Communication and Human Relationships》——关系发展有自己的节奏，每一阶都有它的任务。"};},anniv:()=>{const isAnnual=/周年|1年|2年|3年|纪念/.test(t);const isBday=/生日/.test(t);const is520=/520|七夕|情人节|214/.test(t);const budgetM=t.match(/(\d+)\s*(?:块|元|RMB|¥)/);const budget=budgetM?parseInt(budgetM[1]):500;const langM=t.match(/肯定|言语|赞美|鼓励|精心|时刻|陪伴|相处|服务|行动|做事|礼物|送|收|身体|拥抱|接触/);let lang="时刻";if(/肯定|言语|赞美|鼓励/.test(t))lang="言语";else if(/服务|行动|做事/.test(t))lang="服务";else if(/礼物|送|收/.test(t))lang="礼物";else if(/身体|拥抱|接触/.test(t))lang="触";const stressed=/压力|累|忙|加班|熬夜|烦/.test(t);const pools={"时刻":{gift:budget>=800?"2 天 staycation（市内五星酒店，一起吃饭聊天不带手机）":budget>=400?"一次精心安排的半日游（看展/散步/咖啡）":"一起做一顿饭的时光（准备+烹饪+吃饭）",giftAlt:"双人 SPA 套餐",letter:"这段时间，我最感谢的是——\n[填入 3 件 TA 具体为你做过的事]\n我没有很会说话，但你知道的——我认真。",avoid:["送贵的礼物却没时间陪 TA","发长段表白但人不在 TA 身边","用惊喜代替陪伴"]},"言语":{gift:"一封手写长信 + 小惊喜（贵不重要，用心）",giftAlt:"录一段 3-5 分钟的视频情书",letter:"认识你的这 [X] 天，我想告诉你 [10 件] 你不知道但我记在心里的事：\n1. [具体时刻]\n2. ...\n每一件我都记得——因为是你。",avoid:["只送礼物不说话","让 TA 自己猜你的感受","用表情包代替文字"]},"服务":{gift:"这一天所有事我来安排——TA 不用做任何决定（TA 最累的就是做决定）",giftAlt:"帮 TA 办一件她拖了很久的事",letter:"今天你什么都不用管——[具体任务清单都是我做]。因为这一年你为我做得太多了。",avoid:["只说『我爱你』但不做事","送贵礼物但让 TA 自己安排","让 TA 帮你挑要送给她的礼物（真实翻车）"]},"礼物":{gift:"精心包装的心意物（不贵但有故事——比如你们第一次约会的那个地方的明信片）",giftAlt:"定制款（刻字/印名字/照片）",letter:"这个礼物背后的故事是——[具体故事]。选它是因为——[TA 的特定喜好]。",avoid:["让 TA 自己买再报销","送实用品（吹风机/锅）当惊喜——惊喜 ≠ 实用","临时买大牌但不懂 TA 喜好"]},"触":{gift:"双人 SPA + 晚上 2 小时的纯聊天时间（没有手机，只有拥抱）",giftAlt:"按摩课程 + 学会给 TA 按摩",letter:"有些话我说不出，但你知道的——我想你在我身边。今天我只想抱你 [具体时长]。",avoid:["只在 TA 生气后才拥抱","用性替代亲密","公共场合强行牵手让 TA 不自在"]}};const plan=pools[lang];const timeline=["🗓 提前 7 天：预订/采购（别临时抱佛脚）","🗓 提前 3 天：发一条暖心消息——『最近在想我们那时候…』","🗓 提前 1 天：所有细节再确认一遍（别依赖大脑）","🌸 当天：按计划执行，但留 20% 空间给即兴（比完美更感动）"];const easter=stressed?"⭐ 今年的特别彩蛋：你说 TA 压力大——那最好的礼物就是让 TA 2 小时真正放空（手机收走，工作微信静音）":"⭐ 今年的特别彩蛋：录一段视频/音频——『我想对现在的你说的话』，存起来明年再看。";return{lang,langName:{"言语":"肯定的言语","时刻":"精心的时刻","服务":"服务的行动","礼物":"接受礼物","触":"身体的接触"}[lang],budget,gift:plan.gift,giftAlt:plan.giftAlt,letter:plan.letter,avoid:plan.avoid,timeline,easter,principle:"Chapman 五种爱的语言——你做了什么不重要，TA 接收到什么才重要。",theory:"Gary Chapman《The 5 Love Languages》——每个人都有自己最能感受到爱的方式。错频的爱，再多也无感。"};},breakice:()=>{const durM=t.match(/(\d+)\s*(?:小时|h|天)/i);let hours=48;if(durM){const n=parseInt(durM[1]);hours=/天/.test(durM[0])?n*24:n;}const isLong=hours>=72;const tooLong=hours>=168;const violence=/打|暴力|动手|扔东西|威胁|出轨|背叛|小三/.test(t);const wantBreak=/分手|不想了|算了吧|受够了/.test(t);const isCalm=/理性|讲道理|明事理/.test(t);const isSensitive=/敏感|玻璃心|多想/.test(t);const isCold=/高冷|不爱说|沉默|闷/.test(t);if(violence)return{redirect:true,title:"⚠️ 检测到暴力/背叛关键词",message:"涉及身体暴力、威胁或背叛的冷战，『破冰话术』不是合适的工具。",resources:["如果经历身体暴力：立即拨打 110","情感暴力/精神控制：12338 妇女维权热线","心理支持：当地心理咨询热线 400-161-9995"],advice:"先保护自己，再谈关系。安全第一。"};if(wantBreak)return{redirect:true,title:"我注意到你说了「分手」",message:"看起来你可能需要的不是破冰话术，而是想清楚到底要不要继续。",suggest:"建议你先用 🤔 挽回前自检 功能，做完那 5 个问题再决定要不要破冰。"};const openers=[];if(isCalm||(!isSensitive&&!isCold)){openers.push({type:"🅰️ 共情型（理性型 TA 最吃这套）",say:"这两天我想了很多，我们那天都有点激动。["+(t.length>20?"你提到的事":"具体吵架点")+"]我也有问题——我应该 [具体承诺]。你还在生气吗？",why:["用『我』开头不是『你』","承认自己的部分不过度卑微","最后一个问句给 TA 台阶"]});}if(isSensitive){openers.push({type:"🅱️ 轻松型（敏感型 TA 吃软不吃硬）",say:"冰箱里的 [具体食物] 坏了，我要扔了。你今天吃饭了吗？",why:["用生活小事给台阶","表达关心但不正面对抗","让 TA 有『我们其实没那么严重』的感觉"]});}if(isCold){openers.push({type:"🆅 直接型（高冷型 TA 不绕弯）",say:"我们今晚 8 点见面聊聊？我错的地方我会说。",why:["时间明确","预告自己会反思","不求 TA 也反思（这是免费的礼物）"]});}if(openers.length<2){openers.push({type:"🌿 通用型（稳妥）",say:"这两天冷战我不好过，你应该也是。我想先主动——我们聊聊吗？",why:["承认双方都不好受","表明主动 ≠ 认错","给对方一个邀请而不是命令"]});}const ifReplied=[{case:"🟢 TA 回复积极",say:"那今晚/明天见？我订了 [具体地点]"},{case:"🟡 TA 回复冷淡",say:"『嗯』/『好』——不要追问，回『那晚上给你做饭？』具体行动比话好用"},{case:"🟠 TA 继续抱怨",say:"先听完，不解释。最后说『你说的我听到了，我下周做到 [具体的事]』"},{case:"🔵 TA 转移话题",say:"跟着聊 5-10 分钟，然后自然回到：『刚才的事我还想说一下…』"}];const ifNoReply=tooLong?["⏳ 冷战 7 天+ 了——这不只是冷战，是关系本身出了大问题","📝 写下所有想说的（不要发）——给 2 天时间冷静","🌸 如果 3 天后 TA 还是沉默：一次面对面谈『我们要不要这段关系』"]:isLong?["⏳ 再等 24 小时（但不要主动追消息）","📝 写一封长信——写给自己看，不是给 TA","🌸 第 3 天：换方式『你最近项目进展怎么样？』——具体关心，不提吵架"]:["⏳ 再等 6-12 小时（48h 内 TA 可能还在气头）","🚫 别发『在吗』『为什么不回』——压力翻倍","🌸 下次破冰：换一个场景（别在微信 — 电话 or 见面）"];return{openers,ifReplied,ifNoReply,taboos:["用『你总是』『你从来』——Gottman 四骑士之「批评」","翻旧账——把这次和 3 年前的事串起来","拿前任/朋友的男友对比","发长段情绪化文字——硬启动","用『分手』威胁——对方会记仇，和好后也是雷"],principle:"Gottman 研究：吵架后第一句话决定和解能否成功。软启动成功率 96%，硬启动仅 4%。",theory:"John Gottman 通过 40 年研究 3000+ 对夫妻，发现冲突本身不伤关系，处理冲突的方式才伤。"};},reconcile:()=>{const durM=t.match(/(\d+)\s*(?:天|周|月)/);let days=7;if(durM){const n=parseInt(durM[1]);days=/月/.test(durM[0])?n*30:/周/.test(durM[0])?n*7:n;}const isFresh=days<=3;const tooEarly=days<=1;const violence=/打我|暴力|家暴|出轨|小三|被骗|威胁/.test(t);if(violence)return{redirect:true,title:"💔 检测到暴力/背叛关键词",message:"你经历的不是普通分手——是创伤。挽回的自检对这种情况不够用。",resources:["优先：拨打 12338 妇女维权热线 / 110","心理创伤支持：400-161-9995（心理援助 24h）","如果你感到自伤冲动：立即告诉一位信任的朋友或家人"],advice:"有些关系，不应该回去。你值得更好的。这不是鸡汤——是事实。"};if(tooEarly)return{redirect:true,title:"⏰ 分手不到 1 天",message:"现在情绪太浓——任何自检结果都不准。",suggest:"请等到第 3 天（情绪稍稳）再用这个功能。这 3 天请：不联系 TA、好好吃饭、睡眠。"};let trustScore=0,motiveScore=0,problemScore=0,toleranceScore=0,supportScore=0;if(/完全信|还信|能信任/.test(t))trustScore=25;else if(/重建|慢慢|努力|可以试/.test(t))trustScore=10;else if(/难|不太/.test(t))trustScore=5;if(/爱|喜欢|心动|真的想|在乎/.test(t)&&!/习惯|怕|面子/.test(t))motiveScore=25;else if(/怕有下一个|自尊|面子|不甘/.test(t))motiveScore=0;else if(/习惯|依赖|离不开/.test(t))motiveScore=5;else motiveScore=10;if(/解决了|想清楚了|已经改/.test(t))problemScore=25;else if(/道歉|承诺|答应改/.test(t))problemScore=10;else if(/还在|没解决|一样/.test(t))problemScore=0;else problemScore=5;if(/可以|能接受|一次机会/.test(t)&&!/不能|绝不/.test(t))toleranceScore=15;else if(/不能|再也不/.test(t))toleranceScore=0;else toleranceScore=5;if(/朋友支持|家人同意|大家都|身边人/.test(t)&&!/反对|不看好/.test(t))supportScore=10;else if(/反对|不支持|劝分/.test(t))supportScore=0;else supportScore=5;const total=trustScore+motiveScore+problemScore+toleranceScore+supportScore;const verdict=total>=70?"🟢 可以谨慎尝试挽回——条件基本成熟":total>=40?"🟡 先 2 周冷静期 —— 不要现在决定":"🔴 看起来更多是沉没成本/习惯，不是真的想挽回";const conditions=[["信任可重建",trustScore,25],["动机是爱不是恐惧",motiveScore,25],["核心问题已解决",problemScore,25],["能接受可能再犯",toleranceScore,15],["身边人支持",supportScore,10]];const realMotive=motiveScore>=20?"✨ 你是真的还爱 TA":motiveScore<=5?"⚠️ 可能不是爱——是 [沉没成本/害怕孤独/自尊被伤] 的组合":"🤔 动机混杂，需要区分";const checklist=["每天写 3 条『我今天做的独立的事』（锻炼自我感）","重新联系一位 3 个月没联系的朋友","独自吃一顿饭（测试孤独——是可以忍受的吗？）","运动 3 次（分泌多巴胺，不依赖关系）","不看 TA 朋友圈/社交媒体（必须 — 屏蔽不是幼稚）","如果忍不住想联系：先找 3 个朋友说这件事"];return{total,verdict,conditions,realMotive,checklist,days,principle:"挽回不是『要不要追回来』，是『值不值得追回来』。",theory:"John Bowlby 依恋理论：分手后最初的『想念』70% 是依恋系统的警报，不是爱。2 周后真正的感受才会显现。",dontDo:["立刻去堵 TA『当面谈』——情绪对抗升级","问 TA 朋友『TA 最近怎么样』——幼稚且 TA 会知道","『再给我一次机会』 × N 次——TA 的态度不会变","删掉 TA 又加回来——你自己的情绪过山车"],after2weeks:"2 周后重新回来用这个功能。如果还是想——那是真的。如果平静了——恭喜你放下了。"};},ask_out:()=>({approaches:[{angle:"共同兴趣",say:"周末我想去看那个 [X] 展,听说你也喜欢这类——要不要一起?你有事我自己去也很爽。",why:"有自己的计划+邀请+给对方退出空间"},{angle:"具体事件",say:"上次你说过想试那家 [X] 店,我刚好这周路过——一起?",why:"基于TA说过的事,不是凭空约"},{angle:"轻松低压",say:"下班要不要一起吃饭?随便找一家,聊聊天。",why:"低压力约会,不是约会感太重"}],principle:"主动约 ≠ 倒贴。主动 = 你有计划,邀请他参与,他来或不来都 OK。",formula:"[你的计划] + [邀请他] + [不加条件的退出]",dontDo:["『不知道你有没有空』——显得小心翼翼","『没空也没关系』——主动贬低自己","『随便什么时候都行』——没自我","『打扰你了』——这不是打扰"]}),heat_up:()=>({signals:[{level:"轻度升温",action:"在称呼上加一点点亲密感(比如从『XX』到『XX 呀』)",why:"让他感知到你对他和别人有点不一样"},{level:"中度升温",action:"分享一个不对所有人说的事——一个小秘密、一个糗事、一个在意的人",why:"暴露一点脆弱是让关系升级的关键"},{level:"明确暧昧",action:"主动制造一次更长时间的相处(3+小时)——可以是看电影/长途散步",why:"时间是最诚实的关系度计"}],principle:"升温不是进攻,是给信号让他跟上。跟不上的他,可能没那么想。",rhythm:"周 1-2 次主动找他,其他时间保留你自己的生活。不要为他留所有时间。",dontDo:["连环追问『你在干嘛』——显得没自己的生活","他没回就焦虑发多条——压力翻倍","替他做所有决定(吃什么/去哪里)——他会变被动","秒回每条消息——留出让他想你的空隙"]}),test_him:()=>({indirect:[{method:"聊假设情景",example:"你以后结婚想找什么样的?(随口问,不带目的)",read:"看他是不是具体描述——如果敷衍答,他没认真想过你们的未来"},{method:"提到你的未来计划",example:"我明年想去 [X] 城市发展——你觉得这个选择怎么样?",read:"看他是否自然代入两人视角(如果他说『那我们...』那就是有想法)"},{method:"观察他对你重要事的反应",example:"跟他说一件你很在意的事,不求他回应什么",read:"看他主动记住、跟进,还是过两天就忘"}],direct_when:"当暧昧已 3 个月+,行为信号清晰但他迟迟不表态时",direct_say:"我挺享受跟你这样相处的——你怎么看我们现在?(不是质问,是好奇)",principle:"试探不是套话,是给他空间表达真实想法。",dontDo:["连环质问『你喜不喜欢我』——逼迫回答=抹杀真实","玩忽冷忽热测试他——幼稚且他会记得","翻看他手机——信任崩塌起点","用第三方让他吃醋——制造的焦虑会反噬自己"],red_flag:"如果他连『我们』这个词都回避,或永远在『我不知道』——那他已经回答了,是你不想听。"}),long_dist:()=>({pillars:[{pillar:"共同仪式感",how:"每周日晚上视频通话 1 小时——雷打不动",why:"关系需要仪式固定,不是随机互动"},{pillar:"共享日常",how:"照片/语音/随手分享小事,不等重要事件",why:"日常感是异地最缺的,要主动创造"},{pillar:"期待感",how:"每次见面前 1 周开始『倒数』——制造期待",why:"有期待的关系不会枯"},{pillar:"独立生活",how:"保留自己的朋友圈、爱好、工作挑战——不把全部精神寄托在对方",why:"异地恋最怕的是过度依赖,健康的距离反而更长久"}],daily:"睡前 5 分钟语音消息——说今天的一件小事(开心/难过/好笑都行)",weekly:"周日视频夜——固定时间段,像线下约会一样认真",monthly:"至少 1 次真实见面——机票/高铁贵也值得",principle:"异地不是关系杀手,失联才是。质量 > 频率。",dontDo:["24h 必回强迫症——压力爆棚","监控式关心(查他位置/在干嘛)——信任崩塌","把思念当吵架借口——不是他错","无意义视频刷存在感(他在写 PPT 你非要视频)——会烦"],warning:"如果异地 >6 个月,双方都没见面计划,没有『何时结束异地』的具体讨论——关系在慢慢熄火,该聊未来了。"})};const fn=localGames[gid];const trackIt=(res)=>{const TRACKED_FEATS=["opener","praise","soft","waitprob","lovelang","mirror","initiate","decode","boundary","shine","evidence","confess","pace","anniv","breakice","reconcile","ask_out","heat_up","test_him","long_dist"];if(TRACKED_FEATS.includes(gid)&&learn){try{const cid=learn.trackChoice(t,gid,"health_expr",profile?.nickname||"default");setLastChoiceId(cid);}catch(e){}}};if(AI_FEATS.includes(gid)){const aiRes=await tryAIFeat(gid,t,profile);if(aiRes){setGameRes(aiRes);setGameLd(false);trackIt();return;}if(fn){setTimeout(()=>{setGameRes(fn());setGameLd(false);trackIt();},400);}}else if(fn){setTimeout(()=>{setGameRes(fn());setGameLd(false);trackIt();},400);}else{setGameRes({title:"敬请期待",detail:"这个游戏正在开发中..."});setGameLd(false);}};const doPu=async()=>{if(!puScene||puLd)return;setPuLd(true);setPuRes(null);try{const sys=buildSys(stageId,personaId,profile,`搭讪导师。场景：${puScene.l}。我的特点：${puMyTrait?.l||"自然"}。对方：${puTaTrait?.l||"独自一人"}。目标：${puGoal?.l||"打招呼"}。给出4步搭讪方案。返回JSON：{"steps":[{"step":"第1步","action":"做什么","say":"说什么","why":"为什么"}],"tips":"注意事项","avoid":"千万别做"}`);const r=await ai(sys,"请给出搭讪方案");setPuRes(pJ(r));}catch(e){setPuRes({steps:[{step:"第1步：观察",action:"观察对方状态，确认TA是否方便被打扰",say:"（先不说话，微笑眼神接触）",why:"贸然搭话会让人警惕"},{step:"第2步：借势开口",action:"利用周围环境自然开口",say:"「你好，请问这个___怎么样？我第一次来」",why:"借势比直接搭讪自然10倍"},{step:"第3步：制造互动",action:"根据对方回应延伸话题",say:"「看起来你很熟悉这里，你经常来吗？」",why:"开放性问题让对方愿意多说"},{step:"第4步：留联系方式",action:"在最好的时刻提出",say:"「和你聊天很开心，方便加个微信吗？下次可以约你来***」",why:"给出具体理由提高成功率"}],tips:"保持微笑、不要追问、被拒绝就礼貌离开",avoid:"不要站太近、不要盯着看、不要追着走"});}setPuLd(false);};if(view==="roleplay"&&rpScene)return <div style={{display:"flex",flexDirection:"column",height:"calc(100vh - 110px)",paddingBottom:80}}><div style={{padding:"12px 16px",display:"flex",alignItems:"center",justifyContent:"space-between",background:C.glass,backdropFilter:"blur(20px)",borderBottom:`1px solid ${C.bd}`,flexShrink:0}}><div style={{display:"flex",alignItems:"center",gap:10}}><button className="tap2" onClick={backHome} style={{background:C.pinkBg,border:"none",borderRadius:10,width:32,height:32,color:C.pink,fontSize:14,cursor:"pointer"}}>←</button><div><div style={{fontSize:14,fontWeight:700}}>{rpScene.icon} {rpScene.label}</div><div style={{fontSize:9,color:C.t3}}>提示：{rpScene.hint}</div></div></div><button className="tap2" onClick={()=>startRp(rpScene)} style={{padding:"4px 10px",borderRadius:8,background:C.bg,border:`1px solid ${C.bd}`,color:C.t3,fontSize:10,cursor:"pointer"}}>🔄 重来</button></div><div style={{flex:1,overflowY:"auto",padding:"12px 16px",display:"flex",flexDirection:"column",gap:8}}>{rpMsgs.map((m,i)=>m.role==="sys"?<div key={i} style={{fontSize:10,color:C.peri,textAlign:"center",padding:"6px 12px",background:`${C.peri}08`,borderRadius:10,alignSelf:"center",maxWidth:"90%",lineHeight:1.6,whiteSpace:"pre-wrap"}}>{m.text}</div>:m.role==="ta"?<div key={i} style={{maxWidth:"78%",padding:"10px 14px",borderRadius:"4px 16px 16px 16px",background:C.white,border:`1px solid ${C.bd}`,fontSize:13,lineHeight:1.7,color:C.t1,alignSelf:"flex-start"}}>{m.text}</div>:<div key={i} style={{maxWidth:"78%",padding:"10px 14px",borderRadius:"16px 4px 16px 16px",background:`linear-gradient(135deg,${C.pink},${C.pinkD})`,fontSize:13,lineHeight:1.7,color:"#fff",alignSelf:"flex-end"}}>{m.text}</div>)}{rpLd&&<div style={{fontSize:11,color:C.t3,padding:8}}>💭 TA正在输入...</div>}</div><div style={{display:"flex",gap:8,padding:"8px 16px",borderTop:`1px solid ${C.bd}`,flexShrink:0,background:C.bg}}><input value={rpInp} onChange={e=>setRpInp(e.target.value)} onKeyDown={e=>e.key==="Enter"&&sendRp()} placeholder="你的回复..." style={{flex:1,padding:"10px 14px",borderRadius:14,border:`1px solid ${C.bd}`,background:C.white,fontSize:13,color:C.t1,outline:"none",fontFamily:font}}/><button className="tap" onClick={sendRp} disabled={!rpInp.trim()||rpLd} style={{padding:"10px 16px",borderRadius:14,background:!rpInp.trim()||rpLd?C.bg3:`linear-gradient(135deg,${C.pink},${C.pinkD})`,border:"none",color:!rpInp.trim()||rpLd?C.t3:"#fff",fontSize:13,fontWeight:700,cursor:"pointer"}}>发送</button></div></div>;if(view==="challenge"&&chSel)return <div style={{display:"flex",flexDirection:"column",height:"calc(100vh - 110px)",paddingBottom:80}}><div style={{padding:"12px 16px",display:"flex",alignItems:"center",justifyContent:"space-between",background:C.glass,borderBottom:`1px solid ${C.bd}`,flexShrink:0}}><div style={{display:"flex",alignItems:"center",gap:10}}><button className="tap2" onClick={backHome} style={{background:C.pinkBg,border:"none",borderRadius:10,width:32,height:32,color:C.pink,fontSize:14,cursor:"pointer"}}>←</button><div><div style={{fontSize:14,fontWeight:700}}>{chSel.icon} {chSel.label}</div><div style={{fontSize:9,color:C.t3}}>{chSel.desc}</div></div></div><div style={{textAlign:"right"}}><div style={{fontSize:14,fontWeight:700,color:chTimer>60?C.danger:C.t1}}>{Math.floor(chTimer/60)}:{String(chTimer%60).padStart(2,"0")}</div><div style={{fontSize:8,color:C.t3}}>{chSel.diff}</div></div></div>{chScore&&<div style={{padding:"12px 16px",background:`${C.safe}06`,textAlign:"center"}}><div style={{fontSize:24,fontWeight:900,color:chScore>=70?C.safe:C.warn}}>🎉 {chScore}分</div><div style={{fontSize:11,color:C.t2,marginBottom:8}}>用时 {Math.floor(chTimer/60)}分{chTimer%60}秒</div><div style={{display:"flex",gap:8,justifyContent:"center"}}><button className="tap" onClick={()=>startCh(chSel)} style={{padding:"8px 16px",borderRadius:12,background:C.pinkBg,border:"none",color:C.pink,fontSize:12,fontWeight:700,cursor:"pointer"}}>🔄 再来</button><button className="tap" onClick={backHome} style={{padding:"8px 16px",borderRadius:12,background:C.bg,border:`1px solid ${C.bd}`,color:C.t2,fontSize:12,cursor:"pointer"}}>🎭 换场景</button></div></div>}<div style={{flex:1,overflowY:"auto",padding:"12px 16px",display:"flex",flexDirection:"column",gap:8}}>{chMsgs.map((m,i)=>m.role==="ta"?<div key={i} style={{maxWidth:"78%",padding:"10px 14px",borderRadius:"4px 16px 16px 16px",background:C.white,border:`1px solid ${C.bd}`,fontSize:13,lineHeight:1.7,color:C.t1,alignSelf:"flex-start"}}>{m.text}</div>:<div key={i} style={{maxWidth:"78%",padding:"10px 14px",borderRadius:"16px 4px 16px 16px",background:`linear-gradient(135deg,${C.pink},${C.pinkD})`,fontSize:13,lineHeight:1.7,color:"#fff",alignSelf:"flex-end"}}>{m.text}</div>)}{chLd&&<div style={{fontSize:11,color:C.t3,padding:8}}>💭 TA正在想...</div>}</div>{!chScore&&<div style={{display:"flex",gap:8,padding:"8px 16px",borderTop:`1px solid ${C.bd}`,flexShrink:0,background:C.bg}}><input value={chInp} onChange={e=>setChInp(e.target.value)} onKeyDown={e=>e.key==="Enter"&&sendCh()} placeholder="哄TA..." style={{flex:1,padding:"10px 14px",borderRadius:14,border:`1px solid ${C.bd}`,background:C.white,fontSize:13,color:C.t1,outline:"none",fontFamily:font}}/><button className="tap" onClick={sendCh} disabled={!chInp.trim()||chLd} style={{padding:"10px 16px",borderRadius:14,background:!chInp.trim()||chLd?C.bg3:`linear-gradient(135deg,${C.coral},${C.coral}cc)`,border:"none",color:!chInp.trim()||chLd?C.t3:"#fff",fontSize:13,fontWeight:700,cursor:"pointer"}}>发送</button></div>}</div>;
if(view==="date"&&dateView!==null){const d=DATE_GUIDES[dateView];return <div style={{paddingBottom:100}}><SubHeader onBack={backHome} title={`${d.icon} ${d.title}`}/><div style={{padding:"14px 16px"}}><Cd s={{marginBottom:12,background:`${C.gold}04`}}><div style={{display:"flex",gap:8,marginBottom:6}}>{d.tags.map(t=><Badge key={t} color={C.gold}>{t}</Badge>)}</div><div style={{display:"flex",gap:12,fontSize:11,color:C.t2}}><span>📍 {d.loc}</span><span>⏱ {d.dur}</span><span>🕐 {d.bestTime}</span></div></Cd><Cd s={{marginBottom:12}}><div style={{fontSize:12,fontWeight:700,color:C.pink,marginBottom:6}}>📋 准备清单</div>{d.prep.map((p,i)=><div key={i} style={{fontSize:12,color:C.t1,lineHeight:1.7,paddingLeft:12}}>· {p}</div>)}</Cd><Cd s={{marginBottom:12}}><div style={{fontSize:12,fontWeight:700,color:C.peri,marginBottom:6}}>💬 推荐话题</div>{d.topics.map((t,i)=><div key={i} className="tap" onClick={()=>{navigator.clipboard?.writeText(t);st("已复制");}} style={{padding:"8px 12px",marginBottom:4,borderRadius:10,background:C.bg,cursor:"pointer",fontSize:12,color:C.t1}}>「{t}」</div>)}</Cd><Cd s={{background:`${C.safe}04`}}><div style={{fontSize:12,fontWeight:700,color:C.safe,marginBottom:4}}>💡 贴士</div><div style={{fontSize:12,color:C.t1,lineHeight:1.7}}>{d.tips}</div></Cd></div></div>;}if(view==="game"&&gameId){const V25_GAME_IDS=["roleplay_pro","responsibility","date_spot","gift_rec","scam_v2","npd_check"];if(V25_GAME_IDS.includes(gameId))return <V25Game gameId={gameId} profile={profile} st={st} vip={vip} setShowPay={setShowPay} onBack={backHome}/>;if(gameId==="invite")return <V25Invite st={st} onBack={backHome} setShowPay={setShowPay}/>;if(gameId==="anniv_push")return <V25AnnivPush anniversaries={anniversaries} st={st} onBack={backHome}/>;const g=VIRAL_GAMES.find(x=>x.id===gameId);return <div style={{paddingBottom:100}}><SubHeader onBack={backHome} title={`${g?.icon} ${g?.l}`}/><div style={{padding:"14px 16px"}}>{STEP_FORMS[gameId]?<StepForm gameId={gameId} loading={gameLd} color={g?.c} onSubmit={(formatted)=>{setGameInp(formatted);setTimeout(()=>doGame(gameId),50);}}/>:<><Cd s={{marginBottom:12}}><textarea value={gameInp} onChange={e=>setGameInp(e.target.value)} placeholder="输入内容..." style={{width:"100%",minHeight:60,padding:0,background:"transparent",border:"none",color:C.t1,fontSize:14,outline:"none",resize:"none",lineHeight:1.7,fontFamily:font}}/></Cd><Btn primary color={g?.c||C.pink} onClick={()=>doGame(gameId)} disabled={!gameInp.trim()||gameLd}>{gameLd?"分析中...":`${g?.icon} 开始`}</Btn></>}{gameLd&&<Dots/>}{gameRes&&<div style={{marginTop:14}}>{gameId==="damage"&&<><Cd s={{textAlign:"center",marginBottom:10,background:`${gameRes.score>=60?C.danger:C.safe}06`}}><div style={{fontSize:36,fontWeight:900,color:gameRes.score>=60?C.danger:C.safe}}>💔 {gameRes.score}</div><div style={{fontSize:11,color:C.t3}}>伤害值 · {gameRes.type}</div></Cd><Cd s={{marginBottom:6}}><div style={{fontSize:12,color:C.t1,lineHeight:1.7}}>{gameRes.detail}</div></Cd>{gameRes.betterWay&&<Cd s={{background:`${C.safe}04`}}><div style={{display:"flex",justifyContent:"space-between",gap:6}}><div><div style={{fontSize:11,fontWeight:600,color:C.safe,marginBottom:3}}>✅ 更好的说法</div><div style={{fontSize:13,color:C.t1}}>{gameRes.betterWay}</div></div><CB text={gameRes.betterWay} st={st}/></div></Cd>}</>}{gameId==="battle"&&<><div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8,marginBottom:10}}><Cd s={{textAlign:"center"}}><div style={{fontSize:10,color:C.t3}}>你的</div><div style={{fontSize:28,fontWeight:900,color:C.pink}}>{gameRes.userScore}</div></Cd><Cd s={{textAlign:"center"}}><div style={{fontSize:10,color:C.t3}}>AI的</div><div style={{fontSize:28,fontWeight:900,color:C.peri}}>{gameRes.aiScore}</div></Cd></div><Cd s={{marginBottom:6,background:`${C.peri}04`}}><div style={{fontSize:11,fontWeight:600,color:C.peri,marginBottom:3}}>AI的情话</div><div style={{fontSize:14,color:C.t1,lineHeight:1.7}}>{gameRes.aiLine}</div></Cd></>}{gameId==="predict"&&<><Cd s={{textAlign:"center",marginBottom:10,background:`${gameRes.survival>=60?C.safe:C.danger}06`}}><div style={{fontSize:36,fontWeight:900,color:gameRes.survival>=60?C.safe:C.danger}}>{gameRes.survival}%</div><div style={{fontSize:11,color:C.t3}}>关系存活率</div></Cd>{gameRes.dimensions?.map((d,i)=><div key={i} style={{marginBottom:4}}><EB l={d.name} v={d.score} c={d.score>=60?C.safe:C.danger}/></div>)}{gameRes.advice&&<Cd s={{background:`${C.safe}04`}}><div style={{fontSize:11,fontWeight:600,color:C.safe}}>💡 {gameRes.advice}</div></Cd>}</>}{gameId==="hole"&&<><Cd s={{marginBottom:8,background:`linear-gradient(135deg,#A8E6CF08,${C.teal}04)`}}><div style={{fontSize:16,fontWeight:700,color:C.t1,marginBottom:8,lineHeight:1.6}}>{gameRes.hug}</div></Cd>{gameRes.understand&&<Cd s={{marginBottom:6}}><div style={{fontSize:12,color:C.t1,lineHeight:1.7}}>{gameRes.understand}</div></Cd>}{gameRes.reframe&&<Cd s={{marginBottom:6,background:`${C.peri}04`}}><div style={{fontSize:11,fontWeight:600,color:C.peri,marginBottom:3}}>💡 换个角度</div><div style={{fontSize:12,color:C.t1,lineHeight:1.7}}>{gameRes.reframe}</div></Cd>}{gameRes.action&&<Cd s={{background:`${C.safe}04`}}><div style={{fontSize:11,fontWeight:600,color:C.safe,marginBottom:3}}>🌱 如果你想</div><div style={{fontSize:12,color:C.t1,lineHeight:1.7}}>{gameRes.action}</div></Cd>}</>}{gameId==="fortune"&&<><Cd s={{textAlign:"center",marginBottom:10,background:`linear-gradient(135deg,${C.violet}08,${C.pink}06)`}}><div style={{fontSize:42,fontWeight:900,color:C.violet}}>{gameRes.score}%</div><div style={{fontSize:14,fontWeight:700,color:C.pink}}>{gameRes.level}</div></Cd>{gameRes.methods?.map((m,i)=><Cd key={i} s={{marginBottom:6,padding:"10px 12px"}}><div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:4}}><span style={{fontSize:12,fontWeight:700,color:C.t1}}>{m.icon} {m.name}</span><span style={{fontSize:14,fontWeight:800,color:m.score>=60?C.safe:m.score>=40?C.warn:C.danger}}>{m.score}%</span></div><EB l="" v={m.score} c={m.score>=60?C.safe:m.score>=40?C.warn:C.danger}/><div style={{fontSize:10,color:C.t2,lineHeight:1.6,marginTop:3}}>{m.detail}</div></Cd>)}<Cd s={{background:`${C.peri}04`}}><div style={{fontSize:11,color:C.t1,lineHeight:1.7}}>{gameRes.summary}</div></Cd><Cd s={{background:`${C.violet}04`,marginTop:6}}><div style={{fontSize:11,fontWeight:600,color:C.violet}}>💡 {gameRes.advice}</div></Cd></>}{gameId==="color"&&<><Cd s={{textAlign:"center",marginBottom:10}}><div style={{width:80,height:80,borderRadius:40,background:gameRes.color,margin:"0 auto 10px",boxShadow:`0 8px 32px ${gameRes.color}40`}}/><div style={{fontSize:16,fontWeight:800,color:gameRes.color}}>{gameRes.name}</div></Cd><Cd s={{background:`${gameRes.color}06`}}><div style={{fontSize:12,color:C.t1,lineHeight:1.7}}>{gameRes.meaning}</div></Cd></>}{gameId==="compat"&&<><Cd s={{textAlign:"center",marginBottom:10,background:`${gameRes.total>=60?C.safe:C.warn}06`}}><div style={{fontSize:42,fontWeight:900,color:gameRes.total>=60?C.safe:C.warn}}>{gameRes.total}%</div><div style={{fontSize:11,color:C.t3}}>10维同步率</div></Cd>{gameRes.dimensions?.map((d,i)=><div key={i} style={{marginBottom:4}}><EB l={d.name} v={d.score} c={d.score>=60?C.safe:C.warn}/></div>)}<Cd s={{background:`${C.peri}04`,marginTop:8}}><div style={{fontSize:11,color:C.t1,lineHeight:1.7}}>{gameRes.summary}</div></Cd></>}{gameId==="mr"&&<><Cd s={{marginBottom:10,background:`${C.blue}04`}}><div style={{fontSize:14,fontWeight:700,color:C.blue,marginBottom:6}}>🧠 TA的心理画像</div><div style={{fontSize:12,color:C.t1,lineHeight:1.7}}>{gameRes.type}</div></Cd>{gameRes.traits?.map((t,i)=><div key={i} style={{marginBottom:4}}><EB l={t.name} v={t.score} c={C.peri}/><div style={{fontSize:9,color:C.t3,marginLeft:40}}>{t.note}</div></div>)}<Cd s={{background:`${C.safe}04`}}><div style={{fontSize:11,fontWeight:600,color:C.safe}}>💡 {gameRes.tip}</div></Cd></>}{gameId==="comm"&&<>{gameRes.lines?.map((l,i)=><Cd key={i} s={{marginBottom:8}}><div style={{fontSize:10,color:C.t3,marginBottom:3}}>原文：{l.original}</div><div style={{fontSize:13,fontWeight:600,color:C.peri,lineHeight:1.7,marginBottom:4}}>{l.subtext}</div><Badge color={C.coral}>{l.emotion}</Badge></Cd>)}<Cd s={{background:`${C.teal}04`}}><div style={{fontSize:11,fontWeight:600,color:C.teal}}>💡 {gameRes.tip}</div></Cd></>}{gameId==="fire"&&<><div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8,marginBottom:10}}><Cd s={{textAlign:"center",background:gameRes.winner==="A"?`${C.safe}06`:"transparent",border:gameRes.winner==="A"?`2px solid ${C.safe}30`:`1px solid ${C.bd}`}}><div style={{fontSize:10,color:C.t3}}>A</div><div style={{fontSize:24,fontWeight:900,color:gameRes.winner==="A"?C.safe:C.t3}}>{gameRes.scoreA}</div></Cd><Cd s={{textAlign:"center",background:gameRes.winner==="B"?`${C.safe}06`:"transparent",border:gameRes.winner==="B"?`2px solid ${C.safe}30`:`1px solid ${C.bd}`}}><div style={{fontSize:10,color:C.t3}}>B</div><div style={{fontSize:24,fontWeight:900,color:gameRes.winner==="B"?C.safe:C.t3}}>{gameRes.scoreB}</div></Cd></div><Cd s={{background:`${C.safe}04`}}><div style={{fontSize:11,fontWeight:600,color:C.safe}}>🏆 推荐发{gameRes.winner}：{gameRes.reason}</div></Cd></>}{gameId==="countdown"&&<><Cd s={{textAlign:"center",marginBottom:10,background:`${gameRes.days>200?C.safe:gameRes.days>100?C.warn:C.danger}06`}}><div style={{fontSize:48,fontWeight:900,color:gameRes.days>200?C.safe:gameRes.days>100?C.warn:C.danger}}>{gameRes.days}</div><div style={{fontSize:12,color:C.t3}}>天</div></Cd><Cd s={{marginBottom:6}}><div style={{fontSize:12,color:C.t1,lineHeight:1.7}}>{gameRes.message}</div></Cd><Cd s={{background:`${C.safe}04`}}><div style={{fontSize:11,fontWeight:600,color:C.safe}}>💡 {gameRes.advice}</div></Cd></>}{gameId==="daily"&&<><Cd s={{textAlign:"center",marginBottom:10,background:`linear-gradient(135deg,${C.teal}08,${C.peri}06)`}}><div style={{fontSize:28,marginBottom:6}}>🎯</div><div style={{fontSize:14,fontWeight:700,color:C.teal,lineHeight:1.6}}>{gameRes.challenge}</div><div style={{marginTop:6}}><Badge color={C.coral}>{gameRes.difficulty}</Badge></div></Cd><Cd s={{background:`${C.gold}04`}}><div style={{fontSize:11,fontWeight:600,color:C.gold}}>🎁 {gameRes.reward}</div></Cd></>}{gameId==="polar"&&<><Cd s={{textAlign:"center",marginBottom:10}}><div style={{fontSize:14,fontWeight:800,color:C.t1,lineHeight:1.5}}>{gameRes.topic}</div></Cd><div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8,marginBottom:10}}><Cd s={{background:`${C.safe}04`,borderLeft:`3px solid ${C.safe}`}}><div style={{fontSize:10,fontWeight:700,color:C.safe,marginBottom:3}}>👍 {gameRes.sideA.label}</div><div style={{fontSize:11,color:C.t1,lineHeight:1.6}}>{gameRes.sideA.argument}</div></Cd><Cd s={{background:`${C.danger}04`,borderLeft:`3px solid ${C.danger}`}}><div style={{fontSize:10,fontWeight:700,color:C.danger,marginBottom:3}}>👎 {gameRes.sideB.label}</div><div style={{fontSize:11,color:C.t1,lineHeight:1.6}}>{gameRes.sideB.argument}</div></Cd></div><Cd s={{background:`${C.peri}04`}}><div style={{fontSize:11,fontWeight:600,color:C.peri}}>⚖️ {gameRes.verdict}</div></Cd></>}{gameId==="wrapped"&&<><Cd s={{textAlign:"center",marginBottom:10,background:`linear-gradient(135deg,${C.pink}08,${C.gold}06)`}}><div style={{fontSize:18,fontWeight:800,color:C.pink,marginBottom:8}}>🎁 {gameRes.title}</div>{gameRes.stats?.map((s,i)=><div key={i} style={{display:"flex",justifyContent:"space-between",padding:"6px 0",borderBottom:i<gameRes.stats.length-1?`1px solid ${C.bdL}`:"none"}}><span style={{fontSize:11,color:C.t2}}>{s.icon} {s.label}</span><span style={{fontSize:13,fontWeight:700,color:C.pink}}>{s.value}</span></div>)}</Cd><Cd s={{background:`${C.gold}04`}}><div style={{fontSize:11,color:C.t1,lineHeight:1.7}}>{gameRes.summary}</div></Cd></>}{gameId==="blacklist"&&<><Cd s={{marginBottom:10,background:`${C.danger}06`,borderLeft:`3px solid ${C.danger}`}}><div style={{fontSize:14,fontWeight:700,color:C.danger,marginBottom:4}}>🚩 {gameRes.flag}</div><Badge color={C.danger}>{gameRes.severity}</Badge></Cd><Cd s={{marginBottom:6}}><div style={{fontSize:12,color:C.t1,lineHeight:1.7}}>{gameRes.advice}</div></Cd><Cd s={{background:`${C.safe}04`}}><div style={{fontSize:11,color:C.safe}}>{gameRes.resource}</div></Cd></>}{gameId==="aipartner"&&<><Cd s={{marginBottom:10,background:`linear-gradient(135deg,${C.pink}06,${C.sakura}08)`,textAlign:"center"}}><div style={{fontSize:36,marginBottom:6}}>{gameRes.mood}</div><div style={{fontSize:14,fontWeight:600,color:C.t1,lineHeight:1.7}}>{gameRes.reply}</div></Cd><Cd s={{background:`${C.teal}04`}}><div style={{fontSize:10,color:C.teal}}>💡 {gameRes.tip}</div></Cd></>}{gameId==="progress"&&<><Cd s={{textAlign:"center",marginBottom:10,background:`linear-gradient(135deg,${C.peri}08,${C.teal}06)`}}><div style={{fontSize:11,color:C.t3}}>当前段位</div><div style={{fontSize:24,fontWeight:900,color:C.peri}}>Lv.{gameRes.level}</div><div style={{fontSize:14,fontWeight:700,color:C.teal}}>{gameRes.title}</div><div style={{marginTop:6}}><EB l="XP" v={Math.min(100,Math.round(gameRes.xp/gameRes.nextLevel*100))} c={C.peri}/></div></Cd><Cd s={{background:`${C.gold}04`}}><div style={{fontSize:11,color:C.gold}}>🏅 {gameRes.badges}</div></Cd><Cd s={{marginTop:6}}><div style={{fontSize:11,color:C.t2}}>{gameRes.tip}</div></Cd></>}{gameId==="levels"&&<><Cd s={{textAlign:"center",marginBottom:10,background:`${C.peri}06`}}><div style={{fontSize:11,color:C.t3}}>当前关卡</div><div style={{fontSize:36,fontWeight:900,color:C.peri}}>第{gameRes.currentLevel}关</div></Cd><Cd s={{marginBottom:8}}><div style={{fontSize:13,fontWeight:700,color:C.t1,marginBottom:4}}>🎯 挑战</div><div style={{fontSize:12,color:C.t1,lineHeight:1.7}}>{gameRes.challenge}</div></Cd><Cd s={{background:`${C.safe}04`}}><div style={{fontSize:11,fontWeight:600,color:C.safe}}>💡 {gameRes.tip}</div></Cd></>}{gameId==="scam"&&<><Cd s={{textAlign:"center",marginBottom:10,background:`${gameRes.total>=50?C.danger:gameRes.total>=30?C.warn:C.safe}06`}}><div style={{fontSize:36,fontWeight:900,color:gameRes.total>=50?C.danger:gameRes.total>=30?C.warn:C.safe}}>🔍 {gameRes.total}分</div><div style={{fontSize:13,fontWeight:700,color:C.t1}}>{gameRes.level}</div></Cd>{gameRes.dims?.map((d,i)=><div key={i} style={{marginBottom:6}}><EB l={d.name} v={d.score} c={d.score>=50?C.danger:d.score>=30?C.warn:C.safe}/><div style={{fontSize:9,color:C.t3,marginLeft:40}}>{d.flag}</div></div>)}<Cd s={{marginBottom:8}}><div style={{fontSize:12,color:C.t1,lineHeight:1.7}}>{gameRes.advice}</div></Cd><Cd s={{background:`${C.danger}04`}}><div style={{fontSize:10,fontWeight:600,color:C.danger,marginBottom:4}}>📞 求助资源</div>{gameRes.resources?.map((r,i)=><div key={i} style={{fontSize:10,color:C.t2,lineHeight:1.6}}>• {r}</div>)}</Cd></>}{gameId==="chess"&&(()=>{const CHESS_SCENES=[{id:"lor",icon:"😶",label:"已读不回",taLine:"读了但没回你",hint:"降压不追问",stage:"开局",goal:"让TA主动回你"},{id:"fight",icon:"🧊",label:"吵完架",taLine:"随便你",hint:"软启动不翻旧账",stage:"残局",goal:"修复冷战"},{id:"push",icon:"💕",label:"暧昧推进",taLine:"你人真好",hint:"升温不表白",stage:"中盘",goal:"推进到下一步"},{id:"jealous",icon:"😤",label:"TA吃醋了",taLine:"你和谁吃饭呢",hint:"安抚不审问",stage:"中盘",goal:"化解醋意"},{id:"space",icon:"🫧",label:"要空间",taLine:"我需要一点空间",hint:"给空间不消失",stage:"残局",goal:"保持存在感"},{id:"ex",icon:"💀",label:"提到前任",taLine:"我前任以前也这样",hint:"稳住不追问",stage:"中盘",goal:"展示安全感"},{id:"cold",icon:"❄️",label:"突然变冷",taLine:"嗯",hint:"不卑不亢",stage:"开局",goal:"找回节奏"},{id:"confess",icon:"💘",label:"暗示表白",taLine:"你觉得我们算什么",hint:"接住但不急",stage:"残局",goal:"自然确认关系"}];const RANKS=[{min:0,icon:"🥉",name:"青铜",title:"恋爱萌新"},{min:800,icon:"🥈",name:"白银",title:"暧昧达人"},{min:1200,icon:"🥇",name:"黄金",title:"撩人高手"},{min:1600,icon:"💎",name:"钻石",title:"哄人专家"},{min:2000,icon:"👑",name:"王者",title:"恋爱大师"}];const getRank=elo=>{let r=RANKS[0];for(const rk of RANKS)if(elo>=rk.min)r=rk;return r;};const TA_STYLES=["温柔型","高冷型","作精型","理性型","傲娇型"];const[phase,setPhase]=useState(gameRes?.mode==="select"?"select":"select");const[scene,setScene]=useState(null);const[msgs,setMsgs]=useState([]);const[myInp,setMyInp]=useState("");const[elo,setElo]=useState(1000);const[totalMoves,setTotalMoves]=useState(0);const[taStyle,setTaStyle]=useState(TA_STYLES[0]);const[score,setScore]=useState(null);const[moveScores,setMoveScores]=useState([]);const rank=getRank(elo);const startScene=sc=>{setScene(sc);setMsgs([{role:"sys",text:`♟️ ${sc.label} · ${sc.stage}🎯 目标：${sc.goal}💡 提示：${sc.hint}`},{role:"ta",text:sc.taLine}]);setPhase("play");setScore(null);setMoveScores([]);};const sendMove=()=>{if(!myInp.trim())return;const t=myInp.trim();setMyInp("");const h=t.split("").reduce((a,c)=>a+c.charCodeAt(0),0);const len=t.length;let sc=50;let fb="";if(t.includes("？")&&t.length<8){sc=70;fb="简短提问不给压力，好棋！";}else if(t.includes("我")&&!t.includes("你")){sc=75;fb="用'我'开头表达感受，很好的软启动。";}else if(t.includes("你总是")||t.includes("你从来")){sc=20;fb="⚠️ 绝对词触发防御机制！Gottman四骑士之'批评'。";}else if(t.includes("对不起")||t.includes("是我的问题")){sc=scene?.id==="fight"?80:60;fb=scene?.id==="fight"?"主动认错在冲突修复中很有效。":"态度诚恳，但注意时机。";}else if(t.includes("哈哈")||t.includes("😂")||t.includes("笑")){sc=65;fb="幽默缓解紧张，但注意别让TA觉得你不认真。";}else if(len>30){sc=35;fb="消息太长！微信聊天不超过20字。长消息=压力。";}else if(len<5){sc=55;fb="有点短，TA可能觉得你在敷衍。可以多说一句。";}else{sc=45+h%30;fb=["节奏不错，继续观察TA反应。","可以更自然一些，现在有点刻意。","方向对了，但语气可以再软一点。","不错的选择，看TA怎么接。"][h%4];}const eloDelta=sc>=70?Math.round((sc-50)*1.5):sc>=50?Math.round((sc-50)*0.8):-Math.round((50-sc)*1.2);setElo(e=>Math.max(0,e+eloDelta));setTotalMoves(n=>n+1);setMoveScores(p=>[...p,{text:t,score:sc,fb}]);const taReplies={lor:["嗯...","在忙","没什么","哦","怎么了"],fight:["行吧","随便你","那你说怎么办","我没说不对","算了不想吵了"],push:["你很有趣哈哈","是吗","你人真好","你这话什么意思","下次再说吧"],jealous:["关你什么事","你不也有异性朋友","吃醋了？","没有的事","你想多了"],space:["嗯","我知道了","需要时间","别逼我","好的"],ex:["怎么了","你也这样想？","那是以前的事","嗯...","你在意？"],cold:["嗯","哦","好","知道了","在"],confess:["你说呢","我不知道","朋友吧","你觉得呢","没想过"]};const pool=taReplies[scene?.id]||taReplies.lor;const taReply=pool[h%pool.length];setMsgs(p=>[...p,{role:"me",text:t},{role:"score",text:`${sc>=70?"✅":"⚠️"} ${sc}分 · ${fb}${eloDelta>=0?" ELO+"+eloDelta:" ELO"+eloDelta}`},{role:"ta",text:taReply}]);if(totalMoves>=4&&sc>=70){setTimeout(()=>{setScore({total:Math.round(moveScores.reduce((a,m)=>a+m.score,0)/moveScores.length+sc)/2,moves:totalMoves+1,elo,rank:getRank(elo+eloDelta)});setPhase("result");},500);}};if(phase==="select") return <div><div style={{textAlign:"center",marginBottom:12}}><div style={{fontSize:18,fontWeight:800,color:C.peri}}>♟️ 恋爱棋局™</div><div style={{fontSize:10,color:C.t3}}>AI对话推演 · ELO段位</div></div><div style={{display:"flex",justifyContent:"center",gap:10,marginBottom:14}}><div style={{textAlign:"center"}}><div style={{fontSize:24}}>{rank.icon}</div><div style={{fontSize:11,fontWeight:700,color:C.peri}}>{rank.name}</div><div style={{fontSize:9,color:C.t3}}>{rank.title}</div></div><div style={{textAlign:"center"}}><div style={{fontSize:18,fontWeight:800,color:C.t1}}>{elo}</div><div style={{fontSize:9,color:C.t3}}>ELO</div></div><div style={{textAlign:"center"}}><div style={{fontSize:18,fontWeight:800,color:C.gold}}>{totalMoves}</div><div style={{fontSize:9,color:C.t3}}>总落子</div></div></div><div style={{marginBottom:10}}><div style={{fontSize:10,color:C.t3,marginBottom:4}}>TA的性格</div><div style={{display:"flex",gap:4,flexWrap:"wrap"}}>{TA_STYLES.map(s=><button key={s} className="tap2" onClick={()=>setTaStyle(s)} style={{padding:"4px 10px",borderRadius:8,fontSize:10,background:taStyle===s?`${C.peri}12`:"transparent",border:`1px solid ${taStyle===s?C.peri+"40":C.bd}`,color:taStyle===s?C.peri:C.t3,cursor:"pointer"}}>{s}</button>)}</div></div><div style={{fontSize:11,fontWeight:700,color:C.t2,marginBottom:6}}>选择棋局</div>{CHESS_SCENES.map((sc,i)=><div key={sc.id} className="tap" onClick={()=>startScene(sc)} style={{display:"flex",alignItems:"center",gap:10,padding:"10px 12px",marginBottom:4,borderRadius:12,background:C.white,border:`1px solid ${C.bd}`,cursor:"pointer"}}><span style={{fontSize:20}}>{sc.icon}</span><div style={{flex:1}}><div style={{fontSize:12,fontWeight:700,color:C.t1}}>{sc.label}</div><div style={{fontSize:9,color:C.t3}}>TA说：「{sc.taLine}」· {sc.stage}</div></div><span style={{fontSize:9,color:C.peri}}>{sc.goal}</span></div>)}</div>;if(phase==="play") return <div style={{display:"flex",flexDirection:"column",height:"calc(100vh - 280px)"}}><div style={{display:"flex",justifyContent:"space-between",alignItems:"center",padding:"6px 0",marginBottom:6,borderBottom:`1px solid ${C.bd}`}}><div><span style={{fontSize:12,fontWeight:700,color:C.peri}}>♟️ {scene.label}</span><span style={{fontSize:9,color:C.t3,marginLeft:6}}>{scene.stage} · {taStyle}</span></div><div style={{display:"flex",gap:8,alignItems:"center"}}><span style={{fontSize:10,color:C.gold,fontWeight:700}}>{rank.icon}{elo}</span><button className="tap2" onClick={()=>{setPhase("select");setMsgs([]);}} style={{fontSize:9,color:C.t3,background:"none",border:"none",cursor:"pointer"}}>退出</button></div></div><div style={{flex:1,overflowY:"auto",display:"flex",flexDirection:"column",gap:6,paddingBottom:8}}>{msgs.map((m,i)=>m.role==="sys"?<div key={i} style={{fontSize:10,color:C.peri,textAlign:"center",padding:"6px 10px",background:`${C.peri}08`,borderRadius:8,whiteSpace:"pre-wrap",lineHeight:1.6}}>{m.text}</div>:m.role==="score"?<div key={i} style={{fontSize:10,color:m.text.includes("✅")?C.safe:C.warn,textAlign:"center",padding:"4px 8px",background:m.text.includes("✅")?`${C.safe}06`:`${C.warn}06`,borderRadius:6}}>{m.text}</div>:m.role==="ta"?<div key={i} style={{maxWidth:"78%",padding:"8px 12px",borderRadius:"4px 14px 14px 14px",background:C.white,border:`1px solid ${C.bd}`,fontSize:13,lineHeight:1.6,alignSelf:"flex-start"}}>{m.text}</div>:<div key={i} style={{maxWidth:"78%",padding:"8px 12px",borderRadius:"14px 4px 14px 14px",background:`linear-gradient(135deg,${C.pink},${C.pinkD})`,fontSize:13,lineHeight:1.6,color:"#fff",alignSelf:"flex-end"}}>{m.text}</div>)}</div><div style={{display:"flex",gap:6,paddingTop:6,borderTop:`1px solid ${C.bd}`}}><input value={myInp} onChange={e=>setMyInp(e.target.value)} onKeyDown={e=>e.key==="Enter"&&sendMove()} placeholder="你的回复..." style={{flex:1,padding:"8px 12px",borderRadius:12,border:`1px solid ${C.bd}`,background:C.white,fontSize:13,color:C.t1,outline:"none",fontFamily:font}}/><button className="tap" onClick={sendMove} disabled={!myInp.trim()} style={{padding:"8px 14px",borderRadius:12,background:myInp.trim()?`linear-gradient(135deg,${C.peri},${C.pink})`:"transparent",border:myInp.trim()?"none":`1px solid ${C.bd}`,color:myInp.trim()?"#fff":C.t3,fontSize:12,fontWeight:700,cursor:myInp.trim()?"pointer":"default"}}>落子</button></div></div>;if(phase==="result") return <div style={{textAlign:"center"}}><div style={{fontSize:24,marginBottom:6}}>🏆</div><div style={{fontSize:20,fontWeight:900,color:C.peri}}>{score?.total>=70?"精彩对局！":"还需修炼"}</div><div style={{display:"flex",justifyContent:"center",gap:16,margin:"12px 0"}}><div><div style={{fontSize:28,fontWeight:900,color:score?.total>=70?C.safe:C.warn}}>{Math.round(score?.total||50)}</div><div style={{fontSize:9,color:C.t3}}>平均分</div></div><div><div style={{fontSize:28,fontWeight:900,color:C.gold}}>{score?.rank?.icon}</div><div style={{fontSize:9,color:C.t3}}>{score?.rank?.name} {elo}</div></div></div><div style={{textAlign:"left",marginTop:10}}><div style={{fontSize:11,fontWeight:700,color:C.t2,marginBottom:6}}>📜 棋谱回顾</div>{moveScores.map((m,i)=><div key={i} style={{padding:"6px 10px",marginBottom:3,borderRadius:8,background:m.score>=70?`${C.safe}06`:`${C.warn}06`,borderLeft:`3px solid ${m.score>=70?C.safe:C.warn}`}}><div style={{fontSize:12,color:C.t1}}>「{m.text}」</div><div style={{fontSize:10,color:m.score>=70?C.safe:C.warn}}>{m.score}分 · {m.fb}</div></div>)}</div><div style={{display:"flex",gap:8,marginTop:12}}><Btn primary onClick={()=>{setPhase("select");setMsgs([]);}}>🔄 再来一局</Btn></div></div>;return null;})()}{gameId==="opener"&&<><Cd s={{marginBottom:8,background:`${C.gold}06`}}><div style={{fontSize:13,fontWeight:700,color:C.gold,marginBottom:6}}>✨ 真诚开场库</div><div style={{fontSize:11,color:C.t3,lineHeight:1.6}}>{gameRes.principle}</div></Cd>{gameRes.angles?.map((a,i)=><Cd key={i} s={{marginBottom:6}}><div style={{fontSize:12,fontWeight:700,color:C.pink,marginBottom:4}}>{a.type}</div><div style={{fontSize:13,color:C.t1,lineHeight:1.6,padding:"6px 0"}}>「{a.say}」</div><div style={{fontSize:10,color:C.t3}}>💡 {a.why}</div></Cd>)}<Cd s={{background:`${C.danger}06`}}><div style={{fontSize:11,fontWeight:700,color:C.danger,marginBottom:4}}>🚫 千万别这么开场</div>{gameRes.dontDo?.map((d,i)=><div key={i} style={{fontSize:10,color:C.t2,marginTop:3}}>· {d}</div>)}</Cd></>}{gameId==="praise"&&<><Cd s={{marginBottom:8,background:`${C.pink}06`}}><div style={{fontSize:13,fontWeight:700,color:C.pink,marginBottom:6}}>💌 夸 {gameRes.dim}</div><div style={{fontSize:11,color:C.t3,lineHeight:1.6}}>{gameRes.principle}</div></Cd>{gameRes.examples?.map((e,i)=><Cd key={i} s={{marginBottom:6}}><div style={{fontSize:11,color:C.danger,marginBottom:3}}>❌ {e.bad}</div><div style={{fontSize:12,fontWeight:600,color:C.safe,marginBottom:4}}>✅ {e.good}</div><div style={{fontSize:10,color:C.t3}}>💡 {e.why}</div></Cd>)}<Cd s={{background:`${C.danger}06`}}><div style={{fontSize:11,fontWeight:700,color:C.danger,marginBottom:4}}>🚫 这些不是赞美</div>{gameRes.reject?.map((r,i)=><div key={i} style={{fontSize:10,color:C.t2,marginTop:3}}>· {r}</div>)}</Cd></>}{gameId==="soft"&&<><Cd s={{marginBottom:8,background:`${C.safe}06`}}><div style={{fontSize:13,fontWeight:700,color:C.safe,marginBottom:6}}>🤲 温柔表达</div><div style={{fontSize:11,color:C.t3,lineHeight:1.6}}>{gameRes.principle}</div><div style={{fontSize:10,color:C.t3,marginTop:4,fontStyle:"italic"}}>📚 {gameRes.theory}</div></Cd>{gameRes.examples?.map((e,i)=><Cd key={i} s={{marginBottom:6}}><div style={{fontSize:11,fontWeight:700,color:C.purple,marginBottom:4}}>{e.scene}</div><div style={{fontSize:13,color:C.t1,lineHeight:1.6,padding:"4px 0"}}>「{e.say}」</div><div style={{fontSize:10,color:C.t3}}>💡 {e.why}</div></Cd>)}<Cd s={{background:`${C.danger}06`}}><div style={{fontSize:11,fontWeight:700,color:C.danger,marginBottom:4}}>🚫 别这么做</div>{gameRes.dontDo?.map((d,i)=><div key={i} style={{fontSize:10,color:C.t2,marginTop:3}}>· {d}</div>)}</Cd></>}{gameId==="waitprob"&&<><Cd s={{marginBottom:8,background:`${C.purple}06`}}><div style={{fontSize:13,fontWeight:700,color:C.purple,marginBottom:6}}>🎯 她没回的真实概率</div><div style={{fontSize:11,color:C.t3,lineHeight:1.6}}>{gameRes.principle}</div></Cd>{gameRes.probs?.map((p,i)=><Cd key={i} s={{marginBottom:6,padding:"8px 12px"}}><div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:4}}><div style={{fontSize:12,fontWeight:600,color:C.t1}}>{p.cause}</div><div style={{fontSize:14,fontWeight:900,color:C.pink}}>{p.pct}%</div></div><div style={{height:4,background:C.bd,borderRadius:2,overflow:"hidden",marginBottom:4}}><div style={{width:`${p.pct*2}%`,height:"100%",background:C.pink}}/></div><div style={{fontSize:10,color:C.t3}}>{p.note}</div></Cd>)}<Cd s={{background:`${C.safe}06`,marginBottom:6}}><div style={{fontSize:11,fontWeight:700,color:C.safe,marginBottom:4}}>✅ 该做什么</div><div style={{fontSize:11,color:C.t1,lineHeight:1.7}}>{gameRes.advice}</div>{gameRes.doInstead?.map((d,i)=><div key={i} style={{fontSize:10,color:C.t2,marginTop:3}}>· {d}</div>)}</Cd><Cd s={{background:`${C.danger}06`}}><div style={{fontSize:11,fontWeight:700,color:C.danger,marginBottom:4}}>🚫 千万别</div>{gameRes.dontDo?.map((d,i)=><div key={i} style={{fontSize:10,color:C.t2,marginTop:3}}>· {d}</div>)}</Cd></>}{gameId==="lovelang"&&<><Cd s={{marginBottom:8,background:`${C.pink}06`}}><div style={{fontSize:13,fontWeight:700,color:C.pink,marginBottom:6}}>📖 爱之语雷达</div><div style={{fontSize:11,color:C.t3,lineHeight:1.6,marginBottom:4}}>{gameRes.principle}</div><div style={{fontSize:10,color:C.t3,fontStyle:"italic"}}>📚 {gameRes.theory}</div></Cd><Cd s={{marginBottom:8}}><div style={{fontSize:11,color:C.t2,lineHeight:1.6}}>📝 {gameRes.instruction}</div></Cd>{gameRes.langs?.map((l,i)=><Cd key={i} s={{marginBottom:6}}><div style={{fontSize:12,fontWeight:700,color:C.purple,marginBottom:4}}>{l.name}</div><div style={{fontSize:10,color:C.t3,marginBottom:3}}>👁 信号：{l.signs}</div><div style={{fontSize:11,color:C.t1,lineHeight:1.6}}>💝 给她：{l.give}</div></Cd>)}<Cd s={{background:`${C.gold}06`}}><div style={{fontSize:11,fontWeight:700,color:C.gold,marginBottom:4}}>🔍 怎么判断她的型</div>{gameRes.howToTell?.map((h,i)=><div key={i} style={{fontSize:10,color:C.t2,marginTop:3}}>{h}</div>)}</Cd></>}{gameId==="mirror"&&<><Cd s={{textAlign:"center",marginBottom:10,background:`${gameRes.score>=70?C.safe:gameRes.score>=40?C.gold:C.danger}06`}}><div style={{fontSize:36,fontWeight:900,color:gameRes.score>=70?C.safe:gameRes.score>=40?C.gold:C.danger}}>🪞 {gameRes.score}</div><div style={{fontSize:13,fontWeight:700,color:C.t1,marginTop:4}}>{gameRes.level}</div></Cd><Cd s={{marginBottom:6}}><div style={{fontSize:12,color:C.t1,lineHeight:1.7}}>{gameRes.advice}</div></Cd><Cd s={{marginBottom:6}}><div style={{fontSize:11,fontWeight:700,color:C.pink,marginBottom:6}}>📋 10 项自检</div>{gameRes.checklist?.map((c,i)=><div key={i} style={{padding:"4px 0",borderBottom:i<9?`1px solid ${C.bd}`:"none"}}><div style={{fontSize:11,color:C.t1}}>{i+1}. {c.q}</div><div style={{fontSize:10,color:C.t3,marginTop:2}}>理想：{c.ideal}</div></div>)}</Cd><Cd s={{background:`${C.pink}06`}}><div style={{fontSize:11,color:C.t1,lineHeight:1.6}}>💡 {gameRes.principle}</div><div style={{fontSize:10,color:C.danger,marginTop:6,lineHeight:1.6}}>{gameRes.reject}</div></Cd></>}{gameId==="initiate"&&<><Cd s={{marginBottom:8,background:`${C.pink}06`}}><div style={{fontSize:13,fontWeight:700,color:C.pink,marginBottom:6}}>🦋 不掉价的主动</div><div style={{fontSize:11,color:C.t3,lineHeight:1.6}}>{gameRes.principle}</div></Cd>{gameRes.examples?.map((e,i)=><Cd key={i} s={{marginBottom:6}}><div style={{fontSize:11,fontWeight:700,color:C.purple,marginBottom:4}}>{e.scene}</div><div style={{fontSize:11,color:C.danger,marginBottom:3}}>❌ {e.bad}</div><div style={{fontSize:12,fontWeight:600,color:C.safe,marginBottom:4}}>✅ {e.good}</div><div style={{fontSize:10,color:C.t3}}>💡 {e.why}</div></Cd>)}<Cd s={{background:`${C.gold}06`,marginBottom:6}}><div style={{fontSize:11,color:C.t1,lineHeight:1.7,fontWeight:600}}>💎 {gameRes.insight}</div></Cd><Cd s={{background:`${C.danger}06`}}><div style={{fontSize:11,fontWeight:700,color:C.danger,marginBottom:4}}>🚫 这些想法要破除</div>{gameRes.reject?.map((r,i)=><div key={i} style={{fontSize:10,color:C.t2,marginTop:3}}>· {r}</div>)}</Cd></>}{gameId==="decode"&&<><Cd s={{marginBottom:8,background:`${C.peach}06`}}><div style={{fontSize:13,fontWeight:700,color:C.peach,marginBottom:6}}>🎭 直男翻译机</div><div style={{fontSize:11,color:C.t3,lineHeight:1.6,marginBottom:4}}>{gameRes.principle}</div><div style={{fontSize:10,color:C.t3,fontStyle:"italic"}}>💡 {gameRes.insight}</div></Cd>{gameRes.phrases?.map((p,i)=><Cd key={i} s={{marginBottom:6}}><div style={{fontSize:13,fontWeight:700,color:C.pink,marginBottom:6}}>「{p.say}」</div>{p.mean?.map((m,j)=><div key={j} style={{display:"flex",justifyContent:"space-between",padding:"3px 0",fontSize:11}}><div style={{color:C.t1}}>{m.what}</div><div style={{fontWeight:700,color:C.purple,marginLeft:8,flexShrink:0}}>{m.p}%</div></div>)}<div style={{fontSize:10,color:C.t3,marginTop:4,paddingTop:4,borderTop:`1px dashed ${C.bd}`}}>📌 {p.note}</div></Cd>)}<Cd s={{background:`${C.gold}06`}}><div style={{fontSize:11,fontWeight:700,color:C.gold,marginBottom:4}}>🧪 怎么测他真意</div>{gameRes.howToTest?.map((h,i)=><div key={i} style={{fontSize:10,color:C.t2,marginTop:3}}>· {h}</div>)}</Cd></>}{gameId==="boundary"&&<><Cd s={{marginBottom:8,background:`${C.safe}06`}}><div style={{fontSize:13,fontWeight:700,color:C.safe,marginBottom:6}}>🌿 软边界</div><div style={{fontSize:11,color:C.t3,lineHeight:1.6,marginBottom:4}}>{gameRes.principle}</div><div style={{fontSize:10,color:C.t3,fontStyle:"italic"}}>💡 {gameRes.insight}</div></Cd>{gameRes.examples?.map((e,i)=><Cd key={i} s={{marginBottom:6}}><div style={{fontSize:11,fontWeight:700,color:C.purple,marginBottom:4}}>{e.scene}</div><div style={{fontSize:11,color:C.danger,marginBottom:3}}>❌ {e.bad}</div><div style={{fontSize:12,fontWeight:600,color:C.safe,marginBottom:4}}>✅ {e.good}</div><div style={{fontSize:10,color:C.t3}}>💡 {e.why}</div></Cd>)}<Cd s={{background:`${C.danger}06`}}><div style={{fontSize:11,fontWeight:700,color:C.danger,marginBottom:4}}>🚫 这些想法要破除</div>{gameRes.reject?.map((r,i)=><div key={i} style={{fontSize:10,color:C.t2,marginTop:3}}>· {r}</div>)}</Cd></>}{gameId==="shine"&&<><Cd s={{marginBottom:8,background:`${C.purple}06`}}><div style={{fontSize:13,fontWeight:700,color:C.purple,marginBottom:6}}>💎 我的吸引力盘点</div><div style={{fontSize:12,color:C.t1,lineHeight:1.7,fontWeight:700,marginBottom:4}}>🌟 {gameRes.reminder}</div><div style={{fontSize:11,color:C.t3,lineHeight:1.6}}>{gameRes.principle}</div></Cd>{gameRes.userItems&&<Cd s={{marginBottom:6}}><div style={{fontSize:11,fontWeight:700,color:C.pink,marginBottom:4}}>📝 你输入的亮点</div>{gameRes.userItems.map((u,i)=><div key={i} style={{fontSize:11,color:C.t1,marginTop:3,padding:"3px 8px",background:`${C.pink}08`,borderRadius:4}}>· {u}</div>)}</Cd>}<Cd s={{marginBottom:6}}><div style={{fontSize:11,fontWeight:700,color:C.gold,marginBottom:6}}>🎯 6 维自我盘点</div>{gameRes.dimensions?.map((d,i)=><div key={i} style={{padding:"5px 0",borderBottom:i<5?`1px solid ${C.bd}`:"none"}}><div style={{fontSize:11,fontWeight:600,color:C.t1}}>{d.name}</div><div style={{fontSize:10,color:C.t3,marginTop:2}}>{d.check}</div></div>)}</Cd><Cd s={{background:`${C.safe}06`,marginBottom:6}}><div style={{fontSize:11,fontWeight:700,color:C.safe,marginBottom:4}}>✨ 这周可以做的</div>{gameRes.actions?.map((a,i)=><div key={i} style={{fontSize:10,color:C.t2,marginTop:3}}>· {a}</div>)}</Cd><Cd s={{background:`${C.gold}06`}}><div style={{fontSize:11,color:C.t1,lineHeight:1.7,fontWeight:600}}>💎 {gameRes.insight}</div></Cd></>}{gameId==="evidence"&&<><Cd s={{textAlign:"center",marginBottom:10,background:`${gameRes.score>=70?C.safe:gameRes.score>=40?C.gold:C.danger}06`}}><div style={{fontSize:36,fontWeight:900,color:gameRes.score>=70?C.safe:gameRes.score>=40?C.gold:C.danger}}>🔮 {gameRes.score}</div><div style={{fontSize:13,fontWeight:700,color:C.t1,marginTop:4}}>{gameRes.diagnosis}</div><div style={{fontSize:10,color:C.t3,marginTop:4}}>{gameRes.detail}</div></Cd><Cd s={{marginBottom:6}}><div style={{fontSize:12,color:C.t1,lineHeight:1.7}}>{gameRes.advice}</div></Cd><Cd s={{marginBottom:6}}><div style={{fontSize:11,fontWeight:700,color:C.pink,marginBottom:6}}>📊 5 项行为证据</div>{gameRes.checks?.map((c,i)=><div key={i} style={{padding:"4px 0",borderBottom:i<4?`1px solid ${C.bd}`:"none"}}><div style={{fontSize:11,color:C.t1}}>{i+1}. {c.q}</div><div style={{fontSize:10,color:C.t3,marginTop:2}}>📏 {c.measure}</div></div>)}</Cd><Cd s={{background:`${C.gold}06`,marginBottom:6}}><div style={{fontSize:11,color:C.t1,lineHeight:1.6,fontWeight:600}}>💡 {gameRes.principle}</div></Cd><Cd s={{background:`${C.danger}06`}}><div style={{fontSize:11,fontWeight:700,color:C.danger,marginBottom:4}}>🚫 别给自己找借口</div>{gameRes.reject?.map((r,i)=><div key={i} style={{fontSize:10,color:C.t2,marginTop:3}}>· {r}</div>)}</Cd></>}{gameId==="confess"&&<><Cd s={{marginBottom:8,background:`${C.gold}06`}}><div style={{fontSize:13,fontWeight:700,color:C.gold,marginBottom:6}}>🌅 告白前夜·清醒决策</div><div style={{fontSize:11,color:C.t3,lineHeight:1.6}}>{gameRes.principle}</div></Cd>{gameRes.questions?.map((q,i)=><Cd key={i} s={{marginBottom:6}}><div style={{fontSize:12,fontWeight:700,color:C.purple,marginBottom:6}}>问 {i+1}：{q.q}</div>{Object.entries(q).filter(([k])=>k!=="q").map(([k,v],j)=><div key={j} style={{fontSize:10,color:C.t2,padding:"4px 8px",background:`${C.bd}40`,borderRadius:4,marginTop:4}}><strong style={{color:C.pink}}>{k}：</strong>{v}</div>)}</Cd>)}<Cd s={{marginBottom:6,background:`${C.safe}06`}}><div style={{fontSize:11,fontWeight:700,color:C.safe,marginBottom:6}}>✅ 成熟告白模板（确认型）</div>{gameRes.templates?.confirm?.map((t,i)=><div key={i} style={{fontSize:11,color:C.t1,marginTop:4,lineHeight:1.6}}>· {t}</div>)}</Cd><Cd s={{marginBottom:6,background:`${C.safe}06`}}><div style={{fontSize:11,fontWeight:700,color:C.safe,marginBottom:6}}>✅ 推进式告白模板</div>{gameRes.templates?.advance?.map((t,i)=><div key={i} style={{fontSize:11,color:C.t1,marginTop:4,lineHeight:1.6}}>· {t}</div>)}</Cd><Cd s={{marginBottom:6,background:`${C.purple}06`}}><div style={{fontSize:11,fontWeight:700,color:C.purple,marginBottom:4}}>🌱 如果被拒绝</div>{gameRes.afterReject?.map((a,i)=><div key={i} style={{fontSize:10,color:C.t2,marginTop:3}}>· {a}</div>)}</Cd><Cd s={{background:`${C.danger}06`}}><div style={{fontSize:11,fontWeight:700,color:C.danger,marginBottom:4}}>🚫 这些想法要破除</div>{gameRes.reject?.map((r,i)=><div key={i} style={{fontSize:10,color:C.t2,marginTop:3}}>· {r}</div>)}</Cd></>}{gameId==="pace"&&<>{gameRes.redirect?<Cd s={{background:`${C.danger}10`,marginBottom:8}}><div style={{fontSize:13,fontWeight:700,color:C.danger,marginBottom:6}}>{gameRes.title}</div><div style={{fontSize:11,color:C.t2}}>{gameRes.message}</div></Cd>:<><Cd s={{marginBottom:8,background:`${C.purple}06`}}><div style={{fontSize:13,fontWeight:700,color:C.purple,marginBottom:6}}>🎯 你们的关系位置</div><div style={{fontSize:16,fontWeight:900,color:C.pink,marginBottom:4}}>阶段 {gameRes.stage} · {gameRes.stageName}</div><div style={{fontSize:10,color:C.t3,marginBottom:8}}>接触 → 实验 → 强化 → 整合 → 结合</div><div style={{display:"flex",gap:4,marginBottom:8}}>{[1,2,3,4,5].map(n=><div key={n} style={{flex:1,height:6,borderRadius:3,background:n<=gameRes.stage?C.pink:C.bd}}/>)}</div><div style={{fontSize:12,color:C.t1}}>⏱ 节奏：<strong style={{color:gameRes.pace==="正常"?C.safe:gameRes.pace==="偏快"?C.warn:C.danger}}>{gameRes.pace}</strong></div><div style={{fontSize:10,color:C.t3,marginTop:4}}>{gameRes.principle}</div></Cd><Cd s={{marginBottom:6,background:`${C.safe}06`}}><div style={{fontSize:11,fontWeight:700,color:C.safe,marginBottom:6}}>✅ 你可以做的下一步</div>{gameRes.doNext?.map((d,i)=><div key={i} style={{fontSize:11,color:C.t1,marginTop:4,lineHeight:1.6}}>{i+1}. {d}</div>)}</Cd><Cd s={{marginBottom:6,background:`${C.danger}06`}}><div style={{fontSize:11,fontWeight:700,color:C.danger,marginBottom:6}}>🚫 现在不建议</div>{gameRes.dontDo?.map((d,i)=><div key={i} style={{fontSize:10,color:C.t2,marginTop:3}}>× {d}</div>)}</Cd><Cd s={{background:`${C.bd}30`}}><div style={{fontSize:10,color:C.t3,lineHeight:1.6}}>📚 {gameRes.theory}</div></Cd></>}</>}{gameId==="anniv"&&<><Cd s={{marginBottom:8,background:`${C.pink}06`}}><div style={{fontSize:13,fontWeight:700,color:C.pink,marginBottom:6}}>🎂 基于 TA 的爱之语：{gameRes.langName}</div><div style={{fontSize:11,color:C.t3,lineHeight:1.6}}>{gameRes.principle}</div></Cd><Cd s={{marginBottom:6}}><div style={{fontSize:11,fontWeight:700,color:C.pink,marginBottom:6}}>🗓 时间线</div>{gameRes.timeline?.map((s,i)=><div key={i} style={{fontSize:11,color:C.t1,marginTop:4,lineHeight:1.6}}>{s}</div>)}</Cd><Cd s={{marginBottom:6,background:`${C.gold}06`}}><div style={{fontSize:11,fontWeight:700,color:C.gold,marginBottom:6}}>🎁 推荐方案（预算 ¥{gameRes.budget}）</div><div style={{fontSize:12,color:C.t1,lineHeight:1.6,marginBottom:6}}>⭐ {gameRes.gift}</div><div style={{fontSize:11,color:C.t3,lineHeight:1.6}}>备选：{gameRes.giftAlt}</div></Cd><Cd s={{marginBottom:6,background:`${C.purple}06`}}><div style={{fontSize:11,fontWeight:700,color:C.purple,marginBottom:6}}>💌 情书模板</div><div style={{fontSize:11,color:C.t1,lineHeight:1.8,whiteSpace:"pre-wrap"}}>{gameRes.letter}</div></Cd><Cd s={{marginBottom:6,background:`${C.danger}06`}}><div style={{fontSize:11,fontWeight:700,color:C.danger,marginBottom:6}}>🚫 避雷</div>{gameRes.avoid?.map((a,i)=><div key={i} style={{fontSize:10,color:C.t2,marginTop:3}}>× {a}</div>)}</Cd><Cd s={{marginBottom:6,background:`${C.safe}06`}}><div style={{fontSize:11,color:C.t1,lineHeight:1.6}}>{gameRes.easter}</div></Cd><Cd s={{background:`${C.bd}30`}}><div style={{fontSize:10,color:C.t3,lineHeight:1.6}}>📚 {gameRes.theory}</div></Cd></>}{gameId==="breakice"&&<>{gameRes.redirect?<Cd s={{background:`${C.danger}10`,marginBottom:8}}><div style={{fontSize:13,fontWeight:700,color:C.danger,marginBottom:6}}>{gameRes.title}</div><div style={{fontSize:11,color:C.t2,marginBottom:8}}>{gameRes.message}</div>{gameRes.resources?.map((r,i)=><div key={i} style={{fontSize:11,color:C.danger,fontWeight:700,marginTop:3}}>• {r}</div>)}{gameRes.suggest&&<div style={{fontSize:11,color:C.t1,marginTop:6}}>{gameRes.suggest}</div>}{gameRes.advice&&<div style={{fontSize:11,color:C.pink,marginTop:6,fontWeight:700}}>{gameRes.advice}</div>}</Cd>:<><Cd s={{marginBottom:8,background:`${C.purple}06`}}><div style={{fontSize:13,fontWeight:700,color:C.purple,marginBottom:6}}>🟢 第一步：软启动（现在发）</div><div style={{fontSize:10,color:C.t3,lineHeight:1.6}}>{gameRes.principle}</div></Cd>{gameRes.openers?.map((o,i)=><Cd key={i} s={{marginBottom:6,background:`${C.safe}06`}}><div style={{fontSize:11,fontWeight:700,color:C.safe,marginBottom:4}}>{o.type}</div><div style={{fontSize:12,color:C.t1,background:C.white,padding:"8px 10px",borderRadius:6,lineHeight:1.6,marginBottom:6}}>{o.say}</div>{o.why?.map((w,j)=><div key={j} style={{fontSize:10,color:C.t2,marginTop:2}}>✓ {w}</div>)}</Cd>)}<Cd s={{marginBottom:6}}><div style={{fontSize:11,fontWeight:700,color:C.gold,marginBottom:6}}>🟡 第二步：TA 回复后</div>{gameRes.ifReplied?.map((r,i)=><div key={i} style={{fontSize:11,color:C.t1,marginTop:4,paddingLeft:4,lineHeight:1.6}}><strong>{r.case}：</strong>{r.say}</div>)}</Cd><Cd s={{marginBottom:6,background:`${C.bd}30`}}><div style={{fontSize:11,fontWeight:700,color:C.t2,marginBottom:6}}>🔴 第三步：TA 不回</div>{gameRes.ifNoReply?.map((n,i)=><div key={i} style={{fontSize:11,color:C.t1,marginTop:4,lineHeight:1.6}}>{n}</div>)}</Cd><Cd s={{marginBottom:6,background:`${C.danger}06`}}><div style={{fontSize:11,fontWeight:700,color:C.danger,marginBottom:6}}>🚫 禁忌</div>{gameRes.taboos?.map((t2,i)=><div key={i} style={{fontSize:10,color:C.t2,marginTop:3}}>× {t2}</div>)}</Cd><Cd s={{background:`${C.bd}30`}}><div style={{fontSize:10,color:C.t3,lineHeight:1.6}}>📚 {gameRes.theory}</div></Cd></>}</>}{gameId==="reconcile"&&<>{gameRes.redirect?<Cd s={{background:`${C.danger}10`,marginBottom:8}}><div style={{fontSize:13,fontWeight:700,color:C.danger,marginBottom:6}}>{gameRes.title}</div><div style={{fontSize:11,color:C.t2,marginBottom:8}}>{gameRes.message}</div>{gameRes.resources?.map((r,i)=><div key={i} style={{fontSize:11,color:C.danger,fontWeight:700,marginTop:3}}>• {r}</div>)}{gameRes.suggest&&<div style={{fontSize:11,color:C.t1,marginTop:6}}>{gameRes.suggest}</div>}{gameRes.advice&&<div style={{fontSize:11,color:C.pink,marginTop:6,fontWeight:700}}>{gameRes.advice}</div>}</Cd>:<><Cd s={{marginBottom:8,background:`${C.purple}06`}}><div style={{fontSize:13,fontWeight:700,color:C.purple,marginBottom:6}}>🤔 你的真实状态</div><div style={{fontSize:16,fontWeight:900,color:C.pink,marginBottom:4}}>{gameRes.total} / 100</div><div style={{fontSize:12,color:C.t1,marginBottom:6}}>{gameRes.verdict}</div><div style={{fontSize:11,color:C.t3,lineHeight:1.6}}>{gameRes.principle}</div></Cd><Cd s={{marginBottom:6}}><div style={{fontSize:11,fontWeight:700,color:C.purple,marginBottom:6}}>📊 挽回可行的 5 个条件</div>{gameRes.conditions?.map((c,i)=><div key={i} style={{display:"flex",justifyContent:"space-between",fontSize:11,color:C.t1,marginTop:4,lineHeight:1.6}}><span>{c[0]}</span><strong style={{color:c[1]>c[2]*0.6?C.safe:c[1]>c[2]*0.3?C.warn:C.danger}}>{c[1]} / {c[2]}</strong></div>)}</Cd><Cd s={{marginBottom:6,background:`${C.gold}06`}}><div style={{fontSize:11,fontWeight:700,color:C.gold,marginBottom:6}}>🪞 你的真实动机</div><div style={{fontSize:11,color:C.t1,lineHeight:1.6}}>{gameRes.realMotive}</div></Cd><Cd s={{marginBottom:6,background:`${C.safe}06`}}><div style={{fontSize:11,fontWeight:700,color:C.safe,marginBottom:6}}>🌸 2 周自我照顾清单</div>{gameRes.checklist?.map((c,i)=><div key={i} style={{fontSize:11,color:C.t1,marginTop:4,lineHeight:1.6}}>✓ {c}</div>)}</Cd><Cd s={{marginBottom:6,background:`${C.danger}06`}}><div style={{fontSize:11,fontWeight:700,color:C.danger,marginBottom:6}}>🚫 这 2 周别做</div>{gameRes.dontDo?.map((d,i)=><div key={i} style={{fontSize:10,color:C.t2,marginTop:3}}>× {d}</div>)}</Cd><Cd s={{marginBottom:6,background:`${C.pink}06`}}><div style={{fontSize:11,color:C.t1,lineHeight:1.6}}>⏳ {gameRes.after2weeks}</div></Cd><Cd s={{background:`${C.bd}30`}}><div style={{fontSize:10,color:C.t3,lineHeight:1.6}}>📚 {gameRes.theory}</div></Cd></>}</>}{["opener","praise","soft","waitprob","lovelang","mirror","initiate","decode","boundary","shine","evidence","confess","pace","anniv","breakice","reconcile","ask_out","heat_up","test_him","long_dist"].includes(gameId)&&lastChoiceId&&learn&&<OutcomeFeedback choiceId={lastChoiceId} st={st} onFeedback={(id,outcome)=>{if(learn)learn.trackOutcome(id,outcome);}}/>}}<Btn onClick={()=>{setGameInp("");setGameRes(null);}}s={{background:C.bg,marginTop:10}}>🔄 再来一次</Btn></div>}</div></div>;
}if(view==="pickup")return <div style={{paddingBottom:100}}><SubHeader onBack={backHome}title="😎 搭讪攻略"/><div style={{padding:"14px 16px"}}><div style={{marginBottom:10}}><div style={{fontSize:11,fontWeight:600,color:C.t2,marginBottom:4}}>📍 在哪里</div><div style={{display:"flex",gap:4,flexWrap:"wrap"}}>{PICKUP_SCENES.map(s=><Pill key={s.l} active={puScene?.l===s.l} color={C.peri} onClick={()=>setPuScene(s)}>{s.icon} {s.l}</Pill>)}</div></div><div style={{marginBottom:10}}><div style={{fontSize:11,fontWeight:600,color:C.t2,marginBottom:4}}>😊 我的风格</div><div style={{display:"flex",gap:4,flexWrap:"wrap"}}>{MY_TRAITS.map(t=><Pill key={t.l} active={puMyTrait?.l===t.l} color={C.teal} onClick={()=>setPuMyTrait(t)}>{t.icon} {t.l}</Pill>)}</div></div><div style={{marginBottom:10}}><div style={{fontSize:11,fontWeight:600,color:C.t2,marginBottom:4}}>👤 对方状态</div><div style={{display:"flex",gap:4,flexWrap:"wrap"}}>{TA_TRAITS.map(t=><Pill key={t.l} active={puTaTrait?.l===t.l} color={C.pink} onClick={()=>setPuTaTrait(t)}>{t.icon} {t.l}</Pill>)}</div></div><div style={{marginBottom:10}}><div style={{fontSize:11,fontWeight:600,color:C.t2,marginBottom:4}}>🎯 目标</div><div style={{display:"flex",gap:4,flexWrap:"wrap"}}>{PICKUP_GOALS.map(g=><Pill key={g.l} active={puGoal?.l===g.l} color={C.gold} onClick={()=>setPuGoal(g)}>{g.icon} {g.l}</Pill>)}</div></div><Btn primary color={C.peri}onClick={doPu}disabled={!puScene||puLd}>{puLd?"生成中...":"😎 生成搭讪攻略"}</Btn>{puLd&&<Dots/>}{puRes&&<div style={{marginTop:14}}>{puRes.steps?.map((s,i)=><Cd key={i} s={{marginBottom:8}}><div style={{fontSize:10,fontWeight:700,color:C.peri,marginBottom:3}}>📍 {s.step}</div><div style={{fontSize:12,color:C.t1,lineHeight:1.7,marginBottom:3}}>🎯 {s.action}</div><div style={{fontSize:13,fontWeight:600,color:C.t1,marginBottom:3}}>💬 {s.say}</div><div style={{fontSize:10,color:C.t3}}>💡 {s.why}</div></Cd>)}{puRes.tips&&<Cd s={{background:`${C.safe}04`,marginBottom:6}}><div style={{fontSize:11,fontWeight:600,color:C.safe}}>💡 {puRes.tips}</div></Cd>}{puRes.avoid&&<Cd s={{background:`${C.danger}04`}}><div style={{fontSize:11,fontWeight:600,color:C.danger}}>⚠️ {puRes.avoid}</div></Cd>}<PickupFullPanel result={{compatibility:{score:72,pros:["场景匹配度高","双方特征互补"],cons:["注意不要过度热情","控制时间15分钟内"]}}} st={st}/></div>}</div></div>;return <div style={{paddingBottom:100,position:"relative",zIndex:1}}><div style={{textAlign:"center",padding:"18px 20px 10px"}}><div style={{fontSize:28,marginBottom:2}}>🎭</div><h2 style={{fontSize:18,fontWeight:800,background:`linear-gradient(135deg,${C.coral},${C.pink})`,WebkitBackgroundClip:"text",WebkitTextFillColor:"transparent"}}>教练</h2><p style={{fontSize:10,color:C.t3,marginTop:2}}>练完直接用 · 每次都有评分</p></div>{/* 模拟对话 */}<div style={{padding:"0 14px",marginBottom:16}}><div style={{fontSize:12,fontWeight:700,color:C.t1,marginBottom:8}}>🎭 模拟对话练习（{RP_SCENES.length}个场景）</div><div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:6}}>{RP_SCENES.map((sc,i)=><button key={sc.id} className="tap" onClick={()=>startRp(sc)} style={{padding:"12px 10px",borderRadius:14,background:C.white,border:`1px solid ${C.bd}`,cursor:"pointer",textAlign:"left"}}><div style={{fontSize:18,marginBottom:4}}>{sc.icon}</div><div style={{fontSize:12,fontWeight:700,color:C.t1}}>{sc.label}</div><div style={{fontSize:9,color:C.t3,marginTop:2,lineHeight:1.4}}>{sc.setup.slice(0,30)}...</div></button>)}</div></div>{/* 哄哄挑战 */}<div style={{padding:"0 14px",marginBottom:16}}><div style={{fontSize:12,fontWeight:700,color:C.t1,marginBottom:8}}>🎮 哄哄挑战（{COMFORT_CHALLENGES.length}个）</div>{COMFORT_CHALLENGES.map((ch,i)=><button key={ch.id} className="tap" onClick={()=>startCh(ch)} style={{width:"100%",padding:"12px 16px",borderRadius:14,background:C.white,border:`1px solid ${C.bd}`,cursor:"pointer",display:"flex",alignItems:"center",gap:12,textAlign:"left",marginBottom:6}}><div style={{width:40,height:40,borderRadius:12,background:`${C.coral}10`,display:"flex",alignItems:"center",justifyContent:"center",fontSize:20,flexShrink:0}}>{ch.icon}</div><div style={{flex:1}}><div style={{fontSize:13,fontWeight:700,color:C.t1}}>{ch.label}</div><div style={{fontSize:10,color:C.t3}}>{ch.desc}</div></div><div style={{fontSize:10,color:C.coral}}>{ch.diff}</div></button>)}</div>{/* 搭讪攻略 */}<div style={{padding:"0 14px",marginBottom:16}}><button className="tap" onClick={()=>setView("pickup")}style={{width:"100%",padding:"14px 16px",borderRadius:14,background:C.white,border:`1px solid ${C.bd}`,cursor:"pointer",display:"flex",alignItems:"center",gap:12,textAlign:"left"}}><div style={{width:44,height:44,borderRadius:14,background:`${C.peri}08`,display:"flex",alignItems:"center",justifyContent:"center",fontSize:22,flexShrink:0}}>😎</div><div><div style={{fontSize:14,fontWeight:700,color:C.t1}}>搭讪攻略</div><div style={{fontSize:10,color:C.t3}}>选场景 → 4步教你开口</div></div></button></div>{/* 约会攻略 */}<div style={{padding:"0 14px",marginBottom:16}}><div style={{fontSize:12,fontWeight:700,color:C.t1,marginBottom:8}}>📍 约会攻略（{DATE_GUIDES.length}个）</div><div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:6}}>{DATE_GUIDES.map((d,i)=><button key={i} className="tap" onClick={()=>{setDateView(i);setView("date");}} style={{padding:"12px 10px",borderRadius:14,background:C.white,border:`1px solid ${C.bd}`,cursor:"pointer",textAlign:"left"}}><div style={{fontSize:18,marginBottom:4}}>{d.icon}</div><div style={{fontSize:12,fontWeight:700,color:C.t1}}>{d.title}</div><div style={{display:"flex",gap:3,marginTop:3}}>{d.tags.map(t=><span key={t} style={{fontSize:8,padding:"1px 5px",borderRadius:4,background:`${C.gold}10`,color:C.gold}}>{t}</span>)}</div></button>)}</div></div>{/* v2.5 Plan C: 智能教练区 */}<V25SmartCoach stageId={stageId} setGameId={setGameId} setGameInp={setGameInp} setGameRes={setGameRes} setView={setView}/></div>;}
function SkillTab({st}){const[view,setView]=useState("home");const[artId,setArtId]=useState(null);const[puaInp,setPuaInp]=useState("");const[puaLd,setPuaLd]=useState(false);const[puaResult,setPuaResult]=useState(null);const[artFilter,setArtFilter]=useState("all");const tags=["all",...new Set(ARTICLES.map(a=>a.tag))];const doPuaCheck=async()=>{if(!puaInp.trim()||puaLd)return;setPuaLd(true);setPuaResult(null);const r=await ai(`你是情感操控识别专家。分析6个维度：道德绑架、煤气灯效应、贬低自尊、恐吓控制、例外化、条件式爱。风险评分0-100。返回JSON：{"risk":0-100,"patterns":[{"tag":"操控类型","match":"原文匹配部分","explain":"为什么是操控"}],"advice":"具体建议","safe":"可以直接发的安全回复"}`,`TA说：「${puaInp}」`);setPuaResult(pJ(r)||{risk:30,patterns:[],advice:"暂未发现明显操控",safe:"保持观察"});setPuaLd(false);};if(view==="article"&&artId!==null){const art=ARTICLES.find(a=>a.id===artId);if(!art)return null;return <div style={{paddingBottom:100}}><SubHeader onBack={()=>setView("home")} title={`${art.icon} ${art.title}`}/><div style={{padding:"14px 16px"}}><Badge color={C.peri}>{art.tag}</Badge><div style={{fontSize:12,color:C.t3,marginTop:4,marginBottom:12}}>{art.sub}</div><div style={{fontSize:14,color:C.t1,lineHeight:2}}>{art.content}</div></div></div>;}if(view==="puaCheck") return <div style={{paddingBottom:100}}><SubHeader onBack={()=>setView("home")} title="🛡️ PUA检测"/><div style={{padding:"14px 16px"}}><Cd s={{marginBottom:12,background:`${C.danger}04`}}><div style={{fontSize:11,color:C.danger,fontWeight:600,marginBottom:6}}>粘贴TA说的话，AI帮你分析</div><textarea value={puaInp} onChange={e=>setPuaInp(e.target.value)} placeholder="TA说了什么让你不舒服的话？" style={{width:"100%",minHeight:60,padding:0,background:"transparent",border:"none",color:C.t1,fontSize:14,outline:"none",resize:"none",lineHeight:1.7,fontFamily:font}}/></Cd><Btn primary color={C.danger} onClick={doPuaCheck} disabled={!puaInp.trim()||puaLd}>{puaLd?"检测中...":"🛡️ 检测操控行为"}</Btn>{puaLd&&<Dots/>}{puaResult&&<div style={{marginTop:14,animation:"fadeUp .3s"}}><Cd s={{marginBottom:10,textAlign:"center",background:puaResult.risk>=60?`${C.danger}06`:`${C.safe}06`}}><div style={{fontSize:28,fontWeight:900,color:puaResult.risk>=60?C.danger:C.safe}}>{puaResult.risk}</div><div style={{fontSize:11,color:C.t3}}>操控风险分</div></Cd>{puaResult.patterns?.map((p,i)=><Cd key={i} s={{marginBottom:6}}><div style={{display:"flex",gap:6,marginBottom:4}}><Badge color={C.danger}>{p.tag}</Badge></div><div style={{fontSize:12,color:C.t1,lineHeight:1.6,marginBottom:2}}>「{p.match}」</div><div style={{fontSize:11,color:C.t3}}>{p.explain}</div></Cd>)}{puaResult.advice&&<Cd s={{background:`${C.safe}04`,marginBottom:6}}><div style={{fontSize:11,fontWeight:600,color:C.safe,marginBottom:3}}>💡 建议</div><div style={{fontSize:12,color:C.t1,lineHeight:1.6}}>{puaResult.advice}</div></Cd>}{puaResult.safe&&<Cd><div style={{display:"flex",justifyContent:"space-between",gap:8}}><div><div style={{fontSize:11,fontWeight:600,color:C.teal,marginBottom:3}}>🛡️ 安全回复</div><div style={{fontSize:13,color:C.t1}}>{puaResult.safe}</div></div><CB text={puaResult.safe} st={st}/></div></Cd>}</div>}</div></div>;if(view==="pua") return <div style={{paddingBottom:100}}><SubHeader onBack={()=>setView("home")} title="🛡️ 8大操控话术"/><div style={{padding:"14px 16px"}}>{PUA_PATTERNS.map((p,i)=><Cd key={i} s={{marginBottom:8,animation:`fadeUp .15s ease ${i*.04}s both`}}><div style={{display:"flex",justifyContent:"space-between",marginBottom:4}}><Badge color={C.danger}>{p.tag}</Badge><span style={{fontSize:10,color:C.danger,fontWeight:700}}>⚠️ {p.risk}%</span></div><div style={{fontSize:13,fontWeight:600,color:C.t1,marginBottom:3}}>「{p.pattern}」</div><div style={{fontSize:11,color:C.t3,lineHeight:1.6}}>{p.explain}</div></Cd>)}<Btn primary color={C.danger} onClick={()=>setView("puaCheck")} s={{marginTop:8}}>🛡️ AI检测TA的话</Btn></div></div>;return <div style={{paddingBottom:100,position:"relative",zIndex:1}}><div style={{textAlign:"center",padding:"18px 20px 10px"}}><div style={{fontSize:28,marginBottom:2}}>📚</div><h2 style={{fontSize:18,fontWeight:800,background:`linear-gradient(135deg,${C.teal},${C.peri})`,WebkitBackgroundClip:"text",WebkitTextFillColor:"transparent"}}>技能</h2><p style={{fontSize:10,color:C.t3,marginTop:2}}>知识驱动成长</p></div><div style={{padding:"0 14px",marginBottom:14}}><button className="tap" onClick={()=>setView("pua")} style={{width:"100%",padding:"14px 16px",borderRadius:16,background:C.white,border:`1.5px solid ${C.danger}18`,cursor:"pointer",display:"flex",alignItems:"center",gap:12,textAlign:"left"}}><div style={{width:44,height:44,borderRadius:14,background:`${C.danger}08`,display:"flex",alignItems:"center",justifyContent:"center",fontSize:20,flexShrink:0}}>🛡️</div><div><div style={{fontSize:14,fontWeight:800,color:C.danger}}>反PUA识别</div><div style={{fontSize:10,color:C.t3}}>8大操控话术 + AI检测</div></div></button></div><div style={{padding:"0 14px",marginBottom:8}}><div style={{fontSize:12,fontWeight:700,color:C.t1,marginBottom:8}}>📖 恋爱课程</div><div style={{display:"flex",gap:4,marginBottom:10,overflowX:"auto"}}>{tags.map(t=><Pill key={t} active={artFilter===t} onClick={()=>setArtFilter(t)}>{t==="all"?"全部":t}</Pill>)}</div></div><div style={{padding:"0 14px"}}>{ARTICLES.filter(a=>artFilter==="all"||a.tag===artFilter).map((a,i)=><button key={a.id} className="tap" onClick={()=>{setArtId(a.id);setView("article");}} style={{width:"100%",padding:"12px 16px",borderRadius:14,background:C.white,border:`1px solid ${C.bd}`,cursor:"pointer",display:"flex",alignItems:"center",gap:12,textAlign:"left",marginBottom:6,animation:`fadeUp .12s ease ${i*.03}s both`}}><span style={{fontSize:22}}>{a.icon}</span><div style={{flex:1}}><div style={{fontSize:13,fontWeight:700,color:C.t1}}>{a.title}</div><div style={{fontSize:10,color:C.t3}}>{a.sub}</div></div><Badge color={C.peri}>{a.tag}</Badge></button>)}</div></div>;}/* ═════════════ P6: 我的 ═══════════════════ */
function VaultPage({onBack,vault,delVault,st}){const[vaultTab,setVaultTab]=useState("mine");const[myAmmo,setMyAmmo]=useState([]);const[newAmmo,setNewAmmo]=useState("");const[starred,setStarred]=useState({});useEffect(()=>{(async()=>{try{const r=await window.storage.get("my-ammo-v1");if(r?.value)setMyAmmo(JSON.parse(r.value));}catch{}try{const r=await window.storage.get("my-ammo-stars");if(r?.value)setStarred(JSON.parse(r.value));}catch{}})();},[]);const svMyAmmo=(n)=>{setMyAmmo(n);try{window.storage.set("my-ammo-v1",JSON.stringify(n));}catch{}};const addMyAmmo=()=>{if(!newAmmo.trim())return;const n=[{id:Date.now(),text:newAmmo.trim()},...myAmmo];svMyAmmo(n);setNewAmmo("");st?.("已添加 ✅");};const delMyAmmo=(id)=>{svMyAmmo(myAmmo.filter(x=>x.id!==id));};const toggleStar=(text)=>{const k=text.slice(0,30);const n={...starred};if(n[k]){delete n[k];setMyAmmo(myAmmo.filter(x=>x.text!==text));}else{n[k]=true;if(!myAmmo.find(x=>x.text===text)){const nm=[{id:Date.now(),text},...myAmmo];svMyAmmo(nm);}}setStarred(n);try{window.storage.set("my-ammo-stars",JSON.stringify(n));}catch{}};const isStar=(text)=>!!starred[text.slice(0,30)];const allTabs=["⭐ 我的",...AMMO_PRESETS.map(p=>p.cat)];return <div style={{paddingBottom:100}}><SubHeader onBack={onBack} title="💾 弹药库"/><div style={{display:"flex",gap:0,overflowX:"auto",padding:"6px 14px",borderBottom:`1px solid ${C.bdL}`}}>{allTabs.map((t,i)=>{const isActive=i===0?vaultTab==="mine":vaultTab===AMMO_PRESETS[i-1]?.cat;const cnt=i===0?myAmmo.length+vault.length:0;return <button key={t} className="tap2" onClick={()=>setVaultTab(i===0?"mine":AMMO_PRESETS[i-1].cat)} style={{padding:"6px 12px",borderRadius:10,fontSize:11,fontWeight:isActive?700:500,whiteSpace:"nowrap",border:"none",background:isActive?`${C.gold}12`:"transparent",color:isActive?C.gold:C.t3,cursor:"pointer"}}>{t}{i===0&&cnt>0?` (${cnt})`:""}</button>})}</div><div style={{padding:"10px 14px"}}>{vaultTab==="mine"&&<div><div style={{display:"flex",gap:6,marginBottom:12}}><input value={newAmmo} onChange={e=>setNewAmmo(e.target.value)} placeholder="写你的话术...回车添加" onKeyDown={e=>{if(e.key==="Enter")addMyAmmo();}}style={{flex:1,padding:"8px 12px",borderRadius:10,border:`1px solid ${C.bd}`,fontSize:12,outline:"none",background:C.white}}/><button className="tap" onClick={addMyAmmo} style={{padding:"8px 14px",borderRadius:10,background:`linear-gradient(135deg,${C.gold},${C.gold}cc)`,border:"none",color:"#fff",fontSize:12,fontWeight:700,cursor:"pointer"}}>+添加</button></div>{myAmmo.length===0&&vault.length===0?<div style={{textAlign:"center",padding:"30px 20px",color:C.t3}}><div style={{fontSize:36,marginBottom:8}}>⭐</div><div style={{fontSize:13,fontWeight:700,color:C.t1,marginBottom:4}}>还没有收藏</div><div style={{fontSize:11,lineHeight:1.6}}>上方输入自己的话术，或在预设分类中点⭐收藏</div></div>:null}{myAmmo.map(f=><div key={f.id} style={{display:"flex",alignItems:"center",gap:6,padding:"8px 10px",marginBottom:4,borderRadius:10,background:C.white,border:`1px solid ${C.bdL}`}}><div className="tap2" onClick={()=>{navigator.clipboard?.writeText(f.text);st?.("已复制");}} style={{flex:1,fontSize:12,color:C.t1,cursor:"pointer",lineHeight:1.6}}>{f.text}</div><button className="tap2" onClick={()=>delMyAmmo(f.id)} style={{padding:"3px 6px",borderRadius:6,background:"none",border:"none",color:C.t3,fontSize:11,cursor:"pointer"}}>✕</button></div>)}{vault.length>0&&<div style={{marginTop:12,paddingTop:8,borderTop:`1px solid ${C.bdL}`}}><div style={{fontSize:10,color:C.t3,marginBottom:6}}>📋 AI生成收藏 ({vault.length})</div>{vault.map(f=><div key={f.id} style={{display:"flex",alignItems:"center",gap:6,padding:"6px 10px",marginBottom:3,borderRadius:8,background:C.bg}}><div className="tap2" onClick={()=>{navigator.clipboard?.writeText(f.text);st?.("已复制");}} style={{flex:1,fontSize:11,color:C.t2,cursor:"pointer"}}>{f.tag&&<span style={{color:C.gold,marginRight:3}}>[{f.tag}]</span>}{f.text}</div><button className="tap2" onClick={()=>{delVault(f.id);st?.("已删除");}} style={{padding:"2px 5px",borderRadius:4,background:"none",border:"none",color:C.t3,fontSize:10,cursor:"pointer"}}>🗑️</button></div>)}</div>}</div>}{vaultTab!=="mine"&&AMMO_PRESETS.filter(p=>p.cat===vaultTab).map(p=><div key={p.cat}>{p.items.map((item,i)=><div key={i} style={{display:"flex",alignItems:"center",gap:6,padding:"8px 10px",marginBottom:4,borderRadius:10,background:C.white,border:`1px solid ${C.bdL}`}}><div className="tap2" onClick={()=>{navigator.clipboard?.writeText(item);st?.("已复制 · 可直接粘贴");}} style={{flex:1,fontSize:12,color:C.t1,cursor:"pointer",lineHeight:1.6}}>{item}</div><button className="tap2" onClick={()=>{toggleStar(item);st?.(isStar(item)?"取消收藏":"已收藏 ⭐");}} style={{padding:"3px 8px",borderRadius:6,background:isStar(item)?`${C.gold}15`:"transparent",border:`1px solid ${isStar(item)?C.gold+"30":C.bd}`,color:isStar(item)?C.gold:C.t3,fontSize:12,cursor:"pointer"}}>{isStar(item)?"⭐":"☆"}</button></div>)}</div>)}</div></div>;}
function MeTab({stageId,setStageId,personaId,setPersonaId,profile,setProfile,st,vault,delVault,diary,setDiary,svDiary,anniversaries,setAnniversaries,svAnniv,myStyle,setMyStyle,learn}){const[tab,setTab]=useState("stage");const[pCat,setPCat]=useState("all");const[sub,setSub]=useState(null);const[pulseHist,setPulseHist]=useState([]);const[todayPulse,setTodayPulse]=useState({intimacy:5,passion:5,commit:5});const[emotionAcct,setEmotionAcct]=useState([]);const[diaryInp,setDiaryInp]=useState("");const[diaryMood,setDiaryMood]=useState("💕");const[newAnniv,setNewAnniv]=useState({label:"",date:""});const[myPro,setMyPro]=useState({...MY_PRO});const[taList,setTaList]=useState([{id:1,name:"TA 1",...DPRO,...profile}]);const[activeTa,setActiveTa]=useState(0);useEffect(()=>{(async()=>{try{const m=await window.storage.get("sakura-mypro");if(m?.value)setMyPro(JSON.parse(m.value));}catch{}try{const t=await window.storage.get("sakura-talist");if(t?.value){const tl=JSON.parse(t.value);if(tl.length>0){setTaList(tl);setProfile(tl[0]);setActiveTa(0);}}}catch{}})();},[]);const save=async(k,v)=>{try{await window.storage.set(k,typeof v==="string"?v:JSON.stringify(v));}catch{}};const MOODS=["💕","🥰","😊","🤭","😤","😢","🥺","🔥","🧊","🌈"];const daysUntil=(ds)=>{const d=new Date(ds);const now=new Date();const ty=new Date(now.getFullYear(),d.getMonth(),d.getDate());if(ty<now)ty.setFullYear(ty.getFullYear()+1);return Math.ceil((ty-now)/86400000);};if(sub==="vault") return <VaultPage onBack={()=>setSub(null)} vault={vault} delVault={delVault} st={st}/>;if(sub==="diary") return <div style={{paddingBottom:100}}><SubHeader onBack={()=>setSub(null)} title={`📖 恋爱日记 · ${diary.length}条`}/><div style={{padding:"14px 16px"}}><Cd s={{marginBottom:14,background:`${C.pink}04`}}><div style={{display:"flex",gap:3,marginBottom:8,flexWrap:"wrap"}}>{MOODS.map(m=><button key={m} className="tap2" onClick={()=>setDiaryMood(m)} style={{width:28,height:28,borderRadius:8,background:diaryMood===m?`${C.pink}20`:"transparent",border:`1px solid ${diaryMood===m?C.pink+"30":"transparent"}`,fontSize:13,cursor:"pointer"}}>{m}</button>)}</div><textarea value={diaryInp} onChange={e=>setDiaryInp(e.target.value)} placeholder="记录甜蜜瞬间..." style={{width:"100%",minHeight:50,padding:0,background:"transparent",border:"none",color:C.t1,fontSize:13,outline:"none",resize:"none",lineHeight:1.7,fontFamily:font}}/><Btn primary color={C.pink} onClick={()=>{if(!diaryInp.trim())return;const e={id:Date.now(),text:diaryInp,mood:diaryMood,date:new Date().toLocaleDateString("zh-CN"),time:new Date().toLocaleTimeString("zh-CN",{hour:"2-digit",minute:"2-digit"})};const n=[e,...diary].slice(0,100);svDiary(n);setDiaryInp("");st("已记录 💕");}} disabled={!diaryInp.trim()} s={{marginTop:8}}>🌸 记录</Btn></Cd>{diary.map((e,i)=><Cd key={e.id} s={{marginBottom:6}}><div style={{display:"flex",justifyContent:"space-between",marginBottom:3}}><div style={{display:"flex",alignItems:"center",gap:5}}><span style={{fontSize:15}}>{e.mood}</span><span style={{fontSize:9,color:C.t3}}>{e.date} {e.time}</span></div><button className="tap2" onClick={()=>{svDiary(diary.filter(d=>d.id!==e.id));}}style={{background:"none",border:"none",color:C.t3,fontSize:10,cursor:"pointer"}}>×</button></div><div style={{fontSize:12,lineHeight:1.6,color:C.t1}}>{e.text}</div></Cd>)}</div></div>;if(sub==="anniv") return <div style={{paddingBottom:100}}><SubHeader onBack={()=>setSub(null)} title="📅 纪念日"/><div style={{padding:"14px 16px"}}><Cd s={{marginBottom:14}}><input value={newAnniv.label} onChange={e=>setNewAnniv(p=>({...p,label:e.target.value}))} placeholder="纪念日名称" style={{width:"100%",padding:"8px 12px",borderRadius:10,border:`1px solid ${C.bd}`,background:C.bg,fontSize:13,color:C.t1,outline:"none",fontFamily:font,marginBottom:6}}/><input type="date" value={newAnniv.date} onChange={e=>setNewAnniv(p=>({...p,date:e.target.value}))} style={{width:"100%",padding:"8px 12px",borderRadius:10,border:`1px solid ${C.bd}`,background:C.bg,fontSize:13,color:C.t1,outline:"none",fontFamily:font}}/><Btn primary onClick={()=>{if(!newAnniv.label||!newAnniv.date)return;svAnniv([...anniversaries,{...newAnniv,id:Date.now()}]);setNewAnniv({label:"",date:""});st("已添加 📅");}}disabled={!newAnniv.label||!newAnniv.date} s={{marginTop:8}}>➕ 添加</Btn></Cd>{[...anniversaries].sort((a,b)=>daysUntil(a.date)-daysUntil(b.date)).map((a,i)=><Cd key={a.id} s={{marginBottom:6,background:daysUntil(a.date)<=7?`${C.pink}04`:"transparent"}}><div style={{display:"flex",justifyContent:"space-between",alignItems:"center"}}><div><div style={{fontSize:13,fontWeight:700,color:C.t1}}>{a.label}</div><div style={{fontSize:10,color:C.t3}}>{a.date}</div></div><div style={{display:"flex",alignItems:"center",gap:8}}><div style={{fontSize:14,fontWeight:700,color:daysUntil(a.date)<=7?C.pink:C.t2}}>{daysUntil(a.date)}天</div><button className="tap2" onClick={()=>{svAnniv(anniversaries.filter(x=>x.id!==a.id));st("已删除");}} style={{background:"none",border:"none",color:C.t3,fontSize:11,cursor:"pointer"}}>×</button></div></div></Cd>)}</div></div>;if(sub==="style") return <div style={{paddingBottom:100}}><SubHeader onBack={()=>setSub(null)} title="🪞 更像我"/><div style={{padding:"14px 16px"}}><Cd s={{marginBottom:12,background:`${C.violet}04`}}><div style={{fontSize:13,fontWeight:700,color:C.violet,marginBottom:6}}>粘贴你平时发过的消息</div><div style={{fontSize:10,color:C.t3,lineHeight:1.5,marginBottom:8}}>AI会学习你的说话风格，让回复更像你。越多越准。</div><textarea value={myStyle} onChange={e=>setMyStyle(e.target.value)} placeholder={"粘贴你平时的聊天记录..."} style={{width:"100%",minHeight:120,padding:"10px 12px",background:C.bg,border:`1.5px solid ${myStyle?.trim()?C.violet+"40":C.bdL}`,borderRadius:12,color:C.t1,fontSize:13,outline:"none",resize:"none",lineHeight:1.7,fontFamily:font}}/><div style={{fontSize:9,color:C.t3,marginTop:4}}>💾 自动保存 · {(myStyle||"").length}字</div></Cd></div></div>;if(sub==="pulse"){const savePulse=async(h)=>{try{await window.storage.set("sakura-pulse",JSON.stringify(h));}catch{}};const recordToday=()=>{const today=new Date().toLocaleDateString("zh-CN");const avg=Math.round((todayPulse.intimacy+todayPulse.passion+todayPulse.commit)/3*10);const n=[{date:today,i:todayPulse.intimacy,p:todayPulse.passion,c:todayPulse.commit,avg},...pulseHist.filter(h=>h.date!==today)].slice(0,30);setPulseHist(n);savePulse(n);st("已记录 📊");};const addEmotion=(label,val)=>{const n=[{id:Date.now(),label,val,date:new Date().toLocaleDateString("zh-CN")},...emotionAcct].slice(0,50);setEmotionAcct(n);};const balance=emotionAcct.reduce((s,e)=>s+e.val,0);const deposits=emotionAcct.filter(e=>e.val>0);const withdrawals=emotionAcct.filter(e=>e.val<0);const last7=pulseHist.slice(0,7).reverse();return <div style={{paddingBottom:100}}><SubHeader onBack={()=>setSub(null)} title="📊 关系脉搏"/><div style={{padding:"14px 16px"}}><DkCd s={{marginBottom:12}}><div style={{fontSize:12,fontWeight:700,color:"#ffb7c5",marginBottom:10}}>📈 TriCore 周趋势</div>{last7.length>0?<div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-end",height:100,gap:4}}>{last7.map((d,i)=>{const h=d.avg||50;return <div key={i} style={{flex:1,textAlign:"center"}}><div style={{fontSize:9,color:"#b090a0",marginBottom:3}}>{h}%</div><div style={{height:80,display:"flex",flexDirection:"column",justifyContent:"stretch"}}><div style={{height:`${h}%`,borderRadius:"4px 4px 0 0",background:`linear-gradient(180deg,${C.peri}cc,${C.pink}88)`,minHeight:4,transition:"height .5s"}}/></div><div style={{fontSize:8,color:"#b090a0",marginTop:2}}>{d.date?.slice(-2)}</div></div>;})}</div>:<div style={{fontSize:11,color:"#b090a0",textAlign:"center",padding:16}}>还没有记录，在下方打分开始追踪</div>}</DkCd><DkCd s={{marginBottom:12}}><div style={{fontSize:12,fontWeight:700,color:"#ffb7c5",marginBottom:8}}>🏦 情感账户 <span style={{fontSize:18,fontWeight:900,color:balance>=0?C.safe:C.danger,marginLeft:8}}>{balance>=0?"+":""}{balance}</span></div><div style={{display:"flex",justifyContent:"space-between",marginBottom:8}}><div style={{textAlign:"center"}}><div style={{fontSize:9,color:C.safe}}>存入</div><div style={{fontSize:14,fontWeight:700,color:C.safe}}>+{deposits.reduce((s,e)=>s+e.val,0)}</div></div><div style={{textAlign:"center"}}><div style={{fontSize:9,color:C.danger}}>取出</div><div style={{fontSize:14,fontWeight:700,color:C.danger}}>{withdrawals.reduce((s,e)=>s+e.val,0)}</div></div></div>{emotionAcct.slice(0,5).map((e,i)=><div key={e.id} style={{display:"flex",justifyContent:"space-between",marginBottom:3,fontSize:10}}><span style={{color:"#b090a0"}}>{e.val>0?"✅":"⚠️"} {e.label}</span><span style={{fontWeight:700,color:e.val>0?C.safe:C.danger}}>{e.val>0?"+":""}{e.val}</span></div>)}<div style={{display:"flex",gap:4,marginTop:8,flexWrap:"wrap"}}>{[{l:"主动关心",v:15},{l:"约会投入",v:20},{l:"主动道歉",v:10},{l:"制造惊喜",v:12}].map(d=><button key={d.l} className="tap2" onClick={()=>{addEmotion(d.l,d.v);st(`+${d.v} 存入`);}} style={{padding:"3px 8px",borderRadius:6,background:"rgba(82,163,82,.1)",border:"none",color:C.safe,fontSize:9,cursor:"pointer"}}>+{d.v} {d.l}</button>)}{[{l:"追问不回",v:-8},{l:"攻击语言",v:-12},{l:"忽视感受",v:-10},{l:"翻旧账",v:-15}].map(d=><button key={d.l} className="tap2" onClick={()=>{addEmotion(d.l,d.v);st(`${d.v} 取出`);}} style={{padding:"3px 8px",borderRadius:6,background:"rgba(224,64,64,.08)",border:"none",color:C.danger,fontSize:9,cursor:"pointer"}}>{d.v} {d.l}</button>)}</div></DkCd><Cd s={{marginBottom:12}}><div style={{fontSize:12,fontWeight:700,color:C.t1,marginBottom:10}}>🌡️ 记录今天（0-10）</div>{[{k:"intimacy",l:"亲密",c:C.pink},{k:"passion",l:"激情",c:C.coral},{k:"commit",l:"承诺",c:C.peri}].map(s=><div key={s.k} style={{marginBottom:8}}><div style={{display:"flex",justifyContent:"space-between",fontSize:11,marginBottom:2}}><span style={{color:s.c,fontWeight:600}}>{s.l}</span><span style={{fontWeight:700,color:s.c}}>{todayPulse[s.k]}</span></div><input type="range" min={0} max={10} value={todayPulse[s.k]} onChange={e=>setTodayPulse(p=>({...p,[s.k]:+e.target.value}))} style={{width:"100%",background:`linear-gradient(90deg,${s.c}40,${s.c})`}}/></div>)}<Btn primary onClick={recordToday}>📊 记录今天</Btn></Cd><DkCd><div style={{fontSize:12,fontWeight:700,color:"#ffb7c5",marginBottom:8}}>📊 本周统计</div><div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:8,textAlign:"center"}}>{[{l:"诊断",v:pulseHist.length,c:C.peri,i:"🔬"},{l:"学习",v:learn?.getLearnStats?.()?.totalChoices||0,c:C.peri,i:"🧠"},{l:"收藏",v:vault.length,c:C.gold,i:"⭐"},{l:"日记",v:diary.length,c:C.pink,i:"📖"}].map(s=><div key={s.l}><div style={{fontSize:16}}>{s.i}</div><div style={{fontSize:20,fontWeight:900,color:s.c}}>{s.v}</div><div style={{fontSize:9,color:"#b090a0"}}>{s.l}</div></div>)}</div></DkCd></div></div>;}return <div style={{paddingBottom:100,position:"relative",zIndex:1}}><div style={{textAlign:"center",padding:"18px 20px 12px"}}><div style={{fontSize:28,marginBottom:2}}>👤</div><h2 style={{fontSize:18,fontWeight:800,color:C.t1}}>我的</h2></div><div style={{padding:"0 14px 10px",display:"flex",gap:6,justifyContent:"center",flexWrap:"wrap"}}><Badge color={STAGES.find(s=>s.id===stageId)?.c||C.pink}>{STAGES.find(s=>s.id===stageId)?.icon} {STAGES.find(s=>s.id===stageId)?.l}</Badge><Badge color={PERSONAS.find(p=>p.id===personaId)?.c||C.peri}>{PERSONAS.find(p=>p.id===personaId)?.icon} {PERSONAS.find(p=>p.id===personaId)?.l}</Badge>{profile.zodiac&&<Badge color={C.coral}>{ZODIACS.find(z=>z.id===profile.zodiac)?.icon} {ZODIACS.find(z=>z.id===profile.zodiac)?.l}</Badge>}</div><div style={{padding:"0 14px 6px"}}><button className="tap" onClick={()=>setSub("pulse")} style={{width:"100%",padding:"14px 16px",borderRadius:16,background:"rgba(30,20,28,.92)",border:"1px solid rgba(139,90,120,.2)",cursor:"pointer",display:"flex",alignItems:"center",gap:12,textAlign:"left",marginBottom:10}}><div style={{width:44,height:44,borderRadius:14,background:`linear-gradient(135deg,${C.peri}30,${C.pink}20)`,display:"flex",alignItems:"center",justifyContent:"center",fontSize:20,flexShrink:0}}>📊</div><div><div style={{fontSize:14,fontWeight:800,color:"#ffb7c5"}}>关系脉搏</div><div style={{fontSize:10,color:"#b090a0",marginTop:2}}>TriCore趋势 · 情感账户 · 周统计</div></div></button></div><div style={{padding:"0 14px 14px",display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}>{[{id:"vault",icon:"💾",l:"弹药库",d:`${vault.length}条收藏`,c:C.gold},{id:"diary",icon:"📖",l:"恋爱日记",d:`${diary.length}条记录`,c:C.pink},{id:"anniv",icon:"📅",l:"纪念日",d:anniversaries.length>0?`${anniversaries.length}个`:"添加纪念日",c:C.coral},{id:"style",icon:"🪞",l:"更像我",d:myStyle?`${myStyle.length}字样本`:"设置风格",c:C.violet}].map(f=><button key={f.id} className="tap" onClick={()=>setSub(f.id)} style={{padding:"12px",borderRadius:14,background:C.white,border:`1px solid ${C.bd}`,cursor:"pointer",textAlign:"left"}}><div style={{fontSize:18,marginBottom:4}}>{f.icon}</div><div style={{fontSize:12,fontWeight:700,color:f.c}}>{f.l}</div><div style={{fontSize:9,color:C.t3}}>{f.d}</div></button>)}</div><div style={{padding:"0 14px 12px",display:"flex",gap:4,borderRadius:16,overflow:"hidden",background:C.bg,margin:"0 14px"}}>{[{id:"stage",l:"📍阶段"},{id:"persona",l:"🎭人设"},{id:"zodiac",l:"♈星座"},{id:"me",l:"👤我"},{id:"ta",l:"💕TA"}].map(t=><button key={t.id} onClick={()=>setTab(t.id)} style={{flex:1,padding:"12px 4px",fontSize:12,fontWeight:tab===t.id?800:500,cursor:"pointer",background:tab===t.id?C.white:"transparent",color:tab===t.id?C.pink:C.t3,border:tab===t.id?`2px solid ${C.pink}30`:"2px solid transparent",borderRadius:12,boxShadow:tab===t.id?`0 2px 12px ${C.pink}15`:"none",transition:"all .15s"}}>{t.l}</button>)}</div><div style={{padding:"0 14px"}}>{tab==="stage"&&<div style={{display:"grid",gridTemplateColumns:"repeat(3,1fr)",gap:6}}>{STAGES.map((s,i)=><button key={s.id} className="tap" onClick={()=>{setStageId(s.id);save("sakura-stage",s.id);st(`${s.icon} ${s.l}`);}}style={{padding:"12px 6px",borderRadius:14,cursor:"pointer",textAlign:"center",background:stageId===s.id?`${s.c}10`:C.white,border:`1.5px solid ${stageId===s.id?s.c+"40":C.bd}`}}><div style={{fontSize:18}}>{s.icon}</div><div style={{fontSize:10,fontWeight:stageId===s.id?700:500,color:stageId===s.id?s.c:C.t2,marginTop:2}}>{s.l}</div>{stageId===s.id&&<div style={{fontSize:8,color:s.c,marginTop:1}}>{s.tip}</div>}</button>)}</div>}{tab==="persona"&&<div><div style={{display:"flex",gap:4,marginBottom:10,overflowX:"auto",paddingBottom:2}}>{["all","高频","功能","地域","文化梗","女性向"].map(cat=><Pill key={cat} active={pCat===cat} onClick={()=>setPCat(cat)}>{cat==="all"?"全部":cat}</Pill>)}</div><div style={{display:"grid",gridTemplateColumns:"repeat(4,1fr)",gap:6}}>{PERSONAS.filter(p=>pCat==="all"||p.cat===pCat).map(p=><button key={p.id} className="tap2" onClick={()=>{setPersonaId(p.id);save("sakura-persona",p.id);st(`${p.icon} ${p.l}`);}} style={{padding:"8px 4px",borderRadius:12,border:`1.5px solid ${personaId===p.id?p.c+"50":C.bdL}`,background:personaId===p.id?`${p.c}10`:"transparent",cursor:"pointer",textAlign:"center"}}><div style={{fontSize:18,marginBottom:1}}>{p.icon}</div><div style={{fontSize:9,fontWeight:personaId===p.id?700:500,color:personaId===p.id?p.c:C.t3}}>{p.l}</div></button>)}</div><div style={{marginTop:12}}><div style={{fontSize:11,fontWeight:600,color:C.t2,marginBottom:4}}>✏️ 自定义人设补充（选填）</div><textarea value={profile.customPersona||""} onChange={e=>setProfile({...profile,customPersona:e.target.value})} placeholder="补充你想要的说话风格...\n例如：说话带点东北味/喜欢用emoji/偶尔发语音的感觉" style={{width:"100%",minHeight:60,padding:"10px 12px",borderRadius:12,border:`1.5px solid ${C.bdL}`,background:C.bg,color:C.t1,fontSize:12,outline:"none",resize:"none",lineHeight:1.7,fontFamily:font}}/></div></div>}{tab==="me"&&<div><div style={{fontSize:11,color:C.t3,marginBottom:10,textAlign:"center"}}>👤 我的画像 · 已填{Object.values(myPro||{}).filter(v=>v?.trim()).length}/{MY_FIELDS.length}字段</div>{["基础","性格","喜好","自我认知","关系","动态"].map(g=>{const fields=MY_FIELDS.filter(f=>f.g===g);return fields.length?<div key={g} style={{marginBottom:12}}><div style={{fontSize:11,fontWeight:700,color:C.peri,marginBottom:5}}>{g}</div>{fields.map(f=><div key={f.k} style={{marginBottom:5}}><div style={{fontSize:10,fontWeight:600,color:C.t2,marginBottom:2}}>{f.i} {f.l}</div><input value={myPro?.[f.k]||""} onChange={e=>{const v={...myPro,[f.k]:e.target.value};setMyPro(v);}} placeholder={f.p} style={{width:"100%",padding:"7px 10px",borderRadius:10,border:`1.5px solid ${myPro?.[f.k]?.trim()?C.peri+"40":C.bdL}`,background:myPro?.[f.k]?.trim()?`${C.peri}06`:C.bg,color:C.t1,fontSize:12,outline:"none",fontFamily:font}}/></div>)}</div>:null;})}<Btn primary color={C.peri} onClick={()=>{save("sakura-mypro",myPro);st("已保存 👤");}}>💾 保存我的画像</Btn></div>}{tab==="ta"&&<div><div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:10}}><div style={{fontSize:11,color:C.t3}}>💕 TA的画像（{taList.length}个）</div><button className="tap2" onClick={()=>{const newTa={id:Date.now(),name:"TA "+(taList.length+1),...DPRO};const nl=[...taList,newTa];setTaList(nl);setActiveTa(nl.length-1);save("sakura-talist",nl);st("➕ 新增TA");}} style={{padding:"4px 12px",borderRadius:8,background:`${C.pink}10`,border:`1px solid ${C.pink}30`,color:C.pink,fontSize:11,fontWeight:700,cursor:"pointer"}}>➕ 添加TA</button></div>{taList.length>1&&<div style={{display:"flex",gap:4,marginBottom:10,overflowX:"auto"}}>{taList.map((ta,i)=><button key={ta.id} className="tap2" onClick={()=>{setActiveTa(i);setProfile(taList[i]);}} style={{padding:"5px 12px",borderRadius:10,fontSize:10,fontWeight:activeTa===i?700:500,background:activeTa===i?`${C.pink}12`:"transparent",border:`1.5px solid ${activeTa===i?C.pink+"40":C.bd}`,color:activeTa===i?C.pink:C.t3,cursor:"pointer",whiteSpace:"nowrap",flexShrink:0}}>{ta.nickname||ta.name||`TA ${i+1}`}</button>)}</div>}{taList.length===0&&<div style={{textAlign:"center",padding:20}}><div style={{fontSize:36,marginBottom:8}}>💕</div><div style={{fontSize:13,color:C.t2}}>还没有TA的档案</div><Btn primary onClick={()=>{const newTa={id:Date.now(),name:"TA 1",...DPRO};setTaList([newTa]);setActiveTa(0);setProfile(newTa);save("sakura-talist",[newTa]);st("已创建");}}>➕ 创建TA的画像</Btn></div>}{taList.length>0&&<div><div style={{fontSize:11,color:C.t3,marginBottom:8,textAlign:"center"}}>填越多AI回复越精准 · 已填{Object.values(profile).filter(v=>v?.trim()).length}/{PFIELDS.length}字段</div>{["基础","性格","喜好","沟通","关系","动态"].map(g=>{const fields=PFIELDS.filter(f=>f.g===g);return fields.length?<div key={g} style={{marginBottom:12}}><div style={{fontSize:11,fontWeight:700,color:C.pink,marginBottom:5}}>{g}</div>{fields.map(f=><div key={f.k} style={{marginBottom:5}}><div style={{fontSize:10,fontWeight:600,color:C.t2,marginBottom:2}}>{f.i} {f.l}</div><input value={profile[f.k]||""} onChange={e=>{const v={...profile,[f.k]:e.target.value};setProfile(v);const nl=[...taList];nl[activeTa]=v;setTaList(nl);}} placeholder={f.p} style={{width:"100%",padding:"7px 10px",borderRadius:10,border:`1.5px solid ${profile[f.k]?.trim()?C.sakura:C.bdL}`,background:profile[f.k]?.trim()?`${C.sakura}06`:C.bg,color:C.t1,fontSize:12,outline:"none",fontFamily:font}}/></div>)}</div>:null;})}<div style={{display:"flex",gap:8}}><Btn primary onClick={()=>{const nl=[...taList];nl[activeTa]=profile;setTaList(nl);save("sakura-talist",nl);save("sakura-profile",profile);st("已保存 💕");}}>💾 保存</Btn>{taList.length>1&&<button className="tap" onClick={()=>{if(!confirm("确定删除这个TA的档案？"))return;const nl=taList.filter((_,i)=>i!==activeTa);setTaList(nl);setActiveTa(0);if(nl.length>0)setProfile(nl[0]);else setProfile({...DPRO});save("sakura-talist",nl);st("已删除");}} style={{padding:"13px 16px",borderRadius:14,background:`${C.danger}08`,border:`1px solid ${C.danger}20`,color:C.danger,fontSize:12,cursor:"pointer"}}>🗑️</button>}</div></div>}</div>}{tab==="zodiac"&&<div><div style={{fontSize:11,color:C.t3,marginBottom:10,textAlign:"center"}}>选TA的星座，AI回复更精准</div><div style={{display:"grid",gridTemplateColumns:"repeat(4,1fr)",gap:6}}>{ZODIACS.map(z=><button key={z.id} className="tap" onClick={()=>{const v={...profile,zodiac:z.id};setProfile(v);save("sakura-profile",v);st(`${z.icon} ${z.l}`);}}style={{padding:"10px 4px",borderRadius:14,cursor:"pointer",textAlign:"center",background:profile.zodiac===z.id?`${C.coral}10`:C.white,border:`1.5px solid ${profile.zodiac===z.id?C.coral+"40":C.bd}`}}><div style={{fontSize:20}}>{z.icon}</div><div style={{fontSize:11,fontWeight:profile.zodiac===z.id?700:500,color:profile.zodiac===z.id?C.coral:C.t2}}>{z.l}</div><div style={{fontSize:8,color:C.t3,marginTop:1}}>{z.tip}</div></button>)}</div></div>}</div></div>;}/* ═════════════ APP SHELL ═══════════════════ */


/* ═══ STEP_FORMS · 分步引导表单配置 (v1.0) ═══
   5 个高复杂度功能的结构化输入,替代空文本框 */
const STEP_FORMS = {
  waitprob: {
    title: "🎯 她没回我的真实概率",
    subtitle: "填下面几个字段 · AI 会给你精准诊断",
    fields: [
      {id: "last_msg", label: "你最后发的那句话是?", type: "textarea", placeholder: "完整粘贴或复述你最后发的消息", required: true},
      {id: "duration", label: "距今多久没回?", type: "select", options: ["30分钟内", "1-4 小时", "4-12 小时", "12-24 小时", "1-2 天", "2 天以上"]},
      {id: "normal_pace", label: "之前她回复的节奏是?", type: "select", options: ["每条秒回", "正常节奏(几小时内)", "忽快忽慢", "本来话就少", "有时过夜才回"]},
      {id: "context", label: "最近你们互动怎样?(可选)", type: "textarea", placeholder: "最近的频率/上次见面/最近聊的话题...", required: false}
    ]
  },
  confess: {
    title: "🌅 告白前夜清醒决策",
    subtitle: "3 个关键问题 · 想清楚再决定",
    fields: [
      {id: "how_long", label: "你们认识/暧昧多久了?", type: "select", options: ["1 个月内", "1-3 个月", "3-6 个月", "6 个月-1 年", "1 年以上"]},
      {id: "signals", label: "TA 对你释放过什么信号?", type: "textarea", placeholder: "具体行为:主动找你/记得细节/介绍给朋友/身体接触...", required: true},
      {id: "motive", label: "你想告白的真实动机是?", type: "select", options: ["我爱 TA 想推进", "我想确认关系", "我怕 TA 被别人追走", "我想结束这种模糊状态", "我也不确定"]},
      {id: "after_reject", label: "如果 TA 拒绝,你能接受继续做朋友吗?", type: "select", options: ["可以,关系重要", "不行,会太尴尬", "需要一段时间消化", "不知道"]},
      {id: "worries", label: "你最担心什么?(可选)", type: "textarea", placeholder: "表白被拒绝/失去朋友/尴尬/错过时机...", required: false}
    ]
  },
  breakice: {
    title: "❄️ 冷战破冰脚本",
    subtitle: "Gottman 软启动 · 第一句话决定能否和好",
    fields: [
      {id: "duration", label: "冷战多久了?", type: "select", options: ["24 小时内", "24-48 小时", "48-72 小时", "3-7 天", "超过一周"]},
      {id: "reason", label: "吵架原因是什么?", type: "textarea", placeholder: "具体描述吵架的点,别只说对方的错", required: true},
      {id: "personality", label: "TA 的性格类型?", type: "select", options: ["理性型(讲道理)", "敏感型(吃软不吃硬)", "高冷型(不主动但吃软)", "爆发型(需要时间冷静)", "闷葫芦型(不爱表达)"]},
      {id: "fault", label: "谁先错了?(诚实回答)", type: "select", options: ["我错了", "TA 错了", "都有错", "说不清"]},
      {id: "want", label: "你现在真实想法是?", type: "select", options: ["想和好", "想 TA 先道歉", "还在气头上", "想分手", "想先冷静"]}
    ]
  },
  lovelang: {
    title: "📖 爱之语雷达",
    subtitle: "填入 TA 最近的反应 · AI 诊断 TA 的接收频道",
    fields: [
      {id: "moment1", label: "TA 最近让你感动/开心的 1 件事", type: "textarea", placeholder: "具体事件+你做了什么+TA 的反应", required: true},
      {id: "moment2", label: "TA 最近让你感动/开心的第 2 件事", type: "textarea", placeholder: "具体描述", required: true},
      {id: "upset1", label: "TA 最近让你不爽/失望的 1 件事", type: "textarea", placeholder: "具体事件+为什么不爽", required: true},
      {id: "upset2", label: "TA 最近让你不爽/失望的第 2 件事", type: "textarea", placeholder: "具体描述", required: false},
      {id: "your_effort", label: "你为 TA 做了很多但 TA 似乎没感觉的事?(可选)", type: "textarea", placeholder: "比如送礼物/陪伴/做家务,但 TA 反应冷淡", required: false}
    ]
  },
  reconcile: {
    title: "🤔 挽回前自检",
    subtitle: "5 个问题 · 看清你是真的想挽回,还是不甘心",
    fields: [
      {id: "duration", label: "分手多久了?", type: "select", options: ["1 周内", "1-4 周", "1-3 个月", "3-6 个月", "超过 6 个月"]},
      {id: "who_broke", label: "谁提的分手?", type: "select", options: ["TA 提的", "我提的", "两人都想分", "一时冲动说的"]},
      {id: "reason", label: "主要分手原因?", type: "select", options: ["性格不合", "感情淡了", "TA 变心/出轨", "异地/距离", "家庭反对", "不尊重/伤害", "其他"]},
      {id: "trust", label: "如果 TA 现在回来,你还能信任吗?", type: "select", options: ["完全能", "需要重建", "很难了", "不可能"]},
      {id: "motive", label: "你想挽回的真实原因?", type: "select", options: ["我爱 TA", "我习惯了 TA", "我怕重新开始", "我怕 TA 找下一个", "我觉得还没努力够"]},
      {id: "problem_solved", label: "你们之间的核心问题...", type: "select", options: ["已经解决了", "没解决但互相道歉了", "TA 承诺改但没具体行动", "问题一直都在"]},
      {id: "tolerance", label: "你能接受 TA 再犯一次同样的问题吗?", type: "select", options: ["可以", "一次可以", "不能", "绝不可能"]},
      {id: "support", label: "朋友/家人怎么看这段关系?", type: "select", options: ["都支持", "一半一半", "多数不支持", "都反对"]}
    ]
  }
};

/* ═══ StepForm 组件:根据配置渲染结构化表单 ═══ */
function StepForm({gameId, onSubmit, loading, color}) {
  const config = STEP_FORMS[gameId];
  const [values, setValues] = useState({});
  if (!config) return null;
  const canSubmit = config.fields.every(f => !f.required || (values[f.id] && values[f.id].trim()));
  const handleSubmit = () => {
    // Format values into a structured multi-line string for AI consumption
    const lines = config.fields
      .filter(f => values[f.id] && values[f.id].toString().trim())
      .map(f => `【${f.label}】${values[f.id]}`);
    const formatted = lines.join("\n");
    onSubmit(formatted);
  };
  return (
    <div>
      <div style={{fontSize:13,fontWeight:700,color:color||C.pink,marginBottom:4}}>{config.title}</div>
      <div style={{fontSize:11,color:C.t3,marginBottom:14}}>{config.subtitle}</div>
      {config.fields.map((f, i) => (
        <div key={f.id} style={{marginBottom:14}}>
          <div style={{fontSize:11,fontWeight:700,color:C.t2,marginBottom:6,display:"flex",alignItems:"center",gap:6}}>
            <span style={{background:color||C.pink,color:"#fff",fontSize:9,padding:"1px 6px",borderRadius:8,fontWeight:800}}>{i+1}</span>
            {f.label}
            {f.required && <span style={{color:C.danger,fontSize:9}}>必填</span>}
          </div>
          {f.type === "select" ? (
            <div style={{display:"flex",flexWrap:"wrap",gap:5}}>
              {f.options.map(opt => (
                <button key={opt} className="tap2" onClick={() => setValues({...values, [f.id]: opt})}
                  style={{padding:"6px 11px",borderRadius:12,border:`1.5px solid ${values[f.id]===opt?(color||C.pink):C.bdL}`,background:values[f.id]===opt?`${color||C.pink}10`:"transparent",color:values[f.id]===opt?(color||C.pink):C.t2,fontSize:11,fontWeight:values[f.id]===opt?700:500,cursor:"pointer"}}>
                  {opt}
                </button>
              ))}
            </div>
          ) : (
            <textarea value={values[f.id]||""} onChange={e => setValues({...values, [f.id]: e.target.value})}
              placeholder={f.placeholder}
              style={{width:"100%",minHeight:60,padding:"8px 10px",borderRadius:10,border:`1.5px solid ${values[f.id]?.trim()?(color||C.pink)+"40":C.bdL}`,background:values[f.id]?.trim()?`${color||C.pink}06`:C.bg,color:C.t1,fontSize:12,outline:"none",resize:"vertical",lineHeight:1.6,fontFamily:"inherit"}}/>
          )}
        </div>
      ))}
      <Btn primary color={color||C.pink} onClick={handleSubmit} disabled={!canSubmit||loading}>
        {loading ? "分析中..." : `✨ AI 深度分析`}
      </Btn>
    </div>
  );
}

function App(){const[tab,setTab]=useState("flash");const learn=useLearningEngine();const[toast,setToast]=useState(null);const[vip,setVip]=useState(false);const[coachIntroShown,setCoachIntroShown]=useState(true);const[puaScanOn,setPuaScanOnState]=useState(true);const setPuaScanOn=(v)=>{setPuaScanOnState(v);try{globalThis.__puaScanOff=!v;window.storage.set("sakura-pua-scan",v?"on":"off");}catch{}};useEffect(()=>{try{globalThis.__puaScanOff=!puaScanOn;}catch{}},[puaScanOn]);const[showPay,setShowPay]=useState(false);const[stageId,setStageId]=useState("flirt");const[personaId,setPersonaId]=useState("eq");const[profile,setProfile]=useState({...DPRO});const[vault,setVault]=useState([]);const[diary,setDiary]=useState([]);const[anniversaries,setAnniversaries]=useState([]);const[myStyle,setMyStyle]=useState("");const[loaded,setLoaded]=useState(false);const[onboarded,setOnboarded]=useState(true);const[privacyOk,setPrivacyOk]=useState(false);const[entryMode,setEntryMode]=useState("classic");const[taskFilter,setTaskFilter]=useState(null);const[fontSize,setFontSize]=useState(14);const[showSettings,setShowSettings]=useState(false);const[sosInp,setSosInp]=useState("");const[sosLd,setSosLd]=useState(false);const[sosRes,setSosRes]=useState(null);const[taAvatar,setTaAvatar]=useState(null);const doSos=async()=>{if(!sosInp.trim()||sosLd)return;setSosLd(true);setSosRes(null);const r=await ai(buildSys(stageId,personaId,profile,`紧急求助。用户需要立即可发的回复。返回JSON：{"reply":"直接发送的话(20字内)","why":"为什么这么说(1句)","risk":"low/med/high","alt":"备选回复"}`),"紧急："+sosInp);const p=pJ(r);setSosRes(p||{reply:"我在呢，你说",why:"先给安全感",risk:"low",alt:"嗯嗯，我听着"});setSosLd(false);};const st=useCallback(m=>{setToast(m);setTimeout(()=>setToast(null),1800);},[]);const sv=async(k,v)=>{try{await window.storage.set(k,typeof v==="string"?v:JSON.stringify(v));}catch{}};const addVault=(text,tag)=>{const n=[{id:Date.now(),text,tag,time:new Date().toLocaleDateString("zh-CN")},...vault].slice(0,200);setVault(n);sv("sakura-vault",n);st("已收藏 ⭐");};const delVault=(id)=>{const n=vault.filter(f=>f.id!==id);setVault(n);sv("sakura-vault",n);};useEffect(()=>{(async()=>{try{const r=await window.storage.get("sakura-profile");if(r?.value)setProfile(JSON.parse(r.value));}catch{}try{const r=await window.storage.get("sakura-stage");if(r?.value)setStageId(r.value);}catch{}try{const r=await window.storage.get("sakura-persona");if(r?.value)setPersonaId(r.value);}catch{}try{const r=await window.storage.get("sakura-vault");if(r?.value)setVault(JSON.parse(r.value));}catch{}try{const r=await window.storage.get("sakura-diary");if(r?.value)setDiary(JSON.parse(r.value));}catch{}try{const r=await window.storage.get("sakura-anniversaries");if(r?.value)setAnniversaries(JSON.parse(r.value));}catch{}try{const r=await window.storage.get("sakura-style");if(r?.value)setMyStyle(r.value);}catch{}try{const r=await window.storage.get("sakura-fontsize");if(r?.value)setFontSize(+r.value);}catch{}try{const r=await window.storage.get("sakura-taavatar");if(r?.value&&r.value.startsWith("data:"))setTaAvatar(r.value);}catch{}try{const r=await window.storage.get("sakura-onboarded");if(!r?.value)setOnboarded(false);}catch{}try{const p=await window.storage.get("sakura-privacy-v1");if(p?.value==="accepted")setPrivacyOk(true);}catch{/*keep false*/}try{const em=await window.storage.get("sakura-entry-mode");if(em?.value==="results")setEntryMode("results");}catch{}try{const v=await window.storage.get("sakura-vip");if(v?.value==="true")setVip(true);}catch{}try{const c=await window.storage.get("sakura-coach-intro-v1");if(!c?.value)setCoachIntroShown(false);}catch{}try{const pu=await window.storage.get("sakura-pua-scan");if(pu?.value==="off")setPuaScanOn(false);}catch{}setLoaded(true);})();},[]);/* v2.5 Anniversary daily push check */useEffect(()=>{(async()=>{try{const enabled=await window.storage.get("sakura-push-enabled");if(enabled?.value!=="1")return;if(!("Notification" in window))return;if(Notification.permission!=="granted")return;const lastCheck=await window.storage.get("sakura-push-last-check");const today=new Date().toDateString();if(lastCheck?.value===today)return;const annivs=anniversaries||[];const now=new Date();for(const a of annivs){const d=new Date(a.date);const ty=new Date(now.getFullYear(),d.getMonth(),d.getDate());if(ty<now)ty.setFullYear(ty.getFullYear()+1);const days=Math.ceil((ty-now)/86400000);if(days===3||days===1||days===0){const title=days===0?`🎉 今天是 ${a.label}!`:`🔔 ${a.label} 还有 ${days} 天`;const body=days===0?`别忘了对 TA 说些温暖的话`:days===1?`明天就是 ${a.label},准备好了吗?`:`3 天后是 ${a.label},现在开始准备刚好`;try{new Notification(title,{body,icon:"/favicon.ico",tag:`anniv-${a.id}-${days}`});}catch{}}}await window.storage.set("sakura-push-last-check",today);}catch{}})();},[anniversaries,loaded]);useEffect(()=>{if(!loaded)return;const t=setTimeout(()=>{try{window.storage.set("sakura-profile",JSON.stringify(profile));}catch{}},800);return()=>clearTimeout(t);},[profile,loaded]);const TABS=[{id:"flash",icon:"⚡",l:"秒回"},{id:"ai",icon:"✨",l:"AI思考"},{id:"deep",icon:"🔬",l:"解析"},{id:"coach",icon:"🎭",l:"教练"},{id:"skill",icon:"📚",l:"技能"},{id:"me",icon:"👤",l:"我的"}];if(!privacyOk) return <div style={{maxWidth:430,margin:"0 auto",minHeight:"100vh",background:C.bg,fontFamily:font,position:"relative",overflow:"hidden"}}><style>{CSS}</style><PrivacyDialog onAccept={()=>setPrivacyOk(true)}/></div>;if(!onboarded) return <div style={{maxWidth:430,margin:"0 auto",minHeight:"100vh",background:C.bg,fontFamily:font,position:"relative",overflow:"hidden"}}><style>{CSS}</style><Petals/><div style={{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",minHeight:"100vh",padding:32,position:"relative",zIndex:1}}><div style={{fontSize:48,marginBottom:12,animation:"breathe 3s infinite"}}>🌸</div><div style={{fontSize:22,fontWeight:900,background:`linear-gradient(135deg,${C.pink},${C.gold})`,WebkitBackgroundClip:"text",WebkitTextFillColor:"transparent",marginBottom:6}}>Sakura Ultimate</div><div style={{fontSize:12,color:C.t2,textAlign:"center",lineHeight:1.7,marginBottom:6}}>最懂恋爱的 AI 助手 · 你幸福的守护者</div><div style={{fontSize:10,color:C.t3,textAlign:"center",lineHeight:1.6,marginBottom:20}}>从第一句话到纪念日,陪你经营一整段关系</div><div style={{fontSize:13,fontWeight:700,color:C.t1,marginBottom:8,alignSelf:"flex-start"}}>你们现在什么阶段？</div><div style={{display:"flex",gap:5,flexWrap:"wrap",marginBottom:20,justifyContent:"center"}}>{STAGES.slice(0,8).map(s=><button key={s.id} className="tap2" onClick={()=>{setStageId(s.id);sv("sakura-stage",s.id);}} style={{padding:"6px 12px",borderRadius:12,border:`1.5px solid ${stageId===s.id?C.pink+"50":C.bdL}`,background:stageId===s.id?C.pinkBg:"transparent",color:stageId===s.id?C.pink:C.t2,fontSize:11,fontWeight:stageId===s.id?700:500,cursor:"pointer"}}>{s.icon} {s.l}</button>)}</div><div style={{fontSize:13,fontWeight:700,color:C.t1,marginBottom:8,alignSelf:"flex-start"}}>选一个说话风格</div><div style={{display:"flex",gap:5,flexWrap:"wrap",marginBottom:28,justifyContent:"center"}}>{TOP8.map(p=><button key={p.id} className="tap2" onClick={()=>{setPersonaId(p.id);sv("sakura-persona",p.id);}} style={{padding:"5px 10px",borderRadius:10,border:`1.5px solid ${personaId===p.id?p.c+"50":C.bdL}`,background:personaId===p.id?`${p.c}10`:"transparent",color:personaId===p.id?p.c:C.t3,fontSize:11,fontWeight:personaId===p.id?700:500,cursor:"pointer"}}>{p.icon} {p.l}</button>)}</div><div style={{fontSize:13,fontWeight:700,color:"#4a2838",marginBottom:8,alignSelf:"flex-start",marginTop:8}}>首页模式（可随时在「我的」切换）</div><div style={{display:"flex",gap:8,marginBottom:24,width:"100%"}}><button className="tap2" onClick={()=>{setEntryMode("results");sv("sakura-entry-mode","results");}} style={{flex:1,padding:"12px 10px",borderRadius:12,border:`2px solid ${entryMode==="results"?"#E84D8C":"#ffd2dc"}`,background:entryMode==="results"?"#ffe6ec":"transparent",cursor:"pointer",textAlign:"center"}}><div style={{fontSize:20,marginBottom:4}}>🌸</div><div style={{fontSize:11,fontWeight:700,color:entryMode==="results"?"#c9306b":"#7e4c5c"}}>任务型（新）</div><div style={{fontSize:9,color:"#a07080",marginTop:2}}>按目标找功能</div></button><button className="tap2" onClick={()=>{setEntryMode("classic");sv("sakura-entry-mode","classic");}} style={{flex:1,padding:"12px 10px",borderRadius:12,border:`2px solid ${entryMode==="classic"?"#E84D8C":"#ffd2dc"}`,background:entryMode==="classic"?"#ffe6ec":"transparent",cursor:"pointer",textAlign:"center"}}><div style={{fontSize:20,marginBottom:4}}>📋</div><div style={{fontSize:11,fontWeight:700,color:entryMode==="classic"?"#c9306b":"#7e4c5c"}}>经典 Tab</div><div style={{fontSize:9,color:"#a07080",marginTop:2}}>6 个功能 Tab</div></button></div><Btn primary onClick={()=>{setOnboarded(true);sv("sakura-onboarded","true");if(!["results","classic"].includes(entryMode))sv("sakura-entry-mode","classic");}}>🌸 开始使用</Btn></div></div>;return <div style={{maxWidth:430,margin:"0 auto",minHeight:"100vh",background:C.bg,color:C.t1,fontFamily:font,fontSize:fontSize,position:"relative",overflow:"hidden"}}><style>{CSS+`\n:root{--fs:${fontSize}px} .fs{font-size:var(--fs)!important} textarea,.fs-area{font-size:var(--fs)!important}`}</style><Petals/><Toast m={toast}/><div style={{padding:"8px 14px",display:"flex",alignItems:"center",justifyContent:"space-between",background:C.glass,backdropFilter:"blur(20px)",borderBottom:`1px solid ${C.bdL}`,position:"sticky",top:0,zIndex:100}}><div style={{display:"flex",alignItems:"center",gap:5}}><span style={{fontSize:16,animation:"breathe 3s infinite"}}>🌸</span><span style={{fontSize:14,fontWeight:800,background:`linear-gradient(135deg,${C.pink},${C.gold})`,WebkitBackgroundClip:"text",WebkitTextFillColor:"transparent"}}>Sakura</span></div><div style={{display:"flex",gap:4,alignItems:"center"}}>{vip?<span style={{padding:"2px 8px",borderRadius:8,background:`linear-gradient(135deg,${C.pink},${C.gold})`,color:"#fff",fontSize:9,fontWeight:700}}>PRO</span>:<button className="tap2" onClick={()=>setShowPay(true)} style={{padding:"2px 8px",borderRadius:8,background:`${C.pink}10`,border:`1px solid ${C.pink}25`,color:C.pink,fontSize:9,fontWeight:700,cursor:"pointer"}}>升级Pro</button>}<button className="tap2" onClick={()=>setShowSettings(true)} style={{width:28,height:28,borderRadius:10,background:C.bg,border:`1px solid ${C.bd}`,color:C.t3,fontSize:13,cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center"}}>⚙️</button></div></div>{/* SOS Emergency Box */}<div style={{padding:"6px 14px",background:`linear-gradient(135deg,${C.pink}06,${C.coral}04)`,borderBottom:`1px solid ${C.bdL}`}}><div style={{display:"flex",gap:6}}><input value={sosInp} onChange={e=>setSosInp(e.target.value)} onKeyDown={e=>e.key==="Enter"&&doSos()} placeholder="🚨 救急：粘贴TA的话，秒出回复" style={{flex:1,padding:"8px 12px",borderRadius:12,border:`1.5px solid ${sosInp?C.pink+"40":C.bdL}`,background:C.white,fontSize:12,color:C.t1,outline:"none",fontFamily:font}}/><button className="tap" onClick={doSos} disabled={!sosInp.trim()||sosLd} style={{padding:"8px 14px",borderRadius:12,background:sosInp.trim()&&!sosLd?`linear-gradient(135deg,${C.pink},${C.coral})`:`${C.bg3}`,border:"none",color:sosInp.trim()&&!sosLd?"#fff":C.t3,fontSize:11,fontWeight:700,cursor:"pointer",whiteSpace:"nowrap"}}>{sosLd?"...":"🚨 救急"}</button></div>{sosRes&&<div style={{marginTop:6,padding:"8px 12px",borderRadius:10,background:C.white,border:`1px solid ${C.sakuraL}`,animation:"fadeUp .2s"}}><div style={{display:"flex",justifyContent:"space-between",alignItems:"center",gap:6}}><div style={{fontSize:13,fontWeight:700,color:C.t1,flex:1}}>{sosRes.reply}</div><CB text={sosRes.reply} st={st}/></div><div style={{fontSize:9,color:C.t3,marginTop:3}}>💡 {sosRes.why} · <span style={{color:sosRes.risk==="high"?C.danger:C.safe}}>{sosRes.risk==="high"?"⚠️高风险":"✅安全"}</span></div>{sosRes.alt&&<div style={{fontSize:10,color:C.t2,marginTop:2}}>备选：{sosRes.alt}</div>}</div>}</div>{/* Settings Modal */}{showPay&&<Paywall onClose={()=>setShowPay(false)} st={st} onPurchase={()=>setVip(true)}/>}{showSettings&&<div style={{position:"fixed",inset:0,zIndex:200,display:"flex",flexDirection:"column",justifyContent:"stretch"}}><div style={{background:C.white,borderRadius:0,padding:"20px 20px 40px",height:"100vh",overflowY:"auto",animation:"fadeUp .25s"}}><div style={{display:"flex",justifyContent:"space-between",marginBottom:16}}><span style={{fontSize:16,fontWeight:800}}>⚙️ 设置</span><button onClick={()=>setShowSettings(false)} style={{background:"none",border:"none",fontSize:18,cursor:"pointer",color:C.t3}}>✕</button></div><div style={{marginBottom:16}}><div style={{fontSize:12,fontWeight:700,color:C.t1,marginBottom:8}}>💕 TA的头像</div><div style={{display:"flex",alignItems:"center",gap:12}}><div style={{width:56,height:56,borderRadius:28,background:taAvatar?`url(${taAvatar}) center/cover`:`linear-gradient(135deg,${C.sakura}30,${C.pink}20)`,display:"flex",alignItems:"center",justifyContent:"center",fontSize:taAvatar?0:24,border:`2px solid ${C.sakuraL}`,flexShrink:0,overflow:"hidden"}}>{!taAvatar&&"💕"}{taAvatar&&<img src={taAvatar} style={{width:"100%",height:"100%",objectFit:"cover"}}/>}</div><div style={{flex:1}}><input type="file" accept="image/*" id="taAva" style={{display:"none"}} onChange={e=>{const f=e.target.files?.[0];if(!f)return;const r=new FileReader();r.onload=()=>{setTaAvatar(r.result);sv("sakura-taavatar",r.result);try{const shown=globalThis.__sakuraTaPhotoGuide;if(!shown){globalThis.__sakuraTaPhotoGuide=true;setTimeout(()=>{st("📸 照片已保存 · 去「读心术」或「爱之语雷达」测 TA 的性格,会更准哦");},300);}}catch{}};r.readAsDataURL(f);}}/><button className="tap" onClick={()=>document.getElementById("taAva")?.click()} style={{padding:"8px 16px",borderRadius:10,background:C.pinkBg,border:`1px solid ${C.sakura}`,color:C.pink,fontSize:11,fontWeight:600,cursor:"pointer"}}>{taAvatar?"更换头像":"上传TA的照片"}</button>{taAvatar&&<button className="tap2" onClick={()=>{setTaAvatar(null);sv("sakura-taavatar","");}}style={{marginLeft:8,padding:"6px 10px",borderRadius:8,background:C.bg,border:`1px solid ${C.bd}`,color:C.t3,fontSize:10,cursor:"pointer"}}>移除</button>}</div></div></div><div style={{marginBottom:16}}><div style={{fontSize:12,fontWeight:700,color:C.t1,marginBottom:8}}>🛡️ PUA 智能检测</div><div style={{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"10px 12px",borderRadius:10,background:C.bg}}><div style={{flex:1}}><div style={{fontSize:11,fontWeight:600,color:C.t1}}>自动扫描 PUA 话术</div><div style={{fontSize:9,color:C.t3,marginTop:2,lineHeight:1.5}}>在秒回输入框自动识别对方 PUA 措辞,零延迟纯本地</div></div><button className="tap2" onClick={()=>setPuaScanOn(!puaScanOn)} style={{width:44,height:24,borderRadius:12,border:"none",background:puaScanOn?"linear-gradient(135deg,#E84D8C,#F97316)":"#ddd",cursor:"pointer",position:"relative",transition:"all .2s"}}><div style={{position:"absolute",top:2,left:puaScanOn?22:2,width:20,height:20,borderRadius:10,background:"#fff",transition:"left .2s",boxShadow:"0 1px 3px rgba(0,0,0,.3)"}}/></button></div></div><div style={{marginBottom:16}}><div style={{fontSize:12,fontWeight:700,color:C.t1,marginBottom:8}}>🔤 字体大小</div><div style={{display:"flex",alignItems:"center",gap:10}}><span style={{fontSize:11,color:C.t3}}>小</span><input type="range" min={12} max={18} step={2} value={fontSize} onChange={e=>{setFontSize(+e.target.value);sv("sakura-fontsize",String(e.target.value));}}style={{flex:1,background:`linear-gradient(90deg,${C.pink}40,${C.pink})`}}/><span style={{fontSize:11,color:C.t3}}>大</span><span style={{fontSize:12,fontWeight:700,color:C.pink,width:24,textAlign:"center"}}>{fontSize}</span></div><div style={{fontSize:fontSize,color:C.t2,marginTop:6,padding:8,background:C.bg,borderRadius:8}}>预览：你好呀，今天开心吗？</div></div><Btn onClick={()=>{setShowSettings(false);setTab("me");}}>👤 前往「我的」编辑档案</Btn></div></div>}<div style={{position:"relative",zIndex:1}}><DailyPush st={st}/>{tab==="flash"&&(entryMode==="results"&&!taskFilter?<div style={{padding:"20px 14px 100px"}}><div style={{textAlign:"center",marginBottom:20}}><div style={{fontSize:22,fontWeight:900,background:"linear-gradient(135deg,#c9306b,#cc8b2d)",WebkitBackgroundClip:"text",WebkitTextFillColor:"transparent",marginBottom:6}}>你今天需要什么？</div><div style={{fontSize:11,color:"#a07080"}}>选一个目标,Sakura 帮你搞定</div></div>{[{id:"pursue-female",icon:"💘",title:"追女生",desc:"开场/夸人/升温/告白",color:"#E84D8C",bg:"#ffe6ec"},{id:"pursue-male",icon:"💕",title:"追男生",desc:"主动/升温/试探/告白",color:"#F472B6",bg:"#fff0f7"},{id:"maintain",icon:"💑",title:"维护关系",desc:"爱之语/纪念日/日常",color:"#EC4899",bg:"#ffeef6"},{id:"repair",icon:"🔧",title:"修复关系",desc:"冷战/挽回/哄人",color:"#0EA5E9",bg:"#e0f2fe"},{id:"sos",icon:"🚨",title:"救急一下",desc:"就这条消息",color:"#F97316",bg:"#ffedd5"}].map(task=><button key={task.id} className="tap2" onClick={()=>setTaskFilter(task.id)} style={{width:"100%",padding:"16px 18px",marginBottom:10,borderRadius:16,border:`2px solid ${task.color}20`,background:task.bg,cursor:"pointer",textAlign:"left",display:"flex",alignItems:"center",gap:14}}><div style={{fontSize:32}}>{task.icon}</div><div style={{flex:1}}><div style={{fontSize:16,fontWeight:800,color:task.color,marginBottom:3}}>{task.title}</div><div style={{fontSize:11,color:"#7e4c5c"}}>{task.desc}</div></div><div style={{fontSize:18,color:task.color,opacity:.5}}>{">"}</div></button>)}<div style={{textAlign:"center",marginTop:20,padding:"12px",fontSize:10,color:"#a07080"}}>或者 <span style={{color:"#c9306b",fontWeight:600,cursor:"pointer",textDecoration:"underline"}} onClick={()=>{setEntryMode("classic");sv("sakura-entry-mode","classic");}}>切换到经典 6 Tab</span></div></div>:entryMode==="results"&&taskFilter==="sos"?<div style={{paddingBottom:100}}><div style={{padding:"14px 14px 4px"}}><button className="tap2" onClick={()=>setTaskFilter(null)} style={{background:"none",border:"none",color:"#c9306b",fontSize:13,fontWeight:700,cursor:"pointer",marginBottom:8,padding:0}}>← 回到首页</button><div style={{fontSize:20,fontWeight:900,color:"#F97316",marginBottom:4}}>🚨 救急一下</div><div style={{fontSize:11,color:"#a07080",marginBottom:8}}>把 TA 的消息粘贴进去,立刻给你回复</div></div><FlashTab stageId={stageId} personaId={personaId} learn={learn} setPersonaId={p=>{setPersonaId(p);sv("sakura-persona",p);}} profile={profile} st={st} addVault={addVault} vault={vault} vip={vip} setShowPay={setShowPay} onNavigateGame={(gid)=>{try{globalThis.__sakuraPendingGame=gid;}catch{}setTab("coach");}}/></div>:entryMode==="results"&&taskFilter==="pursue-female"?<div style={{paddingBottom:100}}><div style={{padding:"14px 14px 4px"}}><button className="tap2" onClick={()=>setTaskFilter(null)} style={{background:"none",border:"none",color:"#c9306b",fontSize:13,fontWeight:700,cursor:"pointer",marginBottom:8,padding:0}}>← 回到首页</button><div style={{fontSize:20,fontWeight:900,color:"#E84D8C",marginBottom:4}}>💘 追女生</div><div style={{fontSize:11,color:"#a07080",marginBottom:8}}>粘贴她的消息,AI 生成 5 档回复</div></div><FlashTab stageId={stageId} personaId={personaId} learn={learn} setPersonaId={p=>{setPersonaId(p);sv("sakura-persona",p);}} profile={profile} st={st} addVault={addVault} vault={vault} vip={vip} setShowPay={setShowPay}/><div style={{padding:"20px 14px 0"}}><div style={{fontSize:12,fontWeight:700,color:"#c9306b",marginBottom:8}}>── 或者用这些辅助工具 ──</div><div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}>{VIRAL_GAMES.filter(g=>["opener","praise","soft","waitprob","pace","mirror","confess"].includes(g.id)).map(g=><button key={g.id} className="tap2" onClick={()=>{setView("game");setGameId(g.id);setGameInp("");setGameRes(null);}} style={{padding:"10px 8px",borderRadius:12,border:`1px solid ${g.c||"#E84D8C"}30`,background:"#fff",cursor:"pointer",textAlign:"left"}}><div style={{fontSize:18,marginBottom:3}}>{g.icon}</div><div style={{fontSize:11,fontWeight:700,color:"#4a2838"}}>{g.n||g.l}</div><div style={{fontSize:9,color:"#a07080",marginTop:2}}>{g.d}</div></button>)}</div></div></div>:entryMode==="results"&&taskFilter?<div style={{padding:"14px 14px 100px"}}><button className="tap2" onClick={()=>setTaskFilter(null)} style={{background:"none",border:"none",color:"#c9306b",fontSize:13,fontWeight:700,cursor:"pointer",marginBottom:14,padding:0}}>← 回到首页</button>{(()=>{const TASK_CONFIG={"pursue-male":{title:"💕 追男生",color:"#F472B6",primary:"evidence",primary_label:"🔮 他真的喜欢我吗",primary_desc:"输入他最近的具体行为,AI 给基于事实的判断",features:["ask_out","heat_up","test_him","initiate","confess","decode"]},"maintain":{title:"💑 维护关系",color:"#EC4899",primary:"daily",primary_label:"📅 今日挑战",primary_desc:"今天为 TA 做的一件事 - 小行动,大差别",features:["lovelang","anniv","long_dist"]},"repair":{title:"🔧 修复关系",color:"#0EA5E9",primary:"breakice",primary_label:"❄️ 冷战破冰",primary_desc:"Gottman 软启动 - 吵架后第一句话决定能否和好",features:["reconcile","damage","comm"]}};const cfg=TASK_CONFIG[taskFilter];if(!cfg)return null;const primaryFeat=VIRAL_GAMES.find(g=>g.id===cfg.primary);const secondaryFeats=VIRAL_GAMES.filter(g=>cfg.features.includes(g.id));return <><div style={{fontSize:20,fontWeight:900,color:cfg.color,marginBottom:6}}>{cfg.title}</div><div style={{fontSize:11,color:"#a07080",marginBottom:16}}>这个场景最多人用的是 ↓</div><button className="tap2" onClick={()=>{setView("game");setGameId(cfg.primary);setGameInp("");setGameRes(null);}} style={{width:"100%",padding:"18px 20px",marginBottom:16,borderRadius:16,border:`2.5px solid ${cfg.color}`,background:`${cfg.color}08`,cursor:"pointer",textAlign:"left",display:"flex",alignItems:"center",gap:14}}><div style={{fontSize:36}}>{primaryFeat?.icon||"⭐"}</div><div style={{flex:1}}><div style={{fontSize:15,fontWeight:800,color:cfg.color,marginBottom:3}}>{cfg.primary_label}</div><div style={{fontSize:11,color:"#4a2838",lineHeight:1.5}}>{cfg.primary_desc}</div></div><div style={{fontSize:24,color:cfg.color}}>{">"}</div></button><div style={{fontSize:11,fontWeight:700,color:"#7e4c5c",marginBottom:8,marginTop:8}}>── 其他工具 ──</div><div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>{secondaryFeats.map(g=><button key={g.id} className="tap2" onClick={()=>{setView("game");setGameId(g.id);setGameInp("");setGameRes(null);}} style={{padding:"14px 10px",borderRadius:14,border:`1.5px solid ${g.c||cfg.color}30`,background:"#fff",cursor:"pointer",textAlign:"left"}}><div style={{fontSize:22,marginBottom:6}}>{g.icon}</div><div style={{fontSize:12,fontWeight:700,color:"#4a2838",marginBottom:3}}>{g.n||g.l}</div><div style={{fontSize:10,color:"#a07080",lineHeight:1.4}}>{g.d}</div></button>)}</div></>;})()}</div>:<FlashTab stageId={stageId} personaId={personaId} learn={learn} setPersonaId={p=>{setPersonaId(p);sv("sakura-persona",p);}} profile={profile} st={st} addVault={addVault} vault={vault} vip={vip} setShowPay={setShowPay}/>)}{tab==="ai"&&<AITab stageId={stageId} setStageId={s=>{setStageId(s);sv("sakura-stage",s);}} personaId={personaId} profile={profile} st={st} onNavigateGame={(gid)=>{try{globalThis.__sakuraPendingGame=gid;}catch{}setTab("coach");}}/>}{tab==="deep"&&<DeepTab stageId={stageId} personaId={personaId} profile={profile} st={st} vault={vault} onNavigateGame={(gid)=>{try{globalThis.__sakuraPendingGame=gid;}catch{}setTab("coach");}}/>}{tab==="coach"&&!coachIntroShown&&<CoachIntroDialog onClose={()=>setCoachIntroShown(true)}/>}{tab==="coach"&&<CoachTab stageId={stageId} personaId={personaId} profile={profile} st={st}/>}{tab==="skill"&&<SkillTab st={st}/>}{tab==="me"&&<div style={{padding:"14px 14px 100px"}}><div style={{marginBottom:14,padding:"10px 12px",borderRadius:12,background:`${C.pink}08`,border:`1px solid ${C.pink}15`}}><div style={{fontSize:11,fontWeight:700,color:C.pinkD,marginBottom:6}}>🌸 首页模式（Beta）</div><div style={{display:"flex",gap:6}}><button className="tap2" onClick={()=>{setEntryMode("results");setTaskFilter(null);sv("sakura-entry-mode","results");setTab("flash");st("已切换到任务型首页");}} style={{flex:1,padding:"8px 6px",borderRadius:10,border:`2px solid ${entryMode==="results"?C.pink:C.bdL}`,background:entryMode==="results"?`${C.pink}10`:"transparent",cursor:"pointer",textAlign:"center"}}><div style={{fontSize:16,marginBottom:2}}>🌸</div><div style={{fontSize:10,fontWeight:700,color:entryMode==="results"?C.pinkD:C.t2}}>任务型首页</div><div style={{fontSize:8,color:C.t3,marginTop:1}}>追女/追男/维护/修复/救急</div></button><button className="tap2" onClick={()=>{setEntryMode("classic");setTaskFilter(null);sv("sakura-entry-mode","classic");st("已切换到经典首页");}} style={{flex:1,padding:"8px 6px",borderRadius:10,border:`2px solid ${entryMode==="classic"?C.pink:C.bdL}`,background:entryMode==="classic"?`${C.pink}10`:"transparent",cursor:"pointer",textAlign:"center"}}><div style={{fontSize:16,marginBottom:2}}>📋</div><div style={{fontSize:10,fontWeight:700,color:entryMode==="classic"?C.pinkD:C.t2}}>经典 6 Tab</div><div style={{fontSize:8,color:C.t3,marginTop:1}}>秒回/思考/解析/教练/技能/我</div></button></div></div><MeTab stageId={stageId} learn={learn} setStageId={s=>{setStageId(s);sv("sakura-stage",s);}} personaId={personaId} setPersonaId={p=>{setPersonaId(p);sv("sakura-persona",p);}} profile={profile} setProfile={setProfile} st={st} vault={vault} delVault={delVault} diary={diary} setDiary={setDiary} svDiary={n=>{setDiary(n);sv("sakura-diary",n);}} anniversaries={anniversaries} setAnniversaries={setAnniversaries} svAnniv={n=>{setAnniversaries(n);sv("sakura-anniversaries",n);}}myStyle={myStyle} setMyStyle={s=>{setMyStyle(s);sv("sakura-style",s);}}/></div>}</div><div style={{position:"fixed",bottom:0,left:"50%",transform:"translateX(-50%)",width:"100%",maxWidth:430,padding:"4px 2px 20px",background:C.glass,backdropFilter:"blur(24px)",borderTop:`1px solid ${C.bdL}`,zIndex:100}}><div style={{display:"flex",justifyContent:"space-around"}}>{TABS.map(t=><button key={t.id} className="tap2" onClick={()=>setTab(t.id)} style={{background:"none",border:"none",cursor:"pointer",textAlign:"center",padding:"2px 6px",minWidth:0}}><div style={{fontSize:16,marginBottom:0,opacity:tab===t.id?1:.35}}>{t.icon}</div><div style={{fontSize:9,fontWeight:tab===t.id?700:500,color:tab===t.id?C.pink:C.t3}}>{t.l}</div></button>)}</div></div></div>;}


(function mountSakura(){
  const el = document.getElementById("root");
  if (!el) return;
  if (ReactDOM && typeof ReactDOM.createRoot === "function") {
    ReactDOM.createRoot(el).render(React.createElement(App));
    return;
  }
  if (ReactDOM && typeof ReactDOM.render === "function") {
    ReactDOM.render(React.createElement(App), el);
  }
})();
