/* ============================================================
   OMNIASYNX — EXPERIENCE SYSTEM (v92)
   Le calme, la limpidité, la précision.
   Une seule source de vérité pour : courbes, durées, élévation,
   états, skeletons, états vides, reveal, moments signature.
   Règles : animations GPU uniquement (transform/opacity),
   UN seul usage de verre (nav sticky), reduced-motion respecté.
   Doc : docs/experience-system.md
   ============================================================ */

/* ── 1. TOKENS ──────────────────────────────────────────────
   Deux courbes signature :
   « Seuil »   — l'entrée. Décélération feutrée, sans rebond.
   « Retrait » — la sortie. Part vite, s'efface sans traîner.  */
:root {
  --exp-enter: cubic-bezier(0.22, 0.9, 0.24, 1);
  --exp-exit:  cubic-bezier(0.5, 0.04, 0.7, 0.2);

  --exp-fast: 150ms;  /* états hover/active, sorties          */
  --exp-base: 200ms;  /* composants : boutons, inputs, lignes */
  --exp-slow: 300ms;  /* surfaces : cartes, reveal, modales   */

  /* Élévation — 3 niveaux, jamais plus. (valeurs sombres)    */
  --exp-elev-1: 0 1px 2px rgba(0, 0, 0, 0.35);
  --exp-elev-2: 0 6px 24px rgba(0, 0, 0, 0.35), 0 1px 3px rgba(0, 0, 0, 0.28);
  --exp-elev-3: 0 24px 64px rgba(0, 0, 0, 0.5), 0 4px 16px rgba(0, 0, 0, 0.35);

  --exp-ring: 0 0 0 3px rgba(201, 169, 110, 0.28);
  --exp-glass-bg: rgba(10, 10, 15, 0.72);
  --exp-glass-border: rgba(201, 169, 110, 0.14);
  --exp-hairline: rgba(201, 169, 110, 0.12);
}

[data-theme="light"] {
  --exp-elev-1: 0 1px 2px rgba(26, 25, 22, 0.06), 0 1px 6px rgba(26, 25, 22, 0.04);
  --exp-elev-2: 0 6px 24px rgba(26, 25, 22, 0.08), 0 2px 6px rgba(26, 25, 22, 0.05);
  --exp-elev-3: 0 24px 64px rgba(26, 25, 22, 0.16), 0 4px 16px rgba(26, 25, 22, 0.08);

  --exp-ring: 0 0 0 3px rgba(156, 124, 74, 0.25);
  --exp-glass-bg: rgba(250, 248, 245, 0.82);
  --exp-glass-border: rgba(156, 124, 74, 0.16);
  --exp-hairline: rgba(156, 124, 74, 0.18);
}

/* ── 2. DISCIPLINE DE MOUVEMENT ─────────────────────────────
   Fini les `transition: all .3s ease` : on ne transitionne que
   ce qui bouge réellement, aux durées et courbes du système.  */
html .aura-btn,
html .aura-btn-outline,
.aura-btn-ghost,
button.aura-btn,
a.aura-btn {
  transition:
    transform var(--exp-fast) var(--exp-enter),
    box-shadow var(--exp-base) var(--exp-enter),
    background-color var(--exp-base) var(--exp-enter),
    border-color var(--exp-base) var(--exp-enter),
    color var(--exp-base) var(--exp-enter),
    opacity var(--exp-fast) var(--exp-exit);
}

html .aura-card,
.as-widget,
.as-kpi,
html .ac-widget,
html .ac-kpi,
.ax-widget,
.ax-kpi {
  transition:
    transform var(--exp-base) var(--exp-enter),
    box-shadow var(--exp-slow) var(--exp-enter),
    border-color var(--exp-base) var(--exp-enter);
}

/* Lignes de flux (arrivées, demandes, messages) et cellules de grille
   des trois cockpits : même langue, dans les trois préfixes.          */
.as-feed-item,
html .ac-feed-item,
.ax-feed-item,
html .ac-grid-cell,
.ax-room-cell {
  transition:
    background-color var(--exp-fast) var(--exp-enter),
    border-color var(--exp-fast) var(--exp-enter);
}

/* Une ligne de flux qui apparaît franchit le seuil — pas un fondu quelconque. */
html .ac-feed-item, .ax-feed-item {
  animation: exp-fade-up var(--exp-slow) var(--exp-enter) both;
}

/* omniasynx fige ces surfaces en sombre (rgba en dur) : on repasse par les
   variables de thème pour qu'elles suivent le clair comme les .as-/.ax-.
   Préfixe html obligatoire : au build, Vite injecte le bundle omniasynx
   APRÈS cette feuille — à spécificité égale, l'ordre inverse le vainqueur. */
html .ac-feed-item {
  background: var(--omnia-dark, #12121A);
  border-color: var(--omnia-border, #2A2A3E);
}

html .ac-feed-item:hover {
  background: var(--omnia-card, #1A1A2E);
}

html .ac-grid-cell {
  background: var(--omnia-dark, #12121A);
  border-color: var(--omnia-border, #2A2A3E);
}

/* Les utilitaires Tailwind préconstruits parlent aussi la langue du seuil. */
.transition, .transition-all, .transition-colors,
.transition-opacity, .transition-transform {
  transition-timing-function: var(--exp-enter);
}

html .aura-input,
.aura-select,
select.aura-input,
textarea.aura-input {
  transition:
    border-color var(--exp-base) var(--exp-enter),
    box-shadow var(--exp-base) var(--exp-enter),
    background-color var(--exp-base) var(--exp-enter);
}

html .aura-sidebar-link,
.table-row-hover,
tr[data-hover],
.exp-row {
  transition:
    background-color var(--exp-fast) var(--exp-enter),
    color var(--exp-fast) var(--exp-enter),
    border-color var(--exp-fast) var(--exp-enter);
}

/* ── 3. ÉLÉVATION APPLIQUÉE ────────────────────────────────
   Le verre est réservé à la nav sticky : les surfaces posées
   sont opaques, l'ombre seule dit la profondeur.             */
html .aura-card,
.as-widget,
html .ac-widget,
.ax-widget,
.ax-kpi {
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  box-shadow: var(--exp-elev-1);
}

html .aura-card:hover,
.as-widget:hover,
.as-kpi:hover,
.ac-widget:hover,
html .ac-kpi:hover,
.ax-widget:hover,
.ax-kpi:hover {
  box-shadow: var(--exp-elev-2);
}

/* Un chiffre-clé se soulève d'un souffle au survol — 2px, pas plus. */
.as-kpi:hover, html .ac-kpi:hover, .ax-kpi:hover {
  transform: translateY(-2px);
}

/* omniasynx pose des ombres clair ad hoc à spécificité supérieure
   ([data-theme="light"] .aura-card/.ac-*) : on ré-affirme l'échelle. */
html[data-theme="light"] .aura-card,
html[data-theme="light"] .ac-widget,
html[data-theme="light"] .as-widget,
html[data-theme="light"] .ax-widget,
html[data-theme="light"] .ax-kpi {
  box-shadow: var(--exp-elev-1);
}

html[data-theme="light"] .aura-card:hover,
html[data-theme="light"] .as-widget:hover, html[data-theme="light"] .as-kpi:hover,
html[data-theme="light"] .ac-widget:hover, html[data-theme="light"] .ac-kpi:hover,
html[data-theme="light"] .ax-widget:hover, html[data-theme="light"] .ax-kpi:hover {
  box-shadow: var(--exp-elev-2);
}

.exp-elev-1 { box-shadow: var(--exp-elev-1); }
.exp-elev-2 { box-shadow: var(--exp-elev-2); }
.exp-elev-3 { box-shadow: var(--exp-elev-3); }

/* Modales / popovers / menus flottants = niveau 3.           */
.aura-modal, .modal-content, [role="dialog"] .aura-card {
  box-shadow: var(--exp-elev-3);
}

/* ── 4. LE SEUL VERRE : NAV STICKY ─────────────────────────
   À poser sur un header collant. Nulle part ailleurs.        */
.exp-glass-nav {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--exp-glass-bg);
  backdrop-filter: blur(14px) saturate(1.4);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  border-bottom: 1px solid var(--exp-glass-border);
}

/* Topbar de dashboard : verre pleine largeur en compensant le
   padding responsive du <main> (p-4 md:p-6 lg:px-8 lg:pt-4).  */
.exp-topbar {
  margin: -1rem -1rem 1rem;
  padding: 0.75rem 1rem;
}

@media (min-width: 768px) {
  .exp-topbar { margin: -1.5rem -1.5rem 1.25rem; padding: 0.75rem 1.5rem; }
}

@media (min-width: 1024px) {
  .exp-topbar { margin: -1rem -2rem 1.25rem; padding: 0.75rem 2rem; }
}

/* ── 5. ÉTATS SYSTÉMATIQUES ────────────────────────────────
   hover / focus-visible / active / disabled — partout,
   dans les deux thèmes.                                      */
html .aura-btn:hover { transform: translateY(-1px); box-shadow: var(--exp-elev-2); }
html .aura-btn:active, .aura-btn-outline:active { transform: translateY(0) scale(0.985); transition-duration: var(--exp-fast); }

html .aura-btn:focus-visible,
html .aura-btn-outline:focus-visible,
html .aura-input:focus-visible,
html .aura-sidebar-link:focus-visible,
.exp-row:focus-visible {
  outline: none;
  box-shadow: var(--exp-ring);
}

html .aura-input:focus { box-shadow: var(--exp-ring); }

button:disabled, .aura-btn:disabled, .aura-btn-outline:disabled,
input:disabled, select:disabled, textarea:disabled,
.is-disabled {
  opacity: 0.45;
  cursor: not-allowed;
  transform: none !important;
  box-shadow: none !important;
}

/* Toute surface cliquable répond au doigt.                   */
.exp-pressable:active { transform: scale(0.985); }

.exp-pressable:focus-visible,
.ac-fs-btn:focus-visible,
.feed-filter-btn:focus-visible,
.exp-empty-cta:focus-visible, .empty-state-cta:focus-visible {
  outline: none;
  box-shadow: var(--exp-ring);
}

/* Filtres de flux du cockpit : état par défaut discret, survol lisible. */
.feed-filter-btn {
  transition:
    background-color var(--exp-fast) var(--exp-enter),
    color var(--exp-fast) var(--exp-enter);
}

.feed-filter-btn:not(.active):hover {
  color: var(--omnia-gold, #C9A96E);
}

/* État actif dès le premier rendu (le JS ne repeint qu'au premier filtre). */
.feed-filter-btn.active {
  background: rgba(201, 169, 110, 0.15);
  color: var(--omnia-gold, #C9A96E);
}

/* ── 6. SKELETONS ──────────────────────────────────────────
   Shimmer GPU : un voile translaté, pas de background-position
   animé. S'adapte aux deux thèmes.                            */
html .skeleton {
  position: relative;
  overflow: hidden;
  background: rgba(42, 42, 62, 0.5);
  border-radius: 8px;
  pointer-events: none;
  user-select: none;
  color: transparent !important;
}

[data-theme="light"] .skeleton {
  background: rgba(200, 190, 170, 0.28);
}

html .skeleton::after {
  content: '';
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(201, 169, 110, 0.10) 45%,
    rgba(201, 169, 110, 0.16) 50%,
    rgba(201, 169, 110, 0.10) 55%,
    transparent 100%);
  animation: exp-shimmer 1.6s var(--exp-enter) infinite;
}

[data-theme="light"] .skeleton::after {
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(255, 255, 255, 0.55) 45%,
    rgba(255, 255, 255, 0.8) 50%,
    rgba(255, 255, 255, 0.55) 55%,
    transparent 100%);
}

@keyframes exp-shimmer {
  to { transform: translateX(100%); }
}

html .skeleton-text { height: 12px; margin-bottom: 8px; }
.skeleton-text-sm { height: 10px; width: 60%; }
.skeleton-text-lg { height: 16px; width: 80%; }
.skeleton-title { height: 20px; width: 50%; margin-bottom: 16px; }
.skeleton-circle { width: 40px; height: 40px; border-radius: 50%; flex-shrink: 0; }
.skeleton-card  { height: 120px; border-radius: 16px; margin-bottom: 16px; }
.skeleton-row   { height: 56px; border-radius: 12px; margin-bottom: 8px; }
.skeleton-badge { width: 64px; height: 20px; border-radius: 99px; }

/* ── 7. ÉTATS VIDES ────────────────────────────────────────
   Un vide n'est pas un échec : ornement bronze, titre Fraunces,
   une phrase, une action. De la personnalité, pas du bruit.   */
.exp-empty.hidden, .empty-state.hidden { display: none; }

.exp-empty, html .empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 56px 24px;
  animation: exp-fade-up var(--exp-slow) var(--exp-enter) both;
}

.exp-empty-ornament {
  width: 12px;
  height: 12px;
  margin-bottom: 20px;
  background: var(--omnia-gold, #C9A96E);
  transform: rotate(45deg);
  opacity: 0.75;
  position: relative;
}

.exp-empty-ornament::before,
.exp-empty-ornament::after {
  content: '';
  position: absolute;
  top: 50%;
  width: 28px;
  height: 1px;
  background: var(--exp-hairline);
  transform: rotate(-45deg);
}

.exp-empty-ornament::before { right: 18px; }
.exp-empty-ornament::after  { left: 18px; }

html .empty-state-icon {
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--omnia-gold, #C9A96E);
  opacity: 0.7;
  margin-bottom: 16px;
}

.empty-state-icon svg { width: 32px; height: 32px; }

.exp-empty-title, html .empty-state-title {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 19px;
  font-weight: 550;
  letter-spacing: 0.01em;
  color: var(--omnia-white, #F5F5F7);
  margin-bottom: 8px;
}

.exp-empty-desc, .empty-state-desc, html .empty-state-subtitle {
  font-size: 13px;
  line-height: 1.6;
  color: var(--omnia-gray, #8A8A9A);
  max-width: 360px;
  margin-bottom: 20px;
}

.exp-empty-cta, .empty-state-cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 24px;
  border-radius: 12px;
  border: 1px solid var(--omnia-gold, #C9A96E);
  color: var(--omnia-gold, #C9A96E);
  background: transparent;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  transition:
    background-color var(--exp-base) var(--exp-enter),
    color var(--exp-base) var(--exp-enter),
    transform var(--exp-fast) var(--exp-enter);
}

.exp-empty-cta:hover, .empty-state-cta:hover {
  background: rgba(201, 169, 110, 0.1);
  transform: translateY(-1px);
}

/* Variante compacte pour l'intérieur d'un widget.            */
.exp-empty--compact { padding: 28px 16px; }
.exp-empty--compact .exp-empty-ornament { width: 9px; height: 9px; margin-bottom: 14px; }
.exp-empty--compact .exp-empty-desc { margin-bottom: 0; }
.exp-empty--compact .exp-empty-cta { margin-top: 16px; padding: 8px 18px; font-size: 12px; }

/* ── 8. REVEAL — l'ouverture calme ─────────────────────────
   Une page n'apparaît pas : elle se pose. À mettre sur le
   conteneur principal (.exp-reveal) ou sur une grille dont les
   enfants entrent en quinconce (.exp-stagger).                */
.exp-reveal {
  animation: exp-fade-up var(--exp-slow) var(--exp-enter) both;
}

.exp-stagger > * {
  opacity: 0;
  animation: exp-fade-up var(--exp-slow) var(--exp-enter) forwards;
}

.exp-stagger > *:nth-child(1) { animation-delay: 0ms; }
.exp-stagger > *:nth-child(2) { animation-delay: 40ms; }
.exp-stagger > *:nth-child(3) { animation-delay: 80ms; }
.exp-stagger > *:nth-child(4) { animation-delay: 120ms; }
.exp-stagger > *:nth-child(5) { animation-delay: 160ms; }
.exp-stagger > *:nth-child(6) { animation-delay: 200ms; }
.exp-stagger > *:nth-child(n+7) { animation-delay: 240ms; }

@keyframes exp-fade-up {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Sortie discrète (fermeture de modale, retrait d'un toast). */
.exp-out {
  animation: exp-fade-out var(--exp-fast) var(--exp-exit) forwards;
}

@keyframes exp-fade-out {
  to { opacity: 0; transform: translateY(4px); }
}

/* ── 8b. REVEAL AU SCROLL — le récit se dévoile ────────────
   Déclenché par IntersectionObserver (js/experience.js), au
   rythme du lecteur — jamais de scroll-jack, une seule fois,
   jamais de re-masquage. L'état caché n'existe que sous
   html.exp-io-armed (posé par le JS uniquement si IO existe
   et que reduced-motion est inactif) : sans JS, tout reste
   visible. Décalage : .exp-io-stagger sur le parent, ou
   style="--exp-io-delay: 80ms" à la main.                    */
html.exp-io-armed .exp-io {
  opacity: 0;
  transform: translateY(14px);
}

html.exp-io-armed .exp-io.exp-in {
  opacity: 1;
  transform: translateY(0);
  transition:
    opacity var(--exp-slow) var(--exp-enter),
    transform var(--exp-slow) var(--exp-enter);
  transition-delay: var(--exp-io-delay, 0ms);
}

/* ── 9. CHIFFRES-CLÉS — Fraunces ───────────────────────────
   Les chiffres qui comptent se lisent comme une gravure.
   (La page doit charger Fraunces ; repli Georgia digne.)      */
.exp-figure, .kpi-value {
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 560;
  letter-spacing: -0.01em;
  font-variant-numeric: lining-nums;
}

/* ── 9b. TOGGLE SYSTÈME ────────────────────────────────────
   Interrupteur pilule, theme-aware, focus visible.           */
.exp-toggle {
  appearance: none;
  -webkit-appearance: none;
  width: 44px;
  height: 24px;
  border-radius: 99px;
  background: var(--omnia-border, #2A2A3E);
  border: 1px solid var(--omnia-border, #2A2A3E);
  position: relative;
  cursor: pointer;
  flex-shrink: 0;
  transition: background-color var(--exp-base) var(--exp-enter), border-color var(--exp-base) var(--exp-enter);
}

.exp-toggle::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--omnia-white, #F5F5F7);
  transition: transform var(--exp-base) var(--exp-enter);
}

.exp-toggle:checked {
  background: var(--omnia-gold, #C9A96E);
  border-color: var(--omnia-gold, #C9A96E);
}

.exp-toggle:checked::after {
  transform: translateX(20px);
  background: #FFFFFF;
}

.exp-toggle:focus-visible {
  outline: none;
  box-shadow: var(--exp-ring);
}

/* ── 10. MOMENTS SIGNATURE (≤ 400ms) ───────────────────────
   Primitives CSS des trois moments : reveal du login (§8),
   micro-célébration (encaissement / résa confirmée).          */
.exp-moment {
  position: relative;
}

.exp-moment-seal {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--omnia-gold-light, #D4BC8B), var(--omnia-gold-dark, #A88B4A));
  color: #FFFFFF;
  animation: exp-seal-pop 400ms var(--exp-enter) both;
}

.exp-moment-seal svg { width: 26px; height: 26px; }

@keyframes exp-seal-pop {
  0%   { opacity: 0; transform: scale(0.6); }
  70%  { opacity: 1; transform: scale(1.04); }
  100% { opacity: 1; transform: scale(1); }
}

/* Halo unique et bref autour de l'élément célébré.           */
.exp-moment-halo {
  animation: exp-halo 400ms var(--exp-enter) 1;
}

@keyframes exp-halo {
  0%   { box-shadow: 0 0 0 0 rgba(201, 169, 110, 0.45); }
  100% { box-shadow: 0 0 0 18px rgba(201, 169, 110, 0); }
}

/* ── 11. REDUCED MOTION — respect strict ───────────────────
   Tout devient instantané ; les éléments en attente d'entrée
   restent visibles.                                           */
@media (prefers-reduced-motion: reduce) {
  .exp-reveal,
  .exp-stagger > *,
  .exp-empty, .empty-state,
  .exp-moment-seal,
  .exp-moment-halo,
  .exp-out,
  .ac-feed-item, .ax-feed-item,
  .as-pulse::after, .ac-pulse::after, .ax-pulse::after,
  .skeleton::after {
    animation: none !important;
  }

  .exp-stagger > * { opacity: 1; }

  /* Ceinture + bretelles : le JS n'arme pas .exp-io en
     reduced-motion, mais si la préférence change en cours de
     session, rien ne doit rester caché.                       */
  html.exp-io-armed .exp-io {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  html .aura-btn,
html .aura-btn-outline,
html .aura-card,
.as-widget,
.as-kpi,
html .ac-widget,
html .ac-kpi,
.ax-widget,
.ax-kpi,
.as-feed-item,
html .ac-feed-item,
.ax-feed-item,
html .ac-grid-cell,
.ax-room-cell,
.feed-filter-btn,
html .aura-input,
html .aura-sidebar-link,
.exp-row,
.exp-pressable,
.exp-empty-cta,
.empty-state-cta {
    transition-duration: 0.01ms !important;
  }

  html .aura-btn:hover, .exp-pressable:active, html .aura-btn:active {
    transform: none;
  }
}
