/* =========================================================
   ページ群 1  (members/pages_main.jsx)
   ダッシュボード / 案件一覧 / 案件詳細 / 競合分析
   ========================================================= */

/* ---- 入札価格モデル（pct = 基準額に対する%。例 0.8 = +0.8%） ---- */
const smooth=(x,a,b)=>Math.max(0,Math.min(1,(x-a)/(b-a)));
function bidModel(pct){
  const valid = smooth(pct,-0.3,0.9);                 // 最低制限を上回る確率
  const winGiven = 1 - 0.85*smooth(pct,0.6,2.4);      // 有効札のうち最安で勝てる確率
  const win = Math.round(valid*winGiven*100);
  const disq = Math.round((1-valid)*100);
  let verdict, tone;
  if(pct < -0.1){ verdict="失格リスク大"; tone="red"; }
  else if(pct>=0.6 && pct<=1.0){ verdict="推奨レンジ"; tone="green"; }
  else if(pct>1.7){ verdict="取りこぼし（高すぎ）"; tone="orange"; }
  else if(pct<0.6){ verdict="やや弱い"; tone="orange"; }
  else { verdict="やや高め"; tone="blue"; }
  return { win:Math.max(0,win), disq, valid:Math.round(valid*100), verdict, tone };
}
const yen = man => (man*10000).toLocaleString();
window.bidModel = bidModel;

/* =================== ダッシュボード =================== */
function HatchuCard(){
  const H = DATA.hatchu||[];
  const [kf,setKf]=React.useState("すべて");
  if(!H.length) return null;
  const kinds=["すべて",...Array.from(new Set(H.map(x=>x.koshu)))];
  const open=H.filter(x=>x.status!=="done");
  const doneN=H.length-open.length;            // 落札DBで確認できた落札済み（除外）
  const cnt=k=> open.filter(x=>k==="すべて"||x.koshu===k).length;
  const list=open.filter(x=>kf==="すべて"||x.koshu===kf);
  const ordered=list.slice().sort((a,b)=> a.q-b.q || a.no-b.no);
  const monLabel=q=> q===1?"4〜6月":q===2?"7〜9月":q===3?"10〜12月":q===4?"1〜3月":"";
  const kc=k=> k==="建築一式"?{bg:"var(--green-bg)",fg:"var(--green-deep)"}:k==="災害復旧"?{bg:"#fdeee8",fg:"#bd4321"}:{bg:"var(--blue-bg)",fg:"var(--blue-deep)"};
  const chip=(t,c)=> <span style={{background:c.bg,color:c.fg,fontSize:11,fontWeight:600,padding:"1px 8px",borderRadius:6,whiteSpace:"nowrap"}}>{t}</span>;
  const Item=({x})=>(
    <div className="row-item" style={{alignItems:"center"}}>
      <div className="ri-ic" style={{background:"#eef6ef",color:"#157a51"}}><Icon name="file"/></div>
      <div className="ri-main"><div className="ri-t" style={{fontSize:13}}>{x.name}</div>
        <div className="ri-s">{x.scale}{x.place?`　｜　${x.place}`:""}</div></div>
      <div className="ri-r flex ac" style={{gap:8}}>{chip(x.koshu,kc(x.koshu))}{x.shimei&&chip("指名",{bg:"#f1efe8",fg:"#5f5e5a"})}<span style={{fontSize:12,fontWeight:600,color:"#0e2a47",whiteSpace:"nowrap"}}>{monLabel(x.q)} 予定</span></div>
    </div>
  );
  return (
    <Card className="mt" icon="target" title="発注見通し（御社が入れる工種）" sub={(DATA.prospect?"広島県":"令和8年度 〇〇市")+"の発注予定（御社の参加資格がある工種）"}>
      <div className="flex ac wrap gap-s mb-s">
        {kinds.map(k=><button key={k} className={"chip"+(kf===k?" on":"")} onClick={()=>setKf(k)}>{k}<span className="cnt">{cnt(k)}</span></button>)}
      </div>
      <div style={{fontSize:13,marginBottom:6}}><b style={{color:"#157a51",fontSize:18}}>{list.length}</b> 件 入札予定{DATA.prospect?"":`（落札済み ${doneN}件は除外）`}</div>
      <div style={{maxHeight:360,overflowY:"auto",margin:"0 -2px",paddingRight:4}}>
        {ordered.map(x=><Item key={x.no} x={x}/>)}
        {ordered.length===0 && <div className="center mut" style={{padding:"18px 0"}}>この工種の発注予定はありません</div>}
      </div>
      {ordered.length>8 && <div className="small mut center" style={{paddingTop:8}}>↑ スクロールで全{ordered.length}件を表示</div>}
      <div className="small mut mt-s">{DATA.prospect?"出典：広島県 入札情報（公開公告）。御社の参加資格がある工種に絞って表示。予定価格は公告記載値。":"落札済みは落札DB(2026年度)で確認して除外。4〜6月で未落札のものは公告中の可能性。月は四半期からの目安・予定価格は非掲載（あくまで\"予定\"）。"}</div>
    </Card>
  );
}

function ProfileCard(){
  const c=DATA.company;
  const [open,setOpen]=React.useState(true);
  const quals=DATA.company.qualifications||[
    {gyoshu:"土木一式", shi:(c.keishin.doboku||{}).grade||"", ken:""},
    {gyoshu:"建築一式", shi:(c.keishin.kenchiku||{}).grade||"", ken:""},
  ];
  const wg=DATA.record.winRateByGyoshu||{};
  const wgOf=g=> g==="土木一式"?wg.doboku:wg.kenchiku;
  const scoreOf=g=> g==="土木一式"?(c.keishin.doboku||{}).score:(c.keishin.kenchiku||{}).score;
  const Grade=({g})=>{ if(!g) return <span className="mut">—</span>;
    const cc=g==="B"?{bg:"var(--green-bg)",fg:"var(--green-deep)"}:{bg:"var(--blue-bg)",fg:"var(--blue-deep)"};
    return <span style={{display:"inline-flex",alignItems:"baseline",gap:1,background:cc.bg,color:cc.fg,borderRadius:8,padding:"5px 13px",fontWeight:700,fontSize:17}}>{g}<span style={{fontSize:11,fontWeight:600}}>級</span></span>; };
  const Rate=({v})=>{ if(v&&v.pct!=null){ const good=v.pct>0;
      return <span style={{fontWeight:700,fontSize:20,color:good?"var(--green-deep)":"var(--sub)"}}>{v.pct}%<span className="mut" style={{fontWeight:400,fontSize:11}}> ({v.wins}/{v.denom})</span></span>; }
    return <span className="mut" style={{fontSize:14}}>{v&&v.pct==null?"入札なし":"—"}</span>; };
  const dl={borderLeft:"1px solid var(--line)"};
  return (
    <Card className="mb" icon="award" title="御社の登録情報" sub="入札資格・落札率" more={open?"閉じる":"開く"} onMore={()=>setOpen(!open)}>
      {open && <>
      <table className="tbl" style={{width:"100%",tableLayout:"fixed"}}>
        <colgroup><col style={{width:"26%"}}/><col/><col/><col/><col/></colgroup>
        <thead>
          <tr>
            <th rowSpan={2} style={{verticalAlign:"bottom",background:"#fff",color:"var(--sub)"}}>工種</th>
            <th colSpan={2} className="center" style={{background:"#fff",color:"var(--ink2)"}}>入札資格（格付）</th>
            <th colSpan={2} className="center" style={{...dl,background:"#fff",color:"var(--ink2)"}}>落札率</th>
          </tr>
          <tr>
            <th className="center" style={{fontWeight:400,background:"#fff",color:"var(--sub)"}}>〇〇市</th>
            <th className="center" style={{fontWeight:400,background:"#fff",color:"var(--sub)"}}>〇〇県</th>
            <th className="center" style={{...dl,fontWeight:400,background:"#fff",color:"var(--sub)"}}>今年度</th>
            <th className="center" style={{fontWeight:400,background:"#fff",color:"var(--sub)"}}>前年度</th>
          </tr>
        </thead>
        <tbody>
          {quals.map(q=>{ const w=wgOf(q.gyoshu)||{};
            return (
            <tr key={q.gyoshu}>
              <td><b style={{fontSize:15}}>{q.gyoshu}</b> <span className="small mut">経審{scoreOf(q.gyoshu)}</span></td>
              <td className="center"><Grade g={q.shi}/></td>
              <td className="center"><Grade g={q.ken}/></td>
              <td className="center" style={dl}><Rate v={w.cur}/></td>
              <td className="center"><Rate v={w.prev}/></td>
            </tr>
          );})}
        </tbody>
      </table>
      <div className="small mut mt-s">県は総合数値で格付のため市と異なる場合があります　｜　落札率は辞退を除く（今年度／前年度）</div>
      </>}
    </Card>
  );
}

/* ---- ヘッダー右：営業先専用ページの資格サマリー（自治体ごとにコンパクト） ---- */
function ProspectInfo({ map }){
  const rk=(p,re)=>{ const m=(p||"").match(re); return m?m[1]:""; };
  const col=g=>(g==="A"||g==="特A")?"#0a1f36":g==="B"?"#16a34a":"#0e2a47";
  return (
    <div style={{display:"flex",alignItems:"center",gap:8,flexWrap:"wrap",justifyContent:"flex-end"}}>
      <div style={{display:"inline-flex",alignItems:"center",gap:6}}>
        <Icon name="award" style={{width:15,height:15,color:"#8a8474"}}/>
        <span style={{fontSize:12.5,fontWeight:600,color:"#5b5f6b"}}>御社の入札資格</span>
      </div>
      {map.map((row,i)=>{
        const d=rk(row.profile,/土木?(特?[A-D])/), k=rk(row.profile,/建築?(特?[A-D])/);
        return (
          <span key={i} style={{display:"inline-flex",alignItems:"center",gap:7,background:"#fff",border:"1px solid #ddd8cc",borderRadius:999,padding:"6px 13px"}}>
            <span style={{fontSize:12.5,fontWeight:700,color:"#20242c"}}>{row.gov}</span>
            {(d||k) ? <span style={{display:"inline-flex",gap:6}}>
              {d&&<span style={{fontSize:12}}><span style={{color:"#5b5f6b"}}>土</span> <b style={{color:col(d)}}>{d}</b></span>}
              {k&&<span style={{fontSize:12}}><span style={{color:"#5b5f6b"}}>建</span> <b style={{color:col(k)}}>{k}</b></span>}
            </span> : <span style={{fontSize:11,color:"#8a8474"}}>登録あり</span>}
          </span>
        );
      })}
    </div>
  );
}

/* ---- ヘッダー右：御社情報サマリー（白の丸ピル） ---- */
function InfoSummary(){
  const c=DATA.company;
  if(DATA.prospect && c.shikakuMap) return <ProspectInfo map={c.shikakuMap}/>;
  const quals=DATA.company.qualifications||[];
  const wg=DATA.record.winRateByGyoshu||{};
  const wgOf=g=> g==="土木一式"?wg.doboku:g==="建築一式"?wg.kenchiku:null;
  const gradeColor=g=> g==="B"?"#16a34a":"#0e2a47";
  const Grade=({lab,g})=> g ? (
    <span style={{display:"inline-flex",alignItems:"baseline",gap:3}}>
      <span style={{fontSize:11,color:"#5b5f6b"}}>{lab}</span>
      <span style={{fontSize:15,fontWeight:700,color:gradeColor(g)}}>{g}</span>
    </span>
  ) : null;
  const dl=<span style={{width:1,height:15,background:"#ddd8cc",display:"inline-block"}}/>;
  return (
    <div style={{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap",justifyContent:"flex-end"}}>
      <div style={{display:"inline-flex",alignItems:"center",gap:6}}>
        <Icon name="user" style={{width:15,height:15,color:"#8a8474"}}/>
        <span style={{fontSize:12.5,fontWeight:600,color:"#5b5f6b"}}>御社情報</span>
      </div>
      {quals.map(q=>{ const w=(wgOf(q.gyoshu)||{}).cur||{};
        return (
        <span key={q.gyoshu} style={{display:"inline-flex",alignItems:"center",gap:9,background:"#fff",border:"1px solid #ddd8cc",borderRadius:999,padding:"8px 16px"}}>
          <span style={{fontSize:14,fontWeight:700,color:"#20242c"}}>{q.gyoshu}</span>
          {dl}
          <span style={{fontSize:12,color:"#5b5f6b"}}>資格</span>
          {!DATA.prospect && <Grade lab="市" g={q.shi}/>}
          <Grade lab={DATA.prospect?"広島県":"県"} g={q.ken}/>
          {dl}
          <span style={{display:"inline-flex",alignItems:"baseline",gap:5}}>
            <span style={{fontSize:12,color:"#5b5f6b"}}>落札率</span>
            {w.pct!=null
              ? <span style={{fontSize:13,fontWeight:700,color:"#20242c"}}>{w.pct}%<span style={{fontSize:11,fontWeight:500,color:"#8a8474"}}> ({w.wins}/{w.denom})</span></span>
              : <span style={{fontSize:12.5,fontWeight:600,color:"#8a8474"}}>集計中</span>}
          </span>
        </span>
      );})}
    </div>
  );
}

/* ---- お知らせ（横長バナー） ---- */
function OshiraseBanner({ go }){
  const notices=(DATA.notices||[]).slice(0,2);
  if(!notices.length) return null;
  return (
    <div style={{background:"#fff",border:"1px solid #ddd8cc",borderRadius:14,boxShadow:"var(--shadow)",padding:"14px 20px"}}>
      <div style={{display:"flex",alignItems:"center",gap:20}}>
        <div style={{display:"flex",alignItems:"center",gap:11,flex:"none"}}>
          <div style={{position:"relative",width:32,height:32,borderRadius:9,background:"#e8edf3",display:"flex",alignItems:"center",justifyContent:"center",color:"#0e2a47"}}>
            <Icon name="bell" style={{width:17,height:17}}/>
            <span style={{position:"absolute",top:-2,right:-2,width:8,height:8,borderRadius:"50%",background:"#c8502e",border:"1.5px solid #fff"}}/>
          </div>
          <span style={{fontSize:14,fontWeight:700,color:"#151a26"}}>お知らせ</span>
        </div>
        <span style={{width:1,alignSelf:"stretch",background:"#efece2"}}/>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"6px 28px",flex:1,minWidth:0}}>
          {notices.map((n,i)=>{ const blue=i===0;
            return (
            <div key={i} style={{display:"flex",alignItems:"center",gap:9,minWidth:0}}>
              <span style={{flex:"none",fontSize:11,fontWeight:600,borderRadius:6,padding:"2px 7px",color:blue?"#0e2a47":"#5b5f6b",background:blue?"#e8edf3":"#efece2"}}>{n.time}</span>
              <span style={{fontSize:13,color:"#3a3f4a",lineHeight:1.5,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{n.t}</span>
            </div>
          );})}
        </div>
        <a onClick={()=>go("news")} style={{flex:"none",fontSize:13,fontWeight:600,color:"#0e2a47",cursor:"pointer",whiteSpace:"nowrap"}}>一覧 →</a>
      </div>
    </div>
  );
}

/* ---- 締切が近い順（右カラム下） ---- */
function NearDeadlineCard({ go }){
  const list=(DATA.allCases||[]).filter(c=>c.status==="参加可能"&&c.days!=null&&c.days>=0).sort((a,b)=>a.days-b.days).slice(0,5);
  return (
    <div className="card" style={{borderRadius:16,padding:22}}>
      <div style={{display:"flex",alignItems:"center",gap:9,marginBottom:list.length?14:0}}>
        <Icon name="clock" style={{width:18,height:18,color:"#5b5f6b"}}/>
        <span style={{fontSize:15,fontWeight:700,color:"#151a26"}}>締切が近い順</span>
      </div>
      {list.length===0 ? (
        <div style={{display:"flex",flexDirection:"column",alignItems:"center",textAlign:"center",padding:"18px 16px",gap:8}}>
          <div style={{width:48,height:48,borderRadius:13,background:"#efece2",display:"flex",alignItems:"center",justifyContent:"center",color:"#c9c4b8"}}><Icon name="clock" style={{width:24,height:24}}/></div>
          <div style={{fontSize:14,fontWeight:600,color:"#4d5261"}}>直近の締切はありません</div>
          <div style={{fontSize:12.5,color:"#8a8474",lineHeight:1.6}}>新しい該当公告が出ると、締切が近い順にここへ表示されます。</div>
        </div>
      ) : list.map(cs=>(
        <div className="row-item clickable" key={cs.id} style={{cursor:"pointer"}} onClick={()=>go("case",cs.id)}>
          <div className="ri-main"><div className="ri-t" style={{fontSize:13}}>{cs.title}</div>
            <div className="ri-s">{cs.cat}{cs.grade}　｜　{cs.org}</div></div>
          <div className="ri-r"><Deadline days={cs.days}/></div>
        </div>
      ))}
    </div>
  );
}

/* ---- 御社の入札参加資格マップ（営業先専用ページの目玉） ---- */
function ShikakuMapCard({ map }){
  const isKen=g=>g==="広島県";
  return (
    <div className="card" style={{borderRadius:16,padding:24}}>
      <div className="card-h">
        <div className="ci" style={{width:34,height:34}}><Icon name="award"/></div>
        <div><div className="ct" style={{fontSize:16}}>御社の入札参加資格マップ</div>
          <div className="cs" style={{fontSize:12.5}}>公開情報をもとに、御社が登録している自治体・業種・等級を整理しました</div></div>
      </div>
      <div style={{display:"flex",flexDirection:"column",gap:8}}>
        {map.map((row,i)=>(
          <div key={i} style={{display:"flex",gap:14,alignItems:"baseline",padding:"10px 14px",borderRadius:10,background:isKen(row.gov)?"#e8edf3":"#f6f4ee",border:"1px solid "+(isKen(row.gov)?"#b9c6d4":"#efece2")}}>
            <div style={{flex:"none",width:84,fontWeight:700,fontSize:13.5,color:isKen(row.gov)?"#0a1f36":"#151a26"}}>{row.gov}</div>
            <div style={{fontSize:13,color:"#3a3f4a",lineHeight:1.6}}>{row.profile||"—"}</div>
          </div>
        ))}
      </div>
      <div className="small mut mt-s">出典：広島県・各市町の入札参加資格者名簿（公開情報）。「(等級なし)」はその自治体が等級制度を設けていない業種です。</div>
    </div>
  );
}

function Dashboard({ go }){
  const c=DATA.company, r=DATA.record, m=DATA.market;
  const hist=DATA.myHistory||[];
  const years=((DATA.nendos&&DATA.nendos.length)?DATA.nendos:[...new Set(hist.map(h=>h.nendo).filter(Boolean))]).slice().sort((a,b)=>b-a);
  const yearsWithData=new Set(hist.map(h=>h.nendo));
  const [hYear,setHYear]=React.useState(years.find(y=>yearsWithData.has(y))||years[0]);
  const [hOrg,setHOrg]=React.useState("すべて");
  const byYear=hist.filter(h=>h.nendo===hYear);
  const hOrgs=["すべて",...Array.from(new Set(byYear.map(h=>h.org)))];
  const histRows=byYear.filter(h=>hOrg==="すべて"||h.org===hOrg);
  return (
    <div className="page" style={{display:"flex",flexDirection:"column",gap:24}}>
      <PageHead ey="DASHBOARD" title={`${c.short} 様の入札ダッシュボード`}
        desc={`${new Date().toLocaleDateString("ja-JP",{year:"numeric",month:"long",day:"numeric"})} 時点 ｜ 毎朝7時に最新の公告と分析を更新しています`}>
        <div style={{display:"flex",gap:10,alignItems:"center",flexWrap:"wrap"}}>
          <Btn kind="blue" icon="bell" onClick={()=>window.open('https://lin.ee/yqCt1nb','_blank')}>LINEで毎朝受け取る</Btn>
          <InfoSummary/>
        </div>
      </PageHead>

      {/* お知らせ（横長バナー） */}
      <OshiraseBanner go={go}/>

      {/* メイン2カラム：左カレンダー / 右（本日の該当案件＋締切が近い順） */}
      <div style={{display:"grid",gridTemplateColumns:"1.5fr 1fr",gap:24,alignItems:"start"}}>
        <Calendar go={go} embedded/>
        <div style={{display:"flex",flexDirection:"column",gap:24}}>
          {/* 本日の該当案件 */}
          <div className="card" style={{borderRadius:16,padding:22}}>
            <div className="card-h" style={{marginBottom:DATA.todayCases.length?14:0}}>
              <div className="ci" style={{width:34,height:34}}><Icon name="list"/></div>
              <div><div className="ct" style={{fontSize:16}}>本日の該当案件</div><div className="cs" style={{fontSize:12.5}}>御社の等級で参加可能</div></div>
              <a className="more" onClick={()=>go("cases")}>すべて見る<Icon name="arrow" style={{width:13,height:13}}/></a>
            </div>
            {DATA.todayCases.length===0 ? (
              <div style={{display:"flex",flexDirection:"column",alignItems:"center",textAlign:"center",padding:"18px 16px",gap:9}}>
                <div style={{width:48,height:48,borderRadius:13,background:"#efece2",display:"flex",alignItems:"center",justifyContent:"center",color:"#c9c4b8"}}><Icon name="truck" style={{width:24,height:24}}/></div>
                <div style={{fontSize:14.5,fontWeight:600,color:"#3a3f4a"}}>本日、新規で参加できる公告はありません</div>
                <div style={{fontSize:12.5,color:"#8a8474",lineHeight:1.7}}>直近の該当公告は「入札できる公告」でご確認いただけます。</div>
              </div>
            ) : DATA.todayCases.map(cs=>(
              <div className="row-item clickable" key={cs.id} style={{cursor:"pointer"}} onClick={()=>go("case",cs.id)}>
                <div className="ri-ic"><Icon name="file"/></div>
                <div className="ri-main">
                  <div className="ri-t">{cs.title}</div>
                  <div className="ri-s">{cs.cat}{cs.grade}　｜　{cs.scale}　｜　{cs.org}</div>
                </div>
                <div className="ri-r"><Deadline days={cs.days}/><div className="small mut">締切</div></div>
              </div>
            ))}
          </div>

          {/* 締切が近い順 */}
          <NearDeadlineCard go={go}/>
        </div>
      </div>

      {/* 発注見通し（御社が入れる工種） */}
      <HatchuCard/>

      {/* 過去の応札履歴 */}
      <div className="card" style={{borderRadius:16,padding:24}}>
        <div className="card-h">
          <div className="ci" style={{width:34,height:34}}><Icon name="list"/></div>
          <div><div className="ct" style={{fontSize:16}}>過去の応札履歴</div><div className="cs" style={{fontSize:12.5}}>御社が実際に入れた札と結果（年度で切替・新しい順）</div></div>
        </div>
        <div className="fbar alt mb-s">
          <span className="fbar-lab">年度</span>
          {years.map(y=>(
            <button key={y} className={"chip"+(hYear===y?" on":"")} onClick={()=>{setHYear(y);setHOrg("すべて");}}>
              {y}年度<span className="cnt">{hist.filter(h=>h.nendo===y).length}</span>
            </button>
          ))}
        </div>
        <div className="fbar mb">
          <span className="fbar-lab">発注者</span>
          {hOrgs.map(o=>(
            <button key={o} className={"chip"+(hOrg===o?" on":"")} onClick={()=>setHOrg(o)}>
              {o}<span className="cnt">{o==="すべて"?byYear.length:byYear.filter(h=>h.org===o).length}</span>
            </button>
          ))}
        </div>
        <div className="tbl-wrap scrolly" style={{border:"1px solid #efece2",borderRadius:12,overflowX:"auto",overflowY:"auto",maxHeight:420}}>
          <table className="tbl">
            <colgroup>
              <col style={{width:96}}/><col style={{width:74}}/><col style={{width:86}}/><col style={{width:300}}/>
              <col style={{width:120}}/><col style={{width:120}}/><col style={{width:130}}/><col style={{width:118}}/><col style={{width:84}}/><col/>
            </colgroup>
            <thead><tr><th>開札日</th><th>発注者</th><th>工種</th><th>工事名</th><th className="num">御社の札</th><th className="num">落札額</th><th>落札者</th><th className="num">差額</th><th className="center">結果</th><th></th></tr></thead>
            <tbody>
              {histRows.map((h,i)=>{
                const tone=h.result==="落札"?"green":h.result==="失格"?"red":h.result==="辞退"?"gray":"blue";
                const otone=h.orgType==="県"?"green":h.orgType==="市"?"blue":h.orgType==="町"?"orange":"gray";
                const near=h.result==="有効"&&h.diff!=null&&h.diff>0&&h.diff<=1000;
                return (
                  <tr key={i}>
                    <td className="small mut tnum">{h.date}</td>
                    <td><Badge tone={otone}>{h.org}</Badge></td>
                    <td className="small">{h.gyoshu}{h.est&&<span className="mut" style={{fontSize:10}}>（推定）</span>}</td>
                    <td><b>{h.title}</b></td>
                    <td className="num">{h.myAmount!=null?h.myAmount.toLocaleString():"—"}</td>
                    <td className="num mut">{h.winAmount!=null?h.winAmount.toLocaleString():"—"}</td>
                    <td className="small">{h.winner ? <span style={{fontWeight:h.result==="落札"?700:400,color:h.result==="落札"?"var(--orange-deep)":"inherit"}}>{h.winner}</span> : <span className="mut">—</span>}</td>
                    <td className="num">
                      {h.diff==null ? <span className="mut">—</span>
                       : near ? <b style={{color:"var(--orange-deep)"}}>あと{h.diff.toLocaleString()}円</b>
                       : <span style={{color:h.diff>0?"var(--red)":"var(--sub)"}}>{h.diff>0?"+":""}{h.diff.toLocaleString()}</span>}
                    </td>
                    <td className="center"><Badge tone={tone}>{h.result}</Badge></td>
                    <td></td>
                  </tr>
                );
              })}
              {histRows.length===0 && <tr><td colSpan="10" className="center mut" style={{padding:30}}>該当する応札履歴がありません</td></tr>}
            </tbody>
          </table>
        </div>
        <div className="small mut mt-s">{hYear}年度{hOrg!=="すべて"?`・${hOrg}`:""} の応札 {histRows.length}件 ｜ 金額は円・差額は「御社の札−落札額」｜ <span style={{color:"var(--orange-deep)",fontWeight:600}}>オレンジ</span>は1,000円差の惜敗 ｜ 出典：{DATA.prospect?"広島県":"〇〇市・〇〇県"} 入札結果（公開情報）</div>
      </div>

    </div>
  );
}

/* 営業先専用ページの公告一覧（公開情報のみ・基準額やシミュレーターなし） */
function ProspectCases({ go }){
  const [cat,setCat]=React.useState("すべて");
  const cats=["すべて",...Array.from(new Set(DATA.allCases.map(c=>c.cat)))];
  const list=DATA.allCases.filter(c=>cat==="すべて"||c.cat===cat).slice().sort((a,b)=>(a.days??999)-(b.days??999));
  return (
    <div className="page">
      <PageHead ey="Projects" title="入札できる公告" desc="広島県の公告から、御社の資格に合う案件だけを抽出しています">
        <Btn kind="ghost" icon="calendar" onClick={()=>go("calendar")}>カレンダー</Btn>
      </PageHead>
      <div className="grid cols-4 mb">
        <Tile tone="blue" icon="list" label="御社が入れる公告" value={DATA.allCases.length} unit="件" meta="広島県の公開公告より抽出"/>
        <Tile tone="orange" icon="clock" label="7日以内に開札" value={DATA.allCases.filter(c=>c.days>=0&&c.days<=7).length} unit="件" meta="開札日が近い案件"/>
        <Tile tone="green" icon="award" label="対象工種" value={cats.length-1} unit="種" meta="御社の登録工種"/>
        <Tile tone="blue" icon="pin" label="対象" value="広島県" meta="＋登録市町に順次拡大"/>
      </div>
      <Card style={{padding:"16px 18px"}}>
        <div className="flex ac wrap gap-s">
          <Icon name="filter" style={{color:"#9aa4b1",width:16,height:16}}/>
          {cats.map(x=><button key={x} className={"chip"+(cat===x?" on":"")} onClick={()=>setCat(x)}>{x}</button>)}
        </div>
      </Card>
      <div className="tbl-wrap mt">
        <table className="tbl">
          <thead><tr><th>工種/等級</th><th>工事名</th><th>発注機関</th><th className="num">予定価格</th><th>開札予定日</th><th></th></tr></thead>
          <tbody>
            {list.map(cs=>(
              <tr key={cs.id} className="clickable" onClick={()=>go("case",cs.id)}>
                <td><Badge tone="blue">{cs.cat}{cs.grade&&cs.grade!=="—"?cs.grade:""}</Badge></td>
                <td><b>{cs.title}</b></td>
                <td className="small">{cs.org}</td>
                <td className="num">{cs.scale}</td>
                <td><Deadline days={cs.days}/></td>
                <td><Icon name="arrow" style={{color:"#9aa4b1",width:18,height:18}}/></td>
              </tr>
            ))}
            {list.length===0 && <tr><td colSpan="6" className="center mut" style={{padding:30}}>条件に合う公告はありません</td></tr>}
          </tbody>
        </table>
      </div>
      <div className="small mut mt-s">出典：広島県 入札情報（公開公告）。御社の参加資格がある工種に絞って表示しています。公告番号でどなたでも検証できます。</div>
    </div>
  );
}

/* =================== 案件一覧 =================== */
function Cases({ go }){
  if(DATA.prospect) return <ProspectCases go={go}/>;
  const [cat,setCat]=React.useState("すべて");
  const [region,setRegion]=React.useState("すべて");
  const [onlyOk,setOnlyOk]=React.useState(true);
  const cats=["すべて","土木一式","建築一式","舗装","水道施設"];
  const regions=["すべて","郷ノ浦","勝本","芦辺","石田"];
  const list=DATA.allCases.filter(c=>
    (cat==="すべて"||c.cat===cat) && (region==="すべて"||c.region===region) && (!onlyOk||c.status==="参加可能"));
  return (
    <div className="page">
      <PageHead ey="Projects" title="入札できる公告" desc="御社の等級・地区に合う公告だけを毎朝お届けしています">
        <Btn kind="ghost" icon="calendar" onClick={()=>go("calendar")}>カレンダー</Btn>
      </PageHead>

      <div className="grid cols-4 mb">
        <Tile tone="blue" icon="list" label="参加可能な公告" value={DATA.allCases.filter(c=>c.status==="参加可能").length} unit="件" meta="あなたの等級で入札できます"/>
        <Tile tone="orange" icon="clock" label="3日以内に締切" value={DATA.allCases.filter(c=>c.days>=0&&c.days<=3).length} unit="件" meta="申請を急いでください"/>
        <Tile tone="green" icon="file" label="直近の該当公告" value={DATA.allCases.length} unit="件" meta="直近の巡回で判定した実公告"/>
        <Tile tone="blue" icon="pin" label="対象エリア" value="4" unit="地区" meta="〇〇市全域＋県発注"/>
      </div>

      <Card style={{padding:"16px 18px"}}>
        <div className="flex ac wrap gap-s mb">
          <Icon name="filter" style={{color:"#9aa4b1",width:16,height:16}}/>
          {cats.map(x=><button key={x} className={"chip"+(cat===x?" on":"")} onClick={()=>setCat(x)}>{x}</button>)}
        </div>
        <div className="flex ac wrap gap-s">
          <Icon name="pin" style={{color:"#9aa4b1",width:16,height:16}}/>
          {regions.map(x=><button key={x} className={"chip"+(region===x?" on":"")} onClick={()=>setRegion(x)}>{x}</button>)}
          <label className="flex ac gap-s small" style={{marginLeft:"auto",cursor:"pointer"}}>
            <input type="checkbox" checked={onlyOk} onChange={e=>setOnlyOk(e.target.checked)}/> 参加可能のみ表示
          </label>
        </div>
      </Card>

      <div className="tbl-wrap mt">
        <table className="tbl">
          <thead><tr><th>工種/等級</th><th>工事名</th><th>発注機関</th><th>規模</th><th className="num">発注基準額(推定)</th><th>申請締切</th><th></th></tr></thead>
          <tbody>
            {list.map(cs=>(
              <tr key={cs.id} className="clickable" onClick={()=>go("case",cs.id)}>
                <td><Badge tone={cs.status==="参加可能"?"blue":"gray"}>{cs.cat}{cs.grade!=="—"?cs.grade:""}</Badge></td>
                <td><b>{cs.title}</b><div className="small mut">{cs.no}</div></td>
                <td className="small">{cs.org}<div className="mut">{cs.region}</div></td>
                <td className="small">{cs.scale}</td>
                <td className="num">{cs.base[0].toLocaleString()}〜{cs.base[1].toLocaleString()}万</td>
                <td><Deadline days={cs.days}/></td>
                <td><Icon name="arrow" style={{color:"#9aa4b1",width:18,height:18}}/></td>
              </tr>
            ))}
            {list.length===0 && <tr><td colSpan="7" className="center mut" style={{padding:30}}>条件に合う公告はありません</td></tr>}
          </tbody>
        </table>
      </div>
      <div className="small mut mt-s">※〇〇市は予定価格を事後公表のため、規模は同種・同規模の過去落札からの推定です。公告番号を明記し、ご自身で真偽を確認できます（出典：〇〇市入札情報）。</div>
    </div>
  );
}

/* =================== 案件詳細 =================== */
/* 営業先専用ページの公告詳細（公開情報のみ・シミュレーター等なし） */
function ProspectCaseDetail({ cs, go }){
  const row=(k,v)=> v ? <div key={k}><div className="small mut">{k}</div><div className="b mt-s" style={{fontSize:14}}>{v}</div></div> : null;
  return (
    <div className="page">
      <div className="flex ac gap-s mb" style={{cursor:"pointer"}} onClick={()=>go("cases")}>
        <Icon name="arrow" style={{transform:"rotate(180deg)",color:"#0e2a47"}}/><span className="b" style={{color:"#0e2a47",fontSize:13}}>公告一覧へ戻る</span>
      </div>
      <PageHead ey="Project detail" title={cs.title} desc={cs.org||""}>
        <Badge tone="blue">{cs.cat}{cs.grade&&cs.grade!=="—"?cs.grade:""}</Badge>
        {cs.days!=null&&cs.days>=0&&<Badge tone="orange" pulse>開札まで あと{cs.days}日</Badge>}
      </PageHead>
      <Card icon="file" title="公告の概要">
        <div className="grid cols-2" style={{gap:14}}>
          {[ row("発注機関",cs.org), row("入札・契約方法",cs.method), row("工種",cs.cat),
             row("御社の等級",cs.grade&&cs.grade!=="—"?cs.grade:"（この工種は御社登録あり）"),
             row("予定価格",cs.scale), row("公告日",cs.koukokuAt), row("開札予定日",cs.kaisatsuAt) ]}
        </div>
        <div className="divider"></div>
        <div className="small mut">この案件は御社の入札参加資格（{cs.cat}{cs.grade&&cs.grade!=="—"?cs.grade:""}）で参加できる公告です。出典：広島県 入札情報（公開公告）。</div>
      </Card>
    </div>
  );
}

function CaseDetail({ id, go }){
  const cs=(DATA.allCases.find(c=>c.id===id))||DATA.todayCases[0]||DATA.allCases[0];
  if(!cs) return <div className="page"><PageHead title="案件が見つかりません"/></div>;
  if(DATA.prospect) return <ProspectCaseDetail cs={cs} go={go}/>;
  const mid=(cs.base[0]+cs.base[1])/2;
  const recLo=mid*1.006, recHi=mid*1.010;
  const model=bidModel(0.8);
  const likely=DATA.competitors.filter(x=>!x.me).slice(0,3);
  return (
    <div className="page">
      <div className="flex ac gap-s mb" style={{cursor:"pointer"}} onClick={()=>go("cases")}>
        <Icon name="arrow" style={{transform:"rotate(180deg)",color:"#0e2a47"}}/><span className="b" style={{color:"#0e2a47",fontSize:13}}>公告一覧へ戻る</span>
      </div>
      <PageHead ey="Project detail" title={cs.title}
        desc={`${cs.org}　｜　公告番号 ${cs.no}`}>
        <Badge tone="blue">{cs.cat}{cs.grade!=="—"?cs.grade:""}</Badge>
        <Badge tone="orange" pulse>申請締切 あと{cs.days}日</Badge>
      </PageHead>

      <div className="grid cols-3">
        <Card className="span-2" icon="file" title="公告の概要">
          <div className="grid cols-2" style={{gap:14}}>
            {[["発注機関",cs.org],["地区",cs.region],["工種・等級",`${cs.cat}${cs.grade!=="—"?cs.grade:""}`],["規模",cs.scale],
              ["発注基準額(推定)",`${cs.base[0].toLocaleString()}〜${cs.base[1].toLocaleString()}万円`],["申請締切",`あと${cs.days}日`]].map(([k,v])=>(
              <div key={k}><div className="small mut">{k}</div><div className="b mt-s" style={{fontSize:14}}>{v}</div></div>
            ))}
          </div>
          <div className="divider"></div>
          <div className="small mut">※〇〇市の最低制限価格はランダム係数（1.000〜1.010）で決まります。下回ると失格、上げすぎると他社に最安を奪われます。</div>
        </Card>

        <Card icon="target" title="この案件の落札確率" sub="推奨レンジで入れた場合">
          <div className="flex jc"><Gauge value={model.win} color="#1f9d6b" label={model.verdict} sub="基準額 +0.6〜1.0%"/></div>
        </Card>
      </div>

      <div className="grid cols-3 mt">
        <Card className="span-2" icon="yen" title="推奨入札額" sub="御社の戦績データから算出">
          <div className="flex wrap" style={{gap:22,alignItems:"flex-end"}}>
            <div>
              <div className="small mut">推奨入札額（基準+0.6〜1.0%）</div>
              <div className="b tnum" style={{fontSize:34,color:"#157a51",lineHeight:1.1,marginTop:4}}>{Math.round(recLo).toLocaleString()}〜{Math.round(recHi).toLocaleString()}<span style={{fontSize:16}}>万円</span></div>
              <div className="small mut mt-s">およそ {yen(Math.round(recLo))}〜{yen(Math.round(recHi))} 円</div>
            </div>
            <div style={{flex:1,minWidth:200}}>
              <div className="flex jb small"><span className="mut">従来の入れ方（{DATA.record.myAvg}%）</span><span className="b" style={{color:"#bd4321"}}>失格リスク {bidModel(DATA.record.myAvg).disq}%</span></div>
              <div className="bar-track mt-s"><div className="bar-fill" style={{width:bidModel(DATA.record.myAvg).disq+"%",background:"#e05a37"}}></div></div>
              <div className="flex jb small mt"><span className="mut">推奨レンジ（+0.8%）</span><span className="b" style={{color:"#157a51"}}>落札確率 {model.win}%</span></div>
              <div className="bar-track mt-s"><div className="bar-fill" style={{width:model.win+"%",background:"#1f9d6b"}}></div></div>
            </div>
          </div>
        </Card>

        <Card icon="users" title="入札が予想される競合" sub="同ランク・近い価格帯">
          {likely.map(x=>(
            <div className="row-item" key={x.name}>
              <div className="ri-ic" style={{background:"#eaf3fc"}}><Icon name="building"/></div>
              <div className="ri-main"><div className="ri-t" style={{fontSize:13}}>{x.name}</div><div className="ri-s">{x.note}</div></div>
              <div className="ri-r small"><b>経審 {x.kscore}</b><div className="mut">完工 {x.kanko.toLocaleString()}万</div></div>
            </div>
          ))}
          <div className="mt-s"><Btn kind="ghost" sm block iconR="arrow" onClick={()=>go("competitors")}>競合分析を見る</Btn></div>
        </Card>
      </div>
    </div>
  );
}

/* =================== 競合分析 =================== */
function Competitors({ go }){
  const comp=DATA.competitors;
  const me=comp.find(c=>c.me), top=comp[0];
  const norm=(v,mn,mx)=>Math.max(0.08,Math.min(1,(v-mn)/(mx-mn)));
  const axes=["完工高","経常利益","経審点","営業年数","安定性"];
  const radarVal=(c)=>[
    norm(c.kanko,3500,8500), norm(c.profit,-200,1100), norm(c.kscore,640,750),
    norm(c.years,15,35), c.profit<0?0.15:norm(c.profit,-200,1100)*.8+.2,
  ];
  return (
    <div className="page">
      <PageHead ey="Competition" title="競合分析" desc={`${me.rank.cat||"建築一式B級"} 同ランク${comp.length}社。御社は完工高ベースで${me.rank}位相当の実力です`}>
      </PageHead>

      <div className="grid cols-3 mb">
        <Tile tone="orange" icon="award" label="同ランク内の順位" value="3" unit={`位 / ${comp.length}社`} meta="完成工事高ベース"/>
        <Tile tone="blue" icon="trend" label="2位との完工高差" value="983" unit="万" meta="1〜2件の受注で逆転できる射程"/>
        <Tile tone="green" icon="check" label="御社の建築完工高" value="5,106" unit="万" meta="実は2位相当の規模（元請100%）"/>
      </div>

      <div className="grid cols-3 mb">
        <Card className="span-2" icon="chart" title="建築完工高（元請）の比較" sub="同ランク5社・万円">
          <BarsH unit="万" max={9000} height={210}
            items={comp.map(c=>({label:c.name.replace("（御社）",""), value:c.kanko, me:c.me}))}/>
        </Card>
        <Card icon="award" title="総合力の比較" sub="御社 vs 最有力（クラコウ）">
          <Radar axes={axes} series={[
            {values:radarVal(top), color:"#0e2a47", me:false},
            {values:radarVal(me), color:"#f5871f", me:true},
          ]}/>
          <div className="legend center" style={{justifyContent:"center"}}>
            <span><i style={{background:"#f5871f"}}></i>御社</span>
            <span><i style={{background:"#0e2a47"}}></i>クラコウ</span>
          </div>
        </Card>
      </div>

      <Card icon="users" title="同ランク5社の比較" sub="経営事項審査・公表データより">
        <div className="tbl-wrap">
          <table className="tbl">
            <thead><tr><th>順位</th><th>会社</th><th className="num">建築完工高(元請)</th><th className="num">経常利益</th><th className="num">経審点</th><th>ひとこと</th></tr></thead>
            <tbody>
              {comp.map(c=>(
                <tr key={c.rank} className={c.me?"me":""}>
                  <td className="rankn">{c.rank}</td>
                  <td><b>{c.name}</b></td>
                  <td className="num">{c.kanko.toLocaleString()}万</td>
                  <td className={"num "+(c.profit<0?"neg":"pos")}>{c.profit<0?"▲"+Math.abs(c.profit):"+"+c.profit}万</td>
                  <td className="num">{c.kscore}</td>
                  <td className="small">{c.note}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <div className="alert fix mt" style={{borderRadius:14}}>
          <div className="ai"><Icon name="check"/></div>
          <div><div className="at">あと一歩で順位は動きます</div>
          <div className="ab">御社の建築完工高は5社中3位ですが、2位との差はわずか。<b>1〜2件の受注で順位が動く位置</b>にいます。値付けを直して受注を積めば、実力どおり2位が見えてきます。</div></div>
        </div>
      </Card>
    </div>
  );
}

Object.assign(window, { Dashboard, Cases, CaseDetail, Competitors });
