Commit Graph

11 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
3e56736fa7 feat(marketing): refonte fonctionnalites avec contenu canonique + animations modernes subtiles
7 sections (hero stats counter, sticky sub-nav, 6 fonctionnalités bento avec chips
specs, 3 sous-groupes intégrations, tableau architecture 3 tiers, conformité résumée
+ lien /conformite, CTA final). Contenu canonique extrait du site prod (WhisperX
Large-v3, pyannote-audio, Mistral 7B, RAG sentence-transformers, 8 locuteurs,
30× temps réel, 95%+ FR-CA, prix 3 450/5 750/369 $).

Animations: counter rAF easeOutCubic via Alpine + IntersectionObserver, fade-in
stagger via data-ani-fade, animated underline H2, hover lift cards, sticky sub-nav
avec active highlight, cosmic orbs flottantes, pulse glow sur card recommandée.
Toutes les animations respectent prefers-reduced-motion via media query inline.

Conserve les sections exports/specs/integrations grid pour rétro-compat tests.
13 assertions pytest fonctionnalites passent (les 2 failures conformite sont
pré-existantes sur Windows — mojibake console, non liées à cette refonte).
2026-04-28 11:28:15 -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
d471626183 feat(marketing): A-2.8a /tarifs + /fonctionnalites standalone pages
- /tarifs page: extends base.html, reuses pricing_card + button macros,
  shows the 3 forfaits with NBSP-formatted CAD prices, an 8-row deep-dive
  comparison matrix (DictIA 8 vs DictIA 16 vs DictIA Cloud), 5 tarification
  FAQ items (frais cachés, migration, GPU, taxes TPS/TVQ, plans annuels)
  with Alpine accordion + focus-visible WCAG 2.2 AA, CTA section
- /fonctionnalites page: extends base.html, reuses bento_card macro,
  re-renders the 6 features with same content as landing's bento section
  for consistency, adds dedicated 7-format export grid + 8-integration
  grid (with trademark disclaimer) + 6 tech specs section (Whisper/pyannote
  /Mistral/stack/audio/langues), CTA section
- routes.py: add /tarifs and /fonctionnalites routes (passes FAQ to /tarifs
  for the tarification accordion; preserves existing landing(), TESTIMONIALS,
  FAQ data structures unchanged)
- tests/test_marketing_secondary_pages.py: NEW test file (16 tests covering
  routes 200, base.html inheritance, H1 anchors, 3 pricing cards, comparison
  matrix, tarifs FAQ accordion, OQLF typography, 6 bento + 7 exports + 8
  integrations + 6 tech specs sections, canonical meta)
- All sections respect WCAG 2.2 AA, FlexiHub design discipline, LPC art. 219
  hygiene (sourcing dates, trademark disclaimer, hedged claims, NBSP)
2026-04-27 20:50:07 -04:00