Getting started
Paradox Foundational Design System
The single source of truth for Paradox design values on the web (sirius):
colors, typography, spacing, radius, and the ds/ components. Every specimen on
this site renders from the code tokens themselves — what you see is what ships.
How truth flows
Values are defined once in Figma and travel one way. If two links of the chain disagree, the code token file wins — and the divergence belongs in the drift register.
PX-UI-SYSTEM v3.0 — where decisions are made.
40kJ4ZMhgzkSNpDMPyJsSmVariables leave design as data.
sirius/figma/302 --ds-* properties. When links disagree, this wins.
globals.cssWhat members actually touch.
src/components/ds/You're a human
Browse foundations and components; click any token name to copy it. Specimens are
live — the glass buttons run the real engine. Sections marked soon are still
migrating from preview.html.
You're an agent
Don't read this page, and don't parse its HTML. Two generated companions carry
the same facts, far lighter: ds-facts.ndjson (140 KB — one line per section
and per block, the answers) and ds-index.json (26 KB — the map and the read
contract). One grep answers a question:
grep -o '{"id":"ANCHOR".*' ds-facts.ndjson returns a single line with the
sirius file to edit, the Figma node ids, every rendered state with the exact JSX or CSS it
copies, every recipe a human can click as label/value pairs, the spec tables, the caption
prose verbatim, and the DRIFTs. Median 1.4 KB.
Both are embedded in this page too (script#ds-facts,
script#ds-index) so it stays self-sufficient when deployed — identical bytes,
the same grep works on index.html. Truth order: token values come from
sirius globals.css — this page renders them live, and if they disagree the CSS
wins; component APIs from the sirius file each line names; geometry and intent from the
Figma master; judgment from skills/px-design-bible/SKILL.md. Every divergence
is a DRIFT entry, never a silent fix.
Before claiming a change is done: node tools/verify.js. It fails if
a composite re-declares a primitive, if an icon was hand-written, if a copyable a human can
click is missing from the facts, or if any of the three copies drift apart — they are all
generated from this page. A clean console is part of the contract.
Reading this site
| Marker | Meaning |
|---|---|
| validated | Confirmed by Maxime — safe to build on. |
| hypothesis | Working hypothesis — follow it, flag doubts in the PR. |
| DRIFT-nnn | A documented Figma ↔ code divergence — expand it where it sits, or read the drift register. |
| error | A trap or breakage-level warning — read it before touching the area (e.g. the theming trap below). |
:root = light, .dark = dark) and the official DS
(:root = dark, .light = light). This site follows the DS
convention — dark is the default. Every color you touch must render under both themes.Foundations
Color code truth · 2026-07-20
One warm brand scale — PX Heat — over calm neutral grounds, plus functional
palettes. Warmth arrives in touches: heat is an accent system, never a background. Every
swatch renders live from the code tokens; click a name for var(), a hex to
copy it raw.
PX Heat — the brand scale
Seven steps, 0° → 600°. 150° is burgundy — THE accent: the primary brand moments, charts (via --ds-theme-chart-1…5, never raw heat), badge accents. The gaps in the scale (no 300/500) are the scale — never interpolate missing steps.
Functional palettes
neutral · green · amber · red, steps 50 → 950, plus the one-offs
--ds-color-black, --ds-color-white,
--ds-color-blue-pxs (PXS surfaces only — never a general-purpose
blue). Semantic tokens map onto these: reach for --ds-theme-* first, primitives
only when no intention fits — and flag it in the PR.
Opacity scales
The board defines six scales × 13 steps (8 → 96%), token pattern
{base}-{n}%. In code today only --ds-opacity-neutral-*
and --ds-opacity-accent-* exist, at 8/16/24/40/56/72. ⚠️ Steps
72–96 are all bound to the /64 variable in Figma — they render at 64% (marked *).
Alias variables
(opacity-*-lighter/light/main/dark/darker) exist on top of the step scales —
with inconsistent mappings across groups (exact values read from the
master, 2026-07-23): primary lighter = 10%
but accent/success/warning/destructive lighter = 16%;
light/main/dark = 24/32/40% everywhere; darker = 48%
on primary/accent but 56% on
success/warning/destructive. Pick one ladder (DRIFT-010).
Gradients
Four PX Heat directional ramps + the title text gradient — all Figma color styles, zero code tokens yet. Displayed large on purpose: a 7-stop ramp is unreadable as a thumbnail. Click a ramp to copy its full CSS. Seven more library gradients (Navbar/blur/backdrop) live in the parent master file — fileKey still needed.
Gradients/Other/Text/foreground-title — neutral-50 → neutral-400, for ground titles. Click to copy the clip recipe.
Usage
Foundations
Typography Text board · validated
Two families with a hard pairing rule, one scale from 10 to 128px. Anton is not part of the system: it's a content-only brand asset (thumbnails, video) and never touches product, web or digital surfaces — its former code usages now render Clash (see DRIFT-022). The scale below renders from the live tokens — click a row to copy its size + line-height pair.
Two families
Design that lands
Clash Grotesk — headings, ≥ LG (18px). --ds-font-accent
One idea per sentence, like Athéna talks.
DM Sans — body and UI, ≤ Base (16px). --ds-font-default
The scale
Traps
text-base
renders 18px while text-ds-base renders 16px. Always use the
ds scale — never the bare Tailwind text utilities.Foundations
Spacing 4px scale
A 4px-based scale with half-steps at the low end, plus the non-Tailwind
steps 18 (72px) and
22 (88px). Click a token for
var(), a value for raw px.
Foundations
Radius & borders validated · 2026-07-20
Ten radius steps, four border widths, six breakpoints — and a per-component radius mapping that is spec, not taste.
Radius
Per-component mapping (ISO-verified): buttons 8px at every size · fields 8/8/6 (sm) · checkboxes 4/6 · message textarea 16 · full is a mobile pattern — no pills on web. Details live in Button § Anatomy.
| Role | Step | Token |
|---|---|---|
| Buttons · fields | 8 | --ds-radius-md |
| Message bubbles | 12 | --ds-radius-lg |
| Inner cards | 16 | --ds-radius-xl |
| Containers | 20 | --ds-radius-2xl |
| Pills · badges · toggles | full | --ds-radius-full |
rounded-3xl is 20px =
this scale's 2xl): map by value, never by name — see the drift register.Borders
| Token | Width |
|---|---|
| --ds-border-xs | 1px |
| --ds-border-sm | 2px |
| --ds-border-md | 4px |
| --ds-border-lg | 8px |
Breakpoints
| Name | Value |
|---|---|
| mobile | 360px |
| tablet | 768px |
| desktop-sm | 1024px |
| desktop | 1280px |
| desktop-lg | 1440px |
| desktop-xl | 1600px |
Foundations
Variables Mode collection · dark ⇄ light
The semantic layer exactly as Figma defines it: the Mode
collection aliases Fondations tokens per theme — Dark is the default, Light remaps every
alias. This is what agents and devs consume as --ds-theme-*. Both swatches
below resolve live from the code tokens; click a code token to copy its
var(). Groups flagged ❌ unused in Figma (33 + 2 typography) are deliberately
not imported, per governance.
--ds-theme-*), never raw neutrals: it must survive
both columns of this table. ② Stage-locked specimens — component boards are
specified on dark; their stages stay dark in both modes, on purpose. ③ Theme-agnostic
data (alpha scales, code blocks) carries its own explicit backdrop. Before shipping
anything new: toggle both modes and run the overflow audit at three breakpoints
(REX checklist).Not shown here: opacity
scales and their aliases live in Color §
Opacity; typography size lives in
Typography § Scale; the custom
group (8 variables) is not inventoried yet 🚧. Three Mode variables have no code token
(DRIFT-023): popover foreground-paragraph, success-bg-transparent,
warning-bg-transparent.
Primitives
Button validated · 2026-07-20
Buttons carry the actions of forms, dialogs, and screens. The web family is a rounded rectangle — 8px radius at every size — with a state system driven by opacity, not by color swaps. Eight variants, no more: there is no outline, no link, and no burgundy button. (Glass taxonomy reworked by Maxime, 2026-07-22: glass renamed glass dark, glass light and glass destructive introduced.)
Variants — the eight families
| Variant | Use for | Surface |
|---|---|---|
| primary | The one principal action of a view or dialog | neutral-50 on dark · shadow |
| secondary | Supporting actions next to a primary | neutral-900 · 8% border · shadow |
| glass dark | Actions floating over imagery — dark context | engine Dark Glass preset (brightness −0.3, blur .25) |
| glass light | Actions over imagery — light emphasis | brightness +0.3 · neutral 10% tint layer |
| glass destructive | Destructive actions over imagery | brightness +0.3 · red 16% tint layer · red label |
| ghost | Tertiary, low-emphasis actions | transparent · 8% white on interaction |
| destructive | Irreversible actions | red-600 · shadow |
| ghost destructive | Low-emphasis destructive (e.g. remove row) | transparent · red-600 text |
Anatomy — sizes & content slots
Every button (not icon buttons) can carry a left icon, a right icon, a
badge, or a combo — hidden by default behind the Figma properties Left Icon /
Right Icon / Show Badge, so they're easy to miss. Slots exist on
every variant and every state; geometry is state-invariant (verified on the
master — states only modulate opacity). Icons are Lucide, 16px at every size; the badge is
the “Glass Badge”: dark 56% pill (opacity/neutral-inverted/56), padding 8/2,
radius full, XS 12/16 Medium uppercase, white.
| Size | Height | Padding × | Label | Slot gap | Icon | Radius |
|---|---|---|---|---|---|---|
| xs | 24px | 10px | DM Sans Medium 12/16 | 6px | 16px | 8px |
| sm | 32px | 12px | DM Sans Medium 14/20 | 6px | 16px | 8px |
| md | 36px | 12px | DM Sans Medium 14/20 | 8px | 16px | 8px |
| lg | 40px | 12px | DM Sans Medium 14/20 | 8px | 16px | 8px |
States — an opacity system
States don't swap colors; they modulate the whole button's opacity. Ghost variants add an interaction background on top.
| State | Opacity | Additions |
|---|---|---|
| enabled | .88 | — |
| hover | .80 | ghost: bg white 8% · ghost destructive: bg red 10% |
| active | 1.00 | ghost interaction bg persists |
| focus | 1.00 | 3px ring, white 24% — red 24% on destructive family |
| disabled | .48 | shadow removed |
Glass — the liquid material
Glass exists for actions that float over imagery — the material is the point, and it only reads on a complex surface. Three variants (master's Buttons board, 2026-07-22): glass dark = the “Dark Glass” example of @ybouane/liquidglass, verbatim, radius adapted to 8; glass light = same with brightness +0.3 and a neutral 10% tint layer; glass destructive = light with the destructive-red 16% tint and label. Each variant runs through its five states below, over the WIP artboard’s photo (Paradox App, node 8209:117190). In Figma the variants carry effect style Glass/sm; without WebGL they fall back to the flat recipes below.
Material controls — tune the engine (drives every glass specimen live)
The engine's own parameters, identical to the reference playground at liquid-glass.ybouane.com. Brightness is not a slider: it's fixed per variant (−0.3 dark · +0.3 light & destructive). Tune, compare, then “Copy recipe” — or reset.
Engine recipe — the implementable spec
This block exists because glass is the one variant with zero code
expression in sirius (no token, no component — DRIFT-006): until
ds/ grows a glass primitive, this config IS the handoff. The other
variants don't need it — their values already live in globals.css as
semantic tokens (table above).
/* glass dark — the official "Dark Glass" example, verbatim
(only cornerRadius adapted: 50 → 8, radius-rounded-field) */
element.dataset.config = JSON.stringify({
brightness: -0.3,
blurAmount: 0.25,
cornerRadius: 8
});
/* glass light — brightness flips to +0.3, plus a tint layer under the
label: opacity/primary/lighter = rgba(250,250,250,0.10) */
/* glass destructive — light, with tint and label in destructive red:
opacity/destructive/16% = color-mix(red-600 16%, transparent) · label red-600 */
/* flat fallbacks (no WebGL):
dark → radial-gradient(296.68% 50% at 50.25% 50%, white 0→4%)
+ rgba(23,23,23,.64) + blur(4px)
light → rgba(250,250,250,.10) + blur(4px)
destr → red-600 @ 16% + blur(4px) · label red-600
all → radius 8 · opacity .88 enabled */
Action group
The master's composition pattern for a set of actions: tertiary (ghost) + secondary + principal, optionally paired with 40px secondary icon buttons. The group is modular — 2 or 3 text actions (always exactly one principal), plus 0, 1 or 2 icon buttons. Click a combo to preview it:
Implementation — semantic tokens
The actionable group of the semantic layer backs buttons and
inputs. Reach for these before any primitive — a semantic token is an intention. Values below
resolve live; toggle the theme to see both renditions.
| Token | Resolves to (current theme) | Role |
|---|---|---|
| --ds-theme-actionable-bg-primary | | Primary button surface |
| --ds-theme-actionable-fg-primary | | Primary button label |
| --ds-theme-actionable-bg-secondary | | Secondary button surface |
| --ds-theme-actionable-fg-secondary | | Secondary button label |
| --ds-theme-actionable-fg-tertiary | | Tertiary / meta text |
| --ds-theme-actionable-fg-disabled | | Disabled label |
| --ds-theme-actionable-muted-bg | | Muted control surface |
| --ds-theme-actionable-muted-fg | | Muted foreground — see DRIFT-012 |
| --ds-theme-actionable-input | | Input borders |
| --ds-theme-actionable-ring | | Focus ring |
foundations/mobile.md until the mobile reference exists.Primitives
Icon Button validated · 2026-07-20
The compact sibling of Button: a square carrying a single Lucide glyph. Same eight families, same opacity state system, same 8px radius — squares 24/32/36/40 with a 16px glyph (20px on lg). One nuance of its own: ghost focus is a 2px border, not a shadow ring.
Variants — the eight families
Identical taxonomy, identical use cases — see the Button variants table. One square per family.
Anatomy — sizes
| Size | Square | Glyph | Padding | Radius |
|---|---|---|---|---|
| xs | 24px | 16px | 4px | 8px |
| sm | 32px | 16px | 8px | 8px |
| md | 36px | 16px | 10px | 8px |
| lg | 40px | 20px | 10px | 8px |
States — the same opacity system
Same scale as Button — enabled .88 · hover .80 · active 1 · focus 1 + ring · disabled .48 — with one nuance of its own: ghost focus is a 2px border (--ds-color-neutral-500), not a shadow ring.
Glass — the liquid material
The same three materials as Button — the spec, the playground and the engine recipe live in Button § Glass. Judged over the same artboard photo:
Implementation
src/components/ds/common/IconButton.tsx — same semantic
actionable tokens as Button (table
here). API: Icon (a Lucide component), variant,
size, href. Click any specimen above for ready JSX. Glass
variants staged on the sirius branch design/glass-button-variants.
Primitives
Badge Badge.tsx · 1:1
Badges inform on the status of a piece of data. Seven variants — including the burgundy accent and the px-heat glow, which live here and NOT in buttons — four sizes, two states (default / hover at 80%). Backgrounds are 56% transparent theme mixes with the Glass frost. Click any badge for its JSX.
| Size | Padding | Label | Case | Radius |
|---|---|---|---|---|
| xs | 2 / 8 | 10/14 Medium | regular | full |
| sm | 2 / 8 | 12/16 Medium | uppercase | full |
| md | 4 / 10 | 12/16 Medium | uppercase | full |
| lg | 6 / 12 | 12/16 Medium | uppercase | full |
Liquid glass — over imagery
Badges are Glass Badges: over imagery they carry the exact same liquid material as the glass buttons — engine refraction under their 56% tint layer, pill-radius lens. px-heat is the exception (glow, no glass). Same engine, same playground parameters as Button § Glass.
Optional slots (Figma props, all 12px): dot · left icon · avatar · closable ×. The px-heat glow recipe: px-heat inset glow — click to copy.
Primitives
Tag no ds/ · DRIFT-007
Versatile labels for categorization, filtering and metadata. Five color variants × three types (fill, dash, emphasis) × three sizes — square-ish radii, unlike the Badge's pill. Closest existing code (pxlab Tag.tsx, shadcn ui/badge.tsx) matches neither: this page is the spec.
Status indicator
A 14px dot embedded in tags or labels to reflect a page/update/action status — 2px ground-colored ring, 24% tinted fill, 8px glyph.
Primitives
Selection controls no ds/ · DRIFT-007
Four controls across three master boards: Checkbox (square, plus
an indeterminate shape), Circle checkbox (the task checkbox — it adds a
started state), Radio and Toggle. Two sizes each, the
same opacity state system as Buttons — and selection is signalled by the PX Glow
(radio dot, Heat checkbox, selected Radio item), never by a flat accent fill. ds/ components
are staged on the sirius branch design/selection-controls — Checkbox, Radio,
Toggle, ModeSwitch (tsc-clean, pending team review); the option card already exists as
RadioOptionCard.
Checkbox
Two Figma components: _Checkbox base (the atomic box) and Checkbox
(base + label + description). Two themes: White — near-white fill when checked — and
PX Heat — checked lights the glow. The glyphs are the official Lucide check
and minus, dead-centered, at a rendered 1.5px stroke.
Circle checkbox — the task checkbox
Same anatomy as Checkbox at radius-full, plus one property the square
box doesn't have: isStarted. A started task drops the box entirely and shows the bare
Lucide loader glyph — the full lifecycle reads left to right below.
loader 20px neutral-400, no box, no border — the board is static, the spin is ours · all five interaction states of the square apply to every stepRadio
One board, one theme — because the checked signal is the PX Glow: a 3px-padded neutral-950 disc lit from inside by the 4-layer heat glow. No white dot anywhere.
Toggle
Track sm 36×20 / md 44×24 at radius full with a 2px inset; knob
neutral-50 with
Shadow-dark/xs. OFF = neutral-900 track, no border. ON comes in two
variants — px glow (dark track lit by the heat glow, the default) and
neutral (neutral-200 light track). They replace the board's neutral-100 recipe,
whose knob-on-track contrast was one neutral step (decision Maxime, 2026-07-24).
moon/sun 16 · staged as ds/ModeSwitchImplementation
| Control | Geometry | Selected signal | Copy the recipe |
|---|---|---|---|
| checkbox | 16 r4 / 20 r6 · icon 12/14 | neutral-50 fill, neutral-950 Lucide check | box md |
| checkbox · px heat | same box | accent 56% veil + heat glow, check neutral-50 | heat checked |
| circle checkbox | 16 / 20 · radius full | + started: bare Lucide loader neutral-400 | circle md |
| radio | 16 / 20 · radius full · p 3 | neutral-950 disc + PX Glow (no white dot) | radio md |
| toggle | 36×20 / 44×24 · p 2 · knob 16/20 | track neutral-100 + black-8% border, knob right | toggle md |
ds/ JSX — <Checkbox>,
<Radio>, <Toggle>, <ModeSwitch>
(branch design/selection-controls) and <RadioOptionCard>
(already in ds/). Token-level recipes stay one click away on the highlighted
values in every caption and in the table above.check, minus, loader,
redo, moon, sun) at a rendered 1.5px stroke —
stroke-width = 1.5 × 24 / size on a 24 viewBox.font/family/content token (named "Inter"), while sm labels and every description
bind Paradox/SM text styles (DM Sans). The web renders both as DM Sans — the master's md
binding should be re-pointed at a Paradox style.Primitives
Text input partial ds/ coverage
Five field types (default, leading dropdown, trailing dropdown, leading text, payment) × three sizes × six states (placeholder, filled, focus, destructive, success, disabled) — plus three textarea variants (text, tag, message) with their own state set, and two web-designed extensions (search, password — DRIFT-029). Heights 48/40/32, radius 8/8/6 (sm drops one step). Click a field for its JSX (default type) or its CSS recipe — and try the live one.
Five types
search lens with a trailing clear ×, and a masked value with the eye toggle — no new geometry, no new colorsStates — with label & hint
<input> wearing the exact lg recipe · focus = ring #737373 + 3px halo via :focus-within| Size | Height | Padding | Type | Radius |
|---|---|---|---|---|
| lg | 48px | 12 | Base 16/24 | 8px |
| md | 40px | 8 / 10 | SM 14/20 | 8px |
| sm | 32px | 8 | SM 14/20 | 6px |
Textarea — three variants
<IconButton shape="circle"> (default stays square)
on design/selection-controls. Nothing else may use it without a decision.⚠️ Board inconsistency (flagged): textarea border is white 8%
where inputs use 16% —
part of DRIFT-010. The dropdown/leading/payment types and every textarea variant have no
ds/ component (DRIFT-007).
Primitives
Progress no ds/ · DRIFT-007
Task progress or passing time. Two variants — Primary (white
fill) and PX Heat (the 270° heat ramp) — four track heights, radius full.
The Slider derives from this recipe. shadcn's
ui/progress.tsx does not implement this spec.
Primitives
Slider derived · no board
Born on the web (Maxime, 2026-07-23): the Progress bar anatomy — radius-full
track + fill — plus a handle, in two fill variants (decision 2026-07-24, the same
pair as Toggle ON): px glow, the official PX Heat ramp compressed into the fill, and
neutral, a neutral-50 fill on a 16% track. Same four sizes as Progress. No Figma board yet
(DRIFT-021) — the ds/Slider component is staged on the sirius branch
design/selection-controls; click a size label to copy its JSX.
| Size | Track | Thumb | Fill (px glow / neutral) | Track color |
|---|---|---|---|---|
| sm | 4px | 12px 🚧 | heat ramp / neutral-50 | neutral 16% |
| md | 6px | 14px 🚧 | heat ramp / neutral-50 | neutral 16% |
| lg | 8px | 18px 🚧 | heat ramp / neutral-50 | neutral 16% |
| xl | 12px | 22px 🚧 | heat ramp / neutral-50 | neutral 16% |
Primitives
Rich text code off-spec · DRIFT-008
How every element of an article renders — the full stack from the master's
Text component board: title label, H1 (default + visual block), H2, H3, body, lists, quote,
small, inline code and code paragraphs, picture and video with legends, and three spacers.
Quote/code use JetBrains Mono italic — official as an ultra-rare
option strictly for code / transcript-style content (decision 2026-07-24, token
--ds-font-mono
to add). The off-spec flag is about the
code: ui/markdown.tsx still renders teal h3s and a gray-* palette — this
board is its restyle spec.
À propos de cette Loop
Ceci est un titre H1
Étape 1 sur 4
Ceci est un titre H1 (visual block)
Ceci est un titre H2
Ceci est un titre H3
Un paradoxe est une affirmation qui semble se contredire, mais qui peut néanmoins être vraie. C'est une idée qui défie la logique et le bon sens, et qui nous oblige à remettre en question nos hypothèses et nos croyances.
- Apprendre les contradictions.
- Les paradoxes temporels.
- Réussir à jongler l'impossible.
- Navigue dans les complexités du paradoxe avec assurance.
- Découvre comment les paradoxes stimulent la pensée créative.
Ton chemin vers la liberté financière commence ici.
Par exemple, après qu'il ait dit : "ça me tue intérieurement" tu aurais pu dire : "ça me tue intérieurement"
Par exemple, après qu'il ait dit : "ça me tue intérieurement" tu aurais pu dire : "ça me tue intérieurement"
Un lien vers la méthode complète au fil du texte, du gras qui passe en Medium titre et de l'italique simple.
| Principe | Effet |
|---|---|
| Clarté d'esprit | Moins de bruit, plus de décisions nettes |
| Paradoxe assumé | Deux vérités peuvent coexister |
- Écrire la première itération.
- Confronter la version à un vrai lecteur.
| Element | Style | Spacing above |
|---|---|---|
| Title label | XS SemiBold uppercase · neutral-400 · 16% rule | section start |
| H1 | Clash Medium 24/32 | 28px |
| H2 | Clash Medium 20/28 | 24px (16 after H1) |
| H3 | Clash Medium 18/28 | 20px (12 after H2) |
| body · lists | DM Sans 14/20 | 12px (8 after H3) |
| quote | burgundy 10% · border 56% · r6 | 16px |
| code chip | mono italic 12/16 · #dbbdc8 · burgundy 10% · r2 | inline |
| small | DM Sans 12/16 · neutral-200 | 8px |
| picture / video | radius 16 · black-8% border · Shadow-dark/sm · legend XS pl 8 | 24px |
| spacers | S 12 · M 24 · L 56 | — |
Primitives
Icons Lucide
The icon system is Lucide — the full official library, vendored
(… icons): 24px grid, stroke 2, round caps. The Figma board
mirrors this set; when an icon is missing there, it exists here first. Sizes in use: 16px in
buttons and inputs (20px in lg icon buttons), 12px in badges and tags. Click any icon to copy
its lucide-react import.
Composites
Composites 6 of 11 · growing
The system has two levels. Primitives — every section above:
the smallest possible controls (a button, a checkbox, a tag). Composites —
this section: reusable blocks assembled from primitives (option cards, designed
cards, repeatable UI chunks). A composite never restyles a primitive: it only arranges
them — badges are the DS Badge (and copy as one), the CTA is the DS Button, the bar is DS
Progress, markers are the DS Checkbox and Radio, every icon is resolved from the vendored
Lucide set at runtime, and every string names a documented text style
(text-ds-*, the same utility names as sirius). node
tools/audit-composites.js fails the build if any of that slips.
New designed cards and blocks land here as they are extracted from the two Cards boards. Inventory and order: Course cards ✓ · Action cards ✓ · PX Agent ✓ · Tutorial + Identity ✓ · Loop cards ✓ (Large / Compact / Minimal / block + mobile card / compact mobile / Date / block + Indicator + Line) · Radio item ✓ · next: Event card, One thing cards (big / card / edit / timer), Streak (indicator + card), Athena tools, Long bloc card — plus the remaining mobile variants of the imagery families (Course started, Action, Community, Event).
Course cards
The catalog's flagship (boards ✅ Desktop cards + ✅ Mobile cards,
code ds/cards/CourseCard.tsx). Anatomy: full-bleed visual under a
24% veil, glass badges top-right, and a Details panel sitting on a progressive
scrim — gradient 0% → 56% at 41.35% → 96% with an 8px backdrop blur. Hover lifts the
shadow to Shadow-dark/lg, clears the veil and reveals the CTA.
MentalFocusEmpowered
MentalFocusEmpowered
MentalFocusNouveauEmpowered
MentalFocusEmpowered
FinanceSignaturePsychologie de l’argent
Reprends la main sur tes finances personnelles. De la psychologie à l’investissement, tu es guidé à chaque étape par notre méthode, nos IA, nos partenaires et des outils conçus pour passer à l’action. Pas juste comprendre.
clock + video 16, XS-Uppercase Medium neutral-200) with the Nouveau chip ·
description Base/24 clamped + inline CTA ·88 · same started / inactive deltas as the standard card
FinanceSignatureNouveauPsychologie de l’argent
Action cards
Entry points to a practice — three types from the board (code
ds/cards/ActionCard.tsx + CommunityCard.tsx). Tool: the visual
blends into black (mix-blend-overlay) so any artwork reads on-brand. Loop:
a flat card surface, no imagery — a live session slot with its capacity and schedule.
Community: the Tool treatment carrying the PXL wordmark.
OutilNouveauPratique (Loop IA)
Un espace pour créer ou rejoindre un groupe de travail collectif et progresser entre pairs.
CommunautéParadox LearningCommunauté PXL
Un espace pour échanger, progresser et partager autour des parcours, outils et pratiques de l’app.
arrow-up-right 24 next to the titleProtocole - Tes premières expériences avec l’argent.
Participants : Laurence Gilles
calendar 16 XS-Uppercase neutral-200 · title wraps (XL), participants SM one line ·
the Loop type and its capacity/meta slots are missing from ActionCard.tsx (DRIFT-034)PX Agent cards
One card per agent of the PX roster — the Course card language at
292×272 with the agent's portrait. The default state is just the name; hover reveals
the agent's promise and the CTA without lifting the shadow (the portrait
stays the hero). No ds/ component yet (DRIFT-007).
RevenusAgentMartin
Il identifie les leviers les plus efficaces pour générer rapidement plus de revenus à partir de vos compétences actuelles.
RevenusAgentMartin
Il identifie les leviers les plus efficaces pour générer rapidement plus de revenus à partir de vos compétences actuelles.
RevenusAgentMartin
Tutorial + Identity
The two composites that carry primitives instead of imagery
(code ds/cards/TutorialCard.tsx + IdentityCard.tsx, both created
for this pass with the ds/common/Progress.tsx they needed — see DRIFT-007).
Same shell as the imagery families — r20, border white 16%, Shadow-dark/lg — on the
ground surface. Tutorial is the onboarding checklist: header, Progress, and a step list
masked at both ends. Identity splits one card into two columns: the stats
side (archetype, streak strip, counters) and the orb side (Paradox Score).
Prise en main
Complétée à28%- Démarrer un cours signature
- Participer à une session Loop
- Terminer un micro-cours
- Rejoindre la communauté Circle
- Discuter avec un Agent
Identité Paradox
Tu as une lecture lucide et organisée de l’argent. Tes décisions tracent une trajectoire claire vers tes objectifs.
arrow-right / share-2 /
download / info 16), all at the board's rest opacity 88
two open points: the Low bars' semantics (decay, or a partial week?) and the orb artwork, authored for the dark surface — there is no light rendition of it yet 🚧- Terminer un micro-cours
- Démarrer un cours signature
- Participer à une session Loop
- Terminer un micro-cours
- Rejoindre la communauté Circle
- Discuter avec un Agent
Prise en main
Complétée à28%- Terminer un micro-cours
- Participer à une session Loop
- Terminer un micro-cours
- Rejoindre la communauté Circle
- Discuter avec un Agent
chevron-down / chevron-up
(the whole row is the toggle — a bare 24px chevron is too small a target) ·
every mobile row is tighter — done py8 · pending py4, against 10/12 on desktop ·
closed: no list, just a PROCHAINE ACTION
eyebrow and the next pending step, its label the only one stepped down to SM/Medium 14/20 ·
open: the full list back at 16/24, capped at 184px behind the same bottom fade — the first done
step scrolls out of view firstLoop cards
The scheduling family — the one family that already had code, and
not in ds/: components/(loop)/loops/LoopCardDesktop.tsx renders
the Large and Compact renditions (compact) with the timeline
(showTimeline), LoopMinimalCard.tsx the minimal one. The board splits it
into four pieces: the Line connector, the Indicator (capacity), the Date
separator and the card itself. Values below are the board's; a value-by-value audit of the
existing implementation is still pending (DRIFT-037).
Loop Large
09h00 - 10h15Dans 33 min2 places restantesEmpowered - Décupler sa confiance en soi


09h00 - 10h15Dans 33 min1 place restanteEmpowered - Décupler sa confiance en soi


09h00 - 10h15Dans 33 minCompletEmpowered - Décupler sa confiance en soi


09h00 - 10h15Dans 33 minCompletEmpowered - Décupler sa confiance en soi


Loop Compact
Empowered - Décupler sa confiance en soi


Empowered - Décupler sa confiance en soi


Empowered - Décupler sa confiance en soi


Empowered - Décupler sa confiance en soi


LoopCardDesktop with
compact · the one card in the system with no chrome at all: no surface, no border,
no shadow, no cover — a row in a list rather than a card ·
three rails: the hour (104, pt6, time then countdown stacked),
the details (flex, gap 12) and the actions (128, pt4, right-aligned) ·
the title steps down to LG 18/28
(against XL on the Large card) and the CTA to Button sm (py6, against md) ·
participants and Indicator share one row here instead of stacking ·
same state rule as the Large card: only plain full dims (48% / CTA 88%), full + participate keeps full contrastLoop Minimal
(Suite Live) Protocole - Tes premières expériences avec l’argent. Apprendre à mettre en place une épargne de sécurité sans y penser.


(Suite Live) Protocole - Tes premières expériences avec l’argent. Apprendre à mettre en place une épargne de sécurité sans y penser.


(Suite Live) Protocole - Tes premières expériences avec l’argent. Apprendre à mettre en place une épargne de sécurité sans y penser.


LoopMinimalCard.tsx · the only Loop rendition with interaction states, and the only one
at radius 8 with a
white-8% border ·
enabled: ground surface + Shadow-dark/md · hover: the surface steps up to
block, shadow unchanged ·
focus: block surface + the standard 3px white-24% ring, and the shadow drops ·
hour rail 104 with the day in neutral-50 over the slot in neutral-400 —
the reverse emphasis of the Compact rail · the title is the one Loop title in DM Sans
(SM SemiBold 14/20, not Clash), one line ellipsised ·
no names and no Indicator here: just the avatars and the categories, the category row fading out at 88%
the board pins the avatar rings to the ground colour, so they stay dark on the hover surface — the site follows the card’s own surface insteadBlock — a day of sessions
09h00 - 10h15Dans 33 min2 places restantesEmpowered - Décupler sa confiance en soi


09h00 - 10h15Dans 33 min2 places restantesEmpowered - Décupler sa confiance en soi


LoopCardContainer.tsx + LoopCardDesktop with showTimeline) ·
the connector runs down the left at 8px, then gap 16,
then the container reserves 16px under the card —
which is what keeps the dashed line visible between two sessions ·
the Date Large separator opens the day, its dot sitting on the same 8px rail so the whole column
reads as one timeline · the board's block symbol uses the connector's default state;
start and end are what you swap in at a day's first and last positionsEmpowered - Décupler sa confiance en soi


Empowered - Décupler sa confiance en soi


Mobile renditions
Empowered - Décupler sa confiance en soi
09h00 - 10h152 places restantes

Empowered - Décupler sa confiance en soi
09h00 - 10h152 places restantes

Empowered - Décupler sa confiance en soi
09h00 - 10h15Complet

Empowered - Décupler sa confiance en soi
09h00 - 10h15Complet

Empowered - Décupler sa confiance en soi
09h00 - 10h152 places restantes

Empowered - Décupler sa confiance en soi
09h00 - 10h152 places restantes









Indicator · Date · Line
Radio item — option card
From the Radio board: a 520px option card — featured icon, title + description, optional Glass Badge, radio top-right. Two states (default / selected) × two layouts (simple / with an inline input for the "custom answer" case). Selecting it relights the whole card.
redo 20) · title 16/24 Medium · description 14/20 neutral-400 · optional Glass Badge slot next to the title (white 16% pill · XS Medium uppercase) · the with input layout adds a 1px divider and an inline field (40×40, border white 16%, radius 8) indented 56px under the title · board copy kept verbatimImplementation
What every card in this section shares, and what to reach for when building the next one.
0 0 19px 19px and the card
isolates, because Chromium lets a
backdrop-filter escape a rounded clip. States: the Buttons opacity system —
inactive/full ·48, pressed and rest-CTA ·88, focus/pressed
3px ring white 24%.
Participants: 20px avatars overlapping by 7.5, each ringed 1.25px in the card's own
surface, the last seat being the agent
(PX Heat ramp Low
+ the monogram).<Badge> and copy as one on click; the CTA is <Button>;
the bar is <Progress>; markers are <Checkbox> /
<Radio>; the capacity dot is the shared .pxdot (not the
14px ringed StatusIndicator); every glyph resolves from vendor/lucide.min.js
at runtime through an icon slot
(
.pxi[data-icon]) at a rendered 1.5px stroke —
stroke-width = 1.5 × 24 / size; and every string names a documented text style
(
text-ds-*, the same utility names as sirius). Three values legitimately
escape the scale and say so in the CSS (board-override): the Paradox Score's
32px line, its label's −0.56 tracking, and the PXL wordmark's artwork lettering.
node tools/audit-composites.js fails on any drift from this.Registers
Exemplars canon · validated 2026-07-28
Screen-level canon: the reference screens to imitate when you build a screen.
Components are specced above; this register answers the next question up — how screens are
composed. Source: Maxime's Figma frames (file uZfZ4lr4eJeDb4q5KeWDiz),
41 screens extracted and measured. Imitate the logic (hierarchy, rhythm, density,
tone), never the pixels. The measured facts per screen — annotations verbatim, every value
mapped to its token, layout, type, density — live one file per screen in
exemplars/analysis/ — e.g. exemplars/analysis/home-desktop-large.md
with its export in exemplars/captures/, same slug on both sides. Read the analysis
file to build; look at the capture to compare.
What an exemplar teaches: layout, hierarchy, spacing rhythm, density, composition, focal point, accent discipline, responsive strategy. What it does not: interactive states, motion, copy — those stay with the hard rules and the sections above.
The responsive doctrine, seen on one screen
Home at six widths — the visual proof of Bible hard rule 8. From 1280 up the content column is capped and the margins absorb the extra width; at 1024 and below the cards keep their pixel size and the rows become peeking carousels. Responsiveness is how much of the next card shows, never a resize.






The five exemplars

E1 — Home
- Why it's canon
- The member dashboard reference: mixed card families (course, action, tutorial, event, identity) stacked in labelled sections, each a Ground Header over a horizontal card row. Uniform 20px radius across ~20 card instances of five types. The Paradox Score / streak block is the single focal point.
- Figma constraint → rule
- The tablet frame zeroes the course section and pastes an overlay carousel; desktop-small uses override frames with mask-cropped cards. Same intent both times: at ≤1024px card rows become peeking horizontal carousels at fixed card size. One carousel component for the whole compact family — never per-screen overlays, never a reflow that shrinks cards.
- Also inside
- The richest annotations of the corpus (19 verbatim) — the scroll-linked card animation spec and the streak-chart opacity rules, the only written motion intent we have. The mobile Identity/stats block is annotated 🚧 WIP, do not integrate; the logo 🚧 Wrong logo.
analysis/home-{desktop-large,desktop-xl,desktop,desktop-small,tablet,mobile}.md

E2 — Catalog
- Why it's canon
- Browsing density and section rhythm. Course cards are a fixed size (244×344 standard, 624×344 featured) — wider screens add margin, never columns. Section vertical rhythm is a constant 488px step (440 section + 48 gap), holding through the 11-section multi-topic frame. Exactly one accent badge per visible card, never more, never a fill.
- Figma constraint → rule
- Tablet instances the mobile component at 768px, and every instance is internally named "@ Desktop large" whatever its width. Read as: tablet belongs to the compact family and follows the mobile composition — there is no third tablet grid to build. The naming carries no design meaning.
- Also inside
- Empty states exist but are annotated 🚧 EMPTY STATE ILLUSTRATION MISSING — the intent is there, the illustrations aren't. Hover, search and filters-open variants are captured.
analysis/catalog-*.md · 7 files incl. the multi-topic frame

E3 — Course detail
- Why it's canon
- A long content page with a sidebar. Desktop runs a genuine two-column split (modules flex-1 ≈848px + fixed 392px progress sidebar, 40px gap) that stacks full-width on mobile. Spacing is 100% on the DS scale with zero drift — the cleanest screen of the corpus on that axis. Title and description each drop one type tier from desktop to mobile; body copy stays 16px.
- Figma constraint → rule
- On mobile the hero title/meta block exists twice (one live over the image, one hidden below) — the hidden copy is the component's default content, kept rather than detached. Read as: on mobile the hero title overlays the image, exactly one title in the DOM. Render the overlay, drop the duplicate.
analysis/course-detail-{desktop-large,mobile}.md

E4 — Loop
- Why it's canon
- The broadest reference of the corpus — list shells, overlays, modals, chat and a long report page in one coherent family. Fixes the desktop list shell (Ground Header 64, pagination 64, footer 224) and the overlay vocabulary: 528px side panel, 480px modal, both over a 72%-black + 2px-blur scrim. Accent discipline at its strictest — burgundy is absent from three of four desktop screens and, on chat, marks only the member's own bubbles.
- Figma constraint → rule
- The share modal shows off-grid values (7 / 7.5px offsets, 0.714px borders) — artefacts of scaling a component in the frame. Read as: the close button sits at the standard 8px inset, borders are 1px. The JetBrains Mono Italic quote callout is the real validated exception for transcript content — not a licence for a third UI font.
- Also inside
- A hidden "Section compact" variant (82px cards) on both session lists — an unreleased density system.
analysis/loop-*.md · 16 files (preview, focus mode, share modal, analysis, sessions, chat, transcript, filters)

E5 — Loop creation
- Why it's canon
- The multi-step wizard reference. The whole New Loop flow is ONE master component whose steps are revealed by layer visibility, not a component per step — and the type hierarchy is deliberately flat: a single Clash headline over an otherwise uniform field of DM Sans 14px. Its
State matrixsections inventory the empty, filled, error and recap states — currently the only state documentation in the corpus. - Figma constraint → rule
- The disabled CTA is a raw 48% opacity class. That value is the DS disabled opacity — the intent is right, only the binding is raw. Read as: disabled = the DS
.48state, via its token. - Confetti is dead
- The Success modal ships a full-frame confetti raster. Confetti is banned (Maxime, 2026-07-28) — gamified, childish, dated. The celebration primitive is the fire-crackle border effect, and the code already agrees:
LoopCreateSuccessModal.tsxrenders<BorderFireEffect>. Its palette is PX Heat extended into incandescence and it emits from the card border — it frames the artifact instead of covering the screen. The modal is canon for its layout only.
analysis/loop-creation-*.md · 7 families incl. dispatch, verbatim, thematique, success, detail drawer
How canon gets minted
Two routes, and nobody but Maxime mints. An agent may propose a candidate in a PR; only his explicit promotion counts. An exemplar without a WHY is a screenshot.
| Route | What happens | Refresh |
|---|---|---|
| Figma (all five above) | Maxime hands over frames → export the capture, measure the values, map them to --ds-* tokens and ds/ components, flag what has no token → draft the annotations and a proposed WHY → Maxime validates the WHY in one line. No coded implementation required — the frame is the exemplar. | Re-export when the frame changes. |
| Harness | A screen generated with the Bible, corrected by Maxime, shipped — then explicitly promoted, with captures, measurable annotations and the WHY. | Monthly scripted re-capture and diff — running code rots. |
MeditationScreen (mobile), 62 hardcoded hex values and blue/gold gradients entirely
off PX Heat — every rule it breaks is a Bible hard rule.Registers
Drift register
Every documented divergence between the Figma master, the code tokens, and the
ds/ implementations — found during the ISO reproduction pass of 2026-07-20. Each
entry carries what was expected, what was observed, and where it stands. Resolved entries stay:
they're the history of the system.