/* ==========================================================================
   DYAFA — landing
   Monde visuel : « le voile de couchant ». Structure attendue d'un SaaS,
   exécutée à la barre de craft de Stripe, avec la lumière du couchant pour
   seule matière. Voir .impeccable/surfaces/landing-index-html.md.

   Règles du monde, non négociables :
   - une seule nappe de couchant, jamais répétée, jamais sous du texte ;
   - filets d'un demi-pixel, aucune bordure, aucune ombre, aucune carte ;
   - captures d'écran à plat, jamais inclinées ni encadrées ;
   - l'accroche change de GRAISSE, pas de taille ;
   - rien ne bouge tant que le visiteur n'agit pas.
   ========================================================================== */

/* --- Police de marque, vendorée (jamais Google Fonts en ligne) ------------ */
@font-face{font-family:'Schibsted Grotesk';font-style:normal;font-weight:400;font-display:swap;
  src:url(assets/fonts/schibsted-grotesk-400.woff2) format('woff2')}
@font-face{font-family:'Schibsted Grotesk';font-style:normal;font-weight:500;font-display:swap;
  src:url(assets/fonts/schibsted-grotesk-500.woff2) format('woff2')}
@font-face{font-family:'Schibsted Grotesk';font-style:normal;font-weight:600;font-display:swap;
  src:url(assets/fonts/schibsted-grotesk-600.woff2) format('woff2')}
@font-face{font-family:'Schibsted Grotesk';font-style:normal;font-weight:700;font-display:swap;
  src:url(assets/fonts/schibsted-grotesk-700.woff2) format('woff2')}

/* --- Jetons « Arche au couchant » v3, repris de l'application ------------- */
:root{
  --sky:#A8BEE0;          /* ciel zénithal          */
  --lilac:#B7A8D6;        /* lilas des nuages hauts */
  --coral:#E8998F;        /* corail                 */
  --coral-d:#C4675A;
  --or:#C9A14A;           /* or du design system de l'application */
  --apricot:#F6C9A4;      /* abricot au ras de l'eau*/
  --bg:#FBF4F1;           /* sable nacré — le fond de page EST le sable de la vidéo */
  --panel:#FFFCFB;
  --ink:#2B2333;          /* prune */
  --nav-bg:#5B3A52;       /* prune foncé — la plaque dominante */
  /* ENCRE DOUCE ASSOMBRIE le 2026-09-14 : #443A4B -> #372F3E. « La police du
     texte est peu contrastée, le texte a moins d impact. » Le reproche visait
     la page des fonctionnalités, dont le corps est fait de listes ; il portait
     surtout sur les bandeaux teintés, où cette encre est aussi celle qui
     remplace `--muted` et où elle tombait le plus bas. Mesuré, avant -> après :
       sable   9,89 -> 11,79      abricot 7,07 -> 8,43
       lilas   4,91 ->  5,85      ciel    5,69 ->  6,78
     Le lilas était le point faible de la page — 4,91 pour un texte de 16,5 px,
     juste au-dessus du seuil AA. Il gagne 19 %.

     ⚠️ ELLE RESTE PLUS CLAIRE QUE `--ink` (#2B2333, 13,88 sur le sable). Passer
     directement à l encre principale aurait aplati les deux niveaux en un seul
     — c est exactement ce que le bloc des bandeaux plus bas refuse de faire, et
     pour la même raison. La hiérarchie du texte survit, elle se voit mieux.

     ⚠️ Sur le bandeau PRUNE, `--ink-soft` est réécrite en crème : ce fond
     renverse les encres au lieu de les décaler. Cette ligne ne l atteint pas. */
  --ink-soft:#372F3E;
  --muted:#6D6275;
  --line:#E3CFC8;       /* = --line-2 du core : filet marqué. Le --line du
                             core (#F0E2DC) est trop pâle pour une page où le
                             filet d un demi-pixel porte toute la séparation. */
  --line-doux:#F0E2DC;   /* = --line du core, gardé pour les cas très calmes */
  --on-ink:#FFF5F2;

  /* LA NAPPE DU COUCHANT. Le monde s'appelle « le voile de couchant » : ces
     quatre teintes sont la matière de la page, pas des jetons de réserve.
     Elles étaient déclarées et utilisées ZÉRO fois — le monde choisi n'avait
     donc pas de voile. Règle héritée du design system : elles sont
     DÉCORATIVES — dégradés et aplats seulement, jamais de l'encre, jamais à
     pleine force sous une ligne de texte. */
  --grad-couchant:linear-gradient(105deg,
    var(--sky), var(--lilac) 30%, var(--coral) 62%, var(--apricot));

  --font:'Schibsted Grotesk',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;

  /* Rapport hauteur de capitale / corps de la police, mesuré sur le comp.
     Sert à convertir les hauteurs de capitale du spec en corps de texte. */
  --cap:0.70;
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--bg);color:var(--ink);
  font-family:var(--font);font-weight:400;line-height:1.5;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
}
img,video{display:block;max-width:100%}
a{color:inherit;text-decoration:none}

/* --- LA PAGE -------------------------------------------------------------
   Le héros a été COLLANT du 2026-09-04 au 2026-09-06 : il restait épinglé en
   haut de l'écran et la page montait par-dessus, pour donner à une vidéo de
   douze secondes le temps d'exister. La vidéo est depuis une boucle de dix
   secondes qui tourne seule : le séjour n'a plus rien à faire durer, et le
   propriétaire l'a fait retirer. Le héros redéfile normalement.

   Conséquence directe, et c'est un gain : la page n'a plus besoin d'être
   OPAQUE. Elle ne l'était que pour recouvrir la scène — et c'est cette
   opacité qui obligeait le voile de couchant à vivre à l'intérieur du calque,
   donc AU-DESSUS du texte. Le voile est redescendu sous la page ; il passe
   maintenant sous le contenu, comme le veut le contrat de direction. */
.page{ position:relative;z-index:1 }

/* ==========================================================================
   LA NAVBAR (2026-09-13) — elle remplace la colonne de droite et sa réglette.
   Portage du composant React fourni par le propriétaire : une pastille sombre
   centrée qui se déplie vers le bas en panneau de cartes, la marque à gauche,
   l'appel à l'action à droite. Ni React, ni Tailwind, ni bibliothèque
   d'animation — comme tout le reste de la page.

   Elle est FIXE et flotte au-dessus du héros, qui a perdu sa propre marque :
   deux logos superposés n'en font pas un.
   ========================================================================== */
.nav{
  position:fixed;inset:0 0 auto 0;z-index:40;
  display:flex;align-items:flex-start;justify-content:center;
  gap:clamp(12px,2vw,28px);
  padding:clamp(10px,1.4vw,18px) clamp(16px,3vw,40px);
  /* Le fond reste transparent : la pastille porte à elle seule le poids de la
     barre, et le héros doit rester visible d'un bord à l'autre. */
  pointer-events:none;
}
.nav > *{pointer-events:auto}

.nav__marque{
  display:flex;align-items:baseline;gap:.34em;flex:none;
  font-size:clamp(15px,1.15vw,18px);font-weight:600;letter-spacing:.06em;
  color:#FFF5F2;text-decoration:none;
  /* PAS de `line-height:1`. Il en portait un, et la boîte de la marque
     s'arrêtait alors EXACTEMENT sur la ligne de base : la rangée centrait une
     boîte sans descendante, et le lettrage tombait 4,54 px plus bas que celui
     des liens (mesuré). Avec l'interligne normal, la boîte redevient une ligne
     de texte ordinaire et les encres se retrouvent à 0,4 px près. */
  /* Elle est DANS la pastille depuis le 2026-09-13 : sur le prune, l'encre
     sombre de la page ne se lisait plus. Plus de `padding-top` non plus —
     la rangée centre ses trois occupants elle-même. */
}
/* Même recette que la marque du pied : la ligne de base d'un SVG est le bas de
   sa boîte, et le tracé s'arrête 3 unités sur 24 plus haut. La viewBox est
   recadrée sur le dessin (4 0 16 24), donc le bord gauche tombe sur le lettrage. */
.nav__arche{
  height:calc(1em * var(--cap) * 24 / 18);
  position:relative;top:calc(1em * var(--cap) / 6);
  width:auto;fill:currentColor;flex:none;
}

/* --- La pastille ---------------------------------------------------------
   Un seul bloc sombre : la barre de liens en haut, le panneau qui pousse
   dessous. La hauteur est laissée au contenu — `grid-template-rows` passe de
   0fr à 1fr, ce qui anime une hauteur AUTO sans la mesurer en script. */
.nav__pastille{
  --nav-evase:18px;
  position:relative;
  flex:0 1 auto;
  background:var(--nav-bg);
  border-radius:0 0 18px 18px;
  box-shadow:0 12px 28px -18px rgba(43,35,51,.55);
  margin-top:calc(-1 * clamp(10px,1.4vw,18px));   /* elle pend du bord haut */
}
/* ⚠️ La pastille ne ROGNE PLUS (`overflow:hidden` retiré le 2026-09-13) :
   les évasements vivent en dehors de sa boîte et se faisaient couper. Le
   rognage est descendu là où il sert vraiment — l'enveloppe du panneau, qui
   le portait déjà pour l'animation de hauteur ; les angles bas arrondis sont
   rendus par le panneau lui-même. */

/* --- Les extrémités évasées ----------------------------------------------
   Demandées par le propriétaire (capture du 2026-09-13) : au lieu de tomber
   d'équerre sur le bord haut de la page, la pastille s'y raccorde par un
   congé concave, ce qui l'élargit vers le haut. C'est le dessin des deux SVG
   d'angle du composant fourni, obtenu ici sans SVG : un carré de 18 px rempli
   du fond de la barre, dans lequel un MASQUE retire le quart de disque centré
   sur l'angle bas extérieur. Ils suivent la pastille, qui s'élargit quand le
   panneau s'ouvre.
   Le demi-pixel de chevauchement évite la couture claire que l'antialiasing
   laisse entre deux aplats jointifs. */
.nav__pastille::before,
.nav__pastille::after{
  content:'';position:absolute;top:0;
  width:var(--nav-evase);height:var(--nav-evase);
  background:var(--nav-bg);pointer-events:none;
}
.nav__pastille::before{
  left:calc(.5px - var(--nav-evase));
  -webkit-mask:radial-gradient(circle at 0 100%, transparent 0 var(--nav-evase), #000 calc(var(--nav-evase) + .5px));
          mask:radial-gradient(circle at 0 100%, transparent 0 var(--nav-evase), #000 calc(var(--nav-evase) + .5px));
}
.nav__pastille::after{
  right:calc(.5px - var(--nav-evase));
  -webkit-mask:radial-gradient(circle at 100% 100%, transparent 0 var(--nav-evase), #000 calc(var(--nav-evase) + .5px));
          mask:radial-gradient(circle at 100% 100%, transparent 0 var(--nav-evase), #000 calc(var(--nav-evase) + .5px));
}

/* --- La rangée -----------------------------------------------------------
   La marque, les liens et l'appel à l'action sur une seule ligne, centrés les
   uns sur les autres. Les trois vivaient de part et d'autre de la pastille ;
   le propriétaire les a demandés dedans. */
.nav__barre{
  display:flex;align-items:center;
  gap:clamp(10px,1.6vw,26px);
  padding:0 clamp(12px,1.2vw,18px);
  height:54px;
}
.nav__liens{
  display:flex;align-items:center;justify-content:center;
  gap:clamp(2px,.5vw,10px);
}
.nav__liens a,
.nav__deplie{
  display:inline-flex;align-items:center;gap:.35em;
  padding:.5em .8em;border-radius:9px;
  font:inherit;font-size:clamp(12.5px,.95vw,14px);font-weight:500;
  color:#CDB6C6;                      /* l'encre secondaire du fond prune */
  background:none;border:0;cursor:pointer;white-space:nowrap;
  text-decoration:none;
  transition:color .18s ease, background-color .18s ease;
}
.nav__liens a:hover,
.nav__deplie:hover{color:#FFF5F2}

/* « SE CONNECTER » PORTE UNE ICÔNE ET DU GRAS (2026-09-14). C'est le seul lien
   de la rangée qui mène ailleurs que dans la page : les autres déplacent le
   lecteur, celui-ci le fait entrer. Le gras et le signe le disent avant qu'on
   ait lu le mot.

   Le glyphe est dessiné ici, au trait, comme les trois pictogrammes des étapes :
   aucune bibliothèque d'icônes n'entre dans ce projet. C'est le MÊME dessin que
   celui de l'étape « vous créez votre compte », et c'est voulu — les deux disent
   « entrer ».

   ⚠️ `.nav__liens .nav__connexion` et non `.nav__connexion` : la règle de la
   rangée pose `font-weight:500` avec un poids de (0,1,1), qu'une classe seule
   ne bat pas. */
.nav__liens .nav__connexion{font-weight:600}
.nav__entrer{
  width:1.15em;height:1.15em;flex:none;
  fill:none;stroke:currentColor;stroke-width:1.9;
  stroke-linecap:round;stroke-linejoin:round;
}
.nav__deplie[aria-expanded="true"]{background:rgba(255,245,242,.10);color:#FFF5F2}
.nav__chevron{
  width:.86em;height:.86em;fill:none;stroke:currentColor;stroke-width:2.2;
  stroke-linecap:round;stroke-linejoin:round;opacity:.75;
  transition:transform .22s ease;
}
.nav__deplie[aria-expanded="true"] .nav__chevron{transform:rotate(180deg)}

/* --- Le panneau ----------------------------------------------------------
   `grid-template-rows:0fr → 1fr` : la seule façon d'animer une hauteur qu'on
   ne connaît pas sans la mesurer en JavaScript. L'enfant doit porter
   `min-height:0`, sinon il refuse de descendre sous son contenu. */
.nav__panneau{
  display:grid;grid-template-rows:0fr;
  /* `visibility` en plus de la hauteur : replié, le panneau garderait sinon
     ses neuf liens atteignables au clavier et lisibles par un lecteur d'écran,
     invisibles mais bien là. Le délai la retarde le temps de la fermeture. */
  visibility:hidden;
  transition:grid-template-rows .26s cubic-bezier(.2,.7,.3,1),
             visibility 0s linear .26s;
  border-top:1px solid rgba(255,245,242,0);
}
.nav__panneau{border-radius:0 0 18px 18px}
.nav__enveloppe{overflow:hidden;min-height:0;border-radius:inherit}
.nav__pastille:has(.nav__deplie[aria-expanded="true"]) .nav__panneau{
  grid-template-rows:1fr;
  visibility:visible;
  transition:grid-template-rows .26s cubic-bezier(.2,.7,.3,1), visibility 0s;
  border-top-color:rgba(255,245,242,.14);
}
.nav__grille{
  list-style:none;margin:0;padding:clamp(12px,1.2vw,18px);
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(6px,.7vw,10px);
  width:min(78vw,760px);
}
.nav__grille a{
  display:flex;flex-direction:column;gap:.25em;
  padding:.85em .9em;border-radius:12px;
  text-decoration:none;
  border:1px solid rgba(255,245,242,.10);
  transition:border-color .18s ease, background-color .18s ease;
}
.nav__grille a:hover{
  border-color:rgba(255,245,242,.24);
  background:rgba(255,245,242,.06);
}
.nav__titre{font-size:13.5px;font-weight:600;color:#FFF5F2;line-height:1.25}
.nav__dit{font-size:11.5px;line-height:1.4;color:#CDB6C6}
.nav__aller{
  margin-top:.5em;font-size:11px;font-weight:600;letter-spacing:.04em;
  color:#CDB6C6;transition:color .18s ease, transform .18s ease;
}
.nav__aller::after{content:' →'}
.nav__grille a:hover .nav__aller{color:#FFF5F2;transform:translateX(3px)}

/* --- L'appel à l'action ---------------------------------------------------
   Il était un aplat d'encre sombre posé à côté de la pastille. Dedans, sur le
   prune, ce même aplat disparaissait ; un aplat clair, lui, aurait crié plus
   fort que la marque. Il prend donc l'encre de la barre — celle des titres du
   panneau, pas celle des liens, sans quoi il serait rentré dans le rang — et
   garde son geste : la flèche qui glisse. Le liseré lui laisse sa qualité de
   bouton, que la couleur seule ne porte plus. */
.nav__cta{
  display:inline-flex;align-items:center;gap:.5em;flex:none;
  padding:.62em 1.05em;border-radius:999px;
  font-size:clamp(12.5px,.95vw,14px);font-weight:600;
  color:#FFF5F2;text-decoration:none;
  background:rgba(255,245,242,.09);
  border:1px solid rgba(255,245,242,.24);
  white-space:nowrap;
  transition:background-color .18s ease, border-color .18s ease;
}
.nav__cta:hover{background:rgba(255,245,242,.18);border-color:rgba(255,245,242,.42)}
.nav__fleche{
  width:.9em;height:.9em;fill:none;stroke:currentColor;stroke-width:2.2;
  stroke-linecap:round;stroke-linejoin:round;
  transition:transform .18s ease;
}
.nav__cta:hover .nav__fleche{transform:translateX(2px)}

/* --- Téléphone et tablette ------------------------------------------------
   LA MÊME BARRE, MOINS D'OCCUPANTS (refonte du 2026-09-14). Elle était une
   boîte flottante à coins arrondis, avec un second bloc prune posé à côté
   pour le bouton : deux objets, un dessin de barre qui n'avait plus rien à
   voir avec celui de l'ordinateur. Demande du propriétaire : « elle doit
   correspondre visuellement à celle de l'ordinateur ; pour gérer l'espace on
   n'affichera que Créer mon compte et Se connecter, plus l'icône du menu ».

   Elle garde donc TOUT ce qui fait la barre de l'ordinateur — elle pend du
   bord haut, son sommet est d'équerre, son pied est arrondi, ses extrémités
   sont évasées — et ne perd que des occupants. C'est pour cela que ce bloc
   ne redéfinit ni `margin-top`, ni `border-radius` : ils sont hérités.

   Ce qui reste dans la rangée : la marque, « Se connecter », « Créer mon
   compte », le bouton. Ce qui passe dans le tiroir : Accueil, les neuf
   fonctionnalités, Roadmap, Tarifs, FAQ. */
.nav__burger{display:none}
.nav__tiroir{display:none}

@media (max-width:980px){
  /* La marge latérale de la page borne l'évasement : il déborde de la
     pastille de `--nav-evase`, et la pastille prend toute la largeur
     disponible. 14 px de congé sous 16 px de marge — il reste 2 px. */
  /* `--nav-tel` : l'encre des deux boutons de la rangée. Elle descend avec la
     largeur — à 360 px, quatre occupants et trois écarts ne tiennent dans la
     pastille qu'à 11 px (mesuré : −2 px de marge à 11,5) ; à 430 px, 12,5 px
     respirent. */
  .nav{--nav-tel:clamp(11px,3vw,12.5px);padding:clamp(10px,1.4vw,18px) 14px}
  .nav__pastille{--nav-evase:12px;flex:1 1 auto;min-width:0}

  /* Le panneau à neuf cases n'a pas la place : c'est le tiroir qui porte les
     fonctionnalités au téléphone, en liste repliable. */
  .nav__panneau{display:none}
  .nav__barre{height:50px;padding:0 6px 0 10px;gap:clamp(5px,2vw,10px)}
  .nav__marque{font-size:clamp(13.5px,3.7vw,15px);margin-right:auto}

  /* La rangée de liens RESTE — un seul de ses occupants s'affiche. La cacher
     entièrement aurait emporté « Se connecter » avec elle, et le rapatrier
     dans le tiroir contredisait la demande. */
  /* ⚠️ `> a` et non `> *` : `.nav__liens a` pose `display:inline-flex` avec un
     poids de (0,1,1), qu'un `> *` à (0,1,0) ne bat pas. Mesuré : les cinq liens
     restaient dans la rangée et la pastille débordait de 110 px de chaque côté. */
  .nav__liens{gap:0}
  .nav__liens > a{display:none}
  .nav__liens > .nav__deplie{display:none}
  .nav__liens .nav__connexion{display:inline-flex;font-size:var(--nav-tel);padding:.5em .1em;gap:.3em}
  /* L'icône d'entrée coûte 15 px sur une rangée qui se joue à quelques pixels :
     mesuré, elle faisait déborder la rangée de 1 px à 360 px de large. Elle
     rentre d'un dixième d'em et le lien rend un peu de son rembourrage — la
     marge revient à 6 px, et le signe reste lisible. */
  .nav__entrer{width:1em;height:1em}

  .nav__cta{font-size:var(--nav-tel);padding:.52em .8em;gap:.35em}
  /* La flèche tombe : elle ne sert que le survol, qui n'existe pas ici, et
     elle coûtait 16 px sur une rangée qui se joue à quelques pixels. */
  .nav__cta .nav__fleche{display:none}

  /* Le bouton est DANS la pastille : plus de fond à lui, il lirait comme un
     second bloc. La cible tactile reste tenue par la hauteur de la rangée et
     par les 44 px de la boîte. */
  .nav__burger{
    display:grid;place-items:center;align-content:center;gap:5px;
    width:32px;height:44px;flex:none;
    border:0;border-radius:9px;background:none;cursor:pointer;
  }
  .nav__burger__trait{
    display:block;width:17px;height:1.5px;background:#FFF5F2;border-radius:2px;
    transition:transform .2s ease, opacity .2s ease;
  }
  .nav__burger[aria-expanded="true"] .nav__burger__trait:first-child{transform:translateY(3.25px) rotate(45deg)}
  .nav__burger[aria-expanded="true"] .nav__burger__trait:last-child{transform:translateY(-3.25px) rotate(-45deg)}

  /* LE TIROIR SE DÉPLIE COMME LE PANNEAU : même mécanique de hauteur
     (`0fr → 1fr`), même enveloppe qui rogne, même `visibility` retardée pour
     que les liens repliés cessent d'être atteignables au clavier. Il agrandit
     la pastille au lieu de tomber dessous. */
  .nav__tiroir{
    display:grid;grid-template-rows:0fr;
    visibility:hidden;
    border-top:1px solid rgba(255,245,242,0);
    border-radius:0 0 18px 18px;
    transition:grid-template-rows .26s cubic-bezier(.2,.7,.3,1),
               visibility 0s linear .26s;
  }
  .nav__pastille:has(.nav__burger[aria-expanded="true"]) .nav__tiroir{
    grid-template-rows:1fr;
    visibility:visible;
    transition:grid-template-rows .26s cubic-bezier(.2,.7,.3,1), visibility 0s;
    border-top-color:rgba(255,245,242,.14);
  }
  /* Le rembourrage vit SOUS l'enveloppe : posé sur le tiroir, il survivrait
     au repli et laisserait 16 px de prune sous la barre fermée. */
  .nav__pile{display:grid;padding:8px}
  .nav__tiroir a,
  .nav__tiroir summary{
    display:block;padding:.6em .8em;border-radius:9px;
    font-size:14.5px;color:#CDB6C6;text-decoration:none;cursor:pointer;
    min-height:44px;                     /* cible tactile tenue */
    line-height:1.9;
  }
  .nav__tiroir a:hover,.nav__tiroir summary:hover{color:#FFF5F2;background:rgba(255,245,242,.07)}
  .nav__repli summary{font-weight:600;color:#FFF5F2;list-style:none}
  .nav__repli summary::-webkit-details-marker{display:none}
  .nav__repli summary::after{content:'+';float:right;opacity:.6}
  .nav__repli[open] summary::after{content:'–'}
  .nav__repli > a{margin-left:.8em;font-size:13.5px}
}

/* --- Les petits téléphones ------------------------------------------------
   Mesuré à 320 px : la rangée débordait sa propre boîte de 21 px. Le lettrage
   de la marque tombe, l'arche reste. Ce n'est pas une amputation : l'arche est
   le logo, et l'ancre porte déjà « DYAFA — accueil » comme nom accessible —
   un lecteur d'écran lit exactement la même chose qu'à 390 px.
   Les écarts et les marges se resserrent d'un cran dans la foulée. */
@media (max-width:359px){
  .nav{padding:clamp(10px,1.4vw,18px) 10px}
  .nav__mot{display:none}
  .nav__marque{gap:0}
  .nav__barre{padding:0 4px 0 8px;gap:4px}
  .nav__burger{width:28px}
}

/* --- LA LUMIÈRE QUI DESCEND — RETIRÉE le 2026-09-09 ----------------------
   Deux halos (zénith lilas en haut, abricot au ras de l'eau en bas) descendaient
   avec le visiteur, pilotés par une variable `--jour` de 0 à 1. C'était le
   « moment mémorable » du contrat de direction et une demande du propriétaire
   du 2026-09-04.

   Le propriétaire l'a fait retirer le 2026-09-09 : « les halos ne donnent pas
   grand-chose, des fois c'est juste moche ». Le fond sable reste ; ce sont
   désormais des BANDEAUX TEINTÉS, alternés avec le sable, qui délimitent les
   sections — voir « LES BANDEAUX » plus bas.

   Ce qui part avec eux : l'élément .lumiere en tête de <body>, la variable
   --jour et la ligne de script qui la mettait à jour. Ce qui RESTE dans ce même
   script, et qu'il ne fallait pas emporter : le CTA ancré, la marque de la
   colonne et les blocs `[data-remplit]`. */

/* Le motif de zellige a couvert toute la page du 2026-09-04 au 2026-09-06,
   à 4 % au plus, sous un masque qui le faisait respirer. Retiré à la demande
   du propriétaire, avec le supplément qui le doublait sur la section 2 : les
   motifs à faible opacité s'en vont. Le fichier est sorti du dossier publié ;
   son master reste dans `assets/masters/`. */

/* ==========================================================================
   PREMIER ÉCRAN
   Les positions viennent de .impeccable/build/scaffold/layout.css, mesurées
   sur la maquette approuvée. Unités cqw : tout est proportionnel au cadre,
   donc la composition tient à n'importe quelle largeur.
   ========================================================================== */

/* --u : L'UNITÉ DE LA COMPOSITION DU HÉROS.
   Tout le premier écran est mesuré sur la maquette en `cqw` — des
   pourcentages de la LARGEUR du cadre — tandis que les positions verticales
   sont des pourcentages de sa HAUTEUR. Les deux ne se correspondent que si
   le cadre garde son rapport d'image. Or `max-height:100svh` l'écrase dès
   qu'une fenêtre est large et courte : à 1880 × 820, le cadre passe de
   1870 × 1044 à 1870 × 820, la composition se comprime verticalement, mais
   le texte, lui, se calcule toujours sur la largeur et ne bouge pas. Le
   bouton finissait alors PAR-DESSUS la dernière ligne du titre — 28 px de
   recouvrement, mesurés.

   `min(1cqw, 1.7917cqh)` prend la plus contraignante des deux dimensions,
   1,7917 étant le rapport de la maquette (2752/1536). Tant que le cadre
   tient son rapport, 1.7917cqh vaut exactement 1cqw : le rendu ne change
   PAS d'un pixel. Quand la hauteur est écrasée, toute la composition suit
   au lieu de se chevaucher.

   Hors du héros, --u reste 1cqw : les rares règles partagées (`.btn`) se
   comportent exactement comme avant. */
:root{--u:1cqw}

.hero{
  --u:min(1cqw, 1.7917cqh);
  position:relative;
  /* TOUTE la largeur de l'écran (demande du propriétaire, 2026-09-04). La
     version précédente bornait le cadre par la hauteur disponible et laissait
     du sable sur les côtés au-delà de 1,79:1. On garde le ratio de la
     composition, mais c'est la HAUTEUR qui plafonne : le héros ne dépasse
     jamais l'écran, et la vidéo remplit le cadre bord à bord. */
  width:100%;
  aspect-ratio:2752 / 1536;
  max-height:100svh;
  /* `size` et non `inline-size` : sans la hauteur, `cqh` n'existe pas. */
  container-type:size;
  overflow:hidden;
  background:var(--bg);
}

/* --- Plaque 1 : la vidéo de l'arche --------------------------------------
   Boîte mesurée : x0 y0 w90% h90%.

   L'ancrage était `center bottom`, et sa raison a disparu. Il gardait bas dans
   le cadre le lettrage « DYAFA / hostel manager » gravé dans le sable — mais la
   vidéo a été remplacée le 2026-09-06 par une boucle SANS LETTRAGE (`d38c9d1`),
   et le commentaire est resté. Tant que le cadre garde son rapport d'image,
   l'ancrage ne change rien : il n'y a pas de rognage. Sur un écran large et
   court, en revanche, `bottom` rognait le haut — c'est-à-dire l'arche.

   Relevé sur l'affiche : l'arche occupe la bande 23 % → 60 % de la hauteur de
   l'image ; en dessous, il n'y a que l'eau et le sable. Ancrée au centre, la
   fenêtre visible reste 12,7 % → 87,3 % même sur un rapport de 2,4 : l'arche y
   est entière avec de la marge des deux côtés, et ce qui se perd est du sable
   sans motif. */
.arche{
  /* plein cadre : la vidéo ne laisse plus 10 % de sable à droite et en bas */
  position:absolute;inset:0;
  width:100%;height:100%;
  object-fit:cover;object-position:center center;
  background:var(--bg);
}

/* Le sable de la vidéo se dissout dans le sable de la page : le fond n'est
   pas « sous » l'image, il en est la continuation. Masque, pas recadrage. */
.hero::after{
  content:'';position:absolute;inset:0;pointer-events:none;
  background:
    /* ⚠️ LE HALO DE SABLE A ÉTÉ RETIRÉ le 2026-09-14, à la demande du
       propriétaire — « enlever le masque, je m occupe de dire si le texte reste
       lisible ». Il ne reste donc ici que la dissolution vers le bas.

       CE QU IL FAISAIT, ET CE QU ON PERD : un voile de sable radial sous le bloc
       de texte. Mesuré le 2026-09-13, sans lui le titre passe sur la vidéo nue et
       le contraste de l encre y descend à 2,15 au plus mauvais moment de la
       boucle (t ≈ 7,5 s), sous le seuil de 3 exigé pour un gros texte. Sur les
       autres images il tient 3,7 : une mesure sur UNE seule image aurait conclu
       que le halo ne servait à rien. Le propriétaire arbitre en connaissance de
       cause, et se réserve le jugement de lisibilité.

       La dissolution du bas, elle, RESTE : ce n est pas un masque sur le texte,
       c est le raccord entre le sable de la vidéo et le sable de la page. La
       retirer ouvrirait un bord net au milieu de la page. */

    /* 2. La dissolution du sable de la vidéo vers le sable de la page.
       DESCENDUE ET ALLÉGÉE le 2026-09-13 : « on ne voit plus l'animation de
       l'eau qui monte et descend, on dirait une image fixe ».

       Mesuré, et non supposé : deux images de la vidéo comparées ligne à ligne
       (t = 0,2 s contre t = 4,5 s) montrent que le mouvement se concentre
       entre 60 % et 80 % de la hauteur de l'image, avec un pic net à 65 %. Or
       l'ancien dégradé y était opaque à 87 % : il éteignait très exactement la
       seule chose qui bouge, et le premier écran se lisait comme une photo.

       Le nouveau profil reste transparent jusqu'à 55 % et ne monte qu'à 10 %
       vers 74 % — là où le dégradé précédent était déjà à 92 %. Le mouvement
       visible, pondéré par la couverture du masque, passe de 4,0 à 33,4 : huit
       fois plus. La dissolution vers le sable de la page se fait alors sur les
       douze derniers pour cent, ce qui suffit à ce que le bord ne se voie pas. */
    linear-gradient(to bottom,
      transparent 55%,
      rgba(251,244,241,.10) 74%,
      rgba(251,244,241,.40) 88%,
      rgba(251,244,241,.85) 96%,
      var(--bg) 100%),
    /* plus de fondu latéral : la vidéo va d'un bord à l'autre */
    linear-gradient(to bottom,transparent 100%,transparent 100%);
}

/* --- Couche sémantique ---------------------------------------------------- */
.sem{position:absolute;z-index:2}

/* Hors de vue, mais lu. Sert à donner UNE fois aux lecteurs d'écran un texte
   que l'affichage répète pour boucler (la banderole des canaux). */
.hors-vue{
  position:absolute;width:1px;height:1px;margin:-1px;padding:0;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0;
}

/* `.marque__arche` a été retirée le 2026-09-14 : son dernier utilisateur était
   la marque du pied, qui est devenue une image. L'arche de la navbar a la
   sienne (`.nav__arche`), recadrée et calée autrement. */

.marque{
  left:var(--r-marque-x,10%); top:var(--r-marque-y,0%);
  display:flex;align-items:center;gap:.42em;
  font-size:calc(1.0392 * var(--u) / var(--cap));
  /* le comp est quasiment sans interlettrage : la mesure 0,2451 du script
     n exprime pas des em */
  font-weight:600;letter-spacing:.02em;
  color:var(--ink);
  /* La boîte mesurée du comp démarre sur la lettre D. L'arche est un ajout :
     elle se place DEVANT le nom, donc tout le bloc recule d'exactement sa
     largeur plus la gouttière, sinon le nom glisse hors de sa boîte. */
  transform:translate(-1.3533em, .45em);
}

.accroche{
  left:var(--r-accroche-x,9.99%); top:var(--r-accroche-y,44%);
  /* La composition tient sur TROIS lignes quel que soit le mot de la
     roulette. Elle était réglée sur « maison d'hôtes » (327 px) ; « location
     courte durée » en fait 420 au corps actuel, et c'est lui qui commande la
     boîte. Les deux valeurs ont été mesurées, pas estimées. */
  width:42%;
  margin:0;
  font-size:calc(2.2602 * var(--u) / var(--cap));
  font-weight:400;line-height:1.12;letter-spacing:-.022em;
  color:var(--ink);
  transform:translateY(-0.14em);
}
/* Le mot change de GRAISSE, jamais de taille — sinon la ligne se recompose
   à chaque mot. */
.accroche b{font-weight:700;font-style:normal}

/* LE BLOC DU BAS DESCEND (2026-09-14) — « mettre un espace significatif entre
   les textes du dessus et du dessous ». Le titre finissait à 69,2 % et le
   bouton commençait à 69,99 % : SEPT PIXELS les séparaient à 1 440 px. Ce
   n était pas un choix, c était la rencontre de deux positions posées
   séparément. Le bouton descend à 73,5 %, ce qui ouvre 51 px. */
.actions{
  left:var(--r-cta-primaire-x,9.99%); top:var(--r-cta-primaire-y,70%);
  display:flex;gap:calc(.5 * var(--u));align-items:stretch;
}
/* ⚠️ LES TROIS NOMBRES DU BOUTON SONT LIÉS. Hauteur, largeur et corps
   viennent des boîtes mesurées sur la composition d origine ; les agrandir
   séparément déforme le bouton. Le propriétaire a demandé « un CTA
   significativement plus grand » le 2026-09-14 : les trois sont donc
   multipliés par le MÊME facteur, 1,4, et le dessin est intact — seule
   l échelle change. Le bouton passe de 50 à 70 px de haut à 1 440 px.
   Le facteur vit dans une variable pour que la prochaine main qui le règle
   ne puisse pas en oublier un. */
.btn{
  --echelle-btn:1.4;
  display:inline-flex;align-items:center;justify-content:center;
  height:calc(6.25 * var(--echelle-btn) * var(--u) * 1536 / 2752);
  font-size:calc(0.7485 * var(--echelle-btn) * var(--u) / var(--cap));
  font-weight:400;letter-spacing:-.005em;white-space:nowrap;
  border-radius:.92em;
  cursor:pointer;
  transition:background .18s cubic-bezier(.2,.6,.3,1),color .18s cubic-bezier(.2,.6,.3,1);
}
.btn--primaire{width:calc(12.86 * var(--echelle-btn,1) * var(--u));background:var(--ink);color:var(--on-ink)}
.btn--secondaire{width:calc(10.68 * var(--echelle-btn,1) * var(--u))}
.btn--primaire:hover{background:#1F1926}
.btn--secondaire{
  color:var(--ink);
  /* filet d'un demi-pixel : jamais une bordure pleine */
  box-shadow:inset 0 0 0 .5px var(--ink);
  background:transparent;
}
.btn--secondaire:hover{background:rgba(43,35,51,.05)}
.btn:focus-visible{outline:2px solid var(--coral-d);outline-offset:3px}

/* « Agrandir et contraster significativement » (2026-09-14). Cette ligne est
   la seule du héros qui lève les trois objections d achat — pas de carte, pas
   de rendez-vous, pas de devis — et elle était traitée comme une légende :
   14 px d encre douce sous un titre de 46. Elle prend 33 % de corps, passe en
   demi-gras et prend l encre PRINCIPALE. Elle s élargit d autant, sinon le
   corps plus grand la ferait courir sur trois lignes. */
.ligne-acces{
  left:var(--r-ligne-acces-x,10%);
  top:calc(var(--r-ligne-acces-y,70%) + 11.6%);
  width:var(--r-ligne-acces-w,46%);margin:0;
  font-size:calc(0.92 * var(--u) / var(--cap));
  font-weight:500;color:var(--ink);letter-spacing:-.004em;
}

/* La roulette (plan média §2b). Un ROULEAU vertical, pas un fondu : les mots
   glissent vers le haut et cèdent la place au suivant. Aucune bibliothèque et
   aucun JavaScript — le composant React qui a servi de référence pilotait un
   `translateY` avec un `setInterval` ; un `@keyframes` fait la même chose,
   sans état à tenir ni minuteur à nettoyer.

   Le dernier mot de la piste est une reprise du premier : à la fin du cycle
   l'animation revient à zéro sur une image identique, donc sans saut.

   La pile réserve la largeur du plus long (« location courte durée ») : la
   phrase ne se recompose jamais, ce que la règle du monde interdit. C'est
   pour cela que le titre a été réglé sur ce mot-là et non sur le premier. */
.roulette__pile{
  display:inline-block;overflow:hidden;vertical-align:bottom;
  height:var(--lh, 1.12em);
}
/* La piste réserve la largeur du plus long des mots, mesurée au chargement.
   Un réglage intermédiaire animait cette largeur pour coller au mot affiché :
   plus de trou, mais la phrase se recomposait à chaque tour et le titre
   passait de deux à trois lignes sous les yeux du lecteur. Réserver est plus
   juste — et le vide qui reste après les mots courts tombe en FIN DE LIGNE,
   parce que la phrase passe à la ligne juste après la roulette. */
.roulette__piste{
  display:block;width:var(--wmax, auto);
  animation:roule 14s cubic-bezier(.65,0,.2,1) infinite;
}
.roulette__mot{
  display:block;
  height:var(--lh, 1.12em);line-height:var(--lh, 1.12em);
}
/* Cinq paliers : le mot tient environ quatre cinquièmes de son temps, puis
   glisse. La transition est brève et franche — le glissement doit se lire
   comme un mécanisme, pas comme un effet. */
@keyframes roule{
  0%,  16% {transform:translateY(0)}
  20%, 36% {transform:translateY(calc(var(--lh, 1.12em) * -1))}
  40%, 56% {transform:translateY(calc(var(--lh, 1.12em) * -2))}
  60%, 76% {transform:translateY(calc(var(--lh, 1.12em) * -3))}
  80%, 96% {transform:translateY(calc(var(--lh, 1.12em) * -4))}
  100%     {transform:translateY(calc(var(--lh, 1.12em) * -5))}
}
/* LA MÊME CHORÉGRAPHIE, À CINQ VIGNETTES (téléphone). Quatre mots plus la
   reprise du premier : la piste descend de quatre interlignes, pas de cinq.
   Les paliers sont plus longs — quatre mots en douze secondes au lieu de cinq
   en quatorze — pour que chacun se lise. */
@keyframes roule-court{
  0%,   20% {transform:translateY(0)}
  25%,  45% {transform:translateY(calc(var(--lh, 1.12em) * -1))}
  50%,  70% {transform:translateY(calc(var(--lh, 1.12em) * -2))}
  75%,  95% {transform:translateY(calc(var(--lh, 1.12em) * -3))}
  100%      {transform:translateY(calc(var(--lh, 1.12em) * -4))}
}
/* Sans mouvement demandé, la copy validée reste, seule et lisible. */
@media (prefers-reduced-motion:reduce){
  .roulette__piste{animation:none !important}
}

/* --- Le bloc bêta : ce que le séjour raconte -----------------------------
   Demande du propriétaire (2026-09-04) : le temps passé sur le héros doit
   servir à quelque chose, et les mentions doivent s'afficher UNE À UNE ET
   PERSISTER — la liste s'écrit, elle ne défile pas. Elle occupe l'espace
   laissé vide entre le bloc de texte et la main, celui que le propriétaire a
   entouré sur sa capture.

   Les termes sont les siens, en anglais là où il les a écrits ainsi
   (« channel manager », « booking engine », « OCR CIN ») : un premier
   réglage les avait traduits pour s'aligner sur le reste de la page, ce
   n'était pas ce qui était demandé.

   Chaque mot apparaît quand la course de séjour dépasse son rang, et ne
   repart plus. Aucun déplacement : la place est réservée dès le départ,
   sinon la ligne se recomposerait à chaque apparition. */
.beta{
  left:var(--r-accroche-x,9.99%);
  /* Elle suit la ligne d accès, qui a grossi et descendu. */
  top:91.7%;
  width:52%;
}
.beta__etat{
  margin:0 0 .8em;
  font-size:calc(0.66cqw / var(--cap));
  letter-spacing:.13em;text-transform:uppercase;
  color:var(--ink-soft);
}
.beta__etat b{font-weight:600;color:var(--ink)}

/* Les neuf mentions « Fonctionnalités en développement » qui s'écrivaient au
   fil du séjour ont été retirées (2026-09-06). Seule reste la ligne de vente
   ci-dessus : les fonctionnalités astérisquées sont dites par la frise de la
   feuille de route et par l'encadré d'accès anticipé.

/* Le sommaire ne vit plus dans le héros : il a rejoint la colonne de droite,
   plus bas dans cette feuille. Il y était positionné en absolu et passait
   donc sous le calque qui recouvre la scène. */

/* --- Plaque 2 : la capture réelle du planning, coupée par le pli ---------- */
/* La capture n'est pas étalée dans la région : elle est posée à sa taille
   propre, à l'emplacement exact de l'encre du comp, et c'est le bord bas du
   premier écran qui la coupe — d'où le pli qui invite à faire défiler.
   Boîte d'encre mesurée : 1439 x 148 à (71,159) dans la région. */
/* Plaque 2 : la main au téléphone. Elle entre par le BAS du cadre et le
   héros la coupe net — le téléphone tient entier dans l'image, c'est la
   manche qui sort du champ. Ancrée par « bottom » et par la hauteur, jamais
   par la largeur : la hauteur du héros varie avec l'écran, sa largeur non.
   Le bord droit s'arrête avant la colonne du sommaire. */
/* PLUS GRANDE, ET L ÉCRAN A CHANGÉ (2026-09-14). Le téléphone montrait le
   tableau de bord ; il montre le PLANNING de la semaine — le propriétaire l a
   demandé, c est l écran qui dit le mieux ce que fait l application.

   LE MASTER EST RECADRÉ SUR SON ENCRE : les 497 px de vide à gauche et les
   281 en haut ne servaient qu à placer le sujet, et c est la mise en page qui
   s en charge. Dans l image servie, le téléphone occupe de 0,78 % à 62,02 %
   de la hauteur — mesuré, et c est de là que viennent les deux nombres
   ci-dessous.

   ⚠️ LA TAILLE EST BORNÉE PAR TROIS CHOSES, PAS PAR LE GOÛT.

   1. En haut, la NAVBAR : le téléphone ne doit pas passer dessous.
   2. À gauche, le TITRE : la main ne doit pas le toucher.
   3. En bas, LA MAIN ELLE-MÊME. Premier réglage du 2026-09-14 : 119 % et 38 %
      poussée vers le bas. Le téléphone y gagnait 46 % — et la paume et le
      poignet sortaient du cadre. « La main est trop grossie, il faut qu on la
      voie en entier et un peu la manche. »

   C EST DONC LA MAIN QUI COMMANDE, ET NON LE TÉLÉPHONE. Mesuré sur l image
   servie : la peau cède au tissu de la manche à 78,5 % de la hauteur — la
   saturation moyenne d une ligne y tombe de 0,20 à 0,15 en quarante pixels.
   À 92 % de hauteur et 10 % poussée vers le bas, le bas du cadre coupe l image
   à 89,1 % : la main est entière, et il reste dix points de manche sous le
   poignet. Le téléphone garde 450 px, soit 12 % de plus qu avant ce chantier,
   et son sommet est à 94 px sous la navbar. */
.plaque-2{
  position:absolute;z-index:1;margin:0;
  right:0; bottom:-10%;
  height:92%; width:auto;
}
.plaque-2 img{height:100%;width:auto}

/* --- Rien ne bouge tant que le visiteur n'agit pas ------------------------ */
@media (prefers-reduced-motion:reduce){
  *{animation:none !important;transition:none !important}
}

/* --- Étape de capture : plaques seules (portillon « record hero ») -------- */
body.plaques-seules .sem,
body.plaques-seules .hero::after{display:none}

/* ==========================================================================
   LE RESTE DE LA PAGE
   Mêmes règles que le premier écran : filets d'un demi-pixel, aucune bordure,
   aucune ombre, aucune carte arrondie, captures à plat. La nappe de couchant
   a été dépensée dans le héros — elle ne revient jamais.
   ========================================================================== */

:root{
  --maxw:1120px;
  --fs-h2:clamp(26px,2.4vw,36px);
  --fs-h3:clamp(18px,1.4vw,21px);
  --fs-body:clamp(16px,1.15vw,17.5px);
  --fs-small:clamp(14px,1vw,15px);
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
}

.sec,.pied{position:relative;z-index:1}
/* --pad-sec : le rembourrage horizontal des sections, en UN SEUL endroit.
   Il est lu ailleurs — le bandeau repris du catalogue doit le reprendre pour
   ressortir bord a bord. Le recopier a la main a deja coute 25 px de
   debordement a 900 px : la valeur y est surchargee plus bas, et la copie ne
   le savait pas. Une variable heritee ne peut pas se desynchroniser. */
.sec{--pad-sec:clamp(20px,5vw,64px);padding:clamp(64px,7vw,128px) var(--pad-sec)}
.lisiere{max-width:var(--maxw);margin-inline:auto}

/* --- LES BANDEAUX (2026-09-09) -------------------------------------------
   Ce qui remplace les halos. Le fond sable reste la matière de la page ; des
   sections entières prennent une teinte pleine, en ALTERNANCE avec le sable,
   et c'est ce qui les délimite. Deux teintes, celles du couchant, qui
   alternent aussi entre elles : abricot, sable, lilas, sable, abricot…

   LES JETONS SONT REDÉFINIS SUR LE BANDEAU, ET NON LES 23 RÈGLES QUI LES
   UTILISENT. Les propriétés personnalisées héritent : tout ce que contient un
   bandeau suit, sans qu'on ait à surcharger `.intro`, `.mentions`,
   `.jalon` et les vingt autres — ni à en oublier une.

   Pourquoi --muted devient --ink-soft, et pas --ink : MESURÉ.
   L'encre discrète #6D6275 ne tient que sur le sable (5,28:1) ; elle tombe à
   3,78:1 sur l'abricot et 2,62:1 sur le lilas, sous le seuil AA. L'encre douce
   #443A4B, elle, passe partout — 9,89 / 7,07 / 4,91 — et reste plus claire que
   l'encre principale : la hiérarchie du texte survit, l'accessibilité aussi.
   Passer directement à --ink aurait aplati les deux niveaux en un seul. */
.teinte-abricot,
.teinte-lilas,
.teinte-bleu{
  --muted:var(--ink-soft);
  /* Le filet d'un demi-pixel est calculé pour le sable ; sur une teinte pleine
     il disparaît. On le remplace par de l'encre très diluée, qui tient sur les
     deux fonds. */
  --line:rgba(43,35,51,.24);
  --line-doux:rgba(43,35,51,.13);
  /* Le corail #C4675A tombe à 1,76:1 sur le lilas — « Prochaine étape » de la
     feuille de route y devenait illisible. Cette terre cuite sombre passe sur
     les trois fonds (9,29 sable / 6,65 abricot / 4,61 lilas) et reste chaude.
     L'information n'a jamais tenu à la couleur seule : le mot est écrit. */
  --coral-d:#6E2E23;
}
.teinte-abricot{background:var(--apricot)}
.teinte-lilas{background:var(--lilac)}
.teinte-bleu{background:var(--sky)}

/* L'ENCADRÉ TEINTÉ — la variante « pour changer », demandée le 2026-09-09.
   Là où le bandeau va d'un bord à l'autre, l'encadré laisse le sable tout
   autour. C'est ce qui permet de donner une couleur à CHAQUE fonctionnalité
   sans jamais poser deux couleurs l'une contre l'autre : entre deux encadrés
   teintés, il y a une fonctionnalité nue sur le sable.
   Les classes `.teinte-…` fournissent le fond et les encres ; celle-ci ne
   s'occupe que de la boîte. La règle de bord à bord des bandeaux ne l'atteint
   pas : elle est cadrée sur `.sec.teinte-…`, et un encadré n'est pas une
   section. */
/* LE BANDEAU DES OTA, REPRIS DANS LE CATALOGUE (2026-09-09).
   Celui du haut de page vit HORS de <main> : il va d'un bord à l'autre sans
   rien demander. Celui-ci est enfoui dans le catalogue — section, lisière,
   grille, puis le bloc du groupe — et doit ressortir de tout cela.

   La lisière est bornée à 1 120 px et CENTRÉE : la distance à rattraper n'est
   donc pas seulement le rembourrage de la section, elle dépend de la largeur.
   D'où la requête de conteneur posée sur la section : `100cqw` donne la largeur
   de contenu de la section, `100%` celle de la lisière, et leur demi-différence
   est exactement ce qu'il faut reprendre de chaque côté — plus le rembourrage.

   Pourquoi pas `100vw`, la recette habituelle : `vw` compte la barre de
   défilement, que la page n'occupe pas. Le bandeau dépasserait alors de sa
   largeur et rouvrirait un débordement horizontal — le défaut que ce chantier
   vérifie à chaque livraison. */
.sec--fonctions{container-type:inline-size}

.bandeau.bandeau--repris{
  margin-block:clamp(40px,4vw,72px);
  margin-inline:calc((100% - 100cqw) / 2 - var(--pad-sec));
}
/* La règle de gouttière qui vivait ici est partie avec la colonne (2026-09-13). */

/* --- L'APPARITION AU DÉFILEMENT (2026-09-14) ----------------------------
   « Une animation douce en cascade pour l'apparition des éléments au scroll ».

   ⚠️ LA CLASSE QUI CACHE EST POSÉE PAR LE SCRIPT, jamais dans le HTML — même
   règle que l'entrée des neuf cartes. Sans JavaScript, ou sans
   `IntersectionObserver`, un contenu laissé à `opacity:0` ne serait plus
   jamais montré à personne. La page sans script reste entière.

   La cascade est un simple retard indexé : `--i` est le rang de l'élément
   parmi ses frères, plafonné par le script à 6 — au-delà, le dernier d'une
   longue liste attendrait une seconde entière après le premier, ce qui ne se
   lit plus comme une cascade mais comme un chargement lent.

   22 px, pas 60 : l'élément se pose, il n'arrive pas de l'extérieur du cadre.
   Et `will-change` n'est PAS déclaré — l'entrée ne se joue qu'une fois, et
   une couche de composition par bloc de la page coûterait plus que le geste
   ne rapporte. */
.monte{
  opacity:0;transform:translateY(22px);
  transition:opacity .62s ease, transform .62s cubic-bezier(.23,1,.32,1);
  transition-delay:calc(var(--i,0) * .08s);
}
.monte--vu{opacity:1;transform:none}
/* Sans mouvement demandé, le script s'arrête avant de poser la classe ; cette
   règle est la ceinture de la bretelle, pour le cas où elle aurait été posée
   avant que le réglage change. */
@media (prefers-reduced-motion:reduce){
  .monte{opacity:1;transform:none;transition:none}
}

/* --- LES OMBRES DOUCES ET DIFFUSES (2026-09-14) -------------------------
   Demande du propriétaire : « ajouter des ombres douces et diffuses aux
   éléments ». Douce veut dire trois couches : un contact très court et très
   pâle qui pose l'objet, une portée moyenne qui lui donne son épaisseur, et
   une portée longue et très diluée qui fait le halo. Une ombre à une seule
   couche est toujours soit un trait, soit un nuage.

   Les rayons sont NÉGATIFS en étalement (`-12px`, `-32px`) : l'ombre est
   rétractée sous l'objet avant d'être diffusée, sans quoi elle déborde de
   tous les côtés et l'objet a l'air de flotter à dix centimètres.

   L'encre est celle du texte (#2B2333), jamais du noir : sur du sable, une
   ombre noire vire au gris sale. */
:root{
  --ombre-douce:0 2px 4px -2px rgba(43,35,51,.07),
               0 12px 28px -12px rgba(43,35,51,.20),
               0 30px 64px -34px rgba(43,35,51,.20);
  /* Pour les grands aplats : un panneau large n'a pas besoin d'épaisseur, il
     a besoin d'être décollé du fond. Une seule couche, très diluée. */
  --ombre-tenue:0 20px 52px -34px rgba(43,35,51,.26);
}

/* L'ANGLE ARRONDI, SUR TOUTES LES IMAGES (annotation du 2026-09-09, page 4 :
   « arrondir l'angle — pour toutes les images »). Cela revient sur la décision
   du 2026-09-07 qui voulait la bande d'ambiances « posée à plat, aucun cadre,
   aucune ombre, aucun arrondi » : l'arrondi l'emporte désormais, partout.
   Les captures glissées DANS un châssis d'appareil sont exclues : le châssis
   découpe déjà l'ouverture de l'écran au bon rayon, et un second arrondi par
   en dessous rognerait l'image une deuxième fois, de travers. */
main img{border-radius:14px;box-shadow:var(--ombre-douce)}
main .appareil img,
main .sec--final__arche{border-radius:0}

/* CE QUI NE PREND PAS L'OMBRE, et pourquoi :
   — dans un châssis, l'écran est déjà porté par l'ombre du châssis ;
   — dans une carte, le fond EST la carte, qui a la sienne ;
   — la facture porte la sienne depuis le 2026-09-09 (plus rasante, elle est
     posée sur un bureau, pas décollée d'une page) ;
   — les deux arches sont des glyphes détourés : une ombre rectangulaire
     autour d'un dessin transparent dessinerait une boîte qui n'existe pas. */
main .appareil img,
main .carte img,
main .feuille,
main .sec--final__arche{box-shadow:none}

.encadre-teinte{
  padding:clamp(26px,3.2vw,52px);
  border-radius:18px;
  box-shadow:var(--ombre-tenue);
  /* `.fort` se sépare de son voisin par un filet en haut ; dans un encadré,
     c'est la boîte qui sépare, et le filet ferait doublon. */
  border-top:0;
}

/* LE PRUNE est le seul fond SOMBRE de la série : il renverse les encres au lieu
   de les décaler. Mesuré sur #5B3A52 — crème 9,02:1, l'encre du texte
   secondaire 5,11:1, l'encre normale 1,56:1 (donc impossible). Un fond sombre
   ne se traite pas comme une teinte claire un peu plus forte : c'est une
   inversion complète, filets compris. */
.teinte-prune{
  background:var(--nav-bg);
  --ink:#FFF5F2;
  --ink-soft:#FFF5F2;
  --muted:#CDB6C6;
  --line:rgba(255,245,242,.26);
  --line-doux:rgba(255,245,242,.14);
  --coral-d:#F0B9AC;      /* l'accent doit s'éclaircir lui aussi */
  /* Une carte posée sur un fond SOMBRE s'assombrit, elle ne s'éclaircit pas.
     Premier essai à l'inverse — un voile crème à 7 % : il portait le fond de
     rgb(91,58,82) à rgb(102,71,93) et faisait tomber l'encre secondaire de
     5,11 à 4,22, sous le seuil, sur douze textes. Le défaut était invisible
     tant que la mesure lisait la couleur translucide comme si elle était
     opaque ; il a fallu composer les calques pour le voir.
     Une encre diluée creuse le panneau au lieu de le percer, et le contraste
     du texte clair qu'il porte ne peut qu'y gagner. */
  --surface-carte:rgba(43,35,51,.24);
  color:var(--ink);
}

/* Bord à bord, gouttière comprise. Le bandeau prune (§2a) y arrive en vivant
   HORS de <main> ; les sections, elles, sont dedans, et <main> réserve 148 px
   au sommaire au-dessus de 1 180 px. Une marge négative va rechercher cette
   gouttière, et un rembourrage de MÊME valeur la rend au contenu : la boîte de
   contenu ne bouge donc pas d'un pixel — seule la peinture s'étend. Sans quoi
   le bandeau s'arrêterait 148 px avant le bord droit, ce qui se lirait comme
   un défaut à côté d'un bandeau prune qui, lui, va au bout.
   Ce bloc vit APRÈS la déclaration de `.sec` — c'est tout ce qui lui permet
   d'en surcharger le rembourrage. Il vivait AVANT : le raccourci `padding` de
   `.sec`, à spécificité égale mais déclaré plus bas, écrasait alors ce
   `padding-right`, la gouttière n'était pas rendue au contenu, et le texte des
   bandeaux se décalait de 11 px à gauche et de 137 px à droite (mesuré).

   La règle qui allait chercher la gouttière du sommaire au-dessus de 1 180 px
   vivait ici. Elle est partie le 2026-09-13 avec la colonne de droite : plus
   rien n'occupe ce bord, les bandeaux vont donc au bout d'eux-mêmes. Avec elle
   disparaît la raison de doubler le sélecteur en `.sec.teinte-…` — ce
   doublement bornait la règle aux SECTIONS, pour que les encadrés teintés des
   fonctionnalités n'aillent pas chercher une gouttière qui ne les concernait
   pas. */

.lisiere--centre{text-align:center}

h2{
  margin:0 0 .6em;
  font-size:var(--fs-h2);font-weight:600;line-height:1.14;letter-spacing:-.022em;
  color:var(--ink);max-width:22ch;
}
.lisiere--centre h2{max-width:none}
h3{margin:0 0 .35em;font-size:var(--fs-h3);font-weight:600;letter-spacing:-.015em}
p{margin:0 0 1em;font-size:var(--fs-body);line-height:1.62;color:var(--ink-soft)}
b,strong{font-weight:600;color:var(--ink)}

/* L'astérisque : une marque, jamais une couleur seule. Expliqué une fois. */
/* L'astérisque est le seul garde-fou d'honnêteté de la page : il doit se voir.
   Le corail sur sable tombait à 3,55:1 et sur la plaque prune à 2,50:1 — sous
   le plancher de 4,5:1. Il passe en encre pleine et grossit. */
/* --- LE BADGE « BIENTÔT » -------------------------------------------------
   Il remplace l'astérisque PARTOUT sur la page (décision du 2026-09-07). Un
   astérisque demande une légende et se lit mal à petite taille ; le badge dit
   la chose lui-même, et la légende de l'encadré « accès anticipé » n'a plus
   qu'à le montrer.

   L'or du design system (#C9A14A) ne tient que 2,2:1 sur le sable — il servait
   pour un glyphe, il ne peut pas porter un mot. Le libellé est donc en encre
   douce (9,9:1) et c'est le FILET qui est en terracotta : la couleur ne porte
   jamais l'information toute seule, le mot « Bientôt » la porte. */
.bientot{
  display:inline-block;white-space:nowrap;
  margin-left:.45em;
  padding:.24em .55em .2em;
  font-size:.62em;font-weight:500;
  letter-spacing:.12em;text-transform:uppercase;
  line-height:1.25;
  color:var(--ink-soft);
  box-shadow:inset 0 0 0 .5px var(--coral-d);
  border-radius:.5em;
  vertical-align:.14em;
}
/* En préfixe : il annonce la ligne au lieu de la clore. */
.bientot--avant{margin-left:0;margin-right:.5em;vertical-align:.06em}

/* Sur les fonds prune — la bande des canaux et la plaque du restaurant — le
   même objet emprunte l'encre de son fond. */
.bandeau .bientot{
  margin:0;
  font-size:.74em;letter-spacing:.14em;
  color:rgba(255,243,238,.86);
  box-shadow:inset 0 0 0 .5px rgba(255,243,238,.42);
  vertical-align:0;
}
.intro{font-size:calc(var(--fs-body) * 1.14);max-width:62ch;color:var(--ink-soft)}

/* --- 2a. Le bandeau des capacités ---------------------------------------
   Même prune que la plaque Restaurant : les deux seuls aplats pleins de la
   page se répondent, l'un ouvre le propos, l'autre le referme. Il ferme le
   premier écran et sert de SOL à la main, qui s'arrête sur son bord haut.
   Le texte défile : c'est le premier mouvement porteur de sens de la page,
   et il dit exactement ce que fait le logiciel. */
.bandeau{
  background:var(--nav-bg);color:#FFF3EE;
  overflow:hidden;
  padding-block:clamp(15px,1.6vw,24px);
  /* le bandeau touche le héros sans filet : c'est une rencontre, pas une
     séparation */
  margin:0;
}
.bandeau__voie{
  display:flex;width:max-content;
  animation:defile 64s linear infinite;
}
/* Le bandeau tient sur DEUX lignes depuis le 2026-09-07 : une annonce fixe,
   puis les noms des canaux qui défilent. La ligne fixe doit se lire d'un coup
   — c'est elle qui porte l'information — et seul le second registre bouge. */
.bandeau__texte{
  margin:0;white-space:nowrap;
  font-size:var(--fs-body);
  line-height:1.4;color:rgba(255,243,238,.88);
  display:flex;align-items:center;
}
/* Le titre reproduit EXACTEMENT la construction du contenu de la page :
   le retrait de `.sec`, puis la lisière centrée, puis la gouttière du
   sommaire à droite. Recopier « 20 px » à la main mettait le titre 10 px à
   côté à 1440 et 40 px à côté à 1200 — mesuré. Trois termes, pas un de moins. */
.canaux__haut{padding-inline:clamp(20px,5vw,64px)}
/* Le rembourrage de gouttière est parti avec la colonne (2026-09-13). */
.canaux__titre{
  /* la lisière est reprise ICI et non par la classe `.lisiere` : celle-ci est
     déclarée plus haut dans la feuille, et le raccourci `margin` de cette
     règle écrasait son `margin-inline:auto` — le titre restait collé au bord
     (mesuré : 20 px au lieu de 81). */
  max-width:var(--maxw);
  margin:0 auto .55em;
  /* Deux lignes centrées (demande du propriétaire) : le badge au-dessus,
     l'annonce en dessous. La lisière et la gouttière restent posées — sans
     elles, « centré » voudrait dire centré sur l'écran, donc décalé vers la
     droite de la moitié de la colonne du sommaire. */
  display:flex;flex-direction:column;align-items:center;gap:.42em;
  text-align:center;
  font-size:calc(var(--fs-body) * 1.06);
  line-height:1.35;color:#FFF3EE;
}
/* Chaque reprise de la liste est bornée par un filet d'un demi-pixel, jamais
   par un glyphe : c'est la seule séparation que connaisse le monde visuel. */
.canaux__groupe{
  display:inline-flex;align-items:center;gap:.75em;
  padding-inline:2.2em;
  box-shadow:inset -.5px 0 0 0 rgba(255,243,238,.30);
}
.canaux__ota{flex:none;letter-spacing:.01em}
.canaux__pt{flex:none;color:rgba(255,243,238,.5)}
@keyframes defile{
  from{transform:translate3d(0,0,0)}
  to{transform:translate3d(-50%,0,0)}
}
/* le visiteur qui veut lire arrête le défilement en survolant */
.bandeau:hover .bandeau__voie,
.bandeau:focus-within .bandeau__voie{animation-play-state:paused}

/* --- 2. L'accroche -------------------------------------------------------
   La suite immédiate du titre porté par la vidéo : ce que le logiciel fait,
   puis pour qui il est fait. Un seul bloc de texte, large, dans l'encre
   pleine — c'est la promesse, elle ne se murmure pas. La phrase d'ancrage
   au Maroc se détache d'un filet d'un demi-pixel, qui ne court pas plus
   loin qu'elle. */
.sec--accroche{
  position:relative;isolation:isolate;
  padding-block:clamp(52px,5.6vw,96px);
}

/* Le voile, et le grain du sable. Plan média §2 : « fond sable + motif
   zellige estompé », « dégradé couchant à faible opacité ».
   Le voile est un HORIZON posé au bord haut de la section : la lumière de
   la vidéo ne s'arrête pas au pli, elle finit ici. Il est éteint bien avant
   la première ligne de texte — la règle « jamais sous du texte » tient. */
.sec--accroche::before{
  content:'';position:absolute;inset:0;z-index:-1;pointer-events:none;
}
.sec--accroche::before{
  background:var(--grad-couchant);
  opacity:.13;
  /* Le voile NAÎT du sable : opacité nulle au bord haut, sinon une couture
     nette apparaît là où le héros finit. Il culmine juste sous ce bord et
     s'éteint avant le bas de la section. À 13 % il éclaire le sable sans
     jamais peser sur l'encre — contraste vérifié au navigateur. */
  -webkit-mask-image:linear-gradient(to bottom,
    transparent 0%, rgba(0,0,0,.72) 15%, rgba(0,0,0,.46) 44%, transparent 88%);
          mask-image:linear-gradient(to bottom,
    transparent 0%, rgba(0,0,0,.72) 15%, rgba(0,0,0,.46) 44%, transparent 88%);
}
/* La section ne porte plus qu'une phrase : elle la porte donc en grand.
   C'est la charnière entre ce que fait le logiciel (le bandeau, au-dessus)
   et pour qui il est fait (tout ce qui suit). */
/* --- Les arguments transverses (§2, 2026-09-07) ---------------------------
   Sans puces : chaque argument tient sa ligne, et c'est un filet d'un
   demi-pixel qui les sépare. Deux colonnes sur ordinateur — huit lignes en
   file indienne feraient une colonne interminable sous une phrase courte —
   une seule dès que la place manque. */
.atouts{
  list-style:none;margin:2.4em 0 0;padding:0;
  /* Deux colonnes, une seule quand la place manque, et jamais trois : la
     réserve de 420 px en donne exactement deux sur les 1120 px de la lisière.
     Mesuré : à 300 px de réserve on en obtenait trois, ce qui laissait une
     dernière rangée de deux orpheline ; à 390 px de large, deux colonnes
     donnaient des lignes de 161 px, soit trois mots par ligne. */
  display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,420px),1fr));
  column-gap:clamp(28px,4vw,64px);
  max-width:var(--maxw);
}
.atouts li{
  padding:.85em 0;
  border-top:.5px solid var(--line);
  font-size:var(--fs-body);line-height:1.45;
  color:var(--ink-soft);
}
.atouts b{font-weight:600;color:var(--ink)}
/* Ce qui est encore à venir se lit en retrait, sans qu'on ait à le lire. */
.atouts--bientot{color:var(--muted)}

/* ==========================================================================
   3. TOUT CE QUE FAIT DYAFA
   La section unique qui a remplacé les anciennes 3, 4 et 5. Trois traitements
   alternés — deux grilles de cartes, quatre temps forts, une grille « à venir »
   — pour que cinquante-deux capacités ne fassent pas un mur de texte.
   ========================================================================== */
.fonctions__titre{max-width:30ch;margin-bottom:1.4em}

/* ==========================================================================
   LES NEUF CARTES (2026-09-13) — le catalogue quitte la landing.

   Portage de la carte 3D fournie par le propriétaire (test/animation). Ni
   React, ni Tailwind, ni framer-motion : l'inclinaison suit le pointeur par
   deux variables posées en script, tout le reste est en CSS.

   Ce qui est GARDÉ du composant : l'inclinaison qui suit le curseur, le
   soulèvement, la photo qui respire, le reflet diagonal orienté par le
   pointeur, le texte qui monte et le « Explorer » qui entre par la gauche,
   et l'entrée en cascade.
   Ce qui est ÉCARTÉ : le semis de points, les carrés qui tournent, la pastille
   qui pulse et le halo flou. Quatre décorations qui parlaient d'un autre
   vocabulaire que cette page — et la consigne du 2026-09-09 était d'enlever.
   ========================================================================== */
.cartes{
  list-style:none;margin:0;padding:0;
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(14px,1.6vw,24px);
}

/* La perspective vit sur la CASE, jamais sur la carte : posée sur l'élément
   qui tourne, elle tournerait avec lui et l'inclinaison serait plate. */
.carte-case{perspective:1200px;min-width:0}

/* L'entrée en cascade est un AJOUT du script, pas un état par défaut : sans
   JavaScript, ou sans IntersectionObserver, une carte laissée à `opacity:0`
   ne serait jamais rendue visible par personne. Les cartes sont donc là, et
   c'est le script qui les cache une fraction de seconde pour les faire entrer. */
.cartes--entree .carte-case{
  opacity:0;transform:translateY(26px);
  transition:opacity .55s ease, transform .55s cubic-bezier(.23,1,.32,1);
  transition-delay:calc(var(--i,0) * .07s);
}
.cartes--entree.cartes--vues .carte-case{opacity:1;transform:none}

.carte{
  --rx:0deg;--ry:0deg;--leve:0px;
  position:relative;display:block;
  height:clamp(268px,25vw,340px);
  border-radius:16px;text-decoration:none;
  transform-style:preserve-3d;
  transform:rotateX(var(--rx)) rotateY(var(--ry)) translateZ(var(--leve));
  transition:transform .26s cubic-bezier(.2,.8,.25,1), box-shadow .3s ease;
  box-shadow:0 10px 26px -18px rgba(43,35,51,.55);
}
.carte:hover{box-shadow:0 26px 48px -26px rgba(43,35,51,.6)}
.carte:focus-visible{outline:2px solid var(--coral-d);outline-offset:4px}
/* ⚠️ AUCUN `overflow:hidden` sur la carte. Tout rognage — comme une opacité
   ou un filtre — ramène `transform-style` à plat, et l'inclinaison disparaît
   sans message. Chaque calque porte donc son propre arrondi. */

.carte__fond{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;border-radius:inherit;
  transition:transform .5s ease;
}
.carte:hover .carte__fond{transform:scale(1.04)}

/* Le voile. Il ne décore pas : il garantit le contraste du lettrage QUELLE QUE
   SOIT la photo. Au pire — une photo entièrement blanche — le bas de la carte
   reste à 8,5:1 (calculé sur l'aplat composité). */
.carte__voile{
  position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  /* Le BAS reste couvert — c'est là que le lettrage se pose, et c'est la
     seule chose qui garantisse sa lisibilité quelle que soit la photo. Le HAUT,
     lui, s'est dégagé : à .16 la photo lisait comme un rectangle sombre.
     MESURÉ sur les photos réelles, aux trois lignes de texte, au pire pixel
     de chacune : 5,4:1 dans le pire cas (échantillonnage 200 x 174 ; 5,5 à
     80 x 70) — le libellé de la carte « Canaux » sur le surf de Taghazout, la
     plus claire du lot. */
  background:linear-gradient(to top,
    rgba(26,20,31,.88) 0%,
    rgba(26,20,31,.76) 42%,
    rgba(26,20,31,.22) 72%,
    rgba(26,20,31,.02) 100%);
}

/* Le reflet diagonal. Son ANGLE suit le pointeur — c'est ce qui donne la
   matière : une bande fixe lirait comme un dégradé posé. */
.carte__reflet{
  position:absolute;inset:0;border-radius:inherit;
  overflow:hidden;pointer-events:none;
}
.carte__reflet::before{
  content:'';position:absolute;inset:-40%;
  background:linear-gradient(var(--brille,128deg),
    transparent 42%, rgba(255,245,242,.26) 50%, transparent 58%);
  opacity:0;transition:opacity .3s ease;
}
.carte:hover .carte__reflet::before{opacity:1}

/* Le texte vit 26 px AU-DESSUS de la photo : c'est cet écart qui se voit quand
   la carte s'incline, et rien d'autre. Sans lui, l'inclinaison ne serait qu'une
   image qui penche. */
.carte__dire{
  position:relative;z-index:2;
  display:flex;flex-direction:column;align-items:flex-start;
  height:100%;justify-content:flex-end;
  padding:clamp(16px,1.5vw,22px);
  transform:translateZ(26px);
  color:#FFF5F2;
  transition:transform .3s ease;
}
.carte:hover .carte__dire{transform:translateZ(26px) translateY(-3px)}
.carte__nom{
  font-size:var(--fs-small);font-weight:500;
  letter-spacing:.13em;text-transform:uppercase;
  /* PLEINE ENCRE, et non 82 % puis 88 % comme essayé d'abord : sur la photo la
     plus claire du lot (le surf de Taghazout), le libellé tombait à 4,35:1 —
     sous la norme. Son second plan ne tient donc pas à la couleur mais à la
     TAILLE et à l'interlettrage, ce qui vaut mieux : c'est la règle de la page,
     une information n'est jamais portée par la seule couleur. */
  color:#FFF5F2;
}
.carte__cri{
  margin-top:.5em;
  font-size:calc(var(--fs-body) * 1.12);
  font-weight:600;line-height:1.22;letter-spacing:-.01em;
  text-wrap:balance;
}
.carte__aller{
  display:inline-flex;align-items:center;gap:.55em;
  margin-top:.75em;
  font-size:var(--fs-small);font-weight:600;letter-spacing:.05em;
}
.carte__aller::before{
  content:'';width:16px;height:1.5px;flex:none;
  background:currentColor;border-radius:2px;
}
/* « Explorer » n'apparaît qu'au survol — mais SEULEMENT là où le survol existe.
   Au doigt, il n'y a pas de survol : masquer l'invite y reviendrait à la
   supprimer pour la moitié des visiteurs. */
@media (hover:hover){
  .carte__aller{
    opacity:0;transform:translateX(-8px);
    transition:opacity .3s ease .08s, transform .3s ease .08s;
  }
  .carte:hover .carte__aller,
  .carte:focus-visible .carte__aller{opacity:1;transform:none}
}

/* Le badge « Bientôt » sur une photo : il emprunte l'encre claire de la carte,
   son filet terracotta ne se voyant pas sur un fond sombre. */
.carte .bientot{
  color:#FFF5F2;
  box-shadow:inset 0 0 0 .5px rgba(255,245,242,.5);
}

/* LE DUO DU GROUPE DES CANAUX (2026-09-14) — « le mettre a cote du texte sur
   ordi ; sur mobile le schema et le bandeau s'enchainent, il faudrait mettre
   le texte au milieu ». Une seule structure repond aux deux.

   L'ordre du DOM est : schema, puis capacites. Sur telephone, la grille
   retombe en une colonne et le texte se retrouve donc EXACTEMENT entre le
   schema et le bandeau des OTA. Sur ordinateur, la grille replace les
   capacites en premiere colonne : le texte a gauche, l'image a droite, comme
   partout ailleurs sur la page.

   C'est pour cela que les colonnes sont NOMMEES et non laissees au flux : le
   flux donnerait le schema a gauche, et l'ordre du DOM est ici commande par le
   telephone, pas par l'ordinateur. */
@media (min-width:901px){
  .canaux__duo{
    display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
    gap:clamp(24px,3vw,52px);align-items:start;
  }
  .canaux__duo .capacites{grid-column:1;grid-row:1}
  .canaux__duo .schema--large{grid-column:2;grid-row:1;margin-bottom:0}
}

/* --- La carte des canaux : un schéma, pas une photo ----------------------
   Le schéma est dessiné sur du BLANC. Passé sous le voile des cartes — qui
   monte à 88 % d'encre en bas — il deviendrait de la boue. Il est donc posé
   sur une plaque claire dans le haut de la carte, et c'est la carte qui
   fournit le fond sombre, comme pour le graphe des chiffres.

   `object-fit:contain` et non `cover` : un schéma se lit en entier ou ne se
   lit pas. Recadré, il perdrait deux des huit canaux.

   Le voile reste, inchangé : il ne couvre plus une photo mais le fond de la
   carte, et c'est lui qui tient le lettrage du bas. */
.carte--schema{
  background:linear-gradient(158deg, #3A2B3F 0%, #2B2333 58%, #221B29 100%);
}
.carte--schema .schema{
  /* LA HAUTEUR N EST PAS CHOISIE, ELLE EST CE QUI RESTE. La plaque est calee
     par le BAS a 152 px — la hauteur du bloc de texte, qui ne varie pas : le nom
     de cette carte tient sur deux lignes (« Channel manager & booking engine »
     plus son badge) et le texte remonte donc plus haut que sur les huit autres.
     Une hauteur en POURCENTAGE ne marchait pas : a 44 %, bon sur une carte de
     300 px, la plaque mordait de 18 px sur le texte des cartes de 240 px du
     telephone. Un texte qui ne change pas de taille ne se borne pas en pour cent. */
  position:absolute;left:5%;right:5%;top:4%;bottom:152px;height:auto;
  display:block;border-radius:10px;overflow:hidden;
  background:#FFFFFF;
}
.carte--schema .schema img{
  display:block;width:100%;height:100%;
  object-fit:contain;object-position:center;
}

/* Le même schéma, à sa taille de lecture, dans le groupe des fonctionnalités.
   Sur le sable de la page, une image à fond blanc flotte sans bord : le filet
   d'un demi-pixel la borne, comme il borne la facture. */
.schema--large{
  margin:0 0 1.5em;max-width:620px;
  border-radius:12px;overflow:hidden;
  /* Le filet intérieur borne l'image blanche ; l'ombre la décolle du sable.
     Les deux tiennent dans la même déclaration — `box-shadow` ne se cumule
     pas entre règles, la dernière remplace la précédente. */
  box-shadow:inset 0 0 0 .5px var(--line), var(--ombre-douce);
  background:#FFFFFF;
}
.schema--large img{display:block;width:100%;height:auto}

/* --- La carte des chiffres : un graphe, pas une photo --------------------
   Portage du composant fourni (test/STATS CARD.txt). Ni React, ni Tailwind,
   ni `clsx` : les quatorze barres portent leurs deux états en variables, et
   la feuille interpole. Les coordonnées sont celles du composant, dans sa
   scène de 356 x 180 ramenée en pourcentages — ce qui la rend indépendante de
   la taille de la carte, que le composant, lui, figeait à 356 px.

   GARDÉ : les barres qui changent de hauteur et de couleur, le grandissement
   d'un demi, la grille masquée en ellipse, la lueur radiale, les deux
   pastilles qui s'effacent quand le graphe prend le dessus.
   ÉCARTÉ : le panneau de légende qui remonte du bas au survol — il viendrait
   se poser exactement là où la carte écrit déjà son nom — et le lavis
   dégradé du bas, que le voile de la carte fait déjà.

   LES DEUX PASTILLES NE SONT PAS INVENTÉES : ce sont les chiffres que la page
   des fonctionnalités affiche déjà pour le mois d'exemple (38 % de
   remplissage, 100 290 MAD encaissés). Un graphe décoratif peut être abstrait,
   un chiffre écrit ne le peut pas. */
.carte--graphe{
  background:linear-gradient(158deg, #3A2B3F 0%, #2B2333 58%, #221B29 100%);
}
/* Le graphe ROGNE, et il le peut : c'est une feuille, sans enfant en trois
   dimensions. La carte, elle, ne rogne jamais (§ ci-dessus). */
.graphe{position:absolute;inset:0;border-radius:inherit;overflow:hidden}

.graphe__lueur{
  position:absolute;left:50%;top:31%;width:106%;height:76%;
  transform:translate(-50%,-50%);
  background:radial-gradient(ellipse at center,
    rgba(246,201,164,.26) 0%, rgba(246,201,164,.13) 34%, transparent 72%);
}
.graphe__grille{
  position:absolute;inset:0;opacity:.7;
  background-image:
    linear-gradient(to right, rgba(255,245,242,.12) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255,245,242,.12) 1px, transparent 1px);
  background-size:20px 20px;background-position:center;
  -webkit-mask-image:radial-gradient(ellipse 52% 52% at 50% 34%, #000 60%, transparent 100%);
          mask-image:radial-gradient(ellipse 52% 52% at 50% 34%, #000 60%, transparent 100%);
}

/* Les barres occupent les 62 % du haut : le bas de la carte est au lettrage. */
.graphe__barres{
  position:absolute;left:0;right:0;top:0;height:62%;
  transition:transform .5s cubic-bezier(.6,.6,0,1);
}
.carte--graphe:hover .graphe__barres{transform:scale(1.5)}
.graphe__barres i{
  position:absolute;
  left:calc(var(--x) * 100% / 356);
  width:calc(15 * 100% / 356);
  top:calc(var(--y) * 100% / 180);
  height:calc(var(--h) * 100% / 180);
  border-radius:2px;
  background:rgba(255,245,242,.17);
  transition:top .5s cubic-bezier(.6,.6,0,1),
             height .5s cubic-bezier(.6,.6,0,1),
             background-color .5s ease;
}
/* `.graphe__barres i` vaut (0,1,1) ; une classe seule vaut (0,1,0) et perdait :
   les sept barres pleines sortaient de la MÊME encre translucide que les sept
   autres — mesuré, une seule couleur sur les quatorze. Passer par le parent
   n'est pas un pansement ici, c'est la seule façon de battre un sélecteur qui
   porte un type. */
.graphe__barres .graphe__pleine{background:var(--apricot)}
.carte--graphe:hover .graphe__barres i{
  top:calc(var(--yh) * 100% / 180);
  height:calc(var(--hh) * 100% / 180);
  background:var(--lilac);
}
/* Déclarée APRÈS la règle de survol, et de spécificité supérieure : les barres
   pleines gardent l'abricot dans les deux états, comme dans le composant. */
.carte--graphe:hover .graphe__barres .graphe__pleine{background:var(--apricot)}

.graphe__pastilles{
  position:absolute;left:14px;top:14px;
  display:flex;gap:6px;flex-wrap:wrap;
  transition:opacity .3s ease;
}
.carte--graphe:hover .graphe__pastilles{opacity:0}
.graphe__pastille{
  display:inline-flex;align-items:center;gap:.45em;
  padding:.3em .62em;border-radius:999px;
  font-size:10.5px;line-height:1.3;color:#FFF5F2;white-space:nowrap;
  background:rgba(34,27,41,.42);
  box-shadow:inset 0 0 0 .5px rgba(255,245,242,.24);
  backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);
}
.graphe__pastille::before{
  content:'';width:6px;height:6px;flex:none;
  border-radius:50%;background:var(--apricot);
}
.graphe__pastille--deux::before{background:var(--lilac)}

.cartes__suite{margin:clamp(28px,3vw,44px) 0 0}

@media (max-width:900px){.cartes{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:600px){
  .cartes{grid-template-columns:minmax(0,1fr)}
  .carte{height:clamp(240px,58vw,300px)}
  /* Une carte plus haute que les huit autres, et c est voulu : en colonne
     unique, des hauteurs differentes ne se voient pas — et le schema a besoin
     de la place que le texte lui laisse. A 240 px, il ne restait que 78 px. */
  .carte--schema{height:clamp(320px,84vw,360px)}
}

/* Sans mouvement demandé : les cartes sont posées, rien n'entre, rien ne
   s'incline. Le script n'attache alors aucun écouteur — `--rx` et `--ry`
   restent à zéro — et la classe d'entrée n'est jamais posée. */
@media (prefers-reduced-motion:reduce){
  .carte,.carte__fond,.carte__dire,.carte__aller,
  .graphe__barres,.graphe__barres i,.graphe__pastilles{transition:none}
  .carte--graphe:hover .graphe__barres{transform:none}
}

/* En-tête d'un groupe : son nom en filet de tête, puis le mot du client en
   titre. Les groupes portaient leur rang (01 … 09) pour qu'on retrouve la
   copy ; il est retiré parce que la page les REGROUPE par traitement — des
   numéros qui ne se suivent pas sont pires que pas de numéro du tout. */
.fonction__rang{
  display:flex;align-items:baseline;gap:.6em;flex-wrap:wrap;
  margin:0 0 .4em;
  /* Une capitale écartée de .13 em à 14,4 px et en demi-gras se lit de loin
     comme un filigrane. Elle passe en gras et gagne 6 % : c est le nom du
     domaine, il doit s annoncer. La ligne ne bouge pas de place pour autant. */
  font-size:calc(var(--fs-small) * 1.06);font-weight:600;
  letter-spacing:.13em;text-transform:uppercase;
  /* ENCRE DOUCE, ET NON DISCRÈTE (2026-09-14). Sur les bandeaux teintés,
     `--muted` EST déjà `--ink-soft` — elle n'y tient pas autrement. Le rang ne
     restait donc pâle que sur le sable : 5,28 contre 11,79 deux lignes plus bas,
     pour le nom du domaine. Il se comporte maintenant pareil partout. */
  color:var(--ink-soft);
}
.fonction__cri{
  margin:0 0 1.2em;max-width:24ch;
  font-size:calc(var(--fs-body) * 1.42);
  font-weight:600;line-height:1.2;letter-spacing:-.02em;color:var(--ink);
}

/* Les capacités. Une ligne chacune, séparées par un filet d'un demi-pixel,
   AUCUNE PUCE. La liste reste une <ul> : « pas de puces » vise le glyphe. */
.capacites{list-style:none;margin:0;padding:0}
/* LE CORPS DE LA PAGE DES FONCTIONNALITÉS, C EST CETTE LIGNE-LÀ. Cinquante-deux
   capacités : ce qu on lit de cette page, ce sont elles. À `--fs-body` nu elles
   faisaient 16,56 px à 1 440, la taille d un paragraphe courant — or ce ne sont
   pas des paragraphes, ce sont les affirmations du produit. 8 % de plus
   (17,9 px) et un interligne un peu plus ouvert : elles pèsent ce qu elles
   disent, sans qu une seule colonne ni une seule grille ne bouge.
   Le coefficient est sur `--fs-body`, pas un nombre en dur : la page garde
   UNE échelle typographique, et celle-ci en est un rang, pas une exception. */
.capacites > li{
  padding:.8em 0;
  border-top:.5px solid var(--line);
  font-size:calc(var(--fs-body) * 1.08);line-height:1.5;color:var(--ink-soft);
}
.capacites b{font-weight:600;color:var(--ink)}
.capacites--bientot{color:var(--muted)}

/* Grille de deux cartes. Une seule colonne dès que 380 px ne tiennent plus. */
/* UNE SEULE FONCTIONNALITÉ PAR RANGÉE (décision du propriétaire, 2026-09-09 :
   « c'est trop chargé sur la partie features, on n'affiche qu'une seule feature
   sur un écran, plus de bloc fonctionnalité côte à côte »).

   La grille était en `repeat(auto-fit,minmax(min(100%,380px),1fr))` : deux à
   trois fonctionnalités par rangée sur un écran d'ordinateur. Elle devient une
   colonne unique. On garde `display:grid` plutôt que de revenir à un simple
   empilement : le `gap` reste la seule source d'espacement entre les blocs, et
   il n'y a donc pas de marges à réaccorder.

   Chaque bloc respire davantage — l'écart vertical passe de 32-72 px à
   56-112 px — et le texte reste borné à une largeur de lecture confortable,
   sans quoi une ligne de capacité traverserait les 1 120 px de la lisière. */
.grille-fonctions{
  list-style:none;margin:0 0 clamp(56px,6vw,104px);padding:0;
  display:grid;grid-template-columns:minmax(0,1fr);
  gap:clamp(56px,7vw,112px);
}
.fonction{min-width:0}

/* L'ÉCRAN PASSE À CÔTÉ DU TEXTE, ET RÉTRÉCIT (annotation du 2026-09-09, page 4 :
   « rétrécir et à côté du texte »). Il était posé entre le titre et les
   capacités, sur toute la largeur : il coupait le bloc en deux et prenait plus
   de place que le propos.
   Le `:has()` est la condition, pas une coquetterie : deux groupes n'ont aucun
   écran — on ne montre pas ce qui n'existe pas encore — et la grille à deux
   colonnes leur laisserait une colonne vide. Ils restent en bloc simple. */
/* LA COLONNE DE L IMAGE S ÉLARGIT, ET L IMAGE S Y CENTRE (2026-09-14).
   Annotation du propriétaire, un grand rond rouge sous chaque capture :
   « de petites cartes qui n utilisent pas l espace, par leur taille ou leur
   centrage ». Mesuré à 1 440 px sur le tableau de bord : la colonne de texte
   faisait 459 px de haut, la capture 155 — trois cents pixels de vide sous
   elle, et rien au-dessus.

   Deux gestes, pas un. La colonne passe de .72 à .86 (411 → 475 px) : la
   capture est plus grande. Et elle se CENTRE au lieu de se caler en haut : le
   vide restant, qui est inévitable quand une carte large et courte voisine une
   liste haute, se répartit au-dessus et en dessous au lieu de tomber d un
   seul côté. Un blanc partagé se lit comme de l air ; un blanc d un seul côté
   se lit comme un trou. */
.fonction:has(.fonction__ecran){
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,.86fr);
  gap:clamp(26px,3.2vw,58px);
  align-items:start;
}
.fonction:has(.fonction__ecran) > .fonction__rang{grid-column:1;grid-row:1}
.fonction:has(.fonction__ecran) > .fonction__cri{grid-column:1;grid-row:2}
.fonction:has(.fonction__ecran) > .capacites{grid-column:1;grid-row:3}
/* L écran occupe la seconde colonne sur toute la hauteur du dire. Il se calait
   en HAUT — « aligné sur le titre, il se lit comme sa réponse » —, ce qui était
   juste tant que les deux faisaient la même hauteur. Ils ne la font jamais :
   le vide tombait donc toujours sous l image. Il se centre depuis le
   2026-09-14. */
.fonction:has(.fonction__ecran) > .fonction__ecran{
  grid-column:2;grid-row:1 / span 3;align-self:center;margin:0;
}

/* Sous 760 px il n'y a plus de place pour deux colonnes : l'écran repasse
   dessous, après le texte — et non plus au milieu. */
@media (max-width:760px){
  .fonction:has(.fonction__ecran){grid-template-columns:minmax(0,1fr)}
  .fonction:has(.fonction__ecran) > .fonction__ecran{
    grid-column:1;grid-row:4;margin-top:.4em;
  }
}

/* DEUX VISUELS DANS LA MÊME COLONNE : la personne et la preuve.
   La photo dit qui se sert de l'outil, la capture dit ce qu'elle y voit.
   Empilées et non côte à côte : la colonne fait environ 380 px sur un écran
   d'ordinateur, et deux visuels de 180 px rendraient la liste des rôles comme
   la facture parfaitement illisibles. */
.visuels{display:grid;gap:clamp(16px,1.8vw,28px);align-content:start}
.visuels > figure{margin:0;min-width:0}
.fonction:has(.visuels){
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,.72fr);
  gap:clamp(26px,3.2vw,58px);
  align-items:start;
}
.fonction:has(.visuels) > .fonction__rang{grid-column:1;grid-row:1}
.fonction:has(.visuels) > .fonction__cri{grid-column:1;grid-row:2}
.fonction:has(.visuels) > .capacites{grid-column:1;grid-row:3}
.fonction:has(.visuels) > .visuels{grid-column:2;grid-row:1 / span 3}
@media (max-width:760px){
  .fonction:has(.visuels){grid-template-columns:minmax(0,1fr)}
  .fonction:has(.visuels) > .visuels{grid-column:1;grid-row:4;margin-top:.4em}
}

/* Une photo n'est pas une capture : elle se cadre, là où une capture se montre
   entière. Le rapport 4:3 évite qu'un carré de 900 px ne prenne toute la
   hauteur de la colonne à lui seul. */
/* Le dire garde une largeur de lecture. */
.fonction > p,
.fonction > h3,
.fonction > .capacites{max-width:68ch}
/* Le recadrage est ce qui fait la vignette : sans hauteur, `appareil--coupe`
   affichait la capture ENTIÈRE (2 290 px de haut ramenés à 700). La hauteur
   venait autrefois de `.paire .preuve--tel`, disparu avec les paires. */
.fonction__ecran{margin:0 0 1.5em;max-width:250px}

/* `.fonction__ecran` est plafonné à 250 px, la largeur d'une capture de
   téléphone. Le groupe « Ménages » n'a pas d'écran et porte la photo à sa
   place : sans remise à plat elle héritait du plafond et tombait à 190 px sur
   téléphone — une vignette, pas une image.
   ⚠️ Le sélecteur est DOUBLÉ, et il doit le rester. Ce n'était pas un pansement
   contre l'ordre des déclarations : une surcharge mobile repose ce plafond à
   190 px, bien plus bas dans la feuille. Déplacer ce bloc ne suffit donc pas —
   seule la spécificité (0,2,0 contre 0,1,0) tient. Vérifié en mesurant : sans
   le doublement, la photo du ménage retombe à 190 px sur téléphone. */
.fonction__photo{margin:0}
.fonction__ecran.fonction__photo{max-width:none}
.fonction__photo img{
  display:block;width:100%;height:auto;
  aspect-ratio:4 / 3;object-fit:cover;
}

.fonction__ecran .appareil{height:clamp(240px,24vw,320px)}
/* Une carte du tableau de bord est LARGE et COURTE : elle prend toute la
   largeur de la carte de la grille. Dans les 250 px prévus pour un téléphone
   elle tombait à 0,2 de sa taille — illisible, le même piège que le planning.
   Ni châssis ni recadrage : ce sont déjà des fragments d'interface. */
.fonction__ecran--large{max-width:none}
/* Un fragment en HAUTEUR ne prend pas toute la largeur : la liste des rôles
   fait 382 px de large en réalité ; étirée à 531 elle était AGRANDIE de 39 %,
   donc floue. À 380 elle est à 1:1. Une capture ne se dilate jamais. */
.fonction__ecran--haut{max-width:380px}
.fonction__ecran--large img{
  display:block;width:100%;height:auto;
  box-shadow:0 0 0 .5px var(--line);
}

/* Temps fort : le dire à gauche, le voir à droite, un filet qui l'ouvre. */
.fort{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.15fr);
  gap:clamp(32px,4vw,72px);align-items:start;
  margin:0 0 clamp(56px,6vw,104px);
  padding-top:clamp(40px,4vw,72px);
  border-top:.5px solid var(--line);
}
/* `min-width:0` sur les deux colonnes, sans quoi elles refusent de descendre
   sous leur contenu minimum : le châssis de bureau contient une capture de
   2 400 px, sa largeur minimale valait 1 100 px, et à 390 px la page
   débordait de 730 px (mesuré). Le `min-width:0` vivait autrefois sur
   `.paire .preuve--bureau`, disparu avec les paires. */
.fort > *{min-width:0}
.fort--sans-ecran{grid-template-columns:minmax(0,1fr)}
.fort--sans-ecran .fort__dire{max-width:62ch}
/* Temps fort à écran LARGE : le dire au-dessus, le voir en bande pleine
   largeur. Réservé aux objets qui sont eux-mêmes larges — un planning fait
   2,57 pour 1. Un écran sous un texte se lit mal quand il est haut ; un
   panorama, non : il se lit comme une frise. */
.fort--large{grid-template-columns:minmax(0,1fr)}
/* ⚠️ LA BORNE DE 64 ch NE S APPLIQUE PLUS QU AU PROPOS, PAS À LA LISTE
   (2026-09-14). Sur un bloc pleine largeur, elle laissait 400 px de sable nu à
   droite des capacités — mesuré : 626 px de texte dans 1 028 px de lisière,
   exactement le vide que le propriétaire a entouré sur sa capture du planning.

   Le rang et le cri GARDENT une borne, et plus serrée encore : une ligne de
   titre qui court sur 1 028 px ne se lit plus. C est la LISTE qui s étale, et
   elle s étale en colonnes — c est pour cela que l élargir ne rallonge pas les
   lignes. */
.fort--large .fort__dire{max-width:none;margin-bottom:clamp(24px,2.6vw,40px)}
/* La borne serrée ne vaut que là où le bloc est large : au téléphone, une
   colonne unique fait déjà moins de 30 ch, et la borne y rétrécirait le titre
   pour rien. */
@media (min-width:901px){
  .fort--large > .fort__dire > .fonction__rang,
  .fort--large > .fort__dire > .fonction__cri{max-width:30ch}
}
.fort--large .capacites{columns:2;column-gap:clamp(28px,4vw,64px)}
/* Trois colonnes quand la liste occupe toute la lisière : à deux, chaque
   colonne montait à 485 px, soit près de 75 caractères par ligne — au-delà de
   ce qu un œil suit sans se perdre en revenant à la ligne. Le duo du
   restaurant est exclu : sa liste vit dans une demi-colonne, trois colonnes y
   feraient 180 px de large. */
@media (min-width:1100px){
  .fort--large > .fort__dire:not(.fort__dire--duo) .capacites{columns:3}
}
.fort--large .capacites > li{break-inside:avoid}

/* LE TEXTE ET UNE ILLUSTRATION, COTE A COTE — regle donnee le 2026-09-14 :
   « toujours essayer de mettre du contenu texte avec une illustration cote a
   cote ». Le groupe du restaurant portait quatre visuels ; il n'en porte plus
   que trois, et le premier est contre son texte au lieu de defiler seul.

   ⚠️ CE BLOC DOIT RESTER ICI, SOUS `.fort--large .fort__dire`. Les deux
   sélecteurs pèsent le même poids (0,2,0) : à poids égal, c'est le dernier
   déclaré qui gagne. Posé plus haut dans la feuille, il perdait — mesuré :
   `max-width` calculée à 626 px au lieu de `none`, le texte à 322 px et la
   photo à 263 px dans une lisière de 1 070.

   ⚠️ `max-width:none` : `.fort--large .fort__dire` borne le texte a 64 ch, ce
   qui est juste quand il occupe toute la largeur. Ici il n'occupe qu'une
   colonne — la borne s'applique alors a la colonne DU TEXTE, et la photo se
   retrouvait poussee a 200 px du bord. */
@media (min-width:901px){
  .fort--large .fort__dire--duo{
    display:grid;grid-template-columns:minmax(0,1.1fr) minmax(0,.9fr);
    gap:clamp(28px,3.4vw,58px);align-items:start;
    max-width:none;
  }
}
.fort__ambiance{margin:0}
.fort__ambiance img{display:block;width:100%;height:auto;aspect-ratio:4 / 3;object-fit:cover}
/* Une facture n'est pas un écran : ni châssis, ni barre, ni coins d'appareil.
   Une feuille, posée à plat, avec le filet qui la borne. */
/* La facture est RÉDUITE (annotation du 2026-09-09, page 17 : « réduire »). Elle
   prenait toute sa colonne et écrasait le propos du groupe. Bornée à 420 px et
   calée à gauche de sa colonne : on y lit encore les mentions légales en tête et
   le récapitulatif de TVA en pied, ce qu'elle est là pour montrer, sans qu'elle
   devienne le sujet de la section. */
/* LA FACTURE, POSÉE SUR LE BUREAU (2026-09-14) — « diminuer la taille de la
   facture et la décentrer ». Elle occupait toute la largeur sous la photo,
   comme une seconde image ; elle est maintenant DANS la scène.

   À 44 % de la largeur, décalée en bas à droite : le comptable est à gauche
   du cadre, et les papiers de son bureau sont précisément à cet endroit — la
   facture s'y ajoute au lieu de recouvrir quelqu'un. L'ombre portée la
   décolle du bureau ; le filet d'un demi-pixel qu'elle portait déjà reste,
   c'est lui qui la tient contre un fond clair.

   ⚠️ Sa BOÎTE est carrée alors que la facture ne l'est pas : la photo du
   comptable est en 1:1 et la scène en 3:4, donc `object-fit:cover` recadre.
   C'est la photo qui est recadrée, jamais la facture — elle garde ses
   proportions, sinon les mentions légales se déformeraient. */
.feuille{
  display:block;width:100%;height:auto;
  box-shadow:0 .6vw 2.2vw -1vw rgba(43,35,51,.38), 0 0 0 .5px var(--line);
}
.fort__voir{margin:0}

/* Les deux scènes du restaurant : le châssis posé sur la photo de LA PERSONNE
   QUI S'EN SERT. La photo est le décor, l'écran est la preuve — c'est le
   couplage qui démontre, pas l'écran seul (plan média, 2026-09-07). */
.fort__scenes{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(14px,1.6vw,26px);
}
.scene-ecran{margin:0}
/* Le repère de position est la PHOTO, pas la figure : `bottom` calculé sur la
   figure inclut la légende, et le châssis dépassait de 21 px sous l'image. */
.scene-ecran__vue{position:relative}
.scene-ecran__fond{
  display:block;width:100%;height:auto;
  /* 3:4 et non 4:5 : à 4:5, le châssis dépassait de 17 px par le haut de la
     photo (mesuré). La scène doit respirer autour de l'écran — c'est le
     couplage photo + écran qui démontre, pas l'écran seul. */
  aspect-ratio:3 / 4;object-fit:cover;
}
/* Sélecteur doublé À DESSEIN : `.appareil{position:relative}` est déclarée
   PLUS BAS dans la feuille, et à spécificité égale c'est la dernière qui
   gagne. Le châssis restait dans le flux et poussait la légende 340 px plus
   bas — la figure faisait 723 px au lieu de 383 (mesuré). Même piège que le
   rayon du bouton de la clôture. */
/* Les largeurs sont celles du CHÂSSIS, pas de l'écran. Le châssis déborde de
   l'écran de 21 % en largeur : à 40 %, la capture serait rendue plus petite
   qu'avant les vrais châssis. Ces valeurs gardent la capture à sa taille de
   lecture précédente. */
/* DÉCENTRÉ (2026-09-14) — « il faut décentrer le mobile et la tablette de la
   photo afin qu'on voie les deux éléments ». Le châssis était centré et posé
   au milieu du bas : il couvrait précisément ce que la photo montre. Chacun
   s'écarte donc du côté où la personne n'est PAS :
     — le serveur est à gauche du cadre, il verse le thé : le téléphone part
       à DROITE ;
     — la cuisinière est à droite, penchée sur le tajine : la tablette part à
       GAUCHE, et rétrécit — à 92 % de large, la décentrer ne servait à rien,
       elle couvrait la photo d'un bord à l'autre.

   ⚠️ `transform` n'est plus utilisée pour centrer. Elle est réservée à la
   COURSE : un élément ne peut porter qu'une transformation, et c'est elle qui
   fait la parallaxe. Le placement passe donc par `left` / `right`. */
.scene-ecran__vue .scene-ecran__appareil{
  position:absolute;right:3%;bottom:8%;left:auto;
  width:46%;
}
/* La tablette est couchée : elle prend la largeur, pas la hauteur. */
.scene-ecran--tablette .scene-ecran__appareil{width:66%;bottom:14%;left:3%;right:auto}
/* LES DEUX CHÂSSIS SORTENT DE LEUR PHOTO (2026-09-14) — « décentre encore
   plus, fais-les sortir à moitié de la photo ». Ils débordent maintenant de la
   moitié de leur largeur, chacun du côté où la personne n'est pas.

   ⚠️ LA PHOTO RÉTRÉCIT À 72 % DE SA COLONNE, ET C'EST CE QUI REND LE DÉBORDEMENT
   POSSIBLE. Sans cela, un châssis qui sort de la photo sort aussi de la lisière,
   puis de la fenêtre : à 1 200 px, le téléphone dépassait de 69 px et ouvrait une
   barre de défilement horizontale — le défaut que ce chantier vérifie à chaque
   livraison. Les 28 % laissés libres sont exactement la place où il déborde.

   La photo du serveur se cale à GAUCHE (le téléphone sort à droite), celle de la
   cuisinière à DROITE (la tablette sort à gauche). */
.fort--resto .scene-ecran__vue{width:72%}
.fort--resto .scene-ecran--tablette .scene-ecran__vue{margin-left:auto}
.fort--resto .scene-ecran__vue .scene-ecran__appareil{right:-23%}
.fort--resto .scene-ecran--tablette .scene-ecran__appareil{left:-33%;right:auto}

/* SUR ORDINATEUR, L'UNE AU-DESSUS DE L'AUTRE — « agrandis les deux contenus et
   mets-les l'un au-dessus de l'autre plutôt qu'à côté ». Côte à côte dans la
   colonne de droite, chaque scène faisait 264 px : deux vignettes. Empilées,
   elles prennent toute la colonne. La photo passe de 264 à 403 px de large,
   l'écran qu'elle porte suit. */
@media (min-width:901px){
  .fort--resto .fort__scenes{
    grid-template-columns:minmax(0,1fr);
    gap:clamp(28px,3vw,52px);
  }

  /* PLUS GRANDS ENCORE, « pour qu on voie les ecrans » (2026-09-14). Le bloc est
     passe pleine largeur — la photo double, de 394 a 770 px — et les chassis
     prennent une plus grosse part d elle : le telephone de 46 a 60 %, la tablette
     de 66 a 74 %.

     Ce qu on y gagne, en echelle de l application : la prise de commande passe de
     0,34 a 0,90 de sa taille reelle, l ecran de cuisine de 0,18 a 0,42.

     ⚠️ LA BORNE N EST PAS ESTHETIQUE, ELLE EST GEOMETRIQUE. Le chassis sort de la
     moitie de sa largeur ; ce debordement doit tenir dans ce que la photo laisse
     libre dans la lisiere. La tablette est le cas serre : a 901 px, elle deborde
     de 216 px pour 227 px disponibles. Au-dela de 74 %, elle sort de la lisiere et
     ouvre une barre de defilement horizontale.

     Les deux souhaits se disputent la meme place : « sortir a moitie » et « plus
     grand » consomment tous les deux la marge horizontale. C est elle qui decide.

     Sous 901 px, rien ne change : le proprietaire a valide le telephone tel quel. */
  .fort--resto .scene-ecran__vue .scene-ecran__appareil{width:60%}
  .fort--resto .scene-ecran--tablette .scene-ecran__appareil{width:74%}

  /* ⚠️ ET ELLES TIENNENT DANS UN ÉCRAN (2026-09-14) — « sur ordinateur les
     combos serveur plus téléphone sont très grands, ils n entrent même pas
     dans l écran et créent beaucoup de défilement ». Mesuré à 1 440 × 900 :
     chaque scène faisait 1 075 px de haut, le groupe entier 2 787.

     La photo est bornée par la HAUTEUR de la fenêtre, pas par une valeur en
     dur : elle est en 3/4, donc une largeur de 58 vh lui donne 77 vh de haut
     et la scène entre dans l écran quel que soit celui-ci. Le plancher de
     360 px protège les fenêtres courtes — un portable en 768 de haut ne doit
     pas se retrouver avec une vignette.

     ⚠️ TOUT LE RESTE DE LA COMPOSITION EST EN POURCENTAGE DE CETTE LARGEUR :
     la part du châssis, son débordement, sa hauteur au-dessus du bas. Borner
     la photo réduit donc la scène ENTIÈRE, proportions intactes — et les
     écrans rétrécissent avec elle. C est le prix demandé : « plus grand » et
     « que ça tienne dans l écran » tirent sur la même corde, et cette fois
     c est la seconde qui gagne. */
  .fort--resto{--scene-photo:min(72%, max(360px, 58vh))}
  /* ⚠️ `100 %`, PAS `var(--scene-photo)`. C'est la PISTE de la grille qui
     porte la mesure ; la photo n'a plus qu'à la remplir. Répéter
     l'expression ici la casse : le `72 %` s'y résoudrait contre la piste
     elle-même — 72 % de 522 = 376 px, mesuré — et non contre la scène. Une
     même expression, deux blocs conteneurs, deux valeurs. */
  .fort--resto .scene-ecran__vue{width:100%}

  /* LA PHOTO DE LA CUISINIÈRE N A PAS BESOIN D ÊTRE EN PORTRAIT. Le 3/4 a été
     choisi pour le TÉLÉPHONE, qui est debout. La tablette est couchée : dans
     un cadre en 3/4, elle laissait 480 px de photo vide au-dessus d elle
     (mesuré) — près d un demi-écran de défilement pour ne rien montrer. Le
     carré la cadre de près sans rien couper de ce que la scène raconte. */
  .fort--resto .scene-ecran--tablette .scene-ecran__fond{aspect-ratio:1 / 1}

  /* --- LE TEXTE ENTRE DANS LA PLACE LIBÉRÉE (2026-09-14) ----------------
     Borner la hauteur des scènes a rendu de la largeur : la photo ne fait
     plus 806 px mais 522, et il restait 598 px de sable nu à côté de chacune.
     Le propriétaire les a entourés — « il y a de nouveaux espaces pour mettre
     du texte » — et a dicté quelles phrases y vont. Elles ne sont pas
     nouvelles : elles ont quitté la liste du groupe, qui passe de sept lignes
     à trois.

     La scène devient une rangée de deux colonnes. Le côté change d'une scène
     à l'autre parce que l'appareil change de côté : le téléphone sort à
     DROITE de la photo du serveur, la tablette sort à GAUCHE de celle de la
     cuisinière. Le texte se met toujours en face, jamais derrière.

     ⚠️ LE RETRAIT N'EST PAS UNE MARGE CHOISIE, C'EST LE DÉBORDEMENT DU
     CHÂSSIS. Il sort de la photo de 23 % de sa largeur pour le téléphone, de
     33 % pour la tablette — ce sont les valeurs de `right` et `left` posées
     plus haut. Le texte commence après, plus un écart de lecture. Écrire un
     nombre en dur ici, c'est un chevauchement le jour où l'une des deux
     valeurs bouge. */
  .fort--resto .scene-ecran{
    display:grid;align-items:center;
    grid-template-columns:var(--scene-photo) minmax(0,1fr);
  }
  .fort--resto .scene-ecran--tablette{
    grid-template-columns:minmax(0,1fr) var(--scene-photo);
  }
  /* La photo était poussée à droite par une marge automatique ; c'est la
     grille qui la place maintenant. */
  .fort--resto .scene-ecran--tablette .scene-ecran__vue{margin-left:0}

  /* ⚠️ LE RETRAIT EST UN ÉCART DE GRILLE, PAS UN REMBOURRAGE DU TEXTE. Les
     deux auraient l'air équivalents ; ils ne le sont pas. Un pourcentage de
     `column-gap` se résout contre la largeur de la GRILLE — exactement la
     même base que le `72 %` de la piste — alors qu'un pourcentage de
     `padding` se résout contre la piste du texte, qui est une autre largeur.
     Écrit en rembourrage, le dégagement valait 99 px là où le châssis en
     déborde 120. */
  .fort--resto .scene-ecran{
    column-gap:calc(.23 * var(--scene-photo) + clamp(24px,2.6vw,48px));
  }
  .fort--resto .scene-ecran--tablette{
    column-gap:calc(.33 * var(--scene-photo) + clamp(24px,2.6vw,48px));
  }
  .fort--resto .scene-ecran__dire--gauche{grid-column:1;grid-row:1}
  .fort--resto .scene-ecran__vue{grid-column:1;grid-row:1}
  .fort--resto .scene-ecran--tablette .scene-ecran__vue{grid-column:2;grid-row:1}
}

/* Le texte d'une scène, des deux côtés de la bascule : au téléphone il n'y a
   pas de place à côté, il se pose donc SOUS sa photo — et il y est bien, la
   phrase suit l'image qu'elle décrit. */
.scene-ecran__dire{margin:0}
.scene-ecran__dire .capacites > li:first-child{padding-top:0;border-top:0}
/* ⚠️ UNE SEULE COLONNE. `.fort--large .capacites{columns:2}` mettait les deux
   phrases d'une scene COTE A COTE — le groupe du restaurant est un
   `.fort--large`, la regle les attrapait au passage. Deux lignes juxtaposees
   dans une colonne de 440 px se lisent comme un tableau, pas comme deux
   affirmations. Selecteur a trois classes, et non deux : a poids egal,
   `.fort--large .capacites` gagnerait, elle est declaree plus haut. */
.fort--resto .scene-ecran__dire .capacites{columns:1}
@media (max-width:900px){
  .scene-ecran__dire{margin-top:clamp(14px,2.4vw,22px)}
}

/* La facture est un document posé à plat, pas un appareil : plus petite que
   les châssis, calée dans le coin où les papiers du bureau sont déjà.
   ⚠️ Cette ligne vit APRÈS la base, et c'est tout ce qui la fait tenir : la
   base porte `.scene-ecran__vue .scene-ecran__appareil` (0,2,0), exactement la
   même spécificité. Déclarée avant, elle était battue et la facture sortait à
   46 % au lieu de 44 (mesuré). Énième fois sur ce projet. */
.scene-ecran--feuille .scene-ecran__appareil{width:44%;right:4%;bottom:6%;left:auto}
/* ET LE CADRE DEVIENT CARRÉ SUR ORDINATEUR (2026-09-14). Même mesure que pour
   la tablette : la facture est petite et posée en bas, il restait 343 px de
   photo vide au-dessus d elle, pendant que le texte s arrêtait 400 px avant le
   bas de la colonne. C est le vide que le propriétaire a entouré. En carré, la
   photo tombe de 692 à 519 px et les deux colonnes finissent presque
   ensemble. */
@media (min-width:901px){
  .scene-ecran--feuille .scene-ecran__fond{aspect-ratio:1 / 1}
}

/* LA COURSE. La photo ne bouge pas, le châssis monte — l'objet le plus proche
   de l'œil est celui qui se déplace le plus, c'est ce qui fabrique la
   profondeur. `--glisse` va de -1 quand la scène entre par le bas à +1 quand
   elle sort par le haut ; le signe négatif fait donc MONTER le châssis à
   mesure qu'on descend.

   La course est bornée par la place disponible sous le châssis : il est posé
   à 8 % du bas, et une course plus grande le ferait sortir de la photo — rien
   ne rogne ici, et un téléphone coupé net par le bas d'une image ressemble à
   un défaut, pas à un cadrage.

   Sans script, `--glisse` vaut 0 : le châssis est à sa place, immobile. */
[data-parallaxe] .scene-ecran__appareil{
  --course:clamp(8px, 1.6vw, 22px);
  transform:translateY(calc(var(--glisse, 0) * var(--course) * -1));
  will-change:transform;
}

/* Les deux langues, superposées dans le même châssis. La seconde est posée
   par-dessus la première et c'est son opacité qui bascule : les deux images
   ont exactement le même cadre, donc rien ne saute au changement. */
/* Les deux vues occupent LA MÊME CELLULE — celle de l'ouverture du châssis,
   placée plus bas dans la feuille. Et non l'une par-dessus l'autre en absolu :
   posée en absolu, l'image arabe héritait du `width:100%` de `.appareil img`,
   qui annule les décalages horizontaux — elle sortait à 109 × 237 contre
   96 × 209 pour la française, et le croisement aurait sauté (mesuré). */
.langue-vue{transition:opacity .7s cubic-bezier(.4,0,.2,1)}
[data-langue-vue="fr"] .langue-vue--ar{opacity:0}
[data-langue-vue="ar"] .langue-vue--fr{opacity:0}

/* Les deux libellés, sous la scène. Ils disent quelle langue est montrée et
   permettent de la figer — c'est le contrôle que la capture arabe montre à
   l'écran, rendu à la page. */
.bascule-langue{display:flex;gap:.4em;margin-bottom:.55em}
.bascule-langue__btn{
  font:inherit;font-size:calc(var(--fs-small) * .96);
  letter-spacing:.06em;
  /* 29 px mesurés : la cible s'étend à 44 sans que le libellé grossisse. */
  display:inline-flex;align-items:center;min-height:44px;
  padding:0 .8em;
  color:var(--muted);background:transparent;
  border:0;border-radius:.5em;cursor:pointer;
  box-shadow:inset 0 0 0 .5px var(--line);
  transition:color .2s,box-shadow .2s;
}
.bascule-langue__btn[aria-pressed="true"]{
  color:var(--ink);box-shadow:inset 0 0 0 .5px var(--coral-d);
}
.bascule-langue__btn:focus-visible{outline:2px solid var(--coral-d);outline-offset:2px}

/* La respiration d'avant les tarifs : la seule image de la page qui
   n'illustre rien.

   ⚠️ ELLE A BESOIN D'UNE MARGE EN HAUT, ET D'ELLE SEULE. « Elle sépare deux
   sections qui ont déjà les leurs » était vrai tant que la section du dessus
   était sur du sable : son rembourrage bas faisait le blanc. Celle du dessus
   est un BANDEAU TEINTÉ — son rembourrage est DANS la couleur, donc invisible
   comme séparation. Mesuré : 0 px entre le lilas et la photo, 101 px entre la
   photo et le titre des tarifs. « Ça manque d'harmonie » (2026-09-14).
   En bas, rien à ajouter : les tarifs apportent déjà leurs 101 px. */
.sec--respiration{padding-block:clamp(56px,7vw,101px) 0}
.respiration{margin:0}
.respiration img{
  display:block;width:100%;height:auto;
  aspect-ratio:16 / 9;object-fit:cover;
}

/* Deux photos d'ambiance côte à côte, à plat comme toutes les autres. */
.bande-large{
  list-style:none;margin:0 0 clamp(56px,6vw,104px);padding:0;
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(14px,1.7vw,26px);
}
.bande-large img{
  display:block;width:100%;height:auto;
  aspect-ratio:16 / 9;object-fit:cover;
}

/* La grille « à venir ». Aucun écran : on ne montre pas ce qui n'existe pas
   encore, et on n'invente jamais une interface. L'encre recule d'un cran. */
.fonction--avenir .fonction__cri{color:var(--ink-soft)}
/* ⚠️ LES CAPACITÉS DES GROUPES À VENIR NE SONT PLUS PÂLIES (2026-09-14). Elles
   étaient en `--muted` — 5,28 sur le sable, la lecture la plus faible de la
   page, et pour un groupe entier. Ce qui dit qu il est à venir, ce n est pas
   leur couleur : c est le mot « Bientôt » écrit dans le rang, et le cri qui
   reste en encre douce juste au-dessus. Deux signes écrits valent mieux qu un
   troisième qui ne tient qu à une nuance — c est la règle du projet. */

@media (max-width:900px){
  .fort,.fort__scenes,.bande-large{grid-template-columns:minmax(0,1fr)}
  .fort{gap:26px;padding-top:32px;margin-bottom:44px}
  .grille-fonctions{gap:38px;margin-bottom:44px}
  .bande-large{gap:18px;margin-bottom:44px}

  /* Les vignettes de TÉLÉPHONE rétrécissent ; les fragments larges, non — ils
     prennent la largeur disponible, sinon ils redeviennent illisibles. */
  .fonction__ecran{max-width:190px}
  .fonction__ecran--large{max-width:none}
  .fonction__ecran--haut{max-width:100%}

  /* Deux colonnes de 165 px pour des phrases entières : non. */
  .fort--large .capacites{columns:auto}

  /* LE PLANNING NE SE RÉDUIT PAS À 350 px. Un mois sur huit chambres y ferait
     136 px de haut — la capture réduite au quart, encore. Il garde sa taille
     de lecture et c'est la boîte qui défile, comme le veut la règle du projet
     pour les contenus larges (CLAUDE.md §6). */
  .fort--large .appareil__vue{overflow-x:auto;-webkit-overflow-scrolling:touch}
  /* Elle visait `img` — ce qui attrapait aussi la fiche de réservation posée
     par-dessus, et lui imposait 1 120 px de large. Elle vise l'enveloppe :
     l'image du planning la remplit (`.appareil img{width:100%}`), et la fiche
     garde la largeur de SA boîte. */
  .fort--large .appareil__vue .ouvre{width:1120px;max-width:none}
}

/* --- La bande d'ambiances (2026-09-07) ------------------------------------
   Trois établissements, côte à côte, en réponse à la phrase qui les énumère.
   Photos À PLAT : aucune ombre, aucun arrondi, aucun cadre — la règle du
   monde visuel vaut pour les photographies comme pour les captures. Le seul
   ornement est le filet d'un demi-pixel qui sépare l'image de son libellé.

   En portrait, trois colonnes donneraient des tuiles de 110 px : la bande
   passe à UNE colonne, et les images se recadrent en paysage. Trois portraits
   empilés feraient défiler un écran et demi pour trois photos. */
.ambiances{
  list-style:none;margin:3.2em 0 0;padding:0;
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(14px,1.7vw,26px);
  max-width:var(--maxw);
}
.ambiances figure{margin:0}
.ambiances img{
  display:block;width:100%;height:auto;
  aspect-ratio:4 / 5;object-fit:cover;
}
@media (max-width:700px){
  /* ELLES RESTENT SUR UNE LIGNE (2026-09-14). Empilees, les trois faisaient
     plus de 1 200 px a faire defiler pour trois images qui ne portent aucune
     information — « beaucoup de scroll pour l'utilisateur sans informations ».
     En triptyque elles tiennent en 140 px de haut et disent la meme chose :
     c'est une bande d'ambiance, pas un dossier photo. */
  .ambiances{gap:8px;margin-top:2.2em}
}

.ancrage{
  margin:0;max-width:26ch;
  font-size:calc(var(--fs-body) * 1.34);
  line-height:1.45;letter-spacing:-.014em;
  color:var(--ink);
}

/* --- 3. Les paires plainte / réponse ------------------------------------- */

/* --- Les châssis d'appareil ---------------------------------------------
   Plan média §4 : « Capturé • châssis SVG ». Méthode, règles permanentes :
   « écrans sur TROIS supports : téléphone, ordinateur ET tablette ». Le
   contrat de direction disait l'inverse (« captures à plat, jamais
   encadrées ») — il ne bat pas un document validé par le propriétaire.

   Le châssis n'est pas un ornement, c'est ce qui BORNE l'écran. Une capture
   de téléphone fait 2290 px de haut, le texte à côté en fait 250 : sans
   cadre pour la couper, la page ouvrait un trou de 478 px (mesuré à 1440 px).
   Dessiné au filet d'un demi-pixel, sans ombre, sans reflet, sans
   perspective. L'arrondi est celui de l'objet réel — la règle du monde
   interdit les CARTES arrondies, pas les téléphones. */
.appareil{position:relative;background:var(--panel);overflow:hidden}
.appareil img{display:block;width:100%;height:auto}

/* Le téléphone et la tablette ne sont plus dessinés au filet : ce sont les
   châssis déposés par le propriétaire le 2026-09-09, dont l'ouverture d'écran
   est TRANSPARENTE (mesurée au canal alpha, cf. assets/masters/chassis/).

   D'où la mécanique, et elle est le point important : la capture est posée
   DERRIÈRE, dans une cellule de grille placée exactement à l'ouverture, et
   c'est le châssis lui-même qui la découpe — arrondis compris. Aucun rayon
   n'est approximé ici. Les deux tentatives précédentes d'incrustation avaient
   échoué là : un arrondi approché déborde d'un côté et reste carré de l'autre.

   Les pourcentages ci-dessous sont l'ouverture mesurée, rapportée au châssis.
   Ne pas les arrondir : ils portent la découpe. */
.appareil--tel,
.appareil--tablette{
  display:grid;
  background:none;border-radius:0;padding:0;box-shadow:none;
}
.appareil--tel::after,
.appareil--tablette::after{
  content:"";grid-area:1 / 1 / -1 / -1;z-index:2;pointer-events:none;
  background:center / 100% 100% no-repeat;
}
/* Le châssis est décoratif : il est en fond, jamais en <img>. Rien à annoncer
   à un lecteur d'écran, l'alt de la capture dit déjà ce qui est montré. */
.appareil--tel{
  aspect-ratio:1502 / 2948;
  grid-template-columns:8.655% 82.690% 1fr;
  grid-template-rows:4.410% 91.181% 1fr;
}
.appareil--tel::after{background-image:url(assets/chassis/iphone.webp)}
/* La tablette est en PAYSAGE parce que l'écran de cuisine l'est : une capture
   portrait dans un châssis de tablette serait un mensonge d'objet. */
.appareil--tablette{
  aspect-ratio:3132 / 2448;
  grid-template-columns:6.386% 87.229% 1fr;
  grid-template-rows:8.170% 83.660% 1fr;
}
.appareil--tablette::after{background-image:url(assets/chassis/ipad-paysage.webp)}
/* Toutes les captures d'un même châssis occupent LA MÊME cellule — celle de
   l'ouverture. C'est ce qui fait tenir le fondu croisé français/arabe : posées
   en absolu, les deux images héritaient du `width:100%` de `.appareil img`,
   qui annule les décalages, et sortaient à des tailles différentes.

   ⚠️ Le combinateur est DESCENDANT et non enfant depuis le 2026-09-13 :
   une capture peut être enveloppée dans un `<picture>` (le planning du
   téléphone l'est, pour ne pas télécharger celle de l'autre format), et
   `> img` ne l'atteignait plus. `display:contents` règle la mise en page,
   pas la parenté en DOM — les sélecteurs, eux, lisent le DOM. */
.appareil--tel img,
.appareil--tablette img{
  grid-area:2 / 2;width:100%;height:100%;
  object-fit:cover;border-radius:0;
}

/* Coupé net par le bas : l'écran continue hors du cadre, ce qui est vrai —
   il défile. Trois filets au lieu de quatre, pas d'arrondi bas. */
.appareil--coupe{
  border-radius:1.5rem 1.5rem 0 0;padding-bottom:0;
  box-shadow:
    inset .5px 0 0 0 var(--ink),
    inset -.5px 0 0 0 var(--ink),
    inset 0 .5px 0 0 var(--ink);
}
.appareil--coupe img{border-radius:1.15rem 1.15rem 0 0}

/* Ordinateur : la fenêtre entière. Trois pastilles au filet, jamais en
   couleur — la couleur est réservée au couchant. */
.appareil--bureau{
  border-radius:.55rem;
  box-shadow:inset 0 0 0 .5px var(--ink);
}
.appareil__barre{
  display:flex;align-items:center;gap:.42rem;
  height:1.75rem;padding-inline:.75rem;
  border-bottom:.5px solid var(--line);
}
.appareil__barre span{
  width:.45rem;height:.45rem;border-radius:50%;
  box-shadow:inset 0 0 0 .5px var(--muted);
}
/* La boîte défilante n'a plus d'emploi : la capture du planning est calibrée
   pour tenir exactement dans la bande, à 1:1. Gardée pour un éventuel écran
   plus large que son cadre. */
.appareil__vue{overflow:auto}
.appareil__vue:focus-visible{outline:2px solid var(--coral-d);outline-offset:-2px}

/* ==========================================================================
   ANIMATION 3.A (2026-09-13) — LA RÉSERVATION QUI S'OUVRE.

   Le pointeur se pose sur la barre de M. Sefrioui, clique, et la fiche de
   cette réservation s'ouvre par-dessus le planning, dans la même fenêtre.
   Elle fait 1 988 px de haut pour une bande de 436 : elle défile donc dans
   une boîte qui la rogne — c'est ce que fait l'application, pas un effet.

   UNE SEULE CHORÉGRAPHIE, DEUX RÉGLAGES (2026-09-14). La même suite d'images
   sert l'ordinateur et le téléphone : les `@keyframes` ne portent plus aucun
   nombre, elles lisent des variables que chaque contexte pose. Corriger le
   geste à un endroit le corrige aux deux.

   LA COURSE NE SE CALCULE PLUS À LA MAIN. Elle vaut
   `calc(-100% + hauteur de la boîte)` : `-100%` est la hauteur PROPRE de la
   fiche, quelle qu'elle soit. Le rapport de la capture n'entre donc plus dans
   le calcul — si elle est reprise plus haute ou plus courte, l'animation finit
   toujours EXACTEMENT sur son bas. C'est la version d'avant qui portait
   « -141,37 cqw », un nombre juste une seule fois.

   Ce qui reste à savoir :
     — ordinateur : bande de 38,93 cqw de haut (872 / 2240), boîte de 50 cqw de
       large (560 px à pleine taille, la fiche à 0,875 de sa taille dans
       l'application — le même facteur que le planning derrière elle, 0,88, qui
       a été jugé lisible), 1,4 cqw de marge en haut et en bas ;
     — téléphone : la fiche est à FOND PERDU, parce qu'un téléphone n'ouvre pas
       une carte au milieu de l'écran, il ouvre une page. Le conteneur est en
       `container-type:size` : la hauteur de la boîte s'écrit alors `100cqh`,
       c'est-à-dire elle-même, et aucun rapport n'est à recopier.

   LES BARRES VISÉES, mesurées sur les images servies. Si un planning est refait,
   ces nombres bougent :
     — ordinateur : 33,82 % / 30,16 % ;
     — téléphone  : 39,94 % / 55,97 %.
   ========================================================================== */
/* `overflow:hidden` : le pointeur ENTRE dans le cadre, il part donc de
   dehors — 96 % de la hauteur, soit 5,8 px sous le bord. Sans rognage, ces
   5,8 px faisaient apparaitre une barre de defilement verticale dans le
   chassis (mesure : scrollHeight 386 pour clientHeight 381). */
.ouvre{
  position:relative;display:block;overflow:hidden;container-type:inline-size;
  /* Le réglage « ordinateur », qui est aussi le réglage par défaut. */
  --ouvre-x:33.82%;   --ouvre-y:30.16%;       /* la barre visée */
  --ouvre-dx:44.18cqw; --ouvre-dy:25.63cqw;   /* d'où vient le pointeur */
  --ouvre-boite-h:36.13cqw;                   /* la hauteur de la boîte */
}

/* Tout ce qui bouge est PAUSÉ tant que la figure n'a pas été vue : une
   animation qui a déjà fait deux tours avant qu'on arrive n'est jamais vue
   qu'au milieu d'un geste. Et elle est déclarée ici, pas ajoutée par script :
   sans JavaScript, elle reste au premier temps — le planning seul, intact. */
.ouvre__voile,
.ouvre__boite,
.ouvre__halo,
.ouvre__pointeur,
.ouvre__fiche{
  animation-duration:var(--ouvre-t,15s);
  animation-timing-function:linear;
  animation-iteration-count:infinite;
  animation-play-state:paused;
}
.ouvre--joue .ouvre__voile,
.ouvre--joue .ouvre__boite,
.ouvre--joue .ouvre__halo,
.ouvre--joue .ouvre__pointeur,
.ouvre--joue .ouvre__fiche{animation-play-state:running}

.ouvre__voile{
  position:absolute;inset:0;pointer-events:none;
  background:rgba(43,35,51,.42);opacity:0;
  animation-name:ouvre-voile;
}

.ouvre__boite{
  position:absolute;left:25%;width:50%;
  top:1.4cqw;height:var(--ouvre-boite-h);
  overflow:hidden;border-radius:.5rem;
  background:var(--panel);
  box-shadow:0 1.2cqw 3cqw -1.4cqw rgba(43,35,51,.45), inset 0 0 0 .5px rgba(43,35,51,.28);
  opacity:0;transform:translateY(1.2cqw) scale(.972);
  animation-name:ouvre-boite;
}
/* `<picture>` ne sert qu'à CHOISIR la source ; il ne doit rien peser dans la
   mise en page. Sans `display:contents`, il s'interpose entre le châssis et sa
   capture : la grille du téléphone place `> img`, elle ne place pas un
   `<picture>`, et la capture tombait en vignette SOUS le châssis resté vide.
   La règle vaut pour tous les appareils, pas seulement pour la fiche. */
.appareil picture{display:contents}
/* ⚠️ Le sélecteur passe par `.ouvre` — (0,2,0) — et ce n'est pas décoratif :
   dans le châssis de téléphone, `.appareil--tel img` (0,1,1) imposait à la fiche
   `height:100%;object-fit:cover`. Elle faisait alors exactement la taille de sa
   boîte : plus rien ne dépassait, donc plus rien ne défilait, et la sonde
   « bas sur bas » répondait 0 en même temps que « haut sur haut ». Deux zéros
   qui avaient l'air d'une réussite. C'est la capture recadrée du planning qui
   a besoin de cette règle, pas la fiche qui glisse dessous. */
.ouvre .ouvre__fiche{
  position:absolute;left:0;top:0;width:100%;height:auto;
  animation-name:ouvre-defile;
}

/* Le halo du clic : un cercle qui s'ouvre et s'efface. Il ne dit rien tout
   seul — c'est le pointeur qui appuie qui le dit —, il le rend visible. */
.ouvre__halo{
  position:absolute;left:var(--ouvre-x);top:var(--ouvre-y);
  width:5cqw;height:5cqw;margin:-2.5cqw 0 0 -2.5cqw;
  border-radius:50%;pointer-events:none;
  box-shadow:0 0 0 .28cqw var(--coral-d);
  opacity:0;transform:scale(.2);
  animation-name:ouvre-halo;
}

.ouvre__pointeur{
  position:absolute;left:var(--ouvre-x);top:var(--ouvre-y);
  width:2.15cqw;height:2.15cqw;pointer-events:none;
  /* Le point chaud d'un pointeur, c'est sa POINTE, pas le coin de sa boite.
     Le trace commence a 5/24 et 2,2/24 de la vignette : sans ces deux marges
     negatives, la pointe tombait 10 px a droite et 4 px sous le centre de la
     barre. Elle etait encore dessus — la barre fait 83 x 34 —, mais « encore
     dessus » n'est pas « dessus ». */
  margin:-0.197cqw 0 0 -0.448cqw;
  opacity:0;
  animation-name:ouvre-pointeur;
}
.ouvre__pointeur svg{
  display:block;width:100%;height:100%;
  fill:var(--ink);stroke:#FFFFFF;stroke-width:1.3;stroke-linejoin:round;
  filter:drop-shadow(0 .12cqw .24cqw rgba(43,35,51,.45));
}

/* --- Les cinq temps ------------------------------------------------------
   0 -> 12 %  le pointeur descend sur la barre        (0 - 1,8 s)
   12 -> 15 % il appuie, le halo s'ouvre               (1,8 - 2,25 s)
   13 -> 18 % le voile tombe, la fiche s'ouvre         (1,95 - 2,7 s)
   18 -> 80 % la fiche défile jusqu'au reste à payer   (2,7 - 12 s)
   80 -> 92 % on tient, puis tout se referme           (12 - 13,8 s)
   92 -> 100 % rien, le temps de respirer avant le tour suivant */
@keyframes ouvre-pointeur{
  0%   {opacity:0;transform:translate(var(--ouvre-dx),var(--ouvre-dy)) scale(1)}
  3%   {opacity:1;transform:translate(var(--ouvre-dx),var(--ouvre-dy)) scale(1)}
  12%  {opacity:1;transform:translate(0,0) scale(1)}
  13.5%{opacity:1;transform:translate(0,0) scale(.82)}
  15%  {opacity:1;transform:translate(0,0) scale(1)}
  22%  {opacity:0;transform:translate(0,0) scale(1)}
  99%  {opacity:0;transform:translate(var(--ouvre-dx),var(--ouvre-dy)) scale(1)}
  100% {opacity:0;transform:translate(var(--ouvre-dx),var(--ouvre-dy)) scale(1)}
}
@keyframes ouvre-halo{
  0%,12.9%{opacity:0;transform:scale(.2)}
  13.5%   {opacity:.9;transform:scale(.4)}
  20%     {opacity:0;transform:scale(1)}
  100%    {opacity:0;transform:scale(.2)}
}
@keyframes ouvre-voile{
  0%,13%{opacity:0}
  17%   {opacity:1}
  86%   {opacity:1}
  92%   {opacity:0}
  100%  {opacity:0}
}
@keyframes ouvre-boite{
  0%,13%{opacity:0;transform:translateY(1.2cqw) scale(.972)}
  18%   {opacity:1;transform:translateY(0) scale(1)}
  86%   {opacity:1;transform:translateY(0) scale(1)}
  92%   {opacity:0;transform:translateY(-.8cqw) scale(.985)}
  100%  {opacity:0;transform:translateY(1.2cqw) scale(.972)}
}
@keyframes ouvre-defile{
  0%,18%{transform:translateY(0)}
  80%   {transform:translateY(calc(-100% + var(--ouvre-boite-h)))}
  92%   {transform:translateY(calc(-100% + var(--ouvre-boite-h)))}
  93%   {transform:translateY(0)}          /* remis à zéro pendant qu'on ne la voit plus */
  100%  {transform:translateY(0)}
}

/* --- Où l'animation ne se joue pas ---------------------------------------
   Sous 900 px, le cadre devient une boîte qui défile sur un planning de
   1 120 px : une fiche centrée sur ce canevas tomberait hors de la fenêtre
   presque tout le temps. Le planning reste, seul, comme avant. */
/* --- Le planning du téléphone (2026-09-13) -------------------------------
   Remarque du propriétaire : « sous format mobile, l'affichage d'un écran
   ordinateur n'a pas de raison, on ne voit qu'une partie et l'animation ne se
   voit pas ». Les deux sont vrais : une fenêtre de 1 120 px dans un écran de
   390 n'en montrait qu'un tiers, dans une boîte qu'il fallait pousser du
   doigt, et la fiche, centrée sur ce canevas, tombait hors de la fenêtre.

   Les deux appareils s'excluent donc : la fenêtre d'ordinateur au-dessus de
   900 px, le téléphone en dessous. Chacun porte SA capture — le mois pour
   l'un, la semaine pour l'autre — et un `<picture>` remplace celle qui ne
   sert pas par un pixel transparent, sans quoi les deux seraient téléchargées :
   `display:none` ne l'empêche pas.

   280 px de large : le châssis est calibré en `aspect-ratio`, c'est donc la
   largeur qui commande tout. À 280, la capture de 410 px de large est rendue à
   0,68 — le lettrage de l'application y reste lisible, et le téléphone garde
   la taille à laquelle on le tient dans la main. */
.planning-tel{display:none}

/* --- Le réglage « téléphone » --------------------------------------------
   Le conteneur est la CELLULE DE L'OUVERTURE du châssis : les pourcentages y
   tombent donc directement sur la capture. Et il est en `container-type:size`,
   ce qui donne `100cqh` — sa propre hauteur — pour la hauteur de la boîte,
   sans recopier le moindre rapport.

   La fiche est à FOND PERDU : un téléphone n'ouvre pas une carte au milieu de
   l'écran, il ouvre une page. Ni arrondi, ni ombre, ni marge.

   Et PAS DE FLÈCHE : on ne montre pas un curseur de souris sur un téléphone.
   Le rond du toucher dit le geste à lui seul — il est simplement plus large,
   à la mesure d'un doigt. */
.ouvre--tel{
  grid-area:2 / 2;                  /* la cellule de l'ouverture du châssis */
  container-type:size;
  --ouvre-x:39.94%; --ouvre-y:55.97%;
  --ouvre-boite-h:100cqh;
}
.ouvre--tel .ouvre__halo{width:14cqw;height:14cqw;margin:-7cqw 0 0 -7cqw}
.ouvre--tel .ouvre__boite{
  inset:0;width:auto;height:auto;
  border-radius:0;box-shadow:none;
}

@media (max-width:900px){
  .fort--large .appareil--bureau{display:none}
  .planning-tel{display:grid;width:min(280px,72vw);margin-inline:auto}
}
/* Sans mouvement demandé : le planning seul, lui aussi. Une fiche posée là,
   immobile, cacherait la moitié du planning sans rien expliquer. */
@media (prefers-reduced-motion:reduce){
  .ouvre__voile,.ouvre__boite,.ouvre__halo,.ouvre__pointeur{display:none}
}

/* Les photos « avant », elles, restent à plat : ce ne sont pas des écrans. */

/* --- La colonne de preuve, bornée ---------------------------------------
   Le téléphone sort du flux : la hauteur de la paire est dictée par le
   TEXTE, et l'appareil remplit ce qui reste en étant coupé par la ligne du
   bas. C'est ce qui referme les trois trous de ~480 px. */

/* Le planning bureau : pleine largeur sous le texte de sa paire. C'est la
   preuve massive de « deux clients devant la même porte » — la case rouge
   hachurée y est lisible, ce qu'aucune capture de téléphone ne permet. */
/* La paire du planning n'a pas de troisième colonne : la figure occupe la
   colonne de texte, sous le texte. Sans cela, la colonne « auto » se
   dimensionnait sur les 2400 px intrinsèques de la capture et réduisait la
   colonne de lecture à un mot par ligne. */
/* sélecteur descendant obligatoire : « .paire .preuve » impose déjà une
   colonne 3 et un span de 4 rangées, et gagne sur une classe seule */

/* La clôture : la phrase dit « depuis votre téléphone », l'image le montre. */
/* Le monde d'AVANT est en monochrome ; la couleur revient quand le visiteur
   le survole — rien ne bouge tant qu'il n'agit pas. */

/* --- 4. La plaque : le seul bloc dominant de la page --------------------- */
/* le gras hérite sinon de l encre prune : illisible sur la plaque prune */

/* --- 4b. L'ambiance : peu d'images, mais grandes -------------------------
   Plan média §4b. Cinq photos ont été générées, discutées et retenues le
   2026-09-04, puis oubliées hors de la page ; les voici. Elles s'alignent
   sur la largeur de la plaque, à plat, sans arrondi, sans ombre, sans
   châssis — l'accumulation de vignettes est ce qui fait le « slop », donc
   il y en a peu et elles occupent l'écran. */

/* Deux portraits, puis un paysage : trois cellules de même largeur
   écrasaient les verticales (57 % de leur hauteur perdue) et rognaient
   le geste — le thé versé, le tajine dressé, la table mise. Chaque photo
   reçoit donc un cadre proche de son format natif. */

/* --- 5b. La cour de riad, en fond discret --------------------------------
   Plan média §5b. Elle ne passe pas SOUS le texte : le sable de la page la
   recouvre presque entièrement du côté de la colonne de lecture, et ne la
   laisse respirer qu'à droite, là où il n'y a rien à lire. */

/* --- Les chiffres animés -------------------------------------------------
   Plan média : « jauge de remplissage », « histogramme du CA par chambre »,
   « codé sur les VRAIS chiffres », « remplissage au scroll ». Les valeurs
   sont lues dans la base de démonstration (Riad Zitoune, septembre 2026),
   pas inventées : 92 nuits sur 240, et le détail du CA par chambre. Le plan
   média annonçait 45 % de remplissage — c'était une estimation d'avant la
   lecture ; le vrai chiffre est 38 % et c'est celui qui est affiché.

   Rien n'est porté par la seule couleur : chaque barre écrit sa valeur, et
   la jauge écrit son pourcentage. Le remplissage est un renfort, jamais
   l'information elle-même. */
/* La jauge et l'histogramme vivent maintenant DANS une carte, pas sur la
   pleine largeur d'une paire : ils s'empilent au lieu de se partager la
   largeur. Côte à côte dans 500 px, l'histogramme tombait à 230 px et ses
   huit valeurs se chevauchaient. */
/* LES CHIFFRES DANS UNE CARTE (annotation du 2026-09-09, page 12 : « mettre dans
   card »). Ils flottaient à même le fond, sans rien qui les tienne ensemble ;
   la jauge et l'histogramme se lisaient comme deux blocs sans rapport.
   La surface est donnée par --surface-carte plutôt qu'en dur : sur le prune, un
   panneau nacré serait un trou de lumière. Une encre très diluée éclaircit le
   fond juste assez pour que la carte se détache, sans toucher au contraste du
   texte qu'elle porte (vérifié). */
.chiffres{
  min-width:0;margin:0 0 1.5em;
  display:grid;grid-template-columns:minmax(0,1fr);
  gap:clamp(22px,2.6vw,34px);
  align-items:start;
  background:var(--surface-carte,var(--panel));
  border:.5px solid var(--line);
  border-radius:14px;
  padding:clamp(18px,2.1vw,30px);
}
.chiffres__titre{
  margin:0 0 .5em;font-size:var(--fs-small);font-weight:600;
  text-transform:uppercase;letter-spacing:.13em;color:var(--muted);
}
.chiffres__valeur{
  margin:0 0 .5em;font-size:calc(var(--fs-h2) * .8);
  font-weight:600;color:var(--ink);line-height:1;
}
.chiffres__note{
  margin:.85em 0 0;font-size:var(--fs-small);color:var(--muted);
  font-variant-numeric:tabular-nums;
}

/* La jauge : une piste au filet, une part pleine qui se remplit. */
.jauge{position:relative;height:10px;background:var(--line-doux)}
.jauge__part{
  position:absolute;left:0;top:0;bottom:0;
  width:calc(var(--part) * var(--chiffres,0) * 100%);
  background:var(--coral-d);
}

/* L'histogramme : huit colonnes, chacune avec sa valeur écrite au-dessus. */
.histo{
  margin:0;padding:0;list-style:none;
  display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);
  gap:clamp(6px,.8vw,14px);align-items:end;
  height:clamp(150px,15vw,210px);
}
/* colonne alignée en bas : la valeur reste COLLÉE au sommet de sa barre et
   monte avec elle. En grille à trois rangées, elle flottait en haut du cadre,
   détachée de ce qu'elle mesure. */
.histo li{
  display:flex;flex-direction:column;justify-content:flex-end;
  height:100%;min-width:0;
}
.histo__v{
  font-family:var(--mono);font-size:clamp(9px,.72vw,11px);
  font-variant-numeric:tabular-nums;color:var(--muted);
  text-align:center;padding-bottom:.4em;white-space:nowrap;
}
.histo__b{
  align-self:end;width:100%;
  height:calc(var(--part) * var(--chiffres,0) * 100%);
  background:var(--coral-d);
  /* la barre la plus haute est la seule à l'encre pleine : elle se lit comme
     un maximum, pas comme une catégorie */
}
.histo li:first-child .histo__b{background:var(--ink)}
.histo__l{
  font-family:var(--mono);font-size:clamp(9px,.72vw,11px);
  letter-spacing:.06em;color:var(--ink-soft);
  text-align:center;padding-top:.55em;border-top:.5px solid var(--line);
  margin-top:.4em;
}

/* --- 5c. La démonstration responsive : le cadre qui rétrécit --------------
   Plan média §4. AUCUN TEXTE (décision du 2026-09-09) : la démonstration parle
   seule. Ce qu'on voit est le VRAI tableau de bord de l'application, en HTML
   vivant dans une ombre, qui se recompose sur la largeur du CADRE — d'où la
   requête de conteneur dans assets/tableau-de-bord.css.

   La section est MASQUÉE par défaut et ne se montre qu'une fois la feuille de
   l'application chargée dans l'ombre (data-prete, posé par le script). Sans
   JavaScript elle n'existe donc pas du tout — c'est voulu : le <template> ne
   se rend pas, et mieux vaut une section absente qu'un tableau de bord nu ou
   un trou de la hauteur du cadre.

   Le cadre porte un filet d'un demi-pixel, l'idiome de la page, et rien
   d'autre : ni ombre, ni carte. Il ne peut pas prendre un châssis d'appareil
   comme les scènes du restaurant — un châssis a un rapport d'image fixe, or
   c'est précisément ce rapport qui doit changer ici.
   ========================================================================= */
.sec--demo{display:none;padding-block:clamp(40px,5vw,88px)}
.sec--demo[data-prete]{display:block}

/* LA PISTE — elle porte l'échelle, et occupe la place visuelle.
   Le cadre garde sa vraie largeur de MISE EN PAGE (100cqw ÷ échelle) et n'est
   réduit qu'à la peinture. `transform` ne touchant pas à la mise en page, le
   tableau de bord se recompose sur sa vraie largeur et la requête de conteneur
   voit cette vraie largeur : on montre l'animation en plus petit, jamais une
   image de l'animation.
   `container-type` sert ici d'unité de mesure : 100cqw = la largeur de la
   piste, la seule façon en CSS de déduire la largeur de mise en page du cadre
   de la place réellement disponible. */
.demo-piste{
  --demo-zoom:1;          /* échelle de peinture */
  --demo-etroit:390px;    /* largeur de téléphone, en mise en page */
  --demo-haut:440px;      /* hauteur de mise en page du cadre */
  --demo-course:-560px;   /* de combien le contenu glisse pendant le palier */

  container-type:inline-size;
  height:calc(var(--demo-haut) * var(--demo-zoom));
  display:flex;
  justify-content:center;   /* le cadre, plus large que la piste, déborde
                               également des deux côtés — donc il reste centré
                               quand l'échelle le ramène à la bonne taille */
  overflow:hidden;
}

.demo-cadre{
  /* Plafond à 1 120 px : c'est la largeur de contenu réelle de l'application.
     Sans lui, dans le bas d'une bande d'échelle, la largeur de mise en page
     grimpait à 1 208 px et le tableau de bord passait à QUATRE colonnes — un
     état que personne ne voit en vrai. La démonstration doit montrer ce que
     l'outil fait, pas ce que la formule permet. */
  width:min(calc(100cqw / var(--demo-zoom)), 1120px);
  height:var(--demo-haut);
  flex:none;
  overflow:hidden;
  transform:scale(var(--demo-zoom));
  transform-origin:top center;
  /* Filet et arrondi sont divisés par l'échelle pour retomber sur leur valeur
     réelle une fois la réduction appliquée : sans cela, le filet d'un demi-pixel
     deviendrait un cinquième de pixel sur téléphone, c'est-à-dire rien. */
  border:calc(.5px / var(--demo-zoom)) solid var(--line);
  border-radius:calc(10px / var(--demo-zoom));
}

/* La hauteur ne bouge JAMAIS : seule la largeur est animée. Le contenu, lui,
   passe de 1476 px à 2080 px en rétrécissant — il déborde, et c'est lui qui
   glisse. C'est ce débordement qui dit « rien n'a été retiré ». */
.demo-glisse{will-change:transform}

/* LA CHORÉGRAPHIE — EN BOUCLE LENTE (décision du propriétaire, 2026-09-09, 3ᵉ
   retour : « je veux que ça tourne en boucle lentement »). Elle remplace le
   passage unique décidé le même jour, qui suivait le tempo de
   mobile friendly.mp4 (650 / 2 800 / 650 ms, soit 4 100 ms).

   Une boucle n'est pas un passage unique répété : il lui faut un TEMPS DE REPOS
   en position large, sinon le cadre repart à peine rouvert et le mouvement
   devient un va-et-vient nerveux — l'inverse de « lentement ». D'où un cycle en
   quatre temps, et non trois :

     rétrécissement   1 100 ms   ease-in-out    →  13,10 %
     palier étroit    3 600 ms   le contenu glisse dedans →  55,95 %
     ré-élargissement 1 100 ms   ease-in-out    →  69,05 %
     REPOS large      2 600 ms   rien ne bouge  → 100 %
                      ─────────
                      8 400 ms   (deux fois le tempo d'origine)

   Les pourcentages ci-dessous ne sont rien d'autre que ces durées divisées par
   8 400. Changer la durée sans les recalculer désaccorderait les deux
   animations, qui doivent rester rigoureusement en phase. */
@keyframes demo-cadre{
  0%     {width:min(calc(100cqw / var(--demo-zoom)),1120px); animation-timing-function:ease-in-out}
  13.10% {width:var(--demo-etroit);                          animation-timing-function:linear}
  55.95% {width:var(--demo-etroit);                          animation-timing-function:ease-in-out}
  69.05% {width:min(calc(100cqw / var(--demo-zoom)),1120px)}
  100%   {width:min(calc(100cqw / var(--demo-zoom)),1120px)}   /* le repos */
}

/* Le contenu attend un battement (450 ms) avant de glisser : sans lui, le
   glissement commence pendant que le cadre bouge encore et les deux mouvements
   se brouillent. Il remonte plus vite qu'il n'est descendu (900 ms contre
   1 750) — c'est le geste naturel du retour — et il est revenu à zéro AVANT que
   le cadre ne se rouvre, sinon la ré-ouverture se ferait sur un contenu décalé.

     battement  1 100 → 1 550 ms  → 18,45 %
     descente   1 550 → 3 300 ms  → 39,29 %
     pause      3 300 → 3 800 ms  → 45,24 %
     retour     3 800 → 4 700 ms  → 55,95 %   (puis immobile jusqu'au bout) */
@keyframes demo-glisse{
  0%,18.45%    {transform:translateY(0);                  animation-timing-function:ease-in-out}
  39.29%       {transform:translateY(var(--demo-course)); animation-timing-function:linear}
  45.24%       {transform:translateY(var(--demo-course)); animation-timing-function:ease-in-out}
  55.95%,100%  {transform:translateY(0)}
}

/* La chorégraphie se joue MAINTENANT À TOUTES LES LARGEURS (2026-09-09, 2ᵉ
   retour du propriétaire : « sur mobile impossible de réduire la taille pour que
   ça rentre ? »). Elle ne le pouvait pas tant que le cadre était à l'échelle 1 :
   sur un téléphone il n'y avait pas la place d'un état « ordinateur ». L'échelle
   règle exactement ça, et la démonstration existe désormais partout.

   Les trois paliers ci-dessous fixent l'échelle de façon que la largeur de MISE
   EN PAGE de l'état large reste autour de 1 000 px dans chaque bande — c'est la
   largeur à laquelle le tableau de bord montre plusieurs colonnes. En dessous,
   l'état large tomberait à deux colonnes et la démonstration perdrait son sujet. */
.demo-cadre--joue{animation:demo-cadre 8400ms infinite both}
.demo-cadre--joue .demo-glisse{animation:demo-glisse 8400ms infinite both}

/* Une boucle qui tourne pour personne, c'est de la batterie prise à un visiteur
   qui lit ailleurs. Elle est donc SUSPENDUE dès que la section quitte l'écran,
   et reprend là où elle s'était arrêtée — `animation-play-state`, et non le
   retrait de la classe, qui la ferait repartir du début à chaque passage.
   C'est déjà l'idiome de la page pour le fondu FR/AR des scènes du restaurant. */
.demo-cadre--repos,
.demo-cadre--repos .demo-glisse{animation-play-state:paused}

/* Quatre bandes. Dans chacune, l'échelle est choisie pour que la largeur de MISE
   EN PAGE de l'état large reste proche de 1 000–1 120 px — la largeur à laquelle
   le tableau de bord montre ses trois colonnes. Les hauteurs sont réglées pour
   que le bloc occupe à peu près la même place à l'écran partout (365 à 440 px)
   malgré des échelles très différentes. */
@media (max-width:1179px){
  .demo-piste{--demo-zoom:.82;--demo-haut:500px;--demo-course:-600px}
}
@media (max-width:900px){
  /* .58, mesuré et non deviné. Le titre promet trois supports : l'état large
     doit tenir ses TROIS colonnes jusqu'en bas de la bande (621 px). Le seuil
     n'est pas 3 × 300 + 2 × 16 = 932 px comme on le croirait, mais **964** : la
     vue a 16 px de rembourrage de chaque côté, qui ne comptent pas dans la
     grille. À .62 la mise en page tombait à 938 px — six pixels de trop pour la
     largeur, trente-deux de trop pour la grille — et la troisième colonne
     sautait. Conséquence assumée : en haut de la bande, le plafond de 1 120 px
     rend le cadre un peu plus étroit que la colonne de texte. Il est centré,
     personne ne voit un « trou ». */
  .demo-piste{--demo-zoom:.58;--demo-haut:690px;--demo-course:-640px}
}
@media (max-width:620px){
  .demo-piste{--demo-zoom:.48;--demo-haut:760px;--demo-course:-680px}
}

/* Sans mouvement demandé, le cadre reste à sa pleine largeur et rien ne glisse.
   La page ne perd rien : la vue montre le tableau de bord réel, simplement
   immobile. */
@media (prefers-reduced-motion:reduce){
  .demo-cadre--joue,
  .demo-cadre--joue .demo-glisse{animation:none}
}

/* --- 6. L'encadré accès anticipé ---------------------------------------- */
/* Plan média §6 : « encadré, filigrane de l'arche ». C'est l'arche du logo,
   en très grand et en très pâle, calée sur le bord droit de l'encadré. Elle
   ne passe pas sous le texte : la colonne de lecture s'arrête bien avant. */
.encadre{
  position:relative;overflow:hidden;
  max-width:var(--maxw);margin-inline:auto;
  padding:clamp(28px,3.4vw,56px);
  background:var(--panel);
  box-shadow:0 0 0 .5px var(--line);
}
.encadre::after{
  content:'';position:absolute;pointer-events:none;
  right:-4%;bottom:-22%;
  width:clamp(180px,26%,340px);aspect-ratio:1;
  background-image:url(assets/logo-dyafa.svg);
  background-repeat:no-repeat;background-position:center;background-size:contain;
  color:var(--ink);        /* currentColor du tracé */
  opacity:.06;
}
.conditions li{max-width:64ch}
.conditions{margin:1.4em 0 0;padding:0;list-style:none}
.conditions li{
  font-size:var(--fs-body);line-height:1.6;color:var(--ink-soft);
  padding:.95em 0;border-top:.5px solid var(--line);
}
.conditions li:first-child{border-top:0;padding-top:0}

/* Les boutons posés DANS LE FLUX de la page — celui de l'encadré d'accès
   anticipé, celui qui suit les neuf cartes.
   `width:max-content` : `.btn` est dimensionné en `cqw` pour les appels à
   l'action du héros, ce qui n'a aucun sens ici — sans cette remise à plat il
   prend une largeur héritée d'un tout autre contexte, et le libellé sort du
   filet. C'est ce qui est arrivé à « Voir toutes les fonctionnalités en
   détail » : 10,68 cqw pour un libellé deux fois plus long. */
.encadre__aller{margin:1.6em 0 0}
/* `white-space:normal` : `.btn` interdit le retour a la ligne, ce qui convient
   au heros ou les libelles sont courts. Ici, a 390 px, « Voir toutes les
   fonctionnalites en detail » depassait encore de 4,7 px — le filet coupait le
   dernier mot. Avec `max-content` + `max-width:100%`, le bouton prend la
   largeur de son texte tant qu'il y a la place, et se replie quand il n'y en a
   plus ; la passe telephone lui a deja donne `height:auto` pour grandir. */
.encadre__aller .btn,
.cartes__suite .btn{
  width:max-content;max-width:100%;padding-inline:1.6em;
  white-space:normal;text-align:center;
}

/* --- 7. Les trois étapes, numérotées en colonne de marge ---------------- */
.etapes{margin:0;padding:0;list-style:none;counter-reset:etape;max-width:60ch}
.etapes li{
  counter-increment:etape;
  display:grid;grid-template-columns:3.5rem 1fr;
  font-size:calc(var(--fs-body) * 1.14);color:var(--ink);
  padding:1.05em 0;border-top:.5px solid var(--line);
}
/* LE NUMERO A CEDE LA PLACE AU SIGNE (2026-09-14). La colonne de marge
   portait « 01 », « 02 », « 03 » ; elle porte maintenant un pictogramme. Un
   numero ET un dessin dans 3,5 rem, c etait deux marqueurs pour une seule
   etape — et l ordre est deja dit par les phrases elles-memes.

   Le trait est celui de tous les autres signes de la page : encre douce, 1,7
   d epaisseur, bouts et angles arrondis. Le compteur reste declare sur
   `.etapes` : il ne coute rien, et il reviendra d une ligne si les numeros
   sont reclames. */
.etape__logo{
  width:clamp(26px,2.4vw,34px);height:auto;
  fill:none;stroke:var(--muted);stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round;
  margin-top:.12em;
}

/* --- 8. Les tarifs : trois cartes qui se dilatent ------------------------
   REFAIT le 2026-09-14 sur le composant fourni par le propriétaire
   (test/pricing.txt — React + framer-motion + Tailwind). Les dessins sont
   repris tels quels ; la chorégraphie est retraduite en transitions CSS.

   L ÉLAN QUI DÉPASSE. `backInOut` de framer-motion recule avant de partir et
   dépasse avant de se poser. En courbe de Bézier CSS, ce sont les deux points
   de contrôle hors de l intervalle [0,1] — d où les valeurs négatives et
   supérieures à 1 ci-dessous. Sans elles, le geste devient une glissade.

   LES COULEURS VIENNENT DE LA PALETTE, et d elle seule. Elles sont toutes
   prises à FORCE D ENCRE, pas à la force décorative des jetons : le crème doit
   pouvoir s écrire dessus. Mesuré au pire point de chaque fond :
     ciel profond   #4A5E7F  6,13 : 1
     lilas profond  #5E4E7E  6,83 : 1
     couchant       #8A4F2E  6,05 : 1  (l étape la plus claire des quatre)

   ⚠️ LE DÉGRADÉ DE COUCHANT DE HOSTEL PRO N EST PAS `--grad-couchant`.
   La nappe du monde monte jusqu à l abricot : au pire point, le crème y tombe
   à 3,61 pour 1 — illisible. Ce sont les mêmes teintes, dans le même ordre
   (nuit lilas, prune, corail, ambre), descendues à l encre. La nappe claire
   reste ce qu elle est : décorative, jamais sous une ligne de texte. */
:root{
  --elan:cubic-bezier(.68,-.6,.32,1.6);
  --couchant-encre:linear-gradient(165deg,#4B3A63 0%,#6E4363 36%,#8C4A45 70%,#8A4F2E 100%);
}
.tarifs{
  max-width:var(--maxw);margin:clamp(32px,4vw,56px) auto;
  padding-inline:16px;
  display:flex;flex-wrap:wrap;justify-content:center;
  gap:clamp(14px,1.6vw,22px);
}
.tarif{
  position:relative;overflow:hidden;isolation:isolate;
  width:min(320px,100%);min-height:384px;
  padding:clamp(22px,2.2vw,30px);
  display:flex;flex-direction:column;
  border-radius:16px;
  color:var(--on-ink);
  box-shadow:var(--ombre-douce);
  transition:transform 1s var(--elan), box-shadow .3s ease;
}
.tarif--libre  {background:#4A5E7F}
.tarif--premium{background:#5E4E7E}
.tarif--pro    {background:var(--couchant-encre)}

/* Le fond dessiné. `slice` et non `meet` : la carte n a pas toujours le rapport
   320 / 384 du dessin, et un dessin qui se contente de rentrer laisserait deux
   bandes vides. Il déborde, la carte le rogne. */
.tarif__fond{
  position:absolute;inset:0;z-index:0;
  width:100%;height:100%;pointer-events:none;
  fill:rgba(43,35,51,.22);
  transition:transform 1s var(--elan);
}
/* ⚠️ `transform-box:fill-box`. Sur un élément SVG, l origine des
   transformations CSS est par défaut le coin de l ORIGINE DU REPÈRE, pas le
   centre de la forme : sans cette ligne, le disque ne s aplatit pas sur
   lui-même, il part en diagonale hors du cadre. */
.tarif__fond > *{transform-box:fill-box;transform-origin:center}

/* ⚠️ CHAQUE <p> DE LA CARTE REDIT SON ENCRE. La feuille pose
   `p{color:var(--ink-soft)}` sur l'élément lui-même : une valeur DÉCLARÉE bat
   toujours une valeur héritée, quelle que soit la spécificité. La carte a beau
   être en crème, ses paragraphes redescendaient au prune du corps de page —
   mesuré : rgb(68,58,75) sur un fond bleu nuit. */
.tarif__dire{position:relative;z-index:1;color:var(--on-ink)}
.tarif__nom{
  display:inline-block;margin:0 0 .7em;
  padding:.22em .8em;border-radius:999px;
  color:var(--on-ink);
  background:rgba(255,245,242,.16);
  border:1px solid rgba(255,245,242,.26);
  font-size:var(--fs-small);font-weight:600;
}
/* Le prix est posé à 85 % et reprend sa taille au survol — c est le geste
   central du composant. L origine est en HAUT À GAUCHE : au centre, le bloc
   entier respirerait et pousserait la phrase. */
.tarif__prix{
  margin:0;font-size:clamp(34px,3.6vw,46px);font-weight:700;line-height:1.15;
  color:var(--on-ink);
  transform:scale(.85);transform-origin:top left;
  transition:transform 1s var(--elan);
}
.tarif__prix .chiffre{font-size:1em;font-weight:700}
.tarif__mois{font-size:.44em;font-weight:500}
.tarif__apres{
  margin:.5em 0 1.1em;font-size:var(--fs-small);
  text-transform:uppercase;letter-spacing:.12em;
  color:rgba(255,245,242,.82);
}
.tarif__phrase{margin:0 0 1.2em;font-size:var(--fs-small);line-height:1.5;color:var(--on-ink)}
.tarif__quota{
  margin:0;display:grid;grid-template-columns:1fr auto;gap:.5em 1em;
  font-size:var(--fs-small);
}
.tarif__quota dt{color:rgba(255,245,242,.82)}
.tarif__quota dd{
  margin:0;text-align:right;font-family:var(--mono);
  font-variant-numeric:tabular-nums;font-weight:600;
}
/* `margin-top:auto` colle le bouton au bas de la carte quelle que soit la
   longueur du texte : les trois boutons sont alors sur la même ligne, ce qui
   est la seule façon de comparer trois offres d un coup d œil. */
.tarif__cta{
  position:relative;z-index:1;margin-top:auto;
  display:block;padding:.72em 1em;border-radius:10px;
  background:var(--on-ink);color:var(--ink);
  border:1px solid var(--on-ink);
  font-weight:600;text-align:center;text-decoration:none;
  transition:background-color .2s ease, color .2s ease, border-color .2s ease;
}
.tarif__cta:hover{background:rgba(255,245,242,.12);color:var(--on-ink)}
.tarif__cta:focus-visible{outline:2px solid var(--on-ink);outline-offset:3px}

/* --- Les trois chorégraphies ---------------------------------------------
   Elles ne se jouent QUE là où il y a un pointeur à suivre. Au doigt, il n y a
   pas de survol : la carte resterait dilatée après le geste, comme l était
   l inclinaison des neuf cartes avant qu on la borne de la même façon. */
@media (hover:hover) and (pointer:fine){
  .tarif:hover{transform:scale(1.05);box-shadow:0 30px 60px -30px rgba(43,35,51,.42)}
  .tarif:hover .tarif__prix{transform:scale(1)}

  /* Free — le disque s écrase, l ellipse s étire : le soleil se couche. */
  .tarif--libre:hover .tarif__fond{transform:scale(1.5)}
  .tarif__disque,
  .tarif__ellipse{transition:transform 1s var(--elan) .2s}
  .tarif--libre:hover .tarif__disque {transform:translateY(-25px) scaleY(.5)}
  .tarif--libre:hover .tarif__ellipse{transform:translateY(-25px) scaleY(2.25)}

  /* Hostel Pro — les deux carrés échangent leur place en pivotant. */
  .tarif--pro:hover .tarif__fond{transform:scale(1.05)}
  .tarif__carre{transition:transform 1s var(--elan) .2s}
  .tarif__carre--haut{transform:translateY(12px)}
  .tarif__carre--bas {transform:translateY(219px)}
  .tarif--pro:hover .tarif__carre--haut{transform:translateY(219px) rotate(90deg) scaleX(2)}
  .tarif--pro:hover .tarif__carre--bas {transform:translateY(12px)  rotate(90deg) scaleX(2)}

  /* Premium — les trois écus montent, décalés : l empilement se déploie. */
  .tarif--premium:hover .tarif__fond{transform:scale(1.25)}
  .tarif__ecu--1{transition:transform 1s var(--elan) .1s}
  .tarif__ecu--2{transition:transform 1s var(--elan) .2s}
  .tarif__ecu--3{transition:transform 1s var(--elan) .3s}
  .tarif--premium:hover .tarif__ecu{transform:translateY(-50px)}
}

/* --- AU TÉLÉPHONE, LES TROIS RESTENT CÔTE À CÔTE ------------------------
   « Sur mobile les tarifs sont empilés, ce qui empêche la comparaison ; il
   faudrait qu ils soient juxtaposés » (2026-09-14). Empilées, les trois
   cartes font 1 200 px : on ne compare pas trois prix qu on ne peut pas voir
   ensemble, on les lit l un après l autre et on les oublie.

   Trois cartes lisibles ne tiennent pas dans 390 px — il faudrait 110 px
   chacune. La rangée devient donc une bande qui GLISSE, avec un cran d arrêt
   par carte : le doigt passe de l une à l autre sans quitter la ligne des
   prix, et un bord de la suivante reste toujours visible pour dire qu il y en
   a d autres.

   ⚠️ `overflow-x` sur la bande, jamais sur la page : le débordement est
   contenu ici, la page ne gagne pas de barre horizontale. Et le rembourrage
   vertical n est pas décoratif — sans lui, `overflow-x` rend l axe vertical
   automatique lui aussi, et l ombre douce des cartes se fait rogner. */
@media (max-width:760px){
  .tarifs{
    flex-wrap:nowrap;justify-content:flex-start;
    overflow-x:auto;overscroll-behavior-x:contain;
    scroll-snap-type:x mandatory;scroll-padding-inline:16px;
    padding-block:10px 18px;
    gap:12px;
  }
  .tarif{
    flex:0 0 min(74vw,300px);
    scroll-snap-align:center;
    min-height:0;
  }
}

/* Sans mouvement demandé, il ne reste que le changement d ombre — et le prix
   reprend sa pleine taille, sans quoi il resterait à 85 % pour toujours. */
@media (prefers-reduced-motion:reduce){
  .tarif,.tarif__fond,.tarif__prix,.tarif__fond > *{transition:none}
  .tarif__prix{transform:none}
}

/* les chiffres sont tabulaires partout où la page en montre, pas seulement
   dans les tarifs — sinon la promesse de chasse fixe n est pas tenue */
.mentions,
.conditions li{font-variant-numeric:tabular-nums}
.chiffre{
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-size:calc(var(--fs-h2) * .86);font-weight:600;letter-spacing:-.02em;
}
.mentions{font-size:var(--fs-small);color:var(--muted);max-width:64ch}

/* --- 9. La frise de la feuille de route ----------------------------------
   Plan média §9 : « Frise des chantiers », « progression au scroll ». C'était
   une liste à puces en deux colonnes. La frise dit ce qu'une liste ne dit
   pas : que ces chantiers arrivent DANS L'ORDRE annoncé, l'un après l'autre.
   L'axe se remplit à mesure que la section traverse l'écran — la variable
   `--frise` est posée par le même mécanisme que la lumière. */
/* --- LA FEUILLE DE ROUTE, EN TIMELINE ------------------------------------
   Portage d'un composant React/Tailwind (2026-09-07). Aucune dépendance : le
   geste est du CSS. `framer-motion` servait à faire entrer les jalons en
   cascade — le remplissage de l'axe au défilement, déjà en place, fait mieux :
   c'est le visiteur qui mène. `lucide-react` servait aux glyphes ; ils sont
   remplacés par des repères dessinés au filet, comme le reste de la page.

   DEUX ÉTATS et non trois. Le composant propose « terminé », avec une coche.
   Rien n'est terminé sur une feuille de route — ce serait sa négation. */
.frise{
  position:relative;
  max-width:var(--maxw);margin:clamp(26px,3vw,46px) auto 0;
  padding:0 0 0 2.6rem;list-style:none;
}
/* l'axe, au filet — et par-dessus, la part parcourue au défilement */
.frise::before,.frise::after{
  content:'';position:absolute;left:.42rem;top:1.1em;width:1px;
}
.frise::before{bottom:1.1em;background:var(--line)}
.frise::after{
  height:calc(var(--frise,0) * (100% - 2.2em));
  background:var(--coral-d);
  transition:height .12s linear;
}

.jalon{position:relative;padding:0 0 clamp(28px,3vw,44px)}
.jalon:last-child{padding-bottom:0}
/* Le repère : un anneau creux sur l'axe. */
.jalon::before{
  content:'';position:absolute;left:-2.35rem;top:.95em;
  width:9px;height:9px;border-radius:50%;
  background:var(--bg);box-shadow:inset 0 0 0 1px var(--muted);
}
/* La prochaine étape porte un halo qui bat — le seul de la page, et il ne
   dit rien d'autre que « c'est ici qu'on en est ». */
.jalon--prochain::before{
  background:var(--coral-d);box-shadow:inset 0 0 0 1px var(--coral-d);
}
.jalon--prochain::after{
  content:'';position:absolute;left:-2.35rem;top:.95em;
  width:9px;height:9px;border-radius:50%;
  background:var(--coral-d);
  animation:battement 2.4s cubic-bezier(0,0,.2,1) infinite;
  pointer-events:none;
}
@keyframes battement{
  from{transform:scale(1);opacity:.55}
  to{transform:scale(2.6);opacity:0}
}

.jalon__periode{
  margin:0 0 .5em;
  display:flex;align-items:baseline;gap:.7em;flex-wrap:wrap;
  font-size:var(--fs-small);font-weight:600;
  letter-spacing:.13em;text-transform:uppercase;color:var(--ink);
}
.jalon__etat{
  font-weight:500;letter-spacing:.1em;color:var(--coral-d);
}
.jalon__lignes{list-style:none;margin:0;padding:0}
.jalon__lignes > li{
  padding:.72em 0;
  border-top:.5px solid var(--line);
  font-size:var(--fs-body);line-height:1.45;color:var(--ink-soft);
}

/* Le repli au-delà de huit lignes (plan média). Dépliant natif : pas une
   ligne de script, et le clavier le traverse tout seul. */
.jalon__repli summary{
  list-style:none;cursor:pointer;
  display:flex;align-items:center;gap:.7em;flex-wrap:wrap;
  /* 27 px mesurés au doigt : sous les 44 px de la règle, sur la surface
     principale d'usage. La cible s'étend, le lettrage ne bouge pas. */
  min-height:44px;
}
.jalon__repli summary::-webkit-details-marker{display:none}
.jalon__repli summary .jalon__periode{margin:0}
.jalon__compte{
  font-size:var(--fs-small);letter-spacing:.06em;color:var(--muted);
}
.jalon__compte::after{
  content:' ▾';font-size:.9em;
}
.jalon__repli[open] .jalon__compte::after{content:' ▴'}
.jalon__repli summary:focus-visible{outline:2px solid var(--coral-d);outline-offset:3px}
.jalon__repli .jalon__lignes{margin-top:.6em}


/* --- 10. La FAQ ---------------------------------------------------------- */
.sec--faq details{border-top:.5px solid var(--line);padding:.2em 0}
.sec--faq summary{
  padding:1.05em 2rem 1.05em 0;position:relative;cursor:pointer;
  font-size:calc(var(--fs-body) * 1.06);font-weight:600;color:var(--ink);
  list-style:none;
}
.sec--faq summary::-webkit-details-marker{display:none}
.sec--faq summary::after{
  content:'+';position:absolute;right:0;top:.86em;
  font-weight:400;font-size:1.15em;color:var(--muted);
}
.sec--faq details[open] summary::after{content:'–'}
.sec--faq details p{max-width:64ch;margin:0 0 1.3em;font-size:var(--fs-body)}

/* --- 11. La clôture ------------------------------------------------------ */
/* La lumière arrive au bout de la page. Trois apparitions en tout : le
   voile de l'accroche, le filet de Premium, ce filet-ci. Une lumière qui
   voyage le long de la page, pas une décoration qui se répète. */
.sec--final{position:relative;padding-block:clamp(80px,9vw,152px)}
.sec--final::before{
  content:'';position:absolute;left:0;right:0;top:0;height:2px;
  background:var(--grad-couchant);
}
.sec--final h2{margin-inline:auto;max-width:20ch}
.actions--final{
  position:static;display:flex;gap:.8rem;justify-content:center;flex-wrap:wrap;
  margin-top:2rem;
}
.actions--final .btn,
.actions--etapes .btn{
  width:auto;height:auto;padding:1.05em 1.7em;
  font-size:var(--fs-body);border-radius:.62em;
}

/* Le bloc ci-dessous est posé ICI, et non avec les autres règles de bouton :
   `.actions--final .btn` redéfinit le rayon avec la MÊME spécificité, donc
   c'est la dernière déclarée qui gagne. Placé plus haut, le bouton de la
   clôture gardait ses 10 px d'angle au lieu de la pastille (mesuré). */
/* --- LE BOUTON DE FLUX ----------------------------------------------------
   Portage d'un composant React/Tailwind fourni par le propriétaire. Rien à
   installer : son comportement est entièrement du CSS. React n'apportait que
   le rendu du balisage, Tailwind que des raccourcis de classes, et
   `lucide-react` qu'une flèche de trois lignes de SVG — elle est ici en clair.

   Le geste, INVERSÉ par rapport au composant d'origine (décision du
   propriétaire) : au repos un aplat plein, au survol le disque d'encre qui se
   RETIRE vers son centre et découvre le contour. Le reste est identique — le
   libellé qui glisse vers la droite, une flèche qui entre par la gauche
   pendant que l'autre sort par la droite, l'angle qui passe de la pastille au
   rectangle adouci — et les quatre courbes d'accélération sont celles de
   l'original.

   Pourquoi l'inversion : l'appel à l'action du premier écran est ce qui décide
   du visiteur. En contour au repos il devenait nettement plus discret tant
   qu'on ne le survolait pas, et un survol n'existe pas sur la moitié des
   appareils.

   Deux adaptations, et elles ne sont pas cosmétiques :

   1. Les couleurs #111111 / blanc deviennent l'encre prune et le sable de la
      page. Le filet passe de 1,5 px à 1 px — le monde visuel n'admet que le
      demi-pixel, 1 px est déjà une concession au dessin d'origine.

   2. AU DOIGT, IL N'Y A PAS DE SURVOL. Un bouton qui n'est qu'un contour tant
      qu'on ne le survole pas serait, sur téléphone, un appel à l'action
      définitivement éteint — or le téléphone est l'usage principal. Toute la
      métamorphose est donc sous `@media (hover:hover)`, et sur un écran
      tactile le bouton reste l'aplat prune d'aujourd'hui, avec la seule
      flèche de droite posée. */
.btn.btn--flux{
  position:relative;overflow:hidden;
  background:transparent;color:var(--on-ink);
  box-shadow:inset 0 0 0 1px transparent;
  border-radius:100px;
  transition:color .6s cubic-bezier(.23,1,.32,1),
             box-shadow .6s cubic-bezier(.23,1,.32,1),
             border-radius .6s cubic-bezier(.23,1,.32,1),
             transform .12s ease-out;
}
.btn__texte{
  position:relative;z-index:1;
  transform:translateX(-.75em);
  transition:transform .8s ease-out;
}
/* Le disque part du centre et doit couvrir le bouton entier : 130 % de la
   LARGEUR, jamais une taille en pixels — le bouton du héros, celui de la
   clôture et celui de la colonne n'ont pas la même. */
.btn__cercle{
  position:absolute;top:50%;left:50%;
  width:130%;aspect-ratio:1;
  background:var(--ink);border-radius:50%;
  /* PLEIN au repos : c'est le disque qui fait l'aplat, et c'est lui qui se
     retire au survol. Le disque couvre la diagonale du bouton, donc le
     `overflow:hidden` en fait exactement la pastille. */
  transform:translate(-50%,-50%) scale(1);
  opacity:1;pointer-events:none;
  transition:transform .8s cubic-bezier(.19,1,.22,1),
             opacity .8s cubic-bezier(.19,1,.22,1);
}
.btn__fleche{
  position:absolute;width:1em;height:1em;z-index:9;
  fill:none;stroke:var(--on-ink);stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round;
  transition:left .8s cubic-bezier(.34,1.56,.64,1),
             right .8s cubic-bezier(.34,1.56,.64,1),
             stroke .8s cubic-bezier(.34,1.56,.64,1);
}
.btn__fleche--entre{left:-25%}
.btn__fleche--sort{right:1em}

@media (hover:hover){
  .btn.btn--flux:hover{
    background:transparent;color:var(--ink);
    box-shadow:inset 0 0 0 1px rgba(43,35,51,.4);
    border-radius:12px;
  }
  .btn--flux:hover .btn__texte{transform:translateX(.75em)}
  .btn--flux:hover .btn__cercle{transform:translate(-50%,-50%) scale(.06);opacity:0}
  .btn--flux:hover .btn__fleche{stroke:var(--ink)}
  .btn--flux:hover .btn__fleche--entre{left:1em}
  .btn--flux:hover .btn__fleche--sort{right:-25%}
}
/* Variante sobre : le geste sans les flèches ni le glissement du libellé,
   pour un bouton trop étroit pour les accueillir (la colonne de droite). */
.btn--flux--sobre .btn__texte{transform:none}
@media (hover:hover){
  .btn--flux--sobre:hover .btn__texte{transform:none}
}

.btn.btn--flux:active{transform:scale(.95)}

/* Écran tactile : il n'y a pas de survol, donc rien à découvrir. Le bouton
   garde son aplat — que le disque fait déjà — mais reprend l'angle adouci de
   la page plutôt que la pastille, et la flèche d'entrée n'a plus d'emploi. */
@media (hover:none){
  .btn.btn--flux{
    background:var(--ink);color:var(--on-ink);
    box-shadow:none;border-radius:.62em;
  }
  .btn--flux .btn__texte{transform:none}
  .btn--flux .btn__cercle,
  .btn--flux .btn__fleche--entre{display:none}
  .btn--flux .btn__fleche--sort{stroke:var(--on-ink)}
}

/* --- 11. Le filigrane de l'arche à la clôture (plan média §11) ----------- */
.sec--final{overflow:hidden}
/* L'arche ENTIÈRE, et non la dernière image de la vidéo — celle-ci ne montre
   que le sable et le bas des piliers, ce qui ne donnait rien en filigrane.
   Elle est prise sur l'image de base et posée en grand. */
.sec--final__arche{
  position:absolute;left:50%;top:50%;
  width:auto;height:min(560px,180%);
  transform:translate(-50%,-50%);
  z-index:-1;opacity:.30;
  -webkit-mask-image:radial-gradient(58% 66% at 50% 46%,#000 22%,transparent 76%);
          mask-image:radial-gradient(58% 66% at 50% 46%,#000 22%,transparent 76%);
}

/* --- 12. Le pied --------------------------------------------------------- */
.pied{
  padding:clamp(48px,5vw,80px) clamp(20px,5vw,64px);
  border-top:.5px solid var(--line);
}
/* LE WORDMARK DU PIED EST UNE IMAGE depuis le 2026-09-14.
   Ce qui vivait ici — un jeton de corps propre au pied, une arche en SVG calée
   sur la ligne de base, une interlettre positive et son jumeau obligatoire en
   marge négative, un filet d'or en dégradé, et une signature dont le CORPS
   était recalculé en deux passes au chargement pour rejoindre au pixel la
   largeur du wordmark — tout cela construisait à la main un dessin que le
   propriétaire a maintenant fourni dessiné. Le dessin porte les quatre.

   Rien n'est perdu au passage : ces réglages étaient la description d'une
   image, pas une mise en page. Le seul reste utile est la règle générale
   ci-dessous — c'est une image, elle se borne en largeur et se centre.

   ⚠️ Le pied vit HORS de `main` : `main img` ne l'atteint pas, et le wordmark
   n'hérite donc ni de l'arrondi de 14 px ni de l'ombre douce. C'est voulu —
   une marque posée sur le sable n'est pas une photographie encadrée. */
.pied__marque{
  display:block;width:clamp(190px,19vw,272px);height:auto;
  margin:0 auto 1.5em;
}

/* LE PIED EST CENTRÉ (demande du propriétaire, 2026-09-14). La section de
   clôture juste au-dessus l'était déjà — son titre et son bouton sont posés
   par `.lisiere--centre` — et le pied, lui, restait calé à gauche : la page se
   fermait sur deux axes différents à trois centimètres d'intervalle. */
.pied .lisiere{text-align:center}
.pied__liens{display:flex;flex-wrap:wrap;justify-content:center;gap:.4em 1.6em;margin-bottom:1.2em}
.pied__liens a{
  font-size:var(--fs-small);color:var(--ink-soft);
  border-bottom:.5px solid transparent;transition:border-color .18s;
}
.pied__liens a:hover{border-bottom-color:var(--ink-soft)}
.pied__note{font-size:var(--fs-small);color:var(--muted);margin:0}

/* --- Bornes étroites : la passe responsive complète viendra ensuite ------ */
/* Les cartes des tarifs se replient d elles-mêmes depuis le 2026-09-14 :
   `flex-wrap` et une largeur bornée à 320 px font le travail que faisait la
   bascule de grille qui vivait ici. */

/* ==========================================================================
   MOUVEMENT
   Une seule règle : rien ne bouge tant que le visiteur n'agit pas. Pas de
   révélation au défilement, pas de parallaxe, pas de compteur qui s'anime.
   Le geste signature est la réglette : la maquette la montre dans le premier
   écran, mais un sommaire qui disparaît au premier défilement n'en est pas
   un. Elle devient donc fixe et marque la section courante — c'est un ajout
   assumé au-delà du comp, consigné dans le rapport.
   ========================================================================== */

/* Les règles de base du sommaire doivent précéder les media queries qui le
   masquent : à spécificité égale, c'est la dernière déclarée qui gagne, et le
   sommaire restait visible en portrait. */
/* Le sommaire était en écriture verticale (`writing-mode:vertical-rl`, la
   colonne rotée de 180°). Il se lit à l'horizontale depuis le 2026-09-06 :
   un libellé par ligne, dans le sens normal. Il reste une réglette — c'est la
   position dans la page qu'il donne, pas seulement une liste de liens. */
.reglette{
  display:flex;flex-direction:column;
  align-items:stretch;justify-content:center;
  /* Trois fois l'interligne d'origine (demande du propriétaire) : le blanc
     entre deux libellés passe de 12 à 36 px, rembourrage des cibles compris. */
  gap:2em;
}
.reglette a{
  display:block;
  /* Un libellé fait 17 px de haut : en dessous des 24 px que demande le
     critère de taille de cible, alors que la place ne manque pas. Le
     rembourrage vertical porte la cible à 25 px, et l'écart entre deux
     entrées est réduit d'autant pour que le rythme ne change pas. */
  padding-block:.28em;
  font-size:clamp(12.5px,.92vw,14px);
  font-weight:500;letter-spacing:.01em;color:var(--ink);
  line-height:1.25;
  transition:color .18s cubic-bezier(.2,.6,.3,1);
}
.reglette a:hover{color:var(--coral-d)}

/* La gouttière de droite est partie avec la colonne (2026-09-13) : plus rien
/* En dessous de 1180 px la colonne n'a plus la place : elle disparaît, et
   l'inscription redevient une barre en bas d'écran. */
@media (max-width:1179px){
  .colonne__marque,.reglette{display:none}
  .colonne{
    top:auto;left:0;right:0;bottom:0;width:auto;height:auto;
    padding:10px 16px calc(10px + env(safe-area-inset-bottom));
    background:var(--bg);box-shadow:0 -.5px 0 0 var(--line);
  }
  .cta-ancre{width:100%}
  .cta-ancre .btn{
    width:100%;min-height:52px;font-size:15px;letter-spacing:.06em;
  }
}

/* La section courante : le libellé passe à l'encre pleine et un court filet
   corail le souligne. L'état est porté par DEUX signes, jamais par la seule
   couleur. */
.reglette a{position:relative;padding-left:.62em}
.reglette a[aria-current="true"]{color:var(--ink);font-weight:600}
.reglette a[aria-current="true"]::before{
  content:'';position:absolute;left:0;top:.15em;bottom:.15em;width:2px;
  background:var(--coral-d);
}

/* Le défilement doux est une réponse à un clic, donc une action du visiteur. */
@media (prefers-reduced-motion:no-preference){
  html{scroll-behavior:smooth}
}
:target{scroll-margin-top:2rem}

/* Le focus clavier est visible partout, jamais supprimé. */
a:focus-visible,summary:focus-visible{
  outline:2px solid var(--coral-d);outline-offset:3px;border-radius:2px;
}

/* ==========================================================================
   TÉLÉPHONE ET TABLETTE
   La maquette approuvée est un paysage 2752 × 1536 : appliquée telle quelle à
   375 px, elle écrase le premier écran à 209 px de haut. Le héros passe donc
   en portrait — la vidéo remplit le fond, le texte reprend le flux normal, et
   la composition mesurée du comp ne gouverne plus que le bureau.
   Le mobile est l'usage principal du produit : c'est une passe obligatoire,
   pas une finition (CLAUDE.md §7).
   ========================================================================== */

@media (max-width:900px){

  /* --- Le premier écran, en portrait ------------------------------------ */
  .hero{
    width:100%;margin-inline:0;
    aspect-ratio:auto;
    min-height:100svh;
    /* le plafond du bureau est annulé : en portrait le bloc de texte doit
       pouvoir pousser le cadre, sinon overflow:hidden le tronque */
    max-height:none;
    display:flex;flex-direction:column;justify-content:flex-end;
    padding:0 20px calc(28px + env(safe-area-inset-bottom));
    container-type:normal;          /* les unités cqw ne servent plus */
  }
  /* LA VIDÉO REMONTE DE 12 POINTS (2026-09-14). Sur la capture annotée du
     propriétaire, une flèche part du sommet de l arche et monte : l arche
     était posée trop bas, son pied disparaissait derrière le bloc de texte
     et il ne restait au-dessus d elle qu un grand ciel vide.

     ⚠️ `object-position` N Y POUVAIT RIEN. Dans un cadre PORTRAIT, une vidéo
     en paysage est mise à l échelle par la HAUTEUR : elle remplit le cadre
     exactement de haut en bas, le rognage est entièrement horizontal, et le
     réglage vertical n a aucune marge sur laquelle mordre. C est l ÉLÉMENT
     qu il faut déplacer, pas le cadrage dans l élément : 112 % de haut,
     ancré 12 % plus haut que le cadre. Le bas déborde, le héros le rogne. */
  .arche{
    position:absolute;left:0;right:0;
    top:-12%;bottom:auto;
    width:100%;height:112%;
    object-fit:cover;object-position:center bottom;
  }
  /* ⚠️ LE MASQUE EST RETIRÉ AU TÉLÉPHONE AUSSI (2026-09-14) — « on essaie
     d enlever le masque, voir ce que ça donne ». C était une dissolution vers
     le sable de la page, opaque à 86 % dès 62 % de la hauteur : le texte du
     bas se lisait donc sur du sable, pas sur la vidéo.

     Ce que cela change AUSSI : le bas du héros ne se fond plus dans la page.
     Contrairement à l ordinateur, ce n est pas un défaut — ce qui suit le
     héros au téléphone est le BANDEAU PRUNE des canaux, un aplat sombre
     franc. Une coupe nette entre la vidéo et lui se lit comme une bordure,
     pas comme un raccord raté. */
  .hero::after{display:none}

  /* Le texte reprend le flux : plus de positionnement absolu. */
  .sem{position:static;transform:none}

  .marque{
    position:absolute;top:calc(20px + env(safe-area-inset-top));left:20px;
    font-size:17px;letter-spacing:.14em;gap:.4em;
    transform:none;
  }
  .marque__arche{height:calc(1em * var(--cap) * 24 / 18)}
  /* Le mot-marque est un lien de retour en haut : sa cible tactile passe à
     44 px sans que le lettrage bouge d'un pixel. */
  .marque::after{content:'';position:absolute;inset:-9px -12px}

  .accroche{
    width:auto;max-width:17ch;margin:0 0 18px;
    font-size:clamp(30px,8.4vw,40px);line-height:1.1;letter-spacing:-.022em;
  }
  /* LA ROULETTE TOURNE AU TÉLÉPHONE AUSSI (2026-09-14). Elle y était figée
     sur la copy validée, et pour une raison qui tenait : « location courte
     durée » occupe une ligne à lui seul en portrait, le titre passait de
     quatre à cinq lignes et sa hauteur sautait à chaque mot, entraînant tout
     le bloc du bas.

     LA RAISON TOMBE SI LE MOT TOMBE. C est exactement ce que demande le
     propriétaire — « la roulette auberge, maison d hôtes » : les mots COURTS.
     Le cinquième est donc masqué au téléphone, et il n en reste que quatre,
     dont aucun ne dépasse « maison d hôtes », qui est déjà la copy validée.
     La réserve de largeur ne change donc pas d un pixel, et le titre garde
     ses quatre lignes quel que soit le mot affiché.

     ⚠️ LA CHORÉGRAPHIE CHANGE AVEC LE NOMBRE DE MOTS. `roule` descend
     jusqu à −5 interlignes parce qu il y a six vignettes — cinq mots plus la
     reprise du premier, qui rend la boucle invisible. À cinq vignettes il
     faut −4, sinon la piste finit sur du vide. D où une seconde chorégraphie
     plutôt qu un réglage de la première : deux longueurs, deux animations.

     ⚠️ Et le script qui mesure la réserve de largeur DOIT ignorer les mots
     masqués, sans quoi il réserverait la largeur de « location courte
     durée » — un mot que personne ne verra jamais ici. */
  .roulette__mot:nth-child(5){display:none}
  .roulette__piste{animation-name:roule-court;animation-duration:12s}

  .actions{
    display:flex;flex-direction:column;align-items:stretch;gap:10px;
    margin-bottom:14px;
  }
  .btn{
    width:100%;height:auto;min-height:52px;   /* ≥ 44 px : zone tactile */
    padding:.95em 1.3em;
    font-size:17px;                            /* ≥ 16 px : pas de zoom iOS */
    border-radius:.62em;
  }
  .btn--primaire,.btn--secondaire{width:100%}

  .ligne-acces{width:auto;max-width:38ch;font-size:14.5px;margin:0}

  /* En portrait il n'y a pas de séjour : les mentions sont toutes là. */
  .beta{width:auto;margin-top:18px}
  .beta__etat{font-size:12.5px;margin-bottom:.7em}
  /* elles se replient au lieu de sortir du cadre */

  /* La plaque 2 ne tient pas dans un premier écran en portrait : la preuve
     du produit est donnée plus bas, en grand. */
  .plaque-2{display:none}

  /* --- Le reste de la page ---------------------------------------------- */
  .sec{--pad-sec:20px;padding:56px var(--pad-sec)}

  /* En portrait il n'y a pas de colonne à droite : le téléphone revient dans
     le flux, centré, et reste coupé par le bas — l'écran continue. */
  /* Les chiffres passent en colonne : la jauge d'abord, l'histogramme
     dessous, tous deux pleine largeur. */
  .chiffres{grid-template-columns:1fr;gap:26px}
  .histo{height:clamp(130px,34vw,180px);gap:5px}
  /* Le mois entier ramené à 350 px de large faisait 83 px de haut : illisible.
     Il garde sa taille utile et se parcourt au doigt DANS son cadre, comme
     dans l'application — la page, elle, ne défile pas horizontalement. */
  .appareil--bureau{overflow:hidden}
  .appareil__vue{overflow-x:auto;-webkit-overflow-scrolling:touch}
  .appareil__vue img{width:1100px;max-width:none}

  /* L'ambiance en portrait : les trois photos passent en bandes pleine
     largeur, empilées. Côte à côte, elles tombaient à 156 px de côté —
     c'est-à-dire exactement la vignette décorative que la méthode interdit.
     Aucune photo n'est sacrifiée : le téléphone est l'usage principal, pas
     une version réduite. */

  /* En pleine largeur, le texte occupe tout : le voile de sable redevient
     vertical, sinon la cour passerait sous les lignes. */

  .encadre{padding:26px 20px}


  .etapes li{grid-template-columns:2.2rem 1fr;font-size:17px}
  .frise li{font-size:16px}

  .sec--faq summary{font-size:17px;padding-right:1.6rem}
  .actions--final{flex-direction:column;align-items:stretch}
  .actions--final .btn,
  .actions--etapes .btn{width:100%}

  .pied{padding:40px 20px calc(40px + env(safe-area-inset-bottom))}
  .pied__liens{gap:.2em 1.2em}
  /* Zone tactile réelle : la règle dit ≥ 44 px, les liens du pied en
     faisaient 28. Le filet de survol reste collé au texte grâce au
     display:flex + align-items, la cible s'étend au-dessus et en dessous. */
  .pied__liens a{
    display:inline-flex;align-items:center;
    min-height:44px;
  }
}

/* Écrans tactiles : pas d'état de survol qui reste collé après le tap. */
@media (pointer:coarse){
  .btn--secondaire:hover{background:transparent}
}

/* ==========================================================================
   SURFACES DU NAVIGATEUR
   Une page qui mesure ses filets au demi-pixel ne peut pas laisser la
   sélection, le curseur et le soulignement aux réglages d'usine.
   ========================================================================== */
::selection{background:var(--apricot);color:var(--ink)}
:root{caret-color:var(--coral-d);accent-color:var(--coral-d)}
a{text-underline-offset:.18em;text-decoration-thickness:.5px}
html{scrollbar-color:var(--line-2,#E3CFC8) var(--bg);scrollbar-width:thin}

/* ==========================================================================
   LA PAGE DES FONCTIONNALITÉS — ce qu'elle a en propre.
   Elle n'a pas de héros : la navbar est fixe et flotte sur du sable. Le
   chapeau lui rend donc la hauteur qu'elle occupe, sans quoi le premier titre
   passerait dessous.

   ⚠️ CE BLOC VIT EN FIN DE FEUILLE, ET C'EST TOUT CE QUI LE FAIT TENIR : la
   passe téléphone redéclare `.sec{padding:56px}` plus haut. À spécificité
   égale, la dernière déclarée gagne ; posé avant elle, le rembourrage du
   chapeau était écrasé et le libellé tombait EXACTEMENT sur le bord bas de
   la navbar (dégagement mesuré : 0 px à 390 px de large).
   ========================================================================== */
.sec--chapeau{padding-top:clamp(104px,12vw,168px);padding-bottom:clamp(24px,3vw,48px)}
.sec--chapeau h1{max-width:22ch;margin:0 0 .5em}
.chapeau__dire{max-width:56ch;margin:0;color:var(--ink-soft)}

/* --- Les mentions légales ------------------------------------------------
   Une page de texte, et rien d'autre. Elle suit le chapeau sans respiration
   supplémentaire : les deux ne font qu'un bloc.

   ⚠️ Ce bloc vit ici pour la même raison que celui du chapeau : la passe
   téléphone redéclare `.sec{padding:56px}` plus haut, et à spécificité égale
   c'est la dernière déclarée qui gagne. */
.sec--legal{padding-top:0}
/* `margin-inline:0` : la boite porte AUSSI `.lisiere`, qui centre ce qui est
   plus etroit que 1 120 px. Le texte partait alors 174 px a droite du titre
   qui l'annonce (mesure). Une largeur de lecture se BORNE, elle ne se centre
   pas — le chapeau juste au-dessus fait deja pareil. */
.legal{max-width:74ch;margin-inline:0}
.legal h2{
  margin:2.1em 0 .55em;
  font-size:calc(var(--fs-body) * 1.28);
  font-weight:600;letter-spacing:-.012em;line-height:1.25;color:var(--ink);
}
.legal h2:first-child{margin-top:0}
.legal b{font-weight:600;color:var(--ink)}
/* La feuille pose `a{color:inherit;text-decoration:none}` — juste partout
   ailleurs, faux ici : dans un texte de loi, un lien qui ne se voit pas est
   un lien qui n'existe pas. */
.legal a{color:var(--coral-d);text-decoration:underline}

/* La fiche d'identité : deux colonnes, un filet d'un demi-pixel par ligne,
   comme les capacités des fonctionnalités. Aucune puce. */
.legal__fiche{
  margin:0 0 1.6em;
  display:grid;grid-template-columns:minmax(0,15em) minmax(0,1fr);
}
.legal__fiche dt,
.legal__fiche dd{padding:.75em 0;border-top:.5px solid var(--line)}
.legal__fiche dt{
  font-size:var(--fs-small);font-weight:500;
  letter-spacing:.09em;text-transform:uppercase;color:var(--muted);
}
.legal__fiche dd{margin:0;font-size:var(--fs-body);color:var(--ink)}

/* Ce qui manque se VOIT. Tant qu'il reste un de ces liserés sur la page, elle
   n'est pas publiable — c'est le seul garde-fou possible ici, puisque les
   valeurs manquantes sont des identifiants légaux que personne ne peut deviner. */
.a-completer{
  display:inline-block;
  padding:.16em .5em;border-radius:.4em;
  font-size:.9em;font-style:italic;color:var(--coral-d);
  box-shadow:inset 0 0 0 .5px var(--coral-d);
}

@media (max-width:620px){
  /* Deux colonnes de 15 em ne tiennent pas : l'étiquette passe au-dessus de sa
     valeur, et c'est elle qui porte le filet. */
  .legal__fiche{grid-template-columns:minmax(0,1fr)}
  .legal__fiche dt{padding-bottom:.1em}
  .legal__fiche dd{padding-top:0;border-top:0}
}

/* Une ancre visée sous une barre FIXE arrive sous la barre. `scroll-margin-top`
   est la seule façon de le dire au navigateur ; un décalage en script se
   déclencherait après le saut et se verrait. */
[id]{scroll-margin-top:clamp(72px,9vw,96px)}
