/* -----------------------------------------------------------------------
   Composants réutilisables : boutons, cartes, formulaires, header/nav,
   carrousel, badges. Les styles ici ne dépendent pas de LA section dans
   laquelle le composant apparaît (contrairement à sections.css).
   ----------------------------------------------------------------------- */

/* --- Boutons --- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.7rem 1.5rem;
  border-radius: var(--radius);
  border: 1px solid transparent;
  font-size: 0.95rem;
  font-weight: 500;
  cursor: pointer;
  transition: background-color var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast);
}

.btn-primary {
  background: var(--color-navy);
  color: #fff;
}

.btn-primary:hover {
  background: var(--color-navy-dark);
  text-decoration: none;
  color: #fff;
}

.btn-outline-light {
  background: transparent;
  border-color: rgba(255, 255, 255, 0.6);
  color: #fff;
}

.btn-outline-light:hover {
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
  text-decoration: none;
}

/* --- Header / navigation --- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--color-surface);
  border-bottom: 1px solid transparent;
  transition: box-shadow var(--transition-fast), border-color var(--transition-fast);
}

/* Ajoutée en JavaScript dès que la page est défilée (voir js/main.js) :
   détache visuellement le header du contenu, un comportement standard des
   sites professionnels. */
.site-header--scrolled {
  box-shadow: var(--shadow-sm);
  border-bottom-color: var(--color-border);
}

.site-header__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  height: var(--header-height);
}

.site-header__brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  color: var(--color-text);
  flex-shrink: 0;
}

.site-header__brand:hover {
  text-decoration: none;
}

.site-header__logo {
  height: 40px;
  width: 40px;
  object-fit: contain;
}

.site-header__brand-text {
  font-weight: 500;
  font-size: 1.05rem;
  color: var(--color-navy-dark);
  white-space: nowrap;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: 2rem;
}

.site-nav__links {
  display: flex;
  gap: 1.75rem;
}

.site-nav__links a {
  color: var(--color-text-secondary);
  font-weight: 500;
  font-size: 0.95rem;
}

.site-nav__links a:hover {
  color: var(--color-navy);
  text-decoration: none;
}

.site-header__actions {
  display: flex;
  align-items: center;
  gap: 1rem;
}

/* Sélecteur de langue : réutilise le mécanisme existant (cookie posé par
   GET /lang/:lng, voir routes/publicRoutes.js), simplement restylé. */
.lang-switch {
  display: flex;
  gap: 0.25rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  padding: 0.2rem;
}

.lang-switch a {
  padding: 0.25rem 0.6rem;
  border-radius: var(--radius-pill);
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--color-text-muted);
}

.lang-switch a:hover {
  text-decoration: none;
  color: var(--color-navy);
}

.lang-switch a.active {
  background: var(--color-navy);
  color: #fff;
}

/* Bouton hamburger : visible seulement en dessous de 768px (voir la media
   query dans sections.css). Un vrai <button>, pas une <div> cliquable,
   pour rester utilisable au clavier et par les lecteurs d'écran. */
.hamburger {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 40px;
  height: 40px;
  border: none;
  background: transparent;
  cursor: pointer;
  padding: 0;
}

.hamburger__bar {
  display: block;
  width: 22px;
  height: 2px;
  background: var(--color-navy-dark);
  transition: transform var(--transition-fast), opacity var(--transition-fast);
}

/* Transforme les 3 barres en croix quand le menu mobile est ouvert (classe
   posée par js/main.js en fonction de aria-expanded). */
.hamburger[aria-expanded='true'] .hamburger__bar:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}

.hamburger[aria-expanded='true'] .hamburger__bar:nth-child(2) {
  opacity: 0;
}

.hamburger[aria-expanded='true'] .hamburger__bar:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

/* --- Cartes de contenu (services, réalisations, témoignages) --- */

.card-grid {
  display: grid;
  gap: 1.75rem;
}

.content-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 1.75rem;
  transition: box-shadow var(--transition-fast), transform var(--transition-fast);
}

.content-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}

.service-card__icon {
  width: 48px;
  height: 48px;
  border-radius: var(--radius);
  background: var(--color-navy-pale);
  color: var(--color-navy);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5rem;
  margin-bottom: 1rem;
}

.content-card h3 {
  font-size: 1.15rem;
}

/* Visuel d'une réalisation : image réelle ou repli (icône du service lié,
   voir views/partials/realisation-visual.ejs). */
.realisation-visual {
  width: 100%;
  height: 180px;
  border-radius: var(--radius);
  margin-bottom: 1rem;
}

.realisation-visual--image {
  object-fit: cover;
}

.realisation-visual--fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-navy-pale);
  color: var(--color-navy);
  font-size: 3rem;
}

.realisation-card__client {
  color: var(--color-text-muted);
  font-size: 0.85rem;
  margin-top: 0.75rem;
  margin-bottom: 0;
}

/* Avatar d'un témoignage : photo réelle ou cercle d'initiales (voir
   views/partials/temoignage-avatar.ejs). */
.temoignage-avatar {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  flex-shrink: 0;
}

.temoignage-avatar--image {
  object-fit: cover;
}

.temoignage-avatar--fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-navy);
  color: #fff;
  font-weight: 500;
}

.temoignage-card {
  display: flex;
  gap: 1rem;
  align-items: flex-start;
}

.temoignage-card__quote {
  font-style: italic;
  color: var(--color-text);
}

.temoignage-card__role {
  color: var(--color-text-muted);
  font-size: 0.85rem;
  margin: 0.25rem 0 0;
}

/* --- Formulaires --- */

.form-field {
  margin-bottom: 1.25rem;
}

.form-field label {
  display: block;
  font-weight: 500;
  font-size: 0.9rem;
  margin-bottom: 0.4rem;
  color: var(--color-text);
}

.form-field input[type='text'],
.form-field input[type='email'],
.form-field input[type='tel'],
.form-field input[type='file'],
.form-field select,
.form-field textarea {
  width: 100%;
  padding: 0.65rem 0.85rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  font-family: inherit;
  font-size: 0.95rem;
  color: var(--color-text);
  background: var(--color-surface);
  transition: border-color var(--transition-fast);
}

.form-field input:focus,
.form-field select:focus,
.form-field textarea:focus {
  border-color: var(--color-navy);
}

.form-field--invalid input,
.form-field--invalid select,
.form-field--invalid textarea {
  border-color: var(--color-danger);
}

.field-error {
  color: var(--color-danger);
  font-size: 0.85rem;
  margin-top: 0.35rem;
}

.field-hint {
  color: var(--color-text-muted);
  font-size: 0.8rem;
  margin-top: 0.35rem;
}

.form-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1.25rem;
}

.consent-row {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
}

.consent-row input {
  margin-top: 0.3rem;
}

.consent-row label {
  font-weight: 400;
  font-size: 0.85rem;
  color: var(--color-text-secondary);
}

/* Champ honeypot : jamais affiché à un visiteur humain (voir
   controllers/publicController.js pour la logique anti-spam associée).
   Sorti de l'écran plutôt que `display:none`, que certains robots de spam
   évitent volontairement de remplir en détectant ce style précis. */
.honeypot-field {
  position: absolute;
  left: -9999px;
  top: -9999px;
  opacity: 0;
  height: 0;
  overflow: hidden;
}

/* --- Badges de statut (devis) --- */

.status-badge {
  display: inline-block;
  padding: 0.3rem 0.85rem;
  border-radius: var(--radius-pill);
  font-size: 0.8rem;
  font-weight: 500;
  color: #fff;
}

.status-nouveau {
  background: var(--color-text-muted);
}

.status-en_cours {
  background: var(--color-navy);
}

.status-repondu {
  background: var(--color-success);
}

.status-cloture {
  background: var(--color-text);
}

/* --- Carrousel du hero --- */
/* Voir js/main.js pour la logique (minuterie, pause, navigation clavier)
   et views/partials/hero-carousel.ejs pour le balisage accessible. */

.carousel {
  position: relative;
}

.carousel__track {
  position: relative;
  min-height: 480px;
}

.carousel__slide {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--transition);
  background-color: var(--color-navy-dark);
  background-size: cover;
  background-position: center;
  color: #fff;
}

.carousel__slide--active {
  /* Pas de `position: relative` ici : chaque slide (active ou non) doit
     rester `position: absolute; inset: 0;` (hérité de .carousel__slide
     ci-dessus) pour remplir exactement la hauteur de .carousel__track
     (min-height: 480px). Seuls l'opacité et la visibilité changent pour
     montrer/cacher une slide.
     Bug corrigé (espace blanc disproportionné entre le hero et la bande
     de mise en avant, signalé à plusieurs reprises) : cette règle
     repassait la slide active en `position: relative`, la sortant du
     positionnement absolu qui la faisait remplir tout le bloc — une fois
     "en flux normal", sa hauteur ne dépendait plus que de son propre
     contenu (~300px, juste le texte), bien moins que les 480px du
     carrousel. Comme .hero n'a lui-même aucun fond propre (le fond navy
     vient entièrement du dégradé de la slide, voir .carousel__slide::before
     ci-dessous), les ~180px de .carousel__track non couverts par la
     slide active laissaient voir le blanc de la page en dessous —
     visuellement indiscernable d'un "espace entre les sections", alors
     que .hero et .highlights-bar-section restaient parfaitement adjacents
     (0px d'écart réel entre leurs boîtes, ce qui explique pourquoi les
     mesures précédentes sur CES deux éléments ne révélaient rien
     d'anormal : le vide était À L'INTÉRIEUR de .hero, pas ENTRE .hero et
     la section suivante). */
  opacity: 1;
  visibility: visible;
}

/* Voile sombre semi-transparent : garantit que le texte reste lisible
   même sur une image de fond claire. */
.carousel__slide::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(120deg, rgba(12, 44, 77, 0.88), rgba(12, 44, 77, 0.6));
}

.carousel__content {
  position: relative;
  z-index: 1;
  max-width: 620px;
  padding: 2rem 0;
}

.carousel__content h1 {
  color: #fff;
}

.carousel__content p {
  color: var(--color-navy-pale);
  font-size: 1.1rem;
}

.carousel__arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.4);
  background: rgba(12, 44, 77, 0.5);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.1rem;
  cursor: pointer;
  transition: background-color var(--transition-fast);
}

.carousel__arrow:hover {
  background: rgba(12, 44, 77, 0.85);
}

.carousel__arrow--prev {
  left: 1rem;
}

.carousel__arrow--next {
  right: 1rem;
}

.carousel__dots {
  position: absolute;
  bottom: 1.25rem;
  left: 0;
  right: 0;
  z-index: 2;
  display: flex;
  justify-content: center;
  gap: 0.6rem;
}

.carousel__dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: none;
  background: rgba(255, 255, 255, 0.4);
  cursor: pointer;
  padding: 0;
  transition: background-color var(--transition-fast), transform var(--transition-fast);
}

.carousel__dot--active {
  background: #fff;
  transform: scale(1.2);
}

/* --- Bande de mise en avant (highlights_bar) --- */
/* Voir views/partials/highlights-bar.ejs et le paramètre "highlights_bar"
   dans site_settings (édité depuis /admin/parametres). */

.highlights-bar {
  background: var(--color-surface-alt);
  border-bottom: 1px solid var(--color-border);
}

/* Accroche sobre au-dessus des chiffres — même ton discret que
   .partenaires__label (pas un titre de section imposant, voir
   base.css/.section-title pour la comparaison). */
.highlights-bar__intro {
  text-align: center;
  font-size: 0.8rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-text-muted);
  padding-top: 1.5rem;
}

.highlights-bar__list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  text-align: center;
}

.highlights-bar__item {
  padding: 2rem 1rem;
  border-left: 1px solid var(--color-border);
}

.highlights-bar__item:first-child {
  border-left: none;
}

.highlights-bar__value {
  display: block;
  font-size: 2rem;
  font-weight: 500;
  color: var(--color-navy);
}

.highlights-bar__label {
  color: var(--color-text-muted);
  font-size: 0.9rem;
}

/* --- Partenaires ("Ils nous font confiance") --- */
/* Section placée entre témoignages et devis (voir views/public/home.ejs
   et public/css/sections.css pour le padding vertical, propre à cette
   section). Volontairement discrète : pas de grand titre comme
   .section-title (base.css), juste un petit label sobre en majuscules —
   cette section ne doit pas rivaliser visuellement avec le contenu
   principal. */

.partenaires__label {
  text-align: center;
  font-size: 0.8rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-text-muted);
  margin-bottom: 1.75rem;
}

/* Défilement continu ("marquee") des logos : `.partenaires-marquee` est le
   masque (overflow hidden) et `.partenaires-marquee__track` la piste
   défilante. Par défaut (avant que public/js/main.js n'intervienne),
   c'est une simple rangée centrée qui passe à la ligne — c'est ce que
   voit un visiteur avec peu de partenaires (moins de 4, voir main.js :
   le défilement n'a de sens qu'à partir d'un nombre suffisant de logos
   pour remplir visuellement la largeur), avec JavaScript désactivé, ou
   pendant le court instant avant l'initialisation du script.
   `initPartenairesMarquee` (main.js) ajoute la classe
   `.partenaires-marquee--scrolling` UNIQUEMENT quand un défilement réel a
   du sens (4 logos ou plus ET prefers-reduced-motion inactif) : c'est
   cette classe, pas une media query, qui active l'animation ci-dessous. */
.partenaires-marquee {
  overflow: hidden;
  width: 100%;
}

.partenaires-marquee__track {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 2rem 2.75rem;
  width: 100%;
}

.partenaires-marquee__item {
  flex: 0 0 auto;
}

/* État défilant : la piste contient DEUX copies identiques des logos
   (dupliquées par main.js), mises bout à bout sans retour à la ligne et
   larges de leur contenu (`width: max-content`) — l'animation ne
   translate que sur 50% de cette largeur double, donc exactement la
   largeur d'une seule copie : la fin de la 1re copie s'enchaîne alors
   pile avec le début de la 2e (identique), et le bouclage est invisible. */
.partenaires-marquee--scrolling .partenaires-marquee__track {
  flex-wrap: nowrap;
  justify-content: flex-start;
  width: max-content;
  animation: partenaires-marquee-scroll var(--marquee-duration, 30s) linear infinite;
}

/* Pause au survol ET au focus clavier (cohérent avec le carrousel du
   hero) : `:focus-within` suffit ici, contrairement au carrousel, car
   l'animation est une simple transformation CSS continue — pas besoin de
   JavaScript pour l'arrêter/reprendre, le navigateur s'en charge. */
.partenaires-marquee--scrolling:hover .partenaires-marquee__track,
.partenaires-marquee--scrolling:focus-within .partenaires-marquee__track {
  animation-play-state: paused;
}

@keyframes partenaires-marquee-scroll {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}

/* Logo en niveaux de gris par défaut, qui reprend ses couleurs au
   survol/focus — appliqué aussi bien à l'image réelle qu'au repli
   textuel (voir views/partials/partenaire-logo.ejs), pour un rendu
   cohérent que le logo existe ou non. */
.partenaire-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  filter: grayscale(100%);
  opacity: 0.6;
  transition: filter var(--transition), opacity var(--transition);
}

.partenaire-logo:hover,
.partenaire-logo:focus-visible {
  filter: grayscale(0%);
  opacity: 1;
}

/* Le repli textuel (nom du partenaire) n'a pas d'image à désaturer : le
   même effet visuel "en retrait -> mis en avant" est reproduit via la
   couleur du texte et de la bordure plutôt que via `filter`. */
.partenaire-logo--static .partenaire-logo__fallback {
  cursor: default;
}

.partenaire-logo__image {
  max-height: 42px;
  max-width: 140px;
  width: auto;
  object-fit: contain;
}

.partenaire-logo__fallback {
  display: inline-flex;
  align-items: center;
  padding: 0.6rem 1.1rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  color: var(--color-text-secondary);
  font-weight: 500;
  font-size: 0.9rem;
  white-space: nowrap;
}

.partenaire-logo:hover .partenaire-logo__fallback,
.partenaire-logo:focus-visible .partenaire-logo__fallback {
  border-color: var(--color-navy);
  color: var(--color-navy);
}

/* --- Lien discret vers le backoffice, dans le pied de page --- */
.site-footer__admin-link-sep {
  margin: 0 0.4em;
  opacity: 0.5;
}

.site-footer__admin-link {
  font-size: 0.8rem;
  color: var(--color-navy-light);
  opacity: 0.7;
}

.site-footer__admin-link:hover {
  opacity: 1;
}

/* --- Bouton flottant "retour en haut de page" --- */
/* Masqué par défaut (opacity + visibility, jamais `display: none` : on
   veut une transition douce à l'apparition, ce qu'un `display` ne permet
   pas d'animer) ; `public/js/main.js` ajoute `.back-to-top--visible`
   après un certain défilement. `pointer-events: none` tant qu'il est
   masqué évite qu'il intercepte des clics destinés au contenu en dessous
   (le bouton reste dans le DOM, superposé en `position: fixed`, même
   invisible).
   Position fixe coin inférieur droit, avec une marge confortable (1.5rem)
   pour ne jamais coller au bord ni au contenu du footer en dessous.
   z-index intentionnellement sous le header (.site-header, 100) et le
   lien d'évitement (.skip-link, 1000) : le bouton ne doit jamais passer
   au-dessus du menu mobile ouvert (qui vit dans le header) ni d'une
   éventuelle modale future. */
.back-to-top {
  position: fixed;
  right: 1.5rem;
  bottom: 1.5rem;
  z-index: 40;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: none;
  background: var(--color-navy);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.3rem;
  cursor: pointer;
  box-shadow: var(--shadow-md);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity var(--transition), visibility var(--transition), background-color var(--transition-fast);
}

.back-to-top--visible {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

.back-to-top:hover {
  background: var(--color-navy-dark);
}

@media (max-width: 767px) {
  .back-to-top {
    right: 1rem;
    bottom: 1rem;
    width: 44px;
    height: 44px;
  }
}
