/* ============================================================
   base.css · fondations partagées (accueil + pages projet)
   Variables, reset, typographie, topbar, halos réutilisables.
   ============================================================ */

:root{
  --cream:#EEEDF1;
  --ink:#1c1c26;
  --ink-soft:#55555f;
  /* 4,6:1 sur le crème : les petits textes (dates, meta, footer) restent
     en retrait sans passer sous le seuil de lisibilité */
  --ink-faint:#696975;

  /* anneau de focus clavier, redéfini sur fond nuit (voir projet.css) */
  --focus:#1c1c26;

  /* La colonne du site. Elle s'élargit quand l'écran le permet et ne se
     resserre jamais en dessous de sa valeur d'origine : 1360 px sur un
     16 pouces, 1280 sur un 1440, 1180 en dessous, comme avant. C'est ce qui
     donne sa largeur maximale à l'aperçu au survol, qui vit dans la marge
     à droite des titres. Les six blocs qui la partagent doivent bouger
     ensemble, sinon le site perd son axe vertical. */
  --colonne:clamp(1180px,100vw - 160px,1360px);

  /* couleurs d'identité des projets */
  /* ⚠ L'ordre de ces valeurs suit l'ordre des lignes sur l'accueil, et pas le
     nom des projets. Lues de haut en bas, les huit teintes font un seul tour
     de la roue chromatique, sans jamais revenir en arrière :
       162° vert · 187 cyan · 228 bleu · 252 violet · 312 prune · 339 rose
       · 0 corail · 16 terracotta
     C'est pour ça que le vert est sur Affiliation et pas sur le Portail, et
     que la Peinture est en terracotta plutôt qu'en corail. Ne pas « remettre
     dans l'ordre des noms » : ce sont les lignes qui commandent. */
  --c-affil:rgb(18,184,134);
  --c-merchant:rgb(4,186,210);
  --c-connect:rgb(76,110,245);
  /* violet affiné : moins saturé, plus posé que le magenta d'origine */
  --c-ds:rgb(124,102,210);
  --c-workshop:#C247A9;     /* prune */
  --c-overview:#E64980;     /* rose */
  --c-paint:#E16537;        /* terracotta */
  --c-student:#FC6A5F;      /* corail, remonté en saturation pour tenir dans la série */
  --c-site:rgb(168,208,88);

  /* L'accent chaud du site : les halos du hero, le prénom en italique, les
     filets sous les liens, les flèches. Il valait jusqu'ici --c-paint, donc
     changer la couleur de la Peinture repeignait « Qui suis-je ». Il a son
     jeton à lui maintenant : une couleur de projet ne doit dire que ce projet. */
  --c-accent:#FC6A5F;
  --cg-accent:#E7584F;
  --ci-accent:#BB2E2C;

  /* Les mêmes couleurs, descendues en clarté pour porter du texte.
     Trois portées, parce qu'un même bleu ne se lit pas pareil en 44 px
     et en 13 px :

       --c-*   la couleur pleine. Filets, halos, fonds, pastilles, bordures,
               tout ce qui n'est pas lu.
       --cg-*  le texte au-dessus de 24 px (seuil 3:1). Trois teintes n'ont
               même pas besoin d'être touchées, elles y sont déjà.
       --ci-*  le petit texte (seuil 4,5:1), y compris posé sur un fond
               teinté de sa propre couleur.

     Chaque valeur est la couleur la plus proche de l'originale, au sens de
     l'œil (écart Lab minimal), parmi toutes celles qui tiennent le seuil.
     Elle a été cherchée, pas dérivée : un `color-mix` vers le noir délave
     la couleur en même temps qu'il l'assombrit, et une simple baisse de
     clarté vire le corail au rouge. Trois teintes passent déjà en grand
     titre et ne sont donc pas touchées du tout. */
  --cg-affil:#009B6A;
  --cg-merchant:#0095AA;
  --cg-connect:#4C6EF5;   /* déjà lisible en grand, pas touchée */
  --cg-ds:#7C66D2;        /* idem */
  --cg-workshop:#C247A9;   /* lisible telle quelle */
  --cg-overview:#E64980;   /* idem */
  --cg-paint:#DE6235;
  --cg-student:#E7584F;
  --cg-site:#6D941C;

  --ci-affil:#007445;
  --ci-merchant:#00707A;
  --ci-connect:#1358DC;
  --ci-ds:#6452BA;
  --ci-workshop:#A72C92;
  --ci-overview:#BC195D;
  --ci-paint:#B03C11;
  --ci-student:#BB2E2C;
  --ci-site:#487400;

  /* échelle d'espacement : une seule suite de valeurs pour tout le site,
     pour que « ça respire » se règle à un endroit et pas au cas par cas */
  --s-1:8px;
  --s-2:14px;
  --s-3:22px;
  --s-4:34px;
  --s-5:clamp(46px,6vh,72px);
  --s-6:clamp(72px,11vh,128px);

  /* typographies validées */
  --title-font:'Fraunces';
  --body-font:'Satoshi';

  /* réglages du mesh animé */
  --motion:0.5;      /* vitesse de dérive auto des halos */
  --hovermove:3;     /* intensité de la réaction à la souris */

  --morph-color:rgb(28,28,38);
  --halo-br:rgb(255,162,0);   /* halo orange dédié */
  --halo-tr:rgb(253,218,88);  /* halo jaune dédié  */
}

*{margin:0;padding:0;box-sizing:border-box}
/* Le défilement doux ne vaut que pour les ancres qu'on clique. Actif dès
   le chargement, il transforme la restauration de position du navigateur
   (au rechargement, ou au retour arrière) en un défilement qu'on regarde
   se faire depuis le haut de la page. La classe n'arrive donc qu'une fois
   la page posée : voir js/halos.js. */
/* Le retour arrière au pavé tactile reste actif. Il a été coupé un temps,
   parce qu'un glissement horizontal en fin de bande faisait quitter la page
   pendant qu'on la lisait. Mais couper le geste sur tout le site pour protéger
   cinq bandes, c'est retirer au visiteur le moyen le plus naturel de revenir
   d'une étude de cas à l'accueil. La protection est donc posée là où le
   problème existe : `overscroll-behavior-x:contain` sur chaque bande qui
   défile à l'horizontale, ce qui empêche le geste de déborder sur la page
   sans jamais désactiver la navigation ailleurs. */
html{scroll-behavior:auto}
html.pose{scroll-behavior:smooth}

/* ===== Focus clavier (global) =====
   Un seul anneau pour tout le site. Les composants qui ont leur propre
   traitement (zones cliquables du prototype, rail des états) le gardent :
   leurs règles sont plus spécifiques. */
:focus-visible{outline:2px solid var(--focus);outline-offset:3px}
body{
  font-family:var(--body-font),sans-serif;
  background:var(--cream);
  color:var(--ink);
  overflow-x:hidden;
  transition:background .5s;
}

/* ===== Topbar (partagée) ===== */
/* Le header respire à l'arrivée, puis se resserre dès qu'on descend.
   Il est en position fixe : sa hauteur ne pousse jamais le contenu,
   donc la transition ne déplace rien dans la page. */
.topbar{position:fixed;top:0;left:0;right:0;z-index:20;display:flex;justify-content:space-between;align-items:center;
  padding:38px clamp(20px,5vw,64px);transition:padding .35s cubic-bezier(.2,.8,.2,1)}
.topbar.small{padding:20px clamp(20px,5vw,64px)}
/* voile discret : blur qui s'estompe vers le bas, sans couleur ajoutée.
   (Essayé en dégradé de crème pour supprimer un calque composité, mais
   ça lavait les couleurs de l'accueil : on garde le flou.) */
.topbar::before{content:"";position:absolute;inset:0 0 -14px;z-index:-1;pointer-events:none;
  backdrop-filter:blur(9px);-webkit-backdrop-filter:blur(9px);
  mask-image:linear-gradient(to bottom,black 55%,transparent);
  -webkit-mask-image:linear-gradient(to bottom,black 55%,transparent)}
/* logo : le wordmark de Marie-Liesse (PNG) — noir + tiret corail sur fond clair,
   le même sur toutes les pages, qui sont toutes claires */
.topbar .b{display:inline-block;width:164px;height:39px;background:url(../assets/logo.png) left center/contain no-repeat;text-decoration:none;
  transition:width .35s cubic-bezier(.2,.8,.2,1),height .35s cubic-bezier(.2,.8,.2,1)}
.topbar.small .b{width:134px;height:32px}
.topbar .b .sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.topbar nav{display:flex;gap:34px;font-size:14px}
.topbar nav a{color:var(--ink-soft);text-decoration:none;transition:color .2s}
.topbar nav a:hover{color:var(--ink)}

/* sélecteur de langue FR · EN */
.topbar .lang{display:flex;gap:12px;margin-left:6px;padding-left:28px;border-left:1px solid rgba(128,128,138,.35)}
.topbar .lang a.on{color:var(--ink);font-weight:600;cursor:default}

/* ---- La barre posée sur un fond sombre ----
   Deux endroits du site passent sous la barre avec un fond noir : le bloc
   « Dans l'appartement » d'Expériences et la section noire de Peinture. Le logotype y est noir sur noir et les liens deviennent
   illisibles. La barre bascule donc en blanc le temps du passage, comme elle
   le faisait déjà sur la photo d'ouverture de Peinture. C'est js/halos.js qui
   pose la classe, en regardant ce qui se trouve derrière elle. */
.topbar.sur-sombre{--on-night:#fff}
.topbar.sur-sombre::before{opacity:0}
.topbar.sur-sombre .b{background-image:url(../assets/logo-white.png)}
.topbar.sur-sombre nav a{color:rgba(255,255,255,.82)}
.topbar.sur-sombre nav a.on,.topbar.sur-sombre nav a:hover{color:#fff}
.topbar.sur-sombre .lang{border-color:rgba(255,255,255,.35)}
.topbar.sur-sombre .lang a{color:rgba(255,255,255,.7)}
.topbar.sur-sombre .lang a.on{color:#fff}
/* le basculement se voit : sans transition, le logo clignote d'un noir à un
   blanc au milieu d'un défilement */
.topbar,.topbar .b,.topbar nav a,.topbar .lang a{transition:color .25s ease,background-image .25s ease}
@media (prefers-reduced-motion:reduce){
  .topbar.sur-sombre,.topbar.sur-sombre .b{transition:none}
}

/* topbar compacte en mobile : tout tient sur une seule ligne.
   Le sigle ne se laisse plus écraser : sans `flex:0 0 auto`, le flex le
   comprimait (48 px de large pour 124 déclarés sur un écran de 320) et le
   collait au premier lien, sans un pixel entre les deux. Le `gap` garantit
   l'écart que `space-between` ne garantit pas quand la ligne est pleine. */
@media (max-width:820px){
  .topbar{padding:22px 16px;gap:14px}
  .topbar.small{padding:13px 16px}
  .topbar .b{flex:0 0 auto;width:124px;height:30px}
  .topbar.small .b{width:104px;height:25px}
  /* un cran plus grand qu'avant : 12,5 px était sous le confort de lecture,
     et le padding vertical donne aux liens une vraie cible tactile */
  .topbar nav{gap:18px;font-size:14.5px}
  .topbar nav a{white-space:nowrap;padding:7px 0}
  .topbar .lang{gap:8px;margin-left:0;padding-left:11px}
}

/* ===== Footer discret (partagé clair / sombre) =====
   Pas de liseré (trop proche des lignes de projets) : juste de l'air. */
/* Trois colonnes : le nom, les liens au centre, le rôle à droite. En flex
   avec espace-entre, les liens flottaient selon la longueur du texte de
   droite et les deux lignes de droite ne s'alignaient sur rien. */
.foot{max-width:var(--colonne);margin:0 auto;padding:clamp(56px,9vh,96px) clamp(20px,5vw,64px) 40px;display:grid;grid-template-columns:auto 1fr auto;align-items:start;gap:14px 28px;font-size:13.5px;line-height:1.6;color:var(--ink-faint)}
.foot .foot-name{font-family:var(--title-font),serif;font-style:italic;font-size:14.5px;color:var(--ink-soft)}
/* les pages projet sont claires elles aussi : rien à surcharger ici */

/* contact atteignable depuis n'importe quelle page, pas seulement À propos */
.foot-links{display:flex;flex-wrap:wrap;justify-content:center;gap:18px}
.foot-links a{color:var(--ink-soft);text-decoration:none;border-bottom:1px solid rgba(0,0,0,.2);padding-bottom:1px;transition:color .2s,border-color .2s}
.foot-links a:hover{color:var(--ink);border-color:var(--ink)}
@media (max-width:640px){.foot{grid-template-columns:1fr;gap:10px}.foot-links{gap:14px;justify-content:flex-start;order:3}}

/* ===== Halos réutilisables (mesh animé) =====
   #haze = calque déplacé par la souris (voir js/halos.js).
   Les instances de halos (positions, couleurs) sont définies
   par page dans home.css / projet.css. */
/* Un calque décoratif ne doit jamais recevoir un clic. Sur les pages
   « Qui suis-je » il est passé en `position:fixed` : il couvrait alors
   tout l'écran en permanence, pied de page compris, et comme le pied
   n'a pas de z-index, c'est lui qui recevait les clics. Aucun lien du
   pied n'y répondait. La règle est ici et pas dans about.css pour que
   le problème ne revienne pas le jour où une autre page passe le calque
   en `fixed`. La parallaxe continue de marcher : halos.js écoute la
   fenêtre et se contente d'écrire un transform sur ce calque. */
#haze{position:absolute;inset:-12%;z-index:0;pointer-events:none;
  transition:transform .25s ease-out}
/* pas de will-change ici : sur les pages projet les halos ne bougent
   plus, et forcer un calque permanent plein écran empêche le curseur de
   se mettre à jour au-dessus. Il est remis dans home.css, sur les seuls
   halos qui dérivent vraiment. */
.hblob{position:absolute;border-radius:50%;filter:blur(80px)}

@media (prefers-reduced-motion:reduce){
  .hblob{animation:none}
  .topbar,.topbar .b{transition:none}
}

/* ===== Lien d'évitement =====
   Il ne se voit qu'au clavier : à la première tabulation, il descend
   dans la page et donne accès au contenu sans traverser la barre du
   haut, puis le fil d'Ariane, à chaque page. */
.skip{position:absolute;left:16px;top:-60px;z-index:100;
  padding:10px 16px;border-radius:999px;
  background:var(--ink);color:var(--cream);font-size:14px;font-weight:600;
  text-decoration:none;transition:top .2s ease}
.skip:focus-visible{top:16px;outline:2px solid var(--cream);outline-offset:2px}

/* En dessous de 420 px, le sigle et la navigation ne tiennent plus côte à
   côte à leur taille normale. On réduit les deux d'un cran plutôt que de
   laisser le flex écraser le seul qui accepte de rétrécir. */
@media (max-width:420px){
  .topbar{gap:12px}
  .topbar .b{width:106px;height:26px}
  .topbar.small .b{width:94px;height:23px}
  .topbar nav{gap:13px;font-size:13.5px}
  .topbar .lang{gap:7px;padding-left:9px}
}

/* Les très petits écrans (iPhone SE de première génération, 320 px) : même
   à taille réduite, le sigle et les cinq liens ne tiennent pas. On resserre
   tout d'un dernier cran plutôt que de laisser la navigation déborder. */
@media (max-width:349px){
  .topbar{gap:10px;padding-left:12px;padding-right:12px}
  .topbar.small{padding-left:12px;padding-right:12px}
  .topbar .b{width:86px;height:21px}
  .topbar.small .b{width:78px;height:19px}
  .topbar nav{gap:10px;font-size:13px}
  .topbar .lang{gap:6px;padding-left:8px}
}

/* le CV dans la barre du haut : même traitement que les autres liens */
.topbar nav a.cv{white-space:nowrap}

/* la ligne « fait à la main » sous le rôle, en pied de page */
.foot-made{text-align:right;line-height:1.6}
@media (max-width:640px){.foot-made{text-align:left}}

/* Le repli quand JavaScript ne tourne pas : l'adresse en toutes lettres,
   avec « arobase » écrit, ce qu'un humain lit et qu'un robot ne reconnaît pas. */
.foot-mail{display:block;width:100%;font-size:13px;color:var(--ink-soft)}
.foot-mail b{font-weight:600;color:var(--ink)}


/* La sélection de texte prend la couleur du projet quand la page en a
   une, l'encre du site partout ailleurs. Deux lignes, et le site répond
   à un geste que personne ne pense à traiter. */
::selection{background:color-mix(in srgb,var(--pc,var(--ink)) 22%,transparent)}
::-moz-selection{background:color-mix(in srgb,var(--pc,var(--ink)) 22%,transparent)}

/* ============================================================
   L'IMPRESSION
   Un recruteur en grand groupe imprime encore. Sans cette feuille,
   une étude de cas sortait de l'imprimante avec la barre du haut
   posée en travers des images, dix-huit blocs restés invisibles
   parce qu'ils attendaient un défilement qui n'arrive jamais, et
   des pages de vide là où les dispositifs collants réservent leur
   course. C'est exactement le genre de moment que ce site dit
   savoir regarder, donc il valait mieux le regarder.
   ============================================================ */
@media print{
  /* 1 · Ce qui attendait le défilement s'affiche.
     Sans ça, la moitié d'une page projet sort blanche. */
  .rv,.ent,.in,.xp-fig,.pj-figure,.pj-prose,.pj-step{
    opacity:1!important;transform:none!important;visibility:visible!important;
    animation:none!important;transition:none!important}

  /* 2 · Le décor d'écran s'en va : navigation, sommaire, aperçus,
     commandes de lecture, invitations à cliquer. Rien de tout ça
     ne veut dire quelque chose sur du papier. */
  .topbar,.pj-toc,.scroll,.pj-scroll,.mouse,#hoverwrap,.zoom,.proj-bande,.proj-cta,
  .hblob,.mesh,
  .xp-vctrl,.xp-vplay,.xp-vtag,.xp-vprog,.xp-ecr-btn,.xp-ecr-big,
  .xp-ecr-prog,.xp-ecr-go,.xp-son,.xp-parc-note,.xp-trav-pied,
  .cx-proto-bar,.pj-proto-hint,.pj-proto-spacer,.cx-menu,[data-replay],
  .zoomable-wrap::after,.zoomable-box::after{display:none!important}

  /* 3 · Rien ne colle et rien ne réserve de course.
     Les dispositifs de défilement gardent leur écran en cours et
     rendent le reste de leur hauteur à la page. */
  .pj-proto-sticky,.dz-sticky,.xp-trav-scene,.xp-parc-scene,.sy-stage,
  .murw-scene{position:static!important;height:auto!important;overflow:visible!important}
  .dz,.sy,.xp-parc,.xp-trav,.pj-proto-pin,.murw,.murw.plein{
    height:auto!important;min-height:0!important}
  .pj-hero{min-height:0!important;padding-top:0!important}

  /* 4 · Le fond redevient blanc et l'encre noire. Les aplats sombres
     et les dégradés coûtent une cartouche pour rien. */
  html,body,.pj-hero,.s-hero{background:#fff!important}
  body{color:#111!important}
  .pj-behind,.pj-behind__box,.xp-chute,.hc{background:none!important;color:#111!important}

  /* 5 · On ne coupe pas une image en deux pages, ni un titre de sa
     première ligne de texte. */
  figure,.pj-figure,.xp-fig,.pj-step,blockquote,.pj-quote{break-inside:avoid;page-break-inside:avoid}
  h1,h2,h3,h4{break-after:avoid;page-break-after:avoid}
  img,video{max-width:100%!important;height:auto!important}

  /* 6 · L'adresse du site en pied de première page : une feuille
     imprimée circule sans son onglet. */
  .pj-hero .pj-meta::after,.hero .hero-facts::after{
    content:"marieliesse-desolages.com";display:block;margin-top:14px;
    font-size:11px;letter-spacing:.04em;color:#666}
}
