/* ==========================================================
   Trame · Mouvement
   Sobre et fluide : 120 à 300 ms, une seule courbe « ressort » discrète,
   rien qui ne gêne quand on étudie. Tout s'éteint si l'étudiant (ou son
   système) demande moins d'animations — voir la fin du fichier.
   ========================================================== */
:root {
  --d-rapide: 140ms;
  --d-moyen: 240ms;
  --d-lent: 420ms;
  --ease-ressort: cubic-bezier(0.34, 1.36, 0.64, 1);   /* dépasse à peine, revient */
  --ease-sortie: cubic-bezier(0.23, 1, 0.32, 1);
  --reflet: linear-gradient(105deg, transparent 20%, rgba(255, 255, 255, 0.28) 45%, rgba(255, 255, 255, 0.05) 60%, transparent 75%);
  --c-signal-ok: #5bd48a;    /* le signal est toujours sombre : icônes éclaircies (≥ 3:1) */
  --c-signal-err: #ff8f8f;
  --scintille-a: var(--c-sunken);
  --scintille-b: color-mix(in oklab, var(--c-sunken) 55%, var(--c-card));
}

/* ----------------------------------------------------------
   1. Boutons
   ---------------------------------------------------------- */
/* Pression : le bouton s'enfonce un instant, revient avec un léger ressort. */
.sty-btn, .sty-icon-btn, .sty-chip, .sty-fab, .editeur-outil, .nuancier__choix, .tuile-plus, .sty-segmented button {
  transition-property: transform, background-color, border-color, color, box-shadow, opacity;
  transition-duration: var(--d-rapide);
  transition-timing-function: var(--ease-ressort);
}
.sty-btn:active:not(:disabled), .sty-chip:active, .sty-icon-btn:active:not(:disabled),
.editeur-outil:active, .nuancier__choix:active, .tuile-plus:active, .sty-segmented button:active {
  transform: scale(0.965); transition-duration: 60ms;
}
.sty-btn--primary:active:not(:disabled), .sty-fab:active { transform: scale(0.97); }

/* Bouton principal : au survol, un reflet traverse le dégradé une fois. */
.sty-btn--primary::after, .sty-fab::after {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none; border-radius: inherit;
  background: var(--reflet); background-size: 250% 100%; background-position: 130% 0; opacity: 0;
}
@media (hover: hover) and (pointer: fine) {
  .sty-btn--primary:hover:not(:disabled)::after, .sty-fab:hover::after { animation: reflet 900ms var(--ease-sortie) 60ms both; }
}
@keyframes reflet { 0% { opacity: 1; background-position: 130% 0; } 100% { opacity: 1; background-position: -30% 0; } }

/* ----------------------------------------------------------
   2. Icônes qui réagissent (au survol du bouton qui les porte)
   ---------------------------------------------------------- */
.sty-icon { transition: transform var(--d-moyen) var(--ease-ressort); }
@media (hover: hover) and (pointer: fine) {
  /* navigation : l'icône se soulève à peine */
  .sty-nav-item:hover > .sty-icon { transform: translateY(-1px) scale(1.06); }
}
@keyframes cloche { 0% { transform: rotate(0); } 20% { transform: rotate(14deg); } 40% { transform: rotate(-10deg); } 60% { transform: rotate(6deg); } 80% { transform: rotate(-3deg); } 100% { transform: rotate(0); } }
@keyframes souffle { 0%, 100% { transform: scale(1); } 45% { transform: scale(1.14); } }
@keyframes monte { 0%, 100% { transform: translateY(0); } 45% { transform: translateY(-3px); } }
@keyframes descend { 0%, 100% { transform: translateY(0); } 45% { transform: translateY(3px); } }
@keyframes ecrit { 0%, 100% { transform: rotate(0) translate(0, 0); } 30% { transform: rotate(-10deg) translate(-1px, 1px); } 65% { transform: rotate(6deg) translate(1px, 0); } }
@keyframes secoue { 0%, 100% { transform: rotate(0); } 25% { transform: rotate(-9deg); } 75% { transform: rotate(9deg); } }

/* Bascule : le rond s'étire quand on appuie, puis glisse avec un ressort. */
.sty-switch__track::after { transition: transform var(--d-moyen) var(--ease-ressort), width var(--d-rapide) var(--ease-sortie); }
.sty-switch input:active + .sty-switch__track::after { width: calc(var(--size-bascule-rond) + var(--s-1)); }
.sty-switch input:checked:active + .sty-switch__track::after { transform: translateX(calc(var(--size-bascule-l) - var(--size-bascule-h) - var(--s-1))); }

/* ----------------------------------------------------------
   3. Bouton en attente, réussi, en échec (Sty.mouvement.attente)
   ---------------------------------------------------------- */
.sty-btn[aria-busy="true"], .sty-btn--reussi, .sty-btn--echec { position: relative; }
.sty-btn[aria-busy="true"] > *, .sty-btn--reussi > * { opacity: 0; }
.sty-btn[aria-busy="true"] { color: transparent !important; opacity: 1 !important; cursor: progress; }
.sty-btn[aria-busy="true"]::after {
  content: ""; position: absolute; left: 50%; top: 50%; z-index: 1; opacity: 1; animation: roue 700ms linear infinite;
  width: var(--s-5); height: var(--s-5); margin: calc(var(--s-5) / -2) 0 0 calc(var(--s-5) / -2);
  border-radius: var(--r-pill); border: var(--size-filet-epais) solid currentColor; border-right-color: transparent;
  background: none;
}
.sty-btn--primary[aria-busy="true"]::after { border-color: var(--c-on-accent); border-right-color: transparent; }
.sty-btn--secondary[aria-busy="true"]::after, .sty-btn--ghost[aria-busy="true"]::after { border-color: var(--c-accent-text); border-right-color: transparent; }
@keyframes roue { to { transform: rotate(360deg); } }

.sty-btn--reussi { color: transparent !important; opacity: 1 !important; }
.sty-btn--reussi::after {
  content: ""; position: absolute; left: 50%; top: 50%; z-index: 1; opacity: 1;
  width: var(--s-5); height: var(--s-5); margin: calc(var(--s-5) / -2) 0 0 calc(var(--s-5) / -2);
  background: var(--c-on-accent);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / contain no-repeat;
  animation: coche-pop var(--d-lent) var(--ease-ressort) both;
}
.sty-btn--secondary.sty-btn--reussi::after, .sty-btn--ghost.sty-btn--reussi::after { background: var(--c-ok-strong); }
@keyframes coche-pop { 0% { transform: scale(0.3) rotate(-12deg); opacity: 0; } 100% { transform: scale(1) rotate(0); opacity: 1; } }
.sty-btn--echec { animation: hoche 380ms var(--ease-sortie); }
@keyframes hoche { 0%, 100% { transform: translateX(0); } 20% { transform: translateX(-5px); } 45% { transform: translateX(4px); } 70% { transform: translateX(-2px); } }

/* ----------------------------------------------------------
   4. Chargements
   ---------------------------------------------------------- */
/* Les squelettes scintillent : un reflet lent qui passe, plutôt qu'un clignotement. */
.sty-skeleton {
  animation: scintille 1.4s linear infinite;
  background: linear-gradient(90deg, var(--scintille-a) 0%, var(--scintille-a) 35%, var(--scintille-b) 50%, var(--scintille-a) 65%, var(--scintille-a) 100%);
  background-size: 300% 100%;
}
@keyframes scintille { from { background-position: 100% 0; } to { background-position: 0% 0; } }

/* Les barres se remplissent depuis zéro à l'arrivée, puis suivent la valeur. */
.sty-progress__fill { transition: width var(--d-lent) var(--ease-sortie); }
@starting-style { .sty-progress__fill { width: 0 !important; } }
/* Une barre de traitement : dégradé de la marque et un reflet qui court. */
.sty-progress--working .sty-progress__fill { background: var(--degrade-bouton); }
.sty-progress__fill { position: relative; overflow: hidden; }
.sty-progress--working .sty-progress__fill::after, .transcrire .sty-progress__fill::after {
  content: ""; position: absolute; inset: 0; background: var(--reflet); background-size: 250% 100%; animation: reflet-continu 1.6s linear infinite;
}
@keyframes reflet-continu { from { background-position: 130% 0; } to { background-position: -30% 0; } }

/* Étapes du traitement de l'IA : l'étape en cours tourne, l'étape finie se coche. */
.traitement__etape { transition: color var(--d-moyen) ease; }
.traitement__etape[data-etat="cours"] .traitement__marque { position: relative; }
.traitement__etape[data-etat="cours"] .traitement__marque::before {
  content: ""; position: absolute; inset: calc(-1 * var(--size-filet)); border-radius: var(--r-pill);
  border: var(--size-filet-epais) solid color-mix(in oklab, var(--c-accent) 25%, transparent); border-top-color: var(--c-accent);
  animation: roue 900ms linear infinite;
}
.traitement__etape[data-etat="cours"] .traitement__marque .sty-icon { opacity: 0; }
.traitement__etape[data-etat="fait"] .traitement__marque .sty-icon { animation: coche-pop var(--d-lent) var(--ease-ressort) both; color: var(--c-ok-strong); }

/* Le fil en haut de la page, quand un écran met du temps à arriver. */
#fil-navigation {
  position: fixed; top: 0; left: 0; right: 0; height: var(--size-filet-epais); z-index: 100; pointer-events: none;
  background: var(--degrade-bouton); transform-origin: 0 50%; transform: scaleX(0); opacity: 0;
}
#fil-navigation[data-etat="charge"] { opacity: 1; animation: fil-avance 2.4s var(--ease-sortie) forwards; }
#fil-navigation[data-etat="fin"] { opacity: 0; transform: scaleX(1); transition: transform var(--d-rapide) ease, opacity var(--d-lent) ease 120ms; }
@keyframes fil-avance { 0% { transform: scaleX(0); } 30% { transform: scaleX(0.45); } 100% { transform: scaleX(0.85); } }

/* ----------------------------------------------------------
   5. Retours de succès
   ---------------------------------------------------------- */
/* Le signal arrive avec son icône ; la coche se dessine. */
.sty-signal__icone { flex-shrink: 0; width: var(--size-icone-sm); height: var(--size-icone-sm); margin-right: calc(-1 * var(--s-2)); }
.sty-signal--ok .sty-signal__icone { color: var(--c-signal-ok); stroke-dasharray: 30; stroke-dashoffset: 30; animation: dessine 460ms var(--ease-sortie) 120ms forwards; }
.sty-signal--err .sty-signal__icone { color: var(--c-signal-err); animation: coche-pop var(--d-moyen) var(--ease-ressort) both; }
@keyframes dessine { to { stroke-dashoffset: 0; } }

/* Grande coche de fin (révision terminée, état vide « à jour ») : le rond s'ouvre, la coche se trace. */
.vide-coche { animation: coche-pop var(--d-lent) var(--ease-ressort) both; }
.vide-coche .sty-icon { stroke-dasharray: 30; stroke-dashoffset: 30; animation: dessine 520ms var(--ease-sortie) 200ms forwards; }
.revision--fin .bilan__ligne { opacity: 0; transform: translateY(6px); animation: monte-doux var(--d-moyen) var(--ease-sortie) forwards; }
.revision--fin .bilan__ligne:nth-child(1) { animation-delay: 260ms; }
.revision--fin .bilan__ligne:nth-child(2) { animation-delay: 320ms; }
.revision--fin .bilan__ligne:nth-child(3) { animation-delay: 380ms; }
@keyframes monte-doux { to { opacity: 1; transform: translateY(0); } }

/* Ce qui vient d'entrer (objet gardé, carte ajoutée) : un surlignage qui s'éteint. */
[data-eclaire] { animation: eclaire 1.6s var(--ease-sortie); border-radius: var(--r-sm); }
@keyframes eclaire { 0% { background-color: var(--c-accent-soft); box-shadow: 0 0 0 var(--s-1) var(--c-accent-soft); } 100% { background-color: transparent; box-shadow: 0 0 0 var(--s-1) transparent; } }

/* Une proposition de l'IA arrive en douceur dans le texte ; un calque et un menu aussi. */
.proposition-editeur, .instruction-suggestion { animation: entre-doux var(--d-moyen) var(--ease-sortie); }
@keyframes entre-doux { from { opacity: 0; transform: translateY(6px) scale(0.99); } to { opacity: 1; transform: none; } }
.calque { animation: calque-entre var(--d-moyen) var(--ease-sortie); }
.calque-voile { animation: voile-entre var(--d-moyen) ease; }
@keyframes calque-entre { from { opacity: 0; transform: translateY(8px) scale(0.985); } }
@keyframes voile-entre { from { opacity: 0; } }
.sty-sheet.calque { animation-name: feuille-entre; }
@keyframes feuille-entre { from { transform: translateY(100%); } }
.menu-flottant { animation: menu-entre var(--d-rapide) var(--ease-sortie); transform-origin: var(--sty-origin, top right); }
@keyframes menu-entre { from { opacity: 0; transform: scale(0.96) translateY(-2px); } }

/* Un message envoyé arrive de son côté. */
.message--mien:last-child { animation: entre-doux var(--d-moyen) var(--ease-sortie); }

/* ----------------------------------------------------------
   6. Transitions d'écran
   Le nouvel écran apparaît en fondu avec un glissement de 6 px ;
   ses premiers blocs arrivent l'un après l'autre (30 à 40 ms).
   ---------------------------------------------------------- */
.vue--entree { animation: ecran-entre 260ms var(--ease-sortie); }
@keyframes ecran-entre { from { opacity: 0; } to { opacity: 1; } }   /* opacité seule : un transform sur #vue décalerait les éléments fixes */
.vue--entree :is(.vue-page, .reglages__page) > :nth-child(-n+6) { animation: monte-doux 300ms var(--ease-sortie) both; opacity: 0; transform: translateY(6px); }
.vue--entree :is(.vue-page, .reglages__page) > :nth-child(2) { animation-delay: 35ms; }
.vue--entree :is(.vue-page, .reglages__page) > :nth-child(3) { animation-delay: 70ms; }
.vue--entree :is(.vue-page, .reglages__page) > :nth-child(4) { animation-delay: 105ms; }
.vue--entree :is(.vue-page, .reglages__page) > :nth-child(5) { animation-delay: 140ms; }
.vue--entree :is(.vue-page, .reglages__page) > :nth-child(6) { animation-delay: 170ms; }
/* Les cartes survolées se soulèvent d'un pixel. */
@media (hover: hover) and (pointer: fine) {
  a.carte-cours, .sty-card.proposition[href], .formule, .tuile-plus, .plan-carte { transition: box-shadow var(--d-moyen) var(--ease-sortie), transform var(--d-moyen) var(--ease-sortie); }
  a.carte-cours:hover, .sty-card.proposition[href]:hover, .tuile-plus:hover, .plan-carte:hover { transform: translateY(-2px); }
}

/* ----------------------------------------------------------
   7. Moins d'animations : tout devient instantané, rien ne disparaît.
   ---------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 1ms !important; animation-iteration-count: 1 !important; animation-delay: 0ms !important; transition-duration: 1ms !important; }
  .sty-skeleton { animation: none !important; background: var(--c-sunken); }
  .sty-btn[aria-busy="true"]::after, .traitement__etape[data-etat="cours"] .traitement__marque::before { animation: roue 1.2s linear infinite !important; }
}
:root[data-mouvement-reduit] *, :root[data-mouvement-reduit] *::before, :root[data-mouvement-reduit] *::after {
  animation-duration: 1ms !important; animation-iteration-count: 1 !important; animation-delay: 0ms !important; transition-duration: 1ms !important;
}
:root[data-mouvement-reduit] .sty-skeleton { animation: none !important; background: var(--c-sunken); }
/* Une roue d'attente reste une information : elle continue de tourner, lentement. */
:root[data-mouvement-reduit] .sty-btn[aria-busy="true"]::after,
:root[data-mouvement-reduit] .traitement__etape[data-etat="cours"] .traitement__marque::before { animation: roue 1.2s linear infinite !important; }

/* ----------------------------------------------------------
   8. Le mot d'accueil (Accueil)
   « Bonjour. » → le prénom se glisse → tout défile vers le haut →
   une phrase tirée au sort monte depuis le bas. Phases posées par accueil.js.
   ---------------------------------------------------------- */
.salut__fenetre { display: grid; overflow: hidden; padding-bottom: var(--s-1); margin-bottom: calc(-1 * var(--s-1)); }
.salut__ligne { grid-area: 1 / 1; transition: transform 560ms var(--ease-sortie), opacity 380ms ease; }
.salut__ligne--phrase { transform: translateY(110%); opacity: 0; }
.salut__nom { display: inline-block; vertical-align: bottom; white-space: nowrap; overflow: hidden; max-width: var(--largeur-nom, 12em); }
.salut__nom > span { display: inline-block; }
/* Phase 1 : « Bonjour. » arrive, le prénom attend. */
.salut[data-phase="1"] .salut__ligne--bonjour { animation: salut-entre 420ms var(--ease-sortie) both; }
.salut[data-phase="1"] .salut__nom { max-width: 0; }
.salut[data-phase="1"] .salut__nom > span { opacity: 0; transform: translateY(40%); }
/* Phase 2 : le prénom se glisse, le point se pousse. */
.salut[data-phase="2"] .salut__nom, .salut[data-phase="3"] .salut__nom { transition: max-width 560ms var(--ease-sortie); }
.salut[data-phase="2"] .salut__nom > span { transition: opacity 260ms ease, transform 520ms var(--ease-ressort); }
/* Phase 3 : tout monte, la phrase arrive par le bas. */
.salut[data-phase="3"] .salut__ligne--bonjour { transform: translateY(-110%); opacity: 0; }
.salut[data-phase="3"] .salut__ligne--phrase { transform: none; opacity: 1; transition-delay: 90ms; }
@keyframes salut-entre { from { opacity: 0; transform: translateY(40%); } to { opacity: 1; transform: none; } }

/* La carte « Comment tu t'appelles ? » */
.carte-prenom { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3) var(--s-5); padding: var(--s-5); }
.carte-prenom__textes { display: flex; flex-direction: column; gap: var(--s-1); flex: 1 1 16em; }
.carte-prenom__champ { display: flex; gap: var(--s-2); flex: 1 1 18em; }
.carte-prenom__champ .sty-input { flex: 1; min-width: 0; }
.carte-prenom .sty-error { flex-basis: 100%; }

/* ----------------------------------------------------------
   9. Les cartes de cours regardent le curseur (cours.js)
   ---------------------------------------------------------- */
.cours-regard .carte-cours-bloc, .cours-regard .carte-nouveau {
  transform: perspective(900px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transition: transform 420ms var(--ease-sortie);
  will-change: transform;
}
.cours-regard .carte-cours-bloc:hover, .cours-regard .carte-nouveau:hover { transition-duration: 220ms; }

/* ----------------------------------------------------------
   10. L'intro de l'application (index.html + js/intro.js) — Trame
   1. Une trame de points couvre l'écran ; une vague la traverse des bords
      vers le centre (dessin sur canvas, js/intro.js).
   2. Les 81 points du T s'impriment en diagonale, avec un léger rebond,
      puis le signe s'illumine.
   3. Le mot « trame » glisse hors du signe : le logo complet se compose.
   4. Une onde repart du logo vers les bords.
   5. Sortie : le logo s'efface, et l'écran se dissout en similigravure,
      du centre vers les bords, sur l'application.
   Entrée ~2,6 s, sortie ~0,9 s. Clic ou touche : on passe à la sortie.
   ---------------------------------------------------------- */
:root { --intro-signe: 84px; --intro-mot: 190px; --intro-ecart: 20px; }
@media (max-width: 767px) { :root { --intro-signe: 64px; --intro-mot: 144px; --intro-ecart: 14px; } }
.intro { position: fixed; inset: 0; z-index: 200; display: grid; place-items: center; background: var(--c-page); }
.intro--vivante { background: transparent; }
.intro--sortie { pointer-events: none; }
.intro__toile { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.intro__logo { position: relative; display: flex; align-items: center; }
.intro__signe { width: var(--intro-signe); height: var(--intro-signe); overflow: visible; animation: intro-lueur 1500ms ease-out 1250ms both; }
.intro__signe circle { transform-box: fill-box; transform-origin: center; animation: intro-point 560ms var(--ease-ressort) calc(520ms + var(--i) * 38ms) both; }
@keyframes intro-point { 0% { transform: scale(0); opacity: 0; } 55% { transform: scale(1.35); opacity: 1; } 100% { transform: scale(1); opacity: 1; } }
@keyframes intro-lueur {
  0% { filter: drop-shadow(0 0 0 transparent); }
  35% { filter: drop-shadow(0 0 var(--s-5) color-mix(in srgb, var(--c-trame-1) 70%, transparent)); }
  100% { filter: drop-shadow(0 0 var(--s-1) color-mix(in srgb, var(--c-trame-1) 20%, transparent)); }
}
.intro__nom { display: block; width: 0; margin-left: 0; overflow: hidden; animation: intro-nom 760ms cubic-bezier(0.2, 0.8, 0.2, 1) 1450ms both; }
.intro__nom img { width: var(--intro-mot); max-width: none; height: auto; display: block; animation: intro-mot 700ms var(--ease-sortie) 1560ms both; }
@keyframes intro-nom { to { width: var(--intro-mot); margin-left: var(--intro-ecart); } }
@keyframes intro-mot { from { transform: translateX(calc(-1 * var(--intro-ecart))); opacity: 0; filter: blur(6px); } to { transform: none; opacity: 1; filter: none; } }
.intro--sortie .intro__logo { animation: intro-logo-sortie 420ms var(--ease-sortie) both; }
@keyframes intro-logo-sortie { to { transform: scale(1.06); opacity: 0; filter: blur(4px); } }
.intro--fin .intro__signe, .intro--fin .intro__signe circle, .intro--fin .intro__nom, .intro--fin .intro__nom img { animation: none; opacity: 1; transform: none; filter: none; }
.intro--fin .intro__nom { width: var(--intro-mot); margin-left: var(--intro-ecart); }
.intro--fin.intro--sortie .intro__logo { animation: intro-logo-sortie 300ms var(--ease-sortie) both; }
@media (prefers-reduced-motion: reduce) {
  .intro .intro__signe, .intro .intro__signe circle, .intro .intro__nom, .intro .intro__nom img { animation: none !important; opacity: 1 !important; transform: none !important; filter: none !important; }
  .intro .intro__nom { width: var(--intro-mot); margin-left: var(--intro-ecart); }
  .intro--sortie { opacity: 0; transition: opacity 200ms; }
}

/* ----------------------------------------------------------
   11. Le dégradé signature, vivant
   Le bleu et le violet de la marque coulent autour des zones encadrées :
   un grand dégradé glisse derrière un cadre de 2 px, et un halo flou
   suit le même mouvement. Le trajet passe par des points irréguliers :
   les couleurs changent de place sans motif visible. Fonctionne dans
   tous les navigateurs (on anime la position du fond, rien d'exotique).
   ---------------------------------------------------------- */
:root {
  --c-sig-lumiere: #c9bcff;
  --c-sig-bleu-vif: #2f7bff;
  --degrade-signature: linear-gradient(115deg, var(--c-sig-bleu-vif) 0%, var(--c-degrade-fin) 18%, var(--c-sig-lumiere) 30%,
    var(--c-degrade-debut) 44%, var(--c-degrade-fin) 58%, var(--c-sig-lumiere) 70%, var(--c-sig-bleu-vif) 84%, var(--c-degrade-fin) 100%);
}
@keyframes sig-flux {
  0%   { background-position: 0% 50%; }
  18%  { background-position: 70% 10%; }
  37%  { background-position: 100% 70%; }
  55%  { background-position: 35% 100%; }
  74%  { background-position: 85% 30%; }
  88%  { background-position: 15% 0%; }
  100% { background-position: 0% 50%; }
}
@keyframes sig-flux-champ {
  0%   { background-position: 0 0, 0% 50%; }
  18%  { background-position: 0 0, 70% 10%; }
  37%  { background-position: 0 0, 100% 70%; }
  55%  { background-position: 0 0, 35% 100%; }
  74%  { background-position: 0 0, 85% 30%; }
  88%  { background-position: 0 0, 15% 0%; }
  100% { background-position: 0 0, 0% 50%; }
}
/* L'anneau autour d'un conteneur (il ne change pas la mise en page) + son halo. */
.anneau-signature, .formule--max, .recherche__champ:focus-within, .sty-search:focus-within, .carte-prenom:focus-within { position: relative; }
.formule--max::after, .recherche__champ:focus-within::after, .sty-search:focus-within::after, .carte-prenom:focus-within::after, .anneau-signature::after {
  content: ""; position: absolute; inset: var(--sig-decalage, calc(-1 * var(--size-filet-epais))); pointer-events: none;
  border-radius: calc(var(--sig-rayon, var(--r-xl)) + var(--size-filet-epais));
  background: var(--degrade-signature); background-size: 400% 400%;
  animation: sig-flux 6s ease-in-out infinite;
}
/* le cadre net */
.formule--max::after, .recherche__champ:focus-within::after, .sty-search:focus-within::after, .carte-prenom:focus-within::after, .anneau-signature::after {
  z-index: 1; padding: var(--size-filet-epais);
  -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, linear-gradient(#000 0 0); mask-composite: exclude;
}
/* le halo : une lueur qui passe du bleu au violet et tourne autour du cadre */
.formule--max, .recherche__champ:focus-within, .sty-search:focus-within, .carte-prenom:focus-within, .anneau-signature { animation: sig-halo 6s ease-in-out infinite; }
@keyframes sig-halo {
  0%, 100% { box-shadow: -6px 0 22px -6px color-mix(in oklab, var(--c-sig-bleu-vif) 55%, transparent); }
  33% { box-shadow: 0 7px 22px -6px color-mix(in oklab, var(--c-degrade-fin) 55%, transparent); }
  66% { box-shadow: 6px -5px 22px -6px color-mix(in oklab, var(--c-sig-lumiere) 70%, transparent); }
}
/* La formule Max : l'anneau remplace son cadre fixe. */
.formule--max { border: var(--size-filet) solid transparent; background: var(--c-card); --sig-rayon: var(--r-xl); --sig-decalage: calc(-1 * var(--size-filet)); }
/* Les champs de recherche : l'anneau remplace le contour violet. */
.recherche__champ { border-color: var(--c-line-strong); box-shadow: none; }
.recherche__champ:focus-within { outline: none; border-color: transparent; --sig-rayon: var(--r-xl); --sig-decalage: calc(-1 * var(--size-filet)); }
.sty-search:focus-within { --sig-rayon: var(--r-lg); --sig-decalage: 0px; }
.sty-search .sty-input:focus, .sty-search .sty-input:focus-visible { outline: none; border-color: transparent; box-shadow: none; }
.carte-prenom:focus-within { --sig-rayon: var(--r-xl); --sig-decalage: calc(-1 * var(--size-filet)); }
/* Les autres champs de saisie : leur cadre devient le dégradé qui coule. */
.sty-input:focus-visible, .sty-textarea:focus-visible, .sty-select:focus-visible {
  outline: none; border-color: transparent;
  background-image: linear-gradient(var(--c-card), var(--c-card)), var(--degrade-signature);
  background-origin: border-box; background-clip: padding-box, border-box;
  background-size: 100% 100%, 400% 400%;
  box-shadow: 0 0 0 4px color-mix(in oklab, var(--c-degrade-fin) 16%, transparent);
  animation: sig-flux-champ 6s ease-in-out infinite;
}
.sty-search .sty-input:focus-visible, .recherche__champ .sty-input:focus-visible { background: transparent; box-shadow: none; animation: none; }
.sty-search .sty-input:focus-visible { background: var(--c-card); }
@media (prefers-reduced-motion: reduce) {
  .formule--max, .formule--max::after, .recherche__champ:focus-within, .recherche__champ:focus-within::after,
  .sty-search:focus-within, .sty-search:focus-within::after, .carte-prenom:focus-within, .carte-prenom:focus-within::after,
  .anneau-signature, .anneau-signature::after, .sty-input:focus-visible, .sty-textarea:focus-visible, .sty-select:focus-visible { animation: none !important; }
}

/* ----------------------------------------------------------
   12. La barre de l'assistant (sélection dans l'éditeur)
   Fond au dégradé signature, sombre et qui coule lentement ; un liseré
   de verre ; « Transformer » en verre liquide. Elle éclot de la
   sélection : une pastille qui s'étire, puis les actions arrivent une à une.
   ---------------------------------------------------------- */
.sty-ai-bar.barre-contexte {
  --verre-bord: rgba(255, 255, 255, 0.22);
  background: linear-gradient(120deg, #17247a 0%, #2b2f9e 25%, #4a2fb8 50%, #2c46c4 75%, #17247a 100%);
  background-size: 300% 300%;
  border: 1px solid var(--verre-bord);
  box-shadow: 0 18px 40px -14px rgba(33, 26, 120, 0.55), 0 2px 6px rgba(15, 12, 60, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.18);
  animation: barre-eclot 460ms var(--ease-ressort) both, sig-flux 9s ease-in-out 460ms infinite;
  transform-origin: 50% 0;
}
@keyframes barre-eclot {
  0% { opacity: 0; transform: translateY(-6px) scale(0.55, 0.4); clip-path: inset(0 42% 0 42% round 999px); filter: blur(4px); }
  45% { opacity: 1; filter: blur(0); }
  70% { clip-path: inset(-60px -60px -60px -60px round var(--r-xl)); }
  100% { opacity: 1; transform: none; clip-path: inset(-60px -60px -60px -60px round var(--r-xl)); }
}
.sty-ai-bar.barre-contexte > button { animation: barre-action 320ms var(--ease-sortie) both; }
.sty-ai-bar.barre-contexte > button:nth-child(1) { animation-delay: 140ms; }
.sty-ai-bar.barre-contexte > button:nth-child(2) { animation-delay: 170ms; }
.sty-ai-bar.barre-contexte > button:nth-child(3) { animation-delay: 200ms; }
.sty-ai-bar.barre-contexte > button:nth-child(4) { animation-delay: 230ms; }
.sty-ai-bar.barre-contexte > button:nth-child(5) { animation-delay: 260ms; }
.sty-ai-bar.barre-contexte > button:nth-child(n + 6) { animation-delay: 300ms; }
@keyframes barre-action { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: none; } }
@media (hover: hover) and (pointer: fine) {
  .sty-ai-bar.barre-contexte > button:not([data-primary]):hover { background: rgba(255, 255, 255, 0.12); }
}

/* « Transformer » : verre liquide — transparent, bord lumineux, reflet qui glisse. */
.sty-ai-bar.barre-contexte > button[data-primary] {
  position: relative; overflow: hidden; isolation: isolate; margin-left: var(--s-1);
  border-radius: var(--r-pill); padding-inline: var(--s-4);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.26) 0%, rgba(255, 255, 255, 0.08) 55%, rgba(255, 255, 255, 0.14) 100%);
  -webkit-backdrop-filter: blur(10px) saturate(160%); backdrop-filter: blur(10px) saturate(160%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.7),
    inset 0 -1px 0 rgba(255, 255, 255, 0.18),
    inset 0 0 0 1px rgba(255, 255, 255, 0.28),
    inset 0 -10px 18px -10px rgba(170, 150, 255, 0.55),
    0 6px 16px -6px rgba(10, 8, 50, 0.6);
  text-shadow: 0 1px 1px rgba(20, 10, 80, 0.35);
  transition: transform var(--d-rapide) var(--ease-ressort), box-shadow var(--d-moyen) ease;
}
/* la goutte de lumière qui roule à l'intérieur */
.sty-ai-bar.barre-contexte > button[data-primary]::before {
  content: ""; position: absolute; z-index: -1; top: -60%; left: -30%; width: 70%; height: 160%;
  background: radial-gradient(closest-side, rgba(255, 255, 255, 0.45), rgba(255, 255, 255, 0) 70%);
  filter: blur(2px); animation: verre-goutte 4.5s ease-in-out infinite;
}
/* le liseré irisé du verre */
.sty-ai-bar.barre-contexte > button[data-primary]::after {
  content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; padding: 1px;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.85), rgba(160, 190, 255, 0.35) 35%, rgba(200, 170, 255, 0.2) 65%, rgba(255, 255, 255, 0.7));
  -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, linear-gradient(#000 0 0); mask-composite: exclude;
}
@keyframes verre-goutte { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(120%, 10%); } }
@media (hover: hover) and (pointer: fine) {
  .sty-ai-bar.barre-contexte > button[data-primary]:hover {
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.34) 0%, rgba(255, 255, 255, 0.12) 55%, rgba(255, 255, 255, 0.2) 100%);
    transform: translateY(-1px) scale(1.03);
  }
  .sty-ai-bar.barre-contexte > button[data-primary]:hover::before { animation-duration: 1.6s; }
}
.sty-ai-bar.barre-contexte > button[data-primary]:active { transform: scale(0.96); }
.sty-ai-bar.barre-contexte > button:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .sty-ai-bar.barre-contexte, .sty-ai-bar.barre-contexte > button, .sty-ai-bar.barre-contexte > button[data-primary]::before { animation: none !important; } }

/* ----------------------------------------------------------
   13. Le didacticiel : chaque illustration s'anime à son arrivée
   (et certaines vivent en boucle, doucement : l'onde, le point rouge, la mascotte).
   ---------------------------------------------------------- */
.onb__visuel .demo-carte { animation: onb-carte 520ms var(--ease-ressort) 80ms both; }
@keyframes onb-carte { from { opacity: 0; transform: translateY(18px) scale(0.96) rotate(-1.2deg); } to { opacity: 1; transform: none; } }
.onb__visuel .demo-carte > * { animation: monte-doux 380ms var(--ease-sortie) both; opacity: 0; transform: translateY(6px); }
.onb__visuel .demo-carte > :nth-child(1) { animation-delay: 260ms; }
.onb__visuel .demo-carte > :nth-child(2) { animation-delay: 360ms; }
.onb__visuel .demo-carte > :nth-child(3) { animation-delay: 460ms; }
.onb__visuel .demo-carte > :nth-child(4) { animation-delay: 560ms; }
.onb__visuel .demo-carte > :nth-child(5) { animation-delay: 660ms; }
.onb__visuel .demo-carte > :nth-child(6) { animation-delay: 760ms; }
/* 1 · Bienvenue : la barre se remplit, les icônes clignent une fois */
.onb__visuel--1 .sty-progress__fill { animation: onb-remplit 1100ms var(--ease-sortie) 700ms both; }
@keyframes onb-remplit { from { width: 0; } }
.onb__visuel--1 .demo-carte__ligne .sty-icon, .onb__visuel--2 .puces .notion-puce { animation: ia-pop 380ms var(--ease-ressort) both; }
.onb__visuel--1 .demo-carte__ligne:nth-of-type(1) .sty-icon { animation-delay: 420ms; }
.onb__visuel--1 .demo-carte__ligne:nth-of-type(2) .sty-icon { animation-delay: 520ms; }
.onb__visuel--1 .demo-carte__ligne:nth-of-type(3) .sty-icon { animation-delay: 620ms; }
/* 2 · Cours : les chapitres se numérotent, les notions tombent en place */
.onb__visuel--2 .demo-num { animation: ia-pop 360ms var(--ease-ressort) both; }
.onb__visuel--2 .demo-carte__ligne:nth-child(2) .demo-num { animation-delay: 420ms; }
.onb__visuel--2 .demo-carte__ligne:nth-child(3) .demo-num { animation-delay: 520ms; }
.onb__visuel--2 .demo-carte__ligne:nth-child(4) .demo-num { animation-delay: 620ms; }
.onb__visuel--2 .puces .notion-puce:nth-child(1) { animation-delay: 820ms; }
.onb__visuel--2 .puces .notion-puce:nth-child(2) { animation-delay: 900ms; }
.onb__visuel--2 .puces .notion-puce:nth-child(3) { animation-delay: 980ms; }
/* 3 · Enregistrement : le point rouge respire, l'onde vit, le texte arrive */
.onb__visuel--3 .demo-rec { animation: onb-rec 1.6s ease-in-out infinite; }
@keyframes onb-rec { 0%, 100% { box-shadow: 0 0 0 0 color-mix(in oklab, var(--c-rec) 45%, transparent); } 60% { box-shadow: 0 0 0 10px color-mix(in oklab, var(--c-rec) 0%, transparent); } }
.onb__visuel--3 .demo-onde i { transform-origin: 50% 50%; animation: onb-onde 900ms ease-in-out infinite alternate; }
.onb__visuel--3 .demo-onde i:nth-child(3n) { animation-duration: 700ms; animation-delay: -200ms; }
.onb__visuel--3 .demo-onde i:nth-child(3n + 1) { animation-duration: 1100ms; animation-delay: -500ms; }
.onb__visuel--3 .demo-onde i:nth-child(4n) { animation-duration: 600ms; animation-delay: -350ms; }
@keyframes onb-onde { from { transform: scaleY(0.35); } to { transform: scaleY(1.15); } }
.demo-transcrit { font: var(--t-small); }
.demo-transcrit__t { color: var(--c-accent-text); font-weight: 600; font-variant-numeric: tabular-nums; }
/* 4 · Intelligence : l'instruction s'écrit, puis le tableau glisse en place ligne par ligne */
.onb__visuel--4 .sty-bracket { animation: onb-tape 900ms steps(24, end) 450ms both; max-width: 100%; overflow: hidden; }
@keyframes onb-tape { from { opacity: 1; transform: none; clip-path: inset(0 100% 0 0); } to { opacity: 1; transform: none; clip-path: inset(0 0 0 0); } }
.onb__visuel--4 .objet { animation: onb-objet 520ms var(--ease-ressort) 1450ms both !important; opacity: 0; }
@keyframes onb-objet { from { opacity: 0; transform: translateY(10px) scale(0.97); } to { opacity: 1; transform: none; } }
.onb__visuel--4 .tableau-objet tr { animation: monte-doux 320ms var(--ease-sortie) both; opacity: 0; }
.onb__visuel--4 .tableau-objet tr:nth-child(1) { animation-delay: 1700ms; }
.onb__visuel--4 .tableau-objet tr:nth-child(2) { animation-delay: 1820ms; }
/* 5 · Planning : le jour s'allume, les séances se posent, l'examen clignote */
.onb__visuel--5 .demo-jours b.actif { animation: ia-pop 420ms var(--ease-ressort) 420ms both; }
.onb__visuel--5 .demo-evt { animation: onb-evt 460ms var(--ease-ressort) both; }
.onb__visuel--5 .demo-evt:nth-of-type(2) { animation-delay: 640ms; }
.onb__visuel--5 .demo-evt:nth-of-type(3) { animation-delay: 780ms; }
@keyframes onb-evt { from { opacity: 0; transform: translateX(22px); } to { opacity: 1; transform: none; } }
.onb__visuel--5 .demo-evt--warn b { animation: onb-alerte 1.4s ease-in-out 1.4s infinite; }
@keyframes onb-alerte { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }
/* 6 · Groupes : les membres arrivent, quelqu'un écrit, puis le message apparaît */
.onb__visuel--6 .demo-avatars .sty-avatar { animation: ia-pop 380ms var(--ease-ressort) both; }
.onb__visuel--6 .demo-avatars .sty-avatar:nth-child(1) { animation-delay: 320ms; }
.onb__visuel--6 .demo-avatars .sty-avatar:nth-child(2) { animation-delay: 400ms; }
.onb__visuel--6 .demo-avatars .sty-avatar:nth-child(3) { animation-delay: 480ms; }
.onb__visuel .demo-fil { display: grid; }
.onb__visuel .demo-fil > * { grid-area: 1 / 1; }
.onb__visuel--6 .demo-bulle--ecrit { justify-self: start; align-self: start; display: inline-flex; align-items: center; min-height: 2.5em; animation: onb-ecrit 1500ms ease both 700ms; transform-origin: 0 100%; }
@keyframes onb-ecrit { 0% { opacity: 0; transform: scale(0.8); } 15%, 85% { opacity: 1; transform: none; } 100% { opacity: 0; transform: scale(0.9); } }
.demo-points { display: inline-flex; gap: 5px; }
.demo-points i { width: 7px; height: 7px; border-radius: 50%; background: var(--c-ink-3); animation: onb-point 900ms ease-in-out infinite; }
.demo-points i:nth-child(2) { animation-delay: 150ms; } .demo-points i:nth-child(3) { animation-delay: 300ms; }
@keyframes onb-point { 0%, 100% { transform: translateY(0); opacity: 0.5; } 40% { transform: translateY(-3px); opacity: 1; } }
.onb__visuel--6 .demo-fil .demo-bulle:not(.demo-bulle--ecrit) { animation: onb-bulle 460ms var(--ease-ressort) 2150ms both; transform-origin: 0 100%; }
@keyframes onb-bulle { from { opacity: 0; transform: scale(0.85) translateY(6px); } to { opacity: 1; transform: none; } }
/* 7 · Fin : Max arrive, puis reste en place (il ne flotte pas) */
.onb__visuel--7 .onb__mascotte { animation: onb-max 620ms var(--ease-ressort) both; }
@keyframes onb-max { from { opacity: 0; transform: translateY(24px) scale(0.9); } to { opacity: 1; transform: none; } }

/* ----------------------------------------------------------
   14. Lecteur flottant de l'enregistrement : l'îlot éclot, se range, s'ouvre.
   ---------------------------------------------------------- */
@keyframes ilot-battement { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--c-rec) 55%, transparent); } 70%, 100% { box-shadow: 0 0 0 7px transparent; } }
.ilot--entree { animation: ilot-eclot 620ms var(--ease-ressort) both; }
.ilot--entree .ilot__ouvrir, .ilot--entree .ilot__actions { animation: ilot-contenu 420ms var(--ease-sortie) 160ms both; }
.ilot--entree .ilot__btn { animation: barre-action 380ms var(--ease-ressort) both; }
.ilot--entree .ilot__btn:nth-child(1) { animation-delay: 240ms; }
.ilot--entree .ilot__btn:nth-child(2) { animation-delay: 290ms; }
.ilot--entree .ilot__btn:nth-child(3) { animation-delay: 340ms; }
@keyframes ilot-eclot {
  0% { opacity: 0; transform: scale(0.35, 0.6); filter: blur(6px); }
  55% { opacity: 1; transform: scale(1.05, 0.97); filter: blur(0); }
  100% { opacity: 1; transform: none; }
}
@keyframes ilot-contenu { from { opacity: 0; } to { opacity: 1; } }
.ilot--sortie { animation: ilot-rentre 300ms var(--ease-sortie) forwards; pointer-events: none; }
@keyframes ilot-rentre { to { opacity: 0; transform: scale(0.5, 0.7); filter: blur(4px); } }
.ilot--ouvre { animation: ilot-gonfle 240ms var(--ease-sortie) forwards; pointer-events: none; }
@keyframes ilot-gonfle { to { opacity: 0; transform: scale(1.35); filter: blur(2px); } }
.ilot--range { transition: transform 520ms var(--ease-ressort); }

/* L'écran d'enregistrement se range dans l'îlot. */
.scene-rec--reduction { animation: scene-reduit 300ms var(--ease-sortie) forwards; transform-origin: var(--origine-reduction, 100% 100%); }
@keyframes scene-reduit { to { opacity: 0; transform: scale(0.18); border-radius: var(--r-pill); } }

/* ----------------------------------------------------------
   15. Au doigt (js/toucher.js) : garder le doigt posé = survoler.
   La classe « appui » rejoue les gestes prévus pour le curseur.
   ---------------------------------------------------------- */
html { -webkit-tap-highlight-color: transparent; }   /* plus de carré bleu au toucher : chaque bouton a son propre retour */
.tactile :is(a, button, label, summary, [role="button"], [role="tab"], [role="menuitem"], .carte-cours-bloc, .savoir) { -webkit-touch-callout: none; }
.tactile :is(button, [role="button"], [role="tab"], .carte-cours-bloc, .savoir, .sty-nav-item, .sty-tabbar__item) { -webkit-user-select: none; user-select: none; }
.sty-btn--primary.appui:not(:disabled)::after, .sty-fab.appui::after { animation: reflet 900ms var(--ease-sortie) 60ms both; }
.sty-btn--primary.appui:not(:disabled), .sty-fab.appui { background: var(--c-bouton); box-shadow: var(--shadow-bouton); }
.sty-btn--primary.appui:not(:disabled)::before, .sty-fab.appui::before { opacity: 1; }
.sty-btn--secondary.appui:not(:disabled) { background: var(--c-tile); }
.sty-btn--ghost.appui:not(:disabled) { background: var(--c-accent-soft); }
.sty-icon-btn.appui { background: var(--c-tile); }
:is(.sty-nav-item, .sty-tabbar__item).appui .sty-icon { transform: translateY(-1px) scale(1.08); }
.tactile :is(a.carte-cours, .sty-card.proposition[href], .tuile-plus, .plan-carte) { transition: box-shadow var(--d-moyen) var(--ease-sortie), transform var(--d-moyen) var(--ease-sortie); }
:is(a.carte-cours, .sty-card.proposition[href], .tuile-plus, .plan-carte).appui { transform: translateY(-2px); box-shadow: var(--shadow-floating); }
.carte-cours__menu.appui .points-anime__p { animation: points-tour 820ms var(--ease-in-out) both; }
.carte-cours__menu.appui .points-anime__p:nth-child(2) { animation-delay: 70ms; }
.carte-cours__menu.appui .points-anime__p:nth-child(3) { animation-delay: 140ms; }
.sty-ai-bar.barre-contexte > button[data-primary].appui { transform: translateY(-1px) scale(1.03); }

/* ----------------------------------------------------------
   16. Bouton + et feuilles du bas
   ---------------------------------------------------------- */
/* Le + : il s'enfonce, envoie une onde, et pivote en × tant que la feuille est ouverte. */
.sty-fab { position: relative; overflow: visible; }
.sty-fab .sty-icon { position: relative; z-index: 1; transition: transform 460ms var(--ease-ressort); }
.calque-ouvert .sty-fab .sty-icon { transform: rotate(135deg); }
.fab-onde { position: absolute; inset: 0; border-radius: 50%; pointer-events: none; z-index: 0;
  box-shadow: 0 0 0 0 color-mix(in oklab, var(--c-degrade-fin) 55%, transparent); animation: fab-onde 620ms var(--ease-sortie) forwards; }
.fab-onde--2 { animation-delay: 110ms; }
@keyframes fab-onde { to { box-shadow: 0 0 0 26px transparent; } }
.sty-fab.fab-presse { animation: fab-presse 420ms var(--ease-ressort); }
@keyframes fab-presse { 0% { transform: scale(1); } 30% { transform: scale(0.86); } 65% { transform: scale(1.08); } 100% { transform: scale(1); } }

/* Les feuilles montent avec un léger rebond ; leurs options arrivent en cascade. */
.sty-sheet.calque { animation: feuille-monte 460ms var(--ease-ressort) both; }
@keyframes feuille-monte { from { transform: translateY(100%); } }
.sty-sheet.calque .capture-option { animation: monte-doux 360ms var(--ease-sortie) both; }
.sty-sheet.calque .capture-option:nth-child(1) { animation-delay: 90ms; }
.sty-sheet.calque .capture-option:nth-child(2) { animation-delay: 140ms; }
.sty-sheet.calque .capture-option:nth-child(3) { animation-delay: 190ms; }
.sty-sheet.calque .capture-option:nth-child(4) { animation-delay: 240ms; }

/* La poignée : une vraie zone à attraper (48 px de haut), la barre s'élargit quand on tire. */
.sty-sheet__poignee { margin: calc(-1 * var(--s-3)) calc(-1 * var(--s-4)) 0; padding: var(--s-3) 0 var(--s-4); touch-action: none; cursor: grab; }
.sty-sheet__poignee .sty-sheet__grab { margin: 0 auto; transition: width 200ms var(--ease-sortie), background 200ms ease; }
.sty-sheet .calque__tete { touch-action: none; }
.sty-sheet--tiree { cursor: grabbing; }
.sty-sheet--tiree .sty-sheet__grab { width: 56px; background: var(--c-ink-3); }
