/* =========================================================================
   MALAN MONDE — la vitrine.
   =========================================================================

   ⚠️ UN TRANSFORM PAR COUCHE, PAS UN PAR IMAGE. La centaine de pieces du
   patchwork est posee en pixels dans un repere fixe (voir vitrine.js) ; ce
   sont les douze couches et les deux calques qui bougent. Sur le cabinet
   Demino, deplacer chaque image par `left` a chaque geste avait produit 158
   ecritures de style par image et un site injouable sur telephone.

   ⚠️ ON N'ECRIT RIEN QUI N'AIT ETE DEMANDE. Pas de sous-titre, pas de
   baseline, pas de pied de page, pas de nom a cote des boites. Le titre est
   « Malan Monde », en deux mots. Dans le livre : le compte a rebours, et
   rien d'autre.
   ========================================================================= */

@font-face {
  font-family: 'Grenze Gotisch';
  src: url('assets/fonts/grenze-gotisch-latin-500-normal.woff2?v=9b40e58241') format('woff2');
  font-weight: 500; font-display: swap;
}
@font-face {
  font-family: 'Grenze Gotisch';
  src: url('assets/fonts/grenze-gotisch-latin-700-normal.woff2?v=9b40e58241') format('woff2');
  font-weight: 700; font-display: swap;
}

:root {
  --encre:   #d9c69c;
  --or:      #d9ae5e;
  --or-clair:#f3dda6;
  --fond:    #0b0907;
}

* { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0;
  height: 100%; width: 100%;
  overflow: hidden;
  background: var(--fond);
  color: var(--encre);
  font: 16px/1.55 Georgia, 'Palatino Linotype', serif;
  -webkit-text-size-adjust: 100%;
}

body::before, body::after {
  content: ''; position: fixed; inset: 0; pointer-events: none;
}
body::before {
  background: url('assets/monde/parchemin.webp?v=9b40e58241') repeat;
  background-size: 700px 700px;
  opacity: .15;
  mix-blend-mode: screen;
  z-index: 1;
}
body::after {
  background:
    radial-gradient(132% 102% at 50% 46%, rgba(0,0,0,0) 56%, rgba(0,0,0,.24) 86%, rgba(0,0,0,.58) 100%),
    radial-gradient(64% 48% at 50% 52%, rgba(120,86,38,.08), rgba(0,0,0,0) 74%);
  z-index: 40;
}

#cadre { position: fixed; inset: 0; overflow: hidden; z-index: 2; }

#scene, #avant {
  position: absolute; top: 0; left: 0;
  transform-origin: 0 0;
}
#avant { z-index: 30; }

/* --------------------------------------------------------- LES COUCHES
   Douze, fabriquees par vitrine.js. Leur z-index est leur numero. */
/* ⚠️ `will-change` SUR LES 7 PLANS SEULEMENT, pas sur les 22 couches ni sur
   #scene / #avant : chaque calque prepare est une texture de la taille du
   decor, et c'est leur nombre qui faisait sauter des morceaux (13/09). */
.plan, .couche { position: absolute; inset: 0; }
html:not(.tactile) .plan { will-change: transform; }

.piece {
  position: absolute;
  display: block;
  transform-origin: 50% 50%;
  pointer-events: none;
  user-select: none;
}
.piece img { display: block; width: 100%; height: auto; }
/* une image arrive en fondu : en 4G, sans lui, la page clignote piece par
   piece. `opacity` seulement -- c'est le compositeur qui l'anime. */
.piece img { opacity: 0; transition: opacity .7s ease; }
.piece img.vu { opacity: 1; }

/* TROIS BANDES DE PROFONDEUR. Ce qui est loin est sombre et un peu fondu,
   ce qui est pres est net et porte une ombre franche. C'est ce degrade-la,
   plus que le mouvement, qui fait que le collage a de l'epaisseur. */
.piece.loin img {
  filter: sepia(.36) brightness(.55) contrast(1.06) saturate(.8)
          drop-shadow(0 6px 12px rgba(0,0,0,.6));
}
.piece.moyen img {
  filter: sepia(.24) brightness(.74) contrast(1.04)
          drop-shadow(0 8px 14px rgba(0,0,0,.62));
}
.piece.pres img {
  filter: sepia(.08) brightness(1) contrast(1.03)
          drop-shadow(0 11px 20px rgba(0,0,0,.7));
}

/* les pieces sans bord propre (un paysage, un objet sur son fond) : on les
   fond dans le decor au lieu de les poser dessus -- sans quoi le collage
   n'est qu'une grille de rectangles. */
.piece.fondu img {
  -webkit-mask-image: radial-gradient(ellipse 64% 64% at 50% 50%, #000 42%, transparent 92%);
          mask-image: radial-gradient(ellipse 64% 64% at 50% 50%, #000 42%, transparent 92%);
}

/* LE FOND DU FOND : la carte d'Angardie, en couche 1, floue et presque
   effacee. On ne doit pas la reconnaitre -- seulement sentir qu'il y a un
   pays dessous. */
.piece.fond img {
  filter: sepia(.55) brightness(.5) contrast(.72) saturate(.6) blur(1.6px);
  -webkit-mask-image: radial-gradient(ellipse 60% 60% at 50% 50%, #000 30%, transparent 88%);
          mask-image: radial-gradient(ellipse 60% 60% at 50% 50%, #000 30%, transparent 88%);
}

/* LES QUATRE ZONES. Elles ne sont pas du remplissage : ce sont elles, le
   monde. On les laisse nettes et claires, et le semis leur garde une
   clairiere (voir `reserves` dans vitrine.js). */
.piece.ville img {
  filter: sepia(.12) brightness(1.04) contrast(1.08)
          drop-shadow(0 14px 26px rgba(0,0,0,.8));
  -webkit-mask-image: radial-gradient(ellipse 62% 62% at 50% 50%, #000 46%, transparent 94%);
          mask-image: radial-gradient(ellipse 62% 62% at 50% 50%, #000 46%, transparent 94%);
}

/* LES LAMES. Rendues a part (rondes, epaisses, rutilantes -- celles de la
   boite de Sandras), elles TRAVERSENT le collage : elles percent les
   feuilles et sortent du cadre. Pas d'ombre portee : une aiguille d'acier
   n'a pas d'epaisseur de papier. */
.piece.lame img { width: 100%; height: 100%; }
.piece.lame img {
  filter: brightness(1.02) contrast(1.06) saturate(1.06)
          drop-shadow(0 3px 10px rgba(0,0,0,.9))
          drop-shadow(0 0 26px rgba(0,0,0,.6));
}

/* l'eventail du port : trois cartes tenues en main, donc un vrai bord */
.piece.carte img {
  border: 2px solid rgba(226,206,166,.55);
  box-shadow: 0 14px 26px rgba(0,0,0,.8);
  filter: sepia(.1) brightness(.95) contrast(1.04);
}

/* LES QUATRE BOITES. Grandes, en couche 2, presque entierement recouvertes
   par le collage : on n'en voit que des morceaux d'acier et de gravure. */
.piece.boite img {
  filter: brightness(.92) contrast(1.04)
          drop-shadow(0 18px 30px rgba(0,0,0,.85));
}
.piece.boite::before {
  content: ''; position: absolute; left: 50%; top: 48%;
  width: 112%; padding-bottom: 112%; margin: -56% 0 0 -56%;
  border-radius: 50%; z-index: -1;
  background: radial-gradient(circle, rgba(4,3,2,.7) 0%,
              rgba(4,3,2,.38) 42%, rgba(4,3,2,0) 70%);
}

/* ------------------------------------------------------------ LE TITRE */
#titre {
  position: absolute; left: 0; right: 0; top: 30px;
  z-index: 20; text-align: center; pointer-events: none;
}
/* ⚠️ LE TITRE EST UNE IMAGE (13/09/2026) : les lettres de l'extrapolation
   Flux du monogramme, detourees par outils/titre/detourer.py. Le texte reste
   dans `alt` pour les lecteurs d'ecran et les moteurs. */
#titre h1 { margin: 0; line-height: 0; }
#titre-img {
  display: inline-block; width: 651px; height: auto;   /* 740 - 12 % (14/09) */
  filter: drop-shadow(0 3px 2px rgba(0,0,0,.85)) drop-shadow(0 0 22px rgba(0,0,0,.9));
}
#titre::before {
  content: ''; position: absolute; left: 50%; top: -100px;
  width: 1100px; height: 320px; margin-left: -550px; z-index: -1;
  background: radial-gradient(ellipse 50% 50% at 50% 50%,
    rgba(6,4,3,.94) 0%, rgba(6,4,3,.7) 44%, rgba(6,4,3,0) 74%);
}

/* ------------------------------------------------------- LE TOURBILLON
   Le livre est l'oeil du maelstrom. Cinq spirales d'Archimede tournent
   autour de lui a des vitesses differentes ; le masque radial les efface au
   centre (ou le livre est) et sur le pourtour (ou le collage reprend), de
   sorte qu'on ne voit jamais ni leur depart ni leur fin.

   ⚠️ `will-change: transform` sur les bras, pas sur le conteneur : cinq
   groupes qui tournent en permanence, c'est cinq compositions GPU -- sans
   ca, le navigateur repeint la zone du livre soixante fois par seconde. */
#tourbillon {
  position: absolute; z-index: 19;
  width: 1200px; height: 1200px;
  transform: translate(-50%, -50%);
  pointer-events: none;
  -webkit-mask-image: radial-gradient(circle at 50% 50%,
    transparent 13%, #000 27%, #000 40%, transparent 50%);
          mask-image: radial-gradient(circle at 50% 50%,
    transparent 13%, #000 27%, #000 40%, transparent 50%);
}
#tourbillon svg { display: block; width: 100%; height: 100%; overflow: visible; }
#tourbillon .bras {
  transform-origin: 600px 600px;
  animation-name: tourne;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  will-change: transform;
}
@keyframes tourne { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  #tourbillon .bras { animation: none; }
}

/* ------------------------------------------------------------ LE LIVRE
   ⚠️ NI TRANCHE DOREE NI DOS NOIR. La premiere version dessinait un livre
   vu de trois quarts ; sans perspective sur le reste, les deux lisieres
   ressemblaient a deux barres posees au hasard. On garde les filets. */
#livre {
  position: absolute; z-index: 22;
  width: 340px; height: 430px;
  transform: translate(-50%, -50%);
}
#livre .forme { position: absolute; inset: 0; width: 100%; height: 100%; }
#livre .aura {
  position: absolute; left: 50%; top: 50%;
  width: 820px; height: 820px; margin: -410px 0 0 -410px;
  pointer-events: none;
  background: radial-gradient(circle,
    rgba(0,0,0,.76) 0%, rgba(10,7,4,.64) 30%,
    rgba(226,180,100,.26) 47%, rgba(180,120,40,.11) 63%, rgba(0,0,0,0) 79%);
  animation: respire 7s ease-in-out infinite;
}
@keyframes respire {
  0%, 100% { opacity: .82; transform: scale(1); }
  50%      { opacity: 1;   transform: scale(1.05); }
}
@media (prefers-reduced-motion: reduce) {
  #livre .aura, .porte::before { animation: none !important; }
}

/* ⚠️ EN DEUX COLONNES. Un livre est un rectangle DEBOUT : quatre nombres
   alignes en travers laissaient deux grandes zones noires, et le plat avait
   l'air vide. */
#rebours {
  position: absolute; inset: 14% 15% 14% 15%;
  display: grid; grid-template-columns: 1fr 1fr;
  align-items: center; justify-items: center;
  row-gap: 4%;
}
#rebours .bloc { display: flex; flex-direction: column; align-items: center; }
#rebours b {
  font-family: 'Grenze Gotisch', Georgia, serif;
  font-weight: 700; font-size: 72px; line-height: .92;
  color: var(--or-clair);
  font-variant-numeric: tabular-nums;
  text-shadow: 0 0 24px rgba(224,174,94,.5);
}
#rebours span {
  font-size: 12px; letter-spacing: .22em; text-transform: uppercase;
  color: #93794a; margin-top: 8px;
}

/* -------------------------------------------------- LA SIGNATURE, EN BAS
   Le monogramme en bas a droite, petit, comme une signature ; les reseaux a
   sa gauche. Un masque rond detache le sceau de son carre de parchemin. */
#signature {
  position: fixed; z-index: 45;
  right: 26px; bottom: 20px;
  display: flex; align-items: center; gap: 26px;
}
#reseaux { display: flex; align-items: center; gap: 20px; }
#reseaux a {
  display: block; width: 34px; height: 34px;
  opacity: .58; transition: opacity .25s, transform .25s;
  filter: drop-shadow(0 1px 6px #000) drop-shadow(0 0 16px #000);
}
#reseaux img { display: block; width: 100%; height: 100%; object-fit: contain; }
#reseaux a:hover, #reseaux a:focus-visible {
  opacity: 1; transform: translateY(-2px);
}
#reseaux a:focus-visible { outline: 1px solid var(--or); outline-offset: 5px; }

#sceau {
  width: 104px; height: auto;
  pointer-events: none;
  -webkit-mask-image: radial-gradient(circle at 50% 50%, #000 42%, transparent 60%);
          mask-image: radial-gradient(circle at 50% 50%, #000 42%, transparent 60%);
  filter: sepia(.26) brightness(1.2) contrast(1.22)
          drop-shadow(0 0 22px rgba(0,0,0,.95))
          drop-shadow(0 0 12px rgba(0,0,0,.9))
          drop-shadow(0 0 40px rgba(216,166,86,.3));
}

/* ------------------------------------------------------- LES DEUX PORTES
   ⚠️ PAS DE CADRE. Un rectangle borde a ete juge « pas elegant, trop
   carre ». Un nom grave, un filet a losange, une phrase, un chevron. La
   lisibilite vient d'un halo rond -- et ce halo RESPIRE, parce qu'une porte
   qui ne bouge pas au milieu d'un collage ne se voit pas. */
.porte {
  position: absolute; z-index: 24;
  width: 420px;
  display: block; text-decoration: none; text-align: center;
  padding: 12px 8px 14px;
  color: var(--encre);
  transform: translate(-50%, -50%);
  transition: transform .3s ease;
}
.porte::before {
  /* ⚠️ PAS DE MARGE EN POURCENTAGE POUR CENTRER VERTICALEMENT : une
     `margin-top` en % se calcule sur la LARGEUR du parent, pas sur sa
     hauteur. Avec `-170%` le halo partait 700 px trop haut et formait une
     tache noire dans le ciel (constate le 12/09). `top` et `height`, eux,
     se calculent bien tous les deux sur la hauteur. */
  content: ''; position: absolute; left: -35%; top: -120%;
  width: 170%; height: 340%;
  z-index: -1; pointer-events: none;
  /* ⚠️ MOITIE MOINS NOIR (12/09) : on doit voir un peu le collage derriere,
     meme si ca reste ombreux. */
  background: radial-gradient(ellipse 50% 50% at 50% 50%,
    rgba(3,2,1,.62) 0%, rgba(4,3,2,.58) 34%, rgba(6,4,3,.46) 50%,
    rgba(110,78,32,.16) 64%, rgba(4,3,2,0) 82%);
  animation: appel 5.5s ease-in-out infinite;
}
@keyframes appel {
  0%, 100% { opacity: .88; transform: scale(1); }
  50%      { opacity: 1;   transform: scale(1.05); }
}
#porte-cabinet::before { animation-delay: -2.7s; }

.porte .nom {
  display: block;
  font-family: 'Grenze Gotisch', Georgia, serif;
  font-size: 40px; letter-spacing: .03em; line-height: 1.05;
  color: var(--or);
  text-shadow: 0 2px 12px #000, 0 0 34px rgba(0,0,0,.9);
  transition: color .3s, text-shadow .3s;
}
.porte .filet {
  display: block; position: relative;
  height: 9px; margin: 11px auto 10px; width: 62%;
  transition: width .35s ease;
}
.porte .filet::before {
  content: ''; position: absolute; left: 0; right: 0; top: 4px; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(216,166,86,.85) 22%,
              rgba(216,166,86,.85) 78%, transparent);
}
.porte .filet::after {
  content: ''; position: absolute; left: 50%; top: 0;
  width: 9px; height: 9px; margin-left: -4.5px;
  background: var(--or); transform: rotate(45deg);
  box-shadow: 0 0 10px rgba(216,166,86,.6);
}
.porte .dit {
  display: block;
  font-size: 16px; line-height: 1.45;
  color: #c2ab80; font-style: italic;
  text-shadow: 0 1px 8px #000, 0 0 22px #000;
}
/* le chevron : la seule chose qui dise « ca s'ouvre ». Il avance au survol. */
.porte .fleche {
  display: block; margin: 12px auto 0; width: 46px; color: var(--or);
  opacity: .72; transition: opacity .3s, transform .3s ease;
}
.porte .fleche svg { display: block; width: 100%; height: auto;
  filter: drop-shadow(0 1px 6px #000); }

.porte:hover, .porte:focus-visible { transform: translate(-50%, -52%); }
.porte:hover .nom, .porte:focus-visible .nom {
  color: var(--or-clair);
  text-shadow: 0 2px 12px #000, 0 0 46px rgba(226,180,96,.7);
}
.porte:hover .filet, .porte:focus-visible .filet { width: 86%; }
.porte:hover .fleche, .porte:focus-visible .fleche {
  opacity: 1; transform: translateX(9px);
}
.porte:focus-visible { outline: none; }

/* =========================================================================
   PORTRAIT — le meme repere, mais tout ce qui porte du sens est agrandi.
   ========================================================================= */
body.portrait #titre { top: 44px; }
body.portrait #titre-img { width: 722px; }   /* 820 - 12 % */
body.portrait #titre::before {
  top: -120px; width: 1000px; height: 400px; margin-left: -500px;
}

body.portrait #livre { width: 580px; height: 730px; }
body.portrait #tourbillon { width: 1500px; height: 1500px; }
body.portrait #livre .aura {
  width: 1260px; height: 1260px; margin: -630px 0 0 -630px;
}
body.portrait #rebours { row-gap: 3%; }
body.portrait #rebours b { font-size: 124px; }
body.portrait #rebours span { font-size: 22px; margin-top: 14px; }

body.portrait #sceau { width: 76px; }
body.portrait #signature { right: 14px; bottom: 12px; gap: 16px; }
body.portrait #reseaux { gap: 14px; }
body.portrait #reseaux a { width: 26px; height: 26px; }

body.portrait .porte { width: 800px; padding: 12px 12px 14px; }
body.portrait .porte .nom { font-size: 54px; }
body.portrait .porte .filet { height: 16px; margin: 20px auto 18px; }
body.portrait .porte .filet::before { top: 7px; }
body.portrait .porte .filet::after { width: 16px; height: 16px; margin-left: -8px; }
body.portrait .porte .dit { font-size: 24px; }
body.portrait .porte .fleche { width: 64px; margin-top: 14px; }

/* =========================================================================
   TACTILE — un telephone n'a pas de souris : rien ne bouge, donc rien n'a a
   etre prepare pour bouger.
   ⚠️ Mesure du 13/09/2026 sur Android : avec les couches, le calque de
   parchemin en `mix-blend-mode` et les halos qui respirent, le telephone
   manquait de memoire graphique et laissait des rectangles vides a la place
   des images et du compte a rebours. Les spirales, elles, restent : cinq
   petits calques, c'est ce qu'il peut porter.
   ========================================================================= */
.tactile body::before { mix-blend-mode: normal; opacity: .06; }
.tactile #livre .aura, .tactile .porte::before { animation: none; }
.tactile .piece img { transition: none; }

/* la phrase du cabinet tient en deux lignes egales, pas une longue et un mot */
.porte .dit { text-wrap: balance; }
body.portrait .porte .dit { font-size: 26px; }
body.portrait .porte .filet { margin: 16px auto 14px; }
body.portrait .porte .fleche { margin-top: 10px; }

/* ⚠️ ILLISIBLE SUR UN PETIT PORTABLE (15/09). Le calque #avant est reduit
   pour tenir dans l'ecran. En paysage, vitrine.js pose --t-nom / --t-dit a
   l'echelle reelle (voir caler()) ; la porte s'elargit avec son texte. */
body:not(.portrait):not(.carre) .porte .nom { font-size: var(--t-nom, 40px); }
body:not(.portrait):not(.carre) .porte .dit { font-size: var(--t-dit, 16px); }
body:not(.portrait):not(.carre) .porte { width: max(420px, calc(var(--t-dit, 16px) * 27)); }
