{% load brickwork_components %} {% comment %} Hero (04-interfaces.md section 4d): the marketing headline block. Structural, consumed via {% include %} (no render-time a11y enforcement or icon resolution of its own, so it follows the _card.html/_page_header.html structural-include doctrine, not the tag doctrine, per BR-BW-MKT §4d). Required context: none. An all-empty hero renders a bare hero band, so a page can fill it via context or override the block entirely. Optional context: eyebrow (str): a small overline above the heading. heading (str): the display headline. Rendered as the page's h1: a page composing this include owns exactly one hero per page. subheading (str, #672): optional positioning line between heading and lede. Visually stronger than the lede (fg ink, heading-lg role). Omitted is byte-identical to before this slot existed. lede (str): the subhead paragraph. primary_cta ({label, url}): rendered via {% bw_button %} primary. primary_cta_label / primary_cta_href (str, #98): the same primary CTA as flat strings, generalising _stat.html's flat-string shape. A Django template cannot build a dict inline, so a page composing this include directly (the ADR-056 shape) passes the flat kwargs instead: {% include "..._hero.html" with heading="Ship faster" primary_cta_label="Get started" primary_cta_href="/signup/" %} Both shapes are supported on every CTA in this kit; when both are supplied the dict wins outright (the flat kwargs are ignored), and a dict-shaped caller renders byte-identically to before the flat shape existed. secondary_cta ({label, url}): rendered via {% bw_button %} secondary. secondary_cta_label / secondary_cta_href (str, #98): the flat form of secondary_cta, same precedence. meta (str or safe HTML, #672): quiet status / year line under the actions row. Omitted (and no meta_items) renders nothing and is byte-identical to before this slot existed. The caller owns escaping when passing HTML (mark it safe at the call site), matching media/decoration. When both meta and meta_items are supplied, meta wins outright. meta_items (list of str, #672): structured meta facts rendered with a middle-dot separator (article_meta convention). Used only when meta is absent. Empty list / omitted renders nothing. media (safe string): pre-rendered HTML for an image/illustration slot. Omitted renders a text-only hero, never a broken image box. The caller owns escaping (mark it safe at the call site), matching _stat.html's sparkline convention. decoration (safe string, #645): pre-rendered HTML for a watermark or stamp behind the copy on the ordinary surface (not the media-behind inverse panel). Omitted renders nothing and is byte-identical to before this slot existed. The caller owns escaping (mark it safe at the call site), matching media. Rendered aria-hidden with pointer-events none; it is never content. Prefer this context or the decoration named block; do not use media_placement="behind" for a faded brand mark. eyebrow_marker ("none" default | "rule", #659): optional leading accent rule before the overline text. "none" (also omitted) is byte-identical to before this option existed. "rule" adds bw-hero__eyebrow--rule on the eyebrow
; the mark is drawn by the component's ::before and tuned by --bw-component-hero-eyebrow-marker-{inline-size,block-size, color}. The colour token is independent of the eyebrow text colour (which stays --bw-color-accent under the default tone) so a brand can paint the mark differently. Composes with media_placement, decoration, and eyebrow_tone. eyebrow_tone ("accent" default | "sentence", #672): overline voice. "accent" (also omitted) is the shipped uppercase accent overline and is byte-identical for existing callers. "sentence" emits bw-hero__eyebrow--sentence: muted ink, sentence case (no text-transform), for personal-presence kickers. Explicit option only; never inferred from copy. Composes with eyebrow_marker. align ("start" | "center" | "end", default "start"). align="start" left-aligns .bw-hero__actions; align="end" right-aligns them; align="center" centres them (#672). media_placement ("below" default | "behind" | "beside" | "above", ADR-057 section 1a): where the media slot sits relative to the copy. "below" is the shipped 2.0.0 layout (a column flex, media after the copy in document order) and is the honestly-named default, not "beside": the copy and media were never side by side until this option existed (icvoss/django-brickwork#118). "behind" stacks the media in the same grid area as the copy, with the copy on top; the section takes the inverse surface (--bw-color-surface-inverse / --bw-color-fg-on-inverse) plus a scrim over the media, so contrast holds in both themes regardless of what the media itself contains. "beside" is a true side-by-side row from 48rem up (single column below it), replacing what a consumer previously had to hand-build as its own section (src/brickwork/examples/sections/hero/split-media.html, which collapses to an include of this option, per ADR-077). "above" stacks the media visually above the copy (icvoss/django-brickwork#201); document order stays copy-then-media because this axis is CSS-only. This is a CSS-only option: it changes no markup, only the modifier class on the section root, so a caller who has copied this include still only edits one class to change arrangement (ADR-057 section 1a's binding rule on CSS-only axes). Decoration composes with every placement; it does not require "behind". eyebrow_marker / eyebrow_tone / media_shape likewise compose with every placement and with decoration. media_shape ("default" default | "circle", #672): framing of media images. "default" (also omitted) keeps the shipped radius and is byte-identical. "circle" emits bw-hero--media-circle: square crop, full radius, object-fit cover, sized by --bw-component-hero-media-circle-size, so a circular portrait works under media_placement="beside" without a consumer override. Applies to img only (same SVG carve-out as the default media radius). Uses the display type role (--bw-text-heading-display-*) and the marketing section-rhythm token for its own block spacing. Decoration opacity and inset/size use --bw-component-hero-decoration-* (see DESIGN.md). Eyebrow marker size and colour use --bw-component-hero-eyebrow-marker-* when eyebrow_marker="rule". Circle media size uses --bw-component-hero-media-circle-size when media_shape="circle". Named blocks (semver-public, BR-BW-TPL-001), all empty by default, in document order: eyebrow, heading, subheading, lede, actions, meta, decoration, media. Each wraps the existing conditional rendering above, so a call site supplying only the flat context variables (the pre-existing path) renders byte-identical output to before these blocks existed (new optional slots omitted). These blocks exist because BR-BW-OPT-004 forbids a proliferating set of prose kwargs with no data object behind them: eyebrow/heading/subheading/lede are exactly that shape, so the slot is the escape hatch for a caller with structured copy (a translated mark, a rich lede with an inline link) that a flat string cannot carry, rather than adding yet another *_html kwarg per field. decoration and meta follow the same safe-HTML convention as media. States: none of its own beyond the primary/secondary bw_button CTAs' own states; three align states (start default, center, end), four media_placement states (below default, behind, beside, above), two eyebrow_marker states (none default, rule), two eyebrow_tone states (accent default, sentence), and two media_shape states (default, circle), each a CSS-only modifier class change where applicable. Accessibility: the heading renders as the page's own
{{ eyebrow }}
{% endif %}{% endblock %} {% block heading %}{% if heading %}{{ subheading }}
{% endif %}{% endblock %} {% block lede %}{% if lede %}{{ lede }}
{% endif %}{% endblock %} {% block actions %} {% if primary_cta or secondary_cta or primary_cta_label or secondary_cta_label %}