circulation,
not accumulation
The canonical brand layer for the institution — one palette, one mark, one heartbeat, vendored into every site that renders them.
brand v1.0.0What this is
One definition, vendored — not four copies
This layer lived in four repositories at once and had
already begun to fork. It now lives here, and each
consuming site copies the files it needs behind a
brand.lock hash guard that fails its own CI
offline.
The page you are reading is drawn by those same
files
— every swatch below is painted by the variable it
names, and the mark in the header is beating on the real
rule. A wrong value renders as a wrong page.
The division of labour in the wordmark. Bank is what accumulates — the record of appreciation. Heart is what circulates — the value itself.
The mark
B-Emblem™
A universal heart rotated 45° clockwise. It is bistable — heart and capital B, both immediately apparent. Not a reveal like the FedEx arrow; there is no aha to wait for, which is why it survives down to a 16px favicon.
-
Inline it in the DOM. Never
<img src>— CSS cannot reach inside an<img>, so the colour would have to be duplicated everywhere the mark appears. -
The 45° rotation is baked into the path
coordinates.
It used to be a
transformattribute, which is a trap: a CSS animation ontransformoverrides a non-animated one, so the first heartbeat silently un-rotates the mark and it stops reading as a B. -
fill="currentColor", and the page sets--emblem. There is no second colour to keep in step. - Never re-apply a rotation, and never scale the mark inside an icon canvas to "fix" padding — the maskable safe area was measured against the mark at its shipped size.
Motion
The heartbeat is a signal, not decoration
Two unequal beats and then a long rest — systole, a weaker diastole, then most of the period at rest. That morphology is what a counterfeit gets wrong at any tempo, which is why the rhythm is the signature and the rate is not. A 72 BPM variant was built and rejected.
Placement, not taste.
.beating goes on
chrome — a wordmark, a footer
attribution, anything that says an institution
stands behind this page. It goes
never on a mark drawn beside
somebody's name, where an unverified pulse would be
claiming something about them.
Under prefers-reduced-motion: stop, and
substitute nothing. The static mark is already a
meaningful state, so there is no degradation to
compensate for.
Colour
The B-Gem palette
A colour here means a medium. Ruby is video; fire opal is voice. The order is the Metta Light descent — session start at ruby, session end at diamond.
This is a media-type map, not a site palette, and it is not the six-TLD rainbow either — that is a different palette with a different job. Using a gem as a site accent is only correct where the gem is that product's medium.
The rule
A site's accent is derived, never picked
Each site takes the gem whose media type
is that product's medium. Everything else — the
whole alpha family — then falls out of one
color-mix() chain.
| Site | Accent | Because |
|---|
Two values cannot derive, and that is the
honest limit.
--accent-ink is decided by contrast:
Fire Opal on white is 3.4:1 and fails, Sapphire on
white is 7.0:1 and passes, so one site takes
near-black ink on its fill and another takes white.
No formula picks correctly. On a light ground
--accent-soft often needs pinning too.
The goal was "a fifth site is five declarations"; it
is nine.
Do not build a "pass a gem, get a theme" API. The true shape is a gem plus two measured overrides.
Roles
The token layer, in the theme you are reading
These are live values. Toggle the theme and every swatch below re-resolves through the same three-block cascade a consuming site ships.
Type
The scale
Lifted verbatim from the best-tuned stylesheet in the estate rather than re-derived. The display rungs are fluid.
The scale assumes a normal-width face. A site that picks an expanded display face must override the hero rung in its own layer — the token is shared, the face is that site's choice, and the site that chose the face owns the consequence.
Geometry
Radii and controls
How to consume it
Vendor the files; the lock does the rest
There is no package to install and nothing to fetch at
build time. A consumer copies the files it needs, copies
brand.lock verbatim, and declares what it
took in brand.uses — the one file in the
set that differs per repository.
# take the current layer npm run brand:sync -- --from ../../333.eco/brand.333.eco # in CI — no network, no credentials, no sibling checkout npm run check:brand
Concatenation order
It is not arbitrary. Custom-property substitution is
lazy, so a value declared early may reference one a
later file sets — which is how --accent,
set per site, reaches the derived family.
tokens.css + theme-3block.css or theme-2state.css + motion.css + reduce-global.css (opt-in) + brand.css (per site) + site.css (per site)
Never @import a sibling of these
files.
The partial-based sites inject their stylesheets as
raw text and concatenate them; a relative
@import resolves against
src/, where partials/ is
unreachable, and ships a dead render-blocking
at-rule that quietly destroys the
one-request-renders-complete property.
Two theme files, on purpose
theme-3block.css is a dark-default cascade
for sites that stamp both classes and must resolve the
unstamped case themselves. theme-2state.css
is a light-default stamp for a site whose resolver
already handles three states and writes only
.dark.
Neither is the inferior variant of the
other, and converting a site between them is a regression,
not a tidy-up.