// Screens 3/3: Sim Setup, Sim Results, ERP, ECO, Approvals

const { useState: uS3, useEffect: uE3, useMemo: uM3 } = React;

// ---------- SIM SETUP ----------
function ScreenSimSetup() {
  const tenant = useActiveTenant();
  const [domain, setDomain] = uS3("structural");
  const [bcs, setBcs] = uS3({ fix: true, load: true, symm: false, thermal: false });
  const [meshSz, setMeshSz] = uS3(2.5);
  const [refn, setRefn] = uS3(3);
  const isPump = !!(tenant && tenant.tenant && tenant.tenant.id === "tritan");
  if (isPump) {
    return (
      <div style={{ padding: 28, height: "100%", display: "flex", alignItems: "center", justifyContent: "center" }}>
        <div style={{ maxWidth: 540, textAlign: "center" }}>
          <div className="serif" style={{ fontSize: 28, lineHeight: 1.15, marginBottom: 10 }}>
            Simulation library coming online
          </div>
          <div className="muted" style={{ fontSize: 14, marginBottom: 18 }}>
            Pump CDMO uses physical test gates instead. See Quality Gates for the 30-point CTQ flow already published for {(tenant.program && tenant.program.code) || "this program"}.
          </div>
          <Btn size="sm" variant="primary" icon="Check" onClick={function() { if (typeof navigate === "function") navigate("/build/gates"); else window.location.hash = "/build/gates"; }}>
            See Quality Gates
          </Btn>
        </div>
      </div>
    );
  }

  const domains = [
    { id: "structural", label: "Structural · FEA", icon: "Box",  blurb: "Linear/nonlinear statics, modal, buckling" },
    { id: "thermal",    label: "Thermal",          icon: "Fire", blurb: "Steady, transient, conjugate HT" },
    { id: "cfd",        label: "CFD",              icon: "Wind", blurb: "URANS, LES, multiphase" },
    { id: "em",         label: "Electromagnetics", icon: "Magnet", blurb: "Magnetostatic, eddy, time-step" },
    { id: "vibration",  label: "Vibration / NVH",  icon: "Wave", blurb: "Harmonic, random, modal sup." },
    { id: "mbd",        label: "Multi-body dyn.",  icon: "Layers", blurb: "Rigid + flex bodies" },
    { id: "coupled",    label: "Coupled (FSI/TS)", icon: "Link", blurb: "Co-sim orchestration" },
  ];

  return (
    <div style={{ padding: 14, display: "grid", gridTemplateColumns: "220px minmax(0, 1fr) 240px", gap: 14, minHeight: 0, height: "100%" }}>
      <Panel title="Physics">
        <div style={{ padding: 8 }}>
          {domains.map(d => {
            const _domainRowStyle = {
              display: "grid", gridTemplateColumns: "24px 1fr", gap: 8, padding: "10px 8px", cursor: "pointer",
              borderLeft: `2px solid ${d.id===domain?"var(--accent)":"transparent"}`,
              background: d.id===domain?"var(--bg-2)":"transparent", borderRadius: 4,
            };
            return (
            <div key={d.id} role="button" tabIndex={0} onClick={()=>setDomain(d.id)} onKeyDown={(e)=>{ if(e.key==="Enter"||e.key===" "){ e.preventDefault(); setDomain(d.id); } }} style={_domainRowStyle}>
              <div style={{ color: d.id===domain?"var(--accent)":"var(--ink-3)" }}>{I(d.icon,{size:16})}</div>
              <div>
                <div style={{ fontSize: 12, color: "var(--ink)" }}>{d.label}</div>
                <div className="muted" style={{ fontSize: 12 }}>{d.blurb}</div>
              </div>
            </div>
            );
          })}
        </div>
      </Panel>

      <Panel title="Study · Blade · Modal" right={<>
        <Tag>SIM-0412</Tag>
        <Btn size="sm" icon="Play" variant="primary" disabled title="coming in v2">Submit to cluster</Btn>
      </>}>
        <div style={{ display: "grid", gridTemplateRows: "300px 1fr", height: "100%" }}>
          <div style={{ position: "relative", borderBottom: "1px solid var(--line-soft)", background: "var(--bg-inset)", overflow: "hidden" }}>
            <MeshScene domain={domain} bcs={bcs} refn={refn}/>
            <div style={{ position: "absolute", top: 10, left: 10, display: "flex", gap: 6 }}>
              <Pill tone="accent">{domain.toUpperCase()}</Pill>
              <Pill>mesh · ~{(1.0 + (5-meshSz)*0.4 + refn*0.3).toFixed(2)}M tets</Pill>
            </div>
            <div style={{ position: "absolute", bottom: 10, right: 10 }} className="mono" >
              <span className="pill"><span className="dot"/>preview · sampled 8%</span>
            </div>
          </div>

          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14, padding: 14 }}>
            <div>
              <div className="label">Boundary conditions</div>
              <div style={{ marginTop: 6 }}>
                {Object.entries({
                  fix: "Fixed support · root flange",
                  load: "Distributed pressure · suction side",
                  symm: "Symmetry plane · y=0",
                  thermal: "Convective · 22°C film",
                }).map(([k, v]) => (
                  <label key={k} style={{ display: "grid", gridTemplateColumns: "18px 1fr", gap: 8, padding: "6px 0",
                    borderBottom: "1px solid var(--line-soft)", cursor: "pointer" }}>
                    <input id="sim-f1" name="sim-f1" type="checkbox" checked={bcs[k]} onChange={e=>setBcs(prev => ({...prev, [k]: e.target.checked}))} style={{ accentColor: "var(--accent)" }}/>
                    <span style={{ color: bcs[k]?"var(--ink)":"var(--ink-3)", fontSize: 12 }}>{v}</span>
                  </label>
                ))}
              </div>
              <div className="label" style={{ marginTop: 12 }}>Material model</div>
              <div style={{ padding: 8, border: "1px solid var(--line-soft)", borderRadius: 4, marginTop: 6 }}>
                <KV k="Material"  v="CFRP L-7 (orthotropic)" />
                <KV k="E1 / E2"   v="135 / 9.5 GPa" />
                <KV k="ν12 / G12" v="0.32 / 5.1 GPa" />
                <KV k="Density"   v="1560 kg/m³" />
              </div>
            </div>
            <div>
              <div className="label">Mesh</div>
              <SliderRow label="Element size" unit="mm" v={meshSz} setV={setMeshSz} min={0.5} max={6} step={0.1}/>
              <SliderRow label="Local refinement" unit="lvl" v={refn} setV={setRefn} min={0} max={5} step={1}/>
              <div style={{ display: "grid", gridTemplateColumns: "repeat(3,1fr)", gap: 8, marginTop: 8 }}>
                {[["Elements", "1.24M"], ["Min Jacobian", "0.38"], ["Aspect p95", "8.9"]].map(([k,v])=>
                  <div key={k} style={{ padding: 8, border: "1px solid var(--line-soft)", borderRadius: 4 }}>
                    <div className="label">{k}</div>
                    <div className="mono tnum" style={{ fontSize: 14 }}>{v}</div>
                  </div>)}
              </div>
              <div className="label" style={{ marginTop: 12 }}>Solver</div>
              <div style={{ padding: 8, border: "1px solid var(--line-soft)", borderRadius: 4, marginTop: 6 }}>
                <KV k="Type"       v="Modal · Lanczos" />
                <KV k="Modes"      v="1–40" />
                <KV k="Precision"  v="Double" />
                <KV k="Cores / GPU" v="48 / 0" />
              </div>
            </div>
          </div>
        </div>
      </Panel>

      <Panel title="Compute estimate">
        <div style={{ padding: 12 }}>
          <div className="label">Est. runtime</div>
          <div className="serif" style={{ fontSize: 32 }}>12m 40s</div>
          <div className="muted" style={{ fontSize: 12, marginTop: -2 }}>± 2m · historical model</div>

          <div className="hr"/>
          <KV k="Cluster"   v="forge-hpc-eu-1" />
          <KV k="Queue"     v="priority · modal" />
          <KV k="Cores"     v="48" />
          <KV k="Peak RAM"  v="62 GB" />
          <KV k="I/O est."  v="8.4 GB scratch" />

          <div className="hr"/>
          <div className="label">License check</div>
          <div style={{ marginTop: 6, display: "flex", flexDirection: "column", gap: 4 }}>
            <div style={{ display: "flex", justifyContent: "space-between" }}><span style={{ fontSize: 12 }}>STRUCT-Pro</span><Pill tone="ok">4/8 free</Pill></div>
            <div style={{ display: "flex", justifyContent: "space-between" }}><span style={{ fontSize: 12 }}>SOLVE-Direct</span><Pill tone="ok">2/2 free</Pill></div>
            <div style={{ display: "flex", justifyContent: "space-between" }}><span style={{ fontSize: 12 }}>HPC-NODE-48</span><Pill tone="warn">wait ~90s</Pill></div>
          </div>

          <div className="hr"/>
          <div className="label">Post-run hooks</div>
          {(() => {
            const tenantId = tenant && tenant.tenant && tenant.tenant.id;
            const heroPart = (tenant && tenant.parts && tenant.parts[1]) ? tenant.parts[1].num : "—";
            const slackChan = ({
              tritan: "#m27418-pump",
              aetherion: "#kestrel-3",
              mittelstand: "#mtl-220-mahle",
            })[tenantId] || "#program";
            return (
              <div className="mono" style={{ fontSize: 12, color: "var(--ink-2)", marginTop: 4 }}>
                <div>→ write report to ECO-2611</div>
                <div>{"→ attach modes 1–10 to " + heroPart}</div>
                <div>{"→ notify " + slackChan}</div>
              </div>
            );
          })()}
        </div>
      </Panel>
    </div>
  );
}

function SliderRow({ label, v, setV, min, max, step, unit }) {
  return (
    <div style={{ marginTop: 6 }}>
      <div style={{ display: "flex", justifyContent: "space-between" }}>
        <span className="label">{label}</span>
        <span className="mono tnum" style={{ fontSize: 12 }}>{v} <span className="muted">{unit}</span></span>
      </div>
      <input id="sim-f2" name="sim-f2" type="range" value={v} min={min} max={max} step={step} onChange={e=>setV(+e.target.value)}
        style={{ width: "100%", accentColor: "var(--accent)" }}/>
    </div>
  );
}

function MeshScene({ domain, bcs, refn }) {
  // domain-specific decorative scene
  const colors = {
    structural: "var(--accent)", thermal: "var(--err)", cfd: "var(--cool)",
    em: "var(--info)", vibration: "var(--warn)", mbd: "var(--ok)", coupled: "var(--accent)"
  };
  const c = colors[domain] || "var(--accent)";
  return (
    <svg viewBox="0 0 900 300" preserveAspectRatio="xMidYMid meet" style={{ width: "100%", height: "100%" }}>
      {/* blade */}
      <g transform="translate(450,150) rotate(-8)">
        <path d="M -340 0 C -320 -22, -80 -28, 180 -14 C 230 -10, 280 -4, 300 0 C 280 4, 230 10, 180 14 C -80 24, -320 22, -340 0 Z"
          fill="var(--bg-2)" stroke="var(--line-strong)"/>
        {/* mesh */}
        <g stroke={c} strokeWidth="0.3" fill="none" opacity="0.8">
          {Array.from({length: 42 + refn*6}).map((_, i) => {
            const x = -340 + i * (680 / (42 + refn*6));
            return <g key={i}>
              <line x1={x} y1="-26" x2={x + 6} y2="26" />
              <line x1={x + 6} y1="26" x2={x + 12} y2="-26" />
              <line x1={x} y1="-26" x2={x + 12} y2="-26" />
              <line x1={x} y1="26"  x2={x + 12} y2="26" />
            </g>;
          })}
        </g>
        {bcs.fix && (<>
          <rect x="-348" y="-32" width="10" height="64" fill="var(--warn)" opacity="0.25" stroke="var(--warn)"/>
          <text x="-390" y="-36" fontSize="10" fill="var(--warn)" className="mono">FIX</text>
        </>)}
        {bcs.load && Array.from({length: 10}).map((_, i) => (
          <g key={i} transform={`translate(${-280 + i*60}, -40)`}>
            <line x1="0" y1="0" x2="0" y2="14" stroke="var(--accent)" strokeWidth="1"/>
            <polygon points="0,18 -3,13 3,13" fill="var(--accent)"/>
          </g>
        ))}
        {bcs.symm && <line x1="-340" y1="26" x2="300" y2="26" stroke="var(--info)" strokeDasharray="4,4"/>}
        {bcs.thermal && (
          <g>
            {Array.from({length: 14}).map((_,i)=>(
              <circle key={i} cx={-320 + i*46} cy="40" r="3" fill="none" stroke="var(--err)" opacity="0.6"/>
            ))}
          </g>
        )}
      </g>
    </svg>
  );
}

// ---------- SIM RESULTS ----------
function ScreenSimResults() {
  const tenant = useActiveTenant();
  const [study, setStudy] = uS3("SIM-0411");
  const [view, setView] = uS3("contour");
  const [conv, setConv] = uS3([1, 0.4, 0.18, 0.06, 0.022, 0.012, 0.006, 0.003, 0.0018, 0.0011, 0.00068, 0.00041]);
  const isPump = !!(tenant && tenant.tenant && tenant.tenant.id === "tritan");
  if (isPump) {
    return (
      <div style={{ padding: 28, height: "100%", display: "flex", alignItems: "center", justifyContent: "center" }}>
        <div style={{ maxWidth: 540, textAlign: "center" }}>
          <div className="serif" style={{ fontSize: 26, lineHeight: 1.15, marginBottom: 10 }}>No simulation runs</div>
          <div className="muted" style={{ fontSize: 14, marginBottom: 18 }}>Pump CDMO validates via physical test gates. See the 30-point CTQ flow.</div>
          <Btn size="sm" variant="primary" icon="Check" onClick={function() { if (typeof navigate === "function") navigate("/build/gates"); else window.location.hash = "/build/gates"; }}>See Quality Gates</Btn>
        </div>
      </div>
    );
  }

  return (
    <div style={{ padding: 14, display: "grid", gridTemplateColumns: "220px minmax(0, 1fr) 240px", gap: 14, minHeight: 0, height: "100%" }}>
      <Panel title="Studies">
        <div style={{ padding: 6 }}>
          {STUDIES.map(s => (
            <div key={s.id} role="button" tabIndex={0} onClick={()=>setStudy(s.id)} onKeyDown={(e)=>{ if(e.key==="Enter"||e.key===" "){ e.preventDefault(); setStudy(s.id); } }} style={{
              display: "grid", gridTemplateColumns: "1fr", padding: "8px 8px",
              background: s.id===study?"var(--bg-2)":"transparent", cursor: "pointer", borderRadius: 4,
              borderLeft: `2px solid ${s.id===study?"var(--accent)":"transparent"}`
            }}>
              <div style={{ display: "flex", justifyContent: "space-between" }}>
                <span className="mono" style={{ fontSize: 12, color: "var(--ink-3)" }}>{s.id}</span>
                <Pill tone={s.status==="complete"?"ok":s.status==="running"?"info":s.status==="queued"?"warn":"err"}>{s.status}</Pill>
              </div>
              <div style={{ fontSize: 12, color: "var(--ink)" }}>{s.name}</div>
              <div className="muted mono" style={{ fontSize: 12 }}>{s.domain} · {s.cores}c · {s.mesh}</div>
              {s.progress > 0 && s.progress < 1 && <div style={{ marginTop: 4 }}><Progress value={s.progress} color="var(--info)"/></div>}
            </div>
          ))}
        </div>
      </Panel>

      <Panel title={`Results · ${study} · ${STUDIES.find(x=>x.id===study)?.name}`}
        right={<>
          {["contour","vectors","streamlines","section","modes"].map(v =>
            <Btn key={v} size="sm" variant={v===view?"primary":"ghost"} onClick={()=>setView(v)}>{v}</Btn>)}
        </>}>
        <div style={{ display: "grid", gridTemplateRows: "1fr auto", height: "100%" }}>
          <div style={{ position: "relative", background: "var(--bg-inset)", overflow: "hidden" }}>
            <ContourScene view={view} />
            <ContourLegend view={view} />
            <div style={{ position: "absolute", top: 10, left: 10 }}>
              <Pill tone="info">iteration 312 / 312</Pill>
            </div>
          </div>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", borderTop: "1px solid var(--line-soft)" }}>
            <div style={{ padding: 12, borderRight: "1px solid var(--line-soft)" }}>
              <div className="label">Residuals · L∞</div>
              <Spark data={conv} height={44} stroke="var(--cool)"/>
              <div className="muted mono" style={{ fontSize: 12, marginTop: 4 }}>converged at 312 iter · 4.1e-4</div>
            </div>
            <div style={{ padding: 12, borderRight: "1px solid var(--line-soft)" }}>
              <div className="label">Modes</div>
              <div style={{ display: "grid", gridTemplateColumns: "repeat(5,1fr)", gap: 6, marginTop: 6 }}>
                {[[1,14.2],[2,37.8],[3,52.1],[4,94.7],[5,128.3]].map(([n,f]) =>
                  <div key={n} style={{ padding: 6, border: "1px solid var(--line-soft)", borderRadius: 4, textAlign: "center" }}>
                    <div className="mono" style={{ fontSize: 12, color: "var(--ink-3)" }}>mode {n}</div>
                    <div className="mono tnum" style={{ fontSize: 12 }}>{f}<span className="muted"> Hz</span></div>
                  </div>)}
              </div>
            </div>
            <div style={{ padding: 12 }}>
              <div className="label">Safety factors</div>
              <div style={{ marginTop: 6 }}>
                <RowBar label="Static" v={0.62} color="var(--ok)" />
                <RowBar label="Fatigue (1e7)" v={0.41} color="var(--warn)" />
                <RowBar label="Buckling" v={0.78} color="var(--ok)" />
                <RowBar label="Creep 20y" v={0.33} color="var(--err)" />
              </div>
            </div>
          </div>
        </div>
      </Panel>

      <Panel title="Probes · outputs">
        <div style={{ padding: 12 }}>
          <div className="label">Peak response</div>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8, marginTop: 6 }}>
            {[["Max disp.", "38.2 mm"], ["Max σvm", "412 MPa"], ["Tip accel.", "3.4 g"], ["Wake ΔP", "1.86 kPa"]].map(([k,v])=>
              <div key={k} style={{ padding: 10, border: "1px solid var(--line-soft)", borderRadius: 4 }}>
                <div className="label">{k}</div>
                <div className="mono tnum" style={{ fontSize: 16 }}>{v}</div>
              </div>)}
          </div>
          <div className="hr"/>
          <div className="label">Sensor locations</div>
          <table className="dtable" style={{ marginTop: 4 }}>
            <thead><tr><th>ID</th><th style={{ textAlign: "right" }}>X</th><th style={{ textAlign: "right" }}>Y</th><th style={{ textAlign: "right" }}>Z</th><th style={{ textAlign: "right" }}>Val</th></tr></thead>
            <tbody>
              {[["P01",0.2,0,0.1,"12.4"],["P02",1.0,0,0.3,"87.1"],["P03",1.8,0,0.6,"210"],["P04",2.3,0,0.8,"382"],["P05",2.48,0,1.0,"412"]]
                .map(([id,x,y,z,v]) => (<tr key={id}><td>{id}</td><td className="tnum">{x}</td><td className="tnum">{y}</td><td className="tnum">{z}</td><td className="tnum" style={{color:"var(--accent)"}}>{v}</td></tr>))}
            </tbody>
          </table>
          <div className="hr"/>
          <div className="label">Feeds into</div>
          <div className="mono" style={{ fontSize: 12, color: "var(--ink-2)", marginTop: 4 }}>
            <div>→ M-BOM · WI-210-B acceptance table</div>
            <div>→ ECO-2611 verification</div>
            <div>→ ERP: inspection spec on ITM-0041</div>
          </div>
        </div>
      </Panel>
    </div>
  );
}

function RowBar({ label, v, color }) {
  return (
    <div style={{ display: "grid", gridTemplateColumns: "90px 1fr auto", gap: 8, alignItems: "center", padding: "4px 0" }}>
      <span style={{ fontSize: 12, color: "var(--ink-3)" }}>{label}</span>
      <div style={{ height: 6, background: "var(--bg-3)", borderRadius: 3, overflow: "hidden" }}>
        <div style={{ width: `${v*100}%`, height: "100%", background: color }}/>
      </div>
      <span className="mono tnum" style={{ fontSize: 12 }}>{v.toFixed(2)}</span>
    </div>
  );
}

function ContourScene({ view }) {
  const cols = ["#0b3d66","#156aa6","#2aa3c2","#6ac6b5","#d9c26a","#de8b3d","#c84a2b","#7d1a24"];
  return (
    <svg viewBox="0 0 900 460" preserveAspectRatio="xMidYMid meet" style={{ width: "100%", height: "100%" }}>
      <defs>
        <linearGradient id="stress" x1="0" x2="1">
          {cols.map((c,i) => <stop key={c} offset={i/(cols.length-1)} stopColor={c}/>)}
        </linearGradient>
        <radialGradient id="wake" cx="0.3" cy="0.5" r="0.9">
          <stop offset="0" stopColor="#2aa3c2"/>
          <stop offset="0.4" stopColor="#156aa6"/>
          <stop offset="1" stopColor="#0b3d66"/>
        </radialGradient>
      </defs>

      {view !== "modes" && (
        <g transform="translate(450,230) rotate(-8)">
          <path d="M -340 0 C -320 -26, -80 -32, 180 -16 C 230 -12, 280 -4, 300 0 C 280 4, 230 12, 180 16 C -80 28, -320 26, -340 0 Z"
            fill="url(#stress)" opacity="0.95" stroke="var(--line-strong)"/>
          {/* contour bands */}
          {Array.from({length: 30}).map((_, i) => {
            const y = -28 + i*2;
            return <line key={i} x1="-340" y1={y} x2="300" y2={y} stroke="rgba(0,0,0,0.08)" strokeWidth="0.3"/>;
          })}
          {/* streamlines overlay */}
          {view === "streamlines" && Array.from({length: 22}).map((_, i) => {
            const y = -60 + i*6;
            return <path key={i} d={`M -420 ${y} C -200 ${y + Math.sin(i)*6}, 0 ${y - Math.cos(i)*6}, 380 ${y + Math.sin(i)*10}`}
              stroke="var(--cool)" strokeWidth="0.6" fill="none" opacity="0.6"/>;
          })}
          {/* vectors */}
          {view === "vectors" && Array.from({length: 14}).map((_, i) =>
            Array.from({length: 5}).map((_, j) => {
              const x = -300 + i*48, y = -24 + j*12;
              return <g key={`${i}-${j}`} transform={`translate(${x},${y})`}>
                <line x1="0" y1="0" x2="12" y2="2" stroke="#fff" strokeWidth="0.6" opacity="0.6"/>
                <polygon points="14,2 10,0 10,4" fill="#fff" opacity="0.6"/>
              </g>;
            })
          )}
          {/* section */}
          {view === "section" && (<line x1="80" y1="-60" x2="80" y2="60" stroke="var(--accent)" strokeWidth="1.5"/>)}
        </g>
      )}

      {view === "modes" && (
        <g>
          {[1,2,3,4].map((n, idx) => (
            <g key={n} transform={`translate(${120 + idx*190}, 230) scale(0.4)`}>
              <path d={`M -300 0 C -200 ${-20*(idx+1)}, 0 ${(idx%2?20:-20)*(idx+1)}, 260 ${(idx%2?-8:8)*(idx+1)}`}
                stroke={cols[(idx*2)%cols.length]} strokeWidth="3" fill="none"/>
              <path d="M -300 0 C -280 -26, -80 -32, 180 -16 C 230 -12, 280 -4, 300 0 C 280 4, 230 12, 180 16 C -80 28, -280 26, -300 0 Z"
                fill="none" stroke="var(--ink-4)" strokeWidth="0.6" opacity="0.5"/>
              <text x="-280" y="70" className="mono" fontSize="22" fill="var(--ink-3)">mode {n}</text>
              <text x="-280" y="100" className="mono" fontSize="22" fill="var(--ink-2)">{[14.2,37.8,52.1,94.7][idx]} Hz</text>
            </g>
          ))}
        </g>
      )}
    </svg>
  );
}
function ContourLegend({ view }) {
  const cols = ["#0b3d66","#156aa6","#2aa3c2","#6ac6b5","#d9c26a","#de8b3d","#c84a2b","#7d1a24"];
  return (
    <div style={{ position: "absolute", bottom: 12, left: 12, background: "color-mix(in oklch, var(--bg-1) 80%, transparent)",
      border: "1px solid var(--line-soft)", borderRadius: 4, padding: "6px 8px" }}>
      <div className="label" style={{ marginBottom: 4 }}>
        {view === "modes" ? "MODE SHAPE · NORMALIZED" : view === "streamlines" ? "VELOCITY · m/s" : "VON MISES · MPa"}
      </div>
      <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
        <span className="mono tnum" style={{ fontSize: 12, color: "var(--ink-3)" }}>0</span>
        <div style={{ width: 180, height: 8, borderRadius: 2,
          background: `linear-gradient(to right, ${cols.join(",")})` }} />
        <span className="mono tnum" style={{ fontSize: 12, color: "var(--ink-3)" }}>412</span>
      </div>
    </div>
  );
}

// ---------- ERP ----------
function ScreenERP({ mode = "queue" }) {
  const tenant = useActiveTenant();
  const isTritan = !!(tenant && tenant.tenant && tenant.tenant.id === "tritan");
  const woRows = (tenant && tenant.work_orders && tenant.work_orders.length)
    ? tenant.work_orders.map(function(w) {
        var stateMap = { "completed": "synced", "in-progress": "validating", "pilot": "validating", "scheduled": "queued" };
        return {
          pn: w.id, name: w.sku + " · " + w.customer + " · qty " + w.qty, rev: "B",
          item: "WO-" + (w.id || ""),
          state: stateMap[w.status] || "queued",
          drift: w.scheduled_end ? ("ends " + w.scheduled_end) : "—",
        };
      })
    : null;
  const rows = woRows || ERP_QUEUE;
  return (
    <div style={{ padding: 14, display: "grid", gridTemplateColumns: "1fr 360px", gap: 14, minHeight: 0, height: "100%" }}>
      <div style={{ display: "grid", gridTemplateRows: "180px 1fr", gap: 14, minHeight: 0 }}>
        <Panel title="PLM → ERP → MES · flow">
          <ERPFlow />
        </Panel>
        <Panel title={woRows ? "Work-order release queue" : "Release queue"} right={<>
          <Btn size="sm" icon="Filter" onClick={() => window.forgeToast && window.forgeToast("filter queued — wired in v2")}>filter</Btn>
          <Btn size="sm" icon="Plug" variant="primary" disabled title="coming in v2">Sync all eligible</Btn>
        </>}>
          <table className="dtable">
            <thead><tr><th>{woRows?"WO":"Part"}</th><th>Name</th><th>Rev</th><th>Item</th><th>Mapping</th><th>State</th><th>{woRows?"Window":"Drift / Issue"}</th></tr></thead>
            <tbody>
              {rows.map(r => (
                <tr key={r.pn+r.rev}>
                  <td>{r.pn}</td>
                  <td style={{ color: "var(--ink)" }}>{r.name}</td>
                  <td>{r.rev}</td>
                  <td>{r.item}</td>
                  <td>
                    <Bar v={r.state==="synced"?1:r.state==="validating"?0.6:r.state==="blocked"?0.2:0.4}
                      color={r.state==="synced"?"var(--ok)":r.state==="blocked"?"var(--err)":"var(--warn)"} />
                  </td>
                  <td><Pill tone={r.state==="synced"?"ok":r.state==="blocked"?"err":r.state==="validating"?"info":"warn"}>{r.state}</Pill></td>
                  <td style={{ color: r.drift === "—" ? "var(--ink-3)" : "var(--warn)" }}>{r.drift}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </Panel>
      </div>

      <div style={{ display: "grid", gridTemplateRows: "auto 1fr 1fr", gap: 14, minHeight: 0 }}>
        <Panel title="Sync · today">
          <div style={{ padding: 12, display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 8 }}>
            {[["Upserts","94","ok"],["Blocked","3","err"],["Drift p50","0.4%","info"]].map(([k,v,t])=>
              <div key={k}><div className="label">{k}</div>
                <div className="mono tnum" style={{ fontSize: 20, color: t==="err"?"var(--err)":t==="ok"?"var(--ok)":"var(--info)" }}>{v}</div>
              </div>)}
          </div>
        </Panel>
        <Panel title={(function() {
          if (isTritan) return "Field mapping · WO-44219 (Helios pumpset · 500 u)";
          // Use the first part from tenant.parts so each tenant shows its own example item.
          const firstPart = (tenant && tenant.parts && tenant.parts.length) ? tenant.parts[0] : null;
          if (firstPart) {
            const num  = firstPart.num || firstPart.part_num || "—";
            const name = firstPart.name || "";
            return "Field mapping · " + num + (name ? " · " + name : "");
          }
          return "Field mapping · ITM-0041 (Blade Airfoil A)";
        })()}>
          <table className="dtable">
            <thead><tr><th>PLM field</th><th></th><th>ERP field</th><th>State</th></tr></thead>
            <tbody>
              {[
                ["pn","→","item_number","ok"],
                ["name","→","description","ok"],
                ["mat","→","commodity","ok"],
                ["rev","→","engineering_rev","ok"],
                ["UOM (each)","→","uom (ea vs kg)","warn"],
                ["lot_size","→","lot_size","warn"],
                ["drawing","→","doc_ref","ok"],
                ["source","→","make_buy","ok"],
              ].map(([l,a,r,s]) => (
                <tr key={l}><td>{l}</td><td className="dim">{a}</td><td>{r}</td>
                  <td><Pill tone={s}>{s}</Pill></td></tr>
              ))}
            </tbody>
          </table>
        </Panel>
        <Panel title="Event feed">
          <div style={{ padding: 8 }}>
            {(isTritan && tenant && tenant.ledger && tenant.ledger.length
              ? tenant.ledger.slice(-6).reverse().map(function(e) {
                  var st = e.type && e.type.indexOf("block") >= 0 ? "err"
                         : e.type && e.type.indexOf("eco") >= 0 ? "warn"
                         : e.type && e.type.indexOf("audit") >= 0 ? "info"
                         : "ok";
                  var t = (e.ts || "").slice(11, 19) || "—";
                  return [t, (e.type || "evt"), (e.summary || e.ref || "—"), st];
                })
              : [
                  ["11:42:08", "sync",    "ITM-0033 · Planet Gear · rev A",       "ok"],
                  ["11:41:55", "validate","ITM-0058 · Cooling Manifold rev B",    "info"],
                  ["11:41:02", "drift",   "ITM-0041 · UOM mismatch (ea vs kg)",   "warn"],
                  ["11:38:10", "block",   "ITM-0072 · missing cost-center rev B", "err"],
                  ["11:30:00", "ack",     "MES acknowledged 6 items",             "ok"],
                  ["11:22:16", "sync",    "ITM-0081 · Tower Shell rev B",         "ok"],
                ]
            ).map(([t,op,msg,st]) => (
              <div key={t + msg} style={{ display: "grid", gridTemplateColumns: "68px 62px 1fr auto", gap: 8, padding: "5px 6px", borderBottom: "1px solid var(--line-soft)", alignItems: "center" }}>
                <span className="mono tnum" style={{ fontSize: 12, color: "var(--ink-3)" }}>{t}</span>
                <span className="tag">{op}</span>
                <span style={{ fontSize: 12, color: "var(--ink-2)" }}>{msg}</span>
                <span className={`pill ${st}`}><span className="dot"/>{st}</span>
              </div>
            ))}
          </div>
        </Panel>
      </div>
    </div>
  );
}

function ERPFlow() {
  const nodes = [
    { x: 40,  label: "FORGE · lattice",   sub: "source of truth", color: "var(--accent)" },
    { x: 260, label: "Transformation",    sub: "E→M rules · T1..T7", color: "var(--info)" },
    { x: 480, label: "ERP · item-master", sub: "SAP-like / Oracle-like", color: "var(--cool)" },
    { x: 700, label: "MES · shopfloor",   sub: "station dispatch",     color: "var(--ok)" },
  ];
  return (
    <div style={{ position: "relative", height: "100%" }}>
      <svg viewBox="0 0 900 140" preserveAspectRatio="xMidYMid meet" style={{ width: "100%", height: "100%" }}>
        {/* lanes */}
        <line x1="0" y1="70" x2="900" y2="70" stroke="var(--line-soft)" strokeDasharray="3,3"/>
        {/* arrows */}
        {["a","b","c"].map((slot, i) => (
          <g key={slot}>
            <line x1={40 + 180*i + 160} y1="70" x2={40 + 180*(i+1) + 20} y2="70" stroke="var(--line-strong)" strokeWidth="1"/>
            <polygon points={`${40 + 180*(i+1) + 20},70 ${40 + 180*(i+1) + 12},66 ${40 + 180*(i+1) + 12},74`} fill="var(--line-strong)"/>
          </g>
        ))}
        {nodes.map((n) => (
          <g key={n.label} transform={`translate(${n.x}, 40)`}>
            <rect width="180" height="62" rx="6" fill="var(--bg-2)" stroke={n.color}/>
            <text x="12" y="24" fontSize="12" fill="var(--ink)">{n.label}</text>
            <text x="12" y="42" fontSize="10" fill="var(--ink-3)" className="mono">{n.sub}</text>
            <circle cx="168" cy="10" r="4" fill={n.color} className="pulse"/>
          </g>
        ))}
        {/* data bubbles */}
        {Array.from({length: 12}).map((_, i) => (
          <circle key={`bubble-${i}`} cx={80 + (i*65)%720} cy={70 + ((i%2)?6:-6)} r="2" fill="var(--accent)">
            <animate attributeName="cx" from="80" to="800" dur={`${3 + i*0.2}s`} repeatCount="indefinite"/>
            <animate attributeName="opacity" values="0;0.9;0" dur={`${3 + i*0.2}s`} repeatCount="indefinite"/>
          </circle>
        ))}
      </svg>
    </div>
  );
}

// ---------- ECO ----------
// Tritan branch (pump-eco): uses the ECO state machine + approval chain.
// Aetherion / Mittelstand branches keep the legacy 3-pane diff UI.
//
// `props.selectedId` (optional): id of the ECO to highlight when deep-linked
// via /build/eco/:id. When unset the screen picks the most recent ECO.
//   /build/eco       → ScreenECO()                  → picks default
//   /build/eco/:id   → ScreenECO({ selectedId })    → highlights :id
function ScreenECO(props) {
  const selectedId = props && props.selectedId;
  // useTenantState bumps on any forge:tenant-change. Falls back to useActiveTenant
  // when the stub isn't loaded yet (e.g. legacy aetherion path).
  const useTS = (typeof window !== "undefined" && typeof window.useTenantState === "function")
    ? window.useTenantState
    : null;
  if (useTS) useTS(); // subscribe for re-renders on transitions
  const tenant = useActiveTenant();
  const isTritan = !!(tenant && tenant.tenant && tenant.tenant.id === "tritan");

  if (isTritan) {
    return <ScreenECOPump tenant={tenant} selectedId={selectedId}/>;
  }

  // Legacy fallback (aetherion + mittelstand). Same UI as before.
  return <ScreenECOLegacy tenant={tenant} selectedId={selectedId}/>;
}

// ---------- ECO · pump branch (state-machine aware) ----------
function ScreenECOPump({ tenant, selectedId }) {
  const state = (typeof window !== "undefined" && window.PUMP_TENANT) ? window.PUMP_TENANT : tenant;
  const ecos = (state && Array.isArray(state.eco)) ? state.eco : [];
  // Seed selection from the deep-link id when present; otherwise pick the
  // most recent ECO. If the deep-link id doesn't match an existing ECO the
  // fallback chain below still picks something sane (last or first ECO).
  const initialSel = (selectedId && ecos.find(function(e) { return e.id === selectedId; }))
    ? selectedId
    : ((ecos[ecos.length - 1] && ecos[ecos.length - 1].id) || (ecos[0] && ecos[0].id) || null);
  const [sel, setSel] = uS3(initialSel);
  // Keep selection in sync with route changes (e.g. clicking from one ECO
  // detail link to another) — without this, sel sticks to whatever the
  // component mounted with.
  uE3(function() {
    if (selectedId && ecos.find(function(e) { return e.id === selectedId; })) {
      setSel(selectedId);
    }
  }, [selectedId]);
  const [showProvenance, setShowProvenance] = uS3(false);

  const eco = ecos.find(function(e) { return e.id === sel; }) || ecos[ecos.length - 1] || ecos[0];
  if (!eco) {
    return (
      <div style={{ padding: 28, height: "100%", display: "flex", alignItems: "center", justifyContent: "center" }}>
        <div className="muted">No change orders yet.</div>
      </div>
    );
  }

  const cur = (typeof window !== "undefined" && window.__forgeCurrentUser) || { name: "—", role: "—" };

  function go(path) { if (typeof navigate === "function") navigate(path); else window.location.hash = path; }

  function onSubmitForReview() {
    window.forgeApi.eco.transition(eco.id, "submit-for-review", { actor: cur.name });
  }
  function onApprove() {
    // role-aware sign-off: match the chain entry where name === cur.name or role === cur.role
    window.forgeApi.eco.transition(eco.id, "approve", { actor: cur.name, role: cur.role });
  }
  function onReject() {
    window.forgeApi.eco.transition(eco.id, "reject", { actor: cur.name, role: cur.role });
  }
  function onReleaseQueue() { go("/build/erp-release"); }

  const partsAffected = eco.parts_affected || [];
  // Prefer the cosmopolitan shape (cost_delta_amount_minor + currency) which
  // the server returns on every assembled ECO; fall back to the legacy
  // cost_delta_inr field still emitted by fixtures-pump.jsx for screens that
  // read directly from PUMP_TENANT without round-tripping through the API.
  // The "/u" suffix is per-unit and stays language-neutral.
  var costMinorStr = null;
  var costCcy = "INR";
  var costDelta = 0;
  if (eco.cost_delta_amount_minor != null) {
    costMinorStr = String(eco.cost_delta_amount_minor);
    costCcy = eco.cost_delta_currency || "INR";
    costDelta = Number(costMinorStr) / 100;
  } else if (typeof eco.cost_delta_inr === "number") {
    costDelta = eco.cost_delta_inr;
    costMinorStr = String(Math.round(costDelta * 100));
    costCcy = "INR";
  }
  // Format with locale + currency via forgeI18n; fall back to legacy ₹ syntax.
  var _i18n = (typeof window !== "undefined") ? window.forgeI18n : null;
  var costFormatted = "";
  if (costMinorStr != null) {
    var absMinor = costMinorStr.replace(/^-/, "");
    if (_i18n && typeof _i18n.formatMoneyMinor === "function") {
      var fm = _i18n.formatMoneyMinor(absMinor, costCcy);
      costFormatted = (costDelta >= 0 ? "+" : "-") + (fm || (costCcy + " " + Math.abs(costDelta)));
    } else {
      costFormatted = (costDelta >= 0 ? "+₹" : "-₹") + Math.abs(costDelta);
    }
  } else {
    costFormatted = "+₹0";
  }
  const costStr = costFormatted + "/u";

  // Is the current user able to sign off the next pending chain entry?
  const nextPending = (eco.approval_chain || []).find(function(c) { return c.status === "pending"; });
  const canSign = !!(nextPending && eco.status === "in-review" && (nextPending.name === cur.name || nextPending.role === cur.role));
  const canSubmit = eco.status === "draft";
  const isApproved = eco.status === "approved";

  return (
    <div style={{ padding: 14, display: "grid", gridTemplateColumns: "360px 1fr 320px", gap: 14, minHeight: 0, height: "100%" }}>
      {/* Left: list of ECOs */}
      <Panel title="Change orders" right={<Btn size="sm" icon="Plus" onClick={function(){ go("/build/eco/new"); }}>New ECO</Btn>}>
        <div>
          {ecos.map(function(e) {
            var tone = e.status === "approved" ? "ok"
                     : e.status === "released" ? "ok"
                     : e.status === "applied" ? "ok"
                     : e.status === "rejected" ? "err"
                     : e.status === "in-review" ? "warn"
                     : "";
            var target = (e.parts_affected && e.parts_affected[0] && e.parts_affected[0].new) || "—";
            // Clicking a row both navigates to the deep-link URL (so the
            // address bar reflects the selected ECO and the link is
            // shareable) and updates the local selection state (cheap, lets
            // the right pane re-render synchronously without waiting for the
            // hashchange round-trip).
            function pickRow() {
              setSel(e.id);
              go("/build/eco/" + encodeURIComponent(e.id));
            }
            return (
              <div key={e.id} role="button" tabIndex={0}
                onClick={pickRow}
                onKeyDown={function(ev){ if (ev.key === "Enter" || ev.key === " ") { ev.preventDefault(); pickRow(); } }}
                style={{
                  padding: "10px 12px", borderBottom: "1px solid var(--line-soft)", cursor: "pointer",
                  background: e.id === sel ? "var(--bg-2)" : "transparent",
                  borderLeft: "2px solid " + (e.id === sel ? "var(--accent)" : "transparent"),
                }}>
                <div style={{ display: "flex", justifyContent: "space-between" }}>
                  <span className="mono" style={{ fontSize: 12, color: "var(--ink-3)" }}>{e.id}</span>
                  <Pill tone={tone}>{e.status}</Pill>
                </div>
                <div style={{ fontSize: 12, color: "var(--ink)", marginTop: 2 }}>{e.title}</div>
                <div className="muted mono" style={{ fontSize: 12, marginTop: 2 }}>
                  {target} · {e.originator || "—"} · raised {(window.forgeI18n && window.forgeI18n.formatDate && e.date_raised && /^\d{4}-\d{2}-\d{2}$/.test(e.date_raised) && window.forgeI18n.formatDate(e.date_raised)) || e.date_raised || "—"}
                </div>
              </div>
            );
          })}
        </div>
      </Panel>

      {/* Center: ECO detail */}
      <Panel title={eco.id + " · " + eco.title}
        right={<>
          {typeof window.SwitchUserPill === "function" && React.createElement(window.SwitchUserPill)}
          <Pill tone={eco.status === "approved" || eco.status === "released" ? "ok" : eco.status === "rejected" ? "err" : "warn"}>{eco.status}</Pill>
          {canSubmit && <Btn size="sm" icon="ArrowRight" variant="primary" onClick={onSubmitForReview}>Submit for review</Btn>}
          {canSign && <Btn size="sm" icon="Check" variant="primary" onClick={onApprove}>Approve as {cur.name.split(" ")[0]}</Btn>}
          {canSign && <Btn size="sm" icon="X" onClick={onReject}>Reject</Btn>}
          {isApproved && <Btn size="sm" icon="Plug" variant="primary" onClick={onReleaseQueue}>Go to release queue</Btn>}
        </>}>
        <div style={{ padding: 14 }}>
          <div className="serif" style={{ fontSize: 22 }}>Impact</div>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 8, marginTop: 10 }}>
            <div style={{ padding: 10, border: "1px solid var(--line-soft)", borderRadius: 6 }}>
              <div className="label">Parts affected</div>
              <div className="mono tnum" style={{ fontSize: 20 }}>{partsAffected.length}</div>
            </div>
            <div style={{ padding: 10, border: "1px solid var(--line-soft)", borderRadius: 6 }}>
              <div className="label">Originator</div>
              <div className="mono" style={{ fontSize: 13, marginTop: 4 }}>{eco.originator || "—"}</div>
            </div>
            <div style={{ padding: 10, border: "1px solid var(--line-soft)", borderRadius: 6 }}>
              <div className="label">Cost Δ</div>
              <div className="mono tnum" style={{ fontSize: 20, color: costDelta > 500 ? "var(--err)" : costDelta > 0 ? "var(--warn)" : "var(--ok)" }}>{costStr}</div>
            </div>
            <div style={{ padding: 10, border: "1px solid var(--line-soft)", borderRadius: 6 }}>
              <div className="label">Date raised</div>
              <div className="mono" style={{ fontSize: 13, marginTop: 4 }}>{(window.forgeI18n && window.forgeI18n.formatDate && eco.date_raised && /^\d{4}-\d{2}-\d{2}$/.test(eco.date_raised) && window.forgeI18n.formatDate(eco.date_raised)) || eco.date_raised || "—"}</div>
            </div>
          </div>

          <div className="serif" style={{ fontSize: 20, marginTop: 18 }}>Justification</div>
          <div style={{ marginTop: 6, padding: 12, border: "1px solid var(--line-soft)", borderRadius: 6, fontSize: 13, color: "var(--ink-2)", whiteSpace: "pre-wrap" }}>
            {eco.justification || "(no justification provided)"}
          </div>

          <div className="serif" style={{ fontSize: 20, marginTop: 18 }}>Approval chain</div>
          <div style={{ marginTop: 6, border: "1px solid var(--line-soft)", borderRadius: 6, overflow: "hidden" }}>
            <table className="dtable">
              <thead><tr><th>Step</th><th>Role</th><th>Name</th><th>Status</th><th>At</th></tr></thead>
              <tbody>
                {(eco.approval_chain || []).map(function(c, i) {
                  var tone = c.status === "approved" ? "ok" : c.status === "rejected" ? "err" : "warn";
                  return (
                    <tr key={c.role + i}>
                      <td className="mono">{i + 1}</td>
                      <td>{c.role}</td>
                      <td>{c.name || "—"}</td>
                      <td><Pill tone={tone}>{c.status}</Pill></td>
                      <td className="mono">{c.at || "—"}</td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>

          <div className="serif" style={{ fontSize: 20, marginTop: 18 }}>Parts affected</div>
          <div style={{ marginTop: 6, border: "1px solid var(--line-soft)", borderRadius: 6, overflow: "hidden" }}>
            <table className="dtable">
              <thead><tr><th>Old</th><th>→</th><th>New</th></tr></thead>
              <tbody>
                {partsAffected.map(function(p, i) {
                  return (
                    <tr key={i}>
                      <td>{p.old || "—"}</td>
                      <td className="dim">→</td>
                      <td style={{ color: "var(--ok)" }}>{p.new || "—"}</td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>

          {eco.transitions && eco.transitions.length > 0 && (
            <>
              <div className="serif" style={{ fontSize: 20, marginTop: 18 }}>State transitions</div>
              <div style={{ marginTop: 6, border: "1px solid var(--line-soft)", borderRadius: 6, overflow: "hidden" }}>
                <table className="dtable">
                  <thead><tr><th>From</th><th>To</th><th>Actor</th><th>Timestamp</th></tr></thead>
                  <tbody>
                    {eco.transitions.map(function(t, i) {
                      return (
                        <tr key={i}>
                          <td className="mono">{t.from || "—"}</td>
                          <td className="mono" style={{ color: "var(--ink)" }}>{t.to}</td>
                          <td>{t.actor}</td>
                          <td className="mono tnum" style={{ fontSize: 12 }}>{t.ts}</td>
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              </div>
            </>
          )}

          {eco.provenance && (
            <div style={{ marginTop: 18 }}>
              <Btn size="sm" icon="Box" onClick={function(){ setShowProvenance(true); }}>View provenance receipt</Btn>
            </div>
          )}
        </div>
      </Panel>

      {/* Right: actor + history rail */}
      <Panel title="Live state">
        <div style={{ padding: 12 }}>
          <div className="label">Current actor</div>
          <div style={{ marginTop: 4, padding: 8, border: "1px solid var(--line-soft)", borderRadius: 4 }}>
            <div style={{ fontSize: 13, color: "var(--ink)" }}>{cur.name}</div>
            <div className="mono" style={{ fontSize: 12, color: "var(--ink-3)" }}>{cur.role}</div>
          </div>

          <div className="label" style={{ marginTop: 16 }}>State machine</div>
          <div style={{ marginTop: 4, fontSize: 12, color: "var(--ink-2)" }}>
            draft → in-review → approved | rejected → released → applied
          </div>

          <div className="label" style={{ marginTop: 16 }}>Quick actions</div>
          <div style={{ display: "flex", flexDirection: "column", gap: 6, marginTop: 6 }}>
            <Btn size="sm" icon="Plus" onClick={function(){ go("/build/eco/new"); }}>New ECO (compose)</Btn>
            <Btn size="sm" icon="Plug" onClick={onReleaseQueue}>ERP release queue</Btn>
            <Btn size="sm" icon="List" onClick={function(){ go("/auditor/ledger"); }}>Auditor ledger</Btn>
          </div>

          <div className="label" style={{ marginTop: 16 }}>Hint</div>
          <div style={{ marginTop: 4, fontSize: 12, color: "var(--ink-3)", lineHeight: 1.45 }}>
            Switch actor with the pill above, then sign off the next pending step. Once every step is approved, head to the release queue.
          </div>
        </div>
      </Panel>

      {showProvenance && eco.provenance && (
        <div onClick={function(){ setShowProvenance(false); }} style={{
          position: "fixed", inset: 0, background: "rgba(0,0,0,0.45)", zIndex: 50,
          display: "flex", alignItems: "center", justifyContent: "center",
        }}>
          <div onClick={function(ev){ ev.stopPropagation(); }} style={{
            width: 720, maxHeight: "82vh", overflow: "auto",
            background: "var(--bg-1)", border: "1px solid var(--line-strong)", borderRadius: 8, padding: 18,
          }}>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 8 }}>
              <div className="serif" style={{ fontSize: 22 }}>Provenance receipt · {eco.id}</div>
              <Btn size="sm" onClick={function(){ setShowProvenance(false); }}>Close</Btn>
            </div>
            <pre style={{ margin: 0, padding: 12, background: "var(--bg-2)", border: "1px solid var(--line-soft)", borderRadius: 4, fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--ink-2)", whiteSpace: "pre-wrap", wordBreak: "break-all" }}>
{JSON.stringify(eco.provenance, null, 2)}
            </pre>
          </div>
        </div>
      )}
    </div>
  );
}

// ---------- ECO · legacy (aetherion / mittelstand) ----------
function ScreenECOLegacy({ tenant, selectedId }) {
  const tenantEcos = (tenant && tenant.eco && tenant.eco.length)
    ? tenant.eco.map(function(e) {
        // Aetherion ECOs use `state`, Mittelstand + Tritan use `status`.
        var st = e.status || e.state || "draft";
        var sevMap = { "in-review": "high", "approved": "low", "closed": "low" };
        return {
          id: e.id, title: e.title,
          owner: e.originator || "—",
          target: (e.parts_affected && e.parts_affected[0] && e.parts_affected[0].new) || "—",
          sev: sevMap[st] || "medium",
          state: st, opened: e.date_raised || "—",
          _raw: e,
        };
      })
    : null;
  const list = tenantEcos || ECOS;
  // Seed selection from the deep-link id when present.
  const initSel = (selectedId && list.find(function(e) { return e.id === selectedId; }))
    ? selectedId
    : list[0].id;
  const [sel, setSel] = uS3(initSel);
  // Follow the URL on subsequent /build/eco/:id navigations.
  uE3(function() {
    if (selectedId && list.find(function(e) { return e.id === selectedId; })) {
      setSel(selectedId);
    }
  }, [selectedId]);
  const eco = list.find(e => e.id === sel) || list[0];
  function pickRowLegacy(id) {
    setSel(id);
    if (typeof navigate === "function") navigate("/build/eco/" + encodeURIComponent(id));
    else window.location.hash = "/build/eco/" + encodeURIComponent(id);
  }
  return (
    <div style={{ padding: 14, display: "grid", gridTemplateColumns: "360px 1fr 320px", gap: 14, minHeight: 0, height: "100%" }}>
      <Panel title="Change orders · open">
        <div>
          {list.map(e => (
            <div key={e.id} role="button" tabIndex={0} onClick={()=>pickRowLegacy(e.id)} onKeyDown={(ev)=>{ if(ev.key==="Enter"||ev.key===" "){ ev.preventDefault(); pickRowLegacy(e.id); } }} style={{
              padding: "10px 12px", borderBottom: "1px solid var(--line-soft)", cursor: "pointer",
              background: e.id===sel ? "var(--bg-2)" : "transparent",
              borderLeft: `2px solid ${e.id===sel ? "var(--accent)" : "transparent"}`
            }}>
              <div style={{ display: "flex", justifyContent: "space-between" }}>
                <span className="mono" style={{ fontSize: 12, color: "var(--ink-3)" }}>{e.id}</span>
                <Pill tone={e.sev==="high"?"err":e.sev==="medium"?"warn":""}>{e.sev}</Pill>
              </div>
              <div style={{ fontSize: 12, color: "var(--ink)", marginTop: 2 }}>{e.title}</div>
              <div className="muted mono" style={{ fontSize: 12, marginTop: 2 }}>
                {e.target} · {e.owner} · opened {e.opened}
              </div>
            </div>
          ))}
        </div>
      </Panel>

      <Panel title={`${eco.id} · ${eco.title}`} right={
        <Pill tone={eco.state==="approved"?"ok":eco.state==="closed"?"":"warn"}>{eco.state}</Pill>
      }>
        <div style={{ padding: 14 }}>
          <div className="serif" style={{ fontSize: 22 }}>Impact</div>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 8, marginTop: 10 }}>
            {[["Parts affected","14","info"],["Assemblies","3","warn"],["Sim reruns","5","accent"],["Mass Δ","+1.8%","warn"]].map(([k,v,t]) =>
              <div key={k} style={{ padding: 10, border: "1px solid var(--line-soft)", borderRadius: 6 }}>
                <div className="label">{k}</div>
                <div className="mono tnum" style={{ fontSize: 20, color: t==="warn"?"var(--warn)":t==="accent"?"var(--accent)":"var(--ink)" }}>{v}</div>
              </div>)}
          </div>

          <div className="serif" style={{ fontSize: 20, marginTop: 18 }}>Approval workflow</div>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(5, 1fr)", marginTop: 8, gap: 0 }}>
            {["Impact","Board","Engineering","Mfg","Quality"].map((s, i) => {
              const state = i <= 1 ? "done" : i === 2 ? "active" : "pending";
              return (
                <div key={s} style={{ padding: 8, textAlign: "center", borderTop: `3px solid ${state==="done"?"var(--ok)":state==="active"?"var(--accent)":"var(--line-strong)"}`, borderRight: "1px solid var(--line-soft)" }}>
                  <div className="label">Stage {i+1}</div>
                  <div style={{ fontSize: 12, color: "var(--ink)" }}>{s}</div>
                  <div className="muted mono" style={{ fontSize: 12 }}>{state}</div>
                </div>
              );
            })}
          </div>

          <div className="serif" style={{ fontSize: 20, marginTop: 18 }}>Diff · before → after</div>
          <div style={{ marginTop: 6, border: "1px solid var(--line-soft)", borderRadius: 6, overflow: "hidden" }}>
            <table className="dtable">
              <thead><tr><th>Field</th><th>Before</th><th>After</th><th>Δ</th></tr></thead>
              <tbody>
                <tr><td>Laminate</td><td>L-7</td><td style={{ color: "var(--ok)" }}>L-8</td><td>+2 plies 0°, +1 ply 45°</td></tr>
                <tr><td>Mass / blade</td><td className="tnum">478.5 kg</td><td className="tnum">487.2 kg</td><td className="tnum" style={{ color: "var(--warn)" }}>+8.7 kg</td></tr>
                <tr><td>Fatigue SF @ 1e7</td><td className="tnum">0.34</td><td className="tnum" style={{ color: "var(--ok)" }}>0.41</td><td className="tnum">+0.07</td></tr>
                <tr><td>Cost / blade</td><td className="tnum">{(window.forgeI18n && window.forgeI18n.formatMoneyMinor("1421000", "USD")) || "$14,210"}</td><td className="tnum">{(window.forgeI18n && window.forgeI18n.formatMoneyMinor("1469000", "USD")) || "$14,690"}</td><td className="tnum" style={{ color: "var(--warn)" }}>+{(window.forgeI18n && window.forgeI18n.formatMoneyMinor("48000", "USD")) || "$480"}</td></tr>
                <tr><td>Lead time</td><td className="tnum">42 d</td><td className="tnum">44 d</td><td className="tnum" style={{ color: "var(--warn)" }}>+2 d</td></tr>
              </tbody>
            </table>
          </div>
        </div>
      </Panel>

      <Panel title="Conversation">
        <div style={{ padding: 12, display: "flex", flexDirection: "column", gap: 12 }}>
          {[
            ["J. Park","Structures","Raising severity to HIGH after SIM-0411 showed local fiber fatigue at root shoulder under 1.5g pull-up."],
            ["A. Ibrahim","Thermal","Thermal impact is negligible (+0.3°C matrix). No rerun needed."],
            ["M. Chen","Mfg.","Two extra plies — layup time +0.4h per blade. Update WI-210-B. OK on my side."],
            ["R. Larsen","Quality","Need new FAT criterion on mode 3 freq. Proposing 50.5–54.0 Hz window."],
          ].map(([who, role, msg]) => (
            <div key={msg}>
              <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
                <div style={{ width: 22, height: 22, borderRadius: 22, background: "var(--bg-3)", display:"grid", placeItems:"center" }} className="mono">{who.split(" ").map(x=>x[0]).join("")}</div>
                <div style={{ fontSize: 12 }}>{who}</div>
                <div className="muted" style={{ fontSize: 12 }}>· {role}</div>
              </div>
              <div style={{ fontSize: 12, color: "var(--ink-2)", marginTop: 4, paddingLeft: 28 }}>{msg}</div>
            </div>
          ))}
          <div style={{ marginTop: "auto", border: "1px solid var(--line-soft)", borderRadius: 4, padding: 8 }}>
            <textarea id="sim-f3" name="sim-f3" aria-label="Reply…" placeholder="Reply…" rows={2}
              style={{ width: "100%", background: "transparent", border: 0, color: "var(--ink)", font: "inherit", resize: "none" }}/>
            <div style={{ textAlign: "right" }}><Btn size="sm" variant="primary" onClick={() => window.forgeToast && window.forgeToast("Reply queued — wired in v2")}>Send</Btn></div>
          </div>
        </div>
      </Panel>
    </div>
  );
}

// ---------- APPROVALS ----------
function ScreenApprovals() {
  const tenant = useActiveTenant();
  const isTritan = !!(tenant && tenant.tenant && tenant.tenant.id === "tritan");
  // Resolve a real person name from tenant.people when only an id/role is on the ledger.
  function _resolveActorName(label) {
    if (!label) return "—";
    if (!tenant || !tenant.people || !tenant.people.length) return label;
    const lower = label.toLowerCase();
    for (const p of tenant.people) {
      const name = (p.name || p.full_name || "");
      const id   = (p.id || p.handle || "");
      const role = (p.role || "");
      if (name && lower === name.toLowerCase()) return name;
      if (id   && lower === id.toLowerCase())   return name || label;
      if (role && lower === role.toLowerCase()) return name || label;
    }
    return label;
  }
  // For deep tenants, derive the timeline from tenant.ledger.
  // Tritan preserves its full view; other tenants restrict to eco_* events (last 5).
  // Wave 6B: filter is case-insensitive — Tritan uses lowercase eco_* event types
  // while Aetherion + Mittelstand use uppercase ECO_RAISED / ECO_APPROVED /
  // ECO_BOARD_REVIEW. Without case-folding, deep non-Tritan timelines were empty
  // and fell back to the HTU-220 turbine placeholder rows below.
  const tenantTimeline = (tenant && tenant.ledger && tenant.ledger.length)
    ? (function() {
        const all = tenant.ledger.slice().reverse();
        const filtered = isTritan
          ? all.slice(0, 10)
          : all.filter(function(e) { return e.type && e.type.toLowerCase().indexOf("eco_") === 0; }).slice(0, 5);
        return filtered.map(function(e, i) {
          var typeLower = (e.type || "").toLowerCase();
          var st = typeLower && (typeLower.indexOf("approval_reject") >= 0 || typeLower.indexOf("block") >= 0) ? "err"
                 : typeLower && typeLower.indexOf("eco_") >= 0 ? "info"
                 : typeLower && typeLower.indexOf("warn") >= 0 ? "warn"
                 : "ok";
          var day = i === 0 ? "Today" : i === 1 ? "Today" : i < 4 ? "Yday" : ("-" + Math.min(7, i-2) + "d");
          var t = (e.ts || "").slice(11, 16) || "—";
          var role = (e.actor_role || (e.mode === "build" ? "Design" : "Operations"));
          return [day, t, _resolveActorName(e.actor), role, e.summary || e.type || "—", st];
        });
      })()
    : null;
  // Wave 6B: gate the demo timeline + pending fallbacks so non-Tritan tenants
  // surface an empty state rather than the HTU-220 turbine placeholder rows
  // when the real ledger / eco list resolves to nothing.
  const _showHtuDemoFallback = isTritan;
  const pending = (tenant && tenant.eco && tenant.eco.length)
    ? (function() {
        const out = [];
        for (const e of tenant.eco) {
          // Tritan uses `status`, Aetherion+Mittelstand use `state`. Accept any
          // "pending review" shape so the queue surfaces non-Tritan ECOs too.
          const eState = e.status || e.state;
          const inReview = eState === "in-review" || eState === "board-review";
          if (!inReview) continue;
          const chain = e.approval_chain || [];
          for (const c of chain) {
            if (c.status !== "pending") continue;
            out.push({
              id:     e.id,
              title:  e.title + " · " + c.role + " (" + c.name + ")",
              sev:    "high",
              role:   c.role,
              name:   c.name,
              isLive: true,
            });
          }
        }
        return out;
      })()
    : null;
  return (
    <div style={{ padding: 14, display: "grid", gridTemplateColumns: "1fr 360px", gap: 14, height: "100%", minHeight: 0 }}>
      <Panel title="Approvals timeline · last 7 days">
        <div style={{ padding: 16 }}>
          <div style={{ position: "relative" }}>
            <div style={{ position: "absolute", left: 14, top: 0, bottom: 0, width: 2, background: "var(--line-soft)" }}/>
            {(function() {
              // Wave 6B: prefer tenant-derived rows; fall back to the HTU-220
              // turbine demo only for Tritan. Non-Tritan tenants with an empty
              // derived timeline show an empty state instead of a turbine leak.
              var rows;
              if (tenantTimeline && tenantTimeline.length) rows = tenantTimeline;
              else if (_showHtuDemoFallback) rows = [
                ["Today","09:41","S. Okafor","PGM Lead","Reviewed DR-3 pre-read","ok"],
                ["Today","09:28","J. Park","Structures","Submitted ECO-2611 (severity: HIGH)","info"],
                ["Today","08:55","A. Ibrahim","Thermal","Approved SIM-0409 report","ok"],
                ["Yday","17:04","M. Chen","Manufacturing","Rejected ECO-2608 rev-1 — clearance to cabinet door","err"],
                ["Yday","15:15","R. Larsen","Quality","Signed off ECO-2609 — supplier swap pitch bearing","ok"],
                ["Yday","10:03","ERP Planner","Supply","Flagged HTU-220.40.02 — cost-center missing on rev B","warn"],
                ["-2d","14:50","S. Okafor","PGM Lead","Scheduled DR-3 for 2026-05-14","info"],
                ["-2d","09:00","J. Park","Structures","Submitted SIM-0412 modal study","info"],
                ["-3d","16:30","A. Ibrahim","Thermal","Approved gearbox thermal steady","ok"],
                ["-5d","11:12","R. Larsen","Quality","Issued FAT checklist rev A","ok"],
              ];
              else rows = [];
              if (!rows.length) {
                return (
                  <div style={{ padding: "16px 16px 8px 30px", fontSize: 12, color: "var(--ink-3)" }}>
                    No approval activity in the last 7 days for this tenant.
                  </div>
                );
              }
              return rows.map(function(r, i) {
                var day = r[0], t = r[1], who = r[2], role = r[3], what = r[4], st = r[5];
                return (
                  <div key={(what || "") + "·" + i} style={{ display: "grid", gridTemplateColumns: "30px 64px 1fr auto", gap: 10, alignItems: "start", marginLeft: 0, padding: "10px 0" }}>
                    <div style={{ paddingLeft: 10 }}>
                      <div style={{ width: 10, height: 10, borderRadius: 10, background: "var(--" + (st==="ok"?"ok":st==="err"?"err":st==="warn"?"warn":"info") + ")", position: "relative", zIndex: 1 }}/>
                    </div>
                    <div>
                      <div className="mono tnum" style={{ fontSize: 12, color: "var(--ink-3)" }}>{day}</div>
                      <div className="mono tnum" style={{ fontSize: 12, color: "var(--ink-2)" }}>{t}</div>
                    </div>
                    <div>
                      <div style={{ fontSize: 12, color: "var(--ink)" }}><b style={{ fontWeight: 500 }}>{who}</b> <span className="muted">· {role}</span></div>
                      <div style={{ fontSize: 12, color: "var(--ink-2)" }}>{what}</div>
                    </div>
                    <Pill tone={st}>{st}</Pill>
                  </div>
                );
              });
            })()}
          </div>
        </div>
      </Panel>

      <Panel title="Pending your sign-off">
        <div style={{ padding: 8 }}>
          {(function() {
            // Wave 6B: same fallback gating as the timeline — only Tritan sees
            // the HTU-220 Blade laminate / SIM-0412 / ITM-0041 demo rows when
            // tenant.eco yields no in-review chain items. Non-Tritan shows an
            // empty state when its real eco list is empty.
            var items;
            if (pending && pending.length) items = pending;
            else if (_showHtuDemoFallback) items = [
              { id: "ECO-2611", title: "Blade laminate L-7 → L-8", sev: "high",   isLive: false },
              { id: "SIM-0412", title: "Modal · approve deliverable", sev: "medium", isLive: false },
              { id: "ITM-0041", title: "ERP sync · resolve UOM drift", sev: "medium", isLive: false },
            ];
            else items = [];
            if (!items.length) {
              return (
                <div style={{ padding: 12, fontSize: 12, color: "var(--ink-3)" }}>
                  No items awaiting your sign-off.
                </div>
              );
            }
            return items.map(function(p) {
            // Wave 3C item 25: wire Approve/Reject to forgeApi.eco.transition.
            // Only live entries (derived from tenant.eco) are wired; the stub
            // demo entries above stay disabled so we never POST a bogus ECO id.
            const cur2 = (typeof window !== "undefined" && window.__forgeCurrentUser) || { name: "—", role: "—" };
            function doApprove() {
              if (!p.isLive) return;
              window.forgeApi.eco.transition(p.id, "approve", {
                actor: cur2.name,
                role:  p.role || cur2.role,
              });
            }
            function doReject() {
              if (!p.isLive) return;
              window.forgeApi.eco.transition(p.id, "reject", {
                actor: cur2.name,
                role:  p.role || cur2.role,
              });
            }
            return (
              <div key={p.id} style={{ padding: "10px 10px", borderBottom: "1px solid var(--line-soft)" }}>
                <div style={{ display: "flex", justifyContent: "space-between" }}>
                  <span className="mono" style={{ fontSize: 12, color: "var(--ink-3)" }}>{p.id}</span>
                  <Pill tone={p.sev==="high"?"err":"warn"}>{p.sev}</Pill>
                </div>
                <div style={{ fontSize: 12, color: "var(--ink)", marginTop: 2 }}>{p.title}</div>
                <div style={{ display: "flex", gap: 6, marginTop: 8 }}>
                  <Btn size="sm" icon="Check" variant="primary" onClick={doApprove} disabled={!p.isLive}>Approve</Btn>
                  <Btn size="sm" icon="X" onClick={doReject} disabled={!p.isLive}>Reject</Btn>
                  <Btn size="sm" variant="ghost" icon="More" onClick={() => window.forgeToast && window.forgeToast("Delegation queued — wired in v2")}>Delegate</Btn>
                </div>
              </div>
            );
            });
          })()}
        </div>
      </Panel>
    </div>
  );
}

Object.assign(window, { ScreenSimSetup, ScreenSimResults, ScreenERP, ScreenECO, ScreenApprovals });
