MarketingHero
note

This rune is part of @refrakt-md/marketing. Install with npm install @refrakt-md/marketing and add "@refrakt-md/marketing" to the plugins array in your refrakt.config.json.

Hero

Full-width intro section for the top of a page. Headings and paragraphs become the header, links become action buttons, and code fences become copyable command blocks. The first link is styled as a primary button. For smaller, focused action blocks that can appear anywhere, use CTA instead.

Basic usage

A centered hero section with headline, description, and action buttons.

{% hero %}

Whats new [Version 1.0](#)

# Build with refrakt.md

A content framework that turns Markdown into rich, semantic pages. Write standard Markdown — runes decide how it's interpreted.

- [Get started](/docs/getting-started)
- [View on GitHub](https://github.com/refrakt-md/refrakt)
{% /hero %}
<section data-field="content-section" data-rune="hero" data-rune-fields="{&quot;align&quot;:&quot;center&quot;,&quot;media-position&quot;:&quot;bottom&quot;}">
  <div data-name="content">
    <header>
      <p data-name="eyebrow">
        Whats new
        <a href="#">Version 1.0</a>
      </p>
      <h1 id="build-with-refrakt.md" data-name="headline">Build with refrakt.md</h1>
      <p data-name="blurb">A content framework that turns Markdown into rich, semantic pages. Write standard Markdown — runes decide how it's interpreted.</p>
    </header>
    <div data-name="actions">
      <ul>
        <li data-name="action">
          <a href="/docs/getting-started">
            <span>Get started</span>
          </a>
        </li>
        <li data-name="action">
          <a href="https://github.com/refrakt-md/refrakt">
            <span>View on GitHub</span>
          </a>
        </li>
      </ul>
    </div>
  </div>
</section>

Whats new Version 1.0

Build with refrakt.md

A content framework that turns Markdown into rich, semantic pages. Write standard Markdown — runes decide how it's interpreted.

<section data-field="content-section" class="rf-hero rf-hero--center rf-hero--full" data-media-position="bottom" data-align="center" data-width="full" data-rune="hero" data-density="full">
  <div data-name="content" class="rf-hero__content">
    <header data-name="preamble" class="rf-hero__preamble" data-section="preamble">
      <p data-name="eyebrow" class="rf-hero__eyebrow">
        Whats new 
        <a href="#">Version 1.0</a>
      </p>
      <h1 id="build-with-refrakt.md" data-name="headline" class="rf-hero__headline" data-section="title">Build with refrakt.md</h1>
      <p data-name="blurb" class="rf-hero__blurb" data-section="description">A content framework that turns Markdown into rich, semantic pages. Write standard Markdown — runes decide how it's interpreted.</p>
    </header>
    <div data-name="actions" class="rf-hero__actions">
      <ul>
        <li data-name="action">
          <a href="/docs/getting-started">
            <span>Get started</span>
          </a>
        </li>
        <li data-name="action">
          <a href="https://github.com/refrakt-md/refrakt">
            <span>View on GitHub</span>
          </a>
        </li>
      </ul>
    </div>
  </div>
</section>

With command block

Code fences inside a hero become copyable command blocks — great for install commands on landing pages.

{% hero %}
# Get started in seconds

Scaffold a project and start writing.

```shell
npm create refrakt
```

- [Documentation](/docs/getting-started)
{% /hero %}
<section data-field="content-section" data-rune="hero" data-rune-fields="{&quot;align&quot;:&quot;center&quot;,&quot;media-position&quot;:&quot;bottom&quot;}">
  <div data-name="content">
    <header>
      <h1 id="get-started-in-seconds" data-name="headline">Get started in seconds</h1>
      <p data-name="blurb">Scaffold a project and start writing.</p>
    </header>
    <div data-name="actions">
      <div data-name="command">
        <div class="rf-codeblock" data-name="command">
          <pre data-language="shell">
            <code data-language="shell">npm create refrakt
</code>
          </pre>
        </div>
      </div>
      <ul>
        <li data-name="action">
          <a href="/docs/getting-started">
            <span>Documentation</span>
          </a>
        </li>
      </ul>
    </div>
  </div>
</section>

Get started in seconds

Scaffold a project and start writing.

npm create refrakt
<section data-field="content-section" class="rf-hero rf-hero--center rf-hero--full" data-media-position="bottom" data-align="center" data-width="full" data-rune="hero" data-density="full">
  <div data-name="content" class="rf-hero__content">
    <header data-name="preamble" class="rf-hero__preamble" data-section="preamble">
      <h1 id="get-started-in-seconds" data-name="headline" class="rf-hero__headline" data-section="title">Get started in seconds</h1>
      <p data-name="blurb" class="rf-hero__blurb" data-section="description">Scaffold a project and start writing.</p>
    </header>
    <div data-name="actions" class="rf-hero__actions">
      <div data-name="command" class="rf-hero__command">
        <div class="rf-hero__command rf-codeblock" data-name="command">
          <pre data-language="shell"><code data-language="shell">npm create refrakt
</code></pre>
        </div>
      </div>
      <ul>
        <li data-name="action">
          <a href="/docs/getting-started">
            <span>Documentation</span>
          </a>
        </li>
      </ul>
    </div>
  </div>
</section>

Left-aligned

Use align="left" for a more editorial feel.

{% hero align="left" %}
# Documentation that writes itself

Semantic runes transform your Markdown into structured, accessible content.

- [Quick start](/docs/getting-started)
{% /hero %}
<section data-field="content-section" data-rune="hero" data-rune-fields="{&quot;align&quot;:&quot;left&quot;,&quot;media-position&quot;:&quot;bottom&quot;}">
  <div data-name="content">
    <header>
      <h1 id="documentation-that-writes-itself" data-name="headline">Documentation that writes itself</h1>
      <p data-name="blurb">Semantic runes transform your Markdown into structured, accessible content.</p>
    </header>
    <div data-name="actions">
      <ul>
        <li data-name="action">
          <a href="/docs/getting-started">
            <span>Quick start</span>
          </a>
        </li>
      </ul>
    </div>
  </div>
</section>

Documentation that writes itself

Semantic runes transform your Markdown into structured, accessible content.

<section data-field="content-section" class="rf-hero rf-hero--left rf-hero--full" data-media-position="bottom" data-align="left" data-width="full" data-rune="hero" data-density="full">
  <div data-name="content" class="rf-hero__content">
    <header data-name="preamble" class="rf-hero__preamble" data-section="preamble">
      <h1 id="documentation-that-writes-itself" data-name="headline" class="rf-hero__headline" data-section="title">Documentation that writes itself</h1>
      <p data-name="blurb" class="rf-hero__blurb" data-section="description">Semantic runes transform your Markdown into structured, accessible content.</p>
    </header>
    <div data-name="actions" class="rf-hero__actions">
      <ul>
        <li data-name="action">
          <a href="/docs/getting-started">
            <span>Quick start</span>
          </a>
        </li>
      </ul>
    </div>
  </div>
</section>

Attributes

AttributeTypeDefaultDescription
alignstringcenterHorizontal alignment of headline + body text: left, center, right

Cover — content over a full-bleed backdrop

media-position="cover" turns the media zone into a full-bleed backdrop: the media fills the section interior and the headline, blurb, and actions overlay it. A legibility scrim and a light-on-dark foreground are applied automatically — it's a one-attribute switch on the same content.

{% hero media-position="cover" %}
![Mountain valley at dusk](https://assets.refrakt.md/media-text-valley.jpg)

---

# Documentation that reads like it was designed

Semantic runes turn plain Markdown into structured pages.

- [Get started](/docs/getting-started)
- [Explore the runes](/runes/rune-catalog)
{% /hero %}
<section data-field="content-section" data-rune="hero" data-rune-fields="{&quot;align&quot;:&quot;center&quot;,&quot;media-position&quot;:&quot;cover&quot;}">
  <div data-name="content">
    <header>
      <h1 id="documentation-that-reads-like-it-was-designed" data-name="headline">Documentation that reads like it was designed</h1>
      <p data-name="blurb">Semantic runes turn plain Markdown into structured pages.</p>
    </header>
    <div data-name="actions">
      <ul>
        <li data-name="action">
          <a href="/docs/getting-started">
            <span>Get started</span>
          </a>
        </li>
        <li data-name="action">
          <a href="/runes/rune-catalog">
            <span>Explore the runes</span>
          </a>
        </li>
      </ul>
    </div>
  </div>
  <div data-name="media">
    <img src="https://assets.refrakt.md/media-text-valley.jpg" alt="Mountain valley at dusk">
  </div>
</section>

Documentation that reads like it was designed

Semantic runes turn plain Markdown into structured pages.

Mountain valley at dusk
<section data-field="content-section" class="rf-hero rf-hero--center rf-hero--cover rf-hero--full" data-media-position="cover" data-align="center" data-width="full" data-rune="hero" data-density="full" data-cover-scope="full">
  <div data-name="content" class="rf-hero__content" data-color-scheme="dark">
    <header data-name="preamble" class="rf-hero__preamble" data-section="preamble">
      <h1 id="documentation-that-reads-like-it-was-designed" data-name="headline" class="rf-hero__headline" data-section="title">Documentation that reads like it was designed</h1>
      <p data-name="blurb" class="rf-hero__blurb" data-section="description">Semantic runes turn plain Markdown into structured pages.</p>
    </header>
    <div data-name="actions" class="rf-hero__actions">
      <ul>
        <li data-name="action">
          <a href="/docs/getting-started">
            <span>Get started</span>
          </a>
        </li>
        <li data-name="action">
          <a href="/runes/rune-catalog">
            <span>Explore the runes</span>
          </a>
        </li>
      </ul>
    </div>
  </div>
  <div data-name="media" class="rf-hero__media" data-section="media" data-media="hero" data-guest-posture="presentational">
    <img src="https://assets.refrakt.md/media-text-valley.jpg" alt="Mountain valley at dusk" />
  </div>
</section>

The band's height comes from height (named scale) or aspect (a ratio); with neither, a wide default aspect with a viewport floor applies. content-place anchors the overlay — by default the content sits as a centred band.

Animated background — a live program as the backdrop

The media zone holds any media guest — including a running sandbox. Drop a three.js scene in the media zone and the hero gets an animated background: the sandbox becomes an inert presentational backdrop (no pointer events, no focus stops), the content overlays it, and the scrim keeps the text legible. Here a wireframe terrain rolls in slow swells, its crests picking up the site's own niwaki accent colours:

{% hero media-position="cover" height="lg" %}
{% sandbox src="wireframe-waves" /%}

---

# Markdown in, meaning out

Plain text becomes structured, semantic pages.

- [See how it works](/docs/getting-started)
{% /hero %}
<section data-field="content-section" data-rune="hero" data-rune-fields="{&quot;align&quot;:&quot;center&quot;,&quot;media-position&quot;:&quot;cover&quot;,&quot;height&quot;:&quot;lg&quot;}">
  <div data-name="content">
    <header>
      <h1 id="markdown-in,-meaning-out" data-name="headline">Markdown in, meaning out</h1>
      <p data-name="blurb">Plain text becomes structured, semantic pages.</p>
    </header>
    <div data-name="actions">
      <ul>
        <li data-name="action">
          <a href="/docs/getting-started">
            <span>See how it works</span>
          </a>
        </li>
      </ul>
    </div>
  </div>
  <div data-name="media">
    <rf-sandbox data-rune="sandbox" data-source-content="&lt;div data-source=&quot;HTML&quot;&gt;
&lt;style&gt;
  html, body { height: 100%; margin: 0; overflow: hidden; }
  /* Boot backdrop — the scene fades in over this, so the first paint looks
     designed even before three.js arrives (and remains if it never does). */
  body { background: linear-gradient(rgb(247 246 242) 0%, rgb(236 234 227) 100%); }
  html.dark body, body.dark { background: linear-gradient(rgb(20 20 23) 0%, rgb(13 13 16) 100%); }
  /* Pinned to the iframe viewport, NOT height: 100% — directory-mode sandbox
     content ships inside a plain wrapper div (auto height), which breaks a
     percentage-height chain: the canvas would collapse to its attribute
     height and render as a fixed-size strip at the top of the band. */
  #scene { position: fixed; inset: 0; width: 100%; height: 100%; display: block; opacity: 0; transition: opacity 0.8s ease; }
  #scene.on { opacity: 1; }
  /* No-JS / no-WebGL / blocked-CDN fallback: a few soft horizon lines keep
     the wave suggestion without competing with overlaid hero content. */
  #fallback { display: none; position: fixed; inset: 0; overflow: hidden; }
  #fallback.on { display: block; }
  #fallback i {
    position: absolute; left: -5%; right: -5%; height: 2px; display: block;
    background: linear-gradient(90deg, transparent, var(--c), transparent);
    border-radius: 2px;
  }
&lt;/style&gt;

&lt;canvas id=&quot;scene&quot;&gt;&lt;/canvas&gt;
&lt;div id=&quot;fallback&quot; aria-hidden=&quot;true&quot;&gt;
  &lt;i style=&quot;--c:rgb(138 133 125 / 0.30); top: 58%&quot;&gt;&lt;/i&gt;
  &lt;i style=&quot;--c:rgb(138 133 125 / 0.22); top: 66%; transform: scaleX(0.92)&quot;&gt;&lt;/i&gt;
  &lt;i style=&quot;--c:rgb(61 107 61 / 0.20); top: 74%; transform: scaleX(0.96)&quot;&gt;&lt;/i&gt;
  &lt;i style=&quot;--c:rgb(138 133 125 / 0.16); top: 82%&quot;&gt;&lt;/i&gt;
&lt;/div&gt;

&lt;script type=&quot;module&quot;&gt;
  // ── Wireframe waves (SPEC-101 / WORK-401) ──────────────────────────────
  // The hero backdrop: a vertex-displaced wireframe plane rolling in slow
  // swells — karesansui by way of a vector terrain. Crests pick up a niwaki
  // accent over the stone base. Ambient by contract: the cover posture
  // demotion blocks pointer events, so the scene carries itself with no
  // interaction.

  // Palette of record: packages/lumina/src/presets/niwaki.ts (light/dark pairs).
  // Base = ishi (stone); crest accent = matsu (light) / wakaba (dark).
  const NIWAKI = {
    light: { base: 0x8a857d, crest: 0x3d6b3d, fog: 0xeceae3, opacity: 0.5 },
    dark:  { base: 0x7d7062, crest: 0xb3d475, fog: 0x101013, opacity: 0.55 },
  };

  const dark =
    document.documentElement.classList.contains('dark') ||
    document.body.classList.contains('dark');
  const P = dark ? NIWAKI.dark : NIWAKI.light;
  const reduce = matchMedia('(prefers-reduced-motion: reduce)').matches;
  const canvas = document.getElementById('scene');
  const showFallback = () =&gt; {
    canvas.style.display = 'none';
    document.getElementById('fallback').classList.add('on');
  };

  try {
    // Version-pinned for reproducibility.
    const THREE = await import('https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js');

    const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: true });
    // Backdrop budget: cap the pixel ratio — the scrim sits over us anyway.
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 1.5));

    const scene = new THREE.Scene();
    // Fog fades the far edge into the CSS backdrop, so the grid has a horizon
    // instead of a hard geometric edge.
    scene.fog = new THREE.Fog(P.fog, 9, 26);
    const camera = new THREE.PerspectiveCamera(45, 1, 0.1, 100);
    camera.position.set(0, 2.4, 9.5);
    camera.lookAt(0, 0.2, 0);

    // ── The displaced plane ──
    const SEG_X = 88, SEG_Y = 46;
    const geo = new THREE.PlaneGeometry(38, 22, SEG_X, SEG_Y);
    geo.rotateX(-Math.PI / 2);
    const count = geo.attributes.position.count;
    const colors = new Float32Array(count * 3);
    geo.setAttribute('color', new THREE.BufferAttribute(colors, 3));
    const base = new THREE.Color(P.base);
    const crest = new THREE.Color(P.crest);
    const tmp = new THREE.Color();

    const mat = new THREE.MeshBasicMaterial({
      wireframe: true, vertexColors: true,
      transparent: true, opacity: P.opacity,
      fog: true, depthWrite: false,
    });
    const mesh = new THREE.Mesh(geo, mat);
    mesh.position.y = -0.6;
    scene.add(mesh);

    // Swell: a few travelling sines at different scales — cheap, organic, no
    // noise library. Amplitude stays modest; this is a ground, not a storm.
    const AMP = 0.9;
    function heightAt(x, z, t) {
      return AMP * (
        0.45 * Math.sin(x * 0.32 + t * 0.50) * Math.cos(z * 0.28 + t * 0.32)
        + 0.30 * Math.sin((x + z) * 0.18 - t * 0.40)
        + 0.15 * Math.sin(x * 0.85 + t * 0.90) * Math.sin(z * 0.55 - t * 0.55)
      );
    }
    function displace(t) {
      const pos = geo.attributes.position;
      for (let i = 0; i &lt; count; i++) {
        const x = pos.getX(i), z = pos.getZ(i);
        const h = heightAt(x, z, t);
        pos.setY(i, h);
        // Crest tint: 0 at the troughs, accent at the peaks.
        const k = Math.min(Math.max((h / AMP + 1) / 2, 0), 1);
        tmp.copy(base).lerp(crest, k * k); // square biases the accent to true crests
        colors[i * 3] = tmp.r;
        colors[i * 3 + 1] = tmp.g;
        colors[i * 3 + 2] = tmp.b;
      }
      pos.needsUpdate = true;
      geo.attributes.color.needsUpdate = true;
    }

    function resize() {
      const w = canvas.clientWidth, h = canvas.clientHeight;
      if (!w || !h) return;
      renderer.setSize(w, h, false);
      camera.aspect = w / h;
      camera.updateProjectionMatrix();
    }
    resize();
    window.addEventListener('resize', resize);

    canvas.classList.add('on');

    if (reduce) {
      // Reduced motion: one composed static frame — a mid-swell moment.
      displace(2.4);
      renderer.render(scene, camera);
    } else {
      // The RAF loop pauses with the tab — a backdrop must not drain a
      // backgrounded battery.
      let raf = 0;
      let t = 0;
      let last = performance.now();
      function loop(now) {
        const dt = Math.min((now - last) / 1000, 0.05);
        last = now;
        t += dt;
        displace(t);
        renderer.render(scene, camera);
        raf = requestAnimationFrame(loop);
      }
      raf = requestAnimationFrame(loop);
      document.addEventListener('visibilitychange', () =&gt; {
        if (document.hidden) {
          cancelAnimationFrame(raf);
          raf = 0;
        } else if (!raf) {
          last = performance.now();
          raf = requestAnimationFrame(loop);
        }
      });
    }
  } catch (err) {
    // CDN unreachable / WebGL unavailable → the quiet CSS horizon.
    showFallback();
  }
&lt;/script&gt;

&lt;/div&gt;" data-height="auto" data-source-origins="HTML	wireframe-waves/index.html" data-security-mode="trusted" data-allow-js="true">
      <template data-content="fallback">
        <pre data-language="html">
          <code data-language="html">&lt;div data-source=&quot;HTML&quot;&gt;
&lt;style&gt;
  html, body { height: 100%; margin: 0; overflow: hidden; }
  /* Boot backdrop — the scene fades in over this, so the first paint looks
     designed even before three.js arrives (and remains if it never does). */
  body { background: linear-gradient(rgb(247 246 242) 0%, rgb(236 234 227) 100%); }
  html.dark body, body.dark { background: linear-gradient(rgb(20 20 23) 0%, rgb(13 13 16) 100%); }
  /* Pinned to the iframe viewport, NOT height: 100% — directory-mode sandbox
     content ships inside a plain wrapper div (auto height), which breaks a
     percentage-height chain: the canvas would collapse to its attribute
     height and render as a fixed-size strip at the top of the band. */
  #scene { position: fixed; inset: 0; width: 100%; height: 100%; display: block; opacity: 0; transition: opacity 0.8s ease; }
  #scene.on { opacity: 1; }
  /* No-JS / no-WebGL / blocked-CDN fallback: a few soft horizon lines keep
     the wave suggestion without competing with overlaid hero content. */
  #fallback { display: none; position: fixed; inset: 0; overflow: hidden; }
  #fallback.on { display: block; }
  #fallback i {
    position: absolute; left: -5%; right: -5%; height: 2px; display: block;
    background: linear-gradient(90deg, transparent, var(--c), transparent);
    border-radius: 2px;
  }
&lt;/style&gt;

&lt;canvas id=&quot;scene&quot;&gt;&lt;/canvas&gt;
&lt;div id=&quot;fallback&quot; aria-hidden=&quot;true&quot;&gt;
  &lt;i style=&quot;--c:rgb(138 133 125 / 0.30); top: 58%&quot;&gt;&lt;/i&gt;
  &lt;i style=&quot;--c:rgb(138 133 125 / 0.22); top: 66%; transform: scaleX(0.92)&quot;&gt;&lt;/i&gt;
  &lt;i style=&quot;--c:rgb(61 107 61 / 0.20); top: 74%; transform: scaleX(0.96)&quot;&gt;&lt;/i&gt;
  &lt;i style=&quot;--c:rgb(138 133 125 / 0.16); top: 82%&quot;&gt;&lt;/i&gt;
&lt;/div&gt;

&lt;script type=&quot;module&quot;&gt;
  // ── Wireframe waves (SPEC-101 / WORK-401) ──────────────────────────────
  // The hero backdrop: a vertex-displaced wireframe plane rolling in slow
  // swells — karesansui by way of a vector terrain. Crests pick up a niwaki
  // accent over the stone base. Ambient by contract: the cover posture
  // demotion blocks pointer events, so the scene carries itself with no
  // interaction.

  // Palette of record: packages/lumina/src/presets/niwaki.ts (light/dark pairs).
  // Base = ishi (stone); crest accent = matsu (light) / wakaba (dark).
  const NIWAKI = {
    light: { base: 0x8a857d, crest: 0x3d6b3d, fog: 0xeceae3, opacity: 0.5 },
    dark:  { base: 0x7d7062, crest: 0xb3d475, fog: 0x101013, opacity: 0.55 },
  };

  const dark =
    document.documentElement.classList.contains('dark') ||
    document.body.classList.contains('dark');
  const P = dark ? NIWAKI.dark : NIWAKI.light;
  const reduce = matchMedia('(prefers-reduced-motion: reduce)').matches;
  const canvas = document.getElementById('scene');
  const showFallback = () =&gt; {
    canvas.style.display = 'none';
    document.getElementById('fallback').classList.add('on');
  };

  try {
    // Version-pinned for reproducibility.
    const THREE = await import('https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js');

    const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: true });
    // Backdrop budget: cap the pixel ratio — the scrim sits over us anyway.
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 1.5));

    const scene = new THREE.Scene();
    // Fog fades the far edge into the CSS backdrop, so the grid has a horizon
    // instead of a hard geometric edge.
    scene.fog = new THREE.Fog(P.fog, 9, 26);
    const camera = new THREE.PerspectiveCamera(45, 1, 0.1, 100);
    camera.position.set(0, 2.4, 9.5);
    camera.lookAt(0, 0.2, 0);

    // ── The displaced plane ──
    const SEG_X = 88, SEG_Y = 46;
    const geo = new THREE.PlaneGeometry(38, 22, SEG_X, SEG_Y);
    geo.rotateX(-Math.PI / 2);
    const count = geo.attributes.position.count;
    const colors = new Float32Array(count * 3);
    geo.setAttribute('color', new THREE.BufferAttribute(colors, 3));
    const base = new THREE.Color(P.base);
    const crest = new THREE.Color(P.crest);
    const tmp = new THREE.Color();

    const mat = new THREE.MeshBasicMaterial({
      wireframe: true, vertexColors: true,
      transparent: true, opacity: P.opacity,
      fog: true, depthWrite: false,
    });
    const mesh = new THREE.Mesh(geo, mat);
    mesh.position.y = -0.6;
    scene.add(mesh);

    // Swell: a few travelling sines at different scales — cheap, organic, no
    // noise library. Amplitude stays modest; this is a ground, not a storm.
    const AMP = 0.9;
    function heightAt(x, z, t) {
      return AMP * (
        0.45 * Math.sin(x * 0.32 + t * 0.50) * Math.cos(z * 0.28 + t * 0.32)
        + 0.30 * Math.sin((x + z) * 0.18 - t * 0.40)
        + 0.15 * Math.sin(x * 0.85 + t * 0.90) * Math.sin(z * 0.55 - t * 0.55)
      );
    }
    function displace(t) {
      const pos = geo.attributes.position;
      for (let i = 0; i &lt; count; i++) {
        const x = pos.getX(i), z = pos.getZ(i);
        const h = heightAt(x, z, t);
        pos.setY(i, h);
        // Crest tint: 0 at the troughs, accent at the peaks.
        const k = Math.min(Math.max((h / AMP + 1) / 2, 0), 1);
        tmp.copy(base).lerp(crest, k * k); // square biases the accent to true crests
        colors[i * 3] = tmp.r;
        colors[i * 3 + 1] = tmp.g;
        colors[i * 3 + 2] = tmp.b;
      }
      pos.needsUpdate = true;
      geo.attributes.color.needsUpdate = true;
    }

    function resize() {
      const w = canvas.clientWidth, h = canvas.clientHeight;
      if (!w || !h) return;
      renderer.setSize(w, h, false);
      camera.aspect = w / h;
      camera.updateProjectionMatrix();
    }
    resize();
    window.addEventListener('resize', resize);

    canvas.classList.add('on');

    if (reduce) {
      // Reduced motion: one composed static frame — a mid-swell moment.
      displace(2.4);
      renderer.render(scene, camera);
    } else {
      // The RAF loop pauses with the tab — a backdrop must not drain a
      // backgrounded battery.
      let raf = 0;
      let t = 0;
      let last = performance.now();
      function loop(now) {
        const dt = Math.min((now - last) / 1000, 0.05);
        last = now;
        t += dt;
        displace(t);
        renderer.render(scene, camera);
        raf = requestAnimationFrame(loop);
      }
      raf = requestAnimationFrame(loop);
      document.addEventListener('visibilitychange', () =&gt; {
        if (document.hidden) {
          cancelAnimationFrame(raf);
          raf = 0;
        } else if (!raf) {
          last = performance.now();
          raf = requestAnimationFrame(loop);
        }
      });
    }
  } catch (err) {
    // CDN unreachable / WebGL unavailable → the quiet CSS horizon.
    showFallback();
  }
&lt;/script&gt;

&lt;/div&gt;</code>
        </pre>
      </template>
      <template data-content="source">&lt;div data-source=&quot;HTML&quot;&gt;
&lt;style&gt;
  html, body { height: 100%; margin: 0; overflow: hidden; }
  /* Boot backdrop — the scene fades in over this, so the first paint looks
     designed even before three.js arrives (and remains if it never does). */
  body { background: linear-gradient(rgb(247 246 242) 0%, rgb(236 234 227) 100%); }
  html.dark body, body.dark { background: linear-gradient(rgb(20 20 23) 0%, rgb(13 13 16) 100%); }
  /* Pinned to the iframe viewport, NOT height: 100% — directory-mode sandbox
     content ships inside a plain wrapper div (auto height), which breaks a
     percentage-height chain: the canvas would collapse to its attribute
     height and render as a fixed-size strip at the top of the band. */
  #scene { position: fixed; inset: 0; width: 100%; height: 100%; display: block; opacity: 0; transition: opacity 0.8s ease; }
  #scene.on { opacity: 1; }
  /* No-JS / no-WebGL / blocked-CDN fallback: a few soft horizon lines keep
     the wave suggestion without competing with overlaid hero content. */
  #fallback { display: none; position: fixed; inset: 0; overflow: hidden; }
  #fallback.on { display: block; }
  #fallback i {
    position: absolute; left: -5%; right: -5%; height: 2px; display: block;
    background: linear-gradient(90deg, transparent, var(--c), transparent);
    border-radius: 2px;
  }
&lt;/style&gt;

&lt;canvas id=&quot;scene&quot;&gt;&lt;/canvas&gt;
&lt;div id=&quot;fallback&quot; aria-hidden=&quot;true&quot;&gt;
  &lt;i style=&quot;--c:rgb(138 133 125 / 0.30); top: 58%&quot;&gt;&lt;/i&gt;
  &lt;i style=&quot;--c:rgb(138 133 125 / 0.22); top: 66%; transform: scaleX(0.92)&quot;&gt;&lt;/i&gt;
  &lt;i style=&quot;--c:rgb(61 107 61 / 0.20); top: 74%; transform: scaleX(0.96)&quot;&gt;&lt;/i&gt;
  &lt;i style=&quot;--c:rgb(138 133 125 / 0.16); top: 82%&quot;&gt;&lt;/i&gt;
&lt;/div&gt;

&lt;script type=&quot;module&quot;&gt;
  // ── Wireframe waves (SPEC-101 / WORK-401) ──────────────────────────────
  // The hero backdrop: a vertex-displaced wireframe plane rolling in slow
  // swells — karesansui by way of a vector terrain. Crests pick up a niwaki
  // accent over the stone base. Ambient by contract: the cover posture
  // demotion blocks pointer events, so the scene carries itself with no
  // interaction.

  // Palette of record: packages/lumina/src/presets/niwaki.ts (light/dark pairs).
  // Base = ishi (stone); crest accent = matsu (light) / wakaba (dark).
  const NIWAKI = {
    light: { base: 0x8a857d, crest: 0x3d6b3d, fog: 0xeceae3, opacity: 0.5 },
    dark:  { base: 0x7d7062, crest: 0xb3d475, fog: 0x101013, opacity: 0.55 },
  };

  const dark =
    document.documentElement.classList.contains('dark') ||
    document.body.classList.contains('dark');
  const P = dark ? NIWAKI.dark : NIWAKI.light;
  const reduce = matchMedia('(prefers-reduced-motion: reduce)').matches;
  const canvas = document.getElementById('scene');
  const showFallback = () =&gt; {
    canvas.style.display = 'none';
    document.getElementById('fallback').classList.add('on');
  };

  try {
    // Version-pinned for reproducibility.
    const THREE = await import('https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js');

    const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: true });
    // Backdrop budget: cap the pixel ratio — the scrim sits over us anyway.
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 1.5));

    const scene = new THREE.Scene();
    // Fog fades the far edge into the CSS backdrop, so the grid has a horizon
    // instead of a hard geometric edge.
    scene.fog = new THREE.Fog(P.fog, 9, 26);
    const camera = new THREE.PerspectiveCamera(45, 1, 0.1, 100);
    camera.position.set(0, 2.4, 9.5);
    camera.lookAt(0, 0.2, 0);

    // ── The displaced plane ──
    const SEG_X = 88, SEG_Y = 46;
    const geo = new THREE.PlaneGeometry(38, 22, SEG_X, SEG_Y);
    geo.rotateX(-Math.PI / 2);
    const count = geo.attributes.position.count;
    const colors = new Float32Array(count * 3);
    geo.setAttribute('color', new THREE.BufferAttribute(colors, 3));
    const base = new THREE.Color(P.base);
    const crest = new THREE.Color(P.crest);
    const tmp = new THREE.Color();

    const mat = new THREE.MeshBasicMaterial({
      wireframe: true, vertexColors: true,
      transparent: true, opacity: P.opacity,
      fog: true, depthWrite: false,
    });
    const mesh = new THREE.Mesh(geo, mat);
    mesh.position.y = -0.6;
    scene.add(mesh);

    // Swell: a few travelling sines at different scales — cheap, organic, no
    // noise library. Amplitude stays modest; this is a ground, not a storm.
    const AMP = 0.9;
    function heightAt(x, z, t) {
      return AMP * (
        0.45 * Math.sin(x * 0.32 + t * 0.50) * Math.cos(z * 0.28 + t * 0.32)
        + 0.30 * Math.sin((x + z) * 0.18 - t * 0.40)
        + 0.15 * Math.sin(x * 0.85 + t * 0.90) * Math.sin(z * 0.55 - t * 0.55)
      );
    }
    function displace(t) {
      const pos = geo.attributes.position;
      for (let i = 0; i &lt; count; i++) {
        const x = pos.getX(i), z = pos.getZ(i);
        const h = heightAt(x, z, t);
        pos.setY(i, h);
        // Crest tint: 0 at the troughs, accent at the peaks.
        const k = Math.min(Math.max((h / AMP + 1) / 2, 0), 1);
        tmp.copy(base).lerp(crest, k * k); // square biases the accent to true crests
        colors[i * 3] = tmp.r;
        colors[i * 3 + 1] = tmp.g;
        colors[i * 3 + 2] = tmp.b;
      }
      pos.needsUpdate = true;
      geo.attributes.color.needsUpdate = true;
    }

    function resize() {
      const w = canvas.clientWidth, h = canvas.clientHeight;
      if (!w || !h) return;
      renderer.setSize(w, h, false);
      camera.aspect = w / h;
      camera.updateProjectionMatrix();
    }
    resize();
    window.addEventListener('resize', resize);

    canvas.classList.add('on');

    if (reduce) {
      // Reduced motion: one composed static frame — a mid-swell moment.
      displace(2.4);
      renderer.render(scene, camera);
    } else {
      // The RAF loop pauses with the tab — a backdrop must not drain a
      // backgrounded battery.
      let raf = 0;
      let t = 0;
      let last = performance.now();
      function loop(now) {
        const dt = Math.min((now - last) / 1000, 0.05);
        last = now;
        t += dt;
        displace(t);
        renderer.render(scene, camera);
        raf = requestAnimationFrame(loop);
      }
      raf = requestAnimationFrame(loop);
      document.addEventListener('visibilitychange', () =&gt; {
        if (document.hidden) {
          cancelAnimationFrame(raf);
          raf = 0;
        } else if (!raf) {
          last = performance.now();
          raf = requestAnimationFrame(loop);
        }
      });
    }
  } catch (err) {
    // CDN unreachable / WebGL unavailable → the quiet CSS horizon.
    showFallback();
  }
&lt;/script&gt;

&lt;/div&gt;</template>
    </rf-sandbox>
  </div>
</section>

Markdown in, meaning out

Plain text becomes structured, semantic pages.

<section data-field="content-section" class="rf-hero rf-hero--center rf-hero--cover rf-hero--full" data-media-position="cover" data-align="center" data-height="lg" data-width="full" data-rune="hero" data-density="full" data-cover-scope="full">
  <div data-name="content" class="rf-hero__content" data-color-scheme="dark">
    <header data-name="preamble" class="rf-hero__preamble" data-section="preamble">
      <h1 id="markdown-in,-meaning-out" data-name="headline" class="rf-hero__headline" data-section="title">Markdown in, meaning out</h1>
      <p data-name="blurb" class="rf-hero__blurb" data-section="description">Plain text becomes structured, semantic pages.</p>
    </header>
    <div data-name="actions" class="rf-hero__actions">
      <ul>
        <li data-name="action">
          <a href="/docs/getting-started">
            <span>See how it works</span>
          </a>
        </li>
      </ul>
    </div>
  </div>
  <div data-name="media" class="rf-hero__media" data-section="media" data-media="hero" data-guest-posture="presentational">
    <rf-sandbox class="rf-sandbox" data-source-content="&lt;div data-source=&quot;HTML&quot;&gt;
&lt;style&gt;
  html, body { height: 100%; margin: 0; overflow: hidden; }
  /* Boot backdrop — the scene fades in over this, so the first paint looks
     designed even before three.js arrives (and remains if it never does). */
  body { background: linear-gradient(rgb(247 246 242) 0%, rgb(236 234 227) 100%); }
  html.dark body, body.dark { background: linear-gradient(rgb(20 20 23) 0%, rgb(13 13 16) 100%); }
  /* Pinned to the iframe viewport, NOT height: 100% — directory-mode sandbox
     content ships inside a plain wrapper div (auto height), which breaks a
     percentage-height chain: the canvas would collapse to its attribute
     height and render as a fixed-size strip at the top of the band. */
  #scene { position: fixed; inset: 0; width: 100%; height: 100%; display: block; opacity: 0; transition: opacity 0.8s ease; }
  #scene.on { opacity: 1; }
  /* No-JS / no-WebGL / blocked-CDN fallback: a few soft horizon lines keep
     the wave suggestion without competing with overlaid hero content. */
  #fallback { display: none; position: fixed; inset: 0; overflow: hidden; }
  #fallback.on { display: block; }
  #fallback i {
    position: absolute; left: -5%; right: -5%; height: 2px; display: block;
    background: linear-gradient(90deg, transparent, var(--c), transparent);
    border-radius: 2px;
  }
&lt;/style&gt;

&lt;canvas id=&quot;scene&quot;&gt;&lt;/canvas&gt;
&lt;div id=&quot;fallback&quot; aria-hidden=&quot;true&quot;&gt;
  &lt;i style=&quot;--c:rgb(138 133 125 / 0.30); top: 58%&quot;&gt;&lt;/i&gt;
  &lt;i style=&quot;--c:rgb(138 133 125 / 0.22); top: 66%; transform: scaleX(0.92)&quot;&gt;&lt;/i&gt;
  &lt;i style=&quot;--c:rgb(61 107 61 / 0.20); top: 74%; transform: scaleX(0.96)&quot;&gt;&lt;/i&gt;
  &lt;i style=&quot;--c:rgb(138 133 125 / 0.16); top: 82%&quot;&gt;&lt;/i&gt;
&lt;/div&gt;

&lt;script type=&quot;module&quot;&gt;
  // ── Wireframe waves (SPEC-101 / WORK-401) ──────────────────────────────
  // The hero backdrop: a vertex-displaced wireframe plane rolling in slow
  // swells — karesansui by way of a vector terrain. Crests pick up a niwaki
  // accent over the stone base. Ambient by contract: the cover posture
  // demotion blocks pointer events, so the scene carries itself with no
  // interaction.

  // Palette of record: packages/lumina/src/presets/niwaki.ts (light/dark pairs).
  // Base = ishi (stone); crest accent = matsu (light) / wakaba (dark).
  const NIWAKI = {
    light: { base: 0x8a857d, crest: 0x3d6b3d, fog: 0xeceae3, opacity: 0.5 },
    dark:  { base: 0x7d7062, crest: 0xb3d475, fog: 0x101013, opacity: 0.55 },
  };

  const dark =
    document.documentElement.classList.contains('dark') ||
    document.body.classList.contains('dark');
  const P = dark ? NIWAKI.dark : NIWAKI.light;
  const reduce = matchMedia('(prefers-reduced-motion: reduce)').matches;
  const canvas = document.getElementById('scene');
  const showFallback = () =&gt; {
    canvas.style.display = 'none';
    document.getElementById('fallback').classList.add('on');
  };

  try {
    // Version-pinned for reproducibility.
    const THREE = await import('https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js');

    const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: true });
    // Backdrop budget: cap the pixel ratio — the scrim sits over us anyway.
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 1.5));

    const scene = new THREE.Scene();
    // Fog fades the far edge into the CSS backdrop, so the grid has a horizon
    // instead of a hard geometric edge.
    scene.fog = new THREE.Fog(P.fog, 9, 26);
    const camera = new THREE.PerspectiveCamera(45, 1, 0.1, 100);
    camera.position.set(0, 2.4, 9.5);
    camera.lookAt(0, 0.2, 0);

    // ── The displaced plane ──
    const SEG_X = 88, SEG_Y = 46;
    const geo = new THREE.PlaneGeometry(38, 22, SEG_X, SEG_Y);
    geo.rotateX(-Math.PI / 2);
    const count = geo.attributes.position.count;
    const colors = new Float32Array(count * 3);
    geo.setAttribute('color', new THREE.BufferAttribute(colors, 3));
    const base = new THREE.Color(P.base);
    const crest = new THREE.Color(P.crest);
    const tmp = new THREE.Color();

    const mat = new THREE.MeshBasicMaterial({
      wireframe: true, vertexColors: true,
      transparent: true, opacity: P.opacity,
      fog: true, depthWrite: false,
    });
    const mesh = new THREE.Mesh(geo, mat);
    mesh.position.y = -0.6;
    scene.add(mesh);

    // Swell: a few travelling sines at different scales — cheap, organic, no
    // noise library. Amplitude stays modest; this is a ground, not a storm.
    const AMP = 0.9;
    function heightAt(x, z, t) {
      return AMP * (
        0.45 * Math.sin(x * 0.32 + t * 0.50) * Math.cos(z * 0.28 + t * 0.32)
        + 0.30 * Math.sin((x + z) * 0.18 - t * 0.40)
        + 0.15 * Math.sin(x * 0.85 + t * 0.90) * Math.sin(z * 0.55 - t * 0.55)
      );
    }
    function displace(t) {
      const pos = geo.attributes.position;
      for (let i = 0; i &lt; count; i++) {
        const x = pos.getX(i), z = pos.getZ(i);
        const h = heightAt(x, z, t);
        pos.setY(i, h);
        // Crest tint: 0 at the troughs, accent at the peaks.
        const k = Math.min(Math.max((h / AMP + 1) / 2, 0), 1);
        tmp.copy(base).lerp(crest, k * k); // square biases the accent to true crests
        colors[i * 3] = tmp.r;
        colors[i * 3 + 1] = tmp.g;
        colors[i * 3 + 2] = tmp.b;
      }
      pos.needsUpdate = true;
      geo.attributes.color.needsUpdate = true;
    }

    function resize() {
      const w = canvas.clientWidth, h = canvas.clientHeight;
      if (!w || !h) return;
      renderer.setSize(w, h, false);
      camera.aspect = w / h;
      camera.updateProjectionMatrix();
    }
    resize();
    window.addEventListener('resize', resize);

    canvas.classList.add('on');

    if (reduce) {
      // Reduced motion: one composed static frame — a mid-swell moment.
      displace(2.4);
      renderer.render(scene, camera);
    } else {
      // The RAF loop pauses with the tab — a backdrop must not drain a
      // backgrounded battery.
      let raf = 0;
      let t = 0;
      let last = performance.now();
      function loop(now) {
        const dt = Math.min((now - last) / 1000, 0.05);
        last = now;
        t += dt;
        displace(t);
        renderer.render(scene, camera);
        raf = requestAnimationFrame(loop);
      }
      raf = requestAnimationFrame(loop);
      document.addEventListener('visibilitychange', () =&gt; {
        if (document.hidden) {
          cancelAnimationFrame(raf);
          raf = 0;
        } else if (!raf) {
          last = performance.now();
          raf = requestAnimationFrame(loop);
        }
      });
    }
  } catch (err) {
    // CDN unreachable / WebGL unavailable → the quiet CSS horizon.
    showFallback();
  }
&lt;/script&gt;

&lt;/div&gt;" data-height="fill" data-source-origins="HTML	wireframe-waves/index.html" data-security-mode="trusted" data-allow-js="true" data-rune="sandbox" data-density="compact">
      <template data-content="fallback">
        <pre data-language="html"><code data-language="html">&lt;div data-source=&quot;HTML&quot;&gt;
&lt;style&gt;
  html, body { height: 100%; margin: 0; overflow: hidden; }
  /* Boot backdrop — the scene fades in over this, so the first paint looks
     designed even before three.js arrives (and remains if it never does). */
  body { background: linear-gradient(rgb(247 246 242) 0%, rgb(236 234 227) 100%); }
  html.dark body, body.dark { background: linear-gradient(rgb(20 20 23) 0%, rgb(13 13 16) 100%); }
  /* Pinned to the iframe viewport, NOT height: 100% — directory-mode sandbox
     content ships inside a plain wrapper div (auto height), which breaks a
     percentage-height chain: the canvas would collapse to its attribute
     height and render as a fixed-size strip at the top of the band. */
  #scene { position: fixed; inset: 0; width: 100%; height: 100%; display: block; opacity: 0; transition: opacity 0.8s ease; }
  #scene.on { opacity: 1; }
  /* No-JS / no-WebGL / blocked-CDN fallback: a few soft horizon lines keep
     the wave suggestion without competing with overlaid hero content. */
  #fallback { display: none; position: fixed; inset: 0; overflow: hidden; }
  #fallback.on { display: block; }
  #fallback i {
    position: absolute; left: -5%; right: -5%; height: 2px; display: block;
    background: linear-gradient(90deg, transparent, var(--c), transparent);
    border-radius: 2px;
  }
&lt;/style&gt;

&lt;canvas id=&quot;scene&quot;&gt;&lt;/canvas&gt;
&lt;div id=&quot;fallback&quot; aria-hidden=&quot;true&quot;&gt;
  &lt;i style=&quot;--c:rgb(138 133 125 / 0.30); top: 58%&quot;&gt;&lt;/i&gt;
  &lt;i style=&quot;--c:rgb(138 133 125 / 0.22); top: 66%; transform: scaleX(0.92)&quot;&gt;&lt;/i&gt;
  &lt;i style=&quot;--c:rgb(61 107 61 / 0.20); top: 74%; transform: scaleX(0.96)&quot;&gt;&lt;/i&gt;
  &lt;i style=&quot;--c:rgb(138 133 125 / 0.16); top: 82%&quot;&gt;&lt;/i&gt;
&lt;/div&gt;

&lt;script type=&quot;module&quot;&gt;
  // ── Wireframe waves (SPEC-101 / WORK-401) ──────────────────────────────
  // The hero backdrop: a vertex-displaced wireframe plane rolling in slow
  // swells — karesansui by way of a vector terrain. Crests pick up a niwaki
  // accent over the stone base. Ambient by contract: the cover posture
  // demotion blocks pointer events, so the scene carries itself with no
  // interaction.

  // Palette of record: packages/lumina/src/presets/niwaki.ts (light/dark pairs).
  // Base = ishi (stone); crest accent = matsu (light) / wakaba (dark).
  const NIWAKI = {
    light: { base: 0x8a857d, crest: 0x3d6b3d, fog: 0xeceae3, opacity: 0.5 },
    dark:  { base: 0x7d7062, crest: 0xb3d475, fog: 0x101013, opacity: 0.55 },
  };

  const dark =
    document.documentElement.classList.contains('dark') ||
    document.body.classList.contains('dark');
  const P = dark ? NIWAKI.dark : NIWAKI.light;
  const reduce = matchMedia('(prefers-reduced-motion: reduce)').matches;
  const canvas = document.getElementById('scene');
  const showFallback = () =&gt; {
    canvas.style.display = 'none';
    document.getElementById('fallback').classList.add('on');
  };

  try {
    // Version-pinned for reproducibility.
    const THREE = await import('https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js');

    const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: true });
    // Backdrop budget: cap the pixel ratio — the scrim sits over us anyway.
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 1.5));

    const scene = new THREE.Scene();
    // Fog fades the far edge into the CSS backdrop, so the grid has a horizon
    // instead of a hard geometric edge.
    scene.fog = new THREE.Fog(P.fog, 9, 26);
    const camera = new THREE.PerspectiveCamera(45, 1, 0.1, 100);
    camera.position.set(0, 2.4, 9.5);
    camera.lookAt(0, 0.2, 0);

    // ── The displaced plane ──
    const SEG_X = 88, SEG_Y = 46;
    const geo = new THREE.PlaneGeometry(38, 22, SEG_X, SEG_Y);
    geo.rotateX(-Math.PI / 2);
    const count = geo.attributes.position.count;
    const colors = new Float32Array(count * 3);
    geo.setAttribute('color', new THREE.BufferAttribute(colors, 3));
    const base = new THREE.Color(P.base);
    const crest = new THREE.Color(P.crest);
    const tmp = new THREE.Color();

    const mat = new THREE.MeshBasicMaterial({
      wireframe: true, vertexColors: true,
      transparent: true, opacity: P.opacity,
      fog: true, depthWrite: false,
    });
    const mesh = new THREE.Mesh(geo, mat);
    mesh.position.y = -0.6;
    scene.add(mesh);

    // Swell: a few travelling sines at different scales — cheap, organic, no
    // noise library. Amplitude stays modest; this is a ground, not a storm.
    const AMP = 0.9;
    function heightAt(x, z, t) {
      return AMP * (
        0.45 * Math.sin(x * 0.32 + t * 0.50) * Math.cos(z * 0.28 + t * 0.32)
        + 0.30 * Math.sin((x + z) * 0.18 - t * 0.40)
        + 0.15 * Math.sin(x * 0.85 + t * 0.90) * Math.sin(z * 0.55 - t * 0.55)
      );
    }
    function displace(t) {
      const pos = geo.attributes.position;
      for (let i = 0; i &lt; count; i++) {
        const x = pos.getX(i), z = pos.getZ(i);
        const h = heightAt(x, z, t);
        pos.setY(i, h);
        // Crest tint: 0 at the troughs, accent at the peaks.
        const k = Math.min(Math.max((h / AMP + 1) / 2, 0), 1);
        tmp.copy(base).lerp(crest, k * k); // square biases the accent to true crests
        colors[i * 3] = tmp.r;
        colors[i * 3 + 1] = tmp.g;
        colors[i * 3 + 2] = tmp.b;
      }
      pos.needsUpdate = true;
      geo.attributes.color.needsUpdate = true;
    }

    function resize() {
      const w = canvas.clientWidth, h = canvas.clientHeight;
      if (!w || !h) return;
      renderer.setSize(w, h, false);
      camera.aspect = w / h;
      camera.updateProjectionMatrix();
    }
    resize();
    window.addEventListener('resize', resize);

    canvas.classList.add('on');

    if (reduce) {
      // Reduced motion: one composed static frame — a mid-swell moment.
      displace(2.4);
      renderer.render(scene, camera);
    } else {
      // The RAF loop pauses with the tab — a backdrop must not drain a
      // backgrounded battery.
      let raf = 0;
      let t = 0;
      let last = performance.now();
      function loop(now) {
        const dt = Math.min((now - last) / 1000, 0.05);
        last = now;
        t += dt;
        displace(t);
        renderer.render(scene, camera);
        raf = requestAnimationFrame(loop);
      }
      raf = requestAnimationFrame(loop);
      document.addEventListener('visibilitychange', () =&gt; {
        if (document.hidden) {
          cancelAnimationFrame(raf);
          raf = 0;
        } else if (!raf) {
          last = performance.now();
          raf = requestAnimationFrame(loop);
        }
      });
    }
  } catch (err) {
    // CDN unreachable / WebGL unavailable → the quiet CSS horizon.
    showFallback();
  }
&lt;/script&gt;

&lt;/div&gt;</code></pre>
      </template>
      <template data-content="source">&lt;div data-source=&quot;HTML&quot;&gt;
&lt;style&gt;
  html, body { height: 100%; margin: 0; overflow: hidden; }
  /* Boot backdrop — the scene fades in over this, so the first paint looks
     designed even before three.js arrives (and remains if it never does). */
  body { background: linear-gradient(rgb(247 246 242) 0%, rgb(236 234 227) 100%); }
  html.dark body, body.dark { background: linear-gradient(rgb(20 20 23) 0%, rgb(13 13 16) 100%); }
  /* Pinned to the iframe viewport, NOT height: 100% — directory-mode sandbox
     content ships inside a plain wrapper div (auto height), which breaks a
     percentage-height chain: the canvas would collapse to its attribute
     height and render as a fixed-size strip at the top of the band. */
  #scene { position: fixed; inset: 0; width: 100%; height: 100%; display: block; opacity: 0; transition: opacity 0.8s ease; }
  #scene.on { opacity: 1; }
  /* No-JS / no-WebGL / blocked-CDN fallback: a few soft horizon lines keep
     the wave suggestion without competing with overlaid hero content. */
  #fallback { display: none; position: fixed; inset: 0; overflow: hidden; }
  #fallback.on { display: block; }
  #fallback i {
    position: absolute; left: -5%; right: -5%; height: 2px; display: block;
    background: linear-gradient(90deg, transparent, var(--c), transparent);
    border-radius: 2px;
  }
&lt;/style&gt;

&lt;canvas id=&quot;scene&quot;&gt;&lt;/canvas&gt;
&lt;div id=&quot;fallback&quot; aria-hidden=&quot;true&quot;&gt;
  &lt;i style=&quot;--c:rgb(138 133 125 / 0.30); top: 58%&quot;&gt;&lt;/i&gt;
  &lt;i style=&quot;--c:rgb(138 133 125 / 0.22); top: 66%; transform: scaleX(0.92)&quot;&gt;&lt;/i&gt;
  &lt;i style=&quot;--c:rgb(61 107 61 / 0.20); top: 74%; transform: scaleX(0.96)&quot;&gt;&lt;/i&gt;
  &lt;i style=&quot;--c:rgb(138 133 125 / 0.16); top: 82%&quot;&gt;&lt;/i&gt;
&lt;/div&gt;

&lt;script type=&quot;module&quot;&gt;
  // ── Wireframe waves (SPEC-101 / WORK-401) ──────────────────────────────
  // The hero backdrop: a vertex-displaced wireframe plane rolling in slow
  // swells — karesansui by way of a vector terrain. Crests pick up a niwaki
  // accent over the stone base. Ambient by contract: the cover posture
  // demotion blocks pointer events, so the scene carries itself with no
  // interaction.

  // Palette of record: packages/lumina/src/presets/niwaki.ts (light/dark pairs).
  // Base = ishi (stone); crest accent = matsu (light) / wakaba (dark).
  const NIWAKI = {
    light: { base: 0x8a857d, crest: 0x3d6b3d, fog: 0xeceae3, opacity: 0.5 },
    dark:  { base: 0x7d7062, crest: 0xb3d475, fog: 0x101013, opacity: 0.55 },
  };

  const dark =
    document.documentElement.classList.contains('dark') ||
    document.body.classList.contains('dark');
  const P = dark ? NIWAKI.dark : NIWAKI.light;
  const reduce = matchMedia('(prefers-reduced-motion: reduce)').matches;
  const canvas = document.getElementById('scene');
  const showFallback = () =&gt; {
    canvas.style.display = 'none';
    document.getElementById('fallback').classList.add('on');
  };

  try {
    // Version-pinned for reproducibility.
    const THREE = await import('https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js');

    const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: true });
    // Backdrop budget: cap the pixel ratio — the scrim sits over us anyway.
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 1.5));

    const scene = new THREE.Scene();
    // Fog fades the far edge into the CSS backdrop, so the grid has a horizon
    // instead of a hard geometric edge.
    scene.fog = new THREE.Fog(P.fog, 9, 26);
    const camera = new THREE.PerspectiveCamera(45, 1, 0.1, 100);
    camera.position.set(0, 2.4, 9.5);
    camera.lookAt(0, 0.2, 0);

    // ── The displaced plane ──
    const SEG_X = 88, SEG_Y = 46;
    const geo = new THREE.PlaneGeometry(38, 22, SEG_X, SEG_Y);
    geo.rotateX(-Math.PI / 2);
    const count = geo.attributes.position.count;
    const colors = new Float32Array(count * 3);
    geo.setAttribute('color', new THREE.BufferAttribute(colors, 3));
    const base = new THREE.Color(P.base);
    const crest = new THREE.Color(P.crest);
    const tmp = new THREE.Color();

    const mat = new THREE.MeshBasicMaterial({
      wireframe: true, vertexColors: true,
      transparent: true, opacity: P.opacity,
      fog: true, depthWrite: false,
    });
    const mesh = new THREE.Mesh(geo, mat);
    mesh.position.y = -0.6;
    scene.add(mesh);

    // Swell: a few travelling sines at different scales — cheap, organic, no
    // noise library. Amplitude stays modest; this is a ground, not a storm.
    const AMP = 0.9;
    function heightAt(x, z, t) {
      return AMP * (
        0.45 * Math.sin(x * 0.32 + t * 0.50) * Math.cos(z * 0.28 + t * 0.32)
        + 0.30 * Math.sin((x + z) * 0.18 - t * 0.40)
        + 0.15 * Math.sin(x * 0.85 + t * 0.90) * Math.sin(z * 0.55 - t * 0.55)
      );
    }
    function displace(t) {
      const pos = geo.attributes.position;
      for (let i = 0; i &lt; count; i++) {
        const x = pos.getX(i), z = pos.getZ(i);
        const h = heightAt(x, z, t);
        pos.setY(i, h);
        // Crest tint: 0 at the troughs, accent at the peaks.
        const k = Math.min(Math.max((h / AMP + 1) / 2, 0), 1);
        tmp.copy(base).lerp(crest, k * k); // square biases the accent to true crests
        colors[i * 3] = tmp.r;
        colors[i * 3 + 1] = tmp.g;
        colors[i * 3 + 2] = tmp.b;
      }
      pos.needsUpdate = true;
      geo.attributes.color.needsUpdate = true;
    }

    function resize() {
      const w = canvas.clientWidth, h = canvas.clientHeight;
      if (!w || !h) return;
      renderer.setSize(w, h, false);
      camera.aspect = w / h;
      camera.updateProjectionMatrix();
    }
    resize();
    window.addEventListener('resize', resize);

    canvas.classList.add('on');

    if (reduce) {
      // Reduced motion: one composed static frame — a mid-swell moment.
      displace(2.4);
      renderer.render(scene, camera);
    } else {
      // The RAF loop pauses with the tab — a backdrop must not drain a
      // backgrounded battery.
      let raf = 0;
      let t = 0;
      let last = performance.now();
      function loop(now) {
        const dt = Math.min((now - last) / 1000, 0.05);
        last = now;
        t += dt;
        displace(t);
        renderer.render(scene, camera);
        raf = requestAnimationFrame(loop);
      }
      raf = requestAnimationFrame(loop);
      document.addEventListener('visibilitychange', () =&gt; {
        if (document.hidden) {
          cancelAnimationFrame(raf);
          raf = 0;
        } else if (!raf) {
          last = performance.now();
          raf = requestAnimationFrame(loop);
        }
      });
    }
  } catch (err) {
    // CDN unreachable / WebGL unavailable → the quiet CSS horizon.
    showFallback();
  }
&lt;/script&gt;

&lt;/div&gt;</template>
      <meta data-field="design-tokens" content="{&quot;fonts&quot;:[{&quot;role&quot;:&quot;heading&quot;,&quot;family&quot;:&quot;Inter&quot;,&quot;weights&quot;:[400,600,700],&quot;category&quot;:&quot;sans-serif&quot;},{&quot;role&quot;:&quot;body&quot;,&quot;family&quot;:&quot;Source Sans Pro&quot;,&quot;weights&quot;:[400,600],&quot;category&quot;:&quot;sans-serif&quot;},{&quot;role&quot;:&quot;mono&quot;,&quot;family&quot;:&quot;Fira Code&quot;,&quot;weights&quot;:[400],&quot;category&quot;:&quot;monospace&quot;}],&quot;colors&quot;:[{&quot;name&quot;:&quot;Primary&quot;,&quot;value&quot;:&quot;#2563EB&quot;,&quot;group&quot;:&quot;Brand&quot;},{&quot;name&quot;:&quot;Secondary&quot;,&quot;value&quot;:&quot;#7C3AED&quot;,&quot;group&quot;:&quot;Brand&quot;},{&quot;name&quot;:&quot;Accent&quot;,&quot;value&quot;:&quot;#F59E0B&quot;,&quot;group&quot;:&quot;Brand&quot;},{&quot;name&quot;:&quot;Gray&quot;,&quot;value&quot;:&quot;#F9FAFB&quot;,&quot;group&quot;:&quot;Neutral&quot;},{&quot;name&quot;:&quot;Gray&quot;,&quot;value&quot;:&quot;#E5E7EB&quot;,&quot;group&quot;:&quot;Neutral&quot;},{&quot;name&quot;:&quot;Gray&quot;,&quot;value&quot;:&quot;#9CA3AF&quot;,&quot;group&quot;:&quot;Neutral&quot;},{&quot;name&quot;:&quot;Gray&quot;,&quot;value&quot;:&quot;#374151&quot;,&quot;group&quot;:&quot;Neutral&quot;},{&quot;name&quot;:&quot;Gray&quot;,&quot;value&quot;:&quot;#111827&quot;,&quot;group&quot;:&quot;Neutral&quot;}],&quot;spacing&quot;:{&quot;unit&quot;:&quot;4px&quot;,&quot;scale&quot;:[&quot;4&quot;,&quot;8&quot;,&quot;12&quot;,&quot;16&quot;,&quot;24&quot;,&quot;32&quot;,&quot;48&quot;,&quot;64&quot;]},&quot;radii&quot;:[{&quot;name&quot;:&quot;sm&quot;,&quot;value&quot;:&quot;4px&quot;},{&quot;name&quot;:&quot;md&quot;,&quot;value&quot;:&quot;8px&quot;},{&quot;name&quot;:&quot;lg&quot;,&quot;value&quot;:&quot;12px&quot;},{&quot;name&quot;:&quot;full&quot;,&quot;value&quot;:&quot;9999px&quot;}]}" />
    </rf-sandbox>
  </div>
</section>

The mechanism: the cover layout stacks the content over the media well; the interaction-posture contract demotes any cover guest to presentational; and the sandbox automatically switches to height="fill" so the iframe fills the band. No sandbox-side configuration is needed.

The authoring contract for an animated backdrop:

  • Eager only. activation="visible" or "click" contradicts an inert backdrop — the Run control would be unreachable — and produces a build warning. The cost lands on first paint, so keep the scene lean.
  • Design dim. The scene sits under the scrim; darker than feels right in isolation is right.
  • Respect motion. Render a single static frame under prefers-reduced-motion (the waves scene does).
  • Cap the budget. Pin the dependency version, cap devicePixelRatio, pause the animation loop when the tab is hidden, and put a CSS gradient behind the canvas so the boot frame looks designed. Ship a static fallback for no-WebGL / blocked-CDN visitors.
  • Pin the canvas to the viewport. Size it with position: fixed; inset: 0 rather than a height: 100% chain — sandbox content renders inside a plain wrapper element with auto height, which breaks percentage heights and leaves the canvas as a fixed-size strip.

Cover attributes

AttributeTypeDefaultDescription
content-placestringautoOverlay anchor: "<block> <inline>" (e.g. "end start"), or auto — a centred band
heightstringBand height (named scale): sm, md, lg, xl
aspectstringBand aspect ratio (e.g. "21/9"); without height/aspect, a wide default with a viewport floor applies
scrimstringonScrim edge (top, bottom, left, right) or none to opt out
scrim-typestringgradientScrim treatment: gradient or frost (with scrim-blur: none, sm, md, lg)

Section header

Hero supports an optional eyebrow, headline, and blurb above the headline and description. Place a short paragraph or heading before the main content to use them. See Page sections for the full syntax.

Layout attributes

The body splits on --- into media → content zones (media-first in source). media-position controls visual placement independently of source order — a landing-page hero typically uses media-position="end" to put the screenshot on the right.

AttributeTypeDefaultDescription
media-positionstringbottomWhere the media sits: top, bottom (the default — media beneath the text, the classic hero), start (left), end (right), or cover (full-bleed backdrop — see Cover)
media-ratiostringMedia's share of the row when beside content (start/end): 1/3, 2/5, 1/2, 3/5, 2/3
valignstringCross-axis alignment when media is beside content: top, center, bottom, stretch
collapsestringBreakpoint at which beside layouts collapse to a stack: sm, md, lg, never

Common attributes

All block runes share these attributes for layout and theming.

AttributeTypeDefaultDescription
widthstringcontentPage grid width: content, wide, or full
spacingstringVertical spacing: flush, tight, default, loose, or breathe
insetstringHorizontal padding: flush, tight, default, loose, or breathe
tintstringNamed colour tint from theme configuration
tint-modestringautoColour scheme override: auto, dark, or light
bgstringNamed background preset from theme configuration