refactor(ui): sharpen buttons + inputs to rounded (4px) for modern minimal SaaS look

V2 sharper radii system aligned with Stripe Dashboard / Linear / Vercel
aesthetic — the v1 rounded-lg (8px) on buttons still felt too soft.

New scale:
- Buttons (CTA, submit, ghost, secondary): rounded-lg → rounded (4px)
- Form inputs (text/email/password/select/textarea): rounded-md → rounded (4px)
- Checkboxes: rounded-sm (2px) added explicitly to consent + remember-me
- Cards (pricing, bento, content panels): rounded-xl → rounded-lg (8px)
- Small icon tiles (w-10 h-10 / w-12 h-12 grad-bg squares): rounded-md → rounded
- Pills, badges, avatars, status orbs: rounded-full (KEPT)
- Inline code in legal CSS: rounded (4px) (KEPT)
- Legal blockquote/pre/draft-callout border-radius: 8px → 4px

Files modified (24):
- templates/macros/{button,bento,pricing_card}.html
- templates/marketing/{landing,tarifs,fonctionnalites,conformite,contact}.html
- templates/auth/{check_email,forgot_password,magic_link_request,
  oauth_finish_signup,passkey_setup,reset_password,totp_setup,totp_verify,
  verify_success}.html
- templates/billing/{success,cancel}.html
- templates/legal/{_layout,index}.html
- templates/{register,login}.html
- tests/test_marketing_landing_template.py (assertions updated to match v2)

Verification:
- 18/18 legal page tests pass (tests/_run_legal_pages_windows.py)
- 58/58 marketing landing tests pass

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Allison
2026-04-28 10:13:03 -04:00
parent 48ff4e70e6
commit 0b91294c45
24 changed files with 106 additions and 106 deletions

View File

@@ -5,7 +5,7 @@
{% block content %}
<section class="min-h-[calc(100vh-62px)] bg-brand-bg py-16 px-4" aria-labelledby="check-email-title">
<div class="max-w-md mx-auto bg-white p-8 rounded-xl border border-brand-border shadow-cta text-center">
<div class="max-w-md mx-auto bg-white p-8 rounded-lg border border-brand-border shadow-cta text-center">
<div class="mx-auto mb-6 w-16 h-16 rounded-full grad-bg flex items-center justify-center text-white text-2xl" aria-hidden="true">&#x2709;</div>
<h1 id="check-email-title" class="text-2xl font-black text-brand-navy mb-2">
@@ -45,7 +45,7 @@
<form method="POST" action="{{ url_for('auth.resend_verification') }}" class="mb-4">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<input type="hidden" name="email" value="{{ email }}">
<button type="submit" class="w-full grad-bg text-white font-semibold py-3 rounded-lg shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
<button type="submit" class="w-full grad-bg text-white font-semibold py-3 rounded shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
Renvoyer le lien de vérification
</button>
</form>

View File

@@ -5,7 +5,7 @@
{% block content %}
<section class="min-h-[calc(100vh-62px)] bg-brand-bg py-16 px-4" aria-labelledby="forgot-title">
<div class="max-w-md mx-auto bg-white p-8 rounded-xl border border-brand-border shadow-cta">
<div class="max-w-md mx-auto bg-white p-8 rounded-lg border border-brand-border shadow-cta">
<h1 id="forgot-title" class="text-3xl font-black text-brand-navy mb-2">Mot de passe oublié</h1>
<p class="text-sm text-brand-navy/70 mb-6">{{ "Entrez votre adresse courriel. Si un compte existe, nous vous enverrons un lien sécurisé pour réinitialiser votre mot de passe (valide 1&nbsp;heure)." | safe }}</p>
@@ -29,11 +29,11 @@
<div>
<label for="email" class="block text-sm font-medium text-brand-navy mb-1">Courriel <span class="text-red-600" aria-hidden="true">*</span></label>
<input type="email" id="email" name="email" autocomplete="email" required aria-required="true"
class="w-full px-3 py-2 border border-brand-border rounded-md text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
class="w-full px-3 py-2 border border-brand-border rounded text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
placeholder="vous@cabinet.qc.ca">
</div>
<button type="submit" class="w-full grad-bg text-white font-semibold py-3 rounded-lg shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
<button type="submit" class="w-full grad-bg text-white font-semibold py-3 rounded shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
Recevoir un lien de réinitialisation
</button>
</form>

View File

@@ -5,7 +5,7 @@
{% block content %}
<section class="min-h-[calc(100vh-62px)] bg-brand-bg py-16 px-4" aria-labelledby="magic-title">
<div class="max-w-md mx-auto bg-white p-8 rounded-xl border border-brand-border shadow-cta">
<div class="max-w-md mx-auto bg-white p-8 rounded-lg border border-brand-border shadow-cta">
<h1 id="magic-title" class="text-3xl font-black text-brand-navy mb-2">Lien de connexion</h1>
<p class="text-sm text-brand-navy/70 mb-6">{{ "Recevez un lien par courriel pour vous connecter sans mot de passe. Le lien expire dans 15&nbsp;minutes." | safe }}</p>
@@ -29,11 +29,11 @@
<div>
<label for="email" class="block text-sm font-medium text-brand-navy mb-1">Courriel <span class="text-red-600" aria-hidden="true">*</span></label>
<input type="email" id="email" name="email" autocomplete="email" required aria-required="true"
class="w-full px-3 py-2 border border-brand-border rounded-md text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
class="w-full px-3 py-2 border border-brand-border rounded text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
placeholder="vous@cabinet.qc.ca">
</div>
<button type="submit" class="w-full grad-bg text-white font-semibold py-3 rounded-lg shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
<button type="submit" class="w-full grad-bg text-white font-semibold py-3 rounded shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
{{ "Recevoir le lien (expire dans 15&nbsp;minutes)" | safe }}
</button>
</form>

View File

@@ -5,7 +5,7 @@
{% block content %}
<section class="min-h-[calc(100vh-62px)] bg-brand-bg py-16 px-4" aria-labelledby="finish-title">
<div class="max-w-md mx-auto bg-white p-8 rounded-xl border border-brand-border shadow-cta">
<div class="max-w-md mx-auto bg-white p-8 rounded-lg border border-brand-border shadow-cta">
<h1 id="finish-title" class="text-3xl font-black text-brand-navy mb-2">Finaliser votre inscription</h1>
<p class="text-sm text-brand-navy/70 mb-6">
Vous vous inscrivez via <strong>{{ provider_display or provider | capitalize }}</strong>. Avant de créer votre compte DictIA, nous devons obtenir vos consentements conformément à la {{ "Loi&nbsp;25" | safe }} du Québec.
@@ -26,7 +26,7 @@
{% endwith %}
{# Pre-filled email from OAuth provider — display only, not editable #}
<div class="bg-brand-bg border border-brand-border rounded-md p-3 mb-6 text-sm">
<div class="bg-brand-bg border border-brand-border rounded p-3 mb-6 text-sm">
<p class="text-brand-navy/70 mb-1">Compte fédéré :</p>
<p class="text-brand-navy font-semibold break-all">{{ userinfo.email }}</p>
{% if userinfo.name %}<p class="text-brand-navy/80 text-xs mt-1">{{ userinfo.name }}</p>{% endif %}
@@ -41,32 +41,32 @@
<label for="consent_cgu" class="flex items-start gap-2 text-sm text-brand-navy/90">
<input type="checkbox" id="consent_cgu" name="consent_cgu" value="y" required aria-required="true"
class="mt-1 focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
class="mt-1 rounded-sm focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
<span>J'accepte les <a href="/legal/conditions" target="_blank" rel="noopener" class="grad-text underline">conditions d'utilisation</a>. <span class="text-red-600" aria-hidden="true">*</span></span>
</label>
{% if errors.consent_cgu %}<p class="text-xs text-red-900 mt-1" role="alert">{{ errors.consent_cgu }}</p>{% endif %}
<label for="consent_confidentialite" class="flex items-start gap-2 text-sm text-brand-navy/90">
<input type="checkbox" id="consent_confidentialite" name="consent_confidentialite" value="y" required aria-required="true"
class="mt-1 focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
class="mt-1 rounded-sm focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
<span>J'accepte la <a href="/legal/confidentialite" target="_blank" rel="noopener" class="grad-text underline">politique de confidentialité</a>. <span class="text-red-600" aria-hidden="true">*</span></span>
</label>
{% if errors.consent_confidentialite %}<p class="text-xs text-red-900 mt-1" role="alert">{{ errors.consent_confidentialite }}</p>{% endif %}
<label for="consent_marketing" class="flex items-start gap-2 text-sm text-brand-navy/90">
<input type="checkbox" id="consent_marketing" name="consent_marketing" value="y"
class="mt-1 focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
class="mt-1 rounded-sm focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
<span>J'accepte de recevoir des communications marketing (optionnel, désactivable à tout moment).</span>
</label>
<label for="consent_analytics" class="flex items-start gap-2 text-sm text-brand-navy/90">
<input type="checkbox" id="consent_analytics" name="consent_analytics" value="y"
class="mt-1 focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
class="mt-1 rounded-sm focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
<span>J'accepte les statistiques d'usage anonymisées (optionnel, désactivable à tout moment).</span>
</label>
</fieldset>
<button type="submit" class="w-full grad-bg text-white font-semibold py-3 rounded-lg shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
<button type="submit" class="w-full grad-bg text-white font-semibold py-3 rounded shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
Créer mon compte DictIA
</button>
</form>

View File

@@ -5,7 +5,7 @@
{% block content %}
<section class="min-h-[calc(100vh-62px)] bg-brand-bg py-16 px-4" aria-labelledby="passkey-setup-title">
<div class="max-w-2xl mx-auto bg-white p-8 rounded-xl border border-brand-border shadow-cta">
<div class="max-w-2xl mx-auto bg-white p-8 rounded-lg border border-brand-border shadow-cta">
<h1 id="passkey-setup-title" class="text-3xl font-black text-brand-navy mb-2">Mes passkeys</h1>
<p class="text-sm text-brand-navy/70 mb-6">{{ "Une passkey est un second facteur sans mot de passe (clé matérielle YubiKey, biométrie de votre appareil, etc.). Conforme&nbsp;Loi&nbsp;25." | safe }}</p>
@@ -48,8 +48,8 @@
<h2 class="text-base font-semibold text-brand-navy mb-3">Ajouter une passkey</h2>
<div class="space-y-3">
<label for="passkey-label" class="block text-sm font-medium text-brand-navy">Nom de la passkey (optionnel)</label>
<input id="passkey-label" type="text" maxlength="80" placeholder="ex. YubiKey 5C, MacBook Touch ID..." class="w-full px-3 py-2 border border-brand-border rounded-md text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
<button id="passkey-register-btn" type="button" class="w-full grad-bg text-white font-semibold py-3 rounded-lg shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
<input id="passkey-label" type="text" maxlength="80" placeholder="ex. YubiKey 5C, MacBook Touch ID..." class="w-full px-3 py-2 border border-brand-border rounded text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
<button id="passkey-register-btn" type="button" class="w-full grad-bg text-white font-semibold py-3 rounded shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
Enregistrer une passkey
</button>
<p id="passkey-register-status" class="text-xs text-brand-navy/70" role="status" aria-live="polite"></p>

View File

@@ -5,7 +5,7 @@
{% block content %}
<section class="min-h-[calc(100vh-62px)] bg-brand-bg py-16 px-4" aria-labelledby="reset-title">
<div class="max-w-md mx-auto bg-white p-8 rounded-xl border border-brand-border shadow-cta">
<div class="max-w-md mx-auto bg-white p-8 rounded-lg border border-brand-border shadow-cta">
<h1 id="reset-title" class="text-3xl font-black text-brand-navy mb-2">Nouveau mot de passe</h1>
<p class="text-sm text-brand-navy/70 mb-6">Choisissez un mot de passe robuste pour sécuriser votre compte DictIA.</p>
@@ -29,7 +29,7 @@
<div>
<label for="password" class="block text-sm font-medium text-brand-navy mb-1">Nouveau mot de passe <span class="text-red-600" aria-hidden="true">*</span></label>
<input type="password" id="password" name="password" autocomplete="new-password" minlength="8" required aria-required="true" aria-describedby="password-help"
class="w-full px-3 py-2 border border-brand-border rounded-md text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
class="w-full px-3 py-2 border border-brand-border rounded text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
placeholder="••••••••">
<p id="password-help" class="text-xs text-brand-navy/70 mt-1">{{ "8&nbsp;caractères minimum, dont une majuscule, une minuscule, un chiffre et un caractère spécial." | safe }}</p>
</div>
@@ -37,11 +37,11 @@
<div>
<label for="confirm_password" class="block text-sm font-medium text-brand-navy mb-1">Confirmer le mot de passe <span class="text-red-600" aria-hidden="true">*</span></label>
<input type="password" id="confirm_password" name="confirm_password" autocomplete="new-password" minlength="8" required aria-required="true"
class="w-full px-3 py-2 border border-brand-border rounded-md text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
class="w-full px-3 py-2 border border-brand-border rounded text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
placeholder="••••••••">
</div>
<button type="submit" class="w-full grad-bg text-white font-semibold py-3 rounded-lg shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
<button type="submit" class="w-full grad-bg text-white font-semibold py-3 rounded shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
Définir mon nouveau mot de passe
</button>
</form>

View File

@@ -5,7 +5,7 @@
{% block content %}
<section class="min-h-[calc(100vh-62px)] bg-brand-bg py-16 px-4" aria-labelledby="totp-setup-title">
<div class="max-w-2xl mx-auto bg-white p-8 rounded-xl border border-brand-border shadow-cta">
<div class="max-w-2xl mx-auto bg-white p-8 rounded-lg border border-brand-border shadow-cta">
<h1 id="totp-setup-title" class="text-3xl font-black text-brand-navy mb-2">Configurer la double authentification</h1>
<p class="text-sm text-brand-navy/70 mb-6">{{ "La double authentification (2FA) ajoute une seconde étape lors de la connexion, en plus de votre mot de passe. Une exigence forte recommandée pour les comptes traitant des données confidentielles (Loi&nbsp;25)." | safe }}</p>
@@ -74,11 +74,11 @@
<input type="text" id="code" name="code" required aria-required="true"
inputmode="numeric" autocomplete="one-time-code"
pattern="[0-9]{6}" maxlength="6"
class="w-full md:w-48 px-3 py-2 border border-brand-border rounded-md text-brand-navy text-center text-xl font-mono tracking-widest focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
class="w-full md:w-48 px-3 py-2 border border-brand-border rounded text-brand-navy text-center text-xl font-mono tracking-widest focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
placeholder="000000" autofocus>
</div>
<button type="submit" class="grad-bg text-white font-semibold py-3 px-6 rounded-lg shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
<button type="submit" class="grad-bg text-white font-semibold py-3 px-6 rounded shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
Activer la double authentification
</button>
</form>

View File

@@ -5,7 +5,7 @@
{% block content %}
<section class="min-h-[calc(100vh-62px)] bg-brand-bg py-16 px-4" aria-labelledby="totp-verify-title">
<div class="max-w-md mx-auto bg-white p-8 rounded-xl border border-brand-border shadow-cta">
<div class="max-w-md mx-auto bg-white p-8 rounded-lg border border-brand-border shadow-cta">
<h1 id="totp-verify-title" class="text-3xl font-black text-brand-navy mb-2">Vérification en deux étapes</h1>
<p class="text-sm text-brand-navy/70 mb-6">Entrez le code à 6 chiffres affiché dans votre application authenticator pour terminer la connexion.</p>
@@ -31,7 +31,7 @@
{% if has_passkeys %}
<section class="mb-6" aria-labelledby="passkey-section-title">
<h2 id="passkey-section-title" class="text-base font-semibold text-brand-navy mb-3">Connexion par Passkey</h2>
<button id="passkey-auth-btn" type="button" class="w-full grad-bg text-white font-semibold py-3 rounded-lg shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
<button id="passkey-auth-btn" type="button" class="w-full grad-bg text-white font-semibold py-3 rounded shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
Utiliser ma Passkey
</button>
<p id="passkey-status" class="text-xs text-brand-navy/70 mt-2" role="status" aria-live="polite"></p>
@@ -54,11 +54,11 @@
<input type="text" id="code" name="code"
inputmode="numeric" autocomplete="one-time-code"
pattern="[0-9]{6}" maxlength="6"
class="w-full px-3 py-3 border border-brand-border rounded-md text-brand-navy text-center text-2xl font-mono tracking-widest focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
class="w-full px-3 py-3 border border-brand-border rounded text-brand-navy text-center text-2xl font-mono tracking-widest focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
placeholder="000000" autofocus>
</div>
<button type="submit" class="w-full grad-bg text-white font-semibold py-3 rounded-lg shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
<button type="submit" class="w-full grad-bg text-white font-semibold py-3 rounded shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
Vérifier et se connecter
</button>
</form>
@@ -74,11 +74,11 @@
<label for="recovery_code" class="block text-sm font-medium text-brand-navy mb-1">Code de récupération <span class="text-red-600" aria-hidden="true">*</span></label>
<input type="text" id="recovery_code" name="recovery_code"
autocomplete="off"
class="w-full px-3 py-2 border border-brand-border rounded-md text-brand-navy font-mono uppercase focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
class="w-full px-3 py-2 border border-brand-border rounded text-brand-navy font-mono uppercase focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
placeholder="XXXXX-XXXXX">
<p class="text-xs text-brand-navy/60 mt-1">Format&nbsp;: 5 caractères + tiret + 5 caractères. Chaque code est à usage unique.</p>
</div>
<button type="submit" class="w-full bg-brand-navy text-white font-semibold py-3 rounded-lg hover:bg-brand-navy2 transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
<button type="submit" class="w-full bg-brand-navy text-white font-semibold py-3 rounded hover:bg-brand-navy2 transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
Utiliser le code de récupération
</button>
<p class="text-xs text-brand-navy/60 text-center" aria-live="polite">{{ recovery_codes_remaining }} code{{ 's' if recovery_codes_remaining != 1 else '' }} de récupération restant{{ 's' if recovery_codes_remaining != 1 else '' }}.</p>

View File

@@ -5,7 +5,7 @@
{% block content %}
<section class="min-h-[calc(100vh-62px)] bg-brand-bg py-16 px-4" aria-labelledby="verify-success-title">
<div class="max-w-md mx-auto bg-white p-8 rounded-xl border border-brand-border shadow-cta text-center">
<div class="max-w-md mx-auto bg-white p-8 rounded-lg border border-brand-border shadow-cta text-center">
<div class="mx-auto mb-6 w-16 h-16 rounded-full bg-green-100 text-green-700 flex items-center justify-center text-3xl font-black" aria-hidden="true">&check;</div>
<h1 id="verify-success-title" class="text-2xl font-black text-brand-navy mb-2">Votre courriel a été vérifié</h1>
@@ -14,7 +14,7 @@
</p>
<a href="{{ url_for('auth.login') }}"
class="inline-block w-full grad-bg text-white font-semibold py-3 rounded-lg shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
class="inline-block w-full grad-bg text-white font-semibold py-3 rounded shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
Se connecter
</a>

View File

@@ -24,7 +24,7 @@
<div class="max-w-[820px] mx-auto px-6">
<h2 id="info-title" class="sr-only">Que faire ensuite</h2>
<div class="bg-white p-8 rounded-xl border border-brand-border mb-8">
<div class="bg-white p-8 rounded-lg border border-brand-border mb-8">
<h3 class="text-lg font-bold mb-3 text-brand-navy">Pourquoi avoir hésité&nbsp;?</h3>
<p class="text-sm text-brand-navy/80 leading-relaxed mb-4">
Si vous avez une question sur les forfaits, la conformité Loi&nbsp;25 ou la mise en service, notre équipe peut vous accompagner sans pression commerciale.

View File

@@ -27,7 +27,7 @@
</h2>
<ol class="space-y-6">
<li class="bg-white p-6 rounded-xl border border-brand-border flex gap-4">
<li class="bg-white p-6 rounded-lg border border-brand-border flex gap-4">
<span class="grad-bg text-white font-black w-10 h-10 rounded-full flex items-center justify-center flex-shrink-0 shadow-cta" aria-hidden="true">1</span>
<div>
<h3 class="font-bold text-brand-navy mb-1">Confirmation par courriel</h3>
@@ -37,7 +37,7 @@
</div>
</li>
<li class="bg-white p-6 rounded-xl border border-brand-border flex gap-4">
<li class="bg-white p-6 rounded-lg border border-brand-border flex gap-4">
<span class="grad-bg text-white font-black w-10 h-10 rounded-full flex items-center justify-center flex-shrink-0 shadow-cta" aria-hidden="true">2</span>
<div>
<h3 class="font-bold text-brand-navy mb-1">Activation de votre abonnement</h3>
@@ -47,7 +47,7 @@
</div>
</li>
<li class="bg-white p-6 rounded-xl border border-brand-border flex gap-4">
<li class="bg-white p-6 rounded-lg border border-brand-border flex gap-4">
<span class="grad-bg text-white font-black w-10 h-10 rounded-full flex items-center justify-center flex-shrink-0 shadow-cta" aria-hidden="true">3</span>
<div>
<h3 class="font-bold text-brand-navy mb-1">Mise en service</h3>

View File

@@ -99,7 +99,7 @@
background-color: rgba(247, 249, 252, 0.6);
padding: 0.75rem 1rem;
margin: 1.25rem 0;
border-radius: 0 8px 8px 0;
border-radius: 0 4px 4px 0;
font-style: italic;
color: rgba(6, 13, 26, 0.75);
}
@@ -113,7 +113,7 @@
.legal-content pre {
background-color: #f7f9fc;
border: 1px solid #e6ebf2;
border-radius: 8px;
border-radius: 4px;
padding: 1rem;
overflow-x: auto;
margin-bottom: 1.25rem;
@@ -137,7 +137,7 @@
border-left: 4px solid #f59e0b;
padding: 0.75rem 1rem;
margin: 1rem 0 1.5rem;
border-radius: 0 8px 8px 0;
border-radius: 0 4px 4px 0;
font-size: 0.9rem;
color: #78350f;
}
@@ -199,7 +199,7 @@
{% block content %}
{# Skip link (WCAG 2.4.1) — visible uniquement au focus clavier. #}
<a href="#main-content"
class="sr-only focus:not-sr-only focus:fixed focus:top-2 focus:left-2 focus:z-[100] focus:px-4 focus:py-2 focus:bg-brand-navy focus:text-white focus:rounded-lg focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
class="sr-only focus:not-sr-only focus:fixed focus:top-2 focus:left-2 focus:z-[100] focus:px-4 focus:py-2 focus:bg-brand-navy focus:text-white focus:rounded focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
Aller au contenu principal
</a>
@@ -221,7 +221,7 @@
<article id="main-content"
role="main"
aria-labelledby="legal-title"
class="bg-white p-6 md:p-10 rounded-xl border border-brand-border shadow-cta order-1">
class="bg-white p-6 md:p-10 rounded-lg border border-brand-border shadow-cta order-1">
<header class="mb-8 pb-6 border-b border-brand-border">
<p class="text-xs uppercase tracking-wider text-brand-navy/70 mb-2">Document légal DictIA</p>
<h1 id="legal-title" class="text-3xl md:text-4xl font-black text-brand-navy mb-4 tracking-tight">{{ title }}</h1>
@@ -244,8 +244,8 @@
</header>
{# TOC mobile (collapsible) — visible < lg seulement #}
<details class="lg:hidden mb-6 border border-brand-border rounded-xl bg-brand-bg/50">
<summary class="cursor-pointer px-4 py-3 text-sm font-semibold text-brand-navy flex items-center justify-between focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2 rounded-xl">
<details class="lg:hidden mb-6 border border-brand-border rounded-lg bg-brand-bg/50">
<summary class="cursor-pointer px-4 py-3 text-sm font-semibold text-brand-navy flex items-center justify-between focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2 rounded-lg">
<span>Sur cette page</span>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
@@ -268,7 +268,7 @@
{% if prev_page %}
<a href="{{ url_for('legal.legal_page', page=prev_page) }}"
rel="prev"
class="block p-4 bg-brand-bg/60 border border-brand-border rounded-xl hover:border-brand-b1 hover:bg-white transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
class="block p-4 bg-brand-bg/60 border border-brand-border rounded-lg hover:border-brand-b1 hover:bg-white transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
<span class="block text-xs uppercase tracking-wider text-brand-navy/60 mb-1">
<span aria-hidden="true"></span> Précédent
</span>
@@ -281,7 +281,7 @@
{% if next_page %}
<a href="{{ url_for('legal.legal_page', page=next_page) }}"
rel="next"
class="block p-4 bg-brand-bg/60 border border-brand-border rounded-xl hover:border-brand-b1 hover:bg-white transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2 sm:text-right">
class="block p-4 bg-brand-bg/60 border border-brand-border rounded-lg hover:border-brand-b1 hover:bg-white transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2 sm:text-right">
<span class="block text-xs uppercase tracking-wider text-brand-navy/60 mb-1">
Suivant <span aria-hidden="true"></span>
</span>
@@ -304,7 +304,7 @@
aria-label="Table des matières">
<div x-data="legalToc()"
x-init="init()"
class="legal-toc bg-white border border-brand-border rounded-xl p-5 mt-0">
class="legal-toc bg-white border border-brand-border rounded-lg p-5 mt-0">
<h2 class="text-xs font-bold uppercase tracking-wider text-brand-navy/70 mb-3">
Sur cette page
</h2>

View File

@@ -33,7 +33,7 @@
{% block content %}
<a href="#main-content"
class="sr-only focus:not-sr-only focus:fixed focus:top-2 focus:left-2 focus:z-[100] focus:px-4 focus:py-2 focus:bg-brand-navy focus:text-white focus:rounded-lg focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
class="sr-only focus:not-sr-only focus:fixed focus:top-2 focus:left-2 focus:z-[100] focus:px-4 focus:py-2 focus:bg-brand-navy focus:text-white focus:rounded focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
Aller au contenu principal
</a>
@@ -68,13 +68,13 @@
<a href="{{ page.url }}"
target="_blank"
rel="noopener noreferrer"
class="legal-card is-external group block h-full p-5 md:p-6 bg-white border border-brand-border rounded-xl hover:border-brand-b1 hover:shadow-cta focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2 relative">
class="legal-card is-external group block h-full p-5 md:p-6 bg-white border border-brand-border rounded-lg hover:border-brand-b1 hover:shadow-cta focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2 relative">
{% else %}
<a href="{{ url_for('legal.legal_page', page=page.slug) }}"
class="legal-card group block h-full p-5 md:p-6 bg-white border border-brand-border rounded-xl hover:border-brand-b1 hover:shadow-cta focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2 relative">
class="legal-card group block h-full p-5 md:p-6 bg-white border border-brand-border rounded-lg hover:border-brand-b1 hover:shadow-cta focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2 relative">
{% endif %}
<div class="flex items-start gap-4">
<div class="legal-card-icon shrink-0 inline-flex items-center justify-center w-12 h-12 rounded-xl">
<div class="legal-card-icon shrink-0 inline-flex items-center justify-center w-12 h-12 rounded">
{{ page.icon | safe }}
</div>
<div class="flex-1 min-w-0">
@@ -97,7 +97,7 @@
</ul>
{# Bloc info pied — signature, contact, sous-processeurs #}
<aside class="mt-12 max-w-3xl mx-auto bg-white border border-brand-border rounded-xl p-6 md:p-7"
<aside class="mt-12 max-w-3xl mx-auto bg-white border border-brand-border rounded-lg p-6 md:p-7"
aria-label="Informations complémentaires sur les documents légaux">
<p class="text-sm text-brand-navy/80 leading-relaxed mb-3">
Documents signés numériquement par <strong class="text-brand-navy">Allison Rioux</strong>,

View File

@@ -5,7 +5,7 @@
{% block content %}
<section class="min-h-[calc(100vh-62px)] bg-brand-bg py-16 px-4" aria-labelledby="login-title">
<div class="max-w-md mx-auto bg-white p-8 rounded-xl border border-brand-border shadow-cta">
<div class="max-w-md mx-auto bg-white p-8 rounded-lg border border-brand-border shadow-cta">
<h1 id="login-title" class="text-3xl font-black text-brand-navy mb-2">Connexion</h1>
<p class="text-sm text-brand-navy/70 mb-6">{{ "Bienvenue sur DictIA — la transcription IA conforme à la Loi&nbsp;25." | safe }}</p>
@@ -28,7 +28,7 @@
<div class="space-y-3 mb-6" aria-label="Connexion fédérée">
{% if oauth_microsoft_enabled %}
<a href="{{ url_for('auth.oauth_provider_login', provider='microsoft') }}"
class="w-full inline-flex items-center justify-center gap-3 px-4 py-3 bg-white border border-brand-border rounded-lg text-brand-navy font-semibold hover:bg-brand-bg transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
class="w-full inline-flex items-center justify-center gap-3 px-4 py-3 bg-white border border-brand-border rounded text-brand-navy font-semibold hover:bg-brand-bg transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
{# Official Microsoft 4-square logo #}
<svg width="20" height="20" viewBox="0 0 21 21" aria-hidden="true" focusable="false">
<rect x="1" y="1" width="9" height="9" fill="#F25022"/>
@@ -42,7 +42,7 @@
{% if oauth_google_enabled %}
<a href="{{ url_for('auth.oauth_provider_login', provider='google') }}"
class="w-full inline-flex items-center justify-center gap-3 px-4 py-3 bg-white border border-brand-border rounded-lg text-brand-navy font-semibold hover:bg-brand-bg transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
class="w-full inline-flex items-center justify-center gap-3 px-4 py-3 bg-white border border-brand-border rounded text-brand-navy font-semibold hover:bg-brand-bg transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
{# Official Google "G" logo #}
<svg width="20" height="20" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.76h3.56c2.08-1.92 3.28-4.74 3.28-8.09Z"/>
@@ -56,7 +56,7 @@
{% if sso_enabled %}
<a href="{{ url_for('auth.sso_login') }}"
class="w-full inline-flex items-center justify-center gap-3 px-4 py-3 bg-white border border-brand-border rounded-lg text-brand-navy font-semibold hover:bg-brand-bg transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
class="w-full inline-flex items-center justify-center gap-3 px-4 py-3 bg-white border border-brand-border rounded text-brand-navy font-semibold hover:bg-brand-bg transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
<rect x="3" y="11" width="18" height="11" rx="2"/>
<path d="M7 11V7a5 5 0 0 1 10 0v4"/>
@@ -81,25 +81,25 @@
<div>
<label for="email" class="block text-sm font-medium text-brand-navy mb-1">Courriel <span class="text-red-600" aria-hidden="true">*</span></label>
{{ form.email(id='email', type='email', autocomplete='email', required=true, **{'aria-required':'true', 'class':'w-full px-3 py-2 border border-brand-border rounded-md text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{{ form.email(id='email', type='email', autocomplete='email', required=true, **{'aria-required':'true', 'class':'w-full px-3 py-2 border border-brand-border rounded text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{% if form.email.errors %}<p class="text-xs text-red-700 mt-1" role="alert">{{ form.email.errors[0] }}</p>{% endif %}
</div>
<div>
<label for="password" class="block text-sm font-medium text-brand-navy mb-1">Mot de passe <span class="text-red-600" aria-hidden="true">*</span></label>
{{ form.password(id='password', autocomplete='current-password', required=true, **{'aria-required':'true', 'class':'w-full px-3 py-2 border border-brand-border rounded-md text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{{ form.password(id='password', autocomplete='current-password', required=true, **{'aria-required':'true', 'class':'w-full px-3 py-2 border border-brand-border rounded text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{% if form.password.errors %}<p class="text-xs text-red-700 mt-1" role="alert">{{ form.password.errors[0] }}</p>{% endif %}
</div>
<div class="flex items-center justify-between text-sm">
<label for="remember" class="flex items-center gap-2 text-brand-navy/90 cursor-pointer">
{{ form.remember(id='remember', **{'class':'focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{{ form.remember(id='remember', **{'class':'rounded-sm focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
<span>Se souvenir de moi</span>
</label>
<a href="{{ url_for('auth.forgot_password') }}" class="grad-text font-semibold hover:underline">Mot de passe oublié&nbsp;?</a>
</div>
<button type="submit" class="w-full grad-bg text-white font-semibold py-3 rounded-lg shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
<button type="submit" class="w-full grad-bg text-white font-semibold py-3 rounded shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
Se connecter
</button>
</form>

View File

@@ -3,10 +3,10 @@
so dynamic `col-span-{{ span }}` would produce dead classes — the lookup keeps the utilities discoverable). #}
{% macro bento_card(number, title, description, icon='✦', span='1') %}
{%- set span_classes = {'1': 'col-span-1', '2': 'sm:col-span-2', '3': 'sm:col-span-2 md:col-span-3'} -%}
<div class="relative bg-brand-navy2 p-6 rounded-xl overflow-hidden border border-white/[0.045] {{ span_classes.get(span, 'col-span-1') }}">
<div class="relative bg-brand-navy2 p-6 rounded-lg overflow-hidden border border-white/[0.045] {{ span_classes.get(span, 'col-span-1') }}">
<div class="absolute top-2 right-4 text-[80px] font-black text-white/[0.04]" aria-hidden="true">{{ number }}</div>
<div class="relative">
<div class="w-10 h-10 grad-bg rounded-md mb-4 flex items-center justify-center text-lg">{{ icon }}</div>
<div class="w-10 h-10 grad-bg rounded mb-4 flex items-center justify-center text-lg">{{ icon }}</div>
<h3 class="text-lg font-bold mb-2 text-white">{{ title | safe }}</h3>
<p class="text-sm text-white/70">{{ description | safe }}</p>
</div>

View File

@@ -14,13 +14,13 @@
{%- set sizing = sizes.get(size, sizes['md']) -%}
{%- if as_button -%}
<button type="{{ type }}"
class="inline-flex items-center justify-center gap-2 rounded-lg font-semibold transition-all duration-200 {{ classes }} {{ sizing }}">
class="inline-flex items-center justify-center gap-2 rounded font-semibold transition-all duration-200 {{ classes }} {{ sizing }}">
<span>{{ text }}</span>
{%- if icon -%}<span class="ml-0.5" aria-hidden="true">{{ icon | safe }}</span>{%- endif -%}
</button>
{%- else -%}
<a href="{{ href }}"
class="inline-flex items-center justify-center gap-2 rounded-lg font-semibold transition-all duration-200 {{ classes }} {{ sizing }}"
class="inline-flex items-center justify-center gap-2 rounded font-semibold transition-all duration-200 {{ classes }} {{ sizing }}"
{% if target %}target="{{ target }}"{% endif %}
{% if rel %}rel="{{ rel }}"{% endif %}>
<span>{{ text }}</span>

View File

@@ -15,9 +15,9 @@
The button macro autoescapes its `text` arg, so `name` MUST NOT contain HTML entities
(verified: "DictIA 8", "DictIA 16", "DictIA Cloud" are all entity-free). #}
{%- macro pricing_card(slug, name, price_setup, price_monthly, target, features, recommended=False, cta_url='/checkout') -%}
<div class="relative {% if recommended %}grad-bg p-[1.5px] rounded-xl{% endif %}">
<div class="relative {% if recommended %}grad-bg p-[1.5px] rounded-lg{% endif %}">
{% if recommended %}<span class="absolute -top-3 left-1/2 -translate-x-1/2 grad-bg text-white text-xs font-bold px-3 py-1 rounded-full shadow-cta">★ RECOMMANDÉ</span>{% endif %}
<div class="bg-white p-8 rounded-xl border border-brand-border h-full flex flex-col">
<div class="bg-white p-8 rounded-lg border border-brand-border h-full flex flex-col">
<div class="mb-6">
<h3 class="text-xl font-black mb-1 text-brand-navy">{{ name | safe }}</h3>
<p class="text-sm text-brand-navy/70">{{ target | safe }}</p>

View File

@@ -52,8 +52,8 @@
'desc': 'Fork du projet open source Speakr — architecture entièrement auditable sur <a href="https://gitea.dictia.ca/Innova-AI/dictia-public" target="_blank" rel="noopener" class="underline hover:text-brand-navy">Gitea public</a>. Aucune boîte noire. Vos auditeurs peuvent examiner chaque ligne.'
}
] %}
<article class="bg-brand-bg p-6 rounded-xl border border-brand-border">
<div class="w-10 h-10 grad-bg rounded-md mb-4 flex items-center justify-center text-lg shadow-cta" aria-hidden="true">{{ card.icon }}</div>
<article class="bg-brand-bg p-6 rounded-lg border border-brand-border">
<div class="w-10 h-10 grad-bg rounded mb-4 flex items-center justify-center text-lg shadow-cta" aria-hidden="true">{{ card.icon }}</div>
<h3 class="text-lg font-bold mb-2 text-brand-navy">{{ card.title | safe }}</h3>
<p class="text-sm text-brand-navy/80 leading-relaxed">{{ card.desc | safe }}</p>
</article>
@@ -93,10 +93,10 @@
'desc': 'Avant tout enregistrement, DictIA exige une confirmation que les participants ont consenti à l\'enregistrement et à la transcription IA. Le consentement est tracé dans le journal d\'audit. Vous pouvez configurer une demande de consentement automatique en début de session.'
}
] %}
<article class="bg-white p-6 rounded-xl border border-brand-border">
<article class="bg-white p-6 rounded-lg border border-brand-border">
<div class="flex flex-col md:flex-row md:items-start gap-4">
<div class="flex-shrink-0">
<span class="inline-block bg-brand-navy text-white text-xs font-black px-3 py-1.5 rounded-md">{{ art.num | safe }}</span>
<span class="inline-block bg-brand-navy text-white text-xs font-black px-3 py-1.5 rounded">{{ art.num | safe }}</span>
</div>
<div>
<h3 class="text-lg font-bold mb-2 text-brand-navy">{{ art.title | safe }}</h3>

View File

@@ -25,8 +25,8 @@
<div class="grid md:grid-cols-3 gap-6">
{# Email card #}
<article class="bg-white p-8 rounded-xl border border-brand-border flex flex-col">
<div class="w-12 h-12 grad-bg rounded-md mb-4 flex items-center justify-center text-2xl shadow-cta" aria-hidden="true">✉️</div>
<article class="bg-white p-8 rounded-lg border border-brand-border flex flex-col">
<div class="w-12 h-12 grad-bg rounded mb-4 flex items-center justify-center text-2xl shadow-cta" aria-hidden="true">✉️</div>
<h3 class="text-lg font-bold mb-2 text-brand-navy">Courriel</h3>
<p class="text-sm text-brand-navy/80 mb-4 leading-relaxed flex-grow">
Privilégiez le courriel pour&nbsp;: pré-inscription, devis, démonstration, dossier de conformité, partenariats.
@@ -35,8 +35,8 @@
</article>
{# Phone card #}
<article class="bg-white p-8 rounded-xl border border-brand-border flex flex-col">
<div class="w-12 h-12 grad-bg rounded-md mb-4 flex items-center justify-center text-2xl shadow-cta" aria-hidden="true">☎️</div>
<article class="bg-white p-8 rounded-lg border border-brand-border flex flex-col">
<div class="w-12 h-12 grad-bg rounded mb-4 flex items-center justify-center text-2xl shadow-cta" aria-hidden="true">☎️</div>
<h3 class="text-lg font-bold mb-2 text-brand-navy">Téléphone</h3>
<p class="text-sm text-brand-navy/80 mb-4 leading-relaxed flex-grow">
Du lundi au vendredi, 9&nbsp;h à 17&nbsp;h (heure de l'Est). Laissez un message en dehors de ces heures.
@@ -45,8 +45,8 @@
</article>
{# Mailing address card #}
<article class="bg-white p-8 rounded-xl border border-brand-border flex flex-col">
<div class="w-12 h-12 grad-bg rounded-md mb-4 flex items-center justify-center text-2xl shadow-cta" aria-hidden="true">📬</div>
<article class="bg-white p-8 rounded-lg border border-brand-border flex flex-col">
<div class="w-12 h-12 grad-bg rounded mb-4 flex items-center justify-center text-2xl shadow-cta" aria-hidden="true">📬</div>
<h3 class="text-lg font-bold mb-2 text-brand-navy">Bureau</h3>
<p class="text-sm text-brand-navy/80 mb-4 leading-relaxed flex-grow">
Sur rendez-vous uniquement. Visites en personne pour démonstrations on-premise et déploiements DictIA 16 corporatifs.
@@ -83,7 +83,7 @@
{'label': 'Question média / presse', 'subject': 'Question%20m%C3%A9dia', 'icon': '📰'}
] %}
<a href="mailto:info@dictia.ca?subject={{ shortcut.subject }}"
class="flex items-center gap-3 bg-brand-bg p-4 rounded-xl border border-brand-border hover:bg-white hover:border-brand-b1/30 transition-colors focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
class="flex items-center gap-3 bg-brand-bg p-4 rounded-lg border border-brand-border hover:bg-white hover:border-brand-b1/30 transition-colors focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
<span class="text-2xl flex-shrink-0" aria-hidden="true">{{ shortcut.icon }}</span>
<span class="text-sm font-semibold text-brand-navy">{{ shortcut.label | safe }}</span>
</a>

View File

@@ -25,7 +25,7 @@
{# 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. #}
{% from 'macros/bento.html' import bento_card %}
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-[1.5px] bg-brand-border rounded-xl overflow-hidden">
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-[1.5px] bg-brand-border rounded-lg 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).', '🎙️') }}
{{ bento_card('02', 'Diarisation 8 locuteurs', 'pyannote sépare automatiquement les intervenants. Identification par embeddings vocaux.', '👥') }}
{{ 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.', '📝') }}
@@ -55,7 +55,7 @@
{'ext': 'JSON', 'use': 'Pipeline développeur'},
{'ext': 'MD', 'use': 'Notion, Obsidian, GitHub'}
] %}
<div class="bg-white p-4 rounded-xl border border-brand-border text-center">
<div class="bg-white p-4 rounded-lg border border-brand-border text-center">
<p class="text-base font-black text-brand-navy">{{ fmt.ext }}</p>
<p class="text-xs text-brand-navy/70 mt-1">{{ fmt.use | safe }}</p>
</div>
@@ -87,7 +87,7 @@
{'name': 'Make (Integromat)', 'desc': 'Scénarios visuels'},
{'name': 'n8n', 'desc': 'Open source self-host'}
] %}
<div class="bg-brand-bg p-5 rounded-xl border border-brand-border text-center">
<div class="bg-brand-bg p-5 rounded-lg border border-brand-border text-center">
<p class="text-base font-bold text-brand-navy">{{ integ.name | safe }}</p>
<p class="text-xs text-brand-navy/70 mt-1">{{ integ.desc | safe }}</p>
</div>

View File

@@ -176,7 +176,7 @@
('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-lg border border-white/[0.08]">
<div class="w-10 h-10 grad-bg rounded-md mb-4 flex items-center justify-center font-black text-white shadow-cta" aria-hidden="true"></div>
<div class="w-10 h-10 grad-bg rounded mb-4 flex items-center justify-center font-black text-white shadow-cta" aria-hidden="true"></div>
<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>
@@ -198,7 +198,7 @@
{# 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. #}
{% from 'macros/bento.html' import bento_card %}
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-[1.5px] bg-brand-border rounded-xl overflow-hidden">
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-[1.5px] bg-brand-border rounded-lg 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).', '🎙️') }}
{{ bento_card('02', 'Diarisation 8 locuteurs', 'pyannote sépare automatiquement les intervenants. Identification par embeddings vocaux.', '👥') }}
{{ 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.', '📝') }}
@@ -225,7 +225,7 @@
{% include 'marketing/_partials/_pricing_tiers.html' %}
{# ROI CALCULATOR — Alpine.js, hypotheses transparentes pour LPC art. 219 hygiene #}
<div x-data="roiCalculator()" class="mt-16 max-w-3xl mx-auto bg-white p-8 rounded-xl border border-brand-border" aria-labelledby="roi-title">
<div x-data="roiCalculator()" class="mt-16 max-w-3xl mx-auto bg-white p-8 rounded-lg 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">
@@ -272,7 +272,7 @@
</p>
</div>
<div class="overflow-x-auto rounded-xl border border-brand-border">
<div class="overflow-x-auto rounded-lg 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">
@@ -332,7 +332,7 @@
<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-block px-2 py-1 rounded-md bg-brand-b3/10 text-brand-navy">{{ row.dictia | safe }}</span>
<span class="inline-block px-2 py-1 rounded bg-brand-b3/10 text-brand-navy">{{ row.dictia | safe }}</span>
</td>
<td class="p-4 text-center text-brand-navy/70">{{ row.teams | safe }}</td>
<td class="p-4 text-center text-brand-navy/70">{{ row.otter | safe }}</td>
@@ -391,7 +391,7 @@
}
] %}
<article class="bg-white/[0.05] backdrop-blur-sm p-6 rounded-lg border border-white/[0.08]">
<div class="w-10 h-10 grad-bg rounded-md mb-4 flex items-center justify-center text-lg shadow-cta" aria-hidden="true">{{ card.icon }}</div>
<div class="w-10 h-10 grad-bg rounded mb-4 flex items-center justify-center text-lg shadow-cta" aria-hidden="true">{{ card.icon }}</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>
@@ -421,7 +421,7 @@
<div class="grid md:grid-cols-3 gap-6">
{% for t in testimonials %}
<article class="bg-white p-6 rounded-xl border border-brand-border flex flex-col items-center text-center"
<article class="bg-white p-6 rounded-lg 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" aria-hidden="true">
{%- if t.persona == 'avocat' -%}<span class="text-2xl">⚖️</span>
@@ -459,7 +459,7 @@
<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-md px-2 focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
class="w-full flex items-center justify-between gap-4 py-4 text-left hover:bg-brand-bg/50 transition-colors rounded 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 }}">

View File

@@ -36,7 +36,7 @@
</h2>
</div>
<div class="overflow-x-auto rounded-xl border border-brand-border">
<div class="overflow-x-auto rounded-lg border border-brand-border">
<table class="w-full min-w-[720px] text-sm">
<caption class="sr-only">Comparaison détaillée des 3 forfaits DictIA sur 8 caractéristiques</caption>
<thead class="bg-brand-bg">
@@ -94,7 +94,7 @@
<div x-data="{ open: false }" class="py-2">
<h3>
<button type="button"
class="w-full flex items-center justify-between gap-4 py-4 text-left hover:bg-brand-navy/[0.03] transition-colors rounded-md px-2 focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2"
class="w-full flex items-center justify-between gap-4 py-4 text-left hover:bg-brand-navy/[0.03] transition-colors rounded 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="tarifs-faq-panel-{{ loop.index }}">

View File

@@ -5,7 +5,7 @@
{% block content %}
<section class="min-h-[calc(100vh-62px)] bg-brand-bg py-16 px-4" aria-labelledby="signup-title">
<div class="max-w-md mx-auto bg-white p-8 rounded-xl border border-brand-border shadow-cta">
<div class="max-w-md mx-auto bg-white p-8 rounded-lg border border-brand-border shadow-cta">
<h1 id="signup-title" class="text-3xl font-black text-brand-navy mb-2">Créer un compte</h1>
<p class="text-sm text-brand-navy/70 mb-6">{{ "Conformité Loi&nbsp;25 incluse — consentement granulaire, hébergement au Québec." | safe }}</p>
@@ -28,45 +28,45 @@
<div>
<label for="email" class="block text-sm font-medium text-brand-navy mb-1">Courriel <span class="text-red-600" aria-hidden="true">*</span></label>
{{ form.email(id='email', type='email', autocomplete='email', required=true, **{'aria-required':'true', 'class':'w-full px-3 py-2 border border-brand-border rounded-md text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{{ form.email(id='email', type='email', autocomplete='email', required=true, **{'aria-required':'true', 'class':'w-full px-3 py-2 border border-brand-border rounded text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{% if form.email.errors %}<p class="text-xs text-red-700 mt-1">{{ form.email.errors[0] }}</p>{% endif %}
</div>
<div>
<label for="password" class="block text-sm font-medium text-brand-navy mb-1">Mot de passe <span class="text-red-600" aria-hidden="true">*</span></label>
{{ form.password(id='password', autocomplete='new-password', required=true, minlength=8, **{'aria-required':'true', 'aria-describedby':'password-help', 'class':'w-full px-3 py-2 border border-brand-border rounded-md text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{{ form.password(id='password', autocomplete='new-password', required=true, minlength=8, **{'aria-required':'true', 'aria-describedby':'password-help', 'class':'w-full px-3 py-2 border border-brand-border rounded text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{% if form.password.errors %}<p class="text-xs text-red-900 mt-1">{{ form.password.errors[0] }}</p>{% endif %}
<p id="password-help" class="text-xs text-brand-navy/70 mt-1">8&nbsp;caractères minimum, dont une majuscule, une minuscule, un chiffre et un caractère spécial.</p>
</div>
<div>
<label for="confirm_password" class="block text-sm font-medium text-brand-navy mb-1">Confirmer le mot de passe <span class="text-red-600" aria-hidden="true">*</span></label>
{{ form.confirm_password(id='confirm_password', autocomplete='new-password', required=true, **{'aria-required':'true', 'class':'w-full px-3 py-2 border border-brand-border rounded-md text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{{ form.confirm_password(id='confirm_password', autocomplete='new-password', required=true, **{'aria-required':'true', 'class':'w-full px-3 py-2 border border-brand-border rounded text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{% if form.confirm_password.errors %}<p class="text-xs text-red-700 mt-1">{{ form.confirm_password.errors[0] }}</p>{% endif %}
</div>
<div class="grid grid-cols-2 gap-3">
<div>
<label for="first_name" class="block text-sm font-medium text-brand-navy mb-1">Prénom <span class="text-red-600" aria-hidden="true">*</span></label>
{{ form.first_name(id='first_name', autocomplete='given-name', required=true, **{'aria-required':'true', 'class':'w-full px-3 py-2 border border-brand-border rounded-md text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{{ form.first_name(id='first_name', autocomplete='given-name', required=true, **{'aria-required':'true', 'class':'w-full px-3 py-2 border border-brand-border rounded text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{% if form.first_name.errors %}<p class="text-xs text-red-700 mt-1">{{ form.first_name.errors[0] }}</p>{% endif %}
</div>
<div>
<label for="last_name" class="block text-sm font-medium text-brand-navy mb-1">Nom <span class="text-red-600" aria-hidden="true">*</span></label>
{{ form.last_name(id='last_name', autocomplete='family-name', required=true, **{'aria-required':'true', 'class':'w-full px-3 py-2 border border-brand-border rounded-md text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{{ form.last_name(id='last_name', autocomplete='family-name', required=true, **{'aria-required':'true', 'class':'w-full px-3 py-2 border border-brand-border rounded text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{% if form.last_name.errors %}<p class="text-xs text-red-700 mt-1">{{ form.last_name.errors[0] }}</p>{% endif %}
</div>
</div>
<div>
<label for="cabinet" class="block text-sm font-medium text-brand-navy mb-1">Cabinet / Organisation</label>
{{ form.cabinet(id='cabinet', autocomplete='organization', **{'class':'w-full px-3 py-2 border border-brand-border rounded-md text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{{ form.cabinet(id='cabinet', autocomplete='organization', **{'class':'w-full px-3 py-2 border border-brand-border rounded text-brand-navy focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{% if form.cabinet.errors %}<p class="text-xs text-red-700 mt-1">{{ form.cabinet.errors[0] }}</p>{% endif %}
</div>
<div>
<label for="ordre_pro" class="block text-sm font-medium text-brand-navy mb-1">Ordre professionnel</label>
{{ form.ordre_pro(id='ordre_pro', **{'class':'w-full px-3 py-2 border border-brand-border rounded-md text-brand-navy bg-white focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{{ form.ordre_pro(id='ordre_pro', **{'class':'w-full px-3 py-2 border border-brand-border rounded text-brand-navy bg-white focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
</div>
{# 4 SEPARATE consent checkboxes — Loi 25 art. 14 (consent must be granular, free, informed) #}
@@ -74,29 +74,29 @@
<legend class="text-xs font-semibold text-brand-navy uppercase tracking-wide mb-1">{{ "Consentements — Loi&nbsp;25" | safe }}</legend>
<label for="consent_cgu" class="flex items-start gap-2 text-sm text-brand-navy/90">
{{ form.consent_cgu(id='consent_cgu', required=true, **{'aria-required':'true', 'class':'mt-1 focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{{ form.consent_cgu(id='consent_cgu', required=true, **{'aria-required':'true', 'class':'mt-1 rounded-sm focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
<span>J'accepte les <a href="/legal/conditions" target="_blank" rel="noopener" class="grad-text underline">conditions d'utilisation</a>. <span class="text-red-600" aria-hidden="true">*</span></span>
</label>
{% if form.consent_cgu.errors %}<p class="text-xs text-red-900 mt-1" role="alert">{{ form.consent_cgu.errors[0] }}</p>{% endif %}
<label for="consent_confidentialite" class="flex items-start gap-2 text-sm text-brand-navy/90">
{{ form.consent_confidentialite(id='consent_confidentialite', required=true, **{'aria-required':'true', 'class':'mt-1 focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{{ form.consent_confidentialite(id='consent_confidentialite', required=true, **{'aria-required':'true', 'class':'mt-1 rounded-sm focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
<span>J'accepte la <a href="/legal/confidentialite" target="_blank" rel="noopener" class="grad-text underline">politique de confidentialité</a>. <span class="text-red-600" aria-hidden="true">*</span></span>
</label>
{% if form.consent_confidentialite.errors %}<p class="text-xs text-red-900 mt-1" role="alert">{{ form.consent_confidentialite.errors[0] }}</p>{% endif %}
<label for="consent_marketing" class="flex items-start gap-2 text-sm text-brand-navy/90">
{{ form.consent_marketing(id='consent_marketing', **{'class':'mt-1 focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{{ form.consent_marketing(id='consent_marketing', **{'class':'mt-1 rounded-sm focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
<span>J'accepte de recevoir des communications marketing (optionnel, désactivable à tout moment).</span>
</label>
<label for="consent_analytics" class="flex items-start gap-2 text-sm text-brand-navy/90">
{{ form.consent_analytics(id='consent_analytics', **{'class':'mt-1 focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{{ form.consent_analytics(id='consent_analytics', **{'class':'mt-1 rounded-sm focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
<span>J'accepte les statistiques d'usage anonymisées (optionnel, désactivable à tout moment).</span>
</label>
</fieldset>
{{ form.submit(**{'class':'w-full grad-bg text-white font-semibold py-3 rounded-lg shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
{{ form.submit(**{'class':'w-full grad-bg text-white font-semibold py-3 rounded shadow-cta hover:shadow-cta-hover transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2'}) }}
</form>
<p class="text-center text-sm text-brand-navy/70 mt-6">Déjà un compte ? <a href="{{ url_for('auth.login') }}" class="grad-text font-semibold">Se connecter</a></p>