/* Fredoka, hébergée chez nous — pas chez Google.
   Décision de Maël (18/07) : garder Fredoka (libre, Open Font License) plutôt
   que d'acheter la licence commerciale de Dunkin. Puisqu'elle est permanente,
   on l'auto-héberge : elle vient du domaine, elle marche même quand le réseau
   d'une salle des fêtes ne joint pas Google, et l'IP des invités ne fuit vers
   personne — ce que promet la page « Vos données ». Fichier variable (400→600),
   sous-ensemble latin (français complet, œ inclus, vérifié). */
@font-face {
  font-family: "Fredoka";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("/fonts/fredoka-latin.woff2") format("woff2");
}

/* ============================================================================
   You Nighted — la charte.
   ----------------------------------------------------------------------------
   SOURCE UNIQUE. Aucune page ne redéfinit une couleur : elles importent ce
   fichier. Avant lui, cinq écrans recopiaient leur :root chacun de leur côté —
   et le rose avait dérivé de #E7235C à #E72A5B sur quatre d'entre eux sans que
   personne le voie. Une charte n'est pas une décoration, c'est l'endroit où on
   ne se trompe qu'une fois.

   Tout descend du logo (« Logo Officiel You Nighted », 2022), relevé au pixel
   et non estimé à l'œil. Le logo contient déjà le brief : un croissant de LUNE
   (la nuit), des ÉTOILES à quatre branches (la lumière), un ŒIL dont la pupille
   est un VINYLE (le son, et le regard qu'on porte sur une soirée). On n'invente
   pas un vocabulaire : on transpose celui-là.
   ========================================================================== */

:root {
  /* --- Les trois couleurs de la marque, mesurées dans le logo -------------
     Blush : 85 % des pixels opaques du logo fond foncé.
     Indigo : 85 % des pixels du logo fond clair.
     Rose : 4 % des deux — c'est un accent, il le reste. Jamais une surface. */
  --yn-blush:  #FAEDF0;
  --yn-indigo: #282F6C;
  --yn-rose:   #E7235C;

  /* Les dérivées. Elles n'existent que pour servir les trois ci-dessus. */
  --yn-nuit:       #24254E;   /* l'indigo assombri : le fond du monde soirée */
  --yn-rose-clair: #F1638A;
  --yn-rose-vif:   #FF9BB5;
  --yn-rose-sombre:#C81F4C;
  --yn-rose-pale:  #FDEBF0;   /* le rose posé à plat : un fond de pastille, jamais du texte */
  --yn-menthe:     #1E9E70;   /* le seul vert : « c'est bon », rien d'autre */
  --yn-survol:     #FDF7F9;   /* la ligne qu'on survole dans un tableau */

  --yn-degrade: linear-gradient(105deg, var(--yn-rose-clair) 0%, var(--yn-rose) 55%, var(--yn-rose-sombre) 100%);

  /* --- Les polices -------------------------------------------------------
     ⚠️ Les vraies sont VONIQUE 92 (la linéale fine du « YOU ») et DUNKIN (la
     grasse arrondie du « NIGHTED' »), dans ~/Dropbox/Shamanska/Collaborateurs/
     You Nighted/Font/. Elles ne sont PAS ici : « Vonique 92_D.otf » porte le
     suffixe _D (Demo), et Dunkin arrive avec son « Font License.txt ». Une
     LICENCES LUES le 18/07 : Vonique = démo (pas d'accents) + licence commerciale
     séparée → jamais embarquée, reste dans le logo vectorisé. Dunkin = web permis
     MAIS redevance commerciale à payer (pixelsagas.com) → non achetée. Maël a
     tranché : on garde FREDOKA (Open Font License, libre pour le commercial),
     désormais auto-hébergée (voir @font-face en tête). Le corps de texte est en
     system-ui — le San Francisco/Segoe/Roboto natif : rien à charger, rien qui
     fuit, plus rapide qu'Inter pour un résultat quasi identique. Le logo, lui,
     porte déjà les vraies polices, vectorisées. */
  --yn-titre: "Fredoka", "Avenir Next Rounded", "Trebuchet MS", system-ui, sans-serif;
  --yn-texte: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;

  /* --- Le mouvement ------------------------------------------------------
     Une seule courbe pour tout ce qui est ressenti, une pour le fonctionnel.
     La lenteur est un luxe ; la lenteur d'un geste répété est une taxe. */
  --yn-ease:      cubic-bezier(.22,.61,.36,1);
  --yn-ease-luxe: cubic-bezier(.16,1,.3,1);
  --yn-vite:   .18s;   /* un état qui répond : survol, focus */
  --yn-normal: .4s;    /* un objet qui bouge : carte, chip */
  --yn-ample:  .8s;    /* une scène qui s'installe : entrée d'écran */

  --yn-rayon:    12px;
  --yn-rayon-lg: 18px;
  --yn-pilule:   999px;

  /* --- Les deux mondes ---------------------------------------------------
     Clair et blush pour la PRÉPARATION (18 mois de travail, en plein jour).
     Sombre et indigo pour la SOIRÉE et pour tout ce qui promet la fête.
     Les pages n'utilisent que les jetons ci-dessous, jamais --yn-* en direct :
     c'est ce qui leur permet de changer de monde sans changer une règle. */
  --fond:        var(--yn-blush);
  --fond-carte:  #FFFFFF;
  --encre:       var(--yn-nuit);
  --encre-douce: #6E70A0;
  --encre-faible:#9A9CC0;
  --trait:       #EBD5DC;
  --trait-fort:  #DFC2CB;
  --accent:      var(--yn-rose);
  --halo:        rgba(231,35,92,.28);

  /* Les états et surfaces qui différaient selon le monde. Avant, chaque page
     les codait en dur pour le fond clair (#FDF7F9, #E3F6ED…) — d'où l'admin
     illisible dès qu'on le passait à la nuit. Ici, une fois, avec leur variante
     nuit juste dessous. Les fonds sont des teintes translucides : elles tiennent
     sur les deux mondes. */
  --survol:       rgba(231,35,92,.05);   /* la ligne qu'on survole */
  --verrou:       #B3A8B8;               /* un texte désactivé, verrouillé */
  --puce:         #F2E7EC;               /* un fond plein discret : piste, code */
  --ok:           var(--yn-menthe);
  --ok-fond:      rgba(30,158,112,.14);
  --neutre-fond:  rgba(110,112,160,.13);
  --alerte:       var(--yn-rose);
  --alerte-fond:  rgba(231,35,92,.12);
  --rose-lisible: var(--yn-rose);        /* le rose EN TEXTE. Sur le clair, le rose de marque suffit. */
  --mort:         #948FA8;
  --mort-fond:    rgba(148,143,184,.16);
  --releve:       var(--yn-nuit);        /* une puce sombre posée sur le clair */
  --releve-encre: var(--yn-blush);       /* son texte, toujours vif */
}

/* Le monde de la soirée. On bascule un attribut sur <html>, rien d'autre.
   `:root[...]` et non `[...]` : sans la racine, le sélecteur attrape TOUT
   élément portant l'attribut. Un bouton `data-monde="soiree"` — dans une
   bascule, par exemple — se redéclarait à lui seul les jetons de la nuit et se
   peignait en blush sur une barre blanche. Contraste mesuré : 1,14 : 1. Un
   monde se décide à la racine, jamais au milieu de l'arbre. */
:root[data-monde="soiree"] {
  --fond:        var(--yn-nuit);
  --fond-carte:  rgba(250,237,240,.04);
  --encre:       var(--yn-blush);
  --encre-douce: rgba(250,237,240,.72);
  --encre-faible:rgba(250,237,240,.48);
  --trait:       rgba(250,237,240,.11);
  --trait-fort:  rgba(250,237,240,.22);
  --halo:        rgba(231,35,92,.45);

  --survol:      rgba(250,237,240,.06);
  --verrou:      rgba(250,237,240,.34);
  --puce:        rgba(250,237,240,.08);
  --ok:          #4FD1A0;                /* la menthe s'éclaircit pour tenir sur la nuit */
  --ok-fond:     rgba(79,209,160,.15);
  --neutre-fond: rgba(250,237,240,.09);
  --alerte:      var(--yn-rose-vif);
  --alerte-fond: rgba(255,155,181,.18);   /* un cheveu plus dense : la pastille se détache mieux */
  --rose-lisible: var(--yn-rose-vif);      /* le rose s'éclaircit en texte : #E7235C sombre était illisible sur la nuit */
  --mort:        rgba(250,237,240,.4);
  --mort-fond:   rgba(250,237,240,.07);
  --fond-carte:  rgba(250,237,240,.055);  /* un cheveu plus dense : lisible sur la nuit animée */
  --releve:      #3A4088;                  /* l'indigo se soulève pour rester distinct du fond nuit */
  --releve-encre: var(--yn-blush);
}

/* ============================================================================
   Les motifs de la marque
   ========================================================================== */

/* L'étoile à quatre branches du logo. Concave, jamais une étoile pointue :
   c'est la forme exacte du fichier. Elle scintille — c'est la lumière. */
.yn-etoile {
  display: inline-block; width: 1em; height: 1em; vertical-align: middle;
  background: currentColor;
  -webkit-mask: var(--yn-masque-etoile) center / contain no-repeat;
          mask: var(--yn-masque-etoile) center / contain no-repeat;
}
:root {
  --yn-masque-etoile: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 0c1.1 7.9 4 10.9 12 12-8 1.1-10.9 4-12 12-1.1-8-4-10.9-12-12C8 10.9 10.9 7.9 12 0z'/%3E%3C/svg%3E");
}
.yn-etoile--scintille { animation: yn-scintille 2.4s var(--yn-ease) infinite; }
@keyframes yn-scintille {
  0%, 100% { opacity: .35; transform: scale(.8) rotate(0deg); }
  50%      { opacity: 1;   transform: scale(1)  rotate(15deg); }
}

/* L'étoile filante : rare, fine, elle traverse et s'efface. Le mouvement est
   posé en JS (angle et trajet variés) ; ici, seulement le corps et la traîne.
   Premium veut dire discret — une tête minuscule, une queue qui s'évanouit. */
.yn-filantes { position: fixed; inset: 0; z-index: 1; pointer-events: none; overflow: hidden; }
.yn-filante {
  position: absolute; width: 2px; height: 2px; border-radius: 50%;
  background: #fff; box-shadow: 0 0 6px 1px var(--yn-rose-vif); opacity: 0;
}
.yn-filante::after {   /* la traîne, derrière la tête */
  content: ""; position: absolute; top: 50%; right: 2px; width: 78px; height: 1px;
  transform: translateY(-50%);
  background: linear-gradient(90deg, transparent, rgba(255,155,181,.7));
}

/* Le vinyle : la pupille de l'œil. Il tourne quand quelque chose travaille. */
.yn-vinyle {
  display: inline-block; width: 1em; height: 1em; border-radius: 50%;
  background:
    radial-gradient(circle at center,
      var(--yn-blush) 0 14%,
      transparent 14% 20%,
      currentColor 20% 100%);
  box-shadow: inset 0 0 0 1px rgba(250,237,240,.35),
              inset 0 0 0 3px transparent,
              inset 0 0 0 4px rgba(250,237,240,.22),
              inset 0 0 0 7px transparent,
              inset 0 0 0 8px rgba(250,237,240,.18);
}
.yn-vinyle--tourne { animation: yn-tourne 3.2s linear infinite; }
@keyframes yn-tourne { to { transform: rotate(360deg); } }

/* La nuit qui respire : le fond du monde soirée. Trois halos, très lents. */
.yn-nuit { position: fixed; inset: 0; z-index: 0; overflow: hidden; background: var(--fond); }

/* Le ciel tourne. Un voile chaud (prune) et un voile froid (indigo) se croisent
   en deux minutes — comme la Terre sous les étoiles. C'est la seule chose de la
   page qui n'a pas de fin : elle glisse d'un bord à l'autre, à peine perceptible.
   Premium tient dans cette lenteur-là : on ne la voit pas bouger, on la sent. */
.yn-nuit::before {
  content: ""; position: absolute; inset: -12%;
  background:
    radial-gradient(58% 52% at 24% 16%, rgba(103,71,122,.55), transparent 62%),
    radial-gradient(54% 50% at 82% 86%, rgba(40,47,108,.55), transparent 62%);
  animation: yn-ciel-tourne 120s ease-in-out infinite alternate;
  will-change: transform, opacity;
}
@keyframes yn-ciel-tourne {
  0%   { transform: translate3d(0, 0, 0) rotate(0deg) scale(1.04); opacity: .38; }
  100% { transform: translate3d(2.5%, -2%, 0) rotate(7deg) scale(1.12); opacity: .62; }
}

.yn-nuit i { position: absolute; border-radius: 50%; filter: blur(110px); }
.yn-nuit i:nth-child(1) { width: 48vw; height: 48vw; background: rgba(231,35,92,.26); top: -14%; left: -10%;   animation: yn-derive 26s var(--yn-ease) infinite; }
.yn-nuit i:nth-child(2) { width: 42vw; height: 42vw; background: rgba(40,47,108,.85); bottom: -18%; right: -12%; animation: yn-derive 30s var(--yn-ease) infinite reverse; }
.yn-nuit i:nth-child(3) { width: 30vw; height: 30vw; background: rgba(231,35,92,.14); top: 44%; left: 58%;      animation: yn-derive 34s var(--yn-ease) infinite; }
@keyframes yn-derive { 0%,100% { transform: translate(0,0) scale(1); } 50% { transform: translate(4%,6%) scale(1.14); } }

/* Le grain. Une photo de nuit a du grain ; un aplat numérique n'en a pas. */
.yn-grain {
  position: fixed; inset: -50%; z-index: 900; pointer-events: none; opacity: .045;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: yn-grain 8s steps(8) infinite;
}
@keyframes yn-grain {
  0%,100% { transform: translate(0,0); }  10% { transform: translate(-5%,-5%); }
  30% { transform: translate(3%,-8%); }   50% { transform: translate(-4%,4%); }
  70% { transform: translate(6%,2%); }    90% { transform: translate(-2%,6%); }
}

/* ============================================================================
   Le socle
   ========================================================================== */

* { box-sizing: border-box; }

body {
  margin: 0; background: var(--fond); color: var(--encre);
  font-family: var(--yn-texte); font-weight: 300;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, .yn-titre {
  font-family: var(--yn-titre); font-weight: 500;
  line-height: 1.1; letter-spacing: -.01em; text-wrap: balance; margin: 0;
}
h1 { font-size: clamp(1.9rem, 5vw, 2.5rem); }
h2 { font-size: 1.5rem; }
h3 { font-size: 1.15rem; }

.yn-oeil {   /* le sur-titre : petit, espacé, il regarde ce qui suit */
  font-family: var(--yn-texte);
  font-size: .68rem; font-weight: 500; letter-spacing: .14em; text-transform: uppercase;
  color: var(--encre-faible); margin: 0 0 10px;
}

/* Le mot qu'on éclaire dans un titre : le dégradé du logo, posé sur le texte.
   Un seul mot par titre — sinon ce n'est plus un accent, c'est un néon. */
.yn-eclat {
  background: linear-gradient(100deg, var(--yn-rose-vif), var(--yn-rose) 60%, var(--yn-rose-clair));
  -webkit-background-clip: text; background-clip: text; color: transparent;
  font-style: normal;
}

/* ============================================================================
   Les objets
   ========================================================================== */

.yn-carte {
  background: var(--fond-carte); border: 1px solid var(--trait);
  border-radius: var(--yn-rayon-lg); padding: 18px;
}

/* Le bouton. Le balayage de lumière n'est pas un gadget : c'est un projecteur
   qui passe. Il ne se déclenche qu'au survol — jamais tout seul, jamais en
   boucle : une lumière qui clignote sans raison, c'est une panne, pas du luxe. */
.yn-btn {
  position: relative; overflow: hidden; cursor: pointer;
  font: inherit; font-family: var(--yn-texte); font-size: .95rem; font-weight: 600;
  color: #FFF; background: var(--yn-degrade); border: 0;
  border-radius: var(--yn-pilule); padding: 14px 26px;
  box-shadow: 0 16px 44px -16px var(--halo);
  transition: transform var(--yn-normal) var(--yn-ease-luxe),
              box-shadow var(--yn-normal) var(--yn-ease-luxe);
}
.yn-btn > * { position: relative; z-index: 2; }
.yn-btn::after {
  content: ""; position: absolute; top: 0; left: -120%; width: 60%; height: 100%; z-index: 1;
  background: linear-gradient(105deg, transparent, rgba(255,255,255,.45), transparent);
  transform: skewX(-18deg); transition: left .7s var(--yn-ease-luxe);
}
.yn-btn:hover { transform: translateY(-3px); box-shadow: 0 22px 54px -16px var(--halo); }
.yn-btn:hover::after { left: 130%; }
.yn-btn:disabled { opacity: .5; transform: none; cursor: default; }
.yn-btn:focus-visible { outline: 2px solid var(--yn-rose-vif); outline-offset: 3px; }

.yn-btn--fantome {
  background: transparent; color: var(--encre); border: 1px solid var(--trait-fort);
  font-weight: 400; box-shadow: none;
}
.yn-btn--fantome:hover { border-color: var(--accent); color: var(--accent); box-shadow: none; }

/* Le champ. Au focus, la lumière s'allume — c'est la seule métaphore, et elle
   est juste : on éclaire ce qu'on regarde. */
.yn-champ {
  width: 100%; font: inherit; font-size: 1rem; font-weight: 300;
  color: var(--encre); background: var(--fond-carte);
  border: 1px solid var(--trait-fort); border-radius: var(--yn-rayon); padding: 13px 15px;
  transition: border-color var(--yn-vite) var(--yn-ease),
              box-shadow var(--yn-vite) var(--yn-ease);
}
.yn-champ::placeholder { color: var(--encre-faible); }
.yn-champ:hover { border-color: var(--encre-faible); }
.yn-champ:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 4px rgba(231,35,92,.13), 0 0 30px -6px var(--halo);
}

/* Le chip : éteint, puis allumé. */
.yn-chip {
  position: relative; overflow: hidden; cursor: pointer;
  font: inherit; font-size: .88rem; font-weight: 400; text-align: left; line-height: 1.4;
  color: var(--encre-douce); background: var(--fond-carte);
  border: 1px solid var(--trait-fort); border-radius: var(--yn-pilule); padding: 11px 17px;
  transition: transform var(--yn-normal) var(--yn-ease-luxe),
              border-color var(--yn-normal), color var(--yn-normal),
              box-shadow var(--yn-normal) var(--yn-ease-luxe);
}
.yn-chip:hover { transform: translateY(-2px); border-color: var(--yn-rose-clair); color: var(--encre); }
.yn-chip[aria-pressed="true"] {
  background: var(--yn-degrade); border-color: transparent; color: #FFF; font-weight: 500;
  box-shadow: 0 14px 34px -12px var(--halo);
}
.yn-chip::after {
  content: ""; position: absolute; top: 0; left: -130%; width: 60%; height: 100%; pointer-events: none;
  background: linear-gradient(105deg, transparent, rgba(255,255,255,.4), transparent);
  transform: skewX(-18deg); transition: left .7s var(--yn-ease-luxe);
}
.yn-chip[aria-pressed="true"]::after { left: 130%; }
.yn-chip:focus-visible { outline: 2px solid var(--yn-rose-vif); outline-offset: 3px; }

/* La pastille d'état. */
.yn-pastille {
  display: inline-block; font-size: .69rem; font-weight: 500; line-height: 1;
  border-radius: var(--yn-pilule); padding: 5px 10px; white-space: nowrap;
  background: var(--trait); color: var(--encre-douce);
}
.yn-pastille--ok     { background: var(--ok-fond);     color: var(--ok); }
.yn-pastille--alerte { background: var(--alerte-fond); color: var(--rose-lisible); }

/* Le vu-mètre. On parle de son : un niveau se montre en barres, pas en étoiles. */
.yn-vu { display: flex; align-items: flex-end; gap: 7px; height: 76px; }
.yn-vu button {
  flex: 1; cursor: pointer; font: inherit; font-size: .7rem; font-weight: 600;
  color: var(--encre-faible); background: var(--fond-carte);
  border: 1px solid var(--trait-fort); border-radius: 8px;
  display: flex; align-items: flex-end; justify-content: center; padding-bottom: 6px;
  transition: background var(--yn-normal), box-shadow var(--yn-normal),
              color var(--yn-normal), border-color var(--yn-normal);
}
.yn-vu button:nth-child(1) { height: 36%; } .yn-vu button:nth-child(2) { height: 52%; }
.yn-vu button:nth-child(3) { height: 68%; } .yn-vu button:nth-child(4) { height: 84%; }
.yn-vu button:nth-child(5) { height: 100%; }
.yn-vu button[aria-pressed="true"] {
  background: var(--yn-degrade); border-color: transparent; color: #FFF;
  box-shadow: 0 0 26px -4px var(--halo);
}
.yn-vu button:focus-visible { outline: 2px solid var(--yn-rose-vif); outline-offset: 3px; }

/* L'égaliseur : ce qui vit, ce qui joue. */
.yn-eq { display: inline-flex; align-items: flex-end; gap: 5px; height: 40px; }
.yn-eq i { width: 5px; border-radius: 4px; background: var(--yn-degrade); animation: yn-eq 1.1s ease-in-out infinite; }
.yn-eq i:nth-child(1){animation-delay:-.1s} .yn-eq i:nth-child(2){animation-delay:-.4s}
.yn-eq i:nth-child(3){animation-delay:-.7s} .yn-eq i:nth-child(4){animation-delay:-.2s}
.yn-eq i:nth-child(5){animation-delay:-.5s} .yn-eq i:nth-child(6){animation-delay:-.9s}
.yn-eq i:nth-child(7){animation-delay:-.3s} .yn-eq i:nth-child(8){animation-delay:-.6s}
@keyframes yn-eq { 0%,100% { height: 16%; } 50% { height: 100%; } }

/* Une scène s'installe : les blocs entrent l'un après l'autre.
   .yn-entre sur le conteneur, .yn-entre > * reçoit le décalage. */
.yn-entre > * { opacity: 0; transform: translateY(22px); animation: yn-entre .7s var(--yn-ease-luxe) forwards; }
.yn-entre > :nth-child(1) { animation-delay: .05s; } .yn-entre > :nth-child(2) { animation-delay: .12s; }
.yn-entre > :nth-child(3) { animation-delay: .19s; } .yn-entre > :nth-child(4) { animation-delay: .26s; }
.yn-entre > :nth-child(5) { animation-delay: .33s; } .yn-entre > :nth-child(6) { animation-delay: .40s; }
.yn-entre > :nth-child(n+7) { animation-delay: .47s; }
@keyframes yn-entre { to { opacity: 1; transform: none; } }

/* ============================================================================
   LE PONT — la charte va aux pages, en attendant qu'elles viennent à elle.
   ----------------------------------------------------------------------------
   Les écrans de la plateforme portent leurs propres noms (.btn, .chip, .field,
   .card), nés avant cette charte. Tant qu'ils ne sont pas passés aux noms
   .yn-*, ce bloc leur donne le comportement de la marque sans toucher à une
   seule de leurs règles — donc sans qu'un usage puisse m'échapper.

   Il n'y avait, avant lui, AUCUNE transition dans l'admin. Zéro. On avait
   unifié les couleurs et appelé ça une charte : une charte qui ne change pas
   ce qu'on ressent en cliquant n'a rien changé du tout.

   Les pages déclarent leur <style> APRÈS ce fichier : sur une propriété qu'elles
   posent, elles gagnent. Ce bloc ne pose donc que ce qu'elles ignorent — le
   mouvement — et jamais leurs couleurs ni leurs tailles.
   À supprimer le jour où les écrans utilisent .yn-btn & co.
   ========================================================================== */

/* Un bouton qu'on survole : le projecteur passe, l'objet se soulève. */
.btn { position: relative; overflow: hidden; transition: transform var(--yn-normal) var(--yn-ease-luxe), box-shadow var(--yn-normal) var(--yn-ease-luxe); }
.btn::after {
  content: ""; position: absolute; top: 0; left: -120%; width: 60%; height: 100%; z-index: 1;
  background: linear-gradient(105deg, transparent, rgba(255,255,255,.45), transparent);
  transform: skewX(-18deg); transition: left .7s var(--yn-ease-luxe); pointer-events: none;
}
.btn:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 16px 34px -14px var(--halo); }
.btn:hover:not(:disabled)::after { left: 130%; }
.btn:active:not(:disabled) { transform: translateY(0); }
/* Le fantôme n'est pas un projecteur : il n'a pas de fond à balayer. */
.btn.ghost::after { display: none; }
.btn.ghost:hover { border-color: var(--accent); color: var(--accent); }

/* Un champ qu'on regarde : la lumière s'allume. */
.field { transition: border-color var(--yn-vite) var(--yn-ease), box-shadow var(--yn-vite) var(--yn-ease); }
.field:hover { border-color: var(--encre-douce); }
.field:focus { border-color: var(--accent); box-shadow: 0 0 0 4px rgba(231,35,92,.12), 0 0 24px -8px var(--halo); }

/* Un chip qu'on choisit : il s'allume, et la lumière le traverse. */
.chip { position: relative; overflow: hidden; transition: transform var(--yn-normal) var(--yn-ease-luxe), border-color var(--yn-normal), color var(--yn-normal), box-shadow var(--yn-normal) var(--yn-ease-luxe); }
.chip:hover { transform: translateY(-2px); }
.chip[aria-pressed="true"] { box-shadow: 0 12px 30px -12px var(--halo); }
.chip::after {
  content: ""; position: absolute; top: 0; left: -130%; width: 60%; height: 100%; pointer-events: none;
  background: linear-gradient(105deg, transparent, rgba(255,255,255,.4), transparent);
  transform: skewX(-18deg); transition: left .7s var(--yn-ease-luxe);
}
.chip[aria-pressed="true"]::after { left: 130%; }

/* Une carte, une ligne de tableau : elles répondent, discrètement.
   Un geste répété quarante fois par jour n'a droit qu'à --yn-vite. */
.card { transition: box-shadow var(--yn-normal) var(--yn-ease-luxe), border-color var(--yn-normal); }
tbody tr td { transition: background var(--yn-vite) var(--yn-ease); }
tbody tr:hover td { background: var(--yn-survol); }
.sp-item { transition: background var(--yn-vite) var(--yn-ease); }
.sp-item:hover { background: var(--yn-survol); }

/* La bascule des deux espaces de l'admin. */
.espaces button { transition: background var(--yn-vite) var(--yn-ease), color var(--yn-vite) var(--yn-ease); }
.espaces .n { transition: background var(--yn-vite) var(--yn-ease); }

/* Une pastille d'état qui vient d'apparaître se signale une fois, puis se tait. */
.pill { transition: background var(--yn-vite) var(--yn-ease); }

/* ============================================================================
   Le mouvement est un plaisir, jamais une condition.
   Un samedi à 23h, dans une salle des fêtes, sur un téléphone fatigué :
   tout ce qui suit doit pouvoir disparaître sans que rien ne casse.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .yn-nuit i, .yn-nuit::before, .yn-grain, .yn-eq i, .yn-etoile--scintille, .yn-vinyle--tourne,
  .yn-btn::after, .yn-chip::after { animation: none !important; }
  .yn-entre > * { opacity: 1; transform: none; animation: none !important; }
  .yn-btn, .yn-chip, .yn-champ, .yn-vu button { transition: none !important; }
  /* Le pont aussi : il n'a pas le droit d'échapper à la règle. */
  .btn, .chip, .field, .card, .pill, tbody tr td, .sp-item, .espaces button { transition: none !important; }
  .btn::after, .chip::after { display: none !important; }
  .btn:hover, .chip:hover { transform: none !important; }
}
