<!-- source: openspec/current/entity-densities.md -->

---
title: Entity densities — the five-density grammar
status: stable
owner: pavel
audience: [pavel, architect, executor]
tldr: Every entity renders in exactly five densities — mention, row, card, hovercard, detail. The variant decides geometry, the entity decides content. Ratifies D-ATLAS-1.
canonical_at: openspec/current/entity-densities.md
related:
  - openspec/current/entities.md
  - openspec/brands/studio/design-components.md
  - openspec/_atlas/current/atlas.html
ratifies: D-ATLAS-1
---

# Entity densities — the five-density grammar

> Every entity in the studio renders in exactly **five** densities. The variant
> decides the geometry, not the content. The content is the entity; the variant
> is the camera.

## The five variants

| Variant | Where it lives | Camera distance |
|---|---|---|
| `mention` | Inline in prose (chat, spec body, inquiry source). Baseline-aligned. | Closest. |
| `row` | List item in a table, feed, or sidebar. | Medium. |
| `card` | Gallery tile. Browse view. The "bookshelf shot". | Medium-wide. |
| `hovercard` | Floating preview shown on `mention` hover. 320px. | Mid-air. |
| `detail` | Entity-page header, full-width. The "front of the file". | Widest. |

## Slot anatomy

Each variant carries a different set of slots at different sizes. The full table
lives in the Atlas (`density grammar · slot anatomy` artboard); the canonical
authority is below.

| Slot | mention | row | card | hovercard | detail |
|---|---|---|---|---|---|
| `icon` | 12px | 18px | 22px | 16px | 32px |
| `name` | 13px | 15px Lora 500 | 19px Lora 500 | 15px Lora 500 | 32px Lora 500 |
| `identifier` | ✓ | ✓ | ✓ | ✓ | ✓ |
| `meta` (mono line) | — | ✓ | ✓ | ✓ | ✓ |
| `status` (pill) | ✓ | ✓ | ✓ | ✓ | ✓ |
| `lede` (prose) | — | — | ✓ | ✓ | — |
| `index` (mono index) | — | — | ✓ | — | — |
| `thumbnail` | — | — | optional | — | — |
| `bindings` (`label · value` pairs) | — | — | — | — | ✓ |
| `breadcrumb` | — | — | — | — | ✓ |
| `primary CTA` | — | — | ✓ | ✓ | ✓ |
| `actions menu` | — | ✓ | ✓ | — | ✓ |

## Naming

- `mention` was previously `inline`. The new name reads as a noun (an entity
  mention), not a layout direction. The rename is global; no `inline` callers
  remain after Wave 2 of `ratify-entities-atlas`.
- `hovercard` is new. It is the missing primitive that lets a `mention`'s
  preview be consistent across surfaces — previously hand-rolled in three places
  inconsistently.

## Component contract

The canonical implementation is `<EntityCard>` in
`packages/ui/src/components/entity-card.tsx`. The component is a variant
dispatcher; the five render functions share a common props shape (icon, name,
identifier, meta, status, actions) plus per-variant additions (`lede`,
`thumbnail`, `featured` on `card`; `cta` on `hovercard`; `breadcrumb`,
`bindings` on `detail`).

## Hovercard, specifically

The `hovercard` variant is intended for use inside Radix `<HoverCard.Root>`:

```tsx
<HoverCard.Root openDelay={400}>
  <HoverCard.Trigger asChild>
    <EntityCard variant="mention" {...mentionProps} />
  </HoverCard.Trigger>
  <HoverCard.Portal>
    <HoverCard.Content side="top" sideOffset={6}>
      <EntityCard variant="hovercard" {...hovercardProps} />
    </HoverCard.Content>
  </HoverCard.Portal>
</HoverCard.Root>
```

The corner-bracket pair (top-left + bottom-right) is the visual marker that
distinguishes hovercard from a placed `card` — it signals "this is a floating
preview, dismissable, not the real seat of the entity."

## Off-grammar variants are forbidden

If a surface needs a representation that doesn't fit one of the five, the
correct response is **not** to add a sixth variant. The two correct responses:

1. **Map to the nearest variant.** A sidebar pull-out is `detail` constrained to
   a narrower column. A search-result row is `row` with the `actions menu`
   suppressed. A keyboard-palette match is `row` at a smaller scale.
2. **Promote the slot.** If a recurring need to add a slot emerges (e.g. a
   "thumbnail" on `row`), promote the slot in a new Atlas version, not by
   adding a variant.

Adding a sixth variant requires a new Atlas version + a `ratify-entities-atlas-vN`
change. Do not do it ad-hoc.
