/* =============================================================================
   landing-fonctionnalites.css — la page publique « Fonctionnalités ».

   Elle vit dans l'univers de la page d'accueil : mêmes jetons (--bg, --card,
   --t1..t3, --acc, --brd, --r-*), même en-tête, même pied de page. Aucune
   couleur en dur, aucun dégradé de bannière — PRODUCT.md interdit le « grand
   dégradé violet » et les cartes partout.

   Le parti : une page longue, calme, où l'œil descend une colonne de
   démonstrations. Ce qui porte l'information, c'est la VIDÉO ; le texte tient
   en trois lignes sous elle.
   ========================================================================== */

/* ⚠️ `position: relative` N'EST PAS DÉCORATIF. En mode nuit, theme.css pose un
   décor plein écran en `body::before` (fixed, inset 0). Un contenu NON
   positionné passe dessous : le titre restait visible, mais le chapeau, les
   boutons et les textes disparaissaient purement et simplement (mesuré le
   2026-09-01). Les sections de la page d'accueil s'en protègent de la même
   façon — `.lp-section { position: relative }`. */
/* ⚠️ `position: relative` N'EST PAS DÉCORATIF. En mode nuit, theme.css pose un
   décor plein écran en `body::before` (fixed, inset 0). Un contenu NON
   positionné passe dessous : le titre restait visible, mais le chapeau, les
   boutons et les textes disparaissaient purement et simplement (mesuré le
   2026-09-01). Les sections de la page d'accueil s'en protègent de la même
   façon — `.lp-section { position: relative }`. */
/* ── LE RAYON DES BLOCS ────────────────────────────────────────────────────
   Renew donne `--r-lg: 10px` : sur un média de 700 px de large, l'angle se
   voyait à peine et la page paraissait sèche. Les blocs de cette vitrine
   prennent donc un rayon à eux, plus généreux (demande de Jérôme,
   2026-09-01) — mais TermOS garde le sien, qui est vif par identité et ne se
   négocie pas (DESIGN.md : on n'uniformise jamais ENTRE thèmes). */
.fx-page { padding-top: 96px; position: relative; --fx-rayon: 22px; }
html[data-design="termos"] .fx-page { --fx-rayon: var(--radius-block, 8px); }
.fx-ouverture, .fx-groupe, .fx-fin { position: relative; }

/* ── Ouverture ─────────────────────────────────────────────────────────── */
.fx-ouverture { padding: 72px 0 52px; }
.fx-titre {
  font-family: var(--fd);
  font-size: clamp(36px, 4.6vw, 58px); line-height: 1.04;
  letter-spacing: -.028em; color: var(--t1); margin: 0 0 20px;
  text-wrap: balance;
}
.fx-chapeau {
  font-size: 17px; line-height: 1.62; color: var(--t2);
  max-width: 58ch; margin-bottom: 30px;
}
.fx-actions { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }

/* ── Le sommaire, et sa pilule qui glisse ──────────────────────────────────
   LE MOMENT AUTHORED de la page. Une pilule unique se déplace d'un onglet à
   l'autre pendant qu'on descend : le trajet dit que les six domaines sont un
   parcours, pas six pages. Six pastilles qui s'allument tour à tour auraient
   donné la même information sans montrer le chemin.

   Elle bouge en `transform` + `width` sur UN élément absolu : pas de reflow,
   et l'interruption (on remonte en plein trajet) se règle toute seule puisque
   la transition repart de la position courante.

   ⚠️ `position: sticky` meurt si un ancêtre porte `overflow-x: hidden`
   (piège déjà payé sur la page d'accueil). */
.fx-sommaire {
  position: sticky; top: 76px; z-index: 20;
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  backdrop-filter: blur(12px) saturate(1.4);
  border-bottom: 1px solid var(--brd);
}
.fx-sommaire__rail { padding: 9px 24px; }
.fx-sommaire__piste {
  position: relative; display: flex; gap: 2px;
  overflow-x: auto; scrollbar-width: none;
}
.fx-sommaire__piste::-webkit-scrollbar { display: none; }

.fx-sommaire__pilule {
  position: absolute; left: 0; top: 0; height: 100%;
  border-radius: var(--r-pill, 100px);
  background: color-mix(in srgb, var(--acc) 13%, transparent);
  /* Décélération franche : la pilule part vite et se pose. La distance varie
     (deux onglets voisins ou toute la barre) ; la durée, elle, reste la même —
     c'est ce qui donne l'impression d'un objet qui suit, pas d'un curseur qui
     saute. */
  transition: transform .42s cubic-bezier(.16, 1, .3, 1),
              width .42s cubic-bezier(.16, 1, .3, 1),
              scale .28s cubic-bezier(.16, 1, .3, 1),
              opacity .2s ease;
  opacity: 0;                       /* invisible tant que le script n'a pas mesuré */
  pointer-events: none;
  will-change: transform, width;
}
.fx-sommaire__pilule.est-posee { opacity: 1; }

.fx-sommaire__onglet {
  position: relative; z-index: 1;
  display: inline-flex; align-items: center; gap: 7px; white-space: nowrap;
  padding: 8px 15px; border-radius: var(--r-pill, 100px);
  font-size: 13.5px; color: var(--t2); text-decoration: none;
  transition: color .2s ease;
}
.fx-sommaire__onglet:hover { color: var(--t1); }
.fx-sommaire__onglet[aria-current="true"] { color: var(--t1); font-weight: 600; }
.fx-sommaire__nb {
  font-family: var(--fm, monospace); font-size: 11px; color: var(--t3);
}
.fx-sommaire__onglet[aria-current="true"] .fx-sommaire__nb { color: var(--acc); }
.fx-sommaire__onglet:focus-visible {
  outline: 2px solid var(--acc); outline-offset: 2px;
}

/* ── Un domaine ────────────────────────────────────────────────────────── */
.fx-groupe { padding: 58px 0 10px; scroll-margin-top: 132px; }
.fx-groupe__tete { margin-bottom: 22px; }
.fx-groupe__marque {
  font-family: var(--fd); font-size: clamp(27px, 2.7vw, 36px);
  letter-spacing: -.02em; color: var(--t1); margin: 0 0 5px;
}
.fx-groupe__phrase { font-size: 16px; color: var(--t2); }

/* ── Les bandes ────────────────────────────────────────────────────────────
   LA COMPOSITION. La démonstration occupe une large bande ; le texte est un
   panneau posé PAR-DESSUS son bord, à cheval — une partie sur la vidéo, une
   partie à côté. C'est ce chevauchement qui fait la profondeur : deux blocs
   posés côte à côte forment un tableau, deux blocs qui se recouvrent forment
   une scène.

   Toutes les bandes ont la MÊME taille ; seule change la main — panneau à
   droite, puis à gauche. La forme pleine largeur pour la première d'un
   domaine a été essayée puis retirée : la différence de taille cassait la
   descente au lieu de la rythmer.

   ⚠️ Le panneau n'est PAS une carte dans une carte : la bande elle-même n'a
   ni fond ni bordure. Le seul objet posé, c'est le panneau. */
.fx-lignes { display: flex; flex-direction: column; gap: 14px; }

.fx-ligne {
  position: relative;
  /* 63 % + 46 % = 109 % : les deux colonnes se recouvrent, et c'est ce
     dépassement qui fait le chevauchement — une centaine de pixels, assez
     pour qu'on lise « posé dessus ». Baisser l'un sans monter l'autre
     décolle le panneau de la vidéo. */
  display: grid; grid-template-columns: 63% 1fr;
  align-items: center;
  scroll-margin-top: 132px;
}
.fx-ligne--inverse { grid-template-columns: 1fr 63%; }
.fx-ligne--inverse .fx-ligne__media { grid-column: 2; }
.fx-ligne__media { grid-column: 1; }

/* Le panneau. */
.fx-ligne__texte {
  position: absolute; top: 50%; transform: translateY(-50%);
  right: 0; width: 46%;
  padding: 22px 24px 24px;
  background: var(--card, #fff);
  border: 1px solid var(--brd);
  border-radius: var(--fx-rayon, 22px);
  /* Ombre portée : un décalage vertical et un flou large, jamais un halo
     centré (DESIGN.md — un halo sans offset est une décoration). */
  box-shadow: 0 1px 2px rgba(15, 18, 32, .05),
              0 22px 48px -26px rgba(15, 18, 32, .38);
  transition: transform .3s cubic-bezier(.16, 1, .3, 1),
              box-shadow .3s ease, border-color .3s ease;
}
.fx-ligne--inverse .fx-ligne__texte { right: auto; left: 0; }

/* Au survol, le panneau se soulève de deux pixels et l'ombre s'ouvre : la
   scène respire, l'objet reste à sa place. */
.fx-ligne:hover .fx-ligne__texte {
  transform: translateY(-50%) translateY(-3px);
  border-color: color-mix(in srgb, var(--acc) 28%, var(--brd));
  box-shadow: 0 2px 4px rgba(15, 18, 32, .06),
              0 30px 60px -28px rgba(15, 18, 32, .45);
}

.fx-ligne__titre {
  font-family: var(--fd); font-size: 19px; font-weight: 700; color: var(--t1);
  letter-spacing: -.015em; margin: 0 0 8px;
}
.fx-ligne__resume {
  font-size: 14.5px; line-height: 1.6; color: var(--t2);
}

/* ── Les puces ─────────────────────────────────────────────────────────────
   Une démonstration couvre plusieurs fonctionnalités : les puces les nomment
   toutes, sans imposer une vidéo par ligne. Elles s'égrènent à l'entrée —
   c'est une liste, c'est le seul endroit où un décalage en cascade dit
   quelque chose. */
.fx-puces {
  list-style: none; margin: 14px 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 6px;
}
.fx-puces li {
  font-size: 12.5px; line-height: 1; color: var(--t2);
  padding: 7px 11px; border-radius: var(--r-pill, 100px);
  background: color-mix(in srgb, var(--acc) 7%, transparent);
  border: 1px solid color-mix(in srgb, var(--acc) 14%, transparent);
}

/* ── L'emplacement vidéo ───────────────────────────────────────────────────
   ⚠️ CES RÈGLES PORTENT LA HAUTEUR DE LA BANDE. Le panneau est en position
   absolue : il ne compte pas dans le flux. Sans `aspect-ratio` ici, le média
   n'a plus de hauteur, la bande s'effondre et les panneaux des bandes
   suivantes se superposent. Constaté en regardant la page, le 2026-09-01. */
.fx-ligne__media {
  position: relative; aspect-ratio: 16 / 9; overflow: hidden;
  border-radius: var(--fx-rayon, 22px);
  background: color-mix(in srgb, var(--t3) 6%, transparent);
  /* Un filet et une ombre courte : le média est un objet posé sur la page,
     pas un trou découpé dedans. */
  border: 1px solid color-mix(in srgb, var(--brd) 70%, transparent);
  box-shadow: 0 1px 2px rgba(15, 18, 32, .04),
              0 16px 36px -30px rgba(15, 18, 32, .5);
}
.fx-video__film { width: 100%; height: 100%; object-fit: cover; display: block; }

/* En attente : un cadre sobre et honnête, qui dit ce qu'il est. Pas de faux
   bouton de lecture — il n'y a rien à lire pour l'instant. */
.fx-video__attente {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 9px; color: var(--t3);
  background:
    repeating-linear-gradient(
      -45deg,
      color-mix(in srgb, var(--t3) 7%, transparent) 0 10px,
      transparent 10px 20px);
}
.fx-video__attente .lp-ico { font-size: 24px; opacity: .5; }
.fx-video__mention {
  font-family: var(--fm, monospace); font-size: 10.5px;
  letter-spacing: .18em; text-transform: uppercase;
}

/* ── L'ENTRÉE : la démonstration se dévoile ────────────────────────────────
   L'IDÉE MATÉRIELLE de la page, et la seule : le média n'apparaît pas, il se
   DÉCOUVRE. Un masque s'ouvre du bas vers le haut pendant que l'image, elle,
   se détend d'un pour cent — le geste de quelqu'un qui retire une feuille
   posée sur un écran. Le panneau vient ensuite s'y poser depuis le côté.

   Tout le reste est du décor discret : la bande glisse de vingt pixels, les
   puces s'égrènent. Aucun autre effet, aucun rebond.

   ⚠️ L'état par défaut est VISIBLE. Ces règles ne s'appliquent que si le
   script a posé `.fx-anime` sur <html> : script en échec, page entière
   lisible. C'est la règle du dépôt, et la seule façon d'être correct pour
   les moteurs de recherche. */
.fx-anime .fx-entre {
  opacity: 0;
  transform: translate3d(var(--fx-dx, 0), 16px, 0);
  transition: opacity .5s cubic-bezier(.16, 1, .3, 1),
              transform .66s cubic-bezier(.16, 1, .3, 1);
}
.fx-anime .fx-ligne { --fx-dx: -18px; }
.fx-anime .fx-ligne--inverse { --fx-dx: 18px; }
.fx-anime .fx-entre.est-entre { opacity: 1; transform: none; }

/* Le masque du média. `clip-path` s'anime sur le compositeur, comme une
   transformation : seize bandes peuvent le faire sans faire tousser la page. */
.fx-anime .fx-ligne__media {
  clip-path: inset(0 0 100% 0);
  transition: clip-path .78s cubic-bezier(.16, 1, .3, 1) 60ms;
}
.fx-anime .fx-ligne.est-entre .fx-ligne__media { clip-path: inset(0 0 0 0); }

/* L'image se détend derrière le masque : 1,04 → 1. C'est ce qui empêche le
   dévoilement de ressembler à un simple store qui monte. */
.fx-anime .fx-ligne__media > * {
  transform: scale(1.045);
  transition: transform 1.05s cubic-bezier(.16, 1, .3, 1) 60ms;
}
.fx-anime .fx-ligne.est-entre .fx-ligne__media > * { transform: scale(1); }

/* Le panneau entre en DERNIER et depuis le côté opposé à sa bande : il vient
   se poser sur la vidéo, au lieu d'arriver avec elle. C'est le geste qui
   raconte le chevauchement.
   ⚠️ Sa translation doit conserver le `translateY(-50%)` qui le centre —
   sans lui, il partirait se coller en haut de la bande. */
.fx-anime .fx-ligne .fx-ligne__texte {
  opacity: 0;
  transform: translateY(-50%) translate3d(30px, 0, 0);
  transition: opacity .5s cubic-bezier(.16, 1, .3, 1) 260ms,
              transform .66s cubic-bezier(.16, 1, .3, 1) 260ms;
}
.fx-anime .fx-ligne--inverse .fx-ligne__texte {
  transform: translateY(-50%) translate3d(-30px, 0, 0);
}
.fx-anime .fx-ligne.est-entre .fx-ligne__texte {
  opacity: 1; transform: translateY(-50%);
}

/* Les puces s'égrènent — 45 ms d'écart, six au plus : la cascade se termine
   avant qu'on ait fini de lire le titre. Le rang est posé par le script. */
.fx-anime .fx-puces li {
  opacity: 0; transform: translate3d(0, 8px, 0);
  transition: opacity .34s ease-out, transform .42s cubic-bezier(.16, 1, .3, 1);
  transition-delay: calc(340ms + var(--rang, 0) * 45ms);
}
.fx-anime .fx-ligne.est-entre .fx-puces li { opacity: 1; transform: none; }

/* Le point du domaine se pose : il arrive juste après son mot. */
.fx-anime .fx-groupe__marque .af-marque__point {
  opacity: 0; transform: scale(.4);
  transition: opacity .3s ease-out 180ms,
              transform .5s cubic-bezier(.16, 1, .3, 1) 180ms;
}
.fx-anime .fx-groupe__tete.est-entre .af-marque__point {
  opacity: 1; transform: none;
}

/* ── LE PARALLAXE, quand le navigateur sait le faire sans script ────────────
   `animation-timeline: view()` fait défiler l'image DANS son cadre au rythme
   de la page : elle vit pendant qu'on descend. C'est calculé par le
   compositeur, pas par un écouteur de défilement — donc gratuit là où c'est
   supporté, et simplement absent ailleurs. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .fx-ligne__media > * {
      animation: fx-derive linear both;
      animation-timeline: view();
      animation-range: entry 10% exit 90%;
    }
    /* ⚠️ L'animation prend la main sur `transform` : la remise à l'échelle de
       l'entrée doit donc vivre DANS l'animation, pas à côté, sinon l'une
       écrase l'autre et l'image reste figée à 1,045. */
    @keyframes fx-derive {
      from { transform: scale(1.06) translate3d(0, -2.2%, 0); }
      to   { transform: scale(1.06) translate3d(0, 2.2%, 0); }
    }
  }
}

/* ── Fin de page ───────────────────────────────────────────────────────── */
.fx-fin {
  padding: 78px 0 86px; margin-top: 52px;
  border-top: 1px solid var(--brd); text-align: center;
}
.fx-fin h2 {
  font-family: var(--fd); font-size: clamp(25px, 2.7vw, 33px);
  color: var(--t1); margin-bottom: 10px; letter-spacing: -.02em;
}
.fx-fin p { color: var(--t2); margin-bottom: 22px; }
.fx-fin .fx-actions { justify-content: center; }

/* ── Écrans étroits ────────────────────────────────────────────────────────
   La bande se replie : média au-dessus, texte dessous, dans les deux sens
   d'alternance (sinon une rangée sur deux afficherait son texte en premier
   et l'œil ne saurait plus où commencer). */
@media (max-width: 980px) {
  /* Le chevauchement demande de la largeur : en dessous, le panneau
     reprendrait toute la vidéo. Il redescend donc sous elle, en flux, et
     remonte juste assez pour rester lié à son image. */
  .fx-ligne, .fx-ligne--inverse { grid-template-columns: 1fr; }
  .fx-ligne--inverse .fx-ligne__media { grid-column: 1; }
  .fx-ligne__texte,
  .fx-ligne--inverse .fx-ligne__texte {
    position: static; width: auto; transform: none;
    margin: -28px 16px 0; padding: 20px 22px 22px;
  }
  .fx-ligne:hover .fx-ligne__texte { transform: translateY(-2px); }
  .fx-anime .fx-ligne .fx-ligne__texte,
  .fx-anime .fx-ligne--inverse .fx-ligne__texte {
    transform: translate3d(0, 14px, 0);
  }
  .fx-anime .fx-ligne.est-entre .fx-ligne__texte { transform: none; }
}

/* ── Animations réduites ───────────────────────────────────────────────────
   Réglage d'accessibilité posé par l'utilisateur : rien ne bouge, rien ne
   démarre, et le collant disparaît (il donne le mal de cœur à certains).
   Le contenu, lui, ne dépend d'aucune de ces règles pour être lisible. */
@media (prefers-reduced-motion: reduce) {
  .fx-sommaire { position: static; backdrop-filter: none; }
  .fx-sommaire__pilule { transition: none; }
  .fx-anime .fx-entre { opacity: 1; transform: none; transition: none; }
  .fx-anime .fx-ligne .fx-ligne__texte,
  .fx-anime .fx-ligne--inverse .fx-ligne__texte {
    opacity: 1; transform: translateY(-50%); transition: none;
  }
  .fx-anime .fx-ligne__media { clip-path: none; transition: none; }
  .fx-anime .fx-ligne__media > * { transform: none; transition: none; animation: none; }
  .fx-anime .fx-puces li { opacity: 1; transform: none; transition: none; }
  .fx-anime .fx-groupe__marque .af-marque__point { opacity: 1; transform: none; transition: none; }
  .fx-ligne__texte { transition: none; }
}

/* =============================================================================
   LA SECTION DE LA PAGE D'ACCUEIL (#fonctionnalites)

   Six portes vers le catalogue. Elles doivent se lire d'un coup d'œil, sans
   rivaliser avec les chapitres qui les précèdent : pas d'ombre portée, pas de
   fond plein — un simple filet, et le nombre qui donne l'échelle.
   Cette feuille est chargée par les DEUX pages (l'accueil l'inclut aussi).
   ========================================================================== */
.lp-fonc-grille {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px;
  margin-top: 26px;
}
@media (max-width: 900px) { .lp-fonc-grille { grid-template-columns: repeat(2, 1fr); } }

.lp-fonc-carte {
  display: block; padding: 18px 20px 20px;
  /* Meme parti que la page « Fonctionnalites » : plus rond que le `--r-lg`
     de Renew (10 px), qui se voyait a peine sur un bloc de cette taille.
     TermOS garde ses angles vifs. */
  border: 1px solid var(--brd); border-radius: 18px;
  text-decoration: none; background: transparent;
  transition: border-color .18s, transform .18s, background .18s;
}
.lp-fonc-carte:hover {
  border-color: color-mix(in srgb, var(--acc) 45%, var(--brd));
  background: color-mix(in srgb, var(--acc) 5%, transparent);
  transform: translateY(-2px);
}
.lp-fonc-carte__nb {
  display: block; font-family: var(--fm, monospace); font-size: 12px;
  letter-spacing: .16em; color: var(--acc); margin-bottom: 8px;
}
.lp-fonc-carte__titre {
  display: block; font-family: var(--fd); font-size: 17px; font-weight: 700;
  color: var(--t1); letter-spacing: -.01em; margin-bottom: 5px;
}
.lp-fonc-carte__phrase {
  display: block; font-size: 13.5px; line-height: 1.55; color: var(--t2);
}
html[data-design="termos"] .lp-fonc-carte { border-radius: var(--radius-block, 8px); }
.lp-fonc-action { margin-top: 22px; text-align: center; }   /* le titre de la section est centré : le bouton aussi */

@media (prefers-reduced-motion: reduce) {
  .lp-fonc-carte, .lp-fonc-carte:hover { transform: none; }
}

/* ── L'écrasement de la pilule ─────────────────────────────────────────────
   Pendant qu'elle file d'un onglet à l'autre, elle s'étire dans le sens de la
   marche et s'aplatit un peu — l'élan d'un objet qui a une masse. Elle ne
   dépasse jamais sa cible et ne revient pas en arrière : c'est un étirement,
   pas un rebond (le rebond par réflexe est une facilité, pas une intention).
   La classe est posée 260 ms par le script, le temps du trajet. */
.fx-sommaire__pilule.file { transform-origin: center; }
.fx-sommaire__pilule.file { scale: 1.06 0.94; }
@media (prefers-reduced-motion: reduce) {
  .fx-sommaire__pilule.file { scale: none; }
}
