/* global React, I, S */
/* Pamp — Vendor (Business) portal */

const V_NAV = [
  { key: "dashboard", label: "Dashboard", icon: I.dashboard },
  { key: "appointments", label: "Appointments", icon: I.calendar, badge: "12" },
  { key: "services", label: "Services", icon: I.scissors },
  { key: "gallery", label: "Gallery", icon: I.sparkle },
  { key: "clients", label: "Clients", icon: I.users },
  { key: "staff", label: "Staff", icon: I.staff },
  { section: "Money" },
  { key: "wallet", label: "Wallets & earnings", icon: I.wallet },
  { key: "plan", label: "My plan", icon: I.crown },
  { section: "Insight" },
  { key: "reports", label: "Reports", icon: I.chart },
  { key: "support", label: "Support", icon: I.help },
  { key: "settings", label: "Settings", icon: I.settings },
];

function VendorApp({ collapsed, onToggle, onTheme, theme, onExit, session, onNavigate, currentPage }) {
  const page = currentPage || "dashboard";
  const setPage = onNavigate;
  return (
    <div className="shell" data-sidebar={collapsed ? "collapsed" : "expanded"}>
      <S.Sidebar
        items={V_NAV}
        current={page}
        onNav={setPage}
        collapsed={collapsed}
        footer={
          <button className="nav-item" onClick={onExit} style={{ width: "100%" }} data-tip="Sign out">
            <span className="ni-icon"><I.logout size={18} /></span>
            <span className="ni-label">Sign out</span>
          </button>
        }
      />
      <div className="main-col">
        <S.Topbar
          onToggleSidebar={onToggle}
          onTheme={onTheme}
          theme={theme}
          search="Search clients, appointments, services…"
          right={<>
            <S.IconBtn title="Messages" style={{ position: "relative" }}>
              <I.mail size={18} />
              <span style={{
                position: "absolute", top: 7, right: 7, width: 7, height: 7, borderRadius: "50%",
                background: "var(--accent)", boxShadow: "0 0 0 2px var(--bg)",
              }} />
            </S.IconBtn>
            <S.IconBtn title="Calendar"><I.calendar size={18} /></S.IconBtn>
          </>}
        />
        <main className="main-scroll">
          {page === "dashboard" && <VendorDashboard />}
          {page === "appointments" && <VendorCalendar />}
          {page === "services" && <VendorServices />}
          {page === "gallery" && <VendorGallery />}
          {page === "clients" && <VendorClients />}
          {page === "staff" && <VendorStaff />}
          {page === "wallet" && <VendorWallet />}
          {page === "plan" && <VendorPlan />}
          {page === "reports" && <VendorReports />}
          {page === "support" && <VendorSupport />}
          {page === "settings" && <VendorSettings />}
        </main>
      </div>
    </div>
  );
}

/* ====================================================================
   VENDOR — DASHBOARD
   ==================================================================== */
function VendorDashboard() {
  const [apptOpen, setApptOpen] = React.useState(false);
  return (
    <div className="page-enter">
      <window.DemoBanner feature="vendor dashboard" />
      <S.PageHead
        eyebrow="Maison Color & Co. · Paris, FR"
        title="Today is shaping up well."
        sub="12 appointments booked, 1 chair empty 2–3 PM. Want to fill it?"
        right={<>
          <S.Btn variant="outline" size="sm" icon={<I.calendar size={14} />}>Today</S.Btn>
          <S.Btn variant="primary" size="sm" icon={<I.plus size={14} />} onClick={() => setApptOpen(true)}>New appointment</S.Btn>
        </>}
      />

      {/* KPI strip — asymmetric */}
      <div style={{ display: "grid", gridTemplateColumns: "2.2fr 1fr 1fr 1fr", gap: 20, marginBottom: 20 }}>
        <div className="card" style={{ display: "flex", flexDirection: "column", justifyContent: "space-between", minHeight: 180 }}>
          <div className="row between">
            <div className="eyebrow">Today’s revenue</div>
            <S.Chip tone="pos">+18% vs avg</S.Chip>
          </div>
          <div>
            <div className="display" style={{ fontSize: 56, letterSpacing: "-0.035em", lineHeight: 1 }}>$1,840</div>
            <div className="muted tiny" style={{ marginTop: 6 }}>From 12 bookings · 8 paid, 4 pending</div>
          </div>
          <div className="row" style={{ gap: 12, marginTop: 10 }}>
            <div className="row-tight tiny"><span className="dot dot-pos" /> Card $1,420</div>
            <div className="row-tight tiny"><span className="dot" style={{ background: "var(--ink-3)" }} /> Cash $284</div>
            <div className="row-tight tiny"><span className="dot dot-info" /> Pamp $136</div>
          </div>
        </div>
        <S.Metric label="Bookings" value="12" delta="+2" />
        <S.Metric label="New clients" value="4" delta="+1" />
        <S.Metric label="Avg. ticket" value="$153" delta="+$8" />
      </div>

      <div className="grid-12" style={{ marginBottom: 20 }}>
        {/* day timeline */}
        <div className="card" style={{ gridColumn: "span 8" }}>
          <div className="row between" style={{ marginBottom: 18 }}>
            <div>
              <div className="h3">Today’s schedule</div>
              <div className="muted tiny" style={{ marginTop: 4 }}>Sunday, Feb 2 · 3 stylists · 12 appointments</div>
            </div>
            <div className="row" style={{ gap: 6 }}>
              <S.Btn variant="ghost" size="sm" icon={<I.chevR size={12} style={{ transform: "rotate(180deg)" }} />}>Prev</S.Btn>
              <S.Btn variant="outline" size="sm">Today</S.Btn>
              <S.Btn variant="ghost" size="sm" iconRight={<I.chevR size={12} />}>Next</S.Btn>
            </div>
          </div>
          <DayTimeline />
        </div>

        {/* next up */}
        <div className="card" style={{ gridColumn: "span 4" }}>
          <div className="h3" style={{ marginBottom: 4 }}>Next up</div>
          <div className="muted tiny" style={{ marginBottom: 18 }}>in 4 hours · 14 minutes</div>
          <div style={{ padding: 18, background: "var(--accent-soft)", borderRadius: 14, marginBottom: 12 }}>
            <div className="row between">
              <S.Chip tone="accent">VIP · Gold</S.Chip>
              <span className="mono tiny" style={{ color: "var(--accent-ink)" }}>2:30 PM</span>
            </div>
            <div className="row" style={{ marginTop: 12, gap: 12 }}>
              <S.Avatar name="Amelia Brooks" size="lg" />
              <div>
                <div style={{ fontWeight: 500 }}>Amelia Brooks</div>
                <div className="muted tiny">Full color &amp; cut · 90 min</div>
              </div>
            </div>
            <div className="divider" style={{ margin: "14px 0", borderColor: "oklch(50% 0.13 290 / 0.20)" }} />
            <div className="muted tiny" style={{ lineHeight: 1.5, marginBottom: 12 }}>
              Last visit Dec 14 · prefers cooler blondes · allergic to PPD · likes oat milk in tea.
            </div>
            <div className="row" style={{ gap: 6 }}>
              <S.Btn variant="primary" size="sm" style={{ flex: 1 }}>Check in</S.Btn>
              <S.IconBtn><I.phone size={14} /></S.IconBtn>
              <S.IconBtn><I.mail size={14} /></S.IconBtn>
            </div>
          </div>
          <div className="muted tiny" style={{ marginBottom: 8 }}>Then today</div>
          {[
            { t: "4:00 PM", n: "Marcus Chen", s: "Beard trim", st: "—" },
            { t: "5:15 PM", n: "Priya Shah", s: "Gel manicure", st: "Léa" },
          ].map((u, i) => (
            <div key={i} className="row" style={{ padding: "8px 0", borderTop: "1px solid var(--border)" }}>
              <span className="mono tiny" style={{ width: 56, color: "var(--ink-3)" }}>{u.t}</span>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 13 }}>{u.n}</div>
                <div className="muted tiny">{u.s} · {u.st}</div>
              </div>
              <S.IconBtn><I.chevR size={14} /></S.IconBtn>
            </div>
          ))}
        </div>

        {/* weekly bookings */}
        <div className="card" style={{ gridColumn: "span 5" }}>
          <div className="row between" style={{ marginBottom: 4 }}>
            <div className="h3">This week</div>
            <S.Btn variant="ghost" size="sm" iconRight={<I.chevD size={12} />}>Bookings</S.Btn>
          </div>
          <div className="display" style={{ fontSize: 32, marginTop: 8 }}>84 <span className="muted" style={{ fontSize: 14, fontWeight: 400 }}>bookings</span></div>
          <div className="row-tight" style={{ marginBottom: 22 }}>
            <S.Chip tone="pos">+12%</S.Chip>
            <span className="muted tiny">vs last week</span>
          </div>
          <S.BarChart
            data={[8, 12, 14, 11, 18, 15, 6]}
            labels={["M", "T", "W", "T", "F", "S", "S"]}
            activeIndex={4}
            height={170}
          />
        </div>

        {/* capacity */}
        <div className="card" style={{ gridColumn: "span 4" }}>
          <div className="h3" style={{ marginBottom: 14 }}>Chair utilization</div>
          <div className="row" style={{ justifyContent: "center", marginBottom: 14 }}>
            <S.Gauge value={92} size={170} label="92%" sub="this week" segments={32} />
          </div>
          <div className="col" style={{ gap: 8 }}>
            {[
              { l: "Léa M.", v: 96, c: "var(--accent)" },
              { l: "Camille R.", v: 88, c: "var(--ink)" },
              { l: "Inès K.", v: 92, c: "var(--info)" },
            ].map((r) => (
              <div key={r.l} className="row" style={{ gap: 10 }}>
                <span className="dot" style={{ background: r.c }} />
                <span style={{ flex: 1, fontSize: 13 }}>{r.l}</span>
                <div className="bar" style={{ width: 80 }}><span style={{ width: `${r.v}%`, background: r.c }} /></div>
                <span className="mono tiny" style={{ width: 36, textAlign: "right" }}>{r.v}%</span>
              </div>
            ))}
          </div>
        </div>

        {/* top services */}
        <div className="card" style={{ gridColumn: "span 3" }}>
          <div className="h3" style={{ marginBottom: 18 }}>Top services</div>
          <div className="col" style={{ gap: 14 }}>
            {[
              { l: "Full color", v: 38, c: "var(--accent)" },
              { l: "Cut + style", v: 28, c: "var(--ink)" },
              { l: "Balayage", v: 18, c: "var(--info)" },
              { l: "Treatment", v: 12, c: "var(--warn)" },
              { l: "Other", v: 4, c: "var(--ink-3)" },
            ].map((r) => (
              <div key={r.l}>
                <div className="row between" style={{ marginBottom: 4 }}>
                  <span className="tiny">{r.l}</span>
                  <span className="mono tiny muted">{r.v}%</span>
                </div>
                <div className="bar"><span style={{ width: `${r.v * 2.5}%`, background: r.c }} /></div>
              </div>
            ))}
          </div>
        </div>

        {/* reviews */}
        <div className="card" style={{ gridColumn: "span 7" }}>
          <div className="row between" style={{ marginBottom: 18 }}>
            <div>
              <div className="h3">Recent reviews</div>
              <div className="row-tight" style={{ marginTop: 6 }}>
                <span className="display" style={{ fontSize: 22 }}>4.9</span>
                <div className="row-tight">
                  {[1, 2, 3, 4, 5].map(i => <I.star key={i} size={12} color="var(--warn)" fill="var(--warn)" />)}
                </div>
                <span className="muted tiny">· 1,842 reviews</span>
              </div>
            </div>
            <S.Btn variant="outline" size="sm">Reply queue · 3</S.Btn>
          </div>
          <div className="grid-2">
            {[
              { n: "Sofia Romano", r: 5, t: "Léa is an absolute magician. Best balayage I have ever had — already booked for March.", ago: "2d ago", v: "Color" },
              { n: "Daniel Park", r: 5, t: "The atmosphere is calm and Camille really listened to what I wanted.", ago: "3d ago", v: "Cut" },
            ].map((r, i) => (
              <div key={i} style={{ padding: 14, border: "1px solid var(--border)", borderRadius: 12 }}>
                <div className="row between">
                  <div className="row-tight"><S.Avatar name={r.n} size="sm" /><span style={{ fontSize: 13, fontWeight: 500 }}>{r.n}</span></div>
                  <div className="row-tight" style={{ gap: 2 }}>
                    {[1, 2, 3, 4, 5].map(s => <I.star key={s} size={10} color="var(--warn)" fill="var(--warn)" />)}
                  </div>
                </div>
                <div style={{ fontSize: 13, marginTop: 8, lineHeight: 1.5, color: "var(--ink-2)" }}>“{r.t}”</div>
                <div className="row between" style={{ marginTop: 10 }}>
                  <span className="muted tiny">{r.ago} · {r.v}</span>
                  <S.Btn variant="ghost" size="sm">Reply</S.Btn>
                </div>
              </div>
            ))}
          </div>
        </div>

        {/* fill the gap */}
        <div className="card" style={{ gridColumn: "span 5", background: "var(--accent-soft)", border: "1px solid transparent", color: "var(--accent-ink)" }}>
          <S.Chip tone="accent" style={{ background: "white" }}>Empty chair · 2–3 PM</S.Chip>
          <div className="display" style={{ fontSize: 28, lineHeight: 1.15, letterSpacing: "-0.025em", margin: "16px 0 12px" }}>
            Fill a 60-min slot today with a smart promo?
          </div>
          <div style={{ fontSize: 13, marginBottom: 18, opacity: 0.85 }}>
            We can text 84 dormant regulars 20% off any service this afternoon. Median fill rate: 42%.
          </div>
          <div className="row" style={{ gap: 8 }}>
            <S.Btn variant="primary" size="sm" style={{ background: "var(--accent-ink)", color: "white" }} iconRight={<I.sparkle size={14} />}>Run smart promo</S.Btn>
            <S.Btn variant="ghost" size="sm">Dismiss</S.Btn>
          </div>
        </div>
      </div>

      <NewAppointmentModal open={apptOpen} onClose={() => setApptOpen(false)} onCreate={() => {}} />
    </div>
  );
}

function DayTimeline() {
  const events = [
    { stylist: 0, start: 9, dur: 1, client: "Olivia W.", svc: "Cut", tone: "accent" },
    { stylist: 0, start: 11, dur: 1.5, client: "Mae P.", svc: "Balayage", tone: "pos" },
    { stylist: 0, start: 14.5, dur: 1.5, client: "Amelia B.", svc: "Color · VIP", tone: "accent" },
    { stylist: 0, start: 17, dur: 0.75, client: "Marcus C.", svc: "Trim", tone: "info" },
    { stylist: 1, start: 9.5, dur: 1.25, client: "Lila R.", svc: "Cut + style", tone: "accent" },
    { stylist: 1, start: 12, dur: 1, client: "Eve S.", svc: "Treatment", tone: "warn" },
    { stylist: 1, start: 14, dur: 2, client: "Tara N.", svc: "Color", tone: "pos" },
    { stylist: 2, start: 10, dur: 2, client: "Iris M.", svc: "Full color", tone: "pos" },
    { stylist: 2, start: 13, dur: 1.25, client: "Maya H.", svc: "Cut", tone: "info" },
    { stylist: 2, start: 17.25, dur: 1, client: "Priya S.", svc: "Gel mani", tone: "accent" },
  ];
  const hours = Array.from({ length: 11 }, (_, i) => i + 9); // 9 to 19
  const stylists = ["Léa M.", "Camille R.", "Inès K."];
  const HOUR_PX = 56;

  return (
    <div style={{ display: "grid", gridTemplateColumns: "60px repeat(3, 1fr)", border: "1px solid var(--border)", borderRadius: 14, overflow: "hidden", background: "var(--surface)" }}>
      {/* header row */}
      <div style={{ borderBottom: "1px solid var(--border)", background: "var(--surface-2)" }}></div>
      {stylists.map((s, i) => (
        <div key={s} style={{ padding: "12px 14px", borderBottom: "1px solid var(--border)", borderLeft: i === 0 ? undefined : "1px solid var(--border)", background: "var(--surface-2)" }}>
          <div className="row-tight">
            <S.Avatar name={s} size="sm" />
            <div>
              <div style={{ fontSize: 12, fontWeight: 500 }}>{s}</div>
              <div className="muted tiny">{i === 0 ? "Senior · color" : i === 1 ? "Senior · cuts" : "Specialist"}</div>
            </div>
          </div>
        </div>
      ))}
      {/* time column */}
      <div style={{ position: "relative" }}>
        {hours.map((h, i) => (
          <div key={h} style={{ height: HOUR_PX, padding: "4px 8px", borderTop: i === 0 ? undefined : "1px solid var(--border)", textAlign: "right" }}>
            <span className="mono tiny muted">{h}:00</span>
          </div>
        ))}
      </div>
      {stylists.map((_, si) => (
        <div key={si} style={{ position: "relative", borderLeft: "1px solid var(--border)" }}>
          {hours.map((h, i) => (
            <div key={h} style={{ height: HOUR_PX, borderTop: i === 0 ? undefined : "1px solid var(--border)", borderBottom: "1px dashed transparent" }} />
          ))}
          {/* now line in column 0 */}
          {si === 1 && <div style={{
            position: "absolute", top: (14.2 - 9) * HOUR_PX, left: 0, right: 0, height: 2, background: "var(--accent)",
            boxShadow: "0 0 0 4px var(--accent-glow)", zIndex: 5,
          }}>
            <span style={{ position: "absolute", left: -6, top: -4, width: 10, height: 10, borderRadius: 999, background: "var(--accent)" }} />
            <span style={{ position: "absolute", right: 4, top: -16, fontSize: 10, fontFamily: "var(--font-mono)", color: "var(--accent-ink)" }}>NOW · 2:12</span>
          </div>}
          {events.filter(e => e.stylist === si).map((e, i) => {
            const top = (e.start - 9) * HOUR_PX;
            const height = e.dur * HOUR_PX - 4;
            const colorBg = e.tone === "accent" ? "var(--accent-soft)" : e.tone === "pos" ? "var(--pos-soft)" : e.tone === "warn" ? "var(--warn-soft)" : "var(--info-soft)";
            const colorFg = e.tone === "accent" ? "var(--accent-ink)" : `var(--${e.tone})`;
            return (
              <div key={i} style={{
                position: "absolute", top: top + 2, left: 6, right: 6, height,
                background: colorBg, borderLeft: `3px solid ${colorFg}`,
                borderRadius: 8, padding: "8px 10px", overflow: "hidden",
              }}>
                <div style={{ fontSize: 11.5, fontWeight: 600, color: colorFg }}>{e.client}</div>
                <div className="tiny" style={{ color: colorFg, opacity: 0.85 }}>{e.svc}</div>
                <div className="mono tiny" style={{ color: colorFg, opacity: 0.7, marginTop: 2 }}>
                  {Math.floor(e.start)}:{String(((e.start % 1) * 60) | 0).padStart(2, "0")} · {e.dur * 60}m
                </div>
              </div>
            );
          })}
        </div>
      ))}
    </div>
  );
}

/* ====================================================================
   VENDOR — CALENDAR / APPOINTMENTS (List + Week)
   ==================================================================== */
function VendorCalendar() {
  const [view, setView] = React.useState("list");
  const [selected, setSelected] = React.useState(null);
  const [apptOpen, setApptOpen] = React.useState(false);

  return (
    <div className="page-enter">
      <window.DemoBanner feature="appointments calendar" />
      <S.PageHead
        eyebrow="84 booked · 12 today"
        title="Appointments"
        sub={view === "list" ? "All scheduled appointments — click a row to see details." : "Week of Feb 2 – Feb 8"}
        right={<>
          <div className="row-tight" style={{ background: "var(--surface-3)", padding: 3, borderRadius: 999 }}>
            {[
              { k: "list", l: "List", ic: <I.list size={12} /> },
              { k: "day", l: "Day", ic: <I.calendar size={12} /> },
              { k: "week", l: "Week", ic: <I.calendar size={12} /> },
              { k: "month", l: "Month", ic: <I.calendar size={12} /> },
            ].map(v => (
              <button key={v.k} onClick={() => { setView(v.k); setSelected(null); }}
                className={`btn btn-sm ${view === v.k ? "btn-primary" : "btn-ghost"}`}
                style={view === v.k ? {} : { background: "transparent" }}
              >{v.ic} {v.l}</button>
            ))}
          </div>
          <S.Btn variant="primary" size="sm" icon={<I.plus size={14} />} onClick={() => setApptOpen(true)}>New appointment</S.Btn>
        </>}
      />
      {view === "list" && <AppointmentsList selected={selected} onSelect={setSelected} />}
      {view !== "list" && <WeekCalendar />}

      <NewAppointmentModal open={apptOpen} onClose={() => setApptOpen(false)} onCreate={() => {}} />
    </div>
  );
}

const APPOINTMENTS = [
  { id: "PB-28401", group: "Today · Sunday 2 Feb", time: "2:30 PM", dur: 90, client: "Amelia Brooks", clientTier: "Gold", service: "Full color & cut", staff: "Léa M.", status: "Confirmed", tone: "pos", total: 184, paid: true, notes: "Allergic to PPD. Prefers cooler blondes. Oat milk in tea, please." },
  { id: "PB-28402", group: "Today · Sunday 2 Feb", time: "4:00 PM", dur: 30, client: "Marcus Chen", clientTier: "Silver", service: "Beard trim", staff: "Camille R.", status: "Confirmed", tone: "pos", total: 38, paid: true },
  { id: "PB-28403", group: "Today · Sunday 2 Feb", time: "5:15 PM", dur: 60, client: "Priya Shah", clientTier: "Gold", service: "Gel manicure", staff: "Inès K.", status: "Pending", tone: "warn", total: 64, paid: false },
  { id: "PB-28404", group: "Tomorrow · Monday 3 Feb", time: "10:00 AM", dur: 60, client: "Sofia Romano", clientTier: "Platinum", service: "Deep tissue", staff: "Léa M.", status: "Confirmed", tone: "pos", total: 142, paid: false },
  { id: "PB-28405", group: "Tomorrow · Monday 3 Feb", time: "11:30 AM", dur: 75, client: "Idris Ahmed", clientTier: "Silver", service: "HydraFacial", staff: "Camille R.", status: "Cancelled", tone: "neg", total: 0, paid: false },
  { id: "PB-28406", group: "Tomorrow · Monday 3 Feb", time: "1:00 PM", dur: 75, client: "Daniel Park", clientTier: "Silver", service: "Cut + style", staff: "Camille R.", status: "Confirmed", tone: "pos", total: 96, paid: false },
  { id: "PB-28410", group: "Wednesday 5 Feb", time: "11:00 AM", dur: 120, client: "Iris Mendez", clientTier: "Gold", service: "Balayage", staff: "Léa M.", status: "Confirmed", tone: "pos", total: 285, paid: true },
];

function AppointmentsList({ selected, onSelect }) {
  const selectedAppt = selected ? APPOINTMENTS.find(a => a.id === selected) : null;
  const groups = APPOINTMENTS.reduce((acc, a) => { (acc[a.group] = acc[a.group] || []).push(a); return acc; }, {});

  return (
    <div style={{ display: "grid", gridTemplateColumns: selectedAppt ? "1fr 380px" : "1fr", gap: 20, alignItems: "flex-start" }}>
      <div className="card card-flush">
        <div className="row" style={{ padding: 16, gap: 10, borderBottom: "1px solid var(--border)" }}>
          <S.Input icon={<I.search size={15} />} placeholder="Search by client, service, ID…" style={{ flex: 1, maxWidth: 320 }} />
          <S.Btn variant="ghost" size="sm" iconRight={<I.chevD size={12} />}>Status: All</S.Btn>
          <S.Btn variant="ghost" size="sm" iconRight={<I.chevD size={12} />}>Staff: Any</S.Btn>
          <div className="spacer" />
          <span className="muted tiny">{APPOINTMENTS.length} appointments</span>
        </div>

        {Object.entries(groups).map(([groupLabel, list]) => (
          <div key={groupLabel}>
            <div style={{
              padding: "14px 22px", background: "var(--surface-2)",
              borderBottom: "1px solid var(--border)",
              display: "flex", justifyContent: "space-between", alignItems: "center",
            }}>
              <div className="eyebrow">{groupLabel}</div>
              <span className="muted tiny">{list.length} {list.length === 1 ? "appointment" : "appointments"}</span>
            </div>
            <table className="tbl">
              <tbody>
                {list.map((a) => {
                  const isOpen = selected === a.id;
                  return (
                    <tr key={a.id} onClick={() => onSelect(isOpen ? null : a.id)}
                      style={{ cursor: "pointer", background: isOpen ? "var(--accent-soft)" : undefined }}>
                      <td style={{ width: 90, paddingLeft: 22 }}>
                        <div className="mono" style={{ fontSize: 14, fontWeight: 500 }}>{a.time}</div>
                        <div className="muted tiny">{a.dur} min</div>
                      </td>
                      <td>
                        <div className="row-tight">
                          <S.Avatar name={a.client} size="sm" />
                          <div>
                            <div style={{ fontWeight: 500 }}>{a.client}</div>
                            <div className="muted tiny">{a.id} · {a.clientTier}</div>
                          </div>
                        </div>
                      </td>
                      <td>
                        <div style={{ fontSize: 13 }}>{a.service}</div>
                        <div className="muted tiny">with {a.staff}</div>
                      </td>
                      <td><S.Chip tone={a.tone}>{a.status}</S.Chip></td>
                      <td className="col-num">
                        <div className="mono" style={{ fontWeight: 500 }}>${a.total}</div>
                        <div className="tiny" style={{ color: a.paid ? "var(--pos)" : "var(--ink-3)" }}>{a.paid ? "Paid" : "Due"}</div>
                      </td>
                      <td style={{ width: 50, paddingRight: 22 }}>
                        <S.IconBtn><I.chevR size={14} /></S.IconBtn>
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        ))}
      </div>

      {selectedAppt && <AppointmentDetail appt={selectedAppt} onClose={() => onSelect(null)} />}
    </div>
  );
}

function AppointmentDetail({ appt, onClose }) {
  return (
    <div className="card" style={{ padding: 0, position: "sticky", top: 0 }}>
      <div style={{ padding: "20px 22px 18px", borderBottom: "1px solid var(--border)" }}>
        <div className="row between">
          <div className="eyebrow">{appt.id}</div>
          <S.IconBtn onClick={onClose}><I.x size={14} /></S.IconBtn>
        </div>
        <div className="display" style={{ fontSize: 22, marginTop: 8, letterSpacing: "-0.02em" }}>{appt.service}</div>
        <div className="muted tiny" style={{ marginTop: 4 }}>{appt.group.replace("Today · ", "").replace("Tomorrow · ", "")} · {appt.time}</div>
        <div className="row" style={{ gap: 6, marginTop: 12 }}>
          <S.Chip tone={appt.tone}>{appt.status}</S.Chip>
          <S.Chip tone={appt.paid ? "pos" : ""}>{appt.paid ? "Paid in full" : "Due at visit"}</S.Chip>
        </div>
      </div>

      <div style={{ padding: 22, borderBottom: "1px solid var(--border)" }}>
        <div className="eyebrow" style={{ marginBottom: 10 }}>Client</div>
        <div className="row" style={{ gap: 12 }}>
          <S.Avatar name={appt.client} size="lg" />
          <div style={{ flex: 1 }}>
            <div style={{ fontWeight: 500 }}>{appt.client}</div>
            <div className="row-tight">
              <S.Chip tone={appt.clientTier === "Platinum" ? "accent" : appt.clientTier === "Gold" ? "warn" : ""}>{appt.clientTier}</S.Chip>
            </div>
          </div>
        </div>
        <div className="row" style={{ marginTop: 14, gap: 6 }}>
          <S.Btn variant="outline" size="sm" icon={<I.mail size={12} />} style={{ flex: 1 }}>Message</S.Btn>
          <S.Btn variant="outline" size="sm" icon={<I.phone size={12} />} style={{ flex: 1 }}>Call</S.Btn>
        </div>
      </div>

      <div style={{ padding: 22, borderBottom: "1px solid var(--border)" }}>
        <div className="eyebrow" style={{ marginBottom: 12 }}>Service</div>
        <DetailRow label="Service" value={appt.service} />
        <DetailRow label="Duration" value={`${appt.dur} minutes`} />
        <DetailRow label="With" value={appt.staff} />
        <DetailRow label="Location" value="Maison Color · Chair 2" />
      </div>

      <div style={{ padding: 22, borderBottom: "1px solid var(--border)" }}>
        <div className="eyebrow" style={{ marginBottom: 12 }}>Payment</div>
        <DetailRow label="Service" value={`$${appt.total}`} mono />
        <DetailRow label="Platform fee" value="−$6.44" mono />
        <DetailRow label="Net to you" value={`$${(appt.total * 0.965).toFixed(2)}`} mono strong />
      </div>

      {appt.notes && <div style={{ padding: 22, borderBottom: "1px solid var(--border)" }}>
        <div className="eyebrow" style={{ marginBottom: 10 }}>Notes</div>
        <div style={{ padding: 12, background: "var(--surface-2)", borderRadius: 10, fontSize: 13, lineHeight: 1.5 }}>
          {appt.notes}
        </div>
      </div>}

      <div style={{ padding: 22, display: "flex", flexDirection: "column", gap: 8 }}>
        {appt.status === "Cancelled" ? <>
          <S.Btn variant="primary" icon={<I.plus size={14} />}>Rebook client</S.Btn>
        </> : <>
          <S.Btn variant="primary" iconRight={<I.arrowR size={14} />}>Check in client</S.Btn>
          <S.Btn variant="outline" size="sm">Reschedule</S.Btn>
          <S.Btn variant="ghost" size="sm" style={{ color: "var(--neg)" }}>Cancel appointment</S.Btn>
        </>}
      </div>
    </div>
  );
}

function DetailRow({ label, value, mono, strong }) {
  return (
    <div className="row between" style={{ padding: "8px 0" }}>
      <span className="muted tiny">{label}</span>
      <span className={mono ? "mono" : ""} style={{ fontSize: 13, fontWeight: strong ? 600 : 400 }}>{value}</span>
    </div>
  );
}

function WeekCalendar() {
  const hours = Array.from({ length: 11 }, (_, i) => i + 9);
  const days = ["Mon 2", "Tue 3", "Wed 4", "Thu 5", "Fri 6", "Sat 7", "Sun 8"];
  const events = [
    { d: 0, s: 10, dur: 1.5, c: "Olivia W.", svc: "Cut", t: "accent" },
    { d: 0, s: 14, dur: 1, c: "Mae P.", svc: "Trim", t: "info" },
    { d: 1, s: 11, dur: 2, c: "Sofia R.", svc: "Color", t: "accent" },
    { d: 2, s: 9, dur: 1.5, c: "Iris M.", svc: "Balayage", t: "pos" },
    { d: 2, s: 14.5, dur: 1.5, c: "Amelia B.", svc: "VIP color", t: "accent" },
    { d: 3, s: 10, dur: 1, c: "Marcus C.", svc: "Cut", t: "info" },
    { d: 3, s: 15, dur: 2, c: "Tara N.", svc: "Color", t: "pos" },
    { d: 4, s: 9.5, dur: 1.25, c: "Lila R.", svc: "Style", t: "warn" },
    { d: 4, s: 13, dur: 1.5, c: "Eve S.", svc: "Treatment", t: "warn" },
    { d: 4, s: 17, dur: 1, c: "Priya S.", svc: "Mani", t: "info" },
    { d: 5, s: 11, dur: 3, c: "Maya H.", svc: "Full day", t: "accent" },
    { d: 5, s: 15, dur: 1.5, c: "Daniel P.", svc: "Cut", t: "pos" },
    { d: 6, s: 12, dur: 2, c: "Idris A.", svc: "Color", t: "accent" },
  ];
  const HOUR = 48;
  return (
    <div className="card" style={{ padding: 0, overflow: "hidden" }}>
      <div style={{ display: "grid", gridTemplateColumns: "60px repeat(7, 1fr)", background: "var(--surface-2)", borderBottom: "1px solid var(--border)" }}>
        <div />
        {days.map((d, i) => (
          <div key={d} style={{ padding: "12px 8px", textAlign: "center", borderLeft: "1px solid var(--border)" }}>
            <div className="mono tiny muted">{d.split(" ")[0]}</div>
            <div className="display" style={{ fontSize: 18, marginTop: 2, color: i === 0 ? "var(--accent)" : undefined }}>{d.split(" ")[1]}</div>
          </div>
        ))}
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "60px repeat(7, 1fr)", position: "relative" }}>
        <div>
          {hours.map((h, i) => (
            <div key={h} style={{ height: HOUR, borderTop: i === 0 ? undefined : "1px solid var(--border)", padding: "2px 6px", textAlign: "right" }}>
              <span className="mono tiny muted">{h}:00</span>
            </div>
          ))}
        </div>
        {days.map((_, di) => (
          <div key={di} style={{ position: "relative", borderLeft: "1px solid var(--border)" }}>
            {hours.map((h, i) => (
              <div key={h} style={{ height: HOUR, borderTop: i === 0 ? undefined : "1px solid var(--border)" }} />
            ))}
            {events.filter(e => e.d === di).map((e, i) => {
              const top = (e.s - 9) * HOUR;
              const height = e.dur * HOUR - 4;
              const bg = e.t === "accent" ? "var(--accent-soft)" : e.t === "pos" ? "var(--pos-soft)" : e.t === "warn" ? "var(--warn-soft)" : "var(--info-soft)";
              const fg = e.t === "accent" ? "var(--accent-ink)" : `var(--${e.t})`;
              return (
                <div key={i} style={{
                  position: "absolute", top: top + 2, left: 4, right: 4, height,
                  background: bg, borderLeft: `3px solid ${fg}`, borderRadius: 6,
                  padding: "6px 8px", overflow: "hidden",
                }}>
                  <div style={{ fontSize: 11, fontWeight: 600, color: fg }}>{e.c}</div>
                  <div className="tiny" style={{ color: fg, opacity: 0.8 }}>{e.svc}</div>
                </div>
              );
            })}
          </div>
        ))}
      </div>
    </div>
  );
}

/* ====================================================================
   VENDOR — SERVICES
   ==================================================================== */
function VendorServices() {
  const [services, setServices] = React.useState([
    { cat: "Color", name: "Full single-process color", dur: 90, price: 145, bookings: 480, active: true },
    { cat: "Color", name: "Balayage · long hair", dur: 180, price: 285, bookings: 312, active: true },
    { cat: "Color", name: "Root touch-up", dur: 60, price: 95, bookings: 612, active: true },
    { cat: "Cut", name: "Cut & blowout", dur: 75, price: 110, bookings: 820, active: true },
    { cat: "Cut", name: "Bang trim", dur: 15, price: 25, bookings: 420, active: true },
    { cat: "Treatment", name: "K18 bond repair", dur: 30, price: 60, bookings: 180, active: true },
    { cat: "Treatment", name: "Olaplex add-on", dur: 20, price: 40, bookings: 220, active: false },
  ]);
  const [addOpen, setAddOpen] = React.useState(false);
  const activeCount = services.filter((s) => s.active).length;
  const draftCount = services.length - activeCount;

  const addService = (svc) => {
    setServices((prev) => [svc, ...prev]);
    setAddOpen(false);
  };

  return (
    <div className="page-enter">
      <window.DemoBanner feature="services CRUD" />
      <S.PageHead eyebrow={`${activeCount} active · ${draftCount} draft${draftCount === 1 ? "" : "s"}`} title="Services" sub="Your menu. Reorder, edit, and pause anytime."
        right={<>
          <S.Btn variant="outline" size="sm" icon={<I.list size={14} />}>Categories</S.Btn>
          <S.Btn variant="primary" size="sm" icon={<I.plus size={14} />} onClick={() => setAddOpen(true)}>New service</S.Btn>
        </>}
      />

      <div className="card card-flush">
        <div className="row" style={{ padding: 16, gap: 10 }}>
          <S.Input icon={<I.search size={15} />} placeholder="Search services" style={{ flex: 1, maxWidth: 320 }} />
          <S.Btn variant="ghost" size="sm" iconRight={<I.chevD size={12} />}>Category</S.Btn>
          <S.Btn variant="ghost" size="sm" iconRight={<I.chevD size={12} />}>Status</S.Btn>
          <div className="spacer" />
          <span className="muted tiny">Drag rows to reorder</span>
        </div>
        <table className="tbl">
          <thead>
            <tr>
              <th style={{ width: 30 }}></th>
              <th>Service</th>
              <th>Category</th>
              <th>Duration</th>
              <th className="col-num">Price</th>
              <th className="col-num">Bookings</th>
              <th>Status</th>
              <th />
            </tr>
          </thead>
          <tbody>
            {services.map((s, i) => (
              <tr key={i}>
                <td><I.list size={14} color="var(--ink-4)" /></td>
                <td>
                  <div className="row-tight" style={{ gap: 8 }}>
                    <span style={{ fontWeight: 500 }}>{s.name}</span>
                    {s.bookings === 0 && <S.Chip tone="accent">New</S.Chip>}
                  </div>
                  {s.desc && <div className="muted tiny" style={{ marginTop: 2 }}>{s.desc}</div>}
                </td>
                <td><S.Chip tone={s.cat === "Color" ? "accent" : s.cat === "Cut" ? "info" : "warn"}>{s.cat}</S.Chip></td>
                <td className="mono">{s.dur} min</td>
                <td className="col-num mono" style={{ fontWeight: 500 }}>${s.price}</td>
                <td className="col-num mono muted">{s.bookings.toLocaleString()}</td>
                <td><S.Chip tone={s.active ? "pos" : "warn"}>{s.active ? "Active" : "Draft"}</S.Chip></td>
                <td><S.IconBtn><I.ellipsis size={16} /></S.IconBtn></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      <NewServiceModal open={addOpen} onClose={() => setAddOpen(false)} onCreate={addService} />
    </div>
  );
}

/* ====================================================================
   VENDOR — CLIENTS
   ==================================================================== */
function VendorClients() {
  const [selected, setSelected] = React.useState(null);
  return (
    <div className="page-enter">
      <window.DemoBanner feature="client roster" />
      <S.PageHead eyebrow="1,284 clients · 312 active" title="Clients" sub="Your relationships, with the context to be brilliant."
        right={<>
          <S.Btn variant="outline" size="sm" icon={<I.filter size={14} />}>Segment</S.Btn>
          <S.Btn variant="primary" size="sm" icon={<I.plus size={14} />}>Add client</S.Btn>
        </>}
      />

      <div className="grid-4" style={{ marginBottom: 24 }}>
        <S.Metric label="VIP / Gold+" value="42" delta="+4" />
        <S.Metric label="New this month" value="18" delta="+2" />
        <S.Metric label="At risk" value="14" delta="−3" deltaTone="pos" />
        <S.Metric label="Repeat rate" value="64%" delta="+3pp" />
      </div>

      <div className="card card-flush">
        <table className="tbl">
          <thead>
            <tr>
              <th>Client</th>
              <th>Tier</th>
              <th>Last visit</th>
              <th>Visits</th>
              <th>LTV</th>
              <th>Notes</th>
              <th />
            </tr>
          </thead>
          <tbody>
            {VENDOR_CLIENTS.map((c) => (
              <tr key={c.id} onClick={() => setSelected(c)} style={{ cursor: "pointer" }}>
                <td>
                  <div className="row-tight">
                    <S.Avatar name={c.name} size="sm" />
                    <div>
                      <div style={{ fontWeight: 500 }}>{c.name}</div>
                      <div className="muted tiny">Client since {c.since}</div>
                    </div>
                  </div>
                </td>
                <td><S.Chip tone={c.tier === "Platinum" ? "accent" : c.tier === "Gold" ? "warn" : ""}>{c.tier}</S.Chip></td>
                <td className="mono muted">{c.lastVisit}</td>
                <td className="mono">{c.visits}</td>
                <td className="mono">${c.ltv.toLocaleString()}</td>
                <td className="muted tiny" style={{ maxWidth: 220 }}>{c.note}</td>
                <td><S.IconBtn><I.chevR size={14} /></S.IconBtn></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      <ClientDetailModal client={selected} onClose={() => setSelected(null)} />
    </div>
  );
}

const VENDOR_CLIENTS = [
  { id: 1, name: "Amelia Brooks", since: "Mar 2024", tier: "Gold", lastVisit: "Dec 14", visits: 24, ltv: 4820, note: "Allergic to PPD · oat milk · prefers cooler blondes",
    email: "amelia@hey.com", phone: "+44 7700 900 142", city: "London, UK", birthday: "14 Mar",
    services: [{ s: "Full color", n: 14 }, { s: "Cut + style", n: 6 }, { s: "Treatment", n: 4 }],
    upcoming: { date: "Today · 2:30 PM", svc: "Full color & cut" } },
  { id: 2, name: "Sofia Romano", since: "Aug 2023", tier: "Platinum", lastVisit: "Jan 28", visits: 41, ltv: 9120, note: "Loves cooler blondes · monthly cadence · prefers Léa",
    email: "sofia.r@proton.me", phone: "+39 348 211 9920", city: "Milan, IT", birthday: "02 Sep",
    services: [{ s: "Balayage", n: 18 }, { s: "Color refresh", n: 12 }, { s: "Cut", n: 11 }],
    upcoming: null },
  { id: 3, name: "Marcus Chen", since: "Sep 2024", tier: "Silver", lastVisit: "Jan 18", visits: 8, ltv: 640, note: "Quiet client · no chit-chat · classic side-part",
    email: "marcus.c@gmail.com", phone: "+1 917 555 0142", city: "New York, US", birthday: "—",
    services: [{ s: "Cut", n: 6 }, { s: "Beard trim", n: 2 }],
    upcoming: null },
  { id: 4, name: "Priya Shah", since: "Apr 2024", tier: "Gold", lastVisit: "Jan 10", visits: 14, ltv: 1420, note: "Bring fashion magazines · always orders matcha",
    email: "priya@studio.io", phone: "+91 98201 12390", city: "Mumbai, IN", birthday: "21 May",
    services: [{ s: "Gel manicure", n: 8 }, { s: "Pedicure", n: 4 }, { s: "Extensions", n: 2 }],
    upcoming: null },
  { id: 5, name: "Daniel Park", since: "Dec 2024", tier: "Silver", lastVisit: "Dec 24", visits: 6, ltv: 480, note: "Books last-minute on weekends · soft-spoken",
    email: "dpark@fastmail.com", phone: "+82 10 4218 2210", city: "Seoul, KR", birthday: "—",
    services: [{ s: "Cut + style", n: 6 }],
    upcoming: null },
];

function ClientDetailModal({ client, onClose }) {
  if (!client) return null;
  return (
    <window.M.Modal open={!!client} onClose={onClose} size="lg">
      <div style={{ padding: 28, paddingTop: 8 }}>
        {/* identity */}
        <div className="row" style={{ gap: 18, marginBottom: 24 }}>
          <S.Avatar name={client.name} size="xl" />
          <div style={{ flex: 1 }}>
            <div className="display" style={{ fontSize: 26, letterSpacing: "-0.02em" }}>{client.name}</div>
            <div className="row-tight" style={{ marginTop: 8 }}>
              <S.Chip tone={client.tier === "Platinum" ? "accent" : client.tier === "Gold" ? "warn" : ""}>{client.tier} tier</S.Chip>
              <span className="muted tiny">· Client since {client.since}</span>
            </div>
          </div>
          <button onClick={onClose} className="icon-btn"><I.x size={18} /></button>
        </div>

        {/* upcoming */}
        {client.upcoming && (
          <div style={{
            padding: 18, marginBottom: 20, borderRadius: 14,
            background: "var(--accent-soft)", color: "var(--accent-ink)",
            display: "flex", alignItems: "center", gap: 14,
          }}>
            <span style={{
              width: 36, height: 36, borderRadius: 10, background: "var(--accent)",
              color: "oklch(20% 0.10 145)", display: "flex", alignItems: "center", justifyContent: "center",
            }}><I.calendar size={16} /></span>
            <div style={{ flex: 1 }}>
              <div className="eyebrow" style={{ color: "var(--accent-ink)" }}>Next appointment</div>
              <div style={{ fontSize: 14, fontWeight: 500, marginTop: 2 }}>{client.upcoming.date} · {client.upcoming.svc}</div>
            </div>
            <S.Btn variant="ink" size="sm" iconRight={<I.arrowR size={12} />}>View</S.Btn>
          </div>
        )}

        {/* stats strip */}
        <div className="grid-3" style={{ marginBottom: 20 }}>
          <ClientStat label="Visits" value={client.visits} />
          <ClientStat label="Lifetime value" value={`$${client.ltv.toLocaleString()}`} />
          <ClientStat label="Avg. ticket" value={`$${Math.round(client.ltv / client.visits)}`} />
        </div>

        {/* contact */}
        <div className="card" style={{ padding: 18, marginBottom: 16 }}>
          <div className="eyebrow" style={{ marginBottom: 14 }}>Contact</div>
          <div className="grid-2" style={{ gap: 14 }}>
            <ClientField icon={<I.mail size={14} />} label="Email" value={client.email} />
            <ClientField icon={<I.phone size={14} />} label="Phone" value={client.phone} />
            <ClientField icon={<I.location size={14} />} label="Location" value={client.city} />
            <ClientField icon={<I.heart size={14} />} label="Birthday" value={client.birthday} />
          </div>
        </div>

        {/* services */}
        <div className="card" style={{ padding: 18, marginBottom: 16 }}>
          <div className="eyebrow" style={{ marginBottom: 14 }}>Favourite services</div>
          <div className="col" style={{ gap: 8 }}>
            {client.services.map((s, i) => (
              <div key={i} className="row between" style={{ padding: "8px 0" }}>
                <div className="row-tight"><span className="dot" style={{ background: i === 0 ? "var(--accent)" : "var(--ink-3)" }} />{s.s}</div>
                <span className="mono tiny muted">{s.n} {s.n === 1 ? "visit" : "visits"}</span>
              </div>
            ))}
          </div>
        </div>

        {/* notes */}
        <div className="card" style={{ padding: 18, marginBottom: 20 }}>
          <div className="row between" style={{ marginBottom: 10 }}>
            <div className="eyebrow">Notes</div>
            <S.Btn variant="ghost" size="sm">Edit notes</S.Btn>
          </div>
          <div style={{ padding: 14, background: "var(--surface-2)", borderRadius: 10, fontSize: 13, lineHeight: 1.55 }}>
            {client.note}
          </div>
        </div>
      </div>

      <div className="modal-foot">
        <S.Btn variant="ghost" icon={<I.mail size={14} />}>Message</S.Btn>
        <S.Btn variant="outline" icon={<I.phone size={14} />}>Call</S.Btn>
        <div className="spacer" />
        <S.Btn variant="primary" icon={<I.plus size={14} />}>Book appointment</S.Btn>
      </div>
    </window.M.Modal>
  );
}

function ClientStat({ label, value }) {
  return (
    <div style={{ padding: 16, background: "var(--surface-2)", borderRadius: 12 }}>
      <div className="muted tiny">{label}</div>
      <div className="display" style={{ fontSize: 24, marginTop: 4 }}>{value}</div>
    </div>
  );
}
function ClientField({ icon, label, value }) {
  return (
    <div>
      <div className="muted tiny row-tight" style={{ marginBottom: 4 }}>{icon}{label}</div>
      <div style={{ fontSize: 13.5 }}>{value}</div>
    </div>
  );
}

/* ====================================================================
   VENDOR — STAFF
   ==================================================================== */
const STAFF_ROLES = [
  { value: "Manager", label: "Manager", desc: "Full access to schedules, services, and reports." },
  { value: "Reception", label: "Reception", desc: "Bookings, client check-in, and front desk." },
  { value: "Therapist", label: "Therapist / Service provider", desc: "Owns their calendar and clients." },
  { value: "Custom", label: "Custom role", desc: "Define your own set of permissions." },
];

const STAFF_PERMISSIONS = [
  { id: "bookings", label: "Bookings · view & edit" },
  { id: "clients", label: "Clients · view & contact" },
  { id: "services", label: "Services & pricing" },
  { id: "payouts", label: "Wallet & payouts" },
  { id: "reports", label: "Reports & analytics" },
  { id: "team", label: "Manage other staff" },
];

const INITIAL_STAFF = [
  { id: "s1", name: "Léa Marchand", role: "Manager", email: "lea@maisoncolor.fr", phone: "+33 6 12 34 56 78", status: "Active", joined: "Apr 12, 2023", bookings: 312, util: 96, rating: 4.9 },
  { id: "s2", name: "Camille Roy", role: "Therapist", email: "camille@maisoncolor.fr", phone: "+33 6 21 45 89 01", status: "Active", joined: "Aug 02, 2023", bookings: 284, util: 88, rating: 4.8 },
  { id: "s3", name: "Inès Khan", role: "Therapist", email: "ines@maisoncolor.fr", phone: "+33 6 98 12 33 02", status: "Active", joined: "Jan 18, 2024", bookings: 198, util: 92, rating: 4.9 },
  { id: "s4", name: "Nora Beaumont", role: "Reception", email: "nora@maisoncolor.fr", phone: "+33 6 44 11 76 91", status: "Active", joined: "Sep 04, 2024", bookings: 0, util: 64, rating: null },
  { id: "s5", name: "Theo Sun", role: "Therapist", email: "theo@maisoncolor.fr", phone: "+33 6 22 78 45 19", status: "Pending", joined: "Invited Feb 1", bookings: 0, util: 0, rating: null },
  { id: "s6", name: "Mira Aoki", role: "Custom", email: "mira@maisoncolor.fr", phone: "+33 6 31 02 19 87", status: "Suspended", joined: "Feb 19, 2024", bookings: 142, util: 0, rating: 4.7 },
];

function VendorStaff() {
  const [staff, setStaff] = React.useState(INITIAL_STAFF);
  const [addOpen, setAddOpen] = React.useState(false);
  const [editing, setEditing] = React.useState(null);
  const [confirm, setConfirm] = React.useState(null);
  const [filter, setFilter] = React.useState("all");

  const filtered = staff.filter(s => filter === "all" ? true : filter === "active" ? s.status === "Active" : filter === "pending" ? s.status === "Pending" : s.status === "Suspended");

  const counts = {
    total: staff.length,
    active: staff.filter(s => s.status === "Active").length,
    pending: staff.filter(s => s.status === "Pending").length,
    suspended: staff.filter(s => s.status === "Suspended").length,
    roles: new Set(staff.map(s => s.role)).size,
  };

  const saveStaff = (next) => {
    if (editing) setStaff(staff.map(s => s.id === editing.id ? { ...s, ...next } : s));
    else setStaff([...staff, {
      ...next, id: "s" + Date.now(), status: "Pending",
      joined: "Invited " + new Date().toLocaleDateString("en-US", { month: "short", day: "numeric" }),
      bookings: 0, util: 0, rating: null,
    }]);
    setAddOpen(false); setEditing(null);
  };
  const removeStaff = (id) => { setStaff(staff.filter(s => s.id !== id)); setConfirm(null); };
  const setStatus = (id, status) => setStaff(staff.map(s => s.id === id ? { ...s, status } : s));

  return (
    <div className="page-enter">
      <window.DemoBanner feature="staff management" />
      <S.PageHead
        eyebrow={`Team · ${counts.total} members`}
        title="Staff"
        sub="Invite team members, assign roles, and manage permissions for your studio."
        right={<>
          <S.Btn variant="outline" size="sm" icon={<I.filter size={14} />}>Roles</S.Btn>
          <S.Btn variant="primary" size="sm" icon={<I.plus size={14} />} onClick={() => { setEditing(null); setAddOpen(true); }}>Add staff</S.Btn>
        </>}
      />

      {/* Summary cards */}
      <div className="grid-4" style={{ marginBottom: 20 }}>
        <S.Metric hero label="Total staff" value={String(counts.total)} delta={`+${counts.pending} this month`} />
        <S.Metric label="Active" value={String(counts.active)} delta={`${Math.round(counts.active / counts.total * 100)}% of team`} deltaTone="pos" />
        <S.Metric label="Pending invites" value={String(counts.pending)} delta={counts.pending > 0 ? "Awaiting response" : "All accepted"} deltaTone={counts.pending > 0 ? "warn" : "pos"} />
        <S.Metric label="Roles" value={String(counts.roles)} delta="Across team" />
      </div>

      {/* Directory */}
      <div className="card card-flush">
        <div className="row between" style={{ padding: 16, gap: 10, flexWrap: "wrap", borderBottom: "1px solid var(--border)" }}>
          <div className="row" style={{ gap: 10 }}>
            <S.Input icon={<I.search size={15} />} placeholder="Search by name, role, email…" style={{ flex: 1, maxWidth: 320 }} />
            <div className="segmented">
              {[{ k: "all", l: "All" }, { k: "active", l: "Active" }, { k: "pending", l: "Pending" }, { k: "suspended", l: "Suspended" }].map(t => (
                <button key={t.k} className={filter === t.k ? "active" : ""} onClick={() => setFilter(t.k)}>{t.l}</button>
              ))}
            </div>
          </div>
          <span className="muted tiny">Showing {filtered.length} of {staff.length}</span>
        </div>

        <table className="tbl">
          <thead>
            <tr>
              <th>Staff member</th>
              <th>Role</th>
              <th>Email</th>
              <th>Phone</th>
              <th>Status</th>
              <th>Joined</th>
              <th style={{ width: 160 }}>Actions</th>
            </tr>
          </thead>
          <tbody>
            {filtered.map(s => (
              <tr key={s.id}>
                <td>
                  <div className="row-tight" style={{ gap: 12 }}>
                    <S.Avatar name={s.name} size="sm" />
                    <div>
                      <div style={{ fontWeight: 500 }}>{s.name}</div>
                      <div className="muted tiny">
                        {s.status === "Active" && s.bookings > 0 ? `${s.bookings} bookings · ${s.util}% util` :
                         s.status === "Pending" ? "Invitation sent" : "—"}
                      </div>
                    </div>
                  </div>
                </td>
                <td><S.Chip tone={s.role === "Manager" ? "accent" : s.role === "Reception" ? "info" : s.role === "Custom" ? "warn" : ""}>{s.role}</S.Chip></td>
                <td className="muted">{s.email}</td>
                <td className="muted">{s.phone}</td>
                <td><S.Chip tone={s.status === "Active" ? "pos" : s.status === "Pending" ? "warn" : "neg"}>{s.status}</S.Chip></td>
                <td className="muted">{s.joined}</td>
                <td>
                  <div className="row-tight" style={{ gap: 4 }}>
                    <S.IconBtn title="Edit" onClick={() => { setEditing(s); setAddOpen(true); }}><I.settings size={15} /></S.IconBtn>
                    {s.status === "Suspended" ? (
                      <S.IconBtn title="Reactivate" onClick={() => setStatus(s.id, "Active")}><I.check size={15} /></S.IconBtn>
                    ) : s.status === "Active" ? (
                      <S.IconBtn title="Suspend" onClick={() => setStatus(s.id, "Suspended")}><I.eyeOff size={15} /></S.IconBtn>
                    ) : (
                      <S.IconBtn title="Resend invite" onClick={() => {}}><I.mail size={15} /></S.IconBtn>
                    )}
                    <S.IconBtn title="Remove" onClick={() => setConfirm(s)}><I.x size={15} /></S.IconBtn>
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      <AddStaffModal
        open={addOpen}
        staff={editing}
        onClose={() => { setAddOpen(false); setEditing(null); }}
        onSave={saveStaff}
      />
      <window.M.ConfirmModal
        open={!!confirm}
        onClose={() => setConfirm(null)}
        onConfirm={() => removeStaff(confirm?.id)}
        title={`Remove ${confirm?.name}?`}
        body="They'll lose access to your studio immediately. Their booking history stays intact."
        confirmLabel="Remove staff"
        danger
        icon={<I.x />}
      />
    </div>
  );
}

function AddStaffModal({ open, staff, onClose, onSave }) {
  const [data, setData] = React.useState({ name: "", email: "", phone: "", role: "Therapist", perms: ["bookings", "clients"] });
  const [errors, setErrors] = React.useState({});
  React.useEffect(() => {
    if (open) {
      setData(staff
        ? { name: staff.name, email: staff.email, phone: staff.phone, role: staff.role, perms: ["bookings", "clients"] }
        : { name: "", email: "", phone: "", role: "Therapist", perms: ["bookings", "clients"] });
      setErrors({});
    }
  }, [open, staff]);
  const set = (k, v) => { setData(d => ({ ...d, [k]: v })); setErrors(e => ({ ...e, [k]: undefined })); };
  const togglePerm = (id) => set("perms", data.perms.includes(id) ? data.perms.filter(p => p !== id) : [...data.perms, id]);

  const submit = () => {
    const e = {};
    if (!data.name.trim()) e.name = "Name is required.";
    if (!data.email.trim()) e.email = "Email is required.";
    else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data.email)) e.email = "Enter a valid email address.";
    setErrors(e);
    if (Object.keys(e).length === 0) onSave(data);
  };

  return (
    <window.M.Modal open={open} onClose={onClose} size="lg"
      icon={<I.staff />} title={staff ? `Edit ${staff.name}` : "Add a team member"}
      subtitle={staff ? "Update profile, role, or permissions." : "They'll get an email invite to join your studio on Pamp."}
      footer={<>
        <S.Btn variant="ghost" onClick={onClose}>Cancel</S.Btn>
        <S.Btn variant="primary" iconRight={<I.arrowR size={14} />} onClick={submit}>{staff ? "Save changes" : "Send invite"}</S.Btn>
      </>}
    >
      <window.M.FormGrid>
        <window.M.Field full label="Full name" error={errors.name}>
          <window.M.TextField value={data.name} onChange={(v) => set("name", v)} placeholder="Jordan Lee" />
        </window.M.Field>
        <window.M.Field label="Email" error={errors.email}>
          <window.M.TextField icon={<I.mail size={14} />} value={data.email} onChange={(v) => set("email", v)} placeholder="jordan@studio.com" />
        </window.M.Field>
        <window.M.Field label="Phone">
          <window.M.TextField icon={<I.phone size={14} />} value={data.phone} onChange={(v) => set("phone", v)} placeholder="+1 555 0142" />
        </window.M.Field>
        <window.M.Field full label="Role">
          <window.M.RadioCards value={data.role} onChange={(v) => set("role", v)}
            options={STAFF_ROLES.map(r => ({ value: r.value, label: r.label, desc: r.desc }))} />
        </window.M.Field>
        <window.M.Field full label="Permissions" hint="Pick what this person can access.">
          <div className="grid-2" style={{ gap: 10 }}>
            {STAFF_PERMISSIONS.map(p => {
              const on = data.perms.includes(p.id);
              return (
                <button key={p.id} type="button" onClick={() => togglePerm(p.id)}
                  className="row" style={{
                    padding: "12px 14px", border: `1px solid ${on ? "var(--accent)" : "var(--border-strong)"}`,
                    borderRadius: "var(--r-md)", background: on ? "var(--accent-soft)" : "var(--surface)",
                    gap: 10, textAlign: "left",
                  }}>
                  <span className="cb-box" data-checked={on}>{on && <I.check size={11} />}</span>
                  <span style={{ fontSize: 13, fontWeight: 500 }}>{p.label}</span>
                </button>
              );
            })}
          </div>
        </window.M.Field>
      </window.M.FormGrid>
    </window.M.Modal>
  );
}

/* ====================================================================
   VENDOR — WALLET
   ==================================================================== */
function VendorWallet() {
  return (
    <div className="page-enter">
      <window.DemoBanner feature="vendor wallet & payouts" />
      <S.PageHead eyebrow="Money · this month" title="Wallets & earnings"
        sub="Real-time balance, payout history, and tax-ready statements."
        right={<S.Btn variant="primary" size="sm" icon={<I.download size={14} />}>Request payout</S.Btn>}
      />

      <div className="grid-12" style={{ marginBottom: 20 }}>
        <div className="card" style={{ gridColumn: "span 4", background: "var(--ink)", color: "var(--bg)", borderColor: "transparent", position: "relative", overflow: "hidden" }}>
          <div style={{ position: "absolute", inset: 0, opacity: 0.5, background: "radial-gradient(circle at 80% 20%, var(--accent) 0%, transparent 50%)" }} />
          <div style={{ position: "relative" }}>
            <div className="eyebrow" style={{ color: "oklch(75% 0.02 145)" }}>Available to withdraw</div>
            <div className="display" style={{ fontSize: 48, color: "var(--bg)", letterSpacing: "-0.035em", marginTop: 8 }}>$8,420.18</div>
            <div className="muted tiny" style={{ color: "oklch(75% 0.02 145)" }}>Next auto-payout: Tue Feb 4 · 10 AM</div>
            <div className="row" style={{ marginTop: 28, gap: 8 }}>
              <S.Btn variant="primary" icon={<I.download size={14} />}>Withdraw now</S.Btn>
              <S.Btn variant="ghost" style={{ color: "var(--bg)", background: "oklch(100% 0 0 / 0.10)" }}>Change schedule</S.Btn>
            </div>
          </div>
        </div>
        <div className="card" style={{ gridColumn: "span 2", display: "flex", flexDirection: "column", justifyContent: "space-between" }}>
          <div>
            <div className="eyebrow" style={{ marginBottom: 8 }}>Holding</div>
            <div className="display" style={{ fontSize: 28 }}>$1,420</div>
          </div>
          <div className="row-tight" style={{ marginTop: 12 }}>
            <S.Chip tone="info">Clearing Mon</S.Chip>
          </div>
        </div>
        <div className="card" style={{ gridColumn: "span 2", display: "flex", flexDirection: "column", justifyContent: "space-between" }}>
          <div>
            <div className="eyebrow" style={{ marginBottom: 8 }}>Paid this year</div>
            <div className="display" style={{ fontSize: 28 }}>$84.2k</div>
          </div>
          <div className="row-tight" style={{ marginTop: 12 }}>
            <S.Chip tone="pos">+34%</S.Chip>
          </div>
        </div>
        <div className="card" style={{ gridColumn: "span 4", overflow: "hidden" }}>
          <div className="row between" style={{ marginBottom: 14 }}>
            <div className="eyebrow">Earnings · 30 days</div>
            <S.Chip tone="pos">+24%</S.Chip>
          </div>
          <div className="display" style={{ fontSize: 28, marginBottom: 8 }}>$24,180</div>
          <div style={{ width: "100%", overflow: "hidden" }}>
            <S.Spark data={[12, 14, 13, 16, 18, 17, 19, 22, 21, 24, 26, 28, 30, 32, 31, 34]} width={400} height={70} responsive />
          </div>
        </div>
      </div>

      <div className="card card-flush">
        <div className="row between" style={{ padding: "22px 22px 14px" }}>
          <div className="h3">Payout history</div>
          <S.Btn variant="ghost" size="sm">Download statements</S.Btn>
        </div>
        <table className="tbl">
          <thead><tr><th>Date</th><th>Method</th><th>Period</th><th>Bookings</th><th>Fees</th><th>Status</th><th className="col-num">Net</th></tr></thead>
          <tbody>
            {[
              { d: "Feb 1", m: "ACH ····4821", p: "Jan 25 – Jan 31", b: 48, f: 142, s: "Sent", st: "pos", n: 4820 },
              { d: "Jan 25", m: "ACH ····4821", p: "Jan 18 – Jan 24", b: 52, f: 154, s: "Sent", st: "pos", n: 5210 },
              { d: "Jan 18", m: "ACH ····4821", p: "Jan 11 – Jan 17", b: 41, f: 121, s: "Sent", st: "pos", n: 4120 },
              { d: "Jan 11", m: "ACH ····4821", p: "Jan 4 – Jan 10", b: 38, f: 110, s: "Sent", st: "pos", n: 3820 },
            ].map((r, i) => (
              <tr key={i}>
                <td className="mono">{r.d}</td>
                <td className="muted">{r.m}</td>
                <td className="muted">{r.p}</td>
                <td className="mono">{r.b}</td>
                <td className="mono">${r.f}</td>
                <td><S.Chip tone={r.st}>{r.s}</S.Chip></td>
                <td className="col-num mono" style={{ fontWeight: 500 }}>${r.n.toLocaleString()}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

/* ====================================================================
   VENDOR — PLAN
   ==================================================================== */
function VendorPlan() {
  return (
    <div className="page-enter">
      <window.DemoBanner feature="vendor plan" />
      <S.PageHead eyebrow="Current plan · Studio" title="My plan" sub="Renews Mar 14 · $49/mo billed monthly." />
      <div className="grid-12">
        <div className="card" style={{ gridColumn: "span 5", background: "var(--accent)", color: "oklch(20% 0.10 145)", borderColor: "transparent" }}>
          <div className="row between">
            <span className="chip" style={{ background: "white", color: "oklch(20% 0.10 145)", borderColor: "transparent" }}>Studio plan</span>
            <span className="chip" style={{ background: "oklch(0% 0 0 / 0.14)", color: "oklch(20% 0.10 145)", borderColor: "transparent" }}>Active</span>
          </div>
          <div className="display" style={{ fontSize: 56, color: "oklch(15% 0.10 145)", marginTop: 18, letterSpacing: "-0.035em" }}>$49<span style={{ fontSize: 18, opacity: 0.5 }}>/mo</span></div>
          <div style={{ color: "oklch(28% 0.10 145)", fontSize: 13, marginTop: 6 }}>Best for growing studios with 2–5 staff.</div>
          <div className="divider" style={{ margin: "24px 0", background: "oklch(0% 0 0 / 0.16)" }} />
          <div className="col" style={{ gap: 10 }}>
            {[
              "Up to 5 staff seats",
              "Unlimited bookings",
              "Reduced platform fee · 3.5%",
              "SMS reminders included",
              "Custom branded mini-site",
            ].map(f => <div key={f} className="row-tight" style={{ fontSize: 13, color: "oklch(20% 0.10 145)" }}><I.check size={14} />{f}</div>)}
          </div>
          <div className="row" style={{ marginTop: 28, gap: 8 }}>
            <S.Btn variant="ink" iconRight={<I.arrowR size={14} />}>Upgrade to Atelier</S.Btn>
            <S.Btn variant="ghost" style={{ color: "oklch(20% 0.10 145)", background: "oklch(0% 0 0 / 0.10)" }}>Manage billing</S.Btn>
          </div>
        </div>
        <div className="card" style={{ gridColumn: "span 7" }}>
          <div className="h3" style={{ marginBottom: 16 }}>This billing cycle</div>
          <div className="grid-3">
            <Metric2 label="Bookings used" value="84 / ∞" />
            <Metric2 label="SMS sent" value="142 / 500" />
            <Metric2 label="Staff seats" value="4 / 5" />
          </div>
          <div className="divider" style={{ margin: "24px 0" }} />
          <div className="h3" style={{ marginBottom: 14 }}>Recent invoices</div>
          <div className="col" style={{ gap: 8 }}>
            {[
              { d: "Feb 14", a: 49, s: "Paid" },
              { d: "Jan 14", a: 49, s: "Paid" },
              { d: "Dec 14", a: 49, s: "Paid" },
            ].map((iv, i) => (
              <div key={i} className="row between" style={{ padding: 12, border: "1px solid var(--border)", borderRadius: 10 }}>
                <div className="row-tight"><I.card size={16} /> <span>Studio plan · {iv.d}, 2026</span></div>
                <div className="row-tight"><span className="mono">${iv.a}.00</span><S.Chip tone="pos">{iv.s}</S.Chip><S.IconBtn><I.download size={14} /></S.IconBtn></div>
              </div>
            ))}
          </div>
        </div>
      </div>

      {/* explore other plans */}
      <div style={{ marginTop: 36 }}>
        <div className="row between" style={{ marginBottom: 18 }}>
          <div>
            <div className="eyebrow" style={{ marginBottom: 6 }}>Explore other plans</div>
            <div className="h2" style={{ fontSize: 24 }}>Move up when you’re ready</div>
          </div>
          <div className="row-tight" style={{ background: "var(--surface-3)", padding: 3, borderRadius: 999 }}>
            <button className="btn btn-sm" style={{ background: "var(--surface)", color: "var(--ink)", boxShadow: "var(--shadow-sm)" }}>Monthly</button>
            <button className="btn btn-ghost btn-sm">Annual <span className="chip chip-pos" style={{ marginLeft: 6, height: 18, padding: "0 6px", fontSize: 10 }}>−20%</span></button>
          </div>
        </div>

        <div className="grid-4">
          {[
            {
              name: "Starter", price: 0, suffix: "Free",
              tag: "For trying Pamp", color: "var(--ink-3)",
              features: ["1 location", "30 bookings / month", "Standard platform fee · 5%", "Email reminders only"],
              cta: "Downgrade", action: "outline",
            },
            {
              name: "Studio", price: 49, current: true,
              tag: "Most chosen", color: "var(--accent)",
              features: ["Up to 5 staff seats", "Unlimited bookings", "Reduced fee · 3.5%", "SMS reminders included", "Custom branded site"],
              cta: "Current plan", action: "disabled",
            },
            {
              name: "Atelier", price: 149, featured: true,
              tag: "For established studios", color: "var(--ink)",
              features: ["Unlimited staff seats", "Lowest platform fee · 2.4%", "API access", "Multi-location", "Priority support"],
              cta: "Upgrade to Atelier", action: "primary",
            },
            {
              name: "Enterprise", price: null,
              tag: "For groups & chains", color: "var(--info)",
              features: ["Custom contract", "SSO + SAML", "Audit logs & exports", "Dedicated CSM", "Bespoke SLA"],
              cta: "Talk to sales", action: "outline",
            },
          ].map((p) => (
            <div key={p.name} className="card" style={{
              position: "relative",
              borderColor: p.featured ? "var(--ink)" : p.current ? "var(--accent)" : undefined,
              borderWidth: p.featured || p.current ? 1.5 : 1,
              padding: 24,
              display: "flex", flexDirection: "column",
            }}>
              {p.current && <div style={{ position: "absolute", top: -10, left: 22 }}><S.Chip tone="accent">Current</S.Chip></div>}
              {p.featured && <div style={{ position: "absolute", top: -10, left: 22 }}><span className="chip" style={{ background: "var(--ink)", color: "var(--surface)", borderColor: "transparent" }}>Recommended</span></div>}

              <div className="eyebrow" style={{ color: p.color, marginBottom: 8 }}>{p.name}</div>
              <div className="muted tiny" style={{ marginBottom: 14 }}>{p.tag}</div>
              <div className="display" style={{ fontSize: 38, letterSpacing: "-0.03em", lineHeight: 1 }}>
                {p.price === null ? "Custom" : p.price === 0 ? "Free" : (
                  <>$<span>{p.price}</span><span className="muted" style={{ fontSize: 14, fontWeight: 400 }}> /mo</span></>
                )}
              </div>

              <div className="divider" style={{ margin: "20px 0" }} />
              <div className="col" style={{ gap: 10, flex: 1 }}>
                {p.features.map((f) => (
                  <div key={f} className="row-tight" style={{ fontSize: 13, alignItems: "flex-start" }}>
                    <span style={{ color: p.color, display: "inline-flex", marginTop: 2 }}><I.check size={14} /></span>{f}
                  </div>
                ))}
              </div>

              <div style={{ marginTop: 22 }}>
                <S.Btn
                  variant={p.action === "primary" ? "primary" : p.action === "disabled" ? "outline" : "outline"}
                  size="sm"
                  disabled={p.action === "disabled"}
                  style={{ width: "100%" }}
                  iconRight={p.action === "primary" ? <I.arrowR size={14} /> : null}
                >{p.cta}</S.Btn>
              </div>
            </div>
          ))}
        </div>

        <div className="muted tiny" style={{ textAlign: "center", marginTop: 18 }}>
          All plans include 24/7 support · cancel anytime · prices in USD before tax
        </div>
      </div>
    </div>
  );
}

function Metric2({ label, value }) {
  return (
    <div>
      <div className="muted tiny">{label}</div>
      <div className="display" style={{ fontSize: 22, marginTop: 4 }}>{value}</div>
    </div>
  );
}

function VendorReports() {
  const [range, setRange] = React.useState("90d");
  return (
    <div className="page-enter">
      <window.DemoBanner feature="vendor reports" />
      <S.PageHead
        eyebrow="Insights · last 90 days"
        title="Reports"
        sub="What changed, what worked, where to lean in."
        right={<>
          <div className="row-tight" style={{ background: "var(--surface-3)", padding: 3, borderRadius: 999 }}>
            {[{ k: "7d", l: "7d" }, { k: "30d", l: "30d" }, { k: "90d", l: "90d" }, { k: "ytd", l: "YTD" }].map(r => (
              <button key={r.k} onClick={() => setRange(r.k)}
                className={`btn btn-sm ${range === r.k ? "btn-primary" : "btn-ghost"}`}>{r.l}</button>
            ))}
          </div>
          <S.Btn variant="outline" size="sm" icon={<I.download size={14} />}>Export PDF</S.Btn>
        </>}
      />

      {/* KPI strip */}
      <div className="grid-4" style={{ marginBottom: 20 }}>
        <S.Metric hero label="Net revenue" value="$84,210" delta="+34%" />
        <S.Metric label="Bookings" value="312" delta="+18%" />
        <S.Metric label="Avg ticket" value="$148" delta="+$12" />
        <S.Metric label="Rebook rate" value="62%" delta="+4pp" />
      </div>

      <div className="grid-12" style={{ marginBottom: 20 }}>
        {/* Revenue trend */}
        <div className="card" style={{ gridColumn: "span 8" }}>
          <div className="row between" style={{ marginBottom: 18 }}>
            <div>
              <div className="eyebrow">Revenue & bookings</div>
              <div className="h3" style={{ marginTop: 4 }}>Weekly trend · last 12 weeks</div>
            </div>
            <div className="row" style={{ gap: 14 }}>
              <div className="row-tight"><span className="dot" style={{ background: "var(--accent)" }} /><span className="tiny muted">Net revenue</span></div>
              <div className="row-tight"><span className="dot" style={{ background: "var(--ink-3)" }} /><span className="tiny muted">Last year</span></div>
            </div>
          </div>
          <S.LineChart
            height={260}
            currency
            labels={["W1", "W2", "W3", "W4", "W5", "W6", "W7", "W8", "W9", "W10", "W11", "W12"]}
            series={[
              { color: "var(--accent)", data: [3.2, 3.8, 4.2, 4.0, 4.6, 5.0, 5.4, 5.8, 6.2, 6.6, 7.0, 7.4].map(v => v * 1000) },
              { color: "var(--ink-3)", data: [2.4, 2.6, 2.8, 3.0, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.0, 4.2].map(v => v * 1000), dashed: true },
            ]}
          />
        </div>

        {/* Service mix */}
        <div className="card" style={{ gridColumn: "span 4" }}>
          <div className="eyebrow" style={{ marginBottom: 4 }}>Revenue mix</div>
          <div className="h3" style={{ marginBottom: 18 }}>By service</div>
          <div className="row" style={{ justifyContent: "center", marginBottom: 18 }}>
            <S.Ring value={64} size={140} stroke={14} label="$84k" sub="net · 90d" />
          </div>
          <div className="col" style={{ gap: 10 }}>
            {[
              { l: "Full color", v: 38, n: "$32.0k", c: "var(--accent)" },
              { l: "Balayage", v: 24, n: "$20.2k", c: "var(--ink)" },
              { l: "Cut + style", v: 18, n: "$15.2k", c: "var(--info)" },
              { l: "Treatment", v: 12, n: "$10.1k", c: "var(--warn)" },
              { l: "Other", v: 8, n: "$6.7k", c: "var(--ink-3)" },
            ].map((r) => (
              <div key={r.l} className="row" style={{ gap: 10 }}>
                <span className="dot" style={{ background: r.c }} />
                <span style={{ flex: 1, fontSize: 13 }}>{r.l}</span>
                <span className="mono tiny muted">{r.v}%</span>
                <span className="mono" style={{ fontSize: 12, width: 56, textAlign: "right" }}>{r.n}</span>
              </div>
            ))}
          </div>
        </div>

        {/* Staff performance */}
        <div className="card card-flush" style={{ gridColumn: "span 12" }}>
          <div className="row between" style={{ padding: "22px 22px 14px" }}>
            <div>
              <div className="h3">Staff performance</div>
              <div className="muted tiny" style={{ marginTop: 4 }}>Bookings, utilization, rebook rate, net contribution.</div>
            </div>
            <S.Btn variant="ghost" size="sm" iconRight={<I.chevD size={12} />}>This quarter</S.Btn>
          </div>
          <table className="tbl">
            <thead>
              <tr>
                <th>Stylist</th>
                <th>Role</th>
                <th>Bookings</th>
                <th>Utilization</th>
                <th>Rebook rate</th>
                <th>Avg ticket</th>
                <th>Rating</th>
                <th className="col-num">Net (90d)</th>
              </tr>
            </thead>
            <tbody>
              {[
                { n: "Léa Marchand", r: "Senior colorist", b: 312, u: 96, rb: 72, avg: 178, st: 4.9, net: 41280 },
                { n: "Camille Roy", r: "Senior cuts", b: 284, u: 88, rb: 64, avg: 124, st: 4.8, net: 24180 },
                { n: "Inès Khan", r: "Specialist", b: 198, u: 92, rb: 58, avg: 142, st: 4.9, net: 18610 },
                { n: "Nora B.", r: "Assistant", b: 0, u: 64, rb: null, avg: null, st: null, net: 0 },
              ].map((s, i) => (
                <tr key={i}>
                  <td>
                    <div className="row-tight">
                      <S.Avatar name={s.n} size="sm" />
                      <span style={{ fontWeight: 500 }}>{s.n}</span>
                    </div>
                  </td>
                  <td className="muted">{s.r}</td>
                  <td className="mono">{s.b}</td>
                  <td style={{ width: 160 }}>
                    <div className="row-tight" style={{ gap: 8 }}>
                      <div className="bar" style={{ flex: 1 }}><span style={{ width: `${s.u}%`, background: s.u > 90 ? "var(--neg)" : s.u > 70 ? "var(--pos)" : "var(--warn)" }} /></div>
                      <span className="mono tiny" style={{ width: 36 }}>{s.u}%</span>
                    </div>
                  </td>
                  <td className="mono">{s.rb != null ? `${s.rb}%` : "—"}</td>
                  <td className="mono">{s.avg != null ? `$${s.avg}` : "—"}</td>
                  <td>{s.st != null ? <div className="row-tight"><I.star size={12} color="var(--warn)" />{s.st}</div> : <span className="muted tiny">—</span>}</td>
                  <td className="col-num mono" style={{ fontWeight: 500 }}>${s.net.toLocaleString()}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>

        {/* Time of day heatmap */}
        <div className="card" style={{ gridColumn: "span 7" }}>
          <div className="row between" style={{ marginBottom: 18 }}>
            <div>
              <div className="eyebrow">Demand by hour</div>
              <div className="h3" style={{ marginTop: 4 }}>When clients book</div>
            </div>
            <S.Chip>Peak Fri 4–7 PM</S.Chip>
          </div>
          <DemandHeatmap />
        </div>

        {/* Client retention */}
        <div className="card" style={{ gridColumn: "span 5" }}>
          <div className="eyebrow">Retention</div>
          <div className="h3" style={{ marginBottom: 14, marginTop: 4 }}>Repeat vs new clients</div>
          <div className="row" style={{ gap: 14, marginBottom: 18 }}>
            <div style={{ flex: 1, padding: 16, borderRadius: 12, background: "var(--accent-soft)", color: "var(--accent-ink)" }}>
              <div className="muted tiny" style={{ color: "var(--accent-ink)", opacity: 0.7 }}>Repeat</div>
              <div className="display" style={{ fontSize: 28, marginTop: 6 }}>62%</div>
              <div className="mono tiny" style={{ marginTop: 4 }}>+4pp</div>
            </div>
            <div style={{ flex: 1, padding: 16, borderRadius: 12, background: "var(--surface-2)" }}>
              <div className="muted tiny">New</div>
              <div className="display" style={{ fontSize: 28, marginTop: 6 }}>38%</div>
              <div className="mono tiny muted" style={{ marginTop: 4 }}>−4pp</div>
            </div>
          </div>
          <div className="col" style={{ gap: 10 }}>
            <RetRow label="Booked 4+ times" pct={42} c="var(--accent)" />
            <RetRow label="Booked 2–3 times" pct={28} c="var(--ink)" />
            <RetRow label="First-time clients" pct={22} c="var(--info)" />
            <RetRow label="At-risk (90d gap)" pct={8} c="var(--warn)" />
          </div>
        </div>

        {/* Cancellations / no-shows */}
        <div className="card" style={{ gridColumn: "span 4" }}>
          <div className="eyebrow">Operational</div>
          <div className="h3" style={{ marginBottom: 18, marginTop: 4 }}>Cancellations & no-shows</div>
          <div className="grid-2" style={{ marginBottom: 18 }}>
            <div>
              <div className="display" style={{ fontSize: 28 }}>3.4%</div>
              <div className="muted tiny">Cancellation rate</div>
              <div className="row-tight" style={{ marginTop: 6 }}><S.Chip tone="pos">−0.6pp</S.Chip></div>
            </div>
            <div>
              <div className="display" style={{ fontSize: 28 }}>1.8%</div>
              <div className="muted tiny">No-show rate</div>
              <div className="row-tight" style={{ marginTop: 6 }}><S.Chip tone="pos">−0.4pp</S.Chip></div>
            </div>
          </div>
          <S.BarChart
            data={[4.2, 3.8, 3.6, 3.4, 3.2, 3.4]}
            labels={["Sep", "Oct", "Nov", "Dec", "Jan", "Feb"]}
            activeIndex={5}
            height={110}
          />
        </div>

        {/* Reviews */}
        <div className="card" style={{ gridColumn: "span 4" }}>
          <div className="eyebrow">Reputation</div>
          <div className="h3" style={{ marginBottom: 18, marginTop: 4 }}>Reviews & rating</div>
          <div className="row" style={{ gap: 14, alignItems: "flex-end", marginBottom: 16 }}>
            <div className="display" style={{ fontSize: 44 }}>4.9</div>
            <div>
              <div className="row-tight" style={{ marginBottom: 4 }}>
                {[1, 2, 3, 4, 5].map(i => <I.star key={i} size={12} color="var(--warn)" fill="var(--warn)" />)}
              </div>
              <div className="muted tiny">1,842 reviews · +84 this period</div>
            </div>
          </div>
          <div className="col" style={{ gap: 6 }}>
            {[
              { s: 5, n: 1480, p: 80 },
              { s: 4, n: 280, p: 15 },
              { s: 3, n: 60, p: 3 },
              { s: 2, n: 14, p: 0.8 },
              { s: 1, n: 8, p: 0.4 },
            ].map(r => (
              <div key={r.s} className="row" style={{ gap: 10, fontSize: 12 }}>
                <span className="mono" style={{ width: 18 }}>{r.s}★</span>
                <div className="bar" style={{ flex: 1 }}><span style={{ width: `${r.p}%`, background: "var(--warn)" }} /></div>
                <span className="mono tiny muted" style={{ width: 40, textAlign: "right" }}>{r.n}</span>
              </div>
            ))}
          </div>
        </div>

        {/* Top clients */}
        <div className="card" style={{ gridColumn: "span 4" }}>
          <div className="eyebrow">Audience</div>
          <div className="h3" style={{ marginBottom: 18, marginTop: 4 }}>Top clients · LTV</div>
          <div className="col" style={{ gap: 12 }}>
            {[
              { n: "Sofia Romano", v: 41, ltv: 9120, t: "Platinum" },
              { n: "Amelia Brooks", v: 24, ltv: 4820, t: "Gold" },
              { n: "Iris Mendez", v: 18, ltv: 3120, t: "Gold" },
              { n: "Priya Shah", v: 14, ltv: 1420, t: "Gold" },
            ].map((c, i) => (
              <div key={c.n} className="row" style={{ gap: 10 }}>
                <span className="mono tiny muted" style={{ width: 18 }}>{String(i + 1).padStart(2, "0")}</span>
                <S.Avatar name={c.n} size="sm" />
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 13, fontWeight: 500 }}>{c.n}</div>
                  <div className="muted tiny">{c.v} visits · {c.t}</div>
                </div>
                <span className="mono" style={{ fontSize: 13, fontWeight: 500 }}>${c.ltv.toLocaleString()}</span>
              </div>
            ))}
          </div>
        </div>

        {/* Channel acquisition */}
        <div className="card" style={{ gridColumn: "span 6" }}>
          <div className="eyebrow">Growth</div>
          <div className="h3" style={{ marginBottom: 18, marginTop: 4 }}>How new clients find you</div>
          <div className="col" style={{ gap: 10 }}>
            <RetRow label="Pamp Discover" pct={42} c="var(--accent)" n="138" />
            <RetRow label="Direct (saved link)" pct={26} c="var(--ink)" n="84" />
            <RetRow label="Word of mouth" pct={18} c="var(--info)" n="58" />
            <RetRow label="Instagram" pct={10} c="var(--warn)" n="32" />
            <RetRow label="Other" pct={4} c="var(--ink-3)" n="14" />
          </div>
        </div>

        {/* Payouts summary */}
        <div className="card" style={{ gridColumn: "span 6" }}>
          <div className="eyebrow">Money flow</div>
          <div className="h3" style={{ marginBottom: 18, marginTop: 4 }}>Gross → net breakdown</div>
          <div className="col" style={{ gap: 10 }}>
            <FlowRow label="Gross bookings" value="$96,420" />
            <FlowRow label="Tips" value="$4,180" tone="pos" />
            <FlowRow label="Platform fees" value="−$3,082" tone="neg" />
            <FlowRow label="Refunds & cancellations" value="−$1,108" tone="neg" />
            <FlowRow label="Taxes withheld" value="−$12,200" tone="neg" />
            <div className="divider" style={{ margin: "8px 0" }} />
            <FlowRow label="Net to you" value="$84,210" strong />
          </div>
        </div>
      </div>
    </div>
  );
}

function RetRow({ label, pct, c, n }) {
  return (
    <div>
      <div className="row between" style={{ marginBottom: 4 }}>
        <span style={{ fontSize: 13 }}>{label}</span>
        <span className="row-tight">
          {n != null && <span className="mono tiny muted">{n}</span>}
          <span className="mono tiny" style={{ fontWeight: 500 }}>{pct}%</span>
        </span>
      </div>
      <div className="bar"><span style={{ width: `${pct}%`, background: c }} /></div>
    </div>
  );
}

function FlowRow({ label, value, tone, strong }) {
  return (
    <div className="row between" style={{ padding: "6px 0" }}>
      <span style={{ fontSize: 13, color: strong ? "var(--ink)" : "var(--ink-2)", fontWeight: strong ? 600 : 400 }}>{label}</span>
      <span className="mono" style={{
        fontSize: strong ? 16 : 13,
        fontWeight: strong ? 600 : 500,
        color: tone === "neg" ? "var(--neg)" : tone === "pos" ? "var(--pos)" : "var(--ink)",
      }}>{value}</span>
    </div>
  );
}

function DemandHeatmap() {
  // 7 days × 12 hours (9am–8pm)
  const days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
  const hours = Array.from({ length: 12 }, (_, i) => i + 9);
  // synthetic but stable data — busier in evenings & weekends
  const seed = (d, h) => {
    let base = (h >= 16 ? 8 : h >= 12 ? 5 : 3);
    if (d === 4) base += 3; // Friday
    if (d === 5) base += 2; // Saturday
    if (d === 6) base -= 2; // Sunday
    if (h === 13) base -= 2; // lunch
    base += ((d * 7 + h * 3) % 4);
    return Math.max(0, Math.min(10, base));
  };

  return (
    <div>
      <div style={{ display: "grid", gridTemplateColumns: "48px repeat(12, 1fr)", gap: 4, marginBottom: 4 }}>
        <div />
        {hours.map((h) => (
          <div key={h} className="mono tiny muted" style={{ textAlign: "center" }}>{h}</div>
        ))}
      </div>
      {days.map((d, di) => (
        <div key={d} style={{ display: "grid", gridTemplateColumns: "48px repeat(12, 1fr)", gap: 4, marginBottom: 4 }}>
          <div className="mono tiny muted" style={{ display: "flex", alignItems: "center" }}>{d}</div>
          {hours.map((h) => {
            const v = seed(di, h);
            return (
              <div key={h} style={{
                aspectRatio: "1.4 / 1",
                background: v === 0 ? "var(--surface-3)" :
                  `oklch(${94 - v * 3.5}% ${0.04 + v * 0.014} 145)`,
                borderRadius: 4,
              }} />
            );
          })}
        </div>
      ))}
      <div className="row" style={{ marginTop: 12, gap: 8 }}>
        <span className="mono tiny muted">Less</span>
        {[0, 2, 4, 6, 8, 10].map(v => (
          <span key={v} style={{
            width: 14, height: 14, borderRadius: 3,
            background: v === 0 ? "var(--surface-3)" : `oklch(${94 - v * 3.5}% ${0.04 + v * 0.014} 145)`,
          }} />
        ))}
        <span className="mono tiny muted">More</span>
      </div>
    </div>
  );
}

function VendorSupport() {
  return <window.SupportPage kind="vendor" />;
}

window.VendorApp = VendorApp;

/* ====================================================================
   VENDOR — GALLERY
   ==================================================================== */
function VendorGallery() {
  const [tab, setTab] = React.useState("all");
  const cats = [
    { k: "all", l: "All", n: 48 },
    { k: "color", l: "Color", n: 22 },
    { k: "cuts", l: "Cuts", n: 14 },
    { k: "interior", l: "Studio", n: 8 },
    { k: "team", l: "Team", n: 4 },
  ];
  return (
    <div className="page-enter">
      <window.DemoBanner feature="gallery" />
      <window.DemoBanner feature="vendor support" />
      <S.PageHead
        eyebrow="48 images · 4 collections"
        title="Gallery"
        sub="Show off your best work. Photos appear on your booking page and in Discover."
        right={<>
          <S.Btn variant="outline" size="sm" icon={<I.list size={14} />}>Collections</S.Btn>
          <S.Btn variant="primary" size="sm" icon={<I.plus size={14} />}>Upload photos</S.Btn>
        </>}
      />

      <div className="card" style={{ padding: 22, marginBottom: 20, borderStyle: "dashed", borderColor: "var(--border-strong)", borderWidth: 2 }}>
        <div className="row" style={{ gap: 16, alignItems: "center" }}>
          <div style={{
            width: 56, height: 56, borderRadius: 14, background: "var(--accent-soft)", color: "var(--accent-ink)",
            display: "flex", alignItems: "center", justifyContent: "center",
          }}><I.export size={24} /></div>
          <div style={{ flex: 1 }}>
            <div style={{ fontWeight: 500, fontSize: 15 }}>Drag &amp; drop photos here</div>
            <div className="muted tiny" style={{ marginTop: 4 }}>JPG or PNG · up to 12 MB each · we’ll auto-crop and optimize</div>
          </div>
          <S.Btn variant="outline" size="sm">Browse files</S.Btn>
        </div>
      </div>

      <div className="row" style={{ gap: 8, marginBottom: 18, overflowX: "auto" }}>
        {cats.map((c) => (
          <button key={c.k} onClick={() => setTab(c.k)}
            className={`btn btn-sm ${tab === c.k ? "btn-primary" : "btn-outline"}`}>
            {c.l} <span className="mono tiny" style={{ marginLeft: 6, opacity: 0.7 }}>{c.n}</span>
          </button>
        ))}
        <div className="spacer" />
        <S.Btn variant="ghost" size="sm" iconRight={<I.chevD size={12} />}>Newest first</S.Btn>
      </div>

      {/* mosaic grid */}
      <div style={{
        display: "grid", gridTemplateColumns: "repeat(4, 1fr)",
        gridAutoRows: 140, gap: 12,
      }}>
        {GALLERY.map((g, i) => (
          <div key={i} style={{
            gridColumn: g.col || "span 1", gridRow: g.row || "span 1",
            position: "relative", borderRadius: 14, overflow: "hidden",
          }} className="placeholder-img">
            <div style={{
              position: "absolute", inset: 0, padding: 12,
              display: "flex", flexDirection: "column", justifyContent: "flex-end",
              background: "linear-gradient(180deg, transparent 50%, oklch(0% 0 0 / 0.55) 100%)",
              color: "white",
            }}>
              <div style={{ display: "flex", justifyContent: "space-between", marginTop: "auto" }}>
                <S.Chip tone="accent" style={{ background: "oklch(100% 0 0 / 0.92)" }}>{g.tag}</S.Chip>
                <span className="mono tiny" style={{ background: "oklch(0% 0 0 / 0.50)", color: "white", padding: "3px 7px", borderRadius: 999 }}>
                  <I.heart size={10} /> {g.likes}
                </span>
              </div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

const GALLERY = [
  { tag: "Color", likes: 142, col: "span 2", row: "span 2" },
  { tag: "Cut",   likes: 88 },
  { tag: "Color", likes: 64 },
  { tag: "Color", likes: 218, col: "span 1", row: "span 2" },
  { tag: "Studio", likes: 32 },
  { tag: "Team",  likes: 124 },
  { tag: "Color", likes: 76 },
  { tag: "Cut",   likes: 48, col: "span 2" },
  { tag: "Color", likes: 92 },
  { tag: "Studio", likes: 28, col: "span 1", row: "span 1" },
  { tag: "Color", likes: 156 },
  { tag: "Cut",   likes: 72 },
];

/* ====================================================================
   VENDOR — SETTINGS
   ==================================================================== */
function VendorSettings() {
  const [confirm, setConfirm] = React.useState(null);
  const sections = [
    { key: "business", label: "Business settings", icon: I.store, render: () => <window.ProfileSection kind="vendor" /> },
    { key: "email", label: "Change email", icon: I.mail, render: () => <window.EmailSection current="hello@maisoncolor.fr" /> },
    { key: "password", label: "Change password", icon: I.settings, render: () => <window.PasswordSection /> },
    { key: "invite", label: "Invite friends", icon: I.heart, render: () => <window.InviteSection kind="vendor" /> },
    { key: "notifications", label: "Notifications", icon: I.bell, render: () => <window.NotificationsSection kind="vendor" /> },
    { divider: true, label: "Legal", key: "_legal" },
    { key: "privacy", label: "Privacy Policy", icon: I.help, link: "https://pamp.app/legal/privacy" },
    { key: "terms-use", label: "Terms of Use", icon: I.help, link: "https://pamp.app/legal/terms-of-use" },
    { key: "terms-service", label: "Terms of Service", icon: I.help, link: "https://pamp.app/legal/terms-of-service" },
    { divider: true, label: "Account", key: "_danger" },
    { key: "danger", label: "Danger zone", icon: I.x, render: () => <window.DangerSection kind="vendor" openConfirm={setConfirm} /> },
  ];
  return <>
    <window.SettingsShell sections={sections} />
    <window.M.ConfirmModal
      open={!!confirm}
      onClose={() => setConfirm(null)}
      onConfirm={() => setConfirm(null)}
      title={confirm?.title}
      body={confirm?.body}
      confirmLabel={confirm?.cta}
      icon={confirm?.icon}
      danger={confirm?.tone === "danger"}
    />
  </>;
}

window.VendorGallery = VendorGallery;
window.VendorSettings = VendorSettings;

/* ====================================================================
   VENDOR — SHARED: native select styled like text-input
   ==================================================================== */
function VSelect({ value, onChange, options, placeholder }) {
  return (
    <div className="text-input" style={{ display: "flex", alignItems: "center", padding: "0 12px 0 14px", position: "relative" }}>
      <select
        value={value}
        onChange={(e) => onChange?.(e.target.value)}
        style={{
          flex: 1, height: "100%", border: 0, background: "transparent",
          outline: "none", color: value ? "var(--ink)" : "var(--ink-4)",
          fontSize: 13.5, appearance: "none", cursor: "pointer", paddingRight: 8,
        }}
      >
        {placeholder && <option value="">{placeholder}</option>}
        {options.map((o) => {
          const val = typeof o === "string" ? o : o.value;
          const lab = typeof o === "string" ? o : o.label;
          return <option key={val} value={val}>{lab}</option>;
        })}
      </select>
      <I.chevD size={14} style={{ color: "var(--ink-3)", pointerEvents: "none" }} />
    </div>
  );
}

/* ====================================================================
   VENDOR — NEW APPOINTMENT MODAL
   ==================================================================== */
const APPT_SERVICES = [
  { value: "Full single-process color", price: 145, dur: 90 },
  { value: "Balayage · long hair", price: 285, dur: 180 },
  { value: "Root touch-up", price: 95, dur: 60 },
  { value: "Cut & blowout", price: 110, dur: 75 },
  { value: "Bang trim", price: 25, dur: 15 },
  { value: "K18 bond repair", price: 60, dur: 30 },
];
const APPT_STAFF = ["Any available", "Léa Marchand", "Nina Park", "Sam Okafor", "Mia Russo"];
const APPT_TIMES = ["9:00 AM", "9:30 AM", "10:00 AM", "10:30 AM", "11:00 AM", "11:30 AM",
  "12:00 PM", "1:00 PM", "1:30 PM", "2:00 PM", "2:30 PM", "3:00 PM", "3:30 PM", "4:00 PM", "5:00 PM"];

function NewAppointmentModal({ open, onClose, onCreate }) {
  const today = new Date(2026, 1, 2);
  const iso = (d) => d.toISOString().slice(0, 10);
  const blank = { client: "", phone: "", service: APPT_SERVICES[0].value, staff: "Any available", date: iso(today), time: "10:00 AM", notes: "" };
  const [data, setData] = React.useState(blank);
  const [errors, setErrors] = React.useState({});
  const [done, setDone] = React.useState(false);

  React.useEffect(() => { if (open) { setData(blank); setErrors({}); setDone(false); } }, [open]);
  if (!open) return null;

  const set = (k, v) => { setData((d) => ({ ...d, [k]: v })); setErrors((e) => ({ ...e, [k]: undefined })); };
  const svc = APPT_SERVICES.find((s) => s.value === data.service);

  const submit = () => {
    const e = {};
    if (!data.client.trim()) e.client = "Client name is required.";
    if (!data.date) e.date = "Pick a date.";
    if (!data.time) e.time = "Pick a time.";
    setErrors(e);
    if (Object.keys(e).length) return;
    onCreate?.(data);
    setDone(true);
  };

  const prettyDate = (() => {
    try {
      const d = new Date(data.date + "T00:00:00");
      return d.toLocaleDateString("en-US", { weekday: "long", month: "long", day: "numeric" });
    } catch { return data.date; }
  })();

  if (done) {
    return (
      <window.M.Modal open={open} onClose={onClose} size="lg">
        <div style={{ textAlign: "center", padding: "20px 0 8px" }}>
          <div style={{
            width: 72, height: 72, borderRadius: "50%", margin: "0 auto 20px",
            background: "var(--accent-soft)", color: "var(--accent-ink)",
            display: "flex", alignItems: "center", justifyContent: "center",
          }}><I.check size={34} /></div>
          <div className="display" style={{ fontSize: 26, letterSpacing: "-0.02em" }}>Appointment booked</div>
          <div className="muted" style={{ fontSize: 13.5, marginTop: 6 }}>
            {data.service} for <strong>{data.client}</strong> · {prettyDate} at {data.time}
          </div>
          <div style={{
            marginTop: 20, padding: 16, borderRadius: 14, border: "1px solid var(--border)",
            background: "var(--surface-2)", textAlign: "left",
          }}>
            <div className="row between" style={{ marginBottom: 10 }}>
              <span className="muted tiny">Staff</span>
              <span style={{ fontSize: 13, fontWeight: 500 }}>{data.staff}</span>
            </div>
            <div className="row between" style={{ marginBottom: 10 }}>
              <span className="muted tiny">Duration</span>
              <span style={{ fontSize: 13, fontWeight: 500 }}>{svc?.dur} min</span>
            </div>
            <div className="row between">
              <span className="muted tiny">Price</span>
              <span className="display" style={{ fontSize: 18 }}>${svc?.price}</span>
            </div>
          </div>
        </div>
        <div className="row" style={{ justifyContent: "center", gap: 8, marginTop: 22 }}>
          <S.Btn variant="primary" onClick={onClose}>Done</S.Btn>
        </div>
      </window.M.Modal>
    );
  }

  return (
    <window.M.Modal open={open} onClose={onClose} size="lg"
      icon={<I.calendar />} title="New appointment"
      subtitle="Book a client into an open slot. They'll get a confirmation by text."
      footer={<>
        <div className="row-tight" style={{ marginRight: "auto", gap: 10 }}>
          <span className="muted tiny">Total</span>
          <span className="display" style={{ fontSize: 20 }}>${svc?.price || 0}</span>
          <span className="muted tiny">· {svc?.dur} min</span>
        </div>
        <S.Btn variant="ghost" onClick={onClose}>Cancel</S.Btn>
        <S.Btn variant="primary" iconRight={<I.arrowR size={14} />} onClick={submit}>Book appointment</S.Btn>
      </>}
    >
      <window.M.FormGrid>
        <window.M.Field label="Client name" error={errors.client}>
          <window.M.TextField icon={<I.staff size={14} />} value={data.client} onChange={(v) => set("client", v)} placeholder="Amelia Brooks" />
        </window.M.Field>
        <window.M.Field label="Phone">
          <window.M.TextField icon={<I.phone size={14} />} value={data.phone} onChange={(v) => set("phone", v)} placeholder="+44 7700 900 142" />
        </window.M.Field>
        <window.M.Field full label="Service">
          <VSelect value={data.service} onChange={(v) => set("service", v)}
            options={APPT_SERVICES.map((s) => ({ value: s.value, label: `${s.value} · $${s.price} · ${s.dur} min` }))} />
        </window.M.Field>
        <window.M.Field full label="Staff">
          <VSelect value={data.staff} onChange={(v) => set("staff", v)} options={APPT_STAFF} />
        </window.M.Field>
        <window.M.Field label="Date" error={errors.date}>
          <window.M.TextField type="date" value={data.date} onChange={(v) => set("date", v)} />
        </window.M.Field>
        <window.M.Field label="Time" error={errors.time}>
          <VSelect value={data.time} onChange={(v) => set("time", v)} options={APPT_TIMES} placeholder="Select a time" />
        </window.M.Field>
        <window.M.Field full label="Notes" hint="Allergies, preferences, anything the stylist should know.">
          <window.M.Textarea value={data.notes} onChange={(v) => set("notes", v)} rows={3} placeholder="e.g. Allergic to PPD · prefers cooler blondes" />
        </window.M.Field>
      </window.M.FormGrid>
    </window.M.Modal>
  );
}
window.NewAppointmentModal = NewAppointmentModal;

/* ====================================================================
   VENDOR — NEW SERVICE MODAL
   ==================================================================== */
const SERVICE_CATS = ["Color", "Cut", "Treatment", "Styling", "Add-on"];

function NewServiceModal({ open, onClose, onCreate }) {
  const blank = { name: "", cat: "Color", dur: "", price: "", desc: "", active: true };
  const [data, setData] = React.useState(blank);
  const [errors, setErrors] = React.useState({});

  React.useEffect(() => { if (open) { setData(blank); setErrors({}); } }, [open]);
  if (!open) return null;

  const set = (k, v) => { setData((d) => ({ ...d, [k]: v })); setErrors((e) => ({ ...e, [k]: undefined })); };

  const submit = () => {
    const e = {};
    if (!data.name.trim()) e.name = "Service name is required.";
    if (!data.dur || isNaN(+data.dur) || +data.dur <= 0) e.dur = "Enter a duration in minutes.";
    if (!data.price || isNaN(+data.price) || +data.price < 0) e.price = "Enter a price.";
    setErrors(e);
    if (Object.keys(e).length) return;
    onCreate?.({
      cat: data.cat, name: data.name.trim(),
      dur: +data.dur, price: +data.price, desc: data.desc.trim(),
      bookings: 0, active: data.active,
    });
  };

  return (
    <window.M.Modal open={open} onClose={onClose} size="lg"
      icon={<I.scissors />} title="New service"
      subtitle="Add a service to your menu. Clients can book it right away."
      footer={<>
        <S.Btn variant="ghost" onClick={onClose}>Cancel</S.Btn>
        <S.Btn variant="primary" iconRight={<I.arrowR size={14} />} onClick={submit}>Add service</S.Btn>
      </>}
    >
      <window.M.FormGrid>
        <window.M.Field full label="Service name" error={errors.name}>
          <window.M.TextField value={data.name} onChange={(v) => set("name", v)} placeholder="e.g. Glossing treatment" />
        </window.M.Field>
        <window.M.Field full label="Category">
          <VSelect value={data.cat} onChange={(v) => set("cat", v)} options={SERVICE_CATS} />
        </window.M.Field>
        <window.M.Field label="Duration" error={errors.dur}>
          <window.M.TextField type="number" value={data.dur} onChange={(v) => set("dur", v)} placeholder="60"
            icon={<I.clock size={14} />} suffix={<span className="muted tiny">min</span>} />
        </window.M.Field>
        <window.M.Field label="Price" error={errors.price}>
          <window.M.TextField type="number" value={data.price} onChange={(v) => set("price", v)} placeholder="120"
            icon={<span className="muted" style={{ fontSize: 13.5 }}>$</span>} />
        </window.M.Field>
        <window.M.Field full label="Description" hint="A short line clients see when booking.">
          <window.M.Textarea value={data.desc} onChange={(v) => set("desc", v)} rows={2} placeholder="What's included, who it's for…" />
        </window.M.Field>
        <window.M.Field full label="Availability">
          <div className="row" style={{ gap: 10 }}>
            {[{ v: true, l: "Active · bookable now" }, { v: false, l: "Draft · hidden" }].map((o) => {
              const on = data.active === o.v;
              return (
                <button key={String(o.v)} type="button" onClick={() => set("active", o.v)}
                  className="row" style={{
                    flex: 1, padding: "12px 14px", gap: 10,
                    border: `1px solid ${on ? "var(--accent)" : "var(--border-strong)"}`,
                    borderRadius: "var(--r-md)", background: on ? "var(--accent-soft)" : "var(--surface)",
                    textAlign: "left",
                  }}>
                  <span className="cb-box" data-checked={on} style={{ borderRadius: "50%" }}>{on && <I.check size={11} />}</span>
                  <span style={{ fontSize: 13, fontWeight: 500 }}>{o.l}</span>
                </button>
              );
            })}
          </div>
        </window.M.Field>
      </window.M.FormGrid>
    </window.M.Modal>
  );
}
window.NewServiceModal = NewServiceModal;
