feat(marketing): hero section with cosmic orbs + dual CTA + social proof
- 3 radial-gradient orbs (blue 16%, cyan 7%, green 11%) + subtle 40px grid + horizontal accent line — FlexiHub cosmic background signature - H1 clamp(2.5rem,4vw,4rem) font-black with grad-text accent on 'sans risquer votre permis' tagline - Eyebrow 11px tracking-[0.18em] grad-text — 'TRANSCRIPTION IA · CONFORME LOI 25 · QUÉBEC' - Sub-headline ≤25 words declares Loi 25 compliance + 9 ordres pros - Dual CTA: Réserver une démo (primary gradient+glow) + Voir les tarifs → (ghost) — drives demo conversion + pricing self-service - Social proof microcopy above-the-fold: 5★ + 27 cabinets + Lancement printemps 2026 - Staggered tc-fade-in-up animations 0/75/150/300/400ms with animation-fill-mode: backwards (no FOIT) - 6 new tests verify H1 grad-text, dual CTA, orb opacities, social proof, staggered delays, eyebrow messaging
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -1,19 +1,62 @@
|
|||||||
{% extends 'marketing/base.html' %}
|
{% extends 'marketing/base.html' %}
|
||||||
|
|
||||||
|
{% block title %}Transcription IA conforme Loi 25 — DictIA pour avocats, CPA, secteur public{% endblock %}
|
||||||
|
{% block description %}DictIA transcrit vos réunions confidentielles 100% au Québec. Conforme Loi 25, Barreau, CPA, ChAD. Lancement printemps 2026 — 27 cabinets pilotes.{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<section class="relative overflow-hidden bg-brand-navy text-white py-24 md:py-32">
|
{# ===== HERO ===== #}
|
||||||
<div class="max-w-[1200px] mx-auto px-6 text-center">
|
<section class="relative overflow-hidden bg-brand-navy text-white py-24 md:py-32" aria-labelledby="hero-title">
|
||||||
<p class="eyebrow grad-text mb-6">DICTIA · TRANSCRIPTION IA · CONFORME LOI 25</p>
|
{# Cosmic orbs background — 3 radial gradients (blue 16%, cyan 7%, green 11%) + subtle grid + horizontal accent line #}
|
||||||
<h1 class="text-[clamp(2.5rem,4vw,4rem)] font-black leading-[1.05] mb-6">
|
<div class="absolute inset-0 pointer-events-none" aria-hidden="true">
|
||||||
Refonte en cours — <span class="grad-text">printemps 2026</span>.
|
{# Orb 1 — primary blue, top-left #}
|
||||||
</h1>
|
<div class="absolute top-1/4 left-1/4 w-[600px] h-[600px] rounded-full opacity-100"
|
||||||
<p class="text-lg text-white/70 max-w-2xl mx-auto mb-10">
|
style="background: radial-gradient(circle, rgba(0,98,255,0.16) 0%, transparent 60%); filter: blur(40px);"></div>
|
||||||
La page marketing complète est en construction. Toutes les fonctionnalités de DictIA restent disponibles via votre compte.
|
{# Orb 2 — cyan, mid-right #}
|
||||||
</p>
|
<div class="absolute top-1/2 right-1/4 w-[500px] h-[500px] rounded-full"
|
||||||
<div class="flex flex-col sm:flex-row gap-3 justify-center">
|
style="background: radial-gradient(circle, rgba(0,189,216,0.07) 0%, transparent 60%); filter: blur(40px);"></div>
|
||||||
{% from 'macros/button.html' import button %}
|
{# Orb 3 — accent green, bottom-left #}
|
||||||
{{ button('Réserver une démo', href='/contact', variant='primary', size='lg') }}
|
<div class="absolute bottom-1/4 left-1/3 w-[400px] h-[400px] rounded-full"
|
||||||
{{ button('Connexion', href='/login', variant='ghost', size='lg') }}
|
style="background: radial-gradient(circle, rgba(0,200,150,0.11) 0%, transparent 60%); filter: blur(40px);"></div>
|
||||||
|
{# Subtle grid overlay (FlexiHub signature) #}
|
||||||
|
<div class="absolute inset-0"
|
||||||
|
style="background-image: linear-gradient(rgba(255,255,255,0.02) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.02) 1px, transparent 1px); background-size: 40px 40px;"></div>
|
||||||
|
{# Horizontal accent line — gradient blue→cyan→transparent #}
|
||||||
|
<div class="absolute top-1/3 left-0 right-0 h-px"
|
||||||
|
style="background: linear-gradient(90deg, transparent, rgba(0,98,255,0.3), rgba(0,189,216,0.2), transparent);"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="relative max-w-[1200px] mx-auto px-6">
|
||||||
|
<div class="max-w-3xl mx-auto text-center">
|
||||||
|
{# Eyebrow with gradient text and 0.18em tracking #}
|
||||||
|
<p class="eyebrow grad-text mb-6 animate-tc-fade-in-up" style="animation-delay: 0ms; animation-fill-mode: backwards;">
|
||||||
|
TRANSCRIPTION IA · CONFORME LOI 25 · QUÉBEC
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{# H1 — clamp typography + grad-text accent on key phrase #}
|
||||||
|
<h1 id="hero-title" class="text-[clamp(2.5rem,4vw,4rem)] font-black leading-[1.05] mb-6 animate-tc-fade-in-up" style="animation-delay: 75ms; animation-fill-mode: backwards;">
|
||||||
|
Transcrivez vos réunions
|
||||||
|
<span class="grad-text">sans risquer votre permis</span>.
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
{# Sub-headline — ≤25 words, value prop #}
|
||||||
|
<p class="text-lg text-white/70 max-w-2xl mx-auto mb-10 animate-tc-fade-in-up" style="animation-delay: 150ms; animation-fill-mode: backwards;">
|
||||||
|
DictIA convertit vos audio en texte, résumé et points d'action — 100% au Québec, conforme Barreau, CPA Québec, ChAD et 6 autres ordres professionnels.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{# Dual CTA — primary (demo) + secondary ghost (pricing) #}
|
||||||
|
<div class="flex flex-col sm:flex-row gap-3 justify-center animate-tc-fade-in-up" style="animation-delay: 300ms; animation-fill-mode: backwards;">
|
||||||
|
{% from 'macros/button.html' import button %}
|
||||||
|
{{ button('Réserver une démo', href='/contact', variant='primary', size='lg') }}
|
||||||
|
{{ button('Voir les tarifs →', href='/tarifs', variant='ghost', size='lg') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# Social proof microcopy — above-the-fold trust signal #}
|
||||||
|
<p class="mt-8 text-sm text-white/50 animate-tc-fade-in-up" style="animation-delay: 400ms; animation-fill-mode: backwards;">
|
||||||
|
<span class="text-yellow-400" aria-hidden="true">★★★★★</span>
|
||||||
|
<span class="ml-2">27 cabinets québécois nous font confiance</span>
|
||||||
|
<span class="mx-2 text-white/30">·</span>
|
||||||
|
<span>Lancement printemps 2026</span>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -80,3 +80,63 @@ def test_landing_no_login_redirect_for_anonymous():
|
|||||||
response = client.get('/', follow_redirects=False)
|
response = client.get('/', follow_redirects=False)
|
||||||
assert response.status_code == 200, \
|
assert response.status_code == 200, \
|
||||||
f"Expected 200, got {response.status_code} — possibly login_required regression"
|
f"Expected 200, got {response.status_code} — possibly login_required regression"
|
||||||
|
|
||||||
|
|
||||||
|
def test_hero_has_h1_with_grad_text_accent():
|
||||||
|
"""Hero H1 contains grad-text span on the brand tagline."""
|
||||||
|
client = app.test_client()
|
||||||
|
body = client.get('/').data.decode('utf-8')
|
||||||
|
assert 'id="hero-title"' in body, "Missing hero-title id on H1"
|
||||||
|
assert 'grad-text' in body, "Missing grad-text class somewhere"
|
||||||
|
assert 'sans risquer votre permis' in body, "Missing key brand tagline"
|
||||||
|
|
||||||
|
|
||||||
|
def test_hero_has_dual_cta():
|
||||||
|
"""Hero has both primary (Réserver une démo) and ghost (Voir les tarifs) CTAs."""
|
||||||
|
client = app.test_client()
|
||||||
|
body = client.get('/').data.decode('utf-8')
|
||||||
|
assert 'href="/contact"' in body
|
||||||
|
assert 'href="/tarifs"' in body
|
||||||
|
assert 'Réserver une démo' in body or 'Réserver une démo' in body
|
||||||
|
assert 'Voir les tarifs' in body
|
||||||
|
|
||||||
|
|
||||||
|
def test_hero_has_cosmic_orbs_background():
|
||||||
|
"""Hero has 3 radial gradient orbs (FlexiHub signature)."""
|
||||||
|
client = app.test_client()
|
||||||
|
body = client.get('/').data.decode('utf-8')
|
||||||
|
# Look for the 3 orb opacities (16% blue, 7% cyan, 11% green)
|
||||||
|
assert 'rgba(0,98,255,0.16)' in body, "Missing primary blue orb"
|
||||||
|
assert 'rgba(0,189,216,0.07)' in body, "Missing cyan orb"
|
||||||
|
assert 'rgba(0,200,150,0.11)' in body, "Missing green accent orb"
|
||||||
|
|
||||||
|
|
||||||
|
def test_hero_has_social_proof_microcopy():
|
||||||
|
"""Hero has '27 cabinets' social proof + Lancement printemps 2026."""
|
||||||
|
client = app.test_client()
|
||||||
|
body = client.get('/').data.decode('utf-8')
|
||||||
|
assert '27 cabinets' in body, "Missing social proof '27 cabinets'"
|
||||||
|
assert 'Lancement printemps 2026' in body, "Missing launch date"
|
||||||
|
|
||||||
|
|
||||||
|
def test_hero_has_staggered_animations():
|
||||||
|
"""Hero elements use tc-fade-in-up with staggered delays."""
|
||||||
|
client = app.test_client()
|
||||||
|
body = client.get('/').data.decode('utf-8')
|
||||||
|
assert 'animate-tc-fade-in-up' in body, "Missing fade-in animation"
|
||||||
|
assert 'animation-delay: 0ms' in body
|
||||||
|
assert 'animation-delay: 75ms' in body
|
||||||
|
assert 'animation-delay: 150ms' in body
|
||||||
|
assert 'animation-delay: 300ms' in body
|
||||||
|
assert 'animation-delay: 400ms' in body
|
||||||
|
assert 'animation-fill-mode: backwards' in body, \
|
||||||
|
"Missing animation-fill-mode (causes flash before delay fires)"
|
||||||
|
|
||||||
|
|
||||||
|
def test_hero_eyebrow_has_brand_messaging():
|
||||||
|
"""Hero eyebrow declares the 3 brand pillars."""
|
||||||
|
client = app.test_client()
|
||||||
|
body = client.get('/').data.decode('utf-8')
|
||||||
|
assert 'TRANSCRIPTION IA' in body
|
||||||
|
assert 'CONFORME LOI 25' in body
|
||||||
|
assert 'QU' in body # Either QUÉBEC or QUÉBEC
|
||||||
|
|||||||
Reference in New Issue
Block a user