Gallery

The plate grid between file-selekt (upload) and lightbox (view)

The plate grid — figure, plate, zoom badge, caption

One <figure> per image inside .gallery. The plate anchor is a BOX (.gallery-plate — never a bare inline anchor), the zoom badge is inert to the pointer, the accessible name rides aria-label (never title — the tooltip layer would put a tooltip on a moving target), and the group value is per entity.

Grouping is per ENTITY — never per page

This second gallery groups as lightbox="report-2" — its plates never arrow into the grid above. A page-wide group is the obvious first implementation and it is wrong the moment a page shows two galleries.

The single-image rule — :only-child

A gallery holding ONE image is the page's illustration, not a thumbnail in a grid of one — the lone figure widens and its thumb grows to 16rem, by CSS alone. Same markup, no extra class.

From the files jsonb — g.lightbox.gallery(files, { group })

Client-rendered pages (a lister row's expansion, an API payload) skip the hand-written markup: g.lightbox.gallery(files, { group }) turns the stored files gallery jsonb (file-selekt's shape — path, variants, caption) into exactly the markup above. Inject it, then g.lightbox.refresh() — lister loads re-scan by themselves. Stored order = display order; bare paths prefix g.settings.filesUrl, absolute CDN paths pass through.