// Remaining pages: Ideas, Components, Tickets, Help, Admin. Plus shared wizards/drawers.

// ── IDEAS LIST ───────────────────────────────────────────────────────
const IdeasPage = ({ goto, openCompose }) => {
  const [filter, setFilter] = React.useState('all');
  const items = APM_IDEAS.filter(i => filter === 'all' ? true : i.status === filter);
  return (
    <Page>
      <PageHeader kicker="Ideas" title="The pre-project zone"
        subtitle="Anyone can log an idea. Stage approvers, project owners, and helpdesk leads route the good ones into projects, initiatives, follow-ons, or merges."
        action={<Button variant="accent" icon={<Icon name="plus" size={14} />} onClick={openCompose}>Log idea</Button>}
      />
      <div style={{ display: 'flex', gap: 4, marginBottom: 16 }}>
        {[
          { id: 'all', label: 'All', n: APM_IDEAS.length },
          { id: 'new', label: 'New', n: APM_IDEAS.filter(i => i.status === 'new').length },
          { id: 'promoted', label: 'Promoted', n: APM_IDEAS.filter(i => i.status === 'promoted').length },
          { id: 'merged', label: 'Merged', n: APM_IDEAS.filter(i => i.status === 'merged').length },
        ].map(f => {
          const active = filter === f.id;
          return (
            <button key={f.id} onClick={() => setFilter(f.id)} style={{
              padding: '6px 12px', borderRadius: 999,
              background: active ? 'var(--apm-ink)' : 'transparent',
              color: active ? 'var(--apm-bg-2)' : 'var(--apm-ink-2)',
              border: '1px solid ' + (active ? 'var(--apm-ink)' : 'var(--apm-line-2)'),
              fontFamily: 'var(--apm-font-body)', fontSize: 12.5, fontWeight: 500, cursor: 'pointer',
            }}>{f.label} <span style={{ opacity: 0.6, marginLeft: 4 }}>{f.n}</span></button>
          );
        })}
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 12 }}>
        {items.map(idea => (
          <Card key={idea.id} hoverable onClick={() => goto('ideas', { id: idea.id })}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 12 }}>
              <div style={{ flex: 1 }}>
                <div style={{ fontFamily: 'var(--apm-font-display)', fontSize: 17, lineHeight: 1.25, letterSpacing: '-0.005em' }}>{idea.title}</div>
                <div style={{ fontSize: 12.5, color: 'var(--apm-muted)', marginTop: 6, lineHeight: 1.5 }}>{idea.description}</div>
                <div style={{ display: 'flex', gap: 8, marginTop: 12, alignItems: 'center', fontSize: 11.5, color: 'var(--apm-muted)' }}>
                  <Avatar person={idea.submitter} size={18} />
                  <span>{PERSON_BY_ID[idea.submitter].name}</span>
                  <span>· {idea.submitted}</span>
                  {idea.tags?.map(t => <span key={t} style={{ padding: '1px 6px', background: 'var(--apm-bg-sunken)', borderRadius: 4, fontSize: 10.5 }}>{t}</span>)}
                </div>
              </div>
              <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 8 }}>
                <Badge tone={idea.status === 'promoted' ? 'ok' : idea.status === 'merged' ? 'info' : 'neutral'} size="sm">{idea.status}</Badge>
                <div style={{
                  display: 'flex', flexDirection: 'column', alignItems: 'center',
                  padding: '4px 10px', border: '1px solid var(--apm-line-2)', borderRadius: 6,
                }}>
                  <Icon name="bolt" size={12} />
                  <div style={{ fontSize: 13, fontWeight: 600 }}>{idea.upvotes}</div>
                </div>
              </div>
            </div>
          </Card>
        ))}
      </div>
    </Page>
  );
};

// ── IDEA DETAIL ──────────────────────────────────────────────────────
const IdeaDetail = ({ id, goto }) => {
  const idea = APM_IDEAS.find(i => i.id === id) || APM_IDEAS[0];
  const [pickerOpen, setPickerOpen] = React.useState(false);

  return (
    <Page max={920}>
      <PageHeader kicker={`Idea · logged ${idea.submitted}`} title={idea.title} subtitle={idea.description}
        meta={<>
          <Badge tone={idea.status === 'promoted' ? 'ok' : idea.status === 'merged' ? 'info' : 'neutral'} size="sm">{idea.status}</Badge>
          <span style={{ fontSize: 12, color: 'var(--apm-muted)' }}>· {idea.upvotes} upvotes</span>
          <Avatar person={idea.submitter} size={20} />
          <span style={{ fontSize: 12, color: 'var(--apm-muted)' }}>{PERSON_BY_ID[idea.submitter].name}</span>
        </>}
        action={<Button variant="primary" icon={<Icon name="branch" size={14} />} onClick={() => setPickerOpen(true)}>Route this idea</Button>}
      />

      <Card style={{ marginBottom: 'var(--apm-section-gap)' }}>
        <div style={{ fontSize: 11, color: 'var(--apm-muted)', textTransform: 'uppercase', letterSpacing: '0.12em', marginBottom: 8 }}>Discussion · 4 replies</div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--apm-inner-gap)' }}>
          {[
            { who: 'p_priya', when: '2 days ago', text: 'I\'d be hesitant to overlap this with the Q-shape preview work — different patient outcomes. Worth its own project?' },
            { who: 'p_jenna', when: '1 day ago', text: 'If we ship summaries to patients we need consent scope for it. Let\'s scope that into the wizard before promoting.' },
            { who: 'p_dr_ito', when: '4 hours ago', text: '+1 to keeping it separate. I\'d like to see this on the FY27 deck.' },
          ].map((c, i) => (
            <div key={i} style={{ display: 'flex', gap: 10 }}>
              <Avatar person={c.who} size={28} />
              <div style={{ flex: 1, fontSize: 13, lineHeight: 1.5 }}>
                <span style={{ fontWeight: 600 }}>{PERSON_BY_ID[c.who].name}</span>
                <span style={{ color: 'var(--apm-muted)', fontSize: 11.5, marginLeft: 6 }}>{c.when}</span>
                <div style={{ marginTop: 2 }}>{c.text}</div>
              </div>
            </div>
          ))}
        </div>
        <div style={{ marginTop: 16 }}>
          <Textarea placeholder="Reply…" rows={2} />
        </div>
      </Card>

      {/* Routing picker */}
      <Modal open={pickerOpen} onClose={() => setPickerOpen(false)} width={680}>
        <div style={{ padding: 24, borderBottom: '1px solid var(--apm-line)' }}>
          <div style={{ fontSize: 11, textTransform: 'uppercase', letterSpacing: '0.16em', color: 'var(--apm-muted)' }}>Route idea</div>
          <div style={{ fontFamily: 'var(--apm-font-display)', fontSize: 20, marginTop: 4, letterSpacing: '-0.01em' }}>Where does &ldquo;{idea.title}&rdquo; go?</div>
          <div style={{ fontSize: 13, color: 'var(--apm-muted)', marginTop: 6 }}>Pick one. The idea stays linked so we keep credit and trace.</div>
        </div>
        <div style={{ padding: 16, display: 'flex', flexDirection: 'column', gap: 'var(--apm-inner-gap)' }}>
          {[
            { icon: 'projects', title: 'Promote to project',     hint: 'Becomes a Phase-0 project with the wizard. Best for novel work.', accent: true },
            { icon: 'initiatives', title: 'Promote to initiative', hint: 'Strategic/big. Owner + sponsor required.' },
            { icon: 'flow',     title: 'Add as follow-on to a project', hint: 'Attach to an in-flight project as a deferred item.' },
            { icon: 'link',     title: 'Merge into existing idea',     hint: 'When a duplicate slipped through.' },
            { icon: 'archive',  title: 'Park / Reject',                hint: 'Archive with a reason. Submitter is notified.' },
          ].map((o, i) => (
            <button key={i} onClick={() => { setPickerOpen(false); if (i === 0) goto('__new_project__', { from: id }); }}
              style={{
                display: 'flex', alignItems: 'center', gap: 14,
                padding: 14, textAlign: 'left',
                background: 'transparent',
                border: '1px solid ' + (o.accent ? 'var(--apm-accent)' : 'var(--apm-line)'),
                borderRadius: 'var(--apm-radius)', cursor: 'pointer',
                fontFamily: 'var(--apm-font-body)',
              }}
              onMouseEnter={e => e.currentTarget.style.background = 'var(--apm-bg-sunken)'}
              onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
              <div style={{
                width: 36, height: 36, borderRadius: 8,
                background: o.accent ? 'var(--apm-accent)' : 'var(--apm-bg-sunken)',
                color: o.accent ? '#fff' : 'var(--apm-ink-2)',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
              }}><Icon name={o.icon} size={16} /></div>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 13.5, fontWeight: 600 }}>{o.title}</div>
                <div style={{ fontSize: 12, color: 'var(--apm-muted)', marginTop: 2 }}>{o.hint}</div>
              </div>
              <Icon name="arrow_right" size={14} style={{ color: 'var(--apm-muted)' }} />
            </button>
          ))}
        </div>
      </Modal>
    </Page>
  );
};

// ── COMPONENTS LIST + DETAIL ─────────────────────────────────────────
const ComponentsPage = ({ goto }) => (
  <Page>
    <PageHeader kicker="Components" title="The shared catalog"
      subtitle="Every reusable piece — services, SDKs, integrations. Owners gate breaking changes; dependents see the impact." />
    <Card pad={false}>
      <div style={{ display: 'grid', gridTemplateColumns: '1.4fr 0.7fr 0.7fr 0.7fr 0.6fr 1fr', padding: '10px 16px', fontSize: 11, color: 'var(--apm-muted)', textTransform: 'uppercase', letterSpacing: '0.1em', borderBottom: '1px solid var(--apm-line)' }}>
        <div>Component</div><div>Owner</div><div>Stability</div><div>Version</div><div>Deps</div><div>Sensitivity</div>
      </div>
      {APM_COMPONENTS.map((c,i,a) => (
        <div key={c.id} onClick={() => goto('components', { id: c.id })} style={{
          display: 'grid', gridTemplateColumns: '1.4fr 0.7fr 0.7fr 0.7fr 0.6fr 1fr',
          padding: 'var(--apm-row-pad) var(--apm-card-pad)', alignItems: 'center', cursor: 'pointer',
          borderBottom: i < a.length-1 ? '1px solid var(--apm-line)' : 'none',
        }}
          onMouseEnter={e => e.currentTarget.style.background = 'var(--apm-bg-sunken)'} onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
          <div>
            <div style={{ fontSize: 13.5, fontWeight: 600 }}>{c.name}</div>
            <div style={{ fontSize: 11.5, color: 'var(--apm-muted)' }}>{c.summary}</div>
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
            <Avatar person={c.owner} size={20} />
            <span style={{ fontSize: 12 }}>{PERSON_BY_ID[c.owner].name.split(' ')[0]}</span>
          </div>
          <Badge tone={c.stability === 'GA' ? 'ok' : c.stability === 'Beta' ? 'warn' : c.stability === 'RC' ? 'info' : 'neutral'} size="sm">{c.stability}</Badge>
          <div style={{ fontFamily: 'var(--apm-font-mono)', fontSize: 12, color: 'var(--apm-muted)' }}>{c.version}</div>
          <div style={{ fontSize: 13, color: 'var(--apm-muted)' }}>{c.dependents.length}</div>
          <div style={{ display: 'flex', gap: 4, flexWrap: 'wrap' }}>{c.sensitivity.map(s => <SensitivityTag key={s} id={s} />)}</div>
        </div>
      ))}
    </Card>
  </Page>
);

const ComponentDetail = ({ id, goto, openChange }) => {
  const c = COMP_BY_ID[id] || APM_COMPONENTS[0];
  const changes = APM_CHANGES.filter(ch => ch.component === c.id);
  return (
    <Page>
      <PageHeader kicker={`Component · ${c.version}`} title={c.name} subtitle={c.summary}
        meta={<>
          <Badge tone={c.stability === 'GA' ? 'ok' : c.stability === 'Beta' ? 'warn' : c.stability === 'RC' ? 'info' : 'neutral'} size="sm">{c.stability}</Badge>
          <Avatar person={c.owner} size={20} />
          <span style={{ fontSize: 12, color: 'var(--apm-muted)' }}>{PERSON_BY_ID[c.owner].name}</span>
          {c.sensitivity.map(s => <SensitivityTag key={s} id={s} />)}
        </>}
        action={<Button variant="primary" icon={<Icon name="branch" size={14} />} onClick={openChange}>Submit change</Button>}
      />
      <div style={{ display: 'grid', gridTemplateColumns: '1.4fr 1fr', gap: 24 }}>
        <div>
          <SectionHeading kicker="Change control" title="Open requests" level={3} />
          {changes.length === 0 ? <EmptyState title="No open changes" body="When someone proposes a breaking or compatible change, it appears here for owners to vote on." /> :
            <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--apm-inner-gap)' }}>
              {changes.map(ch => (
                <Card key={ch.id}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 12 }}>
                    <div style={{ flex: 1 }}>
                      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
                        <Badge tone={ch.breaking ? 'risk' : 'info'} size="sm">{ch.breaking ? 'Breaking' : 'Compatible'}</Badge>
                        <Badge tone={ch.status === 'approved' ? 'ok' : 'warn'} size="sm">{ch.status}</Badge>
                      </div>
                      <div style={{ fontSize: 14.5, fontWeight: 600 }}>{ch.title}</div>
                      <div style={{ fontSize: 12.5, color: 'var(--apm-muted)', marginTop: 6, lineHeight: 1.5 }}>{ch.description}</div>
                      <div style={{ marginTop: 12, padding: 10, background: 'var(--apm-bg-sunken)', borderRadius: 'var(--apm-radius)', fontSize: 12 }}>
                        <div style={{ color: 'var(--apm-muted)', marginBottom: 6 }}>Impact: {ch.impact.length} dependent projects</div>
                        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
                          {ch.impact.map(pid => (
                            <a key={pid} onClick={(e) => { e.stopPropagation(); goto('project', { id: pid }); }} style={{ padding: '2px 8px', background: 'var(--apm-card)', border: '1px solid var(--apm-line)', borderRadius: 4, fontSize: 11.5, cursor: 'pointer', textDecoration: 'none', color: 'var(--apm-ink)' }}>{PROJ_BY_ID[pid].name}</a>
                          ))}
                        </div>
                      </div>
                    </div>
                    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4 }}>
                      <button style={{ background: 'transparent', border: '1px solid var(--apm-line-2)', borderRadius: 6, width: 32, height: 32, cursor: 'pointer' }}><Icon name="bolt" size={14} /></button>
                      <div style={{ fontWeight: 600 }}>{ch.votes}</div>
                    </div>
                  </div>
                </Card>
              ))}
            </div>
          }
        </div>
        <div>
          <SectionHeading kicker="Used by" title="Dependent projects" level={3} />
          <Card pad={false}>
            {c.dependents.map((pid, i, a) => (
              <div key={pid} onClick={() => goto('project', { id: pid })} style={{
                padding: '10px 14px', cursor: 'pointer',
                borderBottom: i < a.length-1 ? '1px solid var(--apm-line)' : 'none',
              }}
                onMouseEnter={e => e.currentTarget.style.background = 'var(--apm-bg-sunken)'} onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
                <div style={{ fontSize: 13, fontWeight: 600 }}>{PROJ_BY_ID[pid].name}</div>
                <div style={{ fontSize: 11.5, color: 'var(--apm-muted)' }}>{PROJ_BY_ID[pid].phase}</div>
              </div>
            ))}
          </Card>
        </div>
      </div>
    </Page>
  );
};

// ── TICKETS ──────────────────────────────────────────────────────────
const TicketsPage = ({ goto, openId }) => {
  const [open, setOpen] = React.useState(openId || null);
  React.useEffect(() => { if (openId) setOpen(openId); }, [openId]);
  return (
    <Page>
      <PageHeader kicker="Tickets" title="Live operational queue"
        subtitle="Incidents, bugs, and requests routed against projects. Helpdesk owns triage; project owners take work."
        action={<Button variant="primary" icon={<Icon name="plus" size={14} />}>New ticket</Button>}
      />
      <Card pad={false}>
        <div style={{ display: 'grid', gridTemplateColumns: '60px 1fr 1fr 100px 100px 80px', padding: '10px 16px', fontSize: 11, color: 'var(--apm-muted)', textTransform: 'uppercase', letterSpacing: '0.1em', borderBottom: '1px solid var(--apm-line)' }}>
          <div>Pri</div><div>Title</div><div>Project</div><div>Status</div><div>Assignee</div><div>Age</div>
        </div>
        {APM_TICKETS.map((t,i,a) => (
          <div key={t.id} onClick={() => setOpen(t.id)} style={{
            display: 'grid', gridTemplateColumns: '60px 1fr 1fr 100px 100px 80px',
            padding: 'var(--apm-row-pad) var(--apm-card-pad)', alignItems: 'center', gap: 12, cursor: 'pointer',
            borderBottom: i < a.length-1 ? '1px solid var(--apm-line)' : 'none',
          }}
            onMouseEnter={e => e.currentTarget.style.background = 'var(--apm-bg-sunken)'} onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
            <Badge tone={t.priority === 'P1' ? 'risk' : t.priority === 'P2' ? 'warn' : 'neutral'} size="sm">{t.priority}</Badge>
            <div>
              <div style={{ fontSize: 13.5, fontWeight: 500 }}>{t.title}</div>
              <div style={{ fontSize: 11.5, color: 'var(--apm-muted)' }}>{t.id} · opened by {PERSON_BY_ID[t.from].name}</div>
            </div>
            <div style={{ fontSize: 12.5 }}>{PROJ_BY_ID[t.project].name}</div>
            <Badge tone={t.status === 'open' ? 'warn' : 'info'} size="sm" dot>{t.status}</Badge>
            {t.assignee ? <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}><Avatar person={t.assignee} size={20} /><span style={{ fontSize: 12 }}>{PERSON_BY_ID[t.assignee].name.split(' ')[0]}</span></div> : <span style={{ fontSize: 12, color: 'var(--apm-muted-2)' }}>—</span>}
            <div style={{ fontSize: 12, color: 'var(--apm-muted)' }}>{t.age}</div>
          </div>
        ))}
      </Card>

      {/* Ticket drawer */}
      <Drawer open={!!open} onClose={() => setOpen(null)} width={560}>
        {open && (() => {
          const t = APM_TICKETS.find(x => x.id === open) || APM_TICKETS[0];
          return (
            <>
              <div style={{ padding: 'var(--apm-row-pad) 24px', borderBottom: '1px solid var(--apm-line)' }}>
                <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                    <Badge tone={t.priority === 'P1' ? 'risk' : t.priority === 'P2' ? 'warn' : 'neutral'} size="sm">{t.priority}</Badge>
                    <span style={{ fontSize: 11, color: 'var(--apm-muted)', fontFamily: 'var(--apm-font-mono)' }}>{t.id}</span>
                  </div>
                  <button onClick={() => setOpen(null)} style={{ background: 'transparent', border: 'none', cursor: 'pointer', color: 'var(--apm-muted)' }}><Icon name="x" size={16} /></button>
                </div>
                <div style={{ fontFamily: 'var(--apm-font-display)', fontSize: 22, marginTop: 8, letterSpacing: '-0.01em', lineHeight: 1.25 }}>{t.title}</div>
                <div style={{ fontSize: 12.5, color: 'var(--apm-muted)', marginTop: 6 }}>opened by {PERSON_BY_ID[t.from].name} · {t.age} · in <a onClick={() => goto('project', { id: t.project })} style={{ color: 'var(--apm-accent-ink)', cursor: 'pointer' }}>{PROJ_BY_ID[t.project].name}</a></div>
              </div>
              <div style={{ padding: 24, flex: 1, overflowY: 'auto' }}>
                <SectionHeading kicker="Activity" title="Timeline" level={3} />
                <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--apm-inner-gap)' }}>
                  <div style={{ fontSize: 13, lineHeight: 1.5 }}><strong>{PERSON_BY_ID[t.from].name}</strong> opened — &ldquo;Several EU clinics getting 502 on bulk uploads. Started ~30min ago.&rdquo;</div>
                  <div style={{ fontSize: 13, lineHeight: 1.5 }}><strong>System</strong> escalated to P1 due to clinic count threshold.</div>
                  {t.assignee && <div style={{ fontSize: 13, lineHeight: 1.5 }}><strong>{PERSON_BY_ID[t.assignee].name}</strong> took ownership.</div>}
                </div>
                <Textarea placeholder="Reply…" rows={3} style={{ marginTop: 16 }} />
              </div>
              <div style={{ padding: 16, borderTop: '1px solid var(--apm-line)', display: 'flex', gap: 8 }}>
                <Button variant="primary" size="sm">Resolve</Button>
                <Button variant="outline" size="sm">Re-assign</Button>
                <Button variant="ghost" size="sm">Convert to idea</Button>
              </div>
            </>
          );
        })()}
      </Drawer>
    </Page>
  );
};

// ── HELP BOARD ───────────────────────────────────────────────────────
const HelpPage = ({ goto, openCompose }) => (
  <Page>
    <PageHeader kicker="Help board" title="Ask anything. Promote useful answers."
      subtitle="A low-stakes Q&A for the company. Helpdesk routes patterns into tickets or ideas."
      action={<Button variant="accent" icon={<Icon name="plus" size={14} />} onClick={openCompose}>Ask a question</Button>}
    />
    <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--apm-inner-gap)' }}>
      {APM_HELP.map(h => (
        <Card key={h.id} hoverable>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 16 }}>
            <div style={{ flex: 1 }}>
              <div style={{ fontFamily: 'var(--apm-font-display)', fontSize: 17 }}>{h.title}</div>
              <div style={{ fontSize: 12, color: 'var(--apm-muted)', marginTop: 6, display: 'flex', alignItems: 'center', gap: 8 }}>
                <Avatar person={h.from} size={18} />
                <span>{PERSON_BY_ID[h.from].name}</span>
                <span>· {h.age}</span>
                <span>· topic: {h.topic}</span>
              </div>
            </div>
            <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
              <Badge tone={h.status === 'open' ? 'warn' : 'ok'} dot size="sm">{h.status}</Badge>
              <span style={{ fontSize: 12, color: 'var(--apm-muted)' }}>{h.answers} {h.answers === 1 ? 'reply' : 'replies'}</span>
              {h.promoted && <Badge tone="info" size="sm">→ {h.promoted}</Badge>}
            </div>
          </div>
        </Card>
      ))}
    </div>
  </Page>
);

// ── ADMIN ────────────────────────────────────────────────────────────
const AdminPage = () => (
  <Page>
    <PageHeader kicker="Admin" title="Roles, access groups, and taxonomy" subtitle="Read-only for non-admins. Anyone can request a role; admins approve." />
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 24 }}>
      <div>
        <SectionHeading kicker="Roles" title="9 standard roles" level={3} />
        <Card pad={false}>
          {Object.entries(APM_ROLES).map(([k, r], i, a) => (
            <div key={k} style={{ padding: 'var(--apm-row-pad) 16px', borderBottom: i < a.length-1 ? '1px solid var(--apm-line)' : 'none' }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                <div style={{ fontSize: 13.5, fontWeight: 600 }}>{r.label}</div>
                <span style={{ fontSize: 11, color: 'var(--apm-muted)', fontFamily: 'var(--apm-font-mono)' }}>{k}</span>
              </div>
              <div style={{ fontSize: 12, color: 'var(--apm-muted)', marginTop: 4, lineHeight: 1.5 }}>{r.desc}</div>
            </div>
          ))}
        </Card>
      </div>
      <div>
        <SectionHeading kicker="Access groups" title="Workspaces & teams" level={3} />
        <Card>
          {[
            { n: 'Clinical Apps', members: 14, projects: 4 },
            { n: 'Platform',      members: 9,  projects: 3 },
            { n: 'Regulatory',    members: 6,  projects: 3 },
            { n: 'Executive',     members: 5,  projects: 0 },
          ].map((g, i, a) => (
            <div key={g.n} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: 'var(--apm-row-pad) 0', borderBottom: i<a.length-1 ? '1px solid var(--apm-line)' : 'none' }}>
              <div>
                <div style={{ fontSize: 13.5, fontWeight: 600 }}>{g.n}</div>
                <div style={{ fontSize: 11.5, color: 'var(--apm-muted)' }}>{g.members} members · {g.projects} projects</div>
              </div>
              <Button size="sm" variant="ghost">Manage</Button>
            </div>
          ))}
        </Card>

        <div style={{ marginTop: 'var(--apm-section-gap)' }}>
          <SectionHeading kicker="Taxonomy" title="Sensitivity tags" level={3} />
          <Card>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--apm-inner-gap)' }}>
              {APM_SENSITIVITY.map(s => (
                <div key={s.id} style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                  <SensitivityTag id={s.id} />
                  <div style={{ flex: 1, fontSize: 12.5, color: 'var(--apm-muted)' }}>{s.desc}</div>
                </div>
              ))}
            </div>
          </Card>
        </div>
      </div>
    </div>
  </Page>
);

// ── NEW PROJECT WIZARD (modal) ──────────────────────────────────────
const NewProjectWizard = ({ open, onClose, fromIdea }) => {
  const [step, setStep] = React.useState(0);
  const [interviewOpen, setInterviewOpen] = React.useState(false);
  const idea = fromIdea ? APM_IDEAS.find(i => i.id === fromIdea) : null;
  const [data, setData] = React.useState({
    name: idea?.title || '', initiative: '', summary: idea?.description || '',
    sensitivity: [], owner: '', target: '',
  });

  const applyFill = (filled) => {
    setData(prev => ({
      ...prev,
      name: filled.name || prev.name,
      summary: filled.summary || prev.summary,
      target: filled.target || prev.target,
      sensitivity: filled.sensitivity || prev.sensitivity,
      initiative: filled.initiative || prev.initiative,
    }));
    setInterviewOpen(false);
  };

  if (!open) return null;

  return (
    <Modal open onClose={onClose} width={interviewOpen ? 1060 : 720}>
      <div style={{ display: 'flex', height: interviewOpen ? 640 : 'auto' }}>
        {/* Main wizard */}
        <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minWidth: 0 }}>
          <div style={{ padding: 'var(--apm-row-pad) 28px', borderBottom: '1px solid var(--apm-line)' }}>
            <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 12 }}>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 11, textTransform: 'uppercase', letterSpacing: '0.16em', color: 'var(--apm-muted)' }}>
                  {idea ? 'Promote idea to project' : 'New project'} · Step {step + 1} of 3
                </div>
                <div style={{ fontFamily: 'var(--apm-font-display)', fontSize: 22, marginTop: 4, letterSpacing: '-0.01em' }}>
                  {step === 0 && 'What are we building?'}
                  {step === 1 && 'Who owns it, what does it touch?'}
                  {step === 2 && 'Confirm — this enters Phase 0 Intake'}
                </div>
              </div>
              {!interviewOpen && (
                <button onClick={() => setInterviewOpen(true)} style={{
                  display: 'flex', alignItems: 'center', gap: 6,
                  padding: '7px 12px', borderRadius: 8,
                  background: 'var(--apm-ink)', color: 'var(--apm-bg-2)',
                  border: 'none', cursor: 'pointer', fontSize: 12.5, fontWeight: 500,
                  fontFamily: 'var(--apm-font-body)', flexShrink: 0,
                }}>
                  <Icon name="sparkle" size={13} />
                  Ask Claude
                </button>
              )}
            </div>
            <div style={{ display: 'flex', gap: 4, marginTop: 14 }}>
              {[0,1,2].map(i => <div key={i} style={{ flex: 1, height: 3, background: i <= step ? 'var(--apm-accent)' : 'var(--apm-line)', borderRadius: 2 }} />)}
            </div>
          </div>

      <div style={{ padding: 28, minHeight: 320, overflowY: 'auto' }}>
        {step === 0 && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--apm-inner-gap)' }}>
            <div>
              <div style={{ fontSize: 12, color: 'var(--apm-muted)', marginBottom: 6, fontWeight: 500 }}>Project name</div>
              <Input value={data.name} onChange={v => setData({ ...data, name: v })} placeholder="e.g. Patient Follow-up Loop" />
            </div>
            <div>
              <div style={{ fontSize: 12, color: 'var(--apm-muted)', marginBottom: 6, fontWeight: 500 }}>One-line summary</div>
              <Textarea value={data.summary} onChange={v => setData({ ...data, summary: v })} placeholder="What problem does it solve, in one sentence?" rows={3} />
            </div>
            <div>
              <div style={{ fontSize: 12, color: 'var(--apm-muted)', marginBottom: 6, fontWeight: 500 }}>Roll up to which initiative?</div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--apm-inner-gap)' }}>
                {APM_INITIATIVES.map(ini => (
                  <button key={ini.id} onClick={() => setData({ ...data, initiative: ini.id })} style={{
                    display: 'flex', alignItems: 'center', gap: 12, padding: 10,
                    background: data.initiative === ini.id ? 'var(--apm-bg-sunken)' : 'transparent',
                    border: '1px solid ' + (data.initiative === ini.id ? 'var(--apm-ink)' : 'var(--apm-line)'),
                    borderRadius: 'var(--apm-radius)', cursor: 'pointer', textAlign: 'left',
                    fontFamily: 'var(--apm-font-body)',
                  }}>
                    <div style={{ width: 14, height: 14, borderRadius: '50%', border: '2px solid ' + (data.initiative === ini.id ? 'var(--apm-ink)' : 'var(--apm-line-2)'), display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                      {data.initiative === ini.id && <div style={{ width: 6, height: 6, borderRadius: '50%', background: 'var(--apm-ink)' }} />}
                    </div>
                    <div style={{ flex: 1, fontSize: 13 }}>{ini.name}</div>
                    <div style={{ fontSize: 11, color: 'var(--apm-muted)' }}>{ini.code}</div>
                  </button>
                ))}
              </div>
            </div>
          </div>
        )}
        {step === 1 && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--apm-inner-gap)' }}>
            <div>
              <div style={{ fontSize: 12, color: 'var(--apm-muted)', marginBottom: 8, fontWeight: 500 }}>Project owner</div>
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 6 }}>
                {APM_PEOPLE.filter(p => p.role === 'owner' || p.role === 'manager').map(p => (
                  <button key={p.id} onClick={() => setData({ ...data, owner: p.id })} style={{
                    display: 'flex', alignItems: 'center', gap: 8, padding: 10,
                    background: data.owner === p.id ? 'var(--apm-bg-sunken)' : 'transparent',
                    border: '1px solid ' + (data.owner === p.id ? 'var(--apm-ink)' : 'var(--apm-line)'),
                    borderRadius: 'var(--apm-radius)', cursor: 'pointer', textAlign: 'left',
                  }}>
                    <Avatar person={p} size={28} />
                    <div style={{ flex: 1, minWidth: 0, fontFamily: 'var(--apm-font-body)' }}>
                      <div style={{ fontSize: 12.5, fontWeight: 600, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{p.name}</div>
                      <div style={{ fontSize: 11, color: 'var(--apm-muted)' }}>{APM_ROLES[p.role].label}</div>
                    </div>
                  </button>
                ))}
              </div>
            </div>
            <div>
              <div style={{ fontSize: 12, color: 'var(--apm-muted)', marginBottom: 8, fontWeight: 500 }}>Sensitivity (gates downstream depend on this)</div>
              <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
                {APM_SENSITIVITY.map(s => {
                  const on = data.sensitivity.includes(s.id);
                  return (
                    <button key={s.id} onClick={() => setData({ ...data, sensitivity: on ? data.sensitivity.filter(x => x !== s.id) : [...data.sensitivity, s.id] })} style={{
                      display: 'flex', alignItems: 'center', gap: 6, padding: '6px 12px',
                      background: on ? 'var(--apm-ink)' : 'transparent',
                      color: on ? 'var(--apm-bg-2)' : 'var(--apm-ink)',
                      border: '1px solid ' + (on ? 'var(--apm-ink)' : 'var(--apm-line-2)'),
                      borderRadius: 999, cursor: 'pointer', fontSize: 12.5, fontWeight: 500,
                    }}>{s.label}</button>
                  );
                })}
              </div>
            </div>
            <div>
              <div style={{ fontSize: 12, color: 'var(--apm-muted)', marginBottom: 6, fontWeight: 500 }}>Target date</div>
              <Input value={data.target} onChange={v => setData({ ...data, target: v })} placeholder="YYYY-MM-DD" prefix={<Icon name="calendar" size={14} />} />
            </div>
          </div>
        )}
        {step === 2 && (
          <div>
            <Card>
              <div style={{ fontSize: 11, color: 'var(--apm-muted)', textTransform: 'uppercase', letterSpacing: '0.12em' }}>Summary</div>
              <div style={{ fontFamily: 'var(--apm-font-display)', fontSize: 20, marginTop: 4 }}>{data.name || 'Untitled project'}</div>
              <div style={{ fontSize: 13, color: 'var(--apm-muted)', marginTop: 6 }}>{data.summary || 'No summary yet.'}</div>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12, marginTop: 16 }}>
                <div><div style={{ fontSize: 11, color: 'var(--apm-muted)' }}>Initiative</div><div style={{ fontSize: 13, marginTop: 2 }}>{INI_BY_ID[data.initiative]?.name || '—'}</div></div>
                <div><div style={{ fontSize: 11, color: 'var(--apm-muted)' }}>Owner</div><div style={{ fontSize: 13, marginTop: 2 }}>{PERSON_BY_ID[data.owner]?.name || '—'}</div></div>
                <div><div style={{ fontSize: 11, color: 'var(--apm-muted)' }}>Target</div><div style={{ fontSize: 13, marginTop: 2 }}>{data.target || '—'}</div></div>
                <div><div style={{ fontSize: 11, color: 'var(--apm-muted)' }}>Sensitivity</div><div style={{ display: 'flex', gap: 4, marginTop: 4, flexWrap: 'wrap' }}>{data.sensitivity.length ? data.sensitivity.map(s => <SensitivityTag key={s} id={s} />) : <span style={{ fontSize: 12, color: 'var(--apm-muted-2)' }}>none</span>}</div></div>
              </div>
              <div style={{ marginTop: 16, padding: 12, background: 'var(--apm-bg-sunken)', borderRadius: 'var(--apm-radius)', fontSize: 12.5, color: 'var(--apm-muted-2)' }}>
                On submit, this project enters <strong style={{ color: 'var(--apm-ink-2)' }}>Phase 0 — Intake</strong>. Stage approvers will be notified based on sensitivity.
              </div>
            </Card>
          </div>
        )}
      </div>

      <div style={{ padding: 16, borderTop: '1px solid var(--apm-line)', display: 'flex', justifyContent: 'space-between' }}>
            <Button variant="ghost" onClick={onClose}>Cancel</Button>
            <div style={{ display: 'flex', gap: 8 }}>
              {step > 0 && <Button variant="outline" icon={<Icon name="arrow_left" size={14} />} onClick={() => setStep(step - 1)}>Back</Button>}
              {step < 2 && <Button variant="primary" onClick={() => setStep(step + 1)}>Continue <Icon name="arrow_right" size={14} /></Button>}
              {step === 2 && <Button variant="accent" icon={<Icon name="check" size={14} />} onClick={onClose}>Submit &amp; enter Intake</Button>}
            </div>
          </div>
        </div>{/* end main wizard col */}

        {/* Claude interview panel */}
        {interviewOpen && (
          <div style={{
            width: 340, borderLeft: '1px solid var(--apm-line)',
            display: 'flex', flexDirection: 'column', flexShrink: 0,
            background: 'var(--apm-bg-2)',
          }}>
            <ClaudeInterview
              context="project"
              onFill={applyFill}
              onClose={() => setInterviewOpen(false)}
            />
          </div>
        )}
      </div>{/* end flex row */}
    </Modal>
  );
};

// ── IDEA COMPOSE ─────────────────────────────────────────────────────
const IdeaCompose = ({ open, onClose }) => {
  const [t, setT] = React.useState(''); 
  const [d, setD] = React.useState('');
  const [interviewOpen, setInterviewOpen] = React.useState(false);

  const applyFill = (filled) => {
    if (filled.title) setT(filled.title);
    if (filled.description) setD(filled.description);
    setInterviewOpen(false);
  };

  if (!open) return null;
  return (
    <Modal open onClose={onClose} width={interviewOpen ? 860 : 560}>
      <div style={{ display: 'flex', height: interviewOpen ? 520 : 'auto' }}>
        {/* Main form */}
        <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minWidth: 0 }}>
          <div style={{ padding: 'var(--apm-row-pad) 24px', borderBottom: '1px solid var(--apm-line)' }}>
            <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 12 }}>
              <div>
                <div style={{ fontSize: 11, textTransform: 'uppercase', letterSpacing: '0.16em', color: 'var(--apm-muted)' }}>Log an idea</div>
                <div style={{ fontFamily: 'var(--apm-font-display)', fontSize: 22, marginTop: 4 }}>What if we…</div>
              </div>
              {!interviewOpen && (
                <button onClick={() => setInterviewOpen(true)} style={{
                  display: 'flex', alignItems: 'center', gap: 6,
                  padding: '7px 12px', borderRadius: 8,
                  background: 'var(--apm-ink)', color: 'var(--apm-bg-2)',
                  border: 'none', cursor: 'pointer', fontSize: 12.5, fontWeight: 500,
                  fontFamily: 'var(--apm-font-body)', flexShrink: 0,
                }}>
                  <Icon name="sparkle" size={13} />
                  Ask Claude
                </button>
              )}
            </div>
          </div>
          <div style={{ padding: 24, display: 'flex', flexDirection: 'column', gap: 'var(--apm-inner-gap)', overflowY: 'auto', flex: 1 }}>
            <Input value={t} onChange={setT} placeholder="A short, clear title" />
            <Textarea value={d} onChange={setD} placeholder="Why does it matter? Who benefits? What would success look like?" rows={5} />
            <div style={{ fontSize: 11.5, color: 'var(--apm-muted-2)' }}>
              Ideas stay in the backlog until a project owner, stage approver, or helpdesk lead routes them.
            </div>
          </div>
          <div style={{ padding: 16, borderTop: '1px solid var(--apm-line)', display: 'flex', justifyContent: 'flex-end', gap: 8 }}>
            <Button variant="ghost" onClick={onClose}>Cancel</Button>
            <Button variant="accent" icon={<Icon name="bolt" size={14} />} onClick={onClose}>Submit idea</Button>
          </div>
        </div>

        {/* Claude panel */}
        {interviewOpen && (
          <div style={{
            width: 300, borderLeft: '1px solid var(--apm-line)',
            display: 'flex', flexDirection: 'column', flexShrink: 0,
            background: 'var(--apm-bg-2)',
          }}>
            <ClaudeInterview context="idea" onFill={applyFill} onClose={() => setInterviewOpen(false)} />
          </div>
        )}
      </div>
    </Modal>
  );
};

// ── CLAUDE INTERVIEW PANEL ──────────────────────────────────────────
// Reusable within any wizard modal. Asks a series of targeted questions
// via the claude.complete API, then returns structured data to fill the form.
const ClaudeInterview = ({ context, onFill, onClose }) => {
  const systemPrompt = context === 'project'
    ? `You are helping a healthcare device company employee create a new project record in their portfolio management system. Ask them short, focused questions one at a time to gather: project name, one-sentence summary, which strategic initiative it supports (options: HearWell Cloud Migration, PEARL — AI Fit Coach, Patient Data Platform, Workforce Modernization), target date, and any regulatory sensitivities (PHI, PII, FDA/MDR, Source data, Fin/Internal). Be conversational and concise. After gathering enough info, output a JSON block like: {"name":"...","summary":"...","initiative":"ini_001","target":"YYYY-MM-DD","sensitivity":["phi"]}. Start by asking what the project is trying to accomplish.`
    : `You are helping a healthcare device company employee log a new idea in their innovation backlog. Ask them short questions one at a time to understand: what the idea is, what problem it solves, who benefits, and what success looks like. Be warm and curious. After 3–4 exchanges, output a JSON block like: {"title":"...","description":"..."}. Start with: "What's the spark? Describe the idea in a sentence or two."`;

  const [msgs, setMsgs] = React.useState([]);
  const [input, setInput] = React.useState('');
  const [loading, setLoading] = React.useState(false);
  const [filledData, setFilledData] = React.useState(null);
  const scrollRef = React.useRef(null);

  // Kick off with Claude's opening question
  React.useEffect(() => {
    setLoading(true);
    window.claude.complete({ messages: [{ role: 'user', content: 'Start the interview.' }], system: systemPrompt })
      .then(text => {
        setMsgs([{ who: 'claude', text }]);
        setLoading(false);
      })
      .catch(() => {
        setMsgs([{ who: 'claude', text: context === 'project' ? "What's this project trying to accomplish?" : "What's the spark? Describe the idea in a sentence or two." }]);
        setLoading(false);
      });
  }, []);

  React.useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [msgs, loading]);

  const send = async () => {
    if (!input.trim() || loading) return;
    const userMsg = input.trim();
    setInput('');
    const next = [...msgs, { who: 'me', text: userMsg }];
    setMsgs(next);
    setLoading(true);
    try {
      const history = next.map(m => ({ role: m.who === 'me' ? 'user' : 'assistant', content: m.text }));
      const reply = await window.claude.complete({ messages: history, system: systemPrompt });
      setMsgs([...next, { who: 'claude', text: reply }]);
      // detect JSON block in reply
      const match = reply.match(/\{[\s\S]*\}/);
      if (match) {
        try { setFilledData(JSON.parse(match[0])); } catch (_) {}
      }
    } catch (e) {
      setMsgs([...next, { who: 'claude', text: 'Sorry, I hit an error. Keep going or fill the form manually.' }]);
    }
    setLoading(false);
  };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: '100%', minHeight: 0 }}>
      {/* Header */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: 'var(--apm-row-pad) 20px', borderBottom: '1px solid var(--apm-line)', flexShrink: 0 }}>
        <div style={{ width: 28, height: 28, borderRadius: 8, background: 'var(--apm-ink)', color: 'var(--apm-bg-2)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          <Icon name="sparkle" size={14} />
        </div>
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 13, fontWeight: 600 }}>Claude</div>
          <div style={{ fontSize: 11, color: 'var(--apm-muted)' }}>interviewing you to fill this form</div>
        </div>
        <button onClick={onClose} style={{ background: 'transparent', border: 'none', cursor: 'pointer', color: 'var(--apm-muted)', padding: 4 }}><Icon name="x" size={14} /></button>
      </div>

      {/* Messages */}
      <div ref={scrollRef} style={{ flex: 1, padding: 16, overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: 'var(--apm-inner-gap)', minHeight: 0 }}>
        {msgs.map((m, i) => (
          <div key={i} style={{ display: 'flex', justifyContent: m.who === 'me' ? 'flex-end' : 'flex-start' }}>
            <div style={{
              maxWidth: '88%', padding: '9px 12px', borderRadius: 10,
              background: m.who === 'me' ? 'var(--apm-ink)' : 'var(--apm-bg-sunken)',
              color: m.who === 'me' ? 'var(--apm-bg-2)' : 'var(--apm-ink)',
              fontSize: 13, lineHeight: 1.5,
              whiteSpace: 'pre-wrap',
            }}>{m.who === 'claude' ? m.text.replace(/\{[\s\S]*\}/, '').trim() : m.text}</div>
          </div>
        ))}
        {loading && (
          <div style={{ display: 'flex', justifyContent: 'flex-start' }}>
            <div style={{ padding: '9px 14px', borderRadius: 10, background: 'var(--apm-bg-sunken)', fontSize: 13, color: 'var(--apm-muted)' }}>
              <span style={{ letterSpacing: 2 }}>···</span>
            </div>
          </div>
        )}
        {filledData && (
          <div style={{ padding: 12, background: 'color-mix(in oklab, var(--apm-accent) 10%, var(--apm-bg-2))', border: '1px solid color-mix(in oklab, var(--apm-accent) 40%, transparent)', borderRadius: 10 }}>
            <div style={{ fontSize: 12, fontWeight: 600, marginBottom: 6 }}>Ready to fill the form</div>
            <pre style={{ fontSize: 11, fontFamily: 'var(--apm-font-mono)', margin: 0, whiteSpace: 'pre-wrap', color: 'var(--apm-muted)' }}>{JSON.stringify(filledData, null, 2)}</pre>
            <Button variant="primary" size="sm" style={{ marginTop: 10 }} icon={<Icon name="check" size={13} />} onClick={() => onFill(filledData)}>
              Apply to form
            </Button>
          </div>
        )}
      </div>

      {/* Input */}
      <div style={{ padding: 12, borderTop: '1px solid var(--apm-line)', display: 'flex', gap: 8, flexShrink: 0 }}>
        <Input value={input} onChange={setInput} placeholder="Reply to Claude…" style={{ flex: 1 }} onKeyDown={e => e.key === 'Enter' && send()} />
        <Button variant="primary" size="sm" onClick={send} disabled={loading} icon={<Icon name="arrow_right" size={13} />}>Send</Button>
      </div>
    </div>
  );
};

// ── CHAT DRAWER ──────────────────────────────────────────────────────
const ChatDrawer = ({ open, onClose, persona }) => {
  const [msgs, setMsgs] = React.useState([
    { who: 'claude', text: `Hi ${persona.name.split(' ')[0]}. I can find projects, summarize gates, draft idea routing recommendations, or pull a stat. What do you need?` },
  ]);
  const [v, setV] = React.useState('');
  const [loading, setLoading] = React.useState(false);
  const scrollRef = React.useRef(null);

  React.useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [msgs]);

  const send = async () => {
    if (!v.trim() || loading) return;
    const userText = v.trim();
    setV('');
    const next = [...msgs, { who: 'me', text: userText }];
    setMsgs(next);
    setLoading(true);
    try {
      const history = next.map(m => ({ role: m.who === 'me' ? 'user' : 'assistant', content: m.text }));
      const reply = await window.claude.complete({
        messages: history,
        system: 'You are a portfolio management assistant for a healthcare device company called Earlens. You have knowledge of their projects (PEARL Fit-Coach MVP, HearWell Cloud Migration, Patient Consent Service, etc.), initiatives, RA/QA gates, and team. Answer concisely and helpfully.',
      });
      setMsgs([...next, { who: 'claude', text: reply }]);
    } catch {
      setMsgs([...next, { who: 'claude', text: 'Sorry, I had trouble with that one. Try again?' }]);
    }
    setLoading(false);
  };

  return (
    <Drawer open={open} onClose={onClose} width={420}>
      <div style={{ padding: 'var(--apm-row-pad) 20px', borderBottom: '1px solid var(--apm-line)', flexShrink: 0 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <div style={{ width: 32, height: 32, borderRadius: 8, background: 'var(--apm-ink)', color: 'var(--apm-bg-2)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <Icon name="sparkle" size={16} />
          </div>
          <div style={{ flex: 1 }}>
            <div style={{ fontFamily: 'var(--apm-font-display)', fontSize: 17 }}>Claude</div>
            <div style={{ fontSize: 11, color: 'var(--apm-muted)' }}>Your portfolio assistant · scoped to your access</div>
          </div>
          <button onClick={onClose} style={{ background: 'transparent', border: 'none', cursor: 'pointer', color: 'var(--apm-muted)' }}><Icon name="x" size={16} /></button>
        </div>
      </div>
      <div ref={scrollRef} style={{ flex: 1, padding: 20, overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: 'var(--apm-inner-gap)' }}>
        {msgs.map((m, i) => (
          <div key={i} style={{ display: 'flex', justifyContent: m.who === 'me' ? 'flex-end' : 'flex-start' }}>
            <div style={{
              maxWidth: '85%', padding: '10px 12px', borderRadius: 12,
              background: m.who === 'me' ? 'var(--apm-ink)' : 'var(--apm-bg-sunken)',
              color: m.who === 'me' ? 'var(--apm-bg-2)' : 'var(--apm-ink)',
              fontSize: 13, lineHeight: 1.5,
            }}>{m.text}</div>
          </div>
        ))}
        {loading && (
          <div style={{ display: 'flex', justifyContent: 'flex-start' }}>
            <div style={{ padding: '10px 14px', borderRadius: 12, background: 'var(--apm-bg-sunken)', fontSize: 13, color: 'var(--apm-muted)' }}>···</div>
          </div>
        )}
        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginTop: 4 }}>
          {['What changed since yesterday?', 'Why is PEARL at-risk?', 'Show me my queue'].map(q => (
            <button key={q} onClick={() => setV(q)} style={{
              padding: '5px 10px', background: 'transparent',
              border: '1px solid var(--apm-line-2)', borderRadius: 999,
              fontSize: 12, color: 'var(--apm-muted)', cursor: 'pointer', fontFamily: 'var(--apm-font-body)',
            }}>{q}</button>
          ))}
        </div>
      </div>
      <div style={{ padding: 14, borderTop: '1px solid var(--apm-line)', display: 'flex', gap: 8, flexShrink: 0 }}>
        <Input value={v} onChange={setV} placeholder="Ask Claude…" style={{ flex: 1 }} onKeyDown={e => e.key === 'Enter' && send()} />
        <Button variant="primary" onClick={send} disabled={loading} icon={<Icon name="arrow_right" size={14} />}>Ask</Button>
      </div>
    </Drawer>
  );
};

// ── MESSAGES PAGE ────────────────────────────────────────────────────
const MessagesPage = ({ persona, goto }) => {
  const myTickets = APM_TICKETS.filter(t => t.assignee === persona.id);
  const gateItems = persona.role === 'owner'
    ? [
        { id: 'g1', type: 'gate', title: 'RA/QA gate response needed — PEARL Fit-Coach MVP', project: 'prj_pearl', priority: 'high', age: '2h', from: 'p_jenna' },
        { id: 'g2', type: 'gate', title: 'Security gate condition: adverse-event routing plan', project: 'prj_pearl', priority: 'high', age: '1d', from: 'p_sarah' },
        { id: 'g3', type: 'gate', title: 'Cost & Ops gate sign-off requested — HearWell v3', project: 'prj_hw3', priority: 'med', age: '3d', from: 'p_marisa' },
      ]
    : persona.role === 'approver'
    ? [
        { id: 'g4', type: 'gate', title: 'Security gate review pending — Patient Consent Service', project: 'prj_consent', priority: 'high', age: '4h', from: 'p_priya' },
      ]
    : [];
  const permRequests = [
    { id: 'r1', type: 'perm', title: 'Access request: PHI projects read access', from: 'p_diego', age: '30 min', status: 'pending' },
    { id: 'r2', type: 'perm', title: 'Role request: Stage Approver (HIPAA/PII)', from: 'p_kira', age: '2h', status: 'pending' },
  ];

  const allItems = [
    ...gateItems.map(i => ({ ...i, category: 'Gate review' })),
    ...myTickets.map(t => ({ id: t.id, type: 'ticket', title: t.title, priority: t.priority, age: t.age, from: t.from, category: 'Ticket', project: t.project })),
    ...permRequests.map(r => ({ ...r, category: 'Access request' })),
  ];

  const categories = [...new Set(allItems.map(i => i.category))];

  return (
    <Page>
      <PageHeader kicker="Messages" title="Your open items"
        subtitle="Gate conditions awaiting your response, tickets assigned to you, and access requests that need your approval."
      />
      {allItems.length === 0 && (
        <EmptyState icon={<Icon name="bell" size={28} />} title="You're all caught up" body="No pending gate reviews, tickets, or access requests." />
      )}
      {categories.map(cat => {
        const items = allItems.filter(i => i.category === cat);
        return (
          <div key={cat} style={{ marginBottom: 'var(--apm-section-gap)' }}>
            <SectionHeading kicker={cat} title={`${items.length} item${items.length !== 1 ? 's' : ''}`} level={3} />
            <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--apm-inner-gap)' }}>
              {items.map(item => (
                <Card key={item.id} hoverable onClick={() => {
                  if (item.type === 'ticket') goto('tickets', { id: item.id });
                  else if (item.type === 'gate') goto('project', { id: item.project, tab: 'gates' });
                }}>
                  <div style={{ display: 'flex', gap: 14, alignItems: 'flex-start' }}>
                    <div style={{
                      width: 36, height: 36, borderRadius: 8, flexShrink: 0,
                      background: item.priority === 'high' || item.priority === 'P1' ? 'var(--apm-risk-soft)' : 'var(--apm-warn-soft)',
                      display: 'flex', alignItems: 'center', justifyContent: 'center',
                      color: item.priority === 'high' || item.priority === 'P1' ? 'var(--apm-risk)' : 'var(--apm-warn)',
                    }}>
                      <Icon name={item.type === 'ticket' ? 'tickets' : item.type === 'perm' ? 'admin' : 'flag'} size={16} />
                    </div>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontSize: 14, fontWeight: 500, lineHeight: 1.3 }}>{item.title}</div>
                      <div style={{ fontSize: 12, color: 'var(--apm-muted)', marginTop: 4, display: 'flex', gap: 12, flexWrap: 'wrap', alignItems: 'center' }}>
                        <span style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
                          <Avatar person={item.from} size={16} />
                          {PERSON_BY_ID[item.from]?.name}
                        </span>
                        <span>· {item.age}</span>
                        {item.project && <span>· <a onClick={e => { e.stopPropagation(); goto('project', { id: item.project }); }} style={{ color: 'var(--apm-accent-ink)', cursor: 'pointer' }}>{(PROJ_BY_ID[item.project]||{}).name}</a></span>}
                      </div>
                    </div>
                    <div style={{ display: 'flex', gap: 8, flexShrink: 0 }}>
                      {item.type === 'gate' && <>
                        <Button size="sm" variant="primary">Respond</Button>
                        <Button size="sm" variant="ghost">Snooze</Button>
                      </>}
                      {item.type === 'ticket' && <Button size="sm" variant="outline">Open</Button>}
                      {item.type === 'perm' && <>
                        <Button size="sm" variant="primary">Approve</Button>
                        <Button size="sm" variant="ghost">Deny</Button>
                      </>}
                    </div>
                  </div>
                </Card>
              ))}
            </div>
          </div>
        );
      })}
    </Page>
  );
};

// ── USER PROFILE PAGE ────────────────────────────────────────────────
const UserProfilePage = ({ persona, setTweak, t }) => {
  const PALETTES = [
    { id: 'cream', label: 'Cream', swatch: ['#f7f4ec', '#1d1b16', '#b5651d'] },
    { id: 'light', label: 'Light', swatch: ['#ffffff', '#111827', '#6366f1'] },
    { id: 'dark',  label: 'Dark',  swatch: ['#1a1917', '#f5f4f0', '#c084fc'] },
  ];
  const DENSITIES = [
    { id: 'compact', label: 'Compact', desc: '36px rows, tighter spacing' },
    { id: 'regular', label: 'Regular', desc: '44px rows, comfortable' },
    { id: 'comfy',   label: 'Comfy',   desc: '52px rows, relaxed' },
  ];

  return (
    <Page max={760}>
      <PageHeader kicker="Your account" title={persona.name} subtitle={`${APM_ROLES[persona.role]?.label} · ${persona.email || persona.id + '@earlens.com'}`}
        meta={<><Avatar person={persona} size={48} /><Badge tone="ok" size="sm">Active</Badge></>}
      />
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 24 }}>
        {/* Palette */}
        <div>
          <SectionHeading kicker="Appearance" title="Color palette" level={3} />
          <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--apm-inner-gap)' }}>
            {PALETTES.map(p => {
              const active = (t?.theme || 'cream') === p.id;
              return (
                <button key={p.id} onClick={() => setTweak('theme', p.id)} style={{
                  display: 'flex', alignItems: 'center', gap: 12, padding: 14,
                  background: active ? 'var(--apm-bg-sunken)' : 'transparent',
                  border: '1px solid ' + (active ? 'var(--apm-ink)' : 'var(--apm-line)'),
                  borderRadius: 'var(--apm-radius-lg)', cursor: 'pointer',
                  textAlign: 'left', fontFamily: 'var(--apm-font-body)',
                }}>
                  {/* swatch */}
                  <div style={{ display: 'flex', borderRadius: 6, overflow: 'hidden', flexShrink: 0, border: '1px solid var(--apm-line)' }}>
                    {p.swatch.map((c, i) => <div key={i} style={{ width: 18, height: 32, background: c }} />)}
                  </div>
                  <div style={{ flex: 1 }}>
                    <div style={{ fontSize: 13.5, fontWeight: 600 }}>{p.label}</div>
                  </div>
                  {active && <Icon name="check" size={14} style={{ color: 'var(--apm-accent)' }} />}
                </button>
              );
            })}
          </div>
        </div>

        {/* Density */}
        <div>
          <SectionHeading kicker="Layout" title="Density" level={3} />
          <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--apm-inner-gap)' }}>
            {DENSITIES.map(d => {
              const active = (t?.density || 'regular') === d.id;
              return (
                <button key={d.id} onClick={() => setTweak('density', d.id)} style={{
                  display: 'flex', alignItems: 'center', gap: 12, padding: 14,
                  background: active ? 'var(--apm-bg-sunken)' : 'transparent',
                  border: '1px solid ' + (active ? 'var(--apm-ink)' : 'var(--apm-line)'),
                  borderRadius: 'var(--apm-radius-lg)', cursor: 'pointer',
                  textAlign: 'left', fontFamily: 'var(--apm-font-body)',
                }}>
                  <div style={{ flex: 1 }}>
                    <div style={{ fontSize: 13.5, fontWeight: 600 }}>{d.label}</div>
                    <div style={{ fontSize: 12, color: 'var(--apm-muted)', marginTop: 2 }}>{d.desc}</div>
                  </div>
                  {active && <Icon name="check" size={14} style={{ color: 'var(--apm-accent)' }} />}
                </button>
              );
            })}
          </div>

          <div style={{ marginTop: 'var(--apm-section-gap)' }}>
            <SectionHeading kicker="Session" title="Account" level={3} />
            <Card>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--apm-inner-gap)' }}>
                <div style={{ fontSize: 13 }}>
                  <div style={{ color: 'var(--apm-muted)', fontSize: 11, marginBottom: 2 }}>Role</div>
                  <div>{APM_ROLES[persona.role]?.label}</div>
                </div>
                <div style={{ fontSize: 13 }}>
                  <div style={{ color: 'var(--apm-muted)', fontSize: 11, marginBottom: 2 }}>Email</div>
                  <div style={{ fontFamily: 'var(--apm-font-mono)', fontSize: 12 }}>{persona.id.replace('p_', '')}@earlens.com</div>
                </div>
                <Button variant="outline" size="sm" style={{ marginTop: 4 }}>Sign out</Button>
              </div>
            </Card>
          </div>
        </div>
      </div>
    </Page>
  );
};

Object.assign(window, {
  ClaudeInterview,
  IdeasPage, IdeaDetail, ComponentsPage, ComponentDetail,
  TicketsPage, HelpPage, AdminPage,
  NewProjectWizard, IdeaCompose, ChatDrawer,
  MessagesPage, UserProfilePage,
});
