// views.jsx — All main view screens for the Funding Dashboard
// Pulls helpers from components.jsx (registered on window).

const { useState: useStateV, useEffect: useEffectV, useMemo: useMemoV, useRef: useRefV } = React;

// ═══════════════════════════════════════════════════════════════════════════
// OVERVIEW
// ═══════════════════════════════════════════════════════════════════════════
function OverviewView({ go, openOpp }) {
  const opps = window.OPPORTUNITIES;
  const open = opps.filter(o => o.status === "open");
  const totalCeiling = open.reduce((s, o) => s + o.amountMax, 0);
  const closeSoon = open.filter(o => o.daysLeft !== null && o.daysLeft <= 30).sort((a,b)=>a.daysLeft-b.daysLeft);
  const topMatches = [...open].sort((a,b) => b.match - a.match).slice(0, 4);

  return (
    <React.Fragment>
      {/* Hero */}
      <div className="hero fade-in">
        <div className="hero-mesh" />
        <div className="row between" style={{position:"relative", alignItems:"flex-start", gap:24}}>
          <div className="stack gap-12" style={{maxWidth:560}}>
            <div className="row gap-8">
              <Pill tone="accent" dot>Live · {open.length} active</Pill>
              <Pill tone="success">Match engine v2.4</Pill>
            </div>
            <h1 className="h-title" style={{fontSize:34}}>
              Good morning, Tewodros.
              <span className="serif" style={{display:"block", fontStyle:"italic", color:"var(--accent)", fontWeight:400, fontSize:34}}>
                {open.filter(o=>o.match>=85).length} opportunities are a strong match for SuSu today.
              </span>
            </h1>
            <div className="dim" style={{fontSize:14, lineHeight:1.55, maxWidth:520}}>
              We've scanned EU, US, Asian, and multilateral programs against your eligibility profile.
              Strongest fits are in <b style={{color:"var(--text)"}}>digital infrastructure</b>, <b style={{color:"var(--text)"}}>telecom VAS</b>, and <b style={{color:"var(--text)"}}>public-sector modernization</b>.
            </div>
            <div className="row gap-8" style={{marginTop:4}}>
              <button className="btn btn-primary" onClick={()=>go("opportunities")}>
                <Icon d={Icons.spark} size={14} /> Review top matches
              </button>
              <button className="btn" onClick={()=>go("partners")}>
                <Icon d={Icons.users} size={14} /> Find partners
              </button>
            </div>
          </div>

          {/* Right side: Total ceiling display */}
          <div className="stack gap-8" style={{textAlign:"right", minWidth:200, position:"relative"}}>
            <div style={{fontSize:11.5, letterSpacing:".12em", textTransform:"uppercase", color:"var(--text-mute)", fontWeight:600}}>
              Capital surface accessible
            </div>
            <div style={{fontSize:42, fontWeight:600, letterSpacing:"-.03em", lineHeight:1, color:"var(--text)", fontVariantNumeric:"tabular-nums"}}>
              ${(totalCeiling/1_000_000).toFixed(0)}M
            </div>
            <div style={{fontSize:12.5, color:"var(--text-dim)"}}>
              Sum of ceilings · {open.length} active programs
            </div>
            <div className="row gap-6" style={{justifyContent:"flex-end", marginTop:4}}>
              <Pill tone="success" dot>+2 this week</Pill>
            </div>
          </div>
        </div>
      </div>

      {/* KPIs */}
      <div className="grid grid-4">
        <Kpi label="Active opportunities" value={open.length} delta="+2 new this week" deltaTone="success"
             sparkData={[12,13,14,14,15,16,16,17,18,18]} />
        <Kpi label="Closing within 14 days" value={open.filter(o=>o.daysLeft!==null && o.daysLeft<=14).length}
             delta="2 actions required" deltaTone="danger" sparkData={[2,3,2,3,4,3,4,5,4,4]} />
        <Kpi label="Avg. match score" value={`${Math.round(open.reduce((s,o)=>s+o.match,0)/open.length)}%`}
             delta="+3 pts vs last month" deltaTone="success" sparkData={[68,70,72,73,75,76,78,79,80,81]} />
        <Kpi label="In pipeline" value={window.PIPELINE.length} delta="1 awarded · Mastercard"
             deltaTone="info" sparkData={[5,6,6,7,8,8,9,9,10,10]} />
      </div>

      {/* Top matches + Closing soon + Activity */}
      <div className="grid" style={{gridTemplateColumns:"1.4fr .8fr", gap:20}}>
        <div className="card" style={{padding:20}}>
          <SectionHead
            title="Top matches for SuSu"
            kicker="Ranked by fit against your sectors, location, and revenue band"
            right={<button className="btn btn-sm btn-ghost" onClick={()=>go("opportunities")}>View all <Icon d={Icons.arrowRight} size={12}/></button>}
          />
          <div className="stack gap-10">
            {topMatches.map(o => <OppRow key={o.id} opp={o} onClick={()=>openOpp(o)} />)}
          </div>
        </div>

        <div className="stack gap-20">
          {/* Deadlines */}
          <div className="card">
            <SectionHead title="Closing soon" kicker={`${closeSoon.length} within 30 days`} />
            <div className="stack gap-10">
              {closeSoon.slice(0,4).map(o => {
                const dl = fmtDeadline(o);
                return (
                  <div key={o.id} className="row gap-12" onClick={()=>openOpp(o)}
                       style={{cursor:"pointer", padding:"10px 0", borderBottom:"1px solid var(--border)"}}>
                    <div style={{
                      width:46, height:46, borderRadius:10, display:"grid", placeItems:"center",
                      background: `color-mix(in srgb, var(--${dl.urgency}) 12%, var(--surface-2))`,
                      border:`1px solid color-mix(in srgb, var(--${dl.urgency}) 30%, transparent)`
                    }}>
                      <div className="mono" style={{fontSize:16, fontWeight:600, color:`var(--${dl.urgency})`, lineHeight:1}}>
                        {o.daysLeft}
                      </div>
                      <div style={{fontSize:9, color:`var(--${dl.urgency})`, opacity:.7, marginTop:-2}}>DAYS</div>
                    </div>
                    <div className="stack gap-4" style={{flex:1, minWidth:0}}>
                      <div style={{fontSize:13, fontWeight:500, overflow:"hidden", textOverflow:"ellipsis", whiteSpace:"nowrap"}}>{o.name}</div>
                      <div className="dim" style={{fontSize:11.5}}>{o.source} · {fmtAmount(o.amountMin, o.amountMax, o.currency)}</div>
                    </div>
                  </div>
                );
              })}
            </div>
          </div>

          {/* Activity */}
          <div className="card">
            <SectionHead title="Activity" kicker="Last 7 days" />
            <div className="stack gap-12">
              {window.ACTIVITY.slice(0,5).map((a,i) => (
                <div key={i} className="row gap-10" style={{fontSize:12.5}}>
                  <div className="mono" style={{width:32, color:"var(--text-faint)", flexShrink:0}}>{a.ts}</div>
                  <div className="dim" style={{flex:1}}>{a.text}</div>
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>

      {/* Pipeline mini */}
      <div className="card">
        <SectionHead
          title="Pipeline at a glance"
          kicker="Where every active application stands"
          right={<button className="btn btn-sm btn-ghost" onClick={()=>go("pipeline")}>Open board <Icon d={Icons.arrowRight} size={12}/></button>}
        />
        <div className="row gap-12" style={{flexWrap:"wrap"}}>
          {window.STAGES.map(s => {
            const count = window.PIPELINE.filter(p => p.stage === s.id).length;
            return (
              <div key={s.id} className="card" style={{padding:14, minWidth:140, background:"var(--surface-2)", flex:1}}>
                <div style={{fontSize:11, letterSpacing:".1em", textTransform:"uppercase", color:"var(--text-mute)", fontWeight:600}}>{s.label}</div>
                <div className="mono" style={{fontSize:26, fontWeight:600, letterSpacing:"-.02em", marginTop:6}}>{count}</div>
                <div className="dim" style={{fontSize:11.5, marginTop:2}}>{s.blurb}</div>
              </div>
            );
          })}
        </div>
      </div>
    </React.Fragment>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// OPPORTUNITIES
// ═══════════════════════════════════════════════════════════════════════════
function OpportunitiesView({ openOpp, filterRegion, setFilterRegion }) {
  const opps = window.OPPORTUNITIES;
  const [filters, setFilters] = useStateV({
    region: filterRegion || "all",
    type: "all",
    consortium: "all",
    sort: "match",
  });
  useEffectV(() => {
    if (filterRegion && filterRegion !== filters.region) setFilters(f => ({...f, region: filterRegion}));
  }, [filterRegion]);

  const filtered = useMemoV(() => {
    let r = opps.filter(o => o.status === "open");
    if (filters.region !== "all")     r = r.filter(o => o.region === filters.region);
    if (filters.type !== "all")       r = r.filter(o => o.type.toLowerCase().includes(filters.type.toLowerCase()));
    if (filters.consortium === "yes") r = r.filter(o => o.consortium);
    if (filters.consortium === "no")  r = r.filter(o => !o.consortium);
    if (filters.sort === "match")     r.sort((a,b) => b.match - a.match);
    if (filters.sort === "deadline")  r.sort((a,b) => (a.daysLeft ?? 9999) - (b.daysLeft ?? 9999));
    if (filters.sort === "amount")    r.sort((a,b) => b.amountMax - a.amountMax);
    return r;
  }, [filters]);

  const regions = ["all", "EU", "USA", "Asia", "Africa", "Multilateral"];
  const types   = [["all","All types"],["grant","Grants"],["loan","Loans"],["equity","Equity"],["convert","Convertibles"]];

  return (
    <React.Fragment>
      <div className="stack gap-6">
        <div className="h-eyebrow">Funding Opportunities</div>
        <h1 className="h-title">{filtered.length} programs · curated for SuSu</h1>
        <div className="h-kicker">EU · US · Asia · Multilateral · Africa-led — filtered against your eligibility profile</div>
      </div>

      {/* Filter bar */}
      <div className="card" style={{padding:16}}>
        <div className="stack gap-12">
          <div className="row gap-8" style={{flexWrap:"wrap"}}>
            <div style={{fontSize:11, letterSpacing:".1em", textTransform:"uppercase", color:"var(--text-mute)", fontWeight:600, marginRight:6}}>Region</div>
            {regions.map(r => (
              <button key={r} className={"chip" + (filters.region === r ? " on" : "")}
                      onClick={()=>setFilters(f=>({...f, region: r}))}>
                {r === "all" ? "All" : r}
              </button>
            ))}
          </div>
          <div className="row gap-8" style={{flexWrap:"wrap"}}>
            <div style={{fontSize:11, letterSpacing:".1em", textTransform:"uppercase", color:"var(--text-mute)", fontWeight:600, marginRight:6}}>Type</div>
            {types.map(([v,l]) => (
              <button key={v} className={"chip" + (filters.type === v ? " on" : "")}
                      onClick={()=>setFilters(f=>({...f, type: v}))}>{l}</button>
            ))}
            <div style={{width:1, height:24, background:"var(--border)", margin:"0 8px"}} />
            <button className={"chip" + (filters.consortium === "yes" ? " on" : "")}
                    onClick={()=>setFilters(f=>({...f, consortium: f.consortium === "yes" ? "all" : "yes"}))}>
              <Icon d={Icons.users} size={12}/> Consortium-only
            </button>

            <div className="grow" />

            <div className="row gap-6">
              <div style={{fontSize:11, letterSpacing:".1em", textTransform:"uppercase", color:"var(--text-mute)", fontWeight:600}}>Sort</div>
              {[["match","Best match"],["deadline","Deadline"],["amount","Amount"]].map(([v,l]) => (
                <button key={v} className={"chip" + (filters.sort === v ? " on" : "")}
                        onClick={()=>setFilters(f=>({...f, sort: v}))}>{l}</button>
              ))}
            </div>
          </div>
        </div>
      </div>

      {/* Results */}
      <div className="stack gap-10">
        {filtered.map(o => <OppRow key={o.id} opp={o} onClick={()=>openOpp(o)} />)}
        {filtered.length === 0 && (
          <div className="card" style={{textAlign:"center", padding:48, color:"var(--text-mute)"}}>
            No opportunities match these filters.
          </div>
        )}
      </div>
    </React.Fragment>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// MAP (Geographic explorer)
// ═══════════════════════════════════════════════════════════════════════════
const FUNDER_LOCATIONS = [
  // x,y in viewBox 1000x500
  { city: "Brussels",   x: 503, y: 142, region: "EU",          oppIds: ["eu-horizon-aiforafrica","giz-developpp"] },
  { city: "Berlin",     x: 519, y: 145, region: "EU",          oppIds: ["giz-developpp"] },
  { city: "Paris",      x: 494, y: 152, region: "EU",          oppIds: ["proparco-digital-africa"] },
  { city: "Amsterdam",  x: 505, y: 138, region: "EU",          oppIds: ["fmo-ventures"] },
  { city: "Oslo",       x: 510, y: 115, region: "EU",          oppIds: ["norfund-scale"] },
  { city: "Washington", x: 220, y: 195, region: "USA",         oppIds: ["usaid-digital-ecosystem","dfc-direct-loan","gates-foundation-digital","ifc-digital-economy","worldbank-digital-dev"] },
  { city: "Mountain View", x: 145, y: 215, region: "USA",      oppIds: ["google-blackfounders"] },
  { city: "Redmond",    x: 155, y: 175, region: "USA",         oppIds: ["ms-aiforgood"] },
  { city: "Tokyo",      x: 880, y: 218, region: "Asia",        oppIds: ["jica-innovative-asia-africa"] },
  { city: "Seoul",      x: 858, y: 218, region: "Asia",        oppIds: ["koica-innovation"] },
  { city: "Abidjan",    x: 480, y: 300, region: "Africa",      oppIds: ["afdb-digital-transformation"] },
  { city: "Geneva",     x: 506, y: 165, region: "Multilateral", oppIds: ["climate-cif-ethiopia"] },
  { city: "Toronto",    x: 260, y: 175, region: "Multilateral", oppIds: ["mastercard-resilience"] },
  { city: "New York",   x: 248, y: 195, region: "Multilateral", oppIds: ["endeavor-east-africa"] },
];
const ADDIS = { x: 575, y: 282 };

function MapView({ openOpp }) {
  const [active, setActive] = useStateV(null);
  const opps = window.OPPORTUNITIES;

  // Generate land-dots
  const dots = useMemoV(() => {
    const inEllipse = (px, py, cx, cy, rx, ry) =>
      ((px-cx)/rx)**2 + ((py-cy)/ry)**2 < 1;
    const isLand = (x, y) =>
      inEllipse(x, y, 520, 295, 65, 100) ||  // Africa
      inEllipse(x, y, 510, 148, 80, 38)  ||  // Europe
      inEllipse(x, y, 220, 195, 130, 80) ||  // N America
      inEllipse(x, y, 315, 360, 50, 85)  ||  // S America
      inEllipse(x, y, 720, 200, 165, 65) ||  // Asia main
      inEllipse(x, y, 690, 270, 35, 50)  ||  // India
      inEllipse(x, y, 855, 370, 50, 30)  ||  // Australia
      inEllipse(x, y, 380, 95, 35, 35)   ||  // Greenland
      inEllipse(x, y, 875, 220, 18, 30);     // Japan
    const out = [];
    for (let y = 30; y <= 470; y += 9) {
      for (let x = 20; x <= 980; x += 9) {
        if (isLand(x, y)) out.push([x, y]);
      }
    }
    return out;
  }, []);

  // Region counts
  const byRegion = useMemoV(() => {
    const o = { EU:0, USA:0, Asia:0, Africa:0, Multilateral:0 };
    opps.filter(x=>x.status==="open").forEach(x => { o[x.region] = (o[x.region]||0)+1; });
    return o;
  }, []);

  return (
    <React.Fragment>
      <div className="stack gap-6">
        <div className="h-eyebrow">Geographic Explorer</div>
        <h1 className="h-title">Where capital is flowing from</h1>
        <div className="h-kicker">Hover or tap a marker to see programs available to SuSu from that source.</div>
      </div>

      <div className="grid" style={{gridTemplateColumns:"1fr 320px", gap:20}}>
        <div className="map-wrap">
          <svg viewBox="0 0 1000 500" preserveAspectRatio="xMidYMid meet">
            <defs>
              <radialGradient id="addisGlow" cx="50%" cy="50%" r="50%">
                <stop offset="0%" stopColor="var(--accent)" stopOpacity=".6" />
                <stop offset="100%" stopColor="var(--accent)" stopOpacity="0" />
              </radialGradient>
              <filter id="softBlur"><feGaussianBlur stdDeviation="1" /></filter>
            </defs>

            {/* Equator + tropic lines */}
            <line x1="0" y1="250" x2="1000" y2="250" className="grid-line" />
            <line x1="0" y1="180" x2="1000" y2="180" className="grid-line" />
            <line x1="0" y1="320" x2="1000" y2="320" className="grid-line" />
            <line x1="500" y1="0" x2="500" y2="500" className="grid-line" />

            {/* Land dots */}
            {dots.map(([x,y], i) => (
              <circle key={i} cx={x} cy={y} r="1.4"
                      fill={x>460 && x<590 && y>200 && y<385 ? "color-mix(in srgb, var(--accent) 55%, var(--text-mute))" : "var(--text-faint)"}
                      opacity={x>460 && x<590 && y>200 && y<385 ? .85 : .35} />
            ))}

            {/* Arcs from funders to Addis */}
            {FUNDER_LOCATIONS.map((f, i) => {
              const mx = (f.x + ADDIS.x) / 2;
              const my = (f.y + ADDIS.y) / 2 - Math.abs(f.x - ADDIS.x) * 0.25;
              return (
                <path key={i} d={`M ${f.x} ${f.y} Q ${mx} ${my} ${ADDIS.x} ${ADDIS.y}`}
                      className="arc" style={{opacity: active && active.city !== f.city ? .08 : (active ? .6 : .25)}} />
              );
            })}

            {/* Addis glow + marker */}
            <circle cx={ADDIS.x} cy={ADDIS.y} r="40" fill="url(#addisGlow)" />
            <circle cx={ADDIS.x} cy={ADDIS.y} r="6" fill="var(--accent)"
                    stroke="var(--bg)" strokeWidth="2" filter="url(#softBlur)" />
            <circle cx={ADDIS.x} cy={ADDIS.y} r="6" fill="var(--accent)" />
            <text x={ADDIS.x + 12} y={ADDIS.y + 4} fill="var(--accent)" fontSize="11" fontWeight="600"
                  fontFamily="var(--font-sans)">Addis Ababa · SuSu HQ</text>

            {/* Funder markers */}
            {FUNDER_LOCATIONS.map(f => {
              const tone = ({ EU:"var(--info)", USA:"var(--purple)", Asia:"var(--teal)", Africa:"var(--accent)", Multilateral:"var(--success)" })[f.region];
              const isOn = active?.city === f.city;
              return (
                <g key={f.city} className="marker" onMouseEnter={()=>setActive(f)} onMouseLeave={()=>setActive(null)}>
                  <circle cx={f.x} cy={f.y} r={isOn ? 10 : 8} fill={tone} opacity=".18" className="marker-pulse" />
                  <circle cx={f.x} cy={f.y} r="4" fill={tone} stroke="var(--surface-1)" strokeWidth="1.5" />
                  {isOn && (
                    <g>
                      <rect x={f.x + 8} y={f.y - 22} width="100" height="36" rx="6"
                            fill="var(--surface-1)" stroke="var(--border-strong)" />
                      <text x={f.x + 16} y={f.y - 8} fill="var(--text)" fontSize="10" fontWeight="600">{f.city}</text>
                      <text x={f.x + 16} y={f.y + 5} fill="var(--text-dim)" fontSize="9">{f.oppIds.length} programs</text>
                    </g>
                  )}
                </g>
              );
            })}
          </svg>

          {/* Legend overlay */}
          <div style={{position:"absolute", bottom:14, left:14, display:"flex", gap:8, flexWrap:"wrap"}}>
            {[["EU","info"],["USA","purple"],["Asia","teal"],["Africa","accent"],["Multilateral","success"]].map(([r,t]) => (
              <Pill key={r} tone={t} dot>{r}</Pill>
            ))}
          </div>
        </div>

        {/* Side panel: region summary */}
        <div className="stack gap-14">
          <div className="card">
            <div className="stack gap-12">
              <div className="h-eyebrow">By region</div>
              {Object.entries(byRegion).map(([region, count]) => {
                const max = Math.max(...Object.values(byRegion));
                return (
                  <div key={region} className="stack gap-6">
                    <div className="row between">
                      <Pill tone={regionTone(region)} dot>{region}</Pill>
                      <span className="mono dim" style={{fontSize:12}}>{count} programs</span>
                    </div>
                    <div className="prog-bar"><span style={{width:`${(count/max)*100}%`, background:`var(--${regionTone(region)==="accent"?"accent":regionTone(region)})`}} /></div>
                  </div>
                );
              })}
            </div>
          </div>

          <div className="card">
            <div className="stack gap-10">
              <div className="h-eyebrow">Spotlight</div>
              {active ? (
                <div className="stack gap-10 fade-in">
                  <div style={{fontWeight:600, fontSize:15}}>{active.city}</div>
                  <Pill tone={regionTone(active.region)} dot>{active.region}</Pill>
                  <div className="dim" style={{fontSize:12.5}}>{active.oppIds.length} program(s) available from this source.</div>
                  <div className="stack gap-6">
                    {active.oppIds.map(id => {
                      const o = opps.find(x => x.id === id);
                      if (!o) return null;
                      return (
                        <button key={id} className="btn btn-sm btn-ghost" style={{justifyContent:"space-between"}}
                                onClick={()=>openOpp(o)}>
                          <span style={{textAlign:"left", overflow:"hidden", textOverflow:"ellipsis", whiteSpace:"nowrap"}}>{o.name}</span>
                          <Icon d={Icons.arrowUpRight} size={12} />
                        </button>
                      );
                    })}
                  </div>
                </div>
              ) : (
                <div className="dim" style={{fontSize:12.5, lineHeight:1.6}}>
                  Hover a marker on the map to inspect programs originating from that city.
                  Animated arcs trace flows toward your HQ in Addis Ababa.
                </div>
              )}
            </div>
          </div>
        </div>
      </div>
    </React.Fragment>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// PIPELINE (Kanban)
// ═══════════════════════════════════════════════════════════════════════════
function PipelineView({ openOpp, pipeline: pipelineProp, movePipeline, addBestAvailable }) {
  const stages = window.STAGES;
  const pipeline = pipelineProp || window.PIPELINE;
  const opps = window.OPPORTUNITIES;
  const [owner, setOwner] = useStateV("all");
  const [dropStage, setDropStage] = useStateV(null);
  const owners = useMemoV(() => ["all", ...new Set(pipeline.map(p => p.owner).filter(Boolean))], [pipeline]);
  const visiblePipeline = owner === "all" ? pipeline : pipeline.filter(p => p.owner === owner);
  const moveItem = movePipeline || (() => {});

  return (
    <React.Fragment>
      <div className="row between" style={{alignItems:"flex-end", flexWrap:"wrap", gap:12}}>
        <div className="stack gap-6">
          <div className="h-eyebrow">Pipeline</div>
          <h1 className="h-title">Application board</h1>
          <div className="h-kicker">Track every application's stage, owner, and last update.</div>
        </div>
        <div className="row gap-8">
          <button className="btn btn-primary" onClick={addBestAvailable}><Icon d={Icons.plus} size={14} /> Add best match</button>
        </div>
      </div>

      <div className="row gap-8" style={{flexWrap:"wrap"}}>
        <div style={{fontSize:11, letterSpacing:".1em", textTransform:"uppercase", color:"var(--text-mute)", fontWeight:600, marginRight:6}}>Owner</div>
        {owners.map(o => (
          <button key={o} className={"chip" + (owner === o ? " on" : "")} onClick={() => setOwner(o)}>
            {o === "all" ? "All owners" : o}
          </button>
        ))}
      </div>

      <div className="kanban">
        {stages.map(stage => {
          const items = visiblePipeline.filter(p => p.stage === stage.id);
          const tone = ({ identified:"info", researching:"warning", drafting:"purple", submitted:"teal", won:"success" })[stage.id];
          return (
            <div
              key={stage.id}
              className={"kcol" + (dropStage === stage.id ? " drop-on" : "")}
              onDragOver={(e) => { e.preventDefault(); setDropStage(stage.id); }}
              onDragLeave={() => setDropStage(null)}
              onDrop={(e) => {
                e.preventDefault();
                const id = e.dataTransfer.getData("text/plain");
                if (id) moveItem(id, stage.id);
                setDropStage(null);
              }}
            >
              <div className="kcol-head">
                <div className="row gap-8">
                  <Pill tone={tone} dot>{stage.label}</Pill>
                  <span className="mono dim" style={{fontSize:12}}>{items.length}</span>
                </div>
                <button className="icon-btn" style={{width:24, height:24}} onClick={addBestAvailable}><Icon d={Icons.plus} size={12}/></button>
              </div>
              <div style={{fontSize:11.5, color:"var(--text-mute)"}}>{stage.blurb}</div>
              <div className="stack gap-8">
                {items.map(p => {
                  const o = opps.find(x => x.id === p.oppId);
                  if (!o) return null;
                  const dl = fmtDeadline(o);
                  return (
                    <div
                      key={p.id}
                      className="kcard"
                      draggable
                      onDragStart={(e) => e.dataTransfer.setData("text/plain", p.id)}
                      onClick={()=>openOpp(o)}
                    >
                      <div className="row gap-8" style={{alignItems:"flex-start"}}>
                        <div style={{fontSize:20, lineHeight:1}}>{o.flag}</div>
                        <div className="stack gap-4" style={{flex:1, minWidth:0}}>
                          <div style={{fontSize:13, fontWeight:600, lineHeight:1.3}}>{o.name}</div>
                          <div className="dim" style={{fontSize:11}}>{o.source}</div>
                        </div>
                      </div>
                      <div className="row between" style={{fontSize:11.5}}>
                        <span className="mono dim">{fmtAmount(o.amountMin, o.amountMax, o.currency)}</span>
                        <span style={{color: dl.urgency==="mute"?"var(--text-mute)":`var(--${dl.urgency})`}}>{dl.label}</span>
                      </div>
                      <div className="row between" style={{paddingTop:6, borderTop:"1px solid var(--border)", fontSize:11}}>
                        <div className="row gap-6 dim">
                          <Icon d={Icons.user} size={11}/> {p.owner}
                        </div>
                        <select
                          className="stage-select"
                          value={p.stage}
                          onClick={(e) => e.stopPropagation()}
                          onChange={(e) => moveItem(p.id, e.target.value)}
                        >
                          {stages.map(s => <option key={s.id} value={s.id}>{s.label}</option>)}
                        </select>
                      </div>
                      <div className="mute" style={{fontSize:10.5}}>{p.updated}</div>
                    </div>
                  );
                })}
                {items.length === 0 && (
                  <div style={{fontSize:11.5, color:"var(--text-faint)", padding:"24px 0", textAlign:"center", border:"1px dashed var(--border)", borderRadius:8}}>
                    Drop here
                  </div>
                )}
              </div>
            </div>
          );
        })}
      </div>
    </React.Fragment>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// PARTNERS
// ═══════════════════════════════════════════════════════════════════════════
function PartnersView({ onRequestIntro, introRequests = [], bookmarks = [], onToggleBookmark }) {
  const partners = window.PARTNERS;
  const [filter, setFilter] = useStateV("all");
  const requestIntro = onRequestIntro || (() => {});
  const toggleBookmark = onToggleBookmark || (() => {});

  const filtered = useMemoV(() => {
    if (filter === "all") return partners;
    if (filter === "ready") return partners.filter(p => p.consortiumReady);
    return partners.filter(p => p.type === filter);
  }, [filter]);

  return (
    <React.Fragment>
      <div className="stack gap-6">
        <div className="h-eyebrow">Partner Finder</div>
        <h1 className="h-title">Build winning consortia</h1>
        <div className="h-kicker">Discover tech partners, research institutes, and co-investors with proven funding tracks.</div>
      </div>

      <div className="row gap-8" style={{flexWrap:"wrap"}}>
        {[["all","All partners"],["ready","Consortium-ready"],["Tech Partner","Tech partners"],["Research","Research orgs"],["Investor","Investors"],["Implementer","Implementers"],["Catalyst","Catalysts"]].map(([v,l]) => (
          <button key={v} className={"chip" + (filter === v ? " on" : "")} onClick={()=>setFilter(v)}>{l}</button>
        ))}
      </div>

      <div className="grid grid-3">
        {filtered.map(p => (
          <div key={p.id} className={"partner-card" + (bookmarks.includes(`partner:${p.id}`) ? " is-saved" : "")}>
            <div className="row between" style={{alignItems:"flex-start"}}>
              <div className="row gap-10">
                <div style={{fontSize:32, lineHeight:1}}>{p.flag}</div>
                <div className="stack gap-2">
                  <div style={{fontWeight:600, fontSize:14.5, lineHeight:1.2}}>{p.name}</div>
                  <div className="dim" style={{fontSize:12}}>{p.country} · {p.size}</div>
                </div>
              </div>
              <MatchRing score={p.match} size={36} stroke={3.5}/>
            </div>
            <div className="dim" style={{fontSize:12.5, lineHeight:1.5}}>{p.blurb}</div>
            <div className="row gap-6" style={{flexWrap:"wrap"}}>
              <Pill tone="info">{p.type}</Pill>
              {p.consortiumReady && <Pill tone="success" dot>Consortium-ready</Pill>}
            </div>
            <div className="stack gap-6">
              <div style={{fontSize:10.5, letterSpacing:".1em", textTransform:"uppercase", color:"var(--text-mute)", fontWeight:600}}>Expertise</div>
              <div className="row gap-6" style={{flexWrap:"wrap"}}>
                {p.expertise.map(e => (
                  <span key={e} style={{fontSize:11, padding:"2px 8px", background:"var(--surface-3)", borderRadius:6, color:"var(--text-dim)"}}>{e}</span>
                ))}
              </div>
            </div>
            <div className="stack gap-6">
              <div style={{fontSize:10.5, letterSpacing:".1em", textTransform:"uppercase", color:"var(--text-mute)", fontWeight:600}}>Past funders</div>
              <div className="row gap-6" style={{flexWrap:"wrap"}}>
                {p.pastFunders.map(f => <Pill key={f} tone="purple">{f}</Pill>)}
              </div>
            </div>
            <div className="row gap-8" style={{marginTop:4, paddingTop:12, borderTop:"1px solid var(--border)"}}>
              <button
                className="btn btn-sm btn-primary"
                style={{flex:1, justifyContent:"center"}}
                disabled={introRequests.includes(p.id)}
                onClick={() => requestIntro(p)}
              >
                <Icon d={introRequests.includes(p.id) ? Icons.check : Icons.send} size={12}/>
                {introRequests.includes(p.id) ? "Intro requested" : "Request intro"}
              </button>
              <button
                className={"btn btn-sm btn-ghost" + (bookmarks.includes(`partner:${p.id}`) ? " is-on" : "")}
                onClick={() => toggleBookmark("partner", p.id, p.name)}
                title={bookmarks.includes(`partner:${p.id}`) ? "Remove bookmark" : "Save partner"}
              >
                <Icon d={Icons.bookmark} size={12}/>
              </button>
            </div>
          </div>
        ))}
      </div>
    </React.Fragment>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// PROFILE (SuSu company info)
// ═══════════════════════════════════════════════════════════════════════════
function ProfileView({ onExportProfile }) {
  const p = window.SUSU_PROFILE;
  const eligible = window.OPPORTUNITIES.filter(o => o.match >= 70 && o.status === "open").length;
  const exportBrief = () => {
    const brief = {
      generatedAt: new Date().toISOString(),
      company: p,
      eligibilityStrength: `${eligible}/${window.OPPORTUNITIES.length}`,
      strongestMatches: window.OPPORTUNITIES
        .filter(o => o.match >= 80 && o.status === "open")
        .sort((a, b) => b.match - a.match)
        .map(o => ({
          name: o.name,
          source: o.source,
          amount: fmtAmount(o.amountMin, o.amountMax, o.currency),
          deadline: o.deadline,
          match: o.match,
          fit: o.fit,
        })),
    };
    const blob = new Blob([JSON.stringify(brief, null, 2)], { type: "application/json" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = "susu-eligibility-brief.json";
    a.click();
    window.setTimeout(() => URL.revokeObjectURL(url), 500);
    onExportProfile?.();
  };

  return (
    <React.Fragment>
      <div className="hero" style={{padding:"32px 32px 28px"}}>
        <div className="hero-mesh"/>
        <div className="row" style={{position:"relative", alignItems:"flex-start", gap:24, flexWrap:"wrap"}}>
          <div className="brand-mark" style={{width:64, height:64, borderRadius:18}}/>
          <div className="stack gap-10" style={{flex:1, minWidth:300}}>
            <div className="h-eyebrow">Company profile</div>
            <h1 className="h-title" style={{fontSize:32}}>{p.name}</h1>
            <div className="serif" style={{fontStyle:"italic", color:"var(--accent)", fontSize:18, lineHeight:1.3}}>
              {p.tagline}
            </div>
            <div className="row gap-12" style={{flexWrap:"wrap", marginTop:6}}>
              <span className="dim" style={{fontSize:13}}>📍 {p.location}</span>
              <span style={{color:"var(--text-faint)"}}>·</span>
              <span className="dim" style={{fontSize:13}}>🌐 {p.website}</span>
              <span style={{color:"var(--text-faint)"}}>·</span>
              <span className="dim" style={{fontSize:13}}>✉ {p.email}</span>
            </div>
          </div>
          <div className="stack gap-8" style={{minWidth:180}}>
            <div style={{fontSize:11.5, letterSpacing:".12em", textTransform:"uppercase", color:"var(--text-mute)", fontWeight:600}}>Eligibility strength</div>
            <div style={{fontSize:36, fontWeight:600, color:"var(--success)", letterSpacing:"-.025em", lineHeight:1, fontVariantNumeric:"tabular-nums"}}>
              {eligible}<span style={{color:"var(--text-mute)", fontSize:20}}>/{window.OPPORTUNITIES.length}</span>
            </div>
            <div className="dim" style={{fontSize:12}}>programs you'll qualify for</div>
            <button className="btn btn-sm" style={{marginTop:8}} onClick={exportBrief}><Icon d={Icons.doc} size={12}/> Export eligibility brief</button>
          </div>
        </div>
      </div>

      {/* Pillars */}
      <div>
        <SectionHead title="The four-S brand pillars" kicker="How SuSu operates — and how funders see you" />
        <div className="grid grid-4">
          {p.pillars.map((pl, i) => (
            <div key={i} className="pillar">
              <div className="pillar-letter">{pl.letter}</div>
              <div style={{position:"relative", zIndex:1}}>
                <div className="h-eyebrow" style={{color:"var(--accent)"}}>Pillar {i+1}</div>
                <div style={{fontSize:20, fontWeight:600, letterSpacing:"-.01em", marginTop:6}}>{pl.name}</div>
                <div className="dim" style={{fontSize:12.5, marginTop:8, lineHeight:1.55}}>{pl.blurb}</div>
              </div>
            </div>
          ))}
        </div>
      </div>

      {/* Profile facts grid */}
      <div className="grid" style={{gridTemplateColumns:"1fr 1fr", gap:20}}>
        <div className="card">
          <SectionHead title="Eligibility profile" kicker="What funders see in their first scan"/>
          <div className="stack gap-10">
            {[
              ["Incorporated in",  p.eligibility.incorporated],
              ["Region",           p.eligibility.region],
              ["Size tier",        p.eligibility.sizeTier],
              ["Revenue band",     p.eligibility.revenueBand],
              ["Operational since", `${p.founded} · ${p.eligibility.yearsActive} yrs`],
              ["Team size",        `${p.team} people`],
            ].map(([k,v]) => (
              <div key={k} className="row between" style={{padding:"8px 0", borderBottom:"1px solid var(--border)"}}>
                <span className="dim" style={{fontSize:12.5}}>{k}</span>
                <span style={{fontSize:13, fontWeight:500}}>{v}</span>
              </div>
            ))}
            <div className="row between" style={{padding:"8px 0"}}>
              <span className="dim" style={{fontSize:12.5}}>Certifications</span>
              <div className="row gap-6">
                {p.eligibility.certifications.map(c => <Pill key={c} tone="info">{c}</Pill>)}
              </div>
            </div>
          </div>
        </div>

        <div className="card">
          <SectionHead title="Sectors & service lines" kicker="Used for opportunity matching"/>
          <div className="stack gap-10">
            <div className="row gap-6" style={{flexWrap:"wrap"}}>
              {p.sectors.map(s => <Pill key={s} tone="accent">{s}</Pill>)}
            </div>
            <div style={{height:1, background:"var(--border)", margin:"8px 0"}}/>
            <div className="h-eyebrow">Serves</div>
            <div className="row gap-6" style={{flexWrap:"wrap"}}>
              {p.serves.map(s => <Pill key={s} tone="purple">{s}</Pill>)}
            </div>
            <div style={{height:1, background:"var(--border)", margin:"8px 0"}}/>
            <div className="h-eyebrow">Reference projects</div>
            <div className="stack gap-6">
              {["EthSwitch — IP Telephony Modernization","AATMA — Datacenter & Network","PSSSA — AV & Cinema Hall","Kiyatech — eLearning Platform","CIPE East Africa — Office Network"].map(prj => (
                <div key={prj} className="row gap-8" style={{fontSize:12.5}}>
                  <Icon d={Icons.check} size={12} className="" />
                  <span>{prj}</span>
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>
    </React.Fragment>
  );
}

// ─── Opp detail drawer body (used inside Drawer) ────────────────────────────
function OppDetail({ opp, onClose, onAddToPipeline, inPipeline, bookmarked, onToggleBookmark }) {
  if (!opp) return null;
  const dl = fmtDeadline(opp);
  return (
    <React.Fragment>
      <div className="drawer-head">
        <div className="row between">
          <div className="row gap-12">
            <div className="opp-flag" style={{width:56, height:56, fontSize:36}}>{opp.flag}</div>
            <div className="stack gap-6">
              <div className="row gap-6">
                <Pill tone={regionTone(opp.region)} dot>{opp.region}</Pill>
                <Pill tone={typeTone(opp.type)}>{opp.type}</Pill>
                {opp.consortium && <Pill tone="purple">Consortium</Pill>}
              </div>
              <div style={{fontSize:11, color:"var(--text-mute)", letterSpacing:".05em"}}>{opp.source}</div>
            </div>
          </div>
          <button className="icon-btn" onClick={onClose}><Icon d={Icons.x} size={14}/></button>
        </div>
        <h2 style={{margin:0, fontSize:22, fontWeight:600, letterSpacing:"-.01em", lineHeight:1.2}}>{opp.name}</h2>
      </div>

      <div className="drawer-body">
        <div className="grid grid-3" style={{gap:14, marginBottom:24}}>
          <div className="card" style={{padding:14, background:"var(--surface-2)"}}>
            <div className="h-eyebrow">Amount</div>
            <div className="mono" style={{fontSize:18, fontWeight:600, marginTop:6}}>{fmtAmount(opp.amountMin, opp.amountMax, opp.currency)}</div>
          </div>
          <div className="card" style={{padding:14, background:"var(--surface-2)"}}>
            <div className="h-eyebrow">Deadline</div>
            <div className="mono" style={{fontSize:18, fontWeight:600, marginTop:6,
                color: dl.urgency==="mute"?"var(--text)":`var(--${dl.urgency})`}}>
              {dl.label}
            </div>
            {opp.deadline !== "rolling" && <div className="dim" style={{fontSize:11, marginTop:2}}>{opp.deadline}</div>}
          </div>
          <div className="card" style={{padding:14, background:"var(--surface-2)", display:"flex", alignItems:"center", gap:12}}>
            <MatchRing score={opp.match} size={44} stroke={4.5}/>
            <div className="stack gap-2">
              <div className="h-eyebrow">Match</div>
              <div style={{fontSize:12.5, color:"var(--text-dim)"}}>SuSu fit score</div>
            </div>
          </div>
        </div>

        <div className="stack gap-22">
          <div>
            <div className="h-eyebrow" style={{marginBottom:8}}>Overview</div>
            <div style={{fontSize:13.5, lineHeight:1.65, color:"var(--text)"}}>{opp.summary}</div>
          </div>

          <div>
            <div className="h-eyebrow" style={{marginBottom:8}}>Eligibility</div>
            <div className="stack gap-8">
              {opp.eligibility.map((e,i) => (
                <div key={i} className="row gap-10" style={{fontSize:13, lineHeight:1.5}}>
                  <div style={{width:18, height:18, borderRadius:"50%", background:"var(--success-soft)", color:"var(--success)", display:"grid", placeItems:"center", flexShrink:0, marginTop:1}}>
                    <Icon d={Icons.check} size={10} stroke={2.4}/>
                  </div>
                  <span>{e}</span>
                </div>
              ))}
            </div>
          </div>

          <div>
            <div className="h-eyebrow" style={{marginBottom:8}}>Why SuSu fits</div>
            <div className="stack gap-8">
              {opp.fit.map((f,i) => (
                <div key={i} className="row gap-10" style={{fontSize:13, lineHeight:1.5}}>
                  <div style={{width:18, height:18, borderRadius:"50%", background:"var(--accent-soft)", color:"var(--accent)", display:"grid", placeItems:"center", flexShrink:0, marginTop:1}}>
                    <Icon d={Icons.spark} size={10} stroke={2.2}/>
                  </div>
                  <span>{f}</span>
                </div>
              ))}
            </div>
          </div>

          <div>
            <div className="h-eyebrow" style={{marginBottom:8}}>Sectors</div>
            <div className="row gap-6" style={{flexWrap:"wrap"}}>
              {opp.sectors.map(s => <Pill key={s} tone="info">{s}</Pill>)}
            </div>
          </div>
        </div>
      </div>

      <div className="drawer-foot">
        <button className={"btn btn-ghost" + (bookmarked ? " is-on" : "")} onClick={onToggleBookmark}>
          <Icon d={Icons.bookmark} size={14}/> {bookmarked ? "Saved" : "Save"}
        </button>
        <button className="btn btn-ghost" onClick={onAddToPipeline} disabled={inPipeline}>
          <Icon d={inPipeline ? Icons.check : Icons.layers} size={14}/> {inPipeline ? "In pipeline" : "Add to pipeline"}
        </button>
        <a className="btn btn-primary" href={opp.url} target="_blank" rel="noopener">
          Open application <Icon d={Icons.external} size={14}/>
        </a>
      </div>
    </React.Fragment>
  );
}

Object.assign(window, { OverviewView, OpportunitiesView, MapView, PipelineView, PartnersView, ProfileView, OppDetail });
