Skip to catalogue content
Diqing WuDesign systems / 06 · V2Compare original V1中文

A system withroom to move.

Starting from Deethin’s actual homepage and Fabrica’s editorial rhythm, turn visual, spatial and motion decisions into rules that can be inspected, reused and discussed.

Inspect working components
Deethin × FabricaTokens. Components. Motion.V2 · Proposed · 26 Sep 2026

A point of view.

V1 remains a historical comparison. At the owner’s request, content below the homepage hero and the Portfolio review page now use shared tokens; project cards use the working component below. New homepage compositions retain source and review status, without claiming approved Figma assets. Other pages have not undergone a site-wide style migration.

Evidence, not decoration.

Project imagery and content lead. Use large type, whitespace and differences in scale to organize information rather than putting everything into identical cards.

Editorial outside. Precise inside.

Sections have an editorial rhythm. Components have explicit padding, gap, state and accessibility rules. Keep those two densities distinct.

Motion has a job.

Keep the homepage’s narrative opening; controls respond immediately. Motion must not obstruct reading, keyboard access or reduced-motion users.

Color has a role.

Primary #FFFFFF is the base, Secondary #101010 the contrast, Accent #73D1F8 the brand highlight. 60–30–10 guides composition, not a per-screen pixel quota or a requirement for white primary buttons. Surface / Ink describe purposes and may reference the same primitive.

60 / Base30 / Contrast10
Aa#ffffff

Surface

--ds-surface

Projects, inputs & dialogs

Deethin source
against#101010:19.03:1
Aa#101010

Ink / contrast

--ds-ink

Body text, primary buttons and dark chapters; compositional Secondary

Deethin source / owner direction
against#ffffff:19.03:1
Aa#73d1f8

Accent / identity

--ds-accent

Main logo color, occasional highlights and dark-surface data labels; not small white-background text

Owner direction
against#101010:11.06:1
Aa#f4f4f2

Canvas

--ds-canvas

Page background

Deethin source
against#101010:17.28:1
Aa#1d1d1d

Surface / on dark

--ds-surface-dark

Dark-gray evidence cards inside black sections, avoiding excessive contrast from white cards

Deethin .caseEvidence
against#ffffff:16.86:1
Aa#0087fb

Accent / on light

--ds-accent-ink

MONO data labels on light surfaces; does not replace the logo’s #73D1F8

Owner direction
against#ffffff:3.58:1

Gray descriptions keep the text/muted role, not Secondary. State colors are not shown in this palette. Controls temporarily retain V1 functional colors for later Figma verification, without unilateral replacement.

Hero light field / source palette

165° / Hero fallback
Inkoklch(.18 .02 255)
Blueoklch(.53 .2 263)
Skyoklch(.81 .108 234)
Mistoklch(.955 .022 226)
Lightoklch(.985 .008 235)

The full band uses the homepage CSS fallback recipe: 165° / 48% / 62%. The five swatches below come from smoke-renderer.ts’s light-field palette. These are different algorithms. Figma can start from a static keyframe or gradient approximation; copying five colors does not reproduce the moving field.

DATA / LABEL · 2026 / 013.58:1 / on white
DATA / LABEL · 2026 / 0111.06:1 / on ink

JetBrains Mono · 12px / 500 / 1.6 / .04em. Use #73D1F8 on dark surfaces and the iteration’s #0087FB on white. Its white-background contrast is 3.58:1, below the 4.5:1 small-text threshold. This remains a Proposed data label; essential information needs darker color or larger/heavier type. Explanatory paragraphs use sans and neutral gray.

Type sets the pace.

Inter / system sans handles content; JetBrains Mono handles code and measurements. Reuse existing site fonts without additional requests. Semantic hierarchy and visual size are separate.

Aa
clamp(3rem, 7.5vw, 7rem) · 600
line 0.96 · tracking -.055em

Short English display headings only, not body text

H1
clamp(2.5rem, 5vw, 4.5rem) · 600
line 1.04 · tracking -.04em

Page title; one semantic h 1 per page

H2
clamp(2rem, 3.8vw, 3.5rem) · 600
line 1.1 · tracking -.035em

Section headings

H3
1.5rem · 600
line 1.25 · tracking -.02em

Component and project titles; wrapping allowed

H4
1.25rem · 600
line 1.35 · tracking -.01em

Subsection headings

H5
1rem · 600
line 1.5 · tracking 0

Group headings

H6
.875rem · 600
line 1.5 · tracking 0

Detailed headings; avoid deep nesting

Body
1rem · 400
line 1.7 · tracking 0

English/Chinese explanations; max 65ch; Chinese line-height 1.8

Label
.875rem · 500
line 1.4 · tracking 0

Button and form labels; not all uppercase

Caption / code
.75rem · 400
line 1.6 · tracking 0

Notes; values use JetBrains Mono and do not carry the core explanation

Tight tracking is for English headings only. Chinese headings restore normal tracking /1.25 leading; Chinese body leading is 1.8. Essential information must not use tiny labels.

Space, made explicit.

space-00px
space-14px
space-28px
space-312px
space-416px
space-520px
space-624px
space-832px
space-1248px
space-1664px
space-2496px
space-32128px

Each item has a local diagram. Thumbnails show relationships rather than squeezing a 1440px page into a card. Controls keep actual box-model dimensions; the full responsive grid appears below.

← gutter →
Contentmax 1440px
16–40px

Page gutter

16–40px

clamp(16px, 3vw, 40px), with content capped at 1440px. Do not scale the entire page.

Section A↕ 64–128pxSection B

Section spacing

64–128px

clamp(64px, 8vw, 128px). Distinguish editorial whitespace from compact spacing inside controls.

12 col
6 col
1 col

Editorial grid

12 → 6 → 1

12 columns at ≥1200px, 6 at 700–1199px, and one below 700px. The demonstration grid responds to width.

Project 1
Project 2
gap 8 · cover 4:3

Project composition

2 → 1

Two columns at ≥700px with 8px gap; one below 700px. V2 covers are 4:3, titles stay visible, and supporting tags follow interaction state.

↕12 / ↔20 / gap8

Component box model

48 / 20 / 8

Buttons: min-height 48px, padding 12px 20px, icon–text gap 8px. Long labels can wrap and increase height.

← max 65ch →

Let text breathe.
Read information in order.
Line-height 1.8 without shrinking type.

Reading width

65ch

Long text uses one column; Chinese line-height is 1.8. Mono is for values, not whole explanatory paragraphs.

320pxAa
200%Aa

Small screens & zoom

320px / 200%

Navigation wraps, tables stack and dialogs scroll. Do not conceal overflow to imitate responsiveness.

123456789101112
padding-block 12 · inline 20min-height 48 · gap 8 · pill

This button uses the same class and tokens as the state library; it is not a separate box-model drawing. Controls have a minimum height rather than a fixed height that clips enlarged text.

A quiet visual vocabulary.

Iconography
Lucide: 24px canvas, 1.5px stroke; 18px inside buttons. Standalone icon targets are at least 44×44px and require an action label.
Identity
Use the existing Diqing Wu wordmark, not Fabrica’s logo. Add no registration symbol. Leave at least one character-height of clear space.
Project imagery
Use approved repository assets only. Covers use object-fit: cover; evidence images use contain without cropping content. Paired assets use the matching EN/CN version.
Illustration
No decorative illustrations in this iteration. Do not turn HMI or AI visuals into generic backgrounds. Define a specific narrative purpose before adding an illustration.
Light context
WhiteInkAccent

A gray base supports white cards. Black cards provide section contrast; blue cards are occasional emphasis, not a replacement for all backgrounds.

Inverse context
ResultEvidence first.
ArchitectureA nested system.
WorkflowReview together.

A black base supports #1D1D1D cards. White is primarily text; accent is reserved for occasional MONO labels.

Control8px

Small precise controls: inputs, menus and parameter panels. Cleaner edges avoid making every control look like a large card.

Project18px

Medium content containers: project cover plus title, and dark-gray evidence cards. Radius groups content; it does not imply clickability.

Chapter28px

Large chapters or separate stages: a clearer spatial boundary with the page, not a radius applied to every inner element.

Actionpill

Button height determines the pill. Its action shape does not compete with card radii. Coordinate nested radii with padding; do not blindly nest 18 inside 18.

Elevation ≠ stacking order

Elevation suggests floating above the page through shadow. z-index is overlap order, not shadow size or Figma depth. Static cards use light/dark surfaces, not shadows. Dialogs use two shadow layers; content 0 / sticky 20 / toast 40 is a local stacking convention. Native dialogs use the browser top layer, which is not equivalent to a larger z-index.

States are the system.

These are comparable visual-state samples: hover / focus / pressed are held visibly. Use the demonstration below for real interaction. Disabled and loading controls cannot trigger repeatedly.

primary

default
hover
focus
pressed
disabled
loading

secondary

default
hover
focus
pressed
disabled
loading

quiet

default
hover
focus
pressed
disabled
loading

Preserve focus and minimum width; return feedback after 900ms.

Focus is not removable decoration: Tab users and external keyboards on touch devices need location feedback. Inputs may share a dark boundary with hover, but focus-visible adds a thin 2px ring. Pointer buttons do not keep a heavy ring. Browsers may show focus on active text inputs; this is intentional.

Text field / 6 states

Enter a valid email address.

Label→input 8px; input padding 12×16px / min-height 48px; helper gap 8px; font-size 16px prevents iOS focus zoom. Disabled and read-only are not equivalent.

Selection / native controls

Preview density (changes the sample width below)

From parts to portfolio.

Covers increase to 4:3; body copy contains project type, year and title. White tags and arrow share a row at the cover bottom, revealed on hover / focus and visible on touch. Titles wrap; at 200% text size, supporting information returns to document flow rather than covering the image.

Disclosure

Which values come from the reference, and which are new designs?

Page colors, 18px project radius, 16:9 covers and editorial motion are traceable to Deethin source. State colors, the full type scale, control dimensions and interaction additions are Proposed. Extracted Fabrica data stays separate and does not automatically replace semantic tokens.

Why not replace the existing design system directly?

Homepage, case studies and experimental components have different responsibilities. Confirm direction 6 first, then migrate components individually and check their states and content. Experimental values must not silently become site-wide rules.

Form + feedback

No email is sent and your address is not stored.

Movement with meaning.

The complex homepage opening stays in the production page. This separate stage tests the same editorial rhythm without replaying the entire WebGL opening.

Evidence.Structure.Movement.
01 / Icon feedback

Icon + text button

Hover icon translate(3px,−3px) over 320ms; reverse on leave. Press scales to.98; keyboard location feedback is immediate.

02 / Quiet link

Underline reveal

Hover underline scaleX(0→1) over 240ms, from the left. Focus reveals it immediately; touch always shows the line.

04 / Editorial mask

Section-title reveal

Selected work.

Click to replay translateY(110%→0) over 1050ms (.16,1,.3,1). No looping or reading delay. Reduced motion shows it immediately.

05 / Evidence stagger

Evidence-card sequence

01 / Observe
02 / Define
03 / Refine

Click to replay opacity + translateY(16px→0),240ms with 70ms stagger. Explain reading order without animating size or blur.

Control feedback
150ms · ease-out

Hover changes the background; pointer press scales to .98; keyboard focus is immediate. Leaving or releasing returns smoothly to rest.

Narrative reveal
800ms · (.22,1,.36,1)

Click-to-replay stage only: opacity 0→1, translateY 24→0, stagger 70ms. Content is visible by default, with no scroll gate.

Project media
800ms · (.22,1,.36,1)

Fine-pointer hover scales imagery 1→1.04. Keyboard focus reveals supporting information immediately; touch access does not depend on hover.

Disclosure / dialog
Immediate state change

This iteration uses native details and dialog. Do not imply unimplemented height or exit animations. Escape closes the dialog and restores trigger focus.

Loading
900ms · linear

The save demonstration delays for 900ms, exposes aria-busy, prevents repeat triggers and announces completion as status text. Local only; no data is sent.

Reduced motion
0ms

Either the system preference or the page switch disables animations, transforms and transitions. Save status remains visible; the spinner is not the only feedback.

When content pushes back.

This is a component stress sample, not a full-page browser-zoom test. Also inspect navigation and layout in an actual 320px viewport.

Homepage coverage & review extensions

The catalogue and Figma assets are not synchronized live. Existing rules, deployed homepage source and pending additions are separated so a rendered value does not automatically count as approved.

Homepage compositions need rules too

Deployed CSS from www.deethin.site has been compared with local production source. The hero retains its design; compositions below it, project cards, the Portfolio review page and this catalogue share one token entry point. Sources and pending status remain explicit; added values are not automatically Figma-approved.

Evidence / inverse

fabrica.module.css / .caseSection · .caseEvidence

Black chapter / dark-gray cards / 4 → 2 → 1 columns /18px radius

Dark surfaces composed with evidence; not a universal page dark mode

View homepage compositions

Contact / inverse + light

fabrica.module.css / .contactSection · .contactStory

Paired dark/light surfaces /24px panel /28px padding / separate form

Complete Contact composition; controls reuse the catalogue’s form and button

View homepage compositions

Scroll / editorial reveal

FabricaMotion.tsx + fabrica.module.css:699–717

800/950ms ·40px travel ·7px blur · one entrance

Reveal each group on scroll; visible by default and immediate with reduced motion

View homepage compositions

Hero / interactive field

HeroExperience.tsx / smoke-renderer.ts

WebGL light field / opening timeline / static fallback

Existing Hero analysis is retained; fallback does not prove complete interaction reproduction

View homepage compositions

Evidence / inverse

Product

A deployed bilingual portfolio portal, with historical versions retained for comparison and recovery

Content

A source-led path from an Obsidian factual master to bilingual modules and project pages

Collaboration

A bounded Codex → WorkBuddy task with explicit evidence, acceptance criteria, and return material

Quality

A reviewable pilot spanning the local Design System V2, Figma Inuse assets, and a representative page

Let's talk.

Tell me about the product, the difficult part, and what a useful outcome would look like.

Inspect deployed composition tokens (Current source, not claimed Figma approval)
--home-evidence-canvas
#0d0d0d
--home-evidence-card
var(--ds-surface-dark)
--home-evidence-text
var(--ds-surface)
--home-evidence-muted
#aaaaaa
--home-evidence-label
#8a8a86
--home-evidence-radius
var(--ds-radius-panel)
--home-evidence-card-radius
var(--ds-radius-card)
--home-evidence-card-padding
22px
--home-evidence-card-height
200px
--home-evidence-card-gap
var(--ds-space-2)
--home-evidence-title-size
var(--ds-type-h3)
--home-evidence-title-leading
1.15
--home-evidence-title-gap
50px
--home-contact-canvas
#111111
--home-contact-muted
#b2b2ae
--home-contact-radius
var(--ds-space-6)
--home-contact-padding
var(--ds-radius-panel)
--home-contact-title-leading
.9
--home-contact-title-tracking
-.07em
--home-contact-title-size
clamp(76px,10vw,140px)

Current Figma uses a Paint Style chain

  1. Inuse numeric COLOR primitive
  2. Semantic Paint Style
  3. Node Fill / Stroke
  4. Manual CSS mapping
  5. Representative page + states

Sources: the 2026-10-04 binding manifest and 2026-09-27 foundation audit. Light / Inverse are usage contexts, not automatic modes. The older Semantic-Colors / Component-colors variable manifest below is a historical proposal, not current Figma assets.

Small decision cards & existing buttons

Content remains readable; fine-pointer hover shows the existing Overlay/Modal shadow at the owner’s request, without new shadow colors.

Added & pending items: do not conflate status

The light-blue supporting surface was withdrawn in the owner’s latest feedback and is no longer available. Buttons, muted text and focus reuse the catalogue. Unconfirmed mappings and compositions are listed separately. Figma was not reread this iteration because of tool-call limits; that is not evidence of missing assets.

primary-cta
var(--ds-ink)Existing component reusedV2 / .button

Restore the black pill primary button; no custom large blue panel

muted-text
var(--ds-muted)Existing web token / Figma mapping pendingV2 tokens.ts / muted

An existing web role; live Figma Paint Style has not been verified

focus
var(--ds-focus)Existing web token / Figma mapping pendingV2 tokens.ts / focus; Figma also has propose/System/Focus/Light

Reuse the catalogue focus ring without claiming different values match

mono-strong
700Pending / not usedPrevious candidate

Page uses Data/Label 500 again;700 remains pending and unused

closing-24
var(--ds-type-h3)Existing size / role pendingV2 / H3 24px

Size exists; closing-text role still needs confirmation

responsive-type
var(--ds-type-h1) / var(--ds-type-h2)Existing interpolationV2 / typeScale

Remove ch limits in both languages; restore Chinese leading 1.25 per catalogue

breakpoints
900 / 640 / 400pxPendingPrevious candidate

Generate media rules from this registry

gallery-width
min(85%, 48rem)PendingOwner requested galleries

Both galleries share width; do not limit text lines

bottom-blur
112px / 4,8,16pxPendingPrevious candidate

Keep bottom blur isolated; not an approved Figma Effect Style

scroll-choreography
800ms / 950ms / 40px / 7pxProduction-source pattern / Pending adoptionFabricaMotion.tsx / fabrica.module.css:699

Group entrances; reduced motion and keyboard location show content immediately

The homepage, current Portfolio review page and this catalogue use the same portfolioTokens object. These additions record existing homepage values; they do not imply Figma synchronization or new approval.

Tool strip
Owner-requested

Single row at every width; native horizontal scroll when needed; no visible heading.

Project card
Existing V2 component

4:3 media, project metadata and title; reveal tags and arrow on hover or focus, visible on touch.

Studies
Observed + owner-requested layout

Each card fills a complete row at every width; thumbnail, localized title and summary retain their shared heading and surface roles.

Capabilities
Observed + owner-requested interaction

One movable title per item, images, description and tags; no repeated title or category caption. Owner-requested 650ms ease-in-out layout transition; reduced motion remains immediate.

Evidence + contact
Observed homepage

Existing inverse composition, cards and form consume shared semantic tokens.

Site footer
Owner-requested shared component

One site footer per route; localized navigation points back to homepage sections.

Tool strip · working component

Capabilities · one title / 001–004

Mobile text-input rules defined by the task each piece of content performs.

Interaction DesignContent DesignValidationAutomotive

Shared footer · working component

Inspect the additional homepage tokens
--home-evidence-canvas
#0d0d0d
--home-evidence-card
var(--ds-surface-dark)
--home-evidence-text
var(--ds-surface)
--home-evidence-muted
#aaaaaa
--home-evidence-label
#8a8a86
--home-evidence-radius
var(--ds-radius-panel)
--home-evidence-card-radius
var(--ds-radius-card)
--home-evidence-card-padding
22px
--home-evidence-card-height
200px
--home-evidence-card-gap
var(--ds-space-2)
--home-evidence-title-size
var(--ds-type-h3)
--home-evidence-title-leading
1.15
--home-evidence-title-gap
50px
--home-contact-canvas
#111111
--home-contact-muted
#b2b2ae
--home-contact-radius
var(--ds-space-6)
--home-contact-padding
var(--ds-radius-panel)
--home-contact-title-leading
.9
--home-contact-title-tracking
-.07em
--home-contact-title-size
clamp(76px,10vw,140px)
--home-frame-inset
6px
--home-frame-inset-compact
var(--ds-space-1)
--home-gutter
30px
--home-gutter-tablet
22px
--home-gutter-compact
var(--ds-space-4)
--home-section-space
138px
--home-section-space-compact
94px
--home-display
clamp(84px,11.25vw,144px)
--home-display-compact
clamp(62px,19vw,112px)
--home-display-leading
.92
--home-display-tracking
-.06em
--home-study-heading
clamp(56px,7vw,92px)
--home-study-heading-compact
clamp(52px,17vw,76px)
--home-heading
clamp(50px,6vw,78px)
--home-heading-compact
clamp(42px,13vw,68px)
--home-heading-leading
1.08
--home-heading-tracking
-.055em
--home-intro-size
20px
--home-intro-size-compact
17px
--home-copy-leading
1.45
--home-copy-measure
560px
--home-header-gap
100px
--home-header-gap-compact
60px
--home-heading-gap
90px
--home-heading-gap-compact
var(--ds-space-12)
--home-study-space-start
56px
--home-study-space-end
170px
--home-study-space-end-compact
110px
--home-study-card-height
220px
--home-study-card-height-compact
190px
--home-study-thumb
76px
--home-study-thumb-compact
68px
--home-study-card-radius
22px
--home-study-title
clamp(20px,2.1vw,30px)
--home-study-title-leading
1.05
--home-media-placeholder
#dededb
--home-services-canvas
#0f0f0f
--home-services-text
#f8f8f5
--home-inverse-line
rgb(255 255 255 / .18)
--home-inverse-muted
#aaaaaa
--home-service-index
#b1b1ad
--home-inverse-control-line
rgb(255 255 255 / .25)
--home-services-space-start
110px
--home-services-space-end
90px
--home-services-list-gap
86px
--home-services-list-gap-compact
54px
--home-service-height
92px
--home-service-height-compact
76px
--home-service-title
clamp(24px,3vw,40px)
--home-service-title-compact
21px
--home-service-expanded-title
var(--ds-type-h2)
--home-service-inset
24%
--home-service-inset-compact
72px
--home-service-index-width
62px
--home-service-toggle
46px
--home-service-toggle-compact
40px
--home-service-fan-height
160px
--home-service-image-width
112px
--home-service-image-height
84px
--home-service-image-step
44px
--home-service-image-turn
7deg
--home-service-image-top
20px
--home-tag-padding-block
9px
--home-tag-padding-inline
13px
--home-wordmark-weight
650
--home-section-extended-space
180px
--home-case-title
clamp(44px,5vw,68px)
--home-case-wordmark
clamp(66px,10vw,140px)
--home-case-wordmark-compact
18vw
--home-case-height
min(67vw,800px)
--home-case-height-compact
120vw
--home-case-height-max-compact
650px
--home-case-overlay
linear-gradient(180deg,rgb(0 0 0 / .05),rgb(0 0 0 / .62))
--home-case-media-inset
-7%
--home-case-media-height
114%
--home-case-media-scale
1.05
--home-case-media-travel
5%
--home-contact-height
760px
--home-contact-height-compact
690px
--home-contact-heading
clamp(38px,4vw,58px)
--home-contact-heading-gap
96px
--home-contact-form-gap
7px
--home-contact-textarea-height
110px
--home-contact-muted-note
#999999
--home-contact-border
rgb(255 255 255 / .2)
--home-footer-statement
clamp(32px,4vw,54px)
--home-footer-statement-tracking
-.045em
--home-footer-email
clamp(24px,3vw,42px)
--home-footer-wordmark
clamp(110px,20vw,270px)
--home-footer-wordmark-compact
26vw
--home-footer-wordmark-leading
.7
--home-footer-wordmark-tracking
-.085em
--home-footer-title
clamp(20px,3vw,42px)
--home-footer-label
#92928f
--home-footer-legal
#888888
--home-footer-columns-gap
120px
--home-footer-wordmark-gap
160px
--home-footer-columns-gap-compact
86px
--home-footer-wordmark-gap-compact
110px
--home-heading-reveal-duration
1050ms
--home-heading-reveal-ease
cubic-bezier(.16,1,.3,1)
--home-heading-reveal-travel
110%
--home-study-hover-scale
1.06
--home-hover-travel
3px
--home-hover-duration
320ms
--project-media-ratio
4 / 3
--project-arrow-size
52px
--project-arrow-size-compact
44px
--project-media-hover-scale
1.04
--project-arrow-rest-scale
.75
--project-arrow-rest-turn
-20deg
--project-arrow-duration
500ms
--project-arrow-icon-size
22px
--project-tag-size
11px
--project-tag-padding
6px 10px
--project-tag-padding-compact
5px 8px
--home-tools-gap
var(--ds-space-8)
--home-tools-padding
var(--ds-space-6)
--home-tools-item-width
var(--ds-space-32)
--home-capability-open-padding
76px
--home-capability-index-top
36px
--home-capability-toggle-top
var(--ds-space-6)
--home-capability-index-top-compact
30px
--home-capability-toggle-top-compact
var(--ds-space-4)
--home-blur-layer
30
--home-blur-mask-small
linear-gradient(to bottom, transparent, rgb(0 0 0 / .12) 20%, black 62%)
--home-blur-mask-medium
linear-gradient(to bottom, transparent 25%, rgb(0 0 0 / .15) 48%, black 82%)
--home-blur-mask-large
linear-gradient(to bottom, transparent 48%, rgb(0 0 0 / .2) 72%, black)
--home-grid-projects-heading
minmax(0, 1fr) minmax(260px, .65fr)
--home-grid-studies-heading
minmax(0, 1fr) minmax(240px, .65fr)
--home-grid-service-legacy
minmax(120px, 24%) minmax(0, 1fr) 52px
--home-grid-service-panel-legacy
minmax(120px, 24%) minmax(0, 1fr) minmax(250px, .8fr)
--home-grid-service-compact
62px minmax(0, 1fr) 42px
--home-grid-study-card
var(--home-study-thumb) minmax(0, 1fr)
--home-grid-study-card-compact
var(--home-study-thumb-compact) minmax(0, 1fr)
--home-study-line
rgb(16 16 16 / .16)
--home-study-letter-spacing-heading-3
-.035em
--home-study-padding
0 6px
--home-study-outline
2px solid #0b6eff
--home-section-padding
138px 30px
--home-kicker-font-size
14px
--home-kicker-line-height
1
--home-kicker-width
15px
--home-kicker-padding
2px
--home-heading-suffix-padding-right
22%
--home-item-tag-font-weight
700
--home-item-tag-letter-spacing
.08em
--home-case-hero-inset
-7% 0
--home-case-hero-transition
transform 800ms cubic-bezier(.22,1,.36,1)
--home-studies-header-line-height
.95
--home-studies-header-max-width
38ch
--home-study-card-padding
24px 26px
--home-study-thumb-transition
transform 300ms cubic-bezier(.32,.72,0,1)
--home-study-card-body-letter-spacing
-.04em
--home-study-card-body-margin-top
10px
--home-study-card-body-line-height
1.35
--home-pill-action-gap
36px
--home-pill-action-margin-top
28px
--home-pill-action-padding
0 22px
--home-pill-action-border-radius
999px
--home-pill-action-width
18px
--home-services-section-padding
110px 30px 90px
--home-services-section-box-shadow
0 18px 32px rgb(0 0 0 / .18)
--home-services-section-color
#777
--home-service-list-border-bottom
1px solid rgb(255 255 255 / .18)
--home-service-toggle-border
1px solid rgb(255 255 255 / .25)
--home-service-fan-border
2px solid #111
--home-service-copy-max-width
14ch
--home-service-copy-font-weight
550
--home-service-copy-max-width-1
40ch
--home-service-copy-color
#aaa
--home-service-tags-color
#888
--home-service-tags-padding
9px 13px
--home-service-tags-color-2
#111
--home-case-section-padding
42px 30px 80px
--home-case-section-background
#0d0d0d
--home-case-meta-color
#a7a7a3
--home-case-hero-margin-top
38px
--home-case-hero-background
#1f1f1f
--home-case-wordmark-inset
auto 34px 28px
--home-case-wordmark-line-height
.9
--home-case-wordmark-letter-spacing
-.07em
--home-case-intro-padding-top
42px
--home-case-intro-border-bottom
1px solid currentColor
--home-case-intro-max-width
16ch
--home-case-intro-letter-spacing
-.05em
--home-case-evidence-margin-top
80px
--home-case-evidence-min-height
200px
--home-case-evidence-background
#1d1d1d
--home-case-evidence-color
#8a8a86
--home-case-evidence-margin-top-3
50px
--home-case-evidence-line-height
1.15
--home-insights-header-gap
8%
--home-insights-header-max-width
12ch
--home-contact-section-padding
180px 30px 8px
--home-contact-panel-max-width
10ch
--home-contact-form-padding
12px 0
--home-contact-form-border-bottom
1px
--home-contact-form-width
19px
--home-contact-form-line-height
1.4
--home-contact-story-font-size
clamp(76px, 10vw, 140px)
--home-contact-story-max-width
34ch
--home-contact-story-color
#b2b2ae
--home-contact-notes-border-top
1px solid rgb(255 255 255 / .2)
--home-contact-notes-color
#999
--home-footer-padding
80px 30px 28px
--home-footer-border-radius
28px 28px 0 0
--home-footer-statement-max-width
22ch
--home-study-transform
translate3d(0, 40px, 0)
--home-study-filter
blur(7px)
--home-study-transition
800ms
--home-study-transition-4
950ms
--home-study-transform-5
translate3d(0, 0, 0)
--home-study-filter-6
blur(0)
--home-study-transform-7
translateY(110%)
--home-study-transform-8
translateY(0)
--home-study-card-transform
scale(1.06)
--home-pill-action-transform
translate(3px, -3px)
--home-pill-action-transition
transform 320ms cubic-bezier(.22,1,.36,1)
--home-section-padding-compact
94px 16px
--home-why-section-padding-compact
32px 16px 110px
--home-studies-header-margin-bottom-compact
34px
--home-study-card-padding-compact
20px 22px
--home-services-section-padding-compact
80px 16px 70px
--home-service-panel-margin-bottom-compact
26px
--home-service-fan-min-height-compact
116px
--home-case-section-padding-compact
28px 16px 60px
--home-contact-section-padding-compact
110px 4px 4px
--home-contact-story-font-size-compact
20vw
--home-footer-padding-compact
70px 20px 24px
--home-footer-border-radius-compact
22px 22px 0 0
--home-study-transition-duration
.01ms
--home-service-item-top
-236px
--home-service-item-top-9
-248px
--home-service-item-top-compact
-232px
--home-service-item-top-compact-10
-246px

A system behind the system.

Historical variable architecture proposal (not the current Inuse implementation)Token & Style Architecture v1.1 · Proposed

Local production homepage source and browser measurements provide the evidence; V2 is an inspectable proposal. Separate Figma variable type, name path, scope, mode and alias: variables hold single values and aliases, styles compose recipes, and components define structure and states. This is a manual binding guide, not a claim of Figma synchronization or a universal JSON import format.

Primitive-colors / blue / 500 = #0087FB [Light]
Primitive-colors / sky / 300 = #73D1F8 [Inverse]
  ↑ Semantic-Colors / color / text / accent
    ↑ Component-colors / data-label / text
      ↑ DataLabel instance · text fill

Text Style / Data / Label = family + size + weight + line-height + tracking
Effect Style / Overlay = shadow layers + offsets + blur + alpha
Paint Style / Hero / Fallback = gradient stops + angle + positions

Modes select context; they are not a fourth level in the alias chain.
Raw material / single value

01 · Primitive-colors

Store color values without assigning purpose. Every Figma variable has type COLOR and one Value mode. Leave scope unset to discourage direct primitive selection in components.

  • Neutral covers white, paper, gray, dark gray and near-black; brand covers #73D1F8 / #0087FB.
  • Keep RGBA primitives for translucent boundaries and shadows; do not flatten them into opaque gray.
  • Current names mix roles such as neutral/ink with scale names such as neutral/900. Unify naming when completing the palette, without silently changing existing Figma IDs in this iteration.
Purpose / Light + Inverse

02 · Semantic-Colors

This layer is still COLOR throughout. In color/text/primary, text means a usage location, not a String/Text variable type. Each mode value must be a VARIABLE_ALIAS to Primitive-colors, not a typed path string.

  • Scopes: color/surface/* uses FRAME_FILL + SHAPE_FILL; color/text/* uses TEXT_FILL; color/border/* uses STROKE_COLOR.
  • Light and Inverse select which primitive the same purpose resolves to on light and dark backgrounds.
  • Semantic names do not specify a literal color: use text/primary and surface/card, not black-text or white-card.
Space, shape, type & time

03 · Foundation / numbers

Store bindable FLOAT / STRING single values separately from color modes.

  • spacing/4…128 uses GAP scope; radius/control=8, card=18 and chapter=28 use CORNER_RADIUS.
  • size/control/min-height=48 uses WIDTH_HEIGHT. Font family is STRING; font size, line height and weight are FLOAT.
  • duration/feedback=150 is milliseconds. State the unit in the description so it cannot be mistaken for 150px.
Compact + Wide, independent of color

04 · Layout / viewport

Responsive sample values and Light / Inverse are independent dimensions.

  • Figma uses Compact-390 / Wide-1440 for fixed artboard samples; the web continues to use clamp and breakpoints.
  • Do not combine Light-Mobile, Light-Desktop, Dark-Mobile and Dark-Desktop in one collection: color and layout would no longer switch independently.
Add aliases only for real reuse

05 · Component-colors

Point component parts to semantic purposes, not hex values or direct Primitive-colors references that skip Semantic-Colors.

  • button/primary/background → color/action/primary/background;project-card/background → color/surface/card。
  • data-label/text → color/text/accent; tag/text → color/text/primary. Component aliases continue to resolve when the parent container’s mode changes.
  • Add this layer only when components need an independent branch. Regular body text binds directly to color/text/primary.
TYPE / NAME / SCOPE

Separate variable type ≠ name path ≠ scope

color/text/primary is a name: color is the domain, text the location, primary the priority. Its Figma variable type must be COLOR, not STRING.

TEXT_FILL is a scope that exposes the color in text-fill pickers. Similarly, color/border/subtle remains COLOR but uses STROKE_COLOR.

A String/Text result after import means the importer stored neutral/ink as text instead of creating a VARIABLE_ALIAS. Renaming does not repair a variable’s resolved type. Recreate it as Color and bind the primitive through the variable picker.

Light context

Light

#F4F4F2 canvas + #FFFFFF card

For light homepage sections, white project cards, inputs and regular content. Set the parent Frame / Section to Light; text/primary resolves to #101010.

Inverse context

Inverse

#101010 canvas + #1D1D1D card

For black sections, dark-gray evidence cards and dark stages. Set only that parent to Inverse; text/primary resolves to white. This does not switch the entire website to dark mode.

Manual mapping table: every item is a Color variable

text / surface / border describe semantic purposes, not variable types. Light / Inverse should point to primitives through the Figma alias picker, not names copied as text values.

Semantic variableFigma typeScopeLight → primitiveInverse → primitiveWhy / where it applies
color/surface/canvasCOLORFRAME_FILL, SHAPE_FILLneutral/paper · #F4F4F2neutral/ink · #101010Large section base: paper and dark stage share one responsibility across two modes.
color/surface/cardCOLORFRAME_FILL, SHAPE_FILLneutral/white · #FFFFFFneutral/900 · #1D1D1DContent surfaces on the base; dark contexts use dark gray rather than white cards.
color/text/primaryCOLORTEXT_FILLneutral/ink · #101010neutral/white · #FFFFFFMain body text, headings and high-priority information. text is a usage group.
color/text/mutedCOLORTEXT_FILLneutral/muted · #686866neutral/inverse-muted · #AAAAAASupporting text and placeholders; do not dilute primary with ad hoc opacity.
color/text/accentCOLORTEXT_FILLblue/500 · #0087FBsky/300 · #73D1F8MONO labels on light surfaces and brand accents on dark surfaces. White-background 12px text still requires contrast care.
color/action/primary/backgroundCOLORFRAME_FILL, SHAPE_FILLneutral/ink · #101010neutral/white · #FFFFFFPrimary button background; reversed to white inside dark containers.
color/action/primary/textCOLORTEXT_FILLneutral/white · #FFFFFFneutral/ink · #101010Paired with the primary-button background for readable contrast in Light / Inverse.
color/border/subtleCOLORSTROKE_COLORneutral/ink-alpha-16neutral/white-alpha-16Structural separators and subtle boundaries; retain alpha to blend with the background.
color/border/controlCOLORSTROKE_COLORneutral/boundary · #858581neutral/inverse-muted · #AAAAAAVisible input and secondary-control boundaries, not body-text color.
color/focus/ringCOLORSTROKE_COLORblue/focus · #185BC1blue/500 · #0087FBKeyboard focus-visible indicator. Mapping is temporary; the existing Figma focus definition takes precedence.
color/feedback/errorCOLORTEXT_FILL, STROKE_COLORred/error · #B42318red/error · #B42318Error text and boundaries. Inverse contrast is not verified and should not be published directly.
color/feedback/successCOLORTEXT_FILL, STROKE_COLORgreen/success · #17663Bgreen/success · #17663BCompletion state. Confirm light/dark colors against the existing Figma palette.
color/feedback/warningCOLORTEXT_FILL, STROKE_COLORamber/warning · #825300amber/warning · #825300Warnings and pending confirmation. Confirm light/dark colors against the existing Figma palette.
color/effect/shadowCOLOREFFECT_COLORneutral/ink-alpha-10neutral/ink-alpha-45For overlay / modal effect styles only. Inverse shadow is an unverified placeholder; static cards do not bind it.
ONE COMPLETE EXAMPLE

A complete alias chain

Semantic-Colors / color/text/primary
  variable type: COLOR
  scopes: TEXT_FILL
  Light value: VARIABLE_ALIAS → Primitive-colors / neutral/ink
  Inverse value: VARIABLE_ALIAS → Primitive-colors / neutral/white

Component-colors / data-label/text
  variable type: COLOR
  Light + Inverse: VARIABLE_ALIAS → Semantic-Colors / color/text/accent
  1. Create primitives first

    Create COLOR variables in Primitive-colors with a single Value mode. Enter RGBA values and leave scope unset.

  2. Then create semantics

    Create color/text/primary in Semantic-Colors, explicitly choosing Color, then add Light and Inverse modes.

  3. Bind through the alias picker

    Do not type neutral/ink into the value. Use the variable icon / Apply variable: Primitive-colors/neutral/ink for Light, neutral/white for Inverse.

  4. Set scope

    text/* uses TEXT_FILL, surface/* FRAME_FILL + SHAPE_FILL, border/* STROKE_COLOR. This determines which Figma picker exposes the variable.

  5. Switch mode on the parent container

    Set a light section Frame to Semantic-Colors=Light, and a black section Frame to Inverse. Text inside still binds to the same color/text/primary.

  6. Add component aliases last

    Create Component-colors only for stable reused parts such as Button, ProjectCard and DataLabel, aliasing them to Semantic-Colors.

Current palette completeness

Confirmed visual anchors
#FFFFFF, #F4F4F2, #101010, #1D1D1D, #73D1F8 and #0087FB. Start with canvas, card, primary-text and accent mapping.
Available, but naming needs consolidation
#E4E4DF, #AAAAAA, #858581 and #686866 currently serve disabled, inverse-muted, boundary and muted. Consolidate them as scale names when completing neutrals; keep purposes in Semantic-Colors.
Not ready to lock
Focus, error, success, warning and their Inverse variants are not fully aligned with existing Figma colors. Do not automatically interpolate a full scale merely to complete it.
Text styles
Homepage / Hero, Editorial / Section, Project / Title, Body / ZH and Data / Label. Family, size, weight, leading and tracking form a recipe; bind text fill separately to text/*. Do not hide color in text-style naming.
Effect styles
Overlay / Modal: two real shadow layers, 0 8 24 / ink 10% + 0 32 80 / ink 16%. Blur is an effect, not a gray block. Web z-index does not belong in shadow styles.
Paint styles
Hero / Fallback uses a gradient recipe; stops can reference primitives or hero-local colors. Solid colors can bind semantic variables without duplicate Paint Styles. The WebGL light field is not a CSS gradient.
Layout guides + Auto Layout
Layout guides define column grids; Auto Layout defines padding, gap, hug/fill and alignment. Components/variants define responsive structures and states. Grid Styles cannot replace Auto Layout.
Current source → Proposed mapping

Hero

page.module.css .heroHeading / HeroExperience.tsx / smoke-renderer.ts
Typography

Inter 500;clamp(96px,13.9vw,220px);line .85;tracking −.04em。≤700px:clamp(66px,13.4vw,96px),line .95。

Text Style / Homepage / Hero: size belongs in Layout, weight in Foundation. Approximately 200.16px on a 1440px artboard; 66px on a 390px artboard.

Space / shape

Heading padding 40×38px, gap 24px; at ≤700px, padding 30×24px. The heading itself has no radius, border or shadow.

Component / hero / heading-padding; Auto Layout reflows from horizontal to compact. Do not replace the homepage gutter with the documentation-page gutter.

Paint / motion

White text; five main WebGL palette values. Opening: name .65s, popup 2.95s, typing 3.95s at 42ms per character; dock 1.35s.

Text → text/on-hero; light field → local/hero; static fallback → Paint Style. Record the timeline as choreography, not a universal component animation.

Current source → Proposed mapping

Section Heading

fabrica.module.css .section / .displayRow / .projectsHeader
Typography

Inter 600; clamp(84px,11.25vw,144px); leading .92; measured tracking −.055em. Local source uses −.06em, but global !important overrides it through a variable; browser measurement prevails. At ≤700px: clamp(62px,19vw,112px).

Text Style / Editorial / Section: 1440px→144px / leading 132.48 / tracking−7.92px; 390px→74.1px / leading 68.172 / tracking−4.0755px. This catalogue’s H2 is deliberately smaller and is not the homepage section size.

Space / layout

Section padding 138×30px; at ≤1000px, inline 22px; at ≤700px, 94×16px. displayRow gap 30; below Work heading, 100px / compact 60px.

Layout / section-padding + Component / section-heading / gap. Work is a local exception, not forced into 128px.

Paint / motion

Ink text; no heading shadow. Source title mask: 110%→0 over 1050ms (.16,1,.3,1); outer reveal 800/950ms.

Fill → text/primary; mask and timeline belong to component motion. V2 removes blur and uses transform / opacity only: a Proposed performance trade-off.

Current source + owner-requested V2 changes

Project Card

fabrica.module.css .project / .projectImage / .projectCaption / .imageArrow
Typography

Source title: Inter 18px/600/1.1, inherited tracking −.035em; label 11px/700/.08em; year 13px. V2 uses wrapping 18px/1.25 titles and 12px MONO data labels.

Keep Text Style / Project / Title separate from Data / Label. MONO and readable leading are Proposed in this iteration; actual metadata still comes from project content.

Space / shape

Source: two columns, gap 8, cover 16:9, radius 18, caption padding 20×24 / compact inline 18. V2: cover 4:3, caption 20×24 / compact 20, cover overlay inset 16 / gap 8.

4:3 is the proposal requested for larger images, not an original-site value. Component / project-card references spacing and radius; Auto Layout uses title hug, width fill and cropped media.

Paint / motion

White background, no static shadow. Source cover scale 1.06→1.1 /800ms; arrow 52px, opacity 260ms, scale.75 rotate−20°→rest /500ms.

V2 cover 1→1.04 /800ms; white tags and arrow reveal in one row over 240ms. Title stays visible; Read case study is removed. Hover/focus/touch/reduced-motion have alternatives.

  1. Inventory first, do not rebuild

    Use existing Primitive-colors + Semantic-Colors as the candidate core library. Portfolio / Semantic / Draft initially serves as a migration adapter to one semantic source. Review consumers before discussing retirement; nothing is deleted in this iteration.

  2. Check bindings & opacity

    Record stable ID, alias target, type, mode, scope, sourceRevision, Current/Proposed and replacement ID for each item. Fills use semantic/component bindings; verify text, border and effect alpha separately. No circular aliases.

  3. Build three real components

    Hero → SectionHeading → ProjectCard: record layers, bindings, styles, variants and content sources. Reproduce one artboard’s static keyframe before extending states. A page of color blocks is not sufficient.

  4. Review before adoption

    Compare web and Figma with matching font files, content, crops and widths (1440 / 390 / 320). Suggested key-dimension tolerance is ≤1px, without wrapping drift. Review motion timing and fallback separately; do not promise exact frame-by-frame WebGL reproduction in Figma. V1 stays available.

A traceable handoff.

Sources: the 2026-10-04 binding manifest and 2026-09-27 foundation audit. Light / Inverse are usage contexts, not automatic modes. The older Semantic-Colors / Component-colors variable manifest below is a historical proposal, not current Figma assets.

<button className={styles.button} type="button">
  Review project
</button>

/* tokens.ts → tokenVariables → scoped CSS */
.button {
  min-height: var(--ds-control-height);
  padding: var(--ds-space-3) var(--ds-control-padding);
  gap: var(--ds-control-gap);
  border-radius: var(--ds-radius-pill);
}
Historical variable architecture proposal (not the current Inuse implementation)
LEGACY MANIFEST INTERNALLY VALID5 collections · 75 variables

Internal names, mode values and alias targets are complete. This validates the historical proposal itself, not adoption by current Inuse.

Review, then adopt.

This only demonstrates a protected decision interface. Confirmation does not modify production or mark the direction as accepted. Adoption requires explicit owner feedback.