EssentialsSurfaces

Surfaces

Every block rune exposes one or two decorable surfaces, and a small, universal vocabulary styles them — the same attributes on a card, a figure, a hero, or a bento-cell. A card, for example, has two: its self surface (the card box) and a media surface (its image/embed slot). No per-rune attributes to learn.

AttributeSurfaceWhat it does
elevationselfa box-shadow that floats the box
frame / frame-*mediapresent the media — aspect, crop, silhouette shadow, displacement
substrate / substrate-*self (default)a generated pattern (dots, grid, …)
tintcolourrecolour the surface (see tint)
bgimagean image/video layer behind content (see bg)

The page walks the model along its four axes:

  • Chrome — the shadows and framing that lift a surface off the page.
  • Fills — the colour, pattern, and gradient layers that paint it.
  • Cover — the poster layout, where content overlays the media.
  • Posture — how a clickable surface treats the guests inside it.

Everything here is one or two attributes on an ordinary rune. Nothing is a bespoke component.

Chrome — shadow and frame

A surface decorates on two layers. The self layer is the whole tile — elevation lifts it as a box shadow. The media layer is the framed image inside — frame-* attributes shape it (frame-aspect), anchor the crop (frame-anchor), displace it past the slot (frame-displace), and shadow it (frame-shadow). elevation and frame-shadow are the same physical property (a shadow) on different surfaces, so they carry two names and never collide:

{% card elevation="lg" %}
### `elevation="lg"`
A box shadow on the card's **self** surface — the whole tile floats.
{% /card %}

{% figure frame-aspect="16/9" caption="`frame-aspect` sets the framed media's shape; the image fills it via `object-fit: cover`." %}
![A framed image](https://picsum.photos/seed/gallerysilhouette/800/450)
{% /figure %}
<div data-rune="card" data-rune-fields="{&quot;media-position&quot;:&quot;top&quot;}" elevation="lg">
  <div data-name="body">
    <h3 id="" data-name="title">
      <code>elevation=&quot;lg&quot;</code>
    </h3>
    <p>
      A box shadow on the card's
      <strong marker="**">self</strong>
      surface — the whole tile floats.
    </p>
  </div>
</div>
<figure data-rune="figure" typeof="ImageObject">
  <img src="https://picsum.photos/seed/gallerysilhouette/800/450" alt="A framed image" property="contentUrl">
  <figcaption data-name="caption" property="caption">`frame-aspect` sets the framed media's shape; the image fills it via `object-fit: cover`.</figcaption>
  <meta data-field="frame-aspect" content="16/9">
</figure>

elevation="lg"

A box shadow on the card's self surface — the whole tile floats.

A framed image
`frame-aspect` sets the framed media's shape; the image fills it via `object-fit: cover`.
<div class="rf-card" data-media-position="top" data-elevation="lg" data-rune="card" data-density="full">
  <div data-name="content" class="rf-card__content">
    <div data-name="body" class="rf-card__body">
      <h3 id="" data-name="title" class="rf-card__title">
        <code>elevation=&quot;lg&quot;</code>
      </h3>
      <p>
        A box shadow on the card's 
        <strong marker="**">self</strong>
         surface — the whole tile floats.
      </p>
    </div>
  </div>
</div>
<figure typeof="ImageObject" class="rf-figure rf-figure--default rf-figure--center" data-size="default" data-align="center" data-rune="figure" data-density="compact" style="--frame-aspect: 16/9">
  <img src="https://picsum.photos/seed/gallerysilhouette/800/450" alt="A framed image" property="contentUrl" />
  <figcaption data-name="caption" property="caption" class="rf-figure__caption" data-section="description">`frame-aspect` sets the framed media's shape; the image fills it via `object-fit: cover`.</figcaption>
</figure>

elevation runs a named scale — none | sm | md | lg — on every block rune. elevation="none" flattens a rune's default shadow.

{% card elevation="sm" %}
### `sm`
Barely lifted.
{% /card %}

{% card elevation="md" %}
### `md`
A clear float.
{% /card %}

{% card elevation="lg" %}
### `lg`
Highest z-height.
{% /card %}
<div data-rune="card" data-rune-fields="{&quot;media-position&quot;:&quot;top&quot;}" elevation="sm">
  <div data-name="body">
    <h3 id="" data-name="title">
      <code>sm</code>
    </h3>
    <p>Barely lifted.</p>
  </div>
</div>
<div data-rune="card" data-rune-fields="{&quot;media-position&quot;:&quot;top&quot;}" elevation="md">
  <div data-name="body">
    <h3 id="" data-name="title">
      <code>md</code>
    </h3>
    <p>A clear float.</p>
  </div>
</div>
<div data-rune="card" data-rune-fields="{&quot;media-position&quot;:&quot;top&quot;}" elevation="lg">
  <div data-name="body">
    <h3 id="" data-name="title">
      <code>lg</code>
    </h3>
    <p>Highest z-height.</p>
  </div>
</div>

sm

Barely lifted.

md

A clear float.

lg

Highest z-height.

<div class="rf-card" data-media-position="top" data-elevation="sm" data-rune="card" data-density="full">
  <div data-name="content" class="rf-card__content">
    <div data-name="body" class="rf-card__body">
      <h3 id="" data-name="title" class="rf-card__title">
        <code>sm</code>
      </h3>
      <p>Barely lifted.</p>
    </div>
  </div>
</div>
<div class="rf-card" data-media-position="top" data-elevation="md" data-rune="card" data-density="full">
  <div data-name="content" class="rf-card__content">
    <div data-name="body" class="rf-card__body">
      <h3 id="" data-name="title" class="rf-card__title">
        <code>md</code>
      </h3>
      <p>A clear float.</p>
    </div>
  </div>
</div>
<div class="rf-card" data-media-position="top" data-elevation="lg" data-rune="card" data-density="full">
  <div data-name="content" class="rf-card__content">
    <div data-name="body" class="rf-card__body">
      <h3 id="" data-name="title" class="rf-card__title">
        <code>lg</code>
      </h3>
      <p>Highest z-height.</p>
    </div>
  </div>
</div>

frame decorates the media surface. Apply a named preset (frame="screenshot") or set facets inline — they also work without a preset.

FacetValuesEffect
frame-aspecte.g. 16/9, 1/1aspect ratio
frame-shadownone|sm|md|lgsilhouette drop-shadow
frame-displacetop|bottom|end|bottom-end|top-endmove the guest toward an edge
frame-offsetnone|sm|md|lg|xldisplacement distance (named scale)
frame-oversizescale factorguest exceeds its slot (clipped)
frame-placeleft top, …alignment within the slot
frame-anchorobject-positioncrop focal point

On a figure or showcase the frame lands on the rune itself; on a card or bento-cell it lands on the media zone. Because a card's media zone is a clipping host, a displaced or oversized guest is cropped into a peek rather than spilling out:

{% card elevation="md" frame-aspect="16/9" frame-anchor="top" %}
![Framed, top-anchored crop](https://picsum.photos/seed/galleryframe/800/600)
---
### Framed media
`frame-aspect` sets the shape; `frame-anchor` picks the focal point of the crop.
{% /card %}

{% card frame-aspect="16/9" frame-displace="top-end" frame-offset="md" frame-oversize="1.15" frame-shadow="md" %}
![A displaced peek with silhouette shadow](https://picsum.photos/seed/gallerypeek/800/600)
---
### Displaced peek + silhouette shadow
`frame-displace` + `frame-oversize` push the guest past its slot; the host clips it to a peek, and `frame-shadow` traces the cropped silhouette — not the card.
{% /card %}
<div data-rune="card" data-rune-fields="{&quot;media-position&quot;:&quot;top&quot;}" elevation="md">
  <div data-section="media" data-name="media">
    <img src="https://picsum.photos/seed/galleryframe/800/600" alt="Framed, top-anchored crop">
  </div>
  <div data-name="body">
    <h3 id="framed-media" data-name="title">Framed media</h3>
    <p>
      <code>frame-aspect</code>
      sets the shape;
      <code>frame-anchor</code>
      picks the focal point of the crop.
    </p>
  </div>
  <meta data-field="frame-aspect" content="16/9">
  <meta data-field="frame-anchor" content="top">
</div>
<div data-rune="card" data-rune-fields="{&quot;media-position&quot;:&quot;top&quot;}">
  <div data-section="media" data-name="media">
    <img src="https://picsum.photos/seed/gallerypeek/800/600" alt="A displaced peek with silhouette shadow">
  </div>
  <div data-name="body">
    <h3 id="displaced-peek-+-silhouette-shadow" data-name="title">Displaced peek + silhouette shadow</h3>
    <p>
      <code>frame-displace</code>
      +
      <code>frame-oversize</code>
      push the guest past its slot; the host clips it to a peek, and
      <code>frame-shadow</code>
      traces the cropped silhouette — not the card.
    </p>
  </div>
  <meta data-field="frame-aspect" content="16/9">
  <meta data-field="frame-displace" content="top-end">
  <meta data-field="frame-offset" content="md">
  <meta data-field="frame-oversize" content="1.15">
  <meta data-field="frame-shadow" content="md">
</div>
Framed, top-anchored crop

Framed media

frame-aspect sets the shape; frame-anchor picks the focal point of the crop.

A displaced peek with silhouette shadow

Displaced peek + silhouette shadow

frame-displace + frame-oversize push the guest past its slot; the host clips it to a peek, and frame-shadow traces the cropped silhouette — not the card.

<div class="rf-card" data-media-position="top" data-elevation="md" data-rune="card" data-density="full">
  <div data-section="media" data-name="media" class="rf-card__media" style="--frame-aspect: 16/9; --frame-anchor: top">
    <img src="https://picsum.photos/seed/galleryframe/800/600" alt="Framed, top-anchored crop" />
  </div>
  <div data-name="content" class="rf-card__content">
    <div data-name="body" class="rf-card__body">
      <h3 id="framed-media" data-name="title" class="rf-card__title">Framed media</h3>
      <p>
        <code>frame-aspect</code>
         sets the shape; 
        <code>frame-anchor</code>
         picks the focal point of the crop.
      </p>
    </div>
  </div>
</div>
<div class="rf-card" data-media-position="top" data-rune="card" data-density="full">
  <div data-section="media" data-name="media" class="rf-card__media" data-displace="top-end" data-frame-shadow="md" style="--frame-aspect: 16/9; --frame-offset: var(--rf-spacing-md); --frame-oversize: 1.15">
    <img src="https://picsum.photos/seed/gallerypeek/800/600" alt="A displaced peek with silhouette shadow" />
  </div>
  <div data-name="content" class="rf-card__content">
    <div data-name="body" class="rf-card__body">
      <h3 id="displaced-peek-+-silhouette-shadow" data-name="title" class="rf-card__title">Displaced peek + silhouette shadow</h3>
      <p>
        <code>frame-displace</code>
         + 
        <code>frame-oversize</code>
         push the guest past its slot; the host clips it to a peek, and 
        <code>frame-shadow</code>
         traces the cropped silhouette — not the card.
      </p>
    </div>
  </div>
</div>

Whether a displaced or oversized guest spills out or is cropped into a peek is decided by the host, not the guest — see host-owned clip.

Fills — colour, pattern, gradient

Three fill layers paint the surface itself. tint recolours a rune to a named palette — the whole surface, border, and text shift together (and tint-mode can pin the scheme):

{% card tint="catppuccin" %}
### `tint="catppuccin"`
The card adopts the named palette — surface, border, and text in one move.
{% /card %}

{% card tint="solarized" %}
### `tint="solarized"`
Same card, a different registered tint. See [tint](/runes/tint) for the palette registry.
{% /card %}
<div data-rune="card" data-rune-fields="{&quot;media-position&quot;:&quot;top&quot;}">
  <div data-name="body">
    <h3 id="" data-name="title">
      <code>tint=&quot;catppuccin&quot;</code>
    </h3>
    <p>The card adopts the named palette — surface, border, and text in one move.</p>
  </div>
  <meta data-field="tint" content="catppuccin">
</div>
<div data-rune="card" data-rune-fields="{&quot;media-position&quot;:&quot;top&quot;}">
  <div data-name="body">
    <h3 id="" data-name="title">
      <code>tint=&quot;solarized&quot;</code>
    </h3>
    <p>
      Same card, a different registered tint. See
      <a href="/runes/tint">tint</a>
      for the palette registry.
    </p>
  </div>
  <meta data-field="tint" content="solarized">
</div>

tint="catppuccin"

The card adopts the named palette — surface, border, and text in one move.

tint="solarized"

Same card, a different registered tint. See tint for the palette registry.

<div class="rf-card rf-card--tinted" data-media-position="top" data-tint="catppuccin" data-tint-dark="" data-rune="card" data-density="full" style="--tint-bg: #eff1f5; --tint-surface: #e6e9ef; --tint-text: #4c4f69; --tint-muted: #6c6f85; --tint-primary: #1e66f5; --tint-border: #dce0e8; --tint-dark-bg: #1e1e2e; --tint-dark-surface: #181825; --tint-dark-text: #cdd6f4; --tint-dark-muted: #a6adc8; --tint-dark-primary: #89b4fa; --tint-dark-border: #313244">
  <div data-name="content" class="rf-card__content">
    <div data-name="body" class="rf-card__body">
      <h3 id="" data-name="title" class="rf-card__title">
        <code>tint=&quot;catppuccin&quot;</code>
      </h3>
      <p>The card adopts the named palette — surface, border, and text in one move.</p>
    </div>
  </div>
</div>
<div class="rf-card rf-card--tinted" data-media-position="top" data-tint="solarized" data-tint-dark="" data-rune="card" data-density="full" style="--tint-bg: #fdf6e3; --tint-surface: #eee8d5; --tint-text: #657b83; --tint-muted: #93a1a1; --tint-primary: #268bd2; --tint-border: #eee8d5; --tint-dark-bg: #002b36; --tint-dark-surface: #073642; --tint-dark-text: #839496; --tint-dark-muted: #586e75; --tint-dark-primary: #268bd2; --tint-dark-border: #073642">
  <div data-name="content" class="rf-card__content">
    <div data-name="body" class="rf-card__body">
      <h3 id="" data-name="title" class="rf-card__title">
        <code>tint=&quot;solarized&quot;</code>
      </h3>
      <p>
        Same card, a different registered tint. See 
        <a href="/runes/tint">tint</a>
         for the palette registry.
      </p>
    </div>
  </div>
</div>

substrate prints a token-generated pattern — no image asset — from a fixed vocabulary.

FacetValuesEffect
substratedots|grid|lines|cross|checker|nonethe pattern
substrate-sizesm|md|lgcell size
substrate-opacitysm|md|lgink strength
substrate-fillinherit (default) / insetsit on the surface, or the recessed inset fill

A substrate fills the rune's self surface by default — a banner pattern covers the whole banner. Opt into the media well with substrate-target="media". substrate-fill="inset" lays it over a slightly recessed fill that still tracks the surface colour:

{% card substrate="dots" %}
### dots
A generated dot grid — default size and opacity.
{% /card %}

{% card substrate="grid" %}
### grid
Two tiled gradients.
{% /card %}

{% card substrate="lines" substrate-opacity="lg" %}
### lines · opacity="lg"
Diagonal hatching at heavier ink strength.
{% /card %}

{% card substrate="checker" substrate-size="lg" %}
### checker · size="lg"
Alternating filled cells, scaled up via `substrate-size`.
{% /card %}

{% card substrate="cross" substrate-fill="inset" %}
### cross · fill="inset"
Pattern over a recessed, tint-tracking fill.
{% /card %}
<div data-rune="card" data-rune-fields="{&quot;media-position&quot;:&quot;top&quot;}">
  <div data-name="body">
    <h3 id="dots" data-name="title">dots</h3>
    <p>A generated dot grid — default size and opacity.</p>
  </div>
  <meta data-field="substrate" content="dots">
</div>
<div data-rune="card" data-rune-fields="{&quot;media-position&quot;:&quot;top&quot;}">
  <div data-name="body">
    <h3 id="grid" data-name="title">grid</h3>
    <p>Two tiled gradients.</p>
  </div>
  <meta data-field="substrate" content="grid">
</div>
<div data-rune="card" data-rune-fields="{&quot;media-position&quot;:&quot;top&quot;}">
  <div data-name="body">
    <h3 id="lines-·-opacity=&quot;lg&quot;" data-name="title">lines · opacity=&quot;lg&quot;</h3>
    <p>Diagonal hatching at heavier ink strength.</p>
  </div>
  <meta data-field="substrate" content="lines">
  <meta data-field="substrate-opacity" content="lg">
</div>
<div data-rune="card" data-rune-fields="{&quot;media-position&quot;:&quot;top&quot;}">
  <div data-name="body">
    <h3 id="checker-·-size=&quot;lg&quot;" data-name="title">checker · size=&quot;lg&quot;</h3>
    <p>
      Alternating filled cells, scaled up via
      <code>substrate-size</code>
      .
    </p>
  </div>
  <meta data-field="substrate" content="checker">
  <meta data-field="substrate-size" content="lg">
</div>
<div data-rune="card" data-rune-fields="{&quot;media-position&quot;:&quot;top&quot;}">
  <div data-name="body">
    <h3 id="cross-·-fill=&quot;inset&quot;" data-name="title">cross · fill=&quot;inset&quot;</h3>
    <p>Pattern over a recessed, tint-tracking fill.</p>
  </div>
  <meta data-field="substrate" content="cross">
  <meta data-field="substrate-fill" content="inset">
</div>

dots

A generated dot grid — default size and opacity.

grid

Two tiled gradients.

lines · opacity="lg"

Diagonal hatching at heavier ink strength.

checker · size="lg"

Alternating filled cells, scaled up via substrate-size.

cross · fill="inset"

Pattern over a recessed, tint-tracking fill.

<div class="rf-card" data-media-position="top" data-substrate="dots" data-rune="card" data-density="full">
  <div data-name="content" class="rf-card__content">
    <div data-name="body" class="rf-card__body">
      <h3 id="dots" data-name="title" class="rf-card__title">dots</h3>
      <p>A generated dot grid — default size and opacity.</p>
    </div>
  </div>
</div>
<div class="rf-card" data-media-position="top" data-substrate="grid" data-rune="card" data-density="full">
  <div data-name="content" class="rf-card__content">
    <div data-name="body" class="rf-card__body">
      <h3 id="grid" data-name="title" class="rf-card__title">grid</h3>
      <p>Two tiled gradients.</p>
    </div>
  </div>
</div>
<div class="rf-card" data-media-position="top" data-substrate="lines" data-rune="card" data-density="full" style="--substrate-opacity: 0.85">
  <div data-name="content" class="rf-card__content">
    <div data-name="body" class="rf-card__body">
      <h3 id="lines-·-opacity=&quot;lg&quot;" data-name="title" class="rf-card__title">lines · opacity=&quot;lg&quot;</h3>
      <p>Diagonal hatching at heavier ink strength.</p>
    </div>
  </div>
</div>
<div class="rf-card" data-media-position="top" data-substrate="checker" data-rune="card" data-density="full" style="--substrate-cell: 24px">
  <div data-name="content" class="rf-card__content">
    <div data-name="body" class="rf-card__body">
      <h3 id="checker-·-size=&quot;lg&quot;" data-name="title" class="rf-card__title">checker · size=&quot;lg&quot;</h3>
      <p>
        Alternating filled cells, scaled up via 
        <code>substrate-size</code>
        .
      </p>
    </div>
  </div>
</div>
<div class="rf-card" data-media-position="top" data-substrate="cross" data-substrate-fill="inset" data-rune="card" data-density="full">
  <div data-name="content" class="rf-card__content">
    <div data-name="body" class="rf-card__body">
      <h3 id="cross-·-fill=&quot;inset&quot;" data-name="title" class="rf-card__title">cross · fill=&quot;inset&quot;</h3>
      <p>Pattern over a recessed, tint-tracking fill.</p>
    </div>
  </div>
</div>

Gradient fills are token-driven — from/to take semantic colour names that resolve to var(--rf-color-*), so the gradient tracks the theme. A gradient-only card needs an intrinsic height to show:

{% card height="md" bg-gradient="to-br" bg-from="primary" bg-to="info" %}
### Gradient fill
A two-stop linear gradient from token colours — no image needed.
{% /card %}

{% card height="md" bg-gradient="to-t" bg-from="surface" bg-via="primary" bg-to="info" bg-gradient-type="radial" %}
### Radial, three stops
`bg-gradient-type="radial"` with a `via` middle stop.
{% /card %}
<div data-rune="card" data-rune-fields="{&quot;media-position&quot;:&quot;top&quot;,&quot;height&quot;:&quot;md&quot;}">
  <div data-name="body">
    <h3 id="gradient-fill" data-name="title">Gradient fill</h3>
    <p>A two-stop linear gradient from token colours — no image needed.</p>
  </div>
  <meta data-field="bg-gradient" content="to-br">
  <meta data-field="bg-from" content="primary">
  <meta data-field="bg-to" content="info">
</div>
<div data-rune="card" data-rune-fields="{&quot;media-position&quot;:&quot;top&quot;,&quot;height&quot;:&quot;md&quot;}">
  <div data-name="body">
    <h3 id="radial,-three-stops" data-name="title">Radial, three stops</h3>
    <p>
      <code>bg-gradient-type=&quot;radial&quot;</code>
      with a
      <code>via</code>
      middle stop.
    </p>
  </div>
  <meta data-field="bg-gradient" content="to-t">
  <meta data-field="bg-from" content="surface">
  <meta data-field="bg-to" content="info">
  <meta data-field="bg-via" content="primary">
  <meta data-field="bg-gradient-type" content="radial">
</div>

Gradient fill

A two-stop linear gradient from token colours — no image needed.

Radial, three stops

bg-gradient-type="radial" with a via middle stop.

<div class="rf-card rf-card--has-bg" data-media-position="top" data-height="md" data-bg="" data-rune="card" data-density="full">
  <div data-name="bg" style="--bg-image: linear-gradient(to bottom right, var(--rf-color-primary), var(--rf-color-info))" class="rf-card__bg"></div>
  <div data-name="content" class="rf-card__content">
    <div data-name="body" class="rf-card__body">
      <h3 id="gradient-fill" data-name="title" class="rf-card__title">Gradient fill</h3>
      <p>A two-stop linear gradient from token colours — no image needed.</p>
    </div>
  </div>
</div>
<div class="rf-card rf-card--has-bg" data-media-position="top" data-height="md" data-bg="" data-rune="card" data-density="full">
  <div data-name="bg" style="--bg-image: radial-gradient(var(--rf-color-surface), var(--rf-color-primary), var(--rf-color-info))" class="rf-card__bg"></div>
  <div data-name="content" class="rf-card__content">
    <div data-name="body" class="rf-card__body">
      <h3 id="radial,-three-stops" data-name="title" class="rf-card__title">Radial, three stops</h3>
      <p>
        <code>bg-gradient-type=&quot;radial&quot;</code>
         with a 
        <code>via</code>
         middle stop.
      </p>
    </div>
  </div>
</div>

The full fill vocabulary lives in tint and bg.

Cover — the poster layout

media-position="cover" is a one-attribute switch from a normal card into a poster: the media fills the interior and the content overlays it. Cover mode turns on a legibility scrim automatically, so text stays readable over any photo — a directional gradient by default, or a frosted-glass band with scrim-type="frost". content-place anchors the overlay; height (or aspect) gives the poster its shape:

{% card href="/runes/learning/recipe" media-position="cover" height="lg" %}
![A tequila sunrise cocktail](https://assets.refrakt.md/tequila-sunrise.png)

---

Brunch classic

### Tequila Sunrise
A bright, layered cocktail — five minutes, no shaker.
{% /card %}

{% card media-position="cover" content-place="center center" height="lg" %}
![A coastal scene](https://picsum.photos/seed/gallerycover/800/1000)

---

### Centred hero
`content-place="center center"` pins the overlay; the gradient scrim follows as a centred radial spot.
{% /card %}
<div data-rune="card" data-rune-fields="{&quot;media-position&quot;:&quot;cover&quot;,&quot;height&quot;:&quot;lg&quot;}">
  <div data-section="media" data-name="media">
    <img src="https://assets.refrakt.md/tequila-sunrise.png" alt="A tequila sunrise cocktail">
  </div>
  <p data-name="eyebrow">Brunch classic</p>
  <div data-name="body">
    <h3 id="tequila-sunrise" data-name="title">Tequila Sunrise</h3>
    <p>A bright, layered cocktail — five minutes, no shaker.</p>
  </div>
  <a data-name="link" href="/runes/learning/recipe" aria-hidden="true" tabindex="-1"></a>
</div>
<div data-rune="card" data-rune-fields="{&quot;media-position&quot;:&quot;cover&quot;,&quot;content-place&quot;:&quot;center center&quot;,&quot;height&quot;:&quot;lg&quot;}">
  <div data-section="media" data-name="media">
    <img src="https://picsum.photos/seed/gallerycover/800/1000" alt="A coastal scene">
  </div>
  <div data-name="body">
    <h3 id="centred-hero" data-name="title">Centred hero</h3>
    <p>
      <code>content-place=&quot;center center&quot;</code>
      pins the overlay; the gradient scrim follows as a centred radial spot.
    </p>
  </div>
</div>
A tequila sunrise cocktail

Brunch classic

Tequila Sunrise

A bright, layered cocktail — five minutes, no shaker.

A coastal scene

Centred hero

content-place="center center" pins the overlay; the gradient scrim follows as a centred radial spot.

<div class="rf-card rf-card--cover" data-media-position="cover" data-height="lg" data-rune="card" data-density="full" data-cover-scope="full">
  <div data-section="media" data-name="media" class="rf-card__media" data-guest-posture="presentational">
    <img src="https://assets.refrakt.md/tequila-sunrise.png" alt="A tequila sunrise cocktail" />
  </div>
  <div data-name="content" class="rf-card__content" data-color-scheme="dark">
    <p data-name="eyebrow" class="rf-card__eyebrow">Brunch classic</p>
    <div data-name="body" class="rf-card__body">
      <h3 id="tequila-sunrise" data-name="title" class="rf-card__title">Tequila Sunrise</h3>
      <p>A bright, layered cocktail — five minutes, no shaker.</p>
    </div>
  </div>
  <a data-name="link" href="/runes/learning/recipe" aria-hidden="true" tabindex="-1" class="rf-card__link"></a>
</div>
<div class="rf-card rf-card--cover" data-media-position="cover" data-content-place="center center" data-height="lg" data-rune="card" data-density="full" data-cover-scope="full" style="--cover-place-block: center; --cover-place-inline: center; --cover-scrim-image: radial-gradient(ellipse farthest-side at center, rgb(0 0 0 / 0.55) 40%, transparent 100%); --cover-scrim-mask: radial-gradient(ellipse farthest-side at center, #000 50%, transparent 100%)">
  <div data-section="media" data-name="media" class="rf-card__media" data-guest-posture="presentational">
    <img src="https://picsum.photos/seed/gallerycover/800/1000" alt="A coastal scene" />
  </div>
  <div data-name="content" class="rf-card__content" data-color-scheme="dark">
    <div data-name="body" class="rf-card__body">
      <h3 id="centred-hero" data-name="title" class="rf-card__title">Centred hero</h3>
      <p>
        <code>content-place=&quot;center center&quot;</code>
         pins the overlay; the gradient scrim follows as a centred radial spot.
      </p>
    </div>
  </div>
</div>

A recipe uses header scope: the same media-position="cover" switch, but only the title block overlays the image while the ingredients and steps flow below on the page palette:

{% recipe prepTime="PT5M" servings=1 difficulty="easy" media-position="cover" scrim-type="frost" scrim-blur="md" %}
![A tequila sunrise cocktail](https://assets.refrakt.md/tequila-sunrise.png)

---

A cocktail classic

## Tequila Sunrise

A layered showstopper that transitions from deep orange to golden yellow.

- 60ml tequila
- 120ml fresh orange juice
- 15ml grenadine
- Orange slice and cherry to garnish

1. Fill a tall glass with ice; pour in tequila and orange juice. Stir gently.
2. Slowly pour grenadine over the back of a spoon so it sinks.
3. Let the layers settle, then garnish.
{% /recipe %}
<article data-field="content-section" data-rune="recipe" typeof="Recipe" data-rune-fields="{&quot;prepTime&quot;:&quot;PT5M&quot;,&quot;cookTime&quot;:&quot;&quot;,&quot;servings&quot;:&quot;1&quot;,&quot;difficulty&quot;:&quot;easy&quot;,&quot;media-position&quot;:&quot;cover&quot;}">
  <meta content="PT5M" property="prepTime">
  <meta content="1" property="recipeYield">
  <div data-name="media">
    <img src="https://assets.refrakt.md/tequila-sunrise.png" alt="A tequila sunrise cocktail" property="image">
  </div>
  <p data-name="eyebrow">A cocktail classic</p>
  <h2 id="tequila-sunrise" data-name="headline" property="name">Tequila Sunrise</h2>
  <p data-name="blurb" property="description">A layered showstopper that transitions from deep orange to golden yellow.</p>
  <ul data-name="ingredients">
    <li data-name="ingredient" property="recipeIngredient">60ml tequila</li>
    <li data-name="ingredient" property="recipeIngredient">120ml fresh orange juice</li>
    <li data-name="ingredient" property="recipeIngredient">15ml grenadine</li>
    <li data-name="ingredient" property="recipeIngredient">Orange slice and cherry to garnish</li>
  </ul>
  <ol data-name="steps">
    <li data-name="step" typeof="HowToStep" property="recipeInstructions">
      <p property="text">Fill a tall glass with ice; pour in tequila and orange juice. Stir gently.</p>
    </li>
    <li data-name="step" typeof="HowToStep" property="recipeInstructions">
      <p property="text">Slowly pour grenadine over the back of a spoon so it sinks.</p>
    </li>
    <li data-name="step" typeof="HowToStep" property="recipeInstructions">
      <p property="text">Let the layers settle, then garnish.</p>
    </li>
  </ol>
  <meta data-field="scrim-type" content="frost">
  <meta data-field="scrim-blur" content="md">
</article>
A tequila sunrise cocktail

A cocktail classic

Tequila Sunrise

A layered showstopper that transitions from deep orange to golden yellow.

  • 60ml tequila
  • 120ml fresh orange juice
  • 15ml grenadine
  • Orange slice and cherry to garnish
  1. Fill a tall glass with ice; pour in tequila and orange juice. Stir gently.

  2. Slowly pour grenadine over the back of a spoon so it sinks.

  3. Let the layers settle, then garnish.

<article data-field="content-section" typeof="Recipe" class="rf-recipe rf-recipe--easy rf-recipe--cover" data-media-position="cover" data-prep-time="PT5M" data-cook-time="" data-servings="1" data-difficulty="easy" data-scrim-type="frost" data-scrim-blur="md" data-rune="recipe" data-density="full" data-cover-scope="header">
  <div data-name="cover-band" data-color-scheme="dark" class="rf-recipe__cover-band">
    <div data-name="media" class="rf-recipe__media" data-section="media" data-media="cover" data-guest-posture="presentational">
      <img src="https://assets.refrakt.md/tequila-sunrise.png" alt="A tequila sunrise cocktail" property="image" />
    </div>
    <header data-name="preamble" class="rf-recipe__preamble" data-section="preamble">
      <p data-name="eyebrow" class="rf-recipe__eyebrow">A cocktail classic</p>
      <h2 id="tequila-sunrise" data-name="headline" property="name" class="rf-recipe__headline" data-section="title">Tequila Sunrise</h2>
      <p data-name="blurb" property="description" class="rf-recipe__blurb" data-section="description">A layered showstopper that transitions from deep orange to golden yellow.</p>
    </header>
  </div>
  <div data-name="content" class="rf-recipe__content">
    <dl data-name="metadata" data-zone="metadata" data-zone-layout="definition-list" class="rf-recipe__metadata">
      <div data-name="row" data-field="prepTime" class="rf-recipe__row">
        <dt data-meta-label="">Prep</dt>
        <dd data-meta-type="temporal">5m</dd>
      </div>
      <div data-name="row" data-field="servings" class="rf-recipe__row">
        <dt data-meta-label="">Serves</dt>
        <dd data-meta-type="quantity">1</dd>
      </div>
      <div data-name="row" data-field="difficulty" class="rf-recipe__row">
        <dt data-meta-label="">Difficulty</dt>
        <dd>
          <span class="rf-badge" data-meta-type="category" data-meta-sentiment="positive">easy</span>
        </dd>
      </div>
    </dl>
    <ul data-name="ingredients" class="rf-recipe__ingredients">
      <li data-name="ingredient" property="recipeIngredient" class="rf-recipe__ingredient">60ml tequila</li>
      <li data-name="ingredient" property="recipeIngredient" class="rf-recipe__ingredient">120ml fresh orange juice</li>
      <li data-name="ingredient" property="recipeIngredient" class="rf-recipe__ingredient">15ml grenadine</li>
      <li data-name="ingredient" property="recipeIngredient" class="rf-recipe__ingredient">Orange slice and cherry to garnish</li>
    </ul>
    <ol data-name="steps" class="rf-recipe__steps" data-sequence="numbered">
      <li data-name="step" typeof="HowToStep" property="recipeInstructions" class="rf-recipe__step">
        <p property="text">Fill a tall glass with ice; pour in tequila and orange juice. Stir gently.</p>
      </li>
      <li data-name="step" typeof="HowToStep" property="recipeInstructions" class="rf-recipe__step">
        <p property="text">Slowly pour grenadine over the back of a spoon so it sinks.</p>
      </li>
      <li data-name="step" typeof="HowToStep" property="recipeInstructions" class="rf-recipe__step">
        <p property="text">Let the layers settle, then garnish.</p>
      </li>
    </ol>
  </div>
  <meta content="PT5M" property="prepTime" />
  <meta content="1" property="recipeYield" />
</article>

The cover scrim, content-place, and scrim-type are documented on card → cover mode.

Composition

Every dial here composes with a media guest, not just an image — a codegroup, chart, or map in a card's media zone takes the same frame, substrate, and cover treatments. Those patterns (including a displaced codegroup over a substrate, and a linked cover poster whose guest is demoted to a backdrop) live in Media guests; the demotion rule is the interaction-posture contract.

See also