card-01-ghost-icon
card-06-forecast-timeline
Carte prévision — timeline + sous-cartes
Raconter une trajectoire dans une carte : une timeline verticale de jalons datés à gauche, et à droite deux sous-cartes teintées qui opposent la valeur constatée (menthe, présent) à la projection (lilas, futur).
cardslideweb748×616px10 benchmarks
Le fragment RÉEL, dans son propre document, sur le sol de sa charte — pas une image. Ce que vous voyez est exactement ce que vous collerez.
Employer quand
Carte « perspective » d'un dashboard : quelques jalons dans le temps plus deux chiffres clés, l'un acquis l'autre projeté. Le code couleur menthe/lilas fait lire présent vs futur sans légende.
Éviter quand
Il y a plus de cinq ou six jalons (les points se resserrent et la colonne devient illisible — passer à une frise horizontale), ou un seul chiffre à montrer : les deux sous-cartes n'ont alors plus d'opposition à porter.
Notes
Deux registres dans une même carte, tenus par la couleur : la timeline distribue ses jalons par justify-content:space-between (ils occupent toute la hauteur, dernier point plein = horizon), et les deux sous-cartes opposent menthe=présent / lilas=futur — un code repris de la référence, pas une alternance décorative. Les benchmarks vérifient l'empilement (menthe au-dessus de lilas) et les DEUX contrastes de chiffre sur aplat teinté, que le harnais HTML seul attrape. La courbe et la jauge sont des SVG autonomes sans valeur en dur : rejouables sur une autre charte.
Mots-clés
Benchmarks — la géométrie, en assertions vérifiables
Rejouables par node bin/check.mjs card-06-forecast-timeline : le pattern se prouve, il ne se croit pas.
| assertion | mesure | attendu |
|---|---|---|
| marges intérieures ≈ 5,3 % de la largeur | num('.vl-forecast','paddingLeft') / W | 0.053 ± 0.02 |
| colonne de gauche (timeline) ≈ 43 % de la largeur | box('.vl-forecast__left').w / W | 0.43 ± 0.06 |
| la timeline porte bien 4 jalons | document.querySelectorAll('.vl-tl__it').length | 4 |
| sous-cartes EMPILÉES : la menthe (présent) est au-dessus de la lilas (futur) | box('.vl-fc--lilac').top - box('.vl-fc--mint').bottom | ≥ 8 |
| les deux chiffres clés sont au plancher figure (≥ 28 px) | Math.min(num('.vl-fc--mint .vl-fc__big','fontSize'), num('.vl-fc--lilac .vl-fc__big','fontSize')) | ≥ 28 |
| jauge de progression remplie mais non pleine (fill < track) | box('.vl-progress__fill').w / box('.vl-progress').w | ≤ 0.95 |
| contraste du titre ≥ 7 (il nomme la carte) | contrast('.vl-forecast__ttl') | ≥ 7 |
| contraste du chiffre présent sur la menthe ≥ 4,5 | contrast('.vl-fc--mint .vl-fc__big') | ≥ 4.5 |
| contraste du chiffre projeté sur le lilas ≥ 4,5 | contrast('.vl-fc--lilac .vl-fc__big') | ≥ 4.5 |
| aucun débordement du contenu hors de la carte | overflow('.vl-forecast') | ≤ 0 |
Le code
patterns/card-06-forecast-timeline.html
Télécharger<!-- card-06-forecast-timeline — fragment autonome. Couleurs via --vl-* uniquement, aucune valeur en dur. -->
<div class="vl-forecast">
<div class="vl-forecast__left">
<div class="vl-forecast__head">
<span class="vl-forecast__chip">
<svg viewBox="0 0 24 24" fill="none" stroke="var(--vl-ink)" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M5 13l4 4 10-11"/></svg>
</span>
<h3 class="vl-forecast__ttl">Market<br>forecast</h3>
</div>
<div class="vl-tl">
<div class="vl-tl__it"><div class="vl-tl__y">2023</div><div class="vl-tl__d">Explosive growth of DeFi</div></div>
<div class="vl-tl__it"><div class="vl-tl__y">2024</div><div class="vl-tl__d">Mainstream adoption of CBDCs</div></div>
<div class="vl-tl__it"><div class="vl-tl__y">2025</div><div class="vl-tl__d">1 BTC reaches $500K</div></div>
<div class="vl-tl__it vl-tl__it--now"><div class="vl-tl__y">2027</div><div class="vl-tl__d">Widespread retail use</div></div>
</div>
</div>
<div class="vl-forecast__right">
<div class="vl-fc vl-fc--mint">
<div class="vl-fc__top">
<span class="vl-fc__kicker vl-fc__kicker--mint">BTC price</span>
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="var(--vl-ink)" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M7 17L17 7M8 7h9v9"/></svg>
</div>
<div class="vl-fc__big">21,105$</div>
<span class="vl-fc__delta">+28,21%</span>
<div class="vl-progress"><div class="vl-progress__fill"></div><div class="vl-progress__knob"></div></div>
</div>
<div class="vl-fc vl-fc--lilac">
<span class="vl-fc__kicker vl-fc__kicker--lilac">Market cap forecast</span>
<div class="vl-fc__big">1,3trln$</div>
<svg class="vl-spark" viewBox="0 0 240 70" fill="none" preserveAspectRatio="none" width="100%" height="64">
<polyline points="6,58 52,48 98,52 150,30 196,22 234,8" stroke="var(--vl-mint-deep)" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="52" cy="48" r="4.5" fill="var(--vl-surface-light)" stroke="var(--vl-mint-deep)" stroke-width="2.5"/>
<circle cx="150" cy="30" r="4.5" fill="var(--vl-surface-light)" stroke="var(--vl-mint-deep)" stroke-width="2.5"/>
<circle cx="234" cy="8" r="4.5" fill="var(--vl-mint-deep)"/>
</svg>
</div>
</div>
</div>
<style>
/* Carte prévision : à gauche une TIMELINE verticale (jalons datés, dernier point plein =
horizon), à droite une pile de deux sous-cartes teintées — menthe (valeur constatée +
jauge de progression) sur lilas (projection + courbe). Menthe = présent, lilas = futur. */
.vl-forecast {
width: 748px; height: 616px;
background: var(--vl-surface-light); color: var(--vl-ink);
border-radius: var(--vl-radius-card); padding: 28px;
display: flex; flex-direction: row; gap: 24px;
font-family: Inter, -apple-system, "Helvetica Neue", Arial, sans-serif;
}
.vl-forecast__left { flex: 0 0 43%; display: flex; flex-direction: column; }
.vl-forecast__head { display: flex; gap: 12px; align-items: center; margin-bottom: 22px; }
.vl-forecast__chip {
width: 34px; height: 34px; border-radius: 50%; background: var(--vl-mint);
display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
}
.vl-forecast__chip svg { width: 16px; height: 16px; }
.vl-forecast__ttl { margin: 0; font-size: 18px; font-weight: 600; line-height: 1.12; letter-spacing: -0.01em; }
.vl-tl { position: relative; padding-left: 22px; display: flex; flex-direction: column; justify-content: space-between; flex: 1; }
.vl-tl::before { content: ""; position: absolute; left: 5px; top: 6px; bottom: 6px; width: 2px; background: var(--vl-hairline); }
.vl-tl__it { position: relative; }
.vl-tl__it::before {
content: ""; position: absolute; left: -22px; top: 3px; width: 11px; height: 11px; border-radius: 50%;
background: var(--vl-surface-light); border: 2px solid var(--vl-ink-muted);
}
.vl-tl__it--now::before { background: var(--vl-ink); border-color: var(--vl-ink); }
.vl-tl__y { font-size: 14px; font-weight: 700; }
.vl-tl__d { font-size: 11px; font-weight: 500; color: var(--vl-ink-muted); margin-top: 2px; max-width: 20ch; }
.vl-forecast__right { flex: 1; display: flex; flex-direction: column; gap: 16px; }
.vl-fc { border-radius: var(--vl-radius-sub); padding: 20px; display: flex; flex-direction: column; }
.vl-fc--mint { background: var(--vl-mint); flex: 0 0 auto; }
.vl-fc--lilac { background: var(--vl-lilac); flex: 1; }
.vl-fc__top { display: flex; justify-content: space-between; align-items: flex-start; }
.vl-fc__kicker { font-size: 11px; font-weight: 500; }
.vl-fc__kicker--mint { color: var(--vl-ink-on-mint); }
.vl-fc__kicker--lilac { color: var(--vl-ink-on-lilac); }
.vl-fc__big { margin-top: 8px; font-size: 30px; font-weight: 700; letter-spacing: -0.02em; }
.vl-fc__delta {
align-self: flex-start; margin-top: 12px; padding: 5px 12px; border-radius: 999px;
background: var(--vl-surface-light); font-size: 12px; font-weight: 600; color: var(--vl-ink-on-mint);
}
.vl-progress { margin-top: 16px; height: 9px; border-radius: 999px; background: var(--vl-surface-dark); position: relative; }
.vl-progress__fill { position: absolute; left: 0; top: 0; bottom: 0; width: 74%; border-radius: 999px; background: var(--vl-mint-deep); }
.vl-progress__knob { position: absolute; left: 74%; top: 50%; width: 15px; height: 15px; border-radius: 50%; background: var(--vl-lilac-deep); border: 2px solid var(--vl-surface-light); transform: translate(-50%,-50%); }
.vl-spark { margin-top: auto; }
</style>
systems/ref-11-finance-dashboard-mint.json
Télécharger:root {
--vl-bg: #E6EAE4;
--vl-board: #E6EAE4;
--vl-surface-light: #FFFFFF;
--vl-surface-soft: #F1F2EF;
--vl-surface-dark: #141414;
--vl-mint: #B4E3A0;
--vl-mint-deep: #8FCE72;
--vl-lilac: #B6ABE6;
--vl-lilac-deep: #9A8ADE;
--vl-ink: #181A17;
--vl-ink-muted: #7C817A;
--vl-ink-on-mint: #3D5A30;
--vl-ink-on-lilac: #3E3270;
--vl-ink-invert: #FFFFFF;
--vl-ink-invert-muted: #9CA09A;
--vl-hairline: #E3E5E1;
--vl-hairline-invert: #333333;
--vl-radius-card: 26px;
--vl-radius-sub: 20px;
--vl-radius-chip: 14px;
--vl-gap: 20px;
}
les métadonnées — patterns/card-06-forecast-timeline.json (télécharger)
{
"name": "Carte prévision — timeline + sous-cartes",
"family": "card",
"ref": "ref-11-finance-dashboard-mint",
"intent": "Raconter une trajectoire dans une carte : une timeline verticale de jalons datés à gauche, et à droite deux sous-cartes teintées qui opposent la valeur constatée (menthe, présent) à la projection (lilas, futur).",
"when_to_use": "Carte « perspective » d'un dashboard : quelques jalons dans le temps plus deux chiffres clés, l'un acquis l'autre projeté. Le code couleur menthe/lilas fait lire présent vs futur sans légende.",
"avoid_when": "Il y a plus de cinq ou six jalons (les points se resserrent et la colonne devient illisible — passer à une frise horizontale), ou un seul chiffre à montrer : les deux sous-cartes n'ont alors plus d'opposition à porter.",
"tags": [
"carte",
"prevision",
"forecast",
"timeline",
"frise",
"jalons",
"sous-cartes",
"dashboard",
"menthe",
"lilas",
"projection"
],
"vars": [
{
"name": "--vl-mint",
"role": "sous-carte du présent (valeur constatée)",
"default": "#B4E3A0"
},
{
"name": "--vl-lilac",
"role": "sous-carte du futur (projection)",
"default": "#B6ABE6"
},
{
"name": "--vl-hairline",
"role": "axe de la timeline",
"default": "#E3E5E1"
},
{
"name": "--vl-ink",
"role": "point d'horizon (jalon plein) + encre",
"default": "#181A17"
},
{
"name": "--vl-radius-sub",
"role": "rayon des sous-cartes",
"default": "20px"
}
],
"slots": [
"head",
"timeline",
"tile-present",
"tile-forecast"
],
"geometry": {
"root": ".vl-forecast",
"frame": [
748,
616
],
"ratios": {
"pad_over_width": 0.053,
"left_col_over_width": 0.43
},
"type_px": {
"title": 18,
"figure": 30,
"year": 14,
"desc": 11
},
"pad_ratio": {
"top": 0.05,
"x": 0.053,
"bottom": 0.05
}
},
"benchmarks": [
{
"name": "marges intérieures ≈ 5,3 % de la largeur",
"measure": "num('.vl-forecast','paddingLeft') / W",
"expect": 0.053,
"tol": 0.02
},
{
"name": "colonne de gauche (timeline) ≈ 43 % de la largeur",
"measure": "box('.vl-forecast__left').w / W",
"expect": 0.43,
"tol": 0.06
},
{
"name": "la timeline porte bien 4 jalons",
"measure": "document.querySelectorAll('.vl-tl__it').length",
"expect": 4
},
{
"name": "sous-cartes EMPILÉES : la menthe (présent) est au-dessus de la lilas (futur)",
"measure": "box('.vl-fc--lilac').top - box('.vl-fc--mint').bottom",
"min": 8
},
{
"name": "les deux chiffres clés sont au plancher figure (≥ 28 px)",
"measure": "Math.min(num('.vl-fc--mint .vl-fc__big','fontSize'), num('.vl-fc--lilac .vl-fc__big','fontSize'))",
"min": 28
},
{
"name": "jauge de progression remplie mais non pleine (fill < track)",
"measure": "box('.vl-progress__fill').w / box('.vl-progress').w",
"max": 0.95
},
{
"name": "contraste du titre ≥ 7 (il nomme la carte)",
"measure": "contrast('.vl-forecast__ttl')",
"min": 7
},
{
"name": "contraste du chiffre présent sur la menthe ≥ 4,5",
"measure": "contrast('.vl-fc--mint .vl-fc__big')",
"min": 4.5
},
{
"name": "contraste du chiffre projeté sur le lilas ≥ 4,5",
"measure": "contrast('.vl-fc--lilac .vl-fc__big')",
"min": 4.5
},
{
"name": "aucun débordement du contenu hors de la carte",
"measure": "overflow('.vl-forecast')",
"max": 0
}
],
"notes": "Deux registres dans une même carte, tenus par la couleur : la timeline distribue ses jalons par justify-content:space-between (ils occupent toute la hauteur, dernier point plein = horizon), et les deux sous-cartes opposent menthe=présent / lilas=futur — un code repris de la référence, pas une alternance décorative. Les benchmarks vérifient l'empilement (menthe au-dessus de lilas) et les DEUX contrastes de chiffre sur aplat teinté, que le harnais HTML seul attrape. La courbe et la jauge sont des SVG autonomes sans valeur en dur : rejouables sur une autre charte.",
"id": "card-06-forecast-timeline"
}
À côté
card-02-notched-brief
Carte chanfreinée de second rang
card-03-stat-accent
Vignette statistique sur accent
card-04-stat-barchart
Carte statistique à barres empilées
card-05-balance-gauge
Carte solde à jauge compteur
card-07-transactions