// csr-settings.jsx — console settings: users & permission levels, and service agents.
const { useState: useStateSet } = React;

const AU_STATES = ["NSW", "VIC", "QLD", "WA", "SA", "ACT", "TAS", "NT"];
const ROLE_TONE = { admin: "brand", operator: "success", dispatch: "warn", finance: "neutral", readonly: "neutral" };
const TYPE_TONE = {
  brand:  { bg: "var(--brand-soft)",  fg: "var(--brand)" },
  accent: { bg: "var(--accent-soft)", fg: "var(--accent-700)" },
  warn:   { bg: "var(--warn-soft)",   fg: "#a36a00" },
  danger: { bg: "var(--danger-soft, #fdeaea)", fg: "var(--danger)" },
};
function allWorkTypeIds() { return (window.FX.BOOKING_TYPES || []).map(t => t.id); }
function userWorkTypeIds(u) { return Array.isArray(u.workTypes) ? u.workTypes : allWorkTypeIds(); }
function isAllWorkTypes(list) { const all = allWorkTypeIds(); return all.length > 0 && all.every(id => list.includes(id)); }

function WorkTypeSummary({ ids }) {
  const types = window.FX.BOOKING_TYPES || [];
  if (isAllWorkTypes(ids)) return <span style={{ display: "inline-flex", alignItems: "center", gap: 6, background: "var(--brand-soft)", color: "var(--brand)", borderRadius: 999, padding: "4px 11px", fontSize: 11.5, fontWeight: 600 }}><Icon name="eye" size={12} /> All work types</span>;
  const shorts = ids.map(id => (types.find(t => t.id === id) || {}).short).filter(Boolean);
  if (shorts.length === 0) return <span style={{ display: "inline-flex", alignItems: "center", gap: 6, color: "var(--danger)", fontSize: 12, fontWeight: 600 }}><Icon name="eye-off" size={12} /> No access</span>;
  const show = shorts.slice(0, 2);
  return (
    <div style={{ display: "flex", flexWrap: "wrap", gap: 5, alignItems: "center" }}>
      {show.map(s => <span key={s} style={{ fontSize: 11, fontWeight: 600, background: "var(--bg-mist)", color: "var(--fg-body)", borderRadius: 999, padding: "3px 9px", whiteSpace: "nowrap" }}>{s}</span>)}
      {shorts.length > 2 && <span style={{ fontSize: 11, fontWeight: 600, color: "var(--fg-mute)" }}>+{shorts.length - 2}</span>}
    </div>
  );
}

function WorkTypeChecklist({ value, onChange }) {
  const types = window.FX.BOOKING_TYPES || [];
  const allIds = types.map(t => t.id);
  const all = isAllWorkTypes(value);
  const toggle = id => onChange(value.includes(id) ? value.filter(x => x !== id) : [...value, id]);
  const box = on => <span style={{ width: 20, height: 20, borderRadius: 6, flex: "none", border: "1.5px solid " + (on ? "var(--brand)" : "var(--border-strong)"), background: on ? "var(--brand)" : "transparent", display: "inline-flex", alignItems: "center", justifyContent: "center" }}>{on && <Icon name="check" size={13} color="#fff" />}</span>;
  return (
    <div style={{ border: "1px solid var(--border)", borderRadius: "var(--r-md)", overflow: "hidden" }}>
      <button type="button" onClick={() => onChange(all ? [] : allIds)} style={{ display: "flex", alignItems: "center", gap: 11, width: "100%", textAlign: "left", padding: "11px 13px", border: "none", borderBottom: "1px solid var(--border)", background: "var(--bg-mist)", cursor: "pointer" }}>
        {box(all)}
        <span style={{ fontSize: 13, fontWeight: 700, color: "var(--fg-strong)", flex: 1 }}>All work types</span>
        <span style={{ fontSize: 11.5, color: "var(--fg-mute)", fontFamily: "var(--font-mono)" }}>{all ? "Everything" : `${value.length} of ${types.length}`}</span>
      </button>
      {types.map((t, i) => {
        const on = value.includes(t.id);
        const tone = TYPE_TONE[t.tone] || TYPE_TONE.brand;
        return (
          <button key={t.id} type="button" onClick={() => toggle(t.id)} style={{ display: "flex", alignItems: "center", gap: 11, width: "100%", textAlign: "left", padding: "10px 13px", border: "none", borderTop: i ? "1px solid var(--border)" : "none", background: on ? "var(--brand-soft)" : "var(--surface)", cursor: "pointer" }}>
            {box(on)}
            <span style={{ width: 30, height: 30, borderRadius: 8, flex: "none", background: tone.bg, color: tone.fg, display: "inline-flex", alignItems: "center", justifyContent: "center" }}><Icon name={t.icon} size={16} /></span>
            <span style={{ minWidth: 0, flex: 1 }}>
              <span style={{ display: "block", fontSize: 13.5, fontWeight: 600, color: "var(--fg-strong)" }}>{t.name}</span>
              <span style={{ display: "block", fontSize: 11.5, color: "var(--fg-mute)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{t.blurb}</span>
            </span>
          </button>
        );
      })}
    </div>
  );
}

function SettingsTabs({ tab, setTab }) {
  const tabs = [["users", "Users & permissions", "users"], ["agents", "Service agents", "shield"], ["rules", "Booking rules", "package"], ["announce", "Announcements", "megaphone"]];
  return (
    <div style={{ display: "flex", gap: 8, marginBottom: 22, borderBottom: "1px solid var(--border)" }}>
      {tabs.map(([k, lbl, ic]) => (
        <button key={k} onClick={() => setTab(k)} style={{ display: "inline-flex", alignItems: "center", gap: 8, padding: "11px 16px", border: "none", background: "none", borderBottom: "2px solid " + (tab === k ? "var(--brand)" : "transparent"), color: tab === k ? "var(--brand)" : "var(--fg-mute)", fontSize: 14, fontWeight: 600, marginBottom: -1, cursor: "pointer" }}>
          <Icon name={ic} size={16} /> {lbl}
        </button>
      ))}
    </div>
  );
}

/* ---------------- Users & permissions ---------------- */
function RoleLegend({ roles }) {
  return (
    <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(220px, 1fr))", gap: 12, marginBottom: 22 }}>
      {roles.map(r => (
        <div key={r.id} style={{ border: "1px solid var(--border)", borderRadius: "var(--r-md)", padding: 14, background: "var(--surface)" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 6 }}>
            <Icon name="shield" size={14} color="var(--brand)" />
            <span style={{ fontSize: 13.5, fontWeight: 700, color: "var(--fg-strong)" }}>{r.label}</span>
          </div>
          <div style={{ fontSize: 12, color: "var(--fg-mute)", lineHeight: 1.45, marginBottom: 9, minHeight: 34 }}>{r.desc}</div>
          <div style={{ display: "flex", flexWrap: "wrap", gap: 5 }}>
            {r.access.map(a => <span key={a} style={{ fontSize: 10.5, fontWeight: 600, background: "var(--bg-mist)", color: "var(--fg-body)", borderRadius: 999, padding: "3px 8px" }}>{a}</span>)}
          </div>
        </div>
      ))}
    </div>
  );
}

function UsersPanel({ users, roles, onSaveUser, onDeleteUser, onAdd, onEdit }) {
  const GRID = "1.25fr 0.9fr 1fr 0.62fr 0.6fr 0.55fr";
  const stationLabel = st => (!st || st === "all") ? null : (window.FX.AIRPORTS[st] ? window.FX.AIRPORTS[st].code + " · " + window.FX.AIRPORTS[st].city : st);
  return (
    <div>
      <div style={{ fontFamily: "var(--font-mono)", fontSize: 10.5, letterSpacing: "0.9px", textTransform: "uppercase", color: "var(--fg-mute)", marginBottom: 10 }}>Permission levels</div>
      <RoleLegend roles={roles} />

      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 12 }}>
        <div style={{ fontSize: 15, fontWeight: 700, color: "var(--fg-strong)" }}>Users <span style={{ fontFamily: "var(--font-mono)", fontSize: 12.5, color: "var(--fg-mute)", fontWeight: 500 }}>· {users.length}</span></div>
        <Button variant="primary" size="sm" icon="user-plus" onClick={onAdd}>Add user</Button>
      </div>

      <Card pad={0} style={{ overflow: "hidden" }}>
        <div style={{ display: "grid", gridTemplateColumns: GRID, gap: 10, padding: "11px 18px", background: "var(--bg-mist)", borderBottom: "1px solid var(--border)", fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.7px", textTransform: "uppercase", color: "var(--fg-mute)" }}>
          <span>User</span><span>Permission level</span><span>Work visible</span><span>Station</span><span>Status</span><span style={{ textAlign: "right" }}>Actions</span>
        </div>
        {users.map((u, i) => {
          const role = window.FX.roleById(u.roleId);
          return (
            <div key={u.id} style={{ display: "grid", gridTemplateColumns: GRID, gap: 10, padding: "12px 18px", borderTop: i ? "1px solid var(--border)" : "none", alignItems: "center" }}>
              <div style={{ display: "flex", alignItems: "center", gap: 11, minWidth: 0 }}>
                <span style={{ width: 34, height: 34, borderRadius: "50%", flex: "none", background: u.active ? "var(--brand)" : "var(--bg-mist-2)", color: u.active ? "#fff" : "var(--fg-mute)", display: "inline-flex", alignItems: "center", justifyContent: "center", fontWeight: 700, fontSize: 12 }}>{u.name.split(/\s+/).map(w => w[0]).slice(0, 2).join("").toUpperCase()}</span>
                <div style={{ minWidth: 0 }}>
                  <div style={{ fontSize: 13.5, fontWeight: 600, color: "var(--fg-strong)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{u.name}</div>
                  <div style={{ fontSize: 11.5, color: "var(--fg-mute)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{u.email}</div>
                </div>
              </div>
              <div style={{ minWidth: 0 }}>
                <Select value={u.roleId} onChange={v => onSaveUser({ ...u, roleId: v })} options={roles.map(r => ({ value: r.id, label: r.label }))} style={{ paddingTop: 8, paddingBottom: 8, fontSize: 13 }} />
              </div>
              <div style={{ minWidth: 0 }}>
                <WorkTypeSummary ids={userWorkTypeIds(u)} />
              </div>
              <div style={{ minWidth: 0 }}>
                {stationLabel(u.station)
                  ? <span style={{ display: "inline-flex", alignItems: "center", gap: 5, background: "var(--accent-soft)", color: "var(--accent-700)", borderRadius: 999, padding: "4px 10px", fontSize: 11.5, fontWeight: 700, fontFamily: "var(--font-mono)" }}><Icon name="plane" size={11} /> {stationLabel(u.station)}</span>
                  : <span style={{ fontSize: 12, color: "var(--fg-mute)" }}>All stations</span>}
              </div>
              <div>
                <button onClick={() => onSaveUser({ ...u, active: !u.active })} style={{ display: "inline-flex", alignItems: "center", gap: 6, padding: "5px 10px", borderRadius: 999, border: "1px solid " + (u.active ? "transparent" : "var(--border)"), background: u.active ? "var(--success-soft, #e7f6ee)" : "var(--bg-mist)", color: u.active ? "var(--success, #1f8a5b)" : "var(--fg-mute)", fontSize: 12, fontWeight: 600, cursor: "pointer" }}>
                  <StatusDot color={u.active ? "#22b86e" : "var(--fg-faint)"} /> {u.active ? "Active" : "Disabled"}
                </button>
              </div>
              <div style={{ display: "flex", justifyContent: "flex-end", gap: 6 }}>
                <button onClick={() => onEdit(u)} title="Edit user" style={{ width: 30, height: 30, borderRadius: 8, border: "1px solid var(--border)", background: "var(--surface)", color: "var(--fg-mute)", display: "inline-flex", alignItems: "center", justifyContent: "center", cursor: "pointer" }}><Icon name="pencil" size={14} /></button>
                <button onClick={() => onDeleteUser(u.id)} title="Remove user" style={{ width: 30, height: 30, borderRadius: 8, border: "1px solid var(--border)", background: "var(--surface)", color: "var(--fg-mute)", display: "inline-flex", alignItems: "center", justifyContent: "center", cursor: "pointer" }}><Icon name="trash-2" size={15} /></button>
              </div>
            </div>
          );
        })}
      </Card>
    </div>
  );
}

/* ---------------- Service agents ---------------- */
function AgentsPanel({ agents, onEdit, onDeleteAgent, onSaveAgent, onAdd }) {
  const GRID = "1.4fr 1fr 1.3fr 1fr 0.6fr";
  return (
    <div>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 16, marginBottom: 14 }}>
        <div style={{ maxWidth: 620 }}>
          <div style={{ fontSize: 15, fontWeight: 700, color: "var(--fg-strong)" }}>Service agents <span style={{ fontFamily: "var(--font-mono)", fontSize: 12.5, color: "var(--fg-mute)", fontWeight: 500 }}>· {agents.length}</span></div>
          <div style={{ fontSize: 13, color: "var(--fg-mute)", marginTop: 4 }}>Destination-end partners you can allocate to an interstate booking instead of a driver. Allocation emails the agent (and texts them if a phone number is on file).</div>
        </div>
        <Button variant="primary" size="sm" icon="plus" onClick={onAdd} style={{ flex: "none" }}>Add service agent</Button>
      </div>

      <Card pad={0} style={{ overflow: "hidden" }}>
        <div style={{ display: "grid", gridTemplateColumns: GRID, gap: 10, padding: "11px 18px", background: "var(--bg-mist)", borderBottom: "1px solid var(--border)", fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.7px", textTransform: "uppercase", color: "var(--fg-mute)" }}>
          <span>Agent</span><span>Region</span><span>Email</span><span>Phone / SMS</span><span style={{ textAlign: "right" }}>Actions</span>
        </div>
        {agents.map((a, i) => (
          <div key={a.id} style={{ display: "grid", gridTemplateColumns: GRID, gap: 10, padding: "12px 18px", borderTop: i ? "1px solid var(--border)" : "none", alignItems: "center" }}>
            <div style={{ minWidth: 0 }}>
              <div style={{ fontSize: 13.5, fontWeight: 600, color: "var(--fg-strong)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{a.name}</div>
              <div style={{ fontSize: 11.5, color: "var(--fg-mute)" }}>{a.contact}</div>
            </div>
            <div style={{ display: "flex", alignItems: "center", gap: 7 }}>
              <span style={{ fontFamily: "var(--font-mono)", fontWeight: 700, fontSize: 12.5, color: "var(--brand)" }}>{a.state}</span>
              <span style={{ fontSize: 12.5, color: "var(--fg-body)" }}>{a.city}</span>
            </div>
            <div style={{ fontSize: 12.5, color: "var(--fg-body)", minWidth: 0, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{a.email}</div>
            <div style={{ fontSize: 12.5, minWidth: 0 }}>
              {a.phone
                ? <span style={{ display: "inline-flex", alignItems: "center", gap: 6, color: "var(--fg-body)", fontFamily: "var(--font-mono)" }}><Icon name="message-square" size={12} color="var(--success, #1f8a5b)" /> {a.phone}</span>
                : <span style={{ display: "inline-flex", alignItems: "center", gap: 6, color: "var(--fg-faint)" }}><Icon name="mail" size={12} /> Email only</span>}
            </div>
            <div style={{ display: "flex", justifyContent: "flex-end", gap: 6 }}>
              <button onClick={() => onEdit(a)} title="Edit agent" style={{ width: 30, height: 30, borderRadius: 8, border: "1px solid var(--border)", background: "var(--surface)", color: "var(--fg-mute)", display: "inline-flex", alignItems: "center", justifyContent: "center", cursor: "pointer" }}><Icon name="pencil" size={14} /></button>
              <button onClick={() => onDeleteAgent(a.id)} title="Remove agent" style={{ width: 30, height: 30, borderRadius: 8, border: "1px solid var(--border)", background: "var(--surface)", color: "var(--fg-mute)", display: "inline-flex", alignItems: "center", justifyContent: "center", cursor: "pointer" }}><Icon name="trash-2" size={15} /></button>
            </div>
          </div>
        ))}
        {agents.length === 0 && <div style={{ padding: 36, textAlign: "center", fontSize: 13.5, color: "var(--fg-mute)" }}>No service agents yet. Add one to allocate interstate pickups.</div>}
      </Card>
    </div>
  );
}

/* ---------------- Modals ---------------- */
function UserModal({ open, onClose, roles, seed, onSave }) {
  const [name, setName] = useStateSet("");
  const [email, setEmail] = useStateSet("");
  const [roleId, setRoleId] = useStateSet("operator");
  const [workTypes, setWorkTypes] = useStateSet([]);
  const [station, setStation] = useStateSet("all");
  const [timezone, setTimezone] = useStateSet("Australia/Sydney");
  React.useEffect(() => { if (open) { setName(seed ? seed.name : ""); setEmail(seed ? seed.email : ""); setRoleId(seed ? seed.roleId : "operator"); setWorkTypes(seed ? userWorkTypeIds(seed) : allWorkTypeIds()); setStation((seed && seed.station) || "all"); setTimezone((seed && seed.timezone) || "Australia/Sydney"); } }, [open, seed]);
  const validEmail = /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email.trim());
  const ok = name.trim() && validEmail;
  return (
    <Modal open={open} onClose={onClose} title={seed ? "Edit user" : "Add user"} width={520}>
      <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
        <Field label="Full name"><TextInput value={name} onChange={setName} placeholder="e.g. Alex Taylor" /></Field>
        <Field label="Email"><TextInput value={email} onChange={setEmail} placeholder="name@fedex.com.au" /></Field>
        <Field label="Permission level">
          <Select value={roleId} onChange={setRoleId} options={roles.map(r => ({ value: r.id, label: r.label }))} />
        </Field>
        <div style={{ fontSize: 12, color: "var(--fg-mute)", lineHeight: 1.45, background: "var(--bg-mist)", borderRadius: "var(--r-sm)", padding: "10px 12px" }}>{window.FX.roleById(roleId).desc}</div>
        <Field label="Station" hint="Link the user to a station and they only see bookings touching that station.">
          <Select value={station} onChange={setStation} options={[{ value: "all", label: "All stations — national visibility" }, ...Object.keys(window.FX.AIRPORTS).map(st => ({ value: st, label: window.FX.AIRPORTS[st].code + " — " + window.FX.AIRPORTS[st].city + " (" + st + ")" }))]} />
        </Field>
        <Field label="Timezone" hint="Where this agent works — shown on the console clock and against bookings they enter.">
          <Select value={timezone} onChange={setTimezone} options={window.FX.AU_ZONES.filter((z, i, a) => a.findIndex(x => x.tz === z.tz) === i).map(z => ({ value: z.tz, label: z.city + " · " + z.abbr }))} />
        </Field>
        <Field label="Work types visible" hint="Which job types this user can see in the bookings queue and pre-alerts.">
          <WorkTypeChecklist value={workTypes} onChange={setWorkTypes} />
        </Field>
        <div style={{ display: "flex", justifyContent: "flex-end", gap: 10, marginTop: 4 }}>
          <Button variant="ghost" onClick={onClose}>Cancel</Button>
          <Button variant="primary" icon="check" disabled={!ok} onClick={() => onSave({ id: seed ? seed.id : "u" + Date.now(), name: name.trim(), email: email.trim(), roleId, desk: seed ? seed.desk : "—", active: seed ? seed.active : true, workTypes: isAllWorkTypes(workTypes) ? null : workTypes, station, timezone })}>{seed ? "Save" : "Add user"}</Button>
        </div>
      </div>
    </Modal>
  );
}

function AgentModal({ open, onClose, seed, onSave }) {
  const [name, setName] = useStateSet("");
  const [city, setCity] = useStateSet("");
  const [email, setEmail] = useStateSet("");
  const [areas, setAreas] = useStateSet([]);
  const [contacts, setContacts] = useStateSet([{ name: "", phone: "" }]);
  const [notes, setNotes] = useStateSet("");
  React.useEffect(() => {
    if (open) {
      setName(seed ? seed.name : "");
      setCity(seed ? seed.city : "");
      setEmail(seed ? seed.email : "");
      setAreas(seed ? (seed.serviceAreas || (seed.state ? [seed.state] : [])) : ["VIC"]);
      setContacts(seed ? (seed.contacts && seed.contacts.length ? seed.contacts.map(c => ({ name: c.name || "", phone: c.phone || "" })) : [{ name: seed.contact || "", phone: seed.phone || "" }]) : [{ name: "", phone: "" }]);
      setNotes(seed ? (seed.notes || "") : "");
    }
  }, [open, seed]);
  const cityByState = { NSW: "Sydney", VIC: "Melbourne", QLD: "Brisbane", WA: "Perth", SA: "Adelaide", ACT: "Canberra", TAS: "Hobart", NT: "Darwin" };
  const toggleArea = s => setAreas(prev => prev.includes(s) ? prev.filter(x => x !== s) : [...prev, s]);
  const setContact = (i, k, v) => setContacts(prev => prev.map((c, idx) => idx === i ? { ...c, [k]: v } : c));
  const addContact = () => setContacts(prev => [...prev, { name: "", phone: "" }]);
  const rmContact = (i) => setContacts(prev => prev.length > 1 ? prev.filter((_, idx) => idx !== i) : prev);
  const validEmail = /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email.trim());
  const ok = name.trim() && validEmail && city.trim() && areas.length > 0;

  function save() {
    const cleanContacts = contacts.map(c => ({ name: c.name.trim(), phone: c.phone.trim() })).filter(c => c.name || c.phone);
    const primary = cleanContacts[0] || { name: "", phone: "" };
    onSave({
      id: seed ? seed.id : "sa" + Date.now(),
      name: name.trim(), city: city.trim(), email: email.trim(),
      serviceAreas: areas, state: areas[0],
      contacts: cleanContacts, contact: primary.name, phone: primary.phone,
      notes: notes.trim(), active: seed ? seed.active : true,
    });
  }

  return (
    <Modal open={open} onClose={onClose} title={seed ? "Edit service agent" : "Add service agent"} width={560}>
      <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
        <Field label="Agent / company name"><TextInput value={name} onChange={setName} placeholder="e.g. Metro Freight Services" /></Field>

        <Field label="Service areas" hint="All states this agent covers. The first is used as their base for recommendations.">
          <div style={{ display: "flex", flexWrap: "wrap", gap: 7 }}>
            {AU_STATES.map(s => {
              const on = areas.includes(s);
              const idx = areas.indexOf(s);
              return (
                <button key={s} onClick={() => { toggleArea(s); if (!on && !city.trim()) setCity(cityByState[s] || ""); }} style={{ display: "inline-flex", alignItems: "center", gap: 6, padding: "7px 13px", borderRadius: "var(--r-pill)", fontSize: 13, fontWeight: 600, border: "1.5px solid " + (on ? "var(--accent)" : "var(--border)"), background: on ? "var(--accent-soft)" : "var(--surface)", color: on ? "var(--accent-700)" : "var(--fg-body)", cursor: "pointer" }}>
                  {on && idx === 0 && <span style={{ fontFamily: "var(--font-mono)", fontSize: 9, fontWeight: 700, background: "var(--accent)", color: "#fff", borderRadius: 4, padding: "1px 4px" }}>BASE</span>}
                  {on && <Icon name="check" size={12} />}
                  {s}
                </button>
              );
            })}
          </div>
        </Field>
        <Field label="Base city"><TextInput value={city} onChange={setCity} placeholder="e.g. Melbourne" /></Field>

        <Field label="Account email" hint="The pickup notification is emailed here."><TextInput value={email} onChange={setEmail} placeholder="ops@agent.com.au" /></Field>

        <div>
          <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 8 }}>
            <span style={{ fontSize: 13, fontWeight: 500, color: "var(--fg-strong)" }}>Contact people</span>
            <button onClick={addContact} style={{ display: "inline-flex", alignItems: "center", gap: 5, background: "var(--brand-soft)", border: "none", borderRadius: "var(--r-pill)", padding: "4px 11px", color: "var(--brand)", fontSize: 12, fontWeight: 600, cursor: "pointer" }}><Icon name="plus" size={13} /> Add contact</button>
          </div>
          <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
            {contacts.map((c, i) => (
              <div key={i} style={{ display: "grid", gridTemplateColumns: "1fr 1fr 30px", gap: 8, alignItems: "center" }}>
                <TextInput value={c.name} onChange={v => setContact(i, "name", v)} placeholder={i === 0 ? "Contact name" : "Another contact"} />
                <TextInput value={c.phone} onChange={v => setContact(i, "phone", v)} placeholder="+61 4XX XXX XXX" mono />
                {contacts.length > 1
                  ? <button onClick={() => rmContact(i)} title="Remove" style={{ width: 30, height: 34, borderRadius: 8, border: "1px solid var(--border)", background: "var(--surface)", color: "var(--fg-mute)", display: "inline-flex", alignItems: "center", justifyContent: "center", cursor: "pointer" }}><Icon name="x" size={14} /></button>
                  : <span />}
              </div>
            ))}
          </div>
          <div style={{ fontSize: 11.5, color: "var(--fg-faint)", marginTop: 7 }}>A mobile on the first contact triggers an SMS on allocation.</div>
        </div>

        <Field label="Notes" hint="Anything the team should know — coverage hours, DG handling, dock access, rates.">
          <textarea value={notes} onChange={e => setNotes(e.target.value)} rows={3} placeholder="e.g. Covers metro + regional VIC. After-hours by arrangement. DG-approved to IATA. Invoices weekly." style={{ ...window.inputStyle, resize: "vertical", fontSize: 13.5, lineHeight: 1.45 }} />
        </Field>

        <div style={{ display: "flex", justifyContent: "flex-end", gap: 10, marginTop: 4 }}>
          <Button variant="ghost" onClick={onClose}>Cancel</Button>
          <Button variant="primary" icon="check" disabled={!ok} onClick={save}>{seed ? "Save" : "Add agent"}</Button>
        </div>
      </div>
    </Modal>
  );
}

/* ---------------- Announcements ---------------- */
function AnnouncementsPanel({ announcements, onSaveAnn, onDeleteAnn }) {
  const [title, setTitle] = useStateSet("");
  const [body, setBody] = useStateSet("");
  const [days, setDays] = useStateSet("7");
  const [audience, setAudience] = useStateSet("All customers");
  const [sent, setSent] = useStateSet(false);
  function post() {
    if (!title.trim() || !body.trim()) return;
    const vu = new Date(); vu.setDate(vu.getDate() + parseInt(days, 10)); vu.setHours(23, 59, 0, 0);
    onSaveAnn({ id: window.FX.genAnnId(), title: title.trim(), body: body.trim(), audience, createdAt: new Date().toISOString(), validUntil: vu.toISOString() });
    setTitle(""); setBody(""); setSent(true); setTimeout(() => setSent(false), 2400);
  }
  const daysLeft = a => a.validUntil ? Math.ceil((new Date(a.validUntil) - new Date()) / 86400000) : null;
  const sorted = [...(announcements || [])].sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
  return (
    <div style={{ display: "grid", gridTemplateColumns: "minmax(0,1fr) minmax(0,1.05fr)", gap: 20, alignItems: "start" }}>
      <Card pad={20}>
        <div style={{ fontSize: 15, fontWeight: 700, color: "var(--fg-strong)", marginBottom: 4 }}>Post an announcement</div>
        <div style={{ fontSize: 13, color: "var(--fg-mute)", marginBottom: 16 }}>Shows as a banner on the customer portal home page while valid.</div>
        <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          <Field label="Title"><TextInput value={title} onChange={setTitle} placeholder="e.g. Public holiday hours" /></Field>
          <Field label="Message"><textarea value={body} onChange={e => setBody(e.target.value)} rows={4} placeholder="What customers should know…" style={{ ...inputStyle, resize: "vertical", fontSize: 13.5, lineHeight: 1.5 }} /></Field>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
            <Field label="Valid for"><Select value={days} onChange={setDays} options={[{ value: "1", label: "1 day" }, { value: "3", label: "3 days" }, { value: "7", label: "7 days" }, { value: "14", label: "14 days" }, { value: "30", label: "30 days" }]} /></Field>
            <Field label="Audience"><Select value={audience} onChange={setAudience} options={["All customers", "Active customers", "Next Flight customers", "Customer service team (internal)"]} /></Field>
          </div>
          <div>
            <div style={{ fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.8px", textTransform: "uppercase", color: "var(--fg-mute)", marginBottom: 8 }}>Preview</div>
            <div style={{ display: "flex", gap: 12, alignItems: "flex-start", padding: 15, borderRadius: "var(--r-md)", background: "var(--brand)", color: "#fff" }}>
              <Icon name="megaphone" size={19} style={{ marginTop: 2, flex: "none" }} />
              <div><div style={{ fontWeight: 700, fontSize: 14 }}>{title || "Announcement title"}</div><div style={{ fontSize: 13, opacity: 0.85, marginTop: 3, lineHeight: 1.45 }}>{body || "Your message appears here as customers will see it."}</div></div>
            </div>
          </div>
          <Button variant="primary" size="lg" icon={sent ? "check" : "megaphone"} full disabled={!title.trim() || !body.trim()} onClick={post}>{sent ? "Announcement posted" : "Post announcement"}</Button>
        </div>
      </Card>
      <div>
        <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 12 }}>
          <span style={{ fontSize: 14, fontWeight: 700, color: "var(--fg-strong)" }}>Posted announcements</span>
          <Badge tone="neutral">{sorted.length}</Badge>
        </div>
        <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
          {sorted.map(a => {
            const dl = daysLeft(a); const expired = dl != null && dl < 0;
            return (
              <Card key={a.id} pad={16}>
                <div style={{ display: "flex", alignItems: "center", gap: 9, marginBottom: 7 }}>
                  <span style={{ fontWeight: 700, fontSize: 14.5, color: "var(--fg-strong)", flex: 1 }}>{a.title}</span>
                  {expired ? <Badge tone="neutral">Expired</Badge> : <Badge tone={dl <= 2 ? "warn" : "success"}><StatusDot color={dl <= 2 ? "var(--warn)" : "#22b86e"} /> {dl === 0 ? "Ends today" : "Valid " + dl + " day" + (dl === 1 ? "" : "s")}</Badge>}
                  <button onClick={() => onDeleteAnn(a.id)} title="Remove" style={{ width: 28, height: 28, borderRadius: 7, border: "1px solid var(--border)", background: "var(--surface)", color: "var(--fg-mute)", display: "inline-flex", alignItems: "center", justifyContent: "center", cursor: "pointer" }}><Icon name="trash-2" size={14} /></button>
                </div>
                <div style={{ fontSize: 13, color: "var(--fg-body)", lineHeight: 1.5 }}>{a.body}</div>
                <div style={{ fontSize: 11.5, color: "var(--fg-mute)", fontFamily: "var(--font-mono)", marginTop: 9 }}>{a.audience} · posted {new Date(a.createdAt).toLocaleDateString("en-AU", { day: "numeric", month: "short" })}</div>
              </Card>
            );
          })}
          {sorted.length === 0 && <div style={{ padding: 30, textAlign: "center", fontSize: 13.5, color: "var(--fg-mute)", border: "1px dashed var(--border)", borderRadius: "var(--r-md)" }}>No announcements posted yet.</div>}
        </div>
      </div>
    </div>
  );
}

/* ---------------- Booking rules (item-size presets + vehicle escalation) ---------------- */
function RulesPanel() {
  const [r, setR] = useStateSet(() => JSON.parse(JSON.stringify(window.FX.activeRules())));
  const [saved, setSaved] = useStateSet(false);
  const types = window.FX.ITEM_TYPES;
  const vname = (id) => { const v = window.FX.VEHICLES.find(x => x.id === id); return v ? v.name : id; };
  const touch = () => setSaved(false);
  const setItem = (t, k, v) => { touch(); setR(prev => ({ ...prev, itemDefaults: { ...prev.itemDefaults, [t]: { ...prev.itemDefaults[t], [k]: v } } })); };
  const setCap = (id, k, v) => { touch(); setR(prev => ({ ...prev, vehicleCaps: prev.vehicleCaps.map(c => c.id === id ? { ...c, [k]: v } : c) })); };
  const setTaxi = (k, v) => { touch(); setR(prev => ({ ...prev, taxiTruck: { ...prev.taxiTruck, [k]: v } })); };
  const setPhone = (v) => { touch(); setR(prev => ({ ...prev, phoneOverKg: v })); };
  function save() {
    const clean = { itemDefaults: r.itemDefaults, vehicleCaps: r.vehicleCaps.map(c => ({ id: c.id, kg: parseFloat(c.kg) || 0, m3: parseFloat(c.m3) || 0 })), taxiTruck: { minHours: parseFloat(r.taxiTruck.minHours) || 0, hourly: parseFloat(r.taxiTruck.hourly) || 0 }, phoneOverKg: parseFloat(r.phoneOverKg) || 0 };
    window.FX.setActiveRules(clean); setSaved(true);
  }
  function reset() { setR(JSON.parse(JSON.stringify(window.FX.DEFAULT_RULES))); setSaved(false); }
  const cell = { padding: "7px 8px", fontSize: 13 };
  return (
    <div>
      <div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: 16, marginBottom: 16 }}>
        <div style={{ maxWidth: 640 }}>
          <div style={{ fontSize: 15, fontWeight: 700, color: "var(--fg-strong)" }}>Booking rules</div>
          <div style={{ fontSize: 13, color: "var(--fg-mute)", marginTop: 4 }}>Standard item sizes auto-fill when an item type is chosen. Vehicle bands decide which vehicle is auto-selected from the total weight &amp; volume — above the largest band a taxi-truck / phone quote is required.</div>
        </div>
        <div style={{ display: "flex", gap: 10, flex: "none" }}>
          <Button variant="ghost" onClick={reset}>Reset to defaults</Button>
          <Button variant="primary" icon="check" onClick={save}>{saved ? "Saved" : "Save rules"}</Button>
        </div>
      </div>

      <Card pad={0} style={{ overflow: "hidden", marginBottom: 16 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 8, padding: "13px 18px" }}><Icon name="package" size={15} color="var(--brand)" /><span style={{ fontSize: 13.5, fontWeight: 700, color: "var(--fg-strong)" }}>Standard item sizes</span></div>
        <div style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr 1fr 1fr 1fr", gap: 8, padding: "8px 18px", background: "var(--bg-mist)", borderTop: "1px solid var(--border)", borderBottom: "1px solid var(--border)", fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.6px", textTransform: "uppercase", color: "var(--fg-mute)" }}>
          <span>Type</span><span>Length (cm)</span><span>Width (cm)</span><span>Height (cm)</span><span>Weight (kg)</span>
        </div>
        {types.map((t, i) => { const d = r.itemDefaults[t] || { l: "", w: "", h: "", weight: "" }; return (
          <div key={t} style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr 1fr 1fr 1fr", gap: 8, padding: "8px 18px", borderTop: i ? "1px solid var(--border)" : "none", alignItems: "center" }}>
            <span style={{ fontSize: 13, fontWeight: 600, color: "var(--fg-strong)" }}>{t}</span>
            <TextInput type="number" value={d.l} onChange={v => setItem(t, "l", v)} mono />
            <TextInput type="number" value={d.w} onChange={v => setItem(t, "w", v)} mono />
            <TextInput type="number" value={d.h} onChange={v => setItem(t, "h", v)} mono />
            <TextInput type="number" value={d.weight} onChange={v => setItem(t, "weight", v)} mono />
          </div>
        ); })}
      </Card>

      <Card pad={0} style={{ overflow: "hidden", marginBottom: 16 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 8, padding: "13px 18px" }}><Icon name="truck" size={15} color="var(--brand)" /><span style={{ fontSize: 13.5, fontWeight: 700, color: "var(--fg-strong)" }}>Vehicle escalation bands</span></div>
        <div style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr 1fr", gap: 8, padding: "8px 18px", background: "var(--bg-mist)", borderTop: "1px solid var(--border)", borderBottom: "1px solid var(--border)", fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.6px", textTransform: "uppercase", color: "var(--fg-mute)" }}>
          <span>Vehicle</span><span>Max weight (kg)</span><span>Max volume (m³)</span>
        </div>
        {r.vehicleCaps.map((c, i) => (
          <div key={c.id} style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr 1fr", gap: 8, padding: "8px 18px", borderTop: i ? "1px solid var(--border)" : "none", alignItems: "center" }}>
            <span style={{ fontSize: 13, fontWeight: 600, color: "var(--fg-strong)" }}>{vname(c.id)}</span>
            <TextInput type="number" value={c.kg} onChange={v => setCap(c.id, "kg", v)} mono />
            <TextInput type="number" value={c.m3} onChange={v => setCap(c.id, "m3", v)} mono />
          </div>
        ))}
        <div style={{ padding: "11px 18px", borderTop: "1px solid var(--border)", fontSize: 12, color: "var(--fg-mute)" }}>Anything over the largest band ({vname(r.vehicleCaps[r.vehicleCaps.length - 1].id)}) escalates to a taxi-truck / phone quote.</div>
      </Card>

      <Card pad={18} style={{ marginBottom: 4 }}>
        <div style={{ fontSize: 13.5, fontWeight: 700, color: "var(--fg-strong)", marginBottom: 12 }}>Taxi-truck &amp; phone-quote rules</div>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 14 }}>
          <Field label="Taxi-truck minimum (hours)"><TextInput type="number" value={r.taxiTruck.minHours} onChange={v => setTaxi("minHours", v)} mono /></Field>
          <Field label="Taxi-truck hourly rate ($)"><TextInput type="number" value={r.taxiTruck.hourly} onChange={v => setTaxi("hourly", v)} mono /></Field>
          <Field label="Phone quote required over (kg)"><TextInput type="number" value={r.phoneOverKg} onChange={v => setPhone(v)} mono /></Field>
        </div>
      </Card>
    </div>
  );
}

/* ---------------- Settings shell ---------------- */
function CsrSettings({ users, roles, serviceAgents, announcements, onSaveAnn, onDeleteAnn, onSaveUser, onDeleteUser, onSaveAgent, onDeleteAgent }) {
  const [tab, setTab] = useStateSet("users");
  const [userModal, setUserModal] = useStateSet(false);
  const [userSeed, setUserSeed] = useStateSet(null);
  const [agentModal, setAgentModal] = useStateSet(false);
  const [agentSeed, setAgentSeed] = useStateSet(null);

  return (
    <div className="fade-up">
      <div style={{ marginBottom: 18 }}>
        <Eyebrow>Console</Eyebrow>
        <h1 style={{ margin: "9px 0 0", fontSize: 25, fontWeight: 700, letterSpacing: "-0.6px", color: "var(--fg-strong)" }}>Settings</h1>
        <p style={{ margin: "7px 0 0", fontSize: 14.5, color: "var(--fg-mute)" }}>Manage console users and their permission levels, and the service agents you allocate to interstate bookings.</p>
      </div>

      <SettingsTabs tab={tab} setTab={setTab} />

      {tab === "rules" && <RulesPanel />}

      {tab === "users" && (
        <UsersPanel users={users} roles={roles} onSaveUser={onSaveUser} onDeleteUser={onDeleteUser} onAdd={() => { setUserSeed(null); setUserModal(true); }} onEdit={u => { setUserSeed(u); setUserModal(true); }} />
      )}
      {tab === "agents" && (
        <AgentsPanel agents={serviceAgents} onEdit={a => { setAgentSeed(a); setAgentModal(true); }} onDeleteAgent={onDeleteAgent} onSaveAgent={onSaveAgent} onAdd={() => { setAgentSeed(null); setAgentModal(true); }} />
      )}

      {tab === "announce" && (
        <AnnouncementsPanel announcements={announcements} onSaveAnn={onSaveAnn} onDeleteAnn={onDeleteAnn} />
      )}

      <UserModal open={userModal} onClose={() => setUserModal(false)} roles={roles} seed={userSeed} onSave={u => { onSaveUser(u); setUserModal(false); }} />
      <AgentModal open={agentModal} onClose={() => setAgentModal(false)} seed={agentSeed} onSave={a => { onSaveAgent(a); setAgentModal(false); }} />
    </div>
  );
}

/* ---------------- Service Agents directory (top-level tab) ---------------- */
function CsrServiceAgents({ agents, onSaveAgent, onDeleteAgent }) {
  const [q, setQ] = useStateSet("");
  const [area, setArea] = useStateSet("all");
  const [modal, setModal] = useStateSet(false);
  const [seed, setSeed] = useStateSet(null);
  const counts = {}; agents.forEach(a => { (a.serviceAreas || (a.state ? [a.state] : [])).forEach(s => { counts[s] = (counts[s] || 0) + 1; }); });
  const areas = ["all", ...AU_STATES.filter(s => counts[s])];
  const filtered = agents.filter(a => {
    const aAreas = a.serviceAreas || (a.state ? [a.state] : []);
    if (area !== "all" && !aAreas.includes(area)) return false;
    if (q.trim()) { const t = q.trim().toLowerCase(); const hay = [a.name, a.city, a.contact, a.state, a.notes, ...(a.contacts || []).map(c => c.name)].join(" ").toLowerCase(); if (!hay.includes(t)) return false; }
    return true;
  });
  const openAdd = () => { setSeed(null); setModal(true); };
  const openEdit = (a) => { setSeed(a); setModal(true); };
  return (
    <div className="fade-up">
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-end", gap: 16, marginBottom: 18, flexWrap: "wrap" }}>
        <div>
          <Eyebrow>Operations</Eyebrow>
          <h1 style={{ margin: "9px 0 0", fontSize: 25, fontWeight: 700, letterSpacing: "-0.6px", color: "var(--fg-strong)" }}>Service agents</h1>
          <p style={{ margin: "7px 0 0", fontSize: 14.5, color: "var(--fg-mute)" }}>Destination-end partners who complete Next Flight deliveries. Filter by the area they service to find one fast, then allocate them from an interstate booking.</p>
        </div>
        <Button variant="primary" icon="plus" onClick={openAdd} style={{ flex: "none" }}>Add service agent</Button>
      </div>

      <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 16, flexWrap: "wrap" }}>
        <div style={{ display: "flex", gap: 6, flexWrap: "wrap" }}>
          {areas.map(s => {
            const on = area === s;
            const label = s === "all" ? "All areas" : s;
            const n = s === "all" ? agents.length : counts[s];
            return <button key={s} onClick={() => setArea(s)} style={{ display: "inline-flex", alignItems: "center", gap: 7, padding: "7px 13px", borderRadius: "var(--r-pill)", fontSize: 12.5, fontWeight: 600, border: "1px solid " + (on ? "var(--brand)" : "var(--border)"), background: on ? "var(--brand-soft)" : "var(--surface)", color: on ? "var(--brand)" : "var(--fg-mute)" }}>{label}<span style={{ fontFamily: "var(--font-mono)", fontSize: 11, fontWeight: 700, background: on ? "var(--brand)" : "var(--bg-mist-2)", color: on ? "#fff" : "var(--fg-mute)", padding: "1px 7px", borderRadius: 999 }}>{n}</span></button>;
          })}
        </div>
        <div style={{ position: "relative", flex: "1 1 220px", minWidth: 180, marginLeft: "auto" }}>
          <span style={{ position: "absolute", left: 11, top: "50%", transform: "translateY(-50%)", color: "var(--fg-mute)" }}><Icon name="search" size={14} /></span>
          <input value={q} onChange={e => setQ(e.target.value)} placeholder="Search agent, contact or city…" style={{ ...window.inputStyle, paddingLeft: 34, paddingTop: 9, paddingBottom: 9, fontSize: 13 }} />
        </div>
      </div>

      <div style={{ fontSize: 12.5, color: "var(--fg-mute)", marginBottom: 12 }}><strong style={{ color: "var(--fg-strong)" }}>{filtered.length}</strong> agent{filtered.length === 1 ? "" : "s"}{area !== "all" ? ` servicing ${area}` : ""}</div>

      {filtered.length === 0 ? (
        <Card pad={44} style={{ textAlign: "center", borderStyle: "dashed", background: "var(--bg-mist)" }}>
          <div style={{ width: 54, height: 54, borderRadius: "50%", background: "var(--surface)", display: "inline-flex", alignItems: "center", justifyContent: "center", margin: "0 auto 12px", color: "var(--fg-faint)" }}><Icon name="shield" size={24} /></div>
          <div style={{ fontSize: 15, fontWeight: 600, color: "var(--fg-strong)" }}>No agents in this area</div>
          <div style={{ fontSize: 13.5, color: "var(--fg-mute)", marginTop: 5 }}>Try another area, or add a service agent for it.</div>
        </Card>
      ) : (
        <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(300px, 1fr))", gap: 14 }}>
          {filtered.map(a => (
            <Card key={a.id} pad={0} style={{ overflow: "hidden", display: "flex", flexDirection: "column" }}>
              <div style={{ display: "flex", alignItems: "flex-start", gap: 12, padding: "16px 16px 12px" }}>
                <span style={{ width: 42, height: 42, borderRadius: 11, flex: "none", background: "var(--brand-soft)", color: "var(--brand)", display: "inline-flex", alignItems: "center", justifyContent: "center" }}><Icon name="shield" size={20} /></span>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 14.5, fontWeight: 700, color: "var(--fg-strong)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{a.name}</div>
                  <div style={{ fontSize: 12, color: "var(--fg-mute)" }}>{a.contact || "—"}</div>
                </div>
                {!a.active && <Badge tone="neutral">Inactive</Badge>}
              </div>
              <div style={{ display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap", padding: "0 16px 12px" }}>
                {(a.serviceAreas || (a.state ? [a.state] : [])).map((s, si) => (
                  <span key={s} style={{ display: "inline-flex", alignItems: "center", gap: 5, background: si === 0 ? "var(--accent-soft)" : "var(--bg-mist)", color: si === 0 ? "var(--accent-700)" : "var(--fg-body)", borderRadius: 999, padding: "4px 10px", fontSize: 12, fontWeight: 600 }}>
                    {si === 0 && <Icon name="map-pin" size={11} />}<span style={{ fontFamily: "var(--font-mono)", fontWeight: 700 }}>{s}</span>{si === 0 ? " " + a.city : ""}
                  </span>
                ))}
              </div>
              <div style={{ borderTop: "1px solid var(--border)", padding: "11px 16px", display: "flex", flexDirection: "column", gap: 6, background: "var(--bg-mist)" }}>
                <span style={{ display: "inline-flex", alignItems: "center", gap: 8, fontSize: 12.5, color: "var(--fg-body)", minWidth: 0 }}><Icon name="mail" size={13} color="var(--fg-mute)" style={{ flex: "none" }} /><span style={{ whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{a.email}</span></span>
                {(a.contacts && a.contacts.length ? a.contacts : (a.contact || a.phone ? [{ name: a.contact, phone: a.phone }] : [])).map((c, ci) => (
                  <span key={ci} style={{ display: "inline-flex", alignItems: "center", gap: 8, fontSize: 12.5, color: c.phone ? "var(--fg-body)" : "var(--fg-faint)" }}><Icon name={c.phone ? "message-square" : "user"} size={13} color={c.phone ? "var(--success, #1f8a5b)" : "var(--fg-faint)"} style={{ flex: "none" }} /><span style={{ minWidth: 0, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{c.name || "—"}{c.phone ? " · " : ""}<span style={{ fontFamily: "var(--font-mono)" }}>{c.phone || ""}</span></span></span>
                ))}
                {!(a.contacts && a.contacts.length) && !a.contact && !a.phone && <span style={{ display: "inline-flex", alignItems: "center", gap: 8, fontSize: 12.5, color: "var(--fg-faint)" }}><Icon name="message-square" size={13} style={{ flex: "none" }} /> No mobile — email only</span>}
                {a.notes && <span style={{ display: "flex", gap: 8, fontSize: 12, color: "var(--fg-mute)", lineHeight: 1.4, marginTop: 2 }}><Icon name="info" size={13} color="var(--fg-faint)" style={{ flex: "none", marginTop: 1 }} /><span>{a.notes}</span></span>}
              </div>
              <div style={{ display: "flex", gap: 8, padding: "11px 16px", marginTop: "auto" }}>
                <Button variant="secondary" size="sm" icon="pencil" onClick={() => openEdit(a)}>Edit</Button>
                <button onClick={() => onDeleteAgent(a.id)} title="Remove agent" style={{ marginLeft: "auto", width: 32, height: 32, borderRadius: 8, border: "1px solid var(--border)", background: "var(--surface)", color: "var(--fg-mute)", display: "inline-flex", alignItems: "center", justifyContent: "center", cursor: "pointer" }}><Icon name="trash-2" size={15} /></button>
              </div>
            </Card>
          ))}
        </div>
      )}

      <AgentModal open={modal} onClose={() => setModal(false)} seed={seed} onSave={a => { onSaveAgent(a); setModal(false); }} />
    </div>
  );
}

Object.assign(window, { CsrSettings, CsrServiceAgents });
