暮らし

import { useState, useEffect, useRef, useCallback } from "react";

// ═══ 占星術データ ═══
const SIGNS = ['牡羊座','牡牛座','双子座','蟹座','獅子座','乙女座','天秤座','蠍座','射手座','山羊座','水瓶座','魚座'];
const SSYM  = ['♈','♉','♊','♋','♌','♍','♎','♏','♐','♑','♒','♓'];
const PSYM  = {Sun:'☉',Moon:'☽',Mercury:'☿',Venus:'♀',Mars:'♂',Jupiter:'♃',Saturn:'♄',Uranus:'♅',Neptune:'♆',Pluto:'♇'};
const PJP   = {Sun:'太陽',Moon:'月',Mercury:'水星',Venus:'金星',Mars:'火星',Jupiter:'木星',Saturn:'土星',Uranus:'天王星',Neptune:'海王星',Pluto:'冥王星'};
const PCOL  = {Sun:'#c89840',Moon:'#7090c0',Mercury:'#40a890',Venus:'#d07890',Mars:'#d06050',Jupiter:'#c09050',Saturn:'#8090b0',Uranus:'#50b8c0',Neptune:'#6870d8',Pluto:'#a060b8'};
const PACC  = {Sun:'linear-gradient(90deg,#c89840,#e8c070)',Moon:'linear-gradient(90deg,#7090c0,#a0b8e0)',Mercury:'linear-gradient(90deg,#40a890,#70d0b0)',Venus:'linear-gradient(90deg,#d07890,#f0a8b8)',Mars:'linear-gradient(90deg,#d06050,#f08070)',Jupiter:'linear-gradient(90deg,#c09050,#e0b870)',Saturn:'linear-gradient(90deg,#8090b0,#a8b8d0)',Uranus:'linear-gradient(90deg,#50b8c0,#80d8e0)',Neptune:'linear-gradient(90deg,#6870d8,#9090f0)',Pluto:'linear-gradient(90deg,#a060b8,#c888d8)'};
const FORTUNE_COLORS = [
  {bar:'linear-gradient(90deg,#c8a87a,#a8885a)', dot:'#c8a87a'},
  {bar:'linear-gradient(90deg,#7aa4d4,#4a6fa5)', dot:'#4a6fa5'},
  {bar:'linear-gradient(90deg,#e09aaa,#c86478)', dot:'#c86478'},
  {bar:'linear-gradient(90deg,#7abd8a,#4a8c5c)', dot:'#4a8c5c'},
];

// ═══ 天文計算 ═══
function toJD(y,m,d,h,mn){ if(m<=2){y--;m+=12;} const A=Math.floor(y/100),B=2-A+Math.floor(A/4); return Math.floor(365.25*(y+4716))+Math.floor(30.6001*(m+1))+d+B-1524.5+(h+mn/60)/24; }
function calcDeg(jd,p){ const T=(jd-2451545)/36525; const base={Sun:280.46646+36000.76983*T,Moon:218.3165+481267.8813*T,Mercury:252.2509+149472.6746*T,Venus:181.9798+58517.8157*T,Mars:355.4330+19140.2993*T,Jupiter:34.3515+3034.9057*T,Saturn:50.0775+1221.8760*T,Uranus:314.0550+428.4748*T,Neptune:304.3487+218.4071*T,Pluto:238.9260+145.2078*T}; return((base[p]||0)%360+360)%360; }
function dts(deg){ const i=Math.floor(((deg%360)+360)%360/30); return{idx:i,within:(((deg%360)+360)%360%30).toFixed(1),sign:SIGNS[i],sym:SSYM[i]}; }
function buildPos(y,m,d,hh,mn){
  const jd=toJD(y,m,d,hh||12,mn||0);
  const PL=['Sun','Moon','Mercury','Venus','Mars','Jupiter','Saturn','Uranus','Neptune','Pluto'];
  const pos={}; PL.forEach(p=>pos[p]=calcDeg(jd,p));
  pos.Ascendant=((pos.Sun+90+(hh-6)*15)%360+360)%360;
  return pos;
}

// ═══ Claude API ═══
async function callClaude(prompt) {
  const res = await fetch("https://api.anthropic.com/v1/messages", {
    method:"POST", headers:{"Content-Type":"application/json"},
    body: JSON.stringify({ model:"claude-sonnet-4-20250514", max_tokens:1800,
      messages:[{role:"user", content:prompt}] })
  });
  const data = await res.json();
  if(data.error) throw new Error(data.error.message);
  const text = data.content?.map(c=>c.text||"").join("")||"";
  const m = text.match(/\{[\s\S]*\}/);
  if(!m) throw new Error("レスポンスの解析に失敗しました");
  return JSON.parse(m[0]);
}

// ═══ ホイールキャンバス ═══
function ChartCanvas({ profile }) {
  const ref = useRef(null);
  useEffect(()=>{
    if(!ref.current||!profile)return;
    const cv=ref.current, ctx=cv.getContext("2d");
    const W=360,CX=W/2,CY=W/2,R=155,BD="#e8e4de";
    ctx.clearRect(0,0,W,W);
    // 外周
    ctx.beginPath(); ctx.arc(CX,CY,R,0,Math.PI*2); ctx.fillStyle="#fafaf8"; ctx.fill(); ctx.strokeStyle=BD; ctx.lineWidth=1; ctx.stroke();
    // 12星座帯
    for(let i=0;i<12;i++){
      const a1=(i*30-90)*Math.PI/180, a2=((i+1)*30-90)*Math.PI/180;
      ctx.beginPath(); ctx.moveTo(CX+Math.cos(a1)*R*.67,CY+Math.sin(a1)*R*.67);
      ctx.arc(CX,CY,R*.67,a1,a2); ctx.arc(CX,CY,R,a2,a1,true); ctx.closePath();
      ctx.fillStyle=`hsla(${i*30},28%,97%,.9)`; ctx.fill(); ctx.strokeStyle=BD; ctx.lineWidth=.7; ctx.stroke();
      const am=(i*30+15-90)*Math.PI/180;
      ctx.fillStyle="#9a9288"; ctx.font="11px serif"; ctx.textAlign="center"; ctx.textBaseline="middle";
      ctx.fillText(SSYM[i], CX+Math.cos(am)*R*.84, CY+Math.sin(am)*R*.84);
    }
    // ハウス線
    for(let i=0;i<12;i++){
      const a=(i*30-90)*Math.PI/180;
      ctx.beginPath(); ctx.moveTo(CX+Math.cos(a)*R*.43,CY+Math.sin(a)*R*.43); ctx.lineTo(CX+Math.cos(a)*R*.67,CY+Math.sin(a)*R*.67);
      ctx.strokeStyle=BD; ctx.lineWidth=.7; ctx.stroke();
    }
    // 内円
    ctx.beginPath(); ctx.arc(CX,CY,R*.43,0,Math.PI*2); ctx.fillStyle="#fff"; ctx.fill(); ctx.strokeStyle=BD; ctx.lineWidth=1; ctx.stroke();
    // 惑星
    const PL=["Sun","Moon","Mercury","Venus","Mars","Jupiter","Saturn","Uranus","Neptune","Pluto"], pp=[];
    PL.forEach(p=>{
      const deg=profile.pos[p], ang=(deg-90)*Math.PI/180, pr=R*.55;
      const px=CX+Math.cos(ang)*pr, py=CY+Math.sin(ang)*pr;
      pp.push({p,px,py,deg});
      ctx.beginPath(); ctx.arc(px,py,4,0,Math.PI*2); ctx.fillStyle=PCOL[p]; ctx.fill();
      ctx.fillStyle=PCOL[p]; ctx.font="bold 10px serif"; ctx.textAlign="center"; ctx.textBaseline="middle";
      ctx.fillText(PSYM[p], px, py-11);
    });
    // アスペクト線
    const ASPS=[{d:0,c:"rgba(200,168,122,.55)",w:1.5},{d:120,c:"rgba(74,140,92,.4)",w:1},{d:60,c:"rgba(74,111,165,.3)",w:.8},{d:90,c:"rgba(200,100,100,.3)",w:.8},{d:180,c:"rgba(160,120,60,.28)",w:.8}];
    for(let i=0;i<pp.length;i++) for(let j=i+1;j<pp.length;j++){
      let df=Math.abs(pp[i].deg-pp[j].deg); if(df>180)df=360-df;
      for(const a of ASPS){ if(Math.abs(df-a.d)<7){ ctx.beginPath(); ctx.moveTo(pp[i].px,pp[i].py); ctx.lineTo(pp[j].px,pp[j].py); ctx.strokeStyle=a.c; ctx.lineWidth=a.w; ctx.stroke(); break; }}
    }
    // ASC線
    const aa=(profile.pos.Ascendant-90)*Math.PI/180;
    ctx.beginPath(); ctx.moveTo(CX-Math.cos(aa)*R*.67,CY-Math.sin(aa)*R*.67); ctx.lineTo(CX+Math.cos(aa)*R*.67,CY+Math.sin(aa)*R*.67);
    ctx.strokeStyle="rgba(74,111,165,.5)"; ctx.lineWidth=1.3; ctx.setLineDash([4,3]); ctx.stroke(); ctx.setLineDash([]);
    // 中央名前
    ctx.fillStyle="#9a9288"; ctx.font="10px sans-serif"; ctx.textAlign="center"; ctx.textBaseline="middle";
    ctx.fillText(profile.name, CX, CY);
  }, [profile]);
  return <canvas ref={ref} width={360} height={360} style={{maxWidth:"100%",display:"block"}} />;
}

// ═══ 星座タグ(クリック可能) ═══
function SignTag({ planet, pos, onOpen }) {
  const s = dts(pos[planet]);
  return (
    <button onClick={()=>onOpen(planet, s.sign, s.sym)}
      style={{fontSize:".76rem",padding:"3px 9px",borderRadius:20,background:"rgba(200,168,122,.12)",color:"#a8885a",border:"1px solid rgba(200,168,122,.4)",cursor:"pointer",fontWeight:500,transition:"all .15s",whiteSpace:"nowrap"}}
      onMouseEnter={e=>{e.currentTarget.style.background="rgba(200,168,122,.28)";e.currentTarget.style.transform="scale(1.06)";}}
      onMouseLeave={e=>{e.currentTarget.style.background="rgba(200,168,122,.12)";e.currentTarget.style.transform="scale(1)";}}
      title="クリックで詳細表示"
    >{s.sym} {s.sign}</button>
  );
}

// ═══ 星座ポップアップ ═══
function SignPopup({ planet, signName, signSym, onClose }) {
  const [data, setData] = useState(null);
  const [err,  setErr]  = useState(null);
  useEffect(()=>{
    setData(null); setErr(null);
    callClaude(
      `西洋占星術において、${PJP[planet]}が${signName}にある人の特徴を日本語で教えてください。\n` +
      `JSONのみで返してください(説明・コードブロック不要):\n` +
      `{"element":"火","quality":"活動宮","ruler":"火星","keywords":["情熱的","行動力","直感","リーダーシップ","短気"],"personality":"性格の特徴(100〜130字)","strength":"強み(60〜80字)","weakness":"弱み・課題(60〜80字)","advice":"アドバイス(60〜80字)"}`
    ).then(setData).catch(e=>setErr(e.message));
  }, [planet, signName]);

  return (
    <div onClick={e=>e.target===e.currentTarget&&onClose()} style={{position:"fixed",inset:0,zIndex:9999,background:"rgba(26,24,20,.42)",backdropFilter:"blur(3px)",display:"flex",alignItems:"center",justifyContent:"center",padding:20}}>
      <div style={{background:"#fff",borderRadius:20,maxWidth:480,width:"100%",boxShadow:"0 24px 80px rgba(26,24,20,.22)",overflow:"hidden"}}>
        {/* ヘッダー */}
        <div style={{position:"relative",padding:"26px 26px 18px",borderBottom:"1px solid #ede9e2"}}>
          <div style={{position:"absolute",top:0,left:0,right:0,height:3,background:PACC[planet]||"#c8a87a"}} />
          <div style={{fontSize:".7rem",letterSpacing:".18em",textTransform:"uppercase",color:"#9a9288",marginBottom:5}}>{PJP[planet]}星座</div>
          <div style={{display:"flex",alignItems:"center",gap:12}}>
            <span style={{fontSize:"2rem"}}>{signSym}</span>
            <div>
              <div style={{fontFamily:"Georgia,serif",fontSize:"1.5rem",color:"#1a1814"}}>{signName}</div>
              <div style={{fontSize:".82rem",color:"#9a9288",marginTop:3}}>の特徴</div>
            </div>
          </div>
          <button onClick={onClose} style={{position:"absolute",top:14,right:14,width:28,height:28,borderRadius:"50%",background:"#f2f0ed",border:"none",cursor:"pointer",color:"#9a9288",fontSize:".9rem"}}>✕</button>
        </div>
        {/* ボディ */}
        <div style={{padding:"20px 26px 26px",maxHeight:"68vh",overflowY:"auto"}}>
          {!data&&!err&&<div style={{textAlign:"center",padding:"30px 0"}}><div style={{width:32,height:32,margin:"0 auto 12px",border:"2px solid #e8e4de",borderTopColor:"#c8a87a",borderRadius:"50%",animation:"spin 1s linear infinite"}} /><div style={{fontSize:".85rem",color:"#9a9288"}}>読み込んでいます…</div></div>}
          {err&&<div style={{color:"#a04040",fontSize:".85rem",padding:"16px 0"}}>取得に失敗しました:{err}</div>}
          {data&&<>
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:9,marginBottom:13}}>
              {[["エレメント",data.element],["クオリティ",data.quality],["支配星",data.ruler],["キーワード",(data.keywords||[]).slice(0,3).join(" · ")]].map(([l,v])=>(
                <div key={l} style={{background:"#f8f7f5",borderRadius:9,padding:"10px 13px",border:"1px solid #ede9e2"}}>
                  <div style={{fontSize:".66rem",letterSpacing:".12em",textTransform:"uppercase",color:"#9a9288",marginBottom:3}}>{l}</div>
                  <div style={{fontSize:".87rem",color:"#1a1814"}}>{v||"—"}</div>
                </div>
              ))}
            </div>
            <div style={{display:"flex",flexWrap:"wrap",gap:5,marginBottom:14}}>
              {(data.keywords||[]).map(k=><span key={k} style={{fontSize:".75rem",padding:"3px 9px",borderRadius:20,background:"rgba(200,168,122,.12)",color:"#a8885a",border:"1px solid rgba(200,168,122,.4)"}}>{k}</span>)}
            </div>
            {[["性格の特徴",data.personality],["強み",data.strength],["弱み・課題",data.weakness],["アドバイス",data.advice]].map(([l,v])=>(
              <div key={l} style={{marginBottom:13}}>
                <div style={{fontSize:".71rem",letterSpacing:".13em",textTransform:"uppercase",color:"#9a9288",marginBottom:5,display:"flex",alignItems:"center",gap:8}}>
                  {l}<span style={{flex:1,height:1,background:"#e8e4de",display:"block"}} />
                </div>
                <div style={{fontSize:".875rem",color:"#4a463e",lineHeight:1.85,fontWeight:300}}>{v}</div>
              </div>
            ))}
          </>}
        </div>
      </div>
    </div>
  );
}

// ═══ チャートパネル(本質・性格分析付き) ═══
function ChartPanel({ profile, onOpenPopup }) {
  const [essence, setEssence] = useState(null);
  const [essLoading, setEssLoading] = useState(false);
  const [essErr, setEssErr] = useState(null);

  useEffect(()=>{
    if(!profile) return;
    setEssence(null); setEssLoading(true); setEssErr(null);
    const sun=dts(profile.pos.Sun), moon=dts(profile.pos.Moon), asc=dts(profile.pos.Ascendant);
    const merc=dts(profile.pos.Mercury), ven=dts(profile.pos.Venus), mars=dts(profile.pos.Mars);
    callClaude(
      `あなたは西洋占星術の専門家です。以下の出生ホロスコープをもとに、この人の本質・性格・人生テーマを詳しく日本語で鑑定してください。\n\n` +
      `【ホロスコープデータ】\n` +
      `名前: ${profile.name}\n` +
      `太陽: ${sun.sign} (${sun.within}°)\n` +
      `月: ${moon.sign} (${moon.within}°)\n` +
      `アセンダント: ${asc.sign}\n` +
      `水星: ${merc.sign} / 金星: ${ven.sign} / 火星: ${mars.sign}\n\n` +
      `JSONのみで返してください(説明・コードブロック不要):\n` +
      `{"essence":"この人の本質・魂の傾向(150〜200字)","personality":"日常的な性格・振る舞い(150〜200字)","strength":"持って生まれた才能と強み(120〜150字)","challenge":"人生の課題と成長テーマ(100〜130字)","love":"恋愛・対人関係のスタイル(100〜130字)","career":"向いている仕事・才能の活かし方(100〜130字)","keyword":["キーワード1","キーワード2","キーワード3","キーワード4","キーワード5"]}`
    ).then(d=>{ setEssence(d); setEssLoading(false); }).catch(e=>{ setEssErr(e.message); setEssLoading(false); });
  }, [profile]);

  if(!profile) return (
    <div style={{textAlign:"center",padding:"76px 20px"}}>
      <span style={{fontSize:"2.2rem",opacity:.18,display:"block",marginBottom:14}}>⬡</span>
      <div style={{fontSize:".93rem",color:"#9a9288"}}>出生情報を入力してホロスコープを生成してください</div>
    </div>
  );

  const PL1=["Sun","Moon","Mercury","Venus","Mars"];
  const PL2=["Jupiter","Saturn","Uranus","Neptune","Pluto"];

  return (
    <div>
      {/* チャートラベル */}
      <SectLabel>{profile.name} のネイタルチャート — {profile.dateStr}</SectLabel>

      {/* チャート本体 */}
      <div style={{display:"grid",gridTemplateColumns:"1fr 290px",gap:20,marginBottom:28}}>
        <div style={{background:"#fff",border:"1px solid #ede9e2",borderRadius:16,padding:22,boxShadow:"0 2px 24px rgba(26,24,20,.07)",display:"flex",alignItems:"center",justifyContent:"center"}}>
          <ChartCanvas profile={profile} />
        </div>
        <div style={{display:"flex",flexDirection:"column",gap:13}}>
          {[["個人天体",PL1],["社会・世代天体",PL2]].map(([title,pl])=>(
            <PlanetCard key={title} title={title}>
              {pl.map(p=>(
                <div key={p} style={{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"5px 0",borderBottom:"1px solid #ede9e2"}}>
                  <div style={{fontSize:".85rem",color:"#4a463e",display:"flex",alignItems:"center",gap:7}}>
                    <span style={{color:PCOL[p],fontSize:".95rem",width:16,textAlign:"center"}}>{PSYM[p]}</span>{PJP[p]}
                  </div>
                  <SignTag planet={p} pos={profile.pos} onOpen={onOpenPopup} />
                </div>
              ))}
            </PlanetCard>
          ))}
          <PlanetCard title="アングル">
            {[["ASC(上昇点)",profile.pos.Ascendant],["MC(天頂)",(profile.pos.Ascendant+270)%360]].map(([lbl,deg],i)=>{
              const s=dts(deg);
              return <div key={lbl} style={{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"5px 0",borderBottom:i===0?"1px solid #ede9e2":"none"}}>
                <div style={{fontSize:".85rem",color:"#4a463e"}}>{lbl}</div>
                <span style={{fontSize:".76rem",padding:"3px 9px",borderRadius:20,background:"rgba(200,168,122,.12)",color:"#a8885a",border:"1px solid rgba(200,168,122,.4)",fontWeight:500}}>{s.sym} {s.sign}</span>
              </div>;
            })}
          </PlanetCard>
          <div style={{fontSize:".72rem",color:"#9a9288",textAlign:"center",lineHeight:1.7,padding:"4px 0"}}>
            星座タグをクリックすると<br/>その惑星×星座の特徴が表示されます
          </div>
        </div>
      </div>

      {/* ── 本質・性格分析セクション ── */}
      <SectLabel>ホロスコープが語る あなたの本質</SectLabel>

      {essLoading && (
        <div style={{textAlign:"center",padding:"48px 0"}}>
          <div style={{width:38,height:38,margin:"0 auto 14px",border:"2px solid #e8e4de",borderTopColor:"#c8a87a",borderRadius:"50%",animation:"spin 1s linear infinite"}} />
          <div style={{fontSize:".88rem",color:"#9a9288"}}>星々からあなたの本質を読み取っています…</div>
        </div>
      )}
      {essErr && <div style={{padding:"14px 18px",background:"#fef8f8",border:"1px solid #f0d0d0",borderRadius:9,fontSize:".83rem",color:"#a04040"}}>取得に失敗しました:{essErr}</div>}
      {essence && (
        <div>
          {/* キーワードバッジ */}
          {essence.keyword?.length > 0 && (
            <div style={{display:"flex",flexWrap:"wrap",gap:8,marginBottom:22}}>
              {essence.keyword.map((k,i)=>(
                <span key={i} style={{fontSize:".82rem",padding:"5px 14px",borderRadius:20,background:"rgba(200,168,122,.1)",color:"#a8885a",border:"1px solid rgba(200,168,122,.35)",fontWeight:500}}>{k}</span>
              ))}
            </div>
          )}
          {/* 分析カード */}
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14}}>
            {[
              {key:"essence", label:"本質・魂の傾向", bar:"linear-gradient(90deg,#c89840,#e8c070)", dot:"#c89840", full:true},
              {key:"personality", label:"日常的な性格", bar:"linear-gradient(90deg,#7090c0,#a0b8e0)", dot:"#7090c0", full:true},
              {key:"strength",   label:"才能と強み",   bar:"linear-gradient(90deg,#40a890,#70d0b0)", dot:"#40a890"},
              {key:"challenge",  label:"人生の課題",   bar:"linear-gradient(90deg,#d07890,#f0a8b8)", dot:"#d07890"},
              {key:"love",       label:"恋愛・対人関係",bar:"linear-gradient(90deg,#e09aaa,#c86478)", dot:"#c86478"},
              {key:"career",     label:"仕事・才能の活かし方",bar:"linear-gradient(90deg,#7abd8a,#4a8c5c)",dot:"#4a8c5c"},
            ].map(({key,label,bar,dot,full})=>(
              <div key={key} style={{background:"#fff",border:"1px solid #ede9e2",borderRadius:14,padding:"20px 22px",boxShadow:"0 2px 20px rgba(26,24,20,.06)",position:"relative",overflow:"hidden",gridColumn:full?"1/-1":"auto"}}>
                <div style={{position:"absolute",top:0,left:0,right:0,height:3,background:bar}} />
                <div style={{fontSize:".7rem",letterSpacing:".15em",textTransform:"uppercase",color:"#9a9288",marginBottom:8,display:"flex",alignItems:"center",gap:7}}>
                  <span style={{width:5,height:5,borderRadius:"50%",background:dot,display:"inline-block"}} />{label}
                </div>
                <div style={{fontSize:".875rem",color:"#4a463e",lineHeight:1.88,fontWeight:300}}>{essence[key]}</div>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

// ═══ 運勢パネル(日付指定) ═══
function FortunePanel({ profile }) {
  const today = new Date().toISOString().split("T")[0];
  const [targetDate, setTargetDate] = useState(today);
  const [readings, setReadings]     = useState(null);
  const [loading,  setLoading]      = useState(false);
  const [err,      setErr]          = useState(null);
  const [queried,  setQueried]      = useState(null); // 最後に取得した日付

  const load = useCallback(async (dateStr) => {
    if(!profile) return;
    setLoading(true); setReadings(null); setErr(null);
    const sun=dts(profile.pos.Sun), moon=dts(profile.pos.Moon), asc=dts(profile.pos.Ascendant);
    const d=new Date(dateStr);
    const dow=["日","月","火","水","木","金","土"][d.getDay()];
    const label=dateStr===today?"今日":dateStr<today?"過去の日付":"未来の日付";
    try {
      const result = await callClaude(
        `あなたは西洋占星術の専門家です。以下の出生データと指定日をもとに、その日の運勢を日本語で鑑定してください。\n\n` +
        `【出生データ】\n名前: ${profile.name}\n生年月日: ${profile.dateStr} ${profile.timeStr}\n出生地: ${profile.place}\n太陽: ${sun.sign} (${sun.within}°)\n月: ${moon.sign}\nアセンダント: ${asc.sign}\n\n` +
        `【鑑定対象日】${dateStr} (${dow}曜日) ※${label}\n\n` +
        `この日のトランジット(移動天体)の影響も考慮して、4分野の運勢をJSONのみで返してください(説明・コードブロック不要):\n` +
        `{"date":"${dateStr}","summary":"一言総評(30字以内)","readings":[{"area":"総合運","title":"見出し(15字以内)","text":"鑑定文(150〜200字)","stars":4,"lucky":["ラッキーカラー:○○","ラッキーナンバー:○"]},{"area":"恋愛運","title":"見出し","text":"鑑定文(130字前後)","stars":3,"lucky":[]},{"area":"仕事・金運","title":"見出し","text":"鑑定文(130字前後)","stars":5,"lucky":[]},{"area":"健康運","title":"見出し","text":"鑑定文(100字前後)","stars":4,"lucky":[]}]}`
      );
      setReadings(result); setQueried(dateStr);
    } catch(e) { setErr(e.message); }
    finally    { setLoading(false); }
  }, [profile, today]);

  // 初回・プロフィール変化時に今日の運勢を取得
  useEffect(()=>{ if(profile) load(today); }, [profile]);

  if(!profile) return (
    <div style={{textAlign:"center",padding:"76px 20px"}}>
      <span style={{fontSize:"2.2rem",opacity:.18,display:"block",marginBottom:14}}>◈</span>
      <div style={{fontSize:".93rem",color:"#9a9288"}}>出生情報を入力して運勢を確認してください</div>
    </div>
  );

  return (
    <div>
      {/* 日付選択エリア */}
      <SectLabel>鑑定する日付を選択</SectLabel>
      <div style={{background:"#fff",border:"1px solid #ede9e2",borderRadius:14,padding:"22px 26px",boxShadow:"0 2px 20px rgba(26,24,20,.06)",marginBottom:28,display:"flex",alignItems:"flex-end",gap:14,flexWrap:"wrap"}}>
        <div style={{flex:1,minWidth:200}}>
          <label style={{fontSize:".72rem",letterSpacing:".13em",textTransform:"uppercase",color:"#9a9288",fontWeight:500,display:"block",marginBottom:7}}>日付</label>
          <input type="date" value={targetDate} onChange={e=>setTargetDate(e.target.value)}
            style={{width:"100%",background:"#f8f7f5",border:"1.5px solid #e8e4de",borderRadius:9,padding:"11px 14px",color:"#1a1814",fontFamily:"inherit",fontSize:".93rem",outline:"none",transition:"border-color .2s"}}
            onFocus={e=>{e.target.style.borderColor="#c8a87a";e.target.style.boxShadow="0 0 0 3px rgba(200,168,122,.14)";}}
            onBlur={e=>{e.target.style.borderColor="#e8e4de";e.target.style.boxShadow="none";}}
          />
        </div>
        <div style={{display:"flex",gap:8,flexWrap:"wrap"}}>
          {[["今日",today],["明日",new Date(Date.now()+86400000).toISOString().split("T")[0]],["明後日",new Date(Date.now()+172800000).toISOString().split("T")[0]]].map(([l,v])=>(
            <button key={l} onClick={()=>setTargetDate(v)} style={{padding:"7px 14px",borderRadius:7,background:targetDate===v?"rgba(200,168,122,.15)":"var(--white,#fff)",border:`1.5px solid ${targetDate===v?"#c8a87a":"#e8e4de"}`,color:targetDate===v?"#a8885a":"#9a9288",cursor:"pointer",fontSize:".8rem",transition:"all .2s",fontFamily:"inherit"}}>{l}</button>
          ))}
        </div>
        <button onClick={()=>load(targetDate)} disabled={loading}
          style={{padding:"11px 24px",background:"#1a1814",color:"#fff",border:"none",borderRadius:9,cursor:loading?"not-allowed":"pointer",fontSize:".83rem",fontWeight:500,letterSpacing:".08em",display:"flex",alignItems:"center",gap:8,transition:"background .2s",opacity:loading?.6:1,whiteSpace:"nowrap",fontFamily:"inherit"}}
          onMouseEnter={e=>!loading&&(e.currentTarget.style.background="#4a463e")}
          onMouseLeave={e=>{e.currentTarget.style.background="#1a1814";}}
        >
          <span>✦</span> 運勢を鑑定する
        </button>
      </div>

      {/* ローディング */}
      {loading && (
        <div style={{textAlign:"center",padding:"56px 0"}}>
          <div style={{width:38,height:38,margin:"0 auto 14px",border:"2px solid #e8e4de",borderTopColor:"#c8a87a",borderRadius:"50%",animation:"spin 1s linear infinite"}} />
          <div style={{fontSize:".88rem",color:"#9a9288"}}>星々に問いかけています…</div>
        </div>
      )}

      {/* エラー */}
      {err && <div style={{padding:"14px 18px",background:"#fef8f8",border:"1px solid #f0d0d0",borderRadius:9,fontSize:".83rem",color:"#a04040"}}>エラー:{err}</div>}

      {/* 鑑定結果 */}
      {readings && !loading && (
        <div>
          {/* 日付ヘッダー */}
          <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:18,flexWrap:"wrap",gap:10}}>
            <div>
              <div style={{fontFamily:"Georgia,serif",fontSize:"1.25rem",color:"#1a1814"}}>
                {queried} の運勢
              </div>
              {readings.summary && (
                <div style={{fontSize:".88rem",color:"#a8885a",marginTop:4,fontStyle:"italic"}}>「{readings.summary}」</div>
              )}
            </div>
            <div style={{fontSize:".76rem",color:"#9a9288",background:"#f8f7f5",border:"1px solid #e8e4de",borderRadius:7,padding:"5px 12px"}}>
              {profile.name} · 太陽{dts(profile.pos.Sun).sym}{dts(profile.pos.Sun).sign}
            </div>
          </div>

          {/* 運勢カード */}
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14}}>
            {(readings.readings||[]).map((r,i)=>(
              <div key={i} style={{background:"#fff",border:"1px solid #ede9e2",borderRadius:14,padding:"20px 22px",boxShadow:"0 2px 20px rgba(26,24,20,.06)",position:"relative",overflow:"hidden",gridColumn:i===0?"1/-1":"auto",transition:"box-shadow .22s,transform .22s"}}
                onMouseEnter={e=>{e.currentTarget.style.boxShadow="0 8px 40px rgba(26,24,20,.12)";e.currentTarget.style.transform="translateY(-2px)";}}
                onMouseLeave={e=>{e.currentTarget.style.boxShadow="0 2px 20px rgba(26,24,20,.06)";e.currentTarget.style.transform="translateY(0)";}}
              >
                <div style={{position:"absolute",top:0,left:0,right:0,height:3,background:FORTUNE_COLORS[i].bar}} />
                <div style={{fontSize:".69rem",letterSpacing:".15em",textTransform:"uppercase",color:"#9a9288",marginBottom:7,display:"flex",alignItems:"center",gap:7}}>
                  <span style={{width:5,height:5,borderRadius:"50%",background:FORTUNE_COLORS[i].dot,display:"inline-block"}} />{r.area}
                </div>
                <div style={{fontFamily:"Georgia,serif",fontSize:"1.05rem",color:"#1a1814",marginBottom:10,lineHeight:1.35}}>{r.title}</div>
                <div style={{fontSize:".855rem",color:"#4a463e",lineHeight:1.88,fontWeight:300}}>{r.text}</div>
                <div style={{marginTop:12,display:"flex",gap:2,alignItems:"center"}}>
                  {"★".repeat(r.stars||3).split("").map((_,j)=><span key={j} style={{color:"#c8a87a",fontSize:".88rem"}}>★</span>)}
                  {"☆".repeat(5-(r.stars||3)).split("").map((_,j)=><span key={j} style={{color:"#e8e4de",fontSize:".88rem"}}>☆</span>)}
                  <span style={{fontSize:".72rem",color:"#9a9288",marginLeft:7}}>{r.stars||3} / 5</span>
                </div>
                {r.lucky?.length>0 && (
                  <div style={{marginTop:11,display:"flex",gap:6,flexWrap:"wrap"}}>
                    {r.lucky.map((l,j)=><span key={j} style={{fontSize:".73rem",padding:"3px 9px",borderRadius:20,background:"rgba(200,168,122,.12)",color:"#a8885a",border:"1px solid rgba(200,168,122,.4)"}}>{l}</span>)}
                  </div>
                )}
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

// ═══ 共通コンポーネント ═══
function SectLabel({children}) {
  return (
    <div style={{fontSize:".71rem",letterSpacing:".18em",textTransform:"uppercase",color:"#9a9288",margin:"36px 0 18px",display:"flex",alignItems:"center",gap:12}}>
      {children}<span style={{flex:1,height:1,background:"#e8e4de",display:"block"}} />
    </div>
  );
}
function PlanetCard({title,children}) {
  return (
    <div style={{background:"#fff",border:"1px solid #ede9e2",borderRadius:12,padding:"14px 16px",boxShadow:"0 1px 8px rgba(26,24,20,.04)"}}>
      <div style={{fontSize:".69rem",letterSpacing:".14em",textTransform:"uppercase",color:"#9a9288",marginBottom:9,fontWeight:500}}>{title}</div>
      {children}
    </div>
  );
}

// ═══ メインアプリ ═══
export default function App() {
  const [tab,   setTab]    = useState("birth");
  const [name,  setName]   = useState("");
  const [date,  setDate]   = useState("1990-06-15");
  const [time,  setTime]   = useState("14:30");
  const [place, setPlace]  = useState("東京");
  const [profile, setProfile] = useState(null);
  const [popup, setPopup]  = useState(null);
  const [preview, setPreview] = useState(null);

  useEffect(()=>{
    if(!date) return;
    const [y,m,d]=date.split("-").map(Number);
    setPreview(dts(calcDeg(toJD(y,m,d,12,0),"Sun")));
  },[date]);

  function generate() {
    if(!date){alert("生年月日を入力してください");return;}
    const [y,m,d]=date.split("-").map(Number);
    const [hh,mn]=(time||"12:00").split(":").map(Number);
    const pos=buildPos(y,m,d,hh||12,mn||0);
    setProfile({name:name||"あなた",dateStr:date,timeStr:time,place,pos,y,m,d,hh,mn});
    setTab("chart");
  }

  const TABS=[["birth","出生情報"],["chart","チャート"],["fortune","運勢"]];

  return (
    <div style={{background:"#f8f7f5",minHeight:"100vh",fontFamily:"'DM Sans',sans-serif",fontWeight:300,WebkitFontSmoothing:"antialiased"}}>
      <style>{`
        @import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@300;400;500&display=swap');
        @keyframes spin{to{transform:rotate(360deg);}}
        @keyframes rise{from{opacity:0;transform:translateY(12px);}to{opacity:1;transform:translateY(0);}}
        *{box-sizing:border-box;} button{font-family:inherit;}
        @media(max-width:620px){
          .chart-grid{grid-template-columns:1fr !important;}
          .essence-grid{grid-template-columns:1fr !important;}
          .fortune-grid{grid-template-columns:1fr !important;}
          .birth-grid{grid-template-columns:1fr !important;}
        }
      `}</style>

      <div style={{maxWidth:860,margin:"0 auto",padding:"0 20px 100px"}}>

        {/* ヘッダー */}
        <div style={{padding:"46px 0 22px",display:"flex",alignItems:"flex-end",justifyContent:"space-between",borderBottom:"1px solid #e8e4de"}}>
          <div>
            <div style={{fontFamily:"Georgia,serif",fontSize:"2.2rem",fontWeight:400,letterSpacing:".06em",color:"#1a1814"}}>
              AS<em style={{color:"#a8885a",fontStyle:"italic"}}>tra</em>
            </div>
            <div style={{fontSize:".78rem",color:"#9a9288",letterSpacing:".14em",textTransform:"uppercase",marginTop:6}}>西洋占星術 — 星読みホロスコープ</div>
          </div>
          <div style={{opacity:.28,fontSize:"1.1rem",letterSpacing:6,paddingBottom:4}}>☉ ☽ ☿ ♀ ♂</div>
        </div>

        {/* ナビ */}
        <div style={{display:"flex",borderBottom:"1px solid #e8e4de"}}>
          {TABS.map(([k,l])=>(
            <button key={k} onClick={()=>setTab(k)} style={{padding:"14px 22px",background:"none",border:"none",fontSize:".82rem",fontWeight:400,letterSpacing:".1em",textTransform:"uppercase",color:tab===k?"#1a1814":"#9a9288",cursor:"pointer",position:"relative",transition:"color .2s"}}>
              {l}
              {tab===k&&<span style={{position:"absolute",bottom:-1,left:0,right:0,height:2,background:"#a8885a",display:"block"}} />}
            </button>
          ))}
        </div>

        {/* パネル:出生情報 */}
        {tab==="birth" && (
          <div style={{animation:"rise .4s cubic-bezier(.16,1,.3,1)"}}>
            <SectLabel>あなたのデータを入力</SectLabel>
            <div style={{background:"#fff",border:"1px solid #ede9e2",borderRadius:16,padding:"32px 32px 36px",boxShadow:"0 2px 24px rgba(26,24,20,.07)"}}>
              <div style={{fontFamily:"Georgia,serif",fontSize:"1.35rem",marginBottom:7,lineHeight:1.4}}>
                星はあなたが生まれた<em style={{color:"#a8885a",fontStyle:"italic"}}>瞬間</em>を覚えている。
              </div>
              <div style={{fontSize:".86rem",color:"#9a9288",marginBottom:28,lineHeight:1.75}}>出生日時と場所を入力すると、あなただけのホロスコープを生成します。</div>
              <div className="birth-grid" style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"17px 22px",marginBottom:20}}>
                {[
                  ["お名前","text",name,setName,"山田 太郎",null],
                  ["生年月日","date",date,setDate,null,null],
                  ["出生時刻","time",time,setTime,null,"不明の場合は 12:00 を入力"],
                  ["出生地","text",place,setPlace,"東京",null],
                ].map(([lbl,type,val,setter,ph,hint])=>(
                  <div key={lbl} style={{display:"flex",flexDirection:"column",gap:6}}>
                    <label style={{fontSize:".72rem",letterSpacing:".13em",textTransform:"uppercase",color:"#9a9288",fontWeight:500}}>{lbl}</label>
                    <input type={type} value={val} onChange={e=>setter(e.target.value)} placeholder={ph||""}
                      style={{background:"#f8f7f5",border:"1.5px solid #e8e4de",borderRadius:9,padding:"11px 14px",color:"#1a1814",fontFamily:"inherit",fontSize:".93rem",fontWeight:300,outline:"none",transition:"border-color .2s,box-shadow .2s"}}
                      onFocus={e=>{e.target.style.borderColor="#c8a87a";e.target.style.boxShadow="0 0 0 3px rgba(200,168,122,.14)";}}
                      onBlur={e=>{e.target.style.borderColor="#e8e4de";e.target.style.boxShadow="none";}}
                    />
                    {hint&&<span style={{fontSize:".73rem",color:"#9a9288"}}>{hint}</span>}
                  </div>
                ))}
              </div>
              {preview&&(
                <div style={{marginTop:4,marginBottom:20,padding:"13px 17px",background:"rgba(200,168,122,.1)",border:"1px solid rgba(200,168,122,.38)",borderRadius:9,display:"flex",alignItems:"center",gap:12}}>
                  <span style={{fontSize:"1.7rem"}}>{preview.sym}</span>
                  <div>
                    <div style={{fontFamily:"Georgia,serif",fontSize:"1rem"}}>{preview.sign}</div>
                    <div style={{fontSize:".77rem",color:"#9a9288",marginTop:2}}>太陽星座: {preview.sign} ({preview.within}°)</div>
                  </div>
                </div>
              )}
              <button onClick={generate}
                style={{width:"100%",padding:"14px",background:"#1a1814",color:"#fff",border:"none",borderRadius:9,cursor:"pointer",fontSize:".85rem",fontWeight:500,letterSpacing:".12em",textTransform:"uppercase",display:"flex",alignItems:"center",justifyContent:"center",gap:9,transition:"background .2s,transform .15s"}}
                onMouseEnter={e=>e.currentTarget.style.background="#4a463e"}
                onMouseLeave={e=>e.currentTarget.style.background="#1a1814"}
              ><span>✦</span> ホロスコープを生成する</button>
            </div>
            {profile&&(
              <div style={{display:"flex",alignItems:"center",gap:10,padding:"10px 15px",background:"#fff",border:"1px solid #ede9e2",borderRadius:9,marginTop:18,boxShadow:"0 1px 6px rgba(26,24,20,.05)"}}>
                <div style={{width:30,height:30,borderRadius:"50%",background:"rgba(200,168,122,.12)",border:"1px solid rgba(200,168,122,.4)",display:"flex",alignItems:"center",justifyContent:"center",fontSize:".85rem",flexShrink:0}}>☉</div>
                <div>
                  <div style={{fontSize:".86rem",fontWeight:500}}>{profile.name}</div>
                  <div style={{fontSize:".76rem",color:"#9a9288",marginTop:1}}>{profile.dateStr} · {profile.place} · 太陽: {dts(profile.pos.Sun).sym}{dts(profile.pos.Sun).sign}</div>
                </div>
              </div>
            )}
          </div>
        )}

        {/* パネル:チャート */}
        {tab==="chart" && (
          <div style={{animation:"rise .4s cubic-bezier(.16,1,.3,1)"}}>
            <ChartPanel profile={profile} onOpenPopup={(planet,signName,signSym)=>setPopup({planet,signName,signSym})} />
          </div>
        )}

        {/* パネル:運勢 */}
        {tab==="fortune" && (
          <div style={{animation:"rise .4s cubic-bezier(.16,1,.3,1)"}}>
            <SectLabel>運勢鑑定</SectLabel>
            <FortunePanel profile={profile} />
          </div>
        )}

      </div>

      {/* ポップアップ */}
      {popup&&<SignPopup planet={popup.planet} signName={popup.signName} signSym={popup.signSym} onClose={()=>setPopup(null)} />}
    </div>
  );
}