note

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

Decision

Architecture decision record. Captures the context, options considered, the decision made, the rationale, and the consequences. The most important rune in the package for AI-native workflows — without decision records, every AI session starts from zero context.

Also available as {% adr %}.

Accepted decision

A fully documented architecture decision record.

{% decision id="ADR-007" status="accepted" date="2026-03-11" tags="tint,css" %}
# Use CSS custom properties for tint token injection

## Context
Tint runes need to override colour tokens within a section scope. The solution must work without JavaScript and cascade through nested elements.

## Options Considered
1. **CSS custom properties on the container** — inline styles setting `--tint-*` tokens, theme bridges via `var()` fallbacks.
2. **Generated CSS classes per tint combination** — build step creates per-tint classes. Avoids inline styles but combinatorial explosion.
3. **JavaScript runtime token injection** — behaviour script reads data attributes and sets styles. Most flexible but requires JS.

## Decision
CSS custom properties via inline styles on the container element.

## Rationale
Custom properties cascade naturally through the DOM subtree without JavaScript. Themes opt into tint support by including bridge CSS. The `--tint-*` namespace avoids collisions with theme-internal tokens.

## Consequences
- Themes must include the tint bridge CSS
- Inline styles cannot use media queries — dark mode handled separately
- Inspector must audit tint token contrast ratios
{% /decision %}
<article data-rune="decision">
  <meta content="ADR-007" data-field="id">
  <meta content="accepted" data-field="status">
  <meta content="2026-03-11" data-field="date">
  <meta content="" data-field="supersedes">
  <meta content="tint,css" data-field="tags">
  <meta content="2026-04-10" data-field="created">
  <meta content="2026-04-10" data-field="modified">
  <header data-name="title">
    <h1 id="use-css-custom-properties-for-tint-token-injection">Use CSS custom properties for tint token injection</h1>
  </header>
  <div data-name="body">
    <section data-name="context">
      <h2 id="context">Context</h2>
      <p>Tint runes need to override colour tokens within a section scope. The solution must work without JavaScript and cascade through nested elements.</p>
    </section>
    <section data-name="options-considered">
      <h2 id="options-considered">Options Considered</h2>
      <ol>
        <li>
          <strong marker="**">CSS custom properties on the container</strong>
          — inline styles setting
          <code>--tint-*</code>
          tokens, theme bridges via
          <code>var()</code>
          fallbacks.
        </li>
        <li>
          <strong marker="**">Generated CSS classes per tint combination</strong>
          — build step creates per-tint classes. Avoids inline styles but combinatorial explosion.
        </li>
        <li>
          <strong marker="**">JavaScript runtime token injection</strong>
          — behaviour script reads data attributes and sets styles. Most flexible but requires JS.
        </li>
      </ol>
    </section>
    <section data-name="decision">
      <h2 id="decision">Decision</h2>
      <p>CSS custom properties via inline styles on the container element.</p>
    </section>
    <section data-name="rationale">
      <h2 id="rationale">Rationale</h2>
      <p>
        Custom properties cascade naturally through the DOM subtree without JavaScript. Themes opt into tint support by including bridge CSS. The
        <code>--tint-*</code>
        namespace avoids collisions with theme-internal tokens.
      </p>
    </section>
    <section data-name="consequences">
      <h2 id="consequences">Consequences</h2>
      <ul>
        <li>Themes must include the tint bridge CSS</li>
        <li>Inline styles cannot use media queries — dark mode handled separately</li>
        <li>Inspector must audit tint token contrast ratios</li>
      </ul>
    </section>
  </div>
</article>
ID:ADR-007Status:accepted

Use CSS custom properties for tint token injection

Context

Tint runes need to override colour tokens within a section scope. The solution must work without JavaScript and cascade through nested elements.

Options Considered

  1. CSS custom properties on the container — inline styles setting --tint-* tokens, theme bridges via var() fallbacks.
  2. Generated CSS classes per tint combination — build step creates per-tint classes. Avoids inline styles but combinatorial explosion.
  3. JavaScript runtime token injection — behaviour script reads data attributes and sets styles. Most flexible but requires JS.

Decision

CSS custom properties via inline styles on the container element.

Rationale

Custom properties cascade naturally through the DOM subtree without JavaScript. Themes opt into tint support by including bridge CSS. The --tint-* namespace avoids collisions with theme-internal tokens.

Consequences

  • Themes must include the tint bridge CSS
  • Inline styles cannot use media queries — dark mode handled separately
  • Inspector must audit tint token contrast ratios
<article class="rf-decision rf-decision--ADR-007 rf-decision--accepted" data-id="ADR-007" data-status="accepted" data-date="2026-03-11" data-tags="tint,css" data-created="2026-04-10" data-modified="2026-04-10" data-rune="decision" data-density="full">
  <div data-name="header" class="rf-decision__header" data-section="header">
    <span data-name="id-badge" data-meta-type="id" data-meta-rank="primary" class="rf-decision__id-badge">
      <span data-meta-label="" data-meta-label-hidden="">ID:</span>
      <span data-meta-value="">ADR-007</span>
    </span>
    <span data-name="status-badge" data-meta-type="status" data-meta-rank="primary" data-meta-sentiment="positive" class="rf-decision__status-badge">
      <span data-meta-label="" data-meta-label-hidden="">Status:</span>
      <span data-meta-value="">accepted</span>
    </span>
    <time data-name="date-badge" data-meta-type="temporal" data-meta-rank="secondary" class="rf-decision__date-badge">
      <span data-meta-label="">Date:</span>
      <span data-meta-value="">2026-03-11</span>
    </time>
    <time data-name="created-badge" data-meta-type="temporal" data-meta-rank="secondary" class="rf-decision__created-badge">
      <span data-meta-label="">Created:</span>
      <span data-meta-value="">2026-04-10</span>
    </time>
    <time data-name="modified-badge" data-meta-type="temporal" data-meta-rank="secondary" class="rf-decision__modified-badge">
      <span data-meta-label="">Modified:</span>
      <span data-meta-value="">2026-04-10</span>
    </time>
  </div>
  <div data-name="body" class="rf-decision__body" data-section="body">
    <meta content="ADR-007" data-field="id" />
    <meta content="accepted" data-field="status" />
    <meta content="2026-03-11" data-field="date" />
    <meta content="" data-field="supersedes" />
    <meta content="tint,css" data-field="tags" />
    <meta content="2026-04-10" data-field="created" />
    <meta content="2026-04-10" data-field="modified" />
    <header data-name="title" class="rf-decision__title">
      <h1 id="use-css-custom-properties-for-tint-token-injection">Use CSS custom properties for tint token injection</h1>
    </header>
    <div data-name="body" class="rf-decision__body" data-section="body">
      <section data-name="context" class="rf-decision__context">
        <h2 id="context">Context</h2>
        <p>Tint runes need to override colour tokens within a section scope. The solution must work without JavaScript and cascade through nested elements.</p>
      </section>
      <section data-name="options-considered" class="rf-decision__options-considered">
        <h2 id="options-considered">Options Considered</h2>
        <ol>
          <li>
            <strong marker="**">CSS custom properties on the container</strong>
             — inline styles setting 
            <code>--tint-*</code>
             tokens, theme bridges via 
            <code>var()</code>
             fallbacks.
          </li>
          <li>
            <strong marker="**">Generated CSS classes per tint combination</strong>
             — build step creates per-tint classes. Avoids inline styles but combinatorial explosion.
          </li>
          <li>
            <strong marker="**">JavaScript runtime token injection</strong>
             — behaviour script reads data attributes and sets styles. Most flexible but requires JS.
          </li>
        </ol>
      </section>
      <section data-name="decision" class="rf-decision__decision">
        <h2 id="decision">Decision</h2>
        <p>CSS custom properties via inline styles on the container element.</p>
      </section>
      <section data-name="rationale" class="rf-decision__rationale">
        <h2 id="rationale">Rationale</h2>
        <p>
          Custom properties cascade naturally through the DOM subtree without JavaScript. Themes opt into tint support by including bridge CSS. The 
          <code>--tint-*</code>
           namespace avoids collisions with theme-internal tokens.
        </p>
      </section>
      <section data-name="consequences" class="rf-decision__consequences">
        <h2 id="consequences">Consequences</h2>
        <ul>
          <li>Themes must include the tint bridge CSS</li>
          <li>Inline styles cannot use media queries — dark mode handled separately</li>
          <li>Inspector must audit tint token contrast ratios</li>
        </ul>
      </section>
    </div>
  </div>
</article>

Proposed decision

A decision still under review.

{% decision id="ADR-015" status="proposed" date="2026-03-18" %}
# Adopt content model validation at parse time

## Context
Currently content model violations are only caught during transform. Earlier validation would improve error messages.

## Decision
Move validation to a post-parse AST pass.
{% /decision %}
<article data-rune="decision">
  <meta content="ADR-015" data-field="id">
  <meta content="proposed" data-field="status">
  <meta content="2026-03-18" data-field="date">
  <meta content="" data-field="supersedes">
  <meta content="" data-field="tags">
  <meta content="2026-04-10" data-field="created">
  <meta content="2026-04-10" data-field="modified">
  <header data-name="title">
    <h1 id="adopt-content-model-validation-at-parse-time">Adopt content model validation at parse time</h1>
  </header>
  <div data-name="body">
    <section data-name="context">
      <h2 id="context">Context</h2>
      <p>Currently content model violations are only caught during transform. Earlier validation would improve error messages.</p>
    </section>
    <section data-name="decision">
      <h2 id="decision">Decision</h2>
      <p>Move validation to a post-parse AST pass.</p>
    </section>
  </div>
</article>
ID:ADR-015Status:proposed

Adopt content model validation at parse time

Context

Currently content model violations are only caught during transform. Earlier validation would improve error messages.

Decision

Move validation to a post-parse AST pass.

<article class="rf-decision rf-decision--ADR-015 rf-decision--proposed" data-id="ADR-015" data-status="proposed" data-date="2026-03-18" data-created="2026-04-10" data-modified="2026-04-10" data-rune="decision" data-density="full">
  <div data-name="header" class="rf-decision__header" data-section="header">
    <span data-name="id-badge" data-meta-type="id" data-meta-rank="primary" class="rf-decision__id-badge">
      <span data-meta-label="" data-meta-label-hidden="">ID:</span>
      <span data-meta-value="">ADR-015</span>
    </span>
    <span data-name="status-badge" data-meta-type="status" data-meta-rank="primary" data-meta-sentiment="neutral" class="rf-decision__status-badge">
      <span data-meta-label="" data-meta-label-hidden="">Status:</span>
      <span data-meta-value="">proposed</span>
    </span>
    <time data-name="date-badge" data-meta-type="temporal" data-meta-rank="secondary" class="rf-decision__date-badge">
      <span data-meta-label="">Date:</span>
      <span data-meta-value="">2026-03-18</span>
    </time>
    <time data-name="created-badge" data-meta-type="temporal" data-meta-rank="secondary" class="rf-decision__created-badge">
      <span data-meta-label="">Created:</span>
      <span data-meta-value="">2026-04-10</span>
    </time>
    <time data-name="modified-badge" data-meta-type="temporal" data-meta-rank="secondary" class="rf-decision__modified-badge">
      <span data-meta-label="">Modified:</span>
      <span data-meta-value="">2026-04-10</span>
    </time>
  </div>
  <div data-name="body" class="rf-decision__body" data-section="body">
    <meta content="ADR-015" data-field="id" />
    <meta content="proposed" data-field="status" />
    <meta content="2026-03-18" data-field="date" />
    <meta content="" data-field="supersedes" />
    <meta content="" data-field="tags" />
    <meta content="2026-04-10" data-field="created" />
    <meta content="2026-04-10" data-field="modified" />
    <header data-name="title" class="rf-decision__title">
      <h1 id="adopt-content-model-validation-at-parse-time">Adopt content model validation at parse time</h1>
    </header>
    <div data-name="body" class="rf-decision__body" data-section="body">
      <section data-name="context" class="rf-decision__context">
        <h2 id="context">Context</h2>
        <p>Currently content model violations are only caught during transform. Earlier validation would improve error messages.</p>
      </section>
      <section data-name="decision" class="rf-decision__decision">
        <h2 id="decision">Decision</h2>
        <p>Move validation to a post-parse AST pass.</p>
      </section>
    </div>
  </div>
</article>

Attributes

AttributeTypeDefaultDescription
idstringIdentifier, e.g. ADR-007 (required)
statusstringproposedDecision status: proposed, accepted, superseded, deprecated
datestringDate decided (ISO 8601)
supersedesstringID of the decision this replaces
tagsstringComma-separated labels
createdstring$file.createdCreation date (ISO 8601). Auto-populated from git history
modifiedstring$file.modifiedLast modified date (ISO 8601). Auto-populated from git history

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