Aller au contenu

Design: Platform Vision — Cross-Module UX Patterns

Brand: Papillon HR Suite

Date: 14/03/2026

Version: 1.0

Author: DESIGNER (Claude — Senior UX/UI Designer)

Depends on: docs/design/host-shell-design.md (Sprint 0 shell)

PRD: docs/prd/platform-vision-prd.md


For the DEVELOPER: This document defines every cross-cutting UX pattern shared by ALL modules. The host-shell-design.md covers the app shell (login, navigation, dashboard layout, sync indicator, notifications, PWA, dark mode, breakpoints). This document covers everything ELSE at the platform level: onboarding, tenant switching, module gating/upsell, approvals, billing, employee import, offline conflict resolution, and tenant status degradation.

If something is ambiguous, the design is wrong — flag it.


Table of Contents

  1. Design Decisions (Interview Summary)
  2. User Flow Diagrams
  3. Screen-by-Screen Wireframes
  4. Interaction Specifications
  5. Responsive Behavior
  6. Offline Behavior
  7. French Micro-copy
  8. Component Specs
  9. Motion Choreography
  10. Brand Compliance Checklist

1. Design Decisions

Nine UX decisions were resolved through collaborative interview with the Product Owner. Each decision is referenced by ID (D1–D9) throughout this document.

D1: Onboarding Flow — Step-by-Step Wizard

Decision: 5-step wizard with progress bar. One decision per screen. Auto-save per step. Resume on reconnect.

Rationale: Reduces cognitive load (Hick's Law). Familiar to target users from Wave/M-Pesa/Orange Money flows. Auto-save per step = offline-resilient. On 360px, each step fits without scrolling.

Steps: Account creation (public) → Company info → Owner status → Module selection + payment → Employee import (optional).

D2: Tenant Switcher — Top-Bar Company Badge

Decision: Company name always visible in the top bar. Tap opens tenant list (bottom sheet on mobile, dropdown on desktop). Single-tenant users see name only — no switcher UI.

Rationale: 80% of users belong to one tenant (zero overhead for them). 2-tap switch for the 20% (accountants managing multiple companies). Constant context awareness — Don Norman's principle of visibility.

D3: Module Upsell — Preview + CTA Card

Decision: Tapping a locked module opens a rich preview (bottom sheet on mobile, popover on desktop) with illustration, 3 benefits, segment-aware pricing, and "Essayer gratuitement (14j)" CTA.

Rationale: Zeigarnik Effect — showing what they COULD have creates upgrade desire. Segment-aware pricing enables instant mobile purchasing decisions (PLG). "Me notifier au lancement" toggle captures interest for unreleased modules.

D4: Unified Approval Inbox

Decision: Single "Approbations" screen lists ALL pending approvals across modules. Filter chips by module type. Swipe-to-approve on mobile. Online-only.

Rationale: Fitts's Law — grouping related actions reduces completion time. The DG opens ONE screen and processes all pending items in 2 minutes instead of visiting 3-4 module screens.

D5: Tenant Status Degradation — Persistent Banner + Functional Overlay

Decision: Warm-toned banner at top of every screen. All screens remain navigable (read-only). Write actions show contextual overlay with "Régulariser →" CTA. Never blocks navigation.

Rationale: Loss aversion — users feel losses 2x more than gains. Showing them their data (read-only) reminds them what they're losing. A full-screen block feels punitive and causes churn.

D6: Sync Conflicts — Auto-Resolve + Notification

Decision: 95% auto-resolved (server wins for approvals/financial ops, client wins for drafts). Clear notification explains what happened. 5% edge cases show "Garder ma version / Garder la version serveur" — no "Merge" option.

Rationale: Nielsen's heuristic — error recovery > error prevention. Most conflicts have an obvious correct answer. Manual merge is too complex for target users.

D7: Employee Import — Mobile-Capable with Desktop Nudge

Decision: Mobile uses card list per employee. Desktop uses editable spreadsheet table. For 30+ employees on mobile, non-blocking suggestion: "Pour plus de confort, terminez depuis un ordinateur."

Rationale: 85% of tenants (S1-S2) have ≤29 employees — card list works perfectly on mobile for them. Blocking mobile-only DGs (who may not have a desktop) violates mobile-first principle. Desktop nudge for large imports respects user choice.

Decision: Onboarding step 3 includes "Je suis le Représentant Légal" checkbox. - Checked → ask salarié/indépendant directly. - Unchecked → 3 options: "Oui salarié" / "Non indépendant" / "Je ne sais pas → envoyer un lien au gérant." - Magic link: tokenized URL, single-screen micro-form, no login, expires 7 days. Onboarding continues with INDEPENDANT as safe default.

Rationale: The person onboarding is typically the HR Manager, not the DG. Design for the real workflow: ask questions to the person who can answer them. When they can't answer, delegate asynchronously via magic link.

D9: Billing Page — Single Scrollable Page with Sections

Decision: One page: Plan summary card → Active modules list → Payment method → Invoice history. No tabs.

Rationale: DG reads top card and leaves (5-second glance). Comptable scrolls for invoice details. Progressive disclosure via scroll — no tab-switching needed.


2. User Flow Diagrams

2.1 Self-Onboarding Flow (D1, D8)

flowchart TD
    A[Landing page / Marketing site] --> B[Tap 'Créer mon compte']
    B --> C[Public signup form]
    C -->|Email + Phone + Password| D{CAPTCHA valid?}
    D -->|No| C
    D -->|Yes| E[Account created — PENDING_VERIFICATION]
    E --> F[Email verification sent]
    F --> G{Email verified?}
    G -->|No — resend| F
    G -->|Yes| H[Wizard Step 1: Infos entreprise]

    H -->|Company name, form, employee range, country| I[Wizard Step 2: Votre rôle + Statut gérant]
    I -->|"Je suis le RL" checked| J[Ask salarié/indépendant directly]
    I -->|"Je suis le RL" unchecked| K{HR knows DG status?}
    K -->|Oui salarié| L[Set owner = SALARIE]
    K -->|Non indépendant| M[Set owner = INDEPENDANT]
    K -->|Je ne sais pas| N[Magic link form: DG name + contact]
    N --> O[Send magic link to DG]
    O --> P[Set owner = INDEPENDANT — pending DG response]
    J --> Q[Set owner status]

    L --> R[Wizard Step 3: Choix des modules]
    M --> R
    P --> R
    Q --> R

    R -->|Select modules, see pricing| S[Wizard Step 4: Paiement]
    S -->|CinetPay: Orange Money / Wave / Card| T{Payment result?}
    T -->|Success| U[Tenant = ACTIVE]
    T -->|Failed| V[Tenant = PAYMENT_REQUIRED]
    T -->|Bank transfer chosen| W[Tenant = ACTIVE_PAYMENT_PENDING]
    T -->|Free trial| X[Tenant = TRIAL — 14 days]

    U --> Y[Wizard Step 5: Import employés — optional]
    V --> Y
    W --> Y
    X --> Y

    Y -->|Skip| Z[First login — Dashboard]
    Y -->|Upload Excel| AA[Parse + Editable confirmation]
    AA --> AB{Errors?}
    AB -->|Fix errors| AA
    AB -->|All valid| AC[Submit — create employees + send invitations]
    AC --> Z

    Z --> AD[🎉 Confetti — Bienvenue sur Papillon !]

    style U fill:#d4edda
    style V fill:#f8d7da
    style W fill:#fff3cd
    style X fill:#cce5ff

2.2 CRM-Assisted Onboarding Flow

flowchart TD
    A[Salesperson creates prospect in CRM] --> B[Prospect validated by CRM manager]
    B --> C[Tenant = PENDING_VALIDATION]
    C --> D{CRM manager approves?}
    D -->|Yes| E[Tenant provisioned — PENDING]
    D -->|No| F[Prospect rejected]
    E --> G[Admin invitation email sent to DG/HR]
    G --> H[DG/HR clicks link — lands on Wizard Step 1]
    H --> I[Same wizard flow as self-onboarding]

2.3 Tenant Switching Flow (D2)

flowchart TD
    A[User logged in — Tenant A active] --> B[Tap company badge in top bar]
    B --> C[Tenant list opens — bottom sheet / dropdown]
    C --> D[User selects Tenant B]
    D --> E{Online?}
    E -->|Yes| F[JWT re-issued with new tenant_id]
    F --> G[Subtle transition animation]
    G --> H[Dashboard reloads for Tenant B]
    E -->|No — offline| I[Switch to cached Tenant B data]
    I --> J[Show 'Données hors-ligne' indicator]
    J --> H

2.4 Module Activation Flow (D3)

flowchart TD
    A[User taps locked module in nav] --> B[Preview card opens — bottom sheet / popover]
    B --> C{Module released?}
    C -->|Yes — available| D[Show: illustration + benefits + pricing + CTA]
    C -->|No — coming soon| E[Show: illustration + benefits + 'Me notifier' toggle]

    D --> F{User taps 'Essayer gratuitement'?}
    F -->|Yes| G{User is DG/Admin?}
    G -->|Yes| H[Module activated — TRIAL — 14 days]
    G -->|No| I[Show: 'Seul un administrateur peut activer un module.']
    F -->|No — close| J[Preview dismissed]

    H --> K[Nav item unlocked — full color]
    K --> L[User navigates to new module]

    E --> M{User toggles 'Me notifier'?}
    M -->|Yes| N[Notification preference saved]
    M -->|No| J

2.5 Employee Import Flow (D7)

flowchart TD
    A[Admin opens 'Import employés'] --> B{Device?}
    B -->|Mobile| C[Show upload zone + 'ou ajouter un par un']
    B -->|Desktop| D[Show upload zone + template download]

    C --> E[User selects Excel file]
    D --> E

    E --> F[Parsing — skeleton shimmer]
    F --> G{Parse success?}
    G -->|Error — bad format| H[Show: 'Format non reconnu. Téléchargez le modèle.']
    G -->|Success| I{Employee count?}

    I -->|≤29 on mobile| J[Show editable card list]
    I -->|30+ on mobile| K[Show desktop nudge — non-blocking]
    K --> J
    I -->|Desktop| L[Show editable spreadsheet table]

    J --> M[User reviews/edits — fixes errors]
    L --> M

    M --> N{Validation errors?}
    N -->|Yes| O[Summary: '47 employés, 3 erreurs à corriger']
    O --> M
    N -->|All valid| P[Tap 'Créer X employés']

    P --> Q[Confirm: contact method per employee — EMAIL / SMS]
    Q --> R[Submit — create employees]
    R --> S[Send password creation links via selected channel]
    S --> T[Success: '47 employés créés ! Invitations envoyées.']

    style H fill:#f8d7da
    style T fill:#d4edda
flowchart TD
    A[HR picks 'Je ne sais pas' during onboarding] --> B[Mini-form: DG name + email/phone]
    B --> C[Tap 'Envoyer le lien']
    C --> D[System sends tokenized magic link via email/SMS]
    D --> E[Onboarding continues — owner = INDEPENDANT default]

    F[DG receives SMS/email with link] --> G[DG taps link — single-screen micro-form]
    G --> H{DG chooses?}
    H -->|Oui salarié| I[System updates owner = SALARIE]
    H -->|Non indépendant| J[System confirms owner = INDEPENDANT]
    I --> K[Employee record created for owner]
    K --> L[Dashboard shows updated status]
    J --> L

    M[Link expires after 7 days?] --> N[Reminder sent — new link]
    N --> G

    style I fill:#d4edda
    style J fill:#d4edda

2.7 Cross-Module Approval Flow (D4)

flowchart TD
    A[Employee submits request — leave/commitment/expense] --> B[Notification sent to approver]
    B --> C[Approver sees badge on dashboard + notification bell]
    C --> D[Approver opens Approbations screen]

    D --> E[List of pending approvals — filtered by type]
    E --> F{Approver action?}
    F -->|Approve — tap button or swipe right| G{Online?}
    F -->|Refuse — tap button or swipe left| H{Online?}
    F -->|Tap card for detail| I[Full request detail screen]
    I --> F

    G -->|Yes| J[Request approved — notification to employee]
    G -->|No| K[Show: 'Connexion requise pour approuver']
    H -->|Yes| L[Refuse modal: mandatory comment field]
    L --> M[Request refused — notification to employee]
    H -->|No| K

    style J fill:#d4edda
    style M fill:#f8d7da
    style K fill:#fff3cd

2.8 Billing Resolution Flow (D5, D9)

flowchart TD
    A[Tenant status → PAYMENT_REQUIRED or SUSPENDED] --> B[Degradation banner appears on all screens]
    B --> C[User taps 'Régulariser' on banner or overlay]
    C --> D[Billing page — Plan summary shows overdue status]
    D --> E{Payment method?}
    E -->|CinetPay — Orange Money / Wave / Card| F{Payment result?}
    E -->|Bank transfer| G[Show bank details + reference]

    F -->|Success| H[Tenant → ACTIVE — banner removed]
    F -->|Failed| I[Show: 'Paiement échoué. Réessayer.']
    I --> E

    G --> J[Tenant → ACTIVE_PAYMENT_PENDING — 10 day grace]
    J --> K{Transfer received within 10 days?}
    K -->|Yes — admin confirms| H
    K -->|No| L[Tenant → SUSPENDED]

    style H fill:#d4edda
    style L fill:#f8d7da

2.9 Sync Conflict Resolution Flow (D6)

flowchart TD
    A[Device reconnects — sync begins] --> B[Send queued offline writes to server]
    B --> C{Server accepts?}
    C -->|No conflict — accepted| D[✓ Synced notification]
    C -->|Conflict detected| E{Conflict type?}

    E -->|Approval on cancelled request| F[Auto-resolve: server wins]
    E -->|Financial op — stale data| G[Auto-resolve: server wins]
    E -->|Draft data — both modified| H{Same field modified?}

    F --> I[Notification: 'Approbation non appliquée — demande annulée']
    G --> J[Notification: 'Opération non appliquée — données modifiées']

    H -->|No — different fields| K[Auto-merge: combine both]
    H -->|Yes — same field| L[Manual resolution required]

    L --> M[Show: 'Garder ma version' / 'Garder la version serveur']
    M --> N[User chooses]
    N --> O[Conflict resolved — data saved]

    K --> D
    I --> D
    J --> D
    O --> D

    style D fill:#d4edda
    style L fill:#fff3cd

3. Screen-by-Screen Wireframes

3.1 Onboarding Wizard — Public Signup (before wizard)

Shaped by: D1 (step-by-step wizard)

MOBILE (360px):
┌──────────────────────────────────┐
│                                  │
│        🦋 Papillon HR Suite      │
│     Votre assistant RH           │
│     de confiance.                │
│                                  │
│  Nom complet                     │
│  ┌────────────────────────────┐  │
│  │ Jean-Pierre Kouassi        │  │
│  └────────────────────────────┘  │
│                                  │
│  Email                           │
│  ┌────────────────────────────┐  │
│  │ [email protected]              │  │
│  └────────────────────────────┘  │
│                                  │
│  Téléphone                       │
│  ┌──────┐ ┌──────────────────┐  │
│  │+225 ▼│ │ 07 89 12 34 56   │  │
│  └──────┘ └──────────────────┘  │
│                                  │
│  Mot de passe                    │
│  ┌────────────────────────────┐  │
│  │ ••••••••           👁      │  │
│  └────────────────────────────┘  │
│  Min. 8 caractères, 1 majuscule │
│                                  │
│  ┌────────────────────────────┐  │
│  │      Créer mon compte      │  │
│  └────────────────────────────┘  │
│                                  │
│  Déjà inscrit ? Se connecter    │
│                                  │
│  En créant un compte, vous      │
│  acceptez les CGU et la         │
│  politique de confidentialité.  │
└──────────────────────────────────┘

Components: uses Button variant=primary size=lg fullWidth, Input with label/helperText, phone prefix uses Select (or custom country code picker).

States: - Loading: Button shows spinner on submit - Error: Inline validation under each field. "Cette adresse email est déjà utilisée." / "Mot de passe trop court (min. 8 caractères)." - Offline: "Connexion requise pour créer un compte." overlay — account creation is online-only - Success: Navigate to email verification screen

3.2 Email Verification Screen

MOBILE (360px):
┌──────────────────────────────────┐
│                                  │
│        🦋 Papillon               │
│                                  │
│        ✉️                        │
│                                  │
│  Vérifiez votre email            │
│                                  │
│  Un lien de vérification a été   │
│  envoyé à :                      │
[email protected]│                                  │
│  Cliquez sur le lien dans        │
│  l'email pour continuer.         │
│                                  │
│                                  │
│  Vous n'avez rien reçu ?         │
│  ┌────────────────────────────┐  │
│  │    Renvoyer l'email        │  │
│  └────────────────────────────┘  │
│                                  │
│  💡 Vérifiez aussi vos           │
│  courriers indésirables.         │
│                                  │
└──────────────────────────────────┘

Components: uses Button variant=secondary size=lg fullWidth

States: - Loading: "Renvoi en cours..." on button - Success (resend): "Email renvoyé ✓" toast - Error: "Impossible de renvoyer. Réessayez." toast

3.3 Wizard Step 1: Infos entreprise

Shaped by: D1

MOBILE (360px):
┌──────────────────────────────────┐
│  ←                               │
│  ○───●───○───○───○       1/5     │
│                                  │
│  🏢 Votre entreprise             │
│                                  │
│  Nom de l'entreprise             │
│  ┌────────────────────────────┐  │
│  │ ALTARYS SARL               │  │
│  └────────────────────────────┘  │
│                                  │
│  Forme juridique                 │
│  ┌────────────────────────────┐  │
│  │ SARL                    ▼  │  │
│  └────────────────────────────┘  │
│  Options: SARL, SAS, SA, EI,    │
│  Autre                           │
│                                  │
│  Nombre d'employés               │
│  ┌────────────────────────────┐  │
│  │ 2-12 (TPE)              ▼  │  │
│  └────────────────────────────┘  │
│  Options: 2-12, 13-29, 30-49,   │
│  50-99, 100-199, 200-350         │
│                                  │
│  Pays                            │
│  ┌────────────────────────────┐  │
│  │ 🇨🇮 Côte d'Ivoire    ✓     │  │
│  └────────────────────────────┘  │
│  Pre-filled. MVP = CI only.      │
│                                  │
│  RCCM (optionnel)                │
│  ┌────────────────────────────┐  │
│  │                            │  │
│  └────────────────────────────┘  │
│  💡 Vous avez 3 mois pour le    │
│  renseigner.                     │
│                                  │
│  ┌────────────────────────────┐  │
│  │      Continuer    →        │  │
│  └────────────────────────────┘  │
│                                  │
└──────────────────────────────────┘

Smart defaults: Country pre-filled from IP geolocation (CI for MVP). Phone prefix pre-filled from country. Currency auto-set (XOF).

Validation: Company name required (min 2 chars). Form juridique required. Employee count required. RCCM optional (FR-PV-110).

3.4 Wizard Step 2: Votre rôle + Statut gérant

Shaped by: D8 (checkbox fork + magic link delegation)

MOBILE (360px) — Initial state:
┌──────────────────────────────────┐
│  ←                               │
│  ○───○───●───○───○       2/5     │
│                                  │
│  👤 Votre rôle                   │
│                                  │
│  ☐ Je suis le Représentant      │
│    Légal de l'entreprise         │
│    (gérant, DG, président)       │
│                                  │
│  ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─  │
│                                  │
│  (content below depends on       │
│   checkbox state)                │
│                                  │
└──────────────────────────────────┘

IF CHECKED — user IS the Représentant Légal:

┌──────────────────────────────────┐
│  ←                               │
│  ○───○───●───○───○       2/5     │
│                                  │
│  👤 Votre rôle                   │
│                                  │
│  ☑ Je suis le Représentant      │
│    Légal de l'entreprise         │
│                                  │
│  ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─  │
│                                  │
│  Recevez-vous un salaire de      │
│  votre propre entreprise ?       │
│                                  │
│  ┌────────────────────────────┐  │
│  │ 👔 Oui, je suis salarié    │  │
│  │                            │  │
│  │ Je reçois un salaire,      │  │
│  │ j'ai un bulletin de paie,  │  │
│  │ et des cotisations CNPS.   │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │ 🏢 Non, indépendant        │  │
│  │                            │  │
│  │ Je gère l'entreprise       │  │
│  │ sans bulletin de paie.     │  │
│  │ Pas de CNPS ni de congés   │  │
│  │ comptabilisés.             │  │
│  └────────────────────────────┘  │
│                                  │
│  💡 Modifiable à tout moment    │
│  dans les paramètres.            │
│                                  │
│  ┌────────────────────────────┐  │
│  │      Continuer    →        │  │
│  └────────────────────────────┘  │
└──────────────────────────────────┘

IF UNCHECKED — user is NOT the Représentant Légal (typically HR Manager):

┌──────────────────────────────────┐
│  ←                               │
│  ○───○───●───○───○       2/5     │
│                                  │
│  👤 Votre rôle                   │
│                                  │
│  ☐ Je suis le Représentant      │
│    Légal de l'entreprise         │
│                                  │
│  ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─  │
│                                  │
│  Le gérant de l'entreprise       │
│  reçoit-il un salaire ?          │
│                                  │
│  ┌────────────────────────────┐  │
│  │ 👔 Oui, il est salarié     │  │
│  │ Il reçoit un bulletin de   │  │
│  │ paie et des cotisations.   │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │ 🏢 Non, il est indépendant │  │
│  │ Pas de bulletin de paie.   │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │ 📩 Je ne sais pas          │  │
│  │ Envoyer un lien au gérant  │  │
│  │ pour qu'il réponde.        │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │      Continuer    →        │  │
│  └────────────────────────────┘  │
└──────────────────────────────────┘

IF "Je ne sais pas" selected — magic link delegation form appears:

┌──────────────────────────────────┐
│  ←                               │
│  ○───○───●───○───○       2/5     │
│                                  │
│  📩 Envoyer un lien au gérant   │
│                                  │
│  Nous enverrons un lien pour     │
│  qu'il réponde lui-même.         │
│                                  │
│  Nom du gérant                   │
│  ┌────────────────────────────┐  │
│  │ KOUASSI Jean-Pierre        │  │
│  └────────────────────────────┘  │
│                                  │
│  Email ou téléphone              │
│  ┌────────────────────────────┐  │
│  │ +225 07 89 12 34 56        │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │    Envoyer le lien  📩     │  │
│  └────────────────────────────┘  │
│                                  │
│  💡 En attendant sa réponse,    │
│  le gérant sera configuré comme │
│  indépendant. Ce choix sera     │
│  modifié dès qu'il répondra.    │
│                                  │
│  ┌────────────────────────────┐  │
│  │      Continuer    →        │  │
│  └────────────────────────────┘  │
└──────────────────────────────────┘

After "Envoyer le lien" success:

│  ┌────────────────────────────┐  │
│  │ ✓ Lien envoyé à            │  │
│  │ KOUASSI Jean-Pierre        │  │
│  │ (+225 07 89 12 34 56)      │  │
│  │                            │  │
│  │ En attente de sa réponse.  │  │
│  └────────────────────────────┘  │

3.5 Wizard Step 3: Choix des modules

Shaped by: D3 (module upsell), D9 (pricing)

MOBILE (360px):
┌──────────────────────────────────┐
│  ←                               │
│  ○───○───○───●───○       3/5     │
│                                  │
│  📦 Choisissez vos modules      │
│                                  │
│  Segment S1 (2-12 employés)      │
│  Sélectionnez un ou plusieurs :  │
│                                  │
│  ┌────────────────────────────┐  │
│  │ ☑ 🏖 Congés & Absences     │  │
│  │   Demandes, soldes,        │  │
│  │   approbations.            │  │
│  │   12 000 FCFA/mois         │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │ ☑ 📱 Pointage QR           │  │
│  │   Pointage par QR code,    │  │
│  │   géolocalisation.         │  │
│  │   5 000 FCFA/mois          │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │ ☐ 💰 Engagements & Budget  │  │
│  │   Bons de commande,        │  │
│  │   suivi budgétaire.        │  │
│  │   10 000 FCFA/mois         │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │ ☐ 📊 Paie                  │  │
│  │   Bulletins de paie,       │  │
│  │   cotisations CNPS.        │  │
│  │   30 000 FCFA/mois         │  │
│  └────────────────────────────┘  │
│                                  │
│  💡 Pack Contrôle (Congés + QR) │
│  15 000 FCFA/mois au lieu de    │
│  17 000 — Économisez 12% !      │
│  [Appliquer le pack]             │
│                                  │
│  ┌─ Récapitulatif ────────────┐  │
│  │ 2 modules sélectionnés     │  │
│  │ Total : 17 000 FCFA/mois   │  │
│  │                            │  │
│  │ 💡 Essai gratuit 14 jours  │  │
│  │ disponible !               │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │      Continuer    →        │  │
│  └────────────────────────────┘  │
└──────────────────────────────────┘

Pack detection: When the user's selection matches a pack (e.g., Absences + QR = Pack Contrôle), show a suggestion with savings. Uses smart pricing from the PRD §A.8 pricing grid.

Segment awareness: Module prices change based on the employee range selected in Step 1. The segment label (S1-S6) is displayed. For S4-S6, per-user pricing is shown with Platform Fee explanation.

3.6 Wizard Step 4: Paiement

MOBILE (360px):
┌──────────────────────────────────┐
│  ←                               │
│  ○───○───○───○───●       4/5     │
│                                  │
│  💳 Paiement                    │
│                                  │
│  Récapitulatif                   │
│  ┌────────────────────────────┐  │
│  │ 🏖 Congés       12 000     │  │
│  │ 📱 Pointage QR   5 000     │  │
│  │ ────────────────────────   │  │
│  │ Total    17 000 FCFA/mois  │  │
│  └────────────────────────────┘  │
│                                  │
│  Fréquence de facturation        │
│  ┌────────────────────────────┐  │
│  │ ● Mensuel — 17 000 FCFA   │  │
│  └────────────────────────────┘  │
│  ┌────────────────────────────┐  │
│  │ ○ Annuel — 12 mois payés, │  │
│  │   14 mois offerts ! 🎁    │  │
│  │   204 000 FCFA/an          │  │
│  └────────────────────────────┘  │
│                                  │
│  Moyen de paiement               │
│  ┌────────────────────────────┐  │
│  │ 🟠 Orange Money             │  │
│  └────────────────────────────┘  │
│  ┌────────────────────────────┐  │
│  │ 🔵 Wave                    │  │
│  └────────────────────────────┘  │
│  ┌────────────────────────────┐  │
│  │ 💳 Carte bancaire          │  │
│  └────────────────────────────┘  │
│  ┌────────────────────────────┐  │
│  │ 🏦 Virement bancaire       │  │
│  └────────────────────────────┘  │
│                                  │
│  ── ou ──                        │
│                                  │
│  ┌────────────────────────────┐  │
│  │ 🆓 Essai gratuit 14 jours │  │
│  │ Accès complet, sans        │  │
│  │ engagement. Pas de carte   │  │
│  │ requise.                   │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │      Payer    →            │  │
│  └────────────────────────────┘  │
│                                  │
└──────────────────────────────────┘

CinetPay integration: Selecting Orange Money / Wave / Card opens the CinetPay payment widget (embedded or redirect). Bank transfer shows bank details + unique reference.

Free trial: No payment info required. 14 days full access. After trial, status → PAYMENT_REQUIRED (read-only).

3.7 Wizard Step 5: Import employés (optional)

Shaped by: D7 (mobile-capable + desktop nudge)

MOBILE (360px) — Initial state:
┌──────────────────────────────────┐
│  ←                               │
│  ○───○───○───○───●       5/5     │
│                                  │
│  👥 Ajoutez vos employés        │
│                                  │
│  ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐  │
│  │                            │  │
│  │   📄 Glissez votre         │  │
│  │   fichier Excel ici        │  │
│  │   ou                       │  │
│  │   [Choisir un fichier]     │  │
│  │                            │  │
│  └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘  │
│                                  │
│  📥 Télécharger le modèle Excel │
│                                  │
│  ── ou ──                        │
│                                  │
│  ┌────────────────────────────┐  │
│  │ + Ajouter un employé       │  │
│  │   manuellement             │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │   Passer cette étape  →    │  │
│  └────────────────────────────┘  │
│  Vous pourrez ajouter vos        │
│  employés plus tard.             │
│                                  │
└──────────────────────────────────┘

After Excel upload — mobile card list (D7):

MOBILE (360px):
┌──────────────────────────────────┐
│  ← Import employés              │
│  12 employés · 1 erreur 🔴      │
│                                  │
│  ┌────────────────────────────┐  │
│  │ KOUASSI Jean-Pierre    ✏️  │  │
│  │ [email protected]         │  │
│  │ Direction Générale          │  │
│  │ Contact: [●Email] [SMS]    │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │ DIABATÉ Aminata  🔴  ✏️   │  │
│  │ Téléphone manquant         │  │
│  │ Comptabilité               │  │
│  │ Contact: [Email] [●SMS]    │  │
│  │ ┌──────────────────────┐   │  │
│  │ │ +225                  │   │  │
│  │ └──────────────────────┘   │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │ TRAORÉ Adama           ✏️  │  │
│  │ [email protected]          │  │
│  │ Production                 │  │
│  │ Contact: [●Email] [SMS]    │  │
│  └────────────────────────────┘  │
│                                  │
│  ... (scroll for more)           │
│                                  │
│  ┌────────────────────────────┐  │
│  │   Créer 12 employés        │  │
│  └────────────────────────────┘  │
│  ⚠ 1 erreur à corriger          │
│                                  │
└──────────────────────────────────┘

Desktop table (1024px+):

┌──────────────────────────────────────────────────────────────────┐
│  ← Import employés       12 employés · 1 erreur    [Créer 12]  │
│                                                                  │
│  Nom         │ Prénom    │ Email        │ Dépt    │ Contact      │
│  ────────────┼───────────┼──────────────┼─────────┼────────────  │
│  KOUASSI     │ Jean-P.   │ [email protected]│ DG      │ ● Email      │
│  DIABATÉ 🔴  │ Aminata   │ (vide)       │ Compta  │ ● SMS        │
│  TRAORÉ      │ Adama     │ [email protected]│ Prod    │ ● Email      │
│  ...                                                             │
└──────────────────────────────────────────────────────────────────┘

30+ employees on mobile — desktop nudge:

┌──────────────────────────────────┐
│  47 employés importés            │
│                                  │
│  ┌────────────────────────────┐  │
│  │ 💡 Pour plus de confort,   │  │
│  │ vous pouvez terminer       │  │
│  │ l'import depuis un         │  │
│  │ ordinateur. Votre fichier  │  │
│  │ est sauvegardé.            │  │
│  │                            │  │
│  │ [Continuer ici]            │  │
│  │ [Terminer plus tard]       │  │
│  └────────────────────────────┘  │
│                                  │
│  (card list below if continue)   │
└──────────────────────────────────┘

What the DG sees when they tap the link — no login required:

MOBILE (360px):
┌──────────────────────────────────┐
│                                  │
│        🦋 Papillon               │
│                                  │
│  Bonjour Jean-Pierre,            │
│                                  │
│  Aminata configure Papillon      │
│  HR Suite pour ALTARYS SARL.     │
│                                  │
│  ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─  │
│                                  │
│  Recevez-vous un salaire de      │
│  votre entreprise ?              │
│                                  │
│  ┌────────────────────────────┐  │
│  │ 👔 Oui, je suis salarié    │  │
│  │                            │  │
│  │ Je reçois un bulletin de   │  │
│  │ paie et des cotisations    │  │
│  │ CNPS.                      │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │ 🏢 Non, je suis            │  │
│  │    indépendant             │  │
│  │                            │  │
│  │ Pas de bulletin de paie    │  │
│  │ ni de cotisations.         │  │
│  └────────────────────────────┘  │
│                                  │
│  💡 Vous pourrez modifier ce    │
│  choix à tout moment dans       │
│  l'application.                  │
│                                  │
└──────────────────────────────────┘

After DG responds:

┌──────────────────────────────────┐
│                                  │
│        🦋 Papillon               │
│                                  │
│        ✓                         │
│                                  │
│  Merci Jean-Pierre !             │
│                                  │
│  Votre statut a été mis à jour.  │
│                                  │
│  ┌────────────────────────────┐  │
│  │   Accéder à Papillon  →    │  │
│  └────────────────────────────┘  │
│                                  │
└──────────────────────────────────┘

3.9 Tenant Switcher (D2)

Shaped by: D2. See also host-shell-design.md §5 for top bar layout.

Top bar — single-tenant user (no switcher):

┌──────────────────────────────────┐
│ 🦋  ALTARYS SARL          🔔 👤 │
└──────────────────────────────────┘

Top bar — multi-tenant user:

┌──────────────────────────────────┐
│ 🦋  [ALTARYS SARL ▼]      🔔 👤 │
└──────────────────────────────────┘

Bottom sheet (mobile) — on tap:

┌──────────────────────────────────┐
│  ─── (drag handle) ───          │
│                                  │
│  Changer d'entreprise            │
│                                  │
│  ┌────────────────────────────┐  │
│  │ ● ALTARYS SARL             │  │
│  │   Comptable · 12 employés  │  │
│  │   ━━━━━━━━━━ (active)      │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │ ○ DIALLO & Fils            │  │
│  │   Comptable · 8 employés   │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │ ○ Cabinet Médical Abidjan  │  │
│  │   Comptable · 23 employés  │  │
│  └────────────────────────────┘  │
│                                  │
└──────────────────────────────────┘

Component: TenantSwitcher — see §8.1.

Interaction: Tapping a different tenant triggers JWT re-issue (online) or local context switch (offline). Transition: content area does a 200ms crossfade.

3.10 Module Upsell Preview (D3)

Bottom sheet (mobile):

┌──────────────────────────────────┐
│  ─── (drag handle) ───          │
│  ✕  Core RH                     │
│                                  │
│  ┌────────────────────────────┐  │
│  │  [warm geometric SVG       │  │
│  │   illustration suggesting  │  │
│  │   employee file management]│  │
│  └────────────────────────────┘  │
│                                  │
│  Le dossier complet de           │
│  vos employés                    │
│                                  │
│  ✓ Fiches employé détaillées    │
│  ✓ Import Excel en masse        │
│  ✓ Documents et pièces jointes  │
│                                  │
│  À partir de 12 000 FCFA/mois   │
│  (votre segment : S1, 2-12 emp.)│
│                                  │
│  ┌────────────────────────────┐  │
│  │ Essayer gratuitement 14j 🆓│  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │ 🔔 Me notifier au lancement│  │
│  └────────────────────────────┘  │
│                                  │
└──────────────────────────────────┘

For unreleased modules — CTA changes:

│  Ce module sera bientôt          │
│  disponible.                     │
│                                  │
│  ┌────────────────────────────┐  │
│  │ 🔔 Me notifier au lancement│  │
│  └────────────────────────────┘  │

3.11 Unified Approval Inbox (D4)

MOBILE (360px):
┌──────────────────────────────────┐
│  ← Approbations           ⚡ 4   │
│                                  │
│  ┌─ Filtres ─────────────────┐  │
│  │ [●Tous] [Congés] [Engage.]│  │
│  └───────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │ 🏖 Congé annuel     il y a 2h│
│  │ DIABATÉ Aminata            │  │
│  │ 15/04 → 22/04 (5 jours)   │  │
│  │ Solde après : 18 jours     │  │
│  │                            │  │
│  │  [Refuser]  [✓ Approuver]  │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │ 🏖 Congé maladie    hier   │  │
│  │ TRAORÉ Adama               │  │
│  │ 10/04 → 12/04 (3 jours)   │  │
│  │ 📎 Certificat médical      │  │
│  │                            │  │
│  │  [Refuser]  [✓ Approuver]  │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │ 💰 Engagement       lun.   │  │
│  │ Fournitures bureau         │  │
│  │ 350 000 FCFA · Comptabilité│  │
│  │                            │  │
│  │  [Refuser]  [✓ Approuver]  │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │ 💰 Engagement       lun.   │  │
│  │ Cartouches imprimante      │  │
│  │ 85 000 FCFA · Production   │  │
│  │                            │  │
│  │  [Refuser]  [✓ Approuver]  │  │
│  └────────────────────────────┘  │
│                                  │
│  ← Swipe gauche/droite          │
│  pour refuser/approuver          │
│                                  │
└──────────────────────────────────┘

Refuse flow — mandatory comment:

┌──────────────────────────────────┐
│  Refuser la demande              │
│                                  │
│  DIABATÉ Aminata                 │
│  Congé annuel · 15/04 → 22/04   │
│                                  │
│  Motif du refus (obligatoire)    │
│  ┌────────────────────────────┐  │
│  │ Période déjà prise par     │  │
│  │ un collègue.               │  │
│  └────────────────────────────┘  │
│                                  │
│  [Annuler]     [Confirmer refus] │
└──────────────────────────────────┘

Empty state (no pending approvals):

│        ✓                         │
│                                  │
│  Aucune approbation en attente   │
│                                  │
│  Vous êtes à jour ! Revenez     │
│  quand de nouvelles demandes     │
│  arriveront.                     │

3.12 Billing / Subscription Management (D9)

Shaped by: D9 (single scrollable page)

MOBILE (360px):
┌──────────────────────────────────┐
│  ← Abonnement                   │
│                                  │
│  ┌─ Votre plan ──────────────┐  │
│  │  S2 · 13-29 employés       │  │
│  │  Statut : ● Actif          │  │
│  │                            │  │
│  │  45 000 FCFA/mois          │  │
│  │  Prochain paiement :       │  │
│  │  01/04/2026                │  │
│  │                            │  │
│  │  Facturation : Mensuelle   │  │
│  │  [Passer en annuel →]      │  │
│  │  🎁 12 mois = 14 offerts   │  │
│  └────────────────────────────┘  │
│                                  │
│  Modules actifs                  │
│  ┌────────────────────────────┐  │
│  │ ✓ Congés & Absences        │  │
│  │   15 000 FCFA/mois         │  │
│  ├────────────────────────────┤  │
│  │ ✓ Pointage QR              │  │
│  │   10 000 FCFA/mois         │  │
│  ├────────────────────────────┤  │
│  │ ✓ Engagements              │  │
│  │   20 000 FCFA/mois         │  │
│  │   (incl. Lignes budgétaires)│  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │ + Ajouter un module        │  │
│  └────────────────────────────┘  │
│                                  │
│  Moyen de paiement               │
│  ┌────────────────────────────┐  │
│  │ 🟠 Orange Money ··7823     │  │
│  │                  [Modifier] │  │
│  └────────────────────────────┘  │
│                                  │
│  Historique des factures         │
│  ┌────────────────────────────┐  │
│  │ Mars 2026  45 000  ⏳ En    │  │
│  │                    cours    │  │
│  ├────────────────────────────┤  │
│  │ Fév. 2026  45 000  ✓ Payé  │  │
│  │                    [📄]     │  │
│  ├────────────────────────────┤  │
│  │ Jan. 2026  45 000  ✓ Payé  │  │
│  │                    [📄]     │  │
│  └────────────────────────────┘  │
│                                  │
└──────────────────────────────────┘

"Ajouter un module" flow: Opens the same module preview cards (D3) in a list view, with "Activer" CTA instead of "Essayer gratuitement."

3.13 Degradation Banners (D5)

Shaped by: D5 (persistent banner + functional overlay)

Four banner variants, ordered by severity:

TRIAL_EXPIRING (warm info — not urgent yet):

┌──────────────────────────────────┐
│ 💡 Essai gratuit : 3 jours       │
│ restants. [Souscrire →]          │
└──────────────────────────────────┘

Token: --color-info background. Dismissable (reappears daily).

PAYMENT_REQUIRED (amber warning):

┌──────────────────────────────────┐
│ ⚠️ Paiement requis               │
│ Vos données sont en lecture      │
│ seule. [Régulariser →]           │
└──────────────────────────────────┘

Token: --color-warning background. Not dismissable.

ACTIVE_INCOMPLETE_READONLY (amber warning):

┌──────────────────────────────────┐
│ ⚠️ Informations manquantes       │
│ Complétez votre RCCM pour        │
│ retrouver l'accès. [Compléter →] │
└──────────────────────────────────┘

Token: --color-warning background. Not dismissable.

SUSPENDED (red — critical):

┌──────────────────────────────────┐
│ 🔴 Compte suspendu               │
│ Régularisez votre abonnement     │
│ sous 10 jours. [Régulariser →]   │
└──────────────────────────────────┘

Token: --color-error background. Not dismissable. Shows countdown.

Write action overlay (shown when user taps a write action in degraded state):

┌──────────────────────────────────┐
│                                  │
│  ┌────────────────────────────┐  │
│  │                            │  │
│  │  Action non disponible     │  │
│  │                            │  │
│  │  Régularisez votre         │  │
│  │  abonnement pour           │  │
│  │  continuer à utiliser      │  │
│  │  Papillon.                 │  │
│  │                            │  │
│  │  ┌──────────────────────┐  │  │
│  │  │    Régulariser  →    │  │  │
│  │  └──────────────────────┘  │  │
│  │                            │  │
│  │  [Fermer]                  │  │
│  └────────────────────────────┘  │
│                                  │
└──────────────────────────────────┘

3.14 Sync Conflict Resolution (D6)

Auto-resolved notification (95% of cases):

┌──────────────────────────────────┐
│  🔄 Synchronisation terminée     │
│                                  │
│  ✓ 3 actions synchronisées      │
│  ⚠ 1 conflit résolu :           │
│                                  │
│  ┌────────────────────────────┐  │
│  │ Approbation congé DIABATÉ  │  │
│  │ Non appliquée : la demande │  │
│  │ a été annulée par          │  │
│  │ l'employé.                 │  │
│  │                     [OK]   │  │
│  └────────────────────────────┘  │
└──────────────────────────────────┘

Manual conflict resolution (5% edge cases):

┌──────────────────────────────────┐
│  ⚠ Conflit de données           │
│                                  │
│  Note de frais : Taxi Plateau    │
│                                  │
│  Votre version :                 │
│  ┌────────────────────────────┐  │
│  │ 2 500 FCFA · Transport     │  │
│  │ Modifié hors-ligne         │  │
│  └────────────────────────────┘  │
│                                  │
│  Version serveur :               │
│  ┌────────────────────────────┐  │
│  │ 3 000 FCFA · Transport     │  │
│  │ Modifié par vous           │  │
│  │ sur ordinateur             │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │   Garder ma version        │  │
│  └────────────────────────────┘  │
│  ┌────────────────────────────┐  │
│  │   Garder la version serveur│  │
│  └────────────────────────────┘  │
└──────────────────────────────────┘

3.15 Employee Self-Service Profile (FR-PV-095/096)

Baseline profile (Control Plane — always available):

MOBILE (360px):
┌──────────────────────────────────┐
│  ← Mon profil                    │
│                                  │
│  ┌────────────────────────────┐  │
│  │       👤                   │  │
│  │  KOUASSI Jean-Pierre       │  │
│  │  CDI · Direction Générale  │  │
│  │  Agent de maîtrise         │  │
│  └────────────────────────────┘  │
│                                  │
│  Informations                    │
│  ┌────────────────────────────┐  │
│  │ Email                      │  │
│  │ [email protected]       │  │
│  ├────────────────────────────┤  │
│  │ Téléphone                  │  │
│  │ +225 07 89 12 34 56        │  │
│  ├────────────────────────────┤  │
│  │ Département                │  │
│  │ Direction Générale         │  │
│  ├────────────────────────────┤  │
│  │ Poste                      │  │
│  │ Directeur Adjoint          │  │
│  ├────────────────────────────┤  │
│  │ Responsable                │  │
│  │ DIALLO Mamadou (DG)        │  │
│  ├────────────────────────────┤  │
│  │ Date d'embauche            │  │
│  │ 15/03/2024                 │  │
│  ├────────────────────────────┤  │
│  │ Matricule                  │  │
│  │ ALT-2024-03-001            │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │ 📥 Exporter mes données    │  │
│  └────────────────────────────┘  │
│                                  │
└──────────────────────────────────┘

If HR Core is active — additional sections appear below (enriched fields): - Informations personnelles (date de naissance, nationalité, situation familiale) - Contacts d'urgence - Informations bancaires (RIB) - Documents joints - Historique des modifications

All fields read-only for the employee (FR-PV-095).

3.16 Data Export (FR-PV-092)

Shaped by: FR-PV-092 (employee self-export — privacy right)

MOBILE (360px):
┌──────────────────────────────────┐
│  ← Exporter mes données         │
│                                  │
│  Téléchargez une copie de        │
│  toutes vos données personnelles │
│  (droit à la portabilité,        │
│  Loi n°2013-450).                │
│                                  │
│  Contenu de l'export :           │
│  ┌────────────────────────────┐  │
│  │ ✓ Mon profil               │  │
│  │ ✓ Mes bulletins de paie    │  │
│  │ ✓ Mon historique de congés │  │
│  │ ✓ Mes documents joints     │  │
│  └────────────────────────────┘  │
│                                  │
│  Format : ZIP (PDF + CSV)        │
│                                  │
│  ┌────────────────────────────┐  │
│  │   Générer l'export  📥     │  │
│  └────────────────────────────┘  │
│                                  │
│  💡 La génération peut prendre   │
│  quelques minutes. Vous serez    │
│  notifié quand le fichier sera   │
│  prêt.                           │
│                                  │
└──────────────────────────────────┘

After generation:

│  ┌────────────────────────────┐  │
│  │ ✓ Export prêt !            │  │
│  │ export-kouassi-2026.zip    │  │
│  │ 2.3 Mo                    │  │
│  │                            │  │
│  │ [Télécharger]              │  │
│  └────────────────────────────┘  │

3.17 Settings Hierarchy

Shaped by: D8 (owner status in settings), D9 (billing access)

MOBILE (360px):
┌──────────────────────────────────┐
│  ← Paramètres                   │
│                                  │
│  Mon compte                      │
│  ┌────────────────────────────┐  │
│  │ 👤 Mon profil           →  │  │
│  ├────────────────────────────┤  │
│  │ 🔐 Mot de passe         →  │  │
│  ├────────────────────────────┤  │
│  │ 🌙 Mode sombre        ○●  │  │
│  ├────────────────────────────┤  │
│  │ 🔔 Notifications       →  │  │
│  └────────────────────────────┘  │
│                                  │
│  Entreprise (admin only)         │
│  ┌────────────────────────────┐  │
│  │ 🏢 Infos entreprise     →  │  │
│  ├────────────────────────────┤  │
│  │ 👔 Statut du gérant     →  │  │
│  ├────────────────────────────┤  │
│  │ 🗓 Exercice fiscal      →  │  │
│  ├────────────────────────────┤  │
│  │ 🏗 Structure org.       →  │  │
│  ├────────────────────────────┤  │
│  │ 👥 Utilisateurs         →  │  │
│  ├────────────────────────────┤  │
│  │ 🔑 Rôles & permissions  →  │  │
│  └────────────────────────────┘  │
│                                  │
│  Abonnement (admin only)         │
│  ┌────────────────────────────┐  │
│  │ 💳 Mon abonnement       →  │  │
│  └────────────────────────────┘  │
│                                  │
│  À propos                        │
│  ┌────────────────────────────┐  │
│  │ 📋 CGU                  →  │  │
│  ├────────────────────────────┤  │
│  │ 🔒 Confidentialité      →  │  │
│  ├────────────────────────────┤  │
│  │ ℹ️ Version 1.0.0           │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │   Se déconnecter           │  │
│  └────────────────────────────┘  │
│                                  │
└──────────────────────────────────┘

"Statut du gérant" sub-screen (accessible from settings — D8 post-onboarding change):

┌──────────────────────────────────┐
│  ← Statut du gérant              │
│                                  │
│  KOUASSI Jean-Pierre             │
│  Représentant Légal              │
│                                  │
│  Statut actuel :                 │
│  ┌────────────────────────────┐  │
│  │ ● Indépendant              │  │
│  │   Pas de bulletin de paie  │  │
│  │   ni de cotisations CNPS.  │  │
│  └────────────────────────────┘  │
│                                  │
│  ┌────────────────────────────┐  │
│  │ ○ Salarié                  │  │
│  │   Bulletin de paie,        │  │
│  │   cotisations CNPS,        │  │
│  │   droits aux congés.       │  │
│  └────────────────────────────┘  │
│                                  │
│  ⚠ Modifier ce statut affecte   │
│  la paie et les déclarations     │
│  CNPS. Le changement prend       │
│  effet au prochain mois.         │
│                                  │
│  ┌────────────────────────────┐  │
│  │      Enregistrer           │  │
│  └────────────────────────────┘  │
└──────────────────────────────────┘

4. Interaction Specifications

4.1 Global Interaction Rules

Rule Specification
Auto-save All form fields auto-save on blur (text) or on change (toggles, selects). Visual: brief green check icon next to field.
Validation Inline, on blur. French messages. Never blocks typing. Error text appears below field with slide-down animation (150ms).
Touch targets 48×48px minimum for all interactive elements.
Swipe gestures Approval cards: swipe right = approve (green reveal), swipe left = refuse (red reveal). Confirm with haptic feedback.
Loading Skeleton shimmer for content areas. Button spinner for form submissions. Never bare spinners.
Transitions Screen enter: slide up 12px + fade in (200ms). Modal/sheet: slide up from bottom (300ms). Never hard cuts.
Keyboard (desktop) Enter = submit form. Escape = close modal/sheet. Tab = next field.

4.2 Per-Screen State Table

Screen Loading Empty Error Offline Success
Onboarding wizard Skeleton shimmer on step load N/A (steps always have content) Inline field errors in French "Connexion requise" overlay (account creation is online-only) Step transition with progress bar fill animation
Tenant switcher Shimmer list (3 placeholder items) N/A (user has ≥1 tenant) "Impossible de charger vos entreprises. Réessayer." Shows cached tenant list with "Données hors-ligne" label Crossfade transition to new tenant dashboard
Module preview Shimmer card N/A "Impossible de charger les détails. Réessayer." Shows cached module info if available, else "Connectez-vous pour voir les détails." Trial activation: check animation + nav item unlocks with color pop
Approval inbox Shimmer cards (3 placeholders) Illustration + "Aucune approbation en attente. Vous êtes à jour !" "Impossible de charger les approbations. Réessayer." "Connexion requise pour approuver. Vos approbations seront disponibles dès la reconnexion." Approved card slides out right (green). Refused slides out left (red). Badge count decrements.
Employee import Parsing skeleton (table rows shimmer) Upload zone with template download "Format non reconnu. Téléchargez le modèle." / per-row validation errors Upload requires connectivity. Editing cached import data works offline. "47 employés créés ! Invitations envoyées." with confetti burst
Billing page Shimmer sections (plan card + module list + invoices) N/A (always has plan info) "Impossible de charger l'abonnement." Shows cached billing info with "Dernière mise à jour : il y a 2h" Payment success: green check + banner removal animation
Self-service profile Shimmer card + shimmer rows N/A (user always has a profile) "Impossible de charger votre profil." Shows cached profile with timestamp N/A (read-only)
Data export "Génération en cours..." progress indicator N/A "Impossible de générer l'export. Réessayer." "Connexion requise pour générer un export." "Export prêt !" with download button
Sync conflicts N/A (appears after sync) N/A (only shown when conflicts exist) N/A N/A (only appears on reconnection) Resolved: card fades out. All resolved: "Tout est synchronisé ✓" toast
Degradation banners N/A (instant) N/A N/A Banner still shows (status is cached) Payment success: banner slides up and disappears (300ms)

4.3 Swipe Gesture Specification (Approval Inbox)

SWIPE RIGHT (Approve):
┌────────────────────────────────┐
│ ✓ APPROUVER │ 🏖 Congé annuel   │
│  (green bg) │ DIABATÉ Aminata   │
│             │ 15/04 → 22/04     │
└────────────────────────────────┘
  ← swipe reveals green ✓ action

SWIPE LEFT (Refuse):
┌────────────────────────────────┐
│ 🏖 Congé annuel   │ ✗ REFUSER  │
│ DIABATÉ Aminata   │ (red bg)   │
│ 15/04 → 22/04     │            │
└────────────────────────────────┘
  swipe reveals red ✗ action →

Threshold: 40% of card width triggers action.
Below threshold: card snaps back.
Haptic: light vibration on threshold cross.
Refuse always opens comment modal (mandatory).

5. Responsive Behavior

5.1 Breakpoints

Breakpoint Width Target
Phone 360–767px Primary design target
Tablet 768–1023px Enhanced layout
Desktop 1024–1439px Full experience
Wide desktop 1440px+ Maximum density

5.2 Per-Screen Responsive Adaptations

Screen Phone (360px) Tablet (768px) Desktop (1024px+)
Onboarding wizard Full-width, single column. CTA at bottom of viewport. Centered card (560px max), branding illustration on sides. Split layout: illustration left (40%), form right (60%).
Tenant switcher Bottom sheet (full-width, swipe to dismiss). Bottom sheet (centered, 480px max). Dropdown below company badge (320px wide, max 5 items visible then scroll).
Module preview Bottom sheet (full-width). Bottom sheet (centered, 480px max). Popover card anchored to nav item (400px wide).
Approval inbox Stacked cards, full-width. Swipe gestures. 2-column card grid. Swipe on cards. List view with inline actions (no swipe needed). Filter sidebar on left (240px).
Employee import Card list (one card per employee). Card grid (2 columns). Editable table with inline editing.
Billing page Single column, stacked sections. Single column, wider cards. Two columns: plan + modules left (60%), invoices + payment right (40%).
Self-service profile Single column. Centered card (560px). Card with sidebar navigation for enriched sections (if HR Core active).
Settings Full-width grouped list. Centered (560px). Sidebar navigation (240px) + content area (right).

6. Offline Behavior

6.1 Offline Capability Matrix

Screen / Action Offline Read Offline Write Sync Behavior
Onboarding wizard Online-only. Account creation, payment, and email verification require connectivity.
Tenant switcher ✅ Cached tenant list N/A Tenant list cached in IndexedDB. Offline switch uses cached data for selected tenant.
Module preview ✅ Cached module info ❌ Module activation = online-only Module details cached after first view. Trial activation requires connectivity.
Approval inbox ✅ Cached pending list ❌ Approve/refuse = online-only Approval list cached. "Connexion requise pour approuver" overlay on action buttons.
Employee import ✅ Cached import data (mid-import) ✅ Edits to import data saved locally Upload = online-only. Editing parsed data = offline. Submit = online-only. Auto-save edits to IndexedDB.
Billing page ✅ Cached billing info ❌ Payment = online-only Plan, modules, invoices cached. "Dernière mise à jour" timestamp shown.
Self-service profile ✅ Cached profile ❌ Read-only Profile data cached. Works fully offline.
Data export Export generation requires server. "Connexion requise."
Settings ✅ Cached settings ✅ Dark mode toggle only Most settings changes require connectivity. Dark mode is local.
Dashboard ✅ Cached KPIs + approvals count N/A Shows cached data with "Dernière mise à jour" timestamp.

6.2 Sync Conflict Resolution Rules (D6)

Data Type Conflict Rule Rationale
Approval actions Server wins If someone cancelled a request while you were offline, their action takes precedence.
Financial operations Server wins Budget state may have changed. Server has latest truth.
Draft leave requests Client wins User's latest edits are their intent.
Draft expense entries Client wins User's latest edits are their intent.
Clock-in/clock-out Auto-merge (append) Timestamps don't conflict — they stack.
Profile data (same field changed) Manual resolution Show both versions, user picks.
Settings changes Last-write wins Rare conflict. Most recent change applies.

6.3 Offline Visual Indicators

See host-shell-design.md §8 for the sync status indicator. Additional patterns for this document:

Online-only action overlay (shown when user taps a blocked action):

┌────────────────────────────────┐
│  📡 Connexion requise           │
│                                │
│  Cette action nécessite une    │
│  connexion internet.           │
│                                │
│  Elle sera disponible dès la   │
│  reconnexion.                  │
│                                │
│  [OK]                          │
└────────────────────────────────┘

7. French Micro-copy

7.1 Onboarding Wizard

Element Text
Public signup title Créez votre compte
Public signup CTA Créer mon compte
Public signup — existing user Déjà inscrit ? Se connecter
Public signup — CGU En créant un compte, vous acceptez les CGU et la politique de confidentialité.
Email verification title Vérifiez votre email
Email verification body Un lien de vérification a été envoyé à {email}. Cliquez sur le lien dans l'email pour continuer.
Email verification — resend Vous n'avez rien reçu ? Renvoyer l'email
Email verification — spam tip 💡 Vérifiez aussi vos courriers indésirables.
Step 1 title 🏢 Votre entreprise
Step 1 — RCCM helper 💡 Vous avez 3 mois pour le renseigner.
Step 2 title 👤 Votre rôle
Step 2 — RL checkbox Je suis le Représentant Légal de l'entreprise (gérant, DG, président)
Step 2 — salarié card 👔 Oui, je suis salarié — Je reçois un salaire, j'ai un bulletin de paie, et des cotisations CNPS.
Step 2 — indépendant card 🏢 Non, indépendant — Je gère l'entreprise sans bulletin de paie. Pas de CNPS ni de congés comptabilisés.
Step 2 — don't know 📩 Je ne sais pas — Envoyer un lien au gérant pour qu'il réponde lui-même.
Step 2 — changeable 💡 Modifiable à tout moment dans les paramètres.
Step 2 — link sent ✓ Lien envoyé à {name} ({contact}). En attente de sa réponse.
Step 2 — default while waiting 💡 En attendant sa réponse, le gérant sera configuré comme indépendant. Ce choix sera modifié dès qu'il répondra.
Step 3 title 📦 Choisissez vos modules
Step 3 — pack suggestion 💡 Pack {name} : {price} FCFA/mois au lieu de {sum} — Économisez {percent}% !
Step 3 — trial notice 💡 Essai gratuit 14 jours disponible !
Step 4 title 💳 Paiement
Step 4 — annual upsell 🎁 12 mois payés, 14 mois offerts !
Step 4 — free trial 🆓 Essai gratuit 14 jours — Accès complet, sans engagement. Pas de carte requise.
Step 5 title 👥 Ajoutez vos employés
Step 5 — upload zone 📄 Glissez votre fichier Excel ici ou Choisir un fichier
Step 5 — template 📥 Télécharger le modèle Excel
Step 5 — manual add + Ajouter un employé manuellement
Step 5 — skip Passer cette étape → Vous pourrez ajouter vos employés plus tard.
Step 5 — summary {n} employés · {e} erreurs à corriger
Step 5 — desktop nudge 💡 Pour plus de confort, vous pouvez terminer l'import depuis un ordinateur. Votre fichier est sauvegardé.
Step 5 — submit Créer {n} employés
Step 5 — success {n} employés créés ! Invitations envoyées. 🎉
Progress Continuer →
Element Text
Greeting Bonjour {name},
Context {onboarder_name} configure Papillon HR Suite pour {company_name}.
Question Recevez-vous un salaire de votre entreprise ?
Salarié 👔 Oui, je suis salarié — Je reçois un bulletin de paie et des cotisations CNPS.
Indépendant 🏢 Non, je suis indépendant — Pas de bulletin de paie ni de cotisations.
Changeable 💡 Vous pourrez modifier ce choix à tout moment dans l'application.
Success Merci {name} ! Votre statut a été mis à jour.
CTA after success Accéder à Papillon →

7.3 Tenant Switcher

Element Text
Sheet title Changer d'entreprise
Active badge (active)
Role display {role} · {n} employés

7.4 Module Upsell

Module One-liner Benefit 1 Benefit 2 Benefit 3
Congés & Absences Gérez les congés simplement Demandes et approbations en 2 taps Soldes automatiques par type de congé Export vers la paie
Pointage QR Pointage par QR code Scan QR depuis le téléphone Géolocalisation optionnelle Historique et exports CSV
Engagements & Budget Maîtrisez vos dépenses Bons de commande et validations Suivi budgétaire en temps réel Alertes de dépassement
Paie Bulletins de paie conformes Calcul automatique CNPS/ITS Génération des bulletins Historique et archivage
Core RH Le dossier complet de vos employés Fiches employé détaillées Import Excel en masse Documents et pièces jointes
CRM Interne Suivez vos prospects Pipeline de vente visuel Suivi des commissions Conversion prospect → client

Common elements:

Element Text
Pricing À partir de {price} FCFA/mois (votre segment : {segment})
Trial CTA Essayer gratuitement 14j 🆓
Notify toggle 🔔 Me notifier au lancement
Coming soon Ce module sera bientôt disponible.
Admin required Seul un administrateur peut activer un module.

7.5 Approval Inbox

Element Text
Screen title Approbations
Badge ⚡ {n}
Filter: all Tous
Filter: leave Congés
Filter: commitment Engagements
Leave card 🏖 {leave_type} · {employee_name} · {start} → {end} ({days} jours) · Solde après : {balance} jours
Commitment card 💰 {description} · {amount} FCFA · {department}
Approve button ✓ Approuver
Refuse button Refuser
Refuse modal title Refuser la demande
Refuse comment label Motif du refus (obligatoire)
Refuse confirm Confirmer refus
Empty state Aucune approbation en attente. Vous êtes à jour !
Offline overlay Connexion requise pour approuver. Vos approbations seront disponibles dès la reconnexion.
Swipe hint ← Glissez pour refuser / approuver →

7.6 Degradation Banners

Status Banner Text
TRIAL_EXPIRING 💡 Essai gratuit : {n} jours restants. [Souscrire →]
TRIAL_EXPIRED ⚠️ Votre essai gratuit est terminé. Souscrivez pour continuer. [Souscrire →]
PAYMENT_REQUIRED ⚠️ Paiement requis — Vos données sont en lecture seule. [Régulariser →]
ACTIVE_INCOMPLETE_READONLY ⚠️ Informations manquantes — Complétez votre RCCM pour retrouver l'accès. [Compléter →]
SUSPENDED 🔴 Compte suspendu — Régularisez votre abonnement sous {n} jours. [Régulariser →]
Write overlay Action non disponible. Régularisez votre abonnement pour continuer à utiliser Papillon. [Régulariser →]

7.7 Sync & Conflicts

Element Text
Sync complete 🔄 Synchronisation terminée
Actions synced ✓ {n} actions synchronisées
Conflict resolved ⚠ {n} conflit(s) résolu(s)
Approval conflict Approbation congé {employee} — Non appliquée : la demande a été annulée par l'employé.
Financial conflict Opération non appliquée : les données ont été modifiées entre-temps.
Manual conflict title ⚠ Conflit de données
Your version Votre version :
Server version Version serveur :
Keep mine Garder ma version
Keep server Garder la version serveur
All synced toast Tout est synchronisé ✓

7.8 Billing

Element Text
Screen title Abonnement
Plan label Votre plan
Status active ● Actif
Status trial ● Essai gratuit
Status overdue ⚠ Impayé
Next payment Prochain paiement : {date}
Billing frequency Facturation : Mensuelle / Annuelle
Annual upsell 🎁 Passez en annuel : 12 mois payés, 14 mois offerts !
Modules section Modules actifs
Add module CTA + Ajouter un module
Payment section Moyen de paiement
Modify payment Modifier
Invoice section Historique des factures
Invoice status paid ✓ Payé
Invoice status pending ⏳ En cours
Invoice download 📄 (icon button — downloads PDF receipt)

7.9 Employee Profile & Export

Element Text
Profile title Mon profil
Export button 📥 Exporter mes données
Export page title Exporter mes données
Export description Téléchargez une copie de toutes vos données personnelles (droit à la portabilité, Loi n°2013-450).
Export content label Contenu de l'export :
Export items ✓ Mon profil / ✓ Mes bulletins de paie / ✓ Mon historique de congés / ✓ Mes documents joints
Export format Format : ZIP (PDF + CSV)
Export CTA Générer l'export 📥
Export pending 💡 La génération peut prendre quelques minutes. Vous serez notifié quand le fichier sera prêt.
Export ready ✓ Export prêt ! {filename} · {size}
Export download Télécharger

7.10 Validation Error Messages

Field Error
Email — empty L'adresse email est obligatoire.
Email — invalid Cette adresse email n'est pas valide.
Email — taken Cette adresse email est déjà utilisée.
Phone — empty Le numéro de téléphone est obligatoire.
Phone — invalid Ce numéro n'est pas valide. Format : +225 XX XX XX XX XX
Password — too short Le mot de passe doit contenir au moins 8 caractères.
Password — no uppercase Le mot de passe doit contenir au moins une majuscule.
Password — no number Le mot de passe doit contenir au moins un chiffre.
Company name — empty Le nom de l'entreprise est obligatoire.
Company name — too short Le nom doit contenir au moins 2 caractères.
Form juridique — empty La forme juridique est obligatoire.
Employee count — empty Le nombre d'employés est obligatoire.
Module selection — none Sélectionnez au moins un module.
Refuse comment — empty Le motif du refus est obligatoire.
Generic server error Une erreur est survenue. Veuillez réessayer.
Network error Impossible de se connecter au serveur. Vérifiez votre connexion internet.
Import — bad format Format non reconnu. Téléchargez le modèle Excel.
Import — duplicate employee Un employé avec cet email existe déjà.

8. Component Specs

8.1 TenantSwitcher (NEW)

Purpose: Displays current tenant in top bar, opens tenant list for switching.

Prop Type Description
currentTenant Tenant Currently active tenant
tenants Tenant[] All tenants the user belongs to
onSwitch (tenantId: string) => void Callback on tenant selection
isMultiTenant boolean If false, renders as static text (no chevron, no tap)

Variants: - Single-tenant: Static company name. No chevron. No interaction. - Multi-tenant: Company name + ▼ chevron. Tappable. Opens BottomSheet (mobile) or dropdown (desktop).

States: Default, Loading (shimmer text), Error (last known name + retry)

Accessibility: aria-label="Entreprise active : {name}. Appuyez pour changer." role="button" (multi-tenant only). aria-expanded for dropdown state.

Touch target: Full top-bar badge area, minimum 48px tall.

8.2 ModulePreviewCard (NEW)

Purpose: Rich preview of a locked/unavailable module with upsell CTA.

Prop Type Description
module ModuleInfo Module code, name, description, benefits, illustration
pricing ModulePricing Segment-aware price for current tenant
isAvailable boolean True if module is released and purchasable
onActivateTrial () => void Callback for trial activation
onNotifyMe (enabled: boolean) => void Callback for notification toggle

Variants: - Available: Shows pricing + "Essayer gratuitement 14j" CTA. - Coming soon: Shows "Bientôt disponible" + "Me notifier" toggle.

States: Default, Loading (shimmer), Trial activating (button spinner), Trial activated (success check)

Accessibility: aria-label="Module {name}. {description}." CTA: aria-label="Activer l'essai gratuit de {name} pendant 14 jours".

Container: Rendered inside BottomSheet (mobile, via design system) or popover (desktop).

8.3 ApprovalCard (NEW)

Purpose: Displays a pending approval with inline actions and swipe support.

Prop Type Description
type 'leave' \| 'commitment' \| 'expense' Approval type — determines badge icon
title string E.g., "Congé annuel" or "Fournitures bureau"
employee string Employee name (for leave)
details string Date range, amount, department, etc.
timestamp string Relative time ("il y a 2h")
attachments Attachment[] Optional supporting documents
onApprove () => void Approve callback
onRefuse (comment: string) => void Refuse callback (opens comment modal)
isOnline boolean If false, action buttons disabled with overlay

Type badges: 🏖 (leave), 💰 (commitment), 🧾 (expense)

States: Default, Swiping (reveal action background), Approved (slide out right, green), Refused (slide out left, red), Offline (buttons greyed + overlay)

Accessibility: role="article" aria-label="{type}: {title} de {employee}. {details}." Action buttons: aria-label="Approuver la demande de {employee}" / aria-label="Refuser la demande de {employee}".

Touch target: Full card is tappable for detail view. Approve/Refuse buttons 48px tall, 120px wide min.

8.4 DegradationBanner (NEW)

Purpose: Persistent banner shown when tenant is in degraded state.

Prop Type Description
status 'trial_expiring' \| 'payment_required' \| 'incomplete_readonly' \| 'suspended' Tenant status
daysRemaining number Days left (for trial/suspended countdown)
ctaUrl string Where "Régulariser" navigates to
onDismiss () => void \| undefined Only for trial_expiring (dismissable)

Color mapping: - trial_expiring--color-info background - payment_required--color-warning background - incomplete_readonly--color-warning background - suspended--color-error background

States: Visible, Dismissed (trial_expiring only — reappears daily), Removed (payment successful — slide-up-and-fade-out 300ms)

Accessibility: role="alert" aria-live="polite". CTA: role="link".

Position: Fixed at top of content area, below top bar. Pushes content down (not overlay). Height: auto (1-2 lines of text + CTA).

8.5 SyncConflictDialog (NEW)

Purpose: Shows sync conflict for manual resolution.

Prop Type Description
entityType string "Note de frais", "Demande de congé", etc.
entityLabel string E.g., "Taxi Plateau"
localVersion ConflictVersion User's offline version (value + label)
serverVersion ConflictVersion Server version (value + label + who modified)
onKeepLocal () => void Keep user's version
onKeepServer () => void Keep server version

States: Open, Resolving (button spinner), Resolved (fade out)

Accessibility: role="alertdialog" aria-label="Conflit de données pour {entityLabel}". Focus trapped inside dialog.

8.6 EmployeeImportCard (NEW)

Purpose: Editable employee card for mobile import flow.

Prop Type Description
employee ImportEmployee Parsed employee data
errors FieldError[] Validation errors for this employee
onEdit (field, value) => void Field edit callback
onDelete () => void Remove from import
onContactMethodChange (method: 'EMAIL' \| 'SMS') => void Contact preference

States: Valid (default), Has errors (red border + error messages), Editing (expanded with editable fields), Deleting (swipe-to-delete with red background)

Accessibility: role="article" aria-label="Employé {name}. {error_count} erreurs." Edit button: aria-label="Modifier les informations de {name}".

Touch target: Full card tappable for edit mode. Contact toggle buttons: 48×32px min.

8.7 OnboardingWizardStep (NEW)

Purpose: Container for each wizard step with progress bar and navigation.

Prop Type Description
currentStep number Current step (1-5)
totalSteps number Total steps (5)
title string Step title with emoji
onNext () => void Continue callback
onBack () => void Back navigation
nextLabel string CTA text (default: "Continuer →")
nextDisabled boolean Disable CTA until validation passes
children ReactNode Step content

Accessibility: Progress bar: role="progressbar" aria-valuenow={currentStep} aria-valuemax={totalSteps} aria-label="Étape {current} sur {total}". Back: aria-label="Retour à l'étape précédente".

8.8 MagicLinkMicroForm (NEW)

Purpose: Single-screen form the DG sees when tapping the magic link (no auth required).

Prop Type Description
dgName string DG's name (from token)
onboarderName string Person who sent the link
companyName string Tenant company name
onSubmit (status: 'SALARIE' \| 'INDEPENDANT') => void Choice callback
isExpired boolean If token expired, show "Lien expiré"

States: Default, Submitted (success screen), Expired ("Ce lien a expiré. Demandez un nouveau lien à {onboarderName}.")

Accessibility: Full page, no login. aria-label="Formulaire de statut du gérant pour {companyName}".

8.9 BillingPlanCard (NEW)

Purpose: Summary card showing the tenant's current plan at top of billing page.

Prop Type Description
segment string "S1", "S2", etc.
segmentLabel string "2-12 employés"
status 'active' \| 'trial' \| 'overdue' \| 'suspended' Plan status
totalMonthly number Total monthly amount in FCFA
nextPaymentDate string DD/MM/YYYY
billingFrequency 'monthly' \| 'annual' Current frequency
onSwitchToAnnual () => void Upsell callback

States: Active (green dot), Trial (blue dot + days remaining), Overdue (amber warning), Suspended (red)

Accessibility: role="region" aria-label="Résumé de votre abonnement : plan {segment}, {status}".


9. Motion Choreography

9.1 Per-Screen Entrance Animations

Screen Animation
Onboarding step transition Current step slides out left (200ms). New step slides in from right (200ms). Progress bar fills smoothly (300ms ease-out).
Tenant switcher open Bottom sheet: slide up (300ms ease-out). Dropdown: fade in + scale from 0.95 (150ms).
Module preview open Bottom sheet: slide up (300ms). Items inside stagger: illustration (0ms), title (50ms), benefits (100ms), pricing (150ms), CTA (200ms).
Approval inbox load Cards stagger in: 50ms between each card, slide up 12px + fade in (200ms each).
Approval — approved Card slides right (200ms) with green background reveal. Badge count decrements with bounce (150ms).
Approval — refused Card slides left (200ms) with red background reveal.
Employee import parse Skeleton shimmer on rows → cards pop in with stagger (50ms each, scale from 0.95 + fade, 150ms).
Billing page load Plan card: fade in (0ms). Modules list: stagger 50ms each. Invoices: stagger 30ms each.
Degradation banner appear Slide down from top (300ms ease-out). Content pushes down smoothly.
Degradation banner remove Slide up (200ms). Content slides up to fill space (200ms).
Sync conflict dialog Modal backdrop fade in (200ms). Dialog slides up from bottom (300ms).

9.2 Celebration Moments

Event Animation
Onboarding complete Confetti burst (3s) + "Bienvenue sur Papillon ! 🦋" toast. See host-shell-design.md §Q9.
Employee import success Brief confetti burst (1.5s) + success toast: "{n} employés créés !"
Trial activated Check icon scale-bounce (150ms) + nav item color pop (amber glow, 300ms).
All approvals cleared Green checkmark scale-in (150ms) + "Vous êtes à jour !" toast.
Payment success (from degraded) Banner slides up (200ms) + brief green flash on top bar (300ms) + "Abonnement réactivé ✓" toast.

9.3 Reduced Motion

All animations respect prefers-reduced-motion: reduce. When active: - Slide/scale animations → instant opacity fade (100ms) - Confetti → disabled - Stagger → simultaneous appearance - Progress bar → instant fill (no animation) - Swipe gestures → still functional but no animated background reveal


10. Brand Compliance Checklist

Papillon HR Suite

Criterion Status Notes
Primary color amber/gold All CTAs, active states, progress bars use --color-primary (#F59E0B)
Mobile-first 360px Every wireframe designed at 360px first
Offline states for all writes Every screen specifies offline behavior. Online-only actions show "Connexion requise" overlay.
48px touch targets All buttons, toggles, cards meet minimum. Specified per component.
Warm French copy All UI text in §7. Tone: friendly, never technical.
Loading skeletons No bare spinners anywhere. All loading states use skeleton shimmer.
Generous whitespace Section spacing uses --space-6 to --space-8. Card padding --space-4.
Celebration animations 5 celebration moments defined (onboarding, import, trial, approvals, payment).
Warm gradients Onboarding wizard header, plan summary card use subtle warm gradients.
Card shadow hierarchy Resting (--shadow-sm), interactive (--shadow-md on hover/press), elevated (--shadow-lg for modals).
Dark mode support Deferred to host-shell-design.md §10 token system. All tokens support dark variant.
Auto-save on all forms Specified in §4.1. Auto-save on blur/change with green check indicator.
French error messages Complete validation message table in §7.10. Never technical jargon.
XOF formatting All prices: "15 000 FCFA" (space separator, zero decimals).
DD/MM/YYYY dates All dates in wireframes use DD/MM/YYYY format.
Phone +225 default Phone prefix pre-filled +225 (CI).

Enterprise (ALTARYS ENTERPRISE HR Suite)

Not applicable for this document. Enterprise frontend design begins at Month 12-13. When it does, this document's patterns (approval inbox, tenant switcher, billing, import) will be re-specified with Enterprise design language (navy, dense, desktop-first, keyboard shortcuts, batch operations).


This design document was produced by the DESIGNER personality after a 9-question UX interview with the Product Owner. Every major design decision (D1–D9) is traceable to an interview response and referenced throughout the document.

All module-level design documents should reference this document for: onboarding flow, tenant switching, module gating UX, approval inbox pattern, degradation banner pattern, sync conflict resolution, and billing/subscription management.