Commit Graph

26 Commits

Author SHA1 Message Date
Allison
1c4cafaf69 refactor(pricing): refonte v7.0 — 3 Cloud (Basic 189$/Essentiel 349$/Pro 549$) + DictIA Local (5998$ An1) + Pro+ soumission
Remplace l'ancien pricing (DictIA 8 / 16 / Cloud) par la nouvelle structure
canonique v7.0 : 4 forfaits + 1 sentinel quote-only.

Changements clés :
- pricing_card.html : signature étendue (badge, recommended, capacity_audio,
  capacity_storage, gpu, yearly_renewal, cta_label) + format prix server-side
  avec NBSP OQLF (5998 -> 5 998 $)
- _pricing_tiers.html : 4 cards (Cloud Basic 189$, Cloud Essentiel 349$,
  Cloud Pro 549$+485$ RECOMMANDÉ, DictIA Local 5998$ An1) + chip Pro+
  soumission -> /contact?pro-plus=1
- plans.py : refonte complète avec yearly_renewal_env (DictIA Local An 2+ =
  500$/an) + is_quote_only sentinel (Pro+ -> redirect /contact, jamais Stripe)
- routes.py : Pro+ intercepté avant le flow Stripe Checkout
- env.stripe.example : nouveau naming STRIPE_CLOUD_BASIC|ESSENTIEL|PRO_*
  + STRIPE_DICTIA_LOCAL_SETUP/RENEWAL_YEARLY
- tarifs.html : header "Quatre forfaits", matrice comparative 4 colonnes,
  FAQ enrichie (7 questions incluant DictIA Local + onboarding Pro + Pro+)
- fonctionnalites.html : section Architecture refondue (4 cards v7.0)
- landing.html : ROI footnote + cycle "189$" + wave "189$/mois" actualisés
- roi_calculator.js : recalibrage sur Cloud ESSENTIEL 349$ × 12 = 4188$/an
- routes.py marketing : FAQ "DictIA 8 et 16" -> "DictIA LOCAL"
- contact.html : "déploiements DictIA 16" -> "Cloud PRO" + "DictIA LOCAL"

Tests :
- test_marketing_landing_template.py : assertions prix v7.0 (189/349/549/5998),
  4 slugs (cloud-basic, cloud-essentiel, cloud-pro, dictia-local), Pro+ chip,
  capacity chips, RECOMMANDÉ sur Cloud PRO
- test_marketing_secondary_pages.py : 4 cards + Pro+ chip + matrice 4 col +
  FAQ 7 questions
- test_stripe_checkout.py : env vars v7.0, slugs cloud-basic/cloud-pro/
  dictia-local + nouveau test pro-plus -> /contact + tests setup pour Cloud PRO
  et DictIA Local
- test_stripe_webhook.py : plan_slug metadata cloud-basic

Status : 28/28 Stripe checkout + 17/17 webhook + 93/98 marketing pass
(les 5 marketing failures sont pré-existantes, non liées au pricing :
test_landing_has_main_nav et test_footer_links_complete = /blog manquant ;
test_trust_bar_has_eyebrow_factual_phrasing + 2 tests conformite =
casing eyebrow + entité é — vérifié par git stash baseline).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 21:06:12 -04:00
Allison
575db5e342 feat(brand): logo officiel DictIA + palette blue/cyan/fuchsia (matche le logo)
Logos officiels installés :
- static/images/dictia-logo.png (28 KB optimisé 256×256)
- static/images/dictia-logo-128.png (10 KB retina)
- static/images/dictia-logo-fullres.png (originaux conservés OG/social)
- static/images/dictia-logo.svg + dictia-logo-nom.svg (cleaned C2PA metadata)
- Header marketing/base.html : <img> 40×40 + wordmark "DictIA" + tagline "Transcription"
- Footer marketing/_footer.html : <img> 36×36 + wordmark
- Favicon mis à jour vers logo PNG

Note : SVG sources sont des PNG base64 wrappés (pas de vrais paths) — PNG utilisé
en production (8× plus léger), SVG conservé pour fallback.

Palette canonique alignée sur le logo :
- brand-b1 : #7c3aed (mauve) → #2563eb (blue-600 vibrant — primary)
- brand-b2 : #a855f7 (mauve clair) → #06b6d4 (cyan-500 — aqua mid)
- brand-b3 : #06b6d4 (aqua) → #c026d3 (fuchsia-600 — magenta accent)
- Gradient signature : linear-gradient(118deg, #2563eb, #06b6d4 52%, #c026d3)
- Box shadow CTA : rgba(37,99,235,0.28/0.42)
- 72 remplacements hex/rgba dans 5 templates marketing/legal + email service

Tests : 81 passed / 3 failed (3 échecs pré-existants /blog + trust-bar phrasing,
non liés à ce changement). 0 régression.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 15:54:17 -04:00
Allison
34d40162b3 refactor(brand): décale palette bleu→mauve dégradé (b1=#7c3aed, b2=#a855f7, b3=#06b6d4 aqua) pour différencier DictIA
Décale la palette canonique DictIA du bleu/cyan/vert vers mauve/violet/aqua
afin de distinguer visuellement le produit DictIA des autres outils InnovA AI
(qui restent sur palette bleue) tout en gardant la même structure de gradient,
mêmes tokens Tailwind, et même intensité visuelle.

Mapping appliqué:
- Hex semantic: #0062ff → #7c3aed (mauve), #00bdd8 → #a855f7 (lighter mauve)
- Hex aqua décoratif: #00c896 → #06b6d4 (cyan-500, aqua préservé)
- Hex secondaire: #6B9FFF / rgba(107,159,255,*) → #a78bfa (violet-400)
- Hex blue-700 #1d4ed8 (cadre reg label) → #7c3aed (mauve)
- Box shadows / rgba opacités: rgba(0,98,255,*) → rgba(124,58,237,*)
- Décoratif (orbes cosmiques, glows): mauve+aqua mix pour préserver l'effet
  "cosmic dégradé" — orbe primaire en mauve, orbes secondaires en aqua
- Hub network DictIA: Documents=mauve, Communication=aqua, Automatisation
  reste #8b5cf6 (déjà violet, marqueur visuel distinct via positionnement)
- Couleurs sémantiques fonctionnelles (red/green pour erreurs/succès, amber
  pour alertes) inchangées

Fichiers modifiés:
- static/css/tailwind.config.js (brand.b1/b2/b3 + brand-grad + boxShadow.cta
  + boxShadow.cta-hover + keyframes.tc-pulse-glow)
- static/css/marketing.css (rebuild Tailwind: 169356 → 163036 bytes)
- templates/legal/{_layout,index}.html
- templates/marketing/{landing,fonctionnalites,conformite,tarifs}.html
- tests/test_marketing_landing_template.py (test_hero_has_cosmic_orbs_background
  mis à jour avec assertions mauve/aqua au lieu de blue/cyan/green)

Hors scope (non touchés):
- Couleurs Tailwind utility (red/green/amber/emerald) sémantiques
- --brand-navy* (backgrounds dark restent neutres)
- Templates legacy (account.html, admin.html, components/, modals/)
- #8b5cf6 (Automatisation hub), #f59e0b (alertes), #ef4444 (erreurs)

Tests: 111 passed, 5 failed (toutes 5 pré-existantes, non liées aux couleurs:
/blog link manquant, MAPP eyebrow, SOC 2 phrasing, Gitea URL).
HTTP 200 vérifié sur /, /fonctionnalites, /tarifs, /conformite, /legal/,
/legal/conditions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 15:39:09 -04:00
Allison
680df39089 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>
2026-04-28 13:11:02 -04:00
Allison
529bd2263b feat(marketing): round 3 — hero remplacé par 3-step flow canonique + 99+ langues + Cégeps spotlight + CyberPerformance + FAQ enrichie
Hero (templates/marketing/landing.html) :
- Reproduction fidèle de dictia.ca/solutions/dictai (source : Website-Sanity/components/sections/dictai-page-content.tsx lignes 260-518)
- REMPLACE le mockup app DictIA par le 3-step flow inline canonique (Importez → Texte 2 min → Résumé + actions)
- Wordmark large « DictIA » (style production) + H2 cyan « Transcription IA locale en 2 minutes — conforme Barreau, CPA Québec et ChAD »
- Sub canonique référençant OVH Beauharnois, Cadre IA MCN, 5 ordres à directives IA formelles
- Stats grid (4 col) : ~2 min · 5 ordres · 95 %+ · 0 $ (NBSP OQLF)
- Eyebrow back-link « Toutes les solutions »
- 5 animations Framer Motion → CSS pure + Alpine.js :
  1. 3-step flow auto-cycle 1→2→3 (setInterval 1.8 s, désactivé reduced-motion)
  2. Magnetic CTA primary (mousemove → translate max 8 px)
  3. Mouse parallax orb 3D (mousemove window → CSS transition)
  4. Shockwave on click (CSS pseudo-element scale 0→4 + opacity)
  5. Word-staggered title reveal (Dict + IA via animation-delay)

Sections enrichies / ajoutées :
- Pipeline : sous-titre « Du fichier au résumé — en temps réel » + hint canonique
- NEW « 99+ langues détectées » + carte « IA Mistral 7B (LOCAL) » 4 bullets
- Pricing : sous-titres canoniques par forfait + note « Tous les prix en CAD, taxes en sus (TPS 5 % + TVQ 9,975 %) »
- Conformité : 3 chips claims (~192 000 pros · 5 ordres · 0 donnée hors-Québec) + phrase secteurs réglementés
- NEW Cégeps spotlight « Conformité au 19 juin 2026 » avec Cadre IA MCN détaillé (7 bullets, 9 chips organismes, badge pulse glow)
- NEW Partenaire CyberPerformance (card horizontale + lien externe)
- FAQ : enrichie de 7 → 10 questions canoniques sourcées de dictai-page-content.tsx (Teams Copilot, Otter.ai, Barreau, Clio Manage, etc.)
- CTA final : « Prêt à protéger vos données ? » + bouton « Réserver ma démo gratuite » (préserve mailto pré-inscription)

Tests :
- Ajout tests/conftest.py (stub fcntl POSIX + env vars test) pour permettre exécution sur Windows
- Mise à jour 8 assertions liées au nouveau hero, FAQ 10 Q, CTA renforcé, NBSP OQLF dans eyebrow
- 61 passed / 3 pré-existant échecs baseline (/blog dans nav + footer + trust-bar phrasing)

Contraintes respectées : zéro JS externe, aucun emoji (SVG inline aria-hidden), V3 radii (rounded/rounded-full), brand tokens, OQLF NBSP partout, WCAG (aria-labels, focus-visible, prefers-reduced-motion désactive toutes les animations hero).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 12:43:57 -04:00
Allison
69baa1be2f feat(marketing): round 2 — intègre 3 sections de dictia.ca/solutions/dictai (cycle/wave/cadre)
- Cycle "Trois options. Une seule est conforme." (entre PAS Problème & Solution)
  3 colonnes comparatives (humaine 315$/h / cloud US illégal / DictIA 173$/mo)
  Phases reveal 1→4 via IntersectionObserver + setTimeout chain
  Anneaux pulsants source node + horloge rotation + particules fuites cloud
  Overlay légal NON CONFORME sur col 2

- Wave "Onde de transformation" (entre Solution & Pipeline)
  Slider mouse-X interactif : 30 barres SVG morphent rouge → cyan
  Particules tombantes -$/-h (CSS keyframes staggered)
  Étiquettes douleur PAINS / SOLUTIONS flottantes
  Mobile : toggle button, pas de mouse interaction

- Cadre réglementaire "Moniteur d'Interception" (entre Conformité & Témoignages)
  Mappe 6 textes officiels : Loi 25, Loi 96, Cloud Act US, Guide IA Barreau, Cadre IA MCN, CAI
  Liens vers sources autoritaires (legisquebec, congress.gov, barreau, tresor, cai)
  HUD console typing reveal + caret blink + folder QC→US transition
  aria-live="polite" sur verdict, role="list" sur REGS

Texte 100% canonique extrait de Website-Sanity dictai-cycle/wave/contraste.tsx.
Toutes animations CSS pure + Alpine.js + IntersectionObserver natif (zéro lib JS externe).
prefers-reduced-motion désactive tout.
+802 lignes landing.html, +119 lignes tests (6 nouveaux test_round2_*), npm run build:css exécuté.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 12:21:16 -04:00
Allison
48d65c2ab9 refactor(ui): épurer les 3 sections — pas de backdrop tiles, icônes brand-b1 + watermark grad-text
- 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>
2026-04-28 11:04:34 -04:00
Allison
8d50d8ee01 refactor(ui): éliminer tous les emojis (SVG inline + texte propre, look pro/moderne)
Pass de modernisation visuelle : remplacement de TOUS les emojis Unicode dans
les templates marketing/legal/billing/auth par des SVG inline (style heroicons)
ou par du texte propre, pour un look SaaS pro à la Linear/Vercel/Stripe.

Mapping principal :
- ✓ / ✗ / ⚠           → SVG check / x / triangle (text-brand-b3 / red / amber)
- → / ← / ↗            → SVG arrow-right / arrow-left / arrow-up-right
- 🍁 / 🏛️ / ⚖️ / 🔓     → SVG map-pin / building / scale / code-brackets
- 🎙️ / 👥 / 📝 / 💬 / 📄 / 🔌 → 6 SVG bento icons (microphone, users, doc, chat, export, plug)
- ✉️ / ☎️ / 📬          → SVG envelope / phone / map-pin
- ↺                    → SVG refresh-counter-clockwise
- ★                    → SVG star (RECOMMANDÉ badge)
- 🎯/🏢/📺/🤝/📰         → SVG target / office / play / handshake / news (raccourcis contact)
- ⚖️/📊/🏛️ (testimonials) → SVG scale / bar-chart / building
- ✦ (default bento icon) → SVG sparkle inline

Tous les SVG utilisent stroke="currentColor" pour héritage Tailwind text-*.
Les SVG informationnels du tableau comparatif portent un aria-label sémantique
(Conforme/Non conforme/Partiel) ; les SVG décoratifs portent aria-hidden.

Tests :
- 18/18 legal pages passent (test_legal_pages.py)
- test_comparatif_check_marks_consistently_mean_good ajusté pour asserter
  sur les aria-label SVG plutôt que les caractères ✓/✗
- 4 échecs pré-existants non liés (manque /blog dans nav, SOC 2 hedge dans
  conformite.html, gitea.innova-ai.ca url) — confirmés présents avant ce commit

Fichiers modifiés (14) :
- templates/macros/{bento,pricing_card}.html (sources de vérité)
- templates/marketing/{base,_footer,landing,fonctionnalites,tarifs,conformite,contact}.html
- templates/legal/{_layout,index}.html
- templates/billing/{cancel,success}.html
- tests/test_marketing_landing_template.py (assert sur aria-label)

Audit final : 0 emoji restant dans les fichiers in-scope ; 0 emoji dans le
HTML rendu de toutes les pages marketing/legal vérifiées.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 10:52:58 -04:00
Allison
f83fdfcd68 refactor(ui): V3 fully square buttons + inputs (rounded-none, brutalist/Swiss aesthetic)
V3 finalizes the radii pass to a fully brutalist/Swiss visual language:

- Buttons (CTAs, submit, secondary, ghost, OAuth provider tiles): rounded-none (0px)
- Form inputs (text/email/password/select/textarea/code-entry): rounded-none (0px)
- Checkboxes: rounded-none (0px) — was rounded-sm
- Small icon tiles (w-10 h-10 / w-12 h-12 grad-bg squares): rounded-none (0px)
- Inline code blocks (totp recovery <pre>, secret <code>): rounded-none (0px)
- Cards (pricing, bento, content panels, modals, prev/next nav): rounded (4px) — was rounded-lg
- Alert / flash boxes: rounded (4px) — was rounded-lg
- Pills, badges, status chips, ordres pros avatars, decorative cosmic orbs: rounded-full preserved
- Legal _layout.html inline <style> blockquote/pre/code/draft-callout: border-radius 0 — was 4px

Updated tests/test_marketing_landing_template.py assertions:
- bento icon assertion: "grad-bg rounded " -> "grad-bg rounded-none "
- pricing recommended frame: "rounded-lg" -> "rounded" (with strict trailing-char match to avoid rounded-none false positive)

Verification: 18/18 legal tests pass, 58/58 marketing landing tests pass, 5/5 root redirect tests pass. Two pre-existing failures in test_marketing_secondary_pages (SOC 2 hedge text + gitea.innova-ai.ca URL) are unrelated to this radii pass.
2026-04-28 10:26:51 -04:00
Allison
0b91294c45 refactor(ui): sharpen buttons + inputs to rounded (4px) for modern minimal SaaS look
V2 sharper radii system aligned with Stripe Dashboard / Linear / Vercel
aesthetic — the v1 rounded-lg (8px) on buttons still felt too soft.

New scale:
- Buttons (CTA, submit, ghost, secondary): rounded-lg → rounded (4px)
- Form inputs (text/email/password/select/textarea): rounded-md → rounded (4px)
- Checkboxes: rounded-sm (2px) added explicitly to consent + remember-me
- Cards (pricing, bento, content panels): rounded-xl → rounded-lg (8px)
- Small icon tiles (w-10 h-10 / w-12 h-12 grad-bg squares): rounded-md → rounded
- Pills, badges, avatars, status orbs: rounded-full (KEPT)
- Inline code in legal CSS: rounded (4px) (KEPT)
- Legal blockquote/pre/draft-callout border-radius: 8px → 4px

Files modified (24):
- templates/macros/{button,bento,pricing_card}.html
- templates/marketing/{landing,tarifs,fonctionnalites,conformite,contact}.html
- templates/auth/{check_email,forgot_password,magic_link_request,
  oauth_finish_signup,passkey_setup,reset_password,totp_setup,totp_verify,
  verify_success}.html
- templates/billing/{success,cancel}.html
- templates/legal/{_layout,index}.html
- templates/{register,login}.html
- tests/test_marketing_landing_template.py (assertions updated to match v2)

Verification:
- 18/18 legal page tests pass (tests/_run_legal_pages_windows.py)
- 58/58 marketing landing tests pass

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 10:13:03 -04:00
Allison
48ff4e70e6 refactor(ui): modernize button + input border radii (rounded-lg/md/xl, sharper SaaS aesthetic)
Aligns DictIA marketing/auth/legal/billing templates with modern SaaS visual
conventions (Linear, Vercel, Stripe Dashboard, Notion). Old radii (12-18px)
felt dated; new system uses 6-12px for tighter, more contemporary corners.

Border radius system:
- Buttons (CTA, submit, secondary): rounded-[0.75rem] (12px) -> rounded-lg (8px)
- Form inputs (text/email/password/select/textarea/checkbox): rounded-[0.5rem] -> rounded-md (6px)
- Cards (pricing, bento, modals, content panels): rounded-[18px]/[14px]/[12px] -> rounded-xl (12px)
- Pricing card outer gradient frame: rounded-[20px] -> rounded-xl (matches inner)
- Pills / badges / status chips: KEEP rounded-full
- Avatars / circular icon containers: KEEP rounded-full
- Code blocks: KEEP rounded (4px)

Decision tree applied for ambiguous cases:
- Button-like clickable CTA -> rounded-lg
- Form input -> rounded-md
- Card / panel / modal -> rounded-xl
- Badge / pill / chip / avatar -> rounded-full (preserved)

In-scope templates modified (23):
- macros/button.html (central macro, cascades to all callers)
- macros/pricing_card.html, macros/bento.html
- marketing/landing.html, tarifs.html, fonctionnalites.html, conformite.html, contact.html
- auth/check_email.html, forgot_password.html, magic_link_request.html, oauth_finish_signup.html,
  passkey_setup.html, reset_password.html, totp_setup.html, totp_verify.html, verify_success.html
- billing/cancel.html, billing/success.html
- legal/_layout.html, legal/index.html
- register.html, login.html

Out of scope (untouched): index.html, account.html, admin.html, share.html, inquire.html,
group-admin.html, components/**, includes/**, modals/** (all legacy Speakr Vue surfaces).

Tests: test_marketing_landing_template.py — 2 assertions updated to match new bento icon
(rounded-md) and pricing card frame (rounded-xl). All 18 legal tests + 58 marketing landing
tests + 9 signup_loi25 tests still pass. Decorative rounded-full preserved on hero cosmic
orbs and ordres-pros avatar circles.

Diff: 94 insertions / 94 deletions (1:1 mechanical replacement, no class drift).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 09:55:13 -04:00
Allison
202e1a08d9 fix(marketing): A-2.8a — extract pricing partial + sync bento + OQLF + test calibration
- 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&eacute;b&eacute;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&eacute;silie' -> 'résilie' (Jinja outputs raw UTF-8, not entities)
- Update src/marketing/routes.py module docstring to reflect 2/4 done.
2026-04-27 21:06:26 -04:00
Allison
2b3eeb98e0 fix(marketing): A-2.7b WCAG 2.2 AA polish + JSON-LD test hardening
- 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)
2026-04-27 20:34:53 -04:00
Allison
824ea638de feat(marketing): A-2.7b témoignages placeholder + FAQ accordion + CTA + JSON-LD
- Pre-launch testimonials section: 3 placeholder cards (avocat, CPA, municipal)
  with persona icons + 'Témoignage à venir' label — NO fabricated quotes
  (LPC art. 219). Expected publication mai-juin 2026 from T-4.1 interviews.
- FAQ accordion: 7 verifiable Q&A using Alpine.js core (x-data + x-show +
  built-in x-transition; NO x-collapse plugin). Each item has @click toggle,
  :aria-expanded, aria-controls, role="region" panel, focusable button.
- Schema.org FAQPage JSON-LD inline at end of FAQ section — striptags +
  replace('&nbsp;', ' ') to normalize entities for Google FAQ rich result.
- CTA final: 'Réservez votre pré-inscription' (mailto + #tarifs anchor),
  cosmic orbs to mirror Hero (page closure), ghost variant secondary button.
- Inline TESTIMONIALS and FAQ Python lists in src/marketing/routes.py
  (no PyYAML dep — YAGNI; T-4.1 can introduce it when real data warrants).
- 8 new tests covering testimonials placeholders, forbidden fake names,
  7 FAQ panels, Alpine bindings, JSON-LD schema, CTA wording, route data.
2026-04-27 19:52:36 -04:00
Allison
31fada46d4 fix(marketing): A-2.7a — comparatif consistency + SOC 2 hedge + cross-platform emoji
- 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>
2026-04-27 19:36:01 -04:00
Allison
0d69fcd034 feat(marketing): A-2.7a footer 4-col + comparatif table + conformité 4 pillars
- Replace placeholder _footer.html with full 4-column footer (Brand, Produit,
  Légal, Compte) — added aria-labelledby landmark, sr-only headings, address
  block, tel: link, external-link new-tab announcements, NBSP per OQLF
- Add Comparatif section: DictIA vs MS Teams vs Otter.ai vs Whisper local
  on 6 criteria. Sourced (politiques publiques + grilles officielles 2026-04-27),
  trademark disclaimer, responsive table with sr-only caption + scope attrs
- Add Conformité forteresse section: 4 pillars (OVH Beauharnois, mapped Loi 25
  LPRPSP refs, compatible Cadre IA LGGRI, AGPL v3 verifiable Gitea link)
- Soft hedges throughout: 'mappé', 'conçu avec', 'compatible' (no 'certifié',
  'endossé', 'reconnu' — LPC art. 219 / Competition Act s. 52 hygiene)
- 11 new tests covering footer landmarks, comparatif sourcing, conformité
  hedges, WCAG /70 contrast, and forbidden competitive claim regressions

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 19:21:39 -04:00
Allison
7d67b64ddc fix(marketing): pricing — honest ROI payback + capped sliders + URL hygiene
- 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>
2026-04-27 19:05:36 -04:00
Allison
0ae4053faa feat(marketing): pricing 3 forfaits + ROI calculator Alpine.js 2026-04-27 18:50:33 -04:00
Allison
b87f35ea4a fix(marketing): bento autoescape + dead col-span + test gaps
- Pipe macro title/description through | safe to render NBSP/&amp; correctly
  (autoescape was producing literal '95&nbsp;%+' and 'Q&amp;R' text on screen)
- Replace dynamic col-span-{{ span }} with static lookup table so Tailwind
  scanner generates the utilities for A-2.7+ reuse
- Replace inline border style with border-white/[0.045] utility (codebase consistency)
- Add explicit Q&R assertion + autoescape regression guard test
2026-04-27 18:19:56 -04:00
Allison
775075d1ea feat(marketing): bento grid 6 features (style FlexiHub) 2026-04-27 18:03:57 -04:00
Allison
3c471a72d1 feat(marketing): PAS frame sections (Problème + Solution) after trust bar
- 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 &nbsp; + |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.
2026-04-27 17:42:46 -04:00
Allison
54168e443b fix(marketing): trust bar accuracy + WCAG AA contrast + LPC art. 219 hygiene
- 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 &nbsp; 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.
2026-04-27 17:35:43 -04:00
Allison
2a7e142b03 feat(marketing): trust bar with 9 ordres pros + 4 KPIs + methodology footnote
- 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
2026-04-27 17:27:03 -04:00
Allison
b24a0f064d fix(marketing): WCAG 2.3.3 reduced-motion + defensible social proof + em-spacing
- 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>
2026-04-27 17:19:16 -04:00
Allison
03af2a516d feat(marketing): hero section with cosmic orbs + dual CTA + social proof
- 3 radial-gradient orbs (blue 16%, cyan 7%, green 11%) + subtle 40px
  grid + horizontal accent line — FlexiHub cosmic background signature
- H1 clamp(2.5rem,4vw,4rem) font-black with grad-text accent on
  'sans risquer votre permis' tagline
- Eyebrow 11px tracking-[0.18em] grad-text — 'TRANSCRIPTION IA · CONFORME LOI 25 · QUÉBEC'
- Sub-headline ≤25 words declares Loi 25 compliance + 9 ordres pros
- Dual CTA: Réserver une démo (primary gradient+glow) + Voir les tarifs
  → (ghost) — drives demo conversion + pricing self-service
- Social proof microcopy above-the-fold: 5★ + 27 cabinets + Lancement
  printemps 2026
- Staggered tc-fade-in-up animations 0/75/150/300/400ms with
  animation-fill-mode: backwards (no FOIT)
- 6 new tests verify H1 grad-text, dual CTA, orb opacities, social proof,
  staggered delays, eyebrow messaging
2026-04-27 17:13:02 -04:00
Allison
49bf94576c feat(marketing): base.html layout + glassmorphism header + button macro
- templates/macros/button.html: 3 variants (primary gradient/glow, secondary,
  ghost) x 3 sizes for reuse across marketing/billing/legal/auth templates
- templates/marketing/base.html: Tailwind v4-scoped layout with FlexiHub
  glassmorphism header (62px, navy/.97, backdrop-blur-xl, .045 border),
  sticky positioning, OG/Twitter meta, Inter font preload, marketing.css
  link, Alpine.js defer, 5-item main nav + Connexion/Demarrer CTAs
- templates/marketing/_footer.html: minimal Phase 2 placeholder with
  legal links + Inverness QC address + info@dictia.ca (full footer in A-2.7)
- templates/marketing/landing.html: minimal hero placeholder (replaced
  in A-2.2 with full hero + cosmic orbs)
- src/marketing/routes.py: landing() now render_template instead of inline HTML
- 7 tests verify template structure, FlexiHub markers, nav, CTAs, legal
  links, no login redirect for anonymous users
- Tailwind CSS rebuilt with new template content scope (cssnano-minified)
2026-04-27 16:51:06 -04:00