/* Les Loustics — feuille de style globale.
   Bootstrap 5 (public/assets/vendor/bootstrap) est la couche de base : on ne
   réécrit pas ce qu'il fournit, on le personnalise par ses variables --bs-*.
   Charte « aquarelle douce » tirée des illustrations (docs/source/illustrations).
   Aucun style inline dans les vues : tout vit ici (règle du workspace). */

/* ---------- Polices auto-hébergées (public/assets/fonts, licence OFL) ---------- */
/* Deux familles, deux rôles (directive du porteur, 25-26/08) :
     - Merienda (variable 300-900, « Contes et Légendes ») = h1/h2 du jeu et des pages vitrine ;
       manuscrite, donc JAMAIS de corps de texte — la lisibilité des 3-8 ans passe d'abord.
     - Manrope = tout le reste, et les h1/h2 des pages sérieuses (espace parent, légal, suivi).
   Nunito a été retirée du projet le 26/08 : plus aucune règle ni fichier. */
@font-face { font-family: 'Merienda'; src: url('/assets/fonts/merienda/Merienda-Variable-latin.woff2') format('woff2'); font-weight: 300 900; font-style: normal; font-display: swap; unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Merienda'; src: url('/assets/fonts/merienda/Merienda-Variable-latin-ext.woff2') format('woff2'); font-weight: 300 900; font-style: normal; font-display: swap; unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Manrope'; src: url('/assets/fonts/manrope/Manrope-Medium.woff2') format('woff2'); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: 'Manrope'; src: url('/assets/fonts/manrope/Manrope-SemiBold.woff2') format('woff2'); font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: 'Manrope'; src: url('/assets/fonts/manrope/Manrope-Bold.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'Manrope'; src: url('/assets/fonts/manrope/Manrope-ExtraBold.woff2') format('woff2'); font-weight: 800; font-style: normal; font-display: swap; }

/* ---------- Charte : jetons puis variables Bootstrap ---------- */
:root {
    --lou-papier: #FBF6EE;
    --lou-encre: #3F3A36;
    --lou-sapin: #4F8A6B;
    --lou-sapin-fonce: #3E6F55;
    --lou-sapin-profond: #33604A;
    --lou-ocre: #E2A24B;
    --lou-ocre-fonce: #C98A35;
    --lou-ciel: #7FB4D9;
    --lou-petale: #F2A7B5;
    --lou-loup: #8C8780;
    --lou-loup-clair: #D9D2C7;
    /* #8C8780 sur le papier ne donne que 3,3:1 : sous le seuil AA du texte courant (4,5:1).
       Il reste la couleur des filets et des bordures ; le TEXTE gris prend cette version
       assombrie, qui monte à 5,1:1 (tâche 8e). */
    --lou-loup-texte: #6E6862;
    /* Même raison pour l'ocre : #C98A35 ne donne que 2,7:1 sur le papier. Il reste la couleur
       des bordures, des pastilles et des pictogrammes décoratifs ; les MOTS en ocre (étiquettes
       de section, numéros d'étape) prennent cette version brûlée, à 5,5:1. */
    --lou-ocre-texte: #8A5A12;

    /* Le beige de la charte. Plus aucune règle ne s'en sert depuis la 8k — les bandes de la
       vitrine sont passées au blanc, le pied au gris — mais c'est la teinte des fonds de fiches
       et des planches du dépôt de référence : le retirer obligerait à la réinventer à la
       première illustration qui en aura besoin. */
    --lou-parchemin: #F4EADB;

    /* Le pied de page est GRIS depuis la tâche 8k (point 8 du porteur, « comme RapidoImmo » :
       fond gris clair, texte neutre, marque en accent au survol). Des gris NEUTRES et non un
       beige plus foncé : le pied doit se lire comme la note en bas de page qu'il est, et non
       comme une neuvième bande de la charte.
       Les deux noms trompent, et c'est le seul piège de ce bloc : --lou-gris-titre habille les
       LIENS du pied, tandis que les titres de colonne (.lou-foot h2) partagent la teinte du
       texte courant. Contrastes recalculés sur --lou-gris-pied #EDEDEB :
       titres de colonne et texte (--lou-gris-texte #5C5A57) 5,86:1, liens au repos
       (--lou-gris-titre #4B4845) 7,75:1, liens au survol (--lou-sapin-fonce #3E6F55) 4,96:1
       — tous au-dessus de AA. */
    /* Le rouge du drapeau (porteur, 19/09/2026) : #CE1126, la teinte usuelle de la croix suisse.
       Le rouge pur #FF0000 ne tient PAS le contraste sur le gris du pied — 3,41:1, sous le seuil
       AA de 4,5 pour du texte courant. Celui-ci donne 4,80:1 sur le pied et 5,23:1 sur le papier :
       il se lit comme le drapeau, et il se lit tout court. */
    --lou-rouge-suisse: #CE1126;
    --lou-gris-pied: #EDEDEB;
    --lou-gris-bord: #DCDCD9;
    --lou-gris-titre: #4B4845;
    --lou-gris-texte: #5C5A57;

    /* LES SEPT COULEURS DE DOMAINE, telles que app/Data/domaines.php les déclare (champ
       `couleur`). Elles sont la MÊME donnée que celle qui teinte les pastilles de suivi, les
       lieux de la carte pédagogique et les quartiers de la rosace : un parent qui passe d'un
       écran à l'autre doit retrouver le même bleu pour les langues.
       Publiées ici pour que les feuilles n'aient plus à recopier l'hexadécimal. (Les feuilles
       antérieures — suivi.css, jeu.css, vitrine.css — les portent encore en dur : leur reprise
       est un chantier à part, pas un effet de bord de celui-ci.) */
    --lou-dom-l: #7FB4D9;
    --lou-dom-msn: #E2A24B;
    --lou-dom-shs: #8FB996;
    --lou-dom-a: #F2A7B5;
    --lou-dom-cm: #4F8A6B;
    --lou-dom-fg: #A58BD0;
    --lou-dom-en: #8C8780;

    /* Fonds de la charte (tâche 8e). Le porteur a demandé la fin des cartes à fond blanc :
       une carte est désormais une feuille de papier — un dégradé très court entre deux crèmes,
       assez clair pour se détacher du corps de page, jamais blanc. */
    --lou-carte-haut: #FFFCF6;
    --lou-carte-bas: #FAF2E4;
    --lou-ombre: 0 .5rem 1.5rem rgba(63, 58, 54, .09);
    --lou-ombre-haute: 0 1rem 2.5rem rgba(63, 58, 54, .18);
    --lou-carte: linear-gradient(180deg, var(--lou-carte-haut), var(--lou-carte-bas));

    /* Hauteur de la barre fixe : une seule valeur, lue par le décalage du corps, par les
       ancres (scroll-padding) et par les écrans qui se calent sur la hauteur de fenêtre. */
    --lou-entete-h: 72px;

    --bs-body-bg: var(--lou-papier);
    --bs-body-color: var(--lou-encre);
    /* Familles : --lou-titre est la manuscrite « féérique », --lou-texte la sérieuse.
       Repli réel : cursive pour la manuscrite, sans-serif pour le texte. */
    --lou-titre: 'Merienda', 'Segoe Script', 'Bradley Hand', cursive;
    --lou-texte: 'Manrope', 'Segoe UI', Arial, sans-serif;

    --bs-body-font-family: var(--lou-texte);
    --bs-body-font-size: 1.05rem;
    --bs-primary: var(--lou-sapin);
    --bs-primary-rgb: 79, 138, 107;
    --bs-secondary: var(--lou-ocre);
    --bs-secondary-rgb: 226, 162, 75;
    --bs-link-color: var(--lou-sapin-fonce);
    --bs-link-hover-color: var(--lou-sapin);
    /* Bootstrap 5.3 calcule la couleur des liens sur la variante -rgb
       (a { color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1)) }) :
       sans ces deux lignes, les liens restent au bleu du thème par défaut. */
    --bs-link-color-rgb: 62, 111, 85;        /* --lou-sapin-fonce */
    --bs-link-hover-color-rgb: 79, 138, 107; /* --lou-sapin */
    --bs-border-radius: 1rem;
    --bs-border-radius-sm: .75rem;
    --bs-border-radius-lg: 1.5rem;
    --bs-heading-color: var(--lou-encre);

    /* ─────────────────────────────────────────────────────────────────────────────────────
       ÉCHELLE TYPOGRAPHIQUE (harmonisation vitrine, chantier « vitrine »).
       Le porteur en revue live : « quasiment une police, une taille, une couleur par
       paragraphe et par bouton. » vitrine.css portait ~20 tailles de texte. On les ramène à
       SIX marches nommées, et toute la vitrine (accueil, connexion, inscription, catalogue)
       snappe son texte dessus. Ces jetons ne valent QUE pour le TEXTE : une taille d'icône
       (`.bi { font-size }`) dimensionne un dessin, jamais un mot, et n'y touche pas.
       Base = --bs-body-font-size (1.05rem), pour que corps de texte et jeton coïncident. */
    --lou-fs-legend:  .8rem;    /* micro-étiquettes capitales, pastilles, code PER, méta fine */
    --lou-fs-petit:   .9rem;    /* texte secondaire : légendes d'image, mentions légales, méta */
    --lou-fs-base:    1.05rem;  /* corps de texte courant (= --bs-body-font-size) */
    --lou-fs-lead:    1.2rem;   /* le paragraphe d'accroche agrandi, les intros */
    --lou-fs-titre:   1.35rem;  /* les sous-titres de bloc (h3), toujours en gras */
    --lou-fs-display: clamp(1.95rem, 4vw, 3rem); /* titre du héros, réponse « Rien. » */
}

/* Une image de contenu garde SON rapport (point 3 du porteur, tâche 8e). Les illustrations de
   l'accueil portaient width=800 height=800 en attributs et un `max-width: 100%` en CSS : la
   largeur descendait à 365 px, la hauteur restait à 800, et les louveteaux s'étiraient d'un
   facteur deux. Bootstrap 5 ne pose plus cette règle par défaut (elle vit dans .img-fluid) —
   on la remet pour tout le site. Les images dimensionnées exprès (marque, vignettes du HUD,
   paniers de tri) ont des sélecteurs plus précis, qui gagnent. */
img { max-width: 100%; height: auto; }

/* h1/h2 = la manuscrite (jeu, vitrine) ; h3+ et la marque restent en Manrope, car ce sont des
   intertitres de lecture. Merienda porte peu de graisse utile au-delà de 700 : on s'y tient. */
h1, h2 { font-family: var(--lou-titre); font-weight: 700; letter-spacing: .01em; }
h3, h4, .navbar-brand { font-family: var(--lou-texte); font-weight: 800; }
/* Pages sérieuses (espace parent, légal, suivi, authentification) : le porteur veut Manrope
   « sérieuse et pédagogique ». La classe est posée par common/header.php d'après le chemin. */
body.ambiance-serieuse h1, body.ambiance-serieuse h2 { font-family: var(--lou-texte); font-weight: 800; letter-spacing: normal; }
/* La marque est un bandeau qui PORTE le nom du site : pas de texte à côté, sinon il est écrit
   deux fois. Le nom vit dans l'attribut alt, donc reste lu par les lecteurs d'écran. */
.navbar-brand .marque { height: 44px; width: auto; max-width: 100%; }
/* Les vignettes de costume sont des rendus carrés sur fond crème : arrondies, elles cessent de
   faire un carré beige au milieu d'une carte blanche (revue de la tâche 7c). */
.tenue img, .hud-costume img { border-radius: .6rem; }
.tenue img, .hud-costume img { border-radius: 50%; }
@media (max-width: 575.98px) { .navbar-brand .marque { height: 34px; } }

/* Contraste AA (tâche 8e) : du blanc sur --lou-sapin ne donnait que 4,05:1, sous le seuil de
   4,5:1 du texte courant — et c'est l'action principale de tout le site. Le bouton descend donc
   d'un cran, sur --lou-sapin-fonce (5,8:1) ; le survol prend le vert profond. La teinte de
   marque, elle, ne bouge pas : --lou-sapin reste --bs-primary. */
.btn-primary {
    --bs-btn-bg: var(--lou-sapin-fonce); --bs-btn-border-color: var(--lou-sapin-fonce);
    --bs-btn-hover-bg: var(--lou-sapin-profond); --bs-btn-hover-border-color: var(--lou-sapin-profond);
    --bs-btn-active-bg: var(--lou-sapin-profond); --bs-btn-active-border-color: var(--lou-sapin-profond);
}
.btn-outline-primary {
    --bs-btn-color: var(--lou-sapin-fonce); --bs-btn-border-color: var(--lou-sapin);
    --bs-btn-hover-bg: var(--lou-sapin); --bs-btn-hover-border-color: var(--lou-sapin);
    --bs-btn-active-bg: var(--lou-sapin-fonce);
}
/* Le blanc sur l'ocre tombait à 2,2:1 — illisible pour de bon. L'encre de la charte y monte à
   5,1:1, et un bouton ocre à texte sombre est de toute façon plus juste : c'est la couleur des
   panneaux de bois du village, pas celle d'un bouton d'alerte. */
.btn-secondary {
    --bs-btn-bg: var(--lou-ocre); --bs-btn-border-color: var(--lou-ocre); --bs-btn-color: var(--lou-encre);
    --bs-btn-hover-bg: var(--lou-ocre-fonce); --bs-btn-hover-border-color: var(--lou-ocre-fonce);
    --bs-btn-hover-color: var(--lou-encre); --bs-btn-active-bg: var(--lou-ocre-fonce); --bs-btn-active-color: var(--lou-encre);
}
.btn-pill { border-radius: 50rem; padding-inline: 1.5rem; font-weight: 700; }
.btn-lg.btn-pill { padding-inline: 2rem; }
/* Pastilles à choix unique (R12, T8O) — cf. app/Views/common/_pills.php. Le patron de site pour
   tout réglage à valeur unique : une rangée de pilules qui s'enroule, jamais un <select>. */
.reglage-pastilles { border: 0; padding: 0; margin: 0; }
.reglage-pastilles > legend { float: none; width: auto; font-size: 1rem; margin-bottom: .5rem; }
.pastilles { display: flex; flex-wrap: wrap; gap: .5rem; }
.pastilles .btn-pill { padding-inline: 1.15rem; }
.form-label { font-weight: 700; }
.form-control, .form-select { border-color: var(--lou-loup-clair); }
.form-control:focus, .form-select:focus { border-color: var(--lou-sapin); box-shadow: 0 0 0 .25rem rgba(79, 138, 107, .25); }
/* Cases, radios et curseurs : Bootstrap écrit #0d6efd en dur dans son CSS compilé
   (aucune variable --bs-* ne le pilote), d'où ces règles explicites. */
.form-check-input:checked { background-color: var(--lou-sapin); border-color: var(--lou-sapin); }
.form-check-input:focus { border-color: var(--lou-sapin); box-shadow: 0 0 0 .25rem rgba(79, 138, 107, .25); }
input[type="range"] { accent-color: var(--lou-sapin); }
/* .form-range pose appearance:none : accent-color n'a plus prise, il faut repeindre les
   pouces. Les deux préfixes ne se regroupent pas — un sélecteur inconnu invaliderait
   toute la règle pour l'autre moteur. */
.form-range::-webkit-slider-thumb { background-color: var(--lou-sapin); }
.form-range::-moz-range-thumb { background-color: var(--lou-sapin); }
.form-range:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 .25rem rgba(79, 138, 107, .25); }
.form-range:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 .25rem rgba(79, 138, 107, .25); }

/* ---------- Navigation ---------- */
/* Le fond n'est plus blanc mais le papier de la charte, légèrement translucide : sous une barre
   FIXE, le contenu passe dessous, et un aplat blanc opaque aurait fait une bande étrangère au
   milieu d'un site crème. Le repli opaque vient d'abord, pour les moteurs sans backdrop-filter. */
.navbar-lou { background: var(--lou-papier); border-bottom: 1px solid var(--lou-loup-clair);
    min-height: var(--lou-entete-h); transition: box-shadow .2s, background-color .2s; }
@supports (backdrop-filter: blur(10px)) {
    .navbar-lou { background: rgba(251, 246, 238, .88); backdrop-filter: blur(12px) saturate(140%); }
}
.navbar-lou.nav-scrolled { box-shadow: 0 .25rem 1.25rem rgba(63, 58, 54, .12); }
.navbar-lou .nav-link { font-weight: 600; color: var(--lou-encre); }
.navbar-lou .nav-link.active { color: var(--lou-sapin-fonce); }

/* En-tête FIXE (point 1 du porteur, tâche 8e) — vitrine et espace parent seulement. Les écrans
   enfant gardent leur barre réduite dans le flux : ils se calent sur la hauteur de la fenêtre
   (.ecran-plein), et une barre fixe leur volerait deux fois la même bande.
   `scroll-padding-top` sur <html> est ce qui répare les ancres : sans lui, « Pour qui ? » se
   posait sous la barre. Il vaut aussi pour la tabulation au clavier, qu'un offset en JS rate. */
body.entete-fixe { padding-top: var(--lou-entete-h); }
body.entete-fixe .navbar-lou { position: fixed; top: 0; right: 0; left: 0; z-index: 1035; }
html { scroll-padding-top: calc(var(--lou-entete-h) + 1rem); }
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }
/* Menu déplié sur téléphone : il pend sous une barre fixe, donc il lui faut sa propre limite
   de hauteur et son propre défilement — sinon les derniers liens sortent de l'écran. */
@media (max-width: 991.98px) {
    .navbar-lou .navbar-collapse { max-height: calc(100vh - var(--lou-entete-h) - 1rem);
        max-height: calc(100dvh - var(--lou-entete-h) - 1rem); overflow-y: auto; padding-bottom: .75rem; }
}
@media (max-width: 575.98px) { :root { --lou-entete-h: 62px; } }

/* ---------- Blocs de page ---------- */
/* Les blocs propres à la VITRINE (héros, bandes, fenêtres sur le village, questions
   fréquentes, catalogue) vivent dans vitrine.css, chargée par les seules pages publiques :
   les écrans du jeu et l'espace parent n'ont aucune raison de les télécharger. */
/* Point 9 du porteur : plus aucune carte à fond blanc. Une carte est une feuille de papier —
   dégradé très court entre deux crèmes, filet ocre à peine posé, ombre légère. */
.card-lou { border: 1px solid rgba(226, 162, 75, .22); border-radius: 1.5rem; background: var(--lou-carte); box-shadow: var(--lou-ombre); }
/* CARTE BLANCHE (porteur, 18/09/2026, 23h) — authentification et contact. `.card-lou` pose un
   dégradé crème qui se confondait avec le papier de la page ; le blanc franc rend son premier
   plan au formulaire. `--bs-body-bg` est redéfini SUR LA CARTE, et non `.form-control` repeint :
   c'est la variable que Bootstrap lit pour les champs, leur état de focus et les cases à cocher,
   donc une ligne suffit là où il en aurait fallu cinq — et rien ne dérive le jour où un champ
   d'un autre type entre dans la carte. */
.carte-blanche { background: #fff; --bs-body-bg: #fff; }
/* PAGE BLANCHE (porteur, 18/09/2026, 23h) : la bande entière derrière le contenu, d'un bord à
   l'autre, et pas seulement la largeur du conteneur — sinon le blanc se lit comme une carte
   géante posée sur le papier. Les champs suivent par la même variable que les cartes. */
.page-blanche { background: #fff; --bs-body-bg: #fff; padding-bottom: 4rem; }
/* D'UN BORD À L'AUTRE, MÊME QUAND LE MAIN EST LE CONTENEUR (19/09/2026). Les pages de l'espace
   parent portent `page-blanche` sur un `<main class="container">` : le blanc s'arrêtait alors à
   1140 px et se lisait comme une carte géante posée sur le papier. Deux ombres portées sans flou
   ni étalement recopient la boîte à gauche et à droite : elles peignent EXACTEMENT la hauteur du
   main, sans toucher au bandeau ni au pied, sans déplacer quoi que ce soit et sans créer de
   contexte d'empilement — ce qu'un `::before` en `position: absolute` aurait fait, au risque de
   déranger les pages qui positionnent déjà leurs enfants (rosace, parcours).
   Une ombre ne compte pas dans la zone de défilement : aucune barre horizontale n'apparaît. */
.page-blanche.container, .page-blanche.container-fluid { box-shadow: 0 0 0 100vmax #fff; clip-path: inset(0 -100vmax); }
/* Les deux pieds portent une marge haute (4 rem pour le pied public, 3 rem pour celui, réduit à
   une ligne, de l'espace parent) : sur le papier crème l'écart ne se voit pas ; sous une page
   blanche, il devenait une bande crème entre le contenu et le pied, comme si le blanc s'arrêtait
   trop tôt. L'écart est repris en padding PAR la page blanche — même respiration, bonne couleur.
   Le pied de l'espace parent n'a pas de fond à lui : il se pose donc sur le papier, en dessous du
   blanc, ce qui le détache de la page au lieu d'en faire une bande orpheline. */
.page-blanche + .lou-foot, .page-blanche + .site-footer--simple { margin-top: 0; }
/* La déconnexion n'est plus qu'une icône (porteur, 19/09/2026) : sans texte à côté, elle doit
   rester une cible franche et se lire aussi bien que les mots voisins — d'où la taille et un peu
   d'air autour. En menu replié (téléphone), Bootstrap empile les entrées et l'icône seule serait
   perdue sur sa ligne : le mot caché redevient visible. */
.lou-deconnexion .bi { font-size: 1.35rem; line-height: 1; vertical-align: -.15rem; }
.lou-deconnexion { padding-inline: .75rem; }
@media (max-width: 991.98px) {
    .lou-deconnexion .visually-hidden { position: static !important; width: auto !important; height: auto !important;
        margin: 0 !important; overflow: visible !important; clip: auto !important; white-space: normal !important; }
    .lou-deconnexion .bi { margin-right: .4rem; }
}
/* Un textarea en étiquette flottante : Bootstrap impose 58 px de haut à tout `.form-control`
   flottant, ce qui écrase l'attribut `rows`. La hauteur se redonne ici — jamais en `style=`
   dans la vue, que la CSP refuse. */
.form-floating > textarea.form-control { height: 11rem; }
.card-lou .bi { font-size: 2rem; color: var(--lou-ocre); }
/* … mais PAS l'icône d'un bouton : dans une carte, `.card-lou .bi` la repeignait en ocre — donc
   en ocre sur ocre pour un .btn-secondary, c'est-à-dire invisible. Un pictogramme de bouton suit
   toujours son bouton, en couleur comme en taille. */
.card-lou .btn .bi { color: inherit; font-size: inherit; }

/* ---------- Pages d'authentification ---------- */
/* `d-flex align-items-center` dans la vue (audit R2). La hauteur, elle, RESTE ici : c'est une
   fenêtre MOINS la barre du site, et aucun utilitaire de Bootstrap ne sait retrancher un jeton
   maison à `100vh` — `min-vh-100` déborderait exactement de la hauteur de la barre. */
.auth-page { min-height: calc(100vh - var(--lou-entete-h)); }
.auth-page .card-lou { padding: 1rem; }

/* ---------- Pied de page ---------- */
/* GRIS depuis la tâche 8k (point 8, « comme RapidoImmo ») : fond gris clair, titres et liens en
   gris sombre, texte courant en gris moyen, et la marque — le vert sapin — réservée au SURVOL.
   Il était en parchemin ; sur des sections désormais blanches, un beige lisait comme une bande
   de plus, alors que le pied doit se lire comme ce qu'il est : la note en bas de page.
   Le sapin quitte donc les liens au repos, mais reste sur « Fait et hébergé en Suisse », qui
   n'est pas un lien : c'est la seule fierté qu'on garde en couleur ici.
   La marque du porteur (8e, point 2) ouvre le pied, et le légal tient sa dernière colonne. */
.lou-foot { background: var(--lou-gris-pied); border-top: 1px solid var(--lou-gris-bord); padding: 3.5rem 0 1.5rem; margin-top: 4rem; color: var(--lou-gris-texte); }
.lou-foot h2 { font-family: var(--lou-texte); font-weight: 800; font-size: .95rem; letter-spacing: .04em; text-transform: uppercase; color: var(--lou-gris-texte); margin-bottom: .85rem; }
/* `list-unstyled` dans la vue (audit R2) : les trois listes du pied redéfinissaient à la main
   ce que l'utilitaire de Bootstrap pose. */
.lou-foot li { margin-bottom: .45rem; }
.lou-foot .text-loup { color: var(--lou-gris-texte); }
.lou-foot a { color: var(--lou-gris-titre); text-decoration: none; }
.lou-foot a:hover, .lou-foot a:focus-visible { color: var(--lou-sapin-fonce); text-decoration: underline; }
/* AGRANDIE (retour R4 du porteur, 27/08) : à 52 px, la marque pesait moins que les trois titres
   de colonne à sa droite, et la première chose que lisait un visiteur arrivé en bas de page
   était « Le jeu ». Elle passe à 76 px — 216 px de large dans une colonne qui en fait 380, la
   même autorité que le bandeau du haut sans devenir une bannière. */
.lou-foot-marque { height: 76px; width: auto; margin-bottom: 1rem; }
.lou-foot-suisse { display: inline-flex; align-items: center; gap: .4rem; color: var(--lou-rouge-suisse); font-weight: 700; margin-bottom: 0; }
/* Disposition (`d-flex flex-wrap justify-content-between gap-2`) dans la vue : ne reste ici que
   le filet, l'écart au-dessus et la taille du texte — ce que Bootstrap ne sait pas de la charte. */
.lou-foot .base { border-top: 1px solid var(--lou-gris-bord); padding-top: 1.25rem; margin-top: 2rem; color: var(--lou-gris-texte); font-size: .9rem; }
.site-footer--simple { color: var(--lou-loup-texte); padding: 1.5rem 0; margin-top: 3rem; }

/* Une page qui tient dans un écran (retour R7 du porteur, 27/08, sur « Mes enfants »).
   La page s'ouvrait très bas — un écran centré verticalement dans une boîte d'une hauteur de
   fenêtre, d'où un grand vide entre le bandeau et le titre — et son pied tombait TOUJOURS sous
   la ligne de flottaison : la boîte faisait déjà une fenêtre entière, le pied venait après.
   Le patron est celui du pied collant : le corps est une colonne d'une hauteur de fenêtre, le
   contenu pousse (flex: 1), le pied se pose au bas. Le contenu commence donc en HAUT, sous le
   bandeau, et le pied reste visible sans faire défiler. Une page plus longue que l'écran se
   comporte comme avant : c'est un minimum, pas une hauteur fixe.
   Le `padding-top` réservé au bandeau fixe est compris dans les 100 dvh (box-sizing: border-box
   de Bootstrap) : sans cela, la page dépasserait de la hauteur exacte du bandeau. */
body.page-pleine-hauteur { display: flex; flex-direction: column; min-height: 100vh; min-height: 100dvh; }
body.page-pleine-hauteur > main { flex: 1 0 auto; min-height: 0; }
body.page-pleine-hauteur > footer { flex: 0 0 auto; margin-top: auto; }

/* ---------- Écrans enfant (sélection, pause, verrou) ---------- */
/* Écrans enfant : beige uni de la charte (--lou-papier, déjà --bs-body-bg). Le dégradé vert-jaune
   qui traînait ici depuis le lot 1 a été retiré à la tâche 8d sur demande du porteur — il jurait
   avec les popups papier et donnait au bas de l'écran une teinte verdâtre qui n'est nulle part
   ailleurs dans la charte. */
body.mode-jeu { background: var(--lou-papier); }
/* Page qui occupe TOUTE la hauteur, contenu centré verticalement : « Qui joue aujourd'hui ? » et
   « Mes enfants » restaient collés en haut d'un écran à moitié vide. Le pied de page, quand il y
   en a un, se colle en bas de lui-même — c'est le `flex: 1` qui pousse. */
/* La hauteur retirée est celle de la barre, prise au jeton : dans le flux (écrans enfant) elle
   occupe la place, en position fixe (espace parent) c'est le padding du corps qui la réserve —
   dans les deux cas, l'écran fait exactement une fenêtre, sans barre de défilement parasite. */
.ecran-plein { min-height: calc(100vh - var(--lou-entete-h)); min-height: calc(100dvh - var(--lou-entete-h)); display: flex; flex-direction: column; justify-content: center; padding: 2.5rem 0; }
/* Cartes CENTRÉES (tâche 8d) : `repeat(auto-fit, minmax(220px, 1fr))` étirait une carte unique sur
   toute la largeur de l'écran — un seul enfant, et sa carte faisait 1200 px de large. Des colonnes
   de largeur fixe, centrées, gardent la même carte au milieu qu'il y en ait une ou cinq. */
.loustic-grille { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 260px)); justify-content: center; gap: 1.5rem; }
/* Le costume EN PIED, pas une tête dans un rond (tâche 8d) : l'enfant reconnaît son déguisement.
   La couleur de tenue choisie sur le profil devient le CADRE de la carte, puisqu'il n'y a plus de
   cercle pour la porter. Le survol change l'ombre et la couleur, sans translate — même règle que
   les cartes de costume, pour la même raison : une carte qui saute se dérobe au doigt qui la vise. */
.loustic-carte { background: var(--lou-carte); border: 5px solid var(--tenue, var(--lou-loup-clair)); border-radius: 2rem; padding: 1rem 1rem 1.25rem; text-align: center; width: 100%;
    box-shadow: 0 .5rem 1.5rem rgba(63, 58, 54, .1); transition: box-shadow .15s ease, border-color .15s ease; cursor: pointer; }
.loustic-carte:hover, .loustic-carte:focus-visible { border-color: var(--lou-ocre); box-shadow: 0 10px 26px rgba(63, 58, 54, .28); outline: none; }
/* Tâche 8d (revue) — un en-pied occupe RÉELLEMENT toute la largeur de sa carte.
   La boîte à ratio fixe (3/4) d'avant laissait jusqu'à 14 % de vide de part et d'autre : les
   en-pied ne partagent PAS un ratio unique (319 à 381 px de large pour 512 de haut), et
   `object-fit: contain` les centrait donc dans une boîte plus large qu'eux. `cover` aurait rogné
   — 8 % de chaque côté sur le magicien, c'est-à-dire l'orbe de son bâton. L'image garde donc SON
   ratio, et les attributs width/height de la vue (Avatars::taillePortrait) réservent sa place
   exacte, sans décalage au chargement. Même règle pour les trois écrans qui les montrent :
   « Choisis ton costume », « Qui joue aujourd'hui ? » et « Mes enfants ». */
.loustic-portrait { width: 100%; height: auto; border-radius: 1rem; margin-bottom: .5rem; }
.loustic-carte .prenom { font-family: var(--lou-texte); font-size: 1.75rem; font-weight: 800; }
@media (prefers-reduced-motion: reduce) { .loustic-carte { transition: none; } }
/* LA COULEUR PRÉFÉRÉE DE L'ENFANT, en deux valeurs et pas une (porteur, 21/09/2026 : « utiliser
   la couleur préférée de l'enfant pour la bordure de la card, le contour des boutons et le
   bouton jouer »).
   * `--tenue` est la couleur CHOISIE : elle peint ce qui n'a pas de texte dessus — bordures,
     contours, pastilles de choix.
   * `--tenue-fonce` est la MÊME couleur assombrie jusqu'à porter du texte blanc à 4,5:1 (AA).
     Elle est nécessaire : mesuré sur les huit teintes, trois (coquelicot, sapin, lavande)
     n'atteignent AA ni avec du blanc ni avec l'encre. Un « Jouer » peint à même la tenue serait
     donc illisible pour trois enfants sur huit, et rien ne l'aurait dit.
     Obtenue en ne baissant QUE la luminosité HLS : la teinte et la saturation restent celles que
     l'enfant a choisies — c'est sa couleur, plus sombre, pas une autre couleur.
     Contrôlée par `tests/unit/TenuesContrasteTest.php`, qui recalcule les ratios. */
.tenue-coquelicot { --tenue: #E07A5F; --tenue-fonce: #CD4A28; }
.tenue-ocre       { --tenue: #E2A24B; --tenue-fonce: #A3691A; }
.tenue-soleil     { --tenue: #F2CC6C; --tenue-fonce: #97700D; }
.tenue-sauge      { --tenue: #8FB996; --tenue-fonce: #508058; }
.tenue-sapin      { --tenue: #4F8A6B; --tenue-fonce: #498063; }
.tenue-ciel       { --tenue: #7FB4D9; --tenue-fonce: #347CAF; }
.tenue-lavande    { --tenue: #A58BD0; --tenue-fonce: #8765C1; }
.tenue-petale     { --tenue: #F2A7B5; --tenue-fonce: #E02D4E; }
.choix-couleur { display: flex; flex-wrap: wrap; gap: .75rem; }
.choix-couleur .btn { width: 48px; height: 48px; border-radius: 50%; border: 4px solid transparent; background: var(--tenue); }
/* Rappeler `background` ici : `.btn-check:checked + .btn` (0-3-0) l'emporte sur
   `.choix-couleur .btn` (0-2-0) et repeindrait la pastille en --bs-btn-active-bg,
   jamais définie pour ces boutons sans classe .btn-* — donc transparent. */
.choix-couleur .btn-check:checked + .btn { border-color: var(--lou-encre); background: var(--tenue); }
/* ÉCRAN DE PAUSE (item 53) : une photo Pexels (village à colombage) en fond PLEIN ÉCRAN, sous un
   voile léger, et le texte posé sur une CARTE translucide — jamais à même la photo, pour rester
   lisible quel que soit le thème. Tout ici, jamais en style= inline (CSP). */
.jeu-pause { text-align: center; padding: 3rem 1rem; position: relative; min-height: 100vh; min-height: 100dvh; display: flex; align-items: center; justify-content: center; }
/* `fixed inset:0` couvre la fenêtre entière même si .jeu-pause reste un .container à largeur bornée.
   Le voile (dégradé sombre) assombrit un peu la photo pour que la carte claire ressorte. */
.jeu-pause::before { content: ""; position: fixed; inset: 0; z-index: 0;
    background-image: linear-gradient(rgba(24, 18, 6, .34), rgba(24, 18, 6, .34)), url("/assets/img/pause/village-colombage.webp");
    background-size: cover; background-position: center; }
.jeu-pause-carte { position: relative; z-index: 1; max-width: 34rem; margin-inline: auto; color: #2f2416;
    background: rgba(255, 252, 245, .88); border-radius: 1.25rem; padding: 2.5rem 2rem;
    box-shadow: 0 1.25rem 3rem rgba(30, 22, 8, .32); }
@media (prefers-reduced-motion: reduce) { .jeu-pause::before { background-attachment: scroll; } }
.verrou-calcul { font-family: var(--lou-texte); font-size: 2.5rem; font-weight: 800; letter-spacing: .05em; }
/* LE LIEN DE REPLI des écrans enfant (R51) — « Retour au jeu » sous le verrou adulte, « Espace
   parent » sous « Qui joue aujourd'hui ? ». Un enfant qui atterrit devant le verrou par erreur doit
   en repartir SANS SAVOIR LIRE : le même lien, à la même place, de la même couleur d'un écran à
   l'autre, précédé de la tête de louveteau de la marque. Tout le reste est posé par Bootstrap
   (`small d-inline-flex align-items-center gap-2`) et la couleur par `.text-loup`, c'est-à-dire par
   le jeton --lou-loup-texte : elle n'est recopiée NULLE PART, les deux écrans la tiennent de la
   même règle. Ne reste ici que la taille du logo, que Bootstrap n'a pas d'utilitaire pour dire :
   2,5 rem (40 px) et non 2 rem, parce qu'à 32 px le museau du louveteau se brouille — or c'est
   l'IMAGE, pas le libellé, qui doit se reconnaître d'un coup d'œil quand on ne sait pas lire. */
.lien-repli-logo { width: 2.5rem; height: 2.5rem; }
/* `width: max-content` + `max-width` : SANS eux, le bandeau était bridé à 195 px sur un
   téléphone. Un élément `fixed` posé par `left: 50%` sans `right` ni `width` ne peut pas dépasser
   la moitié droite de l'écran : à 390 px, « Hou hou ! Il reste cinq petites minutes de jeu
   aujourd'hui. » se pliait sur SIX lignes et recouvrait toute la colonne des boutons du HUD (vu à
   la capture, tâche T8V). `pointer-events: none` : c'est une annonce (`role="status"`), rien ne
   s'y clique — elle ne doit jamais voler un geste à ce qu'elle recouvre. */
.hibou-bandeau { position: fixed; left: 50%; bottom: 1.5rem; transform: translateX(-50%); display: none; align-items: center; gap: 1rem;
    width: max-content; max-width: calc(100vw - 2rem); pointer-events: none;
    background: var(--lou-carte); border: 3px solid var(--lou-ocre); border-radius: 2rem; padding: 1rem 1.5rem; box-shadow: 0 .5rem 1.5rem rgba(63, 58, 54, .15); z-index: 1070; }
.hibou-bandeau.visible { display: flex; }
.hibou-bandeau .bi { font-size: 2rem; color: var(--lou-ocre); }
/* R62 : le PORTRAIT du hibou, quand le fichier est au dépôt (App\Libraries\Hibou). Rond, cerclé
   d'ocre comme le bandeau, à la taille de l'icône qu'il remplace en un peu plus grand — c'est un
   personnage qui vient parler, pas un pictogramme. Un enfant de trois ans reconnaît un hibou ; il
   ne reconnaît pas une lune et des étoiles. */
.hibou-portrait { width: 72px; height: 72px; border-radius: 50%; object-fit: cover;
    border: 3px solid var(--lou-ocre); background: var(--lou-papier); flex: 0 0 auto; }
/* Le bandeau ENTRE en scène : le hibou arrive, il ne se téléporte pas. Animation courte, une
   seule fois, et rien du tout pour qui demande moins de mouvement. */
@media (prefers-reduced-motion: no-preference) {
    .hibou-bandeau.visible { animation: hibou-arrive .5s ease-out both; }
    @keyframes hibou-arrive { from { opacity: 0; transform: translate(-50%, 1.5rem); } to { opacity: 1; transform: translate(-50%, 0); } }
}

/* ---------- Tableau de bord parent ---------- */

/* ---------- 404 ---------- */
.err404 { text-align: center; padding: 5rem 0; }
.err404-code { font-family: var(--lou-texte); font-size: 6rem; font-weight: 800; color: var(--lou-ocre); line-height: 1; }
/* Entièrement posée par les utilitaires de Bootstrap dans les deux vues d'erreur (audit R2) :
   `list-unstyled d-flex flex-wrap justify-content-center gap-4 mt-4`. Plus une seule règle ici. */

/* ---------- Divers ---------- */
.toast-stack { z-index: 1080; }
.text-loup { color: var(--lou-loup-texte); }
/* Bootstrap peint <code> en #d63384 : un rose qui n'est nulle part dans la charte et qui ne
   donne que 3,8:1 sur le parchemin. Les codes du PER (« MSN 12 ») sont du texte à lire. */
code { color: var(--lou-encre); background: rgba(226, 162, 75, .18); border-radius: .35rem; padding: .05em .35em; }

/* ---------- Formulaire de contact ---------- */
/* Champ leurre anti-robot (app/Views/contact/index.php) : invisible et hors flux, mais pas
   display:none — certains robots ignorent les champs masqués de cette façon. */
.champ-leurre { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }



/* ---------------------------------------------------------------------------------------------
   Popups du jeu (tâche 8d) — infrastructure GÉNÉRIQUE, partagée par le menu des exercices, le sac,
   les progrès et le choix du costume. Elle vit dans style.css et non dans monde.css : le choix du
   costume est servi par /jeu/costume, qui ne charge que jeu.css.

   L'élément est un <dialog> : Échap, le piège à mise au point et l'inertie de l'arrière-plan sont
   à lui, pas à nous (public/assets/js/monde/hud/Popup.js). On ne redéfinit ici que l'apparence —
   d'où la remise à plat complète du style par défaut du navigateur (bordure, marge, largeur).
   --------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------
   L'horloge du temps d'écran (tâche 8f, point 4). Elle vit ici, dans la feuille commune, parce
   qu'elle apparaît sur QUATRE écrans qui ne chargent pas les mêmes feuilles : le village
   (monde.css), la liste de repli, l'écran d'une quête et le choix du costume (jeu.css). Sa
   POSITION, elle, appartient à chacun de ces écrans.

   Le cadran est un `conic-gradient` : la portion pleine est le temps qui reste, et elle s'efface
   dans le sens des aiguilles. Rien n'est dessiné à la main — pas de SVG, pas de canvas — donc
   c'est net à toute taille et cela ne coûte pas une image par seconde.

   `--part` (0 à 100) est écrit par session.js à chaque signal : c'est une DONNÉE d'exécution,
   la seule exception que la règle « aucun style inline » du projet admette, comme la couleur
   d'un domaine dans la popup des progrès.
   --------------------------------------------------------------------------------------------- */
/* R62 (porteur, 28/08) : « le rond du temps restant doit faire la MÊME taille que les autres
   boutons du HUD ». La taille n'est donc plus un nombre écrit ici : c'est `--horloge-taille`, que
   le village redéfinit sur `--hud-bouton-taille` (monde.css) — un seul chiffre pour le rond du
   temps et pour les boutons, impossible de les désaccorder. 64 px reste le défaut des pages de
   texte (la liste de repli, l'écran de costume), qui n'ont pas de boutons ronds à côté. */
.horloge { --part: 100; --horloge-teinte: var(--lou-sapin); --horloge-taille: 64px;
    width: var(--horloge-taille); height: var(--horloge-taille); border-radius: 50%; border: 3px solid var(--horloge-teinte);
    background: rgba(251, 246, 238, .92); display: grid; place-items: center; padding: 0; margin: 0; }
/* `display: grid` bat l'attribut `hidden` : sans cette ligne, cacher l'horloge (jeu sans limite
   de temps) ne la cacherait pas. */
.horloge[hidden] { display: none; }
/* Le cadran garde sa couronne : 3 px de bordure + 8 px de blanc de chaque côté, soit 22 px de
   moins que le rond. Il suit donc la taille au lieu d'être figé à 42 px. */
.horloge-cadran { position: relative; width: calc(var(--horloge-taille) - 22px); height: calc(var(--horloge-taille) - 22px); border-radius: 50%;
    background: conic-gradient(var(--horloge-teinte) calc(var(--part) * 1%), rgba(43, 42, 40, .14) 0); }
/* Les douze traits du pourtour : ils disent « horloge » sans demander de savoir lire l'heure.
   Le masque radial ne garde du disque rayé que sa couronne extérieure. */
.horloge-cadran::before { content: ''; position: absolute; inset: -5px; border-radius: 50%;
    background: repeating-conic-gradient(var(--lou-encre) 0deg 2deg, transparent 2deg 30deg);
    -webkit-mask: radial-gradient(closest-side, transparent 82%, #000 84%);
    mask: radial-gradient(closest-side, transparent 82%, #000 84%); opacity: .45; }
.horloge-centre { position: absolute; left: 50%; top: 50%; width: 10px; height: 10px; margin: -5px 0 0 -5px;
    border-radius: 50%; background: var(--lou-papier); border: 2px solid var(--horloge-teinte); }
/* Les cinq dernières minutes : la même ocre que le hibou messager, qui prévient au même moment. */
.horloge-avertissement { --horloge-teinte: var(--lou-ocre); }
/* Sur une page de texte (la liste de repli), l'horloge garde sa légende écrite à côté. */
.horloge-legendee { width: auto; height: auto; border: 0; background: none; border-radius: 0;
    grid-auto-flow: column; justify-content: start; align-items: center; gap: .6rem; }
.horloge-legendee .horloge-cadran { width: 34px; height: 34px; }
.horloge-texte { color: var(--lou-loup); }

.popup { position: fixed; inset: 0; width: 100%; height: 100%; max-width: 100%; max-height: 100%;
    margin: 0; padding: 0; border: 0; background: transparent; color: inherit; overflow: hidden; }
.popup:not([open]) { display: none; }
.popup[open] { display: grid; place-items: center; }
.popup::backdrop { background: rgba(63, 58, 54, .55); }
.popup-boite { width: min(94vw, 760px); max-height: 88vh; overflow: auto; background: var(--lou-papier);
    border: 3px solid var(--lou-sapin); border-radius: 1.5rem; box-shadow: 0 12px 40px rgba(0, 0, 0, .3);
    padding: 1.25rem 1.5rem 1.5rem; }
.popup-entete { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; margin-bottom: 1rem; }
.popup-titre { font-family: var(--lou-titre); font-weight: 700; font-size: 1.6rem; margin: 0; }
/* Bouton de fermeture : large et rond, pour un doigt de trois ans. Échap le double au clavier. */
.popup-fermer { flex: 0 0 auto; width: 52px; height: 52px; border-radius: 50%; border: 3px solid var(--lou-ocre);
    background: var(--lou-carte-haut); color: var(--lou-ocre-fonce); font-size: 1.3rem; display: grid; place-items: center; padding: 0; }
.popup-fermer:hover, .popup-fermer:focus-visible { background: var(--lou-ocre); color: #fff; outline: none; }
.popup-fermer:focus-visible { box-shadow: 0 0 0 .25rem rgba(226, 162, 75, .35); }
.popup-corps > :last-child { margin-bottom: 0; }
/* Popup large : le choix du costume range NEUF héros en pied sur deux colonnes ; 760 px les
   réduirait à des timbres, ce qui est le défaut même que la refonte répare. */
.popup-large .popup-boite { width: min(96vw, 1180px); }
/* Une PAGE DU JEU encadrée dans la popup (tâche 8f, points 1 et 2) : un exercice ou le Grand
   Livre. Elle prend presque tout l'écran — un enfant qui compte des glands ne le fera pas dans
   une vignette — et le cadre remplit ce qui reste sous l'en-tête de la popup. `height: 100%` sur
   l'iframe ne suffirait pas : le corps de la popup doit lui-même avoir une hauteur, d'où la
   colonne en grille. */
.popup-cadre-page .popup-boite { width: min(98vw, 1400px); height: 94vh; max-height: 94vh;
    display: grid; grid-template-rows: auto 1fr; padding: 1rem 1.25rem 1.25rem; overflow: hidden; }
.popup-cadre-page .popup-entete { margin-bottom: .5rem; }
.popup-cadre-page .popup-corps { min-height: 0; overflow: hidden; }
.popup-cadre { width: 100%; height: 100%; border: 0; border-radius: 1rem; background: var(--lou-papier); display: block; }
/* LA POPUP « NUE » (porteur, 24/09/2026) : une mission, un cours ou une planche encadrés apportent
   LEUR en-tête — le bandeau du lieu, avec la croix et la flèche de retour. L'en-tête de la popup
   (titre + croix) serait un doublon : il reste dans le DOM pour l'accessibilité (`aria-labelledby`,
   lecteurs d'écran) mais hors de la vue, et le cadre prend toute la boîte. La bordure prend la
   COULEUR DU LIEU (classe `lieu-<code>` posée sur le <dialog>, lieux.css). */
.popup-cadre-nu .popup-boite { position: relative; padding: 0; grid-template-rows: minmax(0, 1fr); border-color: var(--lou-lieu, var(--lou-sapin)); }
.popup-cadre-nu .popup-entete { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.popup-cadre-nu .popup-cadre { border-radius: 1.25rem; }

/* ── L'AMBIANCE DU LIEU : LE BANDEAU (porteur, 23/09/2026 ; en-tête de popup le 24/09) ──────────
   Les variables --lou-lieu* viennent de lieux.css (classe `lieu-<code>` posée par la page ou par le
   HUD) ; sans elle, tout retombe sur la charte neutre. Partagé par les pages du jeu (jeu.css) ET
   le village (monde.css, panneau d'un lieu) — d'où sa place ici. */
.lieu-bandeau { position: relative; display: flex; align-items: center; gap: .75rem; margin: 0 0 .75rem; padding: .45rem 1rem; border-radius: 1rem; overflow: hidden; color: var(--lou-encre); border: 2px solid var(--lou-lieu-doux, var(--lou-loup-clair)); background: var(--lou-lieu-pale, var(--lou-parchemin)); isolation: isolate; }
/* Le paysage du lieu derrière les objets : un fond de chargement, jamais une image de plus au dépôt. */
.lieu-bandeau::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--lou-lieu-fond) center 40% / cover no-repeat; opacity: .28; }
.lieu-bandeau-objets { display: inline-flex; gap: .45rem; font-size: 1.35rem; line-height: 1; color: var(--lou-lieu, var(--lou-loup)); filter: drop-shadow(0 0 2px #fff); }
.lieu-bandeau-nom { font-family: 'Merienda', 'Nunito', system-ui, sans-serif; font-weight: 700; font-size: 1.05rem; margin: 0; text-shadow: 0 0 6px #fff, 0 0 2px #fff; }
/* L'EN-TÊTE (24/09/2026) : haut, pleine largeur, le paysage franchement visible — un voile clair
   part du bord gauche pour que les objets et le nom restent lisibles dessus —, et à droite les
   deux boutons ronds (flèche de retour au lieu, croix), à la taille de la croix des popups. */
.lieu-bandeau--entete { min-height: 6rem; padding: .75rem 1.25rem; gap: 1rem; border-radius: 1.25rem; border-width: 3px; }
.lieu-bandeau--entete::before { opacity: .6; }
.lieu-bandeau--entete::after { content: ""; position: absolute; inset: 0; z-index: -1; background: linear-gradient(90deg, rgba(255, 255, 255, .8) 0%, rgba(255, 255, 255, .45) 40%, rgba(255, 255, 255, 0) 70%); }
.lieu-bandeau--entete .lieu-bandeau-objets { font-size: 1.8rem; gap: .6rem; }
.lieu-bandeau--entete .lieu-bandeau-nom { font-size: 1.5rem; }
.lieu-bandeau-actions { margin-left: auto; display: inline-flex; gap: .6rem; flex: 0 0 auto; }
.bandeau-bouton { width: 52px; height: 52px; border-radius: 50%; border: 3px solid var(--lou-ocre); background: var(--lou-carte-haut); color: var(--lou-ocre-fonce); font-size: 1.3rem; display: grid; place-items: center; padding: 0; text-decoration: none; line-height: 1; }
.bandeau-bouton:hover, .bandeau-bouton:focus-visible { background: var(--lou-ocre); color: #fff; outline: none; }
.bandeau-bouton:focus-visible { box-shadow: 0 0 0 .25rem rgba(226, 162, 75, .35); }
@media (max-width: 575.98px) {
    .lieu-bandeau { padding: .35rem .75rem; gap: .5rem; }
    .lieu-bandeau--entete { min-height: 4.5rem; padding: .5rem .75rem; }
    .lieu-bandeau--entete .lieu-bandeau-nom { font-size: 1.15rem; }
    .lieu-bandeau--entete .lieu-bandeau-objets { font-size: 1.3rem; }
    .bandeau-bouton { width: 44px; height: 44px; }
}


/* --- Cartes de costume (tâche 7c, refondues 8d) : écran enfant /jeu/costume ET formulaire de
   profil de l'espace parent. Le porteur veut les mêmes héros EN PIED des deux côtés — plus de
   petits ronds de 72 px chez les parents. --- */
/* Les deux moitiés « filles / garçons » ont disparu le 24/09/2026 (porteur : « moins clivant ») :
   UNE grille, quatre cartes par rangée, sans titre ni ligne pointillée. Les cartes sont plus larges,
   et les images bornées à la hauteur de la fenêtre pour que l'écran ne défile pas quand il peut
   l'éviter (deux rangées ≈ 60 vh + les noms). Sous 40 rem : deux par rangée. */
.costume-cartes { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 1rem; align-items: stretch; }
.costume-cartes--entiere { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1rem 1.25rem; }
.costume-cartes--entiere .costume-carte img { height: min(27vh, 300px); width: auto; max-width: 100%; object-fit: contain; }
/* La boîte de cet écran peut prendre un peu plus de hauteur que les autres popups : deux rangées de
   costumes y tiennent alors sans défiler dès 900 px de haut. */
#costume-popup .popup-boite { max-height: 94vh; }
@media (max-width: 40rem) { .costume-cartes--entiere { grid-template-columns: repeat(2, minmax(0, 1fr)); } .costume-cartes--entiere .costume-carte img { height: min(22vh, 200px); } }
/* Survol : OMBRE + COULEUR, jamais de translate (directive du porteur — une carte qui saute sous
   le curseur se dérobe au doigt qui la vise). */
.costume-carte { display: flex; flex-direction: column; align-items: center; gap: .2rem; padding: .5rem .5rem .75rem; background: var(--lou-carte); border: 3px solid var(--lou-loup-clair); border-radius: 1.5rem; text-align: center; cursor: pointer; transition: box-shadow .15s ease, border-color .15s ease, background-color .15s ease; }
.costume-carte:hover, .costume-carte:focus-visible { border-color: var(--lou-ocre); background: #FFF6E8; box-shadow: 0 10px 24px rgba(63, 58, 54, .28); outline: none; }
/* Hauteur d'illustration IMPOSÉE : les héros n'ont pas tous la même largeur (le nain est trapu,
   l'elfe élancé) et, laissées libres, les cartes d'une même rangée finissaient décalées. */
/* L'image prend TOUTE la largeur de sa carte (directive du porteur) : le héros en pied était
   auparavant contenu en hauteur et laissait deux bandes blanches sur les côtés. */
/* `aspect-ratio` et non `height: auto` : les en-pied du porteur n'ont pas tous le même rapport
   (la fée est plus large que le prince), et des images de hauteurs différentes décalaient les
   noms d'une carte à l'autre sur une même rangée. La boîte est fixe, l'image s'y contient. */
.costume-carte img { width: 100%; height: auto; border-radius: 1rem; }
/* Le seul costume sans en-pied peint — l'aventurier, encore le SVG CARRÉ du lot 1 (docs/TODO.md)
   — est mis à la hauteur des autres : à son ratio, sa carte s'arrêterait un tiers plus haut que
   ses voisines. C'est la seule image qui garde une boîte, et elle disparaîtra avec le SVG. */
.costume-carte img[src$=".svg"], .loustic-portrait[src$=".svg"], .profil-portrait[src$=".svg"] {
    aspect-ratio: 330 / 512; object-fit: contain; }
.costume-nom { font-weight: 700; font-size: 1.05rem; }
.costume-description { color: var(--lou-loup-texte); font-size: .85rem; }
.costume-carte.actuel { border-color: var(--lou-sapin); background: #F2F7F3; }
@media (prefers-reduced-motion: reduce) { .costume-carte { transition: none; } }
/* Formulaire de profil (espace parent) : le radio Bootstrap est masqué, c'est la carte qui porte
   l'état choisi. Même cadre sapin que la carte « actuel » de l'écran enfant. */
.choix-costume { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 1rem; align-items: stretch; }
.choix-costume .btn-check:checked + .costume-carte { border-color: var(--lou-sapin); background: #F2F7F3; }
.choix-costume .btn-check:focus-visible + .costume-carte { border-color: var(--lou-ocre); box-shadow: 0 0 0 .25rem rgba(226, 162, 75, .35); }

/* R10 (tâche 8P) — QUATRE COSTUMES PAR LIGNE, EXACTEMENT, dans le formulaire du parent.
   `auto-fill` donne cinq colonnes dès 1100 px et coupe les huit costumes en 5 + 3 : les deux
   moitiés du catalogue ne se lisent plus. Le modificateur ne vaut QUE pour cette page — ni
   `.choix-costume` ni `.costume-carte` ne bougent, ils sont partagés avec l'écran de l'enfant.
   Deux paliers seulement, et jamais moins de deux colonnes : sous 34 rem, quatre en-pied côte à
   côte ne feraient plus que des vignettes. */
.choix-costume--parent { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 48rem) { .choix-costume--parent { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 34rem) { .choix-costume--parent { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* 24/09/2026 (porteur) : « tous les costumes à la même hauteur, sur fond blanc ». Les en-pied
   n'ont pas tous le même rapport (319 à 381 px de large pour 512 de haut) : à `height: auto`,
   les noms d'une même rangée se décalaient de quelques lignes. La boîte de l'image est FIXÉE au
   rapport commun (330/512), l'en-pied s'y contient, et le fond passe du papier au blanc — le
   choix reste marqué par le cadre sapin et sa teinte. Portée : la grille du parent seulement,
   `.costume-carte` reste partagée avec l'écran de l'enfant. */
.choix-costume--parent .costume-carte { background: #fff; }
.choix-costume--parent .costume-carte img { aspect-ratio: 330 / 512; object-fit: contain; }

/* R10 — LES CHOIX SONT DES PASTILLES, PLUS DES CARTES. Les deux `.card-lou` qui empilaient tout
   le formulaire (un cadre dans un cadre dans une page) laissent place à des groupes séparés par
   un filet : chaque groupe a sa légende, et la page se lit d'un regard. Rien de neuf côté
   composants — `.choix-pastilles` n'est qu'une rangée souple de `btn-check` Bootstrap. */
/* 23/09/2026 (porteur) : « il reste des <hr> normaux, les remplacer par les versions évoluées ;
   augmenter les marges pour aérer la page ». Le filet gris sous chaque groupe est parti — c'est un
   `.lou-separateur--fin` (le séparateur orné, en plus discret) qui sépare deux groupes, posé par
   la vue —, et les groupes comme les chapitres respirent davantage. */
.profil-groupe { border: 0; padding: 0; margin: 0 0 1.75rem; }
#profil-formulaire .reglage-section { padding: .75rem 0 1.5rem; }
#profil-formulaire .reglage-section > .h4 { margin-bottom: 1.5rem; }
#profil-formulaire .form-text { margin-top: .6rem; }
/* La suppression du profil, dans un CADRE ROUGE (porteur, 23/09) : une bordure de danger, sans
   fond ni ombre — pas une carte —, qui isole le geste irréversible du reste de la page. */
.profil-danger { border: 3px solid var(--bs-danger); border-radius: 1rem; padding: 1.25rem 1.5rem 1.5rem; margin-top: 1.5rem; }
.profil-danger > .h5 { margin-top: 0; }
/* Un <legend> de Bootstrap est FLUIDE (`calc(1.275rem + .3vw)`) et prend toute la largeur : sur
   un grand écran il grossissait jusqu'à concurrencer le titre de la page. Taille fixe, poids du
   titrage sérieux de la charte — les six légendes du formulaire pèsent alors le même poids. */
.profil-groupe > legend { float: none; width: auto; margin-bottom: .5rem;
    font-family: var(--lou-texte); font-size: 1.25rem; font-weight: 800; color: var(--lou-encre); }
.choix-pastilles { display: flex; flex-wrap: wrap; gap: .5rem; }
/* ÂGE ET ANNÉE SCOLAIRE SUR UNE LIGNE (porteur, 24/09/2026) : une rangée souple, l'âge prend sa
   largeur, l'année prend le reste — et son aide se replie dedans. Sous 36 rem, la rangée casse et
   les deux groupes se suivent comme avant. Le `.profil-groupe` de l'année garde sa marge basse ;
   celui de l'âge n'en a plus besoin quand ils sont côte à côte. */
.profil-ligne { display: flex; flex-wrap: wrap; column-gap: 2.5rem; align-items: flex-start; }
.profil-ligne > .profil-groupe:first-child { flex: 0 0 auto; }
.profil-ligne > #groupe-annee { flex: 1 1 22rem; }
/* La pastille « Sans préférence » a disparu le 24/09/2026 : un second clic sur la couleur choisie
   la décoche (profil-formulaire.js), et la rangée peut rester sans valeur active. */

/* « Mes enfants » (espace parent, tâche 8d) : cartes CENTRÉES et costume EN PIED, comme sur
   l'écran de l'enfant. La grille Bootstrap `row/col-lg-4` alignait les cartes à gauche et laissait
   un profil unique flotter dans un tiers d'écran ; des colonnes de largeur fixe, centrées, donnent
   la même carte au milieu qu'il y en ait une ou cinq. Le bouton « Jouer » est poussé en bas par
   `mt-auto`, si bien que des cartes de contenus inégaux gardent leurs boutons alignés. */
/* `minmax(min(300px, 100%), 300px)` et non `300px` sec : sur un écran de 320 px, une piste fixe
   de 300 px plus les marges du conteneur déborde et fait défiler la page en travers. */
/* R58 (tâche 8P) : le compagnon sur la page « Mes enfants » VIDE, et elle seule — dès qu'un profil
   existe, la page doit tenir dans un écran, pied compris (R7). Le fichier est celui que la vitrine
   sert déjà (230 x 478) ; `object-fit: cover` le recadre sans jamais l'étirer, et
   `object-position: center 6%` vise sa tête plutôt que ses pattes. Sous 34 rem il disparaît : sur
   un téléphone il pousserait le texte d'accueil dans une colonne de quatre mots. */
.espace-vide-portrait { flex: 0 0 auto; width: 6rem; height: 7.5rem; border-radius: 1rem;
    object-fit: cover; object-position: center 6%;
    border: 3px solid var(--lou-ocre); box-shadow: var(--lou-ombre); }
@media (max-width: 34rem) { .espace-vide-portrait { display: none; } }
.profil-grille { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 300px)); justify-content: center; gap: 1.5rem; }
.profil-carte { border: 3px solid var(--tenue, var(--lou-loup-clair)); }
/* LA CARTE DE CHAQUE ENFANT PORTE SA COULEUR (porteur, 21/09/2026). Pas seulement la bordure :
   le contour de ses cinq boutons d'action et son bouton « Jouer ». Une rangée de cartes se lit
   alors d'un coup d'œil — chaque enfant a la sienne, et c'est celle de son costume dans le jeu.
   Tout est porté dans la PORTÉE de `.profil-carte`, donc ces règles ne touchent aucune autre
   page : `--tenue` n'est définie que sur les éléments qui portent une classe `.tenue-*`.
   Le repli `var(--tenue…, …)` garde l'ancien vert si un profil n'a pas de couleur. */
.profil-carte .lou-action { border-color: var(--tenue, var(--lou-sapin));
    color: var(--tenue-fonce, var(--lou-sapin-fonce)); }
.profil-carte .lou-action:hover, .profil-carte .lou-action:focus-visible {
    background: var(--tenue-fonce, var(--lou-sapin-fonce)); color: #fff; }
/* Le « Jouer » prend la teinte FONCÉE : c'est le seul endroit où du texte se pose sur la couleur,
   et trois des huit teintes ne portent aucun texte au niveau AA en aplat clair (voir --tenue-fonce).
   `--bs-btn-*` plutôt qu'un `background` : Bootstrap dérive survol, focus et actif de ces
   variables — les écraser une à une laisserait le bouton reprendre le vert au survol. */
.profil-carte .btn-secondary {
    --bs-btn-bg: var(--tenue-fonce, var(--lou-sapin-fonce));
    --bs-btn-border-color: var(--tenue-fonce, var(--lou-sapin-fonce));
    --bs-btn-hover-bg: var(--tenue-fonce, var(--lou-sapin-fonce));
    --bs-btn-hover-border-color: var(--lou-encre);
    --bs-btn-active-bg: var(--tenue-fonce, var(--lou-sapin-fonce));
    --bs-btn-active-border-color: var(--lou-encre);
    --bs-btn-color: #fff; --bs-btn-hover-color: #fff; --bs-btn-active-color: #fff;
    --bs-btn-focus-shadow-rgb: 63, 58, 54; }
/* Plus de fond derrière le portrait : les en-pied sont détourés (tâche 8e), le louveteau se
   pose directement sur le papier de la carte. Le fond crème qu'on posait ici redessinait
   exactement le rectangle beige qu'on vient de supprimer. */
/* Actions d'une carte enfant, en icônes sur UNE ligne (précision du porteur, 26/08). Le rond
   et l'infobulle reprennent exactement le geste du HUD du village (.hud-bouton, monde.css) :
   même forme, même mécanique d'étiquette par `attr(aria-label)`, pour qu'un parent qui a vu
   l'écran de son enfant reconnaisse les mêmes boutons. Cinq ronds de 44 px et leurs écarts
   tiennent dans les 300 px d'une carte — c'est la contrainte qui a fixé la taille, et 44 px
   est aussi la cible tactile minimale recommandée. */
.profil-actions { margin-bottom: 1rem; }
/* 48 px de haut, comme le bouton « Jouer » (porteur, 23/09/2026 : « agrandir les liens ronds »). */
.lou-action { position: relative; flex: 0 0 auto; width: 48px; height: 48px; border-radius: 50%;
    border: 2px solid var(--lou-sapin); background: var(--lou-carte-haut); color: var(--lou-sapin-fonce);
    font-size: 1.25rem; line-height: 1; display: grid; place-items: center; text-decoration: none; }
/* `.card-lou .bi { color: ocre }` (0-2-0) l'emporterait sur `.lou-action` (0-1-0) et repeindrait
   les cinq icônes en ocre pâle sur le papier de la carte — 2,7:1, sous le seuil AA. */
.lou-action .bi { color: inherit; font-size: inherit; }
.lou-action:hover, .lou-action:focus-visible { background: var(--lou-sapin-fonce); color: #fff; outline: none; }
.lou-action:focus-visible { box-shadow: 0 0 0 .25rem rgba(79, 138, 107, .35); }
.lou-action--secondaire { border-color: var(--lou-loup); color: var(--lou-loup-texte); }
.lou-action--secondaire:hover, .lou-action--secondaire:focus-visible { background: var(--lou-loup-texte); color: #fff; }
/* Infobulle : `attr(aria-label)` reprend le libellé, donc une seule chaîne à tenir à jour —
   celle que lit aussi un lecteur d'écran. `hover: hover` la réserve aux pointeurs qui survolent
   vraiment : sur un écran tactile elle apparaîtrait sous le doigt, au moment du tap, pour rien. */
@media (hover: hover) {
    .lou-action::after { content: attr(aria-label); position: absolute; bottom: calc(100% + 8px); left: 50%;
        transform: translateX(-50%); white-space: nowrap; padding: .25rem .6rem; border-radius: .75rem;
        background: var(--lou-encre); color: #fff; font-family: var(--lou-texte); font-weight: 600;
        font-size: .8rem; opacity: 0; pointer-events: none; transition: opacity .15s; z-index: 5; }
    .lou-action:hover::after, .lou-action:focus-visible::after { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) { .lou-action::after { transition: none; } }

/* TOUJOURS LA MÊME HAUTEUR d'une carte à l'autre (porteur, 23/09/2026) : les en-pied n'ont pas
   le même rapport (319 à 381 px de large pour 512 de haut), et « largeur 100 %, hauteur auto »
   donnait des portraits de hauteurs différentes côte à côte. La hauteur est fixée, la largeur
   suit le rapport, l'image se centre ; au-dessus de 992 px, `max-height: 100 %` (plus bas) reste
   la borne quand l'écran est petit — la même pour toutes les cartes. */
/* 24/09/2026 (porteur) : « augmenter la hauteur des images de profil » — 300 → 380 px. Au-dessus
   de 992 px, la borne `max-height: 100 %` (plus bas) reste la seule limite : le portrait prend
   toute la hauteur que la carte lui laisse, et cette valeur n'est que son plafond. */
.profil-portrait { display: block; height: 380px; width: auto; max-width: 100%; margin: 0 auto .75rem; object-fit: contain; border-radius: 1rem; }
/* ---------------------------------------------------------------------------------------------
   « MES ENFANTS » TIENT DANS UN ÉCRAN, PIED COMPRIS (retour R7 du porteur, 27/08) — ET C'EST UN
   MÉCANISME, PLUS UN BUDGET.

   CE QU'IL Y AVAIT AVANT : `max-height: max(140px, calc(100dvh - 600px))` sur le portrait. 600 px
   était la somme MESURÉE du mobilier de la page — bandeau, respirations, titre, barre d'entrées,
   habillage de la carte, pied — et c'est précisément ce qui le rendait fragile : un nombre qui
   décrit une mise en page ne la suit pas. Il avait déjà été relevé de 540 à 600 (la ligne « qui
   suit cet enfant », puis la barre d'entrées), et il avait fallu deux autres rustines pour tenir :
   les trois entrées secondaires en `btn-sm` et sans icône, parce qu'avec elles la barre repliait
   sur deux lignes. MESURÉ AVANT CE CORRECTIF : une cinquième entrée dans la barre, et la page
   débordait de 52 px — le portrait était déjà au plancher de 140 px, il n'avait plus rien à rendre.

   CE QU'IL Y A MAINTENANT : la page dit ce qu'elle veut, et le navigateur mesure. `main` est une
   grille de deux pistes — l'en-tête prend ce qu'il lui faut (`auto`), la rangée de cartes prend
   TOUT LE RESTE (`minmax(0, 1fr)`). Le portrait est le seul élément qui puisse céder : il se borne
   à la hauteur qu'on lui laisse (`max-height: 100%`), garde son rapport (`object-fit: contain`) et
   a le droit de rétrécir (`min-height: 0`, sans quoi un élément remplacé impose sa hauteur
   intrinsèque à son conteneur flex). Plus aucun nombre à tenir à jour : l'en-tête peut replier sur
   deux lignes, gagner une entrée ou des icônes, le mécanisme absorbe.
   Sous 992 px il n'y a plus qu'une colonne et le défilement est normal : la règle s'arrête là.
   --------------------------------------------------------------------------------------------- */
@media (min-width: 992px) {
    .espace-enfants { display: grid; grid-template-rows: auto minmax(0, 1fr); }
    /* La rangée de cartes vit dans la piste souple, et ses rangées s'y partagent la hauteur : une
       carte reçoit ainsi une hauteur RÉELLE, celle qu'on lui laisse, au lieu de la sienne. */
    .espace-enfants > .profil-grille { min-height: 0; grid-auto-rows: minmax(0, 1fr); }
    /* La page VIDE, elle, n'a rien à étirer : son encadré garde sa hauteur, et la piste souple
       lui laisse simplement la place. Sans cela il s'ouvrait sur toute la fenêtre, presque vide. */
    .espace-enfants > .espace-vide { align-self: start; }
    /* Le portrait est le seul élément qui puisse céder. `min-height: 0` est indispensable : sans
       lui, un élément remplacé impose sa hauteur intrinsèque à la colonne qui le porte, et rien
       ne se serre. `width: auto` plutôt qu'une boîte plus large que l'image, qui rendrait les
       bandes de vide de la tâche 8d : un élément remplacé à hauteur définie tire sa largeur de
       son propre rapport. */
    .profil-carte > .card-body { min-height: 0; }
    .profil-carte .profil-portrait { min-height: 0; max-height: 100%; object-fit: contain;
        width: auto; max-width: 100%; margin-inline: auto; display: block; }
}
/* LA PORTÉE DE LA PROMESSE (revue 8N, point 2), ET LE SEUL ENDROIT OÙ ELLE S'ÉNONCE.
   « Tenir dans un écran » ne vaut que pour UNE rangée de cartes : rétrécir les portraits ne
   récupère que la hauteur d'une carte, jamais celle d'une rangée entière. Les colonnes se
   comptent — cartes de 300 px, écart de 1,5 rem, conteneurs de Bootstrap : 3 colonnes de 992 à
   1399 px (conteneurs 960 et 1140), 4 au-delà (1320).
   Tant qu'on est sur une rangée, le corps REND sa hauteur (`flex: 1 1 0`) : la piste souple reçoit
   la place qui reste, et le portrait s'y ajuste. À la rangée suivante, il la PREND (`1 0 auto`,
   la valeur de base) : les portraits gardent leur taille et la page défile — c'est le
   comportement juste, et continuer à raboter ne l'était pas (à 5 profils sur 1280x720, la page
   débordait de 470 px ET les portraits tombaient à 116 px de large : la promesse était perdue et
   les cartes illisibles avec).
   Une seule propriété bascule, contre deux règles et deux nombres magiques auparavant. */
@media (min-width: 992px) and (max-width: 1399.98px) {
    body.page-pleine-hauteur:not(:has(.profil-grille > :nth-child(4))) > main.espace-enfants { flex: 1 1 0; }
}
@media (min-width: 1400px) {
    body.page-pleine-hauteur:not(:has(.profil-grille > :nth-child(5))) > main.espace-enfants { flex: 1 1 0; }
}

/* ---------------------------------------------------------------------------------------------
   LE SECOND PARENT (T8Q) — /espace/co-parents, et la ligne « qui suit cet enfant » des cartes.
   Bootstrap fait tout le gros œuvre (cartes, boutons, formulaires, badges) : il ne reste ici que
   ce qu'il ne donne pas, c'est-à-dire des séparateurs et l'alignement d'une ligne « libellé à
   gauche, action à droite » qui doit se replier proprement sur un téléphone.
   --------------------------------------------------------------------------------------------- */
.coparent-liste > li + li { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--lou-bordure, rgba(0, 0, 0, .1)); }
.coparent-enfant > ul > li + li { margin-top: .25rem; }
/* La ligne se replie plutôt que de pousser le bouton hors de la carte : une adresse e-mail est
   longue, et sur un téléphone elle occupe déjà toute la largeur à elle seule. */
.coparent-ligne { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .5rem; }
/* Les formulaires d'action ne doivent pas ajouter de marge : ils ne portent qu'un bouton. */
.coparent-ligne form { margin: 0; }
/* Sur la carte d'un enfant (« Mes enfants ») : qui le suit, en petit, sous la tranche d'âge.
   `overflow-wrap` parce qu'une adresse e-mail sans espace déborderait d'une carte de 300 px. */
.profil-parents { overflow-wrap: anywhere; }


/* --- Médailles bronze / argent / or (T8h) ------------------------------------------
   UNE SEULE définition des trois teintes, ici et nulle part ailleurs : les médailles
   s'affichent sur le joueur de quête (jeu.css), dans le Grand Livre (suivi.css) et dans le sac
   du village (monde.css), qui ne sont jamais chargés ensemble. style.css l'est toujours.
   Aucune image : le picto Bootstrap `bi-award` teinté suffit et suit la taille du texte.

   LA COULEUR NE DIT JAMAIS SEULE LE PALIER : partout où ces classes servent, le mot
   (« bronze », « argent », « or ») est écrit à côté. C'est la règle daltonisme du projet, et
   elle compte double ici — bronze et or se ressemblent beaucoup en protanopie.

   CES QUATRE TEINTES SONT DU TEXTE, PAS DE LA DÉCORATION. Les classes habillent le mot du
   palier autant que le picto — `.badge-palier` et `.medaille-case` (suivi.css), `.sac-palier`
   (monde.css) — en ~15 px gras, c'est-à-dire du « texte normal » au sens WCAG : le seuil est
   4,5:1, pas 3:1. Les teintes vives du premier jet (bronze #A9713B 3,45:1, argent #8C97A0
   2,50:1, or #D8A81C 1,85:1, vide #D9D2C7 1,26:1 sur le parchemin) écrivaient donc le mot en
   délavé, ce qui ruinait la règle daltonisme ci-dessus : le mot ne sert à rien s'il ne se lit
   pas. Elles sont assombries à hue constante, et vérifiées AU CALCUL sur TOUS les fonds où ces
   classes se posent — carte #FFFCF6/#FAF2E4, parchemin #F4EADB, papier #FBF6EE, blanc des
   pastilles du sac #FFFFFF/#F2F7F3, ouverture de panneau #FBEEDA, suggestion du HUD #FFF4E1 :

     bronze #8A5A2B  4,93:1 (pire fond) … 5,87:1
     argent #5A6570  5,00:1 … 5,95:1
     or     #7D5C00  5,18:1 … 6,17:1
     vide   #6E6862  4,62:1 … 5,50:1

   `.medaille-vide` ne reprend plus `--lou-loup-clair` : cette variable est une teinte de BORDURE
   (elle sert de trait à une douzaine de cadres), elle n'a jamais été lisible en texte. Ce qui dit
   « pas encore gagné » reste la graisse normale et le mot « à gagner », pas le délavage. */
.medaille-bronze { color: #8A5A2B; }
.medaille-argent { color: #5A6570; }
.medaille-or     { color: #7D5C00; }
.medaille-vide   { color: #6E6862; }

/* --- « Continuer avec Google » (porteur, 18/09/2026) ---------------------------------------
   Le logo est le G COLORÉ de Google (SVG embarqué, super-tiny-icons, MIT), sur le modèle du
   formulaire de RapidoImmo. Le SVG est carré et porte son propre fond blanc : on l'arrondit
   légèrement pour qu'il ne fasse pas une tache sur le bouton, et on le laisse à sa taille — un
   logo de marque ne se recolore pas. */
.btn-google-logo { flex: 0 0 auto; border-radius: .25rem; }

/* Le bouton « œil » À CÔTÉ D'UN CHAMP FLOTTANT (18/09/2026). Dans un `.input-group`, les enfants
   s'étirent à la hauteur du plus haut : le bouton, avec le rembourrage vertical de la charte,
   dépassait le champ de douze pixels et le groupe prenait sa hauteur. On lui retire ce rembourrage
   et on centre son icône — c'est le champ qui donne la hauteur, comme il se doit. */
.input-group > .form-floating + .btn { display: inline-flex; align-items: center; padding-block: 0; }

/* --- SÉPARATEUR DE SECTIONS (porteur, 18/09/2026) -------------------------------------------
   « Retirer l'utilisation des cards. Mettre pour l'instant un simple <hr> pour délimiter. Il est
   autorisé de remplacer ce <hr> par une image fine d'une étincelle (comme le logo). »

   C'est donc un vrai <hr> — un séparateur, pour le sens comme pour les lecteurs d'écran — habillé
   d'une étincelle au centre. Trois fonds superposés, et pas un élément de plus : l'étincelle, puis
   deux dégradés qui font les traits et s'effacent avant elle. `opacity: 1` annule le gris que
   Bootstrap pose par défaut sur <hr>. */
.lou-separateur {
    border: 0; height: 1.5rem; margin: 2rem 0; opacity: 1;
    background:
        url('/assets/img/ornements/etincelle.svg') center / 1.5rem no-repeat,
        linear-gradient(to right, transparent, var(--lou-loup-clair) 18%, var(--lou-loup-clair) calc(50% - 1.6rem), transparent calc(50% - 1.6rem)) center / 100% 2px no-repeat,
        linear-gradient(to left,  transparent, var(--lou-loup-clair) 18%, var(--lou-loup-clair) calc(50% - 1.6rem), transparent calc(50% - 1.6rem)) center / 100% 2px no-repeat;
}
/* Le premier séparateur d'une page n'a rien à séparer d'au-dessus : il respire moins. */
.lou-separateur:first-of-type { margin-top: 1.25rem; }
/* Le séparateur FIN (23/09) : entre deux groupes d'un même chapitre — même étincelle, filet plus
   court, marges plus serrées. Un ornement plein entre l'âge et l'année scolaire aurait fait un
   chapitre de chaque question. */
.lou-separateur--fin { height: 1.1rem; margin: 1.25rem 0 1.5rem;
    background:
        url('/assets/img/ornements/etincelle.svg') center / 1.1rem no-repeat,
        linear-gradient(to right, transparent 20%, var(--lou-loup-clair) 34%, var(--lou-loup-clair) calc(50% - 1.2rem), transparent calc(50% - 1.2rem)) center / 100% 2px no-repeat,
        linear-gradient(to left,  transparent 20%, var(--lou-loup-clair) 34%, var(--lou-loup-clair) calc(50% - 1.2rem), transparent calc(50% - 1.2rem)) center / 100% 2px no-repeat; }
/* L'étincelle comme ornement nommé, pour les vues qui déclinent les quatre dessins. */
.lou-separateur--etincelle { background-image: url('/assets/img/ornements/etincelle.svg'),
    linear-gradient(to right, transparent, var(--lou-loup-clair) 18%, var(--lou-loup-clair) calc(50% - 1.6rem), transparent calc(50% - 1.6rem)),
    linear-gradient(to left,  transparent, var(--lou-loup-clair) 18%, var(--lou-loup-clair) calc(50% - 1.6rem), transparent calc(50% - 1.6rem)); }
/* VARIER L'ORNEMENT (porteur, 19/09/2026) : « que ce ne soit pas toujours le même icône ». Quatre
   dessins du village, tous faits à la main dans l'ocre de la charte — l'étincelle du logo, le
   château, la baguette, le sapin. Seule l'image change ; le filet, la taille et les marges restent
   ceux du séparateur, sinon ce serait quatre séparateurs au lieu d'un, décliné.
   Le nom dit le DESSIN et non la section : le jour où les sections changent d'ordre, rien à
   renommer — c'est la vue qui choisit lequel elle pose. */
.lou-separateur--chateau  { background-image: url('/assets/img/ornements/chateau.svg'),
    linear-gradient(to right, transparent, var(--lou-loup-clair) 18%, var(--lou-loup-clair) calc(50% - 1.6rem), transparent calc(50% - 1.6rem)),
    linear-gradient(to left,  transparent, var(--lou-loup-clair) 18%, var(--lou-loup-clair) calc(50% - 1.6rem), transparent calc(50% - 1.6rem)); }
.lou-separateur--baguette { background-image: url('/assets/img/ornements/baguette.svg'),
    linear-gradient(to right, transparent, var(--lou-loup-clair) 18%, var(--lou-loup-clair) calc(50% - 1.6rem), transparent calc(50% - 1.6rem)),
    linear-gradient(to left,  transparent, var(--lou-loup-clair) 18%, var(--lou-loup-clair) calc(50% - 1.6rem), transparent calc(50% - 1.6rem)); }
.lou-separateur--sapin    { background-image: url('/assets/img/ornements/sapin.svg'),
    linear-gradient(to right, transparent, var(--lou-loup-clair) 18%, var(--lou-loup-clair) calc(50% - 1.6rem), transparent calc(50% - 1.6rem)),
    linear-gradient(to left,  transparent, var(--lou-loup-clair) 18%, var(--lou-loup-clair) calc(50% - 1.6rem), transparent calc(50% - 1.6rem)); }

/* --- LE SOMMAIRE COLLANT DES PAGES LONGUES (porteur, 19/09/2026) ----------------------------
   Un écran d'options de jeu se lit toujours pareil : un sommaire à gauche qui reste sous les yeux,
   des chapitres à droite. La règle du workspace demande la même chose des pages légales. Ces deux
   classes servent donc CINQ pages — réglages, profil, mentions, crédits, conditions,
   confidentialité — et leur nom ne dit plus une page en particulier. Le collant est celui de Bootstrap (`position: sticky`), avec une réserve
   sous le bandeau FIXE du site — sinon le sommaire se glisse dessous au premier défilement.
   Sous 992 px il n'y a plus deux colonnes : le sommaire redevient un simple bloc en tête, et
   coller quoi que ce soit sur un téléphone volerait un tiers de l'écran. */
.page-flanc { position: sticky; top: calc(var(--lou-entete-h) + 1rem); }
@media (max-width: 991.98px) { .page-flanc { position: static; } }
.page-sommaire { margin: .75rem 0; gap: .15rem; }
.page-sommaire .nav-link { color: var(--lou-encre); border-radius: .6rem; padding: .45rem .7rem;
    display: flex; align-items: center; gap: .55rem; }
.page-sommaire .nav-link .bi { color: var(--lou-ocre); font-size: 1.05rem; }
.page-sommaire .nav-link:hover { background: var(--lou-parchemin); }
/* `.active` est posé par ScrollSpy (Bootstrap), jamais à la main : c'est le défilement qui dit
   quel chapitre on lit. */
.page-sommaire .nav-link.active { background: var(--lou-parchemin); font-weight: 700; color: var(--lou-sapin-fonce); }
.page-sommaire .nav-link.active .bi { color: var(--lou-sapin-fonce); }
/* L'icône d'un titre de réglage : elle met en contexte, elle ne crie pas. Même ocre que les
   séparateurs, jamais plus grosse que le texte qu'elle accompagne. */
.reglage-icone { color: var(--lou-ocre); margin-right: .1rem; }

/* --- OUI, NON, SANS OBJET (porteur, 19/09/2026) ---------------------------------------------
   Sur la page de confidentialité, ce qu'un parent cherche d'abord, c'est la colonne des « Non ».
   Les mots seuls, en gris dans un tableau de huit lignes, ne se voyaient pas.
   LE SENS DES COULEURS EST DIT DANS LA PAGE, au-dessus du tableau : le vert n'est pas « bien »,
   il veut dire « cette donnée existe chez nous » ; le rouge n'est pas « mal », il veut dire
   « elle n'existe pas ». Sans cette légende, chacun devine, et devine de travers.
   Le MOT reste écrit à côté de l'icône : une couleur seule ne se lit ni en noir et blanc, ni avec
   un filtre daltonien, ni à voix haute. */
.reponse { display: inline-flex; align-items: center; gap: .35rem; font-weight: 700; white-space: nowrap; }
.reponse-oui  { color: var(--lou-sapin-profond); }
.reponse-non  { color: var(--lou-rouge-suisse); }
.reponse-rien { color: var(--lou-loup-texte); font-weight: 500; }
.legende-reponses { font-size: var(--lou-fs-petit); color: var(--lou-loup-texte);
    display: flex; flex-wrap: wrap; align-items: center; gap: .35rem .75rem; margin-bottom: .75rem; }
.legende-reponses .reponse { font-weight: 700; }
/* Les liens vers les autres pages légales, sous le sommaire : une colonne, pas une ligne de
   boutons qui déborderait de la gouttière. */
.page-flanc-liens { margin-top: .75rem; }
.page-flanc-liens .btn-link { padding-block: .15rem; }
/* La liste de ce qui n'existe PAS (conditions générales, § gratuité) : une ligne par chose, et
   le « Aucun » en tête de ligne — c'est le mot qu'on scanne. Les lignes respirent parce qu'on
   les lit une à une, pas d'un bloc. */
/* LES ANCRES ATTERRISSENT SOUS LE BANDEAU FIXE : la réserve est portée UNE fois, par
   `scroll-padding-top` sur <html> (hauteur du bandeau + 1 rem, plus haut dans cette feuille).
   `scroll-margin-top` S'AJOUTE à cette réserve — il ne la remplace pas — : la valeur
   « bandeau + 1,5 rem » posée ici en plus faisait atterrir les chapitres 88 px trop bas (mesuré
   le 24/09/2026 à la capture, tests/captures/profil_2409.py). Ne reste qu'un demi-rem d'air,
   pour que le titre ne colle pas au bandeau. ScrollSpy mesure la même position. */
.chapitre-legal, .reglage-section { scroll-margin-top: .5rem; }
.liste-absences li { margin-bottom: .5rem; }
.sources-cgu li { margin-bottom: .35rem; }

/* --- Bouton d'aide en infobulle (porteur, 18/09/2026) ---------------------------------------
   Les phrases d'aide des réglages passent du texte sous le champ à une INFOBULLE après le titre.
   Le bouton est atteignable au clavier et au doigt (Bootstrap ouvre l'infobulle au survol ET à la
   mise au point) : une aide qui ne s'ouvrirait qu'à la souris n'existerait pas sur une tablette. */
.lou-aide {
    display: inline-grid; place-items: center; width: 1.6rem; height: 1.6rem; padding: 0;
    margin-left: .4rem; vertical-align: text-bottom;
    color: var(--lou-sapin-fonce); background: none;
    border: 2px solid var(--lou-loup-clair); border-radius: 50%;
    font-size: .95rem; line-height: 1; cursor: help;
}
.lou-aide:hover, .lou-aide:focus-visible { border-color: var(--lou-ocre); color: var(--lou-ocre-texte); outline: none; }
