feat(marketing): round 4 — Cadre + Cycle cinématiques (radar, data packet flight, stamp impact, savings counter)

Round 4 transforme les 2 sections "Cadre réglementaire" en expériences cinématiques :

CADRE (Moniteur d'Interception)
- Radar sweep circulaire vert continu en background HUD (4s loop, SVG + @keyframes)
- 6 paquets data "voice.wav" en flight QC→US via offset-path bezier (stagger 420ms, glow rouge)
- Console typewriter char-by-char 3 lignes (28ms/char + caret blink, 3e ligne rouge glow)
- 6 REGS reveal cascadé via revealRegsCascade (stagger 120ms) + hover red glow + border-left
- Verdict NON CONFORME : pulse glow rouge + scan-line traversante 3s
- Decorative grid 40×40 console-style + grid existant 20×20
- Eyebrow ⚠ remplacé par SVG warning-triangle inline

CYCLE (Trois options)
- Phase reveal 1→4 séquentiel (déjà existant) avec animations renforcées
- Col 1 horloge accélérée 1 tour/3s (au lieu de 8s)
- Col 1 prix counter Alpine 0→315 (easeOutCubic 1.4s) via priceHumain + countTo
- Col 2 stamp NON CONFORME impact (rotate -22→-3deg + scale 2.4→1, cubic-bezier 1.6 ease)
- Col 2 flash rouge background à l'impact (cycle-col-flash) + 10 particules de fuite (au lieu de 6)
- Col 3 checkmark draw via stroke-dashoffset 24→0
- Col 3 glow border vert pulsant (cycle-conforme-glow, double-couche emerald + cyan)
- Col 3 badge "Loi 25 conforme" top-right avec pulse subtil (cycle-conforme-badge)
- Connecting lines avec dash flow continu (cycle-line-flow @keyframes)
- Live red dot "Réunion en cours" avec pulse box-shadow
- Section "Économies annuelles · 25 utilisateurs" : 3 cards avec counter Alpine
  (sav1=3924, sav2=6924, sav3=2004) + hover lift + emerald shadow
- Eyebrow ⚠ remplacé par SVG warning-triangle

Accessibilité & performance
- prefers-reduced-motion désactive TOUT (radar, packets, typewriter, stamp, glow, counter)
- Mobile (<768px) cache radar + packets + leak particles (CPU-intensive)
- Counter helper countTo respecte reduced-motion via matchMedia
- Tous les SVG ont aria-hidden, scènes ont role=img/listitem appropriés
- HUD console role=log + aria-live=polite
- OQLF NBSP préservé (315 $/réunion, Loi 25, 100 % Québec, 25 utilisateurs, 3 924 $)

Tests : 4 tests round 4 ajoutés (cadre cinematic, cycle cinematic, no-emoji warning,
reduced-motion guards). 65/68 landing tests passent (3 failures pré-existantes
unrelated : nav /blog, footer /blog, trust-bar phrasing).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Allison
2026-04-28 13:11:02 -04:00
parent 529bd2263b
commit 680df39089
3 changed files with 596 additions and 120 deletions

View File

@@ -49,7 +49,8 @@
--color-green-700: oklch(52.7% 0.154 150.069);
--color-green-800: oklch(44.8% 0.119 151.328);
--color-green-900: oklch(39.3% 0.095 152.535);
--color-emerald-300: oklch(84.5% 0.143 164.978);
--color-emerald-50: oklch(97.9% 0.021 166.113);
--color-emerald-100: oklch(95% 0.052 163.051);
--color-emerald-500: oklch(69.6% 0.17 162.48);
--color-emerald-600: oklch(59.6% 0.145 163.225);
--color-emerald-700: oklch(50.8% 0.118 165.612);
@@ -128,6 +129,7 @@
--font-weight-semibold: 600;
--font-weight-bold: 700;
--font-weight-black: 900;
--tracking-tighter: -0.05em;
--tracking-tight: -0.025em;
--tracking-wide: 0.025em;
--tracking-wider: 0.05em;
@@ -147,7 +149,6 @@
--blur-sm: 8px;
--blur-md: 12px;
--blur-xl: 24px;
--blur-3xl: 64px;
--default-transition-duration: 150ms;
--default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
@@ -391,6 +392,9 @@
.-top-3 {
top: calc(var(--spacing) * -3);
}
.-top-8 {
top: calc(var(--spacing) * -8);
}
.-top-12 {
top: calc(var(--spacing) * -12);
}
@@ -439,6 +443,9 @@
.-right-1\.5 {
right: calc(var(--spacing) * -1.5);
}
.-right-8 {
right: calc(var(--spacing) * -8);
}
.-right-12 {
right: calc(var(--spacing) * -12);
}
@@ -526,6 +533,9 @@
.left-\[3\%\] {
left: 3%;
}
.left-\[6\%\] {
left: 6%;
}
.z-10 {
z-index: 10;
}
@@ -829,6 +839,9 @@
.h-32 {
height: calc(var(--spacing) * 32);
}
.h-40 {
height: calc(var(--spacing) * 40);
}
.h-48 {
height: calc(var(--spacing) * 48);
}
@@ -958,6 +971,9 @@
.w-1\/2 {
width: calc(1 / 2 * 100%);
}
.w-1\/3 {
width: calc(1 / 3 * 100%);
}
.w-2 {
width: calc(var(--spacing) * 2);
}
@@ -1445,10 +1461,6 @@
-moz-column-gap: calc(var(--spacing) * 6);
column-gap: calc(var(--spacing) * 6);
}
.gap-x-8 {
-moz-column-gap: calc(var(--spacing) * 8);
column-gap: calc(var(--spacing) * 8);
}
.space-x-1 {
:where(& > :not(:last-child)) {
--tw-space-x-reverse: 0;
@@ -1490,9 +1502,6 @@
.gap-y-2 {
row-gap: calc(var(--spacing) * 2);
}
.gap-y-3 {
row-gap: calc(var(--spacing) * 3);
}
.divide-y {
:where(& > :not(:last-child)) {
--tw-divide-y-reverse: 0;
@@ -1590,6 +1599,10 @@
border-style: var(--tw-border-style);
border-width: 2px;
}
.border-\[3px\] {
border-style: var(--tw-border-style);
border-width: 3px;
}
.border-y {
border-block-style: var(--tw-border-style);
border-block-width: 1px;
@@ -1719,6 +1732,21 @@
.border-brand-border {
border-color: #e6ebf2;
}
.border-emerald-100 {
border-color: var(--color-emerald-100);
}
.border-emerald-500\/40 {
border-color: color-mix(in srgb, oklch(69.6% 0.17 162.48) 40%, transparent);
@supports (color: color-mix(in lab, red, red)) {
border-color: color-mix(in oklab, var(--color-emerald-500) 40%, transparent);
}
}
.border-emerald-500\/45 {
border-color: color-mix(in srgb, oklch(69.6% 0.17 162.48) 45%, transparent);
@supports (color: color-mix(in lab, red, red)) {
border-color: color-mix(in oklab, var(--color-emerald-500) 45%, transparent);
}
}
.border-gray-300 {
border-color: var(--color-gray-300);
}
@@ -1956,12 +1984,6 @@
background-color: color-mix(in oklab, var(--color-amber-500) 10%, transparent);
}
}
.bg-amber-500\/15 {
background-color: color-mix(in srgb, oklch(76.9% 0.188 70.08) 15%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-amber-500) 15%, transparent);
}
}
.bg-amber-500\/20 {
background-color: color-mix(in srgb, oklch(76.9% 0.188 70.08) 20%, transparent);
@supports (color: color-mix(in lab, red, red)) {
@@ -2064,6 +2086,21 @@
.bg-brand-navy2 {
background-color: #0b1525;
}
.bg-emerald-50 {
background-color: var(--color-emerald-50);
}
.bg-emerald-500\/12 {
background-color: color-mix(in srgb, oklch(69.6% 0.17 162.48) 12%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-emerald-500) 12%, transparent);
}
}
.bg-emerald-500\/15 {
background-color: color-mix(in srgb, oklch(69.6% 0.17 162.48) 15%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-emerald-500) 15%, transparent);
}
}
.bg-emerald-600 {
background-color: var(--color-emerald-600);
}
@@ -2166,6 +2203,12 @@
background-color: color-mix(in oklab, var(--color-red-50) 30%, transparent);
}
}
.bg-red-50\/40 {
background-color: color-mix(in srgb, oklch(97.1% 0.013 17.38) 40%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-red-50) 40%, transparent);
}
}
.bg-red-100 {
background-color: var(--color-red-100);
}
@@ -2178,6 +2221,9 @@
.bg-red-400 {
background-color: var(--color-red-400);
}
.bg-red-500 {
background-color: var(--color-red-500);
}
.bg-red-500\/10 {
background-color: color-mix(in srgb, oklch(63.7% 0.237 25.331) 10%, transparent);
@supports (color: color-mix(in lab, red, red)) {
@@ -2190,6 +2236,18 @@
background-color: color-mix(in oklab, var(--color-red-500) 20%, transparent);
}
}
.bg-red-500\/40 {
background-color: color-mix(in srgb, oklch(63.7% 0.237 25.331) 40%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-red-500) 40%, transparent);
}
}
.bg-red-500\/85 {
background-color: color-mix(in srgb, oklch(63.7% 0.237 25.331) 85%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-red-500) 85%, transparent);
}
}
.bg-red-600 {
background-color: var(--color-red-600);
}
@@ -2229,6 +2287,12 @@
background-color: color-mix(in oklab, var(--color-white) 30%, transparent);
}
}
.bg-white\/80 {
background-color: color-mix(in srgb, #fff 80%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-white) 80%, transparent);
}
}
.bg-white\/95 {
background-color: color-mix(in srgb, #fff 95%, transparent);
@supports (color: color-mix(in lab, red, red)) {
@@ -2812,6 +2876,10 @@
--tw-tracking: var(--tracking-tight);
letter-spacing: var(--tracking-tight);
}
.tracking-tighter {
--tw-tracking: var(--tracking-tighter);
letter-spacing: var(--tracking-tighter);
}
.tracking-wide {
--tw-tracking: var(--tracking-wide);
letter-spacing: var(--tracking-wide);
@@ -2995,6 +3063,9 @@
.text-brand-navy\/80 {
color: color-mix(in oklab, #060d1a 80%, transparent);
}
.text-brand-navy\/85 {
color: color-mix(in oklab, #060d1a 85%, transparent);
}
.text-brand-navy\/90 {
color: color-mix(in oklab, #060d1a 90%, transparent);
}
@@ -3007,6 +3078,15 @@
.text-emerald-600 {
color: var(--color-emerald-600);
}
.text-emerald-600\/70 {
color: color-mix(in srgb, oklch(59.6% 0.145 163.225) 70%, transparent);
@supports (color: color-mix(in lab, red, red)) {
color: color-mix(in oklab, var(--color-emerald-600) 70%, transparent);
}
}
.text-emerald-700 {
color: var(--color-emerald-700);
}
.text-gray-200 {
color: var(--color-gray-200);
}
@@ -3097,6 +3177,12 @@
color: color-mix(in oklab, var(--color-red-500) 80%, transparent);
}
}
.text-red-500\/85 {
color: color-mix(in srgb, oklch(63.7% 0.237 25.331) 85%, transparent);
@supports (color: color-mix(in lab, red, red)) {
color: color-mix(in oklab, var(--color-red-500) 85%, transparent);
}
}
.text-red-600 {
color: var(--color-red-600);
}
@@ -3288,10 +3374,18 @@
--tw-shadow: 0 0 6px var(--tw-shadow-color, #F59E0B);
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
.shadow-\[0_0_6px_rgba\(239\,68\,68\,0\.6\)\] {
--tw-shadow: 0 0 6px var(--tw-shadow-color, rgba(239,68,68,0.6));
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
.shadow-\[0_0_28px_rgba\(0\,98\,255\,0\.35\)\] {
--tw-shadow: 0 0 28px var(--tw-shadow-color, rgba(0,98,255,0.35));
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
.shadow-\[0_8px_30px_-6px_rgba\(239\,68\,68\,0\.55\)\] {
--tw-shadow: 0 8px 30px -6px var(--tw-shadow-color, rgba(239,68,68,0.55));
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
.shadow-cta {
--tw-shadow: 0 4px 20px var(--tw-shadow-color, rgba(0, 98, 255, 0.28));
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);