{% comment %} LISTING / card grid: the browsable index, the shape a catalogue or blog list lands on. WHAT YOUR VIEW MUST SUPPLY. A Django template cannot build a list of dicts inline, so this is one of the sections that genuinely needs context. Pass entries = [ {"title": "Chasing without the awkwardness", "summary": "How to write a reminder that gets paid without costing " "you the relationship.", "url": "/blog/chasing-without-the-awkwardness/", "meta": "14 July 2026", "tag": "Guides"}, ... ] `url` is what makes the whole card clickable. `meta` and `tag` are both optional: a card with neither renders as a plain title-and-summary block rather than leaving empty chrome behind. WHY THIS OWNS ITS GRID. brickwork ships _card.html (one card) and no grid component. The grid here is four declarations of clean-room markup on the same auto-fit idiom the package already uses for .bw-stat-grid and .bw-stat-band, so a component would save a consumer four lines and cost them the ability to change the column floor. If a third listing shape ever wants the identical grid, that is the evidence for promoting it; two is not. WHY THE CARD IS A LINK RATHER THAN A "READ MORE". The whole card carries the href, so the click target is the card and there is one link per entry instead of two pointing at the same place. That is fewer tab stops and a much larger target on a phone. It also means the title must say where the link goes, so resist the temptation to make it a teaser. The grid is mobile-first: one column until a card can hold its own width, then as many columns as fit. No breakpoint is hard-coded, so the section behaves correctly inside a narrow container as well as a wide one. States: each card raises its elevation on hover and focus-visible (shadow only, never a transform, MOT-010), and its title takes the accent colour in the same two states; otherwise static. Accessibility: the section is aria-labelledby its own heading; each card is a single real anchor (one tab stop per entry, a large touch target) rather than a title link plus a separate "read more"; the focus ring comes from the global :focus-visible rule. Covered by axe.spec.mjs against sections-*.html, which renders this exact file, both themes. Responsive: no named breakpoint. grid-template-columns is repeat(auto-fit, minmax(min(18rem, 100%), 1fr)): the column count grows and shrinks continuously with the container width, one column below 18rem, more as space allows. {% endcomment %}

From the blog

What we have learned watching thousands of invoices get paid, and not paid.

{% for entry in entries %} {% if entry.tag %}{{ entry.tag }}{% endif %}

{{ entry.title }}

{% if entry.summary %}

{{ entry.summary }}

{% endif %} {% if entry.meta %}{{ entry.meta }}{% endif %}
{% endfor %}