/* =============================================================================
   IndepWeb — Couche design : profondeur de palette + vocabulaire de mouvement
   -----------------------------------------------------------------------------
   Chargée APRÈS style.css et dopamine.css : elle enrichit sans rien réécrire.
   Tout s'applique aux composants existants (.btn, .card, .service-card,
   .stat-card, .badge…) : aucune page n'a besoin d'être modifiée.

   Principes :
     • Le mouvement sert la lecture (hiérarchie, feedback), il ne décore pas.
     • Une seule courbe d'accélération pour toute la plateforme = cohérence.
     • Rien ne bouge pour qui a demandé à réduire les animations.
     • Aucune propriété animée hors `transform` / `opacity` / `filter`
       (les seules que le navigateur compose sans recalcul de mise en page).
   ============================================================================= */

:root {
    /* --- Profondeur du bleu de marque -------------------------------------- */
    --primary-50:  #F0F6FF;
    --primary-100: #DCEAFE;
    --primary-200: #BBD5FD;
    --primary-400: #5B9BFF;
    --primary-600: #1F6AE0;
    --primary-700: #1451B4;
    --primary-900: #0A2B63;

    /* --- Accent secondaire : violet-indigo -----------------------------------
       Analogue au bleu (donc jamais discordant), mais assez distinct pour
       porter la valeur, la récompense et la mise en avant. Utilisé avec
       parcimonie : c'est le seul endroit où la page « monte le ton ». */
    --accent:      #7C5CFC;
    --accent-dark: #5B3FD4;
    --accent-soft: #F1ECFF;
    --on-accent-soft: #4C2FA8;

    /* --- Dégradés maîtrisés ------------------------------------------------- */
    --grad-primary: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
    --grad-accent:  linear-gradient(135deg, var(--accent) 0%, var(--primary) 100%);
    --grad-warm:    linear-gradient(135deg, #FFB020 0%, #FF7A45 100%);
    --grad-success: linear-gradient(135deg, #10B981 0%, #059669 100%);

    /* --- Ombres teintées ----------------------------------------------------
       Une ombre grise sur un fond coloré paraît sale ; une ombre teintée de
       l'accent donne l'impression que l'élément projette sa propre lumière. */
    --shadow-primary:    0 6px 20px -6px rgba(42, 124, 250, .38);
    --shadow-primary-lg: 0 16px 40px -12px rgba(42, 124, 250, .45);
    --shadow-accent:     0 6px 20px -6px rgba(124, 92, 252, .38);
    --shadow-soft:       0 1px 2px rgba(16, 24, 40, .04), 0 8px 24px -8px rgba(16, 24, 40, .10);
    --shadow-hover:      0 2px 4px rgba(16, 24, 40, .05), 0 18px 40px -14px rgba(16, 24, 40, .18);

    /* --- Tokens de mouvement ------------------------------------------------ */
    --ease-out:    cubic-bezier(.22, .61, .36, 1);    /* sorties : décélération franche */
    --ease-spring: cubic-bezier(.34, 1.56, .64, 1);   /* rebond léger : clics, badges */
    --dur-fast:   .16s;
    --dur-base:   .28s;
    --dur-slow:   .5s;
}

html.dark-mode {
    --primary-50:  #0E1A2E;
    --primary-100: #132644;
    --accent-soft: #221A46;
    --on-accent-soft: #C4B5FD;
    --shadow-soft:  0 1px 2px rgba(0, 0, 0, .3), 0 8px 24px -8px rgba(0, 0, 0, .45);
    --shadow-hover: 0 2px 4px rgba(0, 0, 0, .35), 0 18px 40px -14px rgba(0, 0, 0, .55);
}

/* =============================================================================
   1. APPARITION AU SCROLL
   Les blocs entrent une fois, depuis le bas, décalés les uns des autres.
   L'état initial n'est posé QUE si JS est actif (classe .js-reveal ajoutée par
   le script) : sans JS, le contenu reste visible — jamais de page blanche.
   ============================================================================= */
.js-reveal [data-reveal] {
    opacity: 0;
    transform: translateY(18px);
    will-change: opacity, transform;
}
.js-reveal [data-reveal].is-revealed {
    opacity: 1;
    transform: none;
    transition: opacity var(--dur-slow) var(--ease-out),
                transform var(--dur-slow) var(--ease-out);
}
/* Décalage en cascade pour les grilles (cartes qui se suivent) */
.js-reveal [data-reveal][data-reveal-delay="1"].is-revealed { transition-delay: .06s; }
.js-reveal [data-reveal][data-reveal-delay="2"].is-revealed { transition-delay: .12s; }
.js-reveal [data-reveal][data-reveal-delay="3"].is-revealed { transition-delay: .18s; }
.js-reveal [data-reveal][data-reveal-delay="4"].is-revealed { transition-delay: .24s; }
.js-reveal [data-reveal][data-reveal-delay="5"].is-revealed { transition-delay: .30s; }

/* =============================================================================
   2. CARTES — élévation au survol, enfoncement au clic
   Cible les composants réels du site. `translateZ(0)` force la composition GPU.
   ============================================================================= */
.service-card,
.freelancer-card,
.announcement-card,
.order-card-item,
.stat-card,
.category-tile,
.pricing-card,
.blog-card {
    transition: transform var(--dur-base) var(--ease-out),
                box-shadow var(--dur-base) var(--ease-out),
                border-color var(--dur-base) var(--ease-out);
    will-change: transform;
}
@media (hover: hover) and (pointer: fine) {
    .service-card:hover,
    .freelancer-card:hover,
    .announcement-card:hover,
    .order-card-item:hover,
    .category-tile:hover,
    .blog-card:hover {
        transform: translateY(-4px);
        box-shadow: var(--shadow-hover);
        border-color: var(--primary-200);
    }
    /* L'image de la carte respire légèrement pendant le survol */
    .service-card:hover .service-card-image img,
    .blog-card:hover img {
        transform: scale(1.04);
    }
}
.service-card:active,
.freelancer-card:active,
.category-tile:active {
    transform: translateY(-1px) scale(.995);
    transition-duration: var(--dur-fast);
}
.service-card-image img,
.blog-card img {
    transition: transform var(--dur-slow) var(--ease-out);
}
.service-card-image,
.blog-card-image {
    overflow: hidden; /* contient le zoom de l'image */
}

/* =============================================================================
   3. BOUTONS — retour tactile immédiat + halo de la marque
   ============================================================================= */
.btn {
    transition: transform var(--dur-fast) var(--ease-out),
                box-shadow var(--dur-base) var(--ease-out),
                background-color var(--dur-base) var(--ease-out),
                border-color var(--dur-base) var(--ease-out),
                color var(--dur-base) var(--ease-out);
    will-change: transform;
}
@media (hover: hover) and (pointer: fine) {
    .btn-primary:hover { box-shadow: var(--shadow-primary-lg); transform: translateY(-1px); }
    .btn-outline:hover { border-color: var(--primary); color: var(--primary); }
}
.btn:active     { transform: translateY(0) scale(.97); transition-duration: 90ms; }
.btn-primary    { box-shadow: var(--shadow-primary); }
.btn:disabled,
.btn[disabled]  { transform: none !important; box-shadow: none; opacity: .55; cursor: not-allowed; }

/* Bouton en cours de traitement : le halo respire, l'utilisateur sait que ça
   travaille (paiement, envoi de proposition…). À poser via .is-loading. */
.btn.is-loading { position: relative; pointer-events: none; color: transparent !important; }
.btn.is-loading::after {
    content: "";
    position: absolute; inset: 0; margin: auto;
    width: 16px; height: 16px;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    color: #fff;
    animation: iwSpin .6s linear infinite;
}
.btn-outline.is-loading::after { color: var(--primary); }
@keyframes iwSpin { to { transform: rotate(360deg); } }

/* =============================================================================
   4. LIENS DE NAVIGATION — soulignement qui se déploie
   ============================================================================= */
@media (hover: hover) and (pointer: fine) {
    .nav-link, .footer-links a {
        position: relative;
        transition: color var(--dur-base) var(--ease-out);
    }
    .nav-link::after {
        content: "";
        position: absolute; left: 0; right: 0; bottom: -4px;
        height: 2px; border-radius: 2px;
        background: var(--grad-primary);
        transform: scaleX(0);
        transform-origin: left;
        transition: transform var(--dur-base) var(--ease-out);
    }
    .nav-link:hover::after,
    .nav-link.active::after { transform: scaleX(1); }
}

/* =============================================================================
   5. CHAMPS DE FORMULAIRE — la focalisation guide l'œil
   ============================================================================= */
.form-group input,
.form-group textarea,
.form-group select,
.auth-form input,
.search-input {
    transition: border-color var(--dur-base) var(--ease-out),
                box-shadow var(--dur-base) var(--ease-out),
                background-color var(--dur-base) var(--ease-out);
}
.form-group input:focus,
.form-group textarea:focus,
.form-group select:focus,
.auth-form input:focus,
.search-input:focus {
    border-color: var(--primary);
    box-shadow: 0 0 0 4px var(--primary-100);
}
/* Champ en erreur : une secousse courte, une seule fois */
.form-group.has-error input,
.input-error {
    animation: iwShake .34s var(--ease-out);
    border-color: var(--danger) !important;
}
@keyframes iwShake {
    0%, 100% { transform: translateX(0); }
    20%      { transform: translateX(-5px); }
    40%      { transform: translateX(4px); }
    60%      { transform: translateX(-3px); }
    80%      { transform: translateX(2px); }
}

/* =============================================================================
   6. BADGES & PASTILLES — la valeur attire l'œil sans clignoter
   ============================================================================= */
.badge, .pkg-tab, .filter-pill, .chip {
    transition: transform var(--dur-fast) var(--ease-out),
                background-color var(--dur-base) var(--ease-out),
                color var(--dur-base) var(--ease-out);
}
.filter-pill:active, .pkg-tab:active { transform: scale(.96); }

/* Badge « vérifié », gain de points, nouveauté : entrée avec un léger rebond */
.badge-new, .points-badge, .verified-badge {
    animation: iwPop .4s var(--ease-spring) both;
}
@keyframes iwPop {
    from { opacity: 0; transform: scale(.7); }
    to   { opacity: 1; transform: scale(1); }
}

/* Pastille de notification non lue : pulsation lente, non agressive */
.notification-badge:not(:empty),
.unread-count:not(:empty) {
    animation: iwPulse 2.4s var(--ease-out) infinite;
}
@keyframes iwPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, .5); }
    50%      { box-shadow: 0 0 0 6px rgba(239, 68, 68, 0); }
}

/* =============================================================================
   7. MODALES & PANNEAUX — arrivée depuis le bas, pas d'apparition brutale
   ============================================================================= */
.modal.active .modal-content,
.modal.show .modal-content,
.modal[style*="flex"] .modal-content {
    animation: iwModalIn .34s var(--ease-out) both;
}
@keyframes iwModalIn {
    from { opacity: 0; transform: translateY(24px) scale(.97); }
    to   { opacity: 1; transform: none; }
}
.modal { transition: opacity var(--dur-base) var(--ease-out); }

/* =============================================================================
   8. SQUELETTES DE CHARGEMENT — balayage lumineux plutôt que gris figé
   ============================================================================= */
.skeleton, .skeleton-text {
    background: linear-gradient(90deg,
        var(--gray-100) 25%, var(--gray-200) 37%, var(--gray-100) 63%);
    background-size: 400% 100%;
    animation: iwShimmer 1.4s ease-in-out infinite;
}
@keyframes iwShimmer {
    from { background-position: 100% 50%; }
    to   { background-position: 0 50%; }
}

/* =============================================================================
   9. VALEURS & MONTANTS — chiffres alignés, mise en avant du prix
   ============================================================================= */
.price, .stat-value, .wallet-amount, .order-price, .inv-total td {
    font-variant-numeric: tabular-nums;
    letter-spacing: -.01em;
}
.price-highlight, .wallet-balance {
    background: var(--grad-primary);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

/* =============================================================================
   10. SUCCÈS — confirmation visible d'une action qui compte
        (paiement accepté, livraison validée). À poser via .iw-success-flash.
   ============================================================================= */
.iw-success-flash { animation: iwSuccessFlash 1s var(--ease-out) both; }
@keyframes iwSuccessFlash {
    0%   { box-shadow: 0 0 0 0 rgba(16, 185, 129, .45); }
    60%  { box-shadow: 0 0 0 14px rgba(16, 185, 129, 0); }
    100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); }
}

/* =============================================================================
   11. EN-TÊTE — se densifie au défilement (classe posée par le script)
   ============================================================================= */
.header, .navbar {
    transition: box-shadow var(--dur-base) var(--ease-out),
                backdrop-filter var(--dur-base) var(--ease-out);
}
.header.is-scrolled, .navbar.is-scrolled {
    box-shadow: 0 1px 0 var(--gray-200), 0 8px 24px -16px rgba(16, 24, 40, .3);
    backdrop-filter: saturate(1.6) blur(10px);
}

/* =============================================================================
   12. ACCESSIBILITÉ — respect absolu de la préférence système
   ============================================================================= */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }
    .js-reveal [data-reveal] { opacity: 1 !important; transform: none !important; }
}
