// GuestMaker CRM B2B · accounts list, account sheet (8 tabs), B2B contact record.

function AppFrame({ url, children, height }) {
  return (
    <div style={{
      border: `1px solid ${RULE}`, borderRadius: 12, overflow: "hidden", background: SURFACE,
      boxShadow: "0 40px 90px -50px rgba(26,20,26,0.45)",
    }}>
      <div style={{ display: "flex", alignItems: "center", gap: 7, background: PAPER, borderBottom: `1px solid ${RULE}`, padding: "8px 12px" }}>
        <Dot color="#e0d8cc" size={8} /><Dot color="#e0d8cc" size={8} /><Dot color="#e0d8cc" size={8} />
        <div style={{ flex: 1, display: "grid", placeItems: "center" }}>
          <span style={{ background: SURFACE, border: `1px solid ${RULE}`, borderRadius: 999, padding: "3px 14px" }}>
            <Mono size={9.5} color={DIM}>{url}</Mono>
          </span>
        </div>
        <Icon name="refresh" size={11} color={FAINT} />
      </div>
      <div style={{ position: "relative", height, overflow: "hidden" }}>{children}</div>
    </div>
  );
}

function KpiTile({ label, value, sub, accent = FUCHSIA, wide }) {
  return (
    <div style={{ background: SURFACE, border: `1px solid ${RULE}`, borderRadius: 9, padding: "11px 13px 12px", position: "relative", overflow: "hidden", gridColumn: wide ? "span 2" : "auto" }}>
      <span style={{ position: "absolute", top: 0, left: 0, right: 0, height: 2, background: `linear-gradient(90deg,${accent},${accent}00)` }} />
      <Mono size={9} color={FAINT} style={{ letterSpacing: "0.16em", fontWeight: 700 }}>{label.toUpperCase()}</Mono>
      <div style={{ fontFamily: MONO, fontSize: 21, fontWeight: 700, letterSpacing: "-0.03em", margin: "5px 0 2px" }}>{value}</div>
      {sub && <Mono size={9.5} color={DIM}>{sub}</Mono>}
    </div>
  );
}

function ProfileChip({ profile }) {
  const mice = profile === "MICE";
  return <span style={{
    background: mice ? FUCHSIA_PALE + "70" : PAPER, border: `1px solid ${mice ? FUCHSIA_PALE : RULE}`,
    color: mice ? FUCHSIA_DARK : PLUM, borderRadius: 4, padding: "1px 5px", fontFamily: MONO, fontSize: 8.5, fontWeight: 700, letterSpacing: "0.08em",
  }}>{mice ? "MICE" : "CORP"}</span>;
}

function AccountsFrame() {
  const [q, setQ] = useState("");
  const [profile, setProfile] = useState("all");
  const [type, setType] = useState("all");
  const [mgr, setMgr] = useState("all");
  const [status, setStatus] = useState("all");
  const [open, setOpen] = useState(null);

  const rowsFlat = ACCOUNTS
    .filter(a => !q || (a.name + a.legal + a.cif + a.iata).toLowerCase().includes(q.toLowerCase()))
    .filter(a => profile === "all" || a.profile === profile)
    .filter(a => type === "all" || a.type === type)
    .filter(a => mgr === "all" || a.manager === mgr)
    .filter(a => status === "all" || a.status === status);

  /* The data has always carried parent/children, but the table ignored it:
     children sorted wherever the source array put them and announced
     themselves with a "child of X" label instead of sitting under the
     parent. The real product groups them — parent row with a disclosure and
     a Family pill, children indented beneath it — so this does the same.
     A child whose parent was filtered out is promoted to a root rather than
     silently dropped, otherwise a type or status filter can make rows
     disappear with nothing to explain why. */
  const visible = new Set(rowsFlat.map(a => a.id));
  const ordered = [];
  for (const a of rowsFlat) {
    if (a.parent && visible.has(a.parent)) continue;
    ordered.push({ ...a, depth: 0 });
    for (const kid of rowsFlat.filter(k => k.parent === a.id)) {
      ordered.push({ ...kid, depth: 1 });
    }
  }
  const familySize = id => ACCOUNTS.filter(k => k.parent === id).length;
  const th = { textAlign: "left", padding: "9px 12px", borderBottom: `1px solid ${RULE}`, whiteSpace: "nowrap" };
  const td = { padding: "10px 12px", borderBottom: `1px solid ${RULE_SOFT}`, fontSize: 12 };

  return (
    <div style={{ position: "relative", display: "flex", background: SURFACE, height: "100%" }}>
      <SideNav active="Agencies & Companies" />
      <div style={{ flex: 1, minWidth: 0, display: "flex", flexDirection: "column", overflow: "hidden" }}>
        <div style={{ display: "flex", alignItems: "center", gap: 10, padding: "10px 18px", borderBottom: `1px solid ${RULE}` }}>
          <Mono size={9.5} color={FAINT} style={{ letterSpacing: "0.16em", fontWeight: 600 }}>DATA</Mono>
          <Icon name="chevron-r" size={10} color={FAINT} />
          <Mono size={9.5} color={INK} style={{ letterSpacing: "0.16em", fontWeight: 700 }}>AGENCIES &amp; COMPANIES</Mono>
          <div style={{ flex: 1 }} />
          <Avatar who="ko" size={24} />
        </div>
        <div style={{ padding: "16px 18px 0", display: "flex", alignItems: "flex-start", gap: 12 }}>
          <div style={{ flex: 1 }}>
            <h3 style={{ fontFamily: SERIF, fontSize: 27, fontWeight: 500, margin: 0, letterSpacing: "-0.02em" }}>Agencies &amp; Companies</h3>
            <p style={{ fontSize: 12, color: DIM, margin: "5px 0 0" }}>Travel agencies, tour operators, DMCs and corporate accounts, {ordered.length} of {ACCOUNTS.length} accounts</p>
          </div>
          <div style={{ display: "flex", gap: 7 }}>
            <ChromeButton icon="download">Export CSV</ChromeButton>
            <ChromeButton icon="upload">Import</ChromeButton>
            <ChromeButton kind="solid" icon="plus">New account</ChromeButton>
          </div>
        </div>
        <div style={{ display: "flex", gap: 8, padding: "14px 18px", flexWrap: "wrap" }}>
          <label style={{ position: "relative", display: "inline-flex", alignItems: "center" }}>
            <span style={{ position: "absolute", left: 9 }}><Icon name="search" size={12} color={FAINT} /></span>
            <input value={q} onChange={e => setQ(e.target.value)} placeholder="Search by name, tax ID, or IATA..." style={{
              width: 230, height: 30, borderRadius: 7, border: `1px solid ${RULE}`, background: SURFACE, padding: "0 10px 0 27px", fontFamily: SANS, fontSize: 11.5,
            }} />
          </label>
          <Select value={profile} width={124} onChange={setProfile} options={[{ v: "all", l: "All profiles" }, { v: "CORP", l: "Corporate" }, { v: "MICE", l: "MICE" }]} />
          <Select value={type} width={158} onChange={setType} options={[{ v: "all", l: "All types" }, ...ACC_TYPES.map(t => ({ v: t, l: t }))]} />
          <Select value={mgr} icon="user" width={158} onChange={setMgr} options={[{ v: "all", l: "All managers" }, ...USERS.map(u => ({ v: u.id, l: u.name }))]} />
          <Select value={status} width={124} onChange={setStatus} options={[{ v: "all", l: "All statuses" }, { v: "Active", l: "Active" }, { v: "Prospect", l: "Prospect" }]} />
          <div style={{ flex: 1 }} />
          <ChromeButton icon="board">Columns</ChromeButton>
        </div>
        <div style={{ margin: "0 18px 18px", border: `1px solid ${RULE}`, borderRadius: 9, overflow: "auto", flex: 1, background: SURFACE }}>
          <div style={{ display: "flex", alignItems: "center", gap: 9, padding: "9px 12px", background: PAPER, borderBottom: `1px solid ${RULE}` }}>
            <Icon name="briefcase" size={12} color={DIM} />
            <Mono size={9.5} color={DIM} style={{ letterSpacing: "0.16em", fontWeight: 700 }}>ACCOUNTS</Mono>
            <span style={{ background: SURFACE, border: `1px solid ${RULE}`, borderRadius: 999, padding: "1px 7px" }}><Mono size={9.5} color={INK} style={{ fontWeight: 700 }}>{ordered.length}</Mono></span>
            <div style={{ flex: 1 }} />
            <span style={{ display: "inline-flex", alignItems: "center", gap: 6, background: FUCHSIA_PALE + "50", border: `1px solid ${FUCHSIA_PALE}`, borderRadius: 999, padding: "3px 9px" }}>
              <Icon name="spark" size={10} color={FUCHSIA_DARK} />
              <Mono size={9.5} color={FUCHSIA_DARK} style={{ fontWeight: 600 }}>3 MATCH SUGGESTIONS TO CONFIRM</Mono>
            </span>
          </div>
          <table style={{ width: "100%", borderCollapse: "collapse", fontFamily: SANS }}>
            <thead>
              <tr>{["Name", "Type", "Account manager", "Primary contact", "Open deals", "Attributed RN", "Status"].map(h => (
                <th key={h} style={th}><Mono size={9.5} color={DIM} style={{ letterSpacing: "0.14em", fontWeight: 700 }}>{h.toUpperCase()}</Mono></th>
              ))}</tr>
            </thead>
            <tbody>
              {ordered.map(a => {
                const ct = CT_BY_ID[a.contacts[0]];
                return (
                  <tr key={a.id} onClick={() => setOpen(a.id)} style={{ cursor: "pointer" }}>
                    <td style={{ ...td, paddingLeft: a.depth ? 30 : 12 }}>
                      <div style={{ display: "flex", alignItems: "center", gap: 9 }}>
                        {/* Parents get a disclosure, children a dot on the
                            rail beneath it, so the indent reads as hierarchy
                            rather than as stray padding. */}
                        {a.depth === 0 && familySize(a.id) > 0
                          ? <Icon name="chevron-d" size={11} color={FAINT} />
                          : a.depth
                            ? <span style={{ width: 5, height: 5, borderRadius: "50%", background: RULE, flexShrink: 0, marginLeft: 3, marginRight: 3 }} />
                            : <span style={{ width: 11, flexShrink: 0 }} />}
                        <AccountBadge id={a.id} size={a.depth ? 21 : 24} />
                        <div>
                          <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
                            <span style={{ fontWeight: a.depth ? 500 : 600 }}>{a.name}</span>
                            <ProfileChip profile={a.profile} />
                            {familySize(a.id) > 0 && (
                              <span style={{
                                display: "inline-flex", alignItems: "center", gap: 4,
                                background: FUCHSIA_PALE + "60", border: `1px solid ${FUCHSIA_PALE}`,
                                borderRadius: 999, padding: "1px 7px",
                              }}>
                                <Icon name="users" size={9} color={FUCHSIA_DARK} />
                                <Mono size={8.5} color={FUCHSIA_DARK} style={{ fontWeight: 700 }}>
                                  Family · {familySize(a.id) + 1}
                                </Mono>
                              </span>
                            )}
                          </div>
                          <Mono size={9.5} color={FAINT}>{a.legal}</Mono>
                        </div>
                      </div>
                    </td>
                    <td style={{ ...td, color: DIM }}>{a.type}</td>
                    <td style={td}><span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}><Avatar who={a.manager} size={18} /><span style={{ color: DIM }}>{USER_BY_ID[a.manager].name}</span></span></td>
                    <td style={td}>
                      <div style={{ fontWeight: 500 }}>{ct.name}</div>
                      <Mono size={9.5} color={FAINT}>{ct.email}</Mono>
                    </td>
                    <td style={td}><span style={{ background: FUCHSIA_PALE + "60", border: `1px solid ${FUCHSIA_PALE}`, borderRadius: 999, padding: "2px 8px", fontFamily: MONO, fontSize: 10.5, fontWeight: 700, color: FUCHSIA_DARK }}>{a.openDeals}</span></td>
                    <td style={{ ...td, fontFamily: MONO, color: INK }}>{num(a.prod.rn)}</td>
                    <td style={td}>
                      <span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
                        <Dot color={a.status === "Active" ? GREEN : AMBER} size={6} />
                        <span style={{ color: DIM }}>{a.status}</span>
                      </span>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </div>
      {open && <AccountDrawer acc={ACC_BY_ID[open]} onClose={() => setOpen(null)} />}
    </div>
  );
}

const ACC_TABS = [["overview", "Overview", "chart"], ["contacts", "Contacts", "users"], ["terms", "Terms", "percent"],
  ["deals", "Deals", "board"], ["activity", "Activity", "clock"], ["docs", "Documents", "file"],
  ["prod", "Production", "bed"], ["comm", "Commissions", "euro"]];

function AccountDrawer({ acc, onClose }) {
  const [tab, setTab] = useState("overview");
  const [children, setChildren] = useState(false);
  const kids = acc.children.map(id => ACC_BY_ID[id]);
  const eff = { ...acc.prod };
  if (children && kids.length) kids.forEach(k => { eff.res += k.prod.res; eff.rn += k.prod.rn; eff.revenue += k.prod.revenue; eff.commissionCost += k.prod.commissionCost; });
  const bookings = useMemo(() => {
    const own = bookingsFor(acc.id, 8);
    return children && kids.length ? [...own, ...kids.flatMap(k => bookingsFor(k.id, 4).map(b => ({ ...b, child: k.name })))].sort((a, b) => a.checkin < b.checkin ? 1 : -1) : own;
  }, [acc.id, children]);
  const comms = useMemo(() => commissionsFor(acc.id), [acc.id]);
  const commTotals = ["Accrued", "Invoiced", "Settled", "Cancelled"].map(s => [s, comms.filter(c => c.state === s).reduce((t, c) => t + c.amount, 0)]);
  const deals = DEALS.filter(d => d.acc === acc.id || (children && acc.children.includes(d.acc)));
  const rate = acc.commission ?? (acc.parent ? ACC_BY_ID[acc.parent].commission : 0);

  return (
    <div style={{ position: "absolute", inset: 0, zIndex: 45, display: "flex", justifyContent: "flex-end" }}>
      <div onClick={onClose} style={{ position: "absolute", inset: 0, background: "rgba(26,20,26,0.28)" }} />
      <div style={{
        position: "relative", width: 620, maxWidth: "96%", background: SURFACE, borderLeft: `1px solid ${RULE}`,
        boxShadow: "-30px 0 70px -40px rgba(0,0,0,0.55)", display: "flex", flexDirection: "column",
        animation: "gm-slide-left .22s cubic-bezier(.22,.8,.3,1)",
      }}>
        <div style={{ padding: "14px 18px 0" }}>
          <div style={{ display: "flex", gap: 11, alignItems: "flex-start", marginBottom: 12 }}>
            <AccountBadge id={acc.id} size={34} />
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }}>
                <h3 style={{ fontFamily: SERIF, fontSize: 21, fontWeight: 500, margin: 0, letterSpacing: "-0.02em" }}>{acc.name}</h3>
                <ProfileChip profile={acc.profile} />
                <span style={{ display: "inline-flex", alignItems: "center", gap: 5 }}><Dot color={acc.status === "Active" ? GREEN : AMBER} size = {6} /><Mono size={10} color={DIM}>{acc.status}</Mono></span>
              </div>
              <Mono size={10} color={FAINT}>{acc.legal} · {acc.type}</Mono>
            </div>
            <button onClick={onClose} style={{ background: "none", border: "none", cursor: "pointer", padding: 4 }}><Icon name="x" size={15} color={FAINT} /></button>
          </div>
          <div style={{ display: "flex", gap: 14, flexWrap: "wrap", paddingBottom: 12, borderBottom: `1px dashed ${RULE}` }}>
            {[["TAX ID", acc.cif], ["IATA", acc.iata], ["CHANNEL MGR", acc.cm], ["CRS", acc.crs], ["ENGINE ID", acc.engineId]].map(([k, v]) => (
              <div key={k}><Mono size={8.5} color={FAINT} style={{ letterSpacing: "0.16em", fontWeight: 700 }}>{k}</Mono>
                <div><Mono size={11} color={INK} style={{ fontWeight: 600 }}>{v}</Mono></div></div>
            ))}
            <div><Mono size={8.5} color={FAINT} style={{ letterSpacing: "0.16em", fontWeight: 700 }}>MANAGER</Mono>
              <div style={{ display: "flex", alignItems: "center", gap: 5, marginTop: 1 }}><Avatar who={acc.manager} size={17} /><span style={{ fontSize: 11.5, fontWeight: 600 }}>{USER_BY_ID[acc.manager].name}</span></div></div>
          </div>
          {(acc.parent || kids.length) && (
            <div style={{ display: "flex", alignItems: "center", gap: 9, padding: "10px 0" }}>
              <Icon name="layers" size={12} color={FUCHSIA} />
              <Mono size={10} color={DIM}>
                {acc.parent ? <>Child of <b style={{ color: INK }}>{ACC_BY_ID[acc.parent].name}</b> · terms inherited from the nearest ancestor</> : <>Parent of <b style={{ color: INK }}>{kids.map(k => k.name).join(", ")}</b> · production rolls up</>}
              </Mono>
              {kids.length ? <><div style={{ flex: 1 }} /><MiniToggle on={children} onChange={setChildren} label="Include child accounts" /></> : null}
            </div>
          )}
          <div style={{ display: "flex", gap: 14, marginTop: 8, overflowX: "auto", borderBottom: `1px solid ${RULE}` }}>
            {ACC_TABS.map(([k, l, ic]) => (
              <button key={k} onClick={() => setTab(k)} style={{
                display: "inline-flex", alignItems: "center", gap: 6, padding: "0 1px 8px", background: "none", cursor: "pointer",
                border: "none", borderBottom: `2px solid ${tab === k ? FUCHSIA : "transparent"}`, whiteSpace: "nowrap",
                color: tab === k ? INK : DIM, fontFamily: SANS, fontSize: 11.5, fontWeight: tab === k ? 600 : 500,
              }}><Icon name={ic} size={11} color={tab === k ? FUCHSIA : FAINT} />{l}</button>
            ))}
          </div>
        </div>

        <div style={{ flex: 1, overflowY: "auto", padding: "14px 18px 22px", background: CREAM }}>
          {tab === "overview" && (
            <>
              <div style={{ display: "grid", gridTemplateColumns: "repeat(3,1fr)", gap: 9 }}>
                <KpiTile label="Open pipeline" value={eur(acc.kpi.openPipeline)} sub={`${acc.openDeals} open deals`} />
                <KpiTile label="Won this year" value={eur(acc.kpi.wonYTD)} sub="signed contracts" accent={GREEN} />
                <KpiTile label="Room nights YTD" value={num(children ? eff.rn : acc.kpi.rnYTD)} sub={acc.rnCommitment ? `${Math.round((acc.kpi.rnYTD / acc.rnCommitment) * 100)}% of ${num(acc.rnCommitment)} committed` : "no commitment"} accent={VIOLET} />
                <KpiTile label="Commission accrued" value={eur(acc.kpi.commissionAccrued)} sub={rate ? `${rate}% effective rate` : "no commission"} accent={AMBER} />
                <KpiTile label="Conversion" value={acc.kpi.conversion + "%"} sub="won / closed deals" accent={PLUM} />
                <KpiTile label="Contacts" value={acc.contactCount} sub={`${acc.contacts.length} on file here`} accent={SLATE} />
              </div>
              {acc.rnCommitment ? (
                <div style={{ marginTop: 12, background: SURFACE, border: `1px solid ${RULE}`, borderRadius: 9, padding: "12px 13px" }}>
                  <div style={{ display: "flex", alignItems: "baseline", gap: 8, marginBottom: 8 }}>
                    <Mono size={9.5} color={FAINT} style={{ letterSpacing: "0.16em", fontWeight: 700 }}>ROOM-NIGHT COMMITMENT</Mono>
                    <div style={{ flex: 1 }} />
                    <Mono size={11} color={INK} style={{ fontWeight: 700 }}>{num(acc.kpi.rnYTD)} / {num(acc.rnCommitment)}</Mono>
                  </div>
                  <div style={{ position: "relative", height: 9, borderRadius: 999, background: PAPER, border: `1px solid ${RULE}`, overflow: "hidden" }}>
                    <div style={{ position: "absolute", inset: 0, width: `${Math.min(100, (acc.kpi.rnYTD / acc.rnCommitment) * 100)}%`, background: `linear-gradient(90deg,${FUCHSIA_SOFT},${FUCHSIA})` }} />
                    {[80, 100].map(m => <div key={m} style={{ position: "absolute", top: -2, bottom: -2, left: `${m}%`, width: 1.5, background: m === 100 ? RED : AMBER }} />)}
                  </div>
                  <Mono size={9.5} color={FAINT} style={{ display: "block", marginTop: 7 }}>Allotment watch alerts the account manager at 80% and again at 100% of the contracted volume.</Mono>
                </div>
              ) : null}
            </>
          )}

          {tab === "contacts" && (
            <div style={{ display: "grid", gap: 9 }}>
              {acc.contacts.map(cid => {
                const c = CT_BY_ID[cid];
                return (
                  <div key={cid} style={{ background: SURFACE, border: `1px solid ${RULE}`, borderRadius: 9, padding: "12px 13px", display: "flex", gap: 11, alignItems: "flex-start" }}>
                    <span style={{ width: 30, height: 30, borderRadius: "50%", background: PAPER, border: `1px solid ${RULE}`, display: "grid", placeItems: "center", flexShrink: 0 }}>
                      <Mono size={11} color={DIM} style={{ fontWeight: 700 }}>{c.name.split(" ").map(w => w[0]).join("")}</Mono>
                    </span>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ display: "flex", alignItems: "center", gap: 7, flexWrap: "wrap" }}>
                        <span style={{ fontSize: 13, fontWeight: 600 }}>{c.name}</span>
                        {c.primary && <Pill tone="soon">Primary</Pill>}
                        <Mono size={9.5} color={DIM}>{c.role}</Mono>
                      </div>
                      <div style={{ display: "flex", gap: 12, marginTop: 5, flexWrap: "wrap" }}>
                        <span style={{ display: "inline-flex", alignItems: "center", gap: 5 }}><Icon name="mail" size={11} color={FAINT} /><Mono size={10} color={DIM}>{c.email}</Mono></span>
                        <span style={{ display: "inline-flex", alignItems: "center", gap: 5 }}><Icon name="phone" size={11} color={FAINT} /><Mono size={10} color={DIM}>{c.phone}</Mono></span>
                        <span style={{ display: "inline-flex", alignItems: "center", gap: 5 }}><Icon name="lang" size={11} color={FAINT} /><Mono size={10} color={DIM}>{c.langs}</Mono></span>
                      </div>
                    </div>
                    <div style={{ textAlign: "right" }}>
                      <Mono size={9} color={FAINT} style={{ letterSpacing: "0.14em", fontWeight: 700 }}>OPEN</Mono>
                      <div><Mono size={12} color={INK} style={{ fontWeight: 700 }}>{eur(c.openPipeline)}</Mono></div>
                      <Mono size={9} color={FAINT}>{c.emails} emails</Mono>
                    </div>
                  </div>
                );
              })}
            </div>
          )}

          {tab === "terms" && (
            <div style={{ background: SURFACE, border: `1px solid ${RULE}`, borderRadius: 9, padding: "14px 15px" }}>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "13px 18px" }}>
                <Field label="Commission" mono value={acc.commission != null ? acc.commission + "%" : `${rate}% · inherited`} tone={acc.commission == null ? FUCHSIA_DARK : INK} hint={acc.commission == null ? `From ${ACC_BY_ID[acc.parent].name}` : null} />
                <Field label="Settlement" value={acc.settlement} />
                <Field label="Credit limit" mono value={acc.credit != null ? eurFull(acc.credit) : "inherited"} />
                <Field label="Payment days" mono value={acc.payDays != null ? acc.payDays + " days" : "inherited"} />
                <Field label="Cancellation policy" wide value={acc.cancellation} />
                <Field label="Contract" mono value={`${longDate(acc.contract.from)} → ${longDate(acc.contract.to)}`} hint={`Renewal task raised ${acc.contract.notice} days before the end date`} />
                <Field label="Promo codes" wide>
                  <span style={{ display: "flex", gap: 6, flexWrap: "wrap" }}>
                    {acc.promo.map(p => <span key={p} style={{ background: FUCHSIA_PALE + "60", border: `1px solid ${FUCHSIA_PALE}`, borderRadius: 5, padding: "2px 7px", fontFamily: MONO, fontSize: 10.5, fontWeight: 700, color: FUCHSIA_DARK }}>{p}</span>)}
                  </span>
                </Field>
              </div>
            </div>
          )}

          {tab === "deals" && (
            <div style={{ display: "grid", gap: 8 }}>
              {deals.map(d => {
                const st = PIPE_BY_ID[d.pid].stages.find(s => s.id === d.stage);
                return (
                  <div key={d.id} style={{ background: SURFACE, border: `1px solid ${RULE}`, borderRadius: 8, padding: "10px 12px", display: "flex", alignItems: "center", gap: 10 }}>
                    <Dot color={st.color} size={7} />
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontSize: 12.5, fontWeight: 600 }}>{d.title}</div>
                      <Mono size={9.5} color={FAINT}>{PIPE_BY_ID[d.pid].label} · {st.name} · close {shortDate(d.close)}</Mono>
                    </div>
                    <Mono size={12} color={INK} style={{ fontWeight: 700 }}>{eur(d.value)}</Mono>
                    <Avatar who={d.owner} size={19} />
                  </div>
                );
              })}
              {!deals.length && <Mono size={11} color={FAINT}>No deals on this account.</Mono>}
            </div>
          )}

          {tab === "activity" && (
            <div style={{ background: SURFACE, border: `1px solid ${RULE}`, borderRadius: 9, padding: "14px 15px" }}>
              {[["Call", `Quarterly review with ${CT_BY_ID[acc.contacts[0]].name}`, "3 days ago", acc.manager, PLUM],
                ["Email", "Rate grid sent for review", "6 days ago", acc.manager, FUCHSIA],
                ["Site visit", "Property inspection · 2 hotels", "3 weeks ago", "yf", VIOLET],
                ["Note", "Prefers settlement on the 15th, not month end", "5 weeks ago", "ml", SLATE]].map(([t, title, when, who, tone], i) => (
                <TimelineItem key={i} tone={tone} icon={t === "Call" ? "phone" : t === "Email" ? "mail" : t === "Site visit" ? "building" : "pin"}
                  title={title} meta={`${t} · ${when} · ${USER_BY_ID[who].name}`} />
              ))}
            </div>
          )}

          {tab === "docs" && (
            <div style={{ display: "grid", gap: 8 }}>
              {[[`${acc.name.toLowerCase().replace(/[^a-z]/g, "-")}-framework-agreement-2026.pdf`, "Contract", "1.1 MB"],
                ["commission-schedule-signed.pdf", "Terms", "310 KB"],
                ["proposal-PR-2026-0184.pdf", "Proposal", "2.4 MB"]].map(([n, k, s]) => (
                <div key={n} style={{ background: SURFACE, border: `1px solid ${RULE}`, borderRadius: 8, padding: "10px 12px", display: "flex", alignItems: "center", gap: 10 }}>
                  <Icon name="file" size={14} color={FUCHSIA} />
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 12, fontWeight: 600, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{n}</div>
                    <Mono size={9.5} color={FAINT}>{k} · {s} · private storage · signed link</Mono>
                  </div>
                  <Icon name="download" size={13} color={DIM} />
                </div>
              ))}
            </div>
          )}

          {tab === "prod" && (
            <>
              <div style={{ display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 9, marginBottom: 12 }}>
                <KpiTile label="Reservations" value={num(eff.res)} sub="attributed" />
                <KpiTile label="Room nights" value={num(eff.rn)} sub="last 12 months" accent={VIOLET} />
                <KpiTile label="Revenue" value={eur(eff.revenue)} sub="attributed" accent={GREEN} />
                <KpiTile label="ADR" value={eurFull(acc.prod.adr)} sub="average daily rate" accent={AMBER} />
                <KpiTile label="Cancel rate" value={pct(acc.prod.cancelRate)} sub="of attributed bookings" accent={RED} />
                <KpiTile label="Lead time" value={acc.prod.leadTime + "d"} sub="average booking window" accent={SLATE} />
                <KpiTile label="Commission cost" value={eur(eff.commissionCost)} sub={`${rate}% effective`} accent={PLUM} wide />
              </div>
              <div style={{ background: SURFACE, border: `1px solid ${RULE}`, borderRadius: 9, overflow: "hidden" }}>
                <div style={{ display: "flex", alignItems: "center", gap: 9, padding: "9px 12px", borderBottom: `1px solid ${RULE}`, background: PAPER }}>
                  <Mono size={9.5} color={DIM} style={{ letterSpacing: "0.16em", fontWeight: 700 }}>ATTRIBUTED RESERVATIONS</Mono>
                  <div style={{ flex: 1 }} />
                  <Mono size={9.5} color={FAINT}>WHY IT MATCHED →</Mono>
                </div>
                <table style={{ width: "100%", borderCollapse: "collapse", fontFamily: SANS }}>
                  <thead><tr>{["Locator", "Hotel", "Check-in", "RN", "ADR", "Revenue", "Match"].map(h => (
                    <th key={h} style={{ textAlign: "left", padding: "7px 10px", borderBottom: `1px solid ${RULE_SOFT}` }}>
                      <Mono size={9} color={FAINT} style={{ letterSpacing: "0.12em", fontWeight: 700 }}>{h.toUpperCase()}</Mono></th>))}
                  </tr></thead>
                  <tbody>
                    {bookings.slice(0, 10).map((b, i) => (
                      <tr key={i}>
                        <td style={{ padding: "8px 10px", borderBottom: `1px solid ${RULE_SOFT}`, fontFamily: MONO, fontSize: 10.5 }}>{b.loc}</td>
                        <td style={{ padding: "8px 10px", borderBottom: `1px solid ${RULE_SOFT}`, fontSize: 11.5 }}>
                          {b.hotel}{b.child && <Mono size={9} color={FUCHSIA} style={{ display: "block" }}>via {b.child}</Mono>}
                        </td>
                        <td style={{ padding: "8px 10px", borderBottom: `1px solid ${RULE_SOFT}`, fontFamily: MONO, fontSize: 10.5, color: DIM }}>{shortDate(b.checkin)}</td>
                        <td style={{ padding: "8px 10px", borderBottom: `1px solid ${RULE_SOFT}`, fontFamily: MONO, fontSize: 11 }}>{b.rn}</td>
                        <td style={{ padding: "8px 10px", borderBottom: `1px solid ${RULE_SOFT}`, fontFamily: MONO, fontSize: 11 }}>{eurFull(b.adr)}</td>
                        <td style={{ padding: "8px 10px", borderBottom: `1px solid ${RULE_SOFT}`, fontFamily: MONO, fontSize: 11, fontWeight: 700 }}>{eurFull(b.revenue)}</td>
                        <td style={{ padding: "8px 10px", borderBottom: `1px solid ${RULE_SOFT}` }}>
                          <span style={{ display: "inline-flex", alignItems: "center", gap: 5 }}>
                            <span style={{ background: b.reason.color + "18", border: `1px solid ${b.reason.color}55`, color: b.reason.color, borderRadius: 4, padding: "1px 5px", fontFamily: MONO, fontSize: 8.5, fontWeight: 700 }}>{b.reason.k}</span>
                            <Mono size={9.5} color={DIM}>{b.reason.label}</Mono>
                          </span>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            </>
          )}

          {tab === "comm" && (
            <>
              <div style={{ display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 9, marginBottom: 12 }}>
                {commTotals.map(([s, v], i) => (
                  <KpiTile key={s} label={s} value={eur(v)} sub={s === "Accrued" ? "awaiting invoice" : s === "Invoiced" ? "sent to agency" : s === "Settled" ? "paid" : "reversed"}
                    accent={[FUCHSIA, VIOLET, GREEN, RED][i]} />
                ))}
              </div>
              {acc.commission == null && (
                <div style={{ display: "flex", alignItems: "center", gap: 9, background: FUCHSIA_PALE + "40", border: `1px solid ${FUCHSIA_PALE}`, borderRadius: 8, padding: "9px 11px", marginBottom: 12 }}>
                  <Icon name="layers" size={12} color={FUCHSIA_DARK} />
                  <Mono size={10} color={FUCHSIA_DARK}>No own rate, {rate}% inherited from {ACC_BY_ID[acc.parent].name}, the nearest ancestor with a rate.</Mono>
                </div>
              )}
              <div style={{ background: SURFACE, border: `1px solid ${RULE}`, borderRadius: 9, overflow: "hidden" }}>
                <table style={{ width: "100%", borderCollapse: "collapse", fontFamily: SANS }}>
                  <thead><tr>{["Booking", "Base", "Rate", "Amount", "State", "Accrued"].map(h => (
                    <th key={h} style={{ textAlign: "left", padding: "8px 10px", background: PAPER, borderBottom: `1px solid ${RULE}` }}>
                      <Mono size={9} color={DIM} style={{ letterSpacing: "0.12em", fontWeight: 700 }}>{h.toUpperCase()}</Mono></th>))}
                  </tr></thead>
                  <tbody>
                    {comms.map((c, i) => (
                      <tr key={i}>
                        <td style={{ padding: "8px 10px", borderBottom: `1px solid ${RULE_SOFT}`, fontFamily: MONO, fontSize: 10.5 }}>{c.loc}</td>
                        <td style={{ padding: "8px 10px", borderBottom: `1px solid ${RULE_SOFT}`, fontFamily: MONO, fontSize: 11 }}>{eurFull(c.base)}</td>
                        <td style={{ padding: "8px 10px", borderBottom: `1px solid ${RULE_SOFT}`, fontFamily: MONO, fontSize: 11 }}>{c.rate}%{c.inherited && <Mono size={8.5} color={FUCHSIA}> inh.</Mono>}</td>
                        <td style={{ padding: "8px 10px", borderBottom: `1px solid ${RULE_SOFT}`, fontFamily: MONO, fontSize: 11, fontWeight: 700 }}>{eurFull(c.amount)}</td>
                        <td style={{ padding: "8px 10px", borderBottom: `1px solid ${RULE_SOFT}` }}>
                          <span style={{ display: "inline-flex", alignItems: "center", gap: 5 }}>
                            <Dot size={5} color={c.state === "Settled" ? GREEN : c.state === "Invoiced" ? VIOLET : c.state === "Cancelled" ? RED : FUCHSIA} />
                            <Mono size={10} color={DIM}>{c.state}</Mono>
                          </span>
                        </td>
                        <td style={{ padding: "8px 10px", borderBottom: `1px solid ${RULE_SOFT}`, fontFamily: MONO, fontSize: 10.5, color: DIM }}>{shortDate(c.when)}</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
              <div style={{ display: "flex", alignItems: "center", gap: 9, marginTop: 11 }}>
                <ChromeButton icon="download">Export ledger</ChromeButton>
                <ChromeButton icon="plus">Manual entry</ChromeButton>
                <Mono size={10} color={FAINT}>One entry per reservation at check-out. Exports are logged with user and timestamp.</Mono>
              </div>
            </>
          )}
        </div>
      </div>
    </div>
  );
}

// ─── B2B tab on an ordinary contact record ───
function B2BContactPanel() {
  const [cid, setCid] = useState("c-cr");
  const c = CT_BY_ID[cid];
  const acc = ACC_BY_ID[c.acc];
  const GUEST_TABS = ["Bookings", "Memory", "Loyalty", "Surveys"];
  return (
    <div style={{ background: SURFACE, border: `1px solid ${RULE}`, borderRadius: 11, overflow: "hidden" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 9, padding: "11px 14px", borderBottom: `1px solid ${RULE}` }}>
        <span style={{ width: 32, height: 32, borderRadius: "50%", background: PAPER, border: `1px solid ${RULE}`, display: "grid", placeItems: "center" }}>
          <Mono size={12} color={DIM} style={{ fontWeight: 700 }}>{c.name.split(" ").map(w => w[0]).join("")}</Mono>
        </span>
        <div style={{ flex: 1 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
            <span style={{ fontSize: 14, fontWeight: 600 }}>{c.name}</span>
            <span style={{ background: FUCHSIA_PALE + "70", border: `1px solid ${FUCHSIA_PALE}`, color: FUCHSIA_DARK, borderRadius: 4, padding: "1px 6px", fontFamily: MONO, fontSize: 8.5, fontWeight: 700, letterSpacing: "0.08em" }}>TYPE · B2B</span>
            {c.primary && <Pill tone="soon">Primary contact</Pill>}
          </div>
          <Mono size={10} color={FAINT}>{c.email} · {c.phone}</Mono>
        </div>
        <Select value={cid} width={190} onChange={setCid} options={CONTACTS.map(x => ({ v: x.id, l: `${x.name} · ${ACC_BY_ID[x.acc].name}` }))} />
      </div>
      <div style={{ display: "flex", gap: 16, padding: "10px 14px 0", borderBottom: `1px solid ${RULE}`, flexWrap: "wrap" }}>
        <span style={{ display: "inline-flex", alignItems: "center", gap: 6, paddingBottom: 8, borderBottom: `2px solid ${FUCHSIA}` }}>
          <Icon name="briefcase" size={12} color={FUCHSIA} /><span style={{ fontSize: 12, fontWeight: 600 }}>B2B</span>
        </span>
        {GUEST_TABS.map(t => <span key={t} style={{ paddingBottom: 8, fontSize: 12, color: DIM }}>{t}</span>)}
      </div>
      <div style={{ padding: "14px", display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 9 }}>
        <KpiTile label="Account" value={acc.initials} sub={acc.name} />
        <KpiTile label="Open pipeline" value={eur(c.openPipeline)} sub="deals where this person is the contact" accent={VIOLET} />
        <KpiTile label="Emails sent" value={c.emails} sub="one-to-one, tracked" accent={GREEN} />
        <KpiTile label="Last activity" value={c.lastAct} sub="logged on the timeline" accent={AMBER} />
      </div>
      <div style={{ padding: "0 14px 14px" }}>
        <div style={{ display: "flex", gap: 7, flexWrap: "wrap", marginBottom: 11 }}>
          {["Deals", "Emails", "Activities", "Documents"].map((t, i) => (
            <span key={t} style={{ background: i === 0 ? INK : PAPER, color: i === 0 ? "#fff" : DIM, border: `1px solid ${i === 0 ? INK : RULE}`, borderRadius: 999, padding: "4px 11px", fontSize: 11.5, fontWeight: 600 }}>{t}</span>
          ))}
        </div>
        <div style={{ display: "grid", gap: 7 }}>
          {DEALS.filter(d => d.contact === cid).map(d => (
            <div key={d.id} style={{ display: "flex", alignItems: "center", gap: 9, border: `1px solid ${RULE}`, borderRadius: 8, padding: "9px 11px" }}>
              <Dot color={PIPE_BY_ID[d.pid].stages.find(s => s.id === d.stage).color} size={6} />
              <span style={{ fontSize: 12, fontWeight: 600, flex: 1 }}>{d.title}</span>
              <Mono size={11} color={INK} style={{ fontWeight: 700 }}>{eur(d.value)}</Mono>
            </div>
          ))}
        </div>
        <div style={{ display: "flex", alignItems: "flex-start", gap: 8, marginTop: 12, paddingTop: 11, borderTop: `1px dashed ${RULE}` }}>
          <Icon name="shield" size={12} color={FAINT} style={{ marginTop: 1 }} />
          <Mono size={10} color={FAINT} style={{ lineHeight: 1.6 }}>
            Same record, same consent state, same verified senders as the guest side. Importers never downgrade a B2B contact back to guest.
          </Mono>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { AccountsFrame, AccountDrawer, B2BContactPanel, AppFrame, KpiTile, ProfileChip });
