{% load brickwork_icons %} {% comment %} Feature grid (04-interfaces.md section 4d): a responsive grid of feature cards. Structural, consumed via {% include %} (BR-BW-MKT ยง4d structural- include doctrine). Required context: none. Optional context: heading (str): the section intro heading. lede (str): the section intro body. items (list of dicts): {icon?, heading, body, url?, aria_label?}. icon is a registry name rendered via {% bw_icon %} decorative=True (the icon reinforces the heading/body text, which already carries the meaning). An empty (or omitted) items list renders the section intro alone (or nothing at all if that too is empty), never a fabricated placeholder card. List-shaped, so it has no flat-kwarg spelling (#98): a Django template cannot build a list inline, so supply items from context (the view, or a wrapper template's own data); the scalar intro context (heading, lede, columns) is flat and template-authorable as-is. item.url (str, optional, #99): when present the whole card renders as an anchor (bw-feature-card--link) so a feature card can navigate to its subject, taking the marketing kit's link hover affordance (the heading ink moves to accent on hover, with the standard colour transition; the focus ring comes from the global :focus-visible rule). Absent, the card stays the plain non-interactive
, byte-identical to before #99: never a clickable-looking card with no destination (the same contract as _stat.html's href). item.aria_label (str, optional, #99): overrides a linked card's accessible name; omitted, the name is the card's own text content. Ignored without item.url. columns (2|3|4, default 3): responsive down to one column on narrow viewports (bw-feature-grid-- selects the CSS grid template). States: none: a static grid of cards, no open/closed or hover-only reveal. A linked card (item.url) takes the standard link hover ink shift and the global :focus-visible ring; an unlinked card has no interactive state at all. Accessibility: each card's heading is an

(one level under the section's own

), so a page composing several feature grids keeps a correct outline; the card icon is decorative. A linked card renders as a real wrapping the whole card, never a div with a click handler, and item.aria_label overrides its accessible name when the visible text alone would not describe the destination. Covered by axe.spec.mjs against landing-*.html (its own shipped feature grid) and sections-*.html (features/icon-grid.html), both themes. Responsive: grid-template-columns switches at two named breakpoints: 1 column below --bw-breakpoint-sm (40rem), 2 columns from sm up to below --bw-breakpoint-lg (64rem) regardless of the columns value (2/3/4 all render 2 columns in this band), then the requested column count (2, 3 or 4) from lg upward. {% endcomment %} {% if heading or lede or items %}
{% if heading or lede %}
{% if heading %}

{{ heading }}

{% endif %} {% if lede %}

{{ lede }}

{% endif %}
{% endif %} {% if items %}
{% endif %}
{% endif %}