@ericrisco/rsc 3.1.3 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -6
- package/manifest.json +43 -69
- package/package.json +6 -1
- package/scripts/design-upstream.js +92 -0
- package/scripts/doctor.js +0 -24
- package/scripts/lib/default-skill-floor.js +5 -1
- package/scripts/lib/domains.js +2 -2
- package/scripts/lib/recommend.js +1 -3
- package/scripts/lib/retired-skills.js +7 -1
- package/skills/ai-media/SKILL.md +2 -2
- package/skills/design/IMPECCABLE-LICENSE.txt +191 -0
- package/skills/design/SKILL.md +79 -328
- package/skills/design/THIRD_PARTY.md +26 -0
- package/skills/design/engine/LICENSE +21 -0
- package/skills/design/engine/RUN.md +515 -0
- package/skills/design/engine/UPSTREAM.json +4 -0
- package/skills/design/engine/assets/app.css +216 -0
- package/skills/design/engine/assets/base.css +105 -0
- package/skills/design/engine/assets/base.js +37 -0
- package/skills/design/engine/assets/charts.js +617 -0
- package/skills/design/engine/assets/scenes/stage.css +28 -0
- package/skills/design/engine/assets/scenes/stage.js +133 -0
- package/skills/design/engine/library/app.json +1327 -0
- package/skills/design/engine/library/directions.json +1078 -0
- package/skills/design/engine/library/heroes.json +1086 -0
- package/skills/design/engine/library/motions.json +92 -0
- package/skills/design/engine/library/palettes.json +1485 -0
- package/skills/design/engine/library/photos.json +7240 -0
- package/skills/design/engine/library/sections.json +4429 -0
- package/skills/design/engine/library/sites.json +8350 -0
- package/skills/design/engine/library/type.json +2024 -0
- package/skills/design/engine/references/app-screens.md +1199 -0
- package/skills/design/engine/references/colour.md +141 -0
- package/skills/design/engine/references/copy.md +177 -0
- package/skills/design/engine/references/critique.md +182 -0
- package/skills/design/engine/references/imagery.md +791 -0
- package/skills/design/engine/references/layout.md +292 -0
- package/skills/design/engine/references/motion.md +980 -0
- package/skills/design/engine/references/research.md +356 -0
- package/skills/design/engine/references/scenes.md +174 -0
- package/skills/design/engine/references/tells.md +115 -0
- package/skills/design/engine/references/type.md +170 -0
- package/skills/design/engine/scripts/assets.mjs +865 -0
- package/skills/design/engine/scripts/draw.mjs +584 -0
- package/skills/design/engine/scripts/inspect.mjs +303 -0
- package/skills/design/engine/scripts/lib/app-draw.mjs +203 -0
- package/skills/design/engine/scripts/lib/cdp.mjs +248 -0
- package/skills/design/engine/scripts/lib/probe.mjs +909 -0
- package/skills/design/engine/scripts/lib/rules.mjs +243 -0
- package/skills/design/engine/scripts/lint.mjs +119 -0
- package/skills/design/engine/scripts/scenes.mjs +124 -0
- package/skills/design/evals/cases.yaml +35 -46
- package/skills/design/references/design-md.md +49 -0
- package/skills/design/references/finish-review.md +46 -0
- package/skills/design/references/modes.md +51 -0
- package/skills/expo/SKILL.md +3 -4
- package/skills/marketing/references/landing-copy.md +2 -2
- package/skills/react/SKILL.md +2 -2
- package/skills/react-native/SKILL.md +3 -3
- package/skills/scroll-film/SKILL.md +220 -0
- package/skills/scroll-film/assets/page-template.html +128 -0
- package/skills/scroll-film/assets/scrub-engine.js +352 -0
- package/skills/scroll-film/evals/README.md +26 -0
- package/skills/scroll-film/evals/cases.yaml +81 -0
- package/skills/scroll-film/references/chain.md +218 -0
- package/skills/scroll-film/references/engine.md +132 -0
- package/skills/scroll-film/scripts/verify.sh +158 -0
- package/skills/swift-ios/SKILL.md +1 -1
- package/skills/ui-engineering/SKILL.md +3 -4
- package/skills/ui-engineering/evals/cases.yaml +2 -2
- package/skills/variant-explorer/SKILL.md +4 -4
- package/skills/variant-explorer/evals/cases.yaml +1 -1
- package/targets/clone-bootstrap.mjs +1 -1
- package/scripts/lib/design-identity.js +0 -117
- package/scripts/lib/starting-point.js +0 -314
- package/skills/design/evals/README.md +0 -53
- package/skills/design/references/ai-tells.md +0 -75
- package/skills/design/references/brand-grounding.md +0 -197
- package/skills/design/references/copywriting-frameworks.md +0 -138
- package/skills/design/references/design-systems.md +0 -49
- package/skills/design/references/inspiration-sources.md +0 -96
- package/skills/design/references/landing-anatomy-and-cro.md +0 -202
- package/skills/design/references/motion-and-interaction.md +0 -228
- package/skills/design/references/research-method.md +0 -154
- package/skills/design/references/signature-and-craft.md +0 -148
- package/skills/design/references/starting-point.md +0 -75
- package/skills/design/references/trends-2026.md +0 -80
- package/skills/design/references/visual-system.md +0 -237
- package/skills/design/scripts/verify.sh +0 -357
- package/skills/design-dna/PROMPT.md +0 -211
- package/skills/design-dna/SKILL.md +0 -162
- package/skills/design-dna/design-dna.schema.json +0 -230
- package/skills/design-dna/evals/README.md +0 -64
- package/skills/design-dna/evals/cases.yaml +0 -68
- package/skills/design-dna/references/method.md +0 -436
- package/skills/design-dna/scripts/emit.py +0 -164
- package/skills/design-dna/templates/PROMPT.md.tmpl +0 -42
- package/skills/design-dna/templates/SKILL.md.tmpl +0 -42
- package/skills/design-dna/templates/check.py.tmpl +0 -143
- package/skills/design-loop/SKILL.md +0 -160
- package/skills/design-loop/evals/README.md +0 -56
- package/skills/design-loop/evals/cases.yaml +0 -60
- package/skills/motion-craft/SKILL.md +0 -125
- package/skills/motion-craft/evals/cases.yaml +0 -38
- package/skills/motion-craft/scripts/verify.sh +0 -75
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
# Signature & Craft — manufacturing the distinctive idea, then the finish that sells it
|
|
2
|
-
|
|
3
|
-
A page that obeys every constraint in this skill and still feels generic is the default failure mode.
|
|
4
|
-
Constraints get you to *competent*. They do not get you to *premium*. The difference is a **visual
|
|
5
|
-
concept** — one defensible idea the whole surface commits to — plus the **craft moves** that make the
|
|
6
|
-
rendered artifact read as authored rather than assembled. This reference is the method for both. Use it
|
|
7
|
-
whenever the output has to be genuinely good, not merely compliant.
|
|
8
|
-
|
|
9
|
-
## Why compliant output still scores ~7.7
|
|
10
|
-
|
|
11
|
-
The checklist tells you the page *ships*. It cannot tell you the page is *good*, because every defect it
|
|
12
|
-
catches is an absence (no missing `<h1>`, no `transition: all`, contrast passes). Premium is a presence:
|
|
13
|
-
a point of view. The common shortfalls that keep correct work at "competent" are predictable — fix these
|
|
14
|
-
and the output moves up a band:
|
|
15
|
-
|
|
16
|
-
| Symptom of generic output | Root cause | The move |
|
|
17
|
-
| --- | --- | --- |
|
|
18
|
-
| "Looks like a nice template" | No visual concept; defaults filled every slot | Commit to ONE signature idea (below) |
|
|
19
|
-
| Tonally flat — everything medium-sized | No scale contrast; safe type ramp | Force a dominant element 3–5× the body (below) |
|
|
20
|
-
| Sections blur into one stripe | No rhythm; identical `py`, identical card grids | Vary section format + background + density (below) |
|
|
21
|
-
| Hero is a centered headline + gradient | The default the model reaches for under-specified | Show the product doing the job; earn the layout |
|
|
22
|
-
| Correct but forgettable color | Brand hue used like everyone's brand hue | One owned accent move, applied with restraint |
|
|
23
|
-
| Everything is rounded cards on white | One container idiom repeated | Mix surface treatments; let some content breathe edge-to-edge |
|
|
24
|
-
|
|
25
|
-
## Step 1 — Choose a visual concept (do this before any markup)
|
|
26
|
-
|
|
27
|
-
A visual concept is a single sentence the entire page can be checked against. It is NOT a color or a font;
|
|
28
|
-
it is an organizing idea that dictates layout, type, color, motion, and imagery together. Write it down,
|
|
29
|
-
then make every section answer to it.
|
|
30
|
-
|
|
31
|
-
> Concept = `[adjective of feeling]` + `[structural metaphor]` for `[audience doing job]`.
|
|
32
|
-
> e.g. "Quiet, instrument-panel precision for ops engineers who live in this all day."
|
|
33
|
-
> e.g. "Confident editorial broadsheet for a brand that wants to feel like a publication, not an app."
|
|
34
|
-
> e.g. "Tactile, mechanical-keyboard heft for a dev tool that should feel engineered."
|
|
35
|
-
|
|
36
|
-
Pick the concept from the DIRECTION BRIEF + brand study + research exemplars — never from your prior. If
|
|
37
|
-
you cannot say in one sentence what makes this surface different from the median SaaS page, you have not
|
|
38
|
-
chosen a concept yet, and the output will default to generic.
|
|
39
|
-
|
|
40
|
-
## Step 2 — Manufacture the signature element (the "ONE idea")
|
|
41
|
-
|
|
42
|
-
Every premium page has one element you would describe first to a friend. The brief asks for it; this is how
|
|
43
|
-
to actually generate it instead of defaulting to a gradient. Pick **exactly one** primary signature (a
|
|
44
|
-
second, quieter echo is fine; three competing signatures is noise). Choose from this vocabulary, biased by
|
|
45
|
-
the concept and domain:
|
|
46
|
-
|
|
47
|
-
- **A hero that demonstrates, not describes** — the product mid-task: a real terminal session, a live
|
|
48
|
-
chart updating, an actual diff, a populated dashboard. The single highest-leverage move for dev tools and
|
|
49
|
-
SaaS; it passes the 5s test by *showing* the value instead of claiming it.
|
|
50
|
-
- **An owned type moment** — one oversized display setting (a 96–160px headline, a tight-tracked all-caps
|
|
51
|
-
eyebrow, a serif/grotesk pairing with real contrast) that no template ships by default.
|
|
52
|
-
- **A structural signature** — an unexpected but legible layout: a horizontal-scroll feature rail, an
|
|
53
|
-
asymmetric split hero, a numbered editorial index, a sticky side-rail that tracks the section.
|
|
54
|
-
- **A material signature** — a consistent, restrained physical treatment: hairline grid lines, a single
|
|
55
|
-
grain/noise pass, a duotone photographic style, a precise mono-spaced data aesthetic.
|
|
56
|
-
- **A motion signature** — one purposeful move that recurs (a scroll-driven reveal cadence, a hover that
|
|
57
|
-
uncovers state) — only if it earns its INP/CLS budget.
|
|
58
|
-
- **A data/proof signature** — a real number rendered as the visual centerpiece (a live metric, a benchmark
|
|
59
|
-
bar, a before/after). Strongest when the proof IS the product's claim.
|
|
60
|
-
|
|
61
|
-
Rule: the signature must be *true to the product*. A fintech dashboard's signature is precision and density;
|
|
62
|
-
a creative tool's is expression. A signature borrowed from the wrong domain reads as costume. Cite which
|
|
63
|
-
research exemplar inspired the move (e.g. "feature rail per linear.app/changelog") so it is grounded, not
|
|
64
|
-
invented.
|
|
65
|
-
|
|
66
|
-
## Step 3 — Force scale contrast (the fastest fix for "flat")
|
|
67
|
-
|
|
68
|
-
Generic pages are tonally flat: the headline, the section titles, and the body are all within ~1.5× of each
|
|
69
|
-
other, so nothing dominates and the eye has nowhere to land. Premium pages have a **dramatic range**.
|
|
70
|
-
|
|
71
|
-
- Establish a clear **hero dominant**: the largest single element on the page (a headline or product visual)
|
|
72
|
-
should be **3–5× the body size**, not 2×. Commit to it.
|
|
73
|
-
- Then **demote ruthlessly**: eyebrows, labels, and metadata go *smaller and quieter* (13–14px, muted,
|
|
74
|
-
tracked) than you instinctively want. Contrast is created by the small things being genuinely small.
|
|
75
|
-
- One **focal point per viewport**. If two things compete for "biggest", neither wins — shrink one.
|
|
76
|
-
- Apply the same logic to weight (one heavy display weight against a regular body), and to color (the 10%
|
|
77
|
-
accent appears once or twice per viewport, never spread thin).
|
|
78
|
-
|
|
79
|
-
If a section feels flat, the fix is almost always *more* contrast, not more elements.
|
|
80
|
-
|
|
81
|
-
## Step 4 — Give the page rhythm (sections must not blur)
|
|
82
|
-
|
|
83
|
-
A landing page that is ten identical white sections with `py-24` and a 3-up card grid reads as one long
|
|
84
|
-
stripe. Authored pages have a **beat**: the eye is paced. Vary, section to section, at least one of:
|
|
85
|
-
|
|
86
|
-
- **Format** — full-bleed vs. contained; centered vs. asymmetric; grid vs. single statement; media-left vs.
|
|
87
|
-
media-right (alternate, don't repeat one side).
|
|
88
|
-
- **Background** — alternate base / subtly tinted / inverted (a dark section between two light ones is a
|
|
89
|
-
classic rhythm device and creates a natural CTA anchor).
|
|
90
|
-
- **Density** — a breathing, near-empty statement section after a dense feature grid resets the eye.
|
|
91
|
-
- **Container idiom** — don't make *everything* a bordered card on white. Let a hero visual run edge-to-edge;
|
|
92
|
-
let one statement sit in open space with no container at all.
|
|
93
|
-
|
|
94
|
-
Spacing rhythm is load-bearing here: section padding should step on the scale (e.g. 64 → 96px), and the
|
|
95
|
-
*gap between sections* should be visibly larger than the gap *within* a section, so groups read as groups.
|
|
96
|
-
A flat `py` on every section is the tell of generated output.
|
|
97
|
-
|
|
98
|
-
## Step 5 — The craft finish (compounding micro-decisions)
|
|
99
|
-
|
|
100
|
-
These are in the SKILL's "Premium details" table; apply them as a deliberate pass, not by accident:
|
|
101
|
-
|
|
102
|
-
- Concentric radius (`outer = inner + padding`); never same-radius nesting.
|
|
103
|
-
- Layered transparent OKLCH shadows; hairline `fg/10` borders for separation, shadow only for true float.
|
|
104
|
-
- `text-wrap: balance` on headings, `pretty` on body; `tabular-nums` on any changing number/price.
|
|
105
|
-
- Optical alignment: trust the eye over the math for icon centering and cap-height padding.
|
|
106
|
-
- Restraint: glass on floating surfaces only; gradient as seasoning on one surface; one accent, used rarely.
|
|
107
|
-
|
|
108
|
-
## Step 6 — Self-critique before you claim done (the senior-designer pass)
|
|
109
|
-
|
|
110
|
-
Before shipping, interrogate your own output with the questions a senior designer would ask in a crit. Answer
|
|
111
|
-
them honestly in your own head (or out loud to the user); if any answer is weak, iterate before delivering.
|
|
112
|
-
|
|
113
|
-
1. **What is the one idea here?** If you cannot name it in a sentence, there is no concept — go to Step 1.
|
|
114
|
-
2. **Would this place on Awwwards / Godly, or just pass review?** If "just pass", it is at ~7; name the
|
|
115
|
-
single most generic element and replace it.
|
|
116
|
-
3. **What's the most generic thing on this page right now?** (Usually: the hero, the gradient, the 3-up card
|
|
117
|
-
grid, or the stock-feeling copy.) Fix that one thing first — it has the highest leverage.
|
|
118
|
-
4. **Where does the eye land first, and is that the thing that should win?** If not, fix scale contrast.
|
|
119
|
-
5. **If I deleted the logo, would anyone know whose product this is?** If not, the concept/signature is too
|
|
120
|
-
timid.
|
|
121
|
-
6. **Does every section earn its place, or is one there out of habit?** Cut the weakest section entirely;
|
|
122
|
-
removal is a design decision.
|
|
123
|
-
7. **Is the copy carrying a specific, verifiable claim, or vibes?** Swap one vague benefit for a concrete,
|
|
124
|
-
quantified one.
|
|
125
|
-
|
|
126
|
-
The point of the pass is not to pass it — it is to make at least one concrete change as a result. A surface
|
|
127
|
-
that survives this crit unchanged on the first try usually means the crit was not honest.
|
|
128
|
-
|
|
129
|
-
## Worked example — generic → signature (dev-tool hero)
|
|
130
|
-
|
|
131
|
-
**Generic (≈7, competent):** centered `<h1>` "Ship faster with our developer platform", subhead, two buttons,
|
|
132
|
-
purple→blue gradient blob behind it, 3-up feature cards below, all sections `py-24` on white.
|
|
133
|
-
|
|
134
|
-
**Signature (≈9, premium):**
|
|
135
|
-
- *Concept:* "Engineered precision — this tool should feel like instrumentation."
|
|
136
|
-
- *Signature element:* the hero IS a live, syntax-highlighted terminal session running the actual command,
|
|
137
|
-
output streaming — the product demonstrates the value (Step 2, "demonstrate not describe").
|
|
138
|
-
- *Scale contrast:* a tight-tracked 13px mono eyebrow ("v2.4 — now with preview environments"), a 72px
|
|
139
|
-
display headline with one concrete claim ("Spin up a preview in 4s"), demoted everywhere else (Step 3).
|
|
140
|
-
- *Rhythm:* light hero → dark proof section with a real benchmark bar → light asymmetric feature split
|
|
141
|
-
(media alternating sides) → dark final CTA (Step 4).
|
|
142
|
-
- *Finish:* hairline grid lines as the material signature, mono `tabular-nums` on the benchmark, concentric
|
|
143
|
-
radius on the terminal chrome, one accent used only on the active prompt and the primary CTA (Step 5).
|
|
144
|
-
- *Crit result:* "the live terminal" is the one idea; logo-removed it still reads as this product; eye lands
|
|
145
|
-
on the streaming output, which is the value (Step 6 passed honestly).
|
|
146
|
-
|
|
147
|
-
Same constraints, same tokens, same stack — the difference is concept + signature + contrast + rhythm +
|
|
148
|
-
honest crit. That is the gap between 7.7 and premium.
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
# Reference — proposing a starting point
|
|
2
|
-
|
|
3
|
-
Three places promise to propose one: `../../design-loop/SKILL.md` phase 1 when the user says *skip*,
|
|
4
|
-
the closing line of `brand-grounding.md` when a visual dimension has no direction, and
|
|
5
|
-
`../../design-dna/SKILL.md`'s REUSE mode. This file is what they propose *from*. Without it the
|
|
6
|
-
fallback is your own prior, which is the AI-template median — the thing the whole area exists to escape.
|
|
7
|
-
|
|
8
|
-
## 0. What the project already owns wins
|
|
9
|
-
|
|
10
|
-
**Look before you offer.** Run it; do not reason about it:
|
|
11
|
-
|
|
12
|
-
```bash
|
|
13
|
-
npx @ericrisco/rsc doctor --json # read `designStartingPoint`
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
| State | What it means | What you do |
|
|
17
|
-
| --- | --- | --- |
|
|
18
|
-
| `owned` | An identity article or at least one legible style record exists | Propose **that**, by name, first. Offer nothing external until the user rejects it. More than one record → all of them are candidates, ordered as reported. Never pick one silently. |
|
|
19
|
-
| `none` | Looked in both scopes, found nothing | Go to §1. |
|
|
20
|
-
| `inconclusive` | Something could not be read | Say what, and ask for another route to it. **Do not propose past a blind spot** — a proposal made without looking is the defect this file exists to remove. |
|
|
21
|
-
|
|
22
|
-
If the owned identity **contradicts** what the user is now asking for, name the conflicting rule and let
|
|
23
|
-
them decide which wins. Same rule the loop's preflight already applies to a bar from outside.
|
|
24
|
-
|
|
25
|
-
A record that `doctor` reports with a pair below its contrast floor is not offered as a starting point.
|
|
26
|
-
|
|
27
|
-
## 1. What are you building → which bar
|
|
28
|
-
|
|
29
|
-
At most **three** candidates. Each one gets a name, one line on why it fits *this* product, and one line
|
|
30
|
-
on when it would be the wrong choice. Then **wait**. No answer → take the most demanding one and say so.
|
|
31
|
-
|
|
32
|
-
Sources are in `inspiration-sources.md`; the tier-1 set and the dated-looking list are in
|
|
33
|
-
`trends-2026.md`. **Only propose what you can actually open** — that registry marks several sources as
|
|
34
|
-
bot-blocked, and a bar that cannot be fetched dies in the loop's preflight.
|
|
35
|
-
|
|
36
|
-
| Building | Candidate bars | Wrong choice when |
|
|
37
|
-
| --- | --- | --- |
|
|
38
|
-
| SaaS marketing | Stripe · [SaaS Landing Page](https://saaslandingpage.com) browsed by section · Linear | The product is a daily tool, not a purchase decision — a marketing skin on a workhorse |
|
|
39
|
-
| Dev tool | Linear · Vercel · Resend · [Primer](https://primer.style) | The audience is not technical: dev-tool restraint reads as unfinished to them |
|
|
40
|
-
| Dashboard / internal tool | [Carbon](https://carbondesignsystem.com) · [Polaris](https://polaris.shopify.com) · [Mobbin](https://mobbin.com) flows | It is a landing page with a chart on it — density is not the job |
|
|
41
|
-
| Portfolio / editorial | [Awwwards](https://www.awwwards.com) · [Recent](https://recent.design) · [One Page Love](https://onepagelove.com) | Anything with a conversion target: award craft routinely costs LCP and the 5s test |
|
|
42
|
-
| E-commerce | [Minimal Gallery](https://minimal.gallery) for restraint · [Nicely Done](https://nicelydone.club) for real product surfaces | The catalogue is huge and the real problem is search and filtering, not the hero |
|
|
43
|
-
| Docs | [Stripe docs](https://docs.stripe.com) · [Material 3](https://m3.material.io) on states | Reading is not the job — it is a reference table, so density beats calm |
|
|
44
|
-
|
|
45
|
-
Nothing here fits what they are building? **Say so and interview.** Do not stretch the nearest row: a bar
|
|
46
|
-
chosen because it was closest is the vague bar that makes the loop approve everything on round one.
|
|
47
|
-
|
|
48
|
-
## 2. A proposal is not an answer
|
|
49
|
-
|
|
50
|
-
1. **Open the reference.** No value is proposed from a page you did not fetch. Blocked → say so, pick
|
|
51
|
-
another. Never substitute a description from memory.
|
|
52
|
-
2. **Measure it** — the loop's teardown already does this and writes 5 to 7 mechanisms. Those measured
|
|
53
|
-
values *are* the researched default this file was missing. They are not invented, and they come from
|
|
54
|
-
a page that already ships.
|
|
55
|
-
3. **Check colour before writing it.** Any text pairing must measure **≥ 4.5:1** (≥ 3:1 for large text
|
|
56
|
-
and UI). Below that, it is **not proposed** — not proposed-with-a-warning.
|
|
57
|
-
4. **Write it marked `propuesto`, naming the reference it came from.** Never as a confirmed value.
|
|
58
|
-
5. A dimension that is proposed and not yet confirmed **does not count as complete** against
|
|
59
|
-
`brand-grounding.md`'s checklist. The hard STOP stays up for it. Otherwise the prefill becomes the
|
|
60
|
-
way to cross the gate with nobody having confirmed anything.
|
|
61
|
-
6. Only what the user confirms becomes the project's identity.
|
|
62
|
-
|
|
63
|
-
## 3. The base is the floor, not the concept
|
|
64
|
-
|
|
65
|
-
A starting point gets you a defensible floor in one exchange. It does **not** satisfy the ONE signature
|
|
66
|
-
element (`signature-and-craft.md` §2), and it never will: every project that picked the same bar would
|
|
67
|
-
converge on the same page. If the only thing making this surface distinctive is the bar it started from,
|
|
68
|
-
there is no concept yet.
|
|
69
|
-
|
|
70
|
-
## See Also
|
|
71
|
-
|
|
72
|
-
- `inspiration-sources.md` — the source registry, dated, with the bot-blocked entries marked.
|
|
73
|
-
- `trends-2026.md` — the tier-1 set, and what currently reads as a template.
|
|
74
|
-
- `brand-grounding.md` — the checklist this fills in, and the STOP it does not lift.
|
|
75
|
-
- `signature-and-craft.md` — the part a starting point cannot give you.
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
# 2026 UX/UI Trends — Dated Snapshot (re-verify per project)
|
|
2
|
-
|
|
3
|
-
This is a **point-in-time snapshot**, last verified **June 2026**. Trends churn quarterly and your built-in aesthetic prior is the AI-template median — so this file is a starting reference, not a substitute for live research. **Re-run WebSearch/WebFetch per project** (per `research-method.md`) and refresh this file when you do; cite sources with their dates. Treat anything here older than ~3 months as suspect.
|
|
4
|
-
|
|
5
|
-
## How to use this file
|
|
6
|
-
|
|
7
|
-
- When the brand study (`brand-grounding.md`) leaves a visual dimension with no user direction, or the user asks for "modern" / "2026" / "premium", pull current trends and fold the findings into the output **with citations + dates**.
|
|
8
|
-
- Extract *principles*, not pixels. "Bento for feature sections" is a principle; cloning a competitor's exact grid is theater.
|
|
9
|
-
- Cross-check every trend against the non-negotiables in `SKILL.md` — a trend that breaks contrast, CWV, or the 5s test is out, however current.
|
|
10
|
-
|
|
11
|
-
## Stack currency (verified June 2026)
|
|
12
|
-
|
|
13
|
-
| Tool | Current | Notes |
|
|
14
|
-
| --- | --- | --- |
|
|
15
|
-
| Tailwind CSS | v4.3 (2026-05-08) | OKLCH-native `@theme`, no `tailwind.config.js`; v4.2 added scrollbar/logical-property utilities and new palettes. |
|
|
16
|
-
| Next.js | 15 stable (16 released; this skill targets 15 + App Router) | Async request APIs, Turbopack stable, React 19 required for App Router. |
|
|
17
|
-
| React | 19.2.x (19.2.6, 2026-05-06) | Stable in Next.js 15.1+. |
|
|
18
|
-
|
|
19
|
-
Sources: [Tailwind v4.3 / v4.2 release notes](https://tailwindcss.com/blog), [InfoQ — Tailwind 4.2](https://www.infoq.com/news/2026/04/tailwind-css-4-2-webpack/), [Next.js 15 blog](https://nextjs.org/blog/next-15), [React versions](https://react.dev/versions). Re-verify before quoting a version.
|
|
20
|
-
|
|
21
|
-
## Typography (2026)
|
|
22
|
-
|
|
23
|
-
- **Type as the hero, not decoration.** Oversized headlines, expressive display faces, and variable fonts that respond to interaction/context. Serif and ledger-style numerals are back for editorial weight where the brand allows.
|
|
24
|
-
- **Kinetic typography** — headlines that animate on scroll — but only behind a purpose gate and reduced-motion guard (see `motion-and-interaction.md`); decorative letter-jelly is out.
|
|
25
|
-
- **Still true:** modular scale, ≤2 families, 45–75ch measure, `text-wrap: balance` on headings. Trends do not override the fundamentals in `visual-system.md`.
|
|
26
|
-
|
|
27
|
-
Source: [Figma — Web design trends](https://www.figma.com/resource-library/web-design-trends/) (2026), [Tubik — UI trends 2026](https://blog.tubikstudio.com/ui-design-trends-2026/) (2026).
|
|
28
|
-
|
|
29
|
-
## Color (2026)
|
|
30
|
-
|
|
31
|
-
- **Two poles this cycle:** (1) high-energy / "dopamine" — deep blacks layered with electric neon, sunset coral, holographic accents (Y2K-adjacent); (2) calm/adaptive — light "morning", low-contrast "focus", warm "evening" modes. Pick the pole the *brand* dictates; do not default to the loud one.
|
|
32
|
-
- **OKLCH is the production default** for ramps and dark-mode token swaps (perceptually even lightness, wider P3 gamut). Build ramps by holding hue+chroma and stepping L (see `visual-system.md`).
|
|
33
|
-
- **Adaptive / time-of-day theming** is emerging beyond binary light/dark — only worth it when the audience benefits; otherwise it is complexity for its own sake.
|
|
34
|
-
- **Still true:** 60-30-10 allocation, text ≥ 4.5:1, the brand color earns attention by being rare. Vivid palettes raise the contrast-failure risk — verify, never eyeball.
|
|
35
|
-
|
|
36
|
-
Source: [Envato — UX/UI trends 2026](https://elements.envato.com/learn/ux-ui-design-trends) (2026), [Figma](https://www.figma.com/resource-library/web-design-trends/) (2026).
|
|
37
|
-
|
|
38
|
-
## Layout (2026)
|
|
39
|
-
|
|
40
|
-
- **Bento** remains the standard for feature → benefit sections: asymmetric grid, one focal cell the eye lands on first.
|
|
41
|
-
- **Visible grids / wireframe logic as foreground** — exposed columns and structural lines used as decoration, not hidden scaffolding.
|
|
42
|
-
- **Experimental navigation** (radial menus, drawers, nonlinear journeys) and maximalist/collage layering — high-risk; only where the brand is expressive and it does not cost the 5s test or accessibility.
|
|
43
|
-
- **Container queries** (`@container`, core in Tailwind v4) for components that adapt to their slot, not just the viewport.
|
|
44
|
-
- **Still true:** clear focal point, max-width ~1024–1200px, body measure ~65ch.
|
|
45
|
-
|
|
46
|
-
Source: [Figma](https://www.figma.com/resource-library/web-design-trends/) (2026), [Index.dev — 12 UI/UX trends 2026](https://www.index.dev/blog/ui-ux-design-trends) (2026).
|
|
47
|
-
|
|
48
|
-
## Motion (2026)
|
|
49
|
-
|
|
50
|
-
- **Motion earns its keep by guiding, not flashing.** The cycle has moved away from bouncy micro-interactions toward *believable* motion: progress that reports real wait time, transitions that preserve continuity.
|
|
51
|
-
- **Native CSS scroll-driven animation** (`animation-timeline: view()/scroll()`) is the default engine — zero JS, no CLS — behind an `@supports (animation-timeline: view())` feature query and a `prefers-reduced-motion` guard (see `motion-and-interaction.md`). As of June 2026 it ships in Chromium (115+) and Safari (18+, full in Safari 26); Firefox has it implemented but still behind a flag, so the `@supports` query is load-bearing for the graceful fallback.
|
|
52
|
-
- **Still true:** purpose gate (guide / communicate / preserve), compositor-only properties (`transform`/`opacity`/`filter`), enter ~250ms / exit ~150ms, reduced-motion honored.
|
|
53
|
-
|
|
54
|
-
Source: [Tubik — UI trends 2026](https://blog.tubikstudio.com/ui-design-trends-2026/) (2026), [Envato](https://elements.envato.com/learn/ux-ui-design-trends) (2026).
|
|
55
|
-
|
|
56
|
-
## Tier-1 reference set (re-fetch live)
|
|
57
|
-
|
|
58
|
-
The benchmark for premium product/landing work this cycle — fetch the live sites in the research loop rather than trusting memory of them:
|
|
59
|
-
|
|
60
|
-
- **Linear** — radical restraint, dark near-monochrome, one accent, product-forward.
|
|
61
|
-
- **Stripe** — docs + marketing balance, gradients used as restrained seasoning.
|
|
62
|
-
- **Vercel** — type-led minimalism, dev-tool voice, product shown immediately.
|
|
63
|
-
- **Resend** — dev-tool voice in copy, clean bento, annual-default pricing.
|
|
64
|
-
- **Awwwards / Godly / Land-book / Mobbin** — galleries for direction, motion, and section order; weight by domain (skip the expressive entries for a dense dev tool).
|
|
65
|
-
|
|
66
|
-
## What now reads as dated / AI-generic (avoid)
|
|
67
|
-
|
|
68
|
-
- Purple→blue gradient on every surface; centered headline over an atmospheric mesh with the product hidden below the fold.
|
|
69
|
-
- Heavy glassmorphism / neumorphism everywhere; blob backgrounds.
|
|
70
|
-
- Cards-inside-cards; one hard `0 4px 8px #000` drop shadow on everything.
|
|
71
|
-
- Bouncy jelly micro-interactions with no informational purpose.
|
|
72
|
-
|
|
73
|
-
These are the AI-template median the research-first protocol exists to escape (`research-method.md`).
|
|
74
|
-
|
|
75
|
-
## See Also
|
|
76
|
-
|
|
77
|
-
- `research-method.md` — the live research loop that refreshes this snapshot.
|
|
78
|
-
- `brand-grounding.md` — offer these researched defaults when a brand dimension has no direction.
|
|
79
|
-
- `visual-system.md` — fundamentals these trends sit on top of (and never override).
|
|
80
|
-
- `motion-and-interaction.md` — the scroll-driven / reduced-motion implementation referenced above.
|
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
# Visual System — Tokens, Type, Color, Layout, Depth
|
|
2
|
-
|
|
3
|
-
The full design-token and aesthetics system. Define tokens once with Tailwind v4 `@theme`; consume them everywhere as utilities and raw `var()`. Targets the current stack (verified June 2026): Tailwind CSS v4.3, Next.js 15, React 19, OKLCH-native color.
|
|
4
|
-
|
|
5
|
-
## Spacing scale
|
|
6
|
-
|
|
7
|
-
Spacing rhythm is what separates "designed" from "thrown together". Anchor every gap, padding, and margin to a 4/8px base scale so vertical and horizontal rhythm stays consistent.
|
|
8
|
-
|
|
9
|
-
| Step | rem | px | Typical use |
|
|
10
|
-
| --- | --- | --- | --- |
|
|
11
|
-
| 0 | 0 | 0 | reset |
|
|
12
|
-
| 1 | 0.25rem | 4 | icon gap, hairline inset |
|
|
13
|
-
| 2 | 0.5rem | 8 | tight label/input gap |
|
|
14
|
-
| 3 | 0.75rem | 12 | button padding-y |
|
|
15
|
-
| 4 | 1rem | 16 | base block gap |
|
|
16
|
-
| 6 | 1.5rem | 24 | card padding |
|
|
17
|
-
| 8 | 2rem | 32 | section inner gap |
|
|
18
|
-
| 12 | 3rem | 48 | sub-section gap |
|
|
19
|
-
| 16 | 4rem | 64 | section padding-y (mobile) |
|
|
20
|
-
| 24 | 6rem | 96 | section padding-y (desktop) |
|
|
21
|
-
|
|
22
|
-
Tailwind utilities (`p-4`, `gap-6`, `py-24`) map directly to this scale. **When to break it:** only for *optical* alignment — nudging an icon 1px to look centered, or trimming 2px off cap-height padding. Optical fixes are deliberate exceptions, not a second arbitrary scale.
|
|
23
|
-
|
|
24
|
-
## Typographic scale
|
|
25
|
-
|
|
26
|
-
Pick a modular ratio and step every size from a 16px base. Larger ratios read more editorial; smaller ratios read denser and more utilitarian.
|
|
27
|
-
|
|
28
|
-
| Ratio | Name | Ladder from 16px (rounded) |
|
|
29
|
-
| --- | --- | --- |
|
|
30
|
-
| 1.200 | Minor third | 16 · 19 · 23 · 28 · 33 · 40 |
|
|
31
|
-
| 1.250 | Major third | 16 · 20 · 25 · 31 · 39 · 49 |
|
|
32
|
-
| 1.333 | Perfect fourth | 16 · 21 · 28 · 38 · 51 · 67 |
|
|
33
|
-
|
|
34
|
-
Use fluid `clamp()` so headings scale with the viewport instead of jumping at breakpoints:
|
|
35
|
-
|
|
36
|
-
```css
|
|
37
|
-
/* min, preferred (rem + vw), max — never snaps, never overflows */
|
|
38
|
-
.h1 { font-size: clamp(2.25rem, 1.5rem + 3vw, 3.75rem); line-height: 1.05; text-wrap: balance; }
|
|
39
|
-
.h2 { font-size: clamp(1.75rem, 1.25rem + 2vw, 2.5rem); line-height: 1.1; text-wrap: balance; }
|
|
40
|
-
.lead { font-size: clamp(1.125rem, 1rem + 0.5vw, 1.375rem); line-height: 1.5; }
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
Rules:
|
|
44
|
-
|
|
45
|
-
- **Line-height:** 1.5 for body, 1.05–1.15 for display. Tighter type wants tighter leading.
|
|
46
|
-
- **Measure:** keep body text at 45–75ch (`max-w-prose` ≈ 65ch). Long lines kill readability.
|
|
47
|
-
- **Pairing:** one display face + one text face, or a single superfamily with weight contrast. Never three+ families.
|
|
48
|
-
|
|
49
|
-
Self-host with `next/font` so there is no FOUT swap shift (a CLS source):
|
|
50
|
-
|
|
51
|
-
```tsx
|
|
52
|
-
// app/fonts.ts — next/font, self-hosted, no layout shift
|
|
53
|
-
import { Geist, Inter } from "next/font/google";
|
|
54
|
-
export const display = Geist({ subsets: ["latin"], variable: "--font-display", display: "swap" });
|
|
55
|
-
export const text = Inter({ subsets: ["latin"], variable: "--font-text", display: "swap" });
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
```tsx
|
|
59
|
-
// app/layout.tsx — apply the font variables on <html>
|
|
60
|
-
import { display, text } from "./fonts";
|
|
61
|
-
|
|
62
|
-
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
63
|
-
return (
|
|
64
|
-
<html lang="en" className={`${display.variable} ${text.variable}`}>
|
|
65
|
-
<body>{children}</body>
|
|
66
|
-
</html>
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
`next/font` auto-computes a size-adjusted fallback so the layout does not shift when the web font loads. Pair `display: "swap"` with that fallback to keep CLS at 0.
|
|
72
|
-
|
|
73
|
-
## Color theory (OKLCH)
|
|
74
|
-
|
|
75
|
-
OKLCH is the modern default: `oklch(L C H)` where **L** is perceptual lightness (0–1), **C** is chroma, **H** is hue (0–360). Unlike HSL, equal L steps look equally bright across hues, and OKLCH reaches the wider P3 gamut on capable displays.
|
|
76
|
-
|
|
77
|
-
Build a ramp by **holding hue and chroma, stepping L**:
|
|
78
|
-
|
|
79
|
-
```css
|
|
80
|
-
/* Brand ramp — hold hue 256 + chroma, step lightness */
|
|
81
|
-
@theme {
|
|
82
|
-
--color-brand-50: oklch(0.97 0.02 256);
|
|
83
|
-
--color-brand-100: oklch(0.93 0.05 256);
|
|
84
|
-
--color-brand-300: oklch(0.78 0.13 256);
|
|
85
|
-
--color-brand-500: oklch(0.62 0.19 256);
|
|
86
|
-
--color-brand-700: oklch(0.48 0.17 256);
|
|
87
|
-
--color-brand-900: oklch(0.32 0.10 256);
|
|
88
|
-
}
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
- **60-30-10 allocation:** ~60% background/neutral, ~30% foreground/structure, ~10% brand/accent. The brand color earns attention precisely because it is rare.
|
|
92
|
-
- **Semantic tokens** decouple meaning from value: `bg`, `fg`, `muted`, `brand`, `accent`, `destructive`. Components reference meaning, never raw hex.
|
|
93
|
-
- **Accessible contrast:** verify body text ≥ 4.5:1, large text / UI ≥ 3:1. Check with an APCA-aware contrast checker or browser DevTools (the Color Picker shows the live ratio). Do not eyeball it.
|
|
94
|
-
- **Dark mode via token swap,** not per-component overrides — swap the semantic values at the root and every component follows.
|
|
95
|
-
|
|
96
|
-
```css
|
|
97
|
-
:root { --color-bg: oklch(0.99 0 0); --color-fg: oklch(0.21 0.01 256); }
|
|
98
|
-
@media (prefers-color-scheme: dark) {
|
|
99
|
-
:root { --color-bg: oklch(0.17 0.01 256); --color-fg: oklch(0.96 0.01 256); }
|
|
100
|
-
}
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
Gradients and mesh are seasoning. A single subtle gradient on one surface (a CTA, a hero glow) can lift a page; the same gradient on every card flattens it into AI-slop. **Do not** gradient text, borders, and backgrounds simultaneously, and never make a gradient the value prop.
|
|
104
|
-
|
|
105
|
-
```css
|
|
106
|
-
/* Good — one restrained brand-tinted glow behind the hero, low chroma */
|
|
107
|
-
.hero-glow { background: radial-gradient(60% 50% at 50% 0%, oklch(0.62 0.19 256 / 0.15), transparent); }
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
## Grid & layout
|
|
111
|
-
|
|
112
|
-
- **12-column grid** for marketing pages; **container queries** (`@container`, core in Tailwind v4) for components that must adapt to their slot rather than the viewport.
|
|
113
|
-
- **Bento** is the 2026 standard for feature → benefit sections: an asymmetric grid with one focal cell that scans because the eye lands on the largest tile first, then sweeps the supporting cells.
|
|
114
|
-
- **Asymmetry / optical balance:** an off-center focal point with balanced negative space reads more intentional than a rigid symmetric grid.
|
|
115
|
-
- **Max-width + measure:** cap content at ~1024–1200px and body copy at ~65ch.
|
|
116
|
-
|
|
117
|
-
```html
|
|
118
|
-
<!-- Good — responsive bento: stacks on mobile, focal cell spans 2x2 on desktop -->
|
|
119
|
-
<section aria-label="Features" class="mx-auto grid max-w-5xl grid-cols-1 gap-4 p-6 md:grid-cols-3 md:grid-rows-2">
|
|
120
|
-
<article class="rounded-card border border-fg/10 bg-bg p-6 md:col-span-2 md:row-span-2">
|
|
121
|
-
<h3 class="text-2xl font-semibold">Preview every branch</h3>
|
|
122
|
-
<p class="mt-2 text-pretty text-fg/70">One command spins up an isolated environment.</p>
|
|
123
|
-
</article>
|
|
124
|
-
<article class="rounded-card border border-fg/10 bg-bg p-6">
|
|
125
|
-
<h3 class="font-semibold">No staging queue</h3>
|
|
126
|
-
</article>
|
|
127
|
-
<article class="rounded-card border border-fg/10 bg-bg p-6">
|
|
128
|
-
<h3 class="font-semibold">Auto-teardown</h3>
|
|
129
|
-
</article>
|
|
130
|
-
</section>
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
```html
|
|
134
|
-
<!-- Bad — symmetric 3-up of identical cards: nothing to anchor the scan -->
|
|
135
|
-
<section class="grid grid-cols-3 gap-4">
|
|
136
|
-
<div class="card">A</div><div class="card">B</div><div class="card">C</div>
|
|
137
|
-
</section>
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
## Depth
|
|
141
|
-
|
|
142
|
-
Depth is layered transparent shadow + hairline border + concentric radius — not one hard drop shadow.
|
|
143
|
-
|
|
144
|
-
```css
|
|
145
|
-
/* Layered transparent shadows read as real elevation across any background */
|
|
146
|
-
--shadow-card:
|
|
147
|
-
0 1px 2px oklch(0 0 0 / 0.06),
|
|
148
|
-
0 8px 24px oklch(0 0 0 / 0.08),
|
|
149
|
-
0 16px 48px oklch(0 0 0 / 0.06);
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
**Concentric radius:** `outer = inner + padding`. Worked number — an inner element with `border-radius: 8px` and `16px` of padding wants an outer `border-radius: 24px` so the corners stay parallel. Same-radius nesting (parent and child both `12px`) looks subtly wrong.
|
|
153
|
-
|
|
154
|
-
**Hairline borders before shadows.** Use a 1px `fg/10` border for separation; add shadow only when a surface genuinely floats (dropdown, popover, modal).
|
|
155
|
-
|
|
156
|
-
**Tasteful glass — floating surfaces only:**
|
|
157
|
-
|
|
158
|
-
```html
|
|
159
|
-
<div class="rounded-card border border-white/10 bg-white/5 shadow-card backdrop-blur-xl">
|
|
160
|
-
<!-- floating surface only — never the whole page -->
|
|
161
|
-
</div>
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
**Film grain / noise** via an inline SVG `data:` background adds texture without an image request:
|
|
165
|
-
|
|
166
|
-
```css
|
|
167
|
-
.grain {
|
|
168
|
-
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.04'/%3E%3C/svg%3E");
|
|
169
|
-
}
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
**When depth becomes slop:** glass on every card, a drop shadow on every element, or multiple competing elevations on one screen. Reserve depth for the few surfaces that genuinely sit above the page.
|
|
173
|
-
|
|
174
|
-
## Design tokens end-to-end
|
|
175
|
-
|
|
176
|
-
The canonical Tailwind v4 `@theme` block — colors, type, spacing, radius, shadow, easing — consumed as utilities (`bg-brand-500`, `rounded-card`) AND raw `var(--color-brand-500)`:
|
|
177
|
-
|
|
178
|
-
```css
|
|
179
|
-
@import "tailwindcss";
|
|
180
|
-
@theme {
|
|
181
|
-
/* color */
|
|
182
|
-
--color-bg: oklch(0.99 0 0);
|
|
183
|
-
--color-fg: oklch(0.21 0.01 256);
|
|
184
|
-
--color-muted: oklch(0.55 0.01 256);
|
|
185
|
-
--color-brand-500: oklch(0.62 0.19 256);
|
|
186
|
-
--color-brand-600: oklch(0.55 0.19 256);
|
|
187
|
-
--color-accent-500: oklch(0.78 0.13 256);
|
|
188
|
-
--color-destructive: oklch(0.58 0.22 27);
|
|
189
|
-
/* type */
|
|
190
|
-
--font-display: "Geist", ui-sans-serif, system-ui, sans-serif;
|
|
191
|
-
--font-text: "Inter", ui-sans-serif, system-ui, sans-serif;
|
|
192
|
-
--font-mono: "Geist Mono", ui-monospace, monospace;
|
|
193
|
-
/* radius + shadow */
|
|
194
|
-
--radius-card: 0.875rem;
|
|
195
|
-
--shadow-card: 0 1px 2px oklch(0 0 0 / 0.06), 0 8px 24px oklch(0 0 0 / 0.08);
|
|
196
|
-
/* easing — same values as references/motion-and-interaction.md; two definitions that drift
|
|
197
|
-
is worse than one, so change them together */
|
|
198
|
-
--ease-out: cubic-bezier(0.23, 1, 0.32, 1);
|
|
199
|
-
--ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
|
|
200
|
-
}
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
Mirror the source-of-truth tokens in a `tokens.json` so other tools (Flutter, icon pipelines, Figma sync) consume the same values:
|
|
204
|
-
|
|
205
|
-
```json
|
|
206
|
-
{
|
|
207
|
-
"color": {
|
|
208
|
-
"bg": "oklch(0.99 0 0)",
|
|
209
|
-
"fg": "oklch(0.21 0.01 256)",
|
|
210
|
-
"brand": "oklch(0.62 0.19 256)"
|
|
211
|
-
},
|
|
212
|
-
"radius": { "card": "0.875rem" }
|
|
213
|
-
}
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
Make the cross-platform parity concrete — the Flutter app uses the same brand hue. OKLCH is the source of truth; the sRGB hex is an **approximation** (Flutter's `Color` is sRGB-only, so the wider-gamut OKLCH value cannot round-trip exactly). Label it as such so no one treats the hex as canonical:
|
|
217
|
-
|
|
218
|
-
```dart
|
|
219
|
-
// lib/theme.dart — Flutter mirror of the brand token (Dart 3 / Flutter stable).
|
|
220
|
-
// 0xFF5B54FF is an sRGB APPROXIMATION (≈) of the canonical oklch(0.62 0.19 256);
|
|
221
|
-
// regenerate from the OKLCH source token, never hand-edit this hex.
|
|
222
|
-
final brand = const Color(0xFF5B54FF); // ≈ oklch(0.62 0.19 256)
|
|
223
|
-
final theme = ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: brand));
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
```html
|
|
227
|
-
<!-- Bad — magic hex, hand-tuned per component, drifts instantly -->
|
|
228
|
-
<button style="background:#5b54ff;border-radius:13px">Buy</button>
|
|
229
|
-
<!-- Good — semantic token utilities, single source of truth -->
|
|
230
|
-
<button class="bg-brand-500 rounded-card px-6 py-3 text-white">Buy</button>
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
## See Also
|
|
234
|
-
|
|
235
|
-
- `motion-and-interaction.md` — animate these tokens with intent.
|
|
236
|
-
- `landing-anatomy-and-cro.md` — apply the system across a full page.
|
|
237
|
-
- `../../flutter/SKILL.md` — implement the mirrored tokens in the Flutter app.
|