// Open Labbook — Contributions page.
// Visualizes who contributed what, at which research stage.
// Individuals, AI agents, and institutions are first-class actors.

function LabbookContribDapp() {
  const sidebar = (
    <>
      <div style={{ padding: '0 16px 12px', borderBottom: `1px solid ${UB.rule2}`, marginBottom: 14 }}>
        <div style={{ fontFamily: UB.mono, fontSize: 9, letterSpacing: '0.18em', color: UB.ink3, marginBottom: 6 }}>NOTEBOOK</div>
        <div style={{ fontWeight: 600, fontSize: 13, marginBottom: 4 }}>NB-219 / Glia–Neuron Pruning</div>
        <div style={{ fontFamily: UB.mono, fontSize: 10, color: UB.ink3 }}>main · 142 commits</div>
        <div style={{ display: 'flex', gap: 4, marginTop: 8 }}>
          <Tag tone="ok">PREPRINT</Tag><Tag>OPEN</Tag>
        </div>
      </div>
      <NavGroup label="Stages">
        <NavItem icon={Icon.flask} label="Hypothesis" />
        <NavItem icon={Icon.book} label="Protocols" badge="8" />
        <NavItem icon={Icon.cpu} label="Experiments" badge="14" />
        <NavItem icon={Icon.storage} label="Data & Results" />
        <NavItem icon={Icon.doc} label="Draft paper" />
        <NavItem icon={Icon.branch} label="Issues" badge="3" />
      </NavGroup>
      <NavGroup label="Network">
        <NavItem icon={Icon.user} label="Contributions" badge="32" active />
        <NavItem icon={Icon.cube} label="Forks" badge="4" />
        <NavItem icon={Icon.bank} label="Funding" />
      </NavGroup>
      <NavGroup label="Other notebooks">
        <NavItem label="NB-204 Reproduction · Lin" />
        <NavItem label="NB-231 Dendritic plasticity" />
        <NavItem label="NB-187 2P Imaging dataset" />
      </NavGroup>
    </>
  );

  // Six research stages with stacked share by actor TYPE
  // shares = [HUMAN, AI, INSTITUTION] — sum to 1
  const stages = [
    { k: 'IDEA',    label: 'Idea & framing',         total: 18,  shares: [0.66, 0.22, 0.12], commits: 8,  bounties: 0,  color: 'oklch(0.74 0.10 60)' },
    { k: 'HYPO',    label: 'Hypothesis',             total: 24,  shares: [0.50, 0.34, 0.16], commits: 11, bounties: 1,  color: 'oklch(0.62 0.13 70)' },
    { k: 'PROTO',   label: 'Protocol design',        total: 36,  shares: [0.42, 0.18, 0.40], commits: 18, bounties: 2,  color: UB.accent },
    { k: 'EXP',     label: 'Experimentation',        total: 84,  shares: [0.36, 0.12, 0.52], commits: 42, bounties: 4,  color: 'oklch(0.55 0.10 240)' },
    { k: 'ANALYZE', label: 'Analysis',               total: 56,  shares: [0.32, 0.54, 0.14], commits: 31, bounties: 3,  color: 'oklch(0.50 0.13 280)' },
    { k: 'WRITE',   label: 'Writing & review',       total: 32,  shares: [0.58, 0.30, 0.12], commits: 22, bounties: 2,  color: 'oklch(0.40 0.06 260)' },
  ];
  const totalContrib = stages.reduce((a, s) => a + s.total, 0);

  // Top contributors — mix of HUMAN / AI / INSTITUTION
  const contributors = [
    { name: 'malcolm.h',         type: 'HUMAN',       role: 'Lead PI · Conceptualization · Writing', share: 28, stages: 'idea·hypo·write', tis: 85.8 },
    { name: 'GLIA-AGENT v3',     type: 'AI',          role: 'Lit review · figure regen · pipeline runs', share: 16, stages: 'hypo·analyze', tis: '—', sub: 'on-chain agent · audited' },
    { name: 'a.mwangi',          type: 'HUMAN',       role: 'Investigation · Data curation', share: 14, stages: 'exp·proto', tis: 62.4 },
    { name: 'UCSF Weill Inst.',  type: 'INSTITUTION', role: 'Wet lab · IACUC · 2P rig time', share: 12, stages: 'proto·exp', tis: '—', sub: 'verified org · institutional SBT' },
    { name: 'r.tanaka',          type: 'HUMAN',       role: 'Methodology · Protocols', share: 8, stages: 'proto', tis: 71.2 },
    { name: 'CzBiohub CRO',      type: 'INSTITUTION', role: 'Confocal IHC · 96 slices', share: 6, stages: 'exp', tis: '—', sub: 'CRO · paid 1,800 UBR' },
    { name: 'k.iyer',            type: 'HUMAN',       role: 'Formal analysis · Software', share: 6, stages: 'analyze', tis: 58.0 },
    { name: 'STATS-AGENT v2',    type: 'AI',          role: 'Hierarchical model fit · MCMC', share: 4, stages: 'analyze', tis: '—', sub: 'agent · slashable bond' },
    { name: 'NIH BRAIN Init.',   type: 'INSTITUTION', role: 'Funding · grant compliance', share: 3, stages: 'idea·write', tis: '—', sub: 'funder · 9,000 UBR' },
    { name: 'l.park (anon)',     type: 'HUMAN',       role: 'Peer review (blind)', share: 2, stages: 'write', tis: 'ZK', sub: 'identity proof · ZK-verified' },
    { name: 'j.osei',            type: 'HUMAN',       role: 'Validation · Visualization', share: 1, stages: 'write·analyze', tis: 44.6 },
  ];

  // 60-day commit timeline by actor type
  const timeline = Array.from({ length: 60 }, (_, i) => {
    // varying mix per day
    const human = Math.round(2 + 4 * Math.abs(Math.sin(i / 4)) + (i % 7 < 5 ? 1 : 0));
    const ai = Math.round(1 + 3 * Math.abs(Math.cos(i / 3)) * (i > 18 ? 1 : 0.4));
    const inst = Math.round(0.8 + 2 * Math.abs(Math.sin(i / 9 + 0.5)) * (i > 8 ? 1 : 0.2));
    return { d: i, h: human, a: ai, i: inst };
  });
  const tlMax = Math.max(...timeline.map(t => t.h + t.a + t.i));

  // CRediT-style activity matrix: 14 CRediT roles × 3 actor types
  const credit = [
    'Conceptualization', 'Methodology', 'Software', 'Validation',
    'Formal analysis', 'Investigation', 'Resources', 'Data curation',
    'Writing — orig.', 'Writing — review', 'Visualization', 'Supervision',
    'Project admin', 'Funding acquisition',
  ];
  // density 0–3 per cell; same shape every render
  const density = [
    [3, 2, 1], [2, 1, 2], [1, 3, 0], [2, 2, 1],
    [1, 3, 0], [2, 1, 3], [1, 0, 3], [2, 2, 1],
    [3, 1, 0], [2, 1, 1], [1, 3, 0], [3, 0, 1],
    [2, 0, 2], [1, 0, 3],
  ];

  // Stage stacked bar (HUMAN | AI | INSTITUTION)
  const TYPE_COLORS = {
    HUMAN: UB.ink,
    AI: UB.accent,
    INSTITUTION: 'oklch(0.55 0.10 240)',
  };

  const Pill = ({ type }) => (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 4,
      fontFamily: UB.mono, fontSize: 9, letterSpacing: '0.08em',
      padding: '2px 6px',
      background: type === 'HUMAN' ? UB.paperDeep : type === 'AI' ? UB.accentDim : 'oklch(0.94 0.04 240)',
      color: type === 'HUMAN' ? UB.ink : type === 'AI' ? UB.ink : 'oklch(0.30 0.10 240)',
    }}>
      <span style={{ width: 6, height: 6, background: TYPE_COLORS[type] }} />
      {type}
    </span>
  );

  return (
    <Dapp>
      <ChromeBar dapp="LABBOOK" code="OLD / NB-219 · CONTRIBUTIONS" />
      <Layout rail={sidebar}>
        <PageHead
          eyebrow="Open Labbook · NB-219 · branch: main · contributions"
          title="Who built this notebook"
          sub="Every actor — human, AI, or institution — is a first-class contributor. Their commits, bounty claims, and reviews accrue weight stage-by-stage and settle into citation credit and TIS at publication."
          actions={<>
            <Btn small icon={Icon.search}>Filter actor</Btn>
            <Btn small icon={Icon.doc}>Export CRediT.json</Btn>
            <Btn small primary icon={Icon.shield}>Anchor split on-chain</Btn>
          </>}
        />

        {/* TOP STRIP — totals by actor type */}
        <div style={{ background: UB.paperDeep, borderTop: `1px solid ${UB.rule2}`, borderBottom: `1px solid ${UB.rule2}`, padding: '14px 24px', display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', gap: 18 }}>
          {[
            ['CONTRIBUTIONS · TOTAL', String(totalContrib), '142 commits · 12 bounty claims', UB.ink, null],
            ['HUMANS', '7', '4 lab + 2 ext + 1 anon ZK', UB.ink, 'HUMAN'],
            ['AI AGENTS', '3', '2 audited · 1 pending', UB.accent, 'AI'],
            ['INSTITUTIONS', '4', '1 funder · 1 univ · 2 CRO', 'oklch(0.45 0.10 240)', 'INSTITUTION'],
          ].map((s, i) => (
            <div key={i}>
              <div style={{ fontFamily: UB.mono, fontSize: 9, letterSpacing: '0.18em', color: UB.ink3, marginBottom: 4, display: 'flex', alignItems: 'center', gap: 6 }}>
                {s[4] && <span style={{ width: 8, height: 8, background: TYPE_COLORS[s[4]] }} />}
                {s[0]}
              </div>
              <div style={{ fontFamily: UB.serif, fontSize: 36, lineHeight: 0.95, letterSpacing: '-0.02em', color: s[3] }}>{s[1]}</div>
              <div style={{ fontFamily: UB.mono, fontSize: 10, color: UB.ink3, marginTop: 3 }}>{s[2]}</div>
            </div>
          ))}
        </div>

        <div style={{ flex: 1, padding: 24, overflow: 'auto', display: 'grid', gridTemplateColumns: '1.6fr 1fr', gap: 16 }}>

          {/* LEFT */}
          <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>

            {/* STAGE BREAKDOWN */}
            <Card title="Contributions by research stage" code={`${stages.length} STAGES · ${totalContrib} TOTAL`}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 14, fontFamily: UB.mono, fontSize: 10, color: UB.ink3, letterSpacing: '0.1em', marginBottom: 14 }}>
                <span style={{ display: 'flex', alignItems: 'center', gap: 5 }}><span style={{ width: 10, height: 10, background: TYPE_COLORS.HUMAN }} />HUMAN</span>
                <span style={{ display: 'flex', alignItems: 'center', gap: 5 }}><span style={{ width: 10, height: 10, background: TYPE_COLORS.AI }} />AI</span>
                <span style={{ display: 'flex', alignItems: 'center', gap: 5 }}><span style={{ width: 10, height: 10, background: TYPE_COLORS.INSTITUTION }} />INSTITUTION</span>
                <span style={{ flex: 1 }} />
                <span>SHARE OF STAGE WORK</span>
              </div>
              {stages.map((s, i) => {
                const w = (s.total / Math.max(...stages.map(x => x.total))) * 100;
                return (
                  <div key={s.k} style={{ display: 'grid', gridTemplateColumns: '64px 1fr 60px 60px', gap: 12, alignItems: 'center', padding: '12px 0', borderBottom: i < stages.length - 1 ? `1px solid ${UB.rule3}` : 'none' }}>
                    <div>
                      <div style={{ fontFamily: UB.mono, fontSize: 9, color: UB.ink3, letterSpacing: '0.1em' }}>{s.k}</div>
                      <div style={{ fontFamily: UB.mono, fontSize: 16, color: UB.ink, marginTop: 2 }}>{s.total}</div>
                    </div>
                    <div style={{ minWidth: 0 }}>
                      <div style={{ fontSize: 12, fontWeight: 500, marginBottom: 6 }}>{s.label}</div>
                      {/* Stacked bar */}
                      <div style={{ height: 14, width: `${w}%`, display: 'flex', minWidth: 80 }}>
                        <div style={{ width: `${s.shares[0] * 100}%`, background: TYPE_COLORS.HUMAN, position: 'relative' }} title={`Human ${(s.shares[0] * 100).toFixed(0)}%`}>
                          <span style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: UB.mono, fontSize: 9, color: UB.paper }}>{s.shares[0] >= 0.18 ? `${Math.round(s.shares[0] * 100)}%` : ''}</span>
                        </div>
                        <div style={{ width: `${s.shares[1] * 100}%`, background: TYPE_COLORS.AI, position: 'relative' }} title={`AI ${(s.shares[1] * 100).toFixed(0)}%`}>
                          <span style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: UB.mono, fontSize: 9, color: UB.ink }}>{s.shares[1] >= 0.18 ? `${Math.round(s.shares[1] * 100)}%` : ''}</span>
                        </div>
                        <div style={{ width: `${s.shares[2] * 100}%`, background: TYPE_COLORS.INSTITUTION, position: 'relative' }} title={`Institution ${(s.shares[2] * 100).toFixed(0)}%`}>
                          <span style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: UB.mono, fontSize: 9, color: UB.paper }}>{s.shares[2] >= 0.18 ? `${Math.round(s.shares[2] * 100)}%` : ''}</span>
                        </div>
                      </div>
                    </div>
                    <div style={{ fontFamily: UB.mono, fontSize: 10, color: UB.ink3, textAlign: 'right' }}>
                      <div>{s.commits} commits</div>
                      <div>{s.bounties} bounties</div>
                    </div>
                    <div style={{ fontFamily: UB.mono, fontSize: 10, color: UB.accent, textAlign: 'right' }}>
                      view ›
                    </div>
                  </div>
                );
              })}
            </Card>

            {/* COMMIT TIMELINE — stacked area by actor type */}
            <Card title="60-day commit cadence" code="STACKED · BY ACTOR TYPE">
              <div style={{ display: 'flex', alignItems: 'flex-end', gap: 1, height: 90, paddingTop: 4, borderBottom: `1px solid ${UB.rule3}` }}>
                {timeline.map((t, i) => {
                  const total = t.h + t.a + t.i;
                  const totalH = (total / tlMax) * 86;
                  return (
                    <div key={i} style={{ flex: 1, height: totalH, display: 'flex', flexDirection: 'column', justifyContent: 'flex-end', minWidth: 0 }}>
                      <div style={{ height: `${(t.i / total) * 100}%`, background: TYPE_COLORS.INSTITUTION }} />
                      <div style={{ height: `${(t.a / total) * 100}%`, background: TYPE_COLORS.AI }} />
                      <div style={{ height: `${(t.h / total) * 100}%`, background: TYPE_COLORS.HUMAN }} />
                    </div>
                  );
                })}
              </div>
              <div style={{ display: 'flex', justifyContent: 'space-between', fontFamily: UB.mono, fontSize: 9, color: UB.ink3, letterSpacing: '0.1em', marginTop: 6 }}>
                <span>− 60 D</span>
                <span>HYPOTHESIS LOCK</span>
                <span>EXP COHORT 4</span>
                <span>PREPRINT</span>
                <span>NOW</span>
              </div>
            </Card>

            {/* CONTRIBUTORS LEDGER */}
            <Card title="Contributor ledger" code={`${contributors.length} ACTORS · CRediT + REWARDS`} pad={false}>
              <Row head cells={[
                { v: 'Actor' },
                { v: 'Type', w: '90px' },
                { v: 'Role', w: '220px' },
                { v: 'Stages', w: '130px' },
                { v: 'Share', w: '60px' },
                { v: 'TIS', w: '60px' },
              ]} />
              {contributors.map((c, i) => (
                <div key={c.name} style={{ display: 'flex', alignItems: 'center', padding: '10px 14px', borderBottom: i < contributors.length - 1 ? `1px solid ${UB.rule3}` : 'none' }}>
                  <div style={{ flex: 1, minWidth: 0, display: 'flex', alignItems: 'center', gap: 10 }}>
                    <div style={{
                      width: 26, height: 26, flexShrink: 0,
                      background: c.type === 'HUMAN' ? UB.ink : c.type === 'AI' ? UB.accent : 'oklch(0.55 0.10 240)',
                      color: c.type === 'AI' ? UB.ink : UB.paper,
                      fontFamily: UB.mono, fontSize: 9, fontWeight: 600,
                      display: 'flex', alignItems: 'center', justifyContent: 'center',
                      borderRadius: c.type === 'AI' ? '50%' : c.type === 'INSTITUTION' ? '0' : '0',
                      border: c.type === 'INSTITUTION' ? `2px solid oklch(0.55 0.10 240)` : 'none',
                    }}>
                      {c.type === 'AI' ? '◇' : c.type === 'INSTITUTION' ? '◫' : c.name[0].toUpperCase()}
                    </div>
                    <div style={{ minWidth: 0 }}>
                      <div style={{ fontFamily: UB.mono, fontSize: 11.5, color: UB.ink, fontWeight: 500 }}>{c.name}</div>
                      {c.sub && <div style={{ fontFamily: UB.mono, fontSize: 9, color: UB.ink3 }}>{c.sub}</div>}
                    </div>
                  </div>
                  <div style={{ width: 90 }}><Pill type={c.type} /></div>
                  <div style={{ width: 220, fontSize: 11, color: UB.ink2 }}>{c.role}</div>
                  <div style={{ width: 130, fontFamily: UB.mono, fontSize: 10, color: UB.ink3, letterSpacing: '0.04em' }}>{c.stages}</div>
                  <div style={{ width: 60, position: 'relative' }}>
                    <div style={{ height: 4, background: UB.paperDeep, marginBottom: 3 }}>
                      <div style={{ width: `${(c.share / 28) * 100}%`, height: '100%', background: TYPE_COLORS[c.type] }} />
                    </div>
                    <div style={{ fontFamily: UB.mono, fontSize: 10, color: UB.ink, textAlign: 'right' }}>{c.share}%</div>
                  </div>
                  <div style={{ width: 60, fontFamily: UB.mono, fontSize: 11, color: UB.ink, textAlign: 'right' }}>{c.tis}</div>
                </div>
              ))}
              <div style={{ padding: '10px 14px', background: UB.paperDeep, fontFamily: UB.mono, fontSize: 10, color: UB.ink3, display: 'flex', justifyContent: 'space-between' }}>
                <span>SUM · 100% · 11 actors · 32 verified contributions</span>
                <span style={{ color: UB.accent }}>+ DISPUTE A SHARE</span>
              </div>
            </Card>

          </div>

          {/* RIGHT */}
          <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>

            {/* DISTRIBUTION DONUT */}
            <Card title="Total credit split" code="HUMAN · AI · INSTITUTION">
              {(() => {
                const totals = [0, 0, 0];
                contributors.forEach(c => {
                  const idx = c.type === 'HUMAN' ? 0 : c.type === 'AI' ? 1 : 2;
                  totals[idx] += c.share;
                });
                const sum = totals.reduce((a, b) => a + b, 0) || 1;
                const pct = totals.map(t => t / sum);
                // SVG donut
                const r = 56, cx = 70, cy = 70, sw = 18;
                const C = 2 * Math.PI * r;
                let off = 0;
                const arcs = pct.map((p, i) => {
                  const len = p * C;
                  const arc = (
                    <circle key={i} cx={cx} cy={cy} r={r} fill="none"
                      stroke={[TYPE_COLORS.HUMAN, TYPE_COLORS.AI, TYPE_COLORS.INSTITUTION][i]}
                      strokeWidth={sw}
                      strokeDasharray={`${len} ${C - len}`}
                      strokeDashoffset={-off}
                      transform={`rotate(-90 ${cx} ${cy})`}
                    />
                  );
                  off += len;
                  return arc;
                });
                return (
                  <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
                    <svg width={140} height={140}>
                      <circle cx={cx} cy={cy} r={r} fill="none" stroke={UB.paperDeep} strokeWidth={sw} />
                      {arcs}
                      <text x={cx} y={cy - 4} textAnchor="middle" fontFamily={UB.serif} fontSize="22" fill={UB.ink}>{contributors.length}</text>
                      <text x={cx} y={cy + 14} textAnchor="middle" fontFamily={UB.mono} fontSize="9" fill={UB.ink3} letterSpacing="0.1em">ACTORS</text>
                    </svg>
                    <div style={{ flex: 1 }}>
                      {[
                        ['HUMAN', totals[0]],
                        ['AI', totals[1]],
                        ['INSTITUTION', totals[2]],
                      ].map((row, i) => (
                        <div key={row[0]} style={{ display: 'grid', gridTemplateColumns: '12px 1fr 40px', gap: 8, alignItems: 'center', padding: '5px 0', borderBottom: i < 2 ? `1px solid ${UB.rule3}` : 'none' }}>
                          <span style={{ width: 10, height: 10, background: TYPE_COLORS[row[0]] }} />
                          <span style={{ fontFamily: UB.mono, fontSize: 10, color: UB.ink2, letterSpacing: '0.06em' }}>{row[0]}</span>
                          <span style={{ fontFamily: UB.mono, fontSize: 11, color: UB.ink, textAlign: 'right' }}>{row[1]}%</span>
                        </div>
                      ))}
                    </div>
                  </div>
                );
              })()}
            </Card>

            {/* CRediT × ACTOR-TYPE MATRIX */}
            <Card title="CRediT × actor matrix" code="14 ROLES · DENSITY">
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 30px 30px 30px', gap: 4, alignItems: 'center', marginBottom: 6 }}>
                <span style={{ fontFamily: UB.mono, fontSize: 9, color: UB.ink3, letterSpacing: '0.1em' }}>ROLE</span>
                {['H', 'A', 'I'].map((l, i) => (
                  <div key={l} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
                    <span style={{ width: 8, height: 8, background: [TYPE_COLORS.HUMAN, TYPE_COLORS.AI, TYPE_COLORS.INSTITUTION][i] }} />
                    <span style={{ fontFamily: UB.mono, fontSize: 9, color: UB.ink3, marginTop: 2 }}>{l}</span>
                  </div>
                ))}
              </div>
              {credit.map((role, i) => (
                <div key={role} style={{ display: 'grid', gridTemplateColumns: '1fr 30px 30px 30px', gap: 4, alignItems: 'center', padding: '4px 0', borderBottom: i < credit.length - 1 ? `1px solid ${UB.rule3}` : 'none' }}>
                  <span style={{ fontSize: 11, color: UB.ink2 }}>{role}</span>
                  {density[i].map((d, j) => (
                    <div key={j} style={{
                      width: 22, height: 14, margin: '0 auto',
                      background: d === 0 ? UB.paperDeep
                        : d === 1 ? `color-mix(in oklch, ${[TYPE_COLORS.HUMAN, TYPE_COLORS.AI, TYPE_COLORS.INSTITUTION][j]} 30%, white)`
                        : d === 2 ? `color-mix(in oklch, ${[TYPE_COLORS.HUMAN, TYPE_COLORS.AI, TYPE_COLORS.INSTITUTION][j]} 60%, white)`
                        : [TYPE_COLORS.HUMAN, TYPE_COLORS.AI, TYPE_COLORS.INSTITUTION][j],
                    }} />
                  ))}
                </div>
              ))}
            </Card>

            {/* AI provenance */}
            <Card title="AI agents · provenance" code="3 AGENTS">
              {[
                { name: 'GLIA-AGENT v3', ops: 'lit-review · figure-regen · pipeline', model: 'Claude Sonnet 4.7 · audited', bond: '120 UBR', color: UB.accent },
                { name: 'STATS-AGENT v2', ops: 'hierarchical model · MCMC fits', model: 'open-source · BUGS-MCMC fork', bond: '64 UBR', color: UB.accent },
                { name: 'SEM-INDEXER',    ops: 'paper embedding · semantic recall', model: 'open · sentence-T5', bond: '— (read-only)', color: UB.ink3 },
              ].map((a, i, arr) => (
                <div key={a.name} style={{ padding: '10px 0', borderBottom: i < arr.length - 1 ? `1px solid ${UB.rule3}` : 'none' }}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 3 }}>
                    <span style={{ fontFamily: UB.mono, fontSize: 11, color: UB.ink, fontWeight: 600 }}>{a.name}</span>
                    <Tag tone="accent">AI</Tag>
                  </div>
                  <div style={{ fontSize: 11, color: UB.ink2, marginBottom: 3 }}>{a.ops}</div>
                  <div style={{ display: 'flex', justifyContent: 'space-between', fontFamily: UB.mono, fontSize: 9, color: UB.ink3 }}>
                    <span>{a.model}</span>
                    <span>bond · {a.bond}</span>
                  </div>
                </div>
              ))}
              <div style={{ marginTop: 8, fontFamily: UB.mono, fontSize: 10, color: UB.ink3, lineHeight: 1.5 }}>
                Every AI commit is signed with the agent's key, replays its prompt + tool-trace from IPFS, and posts a slashing bond if its output is later disproved.
              </div>
            </Card>

            {/* Institutions */}
            <Card title="Institutions · receipts" code="4 ORGS">
              {[
                { name: 'UCSF Weill Inst.',  role: 'Wet lab · IACUC · 2P rig',  share: '12%', via: 'institutional SBT' },
                { name: 'CzBiohub CRO',      role: 'Confocal IHC · 96 slices',  share: '6%',  via: 'paid 1,800 UBR' },
                { name: 'NIH BRAIN Init.',   role: 'Funding',                    share: '3%',  via: '9,000 UBR grant' },
                { name: 'VitaDAO',           role: 'Co-funding',                 share: '1%',  via: '1,200 UBR' },
              ].map((o, i, arr) => (
                <div key={o.name} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '8px 0', borderBottom: i < arr.length - 1 ? `1px solid ${UB.rule3}` : 'none' }}>
                  <div style={{ minWidth: 0 }}>
                    <div style={{ fontSize: 11.5, fontWeight: 500 }}>{o.name}</div>
                    <div style={{ fontFamily: UB.mono, fontSize: 10, color: UB.ink3 }}>{o.role} · {o.via}</div>
                  </div>
                  <span style={{ fontFamily: UB.mono, fontSize: 11, color: UB.ink }}>{o.share}</span>
                </div>
              ))}
            </Card>

            {/* Anchor on chain */}
            <Card title="Settle credit on-chain" code="ON PUBLISH">
              <div style={{ fontSize: 11, color: UB.ink2, lineHeight: 1.55, marginBottom: 10 }}>
                When the preprint is published, this split anchors as a CRediT-attestation NFT. Each actor's wallet receives a credit token that flows TIS, citation rewards, and royalties.
              </div>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
                <Stat label="Snapshot" value="v0.4" sub="updated 12m ago" />
                <Stat label="Disputes" value="1 open" sub="EXP-21 · 2%" />
              </div>
              <div style={{ display: 'flex', gap: 6, marginTop: 12 }}>
                <Btn small style={{ flex: 1 }}>Preview attestation</Btn>
                <Btn small primary icon={Icon.shield} style={{ flex: 1 }}>Anchor v0.4</Btn>
              </div>
            </Card>

          </div>
        </div>
      </Layout>
    </Dapp>
  );
}

window.LabbookContribDapp = LabbookContribDapp;
