Letterboxd Watched & Watchlist Highlighter

Highlights films that are marked as watched (green) or are in your watchlist (blue) on any Letterboxd page.

// ==UserScript==
// @name         Letterboxd Watched & Watchlist Highlighter
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Highlights films that are marked as watched (green) or are in your watchlist (blue) on any Letterboxd page.
// @author       0x00a
// @match        https://letterboxd.com/*
// @grant        GM_addStyle
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // --- Style Configuration ---
    const WATCHED_COLOR = "#00E054"; // A bright green
    const WATCHLIST_COLOR = "#00A0E0"; // A bright blue
    const BORDER_WIDTH = "3px";

    // Inject the CSS styles for the highlights into the page
    GM_addStyle(`
        .poster-container .poster.highlight-watched .image,
        .film-poster.highlight-watched .image {
            border: ${BORDER_WIDTH} solid ${WATCHED_COLOR} !important;
            box-shadow: 0 0 12px ${WATCHED_COLOR} !important;
        }
        .poster-container .poster.highlight-watchlist .image,
        .film-poster.highlight-watchlist .image {
            border: ${BORDER_WIDTH} solid ${WATCHLIST_COLOR} !important;
            box-shadow: 0 0 12px ${WATCHLIST_COLOR} !important;
        }
    `);

    function highlightPosters() {
        // **FIXED SELECTOR:** Now correctly looks for the data attribute instead of a class.
        const watchlistPosters = document.querySelectorAll('.film-poster[data-film-in-watchlist="true"]:not([data-highlighted])');
        watchlistPosters.forEach(poster => {
            poster.classList.add('highlight-watchlist');
            poster.dataset.highlighted = 'true';
        });

        // Find all posters for films that are watched
        const watchedPosters = document.querySelectorAll('.film-watched .film-poster:not([data-highlighted])');
        watchedPosters.forEach(poster => {
            // Watched status overrides watchlist status
            poster.classList.remove('highlight-watchlist');
            poster.classList.add('highlight-watched');
            poster.dataset.highlighted = 'true';
        });
    }

    // --- Dynamic Content Handling ---
    // Use a MutationObserver to detect when new content is added to the page.
    const observerCallback = function(mutationsList, observer) {
        for (const mutation of mutationsList) {
            if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                // New elements were added, so we re-run the highlighter
                highlightPosters();
                break;
            }
        }
    };

    const observer = new MutationObserver(observerCallback);
    observer.observe(document.body, { childList: true, subtree: true });

    // Run the highlighter once on initial page load
    highlightPosters();

})();