@zevra/ui 0.17.0 → 0.20.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 +246 -0
- package/dist/catalogue.d.ts.map +1 -1
- package/dist/catalogue.js +76 -2
- package/dist/catalogue.js.map +1 -1
- package/dist/content.d.ts +103 -0
- package/dist/content.d.ts.map +1 -1
- package/dist/content.js +80 -0
- package/dist/content.js.map +1 -1
- package/dist/css-inline.d.ts.map +1 -1
- package/dist/css-inline.js +1 -1
- package/dist/css-inline.js.map +1 -1
- package/dist/forms.d.ts +22 -0
- package/dist/forms.d.ts.map +1 -1
- package/dist/forms.js +18 -0
- package/dist/forms.js.map +1 -1
- package/dist/icon-data.d.ts +1 -1
- package/dist/icon-data.d.ts.map +1 -1
- package/dist/icon-data.js +30 -0
- package/dist/icon-data.js.map +1 -1
- package/dist/layout.d.ts +11 -5
- package/dist/layout.d.ts.map +1 -1
- package/dist/layout.js.map +1 -1
- package/dist/typography.d.ts +8 -3
- package/dist/typography.d.ts.map +1 -1
- package/dist/typography.js +6 -0
- package/dist/typography.js.map +1 -1
- package/icons/index.json +90 -0
- package/icons/sprite.svg +15 -0
- package/package.json +1 -1
- package/react/catalogue.tsx +109 -3
- package/react/content.tsx +272 -1
- package/react/css-inline.ts +1 -1
- package/react/forms.tsx +53 -0
- package/react/icon-data.ts +45 -0
- package/react/layout.tsx +11 -4
- package/react/typography.tsx +13 -3
- package/src/base.css +7 -0
- package/src/components.css +294 -8
- package/src/forms.css +65 -2
- package/src/icons.css +20 -0
- package/src/layout.css +16 -1
- package/src/navigation.css +20 -0
package/react/forms.tsx
CHANGED
|
@@ -21,6 +21,7 @@ import type {
|
|
|
21
21
|
TextareaHTMLAttributes,
|
|
22
22
|
} from 'react'
|
|
23
23
|
import { cx } from './cx.js'
|
|
24
|
+
import { Icon } from './icon.js'
|
|
24
25
|
|
|
25
26
|
/* ─── Groupe de champ ──────────────────────────────────────────────── */
|
|
26
27
|
|
|
@@ -471,3 +472,55 @@ export function Range({ className, style, min, max, value, defaultValue, ...rest
|
|
|
471
472
|
/>
|
|
472
473
|
)
|
|
473
474
|
}
|
|
475
|
+
|
|
476
|
+
export interface InputPasswordProps
|
|
477
|
+
extends Omit<InputHTMLAttributes<HTMLInputElement>, 'className' | 'type'> {
|
|
478
|
+
/** Le mot de passe est-il en clair ? L'état est TENU PAR L'APPELANT. */
|
|
479
|
+
visible?: boolean
|
|
480
|
+
/** Bascule demandée. Sans lui, le bouton n'est pas rendu du tout. */
|
|
481
|
+
onBascule?: () => void
|
|
482
|
+
className?: string
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* Champ de saisie masquée, avec sa bascule d'affichage.
|
|
487
|
+
*
|
|
488
|
+
* C'est le seul endroit de l'interface où l'on tape sans voir ce qu'on écrit :
|
|
489
|
+
* sur un mot de passe long, saisi au clavier d'un téléphone, la bascule évite
|
|
490
|
+
* l'échec silencieux et la réinitialisation qui suit.
|
|
491
|
+
*
|
|
492
|
+
* ⚠️ Sans état, comme tout ce fichier : `visible` et `onBascule` viennent de
|
|
493
|
+
* l'appelant, qui est déjà un composant client puisqu'il tient la valeur du
|
|
494
|
+
* champ. Le paquet ne tire pas React côté navigateur pour un champ.
|
|
495
|
+
*
|
|
496
|
+
* Le libellé du bouton change avec l'état — une icône seule ne dit pas ce qui
|
|
497
|
+
* va se passer — et `aria-pressed` l'annonce aux lecteurs d'écran.
|
|
498
|
+
*/
|
|
499
|
+
export function InputPassword({
|
|
500
|
+
visible,
|
|
501
|
+
onBascule,
|
|
502
|
+
className,
|
|
503
|
+
...reste
|
|
504
|
+
}: InputPasswordProps) {
|
|
505
|
+
return (
|
|
506
|
+
<div className={cx('zv-affix', className)}>
|
|
507
|
+
<input
|
|
508
|
+
type={visible ? 'text' : 'password'}
|
|
509
|
+
className="zv-input zv-input--bare"
|
|
510
|
+
{...reste}
|
|
511
|
+
/>
|
|
512
|
+
{onBascule && (
|
|
513
|
+
<button
|
|
514
|
+
type="button"
|
|
515
|
+
className="zv-affix__btn"
|
|
516
|
+
onClick={onBascule}
|
|
517
|
+
aria-pressed={visible ?? false}
|
|
518
|
+
aria-label={visible ? 'Masquer le mot de passe' : 'Afficher le mot de passe'}
|
|
519
|
+
title={visible ? 'Masquer le mot de passe' : 'Afficher le mot de passe'}
|
|
520
|
+
>
|
|
521
|
+
<Icon nom={visible ? 'oeil-barre' : 'oeil'} taille="sm" />
|
|
522
|
+
</button>
|
|
523
|
+
)}
|
|
524
|
+
</div>
|
|
525
|
+
)
|
|
526
|
+
}
|
package/react/icon-data.ts
CHANGED
|
@@ -8,6 +8,7 @@ export type IconId =
|
|
|
8
8
|
| 'app-couches'
|
|
9
9
|
| 'archiver'
|
|
10
10
|
| 'attention'
|
|
11
|
+
| 'avancer'
|
|
11
12
|
| 'balance'
|
|
12
13
|
| 'base-de-donnees'
|
|
13
14
|
| 'bouclier-verifie'
|
|
@@ -18,6 +19,7 @@ export type IconId =
|
|
|
18
19
|
| 'chevron-droit'
|
|
19
20
|
| 'chevron-gauche'
|
|
20
21
|
| 'chevron-haut'
|
|
22
|
+
| 'citation'
|
|
21
23
|
| 'coche'
|
|
22
24
|
| 'copier'
|
|
23
25
|
| 'corbeille'
|
|
@@ -38,25 +40,38 @@ export type IconId =
|
|
|
38
40
|
| 'filtre'
|
|
39
41
|
| 'globe'
|
|
40
42
|
| 'graphique'
|
|
43
|
+
| 'gras'
|
|
41
44
|
| 'horloge'
|
|
45
|
+
| 'image'
|
|
42
46
|
| 'imprimante'
|
|
43
47
|
| 'info'
|
|
48
|
+
| 'italique'
|
|
49
|
+
| 'lecture'
|
|
44
50
|
| 'lien-externe'
|
|
51
|
+
| 'liste-a-puces'
|
|
45
52
|
| 'livre-ouvert'
|
|
46
53
|
| 'menu'
|
|
47
54
|
| 'moins'
|
|
55
|
+
| 'muet'
|
|
48
56
|
| 'oeil'
|
|
57
|
+
| 'oeil-barre'
|
|
58
|
+
| 'pause'
|
|
59
|
+
| 'plein-ecran'
|
|
49
60
|
| 'plus'
|
|
50
61
|
| 'recherche'
|
|
51
62
|
| 'registre'
|
|
52
63
|
| 'reglages'
|
|
64
|
+
| 'rembobiner'
|
|
53
65
|
| 'reseau'
|
|
66
|
+
| 'signet'
|
|
67
|
+
| 'son'
|
|
54
68
|
| 'taches'
|
|
55
69
|
| 'telecharger'
|
|
56
70
|
| 'telephone'
|
|
57
71
|
| 'tri'
|
|
58
72
|
| 'trois-points'
|
|
59
73
|
| 'utilisateur'
|
|
74
|
+
| 'video'
|
|
60
75
|
|
|
61
76
|
export const CORPS: Record<IconId, string> = {
|
|
62
77
|
'accueil': "<path d=\"M4 10.67 L12 4 L20 10.67 V20 H4 Z\" /><path d=\"M9.33 20 V13.33 H14.67 V20\" />",
|
|
@@ -65,6 +80,7 @@ export const CORPS: Record<IconId, string> = {
|
|
|
65
80
|
'app-couches': "<path d=\"M12 2.67 L20 6.67 L12 10.67 L4 6.67 Z\" /><path d=\"M4 12 L12 16 L20 12\" /><path d=\"M4 17.33 L12 21.33 L20 17.33\" />",
|
|
66
81
|
'archiver': "<rect x=\"3.33\" y=\"4\" width=\"17.33\" height=\"4.67\" /><path d=\"M5.33 8.67 V18.93 A1.07 1.07 0 0 0 6.4 20 H17.6 A1.07 1.07 0 0 0 18.67 18.93 V8.67\" /><path d=\"M9.33 12.67 H14.67\" />",
|
|
67
82
|
'attention': "<path d=\"M10.67 3.87 L2.53 17.87 A1.55 1.55 0 0 0 3.87 20.19 H20.13 A1.55 1.55 0 0 0 21.47 17.87 L13.33 3.87 A1.54 1.54 0 0 0 10.67 3.87 Z\" /><path d=\"M12 9.33 V13.33\" /><rect x=\"11.2\" y=\"15.73\" width=\"1.6\" height=\"1.6\" fill=\"currentColor\" stroke=\"none\" />",
|
|
83
|
+
'avancer': "<path d=\"M4 6 L11 12 L4 18 Z\" fill=\"currentColor\" stroke=\"none\" /><path d=\"M13 6 L20 12 L13 18 Z\" fill=\"currentColor\" stroke=\"none\" />",
|
|
68
84
|
'balance': "<path d=\"M12 3.33 V20.67\" /><path d=\"M8.67 20.67 H15.33\" /><path d=\"M5.33 6 H18.67\" /><path d=\"M6.67 6 L3.33 13.33\" /><path d=\"M6.67 6 L10 13.33\" /><path d=\"M3.33 13.33 A3.33 3.33 0 0 0 10 13.33\" /><path d=\"M17.33 6 L14 13.33\" /><path d=\"M17.33 6 L20.67 13.33\" /><path d=\"M14 13.33 A3.33 3.33 0 0 0 20.67 13.33\" />",
|
|
69
85
|
'base-de-donnees': "<ellipse cx=\"12\" cy=\"6\" rx=\"7.33\" ry=\"2.67\" /><path d=\"M4.67 6 V12 C4.67 13.47 7.87 14.67 12 14.67 C16.13 14.67 19.33 13.47 19.33 12 V6\" /><path d=\"M4.67 12 V18 C4.67 19.47 7.87 20.67 12 20.67 C16.13 20.67 19.33 19.47 19.33 18 V12\" />",
|
|
70
86
|
'bouclier-verifie': "<path d=\"M12 2.67 L20 6 V12 C20 16.67 16.67 19.73 12 21.33 C7.33 19.73 4 16.67 4 12 V6 Z\" /><path d=\"M8.67 12 L11.07 14.4 L15.33 10\" />",
|
|
@@ -75,6 +91,7 @@ export const CORPS: Record<IconId, string> = {
|
|
|
75
91
|
'chevron-droit': "<path d=\"M9.33 4 L17.33 12 L9.33 20\" />",
|
|
76
92
|
'chevron-gauche': "<path d=\"M14.67 4 L6.67 12 L14.67 20\" />",
|
|
77
93
|
'chevron-haut': "<path d=\"M6.67 14.67 L12 9.33 L17.33 14.67\" />",
|
|
94
|
+
'citation': "<path d=\"M4 14 V10 C4 7.8 5.8 6 8 6 V9 C6.9 9 6 9.9 6 11 H9 V14 Z\" /><path d=\"M14 14 V10 C14 7.8 15.8 6 18 6 V9 C16.9 9 16 9.9 16 11 H19 V14 Z\" />",
|
|
78
95
|
'coche': "<path d=\"M5 12.4 L9.4 16.8 L19 6.8\" />",
|
|
79
96
|
'copier': "<rect x=\"4\" y=\"4\" width=\"12\" height=\"12\" /><path d=\"M8 16 V18.93 A1.07 1.07 0 0 0 9.07 20 H18.93 A1.07 1.07 0 0 0 20 18.93 V9.07 A1.07 1.07 0 0 0 18.93 8 H16\" />",
|
|
80
97
|
'corbeille': "<path d=\"M4 6.67 H20\" /><path d=\"M9.33 6.67 V4.67 A1.33 1.33 0 0 1 10.67 3.33 H13.33 A1.33 1.33 0 0 1 14.67 4.67 V6.67\" /><path d=\"M6 6.67 L6.93 18.93 A1.33 1.33 0 0 0 8.27 20 H15.73 A1.33 1.33 0 0 0 17.07 18.93 L18 6.67\" /><path d=\"M10 10.67 V16.67\" /><path d=\"M14 10.67 V16.67\" />",
|
|
@@ -95,25 +112,38 @@ export const CORPS: Record<IconId, string> = {
|
|
|
95
112
|
'filtre': "<path d=\"M2.67 4 H21.33 L14.67 12.27 V18.67 L9.33 21.33 V12.27 Z\" />",
|
|
96
113
|
'globe': "<circle cx=\"12\" cy=\"12\" r=\"8.67\" /><path d=\"M3.33 12 H20.67\" /><path d=\"M12 3.33 C14.22 5.64 15.47 8.71 15.47 12 C15.47 15.29 14.22 18.36 12 20.67 C9.78 18.36 8.53 15.29 8.53 12 C8.53 8.71 9.78 5.64 12 3.33 Z\" />",
|
|
97
114
|
'graphique': "<path d=\"M4 4 V20 H20\" /><path d=\"M8.67 20 V12.67\" /><path d=\"M12.67 20 V8\" /><path d=\"M16.67 20 V15.33\" />",
|
|
115
|
+
'gras': "<path d=\"M7 4 H13 C15.2 4 16.5 5.3 16.5 7.5 C16.5 9.7 15.2 11 13 11 H7 Z\" /><path d=\"M7 11 H14 C16.2 11 17.5 12.5 17.5 15 C17.5 17.5 16.2 19 14 19 H7 Z\" />",
|
|
98
116
|
'horloge': "<circle cx=\"12\" cy=\"12\" r=\"8\" /><path d=\"M12 6.67 V12 L15.33 14\" />",
|
|
117
|
+
'image': "<path d=\"M3.5 5 H20.5 V19 H3.5 Z\" /><path d=\"M3.5 16 L9 10.5 L13.5 15 L16 12.5 L20.5 17\" /><path d=\"M15 8.5 H15.01\" />",
|
|
99
118
|
'imprimante': "<path d=\"M6.67 8 V3.33 H17.33 V8\" /><path d=\"M6.67 17.33 H4.67 A1.33 1.33 0 0 1 3.33 16 V10.67 A1.33 1.33 0 0 1 4.67 9.33 H19.33 A1.33 1.33 0 0 1 20.67 10.67 V16 A1.33 1.33 0 0 1 19.33 17.33 H17.33\" /><rect x=\"6.67\" y=\"13.33\" width=\"10.67\" height=\"7.33\" />",
|
|
100
119
|
'info': "<circle cx=\"12\" cy=\"12\" r=\"8.67\" /><path d=\"M12 11.33 V16\" /><rect x=\"11.2\" y=\"7.2\" width=\"1.6\" height=\"1.6\" fill=\"currentColor\" stroke=\"none\" />",
|
|
120
|
+
'italique': "<path d=\"M10 5 H18\" /><path d=\"M6 19 H14\" /><path d=\"M14.5 5 L9.5 19\" />",
|
|
121
|
+
'lecture': "<path d=\"M8 5 L19 12 L8 19 Z\" fill=\"currentColor\" stroke=\"none\" />",
|
|
101
122
|
'lien-externe': "<path d=\"M10.67 4 H4 V20 H20 V13.33\" /><path d=\"M14.67 4 H20 V9.33\" /><path d=\"M20 4 L12 12\" />",
|
|
123
|
+
'liste-a-puces': "<path d=\"M9 6.5 H20\" /><path d=\"M9 12 H20\" /><path d=\"M9 17.5 H20\" /><path d=\"M4 5.5 H6 V7.5 H4 Z\" fill=\"currentColor\" stroke=\"none\" /><path d=\"M4 11 H6 V13 H4 Z\" fill=\"currentColor\" stroke=\"none\" /><path d=\"M4 16.5 H6 V18.5 H4 Z\" fill=\"currentColor\" stroke=\"none\" />",
|
|
102
124
|
'livre-ouvert': "<path d=\"M2.67 5.33 C5.33 4.67 7.78 4.89 12 6.67 C16.22 4.89 18.67 4.67 21.33 5.33 V18 C18.67 17.33 16.22 17.56 12 19.33 C7.78 17.56 5.33 17.33 2.67 18 Z\" /><path d=\"M12 6.67 V19.33\" />",
|
|
103
125
|
'menu': "<path d=\"M0 5.33 H24\" /><path d=\"M0 12 H24\" /><path d=\"M0 18.67 H24\" />",
|
|
104
126
|
'moins': "<path d=\"M4 12 H20\" />",
|
|
127
|
+
'muet': "<path d=\"M4 9.5 H7.5 L12 5.5 V18.5 L7.5 14.5 H4 Z\" /><path d=\"M16 10 L21 14\" /><path d=\"M21 10 L16 14\" />",
|
|
105
128
|
'oeil': "<path d=\"M2 12 C5.33 6.67 8.67 4.67 12 4.67 C15.33 4.67 18.67 6.67 22 12 C18.67 17.33 15.33 19.33 12 19.33 C8.67 19.33 5.33 17.33 2 12 Z\" /><circle cx=\"12\" cy=\"12\" r=\"2.67\" />",
|
|
129
|
+
'oeil-barre': "<path d=\"M3 12 C5.5 7.5 8.6 5.5 12 5.5 C15.4 5.5 18.5 7.5 21 12 C18.5 16.5 15.4 18.5 12 18.5 C8.6 18.5 5.5 16.5 3 12 Z\" /><path d=\"M9.5 12 A2.5 2.5 0 0 1 14.5 12 A2.5 2.5 0 0 1 9.5 12 Z\" /><path d=\"M4 20 L20 4\" />",
|
|
130
|
+
'pause': "<path d=\"M9 5 H11 V19 H9 Z\" fill=\"currentColor\" stroke=\"none\" /><path d=\"M13 5 H15 V19 H13 Z\" fill=\"currentColor\" stroke=\"none\" />",
|
|
131
|
+
'plein-ecran': "<path d=\"M4 9 V4 H9\" /><path d=\"M20 9 V4 H15\" /><path d=\"M4 15 V20 H9\" /><path d=\"M20 15 V20 H15\" />",
|
|
106
132
|
'plus': "<path d=\"M12 4 V20\" /><path d=\"M4 12 H20\" />",
|
|
107
133
|
'recherche': "<circle cx=\"10.67\" cy=\"10.67\" r=\"6\" /><path d=\"M15.33 15.33 L20 20\" />",
|
|
108
134
|
'registre': "<rect x=\"3.33\" y=\"5.33\" width=\"17.33\" height=\"5.33\" /><rect x=\"3.33\" y=\"13.33\" width=\"17.33\" height=\"5.33\" /><rect x=\"5.87\" y=\"7.2\" width=\"1.6\" height=\"1.6\" fill=\"currentColor\" stroke=\"none\" /><rect x=\"5.87\" y=\"15.2\" width=\"1.6\" height=\"1.6\" fill=\"currentColor\" stroke=\"none\" />",
|
|
109
135
|
'reglages': "<circle cx=\"12\" cy=\"12\" r=\"2.93\" /><path d=\"M12 2 V4.67 M12 19.33 V22 M2 12 H4.67 M19.33 12 H22 M4.8 4.8 L6.67 6.67 M17.33 17.33 L19.2 19.2 M19.2 4.8 L17.33 6.67 M6.67 17.33 L4.8 19.2\" />",
|
|
136
|
+
'rembobiner': "<path d=\"M11 6 L4 12 L11 18 Z\" fill=\"currentColor\" stroke=\"none\" /><path d=\"M20 6 L13 12 L20 18 Z\" fill=\"currentColor\" stroke=\"none\" />",
|
|
110
137
|
'reseau': "<circle cx=\"12\" cy=\"12\" r=\"8\" /><path d=\"M4 12 H20\" /><path d=\"M12 4 C14.67 8 14.67 16 12 20\" /><path d=\"M12 4 C9.33 8 9.33 16 12 20\" />",
|
|
138
|
+
'signet': "<path d=\"M6 4 H18 V20 L12 15.5 L6 20 Z\" />",
|
|
139
|
+
'son': "<path d=\"M4 9.5 H7.5 L12 5.5 V18.5 L7.5 14.5 H4 Z\" /><path d=\"M16 9 C17.5 10.2 17.5 13.8 16 15\" /><path d=\"M18.8 6.6 C21.4 9 21.4 15 18.8 17.4\" />",
|
|
111
140
|
'taches': "<path d=\"M4.67 6.67 L6.67 8.67 L10 5.33\" /><path d=\"M4.67 16 L6.67 18 L10 14.67\" /><path d=\"M13.33 7.33 H20\" /><path d=\"M13.33 16.67 H20\" />",
|
|
112
141
|
'telecharger': "<path d=\"M12 3.33 V15.33\" /><polyline points=\"6.67,10 12,15.33 17.33,10\" /><path d=\"M4.67 20.67 H19.33\" />",
|
|
113
142
|
'telephone': "<path d=\"M20.67 16.93 V19.33 A1.6 1.6 0 0 1 18.93 20.93 C16.13 20.67 13.47 19.67 11.2 18.13 C9.09 16.71 7.29 14.91 5.87 12.8 C4.33 10.52 3.33 7.85 3.07 5.05 A1.6 1.6 0 0 1 4.67 3.33 H7.07 A1.6 1.6 0 0 1 8.67 4.71 C8.79 5.83 9.04 6.93 9.4 7.97 A1.6 1.6 0 0 1 9.04 9.65 L8 10.69 C9.32 13.01 11.03 14.71 13.33 16 L14.37 14.96 A1.6 1.6 0 0 1 16.05 14.6 C17.09 14.96 18.19 15.21 19.31 15.33 A1.6 1.6 0 0 1 20.67 16.93 Z\" />",
|
|
114
143
|
'tri': "<path d=\"M8 4 V20\" /><path d=\"M4.67 7.33 L8 4 L11.33 7.33\" /><path d=\"M16 20 V4\" /><path d=\"M12.67 16.67 L16 20 L19.33 16.67\" />",
|
|
115
144
|
'trois-points': "<rect x=\"4\" y=\"10.67\" width=\"2.66\" height=\"2.66\" fill=\"currentColor\" stroke=\"none\" /><rect x=\"10.67\" y=\"10.67\" width=\"2.66\" height=\"2.66\" fill=\"currentColor\" stroke=\"none\" /><rect x=\"17.34\" y=\"10.67\" width=\"2.66\" height=\"2.66\" fill=\"currentColor\" stroke=\"none\" />",
|
|
116
145
|
'utilisateur': "<circle cx=\"12\" cy=\"8\" r=\"3.33\" /><path d=\"M5.33 20 C5.33 15.33 8.33 13.33 12 13.33 C15.67 13.33 18.67 15.33 18.67 20\" />",
|
|
146
|
+
'video': "<path d=\"M3.5 6 H15 V18 H3.5 Z\" /><path d=\"M15 10 L20.5 7 V17 L15 14 Z\" />",
|
|
117
147
|
}
|
|
118
148
|
|
|
119
149
|
/** Nom lisible de chaque icône — sert de titre accessible par défaut à
|
|
@@ -125,6 +155,7 @@ export const NOMS: Record<IconId, string> = {
|
|
|
125
155
|
'app-couches': "Application (couches)",
|
|
126
156
|
'archiver': "Archiver",
|
|
127
157
|
'attention': "Attention (avertissement)",
|
|
158
|
+
'avancer': "Avancer",
|
|
128
159
|
'balance': "Balance (justice)",
|
|
129
160
|
'base-de-donnees': "Base de données",
|
|
130
161
|
'bouclier-verifie': "Bouclier vérifié (authentification)",
|
|
@@ -135,6 +166,7 @@ export const NOMS: Record<IconId, string> = {
|
|
|
135
166
|
'chevron-droit': "Chevron droit",
|
|
136
167
|
'chevron-gauche': "Chevron gauche",
|
|
137
168
|
'chevron-haut': "Chevron haut",
|
|
169
|
+
'citation': "Citation",
|
|
138
170
|
'coche': "Coche",
|
|
139
171
|
'copier': "Copier",
|
|
140
172
|
'corbeille': "Corbeille (supprimer)",
|
|
@@ -155,23 +187,36 @@ export const NOMS: Record<IconId, string> = {
|
|
|
155
187
|
'filtre': "Filtre",
|
|
156
188
|
'globe': "Globe (international)",
|
|
157
189
|
'graphique': "Graphique (barres)",
|
|
190
|
+
'gras': "Gras",
|
|
158
191
|
'horloge': "Horloge (intégration continue)",
|
|
192
|
+
'image': "Image",
|
|
159
193
|
'imprimante': "Imprimante",
|
|
160
194
|
'info': "Information",
|
|
195
|
+
'italique': "Italique",
|
|
196
|
+
'lecture': "Lecture",
|
|
161
197
|
'lien-externe': "Lien externe",
|
|
198
|
+
'liste-a-puces': "Liste à puces",
|
|
162
199
|
'livre-ouvert': "Livre ouvert (formation)",
|
|
163
200
|
'menu': "Menu (hamburger)",
|
|
164
201
|
'moins': "Moins",
|
|
202
|
+
'muet': "Muet",
|
|
165
203
|
'oeil': "Œil (afficher)",
|
|
204
|
+
'oeil-barre': "Œil barré",
|
|
205
|
+
'pause': "Pause",
|
|
206
|
+
'plein-ecran': "Plein écran",
|
|
166
207
|
'plus': "Plus",
|
|
167
208
|
'recherche': "Recherche (loupe)",
|
|
168
209
|
'registre': "Registre (serveurs empilés)",
|
|
169
210
|
'reglages': "Réglages",
|
|
211
|
+
'rembobiner': "Rembobiner",
|
|
170
212
|
'reseau': "Réseau (entrée / globe)",
|
|
213
|
+
'signet': "Signet",
|
|
214
|
+
'son': "Son",
|
|
171
215
|
'taches': "Tâches (liste à cocher)",
|
|
172
216
|
'telecharger': "Télécharger",
|
|
173
217
|
'telephone': "Téléphone",
|
|
174
218
|
'tri': "Tri",
|
|
175
219
|
'trois-points': "Trois points (menu contextuel)",
|
|
176
220
|
'utilisateur': "Utilisateur",
|
|
221
|
+
'video': "Vidéo",
|
|
177
222
|
}
|
package/react/layout.tsx
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// Tout y est sans état.
|
|
6
6
|
|
|
7
7
|
import type {
|
|
8
|
+
AnchorHTMLAttributes,
|
|
8
9
|
ButtonHTMLAttributes,
|
|
9
10
|
CSSProperties,
|
|
10
11
|
ElementType,
|
|
@@ -162,8 +163,14 @@ export function NavLinks({ className, ...reste }: Div & { className?: string })
|
|
|
162
163
|
return <div className={cx('zv-nav__links', className)} {...reste} />
|
|
163
164
|
}
|
|
164
165
|
|
|
166
|
+
/** Les composants qui rendent un `<a>` sont typés sur
|
|
167
|
+
* `AnchorHTMLAttributes` et non `HTMLAttributes` : sans quoi ils refusent
|
|
168
|
+
* `target`, `rel`, `download` et `hreflang`. Un lien sortant ne peut alors
|
|
169
|
+
* pas porter `rel="noopener"`, et un lien qui doit s'ouvrir à côté ne le
|
|
170
|
+
* peut pas non plus — une app consommatrice a dû écrire la classe à la main
|
|
171
|
+
* pour cette seule raison. (0.19.0) */
|
|
165
172
|
export interface NavLinkProps
|
|
166
|
-
extends Omit<
|
|
173
|
+
extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'className'> {
|
|
167
174
|
/** Lien secondaire : connexion, mentions. */
|
|
168
175
|
discret?: boolean
|
|
169
176
|
href?: string
|
|
@@ -200,7 +207,7 @@ export function NavDrawerLink({
|
|
|
200
207
|
courant,
|
|
201
208
|
className,
|
|
202
209
|
...reste
|
|
203
|
-
}: Omit<
|
|
210
|
+
}: Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'className'> & {
|
|
204
211
|
courant?: boolean
|
|
205
212
|
href?: string
|
|
206
213
|
className?: string
|
|
@@ -287,7 +294,7 @@ export function Langue({
|
|
|
287
294
|
courante,
|
|
288
295
|
className,
|
|
289
296
|
...reste
|
|
290
|
-
}: Omit<
|
|
297
|
+
}: Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'className'> & {
|
|
291
298
|
courante?: boolean
|
|
292
299
|
href?: string
|
|
293
300
|
className?: string
|
|
@@ -389,7 +396,7 @@ export function RailItem({
|
|
|
389
396
|
className,
|
|
390
397
|
children,
|
|
391
398
|
...reste
|
|
392
|
-
}: Omit<
|
|
399
|
+
}: Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'className'> & {
|
|
393
400
|
courant?: boolean
|
|
394
401
|
href: string
|
|
395
402
|
className?: string
|
package/react/typography.tsx
CHANGED
|
@@ -6,7 +6,12 @@
|
|
|
6
6
|
// balise un choix de structure. Les confondre casse le plan du document pour
|
|
7
7
|
// un lecteur d'écran sans que rien ne se voie à l'écran.
|
|
8
8
|
|
|
9
|
-
import type {
|
|
9
|
+
import type {
|
|
10
|
+
AnchorHTMLAttributes,
|
|
11
|
+
ElementType,
|
|
12
|
+
HTMLAttributes,
|
|
13
|
+
ReactNode,
|
|
14
|
+
} from 'react'
|
|
10
15
|
import { cx } from './cx.js'
|
|
11
16
|
|
|
12
17
|
type Div = Omit<HTMLAttributes<HTMLElement>, 'className'>
|
|
@@ -122,12 +127,17 @@ export function Em({
|
|
|
122
127
|
)
|
|
123
128
|
}
|
|
124
129
|
|
|
130
|
+
/** Les composants qui rendent un `<a>` sont typés sur
|
|
131
|
+
* `AnchorHTMLAttributes` et non `HTMLAttributes` : sans quoi ils refusent
|
|
132
|
+
* `target`, `rel`, `download` et `hreflang`. Un lien sortant ne peut alors
|
|
133
|
+
* pas porter `rel="noopener"`, et un lien qui doit s'ouvrir à côté ne le
|
|
134
|
+
* peut pas non plus — une app consommatrice a dû écrire la classe à la main
|
|
135
|
+
* pour cette seule raison. (0.19.0) */
|
|
125
136
|
export function Link({
|
|
126
137
|
className,
|
|
127
138
|
...reste
|
|
128
|
-
}: Omit<
|
|
139
|
+
}: Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'className'> & {
|
|
129
140
|
className?: string
|
|
130
|
-
href?: string
|
|
131
141
|
}) {
|
|
132
142
|
return <a className={cx('zv-link', className)} {...reste} />
|
|
133
143
|
}
|
package/src/base.css
CHANGED
|
@@ -160,6 +160,13 @@ a:not([class]):hover {
|
|
|
160
160
|
.zv-em {
|
|
161
161
|
color: var(--accent-deep);
|
|
162
162
|
font-weight: 400;
|
|
163
|
+
/* Le composant `Em` rend un vrai <em>, que le navigateur penche par
|
|
164
|
+
* défaut — et AUCUNE italique n'est chargée : Outfit n'en a pas, il en
|
|
165
|
+
* fabrique donc une oblique de synthèse. Sur un titre de 76px, ça se voit.
|
|
166
|
+
* La charte ne demande à cette classe qu'un changement de couleur et de
|
|
167
|
+
* graisse ; on remet donc la droite. (`.zv-inset em` portait déjà cette
|
|
168
|
+
* règle : elle vit désormais là où le besoin est structurel.) */
|
|
169
|
+
font-style: normal;
|
|
163
170
|
}
|
|
164
171
|
|
|
165
172
|
/* Sur fond sombre l'accent ne change pas de couleur mais de graisse. */
|
package/src/components.css
CHANGED
|
@@ -41,10 +41,34 @@
|
|
|
41
41
|
box-shadow 160ms cubic-bezier(0.2, 0.7, 0.2, 1);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
/* ─── Le plein ne s'applique QUE si aucune variante n'est posée ────────
|
|
45
|
+
*
|
|
46
|
+
* `zv-btn`, `zv-btn--ghost`, `zv-btn--ink` et `zv-btn--danger` sont quatre
|
|
47
|
+
* classes AUTONOMES et mutuellement exclusives : le socle commun ci-dessus
|
|
48
|
+
* les groupe dans un même sélecteur, ce qui leur donne exactement l'air
|
|
49
|
+
* d'une base et de ses modificateurs. `Button` n'en rend jamais qu'une —
|
|
50
|
+
* mais une app qui écrit ses classes à la main lit du BEM et compose les
|
|
51
|
+
* deux. C'est arrivé (mcp-factory, 0.19.0), et le résultat était vicieux :
|
|
52
|
+
* `.zv-btn:hover` (0,2,0) l'emportait sur `.zv-btn--ghost` (0,1,0), d'où un
|
|
53
|
+
* fond indigo sous un texte encre — illisible, et seulement AU SURVOL, donc
|
|
54
|
+
* invisible en relecture comme en capture.
|
|
55
|
+
*
|
|
56
|
+
* Le `:not(:where(…))` dit ce que le système voulait déjà dire : ces quatre
|
|
57
|
+
* classes s'excluent. `:where()` a une spécificité NULLE — la garde ne
|
|
58
|
+
* change donc aucun arbitrage existant, et une app qui surcharge `.zv-btn`
|
|
59
|
+
* continue de gagner exactement comme avant.
|
|
60
|
+
*
|
|
61
|
+
* ⚠️ À reporter sur toute règle future qui peint le bouton plein. */
|
|
62
|
+
|
|
63
|
+
.zv-btn:not(:where(.zv-btn--ghost, .zv-btn--ink, .zv-btn--danger)) {
|
|
64
|
+
/* Le sommet du dégradé. RELEVÉ dans Main.html à #2b2bb4, mais DÉRIVÉ de
|
|
65
|
+
* --accent depuis la 0.19.0 : la déclaration étant portée par le bouton
|
|
66
|
+
* lui-même, une redéfinition de marque héritée d'un conteneur ne
|
|
67
|
+
* l'atteignait pas — un cabinet en marque blanche obtenait un dégradé
|
|
68
|
+
* allant de l'indigo Zevra à SA couleur. Pour la charte par défaut,
|
|
69
|
+
* l'écart avec la valeur relevée est d'un point de bleu, invisible.
|
|
70
|
+
* Les états de survol le dérivent ensuite par color-mix. */
|
|
71
|
+
--zv-btn-haut: var(--accent);
|
|
48
72
|
background: linear-gradient(180deg, var(--zv-btn-haut) 0%, var(--accent-deep) 100%);
|
|
49
73
|
color: var(--white);
|
|
50
74
|
/* Le liseré interne fait tout le galbe du bouton : il est dans Main.html
|
|
@@ -88,7 +112,7 @@
|
|
|
88
112
|
* chose.
|
|
89
113
|
* Déclarés AVANT [disabled], qui doit l'emporter à spécificité égale. */
|
|
90
114
|
|
|
91
|
-
.zv-btn:hover {
|
|
115
|
+
.zv-btn:not(:where(.zv-btn--ghost, .zv-btn--ink, .zv-btn--danger)):hover {
|
|
92
116
|
background: linear-gradient(
|
|
93
117
|
180deg,
|
|
94
118
|
color-mix(in oklab, var(--zv-btn-haut) 86%, var(--ink)) 0%,
|
|
@@ -96,7 +120,7 @@
|
|
|
96
120
|
);
|
|
97
121
|
}
|
|
98
122
|
|
|
99
|
-
.zv-btn:active {
|
|
123
|
+
.zv-btn:not(:where(.zv-btn--ghost, .zv-btn--ink, .zv-btn--danger)):active {
|
|
100
124
|
background: linear-gradient(
|
|
101
125
|
180deg,
|
|
102
126
|
color-mix(in oklab, var(--zv-btn-haut) 72%, var(--ink)) 0%,
|
|
@@ -177,8 +201,8 @@
|
|
|
177
201
|
* désactivé OU occupé (dont le clic est avalé par la façade) : sans ces
|
|
178
202
|
* règles, les états ci-dessus repeignent le fond et le bouton a l'air
|
|
179
203
|
* actif. Même précaution que les contrôles désactivés de forms.css. */
|
|
180
|
-
.zv-btn[disabled]:is(:hover, :active),
|
|
181
|
-
.zv-btn[aria-busy='true']:is(:hover, :active) {
|
|
204
|
+
.zv-btn:not(:where(.zv-btn--ghost, .zv-btn--ink, .zv-btn--danger))[disabled]:is(:hover, :active),
|
|
205
|
+
.zv-btn:not(:where(.zv-btn--ghost, .zv-btn--ink, .zv-btn--danger))[aria-busy='true']:is(:hover, :active) {
|
|
182
206
|
background: linear-gradient(180deg, var(--zv-btn-haut) 0%, var(--accent-deep) 100%);
|
|
183
207
|
}
|
|
184
208
|
|
|
@@ -911,6 +935,13 @@
|
|
|
911
935
|
|
|
912
936
|
|
|
913
937
|
@media (max-width: 767px) {
|
|
938
|
+
|
|
939
|
+
/* Le `min-width: 260px` de la valeur ne tient pas sous le seuil : dans une
|
|
940
|
+
* carte de 215px — un écran de 320px — elle débordait de 45px. La CLÉ
|
|
941
|
+
* était déjà libérée (flex-basis 100%), il manquait la valeur. */
|
|
942
|
+
.zv-rows__val {
|
|
943
|
+
min-width: 0;
|
|
944
|
+
}
|
|
914
945
|
.zv-btn--sm {
|
|
915
946
|
height: 36px;
|
|
916
947
|
padding: 0 14px;
|
|
@@ -1029,3 +1060,258 @@
|
|
|
1029
1060
|
.zv-lockup--marque-seule .zv-lockup__word {
|
|
1030
1061
|
display: none;
|
|
1031
1062
|
}
|
|
1063
|
+
|
|
1064
|
+
/* ─── Cadre média ───────────────────────────────────────────────────────
|
|
1065
|
+
* HORS RELEVÉ (27/08/2026, 0.18.0). Aucune des dix planches ne montre
|
|
1066
|
+
* d'image de contenu — elles sont composées, pas photographiées. Le manque
|
|
1067
|
+
* était pourtant total : pas un `aspect-ratio`, pas un `object-fit` dans le
|
|
1068
|
+
* paquet, et quatre réécritures du même cadre chez un seul consommateur.
|
|
1069
|
+
*
|
|
1070
|
+
* ⚠️ Le rapport vit sur le CADRE, jamais sur l'image. Posé sur un enfant de
|
|
1071
|
+
* grille aligné au centre, il ne se résout pas et la colonne s'effondre à
|
|
1072
|
+
* zéro — c'est un correctif de production, pas une précaution théorique.
|
|
1073
|
+
*
|
|
1074
|
+
* Le fond est posé et non laissé transparent : une image qui tarde, échoue
|
|
1075
|
+
* ou porte de la transparence laisserait voir la surface du dessous, soit un
|
|
1076
|
+
* trou blanc sur une carte, soit un trou sombre sur une bande. */
|
|
1077
|
+
|
|
1078
|
+
.zv-media {
|
|
1079
|
+
position: relative;
|
|
1080
|
+
display: block;
|
|
1081
|
+
width: 100%;
|
|
1082
|
+
overflow: hidden;
|
|
1083
|
+
background: var(--hairline);
|
|
1084
|
+
/* Angle vif comme le reste ; aucune ombre, l'image est dans le flux. */
|
|
1085
|
+
border-radius: 0;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
/* Les quatre rapports du système. Un cinquième se demande, il ne s'invente
|
|
1089
|
+
* pas : c'est ainsi qu'une bibliothèque finit avec dix-sept rapports dont
|
|
1090
|
+
* trois servent. */
|
|
1091
|
+
.zv-media--16-9 {
|
|
1092
|
+
aspect-ratio: 16 / 9;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
.zv-media--4-3 {
|
|
1096
|
+
aspect-ratio: 4 / 3;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
.zv-media--1-1 {
|
|
1100
|
+
aspect-ratio: 1 / 1;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
.zv-media--3-2 {
|
|
1104
|
+
aspect-ratio: 3 / 2;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
/* L'image REMPLIT le cadre : c'est le seul comportement qui le garantisse
|
|
1108
|
+
* plein quelle que soit la source, et une grille dont les couvertures ne
|
|
1109
|
+
* s'alignent pas se voit aussitôt. En absolu, pour que le cadre garde la
|
|
1110
|
+
* main sur sa hauteur. */
|
|
1111
|
+
.zv-media__img {
|
|
1112
|
+
position: absolute;
|
|
1113
|
+
inset: 0;
|
|
1114
|
+
width: 100%;
|
|
1115
|
+
height: 100%;
|
|
1116
|
+
object-fit: cover;
|
|
1117
|
+
display: block;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
/* Le cas inverse — un logo, un schéma, une pièce qu'on ne peut pas rogner.
|
|
1121
|
+
* Le papier passe derrière : il restera du vide, autant qu'il soit choisi. */
|
|
1122
|
+
.zv-media--contient {
|
|
1123
|
+
background: var(--paper);
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
.zv-media--contient .zv-media__img {
|
|
1127
|
+
object-fit: contain;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
/* Le coin d'un cadre : durée d'une vidéo, nombre de pages, mention de
|
|
1131
|
+
* réserve. Encre diluée et non un gris opaque — le fond d'image est
|
|
1132
|
+
* imprévisible, et l'encre de charte s'y pose sans jurer. */
|
|
1133
|
+
.zv-media__coin {
|
|
1134
|
+
position: absolute;
|
|
1135
|
+
right: 8px;
|
|
1136
|
+
bottom: 8px;
|
|
1137
|
+
z-index: 1;
|
|
1138
|
+
display: inline-flex;
|
|
1139
|
+
align-items: center;
|
|
1140
|
+
gap: 4px;
|
|
1141
|
+
padding: 3px 7px;
|
|
1142
|
+
background: color-mix(in srgb, var(--ink) 72%, transparent);
|
|
1143
|
+
color: var(--white);
|
|
1144
|
+
font-family: var(--font-mono);
|
|
1145
|
+
font-size: var(--mono);
|
|
1146
|
+
font-weight: 500;
|
|
1147
|
+
letter-spacing: 0.08em;
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
.zv-media__coin--gauche {
|
|
1151
|
+
right: auto;
|
|
1152
|
+
left: 8px;
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
.zv-media__coin--haut {
|
|
1156
|
+
bottom: auto;
|
|
1157
|
+
top: 8px;
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
/* Voile de lecture : un titre posé SUR une image n'est lisible qu'au-dessus
|
|
1161
|
+
* d'un dégradé. Il part du bas, là où le texte se pose, et n'assombrit pas
|
|
1162
|
+
* le sujet. Il ne capte pas le pointeur — le cadre reste cliquable. */
|
|
1163
|
+
.zv-media__voile {
|
|
1164
|
+
position: absolute;
|
|
1165
|
+
inset: 0;
|
|
1166
|
+
z-index: 1;
|
|
1167
|
+
pointer-events: none;
|
|
1168
|
+
background: linear-gradient(
|
|
1169
|
+
180deg,
|
|
1170
|
+
transparent 40%,
|
|
1171
|
+
color-mix(in srgb, var(--ink) 78%, transparent) 100%
|
|
1172
|
+
);
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
/* ─── Page légale ───────────────────────────────────────────────────────
|
|
1176
|
+
* HORS RELEVÉ (27/08/2026, voir DECISIONS.md). La forme d'un document
|
|
1177
|
+
* contractuel — CGVU, mentions légales, DPA. Le TEXTE, lui, n'est pas ici :
|
|
1178
|
+
* il vit dans @zevra/legal, versionné et archivé. Ce module ne porte que la
|
|
1179
|
+
* mise en page ; c'est ce qui permet au même texte de s'afficher sur la
|
|
1180
|
+
* vitrine et dans une application sans exister en deux exemplaires.
|
|
1181
|
+
*
|
|
1182
|
+
* Presque tout se compose de pièces existantes : le sommaire est .zv-rail,
|
|
1183
|
+
* les définitions .zv-rows, les tableaux .zv-table, les encarts .zv-callout.
|
|
1184
|
+
* Ne restent ici que la colonne de lecture et ce que les listes de texte
|
|
1185
|
+
* courant n'avaient jamais eu. */
|
|
1186
|
+
|
|
1187
|
+
.zv-legal {
|
|
1188
|
+
display: flex;
|
|
1189
|
+
flex-direction: column;
|
|
1190
|
+
gap: 48px;
|
|
1191
|
+
/* La MESURE, et c'est la seule règle qui compte vraiment pour un contrat :
|
|
1192
|
+
* au-delà d'environ 80 signes par ligne, l'œil perd le début de la ligne
|
|
1193
|
+
* suivante — sur un texte qu'on lit déjà à reculons, c'est rédhibitoire. */
|
|
1194
|
+
max-width: 72ch;
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
.zv-legal__section {
|
|
1198
|
+
display: flex;
|
|
1199
|
+
flex-direction: column;
|
|
1200
|
+
gap: 14px;
|
|
1201
|
+
/* Un lien vers un article précis ne doit pas déposer son titre sous la
|
|
1202
|
+
* barre fixe. Sans cette réserve, cliquer « Art. 7 » dans le sommaire
|
|
1203
|
+
* affiche le corps de l'article et cache son intitulé. */
|
|
1204
|
+
scroll-margin-top: 88px;
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
/* Les listes du texte courant. Le paquet n'en avait aucune : ses listes
|
|
1208
|
+
* étaient toutes des objets (étapes, sommaires numérotés, rangées à filets),
|
|
1209
|
+
* jamais l'énumération d'une clause. */
|
|
1210
|
+
.zv-legal__liste {
|
|
1211
|
+
margin: 0;
|
|
1212
|
+
padding-left: 22px;
|
|
1213
|
+
display: flex;
|
|
1214
|
+
flex-direction: column;
|
|
1215
|
+
gap: 8px;
|
|
1216
|
+
font-size: var(--body);
|
|
1217
|
+
line-height: 1.6;
|
|
1218
|
+
color: var(--muted);
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
.zv-legal__liste li::marker {
|
|
1222
|
+
color: var(--accent-line);
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
/* Le renvoi vers un autre document contractuel, dans le fil d'une clause :
|
|
1226
|
+
* souligné, parce qu'à l'intérieur d'un paragraphe la couleur seule ne
|
|
1227
|
+
* suffit pas à annoncer qu'on change de contrat. */
|
|
1228
|
+
.zv-legal a {
|
|
1229
|
+
color: var(--accent);
|
|
1230
|
+
text-decoration: underline;
|
|
1231
|
+
text-underline-offset: 2px;
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
/* Le tableau d'un contrat (durées de conservation, sous-traitants). Il n'
|
|
1235
|
+
* emprunte PAS .zv-table de data.css : celui-là est une surface de travail
|
|
1236
|
+
* dont les rangées se survolent et se cliquent, ce qu'un tableau de contrat
|
|
1237
|
+
* ne fait jamais. Filets, chiffres alignés, et rien de plus. */
|
|
1238
|
+
.zv-legal__table {
|
|
1239
|
+
width: 100%;
|
|
1240
|
+
border-collapse: collapse;
|
|
1241
|
+
font-size: var(--app);
|
|
1242
|
+
line-height: 1.55;
|
|
1243
|
+
color: var(--ink-2);
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
.zv-legal__table th {
|
|
1247
|
+
border-bottom: 1px solid var(--line);
|
|
1248
|
+
padding: 8px 12px 8px 0;
|
|
1249
|
+
text-align: left;
|
|
1250
|
+
font-family: var(--font-mono);
|
|
1251
|
+
font-size: var(--mono);
|
|
1252
|
+
font-weight: 600;
|
|
1253
|
+
letter-spacing: 0.14em;
|
|
1254
|
+
text-transform: uppercase;
|
|
1255
|
+
color: var(--label);
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
.zv-legal__table td {
|
|
1259
|
+
border-bottom: 1px solid var(--hairline);
|
|
1260
|
+
padding: 10px 12px 10px 0;
|
|
1261
|
+
vertical-align: top;
|
|
1262
|
+
font-variant-numeric: tabular-nums;
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
/* L'en-tête : titre, date d'entrée en vigueur, identifiant de version.
|
|
1266
|
+
* ⚠️ La VERSION est affichée, et ce n'est pas décoratif : c'est ce que
|
|
1267
|
+
* l'utilisateur cite quand il conteste, et ce que le support lui demande. */
|
|
1268
|
+
.zv-legal__tete {
|
|
1269
|
+
display: flex;
|
|
1270
|
+
flex-direction: column;
|
|
1271
|
+
gap: 10px;
|
|
1272
|
+
border-bottom: 1px solid var(--line);
|
|
1273
|
+
padding-bottom: 24px;
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
@media (max-width: 767px) {
|
|
1277
|
+
.zv-legal {
|
|
1278
|
+
gap: 36px;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
.zv-legal__section {
|
|
1282
|
+
scroll-margin-top: calc(var(--topbar-h) + 12px);
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
/* Encart d'accompagnement d'une clause : la reformulation en langage courant
|
|
1287
|
+
* (« En clair ») ou le point à ne pas manquer. Il COMMENTE la clause et ne
|
|
1288
|
+
* la remplace pas — d'où une surface d'accompagnement, et non l'aplat d'une
|
|
1289
|
+
* alerte, qui annoncerait un incident.
|
|
1290
|
+
* Il vit ici et non dans feedback.css : une page légale de vitrine n'a pas à
|
|
1291
|
+
* charger la couche applicative pour afficher une glose. */
|
|
1292
|
+
.zv-legal__encart {
|
|
1293
|
+
display: flex;
|
|
1294
|
+
flex-direction: column;
|
|
1295
|
+
gap: 6px;
|
|
1296
|
+
border-left: 2px solid var(--accent-line);
|
|
1297
|
+
background: var(--panel);
|
|
1298
|
+
padding: 14px 18px;
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
.zv-legal__encart--important {
|
|
1302
|
+
border-left-color: var(--warn);
|
|
1303
|
+
background: var(--warn-soft);
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
.zv-legal__encart-label {
|
|
1307
|
+
font-family: var(--font-mono);
|
|
1308
|
+
font-size: var(--mono);
|
|
1309
|
+
font-weight: 700;
|
|
1310
|
+
letter-spacing: 0.14em;
|
|
1311
|
+
text-transform: uppercase;
|
|
1312
|
+
color: var(--label);
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
.zv-legal__encart--important .zv-legal__encart-label {
|
|
1316
|
+
color: var(--warn-ink);
|
|
1317
|
+
}
|