        :root {
            --hue: 210;
            /* Couleur de fond du bureau (appliquée à <body> ci-dessous), dérivée de
               wallpaperHue/Saturation/Lightness (voir SettingsManager.defaults, js/core/
               settings.js) plutôt que de --hue/--sat (interface/fenêtres). Valeur de
               secours = gris, recalculée par SettingsManager.apply() au boot. */
            --wallpaper-bg-color: hsl(210, 3.4%, 8%);
            --bg-desktop: hsl(var(--hue), calc(15% * var(--sat, 80) / 80), 8%);
            --bg-taskbar: hsl(var(--hue), calc(15% * var(--sat, 80) / 80), 14%);
            --bg-window: hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 16%);
            /* Identique à --bg-window hors mode vitre ; redéfinie séparément dans
               body.glass-on ci-dessous avec un amortissement (même principe que
               --bg-menu) pour que les boîtes de dialogue (confirmation,
               remplacement de fichier...) restent lisibles même à forte
               transparence, plutôt que de suivre --bg-window jusqu'à son minimum. */
            --bg-requester: var(--bg-window);
            --bg-titlebar: hsl(var(--hue), calc(15% * var(--sat, 80) / 80), 20%);
            --text-primary: hsl(var(--hue), calc(10% * var(--sat, 80) / 80), 92%);
            --text-secondary: hsl(var(--hue), calc(10% * var(--sat, 80) / 80), 65%);
            --accent: hsl(var(--hue), calc(80% * var(--sat, 80) / 80), 55%);
            --danger: hsl(0, 70%, 50%);
            --border-color: hsl(var(--hue), calc(10% * var(--sat, 80) / 80), 25%);
            /* Fond des MENUS DÉROULANTS (.notepad-dropdown) : volontairement séparé
               de --bg-window. Reste opaque tant que le mode vitre est désactivé ;
               quand il est actif, body.glass-on plus bas lui applique le MÊME
               --sys-glass-alpha que le reste de l'interface mais AMORTI (voir la
               formule là-bas) — le menu doit rester lisible même transparence
               poussée au maximum, sans pour autant ignorer complètement le
               réglage (retour d'expérience : un menu totalement figé à l'opaque
               "cassait" l'effet plus qu'il ne le corrigeait). Légèrement plus
               clair que --bg-window pour bien se détacher visuellement même
               quand celui-ci devient translucide. */
            --bg-menu: hsl(var(--hue), calc(13% * var(--sat, 80) / 80), 19%);
            /* Effets d'écran globaux (CRT / glow phosphore / vignette), pilotés
               par SettingsManager.apply() — voir js/core/settings.js */
            --sys-glow: 0.55;
            --sys-crt-intensity: 0.55;
            --sys-vignette-intensity: 0.4;
            /* Effet "vitre" (fonds translucides + flou) : intensité pilotée par
               SettingsManager.apply() depuis les réglages "glassBlur"/"glassTransparency" — voir
               js/core/settings.js. Valeurs de secours ci-dessous au cas où le CSS
               serait évalué avant le premier apply(). */
            --sys-glass-alpha: 0.4;
            --sys-glass-blur: 34px;
            /* Taille du texte de l'interface, en %, pilotée par SettingsManager
               (réglage "Taille du texte" — onglet Apparence). Toutes les tailles
               de police du système sont exprimées en `rem` (voir plus bas) : elles
               sont donc TOUTES proportionnelles à cette variable, sans avoir à
               toucher chaque composant individuellement. */
            --sys-text-scale: 100;
            /* Hauteur RÉELLE de #taskbar (voir plus bas) : centralisée ici pour que
               tout élément qui doit se caler dessus (actuellement #ui-notify-stack,
               voir "bottom") reste juste quand cette hauteur change avec la taille
               de texte, au lieu d'un décalage en dur qui se désynchronise — c'est
               exactement ce qui s'était produit ici (chevauchement remonté par
               l'utilisateur) quand #taskbar est passé de 52px fixes à 3.25rem. */
            --taskbar-height: 2.75rem;
        }

        /* Le `%` ici multiplie la taille de police par défaut du navigateur
           (généralement 16px) : le facteur 1.4375 fait que 100% = 23px (au
           lieu de 16px), 150% = 34.5px, etc. Comme toutes les polices du
           système sont en `rem` (relatif à cette taille racine), changer
           cette seule variable redimensionne tout le texte de l'OS —
           fenêtres, menus, boutons, Terminal, applications... */
        html { font-size: calc(var(--sys-text-scale, 100) * 1.1875%); }


        * { margin: 0; padding: 0; box-sizing: border-box; user-select: none; }

        /* ---- Scrollbars uniformes dans toute l'interface ----
           Remplace la scrollbar native du navigateur (grise/blanche sous
           Windows, peu assortie au thème) par un style fin et discret, repris
           du Terminal, appliqué PARTOUT via un sélecteur universel plutôt que
           redéfini au cas par cas par app (ce qui donnait des largeurs et des
           couleurs légèrement différentes selon les endroits, et laissait
           carrément la scrollbar native sur tout ce qui n'avait pas encore
           été stylé — ex: Réglages, Bloc-notes, Todo...). Firefox suit
           scrollbar-width/scrollbar-color (propriétés héritées, posées une
           fois sur `html`) ; Chrome/Edge/Safari suivent les pseudo-éléments
           ::-webkit-scrollbar, ici sur `*` pour couvrir tout élément défilant
           sans avoir à les lister un par un. */
        html { scrollbar-width: thin; scrollbar-color: hsl(var(--hue), calc(15% * var(--sat, 80) / 80), 28%) transparent; }
        *::-webkit-scrollbar { width: 7px; height: 7px; }
        *::-webkit-scrollbar-track { background: transparent; }
        *::-webkit-scrollbar-thumb { background: hsl(var(--hue), calc(15% * var(--sat, 80) / 80), 28%); border-radius: 4px; transition: background 0.6s ease; }
        *::-webkit-scrollbar-thumb:hover { background: hsl(var(--hue), calc(15% * var(--sat, 80) / 80), 40%); }
        *::-webkit-scrollbar-corner { background: transparent; }

        body { 
            overflow: hidden; height: 100vh; width: 100vw; 
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; 
            background: var(--wallpaper-bg-color); color: var(--text-primary); 
            transition: background 0.6s ease, color 0.6s ease;
        }

        /* Les cinq fonds animés (#ps3-waves, #vector-field, #starfield, #plasma,
           #particle-life) partagent le même emplacement plein écran ; un seul est
           visible à la fois, choisi par l'attribut data-wallpaper-anim posé sur <body>
           par SettingsManager.apply() (voir js/core/settings.js). .waves-off les
           masque tous d'un coup, quel que soit le type sélectionné. */
        #ps3-waves, #vector-field, #starfield, #plasma, #particle-life {
            position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 0;
            overflow: hidden; pointer-events: none;
        }
        body.waves-off #ps3-waves, body.waves-off #vector-field, body.waves-off #starfield,
        body.waves-off #plasma, body.waves-off #particle-life { display: none; }
        #ps3-waves canvas, #vector-field canvas, #starfield canvas, #plasma canvas, #particle-life canvas {
            position: absolute; top: 0; left: 0; width: 100%; height: 100%;
            display: block;
        }

        body[data-wallpaper-anim="vectorfield"] #ps3-waves,
        body[data-wallpaper-anim="starfield"] #ps3-waves,
        body[data-wallpaper-anim="plasma"] #ps3-waves,
        body[data-wallpaper-anim="particlelife"] #ps3-waves { display: none; }

        /* Fond animé "particules reliées" (voir vector-field-background.js) : caché par
           défaut, affiché seulement quand data-wallpaper-anim="vectorfield". */
        #vector-field { display: none; }
        body[data-wallpaper-anim="vectorfield"]:not(.waves-off) #vector-field { display: block; }

        /* Fond animé "étoiles" (voir starfield-background.js) : même principe. */
        #starfield { display: none; }
        body[data-wallpaper-anim="starfield"]:not(.waves-off) #starfield { display: block; }

        /* Fond animé "plasma" (voir plasma-background.js) : même principe. */
        #plasma { display: none; }
        body[data-wallpaper-anim="plasma"]:not(.waves-off) #plasma { display: block; }

        /* Fond animé "vie de particules" (voir particle-life-background.js) : même principe. */
        #particle-life { display: none; }
        body[data-wallpaper-anim="particlelife"]:not(.waves-off) #particle-life { display: block; }

        /* Fond d'écran personnalisé (image/vidéo) — même niveau que #ps3-waves,
           masqué par défaut ; SettingsManager._applyWallpaperMedia() ajoute .active
           et bascule laquelle de l'<img>/<video> est visible. object-fit: cover fait
           que le média prend toujours la taille exacte de la fenêtre/écran, quel que
           soit son ratio d'origine. */
        #wallpaper-media {
            position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 0;
            overflow: hidden; pointer-events: none; display: none;
        }
        #wallpaper-media.active { display: block; }
        #wallpaper-media img, #wallpaper-media video {
            position: absolute; top: 0; left: 0; width: 100%; height: 100%;
            object-fit: cover; display: none;
        }

        #boot-screen { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: #000; display: flex; flex-direction: column; justify-content: center; align-items: center; z-index: 99999; transition: opacity 0.8s ease; }
        #boot-screen.hidden { opacity: 0; pointer-events: none; }

        /* ==================================================================
           Effets d'écran globaux — CRT (scanlines + léger scintillement),
           glow phosphore (utilisé par le Terminal, voir plus bas --sys-glow)
           et vignette (assombrissement des bords). Un unique overlay plein
           écran, purement décoratif (pointer-events:none), au lieu d'un
           effet local par app : s'applique donc à la totalité de l'interface
           (bureau, fenêtres, barre des tâches) plutôt qu'à une seule fenêtre.
           Activation/intensité pilotées par SettingsManager (classes
           .crt-on/.vignette-on sur <body> + variables --sys-*), réglables
           depuis l'app Réglages (onglet Effets) ou le Terminal
           ("crt"/"glow"/"vignette"). ================================== */
        #global-fx-overlay { position: fixed; inset: 0; z-index: 99970; pointer-events: none; }
        .fx-scanlines {
            position: absolute; inset: 0;
            opacity: 0;
            background: repeating-linear-gradient(
                to bottom,
                rgba(0,0,0,0.18) 0px,
                rgba(0,0,0,0.18) 1px,
                rgba(0,0,0,0) 1px,
                rgba(0,0,0,0) 3px
            );
            transition: opacity 0.35s ease;
        }
        body.crt-on .fx-scanlines {
            opacity: var(--sys-crt-intensity, 0.55);
            animation: sys-crt-flicker 6s infinite linear;
        }
        /* Léger halo phosphore ambiant diffusé depuis les bords, comme la
           lueur d'un vieux tube cathodique — suit la même intensité CRT. */
        body.crt-on #global-fx-overlay { box-shadow: inset 0 0 calc(46px * var(--sys-crt-intensity, 0.55)) hsla(var(--hue), 70%, 55%, calc(0.12 * var(--sys-crt-intensity, 0.55))); }
        @keyframes sys-crt-flicker {
            0%, 96%, 100% { opacity: var(--sys-crt-intensity, 0.55); }
            97% { opacity: calc(var(--sys-crt-intensity, 0.55) * 0.94); }
            98% { opacity: var(--sys-crt-intensity, 0.55); }
            99% { opacity: calc(var(--sys-crt-intensity, 0.55) * 0.97); }
        }
        @media (prefers-reduced-motion: reduce) {
            body.crt-on .fx-scanlines { animation: none; }
        }
        .fx-vignette {
            position: absolute; inset: 0;
            opacity: 0;
            background: radial-gradient(ellipse at center, rgba(0,0,0,0) 55%, rgba(0,0,0,0.85) 130%);
            transition: opacity 0.35s ease;
        }
        body.vignette-on .fx-vignette { opacity: var(--sys-vignette-intensity, 0.4); }

        /* ==================================================================
           Glow phosphore — appliqué à toute l'interface, pas seulement au
           Terminal. `text-shadow` est une propriété héritée en CSS ; en la
           posant sur <body> avec `currentColor`, chaque élément descendant
           récupère automatiquement un halo dans SA PROPRE couleur (texte
           gris discret = halo discret, texte accent = halo vif), sans avoir
           à cibler chaque composant un par un. Les règles plus spécifiques
           du Terminal (.t-green, etc., définies plus bas) restent
           prioritaires et gardent leur halo plus prononcé.
           `box-shadow` n'est en revanche PAS hérité : le glow des contrôles
           ("gadgets" — fenêtre active, bouton Démarrer, interrupteurs,
           sliders, boutons médias, presets couleur...) est donc ajouté
           directement dans la définition CSS de chacun, plus bas dans ce
           fichier, plutôt que dupliqué ici (l'ordre des règles CSS
           déciderait sinon laquelle des deux définitions l'emporte). ==== */
        body {
            text-shadow: 0 0 calc(1px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(3px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(7px * var(--sys-glow, 0.55)) currentColor;
        }
        #start-btn {
            text-shadow: 0 0 calc(2px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(8px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(18px * var(--sys-glow, 0.55)) currentColor;
        }

        .boot-logo-wrap { position: relative; width: 156px; height: 156px; margin-bottom: 30px; }
        .about-boot-hex-wrap { position: relative; width: 96px; height: 96px; margin: 4px auto 6px; }
        .boot-hex { width: 100%; height: 100%; overflow: visible; }

        .about-title { display: flex; align-items: center; justify-content: center; gap: 8px; margin: 0 0 6px; font-size: 1.5rem; color: var(--text-primary); }
        .about-tagline { color: var(--text-secondary); font-size: 0.8125rem; margin: 0 0 20px; }
        .about-card {
            text-align: left; background: rgba(255,255,255,0.035); border: 1px solid var(--border-color);
            border-radius: 10px; padding: 16px 18px; margin-bottom: 14px;
        }
        .about-card-title { margin: 0 0 8px; font-size: 0.9375rem; color: var(--text-primary); }
        .about-card-desc { margin: 0; font-size: 0.8125rem; line-height: 1.6; color: var(--text-secondary); }
        .about-starme { font-size: 0.8125rem; color: var(--accent); margin: 0 0 22px; }
        .about-actions { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; }
        .about-btn {
            display: flex; align-items: center; padding: 8px 18px; background: transparent; color: var(--text-primary);
            border: 1px solid var(--border-color); border-radius: 20px; cursor: pointer; font-size: 0.8125rem;
            transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease, transform 0.15s ease;
        }
        .about-btn:hover { transform: translateY(-1px); }
        .about-btn--github:hover { border-color: #8b8b8b; color: #fff; background: rgba(255,255,255,0.06); }
        .about-btn--itch:hover { border-color: #fa5c5c; color: #fa5c5c; background: rgba(250,92,92,0.08); }
        .about-btn--primary { background: var(--accent); color: #fff; border-color: var(--accent); }
        .about-btn--primary:hover { filter: brightness(1.1); }

        .boot-hex-outline {
            stroke-dasharray: 300; stroke-dashoffset: 300;
            filter: drop-shadow(0 0 7px hsla(var(--hue), calc(80% * var(--sat, 80) / 80), 60%, 0.55));
            animation: bootHexDraw 2.1s cubic-bezier(.65,0,.35,1) forwards;
        }
        .boot-hex-fill {
            opacity: 0; transform-origin: 50px 50px; transform: scale(0.85);
            animation: bootHexFillIn 1.2s ease-out 1.9s forwards,
                       bootHexPulse 8s ease-in-out 3.1s infinite;
        }
        @keyframes bootHexDraw { to { stroke-dashoffset: 0; } }
        @keyframes bootHexFillIn { to { opacity: 1; transform: scale(1); } }
        @keyframes bootHexPulse {
            0%, 100% { filter: drop-shadow(0 0 9px hsla(var(--hue), calc(80% * var(--sat, 80) / 80), 60%, .4)); transform: scale(1); }
            50%      { filter: drop-shadow(0 0 20px hsla(var(--hue), calc(80% * var(--sat, 80) / 80), 60%, .75)); transform: scale(1.035); }
        }

        .boot-logo {
            font-size: 2.3rem; font-weight: 300; color: #fff;
            opacity: 0; letter-spacing: 22px; transform: translateY(8px); filter: blur(4px);
            animation: bootTextIn 1.4s cubic-bezier(.22,1,.36,1) 2.2s forwards;
        }
        @keyframes bootTextIn { to { opacity: 1; letter-spacing: 4px; transform: translateY(0); filter: blur(0); } }

        /* Numéro de version, centré dans l'hexagone, en grand, sans fond —
           juste un effet de brillance qui pulse doucement en continu. Apparaît
           une fois le remplissage de l'hexagone terminé (bootHexFillIn se
           termine vers 3.1s) pour ne pas se retrouver sur un hexagone encore
           transparent/juste esquissé au trait. */
        .boot-hex-version {
            font-family: 'Geneva', Tahoma, Geneva, Verdana, sans-serif;
            font-size: 40px; font-weight: 500; letter-spacing: 0.3px;
            fill: #fff; opacity: 0;
            animation: bootHexVersionIn 0.7s cubic-bezier(.22,1,.36,1) 3.2s forwards,
                       bootHexVersionShine 3.2s ease-in-out 3.9s infinite;
        }
        @keyframes bootHexVersionIn { to { opacity: 0.95; } }
        @keyframes bootHexVersionShine {
            0%, 100% { filter: drop-shadow(0 0 1px hsla(0,0%,100%,0.25)); }
            50%      { filter: drop-shadow(0 0 4px hsla(0,0%,100%,0.9)) drop-shadow(0 0 14px hsla(0,0%,100%,0.6)); }
        }

        .boot-loading {
            margin-top: 14px; font-size: 0.8rem; font-weight: 400; letter-spacing: 2px;
            color: var(--text-secondary); opacity: 0;
            animation: bootLoadingIn 0.8s ease-out 3.9s forwards,
                       bootLoadingBreathe 4s ease-in-out 4.7s infinite;
        }
        @keyframes bootLoadingIn { to { opacity: 0.7; } }
        @keyframes bootLoadingBreathe { 0%, 100% { opacity: 0.35; } 50% { opacity: 0.85; } }

        .boot-spinner {
            margin-top: 16px; width: 24px; height: 24px;
            border: 3px solid rgba(255,255,255,0.12); border-top: 3px solid var(--accent);
            border-radius: 50%; opacity: 0;
            animation: bootSpinnerIn 0.5s ease-out 4s forwards, spin 0.9s linear infinite;
        }
        @keyframes bootSpinnerIn { to { opacity: 1; } }

        .boot-footer {
            position: absolute; left: 0; right: 0; bottom: 26px; text-align: center;
            font-size: 0.7rem; letter-spacing: .5px; color: hsl(var(--hue), calc(8% * var(--sat, 80) / 80), 38%);
            opacity: 0; animation: bootFooterIn 2s ease-out 0.6s forwards;
        }
        @keyframes bootFooterIn { to { opacity: 1; } }
        @keyframes spin { 100% { transform: rotate(360deg); } }
        @keyframes pulse { 0%, 100% { opacity: 0.6; } 50% { opacity: 1; } }

        /* Pas de z-index ici volontairement : en avoir un créait un contexte
           d'empilement qui piégeait TOUTES les fenêtres (quel que soit le
           z-index que WindowManager leur attribue en interne, ex: 100+) en
           permanence derrière #dock (z-index:50) et #taskbar (z-index:9999)
           — aucune fenêtre ne pouvait jamais passer devant le dock, même
           fraîchement cliquée/focus. Sans z-index explicite, #desktop ne
           crée plus son propre contexte d'empilement : ses fenêtres
           enfants entrent en concurrence directe avec #dock au niveau
           supérieur, comme prévu par WindowManager.focusWindow() /
           OS.bringDockToFront(). Reste au-dessus du fond animé (#ps3-waves,
           z-index:0) simplement grâce à l'ordre du DOM (desktop vient après
           dans index.html), aucun z-index n'est donc nécessaire ici. */
        #desktop { position: absolute; top: 0; left: 0; width: 100%; height: calc(100% - var(--taskbar-height)); padding: 10px; display: flex; flex-direction: column; flex-wrap: wrap; align-content: flex-start; gap: 10px; }
        .desktop-icon { width: 80px; padding: 8px 4px; display: flex; flex-direction: column; align-items: center; gap: 5px; border: 1px solid transparent; border-radius: 5px; cursor: pointer; text-align: center; transition: background 0.2s; }
        .desktop-icon:hover { background: rgba(255,255,255,0.1); border-color: var(--accent); }
        .desktop-icon span { font-size: 0.6875rem; word-wrap: break-word; color: var(--text-primary); text-shadow: 0 1px 3px rgba(0,0,0,0.8), 0 0 calc(1px * var(--sys-glow, 0.55)) var(--text-primary), 0 0 calc(4px * var(--sys-glow, 0.55)) var(--text-primary); }
        .desktop-icon .icon { font-size: 2rem; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.5)); }
        .desktop-icon .icon svg, .start-app-item .icon svg { width: 1em; height: 1em; display: block; }

        /* ---- Dock (façon NeXTSTEP) : colonne verticale fixe à droite, une
           grande icône monochrome + le nom de la catégorie en dessous. Un clic
           ouvre #dock-panel (panneau latéral à gauche du dock) qui affiche les
           apps de cette catégorie dans le même style icône+texte. Une catégorie
           sans aucune app enregistrée reste masquée (updateDockEmptyState). */
        #dock { position: fixed; top: 12px; right: 12px; height: auto; min-height: 60px; max-height: calc(100% - var(--taskbar-height) - 24px); width: 96px; box-sizing: border-box; background: var(--bg-taskbar); border: 1px solid var(--border-color); border-radius: 12px; backdrop-filter: blur(10px); z-index: 50; display: flex; flex-direction: column; align-items: stretch; gap: 4px; padding: 10px 6px; overflow-y: auto; overflow-x: hidden; }
        .dock-cat-btn { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 9px 2px; border-radius: 10px; cursor: pointer; text-align: center; flex: 0 0 auto; transition: background 0.15s; }
        .dock-cat-btn:hover { background: rgba(255,255,255,0.1); }
        .dock-cat-btn.active { background: rgba(255,255,255,0.18); }
        /* Icônes de catégorie : même style SVG monochrome (trait `currentColor`) que
           les icônes d'application (voir js/core/icons.js), au lieu des emojis
           d'origine — cohérence visuelle + rendu identique sur toutes les plateformes. */
        .dock-cat-icon { font-size: 2.15rem; line-height: 1; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.5)); }
        .dock-cat-icon svg { width: 1em; height: 1em; display: block; }
        .dock-cat-label { font-size: 0.5625rem; font-weight: 400; letter-spacing: 0.01em; text-transform: none; color: var(--text-primary); word-break: break-word; line-height: 1.25; }
        .dock-resize-handle { position: absolute; left: 0; bottom: 0; width: 100%; height: 8px; cursor: ns-resize; touch-action: none; }
        .dock-resize-handle::after { content: ''; position: absolute; left: 50%; bottom: 2px; width: 26px; height: 3px; border-radius: 2px; background: var(--border-color); transform: translateX(-50%); }

        #dock-panel { position: fixed; right: 116px; width: 208px; max-height: calc(100% - 24px); box-sizing: border-box; background: var(--bg-taskbar); border: 1px solid var(--border-color); border-radius: 12px; backdrop-filter: blur(10px); z-index: 50; padding: 12px 8px; display: none; flex-wrap: wrap; align-content: flex-start; gap: 4px; overflow-y: auto; }
        #dock-panel.open { display: flex; }
        .dock-panel-icon { width: 84px; padding: 8px 4px; display: flex; flex-direction: column; align-items: center; gap: 5px; border-radius: 8px; cursor: pointer; text-align: center; transition: background 0.15s; }
        .dock-panel-icon:hover { background: rgba(255,255,255,0.1); }
        .dock-panel-icon .icon { font-size: 2rem; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.5)); }
        /* Bug corrigé : sans cette règle, les <svg> des icônes d'app (sans attributs
           width/height, seulement un viewBox) s'affichaient à leur taille intrinsèque
           par défaut (300×150px) au lieu de suivre font-size — d'où des icônes
           invisibles/rognées dans le panneau du dock (seul le nom apparaissait). */
        .dock-panel-icon .icon svg { width: 1em; height: 1em; display: block; }
        .dock-panel-icon span { font-size: 0.6875rem; word-wrap: break-word; color: var(--text-primary); }

        @media (max-width: 720px) {
            #dock { top: auto; right: 6px; bottom: calc(var(--taskbar-height) + 6px); left: 6px; width: auto; height: 72px !important; max-height: none; flex-direction: row; align-items: center; overflow-x: auto; overflow-y: hidden; padding: 6px 8px; }
            .dock-cat-btn { flex: 0 0 auto; }
            .dock-resize-handle { display: none; }
            #dock-panel { right: 6px; left: 6px; width: auto; bottom: 136px; top: auto !important; max-height: 40vh; }
        }
        .title-icon { display: inline-flex; width: 14px; height: 14px; vertical-align: -2px; margin-right: 6px; color: var(--text-secondary); }
        .title-icon svg { width: 100%; height: 100%; display: block; }
        .taskbar-icon { display: inline-flex; width: 16px; height: 16px; margin-right: 2px; }
        .taskbar-icon svg { width: 100%; height: 100%; display: block; }

        /* Hauteur en `rem` (et non px) : comme --sys-text-scale pilote html{font-size}
           (voir en haut du fichier), la barre des tâches grandit/rétrécit avec le
           texte au lieu de rester figée pendant que son contenu change de taille. */
        #taskbar { position: fixed; bottom: 0; left: 0; width: 100%; height: var(--taskbar-height); background: var(--bg-taskbar); border-top: 1px solid var(--border-color); display: flex; align-items: center; z-index: 9999; padding: 0 10px; backdrop-filter: blur(10px); transition: background 0.6s ease; }
        #start-btn { background: none; border: none; color: var(--text-primary); font-size: 2.1875rem; font-weight: bold; cursor: pointer; width: var(--taskbar-height); height: var(--taskbar-height); display: flex; align-items: center; justify-content: center; animation: startBtnPulse 3s ease-in-out infinite; }
        @keyframes startBtnPulse { 0%, 100% { opacity: 0.55; } 50% { opacity: 1; } }
        #start-btn:hover { background: rgba(255,255,255,0.1); }
        #taskbar-apps { display: flex; flex: 1; height: 100%; margin-left: 10px; overflow-x: auto; }
        .taskbar-app { height: 100%; display: flex; align-items: stretch; background: transparent; color: var(--text-secondary); border-bottom: 2px solid transparent; white-space: nowrap; transition: color 0.2s, border-color 0.2s, background 0.2s; }
        .taskbar-app.active { color: var(--text-primary); border-bottom-color: var(--accent); background: rgba(255,255,255,0.05); box-shadow: inset 0 -2px calc(6px * var(--sys-glow, 0.55)) 0 var(--accent); }
        .taskbar-app-main { height: 100%; padding: 0 6px 0 15px; display: flex; align-items: center; gap: 8px; background: transparent; border: none; color: inherit; cursor: pointer; font-size: 0.875rem; font-family: inherit; }
        .taskbar-app-close {
            display: flex; align-items: center; justify-content: center; flex-shrink: 0;
            width: 20px; height: 20px; margin: auto 10px auto 0; padding: 0;
            border: none; border-radius: 5px; background: transparent; color: var(--text-secondary);
            cursor: pointer; font-size: 0.625rem; line-height: 1; opacity: 0.55;
            transition: opacity 0.15s ease, background 0.15s ease, color 0.15s ease;
        }
        .taskbar-app-close:hover { opacity: 1; background: hsla(0, 70%, 50%, 0.18); color: var(--danger); }
        #taskbar-clock { margin-left: auto; padding: 0 15px; text-align: right; line-height: 1.3; display: flex; flex-direction: column; justify-content: center; color: var(--text-secondary); }
        #clock-time { font-size: 0.875rem; }
        #clock-date { font-size: 0.6875rem; opacity: 0.8; }

        /* Zone de notification (tray) — icônes miniatures pour les widgets
           qui se replient hors de la barre des tâches classique en mode
           minimisé (ex: app Yeux). Vide et invisible tant qu'aucune app n'y
           dépose d'icône (voir js/apps/xeyes.js pour un exemple d'usage). */
        #taskbar-tray { display: flex; align-items: center; gap: 4px; height: 100%; flex-shrink: 0; }
        .tray-icon-btn {
            height: 34px; width: 34px; padding: 0; display: flex; align-items: center; justify-content: center;
            background: none; border: 1px solid transparent; border-radius: 6px; color: var(--text-secondary);
            cursor: pointer; transition: background 0.15s ease, border-color 0.15s ease;
        }
        .tray-icon-btn:hover { background: rgba(255,255,255,0.08); border-color: var(--border-color); }
        .tray-icon-btn canvas { width: 24px; height: 16px; display: block; }
        /* Variante agrandie (x3) — utilisée par l'app Yeux, dont les pupilles ont
           besoin de place pour rester lisibles/expressives une fois repliées. */
        .tray-icon-btn.tray-icon-lg { height: 48px; width: 76px; }
        .tray-icon-btn.tray-icon-lg canvas { width: 72px; height: 48px; }

        #fullscreen-switcher { position: relative; height: 100%; display: flex; align-items: center; flex-shrink: 0; }
        #fullscreen-btn {
            height: 34px; width: 34px; display: flex; align-items: center; justify-content: center;
            background: none; border: 1px solid transparent; border-radius: 6px; color: var(--text-secondary);
            cursor: pointer; font-family: inherit; transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
        }
        #fullscreen-btn:hover { background: rgba(255,255,255,0.08); color: var(--text-primary); }
        #fullscreen-btn.active { background: rgba(255,255,255,0.1); color: var(--text-primary); border-color: var(--border-color); }
        #fullscreen-icon { width: 16px; height: 16px; display: flex; }
        #fullscreen-icon svg { width: 100%; height: 100%; }

        #fullscreen-menu {
            position: absolute; bottom: 46px; right: 0; min-width: 210px; background: var(--bg-window);
            border: 1px solid var(--border-color); border-radius: 10px; padding: 6px;
            box-shadow: 0 15px 40px rgba(0,0,0,0.55), 0 0 0 1px rgba(255,255,255,0.03);
            backdrop-filter: blur(16px); z-index: 99998; display: none; flex-direction: column; gap: 2px;
            opacity: 0; transform: translateY(8px) scale(0.97); transition: opacity 0.15s ease, transform 0.15s ease, background 0.6s ease;
        }
        #fullscreen-menu.open { display: flex; opacity: 1; transform: translateY(0) scale(1); }
        .lang-menu-item .lm-icon { width: 16px; height: 16px; flex-shrink: 0; display: flex; color: var(--text-primary); }
        .lang-menu-item .lm-icon svg { width: 100%; height: 100%; }

        #lang-switcher { position: relative; height: 100%; display: flex; align-items: center; flex-shrink: 0; }
        #lang-btn {
            height: 34px; padding: 0 10px; display: flex; align-items: center; gap: 6px;
            background: none; border: 1px solid transparent; border-radius: 6px; color: var(--text-secondary);
            cursor: pointer; font-family: inherit; font-size: 0.75rem; font-weight: 600; letter-spacing: 0.3px;
            transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
        }
        #lang-btn:hover { background: rgba(255,255,255,0.08); color: var(--text-primary); }
        #lang-btn.active { background: rgba(255,255,255,0.1); color: var(--text-primary); border-color: var(--border-color); }
        #lang-flag { width: 16px; height: 11px; flex-shrink: 0; display: flex; border-radius: 2px; overflow: hidden; box-shadow: 0 0 0 1px rgba(255,255,255,0.15); }
        #lang-flag svg { width: 100%; height: 100%; display: block; }
        #lang-code { min-width: 18px; text-align: left; }

        #lang-menu {
            position: absolute; bottom: 46px; right: 0; min-width: 190px; background: var(--bg-window);
            border: 1px solid var(--border-color); border-radius: 10px; padding: 6px;
            box-shadow: 0 15px 40px rgba(0,0,0,0.55), 0 0 0 1px rgba(255,255,255,0.03);
            backdrop-filter: blur(16px); z-index: 99998; display: none; flex-direction: column; gap: 2px;
            opacity: 0; transform: translateY(8px) scale(0.97); transition: opacity 0.15s ease, transform 0.15s ease, background 0.6s ease;
        }
        #lang-menu.open { display: flex; opacity: 1; transform: translateY(0) scale(1); }
        .lang-menu-item {
            display: flex; align-items: center; gap: 10px; padding: 9px 10px; border-radius: 7px;
            cursor: pointer; color: var(--text-primary); font-size: 0.8125rem; transition: background 0.15s ease;
        }
        .lang-menu-item:hover { background: rgba(255,255,255,0.08); }
        .lang-menu-item .lm-flag { width: 19px; height: 13px; flex-shrink: 0; display: flex; border-radius: 2px; overflow: hidden; box-shadow: 0 0 0 1px rgba(255,255,255,0.15); }
        .lang-menu-item .lm-flag svg { width: 100%; height: 100%; display: block; }
        .lang-menu-item .lm-name { flex: 1; }
        .lang-menu-item .lm-check { width: 14px; height: 14px; color: var(--accent); flex-shrink: 0; visibility: hidden; }
        .lang-menu-item.active .lm-check { visibility: visible; }
        .lang-menu-item.active { background: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 55%, 0.1); }

        #start-menu {
            position: fixed; bottom: 62px; left: 10px; width: 340px; max-height: 560px;
            background: var(--bg-window); border: 1px solid var(--border-color);
            border-radius: 10px; z-index: 99998; display: none; flex-direction: column;
            box-shadow: 0 15px 45px rgba(0,0,0,0.55), 0 0 0 1px rgba(255,255,255,0.03);
            overflow: hidden; backdrop-filter: blur(16px);
            transition: background 0.6s ease, opacity 0.18s ease, transform 0.18s ease;
            opacity: 0; transform: translateY(10px) scale(0.98); pointer-events: none;
        }
        #start-menu.open { display: flex; opacity: 1; transform: translateY(0) scale(1); pointer-events: auto; }

        .start-menu-header { flex-shrink: 0; padding: 16px 16px 12px; border-bottom: 1px solid var(--border-color); transition: border-color 0.6s ease; }
        .start-menu-brand { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
        .start-menu-brand-mark {
            width: 52px; height: 52px; display: flex; align-items: center; justify-content: center;
            font-size: 2.4rem; font-weight: 700; flex-shrink: 0;
            background: linear-gradient(135deg, hsl(var(--hue), calc(80% * var(--sat, 80) / 80), 58%), hsl(calc(var(--hue) + 25), 75%, 48%));
            -webkit-background-clip: text; background-clip: text; color: transparent;
            transition: background 0.6s ease;
        }
        .start-menu-brand-text { display: flex; flex-direction: column; line-height: 1.25; }
        .start-menu-brand-title { font-size: 0.9375rem; font-weight: 600; color: var(--text-primary); }
        .start-menu-brand-sub { font-size: 0.6875rem; color: var(--text-secondary); }
        .start-menu-search {
            display: flex; align-items: center; gap: 8px; background: rgba(255,255,255,0.05);
            border: 1px solid var(--border-color); border-radius: 8px; padding: 8px 12px;
            transition: border-color 0.15s ease, background 0.15s ease;
        }
        .start-menu-search:focus-within { border-color: var(--accent); background: rgba(255,255,255,0.07); }
        .start-menu-search svg { width: 15px; height: 15px; color: var(--text-secondary); flex-shrink: 0; }
        .start-menu-search input {
            flex: 1; background: none; border: none; outline: none; color: var(--text-primary);
            font-size: 0.8125rem; font-family: inherit;
        }
        .start-menu-search input::placeholder { color: var(--text-secondary); }

        .start-menu-list { flex: 1; overflow-y: auto; padding: 8px; display: flex; flex-direction: column; gap: 2px; min-height: 60px; }

        .start-menu-empty { display: none; text-align: center; padding: 30px 10px; color: var(--text-secondary); font-size: 0.8125rem; }
        .start-menu-empty.visible { display: block; }

        .start-app-item {
            padding: 9px 12px; display: flex; align-items: center; gap: 13px; cursor: pointer;
            color: var(--text-primary); border-radius: 8px; border: 1px solid transparent;
            transition: background 0.15s ease, transform 0.1s ease;
        }
        .start-app-item:hover { background: rgba(255,255,255,0.08); }
        .start-app-item:active { transform: scale(0.98); }
        .start-app-item .icon {
            font-size: 1.125rem; width: 34px; height: 34px; flex-shrink: 0; display: flex;
            align-items: center; justify-content: center; border-radius: 8px; color: var(--accent);
            background: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 55%, 0.14);
            transition: background 0.6s ease, color 0.6s ease;
        }
        .start-app-item span:not(.icon) { font-size: 0.8438rem; }
        .start-app-item.hidden { display: none; }

        .start-menu-footer {
            flex-shrink: 0; display: flex; border-top: 1px solid var(--border-color);
            transition: border-color 0.6s ease;
        }
        .start-footer-btn {
            flex: 1; display: flex; align-items: center; justify-content: center; gap: 8px;
            background: none; border: none; color: var(--text-secondary); cursor: pointer;
            padding: 12px 8px; font-size: 0.75rem; font-family: inherit; transition: background 0.15s ease, color 0.15s ease;
        }
        .start-footer-btn:first-child { border-right: 1px solid var(--border-color); }
        .start-footer-btn svg { width: 15px; height: 15px; }
        .start-footer-btn:hover { background: rgba(255,255,255,0.06); color: var(--text-primary); }

        .window { position: absolute; background: var(--bg-window); border: 1px solid var(--border-color); box-shadow: 0 5px 20px rgba(0,0,0,0.5); display: flex; flex-direction: column; min-width: 300px; min-height: 200px; border-radius: 6px; transition: box-shadow 0.2s, background 0.6s ease; }
        .window.focused { box-shadow: 0 8px 30px rgba(0,0,0,0.8), 0 0 calc(4px * var(--sys-glow, 0.55)) hsla(var(--hue), calc(80% * var(--sat, 80) / 80), 55%, 0.55), 0 0 calc(16px * var(--sys-glow, 0.55)) hsla(var(--hue), calc(80% * var(--sat, 80) / 80), 55%, 0.35); z-index: auto; }
        .window.maximized { top: 0 !important; left: 0 !important; width: 100% !important; height: calc(100vh - var(--taskbar-height)) !important; transition: all 0.2s ease; border-radius: 0; }
        .window.minimized { transform: scale(0.8); opacity: 0; pointer-events: none; transition: all 0.2s ease; }

        /* ══════════════════════════════════════
           STYLE "VITRE" (optionnel) — fonds translucides + flou façon
           Vista/Windows 11 (acrylic). Activable/désactivable dans
           Réglages > Apparence (voir settings.js / settings-app.js), qui
           bascule body.glass-on. N'affecte QUE l'opacité/le flou des fonds :
           couleurs, tailles, mises en page restent strictement identiques —
           c'est bien un deuxième "style" au sens visuel demandé, pas une
           refonte. Désactivé par défaut : le rendu actuel (fonds opaques)
           reste inchangé tant que le réglage n'est pas activé.
           ══════════════════════════════════════ */
        body.glass-on {
            --bg-taskbar: hsla(var(--hue), calc(15% * var(--sat, 80) / 80), 14%, var(--sys-glass-alpha, 0.4));
            --bg-window: hsla(var(--hue), calc(12% * var(--sat, 80) / 80), 16%, var(--sys-glass-alpha, 0.4));
            --bg-titlebar: hsla(var(--hue), calc(15% * var(--sat, 80) / 80), 20%, var(--sys-glass-alpha, 0.4));
            /* Même alpha que le reste de l'interface, mais AMORTI à 40% de sa
               course : --sys-glass-alpha descend jusqu'à 0.1 (transparence à
               100%) pour les fenêtres, ce qui rendait un menu texte illisible ;
               ici la même valeur ne fait descendre le menu que jusqu'à ~0.64.
               Le menu suit donc toujours le réglage (ce n'était plus le cas
               avant), juste deux fois moins fort. */
            --bg-menu: hsla(var(--hue), calc(13% * var(--sat, 80) / 80), 19%, calc(1 - (1 - var(--sys-glass-alpha, 0.4)) * 0.4));
            /* Même amortissement que --bg-menu ci-dessus, appliqué aux boîtes de
               dialogue (.ui-requester-box/.ui-filepicker-box) : sans lui, un
               requester "écraser ce fichier ?" suivait --bg-window jusqu'à son
               minimum de transparence, ET sans le backdrop-filter (flou) que les
               fenêtres reçoivent (voir le sélecteur juste en dessous, qui ne les
               liste pas) — un fond translucide SANS flou, illisible. */
            --bg-requester: hsla(var(--hue), calc(12% * var(--sat, 80) / 80), 16%, calc(1 - (1 - var(--sys-glass-alpha, 0.4)) * 0.4));
        }
        body.glass-on .window,
        body.glass-on #taskbar,
        body.glass-on #dock,
        body.glass-on #dock-panel,
        body.glass-on #start-menu,
        body.glass-on #lang-menu,
        body.glass-on #fullscreen-menu,
        body.glass-on .notepad-menu-bar,
        body.glass-on .notepad-status,
        body.glass-on .notepad-findbar,
        body.glass-on .settings-sidebar,
        body.glass-on .todo-sidebar,
        body.glass-on .files-shell {
            backdrop-filter: blur(var(--sys-glass-blur, 34px)) saturate(160%);
            -webkit-backdrop-filter: blur(var(--sys-glass-blur, 34px)) saturate(160%);
        }
        /* .window-content couvre la quasi-totalité d'une fenêtre (tout sauf la
           fine barre de titre) et utilisait un fond OPAQUE (--bg-desktop, sans
           canal alpha) non concerné par l'override ci-dessus : c'est ce qui
           masquait l'essentiel de l'effet vitre même à forte intensité. */
        body.glass-on .window-content {
            background: hsla(var(--hue), calc(15% * var(--sat, 80) / 80), 9%, var(--sys-glass-alpha, 0.4));
        }
        /* Même souci pour les apps Lecteur MP3 et Vidéo : elles posent un
           conteneur plein cadre (.mp3-container/.vid-container) par-dessus
           .window-content, avec son propre fond opaque. On le laisse
           transparent plutôt que d'ajouter une 3e couche teintée (qui
           s'empilerait sur .window + .window-content et donnerait un résultat
           plus terne, pas plus transparent) : le flou/la teinte de
           .window-content suffit et reste visible au travers.  */
        /* Même souci pour les autres apps qui posent un conteneur plein cadre
           par-dessus .window-content avec un fond opaque codé en dur : Lecteur
           MP3/Vidéo, Terminal (classe réutilisée par l'app Eliza), Calculatrice,
           et Horloge (classe réutilisée par le Chronomètre). Transparent plutôt
           qu'une 3e couche teintée, pour la même raison que ci-dessus : le
           flou/la teinte de .window-content suffit et reste visible au travers.
           Vérifié pour toutes les autres apps : Explorateur/Todo/Convertisseur/
           Webcam/Visionneuse utilisent déjà var(--bg-window) (donc déjà
           "vitre-compatibles" automatiquement) ; P2P/Chat redirigent leur
           variable interne --bg vers var(--bg-window) (idem) ; Crypto/Démineur/
           Météo/Mots de passe/Xeyes n'ont aucun fond propre (déjà transparents,
           laissent voir .window-content) ; les Post-it gardent volontairement
           leur couleur de papier opaque (--note-color), non concernés. */
        body.glass-on .mp3-container,
        body.glass-on .vid-container,
        body.glass-on .terminal-wrap,
        body.glass-on .calc-container,
        body.glass-on .clock-container {
            background: transparent;
        }
        /* Le commentaire ci-dessus indiquait les Post-it comme "non
           concernés" par le mode vitre, mais body.glass-on .window-content
           (spécificité 0,0,2,1 grâce au sélecteur d'élément body) l'emportait
           en réalité sur .sticky-note-window .window-content (0,0,2,0), ce
           qui délavait leur couleur de papier. Cette règle plus spécifique
           restaure l'opacité voulue. */
        body.glass-on .sticky-note-window .window-content {
            background: var(--note-color, #fff3a0);
        }
        .title-bar { height: 32px; background: var(--bg-titlebar); display: flex; align-items: center; justify-content: space-between; padding-left: 10px; flex-shrink: 0; cursor: default; touch-action: none; border-radius: 6px 6px 0 0; transition: background 0.6s ease; }
        .title-bar .title { font-size: 0.8125rem; color: var(--text-secondary); pointer-events: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
        .window-controls { display: flex; height: 100%; }
        .window-controls button { width: 46px; height: 100%; border: none; background: transparent; color: var(--text-secondary); cursor: pointer; font-size: 0.875rem; display: flex; align-items: center; justify-content: center; transition: background 0.2s; }
        .window-controls button:hover { background: rgba(255,255,255,0.1); color: white; }
        .window-controls .close-btn:hover { background: var(--danger); }
        .window-content { flex: 1; padding: 0; overflow: auto; background: var(--bg-desktop); color: var(--text-primary); display: flex; flex-direction: column; transition: background 0.6s ease; }

        .resize-handle { position: absolute; z-index: 10; }
        .resize-handle.n { top: -3px; left: 10px; right: 10px; height: 6px; cursor: n-resize; }
        .resize-handle.s { bottom: -3px; left: 10px; right: 10px; height: 6px; cursor: s-resize; }
        .resize-handle.e { right: -3px; top: 10px; bottom: 10px; width: 6px; cursor: e-resize; }
        .resize-handle.w { left: -3px; top: 10px; bottom: 10px; width: 6px; cursor: w-resize; }
        .resize-handle.ne { top: -3px; right: -3px; width: 12px; height: 12px; cursor: ne-resize; }
        .resize-handle.nw { top: -3px; left: -3px; width: 12px; height: 12px; cursor: nw-resize; }
        .resize-handle.se { bottom: -3px; right: -3px; width: 12px; height: 12px; cursor: se-resize; }
        .resize-handle.sw { bottom: -3px; left: -3px; width: 12px; height: 12px; cursor: sw-resize; }

        /* Bloc-notes */
        .notepad-menu-bar { display: flex; background: var(--bg-taskbar); border-bottom: 1px solid var(--border-color); position: relative; z-index: 20; transition: background 0.6s ease; flex-shrink: 0; }
        .notepad-menu-item { padding: 4px 12px; font-size: 0.8125rem; cursor: pointer; position: relative; color: var(--text-secondary); user-select: none; }
        .notepad-menu-item:hover, .notepad-menu-item.active { background: rgba(255,255,255,0.1); color: var(--text-primary); }
        .notepad-dropdown { display: none; position: absolute; top: 100%; left: 0; background: var(--bg-menu); border: 1px solid var(--border-color); min-width: 220px; box-shadow: 0 5px 15px rgba(0,0,0,0.5); z-index: 50; padding: 4px 0; border-radius: 4px; }
        .notepad-dropdown.show { display: block; }
        .notepad-dropdown-item { padding: 7px 14px 7px 30px; font-size: 0.8125rem; cursor: pointer; color: var(--text-primary); display: flex; align-items: center; justify-content: space-between; gap: 16px; white-space: nowrap; position: relative; }
        .notepad-dropdown-item:hover { background: var(--accent); color: #fff; }
        .notepad-dropdown-item:hover .notepad-shortcut { color: rgba(255,255,255,0.75); }
        .notepad-dropdown-item .notepad-check { position: absolute; left: 10px; opacity: 0; font-size: 0.75rem; }
        .notepad-dropdown-item.checked .notepad-check { opacity: 1; }
        .notepad-shortcut { font-size: 0.6875rem; color: var(--text-secondary); }
        .notepad-dropdown-sep { height: 1px; background: var(--border-color); margin: 4px 8px; }

        /* Sous-menu en flyout (ex: Image > Modification de l'image) : un item de
           dropdown peut lui-même contenir un second .notepad-dropdown, révélé au survol
           et accroché à son bord droit (left:100%) sans espace mort, pour que la souris
           puisse glisser du déclencheur vers le sous-menu sans que :hover ne se perde en
           chemin. */
        .notepad-dropdown-item.notepad-has-submenu > .notepad-submenu-arrow { color: var(--text-secondary); font-size: 0.8125rem; margin-left: -6px; }
        .notepad-dropdown-item.notepad-has-submenu:hover > .notepad-submenu-arrow { color: rgba(255,255,255,0.75); }
        .notepad-dropdown.notepad-submenu { top: -5px; left: 100%; margin-left: 2px; }
        .notepad-dropdown-item.notepad-has-submenu:hover > .notepad-dropdown.notepad-submenu { display: block; }

        .notepad-findbar { display: none; align-items: center; gap: 6px; padding: 6px 10px; background: var(--bg-taskbar); border-bottom: 1px solid var(--border-color); flex-shrink: 0; transition: background 0.6s ease, border-color 0.6s ease; }
        .notepad-findbar.show { display: flex; }
        .notepad-findbar input { flex: 1; background: rgba(0,0,0,0.25); border: 1px solid var(--border-color); color: var(--text-primary); font-size: 0.8125rem; padding: 5px 10px; border-radius: 4px; outline: none; }
        .notepad-findbar input:focus { border-color: var(--accent); }
        .notepad-find-count { font-size: 0.6875rem; color: var(--text-secondary); min-width: 60px; text-align: center; white-space: nowrap; }
        .notepad-find-btn { background: none; border: 1px solid var(--border-color); color: var(--text-secondary); width: 26px; height: 26px; border-radius: 4px; cursor: pointer; font-size: 0.75rem; display: flex; align-items: center; justify-content: center; transition: background 0.15s, color 0.15s; }
        .notepad-find-btn:hover { background: rgba(255,255,255,0.08); color: var(--text-primary); }
        .notepad-find-btn.close-find:hover { color: var(--danger); }

        .notepad-editor-wrap { flex: 1; display: flex; overflow: hidden; background: rgba(0,0,0,0.2); }
        .notepad-gutter { flex-shrink: 0; overflow: hidden; background: rgba(0,0,0,0.18); border-right: 1px solid var(--border-color); padding: 10px 0; text-align: right; user-select: none; transition: background 0.6s ease, border-color 0.6s ease; }
        .notepad-gutter { font-size: 0.875rem; }
        .notepad-gutter .gutter-line { padding: 0 10px; font-family: Consolas, monospace; font-size: inherit; line-height: 1.5; color: var(--text-secondary); opacity: 0.55; box-sizing: border-box; }
        .notepad-gutter .gutter-line.current { color: var(--accent); opacity: 1; font-weight: 700; }
        .notepad-textarea { flex: 1; background: transparent; color: #d4d4d4; border: none; padding: 10px 14px; resize: none; outline: none; font-family: Consolas, monospace; font-size: 0.875rem; line-height: 1.5; overflow-y: auto; }
        .notepad-textarea.nowrap { white-space: pre; overflow-x: auto; }
        .notepad-textarea:not(.nowrap) { white-space: pre-wrap; word-wrap: break-word; overflow-wrap: anywhere; overflow-x: hidden; }
        .notepad-mirror { position: absolute; top: 0; left: -99999px; visibility: hidden; white-space: pre-wrap; word-wrap: break-word; overflow-wrap: anywhere; padding: 0; margin: 0; border: none; }

        .notepad-status { background: var(--bg-taskbar); padding: 4px 12px; border-top: 1px solid var(--border-color); font-size: 0.6875rem; color: var(--text-secondary); display: flex; align-items: center; gap: 16px; flex-shrink: 0; transition: background 0.6s ease; }
        .notepad-status .status-pos { min-width: 90px; }
        .notepad-status .status-fill { flex: 1; }
        .notepad-status span.dim { opacity: 0.7; }
        /* min-width:0 indispensable pour que text-overflow agisse : un flex-item garde
           sinon la largeur de son contenu comme plancher implicite et pousse le reste de
           la barre (curseur/zoom) hors champ sur une fenêtre Peinture étroite plutôt que
           de se tronquer lui-même. */
        .paint-status-tip { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

        .settings-container { padding: 20px; display: flex; flex-direction: column; gap: 25px; overflow-y: auto; }
        .setting-group { background: rgba(255,255,255,0.03); padding: 15px; border-radius: 6px; border: 1px solid var(--border-color); transition: all 0.6s ease; }
        .setting-group h3 { margin-bottom: 15px; font-size: 1rem; color: var(--accent); border-bottom: 1px solid var(--border-color); padding-bottom: 8px; transition: color 0.6s ease; }
        .setting-row { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; flex-wrap: wrap; row-gap: 10px; column-gap: 10px; }
        .setting-row:last-child { margin-bottom: 0; }
        .setting-label { font-size: 0.875rem; color: var(--text-primary); }
        .color-presets { display: flex; gap: 10px; flex-wrap: wrap; }
        .color-btn { width: 30px; height: 30px; border-radius: 50%; border: 2px solid transparent; cursor: pointer; transition: transform 0.2s; }
        .color-btn:hover { transform: scale(1.2); }
        .color-btn.active { border-color: #fff; box-shadow: 0 0 10px rgba(255,255,255,0.5), 0 0 calc(4px * var(--sys-glow, 0.55)) var(--accent), 0 0 calc(12px * var(--sys-glow, 0.55)) var(--accent); }
        /* Pastille "couleur personnalisée" (<input type="color">) : réutilise .color-btn
           pour la taille, mais reset le chrome natif de l'input pour qu'elle ressemble à
           une pastille ronde classique plutôt qu'au widget natif du navigateur. */
        .color-btn-custom { -webkit-appearance: none; -moz-appearance: none; appearance: none; padding: 0; background: none; }
        .color-btn-custom::-webkit-color-swatch-wrapper { padding: 0; border-radius: 50%; }
        .color-btn-custom::-webkit-color-swatch { border: none; border-radius: 50%; }
        .color-btn-custom::-moz-color-swatch { border: none; border-radius: 50%; }

        .wave-slider-row { display: flex; flex-direction: column; gap: 8px; }
        .wave-slider-row:not(:last-child) { margin-bottom: 4px; }
        .wave-slider-head { display: flex; justify-content: space-between; align-items: center; font-size: 0.8125rem; }
        .wave-slider-icon { font-size: 0.9375rem; margin-right: 6px; opacity: 0.85; }
        .wave-slider-value { font-variant-numeric: tabular-nums; color: var(--accent); font-weight: 600; background: hsla(var(--hue), calc(40% * var(--sat, 80) / 80), 50%, 0.15); padding: 2px 9px; border-radius: 20px; min-width: 42px; text-align: center; transition: background 0.6s ease, color 0.6s ease; }

        input[type="range"].wave-slider {
            -webkit-appearance: none; appearance: none;
            width: 100%; height: 8px; border-radius: 999px; outline: none; cursor: pointer;
            background: linear-gradient(to right,
                hsl(var(--hue), calc(80% * var(--sat, 80) / 80), 55%) 0%,
                hsl(var(--hue), calc(80% * var(--sat, 80) / 80), 55%) var(--range-progress, 50%),
                hsla(var(--hue), calc(15% * var(--sat, 80) / 80), 40%, 0.35) var(--range-progress, 50%),
                hsla(var(--hue), calc(15% * var(--sat, 80) / 80), 40%, 0.35) 100%);
            transition: background-color 0.6s ease;
        }
        input[type="range"].wave-slider::-webkit-slider-thumb {
            -webkit-appearance: none; appearance: none;
            width: 20px; height: 20px; border-radius: 50%;
            background: #fff; border: 3px solid hsl(var(--hue), calc(80% * var(--sat, 80) / 80), 55%);
            box-shadow: 0 0 0 4px hsla(var(--hue), calc(80% * var(--sat, 80) / 80), 55%, 0.18), 0 2px 6px rgba(0,0,0,0.5), 0 0 calc(3px * var(--sys-glow, 0.55)) var(--accent), 0 0 calc(9px * var(--sys-glow, 0.55)) var(--accent);
            cursor: pointer; transition: transform 0.15s ease, box-shadow 0.2s ease;
        }
        input[type="range"].wave-slider::-webkit-slider-thumb:hover { transform: scale(1.15); }
        input[type="range"].wave-slider::-webkit-slider-thumb:active { transform: scale(1.3); box-shadow: 0 0 0 7px hsla(var(--hue), calc(80% * var(--sat, 80) / 80), 55%, 0.25), 0 2px 8px rgba(0,0,0,0.6); }
        input[type="range"].wave-slider::-moz-range-track { height: 8px; border-radius: 999px; background: hsla(var(--hue), calc(15% * var(--sat, 80) / 80), 40%, 0.35); }
        input[type="range"].wave-slider::-moz-range-progress { height: 8px; border-radius: 999px; background: hsl(var(--hue), calc(80% * var(--sat, 80) / 80), 55%); }
        input[type="range"].wave-slider::-moz-range-thumb {
            width: 20px; height: 20px; border-radius: 50%; background: #fff;
            border: 3px solid hsl(var(--hue), calc(80% * var(--sat, 80) / 80), 55%);
            box-shadow: 0 0 0 4px hsla(var(--hue), calc(80% * var(--sat, 80) / 80), 55%, 0.18), 0 2px 6px rgba(0,0,0,0.5), 0 0 calc(3px * var(--sys-glow, 0.55)) var(--accent), 0 0 calc(9px * var(--sys-glow, 0.55)) var(--accent);
            cursor: pointer; transition: transform 0.15s ease;
        }
        input[type="range"].wave-slider::-moz-range-thumb:hover { transform: scale(1.15); }
        .wave-slider-ticks { display: flex; justify-content: space-between; padding: 0 2px; font-size: 0.625rem; color: var(--text-secondary); opacity: 0.7; }

        /* Éditeur de groupes du fond "Vie de particules" (Réglages > Fond d'écran,
           voir settings-app.js) : une boîte par groupe (Bleu/Orange/Leader), reprend
           le style de .paint-newdlg-row pour les champs numériques. */
        .pl-group-box { background: rgba(255,255,255,0.04); border: 1px solid var(--border-color); border-radius: 8px; padding: 10px 12px; margin-top: 14px; }
        .pl-group-box:first-child { margin-top: 0; }
        .pl-group-title { margin: 0 0 8px 0; font-size: 0.8125rem; font-weight: 600; color: var(--accent); }
        .pl-group-row { display: flex; gap: 10px; margin-bottom: 8px; }
        .pl-group-row:last-child { margin-bottom: 0; }
        .pl-group-row label { display: flex; flex-direction: column; gap: 3px; font-size: 0.6875rem; color: var(--text-secondary); flex: 1; }
        .pl-group-row input[type="number"] {
            background: var(--bg-desktop);
            border: 1px solid var(--border-color);
            border-radius: 6px;
            color: var(--text-primary);
            padding: 5px 7px;
            font-family: inherit;
            font-size: 0.75rem;
            width: 100%;
        }
        .pl-group-row input[type="color"] { width: 100%; height: 28px; padding: 2px; border: 1px solid var(--border-color); border-radius: 6px; background: var(--bg-desktop); cursor: pointer; }
        .pl-reset-btn { display: block; margin: 16px auto 0; padding: 8px 18px; font-size: 0.75rem; cursor: pointer; background: var(--bg-desktop); border: 1px solid var(--border-color); border-radius: 6px; color: var(--text-primary); transition: 0.15s; }
        .pl-reset-btn:hover { border-color: var(--accent); color: var(--accent); }

        /* Rangée "Préréglages" (combobox de chargement + suppression) du fond
           "Vie de particules" — voir particleLifePresetsHtml() dans settings-app.js. */
        .pl-preset-row { display: flex; gap: 8px; align-items: center; }
        .pl-preset-select { flex: 1; min-width: 0; }
        #pt-preset-delete { flex: 0 0 auto; padding: 7px 11px; }
        #pt-preset-delete:disabled { opacity: 0.35; cursor: not-allowed; }
        #pt-preset-delete:disabled:hover { background: transparent; }

        /* Matrice de forces (une mini-slider par case, remplace les anciens
           <input type="number">) — voir la boucle pl-matrix-row dans
           particleLifeGroupsHtml() / bindParticleLifeGroups() de settings-app.js. */
        .pl-matrix-block { margin-top: 4px; padding-top: 8px; border-top: 1px solid var(--border-color); }
        .pl-matrix-row { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; }
        .pl-matrix-row:last-child { margin-bottom: 0; }
        .pl-matrix-label { flex: 0 0 auto; width: 96px; font-size: 0.625rem; color: var(--text-secondary); line-height: 1.2; }
        input[type="range"].pl-matrix-slider { flex: 1; min-width: 0; height: 4px; }
        input[type="range"].pl-matrix-slider::-webkit-slider-thumb { width: 14px; height: 14px; border-width: 2px; }
        input[type="range"].pl-matrix-slider::-moz-range-thumb { width: 14px; height: 14px; border-width: 2px; }
        .pl-matrix-value { flex: 0 0 auto; width: 38px; text-align: right; font-variant-numeric: tabular-nums; font-size: 0.6875rem; color: var(--accent); }

        .toggle-switch { position: relative; display: inline-block; width: 50px; height: 24px; }
        .toggle-switch input { opacity: 0; width: 0; height: 0; }
        .toggle-slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #444; transition: .4s; border-radius: 24px; }
        .toggle-slider:before { position: absolute; content: ""; height: 18px; width: 18px; left: 3px; bottom: 3px; background-color: white; transition: .4s; border-radius: 50%; }
        input:checked + .toggle-slider { background-color: var(--accent); box-shadow: 0 0 calc(3px * var(--sys-glow, 0.55)) var(--accent), 0 0 calc(10px * var(--sys-glow, 0.55)) var(--accent); }
        input:checked + .toggle-slider:before { transform: translateX(26px); }

        /* Réglages : shell à onglets (barre latérale + zone de contenu) */
        .settings-shell { flex: 1; display: flex; min-height: 0; }
        .settings-sidebar { width: 190px; flex-shrink: 0; background: var(--bg-titlebar); border-right: 1px solid var(--border-color); overflow-y: auto; padding: 10px 8px; display: flex; flex-direction: column; gap: 3px; transition: background 0.6s ease, border-color 0.6s ease; }
        .settings-tab-btn { display: flex; align-items: center; gap: 10px; padding: 9px 11px; border-radius: 6px; cursor: pointer; color: var(--text-secondary); font-size: 0.8125rem; background: transparent; border: none; text-align: left; width: 100%; font-family: inherit; transition: background 0.15s ease, color 0.15s ease; }
        .settings-tab-btn svg { width: 17px; height: 17px; flex-shrink: 0; }
        .settings-tab-btn span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
        .settings-tab-btn:hover { background: rgba(255,255,255,0.06); color: var(--text-primary); }
        .settings-tab-btn.active { background: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 50%, 0.18); color: var(--accent); }
        .settings-shell > .settings-container { flex: 1; min-width: 0; }

        body.theme-3d .settings-sidebar { box-shadow: inset -1px 0 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 0%, 0.5); }
        body.theme-3d .settings-tab-btn.active { box-shadow: inset 1px 1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 50%, 0.25), inset -1px -1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 0%, 0.5); }

        /* App "Mes Fichiers" */
        .files-shell { flex: 1; display: flex; flex-direction: column; min-height: 0; background: var(--bg-window); transition: background 0.6s ease; }
        .files-toolbar { display: flex; align-items: center; gap: 4px; padding: 8px 10px; border-bottom: 1px solid var(--border-color); flex-shrink: 0; transition: border-color 0.6s ease; }
        .files-tool-btn { display: flex; align-items: center; gap: 6px; padding: 6px 10px; border-radius: 6px; border: none; background: transparent; color: var(--text-secondary); cursor: pointer; font-size: 0.75rem; font-family: inherit; transition: background 0.15s ease, color 0.15s ease; }
        .files-tool-btn svg { width: 16px; height: 16px; flex-shrink: 0; }
        .files-tool-btn:hover:not(:disabled) { background: rgba(255,255,255,0.07); color: var(--text-primary); }
        .files-tool-btn:disabled { opacity: 0.35; cursor: default; }
        .files-tool-btn.files-tool-danger:hover:not(:disabled) { color: var(--danger); background: hsla(0, 70%, 50%, 0.12); }
        .files-tool-sep { width: 1px; height: 20px; background: var(--border-color); margin: 0 4px; }
        .files-tool-fill { flex: 1; }

        .files-breadcrumb { display: flex; align-items: center; gap: 4px; padding: 8px 12px; border-bottom: 1px solid var(--border-color); flex-shrink: 0; font-size: 0.75rem; overflow-x: auto; transition: border-color 0.6s ease; }
        .files-crumb { display: flex; align-items: center; gap: 5px; background: transparent; border: none; color: var(--text-secondary); cursor: pointer; font-family: inherit; font-size: 0.75rem; padding: 3px 7px; border-radius: 5px; white-space: nowrap; transition: background 0.15s ease, color 0.15s ease; }
        .files-crumb svg { width: 14px; height: 14px; }
        .files-crumb:hover { background: rgba(255,255,255,0.06); color: var(--text-primary); }
        .files-crumb.active { color: var(--accent); font-weight: 600; }
        .files-crumb-sep { color: var(--text-secondary); opacity: 0.5; }

        .files-list { flex: 1; overflow-y: auto; padding: 4px 6px; }
        .files-row { display: grid; grid-template-columns: 22px 1fr 70px 90px; align-items: center; gap: 10px; padding: 7px 8px; border-radius: 6px; cursor: default; font-size: 0.8125rem; color: var(--text-primary); transition: background 0.12s ease; }
        .files-row:hover { background: rgba(255,255,255,0.04); }
        .files-row.selected { background: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 50%, 0.18); }
        .files-row-icon { display: flex; color: var(--text-secondary); }
        .files-row-icon svg { width: 18px; height: 18px; }
        .files-row-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
        .files-row-size, .files-row-date { font-size: 0.6875rem; color: var(--text-secondary); text-align: right; white-space: nowrap; }
        .files-empty { padding: 30px 10px; text-align: center; color: var(--text-secondary); font-size: 0.8125rem; }

        .files-footer { display: flex; align-items: center; padding: 6px 12px; border-top: 1px solid var(--border-color); font-size: 0.6875rem; color: var(--text-secondary); flex-shrink: 0; transition: border-color 0.6s ease; }

        body.theme-3d .files-toolbar, body.theme-3d .files-breadcrumb, body.theme-3d .files-footer { box-shadow: inset 0 -1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 0%, 0.4); border-color: transparent; }
        body.theme-3d .files-row.selected { box-shadow: inset 1px 1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 50%, 0.25), inset -1px -1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 0%, 0.5); }

        /* App "Post-it" — reskin complet de la fenêtre générique pour ressembler à
           un vrai Post-it (le drag/z-index/fermeture du WindowManager restent
           utilisés tels quels, seul l'habillage visuel change). Volontairement
           indépendant du thème 3D de l'OS (!important) : une note autocollante n'a
           pas vocation à ressembler au chrome des fenêtres classiques. */
        .sticky-note-window {
            border-radius: 2px 0px 2px 2px !important;
            border: none !important;
            box-shadow: 3px 6px 16px rgba(0,0,0,0.35), 0 1px 2px rgba(0,0,0,0.2) !important;
            transition: transform 0.18s ease, box-shadow 0.18s ease;
        }
        .sticky-note-window:hover { transform: rotate(0deg) !important; box-shadow: 4px 10px 24px rgba(0,0,0,0.4), 0 2px 4px rgba(0,0,0,0.22) !important; }
        .sticky-note-window .title-bar { height: 22px; background: rgba(0,0,0,0.08) !important; border-radius: 0 !important; padding: 0 4px; cursor: grab; box-shadow: none !important; }
        .sticky-note-window .title-bar:active { cursor: grabbing; }
        .sticky-note-window .title { display: none; }
        .sticky-note-window .min-btn, .sticky-note-window .max-btn { display: none; }
        .sticky-note-window .close-btn {
            opacity: 0; transition: opacity 0.15s ease; background: rgba(0,0,0,0.2) !important;
            color: rgba(255,255,255,0.95) !important; font-size: 0.6875rem !important; width: 18px !important; height: 18px !important;
            border-radius: 50% !important;
        }
        .sticky-note-window:hover .close-btn { opacity: 1; }
        .sticky-note-window .close-btn:hover { background: rgba(0,0,0,0.4) !important; }
        .sticky-note-window .window-content { background: var(--note-color, #fff3a0); position: relative; overflow: hidden; }
        /* Coin corné, effet papier — classique des post-it virtuels */
        .sticky-note-window::after {
            content: ''; position: absolute; bottom: 0; right: 0; width: 0; height: 0;
            border-style: solid; border-width: 0 0 16px 16px;
            border-color: transparent transparent rgba(0,0,0,0.13) transparent;
            pointer-events: none; z-index: 2;
        }
        .sn-palette { display: flex; align-items: center; gap: 4px; padding: 0 4px; opacity: 0; transition: opacity 0.15s ease; }
        .sticky-note-window:hover .sn-palette { opacity: 1; }
        .sn-swatch { width: 11px; height: 11px; border-radius: 50%; cursor: pointer; border: 1px solid rgba(0,0,0,0.15); flex-shrink: 0; padding: 0; margin: 0; -webkit-appearance: none; appearance: none; font: inherit; transition: transform 0.1s ease; }
        .sn-swatch:hover { transform: scale(1.25); }
        .sn-textarea {
            width: 100%; height: 100%; border: none; outline: none; resize: none; background: transparent;
            padding: 10px 12px; box-sizing: border-box; font-family: 'Segoe Print', 'Bradley Hand', 'Comic Sans MS', cursive, sans-serif;
            font-size: 0.9062rem; line-height: 1.4; color: rgba(0,0,0,0.78);
        }
        .sn-textarea::placeholder { color: rgba(0,0,0,0.35); }

        /* ==================================================================
           App "Liste de tâches" — refonte visuelle complète.
           Principes : la sidebar a ses propres classes (elle n'emprunte plus
           .settings-tab-btn, pensé pour des réglages, pas des listes avec
           avancement) ; chaque "gadget" (anneau de progression, pastille de
           date) a un espace dédié et prévisible au lieu de flotter sans
           style dans le flux ; le champ <input type="date"> natif reste
           fonctionnel mais invisible, superposé à une pastille stylée (même
           technique que la case à cocher juste en dessous).
           ================================================================== */
        .todo-shell { flex: 1; display: flex; min-height: 0; background: var(--bg-window); }

        /* ---- Sidebar : listes ---- */
        .todo-sidebar { width: 200px; flex-shrink: 0; background: var(--bg-titlebar); border-right: 1px solid var(--border-color); overflow-y: auto; padding: 12px 10px; display: flex; flex-direction: column; gap: 4px; transition: background 0.6s ease, border-color 0.6s ease; }
        .todo-newlist-btn { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-radius: 7px; border: 1px dashed var(--border-color); background: transparent; color: var(--text-secondary); font-size: 0.75rem; font-family: inherit; cursor: pointer; transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease; margin-bottom: 4px; }
        .todo-newlist-btn svg { width: 15px; height: 15px; flex-shrink: 0; }
        .todo-newlist-btn:hover { background: rgba(255,255,255,0.06); color: var(--accent); border-color: var(--accent); }
        .todo-sidebar-sep { height: 1px; background: var(--border-color); margin: 4px 2px 8px; flex-shrink: 0; }
        .todo-list-btn { display: flex; align-items: center; gap: 9px; padding: 8px 9px; border-radius: 7px; border: none; background: transparent; color: var(--text-secondary); font-family: inherit; font-size: 0.8125rem; text-align: left; cursor: pointer; width: 100%; transition: background 0.15s ease, color 0.15s ease; }
        .todo-list-btn:hover { background: rgba(255,255,255,0.06); color: var(--text-primary); }
        .todo-list-btn.active { background: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 50%, 0.18); color: var(--accent); }
        .todo-list-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
        /* Anneau de progression en pur CSS (conic-gradient + masque interne en
           forme de disque) : évite de générer du SVG dynamique par liste. */
        .todo-ring { position: relative; width: 22px; height: 22px; flex-shrink: 0; border-radius: 50%; background: conic-gradient(var(--accent) calc(var(--pct, 0) * 1%), rgba(255,255,255,0.14) 0); transition: background 0.25s ease; }
        .todo-ring::after { content: ''; position: absolute; inset: 3px; border-radius: 50%; background: var(--bg-titlebar); transition: background 0.6s ease; }
        .todo-list-btn.active .todo-ring::after { background: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 22%, 1); }
        .todo-ring-count { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 0.5rem; font-weight: 700; color: var(--text-primary); }
        .todo-empty-lists { color: var(--text-secondary); font-size: 0.75rem; text-align: center; padding: 16px 8px; }

        /* ---- Panneau principal ---- */
        .todo-main { flex: 1; min-width: 0; padding: 18px 22px; display: flex; flex-direction: column; gap: 14px; overflow: hidden; }
        .todo-header { display: flex; align-items: center; gap: 8px; }
        .todo-list-name { flex: 1; min-width: 0; padding: 8px 10px; font-size: 1.0625rem; font-weight: 600; background: transparent; border: 1px solid transparent; border-radius: 7px; color: var(--text-primary); font-family: inherit; }
        .todo-list-name:hover, .todo-list-name:focus { background: var(--bg-desktop); border-color: var(--border-color); outline: none; }
        .todo-progress-track { height: 5px; border-radius: 3px; background: rgba(255,255,255,0.08); overflow: hidden; flex-shrink: 0; }
        .todo-progress-fill { height: 100%; border-radius: 3px; background: var(--accent); transition: width 0.3s ease; }
        .todo-add-row { display: flex; gap: 8px; }
        .todo-add-input { flex: 1; min-width: 0; padding: 10px 13px; background: var(--bg-desktop); border: 1px solid var(--border-color); border-radius: 8px; color: var(--text-primary); font-family: inherit; font-size: 0.8125rem; }
        .todo-add-input:focus { outline: none; border-color: var(--accent); }
        .todo-add-btn { flex-shrink: 0; width: 38px; height: 38px; display: flex; align-items: center; justify-content: center; border: none; border-radius: 8px; background: var(--accent); color: #fff; cursor: pointer; transition: filter 0.15s ease, transform 0.1s ease; }
        .todo-add-btn svg { width: 18px; height: 18px; }
        .todo-add-btn:hover { filter: brightness(1.1); }
        .todo-add-btn:active { transform: scale(0.94); }

        .todo-items { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; }
        .todo-item { display: flex; align-items: center; gap: 10px; padding: 9px 8px; border-radius: 7px; }
        .todo-item:hover { background: rgba(255,255,255,0.03); }
        .todo-item:hover .todo-item-remove { opacity: 1; }
        .todo-checkbox { position: relative; width: 18px; height: 18px; flex-shrink: 0; cursor: pointer; }
        .todo-checkbox input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
        .todo-checkbox span { position: absolute; inset: 0; border: 1.5px solid var(--border-color); border-radius: 5px; transition: background 0.15s ease, border-color 0.15s ease; }
        .todo-checkbox span::after { content: ''; position: absolute; left: 5px; top: 1px; width: 5px; height: 9px; border: solid white; border-width: 0 2px 2px 0; transform: rotate(45deg); opacity: 0; }
        .todo-checkbox input:checked + span { background: var(--accent); border-color: var(--accent); }
        .todo-checkbox input:checked + span::after { opacity: 1; }
        .todo-item-text { flex: 1; min-width: 0; font-size: 0.8438rem; color: var(--text-primary); outline: none; padding: 3px 5px; border-radius: 4px; word-break: break-word; }
        .todo-item-text:focus { background: var(--bg-desktop); }
        .todo-item.done .todo-item-text { color: var(--text-secondary); text-decoration: line-through; }

        /* Pastille de date : le <input type="date"> natif est étiré en
           position absolute par-dessus, opacité 0, cursor pointer -> clic
           n'importe où sur la pastille ouvre le sélecteur natif du
           navigateur, sans jamais afficher son rendu brut non stylé. */
        .todo-date-pill { position: relative; flex-shrink: 0; display: flex; align-items: center; gap: 5px; padding: 4px 9px; border-radius: 20px; font-size: 0.6875rem; color: var(--text-secondary); background: rgba(255,255,255,0.06); border: 1px solid transparent; cursor: pointer; transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease; white-space: nowrap; }
        .todo-date-pill:hover { background: rgba(255,255,255,0.1); }
        .todo-date-pill svg { width: 12px; height: 12px; flex-shrink: 0; opacity: 0.8; }
        .todo-date-input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; margin: 0; padding: 0; border: none; }
        .todo-date-pill[data-status="today"] { color: var(--accent); background: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 55%, 0.16); border-color: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 55%, 0.35); }
        .todo-date-pill[data-status="overdue"] { color: var(--danger); background: hsla(0, 70%, 50%, 0.14); border-color: hsla(0, 70%, 50%, 0.35); }
        .todo-item.done .todo-date-pill { opacity: 0.55; }
        .todo-item-remove { flex-shrink: 0; width: 22px; height: 22px; display: flex; align-items: center; justify-content: center; border: none; background: transparent; color: var(--text-secondary); border-radius: 6px; cursor: pointer; opacity: 0; transition: opacity 0.15s ease, background 0.15s ease, color 0.15s ease; }
        .todo-item-remove svg { width: 13px; height: 13px; }
        .todo-item-remove:hover { background: hsla(0,70%,50%,0.15); color: var(--danger); }

        .todo-footer { display: flex; align-items: center; font-size: 0.7188rem; padding-top: 8px; border-top: 1px solid var(--border-color); }
        .todo-empty { color: var(--text-secondary); font-size: 0.8125rem; text-align: center; padding: 40px 10px; display: flex; flex-direction: column; align-items: center; gap: 10px; }
        .todo-empty svg { width: 40px; height: 40px; opacity: 0.35; }

        /* App "Convertisseur d'unités" */
        .uc-shell { flex: 1; display: flex; min-height: 0; background: var(--bg-window); }
        .uc-main { flex: 1; min-width: 0; padding: 24px; display: flex; flex-direction: column; gap: 14px; overflow-y: auto; }
        .uc-row { display: flex; gap: 8px; }
        .uc-input {
            flex: 1; padding: 10px 12px; font-size: 1.125rem; background: var(--bg-desktop);
            border: 1px solid var(--border-color); border-radius: 8px; color: var(--text-primary); font-family: inherit;
        }
        .uc-input:focus { outline: none; border-color: var(--accent); }
        .uc-select {
            width: 110px; padding: 10px 8px; background: var(--bg-desktop); border: 1px solid var(--border-color);
            border-radius: 8px; color: var(--text-primary); font-family: inherit; font-size: 0.875rem; cursor: pointer;
        }
        /* Même combo box gris que .uc-select (Convertisseur d'unités), mais
           sans largeur fixe : réutilisé dans le panneau de configuration
           (sélecteur de langue, etc.) où le contenu des options varie. */
        .settings-select {
            padding: 10px 8px; background: var(--bg-desktop); border: 1px solid var(--border-color);
            border-radius: 8px; color: var(--text-primary); font-family: inherit; font-size: 0.875rem; cursor: pointer;
        }
        .uc-swap-btn {
            align-self: center; width: 34px; height: 34px; border-radius: 50%; border: 1px solid var(--border-color);
            background: var(--bg-desktop); color: var(--text-secondary); cursor: pointer; display: flex; align-items: center; justify-content: center;
            transition: background 0.15s ease, color 0.15s ease, transform 0.15s ease;
        }
        .uc-swap-btn:hover { background: var(--accent); color: #fff; transform: rotate(180deg); }
        .uc-table-title { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-secondary); margin-top: 10px; }
        .uc-table { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
        .uc-table-row { display: flex; justify-content: space-between; gap: 8px; padding: 8px 10px; background: rgba(255,255,255,0.03); border-radius: 6px; font-size: 0.8125rem; }
        .uc-table-unit { color: var(--text-secondary); }
        .uc-table-value { color: var(--text-primary); font-weight: 600; }

        /* Sous-section "Programmation" du convertisseur d'unités : encodeur/
           décodeur Texte ↔ Binaire ↔ Hexadécimal ↔ Base64, mode Live. */
        .uc-live-row { display: flex; align-items: center; gap: 10px; font-size: 0.8125rem; color: var(--text-secondary); }
        .uc-switch { position: relative; display: inline-block; width: 38px; height: 22px; flex-shrink: 0; cursor: pointer; }
        .uc-switch input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
        .uc-switch span { position: absolute; inset: 0; background: rgba(255,255,255,0.15); border-radius: 22px; transition: background 0.15s ease; pointer-events: none; }
        .uc-switch span::after { content: ''; position: absolute; width: 16px; height: 16px; left: 3px; top: 3px; background: #fff; border-radius: 50%; transition: transform 0.15s ease; }
        .uc-switch input:checked + span { background: var(--accent); }
        .uc-switch input:checked + span::after { transform: translateX(16px); }
        .uc-convert-btn { margin-left: auto; padding: 6px 14px; border-radius: 6px; border: none; background: var(--accent); color: #fff; font-size: 0.8125rem; font-family: inherit; cursor: pointer; }
        .uc-convert-btn:hover { opacity: 0.88; }
        .uc-textarea {
            width: 100%; min-height: 76px; padding: 10px 12px; font-size: 0.8125rem; line-height: 1.45; background: var(--bg-desktop);
            border: 1px solid var(--border-color); border-radius: 8px; color: var(--text-primary); font-family: 'SFMono-Regular', Consolas, Menlo, monospace;
            resize: vertical;
        }
        .uc-textarea:focus { outline: none; border-color: var(--accent); }
        .uc-textarea.uc-textarea-error { border-color: var(--danger); }
        .uc-table.uc-table-enc { grid-template-columns: 1fr; }
        .uc-table-row-enc { flex-direction: column; align-items: flex-start; gap: 4px; }
        .uc-table-row-enc .uc-table-value { font-family: 'SFMono-Regular', Consolas, Menlo, monospace; font-weight: 400; word-break: break-all; }

        /* App "Cam IP Viewer" — gestionnaire de caméras (fenêtre non-singleton :
           le gestionnaire liste les caméras enregistrées, chaque "Ouvrir" lance
           une NOUVELLE fenêtre dédiée à une seule caméra). */
        .camv-shell { flex: 1; display: flex; flex-direction: column; min-height: 0; background: var(--bg-window); }
        .camv-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 14px 16px; border-bottom: 1px solid var(--border-color); flex-shrink: 0; }
        .camv-toolbar-title { font-size: 0.8125rem; color: var(--text-secondary); }
        .camv-add-btn { display: flex; align-items: center; gap: 6px; padding: 8px 14px; border: none; border-radius: 8px; background: var(--accent); color: #fff; font-size: 0.8125rem; font-family: inherit; cursor: pointer; }
        .camv-add-btn:hover { filter: brightness(1.08); }
        .camv-add-btn svg { width: 15px; height: 15px; }
        .camv-list { flex: 1; overflow-y: auto; padding: 10px 12px; display: flex; flex-direction: column; gap: 8px; }
        .camv-empty { color: var(--text-secondary); font-size: 0.8125rem; text-align: center; padding: 50px 16px; display: flex; flex-direction: column; align-items: center; gap: 10px; }
        .camv-empty svg { width: 42px; height: 42px; opacity: 0.35; }
        .camv-empty-hint { font-size: 0.75rem; opacity: 0.8; }
        .camv-row { display: flex; align-items: center; gap: 12px; padding: 10px 12px; background: rgba(255,255,255,0.03); border: 1px solid transparent; border-radius: 10px; transition: background 0.15s ease, border-color 0.15s ease; }
        .camv-row:hover { background: rgba(255,255,255,0.05); border-color: var(--border-color); }
        .camv-row-icon { flex-shrink: 0; width: 34px; height: 34px; border-radius: 8px; background: var(--bg-desktop); display: flex; align-items: center; justify-content: center; color: var(--accent); }
        .camv-row-icon svg { width: 18px; height: 18px; }
        .camv-row-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
        .camv-row-name { font-size: 0.875rem; color: var(--text-primary); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
        .camv-row-url { font-size: 0.75rem; color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-family: 'SFMono-Regular', Consolas, Menlo, monospace; }
        .camv-row-actions { flex-shrink: 0; display: flex; align-items: center; gap: 4px; }
        .camv-row-btn { width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; border: none; background: transparent; color: var(--text-secondary); border-radius: 7px; cursor: pointer; transition: background 0.15s ease, color 0.15s ease; }
        .camv-row-btn svg { width: 15px; height: 15px; }
        .camv-row-btn:hover { background: rgba(255,255,255,0.08); color: var(--text-primary); }
        .camv-row-btn.camv-open:hover { background: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 55%, 0.16); color: var(--accent); }
        .camv-row-btn.camv-danger:hover { background: hsla(0,70%,50%,0.15); color: var(--danger); }

        .camv-form { margin: 10px 12px 0; padding: 14px; background: rgba(255,255,255,0.03); border: 1px solid var(--border-color); border-radius: 10px; display: flex; flex-direction: column; gap: 10px; flex-shrink: 0; }
        .camv-form-title { font-size: 0.8125rem; font-weight: 600; color: var(--text-primary); margin-bottom: 2px; }
        .camv-form-error { font-size: 0.6875rem; color: var(--danger); }
        .camv-form-row { display: flex; flex-direction: column; gap: 5px; }
        .camv-form-row-inline { flex-direction: row; align-items: flex-end; gap: 10px; }
        .camv-form-label { font-size: 0.75rem; color: var(--text-secondary); }
        .camv-input, .camv-select {
            padding: 9px 11px; font-size: 0.8125rem; background: var(--bg-desktop); border: 1px solid var(--border-color);
            border-radius: 7px; color: var(--text-primary); font-family: inherit;
        }
        .camv-input:focus, .camv-select:focus { outline: none; border-color: var(--accent); }
        .camv-input.camv-input-error { border-color: var(--danger); }
        .camv-form-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 2px; }
        .camv-btn { padding: 8px 16px; border-radius: 7px; border: none; font-size: 0.8125rem; font-family: inherit; cursor: pointer; }
        .camv-btn-primary { background: var(--accent); color: #fff; }
        .camv-btn-primary:hover { filter: brightness(1.08); }
        .camv-btn-ghost { background: transparent; color: var(--text-secondary); border: 1px solid var(--border-color); }
        .camv-btn-ghost:hover { color: var(--text-primary); }

        /* Fenêtre de visionnage (une par caméra) */
        .camv-viewer { flex: 1; display: flex; flex-direction: column; min-height: 0; background: var(--bg-window); }
        .camv-viewer-toolbar { display: flex; align-items: center; gap: 6px; padding: 10px 12px; border-bottom: 1px solid var(--border-color); flex-shrink: 0; }
        .camv-viewer-status { display: flex; align-items: center; gap: 6px; font-size: 0.75rem; color: var(--text-secondary); }
        .camv-status-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--text-secondary); flex-shrink: 0; }
        .camv-status-dot.camv-status-ok { background: #4fd167; }
        .camv-status-dot.camv-status-error { background: var(--danger); }
        .camv-status-dot.camv-status-connecting { background: #f5c542; animation: camv-pulse 1s ease-in-out infinite; }
        @keyframes camv-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
        .camv-viewer-fill { flex: 1; }
        .camv-viewer-tool-btn { width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; border: none; background: transparent; color: var(--text-secondary); border-radius: 7px; cursor: pointer; transition: background 0.15s ease, color 0.15s ease; }
        .camv-viewer-tool-btn svg { width: 16px; height: 16px; }
        .camv-viewer-tool-btn:hover { background: rgba(255,255,255,0.08); color: var(--text-primary); }
        .camv-viewer-stage { flex: 1; min-height: 0; background: #0a0a0a; display: flex; align-items: center; justify-content: center; position: relative; overflow: hidden; }
        .camv-viewer-img { max-width: 100%; max-height: 100%; object-fit: contain; display: block; }
        .camv-viewer-placeholder { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; color: var(--text-secondary); font-size: 0.8125rem; text-align: center; padding: 20px; }
        .camv-viewer-placeholder svg { width: 40px; height: 40px; opacity: 0.4; }
        .camv-viewer-retry-btn { padding: 7px 14px; border-radius: 7px; border: 1px solid var(--border-color); background: transparent; color: var(--text-primary); font-size: 0.75rem; font-family: inherit; cursor: pointer; }
        .camv-viewer-retry-btn:hover { background: rgba(255,255,255,0.08); }

        /* App "Visualiseur d'images" */
        .imgv-shell { flex: 1; display: flex; flex-direction: column; min-height: 0; background: var(--bg-window); transition: background 0.6s ease; }
        .imgv-toolbar { display: flex; align-items: center; gap: 4px; padding: 8px 10px; border-bottom: 1px solid var(--border-color); flex-shrink: 0; }
        .imgv-zoom-level { font-size: 0.75rem; color: var(--text-secondary); min-width: 42px; text-align: center; user-select: none; }
        .imgv-canvas {
            flex: 1; position: relative; overflow: hidden; display: flex; align-items: center; justify-content: center;
            cursor: grab; touch-action: none;
            background-image: repeating-conic-gradient(hsl(var(--hue), 8%, 14%) 0% 25%, hsl(var(--hue), 8%, 11%) 0% 50%);
            background-size: 20px 20px;
        }
        .imgv-canvas.panning { cursor: grabbing; }
        .imgv-canvas.dragover { outline: 2px dashed var(--accent); outline-offset: -8px; }
        .imgv-canvas img { user-select: none; -webkit-user-drag: none; will-change: transform; }
        .imgv-empty { color: var(--text-secondary); font-size: 0.8125rem; text-align: center; padding: 20px; pointer-events: none; max-width: 260px; }
        .imgv-footer { display: flex; align-items: center; padding: 6px 12px; border-top: 1px solid var(--border-color); font-size: 0.6875rem; color: var(--text-secondary); flex-shrink: 0; }

        /* UI kit partagé : notifications (toasts) + requesters (dialogues modaux) */
        #ui-notify-stack { position: fixed; right: 16px; bottom: calc(var(--taskbar-height) + 12px); display: flex; flex-direction: column; gap: 10px; z-index: 99960; pointer-events: none; max-width: 340px; }
        .ui-notify {
            pointer-events: auto; position: relative; overflow: hidden; display: flex; gap: 10px; align-items: flex-start;
            background: var(--bg-window); border: 1px solid var(--border-color); border-radius: 10px; padding: 12px 34px 12px 12px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.5); opacity: 0; transform: translateX(24px);
            transition: opacity 0.25s ease, transform 0.25s ease; cursor: default;
        }
        .ui-notify.show { opacity: 1; transform: translateX(0); }
        .ui-notify.hide { opacity: 0; transform: translateX(24px); }
        .ui-notify-icon { flex-shrink: 0; width: 20px; height: 20px; margin-top: 1px; }
        .ui-notify-icon svg { width: 100%; height: 100%; }
        .ui-notify-info .ui-notify-icon { color: var(--accent); }
        .ui-notify-success .ui-notify-icon { color: hsl(140, 65%, 50%); }
        .ui-notify-warning .ui-notify-icon { color: hsl(calc(var(--hue) + 40), 70%, 62%); }
        .ui-notify-error .ui-notify-icon { color: var(--danger); }
        .ui-notify-body { flex: 1; min-width: 0; }
        .ui-notify-title { font-size: 0.8125rem; font-weight: 600; color: var(--text-primary); margin-bottom: 2px; }
        .ui-notify-message { font-size: 0.75rem; color: var(--text-secondary); line-height: 1.4; }
        .ui-notify-actions { display: flex; gap: 8px; margin-top: 8px; }
        .ui-notify-action-btn { padding: 4px 10px; font-size: 0.6875rem; border-radius: 5px; border: 1px solid var(--border-color); background: transparent; color: var(--text-primary); cursor: pointer; font-family: inherit; }
        .ui-notify-action-btn:hover { background: rgba(255,255,255,0.08); }
        .ui-notify-close { position: absolute; top: 8px; right: 8px; width: 18px; height: 18px; border: none; background: transparent; color: var(--text-secondary); cursor: pointer; font-size: 0.625rem; border-radius: 4px; display: flex; align-items: center; justify-content: center; }
        .ui-notify-close:hover { background: rgba(255,255,255,0.08); color: var(--text-primary); }
        .ui-notify-progress { position: absolute; left: 0; bottom: 0; width: 100%; height: 2px; background: rgba(255,255,255,0.08); }
        .ui-notify-progress-bar { height: 100%; background: var(--accent); animation-name: ui-notify-shrink; animation-timing-function: linear; animation-fill-mode: forwards; }
        @keyframes ui-notify-shrink { from { width: 100%; } to { width: 0%; } }

        .ui-requester-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 99950; align-items: center; justify-content: center; opacity: 0; transition: opacity 0.2s ease; }
        .ui-requester-overlay.show { opacity: 1; }
        .ui-requester-box { display: flex; gap: 16px; background: var(--bg-requester); border: 1px solid var(--border-color); border-radius: 10px; padding: 22px; max-width: 380px; box-shadow: 0 20px 60px rgba(0,0,0,0.6); transform: scale(0.95); transition: transform 0.2s ease; }
        /* Variante élargie — utilisée par le requester de renommage, dont le
           champ de saisie bénéficie de plus de place pour les noms de fichiers
           longs. `width` ET `max-width` doivent être redéfinis ensemble : sans
           ça, le `max-width: 380px` de la règle de base continuerait de
           plafonner la largeur réelle. Icône/titre/champ de saisie sont aussi
           agrandis et plus soignés (glow au focus) pour cette variante. */
        /* Boîtes de saisie (_showPrompt, ex: renommage) : contrairement aux
           alertes/confirmations (_showRequester), l'icône n'est pas une large
           colonne latérale mais un petit picto en ligne avec le titre — sinon
           elle grignoterait une bonne partie de la largeur disponible pour le
           champ de saisie, qui doit occuper quasiment toute la largeur de la
           fenêtre. */
        .ui-requester-box.ui-requester-prompt { display: block; }
        .ui-requester-header { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
        .ui-requester-header .ui-requester-icon { width: 22px; height: 22px; flex-shrink: 0; }
        .ui-requester-header .ui-requester-title { margin-bottom: 0; }
        .ui-requester-box.ui-requester-wide { width: min(500px, 92vw); max-width: min(500px, 92vw); padding: 26px; }
        .ui-requester-box.ui-requester-wide .ui-requester-header .ui-requester-icon { width: 26px; height: 26px; }
        .ui-requester-box.ui-requester-wide .ui-requester-title { font-size: 1.0625rem; }
        .ui-requester-box.ui-requester-wide .ui-requester-message { margin-bottom: 20px; }
        .ui-requester-box.ui-requester-wide input.ui-requester-input {
            padding: 13px 15px; font-size: 0.9375rem; border-radius: 8px; margin-bottom: 8px;
            transition: border-color 0.15s ease, box-shadow 0.2s ease;
        }
        .ui-requester-box.ui-requester-wide input.ui-requester-input:focus {
            border-color: var(--accent);
            box-shadow: 0 0 calc(3px * var(--sys-glow, 0.55)) var(--accent), 0 0 calc(10px * var(--sys-glow, 0.55)) var(--accent);
        }
        .ui-requester-overlay.show .ui-requester-box { transform: scale(1); }
        .ui-requester-icon { flex-shrink: 0; width: 28px; height: 28px; color: var(--accent); }
        .ui-requester-icon svg { width: 100%; height: 100%; }
        .ui-requester-warning .ui-requester-icon { color: hsl(calc(var(--hue) + 40), 70%, 62%); }
        .ui-requester-error .ui-requester-icon { color: var(--danger); }
        .ui-requester-success .ui-requester-icon { color: hsl(140, 65%, 50%); }
        .ui-requester-content { flex: 1; min-width: 0; }
        .ui-requester-title { font-size: 0.9375rem; font-weight: 600; color: var(--text-primary); margin-bottom: 6px; }
        .ui-requester-message { font-size: 0.8125rem; color: var(--text-secondary); line-height: 1.5; margin-bottom: 18px; white-space: pre-wrap; }
        .ui-requester-buttons { display: flex; justify-content: flex-end; gap: 8px; flex-wrap: wrap; }
        input.ui-requester-input {
            width: 100%; box-sizing: border-box; padding: 8px 10px; margin-bottom: 6px;
            background: var(--bg-desktop); border: 1px solid var(--border-color); border-radius: 6px;
            color: var(--text-primary); font-family: inherit; font-size: 0.8125rem; outline: none;
            transition: border-color 0.15s ease;
        }
        input.ui-requester-input:focus { border-color: var(--accent); }
        .ui-requester-error { min-height: 15px; font-size: 0.7188rem; color: var(--danger); margin-bottom: 8px; }
        .ui-requester-btn { padding: 7px 16px; border-radius: 6px; border: 1px solid var(--border-color); background: transparent; color: var(--text-primary); cursor: pointer; font-family: inherit; font-size: 0.8125rem; }
        .ui-requester-btn:hover { background: rgba(255,255,255,0.08); }
        .ui-requester-btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
        .ui-requester-btn.primary:hover { filter: brightness(1.1); }
        .ui-requester-btn.danger { color: var(--danger); border-color: var(--danger); }
        .ui-requester-btn.danger:hover { background: hsla(0,70%,50%,0.12); }

        body.theme-3d .ui-notify, body.theme-3d .ui-requester-box { border: none; border-radius: 0; box-shadow: inset 1px 1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 50%, 0.25), inset -1px -1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 0%, 0.5), 0 10px 30px rgba(0,0,0,0.6); }

        /* UI.filePicker() / UI.saveFilePicker() — même overlay que les requesters,
           boîte plus large, avec en-tête iconé + fil d'Ariane en "pilules" + lignes
           à icône sur pastille, pour un rendu plus soigné que le requester générique
           tout en réutilisant strictement les mêmes variables de thème (--accent,
           --hue/--sat, --bg-window/--bg-desktop, --border-color) que le reste de
           l'OS — même mécanique d'apparition (scale) que .ui-requester-box. */
        .ui-filepicker-box { display: flex; flex-direction: column; background: var(--bg-requester); border: 1px solid var(--border-color); border-radius: 12px; padding: 22px; width: 460px; max-width: 90vw; box-shadow: 0 24px 70px rgba(0,0,0,0.65); transform: scale(0.95) translateY(4px); transition: transform 0.2s ease; }
        .ui-requester-overlay.show .ui-filepicker-box { transform: scale(1) translateY(0); }

        .ui-filepicker-header { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
        .ui-filepicker-header-icon { display: flex; align-items: center; justify-content: center; flex-shrink: 0; width: 38px; height: 38px; border-radius: 10px; background: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 50%, 0.16); color: var(--accent); }
        .ui-filepicker-header-icon svg { width: 20px; height: 20px; }
        .ui-filepicker-header .ui-requester-title { margin-bottom: 0; font-size: 1rem; }

        .ui-filepicker-toolbar { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; padding-bottom: 10px; border-bottom: 1px solid var(--border-color); }
        .ui-filepicker-breadcrumb { flex: 1; min-width: 0; display: flex; align-items: center; gap: 2px; overflow-x: auto; }
        .ui-filepicker-crumb { background: transparent; border: none; color: var(--text-secondary); cursor: pointer; font-family: inherit; font-size: 0.75rem; padding: 4px 9px; border-radius: 6px; white-space: nowrap; transition: background 0.15s ease, color 0.15s ease; }
        .ui-filepicker-crumb:hover { background: rgba(255,255,255,0.07); color: var(--text-primary); }
        .ui-filepicker-crumb.active { color: var(--accent); font-weight: 600; background: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 50%, 0.12); }
        .ui-filepicker-sep { color: var(--text-secondary); opacity: 0.4; font-size: 0.75rem; }
        .ui-filepicker-newfolder-btn { flex-shrink: 0; display: flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 7px; border: 1px solid var(--border-color); background: transparent; color: var(--text-secondary); cursor: pointer; transition: background 0.15s ease, color 0.15s ease; }
        .ui-filepicker-newfolder-btn svg { width: 15px; height: 15px; }
        .ui-filepicker-newfolder-btn:hover { background: rgba(255,255,255,0.08); color: var(--text-primary); }

        .ui-filepicker-list { height: 270px; overflow-y: auto; margin-bottom: 14px; padding-right: 2px; }
        .ui-filepicker-row { display: flex; align-items: center; gap: 11px; padding: 8px 9px; border-radius: 8px; cursor: default; font-size: 0.8125rem; color: var(--text-primary); border-left: 2px solid transparent; transition: background 0.12s ease, border-color 0.12s ease; }
        .ui-filepicker-row:hover { background: rgba(255,255,255,0.05); }
        .ui-filepicker-row.selected { background: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 50%, 0.16); border-left-color: var(--accent); }
        .ui-filepicker-icon { display: flex; align-items: center; justify-content: center; flex-shrink: 0; width: 26px; height: 26px; border-radius: 7px; background: rgba(255,255,255,0.05); color: var(--text-secondary); }
        .ui-filepicker-icon svg { width: 15px; height: 15px; }
        .ui-filepicker-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
        .ui-filepicker-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; height: 100%; text-align: center; color: var(--text-secondary); font-size: 0.8125rem; }
        .ui-filepicker-empty svg { width: 40px; height: 40px; opacity: 0.3; }

        .ui-filepicker-newfolder-row { padding: 5px 9px; }
        .ui-filepicker-newfolder-input { flex: 1; min-width: 0; background: var(--bg-desktop); border: 1px solid var(--accent); border-radius: 6px; color: var(--text-primary); font-family: inherit; font-size: 0.8125rem; padding: 5px 8px; outline: none; }

        .ui-filepicker-savebar { margin-bottom: 4px; }
        .ui-filepicker-savebar .ui-requester-input { margin-bottom: 0; }

        body.theme-3d .ui-filepicker-box { border: none; border-radius: 0; box-shadow: inset 1px 1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 50%, 0.25), inset -1px -1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 0%, 0.5), 0 10px 30px rgba(0,0,0,0.6); }
        body.theme-3d .ui-filepicker-header-icon, body.theme-3d .ui-filepicker-icon, body.theme-3d .ui-filepicker-newfolder-btn { border-radius: 0; }

		/* Terminal */
		.terminal-wrap {
			flex:1; display:flex; flex-direction:column;
			position: relative;
			background: hsl(var(--hue), calc(18% * var(--sat, 80) / 80), 5%);
			font-family:'Consolas','Courier New',monospace;
			font-size: 0.8125rem; line-height:1.55; overflow:hidden;
			transition: background 0.6s ease;
		}
		.term-output {
			flex:1; overflow-y:auto; padding:12px 14px;
			white-space:pre-wrap; word-break:break-all;
			user-select: text;
			-webkit-user-select: text;
		}
		/* Le sélecteur universel `* { user-select: none }` du haut de fichier
		   cible directement chaque enfant de .term-output (chaque <span> coloré
		   des commandes, ex: t-yellow) et gagne sur l'héritage, même avec une
		   spécificité plus faible — une valeur directe bat toujours une valeur
		   héritée. Sans cette règle, seul le texte brut hors <span> est
		   sélectionnable, pas les noms de commandes. */
		.term-output * {
			user-select: text;
			-webkit-user-select: text;
		}

		/* Glow phosphore : halo multi-couches (au lieu d'une seule ombre fine)
		   pour un effet nettement plus visible, y compris à faible intensité.
		   --sys-glow va de 0 à 2 (0-200% réglable depuis l'app Réglages ou la
		   commande "glow" du Terminal) : à 2 le halo devient un vrai bloom qui
		   déborde largement du texte. */
		.t-green  { color: var(--accent);                text-shadow: 0 0 calc(1px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(4px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(10px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(20px * var(--sys-glow, 0.55)) currentColor; transition: color 0.6s ease; }
		.t-cyan   { color: hsl(var(--hue), calc(55% * var(--sat, 80) / 80), 72%);    text-shadow: 0 0 calc(1px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(4px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(10px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(20px * var(--sys-glow, 0.55)) currentColor; transition: color 0.6s ease; }
		.t-red    { color: var(--danger);                text-shadow: 0 0 calc(1px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(4px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(10px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(20px * var(--sys-glow, 0.55)) currentColor; transition: color 0.6s ease; }
		.t-yellow { color: hsl(calc(var(--hue) + 40), 70%, 65%); text-shadow: 0 0 calc(1px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(4px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(10px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(20px * var(--sys-glow, 0.55)) currentColor; transition: color 0.6s ease; }
		.t-dim    { color: var(--text-secondary);        transition: color 0.6s ease; }
		.t-white  { color: var(--text-primary);          text-shadow: 0 0 calc(1px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(3px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(8px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(16px * var(--sys-glow, 0.55)) currentColor; transition: color 0.6s ease; }
		.t-bold   { font-weight:700; }
		.t-accent { color: var(--accent);                text-shadow: 0 0 calc(1px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(4px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(10px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(20px * var(--sys-glow, 0.55)) currentColor; transition: color 0.6s ease; }

		.term-input-row {
			display:flex; align-items:center; padding:8px 14px;
			border-top:1px solid hsla(var(--hue), calc(15% * var(--sat, 80) / 80), 30%, 0.5);
			background: hsla(var(--hue), calc(18% * var(--sat, 80) / 80), 3%, 0.6);
			flex-shrink:0;
			transition: background 0.6s ease, border-color 0.6s ease;
		}
		.term-prompt-label {
			color: var(--accent); font-weight:700; margin-right:8px; white-space:nowrap;
			text-shadow: 0 0 calc(1px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(4px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(10px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(20px * var(--sys-glow, 0.55)) currentColor;
			transition: color 0.6s ease;
		}
		.term-input-wrap { position: relative; flex: 1; display: flex; align-items: center; }
		#term-input, .term-input-field {
			width: 100%; background:transparent; border:none; outline:none; padding:0;
			color: var(--text-primary); font-family:inherit; font-size:inherit;
			caret-color: transparent; /* le curseur natif est remplacé par .term-cursor, clignotement piloté en JS */
			text-shadow: 0 0 calc(1px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(3px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(8px * var(--sys-glow, 0.55)) currentColor, 0 0 calc(16px * var(--sys-glow, 0.55)) currentColor;
			transition: color 0.6s ease;
		}
		/* Curseur bloc façon terminal CRT : remplace le curseur natif du champ.
		   Le clignotement (rythme, pause "pleine" pendant la frappe, respect de
		   prefers-reduced-motion) est entièrement piloté en JS (voir terminal.js,
		   fonctions startCursorBlink/refreshCursor) plutôt que par une animation
		   CSS à base de steps() — plus fiable d'un navigateur à l'autre. `opacity`
		   est donc juste basculée directement en JS, sans transition ici (un vrai
		   clignotement de terminal est net, pas un fondu). */
		.term-cursor {
			position: absolute; top: 50%; left: 0; transform: translateY(-50%);
			width: 0.58em; height: 1.15em;
			background: var(--accent);
			box-shadow: 0 0 calc(1px * var(--sys-glow, 0.55)) var(--accent), 0 0 calc(4px * var(--sys-glow, 0.55)) var(--accent), 0 0 calc(10px * var(--sys-glow, 0.55)) var(--accent), 0 0 calc(20px * var(--sys-glow, 0.55)) var(--accent);
			pointer-events: none;
		}
		.term-cursor.hidden { display: none; }


        /* Calculatrice */
        .calc-container {
            flex: 1; display: flex; flex-direction: column;
            background: hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 10%);
            overflow: hidden;
        }
        .calc-display {
            padding: 16px 20px 12px;
            text-align: right;
            background: rgba(0,0,0,0.25);
            border-bottom: 1px solid var(--border-color);
            flex-shrink: 0;
            min-height: 90px;
            display: flex;
            flex-direction: column;
            justify-content: flex-end;
        }
        .calc-expression {
            font-size: 0.875rem;
            color: var(--text-secondary);
            min-height: 22px;
            word-break: break-all;
            margin-bottom: 4px;
            transition: color 0.3s;
        }
        .calc-result {
            font-size: 2.25rem;
            font-weight: 300;
            color: var(--text-primary);
            word-break: break-all;
            line-height: 1.2;
            transition: font-size 0.2s ease, color 0.3s;
            font-variant-numeric: tabular-nums;
        }
        .calc-result.small { font-size: 1.5rem; }
        .calc-result.xsmall { font-size: 1.125rem; }
        .calc-result.error { color: var(--danger); font-size: 1.25rem; }

        .calc-memory-bar {
            display: flex;
            align-items: center;
            gap: 4px;
            padding: 4px 12px;
            background: rgba(0,0,0,0.15);
            border-bottom: 1px solid var(--border-color);
            flex-shrink: 0;
        }
        .calc-memory-bar .mem-indicator {
            font-size: 0.6875rem;
            color: var(--accent);
            font-weight: 600;
            min-width: 18px;
            text-align: center;
            opacity: 0;
            transition: opacity 0.3s;
        }
        .calc-memory-bar .mem-indicator.visible { opacity: 1; }
        .calc-memory-btn {
            background: none;
            border: none;
            color: var(--text-secondary);
            font-size: 0.6875rem;
            font-weight: 600;
            cursor: pointer;
            padding: 2px 6px;
            border-radius: 3px;
            transition: background 0.15s, color 0.15s;
        }
        .calc-memory-btn:hover { background: rgba(255,255,255,0.08); color: var(--text-primary); }

        .calc-history-toggle {
            margin-left: auto;
            background: none;
            border: none;
            color: var(--text-secondary);
            font-size: 0.75rem;
            cursor: pointer;
            padding: 2px 8px;
            border-radius: 3px;
            transition: background 0.15s, color 0.15s;
        }
        .calc-history-toggle:hover { background: rgba(255,255,255,0.08); color: var(--text-primary); }

        .calc-body {
            flex: 1;
            display: flex;
            overflow: hidden;
        }

        .calc-buttons {
            flex: 1;
            display: grid;
            grid-template-columns: repeat(4, 1fr);
            grid-template-rows: repeat(6, 1fr);
            gap: 1px;
            background: rgba(255,255,255,0.03);
        }

        .calc-btn {
            border: none;
            cursor: pointer;
            font-size: 1.125rem;
            font-family: inherit;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: background 0.12s, transform 0.1s, color 0.15s;
            background: hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 18%);
            color: var(--text-primary);
        }
        .calc-btn:hover { background: hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 24%); }
        .calc-btn:active { transform: scale(0.95); background: hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 28%); }

        .calc-btn.op {
            background: hsl(var(--hue), calc(15% * var(--sat, 80) / 80), 22%);
            color: var(--accent);
            font-size: 1.25rem;
        }
        .calc-btn.op:hover { background: hsl(var(--hue), calc(18% * var(--sat, 80) / 80), 28%); }
        .calc-btn.op.active-op {
            background: var(--accent);
            color: #000;
            font-weight: 700;
        }

        .calc-btn.fn {
            background: hsl(var(--hue), calc(10% * var(--sat, 80) / 80), 14%);
            color: var(--text-secondary);
            font-size: 0.9375rem;
        }
        .calc-btn.fn:hover { background: hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 20%); color: var(--text-primary); }

        .calc-btn.eq {
            background: var(--accent);
            color: #000;
            font-weight: 700;
            font-size: 1.375rem;
        }
        .calc-btn.eq:hover { filter: brightness(1.15); }
        .calc-btn.eq:active { filter: brightness(0.95); }

        .calc-btn.zero { }

        .calc-btn.clear { color: var(--danger); font-weight: 600; }

        .calc-history-panel {
            width: 0;
            overflow: hidden;
            background: rgba(0,0,0,0.2);
            border-left: 1px solid transparent;
            transition: width 0.25s ease, border-color 0.25s ease;
            flex-shrink: 0;
        }
        .calc-history-panel.open {
            width: 160px;
            border-left-color: var(--border-color);
        }
        .calc-history-inner {
            width: 160px;
            height: 100%;
            overflow-y: auto;
            padding: 8px;
        }
        .calc-history-item {
            padding: 6px 8px;
            border-radius: 4px;
            cursor: pointer;
            margin-bottom: 4px;
            transition: background 0.15s;
        }
        .calc-history-item:hover { background: rgba(255,255,255,0.06); }
        .calc-history-item .hist-expr {
            font-size: 0.6875rem;
            color: var(--text-secondary);
            word-break: break-all;
        }
        .calc-history-item .hist-result {
            font-size: 0.9375rem;
            color: var(--text-primary);
            font-weight: 500;
            font-variant-numeric: tabular-nums;
        }
        .calc-history-empty {
            font-size: 0.75rem;
            color: var(--text-secondary);
            text-align: center;
            padding: 20px 8px;
            opacity: 0.6;
        }

        /* Horloge analogique */
        .clock-container {
            flex: 1; display: flex; flex-direction: column;
            align-items: center; justify-content: center;
            background: hsl(var(--hue), calc(10% * var(--sat, 80) / 80), 8%);
            padding: 15px; gap: 16px; overflow: hidden;
        }
        .clock-face-wrap {
            width: 260px; height: 260px;
            border-radius: 50%;
            box-shadow: 0 4px 30px rgba(0,0,0,0.5), inset 0 0 40px rgba(0,0,0,0.3);
            overflow: hidden;
        }
        .clock-face-wrap canvas {
            width: 100%; height: 100%; display: block;
        }
        .clock-digital-row {
            display: flex; flex-direction: column; align-items: center; gap: 4px;
        }
        .clock-digital-time {
            font-size: 1.625rem; font-weight: 300; letter-spacing: 3px;
            color: var(--text-primary); font-variant-numeric: tabular-nums;
        }
        .clock-digital-date {
            font-size: 0.75rem; color: var(--text-secondary); text-transform: capitalize;
        }

        /* Minuteur & Chrono — réutilise .clock-container/.clock-face-wrap/.clock-digital-* */
        .tsw-modes { display: flex; gap: 4px; background: rgba(255,255,255,0.05); padding: 3px; border-radius: 8px; }
        .tsw-mode-btn { padding: 6px 14px; border: none; border-radius: 6px; background: transparent; color: var(--text-secondary); cursor: pointer; font-family: inherit; font-size: 0.7812rem; transition: background 0.15s ease, color 0.15s ease; }
        .tsw-mode-btn.active { background: var(--accent); color: #fff; }
        .tsw-timer-controls { display: flex; flex-direction: column; align-items: center; gap: 8px; width: 100%; }
        .tsw-presets { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; }
        .tsw-presets button { padding: 5px 10px; border-radius: 6px; border: 1px solid var(--border-color); background: var(--bg-desktop); color: var(--text-primary); font-family: inherit; font-size: 0.75rem; cursor: pointer; }
        .tsw-presets button.active { background: var(--accent); border-color: var(--accent); color: #fff; }
        .tsw-presets button:hover { border-color: var(--accent); }
        .tsw-custom { display: flex; align-items: center; gap: 4px; }
        .tsw-custom input { width: 46px; padding: 5px 6px; text-align: center; background: var(--bg-desktop); border: 1px solid var(--border-color); border-radius: 6px; color: var(--text-primary); font-family: inherit; font-size: 0.75rem; }
        .tsw-custom span { color: var(--text-secondary); }
        .tsw-custom button { padding: 5px 10px; border-radius: 6px; border: 1px solid var(--border-color); background: var(--bg-desktop); color: var(--text-primary); font-family: inherit; font-size: 0.75rem; cursor: pointer; }
        .tsw-buttons { display: flex; gap: 8px; }
        .tsw-laps-wrap { width: 100%; max-height: 90px; overflow-y: auto; }
        .tsw-laps { display: flex; flex-direction: column; gap: 2px; font-size: 0.75rem; font-variant-numeric: tabular-nums; }
        .tsw-lap-row { display: flex; justify-content: space-between; gap: 10px; padding: 4px 10px; background: rgba(255,255,255,0.03); border-radius: 5px; }

        /* Popup "Ajouter" (Mes Fichiers / Ordinateur) — partagé par MP3 et Vidéo */
        .addsrc-wrap { position: relative; display: inline-block; }
        .addsrc-menu {
            display: none; position: absolute; top: 100%; left: 0; margin-top: 6px;
            background: var(--bg-window); border: 1px solid var(--border-color); border-radius: 8px;
            min-width: 200px; box-shadow: 0 10px 30px rgba(0,0,0,0.5); z-index: 60; padding: 4px;
        }
        .addsrc-menu.show { display: block; }
        .addsrc-menu-item { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-radius: 6px; cursor: pointer; font-size: 0.8125rem; color: var(--text-primary); white-space: nowrap; }
        .addsrc-menu-item:hover { background: var(--accent); color: #fff; }
        .addsrc-menu-item svg { width: 16px; height: 16px; flex-shrink: 0; }

        /* Lecteur MP3 */
        .mp3-container { position: relative; flex: 1; display: flex; flex-direction: row; background: hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 10%); overflow: hidden; }
        .mp3-main { flex: 1; min-width: 0; display: flex; flex-direction: column; overflow: hidden; }
        .mp3-side { width: 210px; flex-shrink: 0; display: flex; flex-direction: column; border-left: 1px solid var(--border-color); background: rgba(0,0,0,0.12); overflow: hidden; }

        .mp3-dropzone-overlay { position: absolute; inset: 6px; z-index: 50; display: none; align-items: center; justify-content: center; flex-direction: column; gap: 10px; background: hsla(var(--hue), calc(40% * var(--sat, 80) / 80), 8%, 0.9); border: 2px dashed var(--accent); border-radius: 8px; color: var(--accent); font-size: 0.8125rem; font-weight: 600; text-align: center; pointer-events: none; padding: 20px; }
        .mp3-dropzone-overlay .mp3-drop-icon { font-size: 2.125rem; filter: drop-shadow(0 2px 6px hsla(var(--hue), calc(80% * var(--sat, 80) / 80), 55%, 0.5)); }
        .mp3-container.drag-over .mp3-dropzone-overlay { display: flex; }
        .mp3-container.drag-over .mp3-main,
        .mp3-container.drag-over .mp3-side { filter: blur(1px); opacity: 0.5; transition: filter 0.15s, opacity 0.15s; }

        .mp3-visual { position: relative; flex: 1 1 auto; min-height: 120px; display: flex; align-items: center; justify-content: center; overflow: hidden; background: radial-gradient(circle at 50% 35%, hsla(var(--hue), calc(45% * var(--sat, 80) / 80), 28%, 0.5), hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 8%) 75%); border-bottom: 1px solid var(--border-color); transition: background 0.6s ease; }
        .mp3-vu-canvas { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 1; }
        .mp3-disc { position: relative; z-index: 2; width: 104px; height: 104px; border-radius: 50%; background: conic-gradient(from 0deg, hsl(var(--hue), calc(55% * var(--sat, 80) / 80), 16%), hsl(var(--hue), calc(75% * var(--sat, 80) / 80), 38%), hsl(var(--hue), calc(55% * var(--sat, 80) / 80), 16%), hsl(var(--hue), calc(75% * var(--sat, 80) / 80), 38%), hsl(var(--hue), calc(55% * var(--sat, 80) / 80), 16%)); box-shadow: 0 6px 25px rgba(0,0,0,0.6), inset 0 0 25px rgba(0,0,0,0.5); animation: mp3-spin 4.5s linear infinite; animation-play-state: paused; transition: box-shadow 0.3s, background 0.6s ease; }
        .mp3-disc.spinning { animation-play-state: running; }
        .mp3-disc::after { content: ''; position: absolute; inset: 0; border-radius: 50%; box-shadow: inset 0 0 0 1px hsla(0,0%,100%,0.08); }
        .mp3-disc-hole { position: absolute; top: 50%; left: 50%; width: 22px; height: 22px; border-radius: 50%; background: var(--bg-window); transform: translate(-50%, -50%); box-shadow: 0 0 0 3px hsl(var(--hue), calc(15% * var(--sat, 80) / 80), 22%); transition: background 0.6s ease; }
        @keyframes mp3-spin { 100% { transform: rotate(360deg); } }

        .mp3-trackinfo { padding: 14px 16px 2px; text-align: center; flex-shrink: 0; }
        .mp3-title { font-size: 0.9375rem; font-weight: 600; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
        .mp3-artist { font-size: 0.75rem; color: var(--text-secondary); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

        .mp3-progress-row { display: flex; align-items: center; gap: 8px; padding: 10px 16px 2px; flex-shrink: 0; }
        .mp3-time { font-size: 0.6875rem; color: var(--text-secondary); font-variant-numeric: tabular-nums; min-width: 32px; }
        .mp3-time.right { text-align: right; }
        input[type="range"].mp3-seek, input[type="range"].mp3-volume { flex: 1; }

        .mp3-controls { display: flex; align-items: center; justify-content: center; gap: 6px; padding: 10px 16px; flex-shrink: 0; }
        .mp3-ctrl-btn { background: none; border: none; color: var(--text-secondary); font-size: 1.0625rem; cursor: pointer; width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; transition: background 0.15s, color 0.15s; }
        .mp3-ctrl-btn svg { width: 18px; height: 18px; display: block; }
        .mp3-ctrl-btn:hover { background: rgba(255,255,255,0.08); color: var(--text-primary); }
        .mp3-ctrl-btn.active { color: var(--accent); box-shadow: 0 0 calc(3px * var(--sys-glow, 0.55)) var(--accent), 0 0 calc(9px * var(--sys-glow, 0.55)) var(--accent); }
        .mp3-ctrl-btn.big { width: 54px; height: 54px; background: var(--accent); color: #000; font-size: 1.1875rem; box-shadow: 0 4px 16px hsla(var(--hue), calc(80% * var(--sat, 80) / 80), 55%, 0.45), 0 0 calc(4px * var(--sys-glow, 0.55)) var(--accent), 0 0 calc(14px * var(--sys-glow, 0.55)) var(--accent); transition: background 0.6s ease, box-shadow 0.3s; }
        .mp3-ctrl-btn.big svg { width: 21px; height: 21px; }
        .mp3-ctrl-btn.big:hover { filter: brightness(1.12); }
        .mp3-ctrl-btn.big:active { transform: scale(0.95); }
        .mp3-vol-icon { display: flex; align-items: center; color: var(--text-secondary); }
        .mp3-vol-icon svg { width: 15px; height: 15px; }

        .mp3-volume-row { display: flex; align-items: center; gap: 10px; padding: 2px 16px 12px; flex-shrink: 0; font-size: 0.8125rem; color: var(--text-secondary); }

        .mp3-playlist-header { display: flex; flex-direction: column; align-items: stretch; gap: 8px; padding: 10px 12px; background: rgba(0,0,0,0.15); border-bottom: 1px solid var(--border-color); flex-shrink: 0; transition: background 0.6s ease, border-color 0.6s ease; }
        .mp3-playlist-title { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-secondary); font-weight: 600; }
        .mp3-playlist-actions { display: flex; gap: 6px; }
        .mp3-add-btn, .mp3-clear-btn { flex: 1; background: none; border: 1px solid var(--border-color); color: var(--accent); font-size: 0.75rem; cursor: pointer; padding: 4px 10px; border-radius: 20px; transition: background 0.15s, border-color 0.15s, color 0.6s ease; }
        .mp3-add-btn:hover { background: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 50%, 0.12); border-color: var(--accent); }
        .mp3-clear-btn { color: var(--text-secondary); }
        .mp3-clear-btn:hover { background: hsla(0, 70%, 50%, 0.12); border-color: var(--danger); color: var(--danger); }

        .mp3-playlist { flex: 1; overflow-y: auto; padding: 6px 8px; }
        .mp3-playlist-empty { text-align: center; font-size: 0.75rem; color: var(--text-secondary); opacity: 0.6; padding: 30px 10px; }
        .mp3-track-item { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 5px; cursor: pointer; transition: background 0.15s; }
        .mp3-track-item:hover { background: rgba(255,255,255,0.06); }
        .mp3-track-item.playing { background: hsla(var(--hue), calc(55% * var(--sat, 80) / 80), 50%, 0.15); }
        .mp3-track-num { font-size: 0.75rem; color: var(--text-secondary); min-width: 16px; text-align: center; flex-shrink: 0; }
        .mp3-track-eq { width: 16px; height: 14px; min-width: 16px; display: none; align-items: flex-end; gap: 2px; flex-shrink: 0; }
        .mp3-track-item.playing .mp3-track-eq { display: flex; }
        .mp3-track-item.playing .mp3-track-num { display: none; }
        .mp3-track-eq span { width: 3px; background: var(--accent); border-radius: 1px; animation: mp3-eq 0.9s ease-in-out infinite; }
        .mp3-track-eq span:nth-child(1) { height: 40%; animation-delay: 0s; }
        .mp3-track-eq span:nth-child(2) { height: 100%; animation-delay: 0.2s; }
        .mp3-track-eq span:nth-child(3) { height: 65%; animation-delay: 0.4s; }
        .mp3-track-eq.paused span { animation-play-state: paused; }
        @keyframes mp3-eq { 0%, 100% { transform: scaleY(0.4); } 50% { transform: scaleY(1); } }
        .mp3-track-info { flex: 1; min-width: 0; }
        .mp3-track-name { font-size: 0.8125rem; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
        .mp3-track-item.playing .mp3-track-name { color: var(--accent); font-weight: 600; }
        .mp3-track-artist { font-size: 0.6875rem; color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
        .mp3-track-dur { font-size: 0.6875rem; color: var(--text-secondary); font-variant-numeric: tabular-nums; flex-shrink: 0; }
        .mp3-track-remove { background: none; border: none; color: var(--text-secondary); font-size: 0.9375rem; cursor: pointer; padding: 4px 6px; border-radius: 4px; opacity: 0; transition: opacity 0.15s, color 0.15s, background 0.15s; flex-shrink: 0; }
        .mp3-track-item:hover .mp3-track-remove { opacity: 1; }
        .mp3-track-remove:hover { color: var(--danger); background: rgba(255,255,255,0.08); }

        body.theme-3d .mp3-disc { box-shadow: 0 6px 25px rgba(0,0,0,0.7), inset 0 0 25px rgba(0,0,0,0.6), inset 1px 1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 60%, 0.3); }
        body.theme-3d .mp3-ctrl-btn.big { box-shadow: inset 1px 1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 70%, 0.4), inset -1px -1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 0%, 0.5), 0 4px 16px hsla(var(--hue), calc(80% * var(--sat, 80) / 80), 55%, 0.4), 0 0 calc(4px * var(--sys-glow, 0.55)) var(--accent), 0 0 calc(14px * var(--sys-glow, 0.55)) var(--accent); }

        .vid-container { position: relative; flex: 1; display: flex; flex-direction: row; background: hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 10%); overflow: hidden; }
        .vid-main { flex: 1; min-width: 0; display: flex; flex-direction: column; overflow: hidden; }
        .vid-side { width: 230px; flex-shrink: 0; display: flex; flex-direction: column; border-left: 1px solid var(--border-color); background: rgba(0,0,0,0.12); overflow: hidden; }

        .vid-dropzone-overlay { position: absolute; inset: 6px; z-index: 50; display: none; align-items: center; justify-content: center; flex-direction: column; gap: 10px; background: hsla(var(--hue), calc(40% * var(--sat, 80) / 80), 8%, 0.9); border: 2px dashed var(--accent); border-radius: 8px; color: var(--accent); font-size: 0.8125rem; font-weight: 600; text-align: center; pointer-events: none; padding: 20px; }
        .vid-dropzone-overlay .vid-drop-icon { font-size: 2.125rem; filter: drop-shadow(0 2px 6px hsla(var(--hue), calc(80% * var(--sat, 80) / 80), 55%, 0.5)); }
        .vid-container.drag-over .vid-dropzone-overlay { display: flex; }
        .vid-container.drag-over .vid-main,
        .vid-container.drag-over .vid-side { filter: blur(1px); opacity: 0.5; transition: filter 0.15s, opacity 0.15s; }

        .vid-screen { position: relative; flex: 1 1 auto; min-height: 120px; display: flex; align-items: center; justify-content: center; overflow: hidden; background: #000; border-bottom: 1px solid var(--border-color); }
        .vid-el { width: 100%; height: 100%; object-fit: contain; background: #000; }
        .vid-placeholder { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; color: var(--text-secondary); pointer-events: none; }
        .vid-placeholder.hidden { display: none; }
        .vid-placeholder-icon { font-size: 2.5rem; opacity: 0.5; }
        .vid-placeholder-text { font-size: 0.75rem; opacity: 0.7; padding: 0 20px; text-align: center; }
        .vid-fullscreen-btn { position: absolute; bottom: 10px; right: 10px; background: rgba(0,0,0,0.5); border: 1px solid hsla(0,0%,100%,0.15); color: #fff; font-size: 0.9375rem; cursor: pointer; width: 32px; height: 32px; border-radius: 6px; display: flex; align-items: center; justify-content: center; transition: background 0.15s; }
        .vid-fullscreen-btn svg { width: 16px; height: 16px; }
        .vid-fullscreen-btn:hover { background: rgba(0,0,0,0.75); }

        /* Visionnage partagé (chat.js) : recouvre le lecteur pendant que l'autoplay
           avec son est bloqué par le navigateur (le Play est déclenché par un
           message réseau, pas un geste utilisateur direct) — même langage visuel
           que .vid-fullscreen-btn plutôt qu'un nouveau style. */
        .chat-video-unmute-btn { position: absolute; bottom: 14px; left: 50%; transform: translateX(-50%); z-index: 5; background: rgba(0,0,0,0.7); border: 1px solid var(--accent); color: #fff; font-size: 0.8125rem; font-weight: 600; cursor: pointer; padding: 0.44em 1em; border-radius: 20px; transition: background 0.15s; }
        .chat-video-unmute-btn:hover { background: rgba(0,0,0,0.85); }

        .vid-trackinfo { padding: 12px 16px 2px; text-align: center; flex-shrink: 0; }
        .vid-title { font-size: 0.9375rem; font-weight: 600; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

        .vid-progress-row { display: flex; align-items: center; gap: 8px; padding: 10px 16px 2px; flex-shrink: 0; }
        .vid-time { font-size: 0.6875rem; color: var(--text-secondary); font-variant-numeric: tabular-nums; min-width: 32px; }
        .vid-time.right { text-align: right; }
        input[type="range"].vid-seek, input[type="range"].vid-volume { flex: 1; }

        .vid-controls { display: flex; align-items: center; justify-content: center; gap: 6px; padding: 10px 16px; flex-shrink: 0; }
        .vid-ctrl-btn { background: none; border: none; color: var(--text-secondary); font-size: 1.0625rem; cursor: pointer; width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; transition: background 0.15s, color 0.15s; }
        .vid-ctrl-btn svg { width: 18px; height: 18px; display: block; }
        .vid-ctrl-btn:hover { background: rgba(255,255,255,0.08); color: var(--text-primary); }
        .vid-ctrl-btn.active { color: var(--accent); box-shadow: 0 0 calc(3px * var(--sys-glow, 0.55)) var(--accent), 0 0 calc(9px * var(--sys-glow, 0.55)) var(--accent); }
        .vid-ctrl-btn.big { width: 54px; height: 54px; background: var(--accent); color: #000; font-size: 1.1875rem; box-shadow: 0 4px 16px hsla(var(--hue), calc(80% * var(--sat, 80) / 80), 55%, 0.45), 0 0 calc(4px * var(--sys-glow, 0.55)) var(--accent), 0 0 calc(14px * var(--sys-glow, 0.55)) var(--accent); transition: background 0.6s ease, box-shadow 0.3s; }
        .vid-ctrl-btn.big svg { width: 21px; height: 21px; }
        .vid-ctrl-btn.big:hover { filter: brightness(1.12); }
        .vid-ctrl-btn.big:active { transform: scale(0.95); }
        .vid-vol-icon { display: flex; align-items: center; color: var(--text-secondary); }
        .vid-vol-icon svg { width: 15px; height: 15px; }

        .vid-volume-row { display: flex; align-items: center; gap: 10px; padding: 2px 16px 12px; flex-shrink: 0; font-size: 0.8125rem; color: var(--text-secondary); }

        .vid-playlist-header { display: flex; flex-direction: column; align-items: stretch; gap: 8px; padding: 10px 12px; background: rgba(0,0,0,0.15); border-bottom: 1px solid var(--border-color); flex-shrink: 0; transition: background 0.6s ease, border-color 0.6s ease; }
        .vid-playlist-title { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-secondary); font-weight: 600; }
        .vid-playlist-actions { display: flex; gap: 6px; }
        .vid-add-btn, .vid-clear-btn { flex: 1; background: none; border: 1px solid var(--border-color); color: var(--accent); font-size: 0.75rem; cursor: pointer; padding: 4px 10px; border-radius: 20px; transition: background 0.15s, border-color 0.15s, color 0.6s ease; }
        .vid-add-btn:hover { background: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 50%, 0.12); border-color: var(--accent); }
        .vid-clear-btn { color: var(--text-secondary); }
        .vid-clear-btn:hover { background: hsla(0, 70%, 50%, 0.12); border-color: var(--danger); color: var(--danger); }

        .vid-playlist { flex: 1; overflow-y: auto; padding: 6px 8px; }
        .vid-playlist-empty { text-align: center; font-size: 0.75rem; color: var(--text-secondary); opacity: 0.6; padding: 30px 10px; }
        .vid-track-item { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 5px; cursor: pointer; transition: background 0.15s; }
        .vid-track-item:hover { background: rgba(255,255,255,0.06); }
        .vid-track-item.playing { background: hsla(var(--hue), calc(55% * var(--sat, 80) / 80), 50%, 0.15); }
        .vid-track-num { font-size: 0.75rem; color: var(--text-secondary); min-width: 16px; text-align: center; flex-shrink: 0; }
        .vid-track-eq { width: 16px; height: 14px; min-width: 16px; display: none; align-items: flex-end; gap: 2px; flex-shrink: 0; }
        .vid-track-item.playing .vid-track-eq { display: flex; }
        .vid-track-item.playing .vid-track-num { display: none; }
        .vid-track-eq span { width: 3px; background: var(--accent); border-radius: 1px; animation: mp3-eq 0.9s ease-in-out infinite; }
        .vid-track-eq span:nth-child(1) { height: 40%; animation-delay: 0s; }
        .vid-track-eq span:nth-child(2) { height: 100%; animation-delay: 0.2s; }
        .vid-track-eq span:nth-child(3) { height: 65%; animation-delay: 0.4s; }
        .vid-track-eq.paused span { animation-play-state: paused; }
        .vid-track-info { flex: 1; min-width: 0; }
        .vid-track-name { font-size: 0.8125rem; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
        .vid-track-item.playing .vid-track-name { color: var(--accent); font-weight: 600; }
        .vid-track-dur { font-size: 0.6875rem; color: var(--text-secondary); font-variant-numeric: tabular-nums; flex-shrink: 0; }
        .vid-track-remove { background: none; border: none; color: var(--text-secondary); font-size: 0.9375rem; cursor: pointer; padding: 4px 6px; border-radius: 4px; opacity: 0; transition: opacity 0.15s, color 0.15s, background 0.15s; flex-shrink: 0; }
        .vid-track-item:hover .vid-track-remove { opacity: 1; }
        .vid-track-remove:hover { color: var(--danger); background: rgba(255,255,255,0.08); }

        body.theme-3d .vid-ctrl-btn.big { box-shadow: inset 1px 1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 70%, 0.4), inset -1px -1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 0%, 0.5), 0 4px 16px hsla(var(--hue), calc(80% * var(--sat, 80) / 80), 55%, 0.4), 0 0 calc(4px * var(--sys-glow, 0.55)) var(--accent), 0 0 calc(14px * var(--sys-glow, 0.55)) var(--accent); }

        body.theme-3d .window { border-radius: 0; border: none; box-shadow: inset 1px 1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 50%, 0.3), inset -1px -1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 0%, 0.7), 5px 5px 15px rgba(0,0,0,0.8); }
        body.theme-3d .window.focused { box-shadow: inset 1px 1px 0 0 hsla(var(--hue), calc(30% * var(--sat, 80) / 80), 60%, 0.4), inset -1px -1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 0%, 0.8), 8px 8px 25px rgba(0,0,0,0.9), 0 0 calc(4px * var(--sys-glow, 0.55)) hsla(var(--hue), calc(80% * var(--sat, 80) / 80), 55%, 0.55), 0 0 calc(16px * var(--sys-glow, 0.55)) hsla(var(--hue), calc(80% * var(--sat, 80) / 80), 55%, 0.35); }
        body.theme-3d .title-bar { background: linear-gradient(180deg, hsl(var(--hue), calc(20% * var(--sat, 80) / 80), 28%), hsl(var(--hue), calc(15% * var(--sat, 80) / 80), 20%)); box-shadow: inset 0 1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 50%, 0.4), inset 0 -1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 0%, 0.5); }
        body.theme-3d .title-bar .title { color: var(--text-primary); font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.8), 0 0 calc(1px * var(--sys-glow, 0.55)) var(--text-primary), 0 0 calc(4px * var(--sys-glow, 0.55)) var(--text-primary); }
        body.theme-3d .window-controls button { background: var(--bg-titlebar); color: var(--text-secondary); border: none; border-radius: 0; box-shadow: inset 1px 1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 50%, 0.3), inset -1px -1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 0%, 0.6); }
        body.theme-3d .window-controls button:hover { color: white; background: var(--accent); box-shadow: none; }
        body.theme-3d .window-controls .close-btn:hover { background: var(--danger); }
        body.theme-3d #taskbar { box-shadow: inset 0 1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 50%, 0.3); background: var(--bg-taskbar); border-top: none; }
        body.theme-3d .notepad-menu-bar { box-shadow: inset 0 1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 50%, 0.3); background: var(--bg-taskbar); border-bottom: none; }
        body.theme-3d .notepad-status { box-shadow: inset 0 1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 0%, 0.5); background: var(--bg-taskbar); border-top: none; }
        body.theme-3d .notepad-gutter { box-shadow: inset -1px 0 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 0%, 0.5); border-right: none; }
        body.theme-3d .notepad-findbar { box-shadow: inset 0 -1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 0%, 0.4); border-bottom: none; }
        body.theme-3d .setting-group { box-shadow: inset 1px 1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 50%, 0.2), inset -1px -1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 0%, 0.5); background: hsl(var(--hue), calc(10% * var(--sat, 80) / 80), 12%); border: none; }

        /* Le style "filets 3D" ci-dessus durcit la barre de titre et les
           encadrés de Réglages avec des couleurs OPAQUES codées en dur (pas
           les variables --bg-*, déjà rendues translucides par le style
           "vitre" — voir plus haut), ce qui coupait le flou/la transparence
           dès que les deux styles étaient combinés. On restaure ici un fond
           translucide spécifiquement quand les deux sont actifs ensemble,
           sans toucher aux ombres en relief (qui font le "3D") ni au look
           quand un seul des deux styles est actif. */
        body.theme-3d.glass-on .title-bar {
            background: hsla(var(--hue), calc(15% * var(--sat, 80) / 80), 20%, var(--sys-glass-alpha, 0.4));
        }
        body.theme-3d.glass-on .setting-group {
            background: hsla(var(--hue), calc(10% * var(--sat, 80) / 80), 12%, var(--sys-glass-alpha, 0.4));
        }

        @media (max-width: 768px) {
            .desktop-icon { width: 70px; } .desktop-icon .icon { font-size: 1.75rem; } #start-menu { width: calc(100% - 20px); left: 10px; max-height: 70vh; }
            .resize-handle.n, .resize-handle.s { height: 15px; top: -7px; bottom: -7px; }
            .resize-handle.e, .resize-handle.w { width: 15px; right: -7px; left: -7px; }
        }

        /* ══════════════════════════════════════
           APP: P2P TRANSFER (portage de l'outil Creepy Cat P2P Transfer 2.0)
        ══════════════════════════════════════ */
    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

    /*
      BASE FONT = 1.875vw  →  at 1440px wide = 27px (original design size)
      Tout le CSS est en rem — l'interface scale proportionnellement avec la fenêtre.
      min: 10px (≈533px viewport), max: 28px (≈1493px viewport)
    */
    /* Palette de secours (si jamais utilisée hors #p2p-app) */
    :root {
      --bg:       #0b0b0b;
      --panel:    #111111;
      --surface:  #161616;
      --surface2: #1c1c1c;
      --border:   #222222;
      --border2:  #2a2a2a;
      --text:     #c2c2c2;
      --dim:      #525252;
      --dim2:     #767676;
      --green:    #22c55e;
      --blue:     #3b82f6;
      --amber:    #f59e0b;
      --red:      #ef4444;
      --cyan:     #06b6d4;
      --mono:     'Arial Narrow', Arial, sans-serif;
      --black:    'Arial Black', Arial, sans-serif;
    }

    /* Reskin WebOSx — reprend les variables du thème système (--hue, --accent, etc.)
       de sorte que l'app suive automatiquement la couleur d'accent et le mode 3D choisis
       dans Configuration. Les couleurs de statut (vert/rouge/ambre/cyan) restent fixes
       car elles portent un sens (connecté / erreur / attention / mode serveur). */
    #p2p-app {
      --bg:       var(--bg-window);
      --panel:    var(--bg-window);
      --surface:  hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 20%);
      --surface2: hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 25%);
      --border:   var(--border-color);
      --border2:  hsl(var(--hue), calc(10% * var(--sat, 80) / 80), 32%);
      --text:     var(--text-primary);
      --dim:      var(--text-secondary);
      --dim2:     hsl(var(--hue), calc(10% * var(--sat, 80) / 80), 58%);
      --blue:     var(--accent);
      --red:      var(--danger);
      --mono:     'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
      --black:    'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;

      /* Réglage "Taille du texte" (Configuration > Apparence) : cette app a sa
         propre échelle basée sur vw (indépendante du rem système), donc on la
         multiplie manuellement par --sys-text-scale pour en tenir compte. */
      font-size: calc(clamp(11px, 1.3vw, 20px) * var(--sys-text-scale, 100) / 100);
      width: 100%; height: 100%; overflow: hidden;
      background: var(--bg); color: var(--text);
      font-family: var(--mono);
    }

    /* ══════════════════════════════════════
       STATUT DE CONNEXION (vit désormais dans la barre de statut
       du bas — voir #statusbar plus loin — plutôt qu'en haut de
       fenêtre, pour ne plus recouvrir les boutons de la toolbar)
    ══════════════════════════════════════ */
    #conn-bar {
      display: none; align-items: center; gap: 0.3em;
      font-size: 0.56em; letter-spacing: .08em; text-transform: uppercase; color: var(--dim2);
      margin-left: auto; flex-shrink: 1; min-width: 0; overflow: hidden;
    }
    .conn-dot {
      width: 0.44em; height: 0.44em; border-radius: 50%; background: var(--dim); flex-shrink: 0;
      transition: background .4s, box-shadow .4s;
    }
    .conn-dot.waiting { background: var(--dim); animation: blink 1.4s ease-in-out infinite; }
    .conn-dot.ok      { background: var(--green); box-shadow: 0 0 0.19em var(--green); animation: none; }
    .conn-dot.err     { background: var(--red);   box-shadow: 0 0 0.19em var(--red);   animation: none; }
    .conn-label       {
      color: var(--dim2); transition: color .4s; font-weight: 500;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; max-width: 16em;
    }
    .conn-label.ok    { color: var(--green); }
    .conn-label.err   { color: var(--red); }
    .conn-ping        { color: var(--amber); font-size: 0.78em; flex-shrink: 0; white-space: nowrap; }

    /* ══════════════════════════════════════
       MAIN LAYOUT
    ══════════════════════════════════════ */
    #app { display: flex; flex-direction: column; height: 100%; overflow: hidden; position: relative; }
    #main { flex: 1; overflow: hidden; position: relative; min-height: 0; }

    .screen { display: none; flex-direction: column; height: 100%; overflow: hidden; }
    .screen.visible { display: flex; }

    /* ══════════════════════════════════════
       SCREEN — ROLE SELECTION
    ══════════════════════════════════════ */
    #screen-role { align-items: center; justify-content: center; background: var(--bg); }
    .role-panel {
      width: min(34em, 92%);
      background: var(--panel); border: 1px solid var(--border2);
      border-radius: 0.22em; overflow: hidden;
    }
    .role-panel-header {
      padding: 1.3em 1.6em 1em;
      border-bottom: 1px solid var(--border); text-align: center;
    }
    .role-panel-title {
      font-size: 1.15em; font-weight: 700; letter-spacing: .08em;
      text-transform: uppercase; color: var(--text); margin-bottom: 0.25em;
      font-family: var(--black);
    }
    .role-panel-sub { font-size: 0.85em; color: var(--dim2); letter-spacing: .05em; }
    .role-btns {
      display: grid; grid-template-columns: 1fr 1fr 1fr;
      gap: 1px; background: var(--border);
    }
    .role-btn {
      display: flex; flex-direction: column; align-items: flex-start;
      gap: 0.35em; padding: 1.3em 1.05em;
      background: var(--panel); border: none; cursor: pointer;
      transition: background .15s; text-align: left;
    }
    .role-btn:hover    { background: var(--surface2); }
    .role-btn.selected { background: var(--surface2); }
    .role-btn:disabled { opacity: .4; cursor: not-allowed; }
    .role-btn .r-icon  { font-size: 1.7em; color: var(--accent); font-weight: 900; line-height: 1; font-family: var(--black); }
    .role-btn .r-label { font-size: 0.95em; font-weight: 700; letter-spacing: .01em; text-transform: none; color: var(--text); font-family: var(--black); }
    .role-btn .r-desc  { font-size: 0.92em; color: var(--dim2); letter-spacing: .02em; white-space: normal; line-height: 1.4; }

    /* Global tooltip — appended to body, above all overflow contexts */
    #role-tooltip {
      display: none; position: fixed; z-index: 9999; pointer-events: none;
      background: hsl(var(--hue), calc(10% * var(--sat, 80) / 80), 14%); border: 1px solid var(--border2);
      border-radius: 0.22em; padding: 0.52em 0.67em;
      width: 14em;
      box-shadow: 0 4px 20px rgba(0,0,0,.6);
    }
    #role-tooltip.visible { display: block; }
    #role-tooltip::after {
      content: ''; position: absolute; top: 100%; left: 50%;
      transform: translateX(-50%);
      border: 0.3em solid transparent;
      border-top-color: var(--border2);
    }
    /* When tooltip flips below the button, arrow points upward */
    #role-tooltip.flipped::after {
      top: auto; bottom: 100%;
      border-top-color: transparent;
      border-bottom-color: var(--border2);
    }
    .role-tooltip-title {
      font-size: 0.72em; font-weight: 700; letter-spacing: .1em;
      text-transform: uppercase; color: var(--text); margin-bottom: 0.3em;
      font-family: var(--black);
    }
    .role-tooltip-line {
      display: flex; align-items: flex-start; gap: 0.3em;
      font-size: 0.74em; color: var(--dim2); letter-spacing: .03em;
      line-height: 1.45; margin-bottom: 0.15em;
    }
    .role-tooltip-line .tt-dot { color: var(--green); flex-shrink: 0; margin-top: 0.04em; }
    .role-tooltip-line:last-child { margin-bottom: 0; }

    .role-edge-note {
      margin-top: 0.67em; padding: 0.7em 1.05em;
      border-top: 1px solid var(--border);
      display: flex; align-items: center; gap: 0.44em;
      font-size: 0.8em; color: var(--dim2); letter-spacing: .04em; line-height: 1.4;
    }
    .role-edge-note .edge-icon { font-size: 1em; flex-shrink: 0; }
    .role-hint { padding: 0.8em 1.4em; border-top: 1px solid var(--border); font-size: 0.8em; color: var(--dim2); letter-spacing: .06em; text-align: center; }

    /* Small screens: role buttons go vertical */
    @media (max-width: 480px) {
      .role-btns { grid-template-columns: 1fr; }
      .role-btn  { flex-direction: row; align-items: center; gap: 0.6em; padding: 0.85em 0.9em; }
      .role-btn .r-icon { flex-shrink: 0; }
    }

    /* ══════════════════════════════════════
       TOOLBAR
    ══════════════════════════════════════ */
    .toolbar {
      min-height: 2.96em; background: var(--panel);
      border-bottom: 1px solid var(--border);
      display: flex; align-items: center; justify-content: space-between;
      padding: 0.3em 0.74em; gap: 0.52em; flex-shrink: 0; flex-wrap: wrap;
    }
    .toolbar-left  { display: flex; align-items: center; gap: 0.52em; flex-wrap: wrap; }
    .toolbar-right { display: flex; align-items: center; gap: 0.22em; flex-wrap: wrap; }

    .session-block { display: flex; align-items: center; gap: 0.3em; }
    .sess-label    { font-size: 0.7em; color: var(--dim); letter-spacing: .2em; text-transform: uppercase; font-weight: 600; }
    .code-pill {
      font-size: 1.11em; font-weight: 700; letter-spacing: .2em;
      color: var(--accent); background: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 50%, .1);
      border: none; border-radius: 0.22em;
      padding: 0.15em 0.6em; cursor: pointer; min-width: 7em; text-align: center;
      transition: background .15s;
    }
    .code-pill:hover { background: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 50%, .18); }

    .queue-count {
      font-size: 0.78em; color: var(--amber); letter-spacing: .08em;
      background: rgba(245,158,11,.08); border: 1px solid rgba(245,158,11,.25);
      border-radius: 0.11em; padding: 0.11em 0.3em; font-weight: 600;
    }
    .queue-count.hidden { display: none; }

    .tb-btn {
      padding: 0.4em 0.85em; font-family: var(--mono); font-size: 0.78em;
      font-weight: 600; letter-spacing: normal; text-transform: none;
      background: hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 18%); color: var(--text);
      border: none; border-radius: 0.22em; cursor: pointer;
      transition: background .12s, color .12s, transform .1s; white-space: nowrap;
    }
    .tb-btn:hover   { background: hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 24%); }
    .tb-btn:active  { transform: scale(0.96); background: hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 28%); }
    .tb-btn:disabled { opacity: .35; cursor: not-allowed; transform: none; }
    .tb-btn.primary { background: var(--accent); color: #000; font-weight: 700; }
    .tb-btn.primary:hover:not(:disabled) { filter: brightness(1.15); }
    .tb-btn.primary:active:not(:disabled) { filter: brightness(0.95); transform: none; }
    .tb-btn.danger  { background: hsl(var(--hue), calc(10% * var(--sat, 80) / 80), 14%); color: var(--red); }
    .tb-btn.danger:hover { background: rgba(239,68,68,.15); color: #fff; }
    .tb-btn.large   { padding: 0.55em 1.1em; font-size: 0.92em; }

    /* SHA-256 toggle */
    .tb-toggle {
      display: flex; align-items: center; gap: 0.22em; cursor: pointer;
      font-size: 0.78em; color: var(--dim2); letter-spacing: .06em;
      font-weight: 600; text-transform: uppercase; user-select: none;
      padding: 0.3em 0.52em; border: 1px solid var(--border2); border-radius: 0.11em;
      background: var(--surface2); transition: border-color .15s, color .15s;
    }
    .tb-toggle:hover { border-color: hsl(var(--hue), calc(8% * var(--sat, 80) / 80), 28%); color: var(--text); }
    .tb-toggle input { display: none; }
    .tb-toggle-track {
      width: 0.96em; height: 0.52em; border-radius: 0.26em; flex-shrink: 0;
      background: var(--border2); position: relative;
      transition: background .2s; border: 1px solid hsl(var(--hue), calc(8% * var(--sat, 80) / 80), 24%);
    }
    .tb-toggle-track::after {
      content: ''; position: absolute; top: 0.07em; left: 0.07em;
      width: 0.37em; height: 0.37em; border-radius: 50%;
      background: var(--dim); transition: left .2s, background .2s;
    }
    .tb-toggle input:checked ~ .tb-toggle-track { background: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 50%, .2); border-color: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 50%, .4); }
    .tb-toggle input:checked ~ .tb-toggle-track::after { left: 0.52em; background: var(--accent); }
    .tb-toggle input:checked ~ .tb-toggle-label { color: var(--accent); }
    .tb-toggle-label { transition: color .2s; }

    /* ── Toggle "Chiffrer les messages" (chat) : pas de majuscules forcées, pleine largeur ── */
    .chat-encrypt-toggle {
      width: 100%; box-sizing: border-box; justify-content: flex-start;
      text-transform: none; font-weight: 500; letter-spacing: normal;
    }
    #chat-passphrase { width: 100%; }

    .srv-clients-badge {
      font-size: 0.7em; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
      color: var(--cyan); background: rgba(6,182,212,.08);
      border: 1px solid rgba(6,182,212,.25); border-radius: 0.11em;
      padding: 0.15em 0.44em; transition: color .3s;
    }
    .srv-clients-badge.active { color: var(--green); background: rgba(34,197,94,.08); border-color: rgba(34,197,94,.3); }

    /* ══════════════════════════════════════
       FILE TABLE
    ══════════════════════════════════════ */
    .file-section { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
    .file-table-header {
      display: grid;
      grid-template-columns: 0.89em 1fr 3.15em 3.7em 4.15em 0.89em;
      gap: 0 0.37em; align-items: center;
      padding: 0.37em 0.81em;
      background: var(--panel); border-bottom: 1px solid var(--border);
      font-weight: 700; letter-spacing: .02em;
      text-transform: none; color: var(--dim); flex-shrink: 0;
    }
    .file-table-header span { font-size: 0.56em; }
    .file-table-header span[data-i18n="p2p.table.status"],
    .file-table-header span[data-i18n="p2p.table.hash"] {
      display: inline-block; transform: translateX(24px);
    }

    .file-queue {
      flex: 1; overflow-y: auto; background: var(--bg);
      display: flex; flex-direction: column;
    }

    .fq-item {
      display: grid;
      grid-template-columns: 0.89em 1fr 3.15em 3.7em 4.15em 0.89em;
      grid-template-rows: auto auto;
      gap: 0 0.37em; align-items: center;
      padding: 0.52em 0.81em 0.3em;
      border-bottom: 1px solid var(--border);
      background: var(--bg); transition: background .12s; flex-shrink: 0;
    }
    .fq-item:hover     { background: hsl(var(--hue), calc(10% * var(--sat, 80) / 80), 9%); }
    .fq-item.active    { background: rgba(59,130,246,.04); border-left: 2px solid var(--blue); padding-left: 0.37em; }
    .fq-item.done      { background: rgba(34,197,94,.03); }
    .fq-item.paused    { background: rgba(245,158,11,.03); border-left: 2px solid var(--amber); padding-left: 0.37em; }
    .fq-item.confirmed { background: rgba(34,197,94,.04); border-left: 2px solid var(--green); padding-left: 0.37em; }

    .fq-icon-sm { font-size: 1em;   color: var(--dim2); }
    .fq-name    { font-size: 0.85em; color: var(--text); font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .fq-size    { font-size: 0.78em; color: var(--dim2); text-align: right; }
    .fq-st      { font-size: 0.6em;  font-weight: 700; letter-spacing: .02em; text-transform: none; text-align: center; justify-self: center; }
    .fq-st.sending   { color: var(--blue); }
    .fq-st.done      { color: var(--green); }
    .fq-st.confirmed { color: var(--green); }
    .fq-st.paused    { color: var(--amber); }

    .fq-remove {
      background: none; border: none; cursor: pointer;
      color: var(--dim); font-size: 0.7em; padding: 0.07em 0.15em;
      border-radius: 0.07em; transition: color .12s, background .12s; line-height: 1;
    }
    .fq-remove:hover { color: var(--red); background: rgba(239,68,68,.1); }
    .fq-item.active .fq-remove,
    .fq-item.done .fq-remove,
    .fq-item.confirmed .fq-remove { display: none; }

    .fq-prow { grid-column: 1 / -1; margin-top: 0.22em; }
    .mini-track { width: 100%; height: 0.44em; background: var(--border2); border-radius: 0.22em; overflow: hidden; }
    .mini-bar {
      height: 100%; background: var(--blue);
      transform-origin: left; transform: scaleX(0);
      transition: transform .15s linear; border-radius: 0.22em;
    }
    .fq-item.done .mini-bar,
    .fq-item.confirmed .mini-bar { background: var(--green); }
    .fq-item.paused .mini-bar    { background: var(--amber); }

    .sha-badge {
      display: inline-flex; align-items: center; gap: 0.11em;
      justify-self: center;
      font-size: 0.37em; font-weight: 700; letter-spacing: .02em;
      padding: 0.11em 0.22em; border-radius: 0.11em; font-family: var(--mono);
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
      transition: color .25s, border-color .25s, background .25s;
    }
    .sha-badge.waiting { color: var(--dim);   border: 1px solid var(--border2);          background: transparent; }
    .sha-badge.hashing { color: var(--amber); border: 1px solid rgba(245,158,11,.3);      background: rgba(245,158,11,.05); }
    .sha-badge.ok      { color: var(--green); border: 1px solid rgba(34,197,94,.3);       background: rgba(34,197,94,.06); }
    .sha-badge.err     { color: var(--red);   border: 1px solid rgba(239,68,68,.3);       background: rgba(239,68,68,.06); }

    .stream-badge { display: none; }

    /* ── DROPZONE ── */
    .dropzone {
      margin: 0.44em; flex-shrink: 0;
      border: 1px dashed hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 55%, .35); border-radius: 0.22em;
      padding: 1.19em 0.59em; text-align: center;
      display: flex; flex-direction: column; align-items: center;
      justify-content: center; gap: 0.3em; cursor: pointer;
      position: relative;
      animation: recv-pulse 2.4s ease-in-out infinite;
      transition: border-color .15s, background .15s;
    }
    .dropzone:hover, .dropzone.drag-over {
      background: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 55%, .12) !important;
      border-color: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 55%, .8) !important;
      box-shadow: inset 0 0 1.19em hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 55%, .1) !important;
      animation: none;
    }
    .dropzone input { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
    .dz-icon {
      font-size: 1.63em; color: var(--accent);
      animation: recv-icon-pulse 2.4s ease-in-out infinite;
    }
    .dz-text {
      font-size: 0.78em; color: var(--accent); letter-spacing: .06em;
      text-transform: none; font-weight: 700; font-family: var(--black);
      opacity: .7; animation: recv-icon-pulse 2.4s ease-in-out infinite;
    }
    .dropzone:hover .dz-icon, .dropzone:hover .dz-text,
    .dropzone.drag-over .dz-icon, .dropzone.drag-over .dz-text { opacity: 1; animation: none; }

    #recv-dropzone {
      margin: 0.44em; flex-shrink: 0;
      border: 1px dashed hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 55%, .35); border-radius: 0.22em;
      padding: 1.19em 0.59em;
      display: flex; flex-direction: column; align-items: center;
      justify-content: center; gap: 0.37em;
      animation: recv-pulse 2.4s ease-in-out infinite;
    }
    #recv-dropzone.hidden { display: none; }
    .recv-dz-icon { font-size: 1.63em; line-height: 1; color: var(--accent); animation: recv-icon-pulse 2.4s ease-in-out infinite; }
    .recv-dz-text { font-size: 0.78em; color: var(--accent); letter-spacing: .06em; text-transform: none; font-weight: 700; font-family: var(--black); opacity: .7; animation: recv-icon-pulse 2.4s ease-in-out infinite; }
    .recv-dz-sub  { font-size: 0.76em; color: var(--dim2); letter-spacing: .04em; text-transform: none; }

    @keyframes recv-pulse {
      0%,100% { background: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 55%, .02); border-color: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 55%, .2); box-shadow: none; }
      50%      { background: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 55%, .07); border-color: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 55%, .6); box-shadow: inset 0 0 0.89em hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 55%, .06); }
    }
    @keyframes recv-icon-pulse { 0%,100%{opacity:.5} 50%{opacity:1} }

    /* ══════════════════════════════════════
       RECEIVER LAYOUT
    ══════════════════════════════════════ */
    .recv-form {
      background: var(--panel); border-bottom: 1px solid var(--border);
      padding: 0.59em 0.74em; flex-shrink: 0;
      transition: padding .2s;
    }
    /* ── recv-form base styles ── */
    .recv-form-inner {
      display: flex; align-items: flex-start; justify-content: space-between;
      gap: 0.37em; flex-wrap: wrap;
    }
    .recv-row  { display: flex; align-items: flex-end; gap: 0.37em; flex-wrap: wrap; }
    .recv-field { display: flex; flex-direction: column; gap: 0.19em; }
    .field-label, .sess-label, .recv-label {
      font-size: 0.7em; color: var(--dim); letter-spacing: .06em;
      text-transform: uppercase; font-weight: 700;
    }

    /* ── Minimized form (once connected) ── */
    .recv-form.minimized { padding: 0.3em 0.74em; }
    .recv-form.minimized .recv-form-inner { display: none; }
    .recv-form-mini {
      display: none; align-items: center; gap: 0.44em; flex-wrap: wrap;
      font-size: 0.7em; color: var(--dim2);
    }
    .recv-form.minimized .recv-form-mini { display: flex; }
    .recv-mini-code { color: var(--green); font-weight: 700; letter-spacing: .25em; }
    .recv-mini-expand {
      margin-left: auto; padding: 0.2em 0.55em;
      font-family: var(--mono); font-size: 0.63em; font-weight: 600;
      letter-spacing: normal; text-transform: none;
      background: hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 18%); color: var(--text);
      border: none; border-radius: 0.22em;
      cursor: pointer; transition: background .12s, color .12s;
    }
    .recv-mini-expand:hover { background: hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 24%); }

    /* ── rfl-footer always visible ── */
    .rfl-footer {
      padding: 0.52em 0.81em; background: var(--panel);
      border-top: 1px solid var(--border);
      display: flex; align-items: center; justify-content: space-between;
      flex-shrink: 0; gap: 0.44em; flex-wrap: wrap;
      position: sticky; bottom: 0; z-index: 2;
    }
    .rfl-sel-count { font-size: 0.7em; color: var(--dim2); letter-spacing: .08em; }
    .rfl-sel-count span { color: var(--green); font-weight: 700; }

    /* ── Mobile ── */
    @media (max-width: 600px) {
      .recv-form-inner { flex-direction: column; gap: 0.44em; }
      .recv-row { flex-direction: column; align-items: stretch; gap: 0.44em; width: 100%; }
      /* Each field: label left (fixed width) + control right */
      .recv-field {
        flex-direction: row; align-items: center; gap: 0.44em; flex-wrap: nowrap;
      }
      .recv-field .field-label { flex-shrink: 0; width: 5.8em; }
      .recv-field input[type="text"], .recv-field input[type="password"] { flex: 1; min-width: 0; width: auto; }
      /* Connect button full width below */
      #btn-connect { width: 100%; text-align: center; }
      /* Dir row fills remaining width */
      .recv-field .dir-row { flex: 1; min-width: 0; }
      .dir-path { flex: 1; min-width: 0; max-width: none; font-size: 0.67em; }
      /* Clear button full width */
      #btn-clear-recv { width: 100%; text-align: center; align-self: stretch; margin-top: 0.15em; }
      /* Bigger tap targets */
      .tb-btn, .btn-dir { min-height: 2.4em; }
      .rfl-item { padding: 0.74em 0.59em; gap: 0.52em; }
      .rfl-footer { padding: 0.44em 0.59em; }
      #btn-rfl-download { flex: 1; text-align: center; }
      .sb-item:not(.sb-green) { display: none; }
      .sb-sep { display: none; }
    }
    @media (max-width: 380px) {
      /* Very small: stack label above control */
      .recv-field { flex-direction: column; align-items: flex-start; }
      .recv-field .field-label { width: auto; }
      .recv-field input[type="text"], .recv-field input[type="password"] { width: 100%; }
      .recv-field .dir-row { width: 100%; }
    }

    /* Scopées à #p2p-app ET #chat-app : ces règles ciblaient auparavant TOUS
       les input[type=text]/[password] du système (même spécificité qu'une
       classe — 0,1,0 — donc elles gagnaient contre .ui-requester-input,
       .term-input, etc. dès lors qu'elles apparaissaient plus bas dans le
       fichier). C'était la cause du champ de saisie du requester de
       renommage resté minuscule (width: 8.15em ≈ 130px) malgré tous les
       réglages de largeur du requester. #chat-app est volontairement inclus
       ici : l'app Chat réutilise cette base (padding/fond/police) et se
       contente de la surcharger partiellement via .chat-text-input (voir
       plus bas), donc retirer #chat-app romprait son style. */
    #p2p-app input[type="text"], #p2p-app input[type="password"],
    #chat-app input[type="text"], #chat-app input[type="password"] {
      padding: 0.37em 0.41em; font-family: var(--mono);
      font-size: 0.78em; font-weight: 400; letter-spacing: normal;
      color: var(--text); text-transform: none;
      background: hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 18%); border: 1px solid transparent;
      border-radius: 0.22em; outline: none; width: 8.15em;
      transition: border-color .15s, background .15s;
      /* iOS auto-zoom prevention — browser zooms when font-size < 16px */
      -webkit-text-size-adjust: none;
    }
    @media (max-width: 600px) {
      #p2p-app input[type="text"], #p2p-app input[type="password"],
      #chat-app input[type="text"], #chat-app input[type="password"] { font-size: max(0.78em, 16px); }
    }
    #p2p-app input[type="text"]::placeholder, #p2p-app input[type="password"]::placeholder,
    #chat-app input[type="text"]::placeholder, #chat-app input[type="password"]::placeholder { color: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 55%, .3); }
    #p2p-app input[type="text"]:focus, #p2p-app input[type="password"]:focus,
    #chat-app input[type="text"]:focus, #chat-app input[type="password"]:focus { border-color: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 55%, .5); background: hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 22%); }

    .dir-row  { display: flex; align-items: center; gap: 0.22em; flex-wrap: wrap; }
    .btn-dir  {
      padding: 0.4em 0.55em; font-family: var(--mono); font-size: 0.78em;
      font-weight: 600; letter-spacing: normal; text-transform: none;
      background: hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 18%); color: var(--text);
      border: none; border-radius: 0.22em; cursor: pointer;
      transition: background .12s, color .12s; white-space: nowrap;
    }
    .btn-dir:hover  { background: hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 24%); }
    .btn-dir.chosen { color: var(--accent); background: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 50%, .15); }
    .dir-path { font-size: 0.78em; color: var(--dim2); max-width: 32em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .dir-path.has-dir { color: var(--accent); cursor: pointer; border-bottom: 1px dashed hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 55%, .35); transition: color .15s, border-color .15s; }
    .dir-path.has-dir:hover { filter: brightness(1.15); border-color: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 55%, .8); }
    .dir-path.has-dir::after { content: ' ↗'; font-size: 0.63em; opacity: .6; }

    .done-banner {
      display: flex; align-items: center; gap: 0.3em;
      margin: 0.3em 0.44em; padding: 0.37em 0.52em;
      background: rgba(34,197,94,.06); border: 1px solid rgba(34,197,94,.25);
      border-radius: 0.15em; font-size: 0.7em; font-weight: 600; color: var(--green);
    }
    .done-banner .done-detail { font-size: 0.74em; color: var(--dim2); font-weight: 400; margin-left: auto; }

    /* ══════════════════════════════════════
       PROGRESS GLOBAL
    ══════════════════════════════════════ */
    .progress-wrap {
      padding: 0.52em 0.74em; flex-shrink: 0;
      border-top: 1px solid var(--border); background: var(--panel);
    }
    .progress-label { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.19em; }
    .progress-label span:first-child {
      font-size: 0.59em; color: var(--text); font-weight: 500;
      letter-spacing: .04em; white-space: nowrap; overflow: hidden;
      text-overflow: ellipsis; max-width: 60%;
    }
    .pct { font-size: 0.63em; color: var(--blue); font-weight: 700; }
    #send-speed, #recv-speed { font-size: 0.59em; color: var(--dim2); font-weight: 400; letter-spacing: .04em; }
    .progress-track { height: 0.37em; background: var(--border2); border-radius: 0.19em; position: relative; overflow: hidden; }
    .progress-bar {
      position: absolute; inset: 0; background: var(--blue);
      transform-origin: left; transform: scaleX(0);
      transition: transform .2s ease; border-radius: 0.19em;
    }

    /* ══════════════════════════════════════
       STATUS LINE
    ══════════════════════════════════════ */
    .status {
      padding: 0.37em 0.81em; font-size: 0.59em; letter-spacing: .03em;
      text-transform: none; color: var(--dim2); font-weight: 600;
      background: var(--panel); border-bottom: 1px solid var(--border);
      min-height: 1.11em; flex-shrink: 0;
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }
    .status.ok   { color: var(--green); }
    .status.err  { color: var(--red); }
    .status.info { color: var(--amber); }
    .status.pulse { animation: blink 1.4s ease-in-out infinite; }

    @keyframes blink { 0%,100%{opacity:1} 50%{opacity:.4} }

    /* ══════════════════════════════════════
       STATUS BAR (bottom)
    ══════════════════════════════════════ */
    #statusbar {
      height: 1.63em; background: hsl(var(--hue), calc(10% * var(--sat, 80) / 80), 5%);
      border-top: 1px solid var(--border);
      display: flex; align-items: center;
      padding: 0 0.89em; padding-bottom: env(safe-area-inset-bottom, 0px);
      gap: 0.52em; flex-shrink: 0;
      overflow: hidden;
    }
    /* Le nom de l'app ne rétrécit jamais. La tagline (décorative) s'efface en
       premier. #sb-mode reçoit en miroir les messages de statut de l'app — qui
       peuvent être longs — et doit donc pouvoir se tronquer avec une ellipse
       plutôt que d'être coupé net ou de pousser le reste de la barre. */
    .sb-item, .sb-sep { flex-shrink: 0; white-space: nowrap; }
    #statusbar [data-i18n="p2p.statusbar.tagline"] {
      flex-shrink: 2; min-width: 0; overflow: hidden; text-overflow: ellipsis;
    }
    #sb-mode {
      flex-shrink: 1; min-width: 3em; overflow: hidden; text-overflow: ellipsis;
    }
    .sb-item  { font-size: 0.66em; color: var(--dim); letter-spacing: .02em; }
    .sb-sep   { font-size: 0.56em; color: var(--border2); }
    .sb-green { color: var(--green); }

    /* ══════════════════════════════════════
       SERVER MODE STYLES
    ══════════════════════════════════════ */
    #srv-receivers-panel {
      flex-shrink: 0; background: var(--panel);
      border-bottom: 1px solid var(--border);
      display: none; flex-direction: column;
    }
    #srv-receivers-panel.visible { display: flex; }
    .srv-recv-header {
      display: flex; align-items: center; justify-content: space-between;
      padding: 0.3em 0.81em; border-bottom: 1px solid var(--border);
    }
    .srv-recv-title { font-size: 0.63em; font-weight: 700; letter-spacing: .18em; text-transform: uppercase; color: var(--cyan); font-family: var(--black); }
    .srv-recv-list { display: flex; flex-direction: column; max-height: 8.15em; overflow-y: auto; }

    .srv-recv-item {
      display: grid;
      grid-template-columns: 1.93em 1fr 2.59em 4.07em 4.07em;
      gap: 0 0.44em; align-items: center;
      padding: 0.3em 0.81em 0.22em;
      border-bottom: 1px solid var(--border);
      background: var(--bg); flex-shrink: 0;
    }
    .srv-recv-item:last-child { border-bottom: none; }
    .srv-recv-item.disconnected { opacity: .38; }
    .srv-recv-id {
      font-size: 0.48em; font-weight: 700; letter-spacing: .12em;
      color: var(--cyan); font-family: var(--black); text-transform: uppercase;
    }
    .srv-recv-item.disconnected .srv-recv-id { color: var(--dim); }
    .srv-recv-prog-wrap { display: flex; flex-direction: column; gap: 0.11em; min-width: 0; }
    .srv-recv-filename  { font-size: 0.72em; color: var(--dim2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; letter-spacing: .03em; }
    .srv-recv-track { width: 100%; height: 0.3em; background: var(--border2); border-radius: 0.15em; overflow: hidden; }
    .srv-recv-bar   { height: 100%; background: var(--cyan); transform-origin: left; transform: scaleX(0); transition: transform .18s linear; border-radius: 0.15em; }
    .srv-recv-bar.done { background: var(--green); }
    .srv-recv-pct   { font-size: 0.63em; font-weight: 700; color: var(--cyan); letter-spacing: .06em; text-align: right; }
    .srv-recv-pct.done { color: var(--green); }
    .srv-recv-speed { font-size: 0.56em; color: var(--dim); letter-spacing: .04em; }

    .srv-ack-badge {
      display: inline-flex; align-items: center; gap: 0.15em;
      font-size: 0.56em; font-weight: 700; letter-spacing: .08em;
      padding: 0.11em 0.3em; border-radius: 0.11em; font-family: var(--mono);
      white-space: nowrap; text-transform: uppercase;
      transition: color .25s, border-color .25s, background .25s;
    }
    .srv-ack-badge.waiting { color: var(--dim);   border: 1px solid var(--border2); background: transparent; }
    .srv-ack-badge.sending { color: var(--blue);  border: 1px solid rgba(59,130,246,.3);  background: rgba(59,130,246,.06); }
    .srv-ack-badge.ok      { color: var(--green); border: 1px solid rgba(34,197,94,.3);   background: rgba(34,197,94,.06); }
    .srv-ack-badge.partial { color: var(--amber); border: 1px solid rgba(245,158,11,.3);  background: rgba(245,158,11,.06); }
    .srv-ack-badge.all-ok  { color: var(--green); border: 1px solid rgba(34,197,94,.5);   background: rgba(34,197,94,.1); box-shadow: 0 0 0.22em rgba(34,197,94,.2); }

    /* ══════════════════════════════════════
       RECEIVER FILELIST (SERVER MODE)
    ══════════════════════════════════════ */
    .recv-filelist-panel { flex: 1; display: flex; flex-direction: column; overflow: hidden; background: var(--bg); }
    .rfl-header {
      display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap;
      padding: 0.52em 0.81em; background: var(--panel);
      border-bottom: 1px solid var(--border); flex-shrink: 0; gap: 0.37em;
    }
    .rfl-title   { font-size: 0.78em; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--text); font-family: var(--black); }
    .rfl-actions { display: flex; gap: 0.3em; align-items: center; flex-wrap: wrap; }
    .rfl-list    { flex: 1; overflow-y: auto; display: flex; flex-direction: column; }
    .rfl-item {
      display: flex; align-items: center; gap: 0.44em;
      padding: 0.52em 0.81em; border-bottom: 1px solid var(--border);
      background: var(--bg); transition: background .12s; cursor: pointer; flex-shrink: 0;
    }
    .rfl-item:hover    { background: hsl(var(--hue), calc(10% * var(--sat, 80) / 80), 9%); }
    .rfl-item.selected { background: rgba(34,197,94,.04); }
    .rfl-cb   { width: 0.74em; height: 0.74em; flex-shrink: 0; cursor: pointer; accent-color: var(--green); border-radius: 0.11em; }
    .rfl-icon { font-size: 1em; color: var(--dim2); flex-shrink: 0; }
    .rfl-name { flex: 1; font-size: 0.85em; color: var(--text); font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .rfl-size { font-size: 0.78em; color: var(--dim2); flex-shrink: 0; }

    .fq-item:nth-child(even)       { background: hsl(var(--hue), calc(10% * var(--sat, 80) / 80), 8%); }
    .fq-item:nth-child(even):hover { background: hsl(var(--hue), calc(10% * var(--sat, 80) / 80), 11%); }
    .rfl-item:nth-child(even)      { background: hsl(var(--hue), calc(10% * var(--sat, 80) / 80), 8%); }
    .rfl-item:nth-child(even):hover{ background: hsl(var(--hue), calc(10% * var(--sat, 80) / 80), 11%); }
    .srv-recv-item:nth-child(even) { background: hsl(var(--hue), calc(10% * var(--sat, 80) / 80), 8%); }

    button { font-family: var(--mono); }

    /* ══════════════════════════════════════
       APP: CHAT (salon de discussion P2P, WebRTC via PeerJS)
       Réutilise volontairement les classes de l'app P2P (.role-panel,
       .role-btn, .tb-btn, .code-pill, .conn-dot, .status…) via le même
       système de variables scopées, pour garder un look'n'feel identique
       entre les deux apps sans dupliquer les règles de base.
    ══════════════════════════════════════ */
    #chat-app {
      --bg:       var(--bg-window);
      --panel:    var(--bg-window);
      --surface:  hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 20%);
      --surface2: hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 25%);
      --border:   var(--border-color);
      --border2:  hsl(var(--hue), calc(10% * var(--sat, 80) / 80), 32%);
      --text:     var(--text-primary);
      --dim:      var(--text-secondary);
      --dim2:     hsl(var(--hue), calc(10% * var(--sat, 80) / 80), 58%);
      --blue:     var(--accent);
      --red:      var(--danger);
      --mono:     'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
      --black:    'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;

      /* Réglage "Taille du texte" (Configuration > Apparence) : cette app a sa
         propre échelle basée sur vw (indépendante du rem système), donc on la
         multiplie manuellement par --sys-text-scale pour en tenir compte. */
      font-size: calc(clamp(11px, 1.3vw, 20px) * var(--sys-text-scale, 100) / 100);
      width: 100%; height: 100%; overflow: hidden;
      background: var(--bg); color: var(--text);
      font-family: var(--mono);
    }

    /* ── Écran de rôle : seulement 2 choix (Créer / Rejoindre) ── */
    .chat-role-btns { grid-template-columns: 1fr 1fr; }

    /* ── Écran de configuration (pseudo + code) ── */
    .chat-setup-panel { width: min(24em, 92%); }
    .chat-setup-body  { padding: 1.2em 1.5em 1.5em; display: flex; flex-direction: column; gap: 0.9em; }
    .chat-setup-actions { display: flex; justify-content: space-between; align-items: center; gap: 0.6em; margin-top: 0.3em; }
    #chat-setup-status:empty { display: none; }

    /* Champ texte "normal" (pseudo, message) — l'input[type=text] global
       du P2P est taillé pour un code à 6 caractères ; on le neutralise ici. */
    .chat-text-input {
      width: 100%; text-transform: none; letter-spacing: normal;
      font-weight: 400; text-align: left; color: var(--text);
    }
    .chat-text-input::placeholder { color: var(--dim); }
    .chat-text-input:focus { border-color: hsla(var(--hue), calc(60% * var(--sat, 80) / 80), 55%, .5); }

    /* ── Écran du salon ── */
    .chat-body { flex: 1; display: flex; overflow: hidden; min-height: 0; }

    .chat-sidebar {
      width: 11.5em; flex-shrink: 0; background: var(--panel);
      border-right: 1px solid var(--border); overflow-y: auto;
      display: flex; flex-direction: column;
    }
    .chat-sidebar-title {
      padding: 0.52em 0.74em; font-size: 0.6em; font-weight: 700;
      letter-spacing: .06em; color: var(--dim); flex-shrink: 0;
      border-bottom: 1px solid var(--border);
    }
    .chat-participant {
      display: flex; align-items: center; gap: 0.44em;
      padding: 0.44em 0.74em; font-size: 0.78em; color: var(--text);
      border-bottom: 1px solid var(--border);
    }
    .chat-participant.is-host { color: var(--text); font-weight: 600; }
    .chat-participant-dot {
      width: 0.5em; height: 0.5em; border-radius: 50%;
      background: var(--dim); flex-shrink: 0; transition: background .3s ease;
    }
    .chat-participant-host-icon { font-size: 0.9em; flex-shrink: 0; line-height: 1; }
    .chat-participant-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .chat-participant-you  { color: var(--dim2); font-size: 0.85em; margin-left: auto; flex-shrink: 0; }
    .chat-kick-btn {
      margin-left: auto; flex-shrink: 0; width: 1.3em; height: 1.3em;
      display: flex; align-items: center; justify-content: center;
      font-size: 0.78em; line-height: 1; color: var(--dim2);
      background: transparent; border: none; border-radius: 0.22em;
      cursor: pointer; transition: background .12s, color .12s;
    }
    .chat-kick-btn:hover { background: rgba(239,68,68,.15); color: var(--red); }

    @media (max-width: 600px) { .chat-sidebar { display: none; } }

    .chat-main-col { flex: 1; display: flex; flex-direction: column; overflow: hidden; min-width: 0; }

    .chat-messages {
      flex: 1; overflow-y: auto; padding: 0.9em 1em;
      display: flex; flex-direction: column; gap: 0.55em;
      background: var(--bg);
    }

    .chat-msg { display: flex; flex-direction: column; max-width: 74%; }
    .chat-msg.theirs { align-self: flex-start; align-items: flex-start; }
    .chat-msg.mine   { align-self: flex-end;   align-items: flex-end; }
    .chat-msg-meta   { font-size: 0.6em; color: var(--dim); margin-bottom: 0.15em; padding: 0 0.3em; letter-spacing: .02em; }
    .chat-bubble {
      padding: 0.5em 0.74em; border-radius: 0.85em;
      font-size: 0.85em; line-height: 1.4; word-break: break-word;
      white-space: pre-wrap;
    }
    .chat-msg.theirs .chat-bubble { color: #000; border-bottom-left-radius: 0.2em; }
    .chat-msg.mine   .chat-bubble { color: #000; border-bottom-right-radius: 0.2em; }
    .chat-msg-time   { font-size: 0.56em; color: var(--dim); margin-top: 0.15em; padding: 0 0.3em; }

    .chat-msg.system {
      align-self: center; max-width: 90%;
      font-size: 0.78em; color: var(--dim); letter-spacing: .02em;
      text-align: center; padding: 0.2em 0;
    }

    .chat-composer {
      flex-shrink: 0; display: flex; align-items: center; gap: 0.5em;
      padding: 0.6em 0.8em; background: var(--panel);
      border-top: 1px solid var(--border);
    }
    .chat-composer .chat-text-input { flex: 1; }
    .chat-composer .tb-btn { flex-shrink: 0; }
    /* ── Badge de chiffrement (à côté du code de session) ── */
    .chat-lock-badge {
      display: inline-flex; align-items: center; gap: 0.2em;
      font-size: 0.63em; font-weight: 700; letter-spacing: .02em;
      color: var(--dim2); background: hsl(var(--hue), calc(12% * var(--sat, 80) / 80), 18%);
      border-radius: 0.22em; padding: 0.15em 0.44em; flex-shrink: 0;
    }
    .chat-lock-badge.on { color: var(--green); background: rgba(34,197,94,.1); }

    /* ── Bulle non déchiffrable (mauvaise phrase secrète / absente) ── */
    .chat-bubble.locked { font-style: italic; opacity: .7; }

    .chat-composer .tb-btn:disabled { opacity: .35; }

    /* ── Barre de statut basse (réutilise .sb-item/.conn-dot/.conn-label) ── */
    #chat-statusbar {
      height: 1.63em; background: hsl(var(--hue), calc(10% * var(--sat, 80) / 80), 5%);
      border-top: 1px solid var(--border);
      display: flex; align-items: center;
      padding: 0 0.89em; padding-bottom: env(safe-area-inset-bottom, 0px);
      gap: 0.52em; flex-shrink: 0; overflow: hidden;
    }
    .chat-conn-bar {
      display: flex; align-items: center; gap: 0.3em; margin-left: auto;
      font-size: 0.66em; letter-spacing: .02em; color: var(--dim2);
      min-width: 0; overflow: hidden;
    }

        /* ==================================================================
           App "Peinture" — réutilise .notepad-menu-bar/.notepad-dropdown,
           .wave-slider, .ui-requester-* et .notepad-status déjà définis
           plus haut dans ce fichier. Uniquement le nécessaire ci-dessous :
           toolbar d'outils, palette de couleurs, zone de canevas.
           ================================================================== */

        .paint-toolbar {
            display: flex;
            align-items: center;
            gap: 18px;
            min-height: 50px; /* hauteur fixe (augmentée) : doit être assez haute pour absorber
                                  la combobox de type de brosse sans que la barre grandisse
                                  quand elle apparaît (outil Pinceau) */
            padding: 8px 14px;
            background: var(--bg-taskbar);
            border-bottom: 1px solid var(--border-color);
            flex-shrink: 0;
            flex-wrap: wrap;
            transition: background 0.6s ease;
        }

        .paint-tools { display: flex; flex-direction: column; gap: 4px; align-items: center; }
        .paint-tool-btn {
            width: 40px; height: 40px;
            display: flex; align-items: center; justify-content: center;
            border-radius: 8px;
            border: 1px solid transparent;
            background: transparent;
            color: var(--text-secondary);
            cursor: pointer;
            transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
        }
        .paint-tool-btn svg { width: 22px; height: 22px; }
        .paint-tool-btn:hover { background: rgba(255,255,255,0.08); color: var(--text-primary); }
        .paint-tool-btn.active {
            background: hsla(var(--hue), calc(80% * var(--sat, 80) / 80), 55%, 0.18);
            border-color: var(--accent);
            color: var(--accent);
        }
        /* Indicateur plein/vide directement sur l'icône des outils Rectangle/Ellipse
           (remplace l'ancien bouton dédié) : un reclic sur l'outil déjà actif bascule
           cette classe plutôt que de changer d'outil. */
        .paint-tool-btn.filled svg { fill: currentColor; fill-opacity: 0.45; }

        .paint-size-row { display: flex; align-items: center; gap: 8px; min-width: 160px; }
        .paint-size-label { font-size: 0.75rem; color: var(--text-secondary); white-space: nowrap; }
        .paint-checkbox-label {
            display: flex; align-items: center; gap: 6px;
            font-size: 0.75rem; color: var(--text-secondary);
            white-space: nowrap; cursor: pointer; user-select: none;
        }
        .paint-checkbox-label input[type="checkbox"] { cursor: pointer; }
        .paint-size-value {
            font-variant-numeric: tabular-nums;
            color: var(--accent);
            font-size: 0.75rem;
            font-weight: 600;
            min-width: 44px;
            text-align: right;
            white-space: nowrap;
        }
        .paint-size-unit { font-size: 0.75rem; color: var(--text-secondary); }
        .paint-num-input {
            width: 52px;
            background: var(--bg-desktop);
            border: 1px solid var(--border-color);
            border-radius: 6px;
            color: var(--text-primary);
            padding: 4px 6px;
            font-family: inherit;
            font-size: 0.75rem;
            text-align: right;
        }
        .paint-num-input:focus { outline: none; border-color: var(--accent); }
        /* Flèches natives masquées (Chrome/Edge/Safari + Firefox) : la molette
           au survol du champ (voir le listener 'wheel' dans paint.js) incrémente/
           décrémente déjà de 1, ce qui rend les flèches redondantes — et elles
           mangeaient une bonne partie des 52px de large du champ. Scopé à
           .paint-num-input (barre d'outils de Peinture) uniquement : les champs
           number des dialogues (Nouveau canevas, Taille de la zone de travail)
           gardent leur comportement natif par défaut. */
        .paint-num-input::-webkit-inner-spin-button,
        .paint-num-input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
        .paint-num-input { -moz-appearance: textfield; }

        .paint-colors-panel {
            width: 78px;
            flex-shrink: 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 12px;
            padding: 10px 10px 10px 8px;
            overflow-y: auto;
            background: var(--bg-taskbar);
            border-right: 1px solid var(--border-color);
            transition: background 0.6s ease;
        }
        .paint-swatch-pair { position: relative; width: 46px; height: 38px; flex-shrink: 0; }
        .paint-swatch {
            position: absolute;
            width: 30px; height: 30px;
            border-radius: 6px;
            border: 2px solid var(--border-color);
            cursor: pointer;
            box-shadow: 0 1px 3px rgba(0,0,0,0.4);
        }
        .paint-swatch.primary { top: 0; left: 0; z-index: 2; }
        .paint-swatch.secondary { bottom: 0; right: 0; z-index: 1; }
        .paint-swap-btn {
            width: 22px; height: 22px;
            flex-shrink: 0;
            border-radius: 50%;
            border: 1px solid var(--border-color);
            background: var(--bg-window);
            color: var(--text-secondary);
            display: flex; align-items: center; justify-content: center;
            cursor: pointer;
        }
        .paint-swap-btn svg { width: 12px; height: 12px; transform: rotate(90deg); } /* flèches verticales, cohérent avec l'empilement vertical du panneau */
        .paint-swap-btn:hover { color: var(--accent); border-color: var(--accent); }
        .paint-color-input { width: 0; height: 0; opacity: 0; position: absolute; pointer-events: none; }

        .paint-palette { display: grid; grid-template-columns: repeat(2, 20px); gap: 5px; justify-content: center; }
        .paint-palette-swatch {
            width: 20px; height: 20px;
            border-radius: 4px;
            border: 1px solid var(--border-color);
            cursor: pointer;
            padding: 0;
        }
        .paint-palette-swatch:hover { transform: scale(1.15); border-color: var(--accent); }

        .paint-canvas-wrap {
            flex: 1;
            overflow: auto;
            display: flex;
            align-items: center;
            justify-content: center;
            background:
                linear-gradient(45deg, rgba(255,255,255,0.04) 25%, transparent 25%, transparent 75%, rgba(255,255,255,0.04) 75%),
                linear-gradient(45deg, rgba(255,255,255,0.04) 25%, transparent 25%, transparent 75%, rgba(255,255,255,0.04) 75%);
            background-size: 20px 20px;
            background-position: 0 0, 10px 10px;
            background-color: var(--bg-desktop);
            padding: 16px;
            transition: background-color 0.6s ease;
        }
        .paint-canvas-wrap.dragover { outline: 2px dashed var(--accent); outline-offset: -8px; }
        .paint-canvas-scroll { display: flex; }
        .paint-canvas {
            background: #ffffff;
            box-shadow: 0 4px 18px rgba(0,0,0,0.5);
            touch-action: none;
            cursor: crosshair;
            image-rendering: pixelated;
        }
        .paint-canvas.cursor-eraser { cursor: cell; }
        .paint-canvas.cursor-picker { cursor: copy; }

        .paint-newdlg-presets { display: flex; gap: 6px; margin: 10px 0; }
        .paint-newdlg-presets .ui-requester-btn { flex: 1; font-size: 0.75rem; padding: 6px 4px; }
        .paint-newdlg-row { display: flex; gap: 12px; margin-bottom: 14px; }
        .paint-newdlg-row label { display: flex; flex-direction: column; gap: 4px; font-size: 0.75rem; color: var(--text-secondary); flex: 1; }
        .paint-newdlg-row input[type="number"] {
            background: var(--bg-desktop);
            border: 1px solid var(--border-color);
            border-radius: 6px;
            color: var(--text-primary);
            padding: 6px 8px;
            font-family: inherit;
            font-size: 0.8125rem;
        }

        /* ==================================================================
           App "Peinture" v2 — pan (bouton milieu), zoom molette centré,
           damier de transparence, outils de sélection, sélecteur de brosse.
           Ces règles surchargent volontairement certaines déclarations du
           premier bloc .paint-* (plus haut dans ce fichier) : la cascade CSS
           donne la priorité à ce qui vient en dernier à spécificité égale.
           ================================================================== */

        .paint-tools-sep { height: 1px; width: 100%; margin: 4px 0; background: var(--border-color); flex-shrink: 0; }

        .paint-brush-type-wrap { display: flex; align-items: center; }
        .paint-brush-select {
            background: var(--bg-desktop);
            border: 1px solid var(--border-color);
            border-radius: 6px;
            color: var(--text-primary);
            font-family: inherit;
            font-size: 0.75rem;
            padding: 4px 8px; /* réduit (était 6px 8px) : moins de hauteur = moins de décalage vertical de la barre */
            cursor: pointer;
        }
        .paint-brush-select:focus { outline: 1px solid var(--accent); }

        /* ---- Conteneur de scroll : correction du piège classique
           flex+overflow (impossible de scroller vers le haut/la gauche
           passé un certain zoom). L'enfant grandit avec le contenu grâce à
           min-width/min-height:100%, et c'est LUI qui définit la zone
           scrollable du parent — donc tous les bords du canevas restent
           atteignables quel que soit le niveau de zoom. ---- */
        .paint-canvas-wrap {
            display: block; /* neutralise le display:flex + align-items/justify-content:center + padding hérités de la toute première règle .paint-canvas-wrap plus haut dans ce fichier : c'est CET élément qui scrolle réellement (overflow:auto), donc c'est lui qui reproduisait le bug de centrage, pas seulement .paint-canvas-scroll */
            padding: 0;
            overflow: auto;
            min-height: 0; min-width: 0; /* essentiel : sans ça, ce flex-item (flex:1, défini plus haut) ne peut pas rétrécir sous la taille de son contenu — il déborde de .window-content au lieu de scroller lui-même, ce qui bloquait l'ascenseur vertical au zoom */
            background:
                linear-gradient(45deg, rgba(255,255,255,0.04) 25%, transparent 25%, transparent 75%, rgba(255,255,255,0.04) 75%),
                linear-gradient(45deg, rgba(255,255,255,0.04) 25%, transparent 25%, transparent 75%, rgba(255,255,255,0.04) 75%);
            background-size: 20px 20px;
            background-position: 0 0, 10px 10px;
            background-color: var(--bg-desktop);
            cursor: default;
        }
        .paint-canvas-wrap.panning { cursor: grabbing; }
        .paint-canvas-wrap.dragover { outline: 2px dashed var(--accent); outline-offset: -8px; }
        /* Pas de align-items/justify-content:center ici — combiné à
           overflow:auto sur le parent, ça reproduit le bug classique où le
           contenu qui déborde AVANT le centre (haut/gauche) devient
           inatteignable au scroll (scrollTop/scrollLeft ne peuvent pas
           devenir négatifs). Le centrage se fait via margin:auto sur
           .paint-canvas ci-dessous à la place : équivalent visuellement
           quand le contenu est plus petit que le conteneur, mais qui reste
           scrollable jusqu'à tous les bords quand il déborde. */
        .paint-canvas-scroll {
            display: flex;
            min-width: 100%; min-height: 100%;
            box-sizing: border-box;
            padding: 60px;
        }

        /* ---- Le canevas lui-même : damier "transparence" en fond CSS pur
           (n'affecte jamais les pixels réellement exportés en PNG — le
           canvas.toBlob() n'exporte que le contenu dessiné, pas ce fond). ---- */
        .paint-canvas {
            margin: auto;
            background-image:
                linear-gradient(45deg, #bdbdbd 25%, transparent 25%, transparent 75%, #bdbdbd 75%, #bdbdbd),
                linear-gradient(45deg, #bdbdbd 25%, #e8e8e8 25%, #e8e8e8 75%, #bdbdbd 75%, #bdbdbd);
            background-size: 16px 16px;
            background-position: 0 0, 8px 8px;
            box-shadow: 0 4px 18px rgba(0,0,0,0.5);
            touch-action: none;
            image-rendering: pixelated;
            flex-shrink: 0;
        }
        .paint-canvas.cursor-brush { cursor: crosshair; }
        .paint-canvas.cursor-eraser { cursor: cell; }
        .paint-canvas.cursor-picker { cursor: copy; }
        .paint-canvas.cursor-select { cursor: crosshair; }
        .paint-canvas.cursor-move-tool { cursor: move; }

        .paint-newdlg-transparent {
            display: flex; align-items: center; gap: 8px;
            font-size: 0.8125rem; color: var(--text-secondary);
            margin: -4px 0 14px;
            cursor: pointer;
        }
        .paint-newdlg-transparent input[type="checkbox"] { accent-color: var(--accent); width: 15px; height: 15px; }

        .paint-anchor-label { font-size: 0.75rem; color: var(--text-secondary); margin: 4px 0 6px; }
        .paint-anchor-grid {
            display: grid; grid-template-columns: repeat(3, 1fr);
            gap: 4px;
            width: 96px; height: 96px;
            margin: 0 auto 16px;
        }
        .paint-anchor-btn {
            background: var(--bg-desktop);
            border: 1px solid var(--border-color);
            border-radius: 4px;
            cursor: pointer;
            position: relative;
        }
        .paint-anchor-btn::after {
            content: ''; position: absolute; top: 50%; left: 50%;
            width: 6px; height: 6px; border-radius: 50%;
            background: var(--text-secondary);
            transform: translate(-50%, -50%);
        }
        .paint-anchor-btn:hover { border-color: var(--accent); }
        .paint-anchor-btn.active { background: hsla(var(--hue), calc(80% * var(--sat, 80) / 80), 55%, 0.18); border-color: var(--accent); }
        .paint-anchor-btn.active::after { background: var(--accent); width: 8px; height: 8px; }

        .paint-fill-toggle {
            display: none; /* affiché en JS uniquement pour les outils Rectangle/Ellipse */
            width: 40px; height: 40px;
            align-items: center; justify-content: center;
            border-radius: 8px;
            border: 1px solid var(--border-color);
            background: transparent;
            color: var(--text-secondary);
            cursor: pointer;
            margin-left: 2px;
            transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
        }
        .paint-fill-toggle svg { width: 18px; height: 18px; }
        .paint-fill-toggle:hover { background: rgba(255,255,255,0.08); color: var(--text-primary); }
        .paint-fill-toggle.active {
            background: hsla(var(--hue), calc(80% * var(--sat, 80) / 80), 55%, 0.18);
            border-color: var(--accent);
            color: var(--accent);
        }

        /* ==================================================================
           Panneau des calques façon Photoshop. .paint-workspace remplace le
           rôle que .paint-canvas-wrap tenait seul auparavant (flex:1 dans le
           flux colonne de .window-content) : c'est maintenant LUI le
           conteneur en ligne (canevas + panneau), .paint-canvas-wrap gardant
           son flex:1 mais désormais dans un contexte ROW plutôt que colonne.
           ================================================================== */
        .paint-workspace { flex: 1; min-height: 0; display: flex; overflow: hidden; }
        .paint-canvas-wrap { min-width: 0; } /* essentiel en contexte row : sans ça, pousse le panneau hors champ au lieu de rétrécir */

        .paint-layers-panel {
            position: relative;
            width: 220px;
            min-width: 160px; max-width: 420px;
            flex-shrink: 0;
            display: flex;
            flex-direction: column;
            background: var(--bg-taskbar);
            border-left: 1px solid var(--border-color);
            transition: background 0.6s ease;
        }

        .paint-layers-resize-handle {
            position: absolute; top: 0; bottom: 0; left: -3px;
            width: 6px;
            cursor: ew-resize;
            z-index: 3;
        }
        .paint-layers-resize-handle:hover, .paint-layers-resize-handle.dragging { background: var(--accent); opacity: 0.5; }

        .paint-layers-blend-row {
            display: flex; align-items: center; gap: 8px;
            padding: 8px 10px 6px;
            font-size: 0.6875rem;
            color: var(--text-secondary);
        }
        .paint-layers-blend-row span:first-child { flex-shrink: 0; }
        .paint-layers-blend-row select {
            flex: 1; min-width: 0;
            padding: 3px 6px; /* combobox moins haute que le style de base .paint-brush-select */
        }

        .paint-layers-opacity-row {
            padding: 4px 10px 10px;
            font-size: 0.6875rem;
            color: var(--text-secondary);
            border-bottom: 1px solid var(--border-color);
        }
        .paint-layers-opacity-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }
        .paint-layers-opacity-row input[type="range"] { width: 100%; } /* pleine largeur du panneau = plus précis qu'en partageant la ligne avec le libellé */
        .paint-layers-opacity-row .paint-size-value { flex-shrink: 0; min-width: 38px; text-align: right; }

        .paint-layers-list { flex: 1; min-height: 0; overflow-y: auto; padding: 6px; display: flex; flex-direction: column; gap: 3px; }

        .paint-layer-row {
            display: flex; align-items: center; gap: 8px;
            padding: 5px 6px;
            border-radius: 6px;
            border: 1px solid transparent;
            cursor: pointer;
            user-select: none;
            transition: background 0.12s ease, border-color 0.12s ease;
        }
        .paint-layer-row:hover { background: rgba(255,255,255,0.06); }
        .paint-layer-row.active { background: hsla(var(--hue), calc(80% * var(--sat, 80) / 80), 55%, 0.16); border-color: var(--accent); }
        .paint-layer-row.dragging { opacity: 0.4; }
        .paint-layer-row.drag-over { border-color: var(--accent); border-style: dashed; }
        .paint-layer-row.hidden-layer .paint-layer-name { opacity: 0.5; }

        .paint-layer-eye {
            flex-shrink: 0;
            width: 22px; height: 22px;
            display: flex; align-items: center; justify-content: center;
            border: none; background: transparent;
            color: var(--text-secondary);
            cursor: pointer;
            border-radius: 5px;
        }
        .paint-layer-eye svg { width: 16px; height: 16px; }
        .paint-layer-eye:hover { background: rgba(255,255,255,0.1); color: var(--text-primary); }
        .paint-layer-row.hidden-layer .paint-layer-eye { color: var(--text-secondary); opacity: 0.5; }

        .paint-layer-thumb {
            flex-shrink: 0;
            width: 52px; height: 38px;
            border-radius: 4px;
            border: 1px solid var(--border-color);
            background-image:
                linear-gradient(45deg, #bdbdbd 25%, transparent 25%, transparent 75%, #bdbdbd 75%, #bdbdbd),
                linear-gradient(45deg, #bdbdbd 25%, #e8e8e8 25%, #e8e8e8 75%, #bdbdbd 75%, #bdbdbd);
            background-size: 12px 12px;
            background-position: 0 0, 6px 6px;
            background-color: #fff;
        }

        .paint-layer-name {
            flex: 1; min-width: 0;
            font-size: 0.75rem;
            color: var(--text-primary);
            white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
        }
        .paint-layer-name-input {
            flex: 1; min-width: 0;
            font-size: 0.75rem;
            font-family: inherit;
            background: var(--bg-desktop);
            color: var(--text-primary);
            border: 1px solid var(--accent);
            border-radius: 4px;
            padding: 2px 5px;
        }

        .paint-layers-toolbar {
            display: flex; align-items: center; gap: 4px;
            padding: 6px 8px;
            border-top: 1px solid var(--border-color);
        }
        .paint-layers-toolbar button {
            width: 28px; height: 28px;
            display: flex; align-items: center; justify-content: center;
            border: none; background: transparent;
            color: var(--text-secondary);
            border-radius: 6px;
            cursor: pointer;
        }
        .paint-layers-toolbar button svg { width: 15px; height: 15px; }
        .paint-layers-toolbar button:hover:not(:disabled) { background: rgba(255,255,255,0.08); color: var(--text-primary); }
        .paint-layers-toolbar button:disabled { opacity: 0.35; cursor: default; }

        /* ---- Aide de Paint (Menu Aide > Aide de Paint) ----
           Réutilise .ui-requester-overlay/.ui-requester-box comme les autres
           dialogues de l'app (voir promptNewCanvas), mais en plus large et en
           colonne (au lieu du flex row par défaut) avec un corps scrollable :
           contrairement à un simple prompt, le contenu (présentation des
           outils + raccourcis) dépasse largement la hauteur d'un écran bas. */
        /* Fond à opacité FIXE à 90% (10% de transparence), indépendamment du
           réglage vitre global : en mode vitre, --bg-window devient translucide
           (voir body.glass-on plus haut, jusqu'à 90% de transparence) mais
           .ui-requester-box n'est pas dans la liste des sélecteurs qui reçoivent
           le backdrop-filter associé — résultat, un fond flou sans flou,
           illisible par-dessus une fenêtre Paint chargée. Ce dialogue étant
           avant tout un texte de référence à lire, on fixe ici une transparence
           légère et constante plutôt que de suivre le curseur vitre. */
        .paint-help-box { flex-direction: column; width: min(1353px, 94vw); max-width: min(1353px, 94vw); max-height: 84vh; padding: 0; overflow: hidden; background: hsla(var(--hue), calc(12% * var(--sat, 80) / 80), 16%, 0.9); }
        .paint-help-content { display: flex; flex-direction: column; min-height: 0; flex: 1; }
        .paint-help-header { display: flex; gap: 14px; align-items: flex-start; padding: 22px 26px 16px; flex-shrink: 0; }
        .paint-help-header-icon { width: 34px; height: 34px; flex-shrink: 0; color: var(--accent); }
        .paint-help-header-icon svg { width: 100%; height: 100%; }
        .paint-help-header .ui-requester-title { font-size: 1.125rem; margin-bottom: 4px; }
        .paint-help-intro { font-size: 0.8125rem; color: var(--text-secondary); line-height: 1.5; margin: 0; }
        .paint-help-body { flex: 1; min-height: 0; overflow-y: auto; padding: 0 26px 4px; }
        .paint-help-section { margin-bottom: 22px; }
        .paint-help-section h3 { font-size: 0.8125rem; font-weight: 700; color: var(--text-primary); text-transform: uppercase; letter-spacing: 0.04em; margin: 0 0 10px; padding-bottom: 6px; border-bottom: 1px solid var(--border-color); }
        .paint-help-section h4 { font-size: 0.75rem; font-weight: 600; color: var(--text-secondary); margin: 14px 0 8px; }
        .paint-help-section h4:first-of-type { margin-top: 0; }
        .paint-help-section p { font-size: 0.8125rem; color: var(--text-secondary); line-height: 1.5; margin: 0; }
        .paint-help-tool-row { display: flex; gap: 12px; align-items: flex-start; padding: 7px 0; }
        .paint-help-tool-icon { width: 20px; height: 20px; flex-shrink: 0; margin-top: 1px; color: var(--text-secondary); }
        .paint-help-tool-icon svg { width: 100%; height: 100%; }
        .paint-help-tool-row strong { display: block; font-size: 0.8125rem; color: var(--text-primary); font-weight: 600; margin-bottom: 2px; }
        .paint-help-tool-row span { font-size: 0.75rem; color: var(--text-secondary); line-height: 1.4; }
        .paint-help-shortcuts-grid { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; align-items: center; }
        .paint-help-kbd { justify-self: start; font-family: var(--mono, monospace); font-size: 0.6875rem; font-weight: 600; color: var(--text-primary); background: var(--bg-desktop); border: 1px solid var(--border-color); border-radius: 5px; padding: 2px 7px; white-space: nowrap; }
        .paint-help-shortcuts-grid span:nth-child(2n) { font-size: 0.8125rem; color: var(--text-secondary); }
        .paint-help-box .ui-requester-buttons { padding: 14px 26px; border-top: 1px solid var(--border-color); flex-shrink: 0; margin: 0; }

        /* ==================================================================
           App "Comparateur de texte" — réutilise .notepad-menu-bar/.notepad-dropdown,
           .notepad-gutter/.gutter-line/.notepad-textarea/.notepad-mirror, .notepad-status
           et .ui-requester-btn déjà définis plus haut. Uniquement le nécessaire ci-dessous :
           barre d'outils, panneaux d'édition à deux volets, vues de résultat (diff texte
           côte-à-côte/unifié, dump hexadécimal binaire), pastille de statistiques.
           ================================================================== */
        .tc-wrap { display: flex; flex-direction: column; height: 100%; color: var(--text-primary); }

        .tc-toolbar { display: flex; align-items: center; gap: 8px; padding: 8px 12px; background: var(--bg-taskbar); border-bottom: 1px solid var(--border-color); flex-shrink: 0; flex-wrap: wrap; transition: background 0.6s ease; }
        .tc-toolbar .ui-requester-btn { display: flex; align-items: center; gap: 6px; padding: 7px 14px; }
        .tc-toolbar .ui-requester-btn svg { width: 15px; height: 15px; flex-shrink: 0; }
        .tc-toolbar-spacer { flex: 1; }
        .tc-icon-btn { width: 32px; height: 32px; flex-shrink: 0; border-radius: 7px; border: 1px solid var(--border-color); background: transparent; color: var(--text-secondary); cursor: pointer; display: flex; align-items: center; justify-content: center; transition: background 0.15s, color 0.15s, border-color 0.15s; }
        .tc-icon-btn:hover { background: var(--accent); color: #fff; border-color: var(--accent); }
        .tc-icon-btn svg { width: 16px; height: 16px; }

        .tc-segmented { display: flex; border: 1px solid var(--border-color); border-radius: 7px; overflow: hidden; }
        .tc-segmented-btn { padding: 6px 12px; font-size: 0.75rem; background: transparent; border: none; color: var(--text-secondary); cursor: pointer; transition: background 0.15s, color 0.15s; }
        .tc-segmented-btn + .tc-segmented-btn { border-left: 1px solid var(--border-color); }
        .tc-segmented-btn:hover { background: rgba(255,255,255,0.08); color: var(--text-primary); }
        .tc-segmented-btn.active { background: var(--accent); color: #fff; }

        .tc-body { flex: 1; overflow: hidden; display: flex; flex-direction: column; min-height: 0; }

        /* ---- Mode édition : deux volets ---- */
        .tc-edit-view { flex: 1; display: flex; overflow: hidden; min-height: 0; }
        .tc-pane { flex: 1; min-width: 0; display: flex; flex-direction: column; background: rgba(0,0,0,0.2); }
        .tc-pane + .tc-pane { border-left: 1px solid var(--border-color); }
        .tc-pane-header { display: flex; align-items: center; gap: 8px; padding: 7px 10px; background: var(--bg-taskbar); border-bottom: 1px solid var(--border-color); flex-shrink: 0; transition: background 0.6s ease; }
        .tc-pane-title { font-size: 0.75rem; font-weight: 700; color: var(--text-primary); white-space: nowrap; }
        .tc-pane-filename { font-size: 0.6875rem; color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1; }
        .tc-pane-actions { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
        .tc-pane-editor { flex: 1; display: flex; overflow: hidden; min-height: 0; }
        .tc-pane-counts { padding: 4px 10px; font-size: 0.6562rem; color: var(--text-secondary); background: var(--bg-taskbar); border-top: 1px solid var(--border-color); flex-shrink: 0; display: flex; gap: 12px; transition: background 0.6s ease; }

        .tc-pane-binary-card { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; padding: 24px; text-align: center; }
        .tc-pane-binary-card svg { width: 46px; height: 46px; color: var(--accent); opacity: 0.85; }
        .tc-bin-name { font-size: 0.8125rem; font-weight: 600; word-break: break-all; }
        .tc-bin-meta { font-size: 0.6875rem; color: var(--text-secondary); font-family: Consolas, monospace; }
        .tc-bin-remove-btn { margin-top: 4px; }

        /* ---- Mode résultat ---- */
        .tc-result-view { flex: 1; display: flex; flex-direction: column; overflow: hidden; min-height: 0; }
        .tc-stats-panel { display: flex; flex-wrap: wrap; gap: 8px 20px; padding: 10px 16px; background: var(--bg-taskbar); border-bottom: 1px solid var(--border-color); flex-shrink: 0; transition: background 0.6s ease; }
        .tc-stat { display: flex; align-items: baseline; gap: 5px; font-size: 0.75rem; }
        .tc-stat-label { color: var(--text-secondary); }
        .tc-stat-value { font-weight: 700; font-family: Consolas, monospace; }
        .tc-stat-value.tc-good { color: var(--green); }
        .tc-stat-value.tc-bad { color: var(--danger); }
        .tc-stat-value.tc-warn { color: var(--amber); }

        /* font-size volontairement ici (et pas sur .tc-diff-col/.tc-hex-col plus bas,
           recréés à chaque rendu via innerHTML) : c'est le niveau que le zoom du
           Comparateur de texte cible en JS (voir applyZoom() dans textcompare.js),
           hérité ensuite par les lignes/dumps enfants qui n'ont pas leur propre
           font-size explicite. */
        .tc-diff-columns { flex: 1; display: flex; overflow: hidden; min-height: 0; font-family: Consolas, monospace; font-size: 0.8125rem; }
        .tc-diff-col { flex: 1; min-width: 0; overflow-y: auto; overflow-x: auto; }
        .tc-diff-col + .tc-diff-col { border-left: 1px solid var(--border-color); }
        .tc-diff-unified { flex: 1; overflow-y: auto; overflow-x: auto; font-family: Consolas, monospace; font-size: 0.8125rem; }

        .tc-line { display: flex; white-space: pre; }
        .tc-line-num { flex-shrink: 0; width: 46px; padding: 1px 8px; text-align: right; color: var(--text-secondary); opacity: 0.55; user-select: none; border-right: 1px solid var(--border-color); }
        .tc-line-content { flex: 1; padding: 1px 10px; min-width: 0; }
        .tc-line-marker { flex-shrink: 0; width: 18px; text-align: center; user-select: none; opacity: 0.8; }
        .tc-line-empty .tc-line-content { opacity: 0.25; }
        .tc-line-add { background: hsla(140, 70%, 45%, 0.16); }
        .tc-line-add .tc-line-num { background: hsla(140, 70%, 45%, 0.1); }
        .tc-line-del { background: hsla(0, 70%, 50%, 0.16); }
        .tc-line-del .tc-line-num { background: hsla(0, 70%, 50%, 0.1); }
        .tc-line-mod { background: hsla(40, 90%, 55%, 0.14); }
        .tc-line-mod .tc-line-num { background: hsla(40, 90%, 55%, 0.1); }
        .tc-word-add { background: hsla(140, 70%, 45%, 0.45); border-radius: 2px; }
        .tc-word-del { background: hsla(0, 70%, 55%, 0.45); border-radius: 2px; text-decoration: line-through; text-decoration-thickness: 1px; }

        /* ---- Vue binaire (hex) ---- */
        .tc-hex-columns { flex: 1; display: flex; overflow: hidden; min-height: 0; font-family: Consolas, monospace; font-size: 0.75rem; }
        .tc-hex-col { flex: 1; min-width: 0; overflow: auto; padding-bottom: 12px; }
        .tc-hex-col + .tc-hex-col { border-left: 1px solid var(--border-color); }
        .tc-hex-col-header { position: sticky; top: 0; padding: 6px 10px; background: var(--bg-taskbar); border-bottom: 1px solid var(--border-color); font-size: 0.6875rem; font-weight: 700; z-index: 2; }
        .tc-hex-row { display: flex; white-space: pre; padding: 0 8px; }
        .tc-hex-offset { flex-shrink: 0; width: 74px; color: var(--text-secondary); opacity: 0.6; }
        .tc-hex-bytes { flex-shrink: 0; letter-spacing: 1px; }
        .tc-hex-byte { display: inline-block; width: 1.5em; text-align: center; }
        .tc-hex-byte-diff { background: hsla(0, 70%, 55%, 0.4); border-radius: 2px; }
        .tc-hex-ascii { margin-left: 14px; color: var(--text-secondary); }
        .tc-hex-ascii .tc-hex-byte-diff { background: hsla(0, 70%, 55%, 0.4); color: var(--text-primary); }
        .tc-hex-loadmore { display: block; margin: 10px auto; }

        .tc-empty-state { flex: 1; display: flex; align-items: center; justify-content: center; color: var(--text-secondary); font-size: 0.8125rem; text-align: center; padding: 20px; }

        body.theme-3d .tc-toolbar { box-shadow: inset 0 1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 50%, 0.3); border-bottom: none; }
        body.theme-3d .tc-pane-header, body.theme-3d .tc-pane-counts, body.theme-3d .tc-stats-panel, body.theme-3d .tc-hex-col-header { box-shadow: inset 0 1px 0 0 hsla(var(--hue), calc(20% * var(--sat, 80) / 80), 50%, 0.25); }
        .paint-layers-toolbar-sep { flex: 1; }

        /* ================== App "Calendrier" ================== */
        .cal-shell { flex: 1; display: flex; flex-direction: column; min-height: 0; background: var(--bg-window); position: relative; }

        .cal-header { display: flex; align-items: center; gap: 12px; padding: 12px 16px; border-bottom: 1px solid var(--border-color); flex-shrink: 0; flex-wrap: wrap; }
        .cal-nav { display: flex; align-items: center; gap: 6px; }
        .cal-nav-btn { width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; border: 1px solid var(--border-color); background: transparent; color: var(--text-secondary); border-radius: 7px; cursor: pointer; }
        .cal-nav-btn:hover { background: rgba(255,255,255,0.06); color: var(--text-primary); }
        .cal-nav-btn svg { width: 15px; height: 15px; }
        .cal-today-btn { padding: 6px 12px; border-radius: 7px; border: 1px solid var(--border-color); background: transparent; color: var(--text-secondary); font-family: inherit; font-size: 0.75rem; cursor: pointer; }
        .cal-today-btn:hover { background: rgba(255,255,255,0.06); color: var(--text-primary); }
        .cal-title { margin-left: 6px; font-size: 1rem; font-weight: 600; color: var(--text-primary); text-transform: capitalize; }
        .cal-view-toggle { display: flex; gap: 2px; background: var(--bg-desktop); border: 1px solid var(--border-color); border-radius: 8px; padding: 2px; margin-left: auto; }
        .cal-view-toggle button { padding: 6px 12px; border: none; background: transparent; color: var(--text-secondary); font-family: inherit; font-size: 0.75rem; border-radius: 6px; cursor: pointer; }
        .cal-view-toggle button.active { background: var(--accent); color: #fff; }
        .cal-add-btn { display: flex; align-items: center; gap: 6px; padding: 7px 14px; border: none; border-radius: 8px; background: var(--accent); color: #fff; font-family: inherit; font-size: 0.75rem; cursor: pointer; transition: filter 0.15s ease; }
        .cal-add-btn:hover { filter: brightness(1.1); }
        .cal-add-btn svg { width: 14px; height: 14px; }

        .cal-body { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }

        @keyframes cal-nav-in-right { from { opacity: 0; transform: translateX(14px); } to { opacity: 1; transform: translateX(0); } }
        @keyframes cal-nav-in-left { from { opacity: 0; transform: translateX(-14px); } to { opacity: 1; transform: translateX(0); } }
        @keyframes cal-nav-in-fade { from { opacity: 0; } to { opacity: 1; } }
        .cal-nav-in-right { animation: cal-nav-in-right 0.18s ease; }
        .cal-nav-in-left { animation: cal-nav-in-left 0.18s ease; }
        .cal-nav-in-fade { animation: cal-nav-in-fade 0.15s ease; }

        /* ---- Vue Mois ---- */
        .cal-month { flex: 1; display: flex; flex-direction: column; min-height: 0; }
        .cal-month-weekdays { display: grid; grid-template-columns: repeat(7, 1fr); border-bottom: 1px solid var(--border-color); flex-shrink: 0; }
        .cal-weekday { padding: 8px 6px; text-align: center; font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-secondary); }
        .cal-month-grid { flex: 1; min-height: 0; display: grid; grid-template-columns: repeat(7, 1fr); grid-template-rows: repeat(6, 1fr); }
        .cal-day-cell { border-right: 1px solid var(--border-color); border-bottom: 1px solid var(--border-color); padding: 6px; display: flex; flex-direction: column; gap: 3px; cursor: pointer; overflow: hidden; transition: background 0.15s ease; }
        .cal-day-cell:hover { background: rgba(255,255,255,0.03); }
        .cal-day-cell.other-month { opacity: 0.3; }
        .cal-day-cell.is-today .cal-day-num { background: var(--accent); color: #fff; width: 26px; height: 26px; font-size: 0.8125rem; font-weight: 600; }
        .cal-day-num { width: 22px; height: 22px; display: flex; align-items: center; justify-content: center; font-size: 0.75rem; border-radius: 50%; color: var(--text-primary); flex-shrink: 0; }
        .cal-day-top { display: flex; align-items: center; justify-content: space-between; gap: 4px; flex-shrink: 0; }
        .cal-day-task-badge { display: flex; align-items: center; gap: 2px; padding: 1px 5px; border-radius: 8px; background: rgba(255,255,255,0.08); color: var(--text-secondary); font-size: 0.625rem; cursor: pointer; }
        .cal-day-task-badge svg { width: 10px; height: 10px; }
        .cal-week-task-badge { margin-top: 2px; cursor: pointer; }
        .cal-day-pills { display: flex; flex-direction: column; gap: 2px; min-height: 0; overflow: hidden; }
        .cal-event-pill { display: flex; align-items: center; gap: 4px; padding: 2px 6px; border-radius: 4px; background: hsla(0,0%,50%,0.12); border-left: 3px solid var(--pill-color, var(--accent)); font-size: 0.6875rem; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer; }
        .cal-event-pill:hover { background: hsla(0,0%,50%,0.2); }
        .cal-pill-time { color: var(--text-secondary); font-size: 0.625rem; flex-shrink: 0; }
        .cal-pill-title { overflow: hidden; text-overflow: ellipsis; }
        .cal-event-more { font-size: 0.625rem; color: var(--text-secondary); padding: 1px 6px; }

        /* ---- Vue Semaine ---- */
        .cal-week { flex: 1; display: flex; flex-direction: column; min-height: 0; }
        .cal-week-sticky-top { position: sticky; top: 0; z-index: 5; background: var(--bg-window); }
        .cal-week-header, .cal-week-allday { display: grid; grid-template-columns: 46px repeat(7, 1fr); flex-shrink: 0; }
        .cal-week-header { border-bottom: 1px solid var(--border-color); }
        .cal-week-gutter { border-right: 1px solid transparent; }
        .cal-week-daycol-head { display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 6px 2px; border-left: 1px solid var(--border-color); }
        .cal-week-daycol-head.is-today .cal-week-dom { background: var(--accent); color: #fff; }
        .cal-week-dow { font-size: 0.625rem; text-transform: uppercase; color: var(--text-secondary); letter-spacing: 0.03em; }
        .cal-week-dom { width: 22px; height: 22px; display: flex; align-items: center; justify-content: center; border-radius: 50%; font-size: 0.8125rem; color: var(--text-primary); }
        .cal-week-allday { min-height: 6px; border-bottom: 1px solid var(--border-color); }
        .cal-week-allday-col { border-left: 1px solid var(--border-color); padding: 2px 4px; display: flex; flex-direction: column; gap: 2px; }
        .cal-allday-chip { padding: 2px 6px; border-radius: 4px; background: hsla(0,0%,50%,0.12); border-left: 3px solid var(--pill-color, var(--accent)); font-size: 0.6875rem; color: var(--text-primary); cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
        .cal-week-scroll { flex: 1; min-height: 0; overflow-y: auto; }
        .cal-week-grid { display: grid; grid-template-columns: 46px repeat(7, 1fr); position: relative; margin-top: 6px; }
        .cal-week-hours { display: flex; flex-direction: column; }
        .cal-hour-label { height: 40px; font-size: 0.625rem; color: var(--text-secondary); text-align: right; padding-right: 6px; box-sizing: border-box; transform: translateY(-6px); }
        .cal-week-daycol { position: relative; border-left: 1px solid var(--border-color); }
        .cal-hour-slot { height: 40px; border-bottom: 1px solid hsla(0,0%,50%,0.08); box-sizing: border-box; cursor: pointer; }
        .cal-hour-slot:hover { background: rgba(255,255,255,0.03); }
        .cal-week-event { position: absolute; left: 2px; right: 2px; border-radius: 5px; background: hsla(0,0%,50%,0.18); border-left: 3px solid var(--pill-color, var(--accent)); padding: 2px 6px; overflow: hidden; cursor: pointer; display: flex; flex-direction: column; z-index: 1; }
        .cal-week-event:hover { filter: brightness(1.2); }
        .cal-week-event-time { font-size: 0.5625rem; color: var(--text-secondary); }
        .cal-week-event-title { font-size: 0.6875rem; color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

        /* ---- Panneaux superposés (détail jour / éditeur) ---- */
        .cal-overlay { position: absolute; inset: 0; background: rgba(0,0,0,0.45); display: flex; justify-content: flex-end; z-index: 20; animation: cal-fade-in 0.15s ease; }
        @keyframes cal-fade-in { from { opacity: 0; } to { opacity: 1; } }
        @keyframes cal-panel-slide-in { from { transform: translateX(24px); opacity: 0.5; } to { transform: translateX(0); opacity: 1; } }
        .cal-panel { width: 340px; max-width: 92%; height: 100%; background: var(--bg-window); border-left: 1px solid var(--border-color); display: flex; flex-direction: column; box-shadow: -8px 0 24px rgba(0,0,0,0.3); animation: cal-panel-slide-in 0.2s ease; }
        .cal-panel-header { display: flex; align-items: center; justify-content: space-between; padding: 14px 16px; border-bottom: 1px solid var(--border-color); font-size: 0.875rem; font-weight: 600; color: var(--text-primary); text-transform: capitalize; flex-shrink: 0; }
        .cal-panel-close { width: 26px; height: 26px; border: none; background: transparent; color: var(--text-secondary); border-radius: 6px; cursor: pointer; font-size: 0.875rem; }
        .cal-panel-close:hover { background: rgba(255,255,255,0.08); color: var(--text-primary); }
        .cal-panel-body { flex: 1; overflow-y: auto; padding: 14px 16px; display: flex; flex-direction: column; gap: 10px; }
        .cal-panel-section-title { font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-secondary); margin-top: 4px; }
        .cal-panel-tasks-title { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border-color); }
        .cal-panel-events, .cal-panel-tasks { display: flex; flex-direction: column; gap: 4px; }
        .cal-panel-empty { color: var(--text-secondary); font-size: 0.75rem; padding: 8px 2px; }
        .cal-panel-event { display: flex; align-items: center; gap: 8px; padding: 8px; border-radius: 7px; cursor: pointer; }
        .cal-panel-event:hover { background: rgba(255,255,255,0.05); }
        .cal-panel-event-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--pill-color, var(--accent)); flex-shrink: 0; }
        .cal-panel-event-title { font-size: 0.8125rem; color: var(--text-primary); }
        .cal-panel-event-meta { font-size: 0.6875rem; color: var(--text-secondary); }
        .cal-panel-add-btn { display: flex; align-items: center; justify-content: center; gap: 6px; padding: 8px; border-radius: 7px; border: 1px dashed var(--border-color); background: transparent; color: var(--text-secondary); font-family: inherit; font-size: 0.75rem; cursor: pointer; }
        .cal-panel-add-btn:hover { background: rgba(255,255,255,0.06); color: var(--accent); border-color: var(--accent); }
        .cal-panel-add-btn svg { width: 14px; height: 14px; }
        .cal-panel-open-todo { border-style: solid; }
        .cal-panel-task { display: flex; align-items: center; gap: 8px; padding: 6px 8px; font-size: 0.75rem; color: var(--text-primary); }
        .cal-panel-task.done { color: var(--text-secondary); text-decoration: line-through; }
        .cal-task-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--text-secondary); flex-shrink: 0; }
        .cal-task-list { margin-left: auto; font-size: 0.625rem; color: var(--text-secondary); }

        /* ---- Éditeur d'événement ---- */
        .cal-editor-panel { width: 380px; }
        .cal-editor-body { gap: 12px; }
        .cal-input { width: 100%; padding: 8px 10px; background: var(--bg-desktop); border: 1px solid var(--border-color); border-radius: 7px; color: var(--text-primary); font-family: inherit; font-size: 0.8125rem; box-sizing: border-box; }
        .cal-input:focus { outline: none; border-color: var(--accent); }
        .cal-input-title { font-size: 0.9375rem; font-weight: 600; }
        .cal-textarea { min-height: 64px; resize: vertical; font-family: inherit; }
        .cal-field { display: flex; flex-direction: column; gap: 4px; flex: 1; min-width: 0; }
        .cal-field > span { font-size: 0.6875rem; color: var(--text-secondary); }
        .cal-field-narrow { max-width: 90px; flex: 0 0 90px; }
        .cal-field-row { display: flex; gap: 10px; align-items: flex-end; }
        .cal-checkbox-field { display: flex; align-items: center; gap: 6px; font-size: 0.75rem; color: var(--text-secondary); padding-bottom: 8px; white-space: nowrap; }
        .cal-color-row { display: flex; gap: 8px; }
        .cal-color-swatch { width: 24px; height: 24px; border-radius: 50%; border: 2px solid transparent; background: var(--pill-color); cursor: pointer; padding: 0; }
        .cal-color-swatch.selected { border-color: var(--text-primary); }
        .cal-editor-actions { display: flex; align-items: center; gap: 8px; padding: 12px 16px; border-top: 1px solid var(--border-color); flex-shrink: 0; }
        .cal-editor-fill { flex: 1; }
        .cal-btn { padding: 7px 14px; border-radius: 7px; border: 1px solid var(--border-color); background: transparent; color: var(--text-secondary); font-family: inherit; font-size: 0.75rem; cursor: pointer; }
        .cal-btn:hover { background: rgba(255,255,255,0.06); color: var(--text-primary); }
        .cal-btn-primary { background: var(--accent); color: #fff; border-color: transparent; }
        .cal-btn-primary:hover { filter: brightness(1.1); }
        .cal-btn-danger { color: var(--danger); border-color: hsla(0,70%,50%,0.35); }
        .cal-btn-danger:hover { background: hsla(0,70%,50%,0.14); }
