# paper.json Schema

The microsite renderer (`src/components/ProposalSite.tsx`) consumes a single JSON file. Branding is identical across all deal types — `meta.deal_type` only controls **section list, charts, terms schema, and intake questions**.

## Top level

```ts
{
  meta: Meta;
  headline_stats?: HeadlineStat[];   // 0–6 stat strip on cover
  sections?: Section[];              // long-form content
  charts?: ChartRef[];               // mounted into their named section
  terms?: Record<string, string>;    // keyed to the deal-type terms_schema
  disclaimer?: string;               // overrides the bundle default
}
```

## meta

```ts
{
  deal_type:
    | "fund"
    | "direct_equity_raise"
    | "share_sale"
    | "private_credit"
    | "real_estate"
    | "project_finance"
    | "m_and_a"
    | "research_note"
    | "teaser";
  title: string;
  subtitle?: string;
  eyebrow?: string;       // e.g. "Confidential IM · June 2026"
  issuer?: string;
  date?: string;          // ISO
  authors?: string[];
}
```

## headline_stats

```ts
{ value: string; label: string; sub?: string }[]
```

Displayed as a 4-up strip on the cover. Use up to 6.

## sections

```ts
{
  id: string;       // must match a section id in the deal-type bundle
  title?: string;
  eyebrow?: string;
  body?: string;    // markdown-lite: **bold**, *italic*, blank line = paragraph; raw <table> blocks allowed
  html?: string;    // escape hatch: full HTML, used instead of body if present
}[]
```

Order is **fixed by the deal-type bundle**, not by JSON order. Sections you omit are simply skipped.

## charts

```ts
{
  id: string;          // must be registered in src/components/charts/registry.ts
  section_id: string;  // section to mount under
}[]
```

If the id isn't registered yet, the slot renders a visible placeholder so you know to request the chart.

## terms

Object whose keys match the `terms_schema` of the deal type. Example for `share_sale`:

```json
{
  "shares_offered": "18% on a fully diluted basis",
  "percent_company": "18.0%",
  "indicative_price": "€25m – €28m",
  "valuation_basis": "14× LTM EBITDA",
  "seller": "Founders A & B (partial exit)",
  "lockup": "12 months on residual stake",
  "drag_tag": "Drag at ≥75%, tag at ≥10%",
  "rofr": "Waived by board resolution dated 2026-05-12",
  "process_type": "Limited auction (8 invited)",
  "exclusivity": "21 days post-shortlist",
  "timeline": "First-round bids 2026-07-10; close target 2026-09-30"
}
```

Each deal-type bundle declares its own `terms_schema` — see `src/templates/deal-types/<type>.ts`.

## disclaimer

Optional. If omitted, the bundle's `default_disclaimer` is rendered.

## Authoring rules

- Section `id`s are stable. Don't invent new ones — extend the bundle if you genuinely need a new section.
- Chart `id`s are stable. Adding a new chart means a PR to `registry.ts` *and* the rendering component.
- Numbers in body text should be tabular-numeric where possible; the `num` class is available.
- `body` accepts raw `<table>...</table>` for hand-built data tables; the `.paper-table` styles apply.
