Facebook Cleaner - Block Group Invites & Spam

Powerful Tampermonkey script to automatically hide Facebook group invitations, spam, and unwanted posts. Customizable, robust, and privacy-friendly.

// ==UserScript==
// @name         Facebook Cleaner - Block Group Invites & Spam
// @namespace    https://github.com/cadot-eu/facebook-cleaner
// @version      2.0
// @description  Powerful Tampermonkey script to automatically hide Facebook group invitations, spam, and unwanted posts. Customizable, robust, and privacy-friendly. 
// @author       FCB Cleaner Project
// @match        https://www.facebook.com/*
// @match        https://facebook.com/*
// @grant        none
// @run-at       document-end

// @homepageURL  https://github.com/cadot-eu/facebook-cleaner
// @supportURL   https://github.com/cadot-eu/facebook-cleaner/issues
// @icon         https://raw.githubusercontent.com/cadot-eu/facebook-cleaner/main/icon.png
//
// ==/UserScript==

/*
*  FCB Cleaner (Facebook Content Blocker)
*  - Instantly blocks Facebook group invites, spam, and unwanted posts.
*  - Customizable: add your own phrases or group/page names to block.
*  - Robust: adapts to Facebook layout changes, cleans up all post fragments.
*  - Privacy-friendly: runs only in your browser, stores nothing online.
*
*  ➡️  To install or update, use the official GreasyFork page:
*  https://greasyfork.org/fr/scripts/545074-facebook-cleaner-block-group-invites-spam
*
*  (Or for manual install: https://github.com/cadot-eu/facebook-cleaner/raw/main/fcb.js)
*
*  📦  GitHub & Documentation:
*  https://github.com/cadot-eu/facebook-cleaner
*/

(function () {
    'use strict';

    // Liste des phrases à bloquer (plus large et flexible)
    let phrasesABloquer = [
        "vous invite",
        "vous a invité",
        "vous a invité.e",
        "invite à rejoindre",
        "a rejoint le groupe",
        "invited you to join",
        "rejoindre ce groupe",
        "rejoindre le groupe",
        "join this group",
        "has joined the group",
        "healthy body"
    ];

    // Récupérer les phrases personnalisées du localStorage
    try {
        const phrasesStockees = localStorage.getItem('fcb-phrases-personnalisees');
        if (phrasesStockees) {
            const phrasesPersonnalisees = JSON.parse(phrasesStockees);
            phrasesABloquer = phrasesABloquer.concat(phrasesPersonnalisees);
        }
    } catch (e) {
        // Erreur silencieuse
    }

    // Fonction pour sauvegarder les phrases personnalisées
    function sauvegarderPhrases() {
        try {
            const phrasesPersonnalisees = phrasesABloquer.slice(11); // Garder seulement les phrases ajoutées (healthy body inclus dans les 11 par défaut)
            localStorage.setItem('fcb-phrases-personnalisees', JSON.stringify(phrasesPersonnalisees));
        } catch (e) {
            // Erreur silencieuse
        }
    }

    let postsTraites = new Set();
    let elementsMarques = new WeakSet(); // Pour éviter de retraiter les mêmes éléments
    let textesBloquesCache = new Set(); // Cache des textes déjà identifiés comme à bloquer

    // État d'activation du script
    let scriptActif = localStorage.getItem('fcb-script-actif') !== 'false'; // Actif par défaut

    // Options du script avec localStorage - chargement robuste
    let options = {
        masquerColonneDroite: false,
        masquerReels: false,
        masquerSuggestions: false,
    };

    // Charger les options de manière robuste
    function chargerOptions() {
        try {
            // Charger chaque option individuellement avec valeur par défaut
            const colonneDroite = localStorage.getItem('fcb-option-colonne-droite');
            const reels = localStorage.getItem('fcb-option-masquer-reels');
            const suggestions = localStorage.getItem('fcb-option-masquer-suggestions');

            options.masquerColonneDroite = colonneDroite === 'true';
            options.masquerReels = reels === 'true';
            options.masquerSuggestions = suggestions === 'true';

        } catch (e) {
            // Garder les valeurs par défaut
        }
    }

    // Charger immédiatement les options
    chargerOptions();

    // Fonction pour sauvegarder les options
    function sauvegarderOptions() {
        localStorage.setItem('fcb-option-colonne-droite', options.masquerColonneDroite);
        localStorage.setItem('fcb-option-masquer-reels', options.masquerReels);
        localStorage.setItem('fcb-option-masquer-suggestions', options.masquerSuggestions);
    }

    // Fonction pour appliquer les modifications CSS selon les options
    function appliquerOptionsCSS() {
        // Supprimer les styles précédents
        const ancienStyle = document.getElementById('fcb-options-styles');
        if (ancienStyle) ancienStyle.remove();

        // Créer un nouveau style
        const style = document.createElement('style');
        style.id = 'fcb-options-styles';
        let css = '';

        if (options.masquerColonneDroite) {
            css += `
                    /* Masquer la colonne de droite */
                    div[role="complementary"] {
                        display: none !important;
                    }
                    
                    /* Agrandir la zone principale pour occuper l'espace libéré */
                    div[role="main"] {
                        max-width: none !important;
                        width: calc(100% - 360px) !important;
                        margin-left: 360px !important;
                        margin-right: 0 !important;
                    }
                    
                    /* Agrandir le conteneur du feed */
                    div[role="feed"] {
                        max-width: none !important;
                        width: 100% !important;
                        padding-right: 20px !important;
                    }
                    
                    /* Ajuster les posts pour qu'ils utilisent toute la largeur disponible */
                    div[role="feed"] > div {
                        max-width: none !important;
                        width: 100% !important;
                    }
                `;
        }

        // CSS pour les boutons de suppression de posts
        css += `
                .fcb-delete-btn {
                    position: absolute !important;
                    top: 10px !important;
                    right: 50px !important;
                    background: rgba(255, 0, 0, 0.8) !important;
                    color: white !important;
                    border: none !important;
                    border-radius: 50% !important;
                    width: 24px !important;
                    height: 24px !important;
                    font-size: 14px !important;
                    cursor: pointer !important;
                    z-index: 1000 !important;
                    display: flex !important;
                    align-items: center !important;
                    justify-content: center !important;
                    font-weight: bold !important;
                }
                .fcb-delete-btn:hover {
                    background: rgba(255, 0, 0, 1) !important;
                    transform: scale(1.1) !important;
                }
                
                /* Assurer que les posts ont position relative pour les boutons absolus */
                div[role="article"],
                div[data-pagelet^="FeedUnit"],
                .x1yztbdb.x1n2onr6.xh8yej3.x1ja2u2z {
                    position: relative !important;
                }
            `;

        style.textContent = css;
        document.head.appendChild(style);
    }

    function masquerReels() {
        if (!options.masquerReels) return;

        // Sélecteurs pour trouver les éléments contenant "Reels"
        const selecteursReels = [
            'span',
            'h3',
            '[aria-label*="Reels"]',
            '[aria-label*="Bobines"]'
        ];

        // Fonction pour vérifier si un élément contient "Reels"
        function contientReels(element) {
            const texte = element.textContent || element.innerText || '';
            return texte.toLowerCase().includes('reels') ||
                (element.getAttribute && element.getAttribute('aria-label') &&
                    element.getAttribute('aria-label').toLowerCase().includes('reels'));
        }

        // Chercher tous les éléments qui contiennent "Reels"
        const tousLesElements = document.querySelectorAll('span, h3, div[aria-label], div[role="button"]');

        tousLesElements.forEach(element => {
            if (contientReels(element)) {
                // Remonter dans la hiérarchie pour trouver le conteneur principal
                let conteneur = element;
                let niveaux = 0;
                const maxNiveaux = 6;

                // Remonter jusqu'à trouver un conteneur approprié
                while (conteneur && niveaux < maxNiveaux) {
                    // Vérifier si c'est un conteneur de section (avec une taille raisonnable)
                    if (conteneur.offsetHeight > 100 && conteneur.offsetWidth > 200 &&
                        conteneur.children.length >= 2) {

                        // Masquer cet élément
                        conteneur.style.setProperty('display', 'none', 'important');
                        conteneur.style.setProperty('visibility', 'hidden', 'important');
                        conteneur.style.setProperty('height', '0px', 'important');
                        conteneur.style.setProperty('overflow', 'hidden', 'important');
                        conteneur.style.setProperty('opacity', '0', 'important');
                        conteneur.style.setProperty('max-height', '0px', 'important');
                        conteneur.setAttribute('data-reels-hidden', 'true');

                        break;
                    }

                    conteneur = conteneur.parentElement;
                    niveaux++;
                }
            }
        });
    }

    function masquerSuggestions() {
        if (!options.masquerSuggestions) return;

        // Utiliser plusieurs approches pour une détection robuste

        // APPROCHE 1: Utiliser la même logique de détection que pour les posts normaux
        const selecteursPosts = [
            'div[role="article"]',
            'div[data-pagelet^="FeedUnit"]',
            '.x1yztbdb.x1n2onr6.xh8yej3.x1ja2u2z',
            'div.x1n2onr6.xh8yej3',
            // Nouveaux sélecteurs plus larges
            'div[style*="flex-direction"]:has(.x1vqgdyp)',
            'div:has(h3):has(img)',
            'section > div > div'
        ];

        // APPROCHE 2: Recherche par texte dans tout le DOM
        const phrasesSuggestions = [
            'personnes que vous pourriez connaître',
            'people you may know',
            'vous connaissez peut-être',
            'you might know',
            'suggested for you',
            'suggéré pour vous',
            'amis suggérés',
            'suggested friends',
            'personnes que vous connaissez peut-être',
            'people you might know'
        ];

        // Scanner tous les éléments texte pour détecter les suggestions
        const tousLesElements = document.querySelectorAll('div, section, article, h3, span');

        tousLesElements.forEach(element => {
            if (element.hasAttribute('data-fcb-suggestions-processed')) return;

            const texte = element.textContent || element.innerText || '';
            const texteNormalise = texte.toLowerCase()
                .normalize('NFD')
                .replace(/[\u0300-\u036f]/g, '')
                .replace(/\s+/g, ' ')
                .trim();

            // Vérifier si c'est une suggestion
            const estSuggestion = phrasesSuggestions.some(phrase =>
                texteNormalise.includes(phrase.toLowerCase())
            );

            if (estSuggestion) {
                // Remonter pour trouver le conteneur principal du post
                let conteneur = element;
                let niveaux = 0;
                const maxNiveaux = 10;

                while (conteneur && niveaux < maxNiveaux) {
                    // Critères pour identifier un conteneur de suggestions
                    const estConteneurSuggestions = (
                        conteneur.offsetHeight > 100 &&
                        conteneur.offsetHeight < 2000 &&
                        conteneur.offsetWidth > 200 &&
                        conteneur.children.length >= 2 &&
                        !conteneur.hasAttribute('data-fcb-suggestions-processed')
                    );

                    if (estConteneurSuggestions) {
                        // Marquer comme traité
                        conteneur.setAttribute('data-fcb-suggestions-processed', 'true');

                        // Masquer complètement le conteneur
                        conteneur.style.setProperty('display', 'none', 'important');
                        conteneur.style.setProperty('visibility', 'hidden', 'important');
                        conteneur.style.setProperty('height', '0px', 'important');
                        conteneur.style.setProperty('overflow', 'hidden', 'important');
                        conteneur.style.setProperty('opacity', '0', 'important');
                        conteneur.style.setProperty('max-height', '0px', 'important');
                        conteneur.setAttribute('data-fcb-hidden', 'suggestions');

                        break;
                    }

                    conteneur = conteneur.parentElement;
                    niveaux++;
                }

                // Marquer l'élément initial comme traité même si on n'a pas trouvé de conteneur
                element.setAttribute('data-fcb-suggestions-processed', 'true');
            }
        });

        // APPROCHE 3: Scanner les posts normaux qui pourraient contenir des suggestions
        selecteursPosts.forEach(selecteur => {
            try {
                const posts = document.querySelectorAll(selecteur);

                posts.forEach(post => {
                    if (post.hasAttribute('data-fcb-suggestions-processed')) return;

                    const textePost = post.textContent || post.innerText || '';
                    const texteNormalise = textePost.toLowerCase()
                        .normalize('NFD')
                        .replace(/[\u0300-\u036f]/g, '')
                        .replace(/\s+/g, ' ')
                        .trim();

                    // Vérifier si c'est une suggestion
                    const estSuggestion = phrasesSuggestions.some(phrase =>
                        texteNormalise.includes(phrase.toLowerCase())
                    );

                    if (estSuggestion) {
                        // Marquer comme traité
                        post.setAttribute('data-fcb-suggestions-processed', 'true');

                        // Masquer complètement le post
                        post.style.setProperty('display', 'none', 'important');
                        post.style.setProperty('visibility', 'hidden', 'important');
                        post.style.setProperty('height', '0px', 'important');
                        post.style.setProperty('overflow', 'hidden', 'important');
                        post.style.setProperty('opacity', '0', 'important');
                        post.style.setProperty('max-height', '0px', 'important');
                        post.setAttribute('data-fcb-hidden', 'suggestions');
                    }
                });
            } catch (e) {
                // Erreur silencieuse
            }
        });
    }

    // Fonction pour ajouter des boutons de suppression sur les posts
    function ajouterBoutonsSuppressionPosts() {
        const selecteursPosts = [
            'div[role="article"]',
            'div[data-pagelet^="FeedUnit"]',
            '.x1yztbdb.x1n2onr6.xh8yej3.x1ja2u2z'
        ];

        selecteursPosts.forEach(selecteur => {
            const posts = document.querySelectorAll(selecteur);

            posts.forEach(post => {
                // Vérifier si le bouton n'existe pas déjà
                if (post.querySelector('.fcb-delete-btn')) return;

                // Trouver le titre du post pour créer le bouton
                const titreSelectors = [
                    'h3',
                    '[role="heading"]',
                    '.x1heor9g',
                    '.x1qlqyl8',
                    'span[dir="ltr"]:first-child'
                ];

                let titreElement = null;
                for (const selector of titreSelectors) {
                    titreElement = post.querySelector(selector);
                    if (titreElement && titreElement.textContent.trim().length > 5) {
                        break;
                    }
                }

                if (titreElement) {
                    let titre = titreElement.textContent.trim();
                    // Échapper les caractères spéciaux
                    titre = titre.replace(/['"\\]/g, ' ').trim();
                    if (titre.length > 5) { // Seulement si le titre a du contenu
                        // Créer le bouton de suppression
                        const boutonSupprimer = document.createElement('button');
                        boutonSupprimer.className = 'fcb-delete-btn';
                        boutonSupprimer.innerHTML = '×';
                        boutonSupprimer.title = `Ajouter "${titre}" aux phrases bloquées`;

                        boutonSupprimer.addEventListener('click', (e) => {
                            e.preventDefault();
                            e.stopPropagation();

                            // Ajouter le titre aux phrases bloquées
                            if (!phrasesABloquer.includes(titre)) {
                                phrasesABloquer.push(titre);
                                sauvegarderPhrases();

                                // Masquer immédiatement le post
                                post.style.display = 'none';

                                // Notification
                                alert(`Phrase "${titre}" ajoutée aux blocages !`);

                                // Relancer le scan pour masquer d'autres posts similaires
                                setTimeout(scannerPosts, 100);
                            }
                        });

                        // Ajouter le bouton au post
                        post.style.position = 'relative';
                        post.appendChild(boutonSupprimer);
                    }
                }
            });
        });
    }

    function contientPhraseBloquee(texte) {
        const texteNormalise = texte.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
        return phrasesABloquer.some(phrase =>
            texteNormalise.includes(phrase.toLowerCase())
        );
    }

    function ajouterBoutonAuPost(element) {
        // Éviter d'ajouter plusieurs boutons au même post
        if (element.querySelector('.fcb-add-title-btn')) return;

        // Ne pas ajouter de bouton aux posts déjà masqués
        if (element.hasAttribute('data-blocked-by-script') ||
            element.style.display === 'none' ||
            element.style.visibility === 'hidden') return;

        // Chercher le conteneur de titre pour le placement
        const conteneurTitre = element.querySelector('div[data-ad-rendering-role="profile_name"], h4, .x1heor9g');
        if (!conteneurTitre) return;

        // Extraire le titre/nom du groupe ou de la page dans ce post spécifique
        const titre = extraireTitrePost(element);
        if (!titre || phrasesABloquer.includes(titre)) return;

        // Créer le bouton d'ajout
        const boutonAjouter = document.createElement('button');
        boutonAjouter.className = 'fcb-add-title-btn';
        boutonAjouter.innerHTML = '×';
        boutonAjouter.title = `Bloquer: "${titre}"`;
        boutonAjouter.style.cssText = `
                background: rgba(220, 38, 38, 0.9);
                color: white;
                border: none;
                padding: 2px 6px;
                border-radius: 3px;
                cursor: pointer;
                font-size: 12px;
                font-weight: bold;
                opacity: 0.8;
                transition: all 0.2s;
                z-index: 10;
                margin-left: 8px;
                vertical-align: middle;
                display: inline-flex;
                align-items: center;
                justify-content: center;
                min-width: 18px;
                height: 18px;
            `;

        boutonAjouter.onmouseover = () => {
            boutonAjouter.style.opacity = '1';
            boutonAjouter.style.transform = 'scale(1.1)';
            boutonAjouter.style.background = 'rgba(220, 38, 38, 1)';
        };
        boutonAjouter.onmouseout = () => {
            boutonAjouter.style.opacity = '0.8';
            boutonAjouter.style.transform = 'scale(1)';
            boutonAjouter.style.background = 'rgba(220, 38, 38, 0.9)';
        };

        boutonAjouter.onclick = function (e) {
            e.preventDefault();
            e.stopPropagation();

            // Interface simple avec prompt pour test
            const titreFinal = prompt(
                `Titre détecté :\n"${titre}"\n\nVous pouvez le modifier avant de l'ajouter aux phrases bloquées :\n(Cliquez Annuler pour ne rien faire)`,
                titre
            );

            // Si l'utilisateur a annulé
            if (titreFinal === null) {
                return;
            }

            // Si le champ est vide
            if (!titreFinal.trim()) {
                alert('Le titre ne peut pas être vide');
                return;
            }

            const titreClean = titreFinal.trim();

            // Vérifier si déjà dans la liste
            if (phrasesABloquer.includes(titreClean)) {
                alert(`"${titreClean}" est déjà dans la liste des phrases bloquées !`);
                return;
            }

            // Ajouter à la liste
            phrasesABloquer.push(titreClean);
            sauvegarderPhrases();

            // Feedback visuel
            boutonAjouter.innerHTML = '✅';
            boutonAjouter.style.background = 'rgba(16, 185, 129, 1)';
            boutonAjouter.title = `Ajouté : "${titreClean}"`;

            // Message de confirmation
            alert(`"${titreClean}" a été ajouté aux phrases bloquées !`);

            // Supprimer le bouton et re-scanner
            setTimeout(() => {
                boutonAjouter.remove();
                setTimeout(scannerPosts, 100);
            }, 1000);
        };

        // Trouver l'élément de titre et ajouter le bouton juste après
        const elementTitre = conteneurTitre.querySelector('strong, b, a[role="link"]');
        if (elementTitre && elementTitre.parentNode) {
            // Insérer le bouton directement après l'élément de titre
            elementTitre.parentNode.insertBefore(boutonAjouter, elementTitre.nextSibling);
        } else {
            // Fallback : ajouter à la fin du conteneur de titre
            conteneurTitre.appendChild(boutonAjouter);
        }
    }

    function extraireTitrePost(postElement) {
        // Sélecteurs spécifiques pour extraire seulement le nom/titre
        const selecteurs = [
            // Sélecteur principal pour le nom d'auteur basé sur votre exemple
            'div[data-ad-rendering-role="profile_name"] strong',
            'div[data-ad-rendering-role="profile_name"] b',
            'div[data-ad-rendering-role="profile_name"] a strong',
            'div[data-ad-rendering-role="profile_name"] a b',
            'h4 span span span a strong',
            'h4 span span span a b',
            // Fallbacks
            'h4 a[role="link"] strong',
            'h4 a[role="link"] b',
            'span[class*="x1vvkbs"] a[role="link"] strong',
            'span[class*="x1vvkbs"] a[role="link"] b',
            'h4 span a[role="link"]',
            'strong a[role="link"]'
        ];

        for (const selecteur of selecteurs) {
            const elements = postElement.querySelectorAll(selecteur);
            for (const element of elements) {
                let texte = element.textContent || element.innerText || '';
                texte = texte.trim();

                // Nettoyer AVANT la validation - ordre important !
                texte = texte.replace(/\s*·.*$/g, ''); // Supprimer tout après le premier ·
                texte = texte.replace(/\s*Compte vérifié\s*/gi, ''); // Supprimer "Compte vérifié"
                texte = texte.replace(/\s*Verified\s*/gi, ''); // Supprimer "Verified"
                texte = texte.replace(/\s*Suivre\s*$/gi, ''); // Supprimer "Suivre" à la fin
                texte = texte.replace(/\s*Follow\s*$/gi, ''); // Supprimer "Follow" à la fin
                texte = texte.replace(/\s*\.\s*Suivre\s*$/gi, ''); // Supprimer ". Suivre"
                texte = texte.replace(/\s*\.\s*Follow\s*$/gi, ''); // Supprimer ". Follow"
                // Supprimer les badges de vérification avec différentes variantes
                texte = texte.replace(/Compte vérifié/gi, '');
                texte = texte.replace(/Verified/gi, '');
                // Nettoyer les espaces multiples
                texte = texte.replace(/\s+/g, ' ').trim();

                // Valider que c'est un titre valide après nettoyage
                if (texte &&
                    texte.length > 2 &&
                    texte.length < 80 &&
                    !texte.includes('ago') &&
                    !texte.includes('il y a') &&
                    !texte.includes('min') &&
                    !texte.includes('h ') &&
                    !texte.includes('Suivre') &&
                    !texte.includes('Follow') &&
                    !texte.includes('Compte vérifié') &&
                    !texte.includes('Verified') &&
                    !texte.match(/^\d+$/) &&
                    !texte.match(/^[.,:;!?·]+$/)) {

                    // Double nettoyage pour s'assurer que tout est propre
                    texte = texte.replace(/Compte vérifié/gi, '');
                    texte = texte.replace(/Verified/gi, '');
                    texte = texte.replace(/\s+/g, ' ').trim();

                    // Échapper les caractères spéciaux qui pourraient causer des erreurs JS
                    texte = texte.replace(/['"\\]/g, ' ').replace(/\s+/g, ' ').trim();

                    if (texte.length > 2) {
                        return texte;
                    }
                }
            }
        }

        return null;
    }

    function masquerPost(element) {
        if (!element || elementsMarques.has(element)) return false;
        // Sécurité : ne jamais masquer <body> ou <html>
        if (element === document.body || element === document.documentElement) {
            return false;
        }
        // Marquage permanent
        element.setAttribute('data-blocked-by-script', 'true');
        element.classList.add('script-blocked-post');
        elementsMarques.add(element);

        // Styles de masquage multiples pour résistance
        element.style.setProperty('display', 'none', 'important');
        element.style.setProperty('visibility', 'hidden', 'important');
        element.style.setProperty('height', '0px', 'important');
        element.style.setProperty('overflow', 'hidden', 'important');
        element.style.setProperty('opacity', '0', 'important');
        element.style.setProperty('max-height', '0px', 'important');

        // Observer si l'élément est modifié pour le re-masquer
        const elementObserver = new MutationObserver(function () {
            if (element.style.display !== 'none') {
                element.style.setProperty('display', 'none', 'important');
                element.style.setProperty('visibility', 'hidden', 'important');
            }
        });

        elementObserver.observe(element, {
            attributes: true,
            attributeFilter: ['style', 'class']
        });

        return true;
    }

    function trouverPostParent(element) {
        // APPROCHE SIMPLIFIÉE : avec les menus actions, on a déjà de bons conteneurs
        // Cette fonction ne fait plus que des vérifications de sécurité basiques

        // Sécurités de base
        if (!element || element === document.body || element === document.documentElement) {
            return null;
        }

        // Si l'élément a déjà une taille raisonnable, on le garde
        if (element.offsetHeight > 80 && element.offsetHeight < 800 &&
            element.offsetWidth > 300 && element.children.length <= 20) {
            return element;
        }

        // Sinon, remonter juste un niveau pour améliorer
        const parent = element.parentElement;
        if (parent && parent !== document.body && parent !== document.documentElement &&
            parent.offsetHeight > element.offsetHeight &&
            parent.offsetHeight < 1000 &&
            parent.offsetWidth < window.innerWidth * 0.8) {

            return parent;
        }

        return element; // Retourner l'élément original si pas d'amélioration
    }

    function scannerPosts() {
        // Vérifier si le script est actif
        if (!scriptActif) {
            return;
        }

        // D'abord, re-masquer tous les posts déjà identifiés comme bloqués
        document.querySelectorAll('[data-blocked-by-script="true"]').forEach(element => {
            if (element.style.display !== 'none') {
                element.style.setProperty('display', 'none', 'important');
                element.style.setProperty('visibility', 'hidden', 'important');
            }
        });

        // NOUVELLE APPROCHE : Utiliser les menus "trois points" comme indicateurs de posts
        const tousLesElements = new Set();

        // 1. Chercher tous les boutons de menu "Actions pour cette publication"
        const menusActions = document.querySelectorAll('div[aria-label*="Actions pour cette publication"], div[aria-label*="Actions for this post"], div[role="button"][aria-haspopup="menu"]:not([data-blocked-by-script="true"])');

        menusActions.forEach(menu => {
            // Remonter dans la hiérarchie pour trouver le conteneur du post
            let conteneurPost = menu;
            let niveaux = 0;
            const maxNiveaux = 8; // Chercher jusqu'à 8 niveaux

            while (conteneurPost && niveaux < maxNiveaux) {
                // Critères pour identifier un conteneur de post valide
                const estConteneurPost = (
                    conteneurPost.offsetHeight > 100 && // Au moins 100px de haut
                    conteneurPost.offsetHeight < 1200 && // Pas plus de 1200px
                    conteneurPost.offsetWidth > 300 && // Au moins 300px de large
                    conteneurPost.textContent.length > 50 && // Contenu substantiel
                    conteneurPost.children.length >= 2 && // Au moins 2 enfants
                    conteneurPost.children.length <= 30 // Pas plus de 30 enfants
                );

                if (estConteneurPost) {
                    const texte = conteneurPost.textContent || '';
                    if (contientPhraseBloquee(texte)) {
                        tousLesElements.add(conteneurPost);
                        break; // Sortir de la boucle une fois qu'on a trouvé le bon conteneur
                    }
                }

                conteneurPost = conteneurPost.parentElement;
                niveaux++;
            }
        });

        // 2. Méthode de fallback : Scanner les sélecteurs classiques
        const selecteursFallback = [
            'div[role="article"]:not([data-blocked-by-script="true"])',
            'div[data-testid]:not([data-blocked-by-script="true"])',
            'div[data-pagelet*="FeedUnit"]:not([data-blocked-by-script="true"])'
        ];

        selecteursFallback.forEach(selecteur => {
            try {
                const elements = document.querySelectorAll(selecteur);

                elements.forEach(el => {
                    if (el.offsetHeight > 50 && el.offsetHeight < 1000 &&
                        el.offsetWidth > 200 && el.textContent.length > 20) {

                        // Ajouter le bouton d'ajout même pour les posts non bloqués
                        ajouterBoutonAuPost(el);

                        const texte = el.textContent || '';
                        if (contientPhraseBloquee(texte)) {
                            tousLesElements.add(el);
                        }
                    }
                });
            } catch (e) {
                // Erreur silencieuse
            }
        });

        // Traiter chaque élément trouvé
        let postsMasques = 0;
        tousLesElements.forEach(element => {
            // Éviter les éléments déjà traités
            if (elementsMarques.has(element)) return;

            // Ajouter le bouton d'ajout à ce post (avant de vérifier s'il doit être masqué)
            ajouterBoutonAuPost(element);

            const texte = element.textContent || element.innerText || '';

            if (texte && contientPhraseBloquee(texte)) {
                const texteSignature = texte.substring(0, 100);

                // Masquer directement l'élément trouvé (déjà optimisé via les menus)
                if (masquerPost(element)) {
                    postsMasques++;
                    postsTraites.add(texteSignature);
                } else {
                    // Échec du masquage
                }
            }
        });

        // Masquer les Reels si l'option est activée
        masquerReels();

        // Masquer les suggestions si l'option est activée
        masquerSuggestions();

        // Ajouter les boutons de suppression sur tous les posts
        ajouterBoutonsSuppressionPosts();
    }

    function nettoyerElementsOrphelins() {
        // NETTOYAGE TRÈS LIMITÉ - seulement les "En voir plus" évidents
        const elementsEnVoirPlus = document.querySelectorAll('div[role="button"]:not([data-blocked-by-script="true"])');
        elementsEnVoirPlus.forEach(element => {
            const texte = element.textContent || '';
            if ((texte.trim() === 'En voir plus' || texte.trim() === 'See more') && texte.length < 20) {
                // Vérifier si cet élément appartient à un post qui devrait être bloqué
                let parent = element.parentElement;
                let niveaux = 0;

                while (parent && niveaux < 3) { // Seulement 3 niveaux max
                    const texteParent = parent.textContent || '';
                    if (texteParent && contientPhraseBloquee(texteParent) &&
                        parent.getAttribute('role') === 'article') { // DOIT être un article
                        masquerPost(element);
                        break;
                    }
                    parent = parent.parentElement;
                    niveaux++;
                }
            }
        });
    }

    // Observer très réactif pour les changements
    const observer = new MutationObserver(function (mutations) {
        let nouveauxPosts = false;

        mutations.forEach(function (mutation) {
            if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                mutation.addedNodes.forEach(node => {
                    if (node.nodeType === Node.ELEMENT_NODE &&
                        (node.textContent.length > 10 || node.querySelector('div'))) {
                        nouveauxPosts = true;
                    }
                });
            }
        });

        if (nouveauxPosts) {
            // Vérifier si le script est actif avant de scanner
            if (!scriptActif) return;

            // Scanner immédiatement et plusieurs fois
            setTimeout(scannerPosts, 10);
            setTimeout(scannerPosts, 100);
            setTimeout(scannerPosts, 500);
            // Ajouter le nettoyage des orphelins
            setTimeout(nettoyerElementsOrphelins, 200);
            setTimeout(nettoyerElementsOrphelins, 600);
            // Masquer les Reels
            setTimeout(masquerReels, 150);
            setTimeout(masquerReels, 400);
            // Masquer les suggestions
            setTimeout(masquerSuggestions, 200);
            setTimeout(masquerSuggestions, 500);
        }
    });

    function initialiser() {
        // Vérifier si le script est actif
        if (!scriptActif) {
            return;
        }

        // Scanner initial multiple
        setTimeout(scannerPosts, 100);
        setTimeout(scannerPosts, 500);
        setTimeout(scannerPosts, 1000);
        setTimeout(scannerPosts, 2000);
        setTimeout(scannerPosts, 5000);

        // Masquage initial des Reels
        setTimeout(masquerReels, 200);
        setTimeout(masquerReels, 800);
        setTimeout(masquerReels, 2000);

        // Masquage initial des suggestions
        setTimeout(masquerSuggestions, 300);
        setTimeout(masquerSuggestions, 900);
        setTimeout(masquerSuggestions, 2200);

        // Ajouter les boutons de suppression initiaux
        setTimeout(ajouterBoutonsSuppressionPosts, 400);
        setTimeout(ajouterBoutonsSuppressionPosts, 1000);
        setTimeout(ajouterBoutonsSuppressionPosts, 2500);

        // Nettoyage des orphelins
        setTimeout(nettoyerElementsOrphelins, 300);
        setTimeout(nettoyerElementsOrphelins, 1200);
        setTimeout(nettoyerElementsOrphelins, 3000);

        // Observer les changements
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });

        // Scanner très fréquent au début puis moins
        let scanCount = 0;
        const intervalId = setInterval(() => {
            if (!scriptActif) {
                clearInterval(intervalId);
                return;
            }
            scannerPosts();
            setTimeout(nettoyerElementsOrphelins, 100);
            setTimeout(masquerReels, 100);
            setTimeout(masquerSuggestions, 100);
            setTimeout(ajouterBoutonsSuppressionPosts, 150);
            scanCount++;
            if (scanCount > 20) {
                clearInterval(intervalId);
                // Passer à un scanner moins fréquent
                setInterval(() => {
                    if (scriptActif) {
                        scannerPosts();
                        setTimeout(nettoyerElementsOrphelins, 100);
                        setTimeout(masquerReels, 100);
                        setTimeout(masquerSuggestions, 100);
                        setTimeout(ajouterBoutonsSuppressionPosts, 150);
                    }
                }, 5000);
            }
        }, 1000);

        // Scanner au scroll plus réactif
        let scrollTimeout;
        let lastScrollTop = 0;
        window.addEventListener('scroll', function () {
            if (!scriptActif) return;

            const currentScrollTop = window.pageYOffset || document.documentElement.scrollTop;
            if (Math.abs(currentScrollTop - lastScrollTop) > 100) {
                clearTimeout(scrollTimeout);
                scrollTimeout = setTimeout(() => {
                    scannerPosts();
                    setTimeout(masquerReels, 50);
                    setTimeout(masquerSuggestions, 50);
                    lastScrollTop = currentScrollTop;
                }, 100);
            }
        });
    }

    // Interface utilisateur améliorée
    function creerInterface() {
        const container = document.createElement('div');
        container.style.cssText = `
                position: fixed;
                bottom: 10px;
                left: 10px;
                z-index: 10000;
                background: rgba(0,0,0,0.8);
                color: white;
                padding: 8px;
                border-radius: 8px;
                font-family: Arial, sans-serif;
                font-size: 12px;
                display: flex;
                gap: 5px;
                align-items: center;
            `;

        const boutonOnOff = document.createElement('button');
        boutonOnOff.innerHTML = scriptActif ? '🟢' : '🔴';
        boutonOnOff.title = scriptActif ? 'Filtres activés - Cliquer pour désactiver' : 'Filtres désactivés - Cliquer pour activer';
        boutonOnOff.style.cssText = `
                background: ${scriptActif ? '#10b981' : '#ef4444'};
                color: white;
                border: none;
                padding: 8px;
                border-radius: 4px;
                cursor: pointer;
                font-size: 14px;
                transition: all 0.3s ease;
                box-shadow: 0 2px 4px rgba(0,0,0,0.2);
            `;

        const boutonAjouter = document.createElement('button');
        boutonAjouter.innerHTML = '➕';
        boutonAjouter.title = 'Ajouter une phrase à bloquer';
        boutonAjouter.style.cssText = `
                background: #1877f2;
                color: white;
                border: none;
                padding: 8px;
                border-radius: 4px;
                cursor: pointer;
                font-size: 14px;
            `;



        const boutonVoir = document.createElement('button');
        boutonVoir.innerHTML = '👁️';
        boutonVoir.title = 'Voir et gérer les phrases bloquées';
        boutonVoir.style.cssText = `
                background: #8b5cf6;
                color: white;
                border: none;
                padding: 8px;
                border-radius: 4px;
                cursor: pointer;
                font-size: 14px;
            `;

        const boutonOptions = document.createElement('button');
        boutonOptions.innerHTML = '⚙️';
        boutonOptions.title = 'Options et paramètres';
        boutonOptions.style.cssText = `
                background: #6366f1;
                color: white;
                border: none;
                padding: 8px;
                border-radius: 4px;
                cursor: pointer;
                font-size: 14px;
            `;

        const compteur = document.createElement('div');
        compteur.innerHTML = postsTraites.size;
        compteur.title = 'Nombre de posts bloqués';
        compteur.style.cssText = `
                background: #dc2626;
                color: white;
                padding: 4px 8px;
                border-radius: 10px;
                font-size: 11px;
                font-weight: bold;
                min-width: 16px;
                text-align: center;
            `;

        boutonOnOff.onclick = function () {
            // Basculer l'état
            scriptActif = !scriptActif;

            // Sauvegarder dans localStorage
            localStorage.setItem('fcb-script-actif', scriptActif.toString());

            // Feedback visuel immédiat
            boutonOnOff.innerHTML = scriptActif ? '🟢' : '🔴';
            boutonOnOff.title = scriptActif ? 'Filtres activés - Cliquer pour désactiver' : 'Filtres désactivés - Cliquer pour activer';
            boutonOnOff.style.background = scriptActif ? '#10b981' : '#ef4444';

            // Animation de feedback
            boutonOnOff.style.transform = 'scale(0.9)';
            setTimeout(() => {
                boutonOnOff.style.transform = 'scale(1)';
            }, 150);

            // Message utilisateur
            const message = scriptActif ? 'Filtres ACTIVÉS 🟢' : 'Filtres DÉSACTIVÉS 🔴';

            // Petite notification visuelle
            const notification = document.createElement('div');
            notification.textContent = message;
            notification.style.cssText = `
                    position: fixed;
                    top: 50%;
                    left: 50%;
                    transform: translate(-50%, -50%);
                    background: ${scriptActif ? '#10b981' : '#ef4444'};
                    color: white;
                    padding: 15px 30px;
                    border-radius: 10px;
                    font-size: 16px;
                    font-weight: bold;
                    z-index: 99999;
                    box-shadow: 0 4px 12px rgba(0,0,0,0.3);
                    animation: fadeInOut 2s ease-in-out;
                `;

            // Ajouter l'animation CSS
            const style = document.createElement('style');
            style.textContent = `
                    @keyframes fadeInOut {
                        0% { opacity: 0; transform: translate(-50%, -50%) scale(0.8); }
                        20% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
                        80% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
                        100% { opacity: 0; transform: translate(-50%, -50%) scale(0.8); }
                    }
                `;
            document.head.appendChild(style);
            document.body.appendChild(notification);

            // Supprimer la notification après l'animation
            setTimeout(() => {
                if (notification.parentNode) {
                    notification.parentNode.removeChild(notification);
                }
                if (style.parentNode) {
                    style.parentNode.removeChild(style);
                }
            }, 2000);

            // Rafraîchir la page après un court délai
            setTimeout(() => {
                window.location.reload();
            }, 1000);
        };

        boutonAjouter.onclick = function () {
            const nouvellePh = prompt('Ajouter une phrase à bloquer:', '');
            if (nouvellePh && nouvellePh.trim()) {
                const phrase = nouvellePh.trim();

                if (!phrasesABloquer.includes(phrase)) {
                    phrasesABloquer.push(phrase);
                    sauvegarderPhrases();
                    alert(`Phrase ajoutée: ${phrase}`);
                    elementsMarques = new WeakSet();
                    scannerPosts();
                } else {
                    alert('Cette phrase existe déjà');
                }
            }
        };



        boutonOptions.onclick = function (e) {
            e.preventDefault();
            e.stopPropagation();
            setTimeout(() => {
                creerMenuOptions();
            }, 100);
        };

        boutonVoir.onclick = function (e) {
            // Empêcher la propagation de l'événement
            e.preventDefault();
            e.stopPropagation();

            // Créer une fenêtre modale pour afficher les phrases avec boutons de suppression
            setTimeout(() => {
                creerFenetreGestion();
            }, 100);
        };

        container.appendChild(boutonOnOff);
        container.appendChild(boutonAjouter);
        container.appendChild(boutonVoir);
        container.appendChild(boutonOptions);
        container.appendChild(compteur);

        document.body.appendChild(container);

        // Mettre à jour le compteur régulièrement
        setInterval(() => {
            compteur.innerHTML = postsTraites.size;
        }, 2000);
    }

    function extraireTitrePage() {
        const titres = new Set();

        // Sélecteurs pour différents types de titres Facebook
        const selecteursTitres = [
            // Titres de groupes dans les posts
            'span[class*="x1vvkbs"]:not([data-blocked-by-script="true"])',
            'h4 span:not([data-blocked-by-script="true"])',
            'a[role="link"] span:not([data-blocked-by-script="true"])',

            // Titres de pages dans les posts
            'div[data-ad-rendering-role="profile_name"] span:not([data-blocked-by-script="true"])',
            'h4[class*="x14z9mp"] span:not([data-blocked-by-script="true"])',

            // Liens vers des groupes/pages
            'a[href*="/groups/"] span:not([data-blocked-by-script="true"])',
            'a[href*="/pages/"] span:not([data-blocked-by-script="true"])',

            // Sélecteurs génériques pour les noms d'entités
            '[aria-label]:not([data-blocked-by-script="true"])',
        ];

        selecteursTitres.forEach(selecteur => {
            try {
                const elements = document.querySelectorAll(selecteur);
                elements.forEach(element => {
                    let texte = '';

                    // Extraire le texte selon le type d'élément
                    if (element.hasAttribute('aria-label')) {
                        texte = element.getAttribute('aria-label');
                    } else {
                        texte = element.textContent || element.innerText || '';
                    }

                    // Nettoyer et valider le texte
                    texte = texte.trim();
                    if (texte &&
                        texte.length > 3 &&
                        texte.length < 100 &&
                        !texte.includes('·') &&
                        !texte.includes('ago') &&
                        !texte.includes('il y a') &&
                        !texte.includes('Posted') &&
                        !texte.includes('Publié') &&
                        !texte.match(/^\d+$/) && // Pas juste des chiffres
                        !texte.match(/^[.,:;!?]+$/) && // Pas juste de la ponctuation
                        !phrasesABloquer.includes(texte) // Pas déjà dans la liste
                    ) {
                        // Vérifier si c'est probablement un nom de groupe/page
                        const estProbablementUnTitre = (
                            texte.includes(' ') || // Au moins deux mots
                            texte.match(/^[A-Z]/) || // Commence par une majuscule
                            texte.length > 15 // Assez long pour être descriptif
                        );

                        if (estProbablementUnTitre) {
                            titres.add(texte);
                        }
                    }
                });
            } catch (e) {
                // Erreur silencieuse
            }
        });

        // Recherche spécifique pour l'exemple donné
        try {
            const selecteurSpecifique = 'span.html-span.xdj266r.x14z9mp.xat24cr.x1lziwak.xexx8yu.xyri2b.x18d9i69.x1c1uobl.x1hl2dhg.x16tdsg8.x1vvkbs';
            const elementsSpecifiques = document.querySelectorAll(selecteurSpecifique);
            elementsSpecifiques.forEach(el => {
                const texte = el.textContent?.trim();
                if (texte && texte.length > 10 && !titres.has(texte)) {
                    titres.add(texte);
                }
            });
        } catch (e) {
            // Erreur silencieuse
        }

        return Array.from(titres).slice(0, 10); // Limiter à 10 résultats
    }

    // Fonction pour créer le menu d'options
    function creerMenuOptions() {
        // Recharger les options à chaque ouverture du menu pour synchronisation
        chargerOptions();

        // Supprimer le menu existant si il existe
        const existant = document.getElementById('fcb-options-modal');
        if (existant) existant.remove();

        const modal = document.createElement('div');
        modal.id = 'fcb-options-modal';
        modal.style.cssText = `
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                background: rgba(0,0,0,0.8);
                z-index: 99999;
                display: flex;
                justify-content: center;
                align-items: center;
            `;

        const contenu = document.createElement('div');
        contenu.style.cssText = `
                background: white;
                padding: 20px;
                border-radius: 10px;
                max-width: 500px;
                max-height: 80%;
                overflow-y: auto;
                color: black;
                position: relative;
                box-shadow: 0 10px 30px rgba(0,0,0,0.5);
            `;

        const titre = document.createElement('h3');
        titre.textContent = '⚙️ Options et Paramètres';
        titre.style.cssText = 'margin-top: 0; color: #333; border-bottom: 2px solid #eee; padding-bottom: 10px;';

        // Section options d'interface
        const sectionInterface = document.createElement('div');
        sectionInterface.innerHTML = '<h4 style="color: #666; margin-bottom: 15px; margin-top: 20px;">🖥️ Interface Facebook:</h4>';

        // Option supprimer colonne droite
        const optionColonneDroite = creerOptionCheckbox(
            'Masquer la colonne de droite',
            'Supprime la colonne de droite (publicités, suggestions) et agrandit le feed principal',
            options.masquerColonneDroite,
            (checked) => {
                const ancienneValeur = options.masquerColonneDroite;
                options.masquerColonneDroite = checked;
                sauvegarderOptions();

                // Feedback visuel
                const feedback = document.createElement('div');
                feedback.textContent = checked ? '✅ Colonne droite masquée' : '❌ Colonne droite restaurée';
                feedback.style.cssText = `
                        position: fixed;
                        top: 20px;
                        right: 20px;
                        background: ${checked ? '#10b981' : '#ef4444'};
                        color: white;
                        padding: 10px 20px;
                        border-radius: 8px;
                        z-index: 100000;
                        font-weight: bold;
                    `;
                document.body.appendChild(feedback);

                setTimeout(() => {
                    if (feedback.parentNode) {
                        feedback.parentNode.removeChild(feedback);
                    }
                }, 2000);

                // Seulement appliquer le CSS immédiatement
                if (ancienneValeur !== checked) {
                    // Appliquer immédiatement le changement CSS
                    appliquerOptionsCSS();

                    // Feedback
                    feedback.textContent += ' - Appliqué !';
                }
            }
        );

        // Option masquer Reels
        const optionMasquerReels = creerOptionCheckbox(
            'Masquer les Reels',
            'Cache complètement les sections Reels de Facebook pour un feed plus épuré',
            options.masquerReels,
            (checked) => {
                options.masquerReels = checked;
                sauvegarderOptions();

                // Feedback visuel
                const feedback = document.createElement('div');
                feedback.textContent = checked ? '✅ Reels masqués' : '❌ Reels restaurés';
                feedback.style.cssText = `
                        position: fixed;
                        top: 20px;
                        right: 20px;
                        background: ${checked ? '#10b981' : '#ef4444'};
                        color: white;
                        padding: 10px 20px;
                        border-radius: 8px;
                        z-index: 100000;
                        font-weight: bold;
                    `;
                document.body.appendChild(feedback);

                setTimeout(() => {
                    if (feedback.parentNode) {
                        feedback.parentNode.removeChild(feedback);
                    }
                }, 2000);

                // Appliquer immédiatement les changements sans recharger la page
                if (checked) {
                    // Activer le masquage des Reels immédiatement
                    setTimeout(masquerReels, 100);
                    setTimeout(masquerReels, 500); // Double appel pour être sûr
                } else {
                    // Restaurer les Reels en supprimant les masquages
                    document.querySelectorAll('[data-reels-hidden="true"]').forEach(element => {
                        element.style.removeProperty('display');
                        element.style.removeProperty('visibility');
                        element.style.removeProperty('height');
                        element.style.removeProperty('overflow');
                        element.style.removeProperty('opacity');
                        element.style.removeProperty('max-height');
                        element.removeAttribute('data-reels-hidden');
                    });
                }
            }
        );

        // Option masquer suggestions
        const optionMasquerSuggestions = creerOptionCheckbox(
            'Masquer les suggestions d\'amis',
            'Cache les sections "Personnes que vous pourriez connaître" pour un feed plus épuré',
            options.masquerSuggestions,
            (checked) => {
                options.masquerSuggestions = checked;
                sauvegarderOptions();

                // Feedback visuel
                const feedback = document.createElement('div');
                feedback.textContent = checked ? '✅ Suggestions masquées' : '❌ Suggestions restaurées';
                feedback.style.cssText = `
                        position: fixed;
                        top: 20px;
                        right: 20px;
                        background: ${checked ? '#10b981' : '#ef4444'};
                        color: white;
                        padding: 10px 20px;
                        border-radius: 8px;
                        z-index: 100000;
                        font-weight: bold;
                    `;
                document.body.appendChild(feedback);

                setTimeout(() => {
                    if (feedback.parentNode) {
                        feedback.parentNode.removeChild(feedback);
                    }
                }, 2000);

                // Appliquer immédiatement les changements sans recharger la page
                if (checked) {
                    // Activer le masquage des suggestions immédiatement
                    setTimeout(masquerSuggestions, 100);
                    setTimeout(masquerSuggestions, 500); // Double appel pour être sûr
                } else {
                    // Restaurer les suggestions en supprimant les masquages
                    document.querySelectorAll('[data-suggestions-hidden="true"]').forEach(element => {
                        element.style.removeProperty('display');
                        element.style.removeProperty('visibility');
                        element.style.removeProperty('height');
                        element.style.removeProperty('overflow');
                        element.style.removeProperty('opacity');
                        element.style.removeProperty('max-height');
                        element.removeAttribute('data-suggestions-hidden');
                    });
                }
            }
        );

        sectionInterface.appendChild(optionColonneDroite);
        sectionInterface.appendChild(optionMasquerReels);
        sectionInterface.appendChild(optionMasquerSuggestions);

        // Section futures options (pour l'extensibilité)
        const sectionAutres = document.createElement('div');
        sectionAutres.innerHTML = '<h4 style="color: #666; margin-bottom: 15px; margin-top: 20px;">🔮 Futures options:</h4>';

        const infoFutures = document.createElement('p');
        infoFutures.textContent = 'D\'autres options d\'interface et de filtrage seront ajoutées ici.';
        infoFutures.style.cssText = 'color: #999; font-style: italic; margin: 10px 0;';
        sectionAutres.appendChild(infoFutures);

        const boutonFermer = document.createElement('button');
        boutonFermer.textContent = '✖️ Fermer les options';
        boutonFermer.style.cssText = `
                background: #dc2626;
                color: white;
                border: none;
                padding: 12px 25px;
                border-radius: 8px;
                cursor: pointer;
                margin-top: 25px;
                width: 100%;
                font-size: 14px;
                font-weight: bold;
                transition: background-color 0.2s;
            `;

        boutonFermer.onmouseover = () => {
            boutonFermer.style.background = '#b91c1c';
        };
        boutonFermer.onmouseout = () => {
            boutonFermer.style.background = '#dc2626';
        };

        boutonFermer.onclick = (e) => {
            e.preventDefault();
            e.stopPropagation();
            modal.remove();
        };

        contenu.appendChild(titre);
        contenu.appendChild(sectionInterface);
        contenu.appendChild(sectionAutres);
        contenu.appendChild(boutonFermer);
        modal.appendChild(contenu);

        // Empêcher la fermeture accidentelle
        contenu.onclick = (e) => {
            e.stopPropagation();
        };

        // Fermer SEULEMENT en cliquant à l'extérieur (pas sur le contenu)
        let modalPeutFermer = false;
        setTimeout(() => {
            modalPeutFermer = true;
        }, 500); // Délai plus long pour éviter les clics accidentels

        modal.onclick = (e) => {
            // Fermer SEULEMENT si on clique sur l'arrière-plan noir (pas sur le contenu)
            if (e.target === modal && modalPeutFermer) {
                modal.remove();
            }
        };

        // Fermer avec Escape
        const fermerAvecEscape = (e) => {
            if (e.key === 'Escape') {
                modal.remove();
                document.removeEventListener('keydown', fermerAvecEscape);
            }
        };
        document.addEventListener('keydown', fermerAvecEscape);

        // Nettoyer l'event listener à la fermeture
        modal.addEventListener('remove', () => {
            document.removeEventListener('keydown', fermerAvecEscape);
        });

        document.body.appendChild(modal);
    }

    // Fonction pour créer une option avec checkbox
    function creerOptionCheckbox(titre, description, etatInitial, onchange) {
        const container = document.createElement('div');
        container.style.cssText = `
                display: flex;
                align-items: flex-start;
                padding: 15px;
                margin: 10px 0;
                background: #f8f9fa;
                border-radius: 8px;
                border-left: 4px solid #6366f1;
            `;

        const checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        checkbox.checked = etatInitial; // Utiliser l'état initial passé en paramètre
        checkbox.style.cssText = `
                margin-right: 15px;
                margin-top: 2px;
                transform: scale(1.2);
                cursor: pointer;
            `;

        // Forcer la synchronisation avec l'état réel au moment de la création
        setTimeout(() => {
            checkbox.checked = etatInitial;
        }, 100);

        const contenuTexte = document.createElement('div');
        contenuTexte.style.cssText = 'flex: 1;';

        const titreLigne = document.createElement('div');
        titreLigne.textContent = titre;
        titreLigne.style.cssText = `
                font-weight: bold;
                color: #333;
                margin-bottom: 5px;
                cursor: pointer;
            `;

        const descriptionLigne = document.createElement('div');
        descriptionLigne.textContent = description;
        descriptionLigne.style.cssText = `
                color: #666;
                font-size: 14px;
                line-height: 1.4;
            `;

        // Permettre de cliquer sur le titre pour toggle la checkbox
        titreLigne.onclick = () => {
            checkbox.checked = !checkbox.checked;
            checkbox.dispatchEvent(new Event('change'));
        };

        checkbox.onchange = () => {
            onchange(checkbox.checked);
        };

        contenuTexte.appendChild(titreLigne);
        contenuTexte.appendChild(descriptionLigne);
        container.appendChild(checkbox);
        container.appendChild(contenuTexte);

        return container;
    }

    // Fonction pour créer la fenêtre de gestion des phrases
    function creerFenetreGestion() {
        // Supprimer la fenêtre existante si elle existe
        const existante = document.getElementById('fb-blocker-modal');
        if (existante) existante.remove();

        const modal = document.createElement('div');
        modal.id = 'fb-blocker-modal';
        modal.style.cssText = `
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                background: rgba(0,0,0,0.8);
                z-index: 99999;
                display: flex;
                justify-content: center;
                align-items: center;
            `;

        const contenu = document.createElement('div');
        contenu.style.cssText = `
                background: white;
                padding: 20px;
                border-radius: 10px;
                max-width: 900px;
                width: 90%;
                max-height: 80%;
                overflow-y: auto;
                color: black;
                position: relative;
                box-shadow: 0 10px 30px rgba(0,0,0,0.5);
            `;

        const titre = document.createElement('h3');
        titre.textContent = 'Gestion des phrases bloquées';
        titre.style.cssText = 'margin-top: 0; color: #333;';

        const phrasesDefaut = phrasesABloquer.slice(0, 11);
        const phrasesPersonnalisees = phrasesABloquer.slice(11);

        // Section phrases par défaut
        const sectionDefaut = document.createElement('div');
        sectionDefaut.innerHTML = '<h4 style="color: #666; margin-bottom: 10px;">📋 Phrases par défaut:</h4>';

        const containerDefaut = document.createElement('div');
        containerDefaut.style.cssText = `
                display: grid;
                grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
                gap: 8px;
                margin-bottom: 20px;
            `;

        phrasesDefaut.forEach(phrase => {
            const ligne = creerLignePhrase(phrase, false);
            containerDefaut.appendChild(ligne);
        });
        sectionDefaut.appendChild(containerDefaut);

        // Section phrases personnalisées
        const sectionPerso = document.createElement('div');
        sectionPerso.innerHTML = '<h4 style="color: #666; margin-bottom: 10px; margin-top: 20px;">✏️ Vos phrases:</h4>';

        if (phrasesPersonnalisees.length === 0) {
            const vide = document.createElement('p');
            vide.textContent = 'Aucune phrase personnalisée';
            vide.style.color = '#999';
            sectionPerso.appendChild(vide);
        } else {
            const containerPerso = document.createElement('div');
            containerPerso.style.cssText = `
                    display: grid;
                    grid-template-columns: repeat(5, 1fr);
                    gap: 8px;
                    margin-bottom: 20px;
                `;

            phrasesPersonnalisees.forEach(phrase => {
                const ligne = creerLignePhrase(phrase, true);
                containerPerso.appendChild(ligne);
            });
            sectionPerso.appendChild(containerPerso);
        }

        const boutonFermer = document.createElement('button');
        boutonFermer.textContent = 'Fermer';
        boutonFermer.style.cssText = `
                background: #666;
                color: white;
                border: none;
                padding: 10px 20px;
                border-radius: 5px;
                cursor: pointer;
                margin-top: 20px;
            `;
        boutonFermer.onclick = (e) => {
            e.preventDefault();
            e.stopPropagation();
            modal.remove();
        };

        contenu.appendChild(titre);
        contenu.appendChild(sectionDefaut);
        contenu.appendChild(sectionPerso);
        contenu.appendChild(boutonFermer);
        modal.appendChild(contenu);

        // Empêcher la fermeture accidentelle
        contenu.onclick = (e) => {
            e.stopPropagation();
        };

        // Fermer en cliquant à l'extérieur (avec délai pour éviter la fermeture immédiate)
        let modalPeutFermer = false;
        setTimeout(() => {
            modalPeutFermer = true;
        }, 200);

        modal.onclick = (e) => {
            if (e.target === modal && modalPeutFermer) {
                modal.remove();
            }
        };

        // Fermer avec Escape
        const fermerAvecEscape = (e) => {
            if (e.key === 'Escape') {
                modal.remove();
                document.removeEventListener('keydown', fermerAvecEscape);
            }
        };
        document.addEventListener('keydown', fermerAvecEscape);

        document.body.appendChild(modal);
    }

    function creerLignePhrase(phrase, supprimable) {
        const ligne = document.createElement('div');
        ligne.style.cssText = `
                display: flex;
                flex-direction: column;
                padding: 10px;
                margin: 2px;
                background: #f5f5f5;
                border-radius: 5px;
                min-height: 80px;
                position: relative;
            `;

        const texte = document.createElement('div');
        texte.textContent = phrase;
        texte.style.cssText = `
                flex: 1; 
                font-size: 12px; 
                line-height: 1.3;
                word-break: break-word;
                margin-bottom: 8px;
            `;

        const boutonSuppr = document.createElement('button');
        boutonSuppr.innerHTML = supprimable ? '🗑️' : '🔒';
        boutonSuppr.title = supprimable ? 'Supprimer cette phrase' : 'Phrase par défaut (non supprimable)';
        boutonSuppr.style.cssText = `
                background: ${supprimable ? '#dc2626' : '#ccc'};
                color: white;
                border: none;
                padding: 4px 6px;
                border-radius: 3px;
                cursor: ${supprimable ? 'pointer' : 'not-allowed'};
                font-size: 10px;
                align-self: flex-end;
                width: fit-content;
            `;

        if (supprimable) {
            boutonSuppr.onclick = function () {
                if (confirm(`Supprimer la phrase: "${phrase}" ?`)) {
                    const index = phrasesABloquer.indexOf(phrase);
                    if (index > -1) {
                        phrasesABloquer.splice(index, 1);
                        sauvegarderPhrases();
                        ligne.remove();
                        alert(`Phrase supprimée: ${phrase}`);
                    }
                }
            };
        } else {
            boutonSuppr.disabled = true;
        }

        ligne.appendChild(texte);
        ligne.appendChild(boutonSuppr);
        return ligne;
    }

    // Démarrage
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', function () {
            initialiser();
            // Appliquer les options CSS après l'initialisation
            setTimeout(appliquerOptionsCSS, 500);
            // Masquer les Reels si l'option est activée
            if (options.masquerReels) {
                setTimeout(masquerReels, 600);
                setTimeout(masquerReels, 1500);
            }
            // Masquer les suggestions si l'option est activée
            if (options.masquerSuggestions) {
                setTimeout(masquerSuggestions, 700);
                setTimeout(masquerSuggestions, 1600);
            }
        });
    } else {
        initialiser();
        // Appliquer les options CSS immédiatement
        setTimeout(appliquerOptionsCSS, 500);
        // Masquer les Reels si l'option est activée
        if (options.masquerReels) {
            setTimeout(masquerReels, 600);
            setTimeout(masquerReels, 1500);
        }
        // Masquer les suggestions si l'option est activée
        if (options.masquerSuggestions) {
            setTimeout(masquerSuggestions, 700);
            setTimeout(masquerSuggestions, 1600);
        }
    }

    setTimeout(creerInterface, 2000);

    // Style CSS pour forcer le masquage même si Facebook réapplique ses styles
    const style = document.createElement('style');
    style.id = 'fcb-style-principal';
    let cssContent = `
            .script-blocked-post,
            [data-blocked-by-script="true"] {
                display: none !important;
                visibility: hidden !important;
                height: 0px !important;
                overflow: hidden !important;
                opacity: 0 !important;
                max-height: 0px !important;
            }
        `;

    // Ajouter immédiatement les styles pour les options activées
    if (options.masquerColonneDroite) {
        cssContent += `
                /* Masquer la colonne de droite immédiatement */
                div[role="complementary"] {
                    display: none !important;
                }
                div[role="main"] {
                    max-width: none !important;
                    width: calc(100% - 360px) !important;
                    margin-left: 360px !important;
                    margin-right: 0 !important;
                }
                div[role="feed"] {
                    max-width: none !important;
                    width: 100% !important;
                    padding-right: 20px !important;
                }
                div[role="feed"] > div {
                    max-width: none !important;
                    width: 100% !important;
                }
            `;
    }

    if (options.masquerReels) {
        cssContent += `
                /* Masquer les Reels immédiatement */
                [data-reels-hidden="true"] {
                    display: none !important;
                    visibility: hidden !important;
                    height: 0px !important;
                    overflow: hidden !important;
                    opacity: 0 !important;
                    max-height: 0px !important;
                }
            `;
    }

    if (options.masquerSuggestions) {
        cssContent += `
                /* Masquer les suggestions immédiatement */
                [data-suggestions-hidden="true"] {
                    display: none !important;
                    visibility: hidden !important;
                    height: 0px !important;
                    overflow: hidden !important;
                    opacity: 0 !important;
                    max-height: 0px !important;
                }
            `;
    }

    style.textContent = cssContent;
    document.head.appendChild(style);

    // LANCEMENT ULTRA-PRÉCOCE pour éviter le flash des contenus non filtrés
    function lancementPrecoce() {
        // Appliquer immédiatement les options CSS si elles sont activées
        if (options.masquerColonneDroite || options.masquerReels || options.masquerSuggestions) {
            appliquerOptionsCSS();
        }

        // Masquage CSS préventif pour les phrases communes
        const stylePreventif = document.createElement('style');
        stylePreventif.id = 'fcb-preventif';
        let cssPreventif = '';

        // Masquer préventivellement les éléments qui contiennent des phrases bloquées communes
        const phrasesCommunes = ['vous invite', 'invited you to join', 'rejoindre ce groupe', 'join this group'];
        phrasesCommunes.forEach(phrase => {
            cssPreventif += `
                    div:contains("${phrase}") {
                        opacity: 0 !important;
                        transition: opacity 0.1s;
                    }
                `;
        });

        // Masquage spécifique pour les suggestions
        if (options.masquerSuggestions) {
            cssPreventif += `
                    /* Masquage préventif des suggestions */
                    h3:contains("Personnes que vous pourriez connaître"),
                    h3:contains("People you may know") {
                        opacity: 0 !important;
                    }
                    /* Masquer les parents des h3 de suggestions */
                    h3:contains("Personnes que vous pourriez connaître") ~ *,
                    h3:contains("People you may know") ~ * {
                        opacity: 0 !important;
                    }
                `;
        }

        stylePreventif.textContent = cssPreventif;
        document.head.appendChild(stylePreventif);

        // Scanner immédiatement sans attendre
        setTimeout(scannerPosts, 0);
        setTimeout(scannerPosts, 50);
        setTimeout(scannerPosts, 150);

        // Masquer immédiatement les Reels et suggestions si activés
        if (options.masquerReels) {
            setTimeout(masquerReels, 0);
            setTimeout(masquerReels, 100);
        }

        if (options.masquerSuggestions) {
            setTimeout(masquerSuggestions, 0);
            setTimeout(masquerSuggestions, 100);
        }

        // Observer précoce pour intercepter les nouveaux contenus dès leur apparition
        if (document.body) {
            const observerPrecoce = new MutationObserver(function (mutations) {
                let nouveauxElements = false;
                mutations.forEach(function (mutation) {
                    if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                        mutation.addedNodes.forEach(node => {
                            if (node.nodeType === Node.ELEMENT_NODE) {
                                nouveauxElements = true;
                            }
                        });
                    }
                });

                if (nouveauxElements && scriptActif) {
                    // Réaction ultra-rapide
                    setTimeout(scannerPosts, 0);
                    setTimeout(masquerReels, 0);
                    setTimeout(masquerSuggestions, 0);
                }
            });

            observerPrecoce.observe(document.body, {
                childList: true,
                subtree: true
            });
        }
    }

    // Lancer immédiatement si possible, sinon dès que le DOM est prêt
    if (document.readyState !== 'loading') {
        // DOM déjà prêt
        lancementPrecoce();
    } else {
        // DOM en cours de chargement - lancer dès que possible
        document.addEventListener('DOMContentLoaded', lancementPrecoce);
    }

    // Lancement IMMÉDIAT même avant DOMContentLoaded pour un masquage ultra-rapide
    setTimeout(lancementPrecoce, 0);

})();