/* =========================================================================
   app.css · kit Spyglass concaténé, commun à tous les sites
   Généré par spyglass-redesign/tools/build-app-css.mjs, dans l'ordre de
   css/spyglass.css : tokens.css, brands/spyglass.css, brands/lighthouse.css, brands/nautilus.css, brands/flagship.css, base.css, layout.css, buttons.css, forms.css, feedback.css, data.css, overlays.css, tickets.css, pages.css, booking.css, integration.css.
   Ne pas modifier à la main : modifier le kit puis régénérer. Les styles
   propres au site sont dans sa feuille (spyglass.css, lighthouse.css…).
   ========================================================================= */
@import url("https://fonts.googleapis.com/css2?family=Gabarito:wght@500..800&family=Inter:wght@400..700&family=JetBrains+Mono:wght@400;500;700&display=swap");

/* ── tokens.css ── */
/* =========================================================================
   Spyglass · tokens.css
   Seule source des couleurs, rayons, ombres, polices et durées.
   Thème clair par défaut, thème sombre via <html data-theme="dark">.
   Aucune autre feuille de composant ne contient de couleur de marque.

   Trois couches, toutes à spécificité nulle (:where) : c'est l'ordre des
   feuilles qui décide, jamais la force d'un sélecteur.
     1. Jetons structurels (surfaces, texte, sémantique, forme…), clair puis
        sombre. Communs à toutes les applications.
     2. Entrées de marque par défaut (--brand-*), clair puis sombre. Ce sont
        les valeurs de Spyglass ; chaque marque les remplace dans
        css/brands/<marque>.css (sélection par <html data-brand="…">).
     3. Jetons dérivés (--accent-*, --side-*…), calculés à partir des
        entrées de marque. Les composants ne lisent QUE cette couche.
   ========================================================================= */

/* ═════════════════════════════════════════════════════════
   1. JETONS STRUCTURELS
   ═════════════════════════════════════════════════════════ */
:where(:root, [data-theme="light"]) {
  color-scheme: light;

  /* ── Surfaces ─────────────────────────────────────────── */
  --bg:          #f3f4f9;   /* fond de page */
  --surface:     #fcfcfe;   /* cartes, barres */
  --surface-2:   #f0f2f8;   /* en-têtes discrets, survols */
  --field:       #ffffff;   /* fond des champs de saisie (blanc : contraste sur l'interface) */
  --surface-3:   #e5e8f1;   /* survol appuyé, interrupteur éteint */
  --line:        #dfe3ee;   /* bordure standard */
  --line-2:      #e9ecf3;   /* bordure douce (cartes) */
  --line-strong: #c9d0e2;   /* bordure appuyée, barre de défilement */

  /* ── Texte ────────────────────────────────────────────── */
  --ink:   #14162b;         /* texte principal */
  --ink-2: #4a5070;         /* texte secondaire */
  --ink-3: #6b7394;         /* libellés, dates (contraste AA) */
  --ink-4: #9aa2bd;         /* placeholders, désactivé */

  /* ── Sémantique : signal (pastilles, barres) / encre (texte) / doux (fond) */
  --success: #0dc87a;  --success-ink: #0b8452;  --success-soft: color-mix(in oklab, var(--success) 12%, var(--surface));
  --warning: #f59c1a;  --warning-ink: #a86200;  --warning-soft: color-mix(in oklab, var(--warning) 14%, var(--surface));
  --danger:  #ef4b5e;  --danger-ink:  #c4283c;  --danger-soft:  color-mix(in oklab, var(--danger) 11%, var(--surface));
  --info:    #3b82f6;  --info-ink:    #1f5fd1;  --info-soft:    color-mix(in oklab, var(--info) 11%, var(--surface));
  --neutral: #8a92ad;  --neutral-ink: #5b6383;  --neutral-soft: var(--surface-2);

  /* ── Domaine : statuts, types, priorités ──────────────── */
  --status-new:         var(--info);
  --status-in-progress: var(--warning);
  --status-resolved:    var(--success);
  --status-wontfix:     var(--neutral);

  --type-bug:         var(--danger);
  --type-improvement: var(--warning);   /* même couleur partout : icône, badge, graphique */
  --type-question:    var(--info);
  --type-other:       var(--neutral);

  --prio-low:      var(--success);
  --prio-medium:   #e9b50c;
  --prio-high:     #f07a2b;
  --prio-high-ink: #b84f0c;
  --prio-critical: var(--danger);

  /* ── Couleurs auparavant codées en dur ────────────────── */
  --project-all:     #94a3b8;   /* pastille « Tous les projets » */
  --media-bg:        #0d0f1a;   /* colonne vidéo de connexion, lecteur */
  --strength-1: #ef4b5e;  --strength-2: #f59c1a;  --strength-3: #e9c21a;
  --strength-4: #7cc83e;  --strength-5: #0dc87a;

  /* ── Barre latérale (nuit, dans les deux thèmes) ──────── */
  --side-ink:   #edf0fb;
  --side-ink-2: #b2bad2;
  --side-ink-3: #8089a8;
  --side-line:  #ffffff14;

  /* ── Forme ────────────────────────────────────────────── */
  --r-xs: 6px;
  --r-sm: 10px;
  --r:    14px;
  --r-lg: 18px;
  --r-xl: 22px;
  --r-pill: 999px;

  --shadow-sm:  0 1px 0 #14162b08, 0 1px 3px #14162b0d;
  --shadow:     0 1px 0 #14162b0a, 0 10px 30px -18px #14162b40;
  --shadow-pop: 0 24px 60px -20px #0b102259, 0 2px 8px #0b102214;

  /* ── Typographie ──────────────────────────────────────── */
  --font-display: "Gabarito", ui-sans-serif, system-ui, sans-serif;
  --font-body:    "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono:    "JetBrains Mono", ui-monospace, "Cascadia Code", Menlo, monospace;

  --fs-micro: 11px;
  --fs-xs:    12px;
  --fs-sm:    13px;
  --fs-base:  14px;
  --fs-md:    15px;
  --fs-lg:    17px;
  --fs-xl:    19px;
  --fs-2xl:   26px;
  --fs-3xl:   clamp(28px, 3.4vw, 38px);

  /* ── Mise en page ─────────────────────────────────────── */
  --sidebar-w: 264px;
  --topbar-h:  60px;
  --nav-h:     40px;
  --gutter:    clamp(16px, 2.4vw, 36px);

  /* ── Mouvement ────────────────────────────────────────── */
  --ease:     cubic-bezier(.22, 1, .36, 1);
  --ease-in:  cubic-bezier(.4, 0, 1, 1);
  --dur-fast: .15s;
  --dur:      .25s;
  --dur-slow: .45s;
}

/* ─────────────────────────────────────────────────────────
   Thème sombre (sur <html> ou sur un conteneur d'aperçu)
   ───────────────────────────────────────────────────────── */
:where(:root[data-theme="dark"], [data-theme="dark"]) {
  color-scheme: dark;

  /* Neutres en gris, plus en bleu nuit (demande de Loïc, 02/11 : d'abord pour Lighthouse, puis pour toutes
     les marques). Chaque gris a la même luminosité (OKLab) que le bleu qu'il remplace : contrastes et
     profondeur inchangés. Anciennes valeurs : #0a0d18 #11152a #181d35 #212844 #272e4a #1d2340 #353d5e. */
  --bg:          #0e0e0e;
  --surface:     #171717;
  --surface-2:   #1f1f1f;
  --field:       #1f1f1f;
  --surface-3:   #2a2a2a;
  --line:        #303030;
  --line-2:      #252525;
  --line-strong: #3f3f3f;

  --ink:   #f0f0f0;
  --ink-2: #bdbdbd;
  --ink-3: #949494;
  --ink-4: #6e6e6e;

  --success: #3dd598;  --success-ink: #5be3ab;
  --warning: #f7ad45;  --warning-ink: #fbc06b;
  --danger:  #f6707f;  --danger-ink:  #ff95a1;
  --info:    #6aa3ff;  --info-ink:    #93bcff;
  --neutral: #858585;  --neutral-ink: #aeaeae;

  --success-soft: color-mix(in oklab, var(--success) 16%, var(--surface));
  --warning-soft: color-mix(in oklab, var(--warning) 16%, var(--surface));
  --danger-soft:  color-mix(in oklab, var(--danger) 16%, var(--surface));
  --info-soft:    color-mix(in oklab, var(--info) 16%, var(--surface));

  --prio-high-ink: #ffa26a;

  --shadow-sm:  0 1px 0 #0000004d;
  --shadow:     0 1px 0 #0000004d, 0 12px 32px -20px #000000b3;
  --shadow-pop: 0 30px 70px -20px #000000c0, 0 0 0 1px #ffffff0f;
}

/* ═════════════════════════════════════════════════════════
   2. ENTRÉES DE MARQUE PAR DÉFAUT
   Obligatoires pour une marque : --brand, --brand-ink, --brand-light,
   --brand-hue-2, --brand-side (et leurs valeurs sombres).
   Facultatives (réglages fins, calculés ici si la marque ne les donne pas) :
   tout le reste. Les valeurs exactes de Spyglass vivent dans
   brands/spyglass.css.
   ═════════════════════════════════════════════════════════ */
:where(:root, [data-brand]) {
  /* Obligatoires */
  --brand:       #4f45e9;   /* signal : pastilles, barres, anneau, halo (≥ 3:1 sur surface) */
  --brand-ink:   #3d35c0;   /* texte de marque sur surface et sur --accent-soft (≥ 4.5:1) */
  --brand-light:     #7069ee;   /* variante claire : dégradés, lueurs */
  --brand-hue-2: #3b82f6;   /* seconde teinte des dégradés et du fond de barre latérale */
  --brand-side:  #0b1022;   /* nuit de la barre latérale */

  /* Facultatives */
  --brand-fill:       var(--brand);                                  /* aplat sous du texte (bouton primaire) */
  --brand-on:         #fff;                                          /* texte sur --brand-fill (≥ 4.5:1) */
  --brand-fill-hover: color-mix(in oklab, var(--brand-fill) 84%, #000);
  --brand-chip:       var(--brand-fill);                             /* petites pastilles pleines (compteur, page active) */
  --brand-chip-on:    var(--brand-on);
  --brand-focus:      var(--brand-fill);                             /* contour de focus clavier (≥ 3:1) */
  --brand-grad:       linear-gradient(135deg, color-mix(in oklab, var(--brand) 72%, #000) 0%, color-mix(in oklab, var(--brand) 58%, #000) 55%, color-mix(in oklab, var(--brand-hue-2) 62%, #000) 100%); /* porte des initiales blanches */
  --brand-glow:       color-mix(in oklab, var(--brand-light) 70%, #fff); /* lueur de l'élément actif (barre latérale) */
  --brand-side-2:     color-mix(in oklab, var(--brand-side) 92%, #fff);
  --brand-side-icon:  color-mix(in oklab, var(--brand-glow) 60%, #fff);
  --brand-side-pill:  color-mix(in srgb, var(--brand-light) 19%, transparent);
  --brand-side-pill-line: color-mix(in srgb, var(--brand-glow) 24%, transparent);
  --brand-side-tint:  color-mix(in srgb, var(--brand) 30%, transparent);
  --brand-side-tint-2: color-mix(in srgb, var(--brand-hue-2) 18%, transparent);
  --brand-badge-ring: color-mix(in srgb, var(--brand) 25%, transparent);
  --brand-media-tint: color-mix(in srgb, var(--brand) 40%, transparent);
  --brand-media-tint-2: color-mix(in srgb, var(--brand-hue-2) 25%, transparent);
  --brand-project:    var(--brand-light);                                /* couleur proposée pour un nouveau projet */
}
:where(:root[data-theme="dark"], [data-brand][data-theme="dark"], [data-theme="dark"] [data-brand]:not([data-theme="light"])) {
  --brand:       #8b84ff;
  --brand-ink:   #b0abff;
  --brand-light:     #a49eff;
  --brand-side:  #070a16;
  --brand-side-2: color-mix(in oklab, var(--brand-side) 92%, #fff);
  --brand-on:    #0e0e0e;
  --brand-fill-hover: var(--brand-light);
}

/* ═════════════════════════════════════════════════════════
   3. JETONS DÉRIVÉS : la seule couche lue par les composants
   Recalculés sur <html> et sur tout conteneur qui porte data-brand
   ou data-theme (aperçus du styleguide).
   ═════════════════════════════════════════════════════════ */
:where(:root, [data-brand], [data-theme]) {
  --accent:      var(--brand);
  --accent-ink:  var(--brand-ink);
  --accent-light:    var(--brand-light);
  --accent-2:    var(--accent-light);   /* ancien nom, gardé pour compatibilité : utiliser --accent-light */
  --accent-soft: color-mix(in oklab, var(--accent) 9%, var(--surface));
  --accent-line: color-mix(in oklab, var(--accent) 28%, transparent);
  --accent-ring: color-mix(in oklab, var(--accent) 18%, transparent);
  --accent-grad: var(--brand-grad);
  --accent-fill:       var(--brand-fill);
  --accent-fill-hover: var(--brand-fill-hover);
  --accent-on:         var(--brand-on);
  --accent-chip:       var(--brand-chip);
  --accent-chip-on:    var(--brand-chip-on);
  --accent-focus:      var(--brand-focus);
  --shadow-accent: 0 8px 20px -10px var(--accent);

  /* Barre latérale */
  --side-bg:   var(--brand-side);
  --side-bg-2: var(--brand-side-2);
  --side-pill: var(--brand-side-pill);
  --side-pill-line: var(--brand-side-pill-line);
  --side-glow: var(--brand-glow);
  --side-icon-active: var(--brand-side-icon);
  --side-tint:   var(--brand-side-tint);
  --side-tint-2: var(--brand-side-tint-2);
  --side-badge-ring: var(--brand-badge-ring);

  /* Divers */
  --media-tint:   var(--brand-media-tint);
  --media-tint-2: var(--brand-media-tint-2);
  --project-default: var(--brand-project);
  --chart-accent:      var(--accent);
  --chart-accent-soft: color-mix(in srgb, var(--accent) 15%, transparent);
}
:where(:root[data-theme="dark"], [data-theme="dark"], [data-theme="dark"] [data-brand]:not([data-theme="light"])) {
  --accent-soft: color-mix(in oklab, var(--accent) 16%, var(--surface));
}

/* ─────────────────────────────────────────────────────────
   Couleur de projet (portail) : <div class="has-project-color"
   style="--accent:#0d9488"> recalcule toute la gamme d'accent.
   ───────────────────────────────────────────────────────── */
.has-project-color {
  --accent-ink:  color-mix(in oklab, var(--accent) 78%, #000);
  --accent-light:    color-mix(in oklab, var(--accent) 72%, #fff);
  --accent-2:    var(--accent-light);   /* ancien nom */
  --accent-soft: color-mix(in oklab, var(--accent) 10%, var(--surface));
  --accent-line: color-mix(in oklab, var(--accent) 28%, transparent);
  --accent-ring: color-mix(in oklab, var(--accent) 18%, transparent);
  --accent-grad: linear-gradient(135deg, var(--accent-light), var(--accent));
  --shadow-accent: 0 8px 20px -10px var(--accent);
  --accent-fill: var(--accent);
  --accent-fill-hover: var(--accent-ink);
  --accent-on: #fff;
  --accent-chip: var(--accent);
  --accent-chip-on: #fff;
  --accent-focus: var(--accent);
}
:root[data-theme="dark"] .has-project-color {
  --accent-ink: color-mix(in oklab, var(--accent) 70%, #fff);
  --accent-fill-hover: var(--accent-light);
  --accent-on: #0e0e0e;
}

/* ── brands/spyglass.css ── */
/* =========================================================================
   Marque · Spyglass (référence, marque par défaut)
   S'applique quand <html> n'a pas de data-brand, ou data-brand="spyglass".
   Valeurs historiques exactes du kit v2 : rien ne bouge à l'écran.
   ========================================================================= */

:where(:root:not([data-brand]), [data-brand="spyglass"]) {
  --brand:       #4f45e9;
  --brand-ink:   #3d35c0;
  --brand-light:     #7069ee;
  --brand-hue-2: #3b82f6;
  --brand-side:  #0b1022;

  --brand-fill:       var(--brand);
  --brand-on:         #fff;
  --brand-fill-hover: var(--brand-ink);
  --brand-chip:       var(--brand);
  --brand-chip-on:    #fff;     /* blanc dans les deux thèmes (comportement historique, voir README) */
  --brand-focus:      var(--brand);
  --brand-grad:       linear-gradient(135deg, #5b52f0 0%, #4f45e9 45%, #3b82f6 100%);
  --brand-glow:       #8b84ff;
  --brand-side-2:     #131a33;
  --brand-side-icon:  #b5b0ff;
  --brand-side-pill:  #7069ee30;
  --brand-side-pill-line: #8b84ff3d;
  --brand-side-tint:  #4f45e94d;
  --brand-side-tint-2: #3b82f62e;
  --brand-badge-ring: #4f45e940;
  --brand-media-tint: #4f45e966;
  --brand-media-tint-2: #3b82f640;
  --brand-project:    #6b5fff;
}

:where(:root[data-theme="dark"]:not([data-brand]), [data-brand="spyglass"][data-theme="dark"], [data-theme="dark"] [data-brand="spyglass"]:not([data-theme="light"])) {
  --brand:       #8b84ff;
  --brand-ink:   #b0abff;
  --brand-light:     #a49eff;
  --brand-side:  #070a16;
  --brand-side-2: #0f1428;
  --brand-on:    #0e0e0e;
  --brand-fill-hover: var(--brand-light);
}

/* ── brands/lighthouse.css ── */
/* =========================================================================
   Marque · Lighthouse (réservation d'espaces partagés en résidence)
   <html data-brand="lighthouse">. Vert d'origine : #23AE77.

   Règles de contraste (voir README, « Contrastes ») :
   - #23AE77 ne supporte pas de texte blanc (2,8:1). Il reste la couleur
     d'identité : --brand-light (dégradés, lueurs).
   - --brand (#1F9F6D) est le même vert assombri pour atteindre 3:1 sur les
     surfaces claires : pastilles, barres, anneaux.
   - --brand-fill (#127A54) porte le texte blanc des boutons (5,3:1).
   - --brand-ink (#0E7048) est le vert des textes et liens (≥ 5,5:1).
   - Succès : le vert sémantique de Spyglass (#0DC87A) est trop proche de la
     marque ; Lighthouse le décale vers un vert-jaune (teinte 128° contre
     161° pour la marque), avec encre et fond doux recalculés.
   ========================================================================= */

:where([data-brand="lighthouse"]) {
  --brand:       #1f9f6d;
  --brand-ink:   #0e7048;
  --brand-light:     #23ae77;
  --brand-hue-2: #0f9aa8;
  --brand-side:  #071a19;

  --brand-fill:       #127a54;
  --brand-on:         #fff;
  --brand-fill-hover: #0d6544;
  --brand-grad:       linear-gradient(135deg, #138058 0%, #0e6a47 55%, #0d5560 100%);  /* même dégradé en sombre : il porte du texte blanc */
  --brand-glow:       #5fe0ab;
  --brand-side-2:     #0f2725;
  --brand-side-icon:  #9cf0c9;
  --brand-project:    #23ae77;

  /* Succès décalé (distinct de la marque) */
  --success: #84b818;  --success-ink: #4f6b00;
  /* redéclarés ici pour qu'un aperçu data-brand="lighthouse" posé sur un
     conteneur les recalcule aussi (sur <html>, la valeur est la même) */
  --success-soft: color-mix(in oklab, var(--success) 12%, var(--surface));
  --status-resolved: var(--success);
  --prio-low: var(--success);
  --strength-5: #84b818;
}

:where([data-brand="lighthouse"][data-theme="dark"], [data-theme="dark"] [data-brand="lighthouse"]:not([data-theme="light"])) {
  --brand:       #3fcf94;
  --brand-ink:   #5fe0ab;
  --brand-light:     #7ee8bd;
  --brand-side:  #041110;
  --brand-side-2: #0a1d1b;

  --brand-fill:       #3fcf94;
  --brand-on:         #0e0e0e;
  --brand-fill-hover: #7ee8bd;

  --success: #a9cf3c;  --success-ink: #c2dc5c;
  --success-soft: color-mix(in oklab, var(--success) 16%, var(--surface));
  --strength-5: #a9cf3c;
}

/* ── brands/nautilus.css ── */
/* =========================================================================
   Marque · Nautilus (outil interne de l'agence)
   <html data-brand="nautilus">.
   Bleu nuit #1E2A3A, la couleur du logo (Figma « nemopoint App system »,
   nœud 2060:2590). Choix de Loïc le 03/11/2026 (remplace le violet du 27/10).
   - Clair : #1E2A3A porte le signal, les textes et les boutons (texte blanc,
     14:1) ; barre latérale un cran plus sombre ; variante claire bleu ardoise
     pour les dégradés et les lueurs.
   - Sombre : un bleu nuit serait invisible sur fond sombre : même famille,
     éclaircie (bleu ardoise clair), texte sombre sur les boutons.
   ========================================================================= */

:where([data-brand="nautilus"]) {
  --brand:       #1e2a3a;   /* signal : pastilles, barres, anneaux */
  --brand-ink:   #1e2a3a;   /* textes et liens */
  --brand-light: #5b7393;   /* variante claire : dégradés, lueurs */
  --brand-hue-2: #3b5675;   /* seconde teinte des dégradés */
  --brand-side:  #111923;   /* barre latérale identique en clair et en sombre (Loïc, 03/11) */
  --side-ink-3:  #9ba8bb;   /* libellés de section : 4,5:1 au moins sur la barre éclaircie */
  --brand-fill:       #1e2a3a;   /* bouton primaire (texte blanc) */
  --brand-fill-hover: #2c3d52;
  --brand-side-tint:   #9db2cc5c;   /* coins éclairés de la barre latérale, mêmes qu'en sombre (03/11) */
  --brand-side-tint-2: #8fa6c43d;
  /* Barre latérale : un seul style pour les deux modes (demande de Loïc, 03/11). Ces valeurs sont celles du
     mode sombre (calculées sur sa variante claire #d3deeb) et ne sont pas redéfinies plus bas. */
  --brand-glow:           color-mix(in oklab, #d3deeb 70%, #fff);
  --brand-side-pill:      color-mix(in srgb, #d3deeb 19%, transparent);
  --brand-side-pill-line: color-mix(in srgb, var(--brand-glow) 24%, transparent);
  --brand-side-icon:      color-mix(in oklab, var(--brand-glow) 60%, #fff);
  --side-avatar: linear-gradient(135deg, color-mix(in oklab, #9db2cc 72%, #000) 0%, color-mix(in oklab, #9db2cc 58%, #000) 55%, color-mix(in oklab, #3b5675 62%, #000) 100%);
  --brand-shadow:     #8fa6c4;   /* ombre du logo dans la barre latérale, bleu ardoise clair : le bleu nuit s'y perdait */
}

:where([data-brand="nautilus"][data-theme="dark"], [data-theme="dark"] [data-brand="nautilus"]:not([data-theme="light"])) {
  --brand:       #9db2cc;
  --brand-ink:   #bccbdd;
  --brand-light: #d3deeb;
  --brand-side:  #111923;   /* même nuit, légèrement éclaircie (Loïc, 03/11 ; avant #0b1118) */
  --brand-side-tint:   #9db2cc5c;   /* coins éclairés un peu plus clairs */
  --brand-side-tint-2: #8fa6c43d;
  --brand-fill:       #9db2cc;
  --brand-fill-hover: #b8c8db;
}

/* ── brands/flagship.css ── */
/* =========================================================================
   Marque · FlagShip
   <html data-brand="flagship">. Bleu d'origine (logo) : #02ADFD.

   Règles de contraste (voir README, « Contrastes ») :
   - #02ADFD ne porte pas de texte blanc : il reste la couleur d'identité
     (--brand-light : dégradés, lueurs).
   - --brand est le même bleu assombri pour atteindre 3:1 sur les surfaces
     (pastilles, barres, anneaux), --brand-fill porte le texte blanc des
     boutons, --brand-ink colore les textes et les liens.
   - Barre latérale : nuit bleue plus claire que celle de Spyglass (choix de
     Loïc, 29/10/2026). Les fonds de page restent ceux du kit.
   - Succès : encre un peu plus foncée que celle de Spyglass pour passer 4,5:1
     sur son fond doux (défaut historique de Spyglass, corrigé ici).
   ========================================================================= */

:where([data-brand="flagship"]) {
  --brand:       #0a86c4;
  --brand-ink:   #05669a;
  --brand-light: #02adfd;
  --brand-hue-2: #3b6cf6;
  --brand-side:  #12324d;

  --brand-fill:       #0773ab;
  --brand-on:         #fff;
  --brand-fill-hover: #05608f;
  --brand-glow:       #7fd6ff;
  --brand-project:    #02adfd;

  --success-ink: #0a7a4c;
  --side-ink-3:  #9aa9c4;   /* libellés de section : plus clairs, la nuit de la barre l'étant aussi */
}

:where([data-brand="flagship"][data-theme="dark"], [data-theme="dark"] [data-brand="flagship"]:not([data-theme="light"])) {
  --brand:       #33bdfd;
  --brand-ink:   #7fd2ff;
  --brand-light: #99dcff;
  --brand-side:  #0b2133;

  --brand-fill:       #33bdfd;
  --brand-on:         #0e0e0e;
  --brand-fill-hover: #7fd2ff;

  --success-ink: #5be3ab;   /* valeur sombre du kit, redéclarée : celle du thème clair passerait sinon */
}

/* ── base.css ── */
/* =========================================================================
   Spyglass · base.css
   Remise à zéro, typographie, icônes, utilitaires et animations partagées.
   ========================================================================= */

/* ── Remise à zéro ───────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
html.is-theme-switching *, html.is-theme-switching *::before, html.is-theme-switching *::after { transition: none !important; }
body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--ink);
  font: 400 var(--fs-base)/1.5 var(--font-body);
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4, p, ul, ol, figure, pre { margin: 0; }
ul[class], ol[class] { list-style: none; padding: 0; }
img, svg, video { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: 0; padding: 0; }
code, kbd, pre { font-family: var(--font-mono); }
details > summary { list-style: none; }
details > summary::-webkit-details-marker { display: none; }
:focus-visible { outline: 2px solid var(--accent-focus); outline-offset: 2px; border-radius: 4px; }
::selection { background: var(--accent-ring); }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 8px; border: 2px solid var(--bg); }
[hidden] { display: none !important; }

/* ── Typographie ─────────────────────────────────────────── */
.h1, .h2, .h3 { font-family: var(--font-display); font-weight: 700; color: var(--ink); }
.h1 { font-size: var(--fs-3xl); letter-spacing: -.035em; line-height: 1.05; }
.h2 { font-size: var(--fs-xl);  letter-spacing: -.02em;  line-height: 1.2; }
.h3 { font-size: var(--fs-md);  letter-spacing: -.01em;  line-height: 1.3; }
.text-muted  { color: var(--ink-3); }
.text-soft   { color: var(--ink-2); }
.text-sm     { font-size: var(--fs-sm); }
.text-xs     { font-size: var(--fs-xs); }
.text-mono   { font-family: var(--font-mono); }
.text-num    { font-variant-numeric: tabular-nums; }
.text-strong { font-weight: 600; color: var(--ink); }
.text-danger  { color: var(--danger-ink); }
.text-success { color: var(--success-ink); }
.text-warning { color: var(--warning-ink); }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.visually-hidden { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* Libellé de section (défini, contrairement à l'ancien .section-label) */
.section-label {
  display: flex; align-items: center; gap: 10px;
  margin: 0 0 12px;
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: .09em; text-transform: uppercase;
  color: var(--ink-3);
}
.section-label::after { content: ""; flex: 1; height: 1px; background: var(--line-2); }
.section-label + .section-label, * + .section-label { margin-top: 32px; }

/* ── Icônes (Lucide au trait, sprite <symbol id="i-…">) ───── */
.icon {
  width: 16px; height: 16px; flex: 0 0 auto;
  fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round;
  vertical-align: -.2em; display: inline-block;
}
.icon-xs  { width: 12px; height: 12px; }
.icon-sm  { width: 14px; height: 14px; }
.icon-lg  { width: 20px; height: 20px; }
.icon-xl  { width: 24px; height: 24px; stroke-width: 1.7; }
.icon-2xl { width: 40px; height: 40px; stroke-width: 1.5; }

.type-icon-bug         { color: var(--type-bug); }
.type-icon-improvement { color: var(--type-improvement); }
.type-icon-question    { color: var(--type-question); }
.type-icon-other       { color: var(--type-other); }

/* ── Mise en page générique ──────────────────────────────── */
.stack    { display: flex; flex-direction: column; gap: 16px; }
.stack-sm { gap: 8px; }
.stack-lg { gap: 24px; }
.cluster  { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.cluster-lg { gap: 14px; }
.spacer   { flex: 1; }
.grid       { display: grid; gap: 16px; }
.grid-2     { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3     { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-aside { grid-template-columns: minmax(0, 1fr) 300px; align-items: start; }
.grid-auto  { grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr)); align-items: start; }
@media (max-width: 960px) {
  .grid-2, .grid-3, .grid-aside { grid-template-columns: minmax(0, 1fr); }
}

/* ── Animations d'entrée ─────────────────────────────────── */
.fade-up { opacity: 0; transform: translateY(12px); animation: fade-up .6s var(--ease) forwards; animation-delay: calc(var(--i, 0) * 60ms + 80ms); }
.reveal .reveal__word { display: inline-block; overflow: hidden; vertical-align: bottom; padding-bottom: .08em; margin-bottom: -.08em; }
.reveal .reveal__word > span { display: inline-block; transform: translateY(110%); animation: rise .85s var(--ease) forwards; animation-delay: calc(var(--i, 0) * 55ms); }

@keyframes fade-up  { to { opacity: 1; transform: none; } }
@keyframes fade-in  { from { opacity: 0; } to { opacity: 1; } }
@keyframes rise     { to { transform: none; } }
@keyframes spin     { to { transform: rotate(360deg); } }
@keyframes ping     { 0% { box-shadow: 0 0 0 0 color-mix(in oklab, currentColor 55%, transparent); } 80%, 100% { box-shadow: 0 0 0 7px transparent; } }
@keyframes blink    { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .35; transform: scale(.7); } }
@keyframes shimmer  { from { background-position: 150% 0; } to { background-position: -150% 0; } }
@keyframes sweep    { from { transform: translateX(-120%); } to { transform: translateX(320%); } }
@keyframes draw     { to { stroke-dashoffset: 0; } }
@keyframes pop-in   { from { opacity: 0; transform: translateY(8px) scale(.97); } to { opacity: 1; transform: none; } }
@keyframes glow-success {
  0%   { box-shadow: 0 0 0 0 color-mix(in oklab, var(--success) 55%, transparent), var(--shadow); }
  30%  { box-shadow: 0 0 0 6px color-mix(in oklab, var(--success) 22%, transparent), var(--shadow); }
  100% { box-shadow: 0 0 0 0 transparent, var(--shadow); }
}

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

/* ── layout.css ── */
/* =========================================================================
   Spyglass · layout.css
   Squelette de l'application : .app, .sidebar, .topbar, .page, .breadcrumb,
   .brand. Responsive : barre latérale hors champ sous 960 px.
   ========================================================================= */

/* ── Marque ──────────────────────────────────────────────── */
.brand { display: inline-flex; align-items: center; gap: 11px; }
.brand__logo {
  width: 36px; height: 36px; flex: 0 0 auto;
  border-radius: 10px; overflow: hidden;
  box-shadow: 0 6px 18px -6px var(--accent);
}
.brand__logo img { width: 100%; height: 100%; object-fit: cover; }
.brand__name { font: 700 21px/1 var(--font-display); letter-spacing: -.03em; color: var(--ink); }
.brand-sm .brand__logo { width: 28px; height: 28px; border-radius: 8px; }
/* Logo de la barre latérale : ombre portée sombre teintée de la marque, comme l'« Ombre teintée » du logo Figma
   (double de la tuile plus petit, décalé vers le bas et flou, à 55 %), plus un fin contour d'ombre */
.sidebar .brand__logo {
  box-shadow: 0 1px 2px rgb(0 0 0 / .18),
              0 4px 6px -2px color-mix(in oklab, color-mix(in oklab, var(--brand-shadow, var(--brand)) 55%, #000) 55%, transparent);
  /* --brand-shadow : teinte de cette ombre, la couleur de marque par défaut ; une marque très sombre (Nautilus)
     en donne une plus claire, sinon l'ombre se confond avec le fond de la barre latérale */
}
.brand-sm .brand__name { font-size: 19px; }
/* Identité d'application : logo + nom + sous-titre facultatif (marque, résidence…) */
.brand__text { display: flex; flex-direction: column; min-width: 0; }
.brand__tagline { display: block; margin-top: 3px; font: 500 var(--fs-xs)/1.2 var(--font-body); letter-spacing: 0; color: var(--ink-3); }
.sidebar .brand__tagline { color: var(--side-ink-3); }
/* Monogramme quand l'application n'a pas encore de logo (ex. Nautilus) */
.brand__mark { display: grid; place-items: center; width: 100%; height: 100%; font: 800 15px/1 var(--font-display); color: #fff; background: var(--accent-grad); }
.brand-sm .brand__mark { font-size: 13px; }

/* ── Application ─────────────────────────────────────────── */
.app {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  min-height: 100vh;
}
.app__main {
  min-width: 0; display: flex; flex-direction: column;
  /* Fond de l'application : trame de points discrète (couleur du texte à 7 %), comme le styleguide */
  background-color: var(--bg);
  background-image: radial-gradient(color-mix(in oklab, var(--ink) 7%, transparent) 1px, transparent 1px);
  background-size: 16px 16px;
}

/* ── Barre latérale ──────────────────────────────────────── */
.sidebar {
  position: sticky; top: 0; z-index: 40;
  height: 100vh; overflow-y: auto;
  display: flex; flex-direction: column; gap: 14px;
  padding: 16px 12px 12px;
  color: var(--side-ink);
  background:
    radial-gradient(120% 45% at 0% 0%, var(--side-tint), transparent 62%),
    radial-gradient(90% 35% at 0% 100%, var(--side-tint-2), transparent 60%),
    var(--side-bg);
  border-right: 1px solid var(--side-line);
}
.sidebar .brand { padding: 4px 8px 8px; }
.sidebar .brand__name { color: var(--side-ink); }
.sidebar__nav { position: relative; display: flex; flex-direction: column; }
/* Sélecteur de contexte (résidence, organisation…) : un .dropdown habillé nuit */
.sidebar__switch .dropdown__trigger {
  min-width: 0; height: auto; padding-block: 8px; color: var(--side-ink); background: var(--side-bg-2);   /* hauteur donnée par le padding (deux lignes : nom et nombre) */
  border-color: var(--side-line); box-shadow: none;
}
.sidebar__switch .dropdown__trigger:hover { border-color: color-mix(in oklab, var(--side-ink) 22%, transparent); }
.sidebar__switch.is-open .dropdown__trigger { border-color: var(--side-glow); box-shadow: 0 0 0 3px var(--side-pill); }
.sidebar__switch .dropdown__chevron { color: var(--side-ink-3); }
.sidebar__switch-meta { display: block; font-size: var(--fs-micro); font-weight: 500; color: var(--side-ink-3); }
/* Le menu s'ouvre dans le flux : la barre latérale défile, un menu flottant y serait rogné */
.sidebar__switch .dropdown__menu {
  position: static; display: none; margin-top: 6px; opacity: 1; transform: none; pointer-events: auto;
  background: var(--side-bg-2); border-color: var(--side-line); box-shadow: none;
}
.sidebar__switch.is-open .dropdown__menu { display: block; animation: fade-in var(--dur) var(--ease); }
.sidebar__switch .dropdown__group { color: var(--side-ink-3); }
.sidebar__switch .dropdown__item { color: var(--side-ink-2); }
.sidebar__switch .dropdown__item:hover { color: var(--side-ink); background: color-mix(in oklab, var(--side-ink) 7%, transparent); }
.sidebar__switch .dropdown__item.is-active { color: var(--side-ink); background: var(--side-pill); }
.sidebar__switch .dropdown__check { color: var(--side-glow); }
.sidebar__section + .sidebar__section { margin-top: 14px; }
.sidebar__label {
  display: block; margin: 6px 10px 6px;
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: .09em; text-transform: uppercase;
  color: var(--side-ink-3);
}
.sidebar__item {
  position: relative; z-index: 1;
  display: flex; align-items: center; gap: 11px;
  height: var(--nav-h); padding: 0 10px;
  border-radius: var(--r-sm);
  font-size: var(--fs-md); font-weight: 500;
  color: var(--side-ink-2);
  transition: color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.sidebar__item .icon { width: 17px; height: 17px; color: var(--side-ink-3); transition: color var(--dur); }
.sidebar__item:hover { color: var(--side-ink); background: #ffffff08; }
.sidebar__item:hover .icon { color: var(--side-ink-2); }
.sidebar__item.is-active { color: var(--side-ink); background: transparent; }
.sidebar__item.is-active .icon { color: var(--side-icon-active); }
.sidebar__item-badge {
  margin-left: auto; min-width: 22px; height: 20px; padding: 0 7px;
  display: grid; place-items: center;
  border-radius: var(--r-pill);
  font-size: var(--fs-micro); font-weight: 700;
  color: var(--accent-chip-on); background: var(--accent-chip);
  box-shadow: 0 0 0 3px var(--side-badge-ring);
}
/* Pastille glissante : suit l'élément actif (positionnée par spyglass.js) */
.sidebar__pill {
  position: absolute; left: 0; right: 0; top: 0; height: var(--nav-h);
  border-radius: var(--r-sm);
  background: var(--side-pill); border: 1px solid var(--side-pill-line);
  transition: transform var(--dur-slow) var(--ease), opacity var(--dur);
  pointer-events: none; opacity: 0;
}
.sidebar__pill.is-ready { opacity: 1; }
.sidebar__pill.is-instant { transition: none; }   /* pose sans glissement (chargement, polices, redimensionnement) */
.sidebar__pill::before {
  content: ""; position: absolute; left: -12px; top: 10px; bottom: 10px; width: 3px;
  border-radius: 3px; background: var(--side-glow); box-shadow: 0 0 12px var(--side-glow);
}
.sidebar__footer {
  margin-top: auto;
  display: flex; align-items: center; gap: 10px;
  padding: 10px;
  border: 1px solid var(--side-line); border-radius: var(--r);
  background: var(--side-bg-2);
}
.sidebar__user { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; border-radius: var(--r-sm); }
.sidebar__user-text { display: flex; flex-direction: column; min-width: 0; line-height: 1.3; }
.sidebar__user-name { font-size: var(--fs-base); font-weight: 600; color: var(--side-ink); }
.sidebar__user-meta { font-size: var(--fs-xs); color: var(--side-ink-3); }
/* Avatar du compte : --side-avatar si la marque en donne un (Nautilus : même barre en clair et en sombre), sinon le dégradé de marque */
.sidebar__user .avatar { background: var(--side-avatar, var(--accent-grad)); }
.sidebar__logout {
  width: 32px; height: 32px; flex: 0 0 auto;
  display: grid; place-items: center; border-radius: 9px;
  color: var(--side-ink-3); transition: color var(--dur), background-color var(--dur);
}
.sidebar__logout:hover { color: #ff95a1; background: #f6707f1f; }

/* ── Barre du haut ───────────────────────────────────────── */
.topbar {
  position: sticky; top: 0; z-index: 30;
  height: var(--topbar-h);
  display: flex; align-items: center; gap: 12px;
  padding: 0 var(--gutter);
  background: color-mix(in oklab, var(--bg) 82%, transparent);
  backdrop-filter: saturate(1.4) blur(12px);
  -webkit-backdrop-filter: saturate(1.4) blur(12px);
  border-bottom: 1px solid var(--line-2);
}
.topbar__menu { display: none; }
.topbar__title { font: 600 var(--fs-md) var(--font-body); color: var(--ink); }
/* Titre de la barre du haut : il n'apparaît (en fondu) qu'une fois l'en-tête de page passé sous la
   barre, piloté par le défilement (scroll-driven animation). La frise --page-head suit l'en-tête de la
   page (enfant direct de .page, un seul par page) ; le décalage de --topbar-h fait comme si la zone
   visible commençait sous la barre. Sans en-tête de page, la frise est inactive et le titre reste
   affiché ; un navigateur qui ne connaît pas ces animations l'affiche aussi. (Demande de Loïc, 29/10.) */
@supports (animation-timeline: view()) {
  .app__main { timeline-scope: --page-head; }
  .page > .page__header { view-timeline: --page-head block; view-timeline-inset: var(--topbar-h) 0; }
  .topbar__title {
    animation: topbar-title linear both;
    animation-timeline: --page-head;
    animation-range: exit 40% exit 100%;
  }
}
@keyframes topbar-title { from { opacity: 0; } to { opacity: 1; } }
/* Barre du haut sans fond tant que la page n'a pas défilé : le fond flouté et le filet reviennent sur les
   48 premiers pixels de défilement (scroll-driven animation). L'état de base est SANS fond et l'animation
   l'ajoute : une page trop courte pour défiler n'a pas de frise active, donc pas d'animation, et la barre
   reste sans fond. Un navigateur qui ne connaît pas ces animations garde le fond (règle .topbar plus haut).
   Sur grand écran, la barre passe par-dessus le haut de la page, dont le contenu commence à 70 px du haut
   du navigateur. (Demande de Loïc, 29/10.) */
@supports (animation-timeline: scroll()) {
  .topbar {
    background-color: transparent; border-bottom-color: transparent;
    backdrop-filter: none; -webkit-backdrop-filter: none;
    animation: topbar-bg linear both;
    animation-timeline: scroll(root block);
    animation-range: 0 48px;
  }
}
@keyframes topbar-bg {
  from { background-color: transparent; border-bottom-color: transparent; backdrop-filter: none; -webkit-backdrop-filter: none; }
  to {
    background-color: color-mix(in oklab, var(--bg) 82%, transparent); border-bottom-color: var(--line-2);
    backdrop-filter: saturate(1.4) blur(12px); -webkit-backdrop-filter: saturate(1.4) blur(12px);
  }
}
@media (min-width: 961px) {
  .topbar { margin-bottom: calc(-1 * var(--topbar-h)); }
  .app__main > .page { padding-top: 70px; }   /* plus précis que .page, défini plus bas */
}
.topbar__actions { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.topbar__divider { width: 1px; height: 22px; background: var(--line); margin: 0 4px; }

/* ── Page ────────────────────────────────────────────────── */
.page { width: 100%; padding: 28px var(--gutter) 72px; }   /* pleine largeur : pas de limite sur grand écran */
.page__header {
  display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
  gap: 16px 24px; margin-bottom: 24px;
}
/* Message posé directement dans la page (flash en haut, erreur sous l'en-tête) : même écart que sous l'en-tête */
.page > .alert { margin-bottom: 24px; }
.page__heading { flex: 1 1 360px; min-width: 0; }
.page__eyebrow { margin-bottom: 6px; font-size: var(--fs-sm); font-weight: 500; color: var(--ink-3); }
.page__title {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  font: 700 var(--fs-3xl)/1.05 var(--font-display); letter-spacing: -.035em; color: var(--ink);
}
/* Titre fait de texte saisi (ex. titre d'un rapport) : Inter, plus lisible que la police de titre */
.page__title-text { font-family: var(--font-body); font-size: var(--fs-2xl); line-height: 1.2; letter-spacing: -.02em; }
.page__title-icon {
  width: 40px; height: 40px; flex: 0 0 auto;
  display: grid; place-items: center;
  border-radius: 12px; color: var(--accent-ink); background: var(--accent-soft);
}
.page__subtitle { margin-top: 8px; font-size: var(--fs-md); color: var(--ink-2); }
.page__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

/* ── Fil d'Ariane ────────────────────────────────────────── */
.breadcrumb { display: flex; align-items: center; gap: 8px; font-size: var(--fs-sm); font-weight: 500; }
.breadcrumb__item { color: var(--ink-3); transition: color var(--dur); }
a.breadcrumb__item:hover { color: var(--ink); }
.breadcrumb__item[aria-current="page"] { color: var(--ink); font-weight: 600; }
.breadcrumb__sep { width: 14px; height: 14px; color: var(--ink-4); }

/* ── Mobile : barre latérale hors champ ──────────────────── */
.sidebar-scrim { display: none; }
@media (max-width: 960px) {
  .app { grid-template-columns: minmax(0, 1fr); }
  .sidebar {
    position: fixed; inset: 0 auto 0 0; width: min(var(--sidebar-w), 86vw);
    transform: translateX(-102%); transition: transform var(--dur-slow) var(--ease);
  }
  .sidebar.is-open { transform: none; box-shadow: var(--shadow-pop); }
  .sidebar-scrim {
    display: block; position: fixed; inset: 0; z-index: 35;
    background: #0b102266; backdrop-filter: blur(2px);
    opacity: 0; pointer-events: none; transition: opacity var(--dur);
  }
  .sidebar-scrim.is-open { opacity: 1; pointer-events: auto; }
  .topbar__menu { display: grid; }
  .page { padding-top: 20px; }
}

/* ── buttons.css ── */
/* =========================================================================
   Spyglass · buttons.css
   .btn (+ variantes et tailles), .link, .segmented, .tabs, .pills
   Variante : .btn-primary | .btn-secondary | .btn-ghost | .btn-danger | .btn-success
   Taille   : .btn-xs | .btn-sm | (défaut) | .btn-lg     Forme : .btn-icon | .btn-block
   État     : :disabled / [aria-disabled="true"] | .is-loading | .is-done
   ========================================================================= */

.btn {
  --btn-h: 40px;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: var(--btn-h); padding: 0 16px;
  border: 1px solid transparent; border-radius: 12px;
  font-size: var(--fs-base); font-weight: 600; line-height: 1; white-space: nowrap;
  color: var(--ink); background: var(--surface-2);
  transition: background-color var(--dur), border-color var(--dur), color var(--dur),
              box-shadow var(--dur), transform var(--dur) var(--ease);
  user-select: none;
}
.btn:active { transform: scale(.97); }
.btn .icon { width: 15px; height: 15px; }

/* Variantes */
/* Aplat de marque : --accent-fill et son texte --accent-on (contraste AA garanti par la marque) */
.btn-primary { color: var(--accent-on); background: var(--accent-fill); box-shadow: var(--shadow-accent); }
.btn-primary:hover { background: var(--accent-fill-hover); }

.btn-secondary { color: var(--ink); background: var(--surface); border-color: var(--line); box-shadow: var(--shadow-sm); }
.btn-secondary:hover { background: var(--surface-2); border-color: var(--line-strong); }

.btn-ghost { color: var(--ink-2); background: transparent; }
.btn-ghost:hover { color: var(--ink); background: var(--surface-2); }

.btn-danger { color: var(--danger-ink); background: var(--danger-soft); }
.btn-danger:hover { background: color-mix(in oklab, var(--danger) 20%, var(--surface)); }

.btn-success { color: var(--success-ink); background: var(--success-soft); }
.btn-success:hover { background: color-mix(in oklab, var(--success) 22%, var(--surface)); }

.btn-dark { color: var(--surface); background: var(--ink); }
.btn-dark:hover { background: color-mix(in oklab, var(--ink) 86%, var(--accent)); }

/* Tailles */
.btn-xs { --btn-h: 26px; padding: 0 9px;  gap: 6px; border-radius: 8px;  font-size: var(--fs-xs); }
.btn-sm { --btn-h: 32px; padding: 0 12px; gap: 7px; border-radius: 10px; font-size: var(--fs-sm); }
.btn-lg { --btn-h: 46px; padding: 0 22px; border-radius: 13px; font-size: var(--fs-md); }
.btn-xs .icon { width: 13px; height: 13px; }
.btn-sm .icon { width: 14px; height: 14px; }

/* Formes */
.btn-icon { width: var(--btn-h); padding: 0; }
.btn-block { display: flex; width: 100%; }

/* Pastille d'état dans un bouton (ex. portail actif / inactif) */
/* overflow: hidden garde les points de suspension d'un libellé trop long (mobile) ; line-height 1.3 car avec le
   line-height: 1 du bouton, la boîte coupait le bas des lettres (p, g, q) */
.btn__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; line-height: 1.3; }
.btn__dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.btn__dot-off { background: transparent; box-shadow: inset 0 0 0 1.5px currentColor; }

/* États */
.btn:disabled, .btn[aria-disabled="true"] {
  opacity: .45; cursor: not-allowed; box-shadow: none; transform: none; pointer-events: none;
}
/* Occupé : plus de clic, le libellé dit ce qui se passe. Aucune icône ne tourne (choix de Loïc, 27/10). */
.btn.is-loading { pointer-events: none; }
.btn.is-done { color: var(--success-ink); }

/* ── Lien d'action avec flèche ───────────────────────────── */
.link {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-sm); font-weight: 600; color: var(--accent-ink);
}
.link .icon { width: 14px; height: 14px; transition: transform var(--dur) var(--ease); }
.link:hover .icon { transform: translateX(3px); }
.link-muted { color: var(--ink-3); font-weight: 500; }
.link-muted:hover { color: var(--ink); }

/* ── Contrôle segmenté (pastille glissante) ──────────────── */
.segmented {
  position: relative; display: inline-flex; padding: 4px;
  border-radius: 12px; background: var(--surface-2); border: 1px solid var(--line-2);
}
.segmented__item {
  position: relative; z-index: 1;
  display: inline-flex; align-items: center; gap: 7px;
  height: 32px; padding: 0 13px; border-radius: 9px;
  font-size: var(--fs-sm); font-weight: 600; color: var(--ink-3);
  transition: color var(--dur);
}
.segmented__item .icon { width: 14px; height: 14px; }
.segmented__item:hover { color: var(--ink-2); }
.segmented__item.is-active { color: var(--ink); }
.segmented__thumb {
  position: absolute; top: 4px; bottom: 4px; left: 0;
  border-radius: 9px; background: var(--surface); box-shadow: var(--shadow-sm), 0 0 0 1px var(--line-2);
  transition: transform var(--dur-slow) var(--ease), width var(--dur-slow) var(--ease);
}
:root[data-theme="dark"] .segmented__thumb { background: var(--surface-3); }
.segmented-sm .segmented__item { height: 26px; padding: 0 10px; font-size: var(--fs-xs); }

/* ── Onglets soulignés (indicateur glissant) ─────────────── */
.tabs { position: relative; display: flex; border-bottom: 1px solid var(--line-2); }
.tabs__item {
  flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 46px; font-size: var(--fs-sm); font-weight: 600; color: var(--ink-3);
  transition: color var(--dur), background-color var(--dur);
}
.tabs__item:hover { color: var(--ink); background: var(--surface-2); }
/* Barre d'onglets en haut d'une carte : le survol du premier et du dernier onglet suit les coins arrondis de la carte
   au lieu de déborder en carré sur son contour */
.card > .tabs:first-child .tabs__item:first-of-type { border-top-left-radius: calc(var(--r-lg) - 1px); }
.card > .tabs:first-child .tabs__item:last-of-type { border-top-right-radius: calc(var(--r-lg) - 1px); }
.tabs__item.is-active { color: var(--accent-ink); }
.tabs__item.has-news:not(.is-active)::after {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  color: var(--accent); background: currentColor; animation: ping 2.2s var(--ease) infinite;
}
.tabs__indicator {
  position: absolute; bottom: -1px; left: 0; height: 2px; border-radius: 2px;
  background: var(--accent);
  transition: transform var(--dur-slow) var(--ease), width var(--dur-slow) var(--ease);
}
.tabs__panel { display: none; }
.tabs__panel.is-active { display: block; animation: fade-in var(--dur) var(--ease); }

/* ── Pilules de filtre ───────────────────────────────────── */
.pills { display: flex; flex-wrap: wrap; gap: 6px; }
.pills__item {
  display: inline-flex; align-items: center; gap: 7px;
  height: 36px; padding: 0 14px;
  border: 1px solid var(--line); border-radius: var(--r-pill);
  font-size: var(--fs-sm); font-weight: 600; color: var(--ink-2); background: var(--surface);
  transition: background-color var(--dur), color var(--dur), border-color var(--dur);
}
.pills__item .icon { width: 14px; height: 14px; }
.pills__item:hover { border-color: var(--ink-4); color: var(--ink); }
.pills__item.is-active { color: var(--surface); background: var(--ink); border-color: var(--ink); }
.pills__item.is-active .icon { color: inherit; }
.pills__count { font-size: var(--fs-xs); color: var(--ink-3); }
.pills__item.is-active .pills__count { color: inherit; opacity: .65; }

/* ── forms.css ── */
/* =========================================================================
   Spyglass · forms.css
   .form, .field, .input / .select / .textarea, .input-group, .search,
   .checkbox, .radio, .switch, .setting, .strength, .access-list, .kbd
   ========================================================================= */

/* ── Structure ───────────────────────────────────────────── */
.form { display: flex; flex-direction: column; gap: 16px; }
.form__row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.form__row-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.form__actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 8px; }
@media (max-width: 640px) { .form__row, .form__row-3 { grid-template-columns: minmax(0, 1fr); } }

.field { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.field__label { font-size: var(--fs-sm); font-weight: 600; color: var(--ink-2); }
.field__label-note { font-weight: 400; color: var(--ink-3); }
.field__required { color: var(--danger-ink); }
.field__hint { font-size: var(--fs-xs); color: var(--ink-3); }
.field__feedback { display: flex; align-items: center; gap: 6px; font-size: var(--fs-xs); font-weight: 500; }
.field__feedback .icon { width: 13px; height: 13px; }
.field__feedback.is-valid   { color: var(--success-ink); }
.field__feedback.is-invalid { color: var(--danger-ink); }

/* ── Champs ──────────────────────────────────────────────── */
.input, .select, .textarea {
  width: 100%; min-width: 0;
  height: 42px; padding: 0 13px;
  border: 1px solid var(--line); border-radius: 11px;
  font-size: var(--fs-base); color: var(--ink); background-color: var(--field);
  outline: 0;
  transition: border-color var(--dur), box-shadow var(--dur), background-color var(--dur);
}
.input::placeholder, .textarea::placeholder { color: var(--ink-4); }
.input:hover, .select:hover, .textarea:hover { border-color: var(--line-strong); }
.input:focus, .select:focus, .textarea:focus {
  border-color: var(--accent); background-color: var(--field);   /* background-color seul : le raccourci background effaçait la flèche du select */
  box-shadow: 0 0 0 4px var(--accent-ring);
}
.input.is-invalid, .textarea.is-invalid { border-color: var(--danger); box-shadow: 0 0 0 4px var(--danger-soft); }
.input.is-valid { border-color: var(--success); }
.input[readonly] { color: var(--ink-3); background: transparent; border-color: var(--line-2); border-style: dashed; cursor: default; }
.input[readonly]:focus { box-shadow: none; border-color: var(--line); }
.input:disabled, .select:disabled { opacity: .55; cursor: not-allowed; }

.textarea { height: auto; min-height: 88px; padding: 11px 13px; line-height: 1.55; resize: vertical; }
.select {
  appearance: none; padding-right: 36px; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' fill='none' stroke='%238b93b0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' viewBox='0 0 24 24'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center;
}
/* Liste ouverte : flèche vers le haut. :open à part (une règle avec un sélecteur inconnu serait ignorée en entier) ;
   .is-open est posé par spyglass.js là où :open n'existe pas. */
.select:open { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' fill='none' stroke='%238b93b0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' viewBox='0 0 24 24'%3E%3Cpath d='m18 15-6-6-6 6'/%3E%3C/svg%3E"); }
.select.is-open { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' fill='none' stroke='%238b93b0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' viewBox='0 0 24 24'%3E%3Cpath d='m18 15-6-6-6 6'/%3E%3C/svg%3E"); }
.select-auto { width: auto; }
/* Ouverture dessinée d'un .select (spyglass.js, sur ordinateur) : le menu .dropdown__menu du kit, posé sous le
   champ dans <body> (position fixe, au-dessus des modales), l'option choisie teintée, la surbrillance au clavier
   comme au survol. */
.select.is-open { border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-ring); }
.dropdown__menu.select-menu { position: fixed; top: 0; left: 0; z-index: 200; max-width: min(480px, calc(100vw - 24px)); }
.dropdown__menu.select-menu.is-open { opacity: 1; transform: none; pointer-events: auto; }
.dropdown__menu.select-menu.is-above { transform: translateY(6px) scale(.98); transform-origin: bottom left; }
.dropdown__menu.select-menu.is-above.is-open { transform: none; }
.select-menu .dropdown__item { height: auto; min-height: 38px; padding: 9px 10px; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; line-height: 1.35; }
.select-menu-sm .dropdown__item { min-height: 34px; padding: 7px 10px; }
.select-menu .dropdown__item.is-highlighted:not(.is-active) { color: var(--ink); background: var(--surface-2); }
.select-menu .dropdown__item.is-active.is-highlighted { background: color-mix(in oklab, var(--accent) 16%, var(--surface)); }
.select-menu .dropdown__item:hover:not(.is-highlighted) { background: transparent; color: var(--ink-2); }
.select-menu .dropdown__item.is-active:hover:not(.is-highlighted) { color: var(--accent-ink); background: var(--accent-soft); }
.select-menu .dropdown__item.is-disabled { opacity: .45; cursor: default; }
@media (prefers-reduced-motion: reduce) { .dropdown__menu.select-menu { transition: none; } }

.input-sm, .select-sm { height: 32px; padding: 0 10px; border-radius: 9px; font-size: var(--fs-sm); }
.select-sm { padding-right: 30px; background-position: right 9px center; }
.input-mono { font-family: var(--font-mono); font-size: var(--fs-xs); }
.input-copy { cursor: copy; }
.input-copy:hover { color: var(--accent-ink); border-color: var(--accent-line); }

.input-color { padding: 5px; cursor: pointer; }
.input-color::-webkit-color-swatch-wrapper { padding: 0; }
.input-color::-webkit-color-swatch { border: 0; border-radius: 7px; }
.input-color::-moz-color-swatch { border: 0; border-radius: 7px; }

/* Fichier : bouton intégré au style des boutons secondaires */
.input-file { height: auto; padding: 6px; font-size: var(--fs-sm); color: var(--ink-3); }
.input-file::file-selector-button {
  margin-right: 12px; height: 30px; padding: 0 12px;
  border: 1px solid var(--line); border-radius: 8px;
  font: 600 var(--fs-sm) var(--font-body); color: var(--ink); background: var(--surface);
  cursor: pointer; transition: background-color var(--dur);
}
.input-file::file-selector-button:hover { background: var(--surface-3); }

/* Champ + bouton accolés */
.input-group { display: flex; align-items: center; gap: 8px; }
.input-group > .input, .input-group > .select { flex: 1; }
.input-group > .select-fixed { flex: 0 0 150px; }

/* ── Recherche ───────────────────────────────────────────── */
.search {
  position: relative; display: flex; align-items: center; gap: 9px;
  height: 42px; padding: 0 12px;
  border: 1px solid var(--line); border-radius: 12px;
  color: var(--ink-3); background: var(--field);
  transition: border-color var(--dur), background-color var(--dur), box-shadow var(--dur);
}
.search:hover { border-color: var(--line-strong); }
.search:focus-within { border-color: var(--accent); background: var(--field); box-shadow: 0 0 0 4px var(--accent-ring); }
.search__icon { width: 16px; height: 16px; }
.search__input { flex: 1; min-width: 0; height: 100%; border: 0; background: none; outline: 0; color: var(--ink); font-size: var(--fs-base); }
.search__input::placeholder { color: var(--ink-4); }
.search:focus-within .kbd { opacity: 0; }

/* ── Touche clavier ──────────────────────────────────────── */
.kbd {
  display: inline-grid; place-items: center; min-width: 22px; height: 22px; padding: 0 6px;
  border-radius: 6px; border: 1px solid var(--line); border-bottom-width: 2px;
  font: 600 var(--fs-micro) var(--font-mono); color: var(--ink-3); background: var(--surface);
  transition: opacity var(--dur);
}

/* ── Case à cocher et bouton radio (coche dessinée) ──────── */
.checkbox, .radio {
  display: inline-flex; align-items: center; gap: 9px;
  font-size: var(--fs-sm); font-weight: 500; color: var(--ink-2);
  cursor: pointer; user-select: none;
}
.checkbox__input, .radio__input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.checkbox__box, .radio__box {
  width: 20px; height: 20px; flex: 0 0 auto;
  display: grid; place-items: center;
  border: 1.5px solid var(--line-strong); border-radius: 7px; background: var(--surface);
  transition: background-color var(--dur), border-color var(--dur), box-shadow var(--dur);
}
.radio__box { border-radius: 50%; }
.checkbox__box svg {
  width: 13px; height: 13px; fill: none; stroke: var(--accent-on); stroke-width: 3.2;
  stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 22; stroke-dashoffset: 22;
  transition: stroke-dashoffset .3s var(--ease) .04s;
}
.radio__box::after { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--accent-on); transform: scale(0); transition: transform var(--dur) var(--ease); }
.checkbox:hover .checkbox__box, .radio:hover .radio__box { border-color: var(--accent); }
.checkbox__input:checked + .checkbox__box,
.radio__input:checked + .radio__box { background: var(--accent-fill); border-color: var(--accent-fill); }
.checkbox__input:checked + .checkbox__box svg { stroke-dashoffset: 0; }
.radio__input:checked + .radio__box::after { transform: scale(1); }
.checkbox__input:focus-visible + .checkbox__box,
.radio__input:focus-visible + .radio__box { box-shadow: 0 0 0 4px var(--accent-ring); }
.checkbox__label { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; }
.checkbox__code { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--ink-3); }

.choice-list { display: flex; flex-direction: column; gap: 10px; }
.choice-list-inline { flex-direction: row; flex-wrap: wrap; gap: 8px 18px; }

/* ── Interrupteur ────────────────────────────────────────── */
.switch { position: relative; display: inline-flex; flex: 0 0 auto; cursor: pointer; }
.switch__input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.switch__track {
  position: relative; width: 42px; height: 24px; border-radius: var(--r-pill);
  background: var(--surface-3); box-shadow: inset 0 0 0 1px var(--line);
  transition: background-color var(--dur), box-shadow var(--dur);
}
.switch__track::after {
  content: ""; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px #0003;
  transition: transform var(--dur-slow) var(--ease);
}
.switch__input:checked + .switch__track { background: var(--accent-fill); box-shadow: none; }
.switch__input:checked + .switch__track::after { transform: translateX(18px); }
.switch__input:focus-visible + .switch__track { box-shadow: 0 0 0 4px var(--accent-ring); }
/* Interrupteur d'alerte (ex. « C'est urgent ») */
.switch-danger .switch__input:checked + .switch__track { background: var(--danger); }

/* Ligne de réglage : texte à gauche, contrôle à droite */
.setting {
  display: flex; align-items: center; justify-content: space-between; gap: 18px;
  padding: 14px 0; border-bottom: 1px solid var(--line-2);
}
.setting:first-child { padding-top: 0; }
.setting:last-child { border-bottom: 0; padding-bottom: 0; }
/* Réglage d'alerte (ex. « C'est urgent ») : encadré gris clair, même padding sur les quatre côtés ;
   rouge pâle une fois activé, sans marge négative (.setting.setting-danger passe devant :first-child / :last-child) */
.setting.setting-danger { padding: 14px; border-bottom: 0; border-radius: var(--r); background: var(--surface-2); transition: background-color var(--dur); }
.setting.setting-danger:has(.switch__input:checked) { background: var(--danger-soft); }
.setting__title { font-size: var(--fs-base); font-weight: 600; color: var(--ink); }
.setting__desc { margin-top: 2px; font-size: var(--fs-sm); color: var(--ink-3); }

/* ── Jauge de robustesse du mot de passe ─────────────────── */
.strength { display: flex; flex-direction: column; gap: 6px; }
.strength__bar { display: grid; grid-template-columns: repeat(5, 1fr); gap: 4px; }
.strength__seg { height: 4px; border-radius: 4px; background: var(--surface-3); transition: background-color var(--dur); }
.strength__label { font-size: var(--fs-xs); font-weight: 600; color: var(--ink-3); min-height: 1.2em; }
.strength[data-level="1"] { --strength: var(--strength-1); }
.strength[data-level="2"] { --strength: var(--strength-2); }
.strength[data-level="3"] { --strength: var(--strength-3); }
.strength[data-level="4"] { --strength: var(--strength-4); }
.strength[data-level="5"] { --strength: var(--strength-5); }
.strength[data-level="1"] .strength__seg:nth-child(-n+1),
.strength[data-level="2"] .strength__seg:nth-child(-n+2),
.strength[data-level="3"] .strength__seg:nth-child(-n+3),
.strength[data-level="4"] .strength__seg:nth-child(-n+4),
.strength[data-level="5"] .strength__seg { background: var(--strength); }
.strength[data-level] .strength__label { color: var(--strength); }

/* ── Grille d'accès aux projets ──────────────────────────── */
.access-list { display: flex; flex-direction: column; border: 1px solid var(--line-2); border-radius: var(--r); overflow: hidden; }
.access-list__row {
  display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap;
  padding: 11px 14px; background: var(--surface);
}
.access-list__row + .access-list__row { border-top: 1px solid var(--line-2); }
.access-list__project { display: flex; align-items: center; gap: 9px; font-size: var(--fs-base); font-weight: 600; }
.access-list__checks { display: flex; gap: 16px; }

/* ── Emplacement anti-robot ──────────────────────────────── */
.captcha-slot {
  width: 300px; max-width: 100%; height: 65px;
  display: grid; place-items: center;
  border: 1px dashed var(--line-strong); border-radius: var(--r-sm);
  font-size: var(--fs-xs); color: var(--ink-3); background: var(--surface-2);
}

/* ── Groupe de choix (fieldset sans habillage) ───────────── */
.fieldset { min-width: 0; margin: 0; padding: 0; border: 0; }
.fieldset__legend { margin-bottom: 10px; padding: 0; }

/* ── feedback.css ── */
/* =========================================================================
   Spyglass · feedback.css
   Petits indicateurs : .badge, .tag, .count, .ticket-id, .dot, .prio,
   .avatar, .pulse, .progress, .spinner, .skeleton, .alert, .empty, .tooltip
   ========================================================================= */

/* ── Badge ───────────────────────────────────────────────────
   Ton générique : .badge-accent | -info | -success | -warning | -danger | -neutral
   Alias métier (générés par PHP à partir des valeurs en base, « _ » → « - ») :
     statut    .badge-status-new | -in-progress | -resolved | -wont-fix
     type      .badge-type-bug | -improvement | -question | -other
     priorité  .badge-prio-low | -medium | -high | -critical
     rôle      .badge-role-super-admin | -admin | -tester | -client | -owner | -member | -guest
   Taille : .badge-sm | .badge-lg      Largeur fixe : .badge-wide
   ─────────────────────────────────────────────────────────── */
.badge {
  --badge-c: var(--neutral-ink); --badge-bg: var(--neutral-soft);
  display: inline-flex; align-items: center; gap: 5px;
  height: 24px; padding: 0 9px;
  border-radius: 8px;
  font-size: var(--fs-xs); font-weight: 600; line-height: 1; white-space: nowrap;
  color: var(--badge-c); background: var(--badge-bg);
}
.badge .icon { width: 13px; height: 13px; }
.badge__dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: 0 0 auto; }
.badge__dot-off { background: transparent; box-shadow: inset 0 0 0 1.5px currentColor; }
.badge-sm { height: 20px; padding: 0 7px; border-radius: 6px; font-size: var(--fs-micro); gap: 4px; }
.badge-sm .icon { width: 11px; height: 11px; }
.badge-lg { height: 30px; padding: 0 12px; border-radius: var(--r-pill); font-size: var(--fs-sm); gap: 6px; }
.badge-wide { min-width: 112px; justify-content: center; }
.badge-outline { box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--badge-c) 30%, transparent); }

.badge-accent  { --badge-c: var(--accent-ink);  --badge-bg: var(--accent-soft); }
.badge-info    { --badge-c: var(--info-ink);    --badge-bg: var(--info-soft); }
.badge-success { --badge-c: var(--success-ink); --badge-bg: var(--success-soft); }
.badge-warning { --badge-c: var(--warning-ink); --badge-bg: var(--warning-soft); }
.badge-danger  { --badge-c: var(--danger-ink);  --badge-bg: var(--danger-soft); }
.badge-neutral { --badge-c: var(--neutral-ink); --badge-bg: var(--neutral-soft); }
.badge-dark    { --badge-c: var(--surface);     --badge-bg: var(--ink); }

.badge-status-new         { --badge-c: var(--info-ink);    --badge-bg: var(--info-soft); }
.badge-status-in-progress { --badge-c: var(--warning-ink); --badge-bg: var(--warning-soft); }
.badge-status-resolved    { --badge-c: var(--success-ink); --badge-bg: var(--success-soft); }
.badge-status-wont-fix    { --badge-c: var(--neutral-ink); --badge-bg: var(--neutral-soft); }
.badge-status-on-hold     { --badge-c: var(--prio-high-ink); --badge-bg: color-mix(in oklab, var(--prio-high) 14%, var(--surface)); } /* attente d'un tiers (prestataire) */
.badge[class*="badge-status-"]::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }

.badge-type-bug         { --badge-c: var(--danger-ink);  --badge-bg: var(--danger-soft); }
.badge-type-improvement { --badge-c: var(--warning-ink); --badge-bg: var(--warning-soft); }
.badge-type-question    { --badge-c: var(--info-ink);    --badge-bg: var(--info-soft); }
.badge-type-other       { --badge-c: var(--neutral-ink); --badge-bg: var(--neutral-soft); }

.badge-prio-low      { --badge-c: var(--success-ink);   --badge-bg: var(--success-soft); }
.badge-prio-medium   { --badge-c: var(--warning-ink);   --badge-bg: color-mix(in oklab, var(--prio-medium) 16%, var(--surface)); }
.badge-prio-high     { --badge-c: var(--prio-high-ink); --badge-bg: color-mix(in oklab, var(--prio-high) 14%, var(--surface)); }
.badge-prio-critical { --badge-c: var(--danger-ink);    --badge-bg: var(--danger-soft); }

.badge-role-super-admin, .badge-role-owner { --badge-c: var(--accent-ink);  --badge-bg: var(--accent-soft); }
.badge-role-admin                          { --badge-c: var(--info-ink);    --badge-bg: var(--info-soft); }
.badge-role-member                         { --badge-c: var(--success-ink); --badge-bg: var(--success-soft); }
.badge-role-client                         { --badge-c: var(--warning-ink); --badge-bg: var(--warning-soft); }
.badge-role-tester, .badge-role-guest      { --badge-c: var(--neutral-ink); --badge-bg: var(--neutral-soft); }

/* Attente (contrôle en cours) : badge + anneau tournant */
.badge-loading { --badge-c: var(--ink-3); --badge-bg: var(--surface-2); }
.badge-loading::before {
  content: ""; width: 10px; height: 10px; border-radius: 50%;
  border: 2px solid var(--accent); border-right-color: transparent; animation: spin .8s linear infinite;
}

/* « Wizard en cours » (liste) */
.badge-busy { --badge-c: var(--accent-ink); --badge-bg: var(--accent-soft); }
.badge-busy::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); animation: blink 1.1s ease-in-out infinite; }

/* ── Étiquette (technologies, mots-clés du Wizard) ───────── */
.tag {
  display: inline-flex; align-items: center; gap: 5px;
  height: 24px; padding: 0 10px; border-radius: var(--r-pill);
  font-size: var(--fs-xs); font-weight: 500; color: var(--ink-2);
  background: var(--surface); box-shadow: inset 0 0 0 1px var(--line);
}
.tag-accent { color: var(--accent-ink); background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent-line); }
.tag-mono { font-family: var(--font-mono); font-size: var(--fs-micro); }
.tag-list { display: flex; flex-wrap: wrap; gap: 6px; }

/* ── Compteur ────────────────────────────────────────────── */
.count {
  display: inline-grid; place-items: center;
  min-width: 22px; height: 20px; padding: 0 7px; border-radius: var(--r-pill);
  font-size: var(--fs-micro); font-weight: 700; font-variant-numeric: tabular-nums;
  color: var(--ink-3); background: var(--surface-2);
}
.count-accent  { color: var(--accent-ink);  background: var(--accent-soft); }
.count-info    { color: var(--info-ink);    background: var(--info-soft); }
.count-success { color: var(--success-ink); background: var(--success-soft); }
.count-warning { color: var(--warning-ink); background: var(--warning-soft); }
.count-danger  { color: #fff; background: var(--danger); }
.count-solid   { color: var(--accent-chip-on); background: var(--accent-chip); }

/* ── Identifiant de ticket ───────────────────────────────── */
.ticket-id {
  font: 700 var(--fs-xs) var(--font-mono); color: var(--accent-ink);
  font-variant-numeric: tabular-nums;
}
.ticket-id-chip { padding: 2px 7px; border-radius: 6px; background: var(--accent-soft); }

/* ── Pastille de couleur (projet, légende) ───────────────── */
.dot {
  --dot: var(--project-default);
  display: inline-block; width: 9px; height: 9px; flex: 0 0 auto;
  border-radius: 50%; background: var(--dot);
}
.dot-xs { width: 6px; height: 6px; }
/* Pastille aux couleurs d'état (suggestions de recherche chargées par un site : tone) */
.dot-success { --dot: var(--success); } .dot-warning { --dot: var(--warning); } .dot-danger { --dot: var(--danger); }
.dot-info { --dot: var(--info); } .dot-neutral { --dot: var(--ink-4); }
.dot-lg { width: 12px; height: 12px; }
.dot-square { border-radius: 3px; }
.dot-all { --dot: var(--project-all); }

/* ── Priorité (pastille à halo) ──────────────────────────── */
.prio { display: inline-flex; align-items: center; gap: 7px; font-size: var(--fs-sm); color: var(--ink-2); }
.prio::before {
  content: ""; width: 9px; height: 9px; flex: 0 0 auto; border-radius: 50%;
  background: var(--prio); box-shadow: 0 0 0 3px color-mix(in oklab, var(--prio) 18%, transparent);
}
.prio-low      { --prio: var(--prio-low); }
.prio-medium   { --prio: var(--prio-medium); }
.prio-high     { --prio: var(--prio-high); }
.prio-critical { --prio: var(--prio-critical); }
.prio-flat::before { box-shadow: none; }

/* ── Avatar ──────────────────────────────────────────────── */
.avatar {
  --size: 32px;
  width: var(--size); height: var(--size); flex: 0 0 auto;
  display: grid; place-items: center; overflow: hidden;
  border-radius: 50%;
  font-size: calc(var(--size) * .36); font-weight: 700; letter-spacing: .02em; color: #fff;
  background: var(--accent-grad);
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.avatar-xs { --size: 22px; }
.avatar-sm { --size: 28px; }
.avatar-md { --size: 32px; }
.avatar-lg { --size: 40px; }
.avatar-xl { --size: 56px; }
.avatar-square { border-radius: calc(var(--size) * .28); }
.avatar-warm { background: linear-gradient(135deg, #f6a04d, #eb6834); }
.avatar-empty { color: var(--ink-3); background: var(--surface-2); font-size: var(--fs-micro); font-weight: 500; }
.avatar-ring { box-shadow: 0 0 0 2px var(--surface); }

/* ── Point vivant ────────────────────────────────────────── */
.pulse { width: 8px; height: 8px; flex: 0 0 auto; border-radius: 50%; color: var(--success); background: currentColor; animation: ping 2.4s var(--ease) infinite; }
.pulse-accent { color: var(--accent); }

/* ── Barre de progression ────────────────────────────────── */
.progress { height: 8px; border-radius: var(--r-pill); background: var(--surface-3); overflow: hidden; }
.progress__fill {
  --value: 0;
  display: block; height: 100%; width: 100%; border-radius: inherit;
  background: var(--progress, var(--accent-grad));
  transform-origin: left; transform: scaleX(0);
  transition: transform 1.1s var(--ease);
}
.is-in-view .progress__fill, .progress__fill.is-static { transform: scaleX(var(--value)); }
.progress-sm { height: 6px; }
.progress-success { --progress: var(--success); }
.progress-warning { --progress: var(--warning); }
.progress-danger  { --progress: var(--danger); }

/* ── Chargement ──────────────────────────────────────────── */
.spinner {
  width: 18px; height: 18px; border-radius: 50%;
  border: 2px solid var(--accent-ring); border-top-color: var(--accent);
  animation: spin .8s linear infinite;
}
.skeleton {
  display: block; border-radius: 8px;
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 50%, var(--surface-2) 75%) 0 0 / 300% 100%;
  animation: shimmer 1.6s linear infinite;
}
.skeleton-line { height: 11px; }
.skeleton-circle { border-radius: 50%; }
.skeleton-avatar { width: 28px; height: 28px; flex: 0 0 auto; border-radius: 50%; }

/* ── Message (ancien .flash) ─────────────────────────────── */
.alert {
  --alert-c: var(--info-ink); --alert-bg: var(--info-soft); --alert-line: var(--info);
  display: flex; align-items: flex-start; gap: 11px;
  padding: 12px 14px;
  border-radius: var(--r); border: 1px solid color-mix(in oklab, var(--alert-line) 30%, transparent);
  font-size: var(--fs-sm); font-weight: 500; line-height: 1.5;
  color: var(--ink); background: var(--alert-bg);
  animation: pop-in var(--dur-slow) var(--ease);
  transition: opacity var(--dur-slow), transform var(--dur-slow) var(--ease);
}
.alert__icon { width: 18px; height: 18px; color: var(--alert-c); margin-top: 1px; }
.alert__text { flex: 1; min-width: 0; }
.alert__title { display: block; font-weight: 700; }
.alert__list { margin: 6px 0 0; padding-left: 18px; color: var(--ink-2); font-weight: 400; }
.alert__close { margin: -4px -6px -4px 0; width: 28px; height: 28px; display: grid; place-items: center; border-radius: 8px; color: var(--ink-3); }
.alert__close:hover { color: var(--ink); background: color-mix(in oklab, var(--alert-line) 12%, transparent); }
.alert-success { --alert-c: var(--success-ink); --alert-bg: var(--success-soft); --alert-line: var(--success); }
.alert-warning { --alert-c: var(--warning-ink); --alert-bg: var(--warning-soft); --alert-line: var(--warning); }
.alert-danger  { --alert-c: var(--danger-ink);  --alert-bg: var(--danger-soft);  --alert-line: var(--danger); }
.alert-info    { --alert-c: var(--info-ink);    --alert-bg: var(--info-soft);    --alert-line: var(--info); }
.alert-inline  { padding: 0; border: 0; background: none; animation: none; color: var(--alert-c); font-size: var(--fs-xs); align-items: center; gap: 6px; }
.alert-inline .alert__icon { width: 13px; height: 13px; margin: 0; }
.alert.is-leaving { opacity: 0; transform: translateY(-6px); }

/* ── État vide ───────────────────────────────────────────── */
.empty {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 44px 20px; text-align: center; color: var(--ink-3);
}
.empty__icon {
  width: 48px; height: 48px; margin-bottom: 8px;
  display: grid; place-items: center; border-radius: 14px;
  color: var(--accent-ink); background: var(--accent-soft);
}
.empty__icon .icon { width: 22px; height: 22px; }
.empty__title { font: 700 var(--fs-lg) var(--font-display); letter-spacing: -.01em; color: var(--ink); }
.empty__text { max-width: 380px; font-size: var(--fs-sm); }
.empty__actions { margin-top: 12px; display: flex; gap: 8px; }
.empty-dashed { border: 1px dashed var(--line-strong); border-radius: var(--r-lg); }
.empty-inline + .empty-inline { border-top: 1px solid var(--line-2); }
.empty-inline { padding: 18px 12px; font-size: var(--fs-sm); text-align: center; color: var(--ink-3); }

/* ── Info-bulle (attribut data-tooltip) ──────────────────── */
[data-tooltip] { position: relative; }
[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute; bottom: calc(100% + 8px); left: 50%; z-index: 60;
  translate: -50% 0; transform: translateY(4px);
  padding: 6px 9px; border-radius: 8px; white-space: nowrap;
  font: 600 var(--fs-xs) var(--font-body); color: var(--surface); background: var(--ink);
  opacity: 0; pointer-events: none;
  transition: opacity var(--dur-fast), transform var(--dur) var(--ease);
}
[data-tooltip]:hover::after, [data-tooltip]:focus-visible::after { opacity: 1; transform: none; }

/* ── data.css ── */
/* =========================================================================
   Spyglass · data.css
   Affichage de données : .card, .stat, .kv, .list, .feed, .rate, .legend,
   .chart, .table, .pagination, .code, .code-block, .note, .identity
   ========================================================================= */

/* ── Carte ───────────────────────────────────────────────── */
.card {
  background: var(--surface);
  border: 1px solid var(--line-2); border-radius: var(--r-lg);
  box-shadow: var(--shadow);
  min-width: 0;
}
.card__header {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 16px 20px 0;
}
.card__header-bordered { padding-bottom: 14px; border-bottom: 1px solid var(--line-2); }
.card__title {
  display: inline-flex; align-items: center; gap: 9px; min-width: 0;
  font: 700 var(--fs-lg)/1.25 var(--font-display); letter-spacing: -.015em; color: var(--ink);
}
.card__title-icon {
  width: 30px; height: 30px; flex: 0 0 auto;
  display: grid; place-items: center; border-radius: 9px;
  color: var(--accent-ink); background: var(--accent-soft);
}
.card__title-icon .icon { width: 15px; height: 15px; }
.card__title-icon-danger  { color: var(--danger-ink);  background: var(--danger-soft); }
.card__title-icon-warning { color: var(--warning-ink); background: var(--warning-soft); }
.card__title-icon-success { color: var(--success-ink); background: var(--success-soft); }
.card__title-count { font: 500 var(--fs-sm) var(--font-body); color: var(--ink-3); }
.card__meta { margin-left: auto; font-size: var(--fs-xs); color: var(--ink-3); }
.card__actions { margin-left: auto; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.card__body { padding: 16px 20px 20px; }
.card__body-flush { padding: 10px 0 6px; }
.card__body-scroll { max-height: 480px; overflow-y: auto; }
.card__section { padding: 16px 20px; border-top: 1px solid var(--line-2); }
.card__footer {
  display: flex; align-items: center; justify-content: flex-end; gap: 8px;
  padding: 14px 20px; border-top: 1px solid var(--line-2);
}
.card-sticky { position: sticky; top: calc(var(--topbar-h) + 16px); }
.card-interactive { transition: border-color var(--dur), box-shadow var(--dur), transform var(--dur) var(--ease); }
.card-interactive:hover { border-color: var(--accent-line); box-shadow: var(--shadow-pop); }
.card-flat { box-shadow: none; }
.card.is-just-done { animation: glow-success 2.6s var(--ease); }

/* Carte repliable (<details class="card card-collapsible">) */
.card-collapsible > summary {
  display: flex; align-items: center; gap: 10px; padding: 16px 20px; cursor: pointer;
  font-size: var(--fs-base); font-weight: 600; color: var(--ink);
}
.card-collapsible > summary > .icon:last-child { margin-left: auto; color: var(--ink-3); transition: transform var(--dur) var(--ease); }
.card-collapsible[open] > summary > .icon:last-child { transform: rotate(180deg); }
.card-collapsible > summary:hover { color: var(--accent-ink); }
.card-collapsible__body { padding: 0 20px 20px; font-size: var(--fs-sm); line-height: 1.65; color: var(--ink-2); }

/* ── Statistique ─────────────────────────────────────────── */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); gap: 14px; }
.stat {
  --stat-c: var(--accent-ink); --stat-bg: var(--accent-soft);
  position: relative; display: flex; flex-direction: column; gap: 4px;
  padding: 16px 18px 16px;
  transition: border-color var(--dur), box-shadow var(--dur);
}
a.stat:hover { border-color: var(--accent-line); box-shadow: var(--shadow-pop); }
.stat__head { display: flex; align-items: center; gap: 10px; font-size: var(--fs-sm); font-weight: 500; color: var(--ink-2); }
.stat__icon {
  width: 30px; height: 30px; flex: 0 0 auto;
  display: grid; place-items: center; border-radius: 9px;
  color: var(--stat-c); background: var(--stat-bg);
}
.stat__icon .icon { width: 15px; height: 15px; }
.stat__go { margin-left: auto; width: 16px; height: 16px; color: var(--ink-4); transition: transform var(--dur) var(--ease), color var(--dur); }
a.stat:hover .stat__go { color: var(--accent); transform: translate(2px, -2px); }
.stat__value {
  margin-top: 10px;
  font: 700 var(--fs-2xl)/1 var(--font-display); letter-spacing: -.035em; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.stat__value-tone { color: var(--stat-c); }
.stat__sub { font-size: var(--fs-xs); color: var(--ink-3); }
/* Évolution par rapport à la période précédente */
.stat__delta { display: inline-flex; align-items: center; gap: 3px; font-size: var(--fs-xs); font-weight: 700; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.stat__delta .icon { width: 12px; height: 12px; }
.stat__delta-up   { color: var(--success-ink); }
.stat__delta-down { color: var(--danger-ink); }
.stat-info    { --stat-c: var(--info-ink);    --stat-bg: var(--info-soft); }
.stat-success { --stat-c: var(--success-ink); --stat-bg: var(--success-soft); }
.stat-warning { --stat-c: var(--warning-ink); --stat-bg: var(--warning-soft); }
.stat-danger  { --stat-c: var(--danger-ink);  --stat-bg: var(--danger-soft); }
.stat-center { align-items: center; text-align: center; padding: 18px 14px; }
.stat-center .stat__value { margin: 0 0 4px; }

/* ── Clé / valeur ────────────────────────────────────────── */
.kv { display: flex; flex-direction: column; margin: 0; }
.kv dd { margin: 0; }
.kv__row { display: flex; justify-content: space-between; align-items: flex-start; gap: 14px; padding: 9px 0; border-bottom: 1px solid var(--line-2); }
.kv__row:first-child { padding-top: 0; }
.kv__row:last-child { border-bottom: 0; padding-bottom: 0; }
.kv__key { font-size: var(--fs-sm); color: var(--ink-3); white-space: nowrap; }
.kv__value { display: inline-flex; align-items: center; gap: 7px; min-width: 0; font-size: var(--fs-sm); font-weight: 500; color: var(--ink); text-align: right; word-break: break-word; }
.kv__value-link { max-width: 180px; color: var(--accent-ink); }
.kv__value-link:hover { text-decoration: underline; }
.kv-compact .kv__row { padding: 6px 0; border: 0; }

/* ── Liste de lignes (organisations, membres, projets, contributeurs) ── */
.list { display: flex; flex-direction: column; }
.list__item {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 20px;
  transition: background-color var(--dur-fast);
}
.list__item + .list__item { border-top: 1px solid var(--line-2); }
a.list__item:hover, .list-hover .list__item:hover { background: var(--surface-2); }
.list__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.list__title { font-size: var(--fs-base); font-weight: 600; color: var(--ink); }
.list__meta { font-size: var(--fs-xs); color: var(--ink-3); }
.list__aside { display: flex; align-items: center; gap: 8px; font-size: var(--fs-xs); color: var(--ink-3); white-space: nowrap; }
.list-compact .list__item { padding: 6px 0; border: 0; gap: 9px; }

/* ── Fil d'activité ──────────────────────────────────────── */
.feed { display: flex; flex-direction: column; }
.feed__item {
  display: flex; gap: 12px; padding: 12px 20px;
  transition: background-color var(--dur-fast);
}
.feed__item + .feed__item { border-top: 1px solid var(--line-2); }
a.feed__item:hover { background: var(--surface-2); }
.feed__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.feed__text { font-size: var(--fs-sm); color: var(--ink-2); }
.feed__text strong { color: var(--ink); font-weight: 600; }
.feed__meta { display: flex; align-items: center; gap: 7px; font-size: var(--fs-xs); color: var(--ink-3); min-width: 0; }
.feed__time { margin-left: auto; white-space: nowrap; }
.feed__quote {
  margin-top: 5px; padding: 8px 12px;
  border-left: 2px solid var(--accent-line); border-radius: 0 8px 8px 0;
  font-size: var(--fs-sm); line-height: 1.5; color: var(--ink-2); background: var(--surface-2);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.feed__arrow { width: 12px; height: 12px; color: var(--ink-4); vertical-align: -1px; }

/* ── Taux de résolution ──────────────────────────────────── */
.rate { display: flex; flex-direction: column; gap: 7px; padding: 4px 0; }
.rate + .rate { margin-top: 14px; }
.rate__head { display: flex; align-items: center; gap: 8px; }
.rate__name { display: flex; align-items: center; gap: 8px; min-width: 0; font-size: var(--fs-sm); font-weight: 600; color: var(--ink); }
.rate__counts { margin-left: auto; display: flex; gap: 4px; }
.rate__value { min-width: 40px; text-align: right; font: 700 var(--fs-sm) var(--font-display); color: var(--rate-c, var(--ink)); }
.rate__caption { font-size: var(--fs-xs); color: var(--ink-3); }
.rate-good { --rate-c: var(--success-ink); --progress: var(--success); }
.rate-mid  { --rate-c: var(--warning-ink); --progress: var(--warning); }
.rate-low  { --rate-c: var(--danger-ink);  --progress: var(--danger); }
a.rate:hover .rate__name { color: var(--accent-ink); }

/* ── Graphique et légende ────────────────────────────────── */
.chart { position: relative; height: 220px; }
.chart__placeholder {
  height: 100%; display: grid; place-items: center; padding: 16px; text-align: center;
  border: 1px dashed var(--line-strong); border-radius: var(--r);
  font-size: var(--fs-xs); color: var(--ink-3);
  background: repeating-linear-gradient(0deg, transparent 0 43px, var(--line-2) 43px 44px);
}
.legend { display: flex; flex-direction: column; gap: 8px; }
.legend__item { display: flex; align-items: center; gap: 9px; font-size: var(--fs-sm); color: var(--ink-2); }
.legend__value { margin-left: auto; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.legend__bar { flex: 0 0 64px; height: 6px; border-radius: 6px; background: var(--surface-3); overflow: hidden; }
.legend__bar > i { display: block; height: 100%; border-radius: inherit; background: var(--dot); transform-origin: left; transform: scaleX(0); transition: transform 1s var(--ease); }
.is-in-view .legend__bar > i { transform: scaleX(var(--value)); }
.legend-inline { flex-direction: row; flex-wrap: wrap; gap: 8px 16px; }

/* ── Tableau (ciblé par classe : plus de règles globales) ── */
.table-wrap { overflow-x: auto; }
.table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.table th {
  padding: 10px 14px; text-align: left; white-space: nowrap;
  font-size: var(--fs-xs); font-weight: 600; color: var(--ink-3);
  border-bottom: 1px solid var(--line-2);
}
.table td { padding: 12px 14px; border-bottom: 1px solid var(--line-2); color: var(--ink-2); vertical-align: middle; white-space: nowrap; }
.table td.table__wrap { white-space: normal; }
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr { transition: background-color var(--dur-fast); }
.table-hover tbody tr:hover, .table__row-link:hover { background: var(--surface-2); }
.table__row-link { cursor: pointer; }
.table tbody tr.is-current { background: var(--accent-soft); }
.table tbody tr.is-current td:first-child { box-shadow: inset 3px 0 0 var(--accent); }
/* th.table__num : l'en-tête suit sa colonne (.table th { text-align: left } l'emportait sur .table__num seul) */
.table__num, .table th.table__num { text-align: right; font-variant-numeric: tabular-nums; }
.table__strong { font-weight: 600; color: var(--ink); }
.table__title { display: block; font-weight: 600; color: var(--ink); }
.table__muted { font-size: var(--fs-xs); color: var(--ink-3); white-space: nowrap; }
.table__truncate { max-width: 300px; }
.table__actions { display: flex; justify-content: flex-end; gap: 6px; }
.table__cell-main { display: flex; align-items: center; gap: 10px; min-width: 0; }
.table__sub { display: block; margin-top: 2px; font-size: var(--fs-xs); color: var(--ink-3); }
.table__sub-mono { font-family: var(--font-mono); font-size: var(--fs-micro); }
.table th[aria-sort] { cursor: pointer; user-select: none; }
.table__sort { width: 13px; height: 13px; margin-left: 4px; opacity: 0; vertical-align: -2px; transition: opacity var(--dur), transform var(--dur) var(--ease); }
.table th:hover .table__sort { opacity: .5; }
.table th[aria-sort="ascending"] .table__sort, .table th[aria-sort="descending"] .table__sort { opacity: 1; }
.table th[aria-sort="ascending"] .table__sort { transform: rotate(180deg); }
.table__ratio strong { color: var(--ink); }
.table__ratio span { color: var(--ink-3); font-size: var(--fs-xs); }
.table__empty-dash { color: var(--ink-4); }

/* ── Tableau en cartes sur mobile (.lst-table) ──────────────
   Sous 820 px, chaque ligne devient une carte : libellé (data-label de la cellule)
   à gauche, valeur à droite. Plusieurs éléments dans une cellule (nom puis e-mail,
   badge puis détail…) s'empilent l'un sous l'autre. data-label="" : cellule
   d'actions, boutons alignés à droite sans libellé. */
@media (max-width: 820px) {
  .lst-table thead { display: none; }
  .lst-table, .lst-table tbody, .lst-table tr, .lst-table td { display: block; width: 100%; }
  .lst-table tr { padding: 10px 14px; border-bottom: 1px solid var(--line-2); }
  .lst-table tbody tr:last-child { border-bottom: 0; }
  .lst-table td {
    display: grid; grid-template-columns: max-content minmax(0, 1fr); column-gap: 12px; row-gap: 2px;
    align-items: center; justify-items: end;
    padding: 5px 0 !important; border: 0 !important; text-align: right; white-space: normal;
  }
  .lst-table td::before {
    content: attr(data-label); grid-column: 1; grid-row: 1 / span 6; align-self: start; justify-self: start;
    font-size: var(--fs-xs); font-weight: 600; color: var(--ink-3); text-align: left; white-space: nowrap;
  }
  .lst-table td > * { grid-column: 2; max-width: 100%; }
  .lst-table td > .table__sub { margin-top: 0; }
  .lst-table td[data-label=""] { display: flex; justify-content: flex-end; padding-top: 10px !important; }
  .lst-table td[data-label=""]::before { content: none; }
  /* data-label="#" : le numéro (#123) se suffit, pas de libellé « # » devant ; il reste à droite comme les
     autres valeurs (demande de Loïc, 03/11) */
  .lst-table td[data-label="#"] { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; justify-content: flex-end; text-align: right; }
  .lst-table td[data-label="#"]::before { content: none; }
  .lst-table .table__truncate { max-width: none; }
}

/* Tableau compact (derniers envois d'un webhook) */
.table-compact { font-size: var(--fs-xs); }
.table-compact th, .table-compact td { padding: 6px 8px; }
.table-compact th:first-child, .table-compact td:first-child { padding-left: 0; }
.table-compact th:last-child, .table-compact td:last-child { padding-right: 0; }
.table-compact td { border-bottom-color: var(--line-2); }
.table__error td { padding-top: 0; color: var(--danger-ink); font-size: var(--fs-micro); }

/* ── Pagination ──────────────────────────────────────────── */
.pagination { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; padding: 12px 20px; border-top: 1px solid var(--line-2); }
.pagination__info { font-size: var(--fs-xs); color: var(--ink-3); }
.pagination__list { display: flex; align-items: center; gap: 4px; }
.pagination__item {
  min-width: 32px; height: 32px; padding: 0 8px;
  display: grid; place-items: center; border-radius: 9px;
  font-size: var(--fs-sm); font-weight: 600; color: var(--ink-2);
  transition: background-color var(--dur), color var(--dur);
}
.pagination__item:hover { background: var(--surface-2); color: var(--ink); }
.pagination__item.is-active { color: var(--accent-chip-on); background: var(--accent-chip); }
.pagination__item:disabled { opacity: .35; pointer-events: none; }
.pagination__gap { color: var(--ink-4); padding: 0 4px; }

/* ── Code ────────────────────────────────────────────────── */
.code {
  padding: 2px 6px; border-radius: 6px;
  font: 500 var(--fs-xs) var(--font-mono); color: var(--ink-2);
  background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--line-2);
  word-break: break-all;
}
.code-plain { padding: 0; background: none; box-shadow: none; color: var(--ink-3); }
.code-selector {
  display: block; padding: 10px 12px; border-radius: var(--r-sm);
  font: 500 var(--fs-xs)/1.55 var(--font-mono); word-break: break-all;
  color: var(--accent-ink); background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent-line);
}
.code-block {
  padding: 12px 14px; border-radius: var(--r-sm); overflow-x: auto;
  font: 400 var(--fs-xs)/1.6 var(--font-mono); color: var(--ink-2);
  background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--line-2);
  white-space: pre;
}
.code-block-wrap { white-space: pre-wrap; word-break: break-all; }
.code-block-dark { color: #d6dbf0; background: #0d1124; box-shadow: none; }

/* ── Note (encadré) ──────────────────────────────────────── */
.note {
  padding: 11px 14px; border-radius: var(--r-sm);
  font-size: var(--fs-xs); line-height: 1.6; color: var(--ink-2); background: var(--surface-2);
}
.note strong { color: var(--ink); }
.note-warning { color: var(--ink); background: var(--warning-soft); box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--warning) 35%, transparent); font-size: var(--fs-sm); }
.note__title { display: block; margin-bottom: 4px; font-weight: 700; color: var(--ink); }
.note-accent { color: var(--ink); background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent-line); font-size: var(--fs-sm); }

/* ── Identité (profil) ───────────────────────────────────── */
.identity { display: flex; align-items: center; gap: 16px; }
.identity__name { font: 700 var(--fs-xl)/1.2 var(--font-display); letter-spacing: -.02em; color: var(--ink); }
.identity__meta { margin-top: 2px; font-size: var(--fs-sm); color: var(--ink-3); }

/* ── overlays.css ── */
/* =========================================================================
   Spyglass · overlays.css
   Éléments flottants : .modal, .dropdown, .suggest (résultats de recherche),
   .bell (centre de notifications), .toast
   Ouverture : classe .is-open (posée par spyglass.js).
   ========================================================================= */

/* ── Modale ──────────────────────────────────────────────── */
.modal {
  position: fixed; inset: 0; z-index: 100;
  display: grid; place-items: center; padding: 16px;
  background: #0b102266; backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
  opacity: 0; visibility: hidden;
  transition: opacity var(--dur), visibility 0s linear var(--dur);
}
.modal.is-open { opacity: 1; visibility: visible; transition: opacity var(--dur); }
.modal__dialog {
  width: 100%; max-width: 520px; max-height: calc(100vh - 32px); overflow-y: auto;
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--r-xl);
  box-shadow: var(--shadow-pop);
  transform: translateY(14px) scale(.97);
  transition: transform var(--dur-slow) var(--ease);
}
.modal.is-open .modal__dialog { transform: none; }
.modal__dialog-sm { max-width: 420px; }
.modal__header { display: flex; align-items: center; gap: 12px; padding: 20px 22px 4px; }
.modal__title { font: 700 var(--fs-xl)/1.2 var(--font-display); letter-spacing: -.02em; color: var(--ink); }
.modal__close { margin-left: auto; }
.modal__body { padding: 16px 22px 20px; }
.modal__section { padding: 16px 22px; border-top: 1px solid var(--line-2); background: var(--surface-2); }

/* ── Visionneuse de photos (a[data-lightbox], spyglass.js) ─ */
.lightbox {
  position: fixed; inset: 0; z-index: 110;
  display: grid; place-items: center; padding: 56px 16px;
  background: #050608e6; backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  opacity: 0; visibility: hidden;
  transition: opacity var(--dur), visibility 0s linear var(--dur);
}
.lightbox.is-open { opacity: 1; visibility: visible; transition: opacity var(--dur); }
.lightbox__figure { display: flex; flex-direction: column; align-items: center; gap: 10px; margin: 0; max-width: 100%; }
.lightbox__img {
  display: block; max-width: min(100%, 1200px); max-height: calc(100vh - 140px); width: auto; height: auto;
  object-fit: contain; border-radius: var(--r-lg); box-shadow: 0 30px 80px -20px #000000cc;
  transform: scale(.97); transition: transform var(--dur-slow) var(--ease);
}
.lightbox.is-open .lightbox__img { transform: none; }
.lightbox__count { font-size: var(--fs-sm); font-weight: 600; color: #ffffffb3; font-variant-numeric: tabular-nums; }
.lightbox__btn {
  position: absolute; display: grid; place-items: center; width: 44px; height: 44px; border-radius: 50%;
  color: #fff; background: #ffffff1f; border: 1px solid #ffffff2e; transition: background-color var(--dur);
}
.lightbox__btn:hover { background: #ffffff33; }
.lightbox__btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.lightbox__btn .icon { width: 20px; height: 20px; }
.lightbox__close { top: 12px; right: 12px; }
.lightbox__prev { left: 12px; top: 50%; transform: translateY(-50%); }
.lightbox__next { right: 12px; top: 50%; transform: translateY(-50%); }
@media (prefers-reduced-motion: reduce) { .lightbox, .lightbox__img { transition: none; } }
.modal__footer {
  display: flex; justify-content: flex-end; gap: 8px;
  padding: 14px 22px; border-top: 1px solid var(--line-2);
}
/* Modale rendue dans un cadre (styleguide) */
.modal-inline { position: absolute; }

/* ── Menu déroulant ──────────────────────────────────────── */
.dropdown { position: relative; display: inline-block; }
.dropdown-block { display: block; }
.dropdown__trigger {
  display: flex; align-items: center; gap: 9px;
  width: 100%; min-width: 220px; height: 42px; padding: 0 12px;
  border: 1px solid var(--line); border-radius: 12px;
  font-size: var(--fs-sm); font-weight: 500; color: var(--ink); background: var(--surface);
  box-shadow: var(--shadow-sm);
  transition: border-color var(--dur), box-shadow var(--dur);
}
.dropdown__trigger:hover { border-color: var(--line-strong); }
.dropdown.is-open .dropdown__trigger { border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-ring); }
.dropdown__label { flex: 1; min-width: 0; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dropdown__chevron { width: 15px; height: 15px; color: var(--ink-3); transition: transform var(--dur) var(--ease); }
.dropdown.is-open .dropdown__chevron { transform: rotate(180deg); }
.dropdown__menu {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 50;
  min-width: 100%; max-height: 320px; overflow-y: auto; padding: 6px;
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--r);
  box-shadow: var(--shadow-pop);
  opacity: 0; transform: translateY(-6px) scale(.98); transform-origin: top left; pointer-events: none;
  transition: opacity var(--dur-fast), transform var(--dur) var(--ease);
}
.dropdown__menu-end { left: auto; right: 0; transform-origin: top right; }
.dropdown.is-open .dropdown__menu { opacity: 1; transform: none; pointer-events: auto; }
.dropdown__group { padding: 8px 10px 4px; font-size: var(--fs-micro); font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3); }
.dropdown__item {
  display: flex; align-items: center; gap: 9px;
  width: 100%; height: 38px; padding: 0 10px; border-radius: 9px;
  font-size: var(--fs-sm); color: var(--ink-2); text-align: left;
  transition: background-color var(--dur-fast), color var(--dur-fast);
}
.dropdown__item:hover { color: var(--ink); background: var(--surface-2); }
.dropdown__item.is-active { color: var(--accent-ink); background: var(--accent-soft); font-weight: 600; }
.dropdown__item.is-active .count { color: var(--accent-ink); background: color-mix(in oklab, var(--accent) 16%, var(--surface)); }
.dropdown__item .count { margin-left: auto; }
.dropdown__item-danger { color: var(--danger-ink); }
.dropdown__check { margin-left: auto; width: 15px; height: 15px; color: var(--accent); }

/* ── Suggestions de recherche ────────────────────────────── */
.suggest { position: relative; }
.suggest__panel {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 50;
  padding: 6px; max-height: 340px; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--r);
  box-shadow: var(--shadow-pop);
  opacity: 0; transform: translateY(-6px); pointer-events: none;
  transition: opacity var(--dur-fast), transform var(--dur) var(--ease);
}
.suggest.is-open .suggest__panel { opacity: 1; transform: none; pointer-events: auto; }
.suggest__item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px; border-radius: 9px;
  font-size: var(--fs-sm); color: var(--ink-2);
}
.suggest__item:hover, .suggest__item.is-highlighted { color: var(--ink); background: var(--accent-soft); }
.suggest__item .ticket-id { min-width: 38px; }
.suggest__text { flex: 1; min-width: 0; display: flex; align-items: center; gap: 7px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.suggest__text .icon { width: 13px; height: 13px; }
.suggest__meta { display: flex; align-items: center; gap: 6px; font-size: var(--fs-xs); color: var(--ink-3); white-space: nowrap; }
.suggest__empty { padding: 18px 12px; text-align: center; font-size: var(--fs-sm); color: var(--ink-3); }
.suggest__empty strong { color: var(--ink); }
.suggest__footer { display: flex; gap: 12px; padding: 8px 10px 4px; margin-top: 4px; border-top: 1px solid var(--line-2); font-size: var(--fs-micro); color: var(--ink-3); }
.suggest__all .suggest__text { color: var(--accent-ink); font-weight: 600; }
/* Suggestions chargées par un site : un champ étroit (barre de filtres) ne doit pas réduire le panneau ;
   largeur minimale, bornée par l'écran. Les raccourcis du pied restent sur une ligne chacun. */
@media (min-width: 821px) { .suggest[data-suggest] .suggest__panel { min-width: min(480px, calc(100vw - 32px)); } }   /* en dessous, le champ a toute la largeur */
.suggest__footer > span { white-space: nowrap; }

/* ── Centre de notifications (cloche) ────────────────────── */
.bell { position: relative; display: inline-flex; }
.bell__btn { position: relative; }
.bell__btn[aria-expanded="true"] { color: var(--accent-ink); background: var(--accent-soft); }
.bell__count {
  position: absolute; top: -4px; right: -4px;
  min-width: 18px; height: 18px; padding: 0 5px;
  display: grid; place-items: center; border-radius: var(--r-pill);
  font-size: 10px; font-weight: 700; color: #fff; background: var(--danger);
  box-shadow: 0 0 0 2px var(--bg);
  animation: pop-in var(--dur-slow) var(--ease);
}
.bell__panel {
  position: absolute; top: calc(100% + 10px); right: 0; z-index: 60;
  width: 380px; max-width: calc(100vw - 24px); overflow: hidden;
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--r-lg);
  box-shadow: var(--shadow-pop);
  opacity: 0; transform: translateY(-6px) scale(.98); transform-origin: top right; pointer-events: none;
  transition: opacity var(--dur-fast), transform var(--dur) var(--ease);
}
.bell.is-open .bell__panel, .bell__panel.is-static { opacity: 1; transform: none; pointer-events: auto; }
.bell__panel.is-static { position: relative; top: auto; right: auto; }
.bell__head { display: flex; align-items: center; gap: 10px; padding: 14px 16px; border-bottom: 1px solid var(--line-2); }
.bell__title { font: 700 var(--fs-md) var(--font-display); color: var(--ink); }
.bell__read-all { margin-left: auto; font-size: var(--fs-xs); font-weight: 600; color: var(--accent-ink); }
.bell__read-all:hover { text-decoration: underline; }
.bell__list { max-height: 380px; overflow-y: auto; }
.bell__item { display: flex; gap: 11px; padding: 12px 16px; transition: background-color var(--dur-fast); }
.bell__item + .bell__item { border-top: 1px solid var(--line-2); }
.bell__item:hover { background: var(--surface-2); }
.bell__dot { width: 8px; height: 8px; margin-top: 6px; flex: 0 0 auto; border-radius: 50%; background: transparent; }
.bell__item.is-unread .bell__dot { background: var(--accent); box-shadow: 0 0 0 3px var(--accent-ring); }
.bell__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.bell__item-title { font-size: var(--fs-sm); font-weight: 500; color: var(--ink-2); }
.bell__item.is-unread .bell__item-title { font-weight: 700; color: var(--ink); }
.bell__item-desc { font-size: var(--fs-sm); color: var(--ink-2); line-height: 1.4; }
.bell__time { font-size: var(--fs-xs); color: var(--ink-3); }
.bell__empty { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 28px 16px; font-size: var(--fs-sm); color: var(--ink-3); text-align: center; }
.bell__empty .icon { width: 22px; height: 22px; color: var(--ink-4); }
.bell__loading { display: flex; flex-direction: column; gap: 14px; padding: 16px; }
.bell__loading-row { display: flex; gap: 11px; align-items: flex-start; }
.bell__device {
  display: flex; align-items: center; gap: 8px;
  padding: 11px 16px; border-top: 1px solid var(--line-2);
  font-size: var(--fs-xs); line-height: 1.5; color: var(--ink-3); background: var(--surface-2);
}
.bell__device .icon { width: 14px; height: 14px; flex: 0 0 auto; }
.bell__device .pulse { width: 7px; height: 7px; }

/* ── Toast ───────────────────────────────────────────────── */
.toast-region {
  position: fixed; z-index: 120; right: 22px; bottom: 22px;
  display: flex; flex-direction: column; align-items: flex-end; gap: 10px;
  pointer-events: none;
}
.toast-region-center { right: 50%; transform: translateX(50%); align-items: center; }
.toast {
  display: flex; align-items: flex-start; gap: 12px;
  max-width: 380px; padding: 12px 12px 12px 14px;
  border-radius: var(--r);
  font-size: var(--fs-sm); line-height: 1.45; color: var(--surface); background: var(--ink);
  box-shadow: var(--shadow-pop);
  pointer-events: auto;
  animation: toast-in var(--dur-slow) var(--ease);
  transition: opacity var(--dur), transform var(--dur) var(--ease);
}
.toast.is-leaving { opacity: 0; transform: translateY(10px); }
.toast__icon { width: 20px; height: 20px; flex: 0 0 auto; margin-top: 1px; color: var(--success); }
.toast__text { flex: 1; min-width: 0; color: color-mix(in oklab, var(--surface) 78%, transparent); }
.toast__title { display: block; font-weight: 700; color: var(--surface); }
.toast__action {
  flex: 0 0 auto; height: 30px; padding: 0 11px; border-radius: 9px;
  font-size: var(--fs-xs); font-weight: 700; color: var(--accent-light); background: #ffffff14;
}
.toast__close {
  flex: 0 0 auto; width: 28px; height: 28px; display: grid; place-items: center; border-radius: 8px;
  color: color-mix(in oklab, var(--surface) 60%, transparent);
}
.toast__close:hover { color: var(--surface); background: #ffffff14; }
.toast-success { box-shadow: var(--shadow-pop), inset 3px 0 0 var(--success); }
.toast-danger .toast__icon { color: var(--danger); }
.toast-compact { align-items: center; padding: 9px 16px; border-radius: var(--r-pill); }
:root[data-theme="dark"] .toast__action { color: var(--accent-ink); background: #00000014; }
:root[data-theme="dark"] .toast__close:hover { background: #00000014; }
@keyframes toast-in { from { opacity: 0; transform: translateY(14px) scale(.98); } to { opacity: 1; transform: none; } }

/* ── tickets.css ── */
/* =========================================================================
   Spyglass · tickets.css
   Composants métier des tickets : .kanban, .ticket-card, .report (page
   détail), .media, .timeline, .console, .comment, .wizard
   ========================================================================= */

/* ── Kanban ──────────────────────────────────────────────── */
.kanban {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(270px, 1fr);
  gap: 14px; align-items: start;
  overflow-x: auto; padding-bottom: 8px; scroll-snap-type: x proximity;
}
.kanban__col {
  --col: var(--status-new);
  display: flex; flex-direction: column; gap: 10px;
  min-height: 320px; padding: 12px;
  border-radius: var(--r-lg); border: 1px dashed transparent;
  background: color-mix(in oklab, var(--surface-2) 70%, var(--bg));
  scroll-snap-align: start;
  transition: border-color var(--dur), background-color var(--dur);
}
.kanban__col-new         { --col: var(--status-new); }
.kanban__col-in-progress { --col: var(--status-in-progress); }
.kanban__col-resolved    { --col: var(--status-resolved); }
.kanban__col-wont-fix    { --col: var(--status-wontfix); }
.kanban__col.is-over { border-color: var(--accent); background: var(--accent-soft); }
.kanban__head { display: flex; align-items: center; gap: 8px; padding: 2px 4px; }
.kanban__title { display: flex; align-items: center; gap: 8px; font-size: var(--fs-base); font-weight: 700; color: var(--ink); }
.kanban__title::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--col); box-shadow: 0 0 0 3px color-mix(in oklab, var(--col) 20%, transparent); }
.kanban__count { margin-left: auto; }
.kanban__body { display: flex; flex-direction: column; gap: 10px; flex: 1; }
.kanban__empty {
  flex: 1; display: grid; place-items: center; min-height: 120px;
  border: 1px dashed var(--line); border-radius: var(--r);
  font-size: var(--fs-xs); color: var(--ink-3);
}
.kanban__col.is-over .kanban__empty { display: none; }
.kanban__placeholder {
  height: 72px; border-radius: var(--r);
  border: 2px dashed var(--accent); background: color-mix(in oklab, var(--accent) 6%, transparent);
  animation: fade-in var(--dur) var(--ease);
}

/* ── Carte de ticket ─────────────────────────────────────── */
.ticket-card {
  position: relative; display: flex; flex-direction: column; gap: 8px;
  padding: 12px 12px 12px;
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--r);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transition: border-color var(--dur), box-shadow var(--dur), transform var(--dur) var(--ease), opacity var(--dur);
}
.ticket-card:hover { border-color: var(--line); box-shadow: var(--shadow); transform: translateY(-1px); }
.ticket-card[draggable="true"] { cursor: grab; }
.ticket-card[draggable="true"]:active { cursor: grabbing; }
.ticket-card.is-dragging { opacity: .45; transform: scale(.97) rotate(-1deg); box-shadow: none; }
.ticket-card__top { display: flex; align-items: center; gap: 8px; }
.ticket-card__top .prio { margin-left: auto; }
.ticket-card__desc {
  font-size: var(--fs-sm); line-height: 1.5; color: var(--ink);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.ticket-card__desc-empty { color: var(--ink-3); font-style: italic; }
.ticket-card__footer { display: flex; align-items: center; gap: 7px; font-size: var(--fs-xs); color: var(--ink-3); }
.ticket-card__url { min-width: 0; font-family: var(--font-mono); font-size: var(--fs-micro); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ticket-card__date { margin-left: auto; white-space: nowrap; }
/* Bandeau « Wizard en cours » */
.ticket-card.is-analyzing { border-color: var(--accent-line); box-shadow: 0 0 0 1px var(--accent-line), 0 6px 18px -10px var(--accent); }
.ticket-card__wizard {
  position: relative; overflow: hidden;
  display: flex; align-items: center; gap: 7px;
  margin: 2px -12px -12px; padding: 7px 12px;
  border-top: 1px solid var(--accent-line); border-radius: 0 0 var(--r) var(--r);
  font-size: var(--fs-xs); font-weight: 600; color: var(--accent-ink);
  background: linear-gradient(90deg, var(--accent-soft), transparent 85%);
}
.ticket-card__wizard .icon { width: 13px; height: 13px; }
.ticket-card__wizard::after {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 40%;
  background: linear-gradient(90deg, transparent, color-mix(in oklab, var(--accent) 22%, transparent), transparent);
  animation: sweep 1.6s ease-in-out infinite;
}

/* ── Page rapport ────────────────────────────────────────── */
.report__nav { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 18px; }
.report__nav-group { display: flex; align-items: center; gap: 10px; }
.report__position { font-size: var(--fs-sm); font-weight: 500; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.report__position strong { color: var(--ink); }
.report__grid { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 18px; align-items: start; }
.report__main { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.report__description { font-size: var(--fs-md); line-height: 1.7; color: var(--ink-2); }
.report__status-form { display: flex; align-items: center; gap: 8px; }
.report__aside-section { padding-top: 16px; margin-top: 16px; border-top: 1px solid var(--line-2); }
.report__aside-title { display: flex; align-items: center; gap: 6px; margin-bottom: 10px; font-size: var(--fs-xs); font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-3); }
.report__aside-title-danger { color: var(--danger-ink); }
.report__aside-actions { display: flex; gap: 8px; }
.report__aside-actions .btn:first-child { flex: 1; }
/* Mobile : « Retour » et « Supprimer » l'un sous l'autre, en pleine largeur (le bouton Supprimer est dans un formulaire) */
@media (max-width: 560px) {
  .report__aside-actions { flex-direction: column; align-items: stretch; }
  .report__aside-actions > form { display: flex; }
  .report__aside-actions .btn, .report__aside-actions .btn:first-child { flex: none; width: 100%; justify-content: center; }   /* flex: 1 (bureau) écrasait la hauteur en colonne */
}
@media (max-width: 1080px) { .report__grid { grid-template-columns: minmax(0, 1fr); } .report__grid .card-sticky { position: static; } }

/* ── Médias (capture, vidéo) ─────────────────────────────── */
.media { padding: 12px; }
.media__frame { position: relative; display: block; overflow: hidden; border-radius: var(--r-sm); border: 1px solid var(--line-2); background: var(--surface-2); }
.media__img { width: 100%; transition: transform .6s var(--ease); }
a.media__frame:hover .media__img { transform: scale(1.015); }
.media__zoom {
  position: absolute; right: 10px; bottom: 10px;
  display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px; border-radius: var(--r-pill);
  font-size: var(--fs-xs); font-weight: 600; color: #fff; background: #0b1022b3; backdrop-filter: blur(6px);
  opacity: 0; transform: translateY(4px); transition: opacity var(--dur), transform var(--dur) var(--ease);
}
a.media__frame:hover .media__zoom { opacity: 1; transform: none; }
.media__video { width: 100%; max-height: 420px; border-radius: var(--r-sm); background: var(--media-bg); aspect-ratio: 16 / 9; }

/* ── Historique ──────────────────────────────────────────── */
/* ol.timeline : même poids que la remise à zéro ol[class] de base.css, qui annulait le retrait et décalait les puces */
.timeline, ol.timeline { position: relative; display: flex; flex-direction: column; gap: 14px; padding-left: 18px; }
.timeline::before { content: ""; position: absolute; left: 4px; top: 6px; bottom: 6px; width: 1px; background: var(--line); }
.timeline__item { position: relative; display: flex; flex-direction: column; gap: 2px; font-size: var(--fs-sm); color: var(--ink-2); }
.timeline__item::before {
  content: ""; position: absolute; left: -18px; top: 5px; width: 9px; height: 9px; border-radius: 50%;
  background: var(--surface); box-shadow: inset 0 0 0 2px var(--timeline-c, var(--line-strong));
}
.timeline__item-accent  { --timeline-c: var(--accent); }
.timeline__item-success { --timeline-c: var(--success); }
.timeline__item-warning { --timeline-c: var(--warning); }
.timeline__time { font-size: var(--fs-xs); color: var(--ink-3); font-variant-numeric: tabular-nums; }
.timeline__text strong { color: var(--ink); font-weight: 600; }
.timeline__change { display: inline-flex; align-items: center; gap: 6px; vertical-align: middle; }
.timeline__change .icon { width: 12px; height: 12px; color: var(--ink-4); }

/* ── Erreurs console ─────────────────────────────────────── */
.console { display: flex; flex-direction: column; gap: 6px; max-height: 220px; overflow-y: auto; }
.console__item {
  padding: 8px 10px; border-radius: var(--r-sm);
  font: 400 var(--fs-micro)/1.55 var(--font-mono); word-break: break-all;
  background: var(--danger-soft); box-shadow: inset 2px 0 0 var(--danger);
}
.console__type { font-weight: 700; color: var(--danger-ink); }
.console__msg { color: var(--ink); }
.console__src { margin-top: 2px; color: var(--ink-3); }

/* ── Commentaires ────────────────────────────────────────── */
.comments { display: flex; flex-direction: column; gap: 14px; }
.comment { display: flex; gap: 11px; align-items: flex-start; }
.comment__main { flex: 1; min-width: 0; }
.comment__head { display: flex; align-items: center; gap: 8px; margin-bottom: 5px; }
.comment__author { font-size: var(--fs-sm); font-weight: 600; color: var(--ink); }
.comment__date { font-size: var(--fs-xs); color: var(--ink-3); }
.comment__delete { margin-left: auto; opacity: 0; transition: opacity var(--dur); }
.comment:hover .comment__delete, .comment__delete:focus-visible { opacity: 1; }
.comment__bubble {
  padding: 10px 13px; border-radius: 4px var(--r) var(--r) var(--r);
  font-size: var(--fs-sm); line-height: 1.6; color: var(--ink-2);
  background: var(--surface-2); border: 1px solid var(--line-2);
}
.comment-form { display: flex; gap: 11px; align-items: flex-start; padding-top: 16px; margin-top: 16px; border-top: 1px solid var(--line-2); }
.comment-form__main { flex: 1; display: flex; flex-direction: column; gap: 8px; align-items: flex-end; }
.comment-form .textarea { min-height: 72px; }
/* Mobile : « Envoyer » en pleine largeur, avec au-dessus le même espace qu'en dessous (marge basse de la carte, 20 px) */
@media (max-width: 560px) {
  .comment-form__main { align-items: stretch; gap: 20px; }
  .comment-form__main .btn { width: 100%; justify-content: center; }
}

/* ── Spyglass Wizard ─────────────────────────────────────── */
.wizard__title-icon { color: #fff; background: var(--accent-grad); box-shadow: var(--shadow-accent); }
.wizard__intro { display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 18px 0 6px; text-align: center; }
.wizard__intro-icon {
  width: 56px; height: 56px; display: grid; place-items: center; border-radius: 16px;
  color: var(--accent-ink); background: var(--accent-soft);
  box-shadow: 0 0 0 8px color-mix(in oklab, var(--accent) 5%, transparent);
}
.wizard__intro-icon .icon { width: 26px; height: 26px; }
.wizard__intro-text { max-width: 440px; font-size: var(--fs-sm); line-height: 1.6; color: var(--ink-2); }
.wizard__meta { margin-left: auto; font-size: var(--fs-xs); color: var(--ink-3); }
.wizard__estimate { display: flex; align-items: center; gap: 10px; margin-bottom: 18px; font-size: var(--fs-sm); color: var(--ink-3); }
.wizard__section + .wizard__section { margin-top: 16px; }
.wizard__label {
  display: flex; align-items: center; gap: 7px; margin-bottom: 8px;
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-3);
}
.wizard__label .icon { width: 13px; height: 13px; color: var(--accent); }
.wizard__diagnosis {
  padding: 13px 15px; border-radius: var(--r);
  font-size: var(--fs-base); line-height: 1.6; color: var(--ink);
  background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent-line);
}
.wizard__clues, .wizard__questions { display: flex; flex-direction: column; gap: 6px; }
.wizard__clue, .wizard__question { display: flex; gap: 9px; align-items: flex-start; font-size: var(--fs-sm); line-height: 1.5; color: var(--ink-2); }
.wizard__clue::before { content: ""; width: 6px; height: 6px; margin-top: 7px; flex: 0 0 auto; border-radius: 50%; background: var(--accent); }
.wizard__question .icon { width: 14px; height: 14px; margin-top: 3px; color: var(--warning); }
.wizard__fixes { display: flex; flex-direction: column; gap: 6px; counter-reset: fix; }
.wizard__fix {
  display: flex; gap: 11px; align-items: flex-start;
  padding: 10px 12px; border-radius: var(--r-sm);
  font-size: var(--fs-sm); line-height: 1.5; color: var(--ink-2); background: var(--surface-2);
  counter-increment: fix;
}
.wizard__fix::before {
  content: counter(fix);
  width: 20px; height: 20px; flex: 0 0 auto; margin-top: 1px;
  display: grid; place-items: center; border-radius: 50%;
  font-size: var(--fs-micro); font-weight: 700; color: var(--accent-chip-on); background: var(--accent-chip);
}
.wizard__footer { display: flex; align-items: center; gap: 10px; margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line-2); }
/* Mobile : « Relancer le Wizard » et « Copier le diagnostic » l'un sous l'autre, en pleine largeur */
@media (max-width: 560px) {
  .wizard__footer { flex-direction: column; align-items: stretch; }
  .wizard__footer .btn { width: 100%; justify-content: center; }
}

/* Progression */
.wizard__progress-head { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.wizard__progress-label { font-size: var(--fs-base); font-weight: 600; color: var(--ink); }
.wizard__elapsed { margin-left: auto; font-size: var(--fs-xs); color: var(--ink-3); font-variant-numeric: tabular-nums; }
.wizard__steps { display: flex; flex-direction: column; gap: 2px; }
.wizard__step {
  display: flex; align-items: center; gap: 11px;
  padding: 9px 11px; border-radius: var(--r-sm);
  font-size: var(--fs-sm); color: var(--ink-3);
  transition: background-color var(--dur), color var(--dur);
}
.wizard__step-dot {
  position: relative; width: 18px; height: 18px; flex: 0 0 auto; border-radius: 50%;
  border: 2px solid var(--line-strong); transition: all var(--dur);
}
.wizard__step.is-active { color: var(--ink); font-weight: 600; background: var(--accent-soft); }
.wizard__step.is-active .wizard__step-dot { border-color: var(--accent); border-top-color: transparent; animation: spin .8s linear infinite; }
.wizard__step.is-done { color: var(--ink-2); }
.wizard__step.is-done .wizard__step-dot { border-color: var(--success); background: var(--success); }
.wizard__step.is-done .wizard__step-dot::after {
  content: ""; position: absolute; left: 4.5px; top: 1.5px; width: 4px; height: 8px;
  border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg);
}
.wizard__step-note { margin-left: auto; font-size: var(--fs-xs); font-weight: 400; color: var(--ink-3); }
.wizard__hint { margin-top: 12px; font-size: var(--fs-xs); line-height: 1.5; color: var(--ink-3); }

/* ── pages.css ── */
/* =========================================================================
   Spyglass · pages.css
   Mises en page propres à une page, préfixées par le nom de la page :
   .home__* · .reports__* · .health__* · .settings__* / .webhook__* ·
   .auth__* (connexion, inscription, vérification) · .portal__* ·
   .mail-preview__*
   Remplace les blocs <style> de reports.php, report.php, health.php,
   login.php et la feuille propre de portal.php.
   ========================================================================= */

/* ── Accueil ─────────────────────────────────────────────── */
.home__stats { margin-bottom: 18px; }
/* Deux cartes d'une même rangée prennent la même hauteur (demande de Loïc, 30/10, comme le tableau de bord de Lighthouse) */
.home__row { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: 16px; margin-bottom: 16px; align-items: stretch; }
.home__row-even { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.home__donut { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: 20px; align-items: center; }
.home__donut-chart { position: relative; width: 150px; height: 150px; }
.home__donut-chart svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.home__donut-track { fill: none; stroke: var(--surface-3); stroke-width: 16; }
.home__donut-seg { fill: none; stroke-width: 16; stroke-dasharray: 0 999; transition: stroke-dasharray 1.2s var(--ease); }
.home__donut-total { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; }
.home__donut-total strong { font: 700 var(--fs-2xl)/1 var(--font-display); letter-spacing: -.03em; color: var(--ink); }
.home__donut-total span { font-size: var(--fs-xs); color: var(--ink-3); }
@media (max-width: 1080px) { .home__row, .home__row-even { grid-template-columns: minmax(0, 1fr); } }

/* ── Rapports : barre de filtres ─────────────────────────── */
.reports__filters { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 18px; }
.reports__search { flex: 1 1 260px; max-width: 360px; }
.reports__count { margin-left: auto; font-size: var(--fs-sm); color: var(--ink-3); white-space: nowrap; }
.reports__count strong { color: var(--ink); }
/* Le choix du projet (« Tous les projets ») est toujours juste à gauche de la recherche : les pastilles de type
   passent devant, sans toucher au HTML (demande de Loïc, 03/11) */
.reports__filters > .pills { order: 1; }
.reports__filters > .dropdown { order: 2; }
.reports__filters > .reports__search { order: 3; }
.reports__filters > .reports__count { order: 4; }
/* Téléphone : pastilles, puis le projet, puis la recherche, chacun sur sa ligne en pleine largeur (Loïc, 03/11) */
@media (max-width: 560px) {
  .reports__filters > .pills { flex-basis: 100%; }
  .reports__filters > .dropdown { flex: 1 1 100%; min-width: 0; }
  .reports__filters > .dropdown .dropdown__trigger { min-width: 0; }
  .reports__filters > .reports__search { flex: 1 1 100%; min-width: 0; max-width: none; }
  .reports__filters > .reports__count { flex-basis: 100%; text-align: right; }
}

/* ── Santé du système ────────────────────────────────────── */
.health__summary {
  --summary-c: var(--success-ink); --summary-bg: var(--success-soft); --summary-line: var(--success);
  display: flex; align-items: flex-start; gap: 14px;
  padding: 16px 18px; margin-bottom: 18px;
  border-radius: var(--r-lg); border: 1px solid color-mix(in oklab, var(--summary-line) 35%, transparent);
  background: var(--summary-bg);
}
.health__summary-danger  { --summary-c: var(--danger-ink);  --summary-bg: var(--danger-soft);  --summary-line: var(--danger); }
.health__summary-warning { --summary-c: var(--warning-ink); --summary-bg: var(--warning-soft); --summary-line: var(--warning); }
.health__summary-icon {
  width: 38px; height: 38px; flex: 0 0 auto; display: grid; place-items: center; border-radius: 11px;
  color: var(--summary-c); background: var(--surface); box-shadow: var(--shadow-sm);
}
.health__summary-title { font: 700 var(--fs-lg) var(--font-display); letter-spacing: -.01em; color: var(--ink); }
.health__summary-text { margin-top: 2px; font-size: var(--fs-sm); color: var(--ink-2); }
/* ul.health__summary-list : même poids que la remise à zéro ul[class] de base.css, qui annulait le retrait et les puces */
.health__summary-list, ul.health__summary-list { margin: 8px 0 0; padding-left: 18px; list-style: disc; font-size: var(--fs-sm); color: var(--ink-2); }
.health__summary-list li + li { margin-top: 3px; }
.health__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 440px), 1fr)); gap: 16px; align-items: start; }
.health__checks { padding: 8px 0 6px; }
.health__check { display: flex; align-items: flex-start; gap: 14px; padding: 11px 20px; }
.health__check + .health__check { border-top: 1px solid var(--line-2); }
.health__check-text { min-width: 0; flex: 1; }
.health__check-label { font-size: var(--fs-sm); font-weight: 600; color: var(--ink); }
.health__check-detail { margin-top: 2px; font-size: var(--fs-xs); color: var(--ink-2); word-break: break-word; }
.health__check-hint {
  margin-top: 7px; padding: 7px 10px; border-radius: 8px;
  font-size: var(--fs-xs); color: var(--ink-2); background: var(--surface-2);
}
.health__check-hint strong { color: var(--ink); }
@media (max-width: 640px) { .health__check { flex-direction: column; gap: 6px; } }

/* ── Réglages : webhooks sortants ────────────────────────── */
.webhook__head { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 12px; padding: 16px 20px; }
.webhook__info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.webhook__name { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font: 700 var(--fs-md) var(--font-display); color: var(--ink); }
.webhook__url { font: 500 var(--fs-xs) var(--font-mono); color: var(--ink-3); word-break: break-all; }
.webhook__format { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: var(--fs-xs); color: var(--ink-3); }
.webhook__actions { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.webhook__body { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); gap: 20px; padding: 16px 20px 18px; border-top: 1px solid var(--line-2); }
.webhook__label { margin-bottom: 8px; font-size: var(--fs-xs); font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-3); }
.webhook__secret { display: flex; align-items: center; gap: 6px; }
.webhook__secret-value {
  flex: 1; min-width: 0; height: 32px; padding: 0 10px; display: flex; align-items: center;
  border-radius: 9px; font: 500 var(--fs-xs) var(--font-mono); color: var(--ink-2); background: var(--surface-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.webhook__secret-actions { margin-top: 8px; }
@media (max-width: 720px) { .webhook__body { grid-template-columns: minmax(0, 1fr); } }

/* ── Pages publiques : connexion, inscription, vérification ─ */
.auth {
  position: relative; overflow: hidden;
  min-height: 100vh; display: grid; place-items: center; padding: 32px 16px;
  background:
    radial-gradient(600px 420px at 85% -10%, color-mix(in oklab, var(--accent) 16%, transparent), transparent 70%),
    radial-gradient(480px 380px at -5% 105%, color-mix(in oklab, var(--info) 12%, transparent), transparent 70%),
    var(--bg);
}
.auth__card {
  position: relative; width: 100%; max-width: 440px; padding: 36px;
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--r-xl);
  box-shadow: var(--shadow-pop);
  animation: pop-in .5s var(--ease);
}
.auth__card-center { text-align: center; }
.auth__card-center .brand { justify-content: center; }
.auth__split {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  width: 100%; max-width: 920px; overflow: hidden;
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--r-xl);
  box-shadow: var(--shadow-pop); animation: pop-in .5s var(--ease);
}
.auth__form { padding: 40px 36px; }
.auth__media {
  position: relative; min-height: 420px; display: grid; place-items: center; padding: 24px;
  color: #c9cdf5; text-align: center; font-size: var(--fs-sm);
  background:
    radial-gradient(80% 60% at 70% 20%, var(--media-tint), transparent 70%),
    radial-gradient(60% 50% at 20% 90%, var(--media-tint-2), transparent 70%),
    var(--media-bg);
}
.auth__media iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.auth__play {
  width: 64px; height: 64px; margin: 0 auto 14px; display: grid; place-items: center; border-radius: 50%;
  color: #fff; background: #ffffff1f; box-shadow: 0 0 0 10px #ffffff0d; backdrop-filter: blur(6px);
}
.auth .brand { margin-bottom: 28px; }
.auth__title { font: 700 var(--fs-2xl)/1.15 var(--font-display); letter-spacing: -.03em; color: var(--ink); }
.auth__subtitle { margin-top: 6px; margin-bottom: 24px; font-size: var(--fs-md); color: var(--ink-3); }
.auth__text { margin-top: 10px; font-size: var(--fs-md); line-height: 1.6; color: var(--ink-2); }
.auth__status-icon {
  width: 72px; height: 72px; margin: 4px auto 18px; display: grid; place-items: center; border-radius: 22px;
  color: var(--accent-ink); background: var(--accent-soft);
  animation: pop-in .6s var(--ease) .1s both;
}
.auth__status-icon .icon { width: 34px; height: 34px; stroke-width: 1.6; }
.auth__status-icon-success { color: var(--success-ink); background: var(--success-soft); }
.auth__status-icon-warning { color: var(--warning-ink); background: var(--warning-soft); }
.auth__status-icon-danger  { color: var(--danger-ink);  background: var(--danger-soft); }
.auth__actions { margin-top: 22px; display: flex; justify-content: center; }
.auth__switch { margin-top: 16px; text-align: center; font-size: var(--fs-sm); color: var(--ink-3); }
.auth__switch a { font-weight: 600; color: var(--accent-ink); }
.auth__switch a:hover { text-decoration: underline; }
.auth__extension {
  display: flex; align-items: center; gap: 12px; margin-top: 18px; padding: 12px 14px;
  border-radius: var(--r); border: 1px solid var(--accent-line); background: var(--accent-soft);
  transition: border-color var(--dur), transform var(--dur) var(--ease);
}
.auth__extension:hover { border-color: var(--accent); transform: translateY(-1px); }
.auth__extension img { width: 30px; height: 30px; border-radius: 8px; }
.auth__extension-title { display: block; font-size: var(--fs-sm); font-weight: 700; color: var(--accent-ink); }
.auth__extension-sub { font-size: var(--fs-xs); color: var(--ink-3); }
.auth__extension .icon { margin-left: auto; color: var(--accent-ink); }
.auth__footer { margin-top: 24px; text-align: center; font-size: var(--fs-xs); color: var(--ink-3); }
.auth__footer a { font-weight: 700; color: var(--ink-2); }
.auth .form { gap: 14px; }
@media (max-width: 760px) {
  .auth__split { grid-template-columns: minmax(0, 1fr); max-width: 440px; }
  .auth__media { min-height: 220px; }
  .auth__form, .auth__card { padding: 28px 22px; }
}

/* ── Portail client public ───────────────────────────────── */
.portal { background: var(--bg); color: var(--ink); }
.portal__header { background: var(--surface); border-bottom: 1px solid var(--line-2); }
.portal__header-inner { max-width: 980px; margin: 0 auto; padding: 18px 24px; display: flex; align-items: center; gap: 14px; }
.portal__logo { --size: 42px; }
.portal__title { font: 700 var(--fs-xl)/1.2 var(--font-display); letter-spacing: -.02em; }
.portal__org { font-size: var(--fs-sm); color: var(--ink-3); }
.portal__header .badge { margin-left: auto; }
.portal__content { max-width: 980px; margin: 0 auto; padding: 24px; display: flex; flex-direction: column; gap: 16px; }
.portal__stats { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.portal__progress-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 12px; }
.portal__progress-value { white-space: nowrap; font: 700 var(--fs-2xl)/1 var(--font-display); letter-spacing: -.03em; color: var(--accent-ink); }
.portal__ticket { display: grid; grid-template-columns: 44px 18px minmax(0, 1fr) auto auto auto; align-items: center; gap: 12px; padding: 12px 20px; font-size: var(--fs-sm); }
.portal__ticket + .portal__ticket { border-top: 1px solid var(--line-2); }
.portal__ticket:hover { background: var(--surface-2); }
.portal__ticket-desc { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); }
.portal__ticket-date { font-size: var(--fs-xs); color: var(--ink-3); white-space: nowrap; }
.portal__footer { padding: 28px 24px 36px; text-align: center; font-size: var(--fs-xs); color: var(--ink-3); }
.portal__footer a { font-weight: 700; color: var(--accent-ink); }
@media (max-width: 640px) {
  .portal__stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .portal__ticket { grid-template-columns: 44px 18px minmax(0, 1fr) auto; }
  .portal__ticket .prio, .portal__ticket-date { display: none; }
}

/* ── Aperçu des e-mails ──────────────────────────────────── */
.mail-preview__bar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 16px; }
.mail-preview__frame { display: block; width: 100%; border: 0; background: var(--bg); border-radius: 0 0 var(--r-lg) var(--r-lg); }
.mail-preview__note { margin-top: 12px; font-size: var(--fs-xs); color: var(--ink-3); }

/* ── booking.css ── */
/* =========================================================================
   Spyglass · booking.css
   Composants génériques ajoutés pour les applications de réservation et de
   vie de résidence (Lighthouse d'abord, réutilisables partout) :
     réservation : .space-card, .period-nav, .daypicker, .slots / .slot,
                   .dayline, .month-cal, .recap
     accès       : .access-pass, .lock-control
     suivi       : .steps
     contenu     : .post-card, .prose, .editor, .photo-drop, .option-grid
     données     : .heatmap, .sparkline
   Comme partout : uniquement des jetons dérivés (--accent-*, sémantique),
   aucune couleur de marque en dur. Les seules variables posées en ligne sont
   des données : --start / --end (frise du jour), --value (carte de chaleur).
   ========================================================================= */

/* ── Carte d'espace réservable (photo, prix, infos) ───────── */
.space-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); gap: 16px; }
.space-card { display: flex; flex-direction: column; overflow: hidden; }
a.space-card, .space-card-interactive { transition: border-color var(--dur), box-shadow var(--dur), transform var(--dur) var(--ease); }
a.space-card:hover, .space-card-interactive:hover { border-color: var(--accent-line); box-shadow: var(--shadow-pop); }
.space-card__media { position: relative; aspect-ratio: 16 / 9; overflow: hidden; background: var(--surface-2); }
.space-card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--dur-slow) var(--ease); }
a.space-card:hover .space-card__media img, .space-card-interactive:hover .space-card__media img { transform: scale(1.03); }
.space-card__price {
  position: absolute; top: 12px; right: 12px;
  display: inline-block; white-space: nowrap;
  height: 28px; padding: 0 11px; border-radius: var(--r-pill);
  font: 700 var(--fs-sm)/28px var(--font-display); color: var(--ink);   /* hauteur de ligne = hauteur : texte centré, prix et unité sur la même ligne de base */
  background: var(--surface); box-shadow: var(--shadow-sm);
  font-variant-numeric: tabular-nums;
}
.space-card__price small { margin-left: 3px; font: 500 var(--fs-xs) var(--font-body); color: var(--ink-3); }
.space-card__price-free { color: var(--success-ink); background: var(--success-soft); }
.space-card__flag { position: absolute; top: 12px; left: 12px; }
.space-card__body { flex: 1; display: flex; flex-direction: column; gap: 6px; padding: 16px 18px 18px; }
.space-card__place { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-xs); font-weight: 600; color: var(--accent-ink); }
.space-card__title { font: 700 var(--fs-lg)/1.25 var(--font-display); letter-spacing: -.015em; color: var(--ink); }
.space-card__desc {
  font-size: var(--fs-sm); line-height: 1.55; color: var(--ink-2);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.space-card__meta { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-top: 4px; font-size: var(--fs-xs); color: var(--ink-3); }
.space-card__meta-item { display: inline-flex; align-items: center; gap: 5px; }
.space-card__meta-item .icon { width: 13px; height: 13px; }
.space-card__actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: auto; padding-top: 12px; }
.space-card__actions .btn-primary { flex: 1; }
.space-card.is-inactive .space-card__media img { filter: grayscale(1); opacity: .6; }

/* ── Navigation de période (semaine, mois) ───────────────── */
.period-nav { display: flex; align-items: center; justify-content: center; gap: 8px; }
.period-nav__label {
  min-width: 170px; text-align: center;
  font: 700 var(--fs-md) var(--font-display); letter-spacing: -.01em; color: var(--ink);
}
.period-nav__label::first-letter { text-transform: uppercase; }
.period-nav-start { justify-content: flex-start; }

/* ── Sélecteur de jour (bande de la semaine) ─────────────── */
.daypicker {
  display: flex; gap: 8px; overflow-x: auto; padding: 2px 2px 6px;
  scroll-snap-type: x proximity; scrollbar-width: thin;
}
.daypicker__day {
  position: relative; flex: 1 0 64px; scroll-snap-align: start;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  min-height: 70px; padding: 8px 6px;
  border: 1px solid var(--line); border-radius: var(--r);
  color: var(--ink); background: var(--surface);
  transition: border-color var(--dur), background-color var(--dur), color var(--dur), transform var(--dur) var(--ease);
}
.daypicker__dow { font-size: var(--fs-micro); font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-3); }
.daypicker__num { font: 700 var(--fs-xl)/1 var(--font-display); font-variant-numeric: tabular-nums; }
.daypicker__day:hover { border-color: var(--accent); }
.daypicker__day:active { transform: scale(.97); }
.daypicker__day.is-today .daypicker__num { color: var(--accent-ink); }
.daypicker__day.is-today::after {
  content: ""; position: absolute; bottom: 7px; width: 4px; height: 4px; border-radius: 50%; background: var(--accent);
}
.daypicker__day.is-selected, .daypicker__day[aria-pressed="true"] {
  color: var(--accent-on); background: var(--accent-fill); border-color: var(--accent-fill); box-shadow: var(--shadow-accent);
}
.daypicker__day.is-selected .daypicker__dow, .daypicker__day[aria-pressed="true"] .daypicker__dow,
.daypicker__day.is-selected .daypicker__num, .daypicker__day[aria-pressed="true"] .daypicker__num { color: inherit; }
.daypicker__day.is-selected::after, .daypicker__day[aria-pressed="true"]::after { background: currentColor; }
.daypicker__day:disabled, .daypicker__day.is-closed {
  color: var(--ink-4); background: var(--surface-2); border-color: transparent; cursor: not-allowed; transform: none;
}
.daypicker__day:disabled .daypicker__dow, .daypicker__day.is-closed .daypicker__dow { color: var(--ink-4); }

/* ── Créneaux horaires ───────────────────────────────────────
   États : libre (défaut) | .is-selected / [aria-pressed=true] | .is-mine
           | .is-booked | .is-unavailable | :disabled
   ─────────────────────────────────────────────────────────── */
.slots { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 8px; }
.slot {
  position: relative; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: 42px; padding: 0 10px;
  border: 1px solid var(--line); border-radius: 11px;
  font-size: var(--fs-sm); font-weight: 600; font-variant-numeric: tabular-nums;
  color: var(--ink); background: var(--surface);
  transition: border-color var(--dur), background-color var(--dur), color var(--dur), box-shadow var(--dur);
}
.slot .icon { width: 13px; height: 13px; }
.slot:hover { border-color: var(--accent); }
.slot.is-selected, .slot[aria-pressed="true"] {
  color: var(--accent-on); background: var(--accent-fill); border-color: var(--accent-fill); box-shadow: var(--shadow-accent);
}
.slot.is-mine { color: var(--accent-ink); background: var(--accent-soft); border-color: var(--accent-line); }
.slot.is-booked, .slot:disabled {
  color: var(--ink-4); background: var(--surface-2); border-color: transparent;
  text-decoration: line-through; cursor: not-allowed;
}
.slot.is-unavailable {
  color: var(--warning-ink); border-color: transparent; cursor: not-allowed;
  background: repeating-linear-gradient(-45deg, var(--warning-soft) 0 6px, var(--surface-2) 6px 12px);
}
.slot.is-booked:hover, .slot:disabled:hover, .slot.is-unavailable:hover, .slot.is-mine:hover { border-color: transparent; }
.slot.is-mine:hover { border-color: var(--accent-line); }

/* Légende commune aux créneaux, à la frise et au calendrier */
.slot-legend { display: flex; flex-wrap: wrap; gap: 8px 16px; font-size: var(--fs-xs); color: var(--ink-3); }
.slot-legend__item { display: inline-flex; align-items: center; gap: 7px; }
.slot-key { width: 14px; height: 14px; flex: 0 0 auto; border-radius: 4px; border: 1px solid var(--line); background: var(--surface); }
.slot-key.is-selected { background: var(--accent-fill); border-color: var(--accent-fill); }
.slot-key.is-mine { background: var(--accent-soft); border-color: var(--accent-line); }
.slot-key.is-booked { background: var(--surface-3); border-color: transparent; }
.slot-key.is-unavailable { border-color: transparent; background: repeating-linear-gradient(-45deg, var(--warning) 0 2px, var(--warning-soft) 2px 5px); }
.slot-key.is-today { background: transparent; border: 2px solid var(--accent); }

/* ── Frise d'occupation d'une journée ────────────────────────
   Chaque segment reçoit --start et --end entre 0 et 1 (fraction de la
   plage d'ouverture), calculés par le serveur.
   ─────────────────────────────────────────────────────────── */
.dayline { display: flex; flex-direction: column; gap: 6px; }
.dayline__track {
  position: relative; height: 38px; overflow: hidden;
  border-radius: 11px; background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--line-2);
}
.dayline__seg {
  --start: 0; --end: 0;
  position: absolute; top: 4px; bottom: 4px;
  left: calc(var(--start) * 100%); width: calc((var(--end) - var(--start)) * 100%);
  display: flex; align-items: center; justify-content: center; overflow: hidden;
  border-radius: 8px; font-size: var(--fs-micro); font-weight: 700; white-space: nowrap;
  color: var(--ink-3); background: var(--surface-3);
}
.dayline__seg.is-mine { color: var(--accent-ink); background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent-line); }
.dayline__seg.is-selected { color: var(--accent-on); background: var(--accent-fill); box-shadow: var(--shadow-accent); }
.dayline__seg.is-unavailable { color: var(--warning-ink); background: repeating-linear-gradient(-45deg, var(--warning-soft) 0 6px, transparent 6px 12px); }
.dayline__hours { display: flex; justify-content: space-between; font-size: var(--fs-micro); color: var(--ink-3); font-variant-numeric: tabular-nums; }

/* ── Calendrier mensuel ──────────────────────────────────────
   Vue planning (événements dans les cases) ou .month-cal-compact (choix
   d'une date). États d'une case : .is-today | .is-selected | .is-past |
   .is-closed | .is-unavailable | .is-outside (autre mois) | .has-events
   ─────────────────────────────────────────────────────────── */
.month-cal { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; }
.month-cal__dow {
  padding: 6px 0; text-align: center;
  font-size: var(--fs-micro); font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-3);
}
.month-cal__day {
  position: relative; min-width: 0; min-height: 88px;
  display: flex; flex-direction: column; gap: 3px; padding: 6px 7px;
  border: 1px solid var(--line-2); border-radius: 10px;
  text-align: left; color: var(--ink); background: var(--surface);
  transition: border-color var(--dur), background-color var(--dur);
}
.month-cal__num { font-size: var(--fs-sm); font-weight: 600; font-variant-numeric: tabular-nums; }
.month-cal__note { font-size: var(--fs-micro); font-weight: 600; color: var(--ink-3); }
.month-cal__event {
  display: block; padding: 2px 6px; border-radius: 5px;
  font-size: var(--fs-micro); font-weight: 600; line-height: 1.45;
  color: var(--accent-ink); background: var(--accent-soft);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.month-cal__event.is-mine { color: var(--accent-chip-on); background: var(--accent-chip); }
.month-cal__more { font-size: var(--fs-micro); color: var(--ink-3); }
.month-cal__day.is-today { border: 2px solid var(--accent); padding: 5px 6px; }
.month-cal__day.is-today .month-cal__num { color: var(--accent-ink); font-weight: 800; }
.month-cal__day.is-past { opacity: .5; }
.month-cal__day.is-closed { background: var(--surface-2); border-color: transparent; }
.month-cal__day.is-unavailable { background: var(--warning-soft); border-color: transparent; }
.month-cal__day.is-unavailable .month-cal__note { color: var(--warning-ink); }
.month-cal__day.is-outside { visibility: hidden; }
button.month-cal__day:not(:disabled):hover { border-color: var(--accent); }
button.month-cal__day:disabled { cursor: not-allowed; }

.month-cal-compact .month-cal__day { min-height: 0; aspect-ratio: 1; align-items: center; justify-content: center; padding: 0; }
.month-cal-compact .month-cal__day.is-today { padding: 0; }
.month-cal-compact .month-cal__day.has-events::after {
  content: ""; position: absolute; bottom: 6px; left: 50%; width: 4px; height: 4px; margin-left: -2px;
  border-radius: 50%; background: var(--accent);
}
.month-cal__day.is-selected, .month-cal__day[aria-pressed="true"] { color: var(--accent-on); background: var(--accent-fill); border-color: var(--accent-fill); }
.month-cal__day.is-selected .month-cal__num, .month-cal__day[aria-pressed="true"] .month-cal__num { color: inherit; }
.month-cal__day.is-selected::after { background: currentColor; }
@media (max-width: 640px) {
  .month-cal__day { min-height: 56px; padding: 4px; }
  .month-cal__event { width: 7px; height: 7px; padding: 0; border-radius: 50%; font-size: 0; }
  .month-cal__note, .month-cal__more { display: none; }
}

/* ── Récapitulatif de réservation / paiement ─────────────── */
.recap { overflow: hidden; }
.recap__head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 18px 20px; border-bottom: 1px solid var(--line-2);
  background: linear-gradient(135deg, var(--accent-soft), var(--surface) 70%);
}
.recap__price { font: 700 var(--fs-2xl)/1 var(--font-display); letter-spacing: -.03em; color: var(--ink); font-variant-numeric: tabular-nums; }
.recap__unit { margin-left: 4px; font: 500 var(--fs-sm) var(--font-body); letter-spacing: 0; color: var(--ink-3); }
.recap__lines { margin: 0; padding: 14px 20px 4px; display: flex; flex-direction: column; }
.recap__line { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; padding: 6px 0; font-size: var(--fs-sm); }
.recap__line dt { color: var(--ink-3); }
.recap__line dd { margin: 0; text-align: right; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.recap__line-detail { font-size: var(--fs-xs); }
.recap__line-detail dd { font-weight: 500; color: var(--ink-2); }
.recap__line-discount dd { color: var(--success-ink); }
.recap__total { margin-top: 6px; padding-top: 12px; border-top: 1px solid var(--line); }
.recap__total dt { font-weight: 700; color: var(--ink); }
.recap__total dd { font: 700 var(--fs-xl)/1 var(--font-display); letter-spacing: -.02em; }
.recap__empty { padding: 22px 20px 8px; text-align: center; font-size: var(--fs-sm); color: var(--ink-3); }
.recap__actions { padding: 14px 20px 18px; display: flex; flex-direction: column; gap: 8px; }
/* ul.recap__notes : même poids que la remise à zéro ul[class] de base.css, qui annulait le padding */
.recap__notes, ul.recap__notes { margin: 0; padding: 12px 20px 16px; display: flex; flex-direction: column; gap: 6px; border-top: 1px solid var(--line-2); background: var(--surface-2); }
.recap__note { display: flex; align-items: center; gap: 8px; font-size: var(--fs-xs); color: var(--ink-3); }
.recap__note .icon { width: 13px; height: 13px; flex: 0 0 auto; }

/* ── Laissez-passer : code d'accès et créneau de validité ────
   Variantes : .access-pass-active | -upcoming | -expired
   ─────────────────────────────────────────────────────────── */
.access-pass {
  --pass-c: var(--info-ink); --pass-bg: var(--info-soft); --pass-dot: var(--info);
  overflow: hidden; text-align: center;
}
.access-pass-active   { --pass-c: var(--success-ink); --pass-bg: var(--success-soft); --pass-dot: var(--success); }
.access-pass-upcoming { --pass-c: var(--info-ink);    --pass-bg: var(--info-soft);    --pass-dot: var(--info); }
.access-pass-expired  { --pass-c: var(--neutral-ink); --pass-bg: var(--neutral-soft); --pass-dot: var(--neutral); }
.access-pass__status {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 10px 16px; font-size: var(--fs-sm); font-weight: 700;
  color: var(--pass-c); background: var(--pass-bg);
}
.access-pass__status .pulse { color: var(--pass-dot); }
.access-pass__body { padding: 20px 20px 18px; display: flex; flex-direction: column; align-items: center; gap: 10px; }
.access-pass__label { font-size: var(--fs-xs); font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3); }
.access-pass__code { display: flex; align-items: center; justify-content: center; gap: 10px; flex-wrap: wrap; }
.access-pass__digits {
  padding: 12px 10px 12px 22px; border-radius: var(--r);
  font: 700 clamp(30px, 7vw, 42px)/1 var(--font-mono); letter-spacing: .3em; font-variant-numeric: tabular-nums;
  color: var(--accent-ink); background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent-line);
}
.access-pass-expired .access-pass__digits { color: var(--ink-4); background: var(--surface-2); box-shadow: none; text-decoration: line-through; text-decoration-thickness: 2px; }
.access-pass__window { display: flex; align-items: center; justify-content: center; gap: 7px; flex-wrap: wrap; font-size: var(--fs-sm); color: var(--ink-2); }
.access-pass__window .icon { color: var(--ink-3); }
.access-pass__window strong { color: var(--ink); }
.access-pass__hint { max-width: 360px; font-size: var(--fs-xs); color: var(--ink-3); }
.access-pass__footer { padding: 14px 20px 18px; border-top: 1px solid var(--line-2); display: flex; flex-direction: column; gap: 10px; }

/* ── Commande de serrure connectée ───────────────────────── */
.lock-control { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.lock-control__buttons { display: flex; justify-content: center; gap: 18px; flex-wrap: wrap; }
.lock-control__btn {
  --lock-c: var(--success-ink); --lock-bg: var(--success-soft); --lock-line: var(--success);
  position: relative; width: 112px; height: 112px; border-radius: 50%;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
  font-size: var(--fs-sm); font-weight: 700; color: var(--lock-c); background: var(--lock-bg);
  box-shadow: inset 0 0 0 2px color-mix(in oklab, var(--lock-line) 55%, transparent);
  transition: box-shadow var(--dur), transform var(--dur) var(--ease), background-color var(--dur);
}
.lock-control__btn .icon { width: 28px; height: 28px; stroke-width: 1.7; }
.lock-control__btn:hover { box-shadow: inset 0 0 0 2px var(--lock-line), 0 0 0 6px color-mix(in oklab, var(--lock-line) 16%, transparent); }
.lock-control__btn:active { transform: scale(.96); }
.lock-control__btn-close { --lock-c: var(--neutral-ink); --lock-bg: var(--surface-2); --lock-line: var(--neutral); }
.lock-control__btn.is-loading { pointer-events: none; }
.lock-control__btn.is-loading::after {
  content: ""; position: absolute; inset: -4px; border-radius: 50%;
  border: 2px solid transparent; border-top-color: var(--lock-line); animation: spin .9s linear infinite;
}
.lock-control__btn:disabled { opacity: .45; cursor: not-allowed; box-shadow: none; }
.lock-control__meta { font-size: var(--fs-xs); color: var(--ink-3); }

/* ── Étapes de suivi (ticket, réservation) ───────────────── */
.steps { display: grid; grid-auto-columns: minmax(0, 1fr); grid-auto-flow: column; gap: 6px; margin: 0; padding: 0; list-style: none; }
.steps__item { display: flex; flex-direction: column; gap: 7px; min-width: 0; font-size: var(--fs-xs); font-weight: 600; color: var(--ink-3); }
.steps__item::before { content: ""; height: 6px; border-radius: var(--r-pill); background: var(--surface-3); transition: background-color var(--dur-slow) var(--ease); }
.steps__item.is-done::before { background: var(--accent); }
.steps__item.is-current { color: var(--ink); font-weight: 700; }
.steps__item.is-current::before { background: var(--accent); box-shadow: 0 0 0 3px var(--accent-ring); }
.steps__item.is-stopped { color: var(--danger-ink); }
.steps__item.is-stopped::before { background: var(--danger); }
.steps__date { font-weight: 500; color: var(--ink-3); }
@media (max-width: 480px) { .steps__date { display: none; } }

/* ── Carte d'annonce (actualité de la résidence) ─────────── */
.post-card { display: flex; flex-direction: column; overflow: hidden; }
.post-card__media { aspect-ratio: 2 / 1; overflow: hidden; background: var(--surface-2); }
.post-card__media img { width: 100%; height: 100%; object-fit: cover; }
.post-card__body { display: flex; flex-direction: column; gap: 8px; padding: 16px 18px 18px; }
.post-card__kicker { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: var(--fs-xs); color: var(--ink-3); }
.post-card__title { font: 700 var(--fs-lg)/1.3 var(--font-display); letter-spacing: -.015em; color: var(--ink); }
a.post-card:hover .post-card__title { color: var(--accent-ink); }
.post-card__excerpt { font-size: var(--fs-sm); line-height: 1.6; color: var(--ink-2); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.post-card__footer { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 12px 18px; border-top: 1px solid var(--line-2); }
.post-card-row { flex-direction: row; }
.post-card-row .post-card__media { flex: 0 0 34%; aspect-ratio: auto; }
@media (max-width: 560px) { .post-card-row { flex-direction: column; } .post-card-row .post-card__media { aspect-ratio: 2 / 1; } }

/* ── Texte riche (annonce, règles d'usage, pages légales) ── */
.prose { max-width: 70ch; font-size: var(--fs-md); line-height: 1.7; color: var(--ink-2); }
.prose > * + * { margin-top: 14px; }
.prose h2, .prose h3 { font-family: var(--font-display); font-weight: 700; color: var(--ink); letter-spacing: -.015em; }
.prose h2 { margin-top: 28px; font-size: var(--fs-xl); line-height: 1.25; }
.prose h3 { margin-top: 22px; font-size: var(--fs-lg); }
.prose ul, .prose ol { padding-left: 22px; }
.prose li + li { margin-top: 6px; }
.prose strong { font-weight: 600; color: var(--ink); }
.prose a { font-weight: 600; color: var(--accent-ink); text-decoration: underline; text-underline-offset: 2px; }
.prose blockquote { margin-left: 0; padding: 4px 0 4px 16px; border-left: 3px solid var(--accent-line); color: var(--ink-2); }
.prose hr { border: 0; border-top: 1px solid var(--line-2); }
.prose-sm { font-size: var(--fs-sm); line-height: 1.65; }
.prose-sm > * + * { margin-top: 10px; }

/* ── Éditeur de texte riche (barre + zone contenteditable) ── */
.editor { border: 1px solid var(--line); border-radius: 12px; background: var(--surface); overflow: hidden; transition: border-color var(--dur), box-shadow var(--dur); }
.editor:focus-within { border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-ring); }
.editor__bar { display: flex; flex-wrap: wrap; align-items: center; gap: 2px; padding: 6px; border-bottom: 1px solid var(--line-2); background: var(--surface-2); }
.editor__bar .btn[aria-pressed="true"] { color: var(--accent-ink); background: var(--accent-soft); }
.editor__sep { width: 1px; height: 18px; margin: 0 4px; background: var(--line); }
.editor__area { min-height: 180px; max-height: 420px; overflow-y: auto; padding: 14px 16px; outline: 0; }
.editor__area:empty::before { content: attr(data-placeholder); color: var(--ink-4); }
/* Étiquettes de variables insérables : <button class="tag tag-mono"> */
button.tag { cursor: pointer; transition: box-shadow var(--dur), color var(--dur); }
button.tag:hover { color: var(--accent-ink); box-shadow: inset 0 0 0 1px var(--accent-line); }

/* ── Photos jointes (signalement, annonce) ───────────────────
   <div class="photo-drop" data-photo-drop data-max="3"> : les aperçus
   sont ajoutés par spyglass.js, le serveur reçoit le champ fichier.
   ─────────────────────────────────────────────────────────── */
.photo-drop { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
@media (min-width: 560px) { .photo-drop { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.photo-drop__item { position: relative; aspect-ratio: 1; overflow: hidden; border-radius: 12px; background: var(--surface-2); animation: pop-in var(--dur-slow) var(--ease); }
.photo-drop__item img { width: 100%; height: 100%; object-fit: cover; }
.photo-drop__remove {
  position: absolute; top: 6px; right: 6px; width: 28px; height: 28px;
  display: grid; place-items: center; border-radius: 50%;
  color: #fff; background: color-mix(in srgb, var(--media-bg) 72%, transparent); backdrop-filter: blur(6px);
}
.photo-drop__remove:hover { background: var(--danger); }
.photo-drop__add {
  position: relative; aspect-ratio: 1; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; padding: 8px;
  border: 1.5px dashed var(--line-strong); border-radius: 12px;
  font-size: var(--fs-xs); font-weight: 600; text-align: center; color: var(--ink-2); background: var(--surface);
  transition: border-color var(--dur), color var(--dur), background-color var(--dur);
}
.photo-drop__add .icon { width: 22px; height: 22px; color: var(--ink-3); }
.photo-drop__add:hover, .photo-drop__add.is-over { border-color: var(--accent); color: var(--accent-ink); background: var(--accent-soft); }
.photo-drop__add:hover .icon { color: var(--accent-ink); }
.photo-drop__add:focus-within { box-shadow: 0 0 0 4px var(--accent-ring); border-color: var(--accent); }
.photo-drop__input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.photo-drop__hint { grid-column: 1 / -1; font-size: var(--fs-xs); color: var(--ink-3); }

/* ── Grille d'options (radio / case en tuiles) ───────────── */
.option-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 130px), 1fr)); gap: 8px; }
.option-grid-inline { display: flex; flex-wrap: wrap; }
.option { position: relative; display: block; cursor: pointer; }
.option__input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.option__box {
  min-height: 48px; height: 100%; padding: 8px 12px;
  display: flex; align-items: center; justify-content: center; gap: 7px; text-align: center;
  border: 1px solid var(--line); border-radius: 11px;
  font-size: var(--fs-sm); font-weight: 600; line-height: 1.25; color: var(--ink-2); background: var(--surface);
  transition: border-color var(--dur), background-color var(--dur), color var(--dur), box-shadow var(--dur);
}
.option__box .icon { width: 15px; height: 15px; }
.option:hover .option__box { border-color: var(--ink-4); color: var(--ink); }
.option__input:checked + .option__box { color: var(--accent-ink); background: var(--accent-soft); border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.option__input:focus-visible + .option__box { box-shadow: 0 0 0 4px var(--accent-ring); border-color: var(--accent); }
.option__input:disabled + .option__box { opacity: .45; cursor: not-allowed; }
.option-grid-inline .option__box { min-height: 38px; padding: 0 14px; border-radius: var(--r-pill); }

/* ── Carte de chaleur (heures de pointe) ─────────────────────
   Chaque case reçoit --value entre 0 et 1 ; le nombre reste lisible par
   les lecteurs d'écran (title + texte masqué).
   ─────────────────────────────────────────────────────────── */
/* Grille et non tableau : toutes les colonnes d'heures ont la même largeur, quel que soit
   leur libellé (une heure sur deux est écrite). --cols = nombre d'heures. Les rangées
   (.heatmap__row, display: contents) gardent les rôles ARIA d'un tableau. */
.heatmap {
  --cols: 12;
  display: grid; grid-template-columns: max-content repeat(var(--cols), minmax(14px, 1fr));
  gap: 3px; font-size: var(--fs-micro);
}
.heatmap__row { display: contents; }
.heatmap__head { padding: 2px 0; font-weight: 600; color: var(--ink-3); text-align: center; white-space: nowrap; }
.heatmap__day { display: flex; align-items: center; padding-right: 6px; font-weight: 600; color: var(--ink-3); white-space: nowrap; }
.heatmap__cell {
  --value: 0;
  position: relative; height: 26px; border-radius: 6px;
  background: color-mix(in oklab, var(--accent) calc(var(--value) * 100%), var(--surface-2));
}
/* Téléphone : colonnes compressibles (plus de 14 px imposés) et écart réduit, la grille tient dans la largeur
   sans barre de défilement ; un libellé d'heure peut déborder sur la colonne vide voisine (demande de Loïc, 03/11) */
@media (max-width: 560px) {
  .heatmap { gap: 2px; grid-template-columns: max-content repeat(var(--cols), minmax(0, 1fr)); }
  /* Libellés d'heure plus larges que leur colonne : en flex, ils débordent des deux côtés (centrés) ; le dernier,
     calé à la fin, déborde vers la grille et non hors de la carte (un texte aligné à droite déborderait quand même
     à droite et créerait la barre de défilement) */
  .heatmap__head { display: flex; justify-content: center; min-width: 0; overflow: visible; }
  .heatmap__row:first-child .heatmap__head:last-child { justify-content: flex-end; }
  .heatmap__cell { border-radius: 4px; }
}
.heatmap__legend { display: flex; align-items: center; gap: 8px; margin-top: 10px; font-size: var(--fs-xs); color: var(--ink-3); }
.heatmap__scale { width: 120px; height: 8px; border-radius: var(--r-pill); background: linear-gradient(90deg, var(--surface-2), var(--accent)); }

/* ── Mini-courbe (tendance d'un indicateur) ──────────────── */
.sparkline { display: block; width: 100%; height: 40px; overflow: visible; }
.sparkline__area { fill: var(--chart-accent-soft); stroke: none; }
.sparkline__line { fill: none; stroke: var(--chart-accent); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.sparkline__dot { fill: var(--surface); stroke: var(--chart-accent); stroke-width: 2; vector-effect: non-scaling-stroke; }

/* ── integration.css ── */
/* =========================================================================
   Spyglass · integration.css
   Correctifs communs à toutes les applications (Spyglass, Lighthouse…),
   constatés en intégration. Chargé en dernier : il passe après les autres
   feuilles du kit, comme le faisaient ces règles dans les app.css des sites.
   Une règle qui ne sert qu'à un site va dans la feuille de ce site.
   ========================================================================= */

/* Libellés .visually-hidden (position:absolute) dans un tableau défilant :
   sans ancêtre positionné, ils sortent du conteneur et élargissent la page sur mobile. */
.table-wrap { position: relative; }

/* .btn (buttons.css, chargé après layout.css) réaffichait le bouton menu sur ordinateur */
.btn.topbar__menu { display: none; }
@media (max-width: 960px) { .btn.topbar__menu { display: inline-grid; } }
/* Bouton du menu (mobile) : même forme que le logo, carré cerné d'un filet et légèrement arrondi
   (rayon du petit logo, 8 px pour 28, ramené aux 32 px du bouton). Demande de Loïc, 29/10. */
.btn.topbar__menu { border-color: var(--line); border-radius: 9px; }
.btn.topbar__menu:hover { border-color: var(--line-strong); }
/* Icônes de la barre du haut : 17 × 17 px pour les actions (thème, cloche…), 20 × 20 px pour le menu, à la
   couleur d'accent du site (demandes de Loïc, 03/11) */
.topbar__actions .btn .icon { width: 17px; height: 17px; }
.btn.topbar__menu .icon { width: 20px; height: 20px; }
.btn.topbar__menu { color: var(--accent); }
/* Mobile : logo et nom de l'application à gauche de la barre du haut ; à droite, le bouton clair / sombre
   (dernier des actions) puis le bouton du menu, tout au bout. Le titre de la barre n'est pas affiché :
   le logo prend sa place (l'en-tête de page porte déjà le titre). Demande de Loïc, 29/10. */
.topbar__brand { display: none; }
@media (max-width: 960px) {
  .topbar__brand { display: inline-flex; min-width: 0; }
  .topbar__title { display: none; }
  .btn.topbar__menu { order: 1; }
  /* Le bouton du menu passé à droite éloigne la cloche du bord : le panneau des notifications se cale
     sur le bord droit de la barre (.bell sans position, la barre collante sert de repère), pas sur la
     cloche, sinon il déborde à gauche sur téléphone. */
  .topbar .bell { position: static; }
  .topbar .bell__panel { right: 12px; }
}

/* Mobile : statistiques deux par ligne plutôt qu'une pleine largeur chacune */
@media (max-width: 560px) {
  .stat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stat-grid > :last-child:nth-child(odd) { grid-column: 1 / -1; }
}

/* Mobile : titre de la barre du haut tronqué, actions resserrées, libellés masqués */
@media (max-width: 560px) {
  .topbar { gap: 8px; }
  .topbar__title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .topbar__actions { gap: 4px; }
  .topbar__actions .btn:has(.btn__label) { font-size: 0; gap: 0; }
  .topbar__actions .btn__label, .topbar__divider { display: none; }
}

/* Grilles de cartes : chaque carte garde sa hauteur (pas d'étirement à la plus haute) */
.grid-2, .grid-3 { align-items: start; }

/* Textes saisis par les utilisateurs (liens, chemins, adresses) : coupés plutôt que d'élargir la page */
.comment__main, .feed__body { min-width: 0; }
.comment__bubble, .feed__quote { overflow-wrap: anywhere; }

/* Colonne de lecture (pages d'une seule carte : compte, détail, paiement) */
.page-narrow { max-width: 840px; margin-inline: auto; }
.portal__content.page-narrow { max-width: 840px; }

/* Pied de page commun (contact, pages légales) */
.app__footer {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 18px;
  margin-top: auto; padding: 18px var(--gutter) 24px;
  border-top: 1px solid var(--line-2);
  font-size: var(--fs-xs); color: var(--ink-3);
}
.app__footer a { color: var(--ink-2); text-decoration: underline; text-underline-offset: 2px; }
.app__footer a:hover { color: var(--accent-ink); }
.portal__footer.app__footer { max-width: 980px; margin: 0 auto; padding: 22px 24px 32px; border-top: 0; justify-content: center; text-align: center; }
.portal { min-height: 100vh; display: flex; flex-direction: column; }
.portal__content { width: 100%; }

/* En-tête public : liens à droite */
.portal__nav { margin-left: auto; display: flex; align-items: center; gap: 6px; }
@media (max-width: 480px) { .portal__nav .btn-ghost:not(.btn-icon) { display: none; } }

/* Pages d'accès : liens légaux sous la carte */
.auth__legal { margin-top: 18px; text-align: center; font-size: var(--fs-xs); color: var(--ink-3); }
.auth__legal a { color: var(--ink-2); text-decoration: underline; text-underline-offset: 2px; }

/* Documents légaux : choix du document centré, défilant sur mobile */
.legal__nav { display: flex; justify-content: center; margin-bottom: 18px; overflow-x: auto; }
/* Document dans une carte : texte sur toute la largeur de la carte, sections séparées par un filet */
.legal__content { max-width: none; padding-block: 28px; }
.legal__content h1 { font: 700 var(--fs-2xl)/1.15 var(--font-display); letter-spacing: -.03em; color: var(--ink); }
.legal__content h2 { padding-top: 18px; border-top: 1px solid var(--line-2); }
.legal__date { font-size: var(--fs-sm); color: var(--ink-3); }
/* Contenu des documents (Lighthouse, Spyglass) : date, tableaux libellé / valeur, valeur à compléter */
.legal-maj { font-size: var(--fs-xs); color: var(--ink-3); }
.legal-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.legal-table td { padding: 9px 12px 9px 0; border-bottom: 1px solid var(--line-2); vertical-align: top; }
.legal-table td:first-child { width: 38%; font-weight: 600; color: var(--ink-3); }
.legal-todo { padding: 1px 6px; border-radius: 4px; font-weight: 600; color: var(--warning-ink); background: var(--warning-soft); }
@media (max-width: 640px) {
  .legal-table td { display: block; width: 100% !important; border: 0; padding: 3px 0; }
  .legal-table tr { display: block; padding: 8px 0; border-bottom: 1px solid var(--line-2); }
}

/* Listes : barre de recherche et de filtres au-dessus d'un tableau (.reports__filters.listing__bar) */
.listing__bar { margin-bottom: 12px; }
.listing__search { flex: 1 1 220px; min-width: 180px; }
/* Tout à la hauteur du champ de recherche (42 px) : listes en .select (pas .select-sm), boutons à 42 px
   (Lighthouse et Flagship, demande de Loïc, 30/10) */
.listing__bar > .btn { --btn-h: 42px; }
/* Résumé de liste et lien « Réinitialiser » à sa droite, seulement quand un filtre est actif (Lighthouse : Listing::entete ;
   FlagShip : pagination du haut). Lien simple souligné, plus de bouton « Filtrer » ni « Tout effacer » (Loïc, 04/11). */
.listing__info { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: 4px 14px; }
.listing__reset { font-size: var(--fs-sm); color: var(--ink-2); text-decoration: underline; text-underline-offset: 3px; }
.listing__reset:hover { color: var(--accent-ink); }
@media (max-width: 820px) {
  .listing__bar { flex-direction: column; align-items: stretch; }
  .listing__bar .listing__search { flex: none; }   /* en colonne, la base de 220 px devenait une hauteur */
  .listing__bar .select { width: 100%; }
}

/* Entrée de page, la même sur tous les sites : glissement de 12 px comme .fade-up, mais plus doux
   (0,7 s, courbe qui ralentit franchement à la fin, sans délai). Réglée avec Loïc sur Flagship, 29/10. */
.page.fade-up { animation-duration: .7s; animation-delay: 0s; animation-timing-function: cubic-bezier(.16, 1, .3, 1); }
@media (prefers-reduced-motion: reduce) { .page.fade-up { animation: none; opacity: 1; transform: none; } }
