@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.
Files changed (77) hide show
  1. package/DECISIONS.md +150 -0
  2. package/README.md +177 -0
  3. package/logos/index.json +599 -0
  4. package/logos/png/campus-glyph-ink.png +0 -0
  5. package/logos/png/campus-glyph-orig.png +0 -0
  6. package/logos/png/campus-glyph-white.png +0 -0
  7. package/logos/png/campus-lockup.png +0 -0
  8. package/logos/png/lexform-glyph-ink.png +0 -0
  9. package/logos/png/lexform-glyph-orig.png +0 -0
  10. package/logos/png/lexform-glyph-white.png +0 -0
  11. package/logos/png/lexform-lockup.png +0 -0
  12. package/logos/png/mcp-glyph-ink.png +0 -0
  13. package/logos/png/mcp-glyph-orig.png +0 -0
  14. package/logos/png/mcp-glyph-white.png +0 -0
  15. package/logos/png/mcp-lockup.png +0 -0
  16. package/logos/png/memoire-dark.png +0 -0
  17. package/logos/png/memoire-glyph-ink.png +0 -0
  18. package/logos/png/memoire-glyph-orig.png +0 -0
  19. package/logos/png/memoire-glyph-white.png +0 -0
  20. package/logos/png/memoire-lockup.png +0 -0
  21. package/logos/png/zevra-lockup-ink.png +0 -0
  22. package/logos/png/zevra-lockup-white.png +0 -0
  23. package/logos/png/zevra-lockup.png +0 -0
  24. package/logos/png/zevra-mark-ink.png +0 -0
  25. package/logos/png/zevra-mark-orig.png +0 -0
  26. package/logos/png/zevra-mark-white.png +0 -0
  27. package/logos/png/zevra-mark.png +0 -0
  28. package/logos/svg/campus-glyph-ink.svg +1 -0
  29. package/logos/svg/campus-glyph-navy.svg +1 -0
  30. package/logos/svg/campus-glyph-orig.svg +1 -0
  31. package/logos/svg/campus-glyph-white.svg +1 -0
  32. package/logos/svg/campus-lockup-ink.svg +1 -0
  33. package/logos/svg/campus-lockup-navy.svg +1 -0
  34. package/logos/svg/campus-lockup-orig.svg +1 -0
  35. package/logos/svg/campus-lockup-white.svg +1 -0
  36. package/logos/svg/lexform-glyph-ink.svg +1 -0
  37. package/logos/svg/lexform-glyph-navy.svg +1 -0
  38. package/logos/svg/lexform-glyph-orig.svg +1 -0
  39. package/logos/svg/lexform-glyph-white.svg +1 -0
  40. package/logos/svg/lexform-lockup-ink.svg +1 -0
  41. package/logos/svg/lexform-lockup-navy.svg +1 -0
  42. package/logos/svg/lexform-lockup-orig.svg +1 -0
  43. package/logos/svg/lexform-lockup-white.svg +1 -0
  44. package/logos/svg/mcp-glyph-ink.svg +1 -0
  45. package/logos/svg/mcp-glyph-navy.svg +1 -0
  46. package/logos/svg/mcp-glyph-orig.svg +1 -0
  47. package/logos/svg/mcp-glyph-white.svg +1 -0
  48. package/logos/svg/mcp-lockup-ink.svg +1 -0
  49. package/logos/svg/mcp-lockup-navy.svg +1 -0
  50. package/logos/svg/mcp-lockup-orig.svg +1 -0
  51. package/logos/svg/mcp-lockup-white.svg +1 -0
  52. package/logos/svg/memoire-glyph-ink.svg +1 -0
  53. package/logos/svg/memoire-glyph-navy.svg +1 -0
  54. package/logos/svg/memoire-glyph-orig.svg +1 -0
  55. package/logos/svg/memoire-glyph-white.svg +1 -0
  56. package/logos/svg/memoire-lockup-ink.svg +1 -0
  57. package/logos/svg/memoire-lockup-navy.svg +1 -0
  58. package/logos/svg/memoire-lockup-orig.svg +1 -0
  59. package/logos/svg/memoire-lockup-white.svg +1 -0
  60. package/logos/svg/zevra-lockup-ink.svg +1 -0
  61. package/logos/svg/zevra-lockup-navy.svg +1 -0
  62. package/logos/svg/zevra-lockup-orig.svg +1 -0
  63. package/logos/svg/zevra-lockup-white.svg +1 -0
  64. package/logos/svg/zevra-mark-ink.svg +1 -0
  65. package/logos/svg/zevra-mark-navy.svg +1 -0
  66. package/logos/svg/zevra-mark-orig.svg +1 -0
  67. package/logos/svg/zevra-mark-white.svg +1 -0
  68. package/package.json +52 -0
  69. package/src/base.css +367 -0
  70. package/src/components.css +553 -0
  71. package/src/fonts.css +16 -0
  72. package/src/index.css +11 -0
  73. package/src/layout.css +542 -0
  74. package/src/motion.css +248 -0
  75. package/src/surfaces.css +235 -0
  76. package/src/tokens.css +76 -0
  77. package/tokens/index.js +91 -0
package/src/layout.css ADDED
@@ -0,0 +1,542 @@
1
+ /* Zevra UI — mise en page : conteneurs, grilles, sections, chrome
2
+ * Dépend de tokens.css et base.css. Ne pose ni reset ni fond de page :
3
+ * c'est le rôle de base.css.
4
+ *
5
+ * ⚠️ Les maquettes sont des rendus FIGÉS (1440px pour les planches, 390px
6
+ * pour Mobile.html). Les reproduire en `width: 1440px` donnerait un
7
+ * débordement horizontal garanti sur téléphone — ce que les règles du projet
8
+ * interdisent explicitement. Les conteneurs sont donc fluides et plafonnés,
9
+ * ce qui rend le rendu identique au-delà de 1440px et utilisable en dessous.
10
+ */
11
+
12
+ /* ─── Page ──────────────────────────────────────────────────────────────*/
13
+
14
+ .zv-page {
15
+ width: 100%;
16
+ max-width: 1440px;
17
+ margin: 0 auto;
18
+ position: relative;
19
+ overflow: hidden;
20
+ background: var(--paper);
21
+ }
22
+
23
+ /* ─── Gouttières ────────────────────────────────────────────────────────
24
+ * Trois retraits relevés, et un seul mécanisme pour les poser : ces
25
+ * utilitaires. Les blocs ci-dessous ne portent QUE leur rythme vertical,
26
+ * jamais leur retrait horizontal — sans quoi poser un utilitaire par-dessus
27
+ * un bloc écraserait son padding vertical (shorthand contre longhand). */
28
+
29
+ .zv-gutter {
30
+ padding-left: 72px;
31
+ padding-right: 72px;
32
+ }
33
+
34
+ /* Blocs centrés : hero, CTA, manifeste du prototype. */
35
+ .zv-gutter--wide {
36
+ padding-left: 120px;
37
+ padding-right: 120px;
38
+ }
39
+
40
+ /* Chrome haut du prototype. */
41
+ .zv-gutter--chrome {
42
+ padding-left: 56px;
43
+ padding-right: 56px;
44
+ }
45
+
46
+ /* Variante en marge, pour les blocs détachés du bord (grille produits,
47
+ * vitrine, pied de page). */
48
+ .zv-inset-x {
49
+ margin-left: 72px;
50
+ margin-right: 72px;
51
+ }
52
+
53
+ /* ─── Grille 12 colonnes ────────────────────────────────────────────────
54
+ * Répartitions relevées : 3+9, 8+4, 6+6. */
55
+
56
+ .zv-grid-12 {
57
+ display: grid;
58
+ grid-template-columns: repeat(12, minmax(0, 1fr));
59
+ gap: 32px;
60
+ }
61
+
62
+ .zv-col-3 { grid-column: span 3; }
63
+ .zv-col-4 { grid-column: span 4; }
64
+ .zv-col-6 { grid-column: span 6; }
65
+ .zv-col-8 { grid-column: span 8; }
66
+ .zv-col-9 { grid-column: span 9; }
67
+
68
+ /* Grille de cartes produit. */
69
+ .zv-grid-3 {
70
+ display: grid;
71
+ grid-template-columns: repeat(3, minmax(0, 1fr));
72
+ gap: 24px;
73
+ }
74
+
75
+ .zv-grid-4 {
76
+ display: grid;
77
+ grid-template-columns: repeat(4, minmax(0, 1fr));
78
+ gap: 16px;
79
+ }
80
+
81
+ /* ─── Sections ──────────────────────────────────────────────────────────*/
82
+
83
+ /* En-tête de section : titre à gauche sur 8 colonnes, texte
84
+ * d'accompagnement à droite sur 4, alignés par le bas. */
85
+ .zv-section-head {
86
+ display: grid;
87
+ grid-template-columns: repeat(12, minmax(0, 1fr));
88
+ gap: 32px;
89
+ align-items: end;
90
+ padding-top: 104px;
91
+ }
92
+
93
+ .zv-section-head__main {
94
+ grid-column: span 8;
95
+ display: flex;
96
+ flex-direction: column;
97
+ gap: 18px;
98
+ }
99
+
100
+ .zv-section-head__aside {
101
+ grid-column: span 4;
102
+ }
103
+
104
+ /* Section de planche : filet haut, titre sur 3 colonnes, corps sur 9.
105
+ * C'est la structure des planches de documentation (DesignSystem, Logos),
106
+ * pas celle des pages produit. */
107
+ .zv-sheet-section {
108
+ display: grid;
109
+ grid-template-columns: repeat(12, minmax(0, 1fr));
110
+ gap: 32px;
111
+ padding: 56px 0;
112
+ border-top: 1px solid var(--line);
113
+ }
114
+
115
+ .zv-sheet-section__title {
116
+ grid-column: span 3;
117
+ display: flex;
118
+ flex-direction: column;
119
+ gap: 10px;
120
+ }
121
+
122
+ .zv-sheet-section__body {
123
+ grid-column: span 9;
124
+ }
125
+
126
+ /* Séparateur de section, avec son rythme vertical. */
127
+ .zv-section-rule {
128
+ border-top: 1px solid var(--line);
129
+ padding-top: 40px;
130
+ padding-bottom: 40px;
131
+ }
132
+
133
+ .zv-section-rule--quiet {
134
+ border-top-color: var(--hairline);
135
+ padding-top: 18px;
136
+ padding-bottom: 28px;
137
+ }
138
+
139
+ /* ─── Blocs centrés : hero et CTA ───────────────────────────────────────*/
140
+
141
+ .zv-hero {
142
+ position: relative;
143
+ display: flex;
144
+ flex-direction: column;
145
+ align-items: center;
146
+ text-align: center;
147
+ padding-top: 96px;
148
+ gap: 28px;
149
+ z-index: 2;
150
+ }
151
+
152
+ .zv-cta {
153
+ position: relative;
154
+ display: flex;
155
+ flex-direction: column;
156
+ align-items: center;
157
+ text-align: center;
158
+ padding-top: 128px;
159
+ padding-bottom: 96px;
160
+ gap: 24px;
161
+ }
162
+
163
+ .zv-cta .zv-lead {
164
+ max-width: 580px;
165
+ font-size: 17px;
166
+ }
167
+
168
+ /* ─── Chrome : navigation ───────────────────────────────────────────────*/
169
+
170
+ .zv-nav {
171
+ position: relative;
172
+ display: flex;
173
+ align-items: center;
174
+ justify-content: space-between;
175
+ padding-top: 26px;
176
+ z-index: 2;
177
+ }
178
+
179
+ .zv-nav__logo {
180
+ height: 42px;
181
+ width: auto;
182
+ display: block;
183
+ }
184
+
185
+ .zv-nav__links {
186
+ display: flex;
187
+ align-items: center;
188
+ gap: 34px;
189
+ }
190
+
191
+ .zv-navlink {
192
+ font-size: 14px;
193
+ font-weight: 500;
194
+ color: var(--accent);
195
+ text-decoration: none;
196
+ }
197
+
198
+ .zv-navlink--quiet {
199
+ color: var(--label);
200
+ }
201
+
202
+ /* Header fixe du prototype : voile dégradé plutôt qu'un fond plein, pour
203
+ * que le contenu s'y fonde au défilement. */
204
+ .zv-header {
205
+ position: fixed;
206
+ top: 0;
207
+ left: 0;
208
+ width: 100%;
209
+ display: flex;
210
+ align-items: center;
211
+ justify-content: space-between;
212
+ padding-top: 22px;
213
+ padding-bottom: 12px;
214
+ z-index: 40;
215
+ background: linear-gradient(180deg, rgba(245, 246, 250, 0.92), rgba(245, 246, 250, 0));
216
+ backdrop-filter: blur(6px);
217
+ -webkit-backdrop-filter: blur(6px);
218
+ }
219
+
220
+ /* ─── Frise d'étapes ────────────────────────────────────────────────────
221
+ * Troisième et dernier emploi autorisé du spectre : les points de méthode,
222
+ * dans l'ordre iris → violet → cyan. */
223
+
224
+ .zv-steps {
225
+ position: relative;
226
+ display: grid;
227
+ grid-template-columns: repeat(3, minmax(0, 1fr));
228
+ gap: 32px;
229
+ }
230
+
231
+ .zv-steps__rail {
232
+ position: absolute;
233
+ top: 5px;
234
+ left: 0;
235
+ width: 100%;
236
+ height: 2px;
237
+ background: var(--line);
238
+ }
239
+
240
+ .zv-steps__progress {
241
+ position: absolute;
242
+ top: 5px;
243
+ left: 0;
244
+ height: 2px;
245
+ background: linear-gradient(90deg, var(--iris), var(--violet) 70%, var(--cyan));
246
+ }
247
+
248
+ .zv-step {
249
+ position: relative;
250
+ display: flex;
251
+ flex-direction: column;
252
+ gap: 12px;
253
+ padding: 36px 32px 0 0;
254
+ }
255
+
256
+ .zv-step:last-child {
257
+ padding-right: 0;
258
+ }
259
+
260
+ .zv-step__dot {
261
+ position: absolute;
262
+ top: 0;
263
+ left: 0;
264
+ width: 12px;
265
+ height: 12px;
266
+ border-radius: 50%;
267
+ /* Le double anneau détache la puce du rail qui passe derrière. */
268
+ background: var(--iris);
269
+ box-shadow:
270
+ 0 0 0 4px var(--paper),
271
+ 0 0 0 5px var(--accent-line);
272
+ }
273
+
274
+ /* Troisième et dernier emploi du spectre : les puces, dans l'ordre
275
+ * iris → violet → cyan. La couleur se pose sur la puce elle-même, et non
276
+ * par :nth-child sur l'étape : le rail et sa progression sont des enfants
277
+ * du même conteneur, ils décalent la numérotation et laissent les puces
278
+ * suivantes sans fond. */
279
+ .zv-step__dot--violet {
280
+ background: var(--violet);
281
+ }
282
+
283
+ .zv-step__dot--cyan {
284
+ background: var(--cyan);
285
+ }
286
+
287
+ /* ─── Ligne de statistiques ─────────────────────────────────────────────
288
+ * Posée sur le bandeau manifeste, d'où le filet clair. */
289
+
290
+ .zv-stats {
291
+ display: flex;
292
+ gap: 64px;
293
+ padding-top: 32px;
294
+ border-top: 1px solid rgba(255, 255, 255, 0.18);
295
+ }
296
+
297
+ .zv-stat {
298
+ display: flex;
299
+ flex-direction: column;
300
+ gap: 6px;
301
+ }
302
+
303
+ .zv-stat__value {
304
+ font-family: var(--font-display);
305
+ letter-spacing: -0.02em;
306
+ font-size: 40px;
307
+ font-weight: 300;
308
+ }
309
+
310
+ /* ─── Pied de page ──────────────────────────────────────────────────────*/
311
+
312
+ .zv-footer {
313
+ position: relative;
314
+ padding-top: 40px;
315
+ padding-bottom: 40px;
316
+ border-top: 1px solid var(--line);
317
+ display: flex;
318
+ justify-content: space-between;
319
+ align-items: flex-start;
320
+ gap: 48px;
321
+ }
322
+
323
+ .zv-footer__brand {
324
+ display: flex;
325
+ flex-direction: column;
326
+ gap: 14px;
327
+ max-width: 320px;
328
+ }
329
+
330
+ .zv-footer__cols {
331
+ display: grid;
332
+ grid-template-columns: repeat(4, minmax(0, 1fr));
333
+ gap: 48px;
334
+ font-size: 13px;
335
+ color: var(--muted);
336
+ line-height: 2;
337
+ }
338
+
339
+ /* ─── Bande de preuve sociale ───────────────────────────────────────────
340
+ * Label à gauche, noms de clients à droite, en Outfit 500 atténué.
341
+ * ⚠️ Règle de la passation : jamais plus d'une ligne. Au-delà, la preuve
342
+ * se dilue au lieu de s'accumuler. */
343
+
344
+ .zv-proof-bar {
345
+ display: flex;
346
+ align-items: center;
347
+ justify-content: space-between;
348
+ gap: 24px;
349
+ padding: 24px 40px;
350
+ }
351
+
352
+ .zv-proof-bar__names {
353
+ display: flex;
354
+ gap: 36px;
355
+ font-family: var(--font-display);
356
+ letter-spacing: -0.02em;
357
+ font-size: 17px;
358
+ font-weight: 500;
359
+ color: var(--ink);
360
+ opacity: 0.72;
361
+ }
362
+
363
+ /* ─── Pied de page réduit ───────────────────────────────────────────────
364
+ * Pages secondaires. Le pied complet à quatre colonnes reste réservé à la
365
+ * page d'accueil. */
366
+
367
+ .zv-footer-mini {
368
+ display: flex;
369
+ align-items: center;
370
+ justify-content: space-between;
371
+ gap: 24px;
372
+ padding: 20px 32px;
373
+ background: var(--paper);
374
+ }
375
+
376
+ .zv-footer-mini__logo {
377
+ height: 22px;
378
+ width: auto;
379
+ display: block;
380
+ }
381
+
382
+ /* ─── Empilement ────────────────────────────────────────────────────────
383
+ * Inventaire complet des couches relevées. Toute nouvelle couche s'arbitre
384
+ * par rapport à celle-ci plutôt qu'en surenchérissant. */
385
+
386
+ .zv-layer-scene { z-index: 1; } /* scène constellation, sous la nav */
387
+ .zv-layer-content { z-index: 2; } /* nav, hero */
388
+ .zv-layer-progress { z-index: 5; } /* barre de progression en flux */
389
+ .zv-layer-chrome { z-index: 40; } /* header fixe, rail d'étapes */
390
+ .zv-layer-top { z-index: 50; } /* barre de progression fixe */
391
+
392
+ /* ─── Bascule d'affichage ───────────────────────────────────────────────
393
+ * HORS RELEVÉ : utilitaires mécaniques, pas des décisions de charte. Ils
394
+ * existent parce que les maquettes desktop et mobile ne montrent PAS les
395
+ * mêmes éléments de navigation — les liens de nav desktop deviennent un
396
+ * menu burger — et que sans eux chaque app réinvente la même règle. */
397
+
398
+ .zv-only-desktop {
399
+ display: none;
400
+ }
401
+
402
+ @media (min-width: 768px) {
403
+ .zv-only-desktop {
404
+ display: revert;
405
+ }
406
+
407
+ .zv-only-mobile {
408
+ display: none;
409
+ }
410
+ }
411
+
412
+ /* ─── Mobile ────────────────────────────────────────────────────────────
413
+ * Les grilles s'empilent, les gouttières se resserrent aux valeurs de
414
+ * Mobile.html (20 / 22 / 24px). */
415
+
416
+ @media (max-width: 767px) {
417
+ .zv-gutter,
418
+ .zv-gutter--wide,
419
+ .zv-gutter--chrome {
420
+ padding-left: 20px;
421
+ padding-right: 20px;
422
+ }
423
+
424
+ .zv-inset-x {
425
+ margin-left: 20px;
426
+ margin-right: 20px;
427
+ }
428
+
429
+ .zv-grid-12,
430
+ .zv-grid-3,
431
+ .zv-section-head,
432
+ .zv-sheet-section,
433
+ .zv-steps {
434
+ grid-template-columns: minmax(0, 1fr);
435
+ gap: 20px;
436
+ }
437
+
438
+ .zv-grid-4 {
439
+ grid-template-columns: repeat(2, minmax(0, 1fr));
440
+ }
441
+
442
+ .zv-col-3,
443
+ .zv-col-4,
444
+ .zv-col-6,
445
+ .zv-col-8,
446
+ .zv-col-9,
447
+ .zv-section-head__main,
448
+ .zv-section-head__aside,
449
+ .zv-sheet-section__title,
450
+ .zv-sheet-section__body {
451
+ grid-column: auto;
452
+ }
453
+
454
+ .zv-section-head {
455
+ padding-top: 44px;
456
+ align-items: start;
457
+ text-align: center;
458
+ justify-items: center;
459
+ }
460
+
461
+ .zv-hero {
462
+ padding-top: 44px;
463
+ gap: 18px;
464
+ }
465
+
466
+ .zv-cta {
467
+ padding-top: 56px;
468
+ padding-bottom: 48px;
469
+ gap: 16px;
470
+ }
471
+
472
+ .zv-nav {
473
+ padding-top: 20px;
474
+ }
475
+
476
+ .zv-nav__logo {
477
+ height: 30px;
478
+ }
479
+
480
+ /* Les liens de navigation desktop n'ont pas d'équivalent mobile au
481
+ * relevé : Mobile.html les remplace par un menu burger. Ils ne sont pas
482
+ * masqués d'office — cela casserait les pages sans burger — mais
483
+ * .zv-only-desktop est là pour le faire en une classe. */
484
+
485
+ .zv-steps__rail,
486
+ .zv-steps__progress {
487
+ display: none;
488
+ }
489
+
490
+ .zv-step {
491
+ padding: 0 0 0 24px;
492
+ }
493
+
494
+ .zv-step__dot {
495
+ top: 4px;
496
+ }
497
+
498
+ .zv-stats {
499
+ display: grid;
500
+ grid-template-columns: repeat(2, minmax(0, 1fr));
501
+ gap: 16px;
502
+ padding-top: 16px;
503
+ }
504
+
505
+ .zv-stat {
506
+ gap: 4px;
507
+ }
508
+
509
+ .zv-stat__value {
510
+ font-size: 28px;
511
+ }
512
+
513
+ .zv-proof-bar,
514
+ .zv-footer-mini {
515
+ flex-direction: column;
516
+ align-items: center;
517
+ text-align: center;
518
+ gap: 12px;
519
+ padding-left: 20px;
520
+ padding-right: 20px;
521
+ }
522
+
523
+ /* Les noms de clients passent en lignes plutôt qu'en une seule rangée,
524
+ * qui déborderait. La règle « jamais plus d'une ligne » vaut pour le
525
+ * desktop : à 390px, aucune rangée de six noms ne tient. */
526
+ .zv-proof-bar__names {
527
+ flex-wrap: wrap;
528
+ justify-content: center;
529
+ gap: 8px 20px;
530
+ font-size: 15px;
531
+ }
532
+
533
+ .zv-footer {
534
+ flex-direction: column;
535
+ gap: 32px;
536
+ }
537
+
538
+ .zv-footer__cols {
539
+ grid-template-columns: repeat(2, minmax(0, 1fr));
540
+ gap: 24px;
541
+ }
542
+ }