/* ══════════════════════════════════════════════════════════════════════
   LIBRADEV — COUCHE D'HARMONISATION
   ----------------------------------------------------------------------
   Chargée APRÈS le <style> de chaque page. Elle impose le même système
   de formes, d'échelles typographiques et de badges sur tout le site,
   sans avoir à réécrire le CSS propre à chaque page.

   Toute modification du langage visuel se fait ICI, une seule fois.
   ══════════════════════════════════════════════════════════════════════ */

:root {
  /* ── Couleurs ── */
  --ink: #111118;
  --ink-soft: #1c1c28;
  --surface: #191924;
  --surface-2: #222232;
  --surface-3: #282840;
  --lavender: #b8a8e8;
  --lavender-light: #d4caf5;
  --lavender-dim: #7c6eb8;
  --sage: #8ec4a0;
  --sage-light: #b4dfc3;
  --cream: #f5f1e8;
  --cream-soft: #e2ddd4;
  --muted: #8e8aa8;
  --muted-light: #b0accc;
  --line: rgba(184,168,232,0.22);
  --line-strong: rgba(184,168,232,0.40);
  --gold: #d4a84c;

  /* ── Formes ── */
  --radius-card: 18px;   /* cartes, panneaux, modales */
  --radius-media: 12px;  /* visuels à l'intérieur d'une carte */
  --radius-field: 10px;  /* champs de formulaire */
  --radius-pill: 999px;  /* boutons, badges, filtres */

  /* ── Surfaces de carte ── */
  --card-bg: rgba(255,255,255,0.03);
  --card-bg-hover: rgba(184,168,232,0.05);

  /* ── Mouvement ──
     Courbe maison : décélération franche avec un léger dépassement. Elle
     existait déjà dans le projet, mais ne servait qu'à l'accordéon de la
     FAQ. Elle devient la courbe de référence de tout le site.            */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --reveal-step: 70ms;
}

/* ══ 1. TITRES DE PAGE ══════════════════════════════════════════════
   Un seul H1 de page sur tout le site, plus discret que le hero
   de l'accueil pour préserver la hiérarchie entre les pages.        */
.page-title {
  font-family: 'Cormorant Garamond', serif;
  font-size: clamp(46px, 6.5vw, 92px);
  font-weight: 300;
  line-height: 0.98;
  letter-spacing: -0.02em;
}
.page-title em { font-style: italic; color: var(--lavender-light); }

/* Sur-titres : 11px / 0.22em partout */
.page-eyebrow,
.section-label,
.faq-category-label { font-size: 11px; letter-spacing: 0.22em; }

/* Chapô de page */
.page-sub, .page-intro { font-size: 16px; line-height: 1.8; }

/* ══ 2. BOUTONS ══════════════════════════════════════════════════════ */
.btn-primary, .btn-submit, .btn-start, .filter-btn,
.modal-link, .img-upload-btn, .admin-save, .admin-new-btn,
.admin-preview-btn, .admin-delete, .auth-submit-btn,
.auth-open-admin-btn, .auth-logout-btn, .block-type-btn,
.ai-generate-btn, .ai-option-chip, .admin-tab,
.btn-cta-primary, .btn-next, .btn-prev, .btn-send-email, .scale-btn {
  border-radius: var(--radius-pill);
}

/* ══ 3. BADGES ET PILULES ════════════════════════════════════════════
   10px, 0.16em, pilule pleine — identique sur toutes les pages.      */
.project-tag, .modal-tag, .page-tag, .blog-category,
.article-category, .admin-tag-pill, .skeleton-tag, .tech-pill,
.module-pill, .priority-badge, .profil-badge, .results-profil-tag {
  border-radius: var(--radius-pill);
}
.project-tag, .modal-tag, .page-tag {
  font-size: 11px;
  letter-spacing: 0.16em;
  padding: 5px 12px;
}
.blog-category, .article-category { font-size: 11px; letter-spacing: 0.16em; }
.tech-pill { padding: 12px 22px; }
.step-time, .use-example { font-size: 11px; letter-spacing: 0.14em; }

/* ══ 4. CARTES ═══════════════════════════════════════════════════════
   Fond translucide, bordure fine, coins arrondis, léger soulèvement
   au survol : le même objet visuel que sur l'accueil.                */
.project-card, .blog-card, .use-card {
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--card-bg);
  transition: background 0.4s, border-color 0.4s, transform 0.4s;
}
.project-card:hover, .blog-card:hover, .use-card:hover {
  background: var(--card-bg-hover);
  border-color: var(--line-strong);
  transform: translateY(-5px);
}
/* neutralise les fonds pleins hérités */
.project-card:hover .project-card-inner { background: transparent; }
.use-card { border-top: 1px solid var(--line); }

/* Respiration entre les cartes */
.projects-grid, .blog-grid, .use-grid { gap: 22px; }

/* Visuels à l'intérieur des cartes */
.project-thumb, .blog-thumb, .modal-thumb,
.article-hero-img, .block-image img, .about-visual {
  border-radius: var(--radius-media);
  overflow: hidden;
}

/* Panneaux et modales */
.modal, .faq-cta, .auth-modal, .article-content,
.block-highlight, .block-callout, .block-code,
.question-card, .cta-card, .profil-card, .email-form-card,
.ai-analysis-card, .analyzing-step, .option-btn {
  border-radius: var(--radius-card);
}
.progress-bar-wrap, .progress-bar-fill, .mscore-bar-wrap, .mscore-bar, .email-input {
  border-radius: var(--radius-pill);
}

/* Squelettes de chargement : même silhouette que les vraies cartes */
.skeleton-card, .skeleton-blog-card, .real-skeleton {
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  overflow: hidden;
}
.skeleton-thumb, .skeleton-blog-thumb { border-radius: var(--radius-media); }
.skeleton-tag, .skeleton-title, .skeleton-line,
.skeleton-category, .skeleton-blog-title, .skeleton-blog-line { border-radius: var(--radius-pill); }

/* ══ 5. BANDEAUX DE CHIFFRES ════════════════════════════════════════
   Plus de cellules soudées : des cartes espacées.                    */
.stats-band {
  gap: 16px;
  background: transparent;
  padding: 56px 0;
  max-width: 1240px;
  margin: 0 auto;
}
.stat-cell,
.stat-cell:last-child {
  border: 1px solid var(--line);
  border-radius: 16px;
  background: rgba(255,255,255,0.02);
  padding: 32px 28px;
}

/* ══ 6. ICÔNES ═══════════════════════════════════════════════════════
   Carré arrondi à dégradé, comme sur l'accueil — plus de cercles
   à filet fin qui juraient avec le reste.                            */
.use-icon {
  width: 56px;
  height: 56px;
  border: none;
  border-radius: 14px;
  background: linear-gradient(140deg, #3d2870 0%, #1a1035 100%);
  box-shadow: inset 0 0 0 1px rgba(184,168,232,0.4);
  font-size: 22px;
}

/* ══ 7. CHAMPS DE FORMULAIRE ════════════════════════════════════════ */
.form-group input, .form-group textarea, .form-group select,
.admin-field input, .admin-field textarea, .admin-field select,
.auth-field input, .ai-prompt-input, .img-url-fallback input,
.block-item-body input, .block-item-body textarea {
  border-radius: var(--radius-field);
}

/* ══ 8. MASCOTTE ═════════════════════════════════════════════════════
   Les cinq poses sont détourées sur fond transparent, avec le halo
   violet d'origine conservé : elles ne fonctionnent QUE sur les fonds
   sombres du site (--ink, --surface). Ne jamais les poser sur du clair.

   Règle de dosage : deux mascottes maximum par page, et jamais deux
   dans deux sections qui se suivent — au delà, elle cesse d'être un
   accent pour devenir un motif de fond.

   Fichiers : /images/mascotte/{laptop,index,pointe,notes,fauteuil}.webp
              suffixe -sm = version 320px pour les petits formats.      */
.mascotte {
  display: block;
  height: auto;
  max-width: 100%;
  user-select: none;
  -webkit-user-drag: none;
  pointer-events: none;
  filter: drop-shadow(0 20px 45px rgba(0,0,0,0.55));
}

/* Échelles — une seule variante par emplacement */
.mascotte--hero    { width: 400px; }  /* à côté d'un titre de page   */
.mascotte--section { width: 300px; }  /* accompagne un header         */
.mascotte--inline  { width: 180px; }  /* petit accent près d'un texte */

/* Flottement discret : la mascotte respire, elle ne s'agite pas */
@keyframes mascotteFloat {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-13px); }
}
.mascotte--float { animation: mascotteFloat 7s ease-in-out infinite; }

/* ── Bascule desktop / mobile ────────────────────────────────────────
   Ces deux règles DOIVENT vivre ici, jamais dans le <style> d'une page :
   brand.css est chargée après, et `.mascotte { display: block }` plus haut
   écraserait tout `display: none` posé en amont — spécificité identique,
   c'est l'ordre source qui tranche.

   `--only-mobile` sert quand la version mobile ne peut pas être le même
   nœud que la version desktop (placement différent dans le DOM). Les deux
   pointent la même URL : le navigateur ne télécharge qu'une fois.        */
.mascotte--only-mobile { display: none; }

/* Halo derrière la mascotte, pour l'asseoir sur le fond */
.mascotte-glow { position: relative; display: inline-block; }
.mascotte-glow::before {
  content: '';
  position: absolute;
  inset: -12% -8%;
  border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(184,168,232,0.18) 0%, transparent 68%);
  pointer-events: none;
}

/* ══ 9. RESPONSIVE ══════════════════════════════════════════════════ */
@media (max-width: 900px) {
  .projects-grid, .blog-grid, .use-grid { gap: 18px; }
  .stats-band { gap: 12px; padding: 40px 0; }
  .stat-cell, .stat-cell:last-child { padding: 26px 22px; }

  /* La mascotte ne doit jamais repousser le contenu */
  .mascotte--hero    { width: 260px; }
  .mascotte--section { width: 210px; }
  .mascotte--inline  { width: 140px; }

  /* Bascule mobile — voir la note ci-dessous */
  .mascotte--no-mobile   { display: none; }
  .mascotte--only-mobile { display: block; }
}

/* ══ 10. RÉVÉLATIONS AU DÉFILEMENT ═══════════════════════════════════
   Chaque page déclare sa propre règle `.reveal` dans son <style>. brand.css
   étant chargée après, cette section les remplace toutes : un seul endroit
   pour régler le rythme des 11 pages.

   Trois apports par rapport à l'origine, qui appliquait la MÊME translation
   verticale de 18-24px et la courbe `ease` par défaut à 51 éléments :
     1. la courbe maison, avec son léger dépassement ;
     2. une cascade entre éléments d'une même rangée (--reveal-i, posé par
        navbar.js) : une grille de cartes ne surgit plus d'un bloc ;
     3. des entrées directionnelles dans les sections à deux colonnes,
        chaque côté entrant depuis le sien.                                */
.reveal {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity .7s var(--ease-out), transform .7s var(--ease-out);
  transition-delay: calc(var(--reveal-i, 0) * var(--reveal-step));
}
.reveal.in-view { opacity: 1; transform: none; }

/* Colonnes de gauche / de droite — spécificité 0,2,0, donc au-dessus de
   la règle générique ci-dessus. */
.reveal.about-left,
.reveal.contact-left,
.reveal.enjeux-aside   { transform: translate(-30px, 12px); }
.reveal.about-right,
.reveal.contact-right  { transform: translate(30px, 12px); }

@media (max-width: 900px) {
  /* Les colonnes s'empilent : une entrée latérale n'aurait plus de sens,
     et elle provoquerait un débordement horizontal. */
  .reveal.about-left, .reveal.contact-left, .reveal.enjeux-aside,
  .reveal.about-right, .reveal.contact-right { transform: translateY(24px); }
}

@media (prefers-reduced-motion: reduce) {
  .mascotte--float { animation: none; }
  /* Le contenu doit rester lisible : on neutralise le mouvement, pas
     l'affichage — sans quoi tout resterait invisible. */
  .reveal, .reveal.about-left, .reveal.contact-left, .reveal.enjeux-aside,
  .reveal.about-right, .reveal.contact-right {
    opacity: 1; transform: none; transition: none; transition-delay: 0s;
  }
}

/* ══ 11. ILLUSTRATIONS DE SECTION ════════════════════════════════════
   Les pages /services portent une illustration SVG au milieu d'une
   section. Ces fichiers (public/visuels/) sont dessinés à FOND
   TRANSPARENT et embarquent déjà leurs ombres portées : on ne les
   encadre pas dans une carte, ils reposent directement sur le fond
   de page. Les attributs width/height du <img> reprennent le viewBox
   pour réserver la place avant chargement.                            */
.svc-figure { margin: 0; }
.svc-figure img { display: block; width: 100%; height: auto; }
.svc-figure figcaption {
  margin: 18px auto 0;
  max-width: 560px;
  font-size: 13px;
  line-height: 1.7;
  color: var(--muted-light);
  text-align: center;
}

/* Illustration centrée entre deux blocs d'une même section. La marge
   haute vient du bloc précédent (.sec-head, .outils-header). */
.svc-figure--wide { max-width: 920px; margin: 0 auto 56px; }

/* Section à deux colonnes : texte d'un côté, illustration de l'autre.
   Réutilise les entrées directionnelles .about-left / .about-right. */
.svc-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr);
  gap: 60px;
  align-items: center;
}
.svc-split .svc-figure figcaption { text-align: left; margin-left: 0; }

@media (max-width: 900px) {
  .svc-split { grid-template-columns: 1fr; gap: 40px; }
  .svc-figure--wide { margin-bottom: 40px; }
  .svc-figure figcaption { text-align: left; margin-left: 0; }
}

/* ══ 12. TRANSITIONS DE PAGE ═════════════════════════════════════════
   Fondu enchaîné natif entre les pages, sans JavaScript ni bibliothèque.
   La règle doit être présente dans le document QUITTÉ comme dans le
   document CHARGÉ : elle vit donc ici, la seule feuille commune à toutes
   les pages publiques.

   Chrome, Edge et Safari 18+ l'appliquent. Firefox l'ignore et garde le
   comportement d'aujourd'hui — aucune dégradation, juste l'absence de
   l'effet.

   NOTE — on ne nomme PAS la barre de navigation, alors que ce serait le
   réflexe pour la faire persister d'une page à l'autre. navbar.js
   importe Firebase depuis un CDN : son exécution attend une requête
   réseau, et la barre n'existe donc pas encore quand le navigateur prend
   l'instantané de la page entrante. Nommée d'un seul côté, elle sortirait
   en fondu puis réapparaîtrait d'un coup — moins bon qu'un fondu simple.
   À reprendre si navbar.js cesse un jour de dépendre du CDN.          */
@view-transition { navigation: auto; }

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 260ms;
  animation-timing-function: var(--ease-out);
}

/* ══ 13. RETOUR AU CLIC ══════════════════════════════════════════════
   Le site n'avait aucun état :active — rien ne répondait à la pression.
   L'enfoncement est volontairement bref et faible : il doit se sentir
   sans se voir.

   Appliqué aux commandes, pas aux cartes : plusieurs cartes portent déjà
   une translation au survol et un décalage d'entrée en révélation, et
   écraser leur transform ici produirait des sauts.

   On ne touche PAS au `transition` de base de ces éléments. Le réflexe
   serait d'y ajouter `transform` pour adoucir l'enfoncement, mais cette
   propriété est un raccourci : la redéclarer écraserait des réglages
   existants — le `transition: all .3s` de .filter-btn, par exemple. Seul
   l'état :active est posé. Là où transform est déjà transitionné, on
   obtient un appui vif et un relâchement souple ; ailleurs, un appui net
   dans les deux sens. Les deux se tiennent, et rien n'est cassé.      */
.btn-primary:active, .btn-ghost:active, .btn-submit:active, .btn-start:active,
.btn-cta-primary:active, .btn-next:active, .btn-prev:active, .btn-send-email:active,
.nav-cta:active, .filter-btn:active, .modal-link:active, .scale-btn:active,
.stack-chip:active, .ai-option-chip:active, .admin-tab:active, .block-type-btn:active {
  transform: scale(.972);
  transition-duration: .08s;   /* l'enfoncement est immédiat, le retour non */
}

/* Les liens de navigation n'ont pas de surface : ils s'assombrissent au
   lieu de s'enfoncer. */
.nav-links a:active, .nav-dropdown-toggle:active { opacity: .62; transition-duration: .08s; }

/* ══ 14. DÉFILEMENT ══════════════════════════════════════════════════
   scroll-behavior: smooth était déjà posé page par page, mais sans garde
   de mouvement réduit — sept pages l'imposaient à des utilisateurs qui
   demandent explicitement l'inverse. Chargée après les styles de page,
   cette règle les couvre toutes en un seul endroit. Le smooth global
   rattrape aussi 404.html, qui n'en avait pas.                        */
html { scroll-behavior: smooth; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
  .btn-primary:active, .btn-ghost:active, .btn-submit:active, .btn-start:active,
  .btn-cta-primary:active, .btn-next:active, .btn-prev:active, .btn-send-email:active,
  .nav-cta:active, .filter-btn:active, .modal-link:active, .scale-btn:active,
  .stack-chip:active, .ai-option-chip:active, .admin-tab:active, .block-type-btn:active {
    transform: none;
  }
}

/* ══ 15. DÉBORDEMENT HORIZONTAL ══════════════════════════════════════
   Aucune page ne doit pouvoir défiler latéralement, en particulier sur
   mobile.

   Chaque page posait jusqu'ici son propre `overflow-x: hidden`, et sept
   d'entre elles le posaient à la fois sur html ET sur body. Cette
   combinaison a un effet de bord peu connu : tant que html laisse passer
   le débordement, le `hidden` de body est reporté sur la fenêtre et body
   reste transparent au défilement ; dès que html masque à son tour, body
   garde sa valeur et devient son propre conteneur de défilement. Or
   `position: sticky` se cale sur le conteneur de défilement le plus
   proche — celui de body ne défile jamais. Le panneau de résultats du
   calculateur et l'aside des enjeux de l'accueil ne collaient donc plus,
   ils défilaient comme du contenu ordinaire.

   `clip` produit le même résultat visible que `hidden` — rien ne dépasse,
   rien ne défile — mais sans créer de conteneur de défilement, donc sans
   casser sticky. La déclaration `hidden` qui la précède sert de repli aux
   navigateurs antérieurs à `clip` (Safari < 16) ; posée sur html seul,
   elle est sans effet sur sticky.

   Ce n'est qu'un filet. Un débordement reste un défaut de mise en page à
   corriger à sa source : ce qui dépasse ici n'est pas atteignable, juste
   coupé. Le filet garantit seulement qu'un oubli ne se traduira jamais
   par un défilement latéral.                                           */
html { overflow-x: hidden; overflow-x: clip; }

/* Neutralise les `overflow-x: hidden` que les pages posent sur body :
   c'est cette déclaration-là qui cassait sticky. Le garde-fou ci-dessus
   la remplace intégralement. */
body { overflow-x: visible; }
