fix(insights): row-fill rule + equal-height trends + hide-on-insufficient-data

Three layout problems landed together because they share the same
root: the `/insights` grids assumed every row would be full, so when a
section dropped a card the layout left a half-row of empty space.

  - Row-fill rule: every grid on `/insights` now picks `xl:grid-cols-2`
    only when 2+ cards actually render. With 1 card the grid collapses
    to a single full-width column. The BP-medication grid, the weight-
    correlation grid, and the medications-per-day grid all carried the
    half-empty-row bug; all three are normalised.

  - Trends row equal heights: each `<TrendsRow>` card is now a flex
    column with `min-h-[300px]` so a multi-line AI annotation under one
    chart doesn't push that card taller than its neighbours. The
    visual rhythm holds even when the prose varies in length.

  - Hide insufficient-data correlation tiles: `<CorrelationRow>` drops
    any hypothesis with `status !== "ok"` instead of painting a
    placeholder. When zero hypotheses qualify, the entire row hides
    itself (no header, no disclaimer). 1 ok card spans 100 % width, 2
    or 3 ok cards split 50/50 on `>=md`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marc-André BombeckandClaude Opus 4.7 committed 2026-05-10 20:49:55 +02:00
1 parent 706aa5fd73
commit 36b9db34c5
4 files changed
+113 -41

No files matched your search

+25 -3
View File
@@ -1060,7 +1060,15 @@ export default function InsightsPage() {
annotations={bpStoryboardAnnotations}
/>
<div className="grid gap-4 xl:grid-cols-2">
{/* v1.4.22 A4 — row-fill rule: 2 cards → 50/50 (xl), 1 card →
100 % width. When the mood section is hidden the BP-medication
card collapses to full-width instead of leaving the right
half empty. */}
<div
className={
showMoodSection ? "grid gap-4 xl:grid-cols-2" : "grid gap-4"
}
>
<Card>
<CardHeader className="pb-2">
<div className="flex items-center justify-between">
@@ -1262,7 +1270,13 @@ export default function InsightsPage() {
compareBaseline={compareBaseline}
/>
<div className="grid gap-4 xl:grid-cols-2">
{/* v1.4.22 A4 — row-fill rule: 2 cards → 50/50 (xl), 1 card →
100 % width. Mirrors the BP-section grid normalisation. */}
<div
className={
showMoodSection ? "grid gap-4 xl:grid-cols-2" : "grid gap-4"
}
>
<Card>
<CardHeader className="pb-2">
<div className="flex items-center justify-between">
@@ -1483,7 +1497,15 @@ export default function InsightsPage() {
</div>
{data.medications.length > 0 ? (
<div className="grid gap-4 sm:grid-cols-2">
/* v1.4.22 A4 — row-fill rule: a single medication card fills
100 % width instead of half the row. */
<div
className={
data.medications.length >= 2
? "grid gap-4 sm:grid-cols-2"
: "grid gap-4"
}
>
{data.medications.map((med) => {
const medicationSummary = medicationSummaryById.get(med.id);
return (