/* ==========================================================================
   ALVYCA — Système de design
   --------------------------------------------------------------------------
   Apparence sombre inspirée des interfaces Apple : gris neutres légèrement
   bleutés, séparateurs translucides, surfaces empilées par élévation,
   un seul accent.

   Trois états de thème :
     :root                        → clair (défaut)
     prefers-color-scheme: dark   → sombre si l'OS le demande
     [data-theme="dark|light"]    → choix explicite de l'utilisateur

   Deux réglages d'affichage, portés par l'attribut racine :
     [data-scale="compact|normal|grand|xl"]   taille du texte et des contrôles
     [data-width="normal|large|full"]         largeur utile de la page

   Tout ce qui doit suivre la taille est en rem ; seuls les traits, rayons
   et ombres restent en px pour ne pas s'épaissir avec l'échelle.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Échelle
   -------------------------------------------------------------------------- */

:root { --ui-scale: 1; --page-max: 1120px; }

:root[data-scale="compact"] { --ui-scale: .9375; }   /* 15 px */
:root[data-scale="normal"]  { --ui-scale: 1; }       /* 16 px */
:root[data-scale="grand"]   { --ui-scale: 1.0938; }  /* 17.5 px */
:root[data-scale="xl"]      { --ui-scale: 1.1875; }  /* 19 px */

/*
 * Trois largeurs qui se distinguent vraiment.
 *
 * Elles valaient 1360, 1680 et « aucune ». Sur un portable de 1440 px de
 * large — la machine de tout le monde ici — les trois donnaient le même
 * écran : la fenêtre est plus étroite que le premier palier, donc aucun des
 * plafonds ne s'applique. Le réglage existait sans jamais rien changer.
 *
 * Les paliers passent sous les tailles d'écran courantes : 1120 laisse
 * respirer les colonnes sur un 13 pouces, 1440 remplit un portable, « aucune »
 * occupe un écran externe. Sur un moniteur très large, « large » garde une
 * ligne de lecture raisonnable au lieu d'étirer les tableaux à l'infini.
 */
:root[data-width="normal"] { --page-max: 1120px; }
:root[data-width="large"]  { --page-max: 1440px; }
:root[data-width="full"]   { --page-max: none; }

/* --------------------------------------------------------------------------
   Accent — six teintes, chacune déclinée pour fond clair et fond sombre.
   Les valeurs claires visent 4.5:1 sur blanc ; les sombres, 4.5:1 sur #202024.
   Elles surchargent --accent* défini plus bas, d'où le placement ici et la
   reprise dans les blocs de thème.
   -------------------------------------------------------------------------- */

/* Les variables --a-* sont injectées par le serveur (voir Auth::accentVars) :
   la teinte est ajustée par thème pour tenir 4,5:1 de contraste. Seules les
   pastilles d'aperçu du sélecteur restent en dur ici. */

:root {
  --acc-orange:   #e2601c;
  --acc-bleu:     #2f74e8;
  --acc-indigo:   #6b58e8;
  --acc-vert:     #1c9a5e;
  --acc-prune:    #c42a7d;
  --acc-graphite: #5c5c66;
}

html { font-size: calc(16px * var(--ui-scale)); -webkit-text-size-adjust: 100%; }

/* --------------------------------------------------------------------------
   2. Jetons
   -------------------------------------------------------------------------- */

:root {
  /*
   * Annonce le thème aux contrôles natifs — ascenseurs, listes déroulantes,
   * sélecteurs de date. Sans elle ils suivent le réglage du système : un
   * thème clair choisi dans l'application sur un système sombre donnait des
   * ascenseurs noirs et des champs sombres au milieu d'une page blanche.
   */
  color-scheme: light;

  /* Fonds, du plus profond au plus élevé */
  --bg:            #f5f5f7;
  --bg-sunken:     #ececee;
  --surface:       #ffffff;
  --surface-2:     #f2f2f4;
  --surface-3:     #e6e6e9;
  --surface-hover: #f0f0f2;

  /* Texte — contrastes vérifiés sur --surface */
  --text:      #1d1d1f;   /* 15.8:1 */
  --text-2:    #45454a;   /* 9.5:1  */
  --text-3:    #6e6e76;   /* 5.2:1  */
/* Le plein d'accentuation ne change pas avec le thème, et son encre
     est choisie par la couleur elle-même — blanc ou encre sombre selon
     celle qui porte (voir App\Color::fill). */
  --accent-fill:   var(--a-fill, #e2601c);
  --text-on-accent: var(--a-on, #16161a);

  /* Séparateurs translucides : se posent sur n'importe quelle surface */
  --sep:        rgba(0, 0, 0, .11);
  --sep-strong: rgba(0, 0, 0, .20);
  --ring:       rgba(0, 0, 0, .06);

  /* Accent — orange ALVYCA par défaut, remplaçable via [data-accent] */
  --accent:       var(--a-l,  #b8400b);
  --accent-hover: var(--a-lh, #94330a);
  --accent-soft:  rgba(var(--a-rgb, 184, 64, 11), .10);
  --accent-ring:  rgba(var(--a-rgb, 184, 64, 11), .32);

  /* Sémantique — indépendante de l'accent */
  --green:  #17693f;  --green-soft:  rgba(23, 105, 63, .12);
  --amber:  #8a5c00;  --amber-soft:  rgba(138, 92, 0, .13);
  --red:    #ab221b;  --red-soft:    rgba(171, 34, 27, .11);
  --rose:   #99105a;  --rose-soft:   rgba(153, 16, 90, .11);
  --blue:   #1a56c4;  --blue-soft:   rgba(26, 86, 196, .11);
  --indigo: #4638c4;  --indigo-soft: rgba(70, 56, 196, .11);
  --cyan:   #046074;  --cyan-soft:   rgba(4, 96, 116, .12);
  --orange: #a94c07;  --orange-soft: rgba(169, 76, 7, .12);
  --slate:  #53585f;  --slate-soft:  rgba(83, 88, 95, .12);
  --neutral:#63636a;  --neutral-soft:rgba(99, 99, 106, .12);
  /* Texte posé sur un plein de la palette : les nuances claires du thème
     clair sont foncées, celles du thème sombre sont claires. */
  --on-palette: #ffffff;

  --shadow-1: 0 1px 2px rgba(0,0,0,.05), 0 1px 3px rgba(0,0,0,.04);
  --shadow-2: 0 2px 6px rgba(0,0,0,.06), 0 8px 24px -12px rgba(0,0,0,.16);
  --shadow-3: 0 8px 32px -8px rgba(0,0,0,.20), 0 2px 8px rgba(0,0,0,.08);

  /* Typographie */
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Inter",
          "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;

  --fs-xs:   .75rem;
  --fs-sm:   .8125rem;
  --fs-md:   .875rem;
  --fs-base: .9375rem;
  --fs-lg:   1.0625rem;
  --fs-xl:   1.3125rem;
  --fs-2xl:  1.75rem;

  /*
   * Icônes de statut d'occupation et de type de logement.
   *
   * Elles servent sur la fiche client et dans les tableaux : définies ici,
   * elles n'existent qu'une fois. Le tracé est noir parce qu'il n'est jamais
   * peint tel quel — il sert de masque, et c'est le fond qui donne la
   * couleur, ce qui laisse chaque compte garder son accent.
   */
    --i-vide: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round'><path d='M9.1 9a3 3 0 1 1 4.5 2.6c-.9.5-1.6 1.3-1.6 2.4'/><path d='M12 18h.01'/></svg>");
    --i-cle:  url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><circle cx='7.5' cy='15.5' r='4.5'/><path d='m10.7 12.3 8.3-8.3M16 5l3 3M14 7l3 3'/></svg>");
    --i-sign: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='M3 16c3-6 5 3 8-3s4 2 7-2'/><path d='M3 21h18'/></svg>");
    --i-buro: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='M4 21V6a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v15'/><path d='M14 10h4a2 2 0 0 1 2 2v9'/><path d='M2 21h20M8 8h2M8 12h2M8 16h2'/></svg>");
    --i-toit: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='m3 10 9-7 9 7v10a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1z'/><path d='M9 21v-6h6v6'/></svg>");
    --i-imm:  url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><rect x='5' y='3' width='14' height='18' rx='1'/><path d='M9 7h2M13 7h2M9 11h2M13 11h2M10 21v-3h4v3'/></svg>");

  /* Contrôles */
  --h-ctl:    2.375rem;
  --h-ctl-sm: 1.875rem;
  --h-ctl-lg: 2.875rem;

  /* Espacement */
  --sp-1: .25rem; --sp-2: .5rem;  --sp-3: .75rem;
  --sp-4: 1rem;   --sp-5: 1.5rem; --sp-6: 2rem;

  /* Rayons et navigation — en px, ne suivent pas l'échelle */
  --r-sm: 6px;  --r: 10px;  --r-lg: 14px;  --r-xl: 20px;  --r-pill: 999px;
  --nav-h: 3.5rem;

  --ease: cubic-bezier(.4, 0, .2, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  /*
   * Courbe des entrées de page.
   *
   * --ease-out démarre trop vite pour un long trajet : à 340 ms, une barre
   * qui traverse toute sa hauteur était déjà arrivée avant qu'on la voie
   * partir. Celle-ci — la courbe des feuilles d'iOS — laisse le mouvement
   * s'installer puis freine longuement : on lit le geste au lieu de le
   * deviner, sans allonger la durée pour autant.
   */
  --ease-entree: cubic-bezier(.32, .72, 0, 1);
}

/* Sombre — si l'OS le demande, sauf choix explicite « clair » */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    /* Gris très sombres, légèrement bleutés — la profondeur vient de
       l'empilement des surfaces, pas d'un noir absolu qui écrase tout. */
    --bg:            #161619;
    --bg-sunken:     #0f0f11;
    --surface:       #202024;
    --surface-2:     #2a2a2f;
    --surface-3:     #35353b;
    --surface-hover: #26262b;

    --text:   #f5f5f7;
    --text-2: #c2c2c7;
    --text-3: #9a9aa0;
    /*
     * Encre sombre sur l'accentuation, et non blanc.
     *
     * Les teintes du thème sombre sont éclaircies pour rester lisibles
     * EN TEXTE sur le fond de la page ; du blanc posé DESSUS retombe
     * alors sous le seuil — 2,2:1 pour le vert. L'encre passe partout
     * de 5,1 à 8,1:1. C'est la même logique que les boutons pleins
     * d'iOS en thème sombre.
     */
/* Le plein d'accentuation ne change pas avec le thème, et son encre
       est choisie par la couleur elle-même — blanc ou encre sombre selon
       celle qui porte (voir App\Color::fill). */
    --accent-fill:   var(--a-fill, #e2601c);
    --text-on-accent: var(--a-on, #16161a);

    --sep:        rgba(255, 255, 255, .11);
    --sep-strong: rgba(255, 255, 255, .20);
    --ring:       rgba(255, 255, 255, .08);

    --accent:       var(--a-d,  #ff8a4d);
    --accent-hover: var(--a-dh, #ffa471);
    --accent-soft:  rgba(var(--a-rgb-d, 255, 138, 77), .17);
    --accent-ring:  rgba(var(--a-rgb-d, 255, 138, 77), .42);

    --green:  #55d98c;  --green-soft:  rgba(85, 217, 140, .16);
    --amber:  #ffc94d;  --amber-soft:  rgba(255, 201, 77, .16);
    --red:    #ff7a72;  --red-soft:    rgba(255, 122, 114, .16);
    --rose:   #ff8ac0;  --rose-soft:   rgba(255, 138, 192, .16);
    --blue:   #74b0ff;  --blue-soft:   rgba(116, 176, 255, .16);
    --indigo: #b3a6ff;  --indigo-soft: rgba(179, 166, 255, .16);
    --cyan:   #5ad9e8;  --cyan-soft:   rgba(90, 217, 232, .16);
    --orange: #ffab5c;  --orange-soft: rgba(255, 171, 92, .16);
    --slate:  #adadb3;  --slate-soft:  rgba(173, 173, 179, .16);
    --neutral:#a4a4aa;  --neutral-soft:rgba(164, 164, 170, .16);
    --on-palette: #16161a;

    --shadow-1: 0 1px 2px rgba(0,0,0,.5);
    --shadow-2: 0 2px 8px rgba(0,0,0,.5), 0 12px 32px -16px rgba(0,0,0,.8);
    --shadow-3: 0 12px 48px -12px rgba(0,0,0,.75), 0 2px 8px rgba(0,0,0,.5);
  }
}

/* Sombre — choix explicite, gagne aussi sur un OS clair */
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg:            #161619;
  --bg-sunken:     #0f0f11;
  --surface:       #202024;
  --surface-2:     #2a2a2f;
  --surface-3:     #35353b;
  --surface-hover: #26262b;

  --text:   #f5f5f7;
  --text-2: #c2c2c7;
  --text-3: #9a9aa0;
/* Le plein d'accentuation ne change pas avec le thème, et son encre
     est choisie par la couleur elle-même — blanc ou encre sombre selon
     celle qui porte (voir App\Color::fill). */
  --accent-fill:   var(--a-fill, #e2601c);
  --text-on-accent: var(--a-on, #16161a);

  --sep:        rgba(255, 255, 255, .11);
  --sep-strong: rgba(255, 255, 255, .20);
  --ring:       rgba(255, 255, 255, .08);

  --accent:       var(--a-d,  #ff8a4d);
  --accent-hover: var(--a-dh, #ffa471);
  --accent-soft:  rgba(var(--a-rgb-d, 255, 138, 77), .17);
  --accent-ring:  rgba(var(--a-rgb-d, 255, 138, 77), .42);

  --green:  #55d98c;  --green-soft:  rgba(85, 217, 140, .16);
  --amber:  #ffc94d;  --amber-soft:  rgba(255, 201, 77, .16);
  --red:    #ff7a72;  --red-soft:    rgba(255, 122, 114, .16);
  --rose:   #ff8ac0;  --rose-soft:   rgba(255, 138, 192, .16);
  --blue:   #74b0ff;  --blue-soft:   rgba(116, 176, 255, .16);
  --indigo: #b3a6ff;  --indigo-soft: rgba(179, 166, 255, .16);
  --cyan:   #5ad9e8;  --cyan-soft:   rgba(90, 217, 232, .16);
  --orange: #ffab5c;  --orange-soft: rgba(255, 171, 92, .16);
  --slate:  #adadb3;  --slate-soft:  rgba(173, 173, 179, .16);
  --neutral:#a4a4aa;  --neutral-soft:rgba(164, 164, 170, .16);
  --on-palette: #16161a;

  --shadow-1: 0 1px 2px rgba(0,0,0,.5);
  --shadow-2: 0 2px 8px rgba(0,0,0,.5), 0 12px 32px -16px rgba(0,0,0,.8);
  --shadow-3: 0 12px 48px -12px rgba(0,0,0,.75), 0 2px 8px rgba(0,0,0,.5);
}

/* --------------------------------------------------------------------------
   3. Base
   -------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: var(--fs-base);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  letter-spacing: -.01em;
}

h1, h2, h3, h4 { margin: 0; font-weight: 600; letter-spacing: -.022em; line-height: 1.22; text-wrap: balance; }
h1 { font-size: var(--fs-2xl); }
h2 { font-size: var(--fs-xl); }
h3 { font-size: var(--fs-lg); }
p  { margin: 0; }

a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-hover); }

:where(a, button, input, select, textarea, [tabindex], [contenteditable]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.num  { font-variant-numeric: tabular-nums; }

::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--sep-strong); border-radius: var(--r-pill);
  border: 3px solid transparent; background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--text-3); background-clip: content-box; }

/* --------------------------------------------------------------------------
   4. Mise en page
   -------------------------------------------------------------------------- */

.page        { max-width: var(--page-max); margin: 0 auto; padding: var(--sp-5) var(--sp-5) 4rem; }
.page-narrow { max-width: 52rem;           margin: 0 auto; padding: var(--sp-5) var(--sp-5) 4rem; }
.page-wide   { max-width: none;            margin: 0;      padding: var(--sp-5) var(--sp-5) 4rem; }
@media (max-width: 640px) { .page, .page-narrow, .page-wide { padding: var(--sp-4) var(--sp-3) 3rem; } }

.stack   { display: flex; flex-direction: column; gap: var(--sp-4); }
.stack-s { display: flex; flex-direction: column; gap: var(--sp-2); }
.stack-l { display: flex; flex-direction: column; gap: var(--sp-5); }
.row     { display: flex; align-items: center; gap: var(--sp-3); }
.row-wrap{ display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.spread  { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); }
.spread-bottom { align-items: flex-end; }
.grow    { flex: 1 1 auto; min-width: 0; }
.right   { margin-left: auto; }
.hide    { display: none !important; }
/* Libellés qui n'apparaissent qu'en carte : sur un tableau large, l'icône
   seule suffit ; sur téléphone, un bouton pleine largeur doit se nommer. */
.only-mobile { display: none; }
.truncate{ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.page-head { display: flex; flex-direction: column; gap: var(--sp-1); margin-bottom: var(--sp-5); }
.page-head .sub { color: var(--text-3); font-size: var(--fs-md); }

/* Le volume d'éléments est ce qu'on cherche en arrivant sur une liste :
   il porte la couleur d'accentuation, le reste du sous-titre reste gris. */
.count-accent { color: var(--accent); font-weight: 600; font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------------------
   Sort d'une date d'étape
   Quand on quitte une étape datée, on demande ce qu'est devenue la date.
   Les réponses sont des lignes cliquables plutôt que des boutons de pied :
   chacune porte sa conséquence en toutes lettres, et on lit la liste au
   lieu de déchiffrer trois libellés serrés côte à côte.
   -------------------------------------------------------------------------- */

.date-recap {
  display: flex; align-items: baseline; gap: var(--sp-2); flex-wrap: wrap;
  padding: var(--sp-3) var(--sp-4); margin-bottom: var(--sp-4);
  background: var(--surface-2); border-radius: var(--r);
  border-left: 3px solid var(--accent);
}
.date-recap b { color: var(--text); font-size: var(--fs-base); }
.date-recap span { color: var(--text-3); font-size: var(--fs-sm); }

/* --------------------------------------------------------------------------
   Fenêtre modale — centrée sur écran large, feuille montante sur téléphone
   (voir la surcharge dans le bloc mobile plus bas).

   Ces règles vivaient recopiées dans chaque page qui en avait besoin ; elles
   sont ici pour qu'une page nouvelle n'ait qu'à poser le balisage.
   -------------------------------------------------------------------------- */

.modal-bg {
  position: fixed; inset: 0; z-index: 1300; background: rgba(0, 0, 0, .45);
  backdrop-filter: blur(3px);
  display: none; align-items: center; justify-content: center; padding: var(--sp-5);
}
.modal-bg.on { display: flex; }
.modal {
  background: var(--bg); border: 1px solid var(--sep); border-radius: var(--r-lg);
  box-shadow: var(--shadow-3); width: min(520px, 100%); max-height: 86vh;
  display: flex; flex-direction: column; overflow: hidden;
}
.modal-hd { padding: var(--sp-4) var(--sp-5); border-bottom: 1px solid var(--sep); background: var(--surface); }
.modal-bd { padding: var(--sp-5); overflow-y: auto; display: flex; flex-direction: column; gap: var(--sp-4); }
.modal-ft {
  padding: var(--sp-3) var(--sp-5); border-top: 1px solid var(--sep);
  background: var(--surface); display: flex; gap: var(--sp-2); justify-content: flex-end;
}

/* Liste de choix d'une feuille : filtres, onglets, actions groupées. */
.filter-list { display: flex; flex-direction: column; gap: var(--sp-1); }
.filter-list button {
  display: flex; align-items: center; gap: var(--sp-3); width: 100%;
  padding: var(--sp-3) var(--sp-4); text-align: left;
  background: transparent; color: var(--text);
  border: 0; border-radius: var(--r); font: inherit; cursor: pointer;
  min-height: 2.75rem;
  transition: background .12s var(--ease);
}
.filter-list button:hover { background: var(--surface-2); }
.filter-list button.on { background: var(--accent-soft); color: var(--accent); }
.filter-list button b { font-weight: 500; flex: 1; min-width: 0; }
.filter-list button.on b { font-weight: 600; }
.filter-list .pt { width: .6rem; height: .6rem; border-radius: 50%; flex: none; }
.filter-list .n {
  font-size: var(--fs-sm); font-weight: 600; color: var(--text-3);
  font-variant-numeric: tabular-nums; flex: none;
}
.filter-list button.on .n { color: var(--accent); }

.outcome-list { display: flex; flex-direction: column; gap: var(--sp-2); }
.outcome-list button {
  display: flex; flex-direction: column; gap: 2px; width: 100%;
  padding: var(--sp-3) var(--sp-4); text-align: left;
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--sep); border-radius: var(--r);
  font: inherit; cursor: pointer;
  transition: border-color .12s var(--ease), background .12s var(--ease);
}
.outcome-list button:hover { border-color: var(--accent); background: var(--surface-3); }
.outcome-list button b { font-size: var(--fs-base); font-weight: 600; }
.outcome-list button span { font-size: var(--fs-sm); color: var(--text-3); }

/* Verdicts relus dans l'historique du parcours. */
.tl-verdict {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--fs-xs); font-weight: 600;
  padding: 1px 7px; border-radius: var(--r-pill); white-space: nowrap;
}
.tl-verdict[data-o="tenue"]    { background: var(--green-soft); color: var(--green); }
.tl-verdict[data-o="annulee"]  { background: var(--red-soft);   color: var(--red); }
.tl-verdict[data-o="reportee"] { background: var(--amber-soft); color: var(--amber); }
.tl-verdict[data-o="attente"]  { background: var(--blue-soft);  color: var(--blue); }

/* --------------------------------------------------------------------------
   Bandeau de régie
   Un administrateur qui travaille sur ses télépros doit le voir au premier
   coup d'œil : la barre porte la couleur d'accentuation sur le flanc, et
   reste collée sous la barre de navigation pendant le défilement. Elle ne
   contient que le choix du télépro et la sortie — l'avatar de la barre du
   haut dit déjà dans quelle vue on est.
   -------------------------------------------------------------------------- */

/* La barre prend la largeur de ce qu'elle contient, et se pose au milieu :
   deux télépros ne justifient pas un bandeau d'un mètre de long, et une
   régie de dix le remplira d'elle-même. */
.focus-bar {
  position: sticky; top: var(--nav-h); z-index: 400;
  display: flex; align-items: center; gap: var(--sp-4);
  width: fit-content; max-width: 100%;
  margin: 0 auto var(--sp-4); padding: var(--sp-2) var(--sp-3);
  background: var(--accent-soft);
  border: 1px solid var(--accent-ring);
  border-left: 3px solid var(--accent);
  border-radius: var(--r);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
}

.focus-tabs { display: flex; align-items: center; gap: 2px; flex-wrap: wrap; justify-content: center; }
.focus-tabs a {
  padding: .3rem var(--sp-3); border-radius: var(--r-pill);
  font-size: var(--fs-sm); font-weight: 500; color: var(--text-2); text-decoration: none;
  transition: background .12s var(--ease), color .12s var(--ease);
}
.focus-tabs a:hover { color: var(--text); background: var(--surface); }
.focus-tabs a.on { background: var(--accent-fill); color: var(--text-on-accent); font-weight: 600; }

/*
 * Les sorties du bandeau sont des boutons, pas des liens gris.
 *
 * « Revenir à ma vue » est le geste le plus fréquent du bandeau, et il se
 * lisait comme une mention en marge : texte pâle, soulignement au survol.
 * Une pastille qui réagit au survol, à l'appui et au clavier dit qu'on
 * peut cliquer, et où l'on va.
 */
.focus-bar .quit {
  display: inline-flex; align-items: center; gap: .35rem;
  height: 1.9rem; padding: 0 .8rem;
  font-size: var(--fs-sm); font-weight: 500; color: var(--text-2);
  text-decoration: none; white-space: nowrap;
  background: var(--surface); border: 1px solid var(--sep); border-radius: var(--r-pill);
  transition: color .14s var(--ease), background .14s var(--ease),
              border-color .14s var(--ease), transform .1s var(--ease);
}
.focus-bar .quit svg { flex: none; transition: transform .16s var(--ease); }
.focus-bar .quit .retour { transform: rotate(180deg); }
/* La sortie ferme la barre, après les visages : on ne la heurte pas en les
   parcourant, et elle est au même endroit d'un écran à l'autre. */
.focus-bar .quit-home { margin-left: 0; }
.focus-bar .quit:hover { color: var(--accent); background: var(--accent-soft); border-color: var(--accent); }
.focus-bar .quit:hover .retour { transform: rotate(180deg) translateX(2px); }
.focus-bar .quit:active { transform: scale(.96); }
.focus-bar .quit:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
  .focus-bar .quit, .focus-bar .quit svg { transition: none; }
  .focus-bar .quit:active { transform: none; }
}

/*
 * Les onglets se lisent d'un coup d'œil : le nom en pleine taille, le choix
 * courant posé sur l'accent plein, son compte dans une pastille claire —
 * un nombre pâli sur fond coloré ne se lisait plus.
 */
.regie-tabs a {
  display: inline-flex; align-items: center; gap: .45rem;
  padding: .32rem .7rem;
  font-size: var(--fs-base); font-weight: 550; color: var(--text-2);
}
.regie-tabs a:hover { color: var(--text); background: var(--surface); }
.regie-tabs a.on {
  font-weight: 650; letter-spacing: -.005em;
  box-shadow: 0 1px 2px color-mix(in srgb, var(--accent) 35%, transparent);
}
.regie-tabs a .avatar-sm { width: 1.3rem; height: 1.3rem; font-size: .55rem; }
.regie-tabs a.on .avatar-sm { box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--text-on-accent) 70%, transparent); }
/* « Tous » n'a pas de visage : un cercle de même taille, pour que la rangée
   commence droit au lieu de flotter. */
.regie-tabs .tp-tous {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.3rem; height: 1.3rem; border-radius: 50%; flex: none;
  background: var(--surface-3); color: var(--text-2);
}
.regie-tabs a.on .tp-tous { background: color-mix(in srgb, var(--text-on-accent) 22%, transparent); color: inherit; }
.regie-tabs a .n {
  font-size: var(--fs-xs); font-weight: 650; font-variant-numeric: tabular-nums;
  color: var(--text-3); background: var(--surface-2);
  padding: .05rem .4rem; border-radius: var(--r-pill);
}
.regie-tabs a:hover .n { color: var(--text-2); }
.regie-tabs a.on .n {
  color: var(--text-on-accent); opacity: 1;
  background: color-mix(in srgb, var(--text-on-accent) 22%, transparent);
}

@media (max-width: 700px) {
  /* Sur téléphone la barre reprend toute la largeur : les visages défilent
     en rangée, la sortie revient dessous, calée à droite. */
  .focus-bar { width: auto; flex-wrap: wrap; gap: var(--sp-2); }
  .focus-tabs { width: 100%; overflow-x: auto; flex-wrap: nowrap; justify-content: flex-start; }
  .focus-bar .quit-home { margin-left: auto; }
}

/* Enfoncé tant que le bandeau est ouvert : on voit d'où l'on sort. */
.btn.btn-regie-on { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }

/* Le télépro d'une ligne, dans l'onglet « Tous ». */
.regie-qui {
  display: inline-block; margin-left: .4rem;
  font-size: var(--fs-xs); font-weight: 500; color: var(--text-3); white-space: nowrap;
}

/* Une fiche ouverte par quelqu'un d'autre : le nom, en clair sur la ligne. */
.verrou-par {
  display: inline-flex; align-items: center; gap: .25rem; margin-left: .4rem;
  padding: 0 .45rem; border-radius: var(--r-pill);
  font-size: var(--fs-xs); font-weight: 600; white-space: nowrap;
  background: var(--amber-soft); color: var(--amber);
}

/* --------------------------------------------------------------------------
   Confirmation — remplace les boîtes natives du navigateur
   Centrée sur ordinateur, en feuille sous le pouce sur téléphone, toujours
   au-dessus de ce qui est ouvert. Voir alvycaConfirmer() dans shell.php.
   -------------------------------------------------------------------------- */

.confirm-bg {
  position: fixed; inset: 0; z-index: 8000;
  display: none; align-items: center; justify-content: center;
  padding: var(--sp-4);
  background: rgba(0, 0, 0, .5);
  opacity: 0; transition: opacity .16s var(--ease);
}
.confirm-bg.ouvert { display: flex; }
.confirm-bg.on { opacity: 1; }
.confirm {
  width: min(27rem, 100%);
  background: var(--bg); color: var(--text);
  border: 1px solid var(--sep); border-radius: var(--r-lg);
  box-shadow: var(--shadow-3);
  padding: var(--sp-5);
  transform: translateY(8px) scale(.98);
  transition: transform .2s var(--ease-out);
}
.confirm-bg.on .confirm { transform: none; }
.confirm h2 { margin: 0 0 var(--sp-2); font-size: var(--fs-lg); font-weight: 600; line-height: 1.3; text-wrap: balance; }
.confirm p  { margin: 0; font-size: var(--fs-md); color: var(--text-2); line-height: 1.5; white-space: pre-line; }
.confirm-ft { display: flex; justify-content: flex-end; gap: var(--sp-2); flex-wrap: wrap; margin-top: var(--sp-5); }
@media (max-width: 640px) {
  .confirm-bg { align-items: flex-end; padding: 0; }
  .confirm {
    width: 100%; border-radius: var(--r-lg) var(--r-lg) 0 0;
    padding-bottom: calc(var(--sp-5) + env(safe-area-inset-bottom, 0px));
    transform: translateY(24px);
  }
  /* Le geste sûr en haut, sous le pouce ; celui qui engage, dessous. */
  .confirm-ft { flex-direction: column-reverse; }
  .confirm-ft .btn { width: 100%; height: var(--h-ctl-lg); }
}

/* Notification porteuse d'une action — « Annuler » une mise à la corbeille. */
.toast .toast-act {
  margin-left: auto; align-self: center; flex: none;
  border: 0; background: none; cursor: pointer;
  padding: .25rem .5rem; border-radius: var(--r-sm);
  font-family: inherit; font-size: inherit; font-weight: 600; color: var(--accent);
}
.toast .toast-act:hover { background: var(--accent-soft); }
.toast .toast-act:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* --------------------------------------------------------------------------
   Bascule entre sa vue et celle de ses télépros
   Un seul geste : le navigateur garde une image de la page qu'on quitte et
   la fait glisser pendant que la suivante arrive. Rien n'attend le
   chargement, et la barre de navigation ne bouge pas. Voir shell.php.
   -------------------------------------------------------------------------- */

@view-transition { navigation: auto; }

/* Les barres de navigation sont capturées à part et ne bougent pas : sans
   cela, tout l'écran glisserait, ce qui donne le mal de mer. */
.navbar { view-transition-name: nav-haut; }
.tabbar { view-transition-name: nav-bas; }
::view-transition-group(nav-haut), ::view-transition-old(nav-haut), ::view-transition-new(nav-haut),
::view-transition-group(nav-bas),  ::view-transition-old(nav-bas),  ::view-transition-new(nav-bas) {
  animation: none; mix-blend-mode: normal;
}

/* Le bandeau de régie garde sa place d'un onglet à l'autre : seuls les
   compteurs et l'onglet actif changent. */
html:active-view-transition-type(bascule-onglet) .focus-bar { view-transition-name: bandeau-regie; }

@keyframes vt-part-gauche  { to   { opacity: 0; transform: translateX(-2.5%); } }
@keyframes vt-part-droite  { to   { opacity: 0; transform: translateX(2.5%); } }
@keyframes vt-vient-droite { from { opacity: 0; transform: translateX(3%); } }
@keyframes vt-vient-gauche { from { opacity: 0; transform: translateX(-3%); } }
@keyframes vt-part-fondu   { to   { opacity: 0; } }
@keyframes vt-vient-fondu  { from { opacity: 0; } }

/* Sortie courte, entrée un peu plus longue et décélérée : les deux images se
   croisent, on lit un seul mouvement. */
html:active-view-transition-type(bascule-regie)::view-transition-old(root) { animation: vt-part-gauche .16s cubic-bezier(.4, 0, 1, 1) both; }
html:active-view-transition-type(bascule-regie)::view-transition-new(root) { animation: vt-vient-droite .26s cubic-bezier(0, 0, .2, 1) both; }
html:active-view-transition-type(bascule-moi)::view-transition-old(root)   { animation: vt-part-droite .16s cubic-bezier(.4, 0, 1, 1) both; }
html:active-view-transition-type(bascule-moi)::view-transition-new(root)   { animation: vt-vient-gauche .26s cubic-bezier(0, 0, .2, 1) both; }
html:active-view-transition-type(bascule-onglet)::view-transition-old(root) { animation: vt-part-fondu .12s linear both; }
html:active-view-transition-type(bascule-onglet)::view-transition-new(root) { animation: vt-vient-fondu .2s linear both; }

/* Repli pour les navigateurs sans transition entre documents : un fondu
   d'entrée seul. Pas d'animation de sortie, donc pas de double geste, et
   aucun délai ajouté au clic. */
@keyframes vue-entre-fondu { from { opacity: 0; } }
.page.vue-entre { animation: vue-entre-fondu .2s var(--ease-out) both; }

@media (prefers-reduced-motion: reduce) {
  .confirm-bg, .confirm { transition: none; }
  .page.vue-entre { animation: none; }
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}

/* --------------------------------------------------------------------------
   Pagination — identique sur toutes les listes
   -------------------------------------------------------------------------- */

.pager { display: flex; align-items: center; justify-content: space-between;
         gap: var(--sp-3); margin-top: var(--sp-4); flex-wrap: wrap; }

.pager-mini { display: inline-flex; align-items: center; gap: 2px; flex: none; }
.pager-mini .pg {
  width: var(--h-ctl); height: var(--h-ctl);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 1rem; color: var(--text-2);
  background: var(--surface); border: 1px solid var(--sep-strong);
  border-radius: var(--r-sm); text-decoration: none;
  transition: background .12s var(--ease), color .12s var(--ease), border-color .12s var(--ease);
}
.pager-mini .pg:hover { background: var(--accent-soft); color: var(--accent); border-color: var(--accent); }
.pager-mini .pg.off { opacity: .3; pointer-events: none; }

.pager-mini .pg-lbl {
  display: inline-flex; align-items: baseline; gap: .3rem;
  padding: 0 var(--sp-2); font-size: var(--fs-md); color: var(--text-3);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.pager-mini .pg-lbl .sep { color: var(--text-3); opacity: .6; }

/* Le rang courant est un champ : on tape la page voulue plutôt que de
   cliquer autant de fois qu'il y a de pages à parcourir. */
.pager-mini .pg-in {
  font: inherit; font-size: var(--fs-md); font-weight: 600;
  font-variant-numeric: tabular-nums; text-align: center;
  color: var(--accent); background: transparent;
  border: 1px solid transparent; border-radius: var(--r-sm);
  padding: .15rem .3rem; min-width: 1.6rem;
  transition: background .12s var(--ease), border-color .12s var(--ease);
  -moz-appearance: textfield;
}
.pager-mini .pg-in:hover { background: var(--surface-2); border-color: var(--sep); }
.pager-mini .pg-in:focus {
  outline: none; background: var(--surface);
  border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-ring);
}

.pager-mini.compact .pg { width: 2rem; height: var(--h-ctl); }
.pager-mini.compact .pg-lbl { padding: 0 var(--sp-1); font-size: var(--fs-sm); }
.pager-mini.compact .pg-in { font-size: var(--fs-sm); }

/* --------------------------------------------------------------------------
   5. Surfaces
   -------------------------------------------------------------------------- */

.card {
  background: var(--surface);
  border: 1px solid var(--sep);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
}
.card-p  { padding: var(--sp-5); }
.card-hd {
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--sep);
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
}
.card-bd { padding: var(--sp-5); }
.panel   { background: var(--surface-2); border-radius: var(--r); padding: var(--sp-4); }

/* --------------------------------------------------------------------------
   6. Boutons
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  padding: 0 var(--sp-4); height: var(--h-ctl);
  font: inherit; font-size: var(--fs-md); font-weight: 500; letter-spacing: -.01em;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--sep-strong);
  border-radius: var(--r-sm);
  cursor: pointer; white-space: nowrap;
  transition: background .15s var(--ease), border-color .15s var(--ease), transform .06s var(--ease);
  user-select: none;
}
.btn:hover:not(:disabled)  { background: var(--surface-hover); color: var(--text); }
.btn:active:not(:disabled) { transform: scale(.975); }
.btn:disabled              { opacity: .42; cursor: not-allowed; }

.btn-primary { background: var(--accent-fill); border-color: transparent; color: var(--text-on-accent); }
.btn-primary:hover:not(:disabled) { background: var(--accent-hover); color: var(--text-on-accent); }

.btn-ghost { background: transparent; border-color: transparent; color: var(--text-2); }
.btn-ghost:hover:not(:disabled) { background: var(--surface-hover); color: var(--text); }

.btn-danger { color: var(--red); border-color: var(--sep-strong); background: var(--surface); }
.btn-danger:hover:not(:disabled) { background: var(--red-soft); border-color: var(--red); color: var(--red); }

.btn-sm   { height: var(--h-ctl-sm); padding: 0 var(--sp-3); font-size: var(--fs-sm); gap: var(--sp-1); }
.btn-lg   { height: var(--h-ctl-lg); padding: 0 var(--sp-5); font-size: var(--fs-base); border-radius: var(--r); }
.btn-icon { width: var(--h-ctl); padding: 0; }
.btn-icon.btn-sm { width: var(--h-ctl-sm); }
.btn-block{ width: 100%; }

/* --------------------------------------------------------------------------
   7. Champs
   -------------------------------------------------------------------------- */

.field { display: flex; flex-direction: column; gap: var(--sp-1); min-width: 0; }
.label { font-size: var(--fs-xs); font-weight: 600; color: var(--text-3); letter-spacing: .01em; }

.input, .select, .textarea {
  width: 100%;
  padding: 0 var(--sp-3);
  height: var(--h-ctl);
  font: inherit; font-size: var(--fs-md);
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--sep-strong);
  border-radius: var(--r-sm);
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.input::placeholder, .textarea::placeholder { color: var(--text-3); }
.input:focus, .select:focus, .textarea:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-ring);
}
.textarea { resize: vertical; min-height: 5.5rem; height: auto; padding: var(--sp-2) var(--sp-3); line-height: 1.55; }

/* Le chevron du select est un fond SVG : sa couleur vient d'un jeton dédié
   plutôt que d'une règle dupliquée par thème. */
:root                      { --chevron: %236e6e76; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --chevron: %239a9aa0; } }
:root[data-theme="dark"]   { --chevron: %239a9aa0; }

.select {
  appearance: none; padding-right: 2rem;
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%239a9aa0' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round' d='M4 6.5 8 10.5l4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right .6rem center; background-size: 1rem;
}

.search { position: relative; }
.search .input { padding-left: 2.1rem; }
.search svg { position: absolute; left: .65rem; top: 50%; transform: translateY(-50%); color: var(--text-3); pointer-events: none; }

.switch { display: inline-flex; align-items: center; gap: var(--sp-2); cursor: pointer; user-select: none; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch .track {
  width: 2.6rem; height: 1.55rem; border-radius: var(--r-pill);
  background: var(--surface-3); position: relative;
  transition: background .2s var(--ease); flex: none;
}
.switch .track::after {
  content: ''; position: absolute; top: 2px; left: 2px;
  width: calc(1.55rem - 4px); height: calc(1.55rem - 4px); border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.3);
  transition: transform .22s var(--ease-out);
}
/* --------------------------------------------------------------------------
   Cases à cocher
   --------------------------------------------------------------------------
   Le contrôle natif suit le thème du SYSTÈME, pas celui de l'application :
   en thème clair choisi sur un système sombre, la case s'affichait en noir
   plein. On la dessine donc nous-mêmes — fond transparent, contour visible,
   remplissage en couleur d'accentuation une fois cochée — pour qu'elle soit
   la même partout et lisible sur les deux fonds.
   -------------------------------------------------------------------------- */

input[type="checkbox"]:not([role]) {
  appearance: none; -webkit-appearance: none;
  width: 1.1rem; height: 1.1rem; flex: none; margin: 0;
  background: transparent;
  border: 1.5px solid var(--sep-strong);
  border-radius: 5px; cursor: pointer;
  /*
   * La coche est positionnée par rapport à la case, pas centrée par une
   * grille : la case change de taille selon les pages et les écrans, et un
   * centrage au décalage laissait la coche de travers, débordant du cadre
   * sur téléphone où la case est plus grande.
   */
  position: relative; display: inline-block; vertical-align: middle;
  transition: background .12s var(--ease), border-color .12s var(--ease);
}
input[type="checkbox"]:not([role]):hover { border-color: var(--accent); }
input[type="checkbox"]:not([role]):checked {
  background: var(--accent-fill); border-color: var(--accent-fill);
}
/* La coche : deux traits, proportionnels à la case et centrés dessus. */
input[type="checkbox"]:not([role]):checked::after {
  content: ''; position: absolute;
  left: 50%; top: 48%;
  width: 28%; height: 55%;
  border: solid var(--text-on-accent); border-width: 0 2px 2px 0;
  transform: translate(-50%, -50%) rotate(45deg);
  transform-origin: center;
}
input[type="checkbox"]:not([role]):indeterminate {
  background: var(--accent-fill); border-color: var(--accent-fill);
}
input[type="checkbox"]:not([role]):indeterminate::after {
  content: ''; position: absolute;
  left: 50%; top: 50%;
  width: 55%; height: 2px; border-radius: 1px;
  background: var(--text-on-accent);
  transform: translate(-50%, -50%);
}
input[type="checkbox"]:not([role]):focus-visible {
  outline: none; box-shadow: 0 0 0 3px var(--accent-ring);
}

.switch input:checked + .track { background: var(--green); }
.switch input:checked + .track::after { transform: translateX(1.05rem); }
.switch input:focus-visible + .track { box-shadow: 0 0 0 3px var(--accent-ring); }

/* --------------------------------------------------------------------------
   8. Pastilles d'état
   -------------------------------------------------------------------------- */

.chip {
  display: inline-flex; align-items: center; gap: var(--sp-1);
  padding: 0 var(--sp-2); height: 1.5rem;
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: -.005em;
  border-radius: var(--r-pill); white-space: nowrap;
  background: var(--neutral-soft); color: var(--neutral);
}
.chip::before { content: ''; width: .4rem; height: .4rem; border-radius: 50%; background: currentColor; flex: none; }
.chip-plain::before { display: none; }

.chip[data-tone="green"]  { background: var(--green-soft);  color: var(--green); }
.chip[data-tone="amber"]  { background: var(--amber-soft);  color: var(--amber); }
.chip[data-tone="red"]    { background: var(--red-soft);    color: var(--red); }
.chip[data-tone="rose"]   { background: var(--rose-soft);   color: var(--rose); }
.chip[data-tone="blue"]   { background: var(--blue-soft);   color: var(--blue); }
.chip[data-tone="indigo"] { background: var(--indigo-soft); color: var(--indigo); }
.chip[data-tone="cyan"]   { background: var(--cyan-soft);   color: var(--cyan); }
.chip[data-tone="orange"] { background: var(--orange-soft); color: var(--orange); }
.chip[data-tone="slate"]  { background: var(--slate-soft);  color: var(--slate); }
.chip[data-tone="neutral"]{ background: var(--neutral-soft);color: var(--neutral); }
.chip[data-tone="accent"] { background: var(--accent-soft); color: var(--accent); }
/* Teinte d'étape choisie à la main (#rrggbb) : voir Step::attrs(). */
.chip[data-tone="perso"] { background: color-mix(in srgb, var(--perso) 16%, transparent); color: var(--perso-txt, var(--perso)); }

/*
 * L'encre d'une teinte libre suit le thème.
 *
 * Step::vars() pose deux nuances de texte calculées à 7:1 : --perso-l pour
 * le thème clair, --perso-d pour le sombre. On choisit ici la bonne, dans
 * les trois états du thème — clair, sombre explicite, et système.
 */
[data-c="perso"], [data-tone="perso"] { --perso-txt: var(--perso-l, var(--perso)); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) :is([data-c="perso"], [data-tone="perso"]) { --perso-txt: var(--perso-d, var(--perso)); }
}
:root[data-theme="dark"] :is([data-c="perso"], [data-tone="perso"]) { --perso-txt: var(--perso-d, var(--perso)); }

/*
 * Le fond d'un badge d'étape est un dégradé, pas un aplat.
 *
 * Une pastille d'une seule teinte plate à côté d'une autre donne un écran de
 * gommettes. Un dégradé vertical très court — la couleur s'épaissit de huit
 * points vers le bas — suffit à donner du relief sans qu'on puisse dire d'où
 * il vient. Il est peint avec `currentColor`, donc il suit la couleur du
 * badge, palette comme teinte libre, dans les deux thèmes, sans une règle de
 * plus par couleur. Le texte, lui, est calculé sur le point le plus dense.
 */
:is(.step-btn, .step-now)[data-c], .chip-etape[data-tone] {
  background-image: linear-gradient(180deg, transparent, color-mix(in srgb, currentColor 8%, transparent));
}

/*
 * Badges d'étape « pleins » — réglage du compte (Profil › Affichage).
 *
 * Par défaut les badges sont doux : fond atténué, texte de la couleur. Qui
 * préfère un contraste maximal les passe en pleins : fond de la couleur,
 * texte blanc ou encre selon ce qui se lit le mieux. Seuls les badges
 * changent ; les points, traits et intitulés de groupe restent discrets, sans
 * quoi une liste de cinquante dossiers devient un nuancier.
 */
:root[data-badges="pleins"] :is(.step-btn, .step-now)[data-c="slate"],  :root[data-badges="pleins"] .chip-etape[data-tone="slate"]  { background: var(--slate);  color: var(--on-palette); }
:root[data-badges="pleins"] :is(.step-btn, .step-now)[data-c="blue"],   :root[data-badges="pleins"] .chip-etape[data-tone="blue"]   { background: var(--blue);   color: var(--on-palette); }
:root[data-badges="pleins"] :is(.step-btn, .step-now)[data-c="indigo"], :root[data-badges="pleins"] .chip-etape[data-tone="indigo"] { background: var(--indigo); color: var(--on-palette); }
:root[data-badges="pleins"] :is(.step-btn, .step-now)[data-c="cyan"],   :root[data-badges="pleins"] .chip-etape[data-tone="cyan"]   { background: var(--cyan);   color: var(--on-palette); }
:root[data-badges="pleins"] :is(.step-btn, .step-now)[data-c="green"],  :root[data-badges="pleins"] .chip-etape[data-tone="green"]  { background: var(--green);  color: var(--on-palette); }
:root[data-badges="pleins"] :is(.step-btn, .step-now)[data-c="amber"],  :root[data-badges="pleins"] .chip-etape[data-tone="amber"]  { background: var(--amber);  color: var(--on-palette); }
:root[data-badges="pleins"] :is(.step-btn, .step-now)[data-c="orange"], :root[data-badges="pleins"] .chip-etape[data-tone="orange"] { background: var(--orange); color: var(--on-palette); }
:root[data-badges="pleins"] :is(.step-btn, .step-now)[data-c="red"],    :root[data-badges="pleins"] .chip-etape[data-tone="red"]    { background: var(--red);    color: var(--on-palette); }
:root[data-badges="pleins"] :is(.step-btn, .step-now)[data-c="rose"],   :root[data-badges="pleins"] .chip-etape[data-tone="rose"]   { background: var(--rose);   color: var(--on-palette); }
:root[data-badges="pleins"] :is(.step-btn, .step-now)[data-c="perso"],  :root[data-badges="pleins"] .chip-etape[data-tone="perso"]  { background: var(--perso-plein, var(--perso)); color: var(--perso-on, #ffffff); }

/* En plein, le relief vient d'un voile clair en haut et d'une ombre en bas :
   assez pour que la pastille ne soit pas un carré de couleur, assez peu pour
   ne pas entamer la lisibilité du texte. */
:root[data-badges="pleins"] :is(.step-btn, .step-now)[data-c],
:root[data-badges="pleins"] .chip-etape[data-tone] {
  background-image: linear-gradient(180deg, rgba(255, 255, 255, .07), rgba(0, 0, 0, .07));
}

/* --------------------------------------------------------------------------
   9. Tableaux
   -------------------------------------------------------------------------- */

.table-wrap {
  overflow-x: auto;
  background: var(--surface);
  border: 1px solid var(--sep);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
}

table.tbl { width: 100%; border-collapse: collapse; font-size: var(--fs-md); }

/*
 * Largeurs tenues, et colonnes à contenu fixe respectées.
 *
 * Deux règles, et seulement au-dessus du seuil des cartes : en dessous, la
 * ligne devient une carte, le tableau n'est plus un tableau et ces largeurs
 * n'auraient aucun sens — pire, elles pousseraient les cartes hors de
 * l'écran.
 *
 *   — `table-layout: fixed` fait des largeurs posées sur les en-têtes des
 *     consignes et non des vœux. Sans elle, l'algorithme automatique du
 *     navigateur arbitrait au contenu : les colonnes bavardes prenaient la
 *     place des autres, et un code postal se retrouvait à 20 px utiles.
 *   — Numéros et code postal ne reviennent jamais à la ligne. Un numéro
 *     s'écrit avec des espaces ; sans cette règle il se coupait dessus et
 *     occupait deux ou trois lignes au milieu d'un tableau à une ligne.
 *
 * Réservé aux deux tableaux qui déclarent leurs largeurs. Les autres — le
 * tableau d'activité du tableau de bord, ceux de l'administration — n'en
 * posent aucune : en largeur fixe, leurs colonnes deviendraient toutes
 * égales.
 */
@media (min-width: 769px) {
  table.tbl.mc, table.tbl.leads { table-layout: fixed; }

  table.tbl.mc :is(th, td).col-number,
  table.tbl.mc :is(th, td).col-postal,
  table.tbl.leads :is(th, td).col-number,
  table.tbl.leads :is(th, td).col-number2,
  table.tbl.leads :is(th, td).col-postal { white-space: nowrap; }

  /* Le numéro est un bouton : il a sa propre mise en page à contenir. */
  table.tbl.mc td.col-number .tel,
  table.tbl.leads :is(td.col-number, td.col-number2) .tel { white-space: nowrap; }

  /*
   * La poignée de largeur, sur le bord droit de chaque en-tête.
   *
   * Invisible au repos — une rangée de traits verticaux ferait un tableau
   * quadrillé —, elle se révèle au survol de l'en-tête et pendant qu'on
   * tire. Sa zone de saisie déborde de quelques pixels de part et d'autre :
   * viser une ligne d'un pixel à la souris n'est pas un geste.
   */
  table.tbl.mc thead th, table.tbl.leads thead th { position: relative; }
  .col-grip {
    position: absolute; top: 0; right: -4px; bottom: 0; width: 9px;
    cursor: col-resize; touch-action: none;
    background: none; border: 0; padding: 0;
  }
  .col-grip::before {
    content: ''; position: absolute; top: 20%; bottom: 20%; left: 4px; width: 2px;
    border-radius: 1px; background: var(--sep-strong);
    opacity: 0; transition: opacity .12s var(--ease), background .12s var(--ease);
  }
  thead th:hover > .col-grip::before,
  .col-grip:focus-visible::before { opacity: 1; }
  .col-grip:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
  /* Pendant le glissement : le trait reste, et rien ne se sélectionne. */
  table.cols-redim { user-select: none; }
  table.cols-redim .col-grip::before { opacity: 1; background: var(--accent); }

  /*
   * Remplissage resserré sur les tableaux denses.
   *
   * 16 px de chaque côté font 32 px par colonne : sur dix colonnes, 320 px
   * de vide pris sur le contenu. À 12 px, on rend 80 px aux données sans
   * que les cellules se touchent.
   */
  table.tbl.mc :is(th, td),
  table.tbl.leads :is(th, td) { padding-left: var(--sp-3); padding-right: var(--sp-3); }
}

table.tbl thead th {
  position: sticky; top: 0; z-index: 2;
  text-align: left;
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: .02em;
  color: var(--text-3);
  background: var(--surface-2);
  border-bottom: 1px solid var(--sep);
  white-space: nowrap;
}

/*
 * L'en-tête colle au bord arrondi du cadre.
 *
 * Un `th` en `position: sticky` est un élément positionné : il échappe au
 * rognage que le conteneur applique à ses coins, et son fond plus clair
 * débordait donc de l'arrondi, aux deux angles du haut. On arrondit les
 * cellules d'angle de la même valeur plutôt que de retirer le collage, qui
 * sert à garder les intitulés visibles pendant le défilement.
 */
.table-wrap table.tbl thead th:first-child { border-top-left-radius:  var(--r-lg); }
.table-wrap table.tbl thead th:last-child  { border-top-right-radius: var(--r-lg); }

table.tbl tbody td {
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--sep);
  vertical-align: middle;
  color: var(--text-2);
}
table.tbl tbody tr:last-child td { border-bottom: 0; }
table.tbl tbody tr { transition: background .12s var(--ease); }
table.tbl tbody tr:hover { background: var(--surface-hover); }
table.tbl tbody td.strong { color: var(--text); font-weight: 500; }

/* Filet de couleur porté par la ligne, selon son statut */
table.tbl tbody tr[data-tone] > td:first-child { position: relative; }
table.tbl tbody tr[data-tone] > td:first-child::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--row-tone, transparent);
}
tr[data-tone="green"]  { --row-tone: var(--green); }
tr[data-tone="amber"]  { --row-tone: var(--amber); }
tr[data-tone="red"]    { --row-tone: var(--red); }
tr[data-tone="rose"]   { --row-tone: var(--rose); }
tr[data-tone="slate"]  { --row-tone: var(--slate); }
tr[data-tone="blue"]   { --row-tone: var(--blue); }
tr[data-tone="neutral"]{ --row-tone: transparent; }

/*
 * Ligne qui vient de changer sous les yeux.
 *
 * Sans repère, une ligne se verrouille en silence et on croit à un bug —
 * « le bouton marchait il y a deux secondes ». Un fond qui s'allume puis
 * s'éteint dit qu'il s'est passé quelque chose, sans arrêter la lecture.
 */
tr.vient-de-changer > td { animation: ligne-changee 1.4s var(--ease) both; }
@keyframes ligne-changee {
  0%   { background: var(--accent-soft); }
  100% { background: transparent; }
}
@media (prefers-reduced-motion: reduce) {
  tr.vient-de-changer > td { animation: none; }
}

.col-num { text-align: right; font-variant-numeric: tabular-nums; }

/*
 * Chiffre qui roule vers sa nouvelle valeur.
 *
 * Les chiffres à largeur fixe sont indispensables ici : sans eux, un compteur
 * qui passe de 8 à 12 fait danser toute la colonne pendant l'animation.
 *
 * La teinte d'accentuation ne dure que le temps du mouvement. Elle sert à
 * dire « celui-ci vient de bouger » — dans un tableau de dix lignes, c'est
 * la seule façon de repérer laquelle a changé sans la regarder fixement.
 */
[data-stat] { font-variant-numeric: tabular-nums; }
.stat-bouge {
  color: var(--accent);
  transition: color .42s var(--ease);
}
@media (prefers-reduced-motion: reduce) {
  .stat-bouge { transition: none; }
}

/*
 * L'en-tête d'une colonne de chiffres s'aligne sur ses chiffres.
 *
 * « table.tbl thead th » impose text-align: left et pèse plus lourd que
 * « .col-num » : les titres Total, Portefeuille et Clients restaient donc
 * calés à gauche au-dessus de nombres alignés à droite. Il faut viser le
 * th explicitement pour reprendre la main.
 */
table.tbl thead th.col-num { text-align: right; }

/* --------------------------------------------------------------------------
   10. Segments de filtre
   -------------------------------------------------------------------------- */

.segmented {
  display: inline-flex; gap: 2px; padding: 2px;
  background: var(--surface-2); border-radius: var(--r);
  overflow-x: auto; max-width: 100%;
}
.segmented a, .segmented button {
  display: inline-flex; align-items: center; gap: var(--sp-1);
  padding: 0 var(--sp-3); height: calc(var(--h-ctl) - 4px);
  font: inherit; font-size: var(--fs-sm); font-weight: 500;
  color: var(--text-2); background: transparent; border: 0; border-radius: 8px;
  cursor: pointer; white-space: nowrap;
  transition: background .15s var(--ease), color .15s var(--ease);
}
.segmented a:hover, .segmented button:hover { color: var(--text); background: var(--surface-3); }

/*
 * Sur le segment actif, seuls le texte et l'icône prennent la couleur
 * d'accentuation. Le fond reste neutre — une pastille teintée alourdit la
 * barre sans rien dire de plus, la couleur du libellé suffit à désigner le
 * choix. Le léger relief distingue toujours le segment de sa piste.
 */
.segmented .on {
  background: var(--surface); color: var(--accent);
  font-weight: 600; box-shadow: var(--shadow-1);
}
.segmented .on svg { opacity: 1; }
.segmented svg { opacity: .75; flex: none; }
.segmented .count { font-size: var(--fs-xs); font-variant-numeric: tabular-nums; color: var(--text-3); font-weight: 500; }
.segmented .on .count { color: var(--accent); }

/* --------------------------------------------------------------------------
   11. Avatars
   -------------------------------------------------------------------------- */

.avatar {
  width: 2rem; height: 2rem; border-radius: 50%;
  object-fit: cover; flex: none;
  background: var(--surface-3);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: var(--fs-xs); font-weight: 600; color: var(--text-2);
  letter-spacing: 0; text-transform: uppercase;
  box-shadow: inset 0 0 0 1px var(--ring);
}
.avatar-lg { width: 5rem; height: 5rem; font-size: var(--fs-xl); }

/*
 * L'avatar du mode régie : un anneau segmenté, un segment par télépro.
 *
 * L'anneau est un dégradé conique masqué en son centre — il ne coûte ni
 * image ni balise de plus, et suit la couleur d'accent du compte. Voir
 * alvyca_avatar_regie() dans shell.php, qui calcule les segments.
 */
.avatar-regie { position: relative; background: var(--surface-3); color: var(--text-2); }
.avatar-regie::before {
  content: ''; position: absolute; inset: 0; border-radius: 50%; padding: 2px;
  background: var(--segments);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
}
.avatar-regie svg { position: relative; }

/* Un télépro consulté : son avatar, cerclé d'accent — on sait chez qui on est. */
.avatar-tp { box-shadow: 0 0 0 2px var(--accent); }
.avatar-sm { width: 1.5rem; height: 1.5rem; font-size: .625rem; }

/* --------------------------------------------------------------------------
   12. États vides
   -------------------------------------------------------------------------- */

.empty {
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-2);
  padding: 3.5rem var(--sp-5); text-align: center; color: var(--text-3);
}
.empty .icon { opacity: .5; line-height: 1; }
.empty h3 { color: var(--text); }
.empty p { font-size: var(--fs-md); max-width: 44ch; }

/* --------------------------------------------------------------------------
   13. Notifications
   -------------------------------------------------------------------------- */

.toast-stack {
  position: fixed; right: var(--sp-4); bottom: var(--sp-4); z-index: 9000;
  display: flex; flex-direction: column; gap: var(--sp-2);
  max-width: min(24rem, calc(100vw - 2rem));
}
.toast {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  background: var(--surface); border: 1px solid var(--sep);
  border-radius: var(--r); box-shadow: var(--shadow-3);
  font-size: var(--fs-md);
  animation: toast-in .28s var(--ease-out);
}
/* Le filet de la notification porte la couleur d'accentuation pour une
   confirmation d'action — copier, enregistrer, ranger : ce n'est pas un
   état à interpréter, juste le retour du geste, et il suit donc l'identité
   choisie. Le rouge et l'orange restent sémantiques : les transformer en
   accent ferait perdre l'information d'erreur ou d'avertissement. */
.toast .bar { width: 3px; align-self: stretch; border-radius: 2px; background: var(--text-3); flex: none; }
.toast[data-tone="green"] .bar { background: var(--accent); }
.toast[data-tone="red"]   .bar { background: var(--red); }
.toast[data-tone="amber"] .bar { background: var(--amber); }
.toast .ttl { font-weight: 600; color: var(--text); }
.toast .msg { color: var(--text-2); }
@keyframes toast-in { from { opacity: 0; transform: translateY(10px) scale(.97); } }

/* --------------------------------------------------------------------------
   14. Divers
   -------------------------------------------------------------------------- */

.kbd {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 1.25rem; height: 1.25rem; padding: 0 .3rem;
  font-family: var(--font-mono); font-size: .6875rem; font-weight: 600;
  color: var(--text-2); background: var(--surface-2);
  border: 1px solid var(--sep-strong); border-bottom-width: 2px; border-radius: 5px;
}

.sep-h { height: 1px; background: var(--sep); border: 0; margin: 0; }

.muted   { color: var(--text-3); }
.text-sm { font-size: var(--fs-sm); }
.text-xs { font-size: var(--fs-xs); }
.fw-600  { font-weight: 600; }

.skeleton {
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 50%, var(--surface-2) 75%);
  background-size: 200% 100%; animation: sk 1.3s linear infinite; border-radius: var(--r-sm);
}
@keyframes sk { to { background-position: -200% 0; } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

/* ==========================================================================
   15. Mobile — traitement « application iOS »
   --------------------------------------------------------------------------
   Sur téléphone, ALVYCA ne se comporte plus comme un site réduit mais comme
   une application : barre d'onglets en bas sous le pouce, feuilles qui
   montent du bas, listes en cartes plutôt qu'en tableau, cibles tactiles
   d'au moins 44 px — la mesure de référence d'Apple.
   ========================================================================== */

:root {
  --safe-top:    env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --tabbar-h: 3.25rem;
}

/* Pas d'effet de survol sur un écran tactile : il « colle » après le tap. */
@media (hover: none) {
  .btn:hover:not(:disabled),
  table.tbl tbody tr:hover,
  .nav-link:hover,
  .segmented a:hover { background: inherit; }
  .tel:hover { background: transparent; color: inherit; }
}

@media (max-width: 768px) {

  html { font-size: calc(17px * var(--ui-scale)); }   /* corps iOS par défaut */

  body {
    /* Le contenu ne passe jamais sous la barre d'onglets ni sous l'encoche. */
    padding-bottom: calc(var(--tabbar-h) + var(--safe-bottom));
    overscroll-behavior-y: none;
  }

  .page, .page-narrow, .page-wide {
    max-width: none;
    padding: var(--sp-4) var(--sp-4) var(--sp-6);
  }

  /* ---- Titres de page façon « large title » ---- */
  .page-head h1 { font-size: 1.75rem; letter-spacing: -.03em; }

  /*
   * Titre et boutons ne cohabitent pas sur une ligne de 375 px : le titre
   * se retrouvait comprimé sur quatre lignes pendant que « Étapes du
   * parcours » sortait de l'écran. Ils s'empilent, et la rangée de boutons
   * défile latéralement plutôt que de déborder.
   */
  .page-head .spread,
  .page-head .spread-bottom {
    flex-direction: column; align-items: stretch; gap: var(--sp-3);
  }
  /*
   * La rangée de boutons défile d'un bord à l'autre de l'écran.
   *
   * Elle s'étend sous les marges de la page — d'où les marges négatives —
   * et se les redonne en marge intérieure. Sans ça, le dernier bouton se
   * coupait net sur le bord du téléphone : ça ne se lisait pas comme
   * « il y en a d'autres à droite », mais comme un défaut d'affichage. Là,
   * une fois défilé jusqu'au bout, le bouton se pose à la même distance du
   * bord que le reste de la page.
   */
  .page-head .spread > .row {
    overflow-x: auto; scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    margin-inline: calc(var(--sp-4) * -1);
    padding-inline: var(--sp-4);
    padding-bottom: 2px;
    scroll-padding-inline: var(--sp-4);
    scroll-snap-type: x proximity;
  }
  .page-head .spread > .row::-webkit-scrollbar { display: none; }
  .page-head .spread > .row > .btn { flex: none; scroll-snap-align: start; }

  /* ---- Contrôles : 44 px minimum sous le doigt ----
     Le seuil vient des recommandations d'Apple et de Google : en dessous,
     on vise à côté. Les cases à cocher gardent leur taille visuelle mais
     reçoivent une zone de clic étendue. */
  .btn      { height: 2.75rem; padding: 0 var(--sp-4); font-size: var(--fs-base); }
  .btn-sm   { height: 2.5rem; font-size: var(--fs-sm); }
  .btn-icon { width: 2.75rem; }
  .input, .select { height: 2.75rem; font-size: 1rem; }   /* 16 px : iOS ne zoome pas */
  .textarea { font-size: 1rem; }

  .tab-pill { min-height: 2.5rem; padding: 0 var(--sp-4); font-size: var(--fs-md); }
  .chip     { height: 1.75rem; padding: 0 var(--sp-3); font-size: var(--fs-sm); }
  .only-mobile { display: inline; }
  .hide-mobile { display: none !important; }

  /* Deux indicateurs par ligne : un seul par écran obligeait à faire
     défiler pour lire quatre chiffres. */
  .kpis { grid-template-columns: repeat(2, 1fr); gap: var(--sp-3); }
  .kpis .kpi .val { font-size: 1.5rem; }

  input[type="checkbox"] {
    width: 1.375rem; height: 1.375rem;
    position: relative;
  }
  input[type="checkbox"]::after {
    content: ''; position: absolute; top: 50%; left: 50%;
    width: 2.75rem; height: 2.75rem; transform: translate(-50%, -50%);
  }

  /* ---- Cartes pleine largeur, façon liste groupée iOS ---- */
  .card { border-radius: var(--r-lg); }
  .card-hd, .card-bd { padding: var(--sp-4); }
  /* Titre et bouton d'en-tête ne tiennent pas côte à côte en 375 px :
     ils passent à la ligne au lieu de pousser la page. */
  .card-hd { flex-wrap: wrap; row-gap: var(--sp-2); }
  .card-hd > h2 { min-width: 0; }

  /* ---- Segments : défilement horizontal sans barre visible ---- */
  .segmented {
    width: 100%;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity;
  }
  .segmented::-webkit-scrollbar { display: none; }
  .segmented a, .segmented button { scroll-snap-align: start; height: 2.25rem; }

  /* ---- Tableaux → cartes empilées ----
     Une ligne devient une carte qui se lit comme une cellule de liste iOS :
     le nom en titre, les champs en paires libellé/valeur, les actions en
     bas, la case de sélection dans le coin.

     L'ordre des colonnes du tableau ne commande plus l'affichage. La carte
     est une colonne flex et chaque cellule reçoit un rang : sans ça, la
     première colonne servait de titre — c'était la case à cocher, et la
     carte s'ouvrait donc sur un carré vide. */
  .table-wrap.as-cards { border: 0; background: transparent; box-shadow: none; overflow: visible; }
  .table-wrap.as-cards table.tbl,
  .table-wrap.as-cards thead,
  .table-wrap.as-cards tbody,
  .table-wrap.as-cards td { display: block; width: auto; }
  .table-wrap.as-cards thead { display: none; }

  .table-wrap.as-cards tbody tr {
    display: flex; flex-direction: column;
    background: var(--surface);
    border: 1px solid var(--sep);
    border-radius: var(--r-lg);
    margin-bottom: var(--sp-3);
    padding: var(--sp-4);
    box-shadow: var(--shadow-1);
    position: relative;
    overflow: hidden;
  }
  .table-wrap.as-cards tbody tr[data-tone]::before {
    content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
    background: var(--row-tone, transparent);
  }
  .table-wrap.as-cards tbody tr[data-tone] > td:first-child::before { display: none; }

  .table-wrap.as-cards tbody td {
    padding: var(--sp-2) 0;
    border: 0;
    display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-4);
    min-height: 2.25rem;
    text-align: right;
    /* « anywhere » et pas « break-word » : seul le premier réduit vraiment
       la largeur minimale du contenu, ce qui empêche une adresse e-mail
       de pousser la carte hors de l'écran. */
    overflow-wrap: anywhere;
    min-width: 0;
  }
  .table-wrap.as-cards tbody td::before {
    content: attr(data-label);
    font-size: var(--fs-sm); font-weight: 500; color: var(--text-3);
    flex: none; text-align: left;
    /* Le libellé garde la police du texte même quand la cellule est en
       chiffres à chasse fixe : « Code postal » n'a pas à être en mono. */
    font-family: var(--font); font-variant-numeric: normal; letter-spacing: 0;
  }
  .table-wrap.as-cards tbody td:not([data-label])::before { display: none; }
  .table-wrap.as-cards tbody td:empty { display: none; }
  /* Rien ne dépasse du cadre de la carte. */
  .table-wrap.as-cards tbody td > * { max-width: 100%; }

  /* Le nom prend la tête, quelle que soit sa position dans le tableau. */
  .table-wrap.as-cards tbody td.col-fullname {
    order: -2;
    display: block; text-align: left;
    font-size: var(--fs-lg); font-weight: 600; color: var(--text);
    padding: 0 2.5rem var(--sp-3) 0; margin-bottom: var(--sp-2);
    border-bottom: 1px solid var(--sep);
  }
  .table-wrap.as-cards tbody td.col-fullname::before { display: none; }
  .table-wrap.as-cards tbody td.col-fullname a { color: inherit; text-decoration: none; }

  /* Le parcours juste sous le nom : c'est l'information qu'on cherche. */
  .table-wrap.as-cards tbody td.col-step { order: -1; }

  /* Case de sélection dans le coin, avec une vraie surface sous le doigt. */
  .table-wrap.as-cards tbody td.c-pick {
    position: absolute; top: var(--sp-2); right: var(--sp-2);
    padding: 0; margin: 0; min-height: 0;
    width: 2.75rem; height: 2.75rem;
    display: flex; align-items: center; justify-content: center;
  }

  /* Les actions ferment la carte, en boutons pleine largeur. */
  .table-wrap.as-cards tbody td.c-act {
    order: 99;
    display: flex; gap: var(--sp-2);
    padding-top: var(--sp-3); margin-top: var(--sp-2);
    border-top: 1px solid var(--sep);
  }
  .table-wrap.as-cards tbody td.c-act::before { display: none; }
  .table-wrap.as-cards tbody td.c-act > * { flex: 1; justify-content: center; }

  /* Le bouton d'étape s'arrête au bord de la carte : son libellé est long
     (« Visite technique demandée ou programmée ») et poussait la carte
     hors de l'écran. Il se coupe, la date reste toujours lisible. */
  .table-wrap.as-cards .step-btn {
    min-width: 0; max-width: 100%; min-height: 2.5rem;
  }
  .table-wrap.as-cards .step-btn .lbl {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
  }
  .table-wrap.as-cards .step-btn .dt { flex: none; }

  /* Ce qui se touche dans une carte atteint la hauteur du doigt. */
  .table-wrap.as-cards .client-link,
  .table-wrap.as-cards .tel {
    display: inline-flex; align-items: center; min-height: 2.75rem;
  }

  /* Un numéro appelle : il se présente comme un lien, pas comme du texte. */
  .tel:not(.bad), .phone-btn, .dd-copy {
    color: var(--accent);
    -webkit-tap-highlight-color: transparent;
  }
  .tel:not(.bad):active, .phone-btn:active, .dd-copy:active { opacity: .5; }
  .table-wrap.as-cards td.col-fullname .client-link { min-height: 2.25rem; }

  /* ---- Notifications au-dessus de la barre d'onglets ---- */
  .toast-stack {
    left: var(--sp-3); right: var(--sp-3);
    bottom: calc(var(--tabbar-h) + var(--safe-bottom) + var(--sp-3));
    max-width: none;
  }
}

/* --------------------------------------------------------------------------
   16. Feuilles modales — montent du bas sur mobile
   -------------------------------------------------------------------------- */

@media (max-width: 768px) {

  /* Panneau latéral des leads → feuille plein écran */
  .drawer {
    width: 100%; top: auto; height: 92vh; border-radius: var(--r-xl) var(--r-xl) 0 0;
    border-left: 0; border-top: 1px solid var(--sep);
    transform: translateY(100%);
    padding-bottom: var(--safe-bottom);
  }
  .drawer.on { transform: none; }
  .drawer::before {
    content: ''; position: absolute; top: .5rem; left: 50%; transform: translateX(-50%);
    width: 2.25rem; height: .25rem; border-radius: var(--r-pill);
    background: var(--sep-strong); z-index: 2;
  }
  .drawer-hd { padding-top: 1.35rem; }
  .drawer-ft { padding-bottom: calc(var(--sp-3) + var(--safe-bottom)); }

  /* Modales génériques → feuille du bas */
  .modal-bg { align-items: flex-end; padding: 0; }
  .modal {
    width: 100%; max-height: 92vh;
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    border-bottom: 0;
    animation: sheet-up .3s var(--ease-out);
    padding-bottom: var(--safe-bottom);
  }
  @keyframes sheet-up { from { transform: translateY(100%); } }
  .modal-ft { padding-bottom: calc(var(--sp-3) + var(--safe-bottom)); }
  .modal-ft .btn { flex: 1; }

  /* Popovers → feuille du bas également, plus faciles à viser */
  .pop {
    position: fixed !important;
    left: 0 !important; right: 0 !important;
    top: auto !important; bottom: 0 !important;
    max-width: none; width: 100%;
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    padding: var(--sp-3) var(--sp-3) calc(var(--sp-3) + var(--safe-bottom));
    max-height: 70vh;
    animation: sheet-up .28s var(--ease-out);
  }
  .pop button, .pop label.opt { min-height: 2.75rem; font-size: var(--fs-base); }
}

/* --------------------------------------------------------------------------
   17. Barre d'onglets basse — visible seulement sur téléphone
   -------------------------------------------------------------------------- */

.tabbar { display: none; }

@media (max-width: 768px) {
  .tabbar {
    display: flex;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 600;
    height: calc(var(--tabbar-h) + var(--safe-bottom));
    padding-bottom: var(--safe-bottom);
    background: color-mix(in srgb, var(--surface) 82%, transparent);
    backdrop-filter: saturate(180%) blur(20px);
    -webkit-backdrop-filter: saturate(180%) blur(20px);
    border-top: 1px solid var(--sep);
  }
  .tabbar a {
    /*
     * `min-width: 0` est indispensable : sans lui, un élément flex refuse de
     * passer sous la largeur de son texte, et le libellé le plus long
     * repousse les autres au lieu de se laisser rogner.
     */
    flex: 1 1 0; min-width: 0;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: .1rem;
    color: var(--text-3); font-size: .6rem; font-weight: 500;
    text-decoration: none; position: relative;
    -webkit-tap-highlight-color: transparent;
  }
  /* Dernier recours si un libellé dépasse encore : on rogne proprement
     plutôt que de laisser deux onglets se chevaucher. */
  .tabbar a > span:not(.badge) {
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .tabbar a.on { color: var(--accent); }

  /*
   * En défilant, la barre se rétracte : les libellés s'effacent, les icônes
   * rapetissent. On rend de la hauteur à la lecture sans jamais perdre la
   * navigation, comme le fait Instagram sur iOS.
   *
   * C'est --tabbar-h qui est redéfinie, pas seulement la hauteur de la
   * barre : le rembourrage du corps, la barre de sélection et les
   * notifications se calent tous dessus et suivent d'eux-mêmes.
   */
  :root[data-scrolled="1"] { --tabbar-h: 2.5rem; }

  .tabbar,
  .tabbar a span,
  .tabbar a svg { transition: height .2s var(--ease), opacity .18s var(--ease), width .2s var(--ease); }

  :root[data-scrolled="1"] .tabbar a span { opacity: 0; height: 0; overflow: hidden; }
  :root[data-scrolled="1"] .tabbar a svg { width: 1.35rem; height: 1.35rem; }

  /* L'onglet actif reste identifiable sans son nom : un point sous l'icône. */
  :root[data-scrolled="1"] .tabbar a.on::after {
    content: ''; position: absolute; bottom: .3rem; left: 50%;
    width: .25rem; height: .25rem; margin-left: -.125rem;
    border-radius: 50%; background: var(--accent);
  }
  .tabbar a:active { opacity: .55; }
  .tabbar .badge {
    position: absolute; top: .35rem; left: 50%; margin-left: .3rem;
    min-width: 1rem; height: 1rem; padding: 0 .25rem;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: .5625rem; font-weight: 700; font-variant-numeric: tabular-nums;
    background: var(--red); color: #fff; border-radius: var(--r-pill);
  }

  /* La barre du haut se réduit à la marque et à l'avatar : ces règles-là
     vivent dans le <style> de shell.php, seul endroit d'où elles peuvent
     l'emporter sur les règles de base de la barre, déclarées après cette
     feuille dans le document. */
}

/* ==========================================================================
   18. Carte date & heure (assets/js/alvyca-calendar.js)
   --------------------------------------------------------------------------
   Toutes les dimensions sont en rem : le calendrier suit le réglage de
   taille du texte comme le reste de l'interface. Rien n'est exprimé en
   pourcentage de la largeur disponible — une carte large ne doit pas
   produire des cases de calendrier démesurées.
   ========================================================================== */

.cal {
  display: flex; flex-direction: column; gap: var(--sp-2);
  background: var(--surface); border: 1px solid var(--sep);
  border-radius: var(--r); padding: var(--sp-3);
  width: 100%; max-width: 19rem; margin-inline: auto;      /* borne haute : la grille reste dense */
}

.cal-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-1); }
.cal-title { font-size: var(--fs-md); font-weight: 600; text-transform: capitalize; letter-spacing: -.01em; }
.cal-nav {
  width: 1.65rem; height: 1.65rem; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 0; border-radius: var(--r-sm);
  color: var(--text-2); cursor: pointer;
  transition: background .12s var(--ease), color .12s var(--ease);
}
.cal-nav:hover { background: var(--surface-hover); color: var(--text); }
.cal-nav svg { width: .8rem; height: .8rem; }

.cal-quick { display: flex; gap: var(--sp-1); flex-wrap: wrap; }
.cal-chip {
  font: inherit; font-size: .6875rem; font-weight: 500; line-height: 1;
  padding: .3rem .45rem; border-radius: var(--r-pill);
  background: var(--surface-2); color: var(--text-2);
  border: 1px solid transparent; cursor: pointer; white-space: nowrap;
  transition: background .12s var(--ease), color .12s var(--ease);
}
.cal-chip:hover { background: var(--surface-3); color: var(--text); }
.cal-chip.on { background: var(--accent-soft); color: var(--accent); border-color: var(--accent); font-weight: 600; }

.cal-dow, .cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; }
.cal-dow span {
  text-align: center; font-size: .625rem; font-weight: 600;
  color: var(--text-3); padding-bottom: 2px;
}

/* Hauteur fixe en rem : la case suit l'échelle du texte, pas le conteneur. */
.cal-day {
  height: 1.85rem; padding: 0;
  display: flex; align-items: center; justify-content: center;
  font: inherit; font-size: var(--fs-sm); font-variant-numeric: tabular-nums;
  color: var(--text); background: transparent;
  border: 1px solid transparent; border-radius: var(--r-sm);
  cursor: pointer;
  transition: background .12s var(--ease), color .12s var(--ease);
}
.cal-day:hover:not(:disabled) { background: var(--surface-hover); }
.cal-day.out  { color: var(--text-3); opacity: .5; }
.cal-day.off  { opacity: .25; cursor: not-allowed; }
/* Le jour courant est cerclé, le jour choisi est plein : deux repères
   distincts qui ne se confondent jamais. */
.cal-day.today { border-color: var(--sep-strong); font-weight: 600; }
.cal-day.on {
  background: var(--accent-fill); color: var(--text-on-accent);
  border-color: transparent; font-weight: 600;
}
.cal-day.on:hover { background: var(--accent-hover); }

.cal-time { display: flex; flex-direction: column; gap: var(--sp-1);
            padding-top: var(--sp-2); border-top: 1px solid var(--sep); }
.cal-time-lbl { font-size: .625rem; font-weight: 600; color: var(--text-3);
                text-transform: uppercase; letter-spacing: .04em; }
/* Dix-huit créneaux tiennent sur trois rangées denses plutôt que d'étirer
   la carte sur toute la hauteur de l'écran. */
.cal-slots {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 2px;
  max-height: 4.6rem; overflow-y: auto;
}
.cal-slots .cal-chip { text-align: center; padding: .3rem .15rem; }
.cal-custom { display: flex; align-items: center; gap: var(--sp-2); }
.cal-custom .input { width: auto; flex: 1; max-width: 8rem; height: 1.9rem;
                     font-size: var(--fs-sm); padding: 0 var(--sp-2); }

.cal-sum {
  font-size: var(--fs-sm); font-weight: 500; color: var(--text);
  padding-top: var(--sp-2); border-top: 1px solid var(--sep);
}
.cal-sum.muted { color: var(--text-3); font-weight: 400; }

/* Sur téléphone, les cases gagnent en hauteur pour rester visées au doigt,
   sans que la carte ne s'élargisse pour autant. */
@media (max-width: 768px) {
  .cal { max-width: none; }
  .cal-day { height: 2.4rem; font-size: var(--fs-base); }
  .cal-chip { padding: .4rem .55rem; font-size: var(--fs-xs); }
  .cal-slots { grid-template-columns: repeat(4, minmax(0, 1fr)); max-height: 6rem; }
}

/*
 * Pastille d'icône — statut d'occupation, type de logement.
 *
 * Un masque plutôt qu'une image : le tracé prend la couleur du texte
 * environnant, donc l'accent du compte, et reste lisible dans les deux
 * thèmes sans qu'on ait à en dessiner deux versions.
 */
.pastille {
  display: inline-block; width: .85rem; height: .85rem;
  vertical-align: -.1rem; margin-right: .3rem; flex: none;
  background: currentColor; color: var(--text-3);
  -webkit-mask-repeat: no-repeat;   mask-repeat: no-repeat;
  -webkit-mask-size: contain;       mask-size: contain;
  -webkit-mask-position: center;    mask-position: center;
}
.pastille[data-icone="vide"]         { -webkit-mask-image: var(--i-vide); mask-image: var(--i-vide); }
.pastille[data-icone="proprietaire"] { -webkit-mask-image: var(--i-cle);  mask-image: var(--i-cle); }
.pastille[data-icone="locataire"]    { -webkit-mask-image: var(--i-sign); mask-image: var(--i-sign); }
.pastille[data-icone="sci"]          { -webkit-mask-image: var(--i-buro); mask-image: var(--i-buro); }
.pastille[data-icone="maison"]       { -webkit-mask-image: var(--i-toit); mask-image: var(--i-toit); }
.pastille[data-icone="appartement"]  { -webkit-mask-image: var(--i-imm);  mask-image: var(--i-imm); }
