/* ==========================================================================
   MODELE `mannequin` - book d'une mannequin mariage
   Charte photo : P. Cyclo cobalt. Typo : Syne 800 + Inter Tight.

   ⚠️ CE MODELE NE VEND RIEN, ET C'EST DELIBERE. Le releve `corpus-fr/mannequin.md`
   etablit que le mannequin freelance est illegal en France (le placement releve
   d'une licence d'agence d'Etat), qu'aucune mannequin n'a de site personnel, et
   que les deux acheteurs du mariage ne payent pas : la boutique recrute des
   mariees benevoles, le salon publie des annonces non remunerees. Un tunnel de
   reservation ferait donc vendre en direct une prestation qui ne se vend pas
   ainsi. Le site est un BOOK adresse aux agences et aux directions artistiques,
   et son point de contact est l'agence. Ne pas y remettre de bouton « reserver ».
   ========================================================================== */

@import url("../fonts/fonts.css");

:root{
  /* Thème clair : celui par défaut. Le catalogue compte déjà huit modèles
     sombres et aucun ne vend une robe (règle tirée de `rb-nuit-poudree`). */
  --fond:#F6F6F3;
  --fond-2:#EDEDE8;
  --encre:#14161C;
  --encre-2:#5C6070;
  --trait:#D9D9D2;
  --cobalt:#1B3AC4;

  /* ⭐ Les deux états du faisceau, et c'est ici que se joue tout le modèle.
     Au repos une image est délavée en gris ; sous le halo elle retrouve sa
     couleur. L'amplitude vient de la CHARTE PHOTO, pas de ces filtres : le
     fond cobalt tombe sur un gris moyen dense pendant que la robe ivoire ne
     bouge pas. Une série faite sur fond neutre n'aurait rien à rendre. */
  --repos-sat:.06;
  --repos-lum:1.16;
  --repos-con:.72;
  --vif-sat:1;
  --vif-lum:1;
  --vif-con:1;

  --large:1180px;
}

[data-theme="nuit"]{
  --fond:#0E1016;
  --fond-2:#161923;
  --encre:#ECEDF2;
  --encre-2:#9095A6;
  --trait:#262B38;
  --cobalt:#5B85FF;
  /* En thème sombre le faisceau n'éclaircit pas une image grise, il ALLUME une
     image éteinte : le repos descend en luminosité au lieu de monter. */
  --repos-sat:.18;
  --repos-lum:.42;
  --repos-con:1.02;
}

*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  margin:0;
  background:var(--fond);
  color:var(--encre);
  font-family:"Inter Tight",system-ui,-apple-system,"Segoe UI",sans-serif;
  font-size:17px;
  line-height:1.62;
  -webkit-font-smoothing:antialiased;
  transition:background .4s ease,color .4s ease;
}
img{max-width:100%;display:block}
a{color:inherit}
.wrap{max-width:var(--large);margin:0 auto;padding:0 26px}

h1,h2,h3,.syne{font-family:Syne,"Inter Tight",sans-serif;font-weight:800;letter-spacing:-.02em;line-height:1.04}
h2{font-size:clamp(28px,4.4vw,50px);margin:0 0 14px}
h3{font-size:19px;margin:0 0 6px;letter-spacing:-.01em}
.sur{
  font-family:"Inter Tight",sans-serif;font-weight:600;font-size:12px;
  letter-spacing:.16em;text-transform:uppercase;color:var(--cobalt);margin:0 0 12px;
}
.chapo{color:var(--encre-2);max-width:62ch;margin:0 0 34px;font-size:18px}

/* ===== Barre du haut ================================================== */
.bar{
  position:fixed;inset:0 0 auto 0;z-index:50;
  display:flex;align-items:center;gap:18px;
  padding:14px 26px;
  background:color-mix(in srgb,var(--fond) 86%,transparent);
  backdrop-filter:blur(10px);
  border-bottom:1px solid transparent;
  transition:border-color .3s ease;
}
.bar.posee{border-bottom-color:var(--trait)}
.bar__nom{font-family:Syne,sans-serif;font-weight:800;font-size:16px;letter-spacing:-.01em;text-decoration:none;cursor:pointer;white-space:nowrap}
.bar__outils{margin-left:auto;display:flex;align-items:center;gap:14px}
.bascule{
  border:1px solid var(--trait);background:none;color:var(--encre-2);
  font:inherit;font-size:12px;padding:6px 12px;border-radius:999px;cursor:pointer;white-space:nowrap;
}
.bascule:hover{color:var(--encre);border-color:var(--encre-2)}
/* ⚠️ La barre reste AU-DESSUS du panneau (z-index 50 contre 40) : sans ca le
   panneau recouvre son propre bouton et on ne peut plus le refermer. */

/* Le bouton : deux barres seulement, qui se croisent en X a l ouverture.
   Trois barres obligeraient a en escamoter une au milieu du croisement. */
.burger{
  width:42px;height:32px;padding:0;border:0;background:none;cursor:pointer;
  display:flex;flex-direction:column;justify-content:center;gap:8px;
}
.burger span{
  display:block;height:2px;width:100%;background:var(--encre);
  transition:transform .3s ease;
}
body.menu-ouvert .burger span:nth-child(1){transform:translateY(5px) rotate(45deg)}
body.menu-ouvert .burger span:nth-child(2){transform:translateY(-5px) rotate(-45deg)}

/* ===== Le menu plein ecran ============================================ */
/* Il DESCEND du haut plutot que d apparaitre : on doit voir d ou il vient,
   sinon le retour en arriere n a pas de sens. */
.panneau{
  position:fixed;inset:0;z-index:40;background:var(--fond);
  display:flex;flex-direction:column;
  padding:12vh 8vw 8vh;overflow-y:auto;
  transform:translateY(-100%);
  transition:transform .42s cubic-bezier(.4,0,.2,1);
}
.panneau.ouvert{transform:translateY(0)}
/* ⚠️ `margin-block:auto` et surtout PAS `justify-content:center` sur le
   panneau : dans un conteneur flex qui defile, le centrage coupe le HAUT du
   contenu des qu il depasse, et ce haut devient inatteignable meme en
   defilant. Avec des marges automatiques, il se centre quand il y a la place
   et reste entierement accessible quand il n y en a pas. */
.panneau nav{display:flex;flex-direction:column;gap:clamp(4px,1.4vh,14px);margin-block:auto}
.panneau nav a{
  display:flex;align-items:baseline;gap:min(4vw,34px);
  text-decoration:none;color:var(--encre);cursor:pointer;
  font-family:Syne,sans-serif;font-weight:800;
  /* ⚠️ 22px de plancher et non 30 : Syne 800 est tres large, et
     « Mensurations » debordait de l ecran sur un telephone. Un menu dont on
     ne lit pas les rubriques ne sert a rien, si grande que soit la typo. */
  font-size:clamp(22px,7.4vw,86px);line-height:1.02;letter-spacing:-.03em;
  /* Les rubriques montent une par une : c est le DECALAGE qui donne
     l impression que le menu se deplie, et non qu il s allume d un coup. */
  opacity:0;transform:translateY(24px);
  transition:opacity .4s ease,transform .4s ease,color .25s ease;
}
.panneau.ouvert nav a{
  opacity:1;transform:none;
  transition-delay:calc(.05s * var(--i) + .18s);
}
.panneau nav a:hover{color:var(--cobalt)}
.panneau nav a em{
  font-family:"Inter Tight",sans-serif;font-style:normal;font-weight:600;
  font-size:12px;letter-spacing:.2em;color:var(--encre-2);min-width:2.6em;
}
.panneau__pied{
  margin:8vh 0 0;color:var(--encre-2);font-size:14px;line-height:1.7;
}
.panneau__pied b{color:var(--encre);font-weight:600}
/* Le fond ne defile plus derriere le menu ouvert. */
body.menu-ouvert{overflow:hidden}

@media(max-width:760px){
  /* Sur telephone les trois elements de la barre doivent tenir sur UNE ligne :
     nom + bascule + bouton. On resserre plutot que de laisser replier. */
  .bar{gap:10px;padding:14px 16px}
  .bar__nom{font-size:14px}
  .bascule{font-size:11px;padding:5px 10px}
  .panneau{padding:14vh 7vw 6vh}
  .panneau nav a em{min-width:2em;font-size:11px}
}

/* ===== LE MUR (le geste) ============================================== */
/* ⚠️ 12vh et pas 34vh : a 34vh le nom avait un PREMIER ECRAN A LUI, seul et
   centre, et les photos n arrivaient qu ensuite. Sur la reference (le
   portfolio de Lilian Ginet) le nom n a jamais son moment : les photographies
   sont la des la premiere image, et c est derriere elles qu on le decouvre. */
.mur{position:relative;padding:12vh 0 16vh}
/* ⭐⭐ LE GESTE : le nom NE S'EN VA JAMAIS. Il est fixe au fond de la fenetre,
   sous les photographies, et ce sont ELLES qui passent par-dessus lui au
   defilement. D'ou `z-index:0` : la premiere version le posait a 20, donc
   au-dessus du mur, et il fallait l'effacer des l'entree dans les photos pour
   qu'on les voie encore. Effacer le nom, c'etait perdre le geste. */
.titre{
  position:fixed;inset:0;z-index:0;
  display:grid;place-items:center;text-align:center;
  pointer-events:none;padding:0 26px;
}
/* ⭐⭐ Le nom est un FILIGRANE, pas un titre. Sur la reference il est a peine
   plus clair que le fond : c est une texture de page, une chose qu on
   remarque au bout de trois secondes, jamais un mot qui crie. En encre pleine
   il ecrasait les photographies au lieu de les porter. Il grossit d autant
   plus qu il s efface : il tient maintenant la largeur de l ecran. */
.titre h1{
  /* Taille de depart seulement : c est le script qui la recale pour que le
     nom tienne exactement la largeur. Voir app.js, « le nom a la mesure ». */
  font-size:clamp(30px,8vw,172px);margin:0;line-height:.92;
  color:color-mix(in srgb, var(--encre) 11%, var(--fond));
  /* ⚠️ UNE SEULE LIGNE. Sur deux lignes le nom debordait des deux cotes et on
     n en lisait que des morceaux (« uise », « sseur ») : un filigrane coupe
     n est plus un nom, c est du bruit. La taille est calee pour que le nom le
     plus long tienne, pas pour remplir l ecran a tout prix. */
  white-space:nowrap;
}
.titre p{
  margin:14px 0 0;font-size:14px;
  letter-spacing:.18em;text-transform:uppercase;
  color:color-mix(in srgb, var(--encre-2) 34%, var(--fond));
}

/* ===================== L OUVERTURE ==================================
   ⭐⭐ LE NOM NE PART JAMAIS, IL CHANGE DE PLAN. C est tout le geste, et il
   se joue en une seconde et demie : le nom s affiche en PLEINE ENCRE sur le
   fond nu, legerement avance ; le sous-titre le rejoint ; puis les deux
   RECULENT en filigrane pendant que les photographies entrent par-dessus.
   Il ne s efface pas, il ne glisse pas, il ne disparait pas : il recule.

   ⚠️ Le mur est masque par `body.avant-intro` ET par `body.intro`, les deux
   seules classes posees par le script. C'est `avant-intro` qui compte : un
   script inline la pose des le parsing du <body> (voir l'index), donc avant
   la premiere peinture, et avant que `intro` ne soit posee au deuxieme
   `requestAnimationFrame`. Si elle ne masquait pas le mur, on verrait les
   photographies s'eteindre pendant que le nom monte a l'encre, puis revenir :
   deux entrees pour une seule. Le mur n'entre qu'UNE fois, a la fin, quand
   les deux classes sont retirees. Si le script echoue, aucune regle ne cache
   les photographies : une page qui cache ses photos quand un script tombe
   est une page vide.
   ==================================================================== */
.titre h1{transition:color 1.1s ease,transform 1.1s cubic-bezier(.4,0,.2,1)}
.titre p{transition:opacity .7s ease,transform .7s ease,color .7s ease}
body.avant-intro .mur,
body.intro .mur{opacity:0}
.mur{transition:opacity 1s ease}
/* Avant que le sous-titre ne soit appele, il attend sous la ligne. */
body.avant-intro .titre p{opacity:0;transform:translateY(10px)}
/* ⚠️ Le nom est a l'encre DES `avant-intro`, donc des la premiere image. Sans
   cette ligne il naissait en filigrane et montait a l'encre pendant 1,1 s,
   puis reculait aussitot : on ne le voyait jamais net « en premier », et
   l'ouverture se lisait comme un aller-retour au lieu d'un recul. (04/09) */
body.avant-intro .titre h1,
body.intro .titre h1{color:var(--encre);transform:scale(1.04)}
body.intro .titre p{color:var(--encre-2);opacity:1;transform:none}
body.intro .titre p{transition-delay:.55s}

@media(prefers-reduced-motion:reduce){
  .titre h1,.titre p,.mur{transition:none}
}

.rang{
  display:flex;align-items:flex-end;
  padding:0 46px;
  margin-bottom:var(--gap,120px);
  gap:34px;
}
.vig{
  position:relative;z-index:2;margin:0;
  width:var(--w,30%);
  /* --t vaut 0 au repos et 1 sous le halo. Une seule variable pilote les trois
     filtres : c'est ce qui permet aux deux thèmes de partager le même moteur. */
  --t:1;
}
/* Sans JavaScript, aucune image n'est éteinte : le filtre n'est appliqué
   qu'une fois le moteur en marche. Une page qui cache ses photos quand un
   script échoue est une page vide. */
body.faisceau .vig img{
  filter:
    saturate(calc(var(--repos-sat) + (var(--vif-sat) - var(--repos-sat)) * var(--t)))
    brightness(calc(var(--repos-lum) + (var(--vif-lum) - var(--repos-lum)) * var(--t)))
    contrast(calc(var(--repos-con) + (var(--vif-con) - var(--repos-con)) * var(--t)));
}
.vig img{
  width:100%;height:auto;
  transition:filter .45s ease,transform .6s ease;
}
.vig figcaption{
  margin-top:9px;font-size:12px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--encre-2);
  opacity:calc(.25 + .75 * var(--t));
  transition:opacity .45s ease;
}
@media(max-width:820px){
  /* Une colonne : les largeurs en pourcentage n'ont plus de sens, et le halo
     du curseur non plus. Le relais est pris par la bande centrale de l'écran,
     voir app.js. */
  .rang{display:block;padding:0 22px;margin-bottom:52px}
  .vig{width:100%;margin-bottom:38px}
  .mur{padding:30vh 0 10vh}
}

/* ===== Sections ======================================================= */
/* Les sections RECOUVRENT le nom : fond opaque et z-index au-dessus de lui.
   Sans ce fond, le titre fixe reste visible derriere leur texte et le rend
   illisible. C'est la contrepartie du geste, elle n'est pas optionnelle. */
.sec{
  position:relative;z-index:2;background:var(--fond);
  padding:104px 0;border-top:1px solid var(--trait);
}
.sec--fond{background:var(--fond-2)}

/* Mensurations */
.mesures{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));
  gap:1px;background:var(--trait);border:1px solid var(--trait);
}
.mesures div{background:var(--fond);padding:22px}
.mesures dt{font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--encre-2)}
/* Syne 800 est une graisse tres large : a 29px, « 1,76 m » se cassait en deux
   lignes et l'unite tombait toute seule sous le chiffre. Un nombre et son
   unite ne se separent pas, c'est une seule valeur. */
.mesures dd{
  margin:6px 0 0;font-family:Syne,sans-serif;font-weight:800;
  font-size:clamp(21px,1.55vw,29px);white-space:nowrap;
}
.daté{
  margin-top:14px;font-size:14px;color:var(--encre-2);
}
.daté b{color:var(--cobalt)}

/* Polas */
.polas{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;margin-top:8px}
.polas figure{margin:0}
.polas figcaption{margin-top:8px;font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--encre-2)}
@media(max-width:640px){.polas{grid-template-columns:1fr;max-width:340px}}

/* Listes de registres et de refus */
.grille{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:26px}
.carte{border:1px solid var(--trait);padding:24px;background:var(--fond)}
.carte p{margin:0;color:var(--encre-2);font-size:15.5px}
.refus{list-style:none;padding:0;margin:0;columns:2;column-gap:34px}
.refus li{padding:11px 0 11px 26px;position:relative;break-inside:avoid;border-bottom:1px solid var(--trait)}
.refus li::before{content:"";position:absolute;left:0;top:20px;width:13px;height:1.5px;background:var(--cobalt)}
@media(max-width:640px){.refus{columns:1}}

/* Encadré : ce qui remplace le bouton « réserver » */
.cadre{
  border:1px solid var(--cobalt);padding:28px;background:var(--fond);
  max-width:70ch;
}
.cadre p:first-child{margin-top:0}
.cadre p:last-child{margin-bottom:0}

/* Tableau des droits */
.droits{width:100%;border-collapse:collapse;font-size:15.5px}
.droits th,.droits td{text-align:left;padding:14px 12px;border-bottom:1px solid var(--trait);vertical-align:top}
.droits th{font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:var(--encre-2);font-weight:600}
.droits td:first-child{font-weight:600;white-space:nowrap}

/* Emplacement de média manquant : un ARGUMENT, pas un trou. */
.manque{
  border:1.5px dashed var(--trait);padding:26px;color:var(--encre-2);
  display:grid;place-items:center;text-align:center;min-height:190px;font-size:15px;
}
.manque b{display:block;color:var(--encre);font-family:Syne,sans-serif;margin-bottom:6px}

/* Formulaire */
form{display:grid;gap:18px;max-width:620px}
label{display:grid;gap:7px;font-size:13px;letter-spacing:.06em;text-transform:uppercase;color:var(--encre-2)}
select,input,textarea{
  font:inherit;font-size:16px;color:var(--encre);
  background:var(--fond);border:1px solid var(--trait);padding:12px 14px;border-radius:0;
}
select:focus,input:focus,textarea:focus{outline:2px solid var(--cobalt);outline-offset:1px;border-color:var(--cobalt)}
button[type=submit]{
  font:inherit;font-weight:600;background:var(--cobalt);color:#fff;border:0;
  padding:15px 26px;cursor:pointer;justify-self:start;letter-spacing:.02em;
}
button[type=submit]:hover{filter:brightness(1.12)}

/* Message d'etat du formulaire.
   ⚠️ `.etat[hidden]` et pas `[hidden]` tout court : dans ce catalogue on a deja
   vu un `display` de feuille de style gagner contre l'attribut natif. Ici le
   parent est une grille, l'enfant n'a pas de display propre, donc `hidden`
   suffirait - la regle est ecrite quand meme, elle coute une ligne et elle
   survit au jour ou quelqu'un donnera un `display` a `.etat`. */
.etat[hidden]{display:none}
.etat{
  margin:0;font-size:14px;line-height:1.5;color:var(--encre-2);
  border-left:2px solid var(--cobalt);padding-left:12px;
}

footer{position:relative;z-index:2;background:var(--fond);border-top:1px solid var(--trait);padding:56px 0 70px;color:var(--encre-2);font-size:14px}
footer .mention{max-width:74ch;margin-top:18px;font-size:13px;line-height:1.7}

@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *{transition:none!important}
}
