/* ═══════════════════════════════════════════════════════════════════════════
   ASap FC — Habillage du socle partagé (visionneuse + apparitions).
   Compagnon de `socle.js`. Écrit le 21/08/2026.

   Ne contient QUE ce qui doit rester identique d'une direction à l'autre :
   le comportement visuel de la visionneuse et la mécanique d'apparition.
   Les couleurs passent par des jetons redéfinissables sur :root.
   ═══════════════════════════════════════════════════════════════════════════ */

:root{
  --vz-voile:rgba(6,10,22,.93);   /* fond derrière la visionneuse */
  --vz-encre:#f3f5fa;             /* texte de la barre du bas */
  --vz-encre-2:#98a3b8;
  --vz-btn-bord:rgba(255,255,255,.34);
  --vz-btn-actif:#e8ff3a;
  --vz-btn-actif-encre:#101b3c;
}

/* ── ce qui rend un rendu cliquable lisible comme tel ─────────────────────── */
[data-zoom]{cursor:zoom-in;position:relative}
[data-zoom]:focus-visible{outline:3px solid var(--vz-btn-actif);outline-offset:3px}
[data-zoom]::after{
  content:'⤢';position:absolute;right:10px;bottom:10px;z-index:3;
  width:30px;height:30px;display:flex;align-items:center;justify-content:center;
  font-size:14px;line-height:1;border-radius:8px;
  background:rgba(8,12,24,.72);color:#fff;border:1px solid rgba(255,255,255,.3);
  opacity:0;transform:translateY(4px);transition:opacity .18s,transform .18s;
  pointer-events:none;
}
[data-zoom]:hover::after,[data-zoom]:focus-visible::after{opacity:1;transform:translateY(0)}

/* ── les clips vidéo des overlays (23/08) ─────────────────────────────────
   Un <video data-clip> est toujours posé dans un cadre qui porte [data-zoom] :
   il prend toute la largeur du cadre, garde ses proportions, et montre son
   image d'affiche tant que socle.js ne l'a pas lancé.                        */
video[data-clip]{display:block;width:100%;height:auto;background:#05080a}

/* ── la visionneuse ───────────────────────────────────────────────────────── */
.vz{
  position:fixed;inset:0;z-index:200;display:flex;align-items:center;justify-content:center;
  padding:24px;background:var(--vz-voile);
  opacity:0;transition:opacity .2s ease-out;
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
}
/* `display:flex` ci-dessus l'emporte sur le `display:none` que le navigateur
   applique à [hidden] : sans cette règle, le voile fermé reste dans le flux et
   intercepte tous les clics de la page. Trouvé par tests-portfolio-hij.mjs. */
.vz[hidden]{display:none}
.vz.on{opacity:1}
.vz-in{
  display:flex;flex-direction:column;gap:16px;
  /* 30/09 : au moins 75 % de la largeur d'écran (retour d'Anthony — sur un
     grand écran le clip agrandi restait à 1180 px, « la même taille que
     l'image qu'on vient de cliquer »). */
  width:min(max(1180px,75vw),100%);max-height:100%;
  transform:scale(.975);transition:transform .22s cubic-bezier(.22,1,.36,1);
}
.vz.on .vz-in{transform:scale(1)}
.vz-scene{
  flex:1;min-height:0;display:flex;align-items:center;justify-content:center;
}
.vz-scene img{
  width:100%;max-height:78vh;height:auto;object-fit:contain;display:block;
  border-radius:6px;box-shadow:0 30px 90px rgba(0,0,0,.6);
}
/* Un clip vidéo agrandi (23/08) : même gabarit qu'une image. Le fond noir
   du produit derrière, pour que les bords d'un cadrage étroit ne sortent pas
   gris sur le voile. */
.vz-scene video{
  width:100%;max-height:78vh;height:auto;display:block;
  border-radius:6px;box-shadow:0 30px 90px rgba(0,0,0,.6);background:#05080a;
}
/* Une démo clonée : on lui rend la largeur qu'elle n'a pas en vignette.
   `container-type:inline-size` est déjà porté par `.ovl` — les paliers
   @container de anims-evenement.css se recalculent donc tout seuls ici. */
.vz-demo{width:100%;max-width:1100px;box-shadow:0 30px 90px rgba(0,0,0,.6)}
.vz-demo.ovl-pitch{max-width:520px}
/* La tuile compositions du « mur de temps » : un bandeau pleine largeur
   serait absurde pour un panneau qui est carre dans le produit. */
.vz-demo.hb-tuile{max-width:600px}

.vz-bas{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:14px;
}
.vz-leg{
  margin:0;flex:1 1 320px;min-width:0;
  font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:11.5px;line-height:1.5;
  letter-spacing:.05em;text-transform:uppercase;color:var(--vz-encre-2);
}
.vz-actions{display:flex;gap:10px;flex-shrink:0}
.vz-actions button{
  font-family:Archivo,system-ui,sans-serif;font-size:13.5px;font-weight:600;
  padding:10px 18px;border-radius:999px;cursor:pointer;
  background:transparent;color:var(--vz-encre);border:1.5px solid var(--vz-btn-bord);
  transition:background .16s,color .16s,border-color .16s;
}
.vz-actions button:hover{border-color:var(--vz-btn-actif);color:var(--vz-btn-actif)}
.vz-rejouer{background:var(--vz-btn-actif) !important;color:var(--vz-btn-actif-encre) !important;border-color:var(--vz-btn-actif) !important}
.vz-rejouer:hover{filter:brightness(1.08)}

@media (max-width:640px){
  .vz{padding:14px}
  .vz-bas{flex-direction:column;align-items:stretch}
  .vz-actions{justify-content:stretch}
  .vz-actions button{flex:1}
}

/* ── apparition à l'entrée dans l'écran ───────────────────────────────────────
   Volontairement sobre : 14 px de montée et un fondu. Au-delà, le contenu
   « saute » au défilement rapide et devient pénible sur une page longue.
   Le décalage se règle par --d, en ligne, pour cascader une grille.           */
[data-reveal]{
  opacity:0;transform:translateY(14px);
  transition:opacity .5s ease-out,transform .5s cubic-bezier(.22,1,.36,1);
  transition-delay:var(--d,0ms);
}
[data-reveal].vu{opacity:1;transform:none}

/* ── Les fenêtres modales : demande d'essai ET « Nous écrire » ─────────────
   22/08 : déplacé ici depuis le <style> de l'accueil, parce que la fenêtre
   de contact est injectée par socle.js sur TOUTES les pages qui le chargent
   (accueil, sur-mesure). Les jetons (--bleu, --fluo, --texte-2, --malt…)
   sont ceux de :root de chaque page ; les replis valent la charte H.        */
dialog{border:3px solid var(--bleu,#0b1329);background:var(--blanc,#f7f6f1);color:var(--bleu,#0b1329);padding:0;max-width:470px;width:calc(100vw - 40px);border-radius:14px}
dialog::backdrop{background:rgba(6,10,22,.74)}
.dlg-in{padding:28px;position:relative}
.dlg-in h3{margin:0;font-family:'Barlow Condensed',sans-serif;font-size:30px;font-weight:800;text-transform:uppercase}
.dlg-in .sub{margin:8px 0 0;font-size:14px;color:var(--texte-2,#4a5468)}
.dlg-in form{margin-top:18px;display:flex;flex-direction:column;gap:12px}
.dlg-in label{display:flex;flex-direction:column;gap:5px;font-family:'IBM Plex Mono',monospace;font-size:11px;letter-spacing:.06em;text-transform:uppercase}
.dlg-in input,.dlg-in textarea{background:#fff;border:2px solid var(--bleu,#0b1329);border-radius:8px;color:var(--bleu,#0b1329);font:14.5px Archivo,sans-serif;padding:11px 12px}
.dlg-in textarea{min-height:112px;resize:vertical;line-height:1.45}
.dlg-in input:focus,.dlg-in textarea:focus{outline:3px solid var(--fluo,#e8ff3a)}
.fermer{position:absolute;top:16px;right:16px;background:none;border:2px solid var(--bleu,#0b1329);border-radius:8px;color:var(--bleu,#0b1329);width:30px;height:30px;cursor:pointer;font-weight:700}
.dlg-note{margin-top:14px;font-family:'IBM Plex Mono',monospace;font-size:11.5px;text-align:center;color:var(--texte-2,#4a5468)}
.dlg-note a{color:var(--malt,#FC5757);font-weight:600}
/* ⚠️ Le champ piège doit rester HORS DE VUE. S'il devient visible, un humain
   le remplit et sa demande est ignorée en silence — le pire des échecs, parce
   qu'il ne se voit ni côté visiteur ni côté boîte de contact. */
.piege{position:absolute;left:-9999px;top:-9999px;height:1px;width:1px;overflow:hidden}
/* Retour du formulaire : l'applicatif renvoie une réponse générique au
   visiteur, mais ses messages d'erreur (adresse invalide, plafond) sont
   affichés tels quels. */
.dlg-msg{display:none;font-size:13.5px;line-height:1.55;border-radius:8px;padding:12px 14px;margin-top:2px}
.dlg-msg.on{display:block}
.dlg-msg.ok{background:var(--fluo,#e8ff3a);border:2px solid var(--bleu,#0b1329);color:var(--encre-sur-fluo,#141804)}
.dlg-msg.ko{background:rgba(239,68,68,.1);border:2px solid #ef4444;color:var(--bleu,#0b1329)}
/* ══ Fenêtre de retour de paiement (08/09/2026) ═══════════════════════════
   Le récapitulatif de ce qui arrive par mail. Il est DENSE — trois lignes que
   le client doit pouvoir relire — donc il est posé sur un aplat, détaché du
   sous-titre, plutôt que fondu dans le corps de la fenêtre. */
.dlg-recap{margin-top:18px;padding:15px 16px;border:2px solid var(--bleu,#0b1329);
  border-radius:10px;background:rgba(11,19,41,.045)}
.dlg-recap:empty{display:none}
.dlg-recap-t{margin:0 0 10px;font-family:'IBM Plex Mono',monospace;font-size:11px;
  letter-spacing:.06em;text-transform:uppercase;color:var(--texte-2,#4a5468)}
.dlg-recap ul{margin:0;padding-left:18px;display:flex;flex-direction:column;gap:8px}
.dlg-recap li{font-size:13.5px;line-height:1.5}
.dlg-recap-d{margin:12px 0 0;font-size:13px;line-height:1.5;color:var(--texte-2,#4a5468)}
/* Les deux appels de la fenêtre : le principal en bouton, le retrait en lien
   nu. `align-items:center` parce qu'un <a class="btn"> et un <button> nus
   n'ont pas la même hauteur de ligne. */
.dlg-actions{margin-top:18px;display:flex;flex-wrap:wrap;gap:12px;align-items:center}
.dlg-actions:empty{display:none}
/* ⚠️ Les deux garde-fous ci-dessous ne servent à rien AUJOURD'HUI (ces blocs
   se vident par `innerHTML`, d'où le `:empty`), et c'est justement pourquoi
   ils sont posés maintenant : le jour où quelqu'un écrira `bloc.hidden = true`,
   il ne se passerait rien. `[hidden]{display:none}` est une règle de l'AGENT,
   `display:flex` une règle d'AUTEUR, et l'auteur gagne — ce piège a déjà livré
   deux fois des boutons « cachés » bien visibles (bloc tarifs, 24/08). */
.dlg-actions[hidden],.dlg-recap[hidden]{display:none}
.dlg-actions .lien-nu{background:none;border:0;padding:0;font:inherit;cursor:pointer;
  color:var(--texte-2,#4a5468);text-decoration:underline;text-underline-offset:3px}
.dlg-actions .lien-nu:hover{color:var(--malt,#FC5757)}
.dlg-actions .lien-nu:focus-visible{outline:3px solid var(--fluo,#e8ff3a);outline-offset:2px}

/* Les boutons de la fenêtre : sur la page sur-mesure, .btn est dessiné pour
   un fond sombre (bord et encre clairs) ; dans la fenêtre, le fond est clair. */
.dlg-in .btn{border-color:var(--bleu,#0b1329);color:var(--bleu,#0b1329);background:none}
.dlg-in .btn-p{background:var(--fluo,#e8ff3a);color:var(--encre-sur-fluo,#141804)}
.dlg-in .btn:hover{background:var(--fluo,#e8ff3a);color:var(--encre-sur-fluo,#141804);box-shadow:4px 4px 0 var(--bleu,#0b1329)}

@media (prefers-reduced-motion:reduce){
  [data-reveal]{opacity:1;transform:none;transition:none}
  .vz,.vz-in{transition:none}
  [data-zoom]::after{transition:none}
}

/* ══ Fenêtre « Parler du projet » — rendez-vous + message (25/08) ══════════
   Une seule fenêtre, deux modes. Le rendez-vous est le chemin principal (la
   vente se joue à l'oral) ; écrire reste offert, en dessous, pour qui ne veut
   pas poser un créneau tout de suite.

   ⚠️ L'agenda (Cal.com) est un TIERS. Son script n'est chargé qu'au clic, jamais au
   chargement de la page — c'est ce qui permet à la recette de continuer à
   exiger zéro requête tierce à l'ouverture du site, et c'est ce que promet
   confidentialite.html. Ne jamais le précharger. */
/* La fenetre du rendez-vous depasse la hauteur d'un portable : sans
   defilement interne, le pied (« Tu preferes ecrire ? ») devient inatteignable
   — donc l'option de repli disparait pour ceux qui en ont le plus besoin. */
dialog{max-height:92vh;overflow-y:auto;overscroll-behavior:contain}
dialog.large{max-width:760px}
.dlg-rdv{margin-top:18px}
.dlg-rdv .cadre-cal{min-height:640px;border:2px solid var(--bleu,#0b1329);border-radius:10px;overflow:hidden;background:#fff}
@media (max-width:640px){.dlg-rdv .cadre-cal{min-height:560px}}
/* Ce que le visiteur voit pendant que le script tiers arrive, et ce qu'il voit
   si le tiers ne répond pas : jamais un cadre vide et muet. */
.dlg-rdv .attente{display:flex;align-items:center;justify-content:center;min-height:640px;padding:20px;text-align:center;font-family:'IBM Plex Mono',monospace;font-size:12px;letter-spacing:.06em;color:var(--texte-2,#4a5468)}
.dlg-bascule{margin:16px 0 0;text-align:center;font-size:13.5px;color:var(--texte-2,#4a5468)}
.dlg-bascule button{background:none;border:0;padding:0;cursor:pointer;font:inherit;color:var(--bleu,#0b1329);font-weight:600;text-decoration:underline;text-underline-offset:3px}
.dlg-bascule button:hover{color:var(--malt,#FC5757)}
.dlg-bascule button:focus-visible{outline:3px solid var(--fluo,#e8ff3a);outline-offset:2px}
/* ⚠️ Sans cette ligne, `form.hidden = true` ne cacherait RIEN : la règle de
   l'agent `[hidden]{display:none}` perd contre `.dlg-in form{display:flex}`,
   qui est une règle d'auteur. Même piège que les boutons de paiement du bloc
   tarifs, relevé le 24/08 — toute classe qui pose `display` doit porter son
   garde-fou `[hidden]`. */
.dlg-in form[hidden],.dlg-rdv[hidden]{display:none}
