Six fonctionnalités principales
+ {# NOTE: bento card content is duplicated between landing.html and fonctionnalites.html.
+ When editing, sync both files. Future refactor: extract to _partials/_bento_features.html. #}
{% from 'macros/bento.html' import bento_card %}
{{ bento_card('01', 'Transcription WhisperX', 'Large-v3 fine-tuné FR-CA. Précision 95 %+ sur réunions, dictées, audiences (méthodologie disponible sur demande).', '🎙️') }}
@@ -108,7 +110,7 @@
{% for spec in [
- {'title': 'Modèle ASR', 'desc': 'WhisperX Large-v3 (1,55 G paramètres) fine-tuné sur audio professionnel québécois. Format ONNX optimisé GPU.'},
+ {'title': 'Modèle ASR', 'desc': 'WhisperX Large-v3 (1,55 G paramètres) fine-tuné sur audio professionnel québécois. Format ONNX optimisé GPU.'},
{'title': 'Diarisation', 'desc': 'pyannote 3.x — clustering hiérarchique sur embeddings ECAPA-TDNN. 1 à 8 locuteurs détectés automatiquement.'},
{'title': 'LLM (résumés / Q&R)', 'desc': 'Mistral 7B Instruct quantifié 4-bit. Inférence locale sur le même GPU. Aucune sortie réseau.'},
{'title': 'Stack web', 'desc': 'Flask 2.3 (backend) + Vue 3 / Alpine.js (front). Chiffrement AES-256 au repos. AGPL v3.'},
diff --git a/templates/marketing/landing.html b/templates/marketing/landing.html
index d83ff7e..153e11c 100644
--- a/templates/marketing/landing.html
+++ b/templates/marketing/landing.html
@@ -195,10 +195,12 @@
+ {# NOTE: bento card content is duplicated between landing.html and fonctionnalites.html.
+ When editing, sync both files. Future refactor: extract to _partials/_bento_features.html. #}
{% from 'macros/bento.html' import bento_card %}
{{ bento_card('01', 'Transcription WhisperX', 'Large-v3 fine-tuné FR-CA. Précision 95 %+ sur réunions, dictées, audiences (méthodologie disponible sur demande).', '🎙️') }}
- {{ bento_card('02', 'Diarisation 8 locuteurs', 'pyannote sépare automatiquement les intervenants. Identification par embeddings.', '👥') }}
+ {{ bento_card('02', 'Diarisation 8 locuteurs', 'pyannote sépare automatiquement les intervenants. Identification par embeddings vocaux.', '👥') }}
{{ bento_card('03', 'Résumés Mistral 7B', 'IA locale génère résumés, points d\'action et procès-verbaux. Aucune connexion cloud.', '📝') }}
{{ bento_card('04', 'Q&R sur enregistrement', 'Posez des questions à vos réunions. RAG local sur embeddings sentence-transformers.', '💬') }}
{{ bento_card('05', 'Exports multiples', 'DOCX, PDF, SRT, VTT, TXT, JSON, MD. Formats avocat, notaire, CPA.', '📄') }}
@@ -220,34 +222,7 @@
- {% from 'macros/pricing_card.html' import pricing_card %}
-
- {{ pricing_card(
- 'dictia-8',
- 'DictIA 8',
- '3 450 $',
- '173 $',
- 'PME · RH · Manufacturiers',
- ['GPU 8 Go RTX', 'Volume illimité', 'WhisperX FR-CA', 'Diarisation 8 locuteurs', 'Support inclus']
- ) }}
- {{ pricing_card(
- 'dictia-16',
- 'DictIA 16',
- '5 750 $',
- '201 $',
- 'Cabinets juridiques · CPA · Finance',
- ['GPU 16 Go RTX', 'Mistral 7B local', 'Q&R sur enregistrement', 'Tout DictIA 8', 'Support prioritaire'],
- recommended=True
- ) }}
- {{ pricing_card(
- 'dictia-cloud',
- 'DictIA Cloud',
- '0 $',
- '369 $',
- 'Organismes · Municipalités · Multi-sites',
- ['Hébergé OVH Beauharnois (Québec)', 'Opérationnel sous 48 h', 'Aucun matériel à gérer', 'SLA visé 99,9 %', 'Conforme Loi 25']
- ) }}
-
+ {% include 'marketing/_partials/_pricing_tiers.html' %}
{# ROI CALCULATOR — Alpine.js, hypotheses transparentes pour LPC art. 219 hygiene #}
diff --git a/templates/marketing/tarifs.html b/templates/marketing/tarifs.html
index e40b2bb..23f7264 100644
--- a/templates/marketing/tarifs.html
+++ b/templates/marketing/tarifs.html
@@ -22,34 +22,7 @@
Trois forfaits DictIA
- {% from 'macros/pricing_card.html' import pricing_card %}
-
- {{ pricing_card(
- 'dictia-8',
- 'DictIA 8',
- '3 450 $',
- '173 $',
- 'PME · RH · Manufacturiers',
- ['GPU 8 Go RTX', 'Volume illimité', 'WhisperX FR-CA', 'Diarisation 8 locuteurs', 'Support inclus']
- ) }}
- {{ pricing_card(
- 'dictia-16',
- 'DictIA 16',
- '5 750 $',
- '201 $',
- 'Cabinets juridiques · CPA · Finance',
- ['GPU 16 Go RTX', 'Mistral 7B local', 'Q&R sur enregistrement', 'Tout DictIA 8', 'Support prioritaire'],
- recommended=True
- ) }}
- {{ pricing_card(
- 'dictia-cloud',
- 'DictIA Cloud',
- '0 $',
- '369 $',
- 'Organismes · Municipalités · Multi-sites',
- ['Hébergé OVH Beauharnois (Québec)', 'Opérationnel sous 48 h', 'Aucun matériel à gérer', 'SLA visé 99,9 %', 'Conforme Loi 25']
- ) }}
-
+ {% include 'marketing/_partials/_pricing_tiers.html' %}
@@ -83,7 +56,7 @@
{'name': 'Diarisation', 'd8': '8 locuteurs', 'd16': '8 locuteurs', 'cloud': '8 locuteurs'},
{'name': 'Résumés Mistral 7B local', 'd8': '—', 'd16': '✓', 'cloud': '✓ (mutualisé)'},
{'name': 'Q&R sur enregistrement', 'd8': '—', 'd16': '✓', 'cloud': '✓'},
- {'name': 'Délai de mise en service', 'd8': '~2 semaines', 'd16': '~2 semaines', 'cloud': '48 h'}
+ {'name': 'Délai de mise en service', 'd8': '~2 semaines', 'd16': '~2 semaines', 'cloud': '48 h'}
] %}
| {{ row.name | safe }} |
@@ -107,7 +80,7 @@
QUESTIONS DE TARIFICATION
-
Vos questions sur les tarifs.
+
Vos questions sur les tarifs.
diff --git a/tests/test_marketing_landing_template.py b/tests/test_marketing_landing_template.py
index af55b5e..223d69a 100644
--- a/tests/test_marketing_landing_template.py
+++ b/tests/test_marketing_landing_template.py
@@ -199,7 +199,8 @@ def test_pas_probleme_section_present():
client = app.test_client()
body = client.get('/').data.decode('utf-8')
assert 'PROBL' in body and 'TRANSCRIPTION CLOUD' in body, "Missing Problème eyebrow"
- assert 'violent la Loi 25' in body, "Missing legal-risk H2 anchor phrase"
+ assert 'violent la Loi 25' in body or 'violent la Loi 25' in body, \
+ "Missing legal-risk H2 anchor phrase"
assert 'Cloud Act' in body, "Missing Cloud Act card"
assert 'biom' in body and 'Loi 25' in body, "Missing Loi 25 biometric card"
assert 'Sanctions disciplinaires' in body, "Missing sanctions disciplinaires card"
@@ -661,7 +662,7 @@ def test_faq_section_with_7_questions():
assert f'id="faq-panel-{i}"' in body, f"Missing FAQ panel {i}"
# Question topic anchors
topics = ['Loi', 'Cloud et DictIA on-premise', 'fran', 'audiences', 'formats',
- 'résilie', 'AGPL']
+ 'résilie', 'AGPL']
for topic in topics:
assert topic in body, f"FAQ missing topic anchor: {topic}"
diff --git a/tests/test_marketing_secondary_pages.py b/tests/test_marketing_secondary_pages.py
index 5f43824..e0aeec1 100644
--- a/tests/test_marketing_secondary_pages.py
+++ b/tests/test_marketing_secondary_pages.py
@@ -141,7 +141,7 @@ def test_fonctionnalites_tech_specs_6_items():
client = app.test_client()
body = client.get('/fonctionnalites').data.decode('utf-8')
assert 'specs-title' in body
- for spec_keyword in ['Modèle ASR', 'pyannote', 'Mistral 7B', 'Flask', 'WAV, MP3', 'québécois']:
+ for spec_keyword in ['Modèle ASR', 'pyannote', 'Mistral 7B', 'Flask', 'WAV, MP3', 'québécois']:
assert spec_keyword in body, f"Missing tech spec keyword: {spec_keyword}"