/* project-detail.css */
/* ===========================================================
   CyNoLux — Pages projet du portfolio (fiches détaillées)
   Chargé APRÈS finitions.css : composants additifs uniquement,
   rien ici ne redéfinit les fondations du design system.
   =========================================================== */

/* ---------- 1. Repères dans le hero (client / année / durée) ---------- */
.hero-meta-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-top: 22px;
}
.hero-meta-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.82rem;
  font-weight: 600;
  color: #fff;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.22);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  padding: 8px 16px;
  border-radius: var(--r-pill);
}
.hero-meta-chip i { color: var(--gold-400); font-size: 0.95em; }

/* ---------- 2. Mise en page à deux colonnes ---------- */
.pd-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.62fr) minmax(0, 1fr);
  gap: 40px;
  align-items: start;
}
@media (max-width: 980px) {
  .pd-layout { grid-template-columns: 1fr; gap: 32px; }
}

.pd-main { min-width: 0; }
.pd-section + .pd-section { margin-top: 44px; }

.pd-kicker {
  font-family: var(--f-mono);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold-700);
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
}
.pd-kicker::before { content: ""; width: 18px; height: 1.5px; background: var(--gold-500); display: inline-block; }
.pd-section h2 { font-size: clamp(1.35rem, 2.2vw, 1.7rem); margin-bottom: 4px; }
.pd-lead { font-size: 1.02rem; line-height: 1.7; }

/* ---------- 3. Visuel d'aperçu (mockup navigateur, sans capture d'écran) ---------- */
.pd-visual {
  border-radius: var(--r-lg);
  overflow: hidden;
  border: 1px solid var(--glass-border);
  box-shadow: var(--glass-shadow);
  margin-bottom: 40px;
}
.pd-visual-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 13px 16px;
  background: rgba(7, 25, 56, 0.9);
}
.pd-visual-dot { width: 9px; height: 9px; border-radius: 50%; background: rgba(255, 255, 255, 0.25); display: inline-block; }
.pd-visual-url {
  margin-left: 10px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--f-mono);
  font-size: 0.72rem;
  color: rgba(255, 255, 255, 0.55);
  background: rgba(255, 255, 255, 0.07);
  padding: 4px 12px;
  border-radius: var(--r-pill);
}
.pd-visual-stage {
  position: relative;
  height: 300px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  overflow: hidden;
  background: linear-gradient(135deg, var(--navy-800), var(--navy-500));
}
@media (max-width: 640px) { .pd-visual-stage { height: 220px; } }
.pd-visual-glow {
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 78% 12%, rgba(253, 185, 19, 0.4), transparent 55%),
    radial-gradient(circle at 8% 92%, rgba(62, 107, 219, 0.55), transparent 50%);
}
.pd-visual-icon {
  position: relative;
  font-size: 2.4rem;
  color: var(--gold-400);
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.18);
  width: 76px;
  height: 76px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 22px;
}
.pd-visual-word {
  position: relative;
  font-family: var(--f-display);
  font-weight: 700;
  font-size: clamp(1.6rem, 4vw, 2.4rem);
  color: rgba(255, 255, 255, 0.96);
  letter-spacing: -0.01em;
  text-align: center;
  padding: 0 24px;
}
/* Variantes de teinte selon la famille du projet */
.pd-visual--applications .pd-visual-stage { background: linear-gradient(135deg, var(--navy-900), #1c3f8f); }
.pd-visual--outils .pd-visual-stage { background: linear-gradient(135deg, #101a33, var(--navy-700)); }
.pd-visual--sites-web .pd-visual-stage { background: linear-gradient(135deg, var(--navy-800), #2c58c9); }

/* ---------- 4. Grille de fonctionnalités ---------- */
.pd-feature-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 14px;
  margin-top: 22px;
  list-style: none;
  padding: 0;
}
.pd-feature {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 16px;
  border-radius: var(--r-md);
  background: var(--glass-fill);
  border: 1px solid var(--glass-border);
}
.pd-feature-icon {
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(253, 185, 19, 0.16);
  color: var(--gold-700);
  font-size: 0.9rem;
}
.pd-feature span { font-size: 0.92rem; color: var(--ink); font-weight: 600; line-height: 1.45; }

/* ---------- 5. Stack technique (réutilise .pmodal-pill) ---------- */
.pd-pills { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 20px; }
.pd-pills .pmodal-pill {
  font-size: 0.84rem;
  padding: 7px 16px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  background: var(--glass-fill);
  border: 1px solid var(--glass-border);
  color: var(--navy-700);
}
[data-theme="dark"] .pd-pills .pmodal-pill { color: var(--gold-200); }
.pd-pills .pmodal-pill i { color: var(--gold-600); }

/* ---------- 6. Projets liés ---------- */
.pd-related-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 14px; margin-top: 20px; }
.pd-related-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px;
  border-radius: var(--r-md);
  background: var(--glass-fill);
  border: 1px solid var(--glass-border);
  transition: transform 0.3s var(--ease), background 0.3s var(--ease);
}
.pd-related-card:hover { transform: translateY(-3px); background: var(--glass-fill-strong); }
.pd-related-thumb {
  flex-shrink: 0;
  width: 42px;
  height: 42px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, var(--navy-700), var(--navy-500));
  color: var(--gold-400);
  font-size: 1.05rem;
}
.pd-related-card b { display: block; font-size: 0.92rem; color: var(--ink); }
.pd-related-card span { display: block; font-size: 0.74rem; color: var(--ink-faint); margin-top: 2px; }

/* ---------- 7. Colonne latérale (infos + actions) ---------- */
.pd-side { display: flex; flex-direction: column; gap: 22px; }
@media (min-width: 981px) {
  .pd-side { position: sticky; top: calc(var(--header-h, 86px) + 28px); }
}
.pd-info-card { padding: 30px; }
.pd-badge {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--f-mono);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 6px 13px;
  border-radius: var(--r-pill);
  background: var(--gold-500);
  color: var(--navy-900);
  margin-bottom: 20px;
}
.pd-info-row { display: flex; align-items: flex-start; gap: 12px; padding: 12px 0; border-top: 1px solid var(--line, rgba(11,42,107,.08)); }
.pd-info-row:first-of-type { border-top: none; padding-top: 0; }
.pd-info-row i { color: var(--gold-600); font-size: 1rem; margin-top: 2px; flex-shrink: 0; }
.pd-info-row div span {
  display: block;
  font-family: var(--f-mono);
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 3px;
}
.pd-info-row div b { font-size: 0.92rem; color: var(--ink); line-height: 1.35; }
.pd-info-card .pmodal-actions { margin-top: 24px; flex-direction: column; align-items: stretch; }
.pd-info-card .pmodal-actions .btn { width: 100%; }
.pd-info-card .pmodal-note { margin-top: 16px; text-align: center; }

/* ---------- 8. Pagination projet précédent / suivant ---------- */
.pd-pager {
  margin-top: 56px;
  padding: 18px 26px;
}
.pd-pager .pmodal-foot-nav { margin-top: 0; }
.pd-pager .pmodal-nav-btn { font-size: 0.86rem; padding: 10px 18px; }
.pd-pager .pmodal-nav-btn b { color: inherit; }
.pd-pager-mid {
  font-family: var(--f-mono);
  font-size: 0.7rem;
  color: var(--ink-faint);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  white-space: nowrap;
}
@media (max-width: 560px) {
  .pd-pager-mid { display: none; }
}

/* refonte.css */
/* ===========================================================
   CyNoLux — Refonte (v5)
   Chargée APRÈS finitions.css. Dernière couche du système.

   Rôle : élever la finition sans toucher à l'identité. Le navy,
   l'or, le verre et les polices ne changent pas. Ce fichier
   corrige la hiérarchie, le contraste et le rythme, et donne au
   bandeau de chiffres le poids qu'il mérite.

   Ce fichier est additif : le supprimer rend le site à son
   état précédent, sans casse.
   =========================================================== */

/* -----------------------------------------------------------
   1. JETONS COMPLÉMENTAIRES
   Deux manques dans le système existant :
   — aucune encre secondaire qui passe AA sur --bg (--ink-faint
     tombe à 3,1:1, insuffisant pour du texte courant) ;
   — aucun réglage de chiffres tabulaires, si bien que les
     compteurs animés font danser la mise en page à chaque tick.
   ----------------------------------------------------------- */
:root {
  --ink-soft: #3c4a6b;          /* 7,4:1 sur --bg — texte courant */
  --ink-quiet: #5a678a;         /* 4,9:1 — métadonnées */
  --plaque: #ffffff;
  --plaque-rule: rgba(11, 42, 107, 0.1);
  --figure-ink: var(--navy-700);
  --lift: 0 24px 60px -32px rgba(11, 42, 107, 0.5);
  --lift-soft: 0 12px 34px -22px rgba(11, 42, 107, 0.4);
}
[data-theme="dark"] {
  --ink-soft: #c2cfe8;
  --ink-quiet: #94a6c8;
  --plaque: #08132b;
  --plaque-rule: rgba(255, 255, 255, 0.11);
  --figure-ink: #f2f6ff;
  --lift: 0 24px 60px -30px rgba(0, 0, 0, 0.8);
  --lift-soft: 0 12px 34px -20px rgba(0, 0, 0, 0.65);
}

/* Les chiffres ne changent plus de largeur pendant qu'ils défilent. */
.counter,
.stat-chip strong,
.pack-price,
.kpi-value,
.hs-count,
.breadcrumb,
time {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* -----------------------------------------------------------
   2. LA PLAQUE DE CHIFFRES
   C'est le seul endroit où ce fichier hausse la voix.

   Avant : quatre nombres de 1,7 rem dans un bandeau de 110 px,
   à peine plus gros que leur propre légende. Un chiffre clé
   qui ne se voit pas ne prouve rien.

   Après : le chiffre devient l'objet graphique. Space Grotesk,
   chasse tabulaire, filets de séparation à un pixel, et un
   unique trait d'or sur l'arête haute — la seule fioriture.
   ----------------------------------------------------------- */
.proof-band {
  padding: 0;
  margin-top: -46px;              /* chevauche le bas du hero */
  position: relative;
  z-index: 6;
}
@media (max-width: 900px) {
  .proof-band { margin-top: -30px; }
}
/* Le chevauchement reste sous les 64 px de marge basse du hero :
   la pagination « 01 / 05 » et les flèches gardent leur place. */

.proof-band .proof-panel,
[data-theme="dark"] .proof-band .proof-panel {
  background: var(--plaque);
  border: 1px solid var(--plaque-rule);
  border-radius: var(--r-lg);
  box-shadow: var(--lift);
  overflow: hidden;
  position: relative;
}

/* Le trait d'or : court, ancré à gauche, il signe la plaque
   sans la souligner sur toute sa longueur. */
.proof-band .proof-panel::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  top: 0;
  width: 96px;
  height: 3px;
  background: linear-gradient(90deg, var(--gold-500), var(--gold-400));
  border-start-start-radius: var(--r-lg);
}

.proof-band .proof-stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}
.proof-band .proof-stats .stat-chip {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  padding: 34px 32px 32px;
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}
.proof-band .proof-stats .stat-chip + .stat-chip {
  border-inline-start: 1px solid var(--plaque-rule);
}

.proof-band .proof-stats .stat-chip strong .counter {
  font-size: inherit;
  font-weight: inherit;
  letter-spacing: inherit;
  color: inherit;
}
.proof-band .proof-stats .stat-chip strong {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: clamp(2.5rem, 4.4vw, 3.9rem);
  line-height: 0.92;
  letter-spacing: -0.035em;
  color: var(--figure-ink);
  display: block;
}
/* Le suffixe (+ ou %) passe en or et redescend d'un cran :
   il qualifie le nombre, il ne le concurrence pas. */
.proof-band .proof-stats .stat-chip strong .counter-suffix {
  color: var(--gold-600);
  font-size: 0.52em;
  letter-spacing: 0;
  vertical-align: 0.42em;
  margin-inline-start: 0.06em;
}
[data-theme="dark"] .proof-band .proof-stats .stat-chip strong .counter-suffix {
  color: var(--gold-400);
}

.proof-band .proof-stats .stat-chip span:not(.counter):not(.counter-suffix) {
  font-size: 0.88rem;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-soft);
  max-width: 15ch;
}

@media (max-width: 900px) {
  .proof-band .proof-stats .stat-chip { padding: 26px 22px 24px; }
}
@media (max-width: 760px) {
  .proof-band .proof-stats { grid-template-columns: repeat(2, 1fr); }
  .proof-band .proof-stats .stat-chip:nth-child(3) { border-inline-start: 0; }
  .proof-band .proof-stats .stat-chip:nth-child(n + 3) {
    border-top: 1px solid var(--plaque-rule);
  }
}

/* -----------------------------------------------------------
   3. HEROS DES PAGES INTÉRIEURES
   Les titres couraient sur 1 100 px : l'œil perd la ligne
   suivante bien avant de l'atteindre. On plafonne la mesure
   autour de 18 caractères par ligne pour un affichage de cette
   taille, et on resserre la hauteur, qui laissait 400 px de
   vide sous le fil d'Ariane.
   ----------------------------------------------------------- */
.page-hero {
  min-height: 520px;
  padding-top: 96px;
  padding-bottom: 72px;
}
@media (max-width: 900px) {
  .page-hero { min-height: 440px; padding-bottom: 56px; }
}
.page-hero h1 {
  max-width: 18ch;
  margin-inline: auto;
  font-size: clamp(2.3rem, 4.6vw, 3.7rem);
  line-height: 1.06;
  text-wrap: balance;
}
.page-hero .lead,
.page-hero > .container > p {
  max-width: 58ch;
  margin-inline: auto;
  text-wrap: pretty;
}
.page-hero .breadcrumb { margin-top: 28px; }

/* Le titre d'accueil, lui, garde toute sa largeur : c'est la
   seule page où il doit occuper le terrain. */
.hero-slider .hs-slide h1,
.hero-slider .hs-slide h2 {
  max-width: 17ch;
  text-wrap: balance;
}
.hero-slider .hs-slide .lead { max-width: 52ch; }

@media (max-width: 760px) {
  .hero-slider .hs-slide h1,
  .hero-slider .hs-slide h2 {
    font-size: clamp(2rem, 8.2vw, 2.6rem);
    max-width: none;
  }
  .hero-slider .hs-slide .lead { font-size: 0.95rem; }
}

/* -----------------------------------------------------------
   4. CONTRASTE DU TEXTE COURANT
   --ink-faint servait à la fois de couleur décorative et de
   couleur de lecture. On le laisse aux ornements et on bascule
   tout ce qui se lit vraiment sur --ink-soft / --ink-quiet.
   ----------------------------------------------------------- */
.why-mini p,
.why-card p,
.feature-card p,
.mini-card p,
.cnx-articles__excerpt,
.timeline-step p,
.svc-card p,
.card p {
  color: var(--ink-soft);
}
.cnx-articles__meta,
.testi-role,
.proj-kind,
.breadcrumb {
  color: var(--ink-quiet);
}

/* Les commandes de navigation du bloc « pourquoi nous » étaient
   grises sur blanc : on ne voyait pas qu'elles étaient cliquables. */
.cnx-why-us .stack-prev,
.cnx-why-us .stack-next,
.cnx-why-us [class*="prev"],
.cnx-why-us [class*="next"] {
  color: var(--navy-700);
  font-weight: 700;
}
[data-theme="dark"] .cnx-why-us .stack-prev,
[data-theme="dark"] .cnx-why-us .stack-next,
[data-theme="dark"] .cnx-why-us [class*="prev"],
[data-theme="dark"] .cnx-why-us [class*="next"] {
  color: var(--gold-300);
}

/* -----------------------------------------------------------
   5. BOUTON FANTÔME SUR FOND SOMBRE
   « Explorer nos services » et « Estimer mon budget » posaient
   du bleu-gris translucide sur du navy : le libellé disparaît.
   Sur fond sombre, le fantôme devient un contour net.
   ----------------------------------------------------------- */
.hero-slider .btn-ghost,
.cta-dark .btn-ghost,
.cta-panel .btn-ghost,
[class*="cta"] .btn-ghost,
.page-hero.has-media .btn-ghost,
section[style*="navy"] .btn-ghost {
  background: rgba(255, 255, 255, 0.07);
  border: 1.5px solid rgba(255, 255, 255, 0.46);
  color: #fff;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.hero-slider .btn-ghost:hover,
.cta-dark .btn-ghost:hover,
.cta-panel .btn-ghost:hover,
[class*="cta"] .btn-ghost:hover,
.page-hero.has-media .btn-ghost:hover,
section[style*="navy"] .btn-ghost:hover {
  background: rgba(255, 255, 255, 0.15);
  border-color: #fff;
  color: #fff;
}

/* Le texte d'accompagnement du dernier appel à l'action tombait à
   3,2:1 sur le navy. */
.cta-band p { color: rgba(255, 255, 255, 0.84); }
.cta-band h2 { color: #fff; }

/* -----------------------------------------------------------
   6. BANDEAU TECHNOLOGIQUE
   Les dégradés de bord ne masquaient pas vraiment : les libellés
   se coupaient net à gauche. Un masque alpha règle le problème
   quel que soit le fond, et le défilement s'arrête au survol
   pour qu'on puisse lire.
   ----------------------------------------------------------- */
.stack-marquee-wrap {
  padding: 30px 0;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
}
.stack-marquee-wrap::before,
.stack-marquee-wrap::after { content: none; }
.stack-marquee-wrap:hover .stack-track,
.stack-marquee-wrap:focus-within .stack-track {
  animation-play-state: paused;
}
.stack-item {
  color: rgba(255, 255, 255, 0.66);
  letter-spacing: 0.01em;
}
@media (prefers-reduced-motion: reduce) {
  .stack-track { animation: none; }
  .stack-marquee-wrap {
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-mask-image: none;
    mask-image: none;
  }
  .stack-marquee-wrap::-webkit-scrollbar { display: none; }
}

/* -----------------------------------------------------------
   7. BOUTONS FLOTTANTS
   Sur mobile, finitions.css range volontairement WhatsApp et la
   palette de commandes en ligne, tout en bas — la hauteur d'écran
   y est la ressource rare. Mais « retour en haut » restait, lui,
   à 26 px du bord : il retombait pile sur cette ligne. Les trois
   boutons forment désormais une seule rangée.
   ----------------------------------------------------------- */
.lab-fab {
  right: 22px;
  bottom: 88px;
  gap: 12px;
  align-items: center;
}
.lab-fab button,
.lab-fab a {
  width: 50px;
  height: 50px;
  box-shadow: var(--lift-soft);
}
.back-to-top {
  right: 22px;
  bottom: 26px;
  width: 50px;
  height: 50px;
}
@media (max-width: 760px) {
  .lab-fab button,
  .lab-fab a { width: 44px; height: 44px; }
  /* 14 (marge) + 44 + 8 + 44 + 8 : la troisième place de la rangée. */
  .back-to-top {
    right: 118px;
    bottom: 14px;
    width: 44px;
    height: 44px;
  }
  /* Il s'efface avec les deux autres au défilement vers le bas. */
  body.scrolling-down .back-to-top {
    transform: translateY(140%);
    opacity: 0;
    pointer-events: none;
  }
}

/* -----------------------------------------------------------
   8. CARTES D'ARTICLES
   La date et l'auteur se cassaient sur deux lignes, et une
   catégorie longue (« Intelligence Artificielle ») venait
   percuter le badge « À la une ».
   ----------------------------------------------------------- */
.cnx-articles__badges {
  align-items: flex-start;
  gap: 10px;
}
.cnx-articles__badge {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 60%;
  line-height: 1.4;
}
.cnx-articles__badge--accent { max-width: none; flex: none; }

.cnx-articles__meta {
  flex-wrap: wrap;
  row-gap: 4px;
  column-gap: 14px;
  font-size: 0.7rem;
}
.cnx-articles__meta span { white-space: nowrap; }

.cnx-articles__title {
  font-size: 1.08rem;
  text-wrap: balance;
  min-height: 2.7em;   /* aligne les résumés d'une carte à l'autre */
}
.cnx-articles__excerpt { font-size: 0.87rem; line-height: 1.6; }

/* La superposition au survol recouvrait la carte entière, titre
   compris, et rejouait la même information. Elle s'efface. */
.cnx-articles__overlay { display: none; }

/* -----------------------------------------------------------
   9. TÉMOIGNAGES
   Le nom et la fonction se serraient sur deux lignes collées.
   ----------------------------------------------------------- */
.testi-meta,
.testi-author {
  gap: 14px;
  align-items: center;
}
.testi-author strong,
.testi-name {
  display: block;
  line-height: 1.3;
  margin-bottom: 3px;
}
.testi-role,
.testi-author span {
  display: block;
  font-size: 0.76rem;
  line-height: 1.45;
  color: var(--ink-quiet);
}

/* -----------------------------------------------------------
   10. LE SCEAU CIRCULAIRE
   Le même médaillon « CYNOLUX · CYBER · NOVATION · LUXURY »
   revenait dans six sections de la page d'accueil. Un motif
   qu'on croise six fois n'est plus une signature, c'est un
   fond d'écran. On le garde une section sur deux.
   ----------------------------------------------------------- */
.wm-seal-wrap { opacity: 0.55; }
section[data-seal] ~ section[data-seal] .wm-seal-wrap { display: none; }
section[data-seal] ~ section[data-seal] ~ section[data-seal] .wm-seal-wrap {
  display: block;
}
section[data-seal] ~ section[data-seal] ~ section[data-seal] ~ section[data-seal] .wm-seal-wrap {
  display: none;
}

/* -----------------------------------------------------------
   10 bis. CORRECTIFS DE THÈME SOMBRE
   ----------------------------------------------------------- */

/* La FAQ de la page contact n'avait jamais reçu sa variante sombre :
   `.faq-q` restait en --navy-800, c'est-à-dire du bleu nuit posé sur
   du bleu nuit. Les quatre questions étaient invisibles. */
[data-theme="dark"] .faq-q { color: var(--ink); }
[data-theme="dark"] .faq-q i { color: var(--gold-400); }
[data-theme="dark"] .faq-item { border-bottom-color: rgba(255, 255, 255, 0.12); }
[data-theme="dark"] .faq-a p { color: var(--ink-soft); }

/* L'or foncé sur fond clair tombe à 3,6:1 : sous le seuil pour du
   texte de 11 px. On le fonce, et la note repasse en encre lisible. */
.est-label { color: #8d5c05; }
.est-note { color: var(--ink-soft); }
[data-theme="dark"] .est-label { color: var(--gold-300); }

/* -----------------------------------------------------------
   11. RYTHME DES SECTIONS
   120 px partout donnait le même silence entre deux idées liées
   et entre deux chapitres. On resserre légèrement et on laisse
   respirer les bascules de fond.
   ----------------------------------------------------------- */
section { padding: 104px 0; }
section[style*="background"] + section[style*="background"] { padding-top: 104px; }
@media (max-width: 900px) { section { padding: 72px 0; } }

.section-head { margin-bottom: 56px; }
.section-head h2 {
  max-width: 20ch;
  text-wrap: balance;
}
.section-head.center h2 { margin-inline: auto; }
.section-head p {
  max-width: 62ch;
  text-wrap: pretty;
  color: var(--ink-soft);
}
.section-head.center p { margin-inline: auto; }

/* -----------------------------------------------------------
   12. CARTES : UNE SEULE GRAMMAIRE
   Toutes les cartes montaient de 6 px au survol, avec la même
   ombre. Le mouvement est réservé à ce qui mène ailleurs — les
   projets, les articles, les liens. Les cartes de contenu se
   contentent d'un filet qui s'affirme.
   ----------------------------------------------------------- */
.card:not(a):hover,
.svc-card:not(a):hover,
.why-mini:hover,
.feature-card:not(a):hover {
  transform: none;
  border-color: rgba(11, 42, 107, 0.22);
  box-shadow: var(--lift-soft);
}
[data-theme="dark"] .card:not(a):hover,
[data-theme="dark"] .svc-card:not(a):hover,
[data-theme="dark"] .why-mini:hover,
[data-theme="dark"] .feature-card:not(a):hover {
  border-color: rgba(255, 255, 255, 0.24);
}
a.card:hover,
.cnx-articles__card:hover,
.proj-card:hover {
  transform: translateY(-5px);
  box-shadow: var(--lift);
}

/* -----------------------------------------------------------
   13. EN-TÊTE
   Le « Lux » doré tombait à 2,6:1 sur le verre clair du hero.
   On le remonte et on épaissit très légèrement la barre.
   ----------------------------------------------------------- */
.brand-word span { color: var(--gold-500); }
.site-header .brand-word span { text-shadow: 0 1px 2px rgba(7, 25, 56, 0.35); }
[data-theme="dark"] .brand-word span,
.page-hero.has-media ~ * .brand-word span { color: var(--gold-400); }

.header-inner { box-shadow: var(--lift-soft); }
.nav-menu a { font-weight: 600; }
.nav-menu a.active { font-weight: 700; }

/* -----------------------------------------------------------
   14. SOCLE DE QUALITÉ
   ----------------------------------------------------------- */
/* Le focus clavier doit rester visible même sur fond or. */
:focus-visible {
  outline: 3px solid var(--gold-500);
  outline-offset: 3px;
}
.btn-primary:focus-visible {
  outline-color: var(--navy-800);
  outline-offset: 4px;
}
[data-theme="dark"] .btn-primary:focus-visible { outline-color: #fff; }

/* Le lien d'évitement est stylé dans lab.css ; on n'ajoute que
   l'adoucissement de son apparition. */
.skip-link { transition: left 0.18s var(--ease); }

/* Césure propre du français dans les colonnes étroites. */
p, li { hyphens: auto; -webkit-hyphens: auto; }
h1, h2, h3, h4, .btn { hyphens: none; -webkit-hyphens: none; }

/* Les images sans dimensions déclarées réservent leur place. */
.cnx-articles__image,
.proj-media,
.svc-media { background: var(--bg-deep); }

@media (prefers-reduced-motion: reduce) {
  a.card:hover,
  .cnx-articles__card:hover,
  .proj-card:hover { transform: none; }
}

/* portfolio.css */
/* ===========================================================
   CyNoLux — Portfolio (v5)
   Chargée après refonte.css, uniquement sur /portfolio et les
   pages projet.

   Deux partis pris :

   1. Les vignettes n'ont plus de photo générique : le fond est
      peint (dégradé navy/or) et porté par des icônes propres à
      chaque projet — deux icônes « fantômes » en coin plus un
      écho agrandi du badge — pendant qu'un emplacement dédié
      attend le vrai logo de l'application au centre.

   2. Les animations servent la lecture, jamais le spectacle.
      Elles indiquent ce qui est cliquable, ce qui vient
      d'arriver, ce qui a changé — et disparaissent toutes si
      le visiteur a demandé moins de mouvement.
   =========================================================== */

/* -----------------------------------------------------------
   1. LA GRILLE DE PROJETS
   ----------------------------------------------------------- */

.project-card {
  position: relative;
  isolation: isolate;
  border: 1px solid var(--line);
  transition:
    transform 0.5s cubic-bezier(0.16, 1, 0.3, 1),
    box-shadow 0.5s cubic-bezier(0.16, 1, 0.3, 1),
    border-color 0.4s var(--ease);
}

/* Vignette : hauteur portante, et non plus une bande de 170 px.
   Le fond est peint, pas photographié. L'angle du dégradé et la
   position du halo doré varient avec l'index de la carte : la
   planche respire sans jamais sortir de la palette. */
.project-thumb {
  height: 210px;
  background:
    radial-gradient(
      circle at calc(26% + var(--i, 0) * 4%) -12%,
      rgba(253, 185, 19, 0.22),
      transparent 52%
    ),
    linear-gradient(
      calc(130deg + var(--i, 0) * 5deg),
      var(--navy-800),
      var(--navy-600) 62%,
      var(--navy-500)
    );
}

/* Fond thématique : chaque vignette porte trois icônes « fantômes »
   propres au projet (deux au choix libre + un écho agrandi du badge)
   plutôt que l'une des trois photos génériques d'origine. Le fond
   dit ce que fait le produit avant même la lecture du texte.
   Chacune dérive doucement en boucle ; le déphasage négatif basé
   sur --i évite que les trente-trois cartes respirent en même
   temps quand la grille apparaît à l'écran. */
.project-ghost {
  position: absolute;
  z-index: 1;
  color: rgba(255, 255, 255, 0.17);
  line-height: 1;
  pointer-events: none;
  transition: opacity 0.4s var(--ease), animation-duration 0.4s var(--ease);
}
.project-ghost-1 {
  top: 2px;
  left: 6px;
  font-size: 5rem;
  animation: ghost-drift-1 7s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * -0.9s);
}
.project-ghost-2 {
  top: -18px;
  right: -14px;
  font-size: 5.4rem;
  animation: ghost-drift-2 8.5s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * -1.1s);
}
.project-ghost-3 {
  bottom: -34px;
  right: -20px;
  font-size: 8.4rem;
  color: rgba(255, 255, 255, 0.1);
  animation: ghost-pulse-3 9s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * -1.3s);
}
@keyframes ghost-drift-1 {
  0%, 100% { transform: translate(0, 0) rotate(0deg); }
  50% { transform: translate(4px, -10px) rotate(-4deg); }
}
@keyframes ghost-drift-2 {
  0%, 100% { transform: rotate(-7deg) translateY(0); }
  50% { transform: rotate(-2deg) translateY(10px); }
}
@keyframes ghost-pulse-3 {
  0%, 100% { transform: scale(1) rotate(0deg); }
  50% { transform: scale(1.09) rotate(3deg); }
}
.project-card:hover .project-ghost { opacity: 0.9; animation-duration: 3s; }

/* Badge d'icône : coin haut-gauche de la vignette. Identifie le
   produit avant même que le logo ne soit posé au centre. */
.project-badge {
  position: absolute;
  top: 18px;
  left: 20px;
  z-index: 3;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: var(--r-sm);
  border: 1px solid rgba(255, 255, 255, 0.22);
  background: rgba(6, 17, 40, 0.52);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: var(--gold-400);
  font-size: 1.05rem;
  transition:
    transform 0.5s cubic-bezier(0.16, 1, 0.3, 1),
    border-color 0.4s var(--ease),
    background 0.4s var(--ease);
}
.project-card:hover .project-badge {
  transform: translateY(-3px);
  border-color: rgba(253, 185, 19, 0.6);
  background: rgba(6, 17, 40, 0.68);
}

/* Emplacement du logo : réservé au centre de la vignette, en
   attente de l'import du visuel réel de chaque application.
   Tant qu'aucune image ne charge (404 volontaire), l'icône
   bootstrap sert de repère visuel discret plutôt que de casser
   la carte avec l'icône « image cassée » du navigateur. */
.project-logo {
  position: absolute;
  top: 46%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 2;
  width: 104px;
  height: 104px;
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.011);
  border: 1px solid rgba(255, 255, 255, 0.032);
  display: grid;
  place-items: center;
  overflow: hidden;
}
.project-logo img {
  /* lab.css pose un ancien réglage `.project-thumb img { position:absolute;
     inset:0; width:100%; height:100% }` pensé pour une photo plein cadre.
     On le neutralise explicitement ici pour que le logo reste centré et
     à taille contenue dans son emplacement, quel que soit l'ordre de
     chargement des feuilles de style. */
  position: relative;
  inset: auto;
  width: 95%;
  height: 95%;
  object-fit: contain;
  transform: none;
}
.project-logo.is-empty img { display: none; }
.project-logo.is-empty::after {
  content: "\f42a"; /* bi-image */
  font-family: "bootstrap-icons";
  font-size: 2.1rem;
  color: rgba(255, 255, 255, 0.32);
}

/* Trame technique par-dessus : supprimée — les icônes fantômes
   suffisent à porter le fond, la grille technique alourdissait
   inutilement la planche. */

/* Le monogramme devient l'élément d'identité : c'est lui qui
   distingue SamaRH de SamaPaie, pas la photo. */
.project-thumb span {
  position: absolute;
  left: 20px;
  bottom: 18px;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding: 8px 18px;
  border-radius: var(--r-pill);
  border: 1px solid rgba(255, 255, 255, 0.22);
  background: rgba(6, 17, 40, 0.52);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  font-family: var(--f-display);
  font-weight: 700;
  font-size: 1.12rem;
  letter-spacing: -0.01em;
  color: #fff;
  opacity: 1;
  transition:
    transform 0.5s cubic-bezier(0.16, 1, 0.3, 1),
    border-color 0.4s var(--ease),
    background 0.4s var(--ease);
}
.project-card:hover .project-thumb span {
  transform: translateY(-3px);
  border-color: rgba(253, 185, 19, 0.6);
  background: rgba(6, 17, 40, 0.68);
}

/* Une flèche apparaît au survol : le signal que la carte mène
   quelque part. Elle n'existe pas au repos, pour ne pas répéter
   trente-deux fois la même icône sur la planche. */
.project-thumb::after {
  content: "\f138"; /* bi-arrow-right-circle-fill */
  font-family: "bootstrap-icons";
  position: absolute;
  z-index: 3;
  inset: auto 18px 18px auto;
  width: auto;
  height: auto;
  display: grid;
  place-items: center;
  font-size: 1.5rem;
  color: var(--gold-400);
  background: none;
  opacity: 0;
  transform: translateX(-8px) scale(0.8);
  transition:
    opacity 0.4s var(--ease),
    transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}
.project-card:hover .project-thumb::after {
  opacity: 1;
  transform: translateX(0) scale(1);
}

.project-body { padding: 24px 24px 26px; }
.project-cat {
  display: inline-block;
  font-size: 0.68rem;
  color: var(--gold-700);
}
[data-theme="dark"] .project-cat { color: var(--gold-400); }

.project-body h3 {
  margin: 8px 0 8px;
  font-size: 1.22rem;
  transition: color 0.3s var(--ease);
}
.project-card:hover .project-body h3 { color: var(--navy-600); }
[data-theme="dark"] .project-card:hover .project-body h3 { color: var(--gold-300); }

/* Le résumé tient en quatre lignes : toutes les cartes s'alignent,
   et le texte long ne fait pas éclater la grille. */
.project-body p {
  font-size: 0.89rem;
  line-height: 1.6;
  color: var(--ink-soft);
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.project-client {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--line-soft);
  font-size: 0.78rem;
  color: var(--ink-quiet);
}
.project-client i { color: var(--gold-600); }

/* -----------------------------------------------------------
   2. ARRIVÉE ET FILTRAGE
   L'apparition est décalée de proche en proche pour que l'œil
   suive la grille au lieu de la recevoir d'un bloc.
   ----------------------------------------------------------- */
.grid .project-card { transition-delay: calc(var(--i, 0) * 45ms); }

.project-card.is-filtering {
  opacity: 0;
  transform: scale(0.96) translateY(8px);
}
.project-card {
  transition-property: transform, box-shadow, border-color, opacity;
}

/* Les boutons de filtre : l'état actif se lit d'abord, et le
   survol annonce le clic. */
.portfolio-filters { gap: 10px; flex-wrap: wrap; }
.filter-btn {
  position: relative;
  transition:
    background 0.35s var(--ease),
    color 0.35s var(--ease),
    border-color 0.35s var(--ease),
    transform 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}
.filter-btn:hover { transform: translateY(-2px); }
.filter-btn.active::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -9px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--gold-500);
  transform: translateX(-50%);
}

/* -----------------------------------------------------------
   3. EN-TÊTE DE LA PAGE PORTFOLIO
   L'intro et l'astuce de clic flottaient, centrées, sans
   structure. On leur donne la même grammaire que les autres
   sections du site.
   ----------------------------------------------------------- */
.portfolio-intro {
  max-width: 60ch;
  margin: 0 auto 10px;
  text-align: center;
  color: var(--ink-soft);
  text-wrap: pretty;
}
.portfolio-hint {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin: 0 auto 30px;
  font-family: var(--f-mono);
  font-size: 0.76rem;
  color: var(--ink-quiet);
}
.portfolio-hint i { color: var(--gold-600); }

/* -----------------------------------------------------------
   4. PAGES PROJET — LE VISUEL D'EN-TÊTE
   La fausse fenêtre de navigateur ne contenait qu'une icône et
   un mot posés au centre. On en fait une scène : halo animé,
   trame en perspective, monogramme qui respire.
   ----------------------------------------------------------- */
.pd-visual {
  border: 1px solid var(--line);
  box-shadow: var(--lift);
  overflow: hidden;
}
.pd-visual-stage {
  position: relative;
  min-height: 300px;
  background:
    radial-gradient(circle at 50% 120%, rgba(253, 185, 19, 0.16), transparent 62%),
    linear-gradient(150deg, var(--navy-800), var(--navy-600) 65%, var(--navy-500));
  overflow: hidden;
}
/* Trame en fuite : donne de la profondeur sans image. */
.pd-visual-stage::before {
  content: "";
  position: absolute;
  inset: -40% -20% -10%;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.07) 1px, transparent 1px);
  background-size: 46px 46px;
  transform: perspective(600px) rotateX(58deg);
  transform-origin: 50% 100%;
  mask-image: linear-gradient(to top, #000, transparent 72%);
  -webkit-mask-image: linear-gradient(to top, #000, transparent 72%);
  pointer-events: none;
}
.pd-visual-glow { animation: pd-breathe 7s ease-in-out infinite; }
@keyframes pd-breathe {
  0%, 100% { opacity: 0.55; transform: scale(1); }
  50% { opacity: 0.9; transform: scale(1.1); }
}
.pd-visual-icon {
  position: relative;
  z-index: 2;
  border: 1px solid rgba(253, 185, 19, 0.32);
  box-shadow: 0 18px 44px -20px rgba(0, 0, 0, 0.7);
  animation: pd-float 6s ease-in-out infinite;
}
@keyframes pd-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-9px); }
}
.pd-visual-word {
  position: relative;
  z-index: 2;
  font-size: clamp(1.8rem, 3.4vw, 2.6rem);
  letter-spacing: -0.03em;
}
/* Un filet doré signe le bas de la scène, comme sur la plaque
   de chiffres de l'accueil. Même geste, même famille. */
.pd-visual-stage::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 110px;
  height: 3px;
  background: linear-gradient(90deg, var(--gold-500), transparent);
}

/* -----------------------------------------------------------
   5. PAGES PROJET — LE BLOC « CE QUE ÇA CHANGE »
   Nouveau. Il répond à la question qu'un visiteur se pose
   vraiment devant une réalisation : et pour moi, ça donne quoi ?
   ----------------------------------------------------------- */
.pd-impact {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 2px;
  border-radius: var(--r-md);
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--line-soft);
}
.pd-impact-item {
  display: flex;
  align-items: flex-start;
  gap: 15px;
  padding: 19px 22px;
  background: var(--surface, #fff);
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--ink);
  transition: background 0.35s var(--ease), padding-inline-start 0.35s var(--ease);
}
[data-theme="dark"] .pd-impact-item { background: var(--plaque); }
.pd-impact-item:hover {
  background: var(--bg-soft);
  padding-inline-start: 28px;
}
[data-theme="dark"] .pd-impact-item:hover { background: rgba(255, 255, 255, 0.04); }

/* Une barre dorée verticale plutôt qu'une énième coche : les
   fonctionnalités juste en dessous en sont déjà couvertes. */
.pd-impact-mark {
  flex: none;
  width: 3px;
  align-self: stretch;
  min-height: 22px;
  margin-top: 2px;
  border-radius: 2px;
  background: linear-gradient(var(--gold-500), var(--gold-400));
}

/* -----------------------------------------------------------
   6. PAGES PROJET — FONCTIONNALITÉS ET DIVERS
   ----------------------------------------------------------- */
.pd-feature {
  transition:
    transform 0.4s cubic-bezier(0.16, 1, 0.3, 1),
    border-color 0.35s var(--ease);
}
.pd-feature:hover {
  transform: translateY(-3px);
  border-color: rgba(253, 185, 19, 0.45);
}
.pd-feature-icon { transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1); }
.pd-feature:hover .pd-feature-icon { transform: scale(1.14) rotate(-8deg); }

.pd-lead {
  font-size: 1.02rem;
  line-height: 1.72;
  color: var(--ink-soft);
  text-wrap: pretty;
}
.pd-lead strong { color: var(--ink); font-weight: 700; }

.pmodal-pill { transition: transform 0.35s var(--ease), border-color 0.35s var(--ease); }
.pmodal-pill:hover { transform: translateY(-2px); border-color: rgba(253, 185, 19, 0.5); }

.pd-related-card {
  transition:
    transform 0.45s cubic-bezier(0.16, 1, 0.3, 1),
    box-shadow 0.45s var(--ease),
    border-color 0.35s var(--ease);
}
.pd-related-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--lift-soft);
  border-color: rgba(253, 185, 19, 0.42);
}
.pd-related-card .pd-related-thumb {
  transition: transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
  display: grid;
  place-items: center;
}
/* L'icône était posée en navy sur une pastille navy : on ne
   voyait qu'un carré bleu vide. */
.pd-related-card .pd-related-thumb i { color: var(--gold-400); font-size: 1.05rem; }
.pd-related-card:hover .pd-related-thumb { transform: scale(1.1); }

/* Le lien de retour annonce son geste. */
.detail-back i { transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1); }
.detail-back:hover i { transform: translateX(-5px); }

/* Pagination bas de page : la flèche accompagne le sens. */
.pmodal-nav-btn { transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1); }
.pmodal-nav-btn:first-child:hover { transform: translateX(-5px); }
.pmodal-nav-btn:last-child:hover { transform: translateX(5px); }

/* Le chapeau du hero tombait à 2,5:1 sur le navy. */
.page-hero.has-media > .container > p { color: rgba(255, 255, 255, 0.88); }
.hero-meta-chip { color: rgba(255, 255, 255, 0.92); }

/* La carte latérale suit la lecture sur grand écran. */
@media (min-width: 1100px) {
  .pd-side .pd-info-card {
    position: sticky;
    top: 112px;
  }
}

/* -----------------------------------------------------------
   7. MOINS DE MOUVEMENT SI ON L'A DEMANDÉ
   ----------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .pd-visual-glow,
  .pd-visual-icon { animation: none; }
  .grid .project-card { transition-delay: 0ms !important; }
  .project-card:hover,
  .pd-feature:hover,
  .pd-related-card:hover,
  .filter-btn:hover,
  .pmodal-nav-btn:hover { transform: none; }
  .project-card:hover .project-thumb img { transform: none; }
  .project-ghost { animation: none; }
}

/* -----------------------------------------------------------
   8. ASSISTANT DE CHOIX PRODUIT
   Trente-deux cartes, c'est beaucoup à comparer soi-même. Le
   bouton sous les filtres ouvre une petite modale qui demande
   le besoin en une phrase et renvoie vers les projets les plus
   proches — même grammaire visuelle que la palette Ctrl+K.
   ----------------------------------------------------------- */
.pf-trigger-row {
  display: flex;
  justify-content: center;
  margin: -6px 0 30px;
}

/* Jumeau flottant du bouton d'aide, posé dans la pile .lab-fab :
   un accent doré le distingue du WhatsApp (vert) et de la recherche (neutre). */
.lab-fab .fab-help {
  background: linear-gradient(140deg, var(--gold-500), var(--gold-400));
  color: #14213a;
  border-color: transparent;
  box-shadow: 0 12px 26px -10px rgba(253, 185, 19, 0.55);
}

.pf-modal {
  position: fixed;
  inset: 0;
  z-index: 320;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(6, 16, 38, 0.5);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.pf-modal.is-open {
  display: flex;
  animation: cmdk-fade 0.2s var(--ease);
}
.pf-panel {
  width: 100%;
  max-width: 540px;
  max-height: 86vh;
  overflow-y: auto;
  border-radius: 22px;
  padding: 40px 34px 32px;
  position: relative;
  text-align: center;
  background: var(--glass-fill-strong);
  border: 1px solid var(--glass-border);
  backdrop-filter: blur(30px) saturate(170%);
  -webkit-backdrop-filter: blur(30px) saturate(170%);
  box-shadow: 0 40px 90px -30px rgba(7, 25, 56, 0.6);
  animation: cmdk-pop 0.28s var(--ease-out);
}
[data-theme="dark"] .pf-panel { background: rgba(12, 26, 54, 0.94); }

.pf-close {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--line-soft);
  color: var(--ink-quiet);
  transition: background 0.25s var(--ease), color 0.25s var(--ease);
}
.pf-close:hover { background: var(--gold-500); color: #14213a; }

.pf-icon {
  width: 52px;
  height: 52px;
  margin: 0 auto 18px;
  display: grid;
  place-items: center;
  border-radius: 16px;
  background: linear-gradient(140deg, var(--gold-500), var(--gold-400));
  color: #14213a;
  font-size: 1.3rem;
}
.pf-step h3 { font-size: 1.2rem; margin-bottom: 8px; }
.pf-step > p { color: var(--ink-soft); font-size: 0.92rem; line-height: 1.6; margin-bottom: 22px; }

.pf-form {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: center;
}
.pf-input {
  flex: 1;
  min-width: 220px;
  padding: 13px 18px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--surface, #fff);
  font-size: 0.92rem;
  color: var(--ink);
  outline: none;
  transition: border-color 0.25s var(--ease);
}
.pf-input:focus { border-color: var(--gold-500); }
[data-theme="dark"] .pf-input { background: rgba(255, 255, 255, 0.06); }

.pf-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
  margin-top: 20px;
}
.pf-chip {
  padding: 7px 15px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--line-soft);
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--ink-muted);
  transition: transform 0.25s var(--ease), border-color 0.25s var(--ease), background 0.25s var(--ease);
}
.pf-chip:hover {
  transform: translateY(-2px);
  border-color: rgba(253, 185, 19, 0.55);
  background: rgba(253, 185, 19, 0.12);
}

.pf-back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0 auto 18px;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--ink-quiet);
  transition: color 0.25s var(--ease);
}
.pf-back:hover { color: var(--gold-600); }
.pf-results-title { font-size: 1.05rem; margin-bottom: 16px; }

.pf-results-list { display: grid; gap: 8px; }
.pf-result {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 13px 16px;
  border-radius: 14px;
  border: 1px solid var(--line);
  text-align: left;
  transition: transform 0.25s var(--ease), border-color 0.25s var(--ease), background 0.25s var(--ease);
}
.pf-result:hover {
  transform: translateY(-2px);
  border-color: rgba(253, 185, 19, 0.5);
  background: rgba(253, 185, 19, 0.08);
}
.pf-result-mono {
  flex-shrink: 0;
  min-width: 38px;
  height: 38px;
  padding: 0 6px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  background: var(--line-soft);
  font-family: var(--f-display);
  font-weight: 700;
  font-size: 0.78rem;
  color: var(--navy-600);
}
[data-theme="dark"] .pf-result-mono { color: var(--gold-400); }
.pf-result-txt { flex: 1; min-width: 0; }
.pf-result-title { display: block; font-weight: 700; font-size: 0.94rem; color: var(--ink); }
.pf-result-cat {
  display: block;
  font-size: 0.76rem;
  color: var(--ink-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pf-result-go { color: var(--ink-faint); flex-shrink: 0; }
.pf-result-alt { border-style: dashed; }

@media (prefers-reduced-motion: reduce) {
  .pf-modal.is-open,
  .pf-panel { animation: none; }
  .pf-chip:hover,
  .pf-result:hover { transform: none; }
}

/* product.css */
/* ===========================================================
   CyNoLux — Fiches produit v2
   Chargée APRÈS project-detail.css : couche strictement additive.
   Aucune règle ici ne redéfinit les fondations (couleurs, type,
   grille) ; elle ajoute les blocs propres aux pages produit :
   affiche, chiffres, écrans, intégrations, FAQ, sommaire.
   =========================================================== */

:root {
  --pd-rule: rgba(11, 42, 107, 0.1);
  --pd-card: rgba(255, 255, 255, 0.72);
  --pd-card-hi: #ffffff;
  --pd-ink-quiet: var(--ink-quiet, #5a678a);
}
[data-theme="dark"] {
  --pd-rule: rgba(255, 255, 255, 0.12);
  --pd-card: rgba(11, 25, 56, 0.5);
  --pd-card-hi: rgba(11, 25, 56, 0.78);
}

/* -----------------------------------------------------------
   1. Hero — actions directes sous le titre
   ----------------------------------------------------------- */
.pd-hero-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
  margin-top: 26px;
}
.pd-hero-actions .btn {
  padding: 13px 26px;
  font-size: 0.92rem;
}
.pd-hero-actions .btn-ghost {
  color: #fff;
  border-color: rgba(255, 255, 255, 0.35);
  background: rgba(255, 255, 255, 0.08);
}
.pd-hero-actions .btn-ghost:hover {
  background: rgba(255, 255, 255, 0.16);
  border-color: rgba(255, 255, 255, 0.55);
}

/* -----------------------------------------------------------
   2. Sommaire collant — repère de lecture, pas décoration
   ----------------------------------------------------------- */
.pd-toc {
  position: sticky;
  top: calc(var(--header-h, 86px) + 10px);
  z-index: 5;
  display: flex;
  gap: 4px;
  overflow-x: auto;
  scrollbar-width: none;
  padding: 7px;
  margin: 0 0 34px;
  border-radius: var(--r-pill);
  background: var(--pd-card-hi);
  border: 1px solid var(--pd-rule);
  box-shadow: var(--lift-soft, 0 12px 34px -22px rgba(11, 42, 107, 0.4));
}
.pd-toc::-webkit-scrollbar { display: none; }
.pd-toc a {
  flex: 0 0 auto;
  padding: 9px 16px;
  border-radius: var(--r-pill);
  font-size: 0.84rem;
  font-weight: 600;
  color: var(--pd-ink-quiet);
  white-space: nowrap;
  transition: background 0.25s var(--ease), color 0.25s var(--ease);
}
.pd-toc a:hover { color: var(--navy-600); background: rgba(11, 42, 107, 0.06); }
.pd-toc a.is-current {
  color: var(--navy-900);
  background: var(--gold-500);
}
[data-theme="dark"] .pd-toc a:hover { color: #fff; background: rgba(255, 255, 255, 0.08); }
[data-theme="dark"] .pd-toc a.is-current { color: var(--navy-900); }
@media (max-width: 640px) {
  .pd-toc { margin-bottom: 26px; }
  .pd-toc a { font-size: 0.8rem; padding: 8px 13px; }
}

/* Les ancres ne passent plus sous l'en-tête fixe. */
.pd-section[id],
section[id] > .container > .pd-section:first-child {
  scroll-margin-top: calc(var(--header-h, 86px) + 74px);
}

/* -----------------------------------------------------------
   3. Vitrine — l'affiche du produit, en pièce maîtresse
   ----------------------------------------------------------- */
.pd-showcase {
  display: grid;
  gap: 18px;
  margin-bottom: 44px;
}

.pd-poster {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border: 1px solid var(--pd-rule);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--navy-900);
  cursor: zoom-in;
  text-align: left;
  box-shadow: var(--lift, 0 24px 60px -32px rgba(11, 42, 107, 0.5));
}
.pd-poster img {
  width: 100%;
  height: auto;
  max-height: 520px;
  object-fit: cover;
  object-position: top center;
  transition: transform 0.6s var(--ease);
}
/* Une affiche se lit en entier : on la contient, quitte à laisser
   des bandes latérales sur les formats portrait. */
.pd-poster--contain img {
  object-fit: contain;
  background: linear-gradient(135deg, var(--navy-900), var(--navy-700));
}
@media (max-width: 640px) { .pd-poster img { max-height: 400px; } }
.pd-poster:hover img { transform: scale(1.02); }
/* Affiche seule (l'ancien zoom en fenêtre n'existe plus : modals.js supprimé) : pas de curseur loupe ni de survol. */
.pd-poster--static { cursor: default; }
.pd-poster--static:hover img { transform: none; }
.pd-poster-zoom {
  position: absolute;
  right: 14px;
  bottom: 14px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 16px;
  border-radius: var(--r-pill);
  font-size: 0.8rem;
  font-weight: 700;
  color: #fff;
  background: rgba(7, 25, 56, 0.72);
  border: 1px solid rgba(255, 255, 255, 0.24);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}
.pd-poster-zoom i { color: var(--gold-400); }
@media (prefers-reduced-motion: reduce) {
  .pd-poster:hover img { transform: none; }
}

/* Panneau à droite de l'affiche : ce que le produit fait, en 4 lignes */
.pd-hl {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 24px 26px;
  border-radius: var(--r-lg);
  background: var(--pd-card);
  border: 1px solid var(--pd-rule);
}
.pd-hl h3 {
  font-size: 1.05rem;
  margin-bottom: 2px;
}
.pd-hl-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 16px 26px;
}
.pd-hl-item {
  display: flex;
  gap: 13px;
  align-items: flex-start;
}
.pd-hl-item i {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border-radius: 11px;
  font-size: 0.95rem;
  color: var(--navy-700);
  background: rgba(253, 185, 19, 0.22);
}
[data-theme="dark"] .pd-hl-item i { color: var(--gold-300); background: rgba(253, 185, 19, 0.14); }
.pd-hl-item b { display: block; font-size: 0.92rem; color: var(--ink); line-height: 1.35; }
.pd-hl-item span { display: block; font-size: 0.82rem; color: var(--pd-ink-quiet); margin-top: 2px; line-height: 1.5; }
.pd-hl-foot {
  margin-top: auto;
  padding-top: 14px;
  border-top: 1px solid var(--pd-rule);
  font-size: 0.8rem;
  color: var(--pd-ink-quiet);
}

/* -----------------------------------------------------------
   4. Chiffres clés — plaque sobre, chiffres tabulaires
   ----------------------------------------------------------- */
.pd-kpis {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--pd-card-hi);
  border: 1px solid var(--pd-rule);
  box-shadow: var(--lift-soft, 0 12px 34px -22px rgba(11, 42, 107, 0.4));
  margin-bottom: 44px;
}
.pd-kpi { padding: 24px 22px; }
.pd-kpi + .pd-kpi { border-inline-start: 1px solid var(--pd-rule); }
@media (max-width: 620px) {
  .pd-kpi:nth-child(odd) { border-inline-start: none; }
  .pd-kpi:nth-child(n + 3) { border-top: 1px solid var(--pd-rule); }
}
.pd-kpi b {
  display: block;
  font-family: var(--f-display);
  font-size: clamp(1.25rem, 2.3vw, 1.75rem);
  line-height: 1.1;
  color: var(--figure-ink, var(--navy-700));
  font-variant-numeric: tabular-nums;
}
.pd-kpi span {
  display: block;
  margin-top: 8px;
  font-size: 0.8rem;
  color: var(--pd-ink-quiet);
  line-height: 1.4;
}

/* -----------------------------------------------------------
   5. Capacités — une icône par fonction, pas une coche répétée
   ----------------------------------------------------------- */
.pd-caps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(248px, 1fr));
  gap: 14px;
  margin-top: 22px;
  list-style: none;
  padding: 0;
}
.pd-cap {
  display: flex;
  gap: 13px;
  align-items: flex-start;
  padding: 18px;
  border-radius: var(--r-md);
  background: var(--pd-card);
  border: 1px solid var(--pd-rule);
  transition: border-color 0.25s var(--ease), transform 0.25s var(--ease);
}
.pd-cap:hover { border-color: rgba(253, 185, 19, 0.6); transform: translateY(-2px); }
@media (prefers-reduced-motion: reduce) { .pd-cap:hover { transform: none; } }
.pd-cap > i {
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border-radius: 11px;
  font-size: 1rem;
  color: var(--gold-700);
  background: rgba(253, 185, 19, 0.16);
}
[data-theme="dark"] .pd-cap > i { color: var(--gold-300); }
.pd-cap b { display: block; font-size: 0.93rem; color: var(--ink); line-height: 1.4; }
.pd-cap p { margin-top: 5px; font-size: 0.84rem; line-height: 1.55; color: var(--pd-ink-quiet); }

/* -----------------------------------------------------------
   6. Écrans — onglets + cadre d'appareil
   ----------------------------------------------------------- */
.pd-screens { margin-top: 22px; }
.pd-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 18px;
}
.pd-tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  border-radius: var(--r-pill);
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--pd-ink-quiet);
  background: var(--pd-card);
  border: 1px solid var(--pd-rule);
  transition: color 0.25s var(--ease), background 0.25s var(--ease), border-color 0.25s var(--ease);
}
.pd-tab i { font-size: 0.95em; }
.pd-tab:hover { color: var(--navy-700); border-color: rgba(11, 42, 107, 0.24); }
.pd-tab[aria-selected="true"] {
  color: #fff;
  background: var(--navy-700);
  border-color: var(--navy-700);
}
.pd-tab[aria-selected="true"] i { color: var(--gold-400); }
[data-theme="dark"] .pd-tab:hover { color: #fff; }

.pd-panel[hidden] { display: none; }
.pd-panel {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.95fr);
  gap: 22px;
  align-items: center;
  padding: 24px;
  border-radius: var(--r-lg);
  background: var(--pd-card);
  border: 1px solid var(--pd-rule);
}
@media (max-width: 760px) { .pd-panel { grid-template-columns: 1fr; } }
.pd-panel h4 { font-size: 1.02rem; margin-bottom: 8px; }
.pd-panel p { font-size: 0.9rem; line-height: 1.6; }
.pd-panel ul { margin-top: 14px; display: flex; flex-direction: column; gap: 9px; }
.pd-panel li {
  position: relative;
  padding-inline-start: 20px;
  font-size: 0.87rem;
  color: var(--pd-ink-quiet);
  line-height: 1.5;
}
.pd-panel li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  top: 8px;
  width: 7px;
  height: 7px;
  border-radius: 2px;
  background: var(--gold-500);
}

/* Cadre d'appareil dessiné en CSS — aucune capture nécessaire */
.pd-device {
  position: relative;
  border-radius: 22px;
  padding: 10px;
  background: linear-gradient(150deg, var(--navy-900), var(--navy-600));
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: var(--lift, 0 24px 60px -32px rgba(11, 42, 107, 0.5));
}
.pd-device-screen {
  border-radius: 15px;
  background: #050d20;
  padding: 16px;
  min-height: 210px;
  display: flex;
  flex-direction: column;
  gap: 11px;
  overflow: hidden;
}
.pd-device-top {
  display: flex;
  align-items: center;
  gap: 9px;
  padding-bottom: 11px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.pd-device-top i { color: var(--gold-400); }
.pd-device-top b { font-size: 0.82rem; color: #fff; font-weight: 700; }
.pd-device-top span {
  margin-inline-start: auto;
  font-family: var(--f-mono);
  font-size: 0.66rem;
  color: rgba(255, 255, 255, 0.45);
}
.pd-device-rows { display: flex; flex-direction: column; gap: 8px; }
.pd-device-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 11px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.07);
}
.pd-device-row i { color: rgba(255, 255, 255, 0.5); font-size: 0.85rem; }
.pd-device-row span { font-size: 0.78rem; color: rgba(255, 255, 255, 0.8); }
.pd-device-row b {
  margin-inline-start: auto;
  font-family: var(--f-display);
  font-size: 0.82rem;
  color: var(--gold-400);
  font-variant-numeric: tabular-nums;
}
.pd-device-row.is-alert { background: rgba(253, 185, 19, 0.1); border-color: rgba(253, 185, 19, 0.3); }
.pd-device-figure {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 4px 2px 2px;
}
.pd-device-figure b {
  font-family: var(--f-display);
  font-size: clamp(1.25rem, 2.4vw, 1.6rem);
  line-height: 1.1;
  color: #fff;
  font-variant-numeric: tabular-nums;
}
.pd-device-figure span { font-size: 0.78rem; color: rgba(255, 255, 255, 0.55); }
.pd-device-bars { display: flex; align-items: flex-end; gap: 6px; height: 54px; margin-top: 2px; }
.pd-device-bars i {
  flex: 1;
  border-radius: 4px 4px 0 0;
  background: linear-gradient(180deg, var(--gold-400), rgba(253, 185, 19, 0.25));
}

/* -----------------------------------------------------------
   7. Intégrations — moyens de paiement et outils connectés
   ----------------------------------------------------------- */
.pd-integrations {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 20px;
}
.pd-int {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 11px 18px;
  border-radius: var(--r-pill);
  background: var(--pd-card-hi);
  border: 1px solid var(--pd-rule);
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ink);
}
.pd-int i { color: var(--gold-600); font-size: 1rem; }
.pd-int small {
  font-family: var(--f-mono);
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  color: var(--pd-ink-quiet);
}

/* -----------------------------------------------------------
   8. FAQ — accordéon natif <details>
   ----------------------------------------------------------- */
.pd-faq { margin-top: 20px; display: flex; flex-direction: column; gap: 10px; }
.pd-faq details {
  border-radius: var(--r-md);
  background: var(--pd-card);
  border: 1px solid var(--pd-rule);
  overflow: hidden;
}
.pd-faq summary {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 18px;
  cursor: pointer;
  font-weight: 700;
  font-size: 0.93rem;
  color: var(--ink);
  list-style: none;
}
.pd-faq summary::-webkit-details-marker { display: none; }
.pd-faq summary::after {
  content: "\F4FE"; /* bi-plus-lg */
  font-family: "bootstrap-icons";
  margin-inline-start: auto;
  font-size: 0.85rem;
  color: var(--gold-600);
  transition: transform 0.3s var(--ease);
}
.pd-faq details[open] summary::after { transform: rotate(45deg); }
.pd-faq details[open] summary { border-bottom: 1px solid var(--pd-rule); }
.pd-faq-body { padding: 16px 18px; font-size: 0.9rem; line-height: 1.65; color: var(--pd-ink-quiet); }
.pd-faq-body p + p { margin-top: 10px; }

/* -----------------------------------------------------------
   9. Tarifs — aperçu qui renvoie vers la modale
   ----------------------------------------------------------- */
.pd-price {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 20px;
  margin-top: 20px;
  padding: 24px 26px;
  border-radius: var(--r-lg);
  background: linear-gradient(135deg, var(--navy-800), var(--navy-600));
  color: #fff;
}
.pd-price-fig { flex: 1 1 260px; }
.pd-price-fig b {
  display: block;
  font-family: var(--f-display);
  font-size: clamp(1.15rem, 2.2vw, 1.55rem);
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
}
.pd-price-fig span { display: block; margin-top: 6px; font-size: 0.85rem; color: rgba(255, 255, 255, 0.72); }
.pd-price .btn-ghost {
  color: #fff;
  border-color: rgba(255, 255, 255, 0.4);
  background: rgba(255, 255, 255, 0.08);
}
.pd-price .btn-ghost:hover { background: rgba(255, 255, 255, 0.18); }

/* -----------------------------------------------------------
   10. Colonne latérale — actions et contact direct
   ----------------------------------------------------------- */
.pd-side-actions { display: flex; flex-direction: column; gap: 10px; margin-top: 22px; }
.pd-side-actions .btn { width: 100%; }
.pd-side-link {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 12px 14px;
  border-radius: var(--r-md);
  border: 1px solid var(--pd-rule);
  background: var(--pd-card);
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--ink);
  text-decoration: none;
  transition: border-color 0.25s var(--ease), background 0.25s var(--ease);
}
.pd-side-link:hover { border-color: rgba(253, 185, 19, 0.6); background: var(--pd-card-hi); }
.pd-side-link i:first-child { color: var(--gold-600); font-size: 1.05rem; }
.pd-side-link small { display: block; font-weight: 500; font-size: 0.74rem; color: var(--pd-ink-quiet); }
.pd-side-link i:last-child { margin-inline-start: auto; color: var(--pd-ink-quiet); font-size: 0.8rem; }

/* -----------------------------------------------------------
   11. Déroulé de mise en route — vraie séquence, donc numérotée
   ----------------------------------------------------------- */
.pd-steps { margin-top: 22px; counter-reset: pdstep; display: grid; gap: 12px; }
.pd-step {
  position: relative;
  display: flex;
  gap: 16px;
  align-items: flex-start;
  padding: 18px 20px;
  border-radius: var(--r-md);
  background: var(--pd-card);
  border: 1px solid var(--pd-rule);
}
.pd-step::before {
  counter-increment: pdstep;
  content: counter(pdstep);
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  font-family: var(--f-display);
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--navy-900);
  background: var(--gold-500);
}
.pd-step b { display: block; font-size: 0.94rem; color: var(--ink); }
.pd-step p { margin-top: 5px; font-size: 0.86rem; line-height: 1.6; color: var(--pd-ink-quiet); }

/* -----------------------------------------------------------
   12. Bandeau « à qui ça s'adresse »
   ----------------------------------------------------------- */
.pd-audience { display: flex; flex-wrap: wrap; gap: 9px; margin-top: 18px; }
.pd-audience span {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 15px;
  border-radius: var(--r-pill);
  font-size: 0.83rem;
  font-weight: 600;
  color: var(--navy-700);
  background: rgba(11, 42, 107, 0.06);
  border: 1px solid var(--pd-rule);
}
[data-theme="dark"] .pd-audience span { color: var(--gold-200); background: rgba(255, 255, 255, 0.06); }
.pd-audience i { color: var(--gold-600); }

/* -----------------------------------------------------------
   13. Impression : on garde le contenu, on retire le décor
   ----------------------------------------------------------- */
@media print {
  .pd-toc,
  .pd-side-actions,
  .pd-hero-actions,
  .pd-poster-zoom { display: none !important; }
  .pd-poster,
  .pd-panel,
  .pd-kpis { box-shadow: none; }
}

/* -----------------------------------------------------------
   14. Bande SamaBalance (page d'accueil)
   Volontairement plus basse que la section Ysraa dans la
   hiérarchie : une bande, pas une section pleine hauteur.
   ----------------------------------------------------------- */
.sb-band {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: 30px;
  align-items: center;
  padding: 26px;
  border-radius: var(--r-lg);
}
@media (max-width: 860px) {
  .sb-band { grid-template-columns: 1fr; gap: 22px; padding: 22px; }
}
.sb-band-media img {
  width: 100%;
  height: auto;
  border-radius: var(--r-md);
  display: block;
}
.sb-band-body h3 {
  font-size: clamp(1.25rem, 2.6vw, 1.65rem);
  margin-top: 4px;
  line-height: 1.25;
}
.sb-band-body p {
  margin-top: 12px;
  font-size: 0.97rem;
  line-height: 1.65;
}
.sb-band-actions {
  margin-top: 22px;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

/* -----------------------------------------------------------
   15. Fiche Ysraa : la scène porte le vrai logo (symbole +
   logotype en dégradé, réservé aux fonds nuit par la charte)
   au lieu de l'icône et du mot génériques.
   ----------------------------------------------------------- */
.pd-visual-icon.is-brand { background: rgba(255, 255, 255, 0.06); }
.pd-visual-icon.is-brand img { width: 56px; height: 56px; object-fit: contain; }
.pd-visual-wordmark {
  position: relative;
  z-index: 2;
  height: clamp(30px, 4vw, 42px);
  width: auto;
}

/* -----------------------------------------------------------
   16. Animation du logo Ysraa (assets/js/ysraa-intro.js)
   Le canvas se pose par-dessus la scène ; le logo statique
   reste dessous comme repli (sans JS, données en échec) et
   s'efface au premier dessin.
   ----------------------------------------------------------- */
.ysraa-intro.pd-visual-stage {
  height: auto;
  aspect-ratio: 16 / 9;
  background: #01030B;
}
/* En portrait étroit, un 16:9 rendrait le slogan illisible. */
@media (max-width: 640px) {
  .ysraa-intro.pd-visual-stage { height: auto; aspect-ratio: 4 / 5; }
}
.ysraa-intro__canvas {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: block;
  width: 100%;
  height: 100%;
}
.ysraa-intro.is-playing > :not(.ysraa-intro__canvas):not(.ysraa-intro__replay) { visibility: hidden; }
.ysraa-intro.is-playing::before,
.ysraa-intro.is-playing::after { display: none; }
/* En haut à droite : le bas de la scène porte le slogan et la signature. */
.ysraa-intro__replay {
  position: absolute;
  top: 1rem;
  right: 1rem;
  z-index: 4;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.45rem 0.95rem;
  border: 1px solid rgba(201, 214, 242, 0.25);
  border-radius: 999px;
  background: rgba(8, 21, 68, 0.55);
  color: #C9D6F2;
  font: inherit;
  font-size: 0.8125rem;
  cursor: pointer;
  backdrop-filter: blur(6px);
  animation: ysraaReplayIn 0.4s ease both;
  transition: border-color 0.2s ease, color 0.2s ease;
}
.ysraa-intro__replay[hidden] { display: none; }
.ysraa-intro__replay:hover,
.ysraa-intro__replay:focus-visible { border-color: #1E7BFF; color: #fff; }
@keyframes ysraaReplayIn { from { opacity: 0; transform: translateY(-4px); } }

/* Variante « fond » : la section 02 de l'accueil. Le canvas
   couvre toute la section, sous le contenu ; un voile plus
   dense à gauche garde le texte lisible pendant la comète. */
.ysraa-fond {
  background: #01030B;
  color: var(--text);
}
.ysraa-fond > .ysraa-intro__canvas { z-index: 0; }
.ysraa-fond::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(90deg, rgba(1, 3, 11, 0.62) 0%, rgba(1, 3, 11, 0.3) 45%, rgba(1, 3, 11, 0.05) 70%);
}
.ysraa-fond > .container { position: relative; z-index: 1; }
/* Le filigrane « YSRAA » ferait doublon avec le ruban animé. */
.ysraa-fond .wm-mark { display: none; }
@media (max-width: 900px) {
  .ysraa-fond::after { background: rgba(1, 3, 11, 0.45); }
}

/* Variante « fond » dans le diaporama de l'accueil : la figure
   de la slide Ysraa porte le canvas au lieu d'une photo. */
.hs-media .ysraa-hero {
  --slide-fallback: radial-gradient(60% 55% at 70% 45%, #0F2A75 0%, #081544 45%, #020514 100%);
}
.ysraa-hero > .ysraa-intro__canvas { z-index: 0; }
/* Slide Ysraa active : le voile du bas s'allège à droite pour
   laisser lire le logotype posé sous le terminal ; la gauche,
   où se trouve le texte, garde son voile dense. */
.hero-slider:has(.ysraa-hero.on) .hs-scrim {
  background:
    linear-gradient(
      90deg,
      rgba(6, 17, 40, 0.92) 0%,
      rgba(6, 17, 40, 0.78) 42%,
      rgba(6, 17, 40, 0.18) 78%,
      rgba(6, 17, 40, 0.4) 100%
    ),
    linear-gradient(0deg, rgba(6, 17, 40, 0.75), transparent 45%) 0 0 / 55% 100% no-repeat;
}
@media (max-width: 900px) {
  .hero-slider:has(.ysraa-hero.on) .hs-scrim {
    background: linear-gradient(0deg, rgba(6, 17, 40, 0.94) 15%, rgba(6, 17, 40, 0.72) 70%, rgba(6, 17, 40, 0.6));
  }
}

/* ---------- Captures réelles des produits ----------
   ⚠️ POURQUOI : les fiches affichaient une icône et le nom du produit
   (ou un faux écran en CSS) à la place de l'application. Ces règles portent
   les vraies captures, faites sur des données FICTIVES d'environnements de
   démonstration — jamais sur la base d'un client. Les images sont en 16/10
   (1440 × 900) ; le ratio est posé ici pour éviter le saut de mise en page
   pendant le chargement différé. */
.pd-visual-stage--shot {
  height: auto;
  display: block;
  padding: 0;
  background: var(--navy-900);
}
.pd-visual-stage--shot img,
.pd-device--shot img,
.pd-shot img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  object-position: top left;
}
.pd-device--shot { padding: 6px; }
/* Une vraie capture se lit mal en demi-colonne : elle prend la plus grande part du panneau. */
.pd-panel:has(> .pd-device--shot) { grid-template-columns: minmax(0, 0.75fr) minmax(0, 1.25fr); }
@media (max-width: 760px) { .pd-panel:has(> .pd-device--shot) { grid-template-columns: 1fr; } }
.pd-device--shot img { border-radius: 16px; }

/* Applications mobiles : trois écrans de téléphone côte à côte */
.pd-visual-stage--phones {
  height: auto;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: flex-start;
  gap: 4%;
  padding: 28px 6% 0;
  max-height: 460px;
  overflow: hidden;
}
.pd-visual-stage--phones img {
  position: relative;
  width: 29%;
  height: auto;
  border-radius: 20px 20px 0 0;
  border: 6px solid rgba(255, 255, 255, 0.14);
  border-bottom: 0;
}
.pd-visual-stage--phones img:not(:nth-of-type(2)) { margin-top: 36px; }

/* Galerie « Les écrans » des fiches sans onglets */
.pd-shots {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px;
  margin-top: 20px;
}
@media (max-width: 760px) { .pd-shots { grid-template-columns: 1fr; } }
.pd-shot {
  margin: 0;
  border: 1px solid var(--pd-rule);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--pd-card);
}
.pd-shot img { border-bottom: 1px solid var(--pd-rule); }
.pd-shot figcaption { padding: 12px 16px; font-size: 0.85rem; line-height: 1.5; color: var(--pd-ink-quiet); }
.pd-shot figcaption b { display: block; margin-bottom: 2px; font-size: 0.92rem; color: var(--pd-ink, inherit); }
.pd-shots-note { margin-top: 12px; font-size: 0.8rem; color: var(--pd-ink-quiet); }

/* epure.css */
/* ===========================================================
   CyNoLux — Épuration (v6)
   Chargée APRÈS refonte.css. Dernière couche du système.

   Contexte : le v5 (refonte.css) corrigeait la hiérarchie et le
   contraste sans toucher au verre ni aux ombres. Cette demande-ci
   va plus loin — un design "encore plus épuré, moins chargé",
   une typographie qui tient à toutes les tailles d'écran, et une
   chronologie de lecture plus nette sur la page d'accueil.

   Trois leviers, dans l'ordre où ils comptent :
   1. Alléger le verre et les ombres (c'est la source la plus
      visible de "surcharge" — 22px de flou et 160% de saturation,
      répétés sur une dizaine de blocs, ça fatigue l'œil).
   2. Étendre la fluidité typographique et le rythme des sections
      aux extrêmes (petits téléphones, très grands écrans).
   3. Donner à la page d'accueil une numérotation de chapitres
      discrète, pour qu'on sente qu'on avance dans un récit plutôt
      que dans une pile de blocs.

   Additif : le supprimer rend le site à son état v5, sans casse.
   =========================================================== */

/* -----------------------------------------------------------
   1. VERRE ET OMBRES — allègement
   Avant : remplissage à 55-58% d'opacité + flou 18-22px +
   saturation 160% + ombres portées jusqu'à 70px. Empilé sur
   bento, why-us, features, partenaires, témoignages, le résultat
   scintille plus qu'il n'apaise.
   Après : un panneau plus mat, presque opaque, avec un flou
   résiduel pour la profondeur — pas pour l'effet. Même teinte,
   même identité (navy/or), poids visuel divisé par deux.
   ----------------------------------------------------------- */
:root {
  --glass-fill: rgba(255, 255, 255, 0.86);
  --glass-fill-strong: rgba(255, 255, 255, 0.94);
  --glass-border: rgba(11, 42, 107, 0.08);

  --glass-shadow: 0 20px 46px -28px rgba(11, 42, 107, 0.22);
  --glass-shadow-sm: 0 10px 24px -16px rgba(11, 42, 107, 0.16);
  --lift: 0 26px 60px -36px rgba(11, 42, 107, 0.34);
  --lift-soft: 0 14px 34px -24px rgba(11, 42, 107, 0.26);
}
[data-theme="dark"] {
  --glass-fill: rgba(19, 38, 76, 0.72);
  --glass-fill-strong: rgba(24, 48, 94, 0.86);
  --glass-border: rgba(255, 255, 255, 0.09);

  --glass-shadow: 0 22px 52px -26px rgba(0, 0, 0, 0.6);
  --glass-shadow-sm: 0 12px 28px -18px rgba(0, 0, 0, 0.48);
  --lift: 0 26px 60px -32px rgba(0, 0, 0, 0.68);
  --lift-soft: 0 14px 34px -22px rgba(0, 0, 0, 0.54);
}

/* Le flou et la saturation restent codés en dur (pas de jeton) sur
   les cartes vitrées les plus visibles : on les corrige ici,
   sélecteur par sélecteur, plutôt que de toucher aux fichiers
   sources. */
.glass,
.glass-dark,
.cnx-why-us__card,
.cnx-features__card,
.cnx-partners__card,
.cnx-testimonials__body {
  backdrop-filter: blur(12px) saturate(118%);
  -webkit-backdrop-filter: blur(12px) saturate(118%);
}

/* -----------------------------------------------------------
   2. RYTHME DES SECTIONS
   Avant : 120px fixes en haut et en bas de chaque section, sur
   mobile comme sur desktop — beaucoup de vide à défiler sur un
   téléphone, pas plus de souffle sur un écran 27". Les en-têtes
   de section (eyebrow + h2 + p) gardaient la même marge partout.
   Après : le rythme respire avec l'écran, dans une fourchette
   sobre (64 à 120px) qui ne s'emballe jamais sur les très grands
   moniteurs.
   ----------------------------------------------------------- */
section {
  padding: clamp(64px, 9vw, 120px) 0;
}
.section-head {
  margin-bottom: clamp(36px, 6vw, 56px);
}

/* -----------------------------------------------------------
   3. TYPOGRAPHIE — les extrêmes
   Les titres (h1-h3) étaient déjà fluides. Ce qui ne l'était pas :
   le conteneur (fixe à 1240px, un peu étroit sur un écran 4K, où
   le texte se retrouve en colonne étroite au milieu du vide) et
   le corps de texte des chapeaux/citations, qui restait figé au
   même rem du téléphone au grand écran.
   ----------------------------------------------------------- */
.container {
  max-width: min(1240px, 92vw);
}
@media (min-width: 1600px) {
  .container {
    max-width: 1320px;
  }
}
.hero p.lead,
.section-head p,
.cta-band p {
  font-size: clamp(0.98rem, 0.85rem + 0.4vw, 1.15rem);
}

/* Garde-fou sur les très petits écrans (dès 340px) : on resserre
   l'interligne des titres pour éviter qu'un h1 sur quatre lignes
   ne pousse le hero hors de l'écran. */
@media (max-width: 380px) {
  h1 {
    line-height: 1.06;
  }
  .container {
    padding-inline: 18px;
  }
}

/* -----------------------------------------------------------
   4. CHRONOLOGIE — repères de chapitre
   La page d'accueil enchaîne une dizaine de sections sans qu'on
   sache jamais où on en est dans la visite. On ajoute un numéro
   discret devant chaque chapeau de section (même esprit graphique
   que la pagination "01 / 05" du hero et les chiffres tabulaires
   du bandeau de preuve) : un repère de lecture, pas une décoration.
   Le HTML porte désormais un <span class="chapter-mark">01</span>
   juste avant chaque .eyebrow / .section-index de chapitre.
   ----------------------------------------------------------- */
.chapter-mark {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--f-mono);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  color: var(--gold-700, var(--gold-600));
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  margin-bottom: 8px;
}
[data-theme="dark"] .chapter-mark {
  color: var(--gold-400);
}
.chapter-mark::after {
  content: "";
  width: 14px;
  height: 1px;
  background: currentColor;
  opacity: 0.5;
}

/* Unifie les deux variantes de chapeau existantes (.eyebrow et
   .section-index) sur une seule couleur, pour que la page ne
   passe plus du navy au gris selon la section. */
.section-index {
  color: var(--gold-700, var(--gold-600));
}
[data-theme="dark"] .section-index {
  color: var(--gold-400);
}

/* -----------------------------------------------------------
   5. CONTENU ALLÉGÉ — ajustements liés à la simplification
   La section « Notes de terrain » est passée de 4 cartes (avec
   dates et auteurs fictifs — le site n'a pas de blog) à 3 cartes
   honnêtes, chacune reliée à une vraie page de service.
   ----------------------------------------------------------- */
.cnx-articles__grid {
  grid-template-columns: repeat(3, 1fr);
}
@media (max-width: 900px) {
  .cnx-articles__grid {
    grid-template-columns: 1fr;
  }
}

/* -----------------------------------------------------------
   7. RAIL DE CHAPITRES
   Injecté par js/chapter-rail.js à partir des .chapter-mark déjà
   posés dans le HTML — rien à modifier côté markup. Reprend le
   "page-spine" du projet TDSI (features/shared/components/
   page-spine) : un trait fin qui se remplit avec la progression
   globale du scroll, et un point minimal par chapitre qui ne
   s'anime qu'au survol/à l'actif — pas d'icône, pas de capsule.
   Seule adaptation à CyNoLux : la halo autour des points est en
   verre translucide plutôt qu'une bordure unie, pour rester
   lisible aussi bien sur les sections claires que sur le hero
   sombre (TDSI n'a qu'un seul thème sombre). Cache sur petit
   écran : pas la place, et le pouce n'en a pas besoin sur mobile.
   ----------------------------------------------------------- */
.chapter-rail {
  position: fixed;
  top: 50%;
  right: 22px;
  transform: translateY(-50%);
  z-index: 60;
  height: min(70vh, 600px);
  display: flex;
  align-items: center;
  padding: 18px 8px;
  opacity: 1;
  transition: opacity 0.4s var(--ease, ease), transform 0.4s var(--ease, ease);
}
.chapter-rail.is-hidden {
  opacity: 0;
  transform: translateY(-50%) translateX(8px);
  pointer-events: none;
}

.chapter-rail__list {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  height: 100%;
  min-height: 100%;
}

.chapter-rail__track {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 3px;
  transform: translateX(-50%);
  background: linear-gradient(
    to bottom,
    transparent,
    rgba(11, 42, 107, 0.16) 8%,
    rgba(11, 42, 107, 0.16) 92%,
    transparent
  );
  border-radius: var(--r-pill, 999px);
  z-index: -1;
}
[data-theme="dark"] .chapter-rail__track {
  background: linear-gradient(
    to bottom,
    transparent,
    rgba(255, 255, 255, 0.18) 8%,
    rgba(255, 255, 255, 0.18) 92%,
    transparent
  );
}
.chapter-rail__fill {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: var(--rail-progress, 0%);
  background: linear-gradient(180deg, var(--navy-400), var(--gold-500));
  box-shadow: 0 0 10px rgba(253, 185, 19, 0.45);
  border-radius: var(--r-pill, 999px);
  transition: height 0.15s linear;
}

.chapter-rail__dot {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: transparent;
  border: 0;
  padding: 0;
  flex-shrink: 0;
  cursor: pointer;
}
.chapter-rail__dot::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(11, 42, 107, 0.4);
  box-shadow: 0 0 0 3px var(--glass-fill, rgba(255, 255, 255, 0.4));
  transition: background 0.3s var(--ease, ease), transform 0.3s var(--ease, ease),
    box-shadow 0.3s var(--ease, ease);
}
[data-theme="dark"] .chapter-rail__dot::before {
  background: rgba(255, 255, 255, 0.4);
  box-shadow: 0 0 0 3px var(--glass-fill-dark, rgba(11, 25, 56, 0.4));
}
.chapter-rail__dot:hover::before {
  background: var(--navy-500);
  transform: scale(1.3);
}
.chapter-rail__dot.is-active::before {
  background: var(--gold-500);
  transform: scale(1.5);
  box-shadow: 0 0 10px rgba(253, 185, 19, 0.7), 0 0 0 3px var(--glass-fill, rgba(255, 255, 255, 0.4));
}
[data-theme="dark"] .chapter-rail__dot.is-active::before {
  box-shadow: 0 0 10px rgba(253, 185, 19, 0.7), 0 0 0 3px var(--glass-fill-dark, rgba(11, 25, 56, 0.4));
}

.chapter-rail__tip {
  position: absolute;
  right: 100%;
  top: 50%;
  margin-right: 14px;
  transform: translateY(-50%) translateX(6px);
  white-space: nowrap;
  background: var(--navy-800);
  color: #fff;
  font-family: var(--f-mono);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  padding: 6px 13px;
  border-radius: var(--r-pill, 999px);
  box-shadow: var(--glass-shadow-sm);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s var(--ease, ease), transform 0.25s var(--ease, ease);
}
.chapter-rail__dot:hover .chapter-rail__tip,
.chapter-rail__dot:focus-visible .chapter-rail__tip {
  opacity: 1;
  transform: translateY(-50%) translateX(0);
}

@media (max-width: 960px) {
  .chapter-rail {
    display: none;
  }
}
@media print {
  .chapter-rail {
    display: none !important;
  }
}

/* -----------------------------------------------------------
   8. FINITIONS
   ----------------------------------------------------------- */
/* Un focus plus net, cohérent avec la seule fioriture dorée que
   ce système s'autorise déjà ailleurs (proof-band, chapter-mark). */
:focus-visible {
  outline-offset: 3px;
  border-radius: 6px;
}

/* Les liens de texte courant (notes, mentions légales, articles)
   gagnent un soulignement discret et espacé plutôt que le contact
   direct avec les descendantes de lettres. */
.section-head p a,
.cnx-articles__card p a {
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

/* Cartes : la même ombre partout, plus légère, au lieu de sauter
   de --glass-shadow-sm à --glass-shadow selon les blocs. */
.card,
.glass,
.cnx-why-us__card,
.cnx-features__card,
.cnx-testimonials__body,
.cnx-articles__card {
  transition: transform 0.4s var(--ease, ease), box-shadow 0.4s var(--ease, ease), background 0.4s var(--ease, ease);
}

/* cta-band.css */
/* ===========================================================
   CyNoLux — Bande « Travaillons ensemble »
   Bande PLEINE LARGEUR posée au milieu de la page, entre deux blocs, là où la page
   a convaincu : accueil, À propos, Services, Packs et fiches du portfolio (sur la
   liste du portfolio, en fin de catalogue : la grille filtrée ne se coupe pas).
   Chaque page y met son propre texte (titre et phrase) ; « Travaillons ensemble »
   reste le repère commun, en surtitre.

   Même composition que la bande « Prêt à commencer ? » de mentasys : un bloc
   « nuit », une aurore qui dérive lentement derrière, un filigrane
   (le logo CyNoLux en masque, plus les courbes de niveau, calque `ct` de
   contours.css) et un seul appel, centré. L'or du bouton reste le seul
   point lumineux.
   Les images du filigrane sont résolues depuis CE fichier (../img/…), donc
   valables depuis la racine comme depuis /portfolio/.

   ⚠️ POURQUOI un fichier à part, chargé par toutes ces pages : l'appel final
   existait en cinq versions (hm-cta, lp-cta, cta-band, cnx-partners__cta…) avec
   chacune sa feuille, et chaque page avait ses mots. Un seul bloc, une seule
   règle. Classes à préfixe ct- : rien n'est hérité des anciennes versions.
   =========================================================== */

.ct-band {
  position: relative; isolation: isolate; overflow: hidden; text-align: center;
  width: 100%; padding: clamp(64px, 8vw, 108px) 24px;
  background: linear-gradient(160deg, var(--navy-800, #0A2258), var(--navy-900, #071938));
  color: #fff;
}

/* Aurore : bleu de marque à gauche et à droite, une touche d'or au centre. */
.ct-aurora {
  position: absolute; z-index: -1; inset: -40% -10%; pointer-events: none;
  background:
    radial-gradient(30% 46% at 22% 62%, rgba(62, 107, 219, .42), transparent 70%),
    radial-gradient(28% 42% at 50% 30%, rgba(253, 185, 19, .16), transparent 70%),
    radial-gradient(30% 46% at 80% 62%, rgba(30, 77, 183, .40), transparent 70%);
  animation: ct-drift 18s ease-in-out infinite alternate;
}
@keyframes ct-drift {
  from { transform: translate3d(-3%, 0, 0) scale(1); }
  to   { transform: translate3d(3%, -4%, 0) scale(1.08); }
}

/* Filigrane : la forme exacte du logo (C, N, ruban) en masque, teinte claire
   très discrète. Il signe le bloc sans gêner la lecture. */
.ct-mark {
  position: absolute; z-index: -1; top: 50%; left: 50%; pointer-events: none;
  width: min(640px, 130vw); aspect-ratio: 1099 / 1002;
  transform: translate(-50%, -50%);
  background: linear-gradient(135deg, rgba(255, 255, 255, .10), rgba(253, 185, 19, .10));
  -webkit-mask: url(../img/cn-c.webp) center / contain no-repeat, url(../img/cn-n.webp) center / contain no-repeat, url(../img/cn-ribbon.webp) center / contain no-repeat;
  mask: url(../img/cn-c.webp) center / contain no-repeat, url(../img/cn-n.webp) center / contain no-repeat, url(../img/cn-ribbon.webp) center / contain no-repeat;
}

.ct-inner { position: relative; max-width: 680px; margin: 0 auto; }
.ct-band .eyebrow { color: var(--gold-300, #FFDA6B); justify-content: center; margin-bottom: 16px; }
.ct-band h2 {
  color: #fff; font-size: clamp(1.9rem, 3.6vw, 2.8rem);
  line-height: 1.15; letter-spacing: -.02em; margin-bottom: 14px;
}
.ct-band p { max-width: 480px; margin: 0 auto 30px; color: rgba(233, 240, 255, .78); line-height: 1.7; }
.ct-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; }
.ct-band .btn-ghost {
  color: #fff; background: rgba(255, 255, 255, .08); border: 1px solid rgba(255, 255, 255, .28);
  backdrop-filter: none; -webkit-backdrop-filter: none;
}
.ct-band .btn-ghost:hover { background: rgba(255, 255, 255, .16); border-color: rgba(255, 255, 255, .5); }

@media (max-width: 560px) { .ct-actions .btn { flex: 1 1 100%; } }

@media (prefers-reduced-motion: reduce) { .ct-aurora { animation: none; } }
.cyn-lite .ct-aurora { animation: none; }

/* contours.css */
/* ===========================================================
   CyNoLux — courbes de niveau (filigrane)
   -----------------------------------------------------------
   UN fichier (contours.webp, 48 Ko, tuile 900×600 sans couture) sert de
   masque ; la COULEUR et l'INTENSITÉ viennent du CSS. Aucune animation.

     <section class="ct-host">
       <div class="ct c-blanc ct--centre" aria-hidden="true"></div>
       …contenu (reste au-dessus tout seul)…
     </section>

   COULEURS  (choisissez-en UNE par calque)
     Fond sombre :  c-blanc  c-gris-clair  c-bleu-clair  c-or
     Fond blanc  :  c-noir   c-gris        c-bleu-nuit    c-or-fonce
     Auto (suit le thème du site) :  c-auto  (bleu-nuit en clair, blanc en sombre)
   INTENSITÉ    k-faible (×0,6)  ·  [défaut]  ·  k-fort (×1,7)  ·  k-max (×2,6)
   ESTOMPE      ct--centre (s'efface derrière le texte) · ct--gauche · ct--droite
                (sans estompe : motif plein sur toute la surface)
   ÉCHELLE      ct--fin (600 px) · [défaut 900 px] · ct--large (1300 px)
   =========================================================== */
.ct-host { position: relative; isolation: isolate; overflow: clip; }
.ct-host > :not(.ct) { position: relative; z-index: 1; }

.ct {
  --ct-c: #fff; --ct-o: .075; --ct-k: 1; --ct-s: 900px; --ct-fade: linear-gradient(#000, #000);
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: var(--ct-c); opacity: calc(var(--ct-o) * var(--ct-k));
  -webkit-mask-image: url(../img/contours/contours.webp), var(--ct-fade); mask-image: url(../img/contours/contours.webp), var(--ct-fade);
  -webkit-mask-size: var(--ct-s) auto, 100% 100%; mask-size: var(--ct-s) auto, 100% 100%;
  -webkit-mask-repeat: repeat, no-repeat; mask-repeat: repeat, no-repeat;
  -webkit-mask-composite: source-in; mask-composite: intersect;
}
@media (max-width: 700px) { .ct { --ct-s: 600px; } .ct.ct--large { --ct-s: 800px; } }

/* ---- couleurs : fond sombre ---- */
.ct.c-blanc      { --ct-c: #FFFFFF; --ct-o: .075; }
.ct.c-gris-clair { --ct-c: #B8C2D9; --ct-o: .10; }
.ct.c-bleu-clair { --ct-c: #9FB4E6; --ct-o: .085; }
.ct.c-or         { --ct-c: #FDB913; --ct-o: .14; }
/* ---- couleurs : fond blanc ---- */
.ct.c-noir       { --ct-c: #000000; --ct-o: .055; }
.ct.c-gris       { --ct-c: #5B6785; --ct-o: .10; }
.ct.c-bleu-nuit  { --ct-c: #0B2A6B; --ct-o: .07; }
.ct.c-or-fonce   { --ct-c: #C98F0A; --ct-o: .17; }
/* ---- auto : suit le thème (la section blanche devient sombre en thème sombre) ---- */
.ct.c-auto { --ct-c: #0B2A6B; --ct-o: .07; }
[data-theme="dark"] .ct.c-auto { --ct-c: #FFFFFF; --ct-o: .075; }

/* ---- intensité ---- */
.ct.k-faible { --ct-k: .6; }
.ct.k-fort   { --ct-k: 1.7; }
.ct.k-max    { --ct-k: 2.6; }

/* ---- estompes ---- */
.ct.ct--centre { --ct-fade: radial-gradient(ellipse 62% 64% at 50% 54%, rgba(0,0,0,.12) 18%, #000 82%); }
.ct.ct--gauche { --ct-fade: linear-gradient(100deg, transparent 18%, #000 80%); }
.ct.ct--droite { --ct-fade: linear-gradient(260deg, transparent 18%, #000 80%); }

/* ---- échelle ---- */
.ct.ct--fin   { --ct-s: 600px; }
.ct.ct--large { --ct-s: 1300px; }

/* ---- fond de page (posé par lab.js) ----
   Le même filigrane que la bande « Travaillons ensemble », fixe derrière toute la page
   (il remplace la trame d'arcs concentriques `.wm-canvas`). z-index explicite : sur les
   pages qui ne chargent pas glass3d.css, `.ct` vaut 0 et passerait devant le contenu. */
.wm-contours { position: fixed; inset: 0; z-index: -1; --ct-s: 1100px; }
/* Jaune de la marque, très transparent : l'or paraît plus fort que le bleu nuit à
   opacité égale, donc on descend sous les ~4 % de la version bleue. La spécificité
   `.ct.wm-contours` passe devant `.ct.c-or` / `.k-faible`. */
.ct.wm-contours { --ct-c: #E5A20D; --ct-o: .05; --ct-k: .6; }
[data-theme="dark"] .ct.wm-contours { --ct-c: #FDB913; --ct-o: .04; --ct-k: .6; }
@media (max-width: 700px) { .wm-contours { --ct-s: 700px; } }

/* glass3d.css */
/* ===========================================================
   CyNoLux — Verre & Profondeur (couche finale, v2)
   À charger EN DERNIER (après cta-band.css) et APRÈS contours.css.

   Ce que fait ce fichier — et rien d'autre :
     • la 3D : les blocs se redressent AU RYTHME DU DÉFILEMENT, le tableau
       du hero réagit à la souris (couches à des profondeurs différentes),
       les cartes ont du volume au survol ;
     • un traitement « verre » sur cartes, en-tête et boutons ;
     • le branchement du filigrane « courbes de niveau » (contours.css).
   Les fonds, le logo CN du hero et les photos ne sont PAS modifiés.

   RÉGLER L'INTENSITÉ : une seule variable, --g3-depth (ci-dessous).
     0.6 = discret · 1 = recommandé · 1.5 = spectaculaire · 0 = plat.

   Sécurité : mouvement réduit = aucune animation ; seuls transform et
   opacity sont animés ; sans « scroll-driven animations » (Firefox), les
   blocs arrivent avec la même 3D mais déclenchée au passage.
   =========================================================== */

:root {
  --g3-depth: 1;
  --g3-persp: 1500px;
  --g3-ease: cubic-bezier(.22, 1, .36, 1);
  --g3-hair: rgba(11, 42, 107, .08);
  --g3-spec: rgba(255, 255, 255, .92);
}

/* ==========================================================
   1. FILIGRANE — branchement du kit « courbes de niveau »
   <div class="ct …"> en premier enfant. On n'utilise PAS .ct-host (il
   forcerait position:relative sur tous les enfants) : l'isolation suffit.
   ========================================================== */
:is(.hm-hero, .hm-section, .lp-hero, .lp-sec, .ct-band, .site-footer, .cnx-why-us) { isolation: isolate; }
body .ct { z-index: -1; }

/* ==========================================================
   2. VERRE — un seul traitement pour toutes les cartes
   (volontairement sans flou d'arrière-plan : il ne se voit pas sur fond
   uni, coûte cher, et empêcherait la 3D des couches internes)
   ========================================================== */
body :is(.hm-pick__panel, .lp-plan, .lp-svc__card, .nt-card, .cnx-why-us__card, .tl-card,
         .lp-form-card, .est-panel, .cnx-partners__card) {
  background: linear-gradient(150deg, rgba(255, 255, 255, .92), rgba(255, 255, 255, .6));
  border: 1px solid rgba(255, 255, 255, .9);
  box-shadow:
    inset 0 1px 0 var(--g3-spec),
    inset 0 -1px 0 rgba(11, 42, 107, .05),
    0 0 0 1px var(--g3-hair),
    0 2px 4px rgba(11, 42, 107, .04),
    0 26px 46px -26px rgba(11, 42, 107, .36);
}
body .lp-plan--hot {
  border-color: rgba(253, 185, 19, .9);
  box-shadow:
    inset 0 1px 0 var(--g3-spec),
    0 0 0 1px rgba(253, 185, 19, .35),
    0 34px 60px -30px rgba(229, 162, 13, .62);
}
[data-theme="dark"] :is(.hm-pick__panel, .lp-plan, .lp-svc__card, .nt-card, .cnx-why-us__card, .tl-card,
                        .lp-form-card, .est-panel, .cnx-partners__card) {
  background: linear-gradient(150deg, rgba(44, 78, 150, .5), rgba(14, 32, 72, .55));
  border-color: rgba(255, 255, 255, .14);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .2),
    inset 0 -1px 0 rgba(0, 0, 0, .25),
    0 28px 50px -26px rgba(0, 0, 0, .8);
}

/* Section Ysraa : ici le flou a du sens (le canvas animé passe derrière). */
body .hm-mods {
  background: linear-gradient(155deg, rgba(48, 86, 168, .38), rgba(12, 30, 72, .5));
  -webkit-backdrop-filter: blur(20px) saturate(1.5);
  backdrop-filter: blur(20px) saturate(1.5);
  border: 1px solid rgba(255, 255, 255, .16);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .26), 0 40px 70px -34px rgba(0, 0, 0, .8);
}
body .hm-mod { background: rgba(255, 255, 255, .05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .12); }

.site-header .header-inner {
  -webkit-backdrop-filter: blur(24px) saturate(1.8);
  backdrop-filter: blur(24px) saturate(1.8);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .95),
    inset 0 -1px 0 rgba(11, 42, 107, .06),
    0 14px 34px -16px rgba(7, 25, 56, .5);
}
[data-theme="dark"] .site-header .header-inner {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .16), 0 14px 34px -16px rgba(0, 0, 0, .7);
}

.btn-primary {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .6),
    inset 0 -2px 0 rgba(160, 100, 0, .28),
    0 14px 30px -10px rgba(253, 185, 19, .6);
}
body :is(.hm-hero, .hm-ysraa, .ct-band, .lp-hero) .btn-ghost {
  background: rgba(255, 255, 255, .07);
  border: 1px solid rgba(255, 255, 255, .3);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .28);
}
body :is(.hm-hero, .hm-ysraa, .ct-band, .lp-hero) .btn-ghost:hover {
  background: rgba(255, 255, 255, .15); border-color: rgba(255, 255, 255, .55);
}
.ct-band { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2), 0 44px 80px -44px rgba(7, 25, 56, .75); }

.sg-step__dot {
  background:
    radial-gradient(circle at 32% 26%, rgba(255, 255, 255, .85), rgba(255, 255, 255, 0) 38%),
    linear-gradient(150deg, var(--gold-300), var(--gold-500) 60%, var(--gold-600));
  color: var(--navy-900);
  box-shadow: inset 0 -3px 6px rgba(160, 100, 0, .3), 0 10px 22px -8px rgba(229, 162, 13, .7);
}

/* ==========================================================
   3. LE VOLUME DES CARTES (souris)
   La carte s'incline vers le pointeur ; ses éléments (titre, icône,
   bouton) se détachent à des profondeurs différentes : en bougeant, on
   voit les couches glisser les unes sur les autres.
   Le JS pose data-g3-tilt (toutes) et data-g3-layers (celles qui ne
   rognent pas leur contenu : le rognage aplatit la 3D).
   ========================================================== */
.g3-glare {
  position: absolute; inset: 0; z-index: 4; border-radius: inherit; pointer-events: none;
  opacity: 0; transition: opacity .35s var(--g3-ease);
  /* Sur fond clair : une lueur dorée (le blanc délaverait le texte). */
  background: radial-gradient(400px circle at var(--g3-mx, 50%) var(--g3-my, 0%), rgba(253, 185, 19, .16), transparent 62%);
}
/* Sur fond sombre : un éclat blanc doux. */
[data-theme="dark"] .g3-glare, .lp-figure > .g3-glare, .bn-card--hero .g3-glare {
  background: radial-gradient(420px circle at var(--g3-mx, 50%) var(--g3-my, 0%), rgba(255, 255, 255, .2), transparent 60%);
}
[data-g3-tilt].is-tilting .g3-glare { opacity: 1; }

:root:root:root [data-g3-tilt].is-tilting,
:root:root:root [data-g3-tilt].g3-settle {
  transform: perspective(900px) rotateX(var(--g3-rx, 0deg)) rotateY(var(--g3-ry, 0deg));
}
:root:root:root [data-g3-tilt].is-tilting { transition: transform .12s linear, box-shadow .35s var(--g3-ease); }
:root:root:root [data-g3-tilt].g3-settle { transition: transform .8s var(--g3-ease), box-shadow .5s var(--g3-ease) !important; }
:root:root:root [data-g3-tilt].is-tilting {
  box-shadow:
    inset 0 1px 0 var(--g3-spec),
    0 0 0 1px var(--g3-hair),
    0 46px 64px -30px rgba(11, 42, 107, .5);
}

[data-g3-layers] { transform-style: preserve-3d; }
[data-g3-layers].is-tilting > :not(.g3-glare):not(.g3-sheen) { animation: g3-pop .5s var(--g3-ease) both; }
[data-g3-layers].g3-settle > :not(.g3-glare):not(.g3-sheen) { animation: g3-unpop .7s var(--g3-ease) both; }
[data-g3-layers] > :nth-child(1) { --g3-lz: 64px; }
[data-g3-layers] > :nth-child(2) { --g3-lz: 46px; }
[data-g3-layers] > :nth-child(n+3) { --g3-lz: 30px; }
@keyframes g3-pop   { from { translate: 0 0 0; } to { translate: 0 0 calc(var(--g3-lz, 28px) * var(--g3-depth)); } }
@keyframes g3-unpop { from { translate: 0 0 calc(var(--g3-lz, 28px) * var(--g3-depth)); } to { translate: 0 0 0; } }

/* ==========================================================
   4. LE TABLEAU DU HERO — une vitre qui flotte, en couches
   Le fond du tableau reste celui d'origine ; on lui ajoute de la 3D :
   il suit le pointeur (±14°), son en-tête, ses mesures et les
   notifications flottent à des profondeurs croissantes, et une ombre
   portée se détache loin derrière.
   ========================================================== */
.hm-hero .hm-board {
  transform-style: preserve-3d;
  transform: perspective(1500px) translate3d(0, 0, 0)
             rotateY(calc(-9deg + var(--g3-bx, 0) * 15deg * var(--g3-depth)))
             rotateX(calc(4deg + var(--g3-by, 0) * -11deg * var(--g3-depth)));
  transform-origin: 40% 50%;
}
.hm-hero .hm-board::after {              /* ombre portée loin derrière la vitre */
  content: ""; position: absolute; inset: 10% 5% -4%; border-radius: inherit; pointer-events: none;
  background: rgba(0, 4, 18, .6); filter: blur(36px);
  transform: translateZ(calc(-90px * var(--g3-depth)));
}
.hm-hero .hm-board__head  { translate: 0 0 calc(34px * var(--g3-depth)); }
.hm-hero .hm-metric       { translate: 0 0 calc(20px * var(--g3-depth)); }
.hm-hero .hm-board__foot  { translate: 0 0 calc(12px * var(--g3-depth)); }
.hm-hero .hm-feed         { translate: 0 0 calc(80px * var(--g3-depth)); }
@media (max-width: 1000px) {
  .hm-hero .hm-board { transform: perspective(1500px) translate3d(0, 0, 0)
    rotateY(calc(-4deg + var(--g3-bx, 0) * 8deg * var(--g3-depth))) rotateX(calc(2deg + var(--g3-by, 0) * -6deg * var(--g3-depth))); }
}

/* ==========================================================
   5. APPARITIONS EN 3D
   5a. Partout : un bloc se redresse depuis le fond (translateZ + rotateX),
       pivotant sur son bord bas, comme une dalle de verre qu'on relève.
   5b. Navigateurs à « scroll-driven animations » (Chrome, Edge, Safari 26) :
       le redressement est LIÉ AU DÉFILEMENT — il suit votre molette, dans
       les deux sens. C'est ça qui se ressent.
   ========================================================== */
@media (prefers-reduced-motion: no-preference) {

  /* 5a. Repli (et Firefox) : même geste, déclenché au passage. */
  [data-reveal] {
    opacity: 0;
    transform: perspective(var(--g3-persp)) translate3d(0, calc(80px * var(--g3-depth)), calc(-300px * var(--g3-depth))) rotateX(calc(34deg * var(--g3-depth)));
    transform-origin: 50% 100%;
    transition: opacity .8s var(--g3-ease), transform 1.3s var(--g3-ease);
  }
  [data-reveal="left"]  { transform: perspective(var(--g3-persp)) translate3d(calc(-90px * var(--g3-depth)), 0, calc(-260px * var(--g3-depth))) rotateY(calc(28deg * var(--g3-depth)));  transform-origin: 0 50%; }
  [data-reveal="right"] { transform: perspective(var(--g3-persp)) translate3d(calc(90px * var(--g3-depth)), 0, calc(-260px * var(--g3-depth))) rotateY(calc(-28deg * var(--g3-depth))); transform-origin: 100% 50%; }
  [data-reveal].is-visible { opacity: 1; transform: none; }
  [data-reveal-delay="1"] { transition-delay: .08s; }
  [data-reveal-delay="2"] { transition-delay: .16s; }
  [data-reveal-delay="3"] { transition-delay: .24s; }
  [data-reveal-delay="4"] { transition-delay: .32s; }
  [data-reveal-delay="5"] { transition-delay: .4s; }

  .cyn-js [data-stagger] > * {
    opacity: 0;
    transform: perspective(var(--g3-persp)) translate3d(0, calc(90px * var(--g3-depth)), calc(-320px * var(--g3-depth))) rotateX(calc(40deg * var(--g3-depth)));
    transform-origin: 50% 100%;
  }
  .cyn-js [data-stagger].is-in > * {
    opacity: 1; transform: none;
    transition: opacity .8s var(--g3-ease), transform 1.3s var(--g3-ease);
    transition-delay: calc(var(--i, 0) * 100ms);
  }

  /* Les en-têtes de section : le bloc reste sobre, ce sont les MOTS qui jouent. */
  .hm-head[data-reveal], .lp-head[data-reveal] {
    transform: perspective(var(--g3-persp)) translate3d(0, 24px, -60px) rotateX(10deg);
  }
  .hm-head[data-reveal].is-visible, .lp-head[data-reveal].is-visible { transform: none; }

  /* Titres : chaque mot bascule vers l'avant, comme un panneau d'affichage. */
  .cyn-js [data-split] .sp-w { perspective: 600px; }
  .cyn-js [data-split] .sp-i {
    opacity: 0;
    transform: translateY(70%) rotateX(calc(-95deg * var(--g3-depth)));
    transform-origin: 50% 100%;
    transition: transform 1s var(--g3-ease) calc(var(--w, 0) * 75ms), opacity .5s ease calc(var(--w, 0) * 75ms);
  }
  .cyn-js [data-split].is-split-in .sp-i { opacity: 1; transform: none; }

  /* Premier écran : le texte se redresse ligne après ligne ; la vitre du
     tableau arrive de côté, en profondeur, et se pose. */
  .hm-hero .hm-hero__inner > *,
  .lp-hero .container > * {
    animation-name: g3-stand; animation-duration: 1.2s; animation-timing-function: var(--g3-ease);
    transform-origin: 0 100%;
  }
  .hm-hero .hm-board { animation: g3-board-in 1.6s var(--g3-ease) .25s both; }

  /* Les panneaux d'onglets : changer d'onglet retourne la vitre. */
  .sg-panel:not([hidden]) { animation: g3-flip .8s var(--g3-ease) both; transform-origin: 50% 0; }

  /* 5b. LIÉ AU DÉFILEMENT — progressive enhancement. */
  @supports (animation-timeline: view()) {
    [data-reveal],
    .cyn-js [data-stagger] > * {
      opacity: 1; transform: none; transition: none;
      animation: g3-scrub linear backwards;
      animation-timeline: view();
      animation-range: entry 0% entry min(100%, 520px);
    }
    .cyn-js [data-stagger].is-in > * { transition: none; }
    .cyn-js [data-stagger] > * {            /* cascade : chaque carte démarre un peu plus tard */
      animation-range: entry min(calc(var(--i, 0) * 5%), 30%) entry min(calc(100% + var(--i, 0) * 5%), 560px);
    }
    [data-reveal="left"]  { animation-name: g3-scrub-l; }
    [data-reveal="right"] { animation-name: g3-scrub-r; }
    .hm-head[data-reveal], .lp-head[data-reveal] { animation-name: g3-scrub-soft; }
  }
}

@keyframes g3-stand {
  from { opacity: 0; transform: perspective(1200px) translate3d(0, 44px, -160px) rotateX(calc(28deg * var(--g3-depth))); }
}
@keyframes g3-board-in {
  from { opacity: 0; transform: perspective(1500px) translate3d(120px, 40px, -380px) rotateY(-55deg) rotateX(12deg); }
}
@keyframes g3-flip {
  from { opacity: 0; transform: perspective(1200px) translate3d(0, 20px, -120px) rotateX(calc(-22deg * var(--g3-depth))); }
}
@keyframes g3-scrub {
  from { opacity: 0; transform: perspective(var(--g3-persp)) translate3d(0, calc(110px * var(--g3-depth)), calc(-340px * var(--g3-depth))) rotateX(calc(42deg * var(--g3-depth))); transform-origin: 50% 100%; }
  55%  { opacity: 1; }
  to   { opacity: 1; transform: perspective(var(--g3-persp)) translate3d(0, 0, 0) rotateX(0deg); transform-origin: 50% 100%; }
}
@keyframes g3-scrub-l {
  from { opacity: 0; transform: perspective(var(--g3-persp)) translate3d(calc(-110px * var(--g3-depth)), 0, calc(-300px * var(--g3-depth))) rotateY(calc(34deg * var(--g3-depth))); transform-origin: 0 50%; }
  55%  { opacity: 1; }
  to   { opacity: 1; transform: perspective(var(--g3-persp)) translate3d(0, 0, 0) rotateY(0deg); transform-origin: 0 50%; }
}
@keyframes g3-scrub-r {
  from { opacity: 0; transform: perspective(var(--g3-persp)) translate3d(calc(110px * var(--g3-depth)), 0, calc(-300px * var(--g3-depth))) rotateY(calc(-34deg * var(--g3-depth))); transform-origin: 100% 50%; }
  55%  { opacity: 1; }
  to   { opacity: 1; transform: perspective(var(--g3-persp)) translate3d(0, 0, 0) rotateY(0deg); transform-origin: 100% 50%; }
}
@keyframes g3-scrub-soft {
  from { opacity: 0; transform: perspective(var(--g3-persp)) translate3d(0, 24px, -60px) rotateX(10deg); transform-origin: 50% 100%; }
  to   { opacity: 1; transform: perspective(var(--g3-persp)) translate3d(0, 0, 0) rotateX(0deg); transform-origin: 50% 100%; }
}

/* 5e. Le reflet : une fois posée, la vitre est traversée par un éclat, une seule fois. */
.g3-sheen {
  position: absolute; inset: 0; z-index: 4; border-radius: inherit; pointer-events: none; opacity: 0;
  background: linear-gradient(105deg, transparent 38%, rgba(255, 255, 255, .6) 50%, transparent 62%) no-repeat;
  background-size: 300% 100%; background-position: 130% 0;
}
@media (prefers-reduced-motion: no-preference) {
  .g3-landed > .g3-sheen { animation: g3-sheen 1.3s cubic-bezier(.4, 0, .2, 1) calc(var(--i, 0) * 95ms + .35s) both; }
}
@keyframes g3-sheen {
  0% { opacity: 0; background-position: 130% 0; }
  15% { opacity: 1; }
  100% { opacity: 0; background-position: -30% 0; }
}

@media (max-width: 700px) { :root { --g3-depth: .75; } }
.cyn-lite .hm-hero .hm-board::after { filter: blur(20px); }

/* ==========================================================
   6. LA PILE DE VITRES (utilitaire réutilisable)
   <div class="g3-pile" data-g3-flat data-g3-max="8">
     <i class="g3-sheet g3-sheet--2"></i><i class="g3-sheet g3-sheet--1"></i>
     <article>…la carte, OPAQUE…</article>
   </div>
   La carte devant, deux feuilles de verre derrière : elles se déploient
   quand la carte se pose, s'écartent au survol, et la carte s'incline
   vers le pointeur. --g3-o règle l'amplitude (1 = normal).
   ========================================================== */
.g3-pile { position: relative; display: flex; border-radius: var(--r-lg); transform-style: preserve-3d; --g3-o: 1; }
.g3-pile > :not(.g3-sheet):not(.g3-glare):not(.g3-sheen) { flex: 1; min-width: 0; position: relative; border-radius: inherit; }
.g3-sheet {
  position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: linear-gradient(150deg, rgba(255, 255, 255, .96), rgba(238, 243, 255, .78));
  border: 1px solid #fff;
  box-shadow: inset 0 1px 0 #fff, 0 0 0 1px rgba(11, 42, 107, .1), 0 22px 34px -24px rgba(11, 42, 107, .45);
  transition: transform 1s var(--g3-ease), opacity .6s ease;
}
.g3-sheet--1 { transform: translate3d(calc(10px * var(--g3-o)), calc(-10px * var(--g3-o)), -34px); opacity: .92; }
.g3-sheet--2 { transform: translate3d(calc(20px * var(--g3-o)), calc(-20px * var(--g3-o)), -68px); opacity: .62;
               background: linear-gradient(150deg, rgba(222, 232, 253, .95), rgba(205, 220, 250, .7)); }
.g3-pile:hover .g3-sheet--1 { transform: translate3d(calc(15px * var(--g3-o)), calc(-14px * var(--g3-o)), -50px) rotate(1.2deg); }
.g3-pile:hover .g3-sheet--2 { transform: translate3d(calc(28px * var(--g3-o)), calc(-25px * var(--g3-o)), -98px) rotate(2.6deg); }
@media (prefers-reduced-motion: no-preference) {
  .cyn-js .g3-pile:not(.g3-landed) .g3-sheet { transform: translate3d(0, 0, -1px); opacity: 0; }
  .g3-pile.g3-landed .g3-sheet--1 { transition-delay: calc(var(--i, 0) * 95ms + .3s); }
  .g3-pile.g3-landed .g3-sheet--2 { transition-delay: calc(var(--i, 0) * 95ms + .5s); }
}
:root:root:root .g3-pile[data-g3-tilt].is-tilting { box-shadow: none; }
.g3-pile .g3-glare { background: radial-gradient(380px circle at var(--g3-mx, 50%) var(--g3-my, 0%), rgba(253, 185, 19, .16), transparent 62%); }
[data-theme="dark"] .g3-sheet { background: linear-gradient(150deg, rgba(44, 78, 150, .55), rgba(14, 32, 72, .6)); border-color: rgba(255, 255, 255, .1); box-shadow: 0 22px 34px -24px rgba(0, 0, 0, .8); }
[data-theme="dark"] .g3-sheet--2 { background: linear-gradient(150deg, rgba(30, 58, 120, .5), rgba(10, 24, 56, .55)); }
@media (max-width: 620px) { .g3-pile { --g3-o: .6; } }

/* portfolio3d.css */
/* ===========================================================
   CyNoLux — Portfolio : clarté et profondeur
   À charger sur /portfolio/ et sur toutes les fiches, après glass3d.css.

   La page liste :
     1. une scène 3D : Ysraa au centre, ses douze modules en orbite ;
     2. une barre de recherche + filtres avec compteurs (collante) ;
     3. quatre familles titrées, des cartes compactes, Ysraa en grande carte.
   Les fiches : volume au survol des maquettes, navigation précédent / suivant.

   Rien n'est retiré de portfolio.css : cette couche surcharge. La logique
   existante (filtres de main.js, assistant portfolio-finder.js) est conservée.
   =========================================================== */

/* ==========================================================
   1. LA SCÈNE : Ysraa et ses modules
   ========================================================== */
.pf-eco { padding: clamp(56px, 7vw, 96px) 0 clamp(20px, 3vw, 44px); content-visibility: visible !important; }
.pf-eco__grid { display: grid; grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr); gap: clamp(28px, 5vw, 72px); align-items: center; }
.pf-eco__txt h2 { font-size: clamp(1.9rem, 3.4vw, 2.8rem); line-height: 1.1; }
.pf-eco__txt p { margin-top: 16px; max-width: 46ch; font-size: 1.02rem; }
.pf-eco__actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 26px; }

.pf-eco__stage {
  position: relative; height: clamp(400px, 46vw, 570px); border-radius: var(--r-xl, 32px); overflow: hidden; isolation: isolate;
  background: radial-gradient(70% 60% at 50% 58%, rgba(62, 107, 219, .5), transparent 70%), linear-gradient(160deg, #123B8F, #071938 82%);
  border: 1px solid rgba(255, 255, 255, .14);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .28), 0 56px 90px -48px rgba(7, 25, 56, .85);
}
.pf-eco__stage .ct { z-index: -1; }
.pf-eco__hint {
  position: absolute; left: 50%; bottom: 16px; translate: -50% 0; margin: 0; white-space: nowrap;
  font-family: var(--f-mono); font-size: .7rem; letter-spacing: .04em; color: rgba(233, 240, 255, .6);
}

.pf-orbit {
  position: absolute; inset: 0; perspective: 1400px; perspective-origin: 50% 30%;
  --R: clamp(128px, 17.5vw, 250px); --tilt: 27deg; --ox: 0; --oy: 0;
}
.pf-orbit__glow {
  position: absolute; left: 50%; bottom: 9%; width: 72%; height: 90px; translate: -50% 0; pointer-events: none;
  background: radial-gradient(closest-side, rgba(253, 185, 19, .3), transparent); filter: blur(10px);
}
.pf-orbit__stage {
  position: absolute; inset: 0; transform-style: preserve-3d;
  transform: rotateX(calc(var(--tilt) * -1 + var(--oy) * -8deg)) rotateY(calc(var(--ox) * 14deg));
}
/* Les deux rails de l'orbite : des cercles posés à plat, vus en ellipse. */
.pf-orbit__path {
  position: absolute; left: 50%; top: 50%; width: calc(var(--R) * 2); height: calc(var(--R) * 2);
  margin: calc(var(--R) * -1) 0 0 calc(var(--R) * -1); border-radius: 50%; pointer-events: none;
  border: 1px solid rgba(253, 185, 19, .42); transform: rotateX(90deg);
}
.pf-orbit__path--in { width: calc(var(--R) * 1.15); height: calc(var(--R) * 1.15); margin: calc(var(--R) * -.575) 0 0 calc(var(--R) * -.575); border-color: rgba(255, 255, 255, .12); }

/* Au centre : Ysraa, la sphère dorée. */
.pf-core {
  position: absolute; left: 50%; top: 50%; width: 150px; height: 150px; margin: -75px 0 0 -75px; border-radius: 50%;
  display: grid; place-items: center; text-align: center; text-decoration: none; color: var(--navy-900);
  background: radial-gradient(circle at 34% 26%, #fff, #FFE59A 18%, #FDB913 50%, #B97800 100%);
  box-shadow: inset -12px -16px 26px rgba(120, 70, 0, .5), inset 6px 8px 16px rgba(255, 255, 255, .5);
  transform: rotateX(var(--tilt)); transition: scale .5s var(--g3-ease, ease);
}
.pf-core::before { content: ""; position: absolute; inset: -55%; z-index: -1; border-radius: 50%; pointer-events: none; background: radial-gradient(closest-side, rgba(253, 185, 19, .4), rgba(253, 185, 19, .12) 55%, transparent); }
.pf-core:hover { scale: 1.06; }
.pf-core span { display: grid; line-height: 1; }
.pf-core b { font-family: var(--f-display); font-size: 1.7rem; letter-spacing: -.01em; }
.pf-core small { margin-top: 5px; font-family: var(--f-mono); font-size: .68rem; letter-spacing: .14em; opacity: .75; }
.pf-core:focus-visible, .pf-chip3d:focus-visible { outline: 3px solid #fff; outline-offset: 4px; }

/* L'anneau tourne ; chaque module tourne en sens inverse pour rester de face. */
.pf-orbit__ring { position: absolute; left: 50%; top: 50%; width: 0; height: 0; transform-style: preserve-3d; animation: pf-spin 70s linear infinite; }
.pf-orbit__item {
  position: absolute; left: 0; top: 0; width: 0; height: 0; transform-style: preserve-3d;
  transform: rotateY(calc(var(--a) * 1deg)) translateZ(var(--R)) translateY(var(--y, 0));
}
.pf-chip3d {
  position: absolute; left: -46px; top: -46px; width: 92px; display: grid; justify-items: center; gap: 8px; text-decoration: none;
  transform: rotateY(calc(var(--a) * -1deg)) rotateX(var(--tilt)); animation: pf-unspin 70s linear infinite;
}
@keyframes pf-spin { to { transform: rotateY(360deg); } }
@keyframes pf-unspin {
  from { transform: rotateY(calc(var(--a) * -1deg)) rotateX(var(--tilt)); }
  to   { transform: rotateY(calc(var(--a) * -1deg - 360deg)) rotateX(var(--tilt)); }
}
.pf-orbit:hover .pf-orbit__ring, .pf-orbit:hover .pf-chip3d, .pf-orbit:focus-within .pf-orbit__ring, .pf-orbit:focus-within .pf-chip3d,
.pf-off .pf-orbit__ring, .pf-off .pf-chip3d { animation-play-state: paused; }

.pf-chip3d__face {
  width: 70px; height: 70px; border-radius: 20px; display: grid; place-items: center; overflow: hidden;
  background: linear-gradient(150deg, rgba(255, 255, 255, .22), rgba(255, 255, 255, .06));
  border: 1px solid rgba(255, 255, 255, .3);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .42), 0 20px 30px -14px rgba(0, 0, 0, .7);
  transition: transform .4s var(--g3-ease, ease), border-color .3s, box-shadow .3s;
}
.pf-chip3d__face img { width: 76%; height: 76%; object-fit: contain; }
.pf-chip3d__face b { display: none; font-family: var(--f-display); font-size: 1.15rem; color: #fff; }
.pf-chip3d.is-empty .pf-chip3d__face img { display: none; }
.pf-chip3d.is-empty .pf-chip3d__face b { display: block; }
.pf-chip3d__name {
  padding: 4px 11px; border-radius: 99px; font-size: .74rem; font-weight: 700; color: #fff; white-space: nowrap;
  background: rgba(6, 17, 40, .6); border: 1px solid rgba(255, 255, 255, .16);
}
.pf-chip3d:hover .pf-chip3d__face { transform: scale(1.14); border-color: var(--gold-400); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), 0 0 0 4px rgba(253, 185, 19, .2), 0 26px 36px -14px rgba(0, 0, 0, .8); }
.pf-chip3d:hover .pf-chip3d__name { border-color: var(--gold-400); color: var(--gold-300); }

@media (prefers-reduced-motion: reduce) {
  .pf-orbit__ring, .pf-chip3d { animation: none; }
}
@media (max-width: 980px) {
  .pf-eco__grid { grid-template-columns: minmax(0, 1fr); }
  .pf-eco__stage { height: clamp(380px, 78vw, 520px); }
  .pf-orbit { --R: clamp(120px, 31vw, 210px); }
}
@media (max-width: 560px) {
  .pf-core { width: 112px; height: 112px; margin: -56px 0 0 -56px; } .pf-core b { font-size: 1.3rem; }
  .pf-chip3d { width: 72px; left: -36px; top: -36px; } .pf-chip3d__face { width: 58px; height: 58px; border-radius: 17px; }
  .pf-chip3d__name { font-size: .66rem; padding: 3px 8px; }
}

/* ==========================================================
   2. LA BARRE : recherche, filtres, assistant
   ========================================================== */
#catalogue { content-visibility: visible !important; }
.pf-intro { text-align: left; margin: 0 0 18px; max-width: 70ch; }
.pf-bar {
  position: sticky; top: calc(var(--header-h, 86px) + 10px); z-index: 40;
  display: grid; grid-template-columns: minmax(280px, 1.15fr) auto auto; gap: 12px; align-items: center; padding: 10px;
  border-radius: 24px; background: linear-gradient(150deg, rgba(255, 255, 255, .9), rgba(255, 255, 255, .68));
  -webkit-backdrop-filter: blur(18px) saturate(1.6); backdrop-filter: blur(18px) saturate(1.6);
  border: 1px solid #fff; box-shadow: inset 0 1px 0 #fff, 0 0 0 1px var(--g3-hair, rgba(11, 42, 107, .08)), 0 26px 44px -28px rgba(11, 42, 107, .42);
}
.pf-search { position: relative; }
.pf-search > i { position: absolute; left: 18px; top: 50%; translate: 0 -50%; color: var(--navy-600); pointer-events: none; }
.pf-search__input {
  width: 100%; height: 50px; padding: 0 46px 0 46px; border-radius: 99px; font: inherit; font-size: .98rem; color: var(--ink);
  background: #fff; border: 1px solid var(--g3-hair, rgba(11, 42, 107, .1)); box-shadow: inset 0 1px 2px rgba(11, 42, 107, .06);
  transition: box-shadow .3s, border-color .3s;
}
.pf-search__input::placeholder { color: var(--ink-faint, #8a96b0); }
.pf-search__input:focus { outline: none; border-color: var(--gold-500); box-shadow: 0 0 0 4px rgba(253, 185, 19, .2), 0 14px 26px -16px rgba(11, 42, 107, .45); }
.pf-search__input::-webkit-search-cancel-button { display: none; }
.pf-search__clear {
  position: absolute; right: 8px; top: 50%; translate: 0 -50%; width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center;
  color: var(--ink-muted); background: rgba(11, 42, 107, .06);
}
.pf-search__clear:hover { background: var(--gold-500); color: var(--navy-900); }
.pf-search__clear[hidden] { display: none; }
.pf-bar .portfolio-filters { justify-content: flex-start !important; gap: 6px; flex-wrap: nowrap; }
.pf-bar .filter-btn { padding: 10px 14px; font-size: .88rem; }
.pf-bar .filter-btn { white-space: nowrap; display: inline-flex; align-items: center; gap: 8px; }
.pf-bar .filter-btn::after { display: none !important; }
.filter-btn em {
  font-style: normal; font-family: var(--f-mono); font-size: .7rem; padding: 2px 8px; border-radius: 99px;
  background: rgba(11, 42, 107, .08); color: inherit;
}
.filter-btn.active em { background: rgba(255, 255, 255, .22); }
.pf-bar #pf-open { white-space: nowrap; }
.pf-status { margin: 16px 6px 0; font-family: var(--f-mono); font-size: .78rem; letter-spacing: .03em; color: var(--ink-quiet, #6b7893); min-height: 1.3em; }
.pf-status b { color: var(--navy-700); }
[data-theme="dark"] .pf-bar { background: linear-gradient(150deg, rgba(30, 56, 112, .86), rgba(12, 28, 64, .8)); border-color: rgba(255, 255, 255, .14); }
[data-theme="dark"] .pf-search__input { background: rgba(255, 255, 255, .06); border-color: rgba(255, 255, 255, .16); color: #fff; }
[data-theme="dark"] .pf-search > i { color: var(--gold-400); }
[data-theme="dark"] .filter-btn em { background: rgba(255, 255, 255, .12); }
[data-theme="dark"] .pf-status b { color: var(--gold-300); }
@media (max-width: 1180px) {
  .pf-bar { grid-template-columns: minmax(0, 1fr) auto; }
  .pf-bar .portfolio-filters { grid-column: 1 / -1; grid-row: 2; overflow-x: auto; scrollbar-width: none; padding-bottom: 2px; }
  .pf-bar .portfolio-filters::-webkit-scrollbar { display: none; }
}
@media (max-width: 640px) {
  .pf-bar { grid-template-columns: minmax(0, 1fr); top: calc(var(--header-h, 76px) + 6px); }
  .pf-bar #pf-open { grid-row: 3; justify-self: start; }
}

/* ==========================================================
   3. LA GRILLE : quatre familles, cartes compactes
   ========================================================== */
.pf-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 22px; margin-top: 18px; }
.pf-group {
  grid-column: 1 / -1; display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px 14px; margin-top: 42px; padding-bottom: 14px;
  border-bottom: 1px solid var(--line, rgba(11, 42, 107, .12)); scroll-margin-top: calc(var(--header-h, 86px) + 90px);
}
.pf-group:first-child { margin-top: 8px; }
.pf-group h2 { font-size: clamp(1.35rem, 2.1vw, 1.8rem); }
.pf-group small { font-family: var(--f-mono); font-size: .78rem; padding: 3px 10px; border-radius: 99px; color: var(--gold-700, #9a6a00); background: rgba(253, 185, 19, .14); }
.pf-group p { margin: 0 0 0 auto; font-size: .9rem; color: var(--ink-quiet, #6b7893); }
.pf-group.is-empty { display: none; }
[data-theme="dark"] .pf-group small { color: var(--gold-300); }
.project-card.is-nomatch { display: none !important; }

.pf-grid .project-card {
  display: flex; flex-direction: column; border-radius: var(--r-lg); overflow: hidden;
  background: linear-gradient(150deg, #fff, rgba(255, 255, 255, .74)); border: 1px solid #fff;
  box-shadow: inset 0 1px 0 #fff, 0 0 0 1px var(--g3-hair, rgba(11, 42, 107, .08)), 0 24px 40px -28px rgba(11, 42, 107, .4);
}
.pf-grid .project-card:hover { box-shadow: inset 0 1px 0 #fff, 0 0 0 1px rgba(253, 185, 19, .6), 0 38px 58px -30px rgba(11, 42, 107, .5); }
[data-theme="dark"] .pf-grid .project-card { background: linear-gradient(150deg, rgba(44, 78, 150, .5), rgba(14, 32, 72, .6)); border-color: rgba(255, 255, 255, .14); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .16), 0 26px 44px -28px rgba(0, 0, 0, .8); }
.pf-grid .project-thumb { height: 128px; flex: none; }
.pf-grid .project-logo { width: 70px; height: 70px; top: 44%; }
.pf-grid .project-thumb span { left: 14px; bottom: 12px; min-height: 32px; padding: 4px 14px; font-size: .95rem; }
.pf-grid .project-badge { transform: scale(.86); transform-origin: 0 0; }
.pf-grid .project-body { flex: 1; display: flex; flex-direction: column; padding: 16px 18px 18px; }
.pf-grid .project-body h3 { font-size: 1.1rem; margin: 6px 0 6px; }
.pf-grid .project-body p { -webkit-line-clamp: 2; font-size: .86rem; line-height: 1.5; }
.pf-grid .project-client { margin-top: auto; padding-top: 12px; border-top: 0; font-size: .76rem; }
.pf-grid .project-body p + .project-client { margin-top: 14px; }
/* Les icônes fantômes glissent doucement avec le curseur (lab.js pose --mx / --my). */
.pf-grid .project-ghost { translate: calc((var(--mx, 135px) - 135px) * -.07) calc((var(--my, 80px) - 80px) * -.07); transition: translate .5s var(--g3-ease, ease); }

/* Ysraa : la grande carte */
.pf-feature { grid-column: span 2; grid-row: span 2; }
.pf-grid .pf-feature .project-thumb { height: auto; flex: 1; min-height: 250px; }
.pf-grid .pf-feature .project-logo { width: 128px; height: 128px; top: 46%; border-radius: 28px; }
.pf-grid .pf-feature .project-thumb span { font-size: 1.15rem; min-height: 38px; padding: 6px 18px; left: 20px; bottom: 18px; }
.pf-grid .pf-feature .project-body { padding: 24px 26px 26px; flex: none; }
.pf-grid .pf-feature .project-body h3 { font-size: 1.75rem; }
.pf-grid .pf-feature .project-body p { -webkit-line-clamp: 3; font-size: .96rem; }
.pf-grid .pf-feature .project-cat { color: var(--gold-600); font-weight: 700; }

.pf-empty { margin: 44px auto 10px; max-width: 460px; text-align: center; padding: 38px 28px; border-radius: var(--r-lg); background: linear-gradient(150deg, #fff, rgba(255, 255, 255, .7)); border: 1px solid #fff; box-shadow: inset 0 1px 0 #fff, 0 0 0 1px var(--g3-hair, rgba(11, 42, 107, .08)), 0 30px 50px -34px rgba(11, 42, 107, .4); }
.pf-empty[hidden] { display: none; }
.pf-empty > i { font-size: 1.8rem; color: var(--gold-600); }
.pf-empty h3 { margin: 10px 0 6px; font-size: 1.2rem; }
.pf-empty__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin-top: 18px; }
[data-theme="dark"] .pf-empty { background: linear-gradient(150deg, rgba(44, 78, 150, .5), rgba(14, 32, 72, .6)); border-color: rgba(255, 255, 255, .14); }

@media (max-width: 1280px) { .pf-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 960px) { .pf-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; } .pf-group p { margin-left: 0; width: 100%; } }
@media (max-width: 560px) { .pf-grid { grid-template-columns: minmax(0, 1fr); } .pf-feature { grid-column: auto; grid-row: auto; } .pf-grid .pf-feature .project-thumb { min-height: 190px; } }

/* ==========================================================
   4. FICHES PROJET : du volume
   ========================================================== */
.pd-visual { box-shadow: 0 50px 80px -44px rgba(7, 25, 56, .8); }
.pd-device { box-shadow: 0 40px 64px -36px rgba(7, 25, 56, .8); }
.pd-related-card, .pd-hl-item { transition: transform .4s var(--g3-ease, ease), box-shadow .4s var(--g3-ease, ease), background .3s; }
.pd-related-card:hover { box-shadow: 0 26px 40px -26px rgba(11, 42, 107, .45); }
.pd-info-card { box-shadow: inset 0 1px 0 #fff, 0 0 0 1px var(--g3-hair, rgba(11, 42, 107, .08)), 0 34px 56px -34px rgba(11, 42, 107, .42); }

/* ==========================================================
   5. PRÉCÉDENT / SUIVANT : on reste dans la même famille
   ========================================================== */
.pf-pager-sec { padding: clamp(36px, 5vw, 64px) 0 clamp(24px, 4vw, 48px); content-visibility: visible !important; }
.pf-pager { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); gap: 16px; align-items: stretch; }
.pf-pager__card {
  position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 16px; align-items: center; padding: 18px 22px; border-radius: var(--r-lg);
  text-decoration: none; color: inherit;
  background: linear-gradient(150deg, #fff, rgba(255, 255, 255, .72)); border: 1px solid #fff;
  box-shadow: inset 0 1px 0 #fff, 0 0 0 1px var(--g3-hair, rgba(11, 42, 107, .08)), 0 24px 40px -28px rgba(11, 42, 107, .4);
  transition: box-shadow .4s var(--g3-ease, ease);
}
.pf-pager__card:hover { box-shadow: inset 0 1px 0 #fff, 0 0 0 1px rgba(253, 185, 19, .6), 0 36px 56px -30px rgba(11, 42, 107, .5); }
.pf-pager__card--prev { grid-template-columns: auto auto minmax(0, 1fr); }
.pf-pager__card--prev > i { order: -1; }
.pf-pager__card > i { font-size: 1.2rem; color: var(--gold-600); transition: transform .35s var(--g3-ease, ease); }
.pf-pager__card:hover > i.bi-arrow-right { transform: translateX(5px); }
.pf-pager__card:hover > i.bi-arrow-left { transform: translateX(-5px); }
.pf-pager__logo {
  width: 56px; height: 56px; border-radius: 16px; display: grid; place-items: center; overflow: hidden;
  background: linear-gradient(150deg, var(--navy-700), var(--navy-900)); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25);
}
.pf-pager__logo img { width: 78%; height: 78%; object-fit: contain; }
.pf-pager__logo b { display: none; font-family: var(--f-display); color: #fff; font-size: .95rem; }
.pf-pager__logo.is-empty img { display: none; } .pf-pager__logo.is-empty b { display: block; }
.pf-pager__txt { display: grid; gap: 1px; min-width: 0; }
.pf-pager__txt small { font-family: var(--f-mono); font-size: .66rem; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-faint, #8a96b0); }
.pf-pager__txt strong { font-family: var(--f-display); font-size: 1.12rem; color: var(--navy-800); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pf-pager__txt span { font-size: .8rem; color: var(--ink-muted, #5b6785); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pf-pager__card--prev .pf-pager__txt { text-align: right; }
.pf-pager__all {
  display: grid; place-items: center; gap: 4px; align-content: center; padding: 14px 26px; border-radius: var(--r-lg); text-decoration: none; font-weight: 700; font-size: .85rem; color: var(--navy-700);
  background: rgba(11, 42, 107, .05); border: 1px dashed rgba(11, 42, 107, .22); transition: background .3s, border-color .3s;
}
.pf-pager__all i { font-size: 1.3rem; color: var(--gold-600); }
.pf-pager__all:hover { background: rgba(253, 185, 19, .12); border-color: var(--gold-500); }
[data-theme="dark"] .pf-pager__card { background: linear-gradient(150deg, rgba(44, 78, 150, .5), rgba(14, 32, 72, .6)); border-color: rgba(255, 255, 255, .14); }
[data-theme="dark"] .pf-pager__txt strong { color: #fff; }
[data-theme="dark"] .pf-pager__all { color: #fff; border-color: rgba(255, 255, 255, .24); background: rgba(255, 255, 255, .05); }
@media (max-width: 860px) { .pf-pager { grid-template-columns: minmax(0, 1fr); } .pf-pager__all { order: 3; grid-auto-flow: column; justify-content: center; } }

/* La barre n'a pas besoin des marges de .portfolio-filters */
.pf-bar .portfolio-filters, .pf-bar .pf-search { margin: 0; }

/* Téléphone : une orbite plus aérée (sans les noms, on touche le module pour l'ouvrir)
   et une barre qui ne reste pas collée (elle mangerait un tiers de l'écran). */
@media (max-width: 640px) {
  .pf-bar { position: relative; top: auto; }
  .pf-eco__stage { height: 420px; }
  .pf-orbit { --R: 128px; --tilt: 34deg; }
  .pf-chip3d { width: 56px; left: -28px; top: -28px; }
  .pf-chip3d__face { width: 50px; height: 50px; border-radius: 15px; }
  .pf-chip3d__name { display: none; }
  .pf-core { width: 96px; height: 96px; margin: -48px 0 0 -48px; } .pf-core b { font-size: 1.1rem; } .pf-core small { font-size: .58rem; }
  .pf-eco__hint { font-size: .62rem; }
}
.pf-eco__hint .h-touch { display: none; }
@media (hover: none) { .pf-eco__hint .h-mouse { display: none; } .pf-eco__hint .h-touch { display: inline; } }

/* cn-mark.css */
/* ----------------------------------------------------------
   cn-mark — le filigrane « logo »
   La FORME EXACTE du logo CyNoLux, dessinée en traits fins : chaque calque réel
   (cn-c.webp, cn-n.webp, cn-ribbon.webp — déjà dans /assets/img, ce sont les
   fichiers de l'écran d'accueil animé) sert de masque, croisé avec un réseau
   d'arcs. Le C et le ruban gardent l'or du logo ; le N, marine, est éclairci
   (un N marine disparaîtrait sur le fond Nuit). Dessous : le logo lui-même, très
   pâle. Un reflet le traverse lentement. Aucun fichier de plus.
   Se pose en absolu derrière un bloc ; la largeur vient du parent.

   Chargé par index, about, services, packs, contact (avant focus.css, qui le
   place dans lp-hero) et par portfolio/ (bandeau page-hero, plus bas).
   ⚠️ POURQUOI un fichier à part : il vivait dans focus.css, que le portfolio ne
   charge pas — et focus.css y masquerait des blocs (data-stagger) que seul
   focus.js révèle.
   ⚠️ POURQUOI :not([data-cn-mark]) : lab.js construit aussi des `.cn-mark`
   (monogramme animé de l'écran de chargement et du rideau entre pages), marqués
   data-cn-mark. Sans ce filtre, ils héritaient du z-index -1 et du tracé
   cn-draw du filigrane.
   ---------------------------------------------------------- */
.cn-mark:not([data-cn-mark]) {
  position: absolute; z-index: -1; aspect-ratio: 1099 / 1002; pointer-events: none;
  animation: cn-draw 1.9s .15s var(--ease) both;
  --cn-stripes: repeating-radial-gradient(ellipse 90% 70% at 50% 130%, #000 0 1.6px, transparent 1.6px 8px);
}
.cn-mark:not([data-cn-mark]) > span { position: absolute; inset: 0; }
.cn-mark__base {
  background: url(../img/cn-c.webp) center / contain no-repeat, url(../img/cn-n.webp) center / contain no-repeat, url(../img/cn-ribbon.webp) center / contain no-repeat;
  opacity: .13;
}
.cn-mark__c, .cn-mark__n, .cn-mark__r {
  opacity: .85;
  -webkit-mask-size: contain, auto; mask-size: contain, auto;
  -webkit-mask-repeat: no-repeat, repeat; mask-repeat: no-repeat, repeat;
  -webkit-mask-position: center, 0 0; mask-position: center, 0 0;
  -webkit-mask-composite: source-in; mask-composite: intersect;
  animation: cn-sweep 9s ease-in-out 1.6s infinite;
}
.cn-mark__c {
  background: linear-gradient(104deg, transparent 40%, #fff 50%, transparent 60%) 130% 0 / 260% 100% no-repeat, linear-gradient(180deg, #FFDA6B, #FDB913 50%, #E5A20D);
  -webkit-mask-image: url(../img/cn-c.webp), var(--cn-stripes); mask-image: url(../img/cn-c.webp), var(--cn-stripes);
}
.cn-mark__n {
  background: linear-gradient(104deg, transparent 40%, #fff 50%, transparent 60%) 130% 0 / 260% 100% no-repeat, linear-gradient(135deg, #DCE8FF, #8FB2FF 55%, #5B86F0);
  -webkit-mask-image: url(../img/cn-n.webp), var(--cn-stripes); mask-image: url(../img/cn-n.webp), var(--cn-stripes);
}
.cn-mark__r {
  background: linear-gradient(104deg, transparent 40%, #fff 50%, transparent 60%) 130% 0 / 260% 100% no-repeat, linear-gradient(90deg, #FFE9A8, #FDB913);
  -webkit-mask-image: url(../img/cn-ribbon.webp), var(--cn-stripes); mask-image: url(../img/cn-ribbon.webp), var(--cn-stripes);
  opacity: 1;
}
@keyframes cn-sweep { from { background-position: 130% 0, 0 0; } to { background-position: -60% 0, 0 0; } }
@keyframes cn-draw { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
.is-paused .cn-mark__c, .is-paused .cn-mark__n, .is-paused .cn-mark__r { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) { .cn-mark:not([data-cn-mark]), .cn-mark__c, .cn-mark__n, .cn-mark__r { animation: none; } }
/* Appareil modeste et téléphone : le reflet repeint toute la silhouette à chaque image — on le fige. */
.cyn-lite .cn-mark__c, .cyn-lite .cn-mark__n, .cyn-lite .cn-mark__r { animation: none; }
@media (max-width: 700px) { .cn-mark__c, .cn-mark__n, .cn-mark__r { animation: none; } }

/* Dans le bandeau à image (Portfolio), à la place de l'ancien sceau tournant.
   ⚠️ POURQUOI z-index 1 : la photo (.ph-media) et la tache dorée sont à 0, le
   texte à 2 ; à -1 (valeur du filigrane), le logo passait sous la photo. */
.page-hero > .cn-mark { z-index: 1; right: 2%; top: 54%; width: min(440px, 28vw); transform: translateY(-50%); }
@media (max-width: 700px) { .page-hero > .cn-mark { right: -34%; width: 112vw; opacity: .4; } }
/* Fiches projet : le contenu centré est bien plus large (paragraphe de 660 px,
   étiquettes, boutons) et passe devant le logo sous ~1800 px (Ysraa, la plus
   large ; mesuré). Le logo pâlit alors derrière le texte, comme sur téléphone. */
@media (max-width: 1800px) { .page-hero:has(.pd-hero-actions) > .cn-mark { opacity: .35; } }
