/* =============================================================================
   NOVAPULSE — DESIGN SYSTEM PUBLIC  (2026-08)
   -----------------------------------------------------------------------------
   Ce fichier est chargé APRÈS style.v16.css, et UNIQUEMENT sur les pages
   publiques. Jamais sur /dashboard.html.

   Pourquoi ce découpage plutôt qu'une réécriture de style.v16.css :
   ce dernier pèse 162 Ko et porte AUSSI les 240 Ko du panel d'administration.
   Y toucher, c'est risquer une régression invisible sur des dizaines d'écrans
   d'admin qu'aucun test ne couvre. Ici, le retour arrière tient en une ligne :
   on retire la balise <link> de la page, et le site retrouve son ancien aspect.

   Ordre de chargement = ordre de priorité. Les règles ci-dessous ont la même
   spécificité que celles de style.v16.css et gagnent parce qu'elles arrivent
   après. `!important` n'est employé QUE là où style.v16.css en pose un lui-même
   (chaque occurrence est commentée).

   Direction artistique : technologique et sobre. Les effets lumineux sont
   réservés aux points de décision (CTA, statut, badges d'état) ; partout
   ailleurs, c'est la hiérarchie typographique qui porte la lecture. Toutes les
   animations sont composables par le GPU (transform / opacity) et se coupent
   sous prefers-reduced-motion.
   ============================================================================= */

/* =============================================================================
   1. JETONS
   ========================================================================== */
:root {
  /* --- Surfaces : bleu très sombre plutôt que gris neutre. Le fond garde une
     dominante froide qui fait ressortir le cyan sans le saturer. --- */
  --np-bg: #06070d;
  --np-bg-1: #0a0c14;
  --np-bg-2: #101320;
  --np-bg-3: #161a2b;
  --np-surface: rgba(19, 23, 38, 0.62);
  --np-surface-solid: #131726;
  --np-surface-hi: rgba(30, 36, 58, 0.72);

  /* --- Accents. Le cyan reste la couleur de marque (favicon, logo, image de
     partage) mais passe de #00f0ff — électrique, fatigant sur de grandes
     surfaces — à un cyan légèrement désaturé, lisible en texte. L'indigo
     remplace le magenta #bd00ff, qui tirait le site vers l'esthétique
     « gaming » alors que le positionnement est professionnel. --- */
  --np-cyan: #22d3ee;
  --np-cyan-soft: #67e8f9;
  --np-cyan-deep: #0891b2;
  --np-indigo: #818cf8;
  --np-violet: #c084fc;
  --np-emerald: #34d399;
  --np-amber: #fbbf24;
  --np-rose: #fb7185;

  /* --- Texte. Contrastes mesurés sur --np-bg-1 :
     --np-text     15.9:1   --np-text-2  8.4:1   --np-text-3  5.1:1
     Les trois passent AA ; --np-text-2 passe AAA pour le corps de texte. --- */
  --np-text: #eef2fb;
  --np-text-2: #aeb9d0;
  --np-text-3: #8290ab;

  --np-line: rgba(129, 140, 248, 0.14);
  --np-line-hi: rgba(34, 211, 238, 0.38);

  /* --- Dégradés de marque --- */
  --np-grad: linear-gradient(120deg, var(--np-cyan) 0%, var(--np-indigo) 55%, var(--np-violet) 100%);
  --np-grad-soft: linear-gradient(120deg, rgba(34, 211, 238, 0.16), rgba(129, 140, 248, 0.12));

  /* --- Rayons : une échelle, pas des valeurs au cas par cas --- */
  --np-r-sm: 10px;
  --np-r: 16px;
  --np-r-lg: 22px;
  --np-r-xl: 30px;
  --np-r-full: 999px;

  /* --- Ombres. Portées franches et sombres : sur fond noir, une ombre grise
     se voit comme un halo sale. --- */
  --np-shadow: 0 18px 50px -18px rgba(0, 0, 0, 0.85);
  --np-shadow-lg: 0 32px 80px -28px rgba(0, 0, 0, 0.92);
  --np-glow: 0 0 0 1px rgba(34, 211, 238, 0.28), 0 12px 44px -12px rgba(34, 211, 238, 0.42);

  /* --- Rythme vertical : une seule échelle pour toutes les sections --- */
  --np-gap: clamp(1rem, 2.2vw, 1.6rem);
  --np-section-y: clamp(4.5rem, 9vw, 8rem);
  --np-max: 1200px;
  --np-max-narrow: 860px;

  --np-ease: cubic-bezier(0.22, 1, 0.36, 1);
  --np-fast: 0.18s var(--np-ease);
  --np-slow: 0.42s var(--np-ease);

  /* =========================================================================
     JETONS HÉRITÉS — le levier le plus important de ce fichier.
     -------------------------------------------------------------------------
     style.v16.css consomme --primary, --accent, --text-muted… dans plusieurs
     CENTAINES de règles : boutons de la page Premium, sommaire de la
     documentation, tableaux du classement, cartes des Légendes, soulignement
     des titres de pied de page… Redéfinir ces variables ici suffit à faire
     basculer toutes ces pages sur la nouvelle palette, sans en réécrire une
     seule règle et sans risquer de casser un composant qu'on n'aurait pas
     ouvert.

     La spécificité est identique (:root dans les deux fichiers) : c'est
     l'ORDRE de chargement qui tranche, et cette feuille arrive en second.
     Le panel, lui, ne la charge pas : il garde sa palette d'origine, donc
     aucune capture d'écran d'administration n'est invalidée.
     ========================================================================= */
  --primary: #22d3ee;
  --primary-hover: #67e8f9;
  --primary-glow: rgba(34, 211, 238, 0.38);
  --accent: #818cf8;
  --accent-glow: rgba(129, 140, 248, 0.42);
  --text-light: #eef2fb;
  --text-muted: #9aa5bb;      /* contraste 5,4:1 sur --bg-main, l'ancien #8e9bb0 était à 4,6:1 */
  --border-color: #1e2437;
  --bg-main: #06070d;
  --bg-card: rgba(19, 23, 38, 0.5);
  --bg-deep: rgba(6, 7, 13, 0.78);
  --bg-sidebar: rgba(10, 12, 20, 0.72);
  --discord-bg: rgba(19, 23, 38, 0.55);
  --discord-embed: rgba(28, 33, 52, 0.6);
}

/* =============================================================================
   2. BASE
   ========================================================================== */
body {
  background-color: var(--np-bg);
  color: var(--np-text);
  font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-feature-settings: 'cv02' 1, 'cv03' 1, 'cv04' 1, 'ss01' 1;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Fond global : deux nappes radiales fixes + une trame technique très discrète.
   Aucune image, aucun GIF — le décor coûte zéro octet de réseau et zéro
   décodage. `position: fixed` sur un pseudo-élément du body évite de repeindre
   quoi que ce soit pendant le défilement.

   ⚠️ LE SÉLECTEUR N'EST PAS `body::before`, ET C'EST OBLIGATOIRE.
   style.v16.css déclare `body:not(.dashboard-body)::before` pour poser quatre
   mascottes en filigrane (4 images, 91 Ko). Sa spécificité est (0,1,2) contre
   (0,0,2) pour un simple `body::before` : arriver après dans l'ordre de
   chargement N'AURAIT PAS SUFFI, la règle la plus spécifique gagne quel que
   soit l'ordre. Le fond de la refonte n'aurait jamais été affiché, et les
   mascottes seraient restées — sans la moindre erreur nulle part.
   En reprenant le MÊME sélecteur, on retombe à spécificité égale, et c'est
   alors l'ordre qui tranche : cette feuille est chargée en second.
   Effet de bord recherché : les quatre images ne sont plus référencées par
   aucune règle appliquée, donc plus téléchargées. */
body:not(.dashboard-body)::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  background:
    radial-gradient(1100px 620px at 12% -8%, rgba(34, 211, 238, 0.13), transparent 62%),
    radial-gradient(950px 560px at 92% 4%, rgba(129, 140, 248, 0.14), transparent 60%),
    radial-gradient(1200px 800px at 50% 108%, rgba(192, 132, 252, 0.08), transparent 65%),
    var(--np-bg);
}

body:not(.dashboard-body)::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.35;
  background-image:
    linear-gradient(rgba(129, 140, 248, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(129, 140, 248, 0.045) 1px, transparent 1px);
  background-size: 64px 64px;
  /* La trame s'efface vers le bas : gardée pleine, elle transforme le bas de
     page en papier millimétré et concurrence le texte. */
  -webkit-mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.9), transparent 78%);
  mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.9), transparent 78%);
}

/* =============================================================================
   MASCOTTE
   -----------------------------------------------------------------------------
   Le robot NovaPulse est CONSERVÉ — il porte le « N » de la marque sur le torse
   et ses éclats cyan sont exactement ceux de la charte. Ce qui change, c'est
   la manière de s'en servir.

   AVANT : quatre exemplaires dispersés aux quatre coins de CHAQUE page, en
   filigrane à 12 % d'opacité et floutés (`.hero-characters` + le fond
   `body::before` de style.v16.css). Quatre images téléchargées partout, quatre
   animations en parallèle, et un résultat qui se lisait comme du remplissage
   décoratif derrière le texte.

   APRÈS : un seul exemplaire, à taille assumée, placé là où il raconte quelque
   chose — il présente la fenêtre de démonstration dans le hero, et salue en
   bas de page. Flottement lent sur `transform` seul, donc entièrement pris en
   charge par le compositeur : aucun recalcul de mise en page pendant
   l'animation.
   ============================================================================= */

/* Le semis en filigrane reste désactivé : c'est la dispersion qui posait
   problème, pas le personnage. */
.hero-characters { display: none !important; } /* style.v16.css les pose en !important */

.np-hero-visuel { position: relative; }

.np-mascotte {
  position: absolute;
  /* DERRIÈRE la fenêtre de démonstration, pas devant. En z-index 3 elle
     recouvrait « Confirmation requise » et le message suivant — capture du
     07/08/2026 : la mascotte occupait 913 px de large là où la carte commence
     à 753 px. Elle dépasse maintenant de derrière le cadre, ce qui se lit
     comme une mise en scène plutôt que comme un calque mal placé. */
  z-index: 1;
  pointer-events: none;
  height: auto;
  /* L'ombre portée suit la couleur de marque : une ombre noire sur fond noir
     ne fait rien, et détacher le personnage du fond est tout l'enjeu. */
  filter: drop-shadow(0 22px 44px rgba(34, 211, 238, 0.28))
          drop-shadow(0 4px 12px rgba(0, 0, 0, 0.6));
  animation: np-flotte 7.5s ease-in-out infinite;
  will-change: transform;
}

/* Amplitude volontairement faible (10 px) et durée longue : au-delà, le regard
   suit la mascotte au lieu de lire le titre juste à côté. */
@keyframes np-flotte {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(-1.5deg); }
  50%      { transform: translate3d(0, -10px, 0) rotate(1.5deg); }
}

/* Halo au sol : donne un point d'appui au personnage, sinon il paraît collé
   sur l'image plutôt que posé dans la scène. */
.np-mascotte::after { content: none; } /* <img> ne peut pas porter de pseudo-élément */
.np-hero-visuel::before {
  content: '';
  position: absolute;
  left: -126px; bottom: -22px;
  width: 180px; height: 40px;
  border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(34, 211, 238, 0.3), transparent 70%);
  filter: blur(10px);
  z-index: 2;
  pointer-events: none;
  animation: np-halo 7.5s ease-in-out infinite;
}
@keyframes np-halo {
  0%, 100% { opacity: 0.85; transform: scaleX(1); }
  50%      { opacity: 0.55; transform: scaleX(0.9); }
}

/* Les fichiers sont recadrés sur le personnage (plus de marge transparente) :
   un décalage en pixels déplace donc bien le robot, et non du vide. C'est ce
   qui permet de le faire dépasser franchement du cadre plutôt que d'en laisser
   apparaître un bout d'antenne. */
.np-mascotte-hero {
  width: 190px;
  left: -132px;
  bottom: -40px;
}

.np-mascotte-cta {
  width: 132px;
  right: clamp(-10px, 2vw, 28px);
  bottom: -8px;
  animation-duration: 9s;
  filter: drop-shadow(0 16px 34px rgba(129, 140, 248, 0.3));
}

/* Sous 1180 px la colonne de gauche se rapproche : la mascotte passerait
   par-dessus le texte. On la ramène à l'intérieur du cadre. */
@media (max-width: 1180px) {
  .np-mascotte-hero { width: 152px; left: -92px; bottom: -30px; }
  .np-hero-visuel::before { left: -84px; width: 150px; }
}

/* Sur téléphone, la démonstration passe pleine largeur : la mascotte se place
   au-dessus, en évidence, plutôt que de mordre sur le bord de l'écran. */
@media (max-width: 980px) {
  .np-mascotte-hero {
    position: relative;
    display: block;
    margin: 0 auto -18px;
    left: auto; bottom: auto;
    width: 150px;
  }
  .np-hero-visuel::before { display: none; }
  .np-mascotte-cta { width: 96px; right: -6px; bottom: -4px; opacity: 0.9; }
}

@media (max-width: 520px) {
  .np-mascotte-hero { width: 122px; }
  /* En dessous de 520 px, le bandeau final est déjà dense : la mascotte y
     deviendrait un obstacle devant le bouton d'installation. */
  .np-mascotte-cta { display: none; }
}

/* Hero historiques (accueil, premium, commandes) : ils chargeaient chacun
   bg_clean.webp — 130 Ko — sous un dégradé quasi opaque (0.85 → 0.98). L'image
   était donc téléchargée pour être recouverte. On la remplace par les mêmes
   nappes que le reste du site, qui ne coûtent rien.
   `background-image: none` plutôt qu'une nouvelle image : c'est la seule
   formulation qui empêche RÉELLEMENT la requête réseau. */
.home-hero,
.premium-hero,
.commands-hero {
  background-image: none !important;
  background-color: transparent;
  padding-top: clamp(6.5rem, 11vw, 9rem) !important;
  padding-bottom: clamp(2.5rem, 5vw, 4rem) !important;
  border-bottom: 1px solid var(--np-line);
}
.premium-hero h1,
.commands-hero h1 {
  font-size: clamp(1.9rem, 4.6vw, 2.9rem);
  letter-spacing: -0.03em;
}
.commands-hero p,
.premium-subtitle {
  color: var(--np-text-2);
  max-width: 60ch;
  margin-inline: auto;
}
/* Les halos décoratifs de ces pages reprennent la nouvelle palette. */
.hero-glow-1 { background: rgba(34, 211, 238, 0.2) !important; }
.hero-glow-2 { background: rgba(129, 140, 248, 0.2) !important; }

h1, h2, h3, h4, h5, h6 {
  color: var(--np-text);
  letter-spacing: -0.022em;
  line-height: 1.14;
  text-wrap: balance;
}

p { text-wrap: pretty; }

a { color: var(--np-cyan-soft); }
a:hover { color: var(--np-cyan); }

::selection {
  background: rgba(34, 211, 238, 0.28);
  color: #fff;
}

/* =============================================================================
   3. ACCESSIBILITÉ
   ========================================================================== */

/* Lien d'évitement : premier élément focusable de chaque page. Invisible tant
   qu'il n'a pas le focus, il évite à un utilisateur au clavier de retraverser
   les 8 liens de navigation à chaque page. */
.np-skip {
  position: absolute;
  left: 50%;
  top: 0;
  transform: translate(-50%, -140%);
  z-index: 2000;
  padding: 0.85rem 1.5rem;
  border-radius: 0 0 var(--np-r) var(--np-r);
  background: var(--np-cyan);
  color: #04121a;
  font-weight: 700;
  text-decoration: none;
  transition: transform var(--np-fast);
}
.np-skip:focus {
  transform: translate(-50%, 0);
  color: #04121a;
}

/* Anneau de focus unique et visible partout. style.v16.css laissait le focus
   par défaut du navigateur, invisible sur fond noir dans plusieurs contextes. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--np-cyan);
  outline-offset: 3px;
  border-radius: 6px;
}

/* Cibles tactiles : 44 px est le minimum recommandé (WCAG 2.5.5). Les liens de
   navigation et de pied de page tombaient sous 30 px sur mobile. */
@media (pointer: coarse) {
  .nav-links a,
  .footer-col ul li a,
  .np-chip {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
}

.np-sr {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* =============================================================================
   4. NAVBAR
   ========================================================================== */
nav {
  height: 68px;
  padding: 0 clamp(1rem, 3vw, 2.25rem);
  background: rgba(6, 7, 13, 0.72);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  backdrop-filter: blur(18px) saturate(150%);
  border-bottom: 1px solid var(--np-line);
  transition: background var(--np-fast), border-color var(--np-fast);
}
/* La navbar se densifie une fois le hero dépassé : posé par navbar.js. */
nav.np-scrolled {
  background: rgba(6, 7, 13, 0.92);
  border-bottom-color: rgba(34, 211, 238, 0.22);
  box-shadow: 0 12px 40px -22px rgba(0, 0, 0, 0.9);
}

nav .logo {
  font-size: 1.16rem;
  font-weight: 750;
  letter-spacing: 0.02em;
  text-transform: none; /* les capitales forcées faisaient « NOVAPULSE » criard */
}
nav .logo img {
  border-color: rgba(34, 211, 238, 0.55) !important; /* style.v16.css : style inline */
  box-shadow: 0 0 18px -4px rgba(34, 211, 238, 0.6);
}

.nav-links { gap: clamp(0.85rem, 1.6vw, 1.5rem); }

.nav-links a.link {
  position: relative;
  font-size: 0.83rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--np-text-2);
  padding: 0.4rem 0;
  transition: color var(--np-fast);
}
.nav-links a.link:hover { color: var(--np-text); }

/* Soulignement animé : scaleX plutôt que width, pour rester sur le compositeur. */
.nav-links a.link::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: -2px;
  height: 2px;
  border-radius: 2px;
  background: var(--np-grad);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--np-fast);
}
.nav-links a.link:hover::after,
.nav-links a.link[aria-current='page']::after { transform: scaleX(1); }
.nav-links a.link[aria-current='page'] { color: var(--np-text); }

/* Sélecteur de langue */
.np-lang-toggle {
  display: inline-flex;
  padding: 3px;
  gap: 2px;
  border: 1px solid var(--np-line);
  border-radius: var(--np-r-full);
  background: rgba(16, 19, 32, 0.7);
}
.np-lang-opt {
  border: 0;
  background: transparent;
  color: var(--np-text-3);
  font: inherit;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  padding: 0.32rem 0.62rem;
  border-radius: var(--np-r-full);
  cursor: pointer;
  transition: color var(--np-fast), background var(--np-fast);
}
.np-lang-opt:hover { color: var(--np-text); }
.np-lang-opt.is-active {
  background: rgba(34, 211, 238, 0.16);
  color: var(--np-cyan-soft);
}

/* Bouton « Panel » de la navbar */
nav .btn-outline {
  border: 1px solid rgba(34, 211, 238, 0.4);
  background: rgba(34, 211, 238, 0.07);
  color: var(--np-cyan-soft);
  font-size: 0.83rem;
  font-weight: 650;
  letter-spacing: 0.02em;
  padding: 0.5rem 1.15rem;
  border-radius: var(--np-r-full);
  transition: background var(--np-fast), border-color var(--np-fast), transform var(--np-fast);
}
nav .btn-outline:hover {
  background: rgba(34, 211, 238, 0.16);
  border-color: var(--np-cyan);
  transform: translateY(-1px);
  color: #fff;
}

/* Éclair « speed-lines » façon manga posé par navbar.js au franchissement du
   hero. Effet d'une identité précédente : sur un site qui met en avant la
   fiabilité et l'audit, un flash de vitesse à chaque défilement dessert le
   propos. Masqué ici, donc sur les pages publiques seulement — le panel, qui
   ne charge pas cette feuille, garde son comportement. */
.np-speedlines { display: none !important; }

/* Burger mobile — injecté par navbar.js */
.nav-burger span { background: var(--np-text); }
.nav-overlay { background: rgba(4, 5, 10, 0.72); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); }

@media (max-width: 900px) {
  nav.nav-open .nav-links {
    background: rgba(8, 10, 18, 0.98);
    -webkit-backdrop-filter: blur(22px);
    backdrop-filter: blur(22px);
    border-left: 1px solid var(--np-line);
  }
}

/* Barre de progression de lecture */
.scroll-progress-container { background: transparent; height: 2px; }
.scroll-progress-bar { background: var(--np-grad); box-shadow: 0 0 12px rgba(34, 211, 238, 0.55); }

/* =============================================================================
   5. BOUTONS
   ========================================================================== */

/* Bouton principal. `.bot-invite` est le nom historique, conservé pour ne pas
   casser les pages qui l'utilisent déjà (404, premium, légendes). */
.np-btn,
.bot-invite,
a.bot-invite {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: 0.92rem 1.7rem;
  font-size: 0.98rem;
  font-weight: 680;
  letter-spacing: 0.005em;
  line-height: 1.2;
  border: 0;
  border-radius: var(--np-r-full);
  text-decoration: none;
  cursor: pointer;
  overflow: hidden;
  isolation: isolate;
  color: #04121a !important; /* style.v16.css force `color: white` sur .bot-invite */
  background: var(--np-grad);
  background-size: 160% 160%;
  box-shadow: 0 10px 30px -12px rgba(34, 211, 238, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.32);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  transition: transform var(--np-fast), box-shadow var(--np-fast), background-position var(--np-slow);
}
.np-btn:hover,
.bot-invite:hover,
a.bot-invite:hover {
  transform: translateY(-2px);
  background-position: 100% 0;
  box-shadow: 0 18px 44px -14px rgba(34, 211, 238, 0.78), inset 0 1px 0 rgba(255, 255, 255, 0.4);
  color: #04121a !important;
  border-color: transparent;
}
.np-btn:active,
.bot-invite:active { transform: translateY(0); }

.np-btn svg,
.bot-invite svg { width: 20px; height: 20px; fill: currentColor; flex-shrink: 0; }

/* Reflet qui balaie le bouton au survol. Une seule couche, transform seul. */
.np-btn::after,
.bot-invite::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(100deg, transparent 30%, rgba(255, 255, 255, 0.45) 50%, transparent 70%);
  transform: translateX(-120%);
  transition: transform 0.7s var(--np-ease);
}
.np-btn:hover::after,
.bot-invite:hover::after { transform: translateX(120%); }

/* Bouton secondaire : contour, sans remplissage. */
.np-btn-ghost,
.btn-secondary-cta,
a.btn-secondary-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  padding: 0.9rem 1.6rem;
  font-size: 0.96rem;
  font-weight: 620;
  color: var(--np-text);
  text-decoration: none;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid var(--np-line);
  border-radius: var(--np-r-full);
  cursor: pointer;
  transition: background var(--np-fast), border-color var(--np-fast), transform var(--np-fast), color var(--np-fast);
}
.np-btn-ghost:hover,
.btn-secondary-cta:hover {
  background: rgba(129, 140, 248, 0.12);
  border-color: rgba(129, 140, 248, 0.45);
  color: #fff;
  transform: translateY(-2px);
}

/* Bouton discret, pour les actions tertiaires */
.np-btn-quiet {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.6rem 0.95rem;
  border-radius: var(--np-r-full);
  border: 1px solid transparent;
  background: transparent;
  color: var(--np-text-2);
  font: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: color var(--np-fast), background var(--np-fast);
}
.np-btn-quiet:hover { color: var(--np-text); background: rgba(255, 255, 255, 0.05); }

.np-btn-lg { padding: 1.05rem 2.1rem; font-size: 1.03rem; }

/* =============================================================================
   6. STRUCTURE DE SECTION
   ========================================================================== */
.np-section {
  position: relative;
  padding: var(--np-section-y) clamp(1.1rem, 4vw, 2.5rem);
}
.np-wrap { max-width: var(--np-max); margin-inline: auto; }
.np-wrap-narrow { max-width: var(--np-max-narrow); margin-inline: auto; }

.np-head { margin-bottom: clamp(2.4rem, 4.5vw, 3.6rem); max-width: 720px; }
.np-head-center { margin-inline: auto; text-align: center; }

.np-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 1rem;
  padding: 0.34rem 0.85rem;
  border: 1px solid var(--np-line);
  border-radius: var(--np-r-full);
  background: rgba(129, 140, 248, 0.08);
  color: var(--np-cyan-soft);
  font-size: 0.73rem;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
}
.np-eyebrow::before {
  content: '';
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--np-cyan);
  box-shadow: 0 0 8px var(--np-cyan);
}

.np-h2 {
  font-size: clamp(1.85rem, 4.2vw, 2.85rem);
  font-weight: 760;
  margin-bottom: 0.9rem;
}
.np-h3 { font-size: clamp(1.12rem, 2vw, 1.28rem); font-weight: 700; }

.np-lead {
  color: var(--np-text-2);
  font-size: clamp(1rem, 1.5vw, 1.1rem);
  line-height: 1.65;
  max-width: 62ch;
}
.np-head-center .np-lead { margin-inline: auto; }

/* Texte en dégradé — réservé aux titres, jamais au corps de texte (un dégradé
   sur un paragraphe fait chuter le contraste sur la moitié des caractères). */
.np-grad-text {
  background: var(--np-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* Repli si background-clip:text n'est pas supporté : sans lui le titre
     serait purement et simplement invisible. */
  -webkit-text-fill-color: transparent;
}
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .np-grad-text { color: var(--np-cyan-soft); -webkit-text-fill-color: currentColor; }
}

/* =============================================================================
   7. CARTES
   ========================================================================== */
.np-card {
  position: relative;
  padding: clamp(1.35rem, 2.4vw, 1.85rem);
  border-radius: var(--np-r-lg);
  background: var(--np-surface);
  border: 1px solid var(--np-line);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  box-shadow: var(--np-shadow);
  transition: transform var(--np-slow), border-color var(--np-slow), box-shadow var(--np-slow);
  overflow: hidden;
}

/* Liseré dégradé sur le bord supérieur, révélé au survol. Fait avec un
   pseudo-élément et non une bordure : une bordure en dégradé impose un
   background-clip qui casse le fond translucide de la carte. */
.np-card::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(34, 211, 238, 0.75), rgba(129, 140, 248, 0.6), transparent);
  opacity: 0;
  transition: opacity var(--np-slow);
}
.np-card:hover {
  transform: translateY(-4px);
  border-color: rgba(129, 140, 248, 0.3);
  box-shadow: var(--np-shadow-lg);
}
.np-card:hover::before { opacity: 1; }

.np-card-title {
  font-size: 1.06rem;
  font-weight: 700;
  margin-bottom: 0.5rem;
}
.np-card-text {
  color: var(--np-text-2);
  font-size: 0.93rem;
  line-height: 1.62;
}

/* Icône de carte : un carré arrondi tramé, pas un emoji. Les emojis rendent
   différemment sur chaque OS et se lisent comme du texte pour un lecteur
   d'écran ; ces icônes sont des SVG marqués aria-hidden. */
.np-ico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px; height: 42px;
  margin-bottom: 1rem;
  border-radius: 12px;
  background: var(--np-grad-soft);
  border: 1px solid var(--np-line);
  color: var(--np-cyan-soft);
  flex-shrink: 0;
}
.np-ico svg { width: 21px; height: 21px; stroke: currentColor; fill: none; stroke-width: 1.7; }
.np-ico-indigo { color: var(--np-indigo); }
.np-ico-violet { color: var(--np-violet); }
.np-ico-emerald { color: var(--np-emerald); }
.np-ico-amber { color: var(--np-amber); }

/* Grilles génériques */
.np-grid { display: grid; gap: var(--np-gap); }
.np-grid-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.np-grid-3 { grid-template-columns: repeat(auto-fit, minmax(268px, 1fr)); }
.np-grid-4 { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }

/* =============================================================================
   8. PASTILLES D'ÉTAT  (disponible / bêta / prévu)
   -----------------------------------------------------------------------------
   Un seul jeu de règles, piloté par l'attribut data-statut. Mettre à jour la
   feuille de route = changer une valeur d'attribut dans le HTML, rien d'autre.
   ========================================================================== */
.np-statut {
  display: inline-flex;
  align-items: center;
  gap: 0.42rem;
  padding: 0.24rem 0.68rem;
  border-radius: var(--np-r-full);
  font-size: 0.71rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap;
  border: 1px solid currentColor;
}
.np-statut::before {
  content: '';
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 7px currentColor;
}
[data-statut='disponible'] .np-statut,
.np-statut[data-statut='disponible'] { color: var(--np-emerald); background: rgba(52, 211, 153, 0.1); }
[data-statut='beta'] .np-statut,
.np-statut[data-statut='beta'] { color: var(--np-amber); background: rgba(251, 191, 36, 0.1); }
[data-statut='prevu'] .np-statut,
.np-statut[data-statut='prevu'] { color: var(--np-text-3); background: rgba(130, 144, 171, 0.1); }
[data-statut='prevu'] .np-statut::before { box-shadow: none; }

/* =============================================================================
   9. HERO
   ========================================================================== */
.np-hero {
  position: relative;
  padding: clamp(7rem, 12vw, 9.5rem) clamp(1.1rem, 4vw, 2.5rem) clamp(3.5rem, 7vw, 6rem);
  overflow: hidden;
}
.np-hero-inner {
  max-width: var(--np-max);
  margin-inline: auto;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}
@media (max-width: 980px) {
  .np-hero-inner { grid-template-columns: 1fr; gap: 2.6rem; }
}

.np-hero-title {
  font-size: clamp(2.15rem, 5.4vw, 3.75rem);
  font-weight: 780;
  line-height: 1.06;
  letter-spacing: -0.032em;
  margin-bottom: 1.15rem;
}
.np-hero-sub {
  color: var(--np-text-2);
  font-size: clamp(1rem, 1.7vw, 1.14rem);
  line-height: 1.66;
  max-width: 54ch;
  margin-bottom: 1.9rem;
}

.np-hero-cta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-bottom: 1.6rem;
}

/* Ligne de réassurance sous les boutons */
.np-hero-proof {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.55rem 1.35rem;
  padding-top: 1.4rem;
  border-top: 1px solid var(--np-line);
  color: var(--np-text-3);
  font-size: 0.845rem;
}
.np-hero-proof li { display: flex; align-items: center; gap: 0.42rem; list-style: none; }
.np-hero-proof svg { width: 15px; height: 15px; stroke: var(--np-emerald); fill: none; stroke-width: 2.2; flex-shrink: 0; }

/* Halos du hero : deux nappes, animation très lente et de faible amplitude.
   `filter: blur()` sur un élément animé est coûteux — ici la taille et le flou
   sont figés, seule l'opacité et la translation varient. */
.np-hero-orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(80px);
  pointer-events: none;
  z-index: 0;
  will-change: transform;
}
.np-hero-orb-1 {
  width: 480px; height: 480px;
  top: -140px; left: -120px;
  background: rgba(34, 211, 238, 0.2);
  animation: np-drift 22s ease-in-out infinite alternate;
}
.np-hero-orb-2 {
  width: 430px; height: 430px;
  top: 120px; right: -140px;
  background: rgba(129, 140, 248, 0.2);
  animation: np-drift 27s ease-in-out infinite alternate-reverse;
}
@keyframes np-drift {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to { transform: translate3d(38px, 34px, 0) scale(1.1); }
}
.np-hero-inner, .np-hero > .np-scroll-hint { position: relative; z-index: 1; }

/* --- Fenêtre de démonstration Discord --- */
.np-demo {
  position: relative;
  z-index: 2;   /* au-dessus de la mascotte : voir la note sur .np-mascotte */
  border-radius: var(--np-r-lg);
  background: linear-gradient(180deg, rgba(22, 26, 43, 0.92), rgba(13, 16, 27, 0.96));
  border: 1px solid var(--np-line);
  box-shadow: var(--np-shadow-lg), 0 0 0 1px rgba(34, 211, 238, 0.08);
  overflow: hidden;
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px);
}
.np-demo-bar {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--np-line);
  background: rgba(10, 12, 20, 0.7);
  font-size: 0.85rem;
}
.np-demo-hash { color: var(--np-text-3); font-weight: 700; }
.np-demo-name { font-weight: 650; color: var(--np-text); }
.np-demo-tag {
  margin-left: auto;
  padding: 0.16rem 0.55rem;
  border-radius: var(--np-r-full);
  background: rgba(129, 140, 248, 0.16);
  border: 1px solid var(--np-line);
  color: var(--np-indigo);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
/* La conversation défile vers le bas à mesure qu'elle se joue, comme un vrai
   salon. Hauteur relevée de 420 à 500 px : à 420, la scène d'ouverture — la
   sanction appliquée et sa ligne d'audit — était déjà sortie du cadre quand la
   dernière réponse arrivait, et c'est précisément la démonstration qu'on veut
   montrer. */
.np-demo-body {
  min-height: 360px;
  max-height: 500px;
  padding: 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  overflow: hidden;
}

.np-msg { display: flex; gap: 0.7rem; animation: np-msg-in 0.4s var(--np-ease) both; }
@keyframes np-msg-in {
  from { opacity: 0; transform: translateY(9px); }
  to { opacity: 1; transform: none; }
}
.np-msg-av {
  width: 34px; height: 34px;
  border-radius: 50%;
  flex-shrink: 0;
  object-fit: cover;
  background: var(--np-bg-3);
  border: 1px solid var(--np-line);
}
.np-msg-av-user {
  display: grid;
  place-items: center;
  background: linear-gradient(135deg, #475569, #334155);
  color: #cbd5e1;
  font-size: 0.78rem;
  font-weight: 700;
}
.np-msg-body { min-width: 0; flex: 1; }
.np-msg-head { display: flex; align-items: baseline; gap: 0.45rem; margin-bottom: 0.16rem; }
.np-msg-author { font-size: 0.87rem; font-weight: 650; color: #e2e8f0; }
.np-msg-author.is-bot { color: var(--np-cyan-soft); }
.np-msg-bot-tag {
  padding: 0.05rem 0.32rem;
  border-radius: 4px;
  background: var(--np-cyan-deep);
  color: #f0fdff;
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.04em;
}
.np-msg-time { font-size: 0.68rem; color: var(--np-text-3); }
.np-msg-text { font-size: 0.885rem; line-height: 1.55; color: #cbd5e1; word-wrap: break-word; }
.np-msg-text strong { color: #fff; font-weight: 650; }
.np-msg-text code {
  padding: 0.1rem 0.32rem;
  border-radius: 4px;
  background: rgba(129, 140, 248, 0.14);
  color: var(--np-cyan-soft);
  font-size: 0.85em;
  font-family: ui-monospace, 'SF Mono', Menlo, monospace;
}

/* Encart « action exécutée » : ce que le bot rend vraiment dans Discord. */
.np-msg-embed {
  margin-top: 0.5rem;
  padding: 0.65rem 0.85rem;
  border-radius: 8px;
  border-left: 3px solid var(--np-emerald);
  background: rgba(52, 211, 153, 0.07);
  font-size: 0.82rem;
  color: var(--np-text-2);
}
.np-msg-embed-title {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--np-emerald);
  font-weight: 650;
  margin-bottom: 0.22rem;
}
.np-msg-embed-title svg { width: 14px; height: 14px; stroke: currentColor; fill: none; stroke-width: 2.4; }
.np-msg-embed.is-warn { border-left-color: var(--np-amber); background: rgba(251, 191, 36, 0.07); }
.np-msg-embed.is-warn .np-msg-embed-title { color: var(--np-amber); }

/* Indicateur de frappe */
.np-typing { display: inline-flex; gap: 4px; padding: 0.35rem 0; }
.np-typing span {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--np-text-3);
  animation: np-typing 1.3s infinite;
}
.np-typing span:nth-child(2) { animation-delay: 0.16s; }
.np-typing span:nth-child(3) { animation-delay: 0.32s; }
@keyframes np-typing {
  0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-3px); }
}

/* Indication de défilement */
.np-scroll-hint {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  margin: clamp(2.5rem, 5vw, 4rem) auto 0;
  padding: 0.5rem;
  background: none;
  border: 0;
  color: var(--np-text-3);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color var(--np-fast);
}
.np-scroll-hint:hover { color: var(--np-cyan-soft); }
.np-scroll-hint svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 2; animation: np-bob 2.2s ease-in-out infinite; }
@keyframes np-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(5px); } }

/* =============================================================================
   10. BANDEAU « EN DIRECT »
   ========================================================================== */
.np-live {
  padding: clamp(1.5rem, 3vw, 2.2rem) clamp(1.1rem, 4vw, 2.5rem);
  border-block: 1px solid var(--np-line);
  background: linear-gradient(180deg, rgba(16, 19, 32, 0.7), rgba(10, 12, 20, 0.45));
}
.np-live-inner { max-width: var(--np-max); margin-inline: auto; }
.np-live-title {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  margin-bottom: 1.25rem;
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--np-text-3);
}
.np-live-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--np-emerald);
  box-shadow: 0 0 0 0 rgba(52, 211, 153, 0.6);
  animation: np-pulse 2.4s infinite;
}
@keyframes np-pulse {
  0% { box-shadow: 0 0 0 0 rgba(52, 211, 153, 0.55); }
  70% { box-shadow: 0 0 0 9px rgba(52, 211, 153, 0); }
  100% { box-shadow: 0 0 0 0 rgba(52, 211, 153, 0); }
}
.np-live-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1px;
  background: var(--np-line);
  border: 1px solid var(--np-line);
  border-radius: var(--np-r);
  overflow: hidden;
}
.np-live-tile {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  padding: 1.1rem 1.25rem;
  background: rgba(10, 12, 20, 0.72);
}
.np-live-tile dt {
  order: 2;
  font-size: 0.76rem;
  color: var(--np-text-3);
  letter-spacing: 0.01em;
}
.np-live-tile dd {
  order: 1;
  margin: 0;
  font-size: clamp(1.45rem, 3vw, 1.9rem);
  font-weight: 720;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--np-text);
}
.np-live-unit { font-size: 0.62em; color: var(--np-text-3); margin-left: 0.12em; font-weight: 600; }
.np-live-value-text { font-size: clamp(1.05rem, 2vw, 1.25rem) !important; color: var(--np-emerald) !important; }
.np-live-note { margin-top: 0.85rem; font-size: 0.78rem; color: var(--np-text-3); }

/* Entrée en cascade, pilotée par --retard depuis le JS */
.np-live-tile { opacity: 0; transform: translateY(10px); }
.np-live-tile.np-in { animation: np-tile-in 0.5s var(--np-ease) forwards; animation-delay: var(--retard, 0ms); }
@keyframes np-tile-in { to { opacity: 1; transform: none; } }

/* =============================================================================
   11. AGENTS IA
   ========================================================================== */
.np-agent {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  padding: clamp(1.4rem, 2.5vw, 1.9rem);
}
.np-agent-head { display: flex; align-items: center; gap: 0.85rem; }
.np-agent-name { font-size: 1.08rem; font-weight: 700; margin: 0; }
.np-agent-role { font-size: 0.78rem; color: var(--np-cyan-soft); font-weight: 600; letter-spacing: 0.03em; }
.np-agent-body { color: var(--np-text-2); font-size: 0.92rem; line-height: 1.62; }

/* Bloc « limites » : dit ce que l'agent NE fait pas. C'est la partie qui donne
   sa crédibilité à la section — une fiche produit qui n'annonce que des
   capacités se lit comme une brochure. */
.np-agent-limits {
  margin-top: auto;
  padding: 0.75rem 0.9rem;
  border-radius: var(--np-r-sm);
  background: rgba(129, 140, 248, 0.06);
  border: 1px solid var(--np-line);
  font-size: 0.82rem;
  color: var(--np-text-3);
  line-height: 1.55;
}
.np-agent-limits strong { color: var(--np-text-2); font-weight: 650; }

.np-agent-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}
.np-chip {
  padding: 0.24rem 0.6rem;
  border-radius: var(--np-r-full);
  background: rgba(255, 255, 255, 0.045);
  border: 1px solid var(--np-line);
  color: var(--np-text-3);
  font-size: 0.72rem;
  font-weight: 600;
  white-space: nowrap;
}

/* =============================================================================
   12. FONCTIONNEMENT (étapes)
   ========================================================================== */
.np-steps {
  display: grid;
  gap: clamp(1rem, 2vw, 1.4rem);
  grid-template-columns: repeat(auto-fit, minmax(215px, 1fr));
  counter-reset: np-step;
}
.np-step {
  position: relative;
  padding: 1.6rem 1.35rem 1.35rem;
  border-radius: var(--np-r-lg);
  background: var(--np-surface);
  border: 1px solid var(--np-line);
  transition: border-color var(--np-slow), transform var(--np-slow);
}
.np-step:hover { border-color: rgba(34, 211, 238, 0.3); transform: translateY(-3px); }
.np-step::before {
  counter-increment: np-step;
  content: counter(np-step, decimal-leading-zero);
  display: block;
  margin-bottom: 0.85rem;
  font-size: 1.55rem;
  font-weight: 780;
  letter-spacing: -0.03em;
  background: var(--np-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.np-step h3 { font-size: 1rem; margin-bottom: 0.42rem; }
.np-step p { color: var(--np-text-2); font-size: 0.885rem; line-height: 1.58; }

/* =============================================================================
   13. SÉCURITÉ
   ========================================================================== */
.np-secu {
  display: grid;
  gap: clamp(1.6rem, 4vw, 3rem);
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
  align-items: start;
}
@media (max-width: 900px) { .np-secu { grid-template-columns: 1fr; } }

.np-secu-list { display: grid; gap: 0.75rem; list-style: none; padding: 0; margin: 0; }
.np-secu-item {
  display: flex;
  gap: 0.9rem;
  padding: 1rem 1.15rem;
  border-radius: var(--np-r);
  background: var(--np-surface);
  border: 1px solid var(--np-line);
  transition: border-color var(--np-fast), background var(--np-fast);
}
.np-secu-item:hover { border-color: rgba(52, 211, 153, 0.3); background: var(--np-surface-hi); }
.np-secu-item svg {
  width: 19px; height: 19px;
  flex-shrink: 0;
  margin-top: 2px;
  stroke: var(--np-emerald);
  fill: none;
  stroke-width: 2;
}
.np-secu-item h3 { font-size: 0.96rem; margin-bottom: 0.25rem; }
.np-secu-item p { color: var(--np-text-2); font-size: 0.865rem; line-height: 1.55; }

/* Encart de code / trace d'audit */
.np-audit {
  border-radius: var(--np-r-lg);
  border: 1px solid var(--np-line);
  background: rgba(8, 10, 17, 0.85);
  overflow: hidden;
  box-shadow: var(--np-shadow);
}
.np-audit-head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.7rem 1rem;
  border-bottom: 1px solid var(--np-line);
  background: rgba(16, 19, 32, 0.75);
  font-size: 0.75rem;
  font-weight: 650;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--np-text-3);
}
.np-audit-body {
  margin: 0;
  padding: 1rem;
  font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  font-size: 0.78rem;
  line-height: 1.85;
  color: var(--np-text-2);
  overflow-x: auto;
}
.np-audit-body .k { color: var(--np-indigo); }
.np-audit-body .s { color: var(--np-emerald); }
.np-audit-body .w { color: var(--np-amber); }
.np-audit-body .m { color: var(--np-text-3); }

/* =============================================================================
   14. COMPARAISON
   ========================================================================== */
.np-compare-scroll {
  overflow-x: auto;
  border-radius: var(--np-r-lg);
  border: 1px solid var(--np-line);
  -webkit-overflow-scrolling: touch;
}
.np-compare {
  width: 100%;
  min-width: 620px;
  border-collapse: collapse;
  background: rgba(13, 16, 27, 0.72);
  font-size: 0.9rem;
}
.np-compare th,
.np-compare td {
  padding: 0.9rem 1.05rem;
  text-align: left;
  border-bottom: 1px solid var(--np-line);
  vertical-align: top;
}
.np-compare thead th {
  position: sticky;
  top: 0;
  background: rgba(16, 19, 32, 0.96);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--np-text-3);
  z-index: 1;
}
.np-compare thead th.is-nova { color: var(--np-cyan-soft); }
.np-compare tbody th {
  font-weight: 620;
  color: var(--np-text);
  font-size: 0.88rem;
}
.np-compare td { color: var(--np-text-2); }
.np-compare td.is-nova {
  color: var(--np-text);
  background: linear-gradient(90deg, rgba(34, 211, 238, 0.07), rgba(129, 140, 248, 0.05));
  border-left: 1px solid rgba(34, 211, 238, 0.18);
}
.np-compare tbody tr:last-child th,
.np-compare tbody tr:last-child td { border-bottom: 0; }
.np-compare-note { margin-top: 0.9rem; font-size: 0.8rem; color: var(--np-text-3); }

/* =============================================================================
   15. FEUILLE DE ROUTE
   -----------------------------------------------------------------------------
   Pour la mettre à jour : changer data-statut sur le <li>, ou déplacer le <li>.
   Aucune autre modification n'est nécessaire — la couleur, la pastille et le
   libellé suivent l'attribut.
   ========================================================================== */
.np-road { display: grid; gap: 0.7rem; list-style: none; padding: 0; margin: 0; }
.np-road-item {
  display: grid;
  grid-template-columns: 122px minmax(0, 1fr);
  gap: 1.1rem;
  align-items: start;
  padding: 1rem 1.2rem;
  border-radius: var(--np-r);
  background: var(--np-surface);
  border: 1px solid var(--np-line);
  border-left: 3px solid transparent;
  transition: border-color var(--np-fast), background var(--np-fast);
}
.np-road-item[data-statut='disponible'] { border-left-color: var(--np-emerald); }
.np-road-item[data-statut='beta'] { border-left-color: var(--np-amber); }
.np-road-item[data-statut='prevu'] { border-left-color: rgba(130, 144, 171, 0.5); }
.np-road-item:hover { background: var(--np-surface-hi); }
.np-road-item h3 { font-size: 0.97rem; margin-bottom: 0.24rem; }
.np-road-item p { color: var(--np-text-2); font-size: 0.865rem; line-height: 1.55; }
@media (max-width: 620px) {
  .np-road-item { grid-template-columns: 1fr; gap: 0.6rem; }
}

/* =============================================================================
   16. APERÇU DU TABLEAU DE BORD
   ========================================================================== */
.np-panel-preview {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  gap: clamp(1.6rem, 4vw, 3rem);
  align-items: center;
}
@media (max-width: 900px) { .np-panel-preview { grid-template-columns: 1fr; } }

.np-panel-mock {
  border-radius: var(--np-r-lg);
  border: 1px solid var(--np-line);
  background: linear-gradient(180deg, rgba(19, 23, 38, 0.92), rgba(10, 12, 20, 0.96));
  box-shadow: var(--np-shadow-lg);
  overflow: hidden;
}
.np-panel-mock-bar {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.65rem 0.9rem;
  border-bottom: 1px solid var(--np-line);
  background: rgba(8, 10, 17, 0.8);
}
.np-panel-dot { width: 9px; height: 9px; border-radius: 50%; background: rgba(130, 144, 171, 0.35); }
.np-panel-dot:first-child { background: rgba(251, 113, 133, 0.55); }
.np-panel-dot:nth-child(2) { background: rgba(251, 191, 36, 0.55); }
.np-panel-dot:nth-child(3) { background: rgba(52, 211, 153, 0.55); }
.np-panel-url {
  margin-left: 0.6rem;
  padding: 0.16rem 0.65rem;
  border-radius: var(--np-r-full);
  background: rgba(255, 255, 255, 0.04);
  color: var(--np-text-3);
  font-size: 0.7rem;
  font-family: ui-monospace, monospace;
}
.np-panel-mock-body { display: grid; grid-template-columns: 88px minmax(0, 1fr); min-height: 260px; }
.np-panel-side {
  padding: 0.9rem 0.6rem;
  border-right: 1px solid var(--np-line);
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}
.np-panel-side i {
  height: 22px;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.045);
}
.np-panel-side i.is-on { background: var(--np-grad-soft); box-shadow: inset 0 0 0 1px rgba(34, 211, 238, 0.28); }
.np-panel-main { padding: 1rem; display: grid; gap: 0.7rem; align-content: start; }
.np-panel-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.8rem;
  padding: 0.7rem 0.85rem;
  border-radius: var(--np-r-sm);
  background: rgba(255, 255, 255, 0.028);
  border: 1px solid var(--np-line);
  font-size: 0.8rem;
  color: var(--np-text-2);
}
.np-panel-switch {
  width: 34px; height: 19px;
  border-radius: var(--np-r-full);
  background: rgba(130, 144, 171, 0.28);
  position: relative;
  flex-shrink: 0;
}
.np-panel-switch::after {
  content: '';
  position: absolute;
  top: 2px; left: 2px;
  width: 15px; height: 15px;
  border-radius: 50%;
  background: #9aa5bb;
  transition: transform var(--np-fast);
}
.np-panel-switch.is-on { background: rgba(34, 211, 238, 0.42); }
.np-panel-switch.is-on::after { transform: translateX(15px); background: var(--np-cyan-soft); }

.np-feature-list { display: grid; gap: 0.65rem; list-style: none; padding: 0; margin: 1.4rem 0 0; }
.np-feature-list li {
  display: flex;
  gap: 0.65rem;
  align-items: flex-start;
  color: var(--np-text-2);
  font-size: 0.92rem;
  line-height: 1.55;
}
.np-feature-list svg {
  width: 17px; height: 17px;
  flex-shrink: 0;
  margin-top: 3px;
  stroke: var(--np-cyan);
  fill: none;
  stroke-width: 2.4;
}

/* =============================================================================
   17. FAQ
   ========================================================================== */
.np-faq { display: grid; gap: 0.6rem; }
.np-faq-item {
  border-radius: var(--np-r);
  border: 1px solid var(--np-line);
  background: var(--np-surface);
  overflow: hidden;
  transition: border-color var(--np-fast);
}
.np-faq-item:hover { border-color: rgba(129, 140, 248, 0.28); }
.np-faq-item.is-open { border-color: rgba(34, 211, 238, 0.32); background: var(--np-surface-hi); }
.np-faq-q {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.05rem 1.3rem;
  background: none;
  border: 0;
  color: var(--np-text);
  font: inherit;
  font-size: 0.98rem;
  font-weight: 620;
  text-align: left;
  cursor: pointer;
}
.np-faq-icon {
  position: relative;
  width: 16px; height: 16px;
  flex-shrink: 0;
}
/* Un « + » qui devient « − » : deux traits, une rotation. Plus lisible qu'un
   chevron pour dire « ceci se déplie ». */
.np-faq-icon::before,
.np-faq-icon::after {
  content: '';
  position: absolute;
  inset: 50% 0 auto 0;
  height: 2px;
  border-radius: 2px;
  background: var(--np-cyan);
  transition: transform var(--np-fast), opacity var(--np-fast);
}
.np-faq-icon::after { transform: rotate(90deg); }
.is-open .np-faq-icon::after { transform: rotate(0deg); opacity: 0; }

/* grid-template-rows 0fr -> 1fr : anime une hauteur inconnue sans max-height
   arbitraire (une max-height trop courte tronque, trop longue rend l'animation
   molle). Repli plus bas pour les navigateurs sans support. */
.np-faq-a {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.3s var(--np-ease);
}
.is-open .np-faq-a { grid-template-rows: 1fr; }
.np-faq-a > div { overflow: hidden; }
.np-faq-a p {
  padding: 0 1.3rem 1.2rem;
  color: var(--np-text-2);
  font-size: 0.92rem;
  line-height: 1.68;
}
@supports not (grid-template-rows: 0fr) {
  .np-faq-a { display: block; height: 0; overflow: hidden; }
  .is-open .np-faq-a { height: auto; }
}

/* =============================================================================
   18. CTA FINAL
   ========================================================================== */
.np-cta {
  position: relative;
  padding: clamp(2.6rem, 6vw, 4.2rem) clamp(1.4rem, 5vw, 3.5rem);
  border-radius: var(--np-r-xl);
  border: 1px solid var(--np-line-hi);
  background:
    radial-gradient(700px 320px at 50% 0%, rgba(34, 211, 238, 0.15), transparent 70%),
    linear-gradient(180deg, rgba(19, 23, 38, 0.9), rgba(10, 12, 20, 0.94));
  text-align: center;
  overflow: hidden;
  box-shadow: var(--np-shadow-lg);
}
.np-cta h2 { font-size: clamp(1.6rem, 3.6vw, 2.35rem); margin-bottom: 0.85rem; }
.np-cta p { color: var(--np-text-2); max-width: 54ch; margin: 0 auto 1.9rem; line-height: 1.65; }
.np-cta-row { display: flex; flex-wrap: wrap; gap: 0.75rem; justify-content: center; }
.np-cta-note { margin-top: 1.5rem !important; font-size: 0.82rem; color: var(--np-text-3); }

/* =============================================================================
   19. PIED DE PAGE
   ========================================================================== */
.footer-wrapper {
  position: relative;
  margin-top: 0;
  padding: clamp(3rem, 6vw, 4.5rem) clamp(1.1rem, 4vw, 2.5rem) 0;
  background: linear-gradient(180deg, transparent, rgba(8, 10, 17, 0.9) 30%);
  border-top: 1px solid var(--np-line);
}
.footer-shadow-svg { display: none; } /* vestige : une ombre SVG en biais, hors sujet */

.footer-inner {
  max-width: var(--np-max);
  margin-inline: auto;
  display: grid;
  grid-template-columns: minmax(220px, 1.5fr) repeat(auto-fit, minmax(150px, 1fr));
  gap: clamp(1.8rem, 4vw, 3rem);
  padding: 0 0 2.5rem;
}
@media (max-width: 720px) {
  .footer-inner { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
  .footer-logo-col { grid-column: 1 / -1; }
}

.footer-logo-col p { color: var(--np-text-3); }
.footer-logo-mark {
  width: 40px; height: 40px;
  border-radius: 11px;
  border: 1px solid var(--np-line-hi);
  object-fit: cover;
}
.np-footer-brand { font-size: 1.05rem; font-weight: 720; margin-top: 0.8rem; }
.np-footer-tag { font-size: 0.87rem; line-height: 1.6; margin-top: 0.4rem; max-width: 34ch; }

.footer-col h3 {
  font-size: 0.73rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--np-text-3);
  margin-bottom: 1rem;
}
.footer-col ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.55rem; }
.footer-col ul li a {
  color: var(--np-text-2);
  font-size: 0.885rem;
  text-decoration: none;
  transition: color var(--np-fast);
}
.footer-col ul li a:hover { color: var(--np-cyan-soft); }

/* Petit repère « ↗ » sur les liens qui quittent le site. */
.footer-col ul li a[target='_blank']::after,
.np-ext::after {
  content: '↗';
  margin-left: 0.28em;
  font-size: 0.82em;
  color: var(--np-text-3);
}

.footer-bottom {
  max-width: var(--np-max);
  margin-inline: auto;
  padding: 1.3rem 0;
  border-top: 1px solid var(--np-line);
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 1.2rem;
  align-items: center;
  justify-content: space-between;
  color: var(--np-text-3);
  font-size: 0.8rem;
}
.np-footer-social { display: flex; gap: 0.5rem; }
.np-footer-social a {
  display: grid;
  place-items: center;
  width: 34px; height: 34px;
  border-radius: 10px;
  border: 1px solid var(--np-line);
  color: var(--np-text-3);
  transition: color var(--np-fast), border-color var(--np-fast), background var(--np-fast);
}
.np-footer-social a:hover { color: var(--np-cyan-soft); border-color: var(--np-line-hi); background: rgba(34, 211, 238, 0.08); }
.np-footer-social svg { width: 17px; height: 17px; fill: currentColor; }
.np-footer-social a::after { content: none; }

/* =============================================================================
   20. BANDEAU D'ALERTE  (retours OAuth, indisponibilités)
   -----------------------------------------------------------------------------
   Posé par js/np-erreurs.js. Sans lui, /?error=invalid_state renvoyait le
   visiteur sur l'accueil sans le moindre message.
   ========================================================================== */
.np-alert {
  position: relative;
  z-index: 900;
  max-width: var(--np-max);
  margin: 84px auto 0;
  display: flex;
  gap: 0.85rem;
  align-items: flex-start;
  padding: 1rem 1.2rem;
  border-radius: var(--np-r);
  border: 1px solid rgba(251, 191, 36, 0.35);
  background: rgba(251, 191, 36, 0.09);
  color: var(--np-text);
  animation: np-alert-in 0.35s var(--np-ease) both;
}
@keyframes np-alert-in { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }
.np-alert svg { width: 20px; height: 20px; flex-shrink: 0; margin-top: 1px; stroke: var(--np-amber); fill: none; stroke-width: 2; }
.np-alert-body { flex: 1; min-width: 0; }
.np-alert-title { font-weight: 680; font-size: 0.95rem; margin-bottom: 0.2rem; }
.np-alert-text { color: var(--np-text-2); font-size: 0.875rem; line-height: 1.55; }
.np-alert-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.8rem; }
.np-alert-close {
  flex-shrink: 0;
  background: none;
  border: 0;
  color: var(--np-text-3);
  font-size: 1.3rem;
  line-height: 1;
  padding: 0 0.2rem;
  cursor: pointer;
}
.np-alert-close:hover { color: var(--np-text); }
.np-alert.is-error { border-color: rgba(251, 113, 133, 0.38); background: rgba(251, 113, 133, 0.09); }
.np-alert.is-error svg { stroke: var(--np-rose); }
.np-alert.is-info { border-color: var(--np-line-hi); background: rgba(34, 211, 238, 0.08); }
.np-alert.is-info svg { stroke: var(--np-cyan); }

/* Le hero suit immédiatement le bandeau quand celui-ci est affiché : sans ça,
   le padding haut du hero s'ajoute à la marge du bandeau. */
.np-alert ~ main .np-hero { padding-top: clamp(2.5rem, 5vw, 4rem); }

/* =============================================================================
   21. PAGE DE STATUT
   ========================================================================== */
.np-status-hero { padding: clamp(6.5rem, 11vw, 8.5rem) clamp(1.1rem, 4vw, 2.5rem) 0; }
.np-status-card {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1.4rem 1.6rem;
  border-radius: var(--np-r-lg);
  border: 1px solid var(--np-line);
  background: var(--np-surface);
}
.np-status-card.is-up { border-color: rgba(52, 211, 153, 0.35); background: rgba(52, 211, 153, 0.07); }
.np-status-card.is-down { border-color: rgba(251, 113, 133, 0.35); background: rgba(251, 113, 133, 0.07); }
.np-status-card.is-unknown { border-color: rgba(251, 191, 36, 0.32); background: rgba(251, 191, 36, 0.07); }
.np-status-led {
  width: 13px; height: 13px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--np-text-3);
}
.is-up .np-status-led { background: var(--np-emerald); box-shadow: 0 0 0 0 rgba(52, 211, 153, 0.6); animation: np-pulse 2.4s infinite; }
.is-down .np-status-led { background: var(--np-rose); }
.is-unknown .np-status-led { background: var(--np-amber); }
.np-status-label { font-size: 1.1rem; font-weight: 700; }
.np-status-sub { color: var(--np-text-2); font-size: 0.88rem; margin-top: 0.15rem; }

.np-status-rows { display: grid; gap: 0.6rem; margin-top: 1.4rem; }
.np-status-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.95rem 1.2rem;
  border-radius: var(--np-r);
  border: 1px solid var(--np-line);
  background: var(--np-surface);
  font-size: 0.92rem;
}
.np-status-row-name { display: flex; flex-direction: column; gap: 0.15rem; }
.np-status-row-name small { color: var(--np-text-3); font-size: 0.79rem; }
.np-status-row-val { font-weight: 650; font-variant-numeric: tabular-nums; white-space: nowrap; }
.np-status-row-val.is-ok { color: var(--np-emerald); }
.np-status-row-val.is-warn { color: var(--np-amber); }
.np-status-row-val.is-ko { color: var(--np-rose); }
.np-status-row-val.is-na { color: var(--np-text-3); font-weight: 500; }

/* Squelettes de chargement : un état de chargement explicite vaut mieux qu'un
   « 0 » qui se lit comme une panne. */
.np-skel {
  display: inline-block;
  min-width: 62px; height: 1em;
  border-radius: 5px;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.11), rgba(255, 255, 255, 0.05));
  background-size: 200% 100%;
  animation: np-skel 1.3s linear infinite;
  vertical-align: middle;
}
@keyframes np-skel { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* =============================================================================
   22. PAGES D'ERREUR (404 / 500)
   ========================================================================== */
.np-error {
  min-height: 68vh;
  display: grid;
  place-content: center;
  justify-items: center;
  text-align: center;
  gap: 0.9rem;
  padding: clamp(7rem, 12vw, 9rem) clamp(1.2rem, 5vw, 2.5rem) clamp(4rem, 8vw, 6rem);
}
.np-error-code {
  font-size: clamp(4.5rem, 15vw, 8.5rem);
  font-weight: 800;
  line-height: 0.9;
  letter-spacing: -0.05em;
  background: var(--np-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.np-error h1 { font-size: clamp(1.4rem, 3.5vw, 2rem); }
.np-error p { color: var(--np-text-2); max-width: 50ch; line-height: 1.65; }
.np-error .np-cta-row { margin-top: 1rem; }
.np-error-links { margin-top: 1.6rem; display: flex; flex-wrap: wrap; gap: 0.4rem 1.2rem; justify-content: center; font-size: 0.86rem; }

/* =============================================================================
   23. RÉVÉLATION AU DÉFILEMENT
   ========================================================================== */
/* ⚠️ L'ÉTAT PAR DÉFAUT EST VISIBLE, et ce n'est pas un détail de confort.
   style.v16.css déclare `.scroll-reveal { opacity: 0 }` : le contenu n'existe
   à l'écran que si un IntersectionObserver vient poser la classe `active`.
   Sans JavaScript — script bloqué, erreur en amont, robot d'indexation sans
   exécution — la page entière se réduit donc au hero, et tout le reste est un
   grand rectangle noir. Constaté en capture le 07/08/2026 : 10 881 px de haut,
   dont 9 500 vides.

   On inverse : visible par défaut, masqué UNIQUEMENT là où un script peut
   effectivement révéler. `scripting: enabled` est la requête média prévue
   exactement pour ça ; un navigateur qui ne la connaît pas n'applique pas le
   bloc, donc affiche tout — le repli va dans le bon sens. */
.scroll-reveal,
.np-reveal {
  opacity: 1;
  transform: none;
  transition: opacity 0.55s var(--np-ease), transform 0.55s var(--np-ease);
}
@media (scripting: enabled) {
  .scroll-reveal:not(.active),
  .np-reveal:not(.active) {
    opacity: 0;
    transform: translateY(16px);
  }
}
.scroll-reveal.active,
.np-reveal.active { opacity: 1; transform: none; }
/* Décalage en cascade à l'intérieur d'une grille */
.np-reveal-stagger > * { transition-delay: calc(var(--np-i, 0) * 70ms); }

/* =============================================================================
   24. MOUVEMENT RÉDUIT
   -----------------------------------------------------------------------------
   Coupure globale. `scroll-behavior: auto` compris : un défilement animé est
   aussi un mouvement, et c'est celui qui déclenche le plus de malaises
   vestibulaires.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  html { scroll-behavior: auto !important; }
  .scroll-reveal, .np-reveal, .np-live-tile { opacity: 1 !important; transform: none !important; }
  .np-hero-orb { animation: none !important; }
  .np-btn::after, .bot-invite::after { display: none; }
  /* La mascotte reste AFFICHÉE, seul son flottement s'arrête : c'est le
     mouvement qui gêne, pas le personnage. La supprimer priverait ces
     visiteurs d'un élément d'identité sans aucune contrepartie. */
  .np-mascotte, .np-hero-visuel::before { animation: none !important; }
}

/* Défilement doux + décalage d'ancre sous la navbar fixe (68 px + air). */
html { scroll-behavior: smooth; }
:target, [id] { scroll-margin-top: 92px; }

/* =============================================================================
   25. IMPRESSION
   ========================================================================== */
@media print {
  body::before, body::after, nav, .footer-wrapper, .np-scroll-hint,
  .scroll-progress-container, #nova-asst { display: none !important; }
  body { background: #fff; color: #111; }
  .np-card, .np-step, .np-road-item { border: 1px solid #ccc; background: #fff; box-shadow: none; }
  h1, h2, h3, .np-grad-text, .np-error-code { color: #111 !important; -webkit-text-fill-color: #111 !important; }
}
