        html { scroll-behavior: smooth; }
        
        /* --- 1. VARIABLES : DARK MODE (Khaki Green Style) --- */
        :root {
            /* Backgrounds : Deep Carbon */
            --bg-color: #0c0d10; 
            --card-bg: #16181d; 
            
            /* Text : Soft White */
            --text-main: #f3f4f6;
            --text-muted: #8b92a5;
            
            /* The Accent : Dark Khaki Green */
            --accent: #8a9a5b; 
            
            /* Borders : Glass effect */
            --border: rgba(255, 255, 255, 0.06);
            --card-shadow: 0 4px 20px rgba(0, 0, 0, 0.2); 
            --hover-shadow: 0 12px 30px -10px rgba(0, 0, 0, 0.7);
            
            /* Navigation and Sidebar */
            --ind-bg: #0c0d10;
            --ind-border: rgba(255, 255, 255, 0.04);
            --ind-accent: #8a9a5b;
            
            /* Inputs */
            --input-bg: rgba(255, 255, 255, 0.05);
            --hover-bg: rgba(255, 255, 255, 0.08);
            
            /* Semantic Colors */
            --fast-grower: #10b981; --success: #10b981;
            --stalwart: #3b82f6;
            --slow-grower: #6b7280;
            --cyclical: #f59e0b; --warning: #f59e0b;
            --turnaround: #ef4444; --danger: #ef4444;
            --asset-play: #8b5cf6;
            /* Catégories crypto sans équivalent Lynch (DeFi, RWA) : deux
               teintes à elles, pour ne pas faire lire « Fast Grower » ou
               « Asset Play » dans une pastille de protocole ou de fonds tokenisé. */
            --cat-defi: #06b6d4;
            --cat-rwa: #b08850;
            /* Aucune des 6 strategies ETF (broad core, secteur, factor,
               levier/inverse, matieres premieres, cash) n'a de couleur dediee
               dans l'app -- un seul ton neutre pour les tuiles de suggestion
               plutot qu'inventer une palette a 6 teintes sans base existante. */
            --cat-fund: #0d9488;
            /* « Unknown » n'est pas une 7e catégorie Lynch : c'est l'absence de
               classement (pas d'historique de BPA sur 3 ans). Teinte neutre et
               plus sourde que --slow-grower, pour qu'elle ne se lise pas comme
               un verdict (audit ELEC 2026-10). */
            --unknown-cat: #8a8a93;

            /* Verdict de l'Investor Lens (pass/warn/fail/na) : palette dédiée,
               distincte des 6 couleurs de catégorie Lynch ci-dessus (un check
               "pass" en vert émeraude Fast Grower prêtait à confusion : est-ce
               le verdict, ou la catégorie du titre ?). --v-pass reprend l'accent
               de la marque plutôt que --fast-grower ; --v-warn est un ambre plus
               sourd que --cyclical ; --v-fail réutilise --danger (le rouge
               "danger" est un code universel, sans ambiguïté celui-là). */
            --v-pass: #8a9a5b; --v-pass-dim: rgba(138, 154, 91, 0.16);
            --v-warn: #c2870c; --v-warn-dim: rgba(194, 135, 12, 0.16);
            --v-fail: #ef4444; --v-fail-dim: rgba(239, 68, 68, 0.14);
            --v-na: #6b7280; --v-na-dim: rgba(107, 114, 128, 0.14);

            /* Journal : note libre vs log structuré */
            --j-note: #f59e0b;
            --j-log: #3b82f6;

            /* ---- SYSTÈME TYPOGRAPHIQUE ----
               3 familles, une par couche : UI (sans) pour l'interface et les
               titres, MONO pour tout ce qui est chiffre / ticker / horodatage,
               SERIF réservée au corps de texte éditorial (leçons Academy).
               8 tailles, une par rôle — on ne met JAMAIS une autre valeur de
               font-size ailleurs, on pointe un de ces tokens. */
            --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
            --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Courier New", monospace;
            --font-serif: "Literata", Georgia, "Iowan Old Style", "Palatino Linotype", "Times New Roman", serif;

            /* Échelle calée sur la fiche action (.sd-page), la référence :
               sans-serif + font-variant-numeric partout, PAS de monospace
               pour les données. */
            --fs-hero:    2.5rem;    /* hero d'en-tête de fiche : nom + cours */
            --fs-display: 1.5rem;    /* le grand nombre unique d'un encart (= .sd-val) */
            --fs-title:   1.5rem;    /* titre de page / de leçon */
            --fs-h2:      1.15rem;   /* titre de carte / de section (= .sd-page h2) */
            --fs-h3:      1rem;      /* sous-titre */
            --fs-read:    0.82rem;   /* corps des leçons : cale la HAUTEUR optique sur le reste
                                       de l'app — Georgia a une œil plus grande, donc un poil
                                       sous --fs-body pour un rendu équivalent. L'« éditorial »
                                       vient de la serif + l'interligne, pas d'un corps plus gros */
            --fs-body:    0.85rem;   /* texte d'interface, cellules, lignes (= .sd-stat-row) */
            --fs-sm:      0.78rem;   /* labels, texte secondaire (= .sd-label) */
            --fs-eyebrow: 0.78rem;   /* libellés MAJUSCULES (= .sd-subhead) */
            --fs-xs:      0.72rem;   /* méta, horodatages, pastilles (= .sd-note) */
        }

        /* --- 2. VARIABLES : LIGHT MODE (Anthracite — fonds gris foncé, accent vert conservé) ---
           Sélecteur sur html.light-mode EN PLUS de body.light-mode : un script
           inline dans <head> (index.html) pose la classe sur <html> avant même
           que le CSS charge, pour peindre le bon fond au tout premier rendu --
           sans ça, la page s'affichait en blanc pur (fond par défaut du
           navigateur) puis basculait sur le gris foncé du dark mode (variante
           sans classe, voir plus haut) avant que app.js, chargé en tout dernier
           dans <body>, ne pose enfin body.light-mode -- un flash blanc -> noir
           -> gris clair bien visible au chargement. */
        html.light-mode, body.light-mode {
            /* Backgrounds : le même vert très pâle que les pages Tools publiques
               (#f4f7f6), pour qu'ouvrir un outil depuis le Terminal ne fasse
               pas de rupture de fond. Les cartes restent quasi blanches : c'est
               leur contraste avec ce fond qui les détache. */
            --bg-color: #f4f7f6;
            --card-bg: #ffffff;

            /* Text : quasi-noir Apple */
            --text-main: #1d1d1f;
            --text-muted: #6e6e73;

            /* The Accent : vert plus foncé pour fond clair */
            --accent: #5f7040;

            /* Borders & ombres : élévation douce */
            --border: rgba(0, 0, 0, 0.07);
            --card-shadow: 0 1px 3px rgba(0, 0, 0, 0.04), 0 6px 16px -4px rgba(0, 0, 0, 0.06);
            --hover-shadow: 0 4px 10px rgba(0, 0, 0, 0.06), 0 16px 32px -8px rgba(0, 0, 0, 0.10);

            /* Navigation */
            --ind-bg: #f7f7f9;
            --ind-border: rgba(0, 0, 0, 0.06);
            --ind-accent: #5f7040;

            /* Inputs */
            --input-bg: #ffffff;
            --hover-bg: #e8e8ec;

            --slow-grower: #86868b;

            /* Verdict de l'Investor Lens, variante fond clair. */
            --v-pass: #5f7040; --v-pass-dim: rgba(95, 112, 64, 0.12);
            --v-warn: #a15c00; --v-warn-dim: rgba(161, 92, 0, 0.12);
            --v-fail: #d1373b; --v-fail-dim: rgba(209, 55, 59, 0.10);
            --v-na: #86868b; --v-na-dim: rgba(134, 134, 139, 0.12);
        }

        /* --- 3. STRUCTURE GENERALE ET SHAPES (Bord-radius) --- */
        body { font-family: var(--font-ui); background-color: var(--bg-color); color: var(--text-main); margin: 0; padding: 0; min-height: 100vh; transition: background-color 0.3s, color 0.3s; }
        .page-title { font-size: var(--fs-display); font-weight: 700; color: var(--text-main); margin: 0 0 5px 0; }
        .page-subtitle { color: var(--text-muted); font-size: var(--fs-h3); margin-top: 0; }
        /* utilitaire : bascule un fragment en police chiffres */
        .mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
        
        #login-screen { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: var(--bg-color); z-index: 9999; display: flex; flex-direction: column; align-items: center; justify-content: center; }
        /* Au chargement : on masque l'encart de connexion tant que /api/me n'a
           pas répondu — sinon il apparaît une fraction de seconde avant que
           l'app connectée ne prenne le dessus. Fond neutre le temps du check. */
        body.booting #login-screen > * { visibility: hidden; }
        
        /* --- Arrondis généreux et Ombres Apple pour TOUS les encarts --- */
        .login-box, .module-card, .table-container, .filter-panel, .widget, .sd-card, .lesson-item, .lesson-content, .tv-chart-container, #section-overview, .sd-hero, .comm-rail, .comm-feed {
            background-color: var(--card-bg); 
            border: 1px solid var(--border); 
            border-radius: 16px; 
            box-shadow: var(--card-shadow); /* <-- L'ombre s'applique maintenant au tableau et aux filtres ! */
            transition: background-color 0.3s, border-color 0.3s, box-shadow 0.3s, transform 0.3s;
        }

        /* En-tete d'une fiche (action ou fonds) : la carte qui porte le nom,
           le cours et les reperes. La fiche action l'avait en styles inline sur
           son seul id ; c'est une classe pour que les deux fiches la partagent. */
        .sd-hero { padding: 30px; margin-bottom: 30px; }

        .login-box { padding: 40px; text-align: center; box-shadow: var(--hover-shadow); width: 100%; max-width: 380px; box-sizing: border-box; }
      
        /* --- 1. Login & Textareas (Sans impacter le reste de l'application) --- */
        .login-input, .sd-textarea { 
            width: 100%; padding: 12px 15px; margin: 8px 0; border-radius: 12px; 
            border: 1px solid var(--border); background-color: var(--input-bg); 
            color: var(--text-main); box-sizing: border-box; font-size: var(--fs-h3); transition: 0.2s;
        }
        .login-input:focus, .sd-textarea:focus { outline: none; border-color: var(--accent); background-color: var(--hover-bg); }

        /* --- 2. Formulaires & Filtres du Screener (Correction des marges) --- */
        .filter-group select, .filter-group input[type="number"], .columns-dropdown-btn { 
            height: 40px; border: 1px solid var(--border); border-radius: 10px; 
            padding: 0 12px; width: 100%; box-sizing: border-box; margin: 0;
            background-color: var(--input-bg); color: var(--text-main); transition: 0.2s; 
        }
        .filter-group select:focus, .filter-group input[type="number"]:focus { 
            outline: none; border-color: var(--accent); 
        }

        /* --- 3. Correction des Menus Déroulants (Select) --- */
        /* Les options doivent avoir un fond plein pour être lisibles au clic */
        .filter-group select option {
            background-color: var(--card-bg);
            color: var(--text-main);
        }

        /* --- 4. Correction des Cases à Cocher (Menu Colonnes) --- */
        /* On force le style natif pour ne pas hériter des gros arrondis Finary */
        .columns-dropdown-menu input[type="checkbox"] { 
            width: auto !important; height: auto !important; margin: 0 8px 0 0 !important; 
            padding: 0 !important; display: inline-block; appearance: auto !important;
            background-color: initial !important; border: none !important;
        }
        
        /* --- Arrondis pilules 10px Finary Style pour les boutons --- */
        .login-btn, button, .nav-link, .tab-btn { 
            border-radius: 10px; /* Arrondi pilule Finary */
            cursor: pointer; transition: 0.2s;
        }
        
        .login-btn { width: 100%; padding: 12px; margin-top: 20px; background-color: var(--accent); color: #fff; font-size: var(--fs-h3); font-weight: 700; border: none; }
        .login-btn:hover { filter: brightness(1.1); }
        
        /* box-sizing: sinon `width: 100%` + le décalage du rail (padding-left)
           déborde la fenêtre de la largeur du rail — barre de défilement
           horizontale, et tout le contenu poussé de travers. */
        #app-container { display: none; width: 100%; box-sizing: border-box; }
        .top-navbar { position: fixed; top: 0; left: 0; width: 100%; height: 65px; background: var(--ind-bg); border-bottom: 1px solid var(--ind-border); display: flex; align-items: center; justify-content: space-between; padding: 0 20px; z-index: 160; box-sizing: border-box; transition: 0.3s; }
        .nav-left { display: flex; align-items: center; gap: 15px; min-width: 0; }
        .hamburger-btn { background: none; border: none; color: var(--ind-accent); font-size: var(--fs-display); }
        
        /* --- LOGO : deux SVG superposés (couleurs multiples -> pas gérable
             par un simple currentColor), celui qui correspond au thème actif
             est affiché via body.light-mode. Même marque partout maintenant :
             les feuilles seules (--mark) dans le terminal, la marque + le nom
             (taille par défaut) sur l'accueil public et l'écran de connexion. --- */
        .brand-logo { display: flex; align-items: center; cursor: pointer; }
        .brand-logo .logo-img { height: 54px; width: auto; display: block; }
        .brand-logo .logo-img--light { display: none; }
        body.light-mode .brand-logo .logo-img--dark { display: none; }
        body.light-mode .brand-logo .logo-img--light { display: block; }
        @media (max-width: 480px) { .brand-logo .logo-img { height: 44px; } }
        .brand-logo--mark .logo-img { height: 38px; }
        @media (max-width: 480px) { .brand-logo--mark .logo-img { height: 32px; } }
        /* "exsys" sous la marque (demandé pour la version icône seule, dans
           le terminal) : passe en colonne, icône gardée à sa taille d'avant
           (38px / 32px mobile ci-dessus, inchangé) -- seul le bloc logo
           grandit un peu pour loger le libellé, pas la top-navbar
           (height:65px fixe, voir plus haut) : son align-items:center
           recentre tout seul le bloc, tant que le total reste
           confortablement sous 65px. */
        .brand-logo--mark { flex-direction: column; align-items: center; gap: 2px; line-height: 1; }
        .brand-logo-label { font-size: var(--fs-xs); font-weight: 800; letter-spacing: 1.5px;
            text-transform: uppercase; color: var(--text-muted); line-height: 1; }
        @media (max-width: 480px) {
            .brand-logo-label { font-size: var(--fs-xs); letter-spacing: 1px; }
        }

        /* --- 4. GESTION DU BOUTON DE MODE CONTEXTUEL A COTÉ DE LOGOUT --- */
        .nav-right { display: flex; gap: 10px; align-items: center; }
        
        /* Le Bouton Mode Contextuel (Style Finary, Cuivre en sombre, Gris en clair) */
        #go-light-btn { 
            display: inline-flex; align-items: center; justify-content: center; width: auto; 
            padding: 6px 12px; font-size: var(--fs-body); font-weight: 700; text-transform: uppercase;
            border-radius: 8px; /* Arrondi léger pilule */
            transition: 0.2s;
        }
        
        /* Style Sombre : Cuivré/Or */
        #go-light-btn { background-color: var(--accent); color: #fff; border: none; }
        #go-light-btn:hover { filter: brightness(1.1); }

        /* Style Clair : Gris carbone */
        .light-mode #go-light-btn { background-color: var(--card-bg); color: var(--text-main); border: 1px solid var(--border); }
        .light-mode #go-light-btn:hover { background-color: rgba(255,255,255,0.08); }

        .logout-btn { padding: 6px 12px; background: rgba(255,255,255,0.05); color: var(--text-muted); border: 1px solid var(--border); border-radius: 8px; font-size: var(--fs-body); transition: 0.2s; }
        .logout-btn:hover { background: rgba(255,255,255,0.1); color: var(--text-main); }
        
        /* --- 5. MENU LATERAL : rail d'icônes (icône + libellé d'un mot) --- */
        .sidebar {
            /* bottom: 0 plutôt qu'une hauteur en 100vh : sur mobile, 100vh compte
               la barre d'adresse même quand elle est masquée, et Settings /
               Log out finissaient sous le bas réel de l'écran. Ancrer les deux
               bords tient toujours, peu importe ce que fait la barre du navigateur. */
            position: fixed; top: 65px; bottom: 0; left: -90px; width: 76px;
            background-color: var(--bg-color); border-right: 1px solid var(--border); z-index: 150;
            padding: 10px 0 22px; box-sizing: border-box; overflow-y: auto;
            display: flex; flex-direction: column;
            transition: left 0.3s cubic-bezier(0.1, 0.9, 0.2, 1), background-color 0.3s;
        }
        .sidebar.open { left: 0; }
        .sidebar-brand { display: none; }   /* les libellés de groupe disparaissent : deux filets suffisent */
        .nav-link { display: flex; align-items: center; gap: 12px; color: var(--text-muted); padding: 10px 12px; text-decoration: none; font-weight: 600; margin-bottom: 4px; font-size: var(--fs-body); border-radius: 8px; transition: 0.15s;}
        .nav-link:hover, .nav-link.active { background: rgba(255,255,255,0.05); color: var(--accent); }

        .sidebar .nav-link {
            flex-direction: column; align-items: center; gap: 5px;
            padding: 9px 4px 8px; margin: 0 6px 2px; border-radius: 10px;
            position: relative; border-left: 0; font-weight: 600;
        }
        .sidebar .nav-link span {
            font-size: var(--fs-xs); letter-spacing: 0.01em; line-height: 1;
            max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
        }
        .sidebar .nav-link:hover { background: rgba(138, 154, 91, 0.10); color: var(--text-main); }
        .sidebar .nav-link.active {
            background: rgba(138, 154, 91, 0.16); color: var(--text-main); font-weight: 700;
        }
        .sidebar .nav-link.active::before {
            content: ""; position: absolute; left: -6px; top: 8px; bottom: 8px;
            width: 3px; border-radius: 0 3px 3px 0; background: var(--accent);
        }
        .nav-sep { height: 1px; background: var(--border); margin: 8px 16px; flex: 0 0 auto; }
        .nav-spacer { flex: 1 1 auto; min-height: 8px; }

        /* Icônes du menu : trait fin hérité de la couleur du libellé, donc
           elles s'allument avec lui. Légèrement estompées au repos pour que
           le texte reste ce qu'on lit en premier. La largeur est figée afin
           que tous les libellés s'alignent, quel que soit le dessin. */
        .nav-ico {
            width: 18px; height: 18px; flex: 0 0 18px;
            fill: none; stroke: currentColor; stroke-width: 1.7;
            stroke-linecap: round; stroke-linejoin: round;
            opacity: 0.7; transition: opacity 0.15s;
        }
        .sidebar .nav-link .nav-ico { width: 22px; height: 22px; flex: 0 0 22px; }
        .sidebar .nav-link:hover .nav-ico,
        .sidebar .nav-link.active .nav-ico { opacity: 1; }
        .sidebar .nav-link.active .nav-ico { color: var(--accent); }
        .sidebar-overlay { display: none; position: fixed; top: 65px; left: 0; width: 100vw; height: calc(100vh - 65px); background: rgba(0, 0, 0, 0.6); z-index: 140; backdrop-filter: blur(4px); }
        .sidebar-overlay.open { display: block; }

        /* Rail repliable (desktop) : « ‹ Hide menu » en tête du rail pour le
           ranger, et un ☰ flottant en haut à gauche pour le rappeler. */
        .rail-collapse { display: none; }
        .rail-open { display: none; position: fixed; top: 76px; left: 12px; z-index: 200;
            width: 38px; height: 38px; border-radius: 10px; cursor: pointer;
            background: var(--card-bg); color: var(--text-main);
            border: 1px solid var(--border); box-shadow: 0 6px 18px rgba(0,0,0,0.35);
            font-size: var(--fs-h2); line-height: 1; padding: 0; transition: 0.15s; }

        /* --- Command Center : colonne admin sur la bande DROITE de l'écran ---
           Toujours en bleu-violet effacé (--admin-*), jamais la couleur d'accent
           du reste du site : ce ton signale à lui seul "réservé à l'admin",
           sur l'icône comme sur le panneau qu'elle ouvre. display:none par
           défaut, révélé par initApp() selon le rôle (jamais dans le rendu
           HTML initial pour un compte non-owner). */
        :root {
            --admin-color: #8577e6;
            --admin-bg: rgba(133, 119, 230, 0.10);
            --admin-bg-strong: rgba(133, 119, 230, 0.18);
            --admin-border: rgba(133, 119, 230, 0.38);
        }
        .admin-rail { display: none; position: fixed; top: 0; right: 0; height: 100vh;
            width: 72px; z-index: 210; flex-direction: column; align-items: stretch;
            background: var(--card-bg); border-left: 1px solid var(--admin-border);
            box-shadow: -6px 0 18px rgba(0,0,0,0.25); overflow-y: auto;
            transform: translateX(100%); transition: transform 0.2s; }
        body.has-admin-rail .admin-rail { display: flex; }
        body.has-admin-rail .admin-rail.open { transform: translateX(0); }
        /* Bouton pour refermer le rail SANS cacher le contenu (jamais un simple
           display:none sur #app-container) -- présent en haut du rail, comme le
           chevron « ‹ » du menu de gauche (.rail-collapse), miroir à droite. */
        .admin-rail-collapse { display: flex; align-items: center; justify-content: center;
            color: var(--admin-color); opacity: 0.75; cursor: pointer; height: 24px;
            margin: 6px 6px 0; border-radius: 8px; font-size: var(--fs-h3); line-height: 1;
            transition: color 0.15s, background 0.15s, opacity 0.15s; }
        .admin-rail-collapse:hover { opacity: 1; background: var(--admin-bg); }
        /* Petit bouton de rappel (mêmes proportions que .rail-open, à gauche) --
           seul élément visible quand le rail est masqué : il ne recouvre jamais
           de contenu, il occupe juste le coin où le rail apparaîtrait. */
        .admin-rail-open { display: none; position: fixed; top: 76px; right: 12px; z-index: 200;
            width: 38px; height: 38px; border-radius: 10px; cursor: pointer;
            background: var(--card-bg); color: var(--admin-color);
            border: 1px solid var(--admin-border); box-shadow: 0 6px 18px rgba(0,0,0,0.35);
            font-size: var(--fs-h2); line-height: 1; padding: 0; transition: 0.15s; }
        .admin-rail-open:hover { background: var(--admin-bg); }
        body.has-admin-rail .admin-rail-open { display: flex; align-items: center; justify-content: center; }
        body.has-admin-rail .admin-rail.open ~ .admin-rail-open { display: none; }
        /* Tiroir mobile/tablette (<1024px) : fermé par défaut (juste le bouton
           ⚙), ouvert par-dessus le contenu avec un fond assombri -- jamais en
           permanence dans la mise en page, comme le tiroir du menu de gauche. */
        .admin-rail-overlay { display: none; position: fixed; top: 0; left: 0; width: 100vw; height: 100vh;
            background: rgba(0, 0, 0, 0.6); z-index: 205; backdrop-filter: blur(4px); }
        .admin-rail-overlay.open { display: block; }
        .admin-rail-label { color: var(--admin-color); font-size: var(--fs-xs); font-weight: 700;
            letter-spacing: 0.08em; text-align: center; padding: 4px 4px 8px; }
        .admin-rail-link { display: flex; flex-direction: column; align-items: center; gap: 4px;
            background: none; border: none; cursor: pointer; color: var(--admin-color);
            padding: 12px 4px; font-size: var(--fs-xs); line-height: 1.15; text-align: center;
            border-left: 3px solid transparent; opacity: 0.75; transition: 0.15s;
            text-decoration: none; }
        .admin-rail-link:hover { opacity: 1; background: var(--admin-bg); }
        .admin-rail-link.active { opacity: 1; background: var(--admin-bg-strong); border-left-color: var(--admin-color); }
        .admin-rail-link .admin-ico { font-size: var(--fs-h3); line-height: 1; }
        .admin-rail-badge { display: inline-block; min-width: 15px; padding: 0 4px; border-radius: 8px;
            background: var(--danger); color: #fff; font-size: var(--fs-xs); font-weight: 700;
            line-height: 15px; margin-top: -2px; }

        .admin-panel { display: none; position: fixed; top: 0; right: 72px; height: 100vh;
            width: 420px; max-width: calc(100vw - 72px); z-index: 209; flex-direction: column;
            background: var(--card-bg); border-left: 1px solid var(--admin-border);
            box-shadow: -10px 0 24px rgba(0,0,0,0.3); }
        .admin-panel-head { display: flex; align-items: center; justify-content: space-between;
            padding: 14px 16px; border-bottom: 1px solid var(--admin-border); color: var(--admin-color); }
        .admin-panel-head strong { color: var(--admin-color); font-size: var(--fs-h3); }
        .admin-panel-close { cursor: pointer; color: var(--admin-color); font-weight: 700; padding: 2px 8px; }
        .admin-panel-body { flex: 1; overflow-y: auto; padding: 16px; font-size: var(--fs-sm); }
        .admin-panel-body h4 { color: var(--admin-color); font-size: var(--fs-body); margin: 0 0 8px; }
        .admin-panel-body table { width: 100%; border-collapse: collapse; }
        .admin-panel-body th, .admin-panel-body td { padding: 6px 6px; text-align: left; border-bottom: 1px solid var(--border); }
        .admin-stat-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid var(--border); }
        .admin-alert { border-left: 3px solid var(--admin-color); background: var(--admin-bg);
            border-radius: 6px; padding: 8px 10px; margin-bottom: 8px; }
        .admin-alert.lvl-error { border-left-color: var(--danger); }
        .admin-alert.lvl-warn { border-left-color: #d69e2e; }
        .admin-btn { background: none; border: 1px solid var(--admin-color); color: var(--admin-color);
            border-radius: 8px; padding: 6px 12px; cursor: pointer; font-size: var(--fs-sm); }
        .admin-btn:hover { background: var(--admin-bg); }
        @media (max-width: 760px) {
            .admin-rail { width: 58px; }
            .admin-rail-link span:last-child { display: none; }
            .admin-panel { right: 58px; width: calc(100vw - 58px); max-width: none; }
        }
        .rail-open:hover { border-color: var(--accent); color: var(--accent); background: var(--card-bg); }

        /* Desktop : rail toujours visible, plus de tiroir */
        @media (min-width: 1024px) {
            .hamburger-btn { display: none; }
            .sidebar { left: 0; }
            .sidebar-overlay { display: none !important; }
            #app-container { padding-left: 76px; }

            /* Ranger le rail : un chevron discret en tête, un ☰ flottant pour
               le rappeler. Le rail — même à 76 px — se replie et rend sa place. */
            .rail-collapse {
                display: flex; align-items: center; justify-content: center;
                color: var(--text-muted); font-size: var(--fs-h3); line-height: 1;
                cursor: pointer; height: 24px; margin: 0 6px 6px; border-radius: 8px;
                transition: color 0.15s, background 0.15s; flex: 0 0 auto;
            }
            .rail-collapse:hover { color: var(--accent); background: rgba(138, 154, 91, 0.10); }
            body.rail-collapsed .sidebar { left: -90px; }
            /* Gouttière de la largeur du bouton, sinon le ☰ passe par-dessus le
               titre. Symétrique à droite : une marge d'un seul côté déséquilibre
               toute la page. */
            body.rail-collapsed #app-container { padding-left: 58px; padding-right: 58px; }
            body.rail-collapsed .rail-open { display: block; }

            /* Command Center (bande droite) : espace réservé en permanence tant
               que le rail est visible -- jamais superposé au contenu, contrairement
               au tiroir mobile ci-dessus (overlay). Repli en un petit bouton ⚙,
               miroir du chevron « ‹ » / ☰ du menu de gauche. */
            body.has-admin-rail .admin-rail { transform: translateX(0); }
            body.has-admin-rail .admin-rail-overlay { display: none !important; }
            body.has-admin-rail #app-container { padding-right: 72px; }
            body.has-admin-rail.admin-rail-collapsed .admin-rail { transform: translateX(100%); }
            body.has-admin-rail.admin-rail-collapsed .admin-rail-open { display: flex; align-items: center; justify-content: center; }
            body.has-admin-rail:not(.admin-rail-collapsed) .admin-rail-open { display: none; }
            body.has-admin-rail.admin-rail-collapsed #app-container { padding-right: 58px; }
        }

        /* Une seule largeur de contenu pour toutes les vues : passer du Dashboard
           à une fiche action ne doit pas faire sauter la mise en page. Seul
           Settings reste étroit (un formulaire long est illisible). */
        .view-container { padding: 90px 28px 24px; max-width: 1600px; margin: 0 auto; width: 100%; box-sizing: border-box; display: none; }
        #view-dashboard { flex-direction: column; align-items: center; }
        .dashboard-header { text-align: center; margin-bottom: 40px; }
        .dashboard-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 24px; width: 100%; max-width: 1200px;}
        
        .module-card { padding: 35px 25px; display: flex; flex-direction: column; align-items: center; text-align: center; transition: 0.3s; }
        .module-card:hover, .widget:hover, .sd-card[onclick]:hover {
            box-shadow: var(--hover-shadow) !important;
            transform: translateY(-2px);
            border-color: var(--accent);
        }
        .module-icon { font-size: var(--fs-display); font-weight: 800; margin-bottom: 20px; background: rgba(255,255,255,0.03); border: 1px solid var(--border); width: 60px; height: 60px; display: flex; align-items: center; justify-content: center; border-radius: 14px; color: var(--accent); }
        .module-title { font-size: var(--fs-h2); font-weight: 600; margin-bottom: 12px; color: var(--text-main); }
        .module-desc { font-size: var(--fs-h3); color: var(--text-muted); }
        
        /* max-width:100% + overflow-x:auto (+ min-width:0, le même flexbug
           que .sd-card : .segmented-control est enfant d'un conteneur flex,
           voir ex. la barre d'options du graphique) : sans ces trois, une
           rangée de boutons qui ne wrap jamais (ex. les périodes du
           graphique -- 1D/5D/1M/.../MAX) reste AU MOINS aussi large que
           tous ses boutons mis côte à côte, quel que soit l'espace dispo --
           avec overflow:hidden seul (sans ce fix), rien ne la force à
           rétrécir, elle déborde donc de son encart en mode Split (panneau
           étroit) au lieu d'y être contenue. overflow-y:hidden conservé
           (au lieu de overflow:hidden) pour garder les coins arrondis nets
           sur les boutons internes tout en permettant overflow-x:auto --
           visible/non-visible ne peuvent pas se mélanger entre les deux axes
           (règle CSS), hidden/auto le peuvent. */
        .segmented-control { display: inline-flex; background: rgba(0,0,0,0.3); border-radius: 10px; padding: 0; margin-bottom: 15px; border: 1px solid var(--border);
            overflow-x: auto; overflow-y: hidden; max-width: 100%; min-width: 0; }
        /* Taille de référence = le bouton EUR/USD du portefeuille. Toutes les
           bascules « choix multiple » grises s'y alignent. */
        .seg-btn { padding: 5px 14px; border: none; background: transparent; color: var(--text-muted); font-size: var(--fs-sm); font-weight: 600; transition: 0.2s;}
        .seg-btn.active { background: var(--card-bg); color: var(--text-main); box-shadow: 0 1px 5px rgba(0,0,0,0.2); }
        
        .tabs-container { display: flex; justify-content: center; margin-bottom: 20px; gap: 8px; }
        .tab-btn { background: transparent; border: 1px solid var(--border); color: var(--text-muted); padding: 8px 16px; font-size: var(--fs-body); font-weight: 600; transition: 0.2s;}
        .tab-btn.active { background-color: rgba(138, 154, 91, 0.1); color: var(--accent); border-color: rgba(138, 154, 91, 0.3); }
        
        .filter-panel { padding: 18px; margin-bottom: 20px; display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 16px; transition: 0.3s; }
        .filter-group { display: flex; flex-direction: column; gap: 6px; position: relative; }
        label { font-size: var(--fs-sm); font-weight: 600; color: var(--text-muted); }

        /* --- IN-PLACE EXPANSION CARDS (Effet Apple / Pinterest) --- */
        .expandable-card {
            background-color: var(--card-bg);
            border: 1px solid var(--border);
            border-radius: 12px;
            padding: 20px;
            cursor: pointer;
            transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
            overflow: hidden; /* Empêche le texte de déborder pendant l'animation */
            box-sizing: border-box;
        }

        /* L'état quand la carte est cliquée */
        .expandable-card.expanded {
            grid-column: 1 / -1; /* Demande à la carte de prendre 100% de la largeur de la grille */
            /* Pas de scale() ici : à pleine largeur, le 1% de zoom faisait
               déborder le contour de la carte sur celui de la leçon / des
               cartes voisines. L'ombre + la bordure accent suffisent. */
            box-shadow: 0 15px 40px -5px rgba(0,0,0,0.15) !important;
            border-color: var(--accent) !important;
            z-index: 10;
        }

        /* Gestion de l'affichage du contenu */
        .expandable-card .hidden-detail { display: none; }
        
        .expandable-card.expanded .hidden-detail { 
            display: block; 
            animation: fadeInDetail 0.5s ease forwards;
        }
        
        /* Quand c'est ouvert, on cache le petit résumé */
        .expandable-card.expanded .card-summary { display: none; }
        
        @keyframes fadeInDetail {
            from { opacity: 0; transform: translateY(10px); }
            to { opacity: 1; transform: translateY(0); }
        }

        /* ============ LEÇONS (format éditorial) ============ */
        /* #lesson-body porte la classe .lesson-content, qui reçoit bordure +
           ombre + fond par la règle globale des encadrés. Dans la nouvelle
           mise en page (Notes), il est DÉJÀ dans une carte (.ac-lesson-card) :
           on lui retire donc son propre contour — c'est lui qui faisait « le
           tour » collé au texte. */
        #lesson-body.lesson-content {
            border: none; box-shadow: none; background: transparent; border-radius: 0;
        }
        /* Deux polices seulement, comme la fiche action (.sd-page) :
             · lecture -> var(--font-serif) + var(--fs-read)   (p, li, leads, encadrés) — l'éditorial
             · reste    -> var(--font-ui) + var(--fs-*)         (titres, labels, tableaux, nombres)
           Les nombres s'alignent via font-variant-numeric: tabular-nums, PAS via
           du monospace. Aucune autre valeur de font-size dans ce bloc. */
        #lesson-body .lesson {
            max-width: 900px; margin: 8px auto 0; color: var(--text-main);
            font-family: var(--font-serif);
            animation: lessonFade .4s ease both;
        }
        /* Leçons "masterclass" (cartes dépliantes) : couche lecture en sans */
        #lesson-body .lesson:has(.grid-container),
        #lesson-body .lesson:has(.expandable-card) { font-family: var(--font-ui); }
        /* Fiches "13 traits" (Lynch) : ouverture ~1.5x plus large */
        dialog[id^="trait-modal-"] {
            max-width: 780px !important; width: 92% !important; padding: 34px !important;
        }
        dialog[id^="trait-modal-"] h3 { font-size: var(--fs-h2) !important; margin: 0 0 16px !important; }
        dialog[id^="trait-modal-"] p { font-size: var(--fs-read) !important; line-height: 1.65 !important; }
        dialog[id^="trait-modal-"] button {
            font-size: var(--fs-body) !important; padding: 10px 20px !important; margin-top: 20px !important;
        }
        @keyframes lessonFade { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

        /* --- couche structure (sans) --- */
        #lesson-body .lesson .l-title {
            font-family: var(--font-ui);
            font-size: var(--fs-title); font-weight: 750; line-height: 1.2; color: var(--text-main);
            margin: 0 0 1.9rem; padding-bottom: 1.15rem; border-bottom: 2px solid var(--border);
        }
        #lesson-body .lesson .l-sec { margin-top: 2.3rem; }
        #lesson-body .lesson .l-sec:first-of-type { margin-top: 0; }
        #lesson-body .lesson h2 {
            font-family: var(--font-ui);
            font-size: var(--fs-h2); font-weight: 700; line-height: 1.3; color: var(--text-main);
            margin: 0 0 .9rem; display: flex; gap: .6rem; align-items: baseline;
        }
        #lesson-body .lesson h2 .l-num {
            font-size: var(--fs-eyebrow); font-weight: 800; color: var(--accent); letter-spacing: .03em;
            flex-shrink: 0; font-variant-numeric: tabular-nums;
        }
        #lesson-body .lesson h3 {
            font-family: var(--font-ui);
            font-size: var(--fs-h3); font-weight: 700; color: var(--text-main); margin: 1.4rem 0 .4rem;
        }
        #lesson-body .lesson .l-eg-label,
        #lesson-body .lesson .l-warn-label,
        #lesson-body .lesson .l-note-label,
        #lesson-body .lesson .l-recap-label {
            font-family: var(--font-ui);
            font-size: var(--fs-eyebrow); font-weight: 800; letter-spacing: .12em; text-transform: uppercase;
            color: var(--text-main); margin-bottom: .6rem;
        }
        #lesson-body .lesson .l-recap-label { color: var(--accent); }
        /* Encadré « attention » (Limitation / Common mistake) : triangle ambre,
           même facture que les icônes des notes explicatives. */
        #lesson-body .lesson .l-warn-label::before {
            content: ""; display: inline-block; width: 13px; height: 13px;
            margin-right: 6px; vertical-align: -2px;
            background: no-repeat center/contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23f59e0b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z'/%3E%3Cline x1='12' y1='9' x2='12' y2='13'/%3E%3Cline x1='12' y1='17' x2='12.01' y2='17'/%3E%3C/svg%3E");
        }

        /* --- couche lecture (serif, une seule taille) ---
           Corps au contraste PLEIN (--text-main : noir sur clair, blanc sur
           sombre) — le gris muté était trop pâle pour lire un texte long. */
        #lesson-body .lesson p,
        #lesson-body .lesson li,
        #lesson-body .lesson .l-eg p,
        #lesson-body .lesson .l-warn p,
        #lesson-body .lesson .l-note p {
            font-size: var(--fs-read); line-height: 1.62; margin: 0 0 .85em; color: var(--text-main);
        }
        #lesson-body .lesson li { line-height: 1.55; margin-bottom: .4em; }
        #lesson-body .lesson .l-eg p,
        #lesson-body .lesson .l-warn p,
        #lesson-body .lesson .l-note p { line-height: 1.55; margin: 0 0 .55rem; color: var(--text-main); }
        #lesson-body .lesson .l-eg p:last-child,
        #lesson-body .lesson .l-warn p:last-child,
        #lesson-body .lesson .l-note p:last-child { margin-bottom: 0; }
        #lesson-body .lesson strong { color: var(--text-main); font-weight: 600; }
        #lesson-body .lesson em.l-term { font-style: normal; border-bottom: 1px dotted var(--text-muted); }
        /* Terme porteur d'une fiche : cliquable, avec le meme « i » en
           exposant que partout ailleurs sur le site. Un terme souligne mais
           muet se lit comme une definition qu'on ne peut pas ouvrir. */
        #lesson-body .lesson .l-term[data-doc] { font-style: normal; cursor: pointer;
            border-bottom: 1px dotted var(--accent); color: inherit; }
        #lesson-body .lesson .l-term[data-doc]:hover { border-bottom-style: solid; }
        #lesson-body .lesson .l-term[data-doc]::after { content: "\00a0i"; font-size: .7em;
            vertical-align: super; color: var(--accent); font-weight: 700; }
        #lesson-body .lesson a { color: var(--accent); }
        #lesson-body .lesson .l-lead {
            font-size: var(--fs-read); line-height: 1.55; color: var(--text-main); margin: 0 0 2.4rem;
            padding-bottom: 1.7rem; border-bottom: 1px solid var(--border);
        }
        #lesson-body .lesson ul, #lesson-body .lesson ol { margin: 0 0 1em; padding-left: 1.25em; }
        /* Ligne "Last updated" des pages légales (legal/*.html) : métadonnée,
           pas du corps de texte — sans, elle hérite du serif pleine taille
           comme un paragraphe normal. */
        #lesson-body .lesson .legal-updated {
            font-family: var(--font-ui); font-size: var(--fs-sm); color: var(--text-muted);
            margin: -0.6rem 0 1.6rem;
        }

        /* Encadrés : exemple chiffré / attention / à retenir */
        #lesson-body .lesson .l-eg,
        #lesson-body .lesson .l-warn,
        #lesson-body .lesson .l-note {
            margin: 1.35rem 0; padding: 1.05rem 1.2rem; border-radius: 6px; border-left: 4px solid;
        }
        #lesson-body .lesson .l-eg { border-left-color: var(--stalwart); background: rgba(59, 130, 246, .10); }
        #lesson-body .lesson .l-warn { border-left-color: var(--cyclical); background: rgba(245, 158, 11, .12); }
        #lesson-body .lesson .l-note { border-left-color: var(--accent); background: rgba(138, 154, 91, .12); }

        /* --- nombres : sans-serif + tabular-nums (comme .sd-page), pas de mono --- */
        #lesson-body .lesson .l-eg .n {
            font-variant-numeric: tabular-nums; font-weight: 600; color: var(--text-main);
        }
        #lesson-body .lesson .l-eg-tbl {
            width: 100%; max-width: 560px; border-collapse: collapse; margin: 1rem 0 1.1rem;
            font-family: var(--font-ui); font-size: var(--fs-body);
            border: 1px solid rgba(128,128,128,.3); border-radius: 4px; overflow: hidden;
        }
        #lesson-body .lesson .l-eg-tbl td {
            padding: .7rem .85rem; border-bottom: 1px solid rgba(128,128,128,.22);
            text-align: right; color: var(--text-main); background: var(--card-bg);
            font-variant-numeric: tabular-nums;
        }
        #lesson-body .lesson .l-eg-tbl tr:last-child td { border-bottom: none; }
        #lesson-body .lesson .l-eg-tbl td:first-child {
            text-align: left; color: var(--text-main); font-weight: 500;
            border-right: 1px solid rgba(128,128,128,.22);
            font-family: var(--font-ui);
        }
        /* Tableaux de rendements : plus de deux colonnes, et un vrai en-tête.
           `position: static` explicite parce que le `th { position: sticky }`
           global du screener collerait sinon ces en-têtes en haut de la page
           pendant qu'on lit la leçon. */
        #lesson-body .lesson .l-eg-scroll { overflow-x: auto; margin: 1rem 0 .4rem; }
        #lesson-body .lesson .l-eg-tbl.wide { max-width: 100%; min-width: 440px; margin: 0; }
        #lesson-body .lesson .l-eg-tbl thead th {
            position: static; z-index: auto; cursor: default;
            padding: .6rem .85rem; text-align: right; font-weight: 700;
            background: var(--hover-bg); color: var(--text-muted);
            font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .05em;
            border-bottom: 1px solid rgba(128,128,128,.3);
        }
        #lesson-body .lesson .l-eg-tbl thead th:first-child { text-align: left; }
        #lesson-body .lesson .l-eg-cap {
            font-family: var(--font-ui); font-size: var(--fs-sm); color: var(--text-muted); margin-top: .5rem;
        }

        /* « In short » : encadré d'OUVERTURE, plus une section de clôture. On
           lit l'essentiel avant d'entrer dans la leçon, pas après l'avoir
           finie -- d'où l'encadré plein plutôt que l'ancien filet horizontal
           de fin de page (margin-top: 3rem / border-top). */
        #lesson-body .lesson .l-recap {
            margin: 0 0 2.4rem; padding: 1.1rem 1.3rem 1.2rem; border-radius: 8px;
            border: 1px solid rgba(138, 154, 91, .35); background: rgba(138, 154, 91, .10);
            /* Encadré volontairement plus étroit que le corps de texte (-40%) :
               c'est un résumé, pas le cours -- la différence de largeur le
               signale avant même qu'on l'ait lu. Les phrases reviennent à la
               ligne normalement. Plancher en px pour qu'il reste lisible sur
               mobile, où 60% d'une colonne déjà étroite ne tiendrait pas. */
            max-width: min(60%, 100%); min-width: min(320px, 100%);
        }
        #lesson-body .lesson .l-recap ul { margin: 0; padding: 0; list-style: none; }
        #lesson-body .lesson .l-recap li {
            font-family: var(--font-ui);
            font-size: var(--fs-body); line-height: 1.5; color: var(--text-main);
            padding: .55rem 0 .55rem 1.4rem; position: relative;
            border-bottom: 1px solid rgba(138, 154, 91, .22);
        }
        #lesson-body .lesson .l-recap li:last-child { border-bottom: none; padding-bottom: 0; }
        #lesson-body .lesson .l-recap li:first-child { padding-top: 0; }
        /* Puce ronde plutôt qu'un tiret cadratin : le tiret ouvrait chaque
           ligne sur un ton sec, presque télégraphique. */
        #lesson-body .lesson .l-recap li::before {
            content: "\2022"; position: absolute; left: .25rem;
            color: var(--accent); font-size: 1.15em;
        }
        @media (max-width: 720px) {
            #lesson-body .lesson { max-width: 100%; }
            /* Sur mobile la colonne est déjà étroite : rétrécir le résumé de
               40% de plus le rendrait illisible. Il reprend toute la largeur. */
            #lesson-body .lesson .l-recap { max-width: 100%; min-width: 0; }
        }

        /* TABLE CSS */
        /* La hauteur est ajustée en JS (_fitTableHeight) : la valeur ci-dessous
           n'est qu'un repli avant le premier calcul. Elle était figée à
           100vh - 250px, réservé pour le bandeau Annual/Rolling et le panneau
           de filtres qui ont disparu — d'où une bande vide sous le tableau. */
        .table-container { overflow-x: auto; max-height: calc(100vh - 210px); overflow-y: auto; transition: 0.3s; }
        
        /* table-layout: fixed = colonnes de largeur égale ; min-width réglé en JS
           selon le nombre de colonnes visibles (peu de colonnes -> remplit l'écran, sans scroll) */
        table { width: 100%; text-align: left; font-size: var(--fs-sm); font-variant-numeric: tabular-nums; border-collapse: separate; border-spacing: 0; table-layout: fixed; min-width: 100%; }
        
        /* 2. Gestion stricte du texte : retours à la ligne autorisés, mots trop longs coupés */
        th, td { 
            padding: 10px 8px; /* Espacement légèrement réduit pour tout faire rentrer proprement */
            border-bottom: 1px solid var(--border); 
            color: var(--text-main);
            
            white-space: normal; /* Les suites de mots vont à la ligne naturellement */
            overflow-wrap: break-word; /* Si un seul mot est trop long, il est coupé */
            word-break: break-word; 
            overflow: hidden; 
            text-overflow: ellipsis; /* Ajoute des "..." si ça déborde d'un bloc non cassable */
        }
        
        th { position: sticky; top: 0; background-color: var(--card-bg); z-index: 40; color: var(--text-muted); cursor: grab; user-select: none; }
        tr.stock-row:hover { background-color: rgba(255,255,255,0.03); cursor: pointer; }
        
        /* Bord droit de la colonne figée : une ombre portée plutôt qu'un trait —
           on sent la colonne « au-dessus » du reste sans ligne dure. (box-shadow
           n'est pas rognée par l'overflow:hidden des cellules, contrairement à
           un ::after.) */
        /* 150px (pas 120px) : assez pour qu'un ticker à 4-5 lettres + la
           plupart des noms de société tiennent sans renvoi à la ligne — un
           nom trop long est tronqué en "…" (voir renderTable) plutôt que
           d'élargir encore la colonne. Compensé côté JS par
           TABLES.stocks.extraWidth() pour ne pas resserrer les autres
           colonnes. */
        .col-ticker { width: 150px; position: sticky; left: 0; background-color: var(--card-bg); z-index: 30; box-shadow: 10px 0 12px -8px rgba(0,0,0,0.28); }
        th.col-ticker { position: sticky; left: 0; top: 0; background-color: var(--card-bg); z-index: 50; box-shadow: 10px 0 12px -8px rgba(0,0,0,0.28); }
        body.light-mode .col-ticker, body.light-mode th.col-ticker { box-shadow: 8px 0 10px -8px rgba(0,0,0,0.10); }
        /* Inventory : le détail entre parenthèses ("+12% vs Rev +2%") passait
           à la ligne dans la largeur partagée par défaut (~132px) et ajoutait
           une 3e ligne à la cellule — élargie comme la colonne Ticker
           ci-dessus, même compensation dans extraWidth(). */
        .col-stocks { width: 158px; }

        /* Catégorie Lynch : une pastille de couleur + un mot, pas un gros badge
           sur chaque ligne. */
        .cat-tag { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-sm); font-weight: 600; white-space: nowrap; }
        .cat-dot { width: 7px; height: 7px; border-radius: 2px; flex: 0 0 auto; }

        /* Score Investor Lens : le ratio seul, coloré. Pas de jauge — elle
           portait la même information que la couleur et, partageant la classe
           `.lens-score` avec le bloc de la fiche action (plus bas, avec son
           padding), elle rehaussait chaque ligne du screener. */
        td.col-lens { text-align: center; }
        th.col-metric, td.col-metric { text-align: center; white-space: nowrap; font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }
        th.col-metric { font-weight: 600; color: var(--text-muted); }
        .lens-n { font-size: var(--fs-sm); font-weight: 700; font-variant-numeric: tabular-nums; }

        /* Composition d'un ETF (fiche fonds) : 4 tuiles côte à côte. Top
           holdings est la seule aux libellés longs (noms de sociétés) -> deux
           colonnes dès qu'il y a la place, le reste des tuiles n'affichant que
           des noms de secteurs ou de pays. */
        .etf-comp-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px; }

        /* Tableau ETFs : la colonne d'identité se fige comme celle des actions,
           même ombrage portée (pas un simple filet) pour dire « ça glisse
           sous moi », les autres prennent une largeur adaptée à ce qu'elles
           portent. */
        .col-etf-fund { width: 190px; text-align: left; position: sticky; left: 0; background-color: var(--card-bg); z-index: 30; box-shadow: 10px 0 12px -8px rgba(0,0,0,0.28); }
        th.col-etf-fund { position: sticky; left: 0; top: 0; background-color: var(--card-bg); z-index: 50; box-shadow: 10px 0 12px -8px rgba(0,0,0,0.28); }
        body.light-mode .col-etf-fund, body.light-mode th.col-etf-fund { box-shadow: 8px 0 10px -8px rgba(0,0,0,0.10); }
        /* Toutes les colonnes centrées — titres et valeurs — sauf la première :
           l'identité (ticker/nom, fonds) reste serrée à gauche, figée. Même
           traitement que les tableaux du dashboard (#pf-table, #pos-lots). */
        #stocksTable th, #stocksTable td, #etfTable th, #etfTable td, #cryptoTable th, #cryptoTable td { text-align: center; }
        /* Pays de résidence : libellés courts, on évite qu'un « United States »
           n'élargisse la colonne — coupe proprement. */
        #stocksTable td.col-country, #stocksTable th.col-country { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 120px; }
        #stocksTable td.col-pea, #stocksTable th.col-pea, #etfTable td.col-etf-pea, #etfTable th.col-etf-pea { white-space: nowrap; }
        #stocksTable th.col-ticker, #stocksTable td.col-ticker,
        #etfTable th.col-etf-fund, #etfTable td.col-etf-fund,
        #cryptoTable th.col-crypto-coin, #cryptoTable td.col-crypto-coin { text-align: left; }
        /* Tableau Crypto : même traitement que la colonne Fund des ETFs —
           colonne d'identité figée avec ombrage porté, largeur adaptée au
           plus long nom (« Binance Coin » etc.). */
        .col-crypto-coin { width: 130px; text-align: left; position: sticky; left: 0; background-color: var(--card-bg); z-index: 30; box-shadow: 10px 0 12px -8px rgba(0,0,0,0.28); }
        th.col-crypto-coin { position: sticky; left: 0; top: 0; background-color: var(--card-bg); z-index: 50; box-shadow: 10px 0 12px -8px rgba(0,0,0,0.28); }
        body.light-mode .col-crypto-coin, body.light-mode th.col-crypto-coin { box-shadow: 8px 0 10px -8px rgba(0,0,0,0.10); }
        /* Aucune largeur sur les autres colonnes, comme au tableau des actions :
           `table-layout: fixed` les répartit à égalité et le plancher posé par
           updateTableWidth() leur garantit de quoi tenir sur une ligne. Des
           largeurs sur mesure plus étroites que ce plancher faisaient replier
           les libellés et triplaient la hauteur des lignes. */
        
        /* Vertical Fine Line Finary Style */
        th.border-separator, td.border-separator { border-right: 1px solid var(--border) !important; }
        
        /* Le conteneur du menu déroulant (Nouvelles règles pour le faire flotter avec un fond) */
        .columns-dropdown-menu {
            display: none;
            position: absolute;
            top: 75px; /* Le place sous le bouton */
            right: 0;
            background-color: var(--card-bg) !important;
            border: 1px solid var(--border);
            border-radius: 12px;
            padding: 15px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
            z-index: 999; /* Force le passage au premier plan, au-dessus de la table */
            flex-direction: column;
            min-width: 200px;
        }

        .columns-dropdown-menu input[type="checkbox"] { width: auto !important; height: auto !important; margin: 0 8px 0 0 !important; display: inline-block; appearance: auto !important; }
        .columns-dropdown-menu label { font-size: var(--fs-body); display: flex; align-items: center; gap: 8px; margin-bottom: 4px; color: var(--text-main); }

        /* Menu "+ Add data" (Portfolio) : point d'entrée unique pour saisie
           manuelle, import, cash, brokers API et gestion des imports. */
        .pf-add-wrap { position: relative; }
        .pf-add-menu {
            display: none; position: absolute; top: calc(100% + 6px); right: 0;
            background: var(--card-bg); border: 1px solid var(--border); border-radius: 12px;
            padding: 6px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4); z-index: 999; min-width: 260px;
        }
        .pf-add-menu.open { display: block; }
        .pf-add-menu button {
            display: block; width: 100%; text-align: left; background: none; border: none;
            font: inherit; color: var(--text-main); font-size: var(--fs-body); font-weight: 700;
            padding: 9px 10px; border-radius: 8px; cursor: pointer;
        }
        .pf-add-menu button:hover { background: var(--hover-bg); }
        .pf-add-menu .pf-add-menu-desc { display: block; font-weight: 400; color: var(--text-muted); font-size: var(--fs-xs); margin-top: 2px; }
        .pf-add-menu hr { border: none; border-top: 1px solid var(--border); margin: 5px 4px; }
        .pf-add-menu .pf-add-menu-group { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); padding: 6px 10px 2px; font-weight: 700; }
        .pf-add-menu .pf-add-menu-tag {
            display: inline-block; margin-left: 8px; padding: 1px 6px; border-radius: 6px;
            font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.02em;
            background: color-mix(in srgb, var(--accent) 15%, transparent); color: var(--accent);
            border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent); vertical-align: 1px;
        }

        .fav-btn { cursor: pointer; background: transparent; border: none; font-size: var(--fs-h2); color: #4b5563; padding: 0; line-height: 1; transition: 0.2s; outline: none; }
        .fav-btn:hover { transform: scale(1.2); }
        .fav-btn.active { color: var(--accent); text-shadow: 0 0 8px rgba(229, 181, 129, 0.3); }

        /* BADGES (Fond transparent teinté Finary Style) */
        .badge { display: inline-block; padding: 4px 8px; border-radius: 8px; font-size: var(--fs-xs); font-weight: normal; text-transform: uppercase; }
        /* #tag inséré dans une note/thèse : même bleu que les autres badges
           d'identité du site (Stalwart, ETF) plutôt qu'un jaune arbitraire qui
           jurait avec la palette et n'avait aucun sens (pas "d'avertissement"). */
        .badge.tag-chip { background: rgba(59, 130, 246, 0.12); color: var(--stalwart); border: 1px solid rgba(59, 130, 246, 0.3); padding: 2px 7px; border-radius: 6px; margin: 0 3px; text-transform: none; font-weight: 600; }
        .bg-fast { background: rgba(16, 185, 129, 0.1); color: var(--fast-grower); border: 1px solid rgba(16, 185, 129, 0.2); }
        .bg-stalwart { background: rgba(59, 130, 246, 0.1); color: var(--stalwart); border: 1px solid rgba(59, 130, 246, 0.2); }
        .bg-slow { background: rgba(156, 163, 175, 0.1); color: var(--slow-grower); border: 1px solid rgba(156, 163, 175, 0.2); }
        .bg-cyclical { background: rgba(245, 158, 11, 0.1); color: var(--cyclical); border: 1px solid rgba(245, 158, 11, 0.2); }
        .bg-turnaround { background: rgba(239, 68, 68, 0.1); color: var(--turnaround); border: 1px solid rgba(239, 68, 68, 0.2); }
        .bg-asset { background: rgba(139, 92, 246, 0.1); color: var(--asset-play); border: 1px solid rgba(139, 92, 246, 0.2); }
        .bg-unknown { background: rgba(138, 138, 147, 0.1); color: var(--unknown-cat); border: 1px dashed rgba(138, 138, 147, 0.35); }
        
        .warn-text { color: var(--danger); font-weight: bold; }
        .good-text { color: var(--success); font-weight: bold; }
        .slow-grower { color: var(--text-muted); }

        /* MACRO WIDGETS AND STOCK DETAILS (Structure rétablie) */
        .tab-content { display: none; } .tab-content.active { display: block; }
        .widget-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 20px; }
        .widget { padding: 24px; display: flex; flex-direction: column; cursor: pointer; }
        .widget-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; }
        .widget-title { font-size: var(--fs-h3); color: var(--text-muted); font-weight: 600; text-transform: uppercase; }
        .widget-value { font-size: var(--fs-display); font-weight: bold; margin-bottom: 10px; color: var(--text-main); }
        .widget-footer { font-size: var(--fs-sm); color: var(--text-muted); display: flex; justify-content: space-between; }
        /* min-width:0 : .sd-grid (ex. le wrapper autour de la carte
           Governance, #section-management) est lui-même un enfant direct de
           .sd-pane -- même flexbug que .sd-card (voir plus bas) mais un
           niveau plus haut. Sans ce min-width:0, .sd-grid restait au moins
           aussi large que le contenu de sa carte (ex. le tableau de
           gouvernance), ce qui forçait tout le PANNEAU à s'élargir au lieu
           de laisser l'encart gérer son propre scroll horizontal (overflow-
           x:auto sur .sd-card, qui lui n'a jamais eu l'occasion de s'activer
           puisque la carte n'était jamais vraiment "trop étroite" -- c'est
           .sd-grid qui s'élargissait en amont). */
        .sd-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; min-width: 0; }
        /* min-width:0 + overflow-x:auto : chaque encart scroll HORIZONTALEMENT
           DANS SES PROPRES BORNES si son contenu est trop large pour la
           colonne qui le contient (mode Split, panneau étroit) -- uniforme
           pour TOUS les encarts, qu'ils contiennent un tableau, une grille
           ou un simple bloc de texte. Avant ce `min-width:0`, un encart,
           enfant d'un flex column (.sd-pane), gardait par défaut la largeur
           MINIMALE de son contenu (min-width:auto, un flexbug classique) :
           certains s'élargissaient donc davantage que la colonne (scroll
           visible, par chance, au niveau du panneau) et d'autres -- ceux
           dont le contenu ne force pas cette largeur minimale -- laissaient
           simplement leur contenu déborder sans aucun moyen de le voir en
           entier. Sans effet hors Split : un encart pleine largeur n'a
           presque jamais de contenu plus large que lui-même. */
        /* flex-shrink:0 : en mode Split, .sd-pane est un flex column à
           hauteur bornée (max-height:calc(100vh-210px), voir plus bas) --
           sans ce flex-shrink:0, le flex-shrink:1 par défaut COMPRIME
           chaque encart (proportionnellement à sa hauteur naturelle) pour
           faire rentrer toute la colonne dans cette hauteur, au lieu de
           laisser le panneau scroller (ce qui est tout l'objet de son
           overflow-y:auto). Un encart haut (graphique, grille de stats)
           pouvait ainsi se retrouver compressé à quelques mm -- visible
           avant ce fix car le contenu débordait du cadre (moche mais
           lisible), invisible depuis l'ajout de overflow-x:auto ci-dessus
           (qui force overflow-y à 'auto' aussi, par la règle CSS qui
           aligne les deux axes dès que l'un n'est pas 'visible' -- donc
           maintenant CLIPPÉ dans la mini-boîte au lieu de déborder). */
        .sd-card { padding: 15px; min-width: 0; overflow-x: auto; flex-shrink: 0; }
        /* Encart replié (sdToggleCollapse, app.js) : seul l'en-tête reste. */
        .sd-card.sd-collapsed > :not(.sd-collapse-head) { display: none !important; }
        .sd-card.sd-collapsed > .sd-collapse-head { border-bottom: none !important; margin-bottom: 0 !important; padding-bottom: 0 !important; }
        .sd-collapse-btn { border: none; background: transparent; color: var(--text-muted); cursor: pointer;
            font-size: 0.85em; padding: 0 6px 0 0; line-height: 1; vertical-align: middle; }
        .sd-collapse-btn:hover { color: var(--accent); }
        .doubt-pop { position: absolute; z-index: 3000; background: var(--card-bg); color: var(--text-main);
            border: 1px solid var(--v-warn, #c08a00); border-radius: 8px; padding: 10px 12px;
            box-shadow: 0 6px 24px rgba(0,0,0,.35); font-size: var(--fs-sm); line-height: 1.45; }
        .doubt-pop p { margin: 2px 0 8px; color: var(--text-muted); }
        .doubt-pop code { font-size: var(--fs-xs); }
        .doubt-pop-foot { font-size: var(--fs-xs); margin: 0 !important; opacity: .8; }
        /* Note de section repliée en lien pointillé (pop-up), voir drawCompanyStats. */
        .cs-note-link { display: inline-block; margin: -4px 0 6px; font-size: var(--fs-xs); color: var(--text-muted);
            border-bottom: 1px dotted var(--text-muted); cursor: pointer; }
        .cs-note-link:hover { color: var(--accent); border-color: var(--accent); }
        /* Pastille de doute (admin seulement, _doubtBadge dans app.js). */
        .doubt-badge { display: inline-block; width: 14px; height: 14px; line-height: 14px; border-radius: 50%;
            font-size: var(--fs-xs); font-weight: 800; text-align: center; vertical-align: middle; cursor: help;
            background: var(--v-warn, #c08a00); color: #fff; margin-left: 4px; }
        .doubt-badge.lvl2 { background: var(--v-warn, #c08a00); }
        .doubt-badge.lvl3 { background: var(--v-fail, #c0392b); }
        .doubt-pop.lvl3 { border-color: var(--v-fail, #c0392b); }
        .doubt-pop ul { margin: 2px 0 8px 16px; padding: 0; color: var(--text-muted); }
        .sd-val { font-size: var(--fs-display); font-weight: bold; color: var(--text-main); }

        /* --- Fiches (action ET fonds) : echelle typographique unifiee ---
           Regles portees par la classe `.sd-page`, pas par l'id d'une vue :
           la fiche d'un fonds doit se lire exactement comme celle d'une
           action, et un id ne se partage pas. */
        .sd-page h2 { font-size: var(--fs-h2); font-weight: 700; color: var(--text-main); margin: 0; line-height: 1.3; }
        .sd-page h3, .sd-page .sd-subhead {
            font-size: var(--fs-sm); font-weight: 700; letter-spacing: 0.6px; text-transform: uppercase;
            color: var(--accent); margin: 0 0 10px 0;
        }
        .sd-page .sd-label {
            font-size: var(--fs-sm); font-weight: 600; color: var(--text-muted);
            display: block; margin-bottom: 5px; text-transform: none; letter-spacing: 0;
        }
        .sd-page .sd-val {
            font-size: var(--fs-h2); font-weight: 700; color: var(--text-main);
            font-variant-numeric: tabular-nums;
        }
        .sd-page .sd-stat-row {
            display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
            padding: 5px 0; border-bottom: 1px solid var(--border); font-size: var(--fs-body);
        }
        .sd-page .sd-stat-row .k { color: var(--text-muted); }
        .sd-page .sd-stat-row .v {
            color: var(--text-main); font-weight: 600; text-align: right;
            font-variant-numeric: tabular-nums; white-space: nowrap;
        }
        .sd-page .sd-note { font-size: var(--fs-xs); color: var(--text-muted); line-height: 1.4; }
        /* Onglet Position (fiche action ET fiche ETF, même composant
           renderSdPosition) : 6 colonnes fixes pour les indicateurs de
           synthèse — avec 11 tuiles, un auto-fit(minmax(120px,1fr)) en
           casait 8 sur la 1re ligne et 3 sur la 2e ; 6 colonnes répartit
           6+5, la meilleure répartition possible sur 2 lignes. */
        .sd-pos-tiles { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 12px 20px; margin-bottom: 16px; }
        @media (max-width: 820px) { .sd-pos-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
        @media (max-width: 480px) { .sd-pos-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
        /* Tableau des lots de l'onglet Position : 7 colonnes visibles + une
           dernière pour "edit". Sans largeurs explicites, le navigateur les
           dimensionne au contenu -> Side (juste "BUY"/"SELL") finissait
           aussi large que Date, et Log (menu déroulant + liens "+ log/+
           note") était écrasé. Les 5 colonnes de chiffres/dates restent
           égales entre elles, Side est réduite, Log est élargie. */
        .sd-pos-table { table-layout: fixed; }
        .sd-pos-table col.c-date, .sd-pos-table col.c-shares, .sd-pos-table col.c-cumul,
        .sd-pos-table col.c-price, .sd-pos-table col.c-pl { width: 13%; }
        .sd-pos-table col.c-side { width: 7%; }
        .sd-pos-table col.c-log { width: 21%; }
        .sd-pos-table col.c-edit { width: 7%; }
        .sd-page .sd-section-desc { font-size: var(--fs-body); color: var(--text-muted); margin: 0 0 15px 0; line-height: 1.45; }
        /* Chevron d'accès à la fiche explicative, à côté du nom de l'indicateur */
        .cs-doc {
            display: inline-block; margin-left: 5px; cursor: pointer;
            color: var(--text-muted); opacity: 0.5; font-weight: 700;
            transition: opacity 0.15s, color 0.15s;
        }
        .cs-doc:hover { opacity: 1; color: var(--accent); }
        .sd-stat-row:hover .cs-doc { opacity: 0.9; }

        /* Tuile Fundamentals sélectionnée : anneau superposé plutôt que
           bordure/fond en dur, pour ne pas écraser le style de pertinence
           (Analysis Framework) posé au rendu sur la même tuile. */
        .fund-tile.selected { box-shadow: 0 0 0 2px var(--accent) inset; }

        /* Panneau Peers d'une tuile Fundamentals : sélecteur de période —
           moyenne notre valeur ET celle des pairs sur leurs n derniers
           exercices (voir enrichir_peers_ref_local côté moteur) — même
           composant segmented-control que partout ailleurs sur le site, juste
           resserré pour tenir dans la largeur d'une tuile. */
        .fund-peer-period { margin-bottom: 10px; }
        .fund-peer-period .seg-btn { padding: 5px 14px; font-size: var(--fs-sm); }
        .fund-peer-period .seg-btn:disabled { opacity: 0.35; cursor: default; }

        /* Insider transactions : bande de tuiles cliquables par fenêtre,
           remplace l'ancien petit tableau à 5 colonnes clairsemées. Cliquer
           une tuile filtre le tableau détaillé en dessous (setInsidersWindow). */
        .ins-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
        .ins-tile { border: 1px solid var(--border); border-radius: 10px; padding: 12px 13px;
            cursor: pointer; background: var(--card-bg); transition: box-shadow .12s, border-color .12s; }
        .ins-tile.active { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; }
        .ins-tile-eyebrow { font-size: var(--fs-xs); font-weight: 800; letter-spacing: .6px;
            text-transform: uppercase; color: var(--text-muted); }
        .ins-tile.active .ins-tile-eyebrow { color: var(--accent); }
        .ins-tile-net { font-size: var(--fs-h2); font-weight: 700; font-variant-numeric: tabular-nums; margin: 4px 0 6px; }
        .ins-tile-break { font-size: var(--fs-xs); color: var(--text-muted); line-height: 1.4; }
        .ins-tile-cnt { font-size: var(--fs-xs); color: var(--text-muted); margin-top: 2px; }
        .ins-showing { font-size: var(--fs-sm); color: var(--text-muted); margin: 10px 2px 0; }
        .ins-showing strong { color: var(--text-main); }
        .ins-clear { font-size: var(--fs-xs); font-weight: 700; color: var(--accent); cursor: pointer;
            text-transform: uppercase; letter-spacing: .3px; }

        /* Governance : clusters thématiques, chaque tuile porte sa propre
           lecture (pas de liste de flags séparée répétant le même chiffre).
           Le cluster "Board composition" embarque directement la liste des
           officers qui le fonde, 4e colonne croisée avec l'insider trading. */
        .gov-cluster { border: 1px solid var(--border); border-radius: 10px; margin-bottom: 14px; overflow: hidden; }
        .gov-cluster-hd { display: flex; align-items: center; gap: 8px; padding: 11px 14px;
            background: var(--ind-bg); border-bottom: 1px solid var(--border); }
        .gov-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
        .gov-cluster-title { font-size: var(--fs-xs); font-weight: 800; letter-spacing: .5px;
            text-transform: uppercase; color: var(--text-muted); }
        .gov-cluster-body { padding: 14px; }
        /* overflow-x:auto (+ overflow-y:hidden pour rester cohérent avec le
           coin arrondi du .gov-cluster parent) : grid-template-columns est
           en minmax(Npx,1fr) (fixé en JS -- voir renderGovernance), donc la
           grille déborde proprement en panneau étroit (mode Split) au lieu
           de comprimer ses tuiles jusqu'à l'illisible comme avant. */
        .gov-tiles { display: grid; gap: 10px; overflow-x: auto; overflow-y: hidden; }
        .gov-tile { background: var(--input-bg); border: 1px solid var(--border); border-radius: 8px;
            padding: 9px 11px 10px; display: flex; flex-direction: column; gap: 5px; }
        .gov-tile-lbl { font-size: var(--fs-xs); color: var(--text-muted); text-transform: uppercase; letter-spacing: .3px; }
        .gov-tile-val { font-size: var(--fs-h2); font-weight: 700; font-variant-numeric: tabular-nums; }
        .gov-tile-sub { font-size: var(--fs-xs); color: var(--text-muted); font-weight: 400; }
        .gov-tile-read { font-size: var(--fs-xs); color: var(--text-muted); line-height: 1.35; }

        .gov-link-row { display: flex; align-items: center; gap: 8px; padding: 10px 14px;
            border-top: 1px dashed var(--border); font-size: var(--fs-xs); color: var(--text-muted); background: var(--ind-bg); }
        .gov-link-row b { color: var(--text-main); }

        /* overflow-x:auto ICI (pas juste sur .sd-card en amont) : .gov-officers
           vit à l'intérieur de .gov-cluster (cluster "Board composition"),
           qui a overflow:hidden pour son coin arrondi -- sans ce scroll
           local, ce overflow:hidden coupait le tableau des officers
           (.gov-off-head/.gov-off-row, min-width:480px) avant même qu'il
           puisse déborder jusqu'au conteneur scrollable de la carte. */
        .gov-officers { padding: 0 14px 6px; overflow-x: auto; }
        .gov-off-head { display: grid; grid-template-columns: 1fr 56px 84px 150px; gap: 10px; padding: 9px 0 6px;
            font-size: var(--fs-xs); font-weight: 800; letter-spacing: .4px; text-transform: uppercase;
            color: var(--text-muted); border-bottom: 1px solid var(--border);
            /* Les 3 colonnes chiffrées sont en px FIXE (jamais plus étroites,
               sans quoi âge/rémunération deviennent illisibles) -- sous cette
               largeur, .gov-off-head/.gov-off-row doivent dépasser l'encart
               plutôt que de s'écraser, pour que le scroll horizontal de
               .sd-card (voir plus haut) prenne le relais au lieu de tasser
               les chiffres. Même largeur mini pour l'en-tête et les lignes :
               elles défilent ensemble, alignées, dans le même conteneur. */
            min-width: 480px; }
        .gov-off-head .r { text-align: right; }
        .gov-off-row { display: grid; grid-template-columns: 1fr 56px 84px 150px; gap: 10px; align-items: baseline;
            padding: 8px 0; border-bottom: 1px solid var(--border); font-size: var(--fs-body); min-width: 480px; }
        .gov-off-row:last-child { border-bottom: none; }
        .gov-off-name { font-weight: 700; }
        .gov-off-title { color: var(--text-muted); font-size: var(--fs-xs); margin-left: 6px; }
        .gov-off-age { font-variant-numeric: tabular-nums; color: var(--text-muted); font-size: var(--fs-sm);
            text-align: right; display: flex; align-items: center; justify-content: flex-end; gap: 5px; }
        .gov-off-pay { font-variant-numeric: tabular-nums; color: var(--text-muted); font-size: var(--fs-sm); text-align: right; }
        .gov-off-act { font-variant-numeric: tabular-nums; font-size: var(--fs-xs); text-align: right; }
        .gov-age-flag { width: 6px; height: 6px; border-radius: 50%; background: var(--cyclical); flex-shrink: 0; }
        .gov-note { font-size: var(--fs-xs); color: var(--text-muted); margin: 6px 2px 0; }
        @media (max-width: 680px) {
            .gov-off-head, .gov-off-row { grid-template-columns: 1fr 44px 64px 110px; gap: 6px; }
        }

        /* Les deux analyses (cascade + bilan) côte à côte, même hauteur, sous
           le tableau brut. .fs-wf est la colonne : flex vertical pour que la
           note se pousse en bas et occupe toute la hauteur de la ligne. */
        .fs-twocol { display: none; grid-template-columns: 1fr 1fr; gap: 24px;
            margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--border); align-items: stretch; }
        .fs-twocol:has(.fs-wf:not(:empty)) { display: grid; }
        .fs-wf { display: flex; flex-direction: column; }
        .fs-wf:empty { display: none; }
        .fs-wf-head { font-size: var(--fs-eyebrow); font-weight: 700; letter-spacing: 0.6px;
            text-transform: uppercase; color: var(--accent); margin-bottom: 12px; }

        /* Étapes comptables en colonnes verticales (pas en lignes) : la
           hauteur de chaque barre occupe tout l'espace dispo dans la colonne,
           au lieu de rester collée en haut comme une petite liste de lignes. */
        .fs-wf-cols { display: flex; align-items: flex-end; gap: 10px; flex: 1 1 auto; min-height: 170px; }
        .fs-wf-col { flex: 1 1 0; min-width: 0; height: 100%; display: flex; flex-direction: column;
            align-items: center; justify-content: flex-end; }
        .fs-wf-col-val { font-size: var(--fs-xs); font-weight: 700; color: var(--text-main);
            font-variant-numeric: tabular-nums; white-space: nowrap; margin-bottom: 4px; }
        .fs-wf-col-drop .fs-wf-col-val { font-weight: 600; color: var(--danger); }
        .fs-wf-col-track { width: 100%; max-width: 54px; flex: 1 1 auto; display: flex; align-items: flex-end;
            background: var(--input-bg); border-radius: 4px 4px 0 0; overflow: hidden; }
        .fs-wf-col-bar { display: block; width: 100%; border-radius: 4px 4px 0 0; }
        .fs-wf-rev { background: var(--text-muted); }
        .fs-wf-ebitda { background: var(--success); }
        .fs-wf-net { background: color-mix(in srgb, var(--success) 65%, black); }
        .fs-wf-cost { background: var(--danger); }
        .fs-wf-col-lbl { font-size: var(--fs-xs); color: var(--text-muted); text-align: center;
            line-height: 1.25; margin-top: 6px; min-height: 2.5em; }
        .fs-wf-note { font-size: var(--fs-xs); color: var(--text-muted); padding-top: 10px; }
        @media (max-width: 780px) {
            .fs-twocol { grid-template-columns: 1fr; gap: 18px; }
        }
        /* Même repli, mais basé sur la largeur du panneau (utile en mode Split,
           où le panneau est étroit sans que le viewport le soit). */
        @container (max-width: 780px) {
            .fs-twocol { grid-template-columns: 1fr; gap: 18px; }
        }
        @media (max-width: 560px) {
            .fs-wf-cols { gap: 5px; }
            .fs-wf-col-track { max-width: 36px; }
        }

        /* Santé du bilan (façon Simply Wall St) : deux colonnes de blocs
           proportionnels, même hauteur (Actif = Passif + Capitaux propres). */
        .fs-bh-cols { display: flex; gap: 20px; margin-top: 6px; }
        .fs-bh-col { flex: 1 1 0; min-width: 0; }
        .fs-bh-cap { font-size: var(--fs-sm); font-weight: 700; color: var(--text-main); margin-bottom: 6px; }
        .fs-bh-bar { display: flex; flex-direction: column; gap: 2px; height: 240px;
            border-radius: 6px; overflow: hidden; background: var(--input-bg); }
        .fs-bh-seg { display: flex; flex-direction: column; justify-content: center; align-items: flex-start;
            min-height: 28px; padding: 4px 10px; overflow: hidden; color: #fff; }
        .fs-bh-t { font-size: var(--fs-xs); font-weight: 600; line-height: 1.2; white-space: nowrap; }
        .fs-bh-v { font-size: var(--fs-sm); font-weight: 800; line-height: 1.25;
            font-variant-numeric: tabular-nums; white-space: nowrap; }
        .fs-bh-a1 { background: var(--success); }
        .fs-bh-a2 { background: var(--success); opacity: 0.55; }
        .fs-bh-l1 { background: var(--danger); }
        .fs-bh-l2 { background: var(--danger); opacity: 0.55; }
        .fs-bh-eq { background: var(--stalwart); }
        .fs-bh-mi { background: var(--stalwart); opacity: 0.55; }
        @media (max-width: 560px) {
            .fs-bh-cols { flex-direction: column; }
            .fs-bh-bar { height: auto; }
            .fs-bh-seg { min-height: 44px; }
        }

        /* --- Investor Lens (test panel) --- */
        .sd-page .lens-btn {
            background: transparent; border: 1px solid var(--border); color: var(--text-muted);
            padding: 5px 12px; border-radius: 8px; cursor: pointer; font-size: var(--fs-sm);
            font-weight: 700; transition: 0.15s; white-space: nowrap;
        }
        .sd-page .lens-btn:hover { border-color: var(--accent); color: var(--text-main); }
        .lens-crit {
            display: grid; grid-template-columns: 20px 1fr auto; gap: 3px 10px;
            padding: 10px 4px 10px 10px; border-bottom: 1px solid var(--border); align-items: baseline;
            /* Liseré de verdict à gauche : scannable même sans lire l'icône ni
               la valeur — l'œil descend vite sur mobile. Transparent par défaut
               (ligne "info" ou verdict non reconnu), coloré par .v-<tone>. */
            border-left: 3px solid transparent; margin-left: -10px; padding-left: 13px;
        }
        .lens-crit.v-pass { border-left-color: var(--v-pass); }
        .lens-crit.v-fail { border-left-color: var(--v-fail); }
        .lens-crit.v-warn { border-left-color: var(--v-warn); }
        .lens-crit.v-na   { border-left-color: color-mix(in srgb, var(--v-na) 45%, transparent); }
        .lens-crit .lc-icon { font-weight: 700; }
        .lens-crit .lc-name { font-weight: 600; color: var(--text-main); font-size: var(--fs-body); }
        .lens-crit .lc-val {
            font-weight: 700; font-variant-numeric: tabular-nums; text-align: right;
            font-size: var(--fs-body); white-space: nowrap;
        }
        .lens-crit .lc-desc { grid-column: 2 / 4; font-size: var(--fs-sm); color: var(--text-muted); line-height: 1.4; }
        /* Réponse manuelle à un critère « Judge » du lens ETF : trois petits
           boutons en fin de description, puis le rappel de la réponse donnée.
           Discret — c'est une action secondaire, la description reste le texte
           qu'on lit. */
        .lens-ans { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 6px; margin-left: 8px;
            font-size: var(--fs-xs); color: var(--text-muted); }
        .lens-ans b { color: var(--text-main); font-weight: 600; }
        .lens-ans-b { font-family: inherit; font-size: var(--fs-xs); font-weight: 600; line-height: 1;
            padding: 3px 8px; border-radius: 999px; border: 1px solid var(--border);
            background: var(--card-bg); color: var(--text-muted); cursor: pointer; }
        .lens-ans-b:hover { border-color: var(--text-muted); color: var(--text-main); }
        .lens-ans-b.v-pass:hover { border-color: var(--v-pass); color: var(--v-pass); }
        .lens-ans-b.v-warn:hover { border-color: var(--v-warn); color: var(--v-warn); }
        .lens-ans-b.v-fail:hover { border-color: var(--v-fail); color: var(--v-fail); }
        /* Réponse périmée : la ligne garde son verdict (on n'efface pas le
           travail de l'utilisateur) mais le dit. */
        .lens-ans.stale { color: var(--v-warn); }
        .lens-crit.is-stale { background: color-mix(in srgb, var(--v-warn) 6%, transparent); }

        /* Score : puces comptées + petit anneau (proportion scored), pas une
           grosse fraction — un lens Lynch est une checklist à parcourir, pas
           une note à optimiser. */
        .lens-score { display: flex; align-items: center; justify-content: space-between;
            gap: 16px; flex-wrap: wrap; padding-bottom: 14px; margin-bottom: 4px; }
        .lens-chips { display: flex; gap: 8px; flex-wrap: wrap; }
        .lens-chip { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-sm);
            font-weight: 700; padding: 5px 11px; border-radius: 20px; font-variant-numeric: tabular-nums; }
        .lens-chip.v-pass { background: var(--v-pass-dim); color: var(--v-pass); }
        .lens-chip.v-fail { background: var(--v-fail-dim); color: var(--v-fail); }
        .lens-chip.v-warn { background: var(--v-warn-dim); color: var(--v-warn); }
        .lens-chip.v-na   { background: var(--v-na-dim); color: var(--v-na); }
        .lens-chip.v-irrelevant { background: transparent; color: var(--text-muted); border: 1px dashed var(--border); font-weight: 600; }
        .lens-ring-wrap { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
        .lens-ring-cap { font-size: var(--fs-sm); color: var(--text-muted); text-align: right; line-height: 1.2;
            text-transform: uppercase; letter-spacing: .07em; }
        .lens-ring-cap b { display: block; color: var(--text-main); font-variant-numeric: tabular-nums;
            font-size: var(--fs-display); font-weight: 800; letter-spacing: normal; text-transform: none; line-height: 1.15; }
        /* Tiroir des critères hors-sujet pour la catégorie courante (même
           registre que .fund-stats-toggle : petit bouton bordé, pas un lien nu). */
        .lens-hidden-toggle {
            display: inline-flex; align-items: center; gap: 5px; margin: 10px 0 2px;
            font-family: var(--font-ui); font-size: var(--fs-xs); font-weight: 700;
            padding: 4px 10px; border: 1px solid var(--border); border-radius: 7px;
            background: transparent; color: var(--text-muted); cursor: pointer;
        }
        .lens-hidden-toggle:hover { background: var(--hover-bg); color: var(--text-main); }
        #lens-hidden-crit .lens-crit:first-child { border-top: 1px solid var(--border); margin-top: 8px; }

        /* --- Sous-titre de zone sur la fiche action --- */
        .sd-page .sd-zone-head { margin: 8px 2px -6px; }
        .sd-page .sd-zone-head p {
            font-size: var(--fs-body); color: var(--text-muted); margin: 0; line-height: 1.45; max-width: 60ch;
        }

        /* --- Onglets de la fiche action (style fiscal.ai) --- */
        .sd-page .sd-tabs {
            display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
            border-bottom: 2px solid var(--border); padding-bottom: 12px; margin-bottom: 22px;
        }
        .sd-page .sd-tab {
            background: var(--card-bg); border: 1px solid var(--border); color: var(--text-muted);
            padding: 5px 14px; border-radius: 9px; cursor: pointer; letter-spacing: 0.2px;
            font-family: var(--font-ui); font-size: var(--fs-sm); font-weight: 700;
            white-space: nowrap; transition: 0.15s;
        }
        .sd-page .sd-tab:hover { color: var(--text-main); border-color: var(--accent); }
        .sd-page .sd-tab.active {
            color: #fff; background: var(--accent); border-color: var(--accent);
            box-shadow: 0 2px 12px rgba(138, 154, 91, 0.4);
        }
        .sd-page #lens-start-thesis,
        .sd-page #etfd-lens-start-thesis,
        .sd-page #cryd-lens-start-thesis,
        .sd-page #lens-learn-method,
        .sd-page #etfd-lens-learn,
        .sd-page #cryd-lens-learn {
            padding: 9px 18px; border-radius: 9px; cursor: pointer; letter-spacing: 0.3px;
            font-size: var(--fs-body); font-weight: 800; white-space: nowrap; transition: 0.15s;
            box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15); text-align: center;
        }
        .sd-page #lens-start-thesis,
        .sd-page #etfd-lens-start-thesis,
        .sd-page #cryd-lens-start-thesis { background: #ec9c4a; color: #3a2400; border: 1px solid #e0913c; }
        .sd-page #lens-learn-method,
        .sd-page #etfd-lens-learn,
        .sd-page #cryd-lens-learn { background: #3b82f6; color: #fff; border: 1px solid #2f6fd6; }
        .sd-page #lens-start-thesis:hover,
        .sd-page #etfd-lens-start-thesis:hover,
        .sd-page #cryd-lens-start-thesis:hover,
        .sd-page #lens-learn-method:hover,
        .sd-page #etfd-lens-learn:hover,
        .sd-page #cryd-lens-learn:hover { filter: brightness(1.05); }
        .sd-page .sd-panes { display: flex; gap: 24px; align-items: flex-start; }
        .sd-page .sd-panes.is-single { max-width: 1180px; margin: 0 auto; }
        .sd-page .sd-pane { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 30px;
            /* Permet aux grilles internes (ex. .fs-twocol) de se replier sur la
               largeur RÉELLE de ce panneau plutôt que sur celle du viewport :
               en mode Split, le panneau peut être étroit sur un écran large,
               ce qu'un @media classique ne détecte jamais. */
            container-type: inline-size; }
        .sd-page .sd-pane.is-hidden { display: none; }
        .sd-page .sd-panes.is-split .sd-pane {
            max-height: calc(100vh - 210px); overflow-y: auto; overflow-x: auto;
            position: sticky; top: 80px;
            border: 1px solid var(--border); border-radius: 12px; padding: 16px;
            background: var(--bg, var(--card-bg));
        }
        /* Sous 680px (téléphone, voir le même seuil ligne 941) seulement :
           même une tablette en portrait (≥768px) garde les deux panneaux
           côte à côte -- juste plus étroits -- grâce aux container queries
           internes (ex. .fs-twocol ligne ~980) qui replient déjà le contenu
           à l'échelle du panneau, pas du viewport. */
        @media (max-width: 680px) {
            /* flex-direction:column fait basculer l'axe transversal sur la
               largeur -- sans ce align-items:stretch, align-items:flex-start
               (ligne 1111, pensé pour le mode row où il gère la hauteur)
               réduit chaque panneau à la largeur de son contenu : tout se
               retrouve collé à gauche, le texte wrap en cascade et les
               panneaux s'étirent en hauteur/se chevauchent. */
            .sd-page .sd-panes.is-split { flex-direction: column; align-items: stretch; }
            .sd-page .sd-panes.is-split .sd-pane {
                max-height: none; overflow-y: visible; overflow-x: auto; position: static;
                width: 100%;
            }
        }
        /* Mode Split, panneau étroit (container query sur .sd-pane -- la
           largeur RÉELLE du panneau, pas du viewport, voir ligne 1114) :
           le scroll horizontal ci-dessus est un filet, pas la solution --
           certains boutons (CTA Investor Lens, .btn-outline/.btn-primary)
           ont un padding/texte pensés pour la pleine largeur et débordaient
           visiblement avant même d'atteindre ce filet. Rétrécis UNIQUEMENT
           en split (le mode Single, ~pleine largeur de l'écran, ne descend
           quasi jamais sous ce seuil) : jamais touché hors split. */
        @container (max-width: 480px) {
            .sd-panes.is-split .sd-pane .btn-outline,
            .sd-panes.is-split .sd-pane .btn-primary,
            .sd-panes.is-split .sd-pane .lens-btn,
            .sd-panes.is-split .sd-pane .lens-hidden-toggle,
            .sd-panes.is-split .sd-pane #lens-learn-method,
            .sd-panes.is-split .sd-pane #lens-start-thesis,
            .sd-panes.is-split .sd-pane #etfd-lens-learn,
            .sd-panes.is-split .sd-pane #etfd-lens-start-thesis,
            .sd-panes.is-split .sd-pane #cryd-lens-learn,
            .sd-panes.is-split .sd-pane #cryd-lens-start-thesis {
                padding: 5px 10px; font-size: var(--fs-xs); white-space: normal; text-align: center;
            }
        }
        /* L'en-tête Investor Lens (titre + "Pick your fighter" à gauche,
           Learn the method/New log entry à droite) est en justify-content:
           space-between + flex-wrap:wrap, avec min-width:220px à gauche et
           flex-shrink:0 à droite -- les deux ensemble ne laissent AUCUNE
           marge pour rétrécir, donc le wrap fait tomber les boutons sous le
           menu dès que le panneau est plus étroit que ~220px + boutons + gap.
           Contrairement au rapetissage des boutons ci-dessus (cosmétique,
           ne sert qu'en dessous de 480px), CE seuil de wrap peut survenir
           bien au-delà de 480px de large -- donc pas de @container ici,
           appliqué à TOUT panneau en Split, large ou étroit : le <select>
           a déjà max-width:100% pour rétrécir proprement, et sans contrainte
           de largeur artificielle les deux blocs se partagent l'espace
           dispo sans jamais wrapper en dessous de la ligne. */
        .sd-panes.is-split .sd-pane .lens-head-left { min-width: 0; }
        .sd-panes.is-split .sd-pane .lens-head-actions { flex-shrink: 1; min-width: 0; }

        /* Poignée de redimensionnement du Split (voir _wireSplitResizer en
           JS) : un 3e flex item entre les deux panneaux, order:2 fixe
           (primaire=1, secondaire=3, mis à jour par apply*Layout). Cachée
           par défaut (mode Single, et JS ne la touche pas) ; visible
           seulement .is-split, et seulement quand les panneaux sont vraiment
           côte à côte -- sous 680px le split est empilé en colonne (voir
           @media plus haut), glisser une largeur n'a alors plus de sens. */
        .sd-split-resizer { display: none; order: 2; flex: 0 0 auto; width: 10px; margin: 0 -5px;
            align-self: stretch; cursor: col-resize; position: relative; z-index: 1; touch-action: none; }
        .sd-split-resizer::before { content: ""; position: absolute; left: 4px; top: 8px; bottom: 8px; width: 2px;
            background: var(--border); border-radius: 2px; transition: background 0.15s; }
        .sd-split-resizer:hover::before, .sd-split-resizer.is-dragging::before { background: var(--accent); }
        .sd-panes.is-split .sd-split-resizer { display: block; }
        @media (max-width: 680px) {
            .sd-panes.is-split .sd-split-resizer { display: none; }
        }

        .back-btn { background: transparent; border: 1px solid var(--border); padding: 8px 16px; border-radius: 10px; cursor: pointer; font-weight: 600; margin-bottom: 20px; color: var(--text-main); transition: 0.2s; }
        .back-btn:hover { background: var(--hover-bg); }
        
        .btn-outline { background: transparent; border: 1px solid var(--border); padding: 5px 14px; border-radius: 10px; cursor: pointer; font-weight: 600; font-size: var(--fs-sm); color: var(--text-main); transition: 0.2s;}
        .btn-outline:hover { background: var(--hover-bg); }
        
        .btn-primary { background: var(--accent); border: none; padding: 5px 14px; border-radius: 10px; cursor: pointer; font-weight: 700; font-size: var(--fs-sm); color: #fff; transition: 0.2s;}
        .btn-primary:hover { filter: brightness(1.1); }
        
        .tv-chart-container { width: 100%; height: 450px; margin-bottom: 30px; background: var(--card-bg); border-radius: 16px; border: 1px solid var(--border); padding: 15px; box-sizing: border-box; }
        
        .toast { visibility: hidden; min-width: 200px; background-color: var(--accent); color: #fff; text-align: center; border-radius: 10px; padding: 12px; position: fixed; z-index: 10100; left: 50%; bottom: 30px; transform: translateX(-50%); font-size: var(--fs-body); font-weight: bold; opacity: 0; transition: opacity 0.3s; }
        .toast.show { visibility: visible; opacity: 1; }
        /* Variante "erreur" : ne se referme pas seule (voir showToast(msg, true))
           -- un message d'erreur technique (sync API, import...) doit rester
           lisible et copiable, pas disparaître après 3s comme un simple accusé
           de réception ("Note enregistrée"). */
        .toast.toast-error { background-color: var(--danger); text-align: left; font-weight: normal;
            display: flex; align-items: flex-start; gap: 10px; max-width: min(90vw, 480px); min-width: 0; }
        .toast-error .toast-msg { user-select: text; white-space: pre-wrap; word-break: break-word; flex: 1; }
        .toast-error .toast-close { flex: 0 0 auto; background: transparent; border: none; color: #fff;
            font-size: var(--fs-h2); line-height: 1; cursor: pointer; padding: 0 2px; opacity: 0.85; }
        .toast-error .toast-close:hover { opacity: 1; }
        
        .info-trigger { cursor: pointer; display: inline-flex; align-items: center; justify-content: center; margin-left: 4px; background: rgba(255,255,255,0.1); border-radius: 50%; width: 10px; height: 10px; font-size: var(--fs-xs); font-weight: bold; border: 1px solid var(--border); color: var(--text-muted); text-transform: none;}
       
        /* La confirmation générique et les toasts s'affichent par-dessus la
           fenêtre qui les a déclenchés. À z-index égal, c'est l'ordre du DOM
           qui tranchait et #appConfirmModal est déclaré avant les autres
           modales : la confirmation d'annulation d'un import s'ouvrait DERRIÈRE
           « Manage imports », donc inatteignable -- on ne pouvait plus annuler
           un import du tout. Même raison pour .toast (z-index 300), invisible
           dès qu'une fenêtre était ouverte. */
        #appConfirmModal { z-index: 10050; }
        .modal-overlay { display: none; position: fixed; z-index: 9999; left: 0; top: 0; width: 100%; height: 100%; background-color: rgba(12, 13, 16, 0.8); backdrop-filter: blur(4px); align-items: center; justify-content: center; }
        .modal-box { background-color: var(--card-bg); border: 1px solid var(--border); border-radius: 16px; width: 90%; max-width: 650px; padding: 28px; box-shadow: var(--hover-shadow); position: relative; max-height: 85vh; overflow-y: auto; color: var(--text-main); }
        .modal-close { position: absolute; top: 14px; right: 18px; font-size: var(--fs-h2); cursor: pointer; font-weight: bold; color: var(--text-muted); transition: 0.2s; }
        .modal-close:hover { color: var(--accent); }

        /* Aperçu de colonnes de l'assistant de mapping CSV : contenu très
           variable (en-têtes/valeurs d'un export tiers) — le tableau générique
           ci-dessus (table-layout:fixed + ellipsis) écrasait chaque colonne à
           une largeur égale et tronquait tout, le rendant illisible. Ici les
           colonnes suivent la largeur de leur contenu ; le wrapper
           overflow-x:auto (index.html) fait défiler horizontalement plutôt
           que de re-tronquer. */
        #csv-map-preview { table-layout: auto; width: auto; min-width: 100%; }
        #csv-map-preview th, #csv-map-preview td { white-space: nowrap; overflow: visible; text-overflow: clip; width: auto; }

        /* --- PORTFOLIO / HOLDINGS ---  (tokens typo : mêmes rôles que .sd-page) */
        .pf-kpi { background: var(--card-bg); border: 1px solid var(--border); border-radius: 12px; padding: 14px 16px; }
        .pf-kpi .k { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); margin-bottom: 6px; }
        .pf-kpi .v { font-size: var(--fs-h2); font-weight: 700; color: var(--text-main); font-variant-numeric: tabular-nums; }
        .pf-kpi .s { font-size: var(--fs-sm); font-weight: 600; margin-top: 2px; }

        /* Bandeau du dashboard : valeur · composition · risque, en une carte
           découpée par des filets — pas trois sous-cartes. */
        :root { --pf-c-etf:#3b82f6; --pf-c-stock:#8a9a5b; --pf-c-crypto:#8b5cf6; --pf-c-cash:#8b92a5; --pf-c-copy:#f59e0b;
            /* 5e cran du risk-meter : entre --warning (ambre) et --danger (rouge),
               aucun token sémantique existant ne couvre cette teinte. */
            --pf-c-risk-aggr:#f97316; }
        body.light-mode { --pf-c-stock:#7a8b4f; --pf-c-cash:#64748b; }
        /* Ecart entre cartes : 30 px, comme `.sd-pane` sur les pages Stock / ETF /
           Crypto. Le portefeuille vivait a 12 px (bande) et 8 px (statistiques) :
           ses cartes se touchaient presque, la ou les pages de detail laissent
           respirer. Une seule valeur pour les deux familles. */
        .pf-band { background: var(--card-bg); border: 1px solid var(--border); border-radius: 14px; display: grid; grid-template-columns: 1fr 1.15fr 1fr; margin-bottom: 30px; }
        .pf-band > .pf-z { padding: 20px 22px; }
        .pf-band > .pf-z + .pf-z { border-left: 1px solid var(--border); }
        /* Échelle typographique calme : les libellés ne sont pas des micro-
           capitales, et ils sont assez grands pour se lire à côté des chiffres
           (rapport ~2× au titre, pas 3,5×). */
        .pf-z .zl { font-size: var(--fs-sm); color: var(--text-muted); font-weight: 600; margin: 0 0 14px; display: flex; justify-content: space-between; align-items: baseline; }
        .pf-z .big { font-size: var(--fs-display); font-weight: 700; letter-spacing: -0.01em; line-height: 1.1; font-variant-numeric: tabular-nums; color: var(--text-main); }
        .pf-z .sub { font-size: var(--fs-sm); color: var(--text-muted); margin: 8px 0 14px; }
        .pf-splitbar { height: 6px; border-radius: 3px; overflow: hidden; display: flex; background: var(--input-bg); margin-bottom: 16px; }
        .pf-splitbar i { display: block; height: 100%; }
        .pf-deltas { display: grid; gap: 10px; }
        .pf-deltas .d { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
        .pf-deltas .d .k { font-size: var(--fs-body); color: var(--text-muted); }
        .pf-deltas .d .v { font-size: var(--fs-h3); font-weight: 700; font-variant-numeric: tabular-nums; }
        .pf-deltas .d .p { font-size: var(--fs-sm); font-weight: 600; margin-left: 6px; opacity: 0.85; }
        /* Œil « masquer les montants » (Home + Portfolio, même état). */
        .pf-z .zl .zl-r { display: inline-flex; align-items: center; gap: 8px; }
        .pv-eye { display: inline-flex; align-items: center; justify-content: center; padding: 3px;
            border: 0; border-radius: 6px; background: transparent; color: var(--text-muted);
            cursor: pointer; line-height: 0; }
        .pv-eye:hover { background: var(--input-bg); color: var(--text-main); }
        .pv-eye.off { color: var(--accent); }
        .ov-big-row { display: flex; align-items: center; gap: 8px; }
        .ov-big-row .ov-big { min-width: 0; }
        .pf-comp { display: flex; gap: 18px; align-items: center; }
        .pf-donut { position: relative; width: 116px; height: 116px; flex: 0 0 116px; }
        .pf-donut canvas { width: 116px; height: 116px; display: block; }
        .pf-donut .mid { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; }
        .pf-donut .mid .m1 { font-size: var(--fs-xs); color: var(--text-muted); }
        .pf-donut .mid .m2 { font-size: var(--fs-body); font-weight: 700; color: var(--text-main); font-variant-numeric: tabular-nums; }
        .pf-legend { flex: 1; display: grid; gap: 7px; min-width: 0; }
        .pf-legend .r { display: grid; grid-template-columns: 10px 1fr auto; gap: 9px; align-items: center; font-size: var(--fs-body); }
        .pf-legend .dot { width: 9px; height: 9px; border-radius: 2px; }
        .pf-legend .nm { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text-main); }
        .pf-legend .pc { color: var(--text-muted); font-variant-numeric: tabular-nums; }
        /* Le dimming ne porte que sur la pastille de couleur (comme le module
           Overview) : le nom et le pourcentage restent en pleine opacité pour
           TOUTES les classes d'actif (ETFs/Stocks comme Crypto/Cash/Copy) —
           avant, `.r.faint` estompait toute la ligne, texte compris, qui
           paraissait alors gris au lieu de noir. */
        .pf-legend .r.faint .dot { opacity: 0.62; }
        .pf-risk .rh { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
        .pf-risk .rh .n { font-size: var(--fs-h2); font-weight: 700; color: var(--text-main); }
        .pf-risk .rh .vv { font-size: var(--fs-sm); color: var(--text-muted); font-variant-numeric: tabular-nums; }
        .pf-meter { display: flex; gap: 3px; margin: 14px 0 5px; }
        .pf-meter i { flex: 1; height: 9px; border-radius: 2px; opacity: 0.3; }
        .pf-meter i.on { opacity: 1; }
        .pf-mrk { position: relative; height: 0; }
        .pf-mrk i { position: absolute; top: -3px; width: 0; height: 0; border-left: 5px solid transparent; border-right: 5px solid transparent; border-top: 7px solid var(--text-main); transform: translateX(-50%); }
        .pf-mscale { display: flex; justify-content: space-between; margin-top: 6px; }
        .pf-mscale span { font-size: var(--fs-xs); color: var(--text-muted); }
        .pf-drivers-hd { font-size: var(--fs-xs); color: var(--text-muted); font-weight: 700; text-transform: uppercase; letter-spacing: .4px; margin: 16px 0 0; }
        .pf-drivers { list-style: none; padding: 0; margin: 6px 0 0; display: grid; gap: 6px; }
        .pf-drivers li { font-size: var(--fs-sm); color: var(--text-muted); }
        .pf-drivers li b { color: var(--text-main); font-weight: 700; }

        .pf-stats { background: var(--card-bg); border: 1px solid var(--border); border-radius: 14px; margin-bottom: 30px; }
        .pf-value-body { position: relative; height: 220px; padding: 4px 18px 16px; }
        /* Sélecteur de période du graphe de compte : même gabarit que celui de
           la fiche action (.seg-btn, 5px 14px), pas les gros boutons d'avant. */
        /* Titre + périodes à gauche, rendement à droite -- même disposition
           que les graphiques de cours de la fiche action. */
        /* Champs de clé API : des <textarea> d'une ligne, pas des <input> --
           seul moyen fiable de sortir du champ d'action du gestionnaire de
           mots de passe de Chrome (voir pfApiConnectBrokerChanged). Maquillés
           ici pour se comporter exactement comme un champ de saisie. */
        .pf-api-secret { width: 100%; margin-top: 4px; box-sizing: border-box;
            padding: 12px 15px; border-radius: 12px; border: 1px solid var(--border);
            background: var(--input-bg); color: var(--text-main); font-family: inherit;
            font-size: var(--fs-body); line-height: 1.3; resize: none; overflow: hidden;
            white-space: nowrap; display: block; }
        .pf-api-secret:focus { outline: none; border-color: var(--accent); background: var(--hover-bg); }
        .pf-value-hd-l { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; min-width: 0; }
        /* Badge de performance : même pastille que le graphe de cours de la
           fiche action (.badge + .bg-fast / .bg-turnaround). */
        .pf-value-perf { font-variant-numeric: tabular-nums; font-weight: 600; white-space: nowrap; flex-shrink: 0; }
        .pf-value-perf:empty { display: none; }
        .pf-value-range { margin-bottom: 0; flex-wrap: wrap; }
        .pf-value-range .seg-btn { cursor: pointer; font-family: inherit; }
        .pf-value-range .seg-btn:disabled { opacity: .35; cursor: default; }
        .pf-stats .hd { font-size: var(--fs-sm); color: var(--text-muted); font-weight: 600; padding: 15px 18px 6px;
            display: flex; align-items: center; justify-content: space-between; gap: 10px; }
        .pf-stats .grid { display: grid; grid-template-columns: repeat(4, 1fr); }
        .pf-stats .s { padding: 13px 18px; border-top: 1px solid var(--border); }
        .pf-stats .s:nth-child(-n+4) { border-top: 0; }
        .pf-stats .s + .s { border-left: 1px solid var(--border); }
        .pf-stats .s:nth-child(4n+1) { border-left: 0; }
        .pf-stats .s .k { font-size: var(--fs-sm); color: var(--text-muted); }
        .pf-stats .s .v { font-size: var(--fs-h2); font-weight: 700; font-variant-numeric: tabular-nums; color: var(--text-main); margin-top: 3px; }
        .pf-stats .s .x { font-size: var(--fs-xs); color: var(--text-muted); margin-top: 1px; }
        /* Tuile « Lynch categories » : sa ligne de valeur est une phrase, pas
           un chiffre. Au format .v (--fs-h2, gras) elle pesait deux fois plus
           lourd que tout ce qui l'entourait dans la grille ; à --fs-body elle
           restait plus grosse que le titre de la tuile. Même taille que le
           titre (--fs-sm), donc même taille que le reste. */
        .pf-stats .s .v .pf-v-flat { font-size: var(--fs-sm); font-weight: 600; line-height: 1.35; }

        /* Colonne Name : ticker en tête, société atténuée à côté, sur UNE
           ligne. La colonne est calée pour que le plus long nom de société
           du portefeuille tienne pile ; les libellés de fonds, plus longs,
           se terminent par « … ». */
        .pf-nm { display: flex; align-items: center; gap: 8px; min-width: 0; }
        .pf-nm .cd { width: 7px; height: 7px; border-radius: 2px; flex: 0 0 auto; }
        .pf-nm .tk { font-weight: 700; color: var(--text-main); flex: 0 0 auto; }
        .pf-nm .co { font-size: var(--fs-body); color: var(--text-muted); min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

        @media (max-width: 900px) {
          .pf-band { grid-template-columns: 1fr; }
          .pf-band > .pf-z + .pf-z { border-left: 0; border-top: 1px solid var(--border); }
          .pf-stats .grid { grid-template-columns: repeat(2, 1fr); }
          .pf-stats .s:nth-child(-n+4) { border-top: 1px solid var(--border); }
          .pf-stats .s:nth-child(2n+1) { border-left: 0; }
          .pf-stats .s:nth-child(1), .pf-stats .s:nth-child(2) { border-top: 0; }
        }
        #pf-table th, #pf-closed-wrap th { text-align: center; padding: 8px 10px; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-muted); border-bottom: 1px solid var(--border); white-space: nowrap; }
        /* En-tête du tableau dashboard : libellé + tri + entonnoir alignés en
           flex ; l'entonnoir et le caret ne rétrécissent jamais, seul le
           libellé se tronque si vraiment à l'étroit. */
        #pf-table thead th, #pf-closed-wrap thead th, #pos-lots thead th { padding: 7px 8px; font-size: var(--fs-xs); text-transform: none; letter-spacing: 0; }
        #pos-lots thead th { border-bottom: 1px solid var(--border); color: var(--text-muted); }
        /* Même rythme que les autres tableaux de l'app (#pf-table…) : padding
           régulier, filet fin sous chaque ligne, survol, pas de retour à la
           ligne. Contrairement à #pf-table (beaucoup de lignes, colonnes à
           parts égales + libellés abrégés + "…"), ce tableau-ci n'a que
           quelques lignes par position -- en-têtes ET contenu doivent
           toujours être intégralement lisibles, quitte à élargir la colonne
           et scroller horizontalement (le conteneur .sd-card est déjà en
           overflow-x:auto) plutôt que de tronquer quoi que ce soit. */
        #pos-lots { table-layout: auto; width: auto; min-width: 100%; }
        #pos-lots th, #pos-lots td { width: auto; text-align: center; }
        #pos-lots td { padding: 10px 12px; white-space: nowrap; overflow: visible; text-overflow: clip; border-bottom: 1px solid var(--border); }
        #pos-lots tbody tr:hover td { background: var(--hover-bg); }
        #pos-lots tfoot td { border-top: 2px solid var(--border); border-bottom: 0; font-weight: 700; padding: 10px 12px; white-space: nowrap; }
        #pos-lots select { background: var(--input-bg); color: var(--text-main); border: 1px solid var(--border); border-radius: 8px; padding: 4px 6px; }
        #pf-table thead th .th-in, #pf-closed-wrap thead th .th-in { display: flex; align-items: center; gap: 3px; justify-content: center; }
        #pos-lots thead th .th-in { display: flex; align-items: center; gap: 3px; justify-content: center; }
        #pf-table thead th.pf-th-name .th-in, #pf-closed-wrap thead th.pf-th-name .th-in { justify-content: flex-start; }
        #pf-table thead th .th-lbl, #pf-closed-wrap thead th .th-lbl { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
        /* Position detail : le nom COMPLET de la colonne reste toujours visible
           (jamais abrégé/tronqué) -- voir la règle #pos-lots ci-dessus. */
        #pos-lots thead th .th-lbl { white-space: nowrap; overflow: visible; text-overflow: clip; }
        #pf-table thead th .col-filter, #pf-table thead th .pf-sc,
        #pf-closed-wrap thead th .col-filter, #pf-closed-wrap thead th .pf-sc,
        #pos-lots thead th .col-filter, #pos-lots thead th .pf-sc { flex: 0 0 auto; }
        #pf-table th.sortable, #pf-closed-wrap th.sortable, #pos-lots th.sortable { cursor: pointer; user-select: none; }
        #pf-table th.sortable:hover, #pf-closed-wrap th.sortable:hover, #pos-lots th.sortable:hover { color: var(--text-main); }
        #pf-table th.sorted, #pf-closed-wrap th.sorted, #pos-lots th.sorted { color: var(--text-main); }
        #pf-table th .pf-sc, #pf-closed-wrap th .pf-sc, #pos-lots th .pf-sc { font-size: 0.9em; }
        .pf-tbl-toolbar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 2px 2px 10px; }
        .pf-tbl-toolbar[hidden], .pf-tbl-toolbar:empty { display: none; }
        #pf-table th:first-child, #pf-closed-wrap th:first-child { text-align: left; }
        #pf-table td, #pf-closed-wrap td { text-align: center; padding: 10px; border-bottom: 1px solid var(--border); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
        #pf-table td:first-child, #pf-closed-wrap td:first-child { text-align: left; white-space: nowrap; }
        /* Largeur calée sur le contenu RÉELLEMENT affiché (pastille + ticker +
           nom, mesuré en JS après chaque rendu — voir _pfSizeNameCol dans
           app.js), entre un plancher et le plafond qui tenait le plus long nom
           de société du portefeuille (« UnitedHealth Group Incorporated »).
           Sans ça la colonne restait toujours à ce plafond même pour un
           portefeuille aux noms courts (crypto, ETF...), à moitié vide.
           table-layout est fixed : cette largeur est honorée, le reste se
           partage la place. La variable est pose sur l'élément <table> (pas
           ici) : ce sélecteur n'a qu'à la lire, avec le même plafond que
           repli tant que le JS n'a pas encore mesuré (premier rendu). */
        #pf-table th:first-child, #pf-table td:first-child { width: var(--pf-name-col-w, 280px); }
        #pf-closed-wrap th:first-child, #pf-closed-wrap td:first-child { width: var(--pf-closed-name-col-w, 260px); }
        /* Freeze pane : la colonne Name reste visible pendant le défilement
           horizontal (mêmes ombre/z-index que .col-ticker etc. dans le
           screener actions — th est déjà sticky top:0 via la règle globale
           `th { position: sticky; top: 0; ... }` plus haut ; on ajoute ici
           left:0 et un z-index plus élevé pour le coin haut-gauche). */
        #pf-table td:first-child, #pf-closed-wrap td:first-child {
            position: sticky; left: 0; background-color: var(--card-bg); z-index: 30;
            box-shadow: 10px 0 12px -8px rgba(0,0,0,0.28);
        }
        #pf-table th:first-child, #pf-closed-wrap th:first-child {
            position: sticky; left: 0; z-index: 50;
            box-shadow: 10px 0 12px -8px rgba(0,0,0,0.28);
        }
        #pf-table tbody tr.pf-pos { cursor: pointer; }
        #pf-table tbody tr.pf-pos:hover { background: var(--hover-bg); }
        /* La cellule figée a son propre fond opaque (ci-dessus, pour occulter
           les colonnes qui défilent dessous) : sans repeindre par-dessus, elle
           ne suivait pas la teinte de survol appliquée à la ligne. */
        #pf-table tbody tr.pf-pos:hover td:first-child {
            background: linear-gradient(var(--hover-bg), var(--hover-bg)) var(--card-bg);
        }
        .pf-lots td { background: rgba(255,255,255,0.02); font-size: var(--fs-sm); color: var(--text-muted); }
        .pf-wbar { display: inline-block; height: 6px; border-radius: 3px; background: var(--accent); vertical-align: middle; margin-left: 6px; }
        #txModal label { display: flex; flex-direction: column; gap: 4px; font-size: var(--fs-sm); color: var(--text-muted); }
        #txModal input, #txModal select, #txModal textarea { background: var(--bg-main, rgba(0,0,0,0.2)); border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px; color: var(--text-main); font-size: var(--fs-body); font-family: inherit; }
        #txModal input:focus, #txModal select:focus, #txModal textarea:focus { outline: none; border-color: var(--accent); }
        /* Compact : les hypothèses sont un moyen, pas la vedette — l'espace
           va au résultat (pastilles, coût, courbe). */
        #etfSimModal .modal-box { max-width: 620px; }
        /* .sd-section-desc n'est stylée que sous .sd-page (fiche action/ETF) ;
           cette modale est en dehors — sans ces deux règles le sous-titre
           gardait la taille par défaut du navigateur, pas var(--fs-body). */
        #etfSimModal #etfsim-title { margin: 0 0 4px; font-size: var(--fs-h3); }
        #etfSimModal .sd-section-desc { font-size: var(--fs-sm); color: var(--text-muted); margin: 0 0 14px; line-height: 1.4; }
        #etfSimModal .etfsim-h4 { margin: 14px 0 8px; font-size: var(--fs-xs); font-weight: 800; letter-spacing: 0.8px; text-transform: uppercase; color: var(--text-muted); }
        #etfSimModal .etfsim-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 12px; }
        #etfSimModal label { display: flex; flex-direction: column; gap: 3px; font-size: var(--fs-xs); font-weight: 700; color: var(--text-muted); }
        #etfSimModal .etfsim-field { position: relative; }
        #etfSimModal input { width: 100%; box-sizing: border-box; background: var(--input-bg); border: 1px solid var(--border); border-radius: 8px;
            padding: 6px 28px 6px 9px; color: var(--text-main); font-size: var(--fs-body); font-weight: 600;
            font-variant-numeric: tabular-nums; font-family: inherit; transition: border-color .15s, box-shadow .15s; }
        #etfSimModal input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 16%, transparent); }
        #etfSimModal .etfsim-suffix { position: absolute; right: 9px; top: 50%; transform: translateY(-50%); color: var(--text-muted); font-size: var(--fs-xs); font-weight: 700; pointer-events: none; }
        #etfSimModal .etfsim-hint { margin: 0; font-size: var(--fs-xs); font-weight: 400; color: var(--text-muted); line-height: 1.3; }
        #etfSimModal .etfsim-results-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin: 16px 0 4px; padding-top: 14px; border-top: 1px solid var(--border); }
        #etfSimModal .etfsim-results-head h4 { margin: 0; font-size: var(--fs-xs); font-weight: 800; letter-spacing: 0.8px; text-transform: uppercase; color: var(--text-muted); }
        #etfSimModal .etfsim-cost-card { display: flex; flex-direction: column; gap: 6px; margin-top: 12px; padding: 11px 14px; border: 1px solid var(--border); border-radius: 10px; background: color-mix(in srgb, var(--danger) 5%, transparent); }
        #etfSimModal .etfsim-cost-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: var(--fs-xs); }
        #etfSimModal .etfsim-cost-row .lbl { color: var(--text-muted); }
        #etfSimModal .etfsim-cost-row .val { font-weight: 700; font-variant-numeric: tabular-nums; color: var(--danger); }
        #etfSimModal .etfsim-cost-row.total { padding-top: 6px; border-top: 1px dashed var(--border); font-size: var(--fs-sm); }
        #etfSimModal .etfsim-cost-row.total .val { font-size: var(--fs-body); }
        #etfSimModal .etfsim-chart-card { margin-top: 14px; padding: 12px 12px 4px; border: 1px solid var(--border); border-radius: 10px; background: var(--input-bg); }
        #etfSimModal .etfsim-chart-note { margin: 6px 2px 0; font-size: var(--fs-xs); color: var(--text-muted); }
        #etfSimModal .etfsim-stat-grid { grid-template-columns: repeat(3, 1fr); }
        @media (max-width: 560px) {
            #etfSimModal .etfsim-grid { grid-template-columns: 1fr; }
            #etfSimModal .etfsim-stat-grid { grid-template-columns: 1fr; row-gap: 10px; }
            #etfSimModal .etfsim-stat-grid .etf-win + .etf-win::before { display: none; }
            #etfSimModal .etfsim-stat-grid .etf-win { padding-left: 0; }
        }
        #pf-ind-btn.active { background: var(--accent); color: #fff; border-color: var(--accent); }

        /* Calculateur de valeur intrinsèque (Buffett lens, critère "Intrinsic
           value check") — même recette visuelle que #etfSimModal ci-dessus
           (grille de champs, suffixe absolu, pastilles .etf-win-grid pour le
           résultat), scoping propre sous #buffettDcfModal plutôt que de
           réutiliser les classes .etfsim-* elles-mêmes scopées à leur modale. */
        #buffettDcfModal #bdcf-title { margin: 0 0 4px; font-size: var(--fs-h3); }
        #buffettDcfModal .sd-section-desc { font-size: var(--fs-sm); color: var(--text-muted); margin: 0 0 14px; line-height: 1.4; }
        #buffettDcfModal .bdcf-h4 { margin: 14px 0 8px; font-size: var(--fs-xs); font-weight: 800; letter-spacing: 0.8px; text-transform: uppercase; color: var(--text-muted); }
        #buffettDcfModal .bdcf-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 12px; }
        #buffettDcfModal label { display: flex; flex-direction: column; gap: 3px; font-size: var(--fs-xs); font-weight: 700; color: var(--text-muted); }
        #buffettDcfModal .bdcf-lbl { display: inline-flex; align-items: center; gap: 4px; }
        #buffettDcfModal .bdcf-field { position: relative; }
        #buffettDcfModal input { width: 100%; box-sizing: border-box; background: var(--input-bg); border: 1px solid var(--border); border-radius: 8px;
            padding: 6px 28px 6px 9px; color: var(--text-main); font-size: var(--fs-body); font-weight: 600;
            font-variant-numeric: tabular-nums; font-family: inherit; transition: border-color .15s, box-shadow .15s; }
        #buffettDcfModal input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 16%, transparent); }
        #buffettDcfModal .bdcf-suffix { position: absolute; right: 9px; top: 50%; transform: translateY(-50%); color: var(--text-muted); font-size: var(--fs-xs); font-weight: 700; pointer-events: none; }
        #buffettDcfModal .bdcf-hint { margin: 0; font-size: var(--fs-xs); font-weight: 400; color: var(--text-muted); line-height: 1.3; }
        #buffettDcfModal .bdcf-results-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin: 16px 0 4px; padding-top: 14px; border-top: 1px solid var(--border); }
        #buffettDcfModal .bdcf-results-head h4 { margin: 0; font-size: var(--fs-xs); font-weight: 800; letter-spacing: 0.8px; text-transform: uppercase; color: var(--text-muted); }
        #buffettDcfModal .etf-win-grid { grid-template-columns: repeat(3, 1fr); }
        #buffettDcfModal .bdcf-split { margin-top: 12px; padding: 11px 14px; border: 1px solid var(--border); border-radius: 10px; background: var(--input-bg); }
        #buffettDcfModal .bdcf-split-bar { display: flex; height: 8px; border-radius: 4px; overflow: hidden; margin: 8px 0 7px; background: var(--border); }
        #buffettDcfModal .bdcf-split-bar span { height: 100%; }
        #buffettDcfModal .bdcf-split-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: var(--fs-xs); color: var(--text-muted); }
        #buffettDcfModal .bdcf-split-row .dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 6px; }
        #buffettDcfModal .bdcf-sens-card { margin-top: 14px; padding: 12px 14px; border: 1px solid var(--border); border-radius: 10px; background: var(--input-bg); }
        #buffettDcfModal .bdcf-sens-card h4 { margin: 0 0 3px; font-size: var(--fs-xs); font-weight: 800; letter-spacing: 0.8px; text-transform: uppercase; color: var(--text-muted); }
        #buffettDcfModal .bdcf-sens-note { margin: 0 0 10px; font-size: var(--fs-xs); color: var(--text-muted); line-height: 1.35; }
        #buffettDcfModal table.bdcf-sens { width: 100%; border-collapse: collapse; font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }
        #buffettDcfModal table.bdcf-sens th, #buffettDcfModal table.bdcf-sens td { padding: 7px 6px; text-align: center; border: 1px solid var(--border); }
        #buffettDcfModal table.bdcf-sens th { color: var(--text-muted); font-weight: 700; background: var(--card-bg); }
        #buffettDcfModal table.bdcf-sens td.center { font-weight: 800; border-width: 2px; border-color: var(--accent); }
        @media (max-width: 560px) {
            #buffettDcfModal .bdcf-grid { grid-template-columns: 1fr; }
            #buffettDcfModal .etf-win-grid { grid-template-columns: 1fr; row-gap: 10px; }
            #buffettDcfModal .etf-win-grid .etf-win + .etf-win::before { display: none; }
            #buffettDcfModal .etf-win-grid .etf-win { padding-left: 0; }
            #buffettDcfModal table.bdcf-sens { font-size: var(--fs-xs); }
        }

              /* --- SIDE-PEEK PANEL --- */
        #side-peek {
            position: fixed;
            top: 65px;
            right: -500px;
            width: 450px;
            max-width: 90vw;
            height: calc(100vh - 65px);
            background-color: var(--card-bg);
            border-left: 1px solid var(--border);
            box-shadow: -8px 0 30px rgba(0, 0, 0, 0.1);
            z-index: 125;
            transition: right 0.3s cubic-bezier(0.1, 0.9, 0.2, 1);
            overflow-y: auto;
            padding: 30px;
            box-sizing: border-box;
        }
        
        #side-peek.open {
            right: 0;
        }
        
        .side-peek-close {
            position: absolute;
            top: 20px;
            right: 20px;
            cursor: pointer;
            font-size: var(--fs-h2);
            color: var(--text-muted);
            font-weight: bold;
            transition: 0.2s;
            padding: 5px 10px;
            border-radius: 6px;
            background: rgba(0, 0, 0, 0.05);
        }
        
        .side-peek-close:hover {
            color: var(--danger);
            background: rgba(239, 68, 68, 0.1);
        }

        /* --- 5. OVERRIDES FORCÉS (Nettoyage des couleurs claires écrites en dur) --- */
        
        /* 1. Cartes standards (On ne traque plus le #eff6ff ici) */
        [style*="background: #f8fafc"], [style*="background:#f8fafc"],
        [style*="background: #fff"], [style*="background:#fff"],
        [style*="background: white"], [style*="background:white"] {
            background-color: var(--card-bg) !important;
            color: var(--text-main) !important;
            border-color: var(--border) !important;
        }

        /* 2. Cartes-métriques cliquables (P/E, PEG, EPS…) — teinte bleue,
           UNIQUEMENT dans la fiche action. Ailleurs, les cartes cliquables
           gardent le fond standard. */
        .sd-page .sd-card[onclick] {
            background-color: rgba(59, 130, 246, 0.1) !important;
            color: var(--text-main) !important;
            transition: 0.2s !important;
        }
        .sd-page .sd-card[onclick]:hover {
            border-color: var(--accent) !important;
            background-color: rgba(59, 130, 246, 0.15) !important;
        }
        /* Cartes cliquables hors fiche action : fond normal, léger survol */
        .sd-card[onclick] { color: var(--text-main); transition: 0.2s; }
        .sd-card[onclick]:hover { border-color: var(--accent) !important; background-color: var(--hover-bg); }

        /* 3. Correction spécifique pour la zone de saisie du Journal —
           même correctif pour le composeur identique de la fiche ETF. */
        #detailNewEntryText, #etfd-detailNewEntryText {
            background-color: var(--card-bg) !important;
            color: var(--text-main) !important;
        }

/* ===================================================================
   BARRE D'OUTILS DU TABLEAU + FILTRES PAR COLONNE
   Les filtres ont quitté le bandeau au-dessus du tableau : ils sont
   maintenant sur l'en-tête de la colonne qu'ils filtrent. Ne reste en
   barre d'outils que ce qui porte sur le tableau entier — le compte de
   lignes, les filtres actifs, le choix des colonnes.
   =================================================================== */
.table-toolbar {
    display: flex; align-items: center; justify-content: space-between;
    gap: 16px; flex-wrap: wrap; margin: 0 0 12px;
}

/* --- En-tête de la page Stocks : titre + résumé vivant + outils --- */
.scr-hdr { display: flex; align-items: flex-start; justify-content: space-between; gap: 18px; flex-wrap: wrap; margin: 0 0 16px; }
.scr-hdr-main { min-width: 0; }
.scr-hdr .page-title { margin: 0; }
/* Sélecteur Stock / ETF / Crypto : remplace le <h1> fixe des 3 pages de
   screener. Mot actif = mêmes taille/poids que .page-title ; les deux
   autres suivent, effacés, dans l'ordre cyclique fixe (jamais un
   historique) — cf. renderScreenerSwitch() dans app.js. */
.scr-switch { display: flex; align-items: baseline; gap: 16px; margin: 0; flex-wrap: wrap; }
.scr-word { font-family: inherit; border: none; background: none; padding: 0; cursor: pointer; transition: font-size .15s ease, color .15s ease, opacity .15s ease; }
.scr-word.on { font-size: var(--fs-display); font-weight: 700; color: var(--text-main); cursor: default; }
.scr-word.off { font-size: var(--fs-h2); font-weight: 600; color: var(--text-muted); opacity: .6; }
.scr-word.off:hover { opacity: .95; color: var(--text-main); }
.scr-sub { margin: 5px 0 0; font-size: var(--fs-body); color: var(--text-muted); font-weight: 500; }
.scr-sub strong { color: var(--text-main); font-weight: 700; }
.scr-sub:empty { display: none; }   /* comptage déplacé dans le bandeau */
.scr-hdr-tools { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.scr-hdr-tools .tb-btn { padding: 5px 14px; font-size: var(--fs-sm); }

.scr-stats {
    display: flex; flex-wrap: wrap; align-items: stretch;
    border: 1px solid var(--border); border-radius: 12px;
    background: var(--card-bg); margin: 0 0 14px;
    /* pas d'overflow:hidden — sinon le menu ⚙ (position:absolute) est coupé */
}
.scr-stats .s:first-child { border-top-left-radius: 12px; border-bottom-left-radius: 12px; }
.scr-stats .s { flex: 1 1 128px; padding: 6px 14px; border-right: 1px solid var(--border); }
.scr-stats .s.s-shown { flex: 1.5 1 210px; }
.scr-stats .s:last-of-type { border-right: 0; }
.scr-stats .s .k { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); font-weight: 700; }
.scr-stats .s .v { font-size: var(--fs-body); font-weight: 700; color: var(--text-main); font-variant-numeric: tabular-nums; margin-top: 1px; }
/* unité (%, B, T, yr, / N) : MÊME taille que le nombre — plus de nombre géant
   collé à une unité minuscule. Juste un poil plus discret en couleur. */
.scr-stats .s .v .u { font-size: 1em; color: var(--text-muted); margin-left: 3px; font-weight: 600; }
/* le tri, À DROITE du comptage, sans faire grandir la case */
.scr-stats .s-sortby { font-size: var(--fs-xs); color: var(--text-muted); font-weight: 600; margin-left: 12px; white-space: nowrap; }
.scr-stats .s-cov { height: 4px; border-radius: 99px; background: var(--border); overflow: hidden; margin-top: 4px; }
.scr-stats .s-cov i { display: block; height: 100%; background: var(--accent); }
/* ⚙ choix des tuiles — partagé par le bandeau screener/ETF/crypto (dans la
   barre .scr-stats elle-même) ET par les Statistics du Portfolio (dans son
   en-tête .pf-stats .hd, une disposition différente donc pas de <div
   class="s-gear"> flottant dans la grille de tuiles). */
.scr-stats .s-gear, .pf-stats .s-gear { position: relative; margin-left: auto; align-self: center; padding: 0 10px; }
.scr-stats .s-gear > button, .pf-stats .s-gear > button {
    background: transparent; border: 1px solid var(--border); border-radius: 8px;
    color: var(--text-muted); font-size: var(--fs-body); padding: 5px 9px; cursor: pointer; line-height: 1;
}
.scr-stats .s-gear > button:hover, .pf-stats .s-gear > button:hover { border-color: var(--accent); color: var(--accent); }
.scr-stats .s-gear-pop, .pf-stats .s-gear-pop {
    display: none; position: absolute; right: 8px; top: calc(100% + 6px); z-index: 200;
    background: var(--card-bg); border: 1px solid var(--border); border-radius: 10px;
    box-shadow: 0 10px 30px rgba(0,0,0,0.4); padding: 8px; min-width: 200px;
    max-height: 60vh; overflow-y: auto;
}
.scr-stats .s-gear-pop label, .pf-stats .s-gear-pop label { display: flex; align-items: center; gap: 8px; padding: 6px 8px; font-size: var(--fs-body); color: var(--text-main); cursor: pointer; border-radius: 6px; }
.scr-stats .s-gear-pop label:hover, .pf-stats .s-gear-pop label:hover { background: var(--hover-bg); }
.scr-stats .s-gear-pop input, .pf-stats .s-gear-pop input { width: auto; margin: 0; }

.scr-chips-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 0 0 10px; }
.scr-chips-row:has(#filterChips:empty):has(#clearFiltersBtn[hidden]) { display: none; }
.scr-chips-row:has(#etfFilterChips:empty):has(#etfClearFiltersBtn[hidden]) { display: none; }
.scr-chips-row:has(#cryptoFilterChips:empty):has(#cryptoClearFiltersBtn[hidden]) { display: none; }

/* Macro — planche « Quiet board » : cartes carrées, mais la couleur ne se
   dépense que sur les lectures vraiment extrêmes (percentile ≤10 ou ≥90).
   Ailleurs le filet en tête de carte et le sparkline restent neutres — le
   silence visuel EST l'information : « rien à signaler ici ». */
/* Cartes à taille FIXE, jamais étirées ; 5 par ligne au maximum. */
.d-grid { display: flex; flex-wrap: wrap; gap: 14px; max-width: calc(224px * 5 + 14px * 4); }
.d-grid .d-card { flex: 0 0 224px; max-width: 100%; }
.d-card {
    background: var(--card-bg); border: 1px solid var(--border); border-top: 2px solid var(--border);
    border-radius: 10px; padding: 16px 18px 14px; cursor: pointer; transition: border-color .12s, transform .12s;
}
.d-card:hover { transform: translateY(-2px); border-color: var(--text-muted); }
.d-card.extreme { border-top-color: var(--rail); }
.d-card .nm { font-size: var(--fs-body); font-weight: 700; margin: 0 0 3px; color: var(--text-main); }
.d-card .ds { font-size: var(--fs-xs); color: var(--text-muted); margin: 0 0 10px; min-height: 2.1em; line-height: 1.4; }
.d-card svg { display: block; margin: 0 0 10px; }
.d-card .row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.d-card .val { font-size: var(--fs-display); font-weight: 700; color: var(--text-main); font-variant-numeric: tabular-nums; }
.d-card.extreme .val { font-weight: 800; }
.d-card .pct { font-size: var(--fs-xs); color: var(--text-muted); font-weight: 600; white-space: nowrap; }
.d-card .verdict { font-size: var(--fs-xs); font-weight: 700; margin-top: 6px; }
.d-empty { background: transparent; border-style: dashed; cursor: default; }
.d-empty:hover { transform: none; border-color: var(--border); }
.d-empty .nm { color: var(--text-muted); }
.d-empty .ds { min-height: 0; margin-bottom: 0; }

@media (max-width: 760px) {
    .scr-stats .s { flex-basis: 44%; border-bottom: 1px solid var(--border); }
    .scr-stats .s-save { flex-basis: 100%; margin: 8px 12px; }
}
/* Le compteur « x of y — sorted by Z » de la barre d'outils. La règle est
   portée par une classe, pas par l'id d'un tableau : les deux tableaux
   (Stocks, ETFs) disent la même chose et doivent se lire pareil. */
.table-count { font-size: var(--fs-body); color: var(--text-muted); font-weight: 600; }
.table-count strong { color: var(--text-main); font-size: var(--fs-h3); }
.toolbar-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.tb-wrap { position: relative; }

.tb-btn {
    display: inline-flex; align-items: center; gap: 7px;
    padding: 5px 14px; font-size: var(--fs-sm); font-weight: 600; cursor: pointer;
    color: var(--text-main); background: var(--input-bg);
    border: 1px solid var(--border); border-radius: 8px; transition: 0.15s;
}
.tb-btn:hover { border-color: var(--accent); color: var(--accent); }
.tb-btn--primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.tb-btn--primary:hover { filter: brightness(1.08); color: #fff; }
.tb-btn--clear { color: var(--text-muted); }
.tb-ico { width: 14px; height: 14px; fill: currentColor; opacity: .75; }

/* Pastilles : ce qui restreint la liste, lisible sans ouvrir un menu */
.filter-chips { display: flex; gap: 6px; flex-wrap: wrap; }
.chip {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 6px 4px 10px; border-radius: 999px; font-size: var(--fs-sm);
    color: var(--text-main); background: rgba(138, 154, 91, 0.14);
    border: 1px solid rgba(138, 154, 91, 0.35);
}
.chip strong { font-weight: 700; }
.chip-x {
    border: none; background: none; cursor: pointer; padding: 0 3px;
    font-size: var(--fs-h3); line-height: 1; color: var(--text-muted);
}
.chip-x:hover { color: var(--danger); }

/* L'entonnoir se remplit quand la colonne filtre — repère visuel immédiat */
th .col-filter {
    display: inline-flex; align-items: center; justify-content: center;
    width: 17px; height: 17px; margin-left: 5px; vertical-align: middle;
    border-radius: 4px; cursor: pointer; transition: 0.15s;
}
th .col-filter svg { width: 11px; height: 11px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linejoin: round; opacity: .45; }
th .col-filter:hover { background: rgba(138, 154, 91, 0.18); }
th .col-filter:hover svg { opacity: 1; }
th .col-filter.on { background: var(--accent); }
th .col-filter.on svg { fill: #fff; stroke: #fff; opacity: 1; }

.col-filter-pop {
    position: absolute; z-index: 400; width: 244px; max-height: 60vh;
    display: flex; flex-direction: column;
    background: var(--card-bg, var(--input-bg)); color: var(--text-main);
    border: 1px solid var(--border); border-radius: 10px;
    box-shadow: 0 12px 32px -12px rgba(0, 0, 0, 0.45);
}
.cf-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 10px 12px; border-bottom: 1px solid var(--border); font-size: var(--fs-body);
}
.cf-clear {
    border: none; background: none; cursor: pointer; padding: 0;
    font-size: var(--fs-sm); font-weight: 600; color: var(--text-muted);
}
.cf-clear:hover { color: var(--danger); }
.cf-body { padding: 10px 12px; overflow-y: auto; }
.cf-opt {
    display: flex; align-items: center; gap: 8px; padding: 4px 0;
    font-size: var(--fs-body); cursor: pointer;
}
.cf-opt input { width: auto !important; height: auto !important; margin: 0 !important; appearance: auto !important; }
.cf-sep { height: 1px; background: var(--border); margin: 9px 0; }
.cf-range { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.cf-range label { font-size: var(--fs-xs); color: var(--text-muted); font-weight: 600; display: block; }
.cf-range input, .col-filter-pop input[type="text"] {
    /* box-sizing : sans lui, 100 % + 16 px de marge intérieure + 2 px de
       bordure débordent de la colonne de grille, et les deux champs Min et
       Max se chevauchent. La feuille n'a pas de box-sizing global. */
    box-sizing: border-box;
    width: 100%; min-width: 0; margin-top: 3px; padding: 6px 8px; font-size: var(--fs-body);
    color: var(--text-main); background: var(--input-bg);
    border: 1px solid var(--border); border-radius: 6px;
}
.cf-range > label { min-width: 0; }
.cf-note { font-size: var(--fs-xs); color: var(--text-muted); margin: 8px 0 0; line-height: 1.4; }
.cf-foot { padding: 10px 12px; border-top: 1px solid var(--border); text-align: right; }

/* Les menus de la barre d'outils s'ancrent sous leur propre bouton */
.tb-wrap .columns-dropdown-menu { top: calc(100% + 6px); right: 0; left: auto; min-width: 226px; }

/* Repère à droite d'une tranche : convention de place (Micro, Small…)
   ou ordre de grandeur du nombre de titres concernés. Jamais le critère. */
.cf-hint {
    margin-left: auto; padding-left: 10px; font-size: var(--fs-xs);
    color: var(--text-muted); font-weight: 600;
}

/* Combinaisons de filtres enregistrées */
.view-row { display: flex; align-items: center; gap: 4px; }
.view-pick {
    flex: 1; text-align: left; padding: 6px 8px; font-size: var(--fs-body); font-weight: 600;
    color: var(--text-main); background: none; border: none; border-radius: 6px; cursor: pointer;
}
.view-pick:hover { background: rgba(138, 154, 91, 0.14); color: var(--accent); }
.view-del {
    border: none; background: none; cursor: pointer; padding: 2px 6px;
    font-size: var(--fs-h3); line-height: 1; color: var(--text-muted);
}
.view-del:hover { color: var(--danger); }

@media (max-width: 640px) {
    .table-toolbar { align-items: flex-start; flex-direction: column; gap: 10px; }
    .col-filter-pop { width: calc(100vw - 24px); }
}

/* --- Base de calcul portée par la colonne ------------------------------- */
th .col-basis {
    display: block; margin: 2px auto 0; font-size: var(--fs-xs); font-weight: 600;
    letter-spacing: .02em; text-transform: none; color: var(--text-muted);
    cursor: pointer; border-radius: 4px; padding: 1px 3px;
    width: fit-content; transition: 0.15s;
}
th .col-basis:hover { background: rgba(138, 154, 91, 0.18); color: var(--accent); }
/* Pastille de base figée : même graisse/police, mais inerte. */
th .col-basis-static { cursor: default; }
th .col-basis-static:hover { background: none; color: var(--text-muted); }
th .cb-car { margin-left: 2px; opacity: .6; }

.tb-val {
    padding: 1px 6px; border-radius: 5px; font-size: var(--fs-sm);
    color: var(--accent); background: rgba(138, 154, 91, 0.16);
}
.cf-group {
    margin: 8px 0 4px; font-size: var(--fs-xs); font-weight: 700; letter-spacing: .07em;
    text-transform: uppercase; color: var(--text-muted);
}
.cf-group:first-child { margin-top: 0; }
.basis-opt {
    display: block; width: 100%; text-align: left; padding: 6px 8px; margin-bottom: 2px;
    font-size: var(--fs-body); font-weight: 600; color: var(--text-main);
    background: none; border: none; border-radius: 6px; cursor: pointer;
}
.basis-opt:hover { background: rgba(138, 154, 91, 0.14); color: var(--accent); }
.basis-opt.on { background: var(--accent); color: #fff; }

/* Lecture d'une série : la conclusion, avant la courbe qui la justifie.
   Volontairement plus lisible que la légende du graphique — c'est la ligne
   qu'on retient, le tracé n'est que la preuve. */
.fund-read {
    margin: 8px 2px 4px; padding: 0;
    font-size: var(--fs-sm); line-height: 1.7; font-weight: 500;
    color: var(--text-muted); font-variant-numeric: tabular-nums;
}
/* superposition de 2 courbes dans le panneau History */
.fund-ov { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; flex-wrap: wrap; }
.fund-ov-sel {
    font-family: var(--font-ui); font-size: var(--fs-xs); padding: 4px 8px;
    border: 1px solid var(--border); border-radius: 7px;
    background: var(--card-bg); color: var(--text-main); cursor: pointer;
}
.fund-ov-norm {
    font-family: var(--font-ui); font-size: var(--fs-xs); font-weight: 700;
    padding: 4px 10px; border: 1px solid var(--accent); border-radius: 7px;
    background: transparent; color: var(--accent); cursor: pointer;
}
.fund-read b { color: var(--text-main); font-weight: 700; }
.fund-read .fr-zone {
    display: inline-block; padding: 0 7px; border-radius: 999px;
    font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.4px; vertical-align: 1px;
}
.fund-read .fr-cheap { color: var(--success); border: 1px solid var(--success); }
.fund-read .fr-mid   { color: var(--text-muted); border: 1px solid var(--border); }
.fund-read .fr-exp   { color: var(--warning); border: 1px solid var(--warning); }

/* Panneau History : le tableau Year/vs now/Growth par yr est replié par
   défaut derrière ce petit bouton — la courbe + la ligne de lecture portent
   déjà la conclusion, le détail année par année reste à un clic. */
.fund-stats-toggle {
    display: inline-flex; align-items: center; gap: 5px; margin-top: 6px;
    font-family: var(--font-ui); font-size: var(--fs-xs); font-weight: 700;
    padding: 4px 10px; border: 1px solid var(--accent); border-radius: 7px;
    background: transparent; color: var(--accent); cursor: pointer;
}
.fund-stats-toggle:hover { background: var(--hover-bg); }

/* Journal : petit repère qui dit d'un coup d'œil « note » ou « log » — un
   point de couleur devant un texte discret, au même registre que le reste
   de la ligne d'en-tête (.j-card-head), pas un badge qui attire l'œil plus
   que le contenu de la carte. */
.j-chip {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: var(--fs-sm); font-weight: 600; color: var(--text-muted);
}
.j-chip::before { content: "●"; font-size: 0.55em; color: var(--text-muted); }
.j-chip.note::before { color: var(--j-note); }
.j-chip.log::before  { color: var(--j-log); }
.j-card {
    border: 1px solid var(--border);
    border-radius: 10px; padding: 14px 16px; margin-bottom: 12px;
    /* surface explicite : les entrées s'alignent sur le blanc de l'éditeur,
       pas sur le fond de carte (qui paraît gris à côté, surtout en Split).
       Plus de bordure gauche colorée par type — le .j-chip la dit déjà
       (pastille + couleur), la répéter sur la carte double le signal pour
       rien. L'accent reste réservé au seul état épinglé. */
    background: var(--input-bg);
    transition: border-color .15s;
}
.j-card.log.clickable { cursor: pointer; }
.j-card.log.clickable:hover { border-color: var(--j-log); }
.j-card-head {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    font-size: var(--fs-sm); color: var(--text-muted); margin-bottom: 8px;
}
.j-card-head .j-actions { margin-left: auto; display: flex; gap: 12px; }
.j-card-head .j-actions span { cursor: pointer; color: var(--text-muted); font-weight: 600;
    font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .3px; }
.j-card-head .j-actions span:hover { color: var(--accent); }
.j-card-head .j-actions span.del:hover { color: var(--danger); }
.j-card.pinned { border-color: var(--accent); background: rgba(138,154,91,0.05); }
.j-card.is-archived, .sd-card.is-archived { opacity: 0.62; }

/* Barre d'outils de note : fondue dans un seul bloc avec l'éditeur (pas une
   barre grise séparée), icônes SVG au lieu d'émojis, tout en tokens du
   thème. Partagée par le composeur de la fiche action et celui de la page
   Notes — corrige les deux d'un coup. */
.composer { border: 1px solid var(--border); border-radius: 10px; background: var(--card-bg); margin-bottom: 15px; }
.fmt-bar { display: flex; align-items: center; gap: 2px; padding: 6px 8px;
    background: var(--ind-bg); border-bottom: 1px solid var(--border);
    border-radius: 10px 10px 0 0; flex-wrap: wrap; }
.fmt-btn { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 28px;
    border-radius: 6px; border: none; background: transparent; color: var(--text-muted);
    cursor: pointer; font-size: var(--fs-sm); font-weight: 700; }
.fmt-btn:hover { background: var(--hover-bg); color: var(--text-main); }
.fmt-btn svg { width: 16px; height: 16px; }
.fmt-div { width: 1px; height: 18px; background: var(--border); margin: 0 5px; flex-shrink: 0; }
.fmt-spacer { flex: 1 1 auto; }
.fmt-action { display: inline-flex; align-items: center; gap: 5px; height: 28px; padding: 0 10px;
    border-radius: 6px; border: none; cursor: pointer; font-size: var(--fs-xs); font-weight: 700; white-space: nowrap; }
.fmt-action.tags { background: var(--accent); color: #fff; }
.fmt-action svg { width: 14px; height: 14px; }
.composer-editor { border: none !important; border-radius: 0 !important; background: transparent !important; margin: 0 !important; }
.j-pin { cursor: pointer; user-select: none; font-size: var(--fs-body); line-height: 1; }
.j-pin.on { color: var(--accent); }
.j-pin:not(.on) { color: var(--text-muted); opacity: .55; }
.j-tags { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0 2px; }
.j-tag {
    font-size: var(--fs-xs); font-weight: 600; letter-spacing: .3px;
    padding: 1px 7px; border-radius: 999px; border: 1px solid var(--border);
    color: var(--text-muted); cursor: pointer;
}
.j-tag:hover, .j-tag.active { color: var(--accent); border-color: var(--accent); }
.j-tk { font-family: inherit; font-size: var(--fs-xs); color: var(--accent); font-weight: 700; }
.notes-toolbar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 18px 0 10px; }

/* ===== Notes — layout « Reader » : liste à gauche, lecture à droite ===== */
/* Composeur de note : bien détaché du panneau liste en dessous. */
#journal-note-form { margin-bottom: 26px; }
.notes-pane {
    display: grid; grid-template-columns: 300px 1fr;
    border: 1px solid var(--border); border-radius: 12px; overflow: hidden;
    background: var(--card-bg); min-height: 460px;
}
@media (max-width: 820px) { .notes-pane { grid-template-columns: 1fr; }
    .notes-pane.reading .notes-list { display: none; }
    .notes-pane:not(.reading) .notes-reader { display: none; } }
.notes-list { border-right: 1px solid var(--border); display: flex; flex-direction: column; min-width: 0; }
.notes-list .notes-toolbar { margin: 0; padding: 9px 11px; gap: 7px; border-bottom: 1px solid var(--border); }
.notes-list .notes-toolbar input[type=search] { flex: 1 1 90px; min-width: 80px; padding: 4px 8px; font-size: var(--fs-xs); border-radius: 6px; }
.notes-list .notes-toolbar label { font-size: var(--fs-xs); }
.notes-list .notes-toolbar .seg-btn { font-size: var(--fs-sm); }
.notes-list #notes-tagbar { display: flex; gap: 6px; flex-wrap: wrap; padding: 7px 11px 0; }
.notes-list #notes-tagbar:empty { display: none; }
.notes-list .rows { overflow-y: auto; flex: 1; }
.nr-compose { margin-top: 16px; border: 1px dashed var(--border); border-radius: 8px; padding: 8px 11px;
    display: flex; align-items: center; gap: 9px; }
.nr-compose input { flex: 1; border: 0; background: transparent; color: var(--text-main);
    font-family: var(--font-ui); font-size: var(--fs-body); outline: none; }
.nr-compose input::placeholder { color: var(--text-muted); }
.nr-compose button { border: 0; background: var(--accent); color: #fff; font-family: var(--font-ui);
    font-weight: 600; font-size: var(--fs-xs); padding: 5px 12px; border-radius: 6px; cursor: pointer; }
.nl-grp { font-size: var(--fs-sm); font-family: var(--font-ui); font-weight: 600;
    color: var(--text-main); padding: 9px 13px 6px; border-bottom: 1px solid var(--border);
    display: flex; justify-content: space-between; align-items: baseline; gap: 10px; cursor: pointer; }
.nl-grp:hover { color: var(--accent); }
.nl-grp > span:last-child { font-size: var(--fs-xs); font-weight: 400; color: var(--text-muted);
    white-space: nowrap; flex: none; }
.nl-it { padding: 9px 13px; border-bottom: 1px solid var(--border); cursor: pointer;
    display: flex; flex-direction: column; gap: 3px; }
.nl-it:hover { background: var(--hover-bg); }
.nl-it.on { background: rgba(138,154,91,0.10); box-shadow: inset 3px 0 0 var(--accent); }
.nl-it .r1 { display: flex; align-items: center; gap: 6px; font-size: var(--fs-xs); color: var(--text-muted); }
.nl-it .r1 .tk { font-family: var(--font-ui); font-weight: 700; color: var(--text-main); font-variant-numeric: tabular-nums; }
.nl-it .r1 .kd { width: 6px; height: 6px; border-radius: 50%; background: var(--j-note); flex: none; }
.nl-it .r1 .kd.log { background: var(--j-log); border-radius: 1px; }
.nl-it .r1 .kd.pin { background: var(--accent); }
.nl-it .r1 .wh { margin-left: auto; font-variant-numeric: tabular-nums; }
.nl-it .r2 { font-size: var(--fs-sm); color: var(--text-main); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Ligne de remplacement de la liste de notes : chargement, liste vide, erreur.
   `.nl-it` ne declare pas de font-size -- ses enfants `.r1`/`.r2` posent la
   leur. Un texte NU dedans heritait donc de la taille ambiante, plus grosse
   que la liste qu'il remplace (signale sur « No ETF notes yet — use “+ New
   entry”. » et « No note matches. »). On aligne sur `.r2`, le texte d'une
   note. Classe plutot qu'inline : le meme style etait recopie 7 fois. */
.nl-it.nl-ph { font-size: var(--fs-sm); color: var(--text-muted); cursor: default; }
.nl-it.nl-ph.err { color: var(--danger); }

/* Section Tools (vue "view-tools") : liste dense, un outil par ligne --
   même esprit que .nl-it ci-dessus (glyphe + libellé + ligne secondaire
   grisée), pas un second système de carte pour 3 lignes. */
/* Tools : les outils sont regroupés par la QUESTION à laquelle ils répondent,
   exactement comme la page publique -- même organisation, même intitulés, une
   palette de moins. L'aplat vert de l'accueil n'est pas repris : dans le
   Terminal il n'y a personne à convaincre, l'utilisateur est déjà entré.
   Les rangées sont un peu plus hautes que la liste d'origine pour loger le
   numéro d'index et le carré d'icône, qui distinguent une rangée d'outil
   d'une simple ligne de tableau. */
.tools-lede { font-size: var(--fs-body); color: var(--text-muted); margin: 0 0 22px; }
.tools-groups { display: flex; flex-direction: column; gap: 26px; max-width: 720px; }
.tools-group > h2 { font-size: var(--fs-xs); font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
  color: var(--text-muted); margin: 0 0 10px; padding-bottom: 9px; border-bottom: 1px solid var(--border); }
.tools-row { display: flex; align-items: center; gap: 14px; padding: 12px; margin-bottom: 8px;
  background: var(--card-bg); border: 1px solid var(--border); border-radius: 12px; cursor: pointer;
  text-decoration: none; color: inherit; box-shadow: var(--card-shadow);
  transition: border-color .15s ease, box-shadow .15s ease; }
.tools-row:hover { border-color: var(--accent); box-shadow: var(--hover-shadow); }
.tools-row .ti-box { flex: 0 0 auto; width: 36px; height: 36px; border-radius: 9px; background: var(--hover-bg);
  color: var(--accent); display: flex; align-items: center; justify-content: center; }
.tools-row .ti-box .ti-ico { width: 18px; height: 18px; opacity: 1; color: var(--accent); }
.tools-row .ti-txt { min-width: 0; flex: 1 1 auto; }
.tools-row .ti-name { display: block; font-size: var(--fs-body); font-weight: 600; color: var(--text-main); }
.tools-row .ti-desc { display: block; font-size: var(--fs-sm); color: var(--text-muted); margin-top: 3px; }
/* L'encart de droite : un échantillon de ce que l'outil produit vraiment --
   un chiffre, une courbe. Le nom d'un outil ne dit pas ce qu'il fait, un
   résultat si. Les échantillons des deux outils publics sont étiquetés
   « example » ; celui de la projection ROI est le rendement RÉELLEMENT obtenu,
   lu dans le portefeuille, parce qu'un chiffre décoratif à cet endroit se
   lirait comme la performance de l'utilisateur. */
/* Aplat vert pâle de l'encart « Specimen » : la même
   valeur rgba en clair et en sombre, le vert olive de la marque. */
.tools-row .ti-spec { flex: 0 0 240px; width: 240px; box-sizing: border-box; min-height: 88px; justify-content: center;
  display: flex; flex-direction: column; gap: 4px;
  padding: 10px 14px; background: rgba(157,179,111,.16); border-radius: 12px; text-align: right; color: var(--accent); }
.tools-row .ti-big { font-size: var(--fs-h2); font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; }
.tools-row .ti-cap { font-size: var(--fs-xs); color: var(--text-muted); line-height: 1.35; }
.tools-row .ti-curve { width: 100%; height: 28px; display: block; }
@media (max-width: 720px) { .tools-row { flex-wrap: wrap; } .tools-row .ti-spec { flex: 1 1 100%; width: 100%; min-height: 0; text-align: left; } }
.tools-row.is-soon { cursor: default; opacity: .55; }
.tools-row.is-soon:hover { border-color: var(--border); box-shadow: var(--card-shadow); }

/* Projection ROI : contrôles à gauche, résultats à droite ; une colonne sur
   écran étroit. Tout le reste réutilise .sd-card / .etf-win-grid déjà posés
   pour les fiches ETF -- rien de neuf à maintenir. */
.roi-grid { display: grid; grid-template-columns: minmax(0, 300px) minmax(0, 1fr); gap: 20px; align-items: start; }
@media (max-width: 900px) { .roi-grid { grid-template-columns: minmax(0, 1fr); } }
.roi-ctl { display: flex; flex-direction: column; gap: 8px; }
.roi-res { display: flex; flex-direction: column; gap: 20px; min-width: 0; }
.roi-h { font-size: var(--fs-eyebrow); letter-spacing: .1em; text-transform: uppercase; font-weight: 700; color: var(--text-muted); }
.roi-fact { display: flex; justify-content: space-between; gap: 12px; font-size: var(--fs-sm); padding-block: 3px; }
.roi-fact span { color: var(--text-muted); }
.roi-fact b { font-variant-numeric: tabular-nums; }
.roi-note { font-size: var(--fs-xs); color: var(--text-muted); }
.roi-dotted { border-bottom: 1px dotted var(--text-muted); cursor: pointer; }
.roi-dotted:hover { color: var(--text-main); border-bottom-style: solid; }
.roi-big { font-size: calc(var(--fs-display) * 1.7); font-weight: 750; letter-spacing: -.02em; font-variant-numeric: tabular-nums; line-height: 1.1; }
.roi-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }
/* position:static explicite : le `th { position: sticky }` global du screener
   collerait ces en-têtes au haut de la page dans une carte qui ne scrolle
   pas verticalement. */
.roi-table th { position: static; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .06em; cursor: default; text-align: right; padding: 6px 0 6px 12px; }
.roi-table th:first-child, .roi-table td:first-child { text-align: left; padding-left: 0; }
.roi-table td { text-align: right; padding: 6px 0 6px 12px; border-top: 1px solid var(--border); }
/* Pastilles des strategies comparees : une par courbe, retirable. */
.roi-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.roi-chip { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-xs); font-weight: 600;
            border: 1px solid var(--border); border-radius: 999px; padding: 3px 5px 3px 10px; white-space: nowrap; }
.roi-chip button { border: 0; background: none; color: var(--text-muted); cursor: pointer; font-size: 1.05em;
                   line-height: 1; padding: 0 4px; }
.roi-chip button:hover { color: var(--text-main); }
/* Bascule nominal / monnaie d'aujourd'hui. Deux boutons, un seul actif. */
.roi-seg { display: inline-flex; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.roi-seg button { flex: 1 1 auto; border: 0; background: none; color: var(--text-muted); cursor: pointer;
                       font-size: var(--fs-xs); font-weight: 600; padding: 6px 10px; font-family: inherit; }
.roi-seg button + button { border-left: 1px solid var(--border); }
.roi-seg button.active { background: var(--accent); color: var(--bg-color); }
.tools-row .ti-badge { font-size: var(--fs-xs); font-weight: 600; text-transform: uppercase; letter-spacing: .03em; }

.notes-reader { padding: 20px 26px; overflow-y: auto; min-width: 0; }
.notes-reader .nr-empty { color: var(--text-muted); font-size: var(--fs-body); padding: 40px 10px; text-align: center; }
.nr-head { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; margin-bottom: 3px; }
.nr-head .tk { font-family: var(--font-ui); font-weight: 700; color: var(--text-main);
    font-size: var(--fs-sm); font-variant-numeric: tabular-nums; cursor: pointer; }
.nr-head .name { font-size: var(--fs-h3); font-weight: 600; color: var(--text-main); cursor: pointer; }
.nr-head .tk:hover, .nr-head .name:hover { color: var(--accent); }
.nr-head .meta { margin-left: auto; font-size: var(--fs-xs); color: var(--text-muted); }
.nr-strip { font-size: var(--fs-xs); color: var(--text-muted); display: flex; gap: 15px; flex-wrap: wrap;
    padding: 8px 0 10px; border-bottom: 1px solid var(--border); font-variant-numeric: tabular-nums; }
.nr-strip b { color: var(--text-main); font-weight: 600; }
.nr-strip .lk { color: var(--accent); cursor: pointer; }
.nr-tags { display: flex; gap: 8px; flex-wrap: wrap; margin: 10px 0; align-items: baseline; }
.nr-tags .wh { margin-left: auto; font-size: var(--fs-xs); color: var(--text-muted); }
.nr-body { font-family: var(--font-ui); font-size: var(--fs-body); line-height: 1.6;
    color: var(--text-main); max-width: 68ch; }
.nr-log { font-family: var(--font-ui); }

/* ===== Investment log — rendu « brief + scorecard » ===================== */
.ilog { font-family: var(--font-ui); color: var(--text-main); }
.ilog-h { position: relative; padding: 13px 16px; border-bottom: 1px solid var(--border); }
.ilog-id { display: flex; align-items: baseline; gap: 6px 10px; flex-wrap: wrap; padding-right: 155px; }
.ilog-h .tk { font-weight: 700; font-variant-numeric: tabular-nums; font-size: var(--fs-sm);
    background: var(--input-bg); border: 1px solid var(--border); border-radius: 5px; padding: 1px 6px; cursor: pointer; }
.ilog-h .nm { font-size: var(--fs-h3); font-weight: 600; cursor: pointer; }
.ilog-h .tk:hover, .ilog-h .nm:hover { color: var(--accent); }
.ilog-h .fw { font-size: var(--fs-sm); color: var(--j-log); font-weight: 600; }
.ilog-h .dt { font-size: var(--fs-xs); color: var(--text-muted); }
.ilog-score { display: flex; align-items: center; gap: 10px 14px; flex-wrap: wrap; margin-top: 8px; }
.ilog-h .lens-chips { display: inline-flex; gap: 6px; flex-wrap: wrap; }
.ilog-h .conv { font-size: var(--fs-eyebrow); font-weight: 700; letter-spacing: .03em;
    padding: 2px 8px; border-radius: 5px; border: 1px solid currentColor; text-transform: uppercase; }
.ilog-h .conv.hi { color: var(--success); }
.ilog-h .conv.mid { color: var(--warning); }
.ilog-h .conv.lo { color: var(--danger); }
.ilog-h .act { position: absolute; top: 13px; right: 16px; display: flex; gap: 13px; font-size: var(--fs-eyebrow); }
.ilog-h .act span { cursor: pointer; font-weight: 700; letter-spacing: .02em; color: var(--text-muted); }
.ilog-h .act span:hover { color: var(--accent); }
.ilog-h .act .del:hover { color: var(--danger); }

.ilog-b { padding: 2px 16px 14px; }
.ilog-sec { padding: 13px 0; border-bottom: 1px solid var(--border-soft, var(--border)); }
.ilog-sec:last-child { border-bottom: 0; padding-bottom: 2px; }
.ilog-lbl { font-size: var(--fs-eyebrow); letter-spacing: .09em; text-transform: uppercase;
    font-weight: 700; color: var(--accent); margin: 0 0 5px; }
.ilog-sec.exit .ilog-lbl { color: var(--danger); }
.ilog-lbl .sub { color: var(--text-muted); font-weight: 400; letter-spacing: 0; text-transform: none; }
.ilog-prose { font-family: var(--font-ui); font-size: var(--fs-body); line-height: 1.55; color: var(--text-main); }
.ilog-prose p { margin: 0 0 .5em; } .ilog-prose p:last-child { margin-bottom: 0; }
.ilog-prose i { color: var(--text-muted); }

.ilog-crit { margin-top: 3px; }
.ilog-cr { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 9px 0;
    border-top: 1px solid var(--border-soft, var(--border)); }
.ilog-cr:first-child { border-top: 0; }
.ilog-cr .ver { font-size: var(--fs-eyebrow); font-weight: 700; letter-spacing: .02em; }
.ilog-cr .ver.ok { color: var(--success); }
.ilog-cr .ver.mid { color: var(--warning); }
.ilog-cr .ver.no { color: var(--danger); }
.ilog-cr .ver.na { color: var(--text-muted); font-weight: 600; font-style: italic; }
.ilog-cr .k { font-size: var(--fs-sm); font-weight: 600; margin-bottom: 2px; }
.ilog-cr .d { font-family: var(--font-ui); font-size: var(--fs-body); line-height: 1.5; color: var(--text-muted); }
.ilog-cr .d i { color: var(--text-muted); }
.ilog-sc { margin: 2px 0 13px; padding: 9px 12px; border-radius: 8px; border: 1px solid var(--border); background: var(--hover-bg); }
.ilog-sc.changed { border-color: var(--warning); }
.ilog-sc-hd { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; font-size: var(--fs-sm); font-weight: 700; }
.ilog-sc.changed .ilog-sc-hd { color: var(--warning); }
.ilog-sc-hd .dt { font-weight: 400; color: var(--text-muted); font-size: var(--fs-xs); }
.ilog-sc-rows { margin-top: 6px; display: flex; flex-direction: column; gap: 3px; }
.ilog-sc-row { font-size: var(--fs-sm); color: var(--text-muted); display: flex; align-items: center; gap: 6px; }
.ilog-sc-arrow { color: var(--text-muted); }
.nr-body p { margin: 0 0 .6em; }
.nr-body ul { margin: .3em 0 .7em; padding-left: 1.3em; }
.nr-sec { font-size: var(--fs-xs); color: var(--text-muted); font-weight: 600; margin: 14px 0 3px; }
.nr-foot { margin-top: 16px; padding-top: 10px; border-top: 1px solid var(--border);
    display: flex; gap: 14px; font-size: var(--fs-xs); }
.nr-foot span { cursor: pointer; color: var(--text-muted); }
.nr-foot span:hover { color: var(--accent); }
.nr-foot .del:hover { color: var(--danger); }
.nr-earlier { margin-top: 18px; }
.nr-earlier .nr-sec { margin-bottom: 6px; }
.nr-earlier .row { font-family: var(--font-ui); font-size: var(--fs-body); color: var(--text-muted);
    line-height: 1.5; margin: 0 0 .4em; cursor: pointer; }
.nr-earlier .row:hover { color: var(--text-main); }
.nr-earlier .row em { color: var(--j-log); font-style: normal; }

.notes-toolbar input[type=search] {
    flex: 1 1 220px; min-width: 160px; background: var(--card-bg);
    border: 1px solid var(--border); color: var(--text-main);
    padding: 7px 12px; border-radius: 8px; font-size: var(--fs-body); outline: none;
}
.notes-toolbar label { font-size: var(--fs-body); color: var(--text-muted); display: flex; align-items: center; gap: 6px; cursor: pointer; }

/* ===== Fiche ETF — onglet Data : Key facts/Composition/Simulateur/
   Governance en grille à 2 colonnes ÉGALES, 2 cartes par ligne (Key facts +
   Composition, puis Simulateur + Governance) — chaque ligne se dimensionne
   sur son propre contenu, contrairement à 2 longues colonnes indépendantes
   qui laissaient un grand vide sous la plus courte. Se replie sur 1 colonne
   sous 960px, comme les autres grilles à 2 colonnes de l'app (.notes-pane à
   820px). ===== */
.etfd-2col { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; align-items: start; }
@media (max-width: 960px) { .etfd-2col { grid-template-columns: 1fr; } }
/* Carte Performance : By window / By calendar year côte à côte plutôt
   qu'empilés — la carte est pleine largeur, une seule colonne de texte
   laisserait un grand vide de chaque côté. Les deux sont maintenant du texte
   pur, mêmes lignes .sd-stat-row (plus de tuiles à gros chiffres) : partage
   à parts égales, plus de colonne "prioritaire". */
/* 3 colonnes : By window, By calendar year, Dividend yield. Les deux
   premieres sont volontairement retrecies (1fr) au profit de la
   troisieme (0.62fr), qui ne porte que deux lignes courtes -- elle n'a
   pas besoin d'autant de place, mais les deux autres n'ont pas besoin
   de toute la carte non plus. */
.etf-perf-cols { display: grid; grid-template-columns: 1fr 1fr 0.62fr; gap: 24px; margin-top: 6px; }
/* Fonds Accumulating : pas de colonne de rendement (il ne verse rien), la
   carte reprend l'allure a deux colonnes qu'elle avait avant. Declare ici,
   donc AVANT les @media ci-dessous, pour que les paliers etroits gardent
   la main sur ce modificateur. */
.etf-perf-cols.etf-perf-cols--sans-rdt { grid-template-columns: 1fr 1fr; }
/* Filet entre les exercices et les moyennes, dans la colonne Dividend yield :
   six lignes d'affilee se lisaient comme une seule liste, alors que les trois
   premieres sont des annees et les suivantes des agregats. */
.etf-rdt-sep { height: 1px; background: var(--border); margin: 5px 0; }
/* Palier intermediaire : a 3 colonnes la carte devient vite etroite, donc
   le rendement passe a la ligne (2 colonnes) AVANT l'empilement complet. */
@media (max-width: 900px) { .etf-perf-cols { grid-template-columns: 1fr 1fr; } }
@media (max-width: 640px) { .etf-perf-cols { grid-template-columns: 1fr; } }
/* Suffixe annualisé (« · +11.2%/yr ») à côté du rendement cumulé, sur la
   même ligne — pas de 2e ligne séparée comme l'ancienne tuile .etf-win. */
.etf-win-ann { color: var(--text-muted); font-weight: 500; font-size: 0.85em; }
/* By calendar year : 2 colonnes au lieu d'une longue liste d'une ligne par
   année (même recette que .etfd-kv-cols) -> la carte gagne en hauteur ce
   que By window gagne en largeur. */
.etfd-years-grid { display: grid; grid-template-columns: 1fr 1fr; column-gap: 20px; }
@media (max-width: 420px) { .etfd-years-grid { grid-template-columns: 1fr; } }
/* Même principe pour la fiche Crypto (option A des 2 propositions soumises
   à l'utilisateur) : colonne large = parcours de la pièce (chart, coin
   statistics) ; colonne étroite = faits (équipe, techno, classification,
   news) — l'équipe n'a plus besoin de toute la largeur de l'écran pour
   tenir sur 2-3 lignes par personne. */
.cryd-2col { display: grid; grid-template-columns: 1.6fr 1fr; gap: 24px; align-items: start; }
.cryd-2col > div { display: flex; flex-direction: column; gap: 20px; min-width: 0; }
@media (max-width: 960px) { .cryd-2col { grid-template-columns: 1fr; } }
/* Technology / Classification / News : 3 tuiles courtes côte à côte plutôt
   qu'empilées, pour ne pas laisser de vide sous chacune. */
.cryd-3col { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; align-items: start; }
@media (max-width: 960px) { .cryd-3col { grid-template-columns: 1fr 1fr; } }
@media (max-width: 640px) { .cryd-3col { grid-template-columns: 1fr; } }
/* Toutes les grilles ci-dessus (.etfd-2col/.etf-perf-cols/.etfd-years-grid/
   .cryd-2col/.cryd-3col) ne repliaient que sur la largeur du VIEWPORT
   (@media), jamais sur celle du panneau -- exactement le piège déjà décrit
   pour .fs-twocol plus haut : en mode Split, le panneau peut être étroit
   sur un écran par ailleurs large, un @media classique ne le voit jamais.
   Résultat signalé : Key facts/Composition et les tuiles crypto restaient
   côte à côte, écrasées, dans un panneau de Split étroit. Mêmes seuils que
   les @media ci-dessus, en @container (largeur réelle de .sd-pane, qui
   porte container-type:inline-size -- voir plus haut) : se replie dès que
   LE PANNEAU est étroit, que le Split soit actif ou non. */
@container (max-width: 960px) {
    .etfd-2col { grid-template-columns: 1fr; }
    .cryd-2col { grid-template-columns: 1fr; }
    .cryd-3col { grid-template-columns: 1fr 1fr; }
}
@container (max-width: 900px) { .etf-perf-cols { grid-template-columns: 1fr 1fr; } }
@container (max-width: 640px) {
    .etf-perf-cols { grid-template-columns: 1fr; }
    .cryd-3col { grid-template-columns: 1fr; }
}
@container (max-width: 420px) {
    .etfd-years-grid { grid-template-columns: 1fr; }
}
/* Liste libellé/valeur générique de la fiche ETF (faits clés, structure
   juridique, statut fiscal…) — un seul style, remplace 3 copies du même
   inline-style qui ne faisaient que grossir le fichier. Des <div>, pas une
   <table> : un CSS multi-colonnes (.etfd-kv-cols) ne fragmente que des
   boîtes de bloc, jamais les lignes d'un tableau. */
.etfd-kv-row { display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
    padding: 7px 0; font-size: var(--fs-body); border-bottom: 1px solid var(--border);
    break-inside: avoid-column; }
.etfd-kv-row .k { color: var(--text-muted); white-space: nowrap; }
.etfd-kv-row .v { text-align: right; }
.etfd-kv-row:last-child { border-bottom: none; }
/* Key facts (11 lignes) laissait la colonne Performance/Index tracked très
   en retrait à côté — 2 colonnes ramènent sa hauteur de moitié, bien plus
   proche de sa voisine. Se replie sur 1 colonne en dessous de 480px (une
   fois la colonne de droite de .etfd-2col déjà repliée en pleine largeur,
   960px de large peut encore être trop étroit pour 2 lignes lisibles). */
.etfd-kv-cols { columns: 2; column-gap: 28px; }
@media (max-width: 480px) { .etfd-kv-cols { columns: 1; } }
/* Même lacune que .etfd-2col ci-dessus : ce seuil ne regarde que le
   viewport, jamais la largeur réelle du panneau en mode Split -- Key facts
   (cette grille) est justement l'encart signalé "tout fucké" en Split,
   compressé en 2 colonnes illisibles dans un panneau étroit. */
@container (max-width: 480px) { .etfd-kv-cols { columns: 1; } }

/* ===== Community — "Desk" (option A des 2 propositions soumises à
   l'utilisateur) : rail de thèmes à gauche (comptage, sélection en place,
   pas de navigation plein écran) + fil de fils dense à droite, barre de
   couleur par thème plutôt que des cartes bordées. Police : --font-ui comme
   PARTOUT ailleurs sur le site (même les tickers/compteurs/horodatages n'y
   passent jamais en --font-mono, ex. .nl-it .r1 .tk, .pf-nm .tk) — seuls les
   nombres prennent font-variant-numeric:tabular-nums pour s'aligner, jamais
   un changement de police. */
.comm-header{ display:flex; align-items:flex-end; justify-content:space-between; gap:16px; flex-wrap:wrap; margin-bottom:16px; }
.comm-header .page-title{ margin:0; }
.comm-header-sub{ margin:0; font-size: var(--fs-xs); color:var(--text-muted); font-variant-numeric: tabular-nums; }
.comm-new-btn{ display:inline-flex; align-items:center; gap:8px; background:var(--accent); color:var(--bg-color);
    font-weight:700; font-size: var(--fs-sm); padding:5px 14px; border-radius:7px; border:none; cursor:pointer; }
.comm-new-btn:hover{ filter:brightness(1.08); }

.comm-body{ display:flex; gap:28px; align-items:flex-start; }

.comm-rail{ width:224px; flex:0 0 auto; display:flex; flex-direction:column; gap:2px; padding:16px; }
.comm-rail-label{ margin:0 0 6px; font-size: var(--fs-xs); letter-spacing:.12em; text-transform:uppercase; color:var(--text-muted); }
.comm-rail-row{ display:flex; align-items:center; gap:10px; padding:9px 10px; border-radius:6px; border-left:2px solid transparent; cursor:pointer; }
.comm-rail-row:hover{ background:var(--hover-bg); }
.comm-rail-row.active{ background:var(--v-pass-dim); border-left-color:var(--accent); }
.comm-rail-dot{ width:6px; height:6px; border-radius:50%; flex:0 0 auto; }
.comm-rail-name{ flex:1 1 auto; font-size: var(--fs-body); color:var(--text-main); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.comm-rail-row.active .comm-rail-name{ font-weight:700; }
.comm-rail-count{ font-size: var(--fs-xs); color:var(--text-muted); font-variant-numeric: tabular-nums; }
.comm-rail-div{ height:1px; background:var(--border); margin:14px 0; }
.comm-rail-note{ margin:0; font-size: var(--fs-sm); color:var(--text-muted); line-height:1.5; }

.comm-feed{ flex:1 1 auto; min-width:0; padding:18px 20px; }
.comm-filter-strip{ display:flex; align-items:center; gap:4px; padding-bottom:10px; margin-bottom:4px; border-bottom:1px solid var(--border); }
.comm-filter-tab{ font-size: var(--fs-sm); color:var(--text-muted); padding:5px 14px; border-radius:20px; border:none; background:none; cursor:pointer; font-family:inherit; }
.comm-filter-tab:hover{ color:var(--text-main); }
.comm-filter-tab.active{ font-weight:700; color:var(--bg-color); background:var(--text-main); }
.comm-filter-spacer{ flex:1 1 auto; }
.comm-filter-hint{ font-size: var(--fs-xs); color:var(--text-muted); font-variant-numeric: tabular-nums; }

.comm-thread-row{ display:flex; align-items:center; gap:14px; padding:14px 8px; border-bottom:1px solid var(--border); border-radius:6px; cursor:pointer; }
.comm-thread-row:hover{ background:var(--hover-bg); }
.comm-thread-bar{ width:4px; align-self:stretch; border-radius:2px; flex:0 0 auto; }
.comm-thread-main{ flex:1 1 auto; min-width:0; display:flex; flex-direction:column; gap:4px; }
.comm-thread-title-row{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.comm-thread-title{ font-size: var(--fs-body); font-weight:650; color:var(--text-main); }
.comm-thread-meta{ margin:0; font-size: var(--fs-xs); color:var(--text-muted); font-variant-numeric: tabular-nums; }
.comm-thread-stat{ flex:0 0 auto; text-align:right; }
.comm-thread-stat .n{ display:block; font-size: var(--fs-h3); font-weight:700; color:var(--text-main); font-variant-numeric: tabular-nums; }
.comm-thread-stat .lbl{ font-size: var(--fs-xs); color:var(--text-muted); }
.comm-thread-icon{ flex:0 0 auto; color:var(--text-muted); }

.comm-reply{ display:flex; gap:10px; padding:14px 0; border-top:1px solid var(--border); }
/* Une réponse ciblée (parent_post_id) s'imbrique sous le message visé plutôt
   que de rester plate dans l'ordre chronologique -- léger décalage à droite
   par niveau, cumulatif si le fil s'enfonce. */
.comm-reply-children{ margin-left:24px; }
.comm-reply-body{ background:var(--input-bg); border-radius:10px; padding:10px 12px; flex:1; font-size: var(--fs-body); color:var(--text-main); }
.comm-reply-who{ font-size: var(--fs-xs); font-weight:700; color:var(--text-main); margin-bottom:3px; display:flex; justify-content:space-between; gap:10px; }
.comm-reply-actions{ display:flex; gap:10px; font-weight:600; }
.comm-reply-who .reply-to{ color:var(--text-muted); cursor:pointer; }
.comm-reply-who .reply-to:hover{ color:var(--accent); }
.comm-reply-who .del{ color:var(--text-muted); cursor:pointer; font-weight:600; }
.comm-reply-who .del:hover{ color:var(--danger); }

/* Aperçu du message ciblé par une réponse (parent_post_id) : pas forcément
   le dernier du fil, donc ce rappel identifie sans ambiguïté lequel. */
.comm-reply-parent{ font-size: var(--fs-xs); color:var(--text-muted); background:var(--hover-bg);
    border-radius:6px; padding:5px 9px; margin-bottom:6px; cursor:pointer; overflow:hidden;
    text-overflow:ellipsis; white-space:nowrap; }
.comm-reply-parent:hover{ color:var(--text-main); }
.comm-reply-parent b{ color:var(--text-main); }

.comm-mention{ color:var(--accent); font-weight:700; }

.comm-tag{ display:inline-flex; align-items:center; background:var(--input-bg); color:var(--accent); border-radius:5px; padding:1px 7px; font-size: var(--fs-xs); font-weight:800; }

/* Chip "Replying to @X" au-dessus du composeur, posée par
   communitySetReplyTarget — identifie la cible avant même d'écrire. */
.comm-reply-target{ display:inline-flex; align-items:center; gap:8px; background:var(--hover-bg);
    color:var(--text-main); border-radius:20px; padding:5px 8px 5px 14px; font-size: var(--fs-sm);
    margin:12px 0 -4px; }
.comm-reply-target .x{ cursor:pointer; color:var(--text-muted); font-weight:700; padding:0 5px; }
.comm-reply-target .x:hover{ color:var(--danger); }

/* .sd-textarea impose font-size:var(--fs-h3) (1rem, pensé pour un champ de
   login) -- beaucoup trop gros pour un corps de message ; les deux
   composeurs Community (réponse ET nouveau fil) repassent au corps de texte
   normal de l'interface. */
.comm-composer-font{ font-size: var(--fs-body); line-height:1.5; }

/* Le bouton Reply et le compteur de mots débordaient dans la zone de texte
   (overlay en coin bas-droit) -- retour à une ligne normale SOUS la boîte,
   hors de la zone cliquable/éditable. Hauteur bornée + défilement interne
   gardée : une réponse de 100+ mots (le plancher ci-dessus) grandirait
   sinon sans limite. */
.comm-reply-editor{ min-height:60px; max-height:220px; overflow-y:auto; padding-bottom:14px; }
/* Pied du composeur : même traitement que .fmt-bar en haut (fond légèrement
   teinté + ligne de séparation), mais en miroir en bas -- sans ça, la zone
   éditable et la ligne compteur/bouton partageaient le même fond et se
   confondaient en un seul bloc flou. */
.comm-composer-footer{ display:flex; align-items:center; justify-content:space-between;
    gap:12px; margin:0; padding:8px 12px; background:var(--ind-bg);
    border-top:1px solid var(--border); border-radius:0 0 10px 10px; }

.comm-word-hint{ margin:0; font-size: var(--fs-xs); color:var(--text-muted); font-variant-numeric: tabular-nums; }
.comm-word-hint.under{ color:var(--text-muted); }
.comm-word-hint.over{ color:var(--danger); }

/* Onglet Discussion, partagé Stock/ETF/Crypto */
.comm-discussion-empty{ color:var(--text-muted); font-size: var(--fs-body); }
/* .sd-note n'est dimensionné que sous .sd-page : hors de cette page, les
   messages d'état de Community (« No threads yet », « Loading… », « No
   replies yet ») retombaient sur la taille d'un paragraphe de corps de
   texte, aussi gros que le contenu qu'ils remplacent. */
#community-index .sd-note,
#community-thread-view .sd-note {
    font-size: var(--fs-xs); color: var(--text-muted); line-height: 1.4;
}

@media (max-width: 820px) {
    .comm-body{ flex-direction:column; }
    .comm-rail{ width:100%; flex-direction:row; flex-wrap:wrap; }
    .comm-rail-div, .comm-rail-note{ display:none; }
}

/* ===== Fiche ETF — encart Performance (by window + by calendar year) ===== */
.etf-perf-hd { display: flex; align-items: baseline; justify-content: space-between;
    gap: 12px; flex-wrap: wrap; margin-bottom: 2px; }
.etf-perf-lbl { font-size: var(--fs-eyebrow); letter-spacing: .13em; text-transform: uppercase;
    font-weight: 700; color: var(--text-muted); margin: 16px 0 0; }
/* auto-fit plutôt que 5 colonnes fixes : reste lisible une fois la carte
   Performance dans une colonne plus étroite (disposition 2 colonnes de
   l'onglet Data), sans dépendre d'une @media sur le viewport — qui ne
   détecte jamais une colonne étroite sur un écran par ailleurs large. */
.etf-win-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(92px, 1fr)); margin: 8px 0 2px; }
.etf-win { padding: 6px 14px 10px; display: flex; flex-direction: column; gap: 3px; position: relative; }
.etf-win:first-child { padding-left: 0; }
.etf-win + .etf-win::before { content: ""; position: absolute; left: 0; top: 50%;
    transform: translateY(-50%); width: 1px; height: 28px; background: var(--border); }
.etf-win .w { font-size: var(--fs-xs); color: var(--text-muted); font-weight: 600; }
.etf-win .ret { font-size: var(--fs-display); font-weight: 750; letter-spacing: -.01em; font-variant-numeric: tabular-nums; }
.etf-win .ret.pos { color: var(--success); } .etf-win .ret.neg { color: var(--danger); }
.etf-win .sub { font-size: var(--fs-xs); color: var(--text-muted); font-variant-numeric: tabular-nums; min-height: 1em; }
@media (max-width: 620px) {
    .etf-win-grid { grid-template-columns: repeat(2, 1fr); row-gap: 6px; }
    .etf-win + .etf-win::before { display: none; }
    .etf-win { padding-left: 12px; }
}
/* ===== Fiche ETF — encart "What that would be worth" (lump sum + DCA) ===== */
.etf-ex-row { display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px 10px; }
.etf-ex-lbl { color: var(--text-muted); font-size: var(--fs-sm); }
.etf-ex-arrow { color: var(--text-muted); }
.etf-ex-val { font-size: var(--fs-h3); font-weight: 750; font-variant-numeric: tabular-nums; }
.etf-ex-val.pos { color: var(--success); } .etf-ex-val.neg { color: var(--danger); }
.etf-ex-sub { font-size: var(--fs-xs); color: var(--text-muted); font-variant-numeric: tabular-nums; }
.etf-ex-note { margin: 4px 0 0; font-size: var(--fs-xs); color: var(--text-muted); }

/* ===== Fiche crypto — onglet Data réorganisé ===== */
.sd-beta { font-size: var(--fs-xs); font-weight: 700; color: var(--warning);
    border: 1px solid var(--warning); border-radius: 4px; padding: 1px 5px;
    vertical-align: middle; letter-spacing: .04em; }
/* Section visible seulement au propriétaire/admin (données encore trop
   brutes/non fiabilisées pour un utilisateur normal) -- distinct de .sd-beta
   (qui lui reste visible à tout le monde) par la couleur, même gabarit. */
.sd-admin-only { font-size: var(--fs-xs); font-weight: 700; color: var(--accent);
    border: 1px solid var(--accent); border-radius: 4px; padding: 1px 5px;
    vertical-align: middle; letter-spacing: .04em; }
/* Marqueur de couverture : la série sous-jacente est plus courte que ce que
   le libellé promet (ex. « 5Yr Avg » calculé sur 4 ans). Discret, info au survol. */
.ind-beta { font-family: var(--font-ui); font-size: var(--fs-xs); color: var(--text-muted);
    letter-spacing: .03em; cursor: help; vertical-align: super; line-height: 0; margin-left: 2px; }

/* ===== Insertion de hashtag dans une note (Ctrl/⌘+clic ou bouton +) ===== */
/* Quand un champ de note/log est actif, les indicateurs cliquables se signalent. */
body.tag-insert-armed [data-tag] { cursor: copy; position: relative; }
body.tag-insert-armed [data-tag]:hover { outline: 1px dashed var(--accent); outline-offset: 2px; border-radius: 3px; }
.tag-add { font-family: var(--font-ui); font-size: var(--fs-xs); line-height: 1;
    border: 1px solid var(--border); background: var(--card-bg); color: var(--accent);
    border-radius: 4px; padding: 1px 5px; margin-left: 6px; cursor: pointer; vertical-align: middle; }
.tag-add:hover { border-color: var(--accent); background: var(--accent); color: #0c0d10; }
.tag-insert-flash { animation: tagInsertFlash .5s ease-out; }
@keyframes tagInsertFlash { from { background: color-mix(in srgb, var(--accent) 30%, transparent); } to { background: transparent; } }
.cryd-pstrip { display: flex; flex-wrap: wrap; gap: 16px 30px; align-items: baseline;
    margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); }
.cryd-pstrip > div { display: flex; flex-direction: column; gap: 2px; }
.cryd-pstrip .k { font-size: var(--fs-eyebrow); letter-spacing: .09em; text-transform: uppercase; color: var(--text-muted); }
.cryd-pstrip .v { font-size: var(--fs-body); font-weight: 700; font-variant-numeric: tabular-nums; }
.cryd-pstrip > div:first-child .v { font-size: var(--fs-h2); }
.cryd-pstrip .d { font-size: var(--fs-xs); font-weight: 400; color: var(--text-muted); }
/* minmax(220px, 1fr), pas juste 1fr : avec 1fr seul, les 4 colonnes se
   compriment pour TOUJOURS tenir dans le panneau -- illisible une fois le
   panneau étroit (mode Split). Avec un plancher par colonne, la grille
   déborde proprement et DEVIENT scrollable horizontalement (overflow-x:auto
   ci-dessous, remplace l'ancien overflow:hidden qui empêchait tout scroll --
   overflow-y:hidden conservé pour garder le coin arrondi net sur les
   cellules internes). 220px (pas 140px, trop juste) : chaque ligne .kv a un
   libellé qui peut être long (« Volume / mcap », « Unlock overhang »...),
   suivi d'un petit bouton "i" puis de la valeur -- sous 220px le libellé et
   la valeur n'avaient pas la place de rester chacun sur une ligne avec le
   gap de 10px prévu (.kv), le tout se retrouvait tassé/peu lisible même
   sans déborder techniquement. */
.cryd-statcols { display: grid; grid-template-columns: repeat(4, minmax(220px, 1fr));
    border: 1px solid var(--border-soft, var(--border)); border-radius: 10px;
    overflow-x: auto; overflow-y: hidden; }
.cryd-statcols > div { padding: 12px 14px; border-right: 1px solid var(--border-soft, var(--border));
    border-bottom: 1px solid var(--border-soft, var(--border)); }
.cryd-statcols > div:nth-child(4n) { border-right: 0; }
.cryd-statcols > div:nth-last-child(-n+4) { border-bottom: 0; }
@media (max-width: 720px) {
    .cryd-statcols { grid-template-columns: repeat(2, 1fr); }
    .cryd-statcols > div:nth-child(2n) { border-right: 0; }
    .cryd-statcols > div:nth-last-child(-n+2) { border-bottom: 0; }
}
.cryd-statcols .col-h { font-size: var(--fs-eyebrow); letter-spacing: .1em; text-transform: uppercase;
    font-weight: 700; color: var(--accent); margin-bottom: 8px; }
.cryd-statcols .kv { display: flex; justify-content: space-between; gap: 10px;
    font-size: var(--fs-sm); padding: 3px 0; }
.cryd-statcols .kv .k { color: var(--text-muted); }
.cryd-statcols .kv .v { font-weight: 600; font-variant-numeric: tabular-nums; }
.cryd-statcols .kv .v.pos { color: var(--success); }
.cryd-statcols .kv .v.warn { color: var(--warning); }
.cryd-statcols .kv .v.neg { color: var(--danger); }
.cryd-person { display: flex; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--border-soft, var(--border)); }
.cryd-person:last-of-type { border-bottom: 0; }
.cryd-person .av { width: 38px; height: 38px; border-radius: 50%; background: var(--input-bg);
    border: 1px solid var(--border); display: flex; align-items: center; justify-content: center;
    font-weight: 700; color: var(--text-muted); flex: 0 0 auto; font-size: var(--fs-sm); }
.cryd-person .who { min-width: 0; }
.cryd-person .nm { font-weight: 700; }
.cryd-person .rl { font-size: var(--fs-xs); color: var(--accent); font-weight: 600;
    text-transform: uppercase; letter-spacing: .04em; }
.cryd-person .cv { font-size: var(--fs-sm); color: var(--text-muted); margin-top: 3px; line-height: 1.5; }
.cryd-assess { margin-top: 14px; background: var(--card-2, var(--input-bg));
    border: 1px solid var(--border-soft, var(--border)); border-radius: 10px; padding: 12px 14px; }
.cryd-assess .lbl { font-size: var(--fs-eyebrow); letter-spacing: .1em; text-transform: uppercase;
    font-weight: 700; color: var(--text-muted); margin-bottom: 6px; }

/* =====================================================================
   INTRO CINÉMATIQUE  (#intro)  — le cercle qui s'ouvre + « Welcome on board »
   Palette sombre par défaut ; claire sous body.light-mode.
   ===================================================================== */
#intro{
    position:fixed; inset:0; z-index:100000; overflow:hidden;
    display:grid; place-items:center;
    /* palette sombre */
    --i-bg:#050604;
    --i-ring:#9bb05f;
    --i-ring2:rgba(195,212,147,.6);
    --i-ring-glow:rgba(155,176,95,.4);
    --i-core:#edeee4;
    --i-core-glow:rgba(237,238,228,.7);
    --i-bloom:rgba(155,176,95,.55);
    --i-welcome:#7f8574;
    background:var(--i-bg);
}
body.light-mode #intro{
    /* EXACTEMENT le blanc des encarts du terminal (--card-bg, #fbfbfd), pas un
       blanc à part : l'ancien #f8f7f2 était un blanc CHAUD (crémeux) là où les
       cartes sont sur un blanc FROID -- l'intro ne raccordait donc pas avec
       l'interface qui apparaît juste après. */
    --i-bg:var(--card-bg);
    --i-ring:#5c6c35;
    --i-ring2:rgba(108,125,64,.5);
    --i-ring-glow:rgba(108,125,64,.22);
    --i-core:#23261c;
    --i-core-glow:rgba(35,38,28,.26);
    --i-welcome:#76796a;
    --i-bloom:rgba(108,125,64,.30);
}
#intro[hidden]{ display:none !important; }
#intro.leaving{ animation:intro-out .45s ease-in forwards; }
@keyframes intro-out{ to{ opacity:0; visibility:hidden; } }

.intro-aperture{ position:absolute; inset:0; display:grid; place-items:center; overflow:hidden; }
.intro-bloom{
    position:absolute; width:36%; aspect-ratio:1; border-radius:50%;
    background:radial-gradient(circle, var(--i-bloom), transparent 70%); opacity:0;
}
.intro-ring{
    position:absolute; width:7%; aspect-ratio:1; border-radius:50%;
    border:2.5px solid var(--i-ring); box-shadow:0 0 22px var(--i-ring-glow); opacity:0;
}
.intro-ring.r2{ border-color:var(--i-ring2); box-shadow:none; }
.intro-dot{
    position:absolute; width:8px; aspect-ratio:1; border-radius:50%;
    background:var(--i-core); box-shadow:0 0 26px 6px var(--i-core-glow); opacity:0;
}
.intro-endcard{ position:absolute; inset:0; display:grid; place-items:center; text-align:center; }
.intro-mark{ display:flex; justify-content:center; opacity:1; }
.intro-mark .intro-logo-img{ height:clamp(72px, 12vw, 120px); width:auto; display:none; }
.intro-mark .intro-logo-img--dark{ display:block; }
body.light-mode .intro-mark .intro-logo-img--dark{ display:none; }
body.light-mode .intro-mark .intro-logo-img--light{ display:block; }
.intro-welcome{
    font-family:'Courier New', Courier, monospace; font-size:clamp(.66rem,1.6vw,.85rem);
    letter-spacing:.36em; text-transform:uppercase; color:var(--i-welcome); margin-top:14px; opacity:1;
}

/* --- séquence (ajoutée quand #intro reçoit .running) --- */
#intro.running .intro-dot{ animation:intro-dot .5s ease-out both; }
@keyframes intro-dot{ 0%{opacity:0;transform:scale(.4);} 30%{opacity:1;transform:scale(1);} 100%{opacity:0;transform:scale(.6);} }

#intro.running .intro-bloom{ animation:intro-bloom 1.7s ease-out both; }
@keyframes intro-bloom{ 0%{opacity:0;transform:scale(.2);} 22%{opacity:.95;} 70%{opacity:.5;} 100%{opacity:0;transform:scale(4);} }

#intro.running .intro-ring{ animation:intro-ring 1.7s cubic-bezier(.45,.03,.15,1) both; }
#intro.running .intro-ring.r2{ animation-delay:.16s; }
@keyframes intro-ring{
    0%{opacity:0;transform:scale(.35);}
    8%{opacity:1;}
    88%{opacity:1;transform:scale(30);}   /* ~210% de la largeur du cadre */
    100%{opacity:0;transform:scale(40);}
}

#intro.running .intro-mark{ animation:intro-markin 1s cubic-bezier(.2,.7,.2,1) 1.15s both; }
@keyframes intro-markin{ 0%{opacity:0;transform:scale(.92);filter:blur(6px);} 60%{opacity:1;filter:blur(0);} 100%{opacity:1;transform:scale(1);} }

#intro.running .intro-welcome{ animation:intro-welin .8s ease-out 2s both; }
@keyframes intro-welin{ 0%{opacity:0;letter-spacing:.5em;} 100%{opacity:1;letter-spacing:.36em;} }

/* au repos (avant .running) l'aperture est masquée : on ne voit que l'écran de fin */
#intro:not(.running) .intro-aperture{ opacity:0; }

@media (prefers-reduced-motion:reduce){
    #intro.running .intro-aperture{ opacity:0 !important; }
    #intro.running .intro-mark, #intro.running .intro-welcome{ animation:none !important; opacity:1 !important; }
}

/* =====================================================================
   ACADEMY  —  parcours guidé (Path) / libre (Browse)
   ===================================================================== */
.ac-topbar{ display:flex; align-items:center; justify-content:space-between; gap:16px; flex-wrap:wrap; margin-bottom:16px; }

.ac-search{ position:relative; }
.ac-search input{
    background:var(--input-bg); border:1px solid var(--border); color:var(--text-main);
    border-radius:8px; padding:7px 30px 7px 12px; font-size: var(--fs-body); width:260px; max-width:60vw;
    font-family:inherit;
}
.ac-search input:focus{ outline:none; border-color:var(--accent); }
.ac-search #academy-search-clear{
    position:absolute; right:9px; top:50%; transform:translateY(-50%); cursor:pointer;
    color:var(--text-muted); font-size:var(--fs-h2); line-height:1;
}
.ac-search #academy-search-clear:hover{ color:var(--text-main); }

#academy-search-view{ display:flex; flex-direction:column; gap:12px; }
.ac-search-hit{
    display:flex; flex-direction:column; gap:4px;
    background:var(--card-bg); border:1px solid var(--border); border-radius:12px;
    padding:14px 18px; cursor:pointer; transition:border-color .15s;
}
.ac-search-hit:hover{ border-color:var(--accent); }
.ac-search-hit h4{ margin:0; font-size: var(--fs-h3); color:var(--text-main); }
.ac-search-hit .ac-search-hit-meta{ font-size: var(--fs-xs); text-transform:uppercase; letter-spacing:0.08em; color:var(--accent); font-weight:700; }
.ac-search-hit p{ margin:0; font-size: var(--fs-body); color:var(--text-muted); line-height:1.4; }
.ac-search-hit mark{ background:var(--accent); color:#fff; border-radius:3px; padding:0 2px; }

#academy-continue{ margin-bottom:18px; }
.ac-continue{
    display:flex; align-items:center; justify-content:space-between; gap:18px; flex-wrap:wrap;
    background:rgba(138, 154, 91, .10); border:1px solid var(--border); border-left:3px solid var(--accent);
    border-radius:14px; padding:18px 22px;
    width:50%; min-width:320px;
}
@media (max-width: 720px) {
    .ac-continue{ width:100%; min-width:0; }
}
.ac-continue h3{ margin:4px 0 4px; font-size: var(--fs-display); color:var(--text-main); }
.ac-continue .ac-tag{ font-size: var(--fs-xs); font-weight:700; letter-spacing:0.16em; text-transform:uppercase; color:var(--accent); }
.ac-continue .ac-sub{ font-size: var(--fs-body); color:var(--text-muted); }

#academy-spine{ margin-bottom:20px; }
.ac-spine-svg{ display:block; width:100%; max-width:480px; margin:0 auto; height:auto; overflow:visible; }
.ac-spine-svg .ac-p-faint{ fill:none; stroke:var(--border); stroke-width:10; stroke-linecap:round; stroke-linejoin:round; }
.ac-spine-svg .ac-p-done{ fill:none; stroke:var(--accent); stroke-width:10; stroke-linecap:round; stroke-linejoin:round; }
.ac-node.locked{ opacity:0.55; }
.ac-spine-svg .ac-n-shadow{ fill:rgba(0,0,0,.22); }
.ac-spine-svg .ac-n-done{ fill:var(--fast-grower); }
.ac-spine-svg .ac-n-here{ fill:var(--accent); }
.ac-spine-svg .ac-n-active{ fill:var(--card-bg); stroke:var(--accent); stroke-width:4; }
.ac-spine-svg .ac-n-lock{ fill:var(--card-bg); stroke:var(--border); stroke-width:4; }
.ac-spine-svg .ac-n-pulse{
    fill:none; stroke:var(--accent); stroke-width:3; opacity:.5;
    transform-origin:center; transform-box:fill-box; animation:acPulse 1.8s ease-out infinite;
}
@keyframes acPulse{ 0%{ transform:scale(.82); opacity:.55; } 100%{ transform:scale(1.2); opacity:0; } }
.ac-spine-svg .ac-check{ fill:none; stroke:#fff; stroke-width:3; stroke-linecap:round; stroke-linejoin:round; }
.ac-spine-svg .ac-lock-body{ fill:var(--text-muted); }
.ac-spine-svg .ac-lock-shackle{ fill:none; stroke:var(--text-muted); stroke-width:2; stroke-linecap:round; }
.ac-spine-svg .ac-n-num{ font-family:var(--font-ui); font-size:var(--fs-body); font-weight:800; fill:var(--accent); }
.ac-spine-svg .ac-n-num.on-fill{ fill:#fff; }
.ac-spine-svg .ac-n-tag{ font-family:var(--font-ui); font-size:var(--fs-xs); font-weight:700; letter-spacing:.04em; text-transform:uppercase; fill:var(--text-muted); }
.ac-spine-svg .ac-n-tag.here{ fill:var(--accent); }
.ac-spine-svg .ac-n-lbl{ font-family:var(--font-ui); font-size:var(--fs-sm); font-weight:600; fill:var(--text-main); }

.ac-tracks{ display:flex; flex-direction:column; gap:12px; }
.ac-track{
    display:flex; align-items:center; justify-content:space-between; gap:18px;
    background:var(--card-bg); border:1px solid var(--border); border-radius:12px;
    padding:16px 20px; cursor:pointer; transition:border-color .15s;
}
.ac-track:not(.locked):hover{ border-color:var(--accent); }
.ac-track.locked{ opacity:0.55; cursor:default; }
.ac-track-main h3{ margin:0 0 4px; font-size: var(--fs-h2); color:var(--text-main); }
.ac-track-main p{ margin:0; font-size: var(--fs-body); color:var(--text-muted); line-height:1.4; }
.ac-track-side{ display:flex; flex-direction:column; align-items:flex-end; gap:6px; flex:0 0 auto; }
.ac-lock{ font-size: var(--fs-body); }

.ac-secbar{
    height:7px; width:150px; border-radius:99px; background:var(--border);
    overflow:hidden; display:block;
}
/* Remplissage d'une seule couleur : le dégradé accent -> fast-grower faisait
   changer la barre de teinte selon l'avancement, deux sections au même stade
   n'ayant pas la même couleur au même endroit. */
.ac-secbar i{
    display:block; height:100%; border-radius:99px; background:var(--accent);
}
.ac-count{ font-size: var(--fs-sm); color:var(--text-muted); font-variant-numeric:tabular-nums; }
/* Pas de display:flex ici : cet élément est la barre elle-même, pas une
   rangée qui en contiendrait une (voir openSection). */
#section-view-progress{ width:100%; max-width:260px; }

/* Sous-catégorie : en-tête inséré avant le premier module de chaque groupe,
   dans une section qui en regroupe plusieurs (voir openSection). Même
   convention que .ov-tile-lab (libellé d'encart = fs-eyebrow/MAJUSCULES). */
.ac-subcat{ font-family: var(--font-ui); font-size: var(--fs-eyebrow); font-weight: 700;
    letter-spacing: 0.6px; text-transform: uppercase; color: var(--text-muted);
    margin: 22px 0 8px; }
.ac-subcat:first-child{ margin-top: 0; }

/* liste des leçons dans une section */
.ac-lesson-row{
    display:flex; align-items:center; gap:16px;
    background:var(--card-bg); border:1px solid var(--border); border-radius:12px;
    padding:14px 18px; cursor:pointer; transition:border-color .15s;
}
.ac-lesson-row:not(.locked):hover{ border-color:var(--accent); }
.ac-lesson-row.locked{ opacity:0.5; cursor:default; }
.ac-lesson-row.done{ border-left:3px solid var(--fast-grower); }
.ac-lesson-row.reading{ border-left:3px solid var(--accent); }
.ac-lr-num{
    flex:0 0 auto; width:28px; height:28px; border-radius:50%; display:grid; place-items:center;
    font-family:var(--font-ui); font-variant-numeric:tabular-nums;
    font-size:var(--fs-eyebrow); font-weight:700; color:var(--text-muted); border:1px solid var(--border);
}
.ac-lesson-row.done .ac-lr-num{ background:var(--fast-grower); color:#fff; border-color:transparent; }
.ac-lr-body{ flex:1 1 auto; min-width:0; }
.ac-lr-body h4{ margin:0 0 3px; font-size:var(--fs-h3); color:var(--text-main); display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.ac-lr-body p{ margin:0; font-size:var(--fs-sm); color:var(--text-muted); line-height:1.4; }
.ac-lr-go{ flex:0 0 auto; color:var(--accent); font-size:var(--fs-sm); font-weight:700; }
.ac-badge{ font-size:var(--fs-xs); font-weight:700; letter-spacing:0.4px; text-transform:uppercase; padding:2px 7px; border-radius:999px; border:1px solid currentColor; }
.ac-badge.done{ color:var(--fast-grower); }
.ac-badge.reading{ color:var(--accent); }
.ac-badge.lock{ color:var(--text-muted); }

/* page leçon */
#lesson-progress{ position:sticky; top:0; z-index:40; height:4px; background:var(--border); border-radius:99px; }
#lesson-progress i{ display:block; height:100%; width:0; background:var(--accent); border-radius:99px; transition:width .1s linear; }
/* 190px -> 150px : le sommaire ne sert plus que sur deux leçons longues, et
   il y prenait trop de largeur au texte. */
.ac-lesson-grid{ display:grid; grid-template-columns:minmax(0,1fr) 150px; gap:24px; align-items:start; }
/* Sans sommaire, la colonne de droite ne reste pas réservée. */
.ac-lesson-grid.ac-no-outline{ grid-template-columns:minmax(0,1fr); }
/* Cadre du texte : PAS de bordure (elle se confondait avec les filets des
   encarts). On garde le fond + l'ombre douce de .sd-card pour délimiter,
   et une marge intérieure large pour que le contenu ne colle à rien. */
.ac-lesson-card{ border:none; padding:44px 60px; }
.ac-lesson-meta{ font-family:var(--font-ui); font-size:var(--fs-sm); color:var(--text-muted); margin:4px 0 22px; }
.ac-lesson-foot{ display:flex; gap:12px; flex-wrap:wrap; margin-top:38px; padding-top:26px; border-top:1px solid var(--border); }
.ac-outline{ position:sticky; top:24px; font-family:var(--font-ui); font-size:var(--fs-sm); }
.ac-outline-t{ font-size:var(--fs-eyebrow); font-weight:700; letter-spacing:0.12em; text-transform:uppercase; color:var(--text-muted); margin-bottom:8px; }
.ac-outline a{ display:block; color:var(--text-muted); text-decoration:none; padding:4px 0 4px 8px; border-left:2px solid transparent; line-height:1.35; }
.ac-outline a .l-num,
.ac-outline a .ac-out-n{ color:var(--accent); font-weight:700; margin-right:.5em; font-variant-numeric:tabular-nums; }
.ac-outline a.on{ color:var(--accent); border-left-color:var(--accent); font-weight:600; }
@media (max-width:860px){
    .ac-lesson-grid{ grid-template-columns:1fr; }
    .ac-outline{ position:static; order:-1; border-bottom:1px solid var(--border); padding-bottom:12px; margin-bottom:6px; }
}

/* --- Academy : quiz de fin de leçon --- */
.ac-badge.quiz { color: var(--stalwart); }
.ac-quiz {
    border: 1px solid var(--border); border-radius: 12px; padding: 18px 20px;
    background: var(--card-bg); flex: 1 1 100%;
}
.ac-quiz-h { font-weight: 700; font-size: var(--fs-h3); color: var(--text-main); margin-bottom: 12px; }
.ac-quiz-h span { display: block; font-weight: 500; font-size: var(--fs-sm); color: var(--text-muted); margin-top: 2px; }
.ac-quiz ol { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 16px; }
.ac-quiz li { padding-left: 4px; }
.ac-quiz li.ac-q-ok { list-style: '✓ '; }
.ac-quiz li.ac-q-bad { list-style: '✗ '; }
.ac-quiz li.ac-q-ok::marker { color: var(--fast-grower); font-weight: 700; }
.ac-quiz li.ac-q-bad::marker { color: var(--danger); font-weight: 700; }
.ac-quiz .q { margin: 0 0 8px; font-weight: 600; font-size: var(--fs-body); color: var(--text-main); }
.ac-opt {
    display: flex; align-items: flex-start; gap: 9px; padding: 7px 10px; margin-bottom: 5px;
    border: 1px solid var(--border); border-radius: 8px; cursor: pointer; font-size: var(--fs-body);
    color: var(--text-main); line-height: 1.4;
}
.ac-opt:hover { border-color: var(--accent); }
.ac-opt input { margin-top: 2px; flex: 0 0 auto; }
.ac-q-ok .ac-opt input:checked + span { color: var(--fast-grower); font-weight: 600; }
.ac-q-bad .ac-opt input:checked + span { color: var(--danger); font-weight: 600; }
.ac-quiz-foot { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-top: 16px; }
.ac-quiz-foot #ac-quiz-res { font-size: var(--fs-body); font-weight: 600; }

/* ============================ ALERTES ============================ */
/* Panneau de la cloche : une ligne = une notification (un TYPE, pas une alerte). */
.al-notif {
    display: flex; align-items: flex-start; gap: 10px; padding: 10px 11px;
    border-radius: 9px; cursor: pointer; border: 1px solid transparent;
}
.al-notif:hover { background: var(--input-bg); border-color: var(--border); }
.al-notif.is-read { opacity: 0.62; }
.al-nic {
    flex: 0 0 auto; width: 30px; height: 30px; border-radius: 8px;
    display: grid; place-items: center; font-family: var(--font-ui); font-weight: 700;
    font-size: var(--fs-xs); letter-spacing: -0.02em;
}
.al-nic.metric  { background: rgba(138,154,91,0.16); color: var(--accent); }
.al-nic.company { background: rgba(239,68,68,0.14);  color: var(--danger); }
.al-notif-t { font-size: var(--fs-body); font-weight: 600; color: var(--text-main); line-height: 1.35; }
.al-notif-s { font-size: var(--fs-sm); color: var(--text-muted); margin-top: 2px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.al-notif-dot { flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%;
    background: var(--accent); margin-top: 6px; }

/* Brique commune : une ligne d'alerte avec sa piste baseline -> seuil -> maintenant. */
.al-row { padding: 12px 0; border-bottom: 1px solid var(--border); }
.al-row:last-child { border-bottom: 0; }
.al-row-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.al-row-tk { font-family: var(--font-ui); font-weight: 700; color: var(--accent); font-size: var(--fs-body); }
.al-row-metric { font-weight: 600; color: var(--text-main); font-size: var(--fs-body); }
.al-row-cur { font-family: var(--font-ui); font-weight: 700; color: var(--text-main); font-size: var(--fs-body); font-variant-numeric: tabular-nums; }
.al-chip {
    font-family: var(--font-ui); font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.05em;
    text-transform: uppercase; padding: 1px 7px; border-radius: 999px; border: 1px solid currentColor;
}
.al-row-rule { font-size: var(--fs-sm); color: var(--text-muted); margin: 5px 0 7px; }
.al-row-why { font-size: var(--fs-sm); color: var(--text-muted); line-height: 1.4; margin: 0 0 7px; }
.al-row-note { color: var(--accent); cursor: pointer; text-decoration: underline; }
.al-row-act { display: inline-flex; gap: 10px; margin-left: auto; }
.al-row-act a { font-size: var(--fs-sm); font-weight: 700; color: var(--accent); cursor: pointer; }
.al-row-delta { font-family: var(--font-ui); font-size: var(--fs-sm); color: var(--text-muted); margin-top: 5px; font-variant-numeric: tabular-nums; }
.al-track { position: relative; height: 7px; border-radius: 999px; background: var(--input-bg); overflow: hidden; }
.al-track-fill { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 999px; }
.al-track-mark { position: absolute; top: -3px; width: 2px; height: 13px; background: var(--text-main); opacity: 0.8; }

/* Onglet « Alerts » : le builder une ligne. */
.al-builder {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0;
    padding-bottom: 14px; border-bottom: 1px solid var(--border); font-size: var(--fs-body);
    color: var(--text-main);
}
.al-builder select, .al-builder input {
    font-family: inherit; font-size: var(--fs-body); background: var(--input-bg);
    border: 1px solid var(--border); border-radius: 7px; padding: 5px 8px; color: var(--text-main);
}
.al-tab-sum {
    font-family: var(--font-ui); font-size: var(--fs-sm); color: var(--text-muted);
    text-transform: uppercase; letter-spacing: 0.04em; margin: 14px 0 4px;
}

/* Alertes pré-proposées sous le builder : grille de 4 tuiles (option B
   retenue le 2026-10-18), une par style de ligne — point de couleur, cible
   et bouton dans le ton de la catégorie (_alStyleColorVar côté JS). */
.al-sug { margin-top: 14px; }
.al-sug-head {
    display: flex; align-items: baseline; gap: 10px; font-family: var(--font-ui);
    font-size: var(--fs-eyebrow); color: var(--text-muted); text-transform: uppercase;
    letter-spacing: 0.04em; margin-bottom: 10px;
}
.al-sug-head a { margin-left: auto; color: var(--accent); cursor: pointer; font-weight: 700;
    text-transform: none; letter-spacing: 0; }
/* Largeur fixe par tuile (pas 1fr) : la grille ne s'étire pas sur toute la
   largeur de la page, elle ne prend que la place dont ses tuiles ont besoin. */
.al-sug-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 215px));
    justify-content: start; gap: 8px; }
@media (max-width: 560px) { .al-sug-grid { grid-template-columns: 1fr; } }
.al-sug-tile {
    border: 1px solid var(--border); border-radius: 10px; padding: 9px 10px 10px;
    display: flex; flex-direction: column; gap: 5px;
}
.al-sug-top { display: flex; align-items: center; gap: 6px; }
.al-sug-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--cat); flex: 0 0 auto; }
/* Libellé d'encart = même convention que .ov-tile-lab (fs-eyebrow, MAJUSCULES,
   couleur d'accent) -- ici la couleur de catégorie de la tuile plutôt que
   l'accent générique, pour rester cohérent avec le point/bouton/cible. */
.al-sug-metric { font-family: var(--font-ui); font-size: var(--fs-eyebrow); font-weight: 700;
    letter-spacing: 0.6px; text-transform: uppercase; color: var(--cat); }
/* Même police que le texte "why" en dessous (var(--font-ui), pas de --font-mono
   séparé) -- seul font-variant-numeric aligne les chiffres, comme .al-row-cur
   et .mw-f-val ; un vrai changement de police entre la valeur et son
   explication (qui répète ce même chiffre) se voyait au premier coup d'œil. */
.al-sug-range {
    display: flex; align-items: baseline; gap: 6px;
    font-variant-numeric: tabular-nums; font-size: var(--fs-h3); font-weight: 700; color: var(--text-main);
}
.al-sug-arrow { color: var(--text-muted); font-weight: 400; font-size: var(--fs-sm); }
.al-sug-target { color: var(--cat); }
.al-sug-why { font-size: var(--fs-sm); color: var(--text-muted); line-height: 1.35; margin: 0; flex: 1; }
.al-sug-add {
    align-self: flex-start; font-family: var(--font-ui); font-size: var(--fs-sm); font-weight: 700;
    color: #fff; background: var(--cat); border: none; border-radius: 7px; padding: 4px 10px; cursor: pointer;
}
.al-sug-add:hover { filter: brightness(1.12); }
.al-sug-set {
    align-self: flex-start; font-family: var(--font-ui); font-size: var(--fs-eyebrow); font-weight: 700;
    letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-muted); padding: 4px 0;
}

/* Fenêtre « Alerts from these notes » : une ligne par #indicateur. */
.al-brow {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    padding: 9px 0; border-bottom: 1px solid var(--border); font-size: var(--fs-body);
}
.al-brow:last-child { border-bottom: 0; }
.al-brow select, .al-brow input {
    font-family: inherit; font-size: var(--fs-body); background: var(--input-bg);
    border: 1px solid var(--border); border-radius: 7px; padding: 4px 7px; color: var(--text-main);
}
.al-brow-chk { display: inline-flex; align-items: center; }
.al-brow-tag { font-weight: 700; color: var(--text-main); }

/* ============================ MACRO WORKBENCH ============================ */
.mw-chart-card { background: var(--card-bg); border: 1px solid var(--border); border-radius: 16px;
    padding: 14px 16px 10px; margin-bottom: 16px; }
.mw-controls { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.mw-chart-card .tv-chart-container { height: 320px; margin: 0; border: none; padding: 0; background: transparent; }
.mw-empty { text-align: center; color: var(--text-muted); font-size: var(--fs-body); padding: 60px 20px; }
.mw-legend { display: flex; gap: 12px 18px; flex-wrap: wrap; align-items: center; margin-top: 10px;
    font-family: var(--font-ui); font-size: var(--fs-xs); color: var(--text-main); }
.mw-lg { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; padding: 2px 4px; border-radius: 6px; }
.mw-lg:hover { background: var(--input-bg); }
.mw-lg.focus { font-weight: 700; }
.mw-lg b { width: 16px; height: 3px; border-radius: 2px; display: inline-block; }
.mw-lg a { color: var(--text-muted); font-weight: 700; padding: 0 3px; }
.mw-lg a:hover { color: var(--danger); }
.mw-corr { color: var(--accent); }

.mw-focus { display: grid; grid-template-columns: 1.05fr 1fr 1fr; gap: 0;
    border: 1px solid var(--border); border-radius: 14px; overflow: hidden;
    background: var(--card-bg); margin-bottom: 18px; }
.mw-focus .mw-f-col { padding: 14px 16px; border-right: 1px solid var(--border); }
.mw-focus .mw-f-col:last-child { border-right: 0; }
.mw-f-ttl { font-family: var(--font-ui); font-size: var(--fs-xs); letter-spacing: 0.13em; text-transform: uppercase;
    color: var(--text-muted); margin-bottom: 8px; }
.mw-f-val { font-size: var(--fs-display); font-weight: 800; color: var(--text-main); font-variant-numeric: tabular-nums; line-height: 1; }
.mw-gauge { position: relative; height: 15px; border-radius: 5px; display: flex; gap: 1px; margin: 14px 0 5px; }
.mw-gauge i { display: block; }
.mw-gauge i:first-child { border-radius: 5px 0 0 5px; }
.mw-gauge i:last-of-type { border-radius: 0 5px 5px 0; }
.mw-gauge .pin { position: absolute; top: -5px; bottom: -5px; width: 3px; background: var(--text-main);
    border-radius: 2px; box-shadow: 0 0 0 1.5px var(--card-bg); left: 50%; transform: translateX(-50%); }
/* tick médian : le « normal » de la fenêtre, discret, sous le curseur */
.mw-gauge .tick { position: absolute; top: 1px; bottom: 1px; width: 2px; background: var(--text-main);
    opacity: 0.3; transform: translateX(-50%); }
.mw-f-pctile { font-size: var(--fs-body); color: var(--text-main); }
.mw-f-verdict { font-family: var(--font-ui); font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.04em; margin-top: 6px; }
.mw-f-default { margin-top: 12px; font-family: var(--font-ui); font-size: var(--fs-xs); color: var(--accent);
    border: 1px solid var(--accent); background: transparent; border-radius: 7px; padding: 4px 9px; cursor: pointer; }
.mw-f-default.on { background: var(--accent); color: #fff; }
.mw-f-howto { font-size: var(--fs-body); line-height: 1.55; color: var(--text-main); }
.mw-f-riw { display: flex; flex-direction: column; gap: 8px; }
.mw-riw-row { display: flex; align-items: center; gap: 8px; }
.mw-riw-row a { font-size: var(--fs-body); color: var(--accent); cursor: pointer; }
.mw-i { width: 16px; height: 16px; flex: 0 0 auto; border-radius: 50%; border: 1px solid var(--accent);
    color: var(--accent); font-family: var(--font-ui); font-size: var(--fs-xs); display: inline-flex;
    align-items: center; justify-content: center; cursor: pointer; text-transform: none; }
/* Bouton « ouvre la leçon » — même traitement que les autres accès leçon
   (accent plein), distinct du bouton contour « période par défaut » au-dessus. */
.mw-f-learn { display: inline-block; margin-top: 10px; font-family: var(--font-ui);
    font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.02em;
    background: var(--accent); color: #fff; border: 1px solid var(--accent);
    border-radius: 7px; padding: 5px 11px; cursor: pointer; }
.mw-f-learn:hover { filter: brightness(1.05); }

.macro-pop { position: absolute; z-index: 4000; max-width: 340px; background: var(--card-bg);
    border: 1px solid var(--border); border-radius: 10px; box-shadow: var(--hover-shadow);
    padding: 12px 14px; font-size: var(--fs-body); line-height: 1.5; color: var(--text-main); }
.macro-info-body h4 { margin: 16px 0 5px; font-size: var(--fs-body); text-transform: uppercase;
    letter-spacing: 0.05em; color: var(--accent); }
.macro-info-body h4:first-child { margin-top: 4px; }
.macro-info-body p { font-size: var(--fs-body); line-height: 1.6; color: var(--text-main); margin: 0; }

.d-card.mw-on { border-color: var(--accent); }
.d-card .mw-cardacts { display: flex; gap: 6px; margin-top: 9px; border-top: 1px solid var(--border); padding-top: 8px; }
.d-card .mw-cardacts button { flex: 1; font-family: var(--font-ui); font-size: var(--fs-xs); letter-spacing: 0.02em;
    border: 1px solid var(--border); background: var(--input-bg); border-radius: 6px; padding: 5px 3px;
    color: var(--text-muted); cursor: pointer; }
.d-card .mw-cardacts button.pri { background: rgba(138,154,91,0.12); border-color: var(--accent); color: var(--accent); }
.d-card .mw-cardacts button.on { background: var(--accent); border-color: var(--accent); color: #fff; }

@media (max-width: 860px) {
    .mw-focus { grid-template-columns: 1fr; }
    .mw-focus .mw-f-col { border-right: 0; border-bottom: 1px solid var(--border); }
    .mw-focus .mw-f-col:last-child { border-bottom: 0; }
}

/* Chart intégré à une leçon Academy (piste macro) */
.ac-macro-chart { border: 1px solid var(--border); border-radius: 12px; background: var(--card-bg);
    padding: 10px; }
.ac-macro-chart canvas { display: block; }

/* Macro workbench : recherche « + Add series » + tag de série dans la légende */
.mw-add-wrap { position: relative; }
#mw-add-in { background: var(--card-bg); color: var(--text-main); border: 1px solid var(--border);
    border-radius: 8px; padding: 6px 10px; font-size: var(--fs-body); font-weight: 600; width: 190px; outline: none; }
#mw-add-in:focus { border-color: var(--accent); }
.mw-add-res { position: absolute; top: calc(100% + 4px); right: 0; width: 300px; max-height: 300px;
    overflow-y: auto; background: var(--card-bg); border: 1px solid var(--border); border-radius: 10px;
    box-shadow: var(--hover-shadow); z-index: 1200; }
.mw-add-row { display: flex; justify-content: space-between; gap: 10px; align-items: baseline;
    padding: 8px 12px; cursor: pointer; border-bottom: 1px solid var(--border); font-size: var(--fs-body); }
.mw-add-row:last-child { border-bottom: 0; }
.mw-add-row:hover { background: var(--input-bg); }
.mw-add-sub { font-family: var(--font-ui); font-size: var(--fs-xs); color: var(--text-muted); white-space: nowrap; }
.mw-lg-tag { font-family: var(--font-ui); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.06em;
    color: var(--text-muted); border: 1px solid var(--border); border-radius: 999px; padding: 0 5px; }
.mw-lg.focus .mw-lg-tag { color: var(--accent); border-color: var(--accent); }

/* ============================ OVERVIEW (Cockpit / Briefing) ============================ */

/* Typo : MÊME vocabulaire que la fiche action (.sd-page) — sans-serif +
   font-variant-numeric, aucun monospace pour les données. */
.ov-r { display: flex; justify-content: space-between; align-items: baseline; gap: 10px;
    padding: 6px 0; border-bottom: 1px solid var(--border);
    font-family: var(--font-ui); font-size: var(--fs-body); }
.ov-r:last-child { border-bottom: 0; }
.ov-r[onclick] { cursor: pointer; }
.ov-r[onclick]:hover { background: var(--input-bg); }
.ov-mt { font-family: var(--font-ui); font-size: var(--fs-xs); color: var(--text-muted);
    font-variant-numeric: tabular-nums; white-space: nowrap; }
.ov-dim { color: var(--text-muted); font-size: var(--fs-sm); }
.ov-hd { font-size: var(--fs-body); color: var(--text-main); line-height: 1.35; }
.ov-big { font-family: var(--font-ui); font-size: var(--fs-display); font-weight: 700; line-height: 1;
    font-variant-numeric: tabular-nums; margin: 2px 0; }
.ov-kpi { display: flex; gap: 16px; flex-wrap: wrap; margin: 8px 0 6px; }
.ov-kpi > div { font-size: var(--fs-eyebrow); color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.ov-kpi b { display: block; font-family: var(--font-ui); font-size: var(--fs-body); color: var(--text-main);
    font-weight: 700; font-variant-numeric: tabular-nums; text-transform: none; letter-spacing: 0; }
.ov-empty { color: var(--text-muted); font-size: var(--fs-sm); padding: 14px 4px; margin: 0; }
.ov-cap { font-size: var(--fs-xs); color: var(--text-muted); margin: 8px 2px 0; }
.ov-sep { height: 1px; background: var(--border); margin: 6px 0; }
/* sélecteur d'univers (Greatest movers) — visible aussi hors mode édition */
.ov-seg { display: flex; gap: 4px; margin-bottom: 8px; flex-wrap: wrap; }
.ov-seg-b { font-family: var(--font-ui); font-size: var(--fs-xs); padding: 3px 9px; border-radius: 6px;
    border: 1px solid var(--border); background: var(--card-bg); color: var(--text-muted); cursor: pointer; }
.ov-seg-b.on { background: var(--accent); color: #fff; border-color: var(--accent); }
.ov-pill { display: inline-block; font-family: var(--font-ui); font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.05em;
    text-transform: uppercase; padding: 1px 6px; border-radius: 999px; }
.ov-pill.hit { background: rgba(239,68,68,0.14); color: var(--danger); }
.ov-pill.near { background: rgba(245,158,11,0.16); color: var(--warning); }
.ov-r .up, .ov-fr .up { color: var(--fast-grower); font-weight: 600; font-variant-numeric: tabular-nums; }
.ov-r .down, .ov-fr .down { color: var(--danger); font-weight: 600; font-variant-numeric: tabular-nums; }

/* Encart Portfolio (Home) : colonne chiffres à gauche, camembert à droite. */
.ov-pf { display: flex; align-items: center; gap: 18px; }
.ov-pf-l { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 12px; }
.ov-pf-day { font-family: var(--font-ui); font-size: var(--fs-xs); color: var(--text-muted); }
.ov-pf-pl { font-family: var(--font-ui); font-size: var(--fs-body); display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
.ov-pf-pl > span:first-child { color: var(--text-muted); }
.ov-pf-pl .up { color: var(--fast-grower); font-weight: 700; font-variant-numeric: tabular-nums; }
.ov-pf-pl .down { color: var(--danger); font-weight: 700; font-variant-numeric: tabular-nums; }
.ov-pf-donut { flex: 0 0 auto; width: 88px; height: 88px; }
.ov-pf-donut canvas { width: 88px; height: 88px; }
.ov-pf-leg { flex: 0 0 auto; display: flex; flex-direction: column; gap: 4px; }
.ov-pf-leg span { display: flex; align-items: center; gap: 6px; white-space: nowrap;
    font-size: var(--fs-xs); color: var(--text-muted); }
.ov-pf-leg i { width: 8px; height: 8px; border-radius: 2px; flex: 0 0 auto; }
.ov-pf-leg b { font-weight: 700; color: var(--text-main); font-variant-numeric: tabular-nums; }
@media (max-width: 560px) { .ov-pf { flex-wrap: wrap; }
    .ov-pf-l { flex-basis: 100%; } }

/* Bento : grille 12 colonnes, tuiles ¼…plein, hauteur = contenu. Édition :
   poignée ⠿ pour déplacer, bord droit pour redimensionner (accroche aux crans). */
.ov-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 14px; flex-wrap: wrap; margin-bottom: 16px; }
.ov-top .page-title { margin: 0; }
.ov-edit-btn { font-size: var(--fs-sm); padding: 5px 12px; }
/* Bento LIBRE : chaque tuile est posée en coordonnées explicites
   (grid-column: x / span w ; grid-row: y / span h). Rangées de hauteur fixe
   (--ov-row) : on peut laisser autant de vide qu'on veut, le seul interdit
   est le chevauchement (géré en JS, retour visuel .ov-bad). */
.ov-bento { display: grid; grid-template-columns: repeat(var(--ov-cols, 24), 1fr);
    grid-auto-rows: var(--ov-row, 23px); gap: var(--ov-gap, 12px); align-items: stretch; }
.ov-bento > .ov-tile { grid-column: span 12; }   /* défaut si le style inline manque */
/* Fiche ETF (#etfd-cockpit) : encarts en flux normal (.sd-card), pas le
   bento à hauteur de tuile fixe ci-dessus (audit "gros vide sous Key facts /
   Country weights / Governance repliée" — un contenu plus court qu'un
   voisin de rangée ne doit plus laisser un blanc jusqu'à une hauteur de
   tuile imposée). Même rythme vertical que .sd-pane (fiches action/crypto,
   gap:30px). */
#etfd-cockpit { display: flex; flex-direction: column; gap: 30px; }
/* .etfd-2col (Key facts / Investment simulator, la grille qui nous occupe
   ici) N'EST PAS redéclarée ici : un doublon exact de la règle ligne ~2144
   vivait à cet endroit, et -- même spécificité, mais plus tard dans la
   feuille -- il regagnait la main après le @container qui replie cette
   grille à 1 colonne en Split (voir plus haut), ce qui réécrasait
   silencieusement le fix et faisait revenir Key facts/Simulation côte à
   côte, pressés, dans un panneau étroit. Supprimé plutôt que dupliqué une
   fois de plus : la seule déclaration qui compte est celle d'en haut. */
.ov-tile { position: relative; border: 1px solid var(--border); border-radius: 12px;
    background: var(--card-bg); padding: 12px 14px; min-width: 0; display: flex;
    flex-direction: column; overflow: hidden; }
.ov-bento.is-edit .ov-tile { border-style: dashed; }
.ov-tile-body { flex: 1 1 auto; overflow: auto; min-height: 0; }
.ov-tile-drag { opacity: 0.75; z-index: 5; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.28); }
.ov-tile.ov-bad { outline: 2px solid var(--danger); outline-offset: -2px; }
.ov-tile-h { display: flex; align-items: center; gap: 7px; margin-bottom: 8px; flex: 0 0 auto; }
/* libellé d'encart = .sd-subhead de la fiche action */
.ov-tile-lab { font-family: var(--font-ui); font-size: var(--fs-eyebrow); font-weight: 700;
    letter-spacing: 0.6px; text-transform: uppercase; color: var(--accent); }
.ov-tile-h-edit { flex-wrap: wrap; }
.ov-grip { font-size: var(--fs-h3); color: var(--text-muted); cursor: grab; touch-action: none; padding: 0 2px; }
.ov-grip:active { cursor: grabbing; }
.ov-pick { font-family: var(--font-ui); font-size: var(--fs-sm); font-weight: 700; background: var(--input-bg);
    border: 1px solid var(--border); border-radius: 7px; padding: 4px 8px; color: var(--text-main); max-width: 55%; }
.ov-sz { font-family: var(--font-ui); font-size: var(--fs-xs); background: var(--input-bg); border: 1px solid var(--border);
    border-radius: 6px; padding: 3px 7px; color: var(--accent); cursor: pointer; }
.ov-rm { margin-left: auto; font-family: var(--font-ui); font-size: var(--fs-sm); background: transparent; border: 0;
    color: var(--danger); cursor: pointer; }
.ov-rz { position: absolute; touch-action: none; display: flex; align-items: center;
    justify-content: center; z-index: 3; }
.ov-rz::before { content: ""; border-radius: 3px; background: var(--accent); opacity: 0.55; }
.ov-rz-w { top: 10px; bottom: 10px; right: -5px; width: 14px; cursor: ew-resize; }
.ov-rz-w::before { width: 4px; height: 34px; max-height: 60%; }
.ov-rz-h { left: 10px; right: 10px; bottom: -5px; height: 14px; cursor: ns-resize; }
.ov-rz-h::before { height: 4px; width: 34px; max-width: 40%; }
.ov-rz:active::before { opacity: 1; }
.ov-addbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    margin-top: 12px; padding: 10px 12px; border: 1px dashed var(--border);
    border-radius: 10px; background: var(--card-bg); }
.ov-addbar-lab { font-family: var(--font-ui); font-size: var(--fs-eyebrow); font-weight: 700; letter-spacing: 0.6px;
    text-transform: uppercase; color: var(--text-muted); }
.ov-more-row { text-align: center; border-top: 1px solid var(--border); margin-top: 6px; padding-top: 5px; }
.ov-more { font-family: var(--font-ui); font-size: var(--fs-xs); background: transparent; border: 0; color: var(--accent);
    cursor: pointer; letter-spacing: 0.03em; }
@media (max-width: 620px) {
    .ov-bento { grid-template-columns: 1fr; grid-auto-rows: auto; }
    .ov-tile[style] { grid-column: 1 / -1 !important; grid-row: auto !important; }
    .ov-tile { overflow: visible; }
    .ov-tile-body { overflow: visible; }
    .ov-rz { display: none; }
}

/* (le « briefing » — flux + panneau Sources & priority — a été retiré) */
.ov-hint { font-family: var(--font-ui); font-size: var(--fs-xs); color: var(--text-muted); margin-top: 10px; line-height: 1.5; }

/* Études DANS le chart de cours (MM200, RSI, volatilité, volume) : boutons SOUS
   le chart, tout masqué par défaut -- voir studyKit dans app.js. Sous les
   boutons, une ligne d'explication (jamais deux) suivie d'un (i) qui ouvre
   l'explication étendue. */
.chart-studies { margin: 10px 0 0; }
.chart-studies:empty { display: none; }
.study-row { display: flex; flex-wrap: wrap; gap: 6px; }
.study-btn { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; font-size: var(--fs-sm); line-height: 1.5;
    color: var(--text-muted); background: transparent; border: 1px solid var(--border); border-radius: 999px; cursor: pointer; }
.study-btn:hover:not(:disabled) { color: var(--text-main); }
.study-btn.on { color: var(--text-main); border-color: var(--text-muted); background: rgba(128, 132, 140, 0.16); }
.study-btn.off, .study-btn:disabled { opacity: .45; cursor: not-allowed; }
.study-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
.study-chip { font-variant-numeric: tabular-nums; font-weight: 600; margin-left: 2px; }
.study-note { display: flex; align-items: center; gap: 0; margin-top: 8px; font-size: var(--fs-sm); color: var(--text-muted); min-width: 0; }
.study-note-txt { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.study-note-name { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px; color: var(--text-main); }
.study-note-name .info-trigger { margin-left: 0; }
.study-note .study-dot { margin-right: 8px; }

/* Chemin des leçons d'une section (mode Path) : même dessin qu'Easy -- pièces en zigzag, étape en cours qui rebondit. */
.acp{ position:relative; width:100%; max-width:460px; margin:8px auto 24px; }
.acp-svg{ position:absolute; inset:0; width:100%; height:100%; }
.acp-seg{ fill:none; stroke:var(--border); stroke-width:6; stroke-linecap:round; stroke-dasharray:2 12; }
.acp-seg.done{ stroke:var(--accent); stroke-dasharray:none; }
.acp-node{ position:absolute; transform:translate(-50%,-50%); width:58px; height:58px; border-radius:50%; display:grid; place-items:center; cursor:pointer;
    font-weight:700; background:var(--card-bg); color:var(--text-muted); border:3px solid var(--border); box-shadow:0 4px 0 var(--border); animation:acpPop .35s ease-out both; }
.acp-node.done{ background:var(--accent); color:#fff; border-color:var(--accent); box-shadow:0 4px 0 rgba(0,0,0,.25); }
.acp-node.cur{ width:68px; height:68px; background:#e8b93a; color:#3b2a00; border-color:#c99a1f; box-shadow:0 5px 0 #b48516; animation:acpPop .35s ease-out both, acpBob 1.6s ease-in-out .5s infinite; }
.acp-node.locked{ opacity:.55; cursor:default; }
.acp-lbl{ position:absolute; top:100%; margin-top:8px; width:130px; left:50%; transform:translateX(-50%); text-align:center; font-size:var(--fs-xs); line-height:1.25; font-weight:600; color:var(--text-main); }
.acp-node.todo .acp-lbl, .acp-node.locked .acp-lbl{ color:var(--text-muted); font-weight:500; }
@keyframes acpPop{ from{ opacity:0; transform:translate(-50%,-50%) scale(.6); } to{ opacity:1; transform:translate(-50%,-50%) scale(1); } }
@keyframes acpBob{ 0%,100%{ transform:translate(-50%,-50%); } 50%{ transform:translate(-50%,calc(-50% - 7px)); } }
@media (prefers-reduced-motion: reduce){ .acp-node, .acp-node.cur{ animation:none; } }
