/* ==========================================================================
   IMPRA × OFFICEVIBE — MISE EN SCÈNE DES MÉDIAS
   Couche additive, chargée après signature.impra.css.
   Ne redéfinit aucun token, aucune grille, aucun composant du système.

   Principe : un média participe à la composition. Il n'est jamais une image
   posée au centre d'une carte vide.
   ========================================================================== */

/* ==========================================================================
   ⚑ 23 août 2026 — le Graphic System (carrosserie.impra.css) a remplacé les
   emplacements d'illustration de S5, S7 et S11 par des scènes vectorielles.
   Les blocs §1 (emplacements), §3 (tag/note du teaser) et §5 (esquisses) ne
   sont donc plus référencés par index.html. Ils sont CONSERVÉS tels quels :
   ils restent la grammaire de placeholder du système et servent aux pages
   intérieures à venir. À supprimer seulement sur décision explicite.
   ========================================================================== */

/* ==========================================================================
   1. EMPLACEMENTS D'ILLUSTRATION
   Un placeholder doit déjà porter le ratio, la position, la profondeur et les
   temps forts de la narration — jamais un rectangle vide générique.
   ========================================================================== */
.figure-slot {
  position: relative;
  border-radius: var(--radius-images);
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--impra-blue-soft) 55%, var(--impra-surface)) 0%, var(--impra-surface) 100%);
  border: 1px dashed color-mix(in srgb, var(--impra-blue) 34%, var(--impra-border));
  overflow: hidden;
  display: grid;
  align-content: space-between;
  gap: var(--space-16);
  padding: var(--space-24);
}
/* Trame discrète : donne de la matière au vide et rappelle la grille */
.figure-slot::before {
  content: "";
  position: absolute; inset: 0;
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--impra-blue) 8%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--impra-blue) 8%, transparent) 1px, transparent 1px);
  background-size: 44px 44px;
  pointer-events: none;
}
.figure-slot > * { position: relative; z-index: 1; }
.figure-slot__tag {
  justify-self: start;
  font-size: 10px; font-weight: var(--weight-bold); letter-spacing: .1em; text-transform: uppercase;
  color: var(--impra-blue);
  background: var(--impra-surface);
  border: var(--border-hairline);
  border-radius: var(--radius-buttons);
  padding: 5px 11px;
}
.figure-slot__note {
  font-size: var(--text-caption); line-height: 1.45; color: var(--impra-muted);
  margin: 0; max-width: 46ch;
}

/* Les temps forts de la narration, matérialisés dès le placeholder */
.beats { display: flex; flex-wrap: wrap; gap: var(--space-8) var(--space-16); align-items: center; }
.beat {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: var(--text-caption); color: var(--impra-muted);
}
.beat::before {
  content: ""; width: 9px; height: 9px; border-radius: var(--radius-buttons);
  background: var(--impra-surface); border: 2px solid var(--impra-blue);
  flex: 0 0 9px;
}
.beat + .beat::after { content: none; }
.beats--flow .beat:not(:last-child) { position: relative; padding-right: var(--space-16); }
.beats--flow .beat:not(:last-child)::after {
  content: ""; position: absolute; right: 2px; top: 50%;
  width: 8px; height: 1px; background: var(--impra-border);
}

/* Ratios déclarés par emplacement */
.figure-slot--portrait { aspect-ratio: 4 / 5; }
.figure-slot--band     { aspect-ratio: 21 / 9; }
.figure-slot--wide     { aspect-ratio: 3 / 1; }
.figure-slot--4-3      { aspect-ratio: 4 / 3; }
@media (max-width: 900px) {
  .figure-slot { padding: var(--space-20); }
  .figure-slot--portrait,
  .figure-slot--band,
  .figure-slot--wide { aspect-ratio: 4 / 3; }
}

/* Zones ancrées sur une bande : elles disent où la narration se posera */
.figure-slot--zones { display: grid; grid-template-columns: repeat(3, 1fr); align-content: stretch; gap: 0; padding: 0; }
.zone {
  display: grid; align-content: center; justify-items: center; gap: var(--space-8);
  padding: var(--space-24); text-align: center;
  border-right: 1px dashed color-mix(in srgb, var(--impra-blue) 22%, var(--impra-border));
}
.zone:last-child { border-right: none; }
.zone__label {
  font-size: var(--text-caption); font-weight: var(--weight-semibold);
  letter-spacing: .06em; text-transform: uppercase; color: var(--impra-navy);
}
.zone__hint { font-size: var(--text-caption); color: var(--impra-muted); margin: 0; max-width: 24ch; }
.zone--link .zone__label { color: var(--impra-blue); }
@media (max-width: 900px) {
  .figure-slot--zones { grid-template-columns: 1fr; }
  .zone { border-right: none; border-bottom: 1px dashed color-mix(in srgb, var(--impra-blue) 22%, var(--impra-border)); }
  .zone:last-child { border-bottom: none; }
}

/* ==========================================================================
   2. MICRO-COMPOSITIONS DE DONNÉES  (S4, S6)
   Reprennent l'ADN du produit sans en afficher l'interface.
   ========================================================================== */
.datum { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-12); }
.datum__v {
  font-family: var(--font-geometric);
  font-weight: var(--weight-semibold);
  font-variant-numeric: var(--font-numeric);
  color: var(--impra-navy);
}
.datum__k { font-size: var(--text-caption); color: var(--impra-muted); }
.on-ink .datum__v, .band-ink .datum__v { color: var(--impra-surface); }
.on-ink .datum__k, .band-ink .datum__k { color: var(--color-lavender-mist); }

/* Barre de progression sobre — sert d'indicateur, pas de décor */
.meter { height: 6px; border-radius: 100px; background: color-mix(in srgb, var(--impra-navy) 10%, transparent); overflow: hidden; }
.on-ink .meter, .band-ink .meter { background: rgba(255,255,255,.14); }
.meter > i { display: block; height: 100%; border-radius: 100px; background: var(--impra-blue); }

/* Micro-graphique en aires — tracé SVG, aucun fichier */
.spark { display: block; width: 100%; height: 44px; }
.spark path.line { fill: none; stroke: var(--impra-blue); stroke-width: 2; }
.spark path.area { fill: color-mix(in srgb, var(--impra-blue) 14%, transparent); stroke: none; }
.on-ink .spark path.line, .band-ink .spark path.line { stroke: #7FB0FF; }
.on-ink .spark path.area, .band-ink .spark path.area { fill: rgba(127,176,255,.18); }

/* Silhouette de véhicule / statut — pictogrammes du système, pas d'asset */
.pill-row { display: flex; flex-wrap: wrap; gap: 6px; }
.pill-mini {
  font-size: 10px; letter-spacing: .04em;
  padding: 3px 9px; border-radius: var(--radius-buttons);
  background: var(--impra-blue-soft); color: var(--impra-blue);
}
.on-ink .pill-mini, .band-ink .pill-mini { background: rgba(255,255,255,.10); color: var(--color-lavender-mist); }

/* ==========================================================================
   3. TEASER « EXPLORER IMPRA »  (S11)
   Un fragment volontairement partiel, qui s'efface dans la bande.
   Il suggère l'environnement sans le livrer.
   ========================================================================== */
.teaser {
  position: relative;
  border-radius: 14px 0 0 14px;
  overflow: hidden;
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.16);
  border-right: none;
  min-height: 220px;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: var(--space-8);
  padding: var(--space-24);
  /* Le fragment se dissout vers la droite : la réponse reste derrière le CTA */
  -webkit-mask-image: linear-gradient(90deg, #000 0%, #000 52%, transparent 96%);
          mask-image: linear-gradient(90deg, #000 0%, #000 52%, transparent 96%);
}
.teaser img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: left top; }
.teaser__tag {
  position: relative; z-index: 1;
  font-size: 10px; font-weight: var(--weight-bold); letter-spacing: .1em; text-transform: uppercase;
  color: var(--color-lavender-mist);
  border: 1px solid rgba(255,255,255,.28);
  border-radius: var(--radius-buttons);
  padding: 5px 11px;
}
.teaser__note { position: relative; z-index: 1; font-size: var(--text-caption); color: rgba(255,255,255,.62); margin: 0; text-align: center; max-width: 26ch; }
@media (max-width: 900px) {
  .teaser {
    border-radius: 14px; border-right: 1px solid rgba(255,255,255,.16);
    min-height: 150px;
    -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 58%, transparent 100%);
            mask-image: linear-gradient(180deg, #000 0%, #000 58%, transparent 100%);
  }
}

/* ==========================================================================
   4. HOOKS DE MOTION
   Sobres par construction. Tout est neutralisé sous prefers-reduced-motion.
   ========================================================================== */
[data-motion] { will-change: transform, opacity; }
.js [data-motion="rise"] {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 520ms var(--ease-standard), transform 520ms var(--ease-standard);
}
[data-motion="rise"].is-in { opacity: 1; transform: none; }
[data-motion="rise"][data-delay="1"] { transition-delay: 90ms; }
[data-motion="rise"][data-delay="2"] { transition-delay: 180ms; }
[data-motion="rise"][data-delay="3"] { transition-delay: 270ms; }

/* Parallaxe de couche : amplitude pilotée par --depth, jamais permanente */
[data-parallax] { transform: translate3d(0, calc(var(--py, 0px) * var(--depth, 1)), 0); }

/* Étape de narration : micro-réaction seulement.
   Le texte reste toujours pleinement lisible — seule la pastille du jalon
   réagit. Atténuer le texte non lu gênerait la lecture de la liste. */
.timeline__item[data-scroll-step]::before {
  transition: background-color 260ms var(--ease-standard), transform 260ms var(--ease-standard);
}
.timeline__item[data-scroll-step].is-active::before {
  background: var(--impra-blue);
  transform: scale(1.3);
}
/* Les zones d'un emplacement d'illustration peuvent, elles, s'éclairer :
   ce sont des repères de composition, pas du contenu à lire. */
.zone[data-scroll-step] { transition: opacity 320ms var(--ease-standard); }
.zone[data-scroll-step]:not(.is-active) { opacity: .62; }

@media (prefers-reduced-motion: reduce) {
  [data-motion="rise"] { opacity: 1; transform: none; transition: none; }
  [data-parallax] { transform: none; }
  .zone[data-scroll-step]:not(.is-active) { opacity: 1; }
  .timeline__item[data-scroll-step]::before { transition: none; }
}

/* Le tag d'un emplacement en zones se pose en surimpression : la bande est
   déjà occupée par les trois temps de la narration. */
.figure-slot--zones .figure-slot__tag {
  position: absolute; top: var(--space-16); left: var(--space-16); z-index: 2;
}
/* Bande CTA : texte dominant, teaser à droite. En colonne unique sur mobile,
   le teaser se recolle au bord bas de la carte. */
.split--teaser { grid-template-columns: 1.25fr .75fr; gap: var(--space-48); }
@media (max-width: 900px) {
  .split--teaser { grid-template-columns: minmax(0, 1fr); gap: var(--space-32); }
  #explorer .teaser { margin-right: 0 !important; }
}

/* ==========================================================================
   5. ESQUISSES DE COMPOSITION
   Le placeholder ne se contente pas de nommer l'illustration : il en indique
   la masse et la répartition, pour que le layout se juge avant l'asset.
   ========================================================================== */
.sketch { display: grid; gap: 7px; width: 100%; max-width: 210px; }
.sketch i {
  display: block; height: 12px; border-radius: 6px;
  background: color-mix(in srgb, var(--impra-blue) 16%, transparent);
}
.sketch i.tall  { height: 46px; border-radius: 10px; }
.sketch i.solid { background: color-mix(in srgb, var(--impra-blue) 30%, transparent); }
.sketch i.w70 { width: 70%; }
.sketch i.w45 { width: 45%; }
.sketch--row { grid-auto-flow: column; align-items: end; max-width: 240px; }
.sketch--row i { width: 100%; }

.zone { align-content: center; }
.zone .sketch { justify-self: center; margin-bottom: var(--space-8); }

/* ==========================================================================
   6. BADGES DE STORE — FICHIERS OFFICIELS
   Apple : Download_on_the_App_Store_Badge_FR_RGB_blk, 126,507 × 40 (SVG).
   Google : fr_badge_web_generic, 646 × 250 (PNG) — l'encre du badge n'occupe
   que 192 px des 250 : 11,6 % de marge haut et bas, imposée par la charte et
   jamais rognée. Pour que les deux badges pèsent optiquement pareil, Google
   est donc rendu à 1,302 × la hauteur d'Apple.

   Les badges ne sont ni redessinés, ni recolorés, ni reproportionnés : le
   composant se contente de les dimensionner et de les aligner.

   Hiérarchie voulue : Explorer IMPRA > Essayer 30 jours > disponibilité iOS
   et Android. Les badges sont une réassurance, jamais un CTA — d'où une
   hauteur d'encre de 36 px dans le hero contre 40 px ailleurs.
   ========================================================================== */
.stores { display: flex; flex-direction: column; gap: var(--space-12); }
.stores__label {
  font-size: var(--text-caption);
  color: var(--impra-muted);
  letter-spacing: .01em;
}
.stores__row {
  --store-ink: 40px;                 /* hauteur d'encre commune aux deux badges */
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
}
.store-badge { display: inline-flex; align-items: center; flex: 0 0 auto; text-decoration: none; }
.store-badge img { display: block; width: auto; }
.store-badge--apple  img { height: var(--store-ink); }
.store-badge--google img { height: calc(var(--store-ink) * 1.302); }

/* Variante claire sur surface sombre — c'est le fichier officiel blanc
   d'Apple qui sert, jamais un filtre appliqué au fichier noir.
   Les sélecteurs qualifient `img` : sans cela `.store-badge img` l'emporterait
   et les deux variantes s'afficheraient côte à côte. */
.store-badge img.store-badge__light { display: none; }
.band-ink .store-badge img.store-badge__dark,
.footer  .store-badge img.store-badge__dark { display: none; }
.band-ink .store-badge img.store-badge__light,
.footer  .store-badge img.store-badge__light { display: block; }

/* Emplacement de secours, si un fichier officiel venait à manquer */
.store-badge--empty {
  height: var(--store-ink);
  border: 1px dashed var(--impra-border-strong);
  border-radius: 8px;
  background: var(--impra-surface);
  color: var(--impra-muted-soft);
  font-size: 9px; font-weight: var(--weight-semibold);
  letter-spacing: .08em; text-transform: uppercase;
  padding-inline: 8px; text-align: center; line-height: 1.15;
  justify-content: center;
}
.store-badge--apple.store-badge--empty  { width: 120px; }
.store-badge--google.store-badge--empty { width: 104px; }
.band-ink .store-badge--empty,
.footer .store-badge--empty {
  background: transparent; border-color: rgba(255,255,255,.28); color: rgba(255,255,255,.55);
}
.footer .stores__label { color: rgba(255,255,255,.62); }

/* ==========================================================================
   7. PREUVE SOCIALE DU HERO
   Une ligne éditoriale, pas deux cartes. Elle ferme la colonne de texte :
   une règle fine, l'adoption, la note. Rien ne bouge, rien ne clignote.
   ========================================================================== */
/* La preuve sociale est désormais traitée dans polish.impra.css §2 :
   deux données signature, pas deux lignes de texte secondaire. */

/* ── Le pied de la colonne de texte : preuve, puis disponibilité mobile ──
   Les badges viennent après la preuve sociale et restent nettement plus
   discrets que les deux boutons. */
.hero__stores { margin-top: var(--space-20); }
.hero__stores .stores__row { --store-ink: 36px; }
.hero__stores .stores { flex-direction: row; align-items: center; gap: var(--space-16); flex-wrap: wrap; }
@media (max-width: 620px) {
  .hero__stores .stores { flex-direction: column; align-items: flex-start; gap: var(--space-8); }
}

/* ==========================================================================
   8. LA COMPOSITION PRODUIT DU HERO
   L'asset est un WebP à canal alpha : 66,5 % de pixels opaques, les quatre
   coins vides (mesuré). Il est donc traité pour ce qu'il est — une
   composition flottante. Pas de carte, pas de fond, pas de cadre : l'ombre
   suit la silhouette (drop-shadow) et non un rectangle (box-shadow).

   Son ratio natif est 1448 × 1086 (4:3). Il n'est jamais recadré au desktop :
   `width` + `height:auto` suffisent, aucune déformation n'est possible.
   ========================================================================== */
/* `.hero .split` (0-2-0) est déclaré dans components.css : une classe seule ne
   peut pas l'emporter. On qualifie au même niveau, plus tard dans la cascade. */
/* ── ÉQUILIBRE OPTIQUE DU HERO ────────────────────────────────────────
   La composition déborde à droite, jamais à gauche. Mesuré au pixel sur le
   rendu (1440 px) : l'encre courait de x=159 à x=1391, soit 159 px de marge
   à gauche pour 48 à droite — 111 px d'écart. D'où l'impression, juste, de
   trop de vide à gauche.

   La correction se fait en deux temps :
   1. le débordement est plafonné à 64 px (au lieu de 112) — au-delà, la
      compensation ne tiendrait plus dans la gouttière ;
   2. le contenu du conteneur est décalé de la moitié de ce débordement,
      en jouant sur ses deux paddings. La boîte reste centrée, sa largeur
      utile ne change pas : seul le contenu glisse vers la gauche.
   Les deux marges optiques deviennent égales à toutes les largeurs.       */
.hero {
  /* Débordement nul au desktop : la composition s'arrête au bord droit du
     conteneur, exactement là où le texte commence à gauche. Décaler le
     texte pour compenser un débordement l'aurait sorti de la grille — il
     serait passé à gauche du logo et de toutes les sections suivantes.
     C'est le débordement qu'on retire, pas l'alignement qu'on sacrifie.
     Le plein écran de la composition reste, lui, en dessous de 900 px. */
  --hero-bleed: 0px;
}

.hero .split--hero {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.32fr);
  gap: var(--space-48);
  align-items: center;
}

.hero-asset {
  /* Le débordement ne peut pas excéder la place réellement disponible entre
     le bord droit du conteneur et celui de la fenêtre — sinon la page défile
     horizontalement dès que le conteneur cesse d'être centré (mesuré : 5 px à
     1280, 7 px à 1024). 24 px sont gardés en marge de sécurité. */
  margin: -24px calc(var(--hero-bleed) * -1) 0 0;
  width: calc(100% + var(--hero-bleed));
  animation: heroIn 780ms var(--ease-standard) 120ms both;
}
/* Deux couches : l'entrée est portée par la figure, la respiration continue
   par le conteneur intérieur. Sans cela les deux transforms se chassent. */
.hero-asset__float { display: block; animation: heroFloat 11s ease-in-out 1100ms infinite; will-change: transform; }
.hero-asset img {
  display: block; width: 100%; height: auto;
  filter: drop-shadow(0 16px 26px rgba(15,23,46,.10)) drop-shadow(0 42px 62px rgba(15,23,46,.07));
}
/* L'entrée du hero n'anime que la transformation : l'image LCP est peinte
   opaque dès la première frame, elle n'attend aucun fondu. */
@keyframes heroIn    { from { transform: translateY(18px) scale(.985); } to { transform: none; } }
@keyframes heroFloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }

/* La réassurance courte tient sur une ligne : trois lignes d'affilée sous les
   boutons alourdiraient le premier écran. */
.checklist--inline { flex-direction: row; flex-wrap: wrap; gap: var(--space-12) var(--space-24); }

/* ── 1120 px : la colonne texte reprend un peu de place ── */
@media (max-width: 1120px) {
  .hero .split--hero { grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr); gap: var(--space-40); }
}

/* ── ≤ 900 px : ce n'est plus la même composition ──
   La composition passe sous le contenu et prend toute la largeur de l'écran,
   marges de page comprises : à cette taille, un asset contenu dans la gouttière
   serait trop petit pour que le web et le mobile restent lisibles. */
@media (max-width: 900px) {
  .hero { padding-block: var(--space-48) var(--space-40); }
  .hero .split--hero { grid-template-columns: minmax(0, 1fr); gap: var(--space-40); }
  .hero-asset {
    --hero-bleed: 0px;
    width: calc(100% + var(--page-gutter) * 2);
    margin: var(--space-8) calc(var(--page-gutter) * -1) 0;
  }
  .hero-asset img { filter: drop-shadow(0 12px 20px rgba(15,23,46,.09)); }
}
@media (max-width: 430px) { .hero-asset { margin-top: 0; } }

@media (prefers-reduced-motion: reduce) {
  .hero-asset, .hero-asset__float { animation: none; }
}
