/* ==========================================================================
   IADICI UI-KIT — effects.css
   Effets de texte (inspi text-effects.colorion.co), apparitions au scroll
   (inspi Annnimate / Hyperiux, version vanilla), fonds (grain, grille, aurora).
   Règle charte : UN effet fort par page, le reste discret.
   ========================================================================== */

/* --- Texte ---------------------------------------------------------------- */
.fx-gradient { background: linear-gradient(100deg, var(--fg) 20%, var(--ac) 50%, var(--ac-2) 80%); -webkit-background-clip: text; background-clip: text; color: transparent; }
.fx-gradient--anim { background-size: 200% 100%; animation: fx-pan 6s var(--ease) infinite alternate; }
.fx-outline { color: transparent; -webkit-text-stroke: 1px var(--fg); }
.fx-outline-fill { color: transparent; -webkit-text-stroke: 1px var(--fg); background: linear-gradient(var(--fg) 0 0) 0 0 / 0 100% no-repeat; -webkit-background-clip: text; background-clip: text; transition: background-size var(--d3) var(--ease); }
.fx-outline-fill:hover { background-size: 100% 100%; }
.fx-shine { background: linear-gradient(110deg, var(--fg-3) 35%, var(--fg) 50%, var(--fg-3) 65%) 0 0 / 250% 100%; -webkit-background-clip: text; background-clip: text; color: transparent; animation: fx-shine 3.5s linear infinite; }
.fx-glow { text-shadow: 0 0 18px color-mix(in srgb, var(--ac) 60%, transparent), 0 0 2px var(--ac); }
.fx-highlight { background: linear-gradient(var(--ac) 0 0) 0 88% / 0 .32em no-repeat; transition: background-size var(--d3) var(--ease); }
.fx-highlight.is-in, .fx-highlight:hover { background-size: 100% .32em; }
.fx-strike { position: relative; } .fx-strike::after { content: ""; position: absolute; left: 0; right: 0; top: 54%; height: 2px; background: var(--err); transform: scaleX(0); transform-origin: left; transition: transform var(--d3) var(--ease); } .fx-strike.is-in::after { transform: scaleX(1); }
/* Glitch (pure CSS, data-text="même texte") */
.fx-glitch { position: relative; } .fx-glitch::before, .fx-glitch::after { content: attr(data-text); position: absolute; inset: 0; pointer-events: none; }
.fx-glitch::before { color: var(--ac); transform: translate(-2px, 0); clip-path: inset(0 0 60% 0); animation: fx-glitch 2.4s steps(2) infinite; mix-blend-mode: screen; }
.fx-glitch::after { color: var(--err); transform: translate(2px, 0); clip-path: inset(55% 0 0 0); animation: fx-glitch 2.4s steps(2) infinite reverse; mix-blend-mode: screen; }
/* Machine à écrire CSS (largeur en ch : style="--n:24") */
.fx-type { display: inline-block; overflow: hidden; white-space: nowrap; border-right: 2px solid var(--ac); width: calc(var(--n) * 1ch); font-family: var(--f-mono); animation: fx-type calc(var(--n) * 80ms) steps(var(--n)) both, ui-blink 1s steps(1) infinite; }
/* Mots qui défilent (rotateur) : .fx-rotate > span × N, hauteur 1 ligne */
.fx-rotate { display: inline-grid; height: 1.1em; overflow: hidden; vertical-align: bottom; }
.fx-rotate > span { grid-area: 1/1; color: var(--ac); animation: fx-rotate calc(var(--count, 3) * 2.4s) var(--ease) infinite; animation-delay: calc(var(--i) * 2.4s); transform: translateY(110%); }
/* Lettres découpées par JS (data-split) */
.fx-split .char, .fx-split .word { display: inline-block; }
.fx-split .word { overflow: hidden; vertical-align: bottom; padding-bottom: .06em; }
.fx-split .word > span { display: inline-block; transform: translateY(105%); transition: transform 800ms var(--ease-out); transition-delay: calc(var(--wi) * 60ms); }
.fx-split.is-in .word > span { transform: none; }
/* Lettres qui sautent au survol */
.fx-wave-hover .char { transition: transform var(--d2) var(--spring), color var(--d2); }
.fx-wave-hover .char:hover { transform: translateY(-.15em); color: var(--ac); }

/* --- Apparitions au scroll (JS ajoute .is-in via IntersectionObserver) ----- */
[data-reveal] { opacity: 0; transition: opacity 800ms var(--ease-out), transform 800ms var(--ease-out), clip-path 900ms var(--ease), filter 800ms var(--ease-out); transition-delay: calc(var(--stagger, 0) * 80ms); }
[data-reveal="up"]    { transform: translateY(32px); }
[data-reveal="down"]  { transform: translateY(-32px); }
[data-reveal="left"]  { transform: translateX(40px); }
[data-reveal="right"] { transform: translateX(-40px); }
[data-reveal="scale"] { transform: scale(.94); }
[data-reveal="blur"]  { filter: blur(12px); }
[data-reveal="clip"]  { opacity: 1; clip-path: inset(0 0 100% 0); }
[data-reveal="wipe"]  { opacity: 1; clip-path: inset(0 100% 0 0); }
[data-reveal].is-in   { opacity: 1; transform: none; filter: none; clip-path: inset(0 0 0 0); }
@media (prefers-reduced-motion: reduce) { [data-reveal] { opacity: 1; transform: none; filter: none; clip-path: none; } }
/* Sans JS : tout reste visible */
.no-js [data-reveal] { opacity: 1; transform: none; clip-path: none; filter: none; }
/* Scroll-driven natif (Chrome/Edge ; ignoré ailleurs) : barre de progression, parallax */
@supports (animation-timeline: scroll()) {
  .fx-scroll-progress { position: fixed; inset: 0 0 auto; height: 2px; background: var(--ac); transform-origin: left; animation: fx-grow linear both; animation-timeline: scroll(root); z-index: 100; }
  .fx-parallax { animation: fx-parallax linear both; animation-timeline: view(); }
  .fx-view-fade { animation: fx-view-fade linear both; animation-timeline: view(); animation-range: entry 0% cover 35%; }
}

/* --- Fonds ----------------------------------------------------------------- */
/* Grain SVG 5 % (charte v2) — à poser sur body ou une section */
.fx-grain { position: relative; isolation: isolate; }
.fx-grain::after { content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 1; opacity: .05; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); }
.fx-gridbg { background-image: linear-gradient(var(--line) 1px, transparent 1px), linear-gradient(90deg, var(--line) 1px, transparent 1px); background-size: 56px 56px; mask-image: radial-gradient(ellipse at center, #000 30%, transparent 75%); }
.fx-dotbg { background-image: radial-gradient(var(--line-2) 1px, transparent 1px); background-size: 22px 22px; }
.fx-aurora { position: relative; overflow: hidden; isolation: isolate; }
.fx-aurora::before { content: ""; position: absolute; inset: -40%; z-index: -1; filter: blur(70px); opacity: .45;
  background: radial-gradient(closest-side at 30% 40%, var(--ac), transparent), radial-gradient(closest-side at 70% 60%, var(--ac-2), transparent), radial-gradient(closest-side at 50% 20%, var(--ac-hi), transparent);
  animation: fx-aurora 18s var(--ease) infinite alternate; }
.fx-spotlight-bg { background: radial-gradient(600px circle at var(--mx, 50%) var(--my, 30%), color-mix(in srgb, var(--ac) 10%, transparent), transparent 60%); }
/* Demi-teinte (halftone) — inspi Kobra Halftone Dots */
.fx-halftone { background-image: radial-gradient(circle at center, var(--ac) 0.9px, transparent 1.4px); background-size: 7px 7px; mask-image: linear-gradient(135deg, #000, transparent 70%); }
/* Hairline lumineuse en haut de section */
.fx-topline { position: relative; } .fx-topline::before { content: ""; position: absolute; top: -1px; left: 10%; right: 10%; height: 1px; background: linear-gradient(90deg, transparent, var(--ac), transparent); }

/* --- Curseur personnalisé (JS : UI.cursor()) ------------------------------ */
.fx-cursor { position: fixed; top: 0; left: 0; width: 10px; height: 10px; border-radius: 50%; background: var(--ac); pointer-events: none; z-index: 999; mix-blend-mode: difference; transform: translate(var(--cx, -50px), var(--cy, -50px)) translate(-50%, -50%) scale(var(--cs, 1)); transition: transform 120ms var(--ease-out); }
@media (hover: none) { .fx-cursor { display: none; } }

/* --- Keyframes ------------------------------------------------------------- */
@keyframes fx-pan { to { background-position: 100% 0; } }
@keyframes fx-shine { from { background-position: 100% 0; } to { background-position: -150% 0; } }
@keyframes fx-glitch { 0%, 92% { transform: translate(0); } 94% { transform: translate(-3px, 1px); } 96% { transform: translate(3px, -1px); } 98% { transform: translate(-1px, 2px); } }
@keyframes fx-type { from { width: 0; } }
@keyframes fx-rotate { 0% { transform: translateY(110%); } 6%, 30% { transform: translateY(0); } 36%, 100% { transform: translateY(-110%); } }
@keyframes fx-grow { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes fx-parallax { from { transform: translateY(8%); } to { transform: translateY(-8%); } }
@keyframes fx-view-fade { from { opacity: 0; transform: translateY(40px); } to { opacity: 1; transform: none; } }
@keyframes fx-aurora { to { transform: rotate(25deg) scale(1.15); } }
