{% load brickwork_components %} {% comment %} Card (CMP-014 to CMP-017): the elevated composition surface. Structural, so it is consumed via {% include %} (like _page_header.html and _data_table.html). Its five named regions are blocks, all empty by default: an unfilled region emits NO markup at all (matching _alert.html's {% block alert_body %} convention), so a card with nothing filled renders a bare elevated surface (resting --bw-elevation-1, radius-lg, density-aware padding; AC-BW-070). Named blocks (semver-public, BR-BW-TPL-001), in document order: header, title, actions, body, footer: present SINCE 3.4.0, the concise names (ADR-077 SS4; the declaring template is the scope, so a component prefix carries no information). Each wraps the corresponding deprecated prefixed block below, so a call site filling only the concise name renders exactly the same output the prefixed block always produced. card_header, card_title, card_actions, card_body, card_footer: present since before 3.4.0 (unchanged back to at least 3.2.1). DEPRECATED, removed at 4.0 (ADR-077 SS4, BR-BW-TPL-001/BR-BW-VER-001). Kept as additional empty extension points for backwards compatibility: a shipped block name cannot be renamed silently. Both a concise block and its deprecated counterpart render when both are filled; a caller migrating to the concise name fills header/title/actions/body/footer only. A block name this file does not define is SILENTLY DISCARDED by Django: no error, no warning, DEBUG=True does not catch it. A consumer pinned below 3.4.0 who reads header/title/actions/body/footer from a newer checkout gets a structurally valid, entirely empty region that still passes template loading; check this header against your pinned version before relying on a name. DUAL CONSUMPTION on `title` only (icvoss/django-brickwork#398): the `title` block also renders a `title` context variable, wrapped in the same

a caller filling the block by hand would write itself (matching the header/title block's own filler example below), so `{% include %} with title="..."` (the shape a copy-paste band example uses, since {% include %} cannot fill a block at all) now renders a real heading instead of silently discarding the value. The wrapper is conditional on `title` being truthy, so a bare card with no title supplied still emits no empty region markup (matching the unfilled-region convention every other block on this file follows). `{% block title %}` still overrides the whole thing, exactly as block override already does everywhere else, so a caller who supplies both gets the block's content: no new precedence rule, just the block winning by construction. The deprecated `card_title` block deliberately does NOT get this treatment (BR-BW-TPL-001's retirement of the prefixed names would otherwise be undone by giving a retiring name a new reason to be used). header, footer, body, actions, and every card_-prefixed block remain markup-only extension points with no matching context variable: their own docstring paragraph below documents why (the filler owns the whole wrapper element for each, e.g. a header row pairing a heading with an actions cluster, not a bare string), so passing a context variable under these names is still silently discarded, correctly, because there is no single string these regions could sensibly wrap. Filling blocks from an include call site: {% include %} cannot fill a block, so a caller that needs a region writes a small template that EXTENDS this one and includes THAT (the mechanism patterns/_table_card.html uses): {% extends "brickwork/components/_card.html" %} {% block header %}

{% translate "Members" %}

{% bw_button label="Add" variant="secondary" size="sm" %}
{% endblock %} {% block body %}...{% endblock %} {% block footer %}{% endblock %} The region classes (bw-card__header/__title/__actions/__body/__footer) are the styling hooks for that filler markup: the header row is a flex row with the title (heading-md voice) at the inline start and the actions cluster at the end; the footer is a quiet caption band under a hairline. The filler owns the wrapper element, so an unfilled region never leaves empty chrome behind. bw-card__body carries NO rule of its own (icvoss/django-brickwork#130): it is a positioning-only hook. The card's own padding already sets the inset on all four sides, and the header/footer margins already open the gap on their own edge when present, so a bare bw-card__body wrapper needs nothing beyond grouping the body markup under a name a consumer's own selectors can target. If body content ever needs spacing of its own, style it on that content's element, not by adding weight to this class. Required context: none. Optional: title: rendered inside the title block when that block is not overridden (icvoss/django-brickwork#398). A caller that also fills {% block title %} gets the block's content; the context variable is the fallback for the common {% include %} case, since {% include %} has no other way to reach a block-shaped region. header, footer, body, actions and the card_-prefixed blocks have no equivalent context variable: see the docstring paragraph above for why. interactive (bool, default False): rests at --bw-elevation-1 and raises to --bw-elevation-2 on hover/focus-within, shadow only, never a transform (MOT-010, AC-BW-071). href: when set the WHOLE card is a clickable anchor (CMP-017) and the interactive treatment always applies (a clickable card is definitionally hoverable, so bw-card--interactive is emitted regardless of the interactive flag). bordered (bool, default False, CMP-015): the hairline alone carries the boundary (elevation-0), for a flat-design context. size ("sm"|"md"|"lg", default "md"): emitted as bw-card--size- only when supplied, composing with (never overriding) the density axis's --bw-density-card-padding (AC-BW-072). Renamed from padding in 3.0.0 (ADR-060 SS1b): scale is spelled size= everywhere. The root element opens and closes in matching {% if href %} branches (an for a linked card, a
otherwise) because a named block may appear only once per template, so the regions cannot be duplicated across two branches the way _button.html duplicates its label. States: resting (--bw-elevation-1) and, when interactive=True or href is set, a raised (--bw-elevation-2) hover/focus-within state, shadow only, never a transform (MOT-010). A linked card (href) is always interactive; the flag only matters for a non-linked card. Accessibility: purely structural, no role or live behaviour of its own; a linked card renders as a real so it is a native focusable, activatable target rather than a div with a click handler. Not covered by a dedicated card fixture in the a11y suite (usedByArchetypes/usedBySections are both empty in the catalogue manifest: no shipped example composes it directly today), so its accessibility floor rests on the WCAG 2.2 AA rules axe checks against whatever markup a consumer fills its blocks with, not a brickwork-authored render. Responsive: no breakpoint switch; no width-dependent CSS on any .bw-card* selector. Sizing is the fixed size="sm"|"md"|"lg" token scale, composed with the density axis's own padding token, never a viewport-driven rule. {% endcomment %} {% if href %}{% else %}{% endif %}