card-10-kpi-notch-tile

Vignette de preuve chiffrée à double chanfrein

Poser UNE preuve chiffrée dans une vignette presque carrée à silhouette de ticket — tuile d'icône en haut, chiffre et son suffixe sur la même ligne de base, libellé collé dessous, commentaire relégué en bas à droite — et n'en accentuer qu'une seule dans la rangée, par le fond et rien d'autre.

cardslidesocialweb420×450px20 benchmarks

Télécharger le .zip

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

Bande de trois à quatre preuves de même rang sur une landing ou une slide « pourquoi nous » : taux, gain de temps, volume. Une seule vignette prend la variante `--accent`, celle qu'on veut faire lire en premier.

Éviter quand

Il n'y a qu'un chiffre à montrer (la rangée n'existe plus, et l'accent n'a plus rien à surpasser), le commentaire dépasse deux lignes courtes (il rejoint le libellé et le décalage à droite devient illisible), ou plusieurs vignettes sont colorées — deux accents dans une rangée annulent le seul geste de hiérarchie du système.

Notes

Le fragment livré est la variante d'ACCENT (`vl-kpi--accent`) : c'est l'état risqué — texte blanc sur dégradé — et un benchmark ne garde que ce qu'il mesure. La vignette neutre est la classe de base ; son encre de note est posée à #6E67A0 (5,18:1 sur blanc) et non au #9B96C4 relevé sur la source, qui plafonne à 2,79:1. Le piège du lot est dans le repli du dégradé : bin/check.mjs lit `background-color` et jamais `background-image`, donc `background-color` déclare l'extrémité CLAIRE (#9A7BF0) et non le départ violet. Poser le repli sur le départ aurait fait mesurer 6,03:1 là où le coin bas-droite — celui qui porte justement la note — ne vaut que 3,20:1 : la mesure doit garder le point le plus défavorable, pas le plus flatteur. Le benchmark des 6 sommets compte les longueurs px de la clip-path calculée (2 par sommet) : notchCorner() ne sait rendre qu'UN coin, il aurait laissé passer un chanfrein simple. Quand un contrôle ne voit qu'une moitié du geste, l'assertion se pose ailleurs, elle ne se supprime pas. Enfin, ce pattern n'est pas une variante de card-03-stat-accent (chanfrein UNIQUE sans rayon, micro-libellé au-dessus du chiffre, corps en pleine largeur) ni de card-02-notched-brief (aucun chiffre) : c'est la grammaire de chanfrein de ref-15, et elle vient avec une règle de rangée que card-03 n'a pas — une seule vignette colorée, jamais deux.

Mots-clés

statchiffrekpipourcentagevignettecarterangeeaccentchanfreinnotchiconetuilelandingpreuvesaas

Benchmarks — la géométrie, en assertions vérifiables

Rejouables par node bin/check.mjs card-10-kpi-notch-tile : le pattern se prouve, il ne se croit pas.

assertionmesureattendu
vignette presque carrée, un rien plus haute que largeW / H0.933 ± 0.03
chanfrein ≈ 11 % de la largeurnotch('.vl-kpi') / W0.11 ± 0.02
le polygone porte 6 sommets : DEUX coins coupés, pas un ni quatre(cs('.vl-kpi','clipPath').match(/,/g) || []).length + 16 ± 0
la coupe commence au coin haut-droit (l'autre est son opposé sur la diagonale)notchCorner('.vl-kpi') === 'tr' ? 1 : 01
les coins non coupés gardent un rayon ≈ 4 % de la largeurnum('.vl-kpi','borderTopLeftRadius') / W0.04 ± 0.015
marge intérieure gauche ≈ 9 % de la largeurnum('.vl-kpi','paddingLeft') / W0.09 ± 0.02
tuile d'icône carréebox('.vl-kpi__tile').w / box('.vl-kpi__tile').h1 ± 0.02
la tuile reste un repère, jamais un sujet : ≤ 22 % de la largeurbox('.vl-kpi__tile').w / W≤ 0.22
saut typographique chiffre / libellé ≥ 2,8num('.vl-kpi__num','fontSize') / num('.vl-kpi__label','fontSize')≥ 2.8
le suffixe pèse entre 35 % et 50 % du chiffrenum('.vl-kpi__suffix','fontSize') / num('.vl-kpi__num','fontSize')0.35 → 0.5
le suffixe est posé À DROITE du chiffre, jamais dessousbox('.vl-kpi__suffix').left - box('.vl-kpi__num').right-1 → 14
lignes de base alignées : l'écart de fond de boîte reste sous 10 % du corps du chiffreMath.abs(box('.vl-kpi__num').bottom - box('.vl-kpi__suffix').bottom) / num('.vl-kpi__num','fontSize')≤ 0.1
libellé collé au chiffre : moins d'un demi-corps de libellé les sépare(box('.vl-kpi__label').top - box('.vl-kpi__figure').bottom) / num('.vl-kpi__label','fontSize')≤ 0.5
la note est bien en bas (haut du bloc entre 72 % et 88 % de la hauteur)box('.vl-kpi__note').top / H0.72 → 0.88
la note est au fer à DROITE : c'est son bord droit qui colle la margeW - num('.vl-kpi','paddingRight') - box('.vl-kpi__note').right0 ± 1.5
la note tient dans la moitié droite : c'est un aparté, pas un paragraphebox('.vl-kpi__note').left / W≥ 0.4
la note s'arrête AVANT le chanfrein du bas-gauchebox('.vl-kpi__note').left - num('.vl-kpi','paddingLeft')≥ 0
contraste du chiffre ≥ 3 (mesuré sur l'extrémité CLAIRE du dégradé)contrast('.vl-kpi__num')≥ 3
contraste de la note ≥ 3 — c'est elle qui plafonne, pas le chiffrecontrast('.vl-kpi__note')≥ 3
aucun débordement du contenu hors de la vignetteoverflow('.vl-kpi')≤ 0

Le code

fragment — patterns/card-10-kpi-notch-tile.html Télécharger
<!-- card-10-kpi-notch-tile — vignette de preuve chiffrée, double chanfrein sur la diagonale.
     Couleurs via --vl-* uniquement. Quatre zones dans un ordre FIXE : tuile d'icône, chiffre +
     suffixe sur la même ligne de base, libellé collé dessous, note collée en bas À DROITE.
     La classe de base est la vignette NEUTRE ; `vl-kpi--accent` est la variante d'aplat, et il
     n'y en a qu'UNE par rangée — c'est le fond qui hiérarchise, rien d'autre ne bouge. -->
<div class="vl-kpi vl-kpi--accent">
  <span class="vl-kpi__tile" aria-hidden="true">
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9"
         stroke-linecap="round" stroke-linejoin="round">
      <path d="M11.9 14.9 9 12a21 21 0 0 1 1.9-3.8A12.6 12.6 0 0 1 21.5 2.4c0 2.7-.8 7.3-5.9 10.8a21 21 0 0 1-3.7 1.7Z"/>
      <path d="M9 12H4.2s.5-3 2-3.9c1.6-1 4.9 0 4.9 0"/>
      <path d="M11.9 14.9v4.7s3-.5 3.9-2c1-1.6 0-4.9 0-4.9"/>
      <path d="M4.6 16.6c-1.5 1.2-2 4.9-2 4.9s3.7-.5 4.9-2c.7-.8.7-2.1-.1-2.8a2.1 2.1 0 0 0-2.8-.1Z"/>
    </svg>
  </span>
  <p class="vl-kpi__figure"><span class="vl-kpi__num">80</span><span class="vl-kpi__suffix">%</span></p>
  <p class="vl-kpi__label">Faster Reporting</p>
  <p class="vl-kpi__note">Generate reports<br>instantly with AI</p>
</div>

<style>
.vl-kpi {
  --vl-nc: var(--vl-notch, 46px);
  --vl-r: var(--vl-radius, 17px);
  width: 420px; height: 450px;
  padding: 38px 38px 34px;
  box-sizing: border-box;
  display: flex; flex-direction: column;
  background: var(--vl-card);
  color: var(--vl-ink);
  border-radius: var(--vl-r);
  /* Le double chanfrein est sur la DIAGONALE (haut-droit + bas-gauche) et les deux autres
     coins gardent leur rayon : c'est cette dissymétrie qui fait la silhouette de ticket.
     Couper les quatre coins donnerait un octogone — une forme, pas une signature. */
  clip-path: polygon(
    0 0,
    calc(100% - var(--vl-nc)) 0,
    100% var(--vl-nc),
    100% 100%,
    var(--vl-nc) 100%,
    0 calc(100% - var(--vl-nc))
  );
  font-family: Montserrat, Poppins, Inter, "Helvetica Neue", Arial, sans-serif;
}
/* La vignette d'accent : le dégradé monte du violet plein (coin bas-gauche, celui qui est
   chanfreiné) vers le lilas clair du coin haut-droit. `background-color` déclare l'extrémité
   CLAIRE — c'est le point le plus défavorable de la carte, et le seul que la mesure de
   contraste sait lire ; y poser le violet du départ rendrait la mesure flatteuse. */
.vl-kpi--accent {
  background-color: var(--vl-violet-light);
  background-image: linear-gradient(45deg, var(--vl-violet) 0%, var(--vl-violet) 18%, var(--vl-violet-light) 100%);
  color: var(--vl-on-accent);
}
.vl-kpi__tile {
  width: 79px; height: 79px; border-radius: 20px;
  display: flex; align-items: center; justify-content: center;
  background: var(--vl-tile); color: var(--vl-violet);
}
.vl-kpi--accent .vl-kpi__tile { background: var(--vl-tile-invert); color: var(--vl-on-accent); }
.vl-kpi__tile svg { width: 38px; height: 38px; }
/* Le chiffre est ~3,2× le libellé qu'il surplombe, et le suffixe ~0,42× le chiffre : le
   suffixe reste sur la ligne de base du nombre (`baseline`), il ne passe jamais à la ligne —
   un `%` orphelin sur sa ligne casse l'unité et la vignette se met à compter deux choses. */
.vl-kpi__figure {
  margin: 26px 0 0;
  display: flex; align-items: baseline; gap: 4px;
  line-height: 1;
}
.vl-kpi__num { font-size: 108px; font-weight: 800; letter-spacing: -0.03em; }
.vl-kpi__suffix { font-size: 46px; font-weight: 800; letter-spacing: -0.01em; }
.vl-kpi__label {
  margin: 12px 0 0;
  font-size: 34px; line-height: 1.25; font-weight: 700; letter-spacing: -0.01em;
}
/* Collée en bas (`margin-top:auto`) ET au fer à DROITE (`align-self`) : c'est le seul élément
   de la vignette qui n'est pas aligné à gauche, et ce décalage est ce qui la fait lire comme
   un aparté. Le vide au-dessus est assumé — il sépare la donnée de son commentaire. */
.vl-kpi__note {
  margin: auto 0 0; align-self: flex-end; text-align: right;
  font-size: 20px; line-height: 1.45; font-weight: 500;
  color: var(--vl-ink-muted);
}
.vl-kpi--accent .vl-kpi__note { color: var(--vl-on-accent-muted); }
</style>
tokens de la charte — systems/ref-15-lilac-notched-kpi.json Télécharger
:root {
  --vl-bg: #F4F4FB;
  --vl-card: #FCFBFF;
  --vl-white: #FFFFFF;
  --vl-violet: #6B3FE4;
  --vl-violet-light: #9A7BF0;
  --vl-figure: #4C1FD6;
  --vl-ink: #2E2166;
  --vl-ink-muted: #6E67A0;
  --vl-tile: #EBE7FB;
  --vl-tile-invert: rgba(255,255,255,0.22);
  --vl-on-accent: #FFFFFF;
  --vl-on-accent-muted: #FFFFFF;
  --vl-notch: 46px;
  --vl-radius: 17px;
  --vl-margin: 120px;
}
les métadonnées — patterns/card-10-kpi-notch-tile.json (télécharger)
{
  "name": "Vignette de preuve chiffrée à double chanfrein",
  "family": "card",
  "ref": "ref-15-lilac-notched-kpi",
  "intent": "Poser UNE preuve chiffrée dans une vignette presque carrée à silhouette de ticket — tuile d'icône en haut, chiffre et son suffixe sur la même ligne de base, libellé collé dessous, commentaire relégué en bas à droite — et n'en accentuer qu'une seule dans la rangée, par le fond et rien d'autre.",
  "when_to_use": "Bande de trois à quatre preuves de même rang sur une landing ou une slide « pourquoi nous » : taux, gain de temps, volume. Une seule vignette prend la variante `--accent`, celle qu'on veut faire lire en premier.",
  "avoid_when": "Il n'y a qu'un chiffre à montrer (la rangée n'existe plus, et l'accent n'a plus rien à surpasser), le commentaire dépasse deux lignes courtes (il rejoint le libellé et le décalage à droite devient illisible), ou plusieurs vignettes sont colorées — deux accents dans une rangée annulent le seul geste de hiérarchie du système.",
  "media": [
    "slide",
    "social",
    "web"
  ],
  "tags": [
    "stat",
    "chiffre",
    "kpi",
    "pourcentage",
    "vignette",
    "carte",
    "rangee",
    "accent",
    "chanfrein",
    "notch",
    "icone",
    "tuile",
    "landing",
    "preuve",
    "saas"
  ],
  "vars": [
    {
      "name": "--vl-card",
      "role": "fond de la vignette neutre",
      "default": "#FCFBFF"
    },
    {
      "name": "--vl-violet",
      "role": "départ du dégradé d'accent, et couleur du glyphe sur la vignette neutre",
      "default": "#6B3FE4"
    },
    {
      "name": "--vl-violet-light",
      "role": "arrivée du dégradé ET couleur de repli — le point le plus clair, donc celui que la mesure de contraste doit lire",
      "default": "#9A7BF0"
    },
    {
      "name": "--vl-ink",
      "role": "chiffre et libellé sur la vignette neutre",
      "default": "#2E2166"
    },
    {
      "name": "--vl-ink-muted",
      "role": "note du bas sur la vignette neutre (relevée à #9B96C4, remontée pour tenir 4,5:1)",
      "default": "#6E67A0"
    },
    {
      "name": "--vl-tile",
      "role": "aplat de la tuile d'icône, vignette neutre",
      "default": "#EBE7FB"
    },
    {
      "name": "--vl-tile-invert",
      "role": "aplat de la tuile d'icône sur l'accent (blanc translucide)",
      "default": "rgba(255,255,255,0.22)"
    },
    {
      "name": "--vl-notch",
      "role": "longueur du chanfrein, posée sur les DEUX coins de la diagonale",
      "default": "46px"
    },
    {
      "name": "--vl-radius",
      "role": "rayon des deux coins non coupés",
      "default": "17px"
    }
  ],
  "slots": [
    "tile",
    "num",
    "suffix",
    "label",
    "note"
  ],
  "geometry": {
    "root": ".vl-kpi",
    "frame": [
      420,
      450
    ],
    "ratios": {
      "width_over_height": 0.933,
      "notch_over_width": 0.11,
      "radius_over_width": 0.04,
      "pad_x_over_width": 0.09,
      "tile_over_width": 0.188,
      "gutter_over_width": 0.102,
      "figure_over_label": 3.18,
      "suffix_over_figure": 0.426,
      "note_top_over_height": 0.795
    },
    "type_px": {
      "num": 108,
      "suffix": 46,
      "label": 34,
      "note": 20
    },
    "pad_ratio": {
      "top": 0.09,
      "x": 0.09,
      "bottom": 0.081
    }
  },
  "benchmarks": [
    {
      "name": "vignette presque carrée, un rien plus haute que large",
      "measure": "W / H",
      "expect": 0.933,
      "tol": 0.03
    },
    {
      "name": "chanfrein ≈ 11 % de la largeur",
      "measure": "notch('.vl-kpi') / W",
      "expect": 0.11,
      "tol": 0.02
    },
    {
      "name": "le polygone porte 6 sommets : DEUX coins coupés, pas un ni quatre",
      "measure": "(cs('.vl-kpi','clipPath').match(/,/g) || []).length + 1",
      "expect": 6,
      "tol": 0
    },
    {
      "name": "la coupe commence au coin haut-droit (l'autre est son opposé sur la diagonale)",
      "measure": "notchCorner('.vl-kpi') === 'tr' ? 1 : 0",
      "expect": 1
    },
    {
      "name": "les coins non coupés gardent un rayon ≈ 4 % de la largeur",
      "measure": "num('.vl-kpi','borderTopLeftRadius') / W",
      "expect": 0.04,
      "tol": 0.015
    },
    {
      "name": "marge intérieure gauche ≈ 9 % de la largeur",
      "measure": "num('.vl-kpi','paddingLeft') / W",
      "expect": 0.09,
      "tol": 0.02
    },
    {
      "name": "tuile d'icône carrée",
      "measure": "box('.vl-kpi__tile').w / box('.vl-kpi__tile').h",
      "expect": 1,
      "tol": 0.02
    },
    {
      "name": "la tuile reste un repère, jamais un sujet : ≤ 22 % de la largeur",
      "measure": "box('.vl-kpi__tile').w / W",
      "max": 0.22
    },
    {
      "name": "saut typographique chiffre / libellé ≥ 2,8",
      "measure": "num('.vl-kpi__num','fontSize') / num('.vl-kpi__label','fontSize')",
      "min": 2.8
    },
    {
      "name": "le suffixe pèse entre 35 % et 50 % du chiffre",
      "measure": "num('.vl-kpi__suffix','fontSize') / num('.vl-kpi__num','fontSize')",
      "min": 0.35,
      "max": 0.5
    },
    {
      "name": "le suffixe est posé À DROITE du chiffre, jamais dessous",
      "measure": "box('.vl-kpi__suffix').left - box('.vl-kpi__num').right",
      "max": 14,
      "min": -1
    },
    {
      "name": "lignes de base alignées : l'écart de fond de boîte reste sous 10 % du corps du chiffre",
      "measure": "Math.abs(box('.vl-kpi__num').bottom - box('.vl-kpi__suffix').bottom) / num('.vl-kpi__num','fontSize')",
      "max": 0.1
    },
    {
      "name": "libellé collé au chiffre : moins d'un demi-corps de libellé les sépare",
      "measure": "(box('.vl-kpi__label').top - box('.vl-kpi__figure').bottom) / num('.vl-kpi__label','fontSize')",
      "max": 0.5
    },
    {
      "name": "la note est bien en bas (haut du bloc entre 72 % et 88 % de la hauteur)",
      "measure": "box('.vl-kpi__note').top / H",
      "min": 0.72,
      "max": 0.88
    },
    {
      "name": "la note est au fer à DROITE : c'est son bord droit qui colle la marge",
      "measure": "W - num('.vl-kpi','paddingRight') - box('.vl-kpi__note').right",
      "expect": 0,
      "tol": 1.5
    },
    {
      "name": "la note tient dans la moitié droite : c'est un aparté, pas un paragraphe",
      "measure": "box('.vl-kpi__note').left / W",
      "min": 0.4
    },
    {
      "name": "la note s'arrête AVANT le chanfrein du bas-gauche",
      "measure": "box('.vl-kpi__note').left - num('.vl-kpi','paddingLeft')",
      "min": 0
    },
    {
      "name": "contraste du chiffre ≥ 3 (mesuré sur l'extrémité CLAIRE du dégradé)",
      "measure": "contrast('.vl-kpi__num')",
      "min": 3
    },
    {
      "name": "contraste de la note ≥ 3 — c'est elle qui plafonne, pas le chiffre",
      "measure": "contrast('.vl-kpi__note')",
      "min": 3
    },
    {
      "name": "aucun débordement du contenu hors de la vignette",
      "measure": "overflow('.vl-kpi')",
      "max": 0
    }
  ],
  "notes": "Le fragment livré est la variante d'ACCENT (`vl-kpi--accent`) : c'est l'état risqué — texte blanc sur dégradé — et un benchmark ne garde que ce qu'il mesure. La vignette neutre est la classe de base ; son encre de note est posée à #6E67A0 (5,18:1 sur blanc) et non au #9B96C4 relevé sur la source, qui plafonne à 2,79:1. Le piège du lot est dans le repli du dégradé : bin/check.mjs lit `background-color` et jamais `background-image`, donc `background-color` déclare l'extrémité CLAIRE (#9A7BF0) et non le départ violet. Poser le repli sur le départ aurait fait mesurer 6,03:1 là où le coin bas-droite — celui qui porte justement la note — ne vaut que 3,20:1 : la mesure doit garder le point le plus défavorable, pas le plus flatteur. Le benchmark des 6 sommets compte les longueurs px de la clip-path calculée (2 par sommet) : notchCorner() ne sait rendre qu'UN coin, il aurait laissé passer un chanfrein simple. Quand un contrôle ne voit qu'une moitié du geste, l'assertion se pose ailleurs, elle ne se supprime pas. Enfin, ce pattern n'est pas une variante de card-03-stat-accent (chanfrein UNIQUE sans rayon, micro-libellé au-dessus du chiffre, corps en pleine largeur) ni de card-02-notched-brief (aucun chiffre) : c'est la grammaire de chanfrein de ref-15, et elle vient avec une règle de rangée que card-03 n'a pas — une seule vignette colorée, jamais deux.",
  "id": "card-10-kpi-notch-tile"
}

À côté