// Home page — 9 persona variants. Project Owner has 2 layout variations.
// Each variant uses the same data primitives but emphasizes different things.

// ── Shared sub-blocks ────────────────────────────────────────────────
const ActivityRow = ({ a }) => (
  <div style={{ display: 'flex', alignItems: 'flex-start', gap: 12, padding: 'var(--apm-row-pad) 0', borderBottom: '1px solid var(--apm-line)' }}>
    <Avatar person={a.who} size={26} />
    <div style={{ flex: 1, minWidth: 0, fontSize: 13, lineHeight: 1.5 }}>
      <span style={{ fontWeight: 600 }}>{PERSON_BY_ID[a.who].name}</span>
      <span style={{ color: 'var(--apm-muted)' }}> {a.verb} </span>
      <span>{a.what}</span>
      <div style={{ fontSize: 11.5, color: 'var(--apm-muted-2)', marginTop: 2 }}>{a.when}</div>
    </div>
  </div>
);

const QuickAction = ({ icon, label, hint, onClick, accent }) => (
  <button onClick={onClick} style={{
    display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: 8,
    padding: 14, minHeight: 96,
    background: accent ? 'var(--apm-accent-soft)' : 'var(--apm-card)',
    border: '1px solid ' + (accent ? 'var(--apm-accent)' : 'var(--apm-line)'),
    borderRadius: 'var(--apm-radius-lg)', cursor: 'pointer', textAlign: 'left',
    fontFamily: 'var(--apm-font-body)', transition: 'border-color .12s, box-shadow .12s',
  }}
    onMouseEnter={e => { e.currentTarget.style.boxShadow = 'var(--apm-shadow-md)'; }}
    onMouseLeave={e => { e.currentTarget.style.boxShadow = 'none'; }}>
    <div style={{
      width: 32, height: 32, borderRadius: 8,
      background: accent ? 'var(--apm-accent)' : 'var(--apm-bg-sunken)',
      color: accent ? '#fff' : 'var(--apm-ink-2)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
    }}><Icon name={icon} size={16} /></div>
    <div style={{ fontWeight: 600, fontSize: 13.5, color: accent ? 'var(--apm-accent-ink)' : 'var(--apm-ink)' }}>{label}</div>
    <div style={{ fontSize: 12, color: 'var(--apm-muted)', lineHeight: 1.4 }}>{hint}</div>
  </button>
);

const InboxRow = ({ icon, tone = 'neutral', title, meta, action, onClick }) => (
  <div onClick={onClick} style={{
    display: 'flex', alignItems: 'center', gap: 12,
    padding: 'var(--apm-row-pad) 12px', borderRadius: 'var(--apm-radius)',
    cursor: onClick ? 'pointer' : 'default',
    transition: 'background .1s',
  }}
    onMouseEnter={e => { if (onClick) e.currentTarget.style.background = 'var(--apm-bg-sunken)'; }}
    onMouseLeave={e => { if (onClick) e.currentTarget.style.background = 'transparent'; }}>
    <div style={{
      width: 28, height: 28, borderRadius: 6,
      background: 'var(--apm-bg-sunken)',
      color: tone === 'risk' ? 'var(--apm-risk)' : tone === 'warn' ? 'var(--apm-warn)' : tone === 'ok' ? 'var(--apm-ok)' : 'var(--apm-ink-2)',
      display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
    }}><Icon name={icon} size={14} /></div>
    <div style={{ flex: 1, minWidth: 0 }}>
      <div style={{ fontSize: 13.5, fontWeight: 500, lineHeight: 1.4, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{title}</div>
      <div style={{ fontSize: 12, color: 'var(--apm-muted)', marginTop: 1 }}>{meta}</div>
    </div>
    {action}
  </div>
);

// ── 1. PROJECT OWNER home (variant A: action-first) ─────────────────
const HomeOwner = ({ persona, variant = 'a', goto }) => {
  const myProjects = projectsByOwner(persona.id);
  const dueGates = myProjects.filter(p => p.health === 'at-risk' || p.progress > 50 && p.progress < 100);
  const myTickets = ticketsByAssignee(persona.id);

  if (variant === 'b') {
    // Variant B — focus mode, single-column timeline of "what's next"
    return (
      <Page max={920}>
        <PageHeader
          kicker={`Good morning, ${persona.name.split(' ')[0]}`}
          title="Three things blocking your week"
          subtitle="A focused view of the gates, decisions, and tickets that need you specifically — in the order they should be tackled."
        />

        <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--apm-inner-gap)' }}>
          {/* 1 */}
          <Card>
            <div style={{ display: 'flex', alignItems: 'flex-start', gap: 16 }}>
              <div style={{
                width: 40, height: 40, borderRadius: 10, background: 'var(--apm-risk-soft)',
                color: 'var(--apm-risk)', display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontFamily: 'var(--apm-font-display)', fontSize: 20,
              }}>1</div>
              <div style={{ flex: 1 }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
                  <Badge tone="risk" dot size="sm">Gate response due</Badge>
                  <span style={{ fontSize: 11, color: 'var(--apm-muted)' }}>· today</span>
                </div>
                <div style={{ fontFamily: 'var(--apm-font-display)', fontSize: 22, lineHeight: 1.2, letterSpacing: '-0.01em' }}>
                  RA/QA flagged 2 conditions on PEARL Fit-Coach MVP
                </div>
                <div style={{ fontSize: 13, color: 'var(--apm-muted)', marginTop: 6 }}>
                  Jenna Rowe needs your response on consent-scope coverage and adverse-event routing before the gate review tomorrow.
                </div>
                <div style={{ display: 'flex', gap: 8, marginTop: 14 }}>
                  <Button variant="primary" size="sm" onClick={() => goto('project', { id: 'proj_fitcoach_mvp', tab: 'gates' })}>Open gate review</Button>
                  <Button variant="ghost" size="sm">Defer 24h</Button>
                </div>
              </div>
            </div>
          </Card>

          {/* 2 */}
          <Card>
            <div style={{ display: 'flex', alignItems: 'flex-start', gap: 16 }}>
              <div style={{
                width: 40, height: 40, borderRadius: 10, background: 'var(--apm-warn-soft)',
                color: 'var(--apm-warn)', display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontFamily: 'var(--apm-font-display)', fontSize: 20,
              }}>2</div>
              <div style={{ flex: 1 }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
                  <Badge tone="warn" dot size="sm">Component change</Badge>
                  <span style={{ fontSize: 11, color: 'var(--apm-muted)' }}>· this week</span>
                </div>
                <div style={{ fontFamily: 'var(--apm-font-display)', fontSize: 22, lineHeight: 1.2, letterSpacing: '-0.01em' }}>
                  Consent Ledger split is breaking — vote on impact for your 2 dependent projects
                </div>
                <div style={{ fontSize: 13, color: 'var(--apm-muted)', marginTop: 6 }}>
                  Migrating to clinical-care-only consent will require a re-prompt flow in PEARL Fit-Coach and Patient Consent Service.
                </div>
                <div style={{ display: 'flex', gap: 8, marginTop: 14 }}>
                  <Button variant="primary" size="sm" onClick={() => goto('components', { id: 'comp_consent', change: 'chg_002' })}>Review change</Button>
                  <Button variant="ghost" size="sm">Pull into a follow-on</Button>
                </div>
              </div>
            </div>
          </Card>

          {/* 3 */}
          <Card>
            <div style={{ display: 'flex', alignItems: 'flex-start', gap: 16 }}>
              <div style={{
                width: 40, height: 40, borderRadius: 10, background: 'var(--apm-info-soft)',
                color: 'var(--apm-info)', display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontFamily: 'var(--apm-font-display)', fontSize: 20,
              }}>3</div>
              <div style={{ flex: 1 }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
                  <Badge tone="info" dot size="sm">Idea routing</Badge>
                  <span style={{ fontSize: 11, color: 'var(--apm-muted)' }}>· no rush</span>
                </div>
                <div style={{ fontFamily: 'var(--apm-font-display)', fontSize: 22, lineHeight: 1.2, letterSpacing: '-0.01em' }}>
                  Tomás logged &ldquo;Auto-summarize visit notes&rdquo; — does it belong in your Q-shape work?
                </div>
                <div style={{ fontSize: 13, color: 'var(--apm-muted)', marginTop: 6 }}>
                  14 upvotes. The idea touches charting and patient comms — your call whether it merges, gets promoted, or gets parked.
                </div>
                <div style={{ display: 'flex', gap: 8, marginTop: 14 }}>
                  <Button variant="primary" size="sm" onClick={() => goto('ideas', { id: 'idea_001' })}>Open idea</Button>
                  <Button variant="ghost" size="sm">Reply to Tomás</Button>
                </div>
              </div>
            </div>
          </Card>
        </div>

        <div style={{ display: 'flex', alignItems: 'center', gap: 12, justifyContent: 'center', marginTop: 'var(--apm-section-gap)', color: 'var(--apm-muted)', fontSize: 12.5 }}>
          <span>You also have {myTickets.length} open tickets and {myProjects.length} projects.</span>
          <Button size="sm" variant="ghost" icon={<Icon name="grid" size={14} />} onClick={() => goto('home', { variant: 'a' })}>
            Switch to dashboard view
          </Button>
        </div>
      </Page>
    );
  }

  // Variant A — full dashboard
  return (
    <Page>
      <PageHeader
        kicker={`Good morning, ${persona.name.split(' ')[0]}`}
        title={`You own ${myProjects.length} projects across ${new Set(myProjects.map(p=>p.initiative)).size} initiatives`}
        subtitle="Gate reviews, change requests touching your components, and ideas in your space all flow here. The home is read-only — actions live on the project pages."
        action={<div style={{ display: 'flex', gap: 8 }}>
          <Button variant="outline" icon={<Icon name="layers" size={14} />} onClick={() => goto('home', { variant: 'b' })}>Focus view</Button>
          <Button variant="primary" icon={<Icon name="plus" size={14} />} onClick={() => goto('__new_project__')}>New project</Button>
        </div>}
      />

      {/* Top stats */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 16, marginBottom: 'var(--apm-section-gap)' }}>
        <Card>
          <Stat label="Gate items waiting on you" value="3" sub="2 RA/QA, 1 Security" tone="warn" />
        </Card>
        <Card>
          <Stat label="Project health" value="64%" sub="↓ 6 pts week" tone="warn" spark={
            <Sparkline values={[78,76,74,71,68,65,64]} stroke="var(--apm-warn)" w={120} h={24} />
          } />
        </Card>
        <Card>
          <Stat label="Open tickets in your projects" value={myTickets.length} sub="2 P1 · 4 P2" />
        </Card>
        <Card>
          <Stat label="Ideas in your space" value="3" sub="1 needs routing" tone="accent" />
        </Card>
      </div>

      {/* Two-col */}
      <div style={{ display: 'grid', gridTemplateColumns: '1.55fr 1fr', gap: 24 }}>
        {/* My projects */}
        <div>
          <SectionHeading kicker="Owned by you" title="Projects" action={
            <Button variant="ghost" size="sm" onClick={() => goto('projects')}>View all <Icon name="arrow_right" size={12} /></Button>
          } />
          <Card pad={false}>
            <div style={{ display: 'grid', gridTemplateColumns: '1.7fr 0.9fr 0.7fr 0.7fr 1fr', padding: '10px 16px', fontSize: 11, color: 'var(--apm-muted)', textTransform: 'uppercase', letterSpacing: '0.1em', borderBottom: '1px solid var(--apm-line)' }}>
              <div>Project</div><div>Phase</div><div>Health</div><div>Tickets</div><div>Target</div>
            </div>
            {myProjects.slice(0, 6).map((p, i) => (
              <div key={p.id} onClick={() => goto('project', { id: p.id })} style={{
                display: 'grid', gridTemplateColumns: '1.7fr 0.9fr 0.7fr 0.7fr 1fr',
                padding: 'var(--apm-row-pad) var(--apm-card-pad)', alignItems: 'center', cursor: 'pointer',
                borderBottom: i < myProjects.slice(0,6).length - 1 ? '1px solid var(--apm-line)' : 'none',
                transition: 'background .1s',
              }}
                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 }}>{p.name}</div>
                  <div style={{ fontSize: 11.5, color: 'var(--apm-muted)', marginTop: 2 }}>{p.code} · {INI_BY_ID[p.initiative].name}</div>
                </div>
                <div><PhasePill phase={p.phase} /></div>
                <div><HealthDot value={p.health} /></div>
                <div style={{ fontSize: 13, color: 'var(--apm-muted)' }}>{p.openTickets}</div>
                <div style={{ fontSize: 12.5, color: 'var(--apm-muted)' }}>{p.target}</div>
              </div>
            ))}
          </Card>

          {/* Gates */}
          <div style={{ marginTop: 'var(--apm-section-gap)' }}>
            <SectionHeading kicker="Phase gates" title="Waiting on you or on a reviewer" />
            <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--apm-inner-gap)' }}>
              <InboxRow icon="flag" tone="warn"
                title="PEARL Fit-Coach MVP — RA/QA review (2 conditions)"
                meta="Jenna Rowe · gate review tomorrow at 10am"
                action={<Button size="sm" variant="primary" onClick={() => goto('project', { id: 'proj_fitcoach_mvp', tab: 'gates' })}>Open</Button>}
                onClick={() => goto('project', { id: 'proj_fitcoach_mvp', tab: 'gates' })} />
              <InboxRow icon="shield" tone="risk"
                title="Audit Event Pipeline — Cost & Ops gate"
                meta="Marisa Vidal · awaiting your budget revision"
                action={<Button size="sm" variant="outline" onClick={() => goto('project', { id: 'proj_audit_pipe', tab: 'gates' })}>Open</Button>}
                onClick={() => goto('project', { id: 'proj_audit_pipe', tab: 'gates' })} />
              <InboxRow icon="check" tone="ok"
                title="Patient Consent Service — HIPAA review cleared"
                meta="approved by Sam Okafor · proceed to UAT"
                action={<Button size="sm" variant="ghost" onClick={() => goto('project', { id: 'proj_consent' })}>View</Button>} />
            </div>
          </div>
        </div>

        {/* Right rail */}
        <div>
          <SectionHeading kicker="Actions" title="Quick start" />
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8, marginBottom: 'var(--apm-section-gap)' }}>
            <QuickAction icon="plus"  label="New project"  hint="Phase 0 intake" accent onClick={() => goto('__new_project__')} />
            <QuickAction icon="ideas" label="Log an idea"  hint="Promote later" />
            <QuickAction icon="flag"  label="Submit gate"  hint="From a project" />
            <QuickAction icon="branch" label="Component change" hint="Notify dependents" />
          </div>

          <SectionHeading kicker="Activity" title="In your space" level={3} />
          <Card pad={false}>
            <div style={{ padding: '0 var(--apm-card-pad)' }}>
              {APM_ACTIVITY.slice(0, 6).map((a, i) => <ActivityRow key={i} a={a} />)}
            </div>
          </Card>
        </div>
      </div>
    </Page>
  );
};

// ── 2. ADMIN home ────────────────────────────────────────────────────
const HomeAdmin = ({ persona, goto }) => (
  <Page>
    <PageHeader kicker={`${persona.name.split(' ')[0]} · Platform admin`}
      title="Platform health, access, and taxonomy"
      subtitle="The admin home is operations-first — what is wrong with the platform, who is asking for access, what taxonomy needs cleaning up."
      action={<Button variant="primary" icon={<Icon name="plus" size={14} />}>Invite user</Button>}
    />

    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 16, marginBottom: 'var(--apm-section-gap)' }}>
      <Card><Stat label="Active users" value="184" sub="↑ 6 this week" tone="ok" /></Card>
      <Card><Stat label="Pending access requests" value="7" sub="2 over 48h" tone="warn" /></Card>
      <Card><Stat label="Failed gate notifications" value="2" tone="risk" sub="re-queued" /></Card>
      <Card><Stat label="SOC 2 control coverage" value="94%" sub="3 controls open" /></Card>
    </div>

    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 24 }}>
      <div>
        <SectionHeading kicker="Inbox" title="Access & roles" />
        <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--apm-inner-gap)' }}>
          <InboxRow icon="user" title="Tomás Beltrán requests Project Owner role on PEARL"
            meta="approved by Marisa Vidal · awaiting you"
            action={<><Button size="sm" variant="primary">Grant</Button></>} />
          <InboxRow icon="users" title="3 new audiologists need clinic-app access"
            meta="bulk request from Diego Salas"
            action={<Button size="sm" variant="outline">Review</Button>} />
          <InboxRow icon="lock" tone="warn" title="Quarterly access review: 12 stale RA/QA accounts"
            meta="revoke or re-attest by Friday"
            action={<Button size="sm" variant="primary">Start</Button>} />
          <InboxRow icon="shield" tone="risk" title="MFA enrollment overdue for 4 clinical roles"
            meta="forced re-enroll active"
            action={<Button size="sm" variant="ghost">View</Button>} />
        </div>
      </div>

      <div>
        <SectionHeading kicker="Taxonomy" title="Sensitivity, tags, and workspaces" />
        <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 style={{ fontSize: 12, color: 'var(--apm-muted-2)' }}>{[42, 31, 8, 5, 27][APM_SENSITIVITY.indexOf(s)]} projects</div>
              </div>
            ))}
            <div style={{ borderTop: '1px solid var(--apm-line)', paddingTop: 16, marginTop: 8 }}>
              <Button size="sm" variant="ghost" icon={<Icon name="plus" size={12} />} onClick={() => goto('admin')}>Manage tags & access groups</Button>
            </div>
          </div>
        </Card>

        <div style={{ marginTop: 'var(--apm-section-gap)' }}>
          <SectionHeading kicker="Audit" title="Recent platform events" level={3} />
          <Card pad={false}>
            <div style={{ padding: '0 var(--apm-card-pad)' }}>
              {APM_ACTIVITY.slice(0, 5).map((a, i) => <ActivityRow key={i} a={a} />)}
            </div>
          </Card>
        </div>
      </div>
    </div>
  </Page>
);

// ── 3. STAGE APPROVER (Security) home ───────────────────────────────
const HomeApprover = ({ persona, goto }) => (
  <Page>
    <PageHeader kicker={`${persona.name.split(' ')[0]} · Stage approver`}
      title="Your queue: 4 projects waiting on a Security or HIPAA decision"
      subtitle="Triage by project sensitivity. Open the gate review to leave conditions or sign off. Approvals here unblock downstream UAT and Go-Live."
    />

    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 16, marginBottom: 'var(--apm-section-gap)' }}>
      <Card><Stat label="Awaiting your sign-off" value="4" tone="warn" /></Card>
      <Card><Stat label="Avg time-to-decision" value="2.4d" sub="goal: <3d" tone="ok" /></Card>
      <Card><Stat label="Conditional approvals (open)" value="7" sub="across 5 projects" /></Card>
    </div>

    <SectionHeading kicker="Gate queue" title="Sorted by sensitivity, then age" />
    <Card pad={false}>
      {[
        { proj: 'proj_fitcoach_mvp', gate: 'HIPAA/PII', age: '6 hr',  prio: 'high' },
        { proj: 'proj_consent',      gate: 'HIPAA/PII', age: '1 day', prio: 'high' },
        { proj: 'proj_doctrl',       gate: 'Security',  age: '2 day', prio: 'med' },
        { proj: 'proj_audit_pipe',   gate: 'Security',  age: '3 day', prio: 'med' },
      ].map((row, i, arr) => {
        const p = PROJ_BY_ID[row.proj];
        return (
          <div key={i} onClick={() => goto('project', { id: p.id, tab: 'gates' })} style={{
            display: 'grid', gridTemplateColumns: '40px 1fr 140px 120px 120px',
            padding: 'var(--apm-row-pad) var(--apm-card-pad)', alignItems: 'center', gap: 12, cursor: 'pointer',
            borderBottom: i < arr.length - 1 ? '1px solid var(--apm-line)' : 'none',
            transition: 'background .1s',
          }}
            onMouseEnter={e => e.currentTarget.style.background = 'var(--apm-bg-sunken)'}
            onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
            <Badge tone={row.prio === 'high' ? 'risk' : 'warn'} dot size="sm">{row.prio === 'high' ? 'High' : 'Med'}</Badge>
            <div>
              <div style={{ fontSize: 14, fontWeight: 600 }}>{p.name}</div>
              <div style={{ fontSize: 12, color: 'var(--apm-muted)', marginTop: 2, display: 'flex', gap: 6, flexWrap: 'wrap' }}>
                {p.code} · owner {PERSON_BY_ID[p.owner].name} · {p.sensitivity.map(s => <SensitivityTag key={s} id={s} />)}
              </div>
            </div>
            <PhasePill phase={row.gate} />
            <div style={{ fontSize: 12.5, color: 'var(--apm-muted)' }}>open {row.age}</div>
            <Button size="sm" variant="primary">Open gate</Button>
          </div>
        );
      })}
    </Card>

    <div style={{ marginTop: 'var(--apm-section-gap)' }}>
      <SectionHeading kicker="Knowledge" title="Standing conditions" level={3} />
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
        <Card>
          <div style={{ fontSize: 13.5, fontWeight: 600 }}>Any project handling PHI</div>
          <div style={{ fontSize: 12.5, color: 'var(--apm-muted)', marginTop: 4 }}>Must use comp_consent v1.2+ and emit to comp_audit. Re-confirm at Go-Live.</div>
        </Card>
        <Card>
          <div style={{ fontSize: 13.5, fontWeight: 600 }}>Any external partner integration</div>
          <div style={{ fontSize: 12.5, color: 'var(--apm-muted)', marginTop: 4 }}>Pen-test on file within 12 months. mTLS only. Logs land in audit pipeline.</div>
        </Card>
      </div>
    </div>
  </Page>
);

// ── 4. PORTFOLIO MANAGER home ───────────────────────────────────────
const HomeManager = ({ persona, goto }) => (
  <Page>
    <PageHeader kicker={`${persona.name.split(' ')[0]} · Portfolio`}
      title="4 initiatives, 12 projects, 1 trending red"
      subtitle="The portfolio dashboard. Capacity, spend, health, and the cross-project risks that don't show up at the project level."
      action={<Button variant="primary" icon={<Icon name="plus" size={14} />}>New initiative</Button>}
    />

    {/* Initiatives strip */}
    <SectionHeading kicker="Initiatives" title="Health & spend" />
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 16, marginBottom: 32 }}>
      {APM_INITIATIVES.map(ini => {
        const tone = ini.health >= 75 ? 'var(--apm-ok)' : ini.health >= 60 ? 'var(--apm-warn)' : 'var(--apm-risk)';
        return (
          <Card key={ini.id} hoverable onClick={() => goto('initiative', { id: ini.id })}>
            <div style={{ display: 'flex', justifyContent: 'space-between', gap: 16, alignItems: 'flex-start' }}>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 11, color: 'var(--apm-muted)', textTransform: 'uppercase', letterSpacing: '0.12em' }}>{ini.code}</div>
                <div style={{ fontFamily: 'var(--apm-font-display)', fontSize: 20, marginTop: 4, letterSpacing: '-0.01em' }}>{ini.name}</div>
                <div style={{ fontSize: 12.5, color: 'var(--apm-muted)', marginTop: 6, lineHeight: 1.5 }}>{ini.summary}</div>
              </div>
              <HealthDot value={ini.status} />
            </div>
            <div style={{ display: 'flex', gap: 16, marginTop: 16, fontSize: 12.5, color: 'var(--apm-muted)' }}>
              <div><span style={{ color: 'var(--apm-ink)', fontWeight: 600 }}>{projectsByInitiative(ini.id).length}</span> projects</div>
              <div><span style={{ color: 'var(--apm-ink)', fontWeight: 600 }}>{fmtMoney(ini.spent)}</span> / {fmtMoney(ini.budget)}</div>
              <div>target {ini.target}</div>
            </div>
            <div style={{ marginTop: 12 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 11, marginBottom: 4 }}>
                <span style={{ color: 'var(--apm-muted)' }}>Health</span>
                <span style={{ color: tone, fontWeight: 600 }}>{ini.health}</span>
              </div>
              <HealthBar value={ini.health} />
            </div>
          </Card>
        );
      })}
    </div>

    <div style={{ display: 'grid', gridTemplateColumns: '1.3fr 1fr', gap: 24 }}>
      <div>
        <SectionHeading kicker="Capacity" title="Team load this quarter" level={3} />
        <Card>
          {[
            { team: 'Clinical Apps', load: 92 },
            { team: 'Platform',      load: 78 },
            { team: 'Regulatory',    load: 64 },
            { team: 'IT Support',    load: 48 },
          ].map((t,i,a) => (
            <div key={t.team} style={{ display: 'flex', alignItems: 'center', gap: 16, padding: 'var(--apm-row-pad) 0', borderBottom: i < a.length-1 ? '1px solid var(--apm-line)' : 'none' }}>
              <div style={{ width: 140, fontSize: 13, fontWeight: 500 }}>{t.team}</div>
              <div style={{ flex: 1 }}><HealthBar value={t.load} height={8} /></div>
              <div style={{ width: 50, textAlign: 'right', fontSize: 12.5, color: 'var(--apm-muted)', fontVariantNumeric: 'tabular-nums' }}>{t.load}%</div>
            </div>
          ))}
        </Card>
      </div>
      <div>
        <SectionHeading kicker="Cross-project" title="Shared risks" level={3} />
        <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--apm-inner-gap)' }}>
          <InboxRow icon="branch" tone="warn" title="Consent Ledger split affects 3 projects across 2 initiatives" meta="open change · 7 votes" action={<Button size="sm" variant="outline">Open</Button>} />
          <InboxRow icon="users"  tone="warn" title="Clinical Apps team is 92% loaded — PEARL OKR slipped" meta="re-plan window: this week" action={<Button size="sm" variant="outline">Plan</Button>} />
          <InboxRow icon="money"  tone="risk" title="Audit Event Pipeline projected 18% over budget" meta="needs Cost & Ops re-baselining" action={<Button size="sm" variant="outline">Open</Button>} />
        </div>
      </div>
    </div>
  </Page>
);

// ── 5. RA/QA home ────────────────────────────────────────────────────
const HomeRaqa = ({ persona, goto }) => (
  <Page>
    <PageHeader kicker={`${persona.name.split(' ')[0]} · RA/QA`}
      title="Compliance posture across the portfolio"
      subtitle="Regulated workflows you sign off on. Document control, post-market, and the projects whose evidence is incomplete."
    />

    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 16, marginBottom: 'var(--apm-section-gap)' }}>
      <Card><Stat label="RA/QA reviews queued" value="4" tone="warn" sub="2 with PHI" /></Card>
      <Card><Stat label="Conditions outstanding" value="11" sub="across 6 projects" /></Card>
      <Card><Stat label="PMS signals (30d)" value="34" sub="3 escalated" tone="info" /></Card>
      <Card><Stat label="QMS migration" value="55%" sub="proj_doctrl" tone="ok" spark={<Sparkline values={[20,25,33,40,48,52,55]} stroke="var(--apm-ok)" w={120} h={24} />} /></Card>
    </div>

    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 24 }}>
      <div>
        <SectionHeading kicker="Queue" title="Awaiting your review" />
        <Card pad={false}>
          {APM_PROJECTS.filter(p => p.raqa === persona.id && (p.phase === 'RA/QA' || p.phase === 'HIPAA/PII')).map((p, i, a) => (
            <div key={p.id} onClick={() => goto('project', { id: p.id, tab: 'gates' })} style={{
              padding: 'var(--apm-row-pad) var(--apm-card-pad)', 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={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
                <div>
                  <div style={{ fontSize: 14, fontWeight: 600 }}>{p.name}</div>
                  <div style={{ fontSize: 11.5, color: 'var(--apm-muted)', marginTop: 2 }}>{p.code} · owner {PERSON_BY_ID[p.owner].name}</div>
                </div>
                <PhasePill phase={p.phase} />
              </div>
              <div style={{ display: 'flex', gap: 6, marginTop: 8, flexWrap: 'wrap' }}>
                {p.sensitivity.map(s => <SensitivityTag key={s} id={s} />)}
              </div>
            </div>
          ))}
        </Card>
      </div>
      <div>
        <SectionHeading kicker="Compliance" title="Standing items" />
        <Card>
          {[
            { label: 'CER documents on file', value: '34 / 36', tone: 'warn' },
            { label: 'Training records up-to-date', value: '92%', tone: 'ok' },
            { label: 'Adverse-event signals', value: '3 escalated', tone: 'risk' },
            { label: 'External audits next 90d', value: '2 (BSI, FDA)', tone: 'info' },
          ].map((r, i, a) => (
            <div key={r.label} 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 style={{ fontSize: 13 }}>{r.label}</div>
              <Badge tone={r.tone} size="sm">{r.value}</Badge>
            </div>
          ))}
        </Card>
      </div>
    </div>
  </Page>
);

// ── 6. HELPDESK home ────────────────────────────────────────────────
const HomeHelpdesk = ({ persona, goto }) => (
  <Page>
    <PageHeader kicker={`${persona.name.split(' ')[0]} · Helpdesk`}
      title="Open tickets, help-board questions, and the things that became patterns"
      subtitle="Run the queue. Promote patterns into ideas or projects when one ticket becomes ten."
      action={<Button variant="primary" icon={<Icon name="plus" size={14} />}>New ticket</Button>}
    />

    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 16, marginBottom: 'var(--apm-section-gap)' }}>
      <Card><Stat label="P1 / P2 open" value="2 / 4" tone="risk" /></Card>
      <Card><Stat label="Help board open" value="2" sub="0 SLA-breaching" /></Card>
      <Card><Stat label="Avg time-to-first-touch" value="14m" sub="↓ from 22m" tone="ok" /></Card>
      <Card><Stat label="Patterns ready to promote" value="3" tone="accent" /></Card>
    </div>

    <div style={{ display: 'grid', gridTemplateColumns: '1.3fr 1fr', gap: 24 }}>
      <div>
        <SectionHeading kicker="Live queue" title="Open tickets" action={<Button size="sm" variant="ghost" onClick={() => goto('tickets')}>All <Icon name="arrow_right" size={12} /></Button>} />
        <Card pad={false}>
          {APM_TICKETS.slice(0, 6).map((t, i, a) => (
            <div key={t.id} onClick={() => goto('tickets', { id: t.id })} style={{
              display: 'grid', gridTemplateColumns: '60px 1fr 130px 80px 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)' }}>{PROJ_BY_ID[t.project].name} · {t.age}</div>
              </div>
              <Badge tone={t.status === 'open' ? 'warn' : 'info'} size="sm" dot>{t.status}</Badge>
              {t.assignee ? <Avatar person={t.assignee} size={24} /> : <span style={{ fontSize: 12, color: 'var(--apm-muted-2)' }}>—</span>}
              <Button size="sm" variant="ghost">Take</Button>
            </div>
          ))}
        </Card>
      </div>

      <div>
        <SectionHeading kicker="Help board" title="Unanswered questions" />
        <Card>
          {APM_HELP.filter(h => h.status === 'open').map((h,i,a) => (
            <div key={h.id} style={{ padding: 'var(--apm-row-pad) 0', borderBottom: i < a.length-1 ? '1px solid var(--apm-line)' : 'none' }}>
              <div style={{ fontSize: 13, fontWeight: 500 }}>{h.title}</div>
              <div style={{ fontSize: 11.5, color: 'var(--apm-muted)', marginTop: 2 }}>asked by {PERSON_BY_ID[h.from].name} · {h.age}</div>
            </div>
          ))}
        </Card>

        <div style={{ marginTop: 'var(--apm-section-gap)' }}>
          <SectionHeading kicker="Patterns" title="Promote to ideas" level={3} />
          <Card>
            <div style={{ fontSize: 13, lineHeight: 1.5 }}>
              <strong>"Where do I find the clinic PIN reset flow?"</strong> appeared 8 times in 30 days.
            </div>
            <div style={{ display: 'flex', gap: 8, marginTop: 12 }}>
              <Button size="sm" variant="primary" onClick={() => goto('ideas', { compose: 'pattern' })}>Promote to idea</Button>
              <Button size="sm" variant="ghost">Dismiss</Button>
            </div>
          </Card>
        </div>
      </div>
    </div>
  </Page>
);

// ── 7. DEVOPS home ──────────────────────────────────────────────────
const HomeDevops = ({ persona, goto }) => (
  <Page>
    <PageHeader kicker={`${persona.name.split(' ')[0]} · DevOps`}
      title="Components you own and the change requests that touch them"
      subtitle="The components catalog is your fan-out: every breaking change here costs N project-weeks downstream. Accept, reject, or schedule."
    />

    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 16, marginBottom: 'var(--apm-section-gap)' }}>
      <Card><Stat label="Components owned" value={componentsByOwner(persona.id).length} sub="2 GA, 2 RC" /></Card>
      <Card><Stat label="Pending changes" value="2" tone="warn" sub="1 breaking" /></Card>
      <Card><Stat label="Dependent projects" value="9" sub="3 in flight" /></Card>
      <Card><Stat label="Releases (30d)" value="6" tone="ok" sub="0 rolled back" spark={<Sparkline values={[1,2,1,3,2,4,6]} stroke="var(--apm-ok)" w={120} h={24} />} /></Card>
    </div>

    <SectionHeading kicker="Components" title="Your catalog" />
    <Card pad={false}>
      {componentsByOwner(persona.id).map((c,i,a) => (
        <div key={c.id} onClick={() => goto('components', { id: c.id })} style={{
          padding: 'var(--apm-row-pad) var(--apm-card-pad)', cursor: 'pointer',
          borderBottom: i < a.length - 1 ? '1px solid var(--apm-line)' : 'none',
          display: 'grid', gridTemplateColumns: '1.2fr 1fr 100px 100px 80px', alignItems: 'center', gap: 12,
        }}
          onMouseEnter={e => e.currentTarget.style.background = 'var(--apm-bg-sunken)'}
          onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
          <div>
            <div style={{ fontSize: 14, fontWeight: 600 }}>{c.name}</div>
            <div style={{ fontSize: 11.5, color: 'var(--apm-muted)', marginTop: 2 }}>{c.summary}</div>
          </div>
          <div style={{ display: 'flex', gap: 4, flexWrap: 'wrap' }}>
            {c.sensitivity.map(s => <SensitivityTag key={s} id={s} />)}
          </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: 12, color: 'var(--apm-muted)' }}>{c.dependents.length} deps</div>
        </div>
      ))}
    </Card>

    <div style={{ marginTop: 'var(--apm-section-gap)' }}>
      <SectionHeading kicker="Change control" title="Requests touching your components" />
      <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--apm-inner-gap)' }}>
        {APM_CHANGES.filter(c => COMP_BY_ID[c.component].owner === persona.id || c.status === 'pending').slice(0,3).map(c => (
          <Card key={c.id} hoverable onClick={() => goto('components', { id: c.component, change: c.id })}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 16 }}>
              <div style={{ flex: 1 }}>
                <div style={{ display: 'flex', gap: 8, alignItems: 'center', marginBottom: 6 }}>
                  <Badge tone={c.breaking ? 'risk' : 'info'} size="sm">{c.breaking ? 'Breaking' : 'Compatible'}</Badge>
                  <span style={{ fontSize: 12, color: 'var(--apm-muted)' }}>{COMP_BY_ID[c.component].name}</span>
                </div>
                <div style={{ fontSize: 14.5, fontWeight: 600 }}>{c.title}</div>
                <div style={{ fontSize: 12.5, color: 'var(--apm-muted)', marginTop: 4, lineHeight: 1.5 }}>{c.description}</div>
                <div style={{ fontSize: 11.5, color: 'var(--apm-muted-2)', marginTop: 8 }}>
                  {c.impact.length} dependent projects · submitted by {PERSON_BY_ID[c.submitter].name} · {c.submitted}
                </div>
              </div>
              <div style={{ display: 'flex', gap: 8 }}>
                <Button size="sm" variant="outline">Reject</Button>
                <Button size="sm" variant="primary">Approve</Button>
              </div>
            </div>
          </Card>
        ))}
      </div>
    </div>
  </Page>
);

// ── 8. EXECUTIVE home ───────────────────────────────────────────────
const HomeExec = ({ persona, goto }) => (
  <Page max={1100}>
    <PageHeader kicker={`Briefing for ${persona.name}`}
      title="Today's portfolio in one read"
      subtitle="Two minutes. Strategy progress, money, decisions waiting on you, and the one thing that changed since yesterday."
    />

    {/* Briefings */}
    <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--apm-inner-gap)', marginBottom: 32 }}>
      {APM_BRIEFINGS.map(b => {
        const tone = b.kind === 'risk' ? 'risk' : b.kind === 'milestone' ? 'ok' : b.kind === 'decision' ? 'accent' : 'info';
        return (
          <Card key={b.id} accent={b.kind === 'decision'}>
            <div style={{ display: 'flex', gap: 16, alignItems: 'flex-start' }}>
              <Badge tone={tone} dot size="sm">{b.kind}</Badge>
              <div style={{ flex: 1 }}>
                <div style={{ fontFamily: 'var(--apm-font-display)', fontSize: 19, lineHeight: 1.2, letterSpacing: '-0.005em' }}>{b.title}</div>
                <div style={{ fontSize: 13.5, color: 'var(--apm-muted)', marginTop: 6, lineHeight: 1.55, textWrap: 'pretty' }}>{b.body}</div>
              </div>
              <div style={{ fontSize: 11.5, color: 'var(--apm-muted-2)', whiteSpace: 'nowrap' }}>{b.when}</div>
            </div>
          </Card>
        );
      })}
    </div>

    {/* Portfolio strip */}
    <SectionHeading kicker="Portfolio" title="Initiative-level view" action={<Button size="sm" variant="ghost" onClick={() => goto('portfolio')}>Full view <Icon name="arrow_right" size={12} /></Button>} />
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 12 }}>
      {APM_INITIATIVES.map(ini => {
        const tone = ini.health >= 75 ? 'var(--apm-ok)' : ini.health >= 60 ? 'var(--apm-warn)' : 'var(--apm-risk)';
        return (
          <Card key={ini.id} hoverable onClick={() => goto('initiative', { id: ini.id })}>
            <div style={{ fontSize: 11, color: 'var(--apm-muted)', textTransform: 'uppercase', letterSpacing: '0.12em' }}>{ini.code}</div>
            <div style={{ fontFamily: 'var(--apm-font-display)', fontSize: 16, marginTop: 6, lineHeight: 1.2 }}>{ini.name}</div>
            <div style={{ display: 'flex', alignItems: 'baseline', gap: 6, marginTop: 14 }}>
              <div style={{ fontFamily: 'var(--apm-font-display)', fontSize: 28, color: tone }}>{ini.health}</div>
              <div style={{ fontSize: 11, color: 'var(--apm-muted)' }}>health</div>
            </div>
            <div style={{ marginTop: 8 }}><HealthBar value={ini.health} /></div>
            <div style={{ display: 'flex', gap: 12, marginTop: 12, fontSize: 11.5, color: 'var(--apm-muted)' }}>
              <span>{fmtMoney(ini.spent)} / {fmtMoney(ini.budget)}</span>
              <span>· {ini.target}</span>
            </div>
          </Card>
        );
      })}
    </div>
  </Page>
);

// ── 9. TEAM MEMBER home ─────────────────────────────────────────────
const HomeMember = ({ persona, goto }) => (
  <Page>
    <PageHeader kicker={`${persona.name.split(' ')[0]} · ${persona.title}`}
      title="Your work, plus the things you can move forward"
      subtitle="Tickets assigned to you, ideas you logged, and projects you're contributing to."
      action={<Button variant="accent" icon={<Icon name="ideas" size={14} />} onClick={() => goto('ideas', { compose: true })}>Submit an idea</Button>}
    />

    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 16, marginBottom: 'var(--apm-section-gap)' }}>
      <Card><Stat label="Tickets assigned" value={ticketsByAssignee(persona.id).length || 1} /></Card>
      <Card><Stat label="Ideas you logged" value="2" sub="1 promoted" tone="ok" /></Card>
      <Card><Stat label="Projects contributing to" value="3" /></Card>
    </div>

    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 24 }}>
      <div>
        <SectionHeading kicker="Your work" title="Tickets" />
        <Card pad={false}>
          {APM_TICKETS.filter((_,i) => i < 4).map((t, i, a) => (
            <div key={t.id} onClick={() => goto('tickets', { id: t.id })} style={{
              padding: 'var(--apm-row-pad) var(--apm-card-pad)', cursor: 'pointer',
              borderBottom: i < a.length - 1 ? '1px solid var(--apm-line)' : 'none',
              display: 'flex', alignItems: 'center', gap: 12,
            }}
              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 style={{ flex: 1 }}>
                <div style={{ fontSize: 13.5, fontWeight: 500 }}>{t.title}</div>
                <div style={{ fontSize: 11.5, color: 'var(--apm-muted)', marginTop: 2 }}>{PROJ_BY_ID[t.project].name} · {t.age}</div>
              </div>
            </div>
          ))}
        </Card>
      </div>

      <div>
        <SectionHeading kicker="Your ideas" title="Submitted by you" />
        <Card>
          {APM_IDEAS.filter(i => i.submitter === persona.id || persona.id === 'p_tomas').slice(0,3).map((idea, i, a) => (
            <div key={idea.id} style={{ padding: 'var(--apm-row-pad) 0', borderBottom: i < a.length-1 ? '1px solid var(--apm-line)' : 'none' }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 12 }}>
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: 13.5, fontWeight: 500 }}>{idea.title}</div>
                  <div style={{ fontSize: 11.5, color: 'var(--apm-muted)', marginTop: 2 }}>
                    {idea.upvotes} upvotes · {idea.submitted}
                  </div>
                </div>
                <Badge tone={idea.status === 'promoted' ? 'ok' : idea.status === 'merged' ? 'info' : 'neutral'} size="sm">{idea.status}</Badge>
              </div>
            </div>
          ))}
        </Card>
      </div>
    </div>
  </Page>
);

// ── Router ───────────────────────────────────────────────────────────
const Home = ({ persona, route, goto }) => {
  const v = route.params?.variant || 'a';
  switch (persona.role) {
    case 'admin':    return <HomeAdmin    persona={persona} goto={goto} />;
    case 'owner':    return <HomeOwner    persona={persona} goto={goto} variant={v} />;
    case 'approver': return <HomeApprover persona={persona} goto={goto} />;
    case 'manager':  return <HomeManager  persona={persona} goto={goto} />;
    case 'raqa':     return <HomeRaqa     persona={persona} goto={goto} />;
    case 'helpdesk': return <HomeHelpdesk persona={persona} goto={goto} />;
    case 'devops':   return <HomeDevops   persona={persona} goto={goto} />;
    case 'exec':     return <HomeExec     persona={persona} goto={goto} />;
    case 'member':   return <HomeMember   persona={persona} goto={goto} />;
    default:         return <HomeMember   persona={persona} goto={goto} />;
  }
};

// Alias so root file can call <HomePage>
const HomePage = ({ persona, variant, goto, openChat, openCompose }) => (
  <Home persona={persona} route={{ params: { variant } }} goto={goto} openChat={openChat} openCompose={openCompose} />
);
Object.assign(window, { Home, HomePage });
