diff --git a/frontend/src/lib/markdown.ts b/frontend/src/lib/markdown.ts
index 2258e3e..75111bd 100644
--- a/frontend/src/lib/markdown.ts
+++ b/frontend/src/lib/markdown.ts
@@ -119,7 +119,16 @@ function groupFigures(html: string): string {
const m = fig.match(/
]*\swidth="(\d+)"[^>]*\sheight="(\d+)"/);
const ratio = m ? Number(m[1]) / Number(m[2]) : 1;
const safe = Number.isFinite(ratio) && ratio > 0 ? ratio : 1;
- return fig.replace('', ``);
+ const r = safe.toFixed(3);
+ // flex-basis tracks target row height (var --row-h) × aspect ratio,
+ // so the browser fits as many figures per row as it can while keeping
+ // each at roughly the target height; the rest wrap. max-width caps
+ // any leftover row so a lone last image doesn't balloon.
+ const style = [
+ `flex:${r} ${r} calc(${r} * var(--row-h, 16rem))`,
+ `max-width:calc(${r} * var(--row-max, 30rem))`,
+ ].join(';');
+ return fig.replace('', ``);
});
return `${items.join('')}
`;
},
diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css
index e9c1d9a..651e424 100644
--- a/frontend/src/styles/global.css
+++ b/frontend/src/styles/global.css
@@ -548,6 +548,11 @@ code, pre, kbd, samp {
* row; each figure gets `flex: ` inline so widths divide
* proportionally and heights line up. Wraps to a column on narrow screens. */
.prose .figure-row {
+ /* Target row height. Each figure's flex-basis is ratio × this value, so
+ * rows pack as many figures as fit at roughly --row-h tall, then wrap.
+ * --row-max caps how tall a sparsely-filled final row can grow. */
+ --row-h: 16rem;
+ --row-max: 30rem;
display: flex;
flex-wrap: wrap;
gap: 0.9rem;
@@ -557,6 +562,12 @@ code, pre, kbd, samp {
width: calc(100% + min(8vw, 4rem));
margin-left: calc(min(8vw, 4rem) / -2);
}
+@media (min-width: 1024px) {
+ .prose .figure-row {
+ --row-h: 18rem;
+ --row-max: 34rem;
+ }
+}
.prose .figure-row figure {
margin: 0;
min-width: 0; /* allow flex children to shrink below content width */