/* nv.css -- Styles du nouveau visuel.
 *
 * Sous-chantier 00_socle du chantier interface__nouveau-visuel (2026-09-25),
 * complete par le sous-chantier 00-bis_habillage-commun (2026-09-26), puis
 * par le sous-chantier 01_accueil (2026-09-26), puis par le sous-chantier
 * 02_page-quiz (2026-09-26), puis par le sous-chantier
 * 02-bis_zone-themes-agrandie (2026-09-26). Plans :
 * .../vague-1_socle-seul/00_socle/PLAN_00_socle.md, § 6,
 * .../vague-1_socle-seul/00-bis_habillage-commun/PLAN_00-bis_habillage-commun.md, § 4,
 * .../vague-2_en-parallele-apres-00/01_accueil/PLAN_01_accueil.md, § 4,
 * .../vague-2_en-parallele-apres-00/02_page-quiz/PLAN_02_page-quiz.md, § 4, et
 * .../vague-2_en-parallele-apres-00/02-bis_zone-themes-agrandie/PLAN_02-bis_zone-themes-agrandie.md, § 2.
 *
 * Regle de hauteur (01_accueil) : a 375 x 812, l'accueil ne defile pas et son
 * dernier element reste visible au-dessus de la barre du bas, tant que la
 * place disponible (voir plus bas) n'est pas depassee ; au-dela, les quatre
 * blocs se resserrent jusqu'a un plancher de 100px (forme compacte),
 * sous-titre perdu en premier, puis icone et nom reduits -- le nom reste
 * toujours visible. Au-dela du plancher, l'ecran grandit avec son contenu et
 * .app-content defile normalement.
 *
 * Place disponible pour 01-bis (B) -- mesuree le 2026-09-26 a 375 x 812,
 * Feutre Vert : **108px**, invite comme compte connecte (rangee des cycles
 * et « Bonjour » sur une seule ligne dans les deux etats) -- mesuree avec
 * le bouton provisoire, retire depuis par 02 : la place reelle est plus
 * grande de sa hauteur (non remesuree).
 *
 * Mise en page seule, AUCUNE VALEUR DE COULEUR : si une couleur est
 * necessaire, elle consomme un role existant de public/styles.css par
 * var(--…) -- ce fichier ne DECLARE aucune propriete personnalisee, il les
 * consomme seulement (garde S7, tests/test_nouveau_visuel_socle.py). Les
 * roles du nouveau visuel se declarent dans public/styles.css (:root, puis
 * le bloc de la charte qui en a besoin), jamais ici.
 * Complete par le sous-chantier 01-bis_accueil-existant (2026-09-26). Plan :
 * .../vague-2_en-parallele-apres-00/01-bis_accueil-existant/
 * PLAN_01-bis_accueil-existant.md, § 4.
 *
 * Ce fichier porte TREIZE regles !important : le masquage de l'accueil commun
 * ci-dessous et la couleur de l'onglet Aide (§ « Barre du bas », plus bas) --
 * deux regles du socle --, NEUF ajoutees par 01-bis dans la reserve
 * (§ « Accueil », plus bas), UNE ajoutee par 03_mes-themes -- le cadre des
 * tuiles de la page Mes themes (§ « Mes themes », plus bas), contre
 * body.theme-vegas .card-glass --, et UNE ajoutee par 05_bibliotheque-cours --
 * le masquage de l'ancienne barre de titre de la bibliotheque (§ « Bibliotheque
 * de cours », plus bas), qui porte son affichage en style en ligne. Chacune
 * des neuf de 01-bis porte son propre commentaire : « l'emporte sur un style
 * en ligne de index.html » pour les marges et rembourrages du bandeau de
 * reprise et de l'objectif, et pour la largeur de la rangee du champ pseudo et
 * la couleur de #pseudo-help ; « l'emporte sur un style en ligne ecrit par
 * main.js » pour la couleur et le masquage hors focus de
 * #pseudo-check-indicator. Ce fichier (nv.css) est hors du perimetre de
 * tools/compter_couleurs.py et de tests/test_24_cliquet_couleurs.py : dans CE
 * fichier, S5 (tests/test_nouveau_visuel_socle.py) est la seule garde contre
 * une couleur ecrite en clair.
 *
 * Chaque selecteur est prefixe body.nv-actif ou porte une classe/un id nv-.
 */

/* Masquage de l'accueil commun sous le nouveau visuel.
 *
 * Le !important est NECESSAIRE : le bandeau de reprise (#quiz-resume-banner)
 * et l'objectif de la semaine (#community-goal-bar) recoivent leur
 * affichage en style en ligne par ui.js, et le « Bonjour » et les quatre
 * tuiles sont affiches par des selecteurs a deux identifiants dans
 * public/styles.css. L'interdit « jamais de display !important sur
 * #quiz-resume-banner » (public/styles.css) protege le pilotage de
 * L'ANCIEN visuel ; cette regle ne s'applique que sous body.nv-actif, ou ce
 * pilotage n'a plus d'ecran -- l'exception est voulue.
 *
 * Depuis 01-bis_accueil-existant : le bandeau et l'objectif, deplaces dans
 * #nv-accueil-reserve par nv_socle.js, ne sont plus enfants directs de
 * #screen-home et echappent donc a cette regle -- leur affichage y est
 * pilote par les regles de la reserve, plus bas. */
body.nv-actif #screen-home > :not(#nv-accueil) {
    display: none !important;
}

/* Regle de hauteur (01_accueil, plan § 4) : grille a une rangee 1fr, en
 * min-height -- jamais height. Grid § 12.7.1 : la rangee 1fr prend la taille
 * de son contenu, puis est portee au min-height de la grille si elle est
 * plus petite ; un element de grille etire (align-self par defaut) a une
 * hauteur DEFINIE, ce qui donne a .nv-blocs (ci-dessous) une hauteur sur
 * laquelle ses pistes 1fr peuvent se partager la place libre. --safe-area-bottom
 * seul (et non le rembourrage de #screen-home) : .app-content reserve deja
 * 80px sous la barre. */
body.nv-actif #screen-home.active {
    display: grid;
    grid-template-rows: 1fr;
    box-sizing: border-box;
    min-height: 100%;
    padding-bottom: var(--safe-area-bottom);
}

/* Accueil du nouveau visuel : quatre blocs en grille 2x2, plus le bandeau
 * Aide en pleine largeur en dessous. Ni flex, ni min-height: 0 : etire par
 * la grille, son minimum reste la hauteur de son contenu. */
#nv-accueil {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 16px 2px;
}

/* « Bonjour » -- phrase claire, nom dore comme l'accueil actuel (Journal
 * n° 16). Contrastes mesures le 2026-09-26 (375 x 812, fond = la page seule,
 * extremite la plus defavorable de --bg-gradient) : phrase (--text-main),
 * seuil 4,5:1 -- classic 8,2:1 ; mint 5,8:1 ; vegas 11,8:1. Nom
 * (--primary-light), seuil 4,5:1 -- classic 6,3:1 ; vegas 9,3:1 ; **mint
 * 4,4:1, sous le seuil** -- ecart accepte par l'utilisateur (Reserve
 * acceptee). */
.nv-bonjour {
    flex: none;
    margin: 0;
    font-size: 14px;
    color: var(--text-main);
}

.nv-bonjour strong {
    color: var(--primary-light);
    font-weight: 700;
}

/* ===========================================================================
 * Accueil (sous-chantier 01-bis_accueil-existant, 2026-09-26) -- plan § 4.
 * Ce que porte l'accueil actuel, deplace dans la reserve par nv_socle.js :
 * la case pseudo, le bandeau de reprise, l'objectif de la semaine. Aucune
 * couleur neuve : seul var(--text-main), role existant. Aucun role declare
 * (S7). Selecteurs sous #nv-accueil-reserve (id nv-, regle de l'en-tete).
 * =========================================================================== */
#nv-accueil-reserve {
    display: flex;
    flex-direction: column;
    gap: 8px;
    flex: none;
}

/* Case pseudo -- forme resserree (utilisateur, arret 1 : la forme cede,
 * jamais le "sans defiler"). Une seule ligne au repos : libelle, champ de
 * 44px, ✓ ; l'aide et l'indicateur de disponibilite prennent leur propre
 * ligne SOUS le champ, uniquement pendant la saisie (:focus-within). */
#nv-accueil-reserve #pseudo-field-group {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    column-gap: 8px;
    row-gap: 4px;
    /* jamais de display ici : pilote par ui.js (updatePseudoFieldLock). */
}

/* Boite calee en haut de la case, hauteur du champ : le libelle reste sur
 * l'axe du champ quand l'indicateur ajoute sa ligne sous lui. --text-muted
 * de .form-label passerait sous 4,5:1 hors de la carte (meme motif que
 * 00-bis et 01). Contraste (11px gras, seuil 4,5:1 -- ni #nv-accueil ni la
 * reserve n'ont de fond, meme fond de page nu que .nv-bonjour ci-dessus, donc
 * meme ratio pour --text-main, deja mesure le 2026-09-26) : classic 8,2:1 ;
 * mint 5,8:1 ; vegas 11,8:1. */
#nv-accueil-reserve #pseudo-label {
    flex: none;
    align-self: flex-start;
    height: 44px;
    min-height: 0;
    align-items: center;
    color: var(--text-main);
}

/* l'emporte sur un style en ligne de index.html : le width: 100% en ligne
 * renverrait le champ a la ligne ; flex-wrap laisse l'indicateur passer sous
 * le champ (puce suivante), a l'ecart deja pose en ligne (gap: 8px, qui vaut
 * aussi entre les lignes). */
#nv-accueil-reserve #pseudo-field-group > div {
    flex: 1 1 0;
    min-width: 0;
    width: auto !important;
    flex-wrap: wrap;
}

/* l'emporte sur un style en ligne ecrit par main.js : les couleurs qu'il
 * pose (--text-muted, --text-pseudo-check-taken, --text-pseudo-check-available)
 * passent sous 4,5:1 sur la page nue (7 cas sur 9) ; l'emoji en tete
 * (⏳ 🔑 ✅ ✉️) garde la distinction des cas. Pendant la frappe, l'indicateur
 * prend une ligne a lui sous le champ et ✓, jamais leur largeur. Jamais
 * display ici : pilote par main.js. Contraste : celui de --text-main sur la
 * page nue, deja mesure ci-dessus pour #pseudo-label (meme fond, memes trois
 * chartes) ; aucun releve propre -- la couleur resolue de l'indicateur est
 * verifiee egale a --text-main par e2e/test_nouveau_visuel_accueil_existant.py
 * (R3). */
#nv-accueil-reserve #pseudo-check-indicator {
    order: 3;
    flex-basis: 100%;
    color: var(--text-main) !important;
}

/* l'emporte sur un style en ligne ecrit par main.js : sans elle, l'indicateur
 * survit a une connexion reussie et revient, fige sur son dernier message,
 * avec la case apres une deconnexion sans rechargement (Reserve acceptee,
 * VERDICT_02 constat 1 -- meme comportement que l'ancien visuel). Visible
 * seulement au focus dans la case (saisie, clavier ouvert). */
#nv-accueil-reserve #pseudo-field-group:not(:focus-within) #pseudo-check-indicator {
    display: none !important;
}

#nv-accueil-reserve #input-pseudo {
    height: 44px;
}

/* l'emporte sur un style en ligne de index.html, pour la couleur seulement :
 * --text-muted passerait sous 4,5:1 hors de la carte. L'aide est sous la
 * ligne du champ : quand elle se replie (iOS ne donne pas le focus a ✓), ✓
 * ne bouge pas entre pointerdown et le clic. Contraste (12px, seuil 4,5:1 --
 * meme fond de page nu, meme ratio pour --text-main que #pseudo-label
 * ci-dessus) : classic 8,2:1 ; mint 5,8:1 ; vegas 11,8:1. */
#nv-accueil-reserve #pseudo-help {
    display: none;
    flex-basis: 100%;
    color: var(--text-main) !important;
}

#nv-accueil-reserve #pseudo-field-group:focus-within #pseudo-help {
    display: block;
}

/* Bandeau de reprise et objectif -- l'emporte sur un style en ligne de
 * index.html (marges et rembourrages). */
#nv-accueil-reserve #quiz-resume-banner {
    /* Resserrement (état "connecté + reprise + objectif" rouge à 8px --
     * padding vertical seul réduit, plan § 4) : 8 -> 6px. */
    padding: 6px 12px !important;
    margin: 0 !important;
}

#nv-accueil-reserve #community-goal-bar {
    /* Resserrement (état "connecté + reprise + objectif" rouge à 6px,
     * plan § 4) : 6 -> 4px. */
    padding: 4px 12px !important;
    margin: 0 !important;
}

#nv-accueil-reserve #community-goal-bar > div:first-child {
    margin-bottom: 4px !important;
}

/* La ligne "x / y questions cette semaine" cede ; titre, pourcentage et
 * barre restent. */
#nv-accueil-reserve #community-goal-label {
    display: none;
}

/* .nv-blocs -- grille 2x2 plafonnee a 170px (maquette), plancher 100px tenu
 * par .nv-bloc (forme compacte, ci-dessous). Quand le contenu depasse la
 * hauteur utile, la rangee de l'ecran grandit et .app-content defile. */
.nv-blocs {
    flex: 1 1 auto;
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr 1fr;
    gap: 12px;
    max-height: calc(2 * 170px + 12px);
}

.nv-bloc {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 10px 8px;
    border-radius: 20px;
    text-align: center;
    font: inherit;
    background: var(--bg-card);
    border: 2px solid var(--bg-card-border);
    color: var(--text-main);
    container-type: size;
    min-height: 100px;
    min-width: 0;
    overflow: hidden;
}

.nv-bloc:focus-visible {
    border-color: var(--primary);
}

#nv-accueil .nv-bloc-icone {
    display: block;
    font-size: 36px;
    line-height: 1.2;
}

#nv-accueil .nv-bloc-nom {
    display: block;
    line-height: 1.2;
    font-size: 19px;
    font-weight: 800;
    text-transform: uppercase;
}

/* --text-muted, et non --text-main, passerait sous 4,5:1 sur ce fond (meme
 * motif que « Mon niveau », 00-bis). Contrastes mesures le 2026-09-26 (375 x
 * 812, fond = --bg-card compose sur l'extremite la plus defavorable de
 * --bg-gradient) : sous-titre/nom non principal (--text-main), seuil 4,5:1 --
 * classic 13,3:1 ; mint 8,4:1 ; vegas 14,3:1. Nom du bloc Quiz (--primary,
 * fond compose avec 18% de --primary en plus), seuil 3:1 (19px gras) --
 * classic 5,6:1 ; mint 3,8:1 ; vegas 10,0:1. */
#nv-accueil .nv-bloc-sous {
    display: block;
    line-height: 1.2;
    font-size: 13px;
    font-weight: 400;
    color: var(--text-main);
}

.nv-bloc-principal {
    border-color: var(--primary);
    background-image: linear-gradient(160deg, color-mix(in srgb, var(--primary) 18%, transparent), transparent);
}

.nv-bloc-principal .nv-bloc-nom {
    color: var(--primary);
}

/* Forme compacte (utilisateur, 2026-09-26, arret 2 de la passe 2) : le
 * contenu d'un bloc ne fixe plus sa hauteur (container-type: size ci-dessus),
 * et s'adapte a la hauteur recue par deux requetes de conteneur (hauteurs DE
 * CONTENU, rembourrage et bordure -- 24px -- exclus). Le nom ne se masque
 * JAMAIS. Ces deux blocs @container doivent rester APRES toutes les regles
 * de base des blocs ci-dessus : @container n'ajoute aucune specificite, donc
 * chaque regle porte une specificite au moins egale a celle qu'elle
 * surcharge -- sinon les requetes ne s'appliquent jamais (VERDICT_02,
 * constat 1). S1 = hauteur de contenu complete du bloc le plus haut
 * (« Premiers cours »), moins 1px, mesuree le 2026-09-26 dans l'application
 * (375 x 812, bloc sans requete active, invite) : somme des hauteurs rendues
 * (getBoundingClientRect) de l'icone (43,1875px), du nom (45,59375px), du
 * sous-titre (15,59375px) et de leurs deux ecarts (6px chacun) = 116,375px,
 * arrondie au pixel entier inferieur moins 1px : 115px (recopiee dans
 * e2e/test_nouveau_visuel_accueil.py, S1_PX -- une seule source de mesure
 * pour les deux, Reserve acceptee n° 2). */
@container (max-height: 115px) {
    #nv-accueil .nv-bloc .nv-bloc-sous {
        display: none;
    }
    #nv-accueil .nv-bloc .nv-bloc-icone {
        font-size: 28px;
    }
}

@container (max-height: 89px) {
    #nv-accueil .nv-bloc .nv-bloc-icone {
        font-size: 22px;
    }
    #nv-accueil .nv-bloc .nv-bloc-nom {
        font-size: 17px;
    }
}

/* Bandeau Aide -- le bleu de l'Aide tient au cadre et au fond ; titre et
 * « Voir ↗ » en --text-main (et non --accent-help, qui tombe entre 2,3 et
 * 4,2:1 selon la charte sur ce fond -- rapport de passe 1, constat 2 ;
 * Journal n° 15). Contrastes mesures le 2026-09-26 (375 x 812, fond =
 * --accent-help a 12% compose sur l'extremite la plus defavorable de
 * --bg-gradient) : titre / texte / « Voir ↗ » (--text-main), seuil 4,5:1 --
 * classic 7,0:1 ; mint 5,2:1 ; vegas 10,1:1. */
.nv-bandeau-aide {
    flex: none;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    border-radius: 18px;
    text-align: left;
    font: inherit;
    width: 100%;
    border: 2px solid var(--accent-help);
    background: color-mix(in srgb, var(--accent-help) 12%, transparent);
}

.nv-bandeau-aide:hover {
    background: color-mix(in srgb, var(--accent-help) 20%, transparent);
}

.nv-bandeau-aide-icone {
    flex: none;
    font-size: 30px;
}

.nv-bandeau-aide-texte {
    flex: 1 1 auto;
    min-width: 0;
}

.nv-bandeau-aide-texte strong {
    display: block;
    font-size: 16px;
    font-weight: 700;
    color: var(--text-main);
}

.nv-bandeau-aide-texte small {
    display: block;
    font-size: 13px;
    color: var(--text-main);
    line-height: 1.35;
    margin-top: 2px;
}

.nv-bandeau-aide-voir {
    flex: none;
    font-size: 13px;
    font-weight: 700;
    color: var(--text-main);
    white-space: nowrap;
}

/* Pages du nouveau visuel, encore vides : titre et lien retour seuls. */
.nv-page {
    padding: 16px;
}

/* ===========================================================================
 * Habillage commun (sous-chantier 00-bis, 2026-09-26) -- plan, § 4.
 * =========================================================================== */

/* Rangée des cycles : façade peinte par public/app/nv_main.js (§ 3) sur les
 * pastilles existantes (#levels-container ou #lessons-cycle-filter). Retour
 * à la ligne admis en dernier recours : une pastille passe sous les autres
 * plutôt que de sortir de la colonne ou d'être cachée par un défilement
 * horizontal (Journal n° 9 et n° 18). */
.nv-cycles {
    flex: none;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}

.nv-cycles-titre {
    flex: none;
    text-align: center;
    color: var(--text-main);
    font-weight: 400;
}

.nv-cycle {
    min-height: 44px;
    border-radius: 999px;
    border: 2px solid var(--chip-inactive-border);
    background: transparent;
    color: var(--text-main);
    /* font: inherit -- sans elle, ce <button> ne recevrait pas la police de
     * la page (regle de base des boutons), a la difference des pastilles de
     * cycle actuelles, qui sont des <label> (heritent nativement). Meme
     * parade que .cycle-filter-chip (public/styles.css). La taille est
     * reposee APRES `font`, qui la remettrait sinon a celle de la page. */
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    padding: 8px 12px;
    white-space: nowrap;
    cursor: pointer;
}

/* Cadenas dessiné recopié de la pastille source (nv_main.js, peindreCycles) :
 * ce bouton n'est pas en flex, l'espace avant le cadenas se pose ici. */
.nv-cycle .cadenas-cycle {
    margin-left: 0.3em;
}

.nv-cycle[aria-pressed="true"] {
    background: var(--primary);
    border-color: var(--primary);
    color: var(--btn-text-color);
}
.nv-cycle[aria-pressed="true"]::before {
    content: "✓ ";
}

/* SEF (non déployé) seul : jamais une pastille active, que la source ne
 * coche jamais (Journal n° 8, même règle que l'ancien visuel). */
.nv-cycle.nv-cycle-inerte {
    opacity: 0.55;
}

/* En-tête de page « ‹ Accueil + titre », posé par public/app/nv_socle.js
 * (§ 2) sur les quatre pages autres que l'accueil. */
.nv-page-tete {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: center;
    gap: 8px;
}

.nv-retour {
    justify-self: start;
    /* Réserve R1 (plan, § 11) : sans fond explicite, ce <button> prendrait
     * le gris clair par défaut du navigateur, qui ferait tomber le contraste
     * de son texte --text-main vers 1:1 sous Feutre Vert et Feutre Menthe. */
    background: transparent;
    border: 2px solid var(--chip-inactive-border);
    color: var(--text-main);
    /* font: inherit -- même motif que .nv-cycle ci-dessus. */
    font: inherit;
    border-radius: 999px;
    padding: 5px 12px 5px 8px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
}

.nv-page-titre {
    font-size: 18px;
    font-weight: 700;
    text-align: center;
    line-height: 1.15;
}

/* --text-muted à même le fond de page passe sous 4,5:1 dès le haut de
 * --bg-gradient, sous Feutre Vert (≈ 3,6:1) comme sous Feutre Menthe
 * (≈ 2,6:1) -- la distinction avec le titre tient donc par la taille et la
 * graisse, pas par la couleur (CORRECTIF_03, F3). */
.nv-page-titre small {
    display: block;
    color: var(--text-main);
    font-weight: 400;
    font-size: 12.5px;
}

/* Masque visuellement un texte sans le retirer de l'arbre d'accessibilité
 * (chantier interface__pastille-mes-stats, 2026-09-28) -- contrairement à
 * display: none, qui le retirerait aussi des lecteurs d'écran. Motif
 * standard. */
.nv-visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
    padding: 0;
    margin: -1px;
}

/* Barre du bas : deux onglets insérés par public/app/nv_main.js (§ 3 bis),
 * Cours masqué. Aucun style en ligne ne vise #tab-lessons : le masquer ici
 * ne casse pas ui.js, qui pilote #tab-premium de la même façon (interdit
 * hérité du socle, plan § 4). */
body.nv-actif #tab-lessons {
    display: none;
}

/* !important NÉCESSAIRE : body.theme-vegas .nav-tab impose sa couleur en
 * !important (public/styles.css) ; l'id l'emporte alors par la spécificité. */
body.nv-actif #nv-tab-aide {
    color: var(--accent-help) !important;
}

/* ===========================================================================
 * Page Quiz (sous-chantier 02_page-quiz, 2026-09-26) -- plan, § 4. Aucune
 * couleur : uniquement des var(--…) de rôles existants (§ 5 du plan).
 * Aucun --text-muted sur cette page (motif de 00-bis, Journal n° 21 : sous
 * 4,5:1 à même le fond) : les petits textes prennent --text-main, graisse
 * normale, et se distinguent par la taille.
 * =========================================================================== */
/* Écart sous la rangée des cycles (02-bis) : 12px, comme le gap de l'accueil. */
.nv-quiz-grille {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin-top: 12px;
}

.nv-etape[data-nv-etape="type"],
.nv-etape[data-nv-etape="themes"],
.nv-etape.nv-etape-seule {
    grid-column: 1 / -1;
}

/* Sans elle, une règle display de la carte battrait l'attribut hidden. */
.nv-etape[hidden] {
    display: none;
}

/* Contraste mesuré le 2026-09-26, méthode de 00-bis (§ 5 du plan) : deux
 * fonds -- le haut de --bg-gradient de la charte pour .nv-quiz-recap (hors
 * des étapes, à même la page), et --bg-card composé sur ce même haut pour
 * .nv-etape-titre small (dans une étape, --bg-card étant translucide sous
 * Feutre Vert et Feutre Menthe). --text-main, seuil 4,5:1 :
 * .nv-quiz-recap -- classic 8,18:1 ; mint 5,77:1 ; vegas 14,64:1.
 * .nv-etape-titre small -- classic 13,31:1 ; mint 8,39:1 ; vegas 14,64:1
 * (vegas : --bg-card quasi opaque, ratio proche de celui de la page nue). */
.nv-etape {
    background: var(--bg-card);
    border: 2px solid var(--bg-card-border);
    border-radius: 16px;
    padding: 10px;
    min-width: 0;
}

.nv-etape-titre {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 8px;
    font-size: 14.5px;
    font-weight: 700;
}

.nv-etape-titre small {
    font-size: 12.5px;
    font-weight: 400;
}

.nv-etape-num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: var(--primary);
    color: var(--btn-text-color);
    font-size: 14px;
    font-weight: 800;
}

/* Motif de .nv-cycle ci-dessus : font: inherit d'abord, taille reposée
 * ensuite sur chaque famille ou sur ses enfants. */
.nv-quiz-type,
.nv-quiz-mode,
.nv-nombre,
.nv-theme {
    font: inherit;
    background: transparent;
    border: 2px solid var(--chip-inactive-border);
    color: var(--text-main);
    cursor: pointer;
}

.nv-quiz-types {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 8px;
}

.nv-quiz-type {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    min-height: 60px;
    border-radius: 12px;
}

.nv-quiz-type .nv-quiz-ico {
    font-size: 21px;
}

.nv-quiz-type .nv-quiz-lib {
    font-size: 13px;
    font-weight: 700;
}

.nv-quiz-modes {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.nv-quiz-mode {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    min-height: 44px;
    border-radius: 12px;
}

.nv-quiz-mode .nv-quiz-lib {
    font-size: 14px;
    font-weight: 700;
}

.nv-quiz-mode small {
    font-size: 11.5px;
    font-weight: 400;
}

.nv-quiz-nombres {
    display: flex;
    gap: 8px;
}

.nv-nombre {
    flex: 1;
    min-height: 48px;
    border-radius: 12px;
    font-size: 20px;
    font-weight: 800;
}

.nv-theme {
    min-height: 34px;
    padding: 6px 12px;
    border-radius: 999px;
    font-size: 14px;
}

/* Choisi -- même couple que la pastille de cycle (Journal n° 4). */
.nv-quiz-type[aria-pressed="true"],
.nv-quiz-mode[aria-pressed="true"],
.nv-nombre[aria-pressed="true"],
.nv-theme[aria-pressed="true"] {
    background: var(--primary);
    border-color: var(--primary);
    color: var(--btn-text-color);
}

.nv-theme[aria-pressed="true"]::before {
    content: "✓ ";
}

.nv-quiz-type[aria-pressed="true"] .nv-quiz-lib::before,
.nv-quiz-mode[aria-pressed="true"] .nv-quiz-lib::before {
    content: "✓ ";
}

.nv-theme-tous {
    font-weight: 700;
}

.nv-theme-inerte {
    opacity: 0.55;
}

/* La rangée coupée en bas signale la suite : pas de data-zone-defilement
 * ici (Journal n° 3 de 02), la flèche de défilement suit la page.
 * Hauteur (sous-chantier 02-bis, 2026-09-26) : 220px = cinq rangées
 * pleines de pastilles de 34px espacées de 7px (198px), plus le haut
 * de la sixième. Si la hauteur d'une pastille change, refaire le calcul.
 * Mesure de la hauteur de page (02-bis) : page Quiz à 375 × 812, compte
 * empreinte_libre, cycle 2&3 (zone à 942px) : bouton à 741px avant 02-bis,
 * 873px après, pour 740px visibles. La page ne tient déjà pas avant (741 >
 * 740) ; le resserrement borné de 02 ne suffirait pas à couvrir les 132px
 * ajoutés et n'est donc pas appliqué : le défilement reste admis
 * (Journal n° 1). */
.nv-quiz-themes {
    display: flex;
    flex-wrap: wrap;
    gap: 7px;
    max-height: 220px;
    overflow-y: auto;
    padding-right: 4px;
}

.nv-quiz-unite {
    display: block;
    text-align: center;
    font-size: 12px;
}

.nv-quiz-recap {
    text-align: center;
    font-size: 13px;
    color: var(--text-main);
    margin: 10px 0 8px;
}

.nv-quiz-note {
    text-align: center;
    font-size: 12px;
    color: var(--text-main);
    margin: 4px 0 0;
}

.nv-quiz-commencer {
    width: 100%;
}

/* ===========================================================================
 * Mes thèmes (sous-chantier 03_mes-themes, 2026-09-26) -- plan, § 5. Un seul
 * rendu (public/app/ui.js) alimente cette page comme l'ancien écran ; ce
 * fichier ne fait que la mettre en page. Aucune couleur neuve : var(--text-main),
 * var(--accent-help) et var(--primary), rôles déjà existants.
 * =========================================================================== */

/* Espace sous l'en-tête (chantier interface__lien-mes-stats, 2026-09-28),
 * scopé à cette page seule -- .nv-page-tete est partagé par trois autres
 * pages (public/app/nv_socle.js, PAGES). Posé ICI plutôt que sur
 * .nv-mt-tuiles : #nv-mt-tout-maitrise s'intercale entre l'en-tête et les
 * tuiles quand il s'affiche, et une marge côté tuiles ne l'aurait pas
 * décollé du titre. */
#nv-screen-mes-themes .nv-page-tete {
    margin-bottom: 16px;
}

/* Pastille « Mes Stats » (chantier interface__pastille-mes-stats,
 * 2026-09-28) : 3ᵉ colonne de grille, symétrique de .nv-retour à gauche.
 * Scopé à Mes thèmes -- .nv-page-tete est partagé par trois autres pages
 * (public/app/nv_socle.js, PAGES), qui ne passent pas d'action et ne
 * reçoivent donc pas cette 3ᵉ colonne. */
#nv-screen-mes-themes .nv-page-tete {
    grid-template-columns: auto 1fr auto;
}

.nv-mt-pastille-stats {
    justify-self: end;
    /* Même motif que .nv-retour ci-dessus : sans fond explicite, ce
     * <button> prendrait le gris clair par défaut du navigateur. */
    background: transparent;
    border: 2px solid var(--chip-inactive-border);
    color: var(--text-main);
    font: inherit;
    border-radius: 999px;
    padding: 5px 12px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
}

/* État initial masqué -- ces cinq blocs sont pilotés en style.display par
 * chargerMesThemes() (public/app/ui.js), à chaque arrivée sur la page. */
#nv-mt-tout-maitrise,
#nv-mt-faibles,
#nv-mt-erreurs,
#nv-mt-rappel,
#nv-mt-badges {
    display: none;
}

/* Même dégagement que l'ancien écran (style en ligne de screen-themes-progress,
 * index.html) : la barre du bas ne cache pas la dernière carte. */
#nv-screen-mes-themes {
    padding-bottom: 80px;
}

/* Blocs repris de l'écran actuel, mêmes valeurs que ses styles en ligne
 * (index.html, section screen-themes-progress), écrites ici en classe. */
.nv-mt-bloc {
    padding: 16px;
    border-radius: 12px;
    margin-bottom: 16px;
}

#nv-mt-tout-maitrise {
    text-align: center;
}

#nv-mt-badges {
    margin-top: 16px;
    margin-bottom: 0;
}

#nv-mt-tout-maitrise-titre {
    font-size: 15px;
    font-weight: 700;
    margin-bottom: 6px;
    color: var(--text-main);
}

#nv-mt-tout-maitrise-sous {
    font-size: 13px;
    line-height: 1.5;
    margin-bottom: 12px;
    color: var(--text-main);
}

#nv-mt-tout-maitrise-bouton {
    width: 100%;
    font-size: 14px;
    font-weight: 700;
}

/* var(--text-main) et non --text-muted de l'écran actuel : son fond
 * .themes-review-hint-tone est un voile clair posé sur le fond de page, où
 * --text-muted tombe sous 4,5:1 sous Feutre Vert et Feutre Menthe, comme pour
 * le compteur ci-dessous -- écart assumé au « comme aujourd'hui », limité à
 * la teinte. Fond, rayon et padding : ceux de .themes-review-hint-tone déjà
 * posée sur ce nœud (index.html, même famille de bandeau). */
.nv-mt-rappel {
    font-size: 12px;
    line-height: 1.5;
    color: var(--text-main);
    border-radius: 10px;
    padding: 10px 14px;
    margin-bottom: 16px;
}

/* var(--text-main) et non --text-muted, qui tombe sous 4,5:1 posé à même le
 * fond sous Feutre Vert et Feutre Menthe (mesure de 00-bis, § 5) : ici le
 * compteur n'est pas dans une carte. */
.nv-mt-compteur {
    font-size: 14px;
    color: var(--text-main);
    margin: 0;
}

.nv-mt-tuiles,
.nv-mt-ligne {
    margin-bottom: 14px;
}

.nv-mt-tuiles {
    display: flex;
    gap: 10px;
}

.nv-mt-tuiles > * {
    flex: 1 1 0;
}

/* .nv-mt-tuile hérite de card-glass sa marge intérieure (12px, que la remise
 * à zéro globale * { padding: 0 } ôterait sinon à un <button>), son flou, son
 * ombre et le même fond que les cartes de thème sous les trois chartes (gris
 * acier sous Feutre Blanc). */
.nv-mt-tuile {
    width: 100%;
    margin-bottom: 0;
    color: var(--text-main);
    font: inherit;
    font-weight: 700;
    text-align: center;
    cursor: pointer;
}

/* !important NÉCESSAIRE : body.theme-vegas .card-glass impose sa bordure en
 * !important (public/styles.css) ; à !important égal, l'identifiant l'emporte
 * par la spécificité, sous les trois chartes. */
body.nv-actif #nv-mt-faibles .nv-mt-tuile,
body.nv-actif #nv-mt-erreurs .nv-mt-tuile {
    border: 2px solid var(--primary) !important;
}

.nv-mt-ligne {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}

.nv-mt-aide-barres {
    background: transparent;
    border: 2px solid var(--accent-help);
    color: var(--text-main);
    font: inherit;
    font-weight: 700;
    border-radius: 999px;
    white-space: nowrap;
    flex: none;
}

#nv-screen-mes-themes .theme-card-legend {
    cursor: pointer;
}

/* Fenêtre d'explication, montée du bas -- même voile que .modal-overlay
 * (public/styles.css), masquée par défaut. */
body.nv-actif .nv-fenetre-barres.nv-ouvert {
    display: flex;
    align-items: flex-end;
    padding: 0;
}

/* margin: 0 auto -- marges latérales automatiques, marges haute et basse
 * nulles : annule aussi la marge basse de .card-glass. */
.nv-feuille {
    width: 100%;
    max-width: 480px;
    margin: 0 auto;
    max-height: 85vh;
    overflow-y: auto;
    border-radius: 20px 20px 0 0;
    color: var(--text-main);
    text-align: left;
}

/* Titre + bouton ✕ sur une seule ligne (la remise à zéro globale
 * `* { margin: 0 }` mettrait sinon le bouton, `display: block` par défaut
 * pour un <h2>, sur la ligne suivante). */
.nv-barres-entete {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 12px;
}

.nv-barres-fermer {
    background: transparent;
    border: none;
    font: inherit;
    font-size: 18px;
    color: var(--text-main);
    cursor: pointer;
    flex: none;
}

/* Espacement des paragraphes et du sous-titre -- même remise à zéro globale
 * que ci-dessus, sans marge par défaut. */
.nv-feuille p {
    margin: 0 0 12px;
}

.nv-feuille h3 {
    margin: 4px 0 8px;
}

/* Exemples de boutons dans la fenêtre : inertes, jamais cliquables.
 * `inline-block` -- en `inline` (par défaut pour un <span>), le padding
 * vertical de .theme-card-action ne compte pas dans la hauteur de ligne : il
 * chevauche alors le texte de la ligne voisine au lieu de l'écarter. */
.nv-feuille .theme-card-action {
    display: inline-block;
    cursor: default;
}

/* ===========================================================================
 * Premiers cours (sous-chantier 04_premiers-cours, 2026-09-26) -- plan, § 6.
 * Aucun rôle nouveau : les tuiles reprennent --bg-card / --bg-card-border des
 * blocs de l'accueil (01) et les rôles déjà déclarés pour l'ancien écran
 * (public/styles.css) pour le groupe et les avis. Aucun --text-muted ni
 * --text-pc-notice sur cette page (même motif que 00-bis et 02).
 * =========================================================================== */
.nv-pc-intro {
    margin: 0 4px 12px;
    font-size: 13.5px;
    color: var(--text-main);
}

.nv-pc-avis {
    margin: 0 0 12px;
    padding: 10px 12px;
    border-radius: 12px;
    font-size: 12.5px;
    color: var(--text-main);
    background: var(--surface-pc-notice);
    border: 1px dashed var(--border-pc-notice);
}

.nv-pc-avis[hidden] {
    display: none;
}

.nv-pc-tuiles {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
}

.nv-pc-tuile {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    min-height: 118px;
    padding: 14px 8px;
    border-radius: 18px;
    text-align: center;
    font: inherit;
    background: var(--bg-card);
    border: 2px solid var(--bg-card-border);
    color: var(--text-main);
    cursor: pointer;
}

.nv-pc-tuile:hover {
    background: var(--surface-pc-btn-hover);
    border-color: var(--border-pc-btn-hover);
}

.nv-pc-tuile-groupe {
    background: var(--surface-pc-btn-groupe);
    border-style: dashed;
    border-color: var(--border-pc-btn-groupe);
}

.nv-pc-tuile-groupe:hover {
    background: var(--surface-pc-btn-groupe-hover);
    border-color: var(--border-pc-btn-groupe-hover);
}

.nv-pc-ico {
    font-size: 34px;
    line-height: 1.2;
}

.nv-pc-nom {
    font-size: 15.5px;
    font-weight: 800;
    line-height: 1.2;
}

.nv-pc-sous {
    font-size: 12px;
    font-weight: 400;
    color: var(--text-main);
}

.nv-pc-pied {
    margin: 14px 0 0;
    font-size: 13px;
    color: var(--text-main);
}

/* ===========================================================================
 * Bibliotheque de cours (sous-chantier 05_bibliotheque-cours, 2026-09-26) --
 * plan, § 4. La bibliotheque se loge dans l'ecran actuel #screen-lessons-menu :
 * ces regles masquent son ancien habillage sous body.nv-actif, sans toucher
 * aux cartes de cours (.lesson-item-card), dont l'affichage reste pilote en
 * style en ligne par le filtre de cycle et par les cadenas (ui.js, router.js).
 * Aucune couleur, aucune propriete personnalisee declaree.
 * =========================================================================== */

/* !important NECESSAIRE : la barre porte display: flex en style en ligne
 * (index.html). */
body.nv-actif #screen-lessons-menu > .lessons-menu-topbar {
    display: none !important;
}

/* Sous-titre de l'ancienne page, repris dans l'en-tete de #nv-bibliotheque. */
body.nv-actif #screen-lessons-menu .lessons-list-scrollable > p {
    display: none;
}

/* Masque, jamais retire : la facade des cycles (public/app/nv_main.js) lit
 * ces pastilles et leur renvoie les clics ; retirees, la rangee du haut
 * serait vide sans erreur. */
body.nv-actif #lessons-cycle-filter {
    display: none;
}

#nv-bibliotheque {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 12px 0 16px;
}
