/* ═══════════════════════════════════════════════════════════
   iJackDoit — storefront
   Direction : studio warm off-white, encre, un seul rouge.
   Typographie : Cabinet Grotesk / General Sans / JetBrains Mono,
   servies depuis assets/fonts — aucune requête externe.
   ═══════════════════════════════════════════════════════════ */

@font-face{font-family:'Cabinet Grotesk';src:url('../assets/fonts/cabinet-grotesk-700.woff2') format('woff2');font-weight:700;font-style:normal;font-display:swap}
@font-face{font-family:'Cabinet Grotesk';src:url('../assets/fonts/cabinet-grotesk-800.woff2') format('woff2');font-weight:800;font-style:normal;font-display:swap}
@font-face{font-family:'General Sans';src:url('../assets/fonts/general-sans-400.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'General Sans';src:url('../assets/fonts/general-sans-500.woff2') format('woff2');font-weight:500;font-style:normal;font-display:swap}
@font-face{font-family:'General Sans';src:url('../assets/fonts/general-sans-600.woff2') format('woff2');font-weight:600;font-style:normal;font-display:swap}
@font-face{font-family:'JetBrains Mono';src:url('../assets/fonts/jetbrains-mono-500.woff2') format('woff2');font-weight:500;font-style:normal;font-display:swap}

:root{
  /* Le fond de page reprend la couleur relevée dans le CGI lui-même :
     les bords de la vidéo ne se voient jamais, quel que soit le cadrage. */
  --studio:#F3ECE5;
  --paper:#FBF8F4;
  --ink:#14120E;
  --graphite:#6A6459;
  --line:rgba(20,18,14,.13);
  --red:#D42817;
  --red-deep:#A81C0F;

  --display:'Cabinet Grotesk','Helvetica Neue',Arial,sans-serif;
  --text:'General Sans','Helvetica Neue',Arial,sans-serif;
  --mono:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace;

  --gutter:clamp(20px,4.2vw,72px);
  --radius-cta:999px;
  /* Le hero n'est plus une piste de lecture : cette course sert
     uniquement de zone de bascule puis de palier de repos. */
  --hero-hold:80vh;

  /* Courbe unique pour tout le site (doctrine : easing constant). */
  --ease:cubic-bezier(.22,1,.36,1);
}

*,*::before,*::after{box-sizing:border-box}

html{
  background:var(--studio);
  -webkit-text-size-adjust:100%;
}

body{
  margin:0;
  background:var(--studio);
  color:var(--ink);
  font-family:var(--text);
  font-size:clamp(1rem,1.15vw,1.0625rem);
  line-height:1.55;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}

::selection{background:var(--red);color:#fff}

a{color:inherit}

:focus-visible{
  outline:2px solid var(--red);
  outline-offset:3px;
}

.u-mono{
  font-family:var(--mono);
  font-weight:500;
  font-size:.6875rem;
  letter-spacing:.16em;
  text-transform:uppercase;
}

.u-sr{
  position:absolute;width:1px;height:1px;
  padding:0;margin:-1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;
}

/* ═══ HERO ═════════════════════════════════════════════════
   La section dépasse d'un palier la hauteur de l'écran : ce
   palier sert à déclencher la bascule vers le site, puis à s'y
   reposer. La scène, elle, reste collée à l'écran.            */

.hero{
  position:relative;
  height:calc(100svh + var(--hero-hold));
}

.hero__stage{
  position:sticky;
  top:0;
  height:100svh;
  overflow:hidden;
  background:var(--studio);
}

.hero__media{position:absolute;inset:0}

/* ⚠ Les masters servis portent une bande noire incrustée : 9 px en
   haut, 10 px en bas sur 1440, mesurés au canvas sur
   06-static-hero.webp. La zone utile est donc 2560×1421, rapport
   1,802 et non 1,778 — et en `cover` sur un écran 16:9 la bande se
   voit, puisque la hauteur est affichée en entier.

   L'agrandissement uniforme de 1,5 % sort les deux bandes du cadre
   (0,75 % rogné de chaque côté contre 0,63 % et 0,69 % à couvrir).
   Il est uniforme, donc il ne déforme pas.

   ⛔ Correctif d'affichage, pas correctif de fond : la vraie
   réparation est de recouper les six assets et de repasser le §13.
   Recouper la seule image finale décalerait son raccord avec la
   dernière image de la vidéo — c'est tout ou rien.              */
.hero__media video,
.hero__media img{
  position:absolute;
  inset:0;
  display:block;
  width:100%;
  height:100%;
  object-fit:cover;
  transform:scale(1.015);
  opacity:0;
}

/* Les raccords sont calés à l'image près : une transition ici
   réintroduirait le fondu que le calcul a justement supprimé. */
.hero__media .is-on{opacity:1}

.hero__grain{
  position:absolute;
  inset:0;
  pointer-events:none;
  opacity:.05;
  mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ── Couche typographique ────────────────────────────────── */

.hero__type{
  position:absolute;
  inset:0;
  display:grid;
  grid-template-rows:auto 1fr auto;
  padding:clamp(26px,4.6vh,64px) var(--gutter) clamp(26px,4.6vh,56px);
  pointer-events:none;
}

.hero__type > *{pointer-events:auto}

.title{
  grid-row:1;
  margin:0;
  font-family:var(--display);
  font-weight:800;
  font-size:clamp(3.15rem,14vw,13rem);
  line-height:.84;
  letter-spacing:-.045em;
  max-width:14ch;
}

.title__line{
  display:block;
  overflow:hidden;
  padding-bottom:.04em;
}

.title__line > span{
  display:block;
  /* --t suit la position dans la chute : le titre monte avec la
     tuile, et redescend quand l'animation est jouée à l'envers. */
  transform:translate3d(0,calc((1 - var(--t,0)) * 112%),0);
  will-change:transform;
}

.title em{
  font-style:normal;
  color:var(--red);
}

.hero__foot{
  grid-row:3;
  display:flex;
  flex-direction:column;
  gap:clamp(18px,2.4vh,28px);
  align-items:flex-start;
  opacity:var(--t2,0);
  transform:translate3d(0,calc((1 - var(--t2,0)) * 18px),0);
}

.lead{
  margin:0;
  font-size:clamp(1.02rem,1.4vw,1.3rem);
  line-height:1.45;
  color:var(--graphite);
  max-width:34ch;
  text-wrap:pretty;
}

/* L'étiquette de la tuile : elle désigne l'objet posé au sol,
   elle ne flotte pas au hasard sur la composition.           */
.tilemark{
  position:absolute;
  left:59%;
  top:70%;
  margin:0;
  display:flex;
  align-items:center;
  gap:14px;
  color:var(--graphite);
  opacity:var(--t3,0);
  transform:translate3d(calc((1 - var(--t3,0)) * -14px),0,0);
}

.tilemark::before{
  content:"";
  width:clamp(28px,5vw,72px);
  height:1px;
  background:var(--ink);
  opacity:.35;
  transform:scaleX(var(--t3,0));
  transform-origin:left;
}

.tilemark figcaption{
  font-family:var(--mono);
  font-weight:500;
  font-size:.625rem;
  letter-spacing:.15em;
  text-transform:uppercase;
  max-width:18ch;
  line-height:1.6;
}

/* ── Actions ─────────────────────────────────────────────── */

.actions{
  display:flex;
  flex-wrap:wrap;
  gap:12px;
}

.cta{
  position:relative;
  isolation:isolate;
  display:inline-flex;
  align-items:center;
  gap:16px;
  padding:16px 28px;
  border:1px solid var(--ink);
  border-radius:var(--radius-cta);
  overflow:hidden;
  font-family:var(--text);
  font-weight:600;
  font-size:.9375rem;
  letter-spacing:.005em;
  text-decoration:none;
  color:var(--ink);
  background:transparent;
}

.cta__fill{
  position:absolute;
  inset:0;
  z-index:-1;
  background:var(--red);
  transform:scaleX(0);
  transform-origin:left center;
  transition:transform .32s var(--ease);
}

/* Deux exemplaires du libellé empilés : au survol la pile glisse
   d'exactement une hauteur de ligne, le second prend la place.   */
.cta__label{
  display:block;
  height:1.2em;
  overflow:hidden;
}

.cta__label span{
  display:block;
  height:1.2em;
  line-height:1.2em;
  transition:transform .32s var(--ease);
}

.cta__arrow{
  width:11px;
  height:11px;
  flex:none;
  transition:transform .32s var(--ease);
}

.cta:hover .cta__fill,
.cta:focus-visible .cta__fill{transform:scaleX(1)}
.cta:hover .cta__label span,
.cta:focus-visible .cta__label span{transform:translateY(-1.2em)}
.cta:hover,
.cta:focus-visible{color:#fff;border-color:var(--red)}
.cta:hover .cta__arrow{transform:translate(3px,-3px)}

.cta--ghost{border-color:var(--line)}
.cta--ghost:hover,
.cta--ghost:focus-visible{border-color:var(--red)}
.cta--ghost .cta__arrow{transition:transform .32s var(--ease)}
.cta--ghost:hover .cta__arrow{transform:translateY(3px)}

/* ── Invite à défiler ────────────────────────────────────── */

/* ⚠ Le repere etait le mot « Defiler », centre en bas du plateau, avec un
   filet de 44 px. Il tombait dans la bande qu'occupent les deux capsules.
   Il passe dans le coin bas DROIT, reduit a une fleche : c'est le seul coin
   libre du plateau, l'autre porte la porte de cote.
   Aucune capsule, aucun texte : une fleche de 11 px qui descend d'un cheveu,
   et qui s'efface au premier geste de defilement. */
.cue{
  position:absolute;
  right:var(--gutter);
  bottom:clamp(18px,2.8vh,30px);
  display:grid;
  place-items:center;
  color:var(--graphite);
  opacity:.5;
  transition:opacity .4s var(--ease);
}

.cue svg{
  display:block;
  width:11px;
  height:18px;
}

.cue.is-gone{opacity:0;pointer-events:none}

/* L'invitation tient dans le mouvement, pas dans un mot. Trois pixels, de
   quoi attirer l'oeil sans disputer l'attention au titre. */
@media (prefers-reduced-motion:no-preference){
  .cue svg{animation:cue-invite 2.4s var(--ease) infinite}
}

@keyframes cue-invite{
  0%,62%,100%{transform:translateY(0)}
  78%{transform:translateY(3px)}
}

/* ── Suite de la page ────────────────────────────────────── */

/* Le sol du studio ne change pas d'une section à l'autre : la page
   est la suite de la scène, pas une autre page posée dessous. Seul
   l'appel final passe sur le papier, pour fermer.               */

.band{
  position:relative;
  background:var(--studio);
  padding:clamp(72px,12vh,140px) var(--gutter) clamp(56px,9vh,110px);
  border-top:1px solid var(--line);
}

.band > h2{
  margin:0 0 18px;
  font-family:var(--display);
  font-weight:700;
  font-size:clamp(1.9rem,4.6vw,3.4rem);
  line-height:1.02;
  letter-spacing:-.03em;
  max-width:18ch;
  text-wrap:balance;
}

.band__lead{
  margin:0;
  max-width:62ch;
  color:var(--graphite);
  font-size:clamp(1.02rem,1.3vw,1.18rem);
  text-wrap:pretty;
}

/* La porte de côté, en haut à droite du plateau.
   ⚠ Elle a d'abord vécu sous les deux capsules. Deux raisons de l'avoir
   montée ici, et la seconde suffit : le bas du plateau est déjà occupé par
   le repère de défilement, centré, qui tombait pile dessus sur un 390×844 ;
   et une troisième ligne sous deux capsules pleine largeur se lit comme une
   troisième offre, ce qu'elle n'est pas.
   Le coin haut droit est vide à toutes les largeurs (le titre tient la
   gauche) et c'est l'endroit où l'on cherche un menu. */
.corner{
  position:absolute;
  top:clamp(13px,1.8vh,22px);
  right:var(--gutter);
  z-index:3;
  display:inline-flex;
  align-items:center;
  gap:6px;
  padding:5px 11px;
  border:1px solid var(--line);
  border-radius:var(--radius-cta);
  font-size:.75rem;
  font-weight:500;
  letter-spacing:.005em;
  text-decoration:none;
  color:var(--graphite);
  /* Elle entre avec les deux capsules, pas avant : --t2 lui est posé par
     hero.js en même temps qu'au pied. Une porte visible dès la première image
     du film propose de partir avant que la page ait dit quoi que ce soit. */
  opacity:var(--t2,0);
  transform:translate3d(0,calc((1 - var(--t2,0)) * -10px),0);
  /* ⛔ La capsule n'est pas une decoration, c'est une condition de lisibilite.
     Le lien flotte sur le film, et le film change : pose en texte nu, il
     disparait sur la scene du nuage d'applications, qui est saturee de bleu et
     d'orange pile dans ce coin. Le fond reprend le studio, donc la capsule se
     lit comme un objet de la scene et pas comme un badge ajoute dessus. */
  background:color-mix(in srgb,var(--studio) 76%,transparent);
  backdrop-filter:blur(10px) saturate(130%);
  -webkit-backdrop-filter:blur(10px) saturate(130%);
  transition:color .22s var(--ease),border-color .22s var(--ease);
}

/* Sans flou, la transparence ne suffit plus : le fond passe en opaque. */
@supports not (backdrop-filter:blur(1px)){
  .corner{background:var(--studio)}
}

.corner svg{
  width:8px;
  height:8px;
  transition:transform .32s var(--ease);
}

.corner:hover,
.corner:focus-visible{color:var(--red);border-color:var(--red)}
.corner:hover svg{transform:translate(2px,-2px)}

/* Le lien de texte : un filet qui s'épaissit et passe au rouge.
   Pas de flèche ajoutée au libellé, la capsule s'en charge déjà. */
.link{
  display:inline-block;
  font-weight:500;
  text-decoration:none;
  color:var(--ink);
  border-bottom:1px solid var(--line);
  padding-bottom:2px;
  transition:color .22s var(--ease),border-color .22s var(--ease);
}

.link:hover,
.link:focus-visible{color:var(--red);border-color:var(--red)}

/* ── Créations : des objets posés, pas des cartes ─────────── */

.works{
  list-style:none;
  margin:clamp(34px,5vh,56px) 0 0;
  padding:0;
  display:grid;
  grid-template-columns:repeat(2,1fr);
  gap:clamp(28px,4vw,52px) clamp(24px,3.4vw,48px);
}

.work{display:flex;flex-direction:column;gap:20px}

/* L'ombre est une ombre de CONTACT : un trait serré sous l'objet
   et une retombée courte. Une ombre grise flottante décollerait la
   tuile du sol sur lequel la scène vient de la poser.           */
.work__tile{
  display:block;
  position:relative;
  aspect-ratio:3/2;
  border-radius:20px;
  overflow:hidden;
  background:var(--paper);
  border:1px solid var(--line);
  box-shadow:0 1px 0 rgba(20,18,14,.05),0 20px 30px -22px rgba(20,18,14,.55);
  transition:transform .3s var(--ease),box-shadow .3s var(--ease);
}

.work__tile img{
  display:block;
  width:100%;
  height:100%;
  object-fit:cover;
  object-position:top center;
}

a.work__tile:hover,
a.work__tile:focus-visible{
  transform:translateY(-4px);
  box-shadow:0 1px 0 rgba(20,18,14,.05),0 32px 44px -26px rgba(20,18,14,.6);
}

/* Pas encore sortie : la tuile reste vide, comme au premier plan
   du film. L'état se montre, il n'a pas besoin d'être écrit.    */
.work__tile--empty{
  background:transparent;
  border:1px dashed rgba(20,18,14,.26);
  box-shadow:none;
}

.work__tile--quiet{box-shadow:0 1px 0 rgba(20,18,14,.05),0 14px 22px -20px rgba(20,18,14,.45)}

.work__say h3{
  margin:0 0 10px;
  font-family:var(--display);
  font-weight:700;
  font-size:clamp(1.3rem,1.9vw,1.6rem);
  letter-spacing:-.02em;
  line-height:1.1;
}

.work__say p{margin:0 0 14px;max-width:46ch;color:var(--graphite)}

.work__meta{color:var(--graphite);opacity:.85;line-height:1.9}

.work__say .link + .link{margin-left:20px}

/* ── L'offre : trois cartes, lues d'un seul coup d'oeil ────
      L'escalier indenté est abandonné : il obligeait à descendre
      pour comparer, alors que comparer est tout ce qu'on fait ici.
      La démarcation ne passe plus par la position mais par le poids :
      la gratuite est sur le papier avec le seul prix rouge, la
      dernière porte le trait d'encre et la capsule pleine.        */

.offers{
  list-style:none;
  margin:clamp(34px,5vh,56px) 0 0;
  padding:0;
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:clamp(16px,1.8vw,24px);
}

.offer{
  display:flex;
  flex-direction:column;
  padding:clamp(24px,2.4vw,34px);
  border:1px solid var(--line);
  border-radius:22px;
}

.offer__name{
  margin:0 0 6px;
  font-weight:600;
  font-size:.9375rem;
  letter-spacing:.005em;
}

/* Le prix porte la comparaison, il prend donc la taille d'un titre.
   Le symbole reste petit et haut : à taille égale il pèserait autant
   que le nombre, qui est la seule chose qu'on lit. */
.offer__price{
  margin:0 0 14px;
  font-family:var(--display);
  font-weight:800;
  font-size:clamp(2.1rem,3.4vw,3rem);
  line-height:1;
  letter-spacing:-.035em;
}

.offer__price span{
  font-size:.46em;
  font-weight:700;
  vertical-align:.34em;
}

/* `flex:1` aligne les trois capsules sur la même ligne quelle que
   soit la longueur de la phrase. */
.offer__line{
  margin:0;
  flex:1;
  color:var(--graphite);
  font-size:.9375rem;
  max-width:32ch;
  text-wrap:pretty;
}

.offer .cta{margin-top:22px;align-self:flex-start}

.offer--free{background:var(--paper)}
.offer--free .offer__price{color:var(--red)}
.offer--lead{border-color:var(--ink)}

/* ── Mouvement ────────────────────────────────────────────
      Doctrine « Stack front premium » : révélation une seule fois,
      décalage de 80 ms, courbe constante, rien au-delà de 0,6 s, et
      on anime `transform`, jamais une géométrie.

      L'état masqué est porté par `.js-motion`, posé par le script
      lui-même : si le script ne tourne pas, la page reste lisible au
      lieu de rester blanche.                                      */

.js-motion .reveal{
  opacity:0;
  transform:translate3d(0,18px,0);
  transition:opacity .52s var(--ease),transform .52s var(--ease);
  transition-delay:calc(var(--i,0) * 80ms);
}

.js-motion .reveal.is-in{opacity:1;transform:none}

/* La flottaison : six pixels, sept secondes, les deux tuiles
   déphasées. Elle passe par `translate` et non `transform`, qui reste
   au survol — les deux se composent au lieu de s'écraser. */
@media (prefers-reduced-motion:no-preference){
  .work__tile{animation:flottaison 7s var(--ease) infinite alternate}
  .work:nth-child(2) .work__tile{animation-delay:-3.4s}
}

@keyframes flottaison{
  from{translate:0 0}
  to{translate:0 -6px}
}

/* ── La méthode : la seule numérotation de la page, et l'ordre
      y porte le sens — on ne publie pas avant d'avoir un plan. ─ */

.steps{
  list-style:none;
  counter-reset:step;
  margin:clamp(34px,5vh,56px) 0 0;
  padding:0;
}

/* Trois colonnes en grand format — rang, étape, détail. Le titre
   et son texte côte à côte se lisent comme une fiche technique, et
   ça occupe la largeur au lieu de laisser un demi-écran vide.   */
.steps li{
  counter-increment:step;
  display:grid;
  /* ⛔ Pas de piste `auto` en tête : une piste `auto` reçoit l'espace
     libre de la grille et le rang poussait le titre au milieu de la
     page. Une largeur fixe laisse le vide à droite, où il est juste. */
  grid-template-columns:2.75rem minmax(0,17rem) minmax(0,42rem);
  gap:10px clamp(20px,3vw,44px);
  padding:clamp(26px,3.4vh,40px) 0;
  border-top:1px solid var(--line);
  align-items:start;
}

.steps li::before{
  content:counter(step,decimal-leading-zero);
  grid-column:1;
  grid-row:1;
  font-family:var(--mono);
  font-weight:500;
  font-size:.75rem;
  letter-spacing:.14em;
  color:var(--graphite);
  opacity:.65;
  padding-top:.5em;
}

.steps h3{
  grid-column:2;
  grid-row:1;
  margin:0;
  font-family:var(--display);
  font-weight:700;
  font-size:clamp(1.25rem,2vw,1.7rem);
  letter-spacing:-.02em;
  line-height:1.12;
}

.steps p{grid-column:3;grid-row:1;margin:0;color:var(--graphite)}

.caveat{
  margin:clamp(30px,4vh,48px) 0 0;
  padding-left:clamp(18px,2.4vw,28px);
  border-left:1px solid var(--line);
  max-width:64ch;
}

.caveat h3{
  margin:0 0 12px;
  font-family:var(--text);
  font-weight:600;
  font-size:.9375rem;
  letter-spacing:.005em;
}

.caveat ul{
  margin:0;
  padding:0;
  list-style:none;
  color:var(--graphite);
  font-size:.9375rem;
}

.caveat li{padding:4px 0}

/* La dernière ligne retourne la phrase : elle remonte à la couleur du
   texte principal pendant que les renoncements restent en retrait. */
.caveat__turn{
  margin:14px 0 0;
  font-weight:500;
  font-size:.9375rem;
  color:var(--ink);
}

/* ── Ressources : une liste dense, pas quatre cartes ──────── */

.tips{
  list-style:none;
  margin:clamp(34px,5vh,56px) 0 0;
  padding:0;
}

/* Les filets courent sur toute la largeur de la bande, comme ceux
   de la méthode : une règle qui s'arrête au milieu se lit comme un
   tableau inachevé.                                              */
.tips li{
  display:grid;
  grid-template-columns:minmax(0,18rem) minmax(0,46rem);
  gap:6px clamp(20px,3vw,44px);
  padding:22px 0;
  border-top:1px solid var(--line);
  align-items:baseline;
}

.tips p{margin:0;color:var(--graphite)}

/* ── L'appel final ───────────────────────────────────────── */

.band--end{background:var(--paper)}

.end{
  display:grid;
  grid-template-columns:minmax(0,12rem) 1fr;
  gap:clamp(28px,4vw,60px);
  align-items:center;
}

/* La tuile vide revient une dernière fois, à la place de l'objet :
   c'est la place de celle du visiteur.                           */
.end__tile{
  display:block;
  aspect-ratio:1;
  border-radius:24px;
  border:1px dashed rgba(20,18,14,.26);
}

.end__say h2{
  margin:0 0 14px;
  font-family:var(--display);
  font-weight:700;
  font-size:clamp(1.9rem,4.2vw,3.2rem);
  line-height:1.02;
  letter-spacing:-.03em;
  max-width:16ch;
  text-wrap:balance;
}

.end__say > p{margin:0 0 26px;max-width:48ch;color:var(--graphite)}

/* ── Pied ────────────────────────────────────────────────── */

.foot{
  display:flex;
  flex-wrap:wrap;
  align-items:baseline;
  justify-content:space-between;
  gap:20px clamp(24px,4vw,48px);
  padding:clamp(30px,4vh,44px) var(--gutter);
  background:var(--paper);
  border-top:1px solid var(--line);
}

.foot__sign{
  margin:0;
  font-family:var(--display);
  font-weight:800;
  font-size:1.0625rem;
  letter-spacing:-.02em;
}

.foot__links{
  list-style:none;
  margin:0;
  padding:0;
  display:flex;
  flex-wrap:wrap;
  gap:12px clamp(20px,3vw,36px);
  font-size:.9375rem;
}

/* ═══ Adaptations ══════════════════════════════════════════ */

/* ⭐ Écran plus étroit que 4:3 — le cas du téléphone tenu debout.
   `cover` sur une source 16:9 met à l'échelle sur la HAUTEUR : la
   largeur déborde de plusieurs fois l'écran et il ne reste qu'une
   bande centrale, avec la tuile coupée et un vide au milieu. C'est
   le piège `sizes="100vw"` du manuel de l'usine, reproduit ici.

   On passe donc en `contain` : le plan devient un panneau posé au
   centre, et le fond de page le complète sans couture puisque sa
   couleur est relevée dans le CGI lui-même. La grille du calque
   typographique — titre en haut, pied en bas — laisse justement
   cette bande libre au milieu.

   ⚠ Ce n'est PAS le cadrage vertical. Un vrai 9:16 demande des
   masters verticaux régénérés ; tant qu'ils n'existent pas, ceci
   est la meilleure lecture possible de la matière 16:9.        */
@media (max-aspect-ratio:4/3){
  /* ⭐ Recadrage, pas lettrage. Mesure faite sur l'image finale : la
     tuile occupe 28,5 % de la largeur du cadre (x 912→1642 sur 2560)
     et son centre est à 79,4 % de la hauteur.

     Conséquence chiffrée : un plein écran 9:16 découpé dans du 16:9
     ne montre que 26 % de la largeur. La tuile n'y tient pas — elle
     serait coupée des deux côtés quoi qu'on fasse. Le recadrage doit
     donc s'arrêter avant le plein écran.

     La fenêtre 4:5 est ce point d'arrêt : elle coupe 55 % du vide
     latéral, la tuile occupe alors 63 % de la largeur de l'écran au
     lieu d'être rognée, et le panneau fait 58 % de la hauteur au lieu
     des 26 % d'un simple lettrage.

     `clip-path` retire les bandes noires incrustées des masters : en
     `cover` sur une fenêtre plus étroite que la source, la hauteur est
     affichée en entier, donc elles arrivent pile aux bords du cadre. */
  .hero__media video,
  .hero__media img{
    inset:0 0 auto 0;
    height:70svh;
    transform:none;
    clip-path:inset(.72% 0 .78% 0);
    /* Le bord bas se dissout dans la page sur 34 px — le sol du studio
       y est vide, l'ombre de la tuile s'arrête bien au-dessus. Un
       raccord de couleur ne tiendrait pas : la teinte du bord change
       d'un plan à l'autre, le premier est même sombre. */
    -webkit-mask-image:linear-gradient(to bottom,#000 calc(100% - 34px),transparent);
    mask-image:linear-gradient(to bottom,#000 calc(100% - 34px),transparent);
  }

  /* Le pied descend sous l'image au lieu de flotter dessus : une arête
     qui traverse une phrase se lit comme un défaut d'affichage, la même
     arête posée entre l'image et le texte se lit comme une composition. */
  .hero__type{
    grid-template-rows:auto 1fr auto;
    /* ⚠ La marge haute s'ouvre pour laisser passer la porte de côté. En
       portrait le titre commençait à 39 px et la capsule descend à 51 : le
       mot « prochaine » passait dessous. Les 25 px se prennent sur la bande
       vide entre le titre et la tuile, jamais sur le pied, qui reste collé
       en bas par sa propre marge. Mesuré sur 390×844 et 360×740. */
    padding-top:clamp(60px,7.6vh,78px);
    padding-bottom:clamp(22px,3.4vh,40px);
  }

}

/* Le seuil est celui où une marche indentée cesse de se lire comme
   une marche : en dessous, l'escalier s'aplatit au lieu de produire
   une colonne étroite qu'on prendrait pour un défaut de gabarit. */
@media (max-width:780px){
  .works{grid-template-columns:1fr}
  /* Les trois cartes s'empilent : côte à côte sous cette largeur,
     la phrase de chacune tomberait à deux mots par ligne. */
  .offers{grid-template-columns:1fr}
  .tips li{grid-template-columns:1fr;gap:4px}
  .end{grid-template-columns:1fr;gap:clamp(24px,4vh,36px)}
  .end__tile{width:clamp(96px,26vw,140px)}
}

@media (max-width:900px){
  :root{--hero-hold:70vh}
  .title{font-size:clamp(2.8rem,13.5vw,5rem);max-width:none}
  .hero__foot{max-width:none}
  .tilemark{display:none}

  /* La fiche technique repasse en bloc : à cette largeur, la colonne
     de détail tomberait sous quarante caractères par ligne.        */
  .steps li{grid-template-columns:2.5rem 1fr;gap:0 clamp(18px,3vw,32px)}
  .steps li::before{grid-row:1 / span 2}
  .steps h3{margin-bottom:10px}
  .steps p{grid-column:2;grid-row:2}
}

@media (max-width:600px){
  :root{--hero-hold:60vh}
  .hero__type{grid-template-rows:auto 1fr auto}
  .actions{flex-direction:column;align-items:flex-start}
  .cta{width:100%;justify-content:space-between}
}

/* Le film n'est pas imposé : on sert l'état final et la page se lit. */
@media (prefers-reduced-motion:reduce){
  .hero{height:100svh}
  .hero__stage{position:relative}
  .title__line > span,
  .hero__foot,
  .corner,
  .tilemark,
  .tilemark::before{transform:none;opacity:1}
  .cue{display:none}
  .cta__fill,.cta__label span,.cta__arrow,
  .work__tile,.link{transition-duration:.01ms}
  .work__tile{animation:none}
  .js-motion .reveal{opacity:1;transform:none;transition:none}
  a.work__tile:hover,a.work__tile:focus-visible{transform:none}
}
