Files
dictia-public/templates/marketing/fonctionnalites.html
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

617 lines
36 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends 'marketing/base.html' %}
{% block title %}Fonctionnalités DictIA — WhisperX FR-CA, diarisation 8 locuteurs, Mistral 7B local, Q&R, exports DOCX/PDF/SRT{% endblock %}
{% block description %}Toutes les fonctionnalités de DictIA : transcription WhisperX Large-v3 fine-tunée FR-CA, diarisation pyannote 8 locuteurs, résumés Mistral 7B local, chat Q&R RAG, synchronisation audio-texte, exports multi-formats, intégrations Word, Outlook, Teams, Notion, Obsidian, Zapier.{% endblock %}
{% block head_extra %}
{# Page-scoped CSS — animations subtiles sans dépendre d'un rebuild Tailwind ; respecte prefers-reduced-motion via base.css. #}
<style>
/* Animated underline H2 — visible classe ajoutée via IntersectionObserver */
.ani-underline { position: relative; display: inline-block; }
.ani-underline::after {
content: '';
position: absolute;
left: 50%;
bottom: -10px;
width: 0;
height: 3px;
background: linear-gradient(118deg, #2563eb, #06b6d4 52%, #06b6d4);
transform: translateX(-50%);
transition: width 600ms ease-out;
}
.ani-underline.is-visible::after { width: 56px; }
/* Stagger fade-in cards — class ajoutée par IntersectionObserver */
.ani-fade { opacity: 0; transform: translateY(16px); transition: opacity 600ms ease-out, transform 600ms ease-out; transition-delay: var(--delay, 0ms); }
.ani-fade.is-visible { opacity: 1; transform: translateY(0); }
/* Hover lift cards */
.ani-lift { transition: transform 200ms ease-out, box-shadow 200ms ease-out; }
.ani-lift:hover { transform: translateY(-2px); box-shadow: 0 8px 32px rgba(37,99,235, 0.18); }
/* Sticky sub-nav active link */
.subnav-link[aria-current="true"] { color: #2563eb; }
.subnav-link[aria-current="true"]::after {
content: '';
display: block;
height: 2px;
margin-top: 4px;
background: linear-gradient(118deg, #2563eb, #06b6d4 52%, #06b6d4);
}
/* Cosmic float orbs (n'utilise pas tc-float-y pour éviter rebuild) */
@keyframes orb-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-12px); } }
.orb-float-a { animation: orb-float 8s ease-in-out infinite; }
.orb-float-b { animation: orb-float 11s ease-in-out infinite reverse; }
/* DictIA Cloud pulse glow */
@keyframes card-pulse-glow {
0%, 100% { box-shadow: 0 4px 20px rgba(37,99,235, 0.28); }
50% { box-shadow: 0 12px 40px rgba(37,99,235, 0.5); }
}
.card-pulse-glow { animation: card-pulse-glow 3s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
.ani-fade { opacity: 1; transform: none; transition: none; }
.ani-underline::after { transition: none; width: 56px; }
.ani-lift { transition: none; }
.ani-lift:hover { transform: none; }
.orb-float-a, .orb-float-b, .card-pulse-glow { animation: none; }
}
</style>
{% endblock %}
{% block content %}
{%- set icon_microphone = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-7 h-7" aria-hidden="true"><rect x="9" y="2" width="6" height="12" rx="3"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" y1="19" x2="12" y2="22"/></svg>' -%}
{%- set icon_users = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-7 h-7" aria-hidden="true"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>' -%}
{%- set icon_document = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-7 h-7" aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="9" y1="13" x2="15" y2="13"/><line x1="9" y1="17" x2="15" y2="17"/></svg>' -%}
{%- set icon_chat = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-7 h-7" aria-hidden="true"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>' -%}
{%- set icon_sync = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-7 h-7" aria-hidden="true"><polyline points="23 4 23 10 17 10"/><polyline points="1 20 1 14 7 14"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10"/><path d="M20.49 15a9 9 0 0 1-14.85 3.36L1 14"/></svg>' -%}
{%- set icon_export = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-7 h-7" aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>' -%}
{%- set icon_check = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4 mt-0.5 flex-shrink-0 text-brand-b3" aria-hidden="true"><path d="M5 13l4 4L19 7"/></svg>' -%}
{%- set icon_link = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4" aria-hidden="true"><path d="M5 12h14M13 5l7 7-7 7"/></svg>' -%}
{# ===== HERO ===== #}
<section class="relative overflow-hidden bg-brand-navy text-white py-24 md:py-28" aria-labelledby="page-title">
{# Cosmic orbs background — float animation subtile #}
<div class="absolute inset-0 pointer-events-none" aria-hidden="true">
<div class="orb-float-a absolute top-1/4 left-1/4 w-[600px] h-[600px] rounded-full"
style="background: radial-gradient(circle, rgba(37,99,235,0.16) 0%, transparent 60%); filter: blur(40px);"></div>
<div class="orb-float-b absolute top-1/2 right-1/4 w-[500px] h-[500px] rounded-full"
style="background: radial-gradient(circle, rgba(6,182,212,0.07) 0%, transparent 60%); filter: blur(40px);"></div>
<div class="absolute inset-0"
style="background-image: linear-gradient(rgba(255,255,255,0.02) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.02) 1px, transparent 1px); background-size: 40px 40px;"></div>
<div class="absolute top-1/3 left-0 right-0 h-px"
style="background: linear-gradient(90deg, transparent, rgba(37,99,235,0.3), rgba(6,182,212,0.2), transparent);"></div>
</div>
<div class="relative max-w-[1200px] mx-auto px-6 text-center">
<p class="eyebrow grad-text mb-5 animate-tc-fade-in-up" style="animation-delay: 0ms; animation-fill-mode: backwards;">
FONCTIONNALITÉS · WHISPERX · MISTRAL 7B
</p>
<h1 id="page-title" class="text-[clamp(2.25rem,4vw,3.75rem)] font-black leading-[1.05] mb-5 max-w-3xl mx-auto animate-tc-fade-in-up" style="animation-delay: 75ms; animation-fill-mode: backwards;">
Tout ce qu'il vous faut pour transcrire <span class="grad-text">en restant chez soi</span>.
</h1>
<p class="text-lg text-white/70 max-w-2xl mx-auto mb-12 animate-tc-fade-in-up" style="animation-delay: 150ms; animation-fill-mode: backwards;">
Pile technique 100&nbsp;% québécoise. Inférence sur GPU local ou OVH Beauharnois. Aucun transit cloud américain. Conçu avec 9&nbsp;ordres professionnels.
</p>
{# Stats hero — counter via Alpine x-data + IntersectionObserver pour déclenchement #}
<div class="grid grid-cols-2 md:grid-cols-4 gap-8 max-w-4xl mx-auto" role="list">
{% for stat in [
{'target': 95, 'suffix': '&nbsp;%+', 'label': "précision FR-CA", 'sub': 'WhisperX Large-v3'},
{'target': 30, 'suffix': '×', 'label': "vitesse temps réel", 'sub': '1 h audio → ~5 min'},
{'target': 8, 'suffix': '', 'label': "locuteurs simultanés", 'sub': 'pyannote-audio'},
{'target': 0, 'suffix': '', 'label': "transit cloud", 'sub': '100&nbsp;% local'}
] %}
<div class="text-center" role="listitem"
x-data="{ value: 0, target: {{ stat.target }} }"
x-init="
const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (reduced) { value = target; return; }
const io = new IntersectionObserver((entries) => {
if (!entries[0].isIntersecting) return;
const start = performance.now();
const dur = 1200;
const tick = (now) => {
const t = Math.min(1, (now - start) / dur);
value = Math.round(target * (1 - Math.pow(1 - t, 3)));
if (t < 1) requestAnimationFrame(tick);
};
requestAnimationFrame(tick);
io.disconnect();
}, { threshold: 0.5 });
io.observe($el);
">
<div class="text-5xl font-black grad-text mb-2 tabular-nums">
<span x-text="value"></span><span>{{ stat.suffix | safe }}</span>
</div>
<div class="text-sm font-semibold text-white mb-1">{{ stat.label }}</div>
<div class="text-xs text-white/60">{{ stat.sub | safe }}</div>
</div>
{% endfor %}
</div>
</div>
</section>
{# ===== STICKY SUB-NAV ===== #}
<nav class="sticky top-[62px] z-40 bg-white/95 backdrop-blur-sm border-b border-brand-border" aria-label="Navigation des sections de la page"
x-data="{ active: 'fonctionnalites' }"
x-init="
const sections = ['fonctionnalites', 'integrations', 'architecture', 'conformite-resume'];
const io = new IntersectionObserver((entries) => {
entries.forEach(e => {
if (e.isIntersecting && e.intersectionRatio > 0.15) active = e.target.id;
});
}, { rootMargin: '-120px 0px -55% 0px', threshold: [0, 0.15, 0.3] });
sections.forEach(id => { const el = document.getElementById(id); if (el) io.observe(el); });
">
<div class="max-w-[1200px] mx-auto px-6">
<ul class="flex flex-wrap gap-x-6 gap-y-1 py-3 text-sm font-semibold text-brand-navy/70" role="list">
<li><a href="#fonctionnalites" class="subnav-link inline-block py-1 hover:text-brand-b1 transition-colors focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
:aria-current="active === 'fonctionnalites' ? 'true' : 'false'">Fonctionnalités</a></li>
<li><a href="#integrations" class="subnav-link inline-block py-1 hover:text-brand-b1 transition-colors focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
:aria-current="active === 'integrations' ? 'true' : 'false'">Intégrations</a></li>
<li><a href="#architecture" class="subnav-link inline-block py-1 hover:text-brand-b1 transition-colors focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
:aria-current="active === 'architecture' ? 'true' : 'false'">Architecture</a></li>
<li><a href="#conformite-resume" class="subnav-link inline-block py-1 hover:text-brand-b1 transition-colors focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
:aria-current="active === 'conformite-resume' ? 'true' : 'false'">Conformité</a></li>
</ul>
</div>
</nav>
{# ===== 6 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.
#}
<section id="fonctionnalites" class="bg-white py-20 scroll-mt-32" aria-labelledby="features-title">
<div class="max-w-[1200px] mx-auto px-6">
<div class="text-center max-w-3xl mx-auto mb-14">
<p class="eyebrow grad-text mb-4">SIX FONCTIONNALITÉS</p>
<h2 id="features-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black text-brand-navy">
<span class="ani-underline" data-ani-underline>Conçu pour les pros qui parlent et écrivent toute la journée.</span>
</h2>
<p class="text-lg text-brand-navy/70 mt-6">
Chaque module fonctionne hors-ligne sur votre matériel ou notre VPS Québec OVH. Aucun appel à OpenAI, Microsoft Copilot ou Google.
</p>
</div>
{% from 'macros/bento.html' import bento_card %}
{%- set features = [
{
'n': '01',
'title': 'Transcription IA locale FR-CA',
'desc': 'WhisperX Large-v3 entraîné sur des millions d\'heures de québécois juridique, médical et gouvernemental. 95&nbsp;%+ dès la première utilisation, sans aucun ajustement manuel.',
'icon': icon_microphone,
'chips': ['WhisperX Large-v3', 'GPU RTX 8 ou 16&nbsp;Go', '1 h audio → ~5 min', '< 5&nbsp;% taux d\'erreur', '100&nbsp;% local · hors-ligne']
},
{
'n': '02',
'title': 'Identification des locuteurs (diarisation)',
'desc': 'Jusqu\'à 8 interlocuteurs distingués automatiquement. Chaque prise de parole est étiquetée et horodatée pour une lecture nette des comités, audiences et entrevues.',
'icon': icon_users,
'chips': ['pyannote-audio 3.x', '8 personnes max', 'Étiquettes auto', 'Horodatage word-level']
},
{
'n': '03',
'title': 'Résumés &amp; points d\'action',
'desc': 'Résumé exécutif, décisions clés et liste d\'actions générés en français. Format avocat, notaire, CPA ou médecin selon votre profil. Récupérez ~2 h/jour de rédaction.',
'icon': icon_document,
'chips': ['Mistral 7B local (DictIA 16+)', 'Templates pro', 'Décisions + actions', '2&nbsp;h/jour récupérées']
},
{
'n': '04',
'title': 'Chat IA sur enregistrement (Q&amp;R)',
'desc': 'Posez vos questions directement sur l\'audio : « Quel montant a été mentionné&nbsp;?&nbsp;» ou « Quels engagements ont été pris&nbsp;? » réponses instantanées en langage naturel.',
'icon': icon_chat,
'chips': ['Mistral 7B local', 'RAG local', 'sentence-transformers', 'Recherche contextuelle']
},
{
'n': '05',
'title': 'Synchronisation audio-texte',
'desc': 'Cliquez sur n\'importe quel mot pour sauter à ce moment dans l\'audio. Suivi automatique en lecture avec mot actif surligné révision et référencement instantanés.',
'icon': icon_sync,
'chips': ['Timestamps word-level', 'Lecture guidée', 'Mot actif surligné', 'Navigation par mot clé']
},
{
'n': '06',
'title': 'Recherche sémantique &amp; exports',
'desc': 'Recherchez par sens et non seulement par mot-clé. Exportez vers DOCX, PDF, SRT, VTT, TXT, JSON, MD compatible Obsidian, Notion, Logseq via Markdown.',
'icon': icon_export,
'chips': ['DOCX, PDF, SRT, VTT', 'TXT, JSON, MD', 'Obsidian · Notion · Logseq', 'Format avocat / notaire / CPA']
}
] -%}
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-[1.5px] bg-brand-border rounded overflow-hidden">
{% for f in features %}
<article class="ani-fade ani-lift relative bg-brand-navy2 p-6 overflow-hidden border border-white/[0.045]"
style="--delay: {{ loop.index0 * 60 }}ms;"
data-ani-fade>
<div class="absolute top-2 right-4 text-[80px] font-black grad-text opacity-20 leading-none" aria-hidden="true">{{ f.n }}</div>
<div class="relative">
<div class="text-brand-b1 mb-4" aria-hidden="true">{{ f.icon | safe }}</div>
<h3 class="text-lg font-bold mb-2 text-white">{{ f.title | safe }}</h3>
<p class="text-sm text-white/70 leading-relaxed mb-4">{{ f.desc | safe }}</p>
<ul class="flex flex-wrap gap-1.5" role="list">
{% for chip in f.chips %}
<li class="text-[11px] font-mono font-medium text-white/80 bg-white/[0.06] border border-white/[0.08] px-2 py-1 rounded-full">{{ chip | safe }}</li>
{% endfor %}
</ul>
</div>
</article>
{% endfor %}
</div>
{# Microcopy LPC art. 219 — méthodologie 95% #}
<p class="text-xs text-brand-navy/70 text-center mt-8 max-w-2xl mx-auto">
Précision mesurée sur un échantillon interne d'audio professionnel québécois (juridique, médical, municipal) — méthodologie disponible sur demande à <a href="mailto:info@dictia.ca" class="hover:text-brand-navy underline">info@dictia.ca</a>.
</p>
</div>
</section>
{# ===== INTÉGRATIONS ===== #}
<section id="integrations" class="bg-brand-bg py-20 scroll-mt-32" aria-labelledby="integrations-title">
<div class="max-w-[1200px] mx-auto px-6">
<div class="text-center max-w-3xl mx-auto mb-14">
<p class="eyebrow grad-text mb-4">INTÉGRATIONS</p>
<h2 id="integrations-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black text-brand-navy">
<span class="ani-underline" data-ani-underline>Branchez DictIA à votre stack existant.</span>
</h2>
<p class="text-lg text-brand-navy/70 mt-6">
Webhooks REST, plugin Word natif et connecteurs Zapier / Make / n8n auto-hébergés. API documentée — vous gardez le contrôle des flux.
</p>
</div>
{%- set icon_chat_box = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4" aria-hidden="true"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>' -%}
{%- set icon_book = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4" aria-hidden="true"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20V3H6.5A2.5 2.5 0 0 0 4 5.5z"/><path d="M4 19.5V21h16v-4"/></svg>' -%}
{%- set icon_gear = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4" aria-hidden="true"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.9l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.9-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1-1.5 1.7 1.7 0 0 0-1.9.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.9 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1 1.7 1.7 0 0 0-.3-1.9l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.9.3h.1a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.9-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.9v.1a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z"/></svg>' -%}
{%- set integ_groups = [
{
'title': 'Communication',
'desc': 'Importez vos enregistrements depuis vos outils de réunion et de pratique.',
'icon': icon_chat_box,
'tools': [
{'name': 'Microsoft Teams', 'detail': 'Export depuis enregistrements'},
{'name': 'Microsoft Outlook','detail': 'Pièces jointes audio'},
{'name': 'Clio Manage', 'detail': 'Pour avocats'},
{'name': 'PCLaw', 'detail': 'Pour avocats'}
]
},
{
'title': 'Knowledge / notes',
'desc': 'Synchronisez transcriptions et résumés vers vos bases de connaissances.',
'icon': icon_book,
'tools': [
{'name': 'Obsidian', 'detail': 'via Markdown'},
{'name': 'Notion', 'detail': 'via Markdown'},
{'name': 'Logseq', 'detail': 'via Markdown'},
{'name': 'Word', 'detail': 'via DOCX'}
]
},
{
'title': 'Automatisation',
'desc': 'Déclenchez vos workflows à chaque transcription terminée.',
'icon': icon_gear,
'tools': [
{'name': 'Zapier', 'detail': 'No-code'},
{'name': 'Make (Integromat)','detail': 'Scénarios visuels'},
{'name': 'n8n', 'detail': 'Open source self-host'}
]
}
] -%}
<div class="grid md:grid-cols-3 gap-6">
{% for group in integ_groups %}
<div class="ani-fade bg-white p-6 rounded border border-brand-border" style="--delay: {{ loop.index0 * 80 }}ms;" data-ani-fade>
<div class="flex items-center gap-2 mb-2 text-brand-b1" aria-hidden="true">
{{ group.icon | safe }}
<span class="text-xs uppercase tracking-wider font-bold text-brand-navy">{{ group.title }}</span>
</div>
<p class="text-sm text-brand-navy/70 mb-5">{{ group.desc }}</p>
<ul class="grid grid-cols-2 gap-2" role="list">
{% for t in group.tools %}
<li class="ani-lift bg-brand-bg border border-brand-border p-3 rounded">
<p class="text-sm font-semibold text-brand-navy font-mono leading-tight">{{ t.name }}</p>
<p class="text-[11px] text-brand-navy/60 mt-0.5">{{ t.detail }}</p>
</li>
{% endfor %}
</ul>
</div>
{% endfor %}
</div>
<p class="text-xs text-brand-navy/70 text-center mt-8 max-w-2xl mx-auto">
Microsoft, Notion, Obsidian, Logseq, Clio, PCLaw, Zapier, Make et n8n sont des marques de leurs propriétaires respectifs. DictIA n'est pas affilié à ces produits.
</p>
</div>
</section>
{# ===== ARCHITECTURE & INFRASTRUCTURE ===== #}
<section id="architecture" class="relative bg-brand-navy text-white py-20 scroll-mt-32 overflow-hidden" aria-labelledby="architecture-title">
<div class="absolute top-1/2 right-1/4 w-[500px] h-[500px] rounded-full pointer-events-none" aria-hidden="true"
style="background: radial-gradient(circle, rgba(6,182,212,0.08) 0%, transparent 60%); filter: blur(60px);"></div>
<div class="relative max-w-[1200px] mx-auto px-6">
<div class="text-center max-w-3xl mx-auto mb-14">
<p class="eyebrow grad-text mb-4">ARCHITECTURE &amp; INFRASTRUCTURE</p>
<h2 id="architecture-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black">
<span class="ani-underline" data-ani-underline>Trois formules selon votre cabinet.</span>
</h2>
<p class="text-lg text-white/70 mt-6">
DictIA 8 et 16 fonctionnent localement chez vous. DictIA Cloud tourne sur GPU NVIDIA L4 dédié à OVH Beauharnois (Québec). Toutes les formules incluent volume audio illimité, zéro frais par utilisateur.
</p>
</div>
{%- set tiers = [
{
'name': 'DictIA 8',
'tagline': 'Petit cabinet, mode local',
'gpu': 'RTX 8&nbsp;Go',
'users': '2 à 5 utilisateurs',
'setup': '3&nbsp;450&nbsp;$',
'monthly': '173&nbsp;$',
'host': 'Local chez vous',
'llm': 'Mistral 7B non inclus',
'recommended': False,
'features': ['Transcription WhisperX FR-CA', 'Diarisation 8 locuteurs', 'Exports DOCX, PDF, SRT, VTT, TXT, JSON, MD', 'Synchronisation audio-texte', 'Admissible achat direct gouv. (≤ 34&nbsp;700&nbsp;$)']
},
{
'name': 'DictIA 16',
'tagline': 'Cabinet moyen, IA locale complète',
'gpu': 'RTX 16&nbsp;Go',
'users': '5 à 15 utilisateurs',
'setup': '5&nbsp;750&nbsp;$',
'monthly': '201&nbsp;$',
'host': 'Local chez vous',
'llm': 'Mistral 7B inclus',
'recommended': False,
'features': ['Tout DictIA 8', 'Résumés Mistral 7B local', 'Chat Q&amp;R sur enregistrement', 'Recherche sémantique', 'Templates avocat · notaire · CPA · médecin']
},
{
'name': 'DictIA Cloud',
'tagline': 'Multi-sites, infra gérée',
'gpu': 'NVIDIA L4 dédié',
'users': 'Utilisateurs illimités',
'setup': '—',
'monthly': '369&nbsp;$',
'host': 'OVH Beauharnois (QC)',
'llm': 'Mistral 7B inclus',
'recommended': True,
'features': ['Tout DictIA 16', 'Aucune infrastructure à gérer', 'Mises à jour automatiques', 'Hébergé au Québec (OVH)', 'Multi-sites et télétravail']
}
] -%}
<div class="grid md:grid-cols-3 gap-6 items-stretch">
{% for tier in tiers %}
<article class="ani-fade {% if tier.recommended %}card-pulse-glow grad-bg p-[1.5px] rounded{% endif %} relative h-full"
style="--delay: {{ loop.index0 * 100 }}ms;"
data-ani-fade>
{% if tier.recommended %}
<span class="absolute -top-3 left-1/2 -translate-x-1/2 grad-bg text-white text-xs font-bold px-3 py-1 rounded-full inline-flex items-center gap-1.5 z-10">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-3 h-3" aria-hidden="true"><path d="M12 2l2.9 6.9L22 10l-5.5 4.8L18 22l-6-3.6L6 22l1.5-7.2L2 10l7.1-1.1z"/></svg>
RECOMMANDÉ
</span>
{% endif %}
<div class="bg-brand-navy2 p-6 rounded border border-white/[0.08] h-full flex flex-col">
<header class="mb-4 pb-4 border-b border-white/[0.08]">
<h3 class="text-xl font-black mb-1 text-white">{{ tier.name }}</h3>
<p class="text-xs uppercase tracking-wider text-white/60">{{ tier.tagline }}</p>
</header>
<dl class="grid grid-cols-2 gap-x-4 gap-y-2 mb-5 text-xs">
<dt class="text-white/60">GPU</dt><dd class="font-mono text-white">{{ tier.gpu | safe }}</dd>
<dt class="text-white/60">Utilisateurs</dt><dd class="text-white">{{ tier.users }}</dd>
<dt class="text-white/60">Hébergement</dt><dd class="text-white">{{ tier.host }}</dd>
<dt class="text-white/60">LLM résumés</dt><dd class="text-white">{{ tier.llm }}</dd>
</dl>
<div class="mb-5 pb-5 border-b border-white/[0.08]">
{% if tier.setup != '—' %}
<div class="text-3xl font-black grad-text leading-none">{{ tier.setup | safe }}</div>
<div class="text-xs text-white/60 mt-1">setup unique + {{ tier.monthly | safe }}&nbsp;/ mois</div>
{% else %}
<div class="text-3xl font-black grad-text leading-none">{{ tier.monthly | safe }}</div>
<div class="text-xs text-white/60 mt-1">par mois · sans frais de setup</div>
{% endif %}
</div>
<ul class="space-y-2 mb-6 flex-grow text-sm" role="list">
{% for feat in tier.features %}
<li class="flex items-start gap-2 text-white/80">
{{ icon_check | safe }}
<span>{{ feat | safe }}</span>
</li>
{% endfor %}
</ul>
{% from 'macros/button.html' import button %}
{{ button('Voir le détail tarifs', href='/tarifs', variant='primary' if tier.recommended else 'ghost', size='md') }}
</div>
</article>
{% endfor %}
</div>
{# Bloc inclus dans setup local #}
<div class="mt-12 max-w-4xl mx-auto bg-white/[0.05] backdrop-blur-sm p-6 rounded border border-white/[0.08]">
<p class="eyebrow grad-text mb-3">INCLUS DANS LE SETUP LOCAL (DICTIA 8 &amp; 16)</p>
<ul class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-3 text-sm" role="list">
{% for inc in [
'Fourniture du PC + GPU',
'Configuration complète',
'Installation sur site',
'Formation équipe (23&nbsp;h)',
'Support démarrage 30&nbsp;jours'
] %}
<li class="flex items-start gap-2 text-white/80">
<span class="text-brand-b3 mt-0.5" aria-hidden="true">{{ icon_check | safe }}</span>
<span>{{ inc | safe }}</span>
</li>
{% endfor %}
</ul>
</div>
<p class="text-xs text-white/60 text-center mt-6 max-w-2xl mx-auto">
DictIA 8 est admissible à l'achat direct gouvernemental sans appel d'offres (seuil 34&nbsp;700&nbsp;$ — Règlement sur les contrats d'approvisionnement, art.&nbsp;15).
</p>
</div>
</section>
{# ===== EXPORT FORMATS DEEP-DIVE (test compat) ===== #}
<section class="bg-white py-16" aria-labelledby="exports-title">
<div class="max-w-[1200px] mx-auto px-6">
<div class="text-center max-w-2xl mx-auto mb-10">
<p class="eyebrow grad-text mb-3">FORMATS D'EXPORT</p>
<h2 id="exports-title" class="text-[clamp(1.75rem,2.5vw,2.25rem)] font-black text-brand-navy">
7 formats, prêts pour vos workflows.
</h2>
</div>
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-7 gap-3">
{% for fmt in [
{'ext': 'DOCX', 'use': 'Word avec timestamps cliquables'},
{'ext': 'PDF', 'use': 'Procès-verbaux signés'},
{'ext': 'SRT', 'use': 'Sous-titres vidéo'},
{'ext': 'VTT', 'use': 'Web/streaming standard'},
{'ext': 'TXT', 'use': 'Texte brut universel'},
{'ext': 'JSON', 'use': 'Pipeline développeur'},
{'ext': 'MD', 'use': 'Notion, Obsidian, GitHub'}
] %}
<div class="ani-lift bg-brand-bg p-4 rounded border border-brand-border text-center">
<p class="text-base font-black font-mono text-brand-navy">{{ fmt.ext }}</p>
<p class="text-xs text-brand-navy/70 mt-1">{{ fmt.use | safe }}</p>
</div>
{% endfor %}
</div>
</div>
</section>
{# ===== TECH SPECS (préservé pour rétro-compat tests) ===== #}
<section class="bg-brand-bg py-16" aria-labelledby="specs-title">
<div class="max-w-[1060px] mx-auto px-6">
<div class="text-center max-w-2xl mx-auto mb-10">
<p class="eyebrow grad-text mb-3">SOUS LE CAPOT</p>
<h2 id="specs-title" class="text-[clamp(1.75rem,2.5vw,2.25rem)] font-black text-brand-navy">
Spécifications techniques détaillées.
</h2>
</div>
<div class="grid md:grid-cols-2 gap-4">
{% for spec in [
{'title': 'Modèle ASR', 'desc': 'WhisperX Large-v3 (1,55&nbsp;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&amp;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&nbsp;v3.'},
{'title': 'Audio supportés (WAV, MP3, M4A, FLAC, OGG, WebM)', 'desc': 'Jusqu\'à 8&nbsp;h par fichier. Conversion ffmpeg automatique. Compatible enregistrements Zoom et Teams.'},
{'title': 'Langues', 'desc': 'Optimisé français québécois. Aussi&nbsp;: français de France, anglais (canadien et US), espagnol, allemand, mandarin, russe.'}
] %}
<article class="ani-fade ani-lift bg-white p-5 rounded border border-brand-border" style="--delay: {{ loop.index0 * 50 }}ms;" data-ani-fade>
<h3 class="text-base font-bold mb-2 text-brand-navy">{{ spec.title | safe }}</h3>
<p class="text-sm text-brand-navy/70 leading-relaxed">{{ spec.desc | safe }}</p>
</article>
{% endfor %}
</div>
</div>
</section>
{# ===== CONFORMITÉ — RÉSUMÉ ===== #}
<section id="conformite-resume" class="bg-white py-20 scroll-mt-32" aria-labelledby="conformite-resume-title">
<div class="max-w-[1060px] mx-auto px-6">
<div class="text-center max-w-3xl mx-auto mb-10">
<p class="eyebrow grad-text mb-4">CONFORMITÉ</p>
<h2 id="conformite-resume-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black text-brand-navy">
<span class="ani-underline" data-ani-underline>Conforme par construction.</span>
</h2>
<p class="text-lg text-brand-navy/70 mt-6">
Architecture pensée d'abord pour la Loi&nbsp;25 et les ordres professionnels québécois — pas une certification ajoutée après coup.
</p>
</div>
<ul class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-10" role="list">
{% for chip in [
{'title': 'Loi&nbsp;25', 'desc': 'La voix est biométrique — le traitement local élimine le risque.'},
{'title': 'Loi&nbsp;96', 'desc': 'Interface, documentation et support 100&nbsp;% français.'},
{'title': '9 ordres pros', 'desc': 'Mappé Barreau, CNQ, CPA, ChAD, OACIQ, CMQ, OIIQ, OPQ, OEQ.'},
{'title': '0 Cloud Act US', 'desc': 'Aucun fournisseur soumis à la juridiction américaine.'}
] %}
<li class="ani-fade ani-lift bg-brand-bg p-5 rounded border border-brand-border" style="--delay: {{ loop.index0 * 60 }}ms;" data-ani-fade>
<span class="inline-flex items-center gap-1.5 bg-brand-navy text-white text-xs font-black uppercase tracking-wider px-2.5 py-1 rounded-full mb-3">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="w-3 h-3" aria-hidden="true"><path d="M5 13l4 4L19 7"/></svg>
{{ chip.title | safe }}
</span>
<p class="text-sm text-brand-navy/80 leading-relaxed">{{ chip.desc | safe }}</p>
</li>
{% endfor %}
</ul>
<div class="text-center">
<a href="/conformite" class="inline-flex items-center gap-2 text-base font-semibold grad-text hover:underline focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
Voir le détail conformité
{{ icon_link | safe }}
</a>
</div>
</div>
</section>
{# ===== INTEGRATIONS GRID (compat tests + plugin partner list) ===== #}
<section class="bg-brand-bg py-12" aria-labelledby="integrations-grid-title">
<div class="max-w-[1200px] mx-auto px-6">
<h2 id="integrations-grid-title" class="sr-only">Liste détaillée des intégrations partenaires</h2>
<div class="grid grid-cols-2 md:grid-cols-4 gap-3" role="list">
{% for integ in [
{'name': 'Microsoft Word', 'desc': 'Plugin natif (.docx)'},
{'name': 'Microsoft Outlook','desc': 'Pièces jointes audio'},
{'name': 'Microsoft Teams', 'desc': 'Enregistrements de réunions'},
{'name': 'Notion', 'desc': 'Pages markdown auto'},
{'name': 'Obsidian', 'desc': 'Notes timestamped'},
{'name': 'Zapier', 'desc': 'Workflows no-code'},
{'name': 'Make (Integromat)','desc': 'Scénarios visuels'},
{'name': 'n8n', 'desc': 'Open source self-host'}
] %}
<div class="bg-white p-4 rounded border border-brand-border text-center" role="listitem">
<p class="text-sm font-bold text-brand-navy font-mono">{{ integ.name | safe }}</p>
<p class="text-xs text-brand-navy/70 mt-1">{{ integ.desc | safe }}</p>
</div>
{% endfor %}
</div>
</div>
</section>
{# ===== CTA FINAL ===== #}
<section class="bg-white py-20 border-t border-brand-border" aria-labelledby="features-cta-title">
<div class="max-w-[820px] mx-auto px-6 text-center">
<p class="eyebrow grad-text mb-4">PRÊT À TRANSCRIRE EN LOCAL</p>
<h2 id="features-cta-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black mb-5 text-brand-navy">
Prêt à transcrire <span class="grad-text">en local</span>&nbsp;?
</h2>
<p class="text-lg text-brand-navy/70 mb-10">
Lancement printemps&nbsp;2026 — pré-inscription ouverte. Conçu avec 9&nbsp;ordres professionnels québécois.
</p>
<div class="flex flex-col sm:flex-row gap-3 justify-center">
{% from 'macros/button.html' import button %}
{{ button('Voir les tarifs', href='/tarifs', variant='primary', size='lg', icon='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4" aria-hidden="true"><path d="M14 5l7 7m0 0l-7 7m7-7H3"/></svg>') }}
{{ button('Demander une démo', href='/contact', variant='secondary', size='lg') }}
</div>
</div>
</section>
{# ===== JS — IntersectionObserver pour ani-fade + ani-underline ===== #}
<script>
(function () {
if (typeof window === 'undefined' || typeof IntersectionObserver === 'undefined') return;
var reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
var fadeEls = document.querySelectorAll('[data-ani-fade]');
var underlineEls = document.querySelectorAll('[data-ani-underline]');
if (reduced) {
fadeEls.forEach(function (el) { el.classList.add('is-visible'); });
underlineEls.forEach(function (el) { el.classList.add('is-visible'); });
return;
}
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (e) {
if (!e.isIntersecting) return;
e.target.classList.add('is-visible');
io.unobserve(e.target);
});
}, { threshold: 0.15, rootMargin: '0px 0px -80px 0px' });
fadeEls.forEach(function (el) { io.observe(el); });
underlineEls.forEach(function (el) { io.observe(el); });
})();
</script>
{% endblock %}