/* ==========================================================================
   Meet — feuille de style unique (mobile first, sans framework, sans CDN)
   Rédigée à la main. Ordre : jetons > socle > mise en page > composants >
   écrans > utilitaires > tablette > préférences système.
   Référence : docs/DESIGN.md — toute nouvelle classe s'y documente.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Jetons — thème CLAIR (valeurs par défaut)
   Contrastes vérifiés : texte 4.5:1 mini, éléments d'interface 3:1 mini.
   -------------------------------------------------------------------------- */
:root {
  /* Fonds et texte */
  --bg: #f5f6f8;            /* fond de page */
  --surface: #ffffff;       /* cartes, barres */
  --surface-2: #eef0f4;     /* champs, puces, zones creuses */
  --text: #14161a;          /* 18.1:1 sur --surface */
  --text-soft: #5a626e;     /* 6.2:1 sur --surface */

  /* Traits : --border décore, --line délimite un élément interactif (3:1) */
  --border: #e2e5ea;
  --line: #7e8695;

  /* Accent */
  --accent: #4a52c8;        /* 6.3:1 sur --surface */
  --accent-strong: #383fa8; /* survol / pression */
  --accent-soft: #ecedfb;
  --accent-on-soft: #343aa0;
  --on-accent: #ffffff;

  /* Note */
  --star: #a97400;          /* 4.0:1 sur --surface */
  --star-off: #7e8695;      /* 3.7:1 — l'étoile vide reste perceptible */

  /* Favori */
  --fav: #d6336c;
  --fav-soft: #fdeaf1;
  --fav-on-soft: #a81b4c;

  /* Danger */
  --danger: #c0392b;
  --danger-soft: #fbeae8;
  --danger-on-soft: #a02c20;

  /* Administration — accent DISTINCT de --accent : on ne doit jamais croire
     qu'on gère des comptes alors qu'on consulte son carnet (et l'inverse).
     Teal foncé : aucune parenté de teinte avec l'indigo de l'application. */
  --admin: #00696e;          /* 6.5:1 sur --surface */
  --admin-strong: #005258;
  --admin-soft: #e0f2f3;
  --admin-on-soft: #0b5a5e;  /* 6.9:1 sur --admin-soft */
  --on-admin: #ffffff;       /* 6.5:1 sur --admin */

  /* Statuts de suivi (cf. models.STATUSES) */
  --st-nouveau-bg: #e6f0fd;        --st-nouveau-fg: #17558c;
  --st-en-cours-bg: #e4f4ea;       --st-en-cours-fg: #1a6b41;
  --st-a-recontacter-bg: #fbf0da;  --st-a-recontacter-fg: #8a5a05;
  --st-archive-bg: #eceef1;        --st-archive-fg: #565e6a;

  /* Élévation */
  --shadow-1: 0 1px 2px rgba(16, 20, 30, .06), 0 2px 8px rgba(16, 20, 30, .05);
  --shadow-2: 0 6px 24px rgba(16, 20, 30, .12);
  --scrim: rgba(9, 11, 16, .82);

  /* Rayons */
  --r-xs: 8px;
  --r-sm: 10px;
  --r: 14px;
  --r-lg: 20px;
  --r-pill: 999px;

  /* Espacements (échelle 4) */
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px; --sp-4: 16px;
  --sp-5: 20px; --sp-6: 24px; --sp-8: 32px; --sp-10: 40px;

  /* Typographie — 16px de base : en dessous, iOS zoome sur les champs. */
  --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --fs-xs: .75rem;    /* 12 — méta discrète */
  --fs-sm: .8125rem;  /* 13 — puces, libellés */
  --fs-md: .875rem;   /* 14 — méta de carte */
  --fs-base: 1rem;    /* 16 — corps, champs */
  --fs-lg: 1.0625rem; /* 17 — titre de carte */
  --fs-xl: 1.25rem;   /* 20 — titre de section */
  --fs-2xl: 1.5rem;   /* 24 — titre d'écran */

  /* Cibles tactiles et gabarits */
  --tap: 44px;              /* jamais moins : pouce adulte */
  --page-max: 760px;
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
  --tabbar-h: 60px;         /* hauteur nue, hors encoche */

  /* Signalement « lapin » : oreilles noires de serre-tête, intérieur rose. */
  --lapin: #b0306a;          /* 5.9:1 sur --surface */
  --lapin-soft: #fbe8f1;
  --lapin-on-soft: #9a2a5d;
  --lapin-ear: #1d1b22;
  --lapin-inner: #f6a8c9;
  --lapin-edge: #ffffff;

  color-scheme: light;
}

/* --------------------------------------------------------------------------
   2. Jetons — thème SOMBRE
   Deux déclencheurs : préférence système (sauf clair forcé) et choix explicite.
   Les deux blocs partagent exactement les mêmes valeurs.
   -------------------------------------------------------------------------- */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #101216;
    --surface: #191c22;
    --surface-2: #232730;
    --text: #eceef2;
    --text-soft: #a3abb8;
    --border: #2a2f38;
    --line: #737b8a;

    --accent: #8f96f0;
    --accent-strong: #a9aef7;
    --accent-soft: #23253a;
    --accent-on-soft: #a9aef7;
    --on-accent: #101216;

    --star: #f0b429;
    --star-off: #737b8a;

    --fav: #ff8fb3;
    --fav-soft: #331a24;
    --fav-on-soft: #ff8fb3;

    --danger: #f28b7d;
    --danger-soft: #33201d;
    --danger-on-soft: #f28b7d;

    --admin: #6fd3e0;
    --admin-strong: #8fdfe9;
    --admin-soft: #12303a;
    --admin-on-soft: #7ad9e2;
    --on-admin: #101216;

    --st-nouveau-bg: #15263a;        --st-nouveau-fg: #82b8f0;
    --st-en-cours-bg: #152a1f;       --st-en-cours-fg: #74cd9b;
    --st-a-recontacter-bg: #2d2513;  --st-a-recontacter-fg: #e0b160;
    --st-archive-bg: #242830;        --st-archive-fg: #a3abb8;

    --shadow-1: 0 1px 2px rgba(0, 0, 0, .4), 0 2px 10px rgba(0, 0, 0, .3);
    --shadow-2: 0 8px 28px rgba(0, 0, 0, .5);
    --scrim: rgba(0, 0, 0, .88);

    --lapin: #f39ac2;
    --lapin-soft: #3a1b2a;
    --lapin-on-soft: #f6a8c9;
    --lapin-ear: #0c0b0f;
    --lapin-inner: #e98ab4;
    --lapin-edge: #d9d6e0;

    color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --bg: #101216;
  --surface: #191c22;
  --surface-2: #232730;
  --text: #eceef2;
  --text-soft: #a3abb8;
  --border: #2a2f38;
  --line: #737b8a;

  --accent: #8f96f0;
  --accent-strong: #a9aef7;
  --accent-soft: #23253a;
  --accent-on-soft: #a9aef7;
  --on-accent: #101216;

  --star: #f0b429;
  --star-off: #737b8a;

  --fav: #ff8fb3;
  --fav-soft: #331a24;
  --fav-on-soft: #ff8fb3;

  --danger: #f28b7d;
  --danger-soft: #33201d;
  --danger-on-soft: #f28b7d;

  --admin: #6fd3e0;
  --admin-strong: #8fdfe9;
  --admin-soft: #12303a;
  --admin-on-soft: #7ad9e2;
  --on-admin: #101216;

  --st-nouveau-bg: #15263a;        --st-nouveau-fg: #82b8f0;
  --st-en-cours-bg: #152a1f;       --st-en-cours-fg: #74cd9b;
  --st-a-recontacter-bg: #2d2513;  --st-a-recontacter-fg: #e0b160;
  --st-archive-bg: #242830;        --st-archive-fg: #a3abb8;

  --shadow-1: 0 1px 2px rgba(0, 0, 0, .4), 0 2px 10px rgba(0, 0, 0, .3);
  --shadow-2: 0 8px 28px rgba(0, 0, 0, .5);
  --scrim: rgba(0, 0, 0, .88);

  --lapin: #f39ac2;
  --lapin-soft: #3a1b2a;
  --lapin-on-soft: #f6a8c9;
  --lapin-ear: #0c0b0f;
  --lapin-inner: #e98ab4;
  --lapin-edge: #d9d6e0;

  color-scheme: dark;
}

/* --------------------------------------------------------------------------
   3. Socle
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  overflow-x: hidden;          /* filet anti-débordement horizontal */
  scroll-behavior: smooth;
}

body {
  margin: 0;
  min-height: 100dvh;
  font-family: var(--font);
  font-size: var(--fs-base);
  line-height: 1.5;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  overflow-wrap: break-word;
  /* Pas d'overflow-x ici : cela ferait de <body> un conteneur de défilement
     et casserait `position: sticky` de la barre supérieure. */
}

h1, h2, h3, h4 { margin: 0; line-height: 1.25; font-weight: 650; letter-spacing: -.01em; }
p { margin: 0; }
img, svg, video { display: block; max-width: 100%; }

/* Toutes les icônes sont dessinées au trait, jamais en aplat : un seul réglage
   ici les rend homogènes, et `currentColor` leur fait suivre la couleur du texte. */
.icon {
  /* Taille par défaut : un SVG sans width/height explicite retomberait sur
     300x150 px. Chaque composant la redéfinit, cette valeur n'est qu'un filet. */
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: none;
}
a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
ul, ol { margin: 0; padding: 0; list-style: none; }
hr { border: 0; border-top: 1px solid var(--border); margin: var(--sp-5) 0; }
summary { list-style: none; cursor: pointer; }
summary::-webkit-details-marker { display: none; }

/* Un seul style de focus dans toute l'application. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}
/* Pas de halo bleu natif sur mobile : on garde le nôtre. */
* { -webkit-tap-highlight-color: transparent; }

::selection { background: var(--accent-soft); color: var(--accent-on-soft); }

/* --------------------------------------------------------------------------
   4. Mise en page générale
   -------------------------------------------------------------------------- */
.app {
  width: 100%;
  max-width: var(--page-max);
  margin: 0 auto;
  padding-left: var(--safe-l);
  padding-right: var(--safe-r);
}

/* Toute page dotée de la barre basse réserve sa hauteur. */
.page {
  padding: var(--sp-4);
  padding-bottom: calc(var(--sp-10) + var(--tabbar-h) + var(--safe-b));
}
/* Écrans sans barre basse (édition, connexion) : la barre d'action prend le relais. */
.page--nonav { padding-bottom: calc(var(--sp-10) + 76px + var(--safe-b)); }
.page--center {
  min-height: 100dvh;
  display: grid;
  align-content: center;
  gap: var(--sp-5);
  padding: var(--sp-6) var(--sp-4) calc(var(--sp-10) + var(--safe-b));
}

.stack { display: grid; gap: var(--sp-4); }
.row { display: flex; align-items: center; gap: var(--sp-2); }
.row--between { justify-content: space-between; }

/* --------------------------------------------------------------------------
   5. Barre supérieure
   -------------------------------------------------------------------------- */
.topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  -webkit-backdrop-filter: saturate(1.5) blur(12px);
  backdrop-filter: saturate(1.5) blur(12px);
  border-bottom: 1px solid var(--border);
  padding-top: var(--safe-t);
}
.topbar__inner {
  width: 100%;
  max-width: var(--page-max);
  margin: 0 auto;
  padding: var(--sp-3) var(--sp-4);
  padding-left: max(var(--sp-4), var(--safe-l));
  padding-right: max(var(--sp-4), var(--safe-r));
  display: grid;
  gap: var(--sp-3);
}
.topbar__row { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; }
.topbar__title {
  flex: 1;
  min-width: 0;
  font-size: var(--fs-2xl);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.topbar__title--sm { font-size: var(--fs-xl); }
.topbar__actions { display: flex; align-items: center; gap: var(--sp-1); flex: none; }
.topbar__sub { font-size: var(--fs-md); color: var(--text-soft); }
/* Variante compacte : la barre se réduit dès qu'on ne montre qu'un titre. */
.topbar--slim .topbar__inner { padding-top: var(--sp-2); padding-bottom: var(--sp-2); }

/* --------------------------------------------------------------------------
   6. Barre de navigation basse (toujours sous le pouce)
   -------------------------------------------------------------------------- */
.tabbar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 40;
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  -webkit-backdrop-filter: saturate(1.5) blur(14px);
  backdrop-filter: saturate(1.5) blur(14px);
  border-top: 1px solid var(--border);
  padding-bottom: var(--safe-b);
}
.tabbar__inner {
  max-width: var(--page-max);
  margin: 0 auto;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  padding: 0 max(var(--sp-2), var(--safe-l)) 0 max(var(--sp-2), var(--safe-r));
}
.tabbar__item {
  min-height: var(--tabbar-h);
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 2px;
  padding: var(--sp-1) 2px;
  color: var(--text-soft);
  text-decoration: none;
  font-size: var(--fs-xs);
  font-weight: 600;
  border-radius: var(--r-sm);
}
.tabbar__item svg { width: 24px; height: 24px; stroke: currentColor; }
.tabbar__item--on { color: var(--accent); }
.tabbar__item:active { background: var(--surface-2); }
/* Six cibles : un intitulé comme « Réglages » ne tient plus sur un
   téléphone en 12 px. La cellule a le droit de rétrécir, et sous 420 px le
   texte se resserre plutôt que de déborder. */
.tabbar__item { min-width: 0; }
.tabbar__item span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* « Ajouter » : même gabarit, mais habillé en accent pour sauter aux yeux. */
.tabbar__item--add { color: var(--accent); }
.tabbar__item--add svg {
  background: var(--accent);
  stroke: var(--on-accent);
  border-radius: var(--r-pill);
  width: 40px; height: 26px;
  padding: 3px 8px;
  box-shadow: 0 2px 8px color-mix(in srgb, var(--accent) 45%, transparent);
}
@media (max-width: 419px) {
  .tabbar__item { font-size: 11px; padding-left: 0; padding-right: 0; letter-spacing: -.01em; }
}
@media (max-width: 359px) {
  .tabbar__inner { padding-left: max(2px, var(--safe-l)); padding-right: max(2px, var(--safe-r)); }
  .tabbar__item { font-size: 10px; padding-left: 0; padding-right: 0; letter-spacing: -.02em; }
  .tabbar__item--add svg { width: 34px; padding: 3px 5px; }
}

/* --------------------------------------------------------------------------
   7. Boutons
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: var(--tap);
  padding: 0 var(--sp-5);
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--text);
  font-size: var(--fs-base);
  font-weight: 600;
  text-decoration: none;
  transition: transform .1s ease, background-color .12s ease;
}
.btn svg { width: 20px; height: 20px; stroke: currentColor; flex: none; }
.btn:active { transform: scale(.98); }
.btn[disabled], .btn[aria-disabled="true"] { opacity: .5; pointer-events: none; }

.btn--primary { background: var(--accent); color: var(--on-accent); }
.btn--primary:active { background: var(--accent-strong); }
.btn--ghost { background: transparent; border-color: var(--line); color: var(--text); }
.btn--quiet { background: transparent; color: var(--text-soft); }
.btn--danger { background: var(--danger-soft); color: var(--danger-on-soft); border-color: transparent; }
.btn--block { display: flex; width: 100%; }
.btn--sm { min-height: 36px; padding: 0 var(--sp-3); font-size: var(--fs-md); }
.btn--lg { min-height: 52px; font-size: var(--fs-lg); }

/* Bouton icône seul. La zone tactile fait 44px même si le rond en fait 40. */
.iconbtn {
  position: relative;
  display: inline-grid;
  place-items: center;
  width: var(--tap);
  height: var(--tap);
  border: 0;
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--text-soft);
  flex: none;
}
.iconbtn svg { width: 24px; height: 24px; stroke: currentColor; }
.iconbtn:active { background: var(--surface-2); }
/* Cadré : il hérite des 44px de `.iconbtn` au lieu de les raboter à 40. Sur la
   corbeille, « Restaurer » est la seule action de la ligne — elle ne peut pas
   passer sous le plancher tactile (DESIGN.md §5.1). */
.iconbtn--boxed { background: var(--surface); border: 1px solid var(--border); }
.iconbtn--fav.is-on { color: var(--fav); }
.iconbtn--fav.is-on svg { fill: currentColor; }
.iconbtn--danger { color: var(--danger); }

/* --------------------------------------------------------------------------
   8. Recherche
   -------------------------------------------------------------------------- */
.search { position: relative; display: flex; align-items: center; }
.search__icon {
  position: absolute; left: var(--sp-3);
  width: 20px; height: 20px;
  stroke: var(--text-soft);
  pointer-events: none;
}
.search__input {
  width: 100%;
  min-height: var(--tap);
  padding: var(--sp-2) 46px var(--sp-2) 42px;
  font-size: var(--fs-base);
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  -webkit-appearance: none;
  appearance: none;
}
.search__input::placeholder { color: var(--text-soft); }
.search__input::-webkit-search-cancel-button { -webkit-appearance: none; display: none; }
/* La croix n'apparaît qu'une fois le champ rempli (classe posée par app.js). */
.search__clear {
  position: absolute; right: 4px;
  display: none;
  place-items: center;
  width: 40px; height: 40px;
  border: 0; border-radius: var(--r-pill);
  background: none;
  color: var(--text-soft);
}
.search__clear svg { width: 18px; height: 18px; stroke: currentColor; }
.search--filled .search__clear { display: grid; }
/* Pendant la requête HTMX : la loupe pulse discrètement. */
.search--busy .search__icon { animation: pulse 1s ease-in-out infinite; }
@keyframes pulse { 50% { opacity: .3; } }

/* --------------------------------------------------------------------------
   9. Filtres repliables + puces
   -------------------------------------------------------------------------- */
.filters { border: 0; }
.filters__summary {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 36px;
  padding: 0 var(--sp-3) 0 var(--sp-2);
  width: fit-content;
  border-radius: var(--r-pill);
  color: var(--text-soft);
  font-size: var(--fs-md);
  font-weight: 600;
  list-style: none;
  cursor: pointer;
}
.filters__summary::-webkit-details-marker { display: none; }
.filters__summary svg { width: 18px; height: 18px; stroke: currentColor; transition: transform .15s ease; }
.filters[open] .filters__summary { color: var(--accent); }
.filters[open] .filters__summary .icon-chevron { transform: rotate(180deg); }
.filters__count {
  min-width: 18px; height: 18px;
  padding: 0 5px;
  display: grid; place-items: center;
  border-radius: var(--r-pill);
  background: var(--accent); color: var(--on-accent);
  font-size: 11px; font-weight: 700;
}
.filters__body { display: grid; gap: var(--sp-3); padding-top: var(--sp-3); }
.filters__group { display: grid; gap: var(--sp-2); }
.filters__label {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-soft);
}

/* Rangée de puces : défile horizontalement sans jamais élargir la page. */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}
.chips--scroll {
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  padding-bottom: 2px;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
}
.chips--scroll::-webkit-scrollbar { display: none; }
.chips--scroll > * { flex: none; scroll-snap-align: start; }

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  min-height: 36px;                 /* puce de filtre : 36px + marge de 8px = 44px utiles */
  padding: 0 var(--sp-3);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--text-soft);
  font-size: var(--fs-sm);
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}
.chip svg { width: 15px; height: 15px; stroke: currentColor; }
.chip:active { background: var(--surface-2); }
.chip--on {
  background: var(--accent-soft);
  border-color: transparent;
  color: var(--accent-on-soft);
}
.chip--fav.chip--on { background: var(--fav-soft); color: var(--fav-on-soft); }
/* Étiquette d'affichage discrète (non cliquable) : dates, compteurs, mentions. */
.chip--meta {
  min-height: 24px;
  padding: 0 var(--sp-2);
  font-size: var(--fs-xs);
  font-weight: 600;
  background: var(--surface-2);
  border-color: transparent;
  color: var(--text-soft);
}
.chip--meta svg { width: 13px; height: 13px; }
/* Puce supprimable dans le formulaire d'édition. */

/* --------------------------------------------------------------------------
   10. (Badges de statut : retirés avec le statut des fiches. Les couleurs
       --st-* restent : la pastille d'état, la tendance et l'éclat
       d'enregistrement s'en servent.)
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   11. Avatar (initiales colorées quand il n'y a pas de photo)
   La teinte vient de --avatar-h, posé en style inline par la macro avatar().
   -------------------------------------------------------------------------- */
.avatar {
  --avatar-h: 240;
  --avatar-size: 48px;
  flex: none;
  width: var(--avatar-size);
  height: var(--avatar-size);
  border-radius: var(--r);
  overflow: hidden;
  display: grid;
  place-items: center;
  background: hsl(var(--avatar-h) 52% 92%);
  color: hsl(var(--avatar-h) 62% 28%);
  font-weight: 700;
  font-size: calc(var(--avatar-size) * .38);
  letter-spacing: .02em;
  user-select: none;
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.avatar--md { --avatar-size: 72px; }
.avatar--xs { --avatar-size: 28px; border-radius: 50%; }
.avatar--lg { --avatar-size: 96px; }
/* Mon profil (Réglages) : photo de compte et ses actions */
.profil { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.profil__actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); min-width: 0; }
.profil__pick { cursor: pointer; position: relative; }
.profil__pick:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Signature d'un compte (avis, lapins) : photo ronde et nom public. */
.signature { display: inline-flex; align-items: center; gap: var(--sp-2); min-width: 0; }
.signature__nom { min-width: 0; overflow-wrap: anywhere; font-weight: 600; }
/* Douze teintes réparties sur la roue : la macro avatar() pose la classe à
   partir de l'identifiant de la fiche (aucun attribut style=, la CSP l'interdit).
   Contraste vérifié : 4,7:1 au pire en clair, 6,7:1 en sombre. */
.avatar--h0 { --avatar-h: 205; }
.avatar--h1 { --avatar-h: 234; }
.avatar--h2 { --avatar-h: 263; }
.avatar--h3 { --avatar-h: 292; }
.avatar--h4 { --avatar-h: 321; }
.avatar--h5 { --avatar-h: 350; }
.avatar--h6 { --avatar-h: 19; }
.avatar--h7 { --avatar-h: 48; }
.avatar--h8 { --avatar-h: 77; }
.avatar--h9 { --avatar-h: 106; }
.avatar--h10 { --avatar-h: 135; }
.avatar--h11 { --avatar-h: 164; }
/* En sombre, la pastille s'assombrit et le texte s'éclaircit. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .avatar {
    background: hsl(var(--avatar-h) 34% 22%);
    color: hsl(var(--avatar-h) 70% 80%);
  }
}
:root[data-theme="dark"] .avatar {
  background: hsl(var(--avatar-h) 34% 22%);
  color: hsl(var(--avatar-h) 70% 80%);
}

/* --------------------------------------------------------------------------
   12. Note en étoiles
   Lecture : suite d'étoiles pleines/vides. Édition : 5 boutons de 44px.
   -------------------------------------------------------------------------- */
.stars-wrap { display: inline-flex; align-items: center; flex-wrap: wrap; gap: var(--sp-1); min-width: 0; }
.stars { display: inline-flex; align-items: center; gap: 2px; }
.stars svg { width: 16px; height: 16px; stroke: var(--star-off); fill: none; }
.stars .star--on { stroke: var(--star); fill: var(--star); }

.stars--editable { gap: 0; touch-action: pan-y; }
.stars__btn {
  display: grid;
  place-items: center;
  width: var(--tap);
  height: var(--tap);
  border: 0;
  background: none;
  padding: 0;
}
.stars--editable svg { width: 30px; height: 30px; transition: transform .12s ease, fill .12s ease; }
.stars__btn:active svg { transform: scale(1.18); }
/* Aperçu au glissement : app.js bascule .star--on étoile par étoile puis
   restaure l'état d'origine si le doigt sort du groupe. */
.stars--editable.is-previewing svg { transition: none; }
.stars__reset {
  margin-left: var(--sp-1);
  color: var(--text-soft);
  font-size: var(--fs-sm);
  background: none; border: 0;
  min-height: var(--tap);
  padding: 0 var(--sp-2);
}
.stars__none { font-size: var(--fs-md); color: var(--text-soft); font-style: italic; }

/* --------------------------------------------------------------------------
   13. Liste de fiches
   Carte horizontale : la vignette suffit à reconnaître, on en voit 7 par écran.
   -------------------------------------------------------------------------- */
.list { display: grid; gap: var(--sp-2); }

.card {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-3);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  box-shadow: var(--shadow-1);
  transition: transform .12s ease;
}
.card:has(.card__link:active) { transform: scale(.99); }
.card__media {
  flex: none;
  width: 76px; height: 76px;
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--surface-2);
}
.card__media img { width: 100%; height: 100%; object-fit: cover; }
.card__media .avatar { --avatar-size: 76px; border-radius: var(--r-sm); }
.card__body { flex: 1; min-width: 0; display: grid; gap: 5px; }
/* Le lien couvre toute la carte ; le bouton favori repasse au-dessus (z-index). */
.card__link { position: static; color: inherit; text-decoration: none; }
.card__link::after { content: ""; position: absolute; inset: 0; border-radius: var(--r); }
.card__name {
  font-size: var(--fs-lg);
  font-weight: 650;
  /* Réserve la place du cœur pour que le nom ne passe pas dessous. */
  padding-right: 34px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.card__nick { color: var(--text-soft); font-weight: 500; }
.card__nick::before { content: " · "; }
.card__meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-1) var(--sp-2);
  font-size: var(--fs-md);
  color: var(--text-soft);
  min-width: 0;
}
.favform { display: flex; }
/* Dans une carte, le cœur se pose en haut à droite, au-dessus du lien étalé. */
.card .favform { position: absolute; top: 4px; right: 4px; z-index: 1; }
.card .favform svg { width: 22px; height: 22px; }
.card__when { font-size: var(--fs-xs); color: var(--text-soft); }

/* En-tête de section de liste (ex. « 12 fiches ») */
.listhead {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2);
  padding: 0 var(--sp-1) var(--sp-1);
  font-size: var(--fs-md);
  color: var(--text-soft);
}
.listhead__sort { display: inline-flex; align-items: center; gap: 5px; font-weight: 600; }
.listhead__sort svg { width: 15px; height: 15px; }

/* --------------------------------------------------------------------------
   14. États vides
   -------------------------------------------------------------------------- */
.empty {
  display: grid;
  justify-items: center;
  gap: var(--sp-3);
  padding: var(--sp-10) var(--sp-5);
  text-align: center;
}
.empty__icon {
  display: grid; place-items: center;
  width: 68px; height: 68px;
  border-radius: var(--r-pill);
  background: var(--accent-soft);
}
.empty__icon svg { width: 32px; height: 32px; stroke: var(--accent-on-soft); }
.empty__title { font-size: var(--fs-xl); }
.empty__hint { color: var(--text-soft); max-width: 34ch; }

/* --------------------------------------------------------------------------
   15. Fiche personne
   -------------------------------------------------------------------------- */
/* Bloc identité : photo de profil, nom, pseudos, statut, note. */
.ident {
  position: relative;
  margin: 0 var(--sp-3);
  padding: var(--sp-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
  display: grid;
  gap: var(--sp-3);
}
.ident { margin-top: var(--sp-3); scroll-margin-top: var(--sp-10); }
.ident__top { display: flex; align-items: flex-start; gap: var(--sp-3); }
.ident__names { flex: 1; min-width: 0; }
.ident__name { font-size: var(--fs-2xl); }
.ident__meta { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center; }
.ident__meta .secedit { margin-left: auto; }
/* La photo de profil s'agrandit d'un tap (visionneuse). */
.ident__photo { flex: none; padding: 0; border: 0; background: none; border-radius: 50%; cursor: zoom-in; }
.ident__photo:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* Pseudos sous le nom, chacun avec le site où il a cours. */
.pseudos { list-style: none; margin: var(--sp-1) 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-3); }
.pseudo { display: inline-flex; align-items: baseline; gap: 6px; min-width: 0; max-width: 100%; }
.pseudo__value { color: var(--text-soft); font-weight: 600; overflow-wrap: anywhere; }
.pseudo__site {
  font-size: var(--fs-xs); font-weight: 700; color: var(--accent-on-soft);
  background: var(--accent-soft); border-radius: var(--r-pill); padding: 1px 8px;
  white-space: nowrap;
}

/* Lien « Modifier / Ajouter » d'une section modifiable sur place. */
.secedit {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: var(--tap); padding: 0 var(--sp-2);
  margin-right: calc(-1 * var(--sp-2));
  color: var(--accent-on-soft); font-weight: 600; font-size: var(--fs-sm);
  text-decoration: none; border-radius: var(--r);
}
.secedit svg { width: 16px; height: 16px; stroke: currentColor; }
.secedit:hover { background: var(--accent-soft); }
.section, .ident { scroll-margin-top: var(--sp-10); }

/* Section ouverte en édition : un cadre qui dit « vous modifiez ceci ». */
.secform {
  padding: var(--sp-3);
  border: 1px solid var(--accent);
  border-radius: var(--r);
  background: var(--surface);
}
.ident--edit .secform { padding: 0; border: 0; }
.secform__actions { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: var(--sp-2); }

/* Lignes répétables : pseudos, moyens de contact, liens. */
.rows { display: grid; gap: var(--sp-2); }
.rows__list { display: grid; gap: var(--sp-2); }
.rowin { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--sp-1) var(--sp-2); align-items: center; }
.rowin > * { min-width: 0; }
.rowin .rowin__del { grid-column: 2; grid-row: 1 / span 2; align-self: center; }
.rowin .rowin__del[hidden] { display: none; }
@media (min-width: 480px) {
  .rowin { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto; }
  .rowin .rowin__del { grid-column: 3; grid-row: 1; }
}
/* Sur mobile, chaque ligne tient sur deux rangs : on les sépare d'un filet. */
.rows__list > .rowin + .rowin { padding-top: var(--sp-2); border-top: 1px dashed var(--border); }
@media (min-width: 480px) { .rows__list > .rowin + .rowin { padding-top: 0; border-top: 0; } }
.rows__add {
  justify-self: start;
  display: inline-flex; align-items: center; gap: 6px;
  min-height: var(--tap); padding: 0 var(--sp-3);
  border: 1px dashed var(--line); border-radius: var(--r);
  background: transparent; color: var(--accent-on-soft); font: inherit; font-weight: 600;
  cursor: pointer;
}
.rows__add svg { width: 16px; height: 16px; stroke: currentColor; }
.rows__add[hidden] { display: none; }

/* Les enfants d'une grille ont `min-width: auto` : un seul enfant trop large
   élargirait toute la grille (et ferait déborder la page). On les autorise
   explicitement à rétrécir. */
.ident > *, .stack > *, .form > *, .fold__body > *, .filters__body > *,
.settings > *, .section > *, .setgroup > *, .contacts > *, .userlist > *,
.timeline > *, .stack > *, .steps > *, .step > *, .rows > *, .rows__list > *,
.tlentry__card > *, .recap > *, .photogrid > *,
.aide > *, .aide__sec > *, .aide__toc > *, .aide__list > *, .aide__tabs > *,
.aide__who > *, .aide__who .panel > *, .aide__faq > * { min-width: 0; }

/* Bande de notation : l'action la plus fréquente, à hauteur de pouce.
   Elle passe à la ligne plutôt que de pousser la mise en page (petits écrans). */
.rating {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  row-gap: var(--sp-1);
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-2) var(--sp-2) var(--sp-3);
  background: var(--surface-2);
  border-radius: var(--r);
}
.rating__label { font-size: var(--fs-md); font-weight: 600; color: var(--text-soft); }

/* Coordonnées : chaque ligne est un lien tel:/mailto:/http de 56px. */
.contacts { display: grid; gap: var(--sp-1); }
.contact {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 56px;
  padding: var(--sp-2) var(--sp-2) var(--sp-2) var(--sp-3);
  border-radius: var(--r-sm);
  background: var(--surface);
  border: 1px solid var(--border);
  color: inherit;
  text-decoration: none;
}
.contact:active { background: var(--surface-2); }
.contact--plain:active { background: var(--surface); }
.contact__icon {
  flex: none;
  display: grid; place-items: center;
  width: 36px; height: 36px;
  border-radius: var(--r-xs);
  background: var(--accent-soft);
}
.contact__icon svg { width: 19px; height: 19px; stroke: var(--accent-on-soft); }
.contact__body { flex: 1; min-width: 0; }
.contact__label, .contact__value { display: block; }
.contact__label { font-size: var(--fs-xs); color: var(--text-soft); text-transform: uppercase; letter-spacing: .05em; font-weight: 700; }
.contact__value { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.contact--wrap .contact__value { white-space: normal; overflow-wrap: anywhere; }
.contact__go { flex: none; width: 20px; height: 20px; stroke: var(--text-soft); }

/* Sections de contenu */
.section { display: grid; gap: var(--sp-3); }
/* Partie distincte d'un formulaire (l'avis saisi à la création d'un lieu). */
.section--sep { padding-top: var(--sp-4); border-top: 1px solid var(--border); }
.section__head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); }
.section__title {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-soft);
}
.panel {
  padding: var(--sp-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
}
.panel--quiet { background: var(--surface-2); border-color: transparent; }
.prose { white-space: pre-wrap; line-height: 1.6; }
.prose--soft { color: var(--text-soft); }

/* Paire libellé/valeur (macro field) */

/* Galerie photos : bande horizontale, la couverture d'abord. */
.gallery {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 104px;
  gap: var(--sp-2);
  overflow-x: auto;
  scrollbar-width: none;
  padding: 2px var(--sp-4) var(--sp-1);
  margin: 0 calc(-1 * var(--sp-4));
  scroll-snap-type: x proximity;
}
.gallery::-webkit-scrollbar { display: none; }
.gallery__item {
  position: relative;
  aspect-ratio: 1;
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--surface-2);
  scroll-snap-align: start;
  border: 1px solid var(--border);
}
.gallery__item img { width: 100%; height: 100%; object-fit: cover; }
.gallery__flag {
  position: absolute; left: 4px; top: 4px;
  padding: 2px 6px;
  border-radius: var(--r-pill);
  background: rgba(9, 11, 16, .66);
  color: #fff;
  font-size: 10px; font-weight: 700;
}
/* Photo rattachée à une rencontre : la date porte le rattachement, dans la
   galerie de la fiche comme dans la chronologie. */
.gallery__flag--event {
  left: 4px; right: 4px; top: auto; bottom: 4px;
  display: flex; align-items: center; justify-content: center; gap: 3px;
  background: rgba(9, 11, 16, .74);
}
.gallery__flag--event svg { width: 11px; height: 11px; stroke: currentColor; flex: none; }

/* --------------------------------------------------------------------------
   16. Formulaires
   -------------------------------------------------------------------------- */
.form { display: grid; gap: var(--sp-4); }

.field { display: grid; gap: var(--sp-1); min-width: 0; }
.field__label {
  font-size: var(--fs-md);
  font-weight: 650;
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
}
/* Champ facultatif : mention discrète, jamais en gras. */
.field__opt { font-size: var(--fs-xs); font-weight: 500; color: var(--text-soft); }
.field__hint { font-size: var(--fs-sm); color: var(--text-soft); }
.field__error {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: var(--fs-sm);
  color: var(--danger);
  font-weight: 600;
}
.field__error svg { width: 15px; height: 15px; }

.input, .textarea, .select {
  width: 100%;
  min-height: var(--tap);
  padding: var(--sp-2) var(--sp-3);
  font-size: var(--fs-base);      /* 16px : évite le zoom auto d'iOS */
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  -webkit-appearance: none;
  appearance: none;
}
.input::placeholder, .textarea::placeholder { color: var(--text-soft); }
.textarea { min-height: 96px; resize: vertical; line-height: 1.55; padding-top: var(--sp-3); }
.select {
  padding-right: var(--sp-8);
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 18px) 50%, calc(100% - 12px) 50%;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}
.field--invalid .input, .field--invalid .textarea, .field--invalid .select { border-color: var(--danger); }

/* Groupe de champs sur une ligne (date + lieu…) */
.field-grid { display: grid; gap: var(--sp-3); }
@media (min-width: 480px) { .field-grid--2 { grid-template-columns: 1fr 1fr; } }

/* Section repliable du formulaire */
.fold {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  overflow: hidden;
}
.fold__summary {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 56px;
  padding: 0 var(--sp-4);
  font-weight: 650;
  cursor: pointer;
  list-style: none;
}
.fold__summary::-webkit-details-marker { display: none; }
.fold__summary .icon-chevron {
  margin-left: auto;
  width: 20px; height: 20px;
  stroke: var(--text-soft);
  transition: transform .15s ease;
}
.fold[open] .fold__summary .icon-chevron { transform: rotate(180deg); }
.fold__summary > svg:first-child { width: 20px; height: 20px; stroke: var(--text-soft); }
.fold__badge { font-size: var(--fs-sm); font-weight: 500; color: var(--text-soft); }
.fold__body {
  display: grid;
  gap: var(--sp-4);
  padding: var(--sp-2) var(--sp-4) var(--sp-4);
  border-top: 1px solid var(--border);
}

/* Choix segmenté (statut, thème, tri) : gros doigts bienvenus. */
.segmented {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: var(--sp-1);
  padding: var(--sp-1);
  background: var(--surface-2);
  border-radius: var(--r-sm);
}
.segmented--grid { grid-auto-flow: row; grid-template-columns: 1fr 1fr; }
.segmented__opt { position: relative; display: flex; }
.segmented__opt input {
  position: absolute;
  opacity: 0;
  width: 100%; height: 100%;
  margin: 0;
}
.segmented__opt span {
  flex: 1;
  display: grid;
  place-items: center;
  gap: 2px;
  min-height: 40px;
  padding: var(--sp-1) 2px;
  border-radius: var(--r-xs);
  font-size: var(--fs-sm);
  font-weight: 650;
  color: var(--text-soft);
  text-align: center;
}
.segmented__opt svg { width: 18px; height: 18px; stroke: currentColor; }
.segmented__opt input:checked + span { background: var(--surface); color: var(--text); box-shadow: var(--shadow-1); }
.segmented__opt input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Interrupteur */
.switch { display: flex; align-items: center; gap: var(--sp-3); min-height: var(--tap); }
.switch input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.switch__track {
  flex: none;
  width: 50px; height: 30px;
  border-radius: var(--r-pill);
  background: var(--line);
  position: relative;
  transition: background-color .15s ease;
}
.switch__track::after {
  content: "";
  position: absolute;
  top: 3px; left: 3px;
  width: 24px; height: 24px;
  border-radius: var(--r-pill);
  background: #fff;
  transition: transform .15s ease;
}
.switch input:checked + .switch__track { background: var(--accent); }
.switch input:checked + .switch__track::after { transform: translateX(20px); }
.switch input:focus-visible + .switch__track { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Téléversement de photos */
.uploader { display: grid; gap: var(--sp-3); }
.uploader__drop {
  display: grid;
  justify-items: center;
  gap: var(--sp-2);
  padding: var(--sp-6) var(--sp-4);
  border: 1.5px dashed var(--line);
  border-radius: var(--r);
  background: var(--surface-2);
  color: var(--text-soft);
  text-align: center;
  cursor: pointer;
}
.uploader__drop svg { width: 30px; height: 30px; stroke: var(--accent); }
.uploader__drop strong { color: var(--text); font-size: var(--fs-base); }
.uploader__drop input[type="file"] { position: absolute; width: 1px; height: 1px; opacity: 0; }
.uploader__previews { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: var(--sp-2); }
.uploader__previews:empty { display: none; }
.uploader__preview { position: relative; aspect-ratio: 1; border-radius: var(--r-sm); overflow: hidden; background: var(--surface-2); }
.uploader__preview img { width: 100%; height: 100%; object-fit: cover; }

/* Barre d'action collante (enregistrer) */
.actionbar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 40;
  background: color-mix(in srgb, var(--surface) 94%, transparent);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border-top: 1px solid var(--border);
  padding-bottom: var(--safe-b);
}
.actionbar__inner {
  max-width: var(--page-max);
  margin: 0 auto;
  display: flex;
  gap: var(--sp-2);
  padding: var(--sp-3) max(var(--sp-4), var(--safe-l)) var(--sp-3) max(var(--sp-4), var(--safe-r));
}
.actionbar .btn--primary { flex: 1; }

/* --------------------------------------------------------------------------
   17. Réglages
   -------------------------------------------------------------------------- */
.settings { display: grid; gap: var(--sp-5); }
.setgroup { display: grid; gap: var(--sp-2); }
.setgroup__title {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-soft);
  padding-left: var(--sp-1);
}
.setgroup__body {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  overflow: hidden;
}
.setrow {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 56px;
  padding: var(--sp-3) var(--sp-4);
  color: inherit;
  text-decoration: none;
}
.setrow + .setrow { border-top: 1px solid var(--border); }
.setrow--stack { display: grid; gap: var(--sp-3); }
.setrow__icon { flex: none; width: 22px; height: 22px; stroke: var(--text-soft); }
.setrow__body { flex: 1; min-width: 0; }
.setrow__title { font-weight: 600; }
.setrow__hint { font-size: var(--fs-sm); color: var(--text-soft); }
.setrow__go { flex: none; width: 20px; height: 20px; stroke: var(--text-soft); }

/* <summary> d'une ligne de réglages : même gabarit qu'une ligne cliquable. */
.setrow > summary {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 40px;
  font-weight: 600;
}
.setrow > summary .icon-chevron {
  margin-left: auto;
  width: 20px; height: 20px;
  stroke: var(--text-soft);
  transition: transform .15s ease;
}
.setrow[open] > summary .icon-chevron { transform: rotate(180deg); }

.pill-state {
  display: inline-flex; align-items: center; gap: 5px;
  height: 24px; padding: 0 var(--sp-2);
  border-radius: var(--r-pill);
  font-size: var(--fs-xs); font-weight: 700;
}
.pill-state--on { background: var(--st-en-cours-bg); color: var(--st-en-cours-fg); }
.pill-state--off { background: var(--st-archive-bg); color: var(--st-archive-fg); }

/* --------------------------------------------------------------------------
   18. Authentification (connexion, verrou PIN)
   -------------------------------------------------------------------------- */
.auth { display: grid; gap: var(--sp-5); justify-items: center; text-align: center; }
.auth__logo { width: 64px; height: 64px; border-radius: var(--r-lg); box-shadow: var(--shadow-1); }
.auth__title { font-size: var(--fs-2xl); }
.auth__hint { color: var(--text-soft); max-width: 32ch; }
.auth__card {
  width: 100%;
  display: grid;
  gap: var(--sp-4);
  padding: var(--sp-5) var(--sp-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
  text-align: left;
}
.auth__foot { font-size: var(--fs-sm); color: var(--text-soft); }

/* Code à 6 chiffres */
.otp {
  letter-spacing: .5em;
  text-align: center;
  font-size: 1.375rem;
  font-weight: 700;
  padding-left: calc(var(--sp-3) + .5em);
}

/* Pavé numérique du verrou : frappe au pouce, une seule main. */
.pindots { display: flex; justify-content: center; gap: var(--sp-3); }
.pindot {
  width: 14px; height: 14px;
  border-radius: var(--r-pill);
  border: 1.5px solid var(--line);
}
.pindot--on { background: var(--accent); border-color: var(--accent); }
.pinpad {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-3);
  max-width: 300px;
  margin: 0 auto;
  width: 100%;
}
.pinpad__key {
  min-height: 64px;
  border: 1px solid var(--border);
  border-radius: var(--r);
  background: var(--surface);
  font-size: 1.5rem;
  font-weight: 600;
  box-shadow: var(--shadow-1);
}
.pinpad__key:active { background: var(--surface-2); transform: scale(.97); }
.pinpad__key--quiet { background: transparent; border-color: transparent; box-shadow: none; }
.pinpad__key svg { width: 24px; height: 24px; stroke: var(--text-soft); margin: 0 auto; }

/* Message d'erreur d'authentification */
.alert {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  padding: var(--sp-3);
  border-radius: var(--r-sm);
  font-size: var(--fs-md);
  font-weight: 600;
}
.alert svg { width: 20px; height: 20px; flex: none; stroke: currentColor; }
/* Le message est UN seul élément flex : sans ce span, un <strong> au
   milieu du texte deviendrait une colonne à lui tout seul. */
.alert__text { min-width: 0; }
.alert--danger { background: var(--danger-soft); color: var(--danger-on-soft); }
.alert--info { background: var(--accent-soft); color: var(--accent-on-soft); }
/* Adresse bannie (administration) */
.banrow { display: flex; align-items: center; gap: var(--sp-3); }
.banrow__body { flex: 1; min-width: 0; }
.banrow__ip { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-weight: 600; overflow-wrap: anywhere; }

/* Alerte cliquable (rappel d'activer la 2FA) : toute la bande est le lien. */
.alert--link { text-decoration: none; font-weight: 500; align-items: center; margin-bottom: var(--sp-3); }
.alert--link .alert__text { flex: 1; }
.alert--link:hover { filter: brightness(0.97); }

/* --------------------------------------------------------------------------
   19. Retour visuel : toasts et confirmations
   -------------------------------------------------------------------------- */
.toasts {
  position: fixed;
  left: 50%;
  bottom: calc(var(--tabbar-h) + var(--safe-b) + var(--sp-3));
  transform: translateX(-50%);
  z-index: 60;
  display: grid;
  gap: var(--sp-2);
  width: min(420px, calc(100vw - 2 * var(--sp-4)));
  pointer-events: none;
}
.toast {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-pill);
  background: var(--text);
  color: var(--bg);
  font-weight: 600;
  font-size: var(--fs-md);
  box-shadow: var(--shadow-2);
  animation: toast-in .22s ease both;
}
.toast svg { width: 18px; height: 18px; stroke: currentColor; flex: none; }
.toast--ok svg { stroke: #6ee7a8; }
.toast--err { background: var(--danger); color: #fff; }
.toast--out { animation: toast-out .2s ease both; }
@keyframes toast-in { from { opacity: 0; transform: translateY(12px) scale(.96); } }
@keyframes toast-out { to { opacity: 0; transform: translateY(8px) scale(.98); } }

/* Éclat vert bref sur l'élément fraîchement enregistré (HTMX). */
.saved { animation: saved-flash 1.1s ease; }
@keyframes saved-flash {
  0%, 100% { box-shadow: var(--shadow-1); }
  25% { box-shadow: 0 0 0 3px var(--st-en-cours-bg); }
}

/* --------------------------------------------------------------------------
   20. Visionneuse plein écran
   -------------------------------------------------------------------------- */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: var(--scrim);
  display: grid;
  grid-template-rows: auto 1fr auto;
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}
.lightbox[hidden] { display: none; }
.lightbox__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: max(var(--sp-2), var(--safe-t)) var(--sp-2) var(--sp-2);
  color: #fff;
}
.lightbox__bar .iconbtn { color: #fff; }
.lightbox__count { font-size: var(--fs-md); font-weight: 600; opacity: .85; }
.lightbox__stage { display: grid; place-items: center; overflow: hidden; padding: var(--sp-2); }
.lightbox__img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border-radius: var(--r-xs);
  touch-action: pan-y;
}
.lightbox__nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-6);
  padding: var(--sp-2) var(--sp-2) calc(var(--sp-4) + var(--safe-b));
}
.lightbox__nav .iconbtn { color: #fff; background: rgba(255, 255, 255, .12); }
/* Empêche le défilement de la page derrière la visionneuse. */
body.is-locked { overflow: hidden; }

/* --------------------------------------------------------------------------
   21. Utilitaires
   -------------------------------------------------------------------------- */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.skip {
  position: absolute;
  left: var(--sp-2);
  top: calc(-100px);
  z-index: 200;
  padding: var(--sp-2) var(--sp-3);
  background: var(--accent);
  color: var(--on-accent);
  border-radius: var(--r-xs);
  font-weight: 700;
  text-decoration: none;
  transition: top .12s ease;
}
.skip:focus { top: calc(var(--safe-t) + var(--sp-2)); }

.muted { color: var(--text-soft); }
.small { font-size: var(--fs-md); }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.grow { flex: 1; min-width: 0; }
.mt-2 { margin-top: var(--sp-2); }
.hidden { display: none !important; }

/* --------------------------------------------------------------------------
   24. Compléments liés aux gabarits
   Ces classes sont utilisées par app/templates/ ; elles restent groupées ici
   pour ne pas casser l'ordre de lecture des sections précédentes.
   -------------------------------------------------------------------------- */

/* Recherche + filtres : un seul formulaire, HTMX sérialise l'ensemble. */
.searchform { display: grid; gap: var(--sp-2); }

/* Puce-filtre : la radio (ou la case) est invisible mais couvre toute la puce,
   ce qui garde une cible tactile pleine et un focus clavier natif. */
.chip { position: relative; }
.chip input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.chip:has(input:checked) { background: var(--accent-soft); border-color: transparent; color: var(--accent-on-soft); }
.chip--fav:has(input:checked) { background: var(--fav-soft); color: var(--fav-on-soft); }
.chip:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.chip__count {
  min-width: 17px;
  padding: 0 4px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, currentColor 14%, transparent);
  font-size: 11px;
  font-weight: 700;
  text-align: center;
}
.filters__foot { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.filters__foot .btn { margin-left: auto; }
.filters__foot .btn + .btn, .filters__foot .btn ~ .btn { margin-left: 0; }

/* Carte de corbeille : plus sobre, l'action est à droite. */
.card--trash { opacity: .92; }
.card--trash .card__name { padding-right: 0; }

/* Paires intitulé / adresse dans le formulaire. */

/* Gestion des photos déjà enregistrées (écran d'édition). */
.photogrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: var(--sp-3); }
.photocard {
  position: relative;
  margin: 0;
  aspect-ratio: 1;
  border-radius: var(--r);
  overflow: hidden;
  background: var(--surface-2);
  border: 1px solid var(--border);
}
.photocard--cover { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.photocard img { width: 100%; height: 100%; object-fit: cover; }
.photocard__flag {
  position: absolute; left: 6px; top: 6px;
  padding: 2px 7px;
  border-radius: var(--r-pill);
  background: var(--accent); color: var(--on-accent);
  font-size: 10px; font-weight: 700;
}
.photocard__flag--event { background: rgba(9, 11, 16, .62); color: #fff; }
.photocard__actions { position: absolute; right: 6px; bottom: 6px; display: flex; gap: 6px; }
.photocard__actions .iconbtn { background: color-mix(in srgb, var(--surface) 88%, transparent); }

/* Compteurs des réglages. */
.stats { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: var(--sp-2); width: 100%; }
.stat { display: grid; justify-items: center; gap: 2px; text-align: center; }
.stat__n { font-size: var(--fs-2xl); font-weight: 700; letter-spacing: -.02em; }
.stat__l { font-size: var(--fs-xs); color: var(--text-soft); }

/* Marche à suivre en trois temps (activation du second facteur). */
.steps { display: grid; gap: var(--sp-4); }
.step {
  display: grid;
  grid-template-columns: 30px 1fr;
  gap: var(--sp-3);
  padding: var(--sp-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
}
.step__n {
  display: grid; place-items: center;
  width: 30px; height: 30px;
  border-radius: var(--r-pill);
  background: var(--accent-soft); color: var(--accent-on-soft);
  font-weight: 700;
}
.step__title { font-weight: 650; }
.step__hint { font-size: var(--fs-md); color: var(--text-soft); margin-top: 2px; }

/* QR code rendu par le serveur : encadré blanc, lisible en thème sombre aussi. */
.qr {
  display: grid;
  place-items: center;
  margin-top: var(--sp-3);
  padding: var(--sp-3);
  background: #fff;
  border-radius: var(--r-sm);
}
.qr svg { width: 100%; max-width: 220px; height: auto; }

/* Blocs à recopier (clé TOTP, commande shell). */
.code {
  margin: var(--sp-2) 0 0;
  padding: var(--sp-3);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--fs-md);
  overflow-x: auto;
  white-space: pre;
  -webkit-user-select: all;
  user-select: all;
}
.code--secret { letter-spacing: .12em; font-weight: 700; text-align: center; }

/* Cadenas de l'écran de verrouillage. */
.auth__lock {
  display: grid; place-items: center;
  width: 64px; height: 64px;
  border-radius: var(--r-pill);
  background: var(--accent-soft);
  color: var(--accent-on-soft);
}
.auth__lock svg { width: 30px; height: 30px; }
.auth__foot { display: inline-flex; align-items: center; gap: 6px; }
.auth__foot svg { width: 14px; height: 14px; }

/* Liste des noms de fichiers, repli quand l'aperçu image n'est pas permis. */
.uploader__names { display: grid; gap: 4px; font-size: var(--fs-md); color: var(--text-soft); }

/* --------------------------------------------------------------------------
   25. Rencontres : résumé et chronologie
   Le cœur de la fiche en v2. Tout est dessiné pour être lu au pouce, du plus
   récent au plus ancien, sans jamais quitter la page.
   -------------------------------------------------------------------------- */

/* Résumé en tête de fiche (compteur, bornes, évolution de la note). */
.recap {
  display: grid;
  gap: var(--sp-3);
  padding: var(--sp-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  box-shadow: var(--shadow-1);
}
.recap > * { min-width: 0; }
/* Une date n'a pas la même longueur qu'un compteur : elle prend le corps du
   titre de carte, pas celui des grands chiffres. */
.stat__n--date { font-size: var(--fs-lg); font-weight: 650; letter-spacing: 0; }
.recap__trend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--border);
}
.recap__avg { display: flex; align-items: baseline; gap: var(--sp-2); flex-wrap: wrap; min-width: 0; }
.recap__avgn { font-size: var(--fs-xl); font-weight: 700; }

/* Évolution de la note : une flèche ET un mot, jamais la couleur seule. */
.trend {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px var(--sp-2);
  border-radius: var(--r-pill);
  font-size: var(--fs-sm);
  font-weight: 650;
  background: var(--surface-2);
  color: var(--text-soft);
}
.trend svg { width: 15px; height: 15px; stroke: currentColor; }
.trend--up { background: var(--st-en-cours-bg); color: var(--st-en-cours-fg); }
.trend--down { background: var(--st-a-recontacter-bg); color: var(--st-a-recontacter-fg); }
.trend--flat { background: var(--st-archive-bg); color: var(--st-archive-fg); }

/* Chronologie. Le fil vertical est décoratif : c'est un ::before de l'entrée,
   pas un élément de plus dans le DOM. */
.timeline { list-style: none; display: grid; gap: var(--sp-3); }
.tlentry {
  position: relative;
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr);
  gap: var(--sp-3);
  min-width: 0;
}
.tlentry > * { min-width: 0; }
.tlentry::before {
  content: "";
  position: absolute;
  left: 13px;
  top: 30px;
  bottom: calc(var(--sp-3) * -1);
  width: 2px;
  background: var(--border);
}
.tlentry:last-child::before { display: none; }
.tlentry__dot {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 28px; height: 28px;
  margin-top: var(--sp-2);
  border-radius: var(--r-pill);
  background: var(--accent-soft);
  color: var(--accent-on-soft);
}
.tlentry__dot svg { width: 16px; height: 16px; stroke: currentColor; }
.tlentry__card {
  display: grid;
  gap: var(--sp-2);
  padding: var(--sp-3);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  box-shadow: var(--shadow-1);
  min-width: 0;
}
.tlentry__card > * { min-width: 0; }
.tlentry__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-2); }
.tlentry__date { font-size: var(--fs-lg); font-weight: 700; line-height: 1.25; }
.tlentry__date::first-letter { text-transform: uppercase; }
.tlentry__ago { font-size: var(--fs-md); color: var(--text-soft); }
.tlentry__meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.tlentry__meta .chip { max-width: 100%; }
.tlentry__notes { color: var(--text); }
/* « Modifier » mène à l'écran dédié de la rencontre : une ligne de 44px en
   pied de carte, jamais un bouton flottant sur la vignette. */
.tlentry__edit {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--tap);
  margin-top: var(--sp-1);
  padding-top: var(--sp-2);
  border-top: 1px dashed var(--border);
  color: var(--text-soft);
  font-size: var(--fs-md);
  font-weight: 650;
  text-decoration: none;
}
.tlentry__edit > svg:first-child { width: 17px; height: 17px; stroke: currentColor; flex: none; }
.tlentry__edit:active { color: var(--accent); }
.tlentry__go { margin-left: auto; width: 18px; height: 18px; stroke: currentColor; flex: none; }

/* Entrée « origine » : d'où vient le contact. Rail en pointillés, ton discret :
   ce n'est pas une rencontre de plus, c'est le point de départ. */

/* Vignettes des photos d'une rencontre : une bande qui défile toute seule. */
.shots {
  display: flex;
  gap: var(--sp-2);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
  padding-bottom: 2px;
}
.shots::-webkit-scrollbar { display: none; }
.shot {
  flex: none;
  width: 76px; height: 76px;
  padding: 0;
  border: 0;
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--surface-2);
  scroll-snap-align: start;
  cursor: pointer;
}
.shot img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Ajout d'une rencontre : un repli sous la chronologie, teinté pour se
   distinguer des rencontres passées. */
.quickadd { background: var(--accent-soft); border-color: transparent; scroll-margin-top: var(--sp-10); }
.quickadd > .fold__summary { color: var(--accent-on-soft); font-weight: 700; }
.quickadd > .fold__body { background: var(--surface); }

/* Rencontre ouverte en édition, à sa place dans la chronologie. */
.tlentry--edit .tlentry__card { display: grid; gap: var(--sp-3); border-color: var(--accent); }
.photogrid--sm { grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); gap: var(--sp-2); }

.form--tight { gap: var(--sp-3); }
.uploader__drop--sm { padding: var(--sp-4) var(--sp-3); }
.uploader__drop--sm svg { width: 24px; height: 24px; }

/* Description tronquée + « Lire la suite ».
   Sans JavaScript le texte reste coupé à cinq lignes : la chronologie garde
   sa lisibilité, et le texte entier reste accessible dans le repli
   « Modifier ». Avec JavaScript, un vrai <button> est ajouté — et seulement
   si le texte déborde réellement. */
.prose--clamp {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 5;
  line-clamp: 5;
  overflow: hidden;
}
.prose--clamp.is-open { display: block; -webkit-line-clamp: unset; line-clamp: unset; }
.readmore {
  align-self: start;
  min-height: 32px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent);
  font: inherit;
  font-size: var(--fs-md);
  font-weight: 650;
  cursor: pointer;
  text-align: left;
}

/* Saisie d'une note en étoiles, sans JavaScript (cf. macro rating_pick). */
.ratingpick { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.starpick { display: flex; flex-direction: row-reverse; justify-content: flex-end; }
.starpick__radio { position: absolute; width: 1px; height: 1px; opacity: 0; }
.starpick__star {
  display: grid;
  place-items: center;
  width: var(--tap); height: var(--tap);
  cursor: pointer;
}
.starpick__star svg { width: 28px; height: 28px; stroke: var(--star-off); fill: none; transition: transform .12s ease; }
.starpick__star:active svg { transform: scale(1.15); }
/* L'étoile cochée et toutes celles qui la précèdent visuellement (elles la
   suivent dans le DOM, l'ordre est inversé) s'allument. */
.starpick__radio:checked ~ .starpick__star svg { stroke: var(--star); fill: var(--star); }
.starpick__radio:focus-visible + .starpick__star { outline: 2px solid var(--accent); outline-offset: -4px; border-radius: var(--r-xs); }
.starpick__none {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  min-height: var(--tap); padding: 0 var(--sp-3);
  border-radius: var(--r-pill);
  font-size: var(--fs-sm); color: var(--text-soft);
  cursor: pointer;
}
.starpick__none:has(input:checked) { background: var(--surface-2); color: var(--text); font-weight: 600; }
.starpick__none input { accent-color: var(--accent); width: 18px; height: 18px; }

/* --------------------------------------------------------------------------
   26. Administration — un espace à part
   L'accent bascule sur --admin pour TOUT l'écran : boutons, puces, focus,
   onglet actif. On ne peut pas confondre « je gère des comptes » et « je
   consulte mon carnet ».
   -------------------------------------------------------------------------- */
.theme-admin {
  --accent: var(--admin);
  --accent-strong: var(--admin-strong);
  --accent-soft: var(--admin-soft);
  --accent-on-soft: var(--admin-on-soft);
  --on-accent: var(--on-admin);
}
.adminbar {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) max(var(--sp-4), var(--safe-l));
  background: var(--admin-soft);
  color: var(--admin-on-soft);
  font-size: var(--fs-md);
  font-weight: 650;
  border-bottom: 2px solid var(--admin);
}
.adminbar__inner {
  max-width: var(--page-max);
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 2px var(--sp-2);
  width: 100%;
  min-width: 0;
}
.adminbar svg { width: 18px; height: 18px; stroke: currentColor; flex: none; }
/* Le libellé ne se coupe jamais ; c'est la précision qui passe à la ligne. */
.adminbar__label { white-space: nowrap; }
.adminbar__hint { font-weight: 500; font-size: var(--fs-sm); }
/* Le lien vers l'administration garde sa couleur propre, même dans la barre
   de navigation d'un écran ordinaire. */
.tabbar__item--admin { color: var(--admin); }

.userlist { display: grid; gap: var(--sp-2); }
.userrow {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  box-shadow: var(--shadow-1);
  min-width: 0;
}
.userrow > * { min-width: 0; }
/* Un compte suspendu se signale par un fond creux et une pastille, pas par
   une opacité qui casserait le contraste. */
.userrow--off { background: var(--surface-2); box-shadow: none; }
.userrow .avatar { flex: none; --avatar-size: 44px; }
.userrow__body { flex: 1; min-width: 0; display: grid; gap: 3px; }
.userrow__name { font-size: var(--fs-lg); font-weight: 650; }
.userrow__link { color: inherit; text-decoration: none; }
.userrow__link::after { content: ""; position: absolute; inset: 0; border-radius: var(--r); }
.userrow__id {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--fs-md);
  color: var(--text-soft);
  overflow-wrap: anywhere;
}
.userrow__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; }
.userrow__last { font-size: var(--fs-xs); color: var(--text-soft); }
.userrow__go { flex: none; width: 20px; height: 20px; stroke: var(--text-soft); }

.rolebadge {
  display: inline-flex;
  align-items: center;
  padding: 2px var(--sp-2);
  border-radius: var(--r-pill);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: .02em;
}
.rolebadge--admin { background: var(--admin-soft); color: var(--admin-on-soft); }
.rolebadge--user { background: var(--surface-2); color: var(--text-soft); }
.pill-state--danger { background: var(--danger-soft); color: var(--danger-on-soft); }
/* Entrée vers l'administration depuis les réglages : même gabarit que les
   autres lignes, mais à l'accent --admin. */
.setrow--admin .setrow__icon { stroke: var(--admin); }
.setrow--admin .setrow__title { color: var(--admin-on-soft); }

/* Journal des actions d'administration. */
.log { list-style: none; display: grid; }
.logrow {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 2px var(--sp-3);
  padding: var(--sp-2) 0;
  font-size: var(--fs-md);
}
.logrow + .logrow { border-top: 1px solid var(--border); }
.logrow__at { color: var(--text-soft); font-variant-numeric: tabular-nums; white-space: nowrap; }
.logrow__what { min-width: 0; overflow-wrap: anywhere; }
.logrow__target { color: var(--text-soft); }
.logrow__details { display: block; font-size: var(--fs-sm); color: var(--text-soft); }
.logrow__who { grid-column: 2; font-size: var(--fs-xs); color: var(--text-soft); }

/* Bloc « ce qui va disparaître » : la suppression d'un compte est la seule
   action de l'application qui détruit les données d'autrui. */
.dangerbox {
  display: grid;
  gap: var(--sp-3);
  padding: var(--sp-4);
  background: var(--surface);
  border: 1.5px solid var(--danger);
  border-radius: var(--r);
}
.dangerbox > * { min-width: 0; }
.dangerbox__title { display: flex; align-items: center; gap: var(--sp-2); font-weight: 700; color: var(--danger-on-soft); }
.dangerbox__title svg { width: 20px; height: 20px; stroke: currentColor; flex: none; }
/* Liste à puces d'un bloc explicatif (zone dangereuse, mot de passe unique). */
.bullets { margin: 0; padding-left: 1.25em; display: grid; gap: 4px; font-size: var(--fs-md); list-style: disc outside; }
.bullets li::marker { color: var(--text-soft); }

/* Mot de passe provisoire : affiché une seule fois, jamais réaffichable. */
.secret { display: grid; gap: var(--sp-4); }
.secret__value {
  margin: 0;
  padding: var(--sp-4) var(--sp-3);
  border-radius: var(--r);
  background: var(--surface-2);
  border: 1.5px dashed var(--line);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--fs-xl);
  font-weight: 700;
  letter-spacing: .08em;
  text-align: center;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
  -webkit-user-select: all;
  user-select: all;
}
.secret__who { font-size: var(--fs-md); color: var(--text-soft); text-align: center; }

/* --------------------------------------------------------------------------
   22. Tablette et grands écrans (≥ 768px)
   La mise en page mobile reste la base ; on gagne en respiration, pas en densité.
   -------------------------------------------------------------------------- */
@media (min-width: 768px) {
  :root { --tabbar-h: 64px; }

  .page { padding: var(--sp-5) var(--sp-5); padding-bottom: calc(var(--sp-10) + var(--tabbar-h) + var(--safe-b)); }
  .list { grid-template-columns: 1fr 1fr; gap: var(--sp-3); }
  .listhead { grid-column: 1 / -1; }
  .empty { grid-column: 1 / -1; }
  .card__media { width: 84px; height: 84px; }
  .card__media .avatar { --avatar-size: 84px; }

  .ident { margin: var(--sp-4) var(--sp-5) 0; }
  .gallery { grid-auto-columns: 132px; }
  .uploader__previews { grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); }
  .toasts { bottom: calc(var(--tabbar-h) + var(--safe-b) + var(--sp-4)); }
}

/* --------------------------------------------------------------------------
   22 bis. Très petits téléphones (≤ 374px, iPhone SE)
   Rien n'est retiré : les blocs trop larges passent simplement à la ligne.
   -------------------------------------------------------------------------- */
@media (max-width: 374px) {
  :root { --page-max: 100%; }
  .rating { justify-content: center; }
  .rating__label { flex: 1 0 100%; }
  .rating .stars-wrap { justify-content: center; width: 100%; }
  .ident { margin-left: var(--sp-2); margin-right: var(--sp-2); }
  .contact { gap: var(--sp-2); padding-left: var(--sp-2); }
}

/* --------------------------------------------------------------------------
   23. Préférences système
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

@media (prefers-contrast: more) {
  :root { --border: var(--line); }
  .card, .panel, .fold, .setgroup__body { border-width: 1.5px; }
}

/* Impression : le contenu, rien d'autre. */
@media print {
  .topbar, .tabbar, .actionbar, .toasts, .lightbox, .skip { display: none !important; }
  body { background: #fff; color: #000; }
  .page { padding: 0; }
}

/* --------------------------------------------------------------------------
   Lapins : fiches signalées, et la page commune à tous les comptes
   -------------------------------------------------------------------------- */
/* Serre-tête à oreilles posé sur la photo de profil. Les oreilles débordent
   au-dessus : le conteneur leur réserve la place, car la vignette
   (overflow: hidden) les rognerait. */
.lapinpic {
  position: relative;
  display: inline-block;
  flex: none;
  padding-top: calc(var(--avatar-size, 48px) * .42);
  line-height: 0;
}
.lapinpic--md { --avatar-size: 72px; }
.lapinpic__ears {
  position: absolute;
  left: 50%;
  top: 0;
  transform: translateX(-50%);
  width: calc(var(--avatar-size, 48px) * .95);
  height: auto;
  overflow: visible;
  pointer-events: none;
}
.lapinpic__ear { fill: var(--lapin-ear); stroke: var(--lapin-edge); stroke-width: 1.4; }
.lapinpic__inner { fill: var(--lapin-inner); }
.lapinpic__band { fill: none; stroke: var(--lapin-ear); stroke-width: 3.2; stroke-linecap: round; }

/* Pastille « Lapin » : carte de la liste et bloc identité de la fiche. */
.lapinpill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 1px 9px 1px 6px;
  border-radius: var(--r-pill);
  background: var(--lapin-soft);
  color: var(--lapin-on-soft);
  font-size: var(--fs-xs);
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
}
.lapinpill svg { width: 15px; height: 15px; stroke: currentColor; fill: none; }
.card .lapinpill { position: relative; z-index: 1; }

.btn--lapin { background: var(--lapin); color: var(--surface); border-color: var(--lapin); }
.lapinbox { display: grid; gap: var(--sp-2); border-color: color-mix(in srgb, var(--lapin) 35%, var(--border)); }
.lapinbox > * { min-width: 0; }
.lapinbox__head { display: flex; align-items: center; gap: var(--sp-2); color: var(--lapin-on-soft); font-weight: 650; }
.lapinbox__head svg { width: 20px; height: 20px; flex: none; }

.lapincard {
  display: grid;
  gap: var(--sp-2);
  padding: var(--sp-3);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  box-shadow: var(--shadow-1);
}
.lapincard > * { min-width: 0; }
.lapincard__head { display: flex; align-items: flex-end; gap: var(--sp-3); }
.lapincard__pic { flex: none; }
.lapincard .ident__photo { border-radius: var(--r); }
.lapincard__who { flex: 1; min-width: 0; padding-bottom: 2px; }
.lapincard__name { font-size: var(--fs-lg); font-weight: 650; overflow-wrap: anywhere; }
.lapincard__motif { margin: 0; padding-left: var(--sp-2); border-left: 3px solid var(--lapin); overflow-wrap: anywhere; }
.lapincard__foot { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--sp-1) var(--sp-3); margin: 0; }
.lapincard__foot { align-items: center; }
.lapincard__by { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) var(--sp-2); min-width: 0; }

/* --------------------------------------------------------------------------
   Lieux : communs à tous les comptes, avec leurs avis
   -------------------------------------------------------------------------- */
.card--lieu .card__name { padding-right: 0; }
.card__addr { margin: 0; color: var(--text-soft); font-size: var(--fs-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.card__media .avatar svg { width: 30px; height: 30px; stroke: currentColor; fill: none; }

.lieuhead > * { min-width: 0; }
.lieuhead .ident__name { overflow-wrap: anywhere; }
.lieuhead__score { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-1) var(--sp-2); }

.avis { display: grid; gap: var(--sp-2); }
.avis > * { min-width: 0; }
.avis--mien { border-color: color-mix(in srgb, var(--accent) 40%, var(--border)); }
.avis__head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--sp-1) var(--sp-3); }
.avis__head strong { overflow-wrap: anywhere; }
.avis .prose { margin: 0; overflow-wrap: anywhere; }
.avis__foot { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-1) var(--sp-3); }
.avis__foot > :first-child { margin-right: auto; }
.avis__foot form { display: flex; }
button.secedit { border: 0; background: none; font: inherit; font-weight: 600; font-size: var(--fs-sm); cursor: pointer; }
.secedit--danger { color: var(--danger); }
.secedit--danger:hover { background: var(--danger-soft); }

/* --------------------------------------------------------------------------
   Aide : le guide d'utilisation (aide.html)
   Texte long lu au téléphone : interlignage généreux, titres nets, ancres
   qui ne passent pas sous la barre du haut.
   -------------------------------------------------------------------------- */
.aide { display: grid; gap: var(--sp-8); line-height: 1.55; }
.aide__lead { font-size: var(--fs-lg); color: var(--text-soft); }
.aide__sec { display: grid; gap: var(--sp-3); scroll-margin-top: calc(var(--sp-10) + var(--sp-10) + var(--safe-t, 0px)); }
.aide__h { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-xl); }
.aide__h .icon { flex: none; width: 22px; height: 22px; stroke: var(--accent); }
.aide__h3 { margin-top: var(--sp-2); font-size: var(--fs-lg); font-weight: 650; }
.aide__note { font-size: var(--fs-md); color: var(--text-soft); }
.aide__url { overflow-wrap: anywhere; }
.aide p, .aide li { overflow-wrap: break-word; }

/* Sommaire : liens d'ancre numérotés, assez hauts pour le pouce. */
.aide__toc { display: grid; gap: var(--sp-2); }
.aide__toclist { list-style: decimal; padding-left: var(--sp-6); }
.aide__toclist li::marker { color: var(--text-soft); font-size: var(--fs-md); }
.aide__toclist a { display: inline-block; padding: 6px 0; font-weight: 600; text-decoration: none; }
.aide__toclist a:hover { text-decoration: underline; }

/* Listes à puces du texte courant (la base les remet à zéro). */
.aide__list { display: grid; gap: var(--sp-2); list-style: disc; padding-left: var(--sp-5); }
.aide__list li::marker { color: var(--text-soft); }

/* Onglets de la barre basse : l'icône, puis ce qu'elle ouvre. */
.aide__tabs { display: grid; gap: var(--sp-2); }
.aide__tabs li { display: flex; align-items: flex-start; gap: var(--sp-3); }
.aide__tabs .icon { flex: none; width: 22px; height: 22px; margin-top: 1px; stroke: var(--text-soft); }

/* Qui voit quoi : deux encadrés, côte à côte dès qu'il y a la place. */
.aide__who { display: grid; gap: var(--sp-3); }
@media (min-width: 560px) { .aide__who { grid-template-columns: 1fr 1fr; } }
.aide__who .panel { display: grid; gap: var(--sp-2); align-content: start; }
.aide__whohead { display: flex; align-items: center; gap: var(--sp-2); font-weight: 700; }
.aide__whohead .icon { flex: none; width: 20px; height: 20px; stroke: var(--accent); }

/* Questions fréquentes : des replis empilés. */
.aide__faq { display: grid; gap: var(--sp-2); }
.aide__faq .fold__summary { padding-top: var(--sp-2); padding-bottom: var(--sp-2); line-height: 1.35; }
