/* ============================================================
   CEWeb Widgets — Avis (colonnes défilantes)
   Tous les réglages de l'onglet Style arrivent par des variables
   --ceweb-avis-* posées sur .ceweb-avis par Elementor.

   Les valeurs ci-dessous ne sont qu'un repli, et elles pointent d'abord sur la
   palette du thème — -6 noms, -7 entreprise, texte et date, -9 bordures et
   étoiles vides, -10 fond de pastille, -11 fond des cartes, comme le reste du
   plugin. Les
   contrôles de couleur de l'onglet Style ont donc un défaut *vide* : tant qu'on
   n'y touche pas, Elementor n'émet rien et c'est le thème qui décide. Y mettre
   un hexadécimal par défaut couperait le lien avec la palette.

   Deux variables sont écrites par PHP, en style en ligne sur chaque colonne, et
   non par un contrôle : --ceweb-avis-duration (calculée depuis le nombre de
   cartes de *cette* colonne, pour que toutes défilent à la même vitesse
   apparente même avec des piles de hauteurs inégales) et --ceweb-avis-offset
   (le décalage de départ qui évite l'effet « trois colonnes au garde-à-vous »).
   ============================================================ */

.ceweb-avis{
  /* Grille de colonnes. Le nombre est responsive côté Elementor (3 / 2 / 1) :
     aucune media query ici, elle écraserait le réglage de l'éditeur. */
  --ceweb-avis-columns: 3;
  --ceweb-avis-column-gap: 22px;

  /* Alignement. `--align` sert de text-align, `--self` en est la traduction
     pour les rangées en flex (en-tête, étoiles), qui ne connaissent ni `left`
     ni `right`. Les deux sont écrites d'un coup par le contrôle Alignement, via
     son selectors_dictionary.

     Ces deux valeurs sont déclarées, et non laissées à l'héritage : sans elles,
     une carte posée dans une section Elementor centrée hérite de son
     `text-align: center` et le nom se retrouve centré à côté de sa pastille,
     sans qu'aucun réglage du widget ne puisse le rattraper. Voir plus bas : la
     déclaration sur la carte ne suffit pas, chaque élément de texte porte la
     sienne. */
  --ceweb-avis-align: left;
  --ceweb-avis-self: flex-start;

  /* Scène : la fenêtre par laquelle on voit défiler les colonnes. */
  --ceweb-avis-height: 620px;
  --ceweb-avis-fade: 110px;
  --ceweb-avis-blur: 6px;

  /* Défilement. La durée est un repli : PHP écrit la vraie valeur colonne par
     colonne. --ceweb-avis-offset va de 0 à 1 (fraction de cycle). */
  --ceweb-avis-duration: 40s;
  --ceweb-avis-offset: 0;

  /* Carte */
  --ceweb-avis-card-bg: var(--theme-palette-color-11, #FFFFFF);
  --ceweb-avis-card-border-color: var(--theme-palette-color-9, #E2E8F0);
  --ceweb-avis-card-border-width: 0px;
  --ceweb-avis-card-radius: 22px;
  --ceweb-avis-card-padding: 24px 26px;
  --ceweb-avis-card-gap: 28px;
  --ceweb-avis-card-inner-gap: 14px;

  /* Place laissée à l'ombre des cartes *à l'intérieur* de la scène. La scène
     rogne (overflow: hidden) pour cadrer le défilement, et ce rognage couperait
     l'ombre net sur les bords gauche et droit. Un padding sur la colonne — et
     non une marge négative sur la scène, qui déborderait de la page — lui rend
     ses quelques pixels. */
  --ceweb-avis-shadow-room: 16px;

  /* Pastille de gauche */
  --ceweb-avis-avatar-size: 46px;
  --ceweb-avis-avatar-radius: 999px;
  --ceweb-avis-avatar-bg: var(--theme-palette-color-10, #F1F5F9);
  --ceweb-avis-avatar-color: var(--theme-palette-color-6, #0C1A3C);
  --ceweb-avis-avatar-icon-size: 20px;
  --ceweb-avis-avatar-gap: 14px;
  /* `cover` recadre un portrait, `contain` contient un logo sans le rogner. */
  --ceweb-avis-avatar-fit: cover;
  --ceweb-avis-avatar-padding: 0px;

  /* Note. Le doré est le seul hexadécimal en dur de la feuille, et il est
     volontairement isolé dans cette déclaration, comme le liseré blanc de la
     grille de projets : une étoile d'avis n'est pas une couleur de charte,
     aucune entrée de la palette ne lui correspond. Le contrôle « Couleur des
     étoiles » suffit à la brancher sur la palette si la charte finit par en
     tenir une. */
  --ceweb-avis-star-color: #F5B544;
  --ceweb-avis-star-empty-color: var(--theme-palette-color-9, #E2E8F0);
  --ceweb-avis-star-size: 19px;
  --ceweb-avis-star-gap: 1px;
  --ceweb-avis-note-color: var(--theme-palette-color-6, #0C1A3C);

  /* Textes */
  --ceweb-avis-name-color: var(--theme-palette-color-6, #0C1A3C);
  --ceweb-avis-company-color: var(--theme-palette-color-7, #475569);
  --ceweb-avis-identity-gap: 2px;
  --ceweb-avis-text-color: var(--theme-palette-color-7, #475569);
  --ceweb-avis-date-color: color-mix(in srgb, var(--theme-palette-color-7, #475569) 68%, transparent);

  /* Fond du bloc — transparent tant que rien n'est réglé dans l'onglet Style. */
  --ceweb-avis-radius: 0px;
  --ceweb-avis-padding: 0px;

  /* Pas de font-family ici : les cartes prennent la police du thème, celle du
     corps de page. */
  position: relative;          /* Repère des voiles de flou, posés par-dessus la scène. */
  color: var(--ceweb-avis-text-color);
  padding: var(--ceweb-avis-padding);
  border-radius: var(--ceweb-avis-radius);
}
.ceweb-avis *{ box-sizing: border-box; }

.ceweb-avis__empty{
  padding: 16px 20px; border: 1px dashed #d63638; border-radius: 8px;
  color: #1d2327; font: 14px/1.5 system-ui, sans-serif;
}

/* ============================================================
   Scène

   Hauteur fixe + overflow: hidden : c'est elle qui transforme une pile de
   cartes bien plus haute qu'elle en fenêtre de défilement.
   ============================================================ */
.ceweb-avis__scene{
  height: var(--ceweb-avis-height);
  overflow: hidden;
}

/* Le fondu haut et bas passe par un masque, pas par deux dégradés opaques posés
   par-dessus : le masque marche sur *n'importe quel* fond — une section
   colorée, une image, un dégradé — là où un dégradé de recouvrement exige de
   lui redonner à la main la couleur exacte de la section, et de la corriger à
   chaque fois qu'elle change.

   Le préfixe -webkit- reste nécessaire pour Safari < 15.4. Un navigateur qui
   ne connaît aucune des deux formes affiche simplement des colonnes à bords
   nets : le bloc reste lisible, il perd son fondu. */
.ceweb-avis--fade-mask .ceweb-avis__scene,
.ceweb-avis--fade-blur .ceweb-avis__scene{
  -webkit-mask-image: linear-gradient(
    to bottom,
    transparent 0,
    #000 var(--ceweb-avis-fade),
    #000 calc(100% - var(--ceweb-avis-fade)),
    transparent 100%
  );
  mask-image: linear-gradient(
    to bottom,
    transparent 0,
    #000 var(--ceweb-avis-fade),
    #000 calc(100% - var(--ceweb-avis-fade)),
    transparent 100%
  );
}

/* Voiles de flou. Frères de la scène, et non enfants : un backdrop-filter
   n'échantillonne que l'arrière-plan de sa « racine de fond » la plus proche,
   et le masque de la scène en crée précisément une. Posé à l'intérieur, le
   voile ne flouterait plus rien d'autre que du vide déjà effacé par le masque.
   À côté, il floute la scène elle-même.

   Leur propre masque fait monter le flou en intensité vers le bord : sans lui,
   la bande floue s'arrêterait sur une ligne franche au milieu des cartes. */
.ceweb-avis__veil{
  position: absolute;
  inset-inline: var(--ceweb-avis-padding);
  height: var(--ceweb-avis-fade);
  pointer-events: none;
  -webkit-backdrop-filter: blur(var(--ceweb-avis-blur));
  backdrop-filter: blur(var(--ceweb-avis-blur));
}
.ceweb-avis__veil--top{
  top: var(--ceweb-avis-padding);
  -webkit-mask-image: linear-gradient(to bottom, #000 0, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0, transparent 100%);
}
.ceweb-avis__veil--bottom{
  bottom: var(--ceweb-avis-padding);
  -webkit-mask-image: linear-gradient(to top, #000 0, transparent 100%);
  mask-image: linear-gradient(to top, #000 0, transparent 100%);
}

/* ============================================================
   Colonnes et défilement
   ============================================================ */
/* Colonnes en flux *colonne* avec une largeur calculée, et non un
   `grid-template-columns: repeat(var(--columns), 1fr)`.

   C'est PHP qui répartit les avis, donc le markup contient toujours autant de
   colonnes que le réglage ordinateur. Avec un template de deux colonnes, la
   troisième passerait à la ligne et casserait la scène en deux rangées. Ici
   elle est posée à la suite, hors du cadre, et le `overflow: hidden` de la
   scène la fait disparaître : baisser le nombre de colonnes sous tablette ou
   mobile n'a plus besoin que d'une seule variable. */
.ceweb-avis__columns{
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: calc(
    (100% - (var(--ceweb-avis-columns) - 1) * var(--ceweb-avis-column-gap))
    / var(--ceweb-avis-columns)
  );
  gap: 0 var(--ceweb-avis-column-gap);
  height: 100%;
}

.ceweb-avis__column{
  /* min-height: 0 — sans lui, une piste de grille refuse de descendre sous la
     hauteur naturelle de son contenu, et la scène serait poussée à la hauteur
     de la pile entière au lieu de la rogner. */
  min-height: 0;
  overflow: hidden;
}

/* La piste contient deux fois la même liste de cartes et se déplace d'exactement
   la moitié de sa hauteur : au moment où l'animation boucle, la première carte
   du second jeu occupe la place qu'avait celle du premier, la reprise est
   invisible.

   Pour que ce compte soit juste, la piste doit mesurer exactement deux fois
   (cartes + entre-deux). L'entre-deux est donc posé sur le jeu de cartes, en
   `gap` doublé d'un `padding-bottom` de même valeur qui rejoue l'écart après
   la dernière carte — un `gap` seul ne pose rien à cet endroit-là, et la
   moitié de la hauteur ne tomberait plus sur une frontière de carte. Voir la
   règle du jeu plus bas. */
.ceweb-avis__track{
  display: flex;
  flex-direction: column;
  padding-inline: var(--ceweb-avis-shadow-room);
  animation: ceweb-avis-scroll var(--ceweb-avis-duration) linear infinite;
  /* Un délai négatif démarre l'animation en cours de route : c'est ce qui
     décale les colonnes entre elles sans dupliquer une seule règle. */
  animation-delay: calc(var(--ceweb-avis-offset) * var(--ceweb-avis-duration) * -1);
  will-change: transform;
}

/* reverse suffit à faire descendre la colonne : même piste, même durée, même
   point de bouclage, lus à l'envers. */
.ceweb-avis__column.is-down .ceweb-avis__track{
  animation-direction: reverse;
}

@keyframes ceweb-avis-scroll{
  from{ transform: translate3d(0, 0, 0); }
  to{ transform: translate3d(0, -50%, 0); }
}

/* Pause au survol — et au focus clavier, sinon personne naviguant sans souris
   ne pourrait arrêter le défilement pour lire. La classe n'est posée par PHP
   que si le réglage est actif : le couper retire la règle au lieu de la
   neutraliser. */
.ceweb-avis--pause .ceweb-avis__scene:hover .ceweb-avis__track,
.ceweb-avis--pause .ceweb-avis__scene:focus-within .ceweb-avis__track{
  animation-play-state: paused;
}

/* ============================================================
   Alignement du texte

   Une seule déclaration sur la carte ne suffit pas, et c'est le piège : les
   deux lignes de l'en-tête vivent dans un `<figcaption>`, et `<blockquote>`
   comme `<figcaption>` sont exactement les balises que les thèmes — et les
   feuilles de blocs de WordPress — centrent d'office, par habitude des légendes
   d'image. Or une déclaration qui vise l'élément lui-même bat toujours la même
   propriété *héritée* d'un ancêtre : l'héritage ne s'applique que là où aucune
   déclaration locale ne correspond, la spécificité n'entre même pas en jeu. Le
   `text-align` de la carte n'atteignait donc jamais le figcaption.

   D'où une règle qui pose l'alignement sur chaque élément porteur de texte,
   avec un sélecteur volontairement long (0,3,0) pour tenir sans `!important`
   face à une règle de thème sur `figcaption p` ou `blockquote`.
   ============================================================ */
/* La carte ne porte aucune marge : l'entre-deux vient du `gap` du jeu. Le
   sélecteur est long (0,3,0) pour la même raison que l'alignement plus bas —
   `<figure>` arrive avec une marge du navigateur, et les thèmes en remettent
   une avec un sélecteur qui bat une simple classe. */
.ceweb-avis .ceweb-avis__set .ceweb-avis__card{
  margin: 0;
}

.ceweb-avis .ceweb-avis__card .ceweb-avis__head,
.ceweb-avis .ceweb-avis__card .ceweb-avis__identity,
.ceweb-avis .ceweb-avis__card .ceweb-avis__name,
.ceweb-avis .ceweb-avis__card .ceweb-avis__company,
.ceweb-avis .ceweb-avis__card .ceweb-avis__quote,
.ceweb-avis .ceweb-avis__card .ceweb-avis__quote p,
.ceweb-avis .ceweb-avis__card .ceweb-avis__date{
  text-align: var(--ceweb-avis-align);
}

/* Chaque jeu de cartes est un conteneur flex, et pas un simple bloc : un `gap`
   n'existe que dans une grille, un conteneur flex ou du multicolonne. C'est ce
   `gap` qui porte l'entre-deux vertical. */
.ceweb-avis__set{
  flex: none;
  display: flex;
  flex-direction: column;
  /* L'entre-deux vertical est porté ici, par le `gap` du jeu, et non par une
     marge sur la carte : `<figure>` est une balise dont Elementor et les thèmes
     réinitialisent la marge avec un sélecteur plus fort qu'une simple classe
     (`.elementor figure{margin:0}` vaut 0,1,1 contre 0,1,0), et l'écart
     disparaissait donc en silence. Un `gap` sur le conteneur, lui, n'est la
     cible d'aucun reset.

     Le `padding-bottom` de même valeur n'est pas décoratif : il rejoue
     l'entre-deux APRÈS la dernière carte du jeu. Sans lui, la moitié de la
     piste ne tomberait plus sur une frontière de carte et la boucle sauterait
     d'un entre-deux à chaque tour. Le compte reste exact : un jeu mesure
     n × (carte + entre-deux). */
  gap: var(--ceweb-avis-card-gap);
  padding-bottom: var(--ceweb-avis-card-gap);
}

/* ============================================================
   Carte
   ============================================================ */
.ceweb-avis__card{
  display: flex;
  flex-direction: column;
  gap: var(--ceweb-avis-card-inner-gap);
  padding: var(--ceweb-avis-card-padding);
  background: var(--ceweb-avis-card-bg);
  border: var(--ceweb-avis-card-border-width) solid var(--ceweb-avis-card-border-color);
  border-radius: var(--ceweb-avis-card-radius);
  text-align: var(--ceweb-avis-align);
  /* Les cartes ne se compriment pas pour tenir dans la colonne : la piste est
     bien plus haute que la scène, c'est tout l'intérêt. */
  flex: none;
}

/* En-tête : pastille, nom, logo de la source. Un figcaption en premier enfant
   d'un figure est valide, et c'est là que la maquette met le nom. */
.ceweb-avis__head{
  display: flex;
  align-items: center;
  justify-content: var(--ceweb-avis-self);
  gap: var(--ceweb-avis-avatar-gap);
}

.ceweb-avis__avatar{
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--ceweb-avis-avatar-size);
  height: var(--ceweb-avis-avatar-size);
  background: var(--ceweb-avis-avatar-bg);
  color: var(--ceweb-avis-avatar-color);
  border-radius: var(--ceweb-avis-avatar-radius);
  /* Le rognage vit sur la pastille, pas seulement sur l'image : <img> est la
     balise que les thèmes stylent le plus volontiers, et une règle globale
     .entry-content img battrait un rayon posé sur la seule image. Un rognage,
     lui, ne se contredit pas à distance. */
  overflow: hidden;
  font-size: calc(var(--ceweb-avis-avatar-size) * 0.4);
  font-weight: 600;
  line-height: 1;
  text-transform: uppercase;
}
.ceweb-avis__avatar img{
  display: block;
  width: 100%;
  height: 100%;
  padding: var(--ceweb-avis-avatar-padding);
  object-fit: var(--ceweb-avis-avatar-fit);
  border-radius: inherit;
}
.ceweb-avis__avatar svg{
  width: var(--ceweb-avis-avatar-icon-size);
  height: var(--ceweb-avis-avatar-icon-size);
  fill: currentColor;
}
.ceweb-avis__avatar i{
  font-size: var(--ceweb-avis-avatar-icon-size);
  line-height: 1;
}

/* Nom et entreprise empilés, collés à la pastille.
   `flex: 0 1 auto` et non `1 1 auto` : le bloc ne prend que sa largeur, il ne
   s'étale pas sur toute la ligne. C'est ce qui fait que pastille et texte
   forment un groupe, que `justify-content` peut ensuite pousser à gauche, au
   centre ou à droite. Étalé, le bloc resterait large et « centrer » ne
   centrerait que le texte à l'intérieur, à côté d'une pastille restée à
   gauche.
   `min-width: 0` autorise la troncature d'un nom très long au lieu d'élargir
   l'en-tête. */
.ceweb-avis__identity{
  flex: 0 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  /* Les deux lignes sont ramenées à leur largeur utile et collées au même bord,
     au lieu d'être étirées sur toute la largeur du bloc. Leur position ne
     dépend donc plus du tout d'un `text-align` — donc plus de nom et
     d'entreprise qui se décalent l'un par rapport à l'autre selon leur
     longueur. */
  align-items: var(--ceweb-avis-self);
  gap: var(--ceweb-avis-identity-gap);
}

.ceweb-avis__name{
  color: var(--ceweb-avis-name-color);
  font-size: 16px;
  font-weight: 600;
  line-height: 1.3;
}

.ceweb-avis__company{
  color: var(--ceweb-avis-company-color);
  font-size: 14px;
  font-weight: 400;
  line-height: 1.3;
}

/* ============================================================
   Note

   Deux rangées d'étoiles superposées : la grise, complète, dans le flux, et la
   dorée au-dessus, rognée à la fraction de la note. Une demi-étoile ne demande
   donc aucun glyphe particulier, juste une largeur. La rangée dorée est en
   position absolue — sortie du flux, elle ne peut pas doubler la hauteur.
   ============================================================ */
.ceweb-avis__rating{
  display: flex;
  align-items: center;
  justify-content: var(--ceweb-avis-self);
  gap: 10px;
}

.ceweb-avis__stars{
  position: relative;
  display: inline-flex;
  flex: none;
}
.ceweb-avis__stars-row{
  display: flex;
  gap: var(--ceweb-avis-star-gap);
  color: var(--ceweb-avis-star-empty-color);
}
/* `left` et `top` seulement, jamais `inset: 0` : avec une largeur en plus, la
   boîte serait sur-contrainte et le navigateur choisirait lui-même quel côté
   ignorer. La largeur est justement ce qui porte la note. */
.ceweb-avis__stars-row--full{
  position: absolute;
  top: 0;
  left: 0;
  width: var(--ceweb-avis-fill, 100%);
  overflow: hidden;
  color: var(--ceweb-avis-star-color);
}
.ceweb-avis__stars svg{
  flex: none;                  /* La rangée dorée est rognée, jamais compressée. */
  display: block;
  width: var(--ceweb-avis-star-size);
  height: var(--ceweb-avis-star-size);
  fill: currentColor;
}

.ceweb-avis__note{
  color: var(--ceweb-avis-note-color);
  font-size: 15px;
  font-weight: 600;
  line-height: 1;
}

/* ============================================================
   Texte et date
   ============================================================ */
.ceweb-avis__quote{
  margin: 0;
  padding: 0;
  border: 0;                   /* Les thèmes décorent volontiers blockquote. */
  color: var(--ceweb-avis-text-color);
  font-size: 15.5px;
  font-style: normal;
  line-height: 1.6;
}
.ceweb-avis__quote p{ margin: 0 0 0.7em; }
.ceweb-avis__quote p:last-child{ margin-bottom: 0; }

/* Écrêtage facultatif. La classe et la variable ne sont posées que si le
   contrôle passe au-dessus de zéro : sans elles, un avis long s'affiche en
   entier et la carte grandit, ce qui est le comportement par défaut voulu.

   Dans ce mode, PHP n'enveloppe plus le texte dans des paragraphes :
   `-webkit-line-clamp` ne compte que les lignes du bloc qui le porte, et des
   enfants de type bloc lui font compter n'importe quoi. Le texte arrive donc en
   direct, avec de simples `<br>`. */
.ceweb-avis--clamp .ceweb-avis__quote{
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: var(--ceweb-avis-lines, 6);
  overflow: hidden;
}

.ceweb-avis__date{
  margin: 0;
  color: var(--ceweb-avis-date-color);
  font-size: 14px;
  line-height: 1.4;
}

/* ============================================================
   Mouvement réduit

   Le défilement s'arrête net, et chaque colonne devient une zone qu'on fait
   défiler soi-même : sans cela, la moitié des avis resterait hors de la
   fenêtre, donc hors d'atteinte. Le second jeu de cartes disparaît — c'est un
   doublon qui n'existait que pour la boucle.
   ============================================================ */
@media (prefers-reduced-motion: reduce){
  .ceweb-avis__track{
    animation: none;
  }
  .ceweb-avis__set--clone{
    display: none;
  }
  .ceweb-avis__column{
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}
