diff --git a/messages/en/treasury.json b/messages/en/treasury.json
index 9c38f434..2ef65684 100644
--- a/messages/en/treasury.json
+++ b/messages/en/treasury.json
@@ -87,7 +87,11 @@
"nameWarehouse": "Splits Warehouse",
"nameVault": "Rider vault",
"nameSplit": "Rider split",
- "loadFailed": "Couldn't load more — try again"
+ "loadFailed": "Couldn't load more — try again",
+ "colFrom": "From",
+ "colSource": "Source",
+ "colAmount": "Amount",
+ "colAge": "Age"
},
"allocation": {
"title": "Allocation",
diff --git a/messages/pt-br/treasury.json b/messages/pt-br/treasury.json
index 1948b89c..6acc7024 100644
--- a/messages/pt-br/treasury.json
+++ b/messages/pt-br/treasury.json
@@ -87,7 +87,11 @@
"nameWarehouse": "Splits Warehouse",
"nameVault": "Vault do rider",
"nameSplit": "Split do rider",
- "loadFailed": "Não deu pra carregar mais — tenta de novo"
+ "loadFailed": "Não deu pra carregar mais — tenta de novo",
+ "colFrom": "De",
+ "colSource": "Origem",
+ "colAmount": "Valor",
+ "colAge": "Idade"
},
"allocation": {
"title": "Alocação",
diff --git a/src/app/[locale]/treasury/page.tsx b/src/app/[locale]/treasury/page.tsx
index 207c4bd6..356e728a 100644
--- a/src/app/[locale]/treasury/page.tsx
+++ b/src/app/[locale]/treasury/page.tsx
@@ -130,7 +130,11 @@ export default async function TreasuryPage({ params }: { params: Promise<{ local
are permissionless. Side by side because they are the two halves
of the same question, and reading one without the other overstates
or understates what the DAO has earned. */}
-
+ {/* `items-start`, against the grid default: stretch forced the short
+ sponsorship card to the inflows card's full height, leaving a void
+ below its button. In the design reference it ends where its content
+ ends. */}
+
}>
diff --git a/src/components/treasury/TreasuryInflowsList.tsx b/src/components/treasury/TreasuryInflowsList.tsx
index a7347c49..ac986a26 100644
--- a/src/components/treasury/TreasuryInflowsList.tsx
+++ b/src/components/treasury/TreasuryInflowsList.tsx
@@ -259,48 +259,39 @@ export function TreasuryInflowsList({
) : null}
+ {/* Column headers, like the reference design — the grid below shares
+ this exact template, which is what actually aligns the columns. */}
+
+ {t("colFrom")}
+ {t("colSource")}
+ {t("colAmount")}
+ {t("colAge")}
+
+
+
- {rows.map((flow) => (
- // `flex-wrap` is the mobile layout: at 390px a hex sender + badge +
- // amount + age don't fit one line, and without the wrap the left
- // group's overflow painted OVER the amount. Wrapped, the amount
- // group drops to its own right-aligned line; on desktop nothing
- // wraps and the row is identical to before.
- -
-
- {(() => {
- const entity = knownEntity(flow.from, flow.source, t);
- if (!entity)
- return (
-
- );
- // `min-h-8` matches the avatar AddressDisplay renders on hex
- // rows: without it a named row is text-height, a hex row is
- // avatar-height, and the card's total height becomes a function
- // of which senders happen to be on the page — which is the
- // instability the fillers below exist to prevent.
- return (
-
- {entity.icon ? (
-
- {/* Rider cut-outs reuse the sponsorship card's face
- crop; square logos just cover; the noggles sit
- padded on a dark ground like the design shows. */}
- {entity.icon.size ? (
- /* eslint-disable-next-line @next/next/no-img-element -- 32px local asset; next/image adds nothing at this size */
+ {rows.map((flow) => {
+ const entity = knownEntity(flow.from, flow.source, t);
+ return (
+ // One grid, five fixed columns from `sm` up — a row is not a bag of
+ // floats, and every cell starts where the header says it does.
+ // Below `sm` the same children wrap: sender+badge line, amount
+ // right, age+link trailing.
+ -
+
+ {entity ? (
+ <>
+
+ {entity.icon ? (
+ entity.icon.size ? (
+ /* eslint-disable-next-line @next/next/no-img-element -- 32px local asset; the sponsorship card's verified face crop */
- )}
-
- ) : null}
+ )
+ ) : (
+ /* A named entity with no known mark still gets ITS
+ identicon (seeded by address, same generator the
+ hex rows use) — never a bare text row: one ragged
+ left edge and the whole column stops reading as a
+ column. */
+ /* eslint-disable-next-line @next/next/no-img-element -- tiny remote identicon, same source AddressDisplay uses */
+
}&backgroundColor=b6e3f4,c0aede,d1d4f9`})
+ )}
+
{entity.name}
-
- );
- })()}
- {/* Every row carries its origin, not just auctions. The binary
- "internal = auction" badge could not say where the other three
- quarters of the income came from. */}
-
- {flow.source === "auction" ? : null}
- {t(flow.source)}
+ >
+ ) : (
+
+ )}
+
+
+
+
+ {flow.source === "auction" ? : null}
+ {t(flow.source)}
+
-
-
- +{formatAmount(flow.amount, flow.asset, locale)}{" "}
- {flow.asset}
-
+
+ +{formatAmount(flow.amount, flow.asset, locale)}{" "}
+ {flow.asset}
+
-
- {ageLabel(flow.at, now)}
-
+
+ {ageLabel(flow.at, now)}
+
-
-
-
-
- ))}
+
+
+
+
+ );
+ })}
{/* Height reservation. `border-t-transparent` cancels the divider so the
padding shows up as space, not as empty ruled lines. The `h-8` block