Section eyebrow

This is an article heading block

Optional subtitle that sits below the title in prose width.

This is the body paragraph after the heading block. The heading replaces a bare ## H2. Pre-title is small, uppercase, in --text-shy. Subtitle is text-l in --text-secondary. Use this for the top of every section that needs an eyebrow.


This is a section with a text-width figure

This is a body paragraph inside the prose column. Articles use a narrow measure for reading. Bold for emphasis, italic for asides, links inline. Inline code renders in monospace.

This is a caption for a text-width figure—same column as the prose.

This is the paragraph after the text-width figure. Use this width when the image belongs to the reading flow.


This is a section with a body-text figure

This is the opening paragraph of the section.

This is a caption for a body-text figure—same column as the prose. Default placement.

This is the closing paragraph after the figure.


This is a section with a full-width figure

This is the opening paragraph.

This is a caption for a full-width figure—edge to edge of the article grid.

This is the closing paragraph.


This is a section with a research finding

This is the paragraph that sets up the callout below.

This is the finding nameplate

This is the finding text. Use this pattern for a pull-quote style callout that breaks the reading rhythm.

This is the paragraph after the callout.


This is a section with a stats callout

This is the paragraph that sets up the stats.

00%This is a stat label
 
00%This is a stat label

This is the paragraph after the stats.


This is a section with a KPI callout

This is the paragraph that sets up the single big number.

This is the KPI label

00%

This is the supporting caption.

Use this when one number carries the section. The number reads at title-l size; label and caption flank it.


This is a section with a 3-column image row

This is the opening paragraph.

This is a caption for a 3-column image row—stacks at mobile, rows at tablet and up.

This is the paragraph after the row.


This is a 3-column row with per-tile captions

Use the __tile variant when each cell needs its own caption (e.g. three prototypes side by side, each with the designer’s name and a one-liner).

Tile 1: A short caption sits under each cell.
Tile 2: Captions can use bold and italics freely.
Tile 3: Each tile is a <figure> with image/video + figcaption.

This is the paragraph after the row.


This is a section with a CTA pill

<ArticleCTA> is a small button-styled link for pointing at a related report or external resource. Sits inline at prose width—use sparingly.

See the report

This is the paragraph after the CTA.


This is a video tile that opens in a modal

Add data-video-modal-trigger to any <video> (typically inside .article-figure-row__tile) to make it clickable. Click opens the shared <ArticleVideoModal> overlay (mounted once on the article route) and plays the video large with a centered caption. ESC, backdrop click, and the X button all close it. The in-row video pauses while the modal is open and resumes on close.


This is a section with a figure + text block

This is the paragraph that introduces the pattern below.

This is a side heading

This is the supporting paragraph that sits beside the figure at tablet and up. On mobile it stacks below the figure.

This is the paragraph after the block.


This is the paragraph that introduces the gallery.

This is the caption for the main video.

This is the paragraph after the gallery.


This is the paragraph that introduces the gallery. Same shape as the video gallery, but for images — and the caption stays static when thumbs are clicked.

This is the static caption — does not change with the image.

This is the paragraph after the gallery.


This is a section with a scroll-controlled video

This is the paragraph that introduces the video.

The video plays when the section enters the viewport, stops at the end, and reveals the Replay button on the caption row below — right-aligned, outside the video frame.


This is a section with sub-section dividers and pre-titles

The first sub-section uses the section’s H2. Subsequent sub-sections use a .article-divider rule + .article-pretitle eyebrow above their body content. Use this pattern when one section has multiple distinct ideas (Solution → Mode toggle → Subtitle removal → Entrance choreography).


Pre-title eyebrow

This is the body of the second sub-section. The pre-title sits in the prose column — small, uppercase, semibold.


Another pre-title

And another sub-section. The divider is a 0.5px rule at the prose width, not full-width.


This is a section with a chart card

This is the paragraph that introduces the chart.

This is the chart title

This is the chart subtitle.

This is a caption for a chart card.

This is the paragraph after the chart.


This is a subsection pattern

This is a heading three

Use ### for subsections within a section. Don’t skip levels.

Unordered list:

  • First item in the list
  • Second item with bold for emphasis
  • Third item with a longer body to show how wrapping works when text extends beyond a single line

Ordered list:

  1. First step in a sequence
  2. Second step with italic reference
  3. Third step to complete the flow

A blockquote for pull quotes or external references. Blockquotes stand apart from the body text.

// Fenced code blocks render with syntax highlighting
const tokens = {
  spacing: '--spacing-md',
  color: '--text-primary',
};

This is the conclusion section

This is the closing paragraph. No figure here—just a clean wrap.

A second paragraph to show vertical rhythm between final blocks.


Frontmatter fields: title (required), subtitle?, date (required), cover? (string—single hero), covers? (string[]—carousel), draft?, theme? ("dark" | "light", default light).

Components: ArticleSection, ArticleSectionDivider, ArticleSubsection, ArticleHeading (pretitle?, title, subtitle?, level?), ArticleCTA (href, label, external?), Figure (src?, alt?, caption?, placeholder?), Video (src, caption?), Divider (label?, spaceAbove?, spaceBelow?). ArticleVideoModal is mounted once per article page automatically—just add data-video-modal-trigger to a <video> to make it clickable.

Section dividers: <ArticleSectionDivider /> is a sibling of <ArticleSection> — place it between sections that need a 0.5px rule. The first section never has a divider before it. For section eyebrows, use <ArticleHeading pretitle="..."> inside the section.

Heading hierarchy: <ArticleHeading> for the section’s H2 (with optional eyebrow + subtitle), <ArticleHeading level={3} title="..."> for sub-sections within a section. .article-pretitle + .article-divider is still available for the standalone “eyebrow between sub-sections” pattern, but most articles will use H3-driven sub-sections instead.

Figure widths: two only — body-text (default, same column as prose) and full-width (article-figure--full-width, edge to edge). The legacy .article-finding--text-width modifier still parses for back-compat but is now a no-op (default IS text-width).

CSS hooks: article-section, article-section-divider (+ __line), article-subsection, article-heading (+ __pretitle / __title / __subtitle), article-cta, article-video-modal (+ __backdrop / __close / __stage / __video / __caption), post-meta, article-finding + --text-width / --kpi / article-card / __nameplate / __text / __stats / __stat / __kpi-label / __kpi-value / __kpi-caption, article-figure--full-width, article-figure-row (+ __tile for per-cell captions), article-figure-with-text, article-figure-pair, article-video-gallery, article-image-gallery (+ data-image-gallery / data-image-src), article-scroll-video (+ data-scroll-video), article-pretitle, article-divider, report-chart-card. Trigger attribute: data-video-modal-trigger on any <video>.