polish(marketing): refonte HYPER PRO 'Comment ça marche' — bezel iPhone, status bar, sound waves, modes enrichis (REC, waveform, typing, ripple, breadcrumb), IA card 40px brain + metrics, connecting line
10 améliorations cinématiques sur la section interactive : PHONE FRAME RÉALISTE - Bezel double border + glow ring externe pulsant - Notch (Dynamic Island stylisé) + speaker grille + camera dot - Status bar mobile (9:41, signal/wifi/batterie SVG) - Drop shadow dramatique + inner shadow encastrée MIC + SOUND WAVES - 3 ripples concentriques émanant du mic (sound-ring keyframes) MODE 1 TRANSCRIPTION - Header REC indicator pulsant (rouge) + nom fichier - Waveform animée (12 bars hauteurs randomisées) - Barre progress double avec gradient + glow MODE 2 DIARISATION - Header conversation : 3 avatars empilés overlapping - Bubbles avec timestamps (09:0X) + box-shadow - Typing indicator (3 dots) entre messages MODE 3 LANGUES - Header DÉTECTION AUTOMATIQUE avec dot pulsant - Ripple wave depuis le centre (rippleDelay calculé par distance) - 5 langues highlight aléatoire glow brièvement - Counter live FR · EN · ES · ... + 99+ détectées MODE 4 EXPORTS - Grid 4×2 organisé (au lieu de wrap aléatoire) - Files détaillés avec mini-pages (3 lignes texte) - Subtitle '7 FORMATS PRÊTS' + checkmark vert MODE 5 USERS - Counter centré 01 → 20 (font-mono black) - 5 USER_COLORS variations (purple/cyan/green/blue/amber) - Connecting lines SVG pointillés vers centre MODE 6 SHARE - Breadcrumb 'Mes dossiers › Réunions' - Toolbar mini (search, filter, sort) - Rows structurées avec 3-dots action BOTTOM ZONE - 6 boutons agrandis (30+px) avec labels + tab indicator border 2px - AUTO pill (badge dot pulse) / Manuel countdown bar 4.5s CARD INFO - Icon container 32×32 + badge top-right + hover lift RIGHT PANEL IA - Brain dans cercle 40×40 gradient + glow - Metrics row : 0ms latence · 100% privé · 24/7 - Sovereignty bullets : icon dans rounded box GLOBAL - Section background : grid pattern + 2 floating orbs blur - Connecting line SVG cyan→violet phone↔IA panel - Header section : eyebrow gradient pill + stats row (6/99+/0) + CTA démo - Crossfade transitions modes (scale 0.96 → 1) ACCESSIBILITÉ - prefers-reduced-motion désactive toutes animations - @media (max-width: 767px) désactive éléments décoratifs CPU-intensive - aria-pressed, aria-live polite, focus-visible préservés - 30 nouveaux keyframes CSS scopés Tests : 1 existant + 1 enrichi (53 lignes, 22 nouvelles assertions) Tests pass : 30/30 sur how-it-works (les 2 fails conformite sont pré-existants).
This commit is contained in:
@@ -255,13 +255,68 @@
|
||||
Exports, Users, Share) + IA Mistral 7B premium card + grid 6 features.
|
||||
Auto-cycle 900ms (1→6→1, skip IA index 0). Click manuel → 4500ms isManual.
|
||||
#}
|
||||
<section class="bg-brand-bg py-20" aria-labelledby="how-it-works-title">
|
||||
<section class="bg-brand-bg py-20 relative overflow-hidden" aria-labelledby="how-it-works-title">
|
||||
<style>
|
||||
/* ============ DECORATIVE BACKGROUND ============ */
|
||||
.dictia-section-grid {
|
||||
background-image:
|
||||
linear-gradient(to right, rgba(15,23,42,0.04) 1px, transparent 1px),
|
||||
linear-gradient(to bottom, rgba(15,23,42,0.04) 1px, transparent 1px);
|
||||
background-size: 60px 60px;
|
||||
mask-image: radial-gradient(ellipse 80% 60% at 50% 50%, black 0%, transparent 70%);
|
||||
-webkit-mask-image: radial-gradient(ellipse 80% 60% at 50% 50%, black 0%, transparent 70%);
|
||||
}
|
||||
.dictia-orb-float-1 { animation: dictia-orb-1 14s ease-in-out infinite; will-change: transform; }
|
||||
.dictia-orb-float-2 { animation: dictia-orb-2 18s ease-in-out infinite; will-change: transform; }
|
||||
@keyframes dictia-orb-1 { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(30px, -20px); } }
|
||||
@keyframes dictia-orb-2 { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(-25px, 25px); } }
|
||||
|
||||
/* ============ PHONE BEZEL & DEVICE FRAME ============ */
|
||||
.dictia-phone-shell {
|
||||
border-radius: 44px;
|
||||
position: relative;
|
||||
will-change: box-shadow, border-color;
|
||||
}
|
||||
.dictia-phone-shell::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 2px;
|
||||
border-radius: 42px;
|
||||
border: 1px solid rgba(255,255,255,0.04);
|
||||
pointer-events: none;
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.05) 0%, rgba(255,255,255,0) 30%);
|
||||
z-index: 0;
|
||||
}
|
||||
.dictia-phone-glow-ring { animation: dictia-glow-ring 3.6s ease-in-out infinite; will-change: opacity; }
|
||||
@keyframes dictia-glow-ring { 0%, 100% { opacity: 0.35; } 50% { opacity: 0.7; } }
|
||||
|
||||
/* ============ STATUS BAR + NOTCH + SPEAKER ============ */
|
||||
.dictia-statusbar { font-variant-numeric: tabular-nums; }
|
||||
|
||||
/* ============ MIC SOUND WAVES (3 ripples) ============ */
|
||||
.dictia-sound-ring {
|
||||
position: absolute;
|
||||
top: 50%; left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
border-radius: 50%;
|
||||
border: 1.5px solid currentColor;
|
||||
opacity: 0;
|
||||
will-change: transform, opacity;
|
||||
animation: dictia-sound-ring-anim 2.4s ease-out infinite;
|
||||
}
|
||||
.dictia-sound-ring.r1 { animation-delay: 0s; }
|
||||
.dictia-sound-ring.r2 { animation-delay: 0.8s; }
|
||||
.dictia-sound-ring.r3 { animation-delay: 1.6s; }
|
||||
@keyframes dictia-sound-ring-anim {
|
||||
0% { transform: translate(-50%, -50%) scale(0.4); opacity: 0.55; }
|
||||
100% { transform: translate(-50%, -50%) scale(2.4); opacity: 0; }
|
||||
}
|
||||
|
||||
/* Mic pulsing en haut du phone */
|
||||
.dictia-mic-pulse { animation: dmic-pulse 1.2s ease-in-out infinite; display: inline-block; }
|
||||
.dictia-mic-pulse { animation: dmic-pulse 1.2s ease-in-out infinite; display: inline-block; will-change: transform; }
|
||||
@keyframes dmic-pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.18); } }
|
||||
|
||||
/* IA card ambient glow + brain glow + LOCAL pulse */
|
||||
/* ============ IA CARD ============ */
|
||||
.ia-ambient-glow { animation: ia-glow 3s ease-in-out infinite; }
|
||||
@keyframes ia-glow { 0%, 100% { opacity: 0.4; } 50% { opacity: 0.75; } }
|
||||
.ia-brain-glow { animation: ia-brain 2.2s ease-in-out infinite; }
|
||||
@@ -273,14 +328,26 @@
|
||||
.dictia-blink { animation: dictia-cursor-blink 0.6s steps(2, end) infinite; }
|
||||
@keyframes dictia-cursor-blink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
|
||||
|
||||
/* Dot pulse (MISTRAL 7B · LOCAL header) */
|
||||
/* Dot pulse */
|
||||
.dictia-dot-pulse { animation: dictia-dot-pulse-anim 1.8s ease-in-out infinite; }
|
||||
@keyframes dictia-dot-pulse-anim { 0%, 100% { opacity: 0.4; transform: scale(1); } 50% { opacity: 1; transform: scale(1.35); } }
|
||||
|
||||
/* REC dot (transcription) */
|
||||
.dictia-rec-dot { animation: dictia-rec-pulse 1.4s ease-in-out infinite; }
|
||||
@keyframes dictia-rec-pulse { 0%, 100% { opacity: 0.5; box-shadow: 0 0 0 0 rgba(239,68,68,0.6); } 50% { opacity: 1; box-shadow: 0 0 0 4px rgba(239,68,68,0); } }
|
||||
|
||||
/* Waveform bars */
|
||||
.dictia-wave-bar { animation: dictia-wave 0.9s ease-in-out infinite; will-change: transform; transform-origin: bottom; }
|
||||
@keyframes dictia-wave { 0%, 100% { transform: scaleY(0.3); } 50% { transform: scaleY(1); } }
|
||||
|
||||
/* Slide-up + fade-in (diarisation messages) */
|
||||
.dictia-msg-in { animation: dictia-fade-up 0.3s ease-out both; }
|
||||
@keyframes dictia-fade-up { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
|
||||
|
||||
/* Typing indicator (3 dots) */
|
||||
.dictia-typing-dot { animation: dictia-typing 1.2s ease-in-out infinite; }
|
||||
@keyframes dictia-typing { 0%, 60%, 100% { opacity: 0.25; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-2px); } }
|
||||
|
||||
/* Spring pop (langues, exports, users, share) */
|
||||
.dictia-spring { animation: dictia-spring-pop 0.28s cubic-bezier(0.34, 1.56, 0.64, 1) both; }
|
||||
@keyframes dictia-spring-pop { 0% { opacity: 0; transform: scale(0.5); } 80% { transform: scale(1.08); } 100% { opacity: 1; transform: scale(1); } }
|
||||
@@ -291,59 +358,204 @@
|
||||
.dictia-fade-y { animation: dictia-fade-y 0.3s ease-out both; }
|
||||
@keyframes dictia-fade-y { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
|
||||
|
||||
/* Mode wrapper fade */
|
||||
.dictia-mode-fade { animation: dictia-mode-fade 0.22s ease-out both; }
|
||||
@keyframes dictia-mode-fade { from { opacity: 0; } to { opacity: 1; } }
|
||||
/* Mode wrapper crossfade + scale */
|
||||
.dictia-mode-fade {
|
||||
animation: dictia-mode-crossfade 0.32s cubic-bezier(0.4, 0, 0.2, 1) both;
|
||||
will-change: opacity, transform;
|
||||
}
|
||||
@keyframes dictia-mode-crossfade {
|
||||
from { opacity: 0; transform: scale(0.96); }
|
||||
to { opacity: 1; transform: scale(1); }
|
||||
}
|
||||
|
||||
/* Lang highlight pulse (random langs glow) */
|
||||
.dictia-lang-highlight { animation: dictia-lang-glow 2.4s ease-in-out infinite; }
|
||||
@keyframes dictia-lang-glow {
|
||||
0%, 100% { box-shadow: 0 0 0 0 currentColor; filter: brightness(1); }
|
||||
50% { box-shadow: 0 0 8px 1px currentColor; filter: brightness(1.4); }
|
||||
}
|
||||
|
||||
/* Connecting line (phone -> IA panel) */
|
||||
.dictia-connecting-line { animation: dictia-flow 3s linear infinite; }
|
||||
@keyframes dictia-flow { from { stroke-dashoffset: 24; } to { stroke-dashoffset: 0; } }
|
||||
|
||||
/* Auto pill */
|
||||
.dictia-auto-pulse { animation: dictia-auto-pulse-anim 1.6s ease-in-out infinite; }
|
||||
@keyframes dictia-auto-pulse-anim { 0%, 100% { transform: scale(1); opacity: 0.7; } 50% { transform: scale(1.4); opacity: 1; } }
|
||||
|
||||
/* Manuel countdown bar */
|
||||
.dictia-countdown-fill { animation: dictia-countdown 4.5s linear forwards; }
|
||||
@keyframes dictia-countdown { from { width: 100%; } to { width: 0%; } }
|
||||
|
||||
/* Feature info card hover */
|
||||
.dictia-feature-card { transition: transform 0.25s ease, box-shadow 0.25s ease; }
|
||||
.dictia-feature-card:hover { transform: translateY(-1px); }
|
||||
|
||||
/* Bottom feature button (tab indicator) */
|
||||
.dictia-feat-btn { transition: transform 0.18s ease, background-color 0.2s ease, opacity 0.2s ease; will-change: transform; }
|
||||
.dictia-feat-btn:hover { transform: scale(1.08); opacity: 1 !important; }
|
||||
|
||||
/* Hide scrollbar mobile pills */
|
||||
.dictia-hide-scrollbar::-webkit-scrollbar { display: none; }
|
||||
|
||||
/* ============ MOBILE OPTIMIZATIONS ============ */
|
||||
@media (max-width: 767px) {
|
||||
.dictia-statusbar,
|
||||
.dictia-speaker-grille,
|
||||
.dictia-camera-dot,
|
||||
.dictia-notch,
|
||||
.dictia-sound-ring,
|
||||
.dictia-connecting-line-wrap,
|
||||
.dictia-bg-orbs,
|
||||
.dictia-bg-grid,
|
||||
.dictia-wave-bar { display: none !important; }
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.dictia-mic-pulse, .ia-ambient-glow, .ia-brain-glow, .ia-local-badge,
|
||||
.dictia-blink, .dictia-dot-pulse, .dictia-msg-in, .dictia-spring,
|
||||
.dictia-spring-y, .dictia-fade-x, .dictia-fade-y, .dictia-mode-fade { animation: none; }
|
||||
.dictia-spring-y, .dictia-fade-x, .dictia-fade-y, .dictia-mode-fade,
|
||||
.dictia-sound-ring, .dictia-orb-float-1, .dictia-orb-float-2,
|
||||
.dictia-phone-glow-ring, .dictia-rec-dot, .dictia-wave-bar,
|
||||
.dictia-typing-dot, .dictia-lang-highlight, .dictia-connecting-line,
|
||||
.dictia-auto-pulse, .dictia-countdown-fill { animation: none !important; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<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-3 inline-flex items-center gap-2 justify-center">
|
||||
{# Decorative background : grid + floating orbs (desktop only) #}
|
||||
<div class="dictia-bg-grid absolute inset-0 dictia-section-grid pointer-events-none" aria-hidden="true"></div>
|
||||
<div class="dictia-bg-orbs absolute inset-0 pointer-events-none overflow-hidden" aria-hidden="true">
|
||||
<div class="dictia-orb-float-1 absolute" style="top:15%;left:8%;width:200px;height:200px;background:radial-gradient(circle, rgba(34,211,238,0.15) 0%, transparent 70%);filter:blur(60px);"></div>
|
||||
<div class="dictia-orb-float-2 absolute" style="bottom:10%;right:10%;width:240px;height:240px;background:radial-gradient(circle, rgba(167,139,250,0.18) 0%, transparent 70%);filter:blur(70px);"></div>
|
||||
</div>
|
||||
|
||||
<div class="max-w-[1200px] mx-auto px-6 relative">
|
||||
<div class="text-center max-w-2xl mx-auto mb-10">
|
||||
<p class="eyebrow grad-text mb-4 inline-flex items-center gap-2 justify-center px-3 py-1 rounded-full"
|
||||
style="background:linear-gradient(135deg, rgba(34,211,238,0.10), rgba(167,139,250,0.10)); border:1px solid rgba(167,139,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" aria-hidden="true">
|
||||
<circle cx="12" cy="12" r="3"/>
|
||||
<path d="M19.4 15a1.7 1.7 0 0 0 .3 1.9l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.9-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1-1.5 1.7 1.7 0 0 0-1.9.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.9 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1 1.7 1.7 0 0 0-.3-1.9l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.9.3h.1a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.9-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.9v.1a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z"/>
|
||||
</svg>
|
||||
COMMENT ÇA MARCHE
|
||||
</p>
|
||||
<h2 id="how-it-works-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black text-brand-navy mb-3">
|
||||
<h2 id="how-it-works-title" class="text-[clamp(2rem,3vw,2.75rem)] font-black text-brand-navy mb-4 leading-tight">
|
||||
Du fichier au résumé — <span class="grad-text">en temps réel</span>
|
||||
</h2>
|
||||
<p class="text-base text-brand-navy/70">
|
||||
<p class="text-base text-brand-navy/70 mb-5">
|
||||
Survolez une fonctionnalité pour voir la machine en action. Glissez pour calculer votre gain de productivité.
|
||||
<a href="/contact" class="grad-text font-semibold hover:underline whitespace-nowrap ml-1">Voir une démo →</a>
|
||||
</p>
|
||||
{# Stats row #}
|
||||
<div class="flex flex-wrap items-center justify-center gap-x-8 gap-y-3 text-brand-navy">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-2xl font-black grad-text">6</span>
|
||||
<span class="text-xs font-medium text-brand-navy/60 uppercase tracking-wider">modules</span>
|
||||
</div>
|
||||
<div class="w-px h-6 bg-brand-navy/15 hidden sm:block" aria-hidden="true"></div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-2xl font-black grad-text">99+</span>
|
||||
<span class="text-xs font-medium text-brand-navy/60 uppercase tracking-wider">langues</span>
|
||||
</div>
|
||||
<div class="w-px h-6 bg-brand-navy/15 hidden sm:block" aria-hidden="true"></div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-2xl font-black grad-text">0</span>
|
||||
<span class="text-xs font-medium text-brand-navy/60 uppercase tracking-wider">cloud</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# ── DASHBOARD HOLOGRAPHIQUE — 2 colonnes (phone center + IA right) ── #}
|
||||
<div x-data="dictiaDashboard()" x-init="init()"
|
||||
class="w-full flex flex-col lg:flex-row lg:justify-center lg:items-start gap-6 lg:gap-10">
|
||||
class="w-full flex flex-col lg:flex-row lg:justify-center lg:items-start gap-6 lg:gap-10 relative">
|
||||
|
||||
{# Connecting line SVG (phone -> IA panel, desktop only) #}
|
||||
<div class="dictia-connecting-line-wrap absolute pointer-events-none hidden lg:block"
|
||||
style="top:200px;left:50%;transform:translateX(-50%);width:160px;height:2px;z-index:1;"
|
||||
aria-hidden="true">
|
||||
<svg width="160" height="2" viewBox="0 0 160 2" preserveAspectRatio="none">
|
||||
<defs>
|
||||
<linearGradient id="dictia-connecting-grad" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" stop-color="#22D3EE" stop-opacity="0.6"/>
|
||||
<stop offset="100%" stop-color="#A78BFA" stop-opacity="0.6"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<line x1="0" y1="1" x2="160" y2="1" stroke="url(#dictia-connecting-grad)"
|
||||
stroke-width="1.5" stroke-dasharray="4 4" class="dictia-connecting-line"/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
{# ─────────── ZONE CENTER : Phone container ─────────── #}
|
||||
<div class="flex flex-col items-center gap-3 lg:w-[280px] flex-shrink-0">
|
||||
<div class="flex flex-col items-center gap-3 lg:w-[290px] flex-shrink-0 relative z-10">
|
||||
|
||||
{# Phone (border-radius 44px, color tinting selon feature active) #}
|
||||
<div class="w-full max-w-[260px] mx-auto flex flex-col overflow-hidden relative"
|
||||
:style="`border-radius: 44px; border: 1.5px solid ${activeColor}33; background: rgba(8,12,24,0.8); box-shadow: 0 0 56px ${activeColor}1A, inset 0 0 28px ${activeColor}0A; min-height: 460px; transition: border-color 0.4s, box-shadow 0.4s;`">
|
||||
{# Phone shell (bezel, glow ring, drop shadow) #}
|
||||
<div class="relative w-full max-w-[290px] mx-auto">
|
||||
|
||||
{# External glow ring (pulse) #}
|
||||
<div class="absolute -inset-2 pointer-events-none dictia-phone-glow-ring"
|
||||
:style="`border-radius: 52px; background: radial-gradient(ellipse 80% 90% at 50% 50%, ${activeColor}28 0%, transparent 60%); transition: background 0.4s;`"
|
||||
aria-hidden="true"></div>
|
||||
|
||||
<div class="dictia-phone-shell w-full flex flex-col overflow-hidden relative"
|
||||
:style="`border: 1.5px solid ${activeColor}40; background: rgba(8,12,24,0.88); box-shadow: 0 30px 80px -20px rgba(0,0,0,0.6), 0 12px 32px -8px ${activeColor}30, inset 0 0 32px ${activeColor}10; min-height: 540px; transition: border-color 0.4s, box-shadow 0.4s;`">
|
||||
|
||||
{# Ambient color tint overlay #}
|
||||
<div class="absolute inset-0 pointer-events-none"
|
||||
:style="`border-radius: 44px; background-color: ${activeColor}06; transition: background-color 0.4s;`"
|
||||
:style="`border-radius: 44px; background-color: ${activeColor}08; transition: background-color 0.4s;`"
|
||||
aria-hidden="true"></div>
|
||||
|
||||
{# TOP : Logo + Mic pulsing #}
|
||||
{# Notch / Dynamic Island (desktop only via mobile media) #}
|
||||
<div class="dictia-notch absolute left-1/2 -translate-x-1/2 z-30"
|
||||
style="top:8px;width:62px;height:6px;border-radius:6px;background:rgba(0,0,0,0.7);"
|
||||
aria-hidden="true"></div>
|
||||
|
||||
{# Status bar mobile-style (9:41 + signals) #}
|
||||
<div class="dictia-statusbar relative z-20 flex items-center justify-between px-5 pt-1"
|
||||
style="height:20px;font-family:ui-monospace,monospace;color:rgba(255,255,255,0.55);font-size:9px;font-weight:600;"
|
||||
aria-hidden="true">
|
||||
<span>9:41</span>
|
||||
<div class="flex items-center gap-1">
|
||||
{# Signal #}
|
||||
<svg viewBox="0 0 14 10" width="11" height="8" fill="currentColor">
|
||||
<rect x="0" y="7" width="2" height="3" rx="0.5"/>
|
||||
<rect x="3" y="5" width="2" height="5" rx="0.5"/>
|
||||
<rect x="6" y="3" width="2" height="7" rx="0.5"/>
|
||||
<rect x="9" y="0" width="2" height="10" rx="0.5"/>
|
||||
</svg>
|
||||
{# Wifi #}
|
||||
<svg viewBox="0 0 14 10" width="11" height="8" fill="none" stroke="currentColor" stroke-width="1.4">
|
||||
<path d="M1 4 Q7 -1 13 4"/>
|
||||
<path d="M3 6 Q7 3 11 6"/>
|
||||
<circle cx="7" cy="9" r="0.8" fill="currentColor"/>
|
||||
</svg>
|
||||
{# Battery #}
|
||||
<svg viewBox="0 0 18 8" width="14" height="7" fill="none" stroke="currentColor" stroke-width="0.8">
|
||||
<rect x="0" y="0" width="14" height="8" rx="1.5"/>
|
||||
<rect x="14.5" y="3" width="1" height="2" rx="0.4" fill="currentColor"/>
|
||||
<rect x="1.5" y="1.5" width="9" height="5" rx="0.5" fill="currentColor"/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Speaker grille + camera (top of screen, below notch) #}
|
||||
<div class="dictia-speaker-grille absolute z-10 flex items-center justify-center gap-2"
|
||||
style="top:32px;left:50%;transform:translateX(-50%);width:80px;height:8px;"
|
||||
aria-hidden="true">
|
||||
<div style="width:24px;height:2px;background:rgba(255,255,255,0.10);border-radius:2px;"></div>
|
||||
<div class="dictia-camera-dot" style="width:4px;height:4px;border-radius:50%;background:rgba(255,255,255,0.18);box-shadow:inset 0 0 1px rgba(0,0,0,0.5);"></div>
|
||||
</div>
|
||||
|
||||
{# TOP : Logo + Mic pulsing (with sound waves) #}
|
||||
<div class="flex flex-col items-center justify-center gap-2 relative z-10"
|
||||
style="height: 96px; border-bottom: 1px solid rgba(255,255,255,0.06);">
|
||||
style="height: 100px; padding-top: 24px; border-bottom: 1px solid rgba(255,255,255,0.06);">
|
||||
<img src="/static/images/dictia-logo-nom.png" alt="DictIA"
|
||||
style="width: 80px; height: 24px; object-fit: contain; opacity: 0.75;">
|
||||
<span class="dictia-mic-pulse" :style="`color: ${activeColor};`" aria-hidden="true">
|
||||
<div class="relative" style="width:36px;height:36px;">
|
||||
{# 3 sound rings emanating #}
|
||||
<span class="dictia-sound-ring r1" :style="`color: ${activeColor}; width:24px; height:24px;`" aria-hidden="true"></span>
|
||||
<span class="dictia-sound-ring r2" :style="`color: ${activeColor}; width:24px; height:24px;`" aria-hidden="true"></span>
|
||||
<span class="dictia-sound-ring r3" :style="`color: ${activeColor}; width:24px; height:24px;`" aria-hidden="true"></span>
|
||||
<span class="dictia-mic-pulse absolute" style="top:50%;left:50%;transform:translate(-50%,-50%);" :style="`color: ${activeColor};`" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:22px;height:22px;">
|
||||
<rect x="9" y="2" width="6" height="12" rx="3"/>
|
||||
<path d="M19 10v2a7 7 0 0 1-14 0v-2"/>
|
||||
@@ -352,15 +564,48 @@
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# MIDDLE : 6 modes (1=Transcription, 2=Diarisation, 3=Langues, 4=Exports, 5=Users, 6=Share, 0=IA chat) #}
|
||||
<div class="flex-1 relative z-10" style="min-height: 220px;"
|
||||
<div class="flex-1 relative z-10" style="min-height: 260px;"
|
||||
role="status" aria-live="polite" aria-atomic="true">
|
||||
|
||||
{# Mode 1 : Transcription (upload bar + words appearing) #}
|
||||
{# Mode 1 : Transcription (header REC + waveform + upload bar + words) #}
|
||||
<template x-if="displayMode === 1">
|
||||
<div class="dictia-mode-fade w-full h-full" x-data="trModeData()" x-init="init()">
|
||||
<div x-show="phase === 'upload'" class="w-full h-full flex flex-col items-center justify-center gap-3 px-4">
|
||||
<div class="dictia-mode-fade w-full h-full flex flex-col" x-data="trModeData()" x-init="init()">
|
||||
{# Header bar (file + REC) #}
|
||||
<div class="flex items-center justify-between px-2.5 py-1.5"
|
||||
style="background:rgba(34,211,238,0.06);border-bottom:1px solid rgba(34,211,238,0.12);">
|
||||
<div class="flex items-center gap-1.5">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:8px;height:8px;color:rgba(34,211,238,0.80);" 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"/>
|
||||
</svg>
|
||||
<span style="font-size:6.5px;font-family:monospace;color:rgba(255,255,255,0.55);">reunion-jan14.mp3</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="dictia-rec-dot" style="width:5px;height:5px;border-radius:50%;background:#EF4444;"></span>
|
||||
<span style="font-size:6px;font-family:monospace;color:rgba(239,68,68,0.85);letter-spacing:0.08em;font-weight:700;">REC</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Waveform animée (8 bars) #}
|
||||
<div class="flex items-end justify-center gap-0.5 px-3 py-2" style="height:24px;" aria-hidden="true">
|
||||
<div class="dictia-wave-bar" style="width:2px;height:14px;background:#22D3EE;animation-delay:0s;"></div>
|
||||
<div class="dictia-wave-bar" style="width:2px;height:18px;background:#22D3EE;animation-delay:0.1s;"></div>
|
||||
<div class="dictia-wave-bar" style="width:2px;height:10px;background:#22D3EE;animation-delay:0.2s;"></div>
|
||||
<div class="dictia-wave-bar" style="width:2px;height:20px;background:#22D3EE;animation-delay:0.05s;"></div>
|
||||
<div class="dictia-wave-bar" style="width:2px;height:12px;background:#22D3EE;animation-delay:0.25s;"></div>
|
||||
<div class="dictia-wave-bar" style="width:2px;height:16px;background:#22D3EE;animation-delay:0.15s;"></div>
|
||||
<div class="dictia-wave-bar" style="width:2px;height:8px;background:#22D3EE;animation-delay:0.3s;"></div>
|
||||
<div class="dictia-wave-bar" style="width:2px;height:14px;background:#22D3EE;animation-delay:0.08s;"></div>
|
||||
<div class="dictia-wave-bar" style="width:2px;height:18px;background:#22D3EE;animation-delay:0.22s;"></div>
|
||||
<div class="dictia-wave-bar" style="width:2px;height:10px;background:#22D3EE;animation-delay:0.18s;"></div>
|
||||
<div class="dictia-wave-bar" style="width:2px;height:14px;background:#22D3EE;animation-delay:0s;"></div>
|
||||
<div class="dictia-wave-bar" style="width:2px;height:6px;background:#22D3EE;animation-delay:0.12s;"></div>
|
||||
</div>
|
||||
|
||||
<div x-show="phase === 'upload'" class="flex-1 flex flex-col items-center justify-center gap-3 px-4">
|
||||
<div class="flex flex-col items-center gap-1.5">
|
||||
<div class="w-10 h-12 rounded-md flex flex-col items-center justify-center relative"
|
||||
style="background-color: rgba(34,211,238,0.12); border: 1.5px solid rgba(34,211,238,0.40);">
|
||||
@@ -372,21 +617,21 @@
|
||||
</svg>
|
||||
<span style="font-size:5.5px;font-family:monospace;color:rgba(34,211,238,0.70);letter-spacing:0.06em;">MP3</span>
|
||||
</div>
|
||||
<span style="font-size:7px;font-family:monospace;color:rgba(255,255,255,0.42);">reunion-jan14.mp3</span>
|
||||
</div>
|
||||
<div class="w-full flex flex-col gap-1">
|
||||
<div class="flex justify-between">
|
||||
<span style="font-size:6.5px;font-family:monospace;color:rgba(34,211,238,0.65);" x-text="progress < 100 ? 'Envoi en cours…' : 'Prêt ✓'"></span>
|
||||
<span style="font-size:6.5px;font-family:monospace;color:rgba(34,211,238,0.50);"><span x-text="progress"></span>%</span>
|
||||
</div>
|
||||
<div class="w-full rounded-full overflow-hidden" style="height:3px;background-color:rgba(34,211,238,0.10);">
|
||||
<div class="h-full rounded-full" :style="`width: ${progress}%; background-color: #22D3EE; transition: width 60ms linear;`"></div>
|
||||
{# Double progress bar (track + active with glow) #}
|
||||
<div class="w-full rounded-full overflow-hidden relative" style="height:4px;background-color:rgba(34,211,238,0.10);box-shadow:inset 0 0 2px rgba(0,0,0,0.4);">
|
||||
<div class="h-full rounded-full" :style="`width: ${progress}%; background: linear-gradient(90deg, #22D3EE, #06B6D4); box-shadow: 0 0 6px rgba(34,211,238,0.6); transition: width 60ms linear;`"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div x-show="phase === 'transcribing'" class="w-full h-full p-3 overflow-hidden flex flex-col justify-start">
|
||||
<p class="font-mono leading-relaxed break-words" style="font-size:9px;color:rgba(34,211,238,0.90);">
|
||||
<span x-text="words.slice(0, n + 1).join(' ')"></span><span class="dictia-blink ml-px" style="color:#22D3EE;">▌</span>
|
||||
<div x-show="phase === 'transcribing'" class="flex-1 p-3 overflow-y-auto flex flex-col justify-start">
|
||||
<p class="font-mono leading-relaxed break-words" style="font-size:9px;color:rgba(34,211,238,0.92);background:rgba(34,211,238,0.04);padding:4px 6px;border-radius:6px;border-left:2px solid rgba(34,211,238,0.4);">
|
||||
<span x-text="words.slice(0, n + 1).join(' ')"></span><span class="dictia-blink ml-px" style="color:#22D3EE;display:inline-block;width:3px;background:#22D3EE;height:9px;vertical-align:middle;"> </span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -394,77 +639,190 @@
|
||||
|
||||
{# Mode 2 : Diarisation (conversation Sophie/Marc/Julie) #}
|
||||
<template x-if="displayMode === 2">
|
||||
<div class="dictia-mode-fade w-full h-full flex flex-col justify-end gap-1.5 p-2 overflow-hidden" x-data="diaModeData()" x-init="init()">
|
||||
<div class="dictia-mode-fade w-full h-full flex flex-col" x-data="diaModeData()" x-init="init()">
|
||||
{# Conversation header with stacked avatars #}
|
||||
<div class="flex items-center justify-between px-2.5 py-1.5"
|
||||
style="background:rgba(107,159,255,0.06);border-bottom:1px solid rgba(107,159,255,0.12);">
|
||||
<div class="flex items-center gap-1.5">
|
||||
<div class="flex" style="margin-right:2px;">
|
||||
<div class="rounded-full flex items-center justify-center text-[7px] font-bold"
|
||||
style="width:14px;height:14px;background:linear-gradient(135deg,#22D3EE,#0891B2);border:1.5px solid rgba(8,12,24,0.9);color:#fff;">S</div>
|
||||
<div class="rounded-full flex items-center justify-center text-[7px] font-bold"
|
||||
style="width:14px;height:14px;background:linear-gradient(135deg,#6B9FFF,#3B82F6);border:1.5px solid rgba(8,12,24,0.9);color:#fff;margin-left:-5px;">M</div>
|
||||
<div class="rounded-full flex items-center justify-center text-[7px] font-bold"
|
||||
style="width:14px;height:14px;background:linear-gradient(135deg,#F59E0B,#D97706);border:1.5px solid rgba(8,12,24,0.9);color:#fff;margin-left:-5px;">J</div>
|
||||
</div>
|
||||
<span style="font-size:6.5px;font-family:monospace;color:rgba(255,255,255,0.65);">Réunion · 3 participants</span>
|
||||
</div>
|
||||
<span class="dictia-rec-dot" style="width:5px;height:5px;border-radius:50%;background:#34D399;"></span>
|
||||
</div>
|
||||
<div class="flex-1 flex flex-col justify-end gap-1.5 p-2 overflow-hidden">
|
||||
<template x-for="(msg, i) in visible" :key="`${cycle}-${startIdx + i}`">
|
||||
<div class="dictia-msg-in flex items-start gap-1.5">
|
||||
<div class="rounded-full flex items-center justify-center text-[8px] font-bold shrink-0 mt-0.5"
|
||||
style="width:20px;height:20px;"
|
||||
:style="`background-color: ${msg.c}28; border: 1px solid ${msg.c}55; color: ${msg.c};`"
|
||||
<div class="rounded-full flex items-center justify-center text-[10px] font-bold shrink-0 mt-0.5"
|
||||
style="width:24px;height:24px;"
|
||||
:style="`background:linear-gradient(135deg, ${msg.c}33, ${msg.c}22); border: 1.5px solid ${msg.c}66; color: ${msg.c};`"
|
||||
x-text="msg.s.charAt(0)"></div>
|
||||
<div class="rounded-lg px-2 py-1 flex-1"
|
||||
:style="`background-color: ${msg.c}10; border: 1px solid ${msg.c}22;`">
|
||||
<p class="text-[8px] font-bold leading-none mb-0.5" :style="`color: ${msg.c};`" x-text="msg.s"></p>
|
||||
<p class="text-[8px] font-mono leading-snug" style="color:rgba(255,255,255,0.75);" x-text="msg.t"></p>
|
||||
<div class="rounded-lg px-2 py-1.5 flex-1 relative"
|
||||
:style="`background-color: ${msg.c}10; border: 1px solid ${msg.c}28; box-shadow: 0 1px 4px rgba(0,0,0,0.15);`">
|
||||
<div class="flex items-baseline justify-between gap-2 mb-0.5">
|
||||
<p class="text-[8.5px] font-bold leading-none" :style="`color: ${msg.c};`" x-text="msg.s"></p>
|
||||
<span class="text-[6.5px] font-mono" style="color:rgba(255,255,255,0.30);" x-text="`09:0${i+1}`"></span>
|
||||
</div>
|
||||
<p class="text-[8.5px] font-mono leading-snug" style="color:rgba(255,255,255,0.78);" x-text="msg.t"></p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
{# Typing indicator #}
|
||||
<div class="flex items-center gap-1.5 px-1" x-show="shownCount < CONVO.length" aria-hidden="true">
|
||||
<div class="rounded-full" style="width:24px;height:24px;background:rgba(255,255,255,0.05);border:1px dashed rgba(255,255,255,0.15);"></div>
|
||||
<div class="flex items-center gap-1 rounded-lg px-2 py-1.5"
|
||||
style="background:rgba(255,255,255,0.04);border:1px solid rgba(255,255,255,0.08);">
|
||||
<span class="dictia-typing-dot" style="width:4px;height:4px;border-radius:50%;background:rgba(255,255,255,0.5);animation-delay:0s;"></span>
|
||||
<span class="dictia-typing-dot" style="width:4px;height:4px;border-radius:50%;background:rgba(255,255,255,0.5);animation-delay:0.2s;"></span>
|
||||
<span class="dictia-typing-dot" style="width:4px;height:4px;border-radius:50%;background:rgba(255,255,255,0.5);animation-delay:0.4s;"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
{# Mode 3 : 99+ langues (grille 100 codes staggered 12ms) #}
|
||||
{# Mode 3 : 99+ langues (grille 100 codes — ripple depuis centre, highlight aléatoire) #}
|
||||
<template x-if="displayMode === 3">
|
||||
<div class="dictia-mode-fade w-full h-full overflow-hidden" style="padding:6px 5px;" x-data="langModeData()">
|
||||
<div class="dictia-mode-fade w-full h-full flex flex-col" x-data="langModeData()">
|
||||
{# Header DÉTECTION AUTOMATIQUE #}
|
||||
<div class="flex items-center justify-center gap-1.5 py-1.5"
|
||||
style="background:rgba(34,211,238,0.06);border-bottom:1px solid rgba(34,211,238,0.12);">
|
||||
<span class="dictia-dot-pulse" style="width:5px;height:5px;border-radius:50%;background:#22D3EE;"></span>
|
||||
<span style="font-size:7px;font-family:monospace;color:rgba(34,211,238,0.85);letter-spacing:0.16em;font-weight:700;">DÉTECTION AUTOMATIQUE</span>
|
||||
</div>
|
||||
<div class="flex-1 overflow-hidden" style="padding:6px 5px;">
|
||||
<div class="grid content-start" style="grid-template-columns: repeat(7, 1fr); gap: 3px;">
|
||||
<template x-for="(lang, i) in LANGS" :key="lang">
|
||||
<span class="font-mono font-bold text-center rounded dictia-spring"
|
||||
:style="`font-size:6.5px;line-height:14px;background-color:${LANG_COLORS[i % LANG_COLORS.length]}12;border:1px solid ${LANG_COLORS[i % LANG_COLORS.length]}28;color:${LANG_COLORS[i % LANG_COLORS.length]};animation-delay:${i * 12}ms;`"
|
||||
:class="HIGHLIGHTS.includes(i) ? 'dictia-lang-highlight' : ''"
|
||||
:style="`font-size:6.5px;line-height:16px;background-color:${LANG_COLORS[i % LANG_COLORS.length]}14;border:1px solid ${LANG_COLORS[i % LANG_COLORS.length]}30;color:${LANG_COLORS[i % LANG_COLORS.length]};animation-delay:${rippleDelay(i)}ms;`"
|
||||
x-text="lang"></span>
|
||||
</template>
|
||||
</div>
|
||||
<p class="text-center font-mono font-bold mt-2 dictia-fade-y"
|
||||
style="font-size:8px;color:#22D3EE;letter-spacing:0.1em;animation-delay:1.4s;">
|
||||
</div>
|
||||
{# Counter live en bas #}
|
||||
<div class="flex items-center justify-between px-2.5 py-1.5 mt-auto"
|
||||
style="background:rgba(34,211,238,0.04);border-top:1px solid rgba(34,211,238,0.10);">
|
||||
<span class="font-mono dictia-fade-y" style="font-size:6.5px;color:rgba(34,211,238,0.75);letter-spacing:0.06em;animation-delay:1.4s;">
|
||||
FR · EN · ES · DE · ZH · JA · AR · ...
|
||||
</span>
|
||||
<span class="font-mono font-bold dictia-fade-y" style="font-size:7.5px;color:#22D3EE;letter-spacing:0.1em;animation-delay:1.4s;">
|
||||
99+ langues détectées
|
||||
</p>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
{# Mode 4 : Exports (7 file icons spring stagger 90ms) #}
|
||||
{# Mode 4 : Exports (grid 4x2 + files détaillés + checkmark) #}
|
||||
<template x-if="displayMode === 4">
|
||||
<div class="dictia-mode-fade w-full h-full p-3 flex flex-wrap gap-2 items-center justify-center" x-data="expModeData()">
|
||||
<div class="dictia-mode-fade w-full h-full flex flex-col" x-data="expModeData()">
|
||||
{# Header subtle #}
|
||||
<div class="flex items-center justify-between px-2.5 py-1.5"
|
||||
style="background:rgba(107,159,255,0.06);border-bottom:1px solid rgba(107,159,255,0.12);">
|
||||
<span style="font-size:7px;font-family:monospace;color:rgba(107,159,255,0.85);letter-spacing:0.14em;font-weight:700;">EXPORTS DISPONIBLES</span>
|
||||
</div>
|
||||
|
||||
{# Grid 4×2 #}
|
||||
<div class="grid grid-cols-4 gap-2 p-3 flex-1 content-center justify-items-center">
|
||||
<template x-for="(f, i) in FILE_TYPES" :key="f.ext">
|
||||
<div class="dictia-spring-y" :style="`animation-delay:${i * 90}ms;`">
|
||||
<div class="w-10 h-12 rounded-md flex flex-col items-center justify-center gap-0.5 relative"
|
||||
<div class="dictia-spring-y" :style="`animation-delay:${i * 110}ms;`">
|
||||
<div class="rounded-md flex flex-col items-center justify-end gap-0.5 relative"
|
||||
style="width:38px;height:46px;"
|
||||
:style="`background-color:${f.bg}CC;border:1.5px solid ${f.bg};box-shadow:0 4px 12px ${f.bg}40;`">
|
||||
<div class="absolute top-0 right-0" style="width:0;height:0;border-style:solid;border-width:0 7px 7px 0;border-color:transparent rgba(0,0,0,0.35) transparent transparent;"></div>
|
||||
<span class="text-[10px] font-black leading-none" :style="`color:${f.fg};`" x-text="f.sym"></span>
|
||||
<span class="text-[7px] font-mono font-bold leading-none" :style="`color:${f.fg}BB;`" x-text="f.ext"></span>
|
||||
<div class="absolute top-0 right-0" style="width:0;height:0;border-style:solid;border-width:0 8px 8px 0;border-color:transparent rgba(0,0,0,0.40) transparent transparent;"></div>
|
||||
{# Mini "page" lines #}
|
||||
<div class="absolute top-2 left-1.5 right-3 flex flex-col gap-0.5" aria-hidden="true">
|
||||
<div :style="`height:1px;background:${f.fg}55;width:80%;`"></div>
|
||||
<div :style="`height:1px;background:${f.fg}40;width:65%;`"></div>
|
||||
<div :style="`height:1px;background:${f.fg}40;width:75%;`"></div>
|
||||
</div>
|
||||
<span class="text-[10px] font-black leading-none mb-0.5" :style="`color:${f.fg};margin-bottom:8px;`" x-text="f.sym"></span>
|
||||
<span class="text-[7px] font-mono font-bold leading-none mb-1" :style="`color:${f.fg}BB;`" x-text="f.ext"></span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
{# Subtitle dynamique avec checkmark #}
|
||||
<div class="flex items-center justify-center gap-1.5 px-2.5 py-1.5 mt-auto dictia-fade-y"
|
||||
style="background:rgba(52,211,153,0.06);border-top:1px solid rgba(52,211,153,0.14);animation-delay:0.9s;">
|
||||
<span style="width:11px;height:11px;border-radius:50%;background:#34D399;display:inline-flex;align-items:center;justify-content:center;">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="rgba(8,12,24,0.9)" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" style="width:7px;height:7px;" aria-hidden="true">
|
||||
<polyline points="20 6 9 17 4 12"/>
|
||||
</svg>
|
||||
</span>
|
||||
<span style="font-size:7px;font-family:monospace;color:#34D399;letter-spacing:0.08em;font-weight:700;">7 FORMATS PRÊTS</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
{# Mode 5 : Users (avatars 1→20 multiplication 200ms) #}
|
||||
{# Mode 5 : Users (counter centré + avatars colors variés + connecting lines) #}
|
||||
<template x-if="displayMode === 5">
|
||||
<div class="dictia-mode-fade w-full h-full p-2 flex flex-wrap gap-1.5 items-center justify-center content-center" x-data="usersModeData()" x-init="init()">
|
||||
<div class="dictia-mode-fade w-full h-full flex flex-col" x-data="usersModeData()" x-init="init()">
|
||||
{# Header counter #}
|
||||
<div class="flex items-center justify-center gap-1.5 py-1.5"
|
||||
style="background:rgba(167,139,250,0.06);border-bottom:1px solid rgba(167,139,250,0.12);">
|
||||
<span style="font-size:7px;font-family:monospace;color:rgba(167,139,250,0.75);letter-spacing:0.14em;font-weight:700;">UTILISATEURS</span>
|
||||
<span class="font-mono font-black" style="font-size:11px;color:#A78BFA;letter-spacing:0.05em;" x-text="count.toString().padStart(2, '0')"></span>
|
||||
<span style="font-size:7px;font-family:monospace;color:rgba(167,139,250,0.45);">/ ∞</span>
|
||||
</div>
|
||||
|
||||
{# Avatar grid with connecting lines SVG #}
|
||||
<div class="flex-1 relative p-2 flex flex-wrap gap-1.5 items-center justify-center content-center">
|
||||
{# SVG connecting lines (desktop only via data attr) #}
|
||||
<svg class="absolute inset-0 pointer-events-none" width="100%" height="100%" aria-hidden="true" style="opacity:0.4;">
|
||||
<line x1="20%" y1="30%" x2="50%" y2="50%" stroke="#A78BFA" stroke-width="0.5" stroke-dasharray="2 2"/>
|
||||
<line x1="80%" y1="30%" x2="50%" y2="50%" stroke="#22D3EE" stroke-width="0.5" stroke-dasharray="2 2"/>
|
||||
<line x1="20%" y1="70%" x2="50%" y2="50%" stroke="#34D399" stroke-width="0.5" stroke-dasharray="2 2"/>
|
||||
<line x1="80%" y1="70%" x2="50%" y2="50%" stroke="#6B9FFF" stroke-width="0.5" stroke-dasharray="2 2"/>
|
||||
</svg>
|
||||
<template x-for="i in count" :key="`${cycle}-${i}`">
|
||||
<div class="rounded-full flex items-center justify-center"
|
||||
<div class="rounded-full flex items-center justify-center relative z-10"
|
||||
:class="i === count ? 'dictia-spring' : ''"
|
||||
style="width:24px;height:24px;background-color:#A78BFA22;border:1.5px solid #A78BFA66;">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:10px;height:10px;color:#A78BFA;" 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"/>
|
||||
<line x1="20" y1="8" x2="20" y2="14"/>
|
||||
<line x1="23" y1="11" x2="17" y2="11"/>
|
||||
:style="`width:24px;height:24px;background-color:${USER_COLORS[(i-1) % USER_COLORS.length]}22;border:1.5px solid ${USER_COLORS[(i-1) % USER_COLORS.length]}77;`">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:10px;height:10px;" :style="`color:${USER_COLORS[(i-1) % USER_COLORS.length]};`" aria-hidden="true">
|
||||
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/>
|
||||
<circle cx="12" cy="7" r="4"/>
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
{# Mode 6 : Share (folders + tags + files staggered) #}
|
||||
{# Mode 6 : Share (breadcrumb + toolbar + rows structurées) #}
|
||||
<template x-if="displayMode === 6">
|
||||
<div class="dictia-mode-fade w-full h-full flex flex-col gap-1.5" style="padding:8px 7px;">
|
||||
<div class="dictia-mode-fade w-full h-full flex flex-col">
|
||||
{# Breadcrumb #}
|
||||
<div class="flex items-center gap-1 px-2.5 py-1.5"
|
||||
style="background:rgba(52,211,153,0.06);border-bottom:1px solid rgba(52,211,153,0.12);">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:7px;height:7px;color:#34D399;" 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>
|
||||
<span style="font-size:6.5px;font-family:monospace;color:rgba(255,255,255,0.55);">Mes dossiers</span>
|
||||
<span style="font-size:6px;color:rgba(255,255,255,0.30);">›</span>
|
||||
<span style="font-size:6.5px;font-family:monospace;color:#34D399;font-weight:700;">Réunions</span>
|
||||
{# Toolbar mini #}
|
||||
<div class="flex items-center gap-1.5 ml-auto" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:8px;height:8px;color:rgba(255,255,255,0.40);">
|
||||
<circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>
|
||||
</svg>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:8px;height:8px;color:rgba(255,255,255,0.40);">
|
||||
<polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"/>
|
||||
</svg>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:8px;height:8px;color:rgba(255,255,255,0.40);">
|
||||
<path d="M3 6h18M3 12h18M3 18h18"/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex-1 flex flex-col gap-1.5" style="padding:6px 7px;">
|
||||
{# Folders #}
|
||||
<div class="flex gap-1 flex-wrap">
|
||||
<template x-for="(f, fi) in [{name:'Réunions',color:'#22D3EE',count:12},{name:'Entretiens',color:'#6B9FFF',count:7},{name:'Formations',color:'#34D399',count:24}]" :key="f.name">
|
||||
@@ -487,30 +845,33 @@
|
||||
x-text="tag"></span>
|
||||
</template>
|
||||
</div>
|
||||
{# Separator #}
|
||||
<div style="height:1px;background:rgba(255,255,255,0.05);margin:2px 0;"></div>
|
||||
{# File rows #}
|
||||
<div class="flex flex-col gap-1">
|
||||
{# File rows structurées #}
|
||||
<div class="flex flex-col gap-1 mt-0.5">
|
||||
<template x-for="(file, fi2) in [{name:'CR-Réunion-Jan14',folder:'Réunions',color:'#22D3EE'},{name:'Entretien-Sophie',folder:'Entretiens',color:'#6B9FFF'},{name:'Formation-RGPD',folder:'Formations',color:'#34D399'}]" :key="file.name">
|
||||
<div class="flex items-center gap-1.5 rounded-lg dictia-fade-x"
|
||||
:style="`background-color:${file.color}0C;border:1px solid ${file.color}22;padding:4px 6px;animation-delay:${650 + fi2 * 120}ms;`">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:7px;height:7px;" :style="`color:${file.color};`" aria-hidden="true">
|
||||
<div class="dictia-share-row group flex items-center gap-1.5 rounded-lg dictia-fade-x cursor-pointer"
|
||||
:style="`background-color:${file.color}0C;border:1px solid ${file.color}22;padding:4px 6px;animation-delay:${650 + fi2 * 120}ms;transition:background-color 0.2s;`">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:8px;height:8px;flex-shrink:0;" :style="`color:${file.color};`" 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"/>
|
||||
</svg>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="truncate" style="font-size:6px;font-family:monospace;color:rgba(255,255,255,0.70);" x-text="file.name"></p>
|
||||
<p style="font-size:5.5px;" :style="`color:${file.color}99;`" x-text="file.folder"></p>
|
||||
<p class="truncate" style="font-size:7px;font-family:monospace;color:rgba(255,255,255,0.78);" x-text="file.name"></p>
|
||||
</div>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:6px;height:6px;flex-shrink:0;" :style="`color:${file.color}66;`" aria-hidden="true">
|
||||
<circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/>
|
||||
<line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/>
|
||||
<span class="rounded font-mono shrink-0"
|
||||
style="font-size:5.5px;padding:1px 4px;"
|
||||
:style="`background:${file.color}18;color:${file.color};border:1px solid ${file.color}33;`"
|
||||
x-text="file.folder"></span>
|
||||
<span class="dictia-share-action shrink-0" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" fill="currentColor" style="width:8px;height:8px;" :style="`color:${file.color}77;`">
|
||||
<circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<p class="text-center font-mono mt-auto dictia-fade-y"
|
||||
style="font-size:6px;color:rgba(52,211,153,0.55);letter-spacing:0.08em;animation-delay:1.2s;">
|
||||
</div>
|
||||
<p class="text-center font-mono mt-auto dictia-fade-y px-2 py-1"
|
||||
style="font-size:6.5px;color:rgba(52,211,153,0.65);letter-spacing:0.08em;background:rgba(52,211,153,0.04);border-top:1px solid rgba(52,211,153,0.10);animation-delay:1.2s;">
|
||||
partage sécurisé · recherche plein texte
|
||||
</p>
|
||||
</div>
|
||||
@@ -544,43 +905,77 @@
|
||||
</template>
|
||||
</div>
|
||||
|
||||
{# BOTTOM : 6 feature icons (skip IA index 0) + auto-cycle status #}
|
||||
{# BOTTOM : 6 feature icons agrandis (28×28) + label + tab indicator + Auto pill #}
|
||||
<div class="relative flex flex-col items-center justify-center gap-2 z-10"
|
||||
style="height: 90px; border-top: 1px solid rgba(255,255,255,0.06);">
|
||||
<div class="flex items-center gap-3.5">
|
||||
style="height: 110px; border-top: 1px solid rgba(255,255,255,0.06); background: linear-gradient(180deg, transparent, rgba(0,0,0,0.30));">
|
||||
<div class="flex items-end gap-1.5">
|
||||
<template x-for="i in [1,2,3,4,5,6]" :key="i">
|
||||
<button type="button" @click="handleManualSelect(i)"
|
||||
class="outline-none p-0 cursor-pointer focus-visible:ring-2 focus-visible:ring-white/40 rounded"
|
||||
style="background:transparent;border:none;"
|
||||
class="dictia-feat-btn outline-none cursor-pointer focus-visible:ring-2 focus-visible:ring-white/40 rounded-md flex flex-col items-center justify-end relative"
|
||||
:style="`background-color: ${selectedFeature === i ? FEATURES[i].color + '14' : 'transparent'}; border:none; padding: 4px 5px 6px; opacity: ${selectedFeature === i ? 1 : 0.55}; min-width: 30px;`"
|
||||
:aria-pressed="selectedFeature === i ? 'true' : 'false'"
|
||||
:aria-label="`Voir : ${FEATURES[i].title}`">
|
||||
<span :style="`color: ${selectedFeature === i ? FEATURES[i].color : 'rgba(255,255,255,0.28)'}; transition: color 0.2s, transform 0.15s, filter 0.2s; filter: ${selectedFeature === i ? 'drop-shadow(0 0 6px ' + FEATURES[i].color + 'CC)' : 'none'}; transform: scale(${selectedFeature === i ? 1.3 : 1}); display: inline-block;`">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:15px;height:15px;" aria-hidden="true" x-html="featureIconPath(i)"></svg>
|
||||
<span :style="`color: ${selectedFeature === i ? FEATURES[i].color : 'rgba(255,255,255,0.42)'}; transition: color 0.2s, transform 0.15s, filter 0.2s; filter: ${selectedFeature === i ? 'drop-shadow(0 0 6px ' + FEATURES[i].color + 'CC)' : 'none'}; transform: scale(${selectedFeature === i ? 1.18 : 1}); display: inline-block;`">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:16px;height:16px;" aria-hidden="true" x-html="featureIconPath(i)"></svg>
|
||||
</span>
|
||||
<span class="text-[7px] font-medium mt-0.5 leading-none uppercase tracking-wide"
|
||||
:style="`color: ${selectedFeature === i ? FEATURES[i].color : 'rgba(255,255,255,0.30)'};`"
|
||||
x-text="featureShortLabel(i)"></span>
|
||||
{# Tab indicator bottom border #}
|
||||
<span x-show="selectedFeature === i" class="absolute" aria-hidden="true"
|
||||
:style="`bottom: 0; left: 4px; right: 4px; height: 2px; background: ${FEATURES[i].color}; border-radius: 1px; box-shadow: 0 0 6px ${FEATURES[i].color};`"></span>
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
<p class="text-[9px]" style="color:rgba(255,255,255,0.28);"
|
||||
x-text="isManual ? 'Cliquez pour changer · Auto reprend bientôt' : '● Auto'"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Feature info card sous le phone (toujours visible, change avec auto-cycle) #}
|
||||
<div style="min-height:54px;" class="w-full max-w-[260px]">
|
||||
<div class="rounded-xl px-3 py-2.5"
|
||||
:style="`background-color: ${activeColor}0E; border: 1px solid ${activeColor}33; box-shadow: 0 4px 20px ${activeColor}18;`">
|
||||
<div class="flex items-center gap-1.5 mb-1 flex-wrap">
|
||||
<span :style="`color: ${activeColor}; flex-shrink: 0;`" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:12px;height:12px;" x-html="featureIconPath(displayMode)"></svg>
|
||||
{# Auto pill / Manuel countdown #}
|
||||
<div class="flex items-center justify-center gap-1.5" style="min-height:14px;">
|
||||
<template x-if="!isManual">
|
||||
<span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full"
|
||||
style="background:rgba(52,211,153,0.10);border:1px solid rgba(52,211,153,0.25);">
|
||||
<span class="dictia-auto-pulse" style="width:5px;height:5px;border-radius:50%;background:#34D399;"></span>
|
||||
<span style="font-size:7px;font-family:monospace;color:#34D399;letter-spacing:0.12em;font-weight:700;">AUTO</span>
|
||||
</span>
|
||||
</template>
|
||||
<template x-if="isManual">
|
||||
<span class="inline-flex flex-col items-center gap-0.5">
|
||||
<span style="font-size:7.5px;font-family:monospace;color:rgba(255,255,255,0.55);" x-text="'Auto reprend bientôt'"></span>
|
||||
<span class="rounded-full overflow-hidden" style="width:50px;height:2px;background:rgba(255,255,255,0.10);">
|
||||
<span class="block dictia-countdown-fill h-full" :key="selectedFeature" style="background:linear-gradient(90deg,#22D3EE,#A78BFA);"></span>
|
||||
</span>
|
||||
</span>
|
||||
<span class="text-[11px] font-bold text-white" x-text="FEATURES[displayMode].title"></span>
|
||||
<template x-if="FEATURES[displayMode].badge">
|
||||
<span class="text-[8px] px-1.5 py-0.5 rounded font-mono font-bold"
|
||||
:style="`background-color: ${activeColor}1A; color: ${activeColor}; border: 1px solid ${activeColor}44;`"
|
||||
x-text="FEATURES[displayMode].badge"></span>
|
||||
</template>
|
||||
</div>
|
||||
<p class="text-[10px] leading-snug" style="color:rgba(255,255,255,0.52);" x-text="FEATURES[displayMode].subtitle"></p>
|
||||
</div>
|
||||
</div>{# /dictia-phone-shell #}
|
||||
</div>{# /phone wrapper (glow ring) #}
|
||||
|
||||
{# Feature info card sous le phone — premium look avec icon container + hover lift #}
|
||||
<div style="min-height:64px;" class="w-full max-w-[290px] mt-3">
|
||||
<div class="dictia-feature-card rounded-xl px-4 py-3 relative"
|
||||
:style="`background-color: ${activeColor}10; border: 1px solid ${activeColor}38; box-shadow: 0 6px 24px ${activeColor}1F;`">
|
||||
{# Badge top-right #}
|
||||
<template x-if="FEATURES[displayMode].badge">
|
||||
<span class="absolute text-[7.5px] px-1.5 py-0.5 rounded font-mono font-bold"
|
||||
style="top:8px;right:8px;letter-spacing:0.08em;"
|
||||
:style="`background-color: ${activeColor}22; color: ${activeColor}; border: 1px solid ${activeColor}55;`"
|
||||
x-text="FEATURES[displayMode].badge"></span>
|
||||
</template>
|
||||
<div class="flex items-start gap-2.5">
|
||||
{# Icon container 32×32 #}
|
||||
<span class="rounded-lg flex items-center justify-center flex-shrink-0"
|
||||
style="width:32px;height:32px;"
|
||||
:style="`background-color: ${activeColor}18; border: 1px solid ${activeColor}33;`"
|
||||
aria-hidden="true">
|
||||
<span :style="`color: ${activeColor};`">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:16px;height:16px;" x-html="featureIconPath(displayMode)"></svg>
|
||||
</span>
|
||||
</span>
|
||||
<div class="flex-1 min-w-0 pr-12">
|
||||
<p class="text-sm font-bold text-white leading-tight mb-0.5" x-text="FEATURES[displayMode].title"></p>
|
||||
<p class="text-[11px] leading-snug" style="color:rgba(255,255,255,0.62);" x-text="FEATURES[displayMode].subtitle"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -604,85 +999,124 @@
|
||||
</div>
|
||||
|
||||
{# ─────────── ZONE RIGHT : IA Mistral premium card + grid 6 features ─────────── #}
|
||||
<div class="flex flex-col gap-3 w-full lg:w-[300px] flex-shrink-0">
|
||||
<div class="flex flex-col gap-3 w-full lg:w-[320px] flex-shrink-0 relative z-10">
|
||||
|
||||
<div class="mb-1">
|
||||
<p class="text-[9px] font-medium uppercase tracking-[0.22em] mb-1" style="color:rgba(167,139,250,0.85);">Fonctions clés</p>
|
||||
<p class="font-bold text-base leading-snug text-brand-navy">Fonctionnalité</p>
|
||||
<div class="mb-1 flex items-center gap-2">
|
||||
<span class="block w-1 h-5 rounded-full" style="background:linear-gradient(180deg,#22D3EE,#A78BFA);" aria-hidden="true"></span>
|
||||
<div>
|
||||
<p class="text-[9px] font-medium uppercase tracking-[0.22em]" style="color:rgba(167,139,250,0.95);">Fonctions clés</p>
|
||||
<p class="font-bold text-base leading-snug text-brand-navy">Le moteur IA local</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# IA Mistral 7B premium card #}
|
||||
<div class="relative rounded-xl overflow-hidden"
|
||||
style="border:1.5px solid rgba(167,139,250,0.28);background-color:rgba(8,12,24,0.85);box-shadow:0 0 28px rgba(167,139,250,0.12);">
|
||||
style="border:1.5px solid rgba(167,139,250,0.32);background-color:rgba(8,12,24,0.92);box-shadow:0 0 32px rgba(167,139,250,0.18), 0 12px 40px -10px rgba(0,0,0,0.5);">
|
||||
{# Ambient purple glow #}
|
||||
<div class="absolute inset-0 pointer-events-none ia-ambient-glow"
|
||||
style="border-radius:inherit;background:radial-gradient(ellipse 120% 60% at 15% 50%, rgba(167,139,250,0.18) 0%, transparent 70%);"
|
||||
style="border-radius:inherit;background:radial-gradient(ellipse 120% 60% at 15% 50%, rgba(167,139,250,0.22) 0%, transparent 70%);"
|
||||
aria-hidden="true"></div>
|
||||
{# Header #}
|
||||
<div class="relative px-3 pt-3 pb-2 flex items-start gap-2.5">
|
||||
<div class="relative flex-shrink-0 mt-0.5">
|
||||
<div class="absolute -inset-2 rounded-full pointer-events-none ia-brain-glow"
|
||||
style="background:radial-gradient(circle, rgba(167,139,250,0.4) 0%, transparent 70%);"
|
||||
|
||||
{# Header — Brain in 40x40 circle #}
|
||||
<div class="relative px-4 pt-4 pb-3 flex items-start gap-3">
|
||||
<div class="relative flex-shrink-0">
|
||||
<div class="absolute -inset-3 rounded-full pointer-events-none ia-brain-glow"
|
||||
style="background:radial-gradient(circle, rgba(167,139,250,0.55) 0%, transparent 70%);"
|
||||
aria-hidden="true"></div>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:18px;height:18px;color:#A78BFA;position:relative;z-index:1;" aria-hidden="true">
|
||||
<div class="rounded-full flex items-center justify-center relative"
|
||||
style="width:40px;height:40px;background:linear-gradient(135deg, rgba(167,139,250,0.30), rgba(167,139,250,0.12));border:1.5px solid rgba(167,139,250,0.50);box-shadow:0 4px 12px rgba(167,139,250,0.20);">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:20px;height:20px;color:#C4B5FD;position:relative;z-index:1;" 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>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-1.5 flex-wrap">
|
||||
<span class="font-bold text-sm text-white">IA intégrée</span>
|
||||
<span class="text-[8px] px-1.5 py-0.5 rounded-md font-mono font-bold"
|
||||
style="background-color:rgba(167,139,250,0.20);color:#C4B5FD;border:1px solid rgba(167,139,250,0.42);letter-spacing:0.06em;">Mistral 7B</span>
|
||||
<span class="text-[7px] px-1.5 py-0.5 rounded font-mono font-bold ia-local-badge"
|
||||
style="background-color:rgba(52,211,153,0.12);color:#34D399;border:1px solid rgba(52,211,153,0.30);letter-spacing:0.10em;">LOCAL</span>
|
||||
<span class="font-bold text-base text-white">IA intégrée</span>
|
||||
</div>
|
||||
<p class="text-[10px] mt-0.5" style="color:rgba(255,255,255,0.55);">Résumé · Points d'action · Q&R</p>
|
||||
<div class="flex items-center gap-1.5 flex-wrap mt-1">
|
||||
<span class="text-[9px] px-2 py-0.5 rounded-md font-mono font-bold"
|
||||
style="background-color:rgba(167,139,250,0.22);color:#C4B5FD;border:1px solid rgba(167,139,250,0.45);letter-spacing:0.08em;">MISTRAL 7B</span>
|
||||
<span class="text-[8px] px-2 py-0.5 rounded font-mono font-bold ia-local-badge inline-flex items-center gap-1"
|
||||
style="background-color:rgba(52,211,153,0.14);color:#34D399;border:1px solid rgba(52,211,153,0.40);letter-spacing:0.12em;">
|
||||
<span class="dictia-dot-pulse" style="width:4px;height:4px;border-radius:50%;background:#34D399;"></span>
|
||||
LOCAL
|
||||
</span>
|
||||
</div>
|
||||
<p class="text-[11px] mt-1.5" style="color:rgba(255,255,255,0.62);">Résumé · Points d'action · Q&R</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Divider #}
|
||||
<div style="height:1px;background:linear-gradient(90deg, transparent, rgba(167,139,250,0.30), transparent);" aria-hidden="true"></div>
|
||||
|
||||
{# Performance metrics 3 cells #}
|
||||
<div class="relative grid grid-cols-3 gap-0">
|
||||
<div class="text-center py-2.5 px-1" style="border-right:1px solid rgba(167,139,250,0.10);">
|
||||
<p class="font-mono font-black text-base text-white leading-none">0 ms</p>
|
||||
<p class="text-[8px] mt-1 uppercase tracking-wider" style="color:rgba(167,139,250,0.65);">latence</p>
|
||||
</div>
|
||||
<div class="text-center py-2.5 px-1" style="border-right:1px solid rgba(167,139,250,0.10);">
|
||||
<p class="font-mono font-black text-base leading-none" style="color:#34D399;">100 %</p>
|
||||
<p class="text-[8px] mt-1 uppercase tracking-wider" style="color:rgba(167,139,250,0.65);">privé</p>
|
||||
</div>
|
||||
<div class="text-center py-2.5 px-1">
|
||||
<p class="font-mono font-black text-base leading-none" style="color:#C4B5FD;">24/7</p>
|
||||
<p class="text-[8px] mt-1 uppercase tracking-wider" style="color:rgba(167,139,250,0.65);">dispo</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Divider #}
|
||||
<div style="height:1px;background:linear-gradient(90deg, transparent, rgba(167,139,250,0.22), transparent);" aria-hidden="true"></div>
|
||||
{# Sovereignty bullets #}
|
||||
<div class="relative px-3 py-2.5 flex flex-col gap-2">
|
||||
<div class="flex items-start gap-2">
|
||||
<span style="color:rgba(167,139,250,0.65);flex-shrink:0;margin-top:1px;" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:10px;height:10px;">
|
||||
|
||||
{# Sovereignty bullets — chacun avec icon dans cercle #}
|
||||
<div class="relative px-4 py-3 flex flex-col gap-2.5">
|
||||
<div class="flex items-start gap-2.5">
|
||||
<span class="rounded-md flex items-center justify-center flex-shrink-0 mt-0.5"
|
||||
style="width:18px;height:18px;background:rgba(167,139,250,0.14);border:1px solid rgba(167,139,250,0.30);"
|
||||
aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:10px;height:10px;color:#C4B5FD;">
|
||||
<rect x="2" y="2" width="20" height="8" rx="2"/><rect x="2" y="14" width="20" height="8" rx="2"/>
|
||||
<line x1="6" y1="6" x2="6.01" y2="6"/><line x1="6" y1="18" x2="6.01" y2="18"/>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="text-[10px] leading-snug" style="color:rgba(255,255,255,0.85);"><strong>Données hébergées sur VOS serveurs</strong> · jamais partagées</span>
|
||||
<span class="text-[11px] leading-snug" style="color:rgba(255,255,255,0.88);"><strong>Données hébergées sur VOS serveurs</strong> · jamais partagées</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2">
|
||||
<span style="color:rgba(167,139,250,0.65);flex-shrink:0;margin-top:1px;" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:10px;height:10px;">
|
||||
<div class="flex items-start gap-2.5">
|
||||
<span class="rounded-md flex items-center justify-center flex-shrink-0 mt-0.5"
|
||||
style="width:18px;height:18px;background:rgba(167,139,250,0.14);border:1px solid rgba(167,139,250,0.30);"
|
||||
aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:10px;height:10px;color:#C4B5FD;">
|
||||
<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>
|
||||
<span class="text-[10px] leading-snug" style="color:rgba(255,255,255,0.65);">Zéro connexion OpenAI · Google · Microsoft</span>
|
||||
<span class="text-[11px] leading-snug" style="color:rgba(255,255,255,0.72);">Zéro connexion OpenAI · Google · Microsoft</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2">
|
||||
<span style="color:rgba(167,139,250,0.65);flex-shrink:0;margin-top:1px;" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" fill="currentColor" stroke="none" style="width:10px;height:10px;"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>
|
||||
<div class="flex items-start gap-2.5">
|
||||
<span class="rounded-md flex items-center justify-center flex-shrink-0 mt-0.5"
|
||||
style="width:18px;height:18px;background:rgba(167,139,250,0.14);border:1px solid rgba(167,139,250,0.30);"
|
||||
aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" fill="currentColor" stroke="none" style="width:10px;height:10px;color:#C4B5FD;"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>
|
||||
</span>
|
||||
<span class="text-[10px] leading-snug" style="color:rgba(255,255,255,0.65);">Inférence hors-ligne · résultats en secondes</span>
|
||||
<span class="text-[11px] leading-snug" style="color:rgba(255,255,255,0.72);">Inférence hors-ligne · résultats en secondes</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Feature grid 3 cols × 6 buttons (cliquables, état actif = featureColor border + glow + scale 1.25) #}
|
||||
<div class="grid grid-cols-3 gap-1.5">
|
||||
{# Feature grid 3 cols × 6 buttons #}
|
||||
<div class="grid grid-cols-3 gap-2">
|
||||
<template x-for="i in [1,2,3,4,5,6]" :key="i">
|
||||
<button type="button" @click="handleManualSelect(i)"
|
||||
class="flex flex-col items-center gap-1 rounded-xl py-2.5 px-1 outline-none transition-all focus-visible:ring-2 focus-visible:ring-white/40"
|
||||
:style="`border: 1px solid ${selectedFeature === i ? FEATURES[i].color + '55' : 'rgba(255,255,255,0.07)'}; background-color: ${selectedFeature === i ? FEATURES[i].color + '12' : 'rgba(8,12,24,0.85)'}; box-shadow: ${selectedFeature === i ? '0 0 12px ' + FEATURES[i].color + '22' : 'none'}; cursor: pointer;`"
|
||||
class="flex flex-col items-center gap-1 rounded-xl py-3 px-1 outline-none transition-all focus-visible:ring-2 focus-visible:ring-white/40"
|
||||
:style="`border: 1px solid ${selectedFeature === i ? FEATURES[i].color + '60' : 'rgba(255,255,255,0.08)'}; background-color: ${selectedFeature === i ? FEATURES[i].color + '14' : 'rgba(8,12,24,0.85)'}; box-shadow: ${selectedFeature === i ? '0 0 16px ' + FEATURES[i].color + '30, inset 0 0 12px ' + FEATURES[i].color + '10' : 'none'}; cursor: pointer;`"
|
||||
:aria-pressed="selectedFeature === i ? 'true' : 'false'"
|
||||
:aria-label="`Sélectionner : ${FEATURES[i].title}`">
|
||||
<span :style="`color: ${selectedFeature === i ? FEATURES[i].color : 'rgba(255,255,255,0.45)'}; filter: ${selectedFeature === i ? 'drop-shadow(0 0 5px ' + FEATURES[i].color + 'AA)' : 'none'}; transform: scale(${selectedFeature === i ? 1.25 : 1}) translateY(${selectedFeature === i ? -1 : 0}px); transition: all 0.2s; display:inline-block;`">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:14px;height:14px;" aria-hidden="true" x-html="featureIconPath(i)"></svg>
|
||||
<span :style="`color: ${selectedFeature === i ? FEATURES[i].color : 'rgba(255,255,255,0.50)'}; filter: ${selectedFeature === i ? 'drop-shadow(0 0 6px ' + FEATURES[i].color + 'BB)' : 'none'}; transform: scale(${selectedFeature === i ? 1.25 : 1}) translateY(${selectedFeature === i ? -1 : 0}px); transition: all 0.2s; display:inline-block;`">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:16px;height:16px;" aria-hidden="true" x-html="featureIconPath(i)"></svg>
|
||||
</span>
|
||||
<span class="text-[7.5px] font-medium text-center leading-tight"
|
||||
:style="`color: ${selectedFeature === i ? 'rgba(255,255,255,0.92)' : 'rgba(255,255,255,0.55)'}; transition: color 0.2s;`"
|
||||
<span class="text-[8px] font-medium text-center leading-tight"
|
||||
:style="`color: ${selectedFeature === i ? 'rgba(255,255,255,0.95)' : 'rgba(255,255,255,0.60)'}; transition: color 0.2s;`"
|
||||
x-text="FEATURES[i].title"></span>
|
||||
</button>
|
||||
</template>
|
||||
@@ -743,6 +1177,10 @@
|
||||
6: '<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"/>'
|
||||
};
|
||||
return paths[i] || '';
|
||||
},
|
||||
featureShortLabel(i) {
|
||||
const labels = { 1: 'Trans', 2: 'Diari', 3: 'Lang', 4: 'Exp', 5: 'Users', 6: 'Part' };
|
||||
return labels[i] || '';
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -807,7 +1245,7 @@
|
||||
};
|
||||
}
|
||||
|
||||
/* Mode 3 — Langues : grille 100 codes (CSS-only stagger 12ms) */
|
||||
/* Mode 3 — Langues : grille 100 codes (ripple depuis centre + highlight aléatoire) */
|
||||
function langModeData() {
|
||||
return {
|
||||
LANG_COLORS: ['#22D3EE','#6B9FFF','#A78BFA','#34D399','#F59E0B','#22D3EE','#6B9FFF','#A78BFA'],
|
||||
@@ -822,7 +1260,20 @@
|
||||
'MN','NE','PS','AM','SQ','HY','MG','YO','SO','ZU',
|
||||
'NY','XH','IG','HA','SN','ST','CEB','HT','JW','KY',
|
||||
'TG','BS','OC','BR','FO','LG','YI','TT','SD','WA'
|
||||
]
|
||||
],
|
||||
/* HIGHLIGHTS : 5 indexes aléatoires qui pulsent (regenerated chaque cycle) */
|
||||
HIGHLIGHTS: (() => {
|
||||
const set = new Set();
|
||||
while (set.size < 5) set.add(Math.floor(Math.random() * 100));
|
||||
return Array.from(set);
|
||||
})(),
|
||||
/* rippleDelay : delay calculé selon distance au centre (50, ~ idx 49) */
|
||||
rippleDelay(i) {
|
||||
const cols = 7, row = Math.floor(i / cols), col = i % cols;
|
||||
const centerRow = 7, centerCol = 3;
|
||||
const dist = Math.sqrt(Math.pow(row - centerRow, 2) + Math.pow(col - centerCol, 2));
|
||||
return Math.round(dist * 28);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -841,10 +1292,11 @@
|
||||
};
|
||||
}
|
||||
|
||||
/* Mode 5 — Users : multiplication 1→20 (200ms each, loop after 700ms) */
|
||||
/* Mode 5 — Users : multiplication 1→20 (200ms each, loop after 700ms) avec couleurs variées */
|
||||
function usersModeData() {
|
||||
return {
|
||||
MAX: 20, count: 1, cycle: 0, _iv: null,
|
||||
USER_COLORS: ['#A78BFA', '#22D3EE', '#34D399', '#6B9FFF', '#F59E0B'],
|
||||
init() {
|
||||
if (this._iv) clearInterval(this._iv);
|
||||
this.count = 1;
|
||||
|
||||
@@ -201,6 +201,59 @@ def test_fonctionnalites_how_it_works_reactor_section():
|
||||
assert 'prefers-reduced-motion' in body, "Reduced-motion guard missing"
|
||||
assert 'aria-pressed' in body, "Missing aria-pressed on feature buttons"
|
||||
|
||||
# ── HYPER PRO polish refactor 2026-04-29 ── ----------------------------
|
||||
# Phone shell : bezel + notch + speaker + status bar
|
||||
assert 'dictia-phone-shell' in body, "Missing phone shell class"
|
||||
assert 'dictia-notch' in body, "Missing notch element"
|
||||
assert 'dictia-statusbar' in body, "Missing mobile-style status bar"
|
||||
assert '9:41' in body, "Missing 9:41 status bar time"
|
||||
assert 'dictia-sound-ring' in body, "Missing sound ring animation"
|
||||
assert 'dictia-phone-glow-ring' in body, "Missing phone external glow ring"
|
||||
|
||||
# Mode 1 — REC indicator + waveform
|
||||
assert 'REC' in body, "Missing transcription REC indicator"
|
||||
assert 'dictia-rec-dot' in body, "Missing REC pulsing dot"
|
||||
assert 'dictia-wave-bar' in body, "Missing waveform animation"
|
||||
|
||||
# Mode 2 — typing indicator + timestamps + stacked avatars
|
||||
assert 'dictia-typing-dot' in body, "Missing typing indicator dots"
|
||||
assert 'Réunion · 3 participants' in body, "Missing diarisation header"
|
||||
|
||||
# Mode 3 — DÉTECTION AUTOMATIQUE header + ripple from center + counter
|
||||
assert 'DÉTECTION AUTOMATIQUE' in body, "Missing langues detection header"
|
||||
assert 'rippleDelay' in body, "Missing ripple delay function"
|
||||
assert 'HIGHLIGHTS' in body, "Missing langues highlights array"
|
||||
|
||||
# Mode 4 — header EXPORTS + checkmark
|
||||
assert 'EXPORTS DISPONIBLES' in body, "Missing exports header"
|
||||
assert '7 FORMATS PRÊTS' in body, "Missing exports checkmark subtitle"
|
||||
|
||||
# Mode 5 — counter centered + USER_COLORS
|
||||
assert 'UTILISATEURS' in body, "Missing users counter header"
|
||||
assert 'USER_COLORS' in body, "Missing users color variations"
|
||||
|
||||
# Mode 6 — breadcrumb + toolbar
|
||||
assert 'Mes dossiers' in body, "Missing share breadcrumb"
|
||||
|
||||
# BOTTOM zone — feature buttons + AUTO pill + countdown
|
||||
assert 'featureShortLabel' in body, "Missing feature short labels function"
|
||||
assert 'dictia-auto-pulse' in body, "Missing auto pill pulse"
|
||||
assert 'dictia-countdown-fill' in body, "Missing manuel countdown bar"
|
||||
|
||||
# Right panel — IA card metrics + Brain in 40x40 circle
|
||||
assert 'MISTRAL 7B' in body, "Missing Mistral badge label"
|
||||
assert 'latence' in body, "Missing latency metric label"
|
||||
|
||||
# Section background + connecting line
|
||||
assert 'dictia-bg-grid' in body, "Missing background grid pattern"
|
||||
assert 'dictia-bg-orbs' in body, "Missing floating orbs"
|
||||
assert 'dictia-connecting-line' in body, "Missing connecting line phone↔IA"
|
||||
|
||||
# Stats row in section header
|
||||
assert 'modules' in body, "Missing stats row 'modules'"
|
||||
assert 'cloud' in body, "Missing stats row 'cloud'"
|
||||
assert 'Voir une démo' in body, "Missing demo CTA link"
|
||||
|
||||
|
||||
def test_fonctionnalites_export_formats_section():
|
||||
client = app.test_client()
|
||||
|
||||
Reference in New Issue
Block a user