/* ============================================================
   app.css -- E-224. Troisieme feuille de la landing v4, chargee APRES
   style.css et visual.css. Elle ne porte QUE les deux composants
   ajoutes par le depot a la page livree par Codex :

     1. le contact flottant LinkedIn (a.tr-linkedin)
     2. la bulle de temoignages (aside.tm-bubble)

   Les regles sont reprises de design/landing-candidat-v3-cc/styles.css
   (tr-linkedin L3001-3113, tm-bubble L3139-3291). Tailles, positions,
   pile de z-index et regles prefers-reduced-motion sont conservees a
   l identique. Seules la palette et la police sont passees a la charte
   de la page v4, lue dans style.css :
     --ink #153a39, --deep #103431, --accent #c55c3d (terracotta),
     --paper #fff, --soft #f2f5f3, --line #d8e2dd, --muted #526762,
     --body 'DM Sans', --display 'Manrope'.

   Pile de z-index de la page : .skip vaut 5, rien d autre n est fixe ni
   empile. Le contact garde 40 et la bulle 90, donc leur ordre relatif
   est celui du depot et rien ne passe au-dessus d eux par accident.
   ============================================================ */

/* ============================================================
   CONTACT FLOTTANT LINKEDIN : cercle photo + badge au repos, libelle
   deploye au hover/focus. Bord droit mi-hauteur, fixe au defilement.
   ============================================================ */
.tr-linkedin {
  position: fixed;
  top: 50%;
  /* Zone sure iPhone : en paysage l encoche mange le bord droit. */
  right: env(safe-area-inset-right, 0px);
  transform: translateY(-50%);
  z-index: 40;
  display: inline-flex;
  align-items: center;
  gap: 0;
  padding: 0.55rem 0.9rem;
  border-radius: 999px 0 0 999px;
  background: var(--deep, #103431);
  color: #fff;
  font-family: var(--body, 'DM Sans', sans-serif);
  text-decoration: none;
  box-shadow: 0 18px 40px #153a3926;
  transition: gap .2s, padding .2s, box-shadow .2s, background .2s;
}

.tr-linkedin:hover,
.tr-linkedin:focus-visible {
  gap: 0.9rem;
  padding-left: 1.4rem;
  background: #24534b;
  color: #fff;
  box-shadow: 0 18px 40px #153a3926, 0 0 0 2px var(--accent, #c55c3d);
}

.tr-linkedin:focus-visible {
  outline: 3px solid var(--accent, #c55c3d);
  outline-offset: 2px;
}

.tr-linkedin__label {
  max-width: 0;
  overflow: hidden;
  opacity: 0;
  white-space: nowrap;
  font-size: 12px;
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: 1.8px;
  text-transform: uppercase;
  transition: max-width .2s, opacity .2s;
}

.tr-linkedin:hover .tr-linkedin__label,
.tr-linkedin:focus-visible .tr-linkedin__label {
  max-width: 18rem;
  opacity: 1;
}

.tr-linkedin__media {
  position: relative;
  flex: 0 0 auto;
  width: 5rem;
  height: 5rem;
}

.tr-linkedin__photo {
  width: 5rem;
  height: 5rem;
  border-radius: 50%;
  object-fit: cover;
  display: block;
}

.tr-linkedin__badge {
  position: absolute;
  right: -0.1rem;
  bottom: -0.1rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.85rem;
  height: 1.85rem;
  border-radius: 50%;
  background: var(--paper, #fff);
  box-shadow: 0 0 0 2px var(--deep, #103431);
}

.tr-linkedin__badge svg {
  width: 1.1rem;
  height: 1.1rem;
  fill: var(--deep, #103431);
}

/* Mobile : le repli (cercle + badge) est deja l etat par defaut ; on ne
   fait que reduire le cercle et le badge. Le libelle reste replie et son
   equivalent textuel est porte par l aria-label de l ancre. */
@media (max-width: 768px) {
  .tr-linkedin__media,
  .tr-linkedin__photo {
    width: 3.75rem;
    height: 3.75rem;
  }

  .tr-linkedin__badge {
    width: 1.5rem;
    height: 1.5rem;
  }

  .tr-linkedin__badge svg {
    width: 0.9rem;
    height: 0.9rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .tr-linkedin,
  .tr-linkedin__label {
    transition: none;
  }
}

/* ============================================================
   BULLE DE TEMOIGNAGES.
   POSITION : bas droite sur ordinateur, bas centre en pleine largeur sur
   mobile. Jamais au-dessus d un bouton d action : le script masque la
   bulle par visibility des que son rectangle recouvre un CTA, le contact
   LinkedIn ou le lien de compte. visibility et non display : le noeud
   reste, la minuterie aussi, et la bulle revient d elle-meme.

   LE TEXTE N EST JAMAIS TRONQUE : pas de line-clamp, pas d ellipse. Un
   temoignage de 600 caracteres agrandit la bulle, il ne se coupe pas.
   ============================================================ */
.tm-bubble {
  position: fixed;
  right: calc(1.5rem + env(safe-area-inset-right, 0px));
  bottom: calc(1.5rem + env(safe-area-inset-bottom, 0px));
  z-index: 90;
  width: min(360px, calc(100vw - 3rem));
  padding: 1rem 1.1rem 0.85rem;
  /* E-196 : 16 px sous la bulle pour la queue (getBoundingClientRect
     ignore les pseudo-elements). */
  margin-bottom: 16px;
  border: 1px solid var(--line, #d8e2dd);
  border-radius: 22px;
  background: var(--paper, #fff);
  color: var(--ink, #153a39);
  font-family: var(--body, 'DM Sans', sans-serif);
  font-size: 15px;
  line-height: 1.55;
  /* E-196 : drop-shadow et non box-shadow, pour que l ombre epouse la queue. */
  filter: drop-shadow(0 2px 6px rgb(21 58 57 / 8%)) drop-shadow(0 14px 34px rgb(21 58 57 / 12%));
  opacity: 0;
  transition: opacity 400ms ease;
}

/* QUEUE (E-196). La bulle a une bordure visible : deux pseudo-elements
   superposes - ::before le triangle couleur bordure, ::after le meme 1 px plus
   haut et plus etroit, couleur du fond, ce qui laisse un lisere de 1 px. */
.tm-bubble::before,
.tm-bubble::after {
  content: "";
  position: absolute;
  top: 100%;
  right: 36px;
  width: 0;
  height: 0;
  border-style: solid;
  border-color: transparent;
  border-width: 16px 12px 0;
  border-top-color: var(--line, #d8e2dd);
}

.tm-bubble::after {
  top: calc(100% - 1px);
  right: 37px;
  border-width: 15px 11px 0;
  border-top-color: var(--paper, #fff);
}

.tm-bubble.tm-shown {
  opacity: 1;
}

/* Collision avec une action ou un overlay : la bulle s efface sans
   quitter le document. */
.tm-bubble.tm-masked {
  visibility: hidden;
}

/* E-197 : citation en italique. Charte v4 : vert institutionnel --ink
   #153a39 sur fond blanc, contraste tres au-dessus de AAA. */
.tm-bubble__text {
  margin: 0;
  font-size: 15px;
  line-height: 1.6;
  font-style: italic;
  color: var(--ink, #153a39);
}

.tm-bubble__who {
  margin: 0.55rem 0 0;
  font-size: 14px;
  color: var(--muted, #526762);
}

/* E-198 : le nom devient un lien quand l auteur a indique son profil
   LinkedIn. E-199 : ce lien doit SE VOIR. Bleu lien #0b57d0, comme dans
   design/landing-candidat-v3-cc/styles.css : sur le blanc de la page le
   rapport de contraste depasse 6:1, AA. Soulignement PERMANENT, epaissi
   au survol et au focus. E-225 : la couleur ne bouge PAS au survol, et
   surtout jamais vers le terracotta ; la regle globale a:hover de
   style.css est donc neutralisee ici par une declaration explicite.
   :visited de la meme couleur : l historique de navigation d un visiteur
   n a pas a se lire sur la page. Aucun logo, aucune image. */
.tm-bubble__link,
.tm-bubble__link:visited {
  color: #0b57d0;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}

.tm-bubble__link:hover,
.tm-bubble__link:focus-visible {
  color: #0b57d0;
  text-decoration-thickness: 2px;
}

.tm-bubble__mention {
  margin: 0.6rem 0 0;
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--muted, #526762);
}

.tm-bubble__actions {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.7rem;
}

.tm-bubble__btn {
  padding: 0.3rem 0.6rem;
  border: 1px solid var(--line, #d8e2dd);
  border-radius: 6px;
  background: transparent;
  color: var(--ink, #153a39);
  font-family: var(--body, 'DM Sans', sans-serif);
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
}

.tm-bubble__btn:hover {
  border-color: var(--accent, #c55c3d);
  color: var(--accent, #c55c3d);
}

/* Focus VISIBLE : les deux boutons sont les seuls elements focalisables de
   la bulle, et la rotation s arrete au focus jusqu a reprise explicite. */
.tm-bubble__btn:focus-visible {
  outline: 3px solid var(--accent, #c55c3d);
  outline-offset: 2px;
}

/* Mobile : pleine largeur moins les marges, bas centre. */
@media (max-width: 640px) {
  .tm-bubble {
    right: calc(0.75rem + env(safe-area-inset-right, 0px));
    left: calc(0.75rem + env(safe-area-inset-left, 0px));
    bottom: calc(0.75rem + env(safe-area-inset-bottom, 0px));
    width: auto;
  }
  /* Queue au centre : la bulle est en bas centre. */
  .tm-bubble::before,
  .tm-bubble::after {
    right: auto;
    left: 50%;
    margin-left: -12px;
  }
  .tm-bubble::after {
    margin-left: -11px;
  }
}

/* prefers-reduced-motion : aucun fondu. Le script coupe deja la rotation ;
   ici on supprime la transition pour qu il ne reste aucun mouvement. */
@media (prefers-reduced-motion: reduce) {
  .tm-bubble {
    transition: none;
  }
}
