// ===== Dapur (Induk + Satelit) Screens =====
const { useState: useS_D, useMemo: useM_D } = React;
const { MESSAGE_TYPES, STATUS_TYPES } = window.IDSS;

function DapurDashboard({ role, scenario, porsi, onEWSClick }) {
  const { ALERTS_AKTIF, MENU_MINGGU, SEKOLAH_INDUK, SEKOLAH_SATELIT, DAPUR_DELIVERY_TRACKING, SUPPLIER_PENGIRIMAN } = window.IDSS;
  const { KPI, Sparkline, Icon, Donut, BarMini } = window.IDSSUI;
  const SEKOLAH = role.id === "induk" ? SEKOLAH_INDUK : SEKOLAH_SATELIT;

  // ===== NEW: Track supplier deliveries to this dapur =====
  const dapurId = role.id === "induk" ? "D1" : "D2";
  const [refreshKey, setRefreshKey] = useS_D(0); // Trigger local re-render on refresh

  const todayDeliveries = (DAPUR_DELIVERY_TRACKING || []).filter(d => d.dapurId === dapurId);
  const totalDelivered = todayDeliveries.reduce((sum, d) => sum + d.volumeDiterima, 0);
  const deliveryStatus = todayDeliveries.length > 0 ? "Bahan tiba ✓" : "Menunggu pengiriman";

  const totalJiwa = SEKOLAH.reduce((s, x) => s + x.siswa, 0);
  const diterima = SEKOLAH.filter(s => s.status === "diterima").reduce((s,x)=>s+x.siswa, 0);
  const alertWarn = ALERTS_AKTIF.filter(a => a.level === "warn").length;
  const alertDanger = ALERTS_AKTIF.filter(a => a.level === "danger").length;
  const lokasiTerlayani = SEKOLAH.filter(s => s.status === "diterima").length;
  const lokasiMenunggu = SEKOLAH.filter(s => s.status !== "diterima").length;
  const porsiProduced = diterima;
  const pctProduced = Math.round((porsiProduced / porsi) * 100);

  const handleRefresh = () => setRefreshKey(k => k + 1);

  const handleExportCSV = () => {
    const { DAPUR_QUALITY_FEEDBACK } = window.IDSS;
    const today = new Date().toISOString().split('T')[0];
    const todayFeedback = (DAPUR_QUALITY_FEEDBACK || []).filter(f => f.dapurId === dapurId && f.tanggal === today);

    const headers = ["Sekolah", "Status", "Tanggal", "Jam"];
    const rows = todayFeedback.map(f => [
      f.sekolahNama,
      f.status,
      f.tanggal,
      f.jam
    ]);
    const csv = [headers, ...rows].map(r => r.map(v => `"${v}"`).join(",")).join("\n");
    const blob = new Blob([csv], { type: "text/csv" });
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = `Dapur-Feedback-${dapurId}-${today}.csv`;
    a.click();
  };

  // Phase 2: Listen for PENERIMA quality feedback broadcasts
  React.useEffect(() => {
    const handleQualityFeedback = (event) => {
      if (event.data?.type === MESSAGE_TYPES.QUALITY_FEEDBACK_SUBMITTED) {
        const feedback = event.data.payload || event.data.feedback;
        if (feedback && feedback.dapurId === dapurId) {
          // This feedback is for our dapur - add to DAPUR_QUALITY_FEEDBACK if not already present
          const { DAPUR_QUALITY_FEEDBACK } = window.IDSS;
          if (DAPUR_QUALITY_FEEDBACK && !DAPUR_QUALITY_FEEDBACK.find(f => f.id === feedback.id)) {
            DAPUR_QUALITY_FEEDBACK.push(feedback);
            // Trigger UI re-render
            setRefreshKey(k => k + 1);
            // C1: Audit log
            window.AuditLog?.log('feedback_received', {
              feedbackId: feedback.id,
              menu: feedback.menu,
              status: feedback.status,
              pejabat: feedback.pejabatNama
            });
          }
        }
      }
    };

    window.addEventListener("message", handleQualityFeedback);
    return () => window.removeEventListener("message", handleQualityFeedback);
  }, [dapurId]);

  return (
    <>
      <div className="page-header">
        <div>
          <div className="crumbs"><span>{role.short}</span><span>Dashboard</span><span>Pilot Cianjur</span></div>
          <h1 className="page-title">Operasional Hari Ini</h1>
          <div className="page-sub">📍 {role.location} · target {porsi.toLocaleString("id-ID")} porsi/hari</div>
        </div>
        <div className="row gap-sm">
          <button className="btn" onClick={handleRefresh}><Icon name="refresh" size={14}/> Refresh</button>
        </div>
      </div>

      {/* C4: SLA Warning Card */}
      {(() => {
        const metrics = window.SLATracker?.calculateSLAMetrics(window.IDSS?.SAFCC_REQUESTS || []);
        const overdueRequests = window.SLATracker?.getOverdueRequests(window.IDSS?.SAFCC_REQUESTS || []) || [];
        if (metrics && metrics.overdue > 0) {
          return (
            <div style={{
              background: 'var(--danger-50)',
              border: '1px solid var(--danger-100)',
              borderRadius: 'var(--radius-lg)',
              padding: '14px 16px',
              marginBottom: 16,
              color: 'var(--danger)'
            }}>
              <div style={{ fontSize: 13, fontWeight: 600 }}>⚠️ {metrics.overdue} Request Overdue</div>
              <div style={{ fontSize: 12, marginTop: 6 }}>
                {overdueRequests.slice(0, 3).map(r => (
                  <div key={r.id}>• {r.komoditas} ({window.SLATracker.calculateOverdue(r.deadline)} hari terlambat)</div>
                ))}
              </div>
              <div style={{ fontSize: 11, marginTop: 8, color: 'var(--ink-2)' }}>
                On-time rate: {metrics.onTimePercent}%
              </div>
            </div>
          );
        }
        return null;
      })()}

      {scenario === "krisis" && (
        <div className="alert danger fade-up" style={{ marginBottom: 20 }}>
          <div style={{ color: "var(--danger)" }}><Icon name="bell" size={18}/></div>
          <div>
            <div className="alert-title">Skenario aktif: Krisis pasokan dari SAFCC</div>
            <div className="alert-body">Stok ayam &amp; bayam tidak mencukupi target hari ini. Sistem otomatis menyiapkan menu alternatif (lihat Optimasi Menu).</div>
          </div>
        </div>
      )}

      {/* ===== NEW: Supplier delivery status =====  */}
      {todayDeliveries.length > 0 && (
        <div className="alert info fade-up" style={{ marginBottom: 20 }}>
          <div style={{ color: "var(--info)" }}><Icon name="box" size={18}/></div>
          <div>
            <div className="alert-title">Pengiriman dari Supplier hari ini</div>
            <div className="alert-body">
              {todayDeliveries.map((d, i) => (
                <span key={d.id} style={{ marginRight: 16, display: "inline-block" }}>
                  <strong>{d.komoditas}</strong> {d.volumeDiterima} kg
                  {i < todayDeliveries.length - 1 && " •"}
                </span>
              ))}
            </div>
          </div>
        </div>
      )}

      <div className="grid cols-4" style={{ marginBottom: 24 }}>
        <KPI intent="primary" label="Total Penerima Manfaat" value={totalJiwa.toLocaleString("id-ID")} unit="jiwa"
          delta={`${((diterima/totalJiwa)*100).toFixed(1)}% sudah terlayani`} deltaKind="up"
          spark={<Sparkline data={[1620,1640,1655,1680,1700,1715,1720,totalJiwa]} color="var(--primary)"/>}/>
        <KPI label="Alert EWS Aktif" value={ALERTS_AKTIF.length} unit="alert hari ini"
          delta={`${alertDanger} kritis · ${alertWarn} peringatan`} deltaKind={alertDanger > 0 ? "down" : "flat"}
          spark={<Sparkline data={[2,1,3,2,4,3,5,4]} color="var(--warn)"/>}/>
        <KPI label="Porsi Diproduksi" value={porsiProduced.toLocaleString("id-ID")} unit={`/ ${porsi.toLocaleString("id-ID")}`}
          delta={`${pctProduced}% target`} deltaKind="up"
          spark={<Sparkline data={[88,90,89,92,91,93,94,pctProduced]} color="var(--accent)"/>}/>
        <KPI label="Lokasi Terlayani" value={`${lokasiTerlayani}/${SEKOLAH.length}`} unit="titik (sekolah & posyandu)"
          delta={`${lokasiMenunggu} menunggu`} deltaKind="flat"
          spark={<Sparkline data={[5,6,6,5,6,6,6,lokasiTerlayani]} color="var(--info)"/>}/>
      </div>

      <div className="grid cols-12" style={{ marginBottom: 24 }}>
        <div className="card" style={{ gridColumn: "span 7" }}>
          <div className="card-head">
            <h2 className="h2">Alert EWS Aktif Hari Ini</h2>
            <button className="btn sm" onClick={onEWSClick} style={{ fontSize: 12, border: "1px solid var(--primary)", color: "var(--primary)", background: "transparent" }}>Buka EWS →</button>
          </div>
          <div style={{ display: "flex", flexDirection: "column" }}>
            {ALERTS_AKTIF.map((a, i) => (
              <div key={a.id} style={{
                display: "grid", gridTemplateColumns: "auto 1fr auto",
                gap: 14, padding: "14px 24px",
                borderBottom: i < ALERTS_AKTIF.length - 1 ? "1px solid var(--line-2)" : "0",
                alignItems: "start"
              }}>
                <div style={{
                  width: 36, height: 36, borderRadius: 8,
                  background: a.level === "danger" ? "var(--danger-100)" : "var(--warn-100)",
                  color: a.level === "danger" ? "var(--danger)" : "oklch(0.45 0.16 55)",
                  display: "grid", placeItems: "center", flexShrink: 0
                }}>
                  <Icon name="bell" size={16}/>
                </div>
                <div style={{ minWidth: 0 }}>
                  <div className="row gap-xs" style={{ marginBottom: 3 }}>
                    <span className="tag mono" style={{ fontSize: 10 }}>{a.tahap}</span>
                    <span className="muted" style={{ fontSize: 11 }}>{a.komoditas} · {a.waktu}</span>
                  </div>
                  <div style={{ fontWeight: 600, fontSize: 13 }}>{a.judul}</div>
                  <div className="muted" style={{ fontSize: 12, marginTop: 2 }}><b style={{ color: "var(--ink-2)" }}>Aksi:</b> {a.aksi}</div>
                </div>
                <div className="col gap-xs" style={{ alignItems: "flex-end" }}>
                  {a.level === "danger" ? <span className="pill danger"><span className="led pulse"/>Kritis</span> : <span className="pill warn"><span className="led"/>Peringatan</span>}
                </div>
              </div>
            ))}
          </div>
        </div>

        <div className="card" style={{ gridColumn: "span 5" }}>
          <div className="card-head"><h2 className="h2">Distribusi ke Penerima Manfaat</h2><span className="tag mono">{SEKOLAH.length} titik</span></div>
          <div className="card-body" style={{ paddingTop: 12 }}>
            <div className="row" style={{ alignItems: "center", gap: 18, marginBottom: 18 }}>
              <Donut value={diterima} max={totalJiwa} size={88} color="var(--accent)" label={`${Math.round((diterima/totalJiwa)*100)}%`}/>
              <div style={{ flex: 1 }}>
                <div className="eyebrow">Cakupan distribusi</div>
                <div style={{ fontFamily: "var(--font-display)", fontSize: 22, fontWeight: 600, marginTop: 4 }}>
                  {diterima.toLocaleString("id-ID")} <span className="muted" style={{ fontSize: 13, fontWeight: 400 }}>/ {totalJiwa.toLocaleString("id-ID")} jiwa</span>
                </div>
                <div className="muted" style={{ fontSize: 12, marginTop: 4 }}>Estimasi penyelesaian: <b style={{ color: "var(--ink-2)" }}>10:15 WIB</b></div>
              </div>
            </div>
            <div style={{ display: "flex", flexDirection: "column", gap: 6, maxHeight: 320, overflowY: "auto" }}>
              {SEKOLAH.map(s => (
                <div key={s.id} className="row between" style={{ padding: "8px 10px", background: s.status === "diterima" ? "var(--bg-2)" : "var(--warn-100)", borderRadius: 4, fontSize: 12 }}>
                  <div style={{ minWidth: 0 }}>
                    <div style={{ fontWeight: 500, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{s.nama}</div>
                    <div className="muted" style={{ fontSize: 10.5 }}>{s.segmen} · {s.siswa} jiwa</div>
                  </div>
                  <span className="row gap-xs" style={{ flexShrink: 0 }}>
                    <span className="mono" style={{ fontSize: 11 }}>{s.waktu}</span>
                    {s.status === "diterima" ? <span className="pill ok"><span className="led"/>OK</span> : <span className="pill warn"><span className="led"/>Delay</span>}
                  </span>
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>

      {/* ===== NEW: Production Schedule for today ===== */}
      {(() => {
        const DAPUR_PRODUCTION_PLAN = window.IDSS.DAPUR_PRODUCTION_PLAN || [];
        const todayPlan = DAPUR_PRODUCTION_PLAN.find(p => p.dapurId === dapurId);
        if (todayPlan?.scheduled) {
          const deliveryAccepted = todayDeliveries.length > 0;
          return (
            <div className="card" style={{ marginBottom: 24 }}>
              <div className="card-head">
                <h2 className="h2">Jadwal Produksi & Pengiriman Hari Ini</h2>
                <span className={`pill ${deliveryAccepted ? "ok" : "warn"}`} style={{ fontSize: 10 }}>
                  {deliveryAccepted ? "✓ Siap Produksi" : "⏳ Menunggu Bahan"}
                </span>
              </div>
              <div className="card-body" style={{ padding: 0 }}>
                <table className="data" style={{ width: "100%", fontSize: 12.5 }}>
                  <thead>
                    <tr>
                      <th style={{ textAlign: "left" }}>Sekolah / Posyandu</th>
                      <th style={{ textAlign: "center" }}>Segmen</th>
                      <th style={{ textAlign: "right" }}>Porsi</th>
                      <th style={{ textAlign: "left" }}>Menu</th>
                      <th style={{ textAlign: "center" }}>Estimasi Tiba</th>
                    </tr>
                  </thead>
                  <tbody>
                    {todayPlan.scheduled.map(s => (
                      <tr key={s.sekolahId} style={{ background: deliveryAccepted ? "transparent" : "var(--bg-2)" }}>
                        <td style={{ fontWeight: 500 }}>{s.sekolahNama}</td>
                        <td style={{ textAlign: "center", fontSize: 11 }}><span className="tag">{s.segmen}</span></td>
                        <td style={{ textAlign: "right", fontWeight: 600 }}>{s.siswa}</td>
                        <td style={{ fontSize: 11.5 }}>{s.menu}</td>
                        <td style={{ textAlign: "center", fontSize: 11, color: "var(--ink-3)" }}>{s.estimatedDelivery}</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
                <div style={{ padding: 12, background: "var(--bg-2)", borderTop: "1px solid var(--line)", fontSize: 12 }}>
                  <strong>Total porsi:</strong> {todayPlan.scheduled.reduce((s, x) => s + x.siswa, 0).toLocaleString("id-ID")} porsi
                  {deliveryAccepted && <span style={{ marginLeft: 20, color: "var(--accent)" }}>✓ Bahan sudah tiba, siap produksi</span>}
                </div>
              </div>
            </div>
          );
        }
        return null;
      })()}

      {(() => {
        const { DAPUR_QUALITY_FEEDBACK } = window.IDSS;
        const today = new Date().toISOString().split('T')[0];
        const todayFeedback = (DAPUR_QUALITY_FEEDBACK || []).filter(f => f.dapurId === dapurId && f.tanggal === today);
        const passed = todayFeedback.filter(f => f.status === STATUS_TYPES.LULUS).length;
        const hasMajor = todayFeedback.filter(f => f.status === STATUS_TYPES.MAJOR).length;
        const hasMinor = todayFeedback.filter(f => f.status === STATUS_TYPES.MINOR).length;

        if (todayFeedback.length === 0) {
          return null;
        }

        return (
          <div className="card" style={{ marginBottom: 24 }}>
            <div className="card-head">
              <h2 className="h2">Penilaian Kualitas dari Sekolah (Hari Ini)</h2>
              <div className="row gap-xs">
                <span className="pill ok" style={{ fontSize: 10 }}>✓ {passed} lulus</span>
                {hasMajor > 0 && <span className="pill danger" style={{ fontSize: 10 }}>🔴 {hasMajor} major</span>}
                {hasMinor > 0 && <span className="pill warn" style={{ fontSize: 10 }}>⚠ {hasMinor} minor</span>}
              </div>
            </div>
            <div className="card-body">
              {todayFeedback.map(f => (
                <div key={f.id} style={{
                  padding: 12,
                  marginBottom: 10,
                  background: f.status === STATUS_TYPES.LULUS ? "var(--accent-50)" : f.status === STATUS_TYPES.MAJOR ? "var(--danger-50)" : "var(--warn-50)",
                  borderLeft: `3px solid ${f.status === STATUS_TYPES.LULUS ? "var(--accent)" : f.status === STATUS_TYPES.MAJOR ? "var(--danger)" : "var(--warn)"}`,
                  borderRadius: "var(--radius-md)"
                }}>
                  <div className="row between" style={{ marginBottom: 6 }}>
                    <div style={{ fontWeight: 600, fontSize: 13 }}>{f.sekolahNama}</div>
                    <span className={`pill ${f.status === STATUS_TYPES.LULUS ? "ok" : f.status === STATUS_TYPES.MAJOR ? "danger" : "warn"}`} style={{ fontSize: 10 }}>
                      {f.status === STATUS_TYPES.LULUS ? "LULUS" : f.status === STATUS_TYPES.MAJOR ? "MAJOR ISSUE" : "MINOR ISSUE"}
                    </span>
                  </div>
                  <div className="muted" style={{ fontSize: 11, marginBottom: 8 }}>
                    Menu: {f.menu} • {f.passedCount}/{f.totalCount} kriteria terpenuhi
                  </div>
                  <div style={{ fontSize: 12, display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 8 }}>
                    <div style={{ color: f.verifikasi.kemasan ? "var(--accent-700)" : "var(--ink-3)" }}>
                      <div>{f.verifikasi.kemasan ? "✓" : "✗"} Kemasan</div>
                      {!f.verifikasi.kemasan && f.alasanPenolakan?.C1 && <div style={{ fontSize: 10, color: "var(--ink-3)", fontStyle: "italic", marginTop: 2 }}>"{f.alasanPenolakan.C1}"</div>}
                    </div>
                    <div style={{ color: f.verifikasi.aroma ? "var(--accent-700)" : "var(--ink-3)" }}>
                      <div>{f.verifikasi.aroma ? "✓" : "✗"} Aroma</div>
                      {!f.verifikasi.aroma && f.alasanPenolakan?.C2 && <div style={{ fontSize: 10, color: "var(--ink-3)", fontStyle: "italic", marginTop: 2 }}>"{f.alasanPenolakan.C2}"</div>}
                    </div>
                    <div style={{ color: f.verifikasi.warna ? "var(--accent-700)" : "var(--ink-3)" }}>
                      <div>{f.verifikasi.warna ? "✓" : "✗"} Warna</div>
                      {!f.verifikasi.warna && f.alasanPenolakan?.C3 && <div style={{ fontSize: 10, color: "var(--ink-3)", fontStyle: "italic", marginTop: 2 }}>"{f.alasanPenolakan.C3}"</div>}
                    </div>
                    <div style={{ color: f.verifikasi.tekstur ? "var(--accent-700)" : "var(--ink-3)" }}>
                      <div>{f.verifikasi.tekstur ? "✓" : "✗"} Tekstur</div>
                      {!f.verifikasi.tekstur && f.alasanPenolakan?.C4 && <div style={{ fontSize: 10, color: "var(--ink-3)", fontStyle: "italic", marginTop: 2 }}>"{f.alasanPenolakan.C4}"</div>}
                    </div>
                    <div style={{ color: f.verifikasi.suhu ? "var(--accent-700)" : "var(--ink-3)" }}>
                      <div>{f.verifikasi.suhu ? "✓" : "✗"} Suhu</div>
                      {!f.verifikasi.suhu && f.alasanPenolakan?.C5 && <div style={{ fontSize: 10, color: "var(--ink-3)", fontStyle: "italic", marginTop: 2 }}>"{f.alasanPenolakan.C5}"</div>}
                    </div>
                    <div style={{ color: f.verifikasi.etiket ? "var(--accent-700)" : "var(--ink-3)" }}>
                      <div>{f.verifikasi.etiket ? "✓" : "✗"} Etiket</div>
                      {!f.verifikasi.etiket && f.alasanPenolakan?.C6 && <div style={{ fontSize: 10, color: "var(--ink-3)", fontStyle: "italic", marginTop: 2 }}>"{f.alasanPenolakan.C6}"</div>}
                    </div>
                  </div>
                  <div className="muted" style={{ fontSize: 11, marginTop: 8 }}>
                    — {f.pejabat}
                  </div>
                </div>
              ))}
            </div>
          </div>
        );
      })()}

      {(() => {
        const { DAPUR_QUALITY_FEEDBACK, PENERIMA_CHECKLIST_CRITERIA } = window.IDSS;
        const allFeedback = (DAPUR_QUALITY_FEEDBACK || []).filter(f => f.dapurId === dapurId);
        if (allFeedback.length === 0) return null;

        const failureCount = {};
        const reasonFreq = {};
        PENERIMA_CHECKLIST_CRITERIA.forEach(crit => {
          failureCount[crit.id] = 0;
          reasonFreq[crit.id] = {};
        });

        allFeedback.forEach(f => {
          PENERIMA_CHECKLIST_CRITERIA.forEach((crit, idx) => {
            const critKey = ['kemasan', 'aroma', 'warna', 'tekstur', 'suhu', 'etiket'][idx];
            if (!f.verifikasi[critKey]) {
              failureCount[crit.id]++;
              const reason = f.alasanPenolakan?.[crit.id] || "Tidak disebutkan";
              reasonFreq[crit.id][reason] = (reasonFreq[crit.id][reason] || 0) + 1;
            }
          });
        });

        const totalFailures = Object.values(failureCount).reduce((a, b) => a + b, 0);
        const maxFailures = Math.max(...Object.values(failureCount), 1);
        const hasAnyFailure = maxFailures > 0;

        if (!hasAnyFailure) return null;

        return (
          <div className="card" style={{ marginBottom: 24 }}>
            <div className="card-head">
              <h2 className="h2">Analitik Penolakan</h2>
              <div style={{ fontSize: 11, color: "var(--fg-3)" }}>
                {totalFailures} penolakan dari {allFeedback.length} feedback
              </div>
            </div>
            <div className="card-body">
              <div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
                {PENERIMA_CHECKLIST_CRITERIA.map(crit => {
                  const fails = failureCount[crit.id];
                  const topReason = Object.entries(reasonFreq[crit.id] || {})
                    .sort(([_, a], [__, b]) => b - a)[0];
                  const topReasonText = topReason ? `${topReason[0]}` : null;
                  const reasonCount = topReason ? topReason[1] : 0;
                  const barWidth = maxFailures > 0 ? (fails / maxFailures * 100) : 0;

                  if (fails === 0) {
                    return (
                      <div key={crit.id} style={{ opacity: 0.4 }}>
                        <div className="row between" style={{ marginBottom: 6 }}>
                          <div style={{ fontWeight: 500, fontSize: 12 }}>{crit.nama}</div>
                          <div style={{ fontSize: 11, color: "var(--fg-3)" }}>—</div>
                        </div>
                        <div style={{ height: 4, background: "var(--line)", borderRadius: 2 }}></div>
                      </div>
                    );
                  }

                  return (
                    <div key={crit.id}>
                      <div className="row between" style={{ marginBottom: 6 }}>
                        <div style={{ fontWeight: 500, fontSize: 12 }}>{crit.nama}</div>
                        <div style={{ fontSize: 11, fontWeight: 600, color: "var(--warn)" }}>{fails}×</div>
                      </div>
                      <div style={{ height: 8, background: "var(--line)", borderRadius: 3, overflow: "hidden", marginBottom: 6 }}>
                        <div style={{ height: "100%", background: "var(--warn)", width: `${barWidth}%`, transition: "width 200ms" }}></div>
                      </div>
                      {topReasonText && (
                        <div style={{ fontSize: 10.5, color: "var(--fg-2)", fontStyle: "italic" }}>
                          "{topReasonText}" {reasonCount > 1 ? `(${reasonCount}×)` : ""}
                        </div>
                      )}
                    </div>
                  );
                })}
              </div>
            </div>
          </div>
        );
      })()}

      <div className="card">
        <div className="card-head"><h2 className="h2">Menu Rekomendasi Minggu Ini</h2><span className="tag">5 hari kerja</span></div>
        <div className="card-body" style={{ display: "grid", gridTemplateColumns: "repeat(5, 1fr)", gap: 12 }}>
          {MENU_MINGGU.map((m, i) => (
            <div key={m.hari} className="menu-card" style={{ borderLeft: `3px solid ${m.status === "tight" ? "var(--warn)" : "var(--accent)"}` }}>
              <div className="row between" style={{ marginBottom: 6 }}>
                <span className="eyebrow">{m.hari}</span>
                {m.status === "tight" ? <span className="pill warn"><span className="led"/>tight</span> : <span className="pill ok"><span className="led"/>feasible</span>}
              </div>
              <div style={{ fontSize: 12.5, lineHeight: 1.45, fontWeight: 500, color: "var(--ink-2)", minHeight: 60 }}>{m.menu}</div>
              <div className="hr" style={{ margin: "10px 0 8px" }}/>
              <div className="row between" style={{ fontSize: 11 }}>
                <span><span className="muted">Kal </span><span className="mono" style={{ fontWeight: 600 }}>{m.kal}</span></span>
                <span><span className="muted">Prot </span><span className="mono" style={{ fontWeight: 600 }}>{m.prot}g</span></span>
              </div>
              <div className="row between" style={{ fontSize: 11, marginTop: 4 }}>
                <span className="muted">Biaya/porsi</span>
                <span className="mono" style={{ fontWeight: 700, color: "var(--primary)" }}>Rp {m.biaya.toLocaleString("id-ID")}</span>
              </div>
            </div>
          ))}
        </div>
      </div>

      {/* C1: Export Audit Log Button */}
      <div className="card" style={{ marginTop: 16 }}>
        <div className="card-head"><h2 className="h2">Utilitas</h2></div>
        <div className="card-body" style={{ display: "grid", gridTemplateColumns: "repeat(2, 1fr)", gap: 10 }}>
          <button className="btn" onClick={() => window.AuditLog?.exportCSV()} style={{
            padding: '11px 14px',
            borderRadius: 'var(--radius-lg)',
            background: 'var(--primary-50)',
            color: 'var(--primary)',
            border: '1px solid var(--primary-100)',
            cursor: 'pointer',
            fontSize: 13,
            fontWeight: 500
          }}>
            📋 Ekspor Audit Log
          </button>
        </div>
      </div>
    </>
  );
}

function MenuOptimasi({ porsi }) {
  const { MENU_DB } = window.IDSS;
  const { Icon } = window.IDSSUI;

  // Enhanced nutrition presets with energy targets and budget constraints
  // Budget hard limit: Rp 10.000 per porsi untuk semua kelompok usia (Program MBG)
  // costPerGram adjusted agar (gram × costPerGram) ≤ 10.000 dengan buffer safety
  const enhancedPresets = [
    { label: "TK/PAUD/RA", energyKcal: 328, protein: 20.5, lemak: 8.637, karbo: 17.138, gram: 250, costPerGram: 30, budgetTarget: 7500 },
    { label: "Siswa SD (1–3)", energyKcal: 368.8, protein: 21.2982, lemak: 9.876, karbo: 18.532, gram: 300, costPerGram: 25, budgetTarget: 7500 },
    { label: "Siswa SD (4–6)", energyKcal: 531, protein: 43.94, lemak: 18.231, karbo: 41.153, gram: 400, costPerGram: 20, budgetTarget: 8000 },
    { label: "Siswa SMP", energyKcal: 719, protein: 62.553, lemak: 24.526, karbo: 55.363, gram: 500, costPerGram: 18, budgetTarget: 9000 },
    { label: "Siswa SMA", energyKcal: 762.5, protein: 69.388, lemak: 26.264, karbo: 57.95, gram: 550, costPerGram: 16, budgetTarget: 8800 },
    { label: "Ibu Hamil", energyKcal: 818, protein: 82.618, lemak: 29.175, karbo: 65.236, gram: 600, costPerGram: 15, budgetTarget: 9000 },
    { label: "Ibu Menyusui", energyKcal: 818, protein: 108.181, lemak: 29.266, karbo: 62.986, gram: 620, costPerGram: 15, budgetTarget: 9300 },
    { label: "Anak Balita", energyKcal: 342, protein: 40.185, lemak: 7.98, karbo: 17.1, gram: 280, costPerGram: 25, budgetTarget: 7000 }
  ];

  // ----- State -----
  const [preset, setPreset] = useS_D("Siswa SD (4–6)");
  const presetObj = enhancedPresets.find(p => p.label === preset) || enhancedPresets[2];

  const [target, setTarget] = useS_D({
    protein: presetObj.protein,
    lemak: presetObj.lemak,
    karbo: presetObj.karbo,
    gram: presetObj.gram,
    energyKcal: presetObj.energyKcal
  });
  React.useEffect(() => {
    setTarget({ protein: presetObj.protein, lemak: presetObj.lemak, karbo: presetObj.karbo, gram: presetObj.gram, energyKcal: presetObj.energyKcal });
  }, [preset]);

  // Selected ingredients per category (single-select for main groups, multi for snack)
  const [picked, setPicked] = useS_D({
    carbohydrate: "Nasi Putih",
    proteinAnimal: "Ayam Goreng",
    proteinPlant: "Tempe Orek",
    vegetable: "Tumis Bayam",
    fruit: "Pisang"
  });
  const [snacks, setSnacks] = useS_D([]);
  const [milkML, setMilkML] = useS_D(200);

  const togglePick = (cat, nama) => setPicked(p => ({ ...p, [cat]: p[cat] === nama ? "" : nama }));
  const toggleSnack = (nama) => setSnacks(s => s.includes(nama) ? s.filter(x => x !== nama) : [...s, nama]);
  const updTarget = (k, v) => { const n = parseFloat(v); if (!isNaN(n) && n >= 0) setTarget(t => ({ ...t, [k]: n })); };

  const handleExportMenuCSV = () => {
    const headers = ["Kategori", "Bahan", "Target Nutrisi"];
    const rows = [
      ["Karbohidrat", picked.carbohydrate, target.gram],
      ["Protein Hewani", picked.proteinAnimal, target.protein],
      ["Protein Nabati", picked.proteinPlant, ""],
      ["Sayuran", picked.vegetable, ""],
      ["Buah", picked.fruit, ""],
      ["Susu", `${milkML} ml`, ""],
      ["Camilan", snacks.join(", "), ""]
    ];
    const csv = [headers, ...rows].map(r => r.map(v => `"${v}"`).join(",")).join("\n");
    const blob = new Blob([csv], { type: "text/csv" });
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = `Menu-Optimasi-${new Date().toISOString().split('T')[0]}.csv`;
    a.click();
  };

  // Build active ingredient list
  const findIng = (cat, nama) => MENU_DB[cat]?.find(x => x.nama === nama);
  const activeIngs = useM_D(() => {
    const list = [];
    if (picked.carbohydrate)  list.push({ ...findIng("carbohydrate",  picked.carbohydrate),  cat: "Karbohidrat" });
    if (picked.proteinAnimal) list.push({ ...findIng("proteinAnimal", picked.proteinAnimal), cat: "Protein Hewani" });
    if (picked.proteinPlant)  list.push({ ...findIng("proteinPlant",  picked.proteinPlant),  cat: "Protein Nabati" });
    if (picked.vegetable)     list.push({ ...findIng("vegetable",     picked.vegetable),     cat: "Sayur" });
    if (picked.fruit)         list.push({ ...findIng("fruit",         picked.fruit),         cat: "Buah" });
    snacks.forEach(s => { const f = findIng("snack", s); if (f) list.push({ ...f, cat: "Snack" }); });
    if (milkML > 0) {
      // Susu UHT proxy: ~0.65 kkal/ml, p 3.4/100ml, l 3.5/100ml, k 4.8/100ml, harga ≈ 18 Rp/ml
      const g = milkML;
      list.push({ nama: `Susu UHT ${milkML} ml`, p: 3.4, l: 3.5, k: 4.8, s: 0, biayaPerG: 18, gMin: g, gMax: g, cat: "Susu" });
    }
    return list.filter(x => x.nama);
  }, [picked, snacks, milkML]);

  // ----- Optimization (3-phase priority-weighted, biaya ≤ 10.000) -----
  // Budget constraint: HARD LIMIT Rp 10.000 per porsi untuk semua kelompok usia (Program MBG)
  // Phase 1: Isi nutrient gaps dengan weighted priority (protein 2.0×, lemak 1.5×, karbo 1.0×)
  // Phase 2: Gunakan sisa budget untuk maximize protein
  // Phase 3: Pad ke target gram (nutrisi dulu jika masih ada gap, lalu gram murni)
  const BUDGET_MAX = 10000;
  const BUDGET_TARGET = presetObj.budgetTarget || 10000;
  const result = useM_D(() => {
    if (activeIngs.length === 0) return null;
    const ings = activeIngs.map(x => ({ ...x, gram: x.gMin }));

    const sumOf = (key, arr) => arr.reduce((a, x) => a + x.gram * (x[key] || 0) / 100, 0);
    const sumGram = (arr) => arr.reduce((a, x) => a + x.gram, 0);
    const sumCost = (arr) => arr.reduce((a, x) => a + x.gram * x.biayaPerG, 0);

    // ── Konstanta
    const NUTRIENT_WEIGHTS = { protein: 2.0, lemak: 1.5, karbo: 1.0 };
    const GAP_THRESHOLD_PCT = 0.05;
    const PROTEIN_UPPER_CAP = 1.20;
    const NUTRI_OVER_CAP = 1.15;
    const MAX_ITER = 600;

    // ── Pre-feasibility check
    const theoreticalMaxProtein = ings.reduce((s, x) => s + x.gMax * (x.p || 0) / 100, 0);
    const proteinFeasible = theoreticalMaxProtein >= target.protein;
    const infeasibilityWarning = !proteinFeasible
      ? `Protein max dari bahan dipilih (${theoreticalMaxProtein.toFixed(1)}g) di bawah target (${target.protein}g). Tambahkan bahan protein atau naikkan batas gram.`
      : null;

    // ── PHASE 1: Priority-Weighted Gap Filling
    let iter = 0;
    while (iter++ < MAX_ITER) {
      const gramLeft = target.gram - sumGram(ings);
      if (gramLeft <= 0) break;

      const cur = { protein: sumOf("p", ings), lemak: sumOf("l", ings), karbo: sumOf("k", ings) };
      const gaps = {
        protein: Math.max(0, target.protein - cur.protein),
        lemak:   Math.max(0, target.lemak   - cur.lemak),
        karbo:   Math.max(0, target.karbo   - cur.karbo)
      };
      const gapPct = {
        protein: gaps.protein / target.protein,
        lemak:   gaps.lemak / target.lemak,
        karbo:   gaps.karbo / target.karbo
      };

      if (gapPct.protein < GAP_THRESHOLD_PCT && gapPct.lemak < GAP_THRESHOLD_PCT && gapPct.karbo < GAP_THRESHOLD_PCT) break;

      const maxGapPct = Math.max(gapPct.protein, gapPct.lemak, gapPct.karbo);
      const rawStep = maxGapPct > 0.30 ? 10 : maxGapPct > 0.10 ? 5 : 2;
      const step = Math.min(rawStep, gramLeft);

      let bestIdx = -1, bestScore = -Infinity;
      ings.forEach((x, i) => {
        if (x.gram >= x.gMax) return;
        if (sumCost(ings) + step * x.biayaPerG > BUDGET_MAX) return;

        const protScore = cur.protein < target.protein * NUTRI_OVER_CAP
          ? NUTRIENT_WEIGHTS.protein * (x.p / 100) * gapPct.protein : 0;
        const lemakScore = cur.lemak < target.lemak * NUTRI_OVER_CAP
          ? NUTRIENT_WEIGHTS.lemak * (x.l / 100) * gapPct.lemak : 0;
        const karboScore = cur.karbo < target.karbo * NUTRI_OVER_CAP
          ? NUTRIENT_WEIGHTS.karbo * (x.k / 100) * gapPct.karbo : 0;

        const score = (protScore + lemakScore + karboScore) / x.biayaPerG;
        if (score > bestScore) { bestScore = score; bestIdx = i; }
      });

      if (bestIdx === -1 || bestScore <= 0) break;
      ings[bestIdx].gram = Math.min(ings[bestIdx].gMax, ings[bestIdx].gram + step);
    }

    // ── PHASE 2: Budget Utilization untuk Protein
    let iter2 = 0;
    const PROTEIN_CAP_GRAM = target.protein * PROTEIN_UPPER_CAP;
    while (iter2++ < 200) {
      if (sumOf("p", ings) >= PROTEIN_CAP_GRAM) break;
      if (sumGram(ings) >= target.gram) break;
      if (BUDGET_MAX - sumCost(ings) < 2) break;

      const gramLeft2 = target.gram - sumGram(ings);
      const candidates = ings.filter(x =>
        x.gram < x.gMax && x.p > 0 && (sumCost(ings) + Math.min(5, gramLeft2) * x.biayaPerG) <= BUDGET_MAX
      );
      if (candidates.length === 0) break;

      const cand = candidates.reduce((best, x) => {
        const costPerGProtein = x.biayaPerG / (x.p / 100);
        return costPerGProtein < best.biayaPerG / (best.p / 100) ? x : best;
      });

      const add = Math.min(5, cand.gMax - cand.gram, gramLeft2);
      if (add < 0.5) break;
      cand.gram += add;
    }

    // ── PHASE 3: Adaptive Gram Padding
    let iter3 = 0;
    while (iter3++ < 200 && sumGram(ings) < target.gram - 1) {
      if (sumCost(ings) >= BUDGET_MAX) break;

      const cur3 = { protein: sumOf("p", ings), lemak: sumOf("l", ings), karbo: sumOf("k", ings) };
      const gaps3 = {
        protein: Math.max(0, target.protein - cur3.protein),
        lemak:   Math.max(0, target.lemak   - cur3.lemak),
        karbo:   Math.max(0, target.karbo   - cur3.karbo)
      };
      const gapPct3 = {
        protein: gaps3.protein / target.protein,
        lemak:   gaps3.lemak / target.lemak,
        karbo:   gaps3.karbo / target.karbo
      };
      const stillNeedsNutri = gaps3.protein > 0.5 || gaps3.lemak > 0.5 || gaps3.karbo > 0.5;

      const gramLeft3 = target.gram - sumGram(ings);
      let cand = null;

      if (stillNeedsNutri) {
        const scored = ings
          .filter(x => x.gram < x.gMax && (sumCost(ings) + Math.min(5, gramLeft3) * x.biayaPerG) <= BUDGET_MAX)
          .map(x => ({
            x,
            score: (
              NUTRIENT_WEIGHTS.protein * (x.p / 100) * gapPct3.protein +
              NUTRIENT_WEIGHTS.lemak   * (x.l / 100) * gapPct3.lemak +
              NUTRIENT_WEIGHTS.karbo   * (x.k / 100) * gapPct3.karbo
            ) / x.biayaPerG
          }))
          .filter(s => s.score > 0);

        if (scored.length > 0) {
          cand = scored.reduce((best, s) => s.score > best.score ? s : best).x;
        }
      }

      if (!cand) {
        cand = ings
          .filter(x => x.gram < x.gMax && (sumCost(ings) + Math.min(5, gramLeft3) * x.biayaPerG) <= BUDGET_MAX)
          .sort((a, b) => a.biayaPerG - b.biayaPerG)[0];
      }

      if (!cand) break;
      const add = Math.min(5, cand.gMax - cand.gram, gramLeft3);
      cand.gram += add;
      if (add < 0.5) break;
    }

    const totals = {
      gram:    sumGram(ings),
      protein: sumOf("p", ings),
      lemak:   sumOf("l", ings),
      karbo:   sumOf("k", ings),
      serat:   sumOf("s", ings),
      biaya:   sumCost(ings)
    };
    const deficits = {
      protein: Math.max(0, target.protein - totals.protein),
      lemak:   Math.max(0, target.lemak   - totals.lemak),
      karbo:   Math.max(0, target.karbo   - totals.karbo)
    };
    const nutrisiOK = deficits.protein < 0.5 && deficits.lemak < 0.5 && deficits.karbo < 0.5;
    const gramOK = Math.abs(totals.gram - target.gram) < 25;
    const costOK = totals.biaya <= BUDGET_MAX;
    const costExcess = Math.max(0, totals.biaya - BUDGET_MAX);
    const budgetPct = (totals.biaya / BUDGET_MAX) * 100;
    return { ings, totals, deficits, nutrisiOK, gramOK, costOK, costExcess, budgetPct, BUDGET_MAX, BUDGET_TARGET, infeasibilityWarning };
  }, [activeIngs, target, BUDGET_MAX, BUDGET_TARGET]);

  // ----- Render -----
  const groups = [
    { key: "carbohydrate",  label: "Karbohidrat",     sub: "Mie/Nasi/Roti", icon: "leaf",      multi: false },
    { key: "proteinAnimal", label: "Protein Hewani",  sub: "Lauk utama",    icon: "shield",    multi: false },
    { key: "proteinPlant",  label: "Protein Nabati",  sub: "Pelengkap lauk",icon: "sprout",    multi: false }
  ];

  const totalKkal = result ? (result.totals.protein*4 + result.totals.karbo*4 + result.totals.lemak*9) : 0;

  return (
    <>
      <div className="page-header">
        <div>
          <div className="crumbs"><span>Submodul</span><span>Optimasi Menu</span></div>
          <h1 className="page-title">Optimasi Menu</h1>
        </div>
        <div className="row gap-sm">
          <button className="btn" onClick={() => { setSnacks([]); setMilkML(200); }}><Icon name="refresh" size={14}/> Reset</button>
          <button className="btn primary" onClick={handleExportMenuCSV}><Icon name="download" size={14}/> Ekspor CSV</button>
        </div>
      </div>

      <div className="grid cols-12" style={{ marginBottom: 24, gap: 20 }}>
        {/* ---------- LEFT: Input ---------- */}
        <div className="card" style={{ gridColumn: "span 7" }}>
          <div className="card-head"><h2 className="h2">Input Target Nutrisi</h2><span className="tag">per porsi</span></div>
          <div className="card-body">
            <div className="eyebrow" style={{ marginBottom: 8 }}>Preset kelompok sasaran (target nutrisi per porsi)</div>
            <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 6, marginBottom: 14 }}>
              {enhancedPresets.map(p => (
                <button key={p.label} onClick={() => setPreset(p.label)}
                  className="btn"
                  style={{
                    padding: "8px 10px", fontSize: 11.5, fontWeight: 600,
                    background: preset === p.label ? "var(--primary)" : "var(--bg-2)",
                    color: preset === p.label ? "white" : "var(--ink-2)",
                    border: preset === p.label ? "1px solid var(--primary)" : "1px solid var(--line)",
                    justifyContent: "flex-start", textAlign: "left"
                  }}>
                  {p.label}
                </button>
              ))}
            </div>

            <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 10, marginBottom: 16 }}>
              {[
                ["protein", "Protein min (g)"],
                ["lemak", "Lemak min (g)"],
                ["karbo", "Karbo min (g)"],
                ["gram", "Total gram/porsi"]
              ].map(([k, lbl]) => (
                <div key={k}>
                  <div className="muted" style={{ fontSize: 10.5, marginBottom: 4, fontWeight: 600, textTransform: "uppercase", letterSpacing: 0.4 }}>{lbl}</div>
                  <input className="mono" type="number" value={target[k]} onChange={e => updTarget(k, e.target.value)}
                    style={{ width: "100%", padding: "6px 9px", border: "1px solid var(--line)", borderRadius: 6, fontSize: 12.5, fontFamily: "var(--font-mono)", background: "var(--bg)", color: "var(--ink)" }}/>
                </div>
              ))}
            </div>

            {/* Bahan utama */}
            {groups.map(g => (
              <div key={g.key} style={{ marginBottom: 14 }}>
                <div className="row gap-xs" style={{ marginBottom: 6, alignItems: "center" }}>
                  <Icon name={g.icon} size={13}/>
                  <span style={{ fontSize: 12.5, fontWeight: 600 }}>{g.label}</span>
                  <span className="muted" style={{ fontSize: 10.5, textTransform: "uppercase", letterSpacing: 0.4 }}>({g.sub})</span>
                </div>
                <div style={{ display: "grid", gridTemplateColumns: "repeat(2, 1fr)", gap: 6 }}>
                  {MENU_DB[g.key].map(opt => {
                    const sel = picked[g.key] === opt.nama;
                    return (
                      <button key={opt.nama} onClick={() => togglePick(g.key, opt.nama)}
                        className="btn"
                        style={{
                          padding: "8px 12px", fontSize: 12, fontWeight: 500, justifyContent: "flex-start",
                          background: sel ? "color-mix(in oklab, var(--primary) 12%, var(--bg))" : "var(--bg)",
                          border: sel ? "1px solid var(--primary)" : "1px solid var(--line)",
                          color: "var(--ink)"
                        }}>
                        <span style={{
                          width: 14, height: 14, borderRadius: "50%",
                          border: sel ? "4px solid var(--primary)" : "1.5px solid var(--ink-3)",
                          background: sel ? "var(--bg)" : "transparent",
                          marginRight: 8, flexShrink: 0
                        }}/>
                        <span>{opt.nama}</span>
                        <span className="mono muted" style={{ marginLeft: "auto", fontSize: 10.5 }}>{opt.biayaPerG} Rp/g</span>
                      </button>
                    );
                  })}
                </div>
              </div>
            ))}

            <div className="hr"/>

            {/* Sayur, Buah, Susu */}
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, marginBottom: 12 }}>
              <div>
                <div className="eyebrow" style={{ marginBottom: 6 }}>Sayur</div>
                <select value={picked.vegetable} onChange={e => setPicked(p => ({ ...p, vegetable: e.target.value }))}
                  style={{ width: "100%", padding: "8px 10px", border: "1px solid var(--line)", borderRadius: 6, fontSize: 12.5, background: "var(--bg)", color: "var(--ink)" }}>
                  <option value="">— pilih sayur —</option>
                  {MENU_DB.vegetable.map(v => <option key={v.nama} value={v.nama}>{v.nama}</option>)}
                </select>
              </div>
              <div>
                <div className="eyebrow" style={{ marginBottom: 6 }}>Buah</div>
                <select value={picked.fruit} onChange={e => setPicked(p => ({ ...p, fruit: e.target.value }))}
                  style={{ width: "100%", padding: "8px 10px", border: "1px solid var(--line)", borderRadius: 6, fontSize: 12.5, background: "var(--bg)", color: "var(--ink)" }}>
                  <option value="">— pilih buah —</option>
                  {MENU_DB.fruit.map(v => <option key={v.nama} value={v.nama}>{v.nama}</option>)}
                </select>
              </div>
            </div>

            <div style={{ marginBottom: 12 }}>
              <div className="eyebrow" style={{ marginBottom: 6 }}>Susu (volume ml)</div>
              <input className="mono" type="number" min="0" value={milkML} onChange={e => setMilkML(parseInt(e.target.value)||0)}
                style={{ width: "100%", padding: "8px 10px", border: "1px solid var(--line)", borderRadius: 6, fontSize: 12.5, fontFamily: "var(--font-mono)", background: "var(--bg)", color: "var(--ink)" }}/>
            </div>

            <div>
              <div className="eyebrow" style={{ marginBottom: 6 }}>Tambahan (Snack)</div>
              <div className="row" style={{ flexWrap: "wrap", gap: 6 }}>
                {MENU_DB.snack.map(s => {
                  const sel = snacks.includes(s.nama);
                  return (
                    <button key={s.nama} onClick={() => toggleSnack(s.nama)} className="btn"
                      style={{
                        padding: "5px 12px", fontSize: 11.5, fontWeight: 500, borderRadius: 999,
                        background: sel ? "color-mix(in oklab, var(--primary) 14%, var(--bg))" : "var(--bg)",
                        border: sel ? "1px solid var(--primary)" : "1px solid var(--line)",
                        color: "var(--ink)"
                      }}>{s.nama}</button>
                  );
                })}
              </div>
            </div>

          </div>
        </div>

        {/* ---------- RIGHT: Result ---------- */}
        <div className="card" style={{ gridColumn: "span 5" }}>
          <div className="card-head"><h2 className="h2">Hasil Optimasi Komposisi</h2><span className="tag mono">biaya minimum</span></div>
          <div className="card-body">
            {!result ? (
              <div className="muted" style={{ padding: 20, textAlign: "center" }}>Pilih minimal satu bahan untuk memulai optimasi.</div>
            ) : (
              <>
                {!result.costOK && (
                  <div style={{ padding: 12, marginBottom: 12, background: "var(--info-100)", border: "1px solid var(--info)", borderRadius: 8, color: "var(--info)", fontSize: 12.5, fontWeight: 500 }}>
                    <span style={{ marginRight: 8 }}>💡</span>Target budget Rp {Math.round(result.BUDGET_TARGET).toLocaleString("id-ID")} untuk {preset} lebih ideal. Pertimbangkan substitusi bahan lebih ekonomis (e.g., Telur daripada Ayam, Tempe daripada Daging).
                  </div>
                )}
                {result.infeasibilityWarning && (
                  <div style={{ padding: 12, marginBottom: 12, background: "var(--warn-100)", border: "1px solid var(--warn)", borderRadius: 8, color: "oklch(0.45 0.16 55)", fontSize: 12.5, fontWeight: 500 }}>
                    <span style={{ marginRight: 8 }}>⚠️</span><b>Kelayakan Nutrisi:</b> {result.infeasibilityWarning}
                  </div>
                )}
                <div className="grid cols-2" style={{ gap: 8, marginBottom: 12 }}>
                  <div style={{ padding: 12, background: result.costOK ? "var(--accent-100)" : "var(--danger-100)", borderRadius: 8, border: `1px solid ${result.costOK ? "var(--accent)" : "var(--danger)"}` }}>
                    <div className="eyebrow" style={{ marginBottom: 4, color: result.costOK ? "var(--accent-700)" : "var(--danger)" }}>Biaya per porsi ({presetObj.costPerGram}Rp/g)</div>
                    <div style={{ fontFamily: "var(--font-display)", fontWeight: 700, fontSize: 22, color: result.costOK ? "var(--accent-700)" : "var(--danger)" }}>Rp {Math.round(result.totals.biaya).toLocaleString("id-ID")}</div>
                    <div style={{ fontSize: 10, color: result.costOK ? "var(--accent-700)" : "var(--danger)", marginTop: 4 }}>
                      {result.costOK ? `✓ Dalam budget (${(100 - result.budgetPct).toFixed(0)}% sisa dari Rp ${Math.round(result.BUDGET_MAX).toLocaleString("id-ID")})` : `Melebihi Rp ${Math.round(result.costExcess).toLocaleString("id-ID")}`}
                    </div>
                  </div>
                  <div style={{ padding: 12, background: "var(--bg-2)", borderRadius: 8, border: "1px solid var(--line)" }}>
                    <div className="eyebrow" style={{ marginBottom: 4 }}>Total gram</div>
                    <div style={{ fontFamily: "var(--font-display)", fontWeight: 700, fontSize: 22 }}>{result.totals.gram.toFixed(0)} g</div>
                  </div>
                </div>

                <div className="grid cols-3" style={{ gap: 8, marginBottom: 12 }}>
                  {[
                    ["Protein", result.totals.protein, target.protein, result.deficits.protein],
                    ["Lemak",   result.totals.lemak,   target.lemak,   result.deficits.lemak],
                    ["Karbo",   result.totals.karbo,   target.karbo,   result.deficits.karbo]
                  ].map(([lbl, val, tgt, gap]) => {
                    const ok = gap < 0.5;
                    return (
                      <div key={lbl} style={{ padding: 9, borderRadius: 6, background: ok ? "var(--accent-100)" : "var(--warn-100)", border: `1px solid ${ok ? "var(--accent)" : "var(--warn)"}` }}>
                        <div className="muted" style={{ fontSize: 10, fontWeight: 600 }}>{lbl}</div>
                        <div className="mono" style={{ fontWeight: 700, fontSize: 14, color: ok ? "var(--accent-700)" : "var(--warn)" }}>{val.toFixed(1)}</div>
                        <div className="muted" style={{ fontSize: 10 }}>tgt {tgt.toFixed(1)} · gap {gap.toFixed(2)}</div>
                      </div>
                    );
                  })}
                </div>

                <div className="row gap-xs" style={{ marginBottom: 12, flexWrap: "wrap" }}>
                  <span className={`pill ${result.nutrisiOK ? "ok" : "warn"}`}><span className="led"/>{result.nutrisiOK ? "Nutrisi terpenuhi" : "Nutrisi belum terpenuhi"}</span>
                  <span className={`pill ${result.gramOK ? "ok" : "warn"}`}><span className="led"/>{result.gramOK ? "Total gram sesuai" : "Total gram perlu disesuaikan"}</span>
                  <span className={`pill ${result.costOK ? "ok" : "danger"}`}><span className="led"/>{result.costOK ? "Biaya OK" : "Biaya melebihi"}</span>
                  <span className="tag mono">{totalKkal.toFixed(0)} kkal</span>
                </div>

                {/* Komposisi pie via SVG */}
                <div className="eyebrow" style={{ marginBottom: 6 }}>Distribusi bahan (gram)</div>
                <svg viewBox="0 0 320 180" style={{ width: "100%", height: 170, marginBottom: 12 }}>
                  {(() => {
                    const cx = 90, cy = 90, R = 70, r = 38;
                    const total = result.ings.reduce((a,x)=>a+x.gram, 0);
                    const colors = ["var(--primary)","var(--accent)","var(--warn)","oklch(0.55 0.14 290)","oklch(0.65 0.16 30)","oklch(0.55 0.10 200)","oklch(0.65 0.10 90)"];
                    let acc = 0;
                    return (
                      <>
                        {result.ings.map((ing, i) => {
                          const frac = ing.gram / total;
                          const a0 = acc * Math.PI * 2 - Math.PI/2;
                          acc += frac;
                          const a1 = acc * Math.PI * 2 - Math.PI/2;
                          const large = frac > 0.5 ? 1 : 0;
                          const x0 = cx + Math.cos(a0)*R, y0 = cy + Math.sin(a0)*R;
                          const x1 = cx + Math.cos(a1)*R, y1 = cy + Math.sin(a1)*R;
                          const xi0 = cx + Math.cos(a0)*r, yi0 = cy + Math.sin(a0)*r;
                          const xi1 = cx + Math.cos(a1)*r, yi1 = cy + Math.sin(a1)*r;
                          const d = `M ${x0} ${y0} A ${R} ${R} 0 ${large} 1 ${x1} ${y1} L ${xi1} ${yi1} A ${r} ${r} 0 ${large} 0 ${xi0} ${yi0} Z`;
                          return <path key={i} d={d} fill={colors[i % colors.length]} opacity="0.92"/>;
                        })}
                        {result.ings.map((ing, i) => (
                          <g key={i} transform={`translate(180, ${10 + i*18})`}>
                            <rect width="11" height="11" fill={colors[i % colors.length]} rx="2"/>
                            <text x="16" y="9.5" fontSize="10.5" fill="var(--ink-2)">{ing.nama}</text>
                            <text x="138" y="9.5" fontSize="10.5" textAnchor="end" fontFamily="var(--font-mono)" fill="var(--ink)">{ing.gram.toFixed(0)} g</text>
                          </g>
                        ))}
                      </>
                    );
                  })()}
                </svg>

                <div className="hr"/>

                <div className="eyebrow" style={{ marginBottom: 10 }}>Analisa Constraint Satisfaction</div>
                <div className="grid cols-2" style={{ gap: 10 }}>
                  {[
                    { label: "Protein", val: result.totals.protein, tgt: target.protein, icon: "✓" },
                    { label: "Lemak", val: result.totals.lemak, tgt: target.lemak, icon: "✓" },
                    { label: "Karbo", val: result.totals.karbo, tgt: target.karbo, icon: "✓" },
                    { label: "Total Gram", val: result.totals.gram, tgt: target.gram, icon: "✓" }
                  ].map((metric) => {
                    const pct = Math.min(100, (metric.val / metric.tgt) * 100);
                    const isSatisfied = pct >= 95;
                    return (
                      <div key={metric.label} style={{ padding: 10, background: isSatisfied ? "var(--accent-100)" : "var(--danger-100)", borderRadius: 6, border: `1px solid ${isSatisfied ? "var(--accent)" : "var(--danger)"}` }}>
                        <div className="row between" style={{ marginBottom: 6 }}>
                          <span className="muted" style={{ fontSize: 11, fontWeight: 600 }}>{metric.label}</span>
                          <span className="mono" style={{ fontWeight: 700, fontSize: 12, color: isSatisfied ? "var(--accent-700)" : "var(--warn)" }}>
                            {`${pct.toFixed(0)}%`}
                          </span>
                        </div>
                        <div className="bar" style={{ height: 6 }}><span style={{ width: `${Math.min(100, pct)}%`, background: isSatisfied ? "var(--accent)" : "var(--warn)", height: "100%", borderRadius: 2 }}/></div>
                        <div className="muted" style={{ fontSize: 10, marginTop: 4 }}>
                          {`${metric.val.toFixed(1)} / ${metric.tgt.toFixed(1)}`}
                        </div>
                      </div>
                    );
                  })}
                </div>
              </>
            )}
          </div>
        </div>
      </div>

      {/* ---------- Detail tabel komposisi ---------- */}
      {result && (
        <div className="card" style={{ marginBottom: 24 }}>
          <div className="card-head"><h2 className="h2">Komposisi Optimal Per Bahan</h2><span className="pill ok"><span className="led"/>{result.ings.length} bahan aktif</span></div>
          <table className="data">
            <thead><tr>
              <th>Bahan</th><th>Kategori</th><th className="num">Optimal (g)</th>
              <th className="num">Protein</th><th className="num">Lemak</th><th className="num">Karbo</th><th className="num">Serat</th>
              <th className="num">Biaya</th><th className="num">Batas</th>
            </tr></thead>
            <tbody>
              {result.ings.map((b, i) => {
                const p = b.gram * b.p / 100, l = b.gram * b.l / 100, k = b.gram * b.k / 100, s = b.gram * b.s / 100;
                const cost = b.gram * b.biayaPerG;
                return (
                  <tr key={i}>
                    <td style={{ fontWeight: 600 }}>{b.nama}</td>
                    <td><span className="tag">{b.cat}</span></td>
                    <td className="num" style={{ fontWeight: 700 }}>{b.gram.toFixed(1)}</td>
                    <td className="num">{p.toFixed(2)}</td>
                    <td className="num">{l.toFixed(2)}</td>
                    <td className="num">{k.toFixed(2)}</td>
                    <td className="num">{s.toFixed(2)}</td>
                    <td className="num">Rp {Math.round(cost).toLocaleString("id-ID")}</td>
                    <td className="num muted" style={{ fontSize: 10.5 }}>{b.gMin}–{b.gMax} g</td>
                  </tr>
                );
              })}
              <tr style={{ background: "var(--primary-50)", fontWeight: 700 }}>
                <td colSpan="2" style={{ textAlign: "right", color: "var(--primary)" }}>TOTAL per porsi</td>
                <td className="num" style={{ color: "var(--primary)" }}>{result.totals.gram.toFixed(1)}</td>
                <td className="num" style={{ color: "var(--primary)" }}>{result.totals.protein.toFixed(2)}</td>
                <td className="num" style={{ color: "var(--primary)" }}>{result.totals.lemak.toFixed(2)}</td>
                <td className="num" style={{ color: "var(--primary)" }}>{result.totals.karbo.toFixed(2)}</td>
                <td className="num" style={{ color: "var(--primary)" }}>{result.totals.serat.toFixed(2)}</td>
                <td className="num" style={{ color: "var(--primary)" }}>Rp {Math.round(result.totals.biaya).toLocaleString("id-ID")}</td>
                <td></td>
              </tr>
              <tr style={{ background: "var(--bg-2)" }}>
                <td colSpan="2" style={{ textAlign: "right", color: "var(--ink-2)", fontWeight: 600 }}>Skala {porsi.toLocaleString("id-ID")} porsi/hari</td>
                <td colSpan="6" className="num" style={{ color: "var(--ink)", fontWeight: 700 }}>Rp {Math.round(result.totals.biaya * porsi).toLocaleString("id-ID")}/hari</td>
                <td></td>
              </tr>
            </tbody>
          </table>
        </div>
      )}
    </>
  );
}

function EWSScreen({ role }) {
  const { EWS_TAHAPAN, EWS_KRITERIA, EWS_HARIINI, EWS_KOMODITAS_LIST, EWS_DATA_KOMODITAS, ALERTS_AKTIF } = window.IDSS;
  const { Pipeline, Icon, ScoreInput, BarMini, Donut } = window.IDSSUI;

  const [activeId, setActiveId] = useS_D("T1");
  const [showDropdown, setShowDropdown] = useS_D(false);
  const [komoditas, setKomoditas] = useS_D(EWS_KOMODITAS_LIST[0]);
  const tahap = EWS_TAHAPAN.find(t => t.id === activeId);
  const isBahanTahap = activeId === "T1" || activeId === "T2";

  const handleExportEWSReport = () => {
    const headers = ["Tahap", "Kriteria", "Skor", "Status"];
    const rows = EWS_TAHAPAN.map(t => {
      const stageData = isBahanTahap && EWS_DATA_KOMODITAS[t.id]?.[komoditas] || EWS_HARIINI[t.id];
      const stageCriteria = EWS_KRITERIA[t.id] || [];
      return stageCriteria.map(k => [
        t.nama,
        k.nama,
        stageData?.scores?.[k.id] || "-",
        stageData?.status?.[k.id] || "-"
      ]);
    }).flat();
    const csv = [headers, ...rows].map(r => r.map(v => `"${v}"`).join(",")).join("\n");
    const blob = new Blob([csv], { type: "text/csv" });
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = `EWS-Laporan-${role.short}-${new Date().toISOString().split('T')[0]}.csv`;
    a.click();
  };

  // Use per-komoditas data for T1/T2, default for T3-T6
  const hariIniData = isBahanTahap
    ? EWS_DATA_KOMODITAS[activeId][komoditas]
    : EWS_HARIINI[activeId];

  // Override batas kritis for T1/T2 based on komoditas
  const kriteria = React.useMemo(() => {
    const base = EWS_KRITERIA[activeId];
    if (isBahanTahap && hariIniData.batasOverride) {
      return base.map(k => hariIniData.batasOverride[k.id]
        ? { ...k, batasKritis: hariIniData.batasOverride[k.id] }
        : k);
    }
    return base;
  }, [activeId, komoditas, isBahanTahap]);

  const [allScores, setAllScores] = useS_D({});
  const [scores, setScores] = useS_D({});

  React.useEffect(() => {
    setScores(Object.fromEntries(kriteria.map((k,i) => [k.id, hariIniData.skor[i]])));
  }, [activeId, komoditas]);

  const updScore = (kid, v) => {
    setScores(s => ({ ...s, [kid]: v }));
    setAllScores(s => ({
      ...s,
      [activeId]: { ...(s[activeId] || {}), [kid]: v }
    }));
  };

  const weightedScore = useM_D(() => {
    return kriteria.reduce((acc, k) => acc + (scores[k.id] || 0) * k.bobot, 0);
  }, [scores, activeId]);

  // Hard filter: jika ada kriteria bernilai 1, langsung KRITIS
  const hasMinimalScore = Object.values(scores).some(score => score === 1);

  // Fuzzy inference output (mock)
  const fuzzyLabel = hasMinimalScore ? "KRITIS" : (weightedScore >= 4.3 ? "AMAN" : weightedScore >= 3.5 ? "WASPADA" : weightedScore >= 2.5 ? "BERESIKO" : "KRITIS");
  const fuzzyColor = hasMinimalScore ? "var(--danger)" : (weightedScore >= 4.3 ? "var(--accent)" : weightedScore >= 3.5 ? "var(--warn)" : "var(--danger)");

  // Monte Carlo distribution based on normal distribution
  const sigma = 0.42;
  const normalPdf = (x) => (1 / (sigma * Math.sqrt(2 * Math.PI))) * Math.exp(-0.5 * Math.pow((x - weightedScore) / sigma, 2));
  const mcDist = useM_D(() => {
    const bins = [[1.0, 1.7], [1.7, 2.4], [2.4, 3.1], [3.1, 3.8], [3.8, 4.5], [4.5, 5.0]];
    const probs = bins.map(([lo, hi]) => {
      const steps = 10;
      let sum = 0;
      for (let i = 0; i < steps; i++) {
        const x = lo + ((hi - lo) / steps) * (i + 0.5);
        sum += normalPdf(x) * ((hi - lo) / steps);
      }
      return sum;
    });
    const total = probs.reduce((a, b) => a + b, 0);
    return probs.map(p => Math.round((p / total) * 100));
  }, [weightedScore]);

  return (
    <>
      <div className="page-header">
        <div>
          <div className="crumbs"><span>{role.short}</span><span>Submodul</span><span>Keamanan Pangan</span></div>
          <h1 className="page-title">Keamanan Pangan</h1>
        </div>
        <div className="row gap-sm">
          <button className="btn"><Icon name="refresh" size={14}/> Re-simulasi (n=10.000)</button>
          <button className="btn primary" onClick={handleExportEWSReport}><Icon name="download" size={14}/> Ekspor laporan</button>
        </div>
      </div>

      <Pipeline tahapan={EWS_TAHAPAN} hariIni={EWS_HARIINI} activeId={activeId} onPick={setActiveId}/>

      <div className="row gap-sm" style={{ margin: "20px 0 16px", flexWrap: "wrap" }}>
        <h2 className="h1" style={{ fontSize: 20 }}>{tahap.idx}. {tahap.nama}</h2>
        <span className="tag">{tahap.fase === "bahan" ? "Bahan baku" : "Makanan jadi"}</span>
        <span className="muted" style={{ fontSize: 12.5 }}>{tahap.deskripsi}</span>
        {isBahanTahap && (
          <div className="row gap-xs" style={{ marginLeft: "auto", alignItems: "center", position: "relative" }}>
            <span className="muted" style={{ fontSize: 11.5, fontWeight: 600, textTransform: "uppercase", letterSpacing: 0.4 }}>Komoditas:</span>
            <div style={{ position: "relative" }}>
              <button
                onClick={() => setShowDropdown(s => !s)}
                style={{
                  padding: "8px 14px",
                  fontSize: 12,
                  fontWeight: 600,
                  background: "linear-gradient(135deg, var(--primary), var(--primary-700))",
                  color: "white",
                  border: "0",
                  borderRadius: 6,
                  cursor: "pointer",
                  display: "flex",
                  alignItems: "center",
                  gap: 8,
                  transition: "all 0.2s",
                  boxShadow: "0 2px 4px rgba(0,0,0,0.1)"
                }}>
                {komoditas}
                <Icon name="arrow" size={14} style={{ transform: showDropdown ? "rotate(-90deg)" : "rotate(90deg)", transition: "transform 0.3s ease" }}/>
              </button>
              {showDropdown && (
                <div style={{
                  position: "absolute",
                  top: 42,
                  left: 0,
                  minWidth: 240,
                  background: "white",
                  border: "1px solid var(--line)",
                  borderRadius: 8,
                  boxShadow: "0 8px 24px rgba(0,0,0,0.12)",
                  zIndex: 30,
                  maxHeight: 350,
                  overflowY: "auto",
                  animation: "slideDown 0.2s ease"
                }}>
                  {EWS_KOMODITAS_LIST.map((k, idx) => (
                    <button
                      key={k}
                      onClick={() => {
                        setKomoditas(k);
                        setShowDropdown(false);
                      }}
                      style={{
                        width: "100%",
                        padding: "10px 14px",
                        fontSize: 12,
                        textAlign: "left",
                        background: komoditas === k ? "var(--primary-50)" : "transparent",
                        border: "0",
                        cursor: "pointer",
                        color: komoditas === k ? "var(--primary)" : "var(--ink-2)",
                        borderBottom: idx < EWS_KOMODITAS_LIST.length - 1 ? "1px solid var(--line-2)" : "0",
                        transition: "all 0.15s",
                        fontWeight: komoditas === k ? 600 : 400
                      }}>
                        {komoditas === k && "✓ "}
                        {k}
                    </button>
                  ))}
                </div>
              )}
            </div>
          </div>
        )}
      </div>

      <div className="grid cols-12">
        <div className="card" style={{ gridColumn: "span 7" }}>
          <div className="card-head"><h2 className="h2">Input Skoring Kriteria (1–5)</h2><span className="tag mono">5 = baik · 1 = kritis</span></div>
          <div className="card-body" style={{ paddingTop: 8 }}>
            <table className="data" style={{ fontSize: 13 }}>
              <thead><tr>
                <th>Kriteria</th><th>Batas kritis (asumsi)</th><th className="num">Bobot</th><th>Skor</th>
              </tr></thead>
              <tbody>
                {kriteria.map(k => (
                  <tr key={k.id}>
                    <td style={{ fontWeight: 600 }}>{k.nama}</td>
                    <td className="muted" style={{ fontSize: 11.5 }}>{k.batasKritis}</td>
                    <td className="num">{(k.bobot*100).toFixed(0)}%</td>
                    <td><ScoreInput value={scores[k.id]} onChange={v => updScore(k.id, v)}/></td>
                  </tr>
                ))}
                <tr style={{ background: "var(--primary-50)", fontWeight: 700 }}>
                  <td colSpan="2" style={{ color: "var(--primary)", textAlign: "right" }}>SKOR TERTIMBANG</td>
                  <td className="num" style={{ color: "var(--primary)" }}>Σw=1.00</td>
                  <td><span className="mono" style={{ fontWeight: 700, fontSize: 14, color: "var(--primary)" }}>{weightedScore.toFixed(2)}</span> <span className="muted">/ 5</span></td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>

        <div className="card" style={{ gridColumn: "span 5" }}>
          <div className="card-head"><h2 className="h2">Output FIS</h2><span className="tag mono">Mamdani · 3.125 rules (5^5)</span></div>
          <div className="card-body">
            <div className="row" style={{ gap: 18, alignItems: "center", marginBottom: 16 }}>
              <Donut value={weightedScore} max={5} size={108} stroke={10} color={fuzzyColor} label={fuzzyLabel}/>
              <div style={{ flex: 1 }}>
                <div className="eyebrow" style={{ color: fuzzyColor }}>Status defuzzifikasi</div>
                <div style={{ fontFamily: "var(--font-display)", fontSize: 26, fontWeight: 600, color: fuzzyColor, marginTop: 2 }}>{fuzzyLabel}</div>
                <div className="muted" style={{ fontSize: 12, marginTop: 4 }}>Centroid output: <b className="mono" style={{ color: "var(--ink)" }}>{weightedScore.toFixed(2)}</b></div>
              </div>
            </div>

            <div className="eyebrow" style={{ marginBottom: 8 }}>Membership pada output sets</div>
            {[
              { name: "AMAN",     val: Math.max(0, Math.min(1, (weightedScore - 3.8)/1.0)), color: "var(--accent)" },
              { name: "WASPADA",  val: Math.max(0, 1 - Math.abs(weightedScore - 3.5)/1.0), color: "var(--warn)" },
              { name: "BERESIKO", val: Math.max(0, 1 - Math.abs(weightedScore - 2.5)/1.0), color: "oklch(0.65 0.16 30)" },
              { name: "KRITIS",   val: Math.max(0, Math.min(1, (2.0 - weightedScore)/1.0)), color: "var(--danger)" }
            ].map(m => (
              <div key={m.name} style={{ marginBottom: 6 }}>
                <div className="row between" style={{ marginBottom: 3 }}>
                  <span style={{ fontSize: 11.5, fontWeight: 500, color: "var(--ink-2)" }}>{m.name}</span>
                  <span className="mono" style={{ fontSize: 11 }}>{(m.val*100).toFixed(0)}%</span>
                </div>
                <div className="bar"><span style={{ width: `${m.val*100}%`, background: m.color }}/></div>
              </div>
            ))}

            <div className="hr" style={{ margin: "12px 0" }}/>

            <div className="eyebrow" style={{ marginBottom: 10 }}>Alert &amp; Rekomendasi</div>
            {(() => {
              const alertConfig = {
                AMAN: {
                  icon: "✓", color: "var(--accent)", bgColor: "var(--accent-50)",
                  action: "Pertahankan standar saat ini",
                  frequency: "Monitoring rutin harian",
                  responsible: "Koordinator Dapur"
                },
                WASPADA: {
                  icon: "!", color: "var(--warn)", bgColor: "var(--warn-50)",
                  action: "Tingkatkan pengawasan & terapkan preventif",
                  frequency: "Monitoring intensif (2× per hari)",
                  responsible: "Supervisor + QC"
                },
                BERESIKO: {
                  icon: "⚠", color: "oklch(0.45 0.17 55)", bgColor: "oklch(0.95 0.05 55)",
                  action: "Segera implementasikan tindakan korektif",
                  frequency: "Monitoring real-time (per shift)",
                  responsible: "Kepala Dapur + Tim QC"
                },
                KRITIS: {
                  icon: "✕", color: "var(--danger)", bgColor: "var(--danger-50)",
                  action: "AKSI DARURAT: Hentikan operasi jika diperlukan",
                  frequency: "Monitoring berkelanjutan (24/7)",
                  responsible: "Kepala Dapur + Management"
                }
              };
              const config = alertConfig[fuzzyLabel];
              return (
                <div style={{ padding: 12, background: config.bgColor, borderRadius: 6, borderLeft: `4px solid ${config.color}` }}>
                  <div style={{ display: "flex", gap: 10, marginBottom: 8 }}>
                    <span style={{ fontSize: 20, color: config.color, fontWeight: 700, width: 24, textAlign: "center" }}>{config.icon}</span>
                    <div style={{ flex: 1 }}>
                      <div style={{ fontSize: 11.5, fontWeight: 600, color: config.color, marginBottom: 2 }}>Aksi yang Direkomendasikan</div>
                      <div style={{ fontSize: 12, color: "var(--ink)", fontWeight: 500 }}>{config.action}</div>
                    </div>
                  </div>
                  <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10, fontSize: 11.5 }}>
                    <div>
                      <div className="muted" style={{ fontSize: 10, fontWeight: 600, marginBottom: 3 }}>Frekuensi Monitoring</div>
                      <div style={{ fontWeight: 500, color: "var(--ink)" }}>{config.frequency}</div>
                    </div>
                    <div>
                      <div className="muted" style={{ fontSize: 10, fontWeight: 600, marginBottom: 3 }}>Penanggung Jawab</div>
                      <div style={{ fontWeight: 500, color: "var(--ink)" }}>{config.responsible}</div>
                    </div>
                  </div>
                </div>
              );
            })()}
          </div>
        </div>
      </div>

      <div className="grid cols-12" style={{ marginTop: 24 }}>
        <div className="card" style={{ gridColumn: "span 6" }}>
          <div className="card-head"><h2 className="h2">Distribusi Monte Carlo (n=10.000)</h2><span className="tag mono">σ = 0.42</span></div>
          <div className="card-body">
            <svg viewBox="0 0 520 220" style={{ width: "100%", height: 220 }}>
              <defs>
                <linearGradient id="gradDanger" x1="0%" y1="0%" x2="0%" y2="100%">
                  <stop offset="0%" stopColor="var(--danger)" stopOpacity="1"/>
                  <stop offset="100%" stopColor="var(--danger)" stopOpacity="0.6"/>
                </linearGradient>
                <linearGradient id="gradWarn" x1="0%" y1="0%" x2="0%" y2="100%">
                  <stop offset="0%" stopColor="oklch(0.65 0.16 30)" stopOpacity="1"/>
                  <stop offset="100%" stopColor="oklch(0.65 0.16 30)" stopOpacity="0.6"/>
                </linearGradient>
                <linearGradient id="gradAccent" x1="0%" y1="0%" x2="0%" y2="100%">
                  <stop offset="0%" stopColor="var(--accent)" stopOpacity="1"/>
                  <stop offset="100%" stopColor="var(--accent)" stopOpacity="0.6"/>
                </linearGradient>
                <filter id="shadow"><feDropShadow dx="0" dy="2" stdDeviation="3" floodOpacity="0.2"/></filter>
              </defs>
              {(() => {
                const labels = ["1.0–1.7", "1.7–2.4", "2.4–3.1", "3.1–3.8", "3.8–4.5", "4.5–5.0"];
                const gradients = ["url(#gradDanger)", "url(#gradWarn)", "url(#gradWarn)", "url(#gradWarn)", "url(#gradAccent)", "url(#gradAccent)"];
                const maxVal = Math.max(...mcDist);
                return (
                  <>
                    <line x1="45" y1="185" x2="505" y2="185" stroke="var(--line)" strokeWidth="1.5"/>
                    {mcDist.map((v, i) => {
                      const x = 45 + i * 77;
                      const h = (v / maxVal) * 160;
                      return (
                        <g key={i} filter="url(#shadow)">
                          <rect x={x+3} y={185-h} width="60" height={h} fill={gradients[i]} rx="4" strokeWidth="1" stroke={gradients[i]}/>
                          <text x={x+33} y={180-h} textAnchor="middle" fontSize="13" fontWeight="700" fill="var(--ink)" fontFamily="var(--font-mono)">{v}%</text>
                          <text x={x+33} y="205" textAnchor="middle" fontSize="11" fontWeight="600" fill="var(--ink-2)" fontFamily="var(--font-mono)">{labels[i]}</text>
                        </g>
                      );
                    })}
                    {/* current marker */}
                    <line x1={45 + ((weightedScore - 1) / 4) * 460} y1="10" x2={45 + ((weightedScore - 1) / 4) * 460} y2="185" stroke="var(--primary)" strokeWidth="2.5" strokeDasharray="5 4" opacity="0.9"/>
                  </>
                );
              })()}
            </svg>
            <div style={{ marginTop: 12 }}>
              <div className="muted" style={{ fontSize: 11.5, marginBottom: 6 }}>
                Probabilitas tahap dalam status BERESIKO atau lebih buruk: <b className="mono" style={{ color: "var(--danger)" }}>{mcDist[0]+mcDist[1]+mcDist[2]}%</b>
              </div>
              <div style={{ padding: 10, background: "var(--bg-2)", borderRadius: 6, fontSize: 11.5, lineHeight: 1.5 }}>
                <div className="eyebrow" style={{ marginBottom: 4, fontSize: 10 }}>Rekomendasi</div>
                {(mcDist[0]+mcDist[1]+mcDist[2]) >= 50 ? (
                  <span><b style={{ color: "var(--danger)" }}>Tingkatkan pengawasan</b> — lebih dari setengah skenario dalam risiko. Identifikasi kriteria dengan skor rendah dan buat rencana mitigasi.</span>
                ) : (mcDist[0]+mcDist[1]+mcDist[2]) >= 20 ? (
                  <span><b style={{ color: "var(--warn)" }}>Monitor secara berkala</b> — risiko sedang terhadap kondisi kritis. Terapkan kontrol preventif pada area yang kurang stabil.</span>
                ) : (
                  <span><b style={{ color: "var(--accent)" }}>Status terjaga</b> — probabilitas risiko rendah. Pertahankan kondisi saat ini melalui praktik-praktik terbaik yang sudah berjalan.</span>
                )}
              </div>
            </div>
          </div>
        </div>

        <div className="card" style={{ gridColumn: "span 6" }}>
          <div className="card-head"><h2 className="h2">Heatmap 6 Tahapan × 5 Kriteria</h2><span className="tag">snapshot hari ini</span></div>
          <div className="card-body">
            <div style={{ display: "grid", gridTemplateColumns: "90px repeat(5, 1fr)", gap: 3, alignItems: "center" }}>
              <div></div>
              {["K1","K2","K3","K4","K5"].map(k => (
                <div key={k} className="mono" style={{ fontSize: 9.5, color: "var(--ink-3)", textAlign: "center", fontWeight: 600 }}>{k}</div>
              ))}
              {EWS_TAHAPAN.map(t => (
                <React.Fragment key={t.id}>
                  <div style={{ fontSize: 10.5, fontWeight: 600, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{t.idx}. {t.nama}</div>
                  {EWS_KRITERIA[t.id].map((k, i) => {
                    const s = allScores[t.id]?.[k.id] ?? EWS_HARIINI[t.id].skor[i];
                    const colors = {
                      5: ["var(--accent-100)", "var(--accent-700)"],
                      4: ["color-mix(in oklab, var(--accent-100) 70%, white)", "var(--accent-700)"],
                      3: ["var(--warn-100)", "oklch(0.45 0.17 55)"],
                      2: ["color-mix(in oklab, var(--danger-100) 60%, white)", "var(--danger)"],
                      1: ["var(--danger-100)", "var(--danger)"]
                    };
                    return (
                      <div key={k.id} className="heatmap-cell" style={{ background: colors[s][0], color: colors[s][1], aspectRatio: "2.5/1", border: t.id === activeId ? "1.5px solid var(--primary)" : "0", display: "grid", placeItems: "center", fontSize: 12, fontWeight: 600 }}>
                        {s}
                      </div>
                    );
                  })}
                </React.Fragment>
              ))}
            </div>
            <div className="hr"/>
            <div className="row gap-sm" style={{ fontSize: 11.5 }}>
              <span className="muted">Legenda:</span>
              {[5,4,3,2,1].map(s => {
                const c = { 5: "var(--accent)", 4: "var(--accent)", 3: "var(--warn)", 2: "var(--danger)", 1: "var(--danger)" }[s];
                return <span key={s} className="row gap-xs"><span style={{ width: 12, height: 12, background: c, borderRadius: 2, opacity: s/5 }}/>{s}</span>;
              })}
            </div>
          </div>
        </div>
      </div>

      <div className="card" style={{ marginTop: 24 }}>
        <div className="card-head"><h2 className="h2">Alert &amp; Tindakan dari EWS</h2><span className="pill warn"><span className="led"/>{ALERTS_AKTIF.length} alert aktif</span></div>
        <table className="data">
          <thead><tr><th>Tahap</th><th>Alert</th><th>Komoditas</th><th className="num">Waktu</th><th>Tindakan</th><th>Status</th></tr></thead>
          <tbody>
            {ALERTS_AKTIF.map(a => (
              <tr key={a.id}>
                <td><span className="tag mono">{a.tahap}</span></td>
                <td style={{ fontWeight: 500 }}>{a.judul}</td>
                <td className="muted">{a.komoditas}</td>
                <td className="num">{a.waktu}</td>
                <td className="muted" style={{ fontSize: 12 }}>{a.aksi}</td>
                <td>{a.level === "danger" ? <span className="pill danger"><span className="led pulse"/>Kritis</span> : <span className="pill warn"><span className="led"/>Peringatan</span>}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </>
  );
}

window.DapurDashboard = DapurDashboard;
window.MenuOptimasi = MenuOptimasi;
window.EWSScreen = EWSScreen;
