/* fx3d-site.css — couche 3D de TOUT forxell.com (fichier NEUF, additif).
 *
 * Injecté par nginx sur les 1 673 pages, comme nav-burger.css. C'est la seule
 * façon d'habiller le site entier sans éditer un seul fichier HTML existant —
 * la règle « ajout seul » du 25/07 y tient, et 1 673 diffs seraient de toute
 * façon impossibles à relire.
 *
 * ⚠️ Tout est porté par `html.fx3d-site`, classe posée par fx3d-site.js à son
 * exécution. Si le script échoue ou est bloqué, AUCUNE de ces règles ne
 * s'applique : le site reste exactement celui d'avant, jamais à moitié
 * transformé. C'est volontaire — une page à moitié animée est pire qu'une page
 * sans animation.
 *
 * ⚠️ La maquette /apercu-3d/ porte `html.fx3d` et sa propre couche : le script
 * s'y abstient pour ne pas superposer deux scènes.
 */

/* ───────────────────── 1. Champ de points en arrière-plan ────────────────── */

/* `isolation: isolate` fait de <body> un contexte d'empilement. Sans lui, un
   enfant en z-index -1 passerait DERRIÈRE le dégradé de fond du body et on ne
   verrait rien. Avec lui, il se place entre le fond et le contenu — exactement
   la couche voulue. La propriété n'a aucun effet de mise en page. */
html.fx3d-site body { isolation: isolate; }

html.fx3d-site .fx3d-amb {
  position: fixed; inset: 0; z-index: -1;
  pointer-events: none;
  opacity: 0; transition: opacity 1.6s ease .25s;
}
html.fx3d-site .fx3d-amb.ready { opacity: 1; }
html.fx3d-site .fx3d-amb canvas { display: block; width: 100%; height: 100%; }

/* ──────────────────── 2. Cartes : inclinaison et reflet ──────────────────── */

/* La classe est posée par le script sur les blocs qui sont des SURFACES (une
   carte de module, un plan tarifaire, une fiche d'aide), jamais sur les
   commandes (onglets, puces, éléments de menu) : incliner un bouton qu'on
   s'apprête à cliquer donne une impression de flottement, pas de matière. */
html.fx3d-site .fx-tilt {
  position: relative;
  transform-style: preserve-3d;
  transition: transform .45s cubic-bezier(.22,.8,.3,1), box-shadow .45s, border-color .3s;
}
/* `will-change` seulement au survol : posé en permanence sur les 200 cartes
   d'une page, il réserve une couche GPU par carte et coûte plus qu'il ne rend. */
html.fx3d-site .fx-tilt.fx-on { will-change: transform; }
html.fx3d-site .fx-tilt.fx-on {
  box-shadow: 0 28px 64px -26px rgba(7,13,36,.9), 0 0 0 1px rgba(91,91,245,.26);
  border-color: rgba(91,91,245,.42);
}

/* Reflet spéculaire suivant le pointeur : c'est lui qui fait lire une surface
   inclinée plutôt qu'une image déformée.
   ⚠️ `.video-wrap` est exclu — il utilise DÉJÀ ::after pour son dégradé de bas
   de cadre (index.html), que cette règle remplacerait en silence. */
html.fx3d-site .fx-tilt:not(.video-wrap)::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background: radial-gradient(220px circle at var(--mx, 50%) var(--my, 50%),
              rgba(120,140,255,.15), transparent 60%);
  opacity: 0; transition: opacity .35s; pointer-events: none;
}
html.fx3d-site .fx-tilt.fx-on:not(.video-wrap)::after { opacity: 1; }

/* ─────────────────── 3. Arrivée des blocs depuis la profondeur ───────────── */

html.fx3d-site .fx-rise {
  opacity: 0;
  transform: perspective(1500px) translate3d(0, 26px, -90px) rotateX(5deg);
  transition: opacity .7s cubic-bezier(.22,.8,.3,1),
              transform .9s cubic-bezier(.22,.8,.3,1);
}
html.fx3d-site .fx-rise.fx-in { opacity: 1; transform: none; }

/* ───────────────────────── 4. Logo, boutons, liens ───────────────────────── */

/* Le X du logo de la barre tourne EN CONTINU sur son axe vertical.
 *
 * Seul le X tourne, pas le mot : « ForXell » vu de profil ne se lit plus, et un
 * nom de marque illisible une seconde sur deux est un contresens. Le X, lui, est
 * symétrique — il reste lui-même sous tous les angles.
 *
 * 9 s par tour : assez lent pour qu'on ne le regarde pas, assez présent pour
 * qu'on le remarque. Une rotation rapide sur un élément permanent de
 * l'interface devient vite fatigante.
 *
 * La perspective est posée sur le PARENT : sans elle, rotateY se réduit à une
 * compression horizontale — aucune profondeur, le X a l'air de se replier à plat.
 */
html.fx3d-site .logo { perspective: 460px; }
html.fx3d-site .logo-x {
  transform-style: preserve-3d;
  animation: fx3d-logo-tourne 9s linear infinite;
}
/* Au survol il accélère : le logo répond à la main sans changer de nature. */
html.fx3d-site .logo:hover .logo-x { animation-duration: 2.2s; }

@keyframes fx3d-logo-tourne {
  from { transform: rotateY(0deg); }
  to   { transform: rotateY(360deg); }
}

html.fx3d-site .btn {
  transition: transform .26s cubic-bezier(.22,.8,.3,1), box-shadow .26s, filter .26s;
}
html.fx3d-site .btn:hover { transform: translateY(-2px) scale(1.015); }

/* ────────────────── 5. Respect de « animations réduites » ────────────────── */

@media (prefers-reduced-motion: reduce) {
  html.fx3d-site .fx-tilt,
  html.fx3d-site .btn,
  html.fx3d-site .logo-x { animation: none !important; }
  html.fx3d-site .logo-x,
  html.fx3d-site .fx-rise,
  html.fx3d-site .fx3d-amb { transition: none !important; }
  html.fx3d-site .fx-rise { opacity: 1; transform: none; }
}

/* ═════════ 6. Sélecteur de langue : le défaut de toutes les pages ══════════
 *
 * Mesuré le 16/09 à 1440 px, identique sur la home, tarifs, faq, aide… :
 * `<div class="lang-selector">` est un enfant direct de <nav> placé APRÈS
 * `nav > .wrap`. Il s'étale donc sur 1 440 px, SOUS la barre — le bouton se
 * colle au bord GAUCHE, et `.lang-dropdown { right: 0 }` s'aligne sur le bord
 * droit de ce bloc pleine largeur, soit 1 270 px plus loin. Le bouton d'un
 * côté, son menu de l'autre : c'est ce que Plamen a signalé.
 *
 * Le marqueur `<!--FORXELL-LANG-SEL-->` laissé DANS `.nav-links` montre que la
 * place prévue était la barre : l'insertion se fait au mauvais marqueur.
 * fx3d-site.js remet le noeud à sa place ; ce qui suit l'habille.
 */

html.fx3d-site .nav-links .lang-selector { position: relative; }
/* `flex-shrink: 0` seulement DANS la barre. Posé partout, il empêchait la
   pastille de se comprimer sur film.html — dont l'en-tête est fait main, sans
   `.nav-links` — et rallongeait de 17 px une page qui débordait déjà. Une règle
   générique doit se limiter au contexte pour lequel elle a été écrite. */
html.fx3d-site .nav-links .lang-selector { flex-shrink: 0; }
html.fx3d-site .nav-links .lang-current { padding: 9px 13px; white-space: nowrap; transition: background .18s, border-color .18s; }
html.fx3d-site .nav-links .lang-current:hover { background: rgba(255,255,255,.10); }

/* Sous 1200 px la pastille garde le drapeau et perd son libellé (58 px de
   gagnés), et l'espacement des liens se resserre de 30 à 18 px (7 écarts, soit
   84 px). Sans ces deux économies, la barre ne tiendrait qu'au-dessus de
   1 070 px et un portable de 1 024 px basculerait sur le menu burger.
   Un drapeau se comprend sans traduction ; 12 px d'écart en moins, non. */
@media (max-width: 1200px) {
  html.fx3d-site .nav-links .lang-current > span { display: none; }
}
@media (max-width: 1280px) {
  html.fx3d-site .nav-links { gap: 18px; }
}

/* 27 langues d'un coup d'oeil, au lieu d'une colonne de 170 px qui défile. */
html.fx3d-site .nav-links .lang-dropdown {
  top: calc(100% + 14px); right: 0;
  display: grid !important;              /* bat le display:none d'origine…    */
  grid-template-rows: repeat(9, auto);   /* 9 lignes ⇒ 3 colonnes             */
  grid-auto-flow: column;                /* remplies colonne par colonne :    */
  gap: 2px 6px;                          /* l'ordre d'origine est conservé    */
  min-width: 0; width: max-content; max-width: min(560px, calc(100vw - 32px));
  max-height: none; overflow: visible;
  padding: 10px; border-radius: 18px; background: #0B1230;
  border: 1px solid var(--stroke);
  box-shadow: 0 28px 64px rgba(0,0,0,.52);
  transform: perspective(900px) rotateX(-12deg); transform-origin: top center;
  opacity: 0; visibility: hidden;        /* … et pilote l'ouverture ici       */
  transition: opacity .2s ease, transform .28s cubic-bezier(.22,.8,.3,1), visibility .28s;
}
html.fx3d-site .nav-links .lang-selector.open .lang-dropdown {
  opacity: 1; visibility: visible; transform: perspective(900px) rotateX(0deg);
}

/* ⚠️ brand.css masque TOUT <a> DESCENDANT de .nav-links sous 760 px
   (`.nav-links a:not(.btn)` — descendance, pas enfant direct). En remontant le
   sélecteur dans la barre, ses 27 liens tombent sous cette règle et le panneau
   s'ouvre VIDE. Spécificité (0,3,0) contre (0,2,1) : on repasse devant. */
html.fx3d-site .nav-links .lang-dropdown .lang-item { display: flex; }

html.fx3d-site .nav-links .lang-item {
  padding: 9px 14px; border-radius: 11px; font-size: 14px; white-space: nowrap;
  transition: background .14s, color .14s;
}
html.fx3d-site .nav-links .lang-item.active {
  background: rgba(91,91,245,.20); box-shadow: inset 0 0 0 1px rgba(91,91,245,.42);
}

/* ═════ 7. La barre se replie dès 960 px, plus seulement 760 ════════════════
 *
 * Remettre la pastille dans la barre l'allonge, même réduite au drapeau. Le
 * site débordait DÉJÀ horizontalement entre 761 et 864 px — un iPad en
 * portrait (768 px) affichait 864 px de contenu. On ne pouvait pas aggraver.
 *
 * Plutôt que de rogner les libellés jusqu'à l'illisible, la barre se replie
 * plus tôt. Les règles reproduisent celles de nav-burger.css (limitées à
 * 760 px) pour la tranche 761–960 : ce fichier est injecté sur les 1 673 pages,
 * le modifier changerait le comportement de toutes — GO de Plamen requis.
 */
@media (min-width: 761px) and (max-width: 960px) {
  html.fx3d-site .nav-burger { display: flex; }
  html.fx3d-site .nav-links > a:not(.nav-burger),
  html.fx3d-site .nav-links > .btn { display: none; }

  html.fx3d-site nav.mobile-menu-open .nav-links {
    position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 2px;
    padding: 10px 20px 20px; background: #0B1230;
    border-bottom: 1px solid var(--stroke);
    box-shadow: 0 20px 44px rgba(0,0,0,.4);
    max-height: calc(100vh - 72px); overflow-y: auto;
  }
  html.fx3d-site nav.mobile-menu-open .nav-links > a:not(.nav-burger) {
    display: block; padding: 12px 4px; border-bottom: 1px solid rgba(122,140,200,.12);
  }
  html.fx3d-site nav.mobile-menu-open .nav-links > .btn {
    display: flex; margin-top: 10px; justify-content: center;
  }
}

/* Barre repliée (burger visible, jusqu'à 960 px) : la liste des langues coule
   dans le panneau au lieu de flotter par-dessus et d'en sortir par le bas. */
@media (max-width: 960px) {
  /* ⚠️ Largeur EXPLICITE : avec `repeat(auto-fill, …)`, une largeur
     intrinsèque (`max-content`) n'a aucune référence pour compter les colonnes
     et le moteur aligne les 27 langues sur UNE ligne — 1 753 px de contenu
     dans 1 000 px de large, mesuré. */
  html.fx3d-site .nav-links .lang-dropdown {
    right: 0; left: auto;
    width: min(540px, calc(100vw - 24px)); max-width: none;
    grid-template-rows: none; grid-auto-flow: row;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    max-height: 60vh; overflow-y: auto;
  }
  /* nav-burger.css pose `align-self: flex-start` sur le sélecteur : sans ceci
     la grille reste à la largeur de la pastille, soit une colonne de 27 lignes
     sur 1 146 px de haut. On étire le conteneur, pas le bouton. */
  html.fx3d-site nav.mobile-menu-open .nav-links .lang-selector {
    align-self: stretch; display: flex; flex-direction: column; align-items: flex-start;
  }
  html.fx3d-site nav.mobile-menu-open .nav-links .lang-dropdown {
    position: static; width: auto; max-width: none; max-height: none;
    overflow: visible; transform: none; margin-top: 6px; align-self: stretch;
  }
}

@media (prefers-reduced-motion: reduce) {
  html.fx3d-site .nav-links .lang-dropdown, html.fx3d-site .nav-links .lang-current { transition: none !important; }
  html.fx3d-site .nav-links .lang-dropdown,
  html.fx3d-site .nav-links .lang-selector.open .lang-dropdown { transform: none; }
}
