/* ============================================================
   Portail client + frise de suivi
   espace-client.css · lignes 257-437 du fichier d'origine
   ============================================================ */
/* ===== Espace client (aperçu du portail) ===== */
.portal-note{background:linear-gradient(135deg,var(--accent-clair),var(--accent));color:#fff;border-radius:14px;padding:14px 16px;margin-bottom:16px;font-size:13px;line-height:1.6}
.portal-note b{font-weight:800}
/* ⚠️ LE FOND EST SOMBRE ET COLORÉ : toute classe qui repose sur la couleur de
   texte par défaut y devient illisible. `.muted` vaut `--ink-faint`, un gris
   foncé — posé ici, il disparaît dans le rose. Constaté le 16/09/2026 sur le
   libellé du lien privé. On neutralise la classe dans ce bloc plutôt que de
   l'éviter au cas par cas : le prochain qui écrira `muted` ici ne saura pas
   qu'il ne faut pas. */
.portal-note .muted{color:rgba(255,255,255,.82)}
.portal-note .lnk{display:flex;gap:8px;align-items:center;margin-top:10px;background:rgba(255,255,255,.14);border-radius:9px;padding:8px 11px;font-family:ui-monospace,monospace;font-size:11.5px;overflow:hidden}
.portal-note .lnk span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}
.portal{border:1px solid var(--line);border-radius:16px;background:var(--surface);overflow:hidden;box-shadow:var(--shadow)}
@media(max-width:720px){
}
.portal-body{padding:20px}
.portal-sec{margin-bottom:24px}
.portal-sec:last-child{margin-bottom:0}
.portal-sec h3{font-size:14px;font-weight:800;margin-bottom:10px;display:flex;align-items:center;gap:8px}
/* ⚠️ LES RÈGLES `.chlist` / `.chrow*` SONT PARTIES AVEC LA PILE DE CARTES
   qu'elles habillaient (20/09/2026) : la liste des chantiers est devenue un
   tableau, comme Facturation et Devis. */
.pdoc{border:1px solid var(--line);border-radius:12px;padding:13px 15px;margin-bottom:9px;background:var(--surface)}
.pdoc.due{border-left:3px solid var(--warn)}
.pdoc.late{border-left:3px solid var(--bad);background:var(--bad-bg)}
.pdoc.paid{border-left:3px solid var(--ok);background:var(--ok-bg)}
.pdoc-top{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:6px}
/* Le titre du document : sur sa propre ligne, il peut passer à la ligne sans
   déplacer quoi que ce soit d'autre. */
.pdoc-titre{font-weight:700;line-height:1.45;margin-bottom:8px}
/* Le montant ET l'état du document, ensemble.
   ⚠️ L'état vivait sur la ligne du TITRE, poussé à droite par un `spacer` :
   dès que le titre passait à la ligne — le cas courant, les intitulés de
   prestation étant longs — l'étiquette se retrouvait seule sur une ligne, et
   se lisait comme une ligne de plus plutôt que comme l'état du document.
   Ici elle ne peut plus être orpheline : le montant tient toujours sur une
   ligne. `align-items:baseline` aligne l'étiquette sur le pied des chiffres
   plutôt que sur leur milieu — 19 px contre 11, le centrage se voit. */
.pdoc-mt{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.pdoc-amt{font-size:19px;font-weight:800;letter-spacing:-.4px}
.pay-btn{background:#1E5AA8;color:#fff;border-color:#1E5AA8;font-weight:800}
.pay-btn:hover{background:#17497f}
.pay-logos{display:flex;gap:6px;align-items:center;margin-top:10px;flex-wrap:wrap}
.pay-logo{border:1px solid var(--line);border-radius:7px;padding:4px 9px;font-size:11px;font-weight:700;color:var(--ink-soft);background:var(--surface)}
.pstep{display:flex;gap:11px;padding:9px 0;font-size:13px;align-items:flex-start}
.pstep .n{width:22px;height:22px;border-radius:50%;background:var(--accent);color:#fff;font-size:11px;font-weight:800;display:grid;place-items:center;flex:0 0 auto}
.pstep.done .n{background:var(--ok)}

/* note interne (équipe uniquement) */
.note-int{margin-top:14px;border:1px dashed color-mix(in srgb,var(--sand) 45%,var(--line));border-radius:11px;background:color-mix(in srgb,var(--sand) 6%,var(--surface-2));padding:11px 13px}
.ni-head{font-size:12px;font-weight:800;color:var(--sand);margin-bottom:7px}
.ni-head .muted{font-weight:400;font-size:11.5px}
.note-int textarea{width:100%;border:1px solid var(--line);border-radius:8px;background:var(--surface);padding:8px 10px;font:inherit;font-size:13px;color:var(--ink);resize:vertical}
.note-int textarea:focus{outline:none;border-color:var(--sand)}

.piece{display:inline-flex;align-items:center;gap:4px;padding:3px 8px;border:1px solid var(--line);border-radius:20px;background:var(--surface-2);font-size:12px}
.piece a{color:var(--accent);cursor:pointer}

.jday{border:1px solid var(--line);border-radius:11px;margin-bottom:8px;overflow:hidden;background:var(--surface)}
.jday-head{display:flex;align-items:center;gap:9px;width:100%;padding:10px 12px;background:var(--surface-2);font-size:13px;text-align:left;transition:.1s}
.jday-head:hover{background:var(--line-soft)}
.jday-head .chev{color:var(--ink-faint);font-size:11px;width:10px}
.jd-date{font-weight:800;text-transform:capitalize}
.jd-sub{color:var(--ink-faint);font-size:11.5px}
.jd-resume{display:flex;gap:5px}
.jd-cnt{background:var(--accent);color:#fff;border-radius:20px;padding:1px 8px;font-size:11px;font-weight:800}
.jsum{display:inline-flex;align-items:center;gap:2px;padding:2px 7px;border-radius:20px;font-size:11.5px;font-weight:700}
.jsum b{font-size:10.5px}
.jday-body{padding:6px 12px 10px}
.jday.fold .jday-body{display:none}
.jitem{display:flex;align-items:flex-start;gap:10px;padding:7px 0;border-bottom:1px solid var(--line-soft);font-size:13px}
.jitem:last-child{border-bottom:none}
.jtxt{flex:1;line-height:1.5}
.jico{width:24px;height:24px;border-radius:50%;display:grid;place-items:center;font-size:12px;font-weight:800;flex:0 0 auto}
.jico.out,.jsum.out{background:var(--info-bg);color:var(--info)}
.jico.in,.jsum.in{background:var(--ok-bg);color:var(--ok)}
.jico.mail,.jsum.mail{background:var(--sand-soft);color:var(--sand)}
.jico.sms,.jsum.sms{background:var(--line-soft);color:var(--ink-soft)}
.jico.rdv,.jsum.rdv{background:color-mix(in srgb,var(--accent) 14%,transparent);color:var(--accent)}
.jico.note,.jsum.note{background:var(--surface-2);color:var(--ink-faint);border:1px solid var(--line)}
/* ⚠️ `1fr` VAUT `minmax(auto,1fr)` : une colonne en `1fr` refuse de passer
   sous la largeur intrinsèque de ce qu'elle contient, et le reste de la
   grille DÉBORDE du panneau. Invisible tant que ce formulaire occupait toute
   la largeur de la page ; le jour où le journal des échanges est passé en
   demi-colonne (19/09/2026), le bouton « Ajouter » sortait du cadre.
   `minmax(0,…)` autorise le rétrécissement. */
.jform{display:grid;grid-template-columns:minmax(0,170px) minmax(0,150px) minmax(0,1fr) auto;
  gap:8px;align-items:center;margin-bottom:14px}
.jform > *{min-width:0}
/* En demi-colonne, la zone de saisie prend sa propre ligne : trois champs et
   un bouton sur 550 px donnent quatre cases où l'on ne peut rien lire.
   ⚠️ LA RÈGLE VISE `.grid-2 .jform`, PAS `.jform`. Ce qui est étroit ici,
   c'est la COLONNE, pas l'écran : à 1440 px de large, une demi-colonne fait
   550 px. Une requête média seule aurait aussi cassé le même formulaire dans
   l'espace client, où il occupe toute la largeur et tient très bien. */
@media(max-width:1700px){
  .grid-2 .jform{grid-template-columns:minmax(0,1fr) minmax(0,1fr) auto}
  .grid-2 .jform > :nth-child(3){grid-column:1 / -1}
}

/* ⚠️ LES RÈGLES DE LA BANDE « Devis à envoyer » SONT PARTIES AVEC ELLE
   (20/09/2026) : `.kband*`, `.bcard`, `.bc-txt`, `.bc-tags`, et le long
   commentaire qui expliquait comment ses étiquettes passaient à la ligne.
   « Devis à envoyer » est devenue la cinquième colonne du kanban. Seule
   `.tag.sand` reste : la colonne s'en sert pour dire « à créer ». */
.tag.sand{background:var(--sand-soft);color:var(--sand)}

/* La colonne « Devis à envoyer » : le nom, puis l'état du devis.
   ⚠️ `flex-basis:110px` SUR LE NOM EST CE QUI FORCE LE PASSAGE À LA LIGNE.
   Avec `flex:1` seul, le nom rétrécit indéfiniment et finit en « Amandine
   R… » pour laisser la place à l'étiquette ; avec une base, dès que les deux
   ne tiennent plus, c'est l'étiquette qui descend. `min-width:0` ne suffit
   PAS : il autorise le nom à rétrécir, il n'empêche pas l'étiquette de tout
   prendre. (Leçon reprise de l'ancienne bande « Devis à envoyer », qui a
   disparu le 20/09/2026 — le défaut, lui, ne disparaît pas tout seul.) */
.kcard.kc-devis{flex-wrap:wrap}
.kc-nom{min-width:0;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.kcard.kc-devis > .kc-nom{flex:1 1 110px;white-space:normal;overflow:visible;text-overflow:clip}

/* planning : présences & affectations */
.today-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:12px}
.tcard{border:1px solid var(--line);border-left:4px solid var(--line);border-radius:12px;padding:12px;background:var(--surface-2)}
.tcard.chantier{border-left-color:var(--info)}
.tcard.conge{border-left-color:var(--warn)}
.tcard.libre{border-left-color:var(--ink-faint)}
.tc-top{display:flex;align-items:center;gap:8px;margin-bottom:10px}
.tc-body{font-size:12.5px;min-height:52px}
.tcard .mini{margin-top:8px}
table.pgrid th{text-align:center;font-size:11.5px}
table.pgrid th:first-child{text-align:left}
table.pgrid th.we{background:var(--surface-2);color:var(--ink-faint)}
table.pgrid th.now{color:var(--accent)}
table.pgrid td.pc{padding:4px;vertical-align:top}
.pcell{border-radius:8px;padding:6px 7px;font-size:11px;line-height:1.35;min-height:44px;display:flex;flex-direction:column;justify-content:center;text-align:center}
.pcell b{font-size:11px;font-weight:800;display:block}
.pcell span{color:inherit;opacity:.8;font-size:10.5px}
.pcell.ch{background:var(--info-bg);color:var(--info);cursor:pointer}
.pcell.ch:hover{filter:brightness(.96)}
.pcell.cg{background:var(--sand-soft);color:var(--sand);font-weight:700}
.pcell.free{background:var(--surface-2);color:var(--ink-faint)}
.pcell.we{background:transparent}

/* filtres segmentés (portefeuille clients) */
.segbar{display:inline-flex;border:1px solid var(--line);border-radius:9px;overflow:hidden}
.seg{padding:8px 13px;background:var(--surface);font-weight:600;font-size:12.5px;color:var(--ink-soft);border-right:1px solid var(--line);transition:.1s}
.seg:last-child{border-right:none}
.seg:hover{background:var(--surface-2);color:var(--ink)}
.seg.on{background:var(--accent);color:#fff}

/* chantiers : grandes étiquettes + équipes */
.chtiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:14px;margin-bottom:22px}
.chtile{background:var(--surface);border:1px solid var(--line);border-left:4px solid var(--warn);border-radius:14px;padding:15px;box-shadow:var(--shadow);cursor:pointer;transition:.12s}
.chtile:hover{transform:translateY(-2px);border-left-color:var(--accent)}
.chtile-top{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px}
.chtile-title{font-size:16px;font-weight:800;letter-spacing:-.3px}
.chtile-cli{color:var(--ink-soft);font-weight:600;font-size:13px;margin-top:2px}
.chtile-meta{display:flex;flex-wrap:wrap;gap:10px;margin-top:10px;font-size:12px;color:var(--ink-soft);font-weight:600}
.chtile-team{margin-top:10px}
/* Étiquettes KPI cliquables (filtre chantiers) */
.kpi.filt{cursor:pointer;user-select:none;transition:.12s}
.kpi.filt:hover{transform:translateY(-1px);border-color:var(--accent)}
.kpi.filt.on{border-color:var(--accent);box-shadow:inset 0 0 0 2px var(--accent),var(--shadow)}
/* Liste des chantiers en cartes pleine largeur, empilées */
.chips{display:flex;flex-wrap:wrap;gap:6px}
.chip{padding:5px 11px;border:1px solid var(--line);border-radius:20px;background:var(--surface);font-weight:600;font-size:12.5px;color:var(--ink-soft);transition:.1s}
.chip:hover{border-color:var(--accent)}
.chip.on{background:var(--accent);color:#fff;border-color:var(--accent)}
.chip.sm{padding:3px 9px;font-size:11.5px}
/* --- Frise chronologique du statut prospect (style suivi de colis) --- */
.lead-timeline{display:flex;align-items:flex-start;margin:4px 0 16px;overflow-x:auto}
.ltl-step{flex:1;min-width:62px;position:relative;display:flex;flex-direction:column;align-items:center;gap:7px;background:none;border:none;padding:0 2px;cursor:pointer}
.ltl-step::before{content:'';position:absolute;top:13px;right:50%;width:100%;height:2px;background:var(--line);z-index:0}
.ltl-step:first-child::before{display:none}
.ltl-dot{position:relative;z-index:1;width:26px;height:26px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;background:var(--surface);border:2px solid var(--line);color:var(--ink-faint);transition:.15s}
.ltl-lab{font-size:11px;line-height:1.25;color:var(--ink-faint);max-width:86px}
.ltl-step.done::before,.ltl-step.current::before{background:var(--accent)}
.ltl-step.done .ltl-dot{background:var(--accent);border-color:var(--accent);color:#fff}
.ltl-step.done .ltl-lab{color:var(--ink-soft)}
.ltl-step.current .ltl-dot{background:var(--surface);border-color:var(--accent);color:var(--accent);box-shadow:0 0 0 4px var(--ok-bg)}
.ltl-step.current .ltl-lab{color:var(--ink);font-weight:700}
.lead-timeline:not(.ro) .ltl-step:hover .ltl-dot{border-color:var(--accent)}
.lead-timeline:not(.ro) .ltl-step:hover .ltl-lab{color:var(--ink)}
.lead-timeline.ro .ltl-step{cursor:default}
.ltl-step.refused::before{background:var(--bad)}
.ltl-step.refused .ltl-dot{background:var(--bad);border-color:var(--bad);color:#fff}
.ltl-step.refused .ltl-lab{color:var(--bad);font-weight:700}
.lead-timeline.is-lost .ltl-dot{border-style:dashed;opacity:.55}
.lead-timeline.is-lost .ltl-lab{opacity:.55}
/* Frise "vue d'ensemble" avec compteurs, alignée sur les colonnes du kanban */
.ct-wrap{margin:2px 0 14px;gap:12px;overflow-x:auto;padding:7px 4px 5px}
.ct-wrap .ltl-step{flex:1 1 160px;min-width:150px}
.ct-wrap .ltl-dot{width:36px;height:36px;font-size:15px;font-weight:800}
.ct-wrap .ltl-step::before{top:18px;width:calc(100% + 12px)}
.ct-wrap .ltl-lab{font-size:11.5px;color:var(--ink-soft)}
.ct-wrap .ltl-step.zero .ltl-lab{color:var(--ink-faint)}
.ct-wrap .ltl-step[onclick]:hover .ltl-dot{box-shadow:0 0 0 3px var(--line)}
.ct-wrap .ltl-step.ct-on .ltl-dot{box-shadow:0 0 0 3px var(--accent)}
.ct-wrap .ltl-step.ct-on .ltl-lab{color:var(--ink);font-weight:800}
.poste-row{display:flex;align-items:center;gap:12px;padding:10px 0;border-bottom:1px solid var(--line-soft);flex-wrap:wrap}
.poste-row.done .poste-lab{text-decoration:line-through;color:var(--ink-faint)}
.paidcard{border:1px solid color-mix(in srgb,var(--ok) 30%,var(--line));border-radius:11px;background:var(--ok-bg);padding:11px 13px;margin-bottom:8px}
.paidcard .pc-top{display:flex;align-items:center;gap:8px;margin-bottom:5px;font-weight:800;font-size:13.5px}
.paidcard .pc-row{display:flex;justify-content:space-between;font-size:12.5px;color:var(--ink-soft)}
.paidcard .pc-row b{color:var(--ink);font-variant-numeric:tabular-nums}

.pcheck{width:22px;height:22px;border-radius:6px;border:1.5px solid var(--line);background:var(--surface);color:#fff;font-size:13px;font-weight:800;flex:0 0 auto;transition:.12s}
.pcheck:hover{border-color:var(--accent)}
.pcheck.on{background:var(--ok);border-color:var(--ok)}
.poste-row:last-child{border-bottom:none}
.poste-lab{font-weight:700;min-width:150px;flex:0 0 auto}
.poste-row .chips{flex:1}
/* Ligne avenant (fiche chantier) */
.av-row{display:flex;align-items:center;gap:10px;padding:10px 12px;border:1px solid var(--line);border-radius:10px;background:var(--surface-2)}
.av-row .av-title{flex:1;min-width:0;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.av-row .av-amt{font-weight:800;white-space:nowrap;font-variant-numeric:tabular-nums}
.av-row .av-act{display:flex;gap:6px;align-items:center;flex-shrink:0;margin:0}

/* ============================================================
   Mode portail — la page ouverte par le lien d'un client
   ============================================================
   Le client ne doit rien voir de l'application interne : ni menu, ni barre
   d'outils, ni barre d'onglets mobile. La grille à deux colonnes redevient
   une seule colonne, centrée. */
:root[data-portail] .app{grid-template-columns:1fr;}
:root[data-portail] .sidebar,
:root[data-portail] .topbar,
:root[data-portail] .tabbar,
:root[data-portail] .sb-backdrop{display:none !important;}
@media (max-width:720px){
}

/* ============================================================
   Les décisions du client, les unes SOUS les autres
   ------------------------------------------------------------
   `.mc-act` range ses boutons en ligne avec retour automatique
   (`flex:1;min-width:110px`). Sur une carte de devis à quatre actions, cela
   donnait deux colonnes de boutons étroits, où « Demander une modification »
   se cassait sur trois lignes et où « J'accepte ce devis » se retrouvait à
   côté de « Je ne donne pas suite » — deux gestes opposés, de même taille,
   côte à côte. C'est exactement la disposition qui fait cliquer à côté.

   Empilés, ils se lisent dans l'ordre où l'on décide : regarder, accepter,
   discuter, renoncer.

   ⚠️ Cette règle ne vise QUE les cartes de document (`.pdoc-act`). `.mc-act`
   sert ailleurs dans l'application, sur des paires de boutons courts où la
   mise en ligne est la bonne.

   ⚠️ LES SÉLECTEURS S'ÉCRIVENT `.mc-act.pdoc-act`, LES DEUX CLASSES ENSEMBLE,
   et ce n'est pas une coquetterie. `.mc-act` vit dans `mobile.css`, qui se
   charge APRÈS ce fichier (ligne 30 contre 26 dans index.html). Écrit
   `.pdoc-act .btn`, le sélecteur aurait la MÊME spécificité que
   `.mc-act .btn` — et à spécificité égale, c'est le dernier chargé qui gagne.
   La règle n'aurait donc strictement rien fait, en silence. Accoler les deux
   classes fait passer la spécificité au-dessus, quel que soit l'ordre des
   fichiers. C'est le même piège de cascade que celui déjà documenté pour
   `peau.css`.
   ============================================================ */
.mc-act.pdoc-act{flex-direction:column;align-items:stretch;gap:9px}
.mc-act.pdoc-act .btn{
  flex:none;                 /* sinon `flex:1` de .mc-act les étire à la verticale */
  width:100%;
  min-width:0;               /* la largeur ne vient plus du texte le plus long */
  justify-content:center;
  white-space:normal;        /* un libellé long se replie plutôt que de déborder */
}

/* Au-delà du téléphone, la ligne redevient naturelle : la carte est large, et
   quatre boutons empilés y feraient une colonne inutilement haute. */
@media (min-width:721px){
  .mc-act.pdoc-act{flex-direction:row;flex-wrap:wrap;align-items:center}
  .mc-act.pdoc-act .btn{flex:1;width:auto;min-width:150px}
}

/* ---------- les portes de l'espace client ----------
   ⚠️ CE SONT DES BOUTONS, PAS DES CARTES. Un client doit voir au premier
   coup d'œil qu'on peut cliquer : une carte élégante mais inerte à l'œil se
   fait ignorer, et l'information reste derrière. D'où la flèche, toujours au
   même endroit, et un état pressé franc.
   ⚠️ 56 px de haut minimum : l'espace se consulte au doigt, souvent dehors. */
.portal-porte{
  display:flex;align-items:center;gap:13px;width:100%;min-height:56px;
  padding:12px 14px;border:1px solid var(--line);border-radius:13px;
  background:var(--surface);cursor:pointer;text-align:left;
  font:inherit;color:inherit;transition:border-color .12s,transform .12s;
}
.portal-porte:hover{border-color:var(--accent)}
.portal-porte:active{transform:scale(.995)}
.portal-porte .pp-ico{
  flex:0 0 auto;width:36px;height:36px;border-radius:10px;
  display:grid;place-items:center;font-size:16px;
  background:var(--surface-2);border:1px solid var(--line);
}
.portal-porte .pp-txt{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.portal-porte .pp-txt b{font-size:14.5px}
.portal-porte .pp-txt .muted{font-size:12px}
.portal-porte .pp-fleche{flex:0 0 auto;font-size:19px;opacity:.35}

/* ⚠️ « Urgent » ne veut pas dire rouge : ici ce n'est pas une alerte, c'est ce
   qu'on attend du client. Un liseré suffit à le faire remarquer sans donner
   l'impression qu'il a fait quelque chose de mal. */
.portal-porte.urgent{border-color:var(--accent);background:var(--accent-wash)}
.portal-porte.urgent .pp-ico{border-color:var(--accent)}

/* ---------- la bulle d'un message ----------
   ⚠️ « 82 % » ÉTAIT UNE MESURE DE TÉLÉPHONE. Sur un écran large, 82 % d'une
   colonne de 900 px donne des bulles de 740 px : trois mots par ligne
   deviennent une bande qui traverse l'écran, et la conversation cesse de se
   lire comme une conversation. On borne donc en CARACTÈRES, pas en
   pourcentage — c'est la longueur de ligne qui compte pour lire, jamais la
   largeur du contenant. */
.pmsg{max-width:min(82%, 34em)}
/* ⚠️ UNE CONVERSATION N'EST PAS UNE PAGE. Sur grand écran, le fil s'étalait
   sur toute la largeur du cadre : le bouton « Poser une question » faisait
   1 300 px de long et les bulles se perdaient au bord droit, loin de l'œil
   qui vient de lire la précédente. On lui donne la largeur d'une colonne de
   lecture ; le téléphone, lui, garde toute la sienne. 16/09/2026. */

/* ---------- « Nous contacter » : des noms qu'on appelle ----------
   ⚠️ SUR TÉLÉPHONE, LES BOUTONS PASSENT SOUS L'ADRESSE, l'un au-dessus de
   l'autre : côte à côte, deux boutons de 150 px sur un écran de 390 px
   donnent deux libellés coupés. `flex-wrap` suffit — aucune deuxième règle
   à tenir à jour. Demandé le 16/09/2026. */
.portal-contact{display:flex;gap:18px;align-items:flex-start;flex-wrap:wrap}
.pc-infos{flex:1 1 220px;min-width:200px;font-size:13px;line-height:1.8}
/* ⚠️ `flex:1 1 440px` — LA PLACE DES DEUX BOUTONS, PAS D'UN SEUL. À 210 px de
   base, ils se partageaient 265 px chacun et « Appeler Jérôme » passait à la
   ligne quand « Appeler Victor », plus court, tenait : deux boutons jumeaux
   d'allure différente. Vu à l'écran le 16/09/2026. */
.pc-appel{display:flex;flex-direction:column;gap:8px;flex:1 1 440px;text-align:center}
.pc-lab{font-size:11.5px;font-weight:800;text-transform:uppercase;letter-spacing:.5px;color:var(--ink-faint)}
/* ⚠️ CÔTE À CÔTE, ET DE MÊME LARGEUR : `flex:1 1 0` donne deux boutons égaux,
   Jérôme à gauche, Victor à droite. Empilés dans le coin, ils avaient l'air
   rangés là faute de place. Demandé le 16/09/2026. */
.pc-boutons{display:flex;gap:8px;justify-content:center}
.pc-boutons .pc-tel{flex:1 1 0;min-width:0;text-align:left}
/* ⚠️ C'EST UN LIEN `tel:`, IL DOIT AVOIR L'AIR D'UN BOUTON. Un numéro écrit
   en gris au fil d'une ligne ne se compose pas : sur un téléphone il faut le
   sélectionner à la main, sur un ordinateur il ne mène nulle part. */
.pc-tel{display:flex;align-items:center;gap:10px;padding:9px 13px;min-height:46px;
  border:1px solid var(--line);border-radius:12px;background:var(--surface);
  color:inherit;text-decoration:none;transition:border-color .12s,transform .12s}
.pc-tel:hover{border-color:var(--accent)}
.pc-tel:active{transform:scale(.99)}
.pc-tel .pc-ico{flex:0 0 auto;width:30px;height:30px;border-radius:9px;display:grid;place-items:center;
  background:var(--accent-wash);border:1px solid var(--accent);color:var(--accent);font-size:14px}
.pc-tel .pc-txt{display:flex;flex-direction:column;line-height:1.35}
.pc-tel .pc-txt b{font-size:13.5px}
.pc-tel .pc-txt .muted{font-size:12px}
@media(max-width:720px){
  .portal-contact{flex-direction:column;gap:14px}
  /* ⚠️ `flex:0 0 auto` POUR LES DEUX BLOCS, et toujours pour la même raison :
     en colonne, `flex-basis` compte en HAUTEUR. Le bloc d'appel, basé sur
     440 px pour tenir deux boutons côte à côte, devenait haut de 440 px dès
     que la carte passait en colonne — un vide de la moitié de l'écran sous
     les deux boutons. Deuxième fois le 16/09/2026 : c'est le même piège des
     deux côtés de la carte. */
  .pc-appel{width:100%;min-width:0;text-align:left;flex:0 0 auto}
  /* Sur téléphone, l'un AU-DESSUS de l'autre : côte à côte, deux boutons de
     170 px coupent leurs libellés en deux. */
  .pc-boutons{flex-direction:column}
  /* ⚠️ `flex:1 1 220px` EN COLONNE, C'EST 220 px DE HAUTEUR : le bloc adresse
     se retrouvait haut de 220 px, avec un grand vide sous les trois lignes
     avant « Nous appeler ». `flex-basis` suit la direction du conteneur, et
     elle change ici. Vu à l'écran le 16/09/2026. */
  .pc-infos{flex:0 0 auto}
}

/* ---------- la navigation de l'espace, sur grand écran ---------- */
@media(min-width:721px){
  /* ⚠️ DEUX PORTES PAR LIGNE. En pleine largeur, quatre bandes empilées de
     900 px font une liste de téléphone agrandie : beaucoup de vide à droite
     de chaque titre, et le regard descend au lieu de balayer. */
  /* ⚠️ EN COLONNES, PAS EN LIGNES : « mes factures sous mes devis, mes
     échanges sous mes photos » — les documents d'un côté, la vie du chantier
     de l'autre. En flux par ligne, les factures se retrouvaient à DROITE des
     devis et la paire n'avait plus de sens. Demandé le 16/09/2026. */
  .portal-body{padding:24px 28px}
}

/* Les onglets : la même navigation, mais permanente.
   ⚠️ Ils ne remplacent le bouton « Retour » que sur grand écran — sur
   téléphone ils mangeraient la moitié du premier écran, pour un geste qui
   s'y fait très bien avec une flèche. */
  display:flex;gap:4px;flex-wrap:wrap;
  border-bottom:1px solid var(--line);
  margin:0 0 20px;padding-bottom:0;
}
  display:flex;align-items:center;gap:7px;
  padding:9px 14px;border:0;background:none;cursor:pointer;
  font:inherit;font-size:13.5px;color:var(--ink-soft);
  border-bottom:2px solid transparent;margin-bottom:-1px;
  transition:color .12s,border-color .12s;
}
/* ⚠️ L'onglet actif se marque par un TRAIT, pas par un fond : un fond coloré
   sur cinq onglets ferait cinq boutons d'égale importance, et on ne verrait
   plus lequel est ouvert. */

/* Le pied de l'accueil : les conditions générales, et rien d'autre.
   ⚠️ SÉPARÉ PAR UN TRAIT et posé sous « Nous contacter » — un lien légal qui
   remonterait dans le menu dirait qu'il compte autant qu'une facture à payer. */
.portal-pied{border-top:1px solid var(--line);margin-top:22px;padding-top:14px;
  display:flex;flex-direction:column;gap:9px}

/* ---------- le bouton « avis Google » ----------
   ⚠️ C'EST LE GESTE DE LA PAGE, il en a donc l'allure : plein, pleine largeur,
   et assez haut pour un pouce. En bouton fantôme sous un paragraphe gris, il
   passait pour une note de bas de page. Signalé le 17/09/2026.
   ⚠️ La peau du portail redéfinit tous les `.btn` avec une sélectivité plus
   forte et une feuille chargée APRÈS : d'où le doublon sous
   `:root[data-portail]`. Même piège que `.pchat-envoi` — ne pas « dédoublonner ». */
/* Le bouton d'avis : plein comme tout bouton principal du portail, et un peu
   plus haut — c'est la seule chose qu'on demande vraiment sur cette page. */
.avis-google{
  display:flex;align-items:center;justify-content:center;gap:9px;width:100%;
  min-height:52px;font-size:15px;text-decoration:none;
}
.avis-google .ag-ico{font-size:17px}

/* ---------- le champ d'écriture de la conversation ----------
   ⚠️ IL EST TOUJOURS LÀ, sous les messages : c'est ce qui fait la différence
   entre une messagerie et un historique en lecture seule. Il a remplacé un
   bouton « Poser une question » qui ouvrait une fenêtre — un clic pour
   découvrir un champ de texte. Demandé le 16/09/2026. */
.pchat{display:flex;gap:8px;align-items:flex-end}
.pchat-txt{
  flex:1;min-width:0;resize:none;overflow-y:auto;max-height:132px;
  border:1px solid var(--line);border-radius:14px;background:var(--surface);
  padding:11px 14px;font:inherit;font-size:13.5px;line-height:1.5;color:var(--ink);
}
.pchat-txt:focus{outline:none;border-color:var(--accent)}
/* Rond, et de la taille d'un doigt : c'est le geste de la page. */
.pchat-envoi{
  flex:0 0 auto;width:44px;height:44px;padding:0;border-radius:50%;
  display:grid;place-items:center;font-size:16px;
  /* ⚠️ PLEIN, pas fantôme : c'est l'action de l'écran. En rose pâle il se
     confondait avec le champ qu'il accompagne. Vu à l'écran le 16/09/2026. */
  background:var(--accent);border-color:var(--accent);color:#fff;
}
.pchat-envoi:hover{filter:brightness(1.07)}
/* ⚠️ PLUS DE COULEUR À FORCER ICI : depuis le 17/09/2026, un `.btn` du portail
   est PLEIN par défaut (peau.css § 13). Il ne reste que la FORME — un rond de
   44 px —, que la peau ne connaît pas. Si un jour ce bouton redevient pâle,
   c'est la règle générale qu'il faut regarder, pas ce bloc. */
:root[data-portail] .pchat .pchat-envoi{
  min-height:44px;width:44px;padding:0;border-radius:50%;
}

/* Un texte de référence se lit en colonne, pas en pleine page : au-delà d'une
   quarantaine de caractères par ligne, l'œil perd le début de la suivante. */
@media(min-width:721px){ .portal-lecture{max-width:46em} }

/* ============================================================
   L'ESPACE CLIENT COMME APPLICATION
   ------------------------------------------------------------
   Deux coques pour une seule page : un rail fixe à gauche sur grand écran,
   une barre d'en-tête et une barre d'onglets sur téléphone.

   ⚠️ AUCUNE COULEUR NOUVELLE — prune, crème, encre, celles de la charte.
   Ce qui change est la STRUCTURE.
   ⚠️ LE PORTAIL PREND TOUT L'ÉCRAN. `:root[data-portail] .content` était
   plafonné à 960 px et centré : sur 1440 px, cela donnait une bande étroite
   au milieu du vide — une application de téléphone agrandie. Voir la règle
   qui l'annule, plus bas.
   ============================================================ */
.pa{display:grid;grid-template-columns:264px minmax(0,1fr);align-items:start;
  background:var(--paper);min-height:100%}

/* ---------- le rail (grand écran) ---------- */
.pa-rail{position:sticky;top:0;align-self:start;height:100vh;overflow-y:auto;
  display:flex;flex-direction:column;gap:4px;padding:22px 16px 20px;
  background:var(--surface);border-right:1px solid var(--line)}
.pa-marque{display:flex;align-items:center;gap:11px;margin-bottom:18px}
.pa-marque-txt{min-width:0;display:flex;flex-direction:column;line-height:1.3}
.pa-marque-txt b{font-size:14.5px;letter-spacing:-.2px}
.pa-marque-txt .muted{font-size:11.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pa-qui{display:flex;flex-direction:column;gap:1px;padding:10px 12px;margin-bottom:16px;
  background:var(--surface-2);border-radius:10px}
.pa-qui .muted{font-size:11px;text-transform:uppercase;letter-spacing:.5px;font-weight:700}
.pa-qui b{font-size:14px}
.pa-nav{display:flex;flex-direction:column;gap:2px}
.pa-lien{display:flex;align-items:center;gap:11px;width:100%;padding:10px 12px;
  border:none;background:none;border-radius:10px;cursor:pointer;
  font-size:14px;font-weight:600;color:var(--ink-soft);text-align:left;
  font-family:inherit;transition:background .12s,color .12s}
.pa-lien:hover{background:var(--surface-2);color:var(--ink)}
.pa-lien.on{background:var(--accent-wash);color:var(--accent-ink);font-weight:800}
.pa-ico{width:20px;text-align:center;font-size:15px;flex:0 0 auto;opacity:.9}
.pa-nav-sec .pa-lien{font-size:13px;font-weight:500;padding:8px 12px}
.pa-sep{height:1px;background:var(--line);margin:14px 4px}
  border:1px solid var(--line);border-radius:12px;background:var(--surface-2);
  text-decoration:none;color:var(--ink);font-size:13px}

/* ---------- le contenu ---------- */
.pa-main{min-width:0}
.pa-vue{padding:30px 34px 60px;max-width:1120px}
.pa-titre{font-size:24px;font-weight:800;letter-spacing:-.5px;margin:0 0 20px}
.pa-top{display:none}
.pa-tabs{display:none}

/* ---------- le héros ---------- */
.pa-hero{display:flex;align-items:center;gap:20px;flex-wrap:wrap;
  padding:22px 24px;border-radius:16px;margin-bottom:18px;
  border:1px solid var(--line);background:var(--surface);box-shadow:var(--shadow)}
.pa-hero-txt{flex:1;min-width:220px}
.pa-hero-sur{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;
  color:var(--ink-faint);margin-bottom:4px}
.pa-hero-gros{font-size:32px;font-weight:800;letter-spacing:-1px;line-height:1.1;
  font-variant-numeric:tabular-nums}
.pa-hero-sous{font-size:13.5px;color:var(--ink-soft);margin-top:6px;max-width:62ch;line-height:1.55}
.pa-hero-act .btn{white-space:nowrap}
/* Trois tons, trois significations — et le ton porte la couleur, jamais le
   texte : « à régler » en rouge sur fond rouge ne se lit plus. */
.pa-hero.du{border-color:color-mix(in srgb,var(--warn) 42%,var(--line));
  background:color-mix(in srgb,var(--warn) 7%,var(--surface))}
.pa-hero.du .pa-hero-gros{color:var(--warn)}
.pa-hero.attente{border-color:color-mix(in srgb,var(--accent) 38%,var(--line));
  background:color-mix(in srgb,var(--accent) 5%,var(--surface))}
.pa-hero.ok{border-color:color-mix(in srgb,var(--ok) 34%,var(--line));
  background:color-mix(in srgb,var(--ok) 6%,var(--surface))}
.pa-hero.ok .pa-hero-gros{color:var(--ok);font-size:22px;letter-spacing:-.4px}

/* ---------- les quatre tuiles ---------- */
.pa-tuiles{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin-bottom:20px}
.pa-tuile{display:flex;flex-direction:column;gap:2px;align-items:flex-start;
  padding:15px 16px;border:1px solid var(--line);border-radius:14px;
  background:var(--surface);cursor:pointer;text-align:left;font-family:inherit;
  transition:border-color .12s,transform .12s,box-shadow .12s}
.pa-tuile:hover{border-color:var(--accent);transform:translateY(-1px);box-shadow:var(--shadow)}
.pa-tuile-ico{font-size:16px;opacity:.55;margin-bottom:5px}
.pa-tuile-val{font-size:21px;font-weight:800;letter-spacing:-.5px;color:var(--ink);
  font-variant-numeric:tabular-nums;line-height:1.15}
.pa-tuile-lab{font-size:13px;font-weight:700;color:var(--ink)}
.pa-tuile-sous{font-size:11.5px}
.pa-tuile.urgent{border-color:color-mix(in srgb,var(--warn) 45%,var(--line));
  background:color-mix(in srgb,var(--warn) 6%,var(--surface))}
.pa-tuile.urgent .pa-tuile-val{color:var(--warn)}

/* ---------- deux colonnes sous les tuiles ---------- */
.pa-colonnes{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(0,1fr);gap:18px;align-items:start}
.pa-colonnes .portal-sec{margin-bottom:18px}
.pa-annexes{display:grid;gap:8px}

/* ⚠️ LE PORTAIL PREND TOUT L'ÉCRAN : on annule ici le plafond de 960 px et
   les marges que `.content` impose au reste de l'application. */
:root[data-portail] .content{max-width:none;margin:0;padding:0}
:root[data-portail] .pa{min-height:100vh}

/* ============================================================
   TÉLÉPHONE : une vraie application
   ⚠️ Le rail disparaît, l'en-tête et les onglets prennent le relais. Le
   bouton « Retour » n'existe plus : on ne revient pas, on change d'onglet.
   ============================================================ */
@media(max-width:1000px){
  .pa{grid-template-columns:1fr}
  .pa-rail{display:none}
  .pa-vue{padding:16px 14px 24px}
  .pa-titre{font-size:20px;margin-bottom:14px}
  .pa-top{display:flex;align-items:center;gap:11px;padding:11px 14px;
    background:var(--surface);border-bottom:1px solid var(--line);
    position:sticky;top:0;z-index:20}
  .pa-top-txt{min-width:0;display:flex;flex-direction:column;line-height:1.3}
  .pa-top-txt b{font-size:14px}
  .pa-top-txt .muted{font-size:11.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  /* ⚠️ PLUS DE NOMBRE DE COLONNES FIGÉ. La barre était `repeat(5,1fr)` :
     une sixième section — « Mes chantiers », ou celle qu'un module déclare —
     passait à la ligne et doublait la hauteur de la barre, qui FLOTTE au bas
     de l'écran : elle recouvrait alors le contenu. En flex, les onglets se
     partagent la largeur, et au-delà de ce qui tient la barre défile
     latéralement — seule elle, jamais la page. */
  .pa-tabs{display:flex;gap:2px;overflow-x:auto;scrollbar-width:none;
    background:var(--surface);border-top:1px solid var(--line);
    padding:6px 4px calc(6px + env(safe-area-inset-bottom,0))}
  .pa-tabs::-webkit-scrollbar{display:none}
  .pa-tab{flex:1 0 58px;min-width:0;display:flex;flex-direction:column;align-items:center;gap:3px;
    padding:7px 2px;border:none;background:none;border-radius:10px;cursor:pointer;
    font-family:inherit;font-size:10.5px;font-weight:700;color:var(--ink-faint);min-height:52px}
  .pa-tab.on{color:var(--accent-ink);background:var(--accent-wash)}
  .pa-tab-ico{font-size:17px;line-height:1}
  .pa-hero{padding:17px 18px;border-radius:14px;gap:14px}
  .pa-hero-gros{font-size:27px}
  .pa-hero-act{width:100%}
  .pa-hero-act .btn{width:100%;justify-content:center}
  /* Deux par deux : quatre tuiles en ligne sur 390 px seraient illisibles. */
  .pa-tuiles{grid-template-columns:1fr 1fr;gap:9px;margin-bottom:16px}
  .pa-tuile{padding:12px 13px;border-radius:12px}
  .pa-tuile-val{font-size:18px}
  .pa-colonnes{grid-template-columns:1fr;gap:0}
  /* ⚠️ LA BARRE FIXE N'EXISTE QUE DANS LE VRAI PORTAIL. En aperçu, la page
     vit dans l'application interne : une barre collée à la fenêtre se
     poserait par-dessus le menu de l'équipe. */
  :root[data-portail] .pa-tabs{position:fixed;left:0;right:0;bottom:0;z-index:30}
  :root[data-portail] .pa-vue{padding-bottom:90px}
}
/* ⚠️ LES ANNEXES NE S'AFFICHENT QU'UNE FOIS. Sur grand écran elles vivent
   dans le rail ; les répéter en bas de l'accueil donnait « Conditions
   générales » à deux endroits du même écran. Sur téléphone il n'y a pas de
   rail : c'est là qu'elles reviennent. */
.pa-annexes{display:none}
@media(max-width:1000px){ .pa-annexes{display:grid} }
/* Voir la note dans espace-client.js : le titre de page nomme la section, le
   titre interne qui le suit immédiatement ferait doublon. */
.pa-tete + .portal-sec > h3{display:none}
.pa-tete + .portal-sec{margin-top:0}

/* ============================================================
   PLEINE LARGEUR, PHOTOS EN GRAND, CONVERSATION PLEIN ÉCRAN
   Demandé le 19/09/2026.
   ============================================================ */

/* ⚠️ PLUS DE PLAFOND SUR LE CONTENU. `.pa-vue` était bridé à 1 120 px : sur un
   écran de 1 600, la page s'arrêtait au milieu et le reste était du vide. Le
   rail borne déjà la colonne à gauche ; à droite, on prend ce qu'il y a. */
.pa-vue{max-width:none}

/* Le chantier et le pied de page occupent toute la largeur disponible. */
.pa-plein > .portal-sec{margin-bottom:18px}
.pa-pied{margin-top:26px;padding-top:22px;border-top:1px solid var(--line)}
.pa-pied .portal-sec{margin-bottom:0}

/* ---------- les photos ----------
   ⚠️ 260 px AU MINIMUM, ET LE FORMAT 4/3 — celui des appareils photo. À 104 px
   et en carré, six photos formaient une ligne de timbres-poste en haut d'une
   page vide : on ne voyait rien de ce qu'on était venu voir. */
.pphotos{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:16px}
.pphoto{margin:0;cursor:pointer;border-radius:14px;overflow:hidden;
  border:1px solid var(--line);background:var(--surface);
  transition:transform .14s,box-shadow .14s,border-color .14s}
.pphoto:hover{transform:translateY(-2px);box-shadow:var(--shadow);border-color:var(--accent)}
.pphoto img{width:100%;aspect-ratio:4/3;object-fit:cover;display:block;background:var(--surface-2)}
.pphoto figcaption{padding:10px 13px;font-size:13px;line-height:1.45;color:var(--ink)}
@media(max-width:1000px){
  .pphotos{grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px}
  .pphoto figcaption{padding:8px 10px;font-size:12px}
}

/* ---------- la conversation ----------
   ⚠️ LE PANNEAU PREND L'ÉCRAN, LA BULLE RESTE ÉTROITE. Une ligne de texte de
   1 400 px ne se lit pas : l'œil perd le début de la ligne suivante. C'est ce
   que font les messageries à pleine fenêtre — colonne large, bulles bornées.
   ⚠️ LA HAUTEUR EST CALCULÉE, pas devinée : `100vh` moins l'en-tête et les
   marges, pour que la saisie soit collée en bas de l'écran et la liste
   défile au-dessus. */
.pfil{display:flex;flex-direction:column;height:calc(100vh - 150px);min-height:420px;
  border:1px solid var(--line);border-radius:16px;background:var(--surface);overflow:hidden}
.pfil-liste{flex:1;overflow-y:auto;padding:22px 26px;display:flex;flex-direction:column;gap:4px}
.pfil-jour{display:flex;align-items:center;gap:12px;margin:16px 0 10px;color:var(--ink-faint);
  font-size:11.5px;font-weight:700;text-transform:uppercase;letter-spacing:.6px}
.pfil-jour::before,.pfil-jour::after{content:"";flex:1;height:1px;background:var(--line)}
.pfil-ligne{display:flex;margin-bottom:8px}
.pfil-ligne.moi{justify-content:flex-end}
.pfil-bulle{max-width:min(640px,72%);padding:12px 16px;border-radius:16px;
  font-size:14.5px;line-height:1.55;border:1px solid var(--line);background:var(--surface-2)}
.pfil-ligne.moi .pfil-bulle{background:var(--accent);color:#fff;border-color:var(--accent)}
.pfil-txt{white-space:pre-wrap}
.pfil-meta{font-size:11px;opacity:.7;margin-top:6px}
.pfil-saisie{padding:14px 18px;border-top:1px solid var(--line);background:var(--surface-2)}
.pfil-vide{margin:auto;text-align:center;max-width:44ch;display:flex;flex-direction:column;gap:7px}
.pfil-vide-ico{font-size:34px;opacity:.5}
.pfil-vide b{font-size:17px}
.pfil-vide .muted{font-size:13.5px;line-height:1.6}
@media(max-width:1000px){
  /* Sur téléphone, la barre d'onglets mange le bas : on lui laisse sa place. */
  .pfil{height:calc(100vh - 210px);min-height:340px;border-radius:14px}
  .pfil-liste{padding:14px 14px}
  .pfil-bulle{max-width:84%;font-size:14px;padding:11px 14px}
  .pfil-saisie{padding:11px 12px}
}

/* ⚠️ RÈGLES RETIRÉES LE 19/09/2026, avec le HTML qu'elles habillaient :
   `.portal-head`, `.portal-qui`, `.portal-menu`, `.portal-onglets` / `.po` et
   `.portal-fil`. La bande du haut est devenue le rail (`.pa-rail`) et la barre
   d'onglets du bas (`.pa-tabs`), les « portes » sont devenues les tuiles
   (`.pa-tuiles`), et la conversation a son propre panneau plein écran
   (`.pfil`). Du style qui n'habille plus rien finit par être recopié ailleurs
   « parce qu'il existait déjà » : même règle que pour un garde-fou dont la
   valeur a disparu. */

/* ============================================================
   LA COQUE TIENT DANS LA HAUTEUR DE L'ÉCRAN
   ------------------------------------------------------------
   ⚠️ `position:sticky` NE SUFFISAIT PAS, et la raison est instructive : un
   élément collant ne colle que DANS SON CONTENEUR. Le rail faisait 100vh
   dans un `.pa` de 1 100 px — cent pixels de course, puis il remontait avec
   la page. Sur une page courte on ne le voyait pas ; sur une page longue le
   logo et le nom du client disparaissaient par le haut. Signalé le
   19/09/2026 (« le logo et le nom sont tronqués »).

   La coque d'une application ne défile pas : elle tient dans l'écran, et
   c'est le CONTENU qui glisse dessous. Le rail ne bouge plus du tout.

   ⚠️ SEULEMENT DANS LE VRAI PORTAIL. En aperçu, la page vit à l'intérieur de
   l'application interne : lui imposer 100vh créerait un défilement imbriqué
   dans un écran qui en a déjà un. Là, le rail reste collant — c'est un
   aperçu, et c'est le contenu qu'on y vérifie.
   ============================================================ */
/* ⚠️ LA COQUE NE SUPPOSE PLUS QU'ELLE COMMENCE EN HAUT DE L'ÉCRAN.
   `height:100vh` sur `.pa` marche tant que rien ne la précède ; le bandeau
   d'aperçu la poussait de 110 px vers le bas, et la barre d'onglets passait
   sous le bord. C'est `.content` qui tient la hauteur de l'écran, et `.pa`
   prend ce qui reste — ce qui vaut aussi le jour où l'on posera un bandeau
   au-dessus pour de vrai.
   ⚠️ `100dvh` ET NON `100vh` : sur un téléphone, `vh` ignore la barre
   d'adresse qui se rétracte, et le bas de l'écran reste inaccessible. */
:root[data-portail] .content{height:100vh;height:100dvh;overflow:hidden;
  display:flex;flex-direction:column}
:root[data-portail] .pa{flex:1 1 auto;min-height:0;height:auto;overflow:hidden;align-items:stretch}
/* ⚠️ CE N'EST PLUS `.pa-main` QUI DÉFILE, MAIS `.pa-vue`. L'en-tête de
   section vit maintenant à côté de la zone qui glisse, pas dedans : il
   reste à l'écran quand on parcourt une liste. */
:root[data-portail] .pa-main{min-height:0;overflow:hidden}
:root[data-portail] .pa-vue{flex:1 1 auto;min-height:0;overflow-y:auto;
  overscroll-behavior:contain}
:root[data-portail] .pa-rail{position:static;height:auto;min-height:0;overflow-y:auto}
@media(max-width:1000px){
  /* Une ligne pour le contenu, une pour la barre : elle n'a plus besoin
     d'être `fixed`, la coque la tient en bas d'elle-même. */
  :root[data-portail] .pa{grid-template-rows:minmax(0,1fr) auto}
  :root[data-portail] .pa-tabs{position:static}
  :root[data-portail] .pa-vue{padding-bottom:26px}
}

/* ============================================================
   FINITIONS — 19/09/2026
   « repasse une couche d'esthétisme, sois plus précis et plus minutieux »
   ============================================================ */

/* ⚠️ LA SIGNATURE NE SE COUPE PLUS AU MILIEU D'UN MOT. « Micro-béton · Béton
   ciré · Enduits … » : une ellipse sur une seule ligne tronquait la troisième
   spécialité de l'entreprise. Deux lignes, et elle tient en entier. */
.pa-marque{align-items:flex-start;gap:12px;margin-bottom:20px}
.pa-marque .portal-logo{flex:0 0 auto;width:40px;height:40px;border-radius:12px;font-size:14px}
.pa-marque-txt b{font-size:15px;line-height:1.25;letter-spacing:-.25px}
.pa-marque-txt .muted{white-space:normal;overflow:visible;text-overflow:clip;
  font-size:11.5px;line-height:1.4;margin-top:2px;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}

/* Le rail respire : un peu plus d'air en haut, des groupes mieux séparés. */
.pa-rail{padding:24px 14px 22px;gap:0}
.pa-qui{padding:11px 13px;margin-bottom:20px;border:1px solid var(--line)}
.pa-qui .muted{font-size:10.5px;letter-spacing:.7px}
.pa-qui b{font-size:14.5px;letter-spacing:-.2px;line-height:1.3}
.pa-lien{padding:9px 13px;font-size:14px}
.pa-lien .pa-ico{font-size:14.5px}
.pa-sep{margin:16px 6px 14px}
.pa-nav-sec .pa-lien{color:var(--ink-faint)}
.pa-nav-sec .pa-lien:hover{color:var(--ink-soft)}

/* Le contenu : une marge haute qui ne colle pas au bord, et un titre qui
   respire autant que le rail. */
.pa-vue{padding:34px 38px 56px}
.pa-titre{font-size:25px;letter-spacing:-.6px;margin:0 0 22px}

/* Les tuiles : l'icône ne dispute plus la place au chiffre. */
.pa-tuiles{gap:14px;margin-bottom:22px}
.pa-tuile{padding:16px 17px;border-radius:15px;gap:1px}
.pa-tuile-ico{font-size:15px;opacity:.42;margin-bottom:7px}
.pa-tuile-val{font-size:22px;letter-spacing:-.6px}
.pa-tuile-lab{font-size:13px;margin-top:3px}
.pa-tuile-sous{font-size:11.5px;line-height:1.4}

/* Le héros : un peu plus de présence, et le bouton qui ne s'écrase pas. */
.pa-hero{padding:24px 26px;border-radius:17px;margin-bottom:20px;gap:24px}
.pa-hero-gros{font-size:34px;letter-spacing:-1.2px}
.pa-hero.ok .pa-hero-gros{font-size:23px;letter-spacing:-.5px}
.pa-hero-act .btn{min-height:46px;padding:13px 22px}

@media(max-width:1000px){
  .pa-vue{padding:16px 14px 22px}
  .pa-titre{font-size:20px;margin-bottom:14px}
  .pa-hero{padding:18px 18px;border-radius:15px;gap:15px}
  .pa-hero-gros{font-size:28px;letter-spacing:-.9px}
  .pa-tuiles{gap:10px;margin-bottom:16px}
  .pa-tuile{padding:13px 13px}
  .pa-tuile-val{font-size:19px}
}

/* ---------- l'en-tête d'une section ----------
   Un mot seul en haut d'un écran ne fait que répéter l'onglet sur lequel on
   vient d'appuyer. La ligne qui le suit porte l'état de la section — combien
   de documents, combien à régler — c'est-à-dire ce qu'on serait allé chercher
   plus bas. Demandé le 19/09/2026. */
.pa-tete{margin:0 0 22px;padding-bottom:16px;border-bottom:1px solid var(--line)}
.pa-tete h1{font-size:27px;font-weight:800;letter-spacing:-.7px;margin:0;line-height:1.15}
.pa-tete-sous{margin:6px 0 0;font-size:13.5px;line-height:1.5;color:var(--ink-soft)}
@media(max-width:1000px){
  .pa-tete{margin-bottom:15px;padding-bottom:12px}
  .pa-tete h1{font-size:21px;letter-spacing:-.5px}
  .pa-tete-sous{font-size:12.5px;margin-top:4px}
}

/* ============================================================
   ⚠️ RIEN NE DÉPASSE DE L'ÉCRAN — 19/09/2026
   ------------------------------------------------------------
   Un lien d'espace client fait quatre-vingts signes SANS UN SEUL ESPACE.
   Collé dans un message, il devient un « mot » plus large que le téléphone :
   la bulle s'étire, le panneau avec, et toute la conversation se met à
   coulisser de gauche à droite. On ne le voyait pas en jeu d'essai — nos
   messages de test tenaient sur une ligne — mais CHAQUE notification que
   nous envoyons contient ce lien, donc chaque vraie conversation en a un.

   `overflow-wrap:anywhere` autorise la coupure À L'INTÉRIEUR du mot, ce que
   `break-word` seul ne fait pas toujours sur un lien. Et `min-width:0` sur la
   bulle : sans lui, un enfant en flex refuse de passer sous sa largeur
   intrinsèque, et la règle de coupure ne s'applique jamais.
   ============================================================ */
.pfil-liste{overflow-x:hidden}
.pfil-ligne{max-width:100%}
.pfil-bulle{min-width:0;overflow-wrap:anywhere;word-break:break-word;hyphens:auto}
.pfil-txt{overflow-wrap:anywhere;word-break:break-word}
/* Et la même garde partout où un texte libre peut contenir une adresse. */
.pa-vue a{overflow-wrap:anywhere}
.pdoc,.pa-tuile,.portal-porte{min-width:0}
.pa-tuile-val,.pa-tuile-lab,.pa-tuile-sous{overflow-wrap:anywhere}

/* ⚠️ LA HAUTEUR DE LA CONVERSATION NE SE CALCULE PLUS EN `vh`.
   `calc(100vh - 210px)` supposait de connaître d'avance tout ce qui la
   surmonte : l'en-tête, le titre, les marges — et la somme changeait à
   chaque retouche. Il suffisait du bandeau d'aperçu pour que la saisie passe
   sous le bord de l'écran. La colonne se déclare donc en flex, et le panneau
   prend « ce qui reste » : la mesure est exacte quoi qu'on mette au-dessus.
   ⚠️ `min-height:0` est indispensable — sans lui, un enfant flex refuse de
   passer sous sa hauteur intrinsèque et déborde au lieu de défiler. */
/* ⚠️ LA COLONNE FLEX NE SERT QU'À LA CONVERSATION — et c'est un défaut que
   j'ai introduit. Posée sur TOUTES les vues, elle faisait de chaque bloc un
   élément flex, et un élément flex RÉTRÉCIT par défaut (`flex-shrink:1`) dès
   que le contenu dépasse la colonne. Le bandeau de titre était donc écrasé à
   moins que sa hauteur, et son `overflow:hidden` — nécessaire pour arrondir
   le filet prune — coupait le résultat en plein milieu d'un mot.
   « Échanges », « Devis & avenants », « Conditions générales » : tous
   tranchés. Signalé le 19/09/2026.
   La conversation seule a besoin d'une colonne qui se partage la hauteur ;
   les autres vues défilent normalement. */
:root[data-portail] .pa-main--plein .pa-vue{display:flex;flex-direction:column}
:root[data-portail] .pa-main--plein .pfil{flex:1 1 auto;min-height:0;height:auto}
/* ⚠️ ET LE BANDEAU NE SE LAISSE JAMAIS COMPRIMER, même dans cette colonne. */
.pa-tete{flex:0 0 auto}

/* Une vue « pleine » : elle occupe la hauteur et gère son propre défilement.
   ⚠️ `height:100%` ET NON `min-height` — c'est la différence entre « au moins
   aussi haut que la colonne » (le panneau grandit, la saisie sort de l'écran)
   et « exactement aussi haut » (la liste défile à l'intérieur). */
/* ⚠️ `height:100%` ÉTAIT FAUX, et de 56 px exactement : sur téléphone, la
   barre d'en-tête occupe le haut de `.pa-main`, donc « cent pour cent de la
   colonne » dépasse de la hauteur de cette barre. Un pourcentage ne sait pas
   ce qui le précède ; une colonne flex, si. */
:root[data-portail] .pa-main{display:flex;flex-direction:column}
:root[data-portail] .pa-main--plein{overflow:hidden}
:root[data-portail] .pa-main--plein .pa-vue{flex:1 1 auto;min-height:0;height:auto;
  padding-bottom:20px;overflow:hidden;display:flex;flex-direction:column}

/* ⚠️ `box-sizing:border-box` N'EST DÉCLARÉ NULLE PART DANS L'APPLICATION.
   Personne ne s'en apercevait tant que rien ne dépendait d'une hauteur
   exacte : `height:100%` plus 36 px de padding donnait 36 px de trop, et la
   zone de saisie passait sous la barre d'onglets.
   ⚠️ ON NE LE POSE PAS GLOBALEMENT. Toutes les marges et paddings de
   l'application ont été réglés à l'œil SANS lui : le passer en global
   déplacerait des dizaines d'écrans d'un coup, pour un gain invisible.
   Ici, sur les éléments de la coque de l'espace client — ceux qui sont
   nouveaux et dont la hauteur est calculée — c'est sans risque et
   nécessaire. */
.pa,.pa *,.pa *::before,.pa *::after{box-sizing:border-box}

/* ============================================================
   LA COQUE OCCUPE VRAIMENT TOUT L'APPAREIL — 19/09/2026
   ------------------------------------------------------------
   ⚠️ `peau.css` EST CHARGÉ APRÈS CETTE FEUILLE, et y remet un padding sur
   `:root[data-portail] .content` (16/14/40 px sur téléphone, 26/20/60 sur
   ordinateur). À spécificité égale, c'est la dernière déclarée qui gagne :
   la coque gardait donc une marge crème tout autour, et la barre d'onglets
   flottait à un centimètre du bord de l'écran. On ne touche pas à `peau.css`
   — ces valeurs servent à tout le reste du portail hors refonte — on passe
   simplement au-dessus en spécificité : `.app .content` compte deux classes
   de plus. Signalé le 19/09/2026 (« il faut utiliser tout l'écran »).
   ============================================================ */
:root[data-portail] .app .content{
  padding:0;margin:0;max-width:none;
  height:100vh;height:100dvh;overflow:hidden;display:flex;flex-direction:column;
}
/* ⚠️ `align-self:start` de la règle de base gagne sur `align-items:stretch`
   du conteneur : le rail s'arrêtait à la hauteur de son contenu, au tiers de
   l'écran, et la page se terminait sur un bloc blanc suspendu. */
:root[data-portail] .pa-rail{align-self:stretch}

/* ---------- la marque, soignée ----------
   ⚠️ `.portal-logo` AVAIT DISPARU. En retirant un commentaire devenu orphelin,
   j'ai emporté la ligne qui le précédait — celle qui donnait au sigle son
   carré prune. Le « GS » s'affichait en texte gris de 14 px à côté du nom.
   Une suppression par plage de lignes se vérifie sur le RÉSULTAT, pas sur le
   compte de lignes retirées. */
.portal-logo{display:grid;place-items:center;flex:0 0 auto;
  background:linear-gradient(140deg,var(--accent-clair),var(--accent));color:#fff;
  font-weight:800;letter-spacing:.03em;
  box-shadow:0 2px 6px rgba(140,64,93,.22)}
.pa-marque{align-items:center;gap:13px;padding-bottom:18px;margin-bottom:18px;
  border-bottom:1px solid var(--line)}
.pa-marque .portal-logo{width:44px;height:44px;border-radius:13px;font-size:15px}
.pa-marque-txt b{font-size:15.5px;line-height:1.2;letter-spacing:-.3px}
.pa-marque-txt .muted{font-size:11px;line-height:1.45;margin-top:3px;
  letter-spacing:.01em;-webkit-line-clamp:2}
.pa-top .portal-logo{width:38px;height:38px;border-radius:11px;font-size:13px}
.pa-top{gap:12px;padding:12px 16px}
.pa-top-txt b{font-size:14.5px;letter-spacing:-.25px}

/* ---------- l'en-tête d'une section : encadré ----------
   Un titre posé sur le fond de la page se confond avec le contenu qui suit.
   Dans un cadre à la couleur de la carte, il devient le bandeau de la
   section — on sait où l'on est sans le chercher.
   Demandé le 19/09/2026 (« les titres doivent être encadrés et classe »). */
/* ⚠️ EN BLOC, PAS EN FLEX. En flex avec `flex-wrap`, la ligne d'état passait
   à la ligne suivante en héritant du `gap` de 16 px : le titre et ce qui le
   précise semblaient appartenir à deux blocs différents. */
/* ⚠️ IL A SA PROPRE MARGE : il n'est plus dans `.pa-vue`, donc le padding
   latéral de la vue ne s'applique plus à lui. */
.pa-tete{display:block;padding:17px 22px 16px;margin:52px 38px 16px;
  background:var(--surface);border:1px solid var(--line);border-radius:15px;
  box-shadow:var(--shadow);position:relative;overflow:hidden}
/* Un filet prune sur la tranche gauche : la signature de la maison, discrète. */
.pa-tete::before{content:"";position:absolute;left:0;top:0;bottom:0;width:4px;
  background:linear-gradient(180deg,var(--accent-clair),var(--accent))}
.pa-tete h1{font-size:23px;letter-spacing:-.6px;margin:0;line-height:1.15;padding-left:6px}
.pa-tete-sous{margin:5px 0 0;padding-left:6px;font-size:13px;color:var(--ink-soft);
  line-height:1.5}
@media(max-width:1000px){
  .pa-tete{padding:13px 16px 12px;margin-bottom:14px;border-radius:13px}
  .pa-tete h1{font-size:19px;letter-spacing:-.4px}
  .pa-tete-sous{font-size:12.5px}
}

/* ---------- la barre du bas, collée au bord de l'appareil ---------- */
.pa-tabs{padding:6px 4px;border-top:1px solid var(--line)}
:root[data-portail] .pa-tabs{padding-bottom:calc(6px + env(safe-area-inset-bottom,0px))}

/* ============================================================
   ARCHIVO — LA VOIX TYPOGRAPHIQUE DE LA MARQUE
   ------------------------------------------------------------
   ⚠️ POURQUOI UNE POLICE, ET POURQUOI CELLE-LÀ. L'application entière est en
   police système : c'est le bon choix pour un outil qu'on regarde huit
   heures par jour, et c'est exactement ce qui fait qu'un écran « ressemble à
   un back-office » quoi qu'on fasse par ailleurs. L'espace client n'est pas
   un outil : c'est la seule surface que voit le client, et la seule qui
   porte la marque.
   Archivo n'est pas un choix d'humeur : c'est DÉJÀ la police d'affichage de
   la présentation Socle (`pages/vitrine.html`). La marque parle d'une seule
   voix, du commercial au client.

   ⚠️ SERVIE DEPUIS `vendor/`, JAMAIS DEPUIS UN CDN. L'application doit rester
   servie depuis un dossier statique, sans aucune ressource réseau — c'est
   écrit dans `tokens.css` et c'est ce qui la rend installable hors ligne.
   Deux sous-ensembles, 68 ko en tout, et `font-display:swap` : le texte
   s'affiche immédiatement en système, la police prend le relais.

   ⚠️ L'AFFICHAGE SEULEMENT. Le texte courant reste en police système : elle
   est optimisée par le téléphone pour être lue en petit, Archivo ne l'est
   pas. Titres, montants, nom de la maison — rien d'autre.
   ============================================================ */
@font-face{
  font-family:'Archivo';font-style:normal;font-weight:600 800;font-stretch:100%;
  font-display:swap;src:url(/vendor/archivo-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF,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;
}
@font-face{
  font-family:'Archivo';font-style:normal;font-weight:600 800;font-stretch:100%;
  font-display:swap;src:url(/vendor/archivo-latinext.woff2) format('woff2');
  unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,
    U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
:root[data-portail]{ --display:'Archivo',var(--sans); }

/* Ce qui passe en Archivo : les titres, les chiffres, le nom de la maison.
   ⚠️ `font-variant-numeric:tabular-nums` avec : sans lui, les montants
   dansent d'une ligne à l'autre. */
.pa-marque-txt b,
.pa-tete h1,
.pa-hero-gros,
.pa-hero-sur,
.pa-tuile-val,
.pa-top-txt b,
.pa-vue .portal-sec > h3,
.pa-vue .pdoc-amt{
  font-family:var(--display,inherit);
  font-weight:700;letter-spacing:-.02em;font-feature-settings:"ss01";
}
.pa-hero-gros,.pa-tuile-val,.pa-vue .pdoc-amt{font-variant-numeric:tabular-nums lining-nums}
/* ⚠️ Le « € » ne pèse pas autant que les chiffres. À la même graisse il
   attire l'œil sur l'unité au lieu du montant. Leçon des applications
   bancaires : on l'allège et on l'espace à peine. */
.pa-hero-gros{font-weight:800;letter-spacing:-.035em}
.pa-tete h1{font-weight:700;letter-spacing:-.025em}
.pa-marque-txt b,.pa-top-txt b{font-weight:800;letter-spacing:-.01em;text-transform:none}

/* ============================================================
   LE PAPIER A DU GRAIN
   ------------------------------------------------------------
   ⚠️ LE MICRO-BÉTON EST UNE MATIÈRE, et l'espace était beige sur beige,
   parfaitement lisse. Un grain très discret — une turbulence SVG en ligne,
   sans requête réseau, à 3 % d'opacité — et le fond cesse d'être « du blanc
   cassé » pour devenir du papier. C'est là que respecter la charte devient
   exprimer la marque.
   ⚠️ SUR LE FOND SEULEMENT, jamais sur les cartes : du grain sous du texte
   de 12 px le rend sale, pas chaleureux.
   ============================================================ */
:root[data-portail] .pa{
  background-color:var(--paper);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23g)' opacity='.055'/%3E%3C/svg%3E");
}
[data-theme="dark"]:root[data-portail] .pa{background-blend-mode:overlay}

/* ============================================================
   LA BANDE PHOTO
   ------------------------------------------------------------
   Pour un client micro-béton, les photos SONT le produit. La dernière
   publiée ouvre l'accueil, pleine largeur, le nom du chantier posé dessus.
   ⚠️ LE VOILE EST UN DÉGRADÉ, PAS UN APLAT. Un aplat noir à 40 % éteint la
   photo entière pour rendre lisibles trois mots en bas ; un dégradé ne
   fonce que là où le texte se pose.
   ============================================================ */
/* ⚠️ LA HAUTEUR VIENT DU CONTENU, PAS D'UN RAPPORT D'IMAGE. Tant que la
   bande portait une photo, `aspect-ratio:21/7` avait un sens : on cadrait
   une image. Depuis qu'elle porte une couleur et trois lignes de texte, ce
   rapport ne cadre plus rien — il réserve simplement 250 px de prune vide
   au-dessus du nom du chantier, et la tête de page écrase tout le reste.
   Elle fait désormais la hauteur de ce qu'elle contient, comme n'importe
   quelle carte. Demandé le 19/09/2026. */
.pa-bande{position:relative;display:flex;align-items:flex-end;gap:16px;
  width:100%;margin:0 0 18px;padding:20px 24px;
  border-radius:16px;overflow:hidden;cursor:pointer;
  border:1px solid var(--line);box-shadow:var(--shadow)}
.pa-bande img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .5s cubic-bezier(.2,.7,.3,1)}
.pa-bande:hover img{transform:scale(1.025)}
/* ⚠️ LE VOILE S'ALLÈGE SUR UN FOND DÉJÀ SOMBRE. À 72 % il était calibré
   pour rendre du blanc lisible sur une photo claire ; sur le prune il
   éteignait la couleur au lieu de la servir. */
.pa-bande-voile{position:absolute;inset:0;
  background:linear-gradient(to top,rgba(20,14,18,.42) 0%,rgba(20,14,18,.12) 46%,rgba(20,14,18,0) 74%)}
.pa-bande-txt{position:relative;z-index:1;flex:1;min-width:0;
  display:flex;flex-direction:column;gap:2px;color:#fff}
.pa-bande-sur{font-size:11px;font-weight:700;text-transform:uppercase;
  letter-spacing:1.1px;opacity:.82}
.pa-bande-txt b{font-family:var(--display,inherit);font-size:26px;font-weight:800;
  letter-spacing:-.03em;line-height:1.15;text-shadow:0 1px 14px rgba(0,0,0,.35)}
.pa-bande-lieu{font-size:13px;opacity:.85}

/* ============================================================
   LA FRISE DU DOSSIER
   ------------------------------------------------------------
   La question qu'on se pose en ouvrant : où en est mon projet ?
   ⚠️ CINQ ÉTAPES RÉELLES, pas un pourcentage abstrait. Un pourcentage se
   calcule ; une étape se reconnaît.
   ⚠️ L'ÉTAPE COURANTE EST LA SEULE EN COULEUR. Cinq pastilles prune
   feraient cinq étapes d'égale importance — et l'on ne saurait plus où
   l'on est.
   ============================================================ */
.pa-frise{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;
  gap:0;margin:0 0 20px;padding:18px 20px 16px;
  background:var(--surface);border:1px solid var(--line);border-radius:15px;
  box-shadow:var(--shadow)}
.pa-etape{position:relative;display:flex;flex-direction:column;align-items:center;
  gap:9px;text-align:center;min-width:0}
/* Le trait qui relie : il s'arrête à l'étape courante. */
.pa-etape::before{content:"";position:absolute;top:8px;left:-50%;width:100%;height:2px;
  background:var(--line);z-index:0}
.pa-etape:first-child::before{display:none}
.pa-etape.faite::before,.pa-etape.ici::before{background:var(--accent)}
.pa-etape-pt{position:relative;z-index:1;width:18px;height:18px;border-radius:50%;
  display:grid;place-items:center;font-size:10px;font-weight:800;line-height:1;
  background:var(--surface);border:2px solid var(--line);color:transparent;
  transition:all .2s}
.pa-etape.faite .pa-etape-pt{background:var(--accent);border-color:var(--accent);color:#fff}
.pa-etape.ici .pa-etape-pt{background:var(--accent);border-color:var(--accent);
  box-shadow:0 0 0 5px var(--accent-wash)}
.pa-etape-lab{font-size:12px;line-height:1.35;color:var(--ink-faint);
  overflow-wrap:anywhere}
.pa-etape.faite .pa-etape-lab{color:var(--ink-soft)}
.pa-etape.ici .pa-etape-lab{color:var(--accent-ink);font-weight:800}

@media(max-width:1000px){
  .pa-bande{padding:15px 16px;border-radius:14px;margin-bottom:14px;gap:10px}
  .pa-bande-txt b{font-size:20px}
  .pa-bande-lieu{font-size:12px}
  /* ⚠️ CINQ LIBELLÉS SUR 390 PX NE SE LISENT PAS. On garde les cinq pastilles
     — la progression reste visible — et seul le libellé de l'étape COURANTE
     s'affiche, sous la frise. */
  .pa-frise{padding:15px 14px 13px;margin-bottom:14px;border-radius:13px}
  .pa-etape-lab{display:none}
  .pa-etape.ici .pa-etape-lab{display:block;position:absolute;top:26px;
    left:50%;transform:translateX(-50%);white-space:nowrap;font-size:12px}
  .pa-frise{padding-bottom:36px}
}

/* ⚠️ LES RÈGLES `.pa-signature*` SONT PARTIES AVEC LE BLOC qu'elles
   habillaient (19/09/2026) : du style orphelin finit par être recopié
   ailleurs « parce qu'il existait déjà ». */

/* ============================================================
   LA BANDE DE TÊTE : UNE SURFACE DE MICRO-BÉTON
   ------------------------------------------------------------
   ⚠️ COMPOSÉE EN CSS, sans le moindre fichier image : des dégradés pour le
   relief, deux couches de grain par-dessus. `feDiffuseLighting` aurait donné
   un vrai relief calculé, mais il NE REND PAS dans une image SVG servie en
   `data:` — vérifié à l'écran, la bande sortait vide.
   ============================================================ */
/* ⚠️ LE PRUNE DE LA MAISON, PAS UNE FAUSSE PHOTO DE BÉTON. La première
   version imitait une surface taloée en dégradés beiges : de près ça
   passait, en tête de page ça faisait surtout « beige sale ». Les arcs
   évoquent le passage de la taloche — décoratif, mais tiré du geste du
   métier, et dans la couleur de la charte. */
.pa-bande-matiere{position:absolute;inset:0;
  background:
    radial-gradient(90% 120% at 15% 0%, #A85073 0%, rgba(168,80,115,0) 62%),
    radial-gradient(70% 100% at 90% 100%, #5E2A3F 0%, rgba(94,42,63,0) 58%),
    linear-gradient(125deg,var(--accent) 0%,var(--accent-ink) 100%)}
.pa-bande-arcs{position:absolute;inset:0;width:100%;height:100%}
.pa-bande-grain{position:absolute;inset:0;mix-blend-mode:overlay;opacity:.5;
  background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='900' height='600'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.006' numOctaves='5' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='900' height='600' filter='url(%23g)' opacity='.30'/%3E%3C/svg%3E") center/cover}
.pa-bande-grain.fin{opacity:.5;
  background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23g)' opacity='.16'/%3E%3C/svg%3E")}
/* La surface s'anime à peine au survol : elle respire, elle ne bouge pas. */
.pa-bande:hover .pa-bande-matiere{transform:scale(1.02)}
.pa-bande-matiere{transition:transform .6s cubic-bezier(.2,.7,.3,1)}

/* Les vraies photos, en vignettes — on montre qu'il y a à voir sans miser
   la tête de page sur un cliché pris au hasard. */
.pa-bande-vues{position:relative;z-index:1;display:flex;align-items:center;gap:8px;flex:0 0 auto}
.pa-bande-vues img{width:52px;height:52px;object-fit:cover;border-radius:9px;
  border:2px solid rgba(255,255,255,.75);box-shadow:0 2px 10px rgba(0,0,0,.22)}
.pa-bande-plus{margin-left:4px;font-size:12px;font-weight:700;color:#fff;
  background:rgba(20,18,16,.42);backdrop-filter:blur(6px);
  padding:6px 11px;border-radius:20px;white-space:nowrap}
@media(max-width:1000px){
  .pa-bande-vues{gap:6px}
  .pa-bande-vues img{width:38px;height:38px;border-radius:8px}
  /* Sur 390 px, trois vignettes ET le nom du chantier se marchent dessus :
     on garde le compteur, qui dit l'essentiel. */
  .pa-bande-vues img{display:none}
  .pa-bande-plus{font-size:11.5px;padding:5px 10px}
}

/* « Nous contacter » : plus d'adresse, la signature la porte déjà. */
/* ⚠️ `flex:1 1 220px` DANS UNE COLONNE, C'EST UNE HAUTEUR DE 220 px.
   `flex-basis` s'applique sur l'axe PRINCIPAL : en ligne c'est une largeur,
   en colonne c'est une hauteur. Sur téléphone, `.pc-boutons` passe en
   colonne — chaque bouton d'appel faisait donc 220 px de haut, deux grandes
   cartes blanches presque vides. Vu le 19/09/2026. */
.pc-boutons.pc-seuls{display:flex;gap:10px;flex-wrap:wrap}
.pc-boutons.pc-seuls .pc-tel{flex:1 1 220px}
@media(max-width:1000px){
  .pc-boutons.pc-seuls{flex-direction:column;gap:8px}
  .pc-boutons.pc-seuls .pc-tel{flex:0 0 auto}
  /* Et les étiquettes reprennent une taille de téléphone : un bouton d'appel
     n'est pas un titre. */
  .pc-tel{min-height:0;padding:9px 12px;gap:9px}
  .pc-tel .pc-ico{width:26px;height:26px;border-radius:8px;font-size:12px}
  .pc-tel .pc-txt b{font-size:13px}
  .pc-tel .pc-txt .muted{font-size:11.5px;font-variant-numeric:tabular-nums}
}

/* ============================================================
   L'INTÉRIEUR DE LA CONVERSATION
   ------------------------------------------------------------
   ⚠️ TROIS RÉPONSES D'AFFILÉE DONNAIENT TROIS FOIS LE NOM ET TROIS FOIS LA
   DATE. On ne lisait plus une conversation, on lisait un journal. Les
   messages consécutifs du même côté forment un groupe : seul le dernier
   porte la signature et l'heure, et les angles se ferment du côté de
   l'auteur — la forme dit qui parle avant qu'on lise.
   ============================================================ */
.pfil-ligne{display:flex;align-items:flex-end;gap:9px;margin-bottom:2px}
.pfil-ligne.fin{margin-bottom:10px}
.pfil-ligne.moi{justify-content:flex-end}
.pfil-ava{flex:0 0 auto;width:28px;height:28px;border-radius:50%;
  display:grid;place-items:center;font-size:10.5px;font-weight:800;letter-spacing:.02em;
  background:var(--accent-wash);color:var(--accent-ink);
  border:1px solid color-mix(in srgb,var(--accent) 22%,transparent)}
.pfil-ava.vide{background:none;border:none}
/* Les angles : pleins du côté de l'auteur, sauf sur la dernière bulle du
   groupe — celle qui « pointe » vers lui. */
.pfil-bulle{border-radius:16px}
.pfil-ligne.eux .pfil-bulle{border-bottom-left-radius:6px}
.pfil-ligne.moi .pfil-bulle{border-bottom-right-radius:6px}
.pfil-ligne.eux.fin .pfil-bulle{border-bottom-left-radius:16px}
.pfil-ligne.moi.fin .pfil-bulle{border-bottom-right-radius:16px}
.pfil-ligne.eux.debut .pfil-bulle{border-top-left-radius:6px}
.pfil-ligne.moi.debut .pfil-bulle{border-top-right-radius:6px}
.pfil-meta{font-size:11px;opacity:.62;margin-top:5px;font-variant-numeric:tabular-nums}
.pfil-jour span{padding:0 2px}

/* La saisie : une zone, pas un formulaire. */
.pfil-saisie{padding:13px 16px;background:var(--surface);
  border-top:1px solid var(--line);align-items:flex-end;gap:10px}
.pfil-saisie .pchat-txt{border-radius:22px;padding:11px 16px;
  background:var(--surface-2);border:1px solid var(--line);
  transition:border-color .14s,box-shadow .14s}
.pfil-saisie .pchat-txt:focus{border-color:var(--accent);
  box-shadow:0 0 0 3px var(--accent-wash);outline:none}
.pfil-saisie .pchat-envoi{width:42px;height:42px;border-radius:50%;flex:0 0 auto;
  display:grid;place-items:center;padding:0;font-size:15px}
@media(max-width:1000px){
  .pfil-ava{width:24px;height:24px;font-size:9.5px}
  .pfil-saisie{padding:10px 11px;gap:8px}
  .pfil-saisie .pchat-envoi{width:38px;height:38px}
}

/* ============================================================
   LE BILAN DES FACTURES : UN EN-TÊTE, PAS UNE QUATRIÈME FACTURE
   ------------------------------------------------------------
   ⚠️ IL AVAIT LA MÊME FORME QUE LES CARTES EN DESSOUS — même fond, même
   bordure, chiffres de 18 px — et se lisait donc comme une facture de plus,
   la plus terne. Or c'est LUI qu'on vient chercher : combien reste-t-il.
   Il prend la place et le poids d'un en-tête. Demandé le 19/09/2026.
   ⚠️ LE RESTE À PAYER EST AU MILIEU ET EN GRAND : c'est la réponse à la
   question qu'on se pose en ouvrant la page. Les deux autres chiffres le
   situent, ils ne le concurrencent pas.
   ============================================================ */
.pfac-bilan{padding:24px 26px 20px;margin:0 0 20px;border-radius:17px;
  background:var(--surface);border:1px solid var(--line);box-shadow:var(--shadow)}
.pfac-bilan.du{border-color:color-mix(in srgb,var(--warn) 40%,var(--line));
  background:color-mix(in srgb,var(--warn) 5%,var(--surface))}
.pfac-bilan.ok{border-color:color-mix(in srgb,var(--ok) 32%,var(--line));
  background:color-mix(in srgb,var(--ok) 4%,var(--surface))}
.pfac-chiffres{display:grid;grid-template-columns:1fr auto 1fr;gap:18px;align-items:end}
.pfac-c{display:flex;flex-direction:column;gap:3px;min-width:0}
.pfac-c:nth-child(2){text-align:center;align-items:center}
.pfac-c:nth-child(3){text-align:right;align-items:flex-end}
.pfac-lab{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.7px;
  color:var(--ink-faint)}
.pfac-val{font-family:var(--display,inherit);font-weight:700;font-size:19px;
  letter-spacing:-.02em;font-variant-numeric:tabular-nums lining-nums;
  color:var(--ink);white-space:nowrap}
.pfac-val.gros{font-size:38px;font-weight:800;letter-spacing:-.04em;line-height:1.05}
.pfac-val.ok{color:var(--ok)}
.pfac-val.du{color:var(--warn)}
.pfac-jauge{height:8px;border-radius:5px;background:color-mix(in srgb,var(--ink) 8%,transparent);
  overflow:hidden;margin-top:18px}
.pfac-jauge i{display:block;height:100%;border-radius:5px;background:var(--ok);
  transition:width .5s cubic-bezier(.2,.7,.3,1)}
.pfac-pied{font-size:12px;color:var(--ink-soft);margin-top:8px;font-variant-numeric:tabular-nums}
@media(max-width:1000px){
  /* ⚠️ TROIS COLONNES SUR 390 PX ÉCRASENT LE CHIFFRE PRINCIPAL. Le reste à
     payer prend toute la largeur, les deux autres se partagent la ligne
     dessous — l'ordre de lecture reste le même. */
  .pfac-bilan{padding:18px 18px 16px;border-radius:15px;margin-bottom:16px}
  .pfac-chiffres{grid-template-columns:1fr 1fr;gap:14px 12px}
  .pfac-c.principal{grid-column:1 / -1;order:-1;text-align:left;align-items:flex-start}
  .pfac-c:nth-child(3){text-align:right;align-items:flex-end}
  .pfac-val{font-size:17px}
  .pfac-val.gros{font-size:33px}
  .pfac-jauge{margin-top:14px}
}

/* ============================================================
   LE BASCULEUR CLAIR / SOMBRE
   ------------------------------------------------------------
   ⚠️ UN SEUL EXEMPLAIRE POUR LES DEUX COQUES. Sur grand écran, la barre du
   haut n'existait pas — le rail porte la marque. Elle réapparaît ici comme
   une simple ligne transparente qui ne tient que ce bouton, en haut à
   droite ; sur téléphone, elle garde la marque et le bouton s'y range.
   Deux exemplaires du même bouton, ce serait deux endroits à corriger.
   ============================================================ */
.pa-theme{margin-left:auto;flex:0 0 auto;
  width:38px;height:38px;border-radius:50%;display:grid;place-items:center;
  border:1px solid var(--line);background:var(--surface);color:var(--ink-soft);
  font-size:16px;line-height:1;cursor:pointer;font-family:inherit;
  transition:color .14s,border-color .14s,background .14s}
.pa-theme:hover{color:var(--accent);border-color:var(--accent);background:var(--accent-wash)}
.pa-theme:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* Grand écran : le bouton se pose DANS la marge haute, à droite.
   ⚠️ HORS DU FLUX. En élément de flux, la barre se réservait une ligne
   entière — 56 px de vide au-dessus de la bande, pour un bouton de 34.
   En `absolute`, elle n'occupe plus rien : le contenu garde sa marge haute,
   et le bouton s'y installe. Vu le 19/09/2026. */
@media(min-width:1001px){
  .pa-main{position:relative}
  .pa-top{display:block;background:none;border:none;padding:0;
    position:absolute;top:12px;right:26px;z-index:5}
  .pa-top .portal-logo,.pa-top .pa-top-txt{display:none}
  .pa-top .pa-theme{width:34px;height:34px;font-size:15px;margin:0}
  /* La marge haute s'élargit juste assez pour l'accueillir sans mordre
     sur la première carte. */
  .pa-vue{padding-top:52px}
}

/* L'en-tête de section vit à côté de la zone qui défile : il garde sa marge
   propre, et la vue en dessous n'a plus besoin de sa marge haute. */
.pa-tete + .pa-vue{padding-top:0}
@media(max-width:1000px){
  .pa-tete{margin:14px 14px 12px}
}
@media(min-width:1001px){
  /* Le basculeur est dans la marge haute : l'en-tête commence sous lui. */
  .pa-tete{margin-top:52px}
}

/* ============================================================
   VERROUILLER LE DOCUMENT — iOS SAFARI
   ------------------------------------------------------------
   ⚠️ `overflow:hidden` NE SUFFIT PAS SUR iOS. Mesuré : `html`, `body`,
   `.content` et `.pa` ont exactement la hauteur de leur contenu — rien ne
   « devrait » bouger. Et pourtant, un glissement qui COMMENCE sur la barre du
   haut ou sur la barre d'onglets fait pourtant voyager toute la page : iOS
   Safari déplace alors le DOCUMENT lui-même (et sa barre d'adresse avec),
   indépendamment des règles de débordement. Signalé le 19/09/2026 :
   « si je prends le bas ou l'en-tête et que je la pousse, tout scrolle ».

   Deux verrous, parce qu'un seul ne tient pas :

   1. `position:fixed` sur le corps. C'est le seul moyen fiable d'empêcher le
      document de se déplacer sur iOS ; `height:100%` + `overflow:hidden`
      n'y arrive pas.
   2. `touch-action:none` sur les barres. Il dit au navigateur qu'aucun geste
      de défilement ne part de là — les touchers, eux, passent toujours.

   ⚠️ ET `pan-y` SUR LES ZONES QUI DÉFILENT, sans quoi le premier verrou les
   bloquerait aussi. Une règle qui interdit tout doit nommer ses exceptions.
   ============================================================ */
:root[data-portail]{height:100%;overflow:hidden;overscroll-behavior:none}
:root[data-portail] body{
  position:fixed;inset:0;width:100%;height:100%;
  overflow:hidden;overscroll-behavior:none;
}
/* Les barres ne répondent à aucun glissement. */
:root[data-portail] .pa-top,
:root[data-portail] .pa-tete,
:root[data-portail] .pa-tabs{touch-action:none}
/* Ce qui défile, et rien d'autre. */
:root[data-portail] .pa-vue,
:root[data-portail] .pa-rail,
:root[data-portail] .pfil-liste{touch-action:pan-y;-webkit-overflow-scrolling:touch}

/* L'intertitre d'un groupe de factures dans l'espace client. */
.pfac-grp{font-size:12.5px;font-weight:800;text-transform:uppercase;letter-spacing:.5px;
  color:var(--ink-faint);margin:20px 0 8px}
.pfac-grp:first-of-type{margin-top:6px}
