/**
 * Blaminhor Essentials — Pattern Library
 *
 * Pas de briques atomiques génériques (button, input, table, select, checkbox, radio, form, link) :
 * on hérite WordPress et on override uniquement ce qui porte l'identité visuelle BE (couleur primary).
 * Exception : .be-badge est un pattern BE (pastilles de statut inline).
 *
 * Patterns codifiés (20, audit Chrome MCP 2026-05-26 sur les 21 modules) :
 *   1. .be-module-page           — wrap page module (+ __header / __header-title / __tagline / __header-actions / __footer / __footer-stats / __footer-cta)
 *   2. .be-section               — regroupement titre + description + body (+ __head / __title / __description / __body)
 *   3. .be-tabs                  — onglets internes (+ __nav / __nav--pills, __tab.is-active, __tab-label / -dot / -count / -kbd, __panel.is-active)
 *   5. .be-notice                — alerte inline (--success / --warning / --danger + neutre par défaut)
 *   6. .be-module-card           — carte module sur le dashboard
 *   7. .be-toggle                — switch ON/OFF (alias .blaminhor-essentials-switch)
 *   8. .be-list                  — liste d'items (+ __item, __item-label, __item-meta)
 *   9. .be-empty-state           — état vide (icône + titre + description + actions)
 *  10. .be-tooltip               — panneau hover dark
 *  11. .be-modal-overlay / .be-modal — modal confirmation / formulaire (+ __header / __body / __footer / __close)
 *  12. .be-terminal              — sortie console read-only, lignes typées (--info / --success / --warning / --danger / --muted) + __cursor
 *  13. .be-stat-grid / .be-stat-card — cartes statistique (variants --primary / --success / --warning / --danger / --info)
 *  14. .be-badge                 — pastille de statut inline (variants --success / --warning / --danger / --info)
 *  15. .be-progress-bar          — barre de progression (+ __fill, __header, --mini)
 *  16. .be-data-view             — vue liste filtrable (toolbar + pills + search + table-wrap + row-title / -slug + chips)
 *  17. .be-import-sources / .be-import-source — source d'import (+ __layout / __info / __title / __actions / __options / __progress / __result)
 *  18. .be-sortable-table / .be-sortable — tableau triable (header avec icône)
 *  19. .be-unsaved-notice / .be-btn-pulse — guard de modifications non sauvées
 *  20. .be-divider + animations utilitaires (.be-anim-appear / -pulse / -spin)
 *
 * Utilitaires : .be-btn-icon (centrage), .be-table-wrap (wrap WP tables), .be-danger (modifier bouton destructive).
 *
 * Loaded AFTER _tokens.css, BEFORE admin.css / modules.css.
 */

/* ========================================================================
 * ACCESSIBILITÉ : ring de focus-visible cohérent sur tous les interactifs BE
 *
 * WCAG 2.1 SC 2.4.7 (Focus Visible) + SC 1.4.11 (Non-text Contrast 3:1).
 * Le ring de 3px en `--be-color-primary-soft` (variante 30% opacity du primary)
 * passe le contraste 3:1 sur tous les fonds clairs/sombres BE.
 * `:focus-visible` (pas `:focus`) pour ne pas afficher le ring au clic souris.
 * ====================================================================== */

.be-tabs__tab:focus-visible,
.be-notice__dismiss:focus-visible,
.be-module-card:focus-visible,
.be-list__item:focus-visible,
.be-toggle:focus-within,
.be-empty-state .button:focus-visible,
.be-modal__close:focus-visible,
.be-tooltip:focus-visible {
    outline: 2px solid var(--be-color-primary);
    outline-offset: 2px;
    box-shadow: 0 0 0 4px var(--be-color-primary-soft);
}


/* ========================================================================
 * GRAMMAIRE DES BOUTONS — règle unique, valable partout dans l'admin BE
 *
 * 4 types par hiérarchie sémantique :
 *
 *   PRIMARY     <button class="button button-primary">     Action principale
 *                                                          de la page (1/écran).
 *                                                          Indigo plein.
 *   SECONDARY   <button class="button">                    Action neutre.
 *                                                          Bordure gris foncé,
 *                                                          fond blanc, texte
 *                                                          foncé. Par défaut.
 *   DESTRUCTIVE <button class="button be-danger">          Action irréversible.
 *                                                          Bordure rouge → rouge
 *                                                          plein au hover.
 *   GHOST       <a class="button-link">…</a>               Lien stylé.
 *                                                          Texte indigo, pas
 *                                                          de bordure.
 *
 * RADIUS UNIQUE — --be-radius-md partout. Pas d'autre valeur.
 * INDIGO RESERVÉ — uniquement primary + onglet actif + liens textuels.
 *                  Les boutons secondaires sont gris, pas indigo.
 * ICÔNES — inline-flex automatique pour tout bouton contenant .dashicons
 *          ou <svg> (cf. règle "Centrage icônes" plus bas).
 * ====================================================================== */

/* --- PRIMARY : action principale (1 par écran) ---
 * Scope `:is(.wrap, .be-modal-overlay)` : les modales BE sont rendues hors
 * du .wrap (après render_page_end()) — sans ce scope étendu, les boutons
 * de modale retombent sur le style WP par défaut (bleu sur blanc, sans
 * border-radius BE). */
:is(.wrap, .be-modal-overlay) .button-primary,
:is(.wrap, .be-modal-overlay) .button.button-primary {
    background: var(--be-color-primary);
    border-color: var(--be-color-primary);
    color: var(--be-text-on-dark);
    box-shadow: var(--be-shadow-card);
    border-radius: var(--be-radius-button);
    transition: background-color var(--be-duration) var(--be-ease),
                border-color var(--be-duration) var(--be-ease);
}
:is(.wrap, .be-modal-overlay) .button-primary:hover,
:is(.wrap, .be-modal-overlay) .button-primary:focus,
:is(.wrap, .be-modal-overlay) .button.button-primary:hover,
:is(.wrap, .be-modal-overlay) .button.button-primary:focus {
    background: var(--be-color-primary-hover);
    border-color: var(--be-color-primary-hover);
    color: var(--be-text-on-dark);
    box-shadow: var(--be-shadow-card);
}
:is(.wrap, .be-modal-overlay) .button-primary:focus {
    box-shadow: 0 0 0 3px var(--be-color-primary-soft);
}

/* --- SECONDARY : action neutre (par défaut sur tout .button non-modifié) ---
 * Bordure gris foncé pour lisibilité (la bordure bleue WP native par défaut
 * se confond avec les liens et avec le primary). Le hover renforce le contraste
 * sans introduire d'indigo (réservé au primary). */
:is(.wrap, .be-modal-overlay) .button:not(.button-primary):not(.button-link):not(.be-danger) {
    background: var(--be-surface-card);
    border: 1px solid var(--be-color-gray-600);
    color: var(--be-text-default);
    border-radius: var(--be-radius-button);
    box-shadow: var(--be-shadow-card);
    transition: background-color var(--be-duration) var(--be-ease),
                border-color var(--be-duration) var(--be-ease),
                color var(--be-duration) var(--be-ease);
}
:is(.wrap, .be-modal-overlay) .button:not(.button-primary):not(.button-link):not(.be-danger):hover,
:is(.wrap, .be-modal-overlay) .button:not(.button-primary):not(.button-link):not(.be-danger):focus {
    background: var(--be-color-gray-50);
    border-color: var(--be-color-gray-900);
    color: var(--be-color-gray-900);
}
:is(.wrap, .be-modal-overlay) .button:not(.button-primary):not(.button-link):not(.be-danger):focus {
    box-shadow: 0 0 0 3px var(--be-color-primary-soft);
}

/* --- DESTRUCTIVE : actions irréversibles (Supprimer, Tout purger) ---
 * Outline rouge au repos, rempli au hover/focus. */
:is(.wrap, .be-modal-overlay) .button.be-danger {
    background: var(--be-surface-card);
    border-color: var(--be-color-danger);
    color: var(--be-color-danger);
    box-shadow: var(--be-shadow-card);
    border-radius: var(--be-radius-button);
    transition: background-color var(--be-duration) var(--be-ease),
                border-color var(--be-duration) var(--be-ease),
                color var(--be-duration) var(--be-ease);
}
:is(.wrap, .be-modal-overlay) .button.be-danger:hover,
:is(.wrap, .be-modal-overlay) .button.be-danger:focus {
    background: var(--be-color-danger);
    border-color: var(--be-color-danger);
    color: var(--be-text-on-dark);
}
:is(.wrap, .be-modal-overlay) .button.be-danger:focus {
    box-shadow: 0 0 0 3px var(--be-color-danger-soft);
}
:is(.wrap, .be-modal-overlay) .button.be-danger:disabled,
:is(.wrap, .be-modal-overlay) .button.be-danger[disabled] {
    background: var(--be-surface-card);
    border-color: var(--be-surface-border);
    color: var(--be-text-muted);
}

/* --- CENTRAGE ICÔNES dans les boutons ---
 * Règle globale : tout bouton contenant une .dashicons ou un <svg> devient
 * inline-flex pour éviter les bugs récurrents de désalignement vertical.
 * Le `gap` remplace le margin-right manuel sur l'icône. */
:is(.wrap, .be-modal-overlay) .button:has(.dashicons),
:is(.wrap, .be-modal-overlay) .button:has(svg),
.button.be-btn-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--be-space-1);
}

/* Tailles des icônes selon la taille du bouton */
:is(.wrap, .be-modal-overlay) .button .dashicons,
.button.be-btn-icon .dashicons {
    width: 16px;
    height: 16px;
    font-size: 16px;
    line-height: 1;
    margin: 0;
    vertical-align: baseline;
}
:is(.wrap, .be-modal-overlay) .button.button-hero .dashicons,
.button.be-btn-icon.button-hero .dashicons {
    width: 18px;
    height: 18px;
    font-size: 18px;
    line-height: 1;
}
:is(.wrap, .be-modal-overlay) .button.button-small .dashicons,
.button.be-btn-icon.button-small .dashicons {
    width: 14px;
    height: 14px;
    font-size: var(--be-font-size-lg);
    line-height: 1;
}


/* ========================================================================
 * INPUTS / TEXTAREAS / SELECTS — homogénéité visuelle dans le scope BE
 *
 * EXCEPTION GRAMMAIRE : les champs à remplir sont CARRÉS (border-radius: 0)
 * pour une meilleure lisibilité de la zone de saisie. Le reste du DS garde
 * --be-radius-md (8px). Bordure gris foncé partout pour cohérence avec les
 * boutons secondaires. Focus ring indigo soft (rappel du primary admin user).
 *
 * Scopé à .be-module-page et .be-dash-dashboard-wrap pour ne pas polluer le
 * reste de l'admin WP.
 * ====================================================================== */

.be-module-page input[type="text"],
.be-module-page input[type="email"],
.be-module-page input[type="url"],
.be-module-page input[type="number"],
.be-module-page input[type="password"],
.be-module-page input[type="search"],
.be-module-page input[type="tel"],
.be-module-page textarea,
.be-module-page select,
.be-dash-dashboard-wrap input[type="text"],
.be-dash-dashboard-wrap input[type="email"],
.be-dash-dashboard-wrap input[type="url"],
.be-dash-dashboard-wrap input[type="number"],
.be-dash-dashboard-wrap input[type="password"],
.be-dash-dashboard-wrap input[type="search"],
.be-dash-dashboard-wrap input[type="tel"],
.be-dash-dashboard-wrap textarea,
.be-dash-dashboard-wrap select {
    border: 1px solid var(--be-color-gray-600);
    border-radius: 0;
    background-color: var(--be-surface-card);
    color: var(--be-text-default);
    box-shadow: none;
    transition: border-color var(--be-duration) var(--be-ease),
                box-shadow var(--be-duration) var(--be-ease);
}
.be-module-page input[type="text"]:focus,
.be-module-page input[type="email"]:focus,
.be-module-page input[type="url"]:focus,
.be-module-page input[type="number"]:focus,
.be-module-page input[type="password"]:focus,
.be-module-page input[type="search"]:focus,
.be-module-page input[type="tel"]:focus,
.be-module-page textarea:focus,
.be-module-page select:focus,
.be-dash-dashboard-wrap input[type="text"]:focus,
.be-dash-dashboard-wrap input[type="email"]:focus,
.be-dash-dashboard-wrap input[type="url"]:focus,
.be-dash-dashboard-wrap input[type="number"]:focus,
.be-dash-dashboard-wrap input[type="password"]:focus,
.be-dash-dashboard-wrap input[type="search"]:focus,
.be-dash-dashboard-wrap input[type="tel"]:focus,
.be-dash-dashboard-wrap textarea:focus,
.be-dash-dashboard-wrap select:focus {
    border-color: var(--be-color-gray-900);
    box-shadow: 0 0 0 3px var(--be-color-primary-soft);
    outline: 0;
}


/* ========================================================================
 * TABLEAU — wrapper léger autour de .widefat à l'intérieur d'une .be-section
 *
 * Le tableau natif WP reste tel quel (carré, contenu brut). Le wrapper lui
 * donne un radius et une bordure douce pour le détacher du fond de la section
 * sans créer de double cadre. Usage : <div class="be-table-wrap"><table…>.
 * ====================================================================== */

.be-table-wrap {
    border: 1px solid var(--be-surface-border);
    border-radius: var(--be-radius-md);
    overflow: hidden;
    background: var(--be-surface-card);
}
.be-table-wrap .widefat {
    border: 0;
    margin: 0;
    box-shadow: none;
    border-radius: 0;
}
.be-table-wrap .widefat th,
.be-table-wrap .widefat td {
    border-color: var(--be-color-gray-200);
}


/* ========================================================================
 * wp-color-picker — le bouton `.wp-color-result` reçoit déjà --be-radius-md
 * via la règle générique `.button`, mais son span interne `.wp-color-result-text`
 * garde le radius natif WP de 2px côté droit. Son fond gris débordait alors
 * sur les coins arrondis du parent, mangeant visuellement la bordure aux
 * coins haut-droite / bas-droite. On aligne le radius interne (8px - 1px de
 * border = 7px) pour rester précis.
 * ====================================================================== */

:is(.wrap, .be-modal-overlay) .wp-picker-container .wp-color-result-text {
    border-top-right-radius: 7px;
    border-bottom-right-radius: 7px;
}


/* ========================================================================
 * 1. .be-module-page — structure d'une page de module
 * ====================================================================== */

.be-module-page {
    background: var(--be-surface-bg);
    margin: 0 0 0 -20px;
    padding: var(--be-space-4) var(--be-space-4) var(--be-space-5);
    min-height: calc(100vh - 32px);
    box-sizing: border-box;
}

/* Single inter-block rhythm — 16px — applied to every direct child of the
 * three layout wrappers that hold module content: the page itself, the tab
 * panels that swap inside it, and the body of any section (so heterogeneous
 * blocks like stat-grid + custom blocks + controls + notice don't collapse).
 * Modules never need to set margin-top manually; everything aligns via this
 * single rule.
 * `:where()` keeps the specificity at (0,0,1) so overrides stay trivial. */
:where(.be-module-page, .be-tabs__panel, .be-section__body) > * + * { margin-top: var(--be-space-3); }

/* WP core ships base margin-top rules on `.widefat`, `p.description`, `.tablenav`
 * with specificity (0,0,1). Those bat the :where(...) universal rule (0,0,0)
 * and stick the element to the previous sibling. Re-establish the 16px rhythm
 * with a (0,0,2) selector — more specific than WP, still trivial to override. */
.be-module-page > .widefat,      .be-tabs__panel > .widefat,      .be-section__body > .widefat,
.be-module-page > p.description, .be-tabs__panel > p.description, .be-section__body > p.description,
.be-module-page > .tablenav,     .be-tabs__panel > .tablenav,     .be-section__body > .tablenav {
    margin-top: var(--be-space-3);
}

/* Marker for WP admin_notices placement — keeps notices below the header */
.be-module-page .wp-header-end {
    visibility: hidden;
    margin: 0;
    height: 0;
    border: 0;
}

/* ========================================================================
 * 2. .be-module-page__header — titre + tagline + actions
 * ====================================================================== */

.be-module-page__header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--be-space-3);
}
.be-module-page__header-title {
    flex: 1;
    min-width: 0;
}
.be-module-page__header-title h1 {
    margin: 0 0 var(--be-space-1) 0;
    padding: 0;
    font-size: var(--be-font-size-xl);
    font-weight: var(--be-font-weight-semibold);
    color: var(--be-text-default);
    line-height: 1.3;
}
.be-module-page__tagline {
    margin: 0;
    color: var(--be-text-muted);
    font-size: var(--be-font-size-md);
}
.be-module-page__header-actions {
    display: flex;
    gap: var(--be-space-2);
    flex-shrink: 0;
}

/* Footer save bar — clone visuel du couple Cancel/Save du header, à la fin
 * de la page. Pas de fond/bordure : reste cohérent avec le header (juste les
 * boutons alignés à droite). Synchronisé avec le header par saveBar() qui
 * pilote tous les boutons partageant le même `form="<id>"`. Auto-émis par
 * render_page_end() quand la page a appelé render_header_save_actions(). */
.be-module-page__footer-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--be-space-2);
    margin-top: var(--be-space-3);
}

/* Non-primary header/footer buttons (Cancel, secondary actions) : style ghost
 * (fond carte, bord léger). Le bouton primary garde son indigo plein hérité
 * de WP — seul CTA habilité à porter l'accent du DS. */
.be-module-page__header-actions .button:not(.button-primary),
.be-module-page__footer-actions .button:not(.button-primary) {
    background: var(--be-surface-card);
    border: 1px solid var(--be-surface-border);
    color: var(--be-text-default);
    box-shadow: var(--be-shadow-card);
    border-radius: var(--be-radius-button);
    padding: 4px 12px;
    height: 32px;
    line-height: 22px;
    display: inline-flex;
    align-items: center;
    gap: var(--be-space-1);
    transition: background-color var(--be-duration) var(--be-ease),
                color var(--be-duration) var(--be-ease);
}
.be-module-page__header-actions .button:not(.button-primary):hover,
.be-module-page__footer-actions .button:not(.button-primary):hover {
    background: var(--be-color-gray-50);
    color: var(--be-color-primary);
}
.be-module-page__header-actions .button .dashicons,
.be-module-page__footer-actions .button .dashicons {
    width: 16px; height: 16px; font-size: 16px; line-height: 1;
}

/* Save (primary) : alignement vertical + ancrage du dot orange unsaved.
 * Fond/couleur restent hérités de .button-primary natif WP. */
.be-module-page__header-actions .button-primary,
.be-module-page__footer-actions .button-primary {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: var(--be-space-1);
    height: 32px;
    line-height: 22px;
    border-radius: var(--be-radius-button);
}

/* Mini-dot orange affordance — visible dès qu'un champ est modifié.
 * Toggle via attribut [hidden] depuis le contrôleur JS saveBar(). */
.be-module-page__header-actions__dot {
    position: absolute;
    top: -3px;
    right: -3px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--be-color-warning);
    border: 2px solid var(--be-surface-bg);
    pointer-events: none;
}
.be-module-page__header-actions__dot[hidden] { display: none; }

/* Override l'aspect "désaturé/illisible" du WP-disabled par défaut. */
.be-module-page__header-actions .button[disabled],
.be-module-page__footer-actions .button[disabled] {
    opacity: 0.55;
    cursor: not-allowed;
}


/* ========================================================================
 * 3. .be-module-page__footer — stats + CTA (bas de dashboard)
 * ====================================================================== */

.be-module-page__footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--be-space-3);
    flex-wrap: wrap;
    padding: var(--be-space-3);
    background: var(--be-surface-card);
    border: 1px solid var(--be-surface-border);
    border-radius: var(--be-radius-lg);
    box-shadow: var(--be-shadow-card);
}
.be-module-page__footer-stats {
    font-size: var(--be-font-size-sm);
    color: var(--be-text-muted);
}
.be-module-page__footer-stats strong {
    color: var(--be-text-default);
    font-weight: var(--be-font-weight-semibold);
}
.be-module-page__footer-cta {
    display: flex;
    align-items: center;
    gap: var(--be-space-2);
    flex-wrap: wrap;
}
.be-module-page__footer-cta-text {
    margin: 0;
    color: var(--be-text-muted);
    font-size: var(--be-font-size-sm);
}


/* ========================================================================
 * 4. .be-section — regroupement titre + intro + body
 * ====================================================================== */

.be-section {
    background: var(--be-surface-card);
    border: 1px solid var(--be-surface-border);
    border-radius: var(--be-radius-lg);
    box-shadow: var(--be-shadow-card);
    padding: var(--be-space-4);
}
.be-section__head {
    margin-bottom: var(--be-space-3);
}
.be-section__title {
    margin: 0 0 var(--be-space-1) 0;
    font-size: var(--be-font-size-lg);
    font-weight: var(--be-font-weight-semibold);
    color: var(--be-text-default);
}
.be-section__description {
    margin: 0;
    color: var(--be-text-muted);
    font-size: var(--be-font-size-md);
}
/* Collapsible variant: a .be-section rendered as <details>. The <summary> reuses
 * .be-section__title typography and gains a click affordance; content gets its
 * rhythm back only once expanded. */
details.be-section > summary {
    cursor: pointer;
}
details.be-section[open] > summary.be-section__title {
    margin-bottom: var(--be-space-3);
}
/* Breathing room when an intro paragraph sits directly above a data table. */
.be-section__description + .be-data-view__table-wrap {
    margin-top: var(--be-space-3);
}

/* Semantic dashicon tint — inline status cue (a leading icon) inside tables and
 * lists. Pairs distinct icon shapes with color so the meaning survives without
 * color (a11y). Token-driven, never hard-coded. */
.be-ico--success,
.be-ico--warning {
    vertical-align: text-bottom;
    margin-right: var(--be-space-1);
}
.be-ico--success { color: var(--be-color-success); }
.be-ico--warning { color: var(--be-color-warning); }


/* ========================================================================
 * 5. .be-tabs — onglets internes d'un module
 * ====================================================================== */

/* Nav d'onglets : pas de border-bottom global (look aéré). La séparation
 * visuelle vient uniquement du souligne épais sous l'onglet actif.
 * Espacement entre onglets : var(--be-space-4) (24px). */
.be-tabs__nav {
    display: flex;
    gap: var(--be-space-4);
    margin: 0 0 var(--be-space-3) 0;
    overflow-x: auto;
}
.be-tabs__tab {
    appearance: none;
    background: transparent;
    border: 0;
    border-bottom: 3px solid transparent;
    padding: var(--be-space-2) 0 var(--be-space-2) 0;
    color: var(--be-text-muted);
    font-size: var(--be-font-size-md);
    font-weight: var(--be-font-weight-medium);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: var(--be-space-1);
    text-decoration: none;
    white-space: nowrap;
    line-height: 1;
    transition: color var(--be-duration) var(--be-ease),
                border-color var(--be-duration) var(--be-ease);
}
.be-tabs__tab:hover { color: var(--be-text-default); }
/* Onglet actif : souligne épais 3px gris foncé + texte foncé + semibold.
 * L'indigo est réservé aux CTA primary. Le souligne épais + le poids du texte
 * portent à eux deux le signal "tu es sur cet onglet". */
.be-tabs__tab.is-active {
    color: var(--be-text-default);
    border-bottom-color: var(--be-color-gray-900);
    font-weight: var(--be-font-weight-semibold);
}
.be-tabs__tab .dashicons {
    width: 16px; height: 16px; font-size: 16px;
}
.be-tabs__panel { display: none; }
.be-tabs__panel.is-active { display: block; }


/* ========================================================================
 * 5a. .be-tabs__nav--pills — barre d'onglets segmentée (refonte v2 header).
 * Container unique blanc bordé, ombre carte. Onglets jointifs (gap=0)
 * séparés par une ligne verticale fine ; coins arrondis uniquement aux
 * extrémités (premier/dernier onglet). Onglet actif = fond gray-700 plein
 * + texte/icône blancs (gris foncé doux, palier entre gray-600 et gray-900 :
 * moins charcoal que gray-900 mais reste clairement foncé ; l'indigo
 * --be-color-primary reste réservé aux CTA cliquables comme .button-primary).
 * Affordances par onglet : icône Lucide à gauche, dot orange (unsaved),
 * badge kbd (Alt+N) à droite. Boutons Annuler/Enregistrer du formulaire
 * sont rendus côté header par render_header_save_actions().
 * ====================================================================== */
.be-tabs__nav--pills {
    display: inline-flex;
    gap: 0;
    margin: 0 0 var(--be-space-3) 0;
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    background: var(--be-surface-card);
    border: 1px solid var(--be-surface-border);
    border-radius: var(--be-radius-md);
    box-shadow: var(--be-shadow-card);
}
.be-tabs__nav--pills .be-tabs__tab {
    background: transparent;
    border: 0;
    border-right: 1px solid var(--be-surface-border);
    border-radius: 0;
    /* Hauteur alignée sur les boutons WP (.button = 32px) pour homogénéité visuelle :
     * padding-vertical = 4px, line-height = 22px, total = 32px. */
    height: 32px;
    padding: 4px var(--be-space-3);
    line-height: 22px;
    color: var(--be-text-default);
    display: inline-flex;
    align-items: center;
    transition: background-color var(--be-duration) var(--be-ease),
                color var(--be-duration) var(--be-ease),
                border-color var(--be-duration) var(--be-ease);
}
.be-tabs__nav--pills .be-tabs__tab:first-child {
    border-top-left-radius: calc(var(--be-radius-md) - 1px);
    border-bottom-left-radius: calc(var(--be-radius-md) - 1px);
}
.be-tabs__nav--pills .be-tabs__tab:last-child {
    border-right: 0;
    border-top-right-radius: calc(var(--be-radius-md) - 1px);
    border-bottom-right-radius: calc(var(--be-radius-md) - 1px);
}
.be-tabs__nav--pills .be-tabs__tab:hover {
    background: var(--be-color-gray-50);
    color: var(--be-text-default);
}
/* Focus ring : neutralise le ring WP core `a:focus` (common.css) qui s'applique
 * au click souris et se fait clipper haut/bas par l'`overflow-x: auto` du nav
 * (→ deux bandes verticales bleues visibles côtés gauche/droite). Notre ring
 * BE ne s'affiche qu'au focus clavier (:focus-visible), inset sur les 4 côtés
 * (jamais clippé par le conteneur). */
.be-tabs__nav--pills .be-tabs__tab:focus {
    outline: none;
    box-shadow: none;
}
.be-tabs__nav--pills .be-tabs__tab:focus-visible {
    outline: 0;
    box-shadow: inset 0 0 0 2px var(--be-color-primary);
}
.be-tabs__nav--pills .be-tabs__tab.is-active,
.be-tabs__nav--pills .be-tabs__tab.is-active:hover {
    background: var(--be-color-gray-700);
    color: #fff;
    border-right-color: var(--be-color-gray-700);
    /* Override de .be-tabs__tab.is-active (underline section 5). */
    border-bottom-color: transparent;
}
/* Onglet précédant immédiatement l'actif : on masque son séparateur droit
 * pour éviter un dédoublement visuel (border-right inactif + bord gauche
 * du fond gray-700 plein). Requiert :has() (Chrome 105+, Safari 15.4+, Firefox 121+). */
.be-tabs__nav--pills .be-tabs__tab:has(+ .be-tabs__tab.is-active) {
    border-right-color: transparent;
}
.be-tabs__nav--pills .be-tabs__tab svg {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    color: currentColor;
}

/* Affordances internes d'un .be-tabs__tab (label / dot unsaved / kbd shortcut).
 * Génériques — utilisables par tout pattern .be-tabs__nav, mais aujourd'hui
 * seul --pills les consomme. */
.be-tabs__tab-label { white-space: nowrap; }
.be-tabs__tab-dot {
    display: inline-block;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--be-color-warning);
    margin-left: var(--be-space-1);
    flex-shrink: 0;
}
/* Le `hidden` attribute doit toujours gagner sur notre `display: inline-block`. */
.be-tabs__tab-dot[hidden] { display: none; }

/* Badge raccourci clavier Alt+N (⌥N sur macOS via JS swap). Caché par défaut,
 * révélé via .is-shortcuts-visible (hold-Alt ou setting global). L'attribut
 * aria-keyshortcuts reste posé sur le tab, lu par les screen readers. */
.be-tabs__tab-kbd {
    display: none;
    align-items: center;
    margin-left: var(--be-space-1);
    padding: 1px 6px;
    background: var(--be-color-gray-50);
    border: 1px solid var(--be-color-gray-200);
    border-radius: var(--be-radius-sm);
    font-family: var(--be-font-mono);
    font-size: var(--be-font-size-xs);
    font-weight: var(--be-font-weight-medium);
    color: var(--be-text-muted);
    line-height: 1;
}
.be-tabs__nav--pills.is-shortcuts-visible .be-tabs__tab-kbd {
    display: inline-flex;
}
/* Onglets inactifs : badge plus discret (sans bord). */
.be-tabs__nav--pills .be-tabs__tab:not(.is-active) .be-tabs__tab-kbd {
    background: transparent;
    border-color: transparent;
}
/* Sur l'onglet actif (fond foncé), badge translucide blanc — texte blanc. */
.be-tabs__nav--pills .be-tabs__tab.is-active .be-tabs__tab-kbd {
    background: rgba(255, 255, 255, 0.18);
    border-color: transparent;
    color: #fff;
}


/* ========================================================================
 * 6. .be-notice — alerte inline BE
 * ====================================================================== */

/* Par défaut : notice NEUTRE — carte douce, même formule que .be-section
 * (bordure surface-border + ombre card). PAS d'accent gauche 3px : il est
 * réservé aux variantes status (success/warning/danger) où il porte la
 * sémantique de couleur. Une notice neutre est un bloc passif, le contraste
 * "bordure foncée" est l'identité des boutons (cliquables), pas des notices.
 * La variante "info" a été retirée (redondance avec --be-color-primary). */
.be-notice {
    display: flex;
    align-items: center;
    gap: var(--be-space-2);
    padding: var(--be-space-2) var(--be-space-3);
    border-radius: var(--be-radius-md);
    background: var(--be-surface-card);
    border: 1px solid var(--be-surface-border);
    box-shadow: var(--be-shadow-card);
    color: var(--be-text-default);
    font-size: var(--be-font-size-md);
}
/* Marge top fixe : une notice est toujours espacée du bloc précédent, sauf
 * si elle est le premier enfant de son container. Plus de cas-par-cas. */
.be-notice { margin-top: var(--be-space-3); }
.be-notice:first-child { margin-top: 0; }

.be-notice__icon {
    flex-shrink: 0;
    color: var(--be-text-muted);
    width: 20px;
    height: 20px;
    font-size: 20px;
    line-height: 1;
}
.be-notice__body { flex: 1; }
.be-notice__title {
    margin: 0 0 2px 0;
    font-size: var(--be-font-size-md);
    font-weight: var(--be-font-weight-semibold);
}
.be-notice__text { margin: 0; color: var(--be-text-muted); }

/* Espace sous une notice suivie de contenu (jamais de marge morte en fin de bloc) */
.be-notice:not(:last-child) { margin-bottom: var(--be-space-3); }
.be-notice__dismiss {
    flex-shrink: 0;
    width: 24px; height: 24px; padding: 0;
    border: 0; background: transparent;
    color: var(--be-text-muted);
    cursor: pointer;
    border-radius: var(--be-radius-sm);
    font-size: 16px;
    line-height: 1;
}
.be-notice__dismiss:hover { background: rgba(0,0,0,0.05); color: var(--be-text-default); }

/* Variantes status : ajoutent un accent gauche coloré 3px + un fond teinté.
 * L'accent gauche est ce qui porte la sémantique de couleur (vert/orange/rouge).
 * La base neutre n'a pas cet accent — il est exclusif aux statuts. */
.be-notice--success {
    border-left-width: 3px;
    border-left-color: var(--be-color-success);
    background: var(--be-color-success-soft);
}
.be-notice--success .be-notice__icon { color: var(--be-color-success); }
.be-notice--warning {
    border-left-width: 3px;
    border-left-color: var(--be-color-warning);
    background: var(--be-color-warning-soft);
}
.be-notice--warning .be-notice__icon { color: var(--be-color-warning); }
.be-notice--danger {
    border-left-width: 3px;
    border-left-color: var(--be-color-danger);
    background: var(--be-color-danger-soft);
}
.be-notice--danger .be-notice__icon { color: var(--be-color-danger); }
.be-notice--beta {
    border-left-width: 3px;
    border-left-color: var(--be-color-beta);
    background: var(--be-color-beta-soft);
}
.be-notice--beta .be-notice__icon  { color: var(--be-color-beta); }
.be-notice--beta .be-notice__title { color: var(--be-color-beta); }


/* ========================================================================
 * 7. .be-module-card — carte module sur le dashboard masonry
 * Patron concret : icône + nom + description + toggle + lien Settings
 * ====================================================================== */

.be-module-card {
    background: var(--be-surface-card);
    border: 1px solid var(--be-surface-border);
    border-radius: var(--be-radius-lg);
    box-shadow: var(--be-shadow-card);
    padding: var(--be-space-3);
    display: flex;
    align-items: center;
    gap: var(--be-space-2);
    transition: box-shadow var(--be-duration) var(--be-ease);
}
.be-module-card:hover { box-shadow: 0 4px 12px rgba(16,24,40,0.08); }
.be-module-card__icon {
    flex-shrink: 0;
    width: 32px; height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--be-color-gray-400);
}
.be-module-card__icon .dashicons {
    width: 20px; height: 20px; font-size: 20px;
}
.be-module-card__body {
    flex: 1;
    min-width: 0;
}
.be-module-card__name {
    margin: 0 0 2px 0;
    font-size: var(--be-font-size-md);
    font-weight: var(--be-font-weight-medium);
    color: var(--be-text-default);
}
.be-module-card__desc {
    margin: 0;
    font-size: var(--be-font-size-sm);
    color: var(--be-text-muted);
}
.be-module-card__toggle { flex-shrink: 0; }


/* ========================================================================
 * 8. .be-toggle — alias du .blaminhor-essentials-switch existant
 * (Le markup historique reste compatible.)
 * ====================================================================== */

.be-toggle {
    position: relative;
    display: inline-block;
    width: 36px;
    height: 20px;
    flex-shrink: 0;
}
.be-toggle input {
    opacity: 0;
    width: 0;
    height: 0;
}
.be-toggle__slider {
    position: absolute;
    inset: 0;
    background: var(--be-color-gray-400);
    border-radius: 20px;
    cursor: pointer;
    transition: background-color var(--be-duration) var(--be-ease);
}
.be-toggle__slider::before {
    content: "";
    position: absolute;
    top: 3px;
    left: 3px;
    width: 14px;
    height: 14px;
    background: #fff;
    border-radius: 50%;
    transition: transform var(--be-duration) var(--be-ease);
}
.be-toggle input:checked + .be-toggle__slider { background: var(--be-color-primary); }
.be-toggle input:checked + .be-toggle__slider::before { transform: translateX(16px); }
.be-toggle input:disabled + .be-toggle__slider { opacity: 0.5; cursor: not-allowed; }


/* ========================================================================
 * 9. .be-list — liste d'items (modules d'une catégorie, relais SMTP, etc.)
 * ====================================================================== */

.be-list {
    list-style: none;
    margin: 0;
    padding: 0;
}
.be-list__item {
    display: flex;
    align-items: center;
    gap: var(--be-space-2);
    padding: var(--be-space-2);
    border-radius: var(--be-radius-md);
    color: var(--be-text-default);
}
.be-list__item + .be-list__item { margin-top: 2px; }
.be-list__item:hover { background: var(--be-color-gray-50); }
.be-list__item-label { flex: 1; min-width: 0; }
.be-list__item-meta { color: var(--be-text-muted); font-size: var(--be-font-size-sm); }


/* ========================================================================
 * 10. .be-empty-state — état vide d'une page/section/liste
 * ====================================================================== */

.be-empty-state {
    text-align: center;
    padding: var(--be-space-5) var(--be-space-4);
    color: var(--be-text-default);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--be-space-2);
}
.be-empty-state__icon {
    width: 40px; height: 40px;
    color: var(--be-color-gray-400);
    font-size: 40px;
    line-height: 1;
    margin-bottom: var(--be-space-1);
}
.be-empty-state__title {
    margin: 0;
    font-size: var(--be-font-size-lg);
    font-weight: var(--be-font-weight-semibold);
    color: var(--be-text-default);
}
.be-empty-state__description {
    margin: 0;
    color: var(--be-text-muted);
    font-size: var(--be-font-size-md);
    max-width: 420px;
}
.be-empty-state__actions {
    display: flex;
    gap: var(--be-space-2);
    margin-top: var(--be-space-2);
}


/* ========================================================================
 * 11. .be-tooltip — panneau hover (utilisé sur les modules du dashboard)
 * ====================================================================== */

.be-tooltip {
    position: absolute;
    z-index: var(--be-z-tooltip);
    background: var(--be-color-gray-900);
    color: var(--be-text-on-dark);
    padding: var(--be-space-2) var(--be-space-3);
    border-radius: var(--be-radius-md);
    box-shadow: var(--be-shadow-overlay);
    font-size: var(--be-font-size-sm);
    line-height: 1.5;
    max-width: 280px;
    opacity: 0;
    transform: translateY(-4px);
    pointer-events: none;
    transition: opacity var(--be-duration) var(--be-ease),
                transform var(--be-duration) var(--be-ease);
}
.be-tooltip.is-open {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}
.be-tooltip__title {
    margin: 0 0 2px 0;
    font-size: var(--be-font-size-md);
    font-weight: var(--be-font-weight-semibold);
    color: var(--be-text-on-dark);
}
.be-tooltip__text { margin: 0; color: rgba(255,255,255,0.75); }


/* ========================================================================
 * 12. .be-modal — modal de confirmation / formulaire
 * ====================================================================== */

.be-modal-overlay {
    position: fixed;
    inset: 0;
    background: var(--be-surface-overlay);
    z-index: var(--be-z-modal);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--be-space-4);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--be-duration) var(--be-ease);
}
.be-modal-overlay.is-open { opacity: 1; pointer-events: auto; }
.be-modal {
    background: var(--be-surface-card);
    border-radius: var(--be-radius-md);
    box-shadow: var(--be-shadow-overlay);
    max-width: 560px;
    width: 100%;
    max-height: calc(100vh - 64px);
    display: flex;
    flex-direction: column;
    transform: translateY(8px);
    transition: transform var(--be-duration) var(--be-ease);
}
.be-modal-overlay.is-open .be-modal { transform: translateY(0); }
.be-modal__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--be-space-2);
    padding: var(--be-space-3) var(--be-space-4);
    border-bottom: 1px solid var(--be-surface-border);
}
.be-modal__title {
    margin: 0;
    font-size: var(--be-font-size-lg);
    font-weight: var(--be-font-weight-semibold);
    color: var(--be-text-default);
}
.be-modal__close {
    appearance: none;
    background: transparent;
    border: 0;
    width: 28px; height: 28px;
    border-radius: var(--be-radius-sm);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--be-text-muted);
    font-size: 18px;
    line-height: 1;
}
.be-modal__close:hover { background: var(--be-color-gray-50); color: var(--be-text-default); }
.be-modal__body {
    padding: var(--be-space-4);
    overflow-y: auto;
    color: var(--be-text-default);
    font-size: var(--be-font-size-md);
    line-height: 1.5;
}
.be-modal__footer {
    display: flex;
    justify-content: flex-end;
    gap: var(--be-space-2);
    padding: var(--be-space-3) var(--be-space-4);
    border-top: 1px solid var(--be-surface-border);
}


/* ========================================================================
 * 13. .be-terminal — sortie console read-only (logs, scans, output)
 * Vert sur fond noir, monospace. Signal visuel fort : "le plugin t'affiche
 * ce qu'il fait, ce n'est pas modifiable".
 *
 * Variantes de ligne :
 *   .be-terminal__line                — sortie standard (vert)
 *   .be-terminal__line--info          — info neutre (gris clair)
 *   .be-terminal__line--success       — succès (vert plus vif)
 *   .be-terminal__line--warning       — alerte (orange)
 *   .be-terminal__line--danger        — erreur (rouge)
 *   .be-terminal__line--muted         — info secondaire (gris foncé)
 *
 * Curseur clignotant : .be-terminal__cursor
 * Animation d'apparition : .be-terminal__line entre en fade+slide
 * ====================================================================== */

.be-terminal {
    --be-terminal-bg:       #0d1117;
    --be-terminal-line:     #c9d1d9;
    --be-terminal-prompt:   #7d8590;
    --be-terminal-success:  #56d364;
    --be-terminal-warning:  #d29922;
    --be-terminal-danger:   #f85149;
    --be-terminal-muted:    #6e7681;

    background: var(--be-terminal-bg);
    color: var(--be-terminal-line);
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    font-size: var(--be-font-size-sm);
    line-height: 1.6;
    padding: var(--be-space-3);
    border-radius: var(--be-radius-md);
    border: 1px solid #21262d;
    max-height: 320px;
    overflow-y: auto;
    overscroll-behavior: contain;
    box-shadow: inset 0 0 0 1px rgba(255,255,255,0.02);
    user-select: text;
}
/* Pretty scrollbar dans le terminal */
.be-terminal::-webkit-scrollbar              { width: 8px; height: 8px; }
.be-terminal::-webkit-scrollbar-track        { background: transparent; }
.be-terminal::-webkit-scrollbar-thumb        { background: #30363d; border-radius: 4px; }
.be-terminal::-webkit-scrollbar-thumb:hover  { background: #484f58; }

.be-terminal__line {
    white-space: pre-wrap;
    word-break: break-all;
    color: var(--be-terminal-line);   /* sortie neutre par défaut */
    animation: be-terminal-line-appear 220ms var(--be-ease) both;
}
.be-terminal__line + .be-terminal__line { margin-top: 2px; }
/* Indicateur de statut en début de ligne — largeur fixe pour aligner toutes
 * les lignes. Le `$` du prompt classique a été retiré (déroutant pour les
 * non-développeurs). Les analyses BE utilisent ce terminal pour afficher
 * leurs résultats : chaque ligne reflète son statut via ✓ / ⚠ / ✗ / · */
.be-terminal__line::before {
    content: "·";
    color: var(--be-terminal-muted);
    display: inline-block;
    width: 1.4em;
    text-align: center;
    margin-right: var(--be-space-1);
    user-select: none;
    font-weight: 600;
}
.be-terminal__line--no-prompt::before { content: none; }

.be-terminal__line--info    { color: var(--be-terminal-line); }
.be-terminal__line--success { color: var(--be-terminal-success); }
.be-terminal__line--warning { color: var(--be-terminal-warning); }
.be-terminal__line--danger  { color: var(--be-terminal-danger); }
.be-terminal__line--muted   { color: var(--be-terminal-muted); }

.be-terminal__line--success::before { content: "\2713"; color: var(--be-terminal-success); }
.be-terminal__line--warning::before { content: "\26A0"; color: var(--be-terminal-warning); }
.be-terminal__line--danger::before  { content: "\2717"; color: var(--be-terminal-danger); }
.be-terminal__line--info::before    { content: "\2192"; color: var(--be-terminal-line); }
.be-terminal__line--muted::before   { content: " "; }

/* Cursor clignotant en fin de bloc actif */
.be-terminal__cursor {
    display: inline-block;
    width: 8px;
    height: 1em;
    margin-left: 4px;
    background: var(--be-terminal-success);
    vertical-align: text-bottom;
    animation: be-terminal-cursor-blink 1s steps(1, end) infinite;
}

@keyframes be-terminal-line-appear {
    from { opacity: 0; transform: translateY(-2px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes be-terminal-cursor-blink {
    50% { opacity: 0; }
}


/* ========================================================================
 * 14. Animation utilities (réutilisables par les patterns)
 * ====================================================================== */

/* Apparition d'un élément (notice, card injectée, etc.) */
@keyframes be-fade-slide-in {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0); }
}
.be-anim-appear { animation: be-fade-slide-in var(--be-duration) var(--be-ease) both; }

/* Pulse léger (highlight d'un élément qui vient d'être modifié) */
@keyframes be-pulse-highlight {
    0%   { box-shadow: 0 0 0 0 var(--be-color-primary-soft); }
    70%  { box-shadow: 0 0 0 6px transparent; }
    100% { box-shadow: 0 0 0 0 transparent; }
}
.be-anim-pulse { animation: be-pulse-highlight 1.2s var(--be-ease) both; }

/* Spinner (pour boutons WP qui ont besoin de feedback de chargement).
 * `display: inline-block` + `transform-origin: center` indispensables pour
 * que les .dashicons (inline par défaut) tournent autour de leur centre
 * géométrique au lieu de leur ligne de base — sinon la loupe « danse » à côté
 * du texte au lieu de tourner sur place. */
@keyframes be-spin {
    to { transform: rotate(360deg); }
}
.be-anim-spin {
    display: inline-block;
    transform-origin: center center;
    animation: be-spin 0.8s linear infinite;
}

/* Notice qui apparaît : auto-animée */
.be-notice { animation: be-fade-slide-in var(--be-duration) var(--be-ease) both; }


/* ========================================================================
 * 15. .be-stat-card — carte de statistique (icône + valeur + label)
 * Posée en grille .be-stat-grid en tête de page de module : compteurs, état.
 * Variante de statut = couleur de la pastille d'icône uniquement.
 * ====================================================================== */

.be-stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--be-space-3);
}

.be-stat-card {
    display: flex;
    align-items: center;
    gap: var(--be-space-3);
    padding: var(--be-space-3);
    background: var(--be-surface-card);
    border: 1px solid var(--be-surface-border);
    border-radius: var(--be-radius-lg);
    box-shadow: var(--be-shadow-card);
}
.be-stat-card__icon {
    flex-shrink: 0;
    width: 48px;
    height: 48px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--be-radius-md);
    background: var(--be-color-gray-50);
    color: var(--be-color-gray-400);
}
.be-stat-card__icon .dashicons {
    width: 24px;
    height: 24px;
    font-size: 24px;
    line-height: 1;
}
.be-stat-card__body { min-width: 0; }
.be-stat-card__value {
    margin: 0;
    font-size: var(--be-font-size-xl);
    font-weight: var(--be-font-weight-semibold);
    color: var(--be-text-default);
    line-height: 1.1;
}
.be-stat-card__label {
    margin: var(--be-space-1) 0 0;
    font-size: var(--be-font-size-md);
    color: var(--be-text-muted);
}

.be-stat-card--primary .be-stat-card__icon { background: var(--be-color-primary-soft); color: var(--be-color-primary); }
.be-stat-card--success .be-stat-card__icon { background: var(--be-color-success-soft); color: var(--be-color-success); }
.be-stat-card--warning .be-stat-card__icon { background: var(--be-color-warning-soft); color: var(--be-color-warning); }
.be-stat-card--danger  .be-stat-card__icon { background: var(--be-color-danger-soft);  color: var(--be-color-danger); }
.be-stat-card--info    .be-stat-card__icon { background: var(--be-color-info-soft);    color: var(--be-color-info); }


/* ========================================================================
 * 16. .be-divider — séparateur horizontal intra-section
 * <hr class="be-divider"> entre deux groupes d'options d'une même section.
 * ====================================================================== */

.be-divider {
    height: 0;
    margin: var(--be-space-3) 0;
    border: 0;
    border-top: 1px solid var(--be-surface-border);
}


/* ========================================================================
 * 17. .be-import-source — carte d'import depuis un autre plugin WP
 * Consommé par redirections (import depuis Redirection / Yoast Redirect /
 * Simple 301), seo-manager (Yoast / Rank Math / AIOSEO), smtp (WP Mail SMTP /
 * Easy WP SMTP / FluentSMTP). Structure :
 *
 *   <div class="be-import-sources">                          (grille)
 *     <div class="be-import-source">                         (item)
 *       <div class="be-import-source__layout">               (flex info / actions)
 *         <div class="be-import-source__info">…</div>
 *         <div class="be-import-source__actions">…</div>
 *       </div>
 *       <div class="be-import-source__options">…</div>       (checkboxes)
 *       <div class="be-import-source__progress" hidden>…</div>
 *       <div class="be-import-source__result" hidden>…</div>
 *     </div>
 *   </div>
 * ====================================================================== */

.be-import-sources {
    display: flex;
    flex-direction: column;
    gap: var(--be-space-3);
    margin-bottom: var(--be-space-3);
}
.be-import-source {
    background: var(--be-surface-card);
    border: 1px solid var(--be-surface-border);
    border-radius: var(--be-radius-md);
    padding: var(--be-space-3);
}
.be-import-source__layout {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: var(--be-space-3);
}
.be-import-source__info { flex: 1; min-width: 0; }
.be-import-source__title {
    margin: 0 0 var(--be-space-1);
    font-size: var(--be-font-size-lg);
    font-weight: var(--be-font-weight-semibold);
    color: var(--be-text-default);
}
.be-import-source__actions { flex-shrink: 0; text-align: right; }
.be-import-source__options {
    margin-top: var(--be-space-3);
    padding-top: var(--be-space-3);
    border-top: 1px solid var(--be-surface-border);
}
.be-import-source__status {
    margin: var(--be-space-2) 0 0;
    font-size: var(--be-font-size-sm);
    color: var(--be-text-muted);
}
.be-import-source__progress { margin-top: var(--be-space-3); }
.be-import-source__result   { margin-top: var(--be-space-3); }


/* ========================================================================
 * 18. .be-progress-bar — barre de progression linéaire
 * Container .be-progress-bar + fill animé .be-progress-bar__fill (width
 * piloté par JS). Variant --mini pour les progress inline (8px de haut,
 * utilisé dans .be-import-source). Header optionnel __header au-dessus
 * (label + ratio X/Y).
 *
 *   <div class="be-progress-bar__header"><span>Pages</span><span>42/100</span></div>
 *   <div class="be-progress-bar">
 *     <div class="be-progress-bar__fill" id="..."></div>
 *   </div>
 *
 *   <div class="be-progress-bar be-progress-bar--mini">
 *     <div class="be-progress-bar__fill"></div>
 *   </div>
 * ====================================================================== */

.be-progress-bar {
    height: var(--be-space-4);
    background: var(--be-color-gray-200);
    border-radius: var(--be-radius-lg);
    overflow: hidden;
}
.be-progress-bar__fill {
    height: 100%;
    width: 0;
    background: linear-gradient(90deg, var(--be-color-primary) 0%, var(--be-color-primary-hover) 100%);
    border-radius: inherit;
    transition: width var(--be-duration) var(--be-ease);
}
.be-progress-bar__header {
    display: flex;
    justify-content: space-between;
    margin-bottom: var(--be-space-2);
    font-weight: var(--be-font-weight-medium);
}

.be-progress-bar--mini {
    height: var(--be-space-2);
    border-radius: var(--be-radius-sm);
}
.be-progress-bar--mini .be-progress-bar__fill {
    background: var(--be-color-primary);
}


/* ========================================================================
 * 19. .be-sortable-table — tri client-side d'une <table class="widefat">
 * Modifier sur la table (.be-sortable-table) + sur chaque <th> cliquable
 * (.be-sortable) + icône dashicon (.be-sortable__icon). État porté par
 * .is-asc / .is-desc sur le <th> (le JS toggle ces classes au clic).
 * Consommé par cache, db-optimizer, smtp, broken-links, backup.
 *
 *   <table class="widefat striped be-sortable-table">
 *     <thead><tr>
 *       <th class="be-sortable" data-sort="string">Nom <span class="be-sortable__icon"></span></th>
 *       <th class="be-sortable is-desc" data-sort="number">Date <span class="be-sortable__icon"></span></th>
 *     </tr></thead>
 *     <tbody>…</tbody>
 *   </table>
 * ====================================================================== */

.be-sortable-table th.be-sortable {
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
}
.be-sortable-table th.be-sortable:hover {
    background: var(--be-color-gray-50);
}
.be-sortable-table th.be-sortable .be-sortable__icon {
    display: inline-block;
    width: 16px;
    height: 16px;
    vertical-align: text-bottom;
    margin-left: var(--be-space-1);
    opacity: 0.3;
}
.be-sortable-table th.be-sortable .be-sortable__icon::before {
    content: "\f156";
    font-family: dashicons;
    font-size: 16px;
}
.be-sortable-table th.be-sortable.is-asc  .be-sortable__icon,
.be-sortable-table th.be-sortable.is-desc .be-sortable__icon {
    opacity: 1;
}
.be-sortable-table th.be-sortable.is-asc  .be-sortable__icon::before { content: "\f142"; }
.be-sortable-table th.be-sortable.is-desc .be-sortable__icon::before { content: "\f140"; }


/* ========================================================================
 * 20. .be-badge — pastille d'annotation accolée à un label
 * Inline-block, font-size sm, radius-sm, margin-left:8px. Variants statuts
 * via .be-badge--success / --warning / --danger / --info / --beta. Consommé par
 * image-sizes (Custom = info, Disabled = danger), user-role-editor
 * (custom-caps count = info) et le tableau de bord (--beta sur les modules
 * récents, drapeau 'beta' du registre — réutilisable pour toute brique neuve).
 *
 *   <span class="be-badge be-badge--info">Custom</span>
 *   <span class="be-badge be-badge--danger">Disabled</span>
 * ====================================================================== */

.be-badge {
    display: inline-block;
    padding: 2px var(--be-space-1);
    font-size: var(--be-font-size-xs);
    font-weight: var(--be-font-weight-medium);
    border-radius: var(--be-radius-sm);
    margin-left: var(--be-space-2);
    vertical-align: middle;
    background: var(--be-color-gray-50);
    color: var(--be-text-muted);
}
.be-badge--success { background: var(--be-color-success-soft); color: var(--be-color-success); }
.be-badge--warning { background: var(--be-color-warning-soft); color: var(--be-color-warning); }
.be-badge--danger  { background: var(--be-color-danger-soft);  color: var(--be-color-danger); }
.be-badge--info    { background: var(--be-color-info-soft);    color: var(--be-color-info); }
.be-badge--beta    { background: var(--be-color-beta-soft);    color: var(--be-color-beta); }


/* ========================================================================
 * 21. Form-guard — .be-unsaved-notice + .be-btn-pulse
 * Couple visuel utilisé par le mixin JS BlaminhorEssentials.unsavedGuard()
 * pour signaler que le formulaire diffère de son état initial : la notice
 * apparaît à gauche du bouton "Save" (fade-in) ET le bouton lui-même pulse.
 * Consommé par classic-editor, mute-core-emails.
 * ====================================================================== */

.be-unsaved-notice {
    display: inline-block;
    margin-right: var(--be-space-2);
    padding: var(--be-space-1) var(--be-space-2);
    background: var(--be-color-danger-soft);
    border: 1px solid var(--be-color-danger);
    border-radius: var(--be-radius-sm);
    color: var(--be-color-danger);
    font-size: var(--be-font-size-md);
    font-weight: var(--be-font-weight-medium);
    animation: be-fade-in var(--be-duration) var(--be-ease);
}
.be-btn-pulse {
    animation: be-pulse 2s infinite;
}

@keyframes be-fade-in {
    from { opacity: 0; transform: translateY(-5px); }
    to   { opacity: 1; transform: translateY(0); }
}
@keyframes be-pulse {
    0%, 100% { box-shadow: 0 0 0 0   var(--be-color-primary-soft); }
    50%      { box-shadow: 0 0 0 8px transparent; }
}


/* ========================================================================
 * 22. .be-data-view — pattern « tableau-card » avec stats, filtres et recherche
 *
 * Wrapper générique pour les vues qui combinent : (1) une grille de stats en
 * tête, (2) une toolbar avec pills de filtre mutex + recherche + select de
 * portée, (3) un tableau WordPress natif (.wp-list-table widefat striped),
 * (4) un tablenav natif (bulk + pagination). Réutilisé par seo-manager
 * (Content Overview) ; à migrer vers broken-links / redirections /
 * user-role-editor / cookies dans une release ultérieure.
 *
 * Réutilise sans dupliquer : .be-stat-grid + .be-stat-card (section 15)
 * pour les stats ; .be-badge + variants (section 20) pour la cellule État
 * et les chips de mots-clés ; .wp-list-table WP natif pour le tableau.
 *
 *   <div class="be-data-view">
 *     <div class="be-stat-grid">                                  (réutilisé)
 *       <div class="be-stat-card be-stat-card--success">…</div>
 *       …
 *     </div>
 *     <div class="be-data-view__toolbar">
 *       <div class="be-data-view__pills" role="tablist">
 *         <button class="be-data-view__pill is-active" data-filter="all">
 *           Tout <span class="be-data-view__pill-count">7</span>
 *         </button>
 *         <button class="be-data-view__pill" data-filter="optimized">
 *           <span class="be-data-view__pill-dot be-data-view__pill-dot--success"></span>
 *           Optimisées <span class="be-data-view__pill-count">3</span>
 *         </button>
 *         …
 *       </div>
 *       <div class="be-data-view__controls">
 *         <div class="be-data-view__search">
 *           <span class="dashicons dashicons-search"></span>
 *           <input type="search" placeholder="Rechercher…">
 *         </div>
 *         <select class="be-data-view__type-select">…</select>
 *       </div>
 *     </div>
 *     <div class="be-data-view__table-wrap">
 *       <table class="wp-list-table widefat striped">…</table>
 *     </div>
 *     <div class="tablenav bottom">…</div>                        (WP natif)
 *   </div>
 *
 * Aucune nouvelle couleur, aucun !important : tous les fonds, bordures et
 * couleurs viennent de tokens --be-* existants.
 * ====================================================================== */

.be-data-view {
    display: flex;
    flex-direction: column;
    gap: var(--be-space-4);
}

/* Toolbar : pills (gauche) + controls (droite) — wrap responsive */
.be-data-view__toolbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--be-space-3);
}

.be-data-view__pills {
    display: inline-flex;
    flex-wrap: wrap;
    gap: var(--be-space-1);
}

.be-data-view__pill {
    display: inline-flex;
    align-items: center;
    gap: var(--be-space-1);
    padding: var(--be-space-1) var(--be-space-3);
    background: var(--be-surface-card);
    border: 1px solid var(--be-surface-border);
    border-radius: 999px;
    color: var(--be-text-default);
    font-size: var(--be-font-size-md);
    font-weight: var(--be-font-weight-medium);
    cursor: pointer;
    transition: background var(--be-duration) var(--be-ease),
                color var(--be-duration) var(--be-ease),
                border-color var(--be-duration) var(--be-ease);
    line-height: 1.6;
}
.be-data-view__pill:hover {
    background: var(--be-color-gray-50);
    border-color: var(--be-surface-border-strong);
}
.be-data-view__pill.is-active {
    background: var(--be-text-default);
    border-color: var(--be-text-default);
    color: var(--be-text-on-dark);
}
.be-data-view__pill.is-active:hover {
    background: var(--be-color-gray-900);
    border-color: var(--be-color-gray-900);
}

/* Dot coloré devant le label (variants reprennent les statuts) */
.be-data-view__pill-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--be-color-gray-400);
}
.be-data-view__pill-dot--success { background: var(--be-color-success); }
.be-data-view__pill-dot--warning { background: var(--be-color-warning); }
.be-data-view__pill-dot--danger  { background: var(--be-color-danger); }
.be-data-view__pill-dot--info    { background: var(--be-color-info); }

/* Compteur inline dans le pill */
.be-data-view__pill-count {
    display: inline-block;
    min-width: 18px;
    padding: 0 var(--be-space-1);
    background: var(--be-color-gray-200);
    color: var(--be-text-muted);
    border-radius: 999px;
    font-size: var(--be-font-size-xs);
    font-weight: var(--be-font-weight-semibold);
    text-align: center;
    line-height: 1.6;
}
.be-data-view__pill.is-active .be-data-view__pill-count {
    background: rgba(255, 255, 255, 0.18);
    color: var(--be-text-on-dark);
}

/* Bloc droite : search + select */
.be-data-view__controls {
    display: inline-flex;
    align-items: center;
    gap: var(--be-space-2);
    flex-wrap: wrap;
}

/* Champ de recherche avec icône — n'override pas le style WP de l'input,
 * juste le padding pour laisser la place à la dashicons. */
.be-data-view__search {
    position: relative;
    display: inline-flex;
    align-items: center;
}
.be-data-view__search .dashicons {
    position: absolute;
    left: var(--be-space-2);
    top: 50%;
    transform: translateY(-50%);
    color: var(--be-color-gray-400);
    pointer-events: none;
    font-size: 18px;
    width: 18px;
    height: 18px;
    line-height: 1;
}
.be-data-view__search input[type="search"] {
    padding-left: calc(var(--be-space-2) + 18px + var(--be-space-1));
    min-width: 240px;
}

/* Wrap autour de la table : fond carte cohérent avec les cards stats */
.be-data-view__table-wrap {
    background: var(--be-surface-card);
    border: 1px solid var(--be-surface-border);
    border-radius: var(--be-radius-md);
    box-shadow: var(--be-shadow-card);
    overflow: hidden;
}
.be-data-view__table-wrap .wp-list-table {
    border: 0;
    margin: 0;
    box-shadow: none;
}
.be-data-view__table-wrap .wp-list-table thead th,
.be-data-view__table-wrap .wp-list-table tfoot th {
    background: var(--be-color-gray-50);
    font-weight: var(--be-font-weight-semibold);
}

/* Placeholder italique gris pour les cellules vides ou héritées
 * (« Hérité du titre », « Auto — contenu non textuel »). */
.be-data-view__placeholder {
    color: var(--be-text-muted);
    font-style: italic;
}

/* Slug en mono sous le titre de la ligne. */
.be-data-view__row-title {
    display: block;
    font-weight: var(--be-font-weight-semibold);
    color: var(--be-color-primary);
    text-decoration: none;
}
.be-data-view__row-title:hover { text-decoration: underline; }
.be-data-view__row-slug {
    display: block;
    margin-top: 2px;
    font-family: var(--be-font-mono);
    font-size: var(--be-font-size-xs);
    color: var(--be-text-muted);
}

/* Liste de chips pour les cellules multi-valeurs (mots-clés cibles).
 * Réutilise .be-badge (section 20) pour chaque tag — pas de nouvelle classe
 * atomique. .be-data-view__chips est juste un container flex+wrap. */
.be-data-view__chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--be-space-1);
}

/* État de cellule vide : tiret centré gris. */
.be-data-view__dash {
    color: var(--be-color-gray-400);
}

