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>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.
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>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
| Attribute | Type | Default | Description |
|---|---|---|---|
id | string | — | Identifier, e.g. ADR-007 (required) |
status | string | proposed | Decision status: proposed, accepted, superseded, deprecated |
date | string | — | Date decided (ISO 8601) |
supersedes | string | — | ID of the decision this replaces |
tags | string | — | Comma-separated labels |
created | string | $file.created | Creation date (ISO 8601). Auto-populated from git history |
modified | string | $file.modified | Last modified date (ISO 8601). Auto-populated from git history |
Common attributes
All block runes share these attributes for layout and theming.
| Attribute | Type | Default | Description |
|---|---|---|---|
width | string | content | Page grid width: content, wide, or full |
spacing | string | — | Vertical spacing: flush, tight, default, loose, or breathe |
inset | string | — | Horizontal padding: flush, tight, default, loose, or breathe |
tint | string | — | Named colour tint from theme configuration |
tint-mode | string | auto | Colour scheme override: auto, dark, or light |
bg | string | — | Named background preset from theme configuration |