Human Register
Warm, pedagogical, tactile.
Used for education, ethics, community, invitation, and voice.
--color-terracotta
--color-amber
--color-burgundy
Tokens, a component library and a contrast gate for work that moves between human pedagogy and digital precision. Every specimen on this page is the real library — link one stylesheet and write HTML.
<!-- The whole system: tokens + base + components -->
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/gh/idcesares/The-Membrane-Palette@2.2.0/membrane.css">
Human Register
Used for education, ethics, community, invitation, and voice.
--color-terracotta
--color-amber
--color-burgundy
The Membrane
Warm cream and neutral grays hold the tension without flattening it into white space.
--color-cream
--color-neutral-200
--gradient-membrane
Digital Register
Used for code, structure, navigation, analytical surfaces, and technical clarity.
--color-teal
--color-chart-5
--color-charcoal
01 / Palette
The palette is organized around what a surface is doing: warming a human moment, clarifying a digital one, or holding the membrane between them. Components only ever see the semantic tier.
Neutral Scale
Register Pairs
Every -text token is verified at ≥4.5:1 on its own -bg wash, on the page, and on cards — in both modes.
Data Colors
chart-1Terracottachart-2Tealchart-3Amberchart-4Burgundychart-5Steel bluechart-6GreenEach step was searched within its brand hue, then checked as a set in both modes: neighbors stay ≥ 11.5 ΔE apart under protanopia and deuteranopia, ≥ 16 for full-color vision, and every series is ≥ 3:1 on page and cards. Assign in order; never cycle. See Chart.
02 / Typography
Fraunces carries human authority, Instrument Sans keeps reading precise, and JetBrains Mono makes the builder layer visible without becoming the whole personality.
03 / Rhythm
The 4px spacing base gives the system a measured cadence. Motion is modest, accessible, and only used to clarify interaction.
Spacing Scale
--space-28px--space-416px--space-832px--space-1664px--space-2496pxMotion Tokens
150ms250ms400msease-in-outDark Mode
Both cards hold identical markup. Each sets data-theme on itself, and every token inside resolves to that mode — no override blocks, no duplicated hex values.
Warm cream, warm neutrals, terracotta emphasis, teal navigation.
Contrast gate passing
Charcoal depth, lightened accents, deeper shadows, lighter elevated surfaces.
Contrast gate passing
04 / Components
Framework-free components in one stylesheet. Classes name the thing (mp-button), data-* attributes choose the option, and ARIA drives the state — so the look and what assistive tech hears can't disagree.
Composed Specimen
Composed Specimen
Educators trained
3,214
18% vs. last year
Bring one real problem
Week one starts from your classroom, not from the tool.
Layout
Container, Stack, Cluster, Grid, Section and Surface primitives that compose any page without custom layout CSS.
.mp-container .mp-stack .mp-cluster .mp-grid .mp-section .mp-surface .mp-visually-hiddendata-sizedata-justifydata-aligndata-mindata-gapdata-toneStack and cluster
Workshop
<div class="mp-stack" data-gap="3">
<p class="mp-card__overline">Workshop</p>
<h3 class="type-h3">Designing with the membrane</h3>
<div class="mp-cluster" data-gap="2">
<span class="mp-tag" data-tone="human">Pedagogy</span>
<span class="mp-tag" data-tone="digital">AI systems</span>
<span class="mp-tag">90 min</span>
</div>
</div>
Responsive grid
One
Two
Three
<div class="mp-grid" data-min="sm" data-gap="4">
<div class="mp-card" data-variant="flat"><p class="mp-card__body">One</p></div>
<div class="mp-card" data-variant="flat"><p class="mp-card__body">Two</p></div>
<div class="mp-card" data-variant="flat"><p class="mp-card__body">Three</p></div>
</div>
Cluster justification and alignment
<div class="mp-stack" data-gap="3">
<div class="mp-cluster" data-justify="between" data-align="baseline">
<h3 class="type-h3">Workshops</h3>
<a class="mp-link" data-variant="standalone" href="#components">See all<span class="mp-visually-hidden"> workshops</span></a>
</div>
<div class="mp-cluster" data-justify="center">
<span class="mp-tag">centered</span>
<span class="mp-tag">row</span>
</div>
<div class="mp-cluster" data-justify="end" data-align="start">
<button class="mp-button" type="button" data-variant="ghost">Cancel</button>
<button class="mp-button" type="button">Save</button>
</div>
</div>
Surface tones
Default — --color-bg-primary
Secondary — cards, alternating bands
Elevated — dialogs, popovers (lighter in dark mode)
<div class="mp-grid" data-min="sm" data-gap="4">
<div class="mp-section mp-surface" data-size="sm"><div class="mp-container"><p class="type-small">Default — <code class="mp-code">--color-bg-primary</code></p></div></div>
<div class="mp-section mp-surface" data-size="sm" data-tone="secondary"><div class="mp-container"><p class="type-small">Secondary — cards, alternating bands</p></div></div>
<div class="mp-section mp-surface" data-size="sm" data-tone="elevated"><div class="mp-container"><p class="type-small">Elevated — dialogs, popovers (lighter in dark mode)</p></div></div>
</div>
Dark band inside a light page
Every token inside this section resolves to its dark value, because data-theme="dark" sets color-scheme for the subtree.
<section class="mp-section mp-surface" data-size="sm" data-theme="dark">
<div class="mp-container" data-size="sm">
<p class="type-body">Every token inside this section resolves to its dark value, because <code class="mp-code">data-theme="dark"</code> sets <code class="mp-code">color-scheme</code> for the subtree.</p>
</div>
</section>
Layout
Tone (muted, subtle, human, digital) and reading measure for running copy — combine with the .type-* size classes instead of writing inline color or max-width.
.mp-textdata-tonedata-measureTones and measure
Workshop
Six weeks for educators who want to use AI with intention — warm in how we teach, precise in how we build.
Updated 3 days ago · v2.1
<div class="mp-stack" data-gap="2">
<p class="mp-text type-label" data-tone="human">Workshop</p>
<h3 class="type-h3">AI literacy, from the classroom up</h3>
<p class="mp-text type-body-lg" data-tone="muted" data-measure>Six weeks for educators who want to use AI with intention — warm in how we teach, precise in how we build.</p>
<p class="mp-text type-small" data-tone="subtle">Updated 3 days ago · <span class="mp-text" data-tone="digital">v2.1</span></p>
</div>
Layout
One class that styles long-form HTML — articles, Markdown output, CMS content — with the full typographic system.
.mp-proseArticle body
Every element should answer one question: what does this translate? If it cannot, it does not belong. Read the notes for the full argument.
Learning happens best when people build things that matter to them.
Inline code keeps the code register visible without taking over the paragraph.
<article class="mp-prose">
<h2>Translation, not decoration</h2>
<p>Every element should answer one question: <strong>what does this translate?</strong> If it cannot, it does not belong. Read the <a href="#prose-notes">notes</a> for the full argument.</p>
<ul>
<li>Warm surfaces for human moments</li>
<li>Cool precision for systems and code</li>
</ul>
<blockquote>Learning happens best when people build things that matter to them.</blockquote>
<p id="prose-notes">Inline <code>code</code> keeps the code register visible without taking over the paragraph.</p>
</article>
Actions
Pill-shaped action trigger. Primary is terracotta (one per view), secondary is a teal outline, ghost is quiet, danger is destructive.
.mp-buttondata-variantdata-sizedata-icon-onlydata-full-widthVariants
<div class="mp-cluster">
<button class="mp-button" type="button">Save draft</button>
<button class="mp-button" type="button" data-variant="secondary">See the work</button>
<button class="mp-button" type="button" data-variant="ghost">Cancel</button>
<button class="mp-button" type="button" data-variant="danger">Delete draft</button>
</div>
Sizes
<div class="mp-cluster">
<button class="mp-button" type="button" data-size="sm">Small</button>
<button class="mp-button" type="button">Default</button>
<button class="mp-button" type="button" data-size="lg">Large</button>
</div>
With icons
<div class="mp-cluster">
<a class="mp-button" href="#components" data-variant="secondary">
Read the essay
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
</a>
<button class="mp-button" type="button" data-variant="ghost" data-icon-only aria-label="Add to reading list">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg>
</button>
</div>
Full width
Two days, twelve seats, one deployed tool.
Six weeks, online, starting from your classroom.
<div class="mp-grid" data-min="sm" data-gap="4">
<article class="mp-card">
<h3 class="mp-card__title">Prototype Lab</h3>
<p class="mp-card__body">Two days, twelve seats, one deployed tool.</p>
<div class="mp-card__footer"><button class="mp-button" type="button" data-full-width>Join the waitlist</button></div>
</article>
<article class="mp-card">
<h3 class="mp-card__title">AI Literacy I</h3>
<p class="mp-card__body">Six weeks, online, starting from your classroom.</p>
<div class="mp-card__footer"><button class="mp-button" type="button" data-variant="secondary" data-full-width>Read the syllabus</button></div>
</article>
</div>
States
<div class="mp-cluster">
<button class="mp-button" type="button" disabled>Disabled</button>
<button class="mp-button" type="button" aria-busy="true">Saving</button>
<button class="mp-button" type="button" data-variant="secondary" aria-pressed="true">Following</button>
</div>
Actions
Text links — inline, quiet and standalone call-to-action — plus the skip link every page should start with.
.mp-link .mp-skip-linkdata-variantInline, quiet, standalone
Read the design principles before proposing a new token.
Updated 3 days ago by Isaac
Explore the case study<div class="mp-stack" data-gap="2">
<p class="type-body">Read the <a class="mp-link" href="#components">design principles</a> before proposing a new token.</p>
<p class="type-small">Updated 3 days ago by <a class="mp-link" data-variant="quiet" href="#components">Isaac</a></p>
<a class="mp-link" data-variant="standalone" href="#components">Explore the case study</a>
</div>
Forms
Wraps one form control with its label, hint and error message; Fieldset groups related controls under a legend.
.mp-field .mp-fieldsetLabel, hint and required marker
We'll only use it to send the workshop materials.
<div class="mp-field">
<label class="mp-field__label" for="field-email">Email<span class="mp-field__required" aria-hidden="true">*</span></label>
<input class="mp-input" id="field-email" type="email" autocomplete="email" required aria-describedby="field-email-hint">
<p class="mp-field__hint" id="field-email-hint">We'll only use it to send the workshop materials.</p>
</div>
Error state
Handles can't contain spaces — try "idcesares".
<div class="mp-field">
<label class="mp-field__label" for="field-handle">GitHub handle<span class="mp-field__optional">(optional)</span></label>
<input class="mp-input" id="field-handle" type="text" value="id cesares" aria-invalid="true" aria-describedby="field-handle-error">
<p class="mp-field__error" id="field-handle-error">Handles can't contain spaces — try "idcesares".</p>
</div>
Fieldset
<fieldset class="mp-fieldset">
<legend class="mp-fieldset__legend">Preferred format</legend>
<label class="mp-choice"><input class="mp-radio" type="radio" name="field-format" checked> In person</label>
<label class="mp-choice"><input class="mp-radio" type="radio" name="field-format"> Online</label>
</fieldset>
Forms
One class for text inputs, textareas and selects, with a ≥3:1 control boundary, visible focus ring, and invalid/disabled/read-only states.
.mp-inputdata-sizeText, select, textarea
<div class="mp-stack">
<div class="mp-field">
<label class="mp-field__label" for="input-name">Full name</label>
<input class="mp-input" id="input-name" type="text" autocomplete="name" placeholder="Isaac D'Césares">
</div>
<div class="mp-field">
<label class="mp-field__label" for="input-topic">Topic</label>
<select class="mp-input" id="input-topic">
<option>AI in education</option>
<option>Learning design</option>
<option>Developer tooling</option>
</select>
</div>
<div class="mp-field">
<label class="mp-field__label" for="input-message">Message</label>
<textarea class="mp-input" id="input-message" rows="3">Tell us what you want to explore.</textarea>
</div>
</div>
Sizes and states
<div class="mp-stack" data-gap="3">
<input class="mp-input" type="text" data-size="sm" aria-label="Small input" placeholder="Small">
<input class="mp-input" type="text" data-size="lg" aria-label="Large input" placeholder="Large">
<input class="mp-input" type="text" aria-label="Disabled input" value="Disabled" disabled>
<input class="mp-input" type="text" aria-label="Read-only input" value="Read-only" readonly>
<input class="mp-input" type="text" aria-label="Invalid input" value="Invalid" aria-invalid="true">
</div>
Forms · beta
A text input that suggests options as you type — accent-insensitive filtering, arrow-key navigation and a result count for screen readers, via membrane.js.
.mp-comboboxTopic
No topics match. You can still use what you typed.
Start typing, or press ↓ to see every topic.
<div class="mp-field">
<label class="mp-field__label" for="combo-topic">Workshop topic</label>
<div class="mp-combobox">
<input class="mp-input mp-combobox__input" id="combo-topic" type="text" role="combobox" aria-autocomplete="list" aria-expanded="false" aria-controls="combo-topic-list" aria-describedby="combo-topic-hint" autocomplete="off">
<ul class="mp-combobox__list" id="combo-topic-list" role="listbox" aria-label="Topics" hidden>
<li class="mp-combobox__option" id="combo-topic-1" role="option" aria-selected="false">AI literacy for educators</li>
<li class="mp-combobox__option" id="combo-topic-2" role="option" aria-selected="false">Assessment design</li>
<li class="mp-combobox__option" id="combo-topic-3" role="option" aria-selected="false">Educação e tecnologia</li>
<li class="mp-combobox__option" id="combo-topic-4" role="option" aria-selected="false">Learning analytics</li>
<li class="mp-combobox__option" id="combo-topic-5" role="option" aria-selected="false">Prompt craft</li>
<li class="mp-combobox__option" id="combo-topic-6" role="option" aria-selected="false">Transformação digital</li>
</ul>
<p class="mp-combobox__empty" hidden>No topics match. You can still use what you typed.</p>
<p class="mp-combobox__status" role="status"></p>
</div>
<p class="mp-field__hint" id="combo-topic-hint">Start typing, or press ↓ to see every topic.</p>
</div>
With hints and an unavailable option
No cohort matches.
<div class="mp-field">
<label class="mp-field__label" for="combo-cohort">Cohort</label>
<div class="mp-combobox">
<input class="mp-input mp-combobox__input" id="combo-cohort" type="text" role="combobox" aria-autocomplete="list" aria-expanded="false" aria-controls="combo-cohort-list" autocomplete="off" placeholder="Rio, São Paulo, online…">
<ul class="mp-combobox__list" id="combo-cohort-list" role="listbox" aria-label="Cohorts" hidden>
<li class="mp-combobox__option" id="combo-cohort-1" role="option" aria-selected="false">Rio de Janeiro <span class="mp-combobox__hint">March</span></li>
<li class="mp-combobox__option" id="combo-cohort-2" role="option" aria-selected="false">São Paulo <span class="mp-combobox__hint">April</span></li>
<li class="mp-combobox__option" id="combo-cohort-3" role="option" aria-selected="false" aria-disabled="true">Belo Horizonte <span class="mp-combobox__hint">Full</span></li>
<li class="mp-combobox__option" id="combo-cohort-4" role="option" aria-selected="false" data-mp-value="Online">Online, any time zone <span class="mp-combobox__hint">Rolling</span></li>
</ul>
<p class="mp-combobox__empty" hidden>No cohort matches.</p>
<p class="mp-combobox__status" role="status"></p>
</div>
</div>
Forms
Checkbox and radio controls drawn in the brand style, inside a clickable .mp-choice label row with optional description.
.mp-choice .mp-checkbox .mp-radioCheckboxes
<fieldset class="mp-fieldset">
<legend class="mp-fieldset__legend">Send me</legend>
<label class="mp-choice"><input class="mp-checkbox" type="checkbox" checked> New essays</label>
<label class="mp-choice">
<input class="mp-checkbox" type="checkbox">
<span>Workshop dates<span class="mp-choice__description">About once a month, never more.</span></span>
</label>
<label class="mp-choice"><input class="mp-checkbox" type="checkbox" disabled> Product updates (paused)</label>
</fieldset>
Radios
<fieldset class="mp-fieldset">
<legend class="mp-fieldset__legend">Audience</legend>
<label class="mp-choice"><input class="mp-radio" type="radio" name="choice-audience" checked> Educators</label>
<label class="mp-choice"><input class="mp-radio" type="radio" name="choice-audience"> Developers</label>
<label class="mp-choice"><input class="mp-radio" type="radio" name="choice-audience"> Researchers</label>
</fieldset>
Forms
An on/off toggle for settings that take effect immediately — a native checkbox with role="switch".
.mp-switch .mp-choiceSettings
<div class="mp-stack" data-gap="0">
<label class="mp-choice"><input class="mp-switch" type="checkbox" role="switch" checked> Email me when a workshop opens</label>
<label class="mp-choice"><input class="mp-switch" type="checkbox" role="switch"> Show code samples in TypeScript</label>
<label class="mp-choice"><input class="mp-switch" type="checkbox" role="switch" disabled> Beta features (invite only)</label>
</div>
Content
A contained unit — overline, serif title, body, footer, optional media — with standard, featured and flat variants and an accessible whole-card link.
.mp-carddata-tonedata-variantStandard, featured, digital
Essay
What changes when a course remembers every cohort that took it.
Featured
A field guide to designing where pedagogy meets code.
Open source
DTCG JSON in, gate-checked OKLCH CSS out.
<div class="mp-grid">
<article class="mp-card">
<p class="mp-card__overline">Essay</p>
<h3 class="mp-card__title">Learning platforms with institutional memory</h3>
<p class="mp-card__body">What changes when a course remembers every cohort that took it.</p>
<div class="mp-card__footer"><span>8 min read</span></div>
</article>
<article class="mp-card" data-variant="featured">
<p class="mp-card__overline">Featured</p>
<h3 class="mp-card__title">The membrane between people and systems</h3>
<p class="mp-card__body">A field guide to designing where pedagogy meets code.</p>
</article>
<article class="mp-card" data-variant="featured" data-tone="digital">
<p class="mp-card__overline">Open source</p>
<h3 class="mp-card__title">Token pipeline</h3>
<p class="mp-card__body">DTCG JSON in, gate-checked OKLCH CSS out.</p>
</article>
</div>
With media
Illustration
Media sits full-bleed at the top and picks up the brand's warm photo filter.
<div class="mp-grid" data-min="sm">
<article class="mp-card">
<div class="mp-card__media"><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 180'%3E%3Crect width='320' height='180' fill='%23F0EBE1'/%3E%3Cpath d='M-10 140C80 20 160 20 330 120' fill='none' stroke='%23B35530' stroke-width='3' stroke-linecap='round'/%3E%3Cpath d='M-10 50C90 170 200 170 330 40' fill='none' stroke='%231B756D' stroke-width='3' stroke-linecap='round'/%3E%3Ccircle cx='160' cy='86' r='6' fill='%23D49A3A'/%3E%3C/svg%3E" alt=""></div>
<p class="mp-card__overline">Illustration</p>
<h3 class="mp-card__title">Where the registers cross</h3>
<p class="mp-card__body">Media sits full-bleed at the top and picks up the brand's warm photo filter.</p>
</article>
</div>
Clickable card
Sample case
A fictional program for testing collaborative AI-literacy workflows.
<article class="mp-card">
<p class="mp-card__overline">Sample case</p>
<h3 class="mp-card__title"><a class="mp-card__link" href="#components">Teaching AI literacy at scale</a></h3>
<p class="mp-card__body">A fictional program for testing collaborative AI-literacy workflows.</p>
<div class="mp-card__footer">
<span class="mp-tag" data-tone="human">Education</span>
<span class="mp-tag" data-tone="digital">LLMs</span>
</div>
</article>
Content
A pill that names a topic or category, colored by register — human (terracotta), digital (teal) or neutral. Can be a link, a toggle, or removable.
.mp-tagdata-toneTones
<div class="mp-cluster" data-gap="2">
<span class="mp-tag" data-tone="human">Pedagogy</span>
<span class="mp-tag" data-tone="human">Community</span>
<span class="mp-tag" data-tone="digital">TypeScript</span>
<span class="mp-tag" data-tone="digital">Multi-agent systems</span>
<span class="mp-tag">45 min</span>
</div>
Interactive
<div class="mp-cluster" data-gap="2">
<a class="mp-tag" data-tone="digital" href="#components">#design-tokens</a>
<button class="mp-tag" type="button" data-tone="human" aria-pressed="true">Educators</button>
<button class="mp-tag" type="button" aria-pressed="false">Developers</button>
<span class="mp-tag" data-tone="digital">
OKLCH
<button class="mp-tag__remove" type="button" aria-label="Remove OKLCH">×</button>
</span>
</div>
Content
A compact, uppercase, non-interactive label for status and metadata — info, success, warning, error, or a register tone.
.mp-badgedata-tonedata-variantTones
<div class="mp-cluster" data-gap="2">
<span class="mp-badge">Draft</span>
<span class="mp-badge" data-tone="info">Beta</span>
<span class="mp-badge" data-tone="success">Live</span>
<span class="mp-badge" data-tone="warning">Deprecated</span>
<span class="mp-badge" data-tone="error">Failing</span>
<span class="mp-badge" data-tone="human">Workshop</span>
<span class="mp-badge" data-tone="digital">API</span>
</div>
With status dot
<div class="mp-cluster" data-gap="2">
<span class="mp-badge" data-tone="success" data-variant="dot">Online</span>
<span class="mp-badge" data-tone="warning" data-variant="dot">Degraded</span>
<span class="mp-badge" data-tone="error" data-variant="dot">Offline</span>
</div>
Content
A person as a warm-filtered photo or Fraunces initials; digital tone uses monospace for bots and systems. Groups overlap.
.mp-avatar .mp-avatar-groupdata-sizedata-toneSizes and tones
<div class="mp-cluster">
<span class="mp-avatar" data-size="sm" role="img" aria-label="Ana Lima">AL</span>
<span class="mp-avatar" role="img" aria-label="Isaac D'Césares">ID</span>
<span class="mp-avatar" data-size="lg" role="img" aria-label="Rafael Costa">RC</span>
<span class="mp-avatar" data-size="xl" data-tone="digital" role="img" aria-label="Course assistant (AI)">AI</span>
</div>
Group
<div class="mp-avatar-group" role="group" aria-label="Facilitators">
<span class="mp-avatar" role="img" aria-label="Ana Lima">AL</span>
<span class="mp-avatar" role="img" aria-label="Bruno Reis">BR</span>
<span class="mp-avatar" data-tone="digital" role="img" aria-label="Course assistant (AI)">AI</span>
</div>
Content
Blockquote with attribution in Fraunces italic; the pull variant renders the brand's signature phrases large and centered.
.mp-quotedata-variantBlockquote
The role of the teacher is to create the conditions for invention rather than provide ready-made knowledge.
<figure class="mp-quote">
<blockquote class="mp-quote__text">
<p>The role of the teacher is to create the conditions for invention rather than provide ready-made knowledge.</p>
</blockquote>
<figcaption class="mp-quote__source">— <cite>Seymour Papert</cite>, <i>Mindstorms</i></figcaption>
</figure>
Pull quote
Human intelligence, amplified with technological intentionality.
<figure class="mp-quote" data-variant="pull">
<blockquote class="mp-quote__text"><p>Human intelligence, amplified with technological intentionality.</p></blockquote>
</figure>
Content
Inline code, keyboard keys, and always-dark code blocks with gate-checked syntax colors that also style Prism and highlight.js output.
.mp-code .mp-kbd .mp-code-block .mp-syntax-keyword .mp-syntax-string .mp-syntax-function .mp-syntax-number .mp-syntax-commentInline code and keys
Run npm run build:system, then press Ctrl + R to reload.
<p class="type-body">Run <code class="mp-code">npm run build:system</code>, then press <kbd class="mp-kbd">Ctrl</kbd> + <kbd class="mp-kbd">R</kbd> to reload.</p>
Code block
/* Consume the semantic tier */
.cta {
background: var(--color-action-primary);
min-height: 44px;
}
<figure class="mp-code-block">
<figcaption class="mp-code-block__header"><span>button.css</span><span>CSS</span></figcaption>
<pre tabindex="0"><code><span class="mp-syntax-comment">/* Consume the semantic tier */</span>
<span class="mp-syntax-keyword">.cta</span> {
<span class="mp-syntax-function">background</span>: var(<span class="mp-syntax-string">--color-action-primary</span>);
<span class="mp-syntax-function">min-height</span>: <span class="mp-syntax-number">44</span>px;
}</code></pre>
</figure>
Content
A fading hairline between sections — or a full-width solid rule inside panels. Prefer whitespace first.
.mp-dividerdata-sizedata-variantFading and full
Section one
Section two
Section three
<div>
<p class="type-small">Section one</p>
<hr class="mp-divider" data-size="sm">
<p class="type-small">Section two</p>
<hr class="mp-divider" data-variant="full" data-size="sm">
<p class="type-small">Section three</p>
</div>
Content
Data tables with a quiet uppercase header, tabular numerals, end-aligned numbers, compact/striped/interactive variants and a scrolling frame.
.mp-table-wrap .mp-tabledata-aligndata-densitydata-variantTable in a scrolling frame
| Cohort | Format | Learners | Status |
|---|---|---|---|
| AI Literacy I | Online | 1,240 | Live |
| Prompting for Teachers | Hybrid | 318 | Enrolling |
| Developers' Lab | In person | 42 | Draft |
<div class="mp-table-wrap" tabindex="0" role="region" aria-labelledby="table-cohorts-caption">
<table class="mp-table" data-variant="interactive">
<caption id="table-cohorts-caption">Cohorts, 2026</caption>
<thead>
<tr><th scope="col">Cohort</th><th scope="col">Format</th><th scope="col" data-align="end">Learners</th><th scope="col">Status</th></tr>
</thead>
<tbody>
<tr><th scope="row">AI Literacy I</th><td>Online</td><td data-align="end">1,240</td><td><span class="mp-badge" data-tone="success">Live</span></td></tr>
<tr><th scope="row">Prompting for Teachers</th><td>Hybrid</td><td data-align="end">318</td><td><span class="mp-badge" data-tone="info">Enrolling</span></td></tr>
<tr><th scope="row">Developers' Lab</th><td>In person</td><td data-align="end">42</td><td><span class="mp-badge">Draft</span></td></tr>
</tbody>
</table>
</div>
Compact and striped
| Token | Surface | Ratio |
|---|---|---|
--color-human-text | Card | 5.02 |
--color-error-text | Card | 4.94 |
--color-warning-text | Card | 5.15 |
--color-info-text | Page | 7.03 |
<div class="mp-table-wrap">
<table class="mp-table" data-density="compact" data-variant="striped">
<caption class="mp-visually-hidden">Contrast checks by surface</caption>
<thead>
<tr><th scope="col">Token</th><th scope="col">Surface</th><th scope="col" data-align="end">Ratio</th></tr>
</thead>
<tbody>
<tr><th scope="row"><code class="mp-code">--color-human-text</code></th><td>Card</td><td data-align="end">5.02</td></tr>
<tr><th scope="row"><code class="mp-code">--color-error-text</code></th><td>Card</td><td data-align="end">4.94</td></tr>
<tr><th scope="row"><code class="mp-code">--color-warning-text</code></th><td>Card</td><td data-align="end">5.15</td></tr>
<tr><th scope="row"><code class="mp-code">--color-info-text</code></th><td>Page</td><td data-align="end">7.03</td></tr>
</tbody>
</table>
</div>
Content
A headline metric — label, Fraunces numeral, and a delta whose arrow (trend) and color (sentiment) are set independently.
.mp-statdata-trenddata-sentimentStat row
Educators trained
3,214
18% vs. last year
Drop-out rate
6.2%
2.1 pts since redesign
Median session
41 min
4 min this term
<div class="mp-grid" data-min="sm">
<div class="mp-stat">
<p class="mp-stat__label">Educators trained</p>
<p class="mp-stat__value">3,214</p>
<p class="mp-stat__delta" data-trend="up" data-sentiment="positive">18% vs. last year</p>
</div>
<div class="mp-stat">
<p class="mp-stat__label">Drop-out rate</p>
<p class="mp-stat__value">6.2%</p>
<p class="mp-stat__delta" data-trend="down" data-sentiment="positive">2.1 pts since redesign</p>
</div>
<div class="mp-stat">
<p class="mp-stat__label">Median session</p>
<p class="mp-stat__value">41 min</p>
<p class="mp-stat__delta" data-trend="down" data-sentiment="negative">4 min this term</p>
</div>
</div>
Content · beta
A figure shell (title, legend, caption) and a CSS bar list — single, multi-series or stacked — colored by the validated --color-chart-* palette, with every value printed.
.mp-chartdata-seriesSingle series
Course completion by cohort
<figure class="mp-chart" aria-labelledby="chart-completion-title">
<div class="mp-chart__header">
<p class="mp-chart__title" id="chart-completion-title">Course completion by cohort</p>
</div>
<ul class="mp-chart__bars">
<li class="mp-chart__row"><span class="mp-chart__label">AI Literacy I</span><span class="mp-chart__track"><span class="mp-chart__fill" style="--mp-chart-value: 82%"></span></span><span class="mp-chart__value">82%</span></li>
<li class="mp-chart__row"><span class="mp-chart__label">Prompting for Teachers</span><span class="mp-chart__track"><span class="mp-chart__fill" style="--mp-chart-value: 64%"></span></span><span class="mp-chart__value">64%</span></li>
<li class="mp-chart__row"><span class="mp-chart__label">Developers' Lab</span><span class="mp-chart__track"><span class="mp-chart__fill" style="--mp-chart-value: 47%"></span></span><span class="mp-chart__value">47%</span></li>
</ul>
<figcaption class="mp-chart__caption">Learners who finished every module, 2026.</figcaption>
</figure>
Stacked, with legend
Enrollment by format
<figure class="mp-chart" aria-labelledby="chart-format-title">
<div class="mp-chart__header">
<p class="mp-chart__title" id="chart-format-title">Enrollment by format</p>
<ul class="mp-chart__legend">
<li class="mp-chart__key" data-series="1">Online</li>
<li class="mp-chart__key" data-series="2">Hybrid</li>
<li class="mp-chart__key" data-series="3">In person</li>
</ul>
</div>
<ul class="mp-chart__bars">
<li class="mp-chart__row"><span class="mp-chart__label">2024</span><span class="mp-chart__track"><span class="mp-chart__fill" data-series="1" style="--mp-chart-value: 40%"></span><span class="mp-chart__fill" data-series="2" style="--mp-chart-value: 25%"></span><span class="mp-chart__fill" data-series="3" style="--mp-chart-value: 35%"></span></span><span class="mp-chart__value">40 · 25 · 35%</span></li>
<li class="mp-chart__row"><span class="mp-chart__label">2025</span><span class="mp-chart__track"><span class="mp-chart__fill" data-series="1" style="--mp-chart-value: 52%"></span><span class="mp-chart__fill" data-series="2" style="--mp-chart-value: 28%"></span><span class="mp-chart__fill" data-series="3" style="--mp-chart-value: 20%"></span></span><span class="mp-chart__value">52 · 28 · 20%</span></li>
<li class="mp-chart__row"><span class="mp-chart__label">2026</span><span class="mp-chart__track"><span class="mp-chart__fill" data-series="1" style="--mp-chart-value: 61%"></span><span class="mp-chart__fill" data-series="2" style="--mp-chart-value: 27%"></span><span class="mp-chart__fill" data-series="3" style="--mp-chart-value: 12%"></span></span><span class="mp-chart__value">61 · 27 · 12%</span></li>
</ul>
</figure>
All six series
Learners by region
<figure class="mp-chart" aria-labelledby="chart-palette-title">
<div class="mp-chart__header">
<p class="mp-chart__title" id="chart-palette-title">Learners by region</p>
<ul class="mp-chart__legend">
<li class="mp-chart__key" data-series="1">Sudeste</li>
<li class="mp-chart__key" data-series="2">Nordeste</li>
<li class="mp-chart__key" data-series="3">Sul</li>
<li class="mp-chart__key" data-series="4">Norte</li>
<li class="mp-chart__key" data-series="5">Centro-Oeste</li>
<li class="mp-chart__key" data-series="6">Exterior</li>
</ul>
</div>
<ul class="mp-chart__bars">
<li class="mp-chart__row"><span class="mp-chart__label">2026</span><span class="mp-chart__track"><span class="mp-chart__fill" data-series="1" style="--mp-chart-value: 38%"></span><span class="mp-chart__fill" data-series="2" style="--mp-chart-value: 22%"></span><span class="mp-chart__fill" data-series="3" style="--mp-chart-value: 16%"></span><span class="mp-chart__fill" data-series="4" style="--mp-chart-value: 9%"></span><span class="mp-chart__fill" data-series="5" style="--mp-chart-value: 8%"></span><span class="mp-chart__fill" data-series="6" style="--mp-chart-value: 7%"></span></span><span class="mp-chart__value">100%</span></li>
</ul>
<figcaption class="mp-chart__caption">Shares of 3,214 learners. Legend order matches bar order.</figcaption>
</figure>
Content
Sizes and colors an inline line-icon SVG from the --size-icon-* tokens (20/24/32/48px) and the register/status text colors.
.mp-icondata-sizedata-toneSizes and tones
<div class="mp-cluster" data-gap="5">
<svg class="mp-icon" data-size="sm" viewBox="0 0 24 24" aria-hidden="true"><path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg>
<svg class="mp-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg>
<svg class="mp-icon" data-size="lg" data-tone="human" viewBox="0 0 24 24" aria-hidden="true"><path d="M22 10v6M2 10l10-5 10 5-10 5z"/><path d="M6 12v5c3 3 9 3 12 0v-5"/></svg>
<svg class="mp-icon" data-size="xl" data-tone="digital" viewBox="0 0 24 24" aria-hidden="true"><path d="m18 16 4-4-4-4M6 8l-4 4 4 4M14.5 4l-5 16"/></svg>
<svg class="mp-icon" data-tone="success" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg>
<svg class="mp-icon" data-tone="warning" viewBox="0 0 24 24" aria-hidden="true"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4M12 17h.01"/></svg>
<svg class="mp-icon" data-tone="error" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="m15 9-6 6M9 9l6 6"/></svg>
</div>
Feedback
An inline message about state — info, success, warning, error — or a human-register editorial note, with optional icon and actions.
.mp-alertdata-toneTones
Tokens are generated
Edit membrane.tokens.json, never the CSS.
Every contrast check passes
Light and dark mode, including hover states.
5 tokens are deprecated
They keep working until v3.0.0.
We couldn't save your draft
Your connection dropped. Nothing was lost — try again in a moment.
A note from the facilitator
Bring one real problem from your classroom. We'll build around it.
<div class="mp-stack" data-gap="3">
<div class="mp-alert">
<svg class="mp-alert__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5M12 8h.01"/></svg>
<div class="mp-alert__content">
<p class="mp-alert__title">Tokens are generated</p>
<p>Edit <code class="mp-code">membrane.tokens.json</code>, never the CSS.</p>
</div>
</div>
<div class="mp-alert" data-tone="success">
<div class="mp-alert__content">
<p class="mp-alert__title">Every contrast check passes</p>
<p>Light and dark mode, including hover states.</p>
</div>
</div>
<div class="mp-alert" data-tone="warning">
<div class="mp-alert__content">
<p class="mp-alert__title">5 tokens are deprecated</p>
<p>They keep working until v3.0.0.</p>
</div>
</div>
<div class="mp-alert" data-tone="error" role="alert">
<div class="mp-alert__content">
<p class="mp-alert__title">We couldn't save your draft</p>
<p>Your connection dropped. Nothing was lost — try again in a moment.</p>
<div class="mp-alert__actions"><button class="mp-button" type="button" data-size="sm" data-variant="secondary">Try again</button></div>
</div>
</div>
<div class="mp-alert" data-tone="human">
<div class="mp-alert__content">
<p class="mp-alert__title">A note from the facilitator</p>
<p>Bring one real problem from your classroom. We'll build around it.</p>
</div>
</div>
</div>
Feedback
Native <progress> bars (determinate or indeterminate, three sizes, register tones) and a spinner for short unmeasured waits.
.mp-progress .mp-spinnerdata-tonedata-sizeDeterminate and indeterminate
<div class="mp-stack">
<div class="mp-field">
<label class="mp-field__label" for="progress-course">Course completion — 64%</label>
<progress class="mp-progress" id="progress-course" value="64" max="100" data-tone="human">64%</progress>
</div>
<div class="mp-field">
<label class="mp-field__label" for="progress-upload">Uploading materials</label>
<progress class="mp-progress" id="progress-upload" data-size="sm"></progress>
</div>
<div class="mp-field">
<label class="mp-field__label" for="progress-gate">Modules completed — 8 of 8</label>
<progress class="mp-progress" id="progress-gate" value="8" max="8" data-tone="success" data-size="lg">8 of 8</progress>
</div>
</div>
Spinner
<div class="mp-cluster">
<span class="mp-spinner" aria-hidden="true"></span>
<span class="type-small" role="status">Generating feedback…</span>
</div>
Feedback
Placeholder text lines, circles and blocks that hold a layout's shape while content loads; they pulse in place under reduced motion.
.mp-skeletondata-variantLoading card
<div class="mp-card" aria-busy="true" aria-describedby="skeleton-status">
<span class="mp-visually-hidden" id="skeleton-status" role="status">Loading workshop…</span>
<div class="mp-skeleton" data-variant="block" aria-hidden="true"></div>
<div aria-hidden="true">
<div class="mp-skeleton" data-variant="text" style="--mp-skeleton-width: 40%"></div>
<div class="mp-skeleton" data-variant="text"></div>
<div class="mp-skeleton" data-variant="text"></div>
</div>
<div class="mp-cluster" aria-hidden="true">
<div class="mp-skeleton" data-variant="circle"></div>
<div class="mp-skeleton" data-variant="text" style="--mp-skeleton-width: 8rem"></div>
</div>
</div>
Feedback
What a view shows before it has content — icon on a warm wash, Fraunces title, one sentence of guidance and the next action.
.mp-emptydata-variantFirst use
Save essays and case studies while you browse — they'll wait for you here, in the order you saved them.
<div class="mp-empty">
<div class="mp-empty__media">
<svg class="mp-icon" data-size="xl" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 7v14M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/></svg>
</div>
<h3 class="mp-empty__title">Your reading list starts here</h3>
<p class="mp-empty__body">Save essays and case studies while you browse — they'll wait for you here, in the order you saved them.</p>
<div class="mp-empty__actions">
<a class="mp-button" href="#components">Browse essays</a>
</div>
</div>
No results (bordered)
Try a broader word, or clear the filters to see everything that's open this term.
<div class="mp-empty" data-variant="bordered">
<h3 class="mp-empty__title">No workshops match "robotics"</h3>
<p class="mp-empty__body">Try a broader word, or clear the filters to see everything that's open this term.</p>
<div class="mp-empty__actions">
<button class="mp-button" type="button" data-variant="secondary">Clear filters</button>
<button class="mp-button" type="button" data-variant="ghost">Suggest a topic</button>
</div>
</div>
Feedback · beta
A brief, polite confirmation of something the person just did — one live region per page, MembranePalette.toast() or a data-mp-toast button, auto-dismissed unless it's an error.
.mp-toast-region .mp-toastdata-leavingdata-tonedata-placementTones
Draft saved
Last edit 2 minutes ago.
Workshop shared
Ana can now edit the syllabus.
Working offline
Changes will sync when you reconnect.
Couldn't publish
The cohort is full. Nothing was lost.
<div class="mp-toast-region" data-placement="inline" aria-live="polite">
<div class="mp-toast" data-tone="success">
<div class="mp-toast__content"><p class="mp-toast__title">Draft saved</p><p>Last edit 2 minutes ago.</p></div>
<button class="mp-toast__close" type="button" aria-label="Dismiss">×</button>
</div>
<div class="mp-toast">
<div class="mp-toast__content"><p class="mp-toast__title">Workshop shared</p><p>Ana can now edit the syllabus.</p></div>
<button class="mp-toast__close" type="button" aria-label="Dismiss">×</button>
</div>
<div class="mp-toast" data-tone="warning">
<div class="mp-toast__content"><p class="mp-toast__title">Working offline</p><p>Changes will sync when you reconnect.</p></div>
<button class="mp-toast__close" type="button" aria-label="Dismiss">×</button>
</div>
<div class="mp-toast" data-tone="error" role="alert">
<div class="mp-toast__content"><p class="mp-toast__title">Couldn't publish</p><p>The cohort is full. Nothing was lost.</p></div>
<button class="mp-toast__close" type="button" aria-label="Dismiss">×</button>
</div>
</div>
Triggered by a button
<div class="mp-cluster">
<button class="mp-button" type="button" data-variant="secondary" data-mp-toast="Link copied" data-mp-toast-body="Paste it anywhere." data-mp-toast-tone="success">Copy link</button>
<button class="mp-button" type="button" data-variant="ghost" data-mp-toast="Couldn't reach the server" data-mp-toast-tone="error">Simulate an error</button>
</div>
Feedback
A short inverse-colored hint shown on hover and keyboard focus — CSS-only, hoverable, Escape-dismissible with membrane.js.
.mp-tooltipdata-placementTop and bottom
<div class="mp-cluster" data-gap="6">
<span class="mp-tooltip">
<button class="mp-button" type="button" data-variant="ghost" data-icon-only aria-label="Copy token" aria-describedby="tooltip-copy">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h2"/></svg>
</button>
<span class="mp-tooltip__content" role="tooltip" id="tooltip-copy">Copies the CSS variable name</span>
</span>
<span class="mp-tooltip" data-placement="bottom">
<button class="mp-button" type="button" data-variant="secondary" data-size="sm" aria-describedby="tooltip-gate">Contrast gate</button>
<span class="mp-tooltip__content" role="tooltip" id="tooltip-gate">Runs on every build</span>
</span>
</div>
Feedback
A modal built on native <dialog> — focus trapping, Escape and the backdrop come from the browser; header, body and footer slots.
.mp-dialogdata-sizeConfirmation dialog
<button class="mp-button" type="button" data-variant="secondary" commandfor="dialog-publish" command="show-modal">Publish workshop…</button>
<dialog class="mp-dialog" id="dialog-publish" data-size="sm" aria-labelledby="dialog-publish-title" closedby="any">
<div class="mp-dialog__header">
<h2 class="mp-dialog__title" id="dialog-publish-title">Publish this workshop?</h2>
<button class="mp-button" type="button" data-variant="ghost" data-size="sm" data-icon-only aria-label="Close" commandfor="dialog-publish" command="close">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"/></svg>
</button>
</div>
<div class="mp-dialog__body">
<p>It becomes visible to all 3,214 educators in the community, and they'll get an email invitation.</p>
</div>
<div class="mp-dialog__footer">
<button class="mp-button" type="button" data-variant="ghost" commandfor="dialog-publish" command="close">Not yet</button>
<button class="mp-button" type="button" commandfor="dialog-publish" command="close">Publish</button>
</div>
</dialog>
Large reading dialog
<button class="mp-button" type="button" data-variant="ghost" commandfor="dialog-syllabus" command="show-modal">Read the syllabus</button>
<dialog class="mp-dialog" id="dialog-syllabus" data-size="lg" aria-labelledby="dialog-syllabus-title" closedby="any">
<div class="mp-dialog__header">
<h2 class="mp-dialog__title" id="dialog-syllabus-title">AI Literacy I — syllabus</h2>
<button class="mp-button" type="button" data-variant="ghost" data-size="sm" data-icon-only aria-label="Close" commandfor="dialog-syllabus" command="close">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"/></svg>
</button>
</div>
<div class="mp-dialog__body mp-prose">
<h3>Week 1 — Start from the classroom</h3>
<p>Bring one real problem. We map it before we touch a tool.</p>
<h3>Week 2 — How models actually work</h3>
<p>Tokens, context, and why a confident answer can still be wrong.</p>
</div>
<div class="mp-dialog__footer">
<button class="mp-button" type="button" commandfor="dialog-syllabus" command="close">Done</button>
</div>
</dialog>
Navigation
Sticky translucent site header with brand, uppercase links (aria-current marks the active page) and an actions slot; collapses by its own width.
.mp-navbarSite header
<header class="mp-navbar">
<div class="mp-navbar__inner">
<a class="mp-navbar__brand" href="#components">D'Césares</a>
<nav class="mp-navbar__nav" aria-label="Primary">
<ul class="mp-navbar__links">
<li><a class="mp-navbar__link" href="#components" aria-current="page">Work</a></li>
<li><a class="mp-navbar__link" href="#components">Writing</a></li>
<li><a class="mp-navbar__link" href="#components">Workshops</a></li>
<li><a class="mp-navbar__link" href="#components">About</a></li>
</ul>
</nav>
<div class="mp-navbar__actions">
<a class="mp-button" href="#components" data-size="sm">See the work</a>
</div>
</div>
</header>
Navigation
The path from site root to the current page, as an ordered list with decorative separators and aria-current on the last item.
.mp-breadcrumbPath
<nav class="mp-breadcrumb" aria-label="Breadcrumb">
<ol class="mp-breadcrumb__list">
<li class="mp-breadcrumb__item"><a class="mp-breadcrumb__link" href="#components">Home</a></li>
<li class="mp-breadcrumb__item"><a class="mp-breadcrumb__link" href="#components">Workshops</a></li>
<li class="mp-breadcrumb__item"><a class="mp-breadcrumb__link" href="#components" aria-current="page">AI Literacy I</a></li>
</ol>
</nav>
Navigation
WAI-ARIA tabs — underline or pill (segmented) style; aria-selected drives the visuals, membrane.js adds click and arrow-key behavior.
.mp-tabsdata-variantUnderline tabs
One <link> to membrane.css on jsDelivr.
Download the three CSS files into your project.
Edit the JSON source and run the build.
<div class="mp-tabs">
<div class="mp-tabs__list" role="tablist" aria-label="Install options">
<button class="mp-tabs__tab" type="button" role="tab" id="tabs-cdn" aria-controls="tabs-cdn-panel" aria-selected="true">CDN</button>
<button class="mp-tabs__tab" type="button" role="tab" id="tabs-copy" aria-controls="tabs-copy-panel" aria-selected="false" tabindex="-1">Copy files</button>
<button class="mp-tabs__tab" type="button" role="tab" id="tabs-fork" aria-controls="tabs-fork-panel" aria-selected="false" tabindex="-1">Fork</button>
</div>
<div class="mp-tabs__panel" role="tabpanel" id="tabs-cdn-panel" aria-labelledby="tabs-cdn" tabindex="0"><p class="type-small">One <code class="mp-code"><link></code> to <code class="mp-code">membrane.css</code> on jsDelivr.</p></div>
<div class="mp-tabs__panel" role="tabpanel" id="tabs-copy-panel" aria-labelledby="tabs-copy" tabindex="0" hidden><p class="type-small">Download the three CSS files into your project.</p></div>
<div class="mp-tabs__panel" role="tabpanel" id="tabs-fork-panel" aria-labelledby="tabs-fork" tabindex="0" hidden><p class="type-small">Edit the JSON source and run the build.</p></div>
</div>
Pill tabs
Warm cream, terracotta emphasis.
Charcoal depth, lightened accents.
<div class="mp-tabs" data-variant="pill">
<div class="mp-tabs__list" role="tablist" aria-label="Theme preview">
<button class="mp-tabs__tab" type="button" role="tab" id="tabs-light" aria-controls="tabs-light-panel" aria-selected="true">Light</button>
<button class="mp-tabs__tab" type="button" role="tab" id="tabs-dark" aria-controls="tabs-dark-panel" aria-selected="false" tabindex="-1">Dark</button>
</div>
<div class="mp-tabs__panel" role="tabpanel" id="tabs-light-panel" aria-labelledby="tabs-light" tabindex="0"><p class="type-small">Warm cream, terracotta emphasis.</p></div>
<div class="mp-tabs__panel" role="tabpanel" id="tabs-dark-panel" aria-labelledby="tabs-dark" tabindex="0" hidden><p class="type-small">Charcoal depth, lightened accents.</p></div>
</div>
Navigation
Expandable sections on native <details>/<summary> — no script, keyboard-ready, exclusive with a shared name, animated where supported.
.mp-accordionFAQ
No. Link one stylesheet and write HTML with mp- classes.
No. Every semantic token carries its own light and dark value.
Yes — start from components/manifest.json.
<div>
<details class="mp-accordion" name="accordion-faq" open>
<summary class="mp-accordion__summary">Do I need a framework?</summary>
<div class="mp-accordion__content"><p>No. Link one stylesheet and write HTML with <code class="mp-code">mp-</code> classes.</p></div>
</details>
<details class="mp-accordion" name="accordion-faq">
<summary class="mp-accordion__summary">Does dark mode need extra CSS?</summary>
<div class="mp-accordion__content"><p>No. Every semantic token carries its own light and dark value.</p></div>
</details>
<details class="mp-accordion" name="accordion-faq">
<summary class="mp-accordion__summary">Can agents use it?</summary>
<div class="mp-accordion__content"><p>Yes — start from <code class="mp-code">components/manifest.json</code>.</p></div>
</details>
</div>
Navigation
Numbered page links with previous/next; aria-current marks the current page (teal pill), and narrow containers collapse to previous · current · next.
.mp-paginationPages
<nav class="mp-pagination" aria-label="Essays pages">
<ul class="mp-pagination__list">
<li class="mp-pagination__item"><a class="mp-pagination__link" href="#components" rel="prev">← Previous</a></li>
<li class="mp-pagination__item"><a class="mp-pagination__link" href="#components">1</a></li>
<li class="mp-pagination__item"><a class="mp-pagination__link" href="#components" aria-current="page">2</a></li>
<li class="mp-pagination__item"><a class="mp-pagination__link" href="#components">3</a></li>
<li class="mp-pagination__item"><span class="mp-pagination__gap" aria-hidden="true">…</span></li>
<li class="mp-pagination__item"><a class="mp-pagination__link" href="#components">12</a></li>
<li class="mp-pagination__item"><a class="mp-pagination__link" href="#components" rel="next">Next →</a></li>
</ul>
</nav>
First page
<nav class="mp-pagination" aria-label="Cohort pages">
<ul class="mp-pagination__list">
<li class="mp-pagination__item"><a class="mp-pagination__link" aria-disabled="true">← Previous</a></li>
<li class="mp-pagination__item"><a class="mp-pagination__link" href="#components" aria-current="page">1</a></li>
<li class="mp-pagination__item"><a class="mp-pagination__link" href="#components">2</a></li>
<li class="mp-pagination__item"><a class="mp-pagination__link" href="#components" rel="next">Next →</a></li>
</ul>
</nav>
Navigation
Progress through an ordered sequence — course modules, onboarding, a multi-page form — vertical or horizontal, with complete, current and upcoming steps.
.mp-stepsdata-statusdata-orientationCourse modules
Start from the classroom (completed)
Map one real problem before touching a tool.
How models actually work
Tokens, context, and why confident answers can be wrong.
Design the assistant
Co-create the prompts with your students.
<ol class="mp-steps" aria-label="Course progress">
<li class="mp-steps__item" data-status="complete">
<p class="mp-steps__label">Start from the classroom<span class="mp-visually-hidden"> (completed)</span></p>
<p class="mp-steps__description">Map one real problem before touching a tool.</p>
</li>
<li class="mp-steps__item" aria-current="step">
<p class="mp-steps__label">How models actually work</p>
<p class="mp-steps__description">Tokens, context, and why confident answers can be wrong.</p>
</li>
<li class="mp-steps__item">
<p class="mp-steps__label">Design the assistant</p>
<p class="mp-steps__description">Co-create the prompts with your students.</p>
</li>
</ol>
Horizontal
Account (completed)
Cohort (completed)
Payment
Done
<ol class="mp-steps" data-orientation="horizontal" aria-label="Enrollment">
<li class="mp-steps__item" data-status="complete"><p class="mp-steps__label">Account<span class="mp-visually-hidden"> (completed)</span></p></li>
<li class="mp-steps__item" data-status="complete"><p class="mp-steps__label">Cohort<span class="mp-visually-hidden"> (completed)</span></p></li>
<li class="mp-steps__item" aria-current="step"><p class="mp-steps__label">Payment</p></li>
<li class="mp-steps__item"><p class="mp-steps__label">Done</p></li>
</ol>
Navigation · beta
A list of actions in a native popover — opened by a popovertarget button, light-dismissed by the browser, arrow-key navigable with membrane.js.
.mp-menudata-toneActions menu
<button class="mp-button" type="button" data-variant="secondary" popovertarget="menu-workshop" aria-haspopup="menu" aria-expanded="false">Workshop actions</button>
<div class="mp-menu" id="menu-workshop" popover role="menu" aria-label="Workshop actions">
<p class="mp-menu__label" role="presentation">Edit</p>
<button class="mp-menu__item" type="button" role="menuitem">
<svg class="mp-icon" viewBox="0 0 24 24" aria-hidden="true"><rect x="8" y="8" width="14" height="14" rx="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>
Duplicate
</button>
<button class="mp-menu__item" type="button" role="menuitem">Export syllabus</button>
<button class="mp-menu__item" type="button" role="menuitem" aria-disabled="true">Move to cohort (none open)</button>
<hr class="mp-menu__separator">
<button class="mp-menu__item" type="button" role="menuitem" data-tone="danger">Archive workshop</button>
</div>
05 / Compositions
Choose a reference by what someone needs to understand or do. These references connect the same components into visual compositions and complete tasks, including bilingual exploration and a form journey.
Invite someone to learn
A human opening, an ordered path and practical preparation. Use it to introduce a learning experience.
Explain a relationship
A question becomes a diagram, with the proposed method and limitation nearby. Use it for careful conceptual explanation.
Present an argument
Six canvases move from a question to a method and a qualification. Read on a phone or print six landscape pages.
Find and inspect
Search and filter a bilingual catalog, keep a selected resource in context, and explore cancel, retry, partial and empty states.
Complete a task
Enter a learning goal, correct errors, review and edit your choices, then try a local confirmation with deliberate failure and retry.
Compose with original artwork
Organic gestures meet precise frames across a website opening, presentation cover and teaching card. Includes six original constructions with editable SVG downloads.
All six contain illustrative content. See the composition guide for adaptation notes, creative freedom and the visual review rubric, and the visual language guide for motifs, arrangements and editable assets.
Complete task patterns · Accessibility evidence and remaining checks
06 / Reference
The tables below are rendered from tokens/membrane.tokens.json by the same build that writes the CSS, and the component gallery above from each component's README. There is no second copy to fall out of sync.
Do / Don't
background: var(--color-action-primary);
Retheme is automatic — the semantic token already carries its light-dark() pair.
background: var(--color-terracotta);
A Tier 1 primitive never changes with the theme. Component CSS that does this fails the build.
<button class="mp-button" aria-busy="true">
State comes from ARIA: the spinner appears and assistive tech hears "busy".
<button class="mp-button is-loading">
Invented state classes do nothing visually and announce nothing.
color: var(--color-warning-text);
Gate-checked at ≥4.5:1 on page, card and warning-wash surfaces — passes WCAG AA for body text.
color: var(--color-warning);
2.3:1 as text on cream — this token is a fill/badge color, not a text color.
<a class="mp-button" data-variant="secondary">
Options are data-* attributes with a closed set of values, listed in the manifest.
<a class="mp-button mp-button--outline">
That class doesn't exist. The docs lint rejects any class or value the CSS doesn't implement.
For Agents
The component API and index are generated from source. Composition guidance adds reviewed examples of complete pieces.
mp- utilities compile{
"slug": "button",
"attributes": {
"data-variant": ["secondary", "ghost", "danger"],
"data-size": ["sm", "lg"]
},
"states": [":disabled", "[aria-busy=\"true\"]", …]
}
Token Table
| Preview | Token | Category | Description |
|---|---|---|---|
--bg-glow-focal |
Glow | ||
--bg-glow-focal-loaded |
Glow | ||
--bg-glow-sage |
Glow | ||
--bg-glow-teal |
Glow | ||
--bg-glow-terracotta |
Glow | ||
--blur-backdrop |
Blur | Backdrop blur for translucent surfaces (nav bars, veils). | |
--border-accent |
Border | ||
--border-default |
Border | ||
--border-emphasis |
Border | ||
--border-width-medium |
Border-width | ||
--border-width-thick |
Border-width | ||
--border-width-thin |
Border-width | ||
--code-bg |
Code | ||
--code-border |
Code | ||
--code-comment |
Code | v2.1: lightened from #7D776E (3.7:1 on code-bg, failing WCAG AA for text) to 5.2:1. | |
--code-function |
Code | ||
--code-keyword |
Code | ||
--code-number |
Code | ||
--code-string |
Code | ||
--code-text |
Code | ||
--color-action-primary |
Color / Semantic | Primary CTAs and key interactive accents. Replaces direct use of --color-terracotta on interactive elements. | |
--color-action-primary-hover |
Color / Semantic | Hover/pressed fill for primary actions. Mixes toward text-primary, so it darkens in light mode and lightens in dark mode — contrast with text-on-accent always increases. | |
--color-action-secondary |
Color / Semantic | Secondary/navigational actions. | |
--color-action-secondary-hover |
Color / Semantic | Hover/pressed fill for secondary actions. | |
--color-amber |
Color / Primitive | Making energy. Fill/badge use only — fails text contrast on cream; use semantic warning-text for text. | |
--color-amber-10 |
Color / Tint | ||
--color-amber-light |
Color / Primitive | ||
--color-bg-active |
Color / Semantic | Neutral pressed/selected wash. Pair with bg-hover. | |
--color-bg-elevated |
Color / Semantic | Surfaces that float above the page: dialogs, popovers, menus. In dark mode elevation reads as a lighter surface, not just a deeper shadow. | |
--color-bg-hover |
Color / Semantic | Neutral hover wash for quiet controls (ghost buttons, nav links, table rows, accordion summaries). Works on any surface because it is a translucent overlay. | |
--color-bg-inverse |
Color / Semantic | Inverted surface for tooltips and high-attention chips. Pair with text-inverse. | |
--color-bg-primary |
Color / Semantic | Page background — the membrane surface. | |
--color-bg-secondary |
Color / Semantic | Cards and alternating sections. | |
--color-bg-tertiary |
Color / Semantic | Nested containers, neutral tag fills, progress tracks. | |
--color-border-default |
Color / Semantic | Decorative dividers and card outlines. Too faint to be the only boundary of a control — use border-input there. | |
--color-border-emphasis |
Color / Semantic | Emphasized separation; hover border for quiet surfaces. | |
--color-border-input |
Color / Semantic | Boundary of form controls (inputs, checkboxes, switches). ≥3:1 against page and card surfaces per WCAG 1.4.11 — border-default is decorative and too faint to be a control's only boundary. | |
--color-burgundy |
Color / Primitive | Heritage depth. | |
--color-burgundy-10 |
Color / Tint | ||
--color-burgundy-light |
Color / Primitive | ||
--color-charcoal |
Color / Primitive | Dark canvas. Never pure black. | |
--color-chart-1 |
Color / Semantic | Categorical chart series 1 (terracotta — human register; the brand's lead series). Assign in order, never cycle; validated as a set (adjacent CVD ΔE ≥ 11.5, ≥3:1 on page and cards in both modes). | |
--color-chart-2 |
Color / Semantic | Categorical chart series 2 (teal — digital register). Assign in order, never cycle; validated as a set (adjacent CVD ΔE ≥ 11.5, ≥3:1 on page and cards in both modes). | |
--color-chart-3 |
Color / Semantic | Categorical chart series 3 (amber). Assign in order, never cycle; validated as a set (adjacent CVD ΔE ≥ 11.5, ≥3:1 on page and cards in both modes). | |
--color-chart-4 |
Color / Semantic | Categorical chart series 4 (burgundy). Assign in order, never cycle; validated as a set (adjacent CVD ΔE ≥ 11.5, ≥3:1 on page and cards in both modes). | |
--color-chart-5 |
Color / Semantic | Categorical chart series 5 (steel blue). Assign in order, never cycle; validated as a set (adjacent CVD ΔE ≥ 11.5, ≥3:1 on page and cards in both modes). | |
--color-chart-6 |
Color / Semantic | Categorical chart series 6 (green). Assign in order, never cycle; validated as a set (adjacent CVD ΔE ≥ 11.5, ≥3:1 on page and cards in both modes). | |
--color-cream |
Color / Primitive | Light canvas. Never pure white. | |
--color-digital-bg |
Color / Semantic | Digital-register wash. Pair with digital-text. | |
--color-digital-text |
Color / Semantic | Digital-register text: tech-stack tags, code-adjacent labels. ≥4.5:1 on page, card, and digital-bg surfaces. | |
--color-error |
Color / Semantic | Error fills, icons, invalid-control borders, danger buttons (≥3:1). | |
--color-error-bg |
Color / Semantic | Error surface. Pair with error-text. | |
--color-error-hover |
Color / Semantic | Hover/pressed fill for destructive actions. | |
--color-error-text |
Color / Semantic | Error body text and validation messages (≥4.5:1 on page, card, and error-bg). | |
--color-focus |
Color / Semantic | Focus indicator color. v2.0: dark mode now remaps to teal-light (raw teal was ~3:1 on charcoal). | |
--color-human-bg |
Color / Semantic | Human-register wash for tags, avatars, callouts. Pair with human-text. | |
--color-human-text |
Color / Semantic | Human-register text: overlines, tags, pull quotes, active nav. ≥4.5:1 on page, card, and human-bg surfaces. | |
--color-info |
Color / Semantic | Informational fills and icons. | |
--color-info-bg |
Color / Semantic | Informational surface. Pair with info-text. | |
--color-info-text |
Color / Semantic | Informational body text (4.5:1 on page, card, and info-bg). | |
--color-neutral-100 |
Color / Neutral | ||
--color-neutral-200 |
Color / Neutral | ||
--color-neutral-300 |
Color / Neutral | ||
--color-neutral-400 |
Color / Neutral | ||
--color-neutral-50 |
Color / Neutral | ||
--color-neutral-500 |
Color / Neutral | ||
--color-neutral-600 |
Color / Neutral | ||
--color-neutral-700 |
Color / Neutral | ||
--color-neutral-800 |
Color / Neutral | ||
--color-neutral-900 |
Color / Neutral | ||
--color-overlay-bg |
Color / Semantic | Scrims and image-readability layers. Intentionally identical in both modes. | |
--color-sage |
Color / Primitive | Growth. Fill/icon use; use semantic success-text for text on light surfaces. | |
--color-sage-10 |
Color / Tint | ||
--color-sage-light |
Color / Primitive | ||
--color-selection |
Color / Semantic | Text selection highlight. | |
--color-success |
Color / Semantic | Fills, icons, large text (≥3:1). For body-size text use success-text. | |
--color-success-bg |
Color / Semantic | Success surface for alerts and badges. Pair with success-text. | |
--color-success-text |
Color / Semantic | Success body text (≥4.5:1 on page, card, and success-bg). | |
--color-teal |
Color / Primitive | Secondary brand. The digital register: technology, depth, Rio's ocean. | |
--color-teal-08 |
Color / Tint | ||
--color-teal-10 |
Color / Tint | ||
--color-teal-12 |
Color / Tint | ||
--color-teal-20 |
Color / Tint | ||
--color-teal-dark |
Color / Primitive | ||
--color-teal-light |
Color / Primitive | ||
--color-terracotta |
Color / Primitive | Primary brand. The human register: earth, hands, making, Brazilian clay. | |
--color-terracotta-10 |
Color / Tint | ||
--color-terracotta-20 |
Color / Tint | ||
--color-terracotta-dark |
Color / Primitive | ||
--color-terracotta-light |
Color / Primitive | ||
--color-text-accent |
Color / Semantic | Inline links and interactive text. | |
--color-text-inverse |
Color / Semantic | Text on bg-inverse. | |
--color-text-on-accent |
Color / Semantic | v2.0: flips to charcoal in dark mode — white on the lightened terracotta was 3.3:1. | |
--color-text-primary |
Color / Semantic | Primary body text and headings. | |
--color-text-secondary |
Color / Semantic | Supporting text: ledes, descriptions, captions. | |
--color-text-tertiary |
Color / Semantic | Metadata, placeholders. v2.0: darkened from neutral-400 (2.5:1) to pass WCAG AA 4.5:1 on bg-primary and bg-secondary. | |
--color-warning |
Color / Semantic | Fills and badges with dark text on top. Never use as text on light surfaces — 2.3:1. | |
--color-warning-bg |
Color / Semantic | Warning surface. Pair with warning-text. | |
--color-warning-text |
Color / Semantic | Warning body text (≥4.5:1 on page, card, and warning-bg). | |
--container-full |
Container | ||
--container-lg |
Container | ||
--container-md |
Container | ||
--container-sm |
Container | ||
--container-xl |
Container | ||
--duration-fast |
Duration | Micro-interactions: hover color, press, exits. | |
--duration-loop |
Duration | Period of continuous loading loops (progress, skeleton; spinners turn at half). New in v2.1 — replaces literal seconds in components. | |
--duration-normal |
Duration | Standard: entrances, state changes, popovers. | |
--duration-slow |
Duration | Larger surfaces: card lift, section reveals. | |
--duration-slower |
Duration | Page-level: view transitions, hero entrance. Stays 150ms under reduced motion for essential feedback. | |
--ease-default |
Ease | General purpose: hover and color changes. | |
--ease-in |
Ease | Leaving: accelerates away (a respectful exit). | |
--ease-in-out |
Ease | State changes that neither enter nor leave (§8.1 rule 3). New in v2.1 — the rule existed without a token. | |
--ease-out |
Ease | Entering: decelerates into place (welcoming). | |
--ease-spring |
Ease | Playful overshoot for small toggles only (the switch thumb). Never on surfaces or text. | |
--elevation-modal |
Elevation | ||
--elevation-overlay |
Elevation | ||
--elevation-raised |
Elevation | ||
--focus-ring |
Focus | ||
--focus-ring-offset |
Focus | ||
--font-mono |
Font | ||
--font-sans |
Font | ||
--font-serif |
Font | ||
--gradient-depth |
Gradient | ||
--gradient-divider |
Gradient | ||
--gradient-membrane |
Gradient | Signature gradient, human → digital. v2.0: endpoints now lighten in dark mode per spec §12.2. | |
--gradient-subtle |
Gradient | ||
--gradient-warmth |
Gradient | ||
--leading-body |
Leading | ||
--leading-body-lg |
Leading | ||
--leading-code |
Leading | ||
--leading-display |
Leading | ||
--leading-heading |
Leading | ||
--leading-label |
Leading | ||
--leading-small |
Leading | ||
--leading-subheading |
Leading | ||
--measure |
Layout | Maximum line length for body copy (DESIGN-SYSTEM.md §3.5 rule 5). | |
--opacity-heavy |
Opacity | ||
--opacity-light |
Opacity | ||
--opacity-medium |
Opacity | ||
--opacity-overlay |
Opacity | ||
--opacity-subtle |
Opacity | ||
--photo-border-radius |
Photo | ||
--photo-dim-dark |
Photo | Recommended brightness() factor for photos on dark surfaces (spec §12.2 rule 6). Applied by the consumer, not automatically. | |
--photo-shadow |
Photo | ||
--photo-warmth |
Photo | ||
--radius-full |
Radius | ||
--radius-lg |
Radius | ||
--radius-md |
Radius | ||
--radius-sm |
Radius | ||
--radius-xl |
Radius | ||
--shadow-glow-teal |
Shadow | v2.0: dark variant added (was unmapped). | |
--shadow-glow-warm |
Shadow | ||
--shadow-lg |
Shadow | ||
--shadow-md |
Shadow | ||
--shadow-sm |
Shadow | ||
--site-margin |
Layout | ||
--size-control-lg |
Size | Prominent control height (hero CTAs). | |
--size-control-md |
Size | Default control height (buttons, inputs, tabs). Equals touch-target. | |
--size-control-sm |
Size | Compact control height for dense, pointer-driven UI. Components grow it to control-md on coarse pointers. | |
--size-icon-lg |
Size | Feature icons. | |
--size-icon-md |
Size | Standard icons. | |
--size-icon-sm |
Size | Inline icons. | |
--size-icon-xl |
Size | Hero icons. | |
--size-nav |
Size | Navigation bar height, desktop. | |
--size-nav-mobile |
Size | Navigation bar height, mobile. | |
--size-touch-target |
Size | Minimum interactive target (WCAG 2.5.5 AAA; the AA floor in 2.5.8 is 24px). | |
--space-1 |
Space | ||
--space-10 |
Space | ||
--space-12 |
Space | ||
--space-16 |
Space | ||
--space-2 |
Space | ||
--space-20 |
Space | ||
--space-24 |
Space | ||
--space-3 |
Space | ||
--space-32 |
Space | ||
--space-4 |
Space | ||
--space-5 |
Space | ||
--space-6 |
Space | ||
--space-8 |
Space | ||
--state-disabled-opacity |
State | ||
--text-base deprecated |
Text | Compatibility alias. | |
--text-body |
Text | ||
--text-body-lg |
Text | ||
--text-code |
Text | ||
--text-display |
Text | ||
--text-h1 |
Text | ||
--text-h2 |
Text | ||
--text-h3 |
Text | ||
--text-h4 |
Text | ||
--text-lg deprecated |
Text | Compatibility alias. | |
--text-md deprecated |
Text | Compatibility alias. | |
--text-sm deprecated |
Text | Compatibility alias. | |
--text-small |
Text | ||
--text-xl deprecated |
Text | Compatibility alias. | |
--text-xs |
Text | ||
--tracking-body |
Tracking | ||
--tracking-display |
Tracking | ||
--tracking-heading |
Tracking | ||
--tracking-label |
Tracking | ||
--tracking-small |
Tracking | ||
--tracking-subheading |
Tracking | ||
--transition-default |
Transition | ||
--transition-enter |
Transition | Something appearing: dialogs, menus, toasts, tooltips. New in v2.1. | |
--transition-exit |
Transition | Something leaving — faster than its entrance, so the interface never waits on a goodbye. New in v2.1. | |
--transition-fast |
Transition | ||
--transition-slow |
Transition | ||
--transition-state |
Transition | A control changing state in place: switch, checkbox, tab indicator, chevron. New in v2.1. | |
--weight-bold |
Weight | ||
--weight-medium |
Weight | ||
--weight-regular |
Weight | ||
--weight-semibold |
Weight | ||
--z-base |
Z | ||
--z-dropdown |
Z | ||
--z-modal |
Z | ||
--z-nav |
Z | ||
--z-overlay |
Z | ||
--z-sticky |
Z | ||
--z-toast |
Z | ||
--z-tooltip |
Z |
Contrast Matrix
Generated from the exact computation that fails npm run build:tokens if a pair regresses — including hover fills, status washes and code syntax colors. See the GATE list in scripts/build-tokens.mjs.
| Mode | Foreground | Background | Ratio | Minimum | Status |
|---|---|---|---|---|---|
| light | --color-text-primary |
--color-bg-primary |
13.93:1 | 7.0:1 | Pass |
| light | --color-text-primary |
--color-bg-secondary |
12.64:1 | 7.0:1 | Pass |
| light | --color-text-primary |
--color-bg-elevated |
13.93:1 | 7.0:1 | Pass |
| light | --color-text-primary |
--color-bg-active |
11.52:1 | 7.0:1 | Pass |
| light | --color-text-secondary |
--color-bg-primary |
6.73:1 | 4.5:1 | Pass |
| light | --color-text-secondary |
--color-bg-secondary |
6.10:1 | 4.5:1 | Pass |
| light | --color-text-secondary |
--color-bg-tertiary |
5.32:1 | 4.5:1 | Pass |
| light | --color-text-secondary |
--color-bg-elevated |
6.73:1 | 4.5:1 | Pass |
| light | --color-text-secondary |
--color-bg-hover |
6.04:1 | 4.5:1 | Pass |
| light | --color-text-tertiary |
--color-bg-primary |
5.12:1 | 4.5:1 | Pass |
| light | --color-text-tertiary |
--color-bg-secondary |
4.64:1 | 4.5:1 | Pass |
| light | --color-text-tertiary |
--color-bg-elevated |
5.12:1 | 4.5:1 | Pass |
| light | --color-text-accent |
--color-bg-primary |
5.11:1 | 4.5:1 | Pass |
| light | --color-text-accent |
--color-bg-secondary |
4.64:1 | 4.5:1 | Pass |
| light | --color-text-inverse |
--color-bg-inverse |
12.64:1 | 4.5:1 | Pass |
| light | --color-text-on-accent |
--color-action-primary |
4.93:1 | 4.5:1 | Pass |
| light | --color-text-on-accent |
--color-action-primary-hover |
5.92:1 | 4.5:1 | Pass |
| light | --color-text-on-accent |
--color-action-secondary |
5.51:1 | 4.5:1 | Pass |
| light | --color-text-on-accent |
--color-action-secondary-hover |
6.51:1 | 4.5:1 | Pass |
| light | --color-text-on-accent |
--color-error |
5.05:1 | 4.5:1 | Pass |
| light | --color-text-on-accent |
--color-error-hover |
6.06:1 | 4.5:1 | Pass |
| light | --color-action-primary |
--color-bg-primary |
4.57:1 | 3.0:1 | Pass |
| light | --color-action-secondary |
--color-bg-primary |
5.11:1 | 3.0:1 | Pass |
| light | --color-action-secondary |
--color-bg-secondary |
4.64:1 | 3.0:1 | Pass |
| light | --color-action-secondary |
--color-bg-tertiary |
4.04:1 | 3.0:1 | Pass |
| light | --color-border-input |
--color-bg-primary |
4.11:1 | 3.0:1 | Pass |
| light | --color-border-input |
--color-bg-secondary |
3.73:1 | 3.0:1 | Pass |
| light | --color-border-input |
--color-bg-elevated |
4.11:1 | 3.0:1 | Pass |
| light | --color-focus |
--color-bg-primary |
5.11:1 | 3.0:1 | Pass |
| light | --color-focus |
--color-bg-secondary |
4.64:1 | 3.0:1 | Pass |
| light | --color-focus |
--color-bg-elevated |
5.11:1 | 3.0:1 | Pass |
| light | --color-human-text |
--color-bg-primary |
6.26:1 | 4.5:1 | Pass |
| light | --color-human-text |
--color-bg-secondary |
5.68:1 | 4.5:1 | Pass |
| light | --color-human-text |
--color-human-bg |
5.51:1 | 4.5:1 | Pass |
| light | --color-human-text |
--color-human-bg |
5.02:1 | 4.5:1 | Pass |
| light | --color-digital-text |
--color-bg-primary |
7.23:1 | 4.5:1 | Pass |
| light | --color-digital-text |
--color-bg-secondary |
6.56:1 | 4.5:1 | Pass |
| light | --color-digital-text |
--color-digital-bg |
6.32:1 | 4.5:1 | Pass |
| light | --color-digital-text |
--color-digital-bg |
5.76:1 | 4.5:1 | Pass |
| light | --color-success |
--color-bg-primary |
3.68:1 | 3.0:1 | Pass |
| light | --color-success-text |
--color-bg-primary |
5.68:1 | 4.5:1 | Pass |
| light | --color-success-text |
--color-bg-secondary |
5.15:1 | 4.5:1 | Pass |
| light | --color-success-text |
--color-success-bg |
5.09:1 | 4.5:1 | Pass |
| light | --color-success-text |
--color-success-bg |
4.65:1 | 4.5:1 | Pass |
| light | --color-warning-text |
--color-bg-primary |
6.08:1 | 4.5:1 | Pass |
| light | --color-warning-text |
--color-bg-secondary |
5.51:1 | 4.5:1 | Pass |
| light | --color-warning-text |
--color-warning-bg |
5.63:1 | 4.5:1 | Pass |
| light | --color-warning-text |
--color-warning-bg |
5.15:1 | 4.5:1 | Pass |
| light | --color-error |
--color-bg-primary |
4.69:1 | 3.0:1 | Pass |
| light | --color-error-text |
--color-bg-primary |
6.20:1 | 4.5:1 | Pass |
| light | --color-error-text |
--color-bg-secondary |
5.63:1 | 4.5:1 | Pass |
| light | --color-error-text |
--color-error-bg |
5.42:1 | 4.5:1 | Pass |
| light | --color-error-text |
--color-error-bg |
4.94:1 | 4.5:1 | Pass |
| light | --color-info-text |
--color-bg-primary |
7.23:1 | 4.5:1 | Pass |
| light | --color-info-text |
--color-info-bg |
6.32:1 | 4.5:1 | Pass |
| light | --color-info-text |
--color-info-bg |
5.76:1 | 4.5:1 | Pass |
| light | --color-success-text |
--color-bg-elevated |
5.68:1 | 4.5:1 | Pass |
| light | --color-warning-text |
--color-bg-elevated |
6.08:1 | 4.5:1 | Pass |
| light | --color-error-text |
--color-bg-elevated |
6.20:1 | 4.5:1 | Pass |
| light | --color-text-primary |
--color-bg-hover |
11.31:1 | 7.0:1 | Pass |
| light | --color-text-primary |
--color-bg-active |
11.52:1 | 7.0:1 | Pass |
| light | --color-text-secondary |
--color-bg-elevated |
6.73:1 | 4.5:1 | Pass |
| light | --color-focus |
--color-bg-active |
4.23:1 | 3.0:1 | Pass |
| light | --color-chart-1 |
--color-bg-primary |
4.57:1 | 3.0:1 | Pass |
| light | --color-chart-1 |
--color-bg-secondary |
4.15:1 | 3.0:1 | Pass |
| light | --color-chart-2 |
--color-bg-primary |
3.61:1 | 3.0:1 | Pass |
| light | --color-chart-2 |
--color-bg-secondary |
3.27:1 | 3.0:1 | Pass |
| light | --color-chart-3 |
--color-bg-primary |
3.86:1 | 3.0:1 | Pass |
| light | --color-chart-3 |
--color-bg-secondary |
3.50:1 | 3.0:1 | Pass |
| light | --color-chart-4 |
--color-bg-primary |
6.00:1 | 3.0:1 | Pass |
| light | --color-chart-4 |
--color-bg-secondary |
5.44:1 | 3.0:1 | Pass |
| light | --color-chart-5 |
--color-bg-primary |
3.80:1 | 3.0:1 | Pass |
| light | --color-chart-5 |
--color-bg-secondary |
3.45:1 | 3.0:1 | Pass |
| light | --color-chart-6 |
--color-bg-primary |
3.62:1 | 3.0:1 | Pass |
| light | --color-chart-6 |
--color-bg-secondary |
3.29:1 | 3.0:1 | Pass |
| light | --code-text |
--code-bg |
12.04:1 | 4.5:1 | Pass |
| light | --code-keyword |
--code-bg |
5.16:1 | 4.5:1 | Pass |
| light | --code-string |
--code-bg |
7.95:1 | 4.5:1 | Pass |
| light | --code-function |
--code-bg |
8.64:1 | 4.5:1 | Pass |
| light | --code-comment |
--code-bg |
5.11:1 | 4.5:1 | Pass |
| light | --code-number |
--code-bg |
8.18:1 | 4.5:1 | Pass |
| dark | --color-text-primary |
--color-bg-primary |
14.48:1 | 7.0:1 | Pass |
| dark | --color-text-primary |
--color-bg-secondary |
13.00:1 | 7.0:1 | Pass |
| dark | --color-text-primary |
--color-bg-elevated |
12.50:1 | 7.0:1 | Pass |
| dark | --color-text-primary |
--color-bg-active |
11.12:1 | 7.0:1 | Pass |
| dark | --color-text-secondary |
--color-bg-primary |
6.39:1 | 4.5:1 | Pass |
| dark | --color-text-secondary |
--color-bg-secondary |
5.74:1 | 4.5:1 | Pass |
| dark | --color-text-secondary |
--color-bg-tertiary |
5.01:1 | 4.5:1 | Pass |
| dark | --color-text-secondary |
--color-bg-elevated |
5.52:1 | 4.5:1 | Pass |
| dark | --color-text-secondary |
--color-bg-hover |
5.53:1 | 4.5:1 | Pass |
| dark | --color-text-tertiary |
--color-bg-primary |
5.23:1 | 4.5:1 | Pass |
| dark | --color-text-tertiary |
--color-bg-secondary |
4.69:1 | 4.5:1 | Pass |
| dark | --color-text-tertiary |
--color-bg-elevated |
4.51:1 | 4.5:1 | Pass |
| dark | --color-text-accent |
--color-bg-primary |
6.45:1 | 4.5:1 | Pass |
| dark | --color-text-accent |
--color-bg-secondary |
5.79:1 | 4.5:1 | Pass |
| dark | --color-text-inverse |
--color-bg-inverse |
12.64:1 | 4.5:1 | Pass |
| dark | --color-text-on-accent |
--color-action-primary |
5.18:1 | 4.5:1 | Pass |
| dark | --color-text-on-accent |
--color-action-primary-hover |
6.22:1 | 4.5:1 | Pass |
| dark | --color-text-on-accent |
--color-action-secondary |
6.45:1 | 4.5:1 | Pass |
| dark | --color-text-on-accent |
--color-action-secondary-hover |
7.44:1 | 4.5:1 | Pass |
| dark | --color-text-on-accent |
--color-error |
5.14:1 | 4.5:1 | Pass |
| dark | --color-text-on-accent |
--color-error-hover |
6.19:1 | 4.5:1 | Pass |
| dark | --color-action-primary |
--color-bg-primary |
5.18:1 | 3.0:1 | Pass |
| dark | --color-action-secondary |
--color-bg-primary |
6.45:1 | 3.0:1 | Pass |
| dark | --color-action-secondary |
--color-bg-secondary |
5.79:1 | 3.0:1 | Pass |
| dark | --color-action-secondary |
--color-bg-tertiary |
5.06:1 | 3.0:1 | Pass |
| dark | --color-border-input |
--color-bg-primary |
3.88:1 | 3.0:1 | Pass |
| dark | --color-border-input |
--color-bg-secondary |
3.48:1 | 3.0:1 | Pass |
| dark | --color-border-input |
--color-bg-elevated |
3.35:1 | 3.0:1 | Pass |
| dark | --color-focus |
--color-bg-primary |
6.45:1 | 3.0:1 | Pass |
| dark | --color-focus |
--color-bg-secondary |
5.79:1 | 3.0:1 | Pass |
| dark | --color-focus |
--color-bg-elevated |
5.57:1 | 3.0:1 | Pass |
| dark | --color-human-text |
--color-bg-primary |
6.57:1 | 4.5:1 | Pass |
| dark | --color-human-text |
--color-bg-secondary |
5.89:1 | 4.5:1 | Pass |
| dark | --color-human-text |
--color-human-bg |
5.77:1 | 4.5:1 | Pass |
| dark | --color-human-text |
--color-human-bg |
5.15:1 | 4.5:1 | Pass |
| dark | --color-digital-text |
--color-bg-primary |
6.45:1 | 4.5:1 | Pass |
| dark | --color-digital-text |
--color-bg-secondary |
5.79:1 | 4.5:1 | Pass |
| dark | --color-digital-text |
--color-digital-bg |
5.54:1 | 4.5:1 | Pass |
| dark | --color-digital-text |
--color-digital-bg |
4.95:1 | 4.5:1 | Pass |
| dark | --color-success |
--color-bg-primary |
7.78:1 | 3.0:1 | Pass |
| dark | --color-success-text |
--color-bg-primary |
7.78:1 | 4.5:1 | Pass |
| dark | --color-success-text |
--color-bg-secondary |
6.98:1 | 4.5:1 | Pass |
| dark | --color-success-text |
--color-success-bg |
6.55:1 | 4.5:1 | Pass |
| dark | --color-success-text |
--color-success-bg |
5.77:1 | 4.5:1 | Pass |
| dark | --color-warning-text |
--color-bg-primary |
9.06:1 | 4.5:1 | Pass |
| dark | --color-warning-text |
--color-bg-secondary |
8.13:1 | 4.5:1 | Pass |
| dark | --color-warning-text |
--color-warning-bg |
7.49:1 | 4.5:1 | Pass |
| dark | --color-warning-text |
--color-warning-bg |
6.66:1 | 4.5:1 | Pass |
| dark | --color-error |
--color-bg-primary |
5.14:1 | 3.0:1 | Pass |
| dark | --color-error-text |
--color-bg-primary |
6.44:1 | 4.5:1 | Pass |
| dark | --color-error-text |
--color-bg-secondary |
5.78:1 | 4.5:1 | Pass |
| dark | --color-error-text |
--color-error-bg |
5.70:1 | 4.5:1 | Pass |
| dark | --color-error-text |
--color-error-bg |
5.10:1 | 4.5:1 | Pass |
| dark | --color-info-text |
--color-bg-primary |
6.45:1 | 4.5:1 | Pass |
| dark | --color-info-text |
--color-info-bg |
5.54:1 | 4.5:1 | Pass |
| dark | --color-info-text |
--color-info-bg |
4.95:1 | 4.5:1 | Pass |
| dark | --color-success-text |
--color-bg-elevated |
6.71:1 | 4.5:1 | Pass |
| dark | --color-warning-text |
--color-bg-elevated |
7.82:1 | 4.5:1 | Pass |
| dark | --color-error-text |
--color-bg-elevated |
5.56:1 | 4.5:1 | Pass |
| dark | --color-text-primary |
--color-bg-hover |
11.06:1 | 7.0:1 | Pass |
| dark | --color-text-primary |
--color-bg-active |
9.39:1 | 7.0:1 | Pass |
| dark | --color-text-secondary |
--color-bg-elevated |
5.52:1 | 4.5:1 | Pass |
| dark | --color-focus |
--color-bg-active |
4.18:1 | 3.0:1 | Pass |
| dark | --color-chart-1 |
--color-bg-primary |
5.18:1 | 3.0:1 | Pass |
| dark | --color-chart-1 |
--color-bg-secondary |
4.65:1 | 3.0:1 | Pass |
| dark | --color-chart-2 |
--color-bg-primary |
5.87:1 | 3.0:1 | Pass |
| dark | --color-chart-2 |
--color-bg-secondary |
5.27:1 | 3.0:1 | Pass |
| dark | --color-chart-3 |
--color-bg-primary |
5.46:1 | 3.0:1 | Pass |
| dark | --color-chart-3 |
--color-bg-secondary |
4.91:1 | 3.0:1 | Pass |
| dark | --color-chart-4 |
--color-bg-primary |
3.57:1 | 3.0:1 | Pass |
| dark | --color-chart-4 |
--color-bg-secondary |
3.21:1 | 3.0:1 | Pass |
| dark | --color-chart-5 |
--color-bg-primary |
5.58:1 | 3.0:1 | Pass |
| dark | --color-chart-5 |
--color-bg-secondary |
5.01:1 | 3.0:1 | Pass |
| dark | --color-chart-6 |
--color-bg-primary |
4.65:1 | 3.0:1 | Pass |
| dark | --color-chart-6 |
--color-bg-secondary |
4.18:1 | 3.0:1 | Pass |
| dark | --code-text |
--code-bg |
12.04:1 | 4.5:1 | Pass |
| dark | --code-keyword |
--code-bg |
5.16:1 | 4.5:1 | Pass |
| dark | --code-string |
--code-bg |
7.95:1 | 4.5:1 | Pass |
| dark | --code-function |
--code-bg |
8.64:1 | 4.5:1 | Pass |
| dark | --code-comment |
--code-bg |
5.11:1 | 4.5:1 | Pass |
| dark | --code-number |
--code-bg |
8.18:1 | 4.5:1 | Pass |
07 / Brand marks
Set in Fraunces 700 with WONK, shaped with real kerning and converted to paths, so the files need no font. Leave clear space equal to the height of the lowercase d on every side. Use the file — never retype, recolor or stretch the mark.
Human intelligence, amplified with technological intentionality.
This showcase is a working reference for that proposition: the same custom properties shape color, type, spacing, state, code, and atmosphere — and this band is just data-theme="dark" on a section.