/* ============================================================================
   rendez-vous.css — la page /rendez-vous.html (2026-09-08, refondue le 08/09).

   POURQUOI UNE FEUILLE A PART plutot qu'un <style> inline comme contact.html :
   le garde des fichiers freres de `scripts/deploy_vitrine.py`
   (`x.html` -> `x.css`) la force alors dans FICHIERS. Une page deployee sans
   sa feuille s'affiche sans ses styles, sans erreur et sans log -- c'est le
   piege « commite != en ligne », deja rencontre treize fois ici.

   TROIS REGLES PERMANENTES SONT TENUES CI-DESSOUS :

   1. Aucun `:hover` hors `@media (hover:hover) and (pointer:fine)` : sur
      tactile, le doigt qui defile declenche :hover et les elements clignotent.

   2. Une animation n'est toleree que si elle NE REPEINT PAS. Mesure du
      2026-08-27 (trace Chromium, emulation iPhone, 3 s au repos) : la meme
      barre animee par `background-position` = 696 Paint, recomposee par
      `transform` = 0 Paint avec quatre boucles actives. Ici, tout ce qui
      boucle n'anime que `transform` et `opacity`.

   3. Le halo de fond ne DERIVE que sur un ecran a souris. L'en-tete du site
      porte `backdrop-filter: blur(10px)` : un fond qui bouge en dessous
      l'oblige a se re-filtrer a chaque image, et une barre re-filtree en
      permanence, sur iOS, c'est exactement ce qui scintille.

   ET UNE REGLE DE SURETE : rien n'est visible UNIQUEMENT grace a une
   animation. Les entrees partent d'`opacity: 0` par `animation-fill-mode:
   backwards` -- l'etat ECRIT dans la regle est « visible », l'animation ne fait
   que l'emprunter au demarrage. Couper les animations
   (`prefers-reduced-motion`, script en panne, vieux navigateur) rend une page
   complete, jamais une page vide. C'est pour ca qu'il n'y a aucune revelation
   au defilement ici : voir le bloc des entrees plus bas.
   ========================================================================== */

/* Le texte pose SUR la couleur d'accent. Les cinq themes sombres ont un accent
   clair et vif (cyan, violet, vert, ambre, rose) : du blanc dessus est
   illisible. Seul le theme clair a un accent fonce. */
:root {
  --rv-on-accent: #0a0a14;
  --rv-ombre: 0 18px 50px rgba(10, 14, 40, .10);
  --rv-ombre-forte: 0 26px 70px rgba(10, 14, 40, .16);
  --rv-voile: rgba(255, 255, 255, .55);
}
:root[data-theme="clair"] { --rv-on-accent: #ffffff; }
:root[data-theme="cyan"],
:root[data-theme="violet"],
:root[data-theme="emeraude"],
:root[data-theme="ambre"],
:root[data-theme="rose"] {
  --rv-ombre: 0 18px 50px rgba(0, 0, 0, .45);
  --rv-ombre-forte: 0 26px 70px rgba(0, 0, 0, .55);
  --rv-voile: rgba(255, 255, 255, .05);
}

/* `[hidden] { display: none }` vient de la feuille du NAVIGATEUR et pese
   (0,1,0) : n'importe quelle regle de classe posant un `display` la bat, parce
   qu'une feuille d'auteur l'emporte toujours sur celle de l'agent utilisateur.
   Le JS peut donc faire `el.hidden = true` et l'element RESTE affiche, sans
   erreur ni log. Vecu EN PRODUCTION le 2026-08-24 (badge « 0 » colle a la
   cloche, carte blanche vide chez tout nouveau client). Une garde par classe ne
   tient pas -- il faut y penser a chaque nouvelle regle. On la pose UNE fois,
   en tete, comme dans portail.html et admin.html.
   Trouve ici par un sabotage de test qui refusait de passer au rouge. */
[hidden] { display: none !important; }

* { box-sizing: border-box; }

body {
  margin: 0;
  padding-top: 62px;
  font-family: 'Poppins', system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
  background: var(--bg, #f4f5fa);
  color: var(--text, #191b2e);
  line-height: 1.65;
  overflow-x: hidden;
}

/* ── Halo de fond ────────────────────────────────────────────────────── */
/* Deux taches floues, fixes, derriere tout le reste. Elles donnent de la
   profondeur sans coûter un pixel de mise en page : `position: fixed` les sort
   du flux, et rien ne peut deborder puisqu'elles sont clippees par le body. */
.rv-aura {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
}
/* Un degrade radial, PAS un rond flou : `filter: blur(90px)` sur 600 px de cote
   fait rasteriser une surface enorme a chaque changement, et c'est justement ce
   qu'on paie sur un telephone. Le degrade, lui, est peint une fois. */
.rv-orb {
  position: absolute;
  display: block;
  border-radius: 50%;
}
.rv-orb-1 {
  top: -22vh; left: -18vw; width: 74vw; height: 74vw; max-width: 900px; max-height: 900px;
  background: radial-gradient(circle closest-side, var(--accent, #0061cc) 0%, transparent 72%);
  opacity: .17;
}
.rv-orb-2 {
  bottom: -28vh; right: -20vw; width: 70vw; height: 70vw; max-width: 860px; max-height: 860px;
  background: radial-gradient(circle closest-side, var(--light-blue, #00d4ff) 0%, transparent 72%);
  opacity: .14;
}
:root[data-theme="cyan"] .rv-orb-1,
:root[data-theme="violet"] .rv-orb-1,
:root[data-theme="emeraude"] .rv-orb-1,
:root[data-theme="ambre"] .rv-orb-1,
:root[data-theme="rose"] .rv-orb-1 { opacity: .13; }
:root[data-theme="cyan"] .rv-orb-2,
:root[data-theme="violet"] .rv-orb-2,
:root[data-theme="emeraude"] .rv-orb-2,
:root[data-theme="ambre"] .rv-orb-2,
:root[data-theme="rose"] .rv-orb-2 { opacity: .10; }

.rv-wrap { position: relative; max-width: 1440px; margin: 0 auto; padding: clamp(1.8rem, 5vw, 3.4rem) 20px 4rem; }

/* ── Entrees : elles PARTENT de l'invisible, elles n'y arrivent jamais ─── */
/* `backwards` : l'element tient la premiere image pendant le retard, puis
   l'animation le rend visible. Sans animation du tout, il est visible : c'est
   l'etat ecrit dans la regle, pas une image de fin. */
@keyframes rv-monte {
  from { opacity: 0; transform: translate3d(0, 20px, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}
.rv-up { animation: rv-monte .72s cubic-bezier(.2, .75, .25, 1) backwards; }
.rv-d1 { animation-delay: .04s; }
.rv-d2 { animation-delay: .10s; }
.rv-d3 { animation-delay: .17s; }
.rv-d4 { animation-delay: .24s; }
.rv-d5 { animation-delay: .30s; }
.rv-d6 { animation-delay: .38s; }
.rv-e1 { animation-delay: .46s; }
.rv-e2 { animation-delay: .54s; }
.rv-e3 { animation-delay: .62s; }

/* PAS de revelation au defilement, et c'est une decision. Un premier jet
   cachait les trois etapes jusqu'a ce qu'un `IntersectionObserver` les
   traverse : sur la CAPTURE pleine page comme sur un telephone qui n'arrive
   jamais jusqu'en bas, la colonne de droite montrait un filet vertical et
   AUCUN texte. Le depot connait deja ce piege (« couper une boucle peut rendre
   un element invisible a vie »). Une entree retardee, elle, se termine toute
   seule : le pire cas est une animation qu'on n'a pas vue. */

/* ── Retour au site ──────────────────────────────────────────────────── */
/* Cette page est une porte d'ENTREE : on y arrive depuis le bouton RESERVER de
   la fiche Google, donc sans avoir vu le site et sans rien derriere dans
   l'historique. MESURE a 390 px : le seul lien de sortie visible etait le logo
   « Alkoras Tech », que rien ne signale comme cliquable -- la nav complete vit
   dans le menu deroulant, ferme. La page etait un cul-de-sac sur telephone,
   c'est-a-dire dans le cas principal.
   Un lien EXPLICITE, jamais un `history.back()` : venant de Google Maps, il n'y
   a rien derriere, ou il renverrait le visiteur chez Google. */
.rv-retour {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  margin: 0 0 1.2rem;
  padding: .4rem .9rem .4rem .7rem;
  border: 1px solid var(--border, #dde0ec);
  border-radius: 999px;
  background: var(--rv-voile);
  color: var(--text-muted, #5b5e77);
  text-decoration: none;
  font-size: .88rem;
  font-weight: 600;
  transition: color .18s ease, border-color .18s ease, transform .18s ease;
}
.rv-retour svg { width: 16px; height: 16px; flex: none; transition: transform .22s ease; }

/* ── En-tete ─────────────────────────────────────────────────────────── */
.rv-hero { text-align: center; max-width: 680px; margin: 0 auto clamp(1.8rem, 4vw, 2.6rem); }

.rv-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  margin: 0 0 1.1rem;
  padding: .4rem 1rem .4rem .75rem;
  border: 1px solid var(--accent-soft, rgba(0, 97, 204, .28));
  border-radius: 999px;
  background: var(--accent-soft, rgba(0, 97, 204, .10));
  color: var(--accent, #0061cc);
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
}
/* La pastille respire. `transform` + `opacity` seulement : composee par le GPU,
   donc zero repeint du fil principal -- c'est la difference mesuree le 27/08
   entre une page qui scintille sur iPhone et une page qui ne scintille pas. */
.rv-pastille {
  width: 8px; height: 8px; flex: none;
  border-radius: 50%;
  background: var(--accent, #0061cc);
  animation: rv-respire 2.4s ease-in-out infinite;
}
@keyframes rv-respire {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: .45; transform: scale(.62); }
}

.rv-hero h1 {
  font-size: clamp(2.1rem, 6vw, 3.4rem);
  line-height: 1.08;
  margin: 0 0 1rem;
  font-weight: 700;
  letter-spacing: -.02em;
}
/* Le mot qui porte la promesse. Le degrade est PEINT UNE FOIS : il ne bouge
   pas, il n'anime rien -- un degrade anime sur du texte se repeint a chaque
   image, et c'est du texte, donc c'est la pire surface a repeindre. */
.rv-mot {
  background: linear-gradient(100deg, var(--accent, #0061cc), var(--light-blue, #00b4e6) 70%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.rv-lead { color: var(--text-muted, #5b5e77); font-size: clamp(1.02rem, 2vw, 1.16rem); margin: 0; }

.rv-gages {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: .5rem .6rem;
  list-style: none;
  margin: 1.5rem 0 0;
  padding: 0;
}
.rv-gages li {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .38rem .85rem;
  border: 1px solid var(--border, #dde0ec);
  border-radius: 999px;
  background: var(--rv-voile);
  color: var(--text-muted, #5b5e77);
  font-size: .84rem;
  font-weight: 600;
}
.rv-gages svg { width: 15px; height: 15px; flex: none; color: var(--accent, #0061cc); }

/* ── Grille : le formulaire d'abord, l'aparte ensuite ────────────────── */
.rv-grid { display: grid; grid-template-columns: 1.4fr 1fr; gap: 1.4rem; align-items: start; }
@media (max-width: 860px) { .rv-grid { grid-template-columns: 1fr; } }

.rv-card {
  position: relative;
  background: var(--bg-card, #fff);
  border: 1px solid var(--border, #dde0ec);
  border-radius: 20px;
  padding: 1.9rem 1.75rem;
  box-shadow: var(--rv-ombre);
}
.rv-card-form { overflow: hidden; }

.rv-card-tete { margin: 0 0 1.5rem; }
.rv-card-tete h2 { margin: 0 0 .25rem; font-size: 1.22rem; font-weight: 700; letter-spacing: -.01em; }
.rv-card-tete p { margin: 0; font-size: .9rem; color: var(--text-muted, #5b5e77); }

/* ── La jauge de remplissage ─────────────────────────────────────────── */
/* Elle se remplit par `transform: scaleX`, jamais par une largeur : une
   largeur qui change relance la mise en page a chaque frappe. */
.rv-jauge {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  overflow: hidden;
  z-index: 1;
  background: var(--border, #dde0ec);
}
.rv-jauge i {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--accent, #0061cc), var(--light-blue, #00d4ff));
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform .45s cubic-bezier(.2, .75, .25, 1);
  will-change: transform;
}

/* ── Champs ──────────────────────────────────────────────────────────── */
.rv-field { margin-bottom: 1.25rem; }
.rv-field label { display: block; font-weight: 600; font-size: .94rem; margin-bottom: .45rem; }
.rv-opt { font-weight: 400; color: var(--text-muted, #5b5e77); font-size: .85rem; }

/* Quand la validation refuse un champ, le script lui donne le focus : le
   navigateur fait alors défiler pour l'amener dans la vue — et l'en-tête est
   `position: fixed`, donc il RECOUVRE le champ, qui se retrouve invisible sous
   la barre. Mesuré à 390 px le 2026-09-08 : le champ téléphone en faute passait
   entièrement dessous. `padding-top` sur le body protège le haut de page, pas
   un défilement programmatique ; `scroll-margin-top` est fait pour ça. */
.rv-field input,
.rv-field textarea,
.rv-status,
.rv-merci { scroll-margin-top: 86px; }

.rv-input { position: relative; }
.rv-ico {
  position: absolute;
  left: .95rem;
  top: 50%;
  width: 18px; height: 18px;
  margin-top: -9px;
  color: var(--text-muted, #5b5e77);
  opacity: .7;
  pointer-events: none;
  transition: color .18s ease, opacity .18s ease;
}
.rv-field input,
.rv-field textarea {
  width: 100%;
  padding: .92rem .95rem;
  border: 1px solid var(--border, #dde0ec);
  border-radius: 13px;
  background: var(--bg, #f7f8fc);
  color: var(--text, #191b2e);
  font: inherit;
  outline: none;
  transition: border-color .18s ease, box-shadow .22s ease, background-color .18s ease;
}
.rv-field textarea { resize: vertical; min-height: 96px; }
.rv-field input::placeholder,
.rv-field textarea::placeholder { color: var(--text-muted, #5b5e77); opacity: .7; }
.rv-field input:focus,
.rv-field textarea:focus {
  border-color: var(--accent, #0061cc);
  box-shadow: 0 0 0 4px var(--accent-soft, rgba(0, 97, 204, .12));
}
/* Le decalage vient APRES `.rv-field input` : les deux selecteurs pesent
   pareil (0,2,1), donc c'est l'ordre qui tranche. Ecrit plus haut, le
   `padding: .92rem .95rem` de la regle generale le reecrasait et le
   texte de substitution passait SOUS l'icone. */
.rv-field .rv-input-icone input { padding-left: 2.75rem; }
.rv-input:focus-within .rv-ico { color: var(--accent, #0061cc); opacity: 1; }
.rv-field input.rv-ko,
.rv-field textarea.rv-ko {
  border-color: #e0455f;
  animation: rv-secousse .42s cubic-bezier(.36, .07, .19, .97);
}
/* Une secousse de 6 px, jouee UNE fois, uniquement sur le champ refuse. Elle
   dit « c'est ici » plus vite qu'une couleur : le regard suit le mouvement. */
@keyframes rv-secousse {
  10%, 90% { transform: translate3d(-2px, 0, 0); }
  30%, 70% { transform: translate3d(5px, 0, 0); }
  50%      { transform: translate3d(-6px, 0, 0); }
}

.rv-hint { margin: .45rem 0 0; font-size: .82rem; color: var(--text-muted, #5b5e77); }

/* Le pot de miel : hors ecran, jamais rempli par un humain. */
.rv-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ── Raccourcis de creneau : ils REMPLISSENT le champ libre ──────────── */
.rv-chips { display: flex; flex-wrap: wrap; gap: .45rem; margin-bottom: .65rem; }
.rv-chip {
  position: relative;
  border: 1px solid var(--border, #dde0ec);
  background: var(--bg, #f7f8fc);
  color: var(--text, #191b2e);
  border-radius: 999px;
  padding: .42rem .9rem;
  font: inherit;
  font-size: .87rem;
  cursor: pointer;
  transition: border-color .18s ease, color .18s ease, background-color .18s ease, transform .12s ease;
}
.rv-chip span { display: inline-block; transition: transform .22s cubic-bezier(.2, .75, .25, 1); }
/* La coche apparait par `transform: scale` a l'interieur de la puce : rien ne
   change de taille, donc la ligne de puces ne se recompose pas quand on
   choisit -- sinon les puces suivantes sautent sous le doigt. */
.rv-chip::before {
  content: "";
  position: absolute;
  left: .62rem;
  top: 50%;
  width: 13px; height: 13px;
  margin-top: -6px;
  background: currentColor;
  transform: scale(0);
  transition: transform .22s cubic-bezier(.2, .9, .3, 1.4);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 13 4.5 4.5L19 7'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 13 4.5 4.5L19 7'/%3E%3C/svg%3E") center / contain no-repeat;
}
.rv-chip[aria-pressed="true"] {
  border-color: var(--accent, #0061cc);
  background: var(--accent-soft, rgba(0, 97, 204, .10));
  color: var(--accent, #0061cc);
  font-weight: 600;
}
.rv-chip[aria-pressed="true"]::before { transform: scale(1); }
.rv-chip[aria-pressed="true"] span { transform: translateX(11px); }
.rv-chip:active { transform: scale(.96); }

/* ── Bouton d'envoi ──────────────────────────────────────────────────── */
.rv-turnstile:not(:empty) { margin: 0 0 1rem; }
.rv-btn {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  width: 100%;
  padding: 1rem;
  border: 0;
  border-radius: 13px;
  overflow: hidden;
  font: inherit;
  font-weight: 600;
  font-size: 1.02rem;
  cursor: pointer;
  color: var(--rv-on-accent);
  background: var(--accent, #0061cc);
  box-shadow: 0 10px 26px var(--accent-glow, rgba(0, 97, 204, .28));
  transition: transform .16s ease, box-shadow .22s ease;
}
/* Le reflet vit dans un element INTERNE clippe et ne bouge que par
   `transform`. Ecrit en `background-position` ou en `left`, le meme effet
   repeignait le bouton a chaque image (696 Paint mesures le 27/08). */
.rv-btn-fond { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.rv-btn-fond i {
  position: absolute;
  top: -50%; bottom: -50%; left: 0;
  width: 45%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .28), transparent);
  transform: translate3d(-180%, 0, 0) skewX(-16deg);
}
.rv-btn-txt, .rv-btn-fleche { position: relative; }
.rv-btn-fleche { width: 19px; height: 19px; flex: none; transition: transform .22s ease; }
.rv-btn:disabled { opacity: .65; cursor: default; box-shadow: none; }
.rv-btn:active:not(:disabled) { transform: scale(.99); }

/* Etat « envoi en cours » : la fleche devient un anneau qui tourne. Une
   rotation `transform`, le temps d'un aller-retour reseau -- pas une boucle
   qui vit sur la page au repos. */
.rv-btn.is-envoi .rv-btn-fleche { display: none; }
.rv-btn.is-envoi::after {
  content: "";
  width: 17px; height: 17px;
  border: 2.2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: rv-tourne .7s linear infinite;
}
@keyframes rv-tourne { to { transform: rotate(360deg); } }

.rv-note { margin: .85rem 0 0; font-size: .82rem; color: var(--text-muted, #5b5e77); text-align: center; }

/* ── Bandeau de retour ───────────────────────────────────────────────── */
/* `hidden` ne masque PAS de facon fiable : la regle du navigateur pese (0,1,0)
   et n'importe quelle classe posant un `display` la bat. On pilote une classe. */
.rv-status { display: none; margin-top: 1rem; padding: .85rem 1rem; border-radius: 12px; font-size: .93rem; font-weight: 600; }
.rv-status.is-shown { display: block; animation: rv-monte .32s ease backwards; }
.rv-status.ok { background: rgba(34, 197, 94, .12); color: #15803d; border: 1px solid rgba(34, 197, 94, .3); }
.rv-status.err { background: rgba(224, 69, 95, .1); color: #b91c1c; border: 1px solid rgba(224, 69, 95, .3); }
:root[data-theme="cyan"] .rv-status.ok,
:root[data-theme="violet"] .rv-status.ok,
:root[data-theme="emeraude"] .rv-status.ok,
:root[data-theme="ambre"] .rv-status.ok,
:root[data-theme="rose"] .rv-status.ok { color: #5ee9a4; }
:root[data-theme="cyan"] .rv-status.err,
:root[data-theme="violet"] .rv-status.err,
:root[data-theme="emeraude"] .rv-status.err,
:root[data-theme="ambre"] .rv-status.err,
:root[data-theme="rose"] .rv-status.err { color: #ff8fa3; }

/* ── Le panneau de confirmation ──────────────────────────────────────── */
/* Une fois la demande partie, l'en-tete de la carte (« Trois champs, une
   minute ») parle d'un formulaire qui n'est plus la : il s'efface, et la jauge
   finit son trajet. */
.rv-card-form.is-fini .rv-card-tete { display: none; }
.rv-merci { text-align: center; padding: .6rem 0 .2rem; }
.rv-merci h2 { margin: 1rem 0 .35rem; font-size: 1.5rem; font-weight: 700; letter-spacing: -.01em; }
.rv-merci-txt { margin: 0; color: var(--text-muted, #5b5e77); }

.rv-check { display: flex; justify-content: center; }
.rv-check svg { width: 78px; height: 78px; }
.rv-check-c {
  fill: none;
  stroke: var(--accent, #0061cc);
  stroke-width: 2.4;
  stroke-dasharray: 152;
  stroke-dashoffset: 152;
  animation: rv-trace .55s cubic-bezier(.65, 0, .45, 1) forwards;
}
.rv-check-v {
  fill: none;
  stroke: var(--accent, #0061cc);
  stroke-width: 4;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 44;
  stroke-dashoffset: 44;
  animation: rv-trace .34s cubic-bezier(.65, 0, .45, 1) .42s forwards;
}
/* Le trace n'est PAS une propriete composee : il repeint. C'est assume, parce
   qu'il dure 0,9 s une seule fois, a la seconde ou le visiteur a fini -- ce
   que la regle interdit, c'est une boucle qui repeint la page AU REPOS. */
@keyframes rv-trace { to { stroke-dashoffset: 0; } }

.rv-recap {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .7rem;
  margin: 1.5rem 0 0;
  text-align: left;
}
@media (max-width: 420px) { .rv-recap { grid-template-columns: 1fr; } }
.rv-recap > div {
  padding: .75rem .9rem;
  border: 1px solid var(--border, #dde0ec);
  border-radius: 13px;
  background: var(--bg, #f7f8fc);
}
.rv-recap dt { margin: 0 0 .1rem; font-size: .74rem; text-transform: uppercase; letter-spacing: .08em; color: var(--text-muted, #5b5e77); }
.rv-recap dd { margin: 0; font-weight: 600; font-size: .98rem; overflow-wrap: anywhere; }
.rv-merci-mail { margin: 1.1rem 0 0; font-size: .84rem; color: var(--text-muted, #5b5e77); }
.rv-merci-retour {
  display: inline-block;
  margin-top: 1.2rem;
  padding: .7rem 1.4rem;
  border: 1px solid var(--border, #dde0ec);
  border-radius: 999px;
  color: var(--text, #191b2e);
  text-decoration: none;
  font-weight: 600;
  font-size: .93rem;
  transition: border-color .18s ease, color .18s ease;
}

/* ── Colonne de droite ───────────────────────────────────────────────── */
.rv-aside h2 { margin: 0 0 .7rem; font-size: 1.12rem; font-weight: 700; }
/* Le sélecteur PORTE le parent : `.rv-aside-h2` seul pèse (0,1,0) contre
   (0,1,1) pour `.rv-aside h2`, donc le `margin: 0` de la règle précédente
   gagnait et le titre restait collé au bouton WhatsApp. Vu sur capture. */
.rv-aside h2.rv-aside-h2 { margin-top: 2rem; }

.rv-tel {
  display: flex;
  align-items: center;
  gap: .7rem;
  text-decoration: none;
  color: var(--accent, #0061cc);
}
/* L'anneau qui bat autour du combine. `transform` + `opacity`, dans un rond de
   44 px : compose par le GPU, zero repeint. */
.rv-tel-rond {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px; height: 44px;
  flex: none;
  border-radius: 50%;
  background: var(--accent-soft, rgba(0, 97, 204, .12));
}
.rv-tel-rond::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid var(--accent, #0061cc);
  animation: rv-onde 2.6s ease-out infinite;
}
@keyframes rv-onde {
  0%   { opacity: .55; transform: scale(1); }
  70%  { opacity: 0;   transform: scale(1.5); }
  100% { opacity: 0;   transform: scale(1.5); }
}
.rv-tel-rond svg { width: 21px; height: 21px; }
.rv-tel-num { font-size: 1.42rem; font-weight: 700; letter-spacing: .01em; }
.rv-tel-sub { margin: .6rem 0 1.2rem; font-size: .87rem; color: var(--text-muted, #5b5e77); }

.rv-wa {
  display: flex; align-items: center; justify-content: center; gap: .5rem;
  background: #128C7E; color: #fff; text-decoration: none;
  border-radius: 13px; padding: .8rem 1rem; font-weight: 600; font-size: .95rem;
  box-shadow: 0 10px 24px rgba(18, 140, 126, .28);
  transition: transform .16s ease, box-shadow .22s ease, filter .18s ease;
}
.rv-wa svg { width: 20px; height: 20px; flex: none; }
.rv-wa:active { transform: scale(.99); }

/* Les trois etapes, reliees par un filet vertical. */
.rv-steps { position: relative; margin: .8rem 0 0; padding: 0 0 0 2.1rem; list-style: none; counter-reset: rv-etape; }
.rv-steps::before {
  content: "";
  position: absolute;
  left: 12px; top: 8px; bottom: 14px;
  width: 2px;
  background: var(--border, #dde0ec);
}
.rv-steps li {
  position: relative;
  margin-bottom: .9rem;
  color: var(--text-muted, #5b5e77);
  font-size: .91rem;
}
.rv-steps li::before {
  counter-increment: rv-etape;
  content: counter(rv-etape);
  position: absolute;
  left: -2.1rem;
  top: .05rem;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px; height: 26px;
  border-radius: 50%;
  background: var(--accent-soft, rgba(0, 97, 204, .12));
  color: var(--accent, #0061cc);
  font-size: .8rem;
  font-weight: 700;
}
.rv-steps li:last-child { margin-bottom: 0; }
.rv-steps strong { color: var(--text, #191b2e); font-weight: 600; }

.rv-zone { margin: 1.6rem 0 0; font-size: .85rem; color: var(--text-muted, #5b5e77); }

/* ── Pied de page ────────────────────────────────────────────────────── */
.rv-foot { text-align: center; color: var(--text-muted, #5b5e77); font-size: .85rem; margin-top: 2.6rem; }
.rv-foot a { color: var(--accent, #0061cc); }

/* ── Survol : UNIQUEMENT a la souris ─────────────────────────────────── */
/* Sur un ecran tactile, :hover reste colle apres le defilement et l'element
   clignote. Remarque repetee de Koray, et cause n°1 de la liste.
   C'est aussi ici que le halo se met a deriver : sous l'en-tete
   `backdrop-filter`, un fond mobile force la barre a se re-filtrer image par
   image, et un pointeur fin veut dire « ni doigt, ni iOS ». */
@media (hover: hover) and (pointer: fine) {
  .rv-retour:hover { color: var(--accent, #0061cc); border-color: var(--accent, #0061cc); }
  .rv-retour:hover svg { transform: translateX(-3px); }
  .rv-btn:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 16px 34px var(--accent-glow, rgba(0, 97, 204, .38)); }
  .rv-btn:hover:not(:disabled) .rv-btn-fleche { transform: translateX(4px); }
  .rv-btn:hover:not(:disabled) .rv-btn-fond i { animation: rv-reflet .85s ease-out; }
  .rv-chip:hover { border-color: var(--accent, #0061cc); color: var(--accent, #0061cc); }
  .rv-wa:hover { transform: translateY(-2px); box-shadow: 0 16px 32px rgba(18, 140, 126, .4); filter: brightness(1.06); }
  .rv-tel:hover .rv-tel-num { text-decoration: underline; }
  .rv-merci-retour:hover { border-color: var(--accent, #0061cc); color: var(--accent, #0061cc); }
  .rv-foot a:hover { text-decoration: underline; }

  .rv-orb-1 { animation: rv-derive-1 26s ease-in-out infinite alternate; }
  .rv-orb-2 { animation: rv-derive-2 32s ease-in-out infinite alternate; }
}
@keyframes rv-reflet { to { transform: translate3d(320%, 0, 0) skewX(-16deg); } }
@keyframes rv-derive-1 { to { transform: translate3d(70px, 60px, 0) scale(1.14); } }
@keyframes rv-derive-2 { to { transform: translate3d(-80px, -50px, 0) scale(.88); } }

/* ── Mouvement reduit : on coupe tout, et rien ne disparait ──────────── */
/* La regle vaut aussi comme filet de securite : si une animation d'entree ne
   se joue pas, l'element reste visible parce que son etat au repos l'est. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    /* `animation-delay` fait partie du lot, et ce n'est PAS un detail : avec
       un retard conserve, un element en `animation-fill-mode: backwards` tient
       sa premiere image -- donc `opacity: 0` -- pendant tout le retard. MESURE
       le 2026-09-08 : la troisieme etape (retard 0,62 s) etait encore invisible
       620 ms apres le chargement, chez quelqu'un qui a justement demande a ne
       pas voir d'animations. Un retard NEGATIF la donne deja terminee. */
    animation-delay: -1ms !important;
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .rv-check-c, .rv-check-v { stroke-dashoffset: 0 !important; }
}
