@zevra/ui 0.1.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/DECISIONS.md +150 -0
- package/README.md +177 -0
- package/logos/index.json +599 -0
- package/logos/png/campus-glyph-ink.png +0 -0
- package/logos/png/campus-glyph-orig.png +0 -0
- package/logos/png/campus-glyph-white.png +0 -0
- package/logos/png/campus-lockup.png +0 -0
- package/logos/png/lexform-glyph-ink.png +0 -0
- package/logos/png/lexform-glyph-orig.png +0 -0
- package/logos/png/lexform-glyph-white.png +0 -0
- package/logos/png/lexform-lockup.png +0 -0
- package/logos/png/mcp-glyph-ink.png +0 -0
- package/logos/png/mcp-glyph-orig.png +0 -0
- package/logos/png/mcp-glyph-white.png +0 -0
- package/logos/png/mcp-lockup.png +0 -0
- package/logos/png/memoire-dark.png +0 -0
- package/logos/png/memoire-glyph-ink.png +0 -0
- package/logos/png/memoire-glyph-orig.png +0 -0
- package/logos/png/memoire-glyph-white.png +0 -0
- package/logos/png/memoire-lockup.png +0 -0
- package/logos/png/zevra-lockup-ink.png +0 -0
- package/logos/png/zevra-lockup-white.png +0 -0
- package/logos/png/zevra-lockup.png +0 -0
- package/logos/png/zevra-mark-ink.png +0 -0
- package/logos/png/zevra-mark-orig.png +0 -0
- package/logos/png/zevra-mark-white.png +0 -0
- package/logos/png/zevra-mark.png +0 -0
- package/logos/svg/campus-glyph-ink.svg +1 -0
- package/logos/svg/campus-glyph-navy.svg +1 -0
- package/logos/svg/campus-glyph-orig.svg +1 -0
- package/logos/svg/campus-glyph-white.svg +1 -0
- package/logos/svg/campus-lockup-ink.svg +1 -0
- package/logos/svg/campus-lockup-navy.svg +1 -0
- package/logos/svg/campus-lockup-orig.svg +1 -0
- package/logos/svg/campus-lockup-white.svg +1 -0
- package/logos/svg/lexform-glyph-ink.svg +1 -0
- package/logos/svg/lexform-glyph-navy.svg +1 -0
- package/logos/svg/lexform-glyph-orig.svg +1 -0
- package/logos/svg/lexform-glyph-white.svg +1 -0
- package/logos/svg/lexform-lockup-ink.svg +1 -0
- package/logos/svg/lexform-lockup-navy.svg +1 -0
- package/logos/svg/lexform-lockup-orig.svg +1 -0
- package/logos/svg/lexform-lockup-white.svg +1 -0
- package/logos/svg/mcp-glyph-ink.svg +1 -0
- package/logos/svg/mcp-glyph-navy.svg +1 -0
- package/logos/svg/mcp-glyph-orig.svg +1 -0
- package/logos/svg/mcp-glyph-white.svg +1 -0
- package/logos/svg/mcp-lockup-ink.svg +1 -0
- package/logos/svg/mcp-lockup-navy.svg +1 -0
- package/logos/svg/mcp-lockup-orig.svg +1 -0
- package/logos/svg/mcp-lockup-white.svg +1 -0
- package/logos/svg/memoire-glyph-ink.svg +1 -0
- package/logos/svg/memoire-glyph-navy.svg +1 -0
- package/logos/svg/memoire-glyph-orig.svg +1 -0
- package/logos/svg/memoire-glyph-white.svg +1 -0
- package/logos/svg/memoire-lockup-ink.svg +1 -0
- package/logos/svg/memoire-lockup-navy.svg +1 -0
- package/logos/svg/memoire-lockup-orig.svg +1 -0
- package/logos/svg/memoire-lockup-white.svg +1 -0
- package/logos/svg/zevra-lockup-ink.svg +1 -0
- package/logos/svg/zevra-lockup-navy.svg +1 -0
- package/logos/svg/zevra-lockup-orig.svg +1 -0
- package/logos/svg/zevra-lockup-white.svg +1 -0
- package/logos/svg/zevra-mark-ink.svg +1 -0
- package/logos/svg/zevra-mark-navy.svg +1 -0
- package/logos/svg/zevra-mark-orig.svg +1 -0
- package/logos/svg/zevra-mark-white.svg +1 -0
- package/package.json +52 -0
- package/src/base.css +367 -0
- package/src/components.css +553 -0
- package/src/fonts.css +16 -0
- package/src/index.css +11 -0
- package/src/layout.css +542 -0
- package/src/motion.css +248 -0
- package/src/surfaces.css +235 -0
- package/src/tokens.css +76 -0
- package/tokens/index.js +91 -0
package/src/base.css
ADDED
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
/* Zevra UI — socle : reset, document, typographie, signature
|
|
2
|
+
* Dépend de tokens.css. À charger en premier.
|
|
3
|
+
*
|
|
4
|
+
* Chaque valeur ci-dessous est relevée dans les maquettes de la passation du
|
|
5
|
+
* 23/08/2026. Quand deux planches divergent, l'arbitrage est écrit dans
|
|
6
|
+
* DECISIONS.md — jamais tranché en silence.
|
|
7
|
+
*
|
|
8
|
+
* POINT DE RUPTURE : 768px. Il ne vient PAS du relevé (les cinq maquettes sont
|
|
9
|
+
* à largeur fixe, sans une seule media query). C'est la convention `md` du
|
|
10
|
+
* projet, et les valeurs mobiles viennent de Mobile.html, qui est un rendu
|
|
11
|
+
* figé à 390px. Les quatre modules utilisent ce seuil et lui seul.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/* ─── Reset ─────────────────────────────────────────────────────────────
|
|
15
|
+
* Posé ici et nulle part ailleurs : les autres modules ne touchent ni au
|
|
16
|
+
* box-sizing ni au body. */
|
|
17
|
+
|
|
18
|
+
*,
|
|
19
|
+
*::before,
|
|
20
|
+
*::after {
|
|
21
|
+
box-sizing: border-box;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
body {
|
|
25
|
+
margin: 0;
|
|
26
|
+
background: var(--paper);
|
|
27
|
+
color: var(--ink);
|
|
28
|
+
font-family: var(--font-text);
|
|
29
|
+
-webkit-font-smoothing: antialiased;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* ─── Liens ─────────────────────────────────────────────────────────────
|
|
33
|
+
* Restreint aux liens SANS classe. Les maquettes stylent `a` nu, ce qui
|
|
34
|
+
* repeint le libellé des boutons au survol (a:hover, 0-1-1, l'emporte sur
|
|
35
|
+
* .zv-btn, 0-1-0) — bug visible dans Main.html et signalé au relevé. Le
|
|
36
|
+
* périmètre est réduit plutôt que neutralisé par un :hover inventé. */
|
|
37
|
+
|
|
38
|
+
a:not([class]) {
|
|
39
|
+
color: var(--accent);
|
|
40
|
+
text-decoration: none;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
a:not([class]):hover {
|
|
44
|
+
color: var(--accent-deep);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.zv-link {
|
|
48
|
+
color: var(--accent);
|
|
49
|
+
text-decoration: none;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.zv-link:hover {
|
|
53
|
+
color: var(--accent-deep);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* ─── Accessibilité ─────────────────────────────────────────────────────
|
|
57
|
+
* HORS RELEVÉ, et assumé : aucune des cinq maquettes ne déclare d'état de
|
|
58
|
+
* focus. Un système livré sans focus clavier est inutilisable au clavier —
|
|
59
|
+
* on ne réplique pas cette lacune. Seules des valeurs existantes sont
|
|
60
|
+
* employées. */
|
|
61
|
+
|
|
62
|
+
:focus-visible {
|
|
63
|
+
outline: 2px solid var(--accent);
|
|
64
|
+
outline-offset: 2px;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@media (prefers-reduced-motion: reduce) {
|
|
68
|
+
*,
|
|
69
|
+
*::before,
|
|
70
|
+
*::after {
|
|
71
|
+
animation-duration: 0.01ms !important;
|
|
72
|
+
animation-iteration-count: 1 !important;
|
|
73
|
+
transition-duration: 0.01ms !important;
|
|
74
|
+
scroll-behavior: auto !important;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/* ─── Titres ────────────────────────────────────────────────────────────
|
|
79
|
+
* Outfit, graisse 300, interlettrage -0.02em. L'échelle est celle de
|
|
80
|
+
* Main.html, la planche de référence. */
|
|
81
|
+
|
|
82
|
+
.zv-display {
|
|
83
|
+
font-family: var(--font-display);
|
|
84
|
+
letter-spacing: -0.02em;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.zv-h1 {
|
|
88
|
+
margin: 0;
|
|
89
|
+
font-family: var(--font-display);
|
|
90
|
+
letter-spacing: -0.02em;
|
|
91
|
+
font-size: var(--h1);
|
|
92
|
+
line-height: 1.05;
|
|
93
|
+
font-weight: 300;
|
|
94
|
+
color: var(--ink);
|
|
95
|
+
max-width: 1100px;
|
|
96
|
+
text-wrap: balance;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.zv-h2 {
|
|
100
|
+
margin: 0;
|
|
101
|
+
font-family: var(--font-display);
|
|
102
|
+
letter-spacing: -0.02em;
|
|
103
|
+
font-size: var(--h2);
|
|
104
|
+
line-height: 1.06;
|
|
105
|
+
font-weight: 300;
|
|
106
|
+
text-wrap: balance;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* Le titre de CTA final est d'un cran au-dessus des titres de section :
|
|
110
|
+
* 64px contre 56px (Main.html). Aucun token ne couvre cette taille. */
|
|
111
|
+
.zv-h2--cta {
|
|
112
|
+
font-size: 64px;
|
|
113
|
+
max-width: 900px;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/* Titre de section des landings produit : un cran EN DESSOUS du 56px de la
|
|
117
|
+
* home. Les trois landings de la passation le posent en classe `.h2`, aux
|
|
118
|
+
* côtés des 56 et 64px qui restent pour la page d'accueil. */
|
|
119
|
+
.zv-h2--sm {
|
|
120
|
+
font-size: 48px;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.zv-h3 {
|
|
124
|
+
margin: 0;
|
|
125
|
+
font-family: var(--font-display);
|
|
126
|
+
letter-spacing: -0.02em;
|
|
127
|
+
font-size: var(--h3);
|
|
128
|
+
line-height: 1.1;
|
|
129
|
+
font-weight: 300;
|
|
130
|
+
max-width: 480px;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.zv-card-title {
|
|
134
|
+
margin: 0;
|
|
135
|
+
font-family: var(--font-display);
|
|
136
|
+
letter-spacing: -0.02em;
|
|
137
|
+
font-size: var(--card-title);
|
|
138
|
+
line-height: 1.25;
|
|
139
|
+
font-weight: 400;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/* La deuxième moitié de phrase d'un titre bascule en indigo et prend un cran
|
|
143
|
+
* de graisse. Motif systématique : présent dans les cinq maquettes. */
|
|
144
|
+
.zv-em {
|
|
145
|
+
color: var(--accent-deep);
|
|
146
|
+
font-weight: 400;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/* Sur fond sombre l'accent ne change pas de couleur mais de graisse. */
|
|
150
|
+
.zv-em--on-dark {
|
|
151
|
+
color: var(--white);
|
|
152
|
+
font-weight: 500;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* ─── Texte courant ─────────────────────────────────────────────────────
|
|
156
|
+
* Quatre paliers relevés : 18 (chapô), 16 (colonne d'accompagnement),
|
|
157
|
+
* 15 (corps), 13 (carte dense). */
|
|
158
|
+
|
|
159
|
+
.zv-lead {
|
|
160
|
+
margin: 0;
|
|
161
|
+
font-size: var(--lead);
|
|
162
|
+
line-height: 1.6;
|
|
163
|
+
color: var(--muted);
|
|
164
|
+
max-width: 660px;
|
|
165
|
+
text-wrap: pretty;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.zv-body {
|
|
169
|
+
margin: 0;
|
|
170
|
+
font-size: var(--body);
|
|
171
|
+
line-height: 1.6;
|
|
172
|
+
color: var(--muted);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* 16px : colonne de droite des en-têtes de section (Main.html). */
|
|
176
|
+
.zv-body--lg {
|
|
177
|
+
font-size: 16px;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/* 13px : légende de carte, texte serré. */
|
|
181
|
+
.zv-body--dense {
|
|
182
|
+
font-size: 13px;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.zv-body strong,
|
|
186
|
+
.zv-lead strong {
|
|
187
|
+
font-weight: 600;
|
|
188
|
+
color: var(--ink);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/* 14px : texte de règle et de légende des planches. */
|
|
192
|
+
.zv-rule {
|
|
193
|
+
margin: 0;
|
|
194
|
+
font-size: 14px;
|
|
195
|
+
line-height: 1.6;
|
|
196
|
+
color: var(--muted);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/* 12,5px : la note d'accompagnement d'un bloc ou d'une carte de
|
|
200
|
+
* documentation. Le plus petit palier de texte courant du système — en
|
|
201
|
+
* dessous, on passe en label capitales. */
|
|
202
|
+
.zv-note {
|
|
203
|
+
margin: 0;
|
|
204
|
+
font-size: 12.5px;
|
|
205
|
+
line-height: 1.55;
|
|
206
|
+
color: var(--muted);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/* ─── Labels capitales ──────────────────────────────────────────────────
|
|
210
|
+
* Space Grotesk, majuscules, très interlettré. Trois tailles seulement :
|
|
211
|
+
* 11px (kicker de section), 10px (label de carte), 9px (micro-label). */
|
|
212
|
+
|
|
213
|
+
.zv-mono {
|
|
214
|
+
font-family: var(--font-mono);
|
|
215
|
+
text-transform: uppercase;
|
|
216
|
+
letter-spacing: 0.2em;
|
|
217
|
+
font-weight: 500;
|
|
218
|
+
font-size: 11px;
|
|
219
|
+
color: var(--accent);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.zv-mono--label {
|
|
223
|
+
font-size: 10px;
|
|
224
|
+
font-weight: 700;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.zv-mono--micro {
|
|
228
|
+
font-size: 9px;
|
|
229
|
+
font-weight: 500;
|
|
230
|
+
color: var(--label);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.zv-mono--muted {
|
|
234
|
+
color: var(--label);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.zv-mono--ink {
|
|
238
|
+
color: var(--ink);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/* Sur fond sombre les labels passent en indigo clair, jamais en blanc pur. */
|
|
242
|
+
.zv-mono--on-dark {
|
|
243
|
+
color: var(--accent-on-dark);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/* Accroche produit, posée sous le nom d'un glyphe : « Votre savoir,
|
|
247
|
+
* interrogeable en une phrase ». Moins interlettrée que le label qu'elle
|
|
248
|
+
* suit (0.14em contre 0.2em) — sinon la phrase se disloque. */
|
|
249
|
+
.zv-tagline {
|
|
250
|
+
font-family: var(--font-mono);
|
|
251
|
+
text-transform: uppercase;
|
|
252
|
+
letter-spacing: 0.14em;
|
|
253
|
+
font-weight: 500;
|
|
254
|
+
font-size: 9px;
|
|
255
|
+
line-height: 1.6;
|
|
256
|
+
color: var(--muted);
|
|
257
|
+
text-align: center;
|
|
258
|
+
/* Remonte sous le label : l'ensemble se lit comme un seul bloc. */
|
|
259
|
+
margin-top: -4px;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/* ─── Signature : le filet de spectre ───────────────────────────────────
|
|
263
|
+
* 56×2px devant chaque kicker. C'est, avec la barre de progression et les
|
|
264
|
+
* points de méthode, l'un des trois seuls emplois autorisés du spectre.
|
|
265
|
+
*
|
|
266
|
+
* ⚠️ ARBITRAGE (voir DECISIONS.md) : --spectre vaut violet → bleu → cyan,
|
|
267
|
+
* comme la charte des logos qui le nomme « signature ». Trois autres
|
|
268
|
+
* planches posent iris → violet → cyan. Le token fait foi ici ; la question
|
|
269
|
+
* est ouverte pour la DA. */
|
|
270
|
+
|
|
271
|
+
.zv-spec {
|
|
272
|
+
display: block;
|
|
273
|
+
width: var(--spec-filet);
|
|
274
|
+
height: 2px;
|
|
275
|
+
background: var(--spectre);
|
|
276
|
+
border-radius: 1px;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/* Bas de page : filet raccourci. */
|
|
280
|
+
.zv-spec--sm {
|
|
281
|
+
width: 40px;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/* Sur fond sombre le filet s'éclaircit pour rester lisible. */
|
|
285
|
+
.zv-spec--on-dark {
|
|
286
|
+
background: linear-gradient(90deg, #7fd8ff, var(--violet));
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/* Filet + label, la composition de tête de section. */
|
|
290
|
+
.zv-kicker {
|
|
291
|
+
display: flex;
|
|
292
|
+
align-items: center;
|
|
293
|
+
gap: 14px;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
.zv-kicker--stack {
|
|
297
|
+
flex-direction: column;
|
|
298
|
+
align-items: flex-start;
|
|
299
|
+
gap: 12px;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.zv-kicker--center {
|
|
303
|
+
flex-direction: column;
|
|
304
|
+
align-items: center;
|
|
305
|
+
gap: 14px;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/* ─── Mobile ────────────────────────────────────────────────────────────
|
|
309
|
+
* Valeurs relevées dans Mobile.html. Le seuil, lui, est la convention du
|
|
310
|
+
* projet (cf. en-tête). */
|
|
311
|
+
|
|
312
|
+
@media (max-width: 767px) {
|
|
313
|
+
.zv-h1 {
|
|
314
|
+
font-size: 40px;
|
|
315
|
+
line-height: 1.08;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
.zv-h2 {
|
|
319
|
+
font-size: 30px;
|
|
320
|
+
line-height: 1.1;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
.zv-h2--cta {
|
|
324
|
+
font-size: 32px;
|
|
325
|
+
line-height: 1.08;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
.zv-card-title {
|
|
329
|
+
font-size: 18px;
|
|
330
|
+
font-weight: 500;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
.zv-lead {
|
|
334
|
+
font-size: 15px;
|
|
335
|
+
line-height: 1.55;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/* .zv-body garde 15px : c'est déjà la taille du chapô mobile. Seule
|
|
339
|
+
* l'interligne se resserre — et --dense reste distinct, à 13px/1.45. */
|
|
340
|
+
.zv-body {
|
|
341
|
+
line-height: 1.55;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
.zv-body--dense {
|
|
345
|
+
font-size: 13px;
|
|
346
|
+
line-height: 1.45;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
.zv-mono {
|
|
350
|
+
letter-spacing: 0.18em;
|
|
351
|
+
font-size: 9px;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
.zv-mono--label {
|
|
355
|
+
font-size: 8px;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.zv-spec {
|
|
359
|
+
width: 44px;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/* Re-déclaré : une media query n'ajoute pas de spécificité, le modificateur
|
|
363
|
+
* serait sinon écrasé par la règle ci-dessus. */
|
|
364
|
+
.zv-spec--sm {
|
|
365
|
+
width: 40px;
|
|
366
|
+
}
|
|
367
|
+
}
|