/* ================================================================
   STYLES-MINDMAP.CSS — Culture Civique
   Mind map à bulles data-driven (pilote : Laïcité)
   Dépend de styles-base.css (variables sémantiques, thèmes, police).
   Référence visuelle : docs/comparaison-styles-mindmap-laicite-v4.html
   (style « Filet teal »)
   ================================================================ */

/* ----------------------------------------------------------------
   0. TOKENS DÉDIÉS — bulle constante + filet variable selon thème
   :root = valeurs sombres (secours), puis overrides clair
   (même logique que styles-base.css : @media light + [data-theme]).
   ---------------------------------------------------------------- */
:root {
    --mindmap-bubble: #5CC9BE;
    --mindmap-bubble-text: #102B44;
    --mindmap-central-bg: #E8F6F4;
    /* SP6a : filet éclairci #0E7C70 → #17A493 pour un contraste non-texte ≥3:1
       (RGAA 3.2 / WCAG 1.4.11) sur TOUT le dégradé sombre. L'ancien #0E7C70
       tombait à 2,13:1 sur le bas du fond (#1B3F65). #17A493 = 5,21:1 (haut) /
       3,48:1 (bas), et reste plus foncé que la bulle #5CC9BE → le liseré des
       bulles reste visible. Sert aussi à l'épine centrale mobile (::before).
       Thème CLAIR inchangé (override plus bas). */
    --mindmap-edge: #17A493;
    --mindmap-edge-w: 2.5px;
    --mindmap-shadow-soft: 0 4px 12px rgba(0, 0, 0, 0.28);
    --mindmap-sel-halo: var(--accent-shadow);
    --mindmap-backdrop: rgba(0, 0, 0, 0.55); /* voile du bottom sheet mobile (SP5a) : même valeur en clair et sombre, un voile sombre semi-transparent fonctionne dans les deux thèmes */
    --mindmap-sheet-bg: var(--bg-page-start); /* fond OPAQUE du bottom sheet mobile (SP5a-fix) : couleur de fond fondamentale du site, en version pleine — la feuille ne laisse jamais voir la carte derrière. Suit automatiquement Phase 1.4. */
}

@media (prefers-color-scheme: light) {
    :root:not([data-theme]) {
        --mindmap-edge: #0A6F68;
        --mindmap-edge-w: 2px;
        --mindmap-shadow-soft: 0 3px 10px rgba(15, 37, 64, 0.12);
        --mindmap-sheet-bg: var(--bg-surface); /* = #FFFFFF : concorde avec les cartes solides du mode clair */
    }
}

[data-theme="light"] {
    --mindmap-edge: #0A6F68;
    --mindmap-edge-w: 2px;
    --mindmap-shadow-soft: 0 3px 10px rgba(15, 37, 64, 0.12);
    --mindmap-sheet-bg: var(--bg-surface);
}

/* ----------------------------------------------------------------
   1. PAGE / MISE EN PAGE
   Colonne pleine hauteur : en-tête (titre + bouton) au-dessus,
   scène centrée (horizontal + vertical) dans l'espace restant.
   Structure volontairement simple : SP2 transformera .mindmap-stage
   en ligne flex « carte 2/3 + panneau 1/3 » sans tout réagencer.
   ---------------------------------------------------------------- */
/* Verrouille le scroll de page pendant que la feuille mobile (SP5a) est
   ouverte : seul le contenu de la feuille défile, posé/retiré par le JS. */
body.mindmap-scroll-lock {
    overflow: hidden;
}

.mindmap-page {
    /* 1040px = confortable pour la scène pleine largeur (SP0, ratio scale
       plafonné à 1 donc aucun changement visuel) ET pour le split SP2
       (zone carte ~66% ≥ 680px sur desktop courant, zone panneau ~34% lisible). */
    max-width: 1040px;
    margin: 0 auto;
    min-height: calc(100vh - 40px); /* 40px = padding vertical du body (styles-base.css) */
    display: flex;
    flex-direction: column;
}

/* Bandeau haut de page (recalé TÂCHE 2) : retour accueil + titre.
   NON collant — il défile et sort par le haut avec le contenu, comme
   l'en-tête des autres pages du site. Fond transparent : le dégradé
   ancré au document transparaît, donc aucune couture possible.
   On abandonne l'ancienne tranche de dégradé calée 100vh (+ sticky top:0),
   conçue pour un fond fixe au viewport : au défilement elle produisait un
   encadré rectangulaire au bas du bandeau ; et la rendre transparente
   laissait les bulles passer derrière le titre. Un en-tête qui défile
   normalement supprime les deux problèmes à la racine. */
.mindmap-topbar {
    display: flex;
    flex-direction: column;
    align-items: flex-start; /* le lien retour ne doit pas s'étirer sur toute la largeur (cross-axis d'une colonne flex = stretch par défaut) */
    padding-top: 12px;
    padding-bottom: 8px;
    margin-bottom: 20px;
}

.mindmap-heading {
    font-size: 1.4em;
    margin-top: 10px; /* espacement sous .back-btn (convention du site, ex. mises-en-situation.html), plus de margin-bottom dédié depuis le retrait de .mindmap-home-link */
    margin-bottom: 0;
}

/* Scène : centre la carte dans tout l'espace restant sous l'en-tête.
   Fermé (par défaut) : seule .mindmap-map-zone est visible → centrage
   identique à SP0. Ouvert (.mindmap-stage--split, posé par le JS à la
   sélection d'une bulle) : carte ~66% + panneau ~34% côte à côte.
   align-items:stretch (SP3-fix) — et non plus centre — pour que la
   hauteur des deux colonnes vienne du stage (donc du viewport) et non
   d'une comparaison mutuelle avec le contenu du panneau : voir
   .mindmap-panel (max-height + scroll interne) plus bas, qui rend ce
   découplage effectif. */
.mindmap-stage {
    flex: 1 1 auto;
    width: 100%;
    display: flex;
    align-items: stretch;
    justify-content: center;
    gap: 36px; /* gouttière carte / panneau — élargie en SP2-fix */
    overflow: hidden; /* garde-fou : jamais de scroll horizontal pendant le scale */
    padding: 12px 0;
}

/* SP4-fix (réaligné SP5a) : en 2 colonnes desktop, basis 0 → la hauteur de
   la rangée vient uniquement du flex-grow (remplit l'espace disponible sous
   le bandeau figé), jamais du contenu. Avec basis:auto, un panneau plus ou
   moins long (donc plus ou moins de questions) changeait la hauteur
   naturelle de la rangée, et via align-items:stretch celle de
   .mindmap-map-zone — la carte se recentrait alors à une position
   différente à chaque bulle. Réservé au desktop 2 colonnes (≥768px,
   même seuil que le bottom sheet mobile ci-dessous) : sous ce seuil, le
   panneau devient une feuille position:fixed qui ne participe plus au
   flex de la rangée — la carte occupe alors naturellement toute la largeur,
   sans qu'un basis fixe soit nécessaire ni pertinent. */
@media (min-width: 768px) {
    .mindmap-stage {
        flex-basis: 0;
    }
}

/* ----------------------------------------------------------------
   2. CARTE (branches + bulles)
   Canvas figé à 680×320 (géométrie de référence) : jamais réagencé.
   .mindmap-map-zone est un contexte de container query : la carte se
   réduit en bloc via transform:scale() à la largeur RÉELLE de sa zone
   (100cqi), que cette zone fasse 100% de la scène (fermé) ou ~66%
   (panneau ouvert) — même mécanisme dans les deux cas, jamais cassé.
   ---------------------------------------------------------------- */
.mindmap-map-zone {
    container-type: inline-size;
    flex: 1 1 100%;
    min-width: 0;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    /* Respiration interne : un peu à gauche, davantage à droite (côté
       panneau) — le scale (100cqi) en tient compte automatiquement,
       la carte ne colle donc plus jamais aux bords de sa zone. */
    padding: 0 28px 0 8px;
}

.mindmap-stage--split .mindmap-map-zone {
    flex-basis: 66%;
}

.mindmap-map {
    position: relative;
    width: 680px;
    height: 320px;
    flex-shrink: 0;
    transform: scale(min(1, calc(100cqi / 680px)));
    will-change: transform;
}

.mindmap-svg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: visible;
    pointer-events: none;
}

.mindmap-branch {
    fill: none;
    stroke: var(--mindmap-edge);
    stroke-width: var(--mindmap-edge-w);
    stroke-linecap: round;
    opacity: 0;
}

.mindmap-branch.mindmap-branch--draw {
    opacity: 1;
    stroke-dasharray: 330;
    stroke-dashoffset: 330;
    animation: mindmap-draw 0.55s ease-out forwards;
}

.mindmap-branch.mindmap-branch--vis {
    opacity: 1;
}

@keyframes mindmap-draw {
    to {
        stroke-dashoffset: 0;
    }
}

.mindmap-bub {
    position: absolute;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    line-height: 1.15;
    border: var(--mindmap-edge-w) solid var(--mindmap-edge);
    box-shadow: var(--mindmap-shadow-soft);
    color: var(--mindmap-bubble-text);
    border-radius: 45% 45% 45% 45% / 50% 50% 50% 50%;
    cursor: pointer;
    transition: box-shadow 0.25s ease;
}

/* SP6d : focus clavier VISUELLEMENT DISTINCT de la sélection.
   Sélection = halo cyan doux (box-shadow, .mindmap-leaf--sel). Pour ne pas
   confondre « focalisé » et « sélectionné » (tous deux cyan jusqu'ici), le
   focus des bulles reçoit un anneau SOLIDE en couleur de texte (quasi-blanc
   en sombre #F0F4F8 / quasi-noir en clair #0F2540) : fort contraste sur le
   fond (~10–15:1), non-cyan, lisible même superposé au halo de sélection.
   Repli .using-keyboard pour Safari (même mécanisme que le skip-link). */
.mindmap-bub:focus-visible,
.using-keyboard .mindmap-bub:focus {
    outline: 3px solid var(--text-primary);
    outline-offset: 2px;
}

.mindmap-central {
    left: 265px;
    top: 126px;
    width: 150px;
    height: 68px;
    background: var(--mindmap-central-bg);
    font-size: 17px;
    font-weight: 700;
    flex-direction: column;
    text-transform: uppercase;
}

.mindmap-central small {
    font-size: 10px;
    font-weight: 400;
    text-transform: none;
    /* SP6a : opacity 0.7 → 0.85 pour un ratio ≥7:1 (texte 10px, seuil AAA).
       0.7 donnait 5,25:1 ; 0.85 donne 8,45:1. Le sous-titre reste secondaire
       par la taille (10px) et le poids (400). #102B44 sur #E8F6F4 dans les
       deux thèmes (tokens non overridés). */
    opacity: 0.85;
    margin-top: 2px;
    color: var(--mindmap-bubble-text);
}

.mindmap-leaf {
    width: 150px;
    height: 54px;
    background: var(--mindmap-bubble);
    font-size: 13px;
    font-weight: 700;
    padding: 4px 12px;
    min-height: 44px;
    opacity: 0;
    transform: translateZ(0) scale(0.3);
    will-change: transform, opacity;
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
}

.mindmap-leaf.mindmap-leaf--pop {
    animation: mindmap-pop 0.5s ease-out forwards;
}

.mindmap-leaf.mindmap-leaf--shown {
    opacity: 1;
    transform: translateZ(0) scale(1);
}

.mindmap-leaf.mindmap-leaf--sel {
    box-shadow: 0 0 0 4px var(--mindmap-sel-halo), var(--mindmap-shadow-soft);
}

.mindmap-leaf.mindmap-leaf--dim {
    opacity: 0.42;
}

@keyframes mindmap-pop {
    0% {
        opacity: 0;
        transform: translateZ(0) scale(0.3);
    }
    60% {
        opacity: 1;
        transform: translateZ(0) scale(1.05);
    }
    100% {
        opacity: 1;
        transform: translateZ(0) scale(1);
    }
}

@media (prefers-reduced-motion: reduce) {
    .mindmap-branch,
    .mindmap-leaf,
    .mindmap-bub {
        transition: none;
        animation: none !important;
    }
}

/* ----------------------------------------------------------------
   3. PANNEAU LATÉRAL (SP2, retouché SP4)
   Contenu lu depuis REFERENTIEL par le JS. Masqué via [hidden] tant
   que rien n'est sélectionné ; le JS bascule .mindmap-panel--visible
   pour l'entrée en fondu (première ouverture depuis l'état fermé).
   Le cadre (position, largeur, fond, bordure) ne bouge jamais au
   changement de bulle panneau déjà ouvert — seul .mindmap-panel-content
   (plus bas) s'estompe puis réapparaît dans ce cas.
   ---------------------------------------------------------------- */
/* Voile + poignée : uniquement mobiles (SP5a), masqués par défaut ici ;
   voir @media (max-width: 767px) plus bas pour leur mise en forme. */
.mindmap-backdrop {
    display: none;
}

.mindmap-panel-handle {
    display: none;
}

.mindmap-panel {
    flex: 0 0 30%; /* légèrement resserré (SP2-fix) pour laisser respirer la zone carte */
    min-width: 0;
    /* Hauteur bornée + défilement interne (SP3-fix) : révéler une réponse
       ne fait plus grandir le panneau, donc ne change plus la hauteur du
       stage ni la position de la carte (voir .mindmap-stage:align-items).
       max-height = garde-fou explicite ; le align-items:stretch du stage
       est ce qui fixe réellement la hauteur au viewport disponible.
       (En-tête collant essayé en SP3-fix-3 puis annulé en SP3-fix-4 : le
       titre + X défilent normalement avec le reste du panneau.) */
    max-height: calc(100vh - 32px);
    overflow-y: auto;
    box-sizing: border-box;
    padding: 22px 24px;
    border-radius: var(--radius-lg);
    border: 1px solid var(--border-default);
    /* SP6b : panneau desktop OPAQUE, unifié avec le bottom sheet mobile
       (même token --mindmap-sheet-bg). L'ancien --bg-surface translucide
       (rgba blanc 0.12 en sombre) laissait le dégradé transparaître : sur la
       moitié basse du panneau (fond plus clair), le texte secondaire tombait
       à ~5,4:1 et l'encadré « bonne réponse » à ~4,0:1 (sous AA). Opaque =
       #0B2237 en sombre (AAA partout : 11,4:1 / 7,3:1) ; en CLAIR, identique
       à avant (--mindmap-sheet-bg = --bg-surface = #FFFFFF). Suit Phase 1.4. */
    background: var(--mindmap-sheet-bg);
    box-shadow: var(--shadow-md);
    opacity: 0;
    /* SP4 : fondu seul à l'ouverture (plus de glissement translateX). */
    transition: opacity 0.18s ease-in-out;
}

.mindmap-panel.mindmap-panel--visible {
    opacity: 1;
}

/* SP4 : cross-fade du contenu seul au changement de bulle, panneau déjà
   ouvert — le cadre ci-dessus reste immobile pendant ce temps. */
.mindmap-panel-content {
    opacity: 1;
    transition: opacity 0.19s ease-in-out;
    /* Couche de compositing PERMANENTE (brief B v6) : sans elle, chaque
       cross-fade crée puis détruit une couche GPU, et depuis l'arrivée du
       calque fixe body::before (z-index:-1), WebKit laisse parfois traîner
       l'ancienne texture du panneau ~1 s en surimpression du nouveau
       contenu au changement de bulle. Couche stable = texture repeinte de
       façon synchrone au remplacement du contenu. Même famille de remède
       que les artefacts d'animation des bulles (SP1). */
    will-change: opacity;
}

.mindmap-panel-content.mindmap-panel-content--fade {
    opacity: 0;
}

.mindmap-panel-head {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin-bottom: 10px;
}

.mindmap-panel-title {
    flex: 1;
    font-size: 1.15em;
    color: var(--text-primary);
}

.mindmap-panel-close {
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    padding: 0;
    border: none;
    border-radius: var(--radius-pill);
    background: none;
    color: var(--text-secondary);
    cursor: pointer;
    transition: background 0.2s, color 0.2s;
}

.mindmap-panel-close:hover {
    background: var(--bg-surface-hover);
    color: var(--text-primary);
}

.mindmap-panel-close svg {
    width: 18px;
    height: 18px;
}

.mindmap-panel-def {
    font-size: 0.95em;
    line-height: 1.6;
    color: var(--text-primary);
    margin-bottom: 16px;
}

/* :not([hidden]) impératif : sans ça, ce display: inline-block (spécificité
   égale à la règle UA [hidden] { display:none }) l'emporte via l'ordre du
   cascade auteur, et l'attribut hidden posé par le JS n'a plus aucun effet. */
.mindmap-panel-link:not([hidden]) {
    display: inline-block;
    margin-bottom: 20px;
    font-weight: 700;
    cursor: pointer;
}

.mindmap-panel-questions {
    padding-top: 16px;
    border-top: 1px solid var(--border-divider);
}

.mindmap-panel-questions h3 {
    font-size: 1em;
    color: var(--text-primary);
    margin-bottom: 6px;
}

.mindmap-questions-count {
    font-size: 0.8em;
    color: var(--text-secondary);
    margin-bottom: 10px;
}

.mindmap-questions-empty {
    font-size: 0.9em;
    font-style: italic;
    color: var(--text-secondary);
    margin: 0;
}

.mindmap-questions-list {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.mindmap-question-item {
    padding-bottom: 16px;
    border-bottom: 1px solid var(--border-divider);
}

.mindmap-question-item:last-child {
    border-bottom: none;
    padding-bottom: 0;
}

.mindmap-question-text {
    font-size: 0.92em;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 10px;
}

.mindmap-question-toggle {
    /* Compact et aligné à gauche (SP3-fix) : largeur auto (jamais pleine
       largeur), pas de centrage — mais hauteur ≥44px conservée (RGAA). */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    align-self: flex-start;
    width: auto;
    min-height: 44px;
    padding: 0 14px;
    border-radius: var(--radius-md);
    border: 1px solid var(--accent);
    background: transparent;
    color: var(--accent);
    font-size: 0.82em;
    font-weight: 700;
    cursor: pointer;
    transition: background 0.2s, color 0.2s;
}

.mindmap-question-toggle:hover {
    background: var(--accent-soft);
}

.mindmap-question-answer {
    margin-top: 12px;
}

.mindmap-question-correct {
    font-size: 0.88em;
    font-weight: 700;
    padding: 10px 12px;
    border-radius: var(--radius-sm);
    background: var(--state-success-soft);
    color: var(--state-success-text);
    margin-bottom: 10px;
}

.mindmap-question-expl {
    font-size: 0.85em;
    line-height: 1.55;
    color: var(--text-secondary);
    margin: 0;
    padding: 0 12px;
}

/* ----------------------------------------------------------------
   4. BOTTOM SHEET MOBILE (SP5a) — sous 768px
   Remplace le repli provisoire (panneau pleine largeur sous la carte).
   Réutilise le même .mindmap-panel / .mindmap-panel-content que le
   panneau desktop (même code de remplissage JS, aucune duplication) :
   seule la présentation change ici, via position:fixed + un voile.
   La carte n'est pas relayoutée en mobile (SP5b) : .mindmap-panel
   devient position:fixed, sort donc du flux flex de .mindmap-stage,
   et .mindmap-map-zone (flex-grow:1, seul item restant dans la
   rangée) occupe alors naturellement toute la largeur disponible.
   ---------------------------------------------------------------- */
@media (max-width: 767px) {
    /* :not([hidden]) impératif (même piège qu'en SP3-fix-2 sur .mindmap-panel-link) :
       sans ça, ce display:block (spécificité égale à la règle UA [hidden]{display:none})
       l'emporte via l'ordre du cascade auteur, et le voile reste affiché — donc
       intercepte les taps sur la carte — même quand le JS pose l'attribut hidden. */
    .mindmap-backdrop:not([hidden]) {
        display: block;
        position: fixed;
        inset: 0;
        background: var(--mindmap-backdrop);
        opacity: 0;
        transition: opacity 0.24s ease-out;
        z-index: 90;
    }

    .mindmap-backdrop.mindmap-backdrop--visible {
        opacity: 1;
    }

    /* La feuille flotte par-dessus la carte (position:fixed) : glissement
       seul (transform), le voile ci-dessus porte le fondu — deux animations
       distinctes comme demandé, plutôt qu'un opacity+transform combiné sur
       le cadre. .mindmap-panel reste le conteneur défilant (overflow-y:auto
       hérité de la règle desktop) ; poignée + en-tête y sont épinglés en
       position:sticky (voir plus bas), le reste du contenu défile dessous. */
    .mindmap-panel:not([hidden]) {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        top: auto;
        width: 100%;
        max-width: none;
        flex: none;
        max-height: 85vh;
        border-radius: var(--radius-lg) var(--radius-lg) 0 0;
        background: var(--mindmap-sheet-bg);
        display: flex;
        flex-direction: column;
        overflow: hidden;
        padding: 0;
        opacity: 1;
        transform: translateY(100%);
        transition: transform 0.24s ease-out;
        z-index: 100;
    }

    .mindmap-panel.mindmap-panel--visible {
        transform: none;
    }

    /* Plus AUCUN sticky (SP5a-fix-4) : la feuille est trois étages empilés —
       poignée figée / en-tête figé / corps défilant (.mindmap-panel-body).
       L'en-tête étant physiquement hors de la zone de défilement, le texte
       ne peut plus passer derrière (le sticky dans un défileur imbriqué
       s'est révélé non fiable dans WebKit, iOS comme macOS). Le cross-fade
       SP4 sur .mindmap-panel-content (qui englobe l'en-tête) est inchangé. */
    .mindmap-panel-content {
        flex: 1 1 auto;
        min-height: 0;
        display: flex;
        flex-direction: column;
        overflow: hidden;
        padding: 0;
    }

    .mindmap-panel-body {
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        padding: 0 24px calc(16px + env(safe-area-inset-bottom)) 24px;
    }

    /* Poignée : premier étage figé de la feuille (hors zone de défilement,
       comme l'en-tête ci-dessous — voir commentaire de .mindmap-panel-content). */
    .mindmap-panel-handle {
        display: flex;
        align-items: center;
        justify-content: center;
        height: 24px;
        flex: none;
        background: var(--mindmap-sheet-bg);
    }

    .mindmap-panel-handle span {
        width: 36px;
        height: 4px;
        border-radius: var(--radius-pill);
        background: var(--text-muted);
    }

    .mindmap-panel-head {
        flex: none;
        padding: 8px 24px 12px 24px;
        border-bottom: 1px solid var(--border-divider);
    }

    /* ------------------------------------------------------------
       SP5b — RELAYOUT PORTRAIT (pile verticale, épine centrale)
       Sous 768px, la carte horizontale (positionnement absolu px calé
       sur le desktop + connecteurs Bézier SVG) est remplacée par une
       pile verticale : bulle centrale en haut, puis les 6 branches
       empilées dans l'ordre du DOM (= ordre du référentiel), reliées
       par une épine centrale (segments verticaux ::before). AUCUN
       position:sticky (leçon SP5a) : la pile défile avec la page.
       Le desktop (≥768px) reste strictement inchangé.
       ------------------------------------------------------------ */

    /* Connecteurs Bézier masqués : l'épine centrale les remplace. */
    .mindmap-svg {
        display: none;
    }

    /* Zone carte : colonne centrée, gouttières symétriques (l'asymétrie
       desktop servait le panneau latéral, absent en portrait). */
    .mindmap-map-zone {
        padding: 8px 16px 24px;
        align-items: center;
    }

    /* Conteneur central + feuilles : pile verticale centrée.
       Neutralise les dimensions et le transform:scale figés du canvas
       680×320 de référence. gap = hauteur de l'épine (cf. ::before). */
    .mindmap-map {
        width: 100%;
        max-width: 360px;
        height: auto;
        margin-inline: auto;
        transform: none;
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 26px;
    }

    /* Neutralise le positionnement absolu inline (left/top/width/height
       posés en px par le JS). position:relative annule left/top inline et
       sert d'ancre au ::before ; les dimensions inline sont rebattues avec
       !important — seul moyen de primer un style inline depuis le CSS.
       border-radius:999px → capsule, comme la maquette SP5b : l'ovale
       45%/50% hérité de .mindmap-bub s'étirait en lentille sur les boîtes
       larges du portrait. */
    .mindmap-central {
        position: relative;
        left: auto !important;
        top: auto !important;
        width: 190px !important;
        height: auto !important;
        min-height: 76px;
        padding: 10px 18px;
        border-radius: 999px;
    }

    .mindmap-leaf {
        position: relative;
        left: auto !important;
        top: auto !important;
        width: 86% !important;
        height: auto !important;
        min-height: 52px;
        padding: 12px 18px; /* dégage le texte des extrémités arrondies de la capsule */
        border-radius: 999px; /* capsule (comme la maquette) — remplace l'ovale hérité */
        font-size: 14px;
        /* Feuilles visibles d'emblée en portrait : la cascade de révélation
           (base opacity:0 → --shown) n'est pas rejouée ici. !important prime
           à la fois la base ET l'animation --pop éventuelle. --sel (box-shadow)
           et --dim (opacity, ré-important ci-dessous) restent opérants. */
        opacity: 1 !important;
        transform: none !important;
    }

    /* --dim doit continuer d'estomper les feuilles non sélectionnées malgré
       le opacity:1 !important ci-dessus (spécificité supérieure : 2 classes). */
    .mindmap-leaf.mindmap-leaf--dim {
        opacity: 0.42 !important;
    }

    /* Épine centrale : un segment vertical dans la gouttière au-dessus de
       chaque feuille. Le premier (au-dessus de la feuille 1) relie la bulle
       centrale ; les suivants relient feuille à feuille. Épaisseur et couleur
       = tokens du filet (identiques aux connecteurs desktop). */
    .mindmap-leaf::before {
        content: "";
        position: absolute;
        left: 50%;
        top: -26px;
        transform: translateX(-50%);
        width: var(--mindmap-edge-w);
        height: 26px;
        background: var(--mindmap-edge);
    }
}

@media (prefers-reduced-motion: reduce) {
    .mindmap-panel,
    .mindmap-panel-content,
    .mindmap-backdrop {
        transition: none;
    }
}

/* ----------------------------------------------------------------
   5. HUB DES CARTES MENTALES (cartes-mentales.html) — SP7a
   Liste data-driven des notions mindmap:true du référentiel, groupées
   par thématique. Une tuile = une notion ; la page s'étend seule.

   Pourquoi des classes dédiées et non celles de l'accueil : .menu-grid,
   .menu-item, .menu-item-v3 et .badge-corner vivent dans le <style>
   inline d'index.html, pas dans styles-base.css — donc non réutilisables
   hors de l'accueil. Seul .glass-card est partagé, et il ne porte NI
   padding NI margin (l'accueil les pose chez lui) : posés ici.
   ---------------------------------------------------------------- */
.hub-intro {
    color: var(--text-secondary);
    max-width: 62ch;
    margin-bottom: 28px;
}

.hub-theme {
    margin-bottom: 32px;
}

.hub-theme:last-child {
    margin-bottom: 0;
}

/* En-tête de thématique : reprend la hiérarchie réelle du référentiel
   (thematiques > notions). Le numéro reste discret, le titre porte. */
.hub-theme-title {
    font-size: 1.05em;
    font-weight: 400;
    color: var(--text-secondary);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    margin-bottom: 24px;
}

.hub-theme-title strong {
    color: var(--text-primary);
    font-weight: 700;
}

/* auto-fill : 2 colonnes aujourd'hui (2 notions), 3 quand il y en aura
   plus, sans retoucher le CSS. 880px garde des tuiles lisibles dans les
   1040px de .mindmap-page. */
.hub-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 16px;
    max-width: 880px;
}

.hub-card {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
    padding: 22px;
    text-decoration: none;
    color: inherit;
    transition: transform 0.2s ease, border-color 0.2s ease;
}

.hub-card:hover {
    transform: translateY(-2px);
    border-color: var(--accent);
    text-decoration: none;
}

.hub-card:active {
    transform: scale(0.98);
}

/* Focus visible : même mécanisme que .mindmap-bub (SP6d) — anneau solide
   en couleur de texte, plus le repli .using-keyboard car :focus-visible
   ne se déclenche pas sur les <a> au Tab initial dans Safari. */
.hub-card:focus-visible,
.using-keyboard .hub-card:focus {
    outline: 3px solid var(--text-primary);
    outline-offset: 3px;
}

/* Mini-bulle : écho de la bulle centrale de la carte (mêmes tokens que
   .mindmap-central) — le hub annonce ce qu'il ouvre. aria-hidden côté
   HTML : son texte double le titre de la tuile. */
.hub-bulle {
    width: 100%;
    height: 64px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    line-height: 1.2;
    padding: 0 12px;
    border-radius: var(--radius-pill);
    background: var(--mindmap-central-bg);
    border: var(--mindmap-edge-w) solid var(--mindmap-edge);
    color: var(--mindmap-bubble-text);
    box-shadow: var(--mindmap-shadow-soft);
}

.hub-bulle-label {
    font-weight: 700;
}

.hub-bulle-num {
    font-size: 0.8em;
    opacity: 0.75;
}

.hub-text {
    display: flex;
    flex-direction: column;
    gap: 6px;
    width: 100%;
}

.hub-title {
    font-size: 1.1em;
    font-weight: 700;
    color: var(--text-primary);
    margin: 0;
}

.hub-accroche {
    color: var(--text-secondary);
    font-size: 0.95em;
    margin: 0;
}

.hub-meta {
    font-size: 0.85em;
    color: var(--accent-text);
    margin: 2px 0 0;
}

.hub-meta .hub-dot {
    opacity: 0.6;
}

.hub-empty {
    color: var(--text-secondary);
    max-width: 62ch;
}

@media (prefers-reduced-motion: reduce) {
    .hub-card,
    .hub-card:hover,
    .hub-card:active {
        transition: none;
        transform: none;
    }
}

/* Portrait : une seule colonne — les tuiles restent larges et tapables. */
@media (max-width: 600px) {
    .hub-grid {
        grid-template-columns: 1fr;
    }
}
