/* Espace expéditeur.
   Les valeurs viennent du prototype Claude Design « Proto Expéditeur.dc.html ».
   Les styles en ligne du prototype sont convertis en classes ; les valeurs, les
   points de rupture (860 / 1040 / 1180) et les tokens sont identiques. */

/* ============================ Primitives ============================ */

.ico { display: inline-flex; flex: 0 0 auto; }

.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--mono-caption-size);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.h1 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(30px, 4.6vw, var(--heading-1-size));
  line-height: 1.15;
  letter-spacing: -.024em;
  margin: 0;
}

.sub { font-size: var(--body-sm-size); color: var(--text-secondary); }
.hint { font-size: var(--body-xs-size); color: var(--text-tertiary); }

/* Un mot du sous-titre qui mène ailleurs. Il prend l'encre du texte et un filet
   dessous, seule différence avec le gris qui l'entoure : dans une phrase, un
   bouton dessiné serait plus voyant que la phrase elle-même. */
.sublink {
  padding: 0;
  border: none;
  border-bottom: 1px solid var(--black-30);
  border-radius: 0;
  background: none;
  font: inherit;
  color: var(--text-primary);
  cursor: pointer;
  transition: var(--transition-control);
}
.sublink:hover { border-bottom-color: var(--text-primary); }

/* Button — SIZES et VARIANTS repris du bundle du design system */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  font-family: var(--font-sans);
  font-weight: var(--weight-medium);
  letter-spacing: -.011em;
  line-height: 1;
  cursor: pointer;
  white-space: nowrap;
  transition: var(--transition-control);
}
.btn--sm { height: 36px; padding: 0 16px; font-size: 14px; gap: 6px; }
.btn--md { height: 44px; padding: 0 22px; font-size: 15px; gap: 8px; }
.btn--lg { height: 52px; padding: 0 28px; font-size: 16px; gap: 10px; }
.btn--full { display: flex; width: 100%; }
.btn--primary { background: var(--action-primary-bg); color: var(--action-primary-fg); }
.btn--primary:hover:not(:disabled) { background: var(--action-primary-bg-hover); }
.btn--secondary {
  background: var(--action-secondary-bg);
  color: var(--action-secondary-fg);
  border-color: var(--action-secondary-border);
}
.btn--secondary:hover:not(:disabled) { background: var(--surface-subtle); }
.btn--ghost { background: transparent; color: var(--action-ghost-fg); }
.btn--ghost:hover:not(:disabled) { background: var(--black-5); }
.btn:disabled { opacity: .35; cursor: not-allowed; }
.btn:active:not(:disabled) { transform: scale(var(--press-scale)); }

/* Input */
.field { display: flex; flex-direction: column; gap: 7px; width: 100%; }
.field__el {
  width: 100%;
  height: 42px;
  padding: 0 12px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-sm);
  background: var(--white);
  font: inherit;
  font-size: 14px;
  letter-spacing: -.006em;
  color: var(--text-primary);
  outline: none;
  transition: var(--transition-control);
}
.field__el::placeholder { color: var(--text-tertiary); }
.field__el:focus { border-color: var(--border-strong); box-shadow: var(--ring-focus); }

/* Tag */
/* Un état se dit, il ne se décore pas.

   Ces étiquettes étaient des pastilles pleines, teintées de la couleur de leur
   état. Posées sur chaque ligne d'une liste, elles formaient un chapelet de
   gélules colorées qui attirait l'œil sans rien lui apprendre, et le vert des
   états positifs finissait par recouvrir la moitié de l'écran. Un point de
   couleur et un mot disent la même chose et laissent la page tranquille. */
.tag {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--font-sans);
  font-size: 13px;
  letter-spacing: -.004em;
  color: var(--text-secondary);
  white-space: nowrap;
}
.tag::before {
  content: '';
  width: 6px; height: 6px;
  flex: none;
  border-radius: 50%;
  background: var(--black-30);
}
.tag--positive::before { background: var(--status-positive); }
.tag--pending::before { background: var(--status-pending); }
.tag--negative::before { background: var(--status-negative); }

/* TabPills */
.pills { display: flex; flex-wrap: wrap; gap: 10px; }
.pill {
  height: 44px;
  padding: 0 22px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-tertiary);
  font-family: inherit;
  font-size: 15px;
  font-weight: var(--weight-medium);
  letter-spacing: -.009em;
  cursor: pointer;
  white-space: nowrap;
  transition: var(--transition-control);
}
.pills--sm .pill { height: 36px; padding: 0 18px; font-size: 14px; }
.pill.is-active { background: var(--surface-inverse); color: var(--text-inverse); border-color: transparent; }

/* ============================== Coque ============================== */

.shell {
  display: flex;
  height: 100vh;
  width: 100%;
  background: var(--surface-page);
  font-family: var(--font-sans);
  color: var(--text-primary);
  overflow: hidden;
}

.side {
  width: clamp(196px, 17vw, 248px);
  flex: none;
  border-right: 1px solid var(--border-hairline);
  display: flex;
  flex-direction: column;
  align-items: stretch;
  padding: 20px 16px;
  gap: 16px;
  /* Pas de defilement ici, a aucune largeur.

     Un conteneur qui defile rogne ce qui depasse, et il rogne dans les deux
     sens : « overflow-x: auto » fait passer « overflow-y » de visible a auto,
     regle CSS souvent oubliee. Le panneau des espaces est plus large que la
     barre debout, et plus haut qu'elle une fois couchee ; il etait donc coupe
     dans un cas comme dans l'autre. C'est .nav qui defile quand la place
     manque, et lui seul en a besoin. */
}

.brand { display: flex; align-items: center; gap: 10px; padding: 0 4px; flex: none; }
/* La marque est un SVG en ligne : display block, sinon la ligne de base du
   texte lui ajoute quelques pixels sous le disque et l'aligne de travers. */
.logo { display: block; flex: none; }
.brand__name { font-family: var(--font-display); font-weight: 600; font-size: 17px; letter-spacing: -.02em; }
.brand__beta {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.side__new { flex: none; }

.nav { display: flex; flex-direction: column; gap: 2px; flex: none; min-width: 0; overflow-x: auto; }
.nav__row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  cursor: pointer;
  font-family: inherit;
  font-size: var(--body-sm-size);
  font-weight: 500;
  color: var(--text-secondary);
  white-space: nowrap;
  flex: none;
  text-align: left;
  transition: var(--transition-control);
}
.nav__row:hover { background: var(--black-5); }
.nav__row.is-active { background: var(--black-5); }
.nav__row span { color: var(--text-primary); }

/* ---------------------- Le sélecteur d'espace ---------------------- */

/* Au pied de la barre, séparé du reste par un filet : la navigation dit où l'on
   va, ce bouton dit de quelle affaire il s'agit. Deux questions différentes, et
   celle-ci se pose moins souvent. */
.espsw {
  position: relative;
  margin-top: auto;
  padding-top: 14px;
  border-top: 1px solid var(--border-hairline);
  flex: none;
}
.espsw__btn {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 7px 8px;
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: var(--transition-control);
}
.espsw__btn:hover, .espsw__btn.is-open { background: var(--black-5); }
.espsw__nom {
  flex: 1;
  min-width: 0;
  font-size: var(--body-sm-size);
  font-weight: 500;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.espsw__fl { display: flex; flex: none; color: var(--text-tertiary); }

/* La pastille porte la couleur choisie pour l'affaire, celle que voient déjà
   ses destinataires. L'encre reste noire dessus : les accents du produit sont
   des teintes claires, une pastille inversée y serait illisible. */
.espav {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 8px;
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: .02em;
  color: var(--text-primary);
  box-shadow: inset 0 0 0 1px rgba(26, 26, 26, .07);
}

/* Le panneau s'ouvre vers le haut, à la largeur de la barre : le bouton est en
   bas, tout ce qu'il propose doit donc pousser au-dessus de lui. */
/* Un peu plus large que la barre, et il deborde sur la page : « Nouvel espace »
   ne tient pas dans 196 px une fois la pastille posee, et un libelle coupe par
   des points de suspension sur la seule ligne qui cree quelque chose serait le
   plus mauvais endroit ou economiser huit pixels. */
.espmenu {
  position: absolute;
  left: 0;
  right: 0;
  min-width: 232px;
  bottom: calc(100% + 6px);
  z-index: 30;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 1px;
  background: var(--white);
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}
.espmenu__t {
  font-family: var(--font-mono);
  font-size: var(--mono-caption-size);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  padding: 4px 10px 6px;
}
.espmenu__it {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 7px 10px 7px 8px;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: var(--transition-control);
}
.espmenu__it:hover { background: var(--black-5); }
.espmenu__it.is-on { background: var(--black-5); }
.espmenu__nom {
  flex: 1;
  min-width: 0;
  font-size: var(--body-sm-size);
  font-weight: 500;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.espmenu__ok { display: flex; flex: none; color: var(--text-primary); }
.espmenu__sep { height: 1px; background: var(--border-hairline); margin: 5px 4px; }

/* La ligne de création n'a pas de pastille de couleur, elle n'est pas un
   espace : un carré vide au trait discontinu, qui dit exactement qu'il reste
   une place à prendre. */
.espmenu__pl {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 8px;
  border: 1px dashed var(--border-strong);
  color: var(--text-secondary);
}
.espmenu__it--neuf .espmenu__nom { color: var(--text-secondary); }
.espmenu__it--neuf:hover .espmenu__nom { color: var(--text-primary); }

.espmenu__form { display: flex; flex-direction: column; gap: 8px; padding: 4px; }
.espmenu__ch {
  width: 100%;
  height: 38px;
  padding: 0 11px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--white);
  font-family: inherit;
  font-size: var(--body-sm-size);
  color: var(--text-primary);
  transition: var(--transition-control);
}
.espmenu__ch:focus { outline: none; border-color: var(--text-primary); }
.espmenu__acts { display: flex; gap: 6px; }
.espmenu__acts .btn { flex: 1; }

.main { flex: 1; min-width: 0; min-height: 0; overflow: auto; }
.main-inner {
  width: 100%;
  max-width: 1440px;
  margin: 0 auto;
  padding: clamp(22px, 3vw, 44px) clamp(18px, 3vw, 48px) 64px;
}

/* ========================= Écran « Mes liens » ========================= */

.page-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 26px;
  flex-wrap: wrap;
}
.page-head__txt { display: flex; flex-direction: column; gap: 6px; }
/* Les actions de l'en-tete tiennent ensemble a droite, le filtre en dernier :
   c'est celui qu'on vient rechercher le plus souvent, il garde sa place. */
.page-head__acts { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* Etiquette sur la ligne d'une reponse qui porte une etude de cas. Elle ne dit
   rien d'urgent, elle sert a retrouver : discrete, et posee contre le nom.

   L'ecart avec le nom et avec l'etiquette voisine vient du gap de .rrow__n, et
   non d'une marge : deux etiquettes collees l'une a l'autre par leurs marges ne
   pouvaient pas se separer en fin de ligne, et la seconde debordait sous
   l'interrupteur des que le nom etait long et la fenetre etroite. */
.rtag {
  padding: 2px 7px;
  border: 1px solid var(--border-hairline);
  border-radius: 999px;
  font-family: var(--font-sans);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: .01em;
  color: var(--text-tertiary);
  white-space: nowrap;
}

/* Le brouillon se distingue par un trait discontinu, pas par une couleur : rien
   ne va mal, c'est simplement un texte qui n'est pas fini. */
.rtag--dr {
  border-style: dashed;
  border-color: var(--border-default);
}

/* Pas encore ouverte. Meme forme que les autres etiquettes, remplie a l'encre
   de la page : dans une liste de contours gris, le plein est ce qui se voit en
   premier, et il n'a fallu inventer aucune couleur pour cela. */
.rtag--neuf {
  background: var(--text-primary);
  border-color: var(--text-primary);
  color: var(--text-inverse);
}

.linkbtn--danger { color: var(--status-negative); }
.linkbtn--danger:hover { color: var(--status-negative); text-decoration: underline; }

.cards { display: flex; flex-direction: column; gap: 14px; }
.card {
  position: relative;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-lg);
  background: var(--white);
  display: flex;
  align-items: stretch;
  flex-wrap: wrap;
}
/* Le coin haut droit de la carte, hors du flux : c'est un repère, il ne doit
   dépendre ni de la longueur du titre ni de la colonne où il tomberait. */
.card__state {
  position: absolute;
  top: 14px;
  right: 18px;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 7px;
}
/* L'aperçu est posé sur une marge beige, comme une page sur une table. Étalé
   bord à bord il devenait une zone de la carte parmi d'autres ; détaché, on
   voit tout de suite que c'est une page, et qu'elle s'ouvre. */
.card__prev {
  width: 312px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 18px;
  background: var(--highlight-50);
  border-radius: var(--radius-lg) 0 0 var(--radius-lg);
  border-right: 1px solid var(--border-hairline);
}
.card__main {
  flex: 1;
  min-width: 300px;
  padding: 18px clamp(16px, 2vw, 22px);
  display: flex;
  flex-direction: column;
  gap: 11px;
  justify-content: center;
}
.card__stats {
  flex: 1 0 auto;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: clamp(18px, 2.4vw, 26px);
  padding: 16px clamp(16px, 2vw, 26px);
}

.card__title { display: flex; align-items: center; gap: 10px; }
.card__name { font-size: var(--body-lg-size); font-weight: 500; letter-spacing: -.011em; }
.dot { width: 8px; height: 8px; border-radius: var(--radius-pill); flex: none; }
.dot--on { background: var(--status-positive); }
.dot--off { background: var(--black-30); }
.state {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.copybar {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  max-width: 100%;
  padding: 6px 14px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-pill);
  background: none;
  font-family: inherit;
  cursor: pointer;
  transition: var(--transition-control);
}
.copybar:hover { background: var(--black-5); }
.copybar__url {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.copybar__cta {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  flex: none;
}

.card__acts { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.waiting {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 14px;
  border: 1px dashed var(--black-30);
  border-radius: var(--radius-pill);
  font-size: var(--body-xs-size);
  color: var(--text-tertiary);
  cursor: default;
}

.menuwrap { position: relative; flex: none; }
.iconbtn {
  width: 34px; height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-pill);
  background: var(--white);
  color: var(--text-secondary);
  cursor: pointer;
  transition: var(--transition-control);
}
.iconbtn:hover { background: var(--black-5); }
.iconbtn:active { transform: scale(.98); }
.iconbtn.is-open { background: var(--black-5); }

.menu {
  position: absolute;
  top: 40px;
  left: 0;
  z-index: 30;
  min-width: 196px;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 1px;
  background: var(--white);
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}
.menu__item {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 9px 10px;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  font-family: inherit;
  font-size: var(--body-sm-size);
  font-weight: 500;
  color: var(--text-primary);
  white-space: nowrap;
  text-align: left;
  cursor: pointer;
  transition: var(--transition-control);
}
.menu__item:hover { background: var(--black-5); }
.menu__item--danger { color: var(--status-negative); border-top: 1px solid var(--border-hairline); }

.stat { display: flex; flex-direction: column; gap: 4px; align-items: center; }
.stat__v {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 22px;
  letter-spacing: -.02em;
  font-feature-settings: 'tnum' 1, 'lnum' 1;
}
.stat__l {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

/* Vignette de la page destinataire, dans la carte */
.mini {
  width: 100%;
  max-width: 252px;
  aspect-ratio: 16 / 10;
  padding: 12px 13px 11px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--white);
  background-image: var(--pattern-dot);
  background-size: var(--pattern-dot-size);
  border: 1px solid var(--black-10);
  border-radius: 10px;
  cursor: pointer;
  transition: transform 260ms var(--ease-out), box-shadow 260ms var(--ease-out);
}
.mini:hover { transform: scale(1.05); box-shadow: 0 14px 30px rgba(26, 26, 26, .14); }
/* Centré comme la vraie page destinataire : la vignette est censée la montrer,
   pas en donner une version réarrangée. */
.mini__id { display: flex; align-items: center; justify-content: center; gap: 5px; flex: none; }
.mini__av {
  width: 14px; height: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 6.5px;
  flex: none;
}
.mini__who {
  font-family: var(--font-mono);
  font-size: 6.5px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.mini__q {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  overflow: hidden;
  padding: 6px 0;
}
/* La question est ce qu'on cherche des yeux pour reconnaître un lien dans la
   liste : elle porte donc la vignette, et se lit sans se pencher. */
.mini__q span {
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 13px;
  line-height: 1.28;
  letter-spacing: -.018em;
  color: var(--text-strong);
}
.mini__acts { display: flex; gap: 5px; flex: none; }
.mini__pri {
  flex: 1.35;
  padding: 5.5px 4px;
  background: var(--action-primary-bg);
  color: var(--action-primary-fg);
  border-radius: var(--radius-pill);
  text-align: center;
  font-size: 7px;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.mini__sec {
  flex: 1;
  padding: 5px 4px;
  border: 1px solid var(--black-30);
  border-radius: var(--radius-pill);
  text-align: center;
  font-size: 6.5px;
  font-weight: 500;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ============================ Écran « Suivi » ============================ */

.empty {
  padding: 56px 24px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  text-align: center;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-lg);
}
.empty__t {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--heading-3-size);
  letter-spacing: -.015em;
}
/* Le même cadre, mais seul au milieu d'une page : il n'y a plus de barre
   latérale ni de liste autour de lui pour lui donner sa largeur. */
.empty--bloc { max-width: 620px; margin: 8vh auto 0; }
.empty--bloc .sub { max-width: 46ch; }
.empty--bloc code {
  font-family: var(--font-mono);
  font-size: .93em;
  padding: 2px 6px;
  border-radius: 5px;
  background: var(--black-5);
}

.linkbtn {
  justify-self: end;
  padding: 4px 0;
  border: none;
  background: none;
  font-family: var(--font-sans);
  font-size: var(--body-sm-size);
  font-weight: 500;
  color: var(--black-100);
  cursor: pointer;
  transition: var(--transition-control);
}
.linkbtn:hover { color: var(--black-70); }

/* ==================== Blocs de formulaire partagés ==================== */

.fgroup { display: flex; flex-direction: column; gap: 8px; }

.drop {
  width: 100%;
  padding: 16px 14px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  border: 1.5px dashed var(--black-30);
  border-radius: var(--radius-sm);
  background: none;
  font-family: inherit;
  text-align: center;
  cursor: pointer;
  transition: var(--transition-control);
}
.drop:hover { background: var(--black-5); }
/* Un fichier survole l'éditeur : la cible se signale */
.drop.is-over { border-color: var(--black-100); border-style: solid; background: var(--highlight-50); }
.drop__t { font-size: var(--body-sm-size); font-weight: 500; color: var(--text-primary); }
.drop__d { font-size: var(--body-xs-size); color: var(--text-tertiary); }

.filechip {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-sm);
}
.filechip__n { flex: 1; font-size: var(--body-sm-size); font-weight: 500; }

.xbtn {
  padding: 2px;
  border: none;
  background: none;
  font-family: var(--font-sans);
  font-size: var(--body-xs-size);
  color: var(--text-tertiary);
  cursor: pointer;
  transition: var(--transition-control);
}
.xbtn:hover { color: var(--black-100); }

.chips { display: flex; gap: 8px; flex-wrap: wrap; }
.chip {
  padding: 6px 14px;
  background: var(--white);
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-pill);
  font-family: var(--font-sans);
  font-size: var(--body-xs-size);
  color: var(--text-secondary);
  cursor: pointer;
  transition: var(--transition-control);
}
.chip:hover { background: var(--black-5); }
.chip:active { transform: scale(.98); }

.formacts { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }

/* Aperçu « téléphone » de l'écran Lien prêt */
.phone {
  width: 250px;
  padding: 18px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  background: var(--white);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-md);
}
.phone__id { display: flex; align-items: center; gap: 8px; }
.phone__av {
  width: 24px; height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 9px;
  flex: none;
}
.phone__who { font-size: var(--body-xs-size); color: var(--text-secondary); }
.phone__who em { font-style: normal; color: var(--text-tertiary); }
.phone__q {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 15px;
  line-height: 1.25;
  letter-spacing: -.015em;
  text-wrap: pretty;
}
.phone__pri {
  padding: 9px;
  background: var(--action-primary-bg);
  color: var(--action-primary-fg);
  border-radius: var(--radius-pill);
  text-align: center;
  font-size: 12px;
  font-weight: 500;
}
.phone__row { display: flex; gap: 8px; }
.phone__alt {
  flex: 1;
  padding: 7px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-pill);
  text-align: center;
  font-size: 11px;
  font-weight: 500;
}
.phone__res { border-top: 1px dashed var(--black-10); padding-top: 10px; }
.phone__resbtn {
  padding: 8px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  text-align: center;
  font-size: 11px;
  font-weight: 500;
}

/* ========================== Écran « Lien prêt » ========================== */
/* Colonne centrée : la version précédente était calée à gauche dans une page
   de 1440px et laissait un grand vide à droite. Sous l'adresse, deux colonnes
   de largeur égale, l'aperçu et le récapitulatif, qui se replient en une. */

.ready {
  width: 100%;
  max-width: 880px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 22px;
}
.ready__head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  text-align: center;
}
.ready__mark {
  width: 46px; height: 46px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-pill);
  background: var(--white);
  flex: none;
}
.ready__lead { margin: 0; max-width: 520px; text-wrap: pretty; }

.urlrow { display: flex; gap: 10px; flex-wrap: wrap; }
.urlbox {
  flex: 1;
  min-width: 220px;
  padding: 11px 14px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-sm);
  background: var(--white);
  font-family: var(--font-mono);
  font-size: var(--body-sm-size);
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  align-content: center;
}

.ready__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 16px;
  align-items: stretch;
}
.ready__prev {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 26px 20px;
  background: var(--highlight-50);
  border-radius: var(--radius-lg);
}
.ready__recap {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
  padding: 22px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-lg);
  background: var(--white);
}
.recap { margin: 0; width: 100%; flex: 1; display: flex; flex-direction: column; gap: 12px; }
.recap__row {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding-bottom: 12px;
  border-bottom: 1px dashed var(--black-10);
}
.recap__row:last-child { padding-bottom: 0; border-bottom: none; }
.recap__k {
  font-family: var(--font-mono);
  font-size: var(--mono-caption-size);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}
.recap__v {
  margin: 0;
  font-size: var(--body-sm-size);
  line-height: 1.4;
  color: var(--text-strong);
  text-wrap: pretty;
}

.ready__acts { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }

/* Colonne étroite du détail d'une réponse */
.narrow { width: 100%; max-width: 620px; display: flex; flex-direction: column; gap: 18px; }

/* L'écran d'une réponse et, à côté, la carte telle qu'elle paraîtra sur le mur.
   La place à droite était vide et le rapprochement est la moitié du travail :
   on encadre un passage d'un côté, on voit la carte se refaire de l'autre. */
.dsplit { display: flex; gap: 36px; }
.dsplit > .narrow { min-width: 0; }

/* La colonne occupe toute la hauteur, l'aperçu colle à l'intérieur.

   L'inverse ne tient pas : une colonne haute comme son seul contenu n'offre
   aucune course à ce qui colle dedans, et la carte redescendait avec la page.
   C'est pour la même raison qu'il n'y a pas d'align-items ici, l'étirement par
   défaut est justement ce qu'on veut. */
.dprev {
  flex: 0 0 320px;
  /* Sans cette remise à zéro, la largeur minimale du contenu l'emporte sur la
     base fixée juste au-dessus : la colonne d'aperçu s'élargissait jusqu'à
     écraser la page à côté d'elle. */
  min-width: 0;
}
.dprev__in {
  position: sticky;
  top: 24px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.dprev__box { border-radius: var(--radius-md); overflow: hidden; }

/* Sous cette largeur, la carte passerait sous la page et n'aiderait plus à
   comparer : deux choses à confronter doivent tenir côte à côte ou disparaître.
   Le mur reste consultable par son propre écran. */
/* L'aperçu ne disparaît jamais, il se resserre puis descend.

   Il était masqué sous 1240 pixels, ce qui le retirait de l'écran de beaucoup
   de portables sans rien dire : on croyait alors que la carte ne s'affichait
   pas pour certaines réponses, alors que c'était la fenêtre qui décidait. */
@media (max-width: 1240px) {
  .dprev { flex-basis: 264px; }
}

/* Sous cette largeur, deux colonnes ne tiennent plus sans écraser celle où l'on
   travaille. La carte passe donc à la suite, en fin de page : plus côte à côte,
   mais toujours là. */
@media (max-width: 1040px) {
  .dsplit { display: block; }
  .dprev { max-width: 360px; margin-top: 26px; }
  .dprev__in { position: static; }
}

/* =========================== Écran « Réponses » =========================== */

/* La ligne d'une réponse contient deux actions, ouvrir et publier : c'est donc
   un conteneur, plus un bouton. Un bouton ne peut pas en contenir un autre. */
/* Récapitulatif en tête des réponses.

   Un seul moment typographique, le mot des clients, et trois chiffres posés à
   côté sans cadre ni icône. C'est l'inverse du bandeau d'information qui
   occupait cette place : là, la surface servait à encadrer une phrase ; ici,
   elle sert à faire lire un mot. */
/* La hauteur de cette carte ne bouge jamais, quel que soit le nombre d'avis.

   C'est une règle et pas une conséquence. La liste des réponses commence juste
   dessous : une carte qui grandirait d'une ligne au dixième avis, puis au
   vingt-cinquième, ferait descendre la liste sans prévenir, et l'endroit où l'on
   va cliquer changerait de place d'une semaine à l'autre.

   Trois choses la tiennent. Le cadre du dessin a une hauteur fixe, et c'est la
   courbe qui se remet à l'échelle dedans. Chaque ligne de texte est en une
   seule ligne, jamais deux. Et rien n'apparaît ni ne disparaît qui occupe une
   ligne à soi : la pastille du prochain cap partage la rangée des nombres, elle
   peut s'en aller sans que rien ne remonte. */
.recap {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 16px 22px 18px;
  margin-bottom: 22px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-lg);
  background: var(--surface-card);
  box-shadow: var(--shadow-xs);
}
.recap__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}
/* Le mois est le titre de la carte : la courbe ne montre que lui. En petites
   capitales dans un coin, il laissait un vide en haut et se lisait comme une
   etiquette de rangement. */
.recap__mois {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(20px, 2.2vw, 25px);
  line-height: 1.1;
  letter-spacing: -.02em;
  color: var(--text-primary);
}
/* Le cap franchi est le seul élément qui se signale, et il ne paraît qu'un
   mois : c'est une nouvelle, pas un état. */
.recap__cap {
  flex: none;
  padding: 4px 11px;
  border-radius: var(--radius-pill);
  background: var(--surface-sunken);
  font-family: var(--font-mono);
  font-size: var(--mono-caption-size);
  letter-spacing: .02em;
  color: var(--text-primary);
}

/* Les étoiles et leur légende sur une seule ligne, à hauteur du mois. Empilées,
   elles faisaient à elles seules le double du titre qu'elles accompagnent, et
   la carte commençait par cinquante pixels qui ne disaient qu'une note. */
.recap__note { flex: none; display: flex; flex-direction: row; align-items: center; gap: 11px; }
.recap__noteL { font-size: var(--body-sm-size); color: var(--text-tertiary); white-space: nowrap; }
.recap__noteL b {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 17px;
  letter-spacing: -.01em;
  color: var(--text-primary);
  font-feature-settings: 'tnum' 1, 'lnum' 1;
}

/* Note en étoiles, remplies à la décimale près : la rangée ambre est posée sur
   la rangée grise et rognée à la fraction voulue. Arrondir à l'étoile entière
   ferait d'un 4,3 et d'un 4,7 la même image. */
.netoi { position: relative; display: inline-flex; line-height: 0; }
.netoi__r { display: inline-flex; gap: 3px; }
.netoi__r--on { position: absolute; left: 0; top: 0; overflow: hidden; }
.netoi svg {
  display: block;
  flex: none;
  width: 20px;
  height: 20px;
  overflow: visible;
  fill: rgba(26, 26, 26, .1);
  stroke: rgba(26, 26, 26, .16);
  stroke-width: .7;
  stroke-linejoin: round;
  paint-order: stroke fill;
}
/* Même ambre que le mur d'avis et la page destinataire. */
.netoi__r--on svg { fill: #fdb022; stroke: #d97706; stroke-width: .8; }

/* ---------------------------- La courbe ---------------------------- */

/* Deux totaux en tete, une courbe dessous, une marche a viser a droite. La
   hierarchie est dans la couleur et dans la place, jamais dans la taille : les
   deux nombres gardent le meme corps pour rester sur la meme ligne de base. */
/* L'écart entre les nombres et le dessin ne descend pas plus bas : le premier
   palier est tracé tout en haut du cadre, et collé de deux pixels de plus il se
   lirait comme un soulignement de « +9 en août ». */
.crb { display: flex; flex-direction: column; gap: 15px; }

.crb__tete {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
}
.crb__kpis { display: flex; gap: clamp(28px, 6vw, 64px); }
.crb__kpi { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.crb__n {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(26px, 2.8vw, 33px);
  line-height: 1;
  letter-spacing: -.03em;
  color: var(--text-primary);
  font-feature-settings: 'tnum' 1, 'lnum' 1;
}
.crb__kpi--o .crb__n { color: var(--text-tertiary); }
/* Les deux lignes sous un nombre ne se replient jamais : une seule d'entre elles
   qui passerait sur deux lignes ferait grandir la carte, et « datées à partir de
   maintenant » est assez longue pour que cela arrive. Sous 700 px, la carte se
   réorganise et la règle est levée. */
.crb__l {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: var(--body-sm-size);
  font-weight: 500;
  color: var(--text-secondary);
  white-space: nowrap;
}
.crb__pt2 { width: 8px; height: 8px; flex: none; border-radius: 50%; }
.crb__pt2--a { background: var(--action-primary-bg); }
.crb__pt2--o { background: var(--black-30); }
.crb__d { font-size: var(--body-xs-size); color: var(--text-tertiary); white-space: nowrap; }
/* Le filet pointille est ce qui dit qu'il y a quelque chose a survoler. */
.crb__d--aide { border-bottom: 1px dotted var(--black-30); cursor: help; }

/* Le pointille de la bordure est celui des paliers du dessin : c'est la meme
   chose dite deux fois, une en mots et une en trait. */
.crb__but {
  flex: none;
  /* Cale sur le haut des nombres, pas au milieu du bloc : centree, la pilule
     flottait entre deux lignes sans se rattacher a rien. */
  align-self: flex-start;
  margin-top: 5px;
  padding: 8px 14px;
  border: 1px dashed var(--black-30);
  border-radius: var(--radius-pill);
  font-size: var(--body-xs-size);
  color: var(--text-secondary);
  white-space: nowrap;
}

/* Hauteur fixe, et c'est tout l'intérêt : la courbe se remet à l'échelle dedans
   à chaque avis reçu, le cadre ne bouge pas. Le dessin grandit sans que la page
   grandisse. */
.crb__cadre {
  position: relative;
  height: clamp(118px, 12.6vw, 146px);
  /* Juste de quoi ne pas rogner la pastille du bout, et rien de plus : une
     marge plus large ferait une colonne vide a droite du dessin. */
  padding-right: 6px;
  cursor: crosshair;
}
.crb__svg { display: block; width: 100%; height: 100%; overflow: visible; }
.crb__svg path, .crb__svg line { vector-effect: non-scaling-stroke; }

.crb__pal { stroke: var(--black-10); stroke-width: 1; stroke-dasharray: 2 4; }
/* Les ouvertures sont le decor : un trait pale, sans remplissage. Les avis sont
   le sujet : un trait franc et son degrade. */
.crb__aire { fill: url(#crbAire); stroke: none; }
.crb__ouv { fill: none; stroke: rgba(26, 26, 26, .22); stroke-width: 1.3; stroke-linejoin: round; }
.crb__avis {
  fill: none;
  stroke: var(--action-primary-bg);
  stroke-width: 2.2;
  stroke-linejoin: round;
  stroke-linecap: round;
}

/* Le trait se dessine de gauche a droite en arrivant. C'est la seule animation
   de la carte, et elle dit dans quel sens elle se lit. */
@keyframes crbTrace { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
.crb__svg { animation: crbTrace 680ms var(--ease-out) both; }
@media (prefers-reduced-motion: reduce) { .crb__svg { animation: none; } }

/* Le nombre du palier est pose sur son trait, au bout, et perce le pointille :
   il annote la ligne au lieu de graduer une marge. */
.crb__palL {
  position: absolute;
  right: 6px;
  transform: translateY(-100%);
  padding: 0 1px 1px 5px;
  background: var(--surface-card);
  font-family: var(--font-mono);
  font-size: var(--mono-caption-size);
  color: var(--text-disabled);
  white-space: nowrap;
}

/* Le repere du jour. Il ne parait que si le mois n'est pas fini : sinon il
   doublerait le bord droit du dessin. */
.crb__jour {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 0;
  border-left: 1px dashed var(--black-10);
  pointer-events: none;
}
.crb__jour i {
  position: absolute;
  bottom: 0;
  left: 7px;
  font-family: var(--font-mono);
  font-size: var(--mono-caption-size);
  font-style: normal;
  color: var(--text-disabled);
  white-space: nowrap;
}

/* Le bout du trait des avis : ou l'on en est aujourd'hui. */
.crb__pt {
  position: absolute;
  right: 6px;
  width: 10px;
  height: 10px;
  margin: -5px -5px 0 0;
  border-radius: 50%;
  background: var(--action-primary-bg);
  box-shadow: 0 0 0 3px var(--surface-card);
}

/* Le repere de survol : un filet vertical et un point par trait. */
.crb__vise {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  margin-left: -.5px;
  background: var(--black-30);
  opacity: 0;
  pointer-events: none;
  transition: opacity 120ms ease;
}
.crb__cadre.is-vise .crb__vise { opacity: 1; }
.crb__vise::before, .crb__vise::after {
  content: '';
  position: absolute;
  left: 50%;
  width: 9px;
  height: 9px;
  margin: -4.5px 0 0 -4.5px;
  border-radius: 50%;
  box-shadow: 0 0 0 3px var(--surface-card);
}
.crb__vise::before { top: var(--y); background: var(--action-primary-bg); }
.crb__vise::after { top: var(--yo); background: var(--black-30); }

.crb__bulle {
  position: absolute;
  top: 6px;
  z-index: 3;
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-left: 14px;
  padding: 10px 13px;
  border-radius: var(--radius-md);
  background: var(--surface-inverse);
  color: var(--text-inverse);
  font-size: var(--body-xs-size);
  line-height: 1.4;
  white-space: nowrap;
  box-shadow: var(--shadow-lg);
  opacity: 0;
  pointer-events: none;
  transition: opacity 120ms ease;
}
.crb__cadre.is-vise .crb__bulle { opacity: 1; }
.crb__bulle.is-gauche { margin-left: 0; transform: translateX(-100%) translateX(-14px); }
.crb__bulle b { font-weight: 600; letter-spacing: -.005em; }
.crb__bl { display: inline-flex; align-items: center; gap: 7px; color: var(--text-inverse-secondary); }
.crb__bl::before { content: ''; width: 7px; height: 7px; border-radius: 50%; }
.crb__bl--a::before { background: var(--bg-100); }
.crb__bl--o::before { background: var(--bg-30); }

.crb__axe {
  display: flex;
  justify-content: space-between;
  margin-top: -6px;
  padding-right: 6px;
  font-family: var(--font-mono);
  font-size: var(--mono-caption-size);
  color: var(--text-disabled);
}

@media (max-width: 700px) {
  .recap { padding: 14px 16px 16px; gap: 12px; }
  .recap__top { align-items: flex-start; }
  .netoi svg { width: 18px; height: 18px; }
  .crb__tete { gap: 14px; }
  .crb__but { align-self: flex-start; }
  /* La place manque vraiment ici : mieux vaut une légende sur deux lignes
     qu'une légende coupée. La carte a le droit de respirer, elle n'est plus
     posée au-dessus d'une liste qu'on parcourt du regard. */
  .crb__l, .crb__d { white-space: normal; }
}

.rrows { display: flex; flex-direction: column; }
.rrow {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 0 8px 0 0;
  border-bottom: 1px solid var(--border-hairline);
  transition: var(--transition-control);
}
.rrow:hover { background: var(--black-5); }
.rrow__open {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px 8px;
  border: none;
  background: none;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}
.rrow__go { display: flex; flex: none; }
.rrow__av {
  width: 40px; height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
  background: var(--highlight);
  flex: none;
}
.rrow__txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
/* Le nom et ses etiquettes sur une ligne qui sait se replier : le nom garde sa
   place, les etiquettes passent dessous plutot que sous l'interrupteur. */
.rrow__n {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 3px 8px;
  font-size: var(--body-md-size);
  font-weight: 500;
}
.rrow__nm { min-width: 0; overflow-wrap: anywhere; }
.rrow__m {
  font-size: var(--body-xs-size);
  color: var(--text-tertiary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Une ligne pas encore ouverte. Le nom prend du gras, la ligne du dessous
   reprend un peu d'encre : de loin, la liste se lit comme une boite de
   reception, on voit ce qui reste a faire sans lire un seul mot.
   Aucun fond ajoute : la ligne survolee en a deja un, deux se seraient
   annules. */
.rrow.is-neuf .rrow__nm { font-weight: 600; }
.rrow.is-neuf .rrow__m { color: var(--text-secondary); }

/* ======================== Écran « Détail réponse » ======================== */

.back {
  padding: 0;
  border: none;
  background: none;
  font-family: var(--font-sans);
  font-size: var(--body-sm-size);
  font-weight: 500;
  color: var(--text-secondary);
  cursor: pointer;
  transition: var(--transition-control);
}
.back:hover { color: var(--black-100); }

.dhead { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.dname {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--heading-2-size);
  letter-spacing: -.02em;
}

.player {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px;
  background: var(--highlight-50);
  border-radius: var(--radius-md);
}
.player__btn {
  width: 44px; height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: var(--radius-pill);
  background: var(--action-primary-bg);
  cursor: pointer;
  flex: none;
  transition: var(--transition-control);
}
.player__btn:hover { background: var(--action-primary-bg-hover); }
.player__btn:active { transform: scale(.98); }
.player__t {
  font-family: var(--font-mono);
  font-size: var(--mono-caption-size);
  letter-spacing: .06em;
  color: var(--text-tertiary);
}

/* Mêmes contraintes que .wl__bars sur le Wall of Love : les traits s'étalent,
   se resserrent jusqu'à un pixel dans une colonne étroite, et ne dépassent
   jamais trois. Sans le plafond, cent dix barres élastiques redeviennent des
   blocs dès que le lecteur est large.

   En dessous de 330 px, les cent dix traits ne tiennent plus et les derniers
   sont rognés, comme sur le mur. Le lecteur vit dans la colonne de détail
   d'une réponse, qui reste plus large que cela ; si elle devait rétrécir un
   jour, c'est le nombre de traits qu'il faudrait baisser, pas le plafond. */
.wave {
  flex: 1;
  min-width: 0;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2px;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  overflow: hidden;
}
.wave i { flex: 1 1 0; min-width: 1px; max-width: 3px; border-radius: 1px; display: block; }
/* Bande de déplacement sans fond ni bordure : le halo général y dessinerait un
   grand rectangle gris en travers du lecteur. Un liseré discret suffit. */
.wave:focus-visible {
  box-shadow: none;
  outline: 2px solid var(--black-30);
  outline-offset: 3px;
  border-radius: 3px;
}

/* La vidéo garde ses proportions ici comme sous une carte. Étirée à la largeur
   de la colonne, un enregistrement pris au téléphone se retrouvait au milieu de
   deux grandes bandes noires. Sans align-self, le conteneur en colonne l'étire
   et width:auto ne sert à rien. */
.dvideo {
  align-self: flex-start;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 420px;
  display: block;
  border-radius: var(--radius-md);
  background: #242424;
}

/* Le conteneur porte l'alignement, la vidéo n'est plus qu'à l'intérieur : le
   bouton se pose dessus, et le cadre épouse l'image quelles que soient ses
   proportions. */
.dvid {
  position: relative;
  align-self: flex-start;
  max-width: 100%;
  line-height: 0;
  cursor: pointer;
}
.dvid .dvideo { align-self: auto; }

/* Un coin plutôt que le centre : le visage occupe le milieu de l'image, et une
   pastille posée dessus cache précisément ce qu'on regarde. */
.dvid__play {
  position: absolute;
  padding: 0;
  border: 0;
  cursor: pointer;
  right: 12px;
  bottom: 12px;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
  /* Un fond sombre translucide plutôt qu'un simple trait blanc : une vidéo peut
     être claire à cet endroit, et le repère y disparaîtrait. */
  background: rgba(20, 20, 20, .55);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  transition: transform 140ms var(--ease-out), background 140ms var(--ease-out);
}
.dvid:hover .dvid__play { background: rgba(20, 20, 20, .72); transform: scale(1.06); }
.dvid:active .dvid__play { transform: scale(.97); }
.dvid__play:focus-visible { outline: 2px solid var(--white); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
  .dvid__play { transition: none; }
  .dvid:hover .dvid__play { transform: none; }
}

.quote {
  padding: 20px;
  background: var(--highlight-50);
  border-radius: var(--radius-md);
  font-size: var(--body-lg-size);
  line-height: 1.45;
  letter-spacing: -.011em;
  color: var(--text-strong);
  text-wrap: pretty;
}

/* Transcription à choisir. Une phrase par ligne : la cible est large, bonne au
   doigt, et la coupure entre deux phrases se voit au lieu de se deviner.

   Le bloc reste sur le fond de la page, encadré d'un filet, là où une citation
   figée pose un aplat : le surligneur a besoin d'une feuille blanche pour se
   voir. Sur l'aplat, la phrase retenue et les autres se ressemblaient trop. */
.tsel {
  padding: 8px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-md);
}
.tsel__p {
  display: block;
  width: 100%;
  padding: 7px 10px;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  font: inherit;
  font-size: var(--body-md-size);
  line-height: 1.45;
  letter-spacing: -.008em;
  text-align: left;
  text-wrap: pretty;
  color: var(--text-secondary);
  cursor: pointer;
  transition: var(--transition-control);
}
.tsel__p:hover { background: var(--black-5); color: var(--text-strong); }
/* Le fond du surligneur, celui de la sélection du navigateur : le geste est le
   même, l'aspect doit l'être aussi. Aucune couleur nouvelle, la palette du
   back-office reste fermée. */
.tsel__p.is-on {
  background: var(--highlight);
  color: var(--text-strong);
  font-weight: 500;
}
.tsel__p:focus-visible { outline: 2px solid var(--black-100); outline-offset: -2px; }

.tsel__foot {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin-top: 8px;
}
.tsel__foot .hint { flex: 1 1 auto; }
.tsel__n {
  flex: 0 0 auto;
  font-family: var(--font-mono);
  font-size: var(--mono-caption-size);
  letter-spacing: var(--mono-caption-ls);
  color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}
/* Le compteur fonce en approchant de la limite plutôt que de virer au rouge :
   c'est un repère, pas une erreur. */
.tsel__n.is-plein { color: var(--text-strong); }
.skel {
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--highlight-50);
  border-radius: var(--radius-md);
}
.skel i { display: block; height: 12px; border-radius: 6px; background: var(--black-5); }

.notice {
  padding: 12px 14px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-sm);
  font-size: var(--body-sm-size);
  color: var(--text-secondary);
}

/* =========================== Écran « Réglages » =========================== */

.settings { width: 100%; max-width: 560px; display: flex; flex-direction: column; gap: 30px; }
.sgroup { display: flex; flex-direction: column; gap: 10px; }

/* De quel espace parlent les réglages. Collée au titre, et non rangée dans un
   bloc : c'est la portée de tout ce qui suit, pas un réglage de plus. */
.settings__ou { margin-top: -20px; }
.settings__ou b { font-weight: 600; color: var(--text-primary); }

/* ------------------------- La liste des espaces ------------------------- */

.esprows {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.esprow {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-top: 1px solid var(--border-hairline);
  flex-wrap: wrap;
}
.esprow:first-child { border-top: none; }
/* L'espace ouvert prend un fond, pas une couleur : dans une liste de trois, il
   faut savoir lequel on est en train de régler sans avoir à chercher. */
.esprow.is-ici { background: var(--highlight-50); }
.esprow__txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.esprow__nom {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--body-sm-size);
  font-weight: 500;
  color: var(--text-primary);
}
.esprow__ici {
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--text-primary);
  color: var(--text-inverse);
  font-family: var(--font-sans);
  font-size: 10.5px;
  font-weight: 500;
  white-space: nowrap;
}
.esprow__m { font-size: var(--body-xs-size); color: var(--text-tertiary); }
.esprow__acts { display: flex; align-items: center; gap: 12px; flex: none; margin-left: auto; }
.esprow--edit { gap: 10px; }
.esprow__ch {
  flex: 1;
  min-width: 140px;
  height: 38px;
  padding: 0 11px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--white);
  font-family: inherit;
  font-size: var(--body-sm-size);
  color: var(--text-primary);
  transition: var(--transition-control);
}
.esprow__ch:focus { outline: none; border-color: var(--text-primary); }
.esprow--edit .esprow__acts { gap: 6px; }
.idrow { display: flex; align-items: center; gap: 12px; }
.idav {
  width: 40px; height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 13px;
  flex: none;
}
.swatches { display: flex; gap: 8px; }
.swatch {
  width: 28px; height: 28px;
  border: none;
  border-radius: var(--radius-pill);
  cursor: pointer;
  box-shadow: inset 0 0 0 1px rgba(26, 26, 26, .1);
}
.swatch.is-on { box-shadow: inset 0 0 0 2px rgb(26, 26, 26); }
.qitem {
  padding: 11px 14px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-sm);
  font-size: var(--body-sm-size);
  color: var(--text-strong);
}
.addrow { display: flex; gap: 10px; align-items: flex-start; }
.addrow .field { flex: 1; }
.sfoot {
  border-top: 1px dashed var(--black-10);
  padding-top: 14px;
  font-size: var(--body-xs-size);
  color: var(--text-tertiary);
}

/* ============================== Adaptatif ============================== */

@media (max-width: 1179px) {
  .card__prev { width: 268px; }
  .card__stats { justify-content: flex-start; }
}

@media (max-width: 859px) {
  .ready__grid { grid-template-columns: minmax(0, 1fr); }
  .ready__acts > * { flex: 1; }
  .shell { flex-direction: column; height: auto; min-height: 100vh; overflow: visible; }
  .side {
    width: 100%;
    flex-direction: row;
    align-items: center;
    padding: 12px 16px;
    gap: 14px;
    border-right: none;
    border-bottom: 1px solid var(--border-hairline);
  }
  .side__new { display: none; }
  .nav { flex-direction: row; flex: 1 1 auto; }

  /* La barre est couchée : le sélecteur passe à droite, et son panneau s'ouvre
     vers le bas, puisqu'il n'y a plus rien en dessous de lui. */
  .espsw {
    margin-top: 0;
    margin-left: auto;
    padding-top: 0;
    border-top: none;
  }
  .espmenu { bottom: auto; top: calc(100% + 8px); left: auto; right: 0; min-width: 232px; }

  /* Écart assumé avec la maquette : en dessous de 860px le nom de l'espace et la
     puce « Bêta » mangeaient toute la largeur et la navigation se retrouvait
     écrasée à une centaine de pixels, premier onglet tronqué. La pastille
     colorée reste, et elle suffit à dire où l'on est ; le panneau, lui, montre
     bien les noms. */
  .espsw__nom { display: none; }
  .brand__beta { display: none; }
  .card__prev {
    width: 100%;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    border-right: none;
    border-bottom: 1px solid var(--border-hairline);
  }
  .card__main { min-width: 100%; }
  /* Empilée, la carte donne son coin haut droit à l'aperçu : la pastille y
     serait posée sur l'image. Elle redescend dans le flux, sur sa propre
     ligne, toujours calée à droite. */
  .card__state {
    position: static;
    order: -1;
    width: 100%;
    justify-content: flex-end;
    padding: 12px 16px 0;
  }
  .linkbtn { justify-self: start; }
}

/* =========================== Éditeur de lien =========================== */
/* Plein écran, logique d'éditeur de formulaire : fil d'Ariane en haut,
   aperçu cliquable au centre, panneau contextuel à droite. Les classes r*
   de l'aperçu viennent de recipient.css, chargé par index.html. */

#editor {
  position: fixed;
  inset: 0;
  z-index: 60;
  overflow: auto;
  overscroll-behavior: contain;
  background: var(--surface-page);
  font-family: var(--font-sans);
  color: var(--text-primary);
}
#editor[hidden] { display: none; }

/* Barre du haut */
.edtop {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px clamp(14px, 2.5vw, 28px);
  background: var(--white);
  border-bottom: 1px solid var(--border-hairline);
}
.edtop__t {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 16px;
  letter-spacing: -.015em;
  white-space: nowrap;
}
.edtop__save { flex: none; }

/* Fil d'Ariane */
.edsteps {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 2px;
  overflow-x: auto;
}
.edstep {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 12px;
  border: none;
  border-radius: var(--radius-pill);
  background: none;
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
  cursor: pointer;
  white-space: nowrap;
  transition: var(--transition-control);
}
.edstep:hover { background: var(--black-5); }
.edstep.is-on { background: var(--black-5); color: var(--text-primary); }
.edstep__n {
  width: 20px; height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--black-30);
  border-radius: var(--radius-pill);
  font-family: var(--font-mono);
  font-size: 11px;
  flex: none;
}
.edstep.is-done .edstep__n {
  background: var(--black-100);
  border-color: var(--black-100);
  color: var(--text-inverse);
}
.edsep { display: flex; color: var(--black-30); flex: none; }

/* Corps : l'étape à gauche, la page du client à droite */
.edbody {
  display: flex;
  align-items: flex-start;
  gap: clamp(24px, 3.5vw, 56px);
  width: 100%;
  max-width: 1120px;
  margin: 0 auto;
  padding: clamp(20px, 3.5vw, 42px) clamp(14px, 2.5vw, 32px) 90px;
}

/* L'étape en cours : une colonne de lecture, du titre au bouton Continuer */
.edwiz {
  flex: 1;
  min-width: 0;
  max-width: 560px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 22px;
}
.edhead { display: flex; flex-direction: column; gap: 10px; }
.edwh {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(23px, 2.6vw, 28px);
  letter-spacing: -.022em;
  line-height: 1.12;
  color: var(--text-primary);
}
.edsub {
  margin: 0;
  max-width: 480px;
  font-size: 14px;
  line-height: 1.55;
  color: var(--text-secondary);
}

/* Pied d'étape : l'action primaire et, quand elle est grisée, sa raison */
.ednext {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 4px;
}
.ednext--fin { flex-direction: column; align-items: stretch; gap: 10px; text-align: center; }
.edmanque {
  border: none;
  background: none;
  padding: 0;
  font-family: inherit;
  font-size: 13px;
  color: var(--status-negative);
  cursor: pointer;
}
.edmanque:hover { text-decoration: underline; }

/* Récapitulatif de l'étape 3 : trois lignes, chacune ramène à son étape */
.edrecaps { display: flex; flex-direction: column; gap: 6px; }
.edrecap {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 11px 12px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-sm);
  background: var(--white);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: var(--transition-control);
}
.edrecap:hover { background: var(--black-5); }
.edrecap__ic {
  width: 30px; height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border-hairline);
  background: var(--surface-subtle);
  color: var(--text-secondary);
  flex: none;
}
.edrecap__ic.is-ok {
  background: #e7f3ec;
  border-color: rgba(31, 158, 86, .28);
  color: var(--status-positive);
}
.edrecap__txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.edrecap__t {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}
.edrecap__d {
  font-size: 14px;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.edrecap__go {
  flex: none;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
}
.edrecap:hover .edrecap__go { color: var(--text-primary); }

/* La page du client, passive : un miroir qui suit la frappe, rien à cliquer */
.edprev {
  width: 340px;
  flex: none;
  position: sticky;
  top: 86px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.edprev__card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  padding: 26px 20px 20px;
  background: var(--white);
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-lg);
  text-align: center;
  background-image: var(--pattern-dot);
  background-size: var(--pattern-dot-size);
}
.edprev .rq { font-size: 19px; }
.edprev .rfoot { max-width: none; }
/* L'aperçu reçoit du texte saisi par l'utilisateur : un intitulé de bouton à
   rallonge, un nom de fichier sans espace, une question-fleuve. La carte fait
   340 px, tout ce qui la traverse doit plier ou s'abréger, jamais déborder. */
.edprev .rq, .edprev .rhint { max-width: 100%; overflow-wrap: anywhere; }
.edprev .rid { max-width: 100%; }
.edprev .rid__t { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.edprev .btn { max-width: 100%; }
.edprev .btn > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.edprev__cap {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: .07em;
  text-transform: uppercase;
  text-align: center;
  color: var(--text-tertiary);
}

/* Classe doublée à dessein. Elle marque un contenu dérivé, pas saisi, et se
   pose sur des éléments qui fixent déjà leur couleur : à égalité de
   spécificité, c'est l'ordre de déclaration qui tranchait, et le texte
   dérivé s'affichait comme un texte écrit à la main. Doubler la classe la fait
   gagner quel que soit l'endroit du fichier. */
.edq--ph.edq--ph { color: var(--text-tertiary); }

/* Liste des éléments à livrer */
.edlist { display: flex; flex-direction: column; gap: 6px; }
.editem {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-sm);
  background: var(--white);
}
.editem__ic {
  width: 28px; height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  background: var(--surface-subtle);
  color: var(--text-secondary);
  flex: none;
}
.editem__txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.editem__t {
  font-size: var(--body-sm-size);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.editem__d {
  font-size: var(--body-xs-size);
  color: var(--text-tertiary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.editem__x {
  width: 26px; height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: var(--radius-pill);
  background: none;
  color: var(--text-tertiary);
  cursor: pointer;
  flex: none;
  transition: var(--transition-control);
}
.editem__x:hover { background: var(--black-5); color: var(--status-negative); }

/* Sélecteur du type d'élément à ajouter */
.edsegs {
  display: flex;
  gap: 4px;
  padding: 3px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-pill);
}
.edseg {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 7px 6px;
  border: none;
  border-radius: var(--radius-pill);
  background: none;
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-tertiary);
  white-space: nowrap;
  cursor: pointer;
  transition: var(--transition-control);
}
.edseg:hover { background: var(--black-5); }
.edseg.is-on { background: var(--surface-inverse); color: var(--text-inverse); }
.edadd { display: flex; }

/* Ligne validité (carte réglages du lien) */
.edfield { display: flex; flex-direction: column; gap: 8px; }
.eddiv { border-top: 1px dashed var(--black-10); }

.edta {
  width: 100%;
  min-height: 92px;
  padding: 10px 12px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-sm);
  background: var(--white);
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.5;
  letter-spacing: -.006em;
  color: var(--text-primary);
  resize: vertical;
  outline: none;
  transition: var(--transition-control);
}
.edta:focus { border-color: var(--border-strong); box-shadow: var(--ring-focus); }

/* ============================================================
   Ecran : Etudes de cas
   ============================================================ */

/* Des cartes debout, et non couchees comme celles de Mes liens. Un lien se lit
   d'une ligne ; une etude se reconnait a son image, qui occupe donc le haut de
   la carte. On parcourt une etagere, pas une liste. */
.ecards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(258px, 1fr));
  gap: 18px;
}
.ecard {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-lg);
  background: var(--white);
  overflow: hidden;
  transition: border-color 160ms ease, box-shadow 160ms ease, transform 160ms ease;
}
.ecard:hover {
  border-color: var(--black-30);
  box-shadow: 0 6px 20px rgba(26, 26, 26, .07);
  transform: translateY(-2px);
}
.ecard__open {
  display: flex;
  flex-direction: column;
  padding: 0;
  border: none;
  background: none;
  text-align: left;
  cursor: pointer;
}

/* La vignette n'est pas une image deposee : c'est la page en tout petit, sa
   diagonale, sa couleur et son titre sur une carte blanche. Rien a televerser,
   et ce qu'on voit sur l'etagere est bien ce qui s'ouvrira. */
.ecard__prev {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 4 / 3;
  padding: 20px;
  background:
    linear-gradient(135deg, rgba(0,0,0,0) 0, rgba(0,0,0,0) 49.9%,
      var(--epage, #f6f6f4) 50.1%, var(--epage, #f6f6f4) 100%),
    linear-gradient(158deg, rgba(255,255,255,.2), rgba(255,255,255,0) 58%),
    var(--eacc, var(--black-100));
}
.ecard__mini {
  max-width: 100%;
  padding: 11px 13px;
  border-radius: 8px;
  background: var(--ecarte, #fff);
  box-shadow: 0 8px 22px rgba(0, 0, 0, .18);
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 11.5px;
  line-height: 1.28;
  letter-spacing: -.018em;
  color: var(--etexte, #151515);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
}

/* Un brouillon n'a pas de vignette, parce qu'il n'a pas encore de page : la
   sienne est un cadre vide sur un fond sourd, la ou une etude publiee montre sa
   couleur. Le trait discontinu, tout autour, dit la meme chose au premier coup
   d'oeil, avant meme qu'on lise l'etiquette.

   Aucune couleur d'alerte : rien ne va mal, c'est un texte qui n'est pas fini. */
.ecard--dr { border-style: dashed; border-color: var(--black-10); }
.ecard--dr:hover { border-style: solid; }
.ecard__prev--dr { background: var(--surface-sunken); }
.ecard--dr .ecard__mini {
  background: none;
  border: 1px dashed var(--black-30);
  box-shadow: none;
  color: var(--text-tertiary);
}

/* Ou en est le brouillon, a la place des statistiques d'une etude publiee. Les
   quatre segments sont les quatre etapes de l'editeur : on retrouve du regard ce
   qu'on a laisse en plan. */
.ecard__prog {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 14px 13px;
  border-top: 1px solid var(--border-hairline);
}
.ecard__bar { display: flex; gap: 4px; }
.ecard__seg {
  flex: 1;
  height: 3px;
  border-radius: 2px;
  background: var(--black-10);
}
.ecard__seg.is-on { background: var(--black-100); }
.ecard__pl { font-size: 11.5px; line-height: 1.4; color: var(--text-tertiary); }

/* Les cartes d'une meme rangee ont la meme hauteur, et la plus courte se
   retrouve avec du vide. Il tombe sous le dernier filet, ou il ressemble a une
   carte coupee ; donne au corps, il n'est plus qu'une marge un peu large. */
.ecard__open { flex: 1 1 auto; }
.ecard__body { flex: 1 1 auto; }
.ecard__tag {
  align-self: flex-start;
  padding: 2px 8px;
  border: 1px dashed var(--border-default);
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.ecard__body { display: flex; flex-direction: column; gap: 12px; padding: 16px 16px 14px; }
.ecard__t {
  font-family: var(--font-sans);
  font-size: 14.5px;
  font-weight: 600;
  line-height: 1.32;
  letter-spacing: -.012em;
  color: var(--text-primary);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
}
.ecard__who { display: flex; align-items: center; gap: 9px; }
.ecard__av {
  width: 30px;
  height: 30px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  border-radius: 999px;
  background: var(--surface-inverse);
  color: var(--text-inverse);
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .02em;
}
.ecard__av.is-photo { background: none; border: 1px solid var(--border-hairline); }
.ecard__avimg { width: 100%; height: 100%; object-fit: cover; display: block; }
.ecard__wt { min-width: 0; display: flex; flex-direction: column; }
.ecard__n {
  font-size: 12.5px;
  font-weight: 500;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ecard__r {
  font-size: 11.5px;
  color: var(--text-tertiary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ecard__d {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

/* Trois chiffres sur une ligne, separes par des filets. Le taux est le seul qui
   dise quelque chose a lui seul : les deux autres sont la pour qu'on puisse le
   croire. */
.ecard__stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border-top: 1px solid var(--border-hairline);
}
.ecard__st {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 10px 6px;
  text-align: center;
}
.ecard__st + .ecard__st { border-left: 1px solid var(--border-hairline); }
.ecard__sv {
  font-family: var(--font-sans);
  font-size: 15px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
  color: var(--text-primary);
}
.ecard__sl {
  font-size: 10.5px;
  line-height: 1.2;
  color: var(--text-tertiary);
}

/* Partager est l'action principale de la carte : une etude ne vaut que si elle
   circule. Le bouton prend donc la largeur, et l'ouverture de la page se range
   dans un carre a cote. */
.ecard__part {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 14px;
  border-top: 1px solid var(--border-hairline);
}
.ecard__part .btn { flex: 1; min-width: 0; }
.ecard__voir {
  width: 34px;
  height: 34px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-sm);
  background: var(--white);
  color: var(--text-secondary);
  transition: var(--transition-control);
}
.ecard__voir:hover { border-color: var(--black-30); color: var(--text-primary); }

.ecard__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 14px 11px;
  border-top: 1px solid var(--border-hairline);
  background: var(--surface-subtle);
}
.ecard__sw { display: flex; align-items: center; gap: 8px; }
.ecard__swl { font-size: 12px; color: var(--text-secondary); }
.ecard__note {
  padding: 9px 14px 11px;
  border-top: 1px solid var(--border-hairline);
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--text-tertiary);
}

@media (prefers-reduced-motion: reduce) {
  .ecard { transition: none; }
  .ecard:hover { transform: none; }
}

/* ============================================================
   Editeur d'etude de cas
   ============================================================ */

/* Les zones de saisie de l'etude n'ont pas toutes le meme poids : un titre
   tient sur deux lignes, un recit en demande quatre. Une hauteur unique
   donnait quatre lignes vides sous un titre de six mots. */
.etta--2 { min-height: 58px; }
.etta--3 { min-height: 76px; }
.etta--4 { min-height: 100px; }

/* Choix de l'avis. La ligne entiere est cliquable, la coche a droite dit
   lequel est retenu : deux avis choisis en meme temps n'existent pas, une
   case a cocher aurait promis le contraire. */
.etpick {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 11px 12px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-md);
  background: var(--white);
  text-align: left;
  cursor: pointer;
  transition: var(--transition-control);
}
.etpick:hover { background: var(--black-5); }
.etpick.is-on { border-color: var(--border-strong); background: var(--black-5); }
.etpick__av {
  width: 32px;
  height: 32px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: var(--surface-inverse);
  color: var(--text-inverse);
  font-family: var(--font-sans);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .02em;
}
.etpick__txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.etpick__t {
  display: flex;
  align-items: center;
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 500;
  color: var(--text-primary);
}
.etpick__tag {
  margin-left: 8px;
  padding: 1px 7px;
  border: 1px solid var(--border-hairline);
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 500;
  color: var(--text-tertiary);
  white-space: nowrap;
}
.etpick__d {
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* La coche occupe sa place des le depart, transparente : sans cela, choisir un
   avis elargissait la ligne d'un cran et toute la liste sautait. */
.etpick__ck { flex: none; display: flex; color: transparent; }
.etpick.is-on .etpick__ck { color: var(--text-primary); }

/* Sections du recit */
.etsecs { display: flex; flex-direction: column; gap: 14px; }
.etsec {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-md);
  background: var(--surface-subtle);
}
.etsec__top { display: flex; align-items: center; gap: 9px; }
.etsec__n {
  width: 20px;
  height: 20px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: var(--surface-inverse);
  color: var(--text-inverse);
  font-family: var(--font-mono);
  font-size: 10.5px;
}
.etsec__lab {
  flex: 1;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}
.etsec__acts { display: flex; align-items: center; gap: 2px; }
.etsec__b {
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text-tertiary);
  cursor: pointer;
  transition: var(--transition-control);
}
.etsec__b:hover:not([disabled]) { background: var(--black-5); color: var(--text-primary); }
.etsec__b[disabled] { opacity: .3; cursor: default; }
.etsec__b--x:hover:not([disabled]) { color: var(--status-negative); }

.etadd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  padding: 11px;
  border: 1px dashed var(--border-hairline);
  border-radius: var(--radius-md);
  background: none;
  font-family: var(--font-sans);
  font-size: 13.5px;
  font-weight: 500;
  color: var(--text-secondary);
  cursor: pointer;
  transition: var(--transition-control);
}
.etadd:hover { border-color: var(--border-strong); color: var(--text-primary); background: var(--black-5); }

/* La suppression est en bas de la derniere etape, apres le bouton qui publie :
   on ne la croise pas en chemin, on va la chercher. */
.etdel {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  margin-top: 10px;
  padding-top: 18px;
  border-top: 1px solid var(--border-hairline);
  text-align: center;
}

/* Illustrations d'une section : une rangee de vignettes carrees, et le bouton
   qui en ajoute au bout. Quatre au plus, apres quoi le bouton cede la place a
   la raison de son absence. */
.etills { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.etill {
  position: relative;
  width: 62px;
  height: 62px;
  flex: none;
  overflow: hidden;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-hairline);
  background: #0c0c0d;
}
.etill img, .etill video { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Pendant l'envoi, un carre qui respire : il tient la place que le fichier
   prendra, ce qui evite a la rangee de sauter quand il arrive. */
.etill--cours {
  background: var(--black-10);
  animation: etpouls 1.1s ease-in-out infinite;
}
@keyframes etpouls { 0%, 100% { opacity: .45; } 50% { opacity: .9; } }
.etill__x {
  position: absolute;
  top: 3px;
  right: 3px;
  width: 20px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  border-radius: 999px;
  background: rgba(12, 12, 13, .68);
  color: #fff;
  cursor: pointer;
  opacity: 0;
  transition: opacity 140ms ease, background 140ms ease;
}
.etill:hover .etill__x, .etill__x:focus-visible { opacity: 1; }
.etill__x:hover { background: var(--status-negative); }

.etill__add {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  flex: 1;
  min-width: 0;
  padding: 9px 12px;
  border: 1px dashed var(--border-hairline);
  border-radius: var(--radius-sm);
  background: none;
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--text-secondary);
  cursor: pointer;
  transition: var(--transition-control);
}
/* Des qu'une vignette est posee, le bouton se reduit a un carre de meme taille :
   il devient le suivant de la rangee, pas une banniere sous elle. */
.etill__add--p { flex: none; width: 62px; height: 62px; padding: 0; }
.etill__add:hover { border-color: var(--border-strong); color: var(--text-primary); background: var(--white); }
.etills__plein { font-size: 11.5px; color: var(--text-tertiary); }

/* ---- Apercu de la page publique, en reduction ---- */

/* Ce n'est pas la vraie page, c'est sa silhouette : ce qu'on suit en tapant,
   c'est le remplissage, pas la typographie. Les gabarits gris disent ou le
   texte ira avant qu'il n'existe. */
.etpv {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 20px 18px 18px;
  background: var(--white);
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-lg);
}
.etpv .is-vide, .etpv__q .is-vide { color: var(--text-tertiary); }
.etpv__t {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 18px;
  line-height: 1.2;
  letter-spacing: -.022em;
  color: var(--text-primary);
  overflow-wrap: anywhere;
}
.etpv__who { display: flex; align-items: center; gap: 9px; }
.etpv__av {
  width: 30px;
  height: 30px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 600;
}
.etpv__wt { min-width: 0; display: flex; flex-direction: column; }
.etpv__n {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.etpv__r {
  font-size: 11px;
  color: var(--text-tertiary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.etpv__sep { height: 1px; background: var(--border-hairline); }

/* Le temoignage dans l'apercu. Il ne se joue pas : l'apercu est passif, il dit
   ce qui sera la. Une video montre son affiche, une voix sa pilule. */
.etpv__vid {
  position: relative;
  aspect-ratio: 16 / 10;
  border-radius: 9px;
  overflow: hidden;
  background: #0c0c0d center/cover no-repeat;
}
.etpv__vid::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,0) 50%, rgba(0,0,0,.5) 100%);
}
.etpv__pl {
  position: absolute;
  right: 9px;
  bottom: 9px;
  z-index: 2;
  display: block;
  color: #fff;
}
.etpv__pl svg { width: 19px; height: 19px; display: block; fill: currentColor;
  filter: drop-shadow(0 1px 4px rgba(0,0,0,.6)); }
.etpv__aud {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 12px 8px 8px;
  border-radius: 999px;
  background: var(--black-5);
}
.etpv__pl--s {
  position: static;
  width: 26px;
  height: 26px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: var(--surface-inverse);
  color: var(--text-inverse);
}
.etpv__pl--s svg { width: 10px; height: 10px; filter: none; }
/* La silhouette de la voix, comme sur le mur et sur la page publique, reduite a
   la taille de l'apercu. Elle ne s'anime pas : l'apercu est passif, il dit ce
   qui sera la, il ne le joue pas. */
.etpv__onde {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1px;
  height: 14px;
  overflow: hidden;
}
.etpv__onde i {
  flex: 1 1 0;
  min-width: 1px;
  max-width: 2px;
  border-radius: 1px;
  background: var(--black-30);
}

/* Les illustrations dans l'apercu, comme sur la page : seule, une image prend
   toute la largeur ; a plusieurs, elles passent en grille et se recadrent. */
/* Une illustration se reduit a une bande dans l'apercu.

   A leurs proportions reelles, deux photos verticales occupaient a elles seules
   plus de hauteur que tout le reste de la page : on ne suivait plus rien de ce
   qu'on ecrivait. La bande dit qu'il y a une image, en montre assez pour la
   reconnaitre, et rend la place au texte. La vraie page les garde en entier. */
.etpvi { display: flex; flex-direction: column; gap: 5px; margin-top: 6px; }
.etpvi__b {
  position: relative;
  display: block;
  height: 44px;
  overflow: hidden;
  border-radius: 6px;
  background: #0c0c0d;
}
.etpvi__b img, .etpvi__b video { width: 100%; height: 100%; object-fit: cover; display: block; }
/* L'icone se pose sur l'image : elle dit la nature du fichier la ou une bande
   de quarante pixels ne suffit pas toujours a la deviner.

   Fond blanc plein, et non un noir transparent : au-dessus d'une photo sombre,
   le voile disparaissait dans l'image et l'icone avec lui. */
.etpvi__i {
  position: absolute;
  left: 7px;
  top: 50%;
  transform: translateY(-50%);
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 5px;
  background: var(--white);
  color: var(--text-primary);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .28);
}
.etpvi__b--v { background: var(--black-10); animation: etpouls 1.1s ease-in-out infinite; }
.etpv__tm { font-size: 11px; font-variant-numeric: tabular-nums; color: var(--text-tertiary); }
.etpv__res { font-size: 12.5px; line-height: 1.5; color: var(--text-secondary); overflow-wrap: anywhere; }
.etpv__q {
  padding: 10px 12px;
  border: 1px solid var(--border-hairline);
  border-left: 3px solid var(--black-100);
  border-radius: 8px;
  font-size: 12.5px;
  line-height: 1.45;
  font-style: italic;
  color: var(--text-primary);
  overflow-wrap: anywhere;
}
.etpv__x { font-size: 12px; line-height: 1.5; color: var(--text-secondary); overflow-wrap: anywhere; }
.etpv__secs { display: flex; flex-direction: column; gap: 10px; }
.etpv__s { display: flex; flex-direction: column; gap: 3px; }
.etpv__st {
  padding-bottom: 5px;
  border-bottom: 1px solid var(--border-hairline);
  font-family: var(--font-sans);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-primary);
  overflow-wrap: anywhere;
}
.etpv__sx { font-size: 11.5px; line-height: 1.5; color: var(--text-tertiary); overflow-wrap: anywhere; }
.etpv__ctaw { display: flex; justify-content: center; margin-top: 4px; }
.etpv__cta {
  padding: 8px 16px;
  border-radius: 999px;
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}
/* Sans adresse, la place du bouton reste dessinee, vide : elle dit a la fois
   qu'il n'y en aura pas et ou il se mettrait si on en donnait une. */
.etpv__cta--off {
  border: 1px dashed var(--black-30);
  background: none;
  color: var(--text-tertiary);
  font-weight: 500;
}

/* Sous 1040px, l'aperçu s'efface : l'étape mérite toute la largeur, et la
   vraie page du client se découvre à l'écran suivant, le lien en main. */
@media (max-width: 1039px) {
  .edbody { flex-direction: column; align-items: stretch; }
  .edprev { display: none; }
}

/* Sous 640px, la barre garde le retour, les trois pastilles et le bouton :
   le titre et les chevrons n'y tiennent pas sans rogner les étapes. */
@media (max-width: 639px) {
  .edtop { gap: 10px; }
  .edtop__t { display: none; }
  .edsep { display: none; }
  .edstep { padding: 7px 9px; }
  .edstep__l { display: none; }
}

/* Filtres de la liste des liens */
/* Filtres et recherche forment un seul groupe, à gauche ; le décompte est
   renvoyé à droite.

   La barre répartissait ses trois éléments à intervalles égaux, et la
   recherche se retrouvait au milieu, sans rien à quoi se rattacher : elle
   avait l'air posée là. Collée aux pastilles, à la même hauteur et avec le
   même arrondi, elle se lit comme le prolongement de la rangée de filtres,
   ce qu'elle est : on filtre, puis on cherche. */
.filterbar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.filterbar__n {
  margin-left: auto;
  padding-left: 14px;
  font-family: var(--font-mono);
  font-size: var(--mono-caption-size);
  letter-spacing: var(--mono-caption-ls);
  color: var(--text-tertiary);
}

/* Recherche. Même hauteur et même bordure que les pastilles de filtre à côté :
   c'est la même barre d'outils, elle doit se lire comme un seul rang.
   Au repos elle reste creuse, sur le fond de la page ; elle ne passe au blanc
   qu'une fois qu'on écrit dedans. */
.search {
  /* Elle s'étire un peu dans la place laissée par les filtres, sans jamais
     traverser la page : un champ qui s'arrête net à deux cent soixante pixels
     laisse un vide au milieu de la rangée, et c'est ce vide qui la faisait
     paraître posée là par hasard. */
  flex: 1 1 260px;
  max-width: 420px;
  min-width: 150px;
  display: flex;
  align-items: center;
  gap: 7px;
  height: 36px;
  padding: 0 5px 0 13px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-pill);
  background: none;
  color: var(--text-tertiary);
  transition: var(--transition-control);
}
.search:hover { border-color: var(--black-30); }
/* Bordure encrée plutôt qu'un halo : la lueur de 3px faisait un second cadre
   flou autour du champ, seul élément de la page à en porter un. */
.search:focus-within {
  border-color: var(--black-100);
  background: var(--white);
  color: var(--text-primary);
}
.search .ico { flex: none; }
.search__el {
  flex: 1;
  min-width: 0;
  height: 100%;
  border: none;
  background: none;
  outline: none;
  font-family: inherit;
  font-size: var(--body-sm-size);
  color: var(--text-primary);
}
.search__el::placeholder { color: var(--text-tertiary); }
/* Le halo général de mise au point suit la boîte de l'élément. Sur un champ
   transparent posé dans une pilule, cette boîte est un rectangle invisible :
   le halo en dessinait les angles au bord de la pilule, et on voyait un carré
   gris sortir du champ. C'est la pilule qui porte la mise au point, elle a la
   bonne forme. */
.search__el:focus-visible { box-shadow: none; }
.search__x {
  width: 24px; height: 24px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: var(--radius-pill);
  background: none;
  color: var(--text-tertiary);
  cursor: pointer;
  transition: var(--transition-control);
}
.search__x:hover { background: var(--black-5); color: var(--text-primary); }

/* Rognage : deux repères sur une règle. La partie gardée est encadrée, ce qui
   tombe reste gris de chaque côté. */
.trim { display: flex; flex-direction: column; gap: 10px; }
.trim__top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.trim__t {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: var(--mono-caption-size);
  letter-spacing: var(--mono-caption-ls);
  color: var(--text-secondary);
  white-space: nowrap;
}
.trim__k { color: var(--text-tertiary); }
.trim__track {
  position: relative;
  height: 30px;
  margin: 2px 13px;
  border-radius: 5px;
  background: var(--black-5);
  touch-action: none;
}
/* Le relief sonore, par-dessus le fond et sous les poignées : on voit où la
   personne parle, donc où couper. Sans événements de pointeur, sinon les traits
   intercepteraient la prise en main juste au-dessus d'eux. */
.trim__on {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  /* Repartis sur toute la piste, pas tasses a gauche. Chaque trait est borne a
     trois pixels de large : sans repartition, les quatre-vingt-seize occupaient
     le premier tiers et le relief ne tombait plus en face du moment qu'il
     decrit, ce qui est exactement ce qu'on lui demande. */
  justify-content: space-between;
  gap: 1px;
  padding: 0 4px;
  overflow: hidden;
  pointer-events: none;
}
.trim__on i {
  flex: 1 1 0;
  min-width: 1px;
  max-width: 3px;
  border-radius: 1px;
  display: block;
  background: var(--black-30);
}
/* Le passage gardé fonce, ce qui tombe reste pâle : la coupe se lit sur le son
   lui-même et pas seulement sur le fond. */
.trim__on i.is-in { background: var(--black-70); }

/* La tête de lecture, comme dans un logiciel de montage : on voit où l'on en
   est, et on l'attrape pour aller ailleurs. Rouge, seule couleur de tout le
   back-office à ne pas sortir de la palette pour une raison de goût : c'est la
   convention de tous les outils de montage, s'en écarter ferait chercher. */
.trim__tete {
  position: absolute;
  top: -5px;
  bottom: -5px;
  z-index: 4;
  width: 15px;
  margin-left: -7.5px;
  padding: 0;
  border: 0;
  background: none;
  cursor: ew-resize;
  touch-action: none;
}
.trim__tete i {
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 2px;
  margin-left: -1px;
  border-radius: 1px;
  background: #e5484d;
  display: block;
}
.trim__tete i::after {
  content: "";
  position: absolute;
  left: 50%;
  top: -3px;
  width: 8px;
  height: 8px;
  margin-left: -4px;
  border-radius: var(--radius-pill);
  background: #e5484d;
}
.trim__tete:focus-visible { outline: none; }
.trim__tete:focus-visible i { box-shadow: 0 0 0 3px rgba(229, 72, 77, .28); }

/* La partie gardée est claire et encadrée, ce qui tombe reste dans le gris de
   la piste : on voit ce qu'on garde, pas seulement où sont les repères. */
.trim__sel {
  position: absolute;
  top: -2px;
  bottom: -2px;
  border: 2px solid var(--black-100);
  border-radius: 7px;
  background: var(--white);
  pointer-events: none;
}
.trim__h {
  position: absolute;
  top: -2px;
  bottom: -2px;
  /* Au-dessus du relief sonore : c'est la poignee qu'on attrape, pas un trait. */
  z-index: 3;
  width: 26px;
  margin-left: -13px;
  padding: 0;
  border: none;
  background: none;
  cursor: ew-resize;
  touch-action: none;
}
.trim__h i {
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 12px;
  margin-left: -6px;
  border-radius: 4px;
  background: var(--black-100);
}
/* La strie dit que ça se saisit, comme la poignée d'une fenêtre. */
.trim__h i::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 2px;
  height: 12px;
  margin: -6px 0 0 -1px;
  border-radius: 1px;
  background: rgba(255, 255, 255, .7);
}
/* Même raison que pour les poignées de surlignage : la zone de préhension est
   transparente, seul le repère se voit, c'est donc lui qui porte le halo. */
.trim__h:focus-visible i { box-shadow: var(--ring-focus); }
.trim__h:focus-visible { outline: none; box-shadow: none; }
.trim.is-drag { cursor: ew-resize; }
.trim__acts { display: flex; gap: 8px; flex-wrap: wrap; }
/* Sur l'écran de détail, la règle vit seule sous le lecteur : elle prend un
   cadre pour ne pas flotter au milieu de la colonne. */
.dtrim {
  padding: 14px 16px 15px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-md);
  background: var(--white);
}

/* Suppression armée : le rouge plein dit que le prochain clic exécute. */
.menu__item.is-armed { background: var(--status-negative); color: var(--white); }
.menu__item.is-armed:hover { background: var(--status-negative); }
.menu__item.is-armed svg { stroke: var(--white) !important; }
.menu__warn {
  padding: 9px 12px 10px;
  border-top: 1px solid var(--border-hairline);
  font-size: var(--body-xs-size);
  line-height: 1.45;
  color: var(--text-tertiary);
  white-space: normal;
}

/* Publication d'un avis, depuis la liste des réponses et depuis son détail */
/* Publier ou non : un interrupteur, pas une pastille.

   Il y avait ici deux gélules côte à côte, de même forme et de même vert :
   l'une disait un état, « Publiable », l'autre était un bouton, « Sur le mur ».
   Rien ne les distinguait, et la première ne servait à rien puisque presque
   toutes les réponses le sont. Un interrupteur se reconnaît sans légende, se
   lit en colonne du haut de la liste au bas, et ne peut pas être confondu avec
   une information.

   Il s'allume en encre et non en vert : l'encre est la couleur des actions
   dans cette application, et le vert, gardé pour les états, revenait à peindre
   la moitié de l'écran de la couleur du succès. */
.pubcell { flex: none; display: flex; align-items: center; }
.pubsw {
  position: relative;
  flex: none;
  width: 36px; height: 21px;
  padding: 0;
  border: 1px solid var(--black-10);
  border-radius: var(--radius-pill);
  background: var(--black-5);
  cursor: pointer;
  transition: background 140ms ease, border-color 140ms ease;
}
.pubsw::after {
  content: '';
  position: absolute; top: 2px; left: 2px;
  width: 15px; height: 15px;
  border-radius: 50%;
  background: var(--white);
  box-shadow: 0 1px 2px rgba(26, 26, 26, .25);
  transition: transform 160ms cubic-bezier(.2, .7, .3, 1);
}
.pubsw:hover { border-color: var(--black-30); }
.pubsw.is-on { background: var(--action-primary-bg); border-color: var(--action-primary-bg); }
.pubsw.is-on:hover { background: var(--action-primary-bg-hover); border-color: var(--action-primary-bg-hover); }
.pubsw.is-on::after { transform: translateX(15px); }

/* Réponse gardée privée : l'interrupteur n'a pas lieu d'être, le choix
   n'appartient pas à celui qui regarde. On dit lequel, et on s'arrête là. */
.publab {
  font-family: var(--font-mono);
  font-size: var(--mono-caption-size);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  white-space: nowrap;
}

/* Un seul intitulé pour toute la colonne, plutôt qu'un mot par ligne. Le
   décalage de droite reproduit celui du chevron et de son écart, pour que le
   titre finisse exactement au bord de l'interrupteur qu'il annonce. */
.rrows__head {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: 0 34px 9px 0;
  border-bottom: 1px solid var(--border-hairline);
  font-family: var(--font-mono);
  font-size: var(--mono-caption-size);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

/* L'image à partager, dans le détail d'une réponse. Elle apparaît sous les
   actions, à l'endroit exact où on vient de la demander, plutôt que dans une
   fenêtre par-dessus : rien ici ne mérite d'interrompre la lecture. */
.partage {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 16px 18px 18px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-lg);
  background: var(--surface-card);
}
.partage__top { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.partage__body { display: flex; align-items: flex-start; gap: 18px; flex-wrap: wrap; }
/* L'aperçu porte le damier du fond : l'image est carrée et claire, sans lui son
   bord se confondrait avec la carte qui la contient. */
.partage__img {
  flex: none;
  width: 208px;
  height: 208px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-hairline);
  background: var(--surface-subtle);
  object-fit: contain;
}
.partage__col { flex: 1 1 260px; min-width: 0; display: flex; flex-direction: column; gap: 12px; }
.partage__txt {
  width: 100%;
  min-height: 118px;
  padding: 11px 13px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-md);
  background: var(--surface-page);
  font-family: var(--font-sans);
  font-size: var(--body-sm-size);
  line-height: 1.5;
  color: var(--text-primary);
  resize: vertical;
}
.partage__txt:focus { outline: none; border-color: var(--border-strong); }

/* Décision de publication, dans le détail d'une réponse. Une ligne posée sur
   un filet, pas un encadré vert : c'est une décision courante, elle n'a pas à
   se signaler comme une alerte au milieu de la page. */
.murpick {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 14px 2px 0;
  border-top: 1px dashed var(--black-10);
}
.murpick__ic {
  width: 30px; height: 30px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
  background: var(--surface-subtle);
  color: var(--text-tertiary);
}
/* Publié : la pastille passe en encre, comme l'interrupteur qui l'a décidé.
   Elle virait au vert vif juste à côté de lui, et deux façons de dire le même
   état sur la même ligne se lisent comme deux états. */
.murpick.is-on .murpick__ic { background: var(--surface-inverse); color: var(--text-inverse); }
.murpick__t { flex: 1; min-width: 180px; display: flex; flex-direction: column; gap: 2px; }
.murpick__l { font-size: var(--body-sm-size); font-weight: 500; }

/* Surlignage à deux poignées, dans l'onglet Avis du mur.

   Le texte est écrit une seule fois et ne bouge plus jamais ; la bande jaune et
   les deux poignées sont posées par-dessus, en absolu, aux coordonnées relevées
   sur chaque caractère. Tant que la mise en page ne bouge pas sous le doigt, la
   lettre visée reste où on la vise. */
.mk {
  padding: 13px 14px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-sm);
  background: var(--white);
  font-size: var(--body-sm-size);
  /* Large, pour que les pastilles de préhension dépassent du texte sans mordre
     sur la ligne voisine. */
  line-height: 2.15;
  color: var(--text-primary);
  /* La sélection du texte gênerait le glissement : c'est la poignée qu'on
     attrape, pas les mots. */
  user-select: none;
  -webkit-user-select: none;
  touch-action: none;
}
.mk__pane { position: relative; display: block; }
.mk__txt {
  position: relative;
  z-index: 1;
  display: block;
  white-space: pre-wrap;
  overflow-wrap: break-word;
}
.mk__bands { position: absolute; inset: 0; z-index: 0; display: block; pointer-events: none; }
.mk__bands i {
  position: absolute;
  border-radius: 3px;
  /* Le jaune du mur, à l'identique : l'aperçu montre ce que verront les
     visiteurs, il ne l'évoque pas. */
  background: rgba(255, 214, 102, .55);
}

/* Deux plages sur le même écran, deux gestes différents : ici on décide de ce
   qu'on garde, plus bas de ce qui ressort. Elles ne peuvent pas se ressembler,
   sinon on ne sait plus laquelle on tire.

   L'encadrement du passage repris prend donc le fond du surligneur maison, celui
   de la sélection du navigateur, et des poignées sombres. Aucune couleur
   nouvelle : la palette du back-office reste fermée, le jaune du surlignage est
   emprunté au mur et n'appartient qu'à lui. */
.mk--cite { line-height: 2.05; }
.mk--cite .mk__bands i { background: var(--highlight); }
/* Encre pleine, jamais un gris transparent. La pastille était posée à 70 %
   d'opacité : on voyait le trait au travers, et le rond avait l'air percé. Le
   relief au survol vient de l'agrandissement, qui lui reste. */
.mk--cite .mk__h i,
.mk--cite .mk__h i::after,
.mk--cite .mk__h:hover i,
.mk--cite .mk__h:hover i::after,
.mk--cite .mk__h:focus-visible i,
.mk--cite .mk__h:focus-visible i::after,
.mk--cite.is-drag .mk__h i { background: var(--black-100); }
.mk--cite .mk__h:focus-visible i { box-shadow: 0 0 0 3px var(--black-10); }
.mk--off { color: var(--text-secondary); line-height: 1.6; user-select: text; -webkit-user-select: text; }

/* Le trait marque la borne, la pastille dit qu'on peut tirer. La zone de
   préhension est bien plus large que le trait : viser un trait de deux pixels
   à la souris est un exercice, pas une commande. */
.mk__h {
  position: absolute;
  z-index: 2;
  width: 26px;
  margin-left: -13px;
  padding: 0;
  border: none;
  background: none;
  cursor: ew-resize;
  touch-action: none;
}
.mk__h i {
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 2.5px;
  margin-left: -1.25px;
  border-radius: 2px;
  background: #e8a300;
  transition: background 120ms var(--ease-out);
}
.mk__h i::after {
  content: "";
  position: absolute;
  left: 50%;
  width: 13px;
  height: 13px;
  margin-left: -6.5px;
  border-radius: var(--radius-pill);
  background: #e8a300;
  /* Un liseré de la couleur du fond plutôt qu'une ombre portée. L'ombre était
     peinte au-dessus du trait, qu'elle salissait d'une bavure grise juste sous
     la pastille : on croyait voir le trait passer par-dessus le rond. Le liseré
     détache la pastille du trait, franchement, et la pose proprement sur le
     texte par la même occasion. */
  box-shadow: 0 0 0 2px var(--white);
  transition: transform 120ms var(--ease-out), background 120ms var(--ease-out);
}
/* Pastille en haut pour le début, en bas pour la fin : les deux poignées ne se
   confondent pas, même collées l'une à l'autre sur un mot unique. */
.mk__h--a i::after { top: -6px; }
.mk__h--b i::after { bottom: -6px; }
.mk__h:hover i,
.mk__h:focus-visible i,
.mk.is-drag .mk__h i { background: #c98a00; }
.mk__h:hover i::after,
.mk__h:focus-visible i::after { background: #c98a00; transform: scale(1.18); }
/* La poignée est une zone de préhension transparente, bien plus large que son
   trait : le halo général en dessinait le contour, un rectangle gris planté au
   milieu de la phrase. La mise au point se voit sur le trait, qui lui existe. */
.mk__h:focus-visible { outline: none; box-shadow: none; }
.mk__h:focus-visible i { box-shadow: 0 0 0 3px rgba(232, 163, 0, .22); }
.mk.is-drag { cursor: ew-resize; }

/* ============================ Wall of Love ============================ */
/* Le mur est l'objet, pas le formulaire : il occupe la page, et c'est sur lui
   qu'on travaille. Les avis s'y prennent et s'y posent à la main, chaque carte
   porte ses commandes. Ne reste à droite que ce qui ne se manipule pas
   directement, couleurs et mise en page, dans un panneau qui se replie.

   Les classes du composant (wl__*) vivent dans l'iframe et ne peuvent donc pas
   rencontrer celles d'ici ; celles de la couche d'édition (me__*) non plus. */

.murpage { display: flex; flex-direction: column; }
.murpage .page-head { margin-bottom: 20px; }

/* La scène prend toute la largeur. Les réglages sont au-dessus, dans un bandeau
   qui se déplie ; ils occupaient une colonne de 330 px à droite, et cette
   colonne se payait en zoom, l'aperçu étant réduit à la largeur disponible. */
.murstage { width: 100%; min-width: 0; display: flex; flex-direction: column; gap: 12px; }

/* ------------------------------- La barre ------------------------------- */

.murbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.murbar__l { display: flex; align-items: center; gap: 6px; min-width: 0; }
.murbar__r { display: flex; align-items: center; gap: 10px; flex: none; }
.edsegs--tight .edseg { flex: none; padding: 7px 12px; }

/* Deux interrupteurs de même forme, parce qu'ils font la même chose : ils
   changent ce qu'on regarde, pas ce qu'on publie. */
.murpli {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 32px;
  padding: 0 13px 0 10px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-pill);
  background: var(--white);
  font-family: inherit;
  font-size: var(--body-sm-size);
  font-weight: 500;
  color: var(--text-secondary);
  cursor: pointer;
  transition: var(--transition-control);
}
.murpli .ico { flex: none; color: var(--text-tertiary); }
.murpli:hover { color: var(--text-primary); border-color: var(--black-30); }
.murpli.is-on {
  border-color: transparent;
  background: var(--surface-inverse);
  color: var(--text-inverse);
}
.murpli.is-on .ico { color: var(--text-inverse-secondary); }
/* Le chevron pointe vers le bas au repos, vers le haut une fois le bandeau
   ouvert : il dit d'où sort le panneau et où il retournera. */
.murpli__fl { display: flex; transition: transform var(--duration-base) var(--ease-out); }
.murpli.is-on .murpli__fl { transform: rotate(180deg); }

/* Facteur de réduction de l'aperçu. Il dit toujours quelque chose, y compris
   quand il n'y a pas de réduction : « 70 % » seul laisserait croire, à
   l'échelle 1, que l'afficheur est cassé. */
.murbar__z {
  font-family: var(--font-mono);
  font-size: var(--mono-caption-size);
  color: var(--text-tertiary);
  white-space: nowrap;
}

/* Bandeau des avis d'exemple. Il n'existe que quand il sert : vide, il ne
   laisse pas de trou. */
.murnote:empty { display: none; }
.murnote__in {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 13px;
  border: 1px dashed var(--black-30);
  border-radius: var(--radius-sm);
  background: var(--highlight-50);
  font-size: var(--body-xs-size);
  color: var(--text-secondary);
}
.murnote__in .ico { flex: none; color: var(--text-tertiary); }
.murnote__in span { flex: 1; min-width: 0; }

/* ------------------------------- Le cadre ------------------------------- */

/* Le damier discret dit que ce fond n'appartient pas au composant : c'est la
   page du client qui prendra sa place.

   Largeur et hauteur sont posées par wallpage.js, qui rend la scène à sa
   largeur de référence puis la réduit pour tenir ici. Le cadre est donc
   toujours centré, en bureau comme en mobile. */
.murview {
  align-self: center;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-lg);
  background: var(--surface-subtle);
  background-image: var(--pattern-dot);
  background-size: var(--pattern-dot-size);
  overflow: hidden;
}
/* La scène porte la largeur d'un vrai site, l'échelle la ramène à la place
   disponible. L'origine en haut à gauche, sinon la réduction se ferait autour
   du centre et sortirait du cadre par le haut.

   Ni le cadre ni la scène ne s'animent, et c'est voulu. Le cadre doit être à
   tout instant la scène multipliée par l'échelle : animés, ils ne suivaient pas
   la même horloge, une colonne d'avis restait coupée au bord le temps du repli
   du panneau, et surtout un avis lâché pendant ce temps-là tombait à côté,
   puisque la place visée est déduite de cette échelle. */
.murscene { transform-origin: top left; }
.murframe {
  display: block;
  width: 100%;
  border: 0;
  min-height: 240px;
  background: transparent;
}

/* ------------------------------ La réserve ------------------------------ */

/* Les avis publiables qui ne sont pas encore sur le mur, posés juste dessous.
   C'est le seul endroit d'où un avis entre, et il est à portée de main de
   l'endroit où il va. */
.murres {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px 16px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-lg);
  background: var(--white);
}
.murres__h { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.murres__t {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  flex: none;
  font-size: var(--body-sm-size);
  font-weight: 600;
  color: var(--text-primary);
}
.murres__n {
  min-width: 20px;
  padding: 1px 6px;
  border-radius: var(--radius-pill);
  background: var(--surface-sunken);
  font-family: var(--font-mono);
  font-size: var(--mono-caption-size);
  color: var(--text-secondary);
  text-align: center;
}
.murres__s { flex: 1; min-width: 0; font-size: var(--body-xs-size); color: var(--text-tertiary); }
.murres__p { flex: none; font-size: var(--body-xs-size); color: var(--text-tertiary); }
/* Trois rangs au plus, puis on fait défiler : une réserve de vingt avis
   repousserait l'aperçu hors de l'écran, alors que c'est lui qu'on regarde. */
.murres__l {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  max-height: 152px;
  overflow-y: auto;
}
.murres__vide {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: var(--body-xs-size);
  color: var(--text-tertiary);
}
.murres__vide .ico { flex: none; color: var(--status-positive); }

/* Un avis en réserve. Il se prend en main, d'où la poignée et le curseur ; le
   bouton à droite reste pour qui préfère ne pas glisser, et pour le clavier. */
.murchip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: 260px;
  padding: 6px 6px 6px 8px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-pill);
  background: var(--white);
  cursor: grab;
  -webkit-user-select: none;
  user-select: none;
  transition: var(--transition-control);
}
.murchip:hover { border-color: var(--black-30); box-shadow: var(--shadow-sm); }
.murchip.is-tire { opacity: .35; box-shadow: none; }
.murchip__ic {
  width: 26px; height: 26px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
  background: var(--surface-subtle);
  color: var(--text-secondary);
}
.murchip__t { min-width: 0; display: flex; flex-direction: column; gap: 0; }
.murchip__n {
  font-size: var(--body-sm-size);
  font-weight: 500;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.murchip__d {
  font-size: var(--body-xs-size);
  color: var(--text-tertiary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.murchip__add {
  width: 26px; height: 26px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: var(--radius-pill);
  background: none;
  color: var(--text-tertiary);
  cursor: pointer;
  transition: var(--transition-control);
}
.murchip__add:hover { background: var(--surface-inverse); color: var(--text-inverse); }

/* L'étiquette qui suit le curseur pendant le geste. Elle dit ce qu'on tient ;
   où ça tombera est montré par le mur lui-même, dans l'iframe. */
.murdrag {
  position: fixed;
  z-index: 90;
  padding: 7px 13px;
  border-radius: var(--radius-pill);
  background: var(--surface-inverse);
  color: var(--text-inverse);
  font-size: var(--body-sm-size);
  font-weight: 500;
  white-space: nowrap;
  pointer-events: none;
  transform: translate(-50%, -160%);
  box-shadow: var(--shadow-md);
}
/* Pendant le geste, l'iframe ne prend plus la souris : le pointeur doit rester
   à ce document, qui seul sait ce qu'il transporte. */
body.is-murdrag { cursor: grabbing; user-select: none; }
body.is-murdrag .murframe { pointer-events: none; }

/* ------------------------------ Le bandeau ------------------------------ */

/* Il se déplie sous la barre, sur toute la largeur.

   Le dépliement passe par une grille à une seule rangée qu'on fait passer de
   0fr à 1fr : c'est la seule façon d'animer vers la hauteur du contenu sans
   l'avoir mesurée, et sans max-height arbitraire qui saccade ou qui rogne. La
   largeur ne bouge pas, l'aperçu n'est donc jamais remis à l'échelle pendant le
   mouvement, et le glissement d'une carte ne peut pas se retrouver décalé. */
.murpan {
  display: grid;
  grid-template-rows: 1fr;
  transition: grid-template-rows var(--duration-base) var(--ease-out),
              opacity var(--duration-base) var(--ease-out);
}
.murpan.is-plie { grid-template-rows: 0fr; opacity: 0; pointer-events: none; }
/* La rangée doit pouvoir descendre sous sa hauteur naturelle, sinon 0fr ne
   ferme rien. */
.murpan > * { min-height: 0; overflow: hidden; }
@media (prefers-reduced-motion: reduce) { .murpan { transition: none; } }

.murpan__in {
  display: flex;
  align-items: stretch;
  gap: clamp(15px, 1.7vw, 24px);
  padding: 17px clamp(16px, 1.6vw, 22px);
  background: var(--white);
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-lg);
  /* Replié, la marge du bas partirait avec : elle est portée par le contenu et
     non par le conteneur, pour que la barre et l'aperçu se recollent. */
  margin-bottom: 2px;
}

/* Quatre groupes côte à côte, séparés par un filet plutôt que par un cadre :
   ils appartiennent au même bandeau, ce ne sont pas quatre encarts. Le premier
   est plus large que les autres, il porte deux champs de texte, et un champ de
   texte a besoin de place là où trois boutons n'en ont pas. */
.murblc {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
/* Les quatre parts ne sont pas égales, et pas au jugé : elles sont taillées sur
   le plus large de ce que chaque groupe doit montrer sans se replier. « La mise
   en page » porte « Système Moderne Classique » sur une ligne, c'est elle qui
   demande le plus ; « Ce qui s'affiche » n'a que deux rangées de cases, et lui
   donner la même part laissait un vide à droite du bandeau.

   Découpées à parts égales, la troisième rognait « Classique » de deux pixels.
   Deux pixels sur un mot, c'est un mot abîmé. */
.murblc:nth-child(1) { flex: 1.05 1 0; }
.murblc:nth-child(3) { flex: 1.1 1 0; }
.murblc:nth-child(4) { flex: .9 1 0; }
.murblc + .murblc { padding-left: clamp(15px, 1.7vw, 24px); border-left: 1px solid var(--border-hairline); }
.murblc__t {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--body-sm-size);
  font-weight: 600;
  letter-spacing: -.008em;
  color: var(--text-primary);
}
.murblc__c { display: flex; flex-direction: column; gap: 11px; }
/* Serrés d'un cran par rapport au reste du produit : couchés, ces champs sont
   quatre fois plus nombreux à l'écran qu'ils ne l'étaient dans la colonne. */
.murpan .edfield { gap: 6px; }
.murpan .edseg { padding: 6px 4px; font-size: 12.5px; }
.murpan .swatch { width: 24px; height: 24px; }
.murpan .swatches { gap: 6px; }
.murpan .murcol { gap: 8px; }

/* Un intitulé qui en sait plus qu'il n'en dit : le filet pointillé signale qu'il
   y a quelque chose à survoler, comme dans la carte du récapitulatif. */
.edaide { border-bottom: 1px dotted var(--black-30); cursor: help; }

/* Interrupteur : une case à cocher qui se lit de loin, sans dépendre du rendu
   natif de la case du système.

   Deux par deux dans le bandeau : empilés, quatre interrupteurs faisaient de ce
   groupe le plus haut des quatre, alors que c'est le plus simple. */
/* auto-fit plutôt que deux colonnes déclarées : si la place manque vraiment, la
   grille retombe sur une colonne au lieu de rogner les mots. */
.murtogs { display: grid; grid-template-columns: repeat(auto-fit, minmax(76px, 1fr)); gap: 2px 4px; }
.murpan .murtog { padding: 7px 5px 7px 4px; gap: 8px; }
.murtog {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 8px 8px 6px;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  font-family: inherit;
  font-size: var(--body-sm-size);
  color: var(--text-secondary);
  text-align: left;
  cursor: pointer;
  transition: var(--transition-control);
}
.murtog:hover { background: var(--black-5); }
.murtog__box {
  width: 19px; height: 19px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1.5px solid var(--black-30);
  border-radius: 6px;
  background: var(--white);
  color: var(--text-inverse);
  transition: var(--transition-control);
}
.murtog.is-on { color: var(--text-primary); }
.murtog.is-on .murtog__box { background: var(--black-100); border-color: var(--black-100); }
.murtog__l { flex: 1; min-width: 0; }
.murtog__l .hint { display: block; margin-top: 1px; }

.murcol { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* Le choix par defaut d'une etude : la couleur du mur, montree et nommee. Il a
   la forme du bouton « Autre » qui le suit, parce que ce sont deux fois la meme
   chose, un choix qui porte sa couleur avec lui. Coche, il prend l'encre : c'est
   l'etat courant de presque toutes les etudes, il doit se lire de loin. */
.etacc__mur {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 28px;
  padding: 0 12px 0 6px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-pill);
  background: none;
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
  cursor: pointer;
  transition: var(--transition-control);
}
.etacc__mur:hover { background: var(--black-5); color: var(--text-primary); }
.etacc__mur.is-on {
  border-color: var(--surface-inverse);
  background: var(--surface-inverse);
  color: var(--text-inverse);
}
.etacc__mur.is-on .murcol__dot { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .28); }

/* Couleur libre. Une pastille de plus se lirait comme un septième choix figé :
   c'est une pastille suivie d'un mot, pour dire qu'elle ouvre la palette du
   système. Le champ natif couvre l'étiquette, invisible mais cliquable. */
.murcol__pick {
  position: relative;
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 28px;
  padding: 0 12px 0 6px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-pill);
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
  cursor: pointer;
  overflow: hidden;
  transition: var(--transition-control);
}
.murcol__pick:hover { background: var(--black-5); color: var(--text-primary); }
.murcol__dot {
  width: 18px; height: 18px;
  flex: none;
  border-radius: var(--radius-pill);
  box-shadow: inset 0 0 0 1px rgba(26, 26, 26, .12);
}
.murcol__pick input {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  padding: 0;
  border: none;
  background: none;
  opacity: 0;
  cursor: pointer;
}

/* ------------------------------ Les feuilles ------------------------------ */

/* Le code d'intégration et la retouche d'un avis. Deux choses qu'on ouvre, qu'on
   règle et qu'on referme : elles n'avaient pas à occuper une colonne en
   permanence, ni un onglet qui cachait le reste. */
.mursh {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.mursh[hidden] { display: none; }
.mursh__sc {
  position: absolute;
  inset: 0;
  background: rgba(26, 26, 26, .32);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}
.mursh__bx {
  position: relative;
  width: min(540px, 100%);
  max-height: 88vh;
  display: flex;
  flex-direction: column;
  border-radius: var(--radius-lg);
  background: var(--white);
  box-shadow: var(--shadow-float);
  overflow: hidden;
}
.mursh__hd {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 18px 20px 14px;
  border-bottom: 1px solid var(--border-hairline);
}
.mursh__t {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--h3-size);
  font-weight: 600;
  letter-spacing: -.015em;
  color: var(--text-primary);
}
.mursh__x {
  width: 30px; height: 30px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: var(--radius-pill);
  background: none;
  color: var(--text-tertiary);
  cursor: pointer;
  transition: var(--transition-control);
}
.mursh__x:hover { background: var(--black-5); color: var(--text-primary); }
.mursh__bd {
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: 18px 20px 20px;
  overflow: auto;
}
.mursh__p {
  margin: 0;
  font-size: var(--body-sm-size);
  line-height: 1.55;
  color: var(--text-secondary);
}
.mursh__tog { padding-top: 4px; border-top: 1px dashed var(--black-10); }
.mursh__ft {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  padding: 14px 20px;
  border-top: 1px solid var(--border-hairline);
  background: var(--surface-page);
}
.mursh__ft .linkbtn { margin-right: auto; }
.mursh__bd .edta { min-height: 84px; }

/* Bloc de code à copier */
.murcode { display: flex; flex-direction: column; gap: 10px; }
.murcode pre {
  margin: 0;
  padding: 12px 13px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-sm);
  background: var(--surface-subtle);
  overflow-x: auto;
}
.murcode code {
  font-family: var(--font-mono);
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--text-secondary);
  white-space: pre;
}

/* Sous 1100 px, les quatre groupes du bandeau ne tiennent plus sur une ligne :
   ils passent sur deux, deux par deux. Le filet vertical disparaît, il ne
   séparerait plus que la moitié d'une rangée ; c'est l'écart qui sépare. */
@media (max-width: 1099px) {
  .murpan__in { flex-wrap: wrap; row-gap: 22px; }
  .murblc, .murblc:nth-child(1), .murblc:nth-child(3), .murblc:nth-child(4) {
    flex: 1 1 calc(50% - 24px);
  }
  .murblc + .murblc { padding-left: 0; border-left: none; }
}

/* Sous 760 px, un groupe par ligne. Deux boutons de segment côte à côte dans une
   demi-largeur de téléphone deviennent illisibles. */
@media (max-width: 759px) {
  .murpan__in { flex-direction: column; gap: 20px; }
  .murblc, .murblc:nth-child(1), .murblc:nth-child(3), .murblc:nth-child(4) { flex: 1 1 auto; }
  .murblc + .murblc { padding-top: 20px; border-top: 1px solid var(--border-hairline); }
}

/* --------------------------------- Connexion ---------------------------------
   Les données ne sont plus dans ce navigateur : il faut dire qui on est avant de
   voir quoi que ce soit. L'écran retire la coque, sinon une barre latérale vide
   resterait à gauche d'un formulaire, comme une application à moitié chargée. */
body.is-out .shell { display: block; }
body.is-out .side { display: none; }
body.is-out .main { margin: 0; }
/* La gouttière de l'application n'a rien à faire ici : posée sous un écran déjà
   haut de toute la fenêtre, elle ajoutait 88 px de vide en bas. Sur un portable
   la page se mettait à défiler et le formulaire n'était plus au centre. */
body.is-out .main-inner { padding: 0; }

.log {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.log__card {
  width: 100%;
  max-width: 348px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.log__mark { margin-bottom: 2px; }
.log__t {
  margin: 0;
  font-family: var(--font-display);
  font-size: 27px;
  font-weight: 500;
  letter-spacing: -.02em;
  color: var(--text-primary);
}
.log__s {
  margin: -10px 0 2px;
  font-size: 14px;
  line-height: 1.5;
  color: var(--text-secondary);
}
.log__s b { font-weight: 600; color: var(--text-primary); }
.log__f { display: flex; flex-direction: column; gap: 8px; }
.log__err {
  font-size: 13px;
  line-height: 1.45;
  color: var(--status-negative);
}
.log__ok { margin: 0; font-size: 13px; line-height: 1.45; color: var(--status-positive); }

/* Une ligne d'appoint sous les champs, alignée à droite : « Mot de passe
   oublié ? » se cherche au bout de la case du mot de passe, pas au-dessus. */
.log__ligne { display: flex; justify-content: flex-end; margin: -4px 0 2px; }

/* Le chemin vers l'autre écran. Un lien et non un bouton : le geste principal
   de la carte est déjà un bouton plein, et deux boutons de même poids ne
   diraient plus lequel on attend. */
.log__p {
  margin: 4px 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-tertiary);
  text-align: center;
}
.log__lien {
  padding: 0;
  border: none;
  border-bottom: 1px solid var(--black-30);
  border-radius: 0;
  background: none;
  font: inherit;
  color: var(--text-primary);
  font-weight: 500;
  cursor: pointer;
  transition: var(--transition-control);
}
.log__lien:hover { border-bottom-color: var(--text-primary); }

/* La règle du mot de passe est là avant qu'on la casse, pas après : elle ne
   passe à l'encre que si ce qui est tapé est trop court, et le reste du temps
   elle informe sans reprocher. */
.log__aide {
  margin: -2px 0 0;
  font-size: var(--body-xs-size);
  color: var(--text-tertiary);
  transition: var(--transition-control);
}
.log__aide.is-court { color: var(--status-negative); }

/* L'œil est posé dans le champ, pas à côté : à côté, il volerait la largeur du
   champ et se lirait comme un second geste. */
.log__mdp { position: relative; display: flex; }
.log__mdp .field { flex: 1; min-width: 0; }
.log__mdp .field__el { padding-right: 42px; }
.log__oeil {
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  width: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text-tertiary);
  cursor: pointer;
  transition: var(--transition-control);
}
.log__oeil:hover { color: var(--text-primary); }

/* ------------------------------- Utilisateurs -------------------------------
   La coulisse. Elle emprunte tout à ce qui existe déjà, cadre, filets, mono des
   en-têtes, pastilles d'état : c'est le même produit vu de derrière, pas un
   outil à part, et lui inventer une allure lui donnerait plus d'importance
   qu'il n'en a. */

/* Quatre chiffres avant la liste. Le premier dit combien de personnes, les
   trois suivants disent combien sont allées jusqu'au bout : confirmer, créer un
   lien, recevoir un avis. C'est l'entonnoir, et il se lit de gauche à droite. */
.ubil {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  margin-bottom: 18px;
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-lg);
  background: var(--surface-card);
  overflow: hidden;
}
.ubil__c {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 15px 18px;
  border-left: 1px solid var(--border-hairline);
}
.ubil__c:first-child { border-left: none; }
.ubil__v {
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 500;
  letter-spacing: -.02em;
  color: var(--text-primary);
  line-height: 1.1;
}
.ubil__l { font-size: var(--body-xs-size); color: var(--text-tertiary); }

.utab {
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-lg);
  background: var(--surface-card);
  overflow: hidden;
}
.urow {
  display: grid;
  /* Les proportions sont réglées sur les deux intitulés les plus longs, « dont
     3 au mur » et « Dernière visite » : sous ces largeurs-là, l'un passe à la
     ligne et la rangée d'en-tête devient plus haute que les autres. */
  grid-template-columns:
    minmax(0, 2.4fr) minmax(92px, 1fr) minmax(96px, 1fr)
    minmax(52px, .55fr) minmax(96px, 1fr) minmax(104px, 1.25fr);
  align-items: center;
  gap: 16px;
  padding: 12px 18px;
  border-top: 1px solid var(--border-hairline);
  font-size: 13.5px;
  color: var(--text-secondary);
}
.urow:first-child { border-top: none; }
.urow--head {
  padding: 10px 18px;
  background: var(--surface-subtle);
  font-family: var(--font-mono);
  font-size: var(--mono-caption-size);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}
.urow:not(.urow--head):hover { background: var(--black-5); }

.ucell { min-width: 0; }
.ucell--qui { display: flex; flex-direction: column; gap: 2px; }
.ucell__nom {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  font-weight: 500;
  color: var(--text-primary);
  overflow-wrap: anywhere;
}
.ucell__mail {
  font-size: 12.5px;
  color: var(--text-tertiary);
  overflow-wrap: anywhere;
}
/* Les compteurs sont en chiffres tabulaires : une colonne de nombres qui ne
   s'aligne pas se recompte à la main. */
.ucell--n { display: flex; align-items: baseline; gap: 7px; }
.ucell__n {
  font-family: var(--font-mono);
  font-size: 14px;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
/* Un zéro reste lisible mais s'efface : dans une colonne, ce sont les comptes
   qui ont bougé qu'on cherche. */
.ucell__n.is-zero { color: var(--text-disabled); }
.ucell__s { font-size: var(--body-xs-size); color: var(--text-tertiary); }
.ucell--vu { color: var(--text-tertiary); }

/* Sous 1000 px, la grille tombe et chaque compte devient une fiche. Six colonnes
   dans une fenêtre étroite ne se rétrécissent pas, elles se chevauchent : les
   intitulés reviennent alors devant chaque valeur, tirés de data-t. */
@media (max-width: 999px) {
  .ubil { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ubil__c:nth-child(3) { border-left: none; }
  .ubil__c:nth-child(n+3) { border-top: 1px solid var(--border-hairline); }

  .urow {
    display: block;
    padding: 15px 16px;
  }
  /* Après « .urow », et non avant : les deux sélecteurs pèsent le même poids,
     et l'en-tête est aussi une rangée. Écrit au-dessus, son « display: none »
     se faisait effacer par le « display: block » qui suit. */
  .urow--head { display: none; }
  .urow .ucell + .ucell { margin-top: 7px; }
  .urow .ucell:not(.ucell--qui) {
    display: flex;
    align-items: baseline;
    gap: 10px;
  }
  .urow .ucell:not(.ucell--qui)::before {
    content: attr(data-t);
    flex: none;
    /* Assez large pour « Dernière visite » d'un seul tenant : un intitulé sur
       deux lignes en face d'une valeur sur une seule décale tout le rang. */
    width: 132px;
    font-family: var(--font-mono);
    font-size: var(--mono-caption-size);
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--text-tertiary);
  }
}
