// Project Brief — Sprint B Phase 3 · single-page executive narrative.
// Goal: open the page and within 5 seconds know
//   (1) what phase the project is in
//   (2) what the Next Step is
//   (3) what is awaiting a decision
//   (4) what risks exist
// All sections degrade gracefully when data is missing.
// Replaces the placeholder registered in screen-portfolio.jsx.
(function () {
  window.SCREENS = window.SCREENS || {};
  const { useState } = React;
  const IC = window.IC, D = window.DATA;
  const sm = D.statusMeta, rm = D.riskMeta;
  const sortByDateDesc = window.sortByDateDesc || ((a) => a.slice());
  const detailFor = (p) => (D.detail && D.detail[p.id]) || (D.genericPhases && D.genericPhases(p)) || { phases: [], updates: [], decisions: [], meetings: [], documents: [], nextSteps: [] };

  // ── Star toggle (reused pattern from Portfolio) ───────────
  function StarButton({ p, canEdit }) {
    const [busy, setBusy] = useState(false);
    const onClick = async (e) => {
      e.preventDefault(); e.stopPropagation();
      if (busy || !canEdit) return;
      setBusy(true);
      try { await window.DB.toggleProjectStar(p.id); } finally { setBusy(false); }
    };
    if (!canEdit) return p.starred ? <span style={{ color: "var(--warn)", fontSize: 22 }}>★</span> : null;
    return (
      <button type="button" className="icon-btn" onClick={onClick} disabled={busy}
        title={p.starred ? "ยกเลิกการปักหมุด" : "ปักหมุดโครงการ"}
        style={{ width: 44, height: 44, color: p.starred ? "var(--warn)" : "var(--faint)", padding: 0 }}>
        <span style={{ fontSize: 22, lineHeight: 1 }}>{p.starred ? "★" : "☆"}</span>
      </button>
    );
  }

  // ── Auto-summary fallback when description is empty ──────
  function autoSummary(p, det) {
    const currentPhase =
      (det.phases || []).find((ph) => ph.status === "active") ||
      (det.phases || []).find((ph) => ph.status === "todo") ||
      ((det.phases || [])[(det.phases || []).length - 1]);
    const phaseName = currentPhase ? currentPhase.name : "ยังไม่มีเฟส";
    const s1 = "อยู่ในเฟส “" + phaseName + "” (ความคืบหน้า " + (p.progress || 0) + "%).";
    let nextMile = null;
    (det.phases || []).forEach((ph) => (ph.tasks || []).forEach((t) => {
      const isMile = window.isMilestone ? window.isMilestone(t) : (t.type === "milestone");
      if (isMile && t.status !== "done" && !nextMile) nextMile = t;
    }));
    const dueLabel = nextMile && nextMile.dateISO ? (window.isoToBE ? window.isoToBE(nextMile.dateISO) : nextMile.dateISO) : "ยังไม่ระบุ";
    const s2 = nextMile ? ("เหตุการณ์ถัดไป: " + nextMile.name + " (" + dueLabel + ").") : "ยังไม่มีเหตุการณ์สำคัญถัดไป.";
    const spentPct = p.budget ? Math.round((p.spent / p.budget) * 100) : 0;
    const rMeta = (rm[p.risk] || {});
    const s3 = "งบใช้ไป " + spentPct + "% · ความเสี่ยง: " + (rMeta.th || p.risk || "—") + ".";
    return s1 + " " + s2 + " " + s3;
  }

  // ── Decision Queue items: combine pending approvals + decision-typed next_steps ──
  function buildDecisionQueue(p, det) {
    const items = [];
    // 1) Active Next Steps with executive-decision-type
    (det.nextSteps || []).forEach((s) => {
      if (s.status !== "pending" && s.status !== "in_progress") return;
      if (s.type !== "decision" && s.type !== "approval") return;
      items.push({
        kind: "nextStep",
        id: "ns-" + s.id,
        title: s.title,
        detail: s.detail || "",
        owner: s.owner || "",
        impact: s.priority === "urgent" ? "ด่วน — กระทบ Timeline หากเลื่อน" : (s.priority === "high" ? "สำคัญ — ส่งผลต่อความคืบหน้า" : "ติดตามตามปกติ"),
        dueDate: s.dueDate || "",
        priority: s.priority || "med",
        type: s.type,
      });
    });
    // 2) Pending Approvals from approvals table (D.approvalRecords)
    (D.approvalRecords || []).filter((a) => a.projectId === p.id).forEach((a) => {
      items.push({
        kind: "approval",
        id: "ap-" + a.id,
        title: a.title,
        detail: a.amount ? "จำนวน " + a.amount : "",
        owner: a.requestedBy || "",
        impact: "รอผู้บริหารอนุมัติ — งานหยุดรอ",
        dueDate: "",
        priority: a.priority || "med",
        type: a.type || "Approval",
      });
    });
    return items;
  }

  // ── Risk Overview — concrete risk ITEMS, not just risk level ──
  // Each item is a specific problem (overdue task, budget overrun, etc.)
  // rather than just "level: medium" — executive needs to see what to act on.
  function buildRiskOverview(p, det) {
    const today = window.todayISO ? window.todayISO() : new Date().toISOString().slice(0,10);
    const risks = [];
    // 1) Past-due project (most actionable signal)
    if (p.end && p.end < today) {
      const overdueDays = Math.round((new Date(today + "T00:00:00") - new Date(p.end + "T00:00:00")) / 86400000);
      risks.push({ severity: "danger", label: "เลยกำหนดส่งโครงการ " + overdueDays + " วัน", detail: "กำหนดเดิม " + (window.isoToBE ? window.isoToBE(p.end) : p.end) });
    }
    // 2) Status-driven specific risks
    if (p.status === "blocked") risks.push({ severity: "danger", label: "ติดปัญหา — งานหยุด", detail: p.riskNote || "ต้องการการแก้ไขปัญหา" });
    if (p.status === "at_risk") risks.push({ severity: "warn", label: "เสี่ยงล่าช้า", detail: p.riskNote || "ติดตามอย่างใกล้ชิด" });
    // 3) Each overdue Next Step is an individual risk item
    const overdueSteps = (det.nextSteps || []).filter((s) =>
      (s.status === "pending" || s.status === "in_progress") && s.dueDate && s.dueDate < today);
    overdueSteps.forEach((s) => {
      const days = Math.round((new Date(today + "T00:00:00") - new Date(s.dueDate + "T00:00:00")) / 86400000);
      risks.push({ severity: "danger", label: "Next Step เลยกำหนด: " + s.title, detail: "เลย " + days + " วัน · ผู้รับ: " + (s.owner || "—") });
    });
    // 4) Budget overrun
    const spentPct = p.budget ? Math.round((p.spent / p.budget) * 100) : 0;
    if (spentPct >= 100) risks.push({ severity: "danger", label: "ใช้งบเกิน 100% (" + spentPct + "%)", detail: "งบใช้ไป " + (window.fmtBaht ? window.fmtBaht(p.spent) : p.spent) + " เกินงบที่อนุมัติ " + (window.fmtBaht ? window.fmtBaht(p.spent - p.budget) : (p.spent - p.budget)) });
    else if (spentPct >= 90) risks.push({ severity: "warn", label: "ใช้งบใกล้เต็ม (" + spentPct + "%)", detail: "งบคงเหลือ " + (p.budget ? (window.fmtBaht ? window.fmtBaht(p.budget - p.spent) : (p.budget - p.spent)) : "—") });
    // 5) Project's own riskNote (concrete narrative from PM)
    if (p.riskNote && p.risk !== "low") {
      // Only show if not already covered by status entries above
      const hasStatusEntry = p.status === "blocked" || p.status === "at_risk";
      if (!hasStatusEntry) {
        const rMeta = rm[p.risk] || { th: p.risk, tone: "warn" };
        risks.push({ severity: p.risk === "high" ? "danger" : "warn", label: p.riskNote, detail: "ระดับความเสี่ยง: " + (rMeta.th || p.risk) });
      }
    }
    // 6) Approaching due date (within 14 days, not yet overdue)
    if (p.end && p.end >= today) {
      const daysUntil = Math.round((new Date(p.end + "T00:00:00") - new Date(today + "T00:00:00")) / 86400000);
      if (daysUntil <= 14 && p.progress < 90) {
        risks.push({ severity: "warn", label: "ใกล้ครบกำหนดส่ง (อีก " + daysUntil + " วัน)", detail: "ความคืบหน้า " + (p.progress || 0) + "% — เร่งงานก่อนถึงกำหนด" });
      }
    }
    return risks;
  }

  // ── Executive Attention — top-of-mind summary that aggregates the
  // 4 things needing executive eyes RIGHT NOW. Sits above Next Step.
  function buildExecutiveAttention(p, det) {
    const today = window.todayISO ? window.todayISO() : new Date().toISOString().slice(0,10);
    const items = [];
    // 1. Overdue project
    if (p.end && p.end < today) {
      const days = Math.round((new Date(today + "T00:00:00") - new Date(p.end + "T00:00:00")) / 86400000);
      items.push({ icon: "🔴", severity: "danger", text: "โครงการเลยกำหนดส่ง " + days + " วัน" });
    }
    // 2. Pending decisions count
    const pendingDecisions =
      (det.nextSteps || []).filter((s) => (s.status === "pending" || s.status === "in_progress") && (s.type === "decision" || s.type === "approval")).length +
      (D.approvalRecords || []).filter((a) => a.projectId === p.id).length;
    if (pendingDecisions > 0) items.push({ icon: "⚖️", severity: "warn", text: pendingDecisions + " รายการรอการตัดสินใจ" });
    // 3. Overdue Next Steps
    const overdueSteps = (det.nextSteps || []).filter((s) => (s.status === "pending" || s.status === "in_progress") && s.dueDate && s.dueDate < today).length;
    if (overdueSteps > 0) items.push({ icon: "🔴", severity: "danger", text: overdueSteps + " Next Steps เลยกำหนด" });
    // 4. Budget alert
    const spentPct = p.budget ? Math.round((p.spent / p.budget) * 100) : 0;
    if (spentPct >= 100) items.push({ icon: "💸", severity: "danger", text: "งบเกินแล้ว " + spentPct + "%" });
    else if (spentPct >= 90) items.push({ icon: "💰", severity: "warn", text: "งบใช้ใกล้เต็ม " + spentPct + "%" });
    // 5. Blocked status
    if (p.status === "blocked") items.push({ icon: "🚧", severity: "danger", text: "โครงการติดปัญหา — งานหยุด" });
    return items;
  }

  // ── Section: Hero (with Health Score ring) ──────────────
  function Hero({ p, canEdit, det }) {
    const health = window.computeHealthScore ? window.computeHealthScore(p, det) : { score: 100, label: "ปกติ", tone: "ok" };
    const colorMap = { ok: "var(--ok)", info: "var(--info)", warn: "var(--warn)", danger: "var(--danger)" };
    return (
      <div className="rail-card" style={{ padding: 18, marginBottom: 16 }}>
        <a className="backlink" href="#/portfolio">{IC.chevL} กลับ Portfolio</a>
        <div style={{ display: "flex", alignItems: "flex-start", gap: 14, marginTop: 8, flexWrap: "wrap" }}>
          <div style={{ flex: "none" }}><StarButton p={p} canEdit={canEdit} /></div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div className="eyebrow">{p.code} · {p.type || ""} · {(sm[p.status] || {}).th || p.status}</div>
            <h1 style={{ fontSize: 24, fontWeight: 600, lineHeight: 1.25, marginTop: 2, wordBreak: "break-word" }}>{p.name}</h1>
            <div style={{ marginTop: 8, fontSize: 13, color: "var(--muted)" }}>
              {IC.user} {p.owner || "ไม่ระบุ"} · {IC.cal} ส่งมอบ {p.end ? (window.isoToBE ? window.isoToBE(p.end) : p.end) : "ไม่กำหนด"}
            </div>
          </div>
          {/* Health ring */}
          <div style={{ display: "flex", alignItems: "center", gap: 10, flex: "none" }}>
            <div className="health-ring" style={{ "--ring-pct": health.score, "--ring-color": colorMap[health.tone] || "var(--accent)" }}>
              <span>{health.score}</span>
            </div>
            <div>
              <div style={{ fontSize: 11, color: "var(--muted)", textTransform: "uppercase", letterSpacing: ".05em" }}>Health Score</div>
              <div className={"health-badge tone-" + health.tone} style={{ marginTop: 4 }}>{health.label}</div>
            </div>
          </div>
          <a className="btn sm" href={"#/project/" + p.id} title="เปิดในมุมมองคอนโซลผู้ดูแล" style={{ flex: "none" }}>
            คอนโซลผู้ดูแล →
          </a>
        </div>
      </div>
    );
  }

  // ── Section: Recommended Actions (per-project) ──────────
  function BriefRecommendations({ p, det }) {
    const recs = window.recommendActions ? window.recommendActions(p, det) : [];
    if (recs.length === 0) return null;   // hide entirely when nothing to do
    return (
      <div className="rail-card" style={{ padding: 16, marginBottom: 12 }}>
        <div className="exec-section-head">
          <span>🎯 สิ่งที่ควรทำต่อไป (โครงการนี้)</span>
          <span style={{ fontSize: 12, color: "var(--muted)", textTransform: "none", letterSpacing: 0 }}>{recs.length} รายการ</span>
        </div>
        <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
          {recs.map((r, i) => (
            <div key={i} className={"rec-action tone-" + r.severity}>
              <span className="ic">{r.icon}</span>
              <div className="body"><div className="act">{r.action}</div><div className="why">{r.reason}</div></div>
            </div>
          ))}
        </div>
      </div>
    );
  }

  // ── Section: Progress + Budget bars ─────────────────────
  function ProgressBudget({ p }) {
    const spentPct = p.budget ? Math.round((p.spent / p.budget) * 100) : 0;
    const bTone = spentPct > 100 ? "danger" : (spentPct >= 90 ? "warn" : "ok");
    return (
      <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(min(100%, 280px), 1fr))", gap: 12, marginBottom: 12 }}>
        <div className="rail-card" style={{ padding: 16 }}>
          <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 8 }}>
            <span style={{ fontSize: 12.5, color: "var(--muted)", textTransform: "uppercase", letterSpacing: ".05em" }}>Progress</span>
            <b className="tnum" style={{ fontSize: 22 }}>{p.progress || 0}%</b>
          </div>
          <div className="prog-bar"><i style={{ width: (p.progress || 0) + "%" }} /></div>
        </div>
        <div className="rail-card" style={{ padding: 16 }}>
          <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 8 }}>
            <span style={{ fontSize: 12.5, color: "var(--muted)", textTransform: "uppercase", letterSpacing: ".05em" }}>Budget</span>
            <b className="tnum" style={{ fontSize: 16, color: bTone === "danger" ? "var(--danger)" : (bTone === "warn" ? "var(--warn)" : "var(--ink)") }}>
              {window.fmtBaht ? window.fmtBaht(p.spent || 0) : (p.spent || 0)} / {window.fmtBaht ? window.fmtBaht(p.budget || 0) : (p.budget || 0)}
            </b>
          </div>
          <div className="prog-bar"><i style={{ width: Math.min(spentPct, 100) + "%", background: bTone === "danger" ? "var(--danger)" : (bTone === "warn" ? "var(--warn)" : "var(--accent)") }} /></div>
          <div style={{ fontSize: 11.5, color: "var(--muted)", marginTop: 4 }}>{spentPct}% ของงบ</div>
        </div>
      </div>
    );
  }

  // ── Section: Narrative — description first, auto fallback ─
  function Narrative({ p, det }) {
    const desc = (p.description || "").trim();
    const isAuto = !desc;
    const text = desc || autoSummary(p, det);
    return (
      <div className="rail-card" style={{ padding: 16, marginBottom: 12, borderLeft: "3px solid var(--accent)" }}>
        <div style={{ fontSize: 11.5, fontWeight: 700, color: "var(--muted)", textTransform: "uppercase", letterSpacing: ".05em", marginBottom: 6 }}>
          {isAuto ? <span style={{ color: "var(--warn)" }}>🤖 สรุปอัตโนมัติ</span> : "คำอธิบายโครงการ"}
        </div>
        <div style={{ fontSize: 14, color: "var(--ink2)", lineHeight: 1.6, whiteSpace: "pre-wrap", wordBreak: "break-word" }}>{text}</div>
        {isAuto && <div style={{ fontSize: 11, color: "var(--faint)", marginTop: 8 }}>ผู้ดูแลระบบสามารถเพิ่มคำอธิบายเองได้ที่คอนโซลผู้ดูแล</div>}
      </div>
    );
  }

  // ── Section: Executive Attention (sits ABOVE Next Step) ──
  function ExecutiveAttention({ p, det }) {
    const items = buildExecutiveAttention(p, det);
    const hasDanger = items.some((it) => it.severity === "danger");
    const tone = hasDanger ? "danger" : (items.length > 0 ? "warn" : "ok");
    return (
      <div className="rail-card" style={{ padding: 16, marginBottom: 12, borderLeft: "4px solid var(--" + tone + ")" }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 10 }}>
          <span style={{ fontSize: 12.5, fontWeight: 700, color: "var(--muted)", textTransform: "uppercase", letterSpacing: ".05em" }}>👀 สิ่งที่ผู้บริหารควรสนใจ</span>
          {items.length > 0 && <span style={{ fontSize: 12, color: "var(--" + tone + ")", fontWeight: 600 }}>{items.length} รายการ</span>}
        </div>
        {items.length === 0 ? (
          <div style={{ padding: 12, fontSize: 13, color: "var(--ok-d, var(--ink2))", background: "var(--ok-tint, var(--raised))", borderRadius: 10, textAlign: "center" }}>
            ✓ โครงการดำเนินไปตามแผน · ไม่มีรายการเร่งด่วน
          </div>
        ) : (
          <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
            {items.map((it, i) => (
              <div key={i} style={{ display: "flex", gap: 10, padding: 10, borderRadius: 8, background: "var(--" + it.severity + "-tint, var(--raised))", alignItems: "center" }}>
                <span style={{ fontSize: 18, flex: "none" }}>{it.icon}</span>
                <span style={{ flex: 1, fontWeight: 600, fontSize: 14, color: "var(--" + it.severity + "-d, var(--ink2))", wordBreak: "break-word" }}>{it.text}</span>
              </div>
            ))}
          </div>
        )}
      </div>
    );
  }

  // ── Section: Next Step ─────────────────────────────────
  function NextStepSection({ p, det }) {
    const steps = (det.nextSteps || []).filter((s) => s.status === "pending" || s.status === "in_progress");
    const top = steps[0];
    const PRI = (D.nextStepPriorityMeta || {});
    return (
      <div className="rail-card" style={{ padding: 16, marginBottom: 12 }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 8 }}>
          <span style={{ fontSize: 12.5, fontWeight: 700, color: "var(--muted)", textTransform: "uppercase", letterSpacing: ".05em" }}>⏭ Next Step</span>
          {steps.length > 1 && <a className="lnk" href={"#/nextsteps"} style={{ fontSize: 12.5 }}>ทั้งหมด {steps.length} →</a>}
        </div>
        {!top ? (
          <window.EmptyState icon="check" title="ยังไม่มี Next Step" sub="เพิ่ม Next Step เพื่อระบุสิ่งที่ต้องทำต่อไป" />
        ) : (
          <div style={{ display: "flex", gap: 12, alignItems: "flex-start" }}>
            <div style={{ width: 6, alignSelf: "stretch", background: "var(--" + ((PRI[top.priority] || {}).tone || "neutral") + ")", borderRadius: 3 }} />
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 15, fontWeight: 600, wordBreak: "break-word" }}>{top.title}</div>
              {top.detail && <div style={{ fontSize: 13, color: "var(--ink2)", marginTop: 4, wordBreak: "break-word" }}>{top.detail}</div>}
              <div style={{ display: "flex", gap: 14, fontSize: 12, color: "var(--muted)", marginTop: 8, flexWrap: "wrap" }}>
                <span>{IC.cal} {top.dueDate ? (window.isoToBE ? window.isoToBE(top.dueDate) : top.dueDate) : "ไม่กำหนด"}</span>
                <span>{IC.user} {top.owner || "ไม่ระบุ"}</span>
                <span className={"pill " + ((PRI[top.priority] || {}).tone || "neutral")} style={{ fontSize: 11 }}><i />{(PRI[top.priority] || {}).th || top.priority}</span>
              </div>
            </div>
          </div>
        )}
      </div>
    );
  }

  // ── Section: Decision Queue — รอตัดสินใจ ──────────────
  function DecisionQueue({ p, det }) {
    const items = buildDecisionQueue(p, det);
    const PRI = (D.nextStepPriorityMeta || {});
    return (
      <div className="rail-card" style={{ padding: 16, marginBottom: 12, borderTop: "3px solid var(--warn)" }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 10 }}>
          <span style={{ fontSize: 12.5, fontWeight: 700, color: "var(--muted)", textTransform: "uppercase", letterSpacing: ".05em" }}>⚖️ รอการตัดสินใจ</span>
          {items.length > 0 && <span style={{ fontSize: 12, color: "var(--warn)", fontWeight: 600 }}>{items.length} รายการ</span>}
        </div>
        {items.length === 0 ? (
          <window.EmptyState icon="dec" title="ไม่มีรายการรอตัดสินใจ" sub="ทุกรายการได้รับการตัดสินใจหรือดำเนินการแล้ว" />
        ) : (
          <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
            {items.map((it) => (
              <div key={it.id} style={{ padding: 12, borderRadius: 10, background: "var(--raised)", display: "flex", gap: 10, alignItems: "flex-start" }}>
                <span style={{ flex: "none", padding: "3px 8px", fontSize: 11, fontWeight: 600, borderRadius: 6, background: "var(--" + ((PRI[it.priority] || {}).tone || "neutral") + "-tint, var(--raised2))", color: "var(--" + ((PRI[it.priority] || {}).tone || "neutral") + "-d, var(--ink2))" }}>
                  {it.kind === "approval" ? "อนุมัติ" : "ตัดสินใจ"}
                </span>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontWeight: 600, fontSize: 14, wordBreak: "break-word" }}>{it.title}</div>
                  {it.detail && <div style={{ fontSize: 12.5, color: "var(--ink2)", marginTop: 3, wordBreak: "break-word" }}>{it.detail}</div>}
                  <div style={{ fontSize: 11.5, color: "var(--danger)", marginTop: 5, fontWeight: 500 }}>
                    ⚠️ ผลกระทบหากยังไม่ตัดสินใจ: {it.impact}
                  </div>
                  <div style={{ fontSize: 11, color: "var(--muted)", marginTop: 3 }}>
                    {it.owner && <>ผู้รับเรื่อง: <b style={{ color: "var(--ink2)" }}>{it.owner}</b></>}
                    {it.dueDate && <> · กำหนด {window.isoToBE ? window.isoToBE(it.dueDate) : it.dueDate}</>}
                  </div>
                </div>
              </div>
            ))}
          </div>
        )}
      </div>
    );
  }

  // ── Section: Risk Overview ────────────────────────────
  function RiskOverview({ p, det }) {
    const risks = buildRiskOverview(p, det);
    return (
      <div className="rail-card" style={{ padding: 16, marginBottom: 12, borderTop: "3px solid " + (risks.some((r) => r.severity === "danger") ? "var(--danger)" : (risks.length > 0 ? "var(--warn)" : "var(--ok)")) }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 10 }}>
          <span style={{ fontSize: 12.5, fontWeight: 700, color: "var(--muted)", textTransform: "uppercase", letterSpacing: ".05em" }}>🛡 ความเสี่ยง</span>
          {risks.length > 0 && <span style={{ fontSize: 12, color: risks.some((r) => r.severity === "danger") ? "var(--danger)" : "var(--warn)", fontWeight: 600 }}>{risks.length} รายการ</span>}
        </div>
        {risks.length === 0 ? (
          <div style={{ padding: 12, background: "var(--ok-tint, var(--raised))", borderRadius: 10, fontSize: 13, color: "var(--ok-d, var(--ink2))", textAlign: "center" }}>
            ✓ ไม่พบความเสี่ยงสำคัญในขณะนี้
          </div>
        ) : (
          <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
            {risks.map((r, i) => (
              <div key={i} style={{ display: "flex", gap: 10, padding: 10, borderRadius: 8, background: "var(--" + r.severity + "-tint, var(--raised))" }}>
                <span style={{ fontSize: 18, lineHeight: 1, flex: "none", color: "var(--" + r.severity + ")" }}>{r.severity === "danger" ? "🔴" : "🟡"}</span>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontWeight: 600, fontSize: 13.5, color: "var(--" + r.severity + "-d, var(--ink2))", wordBreak: "break-word" }}>{r.label}</div>
                  {r.detail && <div style={{ fontSize: 12, color: "var(--ink2)", marginTop: 2, wordBreak: "break-word" }}>{r.detail}</div>}
                </div>
              </div>
            ))}
          </div>
        )}
      </div>
    );
  }

  // ── Section: Phase Timeline (mini-Gantt) ──────────────
  function PhaseTimelineSection({ p, det }) {
    const phases = det.phases || [];
    if (phases.length === 0) {
      return (
        <div className="rail-card" style={{ padding: 16, marginBottom: 12 }}>
          <div style={{ fontSize: 12.5, fontWeight: 700, color: "var(--muted)", textTransform: "uppercase", letterSpacing: ".05em", marginBottom: 10 }}>📅 Timeline ภาพรวม</div>
          <window.EmptyState icon="gantt" title="ยังไม่มี Timeline" sub="ผู้ดูแลระบบสร้าง Timeline ของโครงการได้ที่คอนโซลผู้ดูแล" />
        </div>
      );
    }
    // Reuse window.Gantt with project's phases
    const g = window.ganttScale ? window.ganttScale(p, det) : null;
    return (
      <div className="rail-card" style={{ padding: 16, marginBottom: 12 }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 10 }}>
          <span style={{ fontSize: 12.5, fontWeight: 700, color: "var(--muted)", textTransform: "uppercase", letterSpacing: ".05em" }}>📅 Timeline ภาพรวม</span>
          <a className="lnk" href={"#/project/" + p.id} style={{ fontSize: 12.5 }}>ดูเต็ม →</a>
        </div>
        <div className="gantt-wrap" style={{ marginTop: 0 }}>
          {g && <window.Gantt phases={g.phases} mode="exec" startISO={g.startISO} todayDay={g.todayDay} totalDays={g.totalDays} />}
        </div>
      </div>
    );
  }

  // ── Section: Detailed Phase Timeline (events list) ─────
  function DetailedPhaseTimeline({ p, det }) {
    const phases = det.phases || [];
    if (phases.length === 0) return null;
    return (
      <div className="rail-card" style={{ padding: 16, marginBottom: 12 }}>
        <div style={{ fontSize: 12.5, fontWeight: 700, color: "var(--muted)", textTransform: "uppercase", letterSpacing: ".05em", marginBottom: 10 }}>🪜 รายละเอียดเฟส</div>
        <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          {phases.map((ph, i) => {
            const phUpd = (det.updates || []).filter((u) => u.phaseId === ph.id);
            const miles = (ph.tasks || []).filter((t) => window.isMilestone ? window.isMilestone(t) : (t.type === "milestone"));
            return (
              <div key={ph.id}>
                <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 6 }}>
                  <div><span style={{ fontWeight: 600 }}>{i + 1}. {ph.name}</span> <span className={"pill " + ((D.phaseStatusMeta && D.phaseStatusMeta[ph.status] || {}).tone || "neutral")} style={{ fontSize: 11, marginLeft: 6 }}><i />{(D.phaseStatusMeta && D.phaseStatusMeta[ph.status] || {}).th || ph.status}</span></div>
                  <span className="tnum" style={{ fontSize: 12, color: "var(--muted)" }}>{ph.progress || 0}%</span>
                </div>
                <div className="prog-bar thin" style={{ marginBottom: 6 }}><i style={{ width: (ph.progress || 0) + "%", background: ph.status === "done" ? "var(--ok)" : "var(--accent)" }} /></div>
                {(miles.length > 0 || phUpd.length > 0) && (
                  <div style={{ fontSize: 12, color: "var(--muted)", paddingLeft: 12, borderLeft: "1px solid var(--line-soft)" }}>
                    {miles.slice(0, 2).map((t) => <div key={t.id} style={{ marginBottom: 2 }}>♦ {t.name}{t.dateISO ? " · " + (window.isoToBE ? window.isoToBE(t.dateISO) : t.dateISO) : ""}</div>)}
                    {phUpd.slice(0, 2).map((u) => <div key={u.id} style={{ marginBottom: 2 }}>● {u.title}{u.date ? " · " + u.date : ""}</div>)}
                  </div>
                )}
              </div>
            );
          })}
        </div>
      </div>
    );
  }

  // ── Section: Latest Activities ─────────────────────────
  function LatestActivities({ p, det }) {
    const ups = (det.updates || []).map((u) => ({ kind: "update", id: "u-" + u.id, dateISO: u.dateISO || "", date: u.date || "", title: u.title, sub: ((D.updateTypes && D.updateTypes[u.type] || {}).th || u.type || "") + (u.assignee ? " · " + u.assignee : ""), tone: (D.updateTypes && D.updateTypes[u.type] || {}).tone || "neutral" }));
    const decs = (det.decisions || []).map((d) => ({ kind: "decision", id: "d-" + d.id, dateISO: d.dateISO || "", date: d.date || "", title: d.change, sub: d.by ? "โดย " + d.by : "", tone: "info" }));
    const all = sortByDateDesc([...ups, ...decs]).slice(0, 5);
    return (
      <div className="rail-card" style={{ padding: 16, marginBottom: 12 }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 10 }}>
          <span style={{ fontSize: 12.5, fontWeight: 700, color: "var(--muted)", textTransform: "uppercase", letterSpacing: ".05em" }}>📰 ความเคลื่อนไหวล่าสุด</span>
        </div>
        {all.length === 0 ? (
          <window.EmptyState icon="trend" title="ยังไม่มีความเคลื่อนไหว" sub="อัปเดต / Decision ล่าสุดของโครงการจะแสดงที่นี่" />
        ) : (
          <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
            {all.map((a) => (
              <div key={a.id} style={{ display: "flex", gap: 10, fontSize: 13, alignItems: "flex-start" }}>
                <span style={{ width: 9, height: 9, borderRadius: "50%", background: "var(--" + a.tone + ")", marginTop: 5, flex: "none" }} />
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontWeight: 500, wordBreak: "break-word" }}>{a.title}</div>
                  <div style={{ fontSize: 11.5, color: "var(--muted)" }}>{a.date} · {a.kind === "decision" ? "Decision" : "อัปเดต"}{a.sub ? " · " + a.sub : ""}</div>
                </div>
              </div>
            ))}
          </div>
        )}
      </div>
    );
  }

  // ════════════════════════════════════════════════════════
  //  TAB VIEWS — read-only, live from the single source of truth
  // ════════════════════════════════════════════════════════

  // อัปเดตโครงการ
  function UpdatesTabView({ p, det }) {
    const ups = sortByDateDesc(det.updates || []);
    if (ups.length === 0) return <window.EmptyState icon="trend" title="ยังไม่มีอัปเดต" sub="ความเคลื่อนไหวของโครงการจะแสดงที่นี่" />;
    return <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>{ups.map((u) => <window.UpdateCard key={u.id} u={u} />)}</div>;
  }

  // การประชุม
  function MeetingsTabView({ p }) {
    const ms = sortByDateDesc((D.meetingRecords || []).filter((m) => m.projectId === p.id || m.project === p.name));
    if (ms.length === 0) return <window.EmptyState icon="meet" title="ยังไม่มีการประชุม" sub="การประชุมที่เกี่ยวกับโครงการนี้จะแสดงที่นี่" />;
    return (
      <div className="rail-card" style={{ padding: 0 }}>
        {ms.map((m) => (
          <div key={m.id} style={{ display: "flex", gap: 12, padding: 14, borderBottom: "1px solid var(--line-soft)", alignItems: "flex-start" }}>
            <div style={{ flex: "none", textAlign: "center", minWidth: 54 }}>
              <b className="tnum" style={{ fontSize: 16 }}>{(m.date || "").split(" ")[0]}</b>
              <div style={{ fontSize: 11, color: "var(--muted)" }}>{(m.date || "").split(" ")[1]}</div>
            </div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontWeight: 600, wordBreak: "break-word" }}>{m.title}</div>
              <div style={{ fontSize: 12, color: "var(--muted)", marginTop: 2 }}>{m.type}{m.time ? " · " + m.time : ""}{m.outcome && m.outcome !== "—" ? " · " + m.outcome : ""}</div>
              {(m.agenda || []).length > 0 && <div style={{ fontSize: 12, color: "var(--ink2)", marginTop: 4 }}>วาระ: {m.agenda.slice(0,3).join(" · ")}{m.agenda.length>3?" …":""}</div>}
            </div>
          </div>
        ))}
      </div>
    );
  }

  // Decision
  function DecisionsTabView({ det }) {
    const ds = sortByDateDesc(det.decisions || []);
    if (ds.length === 0) return <window.EmptyState icon="dec" title="ยังไม่มี Decision" sub="บันทึกการตัดสินใจของโครงการจะแสดงที่นี่" />;
    return (
      <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
        {ds.map((d) => (
          <div key={d.id} className="rail-card" style={{ padding: 14 }}>
            <div style={{ display: "flex", justifyContent: "space-between", gap: 8, flexWrap: "wrap" }}>
              <span style={{ fontSize: 12, color: "var(--muted)" }}>{d.date}</span>
              {d.impact && <span className="pill warn" style={{ fontSize: 11 }}><i />{d.impact}</span>}
            </div>
            <div style={{ fontWeight: 600, marginTop: 4, wordBreak: "break-word" }}>{d.change}</div>
            {d.reason && <div style={{ fontSize: 13, color: "var(--ink2)", marginTop: 4, wordBreak: "break-word" }}><window.ExpandableText text={d.reason} lines={3} title="เหตุผล" /></div>}
            {d.by && <div style={{ fontSize: 12, color: "var(--muted)", marginTop: 6 }}>{IC.user} {d.by}</div>}
          </div>
        ))}
      </div>
    );
  }

  // เอกสาร
  function DocumentsTabView({ det }) {
    const docs = det.documents || [];
    if (docs.length === 0) return <window.EmptyState icon="doc" title="ยังไม่มีเอกสาร" sub="เอกสารของโครงการจะแสดงที่นี่" />;
    const openDoc = async (d) => {
      if (window.Files && d.fileId) { await window.Files.open(d); return; }
      if (d.fileUrl) window.open(d.fileUrl, "_blank", "noopener");
      else window.toast && window.toast("เอกสารนี้ยังไม่ได้อัปโหลด");
    };
    return (
      <div className="rail-card" style={{ padding: 0 }}>
        {docs.map((d, i) => (
          <div key={d.id || i} style={{ display: "flex", gap: 12, padding: 13, borderBottom: "1px solid var(--line-soft)", alignItems: "center", cursor: (d.fileId || d.fileUrl) ? "pointer" : "default" }} onClick={() => openDoc(d)}>
            <span className={"doc-ic " + (d.type || "other").toLowerCase()} style={{ flex: "none" }}>{(d.name.split(".").pop() || "OTH").slice(0,3).toUpperCase()}</span>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontWeight: 500, wordBreak: "break-word" }}>{d.name}</div>
              <div style={{ fontSize: 12, color: "var(--muted)" }}>{d.folder ? "📁 " + d.folder + " · " : ""}{d.type} · {d.size} · {d.by} · {d.date}</div>
            </div>
            {(d.fileId || d.fileUrl) && <span className="icon-btn" style={{ flex: "none", width: 32, height: 32 }}>{IC.download}</span>}
          </div>
        ))}
      </div>
    );
  }

  // งบประมาณ
  function BudgetTabView({ p, det }) {
    if (!p.budget) {
      return <window.EmptyState icon="money" title="ยังไม่มีข้อมูลงบประมาณ" sub="ผู้ดูแลระบบกำหนดงบประมาณของโครงการได้ที่คอนโซลผู้ดูแล" />;
    }
    const spentPct = p.budget ? Math.round((p.spent / p.budget) * 100) : 0;
    const remain = (p.budget || 0) - (p.spent || 0);
    const bTone = spentPct > 100 ? "danger" : (spentPct >= 90 ? "warn" : "ok");
    const budgetUps = (det.updates || []).filter((u) => u.type === "budget" || u.type === "approval");
    return (
      <div>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(min(100%, 220px), 1fr))", gap: 12, marginBottom: 12 }}>
          <div className="rail-card" style={{ padding: 16 }}><div style={{ fontSize: 12, color: "var(--muted)" }}>งบประมาณรวม</div><div className="exec-kpi exec-kpi-m" style={{ marginTop: 6 }}>{window.fmtBaht ? window.fmtBaht(p.budget) : p.budget}</div></div>
          <div className="rail-card" style={{ padding: 16 }}><div style={{ fontSize: 12, color: "var(--muted)" }}>เบิกจ่ายแล้ว</div><div className="exec-kpi exec-kpi-m" style={{ marginTop: 6, color: "var(--" + bTone + ")" }}>{window.fmtBaht ? window.fmtBaht(p.spent) : p.spent}</div><div style={{ fontSize: 11.5, color: "var(--muted)", marginTop: 2 }}>{spentPct}% ของงบ</div></div>
          <div className="rail-card" style={{ padding: 16 }}><div style={{ fontSize: 12, color: "var(--muted)" }}>คงเหลือ</div><div className="exec-kpi exec-kpi-m" style={{ marginTop: 6 }}>{window.fmtBaht ? window.fmtBaht(remain) : remain}</div></div>
        </div>
        <div className="rail-card" style={{ padding: 16, marginBottom: 12 }}>
          <div style={{ display: "flex", justifyContent: "space-between", fontSize: 13, marginBottom: 8 }}><span>การใช้งบประมาณ</span><b className="tnum">{spentPct}%</b></div>
          <div className="prog-bar"><i style={{ width: Math.min(spentPct, 100) + "%", background: "var(--" + (bTone === "ok" ? "accent" : bTone) + ")" }} /></div>
        </div>
        {budgetUps.length > 0 && (
          <div>
            <div className="exec-section-head"><span>ความเคลื่อนไหวด้านงบประมาณ</span></div>
            <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>{sortByDateDesc(budgetUps).map((u) => <window.UpdateCard key={u.id} u={u} />)}</div>
          </div>
        )}
      </div>
    );
  }

  // รายงาน
  function ReportingTabView({ p, det }) {
    const done = (det.phases || []).filter((ph) => ph.status === "done").length;
    const spentPct = p.budget ? Math.round((p.spent / p.budget) * 100) : 0;
    const latestUp = sortByDateDesc(det.updates || [])[0];
    const latestDec = sortByDateDesc(det.decisions || [])[0];
    const health = window.computeHealthScore ? window.computeHealthScore(p, det) : null;
    return (
      <div>
        <div className="rail-card" style={{ padding: 16, marginBottom: 12, lineHeight: 1.8, fontSize: 14 }}>
          <div className="exec-section-head"><span>สรุปสำหรับผู้บริหาร</span></div>
          <div><b>{p.name}</b> ({p.code}) — สถานะ <b>{(sm[p.status] || {}).th || p.status}</b> · ความคืบหน้า <b>{p.progress || 0}%</b>{health ? <> · Health <b>{health.score}</b> ({health.label})</> : null}</div>
          <div style={{ color: "var(--ink2)", marginTop: 4 }}>เจ้าของงาน: {p.owner || "—"} · กำหนดส่ง: {p.end ? (window.isoToBE ? window.isoToBE(p.end) : p.end) : "—"} · เฟสเสร็จ {done}/{(det.phases || []).length}</div>
          <div style={{ color: "var(--ink2)", marginTop: 4 }}>งบประมาณ: {window.fmtBaht ? window.fmtBaht(p.spent) : p.spent} / {window.fmtBaht ? window.fmtBaht(p.budget) : p.budget} ({spentPct}%)</div>
          {latestUp && <div style={{ marginTop: 6 }}>อัปเดตล่าสุด: <b>{latestUp.title}</b> ({latestUp.date})</div>}
          {latestDec && <div style={{ marginTop: 2 }}>Decision ล่าสุด: <b>{latestDec.change}</b> ({latestDec.date})</div>}
        </div>
        {window.openReport && (
          <button className="btn pri" onClick={() => window.openReport("exec")}>{IC.download} เปิดรายงานฉบับเต็ม</button>
        )}
      </div>
    );
  }

  // ── Main Brief screen — Overview + tab navigation ──────────
  // OVERRIDES the placeholder registered by screen-portfolio.jsx.
  window.SCREENS.brief = function ProjectBrief({ route }) {
    window.useLiveData();
    const [tab, setTab] = useState("overview");
    const p = (D.projects || []).find((x) => x.id === route.id);
    const canEdit = window.can ? window.can("editProject") : false;
    if (!p) {
      return <div className="page wide"><div className="empty">ไม่พบโครงการ — <a className="lnk" href="#/portfolio">กลับ Portfolio</a></div></div>;
    }
    const det = detailFor(p);
    const meetCt = (D.meetingRecords || []).filter((m) => m.projectId === p.id || m.project === p.name).length;
    const TABS = [
      { id: "overview", label: "ภาพรวม" },
      { id: "updates", label: "อัปเดตโครงการ", ct: (det.updates || []).length },
      { id: "meetings", label: "การประชุม", ct: meetCt },
      { id: "decisions", label: "Decision", ct: (det.decisions || []).length },
      { id: "documents", label: "เอกสาร", ct: (det.documents || []).length },
      { id: "budget", label: "งบประมาณ" },
      { id: "reporting", label: "รายงาน" },
    ];
    return (
      <div className="page wide exec-screen" style={{ maxWidth: 920 }}>
        <Hero p={p} canEdit={canEdit} det={det} />

        <div className="tabs" style={{ marginBottom: 16 }}>
          {TABS.map((t) => (
            <button key={t.id} className={"tab" + (tab === t.id ? " on" : "")} onClick={() => setTab(t.id)}>
              {t.label}{t.ct ? <span className="tb-ct">{t.ct}</span> : null}
            </button>
          ))}
        </div>

        {tab === "overview" && <>
          <ProgressBudget p={p} />
          <Narrative p={p} det={det} />
          <ExecutiveAttention p={p} det={det} />
          <BriefRecommendations p={p} det={det} />
          <NextStepSection p={p} det={det} />
          <DecisionQueue p={p} det={det} />
          <RiskOverview p={p} det={det} />
          <PhaseTimelineSection p={p} det={det} />
          <DetailedPhaseTimeline p={p} det={det} />
          <LatestActivities p={p} det={det} />
        </>}
        {tab === "updates"   && <UpdatesTabView p={p} det={det} />}
        {tab === "meetings"  && <MeetingsTabView p={p} />}
        {tab === "decisions" && <DecisionsTabView det={det} />}
        {tab === "documents" && <DocumentsTabView det={det} />}
        {tab === "budget"    && <BudgetTabView p={p} det={det} />}
        {tab === "reporting" && <ReportingTabView p={p} det={det} />}
      </div>
    );
  };
})();
