/* =====================================================================
   LE STUDIO — V5.2 candidate · Design system (Brand V1.0 — Nuit / Papier)
   Consomme assets/css/tokens.css (chargé avant) : --surface, --text-primary,
   --text-muted, --rule, --accent via [data-mode], + --ls-*, --font-*, --step-*.

   PRINCIPE DE MOUVEMENT UNIQUE — « LA COUTURE »
   Une arête Majorelle balaie, et dans son sillage le contenu devient lisible.
   Même geste à toutes les échelles : la couture de la porte, les lignes du
   manifeste, la démonstration Story Ads. Le mouvement révèle ; il ne décore pas.
   Chaque état animé possède un état statique complet (no-JS / reduced-motion).

   Propriétés logiques (RTL-ready). Mobile-first. Pas de pilule, pas de dégradé
   décoratif, pas de carte SaaS.
   ===================================================================== */

*{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}

body{
  font-family:var(--font-ui);
  background:var(--surface);color:var(--text-primary);
  font-size:var(--step-0);line-height:1.65;font-weight:400;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
  /* `clip` et non `hidden` : `overflow-x:hidden` ferait du body un conteneur de
     défilement et casserait silencieusement tous les position:sticky (seuil,
     manifeste, démonstration). `clip` borne le débordement sans cet effet. */
  overflow-x:clip;
}
img{max-width:100%;display:block;height:auto}
a{color:inherit;text-decoration:none}
::selection{background:var(--accent);color:var(--ls-white)}

/* ---- surfaces par mode ---- */
[data-mode]{background:var(--surface);color:var(--text-primary)}

/* ---- type ---- */
h1,h2,h3{font-family:var(--font-display);font-weight:700;line-height:1.06;letter-spacing:-.01em;text-wrap:balance}
h1{font-size:clamp(2.35rem,6.4vw,4.6rem);line-height:1.03}
h2{font-size:clamp(1.85rem,4vw,2.9rem)}
h3{font-family:var(--font-ui);font-weight:700;font-size:clamp(1.12rem,1.9vw,1.4rem);line-height:1.28;letter-spacing:-.005em}
p{text-wrap:pretty}
p+p{margin-block-start:1em}
strong,b{font-weight:700}

.eyebrow{
  font-family:var(--font-mono);font-size:.72rem;font-weight:500;
  letter-spacing:.16em;text-transform:uppercase;color:var(--text-muted);
  display:inline-flex;align-items:center;gap:.6em;
}
.eyebrow::before{content:"";inline-size:.42em;block-size:.42em;border-radius:50%;background:var(--accent);flex:none}
.meta{font-family:var(--font-mono);font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;color:var(--text-muted)}
.lead{font-size:clamp(1.06rem,1.6vw,1.26rem);line-height:1.55;color:var(--text-muted);font-weight:400;max-inline-size:56ch}
.accent{color:var(--accent)}
/* le point Majorelle — signe graphique propriétaire (jamais le logotype) */
.point{color:var(--accent)}

/* ---- layout ---- */
.container{max-inline-size:1180px;margin-inline:auto;padding-inline:clamp(20px,5vw,28px)}
.container--narrow{max-inline-size:860px}
.section{padding-block:clamp(60px,9vw,110px)}
.section--tight{padding-block:clamp(44px,6vw,72px)}
.section--rule{border-block-start:1px solid var(--rule)}
.head{max-inline-size:60ch}
.head .eyebrow{margin-block-end:16px}
.head h2{margin-block-end:0}
.head .lead{margin-block-start:20px}
.rule{block-size:1px;background:var(--rule);border:0}

/* ---- skip link ---- */
.skip{position:absolute;inset-inline-start:-9999px}
.skip:focus{inset-inline-start:16px;inset-block-start:16px;z-index:2000;background:var(--ls-ink);color:var(--ls-paper);padding:10px 16px;border-radius:2px}

/* =====================================================================
   NAV
   ===================================================================== */
.nav{position:fixed;inset-block-start:0;inset-inline:0;z-index:1000;transition:background .35s ease,border-color .35s ease}
.nav__in{max-inline-size:1300px;margin-inline:auto;padding:15px clamp(20px,5vw,28px);display:flex;align-items:center;justify-content:space-between;gap:20px}
.brand{display:inline-flex;align-items:center;gap:10px}
.brand__logo{block-size:20px;inline-size:auto}
.brand__logo--light{display:none}
.nav__links{display:none;align-items:center;gap:28px}
.nav__links a{font-size:.92rem;font-weight:500;color:var(--text-muted);padding-block:4px;position:relative;transition:color .2s}
.nav__links a:hover,.nav__links a.active{color:var(--text-primary)}
.nav__links a.active::after{content:"";position:absolute;inset-inline:0;inset-block-end:-2px;block-size:1.5px;background:var(--accent)}
.nav__cta.btn{display:none}
.burger{inline-size:42px;block-size:42px;border:1px solid var(--rule);border-radius:2px;background:transparent;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;cursor:pointer}
.burger span{inline-size:16px;block-size:1.5px;background:var(--text-primary);transition:transform .3s,opacity .3s}
.nav.open .burger span:nth-child(1){transform:translateY(5.5px) rotate(45deg)}
.nav.open .burger span:nth-child(2){opacity:0}
.nav.open .burger span:nth-child(3){transform:translateY(-5.5px) rotate(-45deg)}

/* solid state (scrolled / pages papier) */
.nav.scrolled{background:color-mix(in srgb,var(--ls-paper) 88%,transparent);backdrop-filter:saturate(140%) blur(12px);border-block-end:1px solid var(--rule-light)}

/* overlay sur hero Nuit */
.nav--overlay:not(.scrolled):not(.open) .nav__links a{color:rgba(242,238,227,.78)}
.nav--overlay:not(.scrolled):not(.open) .nav__links a:hover,
.nav--overlay:not(.scrolled):not(.open) .nav__links a.active{color:var(--ls-paper)}
.nav--overlay:not(.scrolled):not(.open) .burger{border-color:rgba(242,238,227,.34)}
.nav--overlay:not(.scrolled):not(.open) .burger span{background:var(--ls-paper)}
/* logo swap : sombre par défaut, clair sur overlay Nuit */
.nav--overlay:not(.scrolled):not(.open) .brand__logo--dark{display:none}
.nav--overlay:not(.scrolled):not(.open) .brand__logo--light{display:block}
/* le CTA de nav flotte sur un fond Nuit : il doit porter le Majorelle 300,
   comme le CTA du hero. Un seul bouton, une seule couleur, à l'écran. */
.nav--overlay:not(.scrolled):not(.open) .btn--accent{background:var(--accent-on-dark);color:var(--ls-ink)}
.nav--overlay:not(.scrolled):not(.open) .btn--accent:hover{background:color-mix(in srgb,var(--accent-on-dark) 82%,#fff)}

@media (min-width:980px){
  .nav__links{display:flex}
  .nav__cta.btn{display:inline-flex}
  .burger{display:none}
}

/* drawer mobile — inerte et non focalisable quand fermé (voir main.js : inert/aria-hidden) */
.drawer{position:fixed;inset-block:0;inset-inline-end:0;inline-size:min(86vw,340px);background:var(--ls-paper);color:var(--ls-ink);z-index:1001;transform:translateX(100%);transition:transform .38s var(--ease);box-shadow:-24px 0 60px rgba(16,16,20,.22);padding:92px 30px 40px;display:flex;flex-direction:column;gap:2px}
[dir="rtl"] .drawer{transform:translateX(-100%)}
.drawer.open{transform:none}
.drawer a{font-family:var(--font-display);font-weight:700;font-size:1.4rem;padding-block:13px;border-block-end:1px solid var(--rule-light);color:var(--ls-ink)}
.drawer .btn{margin-block-start:22px}
.scrim{position:fixed;inset:0;background:rgba(16,16,20,.5);z-index:1000;opacity:0;visibility:hidden;transition:opacity .35s,visibility .35s}
.scrim.open{opacity:1;visibility:visible}

/* =====================================================================
   BUTTONS
   ===================================================================== */
.btn{
  display:inline-flex;align-items:center;gap:9px;
  font-family:var(--font-ui);font-weight:700;font-size:.82rem;
  letter-spacing:.12em;text-transform:uppercase;
  padding:14px 24px;border-radius:2px;border:1px solid transparent;
  cursor:pointer;line-height:1;white-space:nowrap;
  transition:background .25s ease,border-color .25s ease,color .25s ease;
}
.btn svg{inline-size:16px;block-size:16px;flex:none}
.btn--accent{background:var(--accent);color:var(--ls-white)}
[data-mode="night"] .btn--accent{color:var(--ls-ink)}
.btn--accent:hover{background:color-mix(in srgb,var(--accent) 82%,#000)}
[data-mode="night"] .btn--accent:hover{background:color-mix(in srgb,var(--accent) 82%,#fff)}
.btn--ghost{background:transparent;border-color:var(--rule);color:var(--text-primary)}
.btn--ghost:hover{border-color:var(--text-primary)}
.nav__cta.btn{padding:11px 18px}
.btns{display:flex;flex-wrap:wrap;gap:14px;align-items:center}
@media (max-width:360px){.btn{white-space:normal;text-align:center;line-height:1.3}}
.tlink{display:inline-flex;align-items:center;gap:7px;color:var(--accent);font-weight:700;font-size:.9rem;font-family:var(--font-ui);border-block-end:1.5px solid transparent;padding-block-end:2px;transition:gap .2s,border-color .2s}
.tlink:hover{gap:11px;border-color:var(--accent)}

/* =====================================================================
   HERO générique
   ===================================================================== */
.hero{position:relative;min-block-size:100svh;display:flex;flex-direction:column;justify-content:flex-end;overflow:hidden}
.hero__in{width:100%;max-inline-size:1180px;margin-inline:auto;padding-inline:clamp(20px,5vw,28px);padding-block:clamp(120px,20vh,180px) clamp(64px,9vh,110px)}
.hero .eyebrow{margin-block-end:22px}
.hero h1{max-inline-size:17ch;text-wrap:balance}
.hero__lead{margin-block-start:26px;max-inline-size:52ch;color:var(--text-muted)}
.hero .btns{margin-block-start:36px}
/* page hero compact (papier) */
.hero--page{min-block-size:auto;justify-content:flex-end}
.hero--page .hero__in{padding-block:clamp(128px,18vh,180px) clamp(30px,5vw,56px)}

/* =====================================================================
   1 · LE SEUIL — hero d'accueil (Nuit)
   Le visiteur franchit une porte : derrière une façade fermée et générique,
   un lieu singulier se révèle. C'est la proposition de valeur, jouée.
   Images V5.1 (riad-door / riad-world) = univers éditorial Le Studio :
   décoratives, jamais un client, jamais un lieu réel, jamais une preuve.
   Base statique (no-JS / reduced-motion) = jardin déjà révélé sous voile Nuit.
   Durée volontairement courte (130vh) : le seuil se franchit, il ne s'habite pas.
   ===================================================================== */
.threshold{--p:0}
.threshold__pin{position:relative;min-block-size:100svh;display:flex;flex-direction:column;justify-content:flex-end;overflow:hidden;isolation:isolate}
.threshold__scene{position:absolute;inset:0;z-index:0;pointer-events:none}
.threshold__world{position:absolute;inset:0;z-index:0;overflow:hidden}
.threshold__world img{inline-size:100%;block-size:100%;object-fit:cover;object-position:center 48%}
/* Voile à 0 : les plaques du seuil sont déjà étalonnées Nuit (luminance moyenne
   32,9 sur 255). Le voile hérité de l'ancien master les écrasait en noir et
   rendait la porte invisible. Le calque est conservé pour un réglage futur. */
.threshold__veil{position:absolute;inset:0;z-index:1;background:#0b0b0e;opacity:0}
.threshold__doors{position:absolute;inset:0;z-index:2;display:none;perspective:1300px;perspective-origin:50% 48%}
.threshold__leaf{position:absolute;inset-block:0;inline-size:50%;overflow:hidden;backface-visibility:hidden;will-change:transform}
.threshold__leaf--l{inset-inline-start:0;transform-origin:left center}
.threshold__leaf--r{inset-inline-end:0;transform-origin:right center}
.threshold__leaf img{position:absolute;inset-block-start:0;block-size:100%;inline-size:200%;max-inline-size:none;object-fit:cover;object-position:center 35%}
.threshold__leaf--l img{inset-inline-start:0}
.threshold__leaf--r img{inset-inline-start:auto;inset-inline-end:0}
/* Les montants fixes n'existent qu'en desktop : sur mobile, le cadrage validé
   reste strictement inchangé. */
.threshold__jamb{display:none}
/* Le voile s'assombrit franchement sous la zone de copie : le texte est posé sur
   une photographie, il doit rester au contraste AA quelle que soit l'image. */
.threshold__scrim{position:absolute;inset:0;z-index:4;background:linear-gradient(180deg,rgba(16,16,20,.34) 0%,rgba(16,16,20,.06) 28%,rgba(16,16,20,.40) 56%,rgba(16,16,20,.74) 78%,rgba(16,16,20,.90) 100%)}
/* la couture : signature du site, ici à l'échelle d'une porte */
.threshold__seam{position:absolute;inset-block:6% 6%;inset-inline-start:50%;inline-size:var(--seam);transform:translateX(-50%);background:linear-gradient(180deg,transparent,var(--ls-majorelle-soft),transparent);z-index:5;opacity:.55}
.threshold__copy{position:relative;z-index:6}
/* petits caractères sur photo : on remonte à quasi-plein pour tenir l'AA */
.threshold__copy .eyebrow,.threshold__copy .cta__alt{color:rgba(242,238,227,.94)}
.threshold__copy .hero__lead{color:rgba(242,238,227,.88)}
.threshold__label{position:absolute;inset-block-start:88px;inset-inline-end:26px;z-index:6;font-family:var(--font-mono);font-size:.6rem;letter-spacing:.2em;text-transform:uppercase;color:rgba(242,238,227,.5)}

/* ---------------------------------------------------------------------
   DESKTOP : LE VIEWPORT DEVIENT LA PORTE
   La plaque EST la composition : les montants sculptés touchent déjà les
   bords, aucun recadrage n'est nécessaire. On étire la plaque sur toute la
   largeur du viewport.

   Repères MESURÉS colonne par colonne sur les masters, volontairement non
   lissés — l'asymétrie du rendu reste visible plutôt que corrigée au CSS
   (paysage 4096x2304, fraction de la largeur) :
     0        bord de plaque
     0.2123   bord intérieur du montant gauche = charnière gauche
     0.5036   couture centrale
     0.8038   bord intérieur du montant droit  = charnière droite
     1        bord de plaque
   Asymétrie gauche/droite assumée : 1,61 point.

   Les deux battants et les deux montants partagent exactement la même
   ressource : une seule requête porte, servie depuis le cache pour les trois
   calques suivants. Seuls les battants pivotent ; montants et mur sont des
   calques fixes posés PAR-DESSUS.
   --------------------------------------------------------------------- */
@media (min-width:721px){
  .threshold__scene{
    /* largeur de la plaque : pleine largeur, relevée si la fenêtre est très
       haute, pour que la plaque 16:9 couvre toujours la hauteur */
    --sw:max(100vw, 177.68svh);
    --x0:calc((100vw - var(--sw)) / 2);   /* bord gauche de la plaque */
  }
  /* Perspective proportionnelle à la porte : le raccourci de l'arête libre est
     alors identique à 1280 comme à 2048, et le débord des battants (16svh)
     suffit partout. Une perspective en px fixes déformerait davantage les
     grands écrans et laisserait réapparaître l'arête. */
  .threshold__doors{perspective:calc(1.7 * var(--sw));perspective-origin:50% 50%}

  /* Les battants débordent de 16svh en haut et en bas. En pivotant, leur arête
     libre recule vers le point de fuite et se rétrécit d'environ 14 % ; sans ce
     débord, ce bord entrerait dans le cadre et on verrait le jardin à la place
     du linteau. Le débord garde les arêtes hors champ à toute ouverture. */
  .threshold__leaf{inline-size:calc(.2913 * var(--sw));inset-block:-16svh}
  .threshold__leaf--l{inset-inline-start:calc(var(--x0) + .2123 * var(--sw))}
  .threshold__leaf--r{inline-size:calc(.3002 * var(--sw));inset-inline-start:calc(var(--x0) + .5036 * var(--sw));inset-inline-end:auto}

  .threshold__jamb{
    display:block;position:absolute;inset-block:0;z-index:3;overflow:hidden;
  }
  .threshold__jamb--l{inset-inline-start:var(--x0);inline-size:calc(.2123 * var(--sw))}
  .threshold__jamb--r{inset-inline-start:calc(var(--x0) + .8038 * var(--sw));inline-size:calc(.1962 * var(--sw))}

  /* Un seul et même cadrage de la plaque dans les quatre calques : chaque
     calque décale l'image de sa propre position, donc le raccord entre montant
     et battant est invisible tant que la porte est fermée. */
  .threshold__leaf img,.threshold__jamb img{
    position:absolute;inline-size:var(--sw);block-size:auto;max-inline-size:none;
    inset-inline-end:auto;object-fit:fill;
  }
  /* Le montant est à ras du pin ; le battant est décalé de 16svh vers le haut.
     Les deux compensations placent la plaque AU MÊME endroit : le raccord
     montant / battant reste invisible porte fermée.
     (hauteur de la plaque à cette échelle = 0.5625 * sw) */
  .threshold__jamb img{inset-block-start:calc(50%   - .2814 * var(--sw))}
  .threshold__leaf img{inset-block-start:calc(66svh - .2814 * var(--sw))}
  .threshold__jamb--l img{inset-inline-start:0}
  .threshold__leaf--l img{inset-inline-start:calc(-.2123 * var(--sw))}
  .threshold__leaf--r img{inset-inline-start:calc(-.5036 * var(--sw))}
  .threshold__jamb--r img{inset-inline-start:calc(-.8038 * var(--sw))}

  /* la couture suit la vraie jonction des battants */
  .threshold__seam{inset-inline-start:calc(var(--x0) + .5036 * var(--sw))}
}
/* Le conteneur reste en écriture horizontale : sinon inset-inline-* se résout
   dans le mode d'écriture de l'élément lui-même et la puce part à gauche.
   Seul le texte interne bascule en vertical. */
.threshold__cue{position:absolute;inset-block-end:24px;inset-inline-end:28px;z-index:5;font-family:var(--font-mono);font-size:.64rem;letter-spacing:.2em;text-transform:uppercase;color:rgba(242,238,227,.55)}
.threshold__cue>span{writing-mode:vertical-rl;display:block}
@media (prefers-reduced-motion:no-preference){
  .js .threshold{block-size:130vh}
  .js .threshold__pin{position:sticky;inset-block-start:0;block-size:100svh}
  .js .threshold__doors{display:block}
  /* le jardin recule très légèrement : un mouvement de caméra, pas un zoom */
  .js .threshold__world img{transform:scale(calc(1.06 - var(--p) * .06));will-change:transform}
  .js .threshold__leaf--l{transform:rotateY(calc(var(--p) * 82deg))}
  .js .threshold__leaf--r{transform:rotateY(calc(var(--p) * -82deg))}
  .js .threshold__seam{opacity:calc(.55 * (1 - var(--p)));will-change:opacity}
  /* la copie ne disparaît jamais avant que la porte soit largement ouverte */
  .js .threshold__copy{opacity:calc(1 - max(0,(var(--p) - .74)) * 3.4);transform:translateY(calc(var(--p) * -26px));will-change:transform,opacity}
}
@media (max-width:720px){
  .threshold__cue{display:none}
  .threshold__label{inset-block-start:78px;inset-inline-end:18px}
}
/* La course de scroll mobile doit rester sous la MÊME condition que l'épinglage :
   sinon, en reduced-motion, la section garderait 118vh sans pin et laisserait
   ~18vh de vide sous la copie.

   MOBILE : plaques portrait natives (2160x3840). Les montants sculptés y sont
   également visibles, avec leurs propres repères mesurés :
     0.1828 charnière gauche · 0.5037 couture · 0.7811 charnière droite.
   Asymétrie assumée : 3,61 points. */
@media (prefers-reduced-motion:no-preference) and (max-width:720px){
  .js .threshold{block-size:118vh}

  .js .threshold__scene{
    --sw:max(100vw, 56.28svh);            /* plaque 9:16 */
    --x0:calc((100vw - var(--sw)) / 2);
  }
  .js .threshold__doors{perspective:calc(1.7 * var(--sw));perspective-origin:50% 50%}

  .js .threshold__leaf{inset-block:-16svh;inline-size:calc(.3209 * var(--sw))}
  .js .threshold__leaf--l{inset-inline-start:calc(var(--x0) + .1828 * var(--sw));inset-inline-end:auto}
  .js .threshold__leaf--r{inline-size:calc(.2774 * var(--sw));inset-inline-start:calc(var(--x0) + .5037 * var(--sw));inset-inline-end:auto}

  .js .threshold__jamb{display:block;position:absolute;inset-block:0;z-index:3;overflow:hidden}
  .js .threshold__jamb--l{inset-inline-start:var(--x0);inline-size:calc(.1828 * var(--sw))}
  .js .threshold__jamb--r{inset-inline-start:calc(var(--x0) + .7811 * var(--sw));inline-size:calc(.2189 * var(--sw))}

  .js .threshold__leaf img,.js .threshold__jamb img{
    position:absolute;inline-size:var(--sw);block-size:auto;max-inline-size:none;
    inset-inline-end:auto;object-fit:fill;
  }
  /* hauteur de la plaque portrait à cette échelle = 1.7768 * sw */
  .js .threshold__jamb img{inset-block-start:calc(50%   - .88841 * var(--sw))}
  .js .threshold__leaf img{inset-block-start:calc(66svh - .88841 * var(--sw))}
  .js .threshold__jamb--l img{inset-inline-start:0}
  .js .threshold__leaf--l img{inset-inline-start:calc(-.1828 * var(--sw))}
  .js .threshold__leaf--r img{inset-inline-start:calc(-.5037 * var(--sw))}
  .js .threshold__jamb--r img{inset-inline-start:calc(-.7811 * var(--sw))}
  .js .threshold__seam{inset-inline-start:calc(var(--x0) + .5037 * var(--sw))}
}

/* =====================================================================
   2 · MANIFESTE — révélation par passage lumineux (Nuit)

   Le texte est découpé en GROUPES DE MOTS (.mseg). Le masque progresse d'un
   groupe à l'autre, jamais au milieu d'un glyphe, et son bord est un dégradé
   doux de plus d'un cadratin : il ne reste aucune arête de 1 px, donc plus
   aucune lecture « caret de saisie ». Une lueur large accompagne le bord et
   n'existe QUE pendant le passage.

   Aucun fondu d'opacité sur le texte : un groupe est masqué, ou il est à 100 %.
   Hors animation (sans JS, ou en reduced-motion), aucun masque n'est appliqué :
   les quatre phrases sont intégralement lisibles.
   ===================================================================== */
.manifesto__pin{margin-inline:auto;text-align:start}
/* La mesure est exprimée en em, donc relative à la taille d'affichage réelle.
   En ch ou en rem sur le parent, elle se résoudrait sur le 16px hérité et la
   colonne s'effondrerait à ~220px. */
.manifesto__lead{font-family:var(--font-display);font-weight:700;font-size:clamp(1.75rem,5vw,3.5rem);line-height:1.12;letter-spacing:-.01em;display:flex;flex-direction:column;gap:.1em;max-inline-size:15em}
.mword{display:block}
.mword--accent{color:var(--accent)}
.manifesto__method{margin-block-start:clamp(22px,3.4vw,36px);font-family:var(--font-mono);font-size:clamp(.72rem,1.2vw,.84rem);letter-spacing:.06em;line-height:1.75;color:var(--text-muted);max-inline-size:44ch}
/* état de base : aucun masque, tout est lisible */
.mseg{display:inline-block;position:relative}
.mseg>span{display:inline-block}

@media (prefers-reduced-motion:no-preference){
  .js .manifesto{padding-block:0}
  /* 200vh : ~100vh de course utile pour 5 groupes, soit ~16vh de passage
     chacun, puis une tenue finale de ~20vh pour lire les quatre phrases. */
  .js .manifesto>.container{block-size:200vh}
  .js .manifesto__pin{position:sticky;inset-block-start:0;min-block-size:100svh;display:flex;flex-direction:column;justify-content:center}

  /* --s : progression du groupe (0 → 1), écrite par main.js.
     --f : largeur du fondu. Le masque va de -f (rien) à 100%+f (tout). */
  .js .mseg{--s:1;--f:1.5em}
  .js .mseg>span{
    -webkit-mask-image:linear-gradient(90deg,#000 calc(var(--s) * (100% + var(--f)) - var(--f)),rgba(0,0,0,0) calc(var(--s) * (100% + var(--f))));
    mask-image:linear-gradient(90deg,#000 calc(var(--s) * (100% + var(--f)) - var(--f)),rgba(0,0,0,0) calc(var(--s) * (100% + var(--f))));
  }
  /* La lueur : large, douce, posée sur le parent NON masqué pour ne pas être
     coupée par le masque. Elle naît à 0, culmine à mi-passage, a disparu
     quand le groupe est net. */
  .js .mseg::after{
    content:"";position:absolute;inset-block:-.18em;pointer-events:none;z-index:1;
    inline-size:calc(var(--f) * 2.4);
    inset-inline-start:calc(var(--s) * (100% + var(--f)) - var(--f) * 1.7);
    background:radial-gradient(closest-side,color-mix(in srgb,var(--accent) 46%,transparent),transparent);
    opacity:calc(var(--s) * (1 - var(--s)) * 4);
  }
}

/* =====================================================================
   3 · SHELL VIDÉO MANIFESTE — carton-titre statique, 16:9 réservé, inerte.
   data-video-ready="false" : aucune source, aucune requête, aucun bouton Play,
   aucun « bientôt disponible ». L'état sans vidéo est un parti pris fini :
   un carton de générique qui porte déjà l'idée.
   ===================================================================== */
.video-shell__frame{position:relative;aspect-ratio:16/9;inline-size:100%;border:1px solid var(--rule);border-radius:2px;display:flex;flex-direction:column;justify-content:space-between;padding:clamp(22px,4vw,44px);overflow:hidden}
.video-shell__frame::before{
  content:"";position:absolute;inset-block:12%;inset-inline-start:clamp(22px,4vw,44px);
  inline-size:var(--seam);background:var(--accent);opacity:.9;
}
.video-shell__row{display:flex;justify-content:space-between;align-items:baseline;gap:16px;flex-wrap:wrap;position:relative}
.video-shell__title{font-family:var(--font-display);font-weight:700;font-size:clamp(1.7rem,4.6vw,3.2rem);line-height:1.05;letter-spacing:-.01em;max-inline-size:16ch;position:relative;padding-inline-start:clamp(18px,2.6vw,30px)}
.video-shell__label{font-family:var(--font-mono);font-size:.68rem;letter-spacing:.18em;text-transform:uppercase;color:var(--text-muted)}
.video-shell__play{display:none} /* bouton futur : reste hidden tant que data-video-ready="false" */
@media (max-width:600px){.video-shell__frame{aspect-ratio:auto;min-block-size:62vw;gap:26px}}

/* =====================================================================
   4 · LA DÉMONSTRATION (page Story Ads)
   Le même lieu, deux fois. Le visiteur voit la méthode se produire :
   plan large générique → détail révélateur → ligne → mouvement → envie d'écrire.
   Assets = univers éditorial Le Studio, signés « Une vision Le Studio ».
   ===================================================================== */
.demo{--d:0}
.demo__stage{display:grid;gap:clamp(26px,4vw,52px);align-items:center}
@media (min-width:900px){.demo__stage{grid-template-columns:minmax(0,clamp(260px,30vw,380px)) minmax(0,1fr)}}

/* ÉTAT STATIQUE (sans JS / reduced-motion) = diptyque assumé.
   Les deux plans sont montrés côte à côte : le large générique, puis le détail.
   C'est une composition finie, pas un état dégradé. */
.demo__frame{position:relative;inline-size:100%;max-inline-size:380px;margin-inline:auto;display:grid;grid-template-columns:1fr 1fr;gap:2px;background:var(--ls-ink);isolation:isolate;border-radius:2px;overflow:hidden}
.demo__shot{position:relative;aspect-ratio:9/32}
.demo__shot img{inline-size:100%;block-size:100%;object-fit:cover}
.demo__seam{display:none}
.demo__caption{
  grid-column:1 / -1;z-index:4;
  padding:clamp(14px,2.6vw,22px);
  background:var(--ls-ink);color:var(--ls-paper);
}
/* les deux légendes : en statique elles se lisent en diptyque (avant / après),
   en animé elles se relaient exactement au passage de la couture. */
.demo__line{display:block;font-family:var(--font-display);font-weight:700;font-size:clamp(1.02rem,2.1vw,1.42rem);line-height:1.22;letter-spacing:-.01em}
.demo__line--wide{color:rgba(242,238,227,.72)}
.demo__line--detail{margin-block-start:.35em}
.demo__sign{display:block;margin-block-start:10px;font-family:var(--font-mono);font-size:.6rem;letter-spacing:.2em;text-transform:uppercase;color:rgba(242,238,227,.62)}

/* les temps de la démonstration, en regard du cadre */
.demo__beats{display:grid;gap:0;border-block-start:1px solid var(--rule);list-style:none;counter-reset:none}
.demo__beat{display:grid;grid-template-columns:auto 1fr;gap:18px;padding-block:clamp(16px,2.4vw,24px);border-block-end:1px solid var(--rule);align-items:start}
.demo__beat .n{font-family:var(--font-mono);font-size:.74rem;letter-spacing:.1em;color:var(--accent);min-inline-size:30px;padding-block-start:.35em}
.demo__beat h3{margin-block-end:6px}
.demo__beat p{color:var(--text-muted);font-size:.97rem}

@media (prefers-reduced-motion:no-preference){
  .js .demo>.container{block-size:280vh}
  .js .demo__stage{position:sticky;inset-block-start:0;min-block-size:100svh;align-content:center;padding-block:clamp(80px,12vh,120px) clamp(30px,6vh,60px)}

  /* ANIMÉ : les deux plans se superposent dans un seul cadre 9:16 et la couture
     balaie le large pour faire apparaître le détail. Le même geste que le seuil. */
  .js .demo__frame{display:block;aspect-ratio:9/16;gap:0}
  .js .demo__shot{position:absolute;inset:0;aspect-ratio:auto}
  .js .demo__shot--detail{clip-path:inset(0 0 0 calc((1 - var(--d)) * 100%));will-change:clip-path}
  .js .demo__shot--wide img{transform:scale(calc(1 + var(--d) * .04));will-change:transform}
  .js .demo__seam{
    display:block;position:absolute;inset-block:0;z-index:3;
    inset-inline-start:calc((1 - var(--d)) * 100%);
    inline-size:var(--seam);background:var(--accent);
    opacity:calc(var(--d) * (1 - var(--d)) * 4);
    will-change:inset-inline-start,opacity;
  }
  .js .demo__caption{
    position:absolute;inset-inline:0;inset-block-end:0;
    background:linear-gradient(0deg,rgba(16,16,20,.94) 14%,rgba(16,16,20,0) 100%);
    display:grid;
  }
  /* les deux lignes occupent la même cellule et se relaient.
     opacity borne elle-même les valeurs hors de [0,1]. */
  .js .demo__line{grid-area:1 / 1}
  .js .demo__line--wide{opacity:calc(1 - var(--d,0) * 2.4);color:var(--ls-paper)}
  .js .demo__line--detail{opacity:calc(var(--d,0) * 2.4 - 1.4);margin-block-start:0}
  .js .demo__sign{grid-area:2 / 1}
  .js .demo__beat{opacity:.42;transition:opacity .5s ease}
  .js .demo__beat.on{opacity:1}
}

/* =====================================================================
   OFFRE — le désir d'abord, le périmètre ensuite
   ===================================================================== */
.offer{display:grid;gap:clamp(30px,5vw,56px)}
@media (min-width:860px){.offer{grid-template-columns:minmax(0,1.1fr) minmax(0,.9fr);align-items:start}}
.price{font-family:var(--font-display);font-weight:700;font-size:clamp(2.4rem,6vw,4rem);line-height:1;letter-spacing:-.01em}
.price small{display:block;font-family:var(--font-mono);font-size:.72rem;font-weight:500;letter-spacing:.14em;text-transform:uppercase;color:var(--text-muted);margin-block-end:12px}
.price__note{margin-block-start:14px;font-size:.92rem;color:var(--text-muted);max-inline-size:40ch}

/* la « carte de livraison » : ce que vous recevez, pas une liste de clauses */
.deliver{border-block-start:1px solid var(--rule)}
.deliver li{display:grid;grid-template-columns:auto 1fr;gap:16px;padding-block:15px;border-block-end:1px solid var(--rule);align-items:baseline;list-style:none}
.deliver li b{font-family:var(--font-ui);font-weight:700;color:var(--text-primary)}
.deliver li span{color:var(--text-muted);font-size:.96rem}
.deliver .n{font-family:var(--font-mono);font-size:.72rem;letter-spacing:.08em;color:var(--accent);min-inline-size:26px}

/* =====================================================================
   PÉRIMÈTRE EXACT — niveau secondaire, dépliable (progressive enhancement :
   <details> reste ouvrable sans JS, et le contenu est indexable).
   ===================================================================== */
.scope{border-block-start:1px solid var(--rule)}
.scope__item{border-block-end:1px solid var(--rule)}
.scope__item summary{
  display:flex;align-items:center;justify-content:space-between;gap:18px;
  padding-block:18px;cursor:pointer;list-style:none;
  font-family:var(--font-ui);font-weight:700;font-size:1.02rem;line-height:1.35;
}
.scope__item summary::-webkit-details-marker{display:none}
.scope__item summary::after{
  content:"";inline-size:11px;block-size:11px;flex:none;
  border-inline-end:1.5px solid var(--accent);border-block-end:1.5px solid var(--accent);
  transform:rotate(45deg) translate(-2px,-2px);transition:transform .3s var(--ease);
}
.scope__item[open] summary::after{transform:rotate(-135deg) translate(-2px,-2px)}
.scope__item summary:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
.scope__body{padding-block-end:20px;color:var(--text-muted);font-size:.97rem;line-height:1.6;max-inline-size:66ch}
.scope__body p+p{margin-block-start:.8em}

/* =====================================================================
   PROJETS — SYSTÈME ÉDITORIAL
   Un projet n'est pas une fiche. C'est un univers visuel dominant, une idée
   centrale, et des supports qui découlent de cette idée.
   Aucune grille répétitive, aucune plaque textuelle vide.
   ===================================================================== */
/* <picture> ne doit jamais interférer avec la mise en page de l'image */
picture{display:contents}

.figfill{margin:0;min-inline-size:0}
.figfill picture{display:block;inline-size:100%}
.figfill img{display:block;inline-size:100%;block-size:100%;object-fit:cover;background:color-mix(in srgb,var(--text-primary) 7%,transparent)}
.figfill figcaption{margin-block-start:10px;font-family:var(--font-mono);font-size:.66rem;line-height:1.5;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted)}
.r-43 picture{aspect-ratio:4/3}
.r-11 picture{aspect-ratio:1/1}
.r-32 picture{aspect-ratio:3/2}

/* --- ACCUEIL : index éditorial compact des projets ---
   Grille asymétrique. Billey occupe la colonne large ; Serval et Garage Ibn
   Sina s'empilent dans la colonne étroite. Une image, un nom, un rôle bref,
   un lien. Toute la tuile est cliquable : aucun JavaScript, aucun carrousel. */
.index{display:grid;gap:clamp(28px,4vw,44px);margin-block-start:clamp(34px,5vw,52px)}
.index__item{display:grid;gap:16px;min-inline-size:0;color:inherit}
.index__fig{overflow:hidden}
.index__fig img{transition:transform .6s var(--ease)}
.index__item:hover .index__fig img{transform:scale(1.03)}
.index__txt{display:grid;gap:6px;align-content:start;min-inline-size:0}
.index__n{font-family:var(--font-mono);font-size:.68rem;letter-spacing:.18em;color:var(--accent)}
.index__item h3{font-family:var(--font-display);font-weight:700;font-size:clamp(1.3rem,2.2vw,1.7rem);line-height:1.1}
.index__role{color:var(--text-muted);font-size:.93rem;line-height:1.45}
.index__go{
  margin-block-start:6px;justify-self:start;
  font-family:var(--font-ui);font-weight:700;font-size:.82rem;color:var(--accent);
  border-block-end:1.5px solid transparent;padding-block-end:2px;transition:border-color .2s;
}
.index__item:hover .index__go{border-color:var(--accent)}
.index__item:focus-visible{outline:2px solid var(--accent);outline-offset:6px;border-radius:2px}
/* les deux projets secondaires forment une colonne autonome : leur espacement
   ne dépend plus de la hauteur du projet principal. */
.index__side{display:grid;gap:clamp(26px,3.4vw,40px);align-content:start;min-inline-size:0}
/* MOBILE : Billey garde toute la largeur ; Serval et Garage passent en grille
   compacte à deux colonnes, donc visuellement secondaires. Aucun carrousel. */
@media (max-width:899px){
  .index__side{grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(14px,4vw,22px)}
  .index__side .index__item{gap:12px}
  .index__side .index__item h3{font-size:clamp(1.02rem,4vw,1.22rem)}
  .index__side .index__role{font-size:.86rem;line-height:1.35}
  .index__side .index__go{font-size:.76rem}
}
@media (min-width:900px){
  .index{grid-template-columns:minmax(0,1.5fr) minmax(0,1fr);column-gap:clamp(32px,4vw,60px);align-items:start}
  .index__item--lead h3{font-size:clamp(1.6rem,2.9vw,2.2rem)}
  /* les tuiles secondaires posent l'image à côté du texte : plus compact */
  .index__side .index__item{grid-template-columns:minmax(0,148px) minmax(0,1fr);align-items:center;gap:20px}
}
/* --- PAGE PROJETS : études de cas à poids asymétrique ---
   Le rythme se déroule dans le scroll : contexte, tension, idée, formes, rôle.
   Chaque temps est un bloc distinct, jamais une colonne d'un tableau. */
.study{padding-block:clamp(56px,8vw,110px);border-block-start:1px solid var(--rule)}
.study:first-child{border-block-start:0;padding-block-start:clamp(8px,2vw,20px)}
.study__kicker{font-family:var(--font-mono);font-size:.7rem;letter-spacing:.18em;text-transform:uppercase;color:var(--accent);margin-block-end:14px}
.study__title{font-family:var(--font-display);font-weight:700;font-size:clamp(2rem,4.6vw,3.4rem);line-height:1.04;letter-spacing:-.012em}
.study--minor .study__title{font-size:clamp(1.6rem,3vw,2.3rem)}
.study__ctx{max-inline-size:60ch;color:var(--text-muted);font-size:clamp(1rem,1.4vw,1.12rem);line-height:1.6}
/* la tension : le seul moment où le cas hausse la voix */
.study__tension{
  padding-inline-start:clamp(18px,2.4vw,30px);
  border-inline-start:var(--seam) solid var(--accent);
  font-family:var(--font-display);font-weight:700;
  font-size:clamp(1.35rem,2.9vw,2.1rem);line-height:1.24;letter-spacing:-.01em;
  max-inline-size:24em;text-wrap:balance;
}
/* Chaque cas se lit en quatre temps étiquetés : mandat, enjeu de forme,
   réponse visuelle, rôle. Aucun autre bloc de texte public. */
.study__block{margin-block-start:clamp(28px,3.8vw,48px);display:grid;gap:12px}
.study__block h3{font-family:var(--font-mono);font-size:.7rem;font-weight:500;letter-spacing:.18em;text-transform:uppercase;color:var(--text-muted)}
.study__answer{font-size:clamp(1rem,1.4vw,1.12rem);line-height:1.6;max-inline-size:62ch}
.study__lead{margin-block-start:clamp(32px,4.5vw,56px)}
.study__forms{margin-block-start:clamp(24px,3.4vw,42px);display:grid;gap:clamp(14px,2.2vw,26px)}
/* Mosaïque : les applications secondaires restent des vignettes, jamais de
   grandes images successives. Deux colonnes dès 320px, trois à partir de 760px. */
.study__forms--3,.study__forms--2{grid-template-columns:repeat(2,minmax(0,1fr))}
@media (min-width:760px){.study__forms--3{grid-template-columns:repeat(3,minmax(0,1fr))}}
.study__foot{margin-block-start:clamp(26px,3.4vw,44px);display:grid;gap:8px;border-block-start:1px solid var(--rule);padding-block-start:18px;max-inline-size:70ch}
.study__foot dt{font-family:var(--font-mono);font-size:.68rem;letter-spacing:.16em;text-transform:uppercase;color:var(--text-muted)}
.study__foot dd{font-size:1rem;line-height:1.55}
.study__note{margin-block-start:16px;font-family:var(--font-mono);font-size:.66rem;letter-spacing:.05em;line-height:1.6;color:var(--text-muted);max-inline-size:64ch}
@media (min-width:900px){
  .study--major .study__lead{max-inline-size:min(100%,88ch)}
  .study--minor{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,clamp(260px,30vw,380px));column-gap:clamp(40px,5vw,72px);align-items:start}
  .study--minor .study__lead{grid-column:2;grid-row:1 / span 6;margin-block-start:0}
}

/* « Également accompagnés » — ligne discrète, sans plaque vide */
.also{border-block-start:1px solid var(--rule);padding-block-start:clamp(26px,4vw,40px)}
.also h2{font-size:clamp(1.2rem,2vw,1.5rem);font-family:var(--font-ui);font-weight:700;letter-spacing:-.005em}
.also__list{list-style:none;display:grid;gap:0;margin-block-start:18px}
.also__list li{display:grid;grid-template-columns:auto 1fr;gap:14px;padding-block:13px;border-block-end:1px solid var(--rule);align-items:baseline}
.also__list b{font-family:var(--font-ui);font-weight:700;font-size:1rem;min-inline-size:min(38vw,190px)}
.also__list span{color:var(--text-muted);font-size:.95rem}
@media (max-width:560px){.also__list li{grid-template-columns:1fr;gap:3px}}

/* =====================================================================
   MÉTHODE (Récit → Désir → Conversation directe)
   ===================================================================== */
.steps{display:grid;gap:0;border-block-start:1px solid var(--rule)}
.step{display:grid;grid-template-columns:auto 1fr;gap:20px;padding-block:clamp(18px,2.4vw,26px);border-block-end:1px solid var(--rule);align-items:start}
.step__n{font-family:var(--font-mono);font-size:.8rem;letter-spacing:.1em;color:var(--accent);min-inline-size:34px;padding-block-start:.35em}
.step h3{margin-block-end:6px}
.step p{color:var(--text-muted);font-size:.97rem}

/* =====================================================================
   STANDARDS DE VÉRITÉ
   ===================================================================== */
.truth{display:grid;gap:24px}
@media (min-width:760px){.truth{grid-template-columns:repeat(3,1fr)}}
.truth__item{border-block-start:2px solid var(--accent);padding-block-start:18px}
.truth__item h3{margin-block-end:8px}
.truth__item p{color:var(--text-muted);font-size:.95rem}

/* =====================================================================
   NOTE DU FONDATEUR
   ===================================================================== */
.founder blockquote{font-family:var(--font-display);font-weight:700;font-size:clamp(1.35rem,2.8vw,2.1rem);line-height:1.36;letter-spacing:-.01em;max-inline-size:23em}
.founder__by{margin-block-start:22px;font-family:var(--font-mono);font-size:.78rem;letter-spacing:.12em;text-transform:uppercase;color:var(--text-muted)}

/* =====================================================================
   CTA FINAL
   ===================================================================== */
.cta{text-align:center}
.cta h2{max-inline-size:20ch;margin-inline:auto}
.cta .lead{margin-inline:auto;margin-block:22px 32px;text-align:center}
.cta .btns{justify-content:center}
.cta__alt{margin-block-start:22px;font-family:var(--font-mono);font-size:.72rem;letter-spacing:.08em;color:var(--text-muted)}
/* Dans un premier écran, cette ligne ne commente pas le CTA : elle porte l'offre
   (nature du livrable, durée, prix). À .72rem sur une photographie, elle se
   lisait comme une note de bas de page. Elle reprend le poids qui lui revient,
   sans devenir un second titre. */
.hero__in .cta__alt{font-size:clamp(.82rem,1.05vw,.92rem);letter-spacing:.055em;line-height:1.6;max-inline-size:44ch}
.cta__alt a{border-block-end:1px solid var(--rule)}
.cta__alt a:hover{border-color:var(--accent);color:var(--accent)}

/* =====================================================================
   LISTES included / excluded
   ===================================================================== */
.duo{display:grid;gap:26px}
@media (min-width:760px){.duo{grid-template-columns:1fr 1fr}}
.list{border:1px solid var(--rule);border-radius:2px;padding:clamp(22px,3vw,30px)}
.list h3{margin-block-end:16px}
.list ul{list-style:none;display:grid;gap:12px}
.list li{display:grid;grid-template-columns:auto 1fr;gap:12px;color:var(--text-muted);font-size:.96rem;line-height:1.45}
.list li::before{content:"";inline-size:6px;block-size:6px;border-radius:50%;margin-block-start:8px;background:var(--accent)}
.list--excl li::before{background:var(--text-muted)}

/* =====================================================================
   CONTACT
   ===================================================================== */
.contact{display:grid;gap:44px}
@media (min-width:840px){.contact{grid-template-columns:1fr 1fr;gap:60px}}
.form{display:grid;gap:0}
.field{display:grid;gap:7px;margin-block-end:18px}
.field label{font-family:var(--font-mono);font-size:.72rem;font-weight:500;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted)}
.field input,.field textarea{font-family:var(--font-ui);font-size:1rem;color:var(--text-primary);background:transparent;border:1px solid var(--rule);border-radius:2px;padding:13px 15px;inline-size:100%;transition:border-color .2s,box-shadow .2s}
.field input:focus,.field textarea:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 20%,transparent)}
.field textarea{min-block-size:120px;resize:vertical}
.form__info{font-size:.86rem;color:var(--text-muted);margin-block:4px 16px;line-height:1.5}
.contact__direct{display:grid;gap:2px;align-content:start}
.crow{display:flex;align-items:center;gap:15px;padding-block:18px;border-block-start:1px solid var(--rule)}
.crow small{display:block;font-family:var(--font-mono);font-size:.7rem;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted)}
.crow a,.crow span{font-family:var(--font-display);font-weight:700;font-size:1.1rem;color:var(--text-primary)}

/* =====================================================================
   FOOTER (Nuit)
   ===================================================================== */
.foot{padding-block:60px 30px}
.foot__top{display:grid;gap:36px}
@media (min-width:760px){.foot__top{grid-template-columns:1.5fr 1fr 1fr}}
.foot__intro{color:var(--text-muted);font-size:.94rem;max-inline-size:34ch;margin-block-start:16px}
.foot h4{font-family:var(--font-mono);font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;color:var(--text-muted);margin-block-end:16px;font-weight:500}
.foot ul{list-style:none;display:grid;gap:10px}
.foot ul a,.foot ul span{color:var(--text-muted);font-size:.94rem;transition:color .2s}
.foot ul a:hover{color:var(--text-primary)}
.foot__bar{margin-block-start:48px;padding-block-start:24px;border-block-start:1px solid var(--rule);display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;font-family:var(--font-mono);font-size:.72rem;letter-spacing:.08em;color:var(--text-muted)}

/* =====================================================================
   REVEAL + A11Y + REDUCED MOTION
   ===================================================================== */
/* reveal : masqué UNIQUEMENT si JS est présent (sinon le contenu reste visible) */
.js .reveal{opacity:0;transform:translateY(16px);transition:opacity .7s var(--ease),transform .7s var(--ease)}
.js .reveal.in{opacity:1;transform:none}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:2px}

@media (prefers-reduced-motion:reduce){
  *{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}
  .js .reveal{opacity:1;transform:none}
  /* Rien ne dépend du scroll : les blocs animés (seuil, manifeste, démonstration)
     n'ont tout simplement pas de règle hors de @media (no-preference).
     Les états statiques de base sont déjà les états finaux et complets. */
  /* aucun masque ne peut subsister : les quatre phrases restent entières */
  .mseg>span{-webkit-mask-image:none!important;mask-image:none!important}
  .mseg::after{display:none!important}
  .demo__beat{opacity:1!important}
}
