/* ============================================================
   FOC STUDIO — BASE
   Fondations partagées par toutes les pages :
   polices, tokens, reset, typographie, boutons, liens, utilitaires.
   (Aucune animation de bloc ici — voir la couche animation à venir.)
   ============================================================ */

/* ---------- POLICES ---------- */
@font-face {
  font-family: 'Bastardo Grotesk';
  src: url('../assets/fonts/BastardoGrotesk-Bold.woff2') format('woff2'),
       url('../assets/fonts/BastardoGrotesk-Bold.woff') format('woff');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'PP Telegraf';
  src: url('../assets/fonts/PPTelegraf-Light.woff2') format('woff2'),
       url('../assets/fonts/PPTelegraf-Light.woff') format('woff');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'PP Telegraf';
  src: url('../assets/fonts/PPTelegraf-Regular.woff2') format('woff2'),
       url('../assets/fonts/PPTelegraf-Regular.woff') format('woff');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'PP Telegraf';
  src: url('../assets/fonts/PPTelegraf-Medium.woff2') format('woff2'),
       url('../assets/fonts/PPTelegraf-Medium.woff') format('woff');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'PP Telegraf';
  src: url('../assets/fonts/PPTelegraf-Bold.woff2') format('woff2'),
       url('../assets/fonts/PPTelegraf-Bold.woff') format('woff');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* ---------- POLICE D'ICÔNES ---------- */
@font-face {
  font-family: 'icons';
  src: url('../assets/fonts/icons/icons.woff2') format('woff2'),
       url('../assets/fonts/icons/icons.woff') format('woff');
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}

.icon:before {
  font-family: 'icons';
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-style: normal;
  font-variant: normal;
  font-weight: normal;
  text-decoration: none;
  text-transform: none;
}

.icon-foc-arrow-full-right:before { content: "\E01B"; }
.icon-foc-arrow-full-left:before  { content: "\E01A"; }

/* ---------- TOKENS ---------- */
:root {
  --feu: #ff3600;
  --rose: #ff99ff;
  --noir: #0a0a0a;
  --blanc: #ffffff;
  --light-text: rgba(255, 255, 255, 0.75);

    --link-slide-color: var(--rose);

  --font-title: 'Bastardo Grotesk', 'Montserrat', sans-serif;
  --font-body: 'PP Telegraf', 'Montserrat', sans-serif;
  /* Auto-hébergé (PP Telegraf) → plus de dépendance Google Fonts. */
  --font-body-alt: 'PP Telegraf', 'Montserrat', sans-serif;

  --max-width: 1280px;
  --section-pad: clamp(4rem, 8vw, 8rem);
  --gutter: clamp(1.5rem, 4vw, 3rem);

  /* Espace standard sous un titre de section (avant son contenu).
     Source de vérité unique → titres homogènes sur tout le site. */
  --title-gap: clamp(2rem, 4vw, 4rem);

  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
  --duration-base: 0.7s;
  --duration-slow: 1s;

  @media (max-width: 600px) {
    --section-pad: clamp(2rem, 4vw, 4rem);
  }
}

/* ---------- RESET ---------- */
*, *::before, *::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  text-wrap: balance;
}

html {
  scroll-behavior: smooth;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* PAS d'overflow ici : `overflow-x: clip` (ou hidden) sur <html> CASSE
     position:sticky des descendants (Chrome/Safari) → les rideaux "Concrètement"
     / "Comment ça se passe" ne se superposent plus. Le scroll horizontal est
     géré par body (ci-dessous) qui, tant que <html> reste visible, propage son
     overflow au viewport → clip horizontal SANS casser le sticky. */
}

body {
  font-family: var(--font-body);
  font-weight: 400;
  color: var(--noir);
  background: var(--rose);
  /* Empêche le scroll horizontal créé par les animations d'apparition
     (reveal--left/right ±44px) et les blocs en 100vw (hero/scrollbar). Comme
     <html> est en overflow visible, cet overflow se propage au viewport. */
  overflow-x: hidden;
  line-height: 1.04;
}

/* Scroll horizontal parasite (mobile / tablette) — filet de sécurité.
   ATTENTION : le `overflow-x: hidden` posé sur <body> ci-dessus ne CLIPPE
   en réalité rien ici. <html> étant volontairement en overflow visible
   (sinon les rideaux sticky du desktop cassent, cf. plus haut), l'overflow
   du body est « propagé » au viewport et ne découpe pas ses descendants
   (un `.reveal--right` décalé de +44px, un bloc trop large… débordent quand
   même → barre de défilement horizontale).
   On clippe donc directement <html>, MAIS seulement sous 1024px : posé sur
   <html>, `overflow-x: clip` décale le calage des `position: sticky`, et le
   seul sticky du site (les rideaux Devil's Touch) n'apparaît qu'à partir de
   1024px. En dessous → aucun sticky, clip sans risque. `clip` (et non
   `hidden`) n'introduit pas de conteneur de scroll. */
@media (max-width: 1023px) {
  html { overflow-x: clip; }
}

img {
  display: block;
  max-width: 100%;
  height: auto;
}

a {
  text-decoration: none;
  color: inherit;
}

/* ============================================================
   SYSTÈME DE TITRES — 3 niveaux, sources de vérité uniques
   ------------------------------------------------------------
   .title-seo   = petit texte du dessus, pensé SEO (mots-clés précis)
   .title-user  = titre de section graphique (parle à l'humain)
   .title-hero  = gros titre d'accroche (hero / display)

   RÈGLE : la taille, la typo et la marge de chaque niveau sont
   définies ICI et NULLE PART AILLEURS. Une section peut seulement
   changer la couleur, la position/alignement et la largeur de boîte.
   ============================================================ */
.title-seo {
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 400;
  margin-bottom: .75rem;
  text-transform: none;
  letter-spacing: normal;
  line-height: 1.2;
}

.title-user {
  font-family: var(--font-title);
  font-size: clamp(2rem, 4vw, 4rem);
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: -0.02em;
  line-height: 1;
  margin: 0;
  text-wrap: balance;
}

/* .title-hero = gros titre d'accroche (hero / display).
   SEUL niveau au-dessus de title-user. Même règle : sa taille/typo/marge
   ne se modifient JAMAIS ailleurs — seules couleur / position / alignement
   / largeur de boîte peuvent varier selon le contexte. */
.title-hero {
  font-family: var(--font-title);
  font-weight: 700;
  font-size: clamp(2.4rem, 6.5vw, 74px);
  line-height: 0.88;
  text-transform: uppercase;
  letter-spacing: -0.03em;
  text-wrap: balance;
  margin: 0;
}

.text-feu { color: var(--feu); }
.text-white {color: var(--blanc);}
.text-rose {color: var(--rose);}
/* ============================================================
   BOUTONS
   ------------------------------------------------------------
   Système unifié. Chaque variante ne définit QUE son style de
   base via 3 variables :
     --btn-bg     : fond au repos
     --btn-text   : couleur du texte au repos
     --btn-border : couleur de la bordure au repos (= fond si plein)
   Le HOVER est IDENTIQUE partout : fond blanc (cercle qui jaillit du
   centre), texte noir. Les flèches FOC slident (l'une sort à droite,
   l'autre entre par la gauche) et le texte glisse — comme le bouton
   "modern button" d'origine. Le cercle + les 2 flèches sont injectés
   automatiquement dans chaque .btn par js/main.js (aucun markup à
   répéter dans le HTML : un simple <span class="btn__text"> suffit).
   ============================================================ */
.btn {
  --btn-bg: var(--noir);
  --btn-text: var(--rose);
  --btn-ring: var(--noir);   /* halo noir pour tous les boutons */
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 1rem 2.25rem;
  font-family: var(--font-title);
  font-weight: 700;
  font-size: clamp(0.8rem, 1vw, 0.95rem);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--btn-text);
  background: var(--btn-bg);
  border: none;
  /* Anneau fin au repos → au survol il enfle (12px) et se dissout :
     c'est le halo qui émane du bouton (effet "alentour"). */
  box-shadow: 0 0 0 2px var(--btn-ring);
  cursor: pointer;
  overflow: hidden;
  transition: color 0.6s cubic-bezier(0.23, 1, 0.32, 1),
              border-color 0.6s cubic-bezier(0.23, 1, 0.32, 1),
              box-shadow 0.6s cubic-bezier(0.23, 1, 0.32, 1),
              scale 0.2s var(--ease-out-quart);
  text-decoration: none;
}

/* Cercle blanc qui jaillit du centre pour remplir le bouton au survol */
.btn__circle {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 150%;
  aspect-ratio: 1;
  background: var(--blanc);
  border-radius: 50%;
  transform: translate(-50%, -50%) scale(0);
  opacity: 0;
  z-index: 0;
  transition: transform 0.8s cubic-bezier(0.23, 1, 0.32, 1),
              opacity 0.8s cubic-bezier(0.23, 1, 0.32, 1);
}

/* Flèches FOC : l'une visible à droite sort, l'autre entre par la gauche.
   fill: currentColor → elles suivent la couleur du texte (rose/feu → noir). */
.btn__arr {
  position: absolute;
  width: 16px;
  height: 16px;
  margin-top: -5px;   /* alignement optique avec le texte */
  z-index: 1;
  fill: currentColor;
  pointer-events: none;
  transition: all 0.8s cubic-bezier(0.23, 1, 0.32, 1);
}
.btn__arr--1 { right: 1.5rem; }   /* visible au repos, à droite */
.btn__arr--2 { left: -25%; }      /* cachée au repos, hors-cadre à gauche */

.btn__text {
  position: relative;
  z-index: 1;
  transform: translateX(-18px);   /* ~8px d'espace en plus avec l'icône */
  transition: transform 0.8s cubic-bezier(0.23, 1, 0.32, 1);
}

.btn:hover {
  color: var(--noir);
  box-shadow: 0 0 0 12px transparent;        /* halo qui émane et se dissout */
}
.btn:hover .btn__circle {
  transform: translate(-50%, -50%) scale(1);
  opacity: 1;
}
.btn:hover .btn__arr--1 { right: -25%; }    /* sort à droite */
.btn:hover .btn__arr--2 { left: 1.5rem; }   /* entre par la gauche */
.btn:hover .btn__text { transform: translateX(18px); }

/* Curseur fantôme (mobile) : on rejoue l'état :hover quand le curseur
   automatique "touche" le bouton — le pseudo :hover ne se déclenche pas sur
   un mouseenter synthétique. Mêmes effets que .btn:hover ci-dessus. */
.btn.is-ghost-hover { color: var(--noir); box-shadow: 0 0 0 12px transparent; }
.btn.is-ghost-hover .btn__circle { transform: translate(-50%, -50%) scale(1); opacity: 1; }
.btn.is-ghost-hover .btn__arr--1 { right: -25%; }
.btn.is-ghost-hover .btn__arr--2 { left: 1.5rem; }
.btn.is-ghost-hover .btn__text { transform: translateX(18px); }

.btn:active {
  scale: 0.96;
  box-shadow: 0 0 0 4px var(--btn-ring);
}

/* Quand un bouton porte AUSSI .reveal, la transition de .reveal (raccourci)
   écraserait celle de .btn → plus de halo ni de changement de couleur au
   survol. On refusionne les deux : entrée (opacity/transform/filter) avec le
   délai du reveal, et hover (color/box-shadow/scale) instantané. */
.btn.reveal {
  transition: opacity 0.7s var(--ease-out-quart) var(--reveal-delay, 0s),
              transform 0.7s var(--ease-out-quart) var(--reveal-delay, 0s),
              filter 0.7s var(--ease-out-quart) var(--reveal-delay, 0s),
              color 0.6s cubic-bezier(0.23, 1, 0.32, 1),
              border-color 0.6s cubic-bezier(0.23, 1, 0.32, 1),
              box-shadow 0.6s cubic-bezier(0.23, 1, 0.32, 1),
              scale 0.2s var(--ease-out-quart);
}

/* ---- Variantes de style de base ---- */

/* Règle : tout bouton à fond noir a le texte blanc. */

/* Fond noir, texte blanc (défaut + CTA Devil's Touch sur le bloc rouge) */
.btn--dark,
.btn--filled,
.btn--dark-feu {
  --btn-bg: var(--noir);
  --btn-text: var(--blanc);
}

/* Fond rouge feu, texte noir */
.btn--feu {
  --btn-bg: var(--feu);
  --btn-text: var(--noir);
  --btn-ring: var(--feu);
}

/* Fond rose, texte noir */
.btn--rose {
  --btn-bg: var(--rose);
  --btn-text: var(--noir);
}

/* Diagnostic — fond rose, bordure noire 2px, texte noir.
   Le halo (box-shadow) reste rose comme le fond ; la bordure noire
   est l'outline visible au repos. Hover : remplissage blanc comme les autres. */
.btn--diagnostic {
  --btn-bg: var(--rose);
  --btn-text: var(--noir);
  border: 2px solid var(--noir);
  /* La bordure noire sert d'outline au repos → pas d'anneau en plus
     (spread 0). Au survol, le halo noir émane quand même (cf. .btn:hover). */
  box-shadow: 0 0 0 0 var(--noir);
}
/* Au survol, le bouton se remplit de blanc → la bordure noire s'accorde
   au fond (blanc) pour ne jamais rester visible. */
.btn--diagnostic:hover {
  border-color: var(--blanc);
}

/* Secondaire — pas de fond ; le box-shadow (noir) tient lieu de bordure. */
.btn--secondary {
  --btn-bg: transparent;
  --btn-text: var(--noir);
  --btn-ring: var(--noir);
}

/* Inline — lien dans un texte. MÊME animation que les boutons (la flèche FOC
   slide droite→gauche : l'une sort à droite, l'autre entre par la gauche, et
   le texte glisse) MAIS sans fond, bordure, halo ni padding de bouton, et
   SANS soulignement. La couleur suit le contexte (currentColor) : blanche sur
   fond sombre, noire sur fond clair (ex. box diagnostic). */
.btn--inline {
  align-self: flex-start;    /* ne pas s'étirer dans une carte en flex colonne */
  width: fit-content;
  justify-content: flex-start;
  padding: 0 1.3rem 0 0;     /* "lane" à droite : la flèche s'y loge / s'en va */
  gap: 0;
  background: none;
  border: none;
  box-shadow: none;
  overflow: visible;         /* la flèche peut entrer/sortir hors-cadre */
  color: inherit;
  text-decoration: none;     /* jamais de soulignement */
}
.btn--inline .btn__circle { display: none; }   /* pas de remplissage ni de halo */
.btn--inline .btn__arr {
  width: 12px;
  height: 12px;
  margin-top: -3px;
}
.btn--inline .btn__text { transform: translateX(0); }
/* Une seule flèche visible à la fois (crossfade) → elle "passe" de droite à
   gauche au survol, sans jamais en afficher deux au repos. */
.btn--inline .btn__arr--1 { right: 0; opacity: 1; }        /* visible, après le texte */
.btn--inline .btn__arr--2 { left: -1.3rem; opacity: 0; }   /* masquée à gauche */

/* Survol : pas de remplissage ni de soulignement, juste le swap de flèche. */
.btn--inline:hover {
  color: inherit;
  box-shadow: none;
  text-decoration: none;
}
.btn--inline:hover .btn__text { transform: translateX(1.3rem); }       /* glisse à droite */
.btn--inline:hover .btn__arr--1 { right: -1.3rem; opacity: 0; }        /* sort à droite */
.btn--inline:hover .btn__arr--2 { left: 0; opacity: 1; }               /* entre par la gauche */
.btn--inline:active { scale: 0.97; box-shadow: none; }

/* ============================================================
   CTA « JUMPY » — bouton qui s'arrime au coin (voir js/jump-btn.js)
   ------------------------------------------------------------
   Un .jump-cta saute hors du hero au scroll et s'arrime en bas-droite
   (.is-docked, position fixe). L'animation est pilotée en JS ; ici on
   ne définit que l'état arrimé. À combiner avec .btn.
   ============================================================ */
.jump-cta { will-change: transform; }
.jump-cta.is-docked {
  position: fixed;
  bottom: clamp(1rem, 3vw, 1.75rem);
  right: clamp(1rem, 3vw, 1.75rem);
  z-index: 1001;
  width: auto;                 /* annule un éventuel 100% mobile : pastille de coin */
  box-shadow: 0 10px 30px rgba(10, 10, 10, 0.28);
}

/* ============================================================
   CARTES — base commune
   ------------------------------------------------------------
   .card = structure partagée par TOUTES les cartes du site
   (padding, bordure, rayon, mise en colonne). La taille/structure
   est définie ICI ; seules les COULEURS changent via les variantes
   .card--* (qui ne touchent qu'aux variables --card-*).
   Un cas particulier peut surcharger une variable, ex. une carte
   avec image pleine largeur : .ma-carte { --card-pad: 0; }
   ============================================================ */
.card {
  --card-pad: clamp(1.5rem, 2.5vw, 2rem);
  --card-bg: transparent;
  --card-border-color: rgba(10, 10, 10, 0.2);
  --card-border-width: 1px;
  --card-radius: 0;

  display: flex;
  flex-direction: column;
  padding: var(--card-pad);
  background: var(--card-bg);
  border: var(--card-border-width) solid var(--card-border-color);
  border-radius: var(--card-radius);
}

/* Carte subtile sur fond CLAIR / rouge (léger voile foncé). */
.card--ghost-light {
  --card-bg: rgba(10, 10, 10, 0.13);
  --card-border-color: rgba(10, 10, 10, 0.2);
}

/* Carte subtile sur fond NOIR (léger voile clair). */
.card--ghost-dark {
  --card-bg: rgba(255, 255, 255, 0.13);
  --card-border-color: rgba(255, 255, 255, 0.2);
}

/* Carte pleine noire. */
.card--solid-dark {
  --card-bg: var(--noir);
  --card-border-color: var(--noir);
}

/* Carte pleine rose (ressort sur un fond rouge / noir). */
.card--solid-rose {
  --card-bg: var(--rose);
  --card-border-color: var(--rose);
}

/* Carte contour épais noir (fond transparent). */
.card--outline {
  --card-border-width: 2px;
  --card-border-color: var(--noir);
}

/* ============================================================
   LIENS — Sliding text effect
   Le <a> clippe (overflow:hidden). Le <span.lt> intérieur glisse
   + text-shadow = copie colorée qui apparaît au survol.
   ============================================================ */
.link-slide,
.header__nav-link,
.footer-contact-links a,
.footer-services a,
.legal-links a,
a.text-feu {
  --link-slide-color: var(--rose);
  display: inline-block;
  overflow: hidden;
  line-height: 1.2;
  position: relative;
}

.link-slide > .lt,
.header__nav-link > .lt,
.footer-contact-links a > .lt,
.footer-services a > .lt,
.legal-links a > .lt,
a.text-feu > .lt {
  display: inline-block;
  text-shadow:
    0 calc(-1lh) var(--link-slide-color),
    0 1lh color-mix(in hsl, var(--link-slide-color), transparent 80%);
  transition: translate 0.2s ease-out;
}

.link-slide:is(:hover, :focus-visible) > .lt,
.header__nav-link:is(:hover, :focus-visible) > .lt,
.footer-contact-links a:is(:hover, :focus-visible) > .lt,
.footer-services a:is(:hover, :focus-visible) > .lt,
.legal-links a:is(:hover, :focus-visible) > .lt,
a.text-feu:is(:hover, :focus-visible) > .lt {
  translate: 0 1lh;
  transition-delay: 0.08s;
}

/* a.text-feu (texte déjà rouge sur fond rose) → slide noir */
a.text-feu {
  --link-slide-color: var(--noir);
}

/* ============================================================
   UTILITAIRES
   ============================================================ */
/* sr-only : masqué visuellement, lu par Google et lecteurs d'écran. */
.sr-only {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

/* ============================================================
   REVEALS AU SCROLL — slideFadeInUp
   ------------------------------------------------------------
   .reveal              → état caché (sous + transparent)
   .reveal.is-visible   → état révélé (ajouté en JS via main.js)
   --reveal-delay       → décalage pour créer une cascade (ex. inline
                          style="--reveal-delay:.16s")
   Désactivé sous prefers-reduced-motion (contenu visible d'emblée).
   ============================================================ */
@media (prefers-reduced-motion: no-preference) {
  .reveal {
    opacity: 0;
    transform: translateY(24px);
    transition: opacity 0.7s var(--ease-out-quart),
                transform 0.7s var(--ease-out-quart),
                filter 0.7s var(--ease-out-quart);
    transition-delay: var(--reveal-delay, 0s);
    will-change: opacity, transform, filter;
  }

  /* Variantes — le mouvement épouse la mise en page.
     L'état révélé (.is-visible) remet tout à zéro, donc une variante
     ne fait que redéfinir l'état CACHÉ de départ. */
  .reveal--left  { transform: translateX(-44px); }
  .reveal--right { transform: translateX(44px); }
  .reveal--scale { transform: scale(0.93); }
  .reveal--blur  { transform: translateY(14px); filter: blur(14px); }

  .reveal.is-visible {
    opacity: 1;
    transform: none;
    filter: none;
  }
}

/* ============================================================
   TRAIL "gooey pixel" — overlay réutilisable (voir js/trail.js)
   ------------------------------------------------------------
   Grille plein écran de cellules qui s'allument sous le curseur.
   Décoratif uniquement (pointer-events: none). Couleur pilotable
   par page via --trail-color.
   ============================================================ */
.goo-cursor {
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
}

.goo-cursor__inner {
  width: 100%;
  height: 100%;
  display: grid;
}

.goo-cursor__cell {
  background: var(--trail-color, var(--rose));
  opacity: 0;
  transition: opacity 0.25s ease, background 0.3s ease;
}

/* ============================================================
   PIXEL DISTORTION — média distordu à la souris (voir js/pixel-distortion.js)
   ------------------------------------------------------------
   Le conteneur porte data-distort ; le canvas WebGL recouvre le
   média, qui reste dans le DOM (accessible) mais invisible une fois
   le rendu prêt. Pour la vidéo, opacity:0 garde la lecture (≠ display:none).
   ============================================================ */
[data-distort] {
  position: relative;
}

[data-distort] .distort-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

[data-distort].is-distort-ready > img,
[data-distort].is-distort-ready > video {
  opacity: 0;
}
