Drift palette

Lays out every raw colour the audit found in one real app, so the reader sees drift as a picture: decisions nobody made at the system level.

Organism · stable · v1.0.0 · owner: Site system lead · contract 19 of 20 points (open: figma)

Do and don't

Do: In the problem section

Rendered by drift-palette.ts

Open example: Drift palette · Do: In the problem section Use the full-page example to follow page links.

Drift as a picture.

Do: Japanese

Rendered by drift-palette.ts

Open example: Drift palette · Do: Japanese Use the full-page example to follow page links.

Translated caption.

Don't: Without commit and date

Rendered by drift-palette.ts

Open example: Drift palette · Don't: Without commit and date Use the full-page example to follow page links.

The evidence must be reproducible.

Don't: Recoloured to the brand

Rendered by drift-palette.ts

Open example: Drift palette · Don't: Recoloured to the brand Use the full-page example to follow page links.

The swatches are the found values; changing them would falsify the evidence.

Rules

RuleWhyCheck
The drift palette is drawn from the raw colours Loom's audit found in an open-source app at a named commit at build time.A figure read from the real records cannot drift from them.Automated: npm run site:build (reads the data; fails if it is missing)
Swatches show the exact raw values found, and only here may raw colours appear.They are evidence, not styling; the brand gate exempts this data, not any stylesheet.Automated: brand gate (inline colours: evidence attributes only)

API

PropTypeRequiredDefaultWhat it does
langen | jaNo"en"Interface language.

Contract details

The full contract: identity, anatomy, variants, states, tokens, layout, motion, accessibility, content, tests

Identity

AspectValue
Iddrift-palette
LayerOrganisms
Categoryfigure
OwnerSite system lead
Statusstable
Version1.0.0
Sourceapps/showcase/site/system/organisms/drift-palette.ts (private repository; the contract and the render function are this one module)
VersionDateChange
1.0.02026-10-26Drift palette, drawn at build time from the raw colours Loom's audit found in an open-source app at a named commit.

Use when

  • The problem section of the landing. Why: A wall of near-duplicate colours makes drift obvious in a second.

Do not use when

  • As decoration. Why: Every swatch is a finding with a source.

Anatomy

PartWhat it is
rootfigure.ix-dp
gridSwatches of each raw value
factsCounts and the commit
captionRepository, commit, date

Made of: figure-frame, stat, caption.

Used in: problem-section.

Variants

VariantWhenWhy
defaultWherever its claim is made.One drawing per claim keeps the evidence consistent.

States

StateRendered or not applicable
defaultAll found-color swatches, facts and source commit/date are complete build-time content, with an optional once-only managed entrance.
hoverNot applicable: Swatches/facts are evidence, not controls; no intrinsic hover action.
focus-visibleNot applicable: The figure itself and aria-hidden swatches do not receive focus.
activeNot applicable: A once-only entrance is motion, not a pressed or selected input state.
disabledNot applicable: No control to disable.
loadingThe complete static palette/facts/caption remain readable while the optional managed entrance chunk loads.
emptyNot applicable: The fixed audit report supplies the palette; there is no caller empty-data variant.
errorCaught optional chunk/init failure restores the static figure and host failed state; remount may retry. Missing build data remains a build failure, not an empty successful figure.
currentNot applicable: No selected swatch, frame or current-step control.
visitedNot applicable: The figure has no link/history state.
expandedNot applicable: The figure does not disclose content.

Tokens

PartToken
swatchthe found colour itself (the only place raw values appear, as evidence)
facts.font--type-small
--drift-palette-background-surfacevar(--surface)
--drift-palette-color-inkvar(--ink)
--drift-palette-padding-space-6var(--space-6)
--drift-palette-padding-space-9var(--space-9)
--drift-palette-gap-space-8var(--space-8)
--drift-palette-border-top-rule-framevar(--rule-frame)
--drift-palette-border-top-inkvar(--ink)
--drift-palette-gap-space-2var(--space-2)
--drift-palette-background-surface-2var(--surface-2)
--drift-palette-padding-space-2var(--space-2)
--drift-palette-box-shadow-inkvar(--ink)
--drift-palette-gap-space-5var(--space-5)
--drift-palette-gap-space-6var(--space-6)
--drift-palette-gap-space-1var(--space-1)
--drift-palette-border-top-rulevar(--rule)
--drift-palette-border-top-maddervar(--madder)
--drift-palette-padding-top-space-3var(--space-3)
--drift-palette-font-type-h2var(--type-h2)
--drift-palette-letter-spacing-ls-h2var(--ls-h2)
--drift-palette-font-type-smallvar(--type-small)
--drift-palette-color-ink-2var(--ink-2)
--drift-palette-animation-dur-slowvar(--dur-slow)
--drift-palette-animation-ease-entervar(--ease-enter)
--drift-palette-animation-delay-staggervar(--stagger)
--drift-palette-animation-dur-weavevar(--dur-weave)
--drift-palette-animation-delay-dur-weavevar(--dur-weave)

Layout

AspectValue
breakpointsRequired review at 390, 768, 1024 and 1440 px; execution is not implied by this declaration; the figure reflows to one column under 768 px.
wrappingLabels wrap; drawings scale to the column.
textExpansionJapanese labels are 20 to 40% longer and wrap inside their cells.

Spacing and rhythm

AspectValue
internalInside the Figure frame's --space-7 padding.
external--space-9 above and below in prose.
rhythmAfter the text whose claim it proves.

Motion

AspectValue
movesThe existing palette swatches/facts entrance plays once on visible entry; found colors and source geometry stay unchanged.
triggerManaged visible entry at threshold0.4 through the existing jobs-strip shared initializer.
durationExisting drift-palette CSS profile; no shared showcase frame hold is introduced.
easingExisting registered CSS entrance easing.
interruptibleHidden/offscreen/reduced preference settles/cancels root animations. No automatic restart after interruption; disposal restores static markup.
reducedStatic authored palette; no automatic entrance.
whyPreserves the existing one-time illustration without inventing reader playback controls.

Runtime and reuse

  1. stylesheet: /css/site.css. Built Site tokens, core and registered element CSS; preserve modes, focus and responsive rules.

  2. stylesheet: /css/demos.css. Existing legacy demo styles where the rendered specimen uses them.

  3. font: /fonts/. Self-hosted files referenced by Site @font-face, with licences; Japanese locale overrides remain applicable.

  4. Static fallback: Original build-time specimen remains readable before loading and after chunk/initialization failure; enhancement controls retain authored hidden state.

  5. Configured initializer: apps/showcase/site/interactives/jobs-strip.ts#init. The host owns transactional static-markup restoration and runtime state.

  6. Consumer module (imports relative to the configured source root):
    import { createRuntimeHost } from "./src/workflows/runtime-host";
    import { SITE_RUNTIMES } from "./apps/showcase/site/runtime-registry";
    const definition = SITE_RUNTIMES.find(entry => entry.binding.id === "drift-palette");
    if (!definition || definition.binding.lifecycle.kind !== "managed") throw new Error("Managed runtime binding unavailable");
    const host = createRuntimeHost([definition]);
    export function mountRuntime(container: ParentNode) { return host.mountAll(container); }
  7. After inserting the rendered markup, call mountRuntime(container) for the container holding [data-demo="drift-palette"]. Retain the returned disposal function and call it before removing, replacing or remounting, including every Storybook args render. The configured host restores captured static markup/attributes on disposal or caught load/initialization failure; retry starts a fresh managed remount.

Accessibility passport

AspectValue
rolefigure, named by its caption
nameThe caption, and a text alternative for any drawing
keyboardNot interactive unless stated.
focusLinks inside are in reading order.
screenReaderReads the figure's text and caption; drawings have role=img with a description.
contrastInk on surface 14:1; dyes used only as marks with their words.
targetNot a target.

Content

SlotLengthVoice
caption1 sentenceWhich app, which commit, which date

Good: “Raw colours in takenote at commit abc123, read on 25 October 2026.”

Bad: “Example palette”

Japanese: i18n.ts ix.dp.*.

Icons and illustrations

None: this element uses no icon or illustration of its own.

Decisions and exceptions

Usage

6 uses across the built pages (measured by npm run site:system).

Tests

AspectValue
unittests/unit/site-system.test.ts: renders every do and don't example through the registry and checks the classes it owns
visualNot yet: there are no screenshot baselines; the Library page is checked for sideways scroll at 1440 px by tests/site/system.spec.ts
a11ytests/site/system.spec.ts: axe (0 serious or critical) on the element's Library page in light and dark
parityscripts/site/system/check.ts: Library examples are rendered by the same render function the site imports

Figma

not-yet: The Loom Site Figma library is the last stage of the plan; this element is not mapped yet.

Open in Storybook

Start with a conversation about your system.

We read your system, show you what we found, and agree with your team what to fix first.