/* ==================================================================
   Workflaws — vitrine (site statique)
   Styles repris tels quels de l'ancien thème WordPress : mêmes variables,
   même maquette, même thème clair/sombre. Les polices Archivo sont
   auto-hébergées dans assets/fonts/.
   ================================================================== */

/* ==================================================================
   Workflaws theme styles
   Toutes les règles ci-dessous reprennent la vitrine à l'identique.
   Les polices Archivo sont servies depuis assets/fonts/.
   ================================================================== */

/* ------------------------------------------------------------------ */
/*  Fonts (self-hosted, latin subset)                                  */
/* ------------------------------------------------------------------ */
@font-face{
  font-family:"Archivo Expanded";font-style:normal;font-weight:700;font-display:swap;
  src:url(../fonts/archivo-expanded-700.woff2) format("woff2");
}
@font-face{
  font-family:"Archivo";font-style:normal;font-weight:400;font-display:swap;
  src:url(../fonts/archivo-400.woff2) format("woff2");
}
@font-face{
  font-family:"Archivo";font-style:normal;font-weight:600;font-display:swap;
  src:url(../fonts/archivo-600.woff2) format("woff2");
}

/* ------------------------------------------------------------------ */
/*  Jetons — thème clair unique                                        */
/*                                                                     */
/*  Le site était sombre. Il passe en clair : matière, profondeur et    */
/*  geste plutôt que régie et néon. `color-scheme:light` prévient le    */
/*  navigateur pour que barres de défilement, champs et menus natifs    */
/*  suivent.                                                            */
/*                                                                     */
/*  L'or de la marque est CONSERVÉ. Sur fond clair il ne peut pas       */
/*  servir de couleur de texte — 2,15:1 sur blanc, très en dessous du   */
/*  seuil. Il sert de matière : fond de bouton avec du texte encre      */
/*  dessus (8,77:1), aplats, jalons. Pour les liens et les petits       */
/*  libellés colorés, --accent-lisible, un or assombri qui passe le     */
/*  seuil sur blanc.                                                    */
/* ------------------------------------------------------------------ */
:root{
  color-scheme:light;
  --ground:#FBFBFC; --ground-2:#F2F2F5;
  --panel:#FFFFFF; --panel-2:#F5F5F8;
  --line:rgba(17,17,22,.09); --line-strong:rgba(17,17,22,.17);
  /* Les trois encres passent toutes le seuil AA sur le fond le plus clair
     comme sur le plus foncé des trois : 16,5 / 6,3 / 5,1 pour 1. La plus
     pâle était à 2,8 — elle servait aux libellés secondaires, qui sont du
     texte comme les autres. */
  --ink:#111116; --ink-muted:#585863; --ink-faint:#666673;
  --accent:#EBA23C; --accent-2:#F7C55E; --on-accent:#1A1206;
  /* l'or ne se lit pas sur blanc : celui-ci si (4,52:1) */
  --accent-lisible:#8A580B;
  /* même histoire pour le vert : --pin-green ne vaut que 4,25:1 sur blanc,
     celui-ci 6,50:1. Il sert partout où le vert porte du texte. */
  --green-lisible:#1F6B41;
  --accent-soft:rgba(235,162,60,.15); --glow:rgba(235,162,60,.30);
  --pin-red:#D6412A; --pin-green:#2E8B57; --pin-cyan:#1B7F9E;
  --pin-yellow:#B98A11; --pin-blue:#3B62C4;
  /* Sur clair, une ombre noire pure salit. Elles sont teintées de la
     couleur du fond et portent plus loin qu'elles ne sont sombres :
     c'est ce qui donne la matière sans donner le crayon gras. */
  --shadow:0 1px 3px rgba(17,17,40,.05),0 12px 28px -14px rgba(17,17,40,.16);
  --shadow-lg:0 2px 6px rgba(17,17,40,.05),0 40px 80px -32px rgba(17,17,40,.24);
}

/* ------------------------------------------------------------------ */
/*  Base                                                               */
/* ------------------------------------------------------------------ */
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  position:relative;
  margin:0;background:var(--ground);color:var(--ink);
  font-family:"Archivo",system-ui,-apple-system,"Segoe UI",sans-serif;
  font-size:16px;line-height:1.65;-webkit-font-smoothing:antialiased;
  /* overflow-x porté par <html> et non ici : sur <body> il se propage au
     viewport et neutralise les animations liées au défilement. */
}

/* Le rail de montage qui bordait la page a été retiré avec le passage au
   clair : c'était un décor de régie, cohérent sur fond sombre, encombrant
   sur fond clair. L'air le remplace. */
html{overflow-x:clip}

.nav,main,.foot{position:relative;z-index:1}
.wf-mono{font-family:ui-monospace,"SF Mono","JetBrains Mono",Menlo,Consolas,monospace}
h1,h2,h3{font-family:"Archivo Expanded","Archivo",system-ui,sans-serif;font-weight:700;
  line-height:1.04;letter-spacing:-.01em;margin:0}
p{margin:0}
a{color:inherit;text-decoration:none}
img,svg{display:block;max-width:100%}
/* L'anneau reprend l'or lisible, pas l'or de marque : sur le fond clair, --accent
   ne pèse que 2,08:1 quand un indicateur de focus en demande 3 (WCAG 1.4.11).
   C'est le même motif que pour le texte, et la même variable. */
:focus-visible{outline:2px solid var(--accent-lisible);outline-offset:3px;border-radius:4px}

/* Lisible par les lecteurs d'écran, invisible à l'œil. clip-path plutôt que
   display:none, qui retirerait le texte de l'arbre d'accessibilité. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0}

/* Passer la navigation d'un coup : premier arrêt de tabulation de chaque page,
   invisible tant qu'il n'a pas le focus. */
.skip{position:absolute;left:50%;top:0;transform:translate(-50%,-120%);z-index:100;
  background:var(--panel);color:var(--ink);border:1px solid var(--line-strong);
  border-radius:0 0 10px 10px;padding:.7rem 1.2rem;font-size:.9rem;font-weight:600;
  box-shadow:var(--shadow);transition:transform .18s}
.skip:focus{transform:translate(-50%,0)}

.wrap{max-width:1140px;margin:0 auto;padding:0 clamp(1.15rem,5vw,2.6rem)}
.section{padding:clamp(1.9rem,4.5vw,3.75rem) 0}

.eyebrow{
  font-family:ui-monospace,"SF Mono",Menlo,monospace;font-size:.72rem;font-weight:400;
  letter-spacing:.22em;text-transform:uppercase;color:var(--accent-lisible);
  display:inline-flex;align-items:center;gap:.6em;
}
.eyebrow::before{content:"";width:1.7em;height:1px;background:var(--accent-lisible);opacity:.55}

.lead{font-size:clamp(1.05rem,1.7vw,1.24rem);line-height:1.6;color:var(--ink-muted);max-width:56ch}

/* ------------------------------------------------------------------ */
/*  Buttons / chips                                                    */
/* ------------------------------------------------------------------ */
.btn{
  display:inline-flex;align-items:center;gap:.55em;justify-content:center;
  font-family:"Archivo",sans-serif;font-weight:600;font-size:.95rem;
  padding:.62em 1.35em;border-radius:999px;cursor:pointer;border:1px solid transparent;
  /* Ressort court plutôt qu'un ease linéaire : le bouton répond au doigt.
     L'enfoncement au :active fait le reste du travail tactile. */
  transition:transform .24s cubic-bezier(.2,.9,.3,1),box-shadow .24s,background .2s,border-color .2s;
  white-space:nowrap;
}
.btn--primary{background:var(--accent);color:var(--on-accent);box-shadow:0 6px 20px -8px var(--glow)}
.btn--primary:hover{transform:translateY(-1px);box-shadow:0 12px 30px -10px var(--glow);filter:brightness(1.04)}
.btn:active{transform:scale(.975)}
.btn--ghost{background:transparent;color:var(--ink);border-color:var(--line-strong)}
.btn--ghost:hover{background:var(--panel-2);border-color:var(--line-strong);transform:translateY(-1px)}
.btn--block{width:100%}

/* ------------------------------------------------------------------ */
/*  Nav                                                                */
/* ------------------------------------------------------------------ */
/* La barre est un matériau posé sur la page, pas un bandeau opaque : le
   contenu la traverse en se floutant. La saturation compense le lavage que le
   flou produit sur les couleurs qui passent dessous.
   Repli sous prefers-reduced-transparency : sans flou, il faut de l'opacité,
   sinon le texte se lit par-dessus une image. */
.nav{
  position:sticky;top:0;z-index:50;
  backdrop-filter:saturate(180%) blur(20px);
  -webkit-backdrop-filter:saturate(180%) blur(20px);
  background:color-mix(in srgb,var(--ground) 72%,transparent);
  border-bottom:1px solid var(--line);
}
@media (prefers-reduced-transparency:reduce){
  .nav{background:var(--ground);backdrop-filter:none;-webkit-backdrop-filter:none}
}
/* position:relative — le panneau du menu mobile s'y accroche.
   56 px : la barre ne doit pas manger la vue. */
.nav__in{position:relative;display:flex;align-items:center;justify-content:space-between;gap:1rem;height:56px}
.brand{display:flex;align-items:center;gap:.6rem;font-family:"Archivo Expanded","Archivo",sans-serif;
  font-weight:700;font-size:1.12rem;letter-spacing:-.01em}
/* Le lockup horizontal remplace l'icône et le mot, en haut comme en pied. Il
   est composé pour ce rapport (520x120) : le logo vertical, lui, ne tient pas
   dans une barre de navigation — son mot tombe à 10 px et devient une tache. */
.brand__logo{height:clamp(26px,2.6vw,34px);width:auto;display:block}
.foot .brand__logo{height:clamp(28px,3vw,38px)}
.nav__links{display:flex;align-items:center;gap:1.6rem}
.nav__links a{font-size:.9rem;color:var(--ink-muted);transition:color .18s}
.nav__links a:hover{color:var(--ink)}
.nav__cta{display:flex;align-items:center;gap:.7rem}
/* Sélecteur de langue : la page courante n'est pas un lien. */
.lang{display:flex;align-items:center;gap:.3rem;font-family:ui-monospace,Menlo,monospace;
  font-size:.72rem;letter-spacing:.06em;color:var(--ink-faint)}
.lang a{color:var(--ink-faint);padding:.2em .3em;border-radius:4px;transition:color .18s}
.lang a:hover{color:var(--ink)}
.lang [aria-current="true"]{color:var(--accent-lisible);font-weight:600}
.lang span[aria-hidden]{opacity:.4}

/* ---- Le menu, sous 820 px -------------------------------------------
   Les liens étaient simplement masqués, sans rien pour les remplacer :
   FAQ et Contact devenaient inatteignables depuis l'en-tête. Le bouton
   déroule le même <nav>, en panneau sous la barre.

   Le bouton n'existe qu'en dessous du seuil, et les liens redeviennent
   une rangée au-dessus : une seule liste sert les deux mises en page. */
.nav__burger{display:none;width:38px;height:38px;flex:none;padding:0;cursor:pointer;
  border:1px solid var(--line-strong);border-radius:9px;background:transparent;
  color:var(--ink);place-items:center;transition:border-color .18s,color .18s}
.nav__burger:hover{border-color:var(--accent-lisible);color:var(--accent-lisible)}
.nav__burger svg{width:19px;height:19px}

/* 1040 px et non 820 : à sept liens, la barre demande 885 px et n'en a que
   817 à 900 px de fenêtre — les liens passaient sous les boutons. Ce seuil-ci
   n'a rien à voir avec celui de l'ouverture animée (voir plus bas, 820 px) :
   c'est un problème d'encombrement de la barre, pas d'animation. Si on le
   change, changer aussi le matchMedia jumeau dans main.js, qui referme le
   menu au franchissement. */
@media (max-width:1040px){
  /* Le bouton n'apparaît que si le script s'est attaché (.js-menu) : un
     bouton qui n'ouvre rien serait pire que pas de bouton. Sans JavaScript on
     retrouve le comportement d'avant — le pied de page porte les mêmes liens. */
  .nav__in.js-menu .nav__burger{display:grid}
  .nav__links{
    position:absolute;top:100%;left:0;right:0;
    flex-direction:column;align-items:stretch;gap:0;
    padding:.4rem clamp(1.15rem,5vw,2.6rem) .9rem;
    /* Fond plein, contrairement à la barre : le titre de l'accueil est énorme
       et clair, et même 4 % de transparence le laissait lire au travers. */
    background:var(--ground);
    border-bottom:1px solid var(--line);
    box-shadow:var(--shadow-lg);
    /* fermé par défaut, y compris sans JavaScript : le bouton est le seul
       moyen d'ouvrir, et il n'apparaît que si le script a pu s'attacher */
    display:none;
  }
  .nav__in.ouvert .nav__links{display:flex}
  .nav__links a{padding:.75rem .2rem;border-bottom:1px solid var(--line);font-size:.95rem}
  .nav__links a:last-child{border-bottom:0}
}
@media (max-width:520px){ .nav__cta .btn--ghost{display:none} }

/* ------------------------------------------------------------------ */
/*  Hero                                                               */
/* ------------------------------------------------------------------ */
.hero{position:relative;padding-top:clamp(1.5rem,3.4vw,2.6rem);overflow:hidden}
.hero::before{
  content:"";position:absolute;inset:-30% -10% auto -10%;height:70%;z-index:0;
  background:radial-gradient(60% 100% at 70% 0%,var(--glow),transparent 70%);
  pointer-events:none;opacity:.9;
}
.hero__in{position:relative;z-index:1}
.hero h1{font-size:clamp(2.5rem,6.2vw,4.6rem);max-width:16ch;margin:.9rem 0 0}
/* L'or pur ne se lit pas sur clair, même en très grand corps : 2,15:1, sous
   le seuil des grands textes (3:1). Le mot surligné prend l'or assombri. */
.hero h1 .hl{color:var(--accent-lisible)}
.hero .lead{margin-top:1.4rem}
.hero__cta{display:flex;flex-wrap:wrap;gap:.8rem;margin-top:2rem}


/* ------------------------------------------------------------------ */
/*  Demo / interface mockup                                            */
/* ------------------------------------------------------------------ */
.demo-shell{margin-top:clamp(2.5rem,5vw,3.6rem);position:relative;z-index:1}
.demo{
  border:1px solid var(--line-strong);border-radius:18px;overflow:hidden;
  background:var(--panel);box-shadow:var(--shadow-lg);
}
.demo__chrome{
  display:flex;align-items:center;gap:.9rem;padding:.7rem 1rem;
  border-bottom:1px solid var(--line);background:var(--panel-2);
}
.demo__dots{display:flex;gap:.42rem}
.demo__dots i{width:11px;height:11px;border-radius:50%;background:var(--line-strong);display:block}
.demo__url{
  flex:1;font-family:ui-monospace,Menlo,monospace;font-size:.75rem;color:var(--ink-faint);
  background:var(--ground);border:1px solid var(--line);border-radius:7px;
  padding:.34em .8em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.demo__url b{color:var(--ink-muted);font-weight:400}


/* ------------------------------------------------------------------ */
/*  Interface breakdown                                                */
/* ------------------------------------------------------------------ */
.sec-head{max-width:40ch}
.sec-head h2{font-size:clamp(1.85rem,3.7vw,2.9rem);margin-top:.7rem}
.sec-head .lead{margin-top:1rem}

/* Variante avec vignette décorative : le texte garde sa largeur de lecture,
   la vignette occupe le reste et se centre dans sa colonne. Les tracés sont en
   currentColor et var(--accent), donc ils suivent le thème sans duplication. */
.sec-head--art{max-width:none;display:grid;grid-template-columns:minmax(0,42ch) 1fr;
  gap:clamp(1.5rem,4vw,3rem);align-items:center}
.sec-head--art > div{min-width:0}
.sec-art{justify-self:center;width:min(100%,320px);color:var(--ink)}
.sec-art svg{width:100%;height:auto;overflow:visible}

/* ---- Les en-têtes de section, au défilement -------------------------
   Même principe que l'ouverture : la position dans la fenêtre pilote tout.
   La vignette se DESSINE trait par trait, le titre se révèle par balayage —
   l'inverse exact de l'effacement de l'ouverture, donc le même langage.

   `pathLength="1"` est posé sur chaque tracé dans le HTML : la longueur de
   chaque forme vaut alors 1, quelle que soit sa géométrie, et le dessin se
   pilote de 0 à 1 sans rien mesurer en JavaScript. Retirer cet attribut casse
   l'effet — le pointillé reprend la longueur réelle et ne correspond plus.

   --r et --t valent 1 par défaut : sans JavaScript, tout est dessiné et
   lisible. */
.sec-art svg *{
  stroke-dasharray:1;
  stroke-dashoffset:calc(1 - var(--r,1));
}
/* Les formes pleines n'ont pas de tracé à dessiner : elles apparaissent une
   fois le trait posé, sinon elles surgiraient d'un bloc au début. */
.sec-art [fill]:not([fill="none"]){
  opacity:clamp(0, calc((var(--r,1) - .5) * 2.6), 1);
}

/* Le titre arrive par la gauche, ligne après ligne. --t va de 0 (dehors) à 1
   (en place) ; à 1 la transformation est nulle, donc sans JavaScript le texte
   est simplement à sa place. */
.sec-head--art .eyebrow,
.sec-head--art h2,
.sec-head--art .lead{
  transform:translateX(calc((var(--t,1) - 1) * 5vw));
  opacity:var(--t,1);
}

@media (prefers-reduced-motion:reduce){
  .sec-art svg *{stroke-dasharray:none;stroke-dashoffset:0}
  .sec-art [fill]:not([fill="none"]){opacity:1}
  .sec-head--art .eyebrow,.sec-head--art h2,.sec-head--art .lead{
    transform:none;opacity:1}
}
/* Sous 820 px, la vignette est purement décorative et volerait de la place au
   titre : on la retire et l'en-tête retrouve son comportement d'origine. */
@media (max-width:820px){
  .sec-head--art{display:block;max-width:40ch}
  .sec-art{display:none}
}

.toggle.feats-switch{margin:clamp(1.2rem,2.4vw,1.8rem) auto 0}
.feats{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;margin-top:clamp(1rem,2vw,1.5rem);
  background:var(--line);border:1px solid var(--line);border-radius:18px;overflow:hidden}
.feats[hidden]{display:none}

/* ---- Bascule vidéo / audio du tableau -------------------------------
   Les six cases du panneau qui entre se posent l'une après l'autre, et du
   côté d'où l'on vient : depuis la droite quand on passe à l'audio, depuis la
   gauche pour revenir à la vidéo. Le sens rend la bascule lisible — sans lui,
   les deux panneaux arrivent pareil et on ne sait plus dans quel sens on va.

   Le passage de display:none à visible relance l'animation : c'est ce qui la
   rejoue à chaque clic sans avoir à la réarmer en JavaScript. */
.feats--de-d .feat{--dx:30px}
.feats--de-g .feat{--dx:-30px}
.feats:not([hidden]) .feat{
  animation:feat-entre .5s cubic-bezier(.2,.7,.2,1) both;
}
.feats:not([hidden]) .feat:nth-child(1){animation-delay:0ms}
.feats:not([hidden]) .feat:nth-child(2){animation-delay:45ms}
.feats:not([hidden]) .feat:nth-child(3){animation-delay:90ms}
.feats:not([hidden]) .feat:nth-child(4){animation-delay:60ms}
.feats:not([hidden]) .feat:nth-child(5){animation-delay:105ms}
.feats:not([hidden]) .feat:nth-child(6){animation-delay:150ms}
@keyframes feat-entre{
  from{opacity:0;transform:translate(var(--dx,0),12px)}
  to  {opacity:1;transform:none}
}
@media (prefers-reduced-motion:reduce){
  .feats:not([hidden]) .feat{animation:none}
}
.feat{background:var(--panel);padding:1.6rem 1.5rem;display:flex;flex-direction:column;gap:.7rem;
  transition:background .2s}
.feat:hover{background:var(--panel-2)}
.feat__ic{width:40px;height:40px;border-radius:10px;display:grid;place-items:center;
  background:var(--accent-soft);color:var(--accent-lisible)}
.feat__ic svg{width:21px;height:21px}
.feat h3{font-family:"Archivo",sans-serif;font-weight:600;font-size:1.05rem;letter-spacing:0}
.feat p{font-size:.9rem;color:var(--ink-muted);line-height:1.55}
/* Encre secondaire et non la plus pâle : ce bandeau tombe parfois sur un
   panneau plus dense que le fond de page, et l'encre pâle y passait sous le
   seuil. */
.feat__tc{font-family:ui-monospace,Menlo,monospace;font-size:.68rem;color:var(--ink-muted);
  letter-spacing:.05em;margin-top:auto}
@media (max-width:860px){.feats{grid-template-columns:repeat(2,1fr)}}
@media (max-width:560px){.feats{grid-template-columns:1fr}}

/* ---- Le volet de comparaison, au geste -------------------------------
   Le carrousel se regardait. Celui-ci se manipule : la poignée suit le
   pointeur et découpe la version B. C'est la fonction signature du produit,
   rendue au doigt.

   Le découpe se fait en clip-path sur une seule propriété personnalisée :
   rien à recalculer en JavaScript, rien à re-rendre. Sans JavaScript, --x
   vaut 50 % et l'image A reste entièrement lisible — le volet est un
   supplément, pas un prérequis. */
.sec-mid{max-width:34ch;margin:0 auto clamp(1.6rem,3.4vw,2.6rem);text-align:center}
.sec-mid h2{font-size:clamp(1.9rem,4.4vw,3.05rem);line-height:1.06;letter-spacing:-.028em}
.sec-mid .lead{margin:.9rem auto 0;max-width:44ch}

.volet{
  position:relative;border-radius:18px;overflow:hidden;
  box-shadow:var(--shadow-lg);background:var(--panel-2);
  /* Le ratio suit celui des captures (1140/622) et non un 16/9 de principe :
     les deux images sont en object-fit:cover, un cadre au mauvais rapport
     leur rognerait les bords — soit la barre latérale, soit le fil de
     commentaires, c'est-à-dire justement ce qu'elles doivent montrer. */
  /* Le préfixe n'est pas décoratif : Safari ne connaît toujours pas
     user-select non préfixé (CSS.supports le dit false en 26.5). Sans lui,
     tirer la poignée surlignait le texte autour du cadre au lieu de déplacer
     la coupe. */
  aspect-ratio:1140/622;cursor:ew-resize;touch-action:none;
  -webkit-user-select:none;user-select:none;
}
/* pointer-events:none et -webkit-user-drag : sans ça, appuyer sur l'image
   déclenche le glisser-déposer natif du navigateur. On attrape la capture
   d'écran au lieu de tirer la poignée, et le geste ne part jamais. Le cadre
   reçoit seul les évènements de pointeur. */
.volet img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;margin:0;
  pointer-events:none;-webkit-user-drag:none;
  -webkit-user-select:none;user-select:none}
/* La version B est révélée à droite de la poignée. Aucun filtre : elle a
   longtemps été désaturée pour rendre la coupe lisible, au prix d'un lecteur
   audio délavé sur la page d'accueil — soit à l'endroit où le produit se
   montre. C'est la couture qui marque la coupe, pas un traitement de l'image. */
.volet__b{clip-path:inset(0 0 0 var(--x,50%))}
/* Trois épaisseurs, parce que la couture traverse deux fonds opposés : une
   photo sombre et chargée à gauche, une interface claire et plate à droite.
   Le trait blanc porte sur le sombre, le liseré sombre porte sur le clair, et
   le halo décolle l'ensemble de ce qui passe dessous. Une seule des trois
   suffirait sur la moitié gauche et disparaîtrait sur la droite. */
.volet__poignee{
  position:absolute;top:0;bottom:0;left:var(--x,50%);width:3px;
  background:#fff;
  box-shadow:0 0 0 1px rgba(17,17,40,.38), 0 0 14px rgba(17,17,40,.28);
  transform:translateX(-1.5px);pointer-events:none;
}
.volet__poignee::after{
  content:"";position:absolute;top:50%;left:50%;width:46px;height:46px;
  transform:translate(-50%,-50%);border-radius:999px;
  background:rgba(255,255,255,.9);backdrop-filter:blur(10px);
  box-shadow:0 4px 18px rgba(17,17,40,.26);
}
.volet__etiq{
  position:absolute;top:14px;padding:.34em .8em;border-radius:999px;
  font-family:ui-monospace,Menlo,monospace;font-size:.68rem;letter-spacing:.06em;
  background:rgba(255,255,255,.86);backdrop-filter:blur(10px);color:var(--ink);
  pointer-events:none;
}
.volet__etiq--a{left:14px}
.volet__etiq--b{right:14px}
.volet__aide{text-align:center;margin:.95rem 0 0;font-size:.85rem;color:var(--ink-faint)}

@media (prefers-reduced-transparency:reduce){
  .volet__poignee::after,.volet__etiq{backdrop-filter:none;background:#fff}
}

/* ------------------------------------------------------------------ */
/*  Why / capabilities band                                            */
/* ------------------------------------------------------------------ */
/* La bande se distingue du fond par une teinte, pas par un cadre : sur clair
   un double filet découpe la page en tranches. */
.band{background:var(--ground-2);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.caps{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(1.4rem,3vw,2.6rem);margin-top:clamp(.9rem,1.75vw,1.3rem)}
.cap{display:flex;flex-direction:column;gap:.45rem}
.cap__n{font-family:"Archivo Expanded","Archivo",sans-serif;font-weight:700;font-size:1.6rem;color:var(--accent-lisible);
  display:flex;align-items:center;gap:.5rem}
.cap__n svg{width:20px;height:20px}
.cap h3{font-family:"Archivo",sans-serif;font-weight:600;font-size:1rem;letter-spacing:0}
.cap p{font-size:.9rem;color:var(--ink-muted);line-height:1.55}
@media (max-width:760px){.caps{grid-template-columns:1fr;gap:1.6rem}}

/* Bandeau de qualité d'encodage par formule (pages Vidéo / Audio). */
/* Deux paliers de qualité seulement depuis la grille du 14/08 : la
   définition bascule une fois (1080p → 4K), la restitution audio aussi
   (320 kbps → PCM). Trois colonnes obligeaient à inventer un palier. */
.specs{display:grid;grid-template-columns:repeat(2,1fr);gap:1.1rem;margin-top:clamp(1rem,2vw,1.5rem)}
.spec{background:var(--panel);border:1px solid var(--line);border-radius:18px;padding:1.3rem 1.4rem;
  display:flex;flex-direction:column;gap:.4rem}
.spec--feat{border-color:var(--accent-lisible);box-shadow:0 0 0 1px var(--accent),var(--shadow)}
.spec__plan{font-family:ui-monospace,Menlo,monospace;font-size:.64rem;letter-spacing:.13em;
  text-transform:uppercase;color:var(--ink-faint)}
.spec__val{font-family:"Archivo Expanded","Archivo",sans-serif;font-weight:700;font-size:1.15rem;
  color:var(--accent-lisible);line-height:1.2}
.spec p{font-size:.86rem;color:var(--ink-muted);line-height:1.5}
@media (max-width:760px){.specs{grid-template-columns:1fr}}

/* ------------------------------------------------------------------ */
/*  Ouverture animée au défilement (.film)                             */
/*                                                                     */
/*  Cinq temps, enchaînés par la position de défilement :              */
/*   0. le titre seul ; il part vers le bas ;                          */
/*   1. une onde audio arrive par la gauche, le lecteur par la droite ;*/
/*      ils se croisent et sortent ;                                   */
/*   2. la barre de saisie monte, le commentaire s'écrit, puis on      */
/*      « clique » sur Envoyer — la barre reste ensuite en place ;     */
/*   3. le commentaire devient une carte qui monte à droite, pendant   */
/*      que le lecteur revient par la gauche accoster à côté ;         */
/*   4. tout s'écarte.                                                 */
/*                                                                     */
/*  Tout est reconstruit en HTML/SVG — le lecteur aussi. Une seule     */
/*  image (le plan vidéo). main.js pilote les déplacements ; ici on ne  */
/*  décrit que l'apparence.                                            */
/* ------------------------------------------------------------------ */
/* La section remonte sous la barre de navigation : sans ça elle démarre plus
   bas, et les premiers pixels de défilement ne font que la hisser jusqu'à ce
   que la scène collée accroche — la page bouge sans que l'animation démarre.
   --nav-h est mesuré par main.js ; la valeur de repli couvre le cas sans JS.
   Uniquement au-delà de 820 px : en dessous la scène est en flux normal. */
/* ---- L'ouverture : repli par défaut, animation sur autorisation ------
   L'état PAR DÉFAUT est la mise en page repliée — titre et lecteur en flux,
   section de hauteur normale. Le mode animé n'existe que sous .est-pilote,
   classe que seul main.js peut poser.

   C'était l'inverse : la scène animée était l'état par défaut et le repli une
   exception en media query. Sans JavaScript — script bloqué, erreur de
   chargement, navigateur sans JS — la section gardait ses 1400 vh avec une
   fenêtre à opacity:0 : quatorze écrans de vide avant la suite de la page.
   Mesuré à 12 544 px sur une fenêtre de 900.

   Écrit dans ce sens, aucune de ces pannes ne peut produire ce trou : sans la
   classe, on a une page courte et lisible. */
.film{position:relative;height:auto}
.film__stage{position:static;height:auto;overflow:visible;
  padding:clamp(2rem,8vh,4rem) clamp(1.15rem,5vw,2.6rem)}
.film__scene{position:static;display:block}
.film__piece{position:static;opacity:1;transform:none;margin:0 auto}
/* Le masquage porte sur l'état NON piloté, et ne redéclare aucun affichage :
   ces éléments ont chacun le leur (la barre est un flex, le fil une colonne
   flex). Les forcer en `block` pour le mode animé empilait les outils de la
   barre les uns sous les autres. En piloté, le sélecteur ne s'applique plus et
   chacun retrouve sa propre règle. */
.film:not(.est-pilote) .film__mots-piece,
.film:not(.est-pilote) .film__bar,
.film:not(.est-pilote) .film__logo,
.film:not(.est-pilote) .film__trait{display:none}

/* ---- Le fil de commentaires au repos ----------------------------------
   Il était masqué avec les autres, et pour une raison sérieuse : les cartes
   sont à opacity:0 tant que jouer() ne les a pas posées. Les montrer sans
   rien changer d'autre n'affichait qu'un panneau blanc.

   Mais le masquage revenait à faire l'impasse sur le cœur du produit — des
   commentaires horodatés, signés, dont un vocal et un avec pièce jointe —
   pour tout visiteur sur téléphone. Le repli n'est pas un cas de secours :
   il s'applique en dessous de 820 px, donc à la majorité des visites. La
   version statique montrait un lecteur vidéo, c'est-à-dire ce que fait déjà
   n'importe quel lecteur.

   On donne donc un état de repos aux cartes plutôt que de cacher le fil.
   La barre de saisie, elle, reste masquée : sa phrase EST le premier
   commentaire du fil — main.js lit MOT sur cette carte — et l'afficher deux
   fois était une redite. À 390 px, ses six outils ne laissaient d'ailleurs
   que 44 px au champ, où l'on lisait « Rem ». */
.film:not(.est-pilote) .film__card{opacity:1}
/* Empilé sous le lecteur, le fil n'est plus à sa droite : son filet passe du
   côté gauche au haut, sinon il souligne dans le vide. */
@media (max-width:820px){
  .film:not(.est-pilote) .film__flux{border-left:0;border-top:1px solid var(--line)}
}
/* Au-dessus, la place existe pour les deux colonnes du mode animé : les
   garder évite une colonne unique interminable sur un grand écran dont les
   animations système sont coupées. */
@media (min-width:821px){
  .film:not(.est-pilote) .film__corps{grid-template-columns:1.62fr 1fr}
}
/* L'écart avec l'ouverture doit être posé ici, et nulle part ailleurs :
   .film__piece remet toutes ses marges à zéro pour se centrer
   horizontalement, ce qui efface aussi l'espace vertical. Le lecteur venait
   donc coller aux boutons d'appel — 0 px mesuré, bord contre bord. La marge
   ne concerne que la scène empilée : en mode animé la pile est positionnée
   en absolu et ne connaît pas les marges. */
.film__pile{width:100%;margin-top:clamp(2rem,5vh,3.5rem)}
.film__player{margin-bottom:1.8rem}
/* La fenêtre est en une seule colonne par défaut : le fil de commentaires
   est masqué en repli, et sa colonne de grille doit partir avec lui. Les deux
   colonnes reviennent sous .est-pilote. */

/* Mode animé, à partir d'ici. La scène reste collée pendant que la section
   défile : c'est la hauteur qui donne sa durée à l'animation. */
.film.est-pilote{height:1400vh}
@media (min-width:821px){
  .film.est-pilote{margin-top:calc(-1 * var(--nav-h, 63px))}
}
.film.est-pilote .film__stage{position:sticky;top:0;height:100vh;overflow:clip;
  padding:72px 0 0}
.film.est-pilote .film__pile{width:min(94vw,1180px)}
.film.est-pilote .film__player{margin-bottom:0}
.film.est-pilote .film__corps{grid-template-columns:1.62fr 1fr}
/* Les repères de cadre broadcast et l'analyseur de spectre qui habillaient
   la scène ont été retirés avec le passage au clair : c'était un décor de
   régie, lisible sur fond sombre, salissant sur fond clair. La scène est
   nue, et la fenêtre y gagne en présence. */

.film.est-pilote .film__scene{position:absolute;left:0;right:0;top:72px;bottom:0;
  display:grid;place-items:center;pointer-events:none}
/* Centrage explicite par left/top + translate(-50%,-50%) dans pose() : une
   pièce en position:absolute n'est PAS alignée par `place-items` de la grille,
   elle reste à sa position statique. S'en remettre à la grille décentre le
   croisement de l'acte 1.

   Les déplacements sont écrits en vw/vh, pas en % de l'élément : des pièces de
   tailles très différentes doivent se situer les unes par rapport aux autres,
   et seul un repère commun le permet. */
.film.est-pilote .film__piece{position:absolute;left:50%;top:50%;
  transform:translate(-50%,-50%);will-change:transform,opacity;opacity:0;margin:0}

/* ---- Le titre, premier temps ---- */
.film__txt{width:100%;text-align:left}

/* Chaque ligne s'efface pour son propre compte, balayée de gauche à droite —
   comme une tête de lecture qui la consomme — en partant au flou. --e va de 0
   (intacte) à 1 (effacée) et est posé par main.js, ligne par ligne.

   Le masque est un dégradé dont la frontière se déplace : à --e = 0 les deux
   bornes sont négatives, la ligne est donc entièrement opaque ; à --e = 1
   elles sont au-delà de 100 %, elle a totalement disparu. Ne pas remplacer par
   une simple opacité : c'est le décalage entre les lignes ET le balayage qui
   font l'effet, pas le fondu. */
.film__ligne{
  -webkit-mask-image:linear-gradient(100deg,
    transparent calc(var(--e,0) * 142% - 24%),
    #000 calc(var(--e,0) * 142% - 2%));
          mask-image:linear-gradient(100deg,
    transparent calc(var(--e,0) * 142% - 24%),
    #000 calc(var(--e,0) * 142% - 2%));
  filter:blur(calc(var(--e,0) * 7px));
  transform:translate3d(calc(var(--e,0) * 4vw), calc(var(--e,0) * -2vh), 0);
}
/* Le titre à gauche, la frise à droite. En dessous de 900 px la frise
   disparaît : elle n'ajouterait que de la hauteur avant le premier écran. */
.film__ouverture{display:grid;grid-template-columns:1fr;align-items:center;
  gap:clamp(1.6rem,4vw,3rem)}
.frise{display:none}
@media (min-width:900px){
  .film__ouverture{grid-template-columns:minmax(0,1fr) minmax(0,.78fr)}
  .frise{display:block}
}

.film__txt h1{font-size:clamp(1.9rem,5vw,3.5rem);line-height:1.04;
  margin-top:.6rem;max-width:15ch;text-wrap:balance}
.film__txt .lead{margin-top:.9rem;max-width:46ch}

/* ---- La frise de l'ouverture ----
   La timeline du logo qui se joue toute seule, avant le moindre défilement :
   le rail paraît, la lecture court jusqu'au repère, l'épingle tombe, la bulle
   éclot. Puis tout s'efface et ça recommence — c'est le geste que la page va
   raconter, en réduction. Le cycle entier tient dans une seule durée, chaque
   pièce n'occupant que sa fenêtre de pourcentages. */
.frise{color:var(--line-strong)}
.frise svg{width:100%;height:auto;display:block}
.frise__rail,.frise__reperes,.frise__or,.frise__tete,.frise__pin,.frise__bulle{
  animation-duration:7s;animation-iteration-count:infinite;animation-fill-mode:both}
.frise__rail    {animation-name:frise-rail}
.frise__reperes {animation-name:frise-rail;animation-delay:.25s}
.frise__or      {animation-name:frise-or;stroke-dasharray:218;stroke-dashoffset:218}
.frise__tete    {animation-name:frise-tete}
.frise__pin     {animation-name:frise-pin;transform-box:view-box;transform-origin:250px 104px}
.frise__bulle   {animation-name:frise-bulle;transform-box:view-box;transform-origin:250px 73px}

@keyframes frise-rail{
  0%,4%   {opacity:0}
  16%,88% {opacity:1}
  100%    {opacity:0}
}
/* Le trait d'or et la tête partagent la même fenêtre et la même détente :
   la tête doit rester sur la pointe du trait, sinon le geste se dédouble. */
@keyframes frise-or{
  0%,12%  {stroke-dashoffset:218;opacity:0;animation-timing-function:cubic-bezier(.62,0,.30,1)}
  15%     {opacity:1}
  52%,88% {stroke-dashoffset:0;opacity:1}
  100%    {stroke-dashoffset:0;opacity:0}
}
@keyframes frise-tete{
  0%,12%  {transform:translateX(-218px);opacity:0;animation-timing-function:cubic-bezier(.62,0,.30,1)}
  15%     {opacity:1}
  52%,88% {transform:translateX(0);opacity:1}
  100%    {transform:translateX(0);opacity:0}
}
/* L'épingle se plante : elle dépasse sa place puis y revient. */
@keyframes frise-pin{
  0%,52%  {opacity:0;transform:translateY(-9px) scale(.72);
           animation-timing-function:cubic-bezier(.2,1.5,.4,1)}
  62%,88% {opacity:1;transform:translateY(0) scale(1)}
  100%    {opacity:0;transform:translateY(0) scale(1)}
}
@keyframes frise-bulle{
  0%,58%  {opacity:0;transform:scale(.6);
           animation-timing-function:cubic-bezier(.2,1.5,.4,1)}
  70%,88% {opacity:1;transform:scale(1)}
  100%    {opacity:0;transform:scale(1)}
}

/* Sans mouvement : la frise s'affiche montée, une fois, et n'y revient plus. */
@media (prefers-reduced-motion:reduce){
  .frise__rail,.frise__reperes,.frise__or,.frise__tete,.frise__pin,.frise__bulle{
    animation:none;opacity:1;transform:none}
  .frise__or{stroke-dashoffset:0}
}
.film__txt .hero__cta{margin-top:1.5rem;pointer-events:auto}

/* ---- Les fonctionnalités qui se relaient ----------------------------
   Premier temps : quatorze noms de fonctionnalités réelles apparaissent en
   fondu un peu partout dans le champ, dérivent de quelques vw, puis
   s'effacent. Ils ne traversent pas l'écran — c'est une nappe qui respire,
   pas un défilement.

   Chacun porte son point sur une grille lâche 4x4 avec du jeu, sa dérive
   (--ax/--ay), son inclinaison (--r) et son opacité (--o). Une valeur commune
   les ferait battre ensemble.

   Le conteneur occupe toute la scène ; les mots sont posés en pourcentages de
   hauteur, donc la nappe reste dense quelle que soit la fenêtre. */
/* Ce conteneur reste opaque : ce sont les mots eux-mêmes qui s'allument et
   s'éteignent. Sans ça il hérite du opacity:0 des pièces et les masque tous,
   même allumés.

   La spécificité doit égaler celle de `.film.est-pilote .film__piece`, sinon
   la règle est perdue. C'est exactement ce qui est arrivé en passant les
   pièces sous .est-pilote : leur sélecteur est monté à trois classes, celui-ci
   est resté à une, et l'acte des fonctionnalités s'est éteint. */
.film__mots-piece{width:100%;height:100%}
.film.est-pilote .film__mots-piece{opacity:1}
.film__mots{position:absolute;inset:0;overflow:clip}
/* Chaque mot est posé sur son point de la grille et centré dessus. Il n'en
   part jamais : il ne fait que dériver de quelques vw pendant qu'il est
   visible. Pas de traversée d'écran. */
.film__mot-f{position:absolute;white-space:nowrap;
  font-family:"Archivo Expanded","Archivo",sans-serif;font-weight:700;
  letter-spacing:-.01em;color:var(--ink);opacity:0;
  transform:translate(calc(-50% + var(--x,0) * 1vw),
                      calc(-50% + var(--y,0) * 1vh))
            rotate(var(--r,0deg)) scale(var(--e,1));
  will-change:transform,opacity}
/* Les termes techniques passent en monospace et en petit : le mélange des deux
   registres évite l'effet « mur de titres ». */
.film__mot-f--tech{font-family:ui-monospace,"SFMono-Regular",Menlo,monospace;
  font-weight:500;letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink-muted)}
.film__mot-f--vif{color:var(--accent-lisible)}

/* ---- La colonne : lecteur + fil, puis la barre de saisie ----
   Une seule pile pour les trois : c'est ce qui garantit qu'ils font exactement
   la même largeur et restent alignés, à toute taille d'écran. Les séparer en
   pièces indépendantes ramène le désalignement.

   Sa largeur est déclarée deux fois plus haut et pas ici : 100 % en scène
   empilée, où .film__stage porte déjà les marges de lecture, et min(94vw,
   1180px) sous .est-pilote, où la scène est en absolu et se cale sur la
   fenêtre. Une troisième déclaration vivait à cet endroit, sans le qualifiant
   .est-pilote : venant après celle du repli, elle l'écrasait, et le lecteur
   se retrouvait 16 px plus large que la colonne de texte à 390 px, 33 px à
   820 px — débordant les marges, l'horloge de l'en-tête rognée au bord. */
/* Une seule fenêtre : un cadre, une ombre, un fond. Le lecteur, le fil et la
   barre ne sont plus des cartes posées côte à côte mais des zones séparées par
   des filets — c'est ce qui fait lire l'ensemble comme une application et non
   comme trois bulles qui se rapprochent. Ne pas remettre de `gap` ni de
   `border-radius` sur les enfants : c'est ce qui les redétacherait. */
/* `overflow:clip` est ce qui permet aux éléments de s'assembler DANS la
   fenêtre : le lecteur entre par la gauche et la barre monte du bas, tous deux
   rognés par le cadre. Sans lui, ils flotteraient au-dehors et on retrouverait
   les bulles qui se rapprochent. */
.film__fenetre{display:flex;flex-direction:column;border-radius:18px;overflow:clip;
  border:1px solid var(--line-strong);box-shadow:var(--shadow-lg);background:var(--panel)}
.film__entete{display:flex;align-items:center;gap:.7rem;padding:.5rem .85rem;
  border-bottom:1px solid var(--line);background:var(--panel-2)}
/* Deux noms superposés dans la même cellule : le fichier vidéo et le fichier
   audio se relaient avec la bascule du lecteur. --bascule est posé par main.js.
   `inline-grid` les empile sans que l'en-tête change de largeur au passage. */
.film__fichier{display:inline-grid;font-family:"Archivo Expanded","Archivo",sans-serif;
  font-weight:700;font-size:.7rem;letter-spacing:.06em;color:var(--ink)}
.film__fichier b{grid-area:1/1;font-weight:inherit;white-space:nowrap}
.film__fichier b:first-child{opacity:calc(1 - var(--bascule,0))}
.film__fichier b:last-child{opacity:var(--bascule,0)}
.film__chemin{font-size:.64rem;color:var(--ink-faint)}
/* L'en-tête est une rangée qui ne se replie pas : quatre pièces pour 349 px
   utiles à 390 px, il en fallait 359. Le dépassement était rogné par le
   `overflow:clip` de la fenêtre — l'horloge coupée net au bord — et « Version
   3 » se cassait en deux lignes pour tenter de tenir, faisant passer la
   rangée de 36 à 52 px de haut.
   C'est le fil d'Ariane qui part, et lui seul : le nom du fichier identifie,
   la version et le timecode sont deux promesses du produit. « Dossiers »
   n'est qu'un décor de contexte, et libère les 51 px qui manquaient. */
@media (max-width:420px){
  .film__chemin{display:none}
}
/* white-space:nowrap — la pastille ne se casse jamais en deux lignes : elle
   grandirait la rangée entière pour un mot. */
.film__etat{margin-left:auto;font-size:.6rem;font-weight:600;padding:.18em .6em;
  border-radius:999px;background:var(--accent-soft);color:var(--accent-lisible);
  white-space:nowrap}
.film__horloge{font-family:ui-monospace,Menlo,monospace;font-size:.64rem;color:var(--accent-lisible)}
/* min-height : en s'élargissant, la fenêtre doit aussi grandir en hauteur,
   sinon le lecteur s'aplatit et l'image se recadre à l'excès. */
.film__corps{display:grid;grid-template-columns:1fr;align-items:stretch;
  min-height:clamp(320px,44vh,470px)}
/* Le fil occupe toute la hauteur du lecteur : les commentaires descendent donc
   jusqu'au niveau de la barre de saisie. */
/* Filet à gauche plutôt qu'un écart : le fil est un panneau de la fenêtre. */
.film__flux{display:flex;flex-direction:column;min-width:0;
  border-left:1px solid var(--line);overflow:clip}

/* ---- Le lecteur, reconstruit ----
   Écran, piste de commentaires, barre de transport. Volontairement pas une
   capture d'écran : les captures existantes sont en thème clair, elles
   vieillissent, et elles ne peuvent pas s'animer (le marqueur qui se pose). */
/* Le lecteur bascule sur son axe horizontal, comme une carte qu'on retourne,
   pour montrer sa face audio. La perspective est portée par le conteneur ;
   `preserve-3d` par la carte elle-même. Sans `overflow:visible` sur .film__player
   pendant la bascule, les faces seraient rognées à mi-parcours — d'où le
   clip porté par chaque face et non par le conteneur. */
.film__player{perspective:1600px;background:transparent;min-width:0}
.film__flip{position:relative;height:100%;transform-style:preserve-3d;
  transform:rotateX(var(--flip,0deg));will-change:transform}
/* --tete porte la position de lecture : le remplissage de la piste, la tête et
   la jauge du transport la partagent, donc un seul réglage les déplace tous. */
/* Plus de cadre propre : la face fait partie de la fenêtre. */
.film__face{--tete:18.19%;height:100%;display:flex;flex-direction:column;
  overflow:clip;background:var(--panel);
  backface-visibility:hidden;-webkit-backface-visibility:hidden}
/* La face audio est superposée à la face vidéo, retournée d'un demi-tour. */
.film__face--a{position:absolute;inset:0;transform:rotateX(180deg)}

/* ---- La face audio : onde et mesures ----
   L'onde prend toute la hauteur disponible (`flex:1` + `preserveAspectRatio:none`
   sur le SVG) : elle remplit le lecteur au lieu de flotter au milieu. */
.film__audio{flex:1;min-height:0;overflow:clip;
  display:flex;flex-direction:column;gap:.7rem;
  padding:.9rem 1.1rem;background:var(--ground-2)}
.film__onde{flex:1;min-height:0;color:var(--accent-lisible);opacity:.92}
.film__onde svg{width:100%;height:100%;display:block}
.film__mesures{display:flex;gap:1.1rem;flex:none;
  font-family:ui-monospace,Menlo,monospace;
  font-size:.62rem;color:var(--ink-faint);letter-spacing:.02em}
.film__mesures b{color:var(--accent-lisible);font-weight:600}
/* ---- Les pièces communes aux deux faces ---- */
/* `flex:1` + `object-fit:cover` : l'image se plie à la hauteur de la colonne
   de commentaires au lieu de l'imposer. Avec `height:auto` c'était le lecteur
   qui dictait la hauteur de la scène, et tout se décalait. */
.film__ecran{position:relative;flex:1;min-height:0;line-height:0;overflow:clip}
.film__ecran img{width:100%;height:100%;object-fit:cover;display:block}

/* `flex:none` obligatoire : sur la face audio, la piste est un élément flex à
   côté d'une onde en `flex:1`. Sans ça elle se laisse comprimer jusqu'à 0 et
   disparaît, la tête de lecture débordant alors sur toute la hauteur. */
.film__piste{position:relative;flex:none;height:16px;background:var(--ground-2);
  border-top:1px solid var(--line)}
.film__piste i{position:absolute;top:0;bottom:0;left:0;width:var(--tete);
  background:color-mix(in srgb,var(--pin-blue) 55%,transparent)}

/* Un marqueur par commentaire, à la position de son timecode et à la couleur
   de son auteur (--av, la même que sur l'avatar). Ils apparaissent avec leur
   carte : voir la boucle sur les cartes dans main.js. */
.film__marq{position:absolute;top:3px;width:9px;height:9px;border-radius:2px;
  background:var(--av,var(--accent));transform:translateX(-50%);opacity:0}
/* Onde de choc au moment où le marqueur se pose. --ping va de 0 à 1. */
.film__marq::after{content:"";position:absolute;inset:-3px;border-radius:5px;
  border:1.5px solid var(--av,var(--accent));pointer-events:none;
  transform:scale(calc(1 + var(--ping,0) * 2.8));
  opacity:calc(1 - var(--ping,0))}

/* Les marqueurs de la face audio sont posés d'avance : au moment où on la voit,
   les cinq commentaires sont déjà publiés. Cette règle DOIT venir après
   `.film__marq` — à spécificité égale, c'est l'ordre qui tranche. */
/* --ping à 1 : l'anneau d'onde de choc est déjà retombé. Sans ça il reste à
   l'échelle 1 et pleinement opaque, ce qui entoure chaque marqueur d'un halo. */
.film__marq--fixe{opacity:1;--ping:1}
.film__tete{position:absolute;top:-2px;bottom:-2px;left:var(--tete);width:2px;background:var(--accent);
  box-shadow:0 0 8px 2px color-mix(in srgb,var(--accent) 50%,transparent)}
.film__transport{display:flex;flex:none;align-items:center;gap:.55rem;padding:.5rem .7rem;
  background:var(--panel);border-top:1px solid var(--line)}
.film__transport svg{width:14px;height:14px;color:var(--ink-muted);flex:none}
.film__tc2{font-family:ui-monospace,Menlo,monospace;font-size:.66rem;color:var(--ink-muted);
  letter-spacing:.02em;flex:none}
.film__jauge{flex:1;height:3px;border-radius:2px;background:var(--panel-2);position:relative}
.film__jauge i{position:absolute;top:0;bottom:0;left:0;width:var(--tete);
  border-radius:2px;background:var(--ink-faint)}
.film__collab{font-size:.6rem;font-weight:600;padding:.2em .6em;border-radius:999px;
  background:var(--accent-soft);color:var(--accent-lisible);flex:none}

/* ---- La barre de saisie ----
   Reprise de la barre réelle : champ bordé d'ambre, chronomètre, IN / OUT,
   stylo, trombone, « Envoyer ». Sa largeur est celle de la pile. */
.film__bar{display:flex;align-items:center;gap:.5rem;
  padding:.55rem .7rem;background:var(--panel-2);
  border-top:1px solid var(--line)}
.film__champ{flex:1;min-width:0;padding:.62rem .85rem;border-radius:8px;
  background:var(--ground-2);border:1px solid color-mix(in srgb,var(--accent) 45%,transparent);
  font-size:.92rem;color:var(--ink);white-space:nowrap;overflow:hidden}
.film__champ.vide{color:var(--ink-faint)}
.film__curseur{display:inline-block;width:1px;height:1.05em;vertical-align:-.16em;
  margin-left:1px;background:var(--accent);opacity:0}
.film__bar.tape .film__curseur{animation:film-curseur 1s steps(1,end) infinite}
@keyframes film-curseur{0%,49%{opacity:1}50%,100%{opacity:0}}
.film__outil{display:grid;place-items:center;width:2rem;height:2rem;border-radius:7px;
  background:var(--panel-2);color:var(--ink-muted);font-size:.62rem;font-weight:600;
  font-family:ui-monospace,Menlo,monospace;letter-spacing:.04em;flex:none}
.film__outil svg{width:15px;height:15px}
.film__outil--accent{color:var(--accent-lisible)}
.film__envoi{padding:.45em 1em;border-radius:8px;background:var(--panel-2);
  color:var(--ink-faint);font-size:.8rem;font-weight:600;flex:none;
  transition:background .25s,color .25s}
.film__bar.pret .film__envoi{background:var(--accent);color:var(--on-accent)}

/* ---- Les cartes de commentaire ---- */
/* Les commentaires sont des lignes du panneau, pas des cartes flottantes. */
.film__card{padding:.6rem .8rem .65rem;
  background:transparent;border-bottom:1px solid var(--line);
  text-align:left;opacity:0;
  /* Le filet sépare deux commentaires ; sous le dernier il ne sépare de rien
     et souligne dans le vide — visible depuis que le fil s'affiche au repos,
     où la pile est complète d'emblée. */
  /* le flou se résorbe à l'arrivée : la carte « fait le point » */
  filter:blur(var(--flou,0px))}
.film__card:last-child{border-bottom:0}
.film__tete-c{display:flex;align-items:center;gap:.5rem}
/* Carré arrondi et non rond : c'est ainsi dans l'application. */
/* --av est posé sur chaque carte dans index.html : les avatars n'ont pas
   tous la même couleur, comme dans une vraie équipe. */
.film__ava{display:grid;place-items:center;width:1.6rem;height:1.6rem;border-radius:6px;
  border:1px solid color-mix(in srgb,var(--av,var(--accent)) 55%,transparent);
  background:color-mix(in srgb,var(--av,var(--accent)) 14%,transparent);
  /* La lettre est en encre, pas dans la couleur du relecteur : sur un aplat
     de la même teinte elle tombait à 1,9 pour 1. L'identité reste portée par
     l'aplat, la bordure et le marqueur de la frise. */
  color:var(--ink);font-weight:700;font-size:.75rem;flex:none;
  /* --pop est posé par main.js : l'avatar apparaît juste après sa carte */
  transform:scale(var(--pop,1))}
.film__qui{flex:1;min-width:0;font-size:.74rem;color:var(--ink-muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.film__tc{font-family:ui-monospace,"SFMono-Regular",Menlo,monospace;
  font-size:.63rem;color:var(--accent-lisible);letter-spacing:.02em;flex:none}
.film__mot{margin-top:.4rem;font-size:.78rem;line-height:1.42;color:var(--ink)}

/* Un commentaire vocal : lecture, onde, durée — la grammaire de la face audio
   du lecteur, en réduction. Pas de texte sous l'onde : c'est justement ce qui
   le distingue d'un commentaire écrit. */
.film__vocal{margin-top:.45rem;display:flex;align-items:center;gap:.5rem}
.film__vocal-lire{display:grid;place-items:center;flex:none;
  width:1.4rem;height:1.4rem;border-radius:50%;
  background:var(--accent);color:var(--on-accent)}
/* Le triangle de lecture est optiquement à gauche de son cercle : on le repousse */
.film__vocal-lire svg{width:.6rem;height:.6rem;margin-left:.08rem}
/* Assez haute et assez contrastée pour qu'on lise une amplitude : plus bas,
   l'onde se confond avec un filet pointillé. */
.film__vocal-onde{flex:1;min-width:0;height:1.25rem;color:var(--ink-muted);opacity:.8}
.film__vocal-onde svg{width:100%;height:100%;display:block}
.film__vocal-duree{font-family:ui-monospace,"SFMono-Regular",Menlo,monospace;
  font-size:.62rem;color:var(--ink-faint);flex:none}

/* Une pièce jointe : une puce sous le commentaire, nom et poids du fichier. */
.film__pj{margin-top:.45rem;display:inline-flex;align-items:center;gap:.4rem;
  max-width:100%;padding:.22rem .5rem .26rem;
  border:1px solid var(--line-strong);border-radius:7px;background:var(--panel-2)}
.film__pj svg{width:.72rem;height:.72rem;color:var(--ink-faint);flex:none}
.film__pj b{min-width:0;font-weight:500;font-size:.7rem;color:var(--ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.film__pj i{font-family:ui-monospace,"SFMono-Regular",Menlo,monospace;
  font-size:.6rem;font-style:normal;color:var(--ink-faint);flex:none}

/* Le trait de fuite : la scène s'y replie, puis il passe la main au logo,
   dont le motif est une timeline. C'est ce raccord qui donne son sens à
   l'écrasement — sans lui, la composition se contente de s'aplatir. */
/* Largeur calée sur la timeline du logo : dans son viewBox de 680, le tracé
   va de x=120 à x=560, soit 64,7 % — donc min(70vw,760px) x 0,647. Si la
   largeur du logo change, celle-ci doit suivre, sinon le raccord se voit. */
.film__trait{width:min(45.3vw,492px);height:2px;border-radius:2px;
  background:linear-gradient(90deg,
    transparent, var(--accent) 14%, var(--accent-2) 50%, var(--accent) 86%, transparent);
  box-shadow:0 0 22px 4px color-mix(in srgb,var(--accent) 38%,transparent)}

/* ---- Le logo, dernier temps ---- */
/* Pas de `position:relative` ici : .film__piece est déjà en position:absolute
   et sert d'ancrage au bokeh. La redéclarer écrase ce positionnement et fait
   sortir le logo de sa place. */
.film__logo{width:min(70vw,760px)}
.film__logo svg{position:relative;width:100%;height:auto;display:block}

/* Bokeh : taches lumineuses floues qui montent derrière le logo. --b, posé par
   main.js, va de 0 à 1 au fil du défilement ; chaque cercle a sa dérive (--d)
   pour que la nappe ne monte pas d'un bloc. */
.film__bokeh{position:absolute;inset:-45% -18%;pointer-events:none;overflow:visible}
/* Sur fond sombre, 34 % d'opacité et un flou de 22 px donnaient des halos.
   Sur clair, les mêmes valeurs donnent des taches : le fond ne peut pas
   absorber la couleur, elle se pose dessus. On descend l'opacité et on monte
   le flou — le bokeh devient une inflexion du blanc, pas un dépôt. */
.film__bokeh i{position:absolute;border-radius:50%;filter:blur(38px);
  opacity:calc(var(--b,0) * .17);
  transform:translateY(calc(var(--b,0) * var(--d,-60px)))
            scale(calc(.55 + var(--b,0) * .75))}


/* Sans JavaScript rien n'est piloté : on montre le titre seul plutôt qu'un
   empilement de pièces au même endroit. */
.film__txt{opacity:1}
.film.est-pilote .film__txt{opacity:0}

/* Repli : ni assez large, ni animation souhaitée. La chorégraphie suppose de
   la largeur — sous 820 px, titre et lecteur en pile, sans animation. Les deux
   cas donnent exactement la même mise en page, d'où la requête unique : ils
   étaient auparavant écrits deux fois, et divergeaient à la première retouche.

   Le JavaScript observe la même bascule (voir anime() dans main.js) : ce qui
   compte ici doit rester en phase avec ce qu'il considère comme actif. */
/* Filet de sécurité : même si la classe est là — course au chargement,
   réglage système changé avant que main.js ne réagisse — la mise en page
   repliée reprend la main sous le seuil. Le JavaScript retire la classe de son
   côté ; ces règles rendent l'ordre des deux sans importance. */
@media (max-width:820px), (prefers-reduced-motion:reduce){
  .film.est-pilote{height:auto;margin-top:0}
  .film.est-pilote .film__stage{position:static;height:auto;overflow:visible;
    padding:clamp(2rem,8vh,4rem) clamp(1.15rem,5vw,2.6rem)}
  .film.est-pilote .film__scene{position:static;display:block}
  .film.est-pilote .film__piece{position:static;opacity:1;transform:none !important;margin:0 auto}
  .film.est-pilote .film__txt{opacity:1}
  .film.est-pilote .film__mots-piece,
  .film.est-pilote .film__bar,
  .film.est-pilote .film__flux,
  .film.est-pilote .film__logo,
  .film.est-pilote .film__trait{display:none}
  /* Même écart que la scène empilée hors mode animé : la classe est-pilote
     peut survivre le temps d'un redimensionnement avant que main.js ne la
     retire, et le lecteur ne doit pas coller aux boutons entre-temps. */
  .film.est-pilote .film__pile{width:100%;margin-top:clamp(2rem,5vh,3.5rem)}
  .film.est-pilote .film__player{margin-bottom:1.8rem}
  .film.est-pilote .film__corps{grid-template-columns:1fr}
}
@media (prefers-reduced-motion:reduce){
  .film__bar.tape .film__curseur{animation:none}
}

/* Bascule Vidéo / Audio en tête des pages dédiées. */
.media-switch{display:flex;gap:.5rem;margin-top:1.6rem;flex-wrap:wrap}
.media-switch a{font-family:"Archivo",sans-serif;font-weight:600;font-size:.88rem;
  padding:.5em 1.1em;border-radius:999px;border:1px solid var(--line-strong);
  color:var(--ink-muted);transition:.18s}
.media-switch a:hover{color:var(--ink);border-color:var(--ink-faint)}
.media-switch a[aria-current="page"]{background:var(--accent);border-color:var(--accent-lisible);color:var(--on-accent)}

/* ------------------------------------------------------------------ */
/*  Pricing                                                            */
/* ------------------------------------------------------------------ */
.price-note{margin-top:1.1rem;font-size:.86rem;color:var(--ink-muted);max-width:60ch;
  border-left:2px solid var(--accent);padding-left:.9rem}
.toggle{display:flex;width:fit-content;align-items:center;gap:.3rem;margin:1.6rem auto 0;padding:.28rem;
  background:var(--panel);border:1px solid var(--line-strong);border-radius:999px}
.toggle button{border:0;background:transparent;color:var(--ink-muted);cursor:pointer;
  font-family:"Archivo",sans-serif;font-weight:600;font-size:.85rem;padding:.45em 1.05em;border-radius:999px;transition:.18s}
.toggle button.on{background:var(--accent);color:var(--on-accent)}

/* L'essai vaut pour les trois formules et pour les deux périodes : l'annoncer
   une fois sous la bascule, plutôt que trois fois de suite sur les cartes. */
/* La promesse est portée par chaque carte (.tier__essai) ; il ne reste ici que
   ses conditions, en retrait. balance : sans lui la phrase se coupe en une
   longue ligne suivie d'un mot seul. */
.essai{margin:.9rem auto 0;max-width:36rem;text-align:center;text-wrap:balance;
  font-size:.84rem;line-height:1.55;color:var(--ink-muted)}
/* La franchise en base n'est pas une promesse commerciale : elle se dit une
   fois, sous la grille, plutôt que d'alourdir chacune des trois cartes. */
.essai__tva{display:block;margin-top:.35rem;font-size:.78rem;color:var(--ink-faint)}

/* Pas d'align-items:start ici : les cartes doivent s'étirer à la hauteur de la
   plus haute, sinon leurs bords bas se décalent selon la longueur des textes. */
/* Cinq paliers : la grille sort de la largeur de lecture du reste de la page,
   sinon les cartes tombent sous 200 px et le prix ne se lit plus. Le retrait
   négatif la recentre sans toucher au .wrap qui la contient. */
.tiers{display:grid;grid-template-columns:repeat(4,1fr);gap:1rem;margin-top:clamp(1rem,2vw,1.5rem);
  width:min(96vw,1280px);margin-left:50%;transform:translateX(-50%)}
/* Quatre colonnes tiennent jusqu'à 1040 px ; en dessous, deux, puis une. */
@media (max-width:1040px){.tiers{grid-template-columns:repeat(2,1fr);width:min(94vw,760px)}}
.tier{background:var(--panel);border:1px solid var(--line);border-radius:18px;padding:1.7rem 1.5rem;
  display:flex;flex-direction:column;gap:1rem;box-shadow:var(--shadow);position:relative;
  transition:transform .34s cubic-bezier(.2,.9,.3,1),box-shadow .34s;
  /* --v va de 0 (dehors) à 1 (en place), piloté par le défilement comme les
     en-têtes de section. Valeur de repos à 1 : sans JavaScript les trois
     cartes sont simplement à leur place. */
  /* Deux mouvements, une seule transformation : l'arrivée (--v) et le
     soulèvement au survol (--lift) s'additionnent. En les écrivant dans deux
     règles concurrentes, le survol remplaçait l'arrivée et la carte sautait à
     sa position finale dès qu'on la survolait en cours d'entrée. */
  --lift:0px;
  transform:translateY(calc((1 - var(--v,1)) * 26px + var(--lift)));
  opacity:var(--v,1)}
.tier--feat{border-color:var(--accent-lisible);box-shadow:0 0 0 1px var(--accent),var(--shadow-lg)}
/* Sous la main, la carte se soulève : la page est en matière, pas en aplat. */
.tier:hover{--lift:-4px;box-shadow:var(--shadow-lg)}
.tier--feat:hover{box-shadow:0 0 0 1px var(--accent),var(--shadow-lg)}
/* Le montant marque le coup à la bascule mensuel / annuel. Sans ça le chiffre
   se substitue sans qu'on voie qu'il a changé. */
.tier__amt{display:inline-block;font-family:"Archivo Expanded","Archivo",sans-serif;
  font-weight:700;font-size:2.7rem;letter-spacing:-.02em;
  transition:transform .26s cubic-bezier(.2,.9,.3,1)}
/* Deux porteurs : la grille quand la période bascule (tous les montants
   changent), la carte seule quand c'est son sélecteur de palier qui bouge. */
.tiers.change .tier__amt,.tier.change .tier__amt{transform:translateY(-5px) scale(1.05)}
@media (prefers-reduced-motion:reduce){
  .tier,.tier__amt{transition:none;transform:none;opacity:1}
  .tier:hover{--lift:0px}
}
/* Un coupon, pas un aplat : fond teinté, liseré en tirets et hachures en biais
   pour la matière. Le texte passe dans l'or lisible au lieu du négatif — un
   deuxième pavé plein sous le bouton d'accent alourdissait la carte.
   Placé au-dessus du prix, jamais collé au bouton pour la même raison. */
.tier__essai{position:relative;display:flex;align-items:center;justify-content:center;
  gap:.5rem;padding:.62rem .9rem;border-radius:11px;
  color:var(--accent-lisible);
  background:
    repeating-linear-gradient(-45deg, transparent 0 7px,
      color-mix(in srgb,var(--accent) 13%,transparent) 7px 8px),
    var(--accent-soft);
  border:1px dashed color-mix(in srgb,var(--accent) 52%,transparent);
  font-family:"Archivo",sans-serif;font-weight:700;font-size:.9rem}
/* Les deux encoches du ticket, poinçonnées dans le fond de la carte. */
.tier__essai::before,.tier__essai::after{content:"";position:absolute;top:50%;
  width:12px;height:12px;border-radius:50%;background:var(--panel);
  transform:translateY(-50%)}
.tier__essai::before{left:-7px}
.tier__essai::after{right:-7px}
.tier__essai svg{width:1.05rem;height:1.05rem;flex:none;opacity:.85}

.tier__flag{position:absolute;top:-11px;left:1.5rem;background:var(--accent);color:var(--on-accent);
  font-family:ui-monospace,Menlo,monospace;font-size:.7rem;letter-spacing:.1em;text-transform:uppercase;
  padding:.32em .7em;border-radius:6px}
.tier__name{font-family:"Archivo Expanded","Archivo",sans-serif;font-weight:700;font-size:1.15rem}
.tier__desc{font-size:.85rem;color:var(--ink-muted);line-height:1.5;min-height:2.4em}
.tier__price{display:flex;align-items:baseline;gap:.35rem}
.tier__per{font-size:.82rem;color:var(--ink-faint)}
.tier__bill{font-family:ui-monospace,Menlo,monospace;font-size:.78rem;color:var(--ink-faint);margin-top:-.4rem}
/* .tier__save (le badge de remise en %) a disparu avec la révision du
   14/08 : un mensuel en « ,90 » avec deux mois offerts donne des remises de
   16,1 à 17,5 % selon le palier. Seuls les euros sont ronds et exacts, c'est
   donc .tier__saved qui porte l'argument. */
/* Même raison sur fond blanc : --pin-green n'y valait que 4,25 pour 1. Et le
   chiffre de l'économie est un argument de vente, pas une note de bas de page —
   il monte à 12,5 px comme la ligne de facturation. */
.tier__saved{font-family:ui-monospace,Menlo,monospace;font-size:.78rem;color:var(--green-lisible);margin-top:.25rem}
/* Le tarif de l'autre engagement, en clair sous le prix : c'est le format
   retenu dans la grille — « 32,90 €/mois … ou 39,90 €/mois sans engagement ».
   Discret : c'est une alternative, pas l'offre qu'on met en avant. */
.tier__alt{font-family:ui-monospace,Menlo,monospace;font-size:.72rem;color:var(--ink-faint);margin-top:.2rem}
.tier__saved[hidden]{display:none}
.tier ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.6rem}
.tier li{font-size:.88rem;color:var(--ink);display:flex;gap:.6rem;line-height:1.4}
.tier li svg{width:16px;height:16px;flex:none;margin-top:.18rem;color:var(--accent-lisible)}
@media (max-width:620px){.tiers{grid-template-columns:1fr;width:min(94vw,440px)}}

/* --- le sélecteur de volume d'ESSENTIEL ------------------------------------
   Deux volumes d'un même produit, pas deux offres : le sélecteur reprend
   l'allure de la bascule mensuel/annuel, en plus petit, pour dire qu'il joue
   le même rôle. */
.tier__vol{display:flex;gap:.25rem;padding:.22rem;border-radius:999px;
  background:var(--panel-2);border:1px solid var(--line)}
.tier__vol button{flex:1;border:0;background:transparent;color:var(--ink-muted);cursor:pointer;
  font-family:ui-monospace,Menlo,monospace;font-size:.72rem;letter-spacing:.04em;
  /* .55em et non .42 : à cette taille de police, le bouton tombait à 23 px de
     haut, sous les 24 exigés par le WCAG 2.5.8. */
  padding:.55em .3em;border-radius:999px;transition:.18s}
.tier__vol button.on{background:var(--accent);color:var(--on-accent);font-weight:600}
@media (prefers-reduced-motion:reduce){.tier__vol button{transition:none}}

/* Ce qui est annoncé mais pas encore livré. Le dire dans la puce elle-même
   plutôt qu'en note de bas de page : c'est là qu'on lit la promesse. */
.tier__soon,.cmp__soon{display:inline-block;font-family:ui-monospace,Menlo,monospace;
  font-size:.62rem;letter-spacing:.08em;text-transform:uppercase;
  padding:.15em .45em;border-radius:5px;
  background:var(--panel-2);color:var(--ink-muted);border:1px solid var(--line-strong);
  white-space:nowrap;vertical-align:middle}
.tier__essai--free{color:var(--green-lisible)}
.tier__mode{font-family:ui-monospace,Menlo,monospace;font-size:.72rem;letter-spacing:.13em;
  text-transform:uppercase;color:var(--ink-faint);display:block;margin-bottom:.4rem}

/* deployment models */
.deploy{display:grid;grid-template-columns:1fr 1fr;gap:1.1rem;
  margin:clamp(1.6rem,3vw,2.2rem) 0 clamp(1.4rem,3vw,2rem)}
.deploy-card{background:var(--panel);border:1px solid var(--line);border-radius:18px;
  padding:1.4rem 1.45rem;display:flex;flex-direction:column;gap:.65rem;box-shadow:var(--shadow)}
.deploy-card--pro{border-color:var(--accent-lisible);box-shadow:0 0 0 1px var(--accent),var(--shadow)}
.deploy-card__top{display:flex;align-items:center;gap:.75rem}
.deploy-card__ic{width:38px;height:38px;flex:none;border-radius:10px;display:grid;place-items:center;
  background:var(--accent-soft);color:var(--accent-lisible)}
.deploy-card__ic svg{width:20px;height:20px}
.deploy-card__tag{font-family:ui-monospace,Menlo,monospace;font-size:.64rem;letter-spacing:.13em;
  text-transform:uppercase;color:var(--accent-lisible);display:block;margin-bottom:.1rem}
.deploy-card h3{font-family:"Archivo",sans-serif;font-weight:600;font-size:1.12rem;letter-spacing:0;line-height:1.15}
.deploy-card p{font-size:.9rem;color:var(--ink-muted);line-height:1.55}
.deploy-card__meta{margin-top:auto;font-family:ui-monospace,Menlo,monospace;font-size:.7rem;
  color:var(--ink-faint);letter-spacing:.02em;padding-top:.3rem}
@media (max-width:720px){.deploy{grid-template-columns:1fr}}

/* ------------------------------------------------------------------ */
/*  FAQ                                                                */
/* ------------------------------------------------------------------ */
.faq-list{margin-top:clamp(1rem,2vw,1.5rem);max-width:880px;border-top:1px solid var(--line)}
.qa{border-bottom:1px solid var(--line)}
.qa>summary{list-style:none;cursor:pointer;display:flex;align-items:center;justify-content:space-between;
  gap:1.2rem;padding:1.2rem .2rem;font-family:"Archivo",sans-serif;font-weight:600;
  font-size:clamp(1rem,1.4vw,1.08rem);color:var(--ink);transition:color .18s}
.qa>summary::-webkit-details-marker{display:none}
.qa>summary:hover{color:var(--accent-lisible)}
.qa__ic{flex:none;width:26px;height:26px;border-radius:7px;border:1px solid var(--line-strong);
  display:grid;place-items:center;color:var(--accent-lisible);position:relative;transition:background .2s,border-color .2s}
.qa__ic::before,.qa__ic::after{content:"";position:absolute;background:currentColor;border-radius:2px}
.qa__ic::before{width:11px;height:2px}
.qa__ic::after{width:2px;height:11px;transition:transform .25s ease}
.qa[open] .qa__ic{background:var(--accent-soft);border-color:var(--accent-lisible)}
.qa[open] .qa__ic::after{transform:scaleY(0)}
.qa__a{padding:0 2.6rem 1.35rem .2rem;color:var(--ink-muted);font-size:.94rem;line-height:1.65;max-width:74ch}
.qa[open] .qa__a{animation:rise .4s ease}
.faq-more{margin-top:1.9rem;font-size:.92rem;color:var(--ink-muted)}
.faq-more a{color:var(--accent-lisible);font-weight:600;border-bottom:1px solid var(--accent-soft)}

/* ------------------------------------------------------------------ */
/*  Subscription form                                                  */
/* ------------------------------------------------------------------ */
.signup{display:grid;grid-template-columns:.85fr 1.15fr;gap:clamp(2rem,5vw,4rem);align-items:start}
.signup__aside .lead{margin-top:1rem}
.signup__pts{list-style:none;margin:1.8rem 0 0;padding:0;display:flex;flex-direction:column;gap:.9rem}
.signup__pts li{display:flex;gap:.7rem;font-size:.92rem;color:var(--ink-muted)}
.signup__pts svg{width:18px;height:18px;flex:none;margin-top:.2rem;color:var(--accent-lisible)}
.form{background:var(--panel);border:1px solid var(--line-strong);border-radius:18px;
  padding:clamp(1.4rem,3vw,2rem);box-shadow:var(--shadow);position:relative;overflow:hidden}
.form__grid{display:grid;grid-template-columns:1fr 1fr;gap:1rem 1rem}
.field{display:flex;flex-direction:column;gap:.35rem}
.field.full{grid-column:1/-1}
.field label{font-size:.78rem;font-weight:600;color:var(--ink);letter-spacing:.01em}
.field label .req{color:var(--accent-lisible)}
.field input,.field select,.field textarea{
  font-family:"Archivo",sans-serif;font-size:.92rem;color:var(--ink);
  background:var(--panel-2);border:1px solid var(--line-strong);border-radius:9px;
  padding:.7em .8em;transition:border-color .16s,box-shadow .16s;width:100%;
}
.field textarea{resize:vertical;min-height:76px}
.field input::placeholder,.field textarea::placeholder{color:var(--ink-faint)}
.field input:focus,.field select:focus,.field textarea:focus{
  outline:0;border-color:var(--accent-lisible);box-shadow:0 0 0 3px var(--accent-soft)}
.consent{grid-column:1/-1;display:flex;gap:.65rem;align-items:flex-start;font-size:.82rem;color:var(--ink-muted)}
/* 24 px : c'est la cible minimale du WCAG 2.2 (2.5.8), et cette case-ci est
   obligatoire pour envoyer le formulaire. */
.consent input{width:24px;height:24px;margin-top:0;accent-color:var(--accent);flex:none}
.form__foot{grid-column:1/-1;display:flex;flex-direction:column;gap:.7rem;margin-top:.3rem}
.form__hint{font-size:.74rem;color:var(--ink-faint);text-align:center}
.form__ok{position:absolute;inset:0;background:var(--panel);display:none;flex-direction:column;
  align-items:center;justify-content:center;gap:.9rem;text-align:center;padding:2rem;z-index:5}
.form__ok.show{display:flex;animation:rise .5s ease forwards}
.form__ok-ic{width:56px;height:56px;border-radius:50%;display:grid;place-items:center;
  background:color-mix(in srgb,var(--pin-green) 18%,transparent);color:var(--pin-green)}
.form__ok-ic svg{width:28px;height:28px}
.form__ok h3{font-family:"Archivo Expanded","Archivo",sans-serif;font-size:1.3rem}
.form__ok p{font-size:.9rem;color:var(--ink-muted);max-width:34ch}
.form__grid noscript{grid-column:1/-1}
.captcha input{max-width:12rem}
.captcha strong{font-family:ui-monospace,Menlo,monospace;font-weight:600;color:var(--accent-lisible)}
.form__err{font-size:.8rem;color:var(--pin-red);text-align:center}
.form__err[hidden]{display:none}
.form.is-sending{opacity:.75;pointer-events:none}
/* honeypot : hors écran, jamais masqué par display:none (certains bots l'ignorent) */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
@media (max-width:820px){.signup{grid-template-columns:1fr}.form__grid{grid-template-columns:1fr}}

/* ------------------------------------------------------------------ */
/*  Footer                                                             */
/* ------------------------------------------------------------------ */
.foot{border-top:1px solid var(--line);background:color-mix(in srgb,var(--panel) 74%,transparent)}
.foot__in{display:flex;flex-wrap:wrap;gap:1.4rem 2rem;align-items:center;justify-content:space-between;
  padding:2.4rem 0}
.foot__links{display:flex;flex-wrap:wrap;gap:1.3rem;font-size:.86rem;color:var(--ink-muted)}
.foot__links a:hover{color:var(--accent-lisible)}
.foot__meta{font-family:ui-monospace,Menlo,monospace;font-size:.72rem;color:var(--ink-faint);line-height:1.7}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none!important;transition:none!important}
}


/* ------------------------------------------------------------------ */
/*  Pages légales (CGV, confidentialité)                               */
/* ------------------------------------------------------------------ */
.legal{max-width:52rem;margin:0 auto}
/* Le titre de la page est un h1 : les pages légales n'en avaient aucun et leur
   plan démarrait au niveau 2. Il garde la taille des titres de section — c'est
   le rang qui change, pas l'allure. */
.legal h1{font-size:1.35rem}
.legal h2{margin-top:2.4rem;font-size:1.35rem}
.legal h2:first-of-type{margin-top:1.2rem}
.legal p,.legal li{color:var(--ink-muted);line-height:1.7}
/* p{margin:0} est global : on réintroduit l'interligne pour les seuls
   paragraphes de corps, sans toucher à ceux qui portent déjà une classe. */
.legal > p:not([class]),.legal > ul{margin-top:.9rem}
.legal ul{padding-left:1.2rem;display:flex;flex-direction:column;gap:.4rem}
.legal a{color:var(--accent-lisible)}
.legal__version{font-family:ui-monospace,Menlo,monospace;font-size:.72rem;letter-spacing:.04em;
  color:var(--ink-faint);margin-top:.9rem}
.legal__quote{border-left:3px solid var(--line-strong);background:var(--panel-2);
  border-radius:0 8px 8px 0;padding:1.1rem 1.3rem;margin:1.2rem 0;
  display:flex;flex-direction:column;gap:.9rem}
.legal__quote p{font-size:.9rem;margin:0}

/* Le conteneur n'est focusable que pour le lien d'évitement : il ne doit pas
   pour autant s'entourer d'un anneau quand on l'atteint. */
main[tabindex="-1"]:focus{outline:none}

/* ------------------------------------------------------------------ */
/*  Comparateur de formules                                            */
/*                                                                     */
/*  Un seul <table> pour tout le comparatif, et non un par catégorie :  */
/*  c'est un seul jeu de données, les colonnes doivent rester alignées, */
/*  et un <thead> unique suffit alors à tenir en haut pendant tout le   */
/*  défilement. Les catégories sont des <tbody> successifs.            */
/* ------------------------------------------------------------------ */
/* Le renvoi depuis le bloc tarifs vers le comparatif. */
.cmp-lien{margin-top:1.2rem;text-align:center}
.cmp-lien a{display:inline-flex;align-items:center;gap:.4rem;color:var(--accent-lisible);
  font-family:"Archivo",sans-serif;font-weight:600;font-size:.95rem;
  border-bottom:1px solid transparent;transition:border-color .18s}
.cmp-lien a:hover{border-bottom-color:var(--accent-lisible)}
.cmp-lien svg{width:17px;height:17px;flex:none;transition:transform .18s}
.cmp-lien a:hover svg{transform:translateX(3px)}
.cmp-lien span{display:block;margin-top:.3rem;font-size:.82rem;color:var(--ink-faint)}
@media (prefers-reduced-motion:reduce){.cmp-lien a:hover svg{transform:none}}

.cmp-wrap{margin-top:clamp(1.4rem,3vw,2.2rem)}
.cmp{width:100%;border-collapse:separate;border-spacing:0;text-align:left;table-layout:fixed}
/* Largeurs fixées : depuis que le tableau ne porte plus que ce qui change, ses
   libellés sont courts (« Clients », « Espace médias ») et ses valeurs longues.
   En répartition automatique, la colonne de gauche tombait sous 100 px et le
   chapeau comme les notes s'y empilaient lettre à lettre. */
.cmp thead th:first-child{width:23%}
.cmp thead th:not(:first-child){width:12.8%}

/* border-collapse:collapse escamote les bordures des cellules collantes :
   d'où separate, et les filets portés par le bas de chaque cellule. */
.cmp th,.cmp td{border-bottom:1px solid var(--line);vertical-align:middle}

/* --- en-tête collant : nom, prix, bouton ------------------------------
   top suit --nav-h, que main.js mesure sur la barre réelle : coder sa
   hauteur en dur ici la ferait chevaucher dès qu'un libellé passe à la
   ligne. */
.cmp thead th{position:sticky;top:var(--nav-h,64px);z-index:3;
  background:var(--ground);border-bottom:1px solid var(--line-strong);
  padding:.9rem .6rem;text-align:center;vertical-align:top}
.cmp thead th:first-child{text-align:left}
.cmp__lede{font-family:"Archivo",sans-serif;font-weight:400;font-size:.82rem;
  color:var(--ink-muted);line-height:1.4;max-width:15rem}
.cmp__nom{font-family:"Archivo Expanded","Archivo",sans-serif;font-weight:700;
  font-size:1.02rem;display:block}
.cmp__prix{display:block;margin-top:.2rem;font-size:.95rem;font-weight:600;color:var(--ink)}
.cmp__prix small{font-weight:400;font-size:.72rem;color:var(--ink-faint)}
/* .tier__amt porte le chiffre géant des cartes de tarifs. La classe est
   nécessaire ici parce que c'est elle que main.js va chercher pour basculer
   mensuel/annuel — mais l'en-tête du comparatif doit rester compact. */
.cmp__prix .tier__amt{font-size:inherit;letter-spacing:0}
.cmp__bill{display:block;font-family:ui-monospace,Menlo,monospace;font-size:.68rem;
  color:var(--ink-faint);margin-top:.15rem;min-height:1.6em}
/* Les colonnes sont fixées à 12,8 % : le bouton doit s'y plier plutôt que
   déborder sur la voisine. */
.cmp thead .btn,.cmp tfoot .btn{margin-top:.5rem;padding:.45em .5em;font-size:.74rem;
  width:100%;text-align:center}
/* La colonne recommandée se signale par un liseré, pas par un aplat : le
   tableau se lit en lignes, un fond plein couperait cette lecture. */
.cmp__col--feat{box-shadow:inset 1px 0 var(--accent),inset -1px 0 var(--accent)}
.cmp tbody .cmp__col--feat{box-shadow:inset 1px 0 var(--accent-soft),inset -1px 0 var(--accent-soft)}
.cmp__flag{display:inline-block;background:var(--accent);color:var(--on-accent);
  font-family:ui-monospace,Menlo,monospace;font-size:.6rem;letter-spacing:.1em;
  text-transform:uppercase;padding:.2em .5em;border-radius:5px;margin-bottom:.3rem}

/* --- lignes de catégorie ----------------------------------------------
   Sélecteurs préfixés de .cmp tbody, et non la seule classe : .cmp tbody th
   plus bas vaut 0,1,2 et l'emporterait sinon sur .cmp__cat th (0,1,1) — la
   couleur et la graisse du libellé de ligne écrasaient celles des
   catégories, y compris de la catégorie clé. */
.cmp tbody .cmp__cat th{background:var(--panel-2);padding:.7rem .8rem;
  font-family:ui-monospace,Menlo,monospace;font-size:.72rem;letter-spacing:.11em;
  text-transform:uppercase;color:var(--ink-muted);font-weight:500;
  border-top:1px solid var(--line-strong)}
/* La première catégorie porte les seules différences entre formules : elle
   se distingue, le reste du tableau étant identique d'une colonne à l'autre. */
.cmp tbody .cmp__cat--cle th{background:var(--accent-soft);color:var(--accent-lisible);font-weight:700}

/* --- cellules ---------------------------------------------------------- */
.cmp tbody th{font-family:"Archivo",sans-serif;font-weight:400;font-size:.88rem;
  color:var(--ink);padding:.72rem .8rem;line-height:1.35}
.cmp tbody td{padding:.72rem .6rem;text-align:center;font-size:.85rem;color:var(--ink-muted)}
/* Le tableau ne porte plus que ce qui change : ses valeurs sont l'information,
   elles doivent peser autant que le libellé de la ligne. */
.cmp__val{font-family:ui-monospace,Menlo,monospace;font-size:.9rem;color:var(--ink);font-weight:600}

/* Le palier où la chose APPARAÎT. Posé uniquement sur les lignes à deux ou
   trois valeurs — la 4K, le PCM, la marque blanche, l'API, l'essai — c'est la
   réponse visuelle à « à partir de quelle offre ? ». Un liseré à gauche plutôt
   qu'un aplat plein : la lecture de la ligne continue. */
.cmp tbody td.cmp__step{background:var(--accent-soft);box-shadow:inset 3px 0 var(--accent-lisible)}
.cmp tbody td.cmp__step .cmp__val,
.cmp tbody td.cmp__step .cmp__soon{color:var(--accent-lisible)}
.cmp tbody td.cmp__step.cmp__col--feat{box-shadow:inset 3px 0 var(--accent-lisible),inset -1px 0 var(--accent-soft)}
.cmp tbody tr:not(.cmp__cat):hover td.cmp__step{background:var(--accent-soft)}
.cmp__note{display:block;font-size:.76rem;color:var(--ink-faint);margin-top:.15rem}
/* :not(.cmp__cat) plutôt qu'une règle de rattrapage après coup : le survol
   d'une ligne de catégorie n'a pas de sens, et la repeindre en gris effaçait
   le fond ambré de la catégorie clé. */
.cmp tbody tr:not(.cmp__cat):hover th,
.cmp tbody tr:not(.cmp__cat):hover td{background:var(--panel-2)}
/* Le crochet porte la couleur lisible, pas l'or de marque : à cette taille
   il doit se voir sur blanc. */
.cmp__y{display:inline-block;width:18px;height:18px;color:var(--accent-lisible)}
.cmp__n{color:var(--ink-faint)}

/* --- sous 760 px : quatre colonnes serrées plutôt qu'un défilement -----
   Un tableau qui glisse horizontalement se lit mal au pouce et cache
   toujours une colonne. Réduire suffit ici : il n'y a que trois formules. */
/* Six colonnes depuis la grille du 14/08 : à partir de 1000 px et en dessous,
   elles ne tiennent plus dans la largeur de lecture. Le tableau glisse alors
   horizontalement dans son propre conteneur, la colonne des libellés restant
   collée à gauche — sans elle, on ne sait plus quelle ligne on lit. */
@media (max-width:1000px){
  /* contain:paint en plus du défilement : sans lui, la largeur du tableau
     (880 px de min-width) remonte dans le débordement de <main> et donc du
     document, qui annonce 849 px de large pour 390 px visibles. La molette et
     le doigt ne peuvent rien en faire — html porte overflow-x:clip — mais un
     défilement programmatique le peut : une cellule atteinte au clavier, et
     scrollIntoView décale la page entière de 459 px sans retour possible.
     La containment de peinture referme le conteneur sur lui-même. */
  /* Le cadre devient un vrai panneau de défilement, borné en hauteur, et non
     plus une simple fenêtre horizontale. C'est ce qui rend l'en-tête collant
     de nouveau utile ici : overflow-x:auto force overflow-y à auto, et le
     conteneur devient donc le repère du position:sticky du thead. Tant qu'il
     faisait toute la hauteur du tableau il ne défilait jamais verticalement —
     l'en-tête ne collait à rien et filait à 643 px au-dessus de l'écran, juste
     au moment où l'on fait glisser six colonnes sans plus savoir laquelle on
     lit. Borné à la hauteur d'écran, il défile, et l'en-tête tient.
     svh et non dvh : dvh change de valeur quand la barre d'URL se rétracte,
     et le panneau se remettrait en page en plein geste. */
  .cmp-wrap{overflow:auto;-webkit-overflow-scrolling:touch;contain:paint;
    max-height:calc(100vh - var(--nav-h,64px) - 1.5rem);
    max-height:calc(100svh - var(--nav-h,64px) - 1.5rem)}
  /* Le repère n'est plus la fenêtre mais le cadre : le retrait de la barre de
     navigation n'a plus lieu d'être, il creuserait un vide sous l'en-tête. */
  .cmp thead th{top:0}
  .cmp{min-width:880px}
  .cmp th:first-child,.cmp tbody th{position:sticky;left:0;z-index:2;background:var(--ground)}
  .cmp tbody tr:not(.cmp__cat):hover th{background:var(--panel-2)}
  .cmp thead th:first-child{z-index:4}
  .cmp tbody .cmp__cat th{z-index:2}
}
@media (max-width:760px){
  /* table-layout:fixed, sinon les largeurs ne sont que des suggestions : le
     moteur répartit d'après le contenu et la colonne des libellés se retrouve
     à un quart de la table, chaque intitulé sur quatre lignes. */
  .cmp{table-layout:fixed}
  .cmp thead th{padding:.6rem .2rem;font-size:.8rem}
  .cmp thead th:first-child{width:180px}
  .cmp thead th:not(:first-child){width:116px}
  .cmp__lede{display:none}
  /* « Professionnal » ne tient pas dans une colonne de soixante-dix pixels et
     ne contient aucune espace où se couper : sans cette autorisation il
     débordait sur la colonne voisine. */
  .cmp__nom{font-size:.76rem;overflow-wrap:anywhere}
  .cmp__prix{font-size:.78rem;white-space:nowrap}
  .cmp__prix small,.cmp__bill{display:none}
  /* Le bouton d'essai est trop large pour une colonne de cette taille : il ne
     vit plus que dans le pied du tableau, où la ligne entière lui est
     consacrée. L'en-tête collant garde le nom et le prix, c'est ce qu'on a
     besoin d'avoir sous les yeux en faisant défiler soixante-huit lignes. */
  .cmp thead .btn{display:none}
  .cmp__flag{font-size:.5rem;padding:.15em .3em;letter-spacing:.06em}
  .cmp tbody th{font-size:.78rem;padding:.6rem .4rem}
  .cmp tbody td{font-size:.76rem;padding:.6rem .15rem}
  .cmp__val{font-size:.66rem;overflow-wrap:anywhere;line-height:1.3}
  .cmp__note{display:none}
  .cmp__y{width:15px;height:15px}
  /* 25 px de haut passaient tout juste les 24 du WCAG 2.5.8 ; ce sont les
     seuls boutons de souscription de la page en mobile, autant qu'ils soient
     confortables. */
  .cmp tfoot .btn{padding:.7em .4em;font-size:.68rem;width:100%;
    overflow-wrap:anywhere;line-height:1.25}
  .cmp tfoot th{font-size:.8rem;padding:1rem .4rem}
  .cmp tfoot td{padding:1rem .15rem}
}

/* --- pied de tableau : les mêmes boutons, à portée de pouce ------------- */
.cmp tfoot th{font-family:"Archivo",sans-serif;font-weight:600;font-size:.88rem;
  color:var(--ink);padding:1rem .8rem}
.cmp tfoot td{padding:1rem .5rem;text-align:center}
.cmp tfoot th,.cmp tfoot td{border-bottom:0;border-top:1px solid var(--line-strong)}
/* Le septième palier n'a pas de colonne : il se dit en une phrase, sous le
   tableau, là où on arrive quand aucune des six n'a convenu. */
.cmp__sur{margin-top:1rem;text-align:center;font-size:.86rem;color:var(--ink-muted)}

/* ---- ce qui est sur toutes les formules -------------------------------
   Quarante-et-une fonctions identiques sur six colonnes faisaient soixante
   lignes de coches que personne ne lisait. En liste, l'argument se prend en
   dix secondes — et le tableau au-dessus ne garde que les décisions. */
.inclus{margin-top:clamp(2rem,4vw,3rem);padding:clamp(1.4rem,3vw,2rem);
  background:var(--panel);border:1px solid var(--line);border-radius:18px;box-shadow:var(--shadow)}
.inclus__t{font-size:1.15rem}
.inclus__c{margin-top:.4rem;font-size:.9rem;color:var(--ink-muted)}
.inclus__grille{display:grid;grid-template-columns:repeat(3,1fr);gap:1.4rem 1.8rem;
  margin-top:clamp(1.2rem,2.5vw,1.8rem)}
@media (max-width:900px){.inclus__grille{grid-template-columns:repeat(2,1fr)}}
@media (max-width:560px){.inclus__grille{grid-template-columns:1fr}}
.inclus__bloc h3{font-family:ui-monospace,Menlo,monospace;font-size:.72rem;letter-spacing:.11em;
  text-transform:uppercase;color:var(--accent-lisible);font-weight:500}
.inclus__bloc ul{list-style:none;margin:.6rem 0 0;padding:0;
  display:flex;flex-direction:column;gap:.4rem}
/* La coche est dessinée en ::before : quarante-et-un SVG pour dire « inclus »
   alourdiraient la page sans rien ajouter. */
.inclus__bloc li{position:relative;padding-left:1.15rem;font-size:.86rem;
  color:var(--ink);line-height:1.4}
.inclus__bloc li::before{content:"";position:absolute;left:0;top:.42em;
  width:.42rem;height:.72rem;border:solid var(--accent-lisible);
  border-width:0 2px 2px 0;transform:rotate(45deg)}

/* Le comparatif est fait pour être posé à côté d'un devis : il s'imprime
   sans l'en-tête collant ni les boutons d'abonnement. */
@media print{
  .cmp thead th{position:static;background:#fff}
  .cmp thead .btn,.cmp__flag{display:none}
  .cmp tbody tr{break-inside:avoid-page;page-break-inside:avoid}
  .cmp__cat th{background:#eee;color:#000}
}

/* ------------------------------------------------------------------ */
/*  Impression                                                         */
/*                                                                     */
/*  Les CGV, les mentions légales et la politique de confidentialité   */
/*  se gardent en PDF ou se classent sur papier. Sans cette feuille,   */
/*  elles s'impriment avec la barre de navigation en travers de la     */
/*  première page, le pied de page marketing et les aplats de fond.    */
/* ------------------------------------------------------------------ */
@media print {
  .nav,.foot,.skip,.legal__nav{display:none !important}
  html,body{background:#fff;color:#000}
  main{padding:0}
  .wrap{max-width:none;padding:0}
  .legal{max-width:none}
  .legal p,.legal li{color:#000;line-height:1.5}
  /* Une URL imprimée ne se clique pas : on écrit la cible à côté du libellé,
     sauf pour les ancres internes et les adresses e-mail déjà lisibles. */
  .legal a{color:#000;text-decoration:underline}
  .legal a[href^="http"]::after{content:" (" attr(href) ")";font-size:.85em;word-break:break-all}
  /* Pas de titre seul en bas de page, pas de paragraphe coupé en deux. */
  h1,h2,h3{break-after:avoid-page;page-break-after:avoid}
  p,li,.legal__quote{break-inside:avoid-page;page-break-inside:avoid}
  .legal__quote{border-left:2px solid #666;background:none}
  @page{margin:18mm 16mm}
}
