Remplace la section "Comment ça marche" (réacteur orbital générique du commit
03f6e56) par une reproduction fidèle du composant DashboardHolographique
défini dans Website-Sanity/components/sections/dictai-narrative.tsx.
Architecture : container "phone" central (border-radius 44px, color tinting
selon feature active) + 6 modes uniques (Transcription upload+words,
Diarisation conversation Sophie/Marc/Julie, 99+ langues grille staggered,
Exports 7 file icons, Users avatars 1→20, Share folders+tags+files) +
IA Mistral 7B premium card + grid 3 cols × 6 features cliquables.
Auto-cycle 900 ms (1→6→1, skip IA index 0) avec click manuel → isManual
pendant 4500 ms puis reprise auto. Animations Framer Motion → CSS
keyframes + Alpine setInterval (preserves prefers-reduced-motion guard,
aria-live, aria-pressed).
Couleurs source spécifiques préservées (#A78BFA #22D3EE #6B9FFF #34D399
#F59E0B) — identifient les features et restent indépendantes de la palette
brand globale b1/b2/b3.
Test test_fonctionnalites_how_it_works_reactor_section adapté à la nouvelle
structure (dictiaDashboard, 5 sub-data fns, 6 modes par signature unique,
IA premium card animations, auto-cycle 900ms / 4500ms manual reset).
Ajoute une nouvelle section interactive sous les 6 fonctionnalités
(préservées intégralement) reproduisant le composant React
dictai-narrative.tsx en CSS pur + Alpine.js — sans Framer Motion ni
autre lib JS.
- Réacteur central holographique : 3 anneaux concentriques rotatifs
(15 s / 22 s / 30 s) + 8 particules orbitales (cyan/blue/fuchsia)
+ wordmark DictIA glow pulsant
- Auto-cycle Alpine.js entre 6 features (1.6 s) avec pause au
hover/focus et reprise au leave/blur
- Panneau feature active avec aria-live='polite' pour annonce
lecteur d'écran (Transcription · Diarisation · 99+ langues ·
Exports · Utilisateurs illimités · Partage & Classement)
- Card 'IA intégrée Mistral 7B LOCAL' avec 3 bullets souveraineté
- Spec list cliquable / hover déclenchant feature dans réacteur
- Layout responsive grid 2 cols desktop, stack mobile
- prefers-reduced-motion désactive rings + orbites + auto-cycle
- Position : APRÈS '6 fonctionnalités', AVANT 'Intégrations'
- Sub-nav reste à 4 ancres (sous-partie visuelle de Fonctionnalités)
- Tests : nouveau test_fonctionnalites_how_it_works_reactor_section
valide structure, contenu canonique, a11y et Alpine bindings
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Restructure _pricing_tiers.html : les 3 forfaits Cloud (Basic 189$/Essentiel 349$/Pro 549$ recommandé) sont maintenant en grid responsive 1/2/3 cols, et DictIA LOCAL est sorti de la grille principale pour devenir un bloc large dédié 'propriété' avec :
- badge 'Au Québec · par InnovA AI' (SVG map-pin, sans emoji 🇨🇦)
- H3 'Vous en êtes propriétaire.' avec grad-text
- 5 bullets checkmark (PC+GPU RTX, 100 % local, assemblé QC, installation incluse, achat direct < 34 700 $)
- CTA 'Voir les serveurs disponibles' → /contact?plan=dictia-local
- mockup serveur à droite (SVG rack + 6 specs : Interface web, PC gaming, RTX 5070 Ti 16 Go, WhisperX+Mistral, DictIA pré-installé, Votre propriété)
- pricing tagline visible '5 998 $ An 1 · 500 $/an dès An 2'
- decorative orbs background (b1 + b3) pour distinguer du grid Cloud
Aussi mis à jour /tarifs (H1 'Trois forfaits Cloud + DictIA LOCAL' au lieu de 'Quatre forfaits') et tests pour refléter le nouveau slug /contact?plan=dictia-local (au lieu du /checkout/dictia-local d'avant). Conserve V3 radii (rounded-none/rounded/rounded-full), palette brand (b1/b2/b3/navy), OQLF NBSP, ARIA WCAG, zéro emoji.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Refonte de la section hero: passage d'un layout centré single-col
à un grid 2 colonnes (texte gauche + mockup app à droite) sur lg+,
avec préservation du centrage actuel sur mobile/tablette.
- Mockup ~560×500px reproduit l'interface DictIA réelle:
- Window chrome (3 dots traffic light + tab "DictIA — Enquêter")
- Sidebar: 6 enregistrements groupés (Semaine dernière 2 + Mois
dernier 4) avec chips colorés (En cours, Barreau Confidentiel,
CPA Corporatif, Urgent Client) + bouton + recording rounded-none
- Center: header card avec 4 metas (avatars/calendar/clock/file),
audio player avec progress bar animée 50%-75% (15s loop),
transcript 5 lignes speaker (Allison/SPEAKER_02) où la ligne
active cycle toutes les 2.8s via Alpine x-data idx
- Right: tabs Résumé/Notes/Discuter (Résumé actif), résumé
exemple + 4 points clés
- Tilt subtil rotate-1 → straighten + scale au hover (lg only)
- 2 glow orbs flottants décoratifs derrière (bg-brand-b1/15 +
bg-brand-b3/10) avec tc-float-y reverse
- role="img" + aria-label descriptif sur le mockup complet
- prefers-reduced-motion désactive toutes animations + freeze
progress bar à 60% + retire transform tilt
- Tous les éléments interactifs ont tabindex="-1" + aria-hidden
car purement décoratifs (pas de duplication d'app réelle)
- Aucun emoji (SVG inline stroke="currentColor" partout)
- Système border-radius respecté: rounded-none (boutons/inputs/
tuiles), rounded (4px wrapper card), rounded-full (chips/avatar)
Tests: 6/6 hero tests pass (eyebrow, h1+grad-text, dual CTA,
cosmic orbs, social proof, animations staggered). Les 3 fails
restants (test_landing_has_main_nav, test_footer_links_complete,
test_trust_bar_has_eyebrow_factual_phrasing) sont préexistants
et sans rapport avec la refonte hero.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Solution pillars (3 cards) : retirer le bloc icône — ne garder que h3 + p
- Bento macro : supprimer la tuile grad-bg, rendre l'icône directement en text-brand-b1, watermark passe à grad-text opacity-20 (famille bleu marque, plus visible que white/[0.04])
- Conformité forteresse (4 cards) : supprimer la tuile grad-bg, rendre l'icône en text-brand-b1
- Bumper toutes les icônes bento (landing + fonctionnalites + default macro) et conformité de w-5 h-5 → w-7 h-7 maintenant qu'elles n'ont plus de backdrop
- Mettre à jour test_bento_uses_flexihub_styling pour refléter la nouvelle structure (grad-text opacity-20 + text-brand-b1 mb-4 au lieu de white/[0.04] + grad-bg rounded-none)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Audit conducted 2026-04-27 against signed PDFs in DOCS_DictIA/. All 6 legal
markdown files + 3 marketing templates aligned on the contractual ground truth
(documents signed by Allison Rioux + Jean-David Lévesque-Rioux 9 mars 2026).
CRITICAL DISCREPANCIES FIXED (D1-D9 — Loi 25 / contractual)
D1. Entity identity: removed false "filiale d'InnovA AI S.E.N.C." claim.
Canonical (PDC §1.1, CGU §1, RPRP doc): DictIA Inc. is a standalone SPA
constituted 22 mars 2026 (LSAQ), 50/50 owned by Allison Rioux + Jean-David
Lévesque-Rioux. NOT a subsidiary of InnovA AI.
D2. NEQ: replaced placeholder with canonical NEQ 1181949562 (DictIA Inc.).
D3. Sub-processors list: PDC §6.2 declares 5 sub-processors. Site listed only
OVH, Stripe, Resend (the latter two not in canonical). Now aligned:
OVH Beauharnois QC + GCP Toronto ON (RAM-only, 5min) + Cloudflare US (CDN)
+ HubSpot US (CRM) + Stripe US (paiements). Resend removed.
D4. GCP Toronto disclosure: NEW. PDC §6.2, §11.2, EFVP_GCP all declare GPU
processing on GCP Toronto Ontario as a transfer hors-Québec under art. 17
LSP. Site previously claimed "100 % au Québec" without GCP disclosure.
Now declared in confidentialite.md §6, §7 + conditions.md §2.4, §9 +
conformite.html pillar.
D5. Biometrics: NEW dedicated section. PDC §12, CGU §6, EFVP_BIOVOCAL all
require disclosure of voice biometrics (pyannote.audio embeddings) per
LCCJTI art. 44-45 + CAI declaration K1. Site had ZERO mention. Now
documented in confidentialite.md §12 + conditions.md §8.
D6. Wrong article number: landing.html cited "art. 60.1 LPRPSP" for biometric
sanctions — that article does NOT exist. Replaced with canonical citation:
"art. 44-45 LCCJTI + art. 12 LSP".
D7. Speakr fork attribution: CGU §13.1.1 explicitly requires the AGPL §13
disclosure URL to be gitea.dictia.ca (not gitea.innova-ai.ca). Mentions.md
+ conformite.html + footer normalized.
D8. Conservation periods: aligned to canonical CGU §8.1.2 + PDC §7.2.
Audio: 30 jours par défaut (extensible 12 mois opt-in) — was "indéfinie".
Biométrie inter-sessions: max 12 mois — était absent.
Facturation: 7 ans — était "6 ans".
Sauvegardes: 30 jours OVH QC.
D9. RPRP contact: confirmed canonical rprp@dictia.ca (per PDC §1.2 + RPRP
designation §1.3) — was already correct on site, kept as-is.
MEDIUM (M1-M3)
M1. Cookies categories: aligned to PDC §5.1 (5 categories: essentiels +
Cloudflare + perf + fonctionnels + HubSpot). Removed "Plausible Analytics
auto-hébergé" claim (not in any signed doc).
M2. DPA status: noted as "signed" for OVH + HubSpot (signed PDFs verified),
"in vigueur" for Stripe.
M3. Footer mentions légales link: added (was missing).
MINOR (N1-N2)
N1. Stripe entity: "Stripe Inc., San Francisco CA" (canonical PDC §2.6),
not "Stripe Payments Canada Ltd." (which doesn't appear in any signed doc).
N2. Engagement de non-entraînement IA: added to conditions.md §10 (canonical
CGU §10).
NOT MODIFIED (per scope boundaries)
- src/api/auth.py, src/billing/*.py, src/models/*.py — code not touched.
- templates/marketing/{tarifs,fonctionnalites}.html — frontend A-2.x final.
- landing.html — only minimal art. 60.1 → art. 44-45 fix (factual law error).
PENDING ALLISON REVIEW
- landing.html line 167-174 marketing claim "Vos données ne sortent jamais
de vos murs ou nos serveurs OVH Beauharnois" is technically inaccurate for
DictIA Cloud users (audio briefly transits to GCP Toronto for GPU processing,
RAM-only, 5min, zero persistence — encadré par EFVP signée). Decision
required: rephrase OR add asterisk pointing to /conformite for Cloud
architecture caveat.
- CAI form (CAI_FO_Declaration_Biometrie_DictIA_COMPLET_signé.pdf) declares
90 jours retention for inter-sessions vectors, while PDC + CGU + EFVP
all say 12 mois. Site uses 12 mois (latest, contractual). Allison should
verify CAI form needs amendment before submission.
TESTS
9/9 test_legal_pages.py passing (added biometrics + decisions automatisees
to required_topics; corrected "transfert hors-québec" → "transferts hors
québec" to match canonical PDC §11 OQLF wording).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Loi 25 article number badges (Art. 3.3, 3.5, 14): change from
`grad-bg text-white text-xs font-black` to `bg-brand-navy text-white
text-xs font-black`. White-on-grad-bg failed AA on the cyan/green
portion of the gradient (~2:1 contrast); solid navy gives ~16:1.
- Update routes.py module docstring to past tense (A-2.8b is now done).
- Add regression assertion ensuring badges use solid navy, not grad-bg.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Extract 3 pricing tiers to templates/marketing/_partials/_pricing_tiers.html
Single source of truth — landing.html and tarifs.html now {% include %} it.
Prevents price drift (LPC art. 219 risk).
- Sync bento card #2 description across landing + fonctionnalites
(was diverged: 'embeddings' vs 'embeddings vocaux'). Add maintenance
reminder comments in both files.
- Fix OQLF NBSP on '~2 semaines' matrix cells in /tarifs deep-dive table.
- Fix mixed UTF-8/entity 'québécois' -> 'québécois' in tech
specs (consistent with rest of file).
- Calibrate H2 size on /tarifs FAQ to match landing (clamp 2.75rem cap).
- Repair 2 pre-existing test bugs from earlier A-2.x commits:
* 'violent la Loi 25' -> accept both NBSP and plain forms (commit 7c6c6fd
added the NBSP after the test was written)
* 'résilie' -> 'résilie' (Jinja outputs raw UTF-8, not entities)
- Update src/marketing/routes.py module docstring to reflect 2/4 done.
- Drop role="region" from FAQ panels (had no accessible name — axe-core
violation; disclosure pattern with button + aria-controls + aria-expanded
is sufficient per WAI-APG accordion guidance)
- Add focus-visible:outline-2 outline-brand-b1 outline-offset-2 to FAQ
buttons (WCAG 2.2 AA 2.4.7 Focus Not Obscured + 2.4.11 Focus Appearance —
Safari default focus indicator is unreliable)
- Sweep pre-existing text-white/50 on Hero social proof microcopy → /70
(branch-wide WCAG floor; recurring landmine flagged at A-2.7a review)
- Strengthen test_faq_jsonld_schema_present to json.loads() the extracted
block and validate the FAQPage schema shape (regression guard for future
content edits with unescaped backslashes/quotes)
- Reword comparatif row 1 to make Teams ✗ for non-Loi-25-compliant US transfer
(was ⚠ — too soft; territoriality is binary)
- Reword row 2 to positive: 'Souveraineté hors Cloud Act US' (was inverted —
✓ used for bad outcomes, breaking visual scan convention)
- Reword row 4 criterion to match deliverable: 'Diarisation jusqu'à 8 locuteurs'
(was '8+', mismatched DictIA's '✓ Jusqu'à 8' cell)
- Reword row 5 to 'Coût mensuel par utilisateur' (was 'utilisateur/mois' —
awkward French + missing NBSP per OQLF)
- Hedge SOC 2 Type II claim about OVH Beauharnois — third-party certification
scope-dependent; reword to 'conformité documentée selon les services
(ISO 27001, SOC 2 selon le périmètre)' to avoid LPC art. 219 risk
- Replace 🇨🇦 regional indicator pair with 🍁 maple leaf — renders reliably
on Windows + Firefox Linux without color-emoji fonts
- Update existing test for renamed criteria keywords
- Add regression test for ✓-means-good convention + SOC 2 hedge guard
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- ROI payback now returns raw months; template branches to 'moins d'un mois'
for sub-month paybacks and 'Payable dès la première année' when savings≤0
(was rounding up to 'Payback : 1 mois' for ~95% of slider combos)
- Cap sliders: users 1..25 (was 50), hours 0.5..4 (was 8) to keep displayed
savings in a defensible band (~8.8 M$/yr max instead of 35 M$)
- pricing_card href uses cta_url.rstrip('/') to avoid double-slash if caller
passes a trailing slash (preempts A-2.8 / B-2.7 regression)
- aria-live polite + aria-atomic on the savings paragraph so screen readers
announce slider updates
- Cleaner JS module pattern: single window.roiCalculator = function() {...}
- Tests updated for payback ternary; new tests for slider caps, aria-live,
and double-slash guard
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Problème section (light bg-brand-bg, white cards): 3 risk cards
(Cloud Act, Loi 25 biométrie art. 60.1 LPRPSP, sanctions disciplinaires
9 ordres pros). H2 grad-text accent on 'violent la Loi 25' — defensible
legal claim citing CAI + LPRPSP statutes by name. text-brand-navy/70 for
all body text (WCAG AA compliant, no /40 or /50 regression).
- Solution section (bg-brand-navy with single subtle green orb): 3 pillars
(100% local, Conforme Loi 25, Précision FR-CA). H2 grad-text accent on
'par design'. Pillars cite specific tech (WhisperX Large-v3, Mistral 7B,
pyannote, OVH Beauharnois, AGPL v3) — all factually verifiable.
- French typography: NBSP via + |safe before %, $, and within
'Loi 25' to prevent line break separation (OQLF rule).
- 4 new tests verify both sections, 3 cards each, key tech mentions,
and WCAG-safe opacity policy.
- Critical (C1): align 9-ordre list with dictia.ca canonical (Barreau, CNQ,
CPA, ChAD, OACIQ, CMQ, OIIQ, OPQ, OEQ). Drop ambiguous OPPQ; replace M/P
short monograms with disambiguated 3-5 char abbreviations (BAR, CNQ, CPA,
ChAD, OACIQ, CMQ, OIIQ, OPQ, OEQ). Tooltips show full disambiguating names.
- Critical (C2): raise text-brand-navy/40 -> /70 on footnote (2.69:1 -> 9:1
contrast, passes WCAG AAA) and text-[10px] navy/50 -> text-xs navy/70 on
monogram captions (12px minimum + AA contrast). Critical for legal
disclosure legibility.
- Critical (C3): drop unverifiable '50 heures' specific number from
methodology footnote — replaced with 'methodologie disponible sur demande'
(defensible without committing to numbers we can't verify).
- Important (I1): use before %/$ in KPI numbers per OQLF French
typography rules + |safe filter to render entities.
- Important (I2): replace fragile substring-strip test with explicit
forbidden-phrase list (RECONNU PAR, ENDOSSÉ PAR, etc.). Update ordre
list test + footnote test to match new wording.
- Section AFTER hero, white bg with brand-border y-borders
- 9 monogram placeholders (gradient circles with initials, NOT official
logos to avoid licensing issues + false-endorsement exposure)
hover from opacity-50 to opacity-100 for subtle interaction
- Eyebrow phrasing 'MAPPÉ AUX 9 ORDRES PROFESSIONNELS' (factual scope,
not 'CERTIFIÉ PAR' which would be a false-endorsement claim under
LPC art. 219 / Competition Act s. 52)
- 4 KPIs with grad-text numbers: ~5 min/heure, 95%+ FR-CA, 0$ par user,
100% local — each with a 1-line context line and a small subtext
- Methodology footnote: 'Précision mesurée sur 50 heures d'audio
interne, détails sur demande' — defensible disclosure for the 95%
claim (LPC art. 219 hygiene)
- 4 new tests verify ordres list, factual phrasing, KPIs, footnote
- Add @media (prefers-reduced-motion: reduce) override to disable animations
for vestibular-sensitive users (covers hero + future scroll/infinite anims)
- Replace 5-star icon + '27 cabinets' claim with shield + 'Conçu avec 9
ordres professionnels' + 'Pré-inscription ouverte' (LPC art. 219 +
Competition Act s. 52 compliance — pre-launch claims must be factual)
- Convert H1/H2/H3 letter-spacing from absolute px to em-relative (-3px →
-0.028em on H1) so tracking scales correctly with clamp font-size on mobile
- Update test_hero_has_social_proof_microcopy to assert new copy
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Button macro: variants/sizes use .get() with primary/md fallback (no KeyError),
add as_button=True parameter for form submit CTAs (forms in B-2.2 signup,
B-2.7 checkout)
- Header: drop hidden sm:inline-block on Connexion link so login is always
visible from mobile (avoids UX dead-end before A-2.7 hamburger lands)
- Add placeholder static/images/favicon.svg (brand gradient + 'D')
- Add placeholder 1x1 PNG static/images/og/og-default.png (replaced in A-3.3
with real 1200x630 branded OG image)