/* ValueCHECK — feuille de style */

/* L'attribut `hidden` doit TOUJOURS masquer. La regle du navigateur
   ([hidden]{display:none}) est une regle « user-agent » : toute declaration
   d'auteur portant display la neutralise silencieusement — un .kv{display:grid}
   ou un .grid-2{display:grid} reste alors visible malgre el.hidden = true.
   Regle globale pour eviter ce piege partout, aujourd'hui et plus tard. */
[hidden] { display: none !important; }

:root {
  /* ---- Neutres chauds (spec §3.1) ---- */
  --ground: #f7f4ef;
  --surface: #fffdfa;
  --surface-2: #f2ede5;
  --line: #e8e1d6;          /* filets et separateurs DECORATIFS uniquement */
  --field-border: #918b81;  /* bordure des CONTROLES — WCAG 1.4.11, spec §3.5 */
  --ink: #232a33;
  --ink-soft: #766d60;
  --ink-mute: #908778;

  /* ---- Marque (spec §3.2) ---- */
  --navy: #14406f;
  --navy-deep: #0d2f53;
  --navy-rgb: 20, 64, 111;  /* --navy en triplet decimal, pour rgba() (halos/ombres, spec §3.2) */
  --green: #0e8368;
  --green-light: #17c79d;
  --green-wash: #e4f6ef;

  /* ---- Etats (spec §3.3) ---- */
  --warn: #a86a08;
  --warn-wash: #fdf4e3;
  --danger: #b3413a;
  --danger-rgb: 179, 65, 58;  /* --danger en triplet decimal, pour rgba() (halos/ombres, spec §3.3) */
  --danger-wash: #fbeeed;
  --info-wash: #eaf0f7;
  /* Texte « foncé sur lavis » pour les petits libellés (pastilles, pilules) :
     ni --warn (4,06:1) ni --green (4,19:1) ne passent 4,5:1 sur leur propre
     lavis en texte — ces deux jetons sont calibrés pour d'autres usages
     (bordures, texte sur --surface/--ground). Valeurs vérifiées par
     tests-internes/contrastes.js (PAIRES : « pastille » et « alerte »). */
  --amber-ink: #7d4f06;   /* 6,42:1 sur --warn-wash */
  --green-ink: #0a6e56;   /* 5,54:1 sur --green-wash */

  /* ---- Anneau de focus du basculement MANUEL de theme (tache 5, correction 1)
     :root[data-theme="dark"/"light"] pilote un bascule independant de
     prefers-color-scheme (non cable a ce jour, mais destine a l'etre) : ses
     couleurs ne doivent PAS deriver de --navy/--navy-deep, qui ne prennent
     leurs valeurs sombres qu'A L'INTERIEUR de la media query. Valeurs
     d'origine, inchangees. ---- */
  --focus-ring-dark: #7fb2ff;
  --focus-ring-light: #1666d4;

  /* Menthe du titre d'accueil (.hero h1 .accent-green) — illustration de
     marque distincte de --green-light (role : jauges, degrades, spec §3.2),
     tuned pour la lisibilite sur le degrade du hero precisement. */
  --mint: #7ff0cf;

  /* ---- Rayons et ombres (spec §3.6) — trois paliers ---- */
  --r-s: 12px;   /* champ */
  --r: 16px;     /* carte */
  --r-l: 20px;   /* panneau, modale */
  --shadow-s: 0 4px 12px rgba(45, 38, 26, .07);
  --shadow: 0 10px 26px rgba(45, 38, 26, .10);
  --shadow-l: 0 16px 38px rgba(45, 38, 26, .14);

  /* ---- Typographie (spec §2.1) : AUCUNE police telechargee.
     La CSP porte font-src 'self'. Romaine pour les titres, le logo et le
     sommaire ; lineale pour le corps ET les chiffres. ---- */
  --font-serif: Georgia, "Iowan Old Style", "Palatino Linotype", serif;
  --font-sans: ui-sans-serif, "Segoe UI Variable Text", "Segoe UI", system-ui, sans-serif;

  /* ---- COMPATIBILITE report.css — NE PAS RETIRER ----
     report.css n'a AUCUN :root : il consomme celui-ci, 88 fois, sur douze
     jetons (--line x22, --ink-soft x17, --accent x12, --brand x9, --radius-s x7,
     --ink x6, --brand-dark x5, --shadow x3, --radius x3, --surface x2,
     --shadow-hover x1, --danger x1). Retirer ces noms sans alias rend les 88
     var() invalides : la declaration entiere est alors ignoree au calcul, et
     bordures, fonds, ombres et rayons disparaissent sans erreur visible.
     Ce sont des ALIAS, pas des valeurs : aucune couleur litterale ici. */
  --bg: var(--ground);
  --brand: var(--navy);
  --brand-rgb: var(--navy-rgb);  /* correction round 1/5 (tache 11) : pour rgba() de halo/ombre, cf. §3.2 */
  --brand-dark: var(--navy-deep);
  --accent: var(--green);
  --radius: var(--r);
  --radius-s: var(--r-s);
  --shadow-hover: var(--shadow-l);
  --font: var(--font-sans);
  --font-display: var(--font-serif);
}

/* ---- Typographie moderne & aérée ---- */
body { letter-spacing: 0.005em; }
h1, h2, h3, h4, .section-title, .hero h1 {
  font-family: var(--font-serif);
  /* Georgia porte un oeil plus large et des approches deja fermees : le -0,022em
     herite de la lineale tasse les capitales. Un tiers du serrage suffit.
     Pas de `color:` sur ce selecteur nu : .hero h1 et .resultat-kicker sont
     blancs sur fond fonce et n'ont pas de couleur propre — la couleur de
     titre se pose composant par composant. */
  letter-spacing: -0.008em;
  font-weight: 700;
}
.accent-green { color: var(--green); }

/* ---- Animations globales ---- */
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}
@keyframes popIn {
  from { opacity: 0; transform: scale(0.96); }
  to { opacity: 1; transform: none; }
}
#app > * { animation: fadeUp 0.45s ease both; }
/* Round 1, tache 8 : `both` figeait `transform` a `none` en PERMANENCE des la
   fin de l'animation d'entree (meme mecanisme que le bug .wrap-wizard .card
   corrige plus haut) — verifie au navigateur, .feature:hover ne se soulevait
   jamais. Ici, delai non nul selon la position (nth-child) : un simple
   retrait du fill-mode (comme pour .card, delai 0) aurait fait clignoter la
   tuile a pleine opacite pendant le delai avant de sauter a l'etat "from".
   `backwards` tient l'etat de depart pendant le delai (pas de flash) SANS
   figer `transform` apres coup (pas de `forwards`) : .feature:hover reprend
   la main normalement une fois l'entree terminee. */
.features .feature { animation: fadeUp 0.5s ease backwards; }
.features .feature:nth-child(1) { animation-delay: 0.05s; }
.features .feature:nth-child(2) { animation-delay: 0.12s; }
.features .feature:nth-child(3) { animation-delay: 0.19s; }
.features .feature:nth-child(4) { animation-delay: 0.26s; }
.hero-badges .hero-badge { animation: fadeUp 0.5s ease both; }
.hero-badges .hero-badge:nth-child(1) { animation-delay: 0.15s; }
.hero-badges .hero-badge:nth-child(2) { animation-delay: 0.25s; }
.hero-badges .hero-badge:nth-child(3) { animation-delay: 0.35s; }
/* Round 1 : la perspective/rotateX contredisait le niveau 2 (le commanditaire a
   explicitement ecarte le niveau 3 « perspective » — sobriete conseil
   patrimonial). Le nom garde « rise3d » (identifiant CSS interne, non requis
   par du JS) mais le mouvement n'est plus 3D : translation verticale + opacite,
   ce que fadeUp fait deja ailleurs dans ce fichier. Amplitude (18px) et
   timing (0.55s, cf. report.css) conserves — seule la perspective est retiree. */
@keyframes rise3d {
  from { opacity: 0; transform: translateY(18px); }
  to { opacity: 1; transform: none; }
}
@keyframes floaty {
  0%, 100% { transform: rotateY(-12deg) rotateX(5deg) translateY(0); }
  50% { transform: rotateY(-7deg) rotateX(8deg) translateY(-14px); }
}
@keyframes shadowPulse {
  0%, 100% { opacity: 0.9; }
  50% { opacity: 0.45; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* Icônes SVG inline */
.ic { vertical-align: -4px; flex: none; }
.feature .ico { color: var(--brand); }
.hero-badge .ic { flex: none; opacity: 0.95; }
* { box-sizing: border-box; }
html, body { margin: 0; }
body {
  font-family: var(--font);
  color: var(--ink);
  background: var(--bg);
  line-height: 1.55;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
a { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; }
/* Dans un paragraphe, un lien doit rester identifiable SANS la couleur seule
   (daltonisme, WCAG 1.4.1) : soulignement permanent en contexte de texte.
   La navigation et les boutons (hors <p>) restent épurés. */
p a, li a, .msg a, .muted a, .disclaimer a, .partner-legal a, .check-row a { text-decoration: underline; text-underline-offset: 2px; }

/* État de FOCUS visible au clavier sur tous les contrôles personnalisés (les
   champs ont déjà leur anneau) : sans lui, la navigation Tab était invisible. */
/* Couleur PLEINE et non translucide. L'anneau était posé en rgba(...,0.55) : une
   fois composité sur le fond clair il tombait à 2,37:1, sous le minimum de 3:1
   exigé pour un indicateur non textuel. On ne voyait donc pas toujours où l'on
   se trouvait au clavier — ce qui rend la navigation sans souris hasardeuse.
   Mesuré : le bleu de marque plein sur fond blanc = 5,4:1. La variante sombre
   est plus bas, à la fin de la feuille (l'ordre source décide à spécificité égale). */
.btn:focus-visible, .nav a:focus-visible, .seg button:focus-visible, .step:focus-visible,
.partner-choice:focus-visible, .partner-close:focus-visible, a:focus-visible,
.dropzone:focus-within, .photo-thumb button:focus-visible, summary:focus-visible {
  outline: 3px solid var(--navy);
  outline-offset: 2px;
}

/* DÉPÔT DE FICHIER ACCESSIBLE. L'input était `hidden` : ni focusable, ni présent
   dans l'arbre d'accessibilité. Le seul moyen de joindre un diagnostic ou une
   photo était de cliquer la zone à la souris — une impasse complète au clavier.
   Il est désormais dans le flux, simplement masqué à l'œil, et la zone qui
   l'entoure est un <label for> : le clic, la touche Entrée et l'annonce par les
   lecteurs d'écran passent tous par le mécanisme natif du navigateur.
   NE PAS remplacer par display:none / visibility:hidden / hidden : ces trois
   propriétés retirent l'élément du parcours de tabulation. */
.input-fichier {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%);
  overflow: hidden;
  white-space: nowrap;
}
.dropzone { cursor: pointer; }

/* Barre supérieure */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* Le repli est PERMANENT, pas reserve au palier mobile : entre 641 et 900 px
     (tablette en portrait, fenetre de bureau reduite) la barre d'un utilisateur
     connecte — 5 liens plus son nom — depassait la fenetre et faisait defiler
     TOUTE la page lateralement. Autoriser le retour a la ligne a n'importe
     quelle largeur evite d'avoir a ajouter un palier a chaque lien futur. */
  flex-wrap: wrap;
  row-gap: 6px;
  padding: 14px 28px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 500;
}
.brand { display: inline-flex; align-items: center; gap: 9px; font-family: var(--font-display); font-size: 1.4rem; font-weight: 650; color: var(--ink); letter-spacing: -0.02em; }
.brand:hover { text-decoration: none; }
.brand-mark { display: inline-flex; }
.brand-accent { color: var(--brand); }
.brand-check { color: var(--green); font-weight: 800; letter-spacing: 0.01em; }

/* Logo « v » 3D vert */
.vlogo { width: 30px; height: 30px; display: block; filter: drop-shadow(0 3px 5px rgba(10, 120, 85, 0.35)); transition: transform 0.25s ease; }
.brand:hover .vlogo { transform: translateY(-2px) rotate(-4deg); }
.vlogo-report { width: 30px; height: 30px; display: inline-block; vertical-align: -8px; margin-right: 4px; filter: none; }
.nav { display: flex; align-items: center; gap: 8px; }
.nav a { color: var(--ink-soft); font-weight: 600; padding: 8px 14px; border-radius: 999px; transition: background 0.15s, color 0.15s; }
.nav a:hover { color: var(--brand); background: var(--info-wash); text-decoration: none; }
.nav-user { display: flex; align-items: center; gap: 12px; }
.hidden { display: none !important; }

/* Layout */
main { flex: 1; }
.wrap { max-width: 1120px; margin: 0 auto; padding: 32px 24px; }
.wrap-narrow { max-width: 460px; }
.wrap-wizard { max-width: 880px; }  /* formulaire large : 3 champs par ligne */

/* Légende de la carte des prix */
.map-legend { display: flex; flex-wrap: wrap; gap: 20px; margin-bottom: 10px; font-size: 0.92rem; color: var(--ink); }
.map-legend span { display: inline-flex; align-items: center; gap: 7px; }
.map-legend .dot { width: 14px; height: 14px; border-radius: 50%; display: inline-block; }
/* ===== ILLUSTRATION — debut : légende de la carte, appariée aux marqueurs
   Leaflet dessinés dans app.js — spec §4.3, couleurs volontairement hors jetons. */
.map-legend .dot-green { background: #12b28c; }
.map-legend .dot-blue { background: #1666d4; }
.map-legend .dot-white { background: #ffffff; border: 1.5px solid #8a8f98; }
/* ===== ILLUSTRATION — fin */

/* Voile de conversion sur la carte des prix (tache 11) : aucun pattern
   d'incrustation absolue sur un element visible n'existait dans cette feuille
   (.partner-overlay est un MODALE plein ecran, position:fixed -- different
   besoin) ; classe ajoutee. .carte-conteneur fournit le contexte de
   positionnement, dimensionne par .bigmap (report.css) qu'il enveloppe. */
.carte-conteneur { position: relative; }
.carte-voile {
  position: absolute; inset: 0; z-index: 1001;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; text-align: center; padding: 24px;
  background: rgba(255, 255, 255, .93); /* repli neutre */
  background: color-mix(in srgb, var(--surface) 93%, transparent); /* la surface de la refonte, jamais l ancien fond froid */
  backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px);
  border-radius: var(--radius);
}
.carte-voile h2 { margin: 0; font-size: 1.3rem; }
.carte-voile p { margin: 0; max-width: 440px; color: var(--ink-soft); }

/* Onglet « Suivi de mes biens » : cartes de suivi + courbe */
.bien-card { background: var(--card, #fff); border: 1px solid var(--line); border-radius: 16px; padding: 18px 20px; margin-bottom: 16px; box-shadow: 0 2px 10px rgba(6,25,55,.05); }
.bien-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.bien-head .addr { font-weight: 700; font-size: 1.08rem; }
.bien-head .meta { color: var(--ink-soft); font-size: .9rem; margin-top: 2px; }
.bien-val { text-align: right; }
.bien-val .v { font-size: 1.5rem; font-weight: 800; color: var(--brand-dark); }
.bien-val .delta { font-size: .9rem; font-weight: 700; margin-top: 2px; }
.bien-val .delta.up { color: var(--green); }
.bien-val .delta.down { color: var(--danger); }
.bien-trend { font-size: .88rem; margin: 8px 0 2px; }
.bien-chart { margin: 6px 0 4px; }
.bien-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 6px; }
/* Ligne de consentement de transmission (révocable) sous chaque bien suivi. */
.bien-consent { font-size: .84rem; margin: 8px 0 0; line-height: 1.45; }
.lien-bouton { background: none; border: none; padding: 0; font: inherit; color: var(--brand); text-decoration: underline; cursor: pointer; }
.lien-bouton:hover { color: var(--brand-dark); }
.lien-bouton:disabled { opacity: .6; cursor: default; }
.track-legend { display: flex; gap: 18px; flex-wrap: wrap; font-size: .82rem; color: var(--ink-soft); margin-top: 4px; }
.track-legend span { display: inline-flex; align-items: center; gap: 6px; }
/* ===== ILLUSTRATION — debut : légende du graphique de suivi, appariée aux
   séries tracées dans app.js — spec §4.3, couleurs volontairement hors jetons. */
.track-legend .ln { width: 22px; height: 0; border-top: 2.6px solid #1666d4; display: inline-block; }
.track-legend .ln-proj { border-top: 1.8px dashed #9aa4b2; }
/* ===== ILLUSTRATION — fin */

/* Fin de parcours : proposition de transmission à une agence partenaire (modale) */
.partner-overlay { position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center; justify-content: center;
  padding: 20px; background: rgba(10, 22, 40, .55); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
  opacity: 0; transition: opacity .22s ease; overflow-y: auto; }
.partner-overlay.show { opacity: 1; }
.partner-card { position: relative; width: 100%; max-width: 560px; background: #fff; color: var(--ink);
  border-radius: 20px; padding: 26px 26px 20px; box-shadow: 0 24px 60px rgba(6, 25, 55, .35);
  transform: translateY(10px) scale(.98); transition: transform .22s ease; }
.partner-overlay.show .partner-card { transform: none; }
/* Cible tactile ≥ 40 px (recommandation 44 px, WCAG 2.5.8 minimum 24 px) : la
   croix était ~31 px et difficile à viser au pouce. */
.partner-close { position: absolute; top: 8px; right: 10px; border: none; background: none; font-size: 1.7rem; line-height: 1;
  color: var(--ink-soft); cursor: pointer; width: 42px; height: 42px; display: flex; align-items: center; justify-content: center; border-radius: 10px; }
.partner-close:hover { background: var(--info-wash); }
.partner-badge { display: inline-block; font-size: .82rem; font-weight: 800; color: var(--green-ink); background: var(--green-wash); border-radius: 999px; padding: 4px 12px; }
.partner-title { margin: 12px 0 6px; font-size: 1.32rem; }
.partner-sub { margin: 0 0 16px; color: var(--ink-soft); line-height: 1.45; }
.partner-choices { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 480px) { .partner-choices { grid-template-columns: 1fr; } }
.partner-choice { display: flex; flex-direction: column; align-items: center; gap: 4px; text-align: center; cursor: pointer;
  border: 2px solid var(--line); background: #fff; border-radius: 16px; padding: 16px 12px 14px; transition: border-color .15s, transform .15s, box-shadow .15s; }
.partner-choice:hover { transform: translateY(-2px); box-shadow: 0 8px 20px rgba(6, 25, 55, .1); }
.partner-choice:disabled { opacity: .5; cursor: default; transform: none; box-shadow: none; }
.partner-yes { border-color: var(--green-wash); } .partner-yes:hover { border-color: var(--green); }
.partner-no { border-color: var(--info-wash); } .partner-no:hover { border-color: var(--navy); }
.partner-ill { width: 100%; max-width: 138px; margin-bottom: 6px; }
.partner-ill svg { width: 100%; height: auto; display: block; }
.partner-choice-lbl { font-weight: 800; font-size: 1.02rem; }
.partner-choice-desc { font-size: .82rem; color: var(--ink-soft); line-height: 1.3; }
.partner-legal { margin: 16px 0 0; font-size: .78rem; color: var(--ink-soft); line-height: 1.5;
  background: var(--info-wash); border-radius: 12px; padding: 12px 14px; }
.partner-legal a { color: var(--brand); }
.partner-done { text-align: center; }
.partner-done .partner-ill, .partner-done svg { width: 128px; margin: 0 auto 8px; }
.partner-done h3 { margin: 6px 0; } .partner-done p { color: var(--ink-soft); line-height: 1.5; margin: 0 0 16px; }

/* Qualification demandée dans la modale quand le profil est incomplet */
.partner-qualif h3 { margin: 2px 0 6px; }
.partner-qualif .field { margin-top: 12px; }
.partner-qualif-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 18px; }
/* Bloc de qualification du formulaire d'inscription */
/* Animation locale : ne pas dépendre du « deplier » de report.css, qui n'est pas
   chargé sur toutes les pages et plafonne la hauteur (le bloc serait tronqué). */
@keyframes qualifIn { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
.qualif-bloc { margin: 4px 0 10px; padding: 12px 14px; background: var(--info-wash); border: 1px solid var(--line);
  border-radius: var(--radius-s); animation: qualifIn .22s ease both; }
.qualif-bloc > p { margin: 0 0 6px; }
/* Note d'aide sous un champ (pourquoi la donnée est demandée) */
.aide { display: block; margin-top: 5px; font-size: .8rem; color: var(--ink-soft); line-height: 1.4; }

/* Demande du NUMÉRO de voie (adresse sans numéro : estimation refusée) */
.num-requis { margin-top: 10px; background: var(--warn-wash); border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; }
.num-requis p { margin: 0 0 8px; font-size: .9rem; line-height: 1.45; color: var(--amber-ink); }
.num-ligne { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.num-ligne input { flex: 1 1 180px; padding: 10px 14px; border: 1.5px solid var(--field-border); border-radius: var(--radius-s); font-size: 1rem; font-family: inherit; background: #fff; color: var(--ink); }
.num-ligne input:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 4px rgba(var(--brand-rgb),.12); }
.num-ligne .btn { flex: none; }

/* Le montant estimé « monte » à l'affichage : le regard suit le chiffre clé. */
@keyframes valeurIn { from { opacity: 0; transform: translateY(8px) scale(.97); } to { opacity: 1; transform: none; } }
.cover-fig .v, .estimate-box .value { animation: valeurIn .5s cubic-bezier(.22,.7,.3,1) both; animation-delay: .12s; }

/* Champ libre « Autre » révélé sous un select */
.autre-field { margin-top: 8px; animation: autreIn .18s ease; }
@keyframes autreIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

/* Repère d'adresse déplaçable (étape 1) */
.addr-map-wrap { margin-top: 12px; }
.addr-map-hint { font-size: 0.9rem; color: var(--ink-soft); margin-bottom: 8px; line-height: 1.4; }
.addr-map { height: 260px; border-radius: 14px; overflow: hidden; border: 1px solid var(--line); }
.repere-conf { min-height: 20px; margin-top: 6px; }
.repere-ok { display: inline-block; font-size: .88rem; font-weight: 700; color: var(--green-ink); background: var(--green-wash); border-radius: 8px; padding: 3px 10px; }
.addr-map .leaflet-container { cursor: crosshair; }

/* Parcelle cadastrale (etape 1). Les quatre etats ont chacun leur traitement :
   l'utilisateur doit distinguer d'un coup d'oeil « pas de parcelle ici »
   (action possible : deplacer le repere) de « service en panne » (rien a
   faire, l'estimation se poursuit). */
.parcelle-zone { margin-top: .5rem; font-size: .92rem; }
.parcelle-carte { border: 1px solid var(--line); border-radius: 8px; padding: .6rem .8rem; }
.parcelle-carte p { margin: .4rem 0 .5rem; }
.parcelle-aide { display: block; margin-top: .35rem; font-size: .85rem; }
.parcelle-ok { font-weight: 600; }
/* Ordre de saillance = ordre d'utilité : « absente » est le SEUL état qui
   appelle une action (déplacer le repère) — il doit donc être plus visible
   que « panne », qui n'en appelle aucune. « att » (chargement) est
   transitoire et sans enjeu : traitement aussi discret que la panne. */
/* --amber-ink et non --warn : --warn ne rend que 4,37:1 sur --surface,
   sous le 4,5 du texte courant (revue de consolidation du 09/09/2026) ; --amber-ink
   est mesure par contrastes.js sur cette meme carte. Contrepartie sombre plus bas. */
.parcelle-absente { color: var(--amber-ink); font-weight: 600; }
.parcelle-panne { color: var(--ink-soft); font-style: italic; }
.parcelle-att { color: var(--ink-soft); font-style: italic; }
/* Trace de la parcelle sur la carte : className Leaflet, pas de couleur en
   dur dans le JS — cf. l'ambre de .disclaimer-alerte (var(--warn)) pour la
   même idée de « point à examiner ». */
.parcelle-trace { stroke: var(--warn); fill: var(--warn); }

/* Boutons */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: none;
  border-radius: 999px;
  padding: 13px 26px;
  font-size: 1rem;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
  transition: background 0.18s, transform 0.15s, box-shadow 0.18s, border-color 0.18s;
}
.btn:hover { transform: translateY(-2px); box-shadow: var(--shadow-hover); }
.btn:active { transform: translateY(0); box-shadow: none; }
.btn-primary { background: var(--brand); color: #fff; box-shadow: 0 4px 14px rgba(var(--brand-rgb), 0.3); }
.btn-primary:hover { background: var(--brand-dark); }
.btn-ghost { background: transparent; color: var(--brand); border: 1.5px solid var(--line); }
.btn-ghost:hover { border-color: var(--brand); }
.btn-block { width: 100%; }
.btn:disabled { opacity: 0.55; cursor: not-allowed; }

/* Hero */
.hero {
  background: linear-gradient(135deg, var(--navy-deep) 0%, var(--navy) 55%, var(--green) 130%);
  color: #fff;
}
.hero-inner { max-width: 1120px; margin: 0 auto; padding: 72px 24px 88px; display: flex; gap: 48px; align-items: center; }
.hero-text { flex: 1; min-width: 0; }
.hero h1 { font-size: 3.1rem; line-height: 1.06; letter-spacing: -0.035em; font-weight: 800; margin: 0 0 10px; max-width: 16ch; }
.hero h1 .accent-green { color: var(--mint); }  /* vert clair, lisible sur le dégradé */
.hero p.hero-lead { font-size: 1.35rem; font-weight: 600; letter-spacing: -0.01em; opacity: 0.97; margin: 0 0 24px; max-width: 30ch; }
.hero p { font-size: 1.08rem; max-width: 50ch; opacity: 0.9; margin: 0 0 30px; font-weight: 400; line-height: 1.6; }

/* Maison 3D flottante du hero */
.hero-visual { width: 320px; flex: none; perspective: 900px; }
.house3d { width: 100%; transform-style: preserve-3d; animation: floaty 5.5s ease-in-out infinite; filter: drop-shadow(0 18px 24px rgba(4, 20, 45, 0.35)); }
.house3d .house-shadow { animation: shadowPulse 5.5s ease-in-out infinite; }
@media (max-width: 900px) { .hero-visual { display: none; } }
.hero .btn-primary { background: #fff; color: var(--brand-dark); }
.hero .btn-primary:hover { background: var(--info-wash); }
.hero-badges { display: flex; flex-wrap: wrap; gap: 26px; margin-top: 42px; }
.hero-badge { display: flex; align-items: center; gap: 10px; font-weight: 600; opacity: 0.95; }
.hero-badge b { font-size: 1.05rem; }

/* Sections marketing */
.features { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 22px; margin-top: 8px; }
.feature { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 26px; box-shadow: var(--shadow); transition: transform 0.22s cubic-bezier(.2, .7, .3, 1), box-shadow 0.22s ease; }
/* Round 1 : vocabulaire du niveau 2 (meme courbe que .card), perspective
   retiree. Tuile ~240-260px (cf. .features, minmax(240px,1fr)) : scale(1.02)
   plutot que le 1,012 de .card, qui est une carte pleine largeur bien plus
   grande — a cette taille, 1,012 se serait a peine vu. */
.feature:hover { transform: translateY(-5px) scale(1.02); box-shadow: var(--shadow-hover); }
.feature .ico { font-size: 1.8rem; }
.feature h3 { margin: 12px 0 6px; }
.feature p { color: var(--ink-soft); margin: 0; }
.section-title { font-size: 1.7rem; margin: 0 0 6px; }
.section-sub { color: var(--ink-soft); margin: 0 0 26px; }

/* Cartes / formulaires */
.card {
  background: var(--surface);
  border-radius: var(--r);
  padding: 28px;
  box-shadow: var(--shadow);
  transition: transform .26s cubic-bezier(.2, .7, .3, 1), box-shadow .26s ease;
}
.card:hover { transform: translateY(-5px) scale(1.012); box-shadow: var(--shadow-l); }
.card h2 { margin-top: 0; }

/* JAUGE « DOSSIER COMPLET » (F-0, tache 8) — barre de completude PENDANT la
   saisie, posee dans la .card du tunnel (fond var(--surface)).

   AUCUN JETON NEUF, et c'est volontaire : les deux paires de texte employees
   (--ink sur --surface, --ink-soft sur --surface) sont deja verifiees par
   tests-internes/contrastes.js, aucune paire de texte nouvelle n'est creee.

   PISTE ET REMPLISSAGE — mesure du 25/09/2026 (calcul WCAG, memes formules que
   tests-internes/contrastes.js). La piste prend --line, filet DECORATIF
   redefini dans les deux themes. Le remplissage prend --green : 3,62:1 sur la
   piste claire, au-dessus du seuil 3,0 de la regle 1.4.11 — mais seulement
   2,47:1 sur la piste sombre, SOUS le seuil. D'ou la reprise de --green-light
   dans la requete media ci-dessous, mesure a 5,35:1 sur la piste sombre ;
   :root lui donne deja explicitement le role « jauges, degrades » (spec §3.2).
   Aucun des deux jetons n'est redefini en sombre, tous deux resolvent donc
   dans les deux jeux. La transition de largeur tombe d'elle-meme sous
   prefers-reduced-motion (regle globale, plus haut dans cette feuille). */
.jauge-dossier { margin: 0 0 16px; }
.jauge-dossier .jd-tete { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; font-size: 0.92rem; }
.jauge-dossier .jd-titre { font-weight: 600; color: var(--ink); }
.jauge-dossier .jd-part { font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ink); }
.jauge-dossier .jd-piste { margin-top: 7px; height: 8px; border-radius: 999px; background: var(--line); overflow: hidden; }
.jauge-dossier .jd-remplie { height: 100%; border-radius: 999px; background: var(--green); transition: width 0.18s ease; }
.jauge-dossier .jd-detail,
.jauge-dossier .jd-compte { margin: 7px 0 0; font-size: 0.82rem; line-height: 1.45; color: var(--ink-soft); }
@media (prefers-color-scheme: dark) {
  .jauge-dossier .jd-remplie { background: var(--green-light); }
}

.field { margin-bottom: 18px; position: relative; }
.field label { display: block; font-weight: 600; margin-bottom: 6px; font-size: 0.95rem; }
/* .annexe-card/.agrement-card input : leurs champs superficie ne sont PAS dans un
   .field ; sans ce sélecteur ils restaient des boîtes blanches non stylées (flagrant
   en mode sombre). */
.field input, .field select, .field textarea, .annexe-card input, .agrement-card input {
  width: 100%;
  padding: 12px 16px;
  font-size: 1rem;
  font-family: inherit;
  color: var(--ink);
  transition: border-color 0.15s, box-shadow 0.15s;
}
/* Tache 8 : bordure de controle conforme et fond en leger degrade — hors
   perimetre pour .annexe-card/.agrement-card, qui gardent ci-dessous leur
   traitement d'origine (non repris par le brief de cette tache). */
.field input, .field select, .field textarea {
  border: 1px solid var(--field-border);
  border-radius: var(--r-s);
  /* Le second arret est repousse a 160 % (et non 100 %) : un degrade plein
     jusqu'a --surface-2 mesure 2,90:1 avec --field-border au point le plus
     sombre — sous le seuil 3,0 de la 1.4.11. Arrete a 160 %, le bas du champ
     n'atteint que les 5/8e du degrade (3,06:1) : memes deux jetons, aucun
     litteral ajoute, seuil tenu. tests-internes/contrastes.js LIT ce
     `linear-gradient(...)` directement (round 2, tache 8, fonction
     extraireDegradeChampLePlusSombre) et recalcule ce contraste a chaque
     execution — deplacer cet arret y deplace la mesure automatiquement,
     rien a resynchroniser a la main. */
  background: linear-gradient(180deg, var(--surface), var(--surface-2) 160%);
  box-shadow: inset 0 1px 0 #fff, var(--shadow-s);
}
.annexe-card input, .agrement-card input {
  border: 1.5px solid var(--field-border);
  border-radius: var(--radius-s);
  background: #fff;
}
.field input:focus, .field select:focus, .field textarea:focus {
  border-color: var(--green);
  box-shadow: 0 0 0 3px rgba(14, 131, 104, .20);  /* --green a 20 % d'opacite */
  outline: none;
}
.annexe-card input:focus, .agrement-card input:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 4px rgba(var(--brand-rgb), 0.12);
}
/* Champ requis manquant : flash rouge bref pour attirer l'œil quand on a cliqué
   un bouton d'action sans l'avoir renseigné (l'action « ne faisait rien » sinon). */
.field-flash { animation: fieldFlash 1.4s ease; }
@keyframes fieldFlash {
  0%, 100% { box-shadow: none; }
  15%, 55% { box-shadow: 0 0 0 4px rgba(var(--danger-rgb), .38); border-color: var(--danger); }
}
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.seg { display: flex; gap: 10px; }
.seg button {
  flex: 1;
  padding: 13px;
  border: 1.5px solid var(--field-border);
  background: #fff;
  border-radius: var(--radius-s);
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
  color: var(--ink-soft);
  transition: border-color 0.15s, background 0.15s, transform 0.12s;
}
.seg button:hover { transform: translateY(-1px); border-color: var(--brand); }
.seg button.active { border-color: var(--brand); background: var(--info-wash); color: var(--brand-dark); }

/* Autocomplétion adresse */
.autocomplete { position: absolute; top: 100%; left: 0; right: 0; background: #fff; border: 1px solid var(--field-border); border-radius: var(--radius-s); margin-top: 6px; box-shadow: var(--shadow-hover); z-index: 40; overflow: hidden; animation: popIn 0.18s ease both; max-height: 320px; overflow-y: auto; }
.autocomplete .ac-item { padding: 11px 16px; cursor: pointer; font-size: 0.95rem; transition: background 0.12s, padding-left 0.12s; display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.autocomplete .ac-item:hover, .autocomplete .ac-item.active { background: var(--info-wash); padding-left: 20px; }
/* Ambre dédié (--amber-ink) et non var(--warn) : ce dernier ne rend que 4,06:1
   sur var(--warn-wash) — sous le minimum 4,5:1 exigé pour du texte de cette
   taille. --amber-ink est mesuré à 6,4:1 sur ce même lavis. */
.autocomplete .ac-type { font-size: 0.72rem; font-weight: 700; color: var(--amber-ink); background: var(--warn-wash); padding: 2px 8px; border-radius: 999px; white-space: nowrap; flex: none; }
.autocomplete .ac-msg { padding: 14px 16px; font-size: 0.9rem; color: var(--ink-soft); line-height: 1.45; }

/* Messages */
.msg { padding: 13px 18px; border-radius: var(--radius-s); margin-bottom: 16px; font-weight: 600; animation: popIn 0.25s ease both; }
.msg-error { background: var(--danger-wash); color: var(--danger); }
.msg-info { background: var(--info-wash); color: var(--brand-dark); }

/* Résultat */
.result-head { display: grid; grid-template-columns: 1.1fr 1fr; gap: 24px; align-items: stretch; }
@media (max-width: 820px) { .result-head { grid-template-columns: 1fr; } }
.estimate-box { text-align: center; padding: 34px 24px; }
.estimate-box .label { color: var(--ink-soft); font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; font-size: 0.8rem; }
.estimate-box .value { font-size: 3rem; font-weight: 800; color: var(--brand-dark); margin: 6px 0; }
.estimate-box .range { color: var(--ink-soft); font-size: 1.05rem; }
.estimate-box .ppm2 { margin-top: 12px; font-weight: 600; }
.badge { display: inline-block; padding: 5px 14px; border-radius: 999px; font-weight: 700; font-size: 0.85rem; margin-top: 14px; }
.badge.elevee { background: var(--green-wash); color: var(--green-ink); }
.badge.moyenne { background: var(--warn-wash); color: var(--amber-ink); }
.badge.faible { background: var(--danger-wash); color: var(--danger); }

.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 14px; }
.stat { background: var(--info-wash); border-radius: var(--radius-s); padding: 14px; text-align: center; }
.stat .n { font-size: 1.4rem; font-weight: 800; color: var(--ink); }
.stat .l { font-size: 0.8rem; color: var(--ink-soft); }

#map { height: 420px; border-radius: var(--radius); border: 1px solid var(--line); z-index: 1; }

table.comps { width: 100%; border-collapse: collapse; font-size: 0.92rem; }
table.comps th, table.comps td { padding: 10px 12px; text-align: left; border-bottom: 1px solid var(--line); }
table.comps th { color: var(--ink-soft); font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.03em; }
table.comps tbody tr:hover { background: var(--info-wash); }
.table-scroll { overflow-x: auto; }
/* Une zone defilante atteignable au clavier doit MONTRER qu'elle a le focus,
   sinon l'utilisateur ne sait pas que les fleches vont faire defiler le tableau. */
.table-scroll:focus-visible { outline: 3px solid rgba(var(--brand-rgb), 0.55); outline-offset: 2px; }
.num { text-align: right; font-variant-numeric: tabular-nums; }

/* Historique */
.hist-item { display: flex; justify-content: space-between; align-items: center; gap: 16px; padding: 16px 0; border-bottom: 1px solid var(--line); flex-wrap: wrap; }
.hist-item .addr { font-weight: 700; }
.hist-item .meta { color: var(--ink-soft); font-size: 0.9rem; }
.hist-item .price { font-size: 1.25rem; font-weight: 800; color: var(--brand-dark); white-space: nowrap; }
.hist-actions { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.btn-sm { padding: 8px 16px; font-size: 0.88rem; }

/* Divers */
.spinner { width: 22px; height: 22px; border: 3px solid rgba(255,255,255,.4); border-top-color:#fff; border-radius:50%; animation: spin .8s linear infinite; display:inline-block; }
.btn-ghost .spinner, .center .spinner { border-color: rgba(var(--brand-rgb),.25); border-top-color: var(--brand); }
@keyframes spin { to { transform: rotate(360deg); } }
.center { text-align: center; padding: 60px 20px; color: var(--ink-soft); }
.mt { margin-top: 26px; }
.mt-s { margin-top: 14px; }
.muted { color: var(--ink-soft); font-size: 0.9rem; }
/* Indice sous un champ : les choix possibles, et la consequence du silence
   (abstention, presaisie). Place APRES .muted : meme specificite (une seule
   classe), et l'usage au piege du G-1 (app.js) combine `class="muted hint"`
   sur le meme <p> — sans cet ordre, le `font-size: 0.9rem` de .muted
   l'emporterait sur le 0.72rem voulu ici, a specificite egale, par le seul
   fait d'etre déclaré plus bas dans ce fichier.
   --ink-soft rend 5,01 sur --surface / 4,64 sur --ground en clair et 6,35 /
   7,44 en sombre (jeton deja redefini dans le :root sombre) : aucune
   contrepartie sombre requise pour .hint lui-meme. */
.hint { font-size: 0.72rem; color: var(--ink-soft); margin-top: 4px; font-style: italic; }
/* Variante d'erreur : --danger rend 5,54 sur --surface / 5,13 sur --ground en
   clair (mesure ad hoc, absente de contrastes.js) mais seulement 2,76 / 3,23
   en sombre — sous le seuil 4,5 du texte courant. Contrepartie sombre plus
   bas (@media dark), via un jeton deja verifie pour cet usage
   (--msg-danger-ink : 9,19 sur --surface sombre — cf. .msg-error, meme
   substitution), pas un nouveau litteral. */
.hint.hint-erreur { color: var(--danger); font-style: normal; font-weight: 600; }
.disclaimer { background: var(--surface-2); border: 1px dashed var(--line); border-radius: 10px; padding: 14px 16px; color: var(--ink-soft); font-size: 0.88rem; margin-top: 22px; }

/* Pied de page légal : sans ces règles il s'affichait en texte brut non stylé,
   en rupture avec le reste de l'interface. */
.footer { background: var(--surface); border-top: 1px solid var(--line); margin-top: 40px; padding: 26px 28px; color: var(--ink-soft); font-size: 0.85rem; line-height: 1.6; }
.footer a { color: var(--brand); }
.footer p { max-width: 1120px; margin: 0 auto 8px; }

@media (max-width: 640px) {
  .hero h1 { font-size: 2rem; }
  /* La barre passe en 2 lignes au lieu de se tasser/déborder : liens à cibles
     tactiles pleines (padding vertical élargi). */
  .topbar { padding: 10px 14px; flex-wrap: wrap; row-gap: 4px; }
  .nav { gap: 6px; font-size: 0.9rem; flex-wrap: wrap; }
  .nav a { padding: 10px 12px; }
  .grid-2 { grid-template-columns: 1fr; }
  /* Grands montants : 3 rem débordait d'une carte de 320 px sur les valeurs
     à 7 chiffres (« 1 250 000 € ») — réduits, jamais tronqués. */
  .estimate-box .value { font-size: 2.2rem; }
  .bien-val .v { font-size: 1.3rem; }
}


/* ===========================================================================
   MODE SOMBRE — CES BLOCS DOIVENT RESTER LES DERNIERS DE LA FEUILLE.
   Une media query n'apporte AUCUNE specificite. Places en tete de fichier
   (ce qu'ils etaient), leurs declarations etaient ecrasees par les regles
   claires de meme specificite ecrites plus bas : les champs de saisie
   s'affichaient en texte clair sur fond blanc, soit environ 1,18:1 — invisibles.
   Toute nouvelle regle claire doit donc etre ajoutee AU-DESSUS d'ici.
   =========================================================================== */
/* ---- Mode sombre (auto, selon le thème du système) ----
   L'app utilise partout les variables de couleur : les redéfinir suffit pour
   l'essentiel ; on ajuste ensuite les quelques fonds clairs codés en dur.
   Le RAPPORT et le hero gardent leurs couleurs (document imprimable + bannière
   de marque) : on ré-épingle donc les variables claires sur .report.

   PERIMETRE (spec §9) — la refonte du theme sombre est un CHANTIER DISTINCT.
   Les couleurs ci-dessous sont donc CONSERVEES A L'IDENTIQUE (tache 5, tables
   de migration/correction du coordinateur) : neuf jetons renommes vers les
   nouveaux noms sans changement de valeur, plus des proprietes locales
   (--surface-raised, --msg-info-bg, --qualif-bg, --report-*, etc.) qui ne font
   qu'extraire vers un nom chaque couleur qui vivait en dur dans une regle —
   AUCUNE n'est reliee a un role de jeton partage comme le sont les jetons
   clairs (§3.1-3.3). Le zero que rend tests-internes/couleurs.js sur ce
   fichier signifie « aucun literal hors :root », PAS « dette nulle » sur ce
   bloc : la palette sombre elle-meme reste a auditer/redessiner separement. */
@media (prefers-color-scheme: dark) {
  :root {
    --ground: #0e1621;
    --surface: #182534;
    --ink: #e8edf4;
    --ink-soft: #9aa7b8;
    --line: #2a3a4d;
    --navy: #4d9bff;
    --navy-deep: #7db6ff;
    --navy-rgb: 77, 155, 255;  /* correction round 1/5 (tache 11) : --navy sombre en triplet, pour rgba() (halo, ombre) */
    --shadow: 0 8px 30px rgba(0, 0, 0, 0.35);
    --shadow-l: 0 12px 34px rgba(0, 0, 0, 0.5);
    /* Bordure de controle en mode sombre — WCAG 1.4.11 (seuil 3,0). La claire
       #918b81 y rendrait 1,9:1. Retenue #607794 : 3,37 sur --surface sombre,
       3,95 sur --ground sombre. Une premiere valeur (#4a5c72) rendait 2,27 —
       plausible a l'oeil, fausse a la mesure. */
    --field-border: #607794;
    /* ---- Compléments locaux (tâche 5) — mêmes littéraux qu'avant, nommés :
       chaque couleur ci-dessous ne servait qu'à UNE règle codée en dur plus
       bas ; aucune valeur ne change, seule la surface de redéfinition s'étend.

       Fusions envisagées (correction 1, I-3) et ÉCARTÉES — mesurées, pas
       identiques, une fusion aurait donc changé un pixel :
         --surface-active #223b5c / --hover-bg #223142 / --row-hover #20314680 :
         deltas RVB (0,10,26) / (2,10,22) / (2,0,-4) selon les paires.
         --msg-info-bg #16304d / --qualif-bg #16273d : delta RVB (0,9,16).
       Gardées distinctes. */
    --surface-raised: #1f2e40;
    --surface-active: #223b5c;
    --msg-info-bg: #16304d;
    --msg-info-ink: #b9d5ff;
    --msg-danger-bg: #3a1e22;
    --msg-danger-ink: #ffb4b4;
    --badge-danger-ink: #ff9f9f;
    --success-bg: #12352a;
    --success-ink: #58d9a8;
    --badge-warn-bg: #352c12;
    --badge-warn-ink: #e6c766;
    --pill-amber-bg: #3a3212;
    --pill-amber-ink: #ecd98a;
    --panel-bg: #16212e;
    --hover-bg: #223142;
    --row-hover: #20314680;
    --detected-border: #1c5540;
    --detected-ink: #8fe4c4;
    --detected-ink-b: #b6f0d8;
    --qualif-bg: #16273d;
    --qualif-border: #24405f;
    --num-requis-border: #5c4c1c;
    --alerte-bg: #2a2411;
    /* ---- Compléments locaux (tâche 6) — même principe que ci-dessus : ces
       trois couleurs ne vivaient QUE dans report.css (hors :root, donc hors
       jetons), sans équivalent parmi les jetons déjà déclarés ici. Sorties
       vers ce :root, nommées par rôle, valeurs strictement inchangées. */
    --plan-bg: #f4f7fb;         /* fond clair du croquis, conserve tel quel en sombre */
    --plan-piece-ink: #cfe0f7;  /* encre des pastilles de pieces du croquis */
    --report-active-border: #1c8a5e;   /* bordure d'etat actif (carte annexe, chip) */
    /* Valeurs FIGÉES pour le ré-épinglage de .report ci-dessous — ne PAS les
       faire dériver de --ink / --ink-soft / --line / --brand-dark : ce sont
       les mêmes noms que .report réassigne localement, un renvoi vers
       var(--ink) y créerait un cycle (valeur invalide, silencieusement). */
    --report-ink: #14202e;
    --report-ink-soft: #556074;
    --report-line: #e3e8f0;
    --report-brand-dark: #0f4fa8;
  }
  .seg button, .field input, .field select, .field textarea, .annexe-card input, .agrement-card input, .autocomplete, .partner-card, .partner-choice, .bien-card { background: var(--surface-raised); }
  /* Tache 8 : le liseré `inset 0 1px 0 #fff` du step 4 est pensé pour le
     dégradé crème clair — sur --surface-raised (fond sombre), ce blanc plein
     tranche en filet lumineux parasite. Contrepartie sombre : même effet de
     brillance, opacité réduite au lieu d'un littéral hexadécimal. */
  .field input, .field select, .field textarea { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .06), var(--shadow-s); }
  .seg button.active, .nav a:hover, .autocomplete .ac-item:hover, .autocomplete .ac-item.active { background: var(--surface-active); color: var(--brand-dark); }
  .stat { background: var(--surface-raised); }
  .msg-info { background: var(--msg-info-bg); color: var(--msg-info-ink); }
  .msg-error { background: var(--msg-danger-bg); color: var(--msg-danger-ink); }
  /* .hint-erreur : --danger tombe a 2,76 (--surface) / 3,23 (--ground) en
     sombre, sous le seuil 4,5 du texte courant — meme constat que .msg-error
     ci-dessus, meme reprise du jeton deja verifie a cet usage. */
  .hint.hint-erreur { color: var(--msg-danger-ink); }
  /* .parcelle-absente : --amber-ink est un brun fonce, illisible sur fond sombre ;
     reprise du jeton ambre deja verifie en texte sur fond sombre (.ac-type). */
  .parcelle-absente { color: var(--pill-amber-ink); }
  .badge.elevee { background: var(--success-bg); color: var(--success-ink); }
  .badge.moyenne { background: var(--badge-warn-bg); color: var(--badge-warn-ink); }
  .badge.faible { background: var(--msg-danger-bg); color: var(--badge-danger-ink); }
  .disclaimer { background: var(--panel-bg); }
  .partner-legal { background: var(--panel-bg); }
  .partner-close:hover { background: var(--hover-bg); }
  table.comps tbody tr:hover, .kv .item:hover { background: var(--row-hover); }
  .ac-type { background: var(--pill-amber-bg); color: var(--pill-amber-ink); }
  .footer { background: var(--surface); }
  .detected { background: var(--success-bg); border-color: var(--detected-border); color: var(--detected-ink); }
  .detected b { color: var(--detected-ink-b); }
  /* Le RAPPORT reste clair (fidélité du PDF) : on ré-épingle les variables,
     sur les valeurs FIGÉES ci-dessus (voir leur commentaire : pas de var(--ink)
     ici, cycle garanti). */
  .report, .report .page {
    --ink: var(--report-ink); --ink-soft: var(--report-ink-soft); --line: var(--report-line); --surface: #fff; --brand-dark: var(--report-brand-dark);
  }
  .report .page { background: #fff; color: var(--ink); }
  .report .kv .item { background: #fff; }
}

@media (prefers-color-scheme: dark) {
  .qualif-bloc { background: var(--qualif-bg); border-color: var(--qualif-border); }
}

@media (prefers-color-scheme: dark) {
  .num-requis { background: var(--pill-amber-bg); border-color: var(--num-requis-border); }
  .num-requis p { color: var(--pill-amber-ink); }
  .num-ligne input { background: var(--surface-raised); }
}

/* Revue R-08 finale — oubli, pas un choix : fond clair pose EN DUR alors que le
   texte (var(--ink-soft)) bascule seul en sombre. Contraste mesure 2,3:1, sous le
   minimum — c'est le seul texte qui explique a un visiteur anonyme pourquoi
   photos et diagnostic sont grises. Meme traitement que .qualif-bloc, un bloc
   visuellement analogue (meme famille de bleu clair en jour). */
@media (prefers-color-scheme: dark) {
  .bloc-verrou { background: var(--qualif-bg); border-color: var(--qualif-border); }
}

/* Anneau de focus en THÈME SOMBRE. Le bleu de marque plein conserve 3,4:1 sur
   le fond sombre — au-dessus du minimum, mais de peu. Un bleu clair y est
   nettement plus lisible (mesuré 8,4:1), et l'indicateur de focus est
   précisément ce qu'il ne faut pas rendre limite. Placé en FIN de feuille :
   une media query n'ajoute aucune spécificité, c'est l'ordre source qui
   tranche à égalité. */
@media (prefers-color-scheme: dark) {
  .btn:focus-visible, .nav a:focus-visible, .seg button:focus-visible, .step:focus-visible,
  .partner-choice:focus-visible, .partner-close:focus-visible, a:focus-visible,
  .dropzone:focus-within, .photo-thumb button:focus-visible, summary:focus-visible {
    outline-color: var(--navy-deep);
  }
}
:root[data-theme="dark"] .btn:focus-visible,
:root[data-theme="dark"] .nav a:focus-visible,
:root[data-theme="dark"] .seg button:focus-visible,
:root[data-theme="dark"] .step:focus-visible,
:root[data-theme="dark"] .partner-choice:focus-visible,
:root[data-theme="dark"] .partner-close:focus-visible,
:root[data-theme="dark"] a:focus-visible,
:root[data-theme="dark"] .dropzone:focus-within,
:root[data-theme="dark"] .photo-thumb button:focus-visible,
:root[data-theme="dark"] summary:focus-visible { outline-color: var(--focus-ring-dark); }
:root[data-theme="light"] .btn:focus-visible,
:root[data-theme="light"] .nav a:focus-visible,
:root[data-theme="light"] .seg button:focus-visible,
:root[data-theme="light"] .step:focus-visible,
:root[data-theme="light"] .partner-choice:focus-visible,
:root[data-theme="light"] .partner-close:focus-visible,
:root[data-theme="light"] a:focus-visible,
:root[data-theme="light"] .dropzone:focus-within,
:root[data-theme="light"] .photo-thumb button:focus-visible,
:root[data-theme="light"] summary:focus-visible { outline-color: var(--focus-ring-light); }

/* Contenu réservé aux lecteurs d'écran : présent dans l'arbre d'accessibilité,
   invisible à l'œil. Ne PAS utiliser display:none — cela retirerait aussi
   l'élément de cet arbre, et la région d'annonce n'annoncerait plus rien. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%);
  overflow: hidden;
  white-space: nowrap;
}

/* R-08 — sections reservees au compte : visibles mais inertes. On les MONTRE
   plutot que de les masquer : c'est au moment ou l'utilisateur pense a ses photos
   qu'il comprend ce que le compte lui apporte. */
.bloc-verrou {
  margin: 0 0 12px; padding: 10px 14px; border-radius: 8px;
  background: var(--info-wash); border: 1px solid var(--line);
  color: var(--ink-soft); font-size: .88rem;
}
.bloc-fieldset { border: 0; padding: 0; margin: 0; min-width: 0; }
.bloc-fieldset[disabled] { opacity: .55; }
.bloc-fieldset[disabled] .dropzone { cursor: not-allowed; }

/* R-08 — page resultat (apercu anonyme) */
.resultat-carte {
  background: linear-gradient(135deg, var(--navy), var(--navy-deep));
  color: #fff; border-radius: 16px; padding: 30px 28px; text-align: center;
}
/* Le kicker est un <h1> semantique (revue R-08, point 5 : la page n'avait aucun
   titre) ; on neutralise ici la regle globale h1,h2,h3,h4 (gras, marges UA) pour
   qu'il garde exactement l'allure discrete d'origine — seule la semantique change. */
.resultat-kicker { margin: 0; font-size: .95rem; font-weight: 400; opacity: .85; }
.resultat-sub { font-size: .85rem; opacity: .7; margin-top: 2px; }
.resultat-label { margin-top: 20px; font-size: .8rem; letter-spacing: .08em; text-transform: uppercase; opacity: .75; }
.resultat-valeur {
  font-family: var(--font-sans);
  font-weight: 800;
  letter-spacing: -0.035em;
  font-variant-numeric: tabular-nums;
  font-size: 2.9rem;
  line-height: 1.15;
  margin-top: 4px;
  /* Pas de `color:` ici, a la difference du brief de la tache : .resultat-valeur
     n'apparait qu'a un seul endroit (public/js/app.js:3387), toujours dans
     .resultat-carte — fond degrade --navy -> --navy-deep, texte blanc herite
     de la carte (ligne ci-dessus). Un `color: var(--navy)` y rendrait le
     chiffre illisible : meme piege que .hero h1 / .resultat-kicker au step 1,
     non signale par le brief pour ce composant precis. */
}
/* Point de rupture recale sur le CONTENEUR, pas la fenetre (revue R-08, point 6).
   .wrap-narrow plafonne a 460px et .wrap a 24px de marge interieure fixe : la
   largeur reelle disponible ici ne depasse JAMAIS ~412px, quelle que soit la
   fenetre. Une @media sur la largeur de fenetre etait donc keyee sur la mauvaise
   mesure — au-dela de son seuil (560px) elle imposait une ligne alors que la
   carte, elle, n'avait jamais grandi : pire sur grand ecran que sur mobile. La
   colonne est desormais la disposition par defaut (et le repli si @container
   n'est pas supporte) ; la ligne n'est autorisee que si le CONTENEUR mesure
   reellement assez de place. */
.resultat-fourchettes { display: grid; gap: 8px; margin-top: 20px; text-align: left; container-type: inline-size; }
.resultat-fourchettes > div {
  display: flex; flex-direction: column; gap: 2px;
  padding: 9px 14px; border-radius: 9px; background: rgba(255, 255, 255, .1);
}
@container (min-width: 300px) {
  .resultat-fourchettes > div { flex-direction: row; justify-content: space-between; align-items: baseline; gap: 14px; }
}
.resultat-fourchettes .f-lbl { opacity: .8; font-size: .88rem; }
.resultat-fourchettes .f-val { font-weight: 600; font-size: .92rem; }
/* Bloc de diagnostic en alerte. Le fond creme etait pose en STYLE EN LIGNE, ce qui
   ecrasait le fond sombre de .disclaimer sans toucher a la couleur du texte : en
   theme sombre, texte clair sur creme, illisible. On passe par une classe, traitee
   dans les deux themes. */
.disclaimer-alerte { border-color: var(--warn); background: var(--warn-wash); color: var(--amber-ink); }
@media (prefers-color-scheme: dark) {
  .disclaimer-alerte { background: var(--alerte-bg); color: var(--ink); border-color: var(--warn); }
}
/* Titre du bloc de fragilite, desormais un <h2> semantique (revue R-08, point 5) :
   on neutralise les marges UA / de la regle globale h1,h2,h3,h4 pour retrouver
   l'allure d'origine (simple ligne en gras en tete de l'encadre). */
.disclaimer-titre { margin: 0 0 2px; font-size: .88rem; font-family: inherit; letter-spacing: inherit; }
.diag-liste { margin: 10px 0 0; padding-left: 20px; }
.diag-liste li { margin-bottom: 8px; font-size: .89rem; line-height: 1.5; }

/* DETAIL DE LA FIABILITE (F-0, tache 9) — les quatre panneaux, les deux listes
   et la jauge de completude, dans une .card de l'ecran resultat.

   AUCUN JETON NEUF, AUCUNE PAIRE DE COULEUR NEUVE, et c'est deliberé :
     - les textes sont var(--ink) et var(--ink-soft) sur le fond de .card,
       var(--surface). Les deux paires sont deja mesurees par
       tests-internes/contrastes.js, et dans les DEUX themes (14,26 / 5,01 en
       clair ; 13,19 / 6,35 en sombre, mesure du 26/09/2026) ;
     - les separateurs prennent var(--line), filet DECORATIF au sens de :root :
       aucun seuil de contraste ne s'y applique ;
     - les qualificatifs reutilisent le composant .badge (etats elevee /
       moyenne / faible, l. 599-602 et leur reprise sombre l. 784-786). Mesure
       du 26/09/2026 : 5,54 / 6,42 / 4,97 en clair, 7,59 / 8,37 / 7,71 en
       sombre — les six au-dessus de 4,5. Ces trois etats n'etaient pas
       mesures par la barriere (constat R-42) ; ils le sont desormais, LUS DANS
       CETTE FEUILLE par extraireBadgesQualificatif (contrastes.js).
   .badge porte un margin-top de 14px, pense pour son usage d'origine (sous un
   paragraphe) : il est neutralise ici, ou la pastille est sur la meme ligne que
   le libelle du panneau. C'est une marge, pas une couleur.

   LA JAUGE NE REDEFINIT RIEN : le bloc reutilise les classes .jauge-dossier /
   .jd-* de la tache 8 telles quelles (l. 494-504), y compris leur reprise
   sombre. Seul son detachement du bloc au-dessus est pose ici. */
.bloc-fiabilite .fb-intro { margin: 0; }
.bloc-fiabilite .fb-panneaux { list-style: none; margin: 14px 0 0; padding: 0; }
.bloc-fiabilite .fb-panneau { padding: 12px 0; border-top: 1px solid var(--line); }
.bloc-fiabilite .fb-panneau:first-child { border-top: 0; padding-top: 0; }
.bloc-fiabilite .fb-tete { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.bloc-fiabilite .fb-nom { font-weight: 600; color: var(--ink); }
.bloc-fiabilite .badge { margin-top: 0; flex: none; }
.bloc-fiabilite .fb-sans-qualif { flex: none; font-size: .8rem; color: var(--ink-soft); font-style: italic; }
.bloc-fiabilite .fb-grandeur { margin: 5px 0 0; font-size: .9rem; line-height: 1.45; color: var(--ink); }
.bloc-fiabilite .fb-points { margin: 3px 0 0; font-size: .82rem; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.bloc-fiabilite .fb-plafond { margin: 5px 0 0; font-size: .85rem; line-height: 1.45; color: var(--ink); }
.bloc-fiabilite .fb-renvoi { margin: 3px 0 0; font-size: .82rem; color: var(--ink-soft); }
.bloc-fiabilite .fb-note { margin: 12px 0 0; font-size: .82rem; line-height: 1.45; color: var(--ink-soft); }
.bloc-fiabilite .fb-listes { display: grid; gap: 18px; margin-top: 20px; }
.bloc-fiabilite .fb-listes h3 { margin: 0 0 6px; font-size: .95rem; color: var(--ink); }
.bloc-fiabilite .fb-listes ul { margin: 0; padding-left: 20px; }
.bloc-fiabilite .fb-listes li { margin-bottom: 6px; font-size: .88rem; line-height: 1.5; color: var(--ink); }
.bloc-fiabilite .fb-ecart { color: var(--ink-soft); font-variant-numeric: tabular-nums; white-space: nowrap; }
.bloc-fiabilite .fb-vide { margin: 0; font-size: .88rem; color: var(--ink-soft); }
.bloc-fiabilite .fb-mesure { margin: 16px 0 0; font-size: .8rem; line-height: 1.45; color: var(--ink-soft); }
.bloc-fiabilite .jauge-dossier { margin: 20px 0 0; padding-top: 18px; border-top: 1px solid var(--line); }
/* LES DEUX LISTES RESTENT L'UNE SOUS L'AUTRE, et ce n'est pas un oubli de
   `grid-template-columns`. Mesure au navigateur le 26/09/2026 : cet ecran vit
   dans .wrap-narrow, plafonne a 460px (l. 249) moins 48px de marge interieure
   de .wrap et 56px de .card, soit ~356px de texte utile. Deux colonnes y font
   166px chacune — « Ce qui fonde cette note » passe alors sur trois lignes et
   chaque puce se brise a trois ou quatre mots. Un point de rupture sur la
   largeur de la FENETRE n'y changerait rien : c'est le CONTENEUR qui est
   etroit, et il l'est a toutes les largeurs de fenetre. */
.resultat-cta .debloque { list-style: none; margin: 16px 0 20px; padding: 0; display: grid; gap: 12px; }
.resultat-cta .debloque li { display: flex; gap: 12px; align-items: flex-start; }
.resultat-cta .debloque li .ic { color: var(--brand-dark); flex: 0 0 auto; margin-top: 2px; }
.resultat-cta .debloque li b { display: block; font-size: .93rem; }
.resultat-cta .debloque li span { display: block; font-size: .84rem; color: var(--ink-soft); }
@media (max-width: 560px) {
  .resultat-valeur { font-size: 2.2rem; }
}
