// ===== m7-reports.jsx =====
// M7 · Reports — replaces window.OrgReports with PRD-fidelity module
//   FR2 Standard / canned report library
//   FR3 Ad-hoc report builder (field tree, filters, save/share, drill-down)
//   FR4 Scoped + read-only views (Universal · Regional · Read-only exec)
//   FR5 Date ranges, comparison ops, export formats incl. mailing labels
//   FR6 Federal/state/funder grant reporting (Hunter Outreach)
//   FR8 Scheduled reports, automated delivery
//   FR9 Data portability / tenant archive
//   FR10 Audit evidence

const {
  React,
  TopBar, Card, SectionHead, Btn, IconBtn, StatusChip, Avatar, Kpi, Progress,
  Field, Input, Textarea, Select, Checkbox, Toggle, Tabs, Empty,
  IconPlus, IconCheck, IconX, IconArrow, IconArrowL, IconDownload, IconUpload,
  IconReport, IconClock, IconClipboard, IconShield, IconSearch, IconFilter,
  IconMore, IconStar, IconAward, IconUsers, IconCal, IconMail, IconChevron, IconChevronD,
  IconExternal, IconEdit,
  VOLUNTEERS,
} = window;
const { useState: useS, useMemo: useM } = React;

const m7_overline = { fontSize: 11, letterSpacing: "0.12em", textTransform: "uppercase", color: "var(--fg-3)", fontWeight: 500 };
const m7_meta = { fontSize: 11, color: "var(--fg-3)" };
const m7_link = { background: "transparent", border: "none", color: "var(--coral-700)", fontSize: 12, fontWeight: 500, cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 4, padding: 0 };

// ============================================================
// CATALOG — required + standard reports
// ============================================================
const REPORT_CATALOG = [
  // CPW RFP-required (9 canned) — definitions placeholder per PRD
  { id: "rep-roster",     group: "RFP required", title: "Volunteer roster", desc: "Active volunteers with role, site, program, status, last activity.", out: ["XLSX", "CSV", "PDF"], lastRun: "Yest, 4:12 pm", rows: 4127, audit: true },
  { id: "rep-signin",     group: "RFP required", title: "Event sign-in sheet", desc: "Per-event roster with name, role, signature line, hours.", out: ["PDF"], lastRun: "Today, 7:01 am", rows: 18, audit: true },
  { id: "rep-hours",      group: "RFP required", title: "Service hours by program", desc: "Sum of approved hours grouped by program × month × site. Includes service value at $33.49/hr.", out: ["XLSX", "CSV", "PDF", "Google Sheets"], lastRun: "Today, 6:14 am", rows: 1284, audit: true },
  { id: "rep-attend",     group: "RFP required", title: "Attendance + no-show", desc: "Per-event attendance, no-shows, waitlist conversions, RSVP custom fields.", out: ["XLSX", "CSV", "PDF"], lastRun: "May 21", rows: 642 },
  { id: "rep-history",    group: "RFP required", title: "Registration history", desc: "Volunteer signup history across opportunities, with status timeline.", out: ["XLSX", "CSV"], lastRun: "May 20", rows: 9128 },
  { id: "rep-recog-elig", group: "RFP required", title: "Recognition eligibility", desc: "Volunteers meeting milestone/pass thresholds. Configurable by recognition program.", out: ["XLSX", "CSV", "Avery 5160"], lastRun: "Today, 8:08 am", rows: 51, audit: true },
  { id: "rep-recog-iss",  group: "RFP required", title: "Award issuance log", desc: "All recorded issuances with actor, timestamp, audit ref. Immutable.", out: ["XLSX", "CSV"], lastRun: "Today, 9:14 am", rows: 412, audit: true },
  { id: "rep-grant-hunt", group: "RFP required", title: "Hunter Outreach grant report", desc: "Federal grant. Per-event hours by activity type with location, start/end times, audit signoff.", out: ["XLSX", "PDF", "CSV"], lastRun: "May 19", rows: 86, audit: true, grant: true },
  { id: "rep-compliance", group: "RFP required", title: "Background check + waiver status", desc: "Compliance roll-up: who's current, who's expiring, red flags.", out: ["XLSX", "CSV", "PDF"], lastRun: "May 15", rows: 624, audit: true },

  // Operational
  { id: "rep-svc-value",  group: "Operational", title: "Service-value report", desc: "Approved hours × Independent Sector value, by program and park.", out: ["XLSX", "PDF"], lastRun: "May 1", rows: 32, audit: true },
  { id: "rep-retention",  group: "Operational", title: "Retention curve", desc: "How many volunteers come back at 1, 3, 12 months. By program.", out: ["XLSX", "PDF"], lastRun: "Apr 28", rows: 18 },
  { id: "rep-demographics", group: "Operational", title: "Demographic snapshot", desc: "Self-disclosed demographics where consented. Aggregated only — never per-volunteer for outreach exports.", out: ["XLSX", "PDF"], lastRun: "Apr 1", rows: 24, sensitive: true },
  { id: "rep-groups",     group: "Operational", title: "Group / corporate participation", desc: "Headcount, hours, projects per partner organization.", out: ["XLSX", "CSV", "PDF"], lastRun: "May 18", rows: 38 },
  { id: "rep-prep",       group: "Operational", title: "Travel / prep / follow-up time", desc: "Includes travel, prep, follow-up, mileage, attendance, no-show, waitlist, RSVP custom fields.", out: ["XLSX", "CSV"], lastRun: "May 17", rows: 1284 },
  { id: "rep-heatmap",    group: "Operational", title: "Site activity heatmap", desc: "Time-of-year × park heatmap.", out: ["PDF"], lastRun: "May 12", rows: 0 },

  // Security & audit
  { id: "rep-audit",      group: "Audit & compliance", title: "Audit log export", desc: "Every hour adjustment, award issuance, configuration change. Immutable.", out: ["CSV"], lastRun: "Apr 30", rows: 18420, audit: true },
  { id: "rep-access",     group: "Audit & compliance", title: "Access review", desc: "Who has what role, when granted, last login, MFA status.", out: ["XLSX", "CSV"], lastRun: "May 1", rows: 38, audit: true, sensitive: true },
  { id: "rep-export-log", group: "Audit & compliance", title: "Export & report-access log", desc: "Every export and report run by actor, with filters, row count, definition version.", out: ["CSV"], lastRun: "Today, 9:14 am", rows: 1248, audit: true },
];

// ============================================================
// ROOT
// ============================================================
const OrgReports = ({ go }) => {
  const [tab, setTab] = useS("library");
  // Role view (from app-level tweak)
  const [viewAs, setViewAs] = useS("universal");

  const tabs = [
    { id: "library",    label: "Standard library", count: REPORT_CATALOG.length },
    { id: "builder",    label: "Ad-hoc builder" },
    { id: "saved",      label: "Saved & shared", count: 7 },
    { id: "scheduled",  label: "Scheduled", count: 4 },
    { id: "grant",      label: "Grant reporting" },
    { id: "audit",      label: "Audit evidence" },
    { id: "archive",    label: "Tenant archive" },
  ];

  return (
    <>
      <TopBar title="Reports"
        subtitle="9 RFP-required canned reports · ad-hoc builder · scheduled deliveries · tenant archive"
        primary={<Btn icon={IconPlus} onClick={() => setTab("builder")}>Build a report</Btn>}
        secondary={<Btn kind="secondary" icon={IconDownload}>Export library</Btn>} />

      <div style={{ flex: 1, overflow: "auto", padding: "20px 32px 56px" }}>
        <ViewAsBar viewAs={viewAs} setViewAs={setViewAs} />
        <Tabs active={tab} onChange={setTab} tabs={tabs} />

        {tab === "library"   && <Library viewAs={viewAs} go={go} />}
        {tab === "builder"   && <Builder viewAs={viewAs} />}
        {tab === "saved"     && <Saved viewAs={viewAs} />}
        {tab === "scheduled" && <Scheduled />}
        {tab === "grant"     && <Grant />}
        {tab === "audit"     && <AuditEvidence />}
        {tab === "archive"   && <Portability />}
      </div>
    </>
  );
};

// ============================================================
// VIEW-AS BAR (FR4 scoped / read-only)
// ============================================================
const ViewAsBar = ({ viewAs, setViewAs }) => {
  const opts = [
    { id: "universal", label: "Universal admin",        desc: "All tenant records · run any report · export full data" },
    { id: "regional",  label: "Regional admin · NE",    desc: "Northeast region only · scoped exports · filtered library" },
    { id: "readonly",  label: "Read-only exec / funder",desc: "Aggregated dashboards · no per-record drill · audited access" },
  ];
  return (
    <div style={{ display: "flex", gap: 10, padding: "10px 14px", marginBottom: 16, borderRadius: 12, background: "var(--paper-soft)", border: "1px solid var(--border-soft)", alignItems: "center", flexWrap: "wrap" }}>
      <div style={{ display: "flex", gap: 6, alignItems: "center", whiteSpace: "nowrap" }}>
        <IconShield size={14} style={{ color: "var(--fg-3)" }} />
        <span style={{ ...m7_overline }}>Preview as</span>
      </div>
      <div style={{ display: "flex", gap: 4 }}>
        {opts.map(o => (
          <button key={o.id} onClick={() => setViewAs(o.id)} style={{
            background: viewAs === o.id ? "var(--ink)" : "transparent",
            color: viewAs === o.id ? "var(--paper)" : "var(--fg-1)",
            border: "1px solid " + (viewAs === o.id ? "var(--ink)" : "var(--border)"),
            padding: "6px 12px", borderRadius: 999, fontSize: 12, fontWeight: 500, cursor: "pointer", fontFamily: "inherit", whiteSpace: "nowrap",
          }}>{o.label}</button>
        ))}
      </div>
      <div style={{ flex: 1, minWidth: 200, fontSize: 12, color: "var(--fg-2)" }}>
        {opts.find(o => o.id === viewAs)?.desc}
      </div>
    </div>
  );
};

// ============================================================
// LIBRARY (FR2)
// ============================================================
const Library = ({ viewAs, go }) => {
  const [q, setQ] = useS("");
  const [group, setGroup] = useS("all");

  // Group/Filter — scoped admins lose some sensitive reports
  let cat = REPORT_CATALOG.filter(r => {
    if (viewAs === "readonly" && (r.audit || r.id === "rep-export-log" || r.id === "rep-access")) return false; // read-only can't pull audit
    if (viewAs === "readonly" && r.sensitive) return false;
    if (viewAs === "regional" && r.id === "rep-access") return false;
    if (group !== "all" && r.group !== group) return false;
    if (q && !(r.title + " " + r.desc).toLowerCase().includes(q.toLowerCase())) return false;
    return true;
  });

  const groups = Array.from(new Set(REPORT_CATALOG.map(r => r.group)));

  return (
    <>
      {viewAs === "readonly" && (
        <div style={{ padding: "14px 16px", marginBottom: 14, borderRadius: 10, background: "var(--iris-100)", border: "1px solid rgba(67,86,161,0.18)", color: "var(--iris-600)", display: "flex", gap: 12, alignItems: "center", fontSize: 12 }}>
          <IconShield size={16} />
          <span><strong>Read-only role.</strong> Outputs are aggregate-only and audited. Per-record drill-down, exports of audit logs, and access-review reports are hidden. Sensitive demographic data is suppressed in this view.</span>
        </div>
      )}
      <div style={{ display: "flex", gap: 10, marginBottom: 16, alignItems: "center" }}>
        <div style={{ position: "relative", flex: 1, maxWidth: 360 }}>
          <Input value={q} onChange={(e) => setQ(e.target.value)} placeholder="Search library…" style={{ width: "100%", paddingLeft: 34 }} />
          <IconSearch size={15} style={{ position: "absolute", left: 12, top: 12, color: "var(--fg-3)" }} />
        </div>
        <div style={{ display: "flex", gap: 6 }}>
          {["all", ...groups].map(g => (
            <button key={g} onClick={() => setGroup(g)} style={{
              padding: "7px 11px", borderRadius: 999, fontSize: 12, fontWeight: 500, cursor: "pointer", fontFamily: "inherit",
              background: group === g ? "var(--coral-100)" : "transparent",
              color: group === g ? "var(--coral-700)" : "var(--fg-1)",
              border: "1px solid " + (group === g ? "var(--coral-200)" : "var(--border)"),
            }}>{g === "all" ? "All reports" : g}</button>
          ))}
        </div>
        <div style={{ marginLeft: "auto", fontSize: 12, color: "var(--fg-3)" }}>{cat.length} of {REPORT_CATALOG.length}</div>
      </div>

      {/* Group by group */}
      {(group === "all" ? groups : [group]).map(g => {
        const list = cat.filter(r => r.group === g);
        if (!list.length) return null;
        return (
          <div key={g} style={{ marginBottom: 22 }}>
            <SectionHead title={g} />
            <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 12 }}>
              {list.map(r => <ReportCard key={r.id} r={r} viewAs={viewAs} />)}
            </div>
          </div>
        );
      })}
    </>
  );
};

const ReportCard = ({ r, viewAs }) => {
  const restricted = viewAs === "regional" && r.id === "rep-access";
  return (
    <Card>
      <div style={{ display: "flex", gap: 8, alignItems: "baseline", marginBottom: 6 }}>
        <div style={{ fontSize: 14, fontWeight: 500, color: "var(--ink)", flex: 1 }}>{r.title}</div>
        {r.audit && <span style={{ fontSize: 10, padding: "2px 7px", borderRadius: 999, background: "var(--iris-100)", color: "var(--iris-600)", fontWeight: 500, whiteSpace: "nowrap" }}>Audit-grade</span>}
        {r.sensitive && <span style={{ fontSize: 10, padding: "2px 7px", borderRadius: 999, background: "var(--amber-100)", color: "var(--amber-600)", fontWeight: 500, whiteSpace: "nowrap" }}>Sensitive</span>}
        {r.grant && <span style={{ fontSize: 10, padding: "2px 7px", borderRadius: 999, background: "var(--sage-100)", color: "var(--sage-700)", fontWeight: 500, whiteSpace: "nowrap" }}>Grant</span>}
      </div>
      <div style={{ fontSize: 12, color: "var(--fg-2)", lineHeight: 1.5, marginBottom: 14, minHeight: 54 }}>{r.desc}</div>
      <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 14 }}>
        {r.out.map(o => <span key={o} style={{ fontSize: 10, padding: "2px 8px", borderRadius: 4, background: "var(--paper-deep)", color: "var(--fg-2)", fontFamily: "var(--font-mono)" }}>{o}</span>)}
      </div>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
        <div style={{ ...m7_meta }}>Last run {r.lastRun} · {r.rows ? r.rows.toLocaleString() + " rows" : "—"}</div>
        <div style={{ display: "flex", gap: 4 }}>
          <Btn size="sm" kind="ghost">Preview</Btn>
          <Btn size="sm" kind="secondary" disabled={restricted}>{restricted ? "Restricted" : "Run"}</Btn>
        </div>
      </div>
    </Card>
  );
};

// ============================================================
// BUILDER (FR3 ad-hoc) — field tree + filters + group by + comparison ops + drill-down preview
// ============================================================
const FIELD_TREE = [
  { group: "Volunteer", fields: [
    { id: "v.name", label: "Name", type: "text" },
    { id: "v.email", label: "Email", type: "text", sensitive: true },
    { id: "v.phone", label: "Phone", type: "text", sensitive: true },
    { id: "v.city", label: "City", type: "text" },
    { id: "v.status", label: "Status", type: "enum" },
    { id: "v.joined", label: "Joined date", type: "date" },
    { id: "v.languages", label: "Languages", type: "list" },
    { id: "v.tags", label: "Tags", type: "list" },
    { id: "v.segment", label: "Saved segment", type: "list" },
  ]},
  { group: "Service hours", fields: [
    { id: "h.total", label: "Total hours", type: "number" },
    { id: "h.ytd", label: "YTD hours", type: "number" },
    { id: "h.last12mo", label: "Rolling 12-mo hours", type: "number" },
    { id: "h.lifetime", label: "Lifetime hours", type: "number" },
    { id: "h.travel", label: "Travel time", type: "number" },
    { id: "h.prep", label: "Prep time", type: "number" },
    { id: "h.followup", label: "Follow-up time", type: "number" },
    { id: "h.mileage", label: "Mileage", type: "number" },
    { id: "h.approval", label: "Approval state", type: "enum" },
  ]},
  { group: "Participation", fields: [
    { id: "p.opportunity", label: "Opportunity", type: "text" },
    { id: "p.attendance", label: "Attendance state", type: "enum" },
    { id: "p.noshow", label: "No-show flag", type: "bool" },
    { id: "p.waitlist", label: "Waitlist?", type: "bool" },
    { id: "p.rsvp_custom", label: "RSVP custom fields", type: "text" },
  ]},
  { group: "Site / program / role", fields: [
    { id: "s.site", label: "Site", type: "text" },
    { id: "s.program", label: "Program", type: "text" },
    { id: "s.role", label: "Role", type: "text" },
    { id: "s.region", label: "Region", type: "text" },
  ]},
  { group: "Recognition", fields: [
    { id: "r.milestone", label: "Milestone tier", type: "enum" },
    { id: "r.pref", label: "Award preference", type: "text" },
    { id: "r.issued", label: "Issued?", type: "bool" },
    { id: "r.issued_at", label: "Issued date", type: "date" },
  ]},
  { group: "Flags & restrictions", fields: [
    { id: "f.red", label: "Red flag", type: "bool", sensitive: true },
    { id: "f.yellow", label: "Yellow flag", type: "bool", sensitive: true },
    { id: "f.deceased", label: "Deceased", type: "bool", sensitive: true },
    { id: "f.comm_optout", label: "Communication opt-out", type: "bool" },
  ]},
];

const Builder = ({ viewAs }) => {
  const [picked, setPicked] = useS(new Set(["v.name", "s.site", "s.program", "s.role", "h.last12mo"]));
  const [filters, setFilters] = useS([
    { id: "f1", field: "h.last12mo", op: ">=", value: "48" },
    { id: "f2", field: "v.status", op: "=", value: "active" },
    { id: "f3", field: "s.region", op: "=", value: "Northeast" },
  ]);
  const [groupBy, setGroupBy] = useS("s.program");
  const [thenBy, setThenBy] = useS("s.site");
  const [dateMode, setDateMode] = useS("cy26");
  const [openGroup, setOpenGroup] = useS({ "Volunteer": true, "Service hours": true, "Site / program / role": true });
  const [previewOpen, setPreviewOpen] = useS(false);
  const [name, setName] = useS("NE region · 48-hr park pass eligible · CY 2026 ytd");

  const togglePick = (id) => {
    const s = new Set(picked); s.has(id) ? s.delete(id) : s.add(id); setPicked(s);
  };

  const fieldById = (id) => {
    for (const g of FIELD_TREE) {
      const f = g.fields.find(x => x.id === id);
      if (f) return f;
    }
    return null;
  };

  return (
    <>
      <div style={{ display: "grid", gridTemplateColumns: "280px minmax(0, 1fr) 320px", gap: 14, alignItems: "start" }}>
        {/* LEFT — field tree */}
        <Card padded={false} style={{ position: "sticky", top: 0, maxHeight: "calc(100vh - 240px)", overflow: "auto" }}>
          <div style={{ padding: "14px 16px 10px", borderBottom: "1px solid var(--border-soft)" }}>
            <div style={{ ...m7_overline, marginBottom: 6 }}>Reportable fields</div>
            <Input placeholder="Search…" />
          </div>
          {FIELD_TREE.map(g => (
            <div key={g.group}>
              <button onClick={() => setOpenGroup({ ...openGroup, [g.group]: !openGroup[g.group] })}
                style={{ display: "flex", justifyContent: "space-between", alignItems: "center", width: "100%", border: "none", background: "var(--paper-deep)", padding: "9px 16px", fontSize: 11, letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--fg-2)", fontWeight: 500, cursor: "pointer", fontFamily: "inherit" }}>
                <span>{g.group}</span>
                <IconChevronD size={12} style={{ transform: openGroup[g.group] ? "rotate(180deg)" : "none", transition: "transform 160ms" }} />
              </button>
              {openGroup[g.group] && g.fields.map(f => {
                const blocked = viewAs === "readonly" && f.sensitive;
                return (
                  <div key={f.id} style={{ display: "flex", padding: "7px 14px", alignItems: "center", gap: 9, opacity: blocked ? 0.4 : 1, cursor: blocked ? "not-allowed" : "pointer" }}
                    onClick={blocked ? null : () => togglePick(f.id)}>
                    <Checkbox checked={picked.has(f.id)} onChange={() => !blocked && togglePick(f.id)} />
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontSize: 12, color: "var(--ink)" }}>{f.label}</div>
                      <div style={{ fontSize: 10, color: "var(--fg-3)", fontFamily: "var(--font-mono)" }}>{f.id} · {f.type}</div>
                    </div>
                    {f.sensitive && <span title="Sensitive" style={{ fontSize: 10, padding: "1px 6px", borderRadius: 4, background: "var(--amber-100)", color: "var(--amber-600)", fontWeight: 500 }}>S</span>}
                  </div>
                );
              })}
            </div>
          ))}
        </Card>

        {/* CENTER — canvas */}
        <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          <Card>
            <div style={{ display: "grid", gridTemplateColumns: "1fr auto", gap: 14, alignItems: "center", marginBottom: 14 }}>
              <Field label="Report name" required>
                <Input value={name} onChange={(e) => setName(e.target.value)} />
              </Field>
              <div style={{ display: "flex", gap: 6, marginTop: 18 }}>
                <Btn kind="ghost" size="sm" icon={IconDownload}>Save</Btn>
                <Btn kind="secondary" size="sm" icon={IconMail}>Share</Btn>
                <Btn size="sm" icon={IconCheck} onClick={() => setPreviewOpen(true)}>Preview & run</Btn>
              </div>
            </div>

            <div style={{ ...m7_overline, marginBottom: 8 }}>Selected columns ({picked.size})</div>
            <div style={{ display: "flex", gap: 6, flexWrap: "wrap", padding: 12, background: "var(--paper-deep)", borderRadius: 10, minHeight: 48 }}>
              {[...picked].map(id => {
                const f = fieldById(id);
                if (!f) return null;
                return (
                  <span key={id} style={{ fontSize: 12, padding: "5px 8px 5px 10px", borderRadius: 999, background: "var(--paper)", border: "1px solid var(--border)", color: "var(--ink)", display: "inline-flex", alignItems: "center", gap: 8 }}>
                    {f.label}
                    <button onClick={() => togglePick(id)} style={{ border: "none", background: "transparent", cursor: "pointer", color: "var(--fg-3)", display: "flex" }}><IconX size={12} /></button>
                  </span>
                );
              })}
              {picked.size === 0 && <span style={{ fontSize: 12, color: "var(--fg-3)" }}>Pick fields from the tree on the left.</span>}
            </div>
          </Card>

          <Card>
            <div style={{ ...m7_overline, marginBottom: 10 }}>Filters · {filters.length}</div>
            <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
              {filters.map((f, i) => {
                const fd = fieldById(f.field);
                return (
                  <div key={f.id} style={{ display: "grid", gridTemplateColumns: "1fr 120px 1fr 36px", gap: 8, alignItems: "center" }}>
                    <Select value={f.field} onChange={(e) => setFilters(filters.map(x => x.id === f.id ? { ...x, field: e.target.value } : x))}
                      options={FIELD_TREE.flatMap(g => g.fields.map(x => ({ value: x.id, label: g.group + " · " + x.label })))} />
                    <Select value={f.op} onChange={(e) => setFilters(filters.map(x => x.id === f.id ? { ...x, op: e.target.value } : x))}
                      options={opsFor(fd?.type)} />
                    <Input value={f.value} onChange={(e) => setFilters(filters.map(x => x.id === f.id ? { ...x, value: e.target.value } : x))} placeholder={fd?.type === "number" ? "48" : "value"} />
                    <IconBtn icon={IconX} size={32} onClick={() => setFilters(filters.filter(x => x.id !== f.id))} aria-label="Remove" />
                  </div>
                );
              })}
              <div style={{ display: "flex", gap: 8 }}>
                <Btn size="sm" kind="ghost" icon={IconPlus}
                  onClick={() => setFilters([...filters, { id: "f" + Math.random().toString(36).slice(2, 6), field: "h.ytd", op: ">=", value: "0" }])}>
                  Add filter
                </Btn>
                <Btn size="sm" kind="ghost">Add saved-segment filter</Btn>
              </div>
            </div>
          </Card>

          <Card>
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
              <Field label="Group by">
                <Select value={groupBy} onChange={(e) => setGroupBy(e.target.value)}
                  options={[{ value: "", label: "—" }, ...FIELD_TREE.flatMap(g => g.fields.map(x => ({ value: x.id, label: g.group + " · " + x.label })))]} />
              </Field>
              <Field label="Then by">
                <Select value={thenBy} onChange={(e) => setThenBy(e.target.value)}
                  options={[{ value: "", label: "—" }, ...FIELD_TREE.flatMap(g => g.fields.map(x => ({ value: x.id, label: g.group + " · " + x.label })))]} />
              </Field>
              <Field label="Date range">
                <Select value={dateMode} onChange={(e) => setDateMode(e.target.value)}
                  options={[
                    { value: "cy26", label: "Calendar year 2026 (current)" },
                    { value: "cy25", label: "Calendar year 2025 (prior)" },
                    { value: "fy26", label: "Fiscal year 2026 (Jul 1 – Jun 30)" },
                    { value: "rolling12", label: "Rolling 12 months" },
                    { value: "rolling6", label: "Rolling 6 months" },
                    { value: "custom", label: "Custom range…" },
                  ]} />
              </Field>
              <Field label="Time zone"><Select defaultValue="America/Denver" options={["America/Denver", "America/New_York", "America/Los_Angeles"]} /></Field>
            </div>
            {dateMode === "custom" && (
              <div style={{ display: "flex", gap: 8, marginTop: 8 }}>
                <Input type="date" defaultValue="2026-01-01" />
                <Input type="date" defaultValue="2026-05-23" />
              </div>
            )}
          </Card>

          <Card>
            <div style={{ ...m7_overline, marginBottom: 10 }}>Output</div>
            <div style={{ display: "grid", gridTemplateColumns: "repeat(2, 1fr)", gap: 12 }}>
              <Checkbox checked={true} onChange={() => {}} label="XLSX (Microsoft Excel)" />
              <Checkbox checked={true} onChange={() => {}} label="CSV" />
              <Checkbox checked={false} onChange={() => {}} label="PDF" />
              <Checkbox checked={false} onChange={() => {}} label="Google Sheets (spreadsheet equivalent)" />
              <Checkbox checked={false} onChange={() => {}} label="HTML (browser view)" />
              <Checkbox checked={false} onChange={() => {}} label="Avery 5160 mailing labels (when address fields present)" />
            </div>
          </Card>
        </div>

        {/* RIGHT — meta + preview */}
        <Card>
          <div style={{ ...m7_overline, marginBottom: 12 }}>Report summary</div>
          <SummRow label="Columns" value={String(picked.size)} />
          <SummRow label="Filters" value={String(filters.length)} />
          <SummRow label="Group by" value={fieldById(groupBy)?.label || "—"} />
          <SummRow label="Then by" value={fieldById(thenBy)?.label || "—"} />
          <SummRow label="Date" value={dateMode === "cy26" ? "CY 2026 ytd" : dateMode === "cy25" ? "CY 2025" : dateMode === "fy26" ? "FY 2026" : dateMode} />
          <SummRow label="Estimated rows" value="~ 28" />

          <div style={{ ...m7_overline, margin: "18px 0 8px" }}>Sensitivity & scope</div>
          <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
            {[...picked].some(id => fieldById(id)?.sensitive)
              ? <Notice tone="warn">Selection includes sensitive fields. Export requires admin role + purpose.</Notice>
              : <Notice tone="info">No sensitive fields selected.</Notice>}
            <Notice>Scoped to your permitted region + sites — others are suppressed without leaking counts.</Notice>
          </div>

          <div style={{ ...m7_overline, margin: "18px 0 8px" }}>Save & share</div>
          <Field label="Folder">
            <Select defaultValue="ne" options={[{ value: "ne", label: "Northeast · my reports" }, { value: "shared", label: "Shared with Regional team" }, { value: "private", label: "Private (just me)" }]} />
          </Field>
          <Field label="Share with">
            <Input placeholder="email or role…" defaultValue="Regional coordinators (NE)" />
          </Field>
          <Field label="Drill-down">
            <Checkbox checked={true} onChange={() => {}} label="Allow row-level drill where permission allows" />
          </Field>
        </Card>
      </div>

      {previewOpen && <BuilderPreview name={name} onClose={() => setPreviewOpen(false)} fields={[...picked].map(fieldById).filter(Boolean)} />}
    </>
  );
};

const SummRow = ({ label, value }) => (
  <div style={{ display: "flex", justifyContent: "space-between", padding: "6px 0", borderTop: "1px dashed var(--border-soft)", fontSize: 12 }}>
    <span style={{ color: "var(--fg-3)" }}>{label}</span>
    <span style={{ color: "var(--ink)", fontWeight: 500 }}>{value}</span>
  </div>
);
const Notice = ({ children, tone = "neutral" }) => {
  const bg = tone === "warn" ? "var(--amber-100)" : tone === "info" ? "var(--iris-100)" : "var(--paper-deep)";
  const fg = tone === "warn" ? "var(--amber-600)" : tone === "info" ? "var(--iris-600)" : "var(--fg-2)";
  return <div style={{ background: bg, color: fg, padding: "8px 10px", borderRadius: 8, fontSize: 11, lineHeight: 1.5 }}>{children}</div>;
};
function opsFor(type) {
  if (type === "number") return [{ value: ">=", label: "≥ at least" }, { value: "<=", label: "≤ at most" }, { value: "=", label: "= equals" }, { value: "between", label: "between" }, { value: "!=", label: "≠ not equal" }];
  if (type === "date") return [{ value: "between", label: "between" }, { value: ">=", label: "on or after" }, { value: "<=", label: "on or before" }, { value: "this_year", label: "this CY" }, { value: "last_year", label: "prior CY" }];
  if (type === "bool") return [{ value: "=", label: "is" }, { value: "!=", label: "is not" }];
  if (type === "list") return [{ value: "contains", label: "contains" }, { value: "any", label: "is any of" }, { value: "none", label: "is none of" }];
  return [{ value: "=", label: "equals" }, { value: "!=", label: "not equals" }, { value: "contains", label: "contains" }, { value: "starts", label: "starts with" }, { value: "blank", label: "is blank" }];
}

const BuilderPreview = ({ name, onClose, fields }) => {
  const rows = VOLUNTEERS.filter(v => v.last12moHours >= 48).slice(0, 8);
  return (
    <div style={overlay} onClick={onClose}>
      <div style={drawer} onClick={(e) => e.stopPropagation()}>
        <div style={drawerHead}>
          <div>
            <div style={{ ...m7_overline }}>Preview · ad-hoc report</div>
            <div style={{ fontSize: 19, fontWeight: 500, color: "var(--ink)", marginTop: 4 }}>{name}</div>
            <div style={{ ...m7_meta, marginTop: 2 }}>Run as Priya Sandoval · {new Date().toLocaleString()} · definition v3 · scoped to NE</div>
          </div>
          <IconBtn icon={IconX} size={32} onClick={onClose} aria-label="Close" />
        </div>
        <div style={{ flex: 1, overflow: "auto", padding: 20 }}>
          <Card padded={false}>
            <div style={{ display: "grid", gridTemplateColumns: fields.map(() => "minmax(120px, 1fr)").join(" "), gap: 14, padding: "12px 16px", fontSize: 11, letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--fg-3)", borderBottom: "1px solid var(--border)" }}>
              {fields.map(f => <span key={f.id}>{f.label}</span>)}
            </div>
            {rows.map((v, i) => (
              <div key={v.id} style={{ display: "grid", gridTemplateColumns: fields.map(() => "minmax(120px, 1fr)").join(" "), gap: 14, padding: "12px 16px", alignItems: "center", borderBottom: i === rows.length - 1 ? "none" : "1px solid var(--border-soft)", fontSize: 13 }}>
                {fields.map(f => <span key={f.id} style={{ fontVariantNumeric: "tabular-nums" }}>{valueFor(v, f)}</span>)}
              </div>
            ))}
          </Card>
          <div style={{ marginTop: 14, padding: 12, background: "var(--paper-soft)", borderRadius: 10, border: "1px solid var(--border-soft)", fontSize: 12, color: "var(--fg-2)", lineHeight: 1.5 }}>
            Showing 8 of ~28 rows. Per-row click would drill into the volunteer record if you have view permission. 14 rows are suppressed because they're outside your region — counts shown without identifying details.
          </div>
        </div>
        <div style={drawerFoot}>
          <span style={{ fontSize: 11, color: "var(--fg-3)", marginRight: "auto" }}>This run will be logged in the export & report-access log.</span>
          <Btn kind="secondary" icon={IconDownload}>CSV</Btn>
          <Btn kind="secondary" icon={IconDownload}>XLSX</Btn>
          <Btn icon={IconCheck} onClick={onClose}>Done</Btn>
        </div>
      </div>
    </div>
  );
};
function valueFor(v, f) {
  if (f.id === "v.name") return v.name;
  if (f.id === "s.site") return v.site;
  if (f.id === "s.program") return v.program;
  if (f.id === "s.role") return v.role;
  if (f.id === "h.last12mo") return v.last12moHours;
  if (f.id === "h.ytd") return v.ytdHours;
  if (f.id === "h.lifetime") return v.lifetimeHours;
  if (f.id === "v.status") return v.status;
  if (f.id === "v.joined") return v.joined;
  return "—";
}

const overlay = { position: "fixed", inset: 0, background: "rgba(31,27,22,0.45)", backdropFilter: "blur(4px)", zIndex: 80, display: "flex", justifyContent: "flex-end" };
const drawer = { width: "min(1080px, 100%)", height: "100%", background: "var(--paper)", display: "flex", flexDirection: "column", boxShadow: "var(--shadow-lg)" };
const drawerHead = { padding: "20px 24px 16px", display: "flex", justifyContent: "space-between", alignItems: "start", gap: 14, borderBottom: "1px solid var(--border-soft)" };
const drawerFoot = { padding: "14px 24px", borderTop: "1px solid var(--border-soft)", display: "flex", alignItems: "center", gap: 8, background: "var(--paper-soft)" };

// ============================================================
// SAVED & SHARED
// ============================================================
const Saved = ({ viewAs }) => {
  const items = [
    { name: "NE region · quarterly service rollup", folder: "Northeast · my reports", by: "Priya Sandoval", lastRun: "Today, 7:32 am", shared: 4, rows: 1284 },
    { name: "Camp hosts · retention curve", folder: "Shared with Regional team", by: "Marcus Chen", lastRun: "Yesterday", shared: 6, rows: 38 },
    { name: "Cherry Creek SP · service value", folder: "Shared with Regional team", by: "Priya Sandoval", lastRun: "3 days ago", shared: 12, rows: 96 },
    { name: "All hands · compliance rollup", folder: "Universal admins only", by: "Marcus Chen", lastRun: "May 1", shared: 4, rows: 624 },
    { name: "Hunter Outreach · grant-ready", folder: "Hunter ed coordinators", by: "Aliyah Chen", lastRun: "May 19", shared: 3, rows: 86 },
    { name: "Boyd Lake camp host roster", folder: "Park managers", by: "Devon Park", lastRun: "Today, 8:42 am", shared: 5, rows: 18 },
    { name: "Audit-ready hours · April 2026", folder: "Shared with Regional team", by: "Priya Sandoval", lastRun: "May 5", shared: 2, rows: 142, audit: true },
  ];
  return (
    <>
      <div style={{ display: "flex", gap: 8, marginBottom: 12 }}>
        <Btn kind="secondary" size="sm" icon={IconPlus}>New folder</Btn>
        <div style={{ marginLeft: "auto", display: "flex", gap: 8 }}>
          <Btn kind="ghost" size="sm" icon={IconFilter}>Filter</Btn>
          <Btn kind="ghost" size="sm">Sort: recent</Btn>
        </div>
      </div>
      <Card padded={false}>
        <div style={{ display: "grid", gridTemplateColumns: "minmax(240px, 1.8fr) minmax(160px, 1fr) minmax(140px, 1fr) 100px 100px 36px", gap: 14, padding: "12px 18px", fontSize: 11, letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--fg-3)", borderBottom: "1px solid var(--border)" }}>
          <span>Report</span><span>Folder</span><span>Last run</span><span>Shared</span><span>Rows</span><span />
        </div>
        {items.map((r, i) => (
          <div key={i} style={{ display: "grid", gridTemplateColumns: "minmax(240px, 1.8fr) minmax(160px, 1fr) minmax(140px, 1fr) 100px 100px 36px", gap: 14, padding: "14px 18px", alignItems: "center", borderBottom: i === items.length - 1 ? "none" : "1px solid var(--border-soft)" }}>
            <div>
              <div style={{ fontSize: 13, fontWeight: 500, color: "var(--ink)", display: "flex", gap: 8, alignItems: "center" }}>
                {r.name}
                {r.audit && <span style={{ fontSize: 10, padding: "1px 6px", borderRadius: 4, background: "var(--iris-100)", color: "var(--iris-600)", fontWeight: 500 }}>Audit-grade</span>}
              </div>
              <div style={{ ...m7_meta, marginTop: 2 }}>by {r.by}</div>
            </div>
            <div style={{ fontSize: 12, color: "var(--fg-2)" }}>{r.folder}</div>
            <div style={{ fontSize: 12, color: "var(--fg-2)" }}>{r.lastRun}</div>
            <div style={{ fontSize: 12, color: "var(--fg-2)" }}>{r.shared} people</div>
            <div style={{ fontSize: 13, fontVariantNumeric: "tabular-nums", color: "var(--ink)" }}>{r.rows.toLocaleString()}</div>
            <IconBtn icon={IconMore} size={28} />
          </div>
        ))}
      </Card>
    </>
  );
};

// ============================================================
// SCHEDULED (FR8)
// ============================================================
const SCHEDULED_JOBS = [
  { name: "Monthly service-value summary", to: "regional-coordinators@cpw.state.co.us", cadence: "1st of every month, 9:00 am MT", format: "XLSX + PDF", next: "Jun 1, 9:00 am", last: "May 1, success", state: "on" },
  { name: "Weekly application digest", to: "priya.s@cpw.state.co.us", cadence: "Mondays, 8:00 am MT", format: "PDF", next: "Mon, 8:00 am", last: "Mon, success", state: "on" },
  { name: "Quarterly compliance audit", to: "compliance@cpw.state.co.us", cadence: "Last day of quarter, 5:00 pm MT", format: "PDF + audit log CSV", next: "Jun 30, 5:00 pm", last: "Mar 31, success", state: "on" },
  { name: "Hunter Outreach federal report", to: "/sftp/grants/hunter-outreach/", cadence: "Monthly, 1st by 4:00 am MT", format: "XLSX", next: "Jun 1, 4:00 am", last: "May 1, success", state: "on", sftp: true },
  { name: "Camp host roster (NE)", to: "ne-parks@cpw.state.co.us", cadence: "Weekly, Fri 5:00 pm", format: "PDF", next: "Fri, 5:00 pm", last: "Fri, FAILED — recipient permission revoked", state: "fail" },
];

const Scheduled = () => (
  <>
    <div style={{ display: "flex", gap: 8, marginBottom: 12 }}>
      <Btn kind="secondary" size="sm" icon={IconPlus}>New schedule</Btn>
      <div style={{ marginLeft: "auto", display: "flex", gap: 8 }}>
        <Btn kind="ghost" size="sm">Last 30 days</Btn>
        <Btn kind="ghost" size="sm" icon={IconDownload}>Delivery log</Btn>
      </div>
    </div>
    <Card padded={false}>
      <div style={{ display: "grid", gridTemplateColumns: "minmax(220px, 1.4fr) minmax(180px, 1fr) minmax(180px, 1fr) 140px 140px 100px 36px", gap: 12, padding: "12px 18px", fontSize: 11, letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--fg-3)", borderBottom: "1px solid var(--border)" }}>
        <span>Schedule</span><span>To</span><span>Cadence</span><span>Format</span><span>Next run</span><span>State</span><span />
      </div>
      {SCHEDULED_JOBS.map((j, i) => (
        <div key={i} style={{ display: "grid", gridTemplateColumns: "minmax(220px, 1.4fr) minmax(180px, 1fr) minmax(180px, 1fr) 140px 140px 100px 36px", gap: 12, padding: "14px 18px", alignItems: "center", borderBottom: i === SCHEDULED_JOBS.length - 1 ? "none" : "1px solid var(--border-soft)" }}>
          <div>
            <div style={{ fontSize: 13, fontWeight: 500 }}>{j.name}</div>
            <div style={{ ...m7_meta, marginTop: 2 }}>Last: {j.last}</div>
          </div>
          <div style={{ fontSize: 12, color: "var(--fg-2)", display: "flex", gap: 6, alignItems: "center", minWidth: 0 }}>
            {j.sftp ? <span style={{ fontSize: 10, padding: "1px 6px", borderRadius: 4, background: "var(--iris-100)", color: "var(--iris-600)", fontWeight: 500, flexShrink: 0 }}>SFTP</span> : <IconMail size={13} style={{ color: "var(--fg-3)", flexShrink: 0 }} />}
            <span style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{j.to}</span>
          </div>
          <div style={{ fontSize: 12, color: "var(--fg-2)" }}>{j.cadence}</div>
          <div style={{ fontSize: 12 }}>{j.format}</div>
          <div style={{ fontSize: 12, color: "var(--fg-2)" }}>{j.next}</div>
          <StatusChip status={j.state === "fail" ? "expired" : "confirmed"} size="sm" label={j.state === "fail" ? "Failed" : "On"} />
          <IconBtn icon={IconMore} size={28} />
        </div>
      ))}
    </Card>

    <div style={{ marginTop: 18, display: "grid", gridTemplateColumns: "minmax(0, 1.4fr) minmax(280px, 1fr)", gap: 14 }}>
      <Card>
        <div style={{ ...m7_overline, marginBottom: 12 }}>Delivery health (last 30 days)</div>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 14, marginBottom: 18 }}>
          <Kpi label="Runs" value="84" delta="across 5 schedules" tone="neutral" icon={IconClock} />
          <Kpi label="Success" value="82" delta="98%" tone="up" icon={IconCheck} />
          <Kpi label="Failed" value="2" delta="recipient perms · 1 retrying" tone="down" icon={IconX} />
          <Kpi label="Avg delivery time" value="4.2s" delta="+0.2 vs last 30d" tone="neutral" icon={IconClock} />
        </div>
        <div style={{ ...m7_overline, marginBottom: 8 }}>Recent runs</div>
        {[
          { name: "Monthly service-value summary", when: "May 1, 9:00:04 am MT", res: "Success · 1,284 rows · 2.1 MB", state: "ok" },
          { name: "Camp host roster (NE)",         when: "May 17, 5:00:11 pm MT", res: "FAILED · recipient j.spencer@… lost reports.view permission", state: "fail" },
          { name: "Hunter Outreach federal",       when: "May 1, 4:00:01 am MT", res: "Success · 86 rows · uploaded to /sftp/grants/hunter-outreach/2026-05/", state: "ok" },
          { name: "Weekly application digest",     when: "May 19, 8:00:00 am MT", res: "Success · 11 applications", state: "ok" },
        ].map((l, i, arr) => (
          <div key={i} style={{ display: "grid", gridTemplateColumns: "minmax(0, 1fr) 180px minmax(0, 1.4fr) 90px", gap: 12, padding: "11px 0", alignItems: "center", borderTop: i === 0 ? "1px solid var(--border-soft)" : "1px solid var(--border-soft)", fontSize: 12 }}>
            <span style={{ color: "var(--ink)" }}>{l.name}</span>
            <span style={{ color: "var(--fg-3)" }}>{l.when}</span>
            <span style={{ color: l.state === "fail" ? "var(--crimson-600)" : "var(--fg-2)", lineHeight: 1.4 }}>{l.res}</span>
            <StatusChip status={l.state === "fail" ? "expired" : "confirmed"} size="sm" label={l.state === "fail" ? "Fail" : "OK"} />
          </div>
        ))}
      </Card>
      <Card>
        <div style={{ ...m7_overline, marginBottom: 12 }}>Permission re-check</div>
        <p style={{ fontSize: 12, color: "var(--fg-2)", lineHeight: 1.5 }}>
          Every scheduled run rechecks the report owner's permission and each recipient's access scope <em>at run time</em>. If a recipient loses access between runs, delivery is blocked for that recipient and the failure is surfaced here — never silently dropped.
        </p>
        <div style={{ marginTop: 16, padding: 12, background: "var(--paper-deep)", borderRadius: 10 }}>
          <div style={{ ...m7_overline, marginBottom: 6 }}>Retry policy</div>
          <div style={{ fontSize: 12, color: "var(--fg-1)", lineHeight: 1.5 }}>3 retries with exponential backoff (1m / 5m / 30m). Then surfaced for manual intervention. Email-channel failures retry; SFTP failures alert ops.</div>
        </div>
      </Card>
    </div>
  </>
);

// ============================================================
// GRANT (FR6 Hunter Outreach)
// ============================================================
const Grant = () => (
  <>
    <p style={{ fontSize: 13, color: "var(--fg-2)", marginBottom: 18, maxWidth: 720 }}>
      Federal, state, and funder grant reporting. CPW launch ships with the Hunter Outreach pack; the underlying framework is configurable for additional funders without code changes.
    </p>
    <Card style={{ marginBottom: 14 }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "start", marginBottom: 12 }}>
        <div>
          <div style={{ ...m7_overline, marginBottom: 6 }}>Federal grant · CFDA 15.252</div>
          <div style={{ fontSize: 17, fontWeight: 500, color: "var(--ink)" }}>Hunter Outreach</div>
          <div style={{ fontSize: 12, color: "var(--fg-2)", marginTop: 4 }}>Pittman–Robertson reporting · activity-typed volunteer hours · monthly cadence to /sftp/grants/hunter-outreach/</div>
        </div>
        <StatusChip status="active" size="sm" label="On schedule" />
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 14, marginBottom: 18 }}>
        <Kpi label="Hours this month" value="86.0" delta="↑ 12 vs Apr" tone="up" icon={IconClock} />
        <Kpi label="Volunteers active" value="14" delta="across 4 events" tone="neutral" icon={IconUsers} />
        <Kpi label="Audit-signed hours" value="100%" delta="all reviewed" tone="up" icon={IconCheck} />
        <Kpi label="Next report due" value="Jun 1" delta="auto-delivered 4:00 am" tone="neutral" icon={IconCal} />
      </div>
      <div style={{ ...m7_overline, marginBottom: 8 }}>Activity taxonomy (Hunter Outreach)</div>
      <div style={{ display: "flex", gap: 6, flexWrap: "wrap" }}>
        {["Youth class instruction", "Adult class instruction", "Range supervision", "Field day", "Curriculum development", "Travel to remote class"]
          .map(c => <span key={c} style={{ fontSize: 11, padding: "4px 10px", borderRadius: 999, background: "var(--paper-deep)", color: "var(--fg-1)" }}>{c}</span>)}
      </div>
    </Card>

    <SectionHead title="Recent event-level evidence" />
    <Card padded={false}>
      <div style={{ display: "grid", gridTemplateColumns: "minmax(220px, 1.6fr) minmax(160px, 1fr) minmax(160px, 1fr) 110px 130px 100px", gap: 12, padding: "12px 16px", fontSize: 11, letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--fg-3)", borderBottom: "1px solid var(--border)" }}>
        <span>Event</span><span>Activity</span><span>Location</span><span>Date</span><span>Start / end</span><span>Hours</span>
      </div>
      {[
        { event: "Hunter ed — youth class · Boulder",  activity: "Youth class instruction", loc: "Boulder field office", date: "May 17, 2026", t: "9:00 – 16:00", hrs: 24.0, vols: 4, signed: true },
        { event: "Hunter ed — adult class · Greeley", activity: "Adult class instruction", loc: "Greeley field office", date: "May 10, 2026", t: "8:30 – 16:30", hrs: 24.0, vols: 3, signed: true },
        { event: "Hunter ed — youth field day", activity: "Field day",            loc: "Pawnee NG range", date: "May 4, 2026",  t: "7:30 – 14:00", hrs: 19.5, vols: 4, signed: true },
        { event: "Hunter ed — adult class · Boulder", activity: "Range supervision", loc: "Boulder rifle range", date: "Apr 27, 2026", t: "8:00 – 14:30", hrs: 18.5, vols: 3, signed: true },
      ].map((e, i, arr) => (
        <div key={i} style={{ display: "grid", gridTemplateColumns: "minmax(220px, 1.6fr) minmax(160px, 1fr) minmax(160px, 1fr) 110px 130px 100px", gap: 12, padding: "13px 16px", alignItems: "center", borderBottom: i === arr.length - 1 ? "none" : "1px solid var(--border-soft)" }}>
          <div>
            <div style={{ fontSize: 13, fontWeight: 500 }}>{e.event}</div>
            <div style={{ ...m7_meta, marginTop: 2, display: "flex", gap: 8, alignItems: "center" }}>
              {e.vols} volunteers · {e.signed ? <StatusChip status="confirmed" size="sm" label="Audit-signed" /> : <StatusChip status="pending" size="sm" label="Pending audit" />}
            </div>
          </div>
          <div style={{ fontSize: 12 }}>{e.activity}</div>
          <div style={{ fontSize: 12, color: "var(--fg-2)" }}>{e.loc}</div>
          <div style={{ fontSize: 12, color: "var(--fg-2)" }}>{e.date}</div>
          <code style={{ fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--fg-2)" }}>{e.t}</code>
          <div style={{ fontFamily: "var(--font-display)", fontSize: 18, color: "var(--ink)", fontVariantNumeric: "tabular-nums" }}>{e.hrs}</div>
        </div>
      ))}
    </Card>

    <div style={{ marginTop: 18, display: "grid", gridTemplateColumns: "repeat(2, 1fr)", gap: 14 }}>
      <Card>
        <div style={{ ...m7_overline, marginBottom: 10 }}>Report run options</div>
        <Field label="Date range">
          <Select defaultValue="cm" options={[{ value: "cm", label: "Current month" }, { value: "lm", label: "Last month" }, { value: "q", label: "Current quarter" }, { value: "fy", label: "FY 2026" }, { value: "custom", label: "Custom range…" }]} />
        </Field>
        <Field label="Approval state">
          <Select defaultValue="audited" options={[{ value: "approved", label: "Approved hours only" }, { value: "audited", label: "Staff-audited only (grant default)" }, { value: "all", label: "Include pending (annotated)" }]} />
        </Field>
        <Field label="Output">
          <div style={{ display: "flex", gap: 12 }}>
            <Checkbox checked={true} onChange={() => {}} label="XLSX" />
            <Checkbox checked={false} onChange={() => {}} label="PDF summary" />
            <Checkbox checked={false} onChange={() => {}} label="CSV (raw)" />
          </div>
        </Field>
        <div style={{ display: "flex", gap: 6, justifyContent: "flex-end" }}>
          <Btn size="sm" kind="secondary">Preview</Btn>
          <Btn size="sm" icon={IconDownload}>Run</Btn>
        </div>
      </Card>
      <Card>
        <div style={{ ...m7_overline, marginBottom: 10 }}>Corrections log</div>
        <p style={{ fontSize: 12, color: "var(--fg-2)", lineHeight: 1.5, marginBottom: 12 }}>
          Corrections to grant hours preserve the original entry and the reviewer's audit signature. The federal report attaches a corrections appendix when prior periods change.
        </p>
        {[
          { who: "Marcus Chen", what: "Audit-signed 6.0 hrs", v: "Maya Okonkwo · Apr 27 adult class", when: "May 4, 11:14 am" },
          { who: "Priya Sandoval", what: "Corrected 9.5 → 9.0 hrs", v: "Maya Okonkwo · Apr 12 youth class", when: "Apr 18 · original preserved" },
          { who: "System", what: "Recalc rolling totals", v: "after hour correction (Apr 18)", when: "Apr 18, 11:14 am" },
        ].map((l, i, arr) => (
          <div key={i} style={{ display: "grid", gridTemplateColumns: "120px 1fr 130px", gap: 10, padding: "10px 0", borderTop: "1px solid var(--border-soft)", fontSize: 12 }}>
            <div style={{ color: "var(--ink)", fontWeight: 500 }}>{l.who}</div>
            <div><div style={{ color: "var(--fg-1)" }}>{l.what}</div><div style={{ ...m7_meta, marginTop: 2 }}>{l.v}</div></div>
            <div style={{ ...m7_meta, textAlign: "right" }}>{l.when}</div>
          </div>
        ))}
      </Card>
    </div>
  </>
);

// ============================================================
// AUDIT EVIDENCE (FR10)
// ============================================================
const AuditEvidence = () => (
  <>
    <p style={{ fontSize: 13, color: "var(--fg-2)", marginBottom: 18, maxWidth: 720 }}>
      Audit, access, configuration, authentication, export, and availability evidence. Logs are immutable and searchable; exports are themselves logged.
    </p>
    <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 14, marginBottom: 22 }}>
      <Kpi label="Audit entries (90d)" value="18,420" delta="+312 vs prior 90" tone="neutral" icon={IconShield} />
      <Kpi label="Export actions (90d)" value="1,248" delta="all logged" tone="neutral" icon={IconDownload} />
      <Kpi label="Failed sign-ins (30d)" value="38" delta="2 locked" tone="down" icon={IconX} />
      <Kpi label="Availability (90d)" value="99.97%" delta="2 incidents" tone="up" icon={IconCheck} />
    </div>

    <SectionHead title="Evidence packs" />
    <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 12, marginBottom: 22 }}>
      {[
        { t: "Access review", d: "Who has what role, when granted, last login, MFA status." },
        { t: "Configuration changes", d: "Settings + program rule history with actor, prior/new values." },
        { t: "Authentication events", d: "Sign-ins, MFA challenges, password resets, SSO assertions." },
        { t: "Export & report-access log", d: "Every export and report run by actor with filters, row count, definition version." },
        { t: "Bulk action audit", d: "Bulk award issuance, bulk hour approvals, bulk merges, bulk reactivations." },
        { t: "Availability + incident", d: "SaaS ops telemetry: uptime, incident notices, maintenance windows." },
      ].map(e => (
        <Card key={e.t}>
          <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 8 }}>
            <div style={{ fontSize: 14, fontWeight: 500, color: "var(--ink)" }}>{e.t}</div>
            <span style={{ fontSize: 10, padding: "2px 7px", borderRadius: 999, background: "var(--iris-100)", color: "var(--iris-600)", fontWeight: 500 }}>Immutable</span>
          </div>
          <div style={{ fontSize: 12, color: "var(--fg-2)", lineHeight: 1.5, marginBottom: 14 }}>{e.d}</div>
          <div style={{ display: "flex", gap: 6 }}>
            <Btn size="sm" kind="ghost">Open</Btn>
            <Btn size="sm" kind="secondary" icon={IconDownload}>Export</Btn>
          </div>
        </Card>
      ))}
    </div>

    <SectionHead title="Live audit feed" />
    <Card padded={false}>
      {[
        { who: "Priya Sandoval", what: "Bulk-issued 12 awards · 10-hr annual", ref: "bulk-issue-2026-05-23-3kf8", when: "Today · 9:14 am", ip: "10.21.4.88" },
        { who: "Priya Sandoval", what: "Ran report 'NE region · quarterly service rollup'", ref: "rpt-run-7c2", when: "Today · 7:32 am", ip: "10.21.4.88" },
        { who: "System", what: "Recalculated park-pass eligibility (nightly)", ref: "sys-recalc-2026-05-23", when: "Today · 6:02 am", ip: "—" },
        { who: "Marcus Chen", what: "Corrected hours · Ben Liu · 32 → 28 hr", ref: "hr-corr-bli-2d1", when: "Yest · 4:42 pm", ip: "10.21.4.61" },
        { who: "Aliyah Chen", what: "Exported Hunter Outreach grant report (XLSX)", ref: "exp-ho-2026-05-1f", when: "Yest · 4:00 am (scheduled)", ip: "10.21.4.13" },
        { who: "j.spencer@cpw…", what: "Failed sign-in · MFA denied", ref: "auth-fail-2d", when: "Mon · 11:02 am", ip: "73.14.66.21" },
      ].map((l, i, arr) => (
        <div key={i} style={{ display: "grid", gridTemplateColumns: "180px minmax(0, 2fr) 200px 160px 110px", gap: 12, padding: "13px 18px", alignItems: "center", borderBottom: i === arr.length - 1 ? "none" : "1px solid var(--border-soft)", fontSize: 13 }}>
          <div style={{ fontWeight: 500 }}>{l.who}</div>
          <div style={{ color: "var(--fg-1)" }}>{l.what}</div>
          <code style={{ fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--fg-3)" }}>{l.ref}</code>
          <div style={{ ...m7_meta }}>{l.when}</div>
          <code style={{ fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--fg-3)" }}>{l.ip}</code>
        </div>
      ))}
    </Card>
  </>
);

// ============================================================
// TENANT ARCHIVE / DATA PORTABILITY (FR9)
// ============================================================
const Portability = () => (
  <>
    <p style={{ fontSize: 13, color: "var(--fg-2)", marginBottom: 18, maxWidth: 720 }}>
      Tenant data portability. Every export bundle includes schema version, data dictionary, attachment metadata, native files, transformation context, and an integrity manifest. Exports are scoped to your role.
    </p>

    <div style={{ display: "grid", gridTemplateColumns: "minmax(0, 1.4fr) minmax(280px, 1fr)", gap: 14, marginBottom: 22 }}>
      <Card>
        <div style={{ ...m7_overline, marginBottom: 12 }}>Build an archive</div>
        <Field label="Entities to include">
          <div style={{ display: "grid", gridTemplateColumns: "repeat(2, 1fr)", gap: 8 }}>
            {["Volunteers", "Opportunities & shifts", "Participations & attendance", "Hours (incl. corrections)", "Recognition & award issuance", "Sites / programs / roles", "Groups", "Files & attachments", "Audit log", "Report definitions", "Survey definitions & responses", "Communications history"].map(e => (
              <Checkbox key={e} checked={true} onChange={() => {}} label={e} />
            ))}
          </div>
        </Field>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 12 }}>
          <Field label="Format"><Select defaultValue="ndjson+csv" options={[{ value: "ndjson+csv", label: "NDJSON + CSV companions" }, { value: "parquet", label: "Parquet (machine-readable)" }, { value: "json", label: "JSON only" }]} /></Field>
          <Field label="Attachments"><Select defaultValue="native" options={[{ value: "native", label: "Native files (in archive)" }, { value: "links", label: "Signed-URL links only" }, { value: "none", label: "Exclude" }]} /></Field>
          <Field label="Encryption"><Select defaultValue="age" options={["AES-256 password", "age (recipient key)", "None — internal only"]} /></Field>
        </div>
        <Field label="Date scope">
          <Select defaultValue="all" options={[{ value: "all", label: "All time" }, { value: "fy", label: "Current fiscal year" }, { value: "custom", label: "Custom…" }]} />
        </Field>
        <div style={{ display: "flex", gap: 6, justifyContent: "flex-end" }}>
          <Btn kind="secondary" size="sm">Schedule monthly</Btn>
          <Btn size="sm" icon={IconDownload}>Build archive</Btn>
        </div>
      </Card>
      <Card>
        <div style={{ ...m7_overline, marginBottom: 12 }}>Manifest contents</div>
        <ul style={{ margin: 0, paddingLeft: 18, fontSize: 13, color: "var(--fg-1)", lineHeight: 1.7 }}>
          <li>Schema version + dictionary (field meanings, types, enums)</li>
          <li>Source-system mappings (Better Impact, VolunteerLocal where present)</li>
          <li>Transformation context (dedupe, merges, migrations)</li>
          <li>Attachment metadata + native files</li>
          <li>Export manifest: time, actor, tenant, entities, row counts, SHA-256 checksums</li>
          <li>Reproducibility README</li>
        </ul>
        <div style={{ marginTop: 14, padding: 12, background: "var(--paper-deep)", borderRadius: 10, fontSize: 12, color: "var(--fg-2)", lineHeight: 1.5 }}>
          Includes everything required for a recipient to interpret the data outside the application — no Crew access needed.
        </div>
      </Card>
    </div>

    <SectionHead title="Recent archives" />
    <Card padded={false}>
      <div style={{ display: "grid", gridTemplateColumns: "minmax(220px, 1.6fr) minmax(120px, 1fr) 140px 140px 110px 100px 36px", gap: 12, padding: "12px 16px", fontSize: 11, letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--fg-3)", borderBottom: "1px solid var(--border)" }}>
        <span>Archive</span><span>Format</span><span>Size</span><span>Built</span><span>Entities</span><span>State</span><span />
      </div>
      {[
        { name: "cpw_archive_2026-05-23_full",         fmt: "NDJSON+CSV", size: "4.21 GB", built: "Today · 9:30 am", ents: "12 / 12", state: "ok" },
        { name: "cpw_archive_2026-05-01_monthly",      fmt: "Parquet",    size: "3.84 GB", built: "May 1, 4:01 am", ents: "12 / 12", state: "ok" },
        { name: "cpw_archive_2026-04-01_monthly",      fmt: "Parquet",    size: "3.66 GB", built: "Apr 1, 4:00 am", ents: "12 / 12", state: "ok" },
        { name: "cpw_migration_reconcile_2026-05-15",  fmt: "NDJSON+CSV", size: "2.14 GB", built: "May 15 · pre-launch dry run", ents: "Vols/Hours/Awards", state: "verify" },
      ].map((a, i, arr) => (
        <div key={i} style={{ display: "grid", gridTemplateColumns: "minmax(220px, 1.6fr) minmax(120px, 1fr) 140px 140px 110px 100px 36px", gap: 12, padding: "13px 16px", alignItems: "center", borderBottom: i === arr.length - 1 ? "none" : "1px solid var(--border-soft)" }}>
          <div>
            <div style={{ fontSize: 13, fontWeight: 500, fontFamily: "var(--font-mono)" }}>{a.name}</div>
            <div style={{ ...m7_meta, marginTop: 2 }}>SHA-256 checksum verified · age-encrypted</div>
          </div>
          <div style={{ fontSize: 12 }}>{a.fmt}</div>
          <div style={{ fontSize: 12, fontVariantNumeric: "tabular-nums" }}>{a.size}</div>
          <div style={{ ...m7_meta }}>{a.built}</div>
          <div style={{ fontSize: 12, color: "var(--fg-2)" }}>{a.ents}</div>
          <StatusChip status={a.state === "verify" ? "pending" : "confirmed"} size="sm" label={a.state === "verify" ? "Reconcile" : "Ready"} />
          <IconBtn icon={IconMore} size={28} />
        </div>
      ))}
    </Card>

    <div style={{ marginTop: 22 }}>
      <SectionHead title="Migration reconciliation · launch gate" />
      <Card>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "start", marginBottom: 12 }}>
          <div>
            <div style={{ ...m7_overline, marginBottom: 4 }}>Pre-launch dry run · May 15, 2026</div>
            <div style={{ fontSize: 16, fontWeight: 500 }}>3 of 6 entities reconcile clean</div>
            <div style={{ fontSize: 12, color: "var(--fg-2)", marginTop: 4 }}>Variances by entity → assign and resolve or accept before go-live</div>
          </div>
          <Btn kind="secondary" size="sm" icon={IconExternal}>Open reconciliation worksheet</Btn>
        </div>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(6, 1fr)", gap: 12 }}>
          {[
            { e: "Volunteers", src: 4127, dest: 4127, var: 0, state: "ok" },
            { e: "Hours", src: 184204, dest: 184204, var: 0, state: "ok" },
            { e: "Awards", src: 412, dest: 408, var: -4, state: "investigate" },
            { e: "Sites/programs", src: 84, dest: 84, var: 0, state: "ok" },
            { e: "Groups", src: 38, dest: 36, var: -2, state: "investigate" },
            { e: "Attachments", src: 12882, dest: 12876, var: -6, state: "accepted" },
          ].map(r => (
            <div key={r.e} style={{ padding: 12, background: "var(--paper)", border: "1px solid var(--border-soft)", borderRadius: 10 }}>
              <div style={{ ...m7_overline, marginBottom: 4 }}>{r.e}</div>
              <div style={{ fontFamily: "var(--font-display)", fontSize: 22, color: "var(--ink)", lineHeight: 1.2, fontVariantNumeric: "tabular-nums" }}>{r.dest.toLocaleString()}</div>
              <div style={{ ...m7_meta, marginTop: 4, marginBottom: 6 }}>src {r.src.toLocaleString()} · Δ {r.var === 0 ? "0" : r.var}</div>
              <StatusChip status={r.state === "ok" ? "confirmed" : r.state === "accepted" ? "info" : "pending"} size="sm" label={r.state === "ok" ? "Clean" : r.state === "accepted" ? "Accepted Δ" : "Investigate"} />
            </div>
          ))}
        </div>
      </Card>
    </div>
  </>
);

// ============================================================
Object.assign(window, { OrgReports });
