/* ==========================================================================
   Nymphea App — couche d'interactions (chargée après styles.css)
   1. Halo de la transition jour / nuit
   2. Spotlight qui suit le curseur sur les cartes et panneaux
   3. Navigation : fond actif qui glisse d'un onglet à l'autre
   4. Connexion : filigrane, lueur, bordure lumineuse, majuscules, secousse
   5. Lisibilité : micro-textes relevés
   Tout est décoratif et coupé en mouvement réduit.
   ========================================================================== */

@property --nx-angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

/* ---------- 1. Halo jour / nuit ---------- */
.theme-halo {
  position: fixed;
  z-index: 2147483647;
  border-radius: 50%;
  pointer-events: none;
  transform: scale(0);
  will-change: transform, opacity;
}
.theme-halo-dark {
  border: 2px solid rgba(214, 170, 255, 0.85);
  box-shadow:
    inset 0 0 28px 6px rgba(190, 130, 250, 0.55),
    inset 0 0 120px 40px rgba(120, 60, 200, 0.35),
    0 0 60px 20px rgba(168, 102, 237, 0.4);
}
.theme-halo-light {
  border: 2px solid rgba(255, 226, 170, 0.95);
  box-shadow:
    inset 0 0 28px 6px rgba(255, 214, 140, 0.6),
    inset 0 0 120px 40px rgba(255, 190, 120, 0.3),
    0 0 60px 20px rgba(255, 200, 130, 0.45);
}
#themeToggle svg,
#authThemeToggle svg {
  transition: transform 520ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
html[data-theme="dark"] #themeToggle svg,
html[data-theme="dark"] #authThemeToggle svg {
  transform: rotate(360deg);
}

/* ---------- 2. Spotlight ---------- */
.hero-stat,
.panel,
.task-summary article,
.auth-feature-list article {
  isolation: isolate;
}
.hero-stat,
.panel,
.task-summary article {
  position: relative;
}
.hero-stat::before,
.task-summary article::before,
.auth-feature-list article::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  transition: opacity 300ms ease;
  background: radial-gradient(
    320px circle at var(--mx, 50%) var(--my, 50%),
    color-mix(in srgb, var(--accent, #8b5cf6) 12%, transparent),
    transparent 50%
  );
}
.auth-feature-list article {
  position: relative;
}
.auth-feature-list article::before {
  background: radial-gradient(
    260px circle at var(--mx, 50%) var(--my, 50%),
    rgba(231, 197, 251, 0.14),
    transparent 55%
  );
}
.panel::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  padding: 1px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 300ms ease;
  background: radial-gradient(
    240px circle at var(--mx, 50%) var(--my, 50%),
    color-mix(in srgb, var(--accent, #8b5cf6) 55%, transparent),
    transparent 60%
  );
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask:
    linear-gradient(#000 0 0) content-box exclude,
    linear-gradient(#000 0 0);
}
@media (hover: hover) and (pointer: fine) {
  .hero-stat:hover::before,
  .task-summary article:hover::before,
  .auth-feature-list article:hover::before,
  .panel:hover::after {
    opacity: 1;
  }
}

/* ---------- 3. Navigation qui glisse ---------- */
.nav.nx-has-indicator {
  position: relative;
}
.nx-nav-indicator {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 0;
  pointer-events: none;
  transition:
    transform 460ms cubic-bezier(0.34, 1.56, 0.64, 1),
    width 300ms cubic-bezier(0.23, 1, 0.32, 1),
    height 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
.nav.nx-has-indicator .nav-item {
  z-index: 1;
}
.nav.nx-has-indicator .nav-item.active,
.nav.nx-has-indicator .nav-item.active:hover {
  background: transparent;
  box-shadow: none;
}
.nav.nx-has-indicator .nav-item.active::before {
  animation: nx-bar-in 320ms 180ms cubic-bezier(0.23, 1, 0.32, 1) both;
}
@keyframes nx-bar-in {
  from {
    opacity: 0;
    scale: 1 0.2;
  }
}

/* ---------- 4. Connexion ---------- */
.auth-page-brand img {
  animation: nx-wordmark-in 1100ms cubic-bezier(0.65, 0, 0.35, 1) both;
}
@keyframes nx-wordmark-in {
  from {
    clip-path: inset(-10% 100% -10% 0);
    filter: blur(4px);
  }
  to {
    clip-path: inset(-10% -2% -10% 0);
    filter: blur(0);
  }
}
.auth-page-story > .auth-story-watermark,
.auth-page-story > .auth-story-grid {
  position: absolute;
  z-index: 0;
  pointer-events: none;
}
.auth-story-grid {
  inset: 0;
  background-image: radial-gradient(rgba(255, 255, 255, 0.08) 1px, transparent 1px);
  background-size: 22px 22px;
  -webkit-mask-image: radial-gradient(ellipse 70% 60% at 70% 30%, #000, transparent 75%);
  mask-image: radial-gradient(ellipse 70% 60% at 70% 30%, #000, transparent 75%);
}
.auth-story-watermark {
  right: -110px;
  bottom: -80px;
  width: 470px;
  height: auto;
  opacity: 0.06;
  translate: calc(var(--px, 0) * 18px) calc(var(--py, 0) * 14px);
  transition: translate 900ms cubic-bezier(0.23, 1, 0.32, 1);
  animation: nx-watermark 16s ease-in-out infinite;
}
@keyframes nx-watermark {
  0%,
  100% {
    scale: 1;
    rotate: -4deg;
  }
  50% {
    scale: 1.05;
    rotate: 3deg;
  }
}
.auth-page-story .nx-story-glow {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(
    480px circle at var(--mx, 70%) var(--my, 30%),
    rgba(255, 255, 255, 0.06),
    transparent 55%
  );
}
.auth-page-story h1 span {
  background: linear-gradient(90deg, #cdb8df 0%, #f6e6ff 25%, #c28ef0 50%, #f0a6d2 75%, #cdb8df 100%);
  background-size: 200% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: nx-shimmer 8s linear infinite;
}
@keyframes nx-shimmer {
  to {
    background-position: -200% 0;
  }
}
/* Bordure lumineuse qui tourne autour du panneau de connexion */
.auth-panel {
  isolation: isolate;
}
.auth-panel::before {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  padding: 1px;
  pointer-events: none;
  background: conic-gradient(
    from var(--nx-angle),
    transparent 0 58%,
    rgba(168, 102, 237, 0.75) 72%,
    rgba(240, 166, 210, 0.6) 82%,
    transparent 94%
  );
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask:
    linear-gradient(#000 0 0) content-box exclude,
    linear-gradient(#000 0 0);
  animation: nx-border-spin 9s linear infinite;
}
@keyframes nx-border-spin {
  to {
    --nx-angle: 360deg;
  }
}
/* Avatars : vague + anneau, écartement au survol */
.auth-role-avatars span {
  position: relative;
  transition:
    margin 450ms cubic-bezier(0.34, 1.56, 0.64, 1),
    rotate 450ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
.auth-role-avatars span::after {
  content: "";
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  border: 2px solid rgba(215, 181, 238, 0.7);
  opacity: 0;
  pointer-events: none;
  animation: nx-avatar-ring 6s ease-out infinite;
}
.auth-role-avatars span:nth-child(2)::after { animation-delay: 160ms; }
.auth-role-avatars span:nth-child(3)::after { animation-delay: 320ms; }
.auth-role-avatars span:nth-child(4)::after { animation-delay: 480ms; }
@keyframes nx-avatar-ring {
  0% { opacity: 0.9; scale: 1; }
  12%, 100% { opacity: 0; scale: 1.7; }
}
.auth-role-preview:hover .auth-role-avatars span:not(:first-child) {
  margin-left: 4px;
}
.auth-role-preview:hover .auth-role-avatars span:last-child {
  rotate: 12deg;
}
.nx-caps-warning {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 2px 0 0;
  padding: 7px 10px;
  border-radius: 8px;
  font-size: 12px;
  font-weight: 600;
  color: #8a5a1c;
  background: #fff5e8;
}
.nx-caps-warning[hidden] {
  display: none;
}
html[data-theme="dark"] .nx-caps-warning {
  color: #f0c38a;
  background: #4d3827;
}
.nx-shake {
  animation: nx-shake 420ms cubic-bezier(0.36, 0.07, 0.19, 0.97);
}
@keyframes nx-shake {
  10%, 90% { transform: translateX(-1px); }
  20%, 80% { transform: translateX(3px); }
  30%, 50%, 70% { transform: translateX(-6px); }
  40%, 60% { transform: translateX(6px); }
}

/* ---------- 5. Lisibilité ---------- */
.remote-module-copy small,
.reach-module-copy small {
  font-size: 0.66rem;
}
.auth-feature-list small {
  font-size: 0.74rem;
}
.auth-role-preview small {
  font-size: 0.7rem;
}
.auth-page-footer {
  font-size: 0.7rem;
}

@media (hover: none) {
  .auth-story-watermark {
    translate: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .auth-page-brand img,
  .auth-story-watermark,
  .auth-page-story h1 span,
  .auth-panel::before,
  .auth-role-avatars span::after,
  .nx-shake,
  .nav.nx-has-indicator .nav-item.active::before {
    animation: none;
  }
  .nx-nav-indicator,
  #themeToggle svg,
  #authThemeToggle svg {
    transition: none;
  }
  .auth-story-watermark {
    translate: none;
  }
}

/* ---------- 6. Badge de connexion : cadenas qui s'ouvre ---------- */
.auth-panel-symbol.nx-lock-mark {
  --lock-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  position: relative;
  overflow: visible;
  color: var(--accent-strong);
  --nymphea-accent: var(--accent-strong);
  background:
    radial-gradient(circle at 30% 20%, color-mix(in srgb, var(--accent) 22%, transparent), transparent 60%),
    var(--accent-soft);
  transition:
    background 420ms ease,
    border-color 420ms ease,
    color 420ms ease,
    box-shadow 420ms ease;
}
.nx-lock-mark .nx-lock-symbol {
  width: 30px;
  height: auto;
  transition: transform 520ms var(--lock-spring);
}
.nx-lock-mark::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(115deg, transparent 40%, rgba(255, 255, 255, 0.55) 50%, transparent 60%) no-repeat;
  background-size: 250% 100%;
  background-position: 130% 0;
}
.nx-lock-chip {
  position: absolute;
  right: -7px;
  bottom: -7px;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  color: var(--muted);
  background: var(--panel);
  border: 1px solid var(--line);
  box-shadow: 0 4px 12px rgba(9, 5, 14, 0.14);
  transition:
    color 300ms ease,
    background 300ms ease,
    border-color 300ms ease,
    transform 420ms var(--lock-spring);
}
.nx-lock-chip svg {
  width: 12px;
  height: 12px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  animation: nx-lock-icon 460ms var(--lock-spring);
}
@keyframes nx-lock-icon {
  from {
    transform: scale(0.4) rotate(-20deg);
    opacity: 0.3;
  }
}
.nx-lock-ring {
  position: absolute;
  inset: -6px;
  border-radius: 20px;
  pointer-events: none;
  opacity: 0;
}

/* Prêt : formulaire rempli → cadenas ouvert, tuile allumée */
.nx-lock-mark.is-ready,
.nx-lock-mark.is-pending {
  color: #fff;
  --nymphea-accent: #f6e6ff;
  border-color: transparent;
  background: linear-gradient(140deg, #7a3fc0, #b36bfb);
  box-shadow:
    0 12px 28px rgba(140, 80, 210, 0.36),
    inset 0 1px 0 rgba(255, 255, 255, 0.25);
}
.nx-lock-mark.is-ready::after {
  animation: nx-lock-sweep 800ms 80ms ease-out;
}
.nx-lock-mark.is-ready .nx-lock-symbol {
  animation: nx-lock-pop 560ms var(--lock-spring);
}
.nx-lock-mark.is-ready .nx-lock-chip,
.nx-lock-mark.is-pending .nx-lock-chip {
  color: #fff;
  background: var(--success, #3ecf9a);
  border-color: transparent;
  transform: scale(1.08);
}
.nx-lock-mark.is-ready .nx-lock-ring {
  border: 2px solid rgba(179, 107, 251, 0.55);
  animation: nx-lock-ripple 700ms ease-out;
}
@keyframes nx-lock-sweep {
  from {
    background-position: 130% 0;
  }
  to {
    background-position: -30% 0;
  }
}
@keyframes nx-lock-pop {
  40% {
    transform: scale(1.16) rotate(-6deg);
  }
  70% {
    transform: scale(0.96) rotate(2deg);
  }
}
@keyframes nx-lock-ripple {
  from {
    opacity: 0.9;
    transform: scale(0.85);
  }
  to {
    opacity: 0;
    transform: scale(1.35);
  }
}

/* Envoi en cours : la tuile respire */
.nx-lock-mark.is-pending .nx-lock-ring {
  border: 2px solid rgba(179, 107, 251, 0.5);
  animation: nx-lock-breathe 1.1s ease-in-out infinite;
}
.nx-lock-mark.is-pending .nx-lock-symbol {
  animation: nx-lock-symbol-breathe 1.1s ease-in-out infinite;
}
@keyframes nx-lock-breathe {
  0%, 100% { opacity: 0; transform: scale(0.92); }
  50% { opacity: 0.9; transform: scale(1.06); }
}
@keyframes nx-lock-symbol-breathe {
  50% { transform: scale(0.92); }
}

/* Erreur : secousse rouge */
.nx-lock-mark.is-error {
  color: var(--danger, #e5484d);
  --nymphea-accent: var(--danger, #e5484d);
  border-color: color-mix(in srgb, var(--danger, #e5484d) 45%, transparent);
  background: color-mix(in srgb, var(--danger, #e5484d) 10%, transparent);
  animation: nx-shake 420ms cubic-bezier(0.36, 0.07, 0.19, 0.97);
}
.nx-lock-mark.is-error .nx-lock-chip {
  color: #fff;
  background: var(--danger, #e5484d);
  border-color: transparent;
}

@media (hover: hover) and (pointer: fine) {
  .nx-lock-mark:not(.is-pending):hover .nx-lock-symbol {
    transform: rotate(-8deg) scale(1.05);
  }
}
@media (max-width: 820px) {
  .nx-lock-mark .nx-lock-symbol {
    width: 26px;
  }
}
@media (prefers-reduced-motion: reduce) {
  .nx-lock-mark,
  .nx-lock-mark::after,
  .nx-lock-chip svg,
  .nx-lock-mark .nx-lock-symbol,
  .nx-lock-mark .nx-lock-ring {
    animation: none !important;
  }
}

/* ==========================================================================
   6. Accueil : action « Importer » alignée sur les onglets
   ========================================================================== */
.nx-toolbar-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}
body:not(:has(#view-overview.active)) .nx-toolbar-actions[data-nx-view="overview"],
body:not(:has(#view-management.active)) .nx-toolbar-actions[data-nx-view="management"] { display: none; }
.nx-toolbar-actions .nx-toolbar-cta {
  width: auto;
  min-width: 0;
  height: 40px;
  min-height: 40px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 0 15px 0 12px;
  color: #fff;
  background: var(--accent-deep, #7c3aed);
  border: 1px solid var(--accent-deep, #7c3aed);
  border-radius: 11px;
  cursor: pointer;
  font: inherit;
  font-size: 0.8rem;
  font-weight: 650;
}
.nx-toolbar-cta svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 220ms var(--ease-out, ease);
}
@media (hover: hover) and (pointer: fine) {
  .nx-toolbar-cta:hover svg { transform: translateY(-2px); }
}
.nx-toolbar-cta:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
@media (max-width: 760px) {
  .workspace-toolbar:has(.nx-toolbar-actions) { flex-direction: row; align-items: center; gap: 8px; }
  .workspace-toolbar:has(.nx-toolbar-actions) .context-nav { width: auto; flex: 1 1 auto; }
  .nx-toolbar-actions .nx-toolbar-cta { width: 42px; padding: 0; justify-content: center; }
  .nx-toolbar-cta span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}

/* ==========================================================================
   7. Imports : zones de dépôt (champ natif masqué, libellés en français)
   ========================================================================== */
.upload-box.nx-upload { position: relative; }
.upload-box.nx-upload input[type="file"] {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
.upload-box.nx-upload:has(input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.upload-box .nx-upload-cta {
  display: flex;
  align-items: center;
  gap: 11px;
  min-width: 0;
  padding: 10px 12px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 9px;
  font-weight: 500;
  transition: border-color 160ms ease, box-shadow 160ms ease;
}
.upload-box .nx-upload-cta > svg {
  flex: none;
  width: 30px;
  height: 30px;
  padding: 7px;
  color: var(--accent-strong, var(--accent));
  background: var(--accent-soft);
  border-radius: 8px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 260ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
.upload-box .nx-upload-cta > span { display: grid; min-width: 0; gap: 1px; font-size: inherit; font-weight: inherit; }
.upload-box .nx-upload-cta b {
  overflow: hidden;
  color: var(--ink);
  font-size: 12.5px;
  font-weight: 620;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.upload-box .nx-upload-cta em { color: var(--muted); font-size: 11.5px; font-style: normal; }
.upload-box.nx-upload:hover .nx-upload-cta,
.upload-box.nx-upload.dragover .nx-upload-cta { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); }
.upload-box.nx-upload:hover .nx-upload-cta > svg,
.upload-box.nx-upload.dragover .nx-upload-cta > svg { transform: translateY(-3px); }
.upload-box.nx-upload.dragover .nx-upload-cta em::after { content: " — relâcher"; }
.upload-box.is-success { border-style: solid; border-color: color-mix(in srgb, var(--success, #2f9e6f) 45%, var(--line)); }
.upload-box.is-success small { color: var(--success, #2f9e6f); font-weight: 600; }
.upload-box.is-success small::before { content: "✓ "; }
.upload-box.is-error { border-color: color-mix(in srgb, var(--danger, #e5484d) 50%, var(--line)); }
.upload-box.is-error small { color: var(--danger, #e5484d); }
.upload-box.nx-pulse { animation: nx-upload-pulse 700ms ease-out; }
@keyframes nx-upload-pulse {
  from { box-shadow: 0 0 0 0 color-mix(in srgb, var(--success, #2f9e6f) 40%, transparent); }
  to { box-shadow: 0 0 0 12px transparent; }
}

/* ==========================================================================
   8. To-do : affichage progressif
   ========================================================================== */
.task-list .nx-task-hidden { display: none !important; }
.nx-task-more {
  display: grid;
  justify-items: center;
  gap: 7px;
  padding: 16px 0 4px;
}
.nx-task-more[hidden] { display: none; }
.nx-task-more-button {
  min-height: 38px;
  padding: 0 18px;
  color: var(--ink);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 999px;
  cursor: pointer;
  font: inherit;
  font-size: 0.8rem;
  font-weight: 620;
  transition: border-color 160ms ease, color 160ms ease, transform 160ms var(--ease-out, ease);
}
.nx-task-more-button:hover { color: var(--accent-strong, var(--accent)); border-color: var(--accent); }
.nx-task-more-button:active { transform: scale(0.97); }
.nx-task-more small { color: var(--faint); font-size: 11.5px; }
.nx-task-all {
  padding: 0;
  color: var(--accent-strong, var(--accent));
  background: none;
  border: 0;
  cursor: pointer;
  font: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.task-row.nx-task-reveal { animation: nx-task-reveal 420ms var(--ease-out, ease); }
@keyframes nx-task-reveal {
  from { opacity: 0; transform: translateY(6px); }
}
@media (prefers-reduced-motion: reduce) {
  .upload-box.nx-pulse, .task-row.nx-task-reveal { animation: none; }
  .nx-toolbar-cta svg, .upload-box .nx-upload-cta > svg { transition: none; }
}

/* ==========================================================================
   9. Équipe : alignements et doublons
   ========================================================================== */
/* L'en-tête du pilotage héritait de la marge des blocs internes (18px) et
   paraissait décalé par rapport aux autres panneaux. */
.management-pilotage > .management-pilotage-head { margin: 4px 0 0; }
/* « Voir les chatteurs » doublonnait l'onglet « Chatteurs » juste à côté. */
.nx-toolbar-actions[data-nx-view="management"] [data-goto="chatting"] { display: none; }
#managementProfitTable .is-zero { color: var(--faint); }

/* ==========================================================================
   10. Logo « Nymphea. » : ondulation des lettres + saut du point au survol
   (voir initWordmarks dans enhancements.js — même signature que les logos
   NymphRemote et NymphReach)
   ========================================================================== */
.nx-wordmark-host > img {
  display: none !important;
}
.nx-wordmark {
  display: block;
  overflow: visible;
  color: var(--ink);
  transition: filter 300ms ease;
}
.auth-page-brand .nx-wordmark {
  width: auto;
  height: 32px;
  animation: nx-wordmark-in 1100ms cubic-bezier(0.65, 0, 0.35, 1) both;
}
.sidebar .brand .nx-wordmark {
  width: 158px;
  height: auto;
  flex: 0 0 158px;
}
@media (max-width: 760px) {
  .sidebar .brand .nx-wordmark {
    width: 136px;
    flex-basis: 136px;
  }
}
.nx-wordmark path {
  transform-box: fill-box;
  transform-origin: center bottom;
}
.nx-wordmark-host {
  cursor: default;
}
.nx-wordmark-host:hover .nx-wordmark {
  filter: drop-shadow(0 0 10px rgba(179, 107, 251, 0.32));
}
.nx-wordmark-host.is-waving .nx-wordmark path {
  animation: nx-letter-wave 760ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
  animation-delay: calc(var(--w, 0) * 42ms);
}
.nx-wordmark-host.is-waving .nx-wordmark .nx-wordmark-dot {
  animation-name: nx-dot-hop;
  animation-duration: 680ms;
  animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1);
}
@keyframes nx-letter-wave {
  0% { translate: 0 0; }
  32% { translate: 0 -46px; }
  64% { translate: 0 9px; }
  100% { translate: 0 0; }
}
@keyframes nx-dot-hop {
  /* Petit saut en arc, sans écrasement : même douceur que NymphRemote/Reach */
  0%,
  100% { translate: 0 0; }
  50% { translate: 0 -110px; }
}
@media (prefers-reduced-motion: reduce) {
  .auth-page-brand .nx-wordmark,
  .nx-wordmark-host.is-waving .nx-wordmark path {
    animation: none;
  }
}
