diff --git a/src/marketing/routes.py b/src/marketing/routes.py index f2b5f57..af7d017 100644 --- a/src/marketing/routes.py +++ b/src/marketing/routes.py @@ -2,7 +2,7 @@ Phase 2 (A-2.1+): renders templates/marketing/landing.html. Tasks A-2.2 through A-2.7 will progressively enrich the landing template. -Tasks A-2.8 will add /tarifs, /fonctionnalites, /conformite, /contact routes. +Task A-2.8a added /tarifs and /fonctionnalites; A-2.8b will add /conformite and /contact. """ from flask import render_template diff --git a/static/css/marketing.css b/static/css/marketing.css index add2a8b..51921fa 100644 --- a/static/css/marketing.css +++ b/static/css/marketing.css @@ -2303,9 +2303,6 @@ .text-\[clamp\(2\.25rem\,4vw\,3\.5rem\)\] { font-size: clamp(2.25rem, 4vw, 3.5rem); } - .text-\[clamp\(2rem\,3vw\,2\.5rem\)\] { - font-size: clamp(2rem, 3vw, 2.5rem); - } .text-\[clamp\(2rem\,3vw\,2\.75rem\)\] { font-size: clamp(2rem, 3vw, 2.75rem); } diff --git a/templates/marketing/_partials/_pricing_tiers.html b/templates/marketing/_partials/_pricing_tiers.html new file mode 100644 index 0000000..a11e00f --- /dev/null +++ b/templates/marketing/_partials/_pricing_tiers.html @@ -0,0 +1,30 @@ +{# Single source of truth for the 3 pricing tiers — used by landing.html#tarifs and /tarifs page. + When prices change, edit ONLY this file. #} +{% 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'] + ) }} +
diff --git a/templates/marketing/fonctionnalites.html b/templates/marketing/fonctionnalites.html index 2421a10..c674b87 100644 --- a/templates/marketing/fonctionnalites.html +++ b/templates/marketing/fonctionnalites.html @@ -22,6 +22,8 @@

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}"