/* ==========================================================================
   Le chatbot : le dock flottant.
   16 septembre 2026.

   L'UI du chatbot Eliana, fournie en React, Tailwind et framer-motion, et
   refaite ici en CSS et en JS natifs. **Aucune des quatre dépendances
   d'origine n'entre** : la section 2 les interdit toutes.

   Ce qui est repris : le dock centré en bas d'écran, ses deux états, la
   pilule au repos et le panneau ouvert, le fil de bulles, la zone de saisie
   qui grandit, le bouton d'envoi, le halo au sol, les raccourcis clavier.

   ⚠️ **Ce qui n'est pas repris, et ce sont des règles, pas des goûts.**

   1. **La surface « liquid » ne dérive plus.** L'original fait tourner un
      dégradé en boucle toutes les dix secondes : ce serait un quatrième
      mouvement permanent, et la section 2 en autorise trois. Le point
      « en ligne » qui pulse sort pour la même raison.
   2. **Le panneau est clair.** L'original est un panneau sombre ; la page a
      déjà deux surfaces sombres et la section 2 n'en voulait qu'une. Un
      panneau clair se lit aussi bien sur le constat et sur Signal que sur le
      reste, parce qu'il est opaque.
   3. **L'ambre et le rouge d'Eliance sortent.** La couleur est celle du
      système : le gradient de site sur l'avatar et sur le halo, le bleu voilé
      du bouton primaire sur l'envoi.
   4. **Le rayon passe de 22 à 24**, multiple de quatre.
   5. **Le champ garde son anneau de focus.** L'original le retire.
   6. **Le texte du champ est à 16 px, et non 14.** Sous 16 px, Safari iOS
      zoome la page à la mise au point du champ.
   ========================================================================== */

.chat-dock {
  position: fixed;
  inset-inline: 0;
  inset-block-end: calc(var(--spacing) * 16);
  z-index: 55;
  display: flex;
  justify-content: center;
  padding-inline: calc(var(--spacing) * 16);
  pointer-events: none;
}

@media (min-width: 768px) {
  .chat-dock { inset-block-end: calc(var(--spacing) * 24); }
}

/* Le bandeau de consentement occupe la même place, et il passe avant. */
.chat-dock[data-masque] { display: none; }

/* --------------------------------------------------------------------------
   La pilule, au repos.

   C'est le bouton à contour de l'en-tête, à double coque et en verre, tel
   quel. **Seule l'encre change avec le fond** : noire sur la page, blanche
   quand la pilule passe sur une surface sombre. Le script lit la couleur
   peinte sous elle et pose data-sur-sombre sur le dock.

   Le verre est gardé, sur demande du 16 septembre 2026 : une enveloppe
   blanche opaque a existé une heure, et la transparence manquait.

   ⚠️ **Le sélecteur pèse trois classes, et c'est nécessaire.** La peau du
   bouton à contour est posée par « .bouton.bouton-contour », qui en pèse
   deux. À une seule classe, la transition de la pilule perdait sans rien
   dire, et la pilule ne s'effaçait plus à l'ouverture.

   L'encre bascule en slow et ease-inout, comme l'en-tête quand il passe au
   thème de Signal : c'est la même bascule, pas un mouvement de plus.
   -------------------------------------------------------------------------- */
.bouton.bouton-contour.chat-pilule {
  position: relative;
  pointer-events: auto;
  border-radius: var(--r-full);
  transition:
    opacity var(--motion-quick) var(--ease-out),
    translate var(--motion-quick) var(--ease-out),
    scale var(--motion-quick) var(--ease-out),
    color var(--motion-slow) var(--ease-inout),
    background-color var(--motion-instant) var(--ease-out);
}

/* Sur le sombre, le blanc du thème Signal, mesuré à 17,4 pour 1. */
.chat-dock[data-sur-sombre] .chat-pilule { color: #F5F5F5; }

.chat-pilule .bouton-noyau {
  border-radius: var(--r-full);
  padding-inline-start: calc(var(--spacing) * 6);
  font-size: var(--cta);
  font-weight: 500;
}

/* Le halo au sol. Il est fixe : l'original ne l'anime pas non plus. */
.chat-pilule::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset-inline: 12%;
  inset-block-end: calc(var(--spacing) * -18);
  block-size: calc(var(--spacing) * 36);
  border-radius: var(--r-full);
  background: radial-gradient(ellipse at center, rgb(102 71 240 / .55) 0%, rgb(0 145 255 / .22) 55%, rgb(0 145 255 / 0) 100%);
  filter: blur(calc(var(--spacing) * 16));
  pointer-events: none;
}

/* La pastille de l'avatar. Le gradient de site y est un visuel, comme la
   section 5.1 le permet ; l'étoile blanche est un tracé et non du texte. */
.chat-avatar {
  display: inline-grid;
  place-items: center;
  flex: none;
  inline-size: calc(var(--spacing) * 32);
  block-size: calc(var(--spacing) * 32);
  border-radius: var(--r-full);
  background: var(--gradient-site);
  color: var(--blanc);
  box-shadow:
    inset 0 1px 0 rgb(255 255 255 / .45),
    0 calc(var(--spacing) * 6) calc(var(--spacing) * 16) calc(var(--spacing) * -6) rgb(102 71 240 / .6);
  transition: rotate var(--motion-quick) var(--ease-out);
}

.chat-avatar svg {
  inline-size: calc(var(--spacing) * 16);
  block-size: calc(var(--spacing) * 16);
}

.chat-pilule:hover .chat-avatar,
.chat-pilule:focus-visible .chat-avatar { rotate: 6deg; }

/* Charly, depuis le 17 septembre 2026. La mascotte a sa propre silhouette :
   la pastille perd son dégradé et son ombre, et Charly déborde un peu de sa
   boîte pour garder la taille de l'étoile qu'il remplace. Il ne tourne pas au
   survol, il salue (chatbot.js). Sans charly.js, l'étoile reste. */
.chat-avatar[data-charly] {
  background: none;
  box-shadow: none;
  overflow: visible;
}

/* Blanc, éclairé par en dessous du violet vers le bleu : la lueur posée sous
   le panneau. Le dégradé `#charly-lumiere` est posé par chatbot.js ; le
   remplissage CSS passe devant celui que le moteur écrit en attribut, et les
   yeux (le groupe découpé) gardent le leur. */
.chat-avatar[data-charly] > svg {
  scale: 1.45;
  filter:
    drop-shadow(0 calc(var(--spacing) * 2) calc(var(--spacing) * 3) rgb(102 71 240 / .5))
    drop-shadow(0 calc(var(--spacing) * 3) calc(var(--spacing) * 6) rgb(0 145 255 / .35));
}

.chat-avatar[data-charly] > svg > g > path,
.chat-avatar[data-charly] > svg > g > g:not([clip-path]) > path {
  fill: url(#charly-lumiere);
}

.chat-pilule:hover .chat-avatar[data-charly],
.chat-pilule:focus-visible .chat-avatar[data-charly] { rotate: none; }

/* --------------------------------------------------------------------------
   Le panneau, ouvert.
   -------------------------------------------------------------------------- */
.chat-panneau {
  position: absolute;
  inset-block-end: 0;
  inset-inline: calc(var(--spacing) * 16);
  margin-inline: auto;
  max-inline-size: calc(var(--spacing) * 672);
  pointer-events: auto;
  transform-origin: 50% 100%;
  transition:
    opacity var(--motion-quick) var(--ease-out),
    translate var(--motion-quick) var(--ease-out),
    scale var(--motion-quick) var(--ease-out),
    visibility 0s linear var(--motion-quick);
}

/* Le halo au sol du panneau, plus large que lui. */
.chat-panneau::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset-inline: -4%;
  inset-block-end: calc(var(--spacing) * -40);
  block-size: calc(var(--spacing) * 96);
  border-radius: var(--r-full);
  background: radial-gradient(ellipse at center, rgb(102 71 240 / .42) 0%, rgb(0 145 255 / .2) 50%, rgb(0 145 255 / 0) 100%);
  filter: blur(calc(var(--spacing) * 40));
  pointer-events: none;
}

.chat-coque {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-xl);
  background: var(--blanc);
  border: 1px solid var(--gris-grille);
  color: var(--noir);
  box-shadow: var(--lueur-carte), var(--ombre-carte-forte);
}

/* Le halo du haut à droite. L'original le pose en couleur de marque ; ici
   c'est le violet noyé à 10 %, sous le texte, qui reste sur du quasi-blanc. */
.chat-coque::before {
  content: "";
  position: absolute;
  inset-block-start: calc(var(--spacing) * -80);
  inset-inline-end: calc(var(--spacing) * -64);
  inline-size: calc(var(--spacing) * 320);
  block-size: calc(var(--spacing) * 320);
  border-radius: var(--r-full);
  background: rgb(102 71 240 / .10);
  filter: blur(calc(var(--spacing) * 80));
  pointer-events: none;
}

.chat-coque > * { position: relative; }

/* Les deux états. La visibilité bascule à la fin de la sortie, pour que le
   panneau fermé sorte aussi du parcours au clavier. */
.chat-dock:not([data-ouvert]) .chat-panneau {
  visibility: hidden;
  opacity: 0;
  translate: 0 calc(var(--spacing) * 18);
  scale: .97;
}

.chat-dock[data-ouvert] .chat-panneau {
  transition-delay: 0s;
}

.chat-dock[data-ouvert] .chat-pilule {
  opacity: 0;
  translate: 0 calc(var(--spacing) * 18);
  scale: .94;
  pointer-events: none;
}

/* L'en-tête du panneau. */
.chat-entete {
  display: flex;
  align-items: center;
  gap: calc(var(--spacing) * 12);
  padding: calc(var(--spacing) * 12) calc(var(--spacing) * 12) calc(var(--spacing) * 10) calc(var(--spacing) * 16);
  border-block-end: 1px solid var(--gris-grille);
}

.chat-entete .chat-avatar {
  inline-size: calc(var(--spacing) * 28);
  block-size: calc(var(--spacing) * 28);
}

.chat-identite { flex: 1; min-inline-size: 0; }

.chat-nom {
  margin: 0;
  font-family: var(--font-corps);
  font-size: var(--corps-sm);
  font-weight: 700;
  line-height: 1.2;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chat-statut {
  display: flex;
  align-items: center;
  gap: calc(var(--spacing) * 6);
  margin: calc(var(--spacing) * 2) 0 0;
  font-size: var(--legende);
  line-height: 1.45;
  color: var(--gris-lisible);
}

/* Le point de statut est fixe : l'original le fait pulser en boucle. */
.chat-statut::before {
  content: "";
  flex: none;
  inline-size: calc(var(--spacing) * 6);
  block-size: calc(var(--spacing) * 6);
  border-radius: var(--r-full);
  background: var(--gradient-site);
}

.chat-icone-bouton {
  display: inline-grid;
  place-items: center;
  flex: none;
  inline-size: calc(var(--spacing) * 32);
  block-size: calc(var(--spacing) * 32);
  padding: 0;
  border: 0;
  border-radius: var(--r-full);
  background: transparent;
  color: var(--gris-lisible);
  cursor: pointer;
  transition:
    background-color var(--motion-instant) var(--ease-out),
    color var(--motion-instant) var(--ease-out);
}

.chat-icone-bouton:hover { background: var(--gris-clair); color: var(--noir); }
.chat-icone-bouton:active { background: var(--gris-hover); }

.chat-icone-bouton svg {
  inline-size: calc(var(--spacing) * 16);
  block-size: calc(var(--spacing) * 16);
}

/* --------------------------------------------------------------------------
   Le fil.
   -------------------------------------------------------------------------- */
.chat-fil {
  display: flex;
  flex-direction: column;
  gap: calc(var(--spacing) * 10);
  max-block-size: min(46vh, calc(var(--spacing) * 360));
  margin: 0;
  padding: calc(var(--spacing) * 12) calc(var(--spacing) * 16);
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  list-style: none;
}

.chat-fil:empty { display: none; }

.chat-message { display: flex; }
.chat-message[data-role="user"] { justify-content: flex-end; }

.chat-bulle {
  max-inline-size: 85%;
  padding: calc(var(--spacing) * 8) calc(var(--spacing) * 14);
  border-radius: var(--r-lg);
  font-size: var(--corps-sm);
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* Le visiteur en noir plein, l'assistant en gris clair : c'est la paire du
   bouton primaire d'origine et du bouton secondaire, sans couleur de plus. */
.chat-message[data-role="user"] .chat-bulle {
  border-end-end-radius: var(--r-xs);
  background: var(--noir);
  color: var(--blanc);
}

.chat-message[data-role="assistant"] .chat-bulle {
  border-end-start-radius: var(--r-xs);
  background: var(--gris-clair);
  color: var(--noir);
}

.chat-bulle a {
  color: inherit;
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.chat-bulle a:hover { text-decoration-thickness: 2px; }

.chat-bulle strong { font-weight: 700; }

.chat-puce { display: flex; gap: calc(var(--spacing) * 6); }
.chat-puce::before { content: "•"; color: var(--gris-lisible); }

.chat-vide { block-size: calc(var(--spacing) * 6); }

/* Les trois points d'écriture. Ils ne bougent que pendant l'attente d'une
   réponse, puis disparaissent : ce n'est pas un mouvement permanent. */
.chat-points {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--spacing) * 4);
  padding-block: calc(var(--spacing) * 6);
}

.chat-points span {
  inline-size: calc(var(--spacing) * 6);
  block-size: calc(var(--spacing) * 6);
  border-radius: var(--r-full);
  background: var(--gris-lisible);
  animation: chat-saut 1s var(--ease-inout) infinite;
}

.chat-points span:nth-child(2) { animation-delay: 150ms; }
.chat-points span:nth-child(3) { animation-delay: 300ms; }

@keyframes chat-saut {
  0%, 60%, 100% { translate: 0 0; }
  30% { translate: 0 calc(var(--spacing) * -4); }
}

/* --------------------------------------------------------------------------
   La saisie.
   -------------------------------------------------------------------------- */
.chat-saisie {
  position: relative;
  border-block-start: 1px solid var(--gris-grille);
}

.chat-fil:empty + .chat-saisie { border-block-start: 0; }

.chat-champ {
  display: block;
  inline-size: 100%;
  min-block-size: calc(var(--spacing) * 48);
  max-block-size: calc(var(--spacing) * 140);
  margin: 0;
  padding: calc(var(--spacing) * 12) calc(var(--spacing) * 60) calc(var(--spacing) * 12) calc(var(--spacing) * 16);
  border: 0;
  border-radius: 0 0 var(--r-xl) var(--r-xl);
  background: transparent;
  color: var(--noir);
  font-family: var(--font-corps);
  font-size: var(--corps-sm);
  line-height: 1.45;
  letter-spacing: -.011em;
  resize: none;
  scrollbar-width: thin;
}

/* Le gris lisible et non le gris du système : 5,02 pour 1 sur ce blanc. */
.chat-champ::placeholder { color: var(--gris-lisible); opacity: 1; }

/* L'anneau reste, il passe seulement à l'intérieur : dehors, le bord du
   panneau le couperait. */
.chat-champ:focus-visible { outline-offset: -4px; }

.chat-envoyer {
  position: absolute;
  inset-block-end: calc(var(--spacing) * 8);
  inset-inline-end: calc(var(--spacing) * 10);
  inline-size: calc(var(--spacing) * 36);
  block-size: calc(var(--spacing) * 36);
}

/* Le bleu voilé du bouton primaire, et pour la même raison : sans le voile,
   le blanc tombe à 3,23 pour 1 sur ce bleu. */
.chat-envoyer:not(:disabled) {
  background: var(--bleu);
  color: var(--blanc);
  box-shadow:
    inset 0 0 calc(var(--spacing) * 10) rgb(255 255 255 / .45),
    inset 0 1px 0 rgb(255 255 255 / .6),
    inset 0 0 0 calc(var(--spacing) * 100) rgb(0 0 0 / .18),
    0 calc(var(--spacing) * 10) calc(var(--spacing) * 24) calc(var(--spacing) * -8) rgb(0 145 255 / .65);
}

.chat-envoyer:not(:disabled):hover {
  background: var(--bleu);
  color: var(--blanc);
  box-shadow:
    inset 0 0 calc(var(--spacing) * 10) rgb(255 255 255 / .45),
    inset 0 1px 0 rgb(255 255 255 / .6),
    inset 0 0 0 calc(var(--spacing) * 100) rgb(0 0 0 / .26),
    0 calc(var(--spacing) * 10) calc(var(--spacing) * 24) calc(var(--spacing) * -8) rgb(0 145 255 / .65);
}

/* L'état désactivé de la section 5.5. */
.chat-envoyer:disabled {
  background: var(--gris-grille);
  color: var(--gris-texte);
  cursor: not-allowed;
}

/* --------------------------------------------------------------------------
   Mouvement réduit : on retire, on ne raccourcit pas.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .bouton.bouton-contour.chat-pilule,
  .chat-panneau,
  .chat-avatar { transition: none; }
  .chat-dock:not([data-ouvert]) .chat-panneau,
  .chat-dock[data-ouvert] .chat-pilule { translate: none; scale: none; }
  .chat-pilule:hover .chat-avatar,
  .chat-pilule:focus-visible .chat-avatar { rotate: none; }
  .chat-points span { animation: none; }
}

@media print {
  .chat-dock { display: none; }
}
