// ===== add-volunteer.jsx =====
// Staff Add Volunteer flow.
// Two entry modes:
//   1. Single volunteer — multi-step modal: Identity → Contact → Role/Site → Screening → Review
//   2. Bulk import — CSV upload + dedupe + invite
// Plus a third quick mode: walk-up kiosk-style add (used for day-of event registration).
//
// Exposes window.AddVolunteerFlow as a single component, controlled by an `open` prop
// and an `onClose` callback. The page that uses it owns the open state.

const {
  React,
  Card, Btn, IconBtn, StatusChip, Avatar, Kpi, Field, Input, Textarea, Select, Checkbox, Toggle,
  IconPlus, IconCheck, IconX, IconArrow, IconArrowL, IconUpload, IconDownload,
  IconUsers, IconShield, IconMail, IconClipboard, IconClock, IconBook, IconAward, IconSearch,
  IconChevron, IconChevronD, IconEdit, IconExternal, IconSwitch,
  VOLUNTEERS,
} = window;
const { useState: useAV, useMemo: useAVM, useEffect: useAVE } = React;

const av_over = { fontSize: 11, letterSpacing: "0.12em", textTransform: "uppercase", color: "var(--fg-3)", fontWeight: 500 };
const av_meta = { fontSize: 11, color: "var(--fg-3)" };

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

// ============================================================
// ROOT
// ============================================================
const AddVolunteerFlow = ({ open, onClose, initialMode }) => {
  const [mode, setMode] = useAV(initialMode || null); // null | "single" | "bulk" | "walkup"
  if (!open) return null;

  return (
    <div style={av_overlay} onClick={onClose}>
      <div style={av_drawer} onClick={(e) => e.stopPropagation()}>
        {mode === null && <ModePicker onPick={setMode} onClose={onClose} />}
        {mode === "single" && <SingleVolunteer onBack={() => setMode(null)} onClose={onClose} />}
        {mode === "bulk"   && <BulkImport     onBack={() => setMode(null)} onClose={onClose} />}
        {mode === "walkup" && <WalkUp         onBack={() => setMode(null)} onClose={onClose} />}
      </div>
    </div>
  );
};

// ============================================================
// MODE PICKER
// ============================================================
const ModePicker = ({ onPick, onClose }) => (
  <>
    <div style={av_head}>
      <div>
        <div style={av_over}>Add a volunteer</div>
        <div style={{ fontSize: 19, fontWeight: 500, color: "var(--ink)", marginTop: 4 }}>How are you bringing them in?</div>
        <div style={{ fontSize: 12, color: "var(--fg-2)", marginTop: 4, maxWidth: 540 }}>Pick the mode that matches the situation. All paths run the same dedupe and consent checks.</div>
      </div>
      <IconBtn icon={IconX} size={32} onClick={onClose} aria-label="Close" />
    </div>
    <div style={{ flex: 1, overflow: "auto", padding: 24 }}>
      <div style={{ display: "grid", gap: 12 }}>
        <ModeCard
          icon={IconPlus} title="Add one volunteer"
          desc="Manual entry. You'll fill in identity, contact, role + site, and screening status, then the system invites them to claim the account."
          badge="Most common · 4 min" onClick={() => onPick("single")} />
        <ModeCard
          icon={IconUpload} title="Bulk import from CSV"
          desc="Upload a roster file from another system. Dry-run mapping, dedupe, and invite-batching before anything commits."
          badge="Up to 5,000 rows · audit-logged" onClick={() => onPick("bulk")} />
        <ModeCard
          icon={IconUsers} title="Walk-up add (day-of)"
          desc="Someone showed up at an event without registering. Capture the minimum, log their hours immediately, complete the rest later."
          badge="On-site · 60 sec" onClick={() => onPick("walkup")} />
      </div>
      <div style={{ marginTop: 22, padding: 12, background: "var(--paper-deep)", borderRadius: 10, fontSize: 12, color: "var(--fg-2)", lineHeight: 1.5 }}>
        <IconShield size={13} style={{ verticalAlign: "middle", marginRight: 6, color: "var(--fg-3)" }} />
        Every add path runs duplicate detection against name + email + phone before committing, and applies your tenant's required-field rules.
      </div>
    </div>
  </>
);

const ModeCard = ({ icon: Icon, title, desc, badge, onClick }) => (
  <Card style={{ cursor: "pointer", padding: 18 }} onClick={onClick}>
    <div style={{ display: "grid", gridTemplateColumns: "44px 1fr auto", gap: 14, alignItems: "start" }}>
      <div style={{ width: 44, height: 44, borderRadius: 10, background: "var(--coral-100)", color: "var(--coral-700)", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }}>
        <Icon size={20} />
      </div>
      <div>
        <div style={{ fontSize: 15, fontWeight: 500, color: "var(--ink)" }}>{title}</div>
        <div style={{ fontSize: 12, color: "var(--fg-2)", lineHeight: 1.5, marginTop: 4 }}>{desc}</div>
        {badge && <div style={{ ...av_meta, marginTop: 6 }}>{badge}</div>}
      </div>
      <IconArrow size={16} style={{ color: "var(--fg-3)", marginTop: 14 }} />
    </div>
  </Card>
);

// ============================================================
// SINGLE VOLUNTEER — multi-step
// ============================================================
const SingleVolunteer = ({ onBack, onClose }) => {
  const [step, setStep] = useAV(1);
  const [data, setData] = useAV({
    first: "", last: "", pronouns: "",
    dob: "", language: "English",
    email: "", phone: "", smsOk: false,
    address1: "", city: "", state: "CO", zip: "",
    emergencyName: "", emergencyPhone: "", emergencyRel: "",
    site: "", program: "", role: "",
    waivers: { liability: false, photo: false, medical: false },
    medical: false, allergies: "",
    minor: false, guardianName: "", guardianRelation: "",
    backgroundCheck: "not-yet", driverCheck: "n-a",
    notes: "",
    inviteImmediately: true,
    autoEnroll: true,
  });
  const update = (patch) => setData({ ...data, ...patch });
  const steps = ["Identity", "Contact", "Role & site", "Screening", "Review"];

  // duplicate detection (mock)
  const possibleDupe = useAVM(() => {
    if (!data.first && !data.email) return null;
    if (data.email && data.email.toLowerCase().includes("okonkwo")) {
      return VOLUNTEERS.find(v => v.id === "v-okonkwo");
    }
    if (data.first.toLowerCase() === "maya" && data.last.toLowerCase() === "okonkwo") {
      return VOLUNTEERS.find(v => v.id === "v-okonkwo");
    }
    return null;
  }, [data.first, data.last, data.email, data.phone]);

  return (
    <>
      <div style={av_head}>
        <div>
          <div style={av_over}>Add volunteer · single</div>
          <div style={{ fontSize: 19, fontWeight: 500, color: "var(--ink)", marginTop: 4 }}>
            {step === 1 ? "Step 1 · Identity"
            : step === 2 ? "Step 2 · Contact"
            : step === 3 ? "Step 3 · Role & site"
            : step === 4 ? "Step 4 · Screening & waivers"
            : step === 5 ? "Step 5 · Review & invite"
            : "Added"}
          </div>
        </div>
        <IconBtn icon={IconX} size={32} onClick={onClose} aria-label="Close" />
      </div>
      {step <= 5 && (
        <div style={{ display: "flex", gap: 4, padding: "12px 24px 0", alignItems: "center" }}>
          {steps.map((label, i) => {
            const n = i + 1;
            return (
              <div key={label} style={{ flex: 1 }}>
                <div style={{ display: "flex", gap: 8, alignItems: "center", padding: "6px 0" }}>
                  <span style={{
                    width: 22, height: 22, borderRadius: 999, display: "flex", alignItems: "center", justifyContent: "center",
                    background: n < step ? "var(--sage-700)" : n === step ? "var(--coral-600)" : "var(--paper-deep)",
                    color: n <= step ? "#FFFFFF" : "var(--fg-3)",
                    fontSize: 11, fontWeight: 600,
                  }}>{n < step ? "✓" : n}</span>
                  <span style={{ fontSize: 12, fontWeight: 500, color: n <= step ? "var(--ink)" : "var(--fg-3)" }}>{label}</span>
                </div>
                <div style={{ height: 2, background: n <= step ? "var(--coral-600)" : "var(--paper-deep)", borderRadius: 2 }} />
              </div>
            );
          })}
        </div>
      )}

      <div style={{ flex: 1, overflow: "auto", padding: 24 }}>
        {step === 1 && <Step1Identity data={data} update={update} possibleDupe={possibleDupe} />}
        {step === 2 && <Step2Contact  data={data} update={update} />}
        {step === 3 && <Step3RoleSite data={data} update={update} />}
        {step === 4 && <Step4Screening data={data} update={update} />}
        {step === 5 && <Step5Review   data={data} update={update} />}
        {step === 6 && <Step6Done     data={data} onClose={onClose} />}
      </div>

      <div style={av_foot}>
        {step === 1
          ? <Btn kind="ghost" onClick={onBack} icon={IconArrowL}>Change mode</Btn>
          : step <= 5
          ? <Btn kind="ghost" onClick={() => setStep(step - 1)} icon={IconArrowL}>Back</Btn>
          : null}
        <div style={{ marginLeft: "auto", display: "flex", gap: 8 }}>
          {step < 5 && (
            <Btn iconRight={IconArrow} onClick={() => setStep(step + 1)} disabled={step === 1 && !data.first}>
              Continue
            </Btn>
          )}
          {step === 5 && (
            <>
              <Btn kind="secondary" onClick={() => update({ inviteImmediately: false })}>Save as draft</Btn>
              <Btn icon={IconCheck} onClick={() => setStep(6)}>
                {data.inviteImmediately ? "Add & send invite" : "Add volunteer"}
              </Btn>
            </>
          )}
          {step === 6 && (
            <>
              <Btn kind="secondary" onClick={() => { setStep(1); update({ first: "", last: "", email: "", phone: "" }); }}>Add another</Btn>
              <Btn icon={IconCheck} onClick={onClose}>Done</Btn>
            </>
          )}
        </div>
      </div>
    </>
  );
};

// ---- Step 1 ----
const Step1Identity = ({ data, update, possibleDupe }) => (
  <>
    <p style={{ fontSize: 13, color: "var(--fg-2)", marginBottom: 18, maxWidth: 540 }}>
      Start with the volunteer's name. We check for duplicates as you type.
    </p>
    <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
      <Field label="Legal first name" required>
        <Input value={data.first} onChange={(e) => update({ first: e.target.value })} placeholder="Maya" autoFocus />
      </Field>
      <Field label="Legal last name" required>
        <Input value={data.last} onChange={(e) => update({ last: e.target.value })} placeholder="Okonkwo" />
      </Field>
      <Field label="Preferred name / pronouns">
        <Input value={data.pronouns} onChange={(e) => update({ pronouns: e.target.value })} placeholder="she/her" />
      </Field>
      <Field label="Date of birth">
        <Input type="date" value={data.dob} onChange={(e) => update({ dob: e.target.value })} />
      </Field>
      <Field label="Preferred language">
        <Select value={data.language} onChange={(e) => update({ language: e.target.value })}
          options={["English", "Spanish", "Vietnamese", "Mandarin", "Russian", "Other"]} />
      </Field>
      <Field label="Minor (under 18)?">
        <Toggle checked={data.minor} onChange={(on) => update({ minor: on })} />
      </Field>
    </div>

    {data.minor && (
      <div style={{ marginTop: 14, padding: 14, background: "var(--amber-100)", borderRadius: 10 }}>
        <div style={{ ...av_over, color: "var(--amber-600)", marginBottom: 8 }}>Minor onboarding required</div>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
          <Field label="Guardian name" required>
            <Input value={data.guardianName} onChange={(e) => update({ guardianName: e.target.value })} />
          </Field>
          <Field label="Relationship" required>
            <Select value={data.guardianRelation} onChange={(e) => update({ guardianRelation: e.target.value })}
              options={["", "Parent", "Legal guardian", "Other family"]} />
          </Field>
        </div>
        <div style={{ fontSize: 12, color: "var(--amber-600)", marginTop: 8 }}>
          A parental consent waiver will be requested before any shifts.
        </div>
      </div>
    )}

    {possibleDupe && (
      <div style={{ marginTop: 14, padding: 14, background: "var(--coral-50)", border: "1px solid var(--coral-200)", borderRadius: 10 }}>
        <div style={{ ...av_over, color: "var(--coral-700)", marginBottom: 10 }}>Possible duplicate · review before continuing</div>
        <div style={{ display: "flex", gap: 14, alignItems: "center" }}>
          <Avatar {...possibleDupe} />
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 14, fontWeight: 500 }}>{possibleDupe.name}</div>
            <div style={{ ...av_meta, marginTop: 2 }}>{possibleDupe.email} · {possibleDupe.role} · joined {possibleDupe.joined}</div>
          </div>
          <Btn size="sm" kind="secondary">Open record</Btn>
          <Btn size="sm" kind="ghost">Continue anyway</Btn>
        </div>
        <div style={{ fontSize: 12, color: "var(--fg-2)", marginTop: 10, lineHeight: 1.5 }}>
          Match by exact name + similar email. Choosing 'Open record' adds the new context to the existing volunteer instead of creating a duplicate.
        </div>
      </div>
    )}
  </>
);

// ---- Step 2 ----
const Step2Contact = ({ data, update }) => (
  <>
    <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
      <Field label="Email" required>
        <Input type="email" value={data.email} onChange={(e) => update({ email: e.target.value })} placeholder="maya@example.com" />
      </Field>
      <Field label="Mobile phone">
        <Input type="tel" value={data.phone} onChange={(e) => update({ phone: e.target.value })} placeholder="(720) 555-0142" />
      </Field>
    </div>

    {data.phone && (
      <div style={{ display: "flex", gap: 8, padding: "10px 12px", background: "var(--iris-100)", color: "var(--iris-600)", borderRadius: 10, fontSize: 12, marginTop: 4, marginBottom: 14, alignItems: "center" }}>
        <IconShield size={14} />
        <span style={{ flex: 1 }}>SMS requires verification. We'll send a one-time code when they claim the account.</span>
        <Checkbox checked={data.smsOk} onChange={(on) => update({ smsOk: on })} label="OK to text" />
      </div>
    )}

    <div style={{ ...av_over, margin: "10px 0 8px" }}>Mailing address</div>
    <div style={{ display: "grid", gridTemplateColumns: "1fr", gap: 12 }}>
      <Field label="Street address">
        <Input value={data.address1} onChange={(e) => update({ address1: e.target.value })} placeholder="123 Main St" />
      </Field>
    </div>
    <div style={{ display: "grid", gridTemplateColumns: "2fr 60px 100px", gap: 12 }}>
      <Field label="City">
        <Input value={data.city} onChange={(e) => update({ city: e.target.value })} />
      </Field>
      <Field label="State">
        <Input value={data.state} onChange={(e) => update({ state: e.target.value })} />
      </Field>
      <Field label="ZIP">
        <Input value={data.zip} onChange={(e) => update({ zip: e.target.value })} placeholder="80524" />
      </Field>
    </div>

    <div style={{ ...av_over, margin: "10px 0 8px" }}>Emergency contact</div>
    <div style={{ display: "grid", gridTemplateColumns: "2fr 2fr 1fr", gap: 12 }}>
      <Field label="Name">
        <Input value={data.emergencyName} onChange={(e) => update({ emergencyName: e.target.value })} />
      </Field>
      <Field label="Phone">
        <Input value={data.emergencyPhone} onChange={(e) => update({ emergencyPhone: e.target.value })} />
      </Field>
      <Field label="Relationship">
        <Select value={data.emergencyRel} onChange={(e) => update({ emergencyRel: e.target.value })}
          options={["", "Spouse / partner", "Parent", "Sibling", "Child", "Friend", "Other"]} />
      </Field>
    </div>

    <div style={{ marginTop: 14, padding: 12, background: "var(--paper-deep)", borderRadius: 10, fontSize: 12, color: "var(--fg-2)", lineHeight: 1.5 }}>
      Emergency contact is required before any field-based role becomes active.
    </div>
  </>
);

// ---- Step 3 ----
const Step3RoleSite = ({ data, update }) => {
  const SITES = ["Cherry Creek SP", "Boyd Lake SP", "Lory SP", "Lake Pueblo SP", "Estes Park", "Statewide / no site"];
  const PROGRAMS = ["State parks", "Wildlife", "Education", "Hunter Outreach", "Search & rescue"];
  const ROLES = [
    { id: "trail",  label: "Trail crew",        program: "State parks", training: ["Trail crew safety"], cert: [] },
    { id: "host",   label: "Camp host",         program: "State parks", training: ["Camp host orientation", "Reservation system basics"], cert: [] },
    { id: "stew",   label: "Trail steward",     program: "State parks", training: ["Wildlife encounter protocols"], cert: [] },
    { id: "natu",   label: "Naturalist",        program: "Education",   training: ["Naturalist program"], cert: ["First aid"] },
    { id: "hunter", label: "Hunter ed instr.",  program: "Hunter Outreach", training: ["Hunter ed methodology"], cert: ["Hunter Ed Instructor (Kalkomey)"] },
    { id: "csv",    label: "Community Science", program: "Wildlife",    training: [], cert: [] },
  ];
  const matchedRole = ROLES.find(r => r.id === data.role);

  return (
    <>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
        <Field label="Primary site / location">
          <Select value={data.site} onChange={(e) => update({ site: e.target.value })} options={["", ...SITES]} />
        </Field>
        <Field label="Program">
          <Select value={data.program} onChange={(e) => update({ program: e.target.value })} options={["", ...PROGRAMS]} />
        </Field>
      </div>

      <div style={{ ...av_over, margin: "12px 0 10px" }}>Role</div>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(2, 1fr)", gap: 8 }}>
        {ROLES.filter(r => !data.program || r.program === data.program).map(r => (
          <button key={r.id} onClick={() => update({ role: r.id })} style={{
            padding: 14, borderRadius: 10, cursor: "pointer", fontFamily: "inherit",
            background: data.role === r.id ? "var(--coral-50)" : "var(--paper)",
            border: "1px solid " + (data.role === r.id ? "var(--coral-500)" : "var(--border-soft)"),
            borderWidth: data.role === r.id ? 2 : 1, textAlign: "left",
          }}>
            <div style={{ fontSize: 14, fontWeight: 500, color: "var(--ink)" }}>{r.label}</div>
            <div style={{ ...av_meta, marginTop: 4 }}>{r.program}</div>
            {(r.training.length > 0 || r.cert.length > 0) && (
              <div style={{ display: "flex", gap: 4, flexWrap: "wrap", marginTop: 8 }}>
                {r.training.map(t => <span key={t} style={{ fontSize: 10, padding: "1px 6px", borderRadius: 4, background: "var(--iris-100)", color: "var(--iris-600)", fontWeight: 500 }}>{t}</span>)}
                {r.cert.map(c => <span key={c} style={{ fontSize: 10, padding: "1px 6px", borderRadius: 4, background: "var(--amber-100)", color: "var(--amber-600)", fontWeight: 500 }}>{c}</span>)}
              </div>
            )}
          </button>
        ))}
      </div>

      {matchedRole && (matchedRole.training.length > 0 || matchedRole.cert.length > 0) && (
        <div style={{ marginTop: 14, padding: 14, background: "var(--iris-100)", color: "var(--iris-600)", borderRadius: 10 }}>
          <div style={{ ...av_over, color: "var(--iris-600)", marginBottom: 8 }}>Role requirements</div>
          <ul style={{ margin: 0, paddingLeft: 18, fontSize: 13, color: "var(--ink)", lineHeight: 1.6 }}>
            {matchedRole.training.map(t => <li key={t}>Training: <strong>{t}</strong> · auto-enrolled when activated</li>)}
            {matchedRole.cert.map(c => <li key={c}>Certification: <strong>{c}</strong> · required before first shift</li>)}
          </ul>
          <Checkbox checked={data.autoEnroll} onChange={(on) => update({ autoEnroll: on })} label="Auto-enroll in required training when activated" />
        </div>
      )}
    </>
  );
};

// ---- Step 4 ----
const Step4Screening = ({ data, update }) => (
  <>
    <div style={{ ...av_over, marginBottom: 10 }}>Waivers & agreements</div>
    <Card style={{ background: "var(--paper)", marginBottom: 14 }}>
      <Checkbox checked={data.waivers.liability} onChange={(on) => update({ waivers: { ...data.waivers, liability: on } })} label="Liability waiver — required for all field roles" />
      <Checkbox checked={data.waivers.photo} onChange={(on) => update({ waivers: { ...data.waivers, photo: on } })} label="Photo / media release — optional" />
      <Checkbox checked={data.waivers.medical} onChange={(on) => update({ waivers: { ...data.waivers, medical: on } })} label="Medical information disclosure — only if relevant" />
      <div style={{ ...av_meta, marginTop: 8 }}>Volunteer will e-sign each selected waiver when they claim their account.</div>
    </Card>

    <div style={{ ...av_over, marginBottom: 10 }}>Background & driving checks</div>
    <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, marginBottom: 14 }}>
      <Field label="Background check">
        <Select value={data.backgroundCheck} onChange={(e) => update({ backgroundCheck: e.target.value })}
          options={[
            { value: "not-yet", label: "Not yet — start when activated" },
            { value: "n-a",     label: "Not required for this role" },
            { value: "valid",   label: "Existing check on file (provide date)" },
            { value: "manual",  label: "Manual — paper waiver collected" },
          ]} />
      </Field>
      <Field label="Driving check">
        <Select value={data.driverCheck} onChange={(e) => update({ driverCheck: e.target.value })}
          options={[
            { value: "n-a",     label: "N/A — role doesn't involve driving" },
            { value: "not-yet", label: "Not yet — start when activated" },
            { value: "valid",   label: "Existing check on file" },
          ]} />
      </Field>
    </div>

    <div style={{ ...av_over, marginBottom: 10 }}>Medical info</div>
    <Card style={{ background: "var(--paper)", marginBottom: 14 }}>
      <Checkbox checked={data.medical} onChange={(on) => update({ medical: on })} label="They've disclosed allergies or medical conditions relevant to field work" />
      {data.medical && (
        <div style={{ marginTop: 10 }}>
          <Field label="Notes (visible to coordinator only)">
            <Textarea rows={3} value={data.allergies} onChange={(e) => update({ allergies: e.target.value })}
              placeholder="e.g. severe bee sting allergy, carries EpiPen." />
          </Field>
        </div>
      )}
    </Card>

    <Field label="Coordinator notes (internal)">
      <Textarea rows={3} value={data.notes} onChange={(e) => update({ notes: e.target.value })}
        placeholder="Anything else we should know about this volunteer?" />
    </Field>
  </>
);

// ---- Step 5 ----
const Step5Review = ({ data, update }) => (
  <>
    <div style={{ display: "grid", gridTemplateColumns: "minmax(0, 1.6fr) minmax(280px, 1fr)", gap: 14 }}>
      <Card>
        <div style={{ ...av_over, marginBottom: 12 }}>Volunteer summary</div>
        <RR label="Name" v={`${data.first} ${data.last}${data.pronouns ? " (" + data.pronouns + ")" : ""}`} />
        {data.dob && <RR label="Date of birth" v={data.dob} />}
        <RR label="Language" v={data.language} />
        {data.minor && <RR label="Minor" v={`Yes · guardian: ${data.guardianName || "—"} (${data.guardianRelation || "—"})`} />}
        <RR label="Email" v={data.email || "—"} />
        <RR label="Phone" v={data.phone ? `${data.phone}${data.smsOk ? " · SMS ok" : ""}` : "—"} />
        <RR label="Address" v={data.address1 ? `${data.address1}, ${data.city}, ${data.state} ${data.zip}` : "—"} />
        <RR label="Emergency contact" v={data.emergencyName ? `${data.emergencyName} (${data.emergencyRel}) · ${data.emergencyPhone}` : "—"} />
        <RR label="Site / program" v={`${data.site || "—"} · ${data.program || "—"}`} />
        <RR label="Role" v={data.role || "—"} />
        <RR label="Background check" v={data.backgroundCheck} />
        <RR label="Driving check" v={data.driverCheck} />
        <RR label="Waivers requested" v={Object.entries(data.waivers).filter(([_, v]) => v).map(([k]) => k).join(", ") || "—"} />
        {data.medical && <RR label="Medical notes" v={data.allergies || "—"} />}
        {data.notes && <RR label="Coordinator notes" v={data.notes} />}
      </Card>
      <Card>
        <div style={{ ...av_over, marginBottom: 12 }}>What happens when you save</div>
        <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
          <Step n="1" t="Volunteer record created · status = Applicant" />
          <Step n="2" t={data.inviteImmediately ? "Account-claim email sent immediately" : "Saved without invite (you can send later)"} />
          <Step n="3" t={data.autoEnroll ? "Auto-enrolled in role-required training" : "Manual training assignment"} />
          <Step n="4" t="Background / driving checks queued (if 'start when activated')" />
          <Step n="5" t="Audit entry created with your actor, timestamp, and consent state" />
        </div>
        <div style={{ ...av_over, margin: "16px 0 8px" }}>Options</div>
        <Checkbox checked={data.inviteImmediately} onChange={(on) => update({ inviteImmediately: on })} label="Send account-claim email immediately" />
        <Checkbox checked={data.autoEnroll} onChange={(on) => update({ autoEnroll: on })} label="Auto-enroll in role-required training" />
        <div style={{ marginTop: 14, padding: 10, background: "var(--paper-deep)", borderRadius: 8, fontSize: 11, color: "var(--fg-2)", lineHeight: 1.5 }}>
          The volunteer can edit their own contact + preferences when they claim the account. Sensitive fields (background check status, internal notes) remain coordinator-only.
        </div>
      </Card>
    </div>
  </>
);

const RR = ({ label, v }) => (
  <div style={{ display: "grid", gridTemplateColumns: "150px 1fr", gap: 14, padding: "7px 0", borderBottom: "1px dashed var(--border-soft)", fontSize: 13, alignItems: "baseline" }}>
    <span style={{ color: "var(--fg-3)" }}>{label}</span>
    <span style={{ color: "var(--ink)" }}>{v}</span>
  </div>
);
const Step = ({ n, t }) => (
  <div style={{ display: "grid", gridTemplateColumns: "24px 1fr", gap: 8, alignItems: "start" }}>
    <span style={{ width: 22, height: 22, borderRadius: 999, background: "var(--coral-100)", color: "var(--coral-700)", display: "flex", alignItems: "center", justifyContent: "center", fontSize: 11, fontWeight: 600, flexShrink: 0 }}>{n}</span>
    <span style={{ fontSize: 13, color: "var(--fg-1)", lineHeight: 1.5 }}>{t}</span>
  </div>
);

// ---- Step 6 ----
const Step6Done = ({ data, onClose }) => (
  <div style={{ textAlign: "center", padding: "30px 20px" }}>
    <div style={{ width: 64, height: 64, borderRadius: 999, background: "var(--sage-100)", color: "var(--sage-700)", display: "flex", alignItems: "center", justifyContent: "center", margin: "0 auto 20px" }}>
      <IconCheck size={32} />
    </div>
    <div style={{ fontFamily: "var(--font-display)", fontSize: 30, color: "var(--ink)", marginBottom: 8 }}>{data.first} {data.last} added</div>
    <div style={{ fontSize: 13, color: "var(--fg-2)", marginBottom: 16 }}>
      Status: <strong>Applicant</strong>{data.inviteImmediately ? " · invite email sent" : " · invite not sent"} · audit ref <code style={{ background: "var(--paper-deep)", padding: "2px 7px", borderRadius: 4, fontFamily: "var(--font-mono)", fontSize: 12 }}>add-vol-{new Date().toISOString().slice(0, 10)}-{Math.random().toString(36).slice(2, 5)}</code>
    </div>
    <div style={{ display: "flex", gap: 12, justifyContent: "center", marginTop: 20, maxWidth: 480, marginInline: "auto" }}>
      <Card style={{ flex: 1, padding: 12, textAlign: "left" }}>
        <div style={{ ...av_over, marginBottom: 6 }}>Up next</div>
        <div style={{ fontSize: 12, color: "var(--fg-1)", lineHeight: 1.5 }}>
          {data.inviteImmediately
            ? "They'll receive an email within 60 seconds. The account-claim link is valid for 14 days."
            : "Send the invite from their record when ready."}
        </div>
      </Card>
      <Card style={{ flex: 1, padding: 12, textAlign: "left" }}>
        <div style={{ ...av_over, marginBottom: 6 }}>Training assignments</div>
        <div style={{ fontSize: 12, color: "var(--fg-1)", lineHeight: 1.5 }}>
          {data.autoEnroll ? "Auto-enrolled in role-required courses." : "No training assigned yet."}
        </div>
      </Card>
    </div>
  </div>
);

// ============================================================
// BULK IMPORT
// ============================================================
const BulkImport = ({ onBack, onClose }) => {
  const [step, setStep] = useAV(1);
  return (
    <>
      <div style={av_head}>
        <div>
          <div style={av_over}>Add volunteer · bulk CSV import</div>
          <div style={{ fontSize: 19, fontWeight: 500, color: "var(--ink)", marginTop: 4 }}>
            {step === 1 ? "Step 1 · Upload CSV"
            : step === 2 ? "Step 2 · Map columns"
            : step === 3 ? "Step 3 · Dedupe & validate"
            : step === 4 ? "Step 4 · Review & commit"
            : "Imported"}
          </div>
        </div>
        <IconBtn icon={IconX} size={32} onClick={onClose} aria-label="Close" />
      </div>
      <div style={{ flex: 1, overflow: "auto", padding: 24 }}>
        {step === 1 && <BulkStep1 />}
        {step === 2 && <BulkStep2 />}
        {step === 3 && <BulkStep3 />}
        {step === 4 && <BulkStep4 />}
        {step === 5 && <BulkStep5 onClose={onClose} />}
      </div>
      <div style={av_foot}>
        {step === 1
          ? <Btn kind="ghost" onClick={onBack} icon={IconArrowL}>Change mode</Btn>
          : step <= 4
          ? <Btn kind="ghost" onClick={() => setStep(step - 1)} icon={IconArrowL}>Back</Btn>
          : null}
        <div style={{ marginLeft: "auto", display: "flex", gap: 8 }}>
          {step < 4 && <Btn iconRight={IconArrow} onClick={() => setStep(step + 1)}>Continue</Btn>}
          {step === 4 && <Btn icon={IconCheck} onClick={() => setStep(5)}>Commit · 156 volunteers</Btn>}
          {step === 5 && <Btn icon={IconCheck} onClick={onClose}>Done</Btn>}
        </div>
      </div>
    </>
  );
};

const BulkStep1 = () => (
  <>
    <p style={{ fontSize: 13, color: "var(--fg-2)", marginBottom: 18, maxWidth: 580 }}>
      Upload a CSV file. We'll map columns, dedupe against existing records, validate required fields, then commit only after you confirm.
    </p>
    <div style={{ padding: 32, border: "2px dashed var(--stone-300)", borderRadius: 12, textAlign: "center", background: "var(--paper)" }}>
      <IconUpload size={36} style={{ color: "var(--fg-3)", margin: "0 auto 14px" }} />
      <div style={{ fontSize: 15, fontWeight: 500, marginBottom: 6 }}>Drop a CSV file here, or browse</div>
      <div style={{ fontSize: 12, color: "var(--fg-3)" }}>Up to 5,000 rows · 5 MB max</div>
      <Btn size="sm" kind="secondary" style={{ marginTop: 14 }}>Choose file…</Btn>
      <div style={{ marginTop: 18, padding: "10px 14px", background: "var(--paper-soft)", borderRadius: 10, fontSize: 12, color: "var(--fg-2)", textAlign: "left", display: "inline-block" }}>
        <div style={{ ...av_over, marginBottom: 6 }}>Preview</div>
        <div style={{ fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--fg-1)" }}>cpw-volunteers-import-2026-05.csv · 168 rows · 4 columns</div>
      </div>
    </div>
    <div style={{ marginTop: 18, padding: 14, background: "var(--paper-deep)", borderRadius: 10, fontSize: 12, color: "var(--fg-2)", lineHeight: 1.6 }}>
      <div style={{ ...av_over, marginBottom: 6 }}>Need a template?</div>
      Download the <a style={{ color: "var(--coral-700)" }} href="#">CPW volunteer import template (CSV)</a> — name, email, phone, mailing address, site, role.
    </div>
  </>
);

const BulkStep2 = () => (
  <>
    <p style={{ fontSize: 13, color: "var(--fg-2)", marginBottom: 18, maxWidth: 580 }}>
      Map your file's columns to CPW fields. Auto-detected mappings are shown — fix any you need.
    </p>
    <Card padded={false}>
      <div style={{ display: "grid", gridTemplateColumns: "180px 30px 1fr 120px", gap: 12, padding: "12px 18px", fontSize: 11, letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--fg-3)", borderBottom: "1px solid var(--border)" }}>
        <span>Your column</span><span /><span>CPW field</span><span>State</span>
      </div>
      {[
        { src: "FirstName",    dest: "First name",     state: "auto" },
        { src: "LastName",     dest: "Last name",      state: "auto" },
        { src: "Email",        dest: "Email",          state: "auto" },
        { src: "Phone",        dest: "Phone",          state: "auto" },
        { src: "Address",      dest: "Mailing line 1", state: "auto" },
        { src: "City",         dest: "City",           state: "auto" },
        { src: "State",        dest: "State",          state: "auto" },
        { src: "Zip",          dest: "ZIP",            state: "auto" },
        { src: "PreferredSite",dest: "Primary site",   state: "auto" },
        { src: "HoursSoFar",   dest: "(ignore)",       state: "ignore" },
        { src: "SiteCode",     dest: "(needs mapping)",state: "needs" },
      ].map((m, i, arr) => (
        <div key={i} style={{ display: "grid", gridTemplateColumns: "180px 30px 1fr 120px", gap: 12, padding: "10px 18px", alignItems: "center", borderBottom: i === arr.length - 1 ? "none" : "1px solid var(--border-soft)" }}>
          <code style={{ fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--fg-1)" }}>{m.src}</code>
          <span style={{ color: "var(--fg-3)" }}>→</span>
          <Select defaultValue={m.dest} options={[m.dest, "First name", "Last name", "Email", "Phone", "Mailing line 1", "City", "State", "ZIP", "Primary site", "Program", "Role", "(ignore)"]} />
          <StatusChip
            status={m.state === "auto" ? "confirmed" : m.state === "ignore" ? "draft" : "pending"}
            size="sm"
            label={m.state === "auto" ? "Auto" : m.state === "ignore" ? "Ignored" : "Map this"} />
        </div>
      ))}
    </Card>
  </>
);

const BulkStep3 = () => (
  <>
    <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 12, marginBottom: 18 }}>
      <Kpi label="Rows in file" value="168" tone="neutral" icon={IconUsers} />
      <Kpi label="Will add" value="156" delta="new volunteers" tone="up" icon={IconCheck} />
      <Kpi label="Duplicates" value="9" delta="merge or skip" tone="neutral" icon={IconSwitch} />
      <Kpi label="Errors" value="3" delta="fix before commit" tone="down" icon={IconX} />
    </div>
    <Card padded={false}>
      <div style={{ display: "grid", gridTemplateColumns: "60px minmax(160px, 1fr) minmax(200px, 1.4fr) 130px 36px", gap: 12, padding: "12px 18px", fontSize: 11, letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--fg-3)", borderBottom: "1px solid var(--border)" }}>
        <span>Row</span><span>From CSV</span><span>Issue</span><span>Action</span><span />
      </div>
      {[
        { row: 12,  name: "Maya Okonkwo · maya@…", issue: "Matches existing record (v-okonkwo). Likely the same person.", action: "Merge" },
        { row: 18,  name: "Robert Fischer · rf@…", issue: "Matches existing record (v-fischer). 80% confidence.", action: "Review" },
        { row: 24,  name: "Sasha Arenas · sasha…", issue: "Email matches existing record (v-arenas).", action: "Merge" },
        { row: 47,  name: "Linh Nguyen · linh.n@…", issue: "Existing volunteer, status inactive. Reactivate?", action: "Reactivate" },
        { row: 89,  name: "(missing email)", issue: "Required field missing. Cannot import.", action: "Fix in CSV", err: true },
        { row: 103, name: "(invalid phone)", issue: "Phone '555-0100' is missing area code.", action: "Fix or ignore", err: true },
        { row: 142, name: "Dakota Lee · 14-yr-old", issue: "Calculated age < 18 — needs guardian info.", action: "Fix in CSV", err: true },
      ].map((r, i, arr) => (
        <div key={i} style={{ display: "grid", gridTemplateColumns: "60px minmax(160px, 1fr) minmax(200px, 1.4fr) 130px 36px", gap: 12, padding: "12px 18px", alignItems: "center", borderBottom: i === arr.length - 1 ? "none" : "1px solid var(--border-soft)", fontSize: 12 }}>
          <code style={{ fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--fg-3)" }}>#{r.row}</code>
          <span style={{ fontWeight: 500 }}>{r.name}</span>
          <span style={{ color: r.err ? "var(--crimson-600)" : "var(--fg-2)", lineHeight: 1.4 }}>{r.issue}</span>
          <Select defaultValue={r.action} options={[r.action, "Skip row", "Merge", "Reactivate", "Create new"]} />
          <IconBtn icon={IconExternal} size={28} />
        </div>
      ))}
    </Card>
  </>
);

const BulkStep4 = () => (
  <>
    <div style={{ display: "grid", gridTemplateColumns: "minmax(0, 1.6fr) minmax(280px, 1fr)", gap: 14 }}>
      <Card>
        <div style={{ ...av_over, marginBottom: 12 }}>Commit summary</div>
        <RR label="File" v="cpw-volunteers-import-2026-05.csv" />
        <RR label="New records" v="156 (status: Applicant)" />
        <RR label="Merged into existing" v="3 records" />
        <RR label="Reactivations" v="1 record" />
        <RR label="Skipped" v="3 rows with errors (will not import)" />
        <RR label="Invite policy" v="Send account-claim email to all new" />
        <RR label="Audit ref" v={`bulk-import-${new Date().toISOString().slice(0, 10)}-${Math.random().toString(36).slice(2, 5)}`} />
      </Card>
      <Card>
        <div style={{ ...av_over, marginBottom: 12 }}>Options</div>
        <Checkbox checked={true} onChange={() => {}} label="Send invite emails immediately" />
        <Checkbox checked={true} onChange={() => {}} label="Auto-enroll in role-required training (per row's mapped role)" />
        <Checkbox checked={false} onChange={() => {}} label="Run dry-run only (no commit)" />
        <div style={{ marginTop: 14, padding: 10, background: "var(--amber-100)", color: "var(--amber-600)", borderRadius: 10, fontSize: 11, lineHeight: 1.5 }}>
          Bulk inserts run in batches of 50. If a batch fails, the run pauses for review without rolling back already-committed batches.
        </div>
      </Card>
    </div>
  </>
);

const BulkStep5 = ({ onClose }) => (
  <div style={{ textAlign: "center", padding: "30px 20px" }}>
    <div style={{ width: 64, height: 64, borderRadius: 999, background: "var(--sage-100)", color: "var(--sage-700)", display: "flex", alignItems: "center", justifyContent: "center", margin: "0 auto 20px" }}>
      <IconCheck size={32} />
    </div>
    <div style={{ fontFamily: "var(--font-display)", fontSize: 30, color: "var(--ink)" }}>156 volunteers added</div>
    <div style={{ fontSize: 13, color: "var(--fg-2)", marginTop: 6, maxWidth: 480, marginInline: "auto" }}>
      3 merged · 1 reactivated · 3 skipped (errors). Invites have been queued and will dispatch over the next 5 minutes (rate-limited).
    </div>
    <div style={{ display: "flex", gap: 8, justifyContent: "center", marginTop: 24 }}>
      <Btn kind="secondary" icon={IconDownload}>Result CSV</Btn>
      <Btn icon={IconCheck} onClick={onClose}>Done</Btn>
    </div>
  </div>
);

// ============================================================
// WALK-UP (day-of, on-site)
// ============================================================
const WalkUp = ({ onBack, onClose }) => {
  const [first, setFirst] = useAV("");
  const [last, setLast] = useAV("");
  const [phone, setPhone] = useAV("");
  const [email, setEmail] = useAV("");
  const [event, setEvent] = useAV("cherry-jun14");
  const [emergencyName, setEmergencyName] = useAV("");
  const [emergencyPhone, setEmergencyPhone] = useAV("");
  const [waiverSigned, setWaiverSigned] = useAV(false);
  const [done, setDone] = useAV(false);

  if (done) {
    return (
      <>
        <div style={av_head}>
          <div>
            <div style={av_over}>Walk-up · added</div>
            <div style={{ fontSize: 19, fontWeight: 500, color: "var(--ink)", marginTop: 4 }}>{first} {last} is on the roster</div>
          </div>
          <IconBtn icon={IconX} size={32} onClick={onClose} aria-label="Close" />
        </div>
        <div style={{ flex: 1, overflow: "auto", padding: 24 }}>
          <div style={{ textAlign: "center", padding: 30 }}>
            <div style={{ width: 64, height: 64, borderRadius: 999, background: "var(--sage-100)", color: "var(--sage-700)", display: "flex", alignItems: "center", justifyContent: "center", margin: "0 auto 14px" }}>
              <IconCheck size={32} />
            </div>
            <div style={{ fontSize: 14, color: "var(--fg-1)", maxWidth: 480, marginInline: "auto", lineHeight: 1.6 }}>
              Volunteer record created with status <strong>Walk-up</strong>. They've been added to the Cherry Creek Jun 14 roster. Hours will log against this event.
              The volunteer can complete the rest of their profile later from the account-claim link.
            </div>
          </div>
        </div>
        <div style={av_foot}>
          <Btn kind="ghost" onClick={() => { setDone(false); setFirst(""); setLast(""); setPhone(""); setEmail(""); }}>Add another walk-up</Btn>
          <div style={{ marginLeft: "auto" }}><Btn icon={IconCheck} onClick={onClose}>Done</Btn></div>
        </div>
      </>
    );
  }

  return (
    <>
      <div style={av_head}>
        <div>
          <div style={av_over}>Walk-up · day-of</div>
          <div style={{ fontSize: 19, fontWeight: 500, color: "var(--ink)", marginTop: 4 }}>Minimum info — capture and go</div>
          <div style={{ fontSize: 12, color: "var(--fg-2)", marginTop: 4, maxWidth: 540 }}>Use this when someone shows up at an event without registering. Only the bare-minimum is captured here; the rest is completed when they claim the account.</div>
        </div>
        <IconBtn icon={IconX} size={32} onClick={onClose} aria-label="Close" />
      </div>
      <div style={{ flex: 1, overflow: "auto", padding: 24 }}>
        <Field label="Event">
          <Select value={event} onChange={(e) => setEvent(e.target.value)} options={[
            { value: "cherry-jun14", label: "Cherry Creek shoreline cleanup · today · 9–11:30 am" },
            { value: "boyd-jun14",   label: "Boyd Lake trail crew · today · 8 am – 1 pm" },
            { value: "lake-pueblo",  label: "Lake Pueblo trash haul · Sat" },
          ]} />
        </Field>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
          <Field label="First name" required><Input value={first} onChange={(e) => setFirst(e.target.value)} autoFocus /></Field>
          <Field label="Last name" required><Input value={last} onChange={(e) => setLast(e.target.value)} /></Field>
          <Field label="Phone" required><Input value={phone} onChange={(e) => setPhone(e.target.value)} placeholder="(720) 555-…" /></Field>
          <Field label="Email"><Input value={email} onChange={(e) => setEmail(e.target.value)} /></Field>
        </div>
        <div style={{ ...av_over, margin: "12px 0 8px" }}>Emergency contact (required for field events)</div>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
          <Field label="Name" required><Input value={emergencyName} onChange={(e) => setEmergencyName(e.target.value)} /></Field>
          <Field label="Phone" required><Input value={emergencyPhone} onChange={(e) => setEmergencyPhone(e.target.value)} /></Field>
        </div>
        <Card style={{ background: "var(--paper)", marginTop: 14 }}>
          <Checkbox checked={waiverSigned} onChange={(on) => setWaiverSigned(on)} label="Paper liability waiver signed (handed to me)" />
          <div style={{ ...av_meta, marginTop: 6 }}>If unchecked, they cannot start the shift. Replace with a digital signature on this device:</div>
          <Btn size="sm" kind="ghost" icon={IconEdit} style={{ marginTop: 6 }}>Sign on this device</Btn>
        </Card>
      </div>
      <div style={av_foot}>
        <Btn kind="ghost" onClick={onBack} icon={IconArrowL}>Change mode</Btn>
        <div style={{ marginLeft: "auto" }}>
          <Btn icon={IconCheck} disabled={!first || !last || !phone || !waiverSigned} onClick={() => setDone(true)}>Add to roster &amp; log shift</Btn>
        </div>
      </div>
    </>
  );
};

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