/**
 * Weavy - Design tokens + composants uniques (Lot A refonte UX, 17/07/2026).
 *
 * POINT DE PASSAGE UNIQUE du système visuel :
 *  - toutes les couleurs, familles de police, z-index viennent d'ici ;
 *  - un seul composant par usage : .weavy-btn, .weavy-alert, .weavy-badge,
 *    .weavy-stat-card ;
 *  - AUCUNE nouvelle couleur hex ni z-index en dur dans les composants PHP :
 *    utiliser var(--weavy-*). Toute nouvelle teinte se déclare ICI.
 *
 * Chargé AVANT weavy-dashboard-orders.css / subscription.css sur toutes les
 * vues front. Les valeurs reprennent 1:1 la palette dominante existante
 * (aucun changement visuel voulu).
 *
 * Note : --weavy-font-family et --weavy-font-size-base sont injectées par
 * weavy_enqueue_typography_vars() (option admin) et font autorité ; les
 * valeurs ci-dessous ne sont que des filets de sécurité.
 */

:root {
    /* ── Couleurs neutres (refonte violet/encre 27/07/2026, alignée maquette) ── */
    --weavy-ink: #1c244b;          /* texte principal (encre) */
    --weavy-text-strong: #3b4468;  /* texte secondaire appuyé */
    --weavy-muted: #79809e;        /* texte atténué, labels */
    --weavy-border: #e7e9f2;       /* bordures, séparateurs */
    --weavy-surface: #f7f8fc;      /* fonds de cartes secondaires / insets */
    --weavy-surface-2: #f5f6fa;    /* fond de page dashboard */
    --weavy-white: #ffffff;

    /* ── Actions (accent violet, comme la landing) ── */
    --weavy-primary: #7935bc;
    --weavy-primary-hover: #5f2799;
    --weavy-primary-contrast: #ffffff;

    /* ── Neutres complémentaires ── */
    --weavy-border-strong: #dfe2ee;   /* bordures d'inputs, boutons outline */
    --weavy-muted-soft: #9aa0ba;      /* placeholders, unités, carets, dates */
    --weavy-text-secondary: #5b6284;  /* texte de corps dans les cartes */

    /* ── Accent violet : tints (pastilles, avatars, cartes teintées) ── */
    --weavy-accent: #7935bc;
    --weavy-accent-soft: #f3ebfb;     /* fond pastille de nav/statut actif */
    --weavy-accent-tint: #fbf8fe;     /* carte/tile teintée la plus douce */
    --weavy-accent-avatar: #efe6fa;   /* pastille avatar (initiales) */
    --weavy-accent-border: #ecdcf8;   /* bordure sur fond teinté violet */

    /* ── Accent praticien (orange) ── */
    --weavy-orange: #f2762e;
    --weavy-orange-tint: #fdf0e7;

    /* ── Dégradé mini-graphes (clair -> accent) ── */
    --weavy-chart-1: #ece2f8;
    --weavy-chart-2: #d7bff0;
    --weavy-chart-3: #a170dd;

    /* ── Sémantiques pleines (icônes, pastilles, liens d'action) ── */
    --weavy-danger: #e05646;
    --weavy-danger-strong: #c0392f;
    --weavy-success: #0f8a5f;
    --weavy-success-strong: #0d6f4d;

    /* ── Sémantiques : triplets fond / bordure / texte (alignés maquette) ── */
    --weavy-success-bg: #e8f6f0;
    --weavy-success-border: #cfe9dd;
    --weavy-success-text: #0f8a5f;

    --weavy-warning-bg: #fdf3e3;
    --weavy-warning-border: #f3e2c6;
    --weavy-warning-text: #b45309;

    --weavy-danger-bg: #fdecec;
    --weavy-danger-border: #f2dcdf;
    --weavy-danger-text: #c0392f;

    --weavy-info-bg: #f3ebfb;
    --weavy-info-border: #ecdcf8;
    --weavy-info-text: #5f2799;

    /* ── Typographie (filets ; l'option admin fait autorité) ──
       Refonte 27/07 : Helvetica comme la landing. */
    --weavy-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
    --weavy-font-size-base: 15px;

    /* ── Échelle z-index unique ──
       dropdown < drawer < modale < overlay paiement < toast */
    --weavy-z-dropdown: 100;
    --weavy-z-drawer: 1000;
    --weavy-z-modal: 1100;
    --weavy-z-modal-high: 1150; /* modale de confirmation pouvant passer au-dessus d'une autre modale */
    --weavy-z-overlay: 1200;    /* loader de page, overlay de redirection paiement */
    --weavy-z-toast: 1300;

    /* ── Rayons (refonte : boutons/pills 10, cartes 14) ── */
    --weavy-radius: 10px;
    --weavy-radius-lg: 14px;
    --weavy-radius-card: 14px;
    --weavy-radius-pill: 999px;

    /* ── Ombre de carte (douce ; le gros drop-shadow reste réservé au cadre) ── */
    --weavy-shadow-card: 0 1px 2px rgba(28, 36, 75, .04);
    --weavy-shadow-pop: 0 18px 40px -22px rgba(28, 36, 75, .35);

    /* ── Échelle d'espacement (audit système visuel 17/07) ──
       Base 4px, non linéaire, calibrée 1:1 sur les valeurs DOMINANTES déjà
       en place : remplacer un padding/margin/gap on-grid par son token est un
       changement STRICTEMENT ZÉRO PIXEL. Adoption progressive : un composant
       non migré continue de fonctionner à l'identique (comme les tokens
       couleur). Toute NOUVELLE valeur d'espacement doit passer par un token.
       Occurrences existantes couvertes indiquées en commentaire. */
    --weavy-space-3xs: 2px;   /* nudges optiques / hairline */
    --weavy-space-2xs: 4px;
    --weavy-space-xs: 8px;
    --weavy-space-sm: 12px;   /* valeur pivot (la plus fréquente) */
    --weavy-space-md: 16px;
    --weavy-space-lg: 20px;
    --weavy-space-xl: 24px;
    --weavy-space-2xl: 32px;
    --weavy-space-3xl: 40px;  /* gouttières larges */
    --weavy-space-4xl: 60px;  /* états vides / hero */
    /* Ponts off-grid à fort volume : figés à leur valeur exacte pour éviter
       de devoir toucher des centaines d'occurrences d'un coup. À résorber
       opportunément vers un pas voisin quand une revue visuelle est possible. */
    --weavy-space-bridge-6: 6px;
    --weavy-space-bridge-10: 10px;

    /* ── Échelle typographique (audit système visuel 17/07, validée Gilles) ──
       8 pas nommés t-shirt, calibrés sur les valeurs DOMINANTES existantes.
       Les tailles aberrantes (15/17/19/22/26/28/40/48) se re-pointent sur le
       pas voisin (changement de 1-5px assumé). line-height apparié pour
       verrouiller le rythme vertical. Toute NOUVELLE taille passe par un token. */
    --weavy-text-2xs: 11px;  --weavy-lh-2xs: 1.4;   /* micro-labels majuscules, badges tabulaires */
    --weavy-text-xs:  12px;  --weavy-lh-xs: 1.4;    /* badges statut, hints, captions */
    --weavy-text-sm:  13px;  --weavy-lh-sm: 1.45;   /* labels, texte de tableau, compact */
    --weavy-text-base:14px;  --weavy-lh-base: 1.5;  /* CORPS, boutons, inputs, alertes (référence) */
    --weavy-text-md:  16px;  --weavy-lh-md: 1.4;    /* valeurs mises en avant */
    --weavy-text-lg:  18px;  --weavy-lh-lg: 1.35;   /* sous-titres de section, h3 */
    --weavy-text-xl:  24px;  --weavy-lh-xl: 1.25;   /* valeur de stat, titre de carte, h1 */
    --weavy-text-2xl: 32px;  --weavy-lh-2xl: 1.2;   /* hero de page (rare) */

    /* ── Hauteur de contrôle (cibles tactiles, validée Gilles) ──
       Plancher tactile 44px (Apple HIG). Les contrôles denses grossissent
       (assumé). Applique en min-height sur boutons/champs. */
    --weavy-control-height: 44px;      /* boutons principaux, champs de saisie */
    --weavy-control-height-sm: 40px;   /* actions secondaires compactes */
}

/* ════════════════════════════════════════════════════════════════════
   PLANCHER DE SPECIFICITE POUR LES BOUTONS (front)

   Le reset du theme hello-elementor cible [type="button"] / [type="submit"],
   soit une specificite (0,2,0), et il charge APRES nos feuilles. Une regle a
   nous en (0,1,0) — le simple `.weavy-machin` — perd donc, et le bouton
   ressort avec la bordure et le texte rose du theme. En (0,2,0) c'est une
   egalite, et l'ordre de chargement tranche : le theme gagne encore.

   REGLE : tout selecteur qui declare border / background / color d'un BOUTON
   destine au front doit etre prefixe par `button[type]` (ou porter un scope
   #dashboard-app / .weavy-auth-root, qui suffit deja). `button[type].weavy-x`
   vaut (0,2,1) et passe devant. On ne redeclare RIEN dans la garde anti-
   conflit : l'apparence reste ici, en un seul endroit.
   ════════════════════════════════════════════════════════════════════ */

/* ════════════════════════════════════════════════════════════════════
   BOUTON UNIQUE - .weavy-btn
   Remplace : boutons inline avec @mouseover JS, weavy-orders-btn (progressif).
   !important requis : Elementor impose sinon sa couleur d'accent.
   ════════════════════════════════════════════════════════════════════ */
.weavy-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--weavy-space-xs);
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-base);
    font-weight: 600;
    /* min-height cible tactile ; padding vertical reduit a 8px pour ne pas
       depasser 44px (8*2 + 14*1.2 ~= 33, min-height porte le reste). */
    min-height: var(--weavy-control-height);
    padding: 8px 22px;
    border-radius: var(--weavy-radius);
    cursor: pointer;
    transition: background-color 0.15s, color 0.15s, opacity 0.15s;
    white-space: nowrap;
    text-decoration: none !important;
    line-height: 1.2;
}
.weavy-btn:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}

.weavy-btn--primary {
    color: var(--weavy-primary-contrast) !important;
    background: var(--weavy-primary) !important;
    border: none !important;
    box-shadow: none !important;
}
.weavy-btn--primary:hover:not(:disabled) {
    background: var(--weavy-primary-hover) !important;
    color: var(--weavy-primary-contrast) !important;
}

.weavy-btn--outline {
    color: var(--weavy-ink) !important;
    background: var(--weavy-white) !important;
    border: 1px solid var(--weavy-border-strong) !important;
    box-shadow: none !important;
}
.weavy-btn--outline:hover:not(:disabled) {
    background: var(--weavy-surface-2) !important;
    border-color: var(--weavy-muted-soft) !important;
}

/* Bouton "encre" (fond bleu foncé) : filtres actifs "Tous"/"Toutes" de la maquette. */
.weavy-btn--ink {
    color: var(--weavy-white) !important;
    background: var(--weavy-ink) !important;
    border: none !important;
    box-shadow: none !important;
}
.weavy-btn--ink:hover:not(:disabled) {
    background: #12193a !important;
    color: var(--weavy-white) !important;
}

.weavy-btn--danger {
    color: var(--weavy-danger-text) !important;
    background: var(--weavy-danger-bg) !important;
    border: 1px solid var(--weavy-danger-border) !important;
    box-shadow: none !important;
}
.weavy-btn--danger:hover:not(:disabled) {
    background: #fee2e2 !important;
}

.weavy-btn--compact {
    min-height: var(--weavy-control-height-sm);
    padding: 6px 14px;
    font-size: var(--weavy-text-sm);
}
/* Bouton icone seul (menu contextuel, actions de ligne) : carre 44px, cible
   tactile pleine. Reprend l'ancien weavy-orders-btn--menu, qui n'existait que
   dans la section commandes. */
.weavy-btn--icon {
    min-width: var(--weavy-control-height);
    min-height: var(--weavy-control-height);
    padding: 10px;
    font-size: 0;
    line-height: 0;
    background: var(--weavy-white);
    color: var(--weavy-text-strong);
    border: 1px solid var(--weavy-border-strong);
}
.weavy-btn--icon:hover:not(:disabled) {
    background: var(--weavy-surface);
    border-color: var(--weavy-muted-soft);
}

/* ─── Application du plancher de specificite aux deux angles morts ───
   Les variantes --primary / --outline / --ink / --danger s'en sortent grace a
   leur !important. Restaient deux declarations en (0,1,0) que le reset du theme
   ecrasait, verifie au navigateur (Chrome sans interface, page « Mes enfants »
   reconstituee avec le reset du theme charge en dernier, 30/07) :
     - le RAYON de .weavy-btn : tous nos boutons sortaient a 3px (le rayon du
       theme) au lieu de var(--weavy-radius) ;
     - l'apparence de .weavy-btn--icon : bordure 1px #cc3366 et texte #cc3366
       mesures sur le bouton kebab de la carte enfant, alors que la regle de
       composant ci-dessus demande une bordure neutre.
   On repasse devant avec le prefixe documente `button[type]` -> (0,2,1).
   Aucune valeur nouvelle : on redit ce que le composant declare deja.

   Le rayon est volontairement limite aux racines dashboard et abonnement :
   weavy-auth.css declare « .weavy-auth-root .weavy-btn { border-radius: 12px } »
   en (0,2,0), un choix assume pour ses boutons pleine largeur. Un plancher
   generique en (0,2,1) l'ecraserait a 10px au passage. La surface auth souffre
   du meme vol de rayon par le theme et doit etre traitee dans sa propre feuille,
   pas ici. */
#dashboard-app button[type].weavy-btn,
#subscription-app button[type].weavy-btn {
    border-radius: var(--weavy-radius);
}
button[type].weavy-btn--icon {
    background: var(--weavy-white);
    color: var(--weavy-text-strong);
    border: 1px solid var(--weavy-border-strong);
}

/* ════════════════════════════════════════════════════════════════════
   ALERTE UNIQUE - .weavy-alert
   Remplace : bannières inline jaunes, weavy-orders-alert--*, blocs
   d'erreur/succès inline des formulaires.
   ════════════════════════════════════════════════════════════════════ */
.weavy-alert {
    display: block;
    /* Un message s'insere toujours dans un flux vertical : sans marge propre il
       se colle a l'element suivant. Sur 24 points d'appel, 3 seulement posaient
       la leur - le defaut appartient donc au composant, pas aux appelants.
       Les marges en ligne deja presentes ont la priorite et ne s'ajoutent pas. */
    margin: 0 0 var(--weavy-space-md) 0;
    padding: var(--weavy-space-sm) var(--weavy-space-md);
    border-radius: var(--weavy-radius);
    border: 1px solid var(--weavy-border);
    background: var(--weavy-surface);
    color: var(--weavy-text-strong);
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-base);
    line-height: var(--weavy-lh-base);
}
/* Dernier element de son conteneur : la marge doublerait le padding du parent. */
.weavy-alert:last-child {
    margin-bottom: 0;
}
.weavy-alert--success {
    background: var(--weavy-success-bg);
    border-color: var(--weavy-success-border);
    color: var(--weavy-success-text);
}
.weavy-alert--warning {
    background: var(--weavy-warning-bg);
    border-color: var(--weavy-warning-border);
    color: var(--weavy-warning-text);
}
.weavy-alert--danger {
    background: var(--weavy-danger-bg);
    border-color: var(--weavy-danger-border);
    color: var(--weavy-danger-text);
}
.weavy-alert--info {
    background: var(--weavy-info-bg);
    border-color: var(--weavy-info-border);
    color: var(--weavy-info-text);
}
/* Alerte ACTIONNABLE : message + boutons. Sous-elements du composant partage,
   pour que « une bannière avec une action » ne se re-dessine pas page par page.
   La variante --split est explicite : sans elle, le retour a la ligne
   ferait descendre le texte des alertes ordinaires sous leur pastille. */
.weavy-alert__content {
    flex: 1 1 240px;
    min-width: 0;
}
.weavy-alert__title {
    display: block;
    font-weight: 700;
}
.weavy-alert__actions {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: var(--weavy-space-xs, 8px);
}
#dashboard-app .weavy-alert--split,
#subscription-app .weavy-alert--split {
    flex-wrap: wrap;
    align-items: center;
}

/* ════════════════════════════════════════════════════════════════════
   Refonte : messages inline d'erreur / succès en style "toast".
   Scopé au dashboard et à l'abonnement (l'auth garde .weavy-auth-msg).
   Carte arrondie, ombre douce + pastille d'icône. Pas de liseré latéral :
   la pastille porte déjà la variante, le doubler surcharge (cf. .weavy-banner).
   ════════════════════════════════════════════════════════════════════ */
#dashboard-app .weavy-alert,
#subscription-app .weavy-alert {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px 16px;
    border-radius: 12px;
    border: 1px solid var(--weavy-border);
    background: #fff;
    box-shadow: 0 8px 22px -14px rgba(28, 36, 75, 0.28);
    color: #1c244b;
    font-family: var(--weavy-font-family);
    font-size: 14px;
    line-height: 1.5;
}
#dashboard-app .weavy-alert::before,
#subscription-app .weavy-alert::before {
    flex: none;
    width: 20px;
    height: 20px;
    border-radius: 999px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    font-weight: 700;
    line-height: 1;
    color: #fff;
    margin-top: 1px;
}
/* Les couleurs de texte reprennent les tokens sémantiques : certains messages
   portent encore un color inline sur leur <p> (var(--weavy-*-text)), qui
   l'emporte sur le conteneur. Une seule source de vérité évite l'écart de teinte. */
#dashboard-app .weavy-alert--success,
#subscription-app .weavy-alert--success { background: #f0faf5; border-color: var(--weavy-success-border); color: var(--weavy-success-text); }
#dashboard-app .weavy-alert--success::before,
#subscription-app .weavy-alert--success::before { content: "\2713"; background: var(--weavy-success-text); }
#dashboard-app .weavy-alert--danger,
#subscription-app .weavy-alert--danger { background: #fdf1f1; border-color: var(--weavy-danger-border); color: var(--weavy-danger-text); }
#dashboard-app .weavy-alert--danger::before,
#subscription-app .weavy-alert--danger::before { content: "\2715"; background: var(--weavy-danger-text); }
#dashboard-app .weavy-alert--warning,
#subscription-app .weavy-alert--warning { background: #fdf6ea; border-color: var(--weavy-warning-border); color: var(--weavy-warning-text); }
#dashboard-app .weavy-alert--warning::before,
#subscription-app .weavy-alert--warning::before { content: "!"; background: var(--weavy-warning-text); }
#dashboard-app .weavy-alert--info,
#subscription-app .weavy-alert--info { background: #f7f1fd; border-color: var(--weavy-info-border); color: var(--weavy-info-text); }
#dashboard-app .weavy-alert--info::before,
#subscription-app .weavy-alert--info::before { content: "i"; background: var(--weavy-info-text); }

/* ════════════════════════════════════════════════════════════════════
   BADGE DE STATUT UNIQUE - .weavy-badge
   Toujours couleur + libellé texte (jamais la couleur seule : daltonisme).
   ════════════════════════════════════════════════════════════════════ */
.weavy-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--weavy-space-bridge-6);
    padding: 3px var(--weavy-space-bridge-10);
    border-radius: 999px;
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-xs);
    font-weight: 600;
    line-height: var(--weavy-lh-xs);
    border: 1px solid var(--weavy-border);
    background: var(--weavy-surface);
    color: var(--weavy-text-strong);
    white-space: nowrap;
}
.weavy-badge--success {
    background: var(--weavy-success-bg);
    border-color: var(--weavy-success-border);
    color: var(--weavy-success-text);
}
.weavy-badge--warning {
    background: var(--weavy-warning-bg);
    border-color: var(--weavy-warning-border);
    color: var(--weavy-warning-text);
}
.weavy-badge--danger {
    background: var(--weavy-danger-bg);
    border-color: var(--weavy-danger-border);
    color: var(--weavy-danger-text);
}
.weavy-badge--info {
    background: var(--weavy-info-bg);
    border-color: var(--weavy-info-border);
    color: var(--weavy-info-text);
}
.weavy-badge--neutral {
    background: var(--weavy-surface);
    border-color: var(--weavy-border);
    color: var(--weavy-muted);
}
/* Violet : statuts "actifs/en cours/offert/par défaut" (ACTIF, EN COURS, OFFERTE...). */
.weavy-badge--primary {
    background: var(--weavy-accent-soft);
    border-color: var(--weavy-accent-border);
    color: var(--weavy-accent);
}
/* Orange : accent praticien (badge PRATICIEN, compteurs de demandes). */
.weavy-badge--orange {
    background: var(--weavy-orange-tint);
    border-color: #f7d9c4;
    color: var(--weavy-orange);
}

/* ════════════════════════════════════════════════════════════════════
   CARTE STAT UNIQUE - .weavy-stat-card
   Remplace : weavy-children-stats, weavy-praticien-extra-stats,
   weavy-suivi-stats, weavy-events-stats, weavy-testimonials-stats,
   weavy-mes-documents-stats (progressif).
   ════════════════════════════════════════════════════════════════════ */
.weavy-stat-cards {
    display: grid;
    /* min(200px, 100%) et non 200px : avec une borne basse FIXE, une piste ne
       peut pas descendre sous 200px, et la rangee deborde donc a droite des que
       le conteneur est plus etroit (colonne de dashboard reduite, rendu dans la
       modale « Mes enfants » large de 1000px moins ses marges, telephone en
       paysage etroit...). En bornant a 100% du conteneur, la piste sait
       retrecir : le debordement lateral devient impossible, quelle que soit la
       largeur d'accueil. */
    grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
    gap: var(--weavy-space-md);
}
.weavy-stat-card {
    background: var(--weavy-white);
    border: 1px solid var(--weavy-border);
    border-radius: var(--weavy-radius-lg);
    padding: var(--weavy-space-md) var(--weavy-space-lg);
}
.weavy-stat-card__value {
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-xl);
    font-weight: 700;
    color: var(--weavy-ink);
    line-height: var(--weavy-lh-xl);
}
.weavy-stat-card__label {
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-sm);
    color: var(--weavy-muted);
    margin-top: var(--weavy-space-2xs);
}
.weavy-stat-card__value--success {
    color: var(--weavy-success-text);
}
.weavy-stat-card__value--warning {
    color: var(--weavy-warning-text);
}
.weavy-stat-card__value--danger {
    color: var(--weavy-danger-text);
}

/* ════════════════════════════════════════════════════════════════════
   STEPPER D'ONBOARDING - .weavy-stepper (Lot D)
   Parcours praticien : Profil - Compte - Formule - Paiement - Documents.

   Code couleur (arbitré le 30/07) :
     - étape FRANCHIE : violet plein, chiffre blanc. Elle est acquise, elle
       s'affirme. Plus de coche verte : le chiffre suffit et garde la lecture
       « où j'en suis sur 5 ».
     - étape EN COURS : violet clair, chiffre violet foncé. Même langage que la
       pastille « PR » du récapitulatif : teinté = en cours, pas encore acquis.
     - étape À VENIR : gris.
   ════════════════════════════════════════════════════════════════════ */
.weavy-stepper {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    gap: 14px;
    margin: 0 auto var(--weavy-space-xl) auto;
    max-width: 620px;
    font-family: var(--weavy-font-family);
}
.weavy-stepper__step {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    min-width: 0;
    text-align: center;
}
.weavy-stepper__dot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 999px;
    font-size: 14px;
    font-weight: 700;
    background: #eceef6;
    color: #9aa0ba;
    border: none;
}
.weavy-stepper__label {
    font-size: 13px;
    font-weight: 600;
    color: #9aa0ba;
    line-height: 1.3;
}
/* En cours : teinté, comme la pastille du récapitulatif. */
.weavy-stepper__step--current .weavy-stepper__dot {
    background: var(--weavy-accent-soft);
    color: var(--weavy-primary);
}
.weavy-stepper__step--current .weavy-stepper__label {
    color: var(--weavy-primary);
    font-weight: 700;
}
/* Franchie : violet plein. */
.weavy-stepper__step--done .weavy-stepper__dot {
    background: var(--weavy-primary);
    color: var(--weavy-primary-contrast);
}
.weavy-stepper__step--done .weavy-stepper__label {
    color: var(--weavy-ink);
}
/* Connecteur : aligné au centre des pastilles (34px), violet une fois l'étape franchie. */
.weavy-stepper__link {
    flex: 0 0 70px;
    max-width: 70px;
    height: 2px;
    background: #dfe2ee;
    margin-top: 16px;
}
.weavy-stepper__link--done {
    background: var(--weavy-primary);
}
@media (max-width: 640px) {
    .weavy-stepper__link {
        flex-basis: 28px;
    }
    .weavy-stepper__label {
        font-size: 11px;
    }
}

/* ════════════════════════════════════════════════════════════════════
   OVERLAYS - classes d'appoint pour harmoniser les z-index existants
   (les modales/drawers inline migrent vers var(--weavy-z-*)).
   ════════════════════════════════════════════════════════════════════ */
.weavy-overlay-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(17, 24, 39, 0.5);
}

/* ════════════════════════════════════════════════════════════════════
   CIBLES TACTILES (audit 17/07, validé Gilles) - min-height 44px
   min-height ne fait que GRANDIR le controle, jamais retrecir son contenu.
   Les contrôles denses gagnent en hauteur (changement assumé). Le centrage
   flex evite que le texte reste colle en haut de la boite agrandie.
   Le bouton icone (--icon) est deja 44x44, exclu.
   Note : .weavy-orders-btn a converge vers .weavy-btn, qui porte deja
   min-height dans sa propre regle - il n'a plus besoin de figurer ici.
   ════════════════════════════════════════════════════════════════════ */
#dashboard-app .weavy-mes-documents-btn,
#dashboard-app .weavy-praticien-extra-main-card__cta,
#dashboard-app .weavy-praticien-extra-page-btn,
#dashboard-app .weavy-dashboard-subscription-cta,
#subscription-app .weavy-plan-card__button {
    min-height: var(--weavy-control-height);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
/* Champs de saisie (hors textarea multi-lignes, deja plus haut) */
#dashboard-app .weavy-licenses-toolbar__select,
#dashboard-app .weavy-mp-browse-list__input,
#dashboard-app .weavy-mp-browse-list__select,
#dashboard-app input[type="text"],
#dashboard-app input[type="email"],
#dashboard-app input[type="url"],
#dashboard-app input[type="number"],
#dashboard-app input[type="tel"],
#dashboard-app input[type="password"],
#dashboard-app select,
#subscription-app input:not([type="checkbox"]):not([type="radio"]),
#subscription-app select {
    min-height: var(--weavy-control-height);
}

/* ════════════════════════════════════════════════════════════════════
   MOBILE - anti-zoom iOS sur les champs (audit systeme visuel 17/07)
   iOS Safari zoome automatiquement au focus quand la police d'un champ
   est < 16px, ce qui deforme la mise en page a chaque saisie. On force
   16px sur les controles de saisie sous 640px (parade standard, WCAG).
   Scope aux racines d'app Weavy pour ne pas toucher au theme hote.
   ════════════════════════════════════════════════════════════════════ */
@media (max-width: 640px) {
    #dashboard-app input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
    #dashboard-app select,
    #dashboard-app textarea,
    #subscription-app input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
    #subscription-app select,
    #subscription-app textarea,
    #documents-app input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
    #documents-app select,
    #documents-app textarea,
    #app input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
    #app select,
    #app textarea {
        font-size: 16px !important;
    }
}

/* ════════════════════════════════════════════════════════════════════
   PRIMITIVES PARTAGÉES DE LA REFONTE (27/07/2026)
   Carte, avatar, mini-graphe, toggle, contrôle segmenté, état vide,
   en-tête de section. Tout en tokens, réutilisable par chaque écran.
   ════════════════════════════════════════════════════════════════════ */

/* Carte de base : fond blanc, bordure fine, rayon 14. */
.weavy-card {
    background: var(--weavy-white);
    border: 1px solid var(--weavy-border);
    border-radius: var(--weavy-radius-card);
    box-shadow: var(--weavy-shadow-card);
}
.weavy-card--tint {
    background: var(--weavy-accent-tint);
    border-color: var(--weavy-accent-border);
}
.weavy-card--pad {
    padding: var(--weavy-space-lg) var(--weavy-space-xl);
}

/* En-tête d'écran : H2 + sous-titre. */
.weavy-page-head {
    display: flex;
    flex-direction: column;
    gap: var(--weavy-space-2xs);
}
.weavy-page-head__title {
    margin: 0;
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-xl);
    font-weight: 700;
    letter-spacing: -.3px;
    color: var(--weavy-ink);
    line-height: var(--weavy-lh-xl);
}
.weavy-page-head__sub {
    margin: 0;
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-base);
    color: var(--weavy-muted);
}

/* Pastille avatar à initiales. */
.weavy-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 999px;
    background: var(--weavy-accent-avatar);
    color: var(--weavy-accent);
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-xs);
    font-weight: 700;
    flex: 0 0 auto;
}
.weavy-avatar--orange {
    background: var(--weavy-orange-tint);
    color: var(--weavy-orange);
}
.weavy-avatar--lg { width: 40px; height: 40px; font-size: var(--weavy-text-base); }

/* Mini-graphe en barres (dégradé clair -> accent). */
.weavy-minibars {
    display: flex;
    align-items: flex-end;
    gap: var(--weavy-space-2xs);
    height: 34px;
}
.weavy-minibars__bar {
    flex: 1;
    background: var(--weavy-chart-1);
    border-radius: 3px;
    min-height: 3px;
}
.weavy-minibars__bar--mid { background: var(--weavy-chart-2); }
.weavy-minibars__bar--strong { background: var(--weavy-accent); }
.weavy-minibars__bar--orange { background: var(--weavy-orange); }

/* Contrôle segmenté (sélecteur de période 7j/30j/3mois/1an). */
.weavy-segmented {
    display: inline-flex;
    background: var(--weavy-white);
    border: 1px solid var(--weavy-border-strong);
    border-radius: var(--weavy-radius);
    padding: 3px;
    gap: 2px;
}
button[type].weavy-segmented__item {
    appearance: none;
    border: none;
    background: transparent;
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-sm);
    font-weight: 600;
    color: var(--weavy-muted);
    padding: 7px 13px;
    border-radius: 8px;
    cursor: pointer;
    white-space: nowrap;
    line-height: 1;
}
button[type].weavy-segmented__item--active {
    color: var(--weavy-white);
    background: var(--weavy-primary);
}

/* Interrupteur (toggle) - état on = accent. */
.weavy-toggle {
    display: inline-flex;
    align-items: center;
    width: 42px;
    height: 24px;
    border-radius: 999px;
    background: #e2e5f0;
    padding: 3px;
    border: none;
    cursor: pointer;
    transition: background-color .15s;
    flex: 0 0 auto;
}
.weavy-toggle__knob {
    width: 18px;
    height: 18px;
    border-radius: 999px;
    background: var(--weavy-white);
    box-shadow: 0 1px 2px rgba(28, 36, 75, .25);
    transition: transform .15s;
}
.weavy-toggle--on { background: var(--weavy-primary); }
.weavy-toggle--on .weavy-toggle__knob { transform: translateX(18px); }

/* Groupe de pastilles-filtres (Tous / En attente / Validés...). */
.weavy-filter-pills {
    display: flex;
    flex-wrap: wrap;
    gap: var(--weavy-space-xs);
}
button[type].weavy-filter-pill {
    appearance: none;
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-sm);
    font-weight: 500;
    color: var(--weavy-text-secondary);
    background: var(--weavy-white);
    border: 1px solid var(--weavy-border-strong);
    padding: 8px 15px;
    border-radius: 999px;
    cursor: pointer;
    white-space: nowrap;
    min-height: var(--weavy-control-height-sm);
}
button[type].weavy-filter-pill--active {
    color: var(--weavy-white);
    background: var(--weavy-ink);
    border-color: var(--weavy-ink);
    font-weight: 600;
}

/* État vide "repensé" : titre + copy + actions. */
.weavy-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--weavy-space-bridge-10);
    padding: var(--weavy-space-2xl) var(--weavy-space-xl);
    background: var(--weavy-white);
    border: 1px dashed var(--weavy-accent-border);
    border-radius: var(--weavy-radius-card);
}
.weavy-empty__title {
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-md);
    font-weight: 700;
    color: var(--weavy-ink);
}
.weavy-empty__text {
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-sm);
    line-height: 1.55;
    color: var(--weavy-muted);
    max-width: 340px;
}
.weavy-empty__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--weavy-space-xs);
    justify-content: center;
    margin-top: var(--weavy-space-2xs);
}
/* Icone d'illustration : pastille ronde teintee. Reprend les __icon locaux
   (weavy-orders-empty__icon, etc.) qui declaraient chacun leur taille. */
.weavy-empty__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 52px;
    height: 52px;
    border-radius: 50%;
    background: var(--weavy-accent-soft);
    color: var(--weavy-primary);
    margin-bottom: var(--weavy-space-2xs);
}
.weavy-empty__icon svg {
    width: 24px;
    height: 24px;
    display: block;
}
.weavy-empty--locked .weavy-empty__icon {
    background: var(--weavy-warning-bg);
    color: var(--weavy-warning-text);
}
/* Variante discrete : pas de cadre, pour un vide inline dans une carte
   existante (liste filtree, panneau lateral) qui a deja ses bordures. */
.weavy-empty--plain {
    background: transparent;
    border: none;
    padding: var(--weavy-space-xl) var(--weavy-space-md);
}
/* Variante "indisponible / verrouillé" : accent ambre (ex : action réservée aux ambassadeurs). */
.weavy-empty--locked {
    background: var(--weavy-warning-bg);
    border-color: var(--weavy-warning-border);
}
.weavy-empty--locked .weavy-empty__title {
    color: var(--weavy-warning-text);
}
/* Liste de tâches / conditions à remplir, centrée dans l'état vide. */
.weavy-empty__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--weavy-space-2xs);
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-sm);
    color: var(--weavy-muted);
}
.weavy-empty__list li {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--weavy-space-bridge-6);
}

/* ── Squelettes de chargement (shimmer) : grille indicateurs + cartes ── */
.weavy-ind-skeleton-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 20px;
}
.weavy-skeleton-card {
    background: var(--weavy-white);
    border: 1px solid var(--weavy-border);
    border-radius: var(--weavy-radius-card);
    padding: 20px;
}
.weavy-skeleton-card__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 16px;
}
.weavy-skeleton-line,
.weavy-skeleton-chart {
    background: linear-gradient(90deg, #eef0f6 25%, #f6f7fb 37%, #eef0f6 63%);
    background-size: 400% 100%;
    animation: weavy-shimmer 1.4s ease infinite;
}
.weavy-skeleton-line {
    border-radius: 6px;
}
.weavy-skeleton-line--title { width: 60%; height: 13px; margin-bottom: 8px; }
.weavy-skeleton-line--sub { width: 40%; height: 10px; }
.weavy-skeleton-line--value { width: 44px; height: 22px; flex-shrink: 0; border-radius: 8px; }
.weavy-skeleton-chart {
    height: 180px;
    border-radius: 10px;
}
@media (prefers-reduced-motion: reduce) {
    .weavy-skeleton-line,
    .weavy-skeleton-chart { animation: none; }
}
@keyframes weavy-shimmer {
    0% { background-position: 100% 0; }
    100% { background-position: 0 0; }
}

/* ── Squelettes generiques additionnels : rangee de stats, tableau, liste, bandeau ── */
/* Rangee de cartes stat en squelette (pages avec .weavy-stat-cards) */
.weavy-skeleton-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: var(--weavy-space-sm);
    margin-bottom: var(--weavy-space-md);
}
.weavy-skeleton-stat {
    background: var(--weavy-white);
    border: 1px solid var(--weavy-border);
    border-radius: var(--weavy-radius-card);
    padding: var(--weavy-space-md);
    display: flex;
    flex-direction: column;
    gap: var(--weavy-space-bridge-10);
}

/* Tableau en squelette : entete + lignes */
.weavy-skeleton-table {
    background: var(--weavy-white);
    border: 1px solid var(--weavy-border);
    border-radius: var(--weavy-radius-card);
    padding: var(--weavy-space-md) var(--weavy-space-lg);
}
.weavy-skeleton-row {
    display: flex;
    align-items: center;
    gap: var(--weavy-space-md);
    padding: 14px 0;
    border-bottom: 1px solid var(--weavy-border);
}
.weavy-skeleton-row:last-child { border-bottom: 0; }
.weavy-skeleton-row--head { padding-top: var(--weavy-space-xs); }
.weavy-skeleton-row .weavy-skeleton-line { margin: 0; }
.weavy-skeleton-row__cell { flex: 1 1 0; height: 12px; }
.weavy-skeleton-row__cell--sm { flex: 0 0 72px; }

/* Liste de lignes/cartes empilees */
.weavy-skeleton-list {
    display: flex;
    flex-direction: column;
    gap: var(--weavy-space-sm);
}

/* Bandeau (hero / banniere) en squelette */
.weavy-skeleton-banner {
    background: var(--weavy-white);
    border: 1px solid var(--weavy-border);
    border-radius: var(--weavy-radius-card);
    padding: var(--weavy-space-lg) var(--weavy-space-xl);
    margin-bottom: var(--weavy-space-md);
    display: flex;
    flex-direction: column;
    gap: var(--weavy-space-sm);
}

/* ── Total des bonus (compact, discret) ── */
.weavy-benefits-total {
    display: inline-flex;
    align-items: baseline;
    gap: var(--weavy-space-xs);
    padding: 7px var(--weavy-space-md);
    background: var(--weavy-accent-soft);
    border: 1px solid var(--weavy-accent-border);
    border-radius: 999px;
    margin-bottom: var(--weavy-space-lg);
}
.weavy-benefits-total__label {
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-sm);
    color: var(--weavy-muted);
}
.weavy-benefits-total__value {
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-md);
    font-weight: 700;
    color: var(--weavy-primary);
}

/* ── Historique des bonus (liste chronologique) ── */
.weavy-benefits-timeline {
    display: flex;
    flex-direction: column;
}
.weavy-benefit-row {
    display: flex;
    align-items: center;
    gap: var(--weavy-space-sm);
    padding: var(--weavy-space-md) 0;
    border-bottom: 1px solid var(--weavy-border);
}
.weavy-benefit-row:last-child {
    border-bottom: none;
}
.weavy-benefit-row__marker {
    flex-shrink: 0;
    width: 44px;
    height: 44px;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--weavy-text-lg);
    background: var(--weavy-accent-soft);
    color: var(--weavy-accent);
}
.weavy-benefit-row__body {
    flex: 1;
    min-width: 0;
}
.weavy-benefit-row__label {
    margin: 0 0 2px;
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-base);
    font-weight: 600;
    color: var(--weavy-ink);
}
.weavy-benefit-row__date {
    margin: 0;
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-xs);
    color: var(--weavy-muted);
}
.weavy-benefit-row__amount {
    flex-shrink: 0;
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-sm);
    font-weight: 700;
    color: var(--weavy-primary);
    background: var(--weavy-accent-soft);
    border: 1px solid var(--weavy-accent-border);
    padding: 5px var(--weavy-space-sm);
    border-radius: 999px;
    white-space: nowrap;
}

/* ── Mise en page de formulaire (refonte) : sections + grille 2 colonnes ── */
.weavy-form-section {
    background: var(--weavy-white);
    border: 1px solid var(--weavy-border);
    border-radius: var(--weavy-radius-card);
    box-shadow: var(--weavy-shadow-card);
    padding: var(--weavy-space-xl) var(--weavy-space-xl);
    margin-bottom: var(--weavy-space-md);
}
.weavy-form-section__title {
    margin: 0 0 var(--weavy-space-md);
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-md);
    font-weight: 700;
    color: var(--weavy-ink);
}
.weavy-form-section__hint {
    margin: -8px 0 var(--weavy-space-md);
    font-size: var(--weavy-text-sm);
    color: var(--weavy-muted);
}
/* Section a colonne de libelle a gauche (mockup P5 : 220px libelle / 1fr champs). */
.weavy-form-section--split {
    display: grid;
    grid-template-columns: 220px 1fr;
    gap: var(--weavy-space-xl);
    align-items: start;
}
.weavy-form-section__aside {
    display: flex;
    flex-direction: column;
    gap: var(--weavy-space-2xs);
}
.weavy-form-section__desc {
    font-size: var(--weavy-text-sm);
    color: var(--weavy-muted);
    line-height: 1.5;
    margin: 0;
}
.weavy-form-section__fields {
    min-width: 0;
    display: flex;
    flex-direction: column;
}
@media (max-width: 768px) {
    .weavy-form-section--split {
        grid-template-columns: 1fr;
        gap: var(--weavy-space-md);
    }
}

/* Grille 2 colonnes (une seule sous 640px). Neutralise le mb-4 des champs. */
.weavy-form-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--weavy-space-md);
}
.weavy-form-grid > * {
    margin-bottom: 0 !important;
    min-width: 0;
}
.weavy-form-grid__full {
    grid-column: 1 / -1;
}
@media (max-width: 639px) {
    .weavy-form-grid {
        grid-template-columns: 1fr;
    }
}

/* Barre d'enregistrement collante (bas de formulaire). */
.weavy-save-bar {
    position: sticky;
    bottom: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--weavy-space-md);
    flex-wrap: wrap;
    margin-top: var(--weavy-space-md);
    padding: var(--weavy-space-sm) var(--weavy-space-lg);
    background: var(--weavy-white);
    border: 1px solid var(--weavy-border);
    border-radius: var(--weavy-radius-card);
    box-shadow: 0 -6px 24px -14px rgba(28, 36, 75, .3);
    z-index: 2;
}
.weavy-save-bar__note {
    font-size: var(--weavy-text-sm);
    color: var(--weavy-muted);
}
.weavy-save-bar__actions {
    display: flex;
    gap: var(--weavy-space-xs);
    flex-wrap: wrap;
}

/* Barre de progression fine (ambassadeur, quota enfants...). */
.weavy-progress {
    height: 9px;
    border-radius: 999px;
    background: var(--weavy-surface-2);
    overflow: hidden;
}
.weavy-progress__fill {
    height: 100%;
    border-radius: 999px;
    background: linear-gradient(90deg, var(--weavy-primary), var(--weavy-orange));
}

/* ════════════════════════════════════════════════════════════════════
   BANNIERE UNIQUE - .weavy-banner
   Composant : app/components/ui/banner.php

   Remplace les familles divergentes qui rendaient toutes la meme chose
   (variante + titre + texte + actions) avec un habillage different :
   weavy-docs-promo, weavy-sub-reminder, weavy-dashboard-visibility-banner,
   weavy-testimonials-promo, weavy-subscription-notice,
   weavy-mes-documents-banner, weavy-orders-alert, weavy-mp-alert.

   Carte blanche + pastille d'icone teintee par la variante : la couleur
   porte le sens sans nuire a la lisibilite du texte (les anciens aplats
   ambre/lavande delavaient le contenu).
   ════════════════════════════════════════════════════════════════════ */
.weavy-banner {
    display: flex;
    align-items: center;
    gap: 16px;
    background: #fff;
    border: 1px solid var(--weavy-border, #e7e9f2);
    border-radius: 14px;
    padding: 18px 20px;
    margin-bottom: 20px;
    box-shadow: 0 6px 18px -14px rgba(28, 36, 75, 0.18);
    font-family: var(--weavy-font-family);
    box-sizing: border-box;
}
.weavy-banner__icon {
    flex: none;
    width: 44px;
    height: 44px;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.weavy-banner--info .weavy-banner__icon { background: #f3ebfb; color: #7935bc; }
.weavy-banner--warn .weavy-banner__icon { background: #fdf3e3; color: #b45309; }
.weavy-banner--success .weavy-banner__icon { background: #e8f6f0; color: #0f8a5f; }
.weavy-banner--danger .weavy-banner__icon { background: #fdecec; color: #c0392f; }
.weavy-banner--neutral .weavy-banner__icon { background: var(--weavy-surface-2, #f5f6fa); color: var(--weavy-muted, #79809e); }

/* Pas de lisere lateral : la pastille d'icone porte deja la variante, et le
   doubler surchargeait la carte (retour Gilles). La couleur reste donc
   presente une seule fois, au bon endroit. */

.weavy-banner__body { flex: 1; min-width: 0; }
.weavy-banner__title {
    margin: 0 0 4px;
    font-size: 15px;
    font-weight: 700;
    color: var(--weavy-ink, #1c244b);
}
.weavy-banner__text {
    margin: 0;
    font-size: 13px;
    line-height: 1.5;
    color: var(--weavy-text-secondary, #5b6284);
}
.weavy-banner__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    flex: none;
}
.weavy-banner__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    font-size: 13px;
    font-weight: 600;
    font-family: inherit;
    border-radius: 10px;
    padding: 11px 16px;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    border: 1px solid transparent;
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.weavy-banner__btn--primary { background: var(--weavy-primary, #7935bc); color: #fff; }
.weavy-banner__btn--primary:hover { background: var(--weavy-primary-hover, #5f2799); color: #fff; }
.weavy-banner__btn--ghost { background: #fff; border-color: var(--weavy-border-strong, #e0e3f0); color: var(--weavy-ink, #1c244b); }
.weavy-banner__btn--ghost:hover { border-color: var(--weavy-primary, #7935bc); color: var(--weavy-primary, #7935bc); }
.weavy-banner__btn--link {
    background: none;
    border: none;
    padding: 11px 4px;
    color: var(--weavy-primary, #7935bc);
    text-decoration: underline;
}
.weavy-banner__spinner {
    width: 20px;
    height: 20px;
    border: 2.5px solid #e6d8f5;
    border-top-color: var(--weavy-primary, #7935bc);
    border-radius: 50%;
    animation: spin 1s linear infinite;
}
@media (max-width: 640px) {
    .weavy-banner { flex-direction: column; align-items: flex-start; }
    .weavy-banner__actions { width: 100%; }
    .weavy-banner__btn { flex: 1; }
}

/* ════════════════════════════════════════════════════════════════════
   PANNEAU DE PAIEMENT EMBARQUE - .weavy-dropin-panel
   Coquille du Drop-in Airwallex, commune a tous les parcours de paiement
   (abonnement, commande d'appareil, licences). Composant PHP associe :
   app/components/ui/dropin-panel.php.

   Etait scope a .weavy-subscription-root dans subscription.css ; remonte ici
   le 28/07/2026 pour que le tableau de bord encaisse sur la page au lieu de
   rediriger vers la page hebergee Airwallex (WEAVY-105).
   ════════════════════════════════════════════════════════════════════ */
.weavy-dropin-panel {
    background: var(--weavy-white);
    border: 1px solid var(--weavy-border);
    border-radius: var(--weavy-radius-card);
    box-shadow: 0 6px 18px -12px rgba(28, 36, 75, 0.15);
    padding: var(--weavy-space-xl);
}
.weavy-dropin-panel__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--weavy-space-sm);
    margin-bottom: 18px;
}
.weavy-dropin-panel__title {
    margin: 0;
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-lg);
    line-height: var(--weavy-lh-lg);
    font-weight: 700;
    color: var(--weavy-ink);
}
button[type].weavy-dropin-panel__back {
    background: none;
    border: none;
    cursor: pointer;
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-sm);
    line-height: var(--weavy-lh-sm);
    font-weight: 600;
    color: var(--weavy-primary);
    padding: 0;
}
button[type].weavy-dropin-panel__back:hover { color: var(--weavy-primary-hover); }
.weavy-dropin-panel__error {
    background: var(--weavy-danger-bg);
    border: 1px solid var(--weavy-danger-border);
    color: var(--weavy-danger-text);
    border-radius: var(--weavy-radius);
    padding: 10px 14px;
    margin-bottom: 14px;
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-sm);
    line-height: var(--weavy-lh-sm);
}
.weavy-dropin-panel__loading {
    display: flex;
    align-items: center;
    gap: var(--weavy-space-bridge-10);
    margin-bottom: 14px;
    font-family: var(--weavy-font-family);
    font-size: var(--weavy-text-sm);
    line-height: var(--weavy-lh-sm);
    color: var(--weavy-muted);
}
/* Keyframe propre au composant : ne pas dependre du "spin" declare au coup par
   coup dans les feuilles de surface (il n'existe pas partout). */
.weavy-dropin-panel__spinner {
    width: 18px;
    height: 18px;
    border: 2px solid var(--weavy-border);
    border-top-color: var(--weavy-primary);
    border-radius: 50%;
    animation: weavy-dropin-spin 1s linear infinite;
    flex-shrink: 0;
}
@keyframes weavy-dropin-spin {
    to { transform: rotate(360deg); }
}
.weavy-dropin-mount {
    min-height: 60px;
}
