- Cycle "Trois options. Une seule est conforme." (entre PAS Problème & Solution) 3 colonnes comparatives (humaine 315$/h / cloud US illégal / DictIA 173$/mo) Phases reveal 1→4 via IntersectionObserver + setTimeout chain Anneaux pulsants source node + horloge rotation + particules fuites cloud Overlay légal NON CONFORME sur col 2 - Wave "Onde de transformation" (entre Solution & Pipeline) Slider mouse-X interactif : 30 barres SVG morphent rouge → cyan Particules tombantes -$/-h (CSS keyframes staggered) Étiquettes douleur PAINS / SOLUTIONS flottantes Mobile : toggle button, pas de mouse interaction - Cadre réglementaire "Moniteur d'Interception" (entre Conformité & Témoignages) Mappe 6 textes officiels : Loi 25, Loi 96, Cloud Act US, Guide IA Barreau, Cadre IA MCN, CAI Liens vers sources autoritaires (legisquebec, congress.gov, barreau, tresor, cai) HUD console typing reveal + caret blink + folder QC→US transition aria-live="polite" sur verdict, role="list" sur REGS Texte 100% canonique extrait de Website-Sanity dictai-cycle/wave/contraste.tsx. Toutes animations CSS pure + Alpine.js + IntersectionObserver natif (zéro lib JS externe). prefers-reduced-motion désactive tout. +802 lignes landing.html, +119 lignes tests (6 nouveaux test_round2_*), npm run build:css exécuté. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2044 lines
128 KiB
HTML
2044 lines
128 KiB
HTML
{% extends 'marketing/base.html' %}
|
||
|
||
{% block title %}Transcription IA conforme Loi 25 — DictIA pour avocats, CPA, secteur public{% endblock %}
|
||
{% block description %}DictIA transcrit vos réunions confidentielles 100% au Québec. Conforme Loi 25, Barreau, CPA, ChAD. Conçu avec 9 ordres professionnels — lancement printemps 2026.{% endblock %}
|
||
|
||
{% block content %}
|
||
{# ===== HERO ===== #}
|
||
{# Local keyframes scoped to the hero — audio progress bar loops 50%→75%→50% over 15s #}
|
||
<style>
|
||
@keyframes audio-progress {
|
||
0%, 100% { width: 50%; }
|
||
50% { width: 75%; }
|
||
}
|
||
.hero-audio-progress { animation: audio-progress 15s ease-in-out infinite; }
|
||
.hero-audio-thumb { animation: audio-progress 15s ease-in-out infinite; }
|
||
/* Mockup tilt + interactive hover — straightens on hover */
|
||
@media (min-width: 1024px) {
|
||
.hero-mockup-tilt { transform: rotate(1deg); transition: transform 500ms ease-out; }
|
||
.hero-mockup-tilt:hover { transform: rotate(0deg) scale(1.01); }
|
||
}
|
||
/* Glow orbs decorative float — uses tc-float-y from tailwind.config */
|
||
.hero-mockup-glow-a { animation: tc-float-y 6s ease-in-out infinite; }
|
||
.hero-mockup-glow-b { animation: tc-float-y 8s ease-in-out infinite reverse; }
|
||
/* Reduced-motion: freeze all hero mockup animations on first frame */
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.hero-audio-progress, .hero-audio-thumb,
|
||
.hero-mockup-glow-a, .hero-mockup-glow-b {
|
||
animation: none !important;
|
||
}
|
||
.hero-audio-progress { width: 60% !important; }
|
||
.hero-audio-thumb { left: 60% !important; }
|
||
.hero-mockup-tilt { transform: none !important; transition: none !important; }
|
||
}
|
||
</style>
|
||
<section class="relative overflow-hidden bg-brand-navy text-white py-24 md:py-32" aria-labelledby="hero-title">
|
||
{# Cosmic orbs background — 3 radial gradients (blue 16%, cyan 7%, green 11%) + subtle grid + horizontal accent line #}
|
||
<div class="absolute inset-0 pointer-events-none" aria-hidden="true">
|
||
{# Orb 1 — primary blue, top-left #}
|
||
<div class="absolute top-1/4 left-1/4 w-[600px] h-[600px] rounded-full opacity-100"
|
||
style="background: radial-gradient(circle, rgba(0,98,255,0.16) 0%, transparent 60%); filter: blur(40px);"></div>
|
||
{# Orb 2 — cyan, mid-right #}
|
||
<div class="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>
|
||
{# Orb 3 — accent green, bottom-left #}
|
||
<div class="absolute bottom-1/4 left-1/3 w-[400px] h-[400px] rounded-full"
|
||
style="background: radial-gradient(circle, rgba(0,200,150,0.11) 0%, transparent 60%); filter: blur(40px);"></div>
|
||
{# Subtle grid overlay (FlexiHub signature) #}
|
||
<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>
|
||
{# Horizontal accent line — gradient blue to cyan to transparent #}
|
||
<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">
|
||
{# 2-col grid on lg+: text left, app mockup right. On <lg, mockup hidden, text centered as before. #}
|
||
<div class="grid lg:grid-cols-[1fr_minmax(0,560px)] gap-12 lg:gap-16 items-center">
|
||
{# ---------- COLUMN LEFT: hero copy ---------- #}
|
||
<div class="text-center lg:text-left max-w-3xl mx-auto lg:mx-0">
|
||
{# Eyebrow with gradient text and 0.18em tracking #}
|
||
<p class="eyebrow grad-text mb-6 animate-tc-fade-in-up" style="animation-delay: 0ms; animation-fill-mode: backwards;">
|
||
TRANSCRIPTION IA · CONFORME LOI 25 · QUÉBEC
|
||
</p>
|
||
|
||
{# H1 — clamp typography + grad-text accent on key phrase #}
|
||
<h1 id="hero-title" class="text-[clamp(2.5rem,4vw,4rem)] font-black leading-[1.05] mb-6 animate-tc-fade-in-up" style="animation-delay: 75ms; animation-fill-mode: backwards;">
|
||
Transcrivez vos réunions
|
||
<span class="grad-text">sans risquer votre permis</span>.
|
||
</h1>
|
||
|
||
{# Sub-headline — ≤25 words, value prop #}
|
||
<p class="text-lg text-white/70 max-w-xl mx-auto lg:mx-0 mb-10 animate-tc-fade-in-up" style="animation-delay: 150ms; animation-fill-mode: backwards;">
|
||
DictIA convertit vos audio en texte, résumé et points d'action — 100% au Québec, conforme Barreau, CPA Québec, ChAD et 6 autres ordres professionnels.
|
||
</p>
|
||
|
||
{# Dual CTA — primary (demo) + secondary ghost (pricing) #}
|
||
<div class="flex flex-col sm:flex-row gap-3 justify-center lg:justify-start animate-tc-fade-in-up" style="animation-delay: 300ms; animation-fill-mode: backwards;">
|
||
{% from 'macros/button.html' import button %}
|
||
{{ button('Réserver une démo', href='/contact', variant='primary', size='lg') }}
|
||
{{ button('Voir les tarifs', href='/tarifs', variant='ghost', 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>') }}
|
||
</div>
|
||
|
||
{# Social proof microcopy — defensible: refers to pre-launch waitlist + factual ordres pros count #}
|
||
<p class="mt-8 text-sm text-white/70 flex flex-wrap items-center justify-center lg:justify-start gap-x-2 gap-y-1 animate-tc-fade-in-up" style="animation-delay: 400ms; animation-fill-mode: backwards;">
|
||
<span class="inline-flex items-center gap-1.5">
|
||
<svg width="14" height="14" viewBox="0 0 20 20" fill="currentColor" class="text-brand-b3" aria-hidden="true">
|
||
<path d="M10 2L3 5v5.5c0 4.04 2.84 7.85 7 8.5 4.16-.65 7-4.46 7-8.5V5l-7-3z"/>
|
||
</svg>
|
||
<span>Conçu avec 9 ordres professionnels québécois</span>
|
||
</span>
|
||
<span class="text-white/30">·</span>
|
||
<span>Pré-inscription ouverte</span>
|
||
<span class="text-white/30">·</span>
|
||
<span>Lancement printemps 2026</span>
|
||
</p>
|
||
</div>
|
||
|
||
{# ---------- COLUMN RIGHT: app mockup (lg+ only) ---------- #}
|
||
<div class="hidden lg:block relative animate-tc-fade-in-up" style="animation-delay: 250ms; animation-fill-mode: backwards;">
|
||
{# Decorative glow orbs floating behind the mockup #}
|
||
<div class="absolute -inset-8 pointer-events-none" aria-hidden="true">
|
||
<div class="hero-mockup-glow-a absolute -top-10 -left-10 w-72 h-72 rounded-full bg-brand-b1/15 blur-3xl"></div>
|
||
<div class="hero-mockup-glow-b absolute -bottom-10 -right-6 w-64 h-64 rounded-full bg-brand-b3/10 blur-3xl"></div>
|
||
</div>
|
||
|
||
{# The mockup itself — role=img with descriptive label for screen readers #}
|
||
<div role="img"
|
||
aria-label="Aperçu de l'interface DictIA — liste d'enregistrements à gauche, transcription au centre, résumé IA à droite"
|
||
class="hero-mockup-tilt relative bg-brand-navy2 border border-white/[0.08] shadow-2xl shadow-black/40 rounded overflow-hidden">
|
||
|
||
{# A) Browser chrome / window header (h-8) #}
|
||
<div class="flex items-center px-3 h-8 border-b border-white/[0.06] bg-white/[0.03]" aria-hidden="true">
|
||
{# Traffic light dots #}
|
||
<div class="flex items-center gap-1.5">
|
||
<span class="block w-3 h-3 rounded-full" style="background:#ff5f57"></span>
|
||
<span class="block w-3 h-3 rounded-full" style="background:#febc2e"></span>
|
||
<span class="block w-3 h-3 rounded-full" style="background:#28c840"></span>
|
||
</div>
|
||
{# Centered tab label #}
|
||
<div class="flex-1 text-center text-[11px] font-medium text-white/60 tracking-tight">DictIA — Enquêter</div>
|
||
{# Expand 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-3.5 h-3.5 text-white/40">
|
||
<path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7"/>
|
||
</svg>
|
||
</div>
|
||
|
||
{# B) Main app area — 3 sub-columns (sidebar / center / summary), h-[460px] #}
|
||
<div class="grid grid-cols-[180px_1fr_170px] h-[460px]"
|
||
x-data="{ idx: 0 }"
|
||
x-init="$el.__hero_int = setInterval(() => { idx = (idx + 1) % 5 }, 2800)">
|
||
|
||
{# B1 — SIDEBAR (left) #}
|
||
<aside class="border-r border-white/[0.06] flex flex-col overflow-hidden">
|
||
{# Sidebar header — DictIA monogram + JD avatar #}
|
||
<div class="flex items-center justify-between px-3 py-2.5 border-b border-white/[0.05]">
|
||
<span class="grad-text font-black text-[13px] tracking-tight">DictIA</span>
|
||
<span class="grad-bg rounded-full w-6 h-6 flex items-center justify-center text-[10px] font-bold text-white">JD</span>
|
||
</div>
|
||
|
||
{# New recording button — rounded-none brutalist #}
|
||
<div class="px-2 pt-2">
|
||
<button type="button" class="grad-bg w-full inline-flex items-center justify-center gap-1.5 py-2 text-[11px] font-semibold rounded-none" tabindex="-1" aria-hidden="true">
|
||
<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"><path d="M12 5v14M5 12h14"/></svg>
|
||
<span>Nouvel Enregistrement</span>
|
||
</button>
|
||
</div>
|
||
|
||
{# Search input #}
|
||
<div class="px-2 pt-2">
|
||
<div class="relative">
|
||
<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="absolute left-2 top-1/2 -translate-y-1/2 w-3 h-3 text-white/40"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg>
|
||
<div class="bg-white/[0.05] border border-white/[0.06] py-1.5 pl-7 pr-2 text-[10px] text-white/40 rounded-none">Rechercher…</div>
|
||
</div>
|
||
</div>
|
||
|
||
{# Sidebar list — scrollable area #}
|
||
<div class="flex-1 overflow-hidden mt-3 px-1">
|
||
|
||
{# Group: Semaine dernière #}
|
||
<p class="px-2 text-[9px] uppercase tracking-[0.12em] text-white/40 font-bold mb-1.5">Semaine dernière</p>
|
||
|
||
{# Item 1 — ACTIVE #}
|
||
<div class="px-2 py-2 mb-1 bg-white/[0.08] border-l-2 border-brand-b1">
|
||
<p class="text-[11px] text-white font-semibold truncate">Dossier Beaumont — clauses 7 et 9</p>
|
||
<p class="text-[9px] text-white/50 truncate mt-0.5">Jeu · Me Roy, Jean T., Marie C.</p>
|
||
<span class="inline-block mt-1 rounded-full bg-blue-500/20 text-blue-300 text-[9px] px-2 py-0.5 font-medium">En cours</span>
|
||
</div>
|
||
|
||
{# Item 2 #}
|
||
<div class="px-2 py-2 mb-1 hover:bg-white/[0.04]">
|
||
<p class="text-[11px] text-white/90 truncate">Succession Gagnon — répartition…</p>
|
||
<p class="text-[9px] text-white/50 truncate mt-0.5">26 févr. · Me Gagnon, Client</p>
|
||
</div>
|
||
|
||
{# Group: Mois dernier #}
|
||
<p class="px-2 mt-3 text-[9px] uppercase tracking-[0.12em] text-white/40 font-bold mb-1.5">Mois dernier</p>
|
||
|
||
{# Item 3 #}
|
||
<div class="px-2 py-2 mb-1 hover:bg-white/[0.04]">
|
||
<p class="text-[11px] text-white/90 truncate">Consultation Tremblay — litige loc…</p>
|
||
<p class="text-[9px] text-white/50 truncate mt-0.5">19 févr. · Me Roy, Sophie T.</p>
|
||
</div>
|
||
|
||
{# Item 4 — Barreau Confidentiel #}
|
||
<div class="px-2 py-2 mb-1 hover:bg-white/[0.04]">
|
||
<p class="text-[11px] text-white/90 truncate">Réunion constitutive INC Bédard…</p>
|
||
<p class="text-[9px] text-white/50 truncate mt-0.5">10 févr. · Sophie B., Jean R.</p>
|
||
<span class="inline-block mt-1 rounded-full bg-purple-500/20 text-purple-300 text-[9px] px-2 py-0.5 font-medium">Barreau Confidentiel</span>
|
||
</div>
|
||
|
||
{# Item 5 — CPA Corporatif #}
|
||
<div class="px-2 py-2 mb-1 hover:bg-white/[0.04]">
|
||
<p class="text-[11px] text-white/90 truncate">Entretien RQAP et structure salariale</p>
|
||
<p class="text-[9px] text-white/50 truncate mt-0.5">10 févr. · Me Roy, Allison, Robert</p>
|
||
<span class="inline-block mt-1 rounded-full bg-emerald-500/20 text-emerald-300 text-[9px] px-2 py-0.5 font-medium">CPA Corporatif</span>
|
||
</div>
|
||
|
||
{# Item 6 — Urgent Client #}
|
||
<div class="px-2 py-2 mb-1 hover:bg-white/[0.04]">
|
||
<p class="text-[11px] text-white/90 truncate">Révision contrat Côté & Associés</p>
|
||
<p class="text-[9px] text-white/50 truncate mt-0.5">5 févr. · Me Roy, Marie C.</p>
|
||
<span class="inline-block mt-1 rounded-full bg-red-500/20 text-red-300 text-[9px] px-2 py-0.5 font-medium">Urgent Client</span>
|
||
</div>
|
||
|
||
</div>
|
||
</aside>
|
||
|
||
{# B2 — CENTER (audio + transcript) #}
|
||
<section class="flex flex-col p-3 overflow-hidden">
|
||
|
||
{# Header card #}
|
||
<div class="mb-3">
|
||
<h3 class="text-[13px] font-bold text-white">Dossier Beaumont — clauses 7 et 9</h3>
|
||
<div class="flex flex-wrap items-center gap-x-3 gap-y-1 mt-1.5 text-[10px] text-white/50">
|
||
<span class="inline-flex items-center gap-1">
|
||
<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-3 h-3"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
|
||
<span>Me Roy, Jean T., Marie C.</span>
|
||
</span>
|
||
<span class="inline-flex items-center gap-1">
|
||
<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-3 h-3"><rect x="3" y="4" width="18" height="18" rx="2"/><path d="M16 2v4M8 2v4M3 10h18"/></svg>
|
||
<span>27 févr. 2026</span>
|
||
</span>
|
||
<span class="inline-flex items-center gap-1">
|
||
<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-3 h-3"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
|
||
<span>38:47</span>
|
||
</span>
|
||
<span class="inline-flex items-center gap-1">
|
||
<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-3 h-3"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/></svg>
|
||
<span>28.3 MB</span>
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
{# Audio player block #}
|
||
<div class="bg-white/[0.04] p-3 rounded-none">
|
||
{# Progress bar #}
|
||
<div class="relative h-1 bg-white/10">
|
||
<div class="hero-audio-progress h-full grad-bg" style="width:60%"></div>
|
||
<div class="hero-audio-thumb absolute -top-1 grad-bg w-3 h-3 rounded-full" style="left:60%; transform: translateX(-50%);"></div>
|
||
</div>
|
||
{# Time + speed + play row #}
|
||
<div class="flex items-center justify-between mt-2">
|
||
<div class="text-[10px] font-mono text-white/60">
|
||
<span class="text-white/80">28:17</span>
|
||
<span class="text-white/30 mx-1">/</span>
|
||
<span>46:23</span>
|
||
</div>
|
||
<div class="flex items-center gap-2">
|
||
<span class="text-[9px] text-white/60 px-1.5 py-0.5 bg-white/[0.06] rounded-full font-mono">1x</span>
|
||
<button type="button" class="grad-bg w-8 h-8 rounded-full flex items-center justify-center animate-plus-breathe" tabindex="-1" aria-hidden="true">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" class="w-3 h-3"><path d="M8 5v14l11-7z"/></svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{# Transcript area — 5 lines, active line cycles via Alpine idx #}
|
||
<div class="flex-1 mt-3 overflow-hidden space-y-1.5">
|
||
<div class="px-2 py-1.5 transition-colors duration-300" :class="idx === 0 ? 'bg-brand-b1/10 border-l-2 border-brand-b1' : 'border-l-2 border-transparent'">
|
||
<p class="text-[10px]">
|
||
<span class="text-brand-b1 font-bold">Allison</span>
|
||
<span class="text-white/80 ml-1.5">Tu l'as su? Comment ça va, vous deux?</span>
|
||
</p>
|
||
</div>
|
||
<div class="px-2 py-1.5 transition-colors duration-300" :class="idx === 1 ? 'bg-brand-b1/10 border-l-2 border-brand-b1' : 'border-l-2 border-transparent'">
|
||
<p class="text-[10px]">
|
||
<span class="text-brand-b3 font-bold">SPEAKER_02</span>
|
||
<span class="text-white/80 ml-1.5">Super bien, super vite, mais très bien.</span>
|
||
</p>
|
||
</div>
|
||
<div class="px-2 py-1.5 transition-colors duration-300" :class="idx === 2 ? 'bg-brand-b1/10 border-l-2 border-brand-b1' : 'border-l-2 border-transparent'">
|
||
<p class="text-[10px]">
|
||
<span class="text-brand-b1 font-bold">Allison</span>
|
||
<span class="text-white/80 ml-1.5">Oui, oui. Je suis contente d'entendre ça.</span>
|
||
</p>
|
||
</div>
|
||
<div class="px-2 py-1.5 transition-colors duration-300" :class="idx === 3 ? 'bg-brand-b1/10 border-l-2 border-brand-b1' : 'border-l-2 border-transparent'">
|
||
<p class="text-[10px]">
|
||
<span class="text-brand-b3 font-bold">SPEAKER_02</span>
|
||
<span class="text-white/80 ml-1.5">Moi, je l'ai vu quand vous l'avez payé.</span>
|
||
</p>
|
||
</div>
|
||
<div class="px-2 py-1.5 transition-colors duration-300" :class="idx === 4 ? 'bg-brand-b1/10 border-l-2 border-brand-b1' : 'border-l-2 border-transparent'">
|
||
<p class="text-[10px]">
|
||
<span class="text-brand-b1 font-bold">Allison</span>
|
||
<span class="text-white/80 ml-1.5">J'étais comme, « Hein? »</span>
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
{# Question input (disabled — visual only) #}
|
||
<div class="mt-3">
|
||
<input type="text" disabled tabindex="-1" aria-hidden="true"
|
||
placeholder="Posez une question sur cette transcription…"
|
||
class="w-full bg-white/[0.05] border border-white/10 px-3 py-2 text-[11px] text-white/40 placeholder-white/40 rounded-none">
|
||
</div>
|
||
</section>
|
||
|
||
{# B3 — RIGHT pane (summary) #}
|
||
<aside class="border-l border-white/[0.06] p-3 overflow-hidden">
|
||
{# Tabs #}
|
||
<div class="flex items-center gap-3 border-b border-white/[0.06] pb-2 mb-3">
|
||
<span class="text-[10px] uppercase tracking-[0.12em] text-brand-b1 font-bold border-b-2 border-brand-b1 pb-1 -mb-[0.5rem]">Résumé</span>
|
||
<span class="text-[10px] uppercase tracking-[0.12em] text-white/40 font-medium">Notes</span>
|
||
<span class="text-[10px] uppercase tracking-[0.12em] text-white/40 font-medium">Discuter</span>
|
||
</div>
|
||
|
||
{# Summary text #}
|
||
<p class="text-[10px] text-white/80 leading-relaxed">
|
||
Cette réunion aborde les complexités fiscales et juridiques liées à la création d'un nouveau produit nommé Dictéa…
|
||
</p>
|
||
|
||
{# Key points #}
|
||
<p class="mt-3 text-[9px] uppercase tracking-[0.12em] text-white/50 font-bold mb-1.5">Points clés</p>
|
||
<ul class="space-y-1 text-[10px] text-white/70 leading-snug">
|
||
<li class="flex gap-1.5"><span class="text-brand-b1">•</span><span>Structure de propriété : SNC + INC</span></li>
|
||
<li class="flex gap-1.5"><span class="text-brand-b1">•</span><span>RQAP et Salaire : Allison ne peut pas se verser</span></li>
|
||
<li class="flex gap-1.5"><span class="text-brand-b1">•</span><span>Subventions : 4 ans à conserver</span></li>
|
||
<li class="flex gap-1.5"><span class="text-brand-b1">•</span><span>Exonération des gains personnels</span></li>
|
||
</ul>
|
||
</aside>
|
||
|
||
</div>{# /Main app area #}
|
||
</div>{# /mockup container #}
|
||
</div>{# /column right #}
|
||
</div>{# /grid #}
|
||
</div>
|
||
</section>
|
||
|
||
{# ===== TRUST BAR — 9 ordres pros ===== #}
|
||
<section class="bg-white py-16 border-y border-brand-border" aria-labelledby="trust-bar-title">
|
||
<div class="max-w-[1200px] mx-auto px-6">
|
||
<div class="text-center max-w-xl mx-auto mb-10">
|
||
<p id="trust-bar-title" class="eyebrow text-brand-navy/70 mb-3">
|
||
Mappé aux 9 ordres professionnels québécois
|
||
</p>
|
||
<p class="text-sm text-brand-navy/70">
|
||
L'architecture DictIA est conçue pour répondre aux exigences de confidentialité et d'audit des principaux ordres professionnels du Québec.
|
||
</p>
|
||
</div>
|
||
|
||
{# 9 ordres — uniform card grid, official names, profession labels (no repeated acronyms) #}
|
||
<ul class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 mb-14" role="list">
|
||
{% for ordre in [
|
||
{'acronym': 'Barreau', 'name': 'Barreau du Québec', 'profession': 'Avocats'},
|
||
{'acronym': 'CNQ', 'name': 'Chambre des notaires du Québec', 'profession': 'Notaires'},
|
||
{'acronym': 'CPA', 'name': 'Ordre des CPA du Québec', 'profession': 'Comptables'},
|
||
{'acronym': 'ChAD', 'name': "Chambre de l'assurance de dommages", 'profession': 'Assurance'},
|
||
{'acronym': 'OACIQ', 'name': "Organisme d'autoréglementation du courtage immobilier du Québec", 'profession': 'Courtage immobilier'},
|
||
{'acronym': 'CMQ', 'name': 'Collège des médecins du Québec', 'profession': 'Médecins'},
|
||
{'acronym': 'OIIQ', 'name': 'Ordre des infirmières et infirmiers du Québec', 'profession': 'Infirmières'},
|
||
{'acronym': 'OPQ', 'name': 'Ordre des pharmaciens du Québec', 'profession': 'Pharmaciens'},
|
||
{'acronym': 'OEQ', 'name': 'Ordre des ergothérapeutes du Québec', 'profession': 'Ergothérapeutes'}
|
||
] %}
|
||
<li class="flex items-center gap-4 p-4 bg-white border border-brand-border rounded hover:border-brand-b1 transition-colors">
|
||
<span class="flex-shrink-0 w-14 h-14 flex items-center justify-center bg-brand-bg border border-brand-border" aria-hidden="true">
|
||
<span class="grad-text font-black text-sm tracking-tight">{{ ordre.acronym }}</span>
|
||
</span>
|
||
<span class="min-w-0 flex-1">
|
||
<span class="block text-sm font-semibold text-brand-navy leading-snug">{{ ordre.name | safe }}</span>
|
||
<span class="block text-xs uppercase tracking-wider text-brand-navy/60 mt-1">{{ ordre.profession }}</span>
|
||
</span>
|
||
</li>
|
||
{% endfor %}
|
||
</ul>
|
||
|
||
{# 4 KPI metrics — defensible numbers with footnote attribution #}
|
||
<div class="grid grid-cols-2 md:grid-cols-4 gap-8">
|
||
{% for kpi in [
|
||
('~5 min', 'par heure d\'audio', 'Traitement local 30× temps réel sur GPU RTX'),
|
||
('95 %+', 'précision FR-CA', 'WhisperX Large-v3 — test interne 2026-Q1'),
|
||
('0 $', 'frais par utilisateur', 'Modèle par serveur, volume illimité'),
|
||
('100 %', 'local au Québec', 'OVH Beauharnois ou vos serveurs')
|
||
] %}
|
||
<div class="text-center">
|
||
<div class="text-4xl font-black grad-text mb-2">{{ kpi[0] | safe }}</div>
|
||
<div class="text-sm font-semibold text-brand-navy mb-1">{{ kpi[1] }}</div>
|
||
<div class="text-xs text-brand-navy/60">{{ kpi[2] }}</div>
|
||
</div>
|
||
{% endfor %}
|
||
</div>
|
||
|
||
{# Footnote — discloses methodology for the 95% claim (LPC art. 219 hygiene) #}
|
||
<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">info@dictia.ca</a>.
|
||
</p>
|
||
</div>
|
||
</section>
|
||
|
||
{# ===== PROBLÈME (P de PAS) ===== #}
|
||
<section class="bg-brand-bg py-20" aria-labelledby="probleme-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">LE PROBLÈME — TRANSCRIPTION CLOUD</p>
|
||
<h2 id="probleme-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black mb-4">
|
||
Vos réunions confidentielles dans Teams Copilot ou Otter.ai
|
||
<span class="grad-text">violent la Loi 25</span>.
|
||
</h2>
|
||
<p class="text-lg text-brand-navy/70">
|
||
Le transfert de données vocales hors-Québec sans consentement explicite expose les professionnels réglementés à des sanctions disciplinaires de leurs ordres et à des amendes CAI jusqu'à 25 M$ ou 4 % du chiffre d'affaires mondial.
|
||
</p>
|
||
</div>
|
||
|
||
{# 3 problem cards on white surface — Cloud Act, Loi 25, Sanctions #}
|
||
<div class="grid md:grid-cols-3 gap-6 mt-12">
|
||
{% for card in [
|
||
('Cloud Act', 'Loi américaine 2018', 'Microsoft, Google et OpenAI sont soumis au Cloud Act. Vos données peuvent être saisies par les autorités américaines sans votre consentement ni notification — y compris les enregistrements de vos réunions client.',
|
||
'<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-6 h-6" aria-hidden="true"><path d="M12 3v18"/><path d="M5 7h14"/><path d="M5 7l-2 6a4 4 0 0 0 8 0L9 7"/><path d="M19 7l2 6a4 4 0 0 1-8 0l2-6"/><path d="M8 21h8"/></svg>'),
|
||
('Loi 25 — biométrie', 'Sanctions CAI jusqu\'à 25 M$', 'La voix est une donnée biométrique au sens des articles 44-45 de la LCCJTI et un renseignement sensible au sens de la Loi 25 (art. 12 LSP). Tout traitement nécessite un consentement explicite, une déclaration préalable à la CAI et un transfert vers un territoire offrant une protection équivalente — ce que les États-Unis n\'offrent pas.',
|
||
'<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-6 h-6" aria-hidden="true"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>'),
|
||
('Sanctions disciplinaires', '~250 000 pros réglementés QC (CIQ)', 'Les ordres professionnels québécois — au premier rang desquels le Barreau, la Chambre des notaires et CPA Québec — exigent une obligation stricte de confidentialité. Le transfert de données client hors-juridiction sans consentement explicite peut être qualifié de manquement, jusqu\'à la radiation pour les fautes graves.',
|
||
'<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-6 h-6" aria-hidden="true"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>')
|
||
] %}
|
||
<article class="bg-white p-6 rounded border border-brand-border">
|
||
<div class="grad-text mb-4" aria-hidden="true">{{ card[3] | safe }}</div>
|
||
<h3 class="text-lg font-bold mb-1 text-brand-navy">{{ card[0] }}</h3>
|
||
<p class="text-xs uppercase tracking-wider text-brand-navy/70 mb-3 font-semibold">{{ card[1] | safe }}</p>
|
||
<p class="text-sm text-brand-navy/70 leading-relaxed">{{ card[2] | safe }}</p>
|
||
</article>
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
{# ===== CYCLE — "Trois options. Une seule est conforme." ===== #}
|
||
{# Source canonique : InnovA-AI/Website-Sanity/components/sections/dictai-cycle.tsx
|
||
Animation : phase reveal phasé (1→4) déclenché par IntersectionObserver natif + Alpine.
|
||
3 colonnes comparatives : 01 Humaine · 02 Cloud US (overlay non-conforme) · 03 DictIA (featured + pulse rings) #}
|
||
<style>
|
||
/* Cycle pulse rings — appliqués au nœud source "Réunion en cours" */
|
||
@keyframes cycle-pulse-ring {
|
||
0% { transform: scale(1); opacity: 0.5; }
|
||
100% { transform: scale(2.1); opacity: 0; }
|
||
}
|
||
.cycle-pulse { animation: cycle-pulse-ring 2.4s ease-out infinite; }
|
||
.cycle-pulse-2 { animation-delay: 0.65s; }
|
||
.cycle-pulse-3 { animation-delay: 1.3s; }
|
||
|
||
/* Cycle col 3 (DictIA) — bordure lumineuse pulsante */
|
||
@keyframes cycle-glow {
|
||
0%, 100% { box-shadow: 0 0 0 0 rgba(0,189,216,0.12); }
|
||
50% { box-shadow: 0 0 35px 0 rgba(0,189,216,0.30); }
|
||
}
|
||
.cycle-card-dictia.is-visible { animation: cycle-glow 3.8s ease-in-out infinite; }
|
||
|
||
/* Cycle col 3 — anneaux concentriques autour du Lock */
|
||
@keyframes cycle-ring-out {
|
||
0%, 100% { transform: scale(1); opacity: 0.45; }
|
||
50% { transform: scale(1.07); opacity: 0.18; }
|
||
}
|
||
.cycle-ring-outer.is-visible { animation: cycle-ring-out 3.8s ease-in-out infinite; }
|
||
.cycle-ring-inner.is-visible { animation: cycle-ring-out 2.9s ease-in-out infinite 0.5s; }
|
||
|
||
/* Cycle SVG lignes de connexion — drawn via stroke-dashoffset */
|
||
.cycle-line { stroke-dasharray: 50; stroke-dashoffset: 50; transition: stroke-dashoffset 600ms ease-out; }
|
||
.cycle-line.is-visible { stroke-dashoffset: 0; }
|
||
|
||
/* Cycle phase reveal — colonnes 1+2 (phase 2), overlay (phase 3), col 3 (phase 4) */
|
||
.cycle-reveal { opacity: 0; transform: translateX(14px); transition: opacity 380ms ease-out, transform 380ms ease-out; }
|
||
.cycle-reveal.is-visible { opacity: 1; transform: translateX(0); }
|
||
.cycle-reveal-up { opacity: 0; transform: translateY(10px); transition: opacity 500ms ease-out, transform 500ms ease-out; }
|
||
.cycle-reveal-up.is-visible { opacity: 1; transform: translateY(0); }
|
||
|
||
/* Cycle horloge rotation (col 1) */
|
||
@keyframes cycle-clock-spin { to { transform: rotate(360deg); } }
|
||
.cycle-clock { animation: cycle-clock-spin 8s linear infinite; transform-origin: center; display: inline-block; }
|
||
|
||
/* Cycle col 2 — fuite particules rouges */
|
||
@keyframes cycle-leak {
|
||
0% { transform: translate(0,0) scale(1); opacity: 0; }
|
||
20% { opacity: 0.75; }
|
||
100% { transform: translate(var(--lx,18px), var(--ly,-22px)) scale(0.4); opacity: 0; }
|
||
}
|
||
.cycle-leak-particle { animation: cycle-leak 1.8s ease-out infinite; }
|
||
|
||
/* Reduced motion */
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.cycle-pulse, .cycle-card-dictia, .cycle-ring-outer, .cycle-ring-inner,
|
||
.cycle-clock, .cycle-leak-particle { animation: none !important; }
|
||
.cycle-reveal, .cycle-reveal-up { opacity: 1 !important; transform: none !important; }
|
||
.cycle-line { stroke-dashoffset: 0 !important; }
|
||
}
|
||
</style>
|
||
<section
|
||
class="bg-white py-20 border-y border-brand-border relative overflow-hidden"
|
||
aria-labelledby="cycle-title"
|
||
x-data="{ phase: 0, observer: null }"
|
||
x-init="
|
||
observer = new IntersectionObserver((entries) => {
|
||
entries.forEach(e => {
|
||
if (e.isIntersecting && phase === 0) {
|
||
setTimeout(() => phase = 1, 250);
|
||
setTimeout(() => phase = 2, 1100);
|
||
setTimeout(() => phase = 3, 2200);
|
||
setTimeout(() => phase = 4, 3000);
|
||
observer.disconnect();
|
||
}
|
||
});
|
||
}, { rootMargin: '-60px' });
|
||
observer.observe($el);
|
||
"
|
||
>
|
||
{# Subtle dot-grid bg #}
|
||
<div class="absolute inset-0 pointer-events-none" aria-hidden="true"
|
||
style="background-image: radial-gradient(circle, rgba(11,15,26,0.04) 1px, transparent 1px); background-size: 28px 28px;"></div>
|
||
|
||
<div class="relative max-w-[1200px] mx-auto px-6">
|
||
<div class="max-w-2xl mb-10">
|
||
<p class="eyebrow text-amber-600 mb-4">⚠ CADRE RÉGLEMENTAIRE</p>
|
||
<h2 id="cycle-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black mb-3 text-brand-navy">
|
||
Trois options. <span class="text-brand-navy/30">Une seule est conforme.</span>
|
||
</h2>
|
||
<p class="text-base text-brand-navy/70">
|
||
La Loi 25, le Cloud Act américain et le Guide IA du Barreau du Québec délimitent vos options —
|
||
<span class="font-semibold text-brand-b1">pas votre volonté.</span>
|
||
</p>
|
||
</div>
|
||
|
||
<div class="max-w-5xl mx-auto">
|
||
|
||
{# Nœud source : "Réunion en cours" #}
|
||
<div class="flex justify-center mb-2">
|
||
<div class="relative inline-flex items-center gap-2.5 px-5 py-3 bg-brand-bg border border-brand-border rounded">
|
||
<template x-if="phase >= 1">
|
||
<span class="absolute inset-0 cycle-pulse pointer-events-none border border-brand-border rounded"></span>
|
||
</template>
|
||
<template x-if="phase >= 1">
|
||
<span class="absolute inset-0 cycle-pulse cycle-pulse-2 pointer-events-none border border-brand-border rounded"></span>
|
||
</template>
|
||
<template x-if="phase >= 1">
|
||
<span class="absolute inset-0 cycle-pulse cycle-pulse-3 pointer-events-none border border-brand-border rounded"></span>
|
||
</template>
|
||
<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-3.5 h-3.5 shrink-0 text-brand-navy/40" aria-hidden="true"><path d="M3 21h18"/><path d="M5 21V8l7-4 7 4v13"/><path d="M9 21v-6h6v6"/></svg>
|
||
<span class="text-[11px] tracking-wide text-brand-navy/55">Réunion en cours — données confidentielles</span>
|
||
</div>
|
||
</div>
|
||
|
||
{# Lignes de connexion SVG — de la source vers les 3 colonnes #}
|
||
<div class="relative h-10">
|
||
<svg class="w-full h-full" viewBox="0 0 100 10" preserveAspectRatio="none" aria-hidden="true">
|
||
<line class="cycle-line" :class="phase >= 1 ? 'is-visible' : ''"
|
||
x1="50" y1="0" x2="14" y2="10"
|
||
stroke="rgba(148,163,184,0.45)" stroke-width="0.3" stroke-dasharray="1.2 0.9" />
|
||
<line class="cycle-line" :class="phase >= 1 ? 'is-visible' : ''"
|
||
x1="50" y1="0" x2="50" y2="10"
|
||
stroke="rgba(239,68,68,0.45)" stroke-width="0.3" stroke-dasharray="1.2 0.9"
|
||
style="transition-delay: 80ms;" />
|
||
<line class="cycle-line" :class="phase >= 1 ? 'is-visible' : ''"
|
||
x1="50" y1="0" x2="86" y2="10"
|
||
stroke="rgba(0,189,216,0.55)" stroke-width="0.3" stroke-dasharray="1.2 0.9"
|
||
style="transition-delay: 160ms;" />
|
||
</svg>
|
||
</div>
|
||
|
||
{# Grille 3 colonnes — équivalence du grid-cols-[2fr_2fr_3fr] desktop #}
|
||
<div class="grid grid-cols-1 md:grid-cols-[2fr_2fr_3fr] gap-3 items-stretch">
|
||
|
||
{# COL 1 — Retranscription humaine #}
|
||
<div class="cycle-reveal-up flex flex-col rounded border border-brand-border bg-brand-bg overflow-hidden"
|
||
:class="phase >= 2 ? 'is-visible' : ''">
|
||
<div class="px-5 py-3 border-b border-brand-border">
|
||
<div class="font-mono text-[10px] tracking-[0.28em] uppercase text-brand-navy/40 mb-0.5">01</div>
|
||
<div class="font-bold text-sm text-brand-navy/55">Retranscription humaine</div>
|
||
</div>
|
||
<div class="flex-1 flex flex-col items-center justify-center px-5 py-7 gap-6">
|
||
{# Stack de papiers #}
|
||
<div class="relative w-[100px] h-[90px]" aria-hidden="true">
|
||
{% for offset in [0,1,2,3,4] %}
|
||
<div class="absolute left-0 right-0 h-[17px] rounded-sm flex items-center px-2 gap-1.5 bg-white border border-brand-border"
|
||
style="bottom: {{ offset * 15 }}px; transform: rotate({{ '1deg' if offset is even else '-1deg' }});">
|
||
<div class="w-2.5 h-1.5 rounded-sm bg-brand-navy/15 shrink-0"></div>
|
||
<div class="flex-1 h-[1.5px] rounded-full bg-brand-navy/10"></div>
|
||
</div>
|
||
{% endfor %}
|
||
</div>
|
||
<div class="flex items-center gap-4 w-full">
|
||
<div class="flex flex-col items-center gap-1.5 flex-1">
|
||
<span class="cycle-clock">
|
||
<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-5 h-5 text-brand-navy/45" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
|
||
</span>
|
||
<span class="font-mono text-[10px] text-brand-navy/45">5 jours</span>
|
||
</div>
|
||
<div class="w-px h-8 bg-brand-border"></div>
|
||
<div class="flex flex-col items-center gap-1.5 flex-1">
|
||
<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-5 h-5 text-brand-navy/45" 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"/><path d="M14 2v6h6"/></svg>
|
||
<span class="font-mono text-[10px] text-brand-navy/45">~85 $/h</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="px-5 pb-5 pt-4 border-t border-brand-border">
|
||
<div class="flex items-baseline gap-1.5 mb-2">
|
||
<span class="font-black text-3xl leading-none text-brand-navy/65">315</span>
|
||
<span class="text-xs text-brand-navy/45">$ / réunion</span>
|
||
</div>
|
||
<span class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded bg-red-50 border border-red-100">
|
||
<span class="w-1 h-1 rounded-full bg-red-400"></span>
|
||
<span class="font-mono text-[9px] tracking-[0.16em] uppercase text-red-500/80">Lent · Coûteux</span>
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
{# COL 2 — IA cloud américaine #}
|
||
<div class="cycle-reveal-up relative flex flex-col rounded border border-red-200 bg-red-50/30 overflow-hidden"
|
||
:class="phase >= 2 ? 'is-visible' : ''"
|
||
style="transition-delay: 120ms;">
|
||
{# Overlay légal NON CONFORME (phase 3) #}
|
||
<div class="absolute inset-0 z-30 flex flex-col items-center justify-center pointer-events-none cycle-reveal-up"
|
||
:class="phase >= 3 ? 'is-visible' : ''"
|
||
style="backdrop-filter: blur(6px); background: rgba(255,255,255,0.78);">
|
||
<div class="flex flex-col items-center gap-3 px-6 py-5 rounded bg-white border border-red-300 shadow-lg">
|
||
<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-7 h-7 text-red-500" aria-hidden="true"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
|
||
<div class="text-center">
|
||
<div class="font-mono font-bold tracking-[0.14em] text-sm uppercase text-red-600">NON CONFORME</div>
|
||
<div class="font-mono text-[10px] tracking-[0.20em] uppercase mt-1.5 text-red-500/70">Loi 25 · Cloud Act américain</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="px-5 py-3 border-b border-red-100">
|
||
<div class="font-mono text-[10px] tracking-[0.28em] uppercase text-red-500/60 mb-0.5">02</div>
|
||
<div class="font-bold text-sm text-red-500/75">IA cloud américaine</div>
|
||
</div>
|
||
|
||
<div class="relative flex-1 flex flex-col items-center justify-center px-5 py-6 gap-5">
|
||
<div class="relative flex flex-col items-center gap-2">
|
||
<div class="relative w-14 h-14 rounded flex items-center justify-center bg-red-100/60 border border-red-200" aria-hidden="true">
|
||
<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-6 h-6 text-red-500/70"><path d="M2 12s3-7 10-7c2.5 0 4.7.9 6.4 2.4M22 12s-3 7-10 7c-2.5 0-4.7-.9-6.4-2.4"/><line x1="2" y1="2" x2="22" y2="22"/></svg>
|
||
{# Particules de fuite #}
|
||
{% for i in range(6) %}
|
||
<span class="cycle-leak-particle absolute w-[3px] h-[3px] rounded-full bg-red-400 pointer-events-none"
|
||
style="left: 50%; top: 50%; --lx: {{ (-30 + i*12) }}px; --ly: -{{ 14 + (i % 3) * 8 }}px; animation-delay: {{ i * 0.20 }}s;"></span>
|
||
{% endfor %}
|
||
</div>
|
||
<div class="px-2 py-0.5 rounded bg-red-50 border border-red-100">
|
||
<span class="font-mono text-[9px] tracking-[0.22em] uppercase text-red-500/65">USA</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="flex flex-col gap-2.5 w-full">
|
||
{% for risk in [
|
||
('cloud', 'Données transférées aux États-Unis'),
|
||
('alert', "Entraînement de l'IA publique"),
|
||
('users', '500–750 $/mois · facturation par utilisateur')
|
||
] %}
|
||
<div class="flex items-start gap-2.5">
|
||
{% if risk[0] == 'cloud' %}
|
||
<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 mt-0.5 shrink-0 text-red-500/60" aria-hidden="true"><path d="M2 12s3-7 10-7c2.5 0 4.7.9 6.4 2.4M22 12s-3 7-10 7c-2.5 0-4.7-.9-6.4-2.4"/><line x1="2" y1="2" x2="22" y2="22"/></svg>
|
||
{% elif risk[0] == 'alert' %}
|
||
<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 mt-0.5 shrink-0 text-red-500/60" aria-hidden="true"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
|
||
{% else %}
|
||
<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 mt-0.5 shrink-0 text-red-500/60" 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"/></svg>
|
||
{% endif %}
|
||
<span class="text-[12px] leading-snug text-brand-navy/55">{{ risk[1] | safe }}</span>
|
||
</div>
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
|
||
<div class="px-5 pb-5 pt-4 border-t border-red-100">
|
||
<div class="flex items-center gap-2">
|
||
<div class="w-1.5 h-1.5 rounded-full bg-red-400"></div>
|
||
<span class="font-mono text-[9px] tracking-[0.20em] uppercase text-red-500/70">Violation légale possible</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{# COL 3 — DictIA (featured, 3fr) #}
|
||
<div class="cycle-card-dictia cycle-reveal-up relative flex flex-col rounded border border-brand-b1/35 bg-gradient-to-br from-brand-b1/[0.06] to-brand-b3/[0.04] overflow-hidden"
|
||
:class="phase >= 4 ? 'is-visible' : ''"
|
||
style="transition-delay: 240ms;">
|
||
{# Halo ambiant #}
|
||
<div class="absolute inset-0 pointer-events-none" aria-hidden="true"
|
||
style="background: radial-gradient(ellipse 80% 35% at 50% 0%, rgba(0,189,216,0.12) 0%, transparent 65%);"></div>
|
||
|
||
<div class="relative px-5 py-3 border-b border-brand-b1/15 flex items-center gap-2.5">
|
||
<div class="relative w-4 h-4 flex items-center justify-center shrink-0">
|
||
<div class="absolute inset-0 rounded-full bg-brand-b1/15 border border-brand-b1/30"></div>
|
||
<div class="w-1.5 h-1.5 rounded-full bg-brand-b1"></div>
|
||
</div>
|
||
<span class="text-[11px] uppercase tracking-[0.22em] font-semibold text-brand-b1/80">Solution</span>
|
||
</div>
|
||
|
||
<div class="relative flex-1 flex flex-col items-center justify-center px-5 py-7 gap-5">
|
||
{# Lock + anneaux concentriques #}
|
||
<div class="relative flex items-center justify-center" aria-hidden="true">
|
||
<span class="cycle-ring-outer absolute rounded-full border border-brand-b1/15"
|
||
:class="phase >= 4 ? 'is-visible' : ''"
|
||
style="width: 96px; height: 96px;"></span>
|
||
<span class="cycle-ring-inner absolute rounded-full border border-brand-b1/25"
|
||
:class="phase >= 4 ? 'is-visible' : ''"
|
||
style="width: 68px; height: 68px;"></span>
|
||
<div class="relative w-[52px] h-[52px] rounded flex items-center justify-center bg-gradient-to-br from-brand-b1/15 to-brand-b3/10 border border-brand-b1/35">
|
||
<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-6 h-6 text-brand-b1"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
|
||
</div>
|
||
</div>
|
||
|
||
{# Flux sécurisé #}
|
||
<div class="cycle-reveal flex items-center gap-2 px-3.5 py-1.5 rounded bg-brand-b1/5 border border-brand-b1/15"
|
||
:class="phase >= 4 ? 'is-visible' : ''"
|
||
style="transition-delay: 350ms;">
|
||
<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-3 h-3 shrink-0 text-brand-b1/55" 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"/></svg>
|
||
<span class="text-[11px] text-brand-b1/70">Transcription sécurisée</span>
|
||
<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-3 h-3 text-brand-b1/45" aria-hidden="true"><path d="M5 12h14M13 5l7 7-7 7"/></svg>
|
||
<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-3 h-3 shrink-0 text-brand-b1/55" 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"/></svg>
|
||
</div>
|
||
|
||
{# Badges conformité #}
|
||
<div class="flex flex-col gap-2 w-full">
|
||
{% for badge_label in ['Loi 25 conforme', '100 % hébergé au Québec', 'Données jamais partagées'] %}
|
||
<div class="cycle-reveal flex items-center gap-2.5 px-3.5 py-2.5 rounded bg-brand-b1/[0.06] border border-brand-b1/20"
|
||
:class="phase >= 4 ? 'is-visible' : ''"
|
||
style="transition-delay: {{ 180 + loop.index0 * 170 }}ms;">
|
||
<span class="w-4 h-4 rounded-full flex items-center justify-center shrink-0 bg-brand-b1/15 border border-brand-b1/30">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="w-2.5 h-2.5 text-brand-b1" aria-hidden="true"><path d="M5 13l4 4L19 7"/></svg>
|
||
</span>
|
||
<span class="text-[12px] font-medium text-brand-navy/75">{{ badge_label | safe }}</span>
|
||
</div>
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
|
||
<div class="relative px-5 pb-5 pt-4 border-t border-brand-b1/15">
|
||
<div class="flex items-center gap-2 mb-2.5">
|
||
<span class="flex-1 h-px bg-brand-b1/15"></span>
|
||
<span class="font-mono font-bold text-[10px] uppercase tracking-[0.20em] text-brand-b1">UTILISATEURS ILLIMITÉS</span>
|
||
<span class="flex-1 h-px bg-brand-b1/15"></span>
|
||
</div>
|
||
<p class="text-center text-[10px] mb-3.5 text-brand-b1/55">Zéro frais caché · Du jamais vu</p>
|
||
<div class="flex items-baseline gap-2">
|
||
<span class="font-black leading-none text-5xl text-brand-b1">173</span>
|
||
<span class="text-sm text-brand-navy/45 mb-0.5">$ / mois</span>
|
||
</div>
|
||
<div class="flex items-center gap-1.5 mt-2">
|
||
<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-3 h-3 text-brand-b1/65" aria-hidden="true"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
|
||
<p class="text-[10px] text-brand-b1/60">Conforme Loi 25 · 100 % Québec</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{# Barre d'économies — apparaît avec phase 4 #}
|
||
<div class="cycle-reveal-up mt-10 flex flex-wrap items-center gap-x-8 gap-y-3 justify-center"
|
||
:class="phase >= 4 ? 'is-visible' : ''"
|
||
style="transition-delay: 700ms;">
|
||
<div class="flex items-center gap-2 text-[12px] text-brand-navy/55">
|
||
<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-3.5 h-3.5 text-emerald-500" aria-hidden="true"><polyline points="23 18 13.5 8.5 8.5 13.5 1 6"/><polyline points="17 18 23 18 23 12"/></svg>
|
||
Économies annuelles · 25 utilisateurs
|
||
</div>
|
||
{% for sav in [('3 924 $', 'vs Otter.ai'), ('6 924 $', 'vs MS Teams'), ('2 004 $', 'vs Sténographe')] %}
|
||
<div class="flex items-baseline gap-1.5">
|
||
<span class="font-black text-xl text-emerald-600">{{ sav[0] | safe }}</span>
|
||
<span class="text-xs text-brand-navy/55">{{ sav[1] }}</span>
|
||
</div>
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
{# ===== SOLUTION (S de PAS) ===== #}
|
||
<section class="relative bg-brand-navy text-white py-20 overflow-hidden" aria-labelledby="solution-title">
|
||
{# Single subtle orb in solution bg — less busy than hero #}
|
||
<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-2xl mx-auto mb-12">
|
||
<p class="eyebrow grad-text mb-4">LA SOLUTION — DICTIA</p>
|
||
<h2 id="solution-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black mb-4">
|
||
Conforme <span class="grad-text">par design</span>, pas par défaut.
|
||
</h2>
|
||
<p class="text-lg text-white/70">
|
||
DictIA reproduit la précision des outils cloud — WhisperX Large-v3 + Mistral 7B — mais avec une architecture où vos données ne quittent jamais vos murs ou nos serveurs OVH Beauharnois.
|
||
</p>
|
||
</div>
|
||
|
||
{# 3 solution pillars — dark cards with grad-bg icon corners #}
|
||
<div class="grid md:grid-cols-3 gap-6">
|
||
{% for pillar in [
|
||
('100 % local', 'Vos données ne sortent jamais de vos murs. Inférence GPU sur place ou VPS Québec OVH Beauharnois — vous gardez le contrôle, l\'audit, et les clés.'),
|
||
('Conforme Loi 25', 'Audit trail intégré (qui a écouté quoi, quand). Déclaration CAI prête. Consentement explicite tracé pour chaque enregistrement. Code source AGPL v3 — transparence vérifiable.'),
|
||
('Précision FR-CA', 'WhisperX Large-v3 fine-tuné français québécois. Diarisation pyannote 8 locuteurs. Résumés Mistral 7B local — aucune connexion OpenAI/Google/Microsoft.')
|
||
] %}
|
||
<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">{{ pillar[0] | safe }}</h3>
|
||
<p class="text-sm text-white/70 leading-relaxed">{{ pillar[1] | safe }}</p>
|
||
</article>
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
{# ===== WAVE — Onde de transformation chaos→ordre ===== #}
|
||
{# Source canonique : InnovA-AI/Website-Sanity/components/sections/dictai-wave.tsx
|
||
Animation : slider mouse-X interactif morphe les barres rouge→cyan, particules pain→solution.
|
||
Mobile : bouton toggle (activé/désactivé) — pas de mousemove. #}
|
||
<style>
|
||
/* Wave bars — chaque barre est composée d'un wrapper + 2 spans (rouge et cyan) qu'on fait fader */
|
||
.wave-bar { transition: opacity 60ms linear, transform 60ms linear; }
|
||
|
||
/* Wave pain labels — flottent légèrement */
|
||
@keyframes wave-pain-float {
|
||
0%, 100% { transform: translate(-50%, calc(-50% - 2px)); opacity: 0.7; }
|
||
50% { transform: translate(-50%, calc(-50% + 3px)); opacity: 0.45; }
|
||
}
|
||
.wave-pain { animation: wave-pain-float 3.4s ease-in-out infinite; }
|
||
.wave-pain:nth-child(2) { animation-delay: 0.4s; }
|
||
.wave-pain:nth-child(3) { animation-delay: 0.8s; }
|
||
.wave-pain:nth-child(4) { animation-delay: 1.2s; }
|
||
|
||
/* Wave fall particles — chute des $ et h */
|
||
@keyframes wave-fall {
|
||
0% { transform: translate(-50%, 0) scale(1); opacity: 0.85; }
|
||
50% { transform: translate(-50%, 22px) scale(0.7); opacity: 0.30; }
|
||
100% { transform: translate(-50%, 42px) scale(0.3); opacity: 0; }
|
||
}
|
||
.wave-fall { animation: wave-fall 2.4s ease-out infinite; }
|
||
|
||
/* Wave flow particles — flux cyan gauche→droite (état ordre) */
|
||
@keyframes wave-flow {
|
||
0% { left: 12%; opacity: 0; }
|
||
20% { opacity: 0.85; }
|
||
100% { left: 84%; opacity: 0; }
|
||
}
|
||
.wave-flow { animation: wave-flow 1.7s linear infinite; }
|
||
|
||
/* Wave hint — chevron CTA hover droite */
|
||
@keyframes wave-hint-pulse {
|
||
0%, 100% { transform: translateX(0); opacity: 0.55; }
|
||
50% { transform: translateX(7px); opacity: 1; }
|
||
}
|
||
.wave-hint { animation: wave-hint-pulse 1.5s ease-in-out infinite; }
|
||
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.wave-pain, .wave-fall, .wave-flow, .wave-hint { animation: none !important; }
|
||
}
|
||
</style>
|
||
<section class="bg-brand-navy text-white py-20 border-t border-white/[0.06] overflow-hidden" aria-labelledby="wave-title"
|
||
x-data="{
|
||
p: 0,
|
||
isMobile: false,
|
||
activated: false,
|
||
init() {
|
||
this.isMobile = window.innerWidth < 768;
|
||
window.addEventListener('resize', () => { this.isMobile = window.innerWidth < 768; });
|
||
},
|
||
onMove(e) {
|
||
if (this.isMobile) return;
|
||
const r = e.currentTarget.getBoundingClientRect();
|
||
this.p = Math.max(0, Math.min(1, (e.clientX - r.left) / r.width));
|
||
},
|
||
onLeave() { if (!this.isMobile) this.p = 0; },
|
||
toggle() { this.activated = !this.activated; this.p = this.activated ? 1 : 0; },
|
||
clamp(v) { return Math.max(0, Math.min(1, v)); },
|
||
get chaosOp() { return this.clamp(1 - (this.p - 0.12) / 0.42); },
|
||
get orderOp() { return this.clamp((this.p - 0.42) / 0.42); }
|
||
}">
|
||
<div class="max-w-[1200px] mx-auto px-6">
|
||
<div class="flex items-center gap-3 mb-5">
|
||
<span class="eyebrow text-brand-b3">Le problème</span>
|
||
<span class="flex-1 h-px bg-white/10 max-w-[60px]"></span>
|
||
</div>
|
||
<h2 id="wave-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black leading-[1.05] mb-3">
|
||
La transcription manuelle <span class="grad-text">coûte cher</span>.
|
||
</h2>
|
||
<p class="text-base text-white/55 mb-8 max-w-lg hidden md:block">
|
||
Déplacez votre curseur vers la droite pour transcrire l'avenir.
|
||
</p>
|
||
<p class="text-base text-white/55 mb-8 max-w-lg md:hidden">
|
||
Touchez pour basculer entre : aujourd'hui (chaos) et avec DictIA (ordre).
|
||
</p>
|
||
|
||
{# Scène interactive — aspect-ratio 2/1 desktop, 4/3 mobile #}
|
||
<div
|
||
class="relative w-full max-w-5xl mx-auto overflow-hidden rounded border border-white/[0.06]"
|
||
style="aspect-ratio: 2 / 1; min-height: 280px; cursor: ew-resize;"
|
||
:style="isMobile ? 'cursor: pointer; aspect-ratio: 4/3' : ''"
|
||
@mousemove="onMove($event)"
|
||
@mouseleave="onLeave()"
|
||
@click="if (isMobile) toggle()"
|
||
role="img"
|
||
aria-label="Visualisation interactive : transcription manuelle (chaos rouge) vs DictIA (ordre cyan)"
|
||
>
|
||
{# Fond dégradé radial dynamique #}
|
||
<div class="absolute inset-0"
|
||
:style="`background: radial-gradient(ellipse 75% 75% at 50% 50%, rgba(${Math.round(45 + (11-45)*p)},${Math.round(10 + (15-10)*p)},${Math.round(12 + (40-12)*p)},0.55) 0%, rgba(11,15,26,1) 100%);`"
|
||
aria-hidden="true"></div>
|
||
|
||
{# Grille subtile #}
|
||
<div class="absolute inset-0 opacity-[0.02]"
|
||
style="background-image: linear-gradient(rgba(255,255,255,0.1) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.1) 1px, transparent 1px); background-size: 40px 40px;"
|
||
aria-hidden="true"></div>
|
||
|
||
{# SVG : 30 barres d'onde — calculées par macro Jinja (chaos vs order par lerp p) #}
|
||
<svg class="absolute inset-0 w-full h-full pointer-events-none z-10" viewBox="0 0 100 50" preserveAspectRatio="none" aria-hidden="true">
|
||
<defs>
|
||
<filter id="dw-glow" x="-50%" y="-50%" width="200%" height="200%">
|
||
<feGaussianBlur stdDeviation="0.9" result="blur"/>
|
||
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
|
||
</filter>
|
||
</defs>
|
||
|
||
{# Fixed bar geometry — nous générons 30 barres avec hauteur min/max statique;
|
||
l'opacité chaos vs order est gérée par 2 groupes superposés contrôlés par x-attr style. #}
|
||
{% set NUM_BARS = 30 %}
|
||
{% set chaos_heights = [10.5, 13.2, 15.8, 17.4, 18.1, 17.6, 15.9, 13.6, 11.2, 9.5, 8.7, 9.4, 11.7, 14.5, 17.2, 18.8, 18.6, 16.9, 14.3, 11.5, 9.2, 8.4, 9.8, 12.6, 15.5, 17.5, 17.8, 16.2, 13.4, 10.1] %}
|
||
{% set order_heights = [0.85, 0.95, 1.05, 1.15, 1.10, 1.00, 0.92, 0.88, 1.00, 1.12, 1.18, 1.14, 1.05, 0.95, 0.88, 0.92, 1.05, 1.15, 1.18, 1.10, 1.00, 0.92, 0.88, 0.95, 1.10, 1.18, 1.15, 1.05, 0.95, 0.90] %}
|
||
{% for i in range(NUM_BARS) %}
|
||
{% set spacing = 84 / NUM_BARS %}
|
||
{% set bw = spacing * 0.52 %}
|
||
{% set cx = 8 + i * spacing + spacing / 2 %}
|
||
{# Chaos bar — visible quand p ≈ 0 #}
|
||
<g class="wave-bar" :style="`opacity: ${1 - p}`">
|
||
<rect x="{{ cx - bw / 2 }}" y="{{ 25 - chaos_heights[i] / 2 }}" width="{{ bw }}" height="{{ chaos_heights[i] }}" rx="{{ bw / 2 }}" fill="rgba(255,75,75,0.78)"/>
|
||
</g>
|
||
{# Order bar — visible quand p ≈ 1 #}
|
||
<g class="wave-bar" :style="`opacity: ${p}`">
|
||
<rect x="{{ cx - bw / 2 }}" y="{{ 25 - order_heights[i] / 2 }}" width="{{ bw }}" height="{{ order_heights[i] }}" rx="{{ bw / 2 }}" fill="rgba(107,159,255,0.6)"/>
|
||
</g>
|
||
{% endfor %}
|
||
|
||
{# Bouclier holographique (état ordre) #}
|
||
<path d="M 50 8 L 68 14 L 68 27 Q 68 38 50 43 Q 32 38 32 27 L 32 14 Z"
|
||
fill="none" stroke="rgba(107,159,255,0.55)" stroke-width="0.55" stroke-dasharray="2.5 2"
|
||
:style="`opacity: ${orderOp * 0.4}`"/>
|
||
</svg>
|
||
|
||
{# Icône Microphone (gauche) #}
|
||
<div class="absolute z-20 left-[3%] top-1/2 -translate-y-1/2 flex flex-col items-center gap-1.5"
|
||
:style="`opacity: ${Math.max(0.25, 1 - p * 0.55)}`" aria-hidden="true">
|
||
<div class="w-10 h-10 md:w-12 md:h-12 rounded flex items-center justify-center backdrop-blur-md border"
|
||
:style="`background: rgba(${Math.round(255 + (107-255)*p)},${Math.round(60 + (130-60)*p)},${Math.round(60 + (159-60)*p)},0.12); border-color: rgba(${Math.round(255 + (107-255)*p)},${Math.round(80 + (159-80)*p)},${Math.round(80 + (255-80)*p)},0.28);`">
|
||
<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 md:w-5 md:h-5"
|
||
:style="`color: ${p < 0.5 ? '#FF6B6B' : '#6B9FFF'}`"><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>
|
||
</div>
|
||
<span class="text-[8px] font-medium" :style="`color: ${p < 0.5 ? 'rgba(255,107,107,0.65)' : 'rgba(107,159,255,0.65)'}`">Audio</span>
|
||
</div>
|
||
|
||
{# Icône Texte transcrit (droite) #}
|
||
<div class="absolute z-20 right-[3%] top-1/2 -translate-y-1/2 flex flex-col items-center gap-1.5"
|
||
:style="`opacity: ${orderOp}`" aria-hidden="true">
|
||
<div class="w-10 h-10 md:w-12 md:h-12 rounded flex items-center justify-center backdrop-blur-md border border-brand-b1/30"
|
||
style="background: linear-gradient(135deg, rgba(107,159,255,0.15), rgba(45,127,249,0.07)); box-shadow: 0 0 18px rgba(107,159,255,0.18);">
|
||
<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 md:w-5 md:h-5 text-brand-b1"><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"/></svg>
|
||
</div>
|
||
<span class="text-[8px] font-medium text-brand-b1/70">Texte</span>
|
||
</div>
|
||
|
||
{# Particules tombantes chaos ($, h) #}
|
||
<div class="absolute inset-0 z-10 pointer-events-none" :style="`opacity: ${chaosOp}`" aria-hidden="true">
|
||
{% for fp in [
|
||
{'x': 22, 'd': 0, 'type': 'money'},
|
||
{'x': 36, 'd': 0.9, 'type': 'time'},
|
||
{'x': 50, 'd': 1.5, 'type': 'money'},
|
||
{'x': 63, 'd': 0.4, 'type': 'time'},
|
||
{'x': 77, 'd': 1.2, 'type': 'money'},
|
||
{'x': 30, 'd': 1.9, 'type': 'time'},
|
||
{'x': 56, 'd': 0.7, 'type': 'money'},
|
||
{'x': 43, 'd': 2.1, 'type': 'time'}
|
||
] %}
|
||
<span class="wave-fall absolute font-bold text-[9px] md:text-[10px]"
|
||
style="left: {{ fp.x }}%; top: 30%; color: {{ '#FF6B6B' if fp.type == 'money' else '#FFD93D' }}; text-shadow: 0 0 8px rgba({{ '255,80,80' if fp.type == 'money' else '255,210,60' }},0.6); animation-delay: {{ fp.d }}s;">{{ '-$' if fp.type == 'money' else '-1h' }}</span>
|
||
{% endfor %}
|
||
</div>
|
||
|
||
{# Flux cyan (ordre) #}
|
||
<div class="absolute inset-0 z-10 pointer-events-none" :style="`opacity: ${orderOp}`" aria-hidden="true">
|
||
{% for fy in [18, 21, 24, 27, 30] %}
|
||
<span class="wave-flow absolute w-1 h-1 rounded-full bg-brand-b1"
|
||
style="top: {{ fy }}%; left: 12%; box-shadow: 0 0 5px rgba(107,159,255,0.7); animation-delay: {{ loop.index0 * 0.32 }}s;"></span>
|
||
{% endfor %}
|
||
</div>
|
||
|
||
{# Étiquettes douleur (chaos) #}
|
||
<div class="absolute inset-0 pointer-events-none" :style="`opacity: ${chaosOp}`" aria-hidden="true">
|
||
{% for pain in [
|
||
{'text': '4 à 6h pour transcrire 1h', 'x': 20, 'y': 12},
|
||
{'text': '600 à 1 800 $ / enregistrement', 'x': 64, 'y': 10},
|
||
{'text': 'Délais de 48h à 5 jours', 'x': 74, 'y': 38},
|
||
{'text': 'Risques de confidentialité', 'x': 18, 'y': 40}
|
||
] %}
|
||
<div class="wave-pain absolute text-[8px] md:text-[10px] font-medium px-2 py-0.5 rounded whitespace-nowrap"
|
||
style="left: {{ pain.x }}%; top: {{ pain.y }}%; transform: translate(-50%, -50%); background: rgba(255,50,50,0.1); border: 1px solid rgba(255,80,80,0.18); color: rgba(255,150,130,0.85);">
|
||
{{ pain.text | safe }}
|
||
</div>
|
||
{% endfor %}
|
||
</div>
|
||
|
||
{# Cartes solution (ordre) #}
|
||
<div class="absolute inset-0 pointer-events-none" :style="`opacity: ${orderOp}`" aria-hidden="true">
|
||
{% for sol in [
|
||
{'text': '~2 min pour 1h d\'audio', 'x': 20, 'y': 12},
|
||
{'text': 'Dès 173 $/mois — illimité', 'x': 64, 'y': 10},
|
||
{'text': '90 %+ d\'économies', 'x': 74, 'y': 38},
|
||
{'text': '100 % Confidentiel — Hébergé au Qc', 'x': 18, 'y': 40}
|
||
] %}
|
||
<div class="absolute flex items-center gap-1.5 px-2 py-1 rounded backdrop-blur-sm"
|
||
style="left: {{ sol.x }}%; top: {{ sol.y }}%; transform: translate(-50%, -50%); background: rgba(107,159,255,0.10); border: 1px solid rgba(107,159,255,0.20);">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="w-2.5 h-2.5 text-brand-b1 shrink-0" aria-hidden="true"><path d="M5 13l4 4L19 7"/></svg>
|
||
<span class="text-[8px] md:text-[10px] text-white/80 whitespace-nowrap">{{ sol.text | safe }}</span>
|
||
</div>
|
||
{% endfor %}
|
||
</div>
|
||
|
||
{# Séparateur central + hint "→" #}
|
||
<div class="absolute left-1/2 top-0 bottom-0 w-px z-10 hidden md:block pointer-events-none"
|
||
:style="`opacity: ${Math.max(0, 1 - p * 2.8)}; background: linear-gradient(to bottom, transparent 10%, rgba(255,255,255,0.06) 30%, rgba(255,255,255,0.06) 70%, transparent 90%);`"
|
||
aria-hidden="true">
|
||
<div class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 whitespace-nowrap"
|
||
:style="`opacity: ${Math.max(0, 1 - p * 3.2)}`">
|
||
<span class="wave-hint inline-block text-[9px] text-white/40 tracking-wider uppercase px-3 py-1 rounded-full border border-white/[0.08] bg-brand-navy/80 backdrop-blur-sm">
|
||
Survolez vers la droite →
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
{# Toggle mobile #}
|
||
<button type="button"
|
||
x-show="isMobile"
|
||
@click.stop="toggle()"
|
||
class="absolute bottom-3 left-1/2 -translate-x-1/2 z-30 inline-flex items-center gap-2 px-5 py-2.5 rounded text-xs font-bold transition-all border focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
|
||
:class="activated ? 'border-brand-b1/30 text-brand-b1' : 'border-white/15 text-white/70'"
|
||
:style="activated ? 'background: linear-gradient(135deg, rgba(107,159,255,0.2), rgba(45,127,249,0.1));' : 'background: linear-gradient(135deg, rgba(255,255,255,0.08), rgba(255,255,255,0.03));'"
|
||
x-cloak>
|
||
<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-3.5 h-3.5"><rect x="9" y="2" width="6" height="12" rx="3"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/></svg>
|
||
<span x-text="activated ? 'Voir sans DictIA' : 'Activer DictIA'"></span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
{# ===== PIPELINE — Comment ça marche : 4 étapes ===== #}
|
||
{# Source canonique : InnovA-AI/Website-Sanity/components/sections/dictai-pipeline.tsx
|
||
Animation traduite : Framer Motion auto-advance + sweep ring → Alpine.js setInterval + CSS keyframes #}
|
||
<style>
|
||
/* Sweep ring on the active pipeline node — restarts via :key (DOM swap) */
|
||
@keyframes pipeline-sweep {
|
||
from { stroke-dashoffset: 257.6; }
|
||
to { stroke-dashoffset: 0; }
|
||
}
|
||
.pipeline-sweep-ring {
|
||
stroke-dasharray: 257.6; /* 2π × 41 */
|
||
animation: pipeline-sweep 2400ms linear forwards;
|
||
}
|
||
/* Underline sweep on the description card — restart on Alpine swap */
|
||
@keyframes pipeline-underline {
|
||
from { transform: scaleX(0); }
|
||
to { transform: scaleX(1); }
|
||
}
|
||
.pipeline-underline {
|
||
transform-origin: left;
|
||
animation: pipeline-underline 2400ms linear forwards;
|
||
}
|
||
/* Glowing dot trailing the active step on the track */
|
||
.pipeline-dot {
|
||
transition: left 450ms cubic-bezier(0.4, 0, 0.2, 1);
|
||
}
|
||
/* Filled track from start to active step */
|
||
.pipeline-track-fill {
|
||
transition: transform 450ms cubic-bezier(0.4, 0, 0.2, 1);
|
||
transform-origin: left;
|
||
}
|
||
/* Reduced motion : freeze auto-advance + remove all animations */
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.pipeline-sweep-ring, .pipeline-underline, .pipeline-dot, .pipeline-track-fill {
|
||
animation: none !important;
|
||
transition: none !important;
|
||
}
|
||
}
|
||
/* Hide Alpine x-show elements until Alpine hydrates (avoids FOUC flash of all 4 cards) */
|
||
[x-cloak] { display: none !important; }
|
||
</style>
|
||
<section class="bg-white py-20 border-y border-brand-border" aria-labelledby="pipeline-title">
|
||
<div class="max-w-[1100px] mx-auto px-6">
|
||
<div class="text-center max-w-2xl mx-auto mb-14">
|
||
<p class="eyebrow grad-text mb-4">COMMENT ÇA MARCHE</p>
|
||
<h2 id="pipeline-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black mb-4 text-brand-navy">
|
||
Du fichier au résumé <span class="grad-text">en 4 étapes</span>.
|
||
</h2>
|
||
<p class="text-lg text-brand-navy/70">
|
||
Aucune installation côté utilisateur, aucune conversion préalable. DictIA orchestre l'ensemble du pipeline — du téléversement à l'export — en moins de deux minutes pour une heure d'audio.
|
||
</p>
|
||
</div>
|
||
|
||
{# Pipeline track + 4 nodes — Alpine state drives all visuals.
|
||
active = 0..3 (current step), prefers-reduced-motion stops the autoplay (handled in x-init). #}
|
||
<div
|
||
class="relative max-w-4xl mx-auto"
|
||
x-data="{
|
||
active: 0,
|
||
timer: null,
|
||
steps: [
|
||
{ positionPct: 12.5, fillPct: 0 },
|
||
{ positionPct: 37.5, fillPct: 33.33 },
|
||
{ positionPct: 62.5, fillPct: 66.66 },
|
||
{ positionPct: 87.5, fillPct: 100 }
|
||
],
|
||
startTimer() {
|
||
if (this.timer) clearInterval(this.timer);
|
||
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
|
||
this.timer = setInterval(() => { this.active = (this.active + 1) % 4; }, 2400);
|
||
},
|
||
select(i) { this.active = i; this.startTimer(); }
|
||
}"
|
||
x-init="startTimer()"
|
||
>
|
||
{# Background + filled track (top: 44px = node center 88px / 2) #}
|
||
<div class="absolute h-px bg-brand-border" style="top: 44px; left: 12.5%; right: 12.5%;" aria-hidden="true"></div>
|
||
<div
|
||
class="pipeline-track-fill absolute h-[2px]"
|
||
style="top: 43px; left: 12.5%; width: 75%; background: linear-gradient(90deg, #0062ff 0%, #00bdd8 100%);"
|
||
:style="`transform: scaleX(${steps[active].fillPct / 100})`"
|
||
aria-hidden="true"
|
||
></div>
|
||
|
||
{# Moving glowing dot — left transitions via CSS #}
|
||
<div
|
||
class="pipeline-dot absolute w-3.5 h-3.5 rounded-full bg-white pointer-events-none z-10"
|
||
style="top: 44px; transform: translate(-50%, -50%); box-shadow: 0 0 18px rgba(0,189,216,0.55), 0 0 36px rgba(0,98,255,0.35);"
|
||
:style="`left: ${steps[active].positionPct}%`"
|
||
aria-hidden="true"
|
||
></div>
|
||
|
||
{# Nodes grid — 4 cols #}
|
||
<div class="grid grid-cols-4 gap-2">
|
||
{# Each step rendered statically; active state computed via :class. #}
|
||
{% set steps = [
|
||
('Uploader', 'Audio ou vidéo', '<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="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>',
|
||
"Glissez n'importe quel format — MP3, WAV, MP4, MKV. Aucune conversion nécessaire. DictIA accepte tout sans préparation."),
|
||
('GPU transcrit', 'WhisperX Large-v3', '<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="4" y="4" width="16" height="16" rx="2"/><rect x="9" y="9" width="6" height="6"/><path d="M9 1v3M15 1v3M9 20v3M15 20v3M20 9h3M20 14h3M1 9h3M1 14h3"/></svg>',
|
||
"Votre GPU traite le fichier 60× plus vite qu'un humain. 1 heure d'audio → 2 minutes. Précision 95 %+ en français canadien. 100 % en local — zéro cloud étranger."),
|
||
('IA structure', 'Mistral 7B / Nemo 12B', '<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.5 2A2.5 2.5 0 0 1 12 4.5v15a2.5 2.5 0 0 1-4.96.44 2.5 2.5 0 0 1-2.96-3.08 3 3 0 0 1-.34-5.58 2.5 2.5 0 0 1 1.32-4.24 2.5 2.5 0 0 1 1.98-3A2.5 2.5 0 0 1 9.5 2z"/><path d="M14.5 2A2.5 2.5 0 0 0 12 4.5v15a2.5 2.5 0 0 0 4.96.44 2.5 2.5 0 0 0 2.96-3.08 3 3 0 0 0 .34-5.58 2.5 2.5 0 0 0-1.32-4.24 2.5 2.5 0 0 0-1.98-3A2.5 2.5 0 0 0 14.5 2z"/></svg>',
|
||
"L'IA identifie automatiquement chaque locuteur, génère un résumé structuré, extrait les points d'action et répond à vos questions sur le contenu transcrit."),
|
||
('Exporter', 'Dans votre écosystème', '<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>',
|
||
"DOCX, SRT, VTT, JSON, Obsidian, Logseq. Connectez avec n8n, Zapier ou Make pour automatiser vos workflows — zéro copier-coller.")
|
||
] %}
|
||
{% for label, sublabel, icon, desc in steps %}
|
||
<button
|
||
type="button"
|
||
@click="select({{ loop.index0 }})"
|
||
class="group flex flex-col items-center gap-4 cursor-pointer select-none focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-4 rounded-none p-2"
|
||
:aria-current="active === {{ loop.index0 }} ? 'step' : 'false'"
|
||
aria-label="Étape {{ loop.index }} sur 4 : {{ label }} — {{ sublabel }}"
|
||
>
|
||
{# Circle node — visual state driven by :class (active / completed / pending) #}
|
||
<span
|
||
class="relative w-[88px] h-[88px] rounded-full border-2 flex items-center justify-center transition-all duration-300"
|
||
:class="{
|
||
'border-brand-b1 bg-brand-b1/10 scale-105 shadow-[0_0_28px_rgba(0,98,255,0.35)]': active === {{ loop.index0 }},
|
||
'border-brand-b3/60 bg-brand-b3/10': active > {{ loop.index0 }},
|
||
'border-brand-border bg-white': active < {{ loop.index0 }}
|
||
}"
|
||
aria-hidden="true"
|
||
>
|
||
<span
|
||
class="transition-opacity duration-300"
|
||
:class="active >= {{ loop.index0 }} ? 'opacity-100 text-brand-b1' : 'opacity-30 text-brand-navy/30'"
|
||
>{{ icon | safe }}</span>
|
||
|
||
{# Step badge — top-right corner with index #}
|
||
<span
|
||
class="absolute -top-1.5 -right-1.5 w-6 h-6 rounded-full flex items-center justify-center text-[11px] font-bold transition-colors duration-300"
|
||
:class="active >= {{ loop.index0 }} ? 'bg-brand-b1 text-white' : 'bg-brand-border text-brand-navy/40'"
|
||
>{{ loop.index }}</span>
|
||
|
||
{# Sweep progress ring — only visible on active step. Re-keyed via :key when active changes. #}
|
||
<template x-if="active === {{ loop.index0 }}">
|
||
<svg
|
||
:key="active"
|
||
class="absolute inset-0 w-full h-full -rotate-90 pointer-events-none"
|
||
viewBox="0 0 88 88"
|
||
aria-hidden="true"
|
||
>
|
||
<circle class="pipeline-sweep-ring" cx="44" cy="44" r="41" fill="none" stroke="#0062ff" stroke-width="2" stroke-linecap="round"></circle>
|
||
</svg>
|
||
</template>
|
||
</span>
|
||
|
||
{# Label + sublabel — opacity dimmed on pending steps #}
|
||
<span
|
||
class="text-center px-1 transition-opacity duration-300 block"
|
||
:class="active >= {{ loop.index0 }} ? 'opacity-100' : 'opacity-40'"
|
||
>
|
||
<span class="block font-bold text-sm leading-tight mb-0.5 text-brand-navy">{{ label }}</span>
|
||
<span class="block text-xs text-brand-navy/70 leading-tight">{{ sublabel }}</span>
|
||
</span>
|
||
</button>
|
||
{% endfor %}
|
||
</div>
|
||
|
||
{# Step description card — swaps with x-show + x-transition. Underline sweep restarts via :key on active. #}
|
||
<div class="mt-12 max-w-2xl mx-auto min-h-[110px] flex items-center justify-center">
|
||
{% for label, sublabel, icon, desc in steps %}
|
||
<div
|
||
x-show="active === {{ loop.index0 }}"
|
||
x-transition:enter="transition ease-out duration-300"
|
||
x-transition:enter-start="opacity-0 translate-y-2"
|
||
x-transition:enter-end="opacity-100 translate-y-0"
|
||
x-transition:leave="transition ease-in duration-150"
|
||
x-transition:leave-start="opacity-100"
|
||
x-transition:leave-end="opacity-0"
|
||
class="relative w-full bg-brand-bg border border-brand-border px-7 py-6 text-center rounded overflow-hidden"
|
||
x-cloak
|
||
>
|
||
<p class="text-sm text-brand-navy/80 leading-relaxed">{{ desc | safe }}</p>
|
||
<span
|
||
:key="active"
|
||
class="pipeline-underline absolute bottom-0 left-0 h-[2px] w-full"
|
||
style="background: linear-gradient(90deg, #0062ff, #00bdd8);"
|
||
aria-hidden="true"
|
||
></span>
|
||
</div>
|
||
{% endfor %}
|
||
</div>
|
||
|
||
{# Progress dots (mobile-friendly + click target redundancy) #}
|
||
<div class="flex justify-center gap-2 mt-8" role="tablist" aria-label="Sélectionner une étape">
|
||
{% for label, sublabel, icon, desc in steps %}
|
||
<button
|
||
type="button"
|
||
role="tab"
|
||
@click="select({{ loop.index0 }})"
|
||
class="h-1 rounded-full transition-all duration-300 focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
|
||
:class="{
|
||
'w-8 bg-brand-b1': active === {{ loop.index0 }},
|
||
'w-8 bg-brand-b3/60': active > {{ loop.index0 }},
|
||
'w-2 bg-brand-border': active < {{ loop.index0 }}
|
||
}"
|
||
:aria-selected="active === {{ loop.index0 }} ? 'true' : 'false'"
|
||
aria-label="Aller à l'étape {{ loop.index }} : {{ label }}"
|
||
></button>
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
{# ===== BENTO FEATURES ===== #}
|
||
<section class="bg-white py-20" aria-labelledby="bento-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">FONCTIONNALITÉS</p>
|
||
<h2 id="bento-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black text-brand-navy">
|
||
Tout ce dont vous avez besoin, <span class="grad-text">rien que vous n'ayez besoin</span>.
|
||
</h2>
|
||
</div>
|
||
|
||
{# 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 %+ 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&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) }}
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
{# ===== HUB — Réseau d'intégrations ===== #}
|
||
{# Source canonique : InnovA-AI/Website-Sanity/components/sections/dictai-hub.tsx
|
||
Animation : SVG pur avec <animateMotion> sur bezier paths — aucune lib JS, aucune config.
|
||
Particules cyan circulent en continu de DictIA → Hubs → Outils. #}
|
||
<style>
|
||
/* DictIA central node — pulsing rings (decorative, native CSS) */
|
||
@keyframes hub-ring-pulse {
|
||
0% { transform: scale(1); opacity: 0.55; }
|
||
70% { transform: scale(2.6); opacity: 0; }
|
||
100% { transform: scale(2.6); opacity: 0; }
|
||
}
|
||
.hub-ring { animation: hub-ring-pulse 3s ease-out infinite; }
|
||
.hub-ring-2 { animation-delay: 1s; }
|
||
.hub-ring-3 { animation-delay: 2s; }
|
||
/* DictIA core breathing glow */
|
||
@keyframes hub-core-breathe {
|
||
0%, 100% { box-shadow: 0 0 26px rgba(0,189,216,0.55), 0 0 56px rgba(0,189,216,0.18); }
|
||
50% { box-shadow: 0 0 38px rgba(0,189,216,0.75), 0 0 72px rgba(0,189,216,0.28); }
|
||
}
|
||
.hub-core { animation: hub-core-breathe 3.5s ease-in-out infinite; }
|
||
/* Reduced motion : freeze everything */
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.hub-ring, .hub-core { animation: none !important; }
|
||
/* Disable SVG animateMotion via display:none on the animateMotion elements (browser respects this). */
|
||
.hub-network-svg animateMotion { display: none !important; }
|
||
}
|
||
</style>
|
||
<section class="bg-brand-navy text-white py-20 overflow-hidden relative" aria-labelledby="hub-title">
|
||
{# Decorative cosmic orb — cyan, mid-section #}
|
||
<div class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[700px] h-[700px] rounded-full pointer-events-none" aria-hidden="true"
|
||
style="background: radial-gradient(circle, rgba(0,189,216,0.10) 0%, transparent 60%); filter: blur(60px);"></div>
|
||
|
||
<div class="relative 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 — RÉSEAU OUVERT</p>
|
||
<h2 id="hub-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black mb-4">
|
||
DictIA <span class="grad-text">se connecte à tout</span>.
|
||
</h2>
|
||
<p class="text-lg text-white/70">
|
||
Transcriptions et résumés acheminés automatiquement vers vos outils de travail. Trois familles d'intégrations couvrent l'essentiel des flux documentaires, communication et automatisation.
|
||
</p>
|
||
</div>
|
||
|
||
{# Network diagram — SVG with native <animateMotion> for particle flow.
|
||
Layout : DictIA center-top, 3 hubs (Documents | Communication | Automatisation), 9 tools below. #}
|
||
<div class="relative max-w-4xl mx-auto">
|
||
<svg
|
||
viewBox="0 0 900 460"
|
||
preserveAspectRatio="xMidYMid meet"
|
||
class="hub-network-svg w-full h-auto"
|
||
role="img"
|
||
aria-labelledby="hub-svg-title hub-svg-desc"
|
||
>
|
||
<title id="hub-svg-title">Diagramme du réseau d'intégrations DictIA</title>
|
||
<desc id="hub-svg-desc">DictIA au centre, connecté à trois familles : Documents (Word, Google Docs, Obsidian), Communication (Outlook, Teams, Notion) et Automatisation (Zapier, Make, n8n).</desc>
|
||
|
||
<defs>
|
||
{# Bezier path definitions — DictIA top → 3 hubs (mid) #}
|
||
<path id="hub-path-docs" d="M450,54 C450,127 168,127 168,200" />
|
||
<path id="hub-path-comm" d="M450,54 C450,127 450,127 450,200" />
|
||
<path id="hub-path-auto" d="M450,54 C450,127 732,127 732,200" />
|
||
|
||
{# Bezier paths — Hub → Tool #}
|
||
{# Documents hub (168, 200) → Word(62,390), Google(175,390), Obsidian(282,390) #}
|
||
<path id="hub-path-word" d="M168,216 C168,303 62,303 62,390" />
|
||
<path id="hub-path-google" d="M168,216 C168,303 175,303 175,390" />
|
||
<path id="hub-path-obsidian" d="M168,216 C168,303 282,303 282,390" />
|
||
{# Communication hub (450, 200) → Outlook(358,390), Teams(450,390), Notion(542,390) #}
|
||
<path id="hub-path-outlook" d="M450,216 C450,303 358,303 358,390" />
|
||
<path id="hub-path-teams" d="M450,216 C450,303 450,303 450,390" />
|
||
<path id="hub-path-notion" d="M450,216 C450,303 542,303 542,390" />
|
||
{# Automatisation hub (732, 200) → Zapier(618,390), Make(722,390), n8n(828,390) #}
|
||
<path id="hub-path-zapier" d="M732,216 C732,303 618,303 618,390" />
|
||
<path id="hub-path-make" d="M732,216 C732,303 722,303 722,390" />
|
||
<path id="hub-path-n8n" d="M732,216 C732,303 828,303 828,390" />
|
||
</defs>
|
||
|
||
{# Render bezier connections (visible strokes) — DictIA → Hubs (thick), Hub → Tools (thin) #}
|
||
{# DictIA → Hubs #}
|
||
<use href="#hub-path-docs" fill="none" stroke="#0062ff" stroke-width="1.5" opacity="0.55" />
|
||
<use href="#hub-path-comm" fill="none" stroke="#00bdd8" stroke-width="1.5" opacity="0.55" />
|
||
<use href="#hub-path-auto" fill="none" stroke="#8b5cf6" stroke-width="1.5" opacity="0.55" />
|
||
|
||
{# Hub → Tool (lighter) #}
|
||
<use href="#hub-path-word" fill="none" stroke="#0062ff" stroke-width="1" opacity="0.30" />
|
||
<use href="#hub-path-google" fill="none" stroke="#0062ff" stroke-width="1" opacity="0.30" />
|
||
<use href="#hub-path-obsidian" fill="none" stroke="#0062ff" stroke-width="1" opacity="0.30" />
|
||
<use href="#hub-path-outlook" fill="none" stroke="#00bdd8" stroke-width="1" opacity="0.30" />
|
||
<use href="#hub-path-teams" fill="none" stroke="#00bdd8" stroke-width="1" opacity="0.30" />
|
||
<use href="#hub-path-notion" fill="none" stroke="#00bdd8" stroke-width="1" opacity="0.30" />
|
||
<use href="#hub-path-zapier" fill="none" stroke="#8b5cf6" stroke-width="1" opacity="0.30" />
|
||
<use href="#hub-path-make" fill="none" stroke="#8b5cf6" stroke-width="1" opacity="0.30" />
|
||
<use href="#hub-path-n8n" fill="none" stroke="#8b5cf6" stroke-width="1" opacity="0.30" />
|
||
|
||
{# Animated particles — DictIA → Hubs (bigger, dual particles) #}
|
||
{% for hub in [
|
||
('docs', '#0062ff', '0s', '2.4s'),
|
||
('comm', '#00bdd8', '0.8s', '2.4s'),
|
||
('auto', '#8b5cf6', '1.6s', '2.4s')
|
||
] %}
|
||
<circle r="3.2" fill="{{ hub[1] }}" opacity="0.95">
|
||
<animateMotion dur="{{ hub[3] }}" repeatCount="indefinite" begin="{{ hub[2] }}">
|
||
<mpath href="#hub-path-{{ hub[0] }}" />
|
||
</animateMotion>
|
||
</circle>
|
||
<circle r="1.8" fill="{{ hub[1] }}" opacity="0.6">
|
||
<animateMotion dur="{{ hub[3] }}" repeatCount="indefinite" begin="{{ hub[2] }}s + 1.2s">
|
||
<mpath href="#hub-path-{{ hub[0] }}" />
|
||
</animateMotion>
|
||
</circle>
|
||
{% endfor %}
|
||
|
||
{# Animated particles — Hub → Tool (smaller, fast) #}
|
||
{% for tool in [
|
||
('word', '#0062ff', '0s'),
|
||
('google', '#0062ff', '0.4s'),
|
||
('obsidian', '#0062ff', '0.8s'),
|
||
('outlook', '#00bdd8', '0.2s'),
|
||
('teams', '#00bdd8', '0.6s'),
|
||
('notion', '#00bdd8', '1.0s'),
|
||
('zapier', '#8b5cf6', '0.1s'),
|
||
('make', '#8b5cf6', '0.5s'),
|
||
('n8n', '#8b5cf6', '0.9s')
|
||
] %}
|
||
<circle r="2.2" fill="{{ tool[1] }}" opacity="0.75">
|
||
<animateMotion dur="2s" repeatCount="indefinite" begin="{{ tool[2] }}">
|
||
<mpath href="#hub-path-{{ tool[0] }}" />
|
||
</animateMotion>
|
||
</circle>
|
||
{% endfor %}
|
||
</svg>
|
||
|
||
{# DictIA central node — absolute positioned over the SVG (z-10) #}
|
||
<div class="absolute pointer-events-none" style="left: 50%; top: 11.7%; transform: translate(-50%, -50%); z-index: 10;" aria-hidden="true">
|
||
<div class="relative w-[68px] h-[68px]">
|
||
{# Pulsing rings #}
|
||
<span class="hub-ring absolute inset-0 rounded-full border-2 border-brand-b2/40"></span>
|
||
<span class="hub-ring hub-ring-2 absolute inset-0 rounded-full border-2 border-brand-b2/40"></span>
|
||
<span class="hub-ring hub-ring-3 absolute inset-0 rounded-full border-2 border-brand-b2/40"></span>
|
||
{# Core orb #}
|
||
<span class="hub-core absolute inset-0 rounded-full grad-bg flex items-center justify-center">
|
||
<span class="font-black text-white text-[13px] tracking-tight">DictIA</span>
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
{# Hub labels overlay — positioned to match SVG hub coords (200/460 = 43.5% top, 168/900=18.7% / 450/900=50% / 732/900=81.3% left) #}
|
||
{% set hub_data = [
|
||
('Documents', 'Word · Google Docs · Obsidian', '18.7%', 'rgba(0,98,255,0.10)', 'rgba(0,98,255,0.30)', 'text-blue-300'),
|
||
('Communication', 'Outlook · Teams · Notion', '50%', 'rgba(0,189,216,0.10)', 'rgba(0,189,216,0.30)', 'text-cyan-300'),
|
||
('Automatisation', 'Zapier · Make · n8n', '81.3%', 'rgba(139,92,246,0.10)', 'rgba(139,92,246,0.30)', 'text-purple-300')
|
||
] %}
|
||
{% for name, sub, leftpos, bgcol, brdcol, txtcol in hub_data %}
|
||
<div
|
||
class="absolute pointer-events-none px-3 py-2 rounded-full backdrop-blur-sm whitespace-nowrap"
|
||
style="left: {{ leftpos }}; top: 43.5%; transform: translate(-50%, -50%); background: {{ bgcol }}; border: 1px solid {{ brdcol }};"
|
||
aria-hidden="true"
|
||
>
|
||
<p class="text-[11px] font-bold text-white leading-none">{{ name }}</p>
|
||
<p class="text-[9px] {{ txtcol }} leading-none mt-0.5 opacity-80">{{ sub }}</p>
|
||
</div>
|
||
{% endfor %}
|
||
</div>
|
||
|
||
{# Tool list — text fallback below the diagram (covers screen readers + reduces visual noise on mobile) #}
|
||
<div class="mt-12 grid sm:grid-cols-3 gap-6 max-w-3xl mx-auto" role="list" aria-label="Outils intégrés à DictIA">
|
||
{% for col_label, tools, accent in [
|
||
('Documents', [('Word', 'Export .docx instantané'), ('Google Docs', 'Sync Google Workspace'), ('Obsidian', 'Notes Markdown locales')], 'text-brand-b1'),
|
||
('Communication', [('Outlook', 'Envoi email automatique'), ('Teams', 'Canal Teams dédié'), ('Notion', 'Page Notion structurée')], 'text-brand-b2'),
|
||
('Automatisation', [('Zapier', '5 000+ apps connectées'), ('Make', 'Scénarios visuels no-code'), ('n8n', 'Workflows open-source')], 'text-purple-400')
|
||
] %}
|
||
<div role="listitem" class="bg-white/[0.03] border border-white/[0.06] p-5 rounded">
|
||
<p class="eyebrow {{ accent }} mb-3">{{ col_label | upper }}</p>
|
||
<ul class="space-y-2">
|
||
{% for tool_name, tool_desc in tools %}
|
||
<li class="text-sm">
|
||
<span class="font-semibold text-white">{{ tool_name }}</span>
|
||
<span class="text-white/70"> — {{ tool_desc | safe }}</span>
|
||
</li>
|
||
{% endfor %}
|
||
</ul>
|
||
</div>
|
||
{% endfor %}
|
||
</div>
|
||
|
||
<p class="text-center text-sm text-white/70 mt-8 max-w-2xl mx-auto">
|
||
Architecture ouverte. Tout export est aussi disponible en DOCX, SRT, VTT, JSON, TXT et MD — formats standards consommables par n'importe quel logiciel métier (gestion de dossiers, paie, CRM).
|
||
</p>
|
||
</div>
|
||
</section>
|
||
|
||
{# ===== PRICING ===== #}
|
||
<section class="bg-brand-bg py-20" id="tarifs" aria-labelledby="pricing-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">TARIFS</p>
|
||
<h2 id="pricing-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black mb-4 text-brand-navy">
|
||
Choisissez votre formule.
|
||
</h2>
|
||
<p class="text-lg text-brand-navy/70">
|
||
Tous les forfaits incluent WhisperX Large-v3, volume illimité et zéro frais par utilisateur. Prix en CAD, taxes en sus (TPS 5 % + TVQ 9,975 %).
|
||
</p>
|
||
</div>
|
||
|
||
{% include 'marketing/_partials/_pricing_tiers.html' %}
|
||
|
||
{# ROI CALCULATOR — Alpine.js, hypotheses transparentes pour LPC art. 219 hygiene #}
|
||
<div x-data="roiCalculator()" class="mt-16 max-w-3xl mx-auto bg-white p-8 rounded border border-brand-border" aria-labelledby="roi-title">
|
||
<p class="eyebrow text-center grad-text mb-2">CALCULATEUR ROI</p>
|
||
<h3 id="roi-title" class="text-2xl font-black text-center mb-6 text-brand-navy">Combien DictIA peut vous faire économiser ?</h3>
|
||
<div class="grid sm:grid-cols-3 gap-4 mb-6">
|
||
<label class="flex flex-col">
|
||
<span class="text-xs font-semibold mb-1 text-brand-navy">Utilisateurs</span>
|
||
<input type="range" x-model.number="users" min="1" max="25" step="1" class="accent-brand-b1" aria-label="Nombre d'utilisateurs">
|
||
<span class="text-sm text-brand-navy/70" x-text="users + ' utilisateur' + (users > 1 ? 's' : '')"></span>
|
||
</label>
|
||
<label class="flex flex-col">
|
||
<span class="text-xs font-semibold mb-1 text-brand-navy">Heures audio / jour</span>
|
||
<input type="range" x-model.number="hours" min="0.5" max="4" step="0.5" class="accent-brand-b1" aria-label="Heures d'audio par jour">
|
||
<span class="text-sm text-brand-navy/70" x-text="hours + ' h/jour'"></span>
|
||
</label>
|
||
<label class="flex flex-col">
|
||
<span class="text-xs font-semibold mb-1 text-brand-navy">Tarif horaire ($)</span>
|
||
<input type="range" x-model.number="rate" min="50" max="500" step="25" class="accent-brand-b1" aria-label="Tarif horaire en dollars">
|
||
<span class="text-sm text-brand-navy/70" x-text="rate + ' $/h'"></span>
|
||
</label>
|
||
</div>
|
||
<div class="text-center pt-6 border-t border-brand-border">
|
||
<p class="text-sm text-brand-navy/70 mb-2">Économies estimées par an</p>
|
||
<p class="text-5xl font-black grad-text" aria-live="polite" aria-atomic="true"
|
||
x-text="savings.toLocaleString('fr-CA') + ' $'"></p>
|
||
<p class="text-sm text-brand-navy/70 mt-2"
|
||
x-text="payback === null ? 'Payable dès la première année' : (payback < 1 ? 'Payback : moins d\'un mois' : 'Payback : ' + Math.round(payback) + ' mois')"></p>
|
||
</div>
|
||
<p class="text-xs text-brand-navy/70 mt-6 text-center">
|
||
Hypothèses : 80 % du temps de transcription manuelle économisé, 220 jours ouvrables/an, comparé à DictIA 16 (5 750 $ + 201 $/mois). Estimation à titre indicatif.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
{# ===== COMPARATIF ===== #}
|
||
<section class="bg-white py-20" aria-labelledby="comparatif-title">
|
||
<div class="max-w-[1200px] mx-auto px-6">
|
||
<div class="text-center max-w-3xl mx-auto mb-12">
|
||
<p class="eyebrow grad-text mb-4">COMPARATIF</p>
|
||
<h2 id="comparatif-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black mb-4 text-brand-navy">
|
||
DictIA face aux solutions cloud américaines.
|
||
</h2>
|
||
<p class="text-lg text-brand-navy/70">
|
||
Comparaison factuelle au 2026-04-27. Sources : politiques de confidentialité publiques + grilles tarifaires officielles. Détails sur demande : <a href="mailto:info@dictia.ca" class="grad-text font-semibold hover:underline">info@dictia.ca</a>.
|
||
</p>
|
||
</div>
|
||
|
||
<div class="overflow-x-auto rounded border border-brand-border">
|
||
<table class="w-full min-w-[720px] text-sm">
|
||
<caption class="sr-only">Comparaison DictIA, Microsoft Teams Premium, Otter.ai Business, Whisper local sur 6 critères</caption>
|
||
<thead class="bg-brand-bg">
|
||
<tr>
|
||
<th scope="col" class="text-left p-4 font-bold text-brand-navy">Critère</th>
|
||
<th scope="col" class="p-4 font-bold text-brand-navy">DictIA</th>
|
||
<th scope="col" class="p-4 font-bold text-brand-navy/70">MS Teams Premium</th>
|
||
<th scope="col" class="p-4 font-bold text-brand-navy/70">Otter.ai Business</th>
|
||
<th scope="col" class="p-4 font-bold text-brand-navy/70">Whisper local (DIY)</th>
|
||
</tr>
|
||
</thead>
|
||
{# Status SVGs — check (green), x (red), warning (amber). `aria-label` preserves the meaning for AT users. #}
|
||
{%- set svg_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 inline-block flex-shrink-0 text-brand-b3" aria-label="Conforme" role="img"><path d="M5 13l4 4L19 7"/></svg>' -%}
|
||
{%- set svg_x = '<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 inline-block flex-shrink-0 text-red-500" aria-label="Non conforme" role="img"><path d="M6 18L18 6M6 6l12 12"/></svg>' -%}
|
||
{%- set svg_warn = '<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 inline-block flex-shrink-0 text-amber-500" aria-label="Partiel" role="img"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>' -%}
|
||
<tbody class="divide-y divide-brand-border">
|
||
{% for row in [
|
||
{
|
||
'critere': 'Conforme Loi 25 sans transfert hors-Québec',
|
||
'dictia': {'status': 'check', 'text': 'Hébergement OVH Beauharnois'},
|
||
'teams': {'status': 'x', 'text': 'Soumis Cloud Act (US)'},
|
||
'otter': {'status': 'x', 'text': 'Hébergement US'},
|
||
'whisper':{'status': 'check', 'text': 'Aucun transfert (local)'}
|
||
},
|
||
{
|
||
'critere': 'Souveraineté hors Cloud Act US',
|
||
'dictia': {'status': 'check', 'text': 'Aucune exposition'},
|
||
'teams': {'status': 'x', 'text': 'Microsoft = entité US'},
|
||
'otter': {'status': 'x', 'text': 'Otter.ai Inc. = US'},
|
||
'whisper':{'status': 'check', 'text': 'Local'}
|
||
},
|
||
{
|
||
'critere': 'WhisperX Large-v3 fine-tuné FR-CA',
|
||
'dictia': {'status': 'check', 'text': 'FR-CA optimisé'},
|
||
'teams': {'status': 'warn', 'text': 'FR générique (FR-FR)'},
|
||
'otter': {'status': 'x', 'text': 'Anglais privilégié'},
|
||
'whisper':{'status': 'warn', 'text': 'FR générique de base'}
|
||
},
|
||
{
|
||
'critere': 'Diarisation jusqu\'à 8 locuteurs (pyannote)',
|
||
'dictia': {'status': 'check', 'text': 'Inclus par défaut'},
|
||
'teams': {'status': 'warn', 'text': 'Limité ~6 (Premium)'},
|
||
'otter': {'status': 'warn', 'text': 'Variable selon le forfait'},
|
||
'whisper':{'status': 'x', 'text': 'Non incluse'}
|
||
},
|
||
{
|
||
'critere': 'Coût mensuel par utilisateur',
|
||
'dictia': {'status': None, 'text': '0 $ (forfait fixe)'},
|
||
'teams': {'status': None, 'text': '~14 $ CAD (Premium)'},
|
||
'otter': {'status': None, 'text': '~20 $ US (Business)'},
|
||
'whisper':{'status': None, 'text': '0 $ (mais GPU + DevOps requis)'}
|
||
},
|
||
{
|
||
'critere': 'Audit trail intégré (Loi 25 art. 3.5)',
|
||
'dictia': {'status': 'check', 'text': 'Inclus par défaut'},
|
||
'teams': {'status': 'warn', 'text': 'Via M365 Audit séparé'},
|
||
'otter': {'status': 'warn', 'text': 'Logs basiques seulement'},
|
||
'whisper':{'status': 'x', 'text': 'À développer soi-même'}
|
||
}
|
||
] %}
|
||
{%- set status_svg = {'check': svg_check, 'x': svg_x, 'warn': svg_warn} -%}
|
||
<tr class="hover:bg-brand-bg/50 transition-colors">
|
||
<th scope="row" class="text-left p-4 font-semibold text-brand-navy/80">{{ row.critere | safe }}</th>
|
||
<td class="p-4 text-center font-semibold text-brand-navy">
|
||
<span class="inline-flex items-center gap-1.5 px-2 py-1 rounded-none bg-brand-b3/10 text-brand-navy">
|
||
{%- if row.dictia.status -%}{{ status_svg[row.dictia.status] | safe }}{%- endif -%}
|
||
<span>{{ row.dictia.text | safe }}</span>
|
||
</span>
|
||
</td>
|
||
<td class="p-4 text-center text-brand-navy/70">
|
||
<span class="inline-flex items-center gap-1.5">
|
||
{%- if row.teams.status -%}{{ status_svg[row.teams.status] | safe }}{%- endif -%}
|
||
<span>{{ row.teams.text | safe }}</span>
|
||
</span>
|
||
</td>
|
||
<td class="p-4 text-center text-brand-navy/70">
|
||
<span class="inline-flex items-center gap-1.5">
|
||
{%- if row.otter.status -%}{{ status_svg[row.otter.status] | safe }}{%- endif -%}
|
||
<span>{{ row.otter.text | safe }}</span>
|
||
</span>
|
||
</td>
|
||
<td class="p-4 text-center text-brand-navy/70">
|
||
<span class="inline-flex items-center gap-1.5">
|
||
{%- if row.whisper.status -%}{{ status_svg[row.whisper.status] | safe }}{%- endif -%}
|
||
<span>{{ row.whisper.text | safe }}</span>
|
||
</span>
|
||
</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<p class="text-xs text-brand-navy/70 mt-6 text-center max-w-3xl mx-auto">
|
||
Comparatif établi à partir de sources publiques (politiques de confidentialité, grilles tarifaires officielles, documentation produit) au 2026-04-27. Microsoft Teams Premium et Otter.ai sont des marques déposées de leurs propriétaires respectifs. DictIA n'est pas affilié à ces produits.
|
||
</p>
|
||
</div>
|
||
</section>
|
||
|
||
{# ===== CONFORMITÉ FORTERESSE ===== #}
|
||
<section class="bg-brand-navy text-white py-20 overflow-hidden relative" aria-labelledby="conformite-title">
|
||
{# Subtle decorative orb — green this time, like the Solution section #}
|
||
<div class="absolute top-1/3 left-1/4 w-[500px] h-[500px] rounded-full pointer-events-none" aria-hidden="true"
|
||
style="background: radial-gradient(circle, rgba(0,200,150,0.07) 0%, transparent 60%); filter: blur(60px);"></div>
|
||
|
||
<div class="relative 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">CONFORMITÉ — FORTERESSE QUÉBÉCOISE</p>
|
||
<h2 id="conformite-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black mb-4">
|
||
Architecture <span class="grad-text">conçue avec</span> les exigences professionnelles québécoises.
|
||
</h2>
|
||
<p class="text-lg text-white/70">
|
||
DictIA mappe son architecture aux cadres réglementaires applicables au secteur public et aux ordres professionnels du Québec. Détails techniques (EFVP, audit trail, déclaration CAI) disponibles sur demande : <a href="mailto:info@dictia.ca" class="grad-text font-semibold hover:underline">info@dictia.ca</a>.
|
||
</p>
|
||
</div>
|
||
|
||
{# 4 conformity pillars — dark cards with grad-bg icon corners (matches Solution pillars style).
|
||
Icons (heroicons-style outline): map-pin (Québec), scale (Loi 25), building-library (LGGRI), code-bracket (AGPL). #}
|
||
{%- set svg_pin = '<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 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>' -%}
|
||
{%- set svg_scale = '<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="M12 3v18"/><path d="M5 7h14"/><path d="M5 7l-2 6a4 4 0 0 0 8 0L9 7"/><path d="M19 7l2 6a4 4 0 0 1-8 0l2-6"/><path d="M8 21h8"/></svg>' -%}
|
||
{%- set svg_building = '<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="M3 21h18"/><path d="M5 21V8l7-4 7 4v13"/><path d="M9 21v-6h6v6"/><path d="M9 11h.01"/><path d="M15 11h.01"/></svg>' -%}
|
||
{%- set svg_code = '<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="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/><line x1="14" y1="4" x2="10" y2="20"/></svg>' -%}
|
||
<div class="grid md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||
{% for card in [
|
||
{
|
||
'icon': svg_pin,
|
||
'title': 'Hébergement OVH Beauharnois',
|
||
'desc': 'Centre de données opéré par OVHcloud Canada en territoire québécois. Conformité documentée selon les services (ISO 27001, SOC 2 selon le périmètre). Détails sur demande.'
|
||
},
|
||
{
|
||
'icon': svg_scale,
|
||
'title': 'Mappé Loi 25 (LPRPSP)',
|
||
'desc': 'Audit trail art. 3.5, EFVP préparée art. 3.3, registre des consentements art. 14. Modèles de déclaration CAI fournis.'
|
||
},
|
||
{
|
||
'icon': svg_building,
|
||
'title': 'Compatible Cadre IA secteur public',
|
||
'desc': 'DictIA est conçu pour s\'inscrire dans le cadre de gestion des systèmes d\'IA du secteur public québécois (LGGRI). Documentation détaillée sur demande.'
|
||
},
|
||
{
|
||
'icon': svg_code,
|
||
'title': 'Code source AGPL v3 vérifiable',
|
||
'desc': 'Architecture entièrement auditable sur <a href="https://gitea.innova-ai.ca/Innova-AI/dictia-public" target="_blank" rel="noopener" class="underline hover:text-white">Gitea public</a>. Aucune boîte noire. Vos auditeurs peuvent examiner chaque ligne.'
|
||
}
|
||
] %}
|
||
<article class="bg-white/[0.05] backdrop-blur-sm p-6 rounded border border-white/[0.08]">
|
||
<div class="text-brand-b1 mb-4" aria-hidden="true">{{ card.icon | safe }}</div>
|
||
<h3 class="text-lg font-bold mb-2 text-white">{{ card.title | safe }}</h3>
|
||
<p class="text-sm text-white/80 leading-relaxed">{{ card.desc | safe }}</p>
|
||
</article>
|
||
{% endfor %}
|
||
</div>
|
||
|
||
<div class="text-center mt-10">
|
||
<p class="text-sm text-white/70">
|
||
Lancement prévu : <strong class="text-white">printemps 2026</strong>. Pré-inscription ouverte.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
{# ===== CADRE RÉGLEMENTAIRE — Moniteur d'Interception ===== #}
|
||
{# Source canonique : InnovA-AI/Website-Sanity/components/sections/dictai-contraste.tsx (REGS + MoniteurInterception)
|
||
Animation : cycle automatique en 4 étapes (folder QC→US, alerte, HUD log, flash REGS séquentiel) + Alpine
|
||
Cartographie 6 textes : Loi 25, Loi 96, Cloud Act, Guide IA Barreau, Cadre IA MCN, CAI #}
|
||
<style>
|
||
/* Cadre — folder qui glisse de QC vers US */
|
||
.cadre-folder { transition: left 1.4s cubic-bezier(0.4,0,0.2,1), color 0.4s, filter 0.4s; }
|
||
|
||
/* Cadre — pulse halo autour du folder en alerte */
|
||
@keyframes cadre-folder-halo {
|
||
0%, 100% { transform: scale(1); opacity: 0.5; }
|
||
50% { transform: scale(1.8); opacity: 0; }
|
||
}
|
||
.cadre-halo { animation: cadre-folder-halo 1.2s ease-out infinite; }
|
||
|
||
/* Cadre — REGS row flash amber pendant le sweep */
|
||
.cadre-reg { transition: border-color 180ms, background-color 180ms; }
|
||
.cadre-reg.is-flash { border-color: rgba(245,158,11,0.50) !important; background-color: rgba(245,158,11,0.06) !important; }
|
||
.cadre-reg.is-flash .cadre-reg-label { color: #d97706 !important; }
|
||
|
||
/* Cadre — alerte clignotante footer */
|
||
@keyframes cadre-blink {
|
||
0%, 100% { opacity: 1; }
|
||
50% { opacity: 0.3; }
|
||
}
|
||
.cadre-blink { animation: cadre-blink 0.85s ease-in-out infinite; }
|
||
|
||
/* Cadre — caret HUD blink */
|
||
@keyframes cadre-caret {
|
||
0%, 100% { opacity: 1; }
|
||
50% { opacity: 0; }
|
||
}
|
||
.cadre-caret { animation: cadre-caret 0.7s ease-in-out infinite; }
|
||
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.cadre-folder, .cadre-halo, .cadre-reg, .cadre-blink, .cadre-caret {
|
||
animation: none !important; transition: none !important;
|
||
}
|
||
}
|
||
</style>
|
||
<section
|
||
class="bg-white py-20 border-b border-brand-border relative overflow-hidden"
|
||
aria-labelledby="cadre-title"
|
||
x-data="{
|
||
step: 0,
|
||
hudLines: [],
|
||
flashIdx: -1,
|
||
timers: [],
|
||
observer: null,
|
||
HUD: ['> Interception IA détectée.', '> Données utilisées pour entraînement.', '> Statut : Violation Légale.'],
|
||
runCycle() {
|
||
this.step = 0; this.hudLines = []; this.flashIdx = -1;
|
||
this.timers.push(setTimeout(() => this.step = 1, 900));
|
||
this.timers.push(setTimeout(() => this.step = 2, 2300));
|
||
this.timers.push(setTimeout(() => {
|
||
this.step = 3;
|
||
this.HUD.forEach((line, i) => {
|
||
this.timers.push(setTimeout(() => this.hudLines.push(line), i * 650));
|
||
});
|
||
}, 2800));
|
||
for (let i = 0; i < 6; i++) {
|
||
this.timers.push(setTimeout(() => this.flashIdx = i, 4700 + i * 200));
|
||
}
|
||
this.timers.push(setTimeout(() => this.flashIdx = -1, 4700 + 6 * 200 + 500));
|
||
this.timers.push(setTimeout(() => this.runCycle(), 8500));
|
||
},
|
||
init() {
|
||
this.observer = new IntersectionObserver((entries) => {
|
||
entries.forEach(e => {
|
||
if (e.isIntersecting && this.step === 0 && this.timers.length === 0) {
|
||
this.timers.push(setTimeout(() => this.runCycle(), 300));
|
||
this.observer.disconnect();
|
||
}
|
||
});
|
||
}, { rootMargin: '-100px' });
|
||
this.observer.observe($el);
|
||
}
|
||
}"
|
||
>
|
||
<div class="absolute inset-0 pointer-events-none" aria-hidden="true"
|
||
style="background-image: radial-gradient(circle, rgba(11,15,26,0.04) 1px, transparent 1px); background-size: 28px 28px;"></div>
|
||
|
||
<div class="relative max-w-[1200px] mx-auto px-6">
|
||
<div class="text-center max-w-2xl mx-auto mb-12">
|
||
<p class="eyebrow text-amber-600 mb-4">⚠ CADRE RÉGLEMENTAIRE QUÉBEC</p>
|
||
<h2 id="cadre-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black mb-4 text-brand-navy">
|
||
Ce que vos outils actuels enfreignent <span class="grad-text">en secret</span>.
|
||
</h2>
|
||
<p class="text-base text-brand-navy/70">
|
||
Six textes officiels encadrent l'usage de l'IA et la circulation des données vocales au Québec.
|
||
Visualisez en temps réel comment une transcription cloud quitte la province et déclenche les violations.
|
||
</p>
|
||
</div>
|
||
|
||
{# Carte principale — header + body 2 colonnes (animation à gauche, REGS à droite) #}
|
||
<div class="max-w-5xl mx-auto rounded border border-brand-border bg-brand-bg overflow-hidden">
|
||
|
||
{# Header — Moniteur d'Interception #}
|
||
<div class="flex items-center gap-2.5 px-5 pt-4 pb-3 border-b border-brand-border bg-white">
|
||
<span class="w-1.5 h-1.5 rounded-full shrink-0 transition-all duration-300"
|
||
:class="step >= 2 ? 'bg-amber-500 shadow-[0_0_6px_#F59E0B]' : 'bg-brand-navy/30'"
|
||
aria-hidden="true"></span>
|
||
<span class="font-medium text-[10px] uppercase tracking-[0.22em] text-brand-navy/55">
|
||
Moniteur d'Interception
|
||
</span>
|
||
<span x-show="step >= 2"
|
||
class="ml-auto font-bold text-[9px] uppercase tracking-[0.18em] text-amber-600 cadre-blink"
|
||
x-cloak>
|
||
⚠ Alerte Active
|
||
</span>
|
||
</div>
|
||
|
||
{# Body — 2 colonnes #}
|
||
<div class="flex flex-col md:flex-row">
|
||
|
||
{# LEFT — animation track (~42%) #}
|
||
<div class="relative md:w-[42%] px-5 py-5 overflow-hidden bg-brand-bg" style="min-height: 200px;">
|
||
{# Grille bg #}
|
||
<div class="absolute inset-0 pointer-events-none" aria-hidden="true"
|
||
style="background-image: linear-gradient(rgba(11,15,26,0.04) 1px, transparent 1px), linear-gradient(90deg, rgba(11,15,26,0.04) 1px, transparent 1px); background-size: 20px 20px;"></div>
|
||
|
||
{# Labels QC / US #}
|
||
<div class="relative flex items-center justify-between mb-3">
|
||
<span class="font-bold text-[9px] uppercase tracking-[0.16em] transition-colors duration-300"
|
||
:class="step >= 2 ? 'text-brand-navy/30' : 'text-brand-b3'">
|
||
QC
|
||
</span>
|
||
<span class="font-bold text-[9px] uppercase tracking-[0.16em] text-brand-navy/30">
|
||
US
|
||
</span>
|
||
</div>
|
||
|
||
{# Track #}
|
||
<div class="relative h-10">
|
||
<div class="absolute top-0 bottom-0 transition-colors duration-300"
|
||
:style="`left: 50%; width: 0; border-left: 1.5px dashed ${step >= 2 ? 'rgba(245,158,11,0.6)' : 'rgba(11,15,26,0.18)'};`"
|
||
aria-hidden="true"></div>
|
||
<div class="cadre-folder absolute top-1/2 -translate-y-1/2 -translate-x-1/2"
|
||
:style="`left: ${step === 0 ? '6%' : '54%'}`">
|
||
<span x-show="step >= 2" class="cadre-halo absolute inset-[-8px] rounded-full bg-amber-500/15" x-cloak></span>
|
||
<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="relative w-5 h-5 transition-colors duration-300"
|
||
:class="step >= 2 ? 'text-amber-500' : 'text-brand-b1'"
|
||
:style="`filter: drop-shadow(0 0 ${step >= 2 ? '6px rgba(245,158,11,0.7)' : '4px rgba(0,98,255,0.5)'})`"
|
||
aria-hidden="true">
|
||
<path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
|
||
{# HUD panel #}
|
||
<div x-show="step >= 3"
|
||
x-transition:enter="transition ease-out duration-300"
|
||
x-transition:enter-start="opacity-0 translate-y-2"
|
||
x-transition:enter-end="opacity-100 translate-y-0"
|
||
class="mt-3 rounded px-3 py-2.5 font-mono"
|
||
style="background: rgba(11,15,26,0.92); border: 1px solid rgba(245,158,11,0.30); font-size: 10px; color: #F59E0B; line-height: 1.65;"
|
||
x-cloak>
|
||
<template x-for="(line, i) in hudLines" :key="i">
|
||
<div x-html="line"></div>
|
||
</template>
|
||
<span x-show="hudLines.length < HUD.length" class="cadre-caret">▌</span>
|
||
</div>
|
||
</div>
|
||
|
||
{# RIGHT — REGS list (~58%) #}
|
||
<div class="md:w-[58%] px-5 py-5 border-t md:border-t-0 md:border-l border-brand-border bg-white">
|
||
<p class="font-semibold text-[10px] uppercase tracking-[0.18em] mb-3 text-brand-navy/45">
|
||
Ce que vos outils actuels enfreignent en secret :
|
||
</p>
|
||
<ul class="flex flex-col gap-1.5" role="list">
|
||
{% for reg in [
|
||
{'label': 'Loi 25 (P-39.1)', 'detail': 'Renseignements personnels sensibles — pénalité jusqu\'à 25 M$', 'href': 'https://www.legisquebec.gouv.qc.ca/fr/document/lc/P-39.1', 'risk': True},
|
||
{'label': 'Loi 96 (C-11)', 'detail': 'Francisation — PME 25+ employés depuis juin 2025', 'href': 'https://www.legisquebec.gouv.qc.ca/fr/document/lc/C-11', 'risk': True},
|
||
{'label': 'US Cloud Act', 'detail': 'Accès aux données hébergées hors QC par les autorités américaines', 'href': 'https://www.congress.gov/bill/115th-congress/senate-bill/2383', 'risk': True},
|
||
{'label': 'Guide IA — Barreau QC', 'detail': 'Recommande systèmes fermés déployés en interne (publié 2024)', 'href': 'https://www.barreau.qc.ca/', 'risk': False},
|
||
{'label': 'Cadre IA — MCN', 'detail': 'Gouvernance IA pour organismes publics (déc. 2025, conformité 19 juin 2026)', 'href': 'https://www.tresor.gouv.qc.ca/', 'risk': False},
|
||
{'label': 'CAI', 'detail': 'Commission d\'accès à l\'information — application active', 'href': 'https://www.cai.gouv.qc.ca/', 'risk': False}
|
||
] %}
|
||
<li role="listitem">
|
||
<a href="{{ reg.href }}" target="_blank" rel="noopener noreferrer"
|
||
class="cadre-reg group flex items-start gap-2 rounded px-2.5 py-1.5 no-underline border focus-visible:outline-2 focus-visible:outline-amber-500 focus-visible:outline-offset-2"
|
||
:class="flashIdx === {{ loop.index0 }} ? 'is-flash' : ''"
|
||
style="border-color: {{ 'rgba(239,68,68,0.20)' if reg.risk else 'rgba(0,98,255,0.15)' }};">
|
||
<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-3.5 h-3.5 mt-0.5 shrink-0"
|
||
style="color: {{ 'rgba(239,68,68,0.65)' if reg.risk else 'rgba(0,98,255,0.55)' }};"
|
||
aria-hidden="true"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
|
||
<div class="min-w-0 flex-1">
|
||
<div class="flex items-start gap-1.5 flex-wrap">
|
||
<span class="cadre-reg-label font-semibold text-[11px] leading-tight shrink-0 transition-colors"
|
||
style="color: {{ '#dc2626' if reg.risk else '#1d4ed8' }};">{{ reg.label }}</span>
|
||
<span class="text-[10px] leading-tight text-brand-navy/55">{{ reg.detail | safe }}</span>
|
||
</div>
|
||
</div>
|
||
<span class="text-[9px] shrink-0 mt-0.5 opacity-0 group-hover:opacity-60 transition-opacity text-brand-navy/70">Lire ↗</span>
|
||
</a>
|
||
</li>
|
||
{% endfor %}
|
||
</ul>
|
||
<p class="mt-3 text-right text-[9px] text-brand-navy/30">
|
||
Les textes officiels font foi. Les informations ci-dessus sont fournies à titre indicatif.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
{# Footer — verdict #}
|
||
<div class="px-5 py-3 flex items-center gap-2.5 border-t border-brand-border bg-white">
|
||
<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 transition-colors"
|
||
:class="step >= 2 ? 'text-amber-500 cadre-blink' : 'text-brand-navy/35'"
|
||
aria-hidden="true"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
|
||
<span class="font-bold text-[10px] uppercase tracking-[0.20em] transition-colors"
|
||
:class="step >= 2 ? 'text-amber-600 cadre-blink' : 'text-brand-navy/35'"
|
||
style="text-shadow: 0 0 6px rgba(245,158,11,0.20);"
|
||
aria-live="polite">
|
||
<span x-text="step >= 2 ? 'NON CONFORME — Loi 25 · Cloud Act' : 'Surveillance active...'"></span>
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
<p class="text-center text-xs text-brand-navy/55 mt-6 max-w-2xl mx-auto">
|
||
DictIA est conçu pour les secteurs réglementés du Québec — Loi 25, Cloud Act, Barreau, ChAD, AMF. Hébergement OVH Beauharnois,
|
||
code source AGPL v3 vérifiable, audit trail intégré.
|
||
</p>
|
||
</div>
|
||
</section>
|
||
|
||
{# ===== TÉMOIGNAGES (placeholder pré-lancement) ===== #}
|
||
<section class="bg-brand-bg py-20" aria-labelledby="testimonials-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">TÉMOIGNAGES</p>
|
||
<h2 id="testimonials-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black mb-4 text-brand-navy">
|
||
Premiers cabinets pilotes interviewés au printemps 2026.
|
||
</h2>
|
||
<p class="text-lg text-brand-navy/70">
|
||
Trois pilotes confidentiels en cours : un cabinet juridique, un cabinet CPA, une municipalité. Témoignages publiés ici dès l'aboutissement des entrevues, accompagnés d'une métrique vérifiable.
|
||
</p>
|
||
</div>
|
||
|
||
<div class="grid md:grid-cols-3 gap-6">
|
||
{% for t in testimonials %}
|
||
<article class="bg-white p-6 rounded border border-brand-border flex flex-col items-center text-center"
|
||
aria-label="Témoignage {{ t.placeholder_label }} à venir">
|
||
<div class="w-16 h-16 rounded-full grad-bg flex items-center justify-center mb-4 shadow-cta text-white" aria-hidden="true">
|
||
{%- if t.persona == 'avocat' -%}
|
||
<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"><path d="M12 3v18"/><path d="M5 7h14"/><path d="M5 7l-2 6a4 4 0 0 0 8 0L9 7"/><path d="M19 7l2 6a4 4 0 0 1-8 0l2-6"/><path d="M8 21h8"/></svg>
|
||
{%- elif t.persona == 'cpa' -%}
|
||
<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"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/><line x1="3" y1="20" x2="21" y2="20"/></svg>
|
||
{%- elif t.persona == 'municipal' -%}
|
||
<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"><path d="M3 21h18"/><path d="M5 21V8l7-4 7 4v13"/><path d="M9 21v-6h6v6"/><path d="M9 11h.01"/><path d="M15 11h.01"/></svg>
|
||
{%- endif -%}
|
||
</div>
|
||
<p class="text-sm font-bold text-brand-navy mb-1">{{ t.placeholder_label | safe }}</p>
|
||
<p class="text-xs text-brand-navy/70 mb-4">Témoignage à venir · {{ t.expected | safe }}</p>
|
||
<p class="text-sm text-brand-navy/70 italic">
|
||
« Citation et métrique publiées après validation par le pilote. »
|
||
</p>
|
||
</article>
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
{# ===== FAQ ===== #}
|
||
<section class="bg-white py-20" aria-labelledby="faq-title">
|
||
<div class="max-w-[820px] mx-auto px-6">
|
||
<div class="text-center mb-12">
|
||
<p class="eyebrow grad-text mb-4">FAQ</p>
|
||
<h2 id="faq-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black mb-4 text-brand-navy">
|
||
Vos questions les plus fréquentes.
|
||
</h2>
|
||
<p class="text-lg text-brand-navy/70">
|
||
Une question qui n'est pas couverte ici ? Écrivez-nous :
|
||
<a href="mailto:info@dictia.ca" class="grad-text font-semibold hover:underline">info@dictia.ca</a>.
|
||
</p>
|
||
</div>
|
||
|
||
<div class="divide-y divide-brand-border border-y border-brand-border" role="list">
|
||
{% for item in faq %}
|
||
<div x-data="{ open: false }" class="py-2" role="listitem">
|
||
<h3>
|
||
<button type="button"
|
||
class="w-full flex items-center justify-between gap-4 py-4 text-left hover:bg-brand-bg/50 transition-colors rounded-none px-2 focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
|
||
@click="open = !open"
|
||
:aria-expanded="open.toString()"
|
||
aria-controls="faq-panel-{{ loop.index }}">
|
||
<span class="font-semibold text-brand-navy text-base">{{ item.q | safe }}</span>
|
||
<span class="grad-text text-2xl flex-shrink-0 transition-transform"
|
||
:class="open ? 'rotate-45' : ''" aria-hidden="true">+</span>
|
||
</button>
|
||
</h3>
|
||
<div id="faq-panel-{{ loop.index }}"
|
||
x-show="open"
|
||
x-transition.opacity.duration.200ms>
|
||
<p class="px-2 pb-4 text-sm text-brand-navy/80 leading-relaxed">{{ item.a | safe }}</p>
|
||
</div>
|
||
</div>
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
|
||
{# Schema.org FAQPage JSON-LD for SEO/GEO — inline so it travels with this page only #}
|
||
<script type="application/ld+json">
|
||
{
|
||
"@context": "https://schema.org",
|
||
"@type": "FAQPage",
|
||
"mainEntity": [
|
||
{%- for item in faq -%}
|
||
{
|
||
"@type": "Question",
|
||
"name": {{ (item.q | striptags | replace(' ', ' '))|tojson }},
|
||
"acceptedAnswer": {
|
||
"@type": "Answer",
|
||
"text": {{ (item.a | striptags | replace(' ', ' '))|tojson }}
|
||
}
|
||
}{{ "," if not loop.last }}
|
||
{%- endfor -%}
|
||
]
|
||
}
|
||
</script>
|
||
</section>
|
||
|
||
{# ===== CTA FINAL ===== #}
|
||
<section class="relative bg-brand-navy text-white py-24 overflow-hidden" aria-labelledby="cta-title">
|
||
{# Two warm cosmic orbs to mirror the Hero — visual closure of the page #}
|
||
<div class="absolute inset-0 pointer-events-none" aria-hidden="true">
|
||
<div class="absolute top-1/4 left-1/3 w-[500px] h-[500px] rounded-full"
|
||
style="background: radial-gradient(circle, rgba(0,98,255,0.14) 0%, transparent 60%); filter: blur(50px);"></div>
|
||
<div class="absolute bottom-1/4 right-1/3 w-[450px] h-[450px] rounded-full"
|
||
style="background: radial-gradient(circle, rgba(0,200,150,0.10) 0%, transparent 60%); filter: blur(50px);"></div>
|
||
</div>
|
||
|
||
<div class="relative max-w-[820px] mx-auto px-6 text-center">
|
||
<p class="eyebrow grad-text mb-4">PRÊT ?</p>
|
||
<h2 id="cta-title" class="text-[clamp(2.25rem,4vw,3.5rem)] font-black mb-6">
|
||
Réservez votre <span class="grad-text">pré-inscription</span>.
|
||
</h2>
|
||
<p class="text-lg text-white/80 mb-8">
|
||
Lancement printemps 2026. Les premiers utilisateurs bénéficient d'une remise de bienvenue et d'un accompagnement direct par notre équipe technique. Aucun engagement.
|
||
</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 forfaits', href='#tarifs', variant='ghost', size='lg') }}
|
||
</div>
|
||
|
||
<p class="text-xs text-white/70 mt-8">
|
||
Pré-inscription par courriel jusqu'à l'ouverture de la plateforme. Inscription en ligne disponible dès le lancement.
|
||
</p>
|
||
</div>
|
||
</section>
|
||
{% endblock %}
|
||
|
||
{% block scripts %}
|
||
<script src="/static/js/roi_calculator.js" defer></script>
|
||
{% endblock %}
|