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).
This commit is contained in:
Allison
2026-04-28 11:28:15 -04:00
parent 48d65c2ab9
commit 3e56736fa7
2 changed files with 764 additions and 149 deletions

View File

@@ -94,6 +94,7 @@
--container-sm: 24rem;
--container-md: 28rem;
--container-lg: 32rem;
--container-xl: 36rem;
--container-2xl: 42rem;
--container-3xl: 48rem;
--container-4xl: 56rem;
@@ -128,6 +129,7 @@
--tracking-wide: 0.025em;
--tracking-wider: 0.05em;
--tracking-widest: 0.1em;
--leading-tight: 1.25;
--leading-snug: 1.375;
--leading-relaxed: 1.625;
--radius-md: 0.375rem;
@@ -403,6 +405,9 @@
.top-\[42px\] {
top: 42px;
}
.top-\[62px\] {
top: 62px;
}
.top-full {
top: 100%;
}
@@ -505,6 +510,12 @@
.z-\[9999\] {
z-index: 9999;
}
.order-1 {
order: 1;
}
.order-2 {
order: 2;
}
.col-span-1 {
grid-column: span 1 / span 1;
}
@@ -559,6 +570,9 @@
.-mt-6 {
margin-top: calc(var(--spacing) * -6);
}
.mt-0 {
margin-top: calc(var(--spacing) * 0);
}
.mt-0\.5 {
margin-top: calc(var(--spacing) * 0.5);
}
@@ -631,6 +645,9 @@
.mb-4 {
margin-bottom: calc(var(--spacing) * 4);
}
.mb-5 {
margin-bottom: calc(var(--spacing) * 5);
}
.mb-6 {
margin-bottom: calc(var(--spacing) * 6);
}
@@ -643,8 +660,8 @@
.mb-12 {
margin-bottom: calc(var(--spacing) * 12);
}
.mb-16 {
margin-bottom: calc(var(--spacing) * 16);
.mb-14 {
margin-bottom: calc(var(--spacing) * 14);
}
.ml-0\.5 {
margin-left: calc(var(--spacing) * 0.5);
@@ -835,9 +852,6 @@
.min-h-\[8rem\] {
min-height: 8rem;
}
.min-h-\[60vh\] {
min-height: 60vh;
}
.min-h-\[calc\(100vh-62px\)\] {
min-height: calc(100vh - 62px);
}
@@ -964,6 +978,9 @@
.max-w-\[1060px\] {
max-width: 1060px;
}
.max-w-\[1100px\] {
max-width: 1100px;
}
.max-w-\[1200px\] {
max-width: 1200px;
}
@@ -979,6 +996,9 @@
.max-w-sm {
max-width: var(--container-sm);
}
.max-w-xl {
max-width: var(--container-xl);
}
.max-w-xs {
max-width: var(--container-xs);
}
@@ -1015,6 +1035,9 @@
.flex-shrink-0 {
flex-shrink: 0;
}
.shrink-0 {
flex-shrink: 0;
}
.flex-grow {
flex-grow: 1;
}
@@ -1105,6 +1128,9 @@
.resize-y {
resize: vertical;
}
.scroll-mt-32 {
scroll-margin-top: calc(var(--spacing) * 32);
}
.list-inside {
list-style-position: inside;
}
@@ -1167,9 +1193,6 @@
.justify-start {
justify-content: flex-start;
}
.justify-items-center {
justify-items: center;
}
.gap-0\.5 {
gap: calc(var(--spacing) * 0.5);
}
@@ -1341,24 +1364,6 @@
.rounded {
border-radius: 0.75rem;
}
.rounded-\[0\.5rem\] {
border-radius: 0.5rem;
}
.rounded-\[0\.75rem\] {
border-radius: 0.75rem;
}
.rounded-\[12px\] {
border-radius: 12px;
}
.rounded-\[14px\] {
border-radius: 14px;
}
.rounded-\[18px\] {
border-radius: 18px;
}
.rounded-\[20px\] {
border-radius: 20px;
}
.rounded-full {
border-radius: calc(infinity * 1px);
}
@@ -1368,6 +1373,9 @@
.rounded-md {
border-radius: var(--radius-md);
}
.rounded-none {
border-radius: 0;
}
.rounded-xl {
border-radius: var(--radius-xl);
}
@@ -1762,6 +1770,12 @@
.bg-brand-bg {
background-color: #f7f9fc;
}
.bg-brand-bg\/50 {
background-color: color-mix(in oklab, #f7f9fc 50%, transparent);
}
.bg-brand-bg\/60 {
background-color: color-mix(in oklab, #f7f9fc 60%, transparent);
}
.bg-brand-border {
background-color: #e6ebf2;
}
@@ -1918,6 +1932,12 @@
background-color: color-mix(in oklab, var(--color-white) 30%, transparent);
}
}
.bg-white\/95 {
background-color: color-mix(in srgb, #fff 95%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-white) 95%, transparent);
}
}
.bg-white\/\[0\.05\] {
background-color: color-mix(in srgb, #fff 5%, transparent);
@supports (color: color-mix(in lab, red, red)) {
@@ -1960,9 +1980,6 @@
--tw-gradient-position: to right in oklab;
background-image: linear-gradient(var(--tw-gradient-stops));
}
.bg-brand-grad {
background-image: linear-gradient(118deg, #0062ff, #00bdd8 52%, #00c896);
}
.from-\[var\(--bg-accent\)\] {
--tw-gradient-from: var(--bg-accent);
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
@@ -2183,6 +2200,9 @@
.pt-8 {
padding-top: calc(var(--spacing) * 8);
}
.pt-12 {
padding-top: calc(var(--spacing) * 12);
}
.pt-\[62px\] {
padding-top: 62px;
}
@@ -2216,12 +2236,24 @@
.pb-2 {
padding-bottom: calc(var(--spacing) * 2);
}
.pb-3 {
padding-bottom: calc(var(--spacing) * 3);
}
.pb-4 {
padding-bottom: calc(var(--spacing) * 4);
}
.pb-5 {
padding-bottom: calc(var(--spacing) * 5);
}
.pb-6 {
padding-bottom: calc(var(--spacing) * 6);
}
.pb-16 {
padding-bottom: calc(var(--spacing) * 16);
}
.pb-20 {
padding-bottom: calc(var(--spacing) * 20);
}
.pl-2 {
padding-left: calc(var(--spacing) * 2);
}
@@ -2255,6 +2287,9 @@
.align-middle {
vertical-align: middle;
}
.align-text-top {
vertical-align: text-top;
}
.align-top {
vertical-align: top;
}
@@ -2328,6 +2363,9 @@
.text-\[clamp\(2\.25rem\,4vw\,3\.5rem\)\] {
font-size: clamp(2.25rem, 4vw, 3.5rem);
}
.text-\[clamp\(2\.25rem\,4vw\,3\.75rem\)\] {
font-size: clamp(2.25rem, 4vw, 3.75rem);
}
.text-\[clamp\(2rem\,3vw\,2\.5rem\)\] {
font-size: clamp(2rem, 3vw, 2.5rem);
}
@@ -2354,6 +2392,10 @@
--tw-leading: var(--leading-snug);
line-height: var(--leading-snug);
}
.leading-tight {
--tw-leading: var(--leading-tight);
line-height: var(--leading-tight);
}
.font-black {
--tw-font-weight: var(--font-weight-black);
font-weight: var(--font-weight-black);
@@ -2374,6 +2416,10 @@
--tw-font-weight: var(--font-weight-semibold);
font-weight: var(--font-weight-semibold);
}
.tracking-\[0\.2em\] {
--tw-tracking: 0.2em;
letter-spacing: 0.2em;
}
.tracking-tight {
--tw-tracking: var(--tracking-tight);
letter-spacing: var(--tracking-tight);
@@ -2501,6 +2547,9 @@
.text-brand-navy {
color: #060d1a;
}
.text-brand-navy\/40 {
color: color-mix(in oklab, #060d1a 40%, transparent);
}
.text-brand-navy\/50 {
color: color-mix(in oklab, #060d1a 50%, transparent);
}
@@ -2621,6 +2670,12 @@
color: color-mix(in oklab, var(--color-white) 50%, transparent);
}
}
.text-white\/60 {
color: color-mix(in srgb, #fff 60%, transparent);
@supports (color: color-mix(in lab, red, red)) {
color: color-mix(in oklab, var(--color-white) 60%, transparent);
}
}
.text-white\/70 {
color: color-mix(in srgb, #fff 70%, transparent);
@supports (color: color-mix(in lab, red, red)) {
@@ -2633,12 +2688,6 @@
color: color-mix(in oklab, var(--color-white) 80%, transparent);
}
}
.text-white\/\[0\.04\] {
color: color-mix(in srgb, #fff 4%, transparent);
@supports (color: color-mix(in lab, red, red)) {
color: color-mix(in oklab, var(--color-white) 4%, transparent);
}
}
.text-yellow-400 {
color: var(--color-yellow-400);
}
@@ -2698,6 +2747,9 @@
.opacity-0 {
opacity: 0%;
}
.opacity-20 {
opacity: 20%;
}
.opacity-30 {
opacity: 30%;
}
@@ -2800,6 +2852,9 @@
--tw-backdrop-blur: blur(var(--blur-xl));
backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
}
.backdrop-filter {
backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
}
.transition {
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, backdrop-filter, display, content-visibility, overlay, pointer-events;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
@@ -2905,13 +2960,6 @@
}
}
}
.group-hover\:text-brand-navy {
&:is(:where(.group):hover *) {
@media (hover: hover) {
color: #060d1a;
}
}
}
.group-hover\:opacity-100 {
&:is(:where(.group):hover *) {
@media (hover: hover) {
@@ -3759,6 +3807,43 @@
}
}
}
.focus\:not-sr-only {
&:focus {
position: static;
width: auto;
height: auto;
padding: 0;
margin: 0;
overflow: visible;
clip-path: none;
white-space: normal;
}
}
.focus\:fixed {
&:focus {
position: fixed;
}
}
.focus\:top-2 {
&:focus {
top: calc(var(--spacing) * 2);
}
}
.focus\:left-2 {
&:focus {
left: calc(var(--spacing) * 2);
}
}
.focus\:z-\[100\] {
&:focus {
z-index: 100;
}
}
.focus\:rounded-none {
&:focus {
border-radius: 0;
}
}
.focus\:border-\[var\(--border-accent\)\] {
&:focus {
border-color: var(--border-accent);
@@ -3774,6 +3859,26 @@
border-color: transparent;
}
}
.focus\:bg-brand-navy {
&:focus {
background-color: #060d1a;
}
}
.focus\:px-4 {
&:focus {
padding-inline: calc(var(--spacing) * 4);
}
}
.focus\:py-2 {
&:focus {
padding-block: calc(var(--spacing) * 2);
}
}
.focus\:text-white {
&:focus {
color: var(--color-white);
}
}
.focus\:ring-1 {
&:focus {
--tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
@@ -4023,11 +4128,6 @@
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}
.sm\:grid-cols-5 {
@media (width >= 40rem) {
grid-template-columns: repeat(5, minmax(0, 1fr));
}
}
.sm\:flex-row {
@media (width >= 40rem) {
flex-direction: row;
@@ -4043,6 +4143,11 @@
justify-content: center;
}
}
.sm\:justify-end {
@media (width >= 40rem) {
justify-content: flex-end;
}
}
.sm\:gap-2 {
@media (width >= 40rem) {
gap: calc(var(--spacing) * 2);
@@ -4171,6 +4276,11 @@
padding-bottom: calc(var(--spacing) * 6);
}
}
.sm\:text-right {
@media (width >= 40rem) {
text-align: right;
}
}
.sm\:text-base {
@media (width >= 40rem) {
font-size: var(--text-base);
@@ -4289,6 +4399,11 @@
gap: calc(var(--spacing) * 4);
}
}
.md\:gap-5 {
@media (width >= 48rem) {
gap: calc(var(--spacing) * 5);
}
}
.md\:p-2 {
@media (width >= 48rem) {
padding: calc(var(--spacing) * 2);
@@ -4304,6 +4419,11 @@
padding: calc(var(--spacing) * 6);
}
}
.md\:p-7 {
@media (width >= 48rem) {
padding: calc(var(--spacing) * 7);
}
}
.md\:p-8 {
@media (width >= 48rem) {
padding: calc(var(--spacing) * 8);
@@ -4329,6 +4449,11 @@
padding-block: calc(var(--spacing) * 3);
}
}
.md\:py-28 {
@media (width >= 48rem) {
padding-block: calc(var(--spacing) * 28);
}
}
.md\:py-32 {
@media (width >= 48rem) {
padding-block: calc(var(--spacing) * 32);
@@ -4351,12 +4476,24 @@
line-height: var(--tw-leading, var(--text-4xl--line-height));
}
}
.md\:text-5xl {
@media (width >= 48rem) {
font-size: var(--text-5xl);
line-height: var(--tw-leading, var(--text-5xl--line-height));
}
}
.md\:text-base {
@media (width >= 48rem) {
font-size: var(--text-base);
line-height: var(--tw-leading, var(--text-base--line-height));
}
}
.md\:text-lg {
@media (width >= 48rem) {
font-size: var(--text-lg);
line-height: var(--tw-leading, var(--text-lg--line-height));
}
}
.md\:text-sm {
@media (width >= 48rem) {
font-size: var(--text-sm);
@@ -4393,6 +4530,11 @@
display: flex;
}
}
.lg\:grid {
@media (width >= 64rem) {
display: grid;
}
}
.lg\:hidden {
@media (width >= 64rem) {
display: none;
@@ -4439,14 +4581,19 @@
grid-template-columns: repeat(4, minmax(0, 1fr));
}
}
.lg\:grid-cols-5 {
@media (width >= 64rem) {
grid-template-columns: repeat(5, minmax(0, 1fr));
}
}
.lg\:grid-cols-7 {
@media (width >= 64rem) {
grid-template-columns: repeat(7, minmax(0, 1fr));
}
}
.lg\:grid-cols-9 {
.lg\:grid-cols-\[1fr_240px\] {
@media (width >= 64rem) {
grid-template-columns: repeat(9, minmax(0, 1fr));
grid-template-columns: 1fr 240px;
}
}
.lg\:flex-row {
@@ -4454,6 +4601,11 @@
flex-direction: row;
}
}
.lg\:gap-10 {
@media (width >= 64rem) {
gap: calc(var(--spacing) * 10);
}
}
.lg\:border-r {
@media (width >= 64rem) {
border-right-style: var(--tw-border-style);

View File

@@ -1,54 +1,464 @@
{% extends 'marketing/base.html' %}
{% block title %}Fonctionnalités DictIA — Transcription IA WhisperX, diarisation, résumés Mistral 7B local{% endblock %}
{% block description %}Toutes les fonctionnalités de DictIA : WhisperX Large-v3 fine-tuné FR-CA, diarisation 8 locuteurs, Mistral 7B local, Q&R RAG, exports DOCX/PDF/SRT, intégrations Word/Outlook/Teams.{% endblock %}
{% 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, #0062ff, #00bdd8 52%, #00c896);
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(0, 98, 255, 0.18); }
/* Sticky sub-nav active link */
.subnav-link[aria-current="true"] { color: #0062ff; }
.subnav-link[aria-current="true"]::after {
content: '';
display: block;
height: 2px;
margin-top: 4px;
background: linear-gradient(118deg, #0062ff, #00bdd8 52%, #00c896);
}
/* 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(0, 98, 255, 0.28); }
50% { box-shadow: 0 12px 40px rgba(0, 98, 255, 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>' -%}
{# ===== HEADER ===== #}
<section class="bg-brand-navy text-white py-20" aria-labelledby="page-title">
<div class="max-w-[820px] mx-auto px-6 text-center">
<p class="eyebrow grad-text mb-4">FONCTIONNALITÉS</p>
<h1 id="page-title" class="text-[clamp(2.25rem,4vw,3.5rem)] font-black mb-4">
Tout ce qu'il faut pour transcrire <span class="grad-text">en restant chez soi</span>.
{# ===== 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(0,98,255,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(0,189,216,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(0,98,255,0.3), rgba(0,189,216,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/80">
Une pile technique 100&nbsp;% québécoise, sans dépendance à un fournisseur cloud américain. Détails techniques sur demande&nbsp;: <a href="mailto:info@dictia.ca" class="grad-text font-semibold hover:underline">info@dictia.ca</a>.
<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>
{# ===== 6 BENTO FEATURES ===== #}
<section class="bg-white py-20" aria-labelledby="features-title">
<div class="max-w-[1060px] mx-auto px-6">
<h2 id="features-title" class="sr-only">Six fonctionnalités principales</h2>
{# 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.
Icon SVGs (heroicons-style outline) are inlined directly because the macro renders `icon | safe`. #}
{% from 'macros/bento.html' import bento_card %}
{%- 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_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_plug = '<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="M9 2v6"/><path d="M15 2v6"/><path d="M5 8h14v4a5 5 0 0 1-5 5h-4a5 5 0 0 1-5-5z"/><path d="M12 17v5"/></svg>' -%}
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-[1.5px] bg-brand-border rounded overflow-hidden">
{{ bento_card('01', 'Transcription WhisperX', 'Large-v3 fine-tuné FR-CA. Précision 95&nbsp;%+ sur réunions, dictées, audiences (méthodologie disponible sur demande).', icon_microphone) }}
{{ bento_card('02', 'Diarisation 8 locuteurs', 'pyannote sépare automatiquement les intervenants. Identification par embeddings vocaux.', icon_users) }}
{{ 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.', icon_document) }}
{{ bento_card('04', 'Q&amp;R sur enregistrement', 'Posez des questions à vos réunions. RAG local sur embeddings sentence-transformers.', icon_chat) }}
{{ bento_card('05', 'Exports multiples', 'DOCX, PDF, SRT, VTT, TXT, JSON, MD. Formats avocat, notaire, CPA.', icon_export) }}
{{ bento_card('06', 'Intégrations', 'Word, Outlook, Teams, Notion, Obsidian, Zapier, Make, n8n.', icon_plug) }}
{# ===== 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>
{# ===== EXPORT FORMATS DEEP-DIVE ===== #}
<section class="bg-brand-bg py-20" aria-labelledby="exports-title">
{# ===== 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(0,200,150,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-12">
<p class="eyebrow grad-text mb-4">FORMATS D'EXPORT</p>
<h2 id="exports-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black mb-4 text-brand-navy">
<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>
@@ -62,8 +472,8 @@
{'ext': 'JSON', 'use': 'Pipeline développeur'},
{'ext': 'MD', 'use': 'Notion, Obsidian, GitHub'}
] %}
<div class="bg-white p-4 rounded border border-brand-border text-center">
<p class="text-base font-black text-brand-navy">{{ fmt.ext }}</p>
<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 %}
@@ -71,83 +481,136 @@
</div>
</section>
{# ===== INTEGRATIONS GRID ===== #}
<section class="bg-white py-20" aria-labelledby="integrations-title">
<div class="max-w-[1200px] mx-auto px-6">
<div class="text-center max-w-2xl mx-auto mb-12">
<p class="eyebrow grad-text mb-4">INTÉGRATIONS</p>
<h2 id="integrations-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black mb-4 text-brand-navy">
Branchez DictIA à votre stack existant.
</h2>
<p class="text-base text-brand-navy/70">
Webhooks REST, plugin Word natif, connecteurs Zapier/Make/n8n. API documentée — auto-hébergée avec votre déploiement.
</p>
</div>
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
{% 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-brand-bg p-5 rounded border border-brand-border text-center">
<p class="text-base font-bold text-brand-navy">{{ integ.name | safe }}</p>
<p class="text-xs text-brand-navy/70 mt-1">{{ integ.desc | safe }}</p>
</div>
{% endfor %}
</div>
<p class="text-xs text-brand-navy/70 text-center mt-6">
Microsoft, Notion, Obsidian, Zapier, Make et n8n sont des marques de leurs propriétaires respectifs. DictIA n'est pas affilié à ces produits.
</p>
</div>
</section>
{# ===== TECH SPECS ===== #}
<section class="bg-brand-navy text-white py-20" aria-labelledby="specs-title">
{# ===== 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-12">
<p class="eyebrow grad-text mb-4">SPÉCIFICATIONS TECHNIQUES</p>
<h2 id="specs-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black mb-4">
Sous le capot.
<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-6">
<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', 'desc': 'WAV, MP3, M4A, FLAC, OGG, WebM — jusqu\'à 8&nbsp;h par fichier. Conversion ffmpeg automatique.'},
{'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="bg-white/[0.05] backdrop-blur-sm p-6 rounded border border-white/[0.08]">
<h3 class="text-lg font-bold mb-2 text-white">{{ spec.title | safe }}</h3>
<p class="text-sm text-white/80 leading-relaxed">{{ spec.desc | safe }}</p>
<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>
{# ===== CTA ===== #}
<section class="bg-brand-bg py-20" aria-labelledby="features-cta-title">
<div class="max-w-[820px] mx-auto px-6 text-center">
<h2 id="features-cta-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black mb-6 text-brand-navy">
Prêt à <span class="grad-text">essayer DictIA</span>&nbsp;?
{# ===== 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/80 mb-8">
Lancement printemps&nbsp;2026. Inscrivez-vous pour figurer sur la liste prioritaire.
<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 class="flex flex-col sm:flex-row gap-4 justify-center">
{% from 'macros/button.html' import button %}
{{ button('Pré-inscription par courriel', href='mailto:info@dictia.ca?subject=Pré-inscription%20DictIA', 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="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>') }}
{{ button('Voir les tarifs', href='/tarifs', variant='secondary', size='lg') }}
</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 %}