/* ==========================================================================
   EMEK BATI — Maçonnerie générale : Chantier en cours
   Feuille de style de la page unique de chantier et de la page 404.
   Zéro dépendance, compatible CSP stricte (style-src 'self').
   ========================================================================== */

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/assets/fonts/inter-latin.woff2') format('woff2');
  unicode-range: U+00??, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --c-nuit: #16243A;
  --c-bleu: #2F4B72;
  --c-bleu-fonce: #24395A;
  --c-bleu-clair: #5B7CA6;
  --c-brique: #B4523A;
  --c-brique-fonce: #93412D;
  --c-brique-clair: #E08A6B;
  --c-ardoise: #8195A6;
  --c-acier: #5F7185;
  --c-jaune: #F2B33D;
  --c-jaune-fonce: #D08E22;
  --c-bois: #C98D5A;
  --c-bois-fonce: #8E5E3D;
  --c-beton: #A9B3BC;
  --c-beton-clair: #C7CFD6;
  --c-terre: #9A6B45;
  --c-terre-fonce: #7A5233;
  --c-blanc: #FFFFFF;
  --c-fond: #F4F6F8;
  --c-trait: #DDE3EA;
  --c-texte: #16243A;
  --c-texte-muet: #5F7185;
  --c-wa: #25D366;
  --c-erreur: #DC2626;
  --c-succes: #15803D;
  --font-sans: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

/* ── Reset & Bases ───────────────────────────────────────────────────────── */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  scroll-behavior: smooth;
  font-family: var(--font-sans);
  color: var(--c-texte);
  background: var(--c-nuit);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  min-height: 100vh;
  overflow-x: hidden;
  background: #FFFFFF;
  color: var(--c-texte);
}

img, svg {
  display: block;
}

[hidden] {
  display: none !important;
}

.visuellement-cache {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.evitement {
  position: absolute;
  left: -9999px;
  top: 1rem;
  z-index: 100;
  background: var(--c-bleu);
  color: #FFFFFF;
  padding: 0.75rem 1.25rem;
  border-radius: 0.5rem;
  font-weight: 700;
  text-decoration: none;
}
.evitement:focus {
  left: 1rem;
}

/* ── En-tête (Sticky Header) ─────────────────────────────────────────────── */
.entete {
  position: sticky;
  top: 0;
  z-index: 40;
  width: 100%;
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid rgba(47, 75, 114, 0.12);
  transition: background-color 0.25s ease, box-shadow 0.25s ease;
}

.entete-dedans {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0.75rem 1.25rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.marque {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  text-decoration: none;
  color: inherit;
}

/* Le logo du propriétaire, sur son fond blanc : il se pose tel quel sur le
   blanc de l'en-tête. La largeur suit ; build/logo.emekbati.fr.mjs fabrique
   le fichier à trois fois cette hauteur. */
.marque-logo {
  width: auto;
  height: 44px;
  flex-shrink: 0;
  /* L'en-tête est blanc à 94 % : au-dessus du pied de page, sombre, il
     grise un peu, et le fond blanc du logo y ferait un rectangle plus clair.
     En « multiply », le blanc de l'image prend la teinte de ce qui est
     dessous — il disparaît — et les couleurs ne bougent pas. */
  mix-blend-mode: multiply;
}

.marque-texte {
  display: flex;
  flex-direction: column;
}

.marque-nom {
  font-weight: 800;
  font-size: 1.25rem;
  line-height: 1.1;
  letter-spacing: -0.025em;
  color: var(--c-bleu);
}

.marque-metier {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-weight: 600;
  color: var(--c-ardoise);
}

.entete-actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.interrupteur {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.45rem 0.85rem;
  border-radius: 9999px;
  border: 1px solid var(--c-trait);
  background: #FFFFFF;
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--c-acier);
  cursor: pointer;
  transition: all 0.2s ease;
}
.interrupteur:hover {
  background: #F4F6F8;
  border-color: var(--c-ardoise);
  color: var(--c-nuit);
}
.interrupteur svg {
  width: 14px;
  height: 14px;
  fill: currentColor;
}
.interrupteur .ico-pause {
  display: block;
  stroke: currentColor;
  stroke-width: 3.5;
  stroke-linecap: round;
}
.interrupteur .ico-lecture {
  display: none;
}
html:not(.anime) .interrupteur .ico-pause {
  display: none;
}
html:not(.anime) .interrupteur .ico-lecture {
  display: block;
}

.bouton-tel {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 1.05rem;
  border-radius: 9999px;
  background: var(--c-bleu);
  color: #FFFFFF;
  font-weight: 700;
  font-size: 0.9rem;
  text-decoration: none;
  transition: background-color 0.2s ease, transform 0.15s ease;
}
.bouton-tel:hover {
  background: var(--c-bleu-fonce);
  transform: translateY(-1px);
}
.bouton-tel svg {
  width: 15px;
  height: 15px;
  fill: currentColor;
}

/* Rien dans l'en-tête ne passe à la ligne : un numéro coupé en cinq lignes
   en ferait un bandeau de 150 px de haut. */
.marque-nom,
.marque-metier,
.interrupteur,
.bouton-tel {
  white-space: nowrap;
}

/* Sur téléphone, le bouton d'appel de l'en-tête s'efface : la barre du bas
   (.barre-appel) le tient déjà sous le pouce. */
@media (max-width: 599px) {
  .entete-dedans {
    padding: 0.6rem 1rem;
  }
  .marque {
    gap: 0.6rem;
  }
  .marque-logo {
    height: 37px;
  }
  .marque-nom {
    font-size: 1.08rem;
  }
  .marque-metier {
    font-size: 0.62rem;
    letter-spacing: 0.1em;
  }
  .bouton-tel {
    display: none;
  }
}
@media (max-width: 349px) {
  .marque-metier {
    display: none;
  }
}

/* ── Le Ciel & Accueil (Haut de page) ─────────────────────────────────────── */
.ciel {
  position: relative;
  background: linear-gradient(180deg, #C5E4F8 0%, #D8ECF9 40%, #EBF4FB 75%, #F7FAFD 100%);
  overflow: hidden;
  /* Largeur du dessin de la grue. Tout ce qui doit s'aligner sur elle s'en
     déduit : le prolongement du fût, la place laissée au texte. */
  --grue-l: clamp(340px, 44vw, 620px);
}

.ciel-deco {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1;
}

/* Les nuages tiennent dans la bande de ciel libre au-dessus du titre, ou
   derrière la grue : jamais derrière le texte. Les hauteurs sont en rem et
   non en % : .ciel englobe aussi l'étage du toit, 30 % de sa hauteur tombe
   n'importe où. */
.nuage-ciel {
  position: absolute;
  height: auto;
  fill: #FFFFFF;
  opacity: 0.85;
}
.nc1 {
  top: 0.8rem;
  left: 5%;
  width: 104px;
}
.nc2 {
  top: 1.1rem;
  left: 37%;
  width: 124px;
  opacity: 0.7;
}
.nc3 {
  top: 14rem;
  right: 6%;
  width: 150px;
  opacity: 0.75;
}

.oiseaux {
  position: absolute;
  top: 2.2rem;
  left: 20%;
  width: 60px;
  height: auto;
  fill: none;
  stroke: var(--c-bleu-clair);
  stroke-width: 2.2;
  stroke-linecap: round;
  opacity: 0.75;
}

/* La grue se dresse DERRIÈRE la maison : son cadre court sur toute la hauteur
   du ciel, mais l'étage du toit (.ciel .etage, plus bas) passe devant. */
.grue-cadre {
  position: absolute;
  top: 0;
  right: 2%;
  width: var(--grue-l);
  height: 100%;
  pointer-events: none;
  z-index: 1;
}

.grue {
  width: 100%;
  height: auto;
  display: block;
}

/* Le fût, sous le dessin. Le SVG s'arrête à 600 de haut ; le bandeau, lui,
   peut être plus long. Cette bande reprend le treillis du dessin — deux
   montants, une diagonale et une traverse par cellule de 36 — à la même
   échelle, en partant de la dernière cellule entière (y = 592) : le raccord
   ne se voit pas. Les cotes sont celles du viewBox (560 de large). */
.grue-fut {
  position: absolute;
  top: calc(var(--grue-l) * 592 / 560);
  left: calc(var(--grue-l) * 259.5 / 560);
  width: calc(var(--grue-l) * 41 / 560);
  bottom: 0;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='41' height='36' viewBox='0 0 41 36'%3E%3Cpath d='M2.5 0V36M38.5 0V36' stroke='%23F2B33D' stroke-width='5'/%3E%3Cpath d='M2.5 0L38.5 36M2.5 0H38.5M2.5 36H38.5' stroke='%23D08E22' stroke-width='2.5' fill='none'/%3E%3C/svg%3E") top center / 100% auto repeat-y;
}

.accueil {
  position: relative;
  z-index: 3;
  max-width: 1200px;
  margin: 0 auto;
  padding: clamp(5rem, 8vw, 6.5rem) 1.25rem clamp(2.5rem, 6vw, 4.5rem);
  min-height: 68vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* Le texte s'arrête avant le fût de la grue, planté au milieu de son cadre. */
.accueil-texte {
  max-width: min(600px, calc(100% - var(--grue-l) * 0.5 - 2vw - 1.5rem));
}

/* Sur téléphone, plus de place pour une grue à côté du texte. Elle passe au
   bord droit, retournée : le fût longe l'écran, la flèche et sa palette
   survolent le titre, qui commence dessous. Le fût étant au milieu du cadre,
   le retournement ne le déplace pas. */
@media (max-width: 759px) {
  .ciel {
    --grue-l: 300px;
  }
  .grue-cadre {
    right: calc(18px - var(--grue-l) / 2);
    transform: scaleX(-1);
  }
  .accueil {
    padding: 12.6rem 2.75rem 2.5rem 1.25rem;
    min-height: 0;
    justify-content: flex-start;
  }
  .accueil-texte {
    max-width: none;
  }
  .nc1 {
    top: 1.4rem;
    left: 6%;
    width: 84px;
  }
  .nc2 {
    top: 7rem;
    left: 26%;
    width: 96px;
  }
  .nc3 {
    display: none;
  }
  .oiseaux {
    top: 5.4rem;
    left: 8%;
    width: 48px;
  }
}

.surtitre {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 0.82rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--c-brique);
  margin-bottom: 1.1rem;
}

.gyrophare {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #E5484D;
  box-shadow: 0 0 0 0 rgba(229, 72, 77, 0.7);
  display: inline-block;
}

h1#titre {
  font-size: clamp(2.2rem, 5.2vw, 3.8rem);
  font-weight: 900;
  line-height: 1.08;
  letter-spacing: -0.03em;
  color: var(--c-nuit);
  margin-bottom: 1.25rem;
}
/* Téléphone : « Le site se construit, » doit tenir sur une ligne à côté du
   fût, sinon le titre en prend trois. */
@media (max-width: 759px) {
  h1#titre {
    font-size: clamp(1.55rem, 8.2vw, 2.4rem);
  }
}

h1#titre .accent {
  color: var(--c-bleu);
}

.chapo {
  font-size: clamp(1.05rem, 1.8vw, 1.22rem);
  color: var(--c-acier);
  line-height: 1.55;
  margin-bottom: 2rem;
  max-width: 520px;
}

.accueil-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  align-items: center;
  margin-bottom: 1.5rem;
}

.bouton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  padding: 0.85rem 1.65rem;
  border-radius: 0.75rem;
  font-family: inherit;
  font-weight: 700;
  font-size: 0.98rem;
  text-decoration: none;
  cursor: pointer;
  transition: all 0.2s ease;
}

.bouton-plein {
  background: var(--c-bleu);
  color: #FFFFFF;
  border: 1.5px solid var(--c-bleu);
  box-shadow: 0 4px 14px rgba(47, 75, 114, 0.22);
}
.bouton-plein:hover {
  background: var(--c-bleu-fonce);
  border-color: var(--c-bleu-fonce);
  transform: translateY(-2px);
  box-shadow: 0 6px 20px rgba(47, 75, 114, 0.3);
}

.bouton-clair {
  background: #FFFFFF;
  color: var(--c-bleu);
  border: 1.5px solid var(--c-trait);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}
.bouton-clair:hover {
  border-color: var(--c-bleu);
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(47, 75, 114, 0.12);
}
.bouton-clair svg {
  width: 17px;
  height: 17px;
  fill: currentColor;
}

.calme-note {
  font-size: 0.85rem;
  color: var(--c-acier);
  background: rgba(255, 255, 255, 0.85);
  padding: 0.6rem 0.9rem;
  border-radius: 0.5rem;
  border-left: 3px solid var(--c-jaune);
  margin-top: 1rem;
}

.lien-bouton {
  background: none;
  border: none;
  color: var(--c-bleu);
  font-weight: 700;
  text-decoration: underline;
  cursor: pointer;
  font-family: inherit;
  font-size: inherit;
  padding: 0;
}

.descendre {
  align-self: flex-start;
  margin-top: 1.5rem;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--c-acier);
  font-weight: 700;
  font-size: 0.88rem;
  text-decoration: none;
  transition: color 0.2s ease, transform 0.2s ease;
}
.descendre:hover {
  color: var(--c-bleu);
  transform: translateY(3px);
}
.descendre svg {
  width: 18px;
  height: 18px;
  stroke: currentColor;
  stroke-width: 2.2;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ── Les Étages de la Maison en coupe ────────────────────────────────────── */
.etage {
  position: relative;
  width: 100%;
  border-top: 1px solid rgba(22, 36, 58, 0.08);
  overflow: hidden;
}

/* L'étage du toit partage le ciel avec la grue, et passe devant elle. */
.ciel .etage {
  z-index: 2;
}

.piece {
  max-width: 1200px;
  margin: 0 auto;
  padding: 3rem 1.25rem;
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  align-items: center;
}

@media (min-width: 960px) {
  .piece {
    grid-template-columns: 340px 1fr;
    gap: 3.5rem;
    padding: 4.5rem 1.25rem;
  }
}

/* Tant que l'écran n'est pas assez large pour le loger dans la marge, le
   monte-charge (fixe, à droite) passerait sur les scènes. Même réserve plus
   bas pour la fiche du bureau. */
@media (min-width: 1024px) and (max-width: 1439px) {
  .piece {
    padding-right: 6.75rem;
  }
}

.panneau {
  max-width: 380px;
}

.panneau-niveau {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  font-size: 0.82rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--c-acier);
  margin-bottom: 0.75rem;
}

.badge {
  background: var(--c-bleu);
  color: #FFFFFF;
  padding: 0.2rem 0.65rem;
  border-radius: 0.4rem;
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0;
}

.panneau h2 {
  font-size: clamp(1.7rem, 3.2vw, 2.3rem);
  font-weight: 800;
  color: var(--c-nuit);
  line-height: 1.15;
  letter-spacing: -0.025em;
  margin-bottom: 0.95rem;
}

.panneau p {
  font-size: 1.02rem;
  color: var(--c-acier);
  line-height: 1.6;
}

.scene {
  width: 100%;
  height: auto;
  display: block;
  border-radius: 1.25rem;
  background: #FFFFFF;
  box-shadow: 0 12px 36px rgba(22, 36, 58, 0.08), 0 1px 3px rgba(0, 0, 0, 0.04);
}

/* Thèmes spécifiques par étage */
.etage-toit {
  background: linear-gradient(180deg, #F7FAFD 0%, #FFFFFF 100%);
}
.etage-toit .scene {
  background: linear-gradient(180deg, #E6F3FB 0%, #F8FBFE 60%, #FFFFFF 100%);
}
.etage-toit .badge {
  background: var(--c-bois-fonce);
}

.etage-murs {
  background: #F9F9FA;
}
.etage-murs .badge {
  background: var(--c-brique);
}

.etage-dalle {
  background: #F1F4F7;
}
.etage-dalle .badge {
  background: var(--c-bleu);
}

.etage-fondations {
  background: #EBE5DC;
}
.etage-fondations .badge {
  background: var(--c-terre-fonce);
}
.etage-fondations .scene {
  background: var(--c-terre);
}

/* Textes dans les SVG. Les tailles sont en unités du dessin, pas de l'écran.
   Ces règles valent animation coupée comme en marche : sans elles, les « z »
   du chat et les notes de la radio retombent sur la police par défaut. */
.panneau-texte,
.bulle-texte,
.bureau-texte,
.note,
.zzz {
  font-family: var(--font-sans);
  font-weight: 800;
  font-size: 13px;
  fill: var(--c-bleu);
}
.bulle-texte {
  font-size: 17px;
}
/* L'enseigne du bungalow fait 44 de large : « BUREAU » doit y tenir. */
.bureau-texte {
  font-size: 8.5px;
  letter-spacing: 0.3px;
  fill: #FFFFFF;
}
.note {
  font-size: 20px;
  fill: var(--c-bleu-clair);
}
.zzz {
  fill: var(--c-acier);
}
.zzz.z1 {
  font-size: 14px;
}
.zzz.z2 {
  font-size: 11px;
  fill: var(--c-ardoise);
}

/* ── La Palissade de Chantier (Séparateur) ────────────────────────────────── */
.palissade {
  background: repeating-linear-gradient(
    90deg,
    #A7734C 0px,
    #A7734C 32px,
    #8E5E3D 32px,
    #8E5E3D 36px,
    #B68058 36px,
    #B68058 68px,
    #7A5233 68px,
    #7A5233 72px
  );
  padding: 2.2rem 1.25rem;
  border-top: 5px solid #6E4A2F;
  border-bottom: 5px solid #5B3B22;
  text-align: center;
  color: #FFFFFF;
  box-shadow: inset 0 4px 12px rgba(0, 0, 0, 0.28);
}

.palissade-planches {
  display: inline-block;
  background: var(--c-brique);
  padding: 0.75rem 1.75rem;
  border-radius: 0.4rem;
  font-weight: 900;
  font-size: 1.05rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  border: 2.5px dashed #FFFFFF;
  transform: rotate(-1.2deg);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.25);
}

.palissade-sauf {
  display: block;
  font-size: 0.8rem;
  text-transform: lowercase;
  font-style: italic;
  font-weight: 600;
  letter-spacing: 0;
  opacity: 0.92;
  margin-top: 0.15rem;
}

/* ── Le Bureau de Chantier & Formulaire (#contact) ────────────────────────── */
.bureau {
  position: relative;
  background: #EDF1F5;
  border-top: 1px solid rgba(22, 36, 58, 0.08);
}

.bureau-dedans {
  max-width: 1200px;
  margin: 0 auto;
  padding: 4.5rem 1.25rem 5.5rem;
  display: grid;
  grid-template-columns: 1fr;
  gap: 3.5rem;
  align-items: start;
}

@media (min-width: 960px) {
  .bureau-dedans {
    grid-template-columns: 1fr 1.2fr;
    gap: 4rem;
  }
}

/* La place du monte-charge, comme pour .piece. */
@media (min-width: 1024px) and (max-width: 1439px) {
  .bureau-dedans {
    padding-right: 6.75rem;
  }
}

.bureau-accueil h2 {
  font-size: clamp(1.8rem, 3.5vw, 2.5rem);
  font-weight: 800;
  color: var(--c-nuit);
  line-height: 1.15;
  letter-spacing: -0.025em;
  margin-bottom: 0.95rem;
}

.bureau-chapo {
  font-size: 1.05rem;
  color: var(--c-acier);
  line-height: 1.6;
  margin-bottom: 2rem;
}

.joindre {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  margin-bottom: 2.5rem;
}

.joindre-lien {
  display: flex;
  align-items: center;
  gap: 1.1rem;
  padding: 0.9rem 1.25rem;
  background: #FFFFFF;
  border-radius: 0.95rem;
  border: 1.5px solid var(--c-trait);
  text-decoration: none;
  color: inherit;
  transition: all 0.2s ease;
  box-shadow: 0 2px 8px rgba(22, 36, 58, 0.03);
}
.joindre-lien:hover {
  border-color: var(--c-bleu);
  transform: translateY(-2px);
  box-shadow: 0 8px 20px rgba(47, 75, 114, 0.1);
}

.joindre-ico {
  width: 44px;
  height: 44px;
  border-radius: 0.75rem;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.joindre-ico svg {
  width: 22px;
  height: 22px;
  fill: #FFFFFF;
}

.joindre-ico-tel {
  background: var(--c-bleu);
}
.joindre-ico-wa {
  background: var(--c-wa);
}
.joindre-ico-mail {
  background: var(--c-brique);
}

.joindre-titre {
  font-weight: 800;
  font-size: 0.98rem;
  color: var(--c-nuit);
  display: block;
}

.joindre-detail {
  font-size: 0.85rem;
  color: var(--c-acier);
  display: block;
}

.bungalow {
  width: 100%;
  max-width: 380px;
  height: auto;
  display: block;
  margin-top: 1rem;
}

/* ── La Fiche de Chantier (Presse-papier & Formulaire) ───────────────────── */
.fiche {
  position: relative;
  background: #FFFFFF;
  border-radius: 1.25rem;
  padding: 3rem 2.2rem 2.5rem;
  box-shadow: 0 16px 40px rgba(22, 36, 58, 0.1), 0 2px 4px rgba(0, 0, 0, 0.04);
  border: 2px solid #E2E8F0;
}

.fiche-pince {
  position: absolute;
  top: -15px;
  left: 50%;
  transform: translateX(-50%);
  width: 74px;
  height: 28px;
  background: linear-gradient(180deg, #D08E22 0%, #A66E15 100%);
  border-radius: 5px;
  border: 2px solid #7E5109;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.22);
}
.fiche-pince::after {
  content: '';
  position: absolute;
  top: -11px;
  left: 17px;
  right: 17px;
  height: 11px;
  border: 3.5px solid #7E5109;
  border-bottom: none;
  border-radius: 8px 8px 0 0;
}

.fiche-titre {
  font-size: 1.25rem;
  font-weight: 900;
  color: var(--c-bleu);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border-bottom: 2px solid #F1F5F9;
  padding-bottom: 0.75rem;
  margin-bottom: 1.75rem;
}

.paire {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.1rem;
  margin-bottom: 1.1rem;
}

@media (min-width: 600px) {
  .paire {
    grid-template-columns: 1fr 1fr;
  }
}

.champ {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-bottom: 1.1rem;
}
/* Dans une paire, c'est la paire qui porte la marge : sinon elle compte
   double, et les rangées du formulaire s'écartent. */
.paire .champ {
  margin-bottom: 0;
}

.champ label {
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--c-nuit);
}

.requis {
  color: var(--c-brique);
  font-weight: 800;
}

.champ input,
.champ select,
.champ textarea {
  width: 100%;
  border-radius: 0.75rem;
  border: 1.5px solid var(--c-trait);
  padding: 0.8rem 1rem;
  font-size: 0.95rem;
  font-family: inherit;
  background: #F9FBFC;
  color: var(--c-nuit);
  transition: border-color 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease;
}

.champ input:focus,
.champ select:focus,
.champ textarea:focus {
  outline: none;
  border-color: var(--c-bleu);
  box-shadow: 0 0 0 4px rgba(47, 75, 114, 0.12);
  background: #FFFFFF;
}

.champ textarea {
  resize: vertical;
  min-height: 110px;
}

.aide {
  font-size: 0.8rem;
  color: var(--c-acier);
  margin-top: -0.6rem;
  margin-bottom: 1.1rem;
}

.erreur {
  font-size: 0.85rem;
  color: var(--c-erreur);
  font-weight: 700;
  margin-top: -0.6rem;
  margin-bottom: 1.1rem;
}

.etat {
  padding: 1.1rem 1.3rem;
  border-radius: 0.85rem;
  margin-bottom: 1.75rem;
  font-size: 0.92rem;
}
.etat-titre {
  font-weight: 800;
  font-size: 1rem;
  margin-bottom: 0.25rem;
}
.etat-ok {
  background: #ECFDF5;
  border: 1.5px solid #A7F3D0;
  color: #065F46;
}
.etat-attention {
  background: #FFFBEB;
  border: 1.5px solid #FDE68A;
  color: #92400E;
}
.etat-erreur {
  background: #FEF2F2;
  border: 1.5px solid #FECACA;
  color: #991B1B;
}

.bouton-envoi {
  width: 100%;
  padding: 1rem;
  font-size: 1.05rem;
  margin-top: 0.5rem;
}
/* La note sous le bouton. La marge négative de .aide la rapproche du champ
   qu'elle commente ; ici elle n'en commente aucun, et cette marge la faisait
   monter sur le bouton. */
.bouton-envoi + .aide {
  margin-top: 1rem;
  margin-bottom: 0;
}

.piege {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ── Le Pied de Page ─────────────────────────────────────────────────────── */
.pied {
  background: var(--c-nuit);
  color: var(--c-ardoise);
  padding: 3rem 1.25rem calc(4.5rem + env(safe-area-inset-bottom, 0px));
  text-align: center;
  font-size: 0.88rem;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.pied a {
  color: #FFFFFF;
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ── Le Monte-charge (Ascenseur d'étages sur grand écran) ─────────────────── */
@media (max-width: 1023px) {
  .monte-charge {
    display: none !important;
  }
}

@media (min-width: 1024px) {
  .monte-charge {
    position: fixed;
    right: 1.5rem;
    top: 50%;
    transform: translateY(-50%);
    z-index: 50;
    background: rgba(22, 36, 58, 0.88);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    padding: 0.85rem 0.6rem;
    border-radius: 2rem;
    border: 2px solid var(--c-jaune);
    box-shadow: 0 12px 36px rgba(0, 0, 0, 0.35);
  }

  .monte-charge ol {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    position: relative;
  }

  .monte-charge li a {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    text-decoration: none;
    color: #FFFFFF;
    padding: 0.35rem 0.55rem;
    border-radius: 9999px;
    position: relative;
    z-index: 2;
    transition: background-color 0.2s ease;
  }

  .mc-code {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.15);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 800;
    font-size: 0.82rem;
    color: #FFFFFF;
    transition: background-color 0.2s ease, color 0.2s ease;
  }

  .mc-nom {
    font-size: 0.78rem;
    font-weight: 700;
    white-space: nowrap;
    opacity: 0;
    max-width: 0;
    overflow: hidden;
    transition: opacity 0.22s ease, max-width 0.25s ease;
  }

  .monte-charge:hover .mc-nom,
  .monte-charge:focus-within .mc-nom {
    opacity: 1;
    max-width: 110px;
    padding-right: 0.4rem;
  }

  .monte-charge a.actif .mc-code {
    background: var(--c-jaune);
    color: var(--c-nuit);
  }

  .mc-code-bureau {
    background: rgba(180, 82, 58, 0.6);
  }
  .monte-charge a.actif .mc-code-bureau {
    background: var(--c-brique-clair);
    color: #FFFFFF;
  }

  /* La cabine : un anneau de 32 autour de la pastille de 28 de l'étage en
     cours. Son origine est le coin de la liste (le remplissage du
     monte-charge), décalé du remplissage du lien moins les 2 px de débord de
     l'anneau ; assets/chantier.js n'a plus qu'à la descendre. */
  .mc-cabine {
    position: absolute;
    left: calc(0.6rem + 0.55rem - 2px);
    top: 0.85rem;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    border: 2px solid var(--c-jaune);
    pointer-events: none;
    transition: transform 0.32s cubic-bezier(0.2, 0.8, 0.3, 1);
    z-index: 1;
  }
}

/* ── Barre d'Appel Mobile (Sticky Footer) ─────────────────────────────────── */
@media (min-width: 1024px) {
  .barre-appel {
    display: none !important;
  }
}

@media (max-width: 1023px) {
  .barre-appel {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 50;
    background: rgba(255, 255, 255, 0.95);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-top: 1px solid var(--c-trait);
    padding: 0.65rem 1rem calc(0.65rem + env(safe-area-inset-bottom, 0px));
    display: flex;
    gap: 0.75rem;
    box-shadow: 0 -4px 18px rgba(0, 0, 0, 0.08);
  }

  .barre-appel-tel {
    flex: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    background: var(--c-bleu);
    color: #FFFFFF;
    padding: 0.75rem;
    border-radius: 0.65rem;
    font-weight: 700;
    font-size: 0.92rem;
    text-decoration: none;
    transition: background-color 0.2s ease;
  }
  .barre-appel-tel svg {
    width: 18px;
    height: 18px;
    fill: currentColor;
  }

  .barre-appel-ecrire {
    flex: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: #FAFAFB;
    color: var(--c-bleu);
    border: 1.5px solid var(--c-trait);
    padding: 0.75rem;
    border-radius: 0.65rem;
    font-weight: 700;
    font-size: 0.92rem;
    text-decoration: none;
    transition: border-color 0.2s ease;
  }
}

/* ── Page 404 (Perdu) ────────────────────────────────────────────────────── */
.page-404 {
  background: linear-gradient(180deg, #F8FAFD 0%, #EDF2F7 100%);
  min-height: 100vh;
}

.page-404 .page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.page-404 .perdu,
.perdu-main {
  flex: 1;
  min-height: 70vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3rem 1.25rem;
}

.perdu-contenu,
.perdu-cadre {
  text-align: center;
  max-width: 520px;
  background: #FFFFFF;
  border-radius: 1.5rem;
  padding: 3rem 2.2rem 2.5rem;
  box-shadow: 0 16px 40px rgba(22, 36, 58, 0.08);
  border: 1.5px solid var(--c-trait);
}

.perdu-dessin {
  width: 260px;
  height: auto;
  margin: 0 auto 1.5rem;
  display: block;
}

.perdu-point {
  font-size: 38px;
  font-weight: 900;
  fill: var(--c-brique);
  font-family: var(--font-sans);
}

.perdu-contenu h1,
.perdu-cadre h1 {
  font-size: 1.85rem;
  font-weight: 800;
  color: var(--c-nuit);
  margin-bottom: 0.75rem;
  line-height: 1.2;
}

.perdu-contenu .chapo,
.perdu-cadre p {
  color: var(--c-acier);
  font-size: 1rem;
  line-height: 1.6;
  margin-bottom: 2rem;
}

.perdu-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  justify-content: center;
  align-items: center;
  margin-top: 1.5rem;
}

/* ==========================================================================
   MOTEUR D'ANIMATION DU CHANTIER
   ========================================================================== */

/* TROIS ÉTATS, UNE SEULE RÈGLE DU JEU

   Sans la classe « anime » sur <html> (pas de JavaScript, animations coupées
   par le système, bouton Pause) : la maison s'affiche TERMINÉE et immobile.
   C'est l'état de repos, celui que le dessin décrit tel quel.

   Avec « anime » : chaque étage part vide. Ses boucles (un bras qui martèle,
   la bétonnière) tournent tant qu'il est à l'écran — classe « en-vue » — et
   sa construction se joue une fois, quand la scène est vraiment visible —
   classe « monte ». Les deux sont posées par assets/chantier.js, et retirées
   quand l'étage sort de l'écran : y revenir rejoue le chantier.

   Les retards voyagent avec les pièces : le générateur leur donne un rang
   (i0 à i15, j0 à j7), traduit ici en variables. Une règle par scène suffit
   alors, au lieu d'une par brique. */
.i0 { --i: 0; } .i1 { --i: 1; } .i2 { --i: 2; } .i3 { --i: 3; }
.i4 { --i: 4; } .i5 { --i: 5; } .i6 { --i: 6; } .i7 { --i: 7; }
.i8 { --i: 8; } .i9 { --i: 9; } .i10 { --i: 10; } .i11 { --i: 11; }
.i12 { --i: 12; } .i13 { --i: 13; } .i14 { --i: 14; } .i15 { --i: 15; }
.j0 { --j: 0; } .j1 { --j: 1; } .j2 { --j: 2; } .j3 { --j: 3; }
.j4 { --j: 4; } .j5 { --j: 5; } .j6 { --j: 6; } .j7 { --j: 7; }

/* Éléments éphémères (la coulée de béton, le chat qui marche, les éclats du
   marteau) : ils n'existent que le temps de leur animation. Au repos, on ne
   les voit pas — sinon la scène de la dalle montre deux chats. */
.ephemere {
  opacity: 0;
}

/* Ce qui se pose pendant le chantier attend, invisible, son tour. */
html.anime .pose,
html.anime .bouquet,
html.anime .oiseau,
html.anime .niveau,
html.anime .plomb-pose,
html.anime .chat-assis,
html.anime .bulle-dialogue {
  opacity: 0;
}

@keyframes pose {
  from { opacity: 0; transform: translateY(-16px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes apparait {
  from { opacity: 0; }
  to { opacity: 1; }
}
html.anime .monte .pose {
  animation: pose 0.5s cubic-bezier(0.2, 0.9, 0.3, 1.15) both;
  animation-delay: calc(var(--i, 0) * 0.3s);
}

/* Clignement des yeux des maçons */
@keyframes cligne {
  0%, 96%, 100% { transform: scaleY(1); }
  98% { transform: scaleY(0.1); }
}
.yeux {
  transform-origin: 4px -108px;
}
html.anime .c1 .yeux { animation: cligne 4.2s infinite; }
html.anime .c2 .yeux { animation: cligne 5.1s 1.2s infinite; }
html.anime .c3 .yeux { animation: cligne 4.8s 2.4s infinite; }
html.anime .c4 .yeux { animation: cligne 5.5s 3.1s infinite; }

/* Gyrophare surtitre */
@keyframes gyrophare-eclat {
  0%, 100% { box-shadow: 0 0 0 0 rgba(229, 72, 77, 0.7); opacity: 0.85; }
  50% { box-shadow: 0 0 0 7px rgba(229, 72, 77, 0); opacity: 1; }
}
html.anime .gyrophare {
  animation: gyrophare-eclat 1.8s infinite;
}

/* Nuages du ciel */
@keyframes derive-nuage {
  0% { transform: translateX(0); }
  50% { transform: translateX(25px); }
  100% { transform: translateX(0); }
}
html.anime .nc1 { animation: derive-nuage 14s ease-in-out infinite; }
html.anime .nc2 { animation: derive-nuage 19s ease-in-out infinite 3s; }
html.anime .nc3 { animation: derive-nuage 16s ease-in-out infinite 6s; }

/* ── 1. La Grue ──────────────────────────────────────────────────────────── */
@keyframes grue-chariot {
  0%, 100% { transform: translateX(0); }
  50% { transform: translateX(58px); }
}
@keyframes grue-balance {
  0%, 100% { transform: rotate(-3deg); }
  50% { transform: rotate(3deg); }
}
@keyframes grue-feu {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.2; }
}
@keyframes fanion-flotte {
  0%, 100% { transform: rotate(0deg); }
  50% { transform: rotate(7deg); }
}

html.anime .grue .chariot {
  animation: grue-chariot 14s ease-in-out infinite;
}
html.anime .grue .balance {
  transform-origin: 420px 292px;
  animation: grue-balance 3.8s ease-in-out infinite;
}
html.anime .grue .feu {
  animation: grue-feu 1.4s ease-in-out infinite;
}
html.anime .grue .fanion {
  transform-origin: 281px 24px;
  animation: fanion-flotte 2.2s ease-in-out infinite;
}

/* ── 2. Étage 1 : Le Toit ────────────────────────────────────────────────── */
@keyframes soleil-tourne {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
@keyframes oiseau-tete-sursaute {
  0%, 82%, 100% { transform: rotate(0deg); }
  86% { transform: rotate(-14deg); }
  92% { transform: rotate(8deg); }
}
@keyframes charpentier-marteler {
  0%, 100% { transform: rotate(0deg); }
  35% { transform: rotate(-44deg); }
  45% { transform: rotate(6deg); }
  55% { transform: rotate(0deg); }
}
@keyframes toc-etincelle {
  0%, 43%, 52%, 100% { opacity: 0; transform: scale(0.6); }
  45% { opacity: 1; transform: scale(1.2); }
}
@keyframes charpentier-hisser {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-15px); }
}
@keyframes ruban-flotte {
  0%, 100% { transform: skewX(-4deg); }
  50% { transform: skewX(6deg); }
}

html.anime [data-etage="toit"].en-vue .soleil-rayons {
  transform-origin: 900px 80px;
  animation: soleil-tourne 28s linear infinite;
}
html.anime [data-etage="toit"].en-vue .oiseau-tete {
  transform-origin: 626px 214px;
  animation: oiseau-tete-sursaute 4.8s ease infinite;
}
html.anime [data-etage="toit"].en-vue .marteler {
  transform-origin: 19px -78px;
  animation: charpentier-marteler 2.2s cubic-bezier(0.2, 0.8, 0.4, 1) infinite;
}
html.anime [data-etage="toit"].en-vue .toc {
  transform-origin: 526px 500px;
  animation: toc-etincelle 2.2s infinite;
}
html.anime [data-etage="toit"].en-vue .hisser {
  animation: charpentier-hisser 3.6s ease-in-out infinite;
}
html.anime [data-etage="toit"].en-vue .rubans .ruban {
  transform-origin: 500px 96px;
  animation: ruban-flotte 3s ease-in-out infinite;
}
html.anime [data-etage="toit"].en-vue .rubans .ruban.r2 {
  animation-delay: 0.4s;
}
html.anime [data-etage="toit"].en-vue .rubans .ruban.r3 {
  animation-delay: 0.8s;
}
html.anime [data-etage="toit"].en-vue .nuage {
  animation: derive-nuage 17s ease-in-out infinite;
}
html.anime [data-etage="toit"].en-vue .nuage.n2 {
  animation-duration: 23s;
  animation-delay: -7s;
}
/* La charpente se lève pièce par pièce (treize pièces, une toutes les 0,3 s :
   la règle générale de .pose). Le bouquet de faîte vient en dernier. */
html.anime [data-etage="toit"].monte .bouquet {
  animation: pose 0.6s cubic-bezier(0.2, 0.9, 0.3, 1.15) 4.3s both;
}
/* L'oiseau attend que son chevron soit posé pour s'y percher. */
html.anime [data-etage="toit"].monte .oiseau {
  animation: pose 0.5s ease-out 1.9s both;
}

/* ── 3. Étage 2 : Les Murs ───────────────────────────────────────────────── */
@keyframes macon-etaler {
  0%, 100% { transform: rotate(0deg); }
  30% { transform: rotate(-24deg); }
  60% { transform: rotate(14deg); }
}
@keyframes macon-tapoter {
  0%, 100% { transform: rotate(0deg); }
  40% { transform: rotate(-18deg); }
  48% { transform: rotate(4deg); }
  56% { transform: rotate(0deg); }
  68% { transform: rotate(-12deg); }
  76% { transform: rotate(3deg); }
}
@keyframes bulle-oscille {
  0%, 100% { transform: translateX(0); }
  35% { transform: translateX(2.5px); }
  70% { transform: translateX(-2.5px); }
}
@keyframes fil-a-plomb {
  0%, 100% { transform: rotate(-1.5deg); }
  50% { transform: rotate(1.5deg); }
}
@keyframes note-flotte {
  0% { opacity: 0; transform: translateY(0) scale(0.6); }
  25% { opacity: 0.9; }
  100% { opacity: 0; transform: translateY(-28px) translateX(6px) scale(1.1); }
}
@keyframes vapeur-monte {
  0% { opacity: 0; transform: translateY(0); }
  40% { opacity: 0.8; }
  100% { opacity: 0; transform: translateY(-16px); }
}
@keyframes bulle-pop {
  0%, 72%, 100% { opacity: 0; transform: scale(0.85); }
  78%, 94% { opacity: 1; transform: scale(1); }
}

html.anime [data-etage="murs"].en-vue .etaler {
  transform-origin: 19px -78px;
  animation: macon-etaler 3s ease-in-out infinite;
}
html.anime [data-etage="murs"].en-vue .tapoter {
  transform-origin: 19px -78px;
  animation: macon-tapoter 3.8s ease-in-out infinite;
}
html.anime [data-etage="murs"].en-vue .bulle-niveau {
  animation: bulle-oscille 4.2s ease-in-out infinite;
}
/* Le pivot est le point d'accroche du fil, en haut du mur (y = 410). Plus
   haut, le plomb ne se balance plus : il glisse de côté. */
html.anime [data-etage="murs"].en-vue .plomb {
  transform-origin: 632px 410px;
  animation: fil-a-plomb 4.5s ease-in-out infinite;
}
html.anime [data-etage="murs"].en-vue .note.n1 {
  animation: note-flotte 2.8s linear infinite;
}
html.anime [data-etage="murs"].en-vue .note.n2 {
  animation: note-flotte 3.2s linear infinite 0.9s;
}
html.anime [data-etage="murs"].en-vue .note.n3 {
  animation: note-flotte 2.6s linear infinite 1.8s;
}
html.anime [data-etage="murs"].en-vue .vapeur.v1 {
  animation: vapeur-monte 2.4s ease-out infinite;
}
html.anime [data-etage="murs"].en-vue .vapeur.v2 {
  animation: vapeur-monte 2.4s ease-out infinite 1.2s;
}
/* Le mur se monte : six rangs, un par seconde. Le lit de mortier s'étale,
   puis les briques du rang se posent de gauche à droite. Vers 6 s le mur est
   fini ; le niveau arrive, puis le fil à plomb, et le maçon peut le dire :
   la bulle sort à 78 % de ses 9 s, soit à 7 s, et revient ensuite. */
@keyframes lit-etale {
  from { opacity: 0; transform: scaleX(0); }
  to { opacity: 1; transform: scaleX(1); }
}
html.anime [data-etage="murs"].monte .lit {
  transform-box: fill-box;
  transform-origin: left center;
  animation: lit-etale 0.3s ease-out both;
  animation-delay: calc(var(--j, 0) * 0.95s);
}
html.anime [data-etage="murs"].monte .brique {
  animation: pose 0.34s cubic-bezier(0.2, 0.9, 0.3, 1.15) both;
  animation-delay: calc(var(--j, 0) * 0.95s + 0.2s + var(--i, 0) * 0.12s);
}
html.anime [data-etage="murs"].monte .niveau {
  animation: pose 0.5s cubic-bezier(0.2, 0.9, 0.3, 1.15) 6.1s both;
}
html.anime [data-etage="murs"].monte .plomb-pose {
  animation: apparait 0.4s ease-out 6.5s both;
}
html.anime [data-etage="murs"].monte .bulle-dialogue.aplomb {
  transform-origin: 340px 382px;
  animation: bulle-pop 9s infinite;
}

/* ── 4. Étage 3 : La Dalle ───────────────────────────────────────────────── */
/* TROIS BROUETTES, PUIS LE CHAT

   Un voyage dure 7 s : la brouette se remplit sous la bétonnière, traverse,
   se renverse dans le coffrage, revient. La dalle monte d'un tiers à chaque
   fois. Au bout de trois voyages (21 s) elle est pleine, le maçon souffle —
   et le chat traverse le béton frais, en y laissant ses empreintes.

   Les trois voyages sont une même animation jouée trois fois ; la dalle et
   la suite se calent sur ces 21 s. Changer la durée d'un voyage, c'est
   reprendre tous les retards de ce bloc. */
@keyframes tambour-tourne {
  to { transform: translateX(-34px); }
}
@keyframes brouette-voyage {
  0%, 14% { transform: translateX(0); }
  40%, 58% { transform: translateX(250px); }
  84%, 100% { transform: translateX(0); }
}
@keyframes brouette-bascule {
  0%, 42% { transform: rotate(0deg); }
  46%, 54% { transform: rotate(18deg); }
  58%, 100% { transform: rotate(0deg); }
}
@keyframes coulee-mixer {
  0%, 2%, 14%, 100% { opacity: 0; }
  4%, 12% { opacity: 1; }
}
@keyframes coulee-dalle-verse {
  0%, 45%, 56%, 100% { opacity: 0; }
  47%, 54% { opacity: 1; }
}
/* Le tas de béton dans la brouette : il arrive sous la bétonnière et part
   dans le coffrage. */
@keyframes tas-charge {
  0%, 3% { opacity: 0; }
  12%, 47% { opacity: 1; }
  54%, 100% { opacity: 0; }
}
/* Les trois coulées tombent à 16-18 %, 49-51 % et 82-85 % des 21 s. */
@keyframes beton-monte {
  0%, 15.7% { transform: scaleY(0); }
  18%, 49% { transform: scaleY(0.34); }
  51.3%, 82.3% { transform: scaleY(0.67); }
  84.7%, 100% { transform: scaleY(1); }
}
@keyframes chat-traverse {
  0% { opacity: 0; transform: translateX(300px); }
  4% { opacity: 1; }
  92% { opacity: 1; transform: translateX(0); }
  100% { opacity: 0; transform: translateX(0); }
}
@keyframes chat-patte {
  from { transform: rotate(-24deg); }
  to { transform: rotate(24deg); }
}
@keyframes bulle-une-fois {
  0% { opacity: 0; transform: scale(0.85); }
  10%, 86% { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1); }
}
@keyframes chat-queue-balancement {
  0%, 100% { transform: rotate(0deg); }
  50% { transform: rotate(-8deg); }
}
@keyframes macon-boire {
  0%, 60%, 100% { transform: rotate(0deg); }
  70%, 85% { transform: rotate(-35deg); }
}

/* Les rayures glissent d'un pas (34) le long du tambour : c'est ce qu'on voit
   d'une cuve qui tourne sur son axe. */
html.anime [data-etage="dalle"].en-vue .tambour .rayures {
  animation: tambour-tourne 1.1s linear infinite;
}
html.anime [data-etage="dalle"].en-vue .chat-queue {
  transform-origin: 612px 498px;
  animation: chat-queue-balancement 3.2s ease-in-out infinite;
}
html.anime [data-etage="dalle"].en-vue .boire {
  transform-origin: 19px -78px;
  animation: macon-boire 6.5s ease-in-out infinite;
}
html.anime [data-etage="dalle"].en-vue .fumee-tasse .vapeur {
  animation: vapeur-monte 2.4s ease-out infinite;
}

/* La dalle part vide. */
.beton {
  transform-box: fill-box;
  transform-origin: center bottom;
}
html.anime .beton {
  transform: scaleY(0);
}

html.anime [data-etage="dalle"].monte .brouette-cycle {
  animation: brouette-voyage 7s ease-in-out 3 both;
}
html.anime [data-etage="dalle"].monte .bascule {
  transform-origin: 430px 532px;
  animation: brouette-bascule 7s ease-in-out 3 both;
}
html.anime [data-etage="dalle"].monte .coulee {
  animation: coulee-mixer 7s ease-in-out 3 both;
}
html.anime [data-etage="dalle"].monte .coulee-dalle {
  animation: coulee-dalle-verse 7s ease-in-out 3 both;
}
html.anime [data-etage="dalle"].monte .tas {
  animation: tas-charge 7s ease-in-out 3 both;
}
html.anime [data-etage="dalle"].monte .beton {
  animation: beton-monte 21s ease-in-out both;
}
/* 21,4 s : le chat entre par la droite du coffrage. Il met 4,6 s à le
   traverser ; ses empreintes apparaissent derrière lui, une toutes les
   0,55 s, puis il s'assoit au bord (le dessin fixe prend le relais). */
html.anime [data-etage="dalle"].monte .chat-marche {
  animation: chat-traverse 4.6s linear 21.4s both;
}
html.anime [data-etage="dalle"].monte .patte {
  transform-box: fill-box;
  transform-origin: center top;
  animation: chat-patte 0.28s ease-in-out infinite alternate;
}
html.anime [data-etage="dalle"].monte .patte.p2 {
  animation-direction: alternate-reverse;
}
html.anime [data-etage="dalle"].monte .empreinte {
  animation: apparait 0.2s ease-out both;
  animation-delay: calc(21.7s + var(--i, 0) * 0.55s);
}
html.anime [data-etage="dalle"].monte .chat-assis {
  animation: apparait 0.3s ease-out 25.8s both;
}
html.anime [data-etage="dalle"].monte .bulle-dialogue.ohnon {
  transform-origin: 238px 404px;
  animation: bulle-une-fois 3.8s ease-out 22.2s both;
}

/* ── 5. Étage 4 : Les Fondations ─────────────────────────────────────────── */
@keyframes pelle-fleche {
  0%, 100% { transform: rotate(0deg); }
  32% { transform: rotate(12deg); }
  64% { transform: rotate(-5deg); }
}
@keyframes pelle-balancier {
  0%, 100% { transform: rotate(0deg); }
  30% { transform: rotate(18deg); }
  62% { transform: rotate(-14deg); }
}
@keyframes pelle-godet {
  0%, 100% { transform: rotate(0deg); }
  34% { transform: rotate(32deg); }
  64% { transform: rotate(-24deg); }
}
@keyframes macon-pelleter {
  0%, 100% { transform: rotate(0deg) translateY(0); }
  30% { transform: rotate(18deg) translateY(3px); }
  55% { transform: rotate(-12deg) translateY(-2px); }
}
@keyframes mottes-vol {
  0%, 46%, 100% { opacity: 0; transform: translate(0, 0); }
  50% { opacity: 1; }
  62% { opacity: 0; transform: translate(-16px, -22px); }
}
@keyframes taupe-sort {
  0%, 65%, 100% { transform: translateY(42px); }
  75%, 90% { transform: translateY(0); }
  82% { transform: translateY(-3px) rotate(4deg); }
}
@keyframes ver-ondulation {
  0%, 100% { transform: scaleX(1); }
  50% { transform: scaleX(0.85) translateX(3px); }
}
@keyframes ampoule-lueur {
  0%, 100% { opacity: 0.9; }
  50% { opacity: 1; }
}

html.anime [data-etage="fondations"].en-vue .fleche {
  transform-origin: 436px 478px;
  animation: pelle-fleche 6.5s ease-in-out infinite;
}
html.anime [data-etage="fondations"].en-vue .balancier {
  transform-origin: 548px 372px;
  animation: pelle-balancier 6.5s ease-in-out infinite;
}
html.anime [data-etage="fondations"].en-vue .godet {
  transform-origin: 610px 458px;
  animation: pelle-godet 6.5s ease-in-out infinite;
}
html.anime [data-etage="fondations"].en-vue .pelleter {
  transform-origin: 0 -40px;
  animation: macon-pelleter 3.2s ease-in-out infinite;
}
html.anime [data-etage="fondations"].en-vue .mottes {
  animation: mottes-vol 3.2s ease-out infinite;
}
html.anime [data-etage="fondations"].en-vue .taupe {
  animation: taupe-sort 9.5s ease-in-out infinite;
}
html.anime [data-etage="fondations"].en-vue .ver {
  transform-origin: 765px 474px;
  animation: ver-ondulation 2.8s ease-in-out infinite;
}
html.anime [data-etage="fondations"].en-vue .ampoule {
  animation: ampoule-lueur 3.2s ease-in-out infinite;
}

/* ── 6. Bureau de Chantier ───────────────────────────────────────────────── */
@keyframes lumiere-douce {
  0%, 100% { opacity: 0.2; }
  50% { opacity: 0.7; }
}
@keyframes chat-respiration {
  0%, 100% { transform: scaleY(1); }
  50% { transform: scaleY(1.08); }
}
@keyframes zzz-monte {
  0% { opacity: 0; transform: translateY(0) scale(0.7); }
  40% { opacity: 0.9; }
  100% { opacity: 0; transform: translateY(-20px) translateX(-6px) scale(1.1); }
}

html.anime [data-etage="contact"].en-vue .lumiere {
  animation: lumiere-douce 4.5s ease-in-out infinite;
}
html.anime [data-etage="contact"].en-vue .chat-dort {
  transform-origin: 112px 70px;
  animation: chat-respiration 3.6s ease-in-out infinite;
}
html.anime [data-etage="contact"].en-vue .zzz.z1 {
  animation: zzz-monte 3.5s ease-out infinite;
}
html.anime [data-etage="contact"].en-vue .zzz.z2 {
  animation: zzz-monte 3.5s ease-out infinite 1.75s;
}

/* ── 7. Page 404 (Perdu) ─────────────────────────────────────────────────── */
@keyframes macon-gratter {
  0%, 100% { transform: rotate(0deg); }
  25% { transform: rotate(-18deg); }
  50% { transform: rotate(8deg); }
  75% { transform: rotate(-12deg); }
}
@keyframes macon-perplexe {
  0%, 100% { transform: rotate(0deg); }
  50% { transform: rotate(-12deg); }
}
@keyframes point-flotte {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-8px); }
}

html.anime .gratter,
.page-404 .gratter {
  transform-origin: 19px -78px;
  animation: macon-gratter 2.8s ease-in-out infinite;
}
html.anime .perplexe,
.page-404 .perplexe {
  transform-origin: 0 -84px;
  animation: macon-perplexe 4s ease-in-out infinite;
}
html.anime .perdu-point,
.page-404 .perdu-point {
  animation: point-flotte 2.4s ease-in-out infinite;
}

/* ── 8. Accessibilité & Préférence Mouvement Réduit ────────────────────────── */
/* Qui a demandé « moins d'animations » à son système arrive sur un chantier
   à l'arrêt : assets/chantier.js ne pose pas « anime », donc rien de ce qui
   précède ne s'applique. Ce bloc est la ceinture : il tient aussi la page
   404, qui s'anime sans script, et les transitions.

   « force-anime » le lève. Le script la pose quand ce visiteur-là clique
   lui-même sur « Le mettre en route » : sans elle, son clic ne lancerait
   que des animations d'un millième de milliseconde, autant dire rien. */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  html:not(.force-anime) *,
  html:not(.force-anime) *::before,
  html:not(.force-anime) *::after {
    animation-duration: 0.001ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}
