{% 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 — round 3 : reproduction fidèle dictia.ca/solutions/dictai ===== #}
{# Source : InnovA-AI/Website-Sanity/components/sections/dictai-page-content.tsx (lignes 260-518)
   Animations Framer Motion → CSS pure + Alpine.js :
     1. 3-step flow auto-cycle 1→2→3 (setInterval 1.8 s, désactivé reduced-motion)
     2. Magnetic CTA primary (mousemove → translate, max 8 px)
     3. Mouse parallax orb (mousemove window → translate, inertie via CSS transition)
     4. Shockwave on click (CSS pseudo-element, scale 0→4 + opacity 1→0)
     5. Hero title fade-in + word-staggered animation #}
<style>
  /* ── 3-step flow : auto-cycle highlight ── */
  .hero-flow-card {
    transition: transform 350ms ease-out, opacity 350ms ease-out, box-shadow 350ms ease-out, background-color 350ms ease-out;
  }
  .hero-flow-card.is-active {
    transform: scale(1.05);
    box-shadow: 0 0 22px rgba(6, 182, 212, 0.45), 0 0 44px rgba(37,99,235, 0.18);
  }
  .hero-flow-card.is-inactive { opacity: 0.45; }
  /* Animated arrow draw between cards */
  @keyframes hero-arrow-draw {
    0%   { stroke-dashoffset: 24; opacity: 0.3; }
    50%  { stroke-dashoffset: 0;  opacity: 1;   }
    100% { stroke-dashoffset: -24; opacity: 0.3; }
  }
  .hero-flow-arrow path { stroke-dasharray: 24; animation: hero-arrow-draw 1.8s ease-in-out infinite; }
  /* ── Magnetic CTA — Alpine writes :style="--mx,--my", we apply it ── */
  .hero-magnetic { transition: transform 220ms cubic-bezier(0.2, 0.8, 0.2, 1); will-change: transform; }
  .hero-magnetic:hover { transform: translate(var(--mx, 0px), var(--my, 0px)); }
  /* Pulse halo around primary CTA */
  @keyframes hero-cta-halo {
    0%, 100% { transform: scale(1);    opacity: 0.35; }
    50%      { transform: scale(1.18); opacity: 0.10; }
  }
  .hero-cta-halo { animation: hero-cta-halo 2.4s ease-in-out infinite; }
  /* ── Parallax orb — Alpine writes :style="--ox,--oy" ── */
  .hero-parallax-orb {
    transform: translate3d(var(--ox, 0px), var(--oy, 0px), 0);
    transition: transform 600ms cubic-bezier(0.2, 0.8, 0.2, 1);
    will-change: transform;
  }
  /* Slow rotating mesh ring overlay */
  @keyframes hero-orb-rotate {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
  }
  .hero-orb-ring-a { animation: hero-orb-rotate 28s linear infinite; }
  .hero-orb-ring-b { animation: hero-orb-rotate 40s linear infinite reverse; }
  /* ── Shockwave click effect ── */
  @keyframes hero-shockwave {
    0%   { transform: translate(-50%, -50%) scale(0);   opacity: 0.55; }
    100% { transform: translate(-50%, -50%) scale(4.5); opacity: 0;    }
  }
  .hero-shockwave {
    position: fixed;
    width: 30vmax;
    height: 30vmax;
    border-radius: 9999px;
    pointer-events: none;
    z-index: 9999;
    background: radial-gradient(circle, rgba(6,182,212,0.18) 0%, rgba(37,99,235,0.10) 50%, transparent 70%);
    animation: hero-shockwave 700ms cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
  }
  /* ── Word-staggered title reveal ── */
  @keyframes hero-word-rise {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
  }
  .hero-h1-word {
    display: inline-block;
    opacity: 0;
    animation: hero-word-rise 0.55s ease-out forwards;
  }
  /* ── Reduced-motion : freeze all hero animations ── */
  @media (prefers-reduced-motion: reduce) {
    .hero-flow-card, .hero-flow-arrow path, .hero-magnetic,
    .hero-cta-halo, .hero-parallax-orb, .hero-orb-ring-a, .hero-orb-ring-b,
    .hero-shockwave, .hero-h1-word {
      animation: none !important;
      transition: none !important;
    }
    .hero-flow-card.is-active   { transform: none !important; box-shadow: none !important; }
    .hero-flow-card.is-inactive { opacity: 1 !important; }
    .hero-h1-word { opacity: 1 !important; transform: none !important; }
    .hero-parallax-orb { transform: none !important; }
  }
</style>
<section
  class="relative overflow-hidden bg-brand-navy text-white py-24 md:py-32 min-h-[85vh] flex items-center"
  aria-labelledby="hero-title"
  x-data="{
    flowIdx: 0,
    flowTimer: null,
    mx: 0, my: 0,
    ox: 0, oy: 0,
    shockwaves: [],
    swId: 0,
    startFlow() {
      if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
      if (this.flowTimer) clearInterval(this.flowTimer);
      this.flowTimer = setInterval(() => { this.flowIdx = (this.flowIdx + 1) % 3 }, 1800);
    },
    onSectionMove($event) {
      if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
      const r = $event.currentTarget.getBoundingClientRect();
      const cx = r.left + r.width / 2;
      const cy = r.top + r.height / 2;
      this.ox = ($event.clientX - cx) * -0.025;
      this.oy = ($event.clientY - cy) * -0.018;
    },
    onSectionLeave() { this.ox = 0; this.oy = 0; this.mx = 0; this.my = 0; },
    onCtaMove($event) {
      if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
      const r = $event.currentTarget.getBoundingClientRect();
      const dx = $event.clientX - (r.left + r.width / 2);
      const dy = $event.clientY - (r.top + r.height / 2);
      const dist = Math.sqrt(dx*dx + dy*dy);
      const max = 110;
      if (dist < max) {
        const f = (1 - dist / max) * 0.18;
        this.mx = Math.max(-8, Math.min(8, dx * f));
        this.my = Math.max(-8, Math.min(8, dy * f));
      } else { this.mx = 0; this.my = 0; }
    },
    onCtaLeave() { this.mx = 0; this.my = 0; },
    onCtaClick($event) {
      if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
      const id = ++this.swId;
      this.shockwaves.push({ id, x: $event.clientX, y: $event.clientY });
      setTimeout(() => { this.shockwaves = this.shockwaves.filter(s => s.id !== id); }, 700);
    }
  }"
  x-init="startFlow()"
  @mousemove="onSectionMove($event)"
  @mouseleave="onSectionLeave()"
>
  {# Shockwave overlays — fixed-position ripples on CTA click #}
  <template x-for="sw in shockwaves" :key="sw.id">
    <span class="hero-shockwave" :style="`left:${sw.x}px; top:${sw.y}px;`" aria-hidden="true"></span>
  </template>

  {# Cosmic orbs background — 3 radial gradients (mauve 16%, aqua 7%, aqua 11%) + subtle grid + horizontal accent line #}
  <div class="absolute inset-0 pointer-events-none" aria-hidden="true">
    {# Orb 1 — primary mauve, 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(37,99,235,0.16) 0%, transparent 60%); filter: blur(40px);"></div>
    {# Orb 2 — aqua, mid-right #}
    <div class="absolute top-1/2 right-1/4 w-[500px] h-[500px] rounded-full"
         style="background: radial-gradient(circle, rgba(6,182,212,0.07) 0%, transparent 60%); filter: blur(40px);"></div>
    {# Orb 3 — aqua accent, bottom-left #}
    <div class="absolute bottom-1/4 left-1/3 w-[400px] h-[400px] rounded-full"
         style="background: radial-gradient(circle, rgba(6,182,212,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 mauve to aqua to transparent #}
    <div class="absolute top-1/3 left-0 right-0 h-px"
         style="background: linear-gradient(90deg, transparent, rgba(37,99,235,0.3), rgba(6,182,212,0.2), transparent);"></div>
  </div>

  {# 3D abstract orb — reacts to mouse via Alpine ox/oy → CSS variables #}
  <div
    class="hero-parallax-orb absolute right-[6%] top-[12%] pointer-events-none hidden lg:block"
    :style="`--ox:${ox}px; --oy:${oy}px;`"
    aria-hidden="true"
  >
    <div class="relative w-72 h-72">
      {# Outer ring #}
      <div class="absolute inset-0 rounded-full border border-brand-b3/15" style="transform: scale(1.35);"></div>
      {# Ambient blob #}
      <div class="absolute inset-0 rounded-full"
           style="background: radial-gradient(ellipse at 40% 40%, rgba(96,165,250,0.14) 0%, rgba(6,182,212,0.07) 50%, transparent 75%); filter: blur(20px);"></div>
      {# Rotating mesh ring A #}
      <div class="hero-orb-ring-a absolute inset-0 rounded-full border border-dashed border-white/[0.07]" style="transform: scale(1.15);"></div>
      {# Rotating mesh ring B #}
      <div class="hero-orb-ring-b absolute inset-0 rounded-full border border-white/[0.05]" style="transform: scale(0.9);"></div>
      {# Inner glow core #}
      <div class="absolute inset-[30%] rounded-full"
           style="background: radial-gradient(circle, rgba(96,165,250,0.25) 0%, rgba(6,182,212,0.08) 60%, transparent 100%);"></div>
    </div>
  </div>

  <div class="relative max-w-[1200px] mx-auto px-6 w-full">
    {# Single-column hero — texte centré (lg : aligné gauche). Le visuel canonique est le 3-step flow inline (pas de mockup app). #}
    <div class="max-w-4xl mx-auto lg:mx-0">

      {# Eyebrow / breadcrumb back-link "Toutes les solutions" — link to anchor #solutions sur landing #}
      <a href="#tarifs"
         class="inline-flex items-center gap-2 text-white/40 hover:text-white text-xs font-sans uppercase tracking-[0.18em] transition-colors mb-8 animate-tc-fade-in-up"
         style="animation-delay: 0ms; animation-fill-mode: backwards;">
        <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" aria-hidden="true"><path d="M19 12H5M12 19l-7-7 7-7"/></svg>
        Toutes les solutions
      </a>

      {# Sous-eyebrow — pillars #}
      <div class="flex flex-wrap items-center gap-x-3 gap-y-1 mb-5 animate-tc-fade-in-up" style="animation-delay: 75ms; animation-fill-mode: backwards;">
        <span class="eyebrow grad-text">
          TRANSCRIPTION IA · CONFORME LOI&nbsp;25 · QUÉBEC
        </span>
        <span class="hidden sm:block h-px bg-white/10 w-[80px]" aria-hidden="true"></span>
      </div>
      <p class="text-sm text-white/60 mb-8 animate-tc-fade-in-up" style="animation-delay: 75ms; animation-fill-mode: backwards;">
        Audio → Texte · Résumés IA · Conforme Loi&nbsp;25 &amp; ordres professionnels
      </p>

      {# Brand wordmark large — Dict + IA accent #}
      <h1 id="hero-title" class="font-black leading-[0.92] mb-6 text-white" style="font-size: clamp(3rem, 7vw, 6rem); letter-spacing: -0.025em;">
        <span class="hero-h1-word" style="animation-delay: 80ms;">Dict</span><span class="hero-h1-word grad-text" style="animation-delay: 160ms;">IA</span>
      </h1>

      {# 3-step flow inline — REMPLACE le mockup app actuel. Auto-cycle 1→2→3 toutes les 1.8s. #}
      <div
        class="flex flex-wrap items-center gap-2 mb-8 animate-tc-fade-in-up"
        style="animation-delay: 200ms; animation-fill-mode: backwards;"
        role="group"
        aria-label="Flux DictIA en 3 étapes"
      >
        {% set flow_steps = [
          ('Importez un fichier', '<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" 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>'),
          ('Texte en 2&nbsp;min', '<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" 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="8" y1="13" x2="16" y2="13"/><line x1="8" y1="17" x2="13" y2="17"/></svg>'),
          ('Résumé + actions', '<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" aria-hidden="true"><path d="M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5z"/><path d="M5 19l1.5-1.5"/><path d="M19 19l-1.5-1.5"/></svg>')
        ] %}
        {% for label, icon in flow_steps %}
        <span
          class="hero-flow-card inline-flex items-center gap-1.5 border border-white/10 bg-white/[0.04] rounded-full px-3.5 py-1.5 text-[12px] font-medium text-white/70"
          :class="flowIdx === {{ loop.index0 }} ? 'is-active grad-bg !text-white !border-transparent' : 'is-inactive'"
          aria-label="Étape {{ loop.index }} sur 3 : {{ label | striptags }}"
        >
          <span aria-hidden="true">{{ icon | safe }}</span>
          <span>{{ label | safe }}</span>
        </span>
        {% if not loop.last %}
        <svg class="hero-flow-arrow w-5 h-5 text-white/40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
          <path d="M5 12h14M13 6l6 6-6 6"/>
        </svg>
        {% endif %}
        {% endfor %}
      </div>

      {# H2 (canonique : phrase clé en cyan/grad) #}
      <p class="text-xl md:text-2xl lg:text-3xl font-black mb-6 leading-snug grad-text animate-tc-fade-in-up" style="animation-delay: 280ms; animation-fill-mode: backwards;">
        Transcription IA locale en 2&nbsp;minutes — Audio → Texte · Résumés IA · Conforme Loi&nbsp;25 &amp; ordres professionnels
      </p>

      {# Sub canonique #}
      <p class="text-base md:text-lg text-white/65 max-w-3xl leading-relaxed mb-10 animate-tc-fade-in-up" style="animation-delay: 360ms; animation-fill-mode: backwards;">
        DictIA transforme vos réunions en texte, résumés et points d'action en 2&nbsp;minutes — hébergé au Québec sur OVH&nbsp;Beauharnois, zéro Cloud Act. Contrairement à Teams Copilot ou Otter.ai, vos données ne quittent jamais le Québec. Conforme au Cadre&nbsp;IA MCN et aux 5&nbsp;ordres à directives IA formelles (Barreau, ChAD, CMQ, OIIQ, OACIQ).
      </p>

      {# Stats grid — 4 colonnes #}
      <div class="grid grid-cols-2 sm:grid-cols-4 gap-3 mb-10 max-w-3xl animate-tc-fade-in-up" style="animation-delay: 440ms; animation-fill-mode: backwards;">
        {% for stat in [
          ('~2&nbsp;min',  'Pour 1&nbsp;h d\'audio'),
          ('5&nbsp;ordres','Directives IA formelles'),
          ('95&nbsp;%+',   'Précision FR-CA'),
          ('0&nbsp;$',     'Frais par utilisateur')
        ] %}
        <div class="bg-white/[0.04] border border-white/10 rounded px-4 py-3 text-center">
          <div class="font-display font-black grad-text text-xl leading-none mb-1">{{ stat[0] | safe }}</div>
          <div class="text-[10.5px] text-white/55 uppercase tracking-wider leading-tight">{{ stat[1] | safe }}</div>
        </div>
        {% endfor %}
      </div>

      {# Dual CTA — primary "Réserver une démo" magnétique + ghost "Voir les forfaits" #}
      <div class="flex flex-col sm:flex-row gap-3 animate-tc-fade-in-up" style="animation-delay: 520ms; animation-fill-mode: backwards;">
        {# Magnetic CTA wrapper — Alpine writes mx/my via mousemove #}
        <span class="relative inline-flex">
          {# Pulse halo behind the primary CTA #}
          <span class="hero-cta-halo absolute -inset-1 rounded pointer-events-none"
                style="background: radial-gradient(ellipse, rgba(96,165,250,0.50) 0%, transparent 70%);"
                aria-hidden="true"></span>
          <a
            href="/contact"
            @mousemove="onCtaMove($event)"
            @mouseleave="onCtaLeave()"
            @click="onCtaClick($event)"
            class="hero-magnetic relative inline-flex items-center justify-center gap-2 bg-gradient-to-r from-brand-b3 to-brand-b1 hover:from-brand-b1 hover:to-brand-b3 text-brand-navy font-bold px-8 h-12 text-sm rounded transition-colors w-full sm:w-auto focus-visible:outline-2 focus-visible:outline-white focus-visible:outline-offset-2"
            :style="`--mx:${mx}px; --my:${my}px;`"
          >
            <span>Réserver une démo</span>
            <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" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
          </a>
        </span>
        <a
          href="/tarifs"
          class="inline-flex items-center justify-center gap-2 border border-white/15 hover:border-white/30 text-white font-semibold px-8 h-12 text-sm rounded transition-colors w-full sm:w-auto focus-visible:outline-2 focus-visible:outline-white focus-visible:outline-offset-2"
        >
          <span>Voir les forfaits</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-4 h-4" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg>
        </a>
      </div>

      {# Social proof microcopy — defensible: 9 ordres pros + waitlist + launch date (préservé pour SEO/legal) #}
      <p class="mt-8 text-sm text-white/70 flex flex-wrap items-center gap-x-2 gap-y-1 animate-tc-fade-in-up" style="animation-delay: 600ms; 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>

  </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&nbsp;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&nbsp;%+', 'précision FR-CA', 'WhisperX Large-v3 — test interne 2026-Q1'),
        ('0&nbsp;$', 'frais par utilisateur', 'Modèle par serveur, volume illimité'),
        ('100&nbsp;%', '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&nbsp;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&nbsp;M$ ou 4&nbsp;% 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&nbsp;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.&nbsp;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&nbsp;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
   Round 5 cinématique PRO : palette brand uniformisée (blue/cyan/fuchsia, zéro vert)
   + connecting beam progressive 0→33→66→100 + spotlight active column + USA map silhouette col 2
   + Quebec outline col 3 + halo multi-couches blue+cyan + screen shake + 12 paquets data flying
   + grad-text counters + chips contextuels + phase delays cinématiques 400/1100/2000/3100ms #}
<style>
  /* === ROUND 5 — Cycle background ambiance (vignette + grid + orbes) === */
  .cycle-section-bg {
    background:
      radial-gradient(ellipse 60% 40% at 12% 0%,   rgba(37,99,235,0.045) 0%, transparent 70%),
      radial-gradient(ellipse 60% 40% at 88% 100%, rgba(6,182,212,0.045) 0%, transparent 70%);
  }
  .cycle-grid-bg {
    background-image:
      linear-gradient(rgba(11,15,26,0.025) 1px, transparent 1px),
      linear-gradient(90deg, rgba(11,15,26,0.025) 1px, transparent 1px);
    background-size: 40px 40px;
  }
  @keyframes cycle-orb-float {
    0%, 100% { transform: translate(0,0)     scale(1); }
    50%      { transform: translate(8px,-12px) scale(1.04); }
  }
  .cycle-orb { animation: cycle-orb-float 8s ease-in-out infinite; }
  .cycle-orb-2 { animation-delay: 2.5s; animation-duration: 10s; }

  /* === ROUND 5 — Connecting horizontal beam progressive 0→33→66→100 === */
  .cycle-beam {
    height: 2px;
    background: linear-gradient(90deg,
      rgba(148,163,184,0.55) 0%,
      rgba(148,163,184,0.55) 33%,
      rgba(239,68,68,0.55)   33%,
      rgba(239,68,68,0.55)   66%,
      rgba(6,182,212,0.85)   66%,
      rgba(37,99,235,0.85)   100%);
    width: var(--beam, 0%);
    transition: width 800ms cubic-bezier(0.34, 1.56, 0.64, 1);
    box-shadow: 0 0 8px rgba(37,99,235,0.25);
  }
  /* Loading dot qui suit la beam */
  @keyframes cycle-beam-dot {
    0%   { left: 4%;  background: rgba(148,163,184,1); }
    33%  { left: 33%; background: rgba(148,163,184,1); }
    50%  { left: 50%; background: rgba(239,68,68,1); }
    66%  { left: 66%; background: rgba(239,68,68,1); }
    100% { left: 96%; background: rgba(6,182,212,1); }
  }
  .cycle-beam-dot {
    width: 6px; height: 6px; border-radius: 9999px;
    top: 50%; transform: translate(-50%,-50%);
    box-shadow: 0 0 10px currentColor;
    animation: cycle-beam-dot 4s ease-in-out 0.4s 1 forwards;
  }

  /* === ROUND 5 — Spotlight active column === */
  .cycle-col-card {
    transition: opacity 600ms cubic-bezier(0.34, 1.56, 0.64, 1),
                transform 600ms cubic-bezier(0.34, 1.56, 0.64, 1);
    opacity: 0.65;
  }
  .cycle-col-card.is-active   { opacity: 1; transform: scale(1.015); }
  .cycle-col-card.is-revealed { opacity: 1; }

  /* === Cycle pulse rings — 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; }

  /* Live red dot — pulse plus marqué pour signal "réunion en cours" */
  @keyframes cycle-live-dot {
    0%, 100% { opacity: 1;   box-shadow: 0 0 0 0    rgba(239,68,68,0.55); }
    50%      { opacity: 0.6; box-shadow: 0 0 0 5px  rgba(239,68,68,0);    }
  }
  .cycle-live-dot { animation: cycle-live-dot 1.4s ease-in-out infinite; }

  /* === ROUND 5 — Cycle col 3 (DictIA) — halo multi-couches blue+cyan (PALETTE BRAND) === */
  @keyframes cycle-conforme-glow {
    0%, 100% { box-shadow: 0 0 0 0    rgba(37,99,235,0.20),  0 0 0 0    rgba(6,182,212,0.12),  0 0 0 0    rgba(192,38,211,0.06); }
    50%      { box-shadow: 0 0 36px 3px rgba(37,99,235,0.45), 0 0 64px 6px rgba(6,182,212,0.20), 0 0 96px 12px rgba(192,38,211,0.10); }
  }
  .cycle-card-dictia.is-visible { animation: cycle-conforme-glow 3.4s ease-in-out infinite; will-change: box-shadow; }
  .cycle-card-dictia { transition: transform 400ms ease-out; will-change: transform; }
  .cycle-card-dictia.is-visible:hover { transform: translateY(-3px) scale(1.03); }

  /* Cycle col 3 — anneaux concentriques autour du Shield (multi-couches drawn) */
  @keyframes cycle-ring-out {
    0%, 100% { transform: scale(1);    opacity: 0.55; }
    50%      { transform: scale(1.08); opacity: 0.20; }
  }
  .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; }

  /* Ring SVG drawn line cycling (round 5) */
  @keyframes cycle-ring-draw {
    0%   { stroke-dashoffset: 220; }
    100% { stroke-dashoffset: 0; }
  }
  .cycle-ring-draw-svg circle {
    stroke-dasharray: 220;
    stroke-dashoffset: 220;
    transform-origin: center;
    transform: rotate(-90deg);
  }
  .cycle-ring-draw-svg.is-visible circle { animation: cycle-ring-draw 4s linear infinite; }

  /* Cycle SVG lignes de connexion — drawn via stroke-dashoffset, dash flow continu */
  .cycle-line { stroke-dasharray: 1.2 0.9; stroke-dashoffset: 50; transition: stroke-dashoffset 600ms ease-out; }
  .cycle-line.is-visible { stroke-dashoffset: 0; }
  @keyframes cycle-dash-flow { to { stroke-dashoffset: -42; } }
  .cycle-line.is-visible.cycle-line-flow { animation: cycle-dash-flow 12s linear infinite; }

  /* Cycle phase reveal */
  .cycle-reveal { opacity: 0; transform: translateX(14px); transition: opacity 380ms cubic-bezier(0.34, 1.56, 0.64, 1), transform 380ms cubic-bezier(0.34, 1.56, 0.64, 1); }
  .cycle-reveal.is-visible { opacity: 1; transform: translateX(0); }
  .cycle-reveal-up { opacity: 0; transform: translateY(10px); transition: opacity 500ms cubic-bezier(0.34, 1.56, 0.64, 1), transform 500ms cubic-bezier(0.34, 1.56, 0.64, 1); }
  .cycle-reveal-up.is-visible { opacity: 1; transform: translateY(0); }

  /* === ROUND 5 — Col 1 — Stack papiers stagger reveal === */
  @keyframes cycle-paper-in {
    0%   { opacity: 0; transform: translateY(8px) rotate(var(--rot, 0deg)); }
    100% { opacity: 1; transform: translateY(0)   rotate(var(--rot, 0deg)); }
  }
  .cycle-paper-stack.is-active .cycle-paper {
    animation: cycle-paper-in 400ms ease-out forwards;
    opacity: 0;
  }

  /* Cycle horloge rotation (col 1) — accélérée 1 tour / 2.5s + motion blur subtle */
  @keyframes cycle-clock-spin { to { transform: rotate(360deg); } }
  .cycle-clock { animation: cycle-clock-spin 2.5s linear infinite; transform-origin: center; display: inline-block; will-change: transform; }

  /* === ROUND 5 — Col 2 — Data leak particles AMÉLIORÉES (12 paquets vers USA top-right) === */
  @keyframes cycle-leak {
    0%   { transform: translate(0,0)   rotate(var(--rot, 0deg)) scale(0.85); opacity: 0; }
    18%  { opacity: 0.9; }
    100% { transform: translate(var(--lx, 60px), var(--ly, -80px)) rotate(var(--rot, 0deg)) scale(0.35); opacity: 0; }
  }
  .cycle-leak-particle { animation: cycle-leak 2.2s ease-out infinite; will-change: transform, opacity; }

  /* Cycle col 2 — server rack LED pulse */
  @keyframes cycle-led-pulse {
    0%, 100% { opacity: 0.4; }
    50%      { opacity: 1; box-shadow: 0 0 6px currentColor; }
  }
  .cycle-led { animation: cycle-led-pulse 1.2s ease-in-out infinite; }
  .cycle-led-2 { animation-delay: 0.3s; }
  .cycle-led-3 { animation-delay: 0.6s; }

  /* Warning chevrons slide */
  @keyframes cycle-chev-slide {
    0%, 100% { transform: translateX(0);   opacity: 0.4; }
    50%      { transform: translateX(-6px); opacity: 1; }
  }
  .cycle-chev { animation: cycle-chev-slide 1.4s ease-in-out infinite; }
  .cycle-chev-2 { animation-delay: 0.2s; }
  .cycle-chev-3 { animation-delay: 0.4s; }

  /* Cycle col 2 — STAMP NON CONFORME impact (overshoot + screen shake + flash red) */
  @keyframes cycle-stamp-impact {
    0%   { transform: translate(-50%,-50%) rotate(-25deg) scale(3); opacity: 0; filter: blur(3px); }
    55%  { transform: translate(-50%,-50%) rotate(-9deg)  scale(0.90); opacity: 1; filter: blur(0); }
    70%  { transform: translate(-50%,-50%) rotate(-6deg)  scale(1.08); }
    100% { transform: translate(-50%,-50%) rotate(-8deg)  scale(1); opacity: 1; }
  }
  .cycle-stamp.is-visible { animation: cycle-stamp-impact 700ms cubic-bezier(0.34, 1.56, 0.64, 1) forwards; will-change: transform, opacity; }

  /* Screen shake on stamp impact */
  @keyframes cycle-shake {
    0%, 100% { transform: translate(0,0); }
    20%  { transform: translate(-3px, 2px); }
    40%  { transform: translate(4px, -2px); }
    60%  { transform: translate(-2px, 3px); }
    80%  { transform: translate(3px, -1px); }
  }
  .cycle-col-shake.is-visible { animation: cycle-shake 320ms ease-out 480ms 1; }

  /* Cycle col 2 — flash background rouge à l'impact stamp (amplifié) */
  @keyframes cycle-flash-red {
    0%   { background-color: rgba(239,68,68,0); }
    30%  { background-color: rgba(239,68,68,0.22); }
    100% { background-color: rgba(239,68,68,0); }
  }
  .cycle-col-flash.is-visible { animation: cycle-flash-red 700ms ease-out 480ms forwards; }

  /* Cycle col 2 — sound icon pulse */
  @keyframes cycle-alert-pulse {
    0%, 100% { opacity: 0.7; transform: scale(1); }
    50%      { opacity: 1;   transform: scale(1.2); }
  }
  .cycle-alert-icon { animation: cycle-alert-pulse 0.9s ease-in-out infinite; }

  /* === ROUND 5 — Col 3 — checkmark draw CYAN (au lieu de vert) === */
  .cycle-check-svg path { stroke-dasharray: 24; stroke-dashoffset: 24; transition: stroke-dashoffset 400ms ease-out 220ms; stroke: #06b6d4; stroke-width: 3.5; }
  .cycle-check-svg.is-visible path { stroke-dashoffset: 0; }

  /* === ROUND 5 — Col 3 — badge "Loi 25 conforme" pulse BLUE+CYAN (palette brand) === */
  @keyframes cycle-badge-pulse {
    0%, 100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(37,99,235,0.45); }
    50%      { transform: scale(1.04); box-shadow: 0 0 0 7px rgba(37,99,235,0); }
  }
  .cycle-conforme-badge.is-visible { animation: cycle-badge-pulse 2.4s ease-in-out infinite 600ms; }

  /* === ROUND 5 — Cycle "Économies annuelles" cards — hover lift + glow BRAND BLUE === */
  .cycle-savings-card {
    transition: transform 240ms cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 240ms ease-out, border-color 240ms ease-out;
  }
  .cycle-savings-card:hover {
    transform: translateY(-3px);
    box-shadow: 0 12px 28px -8px rgba(37,99,235,0.30), 0 6px 14px -4px rgba(11,15,26,0.08);
    border-color: rgba(37,99,235,0.45);
  }
  /* Save chip subtle pulse */
  @keyframes cycle-save-chip {
    0%, 100% { opacity: 0.85; }
    50%      { opacity: 1; }
  }
  .cycle-save-chip { animation: cycle-save-chip 2.5s ease-in-out infinite; }

  /* === ROUND 5 — Phase 4 zoom-out subtle (suggère "all options revealed") === */
  .cycle-grid-zoom { transition: transform 700ms ease-out; transform: scale(1.02); }
  .cycle-grid-zoom.is-revealed { transform: scale(1); }

  /* Mobile — désactiver fuites particules + glow heavy + screen shake */
  @media (max-width: 768px) {
    .cycle-leak-particle, .cycle-orb, .cycle-orb-2 { display: none; }
    .cycle-card-dictia.is-visible { animation: none; }
    .cycle-col-shake.is-visible, .cycle-col-flash.is-visible { animation: none; }
    .cycle-ring-draw-svg.is-visible circle { animation: none; }
    .cycle-col-card { opacity: 1 !important; transform: none !important; }
  }

  /* Reduced motion — TOUT figé (mode statique) */
  @media (prefers-reduced-motion: reduce) {
    .cycle-pulse, .cycle-card-dictia, .cycle-ring-outer, .cycle-ring-inner,
    .cycle-clock, .cycle-leak-particle, .cycle-live-dot, .cycle-conforme-badge,
    .cycle-line.cycle-line-flow, .cycle-stamp, .cycle-col-flash, .cycle-col-shake,
    .cycle-led, .cycle-chev, .cycle-alert-icon, .cycle-orb, .cycle-orb-2,
    .cycle-save-chip, .cycle-paper-stack.is-active .cycle-paper,
    .cycle-ring-draw-svg.is-visible circle, .cycle-beam-dot { animation: none !important; }
    .cycle-paper-stack .cycle-paper { opacity: 1 !important; }
    .cycle-reveal, .cycle-reveal-up { opacity: 1 !important; transform: none !important; }
    .cycle-line { stroke-dashoffset: 0 !important; }
    .cycle-check-svg path { stroke-dashoffset: 0 !important; }
    .cycle-savings-card { transition: none !important; }
    .cycle-col-card { opacity: 1 !important; transform: none !important; transition: none !important; }
    .cycle-beam { width: 100% !important; transition: none !important; }
    .cycle-grid-zoom { transform: none !important; transition: none !important; }
  }
</style>
<section
  class="cycle-section-bg bg-white py-20 border-y border-brand-border relative overflow-hidden"
  aria-labelledby="cycle-title"
  x-data="{
    phase: 0,
    observer: null,
    priceHumain: 0,
    sav1: 0, sav2: 0, sav3: 0,
    /* easeOutCubic counter helper */
    countTo(prop, target, duration) {
      if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) { this[prop] = target; return; }
      const start = performance.now();
      const tick = (now) => {
        const t = Math.min(1, (now - start) / duration);
        const eased = 1 - Math.pow(1 - t, 3);
        this[prop] = Math.round(target * eased);
        if (t < 1) requestAnimationFrame(tick);
      };
      requestAnimationFrame(tick);
    },
    fmt(n) { return n.toLocaleString('fr-CA').replace(/ /g, ' '); },
    /* Round 5 — beam progressive % par phase */
    get beamPct() {
      if (this.phase >= 4) return 100;
      if (this.phase >= 3) return 66;
      if (this.phase >= 2) return 33;
      return 0;
    }
  }"
  x-init="
    observer = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting && phase === 0) {
          /* Round 5 — phase delays cinématiques 400/1100/2000/3100ms */
          setTimeout(() => { phase = 1; }, 400);
          setTimeout(() => { phase = 2; countTo('priceHumain', 315, 1400); }, 1100);
          setTimeout(() => phase = 3, 2000);
          setTimeout(() => {
            phase = 4;
            /* Savings counters fire 700ms after col 3 reveal (round 5) */
            setTimeout(() => {
              countTo('sav1', 3924, 1500);
              countTo('sav2', 6924, 1500);
              countTo('sav3', 2004, 1500);
            }, 700);
          }, 3100);
          observer.disconnect();
        }
      });
    }, { rootMargin: '-60px' });
    observer.observe($el);
  "
>
  {# Round 5 — Subtle grid pattern bg + dot grid overlay #}
  <div class="cycle-grid-bg absolute inset-0 pointer-events-none" aria-hidden="true"></div>
  <div class="absolute inset-0 pointer-events-none opacity-50" aria-hidden="true"
       style="background-image: radial-gradient(circle, rgba(11,15,26,0.04) 1px, transparent 1px); background-size: 28px 28px;"></div>

  {# Round 5 — Decorative orbs ambiance #}
  <div class="cycle-orb absolute -top-20 -left-20 w-[360px] h-[360px] rounded-full pointer-events-none" aria-hidden="true"
       style="background: radial-gradient(circle, rgba(37,99,235,0.10) 0%, transparent 65%); filter: blur(40px);"></div>
  <div class="cycle-orb cycle-orb-2 absolute -bottom-24 -right-24 w-[420px] h-[420px] rounded-full pointer-events-none" aria-hidden="true"
       style="background: radial-gradient(circle, rgba(6,182,212,0.08) 0%, transparent 65%); filter: blur(50px);"></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 inline-flex items-center gap-1.5">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" class="w-3.5 h-3.5" 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>
        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&nbsp;25, le Cloud Act américain et le Guide IA du Barreau du Québec délimitent vos options&nbsp;—
        <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>
          <span class="cycle-live-dot inline-block w-1.5 h-1.5 rounded-full bg-red-500 shrink-0" aria-hidden="true"></span>
          <span class="font-mono font-bold text-[8px] tracking-[0.22em] uppercase text-red-500/85">Live</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 cycle-line-flow" :class="phase >= 1 ? 'is-visible' : ''"
                x1="50" y1="0" x2="14" y2="10"
                stroke="rgba(148,163,184,0.55)" stroke-width="0.3" />
          <line class="cycle-line cycle-line-flow" :class="phase >= 1 ? 'is-visible' : ''"
                x1="50" y1="0" x2="50" y2="10"
                stroke="rgba(239,68,68,0.55)" stroke-width="0.3"
                style="transition-delay: 80ms; animation-delay: 0.4s;" />
          <line class="cycle-line cycle-line-flow" :class="phase >= 1 ? 'is-visible' : ''"
                x1="50" y1="0" x2="86" y2="10"
                stroke="rgba(6,182,212,0.7)" stroke-width="0.3"
                style="transition-delay: 160ms; animation-delay: 0.8s;" />
        </svg>
      </div>

      {# Round 5 — Connecting horizontal beam progressive 0->33->66->100 #}
      <div class="relative h-3 mb-4" aria-hidden="true">
        <div class="absolute inset-x-0 top-1/2 -translate-y-1/2 h-[2px] bg-brand-border/60"></div>
        <div class="cycle-beam absolute top-1/2 left-0 -translate-y-1/2 rounded-full"
             :style="`--beam: ${beamPct}%`"></div>
        <template x-if="phase >= 1">
          <div class="cycle-beam-dot absolute"></div>
        </template>
      </div>

      {# Grille 3 colonnes — équivalence du grid-cols-[2fr_2fr_3fr] desktop, avec spotlight active #}
      <div class="cycle-grid-zoom grid grid-cols-1 md:grid-cols-[2fr_2fr_3fr] gap-3 items-stretch"
           :class="phase >= 4 ? 'is-revealed' : ''">

        {# COL 1 — Retranscription humaine (sténographe) #}
        <div class="cycle-col-card cycle-reveal-up flex flex-col rounded border border-brand-border bg-brand-bg overflow-hidden relative"
             :class="{ 'is-visible': phase >= 2, 'is-revealed': phase >= 4, 'is-active': phase === 2 }">
          {# Subtle "cahier" lines bg #}
          <div class="absolute inset-0 pointer-events-none opacity-[0.04]" aria-hidden="true"
               style="background-image: linear-gradient(rgba(11,15,26,1) 1px, transparent 1px); background-size: 100% 18px;"></div>
          <div class="relative 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="relative flex-1 flex flex-col items-center justify-center px-5 py-7 gap-6">
            {# Stack de papiers (round 5 : stagger reveal stagger 180ms) #}
            <div class="cycle-paper-stack relative w-[100px] h-[90px]"
                 :class="phase >= 2 ? 'is-active' : ''"
                 aria-hidden="true">
              {% for offset in [0,1,2,3,4] %}
              <div class="cycle-paper absolute left-0 right-0 h-[17px] rounded-sm flex items-center px-2 gap-1.5 bg-white border border-brand-border shadow-sm"
                   style="bottom: {{ offset * 15 }}px; --rot: {{ '1deg' if offset is even else '-1deg' }}; transform: rotate({{ '1deg' if offset is even else '-1deg' }}); animation-delay: {{ offset * 180 }}ms;">
                <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&nbsp;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&nbsp;$/h</span>
              </div>
            </div>
          </div>
          <div class="relative 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 tabular-nums" x-text="priceHumain">315</span>
              <span class="text-xs text-brand-navy/45">$&nbsp;/&nbsp;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 (DRAMATIC : USA map + 12 paquets + screen shake) #}
        <div class="cycle-col-card cycle-reveal-up cycle-col-flash cycle-col-shake relative flex flex-col rounded border border-red-200 bg-red-50/30 overflow-hidden"
             :class="{ 'is-visible': phase >= 3, 'is-revealed': phase >= 4, 'is-active': phase === 3 }"
             style="transition-delay: 120ms;">
          {# Round 5 — USA map silhouette subtle background #}
          <svg class="absolute pointer-events-none" aria-hidden="true"
               style="top: 22%; right: 8%; width: 110px; height: 70px; opacity: 0.55;"
               viewBox="0 0 110 70" preserveAspectRatio="xMidYMid meet">
            <path d="M5,25 L8,18 L18,15 L32,12 L48,10 L65,11 L82,14 L92,18 L102,22 L105,28 L100,35 L95,42 L88,48 L78,52 L68,55 L58,57 L48,58 L38,57 L28,55 L18,52 L10,45 L6,38 Z"
                  fill="rgba(239,68,68,0.05)" stroke="rgba(239,68,68,0.20)" stroke-width="0.8"/>
            <circle cx="78" cy="32" r="2.2" fill="rgba(239,68,68,0.55)"/>
            <circle cx="78" cy="32" r="4.5" fill="none" stroke="rgba(239,68,68,0.35)" stroke-width="0.6"/>
          </svg>

          {# Overlay légal NON CONFORME (phase 3) — STAMP huissier amplifié round 5 #}
          <div class="absolute inset-0 z-30 flex flex-col items-center justify-center pointer-events-none"
               :class="phase >= 3 ? 'opacity-100' : 'opacity-0'"
               style="transition: opacity 220ms ease-out; backdrop-filter: blur(6px); background: rgba(255,255,255,0.78);">
            <div class="cycle-stamp absolute top-1/2 left-1/2 flex flex-col items-center gap-3 px-7 py-6 rounded bg-white border-[3px] border-red-500 shadow-[0_12px_40px_-6px_rgba(239,68,68,0.65)]"
                 :class="phase >= 3 ? 'is-visible' : ''"
                 style="transform: translate(-50%,-50%) scale(0); opacity: 0;">
              <div class="flex items-center gap-2.5">
                <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-8 h-8 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>
                <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="cycle-alert-icon w-5 h-5 text-red-500" aria-hidden="true"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><line x1="23" y1="9" x2="17" y2="15"/><line x1="17" y1="9" x2="23" y2="15"/></svg>
              </div>
              <div class="text-center">
                <div class="font-mono font-black tracking-[0.16em] text-2xl uppercase text-red-600 leading-none">NON CONFORME</div>
                <div class="font-mono text-[10px] tracking-[0.20em] uppercase mt-2 text-red-500/70">Loi&nbsp;25 · Cloud Act américain</div>
              </div>
            </div>
          </div>

          <div class="relative 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">
            {# Server rack icon (round 5) — 3 stacked rectangles avec leds rouges #}
            <div class="relative flex flex-col items-center gap-2">
              <div class="relative w-16 h-14 rounded-sm flex flex-col items-center justify-center gap-[3px] bg-red-100/60 border border-red-200 px-2 py-1.5" aria-hidden="true">
                {% for rack_i in [0,1,2] %}
                <div class="w-full h-2.5 rounded-[2px] bg-red-50/80 border border-red-200/70 flex items-center px-1 gap-1">
                  <span class="cycle-led{% if rack_i > 0 %} cycle-led-{{ rack_i + 1 }}{% endif %} w-1 h-1 rounded-full bg-red-500"></span>
                  <span class="cycle-led cycle-led-{{ ((rack_i + 1) % 3) + 1 }} w-1 h-1 rounded-full bg-red-500"></span>
                  <span class="flex-1 h-[1px] rounded-full bg-red-300/60"></span>
                  <span class="cycle-led cycle-led-{{ ((rack_i + 2) % 3) + 1 }} w-1 h-1 rounded-full bg-red-500"></span>
                </div>
                {% endfor %}

                {# Round 5 — 12 paquets data .wav/.aac qui s'envolent vers TOP-RIGHT (USA direction) #}
                {% for i in range(12) %}
                <span class="cycle-leak-particle absolute pointer-events-none flex items-center justify-center font-mono font-bold uppercase text-white text-[6px] rounded-sm"
                      style="left: {{ 25 + (i % 4) * 12 }}%; top: {{ 30 + (i % 3) * 18 }}%;
                             width: 18px; height: 9px;
                             background: rgba(239,68,68,0.65); border: 1px solid rgba(239,68,68,0.85);
                             box-shadow: 0 0 4px rgba(239,68,68,0.55);
                             --lx: {{ 50 + i*6 }}px; --ly: -{{ 70 + (i % 4) * 15 }}px;
                             --rot: {{ -8 + (i % 5) * 4 }}deg;
                             animation-delay: {{ i * 0.18 }}s;">{{ '.wav' if i is even else '.aac' }}</span>
                {% endfor %}
              </div>
              <div class="px-2 py-0.5 rounded bg-red-50 border border-red-100 inline-flex items-center gap-1">
                <span class="cycle-chev font-mono font-bold text-[8px] text-red-500/70">&lt;</span>
                <span class="cycle-chev cycle-chev-2 font-mono font-bold text-[8px] text-red-500/70">&lt;</span>
                <span class="cycle-chev cycle-chev-3 font-mono font-bold text-[8px] text-red-500/70">&lt;</span>
                <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&ndash;750&nbsp;$/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="relative 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) — PALETTE BRAND BLUE+CYAN+FUCHSIA #}
        <div class="cycle-col-card cycle-card-dictia cycle-reveal-up relative flex flex-col rounded border border-brand-b1/40 bg-gradient-to-br from-brand-b1/[0.07] via-brand-b2/[0.04] to-brand-b3/[0.04] overflow-hidden"
             :class="{ 'is-visible': phase >= 4, 'is-revealed': phase >= 4, 'is-active': phase >= 4 }"
             style="transition-delay: 240ms;">
          {# Halo ambiant blue->cyan->fuchsia #}
          <div class="absolute inset-0 pointer-events-none" aria-hidden="true"
               style="background: radial-gradient(ellipse 80% 35% at 50% 0%, rgba(6,182,212,0.18) 0%, transparent 65%), radial-gradient(ellipse 60% 50% at 50% 100%, rgba(37,99,235,0.10) 0%, transparent 70%);"></div>

          {# Round 5 — Quebec province outline subtle background #}
          <svg class="absolute pointer-events-none" aria-hidden="true"
               style="top: 18%; right: 6%; width: 95px; height: 95px; opacity: 0.6;"
               viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet">
            <path d="M22,10 L35,8 L48,9 L62,11 L74,15 L82,22 L86,32 L88,45 L85,58 L80,68 L72,76 L62,82 L52,85 L42,84 L32,80 L24,72 L18,62 L15,50 L14,38 L17,26 Z"
                  fill="rgba(37,99,235,0.06)" stroke="rgba(37,99,235,0.28)" stroke-width="1"/>
            <circle cx="48" cy="62" r="2.2" fill="rgba(6,182,212,0.85)"/>
            <circle cx="48" cy="62" r="5" fill="none" stroke="rgba(6,182,212,0.45)" stroke-width="0.8"/>
            <text x="40" y="71" font-family="Inter, sans-serif" font-size="7" fill="rgba(192,38,211,0.7)" font-weight="bold">QC</text>
          </svg>

          <div class="relative px-5 py-3 border-b border-brand-b1/20 flex items-center gap-2.5">
            {# Round 5 — mini logo DictIA (subtle) connecte le brand visuellement #}
            <img src="{{ url_for('static', filename='images/dictia-logo.png') }}"
                 alt="" aria-hidden="true"
                 class="w-7 h-7 rounded shrink-0 opacity-95"
                 width="28" height="28" loading="lazy">
            {# Numéro 03 → checkmark CYAN (round 5 : palette brand) #}
            <span class="relative w-5 h-5 rounded-full flex items-center justify-center shrink-0 bg-brand-b2/20 border border-brand-b2/50" aria-hidden="true">
              <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" class="cycle-check-svg w-3 h-3"
                   :class="phase >= 4 ? 'is-visible' : ''"><path d="M5 13l4 4L19 7"/></svg>
            </span>
            <span class="text-[11px] uppercase tracking-[0.22em] font-semibold text-brand-b1/85">Solution</span>
            {# Badge top-right : Loi 25 conforme — round 5 : gradient brand blue->fuchsia #}
            <span class="cycle-conforme-badge ml-auto inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 border border-brand-b2/50"
                  :class="phase >= 4 ? 'is-visible' : ''" aria-label="Loi 25 conforme"
                  style="background: linear-gradient(135deg, rgba(37,99,235,0.22), rgba(192,38,211,0.18));">
              <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-2.5 h-2.5 text-white" aria-hidden="true"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/><path d="M9 12l2 2 4-4"/></svg>
              <span class="font-mono font-bold text-[8px] tracking-[0.16em] uppercase text-white">Loi&nbsp;25 conforme</span>
            </span>
          </div>

          <div class="relative flex-1 flex flex-col items-center justify-center px-5 py-7 gap-5">
            {# Shield + microphone (round 5) + halo multi-couches blue+cyan + drawn ring SVG #}
            <div class="relative flex items-center justify-center" aria-hidden="true">
              {# Couche externe drawn ring SVG (fuchsia accent) #}
              <svg class="cycle-ring-draw-svg absolute" :class="phase >= 4 ? 'is-visible' : ''"
                   width="108" height="108" viewBox="0 0 80 80">
                <circle cx="40" cy="40" r="35" fill="none" stroke="rgba(192,38,211,0.32)" stroke-width="1" stroke-linecap="round"/>
              </svg>
              <span class="cycle-ring-outer absolute rounded-full border border-brand-b1/25"
                    :class="phase >= 4 ? 'is-visible' : ''"
                    style="width: 96px; height: 96px;"></span>
              <span class="cycle-ring-inner absolute rounded-full border border-brand-b2/40"
                    :class="phase >= 4 ? 'is-visible' : ''"
                    style="width: 68px; height: 68px;"></span>
              <div class="relative w-[56px] h-[56px] rounded flex items-center justify-center bg-gradient-to-br from-brand-b1/20 via-brand-b2/15 to-brand-b3/10 border border-brand-b2/45"
                   style="box-shadow: 0 0 24px rgba(37,99,235,0.35), 0 0 48px rgba(6,182,212,0.18);">
                {# Shield extérieur #}
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" class="w-7 h-7 text-brand-b1">
                  <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>
                </svg>
                {# Microphone à l'intérieur #}
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" class="w-3.5 h-3.5 text-brand-b2 absolute"
                     style="top: 50%; left: 50%; transform: translate(-50%, -45%);">
                  <rect x="9" y="6" width="6" height="9" rx="3"/>
                  <path d="M12 17v3"/>
                  <path d="M9 20h6"/>
                </svg>
              </div>
            </div>

            {# Flux sécurisé (palette brand b1+b2) #}
            <div class="cycle-reveal flex items-center gap-2 px-3.5 py-1.5 rounded bg-brand-b1/10 border border-brand-b2/25"
                 :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/65" 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/80 font-medium">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-b2" 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/65" 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é (palette brand b1+b2 cyan checkmark) #}
            <div class="flex flex-col gap-2 w-full">
              {% for badge_label in ['Loi 25 conforme', '100&nbsp;% 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.08] border border-brand-b2/25"
                   :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-b2/20 border border-brand-b2/45">
                  <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-b2" aria-hidden="true"><path d="M5 13l4 4L19 7"/></svg>
                </span>
                <span class="text-[12px] font-medium text-brand-navy/80">{{ badge_label | safe }}</span>
              </div>
              {% endfor %}
            </div>
          </div>

          <div class="relative px-5 pb-5 pt-4 border-t border-brand-b2/20">
            <div class="flex items-center gap-2 mb-2.5">
              <span class="flex-1 h-px bg-gradient-to-r from-transparent via-brand-b1/30 to-brand-b2/30"></span>
              <span class="font-mono font-bold text-[10px] uppercase tracking-[0.20em] grad-text">UTILISATEURS ILLIMITÉS</span>
              <span class="flex-1 h-px bg-gradient-to-l from-transparent via-brand-b3/30 to-brand-b2/30"></span>
            </div>
            <p class="text-center text-[10px] mb-3.5 text-brand-b1/65">Zéro frais caché · Du jamais vu</p>
            <div class="flex items-baseline gap-2">
              {# Round 5 — big number en grad-text (blue->cyan->fuchsia) — Cloud BASIC v7.0 #}
              <span class="font-black leading-none text-5xl grad-text">189</span>
              <span class="text-sm text-brand-navy/55 mb-0.5 font-semibold">$ / 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-b2" 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/70 font-medium">Conforme Loi&nbsp;25 · 100&nbsp;% Québec</p>
            </div>
          </div>
        </div>
      </div>

      {# Section "Économies annuelles · 25 utilisateurs" — round 5 : 3 cards palette brand + chips contextuels #}
      <div class="cycle-reveal-up mt-12"
           :class="phase >= 4 ? 'is-visible' : ''"
           style="transition-delay: 700ms;">
        <div class="flex items-center justify-center gap-2.5 mb-5">
          <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 text-brand-b1" 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>
          <span class="font-mono font-bold text-[10px] uppercase tracking-[0.22em] text-brand-navy/65">
            Économies annuelles · 25&nbsp;utilisateurs
          </span>
          <span class="flex-1 h-px bg-brand-border max-w-[60px]" aria-hidden="true"></span>
        </div>

        <div class="grid grid-cols-1 md:grid-cols-3 gap-3" role="list" aria-label="Trois comparaisons d'économies annuelles">
          {% for sav in [
            {'icon': 'otter', 'val_prop': 'sav1', 'val_static': '3&nbsp;924', 'label': 'vs Otter.ai',  'sub': 'IA cloud US',           'chip': 'IA cloud US'},
            {'icon': 'teams', 'val_prop': 'sav2', 'val_static': '6&nbsp;924', 'label': 'vs MS Teams',  'sub': 'Copilot premium',       'chip': 'Copilot premium'},
            {'icon': 'scribe','val_prop': 'sav3', 'val_static': '2&nbsp;004', 'label': 'vs Sténographe','sub': 'Service humain',        'chip': 'Service humain'}
          ] %}
          <div class="cycle-savings-card flex items-center gap-3 px-4 py-4 rounded border border-brand-border bg-white relative overflow-hidden" role="listitem">
            {# Round 5 — subtle blue tint bg layer #}
            <div class="absolute inset-0 pointer-events-none opacity-60" aria-hidden="true"
                 style="background: linear-gradient(135deg, rgba(37,99,235,0.04) 0%, transparent 60%);"></div>
            <span class="relative shrink-0 w-10 h-10 rounded flex items-center justify-center bg-brand-b1/10 border border-brand-b2/30 text-brand-b1" aria-hidden="true">
              {% if sav.icon == 'otter' %}
              {# Round 5 — silhouette de loutre stylisée (tête + oreilles + moustache) #}
              <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-5 h-5">
                <path d="M5 8 C5 5, 7 3, 8 3 C8.5 4, 9 5, 8.5 6"/>
                <path d="M19 8 C19 5, 17 3, 16 3 C15.5 4, 15 5, 15.5 6"/>
                <ellipse cx="12" cy="13" rx="6" ry="6.5"/>
                <circle cx="9.5" cy="11.5" r="0.8" fill="currentColor"/>
                <circle cx="14.5" cy="11.5" r="0.8" fill="currentColor"/>
                <path d="M11 15 Q12 16 13 15"/>
                <path d="M9 16 L7.5 16.5 M15 16 L16.5 16.5"/>
              </svg>
              {% elif sav.icon == 'teams' %}
              {# Round 5 — carré avec "T" stylisé Teams #}
              <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-5 h-5">
                <rect x="3" y="3" width="18" height="18" rx="2"/>
                <path d="M8 8h8"/>
                <path d="M12 8v9"/>
              </svg>
              {% else %}
              {# Round 5 — silhouette humain (sténographe) avec doc #}
              <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-5 h-5">
                <circle cx="9" cy="6" r="3"/>
                <path d="M3 21v-1.5C3 17 5.7 15 9 15s6 2 6 4.5V21"/>
                <rect x="15.5" y="11" width="6" height="8" rx="0.8"/>
                <line x1="17" y1="13.5" x2="20" y2="13.5"/>
                <line x1="17" y1="15.5" x2="20" y2="15.5"/>
              </svg>
              {% endif %}
            </span>
            <div class="relative flex-1 min-w-0">
              {# Round 5 — save chip "+économies" au-dessus du big number #}
              <span class="cycle-save-chip inline-flex items-center gap-1 rounded-full px-1.5 py-px mb-1 bg-brand-b1/10 border border-brand-b1/25">
                <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-2 h-2 text-brand-b1" aria-hidden="true"><polyline points="6 9 12 15 18 9"/></svg>
                <span class="font-mono font-bold text-[7px] tracking-[0.16em] uppercase text-brand-b1">+économies</span>
              </span>
              <div class="flex items-baseline">
                {# Round 5 — big number en grad-text (blue->cyan->fuchsia) #}
                {# OQLF NBSP entre nombre et $ — préservé en placeholder statique pour SEO/no-JS, JS écrase via x-html #}
                <span class="font-black text-2xl leading-none grad-text tabular-nums"
                      x-html="fmt({{ sav.val_prop }}) + '&nbsp;<span class=&quot;text-sm font-bold&quot;>$</span>'">{{ sav.val_static | safe }}&nbsp;$</span>
              </div>
              <div class="text-[11px] font-semibold text-brand-navy/85 mt-1">{{ sav.label }}</div>
              <div class="inline-flex items-center gap-1 mt-0.5">
                <span class="w-1 h-1 rounded-full bg-brand-b2"></span>
                <span class="font-mono text-[9px] tracking-[0.10em] text-brand-navy/50">{{ sav.chip }}</span>
              </div>
            </div>
          </div>
          {% endfor %}
        </div>
      </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(6,182,212,0.08) 0%, transparent 60%); filter: blur(60px);"></div>

  <div class="relative max-w-[1200px] mx-auto px-6">
    <div class="text-center max-w-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&nbsp;% 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&nbsp;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&nbsp;: 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(96,165,250,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(96,165,250,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 + (167-255)*p)},${Math.round(60 + (139-60)*p)},${Math.round(60 + (250-60)*p)},0.12); border-color: rgba(${Math.round(255 + (167-255)*p)},${Math.round(80 + (139-80)*p)},${Math.round(80 + (250-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' : '#60a5fa'}`"><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(96,165,250,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(96,165,250,0.15), rgba(37,99,235,0.07)); box-shadow: 0 0 18px rgba(96,165,250,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(96,165,250,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&nbsp;800&nbsp;$ / 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 189&nbsp;$/mois — illimité',          'x': 64, 'y': 10},
          {'text': '90&nbsp;%+ d\'économies',                 'x': 74, 'y': 38},
          {'text': '100&nbsp;% 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(96,165,250,0.10); border: 1px solid rgba(96,165,250,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(96,165,250,0.2), rgba(37,99,235,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&nbsp;Ç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 temps réel</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>
      <p class="text-sm text-brand-navy/55 mt-3 italic">
        Survolez une fonctionnalité pour voir la machine en action. Glissez pour calculer votre gain de productivité.
      </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, #2563eb 0%, #06b6d4 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(6,182,212,0.55), 0 0 36px rgba(37,99,235,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&nbsp;heure d'audio → 2&nbsp;minutes. Précision 95&nbsp;%+ en français canadien. 100&nbsp;% 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(37,99,235,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="#2563eb" 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, #2563eb, #06b6d4);"
            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>

{# ===== LANGUES + IA LOCALE ===== #}
{# Section compacte : grille 99+ langues détectées (gauche) + carte IA Mistral 7B LOCAL (droite). #}
<section class="bg-brand-bg py-16 border-y border-brand-border" aria-labelledby="langues-title">
  <div class="max-w-[1100px] mx-auto px-6">
    <div class="grid lg:grid-cols-2 gap-8">
      {# Colonne gauche — 99+ langues #}
      <div class="bg-white rounded border border-brand-border p-6">
        <div class="flex items-center gap-3 mb-4">
          <span class="grad-bg w-9 h-9 rounded flex items-center justify-center text-white" aria-hidden="true">
            <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"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
          </span>
          <div>
            <h2 id="langues-title" class="text-lg font-bold text-brand-navy leading-tight">99+ langues détectées</h2>
            <p class="text-xs text-brand-navy/55 mt-0.5">WhisperX Large-v3 · multilingue par défaut</p>
          </div>
        </div>

        {# Grille codes langue — 12 puces (FR mis en avant via grad-bg) #}
        <ul class="grid grid-cols-6 sm:grid-cols-8 gap-1.5 mb-4" role="list" aria-label="Quelques langues supportées">
          {% for code in ['FR','EN','ES','DE','PT','IT','NL','PL','ZH','JA','KO','AR','RU','HI','TR','VI','TH','SV','DA','NO','FI'] %}
          <li class="text-center">
            <span class="block text-[10px] font-mono font-bold py-1 rounded
                         {{ 'grad-bg text-white' if code == 'FR' else 'bg-brand-bg border border-brand-border text-brand-navy/70' }}">
              {{ code }}
            </span>
          </li>
          {% endfor %}
        </ul>

        <p class="text-xs text-brand-navy/55 flex items-center gap-1.5">
          <span class="inline-block w-1.5 h-1.5 rounded-full bg-brand-b3"></span>
          <span><strong class="text-brand-navy">Auto</strong> · Détection automatique de la langue à l'upload</span>
        </p>
      </div>

      {# Colonne droite — IA intégrée Mistral 7B LOCAL #}
      <div class="bg-brand-navy text-white rounded p-6 relative overflow-hidden">
        {# Subtle orb décoratif #}
        <div class="absolute -top-12 -right-12 w-48 h-48 rounded-full pointer-events-none" aria-hidden="true"
             style="background: radial-gradient(circle, rgba(6,182,212,0.15) 0%, transparent 60%); filter: blur(30px);"></div>

        <div class="relative">
          <div class="flex items-center gap-3 mb-4">
            <span class="bg-white/10 border border-white/15 w-9 h-9 rounded flex items-center justify-center text-brand-b3" aria-hidden="true">
              <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"><path d="M12 2a3 3 0 0 0-3 3v1a3 3 0 0 0-3 3v1a3 3 0 0 0 0 6v1a3 3 0 0 0 3 3 3 3 0 0 0 6 0 3 3 0 0 0 3-3v-1a3 3 0 0 0 0-6V9a3 3 0 0 0-3-3V5a3 3 0 0 0-3-3z"/></svg>
            </span>
            <div>
              <h3 class="text-lg font-bold leading-tight">IA intégrée — Mistral 7B <span class="grad-text">(LOCAL)</span></h3>
              <p class="text-xs text-white/55 mt-0.5">Inférence sur votre GPU · zéro cloud étranger</p>
            </div>
          </div>

          <ul class="space-y-2 text-sm" role="list">
            <li class="flex items-start gap-2">
              <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4 mt-0.5 text-brand-b3 shrink-0" aria-hidden="true"><path d="M5 13l4 4L19 7"/></svg>
              <span class="text-white/80"><strong class="text-white">Résumé · Points d'action · Q&amp;R</strong></span>
            </li>
            <li class="flex items-start gap-2">
              <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4 mt-0.5 text-brand-b3 shrink-0" aria-hidden="true"><path d="M5 13l4 4L19 7"/></svg>
              <span class="text-white/80">Données hébergées sur <strong class="text-white">vos serveurs</strong> · jamais partagées</span>
            </li>
            <li class="flex items-start gap-2">
              <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4 mt-0.5 text-brand-b3 shrink-0" aria-hidden="true"><path d="M5 13l4 4L19 7"/></svg>
              <span class="text-white/80">Zéro connexion <strong class="text-white">OpenAI · Google · Microsoft</strong></span>
            </li>
            <li class="flex items-start gap-2">
              <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4 mt-0.5 text-brand-b3 shrink-0" aria-hidden="true"><path d="M5 13l4 4L19 7"/></svg>
              <span class="text-white/80">Inférence <strong class="text-white">hors-ligne</strong> · résultats en secondes</span>
            </li>
          </ul>
        </div>
      </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&nbsp;%+ sur réunions, dictées, audiences (méthodologie disponible sur demande).', icon_microphone) }}
      {{ bento_card('02', 'Diarisation 8 locuteurs', 'pyannote sépare automatiquement les intervenants. Identification par embeddings vocaux.', icon_users) }}
      {{ bento_card('03', 'Résumés Mistral 7B', 'IA locale génère résumés, points d\'action et procès-verbaux. Aucune connexion cloud.', icon_document) }}
      {{ bento_card('04', 'Q&amp;R sur enregistrement', 'Posez des questions à vos réunions. RAG local sur embeddings sentence-transformers.', icon_chat) }}
      {{ bento_card('05', 'Exports multiples', 'DOCX, PDF, SRT, VTT, TXT, JSON, MD. Formats avocat, notaire, CPA.', icon_export) }}
      {{ bento_card('06', 'Intégrations', 'Word, Outlook, Teams, Notion, Obsidian, Zapier, Make, n8n.', icon_plug) }}
    </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(6,182,212,0.55), 0 0 56px rgba(6,182,212,0.18); }
    50%      { box-shadow: 0 0 38px rgba(6,182,212,0.75), 0 0 72px rgba(6,182,212,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 — aqua, 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(6,182,212,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="#2563eb" stroke-width="1.5" opacity="0.55" />
        <use href="#hub-path-comm"  fill="none" stroke="#06b6d4" 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="#2563eb" stroke-width="1" opacity="0.30" />
        <use href="#hub-path-google"   fill="none" stroke="#2563eb" stroke-width="1" opacity="0.30" />
        <use href="#hub-path-obsidian" fill="none" stroke="#2563eb" stroke-width="1" opacity="0.30" />
        <use href="#hub-path-outlook"  fill="none" stroke="#06b6d4" stroke-width="1" opacity="0.30" />
        <use href="#hub-path-teams"    fill="none" stroke="#06b6d4" stroke-width="1" opacity="0.30" />
        <use href="#hub-path-notion"   fill="none" stroke="#06b6d4" 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',  '#2563eb', '0s',   '2.4s'),
          ('comm',  '#06b6d4', '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',     '#2563eb', '0s'),
          ('google',   '#2563eb', '0.4s'),
          ('obsidian', '#2563eb', '0.8s'),
          ('outlook',  '#06b6d4', '0.2s'),
          ('teams',    '#06b6d4', '0.6s'),
          ('notion',   '#06b6d4', '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(37,99,235,0.10)', 'rgba(37,99,235,0.30)', 'text-violet-300'),
        ('Communication',  'Outlook · Teams · Notion',        '50%',   'rgba(6,182,212,0.10)',  'rgba(6,182,212,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&nbsp;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&nbsp;5&nbsp;% + TVQ&nbsp;9,975&nbsp;%).
      </p>
    </div>

    {% include 'marketing/_partials/_pricing_tiers.html' %}

    <p class="text-center text-xs text-brand-navy/60 mt-6 max-w-2xl mx-auto">
      Tous les prix en CAD, taxes en sus (TPS&nbsp;5&nbsp;% + TVQ&nbsp;9,975&nbsp;%).
    </p>

    {# 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&nbsp;?</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&nbsp;: 80&nbsp;% du temps de transcription manuelle économisé, 220 jours ouvrables/an, comparé à Cloud&nbsp;ESSENTIEL (349&nbsp;$/mois × 12 = 4&nbsp;188&nbsp;$/an). 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&nbsp;: politiques de confidentialité publiques + grilles tarifaires officielles. Détails sur demande&nbsp;: <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&nbsp;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&nbsp;$ (forfait fixe)'},
              'teams':  {'status': None, 'text': '~14&nbsp;$ CAD (Premium)'},
              'otter':  {'status': None, 'text': '~20&nbsp;$ US (Business)'},
              'whisper':{'status': None, 'text': '0&nbsp;$ (mais GPU&nbsp;+ DevOps requis)'}
            },
            {
              'critere': 'Audit trail intégré (Loi&nbsp;25 art.&nbsp;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 — aqua, 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(6,182,212,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. DictIA a été conçu pour les secteurs réglementés du Québec — Loi&nbsp;25, Cloud Act, Barreau, ChAD, AMF. Détails techniques (EFVP, audit trail, déclaration CAI) disponibles sur demande&nbsp;: <a href="mailto:info@dictia.ca" class="grad-text font-semibold hover:underline">info@dictia.ca</a>.
      </p>

      {# Chips claims — 3 marqueurs canoniques (~192 000 pros · 5 ordres · 0 donnée hors-Québec) #}
      <div class="flex flex-wrap items-center justify-center gap-2 mt-6" role="list" aria-label="Chiffres clés conformité">
        {% for chip in [
          ('~192&nbsp;000 professionnels Tier&nbsp;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.5 h-3.5" aria-hidden="true"><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>'),
          ('5&nbsp;ordres · directives IA formelles', '<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" aria-hidden="true"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>'),
          ('0&nbsp;donnée transmise hors Québec', '<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" 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>')
        ] %}
        <span class="inline-flex items-center gap-1.5 bg-white/[0.06] border border-white/15 rounded-full px-3 py-1 text-xs text-white/85" role="listitem">
          <span class="text-brand-b3" aria-hidden="true">{{ chip[1] | safe }}</span>
          <span>{{ chip[0] | safe }}</span>
        </span>
        {% endfor %}
      </div>
    </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&nbsp;27001, SOC&nbsp;2 selon le périmètre). Détails sur demande.'
        },
        {
          'icon': svg_scale,
          'title': 'Mappé Loi&nbsp;25 (LPRPSP)',
          'desc': 'Audit trail art.&nbsp;3.5, EFVP préparée art.&nbsp;3.3, registre des consentements art.&nbsp;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&nbsp;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&nbsp;: <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)
   Round 4 cinématique : radar sweep continu, 6 paquets data en flight QC→US (offset-path bezier),
   typewriter 3 lignes char-par-char, REGS reveal cascadé + glow rouge hover, verdict pulse + scan-line,
   grid pattern bg console. #}
<style>
  /* Cadre — RADAR SWEEP circulaire continu (round 4) */
  @keyframes cadre-radar-sweep { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
  .cadre-radar { animation: cadre-radar-sweep 4s linear infinite; transform-origin: center; }

  /* 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 — DATA PACKET flight QC→US via offset-path bezier (round 4) */
  @keyframes cadre-packet-fly {
    0%   { offset-distance: 0%;   opacity: 0;    transform: scale(0.7); }
    8%   { opacity: 1;            transform: scale(1); }
    85%  { opacity: 1;            transform: scale(1); }
    100% { offset-distance: 100%; opacity: 0;    transform: scale(0.4); }
  }
  .cadre-packet {
    offset-path: path('M 0 24 Q 100 -24, 200 24');
    offset-rotate: auto;
    animation: cadre-packet-fly 2.6s ease-in-out infinite;
    will-change: offset-distance, opacity, transform;
  }

  /* Cadre — packet trail (traînée fade rouge à l'arrivée) */
  @keyframes cadre-packet-arrive {
    0%, 70% { opacity: 0; transform: translate(-50%,-50%) scale(0.5); }
    80%     { opacity: 0.85; transform: translate(-50%,-50%) scale(1.4); }
    100%    { opacity: 0; transform: translate(-50%,-50%) scale(2.2); }
  }
  .cadre-packet-burst { animation: cadre-packet-arrive 2.6s ease-in-out infinite; }

  /* Cadre — REGS row flash amber pendant le sweep */
  .cadre-reg { transition: border-color 220ms, background-color 220ms, box-shadow 220ms, transform 220ms; }
  .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; }
  /* Hover red glow (round 4) */
  .cadre-reg:hover { box-shadow: 0 0 18px rgba(239,68,68,0.22); border-left-width: 3px !important; border-left-color: rgba(239,68,68,0.65) !important; transform: translateX(2px); }

  /* Cadre — REGS reveal cascadé (round 4 : IntersectionObserver via Alpine `revealRegs`) */
  .cadre-reg-item { opacity: 0; transform: translateX(12px); transition: opacity 420ms ease-out, transform 420ms ease-out; }
  .cadre-reg-item.is-visible { opacity: 1; transform: translateX(0); }

  /* 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; }

  /* Cadre — VERDICT NON CONFORME pulse glow (round 4) */
  @keyframes cadre-verdict-pulse {
    0%, 100% { box-shadow: 0 0 0 0   rgba(239,68,68,0.50), inset 0 0 0 1px rgba(239,68,68,0.45); }
    50%      { box-shadow: 0 0 18px 3px rgba(239,68,68,0.30), inset 0 0 0 1px rgba(239,68,68,0.85); }
  }
  .cadre-verdict-active { animation: cadre-verdict-pulse 2s ease-in-out infinite; }

  /* Cadre — VERDICT scan-line traversante (round 4) */
  @keyframes cadre-scan-line {
    0%   { transform: translateX(-110%); opacity: 0; }
    20%  { opacity: 0.85; }
    80%  { opacity: 0.85; }
    100% { transform: translateX(110%);  opacity: 0; }
  }
  .cadre-scan-line { animation: cadre-scan-line 3s linear infinite; }

  /* Cadre — typewriter caret (3e ligne en rouge avec glow) */
  .cadre-hud-line-3 { color: #ff5252 !important; text-shadow: 0 0 8px rgba(239,68,68,0.55); }

  /* Mobile — désactiver radar + packets (CPU-intensive) */
  @media (max-width: 768px) {
    .cadre-radar, .cadre-packet, .cadre-packet-burst { display: none; }
  }

  /* Reduced motion — TOUT figé */
  @media (prefers-reduced-motion: reduce) {
    .cadre-radar, .cadre-halo, .cadre-blink, .cadre-caret, .cadre-packet,
    .cadre-packet-burst, .cadre-verdict-active, .cadre-scan-line {
      animation: none !important;
    }
    .cadre-reg, .cadre-reg-item { transition: none !important; opacity: 1 !important; transform: 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,
    /* hudTyped[i] = sous-chaîne progressive de HUD[i] (typewriter char-by-char) */
    hudTyped: ['','',''],
    hudCursorLine: -1,
    flashIdx: -1,
    revealedRegs: [],
    timers: [],
    observer: null,
    HUD: ['&gt; Interception IA détectée.', '&gt; Données utilisées pour entraînement.', '&gt; Statut : Violation Légale.'],
    typeLine(idx, cb) {
      const full = this.HUD[idx];
      const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
      if (reduced) { this.hudTyped[idx] = full; if (cb) cb(); return; }
      this.hudCursorLine = idx;
      let i = 0;
      const tick = () => {
        if (i > full.length) { if (cb) cb(); return; }
        this.hudTyped[idx] = full.slice(0, i);
        i++;
        this.timers.push(setTimeout(tick, 28));
      };
      tick();
    },
    runCycle() {
      this.step = 0; this.hudTyped = ['','','']; this.hudCursorLine = -1; 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;
        /* Typewriter chain : ligne 0 → 1 → 2 puis reset cursor */
        this.typeLine(0, () => {
          this.timers.push(setTimeout(() => this.typeLine(1, () => {
            this.timers.push(setTimeout(() => this.typeLine(2, () => {
              this.hudCursorLine = -1;
            }), 280));
          }), 280));
        });
      }, 2800));
      for (let i = 0; i < 6; i++) {
        this.timers.push(setTimeout(() => this.flashIdx = i, 5400 + i * 200));
      }
      this.timers.push(setTimeout(() => this.flashIdx = -1, 5400 + 6 * 200 + 500));
      this.timers.push(setTimeout(() => this.runCycle(), 9500));
    },
    revealRegsCascade() {
      [0,1,2,3,4,5].forEach((i) => {
        this.timers.push(setTimeout(() => {
          if (!this.revealedRegs.includes(i)) this.revealedRegs.push(i);
        }, i * 120));
      });
    },
    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.timers.push(setTimeout(() => this.revealRegsCascade(), 500));
            this.observer.disconnect();
          }
        });
      }, { rootMargin: '-100px' });
      this.observer.observe($el);
    }
  }"
>
  {# Round 4 : decorative grid pattern bg console-style 40×40 #}
  <div class="absolute inset-0 pointer-events-none" aria-hidden="true"
       style="background-image: linear-gradient(rgba(255,255,255,0.03) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.03) 1px, transparent 1px), radial-gradient(circle, rgba(11,15,26,0.045) 1px, transparent 1px); background-size: 40px 40px, 40px 40px, 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 inline-flex items-center gap-1.5">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" class="w-3.5 h-3.5" 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>
        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 inline-flex items-center gap-1 font-bold text-[9px] uppercase tracking-[0.18em] text-amber-600 cadre-blink"
              x-cloak>
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" class="w-2.5 h-2.5" 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>
          Alerte Active
        </span>
      </div>

      {# Body — 2 colonnes #}
      <div class="flex flex-col md:flex-row">

        {# LEFT — animation track (~42%) — round 4 : radar + data packets en flight #}
        <div class="relative md:w-[42%] px-5 py-5 overflow-hidden bg-brand-bg" style="min-height: 240px;" role="img" aria-label="Visualisation : radar de surveillance et paquets de données voix transférés du Québec aux États-Unis">
          {# Grille bg console #}
          <div class="absolute inset-0 pointer-events-none" aria-hidden="true"
               style="background-image: linear-gradient(rgba(11,15,26,0.045) 1px, transparent 1px), linear-gradient(90deg, rgba(11,15,26,0.045) 1px, transparent 1px); background-size: 20px 20px;"></div>

          {# Round 4 : Radar sweep — cercle vert avec ligne rotative balayant 360° #}
          <div class="absolute -top-8 -right-8 w-40 h-40 pointer-events-none opacity-50" aria-hidden="true">
            <svg viewBox="0 0 100 100" class="w-full h-full">
              <defs>
                <linearGradient id="cadre-radar-grad" x1="0" y1="0" x2="1" y2="0">
                  <stop offset="0%" stop-color="rgba(34,197,94,0)"/>
                  <stop offset="80%" stop-color="rgba(34,197,94,0.55)"/>
                  <stop offset="100%" stop-color="rgba(34,197,94,0.85)"/>
                </linearGradient>
              </defs>
              <circle cx="50" cy="50" r="48" fill="none" stroke="rgba(34,197,94,0.20)" stroke-width="0.5"/>
              <circle cx="50" cy="50" r="32" fill="none" stroke="rgba(34,197,94,0.15)" stroke-width="0.4"/>
              <circle cx="50" cy="50" r="16" fill="none" stroke="rgba(34,197,94,0.12)" stroke-width="0.4"/>
              <line x1="2" y1="50" x2="98" y2="50" stroke="rgba(34,197,94,0.10)" stroke-width="0.3"/>
              <line x1="50" y1="2" x2="50" y2="98" stroke="rgba(34,197,94,0.10)" stroke-width="0.3"/>
              {# Sweep arm #}
              <g class="cadre-radar" style="transform-origin: 50px 50px;">
                <path d="M 50 50 L 98 50 A 48 48 0 0 0 84 16 Z" fill="url(#cadre-radar-grad)" opacity="0.45"/>
                <line x1="50" y1="50" x2="98" y2="50" stroke="rgba(34,197,94,0.85)" stroke-width="0.6"/>
              </g>
              <circle cx="50" cy="50" r="1.6" fill="rgba(34,197,94,0.85)"/>
            </svg>
          </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 + folder + DATA PACKETS en flight (round 4) #}
          <div class="relative h-12">
            <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>

            {# Folder source (QC) #}
            <div class="absolute top-1/2 -translate-y-1/2 -translate-x-1/2"
                 style="left: 6%; transition: color 0.4s, filter 0.4s;">
              <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(37,99,235,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>

            {# Folder destination (US) avec halo alerte #}
            <div class="absolute top-1/2 -translate-y-1/2 -translate-x-1/2"
                 style="left: 94%;">
              <span x-show="step >= 2" class="cadre-halo absolute inset-[-8px] rounded-full bg-red-500/20" x-cloak aria-hidden="true"></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-red-500' : 'text-brand-navy/40'"
                   :style="`filter: drop-shadow(0 0 ${step >= 2 ? '6px rgba(239,68,68,0.7)' : '0'})`"
                   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>
              {# Burst rouge à l'arrivée des paquets #}
              <span x-show="step >= 2" class="cadre-packet-burst absolute top-1/2 left-1/2 w-4 h-4 rounded-full bg-red-500/40 pointer-events-none" x-cloak aria-hidden="true"></span>
            </div>

            {# 6 PAQUETS DATA en flight QC→US (round 4 : offset-path bezier) #}
            <div x-show="step >= 1" class="absolute inset-0 pointer-events-none" x-cloak aria-hidden="true">
              {% for pi in range(6) %}
              <span class="cadre-packet absolute top-0 left-[6%] inline-flex items-center gap-1 px-1 py-0.5 rounded bg-red-500/85 text-white font-mono text-[8px] tracking-tighter shadow-[0_0_6px_rgba(239,68,68,0.6)]"
                    style="animation-delay: {{ pi * 0.42 }}s;">
                <span class="w-1 h-1 rounded-full bg-white/80"></span>
                voice.wav
              </span>
              {% endfor %}
            </div>
          </div>

          {# HUD panel — typewriter char-by-char (round 4) #}
          <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="relative mt-3 rounded px-3 py-2.5 font-mono"
               style="background: rgba(11,15,26,0.94); border: 1px solid rgba(245,158,11,0.30); font-size: 10px; color: #F59E0B; line-height: 1.65; min-height: 70px;"
               role="log" aria-live="polite"
               x-cloak>
            <div class="flex items-baseline">
              <span x-html="hudTyped[0]"></span>
              <span x-show="hudCursorLine === 0" class="cadre-caret ml-0.5">▮</span>
            </div>
            <div class="flex items-baseline" x-show="hudTyped[1].length > 0 || hudCursorLine === 1">
              <span x-html="hudTyped[1]"></span>
              <span x-show="hudCursorLine === 1" class="cadre-caret ml-0.5">▮</span>
            </div>
            <div class="flex items-baseline cadre-hud-line-3" x-show="hudTyped[2].length > 0 || hudCursorLine === 2">
              <span x-html="hudTyped[2]"></span>
              <span x-show="hudCursorLine === 2" class="cadre-caret ml-0.5">▮</span>
            </div>
          </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&nbsp;:
          </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.&nbsp;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" class="cadre-reg-item"
                :class="revealedRegs.includes({{ loop.index0 }}) ? 'is-visible' : ''"
                style="transition-delay: {{ loop.index0 * 30 }}ms;">
              <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(37,99,235,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(37,99,235,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 '#2563eb' }};">{{ 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 (round 4 : pulse glow rouge + scan-line traversante) #}
      <div class="relative px-5 py-3 border-t border-brand-border bg-white overflow-hidden">
        <div class="relative flex items-center gap-2.5 px-3 py-2 rounded transition-all duration-300"
             :class="step >= 2 ? 'cadre-verdict-active bg-red-50/40' : ''"
             style="border-radius: 4px;">
          <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-red-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-red-600' : 'text-brand-navy/35'"
                style="text-shadow: 0 0 6px rgba(239,68,68,0.30);"
                aria-live="polite">
            <span x-text="step >= 2 ? 'NON CONFORME — Loi 25 · Cloud Act' : 'Surveillance active...'"></span>
          </span>
          {# Scan-line horizontale (round 4) #}
          <span x-show="step >= 2" x-cloak class="cadre-scan-line absolute inset-y-0 left-0 w-1/3 pointer-events-none"
                style="background: linear-gradient(90deg, transparent 0%, rgba(239,68,68,0.18) 50%, transparent 100%);"
                aria-hidden="true"></span>
        </div>
      </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&nbsp;25, Cloud Act, Barreau, ChAD, AMF. Hébergement OVH&nbsp;Beauharnois,
      code source AGPL&nbsp;v3 vérifiable, audit trail intégré.
    </p>
  </div>
</section>

{# ===== CÉGEPS · CONFORMITÉ AU 19 JUIN 2026 (spotlight) ===== #}
{# Source canonique : texte fourni par l'utilisateur — Cadre IA MCN, Énoncé de principes mis à jour
   + Indication d'application IAG (publié 19 déc. 2025, conformité 19 juin 2026, art. 21 LGGRI). #}
<style>
  /* Pulse glow autour du badge "Conformité imminente" */
  @keyframes cegep-pulse-badge {
    0%, 100% { box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.55); }
    50%      { box-shadow: 0 0 0 6px rgba(245, 158, 11, 0);    }
  }
  .cegep-badge-pulse { animation: cegep-pulse-badge 2.2s ease-in-out infinite; }
  /* Bullets reveal staggered (intersection observer via Alpine x-intersect non requis, on utilise CSS animation-delay) */
  @keyframes cegep-bullet-rise {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
  }
  .cegep-bullet { opacity: 0; animation: cegep-bullet-rise 0.5s ease-out forwards; }
  @media (prefers-reduced-motion: reduce) {
    .cegep-badge-pulse, .cegep-bullet { animation: none !important; }
    .cegep-bullet { opacity: 1 !important; transform: none !important; }
  }
</style>
<section class="bg-brand-bg py-20 border-y border-brand-border" aria-labelledby="cegeps-title">
  <div class="max-w-[1100px] mx-auto px-6">

    {# Bandeau d'eyebrow + badge pulse #}
    <div class="flex flex-wrap items-center justify-center gap-3 mb-5">
      <span class="cegep-badge-pulse inline-flex items-center gap-1.5 bg-amber-50 border border-amber-300 text-amber-800 rounded-full px-3 py-1 text-[11px] font-bold uppercase tracking-wider">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="w-3 h-3" aria-hidden="true"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
        Conformité imminente
      </span>
      <span class="text-xs uppercase tracking-[0.18em] text-brand-navy/55 font-semibold">
        Adopté 19&nbsp;déc.&nbsp;2025 · Décret officiel
      </span>
    </div>

    <div class="text-center max-w-3xl mx-auto mb-12">
      <h2 id="cegeps-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black mb-5 text-brand-navy leading-tight">
        Conformité au <span class="grad-text">19&nbsp;juin&nbsp;2026</span> — vous dirigez un cégep, un CISSS ou un ministère&nbsp;?
      </h2>
      <p class="text-lg text-brand-navy/80 font-semibold mb-3">
        Vous avez jusqu'au 19&nbsp;juin&nbsp;2026.
      </p>
      <p class="text-base text-brand-navy/70 leading-relaxed">
        Depuis le 19&nbsp;décembre&nbsp;2025, tous les organismes publics québécois doivent appliquer un cadre IA strict. Aucun outil cloud non approuvé ne peut recevoir de renseignements confidentiels — fini ChatGPT ou Teams Copilot dans les CA, les séances cliniques ou les comités universitaires.
      </p>
    </div>

    {# Carte spotlight — Cadre IA MCN détaillé #}
    <div class="bg-white border border-brand-border rounded p-6 md:p-8 max-w-4xl mx-auto">
      <div class="flex items-start gap-3 mb-5">
        <span class="grad-bg w-10 h-10 rounded flex items-center justify-center text-white shrink-0" aria-hidden="true">
          <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"><path d="M3 21h18"/><path d="M5 21V8l7-4 7 4v13"/><path d="M9 21v-6h6v6"/></svg>
        </span>
        <div class="min-w-0">
          <h3 class="text-lg md:text-xl font-bold text-brand-navy leading-tight">
            Cadre IA MCN — Énoncé de principes mis à jour + Indication d'application IAG
          </h3>
          <p class="text-xs text-brand-navy/55 mt-1">Publié le 19&nbsp;décembre&nbsp;2025 sous l'art.&nbsp;21 LGGRI</p>
        </div>
      </div>

      <p class="text-sm text-brand-navy/75 leading-relaxed mb-5">
        Interdit aux organismes publics (art.&nbsp;2 LGGRI) d'entrer des renseignements confidentiels dans un système IA non approuvé — ministères, organismes budgétaires, Santé&nbsp;Québec, CISSS/CIUSSS, centres de services scolaires, cégeps, universités. Régime allégé pour entreprises du gouvernement (art.&nbsp;4 — Hydro-Québec, SAQ, Loto-Québec, CDPQ).
      </p>

      <ul class="space-y-2.5 mb-6" role="list">
        {% for bullet in [
          ('Énoncé de principes — 12 principes éthiques applicables à tout système IA dans l\'administration publique', 0),
          ('Indication d\'application IAG — gouvernance, gestion des risques, mesures de contrôle, protection des données, formation du personnel', 80),
          ('Délai conformité&nbsp;: <strong>19&nbsp;juin&nbsp;2026</strong> (6&nbsp;mois post publication 19&nbsp;déc.&nbsp;2025)', 160),
          ('Municipalités, MRC et Assemblée nationale <em>non</em> visées par l\'Énoncé — mais Loi sur l\'accès (A-2.1) reste applicable aux séances publiques', 240),
          ('<strong>Loi&nbsp;25</strong> — voix = donnée biométrique (LCCJTI art.&nbsp;44-45), déclaration CAI obligatoire si banque biométrique', 320),
          ('<strong>Loi&nbsp;96 (C-11)</strong> — documents générés en français pour organisations 25+ employés', 400),
          ('Hébergement au Québec — aucune société US dans la chaîne (Cloud Act inapplicable)', 480)
        ] %}
        <li class="cegep-bullet flex items-start gap-2.5 text-sm text-brand-navy/80 leading-relaxed" role="listitem"
            style="animation-delay: {{ bullet[1] }}ms;">
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4 mt-1 text-brand-b3 shrink-0" aria-hidden="true"><path d="M5 13l4 4L19 7"/></svg>
          <span>{{ bullet[0] | safe }}</span>
        </li>
        {% endfor %}
      </ul>

      {# Liste organismes visés (chips) #}
      <div class="border-t border-brand-border pt-5">
        <p class="text-[11px] uppercase tracking-[0.16em] font-bold text-brand-navy/50 mb-3">Organismes visés par le Cadre&nbsp;IA MCN</p>
        <div class="flex flex-wrap gap-1.5" role="list">
          {% for org in ['Ministères', 'Santé Québec', 'CISSS/CIUSSS', 'Universités', 'Cégeps', 'Hydro-Québec', 'SAQ', 'SAAQ', 'CDPQ'] %}
          <span class="inline-flex items-center bg-brand-bg border border-brand-border rounded-full px-2.5 py-0.5 text-[11px] text-brand-navy/75" role="listitem">{{ org }}</span>
          {% endfor %}
        </div>
      </div>
    </div>
  </div>
</section>

{# ===== PARTENAIRE DE CONFIANCE — CyberPerformance ===== #}
<section class="bg-white py-12" aria-labelledby="partner-title">
  <div class="max-w-[1100px] mx-auto px-6">
    <div class="flex items-center gap-3 mb-4">
      <span id="partner-title" class="text-[10px] font-bold uppercase tracking-[0.20em] text-brand-navy/45">
        Partenaire de confiance
      </span>
      <span class="flex-1 h-px max-w-[60px] bg-brand-border"></span>
    </div>

    <a
      href="https://cyberperformance.ca"
      target="_blank"
      rel="noopener noreferrer"
      class="group flex flex-wrap sm:flex-nowrap items-center gap-5 px-5 py-4 rounded border border-brand-border hover:border-brand-b1 transition-colors no-underline focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
      aria-label="CyberPerformance — Marketing numérique, Lévis, QC. Site externe (s'ouvre dans un nouvel onglet)"
    >
      {# Icône SVG handshake générique (pas d'emoji, pas de logo bitmap) #}
      <span class="shrink-0 w-12 h-12 grad-bg rounded flex items-center justify-center text-white" aria-hidden="true">
        <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-6 h-6"><path d="M11 17l-2-2 2-2"/><path d="M13 7l2 2-2 2"/><path d="M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0z"/></svg>
      </span>

      <span class="hidden sm:block w-px h-8 bg-brand-border shrink-0"></span>

      <span class="flex-1 min-w-0">
        <span class="block text-sm font-bold text-brand-navy leading-tight">CyberPerformance</span>
        <span class="block text-xs text-brand-navy/60 mt-0.5">Marketing numérique · Lévis, QC</span>
      </span>

      <span class="shrink-0 inline-flex items-center gap-1.5 ml-auto text-xs text-brand-navy/55 group-hover:text-brand-b1 transition-colors">
        <span>cyberperformance.ca</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.5 h-3.5" aria-hidden="true"><path d="M7 17L17 7M7 7h10v10"/></svg>
        <span class="sr-only">(s'ouvre dans un nouvel onglet)</span>
      </span>
    </a>
  </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&nbsp;2026.
      </h2>
      <p class="text-lg text-brand-navy/70">
        Trois pilotes confidentiels en cours&nbsp;: 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 &middot; {{ 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&nbsp;? Écrivez-nous&nbsp;:
        <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('&nbsp;', ' '))|tojson }},
        "acceptedAnswer": {
          "@type": "Answer",
          "text": {{ (item.a | striptags | replace('&nbsp;', ' '))|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(37,99,235,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(6,182,212,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&nbsp;?</p>
    <h2 id="cta-title" class="text-[clamp(2.25rem,4vw,3.5rem)] font-black mb-6">
      Prêt à <span class="grad-text">protéger vos données</span>&nbsp;?
    </h2>
    <p class="text-lg text-white/80 mb-3">
      Réservez une démonstration gratuite. Nous analyserons vos besoins et vous recommanderons le forfait adapté à votre réalité.
    </p>
    <p class="text-base text-white/65 mb-8">
      Lancement printemps&nbsp;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('Réserver ma démo gratuite', href='/contact', 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.5" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"/></svg>') }}
      {{ button('Pré-inscription par courriel', href='mailto:info@dictia.ca?subject=Pré-inscription%20DictIA', 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="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 %}
