/* ═══════════════════════════════════════════════════════════════════
   LA VIGNETTE DE BIEN — feuille unique, partagée par tout le site
   ───────────────────────────────────────────────────────────────────
   Ce dessin vivait dans le <style> de index.html. Il est désormais
   réclamé sur cinq pages : l'accueil, les Opportunités, les six guides,
   la Prospection et Mes biens. Le recopier cinq fois, c'est accepter
   qu'il diverge — on l'a vu cette semaine avec les frais de notaire
   calculés sur deux bases différentes dans la même page.

   Une seule feuille, donc. Elle porte le nom de classe `opp-card`,
   celui qu'utilisaient déjà l'accueil et les guides : renommer sept
   fichiers pour gagner en justesse de vocabulaire aurait coûté plus
   que ça ne rapporte.

   UN SEUL RÉGLAGE DE TAILLE
   `--opp-carte` commande tout. Chaque dimension du dessin est un
   pourcentage de la largeur de la carte — polices, cœur, rayons,
   marges, bouton. Changez ce nombre et l'ensemble suit.
   ═══════════════════════════════════════════════════════════════════ */

/* ════════════════════════════════════════════════════════════════════
   OPPORTUNITES — la variante douce
   ────────────────────────────────────────────────────────────────────
   Ce que ce dessin fait et que le precedent ne faisait pas : il laisse
   la photo occuper toute la carte. Le cadre bleu ramenait les annonces
   au meme registre, mais il mangeait un quart de la vignette pour du
   vide colore. Ici la photo va bord a bord, et c'est une courbe blanche
   qui remonte du bas pour porter le prix — le blanc du corps deborde
   dans l'image au lieu de la couper net.

   Trois niveaux de lecture, dans l'ordre ou l'oeil les prend :
     1. la photo et le prix, ensemble ;
     2. l'adresse, puis le rendement et le loyer cote a cote ;
     3. l'economie et le bouton, sur un pied lavande separe par un
        angle rentrant — le meme creux que sur la maquette.

   Le rendement porte un asterisque et l'economie un bouton d'aide : ces
   deux nombres reposent sur des hypotheses, et une carte qui les montre
   gros doit dire ou les verifier.
   ══════════════════════════════════════════════════════════════════ */
/* La maquette arrivait avec ses propres teintes : un lavande #eeebff et
   une bordure #e1e2ec, tous deux tirant sur le violet. Aucun des deux
   n'existe dans la palette du site — ce sont des couleurs d'auteur, pas
   les votres. On prend les equivalents de marque : le bleu a 10 %, qui
   joue exactement le meme role de fond clair, et la bordure du site. */
/* Les reglages vivent sur :root et non sur un conteneur de page.
   Ils etaient poses sur « #opportunites, .opp-marquee » — deux selecteurs de
   l'accueil. Dans les guides, ou les vignettes vivent dans un carrousel,
   aucun des deux n'existe : la carte se retrouvait sans largeur de reference
   et sans rapport de photo, donc haute de 269 px au lieu de 537. Une feuille
   partagee ne peut pas dependre du balisage d'une seule page. */
:root {
  /* LE FOND DU PIED, ET CE QUI DOIT SUIVRE AVEC LUI.
     Trois variables et non une : changer le fond seul rendrait le texte
     illisible et ferait disparaitre le bouton, qui etait justement de la
     meme couleur. Pour revenir au lavande, remettre les trois valeurs
     entre parentheses. */
  --opp-lavande: var(--blue, #405AD2);        /* lavande : var(--blue-light, #e8ebfe) */
  --opp-pied-texte: #fff;                     /* lavande : var(--blue-dark, #04024D) */
  --opp-pied-bouton: #fff;                    /* lavande : var(--blue, #405AD2)      */
  --opp-pied-bouton-texte: var(--blue, #405AD2); /* lavande : #fff                   */
  --opp-pied-aide: #fff;                      /* lavande : var(--accent, #ed797b)    */
  --opp-pied-aide-i: var(--blue, #405AD2);    /* lavande : #fff                      */

  /* LES DEUX PASTILLES POSEES SUR LA PHOTO — le compteur a gauche, le
     favori a droite. Elles vivaient chacune sa vie : 17 px de haut a 10 px
     du bord pour l'une, 44 px a 15 px du bord pour l'autre. Deux coins qui
     ne se repondaient pas, et un compteur a 7,8 px de police, sous le seuil
     du lisible. Une hauteur et un retrait communs, ici, pour qu'ils ne
     puissent plus diverger. */
  --opp-coin: 3.4cqw;
  --opp-pastille: 9.7cqw;
  --opp-bord: var(--border, #e2e0db);
  --opp-doux: var(--gray-500, #6c6a94);
  /* Tout est proportionnel a la largeur de la carte. Les tailles de
     police etaient deja en `cqw` — un pourcentage de cette largeur — mais
     les dimensions fixes de la maquette (coeur, rayons, marges, bouton)
     ne l'etaient pas : reduire la carte les laissait a leur taille et
     cassait les proportions. Elles sont converties, base 520 px, ou
     1 cqw valait 5,2 px.
     Le rayon de la carte ne peut pas etre en `cqw` — un element ne se
     mesure pas lui-meme — il se calcule donc sur --opp-carte. */
  --opp-rayon: calc(var(--opp-carte) * 0.0577);
  /* LE SEUL REGLAGE DE TAILLE. Tout le dessin est exprime en pourcentage
     de la largeur de la carte : ce nombre commande le prix, le titre, le
     rendement, le bouton et les marges d'un coup.

     341 px, c'est la largeur des vignettes actuellement en ligne : trois
     colonnes dans les 1 120 px de la grille du site, moins les
     gouttieres. La maquette dessinait a 516 px ; tout le reste etant
     proportionnel, la carte se reduit sans se deformer. */
  --opp-carte: 341px;
  /* La largeur plancher d'une colonne, pour les grilles du site :
     `repeat(auto-fill, minmax(min(100%, var(--opp-carte-min)), 1fr))`.
     Elles retirent une colonne plutot que de serrer les cartes — a 611 px
     de fenetre, deux colonnes donnaient 251 px de carte, le prix debordait
     de la courbe blanche et « 1 008 €/mois » sortait du cadre.
     Cinq pixels sous --opp-carte, et pas zero : a 1440 px, trois colonnes
     de 341 plus deux gouttieres de 28 font 1079 pour 1072 disponibles, et
     Mes biens perdait sa troisieme colonne pour sept pixels. Le maximum
     reste `1fr` et non 341 : c'est le MAXIMUM, quand il est chiffre, qui
     sert a compter les colonnes — un plancher a 336 face a un plafond a
     341 ne changeait donc rien du tout. */
  --opp-carte-min: 336px;
  /* Le format des photos d'annonce, releve dans data/properties.json :
     les 277 vues telechargees sont TOUTES en 525x394, soit 4:3. Le 1,43
     de la maquette en rognait sept pour cent en haut et en bas — un
     plafond, un bout de facade. Au format des photos, rien n'est coupe. */
  --opp-photo: 4 / 3;
}
.opp-marquee { width: 100%; }
/* Trois colonnes, comme aujourd'hui en ligne. */
.opp-track {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px; justify-items: center;
  max-width: 1120px; margin: 0 auto; padding: 0 24px;
}

.opp-card {
  /* Le plafond de largeur, et c'est lui qui regle tout le reste.
     Chaque taille de la maquette est un pourcentage de la largeur de la
     carte : a 462 px — une fenetre etroite, une seule colonne — le prix
     montait a 41 px et le rendement a 55. Le texte n'y est pour rien,
     c'est la carte qui s'etalait. Plafonnee a 380, elle se comporte
     partout comme dans la grille a trois colonnes, ou le dessin a ete
     valide. */
  /* width:100% est indispensable : « justify-self: center » fait perdre a
     l'element son etirement, et une carte en display:block sans largeur
     retombe alors sur la largeur de son contenu — mesure faite, 2 px. */
  min-width: 0; width: 100%; max-width: var(--opp-carte); justify-self: center;
  container-type: inline-size;
  /* Une colonne, et non un bloc. Dans une grille, les cartes d'une meme
     rangee s'etirent a la hauteur de la plus haute — c'est voulu, elles
     finissent alignees. Mais un bloc ne repartit pas cette hauteur en
     trop : elle s'ajoutait APRES le dernier enfant, et le pied lavande se
     retrouvait a trente-six pixels du bas, sur du blanc. Visible des qu'une
     adresse tient en deux lignes et sa voisine en une. */
  display: flex; flex-direction: column; position: relative;
  background: #fff; border: 1px solid var(--opp-bord);
  border-radius: var(--opp-rayon); overflow: hidden;
  text-decoration: none; cursor: pointer;
  transition: box-shadow 0.2s, transform 0.2s;
}
.opp-card:hover {
  box-shadow: 0 12px 26px rgba(4, 2, 77, 0.043);
  transform: translateY(-3px);
}

/* ── La photo, et la courbe qui porte le prix ── */
.opp-card__img {
  /* La photo garde sa proportion quoi qu'il arrive : sans cela, c'est elle
     que la colonne comprimerait pour absorber la difference de hauteur. */
  flex: none;
  /* Deuxieme et dernier reglage de taille, avec --opp-carte : la hauteur
     de la photo. Plus le nombre est petit, plus la photo est haute.
     1,43 est la valeur de la maquette ; en 16:9 (1,78) elle perdait 47 px
     et la carte paraissait bavarde. */
  position: relative; aspect-ratio: var(--opp-photo); overflow: hidden;
  background: var(--blue-pale, #f2f3fe); isolation: isolate;
  /* Arrondi en HAUT seulement. La maquette arrondissait les quatre coins
     de la zone photo ; en bas, la courbe blanche du prix se faisait alors
     rogner par cet arrondi, et un eclat de photo reapparaissait sous le
     blanc, a gauche — l'angle qui bugait. En bas, la carte elle-meme
     porte l'arrondi et le recadrage : la zone photo n'a rien a arrondir. */
  border-radius: calc(var(--opp-rayon) - 1px) calc(var(--opp-rayon) - 1px) 0 0;
  padding: 0; border: 0;
}
/* ── La piste de photos ──
   Un defilement horizontal natif : le doigt fonctionne sans une ligne de
   JavaScript, et `scroll-snap` cale chaque vue. Les fleches ne font que
   pousser cette meme piste — elles ne sont pas un second mecanisme.
   Pas de `touch-action` : j'y avais mis `pan-x`, ce qui reserve la piste
   au geste horizontal — et interdit purement et simplement le geste
   vertical, sans le passer a la page. Un pouce qui part sur la photo pour
   faire descendre l'accueil ne faisait plus rien. Laisse a lui-meme, le
   navigateur fait le bon choix : horizontal pour la piste, vertical pour
   la page. */
.opp-card__piste {
  position: absolute; inset: 0;
  display: flex; overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory;
  /* PAS de `scroll-behavior: smooth` ici. Pose en CSS, il fait passer
     TOUS les defilements par l'animation du navigateur — y compris
     l'inertie du doigt et de la molette, qui se retrouvent en retard sur
     le geste. C'est ce qui manquait de fluidite. Les fleches, elles,
     demandent le lissage au coup par coup dans leur appel a scrollBy. */
  scrollbar-width: none; -ms-overflow-style: none;
  overscroll-behavior-x: contain;
}
.opp-card__piste::-webkit-scrollbar { display: none; }
/* Les vues, et elles seules. La regle visait « .opp-card__img img » — donc
   TOUTE image posee sur la photo. La pastille « Propose par » de Mes biens
   porte l'avatar du conseiller : il heritait de `flex: 0 0 100%` et occupait
   toute la largeur de la pastille, 141 px pour un rond de 26. Une largeur
   posee a cote n'y changeait rien, la base flex prime. */
.opp-card__piste img {
  flex: 0 0 100%; width: 100%; height: 100%;
  object-fit: cover; object-position: center;
  display: block; border-radius: 0;
  scroll-snap-align: center;
  /* Un balayage rapide sautait plusieurs vues d'un coup. « always » borne
     le geste a une photo : on avance d'une image, jamais de trois. */
  scroll-snap-stop: always;
  -webkit-user-drag: none; user-select: none;
}

/* ── Fleches et compteur ──
   Des span, pas des bouton : la carte entiere est un lien, et un bouton
   dans un lien est du balisage invalide. Le role est porte par l'attribut,
   et le gestionnaire de clic de la carte les intercepte avant de naviguer. */
.opp-card__fleche {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 3;
  display: grid; place-items: center;
  width: 6.54cqw; height: 6.54cqw; border-radius: 50%;
  background: rgba(255, 255, 255, 0.92);
  color: var(--blue-dark, #04024D); cursor: pointer;
  box-shadow: 0 1px 4px rgba(4, 2, 77, 0.16);
  opacity: 0; transition: opacity 0.2s, background 0.2s;
}
.opp-card__fleche svg {
  width: 3.46cqw; height: 3.46cqw; fill: none; stroke: currentColor;
  stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round;
}
.opp-card__fleche--prec { left: 2.3cqw; }
.opp-card__fleche--suiv { right: 2.3cqw; }
.opp-card:hover .opp-card__fleche,
.opp-card__fleche:focus-visible { opacity: 1; }
.opp-card__fleche:hover { background: #fff; }
/* Sans survol — telephone, tablette — les fleches ne servent a rien : le
   doigt fait defiler. Le compteur, lui, reste : c'est lui qui annonce
   qu'il y a d'autres vues. */
@media (hover: none) {
  .opp-card__fleche { display: none; }
}
.opp-card__compteur {
  position: absolute; top: var(--opp-coin); left: var(--opp-coin); z-index: 3;
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--opp-pastille); padding: 0 3.2cqw; border-radius: 999px;
  background: rgba(4, 2, 77, 0.55); color: #fff;
  font-size: 3.5cqw; font-weight: 600; letter-spacing: -0.01em;
  backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
  pointer-events: none;
}
/* Le trace vient de la maquette, au pixel : le creux part a 42 % de la
   largeur et remonte vers la droite. */
.opp-card__courbe {
  position: absolute; bottom: -1px; left: 0;
  width: 100%; height: 31%; fill: #fff; z-index: 1;
}
.opp-card__prix {
  position: absolute; bottom: 3%; left: 7%; z-index: 2;
  margin: 0; line-height: 1.1;
}
.opp-card__prix dt {
  font-size: clamp(12px, 3.8cqw, 19px); margin: 0 0 6px;
  font-weight: 700; color: var(--blue-dark, #04024D);
}
.opp-card__prix dd {
  margin: 0; font-size: clamp(24px, 9cqw, 46px); font-weight: 700;
  letter-spacing: -0.045em; white-space: nowrap;
  color: var(--blue-dark, #04024D);
}

/* ── Le corps ── */
/* Le bloc du bas arrondit LUI-MEME ses deux coins inferieurs.
   Il s'appuyait sur le rognage de la carte — `overflow: hidden` plus un
   `border-radius`. Ce rognage n'est pas net : sur un ecran a densite 2,
   avec une carte dont le bord gauche tombe a 74,5 px, il reste un eclat
   de lavande a l'exterieur de chaque arrondi. Ce sont les pointes.
   Un element qui porte son propre arrondi n'a plus rien a deborder.
   Moins un pixel, l'epaisseur de la bordure de la carte. */
.opp-card__bas {
  /* Prend toute la hauteur restante et la passe a son bloc blanc : c'est
     lui qui doit grandir, pour que le pied reste colle au bas. */
  flex: 1 1 auto; display: flex; flex-direction: column;
  background: var(--opp-lavande);
  border-radius: 0 0 calc(var(--opp-rayon) - 1px) calc(var(--opp-rayon) - 1px);
}
.opp-card__info {
  position: relative; z-index: 1;
  flex: 1 1 auto; display: flex; flex-direction: column;
  padding: 4.23cqw 7% 6.15cqw; background: #fff;
  border-radius: 0 0 7.69cqw 0;
  color: var(--blue-dark, #04024D);
}
/* L'adresse est ce qu'on retient d'un bien : c'est elle qu'on cherche en
   remontant la page et elle qu'on repete au telephone. Elle arrivait
   pourtant en sixieme position sur sept — 23 px, derriere le prix (30,5),
   l'economie (29,5) et les deux mesures (25,8). Elle passe devant tout
   sauf le prix.

   La taille s'adapte a la longueur : « Rue d'Alesia » tient a 8,8cqw,
   « 225 Avenue Georges Clemenceau » n'y tiendrait pas en deux lignes et
   redescend. C'est mkAjusterTitres(), dans js/main.js, qui pose
   --titre-cqw ; sans JavaScript la valeur par defaut vaut 7,6cqw, ou tout
   ce que le site affiche aujourd'hui tient en deux lignes.

   L'ajustement ne se refait PAS au redimensionnement : tout est en cqw,
   la police et la carte retrecissent ensemble, et un titre qui tient en
   deux lignes a 341 px y tient encore a 275. */
.opp-card__title {
  margin: 0 0 8px; font-weight: 700;
  font-size: clamp(17px, calc(var(--titre-cqw, 7.6) * 1cqw), 44px);
  letter-spacing: -0.045em; line-height: 1.18;
  color: var(--blue-dark, #04024D); text-shadow: none;
}
.opp-card__details {
  /* `auto` en bas : toute la hauteur en trop se loge ICI, juste sous
     l'adresse — la ou une deuxieme ligne se serait trouvee. Les chiffres
     et le pied restent donc alignes d'une carte a l'autre dans la rangee,
     au lieu de flotter chacun a sa hauteur. */
  margin: 0 0 auto; font-size: clamp(14px, 4.6cqw, 23px); font-weight: 700;
  line-height: 1.45; letter-spacing: -0.025em;
  color: var(--opp-doux); text-shadow: none;
}

/* Les planchers des `clamp` ci-dessous et ci-dessus valent ce que `cqw`
   rend pour une carte de 272 px, la plus etroite qu'un telephone de 320 px
   puisse produire. Plus haut, ils figeaient la taille du texte pendant que
   la carte continuait de retrecir, et tout ce qui est en `nowrap` — le
   prix, le loyer, l'economie — sortait de sa case. A 341 px, la largeur de
   reference, aucun de ces planchers n'agit : `cqw` y est toujours au-dessus.

   ── Rendement et loyer, cote a cote ──
   Les libelles passent SOUS les nombres (order), comme sur la maquette :
   on lit le chiffre, puis ce qu'il designe. */
/* Les deux nombres font la MEME taille. Ils ne la faisaient pas : le
   rendement etait a 12cqw (41 px sur une carte de 341) et le loyer a
   6,3cqw (21 px), et « 5,6 % » ecrasait « 698 €/mois » juste a cote.

   Pourquoi 7,6cqw — 26 px — et pas les 41 du rendement : le plus long
   libelle que ces cartes affichent est le cashflow de Mes biens,
   « +1 234 €/mois ». A 41 px il mesure 232 px ; la colonne en offrait 137.
   7,6cqw est la plus grande taille ou il tient, colonnes rebattues, avec
   8 px de marge. Mesure faite sur la carte, pas estimee.

   Les colonnes passent donc de 0,9/1,2 a 0,85/1,6, la gouttiere de 6 a
   4 % et le retrait du loyer de 12 a 6 % : a taille egale, « 5,6 % » n'a
   plus besoin de la moitie de la ligne et « +1 234 €/mois » en reclame
   nettement plus. Le trait separateur se deplace vers la gauche, c'est la
   consequence visible.

   Le prix reste le plus gros caractere de la carte — 30,5 px contre 26 :
   la hierarchie tient toujours, elle se joue simplement entre le prix et
   le reste, et non plus entre les deux mesures. */
.opp-card__chiffres {
  display: grid; grid-template-columns: 0.85fr 1.6fr; gap: 4%;
  align-items: end; margin: 34px 0 0;
}
.opp-card__mesure { display: flex; flex-direction: column; min-width: 0; }
.opp-card__mesure dt {
  order: 2; margin-top: 3px; white-space: nowrap;
  font-size: clamp(11px, 4cqw, 20px); font-weight: 700;
  color: var(--opp-doux);
}
.opp-card__mesure dd {
  order: 1; margin: 0; white-space: nowrap;
  letter-spacing: -0.045em; line-height: 1.1; font-weight: 700;
  /* Le plancher vaut ce que 7,6cqw rend sur une carte de 272 px, comme
     partout ailleurs dans cette feuille. */
  font-size: clamp(20px, 7.6cqw, 38px);
}
/* Il ne reste de difference entre les deux que la couleur. */
.opp-card__mesure--rdt dd { color: var(--blue, #405AD2); }
.opp-card__mesure--loyer {
  border-left: 1px solid var(--opp-bord);
  padding-left: 6%; padding-bottom: 1px;
}
.opp-card__mesure--loyer dd { color: var(--blue-dark, #04024D); }

/* ── Le pied lavande ──
   L'angle rentrant en haut a gauche : un carre de 42 px dont l'ombre
   portee blanche remplit l'exterieur de l'arrondi. C'est ce creux qui
   fait que le pied semble decoupe dans le corps. */
.opp-card__pied {
  position: relative; display: flex; align-items: center;
  justify-content: space-between; gap: 12px;
  padding: 4.81cqw 6.5% 4.62cqw;
  /* Le creux en haut a gauche, et les deux coins du bas que la carte
     arrondit. Le pied depasse de son bloc parent sans cela : celui-ci
     arrondit desormais ses coins, mais il ne rogne pas ses enfants. */
  background: var(--opp-lavande);
  border-radius: 8.08cqw 0 calc(var(--opp-rayon) - 1px) calc(var(--opp-rayon) - 1px);
}
/* LES DEUX PETITS COINS.
   La maquette fabrique ce creux avec une ombre portee : un carre de
   42 px sans fond, portant `box-shadow: -16px -16px 0 0 #fff`. L'ombre
   est la silhouette du carre repeinte en blanc, decalee de seize pixels.
   Elle couvre donc un bloc de 26 x 26 a l'interieur du pied — et ses
   bords DROITS, a 26 px, viennent trancher la courbe du lavande, dont le
   rayon est de 42. Les deux traits ne se rejoignent pas : il reste un
   angle vif en haut et un autre a gauche. Ce sont les pointes.

   On dessine le creux au lieu de le suggerer. Un carre blanc plein dans
   le coin, et par-dessus un quart de disque lavande qui y decoupe l'arc.
   Les bords droits du quart de disque tombent dans le lavande du pied,
   ou ils sont invisibles ; le seul contour qui se voit est l'arc. */
/* Les deux couches passent SOUS le contenu. Sans cela le quart de disque,
   qui se peint apres le contenu de l'element, recouvrait « Economie
   estimee » : le libelle commence a 30 px du bord, dans le coin. */
.opp-card__pied::before,
.opp-card__pied::after {
  content: ''; position: absolute; top: 0; left: 0; z-index: 0;
  width: 8.08cqw; height: 8.08cqw; pointer-events: none;
}
.opp-card__pied::before { background: #fff; }
.opp-card__pied::after {
  background: var(--opp-lavande);
  border-top-left-radius: 8.08cqw;
}

/* `position: static` et pourtant un `z-index` qui fonctionne : un element
   flex est traite comme positionne pour l'empilement, c'est une regle a
   part de la specification. On y gagne de ne plus servir de repere a
   l'infobulle — ce bloc est etroit et colle a gauche, une bulle ancree
   dessus sortait de la carte par la droite. Elle se cale desormais sur le
   pied, qui fait toute la largeur. */
.opp-card__eco { position: static; z-index: 1; min-width: 0; }
.opp-card__eco-lbl {
  display: flex; align-items: center; gap: 7px; white-space: nowrap;
  font-size: clamp(10px, 3.65cqw, 18px); font-weight: 700;
  letter-spacing: -0.025em; color: var(--opp-pied-texte, var(--blue-dark, #04024D));
}
.opp-card__eco strong {
  /* 7cqw et non 8,7 : a 29,5 px l'economie rivalisait avec le prix
     (30,5), et ces deux montants ne disent pas du tout la meme chose —
     l'un est ce qu'on paie, l'autre un argument. Elle passe sous les deux
     mesures. */
  display: block; font-size: clamp(19px, 7cqw, 36px); font-weight: 700;
  line-height: 1.2; letter-spacing: -0.05em; white-space: nowrap;
  color: var(--opp-pied-texte, var(--blue-dark, #04024D));
}
/* Un <button> dans un <a> serait du balisage invalide : c'est un span
   qui porte le role, et le gestionnaire de clic de la carte l'intercepte. */
.opp-card__aide {
  display: inline-grid; place-items: center;
  width: 4.4cqw; height: 4.4cqw; flex: none;
  /* Le corail sur le bleu vif tombe a 2,11:1 — un pictogramme de 15 px en
     demande 3. Il suit donc le fond du pied, comme le texte et le bouton. */
  color: var(--opp-pied-aide, var(--accent, #ed797b)); cursor: pointer;
  background: none; border: 0; padding: 0;
  transition: transform 0.2s;
}
/* Le trace porte ses propres remplissages — la pastille prend la couleur
   du texte, le « i » reste blanc. Aucun contour : un « i » dessine au
   trait devient maigre des qu'on descend sous vingt pixels. */
.opp-card__aide svg { width: 100%; height: 100%; display: block; }
/* Le « i » est peint en dur dans le trace, en blanc. Sur une pastille
   devenue blanche elle aussi, il disparaissait. Un attribut de
   presentation cede devant une regle CSS : on le repeint d'ici. */
.opp-card__aide svg circle + circle,
.opp-card__aide svg rect { fill: var(--opp-pied-aide-i, #fff); }
.opp-card__aide:hover { transform: scale(1.12); }
/* ── L'explication ──
   Au survol sur ordinateur : une bulle suffit, personne n'a envie d'une
   fenetre qui s'ouvre pour trois lignes. Au doigt, il n'y a pas de survol
   — le clic ouvre la fenetre, et elle seule. Les deux ne coexistent
   jamais : chaque famille d'appareil n'en connait qu'une. */
.opp-card__bulle {
  position: absolute; bottom: calc(100% + 10px); z-index: 6;
  /* Centree sur le pied, donc sur la carte. Et bornee a 88cqw : elle ne
     peut plus en sortir, quelle que soit la largeur de la carte. Elle
     faisait « max(220px, 78cqw) » — le plancher de 220 px ne connaissait
     pas la carte et debordait des qu'elle retrecissait. */
  left: 50%; width: max-content; max-width: 88cqw;
  text-align: center; padding: 12px 14px;
  border-radius: 14px; background: var(--blue-dark, #04024D); color: #fff;
  font-size: 12.5px; font-weight: 400; line-height: 1.5;
  letter-spacing: normal;
  /* Le libelle parent est en `nowrap` pour que « Economie estimee » ne se
     coupe pas en deux. La bulle en heritait et sortait de la carte sur une
     seule ligne : elle reprend le retour a la ligne. */
  white-space: normal;
  box-shadow: 0 10px 24px rgba(4, 2, 77, 0.22);
  opacity: 0; visibility: hidden;
  transform: translateX(-50%) translateY(4px);
  transition: opacity 0.16s, transform 0.16s, visibility 0.16s;
  pointer-events: none;
}
/* La pointe, un simple carre tourne. */
.opp-card__bulle::after {
  content: ''; position: absolute; top: 100%; left: 50%;
  width: 10px; height: 10px; margin: -5px 0 0 -5px;
  background: var(--blue-dark, #04024D); transform: rotate(45deg);
  border-radius: 2px;
}
@media (hover: hover) {
  .opp-card__aide:hover .opp-card__bulle,
  .opp-card__aide:focus-visible .opp-card__bulle {
    opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0);
  }
}
/* Sans survol, la bulle ne doit jamais apparaitre : c'est la fenetre qui
   prend le relais au clic. */
@media (hover: none) {
  .opp-card__bulle { display: none; }
}
/* Pied sans chiffre a gauche — les guides n'affichent pas d'economie. Le
   bouton prend alors toute la largeur plutot que de flotter a droite. */
.opp-card__pied--simple .opp-card__cta { flex: 1; }

.opp-card__cta {
  position: relative; z-index: 1; display: inline-flex; align-items: center;
  justify-content: center; gap: 2.12cqw;
  min-height: 10.96cqw; padding: 3.08cqw 3.46cqw;
  background: var(--opp-pied-bouton, var(--blue, #405AD2)); border-radius: 999px;
  color: var(--opp-pied-bouton-texte, #fff); text-decoration: none; white-space: nowrap;
  font-size: clamp(12px, 3.55cqw, 17px); font-weight: 700;
  letter-spacing: -0.03em; box-shadow: none;
  transition: background 0.2s;
}
.opp-card:hover .opp-card__cta { background: var(--blue-dark, #04024D); color: #fff; box-shadow: none; }
.opp-card__cta svg {
  width: 4.42cqw; height: 4.42cqw; flex: none;
  stroke: currentColor; stroke-width: 2; fill: none;
}

/* ── Coeur, pose sur la photo ──
   Les deux couleurs s'echangent selon l'etat, au lieu de ne changer que le
   remplissage : pastille BLANCHE et coeur corail tant que le bien n'est
   pas garde, puis fond corail et coeur blanc une fois qu'il l'est. Le
   bien retenu est celui qui porte la couleur pleine — il se repere d'un
   coup d'oeil sur toute une grille. */
.opp-card__fav {
  position: absolute; top: var(--opp-coin); right: var(--opp-coin); z-index: 3;
  display: grid; place-items: center;
  width: var(--opp-pastille); height: var(--opp-pastille); border-radius: 50%;
  background: rgba(255, 255, 255, 0.96);
  color: var(--accent, #ed797b);
  border: 0; padding: 0; cursor: pointer;
  box-shadow: 0 2px 6px rgba(4, 2, 77, 0.16);
  transition: all 0.2s;
}
/* Coeur PLEIN dans les deux etats, et deux pixels de plus qu'avant :
   19 px devenaient 21 sur une carte de 341. Le remplissage suit la
   couleur du texte — corail sur la pastille blanche, blanc sur la pastille
   corail — et le renversement reste le seul signal d'etat. */
.opp-card__fav svg {
  width: 5.6cqw; height: 5.6cqw;
  fill: currentColor; stroke: currentColor; stroke-width: 1.8;
  color: inherit;
}
/* Le coeur etant deja plein, le survol ne peut plus se dire par le
   remplissage : c'est la pastille qui grossit legerement. */
.opp-card__fav:hover { transform: scale(1.08); }
.opp-card__fav.liked {
  background: var(--accent, #ed797b);
  color: #fff;
}
/* Le remplissage suit `currentColor` : rien a redire ici. */

/* La mention sous la grille : le rendement et l'economie reposent sur des
   hypotheses, et la carte les affiche gros. */
.opp-note {
  max-width: 1120px; margin: 28px auto 0; padding: 0 30px;
  font-size: 14px; line-height: 1.6; color: var(--opp-doux);
  /* Centree : la mention est sous une grille de cartes elles-memes
     centrees, et alignee a gauche elle partait seule dans un coin. */
  text-align: center; text-wrap: balance;
}
.opp-dialogue {
  max-width: 470px; width: calc(100% - 40px); padding: 28px;
  border: 1px solid var(--opp-bord); border-radius: 24px;
  color: var(--blue-dark, #04024D); background: #fff;
}
.opp-dialogue::backdrop { background: rgba(4, 2, 77, 0.4); }
.opp-dialogue h2 { margin: 0 0 12px; font-size: 22px; font-weight: 700; }
.opp-dialogue p { font-weight: 400; line-height: 1.6; margin: 0; color: var(--gray-600); }
.opp-dialogue button {
  display: block; margin: 22px 0 0 auto; border: 0; border-radius: 99px;
  padding: 12px 22px; background: var(--blue, #405AD2); color: #fff;
  font: inherit; font-weight: 600; cursor: pointer;
}

@media (max-width: 1120px) {
  .opp-track { grid-template-columns: minmax(0, 1fr); max-width: 568px; }
}
@media (max-width: 900px) {
  .opp-track { grid-template-columns: minmax(0, 1fr); max-width: 510px; gap: 24px; }
  .opp-card__info { padding-bottom: 26px; }
  .opp-card__chiffres { margin-top: 27px; }
  .opp-card__pied { padding-top: 20px; padding-bottom: 20px; }
  .opp-card__cta { min-height: 48px; padding: 13px 14px; gap: 6px; }
  .opp-note { font-size: 12px; }
}
/* Carte etroite : le bouton passe sous l'economie plutot que de la serrer.
   La maquette posait ce seuil a 350 px, ou ses cartes faisaient 520. Nos
   colonnes tiennent dans les 1120 px de la grille du site, soit 341 px par
   carte : a 350 le repli se declenchait sur TOUTES les cartes de bureau.
   Mesure faite : a 341 px, l'economie et le bouton tiennent cote a cote. */
@container (max-width: 300px) {
  .opp-card__pied { flex-wrap: wrap; }
  .opp-card__cta, .opp-card__eco { width: 100%; }
}

/* Anciens elements des versions precedentes, sans emploi ici */
.opp-card__overlay,
.opp-card__top,
.opp-card__pill,
.opp-card__highlight,
.opp-card__highlight-rendement,
.opp-card__footer,
.opp-card__footer-accent,
.opp-card__note,
.opp-card__yield,
.opp-card__location,
.opp-card__meta,
.opp-card__bottom,
.opp-card__price,
.opp-card__loyer,
.opp-card__tag,
.opp-card__quartier { display: none !important; }
