Token · stable · v1.0.0 · owner: Site system lead · contract 19 of 20 points (open: figma)
Reference
Source reference; not an executed check.
--cotton- #f3eee3
--surface- #fbf8f1
--surface-2- #ebe4d6
--surface-3- #e2d9c8
--ink- #17140f
--ink-2- #4a443a
--line- #d1c6b2
--line-strong- #716856
--focus- #1e2a78
--link- #1e2a78
--indigo- #1e2a78
--madder- #b02a1e
--saffron- #e9a21b
--teal- #0b6b66
--field-ink- #17140f
--on-dye- #f3eee3
--on-dye-2- #e2d9c8
--on-saffron- #17140f
--on-saffron-2- #26221c
--indigo-ink- #1e2a78
--madder-ink- #b02a1e
--teal-ink- #0b6b66
--saffron-ink- #7a5206
--indigo-2- #6f7fe0
--madder-2- #d4574a
--saffron-2- #f3bb4c
--teal-2- #1d948c
--indigo-soft- #eceefa
--madder-soft- #fbecea
--saffron-soft- #fdf4e1
--teal-soft- #e3f3f1
--band-woven- #1e2a78
--band-holding- #0b6b66
--band-shape- #9e6b08
--band-loose- #b02a1e
--ai- #826bab
--ai-ink- #4d386f
--term-bg- #17140f
--term-fg- #ebe4d6
--term-muted- #b3a892
--term-accent- #c3c9ef
--term-add- #94d1ca
--term-del- #efb3ab
--sample-1- #0d1c58
--sample-2- #3f6bdc
--sample-3- #f5ab77
--sample-4- #f6f1e7
--sample-on- #ffffff
--font-display- Archivo, "Archivo Wide Fallback", "Noto Sans JP", "Hiragino Sans", "Hiragino Kaku Gothic ProN", "Yu Gothic UI", "Yu Gothic", Meiryo, system-ui, sans-serif
--font-text- "Loom Figures", "Atkinson Hyperlegible Next", "Atkinson Fallback", "Noto Sans JP", "Hiragino Sans", "Hiragino Kaku Gothic ProN", "Yu Gothic UI", "Yu Gothic", Meiryo, system-ui, sans-serif
--font-mono- "Martian Mono", ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace
--font-display-ja- "Loom JP Display", "Noto Sans JP", "Hiragino Sans", "Hiragino Kaku Gothic ProN", "Yu Gothic UI", "Yu Gothic", Meiryo, sans-serif
--font-sample- "Helvetica Neue", "Segoe UI", Arial, "Hiragino Sans", "Hiragino Kaku Gothic ProN", "Noto Sans JP", "Yu Gothic", Meiryo, system-ui, sans-serif
--fs-display- clamp(2.25rem, 7.2vw, 6rem)
--fs-h2- clamp(1.875rem, 4.4vw, 3.5rem)
--fs-h3- clamp(1.25rem, 1.2rem + .4vw, 1.5rem)
--fs-body- clamp(1rem, .95rem + .2vw, 1.125rem)
--fs-small- 0.875rem
--fs-label- 0.75rem
--type-display- expanded 900 var(--fs-display)/0.9 var(--font-display)
--ls-display- -0.02em
--type-h1- expanded 900 var(--fs-display)/0.9 var(--font-display)
--ls-h1- -0.02em
--type-h2- expanded 800 var(--fs-h2)/1 var(--font-display)
--ls-h2- -0.02em
--type-h3- semi-expanded 800 var(--fs-h3)/1.2 var(--font-display)
--ls-h3- -0.01em
--type-lede- normal 400 var(--fs-h3)/1.4 var(--font-text)
--ls-lede- 0em
--type-body- normal 400 var(--fs-body)/1.6 var(--font-text)
--ls-body- 0em
--type-strong- normal 700 var(--fs-body)/1.4 var(--font-text)
--ls-strong- 0em
--type-small- normal 400 var(--fs-small)/1.5 var(--font-text)
--ls-small- 0em
--type-small-strong- normal 700 var(--fs-small)/1.4 var(--font-text)
--ls-small-strong- 0em
--type-label- normal 600 var(--fs-label)/1.4 var(--font-mono)
--ls-label- 0em
--type-figure- normal 500 var(--fs-small)/1.6 var(--font-mono)
--ls-figure- 0em
--weight-strong- 700
--weight-heavy- 800
--space-0- 0px
--space-1- 2px
--space-2- 4px
--space-3- 6px
--space-4- 8px
--space-5- 12px
--space-6- 16px
--space-7- 20px
--space-8- 24px
--space-9- 32px
--space-10- 40px
--space-11- 48px
--space-12- 64px
--space-13- 80px
--columns- 12
--w-max- 1240px
--w-text- 720px
--w-narrow- 560px
--gutter- 16px
--grid-gap- 24px
--header-h- 64px
--section- clamp(48px, 5vw, 72px)
--radius- 2px
--radius-round- 9999px
--radius-sample- 6px
--rule-hair- 2px
--rule- 4px
--rule-frame- 6px
--rule-heavy- 8px
--shadow-float- 0px 16px 48px 0px #13110f1f
--ease-standard- cubic-bezier(0.2, 0, 0, 1)
--ease-enter- cubic-bezier(0, 0, 0, 1)
--ease-exit- cubic-bezier(0.3, 0, 1, 1)
--dur-fast- 100ms
--dur-moderate- 160ms
--dur-slow- 240ms
--dur-weave- 360ms
--stagger- 60ms
--selvedge-row- 6px
--selvedge-square- 12px
--selvedge-height- 18px
--header-h- 80px
--gutter- 40px
--grid-gap- 32px
--cotton- #17140f
--surface- #26221c
--surface-2- #0d0b08
--surface-3- #38332b
--ink- #ebe4d6
--ink-2- #b3a892
--line- #38332b
--line-strong- #8f8571
--focus- #9aa5e6
--link- #9aa5e6
--field-ink- #0d0b08
--indigo-ink- #9aa5e6
--madder-ink- #e3877a
--teal-ink- #94d1ca
--saffron-ink- #f3bb4c
--indigo-soft- #151d55
--madder-soft- #4c110b
--saffron-soft- #3a2603
--teal-soft- #042a28
--ai- #a18bca
--ai-ink- #dfd0ff
--term-bg- #0d0b08
--shadow-float- 0px 16px 48px 0px #00000099
--cotton- #17140f
--surface- #26221c
--surface-2- #0d0b08
--surface-3- #38332b
--ink- #ebe4d6
--ink-2- #b3a892
--line- #38332b
--line-strong- #8f8571
--focus- #9aa5e6
--link- #9aa5e6
--field-ink- #0d0b08
--indigo-ink- #9aa5e6
--madder-ink- #e3877a
--teal-ink- #94d1ca
--saffron-ink- #f3bb4c
--indigo-soft- #151d55
--madder-soft- #4c110b
--saffron-soft- #3a2603
--teal-soft- #042a28
--ai- #a18bca
--ai-ink- #dfd0ff
--term-bg- #0d0b08
--shadow-float- 0px 16px 48px 0px #00000099
--cotton- #ffffff
--surface- #ffffff
--surface-2- #ebe4d6
--surface-3- #e2d9c8
--ink- #000000
--ink-2- #26221c
--line- #38332b
--line-strong- #000000
--focus- #000000
--link- #1e2a78
--indigo- #151d55
--madder- #6e1810
--saffron- #e9a21b
--teal- #063e3b
--field-ink- #000000
--on-dye- #ffffff
--on-dye-2- #ffffff
--on-saffron- #000000
--on-saffron-2- #000000
--indigo-ink- #1e2a78
--madder-ink- #b02a1e
--teal-ink- #0b6b66
--saffron-ink- #7a5206
--indigo-2- #6f7fe0
--madder-2- #d4574a
--saffron-2- #f3bb4c
--teal-2- #1d948c
--indigo-soft- #eceefa
--madder-soft- #fbecea
--saffron-soft- #fdf4e1
--teal-soft- #e3f3f1
--band-woven- #151d55
--band-holding- #063e3b
--band-shape- #7a5206
--band-loose- #6e1810
--ai- #372553
--ai-ink- #24143a
--term-bg- #17140f
--term-fg- #ebe4d6
--term-muted- #b3a892
--term-accent- #c3c9ef
--term-add- #94d1ca
--term-del- #efb3ab
--sample-1- #0d1c58
--sample-2- #3f6bdc
--sample-3- #f5ab77
--sample-4- #f6f1e7
--sample-on- #ffffff
--shadow-float- 0px 16px 48px 0px #13110f1f
--identity-art-ink- var(--ink)
--identity-art-lettering- var(--font-display)
--identity-art-indigo- var(--indigo-ink)
--identity-art-teal- var(--teal-ink)
--identity-art-saffron- var(--saffron)
--identity-art-madder- var(--madder-ink)
--identity-art-seam- var(--cotton)
--identity-art-duration- var(--dur-weave)
--identity-art-easing- var(--ease-standard)
--identity-sticker-surface- var(--cotton)
--identity-sticker-ink- var(--ink)
--identity-sticker-on-ink- var(--cotton)
--identity-sticker-lettering- var(--font-display)
--identity-sticker-cutout- var(--on-dye)
--identity-sticker-fixed-ink- var(--field-ink)
--identity-sticker-mark-indigo- var(--indigo-ink)
--identity-sticker-mark-madder- var(--madder-ink)
--identity-sticker-mark-teal- var(--teal-ink)
--identity-sticker-on-dye- var(--on-dye)
--identity-sticker-on-saffron- var(--on-saffron)
--identity-sticker-indigo- var(--indigo)
--identity-sticker-madder- var(--madder)
--identity-sticker-saffron- var(--saffron)
--identity-sticker-teal- var(--teal)
--identity-sticker-caption- var(--type-small)
--identity-sticker-gap- var(--space-4)
--identity-motion-surface- var(--cotton)
--identity-motion-ink- var(--ink)
--identity-motion-ink-muted- var(--ink-2)
--identity-motion-control-surface- var(--surface)
--identity-motion-control-hover- var(--surface-2)
--identity-motion-line- var(--line-strong)
--identity-motion-rule- var(--rule-hair)
--identity-motion-focus-width- var(--rule)
--identity-motion-focus- var(--focus)
--identity-motion-focus-offset- var(--space-2)
--identity-motion-title- var(--type-h3)
--identity-motion-caption- var(--type-small)
--identity-motion-mono- var(--font-mono)
--identity-motion-accent- var(--indigo-ink)
--identity-motion-route- var(--madder-ink)
--identity-motion-gap- var(--space-4)
--identity-motion-gap-small- var(--space-3)
--identity-motion-gap-section- var(--space-6)
--identity-motion-padding- var(--space-8)
--identity-motion-scene-space- var(--space-9)
--identity-motion-status-gap- var(--space-5)
--identity-motion-target- var(--space-11)
--identity-motion-scene-unit- var(--space-13)
--identity-motion-duration- var(--dur-weave)
--identity-motion-easing- var(--ease-standard)
--identity-playground-label- var(--type-label)
--identity-playground-tracking- var(--ls-label)
--identity-playground-gap-caption- var(--space-5)
--identity-playground-surface- var(--cotton)
--identity-playground-ink- var(--ink)
--identity-playground-ink-muted- var(--ink-2)
--identity-playground-line- var(--line-strong)
--identity-playground-rule- var(--rule-hair)
--identity-playground-link- var(--link)
--identity-playground-caption- var(--type-small)
--identity-playground-title- var(--type-h3)
--identity-playground-gap- var(--space-6)
--identity-playground-gap-small- var(--space-3)
--identity-playground-padding- var(--space-8)
--identity-playground-margin- var(--space-9)
--identity-playground-target- var(--space-11)
--identity-playground-focus- var(--focus)
--identity-playground-focus-width- var(--rule)
--identity-playground-focus-offset- var(--space-2)
--identity-playground-gap-medium- var(--space-4)
--state-badge-field-ink- var(--field-ink)
--state-badge-padding-large- var(--space-6)
--state-badge-mark-large- var(--space-12)
--state-badge-surface- var(--cotton)
--state-badge-ink- var(--ink)
--state-badge-healthy- var(--teal-ink)
--state-badge-attention- var(--saffron)
--state-badge-broken- var(--madder-ink)
--state-badge-action- var(--indigo-ink)
--state-badge-gap- var(--space-4)
--state-badge-caption- var(--type-small)
--state-badge-mark- var(--space-11)
--state-badge-rule- var(--rule-hair)
--state-badge-line- var(--line-strong)
--state-badge-padding- var(--space-5)
--job-map-gap-medium- var(--space-5)
--job-map-mark- var(--type-h2)
--job-map-surface- var(--cotton)
--job-map-ink- var(--ink)
--job-map-see- var(--teal-ink)
--job-map-shape- var(--madder-ink)
--job-map-govern- var(--saffron-ink)
--job-map-run- var(--indigo-ink)
--job-map-gap- var(--space-6)
--job-map-margin- var(--space-8)
--job-map-gap-small- var(--space-4)
--job-map-title- var(--type-h3)
--job-map-caption- var(--type-small)
--job-map-rule- var(--rule-hair)
--job-map-line- var(--line-strong)
--job-map-target- var(--space-11)
--job-map-focus- var(--focus)
--job-map-focus-width- var(--rule)
--job-map-focus-offset- var(--space-2)
--atomic-guide-preview-min-width- var(--w-text)
--atomic-guide-cotton- var(--cotton)
--atomic-guide-surface- var(--surface)
--atomic-guide-ink- var(--ink)
--atomic-guide-ink-muted- var(--ink-2)
--atomic-guide-line- var(--line)
--atomic-guide-line-strong- var(--line-strong)
--atomic-guide-rule- var(--rule-hair)
--atomic-guide-gap- var(--space-6)
--atomic-guide-gap-small- var(--space-3)
--atomic-guide-gap-medium- var(--space-4)
--atomic-guide-margin- var(--space-9)
--atomic-guide-title- var(--type-h3)
--atomic-guide-caption- var(--type-small)
--atomic-guide-link- var(--link)
--atomic-guide-target- var(--space-11)
--atomic-guide-indigo- var(--indigo)
--atomic-guide-teal- var(--teal)
--atomic-guide-saffron- var(--saffron)
--atomic-guide-madder- var(--madder)
--atomic-guide-focus- var(--focus)
--atomic-guide-focus-width- var(--rule)
--atomic-guide-focus-offset- var(--space-2)
Do and don't
2 positive / 2 negative authored documentation examples (2 each required); 1 reference (1 required); 0 failed. References and failures do not count; this is not behavior acceptance.
Do: A reading role travels through native Text
Authored by tokens.tsRendered consumer example; not an executed correctness check. text Isolated document follows the browser's colour and contrast preferences. The outer theme toolbar does not control this document.
Open example: Semantic tokens · Do: A reading role travels through native Text Use the full-page example to follow page links.
Do: An action uses its existing role bindings
Authored by tokens.tsRendered consumer example; not an executed correctness check. button Isolated document follows the browser's colour and contrast preferences. The outer theme toolbar does not control this document.
Open example: Semantic tokens · Do: An action uses its existing role bindings Use the full-page example to follow page links.
Don't: A generated role is edited by hand
Authored by tokens.tsRule illustration; not an executed check. tokens-semantic / tokens.generated
Edit --cotton directly in apps/showcase/site/brand/tokens.css after generation.
Leave brand.ts and the underlying token authority unchanged.Don't: A private page-local role bypasses the source
Authored by tokens.tsRule illustration; not an executed check. tokens-semantic / tokens.generated
Append a new page-only semantic role to generated tokens.css by hand.
Its purpose, source mapping and supported modes are absent from brand.ts.Rules
| Rule | Why | Check |
|---|---|---|
| tokens.css is generated; never edited by hand. | The CSS must match the brand data and Loom Base. | Automated: npm run site:build (regenerates tokens.css) |
API
No props.
Contract details
The full contract: identity, anatomy, variants, states, tokens, layout, motion, accessibility, content, tests
Identity
| Aspect | Value |
|---|---|
| Id | tokens-semantic |
| Layer | Tokens |
| Category | tokens |
| Owner | Site system lead |
| Status | stable |
| Version | 1.0.0 |
| Source | apps/showcase/site/system/tokens/tokens.ts (private repository; the contract and the render function are this one module) |
| Version | Date | Change |
|---|---|---|
| 1.0.0 | 2026-10-26 | Semantic tokens as one module: its markup moved out of the page builder (scripts/site) into the system. |
Use when
- Component-token bindings and product composition. Why: MVDS §5.1 requires components to consume their component tier. Scoped component bindings retain the same semantic defaults at their actual selector and state; source agreement and rendered checks remain separate obligations.
Do not use when
- Defining a role inside an element. Why: Roles change in brand.ts, for every element at once.
Anatomy
| Part | What it is |
|---|---|
| roles | apps/showcase/site/brand/brand.ts |
| output | apps/showcase/site/brand/tokens.css (generated by scripts/site/brand-tokens.ts) |
Made of: tokens-primitive.
Used in: tokens-component.
Variants
| Variant | When | Why |
|---|---|---|
| light and dark | Every page, following the reader's setting. | The same roles resolve to light or dark values, so no element chooses its own. |
States
| State | Rendered or not applicable |
|---|---|
| default | The specimen. |
| hover | Not applicable: A foundation is not interactive. |
| focus-visible | Not applicable: Not focusable. |
| active | Not applicable: Not interactive. |
| disabled | Not applicable: Nothing to disable. |
| loading | Not applicable: Values are built into the stylesheet. |
| empty | Not applicable: The build fails if a value is missing. |
| error | Not applicable: Unresolved values fail the brand gate, not the reader. |
| current | Not applicable: No current item. |
| visited | Not applicable: Not a link. |
| expanded | Not applicable: Does not open. |
Tokens
| Part | Token |
|---|---|
| --cotton | #f3eee3 |
| --surface | #fbf8f1 |
| --surface-2 | #ebe4d6 |
| --surface-3 | #e2d9c8 |
| --ink | #17140f |
| --ink-2 | #4a443a |
| --line | #d1c6b2 |
| --line-strong | #716856 |
| --focus | #1e2a78 |
| --link | #1e2a78 |
Layout
| Aspect | Value |
|---|---|
| breakpoints | Required review at 390, 768, 1024 and 1440 px; execution is not implied by this declaration; columns stack under 768 px; the wrap keeps a 16 px gutter on phones. |
| wrapping | Text wraps; nothing scrolls sideways. |
| textExpansion | Japanese runs 20 to 40% longer; headings break between phrases (jaBreaks) and blocks grow downwards. |
Spacing and rhythm
| Aspect | Value |
|---|---|
| internal | Not applicable: a foundation has no box of its own. |
| external | Not applicable. |
| rhythm | Applies to every element that reads it. |
Motion
| Aspect | Value |
|---|---|
| None | A foundation does not move. |
Runtime and reuse
Render-only element; mount any registered child enhancements separately. Preserve required Site CSS, fonts, responsive and locale rules from nativeElement.
Accessibility passport
| Aspect | Value |
|---|---|
| role | Not rendered on the site; its specimen in the Library is a list |
| name | The foundation's name |
| keyboard | Not interactive. |
| focus | Not focusable. |
| screenReader | The specimen is a plain list of names and values. |
| contrast | Every text and ground pair in the palette is checked (check-brand). |
| target | Not a target. |
Content
| Slot | Length | Voice |
|---|---|---|
| specimen: CSS role and resolved value | Generated role/value pairs from tokens.css; no hand-edited output or new element-local role. | Name the role's purpose and preserve its source identity. |
Good: “A component background alias reads the existing semantic cotton role.”
Bad: “Edit the generated --cotton value in tokens.css for one page.”
Japanese: CSS identifiers and source paths are locale independent. Translate role explanations; Japanese typography uses the existing named language rules, not renamed tokens.
Icons and illustrations
None: this element uses no icon or illustration of its own.
Decisions and exceptions
- None.
Usage
640 owned-class occurrences in built pages plus metadata-token references in built CSS (measured by npm run site:system).
No application mechanism is declared.
Current check result: not assessed by this report. Declarations and source-file presence do not establish executed enforcement or accepted coverage.
Tests
| Aspect | Value |
|---|---|
| unit | tests/unit/site-system.test.ts: renders every do and don't example through the registry and checks the classes it owns |
| visual | Not yet: there are no screenshot baselines; the Library page is checked for sideways scroll at 1440 px by tests/site/system.spec.ts |
| a11y | tests/site/system.spec.ts: axe (0 serious or critical) on the element's Library page in light and dark |
| parity | scripts/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.