/* ════════════════════════════════════════════════════════
   FormGenerator.css — v3.5
   Styles + thèmes intégrés (variables CSS par classe)
   ════════════════════════════════════════════════════════ */

/* ── Variables partagées entre tous les thèmes sombres ─── */
/* La police DM Mono est commune à dark, light, ocean,      */
/* sunset, forest et monochrome. Elle est déclarée ici      */
/* et chaque thème peut la surcharger si besoin.            */
:root {
  --fg-font-mono: 'DM Mono', monospace;
  --fg-font-system: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
}

/* ── Thème par défaut ─────────────────────────────────── */
.fg-form {
  display: block;
  width: 100%;
  --fg-bg: #fafafa;
  --fg-surface: #ffffff;
  --fg-surface2: #ffffff;
  --fg-border: #e5e5e5;
  --fg-border-focus: #0066cc;
  --fg-accent: #0066cc;
  --fg-accent-glow: rgba(0, 102, 204, 0.12);
  --fg-accent-ring: rgba(0, 102, 204, 0.15);
  --fg-green: #28a745;
  --fg-red: #dc3545;
  --fg-text: #212529;
  --fg-text-muted: #6c757d;
  --fg-text-dim: #495057;
  --fg-placeholder: #6c757d;
  --fg-dropdown-bg: #ffffff;
  --fg-hover-bg: rgba(0, 102, 204, 0.05);
  --fg-checked-bg: rgba(0, 102, 204, 0.08);
  --fg-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  --fg-radius: 6px;
  --fg-font: var(--fg-font-system);
  --fg-field-h: 44px;
}

.fg-form[is-submitting] {
  opacity: 0.6;
  pointer-events: none;
}

/* ── Thème dark ───────────────────────────────────────── */
.fg-form.fg-theme-dark {
  --fg-bg: #0d0f14;
  --fg-surface: #13161e;
  --fg-surface2: #1a1e2a;
  --fg-border: #252936;
  --fg-border-focus: #4f6ef7;
  --fg-accent: #4f6ef7;
  --fg-accent-glow: rgba(79, 110, 247, 0.18);
  --fg-accent-ring: rgba(79, 110, 247, 0.15);
  --fg-green: #22d3a3;
  --fg-red: #f75f6e;
  --fg-text: #e8eaf2;
  --fg-text-muted: #6b7280;
  --fg-text-dim: #9ca3af;
  --fg-placeholder: #4b5263;
  --fg-dropdown-bg: #161923;
  --fg-hover-bg: rgba(79, 110, 247, 0.10);
  --fg-checked-bg: rgba(79, 110, 247, 0.07);
  --fg-shadow: 0 16px 40px rgba(0, 0, 0, 0.5);
  --fg-radius: 10px;
  --fg-font: var(--fg-font-mono);
  --fg-gps-map-bg: #1a1e2a;
}

/* ── Thème light ──────────────────────────────────────── */
.fg-form.fg-theme-light {
  --fg-bg: #ffffff;
  --fg-surface: #f9fafb;
  --fg-surface2: #f3f4f6;
  --fg-border: #e5e7eb;
  --fg-border-focus: #6366f1;
  --fg-accent: #6366f1;
  --fg-accent-glow: rgba(99, 102, 241, 0.12);
  --fg-accent-ring: rgba(99, 102, 241, 0.15);
  --fg-green: #059669;
  --fg-red: #ef4444;
  --fg-text: #111827;
  --fg-text-muted: #6b7280;
  --fg-text-dim: #374151;
  --fg-placeholder: #9ca3af;
  --fg-dropdown-bg: #ffffff;
  --fg-hover-bg: rgba(99, 102, 241, 0.07);
  --fg-checked-bg: rgba(99, 102, 241, 0.06);
  --fg-shadow: 0 8px 24px rgba(0, 0, 0, 0.10);
  --fg-radius: 8px;
  --fg-font: var(--fg-font-mono);
  --fg-gps-map-bg: #f3f4f6;
}

/* ── Thème ocean ──────────────────────────────────────── */
.fg-form.fg-theme-ocean {
  --fg-bg: #050d1a;
  --fg-surface: #071525;
  --fg-surface2: #0b1e30;
  --fg-border: #0f2d47;
  --fg-border-focus: #00bcd4;
  --fg-accent: #00bcd4;
  --fg-accent-glow: rgba(0, 188, 212, 0.18);
  --fg-accent-ring: rgba(0, 188, 212, 0.15);
  --fg-green: #26c6a0;
  --fg-red: #ff5370;
  --fg-text: #cfe8f5;
  --fg-text-muted: #4a7a96;
  --fg-text-dim: #7fb5cc;
  --fg-placeholder: #2a5570;
  --fg-dropdown-bg: #071828;
  --fg-hover-bg: rgba(0, 188, 212, 0.10);
  --fg-checked-bg: rgba(0, 188, 212, 0.08);
  --fg-shadow: 0 16px 48px rgba(0, 0, 0, 0.6);
  --fg-radius: 10px;
  --fg-font: var(--fg-font-mono);
  --fg-gps-map-bg: #0b1e30;
}

/* ── Thème sunset ─────────────────────────────────────── */
.fg-form.fg-theme-sunset {
  --fg-bg: #1a0f0a;
  --fg-surface: #231510;
  --fg-surface2: #2e1c15;
  --fg-border: #4a2e22;
  --fg-border-focus: #f97316;
  --fg-accent: #f97316;
  --fg-accent-glow: rgba(249, 115, 22, 0.18);
  --fg-accent-ring: rgba(249, 115, 22, 0.15);
  --fg-green: #34d399;
  --fg-red: #fb7185;
  --fg-text: #fde8d8;
  --fg-text-muted: #8c5a42;
  --fg-text-dim: #c4846a;
  --fg-placeholder: #5c3525;
  --fg-dropdown-bg: #1e1008;
  --fg-hover-bg: rgba(249, 115, 22, 0.10);
  --fg-checked-bg: rgba(249, 115, 22, 0.08);
  --fg-shadow: 0 16px 48px rgba(0, 0, 0, 0.55);
  --fg-radius: 12px;
  --fg-font: var(--fg-font-mono);
  --fg-gps-map-bg: #2e1c15;
}

/* ── Thème forest ─────────────────────────────────────── */
.fg-form.fg-theme-forest {
  --fg-bg: #060e08;
  --fg-surface: #0b1710;
  --fg-surface2: #102016;
  --fg-border: #1a3522;
  --fg-border-focus: #22c55e;
  --fg-accent: #22c55e;
  --fg-accent-glow: rgba(34, 197, 94, 0.18);
  --fg-accent-ring: rgba(34, 197, 94, 0.15);
  --fg-green: #4ade80;
  --fg-red: #f87171;
  --fg-text: #d1fae5;
  --fg-text-muted: #3d6b4e;
  --fg-text-dim: #6bab82;
  --fg-placeholder: #254733;
  --fg-dropdown-bg: #081208;
  --fg-hover-bg: rgba(34, 197, 94, 0.10);
  --fg-checked-bg: rgba(34, 197, 94, 0.08);
  --fg-shadow: 0 16px 48px rgba(0, 0, 0, 0.6);
  --fg-radius: 10px;
  --fg-font: var(--fg-font-mono);
  --fg-gps-map-bg: #102016;
}

/* ── Thème monochrome ─────────────────────────────────── */
.fg-form.fg-theme-monochrome {
  --fg-bg: #000000;
  --fg-surface: #0a0a0a;
  --fg-surface2: #141414;
  --fg-border: #2a2a2a;
  --fg-border-focus: #ffffff;
  --fg-accent: #ffffff;
  --fg-accent-glow: rgba(255, 255, 255, 0.10);
  --fg-accent-ring: rgba(255, 255, 255, 0.10);
  --fg-green: #aaaaaa;
  --fg-red: #888888;
  --fg-text: #f5f5f5;
  --fg-text-muted: #555555;
  --fg-text-dim: #999999;
  --fg-placeholder: #333333;
  --fg-dropdown-bg: #0d0d0d;
  --fg-hover-bg: rgba(255, 255, 255, 0.06);
  --fg-checked-bg: rgba(255, 255, 255, 0.05);
  --fg-shadow: 0 16px 40px rgba(0, 0, 0, 0.8);
  --fg-radius: 6px;
  --fg-font: var(--fg-font-mono);
  --fg-gps-map-bg: #141414;
}

/* ────────────────────────────────────────────────────────
   GPS map — base (couleur de fond pilotée par --fg-gps-map-bg,
   définie par chaque thème sur .fg-form.fg-theme-x ci-dessus ;
   thème "default" → pas de variable définie, fallback #e9ecef).
   Piloter cette couleur via une variable CSS — plutôt que par un
   sélecteur descendant .fg-form.fg-theme-x .fg-gps-map comme
   auparavant — permet à _applyThemeToTeleported() de la reporter
   correctement sur le wrapper GPS une fois celui-ci téléporté hors
   de .fg-form (popup GLightbox d'agrandissement, cf.
   _fgOpenGpsExpandPopup dans form_generator.js) : un sélecteur
   descendant ne peut plus matcher une fois l'élément sorti de
   l'arbre .fg-form, alors qu'une variable CSS recopiée en inline
   continue de s'appliquer.
   ──────────────────────────────────────────────────────── */
.fg-gps-map {
  margin-top: 2px;
  min-height: 240px;
  height: 240px;
  border-radius: var(--fg-radius);
  border: 1px solid var(--fg-border);
  background: var(--fg-gps-map-bg, #e9ecef);
}
  
  .fg-file-zone {
    min-height: 120px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
  }
  
  .fg-file-zone input[type='file'] {
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
  }
  
  .fg-select-trigger {
    -webkit-appearance: none;
    appearance: none;
  }
  
  .fg-form button:not(:disabled) {
    cursor: pointer;
  }
  
  .fg-dropdown-teleport,
  .fg-confirm-popup,
  .fg-date-cal {
    -webkit-transform: translateZ(0);
    transform: translateZ(0);
  }
  
  /* ========== STYLES DE BASE ========== */
  
  .fg-form {
    font-family: var(--fg-font);
    font-size: 14px;
    color: var(--fg-text);
  }
  
  .fg-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 16px;
    /* Permet au champ de retrecir sous sa taille intrinseque (max-content)
       quand il est contraint par un parent flex (.fg-group-body en pile)
       ou grille (.fg-group[data-fg-columns] .fg-group-body) plus etroit
       que son contenu naturel : sans ce reset, un champ composite
       (icon+color picker, double, gps...) deborde silencieusement hors
       du viewport plutot que de se compresser. */
    min-width: 0;
  }
  
  .fg-label {
    font-size: 11.5px;
    font-weight: 500;
    color: var(--fg-text-dim);
    letter-spacing: 0.07em;
    text-transform: uppercase;
    display: flex;
    align-items: center;
    gap: 6px;
    user-select: none;
  }
  
  .fg-required {
    color: var(--fg-red);
    font-size: 14px;
    line-height: 1;
  }

  /* ── Groupes de champs (fieldsets) ───────────────────────────────────────
     <fieldset class="fg-group"> natif : le navigateur "découpe" déjà la
     bordure supérieure au niveau du <legend> par défaut — on s'appuie sur ce
     comportement plutôt que de le réimplémenter en position:absolute. */
  .fg-group {
    border: 1px solid var(--fg-border);
    border-radius: var(--fg-radius);
    background: var(--fg-surface);
    margin: 0 0 20px;
    /* Padding-top porte a 18px (au lieu de 6px) : la legende, decoupee dans
       la bordure par le <fieldset> natif, ne laissait quasiment aucun espace
       avant le premier champ, qui se retrouvait visuellement colle au bord
       superieur du groupe. */
    padding: 18px 20px 4px;
    min-width: 0;
    transition: border-color 0.18s, box-shadow 0.18s;
  }

  .fg-group + .fg-group { margin-top: 0; }

  /* Un groupe qui contient une erreur de validation (posée par le code
     appelant sur .fg-field.fg-invalid) reste visuellement neutre lui-même :
     seul le champ fautif à l'intérieur est mis en évidence. Un focus sur
     n'importe quel contrôle interne au groupe est en revanche un signal
     utile — légère mise en avant de la bordure, cohérente avec le focus des
     champs simples. */
  .fg-group:focus-within {
    border-color: var(--fg-border-focus);
  }

  .fg-group-legend {
    display: flex;
    align-items: center;
    gap: 6px;
    /* Fond en "badge" pose sur la coupure de bordure du <fieldset> :
       --fg-accent-glow est une teinte de l'accent du theme (12-18% d'opacite
       selon les themes), donc toujours visible sur --fg-surface, contrairement
       a --fg-surface2 qui est parfois identique a --fg-surface (theme clair
       par defaut). border-radius via --fg-radius pour rester coherent avec le
       reste des composants (champs, groupes...). */
    background: var(--fg-accent-glow);
    border-radius: var(--fg-radius);
    padding: 3px 9px;
    margin-left: 2px;
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--fg-accent);
    user-select: none;
    transition: background-color 0.18s, color 0.18s;
  }

  .fg-group-legend--toggleable {
    cursor: pointer;
  }

  .fg-group-legend--toggleable:hover {
    background: color-mix(in srgb, var(--fg-accent-glow), var(--fg-accent) 12%);
  }

  .fg-group-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    padding: 0;
    border: none;
    background: transparent;
    color: var(--fg-text-dim);
    cursor: pointer;
    flex-shrink: 0;
    transition: transform 0.2s ease, color 0.15s ease;
  }

  .fg-group-toggle:hover { color: var(--fg-accent); }

  .fg-group.fg-group-collapsed .fg-group-toggle {
    transform: rotate(-90deg);
  }

  .fg-group-description {
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--fg-text-muted);
    margin: 4px 2px 16px;
  }

  /* Piège CSS "grid-template-rows: 0fr" pour un repli/dépli animé sans
     connaître la hauteur du contenu à l'avance — robuste au contenu
     dynamique (select ouvert, texte traduit plus long, etc.). */
  .fg-group-collapse {
    display: grid;
    grid-template-rows: 1fr;
    transition: grid-template-rows 0.22s ease;
  }
  .fg-group.fg-group-collapsed .fg-group-collapse {
    grid-template-rows: 0fr;
  }
  .fg-group-collapse-inner {
    overflow: hidden;
    min-height: 0;
  }

  .fg-group-body {
    display: flex;
    flex-direction: column;
  }
  .fg-group-body > .fg-field:last-child,
  .fg-group-body > .fg-group:last-child {
    margin-bottom: 16px; /* conserve la respiration basse même en dernière position */
  }

  /* Grille interne à plusieurs colonnes — répartit les champs du groupe côte
     à côte plutôt qu'en pile verticale (ex. Prénom/Nom, Ville/Code postal).
     Un champ "double" ou de largeur intrinsèquement pleine (textarea,
     richtext, file…) reste libre de s'étendre sur toute la largeur au
     besoin via cfg.class + 'grid-column: 1 / -1' côté appelant. */
  .fg-group[data-fg-columns] .fg-group-body {
    display: grid;
    grid-template-columns: repeat(var(--fg-group-cols, 1), 1fr);
    column-gap: 20px;
    row-gap: 0;
    align-items: start;
  }
  .fg-group[data-fg-columns="2"] .fg-group-body { --fg-group-cols: 2; }
  .fg-group[data-fg-columns="3"] .fg-group-body { --fg-group-cols: 3; }
  .fg-group[data-fg-columns="4"] .fg-group-body { --fg-group-cols: 4; }
  .fg-group[data-fg-columns] .fg-group-body > .fg-field,
  .fg-group[data-fg-columns] .fg-group-body > .fg-group {
    margin-bottom: 16px; /* remplace le row-gap : uniforme avec le mode pile */
  }
  .fg-group[data-fg-columns] .fg-group-body > .fg-group {
    grid-column: 1 / -1; /* un sous-groupe imbriqué reste toujours pleine largeur */
  }
  .fg-group[data-fg-columns] .fg-group-body > .fg-field-full {
    grid-column: 1 / -1; /* cf. cfg.fullWidth dans _buildField() */
  }

  /* ── Groupe "actions" (cfg.layout === 'actions') ───────────────────────
     Rangée de boutons CRUD (Ajouter / Mettre à jour + Supprimer…) : AUCUN
     chrome de conteneur - pas de bordure, pas de fond, pas de hover/focus
     visible sur le <fieldset> lui-même (seuls les boutons enfants gardent
     leur propre hover/focus). Les boutons se suivent immédiatement, sans
     séparateur, avec un espacement minimal (8px) plutôt qu'empilés en
     colonne comme un groupe classique. */
  .fg-group[data-fg-layout="actions"] {
    border: none;
    background: transparent;
    padding: 0;
  }

  .fg-group[data-fg-layout="actions"]:hover,
  .fg-group[data-fg-layout="actions"]:focus-within {
    border-color: transparent;
    box-shadow: none;
  }

  .fg-group[data-fg-layout="actions"] .fg-group-body {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
  }

  /* Les champs 'button' individuels restent des .fg-field (label éventuel,
     etc.) mais ne doivent ni s'étirer sur toute la largeur (comportement
     par défaut en pile verticale) ni conserver leur marge basse - la rangée
     gère elle-même l'espacement horizontal via le gap ci-dessus. */
  .fg-group[data-fg-layout="actions"] .fg-group-body > .fg-field {
    width: auto;
    margin-bottom: 0;
  }

  @media (max-width: 640px) {
    .fg-group[data-fg-columns] .fg-group-body {
      grid-template-columns: 1fr;
    }
  }

  /* Label présent pour l'accessibilité (lu par les lecteurs d'écran et
     ciblé par label[for]) mais visuellement masqué : utilisé quand le
     design ne prévoit pas de label visible pour un sous-champ (ex.
     Latitude/Longitude du champ GPS, saisie du captcha) et que le
     placeholder seul ne suffit pas comme nom accessible. Technique
     standard "clip" : l'élément reste dans le flux (measurable) mais
     n'occupe visuellement aucun espace ni pixel visible. */
  .fg-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }
  
  .fg-input,
  .fg-textarea {
    background: var(--fg-surface2);
    border: 1px solid var(--fg-border);
    border-radius: var(--fg-radius);
    color: var(--fg-text);
    font-family: var(--fg-font);
    font-size: 14px;
    padding: 0 14px;
    height: var(--fg-field-h);
    outline: none;
    width: 100%;
    resize: none;
    box-sizing: border-box;
    transition: border-color 0.18s, box-shadow 0.18s, background 0.18s;
  }
  
  .fg-input::placeholder,
  .fg-textarea::placeholder {
    color: var(--fg-placeholder);
  }
  
  .fg-input:hover:not(:focus),
  .fg-textarea:hover:not(:focus) {
    border-color: color-mix(in srgb, var(--fg-border) 80%, #000);
    box-shadow: 0 3px 8px rgba(0,0,0,0.08);
  }

  .fg-input:focus,
  .fg-textarea:focus {
    border-color: var(--fg-border-focus);
    box-shadow: 0 0 0 3px var(--fg-accent-ring);
    background: var(--fg-surface);
  }
  
  .fg-textarea {
    height: auto;
    min-height: 90px;
    padding: 11px 14px;
    resize: vertical;
  }
  
  /* Rich text */
  .fg-richtext-wrapper {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--fg-border);
    border-radius: var(--fg-radius);
    overflow: visible;
    transition: border-color 0.18s, box-shadow 0.18s;
    position: relative;
  }
  
  .fg-richtext-wrapper .fg-byte-counter {
    order: 1;
    margin-top: 6px;
  }

  /* Coins arrondis sans overflow:hidden — celui-ci clippait les dropdowns .ql-picker-options */
  .fg-richtext-wrapper .ql-toolbar { border-radius: var(--fg-radius) var(--fg-radius) 0 0; overflow: visible; }
  .fg-richtext-wrapper .ql-container { border-radius: 0 0 var(--fg-radius) var(--fg-radius); overflow: visible; }
  
  .fg-richtext-wrapper:hover:not(:focus-within) {
    border-color: color-mix(in srgb, var(--fg-border) 80%, #000);
    box-shadow: 0 3px 8px rgba(0,0,0,0.08);
  }

  .fg-richtext-wrapper:focus-within {
    border-color: var(--fg-border-focus);
    box-shadow: 0 0 0 3px var(--fg-accent-ring);
  }
  
  .fg-field .fg-richtext-counter {
    margin-top: 6px;
    text-align: right;
  }
  
  .fg-richtext-wrapper .fg-byte-counter {
    display: none;
  }
  
  .fg-richtext-wrapper .ql-toolbar {
    background: var(--fg-surface);
    border: none;
    border-bottom: 1px solid var(--fg-border);
    padding: 8px 10px;
    flex-wrap: wrap;
    position: relative;   /* crée un contexte d'empilement */
    z-index: 2;           /* passe au-dessus de ql-container */
  }
  
  .fg-richtext-wrapper .ql-toolbar button {
    color: var(--fg-text-dim) !important;
    border-radius: 4px;
    transition: background 0.15s, color 0.15s;
  }
  
  .fg-richtext-wrapper .ql-toolbar button:hover,
  .fg-richtext-wrapper .ql-toolbar button.ql-active {
    background: var(--fg-hover-bg) !important;
    color: var(--fg-accent) !important;
  }
  
  .fg-richtext-wrapper .ql-toolbar .ql-stroke {
    stroke: var(--fg-text-dim);
  }
  
  .fg-richtext-wrapper .ql-toolbar button:hover .ql-stroke,
  .fg-richtext-wrapper .ql-toolbar button.ql-active .ql-stroke {
    stroke: var(--fg-accent);
  }
  
  .fg-richtext-wrapper .ql-toolbar .ql-fill {
    fill: var(--fg-text-dim);
  }
  
  .fg-richtext-wrapper .ql-toolbar button:hover .ql-fill,
  .fg-richtext-wrapper .ql-toolbar button.ql-active .ql-fill {
    fill: var(--fg-accent);
  }
  
  .fg-richtext-wrapper .ql-toolbar .ql-picker-label {
    color: var(--fg-text-dim);
  }
  
  .fg-richtext-wrapper .ql-toolbar .ql-picker {
    position: relative;
  }
  .fg-richtext-wrapper .ql-toolbar .ql-picker-options {
    background: var(--fg-dropdown-bg);
    border: 1px solid var(--fg-border);
    border-radius: var(--fg-radius);
    box-shadow: var(--fg-shadow);
    position: absolute;
    z-index: 10;
  }
  
  .fg-richtext-wrapper .ql-toolbar .ql-picker-item {
    color: var(--fg-text-dim);
  }
  
  .fg-richtext-wrapper .ql-toolbar .ql-picker-item:hover {
    color: var(--fg-accent);
  }
  
  .fg-richtext-wrapper .ql-container {
    border: none;
    font-family: var(--fg-font);
    font-size: 14px;
  }
  
  /* Le fond colore vient de .ql-editor lui-meme (pas de .ql-container,
     transparent) : sans son propre border-radius, ce fond rectangulaire
     depassait l'arrondi du wrapper des lors que overflow:visible est
     necessaire (cf. commentaire plus haut sur les dropdowns Quill) — d'ou
     les coins inferieurs qui semblaient "coupes" au lieu d'etre arrondis. */
  .fg-richtext-wrapper .ql-editor {
    background: var(--fg-surface2);
    color: var(--fg-text);
    min-height: 120px;
    padding: 12px 14px;
    line-height: 1.7;
    border-radius: 0 0 var(--fg-radius) var(--fg-radius);
  }
  
  .fg-richtext-wrapper .ql-editor.ql-blank::before {
    color: var(--fg-placeholder);
    font-style: normal;
  }
  
  .fg-richtext-wrapper .ql-editor h1,
  .fg-richtext-wrapper .ql-editor h2,
  .fg-richtext-wrapper .ql-editor h3 {
    color: var(--fg-text);
    margin: 0.4em 0;
  }
  
  .fg-richtext-wrapper .ql-editor a {
    color: var(--fg-accent);
  }
  
  .fg-richtext-wrapper .ql-editor ul,
  .fg-richtext-wrapper .ql-editor ol {
    padding-left: 1.5em;
  }
  
  .fg-richtext-wrapper .ql-tooltip {
    background: var(--fg-surface);
    border: 1px solid var(--fg-border);
    border-radius: var(--fg-radius);
    color: var(--fg-text);
    box-shadow: var(--fg-shadow);
  }
  
  .fg-richtext-wrapper .ql-tooltip input {
    background: var(--fg-surface2);
    border: 1px solid var(--fg-border);
    color: var(--fg-text);
    border-radius: 4px;
    padding: 2px 6px;
  }
  
  .fg-richtext-wrapper .ql-tooltip a.ql-action,
  .fg-richtext-wrapper .ql-tooltip a.ql-remove {
    color: var(--fg-accent);
  }
  
  /* Compteur de bytes pour textarea et richtext */
  .fg-textarea-wrapper {
    position: relative;
    width: 100%;
  }

  /* Copy btn en overlay dans textarea et richtext */
  .fg-copy-btn--textarea,
  .fg-copy-btn--richtext {
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 3;
  }

  /* Bouton "Agrandir" (popup plein écran, cf. _fgOpenRichtextExpandPopup) —
     même coin que .fg-copy-btn--richtext (8px du bord, à droite en LTR, à
     gauche en RTL, cf. .fg-rtl .fg-richtext-expand-btn plus bas). Les deux
     boutons se chevauchent donc visuellement lorsqu'ils sont visibles en
     même temps — le bouton copier restant masqué tant que le champ a le
     focus ou est vide (cf. updateCopyBtn dans _buildRichtext), le
     chevauchement ne survient qu'une fois le champ rempli ET non focus. */
  .fg-richtext-expand-btn {
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 3;
    width: 26px;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: var(--fg-text-muted, #6b7280);
    cursor: pointer;
    padding: 0;
    overflow: hidden; /* clippe l'animation .fg-ripple-host (_ripple()) */
    transition: background 0.15s, color 0.15s;
  }
  .fg-richtext-expand-btn:hover {
    background: var(--fg-hover-bg);
    color: var(--fg-accent);
  }
  .fg-richtext-expand-btn:focus-visible {
    box-shadow: inset 0 0 0 2px var(--fg-border-focus);
    outline: none;
  }
  
  .fg-byte-counter {
    font-size: 11px;
    color: var(--fg-text-muted);
    text-align: right;
    margin-top: 4px;
    transition: color 0.2s;
  }
  
  .fg-byte-counter.fg-byte-counter-exceeded {
    color: var(--fg-red);
    font-weight: 500;
  }
  
  /* Select */
  .fg-select-wrapper {
    position: relative;
    user-select: none;
  }
  
  .fg-select-trigger {
    background: var(--fg-surface2);
    border: 1px solid var(--fg-border);
    border-radius: var(--fg-radius);
    color: var(--fg-text);
    font-family: var(--fg-font);
    font-size: 14px;
    padding: 0 14px;
    height: var(--fg-field-h);
    box-sizing: border-box;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    transition: border-color 0.18s, box-shadow 0.18s;
  }
  
  .fg-select-trigger:hover {
    border-color: color-mix(in srgb, var(--fg-border) 80%, #000);
    box-shadow: 0 3px 8px rgba(0,0,0,0.08);
  }
  
  .fg-select-trigger.open {
    border-color: var(--fg-border-focus);
    box-shadow: 0 0 0 3px var(--fg-accent-ring);
    border-radius: var(--fg-radius) var(--fg-radius) 0 0;
  }
  
  .fg-chevron {
    transition: transform 0.18s;
    color: var(--fg-text-muted);
    flex-shrink: 0;
  }
  
  .fg-select-trigger.open .fg-chevron {
    transform: rotate(180deg);
  }
  
  .fg-select-placeholder {
    color: var(--fg-placeholder);
  }
  
  .fg-dropdown {
    display: none;
    position: absolute;
    left: 0;
    right: 0;
    background: var(--fg-dropdown-bg);
    border: 1px solid var(--fg-border-focus);
    border-top: none;
    border-radius: 0 0 var(--fg-radius) var(--fg-radius);
    z-index: 100;
    box-shadow: var(--fg-shadow);
    overflow: hidden;
  }
  
  .fg-dropdown.open {
    display: block;
  }
  
  /* Dropdown téléporté (hors scope) */
  .fg-dropdown-teleport {
    display: none;
    position: fixed;
    z-index: 9999;
    background: var(--fg-dropdown-bg);
    scrollbar-width: thin;
    scrollbar-color: var(--fg-border, #252936) transparent;
    overflow: visible;
    font-family: var(--fg-font, 'DM Mono', monospace);
    font-size: 14px;
    border-radius: var(--fg-radius);
    box-shadow:
      0 8px 24px rgba(0, 0, 0, 0.18),
      0 20px 48px rgba(0, 0, 0, 0.22),
      0 0 0 1px rgba(0, 0, 0, 0.06);
    -webkit-transform: translateZ(0);
    transform: translateZ(0);
  }
  
  .fg-dropdown-teleport.open {
    display: block;
  }
  
  /* Les listes internes restent clipées normalement */
  .fg-dropdown-teleport .fg-options-list {
    overflow-y: auto;
    border-radius: inherit;
  }
  
  .fg-dropdown-teleport .fg-options-list::-webkit-scrollbar {
    width: 5px;
  }
  
  .fg-dropdown-teleport .fg-options-list::-webkit-scrollbar-thumb {
    border-radius: 99px;
  }
  
  .fg-dropdown-teleport .fg-option {
    padding: 10px 14px;
    cursor: pointer;
    font-size: 13.5px;
    display: flex;
    align-items: center;
    gap: 8px;
    transition: background 0.15s, color 0.15s;
    border-top: 1px solid var(--fg-border);
  }
  .fg-dropdown-teleport .fg-option:first-child {
    border-top: none;
  }
  
  .fg-dropdown-teleport .fg-option.hidden {
    display: none;
  }
  
  .fg-dropdown-teleport .fg-no-results {
    padding: 14px;
    font-size: 13px;
    text-align: center;
    display: none;
  }
  
  .fg-dropdown-teleport .fg-option-avatar {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
  }
  
  .fg-dropdown-teleport .fg-option-icon {
    font-size: 14px;
    flex-shrink: 0;
    width: 20px;
    text-align: center;
  }
  
  .fg-dropdown-teleport .fg-multi-close-row {
    padding: 8px 12px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
  }
  
  .fg-dropdown-teleport .fg-multi-count {
    font-size: 11px;
  }
  
  .fg-options-list {
    max-height: 180px;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: var(--fg-border) transparent;
  }
  
  .fg-option {
    padding: 10px 14px;
    cursor: pointer;
    font-size: 13.5px;
    color: var(--fg-text-dim);
    display: flex;
    align-items: center;
    gap: 8px;
    transition: background 0.15s, color 0.15s;
    border-top: 1px solid var(--fg-border);
  }

  .fg-option:first-child {
    border-top: none;
  }
  
  .fg-dropdown-teleport .fg-option:hover,
  .fg-option:hover {
    background: var(--fg-hover-bg) !important;
    color: var(--fg-accent) !important;
  }
  
  .fg-dropdown-teleport .fg-option.fg-option-focused,
  .fg-option.fg-option-focused {
    background: var(--fg-hover-bg) !important;
    color: var(--fg-accent) !important;
    outline: none;
  }
  
  .fg-option.selected::before {
    /*
    content: '✔';
    color: var(--fg-green);
    font-size: 11px;
    font-weight: 700;
    */
    
    /* Style de la case */
    content: '';
    width: 6px;
    height: 6px;
    background-color: var(--fg-green);
    border-radius: 50%;
    vertical-align: middle;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  
  .fg-dropdown-teleport .fg-option.selected,
  .fg-option.selected {
    background: var(--fg-accent-glow) !important;
    color: var(--fg-accent) !important;
  }
  
  .fg-dropdown-teleport .fg-option.selected.fg-option-focused,
  .fg-option.selected.fg-option-focused {
    background: var(--fg-accent-glow) !important;
    filter: brightness(1.2);
  }
  
  .fg-no-results {
    padding: 14px;
    color: var(--fg-text-muted);
    font-size: 13px;
    text-align: center;
    display: none;
  }
  
  /* Choices (radio/checkbox) */
  .fg-choices {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }
  
  .fg-choices.fg-choices-inline {
    flex-direction: row;
    flex-wrap: wrap;
    gap: 8px;
  }
  
  .fg-choices.fg-choices-inline .fg-choice-item {
    flex: 0 1 auto;
  }
  
  .fg-choice-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    border-radius: var(--fg-radius);
    cursor: pointer;
    transition: background 0.18s;
    position: relative;
    overflow: hidden;
  }

  .fg-choice-item:hover {
    background: var(--fg-hover-bg);
  }
  
  .fg-choice-item input[type='radio'],
  .fg-choice-item input[type='checkbox'] {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
    pointer-events: none;
  }
  
  .fg-choice-indicator {
    width: 20px;
    height: 20px;
    border: 2px solid var(--fg-border);
    background: var(--fg-surface2);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: border-color 0.18s, background 0.18s, box-shadow 0.18s;
  }
  
  .fg-choice-item[data-type='radio'] .fg-choice-indicator {
    border-radius: 50%;
  }
  
  .fg-choice-item[data-type='checkbox'] .fg-choice-indicator {
    border-radius: calc(var(--fg-radius) * 0.5);
  }
  
  .fg-choice-item.checked {
    background: var(--fg-checked-bg);
  }
  
  .fg-choice-item.checked .fg-choice-indicator {
    border-color: var(--fg-accent);
    background: var(--fg-accent);
    box-shadow: 0 0 10px var(--fg-accent-glow);
  }
  
  .fg-choice-item[data-type='radio'].checked .fg-choice-indicator::after {
    content: '';
    width: 6px;
    height: 6px;
    background: var(--fg-bg);
    border-radius: 50%;
  }
  
  .fg-choice-item[data-type='checkbox'].checked .fg-choice-indicator::after {
    content: '';
    width: 10px;
    height: 6px;
    border-left: 2px solid var(--fg-bg);
    border-bottom: 2px solid var(--fg-bg);
    transform: rotate(-45deg) translateY(-1px);
    margin-top: 0;
  }
  
  .fg-choice-label {
    font-size: 13.5px;
    color: var(--fg-text-muted);
    transition: color 0.18s;
    flex: 1;
  }
  
  .fg-choice-item.checked .fg-choice-label {
    color: var(--fg-text);
  }
  
  /* File */
  /* ══════════════════════════════════════════════════════════════════════
     FILE UPLOAD — Refactored v2
     Zone de dépôt + Swiper carousel + cartes fichiers + statut
     ══════════════════════════════════════════════════════════════════════ */

  /* ── Wrapper principal ────────────────────────────────────────────────── */
  .fg-file-wrapper {
    display: flex;
    flex-direction: column;
    gap: 10px;
  }

  /* ── Zone de dépôt ────────────────────────────────────────────────────── */
  .fg-file-zone {
    border: 2px dashed var(--fg-border);
    border-radius: var(--fg-radius);
    background: var(--fg-surface2);
    text-align: center;
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s, transform 0.15s;
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 110px;
  }

  .fg-file-wrapper.multiple .fg-file-zone {
    padding: 22px 20px;
  }

  .fg-file-zone:hover,
  .fg-file-zone.dragover {
    border-color: var(--fg-accent);
    background: var(--fg-hover-bg);
  }

  .fg-file-zone.dragover {
    transform: scale(1.01);
    box-shadow: 0 0 0 3px var(--fg-accent-ring);
  }

  .fg-file-zone input[type='file'] {
    position: absolute;
    inset: 0;
    opacity: 0;
    cursor: pointer;
    z-index: 2;
  }

  .fg-file-icon {
    color: var(--fg-text-muted);
    transition: color 0.2s, transform 0.2s;
    display: block;
    line-height: 1;
  }

  /* Icône SVG issue du cache icons.json (cfg.icon = "svg-icon:<slug>") :
     le SVG généré par _buildSvgElement() ne porte qu'un viewBox, sans
     width/height → dimension explicite requise ici, même principe que
     .fg-choice-icon svg / .fg-option-icon svg / .fg-btn-icon svg. */
  .fg-file-icon svg {
    width: 28px;
    height: 28px;
    display: block;
    flex-shrink: 0;
    pointer-events: none;
  }

  .fg-file-zone:hover .fg-file-icon,
  .fg-file-zone.dragover .fg-file-icon {
    color: var(--fg-accent);
    transform: translateY(-2px);
  }

  .fg-file-hint {
    color: var(--fg-text-muted);
    font-size: 13px;
    line-height: 1.5;
    margin: 0;
  }

  .fg-file-hint strong {
    color: var(--fg-accent);
    font-weight: 500;
    display: block;
    margin-bottom: 2px;
  }

  .fg-file-hint-sub {
    font-size: 11.5px;
    color: var(--fg-text-muted);
    opacity: 0.8;
  }

  /* Chaque partie du hint (taille · formats · maxFiles) sur sa propre
     ligne, sans séparateur. */
  .fg-file-hint-line {
    display: block;
  }
  .fg-file-hint-line + .fg-file-hint-line {
    margin-top: 2px;
  }

  /* ── Barre de statut — sous les deux panels, alignée à droite (LTR) ──── */
  .fg-file-status-bar {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 5px;
    font-size: 11px;
    margin-top: 8px;
    align-self: flex-end;   /* droite en LTR, inversé via RTL ci-dessous */
  }

  .fg-file-status-count {
    color: var(--fg-accent);
    font-weight: 600;
  }

  .fg-file-status-sep {
    color: var(--fg-border);
  }

  .fg-file-status-size {
    color: var(--fg-text-muted);
    font-size: 11px;
  }

  /* ── Conteneur preview global : fond + padding + onglets à l'intérieur ── */
  .fg-file-preview {
    display: flex;
    flex-direction: column;
    gap: 0;
    background: var(--fg-surface);
    border: 1px solid var(--fg-border);
    border-radius: var(--fg-radius);
    padding: 14px;
  }

  /* Mode non-multiple : _buildFile() fusionne .fg-file-wrapper dans
     .fg-file-preview (même nœud, les deux classes cohabitent) pour éviter un
     niveau de wrapper DOM superflu — cf. commentaire "Assemblage final" dans
     form_generator.js. On en profite pour retirer le cadrage visuel (fond +
     bordure + padding + radius hérités de .fg-file-preview ci-dessus), non
     souhaité pour ce mode. Le mode multiple garde deux nœuds distincts
     (.fg-file-wrapper.multiple > .fg-file-preview) : ce sélecteur, qui exige
     les deux classes sur UN SEUL élément, ne peut donc jamais le matcher. */
  .fg-file-preview.fg-file-wrapper {
    background: transparent;
    border: none;
    border-radius: 0;
    padding: 0;
  }

  .fg-file-preview-tabs {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 4px;
    margin-bottom: 14px;
  }

  /* En RTL : inverser l'ordre des onglets (online reste "physiquement" à gauche
     mais apparaît à droite visuellement grâce au row-reverse) */
  .fg-rtl .fg-file-preview-tabs {
    flex-direction: row-reverse;
  }

  .fg-file-tab {
    padding: 5px 13px;
    font-size: 12px;
    font-weight: 500;
    color: var(--fg-text-muted);
    background: transparent;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    transition: color 0.15s, background 0.15s;
    white-space: nowrap;
    line-height: 1.5;
  }

  .fg-file-tab:hover:not(.is-active) {
    color: var(--fg-text);
    background: color-mix(in srgb, var(--fg-border) 60%, transparent);
  }

  .fg-file-tab.is-active {
    color: var(--fg-accent);
    background: color-mix(in srgb, var(--fg-accent) 12%, transparent);
    font-weight: 700;
    border: 1px solid color-mix(in srgb, var(--fg-accent) 25%, transparent);
  }

  /* ── Panel local : flex-column simple, sans fond propre ─────────────── */
  .fg-local-file-preview {
    display: flex;
    flex-direction: column;
    gap: 0;
  }

  /* Panel en ligne */
  .fg-online-file-preview .fg-file-remote-section {
    margin-bottom: 0;
  }

  /* ── État vide du panel "Fichiers en ligne" ──────────────────────────── */
  .fg-online-file-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 120px;
    padding: 32px 16px;
  }

  /* Conteneur interne : badge pill horizontal centré */
  .fg-online-file-empty-inner {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 6px 14px 6px 10px;
    border-radius: 20px;
    background: color-mix(in srgb, #F97316 8%, transparent);
    border: 1px solid color-mix(in srgb, #F97316 22%, transparent);
    transition: background 0.2s;
  }

  /* Icône warning : centrée, taille fixe */
  .fg-online-file-empty-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    line-height: 1;
  }

  .fg-online-file-empty-icon svg {
    display: block;
    filter: drop-shadow(0 1px 2px color-mix(in srgb, #F97316 30%, transparent));
  }

  /* Texte "Aucun fichier" — gris neutre, léger */
  .fg-online-file-empty-label {
    font-size: 12px;
    font-weight: 500;
    color: var(--fg-text-muted);
    letter-spacing: 0.015em;
    white-space: nowrap;
  }

  /* ── Section fichiers distants (loadFiles) ───────────────────────────── */
  .fg-file-remote-section {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-bottom: 12px;
  }

  .fg-file-remote-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
  }

  /* Card distante : légère bordure accentuée pour la distinguer */
  .fg-file-card--remote {
    position: relative;
    outline: 2px solid color-mix(in srgb, var(--fg-accent) 30%, transparent);
    outline-offset: -2px;
  }

  /* ── Swiper distant (section "Fichiers enregistrés") ─────────────────── */
  /* Même architecture que .fg-file-swiper-* mais namespaced -remote-swiper-  */

  .fg-file-remote-swiper-section {
    display: flex;
    flex-direction: column;
    gap: 0;
    position: relative;
    /* Réserve de l'espace en bas pour la pagination */
    padding-bottom: 24px;
    /* Petite marge haute pour respirer sous le badge */
    margin-top: 4px;
  }

  /* Ligne horizontale : prev + swiper + next */
  .fg-file-remote-swiper-row {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 6px;
  }

  /* Conteneur Swiper — flex:1 pour occuper l'espace entre prev/next */
  .fg-file-remote-swiper {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    /* Respiration pour les ombres des cartes */
    padding: 6px 4px;
    margin: -6px -4px;
  }

  /* Slide distante — largeur auto pour respecter itemWidth de la card */
  .fg-file-remote-slide {
    width: auto !important;  /* override Swiper qui force 100% en grid mode */
    height: auto !important;
  }

  /* En mode grid (rows > 1), Swiper force height sur chaque slide.
     On le laisse faire ; on s'assure seulement que la card remplit la slide. */
  .fg-file-remote-slide .fg-file-card {
    width: 100%;
    height: 100%;
  }

  /* ── Boutons nav prev / next (section distante) ──────────────────────── */
  .fg-file-remote-swiper-nav {
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: 1px solid var(--fg-border);
    background: var(--fg-surface);
    color: var(--fg-text-muted);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    padding: 0;
    align-self: center;
    transition: border-color 0.15s, color 0.15s, background 0.15s, box-shadow 0.15s;
  }

  .fg-file-remote-swiper-nav:hover {
    border-color: var(--fg-accent);
    color: var(--fg-accent);
    background: var(--fg-hover-bg);
    box-shadow: 0 2px 8px color-mix(in srgb, var(--fg-accent) 18%, transparent);
  }

  .fg-file-remote-swiper-nav.swiper-button-disabled {
    opacity: 0.3;
    pointer-events: none;
  }

  /* ── Pagination distante — sous la row, centrée, même style que section locale */
  .fg-file-remote-swiper-pagination {
    position: absolute !important;
    bottom: 0 !important;
    left: 0 !important;
    right: 0 !important;
    top: auto !important;
    transform: none !important;
    width: 100% !important;

    display: flex !important;
    justify-content: center;
    align-items: center;
    gap: 4px;
    height: 16px;
  }

  .fg-file-remote-swiper-pagination .swiper-pagination-bullet {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--fg-border);
    opacity: 1;
    transition: background 0.2s, width 0.2s;
    cursor: pointer;
    flex-shrink: 0;
  }

  .fg-file-remote-swiper-pagination .swiper-pagination-bullet-active {
    background: var(--fg-accent);
    width: 16px;
    border-radius: 3px;
  }

  /* ── Section Swiper ───────────────────────────────────────────────────── */
  .fg-file-swiper-section {
    display: flex;
    flex-direction: column;
    gap: 0;
    /* Containing block pour la pagination absolute injectée par Swiper */
    position: relative;
    /* Réserve de l'espace en bas pour la pagination (hauteur bullet + marge) */
    padding-bottom: 22px;
    margin-top: 10px;
  }

  /* Ligne horizontale : bouton prev + conteneur swiper + bouton next */
  .fg-file-swiper-row {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 6px;
  }

  .fg-file-swiper {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    /* Laisser respirer l'ombre des cartes de chaque côté */
    padding: 6px 6px;
    margin: -6px -6px;
    box-sizing: content-box;
  }

  /* Fallback plain scroll (cfg.swiper === false) */
  .fg-file-slides-plain {
    display: flex;
    flex-direction: row;
    gap: 10px;
    overflow-x: auto;
    overflow-y: hidden;
    /* Padding haut/bas pour laisser l'ombre visible, compensé par margin négatif */
    padding: 6px 6px 10px;
    margin: -6px -6px 0;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
  }
  .fg-file-slides-plain .fg-file-slide {
    flex-shrink: 0;
    scroll-snap-align: start;
  }
  .fg-file-slides-plain::-webkit-scrollbar {
    height: 4px;
  }
  .fg-file-slides-plain::-webkit-scrollbar-track {
    background: var(--fg-surface2);
    border-radius: 2px;
  }
  .fg-file-slides-plain::-webkit-scrollbar-thumb {
    background: var(--fg-border);
    border-radius: 2px;
  }
  .fg-file-slides-plain::-webkit-scrollbar-thumb:hover {
    background: var(--fg-accent);
  }

  /* ── Carte fichier — dimensions flexibles ───────────────────────────────── */
  .fg-file-card {
    position: relative;
    border-radius: calc(var(--fg-radius) + 2px);
    border: 1px solid var(--fg-border);
    background: var(--fg-surface2);
    overflow: hidden;
    cursor: default;
    width: 100%;
    animation: _fg-card-in 0.32s cubic-bezier(0.34, 1.56, 0.64, 1) both;
    transition: transform 0.22s cubic-bezier(0.34, 1.56, 0.64, 1),
                box-shadow 0.18s ease,
                border-color 0.18s ease;
    will-change: transform;
  }

  .fg-file-card:hover {
    transform: translateY(-4px) scale(1.03);
    border-color: var(--fg-border-focus);
    box-shadow:
      0 8px 20px rgba(0,0,0,0.12),
      0 0 0 1px var(--fg-accent-ring);
  }

  /* ── Thumbnail — couvre toute la carte ───────────────────────────────── */
  .fg-file-card-thumb {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--fg-surface2);
    overflow: hidden;
  }

  .fg-file-card-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    display: block;
    transition: transform 0.35s ease;
  }

  .fg-file-card:hover .fg-file-card-img {
    transform: scale(1.06);
  }

  .fg-file-card-icon {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    transition: transform 0.25s ease;
  }

  .fg-file-card:hover .fg-file-card-icon {
    transform: scale(1.1);
  }

  .fg-file-card-emoji {
    font-size: 30px;
    line-height: 1;
    filter: drop-shadow(0 2px 4px rgba(0,0,0,0.15));
  }

  .fg-file-card-ext {
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: 0.1em;
    padding: 2px 6px;
    border-radius: 3px;
    background: rgba(0,0,0,0.12);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    opacity: 0.9;
  }

  /* ── Overlay infos — glassmorphism en bas ────────────────────────────── */
  .fg-file-card-info {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 20px 8px 8px;
    /* Dégradé noir en bas pour lisibilité */
    background: linear-gradient(
      to top,
      rgba(0,0,0,0.72) 0%,
      rgba(0,0,0,0.28) 65%,
      transparent 100%
    );
    backdrop-filter: blur(0px);
    -webkit-backdrop-filter: blur(0px);
    display: flex;
    flex-direction: column;
    gap: 1px;
    /* Glisse depuis le bas au survol */
    transform: translateY(4px);
    opacity: 0.82;
    transition: transform 0.25s ease, opacity 0.2s ease;
  }

  .fg-file-card:hover .fg-file-card-info {
    transform: translateY(0);
    opacity: 1;
  }

  .fg-file-card-name {
    font-size: 11px;
    color: #ffffff;
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.3;
    text-shadow: 0 1px 3px rgba(0,0,0,0.5);
  }

  .fg-file-card-size {
    font-size: 9.5px;
    color: rgba(255,255,255,0.7);
    font-weight: 400;
  }

  /* ── Colonne de boutons d'action (top-right de la carte) ────────────── */
  .fg-file-card-actions {
    position: absolute;
    top: 8px;
    right: 8px;
    display: flex;
    flex-direction: column;
    gap: 5px;
    z-index: 20;
  }

  /* Base commune à tous les boutons d'action.
     Taille portée de 24px à 28px (+icônes ci-dessous, mêmes proportions)
     pour une meilleure visibilité et une cible tactile plus confortable —
     28px reste sous la carte (220px par défaut) sans jamais l'écraser. */
  .fg-file-card-btn {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.2);
    background: rgba(0, 0, 0, 0.48);
    color: rgba(255, 255, 255, 0.9);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    padding: 0;
    line-height: 1;
    transition: background 0.15s ease, border-color 0.15s ease,
                transform 0.15s ease, color 0.15s ease;
  }

  /* Icônes (remove/like/view) : dimensions fixées en HTML (10/11/13px,
     cf. _FG_ICON_CLOSE_SVG/_FG_ICON_STAR_SVG/form_generator.js) — surchargées
     ici pour suivre le même ratio d'agrandissement (×1.167) que le bouton,
     sans dupliquer la mise à jour dans les 3 endroits où ce HTML est généré.
     Le viewBox de chaque SVG reste inchangé : l'agrandissement via CSS
     redimensionne le tracé (traits compris) de façon proportionnelle. */
  .fg-file-card-btn svg {
    width: 14px;
    height: 14px;
  }
  .fg-file-card-remove svg {
    width: 12px;
    height: 12px;
  }
  .fg-file-card-like svg {
    width: 13px;
    height: 13px;
  }

  .fg-file-card-btn:hover {
    transform: scale(1.12);
  }

  /* Bouton suppression — rouge au survol */
  .fg-file-card-remove:hover {
    background: rgba(220, 38, 38, 0.9);
    border-color: rgba(220, 38, 38, 0.6);
    color: #fff;
  }

  /* Bouton aperçu (loupe) — bleu au survol
     Ajouté systématiquement quel que soit le type de fichier (image, vidéo,
     mais aussi fichiers bruts : PDF, Office, archives, audio…), visible en
     permanence (pas de dépendance au survol de la card), même gabarit que
     les boutons remove/like. Ouvre GLightbox au clic : aperçu direct pour
     les fichiers prévisualisables (image/vidéo), popup nom + bouton de
     téléchargement pour les fichiers bruts, dont le PDF (cf.
     .fg-download-popup). */
  .fg-file-card-view:hover {
    background: rgba(37, 99, 235, 0.9);
    border-color: rgba(59, 130, 246, 0.6);
    color: #fff;
  }

  /* Bouton téléchargement (flèche) — DÉPRÉCIÉ depuis le refactor "loupe
     unique" (v3.6+) : la card n'affiche plus que le bouton .fg-file-card-view
     (loupe), quel que soit le type de fichier. Le téléchargement réel se
     déclenche désormais uniquement depuis .fg-download-popup-btn, à
     l'intérieur de la popup ouverte par ce même bouton loupe (cf.
     _fgAttachThumbAction / _fgBuildDownloadPopupHtml dans form_generator.js).
     Règle conservée pour compatibilité ascendante avec du HTML/CSS custom
     qui référencerait encore .fg-file-card-download. */
  .fg-file-card-download:hover {
    background: rgba(5, 150, 105, 0.9);
    border-color: rgba(16, 185, 129, 0.6);
    color: #fff;
  }

  /* Bouton primary — étoile, dorée quand actif */
  .fg-file-card-like:hover {
    background: rgba(0, 0, 0, 0.65);
    border-color: rgba(251, 191, 36, 0.6);
    color: rgb(251, 191, 36);
  }

  .fg-file-card-like.is-active {
    background: rgba(245, 158, 11, 0.85);
    border-color: rgba(251, 191, 36, 0.8);
    color: #fff;
  }

  .fg-file-card-like.is-active svg {
    fill: currentColor;
  }

  .fg-file-card-like.is-active:hover {
    background: rgba(217, 119, 6, 0.9);
    border-color: rgba(217, 119, 6, 0.8);
  }

  /* ── Centrage de la slide de téléchargement dans GLightbox ───────────────
     Le contenu 'inline' de GLightbox (.gslide-inline / .ginlined-content)
     n'est centré ni horizontalement ni verticalement par défaut — il
     s'aligne en haut du conteneur de slide. On force ici un centrage
     complet, que la popup soit ouverte seule (preview.lightbox: false,
     cf. _fgOpenSimpleDownloadPopup) ou intercalée comme slide au sein de la
     galerie unifiée, entre deux fichiers image/vidéo navigables et les
     fichiers bruts (dont PDF — cf. _fgOpenGallery). Sélecteurs multiples car
     le nom de classe exact du conteneur direct varie selon la version de
     GLightbox. ────────────────────────────────────────────────────────── */
  .glightbox-container .gslide-inline,
  .glightbox-container .ginlined-content,
  .glightbox-container .gslide-inner-content,
  .glightbox-container .ginner-container {
    display: flex !important;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
  }
  .glightbox-container .gslide-inline:has(.fg-gps-lightbox-slide),
  .glightbox-container .gslide-inline:has(.fg-richtext-lightbox-slide){
    cursor: default !important
  }
  /* La popup GPS / richtext doit occuper TOUT l'espace disponible (le champ
     étant lui-même en `height:100%`, cf. .fg-gps-wrapper-expanded /
     .fg-richtext-wrapper-expanded), et non être centrée comme le contenu de
     la popup de téléchargement ci-dessus (qui, lui, est plus petit que son
     conteneur et a besoin d'être centré). Sans cette exclusion,
     `align-items:center`/`justify-content:center` hérités de la règle
     générale peuvent empêcher le champ de s'étirer pleinement sur toute la
     hauteur réservée (padding-top:60px, cf. glightbox_min.css) — le contenu
     se retrouve alors plus haut que prévu, sous les boutons de contrôle de
     la lightbox au lieu d'en dessous. Sélecteur générique
     `.fg-field-expand-lightbox-slide` : marqueur commun posé sur toute
     slide de ce type (GPS, richtext, et futurs champs "agrandissables"),
     pour ne pas dupliquer cette règle à chaque nouveau champ concerné. */
  .glightbox-container .gslide-inline:has(.fg-field-expand-lightbox-slide),
  .glightbox-container .ginlined-content:has(.fg-field-expand-lightbox-slide),
  .glightbox-container .gslide-inner-content:has(.fg-field-expand-lightbox-slide),
  .glightbox-container .ginner-container:has(.fg-field-expand-lightbox-slide) {
    align-items: stretch !important;
    justify-content: flex-start !important;
  }

  /* ── Curseur normal dans les popups d'agrandissement de champ ────────────
     glightbox_min.css pose `cursor:grab` sur TOUT `.gslide-media` (pensé
     pour les images/vidéos "glisser pour naviguer" de la galerie), sans
     condition sur l'option `draggable`. Or ces popups de champ (GPS,
     richtext, picker d'icônes, …) passent systématiquement `draggable:
     false` à setGLightbox() (cf. _fgOpenGpsExpandPopup et consorts,
     form_generator.js) : le drag est donc déjà désactivé côté librairie,
     mais le curseur "main ouverte" reste affiché malgré tout — trompeur,
     puisqu'il suggère une interaction (glisser) qui n'a plus lieu d'être.
     Sur le champ GPS, ce curseur passait déjà inaperçu car la carte
     Leaflet (et ses contrôles) couvre toute la surface et impose son
     propre curseur par-dessus ; mais sur le picker d'icônes, les espaces
     entre les icônes (gaps de la grille) ne sont couverts par aucun
     élément avec un curseur propre, laissant transparaître ce `grab`
     hérité. Repris ici au niveau générique `.fg-field-expand-lightbox-
     slide` (comme les règles align/justify ci-dessus) pour un rendu
     cohérent sur les trois popups, GPS y compris. */
  .glightbox-container .gslide-media:has(.fg-field-expand-lightbox-slide) {
    cursor: default;
  }

  /* ── Popup GLightbox de téléchargement ──────────────────────────────────
     Contenu injecté par _fgBuildDownloadPopupHtml (type: 'inline'). Affiche
     le nom du fichier et un unique bouton de téléchargement centré ; c'est
     ce bouton, et lui seul, qui déclenche le téléchargement réel. ──────── */
  .fg-download-popup {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 36px 32px;
    min-width: 220px;
    max-width: 320px;
    background: var(--fg-surface, #1f2430);
    border-radius: var(--fg-radius, 10px);
    text-align: center;
  }

  .fg-download-popup-icon {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--fg-surface2, rgba(255,255,255,0.08));
    border: 1px solid var(--fg-border, rgba(255,255,255,0.14));
    margin-bottom: 4px;
  }

  .fg-download-popup-ext {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    color: var(--fg-text-muted, rgba(255,255,255,0.65));
  }

  .fg-download-popup-name {
    font-size: 13.5px;
    font-weight: 600;
    color: var(--fg-text, #fff);
    word-break: break-word;
  }

  .fg-download-popup-size {
    font-size: 11.5px;
    color: var(--fg-text-muted, rgba(255,255,255,0.6));
    margin-top: -6px;
  }

  .fg-download-popup-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
    padding: 9px 18px;
    border-radius: 999px;
    border: none;
    background: var(--fg-accent, #2563eb);
    color: #fff;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s ease, transform 0.15s ease;
  }

  .fg-download-popup-btn:hover {
    background: var(--fg-accent-strong, #1d4ed8);
    transform: translateY(-1px);
  }

  .fg-download-popup-btn:active {
    transform: translateY(0);
  }

  /* ── Animation d'entrée — élastique ──────────────────────────────────── */
  @keyframes _fg-card-in {
    0%   { opacity: 0; transform: scale(0.72) translateY(10px); filter: blur(3px); }
    60%  { opacity: 1; filter: blur(0); }
    100% { opacity: 1; transform: scale(1)    translateY(0);    filter: blur(0);   }
  }

  /* ── Animation de sortie — effet heartbeat (battement de cœur) ─────────
     Phase 1 (0-35%)  : zoom avant  — le cœur se gonfle
     Phase 2 (35-65%) : zoom arrière — le cœur se contracte
     Phase 3 (65-100%): disparition complète avec micro-flou               */
  @keyframes _fg-card-out {
    0%   { opacity: 1; transform: scale(1);    filter: blur(0);    }
    20%  { opacity: 1; transform: scale(1.18); filter: blur(0);    }
    45%  { opacity: 1; transform: scale(0.88); filter: blur(0);    }
    65%  { opacity: 0.6; transform: scale(1.06); filter: blur(0);  }
    100% { opacity: 0; transform: scale(0);    filter: blur(4px);  }
  }

  .fg-file-card--removing {
    animation: _fg-card-out 0.48s cubic-bezier(0.4, 0, 0.6, 1) forwards !important;
    pointer-events: none;
    transform-origin: center center;
  }

  /* ── Mode fichier unique — fg-file-card injecté directement dans
     fg-file-zone (sans Swiper, sans swiper-slide) ───────────────────── */

  .fg-file-zone > .fg-file-card {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: none;
    border-radius: 0;
    margin: 0;
    /* Pas de hover élastique en mode single — la zone est le conteneur */
    transition: border-color 0.18s ease, box-shadow 0.18s ease;
  }

  .fg-file-zone > .fg-file-card:hover {
    transform: none;
    box-shadow: none;
  }

  /* Thumbnail couvre intégralement la zone quelle que soit sa forme */
  .fg-file-zone > .fg-file-card .fg-file-card-thumb {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
  }

  .fg-file-zone > .fg-file-card .fg-file-card-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    display: block;
  }

  /* En mode single la carte couvre toute la zone, on ne change rien aux boutons */

  /* Icône non-image — agrandie pour occuper la zone */
  .fg-file-zone > .fg-file-card .fg-file-card-emoji {
    font-size: 48px;
  }

  .fg-file-zone > .fg-file-card .fg-file-card-ext {
    font-size: 13px;
    padding: 4px 10px;
  }

  /* ── Mode single : infos — comportement identique au mode multiple ───── */
.fg-file-zone > .fg-file-card .fg-file-card-info--single {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 20px 8px 8px;
  background: linear-gradient(
    to top,
    rgba(0,0,0,0.72) 0%,
    rgba(0,0,0,0.28) 65%,
    transparent 100%
  );
  backdrop-filter: blur(0px);
  -webkit-backdrop-filter: blur(0px);
  display: flex;
  flex-direction: column;
  gap: 1px;
  /* Identique au multiple : visible au repos, glisse au survol */
  transform: translateY(4px);
  opacity: 0.82;
  transition: transform 0.25s ease, opacity 0.2s ease;
}

.fg-file-zone > .fg-file-card:hover .fg-file-card-info--single {
  transform: translateY(0);
  opacity: 1;
}

.fg-file-zone > .fg-file-card .fg-file-card-info--single .fg-file-card-name {
  font-size: 11px;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.3;
  text-shadow: 0 1px 3px rgba(0,0,0,0.5);
}

.fg-file-zone > .fg-file-card .fg-file-card-info--single .fg-file-card-size {
  font-size: 9.5px;
  font-weight: 400;
  color: rgba(255,255,255,0.7);
}

/* ── Vidéo (multiple ET single) : infos centrées horizontalement et
   verticalement — toujours visibles (pas de masquage au survol) ──────── */
.fg-file-card:has(.fg-file-card-video) .fg-file-card-info,
.fg-file-zone > .fg-file-card:has(.fg-file-card-video) .fg-file-card-info--single {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: unset;
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 10px 12px;
  transform: none;
  opacity: 0.82;
  transition: opacity 0.25s ease;
  z-index: 10;
  pointer-events: none;
}

.fg-file-card:has(.fg-file-card-video):hover .fg-file-card-info,
.fg-file-zone > .fg-file-card:has(.fg-file-card-video):hover .fg-file-card-info--single {
  opacity: 1;
}
  .fg-file-swiper-nav {
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: 1px solid var(--fg-border);
    background: var(--fg-surface);
    color: var(--fg-text-muted);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: border-color 0.15s, color 0.15s, background 0.15s;
    padding: 0;
    flex-shrink: 0;
    align-self: center;
  }

  .fg-file-swiper-nav:hover {
    border-color: var(--fg-accent);
    color: var(--fg-accent);
    background: var(--fg-hover-bg);
  }

  .fg-file-swiper-nav.swiper-button-disabled {
    opacity: 0.3;
    pointer-events: none;
  }

  /* ── Pagination Swiper — positionnée sous la row nav+slides ─────────── */
  .fg-file-swiper-pagination {
    /* Swiper force position:absolute + bottom:N + left:50% + transform sur .swiper-pagination.
       On exploite ce comportement : la pagination reste absolute MAIS son containing block
       est désormais fg-file-swiper-section (position:relative), pas .swiper-container.
       On la repositionne en bas de la section, centrée horizontalement. */
    position: absolute !important;
    bottom: 0 !important;
    left: 0 !important;
    right: 0 !important;
    top: auto !important;
    transform: none !important;
    width: 100% !important;

    display: flex !important;
    justify-content: center;
    align-items: center;
    gap: 4px;
    height: 14px;
  }

  .fg-file-swiper-pagination .swiper-pagination-bullet {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--fg-border);
    opacity: 1;
    transition: background 0.2s, width 0.2s;
    cursor: pointer;
    flex-shrink: 0;
  }

  .fg-file-swiper-pagination .swiper-pagination-bullet-active {
    background: var(--fg-accent);
    width: 16px;
    border-radius: 3px;
  }

  /* ── Rendu vidéo dans les cards fichier ─────────────────────────────── */
  .fg-file-card-video {
    width: 100%;
    height: 100%;
    display: block;
    border: none;
    border-radius: inherit;
  }

  .fg-file-card-video {
    object-fit: cover;
    background: #000;
    pointer-events: auto; /* indispensable : permet l'interaction avec les contrôles natifs */
    position: relative;
    z-index: 5;           /* passe au-dessus de fg-file-card-info (overlay glassmorphism) */
  }

  /* Quand une card contient une vidéo, désactiver l'overlay info et le hover transform
     pour ne pas bloquer les contrôles natifs du lecteur */
  .fg-file-card:has(.fg-file-card-video) {
    cursor: default;
  }
  .fg-file-card:has(.fg-file-card-video):hover {
    transform: none;
  }

  /* ── Toast erreur ─────────────────────────────────────────────────────── */
  .fg-file-error-toast {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    background: color-mix(in srgb, var(--fg-red) 12%, var(--fg-surface));
    border: 1px solid color-mix(in srgb, var(--fg-red) 35%, var(--fg-border));
    border-radius: var(--fg-radius);
    color: var(--fg-red);
    font-size: 12.5px;
    animation: _fg-fade 0.2s ease;
  }

  /* Ripple — uniquement sur les boutons (submit/button) et les
     éléments cliquables internes (icônes, catégories, captcha, GPS).
     Exclu volontairement des wrappers de champs (toggle, date,
     choice, etc.) pour ne pas perturber leur rendu. */
  .fg-btn.fg-ripple-host,
  .fg-icon-item.fg-ripple-host,
  .fg-icon-cat-btn.fg-ripple-host,
  .fg-captcha-refresh.fg-ripple-host,
  .fg-gps-btn.fg-ripple-host,
  .fg-confirm-popup .fg-ripple-host,
  .fg-dropdown-teleport .fg-option.fg-ripple-host {
    position: relative;
    overflow: hidden;
  }
  
  @keyframes _fg-ripple {
    0% {
      transform: scale(0);
      opacity: 0.5;
    }
    100% {
      transform: scale(4);
      opacity: 0;
    }
  }
  
  .fg-ripple-wave {
    position: absolute;
    border-radius: 50%;
    background: currentColor;
    opacity: 0;
    pointer-events: none;
    transform: scale(0);
    animation: _fg-ripple 0.5s ease-out forwards;
    will-change: transform, opacity;
  }
  
  /* Range */
  .fg-range-wrapper,
  .fg-range-dual-wrapper {
    display: flex;
    align-items: center;
    gap: 14px;
  }

  .fg-range-track,
  .fg-range-dual-track {
    position: relative;
    flex: 1;
    height: 3px;
    background: var(--fg-border);
    border-radius: 99px;
    margin: 14px 0;
  }

  .fg-range-fill,
  .fg-range-dual-fill {
    position: absolute;
    height: 100%;
    background: var(--fg-accent);
    border-radius: 99px;
    pointer-events: none;
  }
  
  .fg-range-input {
    position: absolute;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
    margin: 0;
    top: 0;
    left: 0;
    z-index: 2;
  }

  .fg-range-thumb,
  .fg-range-dual-thumb {
    position: absolute;
    width: 24px;
    height: 24px;
    background: var(--fg-accent);
    border: 9px solid var(--fg-bg);
    border-radius: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    cursor: grab;
    box-shadow: 0 0 12px var(--fg-accent-glow), 0 2px 8px rgba(0, 0, 0, 0.35);
    transition: box-shadow 0.15s, transform 0.1s;
  }
  
  .fg-range-thumb {
    pointer-events: none;
    z-index: 1;
  }
  
  .fg-range-track:hover .fg-range-thumb {
    transform: translate(-50%, -50%) scale(1.1);
  }
  
  .fg-range-counter {
    min-width: 58px;
    text-align: center;
    font-size: 13px;
    font-weight: 500;
    color: var(--fg-accent);
    background: var(--fg-surface2);
    border: 1px solid var(--fg-border);
    border-radius: 6px;
    padding: 5px 8px;
    outline: none;
    transition: border-color 0.15s;
    font-family: var(--fg-font);
  }
  
  .fg-range-counter:focus {
    border-color: var(--fg-border-focus);
    box-shadow: 0 0 0 3px var(--fg-accent-ring);
  }
  
  .fg-range-dual-thumb {
    z-index: 3;
  }
  
  .fg-range-dual-thumb:active {
    cursor: grabbing;
    transform: translate(-50%, -50%) scale(1.15);
  }
  
  .fg-range-dual-thumb:hover {
    transform: translate(-50%, -50%) scale(1.1);
  }

  /* ── Range RTL — thumb ancré à droite, transform X inversé ── */
  .fg-rtl .fg-range-thumb,
  .fg-rtl .fg-range-dual-thumb {
    left: auto;
    transform: translate(50%, -50%);
  }
  .fg-rtl .fg-range-track:hover .fg-range-thumb {
    transform: translate(50%, -50%) scale(1.1);
  }
  .fg-rtl .fg-range-dual-thumb:active {
    transform: translate(50%, -50%) scale(1.15);
  }
  .fg-rtl .fg-range-dual-thumb:hover {
    transform: translate(50%, -50%) scale(1.1);
  }
  .fg-rtl .fg-range-fill,
  .fg-rtl .fg-range-dual-fill {
    left: auto;
  }
  
  .fg-range-counters {
    display: flex;
    align-items: center;
    gap: 6px;
  }
  
  .fg-range-sep {
    font-size: 12px;
    color: var(--fg-text-muted);
  }
  
  /* Double field */
  .fg-double-wrapper {
    display: flex;
    align-items: stretch;
    background: var(--fg-surface2);
    border: 1px solid var(--fg-border);
    border-radius: var(--fg-radius);
    overflow: hidden;
    transition: border-color 0.18s, box-shadow 0.18s;
  }
  
  .fg-double-wrapper:hover:not(:focus-within) {
    border-color: color-mix(in srgb, var(--fg-border) 80%, #000);
    box-shadow: 0 3px 8px rgba(0,0,0,0.08);
  }

  .fg-double-wrapper:focus-within {
    border-color: var(--fg-border-focus);
    box-shadow: 0 0 0 3px var(--fg-accent-ring);
  }
  
  .fg-double-wrapper > .fg-field {
    flex: 1;
    justify-content: center;
    min-width: 0;
    margin-bottom: 0 !important;
  }
  
  .fg-double-wrapper > .fg-field + .fg-field {
    border-left: 1px solid var(--fg-border);
  }

  /* Pas de séparateur quand le second champ est un bouton */
  .fg-double-wrapper > .fg-field:has(.fg-btn) {
    border-left: none;
    padding-left: 8px;
  }
  
  .fg-double-wrapper .fg-input {
    background: transparent;
    border: none !important;
    box-shadow: none !important;
    border-radius: 0 !important;
  }
  
  .fg-double-wrapper .fg-select-trigger {
    background: transparent;
    border: none !important;
    box-shadow: none !important;
    border-radius: 0 !important;
  }
  
  .fg-double-wrapper .fg-select-trigger.open {
    box-shadow: none !important;
  }
  
  .fg-double-wrapper .fg-date-trigger {
    background: transparent;
    border: none !important;
    box-shadow: none !important;
    border-radius: 0 !important;
  }
  
  .fg-double-wrapper .fg-date-trigger.open {
    box-shadow: none !important;
  }
  
  .fg-double-wrapper .fg-number-wrapper {
    border: none !important;
    box-shadow: none !important;
    border-radius: 0 !important;
    background: transparent;
  }
  
  .fg-double-wrapper .fg-number-wrapper:focus-within {
    border: none !important;
    box-shadow: none !important;
  }
  
  .fg-double-wrapper .fg-num-btn {
    background: var(--fg-surface) !important;
  }
  
  .fg-double-wrapper .fg-pwd-wrapper {
    border: none !important;
    box-shadow: none !important;
    border-radius: 0 !important;
    background: transparent;
  }
  
  .fg-double-wrapper .fg-icon-wrapper {
    border: none !important;
    box-shadow: none !important;
    border-radius: 0 !important;
    background: transparent;
  }
  
  .fg-double-wrapper .fg-color-wrapper {
    border: none !important;
    box-shadow: none !important;
    border-radius: 0 !important;
    background: transparent;
  }
  
  .fg-double-fixed {
    flex: 0 0 auto !important;
  }
  
  /* Cascading */
  .fg-cascading-wrapper {
    display: flex;
    flex-direction: column;
    gap: 12px;
  }
  
  /* Toggle - structure commune (switch + texte), partagee par le toggle
     AUTONOME (div.fg-toggle-wrapper, un champ isole) ET chaque OPTION
     d'un groupe (label.fg-toggle-wrapper.fg-toggle-item, cf.
     .fg-toggle-group plus bas) - uniquement les proprietes structurelles
     communes aux deux contextes. L'habillage "carte" (fond, padding,
     hover, focus) est desormais reserve aux options de groupe via
     .fg-toggle-item ci-dessous - le toggle autonome n'en a plus besoin. */
  .fg-toggle-wrapper {
    display: flex;
    align-items: center;
    /* gap fixe (et non justify-content: space-between) : le track reste
       colle a la description quelle que soit la largeur du wrapper - meme
       principe que .fg-choice-item (radio/checkbox), cf. plus haut. */
    gap: 12px;
  }

  /* Toggle autonome (hors groupe) : rendu "inline", pas "bloc" - il ne
     doit pas s'etirer sur toute la largeur du .fg-field englobant
     (flex-direction:column, align-items:stretch par defaut) ni se
     comporter comme un item de liste empile (cf. .fg-toggle-item pour ce
     cas). align-self:flex-start (et non un simple display, qui serait de
     toute facon "blockifie" en tant qu'item flex de .fg-field - cf. specs
     CSS Display) est ce qui produit reellement la largeur "au contenu" ;
     inline-flex conserve neanmoins le bon type de boite pour un usage
     hors flex-item (ex. injecte dans du texte). Plus de fond, de padding,
     ni d'effet hover/focus sur ce conteneur global : voir
     .fg-toggle-track:focus-visible plus bas pour le retour visuel de
     focus, desormais localise sur le switch lui-meme. */
  .fg-toggle-wrapper:not(.fg-toggle-item) {
    display: inline-flex;
    align-self: flex-start;
  }
  
  .fg-toggle-desc {
    font-size: 13px;
    color: var(--fg-text-dim);
    /* flex:1 est correct ICI car .fg-toggle-desc suit desormais le track
       (element fixe, flex-shrink:0) dans l'ordre DOM - meme agencement que
       .fg-choice-label (flex:1) apres .fg-choice-indicator (fixe) pour
       radio/checkbox. Le texte demarre donc immediatement apres le track,
       tout espace superflu se retrouve en fin de ligne (invisible/sans
       consequence), et non plus entre le texte et le track. */
    flex: 1;
  }
  
  .fg-toggle-track {
    position: relative;
    width: 44px;
    height: 24px;
    border-radius: 99px;
    background: var(--fg-border);
    cursor: pointer;
    transition: background 0.25s;
    flex-shrink: 0;
  }
  
  .fg-toggle-track.on {
    background: var(--fg-accent);
  }

  /* Focus clavier localise sur le switch lui-meme (Tab, cf. tabindex="0"
     pose en JS) - remplace l'ancien anneau global porte par
     .fg-toggle-wrapper:focus-within (supprime pour le toggle autonome,
     cf. plus haut). Reste actif pour .fg-toggle-item (groupe) via
     .fg-toggle-item:focus-within, qui prend le relais separement. */
  .fg-toggle-track:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px var(--fg-accent-ring);
  }
  
  .fg-toggle-knob {
    position: absolute;
    top: 3px;
    left: 3px;
    width: 18px;
    height: 18px;
    background: #fff;
    border-radius: 50%;
    transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
  }
  
  .fg-toggle-track.on .fg-toggle-knob {
    transform: translateX(20px);
  }
  
  .fg-toggle-hidden {
    display: none;
  }

  /* ── Groupe de toggles (cfg.options / cfg.endpoint) ────────────────────
     Pendant de .fg-choices pour radio/checkbox : conteneur en colonne avec
     gap, variante inline en ligne avec retour a la ligne (meme regles). */
  .fg-toggle-group {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }

  .fg-toggle-group.fg-toggle-group-inline {
    flex-direction: row;
    flex-wrap: wrap;
    gap: 8px;
  }

  .fg-toggle-group.fg-toggle-group-inline .fg-toggle-item {
    flex: 0 1 auto;
  }

  /* Chaque ligne est un <label> (curseur pointeur sur toute la ligne, texte
     compris - clic natif du navigateur) enveloppant un vrai
     input[type=checkbox] visuellement masque mais toujours focusable au
     clavier (Tab) et lisible par un lecteur d'ecran - c'est lui qui pilote
     .fg-toggle-track via le selecteur :checked ci-dessous, sans JS. */
  .fg-toggle-item {
    cursor: pointer;
    /* Habillage "carte pleine" - propre aux options d'un groupe (liste a
       la radio/checkbox), transfere ici depuis .fg-toggle-wrapper pour que
       le toggle autonome (ci-dessus) ne le porte plus. */
    padding: 12px 14px;
    background: var(--fg-surface2);
    border-radius: var(--fg-radius);
    transition: box-shadow 0.18s;
  }

  .fg-toggle-item:hover:not(:focus-within) {
    box-shadow: 0 3px 8px rgba(0,0,0,0.08);
  }

  .fg-toggle-item:focus-within {
    /* Anneau interne (inset) plutot qu'une bordure : meme convention que
       .fg-icon-preview:focus-visible, coherent sans reintroduire de bordure. */
    box-shadow: inset 0 0 0 2px var(--fg-border-focus);
  }

  .fg-toggle-item input[type="checkbox"] {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }

  .fg-toggle-item input[type="checkbox"]:checked ~ .fg-toggle-track {
    background: var(--fg-accent);
  }

  .fg-toggle-item input[type="checkbox"]:checked ~ .fg-toggle-track .fg-toggle-knob {
    transform: translateX(20px);
  }
  
  /* ===== COLOR PICKER (COLORIS) ===== */
  /* ════════════════════════════════════════════════════
     Color Picker inline — structure unifiée
     DOM : fg-color-wrapper > fg-color-picker-field (clr-field)
                                 button.fg-clr-swatch
                                 input.fg-color-picker-hex
     Règles obsolètes supprimées : fg-color-picker-inline,
     fg-color-picker-field-wrapper (anciens wrappers intermédiaires)
  ════════════════════════════════════════════════════ */

  /* Champ couleur — root du picker, occupe toute la hauteur du wrapper */
  .fg-color-picker-field {
    display: flex;
    align-items: center;
    flex: 1;
    min-width: 0;
    width: 100%;
    height: 100%;
    position: relative;
  }

  /* Pastille couleur — ronde
     ⚠️ Toutes les propriétés de positionnement sont verrouillées en !important.
     Raison : .clrField porte volontairement la classe "clr-field" (réutilisée
     pour hériter du thème visuel Coloris), donc le sélecteur générique
     ".clr-field button" de la feuille de style Coloris cible AUSSI notre
     bouton. Sans ce verrouillage, "position" (jamais déclaré ici auparavant)
     retombait sur la valeur par défaut de Coloris dès que sa feuille de
     style était prise en compte par le moteur de rendu — d'où le décalage
     de la pastille vers la droite après un court délai. En fixant ici
     position/top/left/right/bottom explicitement, plus aucune règle externe
     ne peut reprendre la main, quel que soit l'ordre ou le moment de
     chargement des CSS. */
  .fg-color-picker-field .fg-clr-swatch,
  .clr-field button.fg-clr-swatch {
    position: absolute !important;
    top: 50% !important;
    left: 10px !important;
    right: auto !important;
    bottom: auto !important;
    transform: translateY(-50%) !important;
    margin: 0 !important;
    width: 22px !important;
    height: 22px !important;
    border-radius: 50% !important;
    border: none;
    cursor: pointer;
    background: currentColor;
    flex-shrink: 0;
    z-index: 2;
    transition: transform 0.15s, border-color 0.15s;
  }

  .fg-color-picker-field .fg-clr-swatch:hover,
  .clr-field button.fg-clr-swatch:hover {
    transform: translateY(-50%) scale(1.12) !important;
    border-color: var(--fg-border-focus);
  }

  /* Input hex */
  .fg-color-picker-hex {
    flex: 1;
    min-width: 0;
    width: 100%;
    height: 100%;
    padding-left: 40px;
    padding-right: 12px;
    background: transparent !important;
    border: none !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    outline: none !important;
    color: var(--fg-text);
    font-family: var(--fg-font);
    font-size: 13px;
    text-transform: uppercase;
    box-sizing: border-box;
  }

  /* Wrapper externe du champ couleur standalone */
  .fg-color-wrapper {
    display: flex;
    align-items: stretch;
    background: var(--fg-surface2);
    border: 1px solid var(--fg-border);
    border-radius: var(--fg-radius);
    overflow: visible;
    transition: border-color 0.18s, box-shadow 0.18s;
    position: relative;
    height: var(--fg-field-h);
  }

  .fg-color-wrapper:hover:not(:focus-within) {
    border-color: color-mix(in srgb, var(--fg-border) 80%, #000);
    box-shadow: 0 3px 8px rgba(0,0,0,0.08);
  }

  .fg-color-wrapper:focus-within {
    border-color: var(--fg-border-focus);
    box-shadow: 0 0 0 3px var(--fg-accent-ring);
  }

  /* Palette flottante Coloris
     ⚠️ z-index porté à une valeur maximale (2147483647, le plafond des
     entiers 32 bits signés — convention pour « toujours au-dessus de tout,
     sans exception ») plutôt que 100000 comme auparavant : ce popup est un
     singleton partagé par TOUS les champs couleur de la page (cf.
     commentaires _buildColorPickerInline), y compris ceux qui vivent
     désormais dans une popup GLightbox une fois agrandis (champ icons, cf.
     _fgOpenIconsColorExpandPopup) — or GLightbox (glightbox_min.css) pose
     son propre conteneur à un z-index bien supérieur à 100000. Résultat
     avec l'ancienne valeur : le clic sur la pastille ouvrait bien le picker
     (position/logique correctes), mais celui-ci s'affichait DERRIÈRE la
     modale GLightbox — invisible à l'écran, d'où l'impression qu' « il ne
     se passe rien » au clic. Un singleton de ce type doit systématiquement
     dominer n'importe quel autre calque de la page, quel qu'il soit :
     autant fixer une bonne fois la valeur la plus haute possible plutôt que
     de deviner/traquer le z-index de chaque future popup tierce
     susceptible de l'englober. */
  .clr-picker {
    z-index: 2147483647 !important;
    border-radius: 10px !important;/*var(--fg-radius) !important;*/
    overflow: hidden !important;
    /*box-shadow: var(--fg-shadow) !important;*/
    font-family: var(--fg-font) !important;
  }

  /* Filet de sécurité « picker plus grand que le viewport lui-même » (ex.
     très petit écran mobile) : le recadrage JS (_fgClampColorisToViewport,
     form_generator.js) ne peut que REPOSITIONNER le picker dans les bords
     du viewport, jamais le REDIMENSIONNER — il lui faut donc un picker qui
     ne dépasse structurellement JAMAIS la taille du viewport pour être
     réellement efficace. `overflow-y: auto` (et non `hidden`, qui
     couperait silencieusement le bas du picker) laisse la palette/les
     inputs défiler verticalement plutôt que de disparaître dans ce cas
     limite. La marge de 16px (8px de chaque bord) reprend celle du clamp
     JS (`margin`, cf. sa doc) pour rester visuellement cohérente avec lui. */
  .clr-picker {
    max-width: calc(100vw - 16px) !important;
    max-height: calc(100vh - 16px) !important;
    overflow-y: auto !important;
  }

  /* ── Anti-flash : masquer le picker tant que _repositionPicker() n'a pas
     posé sa position finale (form_generator.js, _buildColorPickerInline) ──
     À l'ouverture, Coloris pose d'abord SA propre position (`position:fixed`,
     calcul basé sur innerWidth/innerHeight — cf. commentaires JS), avant que
     notre correctif ne prenne la main (délai volontaire d'un double rAF pour
     laisser Coloris finir son rendu). Sans ce masquage, l'utilisateur voit la
     popup apparaître au mauvais endroit puis « sauter » à sa position
     correcte — c'est exactement le décalage droite/bas en position
     dynamique. `.fg-clr-positioned` n'est ajoutée qu'une fois top/left
     calculés par notre code, et retirée à chaque fermeture (`coloris:close`)
     pour repartir masqué au prochain open — le picker Coloris étant un
     singleton partagé entre tous les champs couleur de la page. */
  .clr-picker {
    opacity: 0;
    pointer-events: none;
  }
  .clr-picker.fg-clr-positioned {
    opacity: 1;
    pointer-events: auto;
  }

  .clr-picker input[type="text"] {
    font-family: var(--fg-font) !important;
    font-size: 13px !important;
  }

  .clr-picker.clr-pill {
    width: 330px !important;
    padding-left: 150px !important;
    border: 1px solid #c4c6cb !important;
  }

  .clr-picker.clr-pill .clr-gradient {
    width: 130px !important;
    padding-left: 153px !important;
  }
  
  .fg-color-swatch-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 46px;
    flex-shrink: 0;
    cursor: pointer;
    border: none;
    outline: none;
    background: transparent;
    border-right: 1px solid var(--fg-border);
    padding: 0 10px;
    transition: opacity 0.15s;
    position: relative;
  }
  
  .fg-color-swatch-btn:hover {
    opacity: 0.85;
  }
  
  .fg-color-swatch-circle {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: 2px solid rgba(255, 255, 255, 0.25);
    flex-shrink: 0;
    pointer-events: none;
  }
  
  .fg-color-native {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
    pointer-events: none;
  }
  
  .fg-color-hex {
    flex: 1;
    border: none !important;
    box-shadow: none !important;
    background: transparent !important;
    border-radius: 0 !important;
  }
  
  /* --- Champ de recherche avec icônes --- */
  .fg-search-field-wrapper {
    position: relative;
    display: flex;
    align-items: center;
    width: 100%;
  }
  
  .fg-search-field-wrapper.fg-search-focused .fg-search-icon {
    color: var(--fg-accent);
  }

  /* ── fg-input-wrapper : enveloppe l'input standard pour y loger le bouton copier ── */
  .fg-input-wrapper {
    position: relative;
    display: flex;
    align-items: stretch;
    width: 100%;
  }

  /* L'input à l'intérieur garde toute sa hauteur */
  .fg-input-wrapper .fg-input {
    flex: 1;
    min-width: 0;
    padding-right: 34px; /* réserve la place du bouton copier */
  }

  /* ── Bouton copier ── */
  .fg-copy-btn {
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    width: 26px;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: var(--fg-text-muted, #6b7280);
    cursor: pointer;
    padding: 0;
    opacity: 1;
    transition: opacity 0.15s, background 0.15s, color 0.15s;
    z-index: 2;
  }
  /*
  .fg-textarea-wrapper .fg-copy-btn,
  .fg-richtext-wrapper .fg-copy-btn {
    top: 8px;
    transform: none;
  }
  */

  /* Caché quand le champ est focus */
  .fg-input-focused .fg-copy-btn,
  .fg-input-wrapper:has(.fg-input:focus) .fg-copy-btn {
    opacity: 0;
    pointer-events: none;
  }

  .fg-copy-btn:hover {
    background: var(--fg-hover-bg);
    color: var(--fg-accent);
  }

  /* Feedback succès (coche verte) */
  .fg-copy-btn.fg-copy-done {
    color: var(--fg-green, #22d3a3);
  }

  /* Dans fg-icon-wrapper / fg-icon-body — même positionnement */
  .fg-icon-body .fg-copy-btn {
    right: 8px;
  }

  /* Caché quand fg-icon-wrapper est focused */
  .fg-icon-wrapper.fg-input-focused .fg-copy-btn {
    opacity: 0;
    pointer-events: none;
  }
  
  
  /* GPS */
  /* Animation de rotation */
  @keyframes fg-spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
  }
  /* Animation combinée : rotation continue + fondu alterné */
  @keyframes fg-spin-fade {
    0% {
      transform: rotate(0deg);
      opacity: 1;
    }
    50% {
      transform: rotate(180deg);
      opacity: 0.4;
    }
    100% {
      transform: rotate(360deg);
      opacity: 1;
    }
  }
  .fg-gps-btn.spinning svg {
    animation: fg-spin-fade 2s ease-in-out infinite;
  }
  .fg-gps-btn.spinning {
    cursor: wait;
  }
  
  /* Disposition Grid — le nombre de colonnes "bouton" dépend du nombre de
     boutons réellement rendus (cf. cfg.showLocateBtn / cfg.showExpandBtn et
     la classe fg-gps-controls-row--btns-N posée par _buildGPS) : évite une
     colonne vide/mal proportionnée quand l'un des deux boutons — ou les
     deux — est désactivé. */
  .fg-gps-controls-row {
    display: grid;
    gap: 8px;
    align-items: stretch;
    height: var(--fg-field-h);
    width: 100%;
  }
  /* 2 boutons (comportement historique, par défaut) */
  .fg-gps-controls-row--btns-2 {
    grid-template-columns: 5fr 2fr 2fr auto var(--fg-field-h) var(--fg-field-h);
  }
  /* 1 seul bouton (locate OU expand, peu importe lequel) */
  .fg-gps-controls-row--btns-1 {
    grid-template-columns: 5fr 2fr 2fr auto var(--fg-field-h);
  }
  /* Aucun bouton — recherche + coordonnées seules, pas de séparateur */
  .fg-gps-controls-row--btns-0 {
    grid-template-columns: 5fr 2fr 2fr;
  }
  /* Sous-groupe [Lat][Lng][|][LocBtn][ExpandBtn] (cf. _buildGPS,
     form_generator.js). Au dessus de 700px il reste "transparent" pour la
     grille parente : ses enfants continuent d'occuper directement les
     colonnes 2/3/4/5/6 de .fg-gps-controls-row--btns-N, donc AUCUN
     changement visuel par rapport au comportement historique ici. Le
     reflow en une ligne horizontale propre au mobile est défini dans le
     @media (max-width: 700px) plus bas. */
  .fg-gps-coords-group {
    display: contents;
  }
  .fg-gps-search-container {
    position: relative;
    display: flex;
    align-items: stretch;
    min-width: 0;
  }
  .fg-gps-coord-input {
    height: 100%;
    padding: 0 8px;
    box-sizing: border-box;
    min-width: 0;
  }
  .fg-gps-separator {
    width: 1px;
    background: var(--fg-border);
    margin: 0 4px;
    align-self: stretch;
  }
  .fg-gps-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    background: var(--fg-accent);
    color: #fff;
    border: none;
    border-radius: var(--fg-radius);
    padding: 0;
    cursor: pointer;
    box-shadow: 0 2px 8px var(--fg-accent-glow);
    box-sizing: border-box;
  }
  .fg-gps-btn svg {
    color: #fff;
    stroke: #fff;
    stroke-width: 2.2;
  }
  .fg-gps-btn:hover {
    opacity: 0.9;
    background: var(--fg-accent);
  }
  .fg-gps-btn:hover svg {
    color: #fff !important;
    stroke: #fff !important;
  }

  /* Bouton "Agrandir" (.fg-gps-expand-btn) — variante visuellement distincte
     du bouton "Me localiser" : celui-ci MODIFIE la valeur du champ (déplace
     le marqueur), tandis qu'agrandir n'est qu'une action d'affichage. Même
     teinte (--fg-accent) pour rester dans la palette du thème actif, mais en
     "outline" tonique (fond légèrement teinté + contour) au lieu du
     remplissage plein utilisé pour l'action principale — cohérent dans les
     6 thèmes intégrés sans avoir à leur ajouter une variable dédiée. */
  .fg-gps-btn.fg-gps-expand-btn {
    background: color-mix(in srgb, var(--fg-accent) 12%, var(--fg-surface));
    color: var(--fg-accent);
    border: 1px solid color-mix(in srgb, var(--fg-accent) 40%, var(--fg-border));
    box-shadow: none;
  }
  .fg-gps-btn.fg-gps-expand-btn svg {
    color: var(--fg-accent);
    stroke: var(--fg-accent);
  }
  .fg-gps-btn.fg-gps-expand-btn:hover {
    opacity: 1;
    background: color-mix(in srgb, var(--fg-accent) 22%, var(--fg-surface));
  }
  .fg-gps-btn.fg-gps-expand-btn:hover svg {
    color: var(--fg-accent) !important;
    stroke: var(--fg-accent) !important;
  }

  /* Le CSS de l'option `inlineFull` (.glightbox-container.glightbox-inline-
     full ...) a été déplacé dans glightbox_min.css : purement générique et
     indépendant de .fg-form/.fg-gps-*, il doit vivre à côté du reste du
     CSS de la librairie plutôt que dans la feuille de style du widget
     formulaire — cf. glightbox_min.css (section ajoutée en fin de fichier)
     et plugins/glightbox.js (glightboxParams()/setGLightbox()) pour le
     détail complet. */

  /* ── Popup d'agrandissement du champ GPS (GLightbox) ──────────────────────
     Le nœud .fg-gps-wrapper est physiquement déplacé dans la popup (cf.
     _fgOpenGpsExpandPopup, form_generator.js) : ces règles ne s'appliquent
     donc qu'à l'état temporaire "agrandi", identifié par la classe
     .fg-gps-wrapper-expanded ajoutée/retirée par cette même fonction. */
  /* ── Popup d'agrandissement (champs "téléportés" : GPS, richtext,
     picker d'icônes, …) ─────────────────────────────────────────────────
     Le nœud du champ concerné (.fg-gps-wrapper, .fg-richtext-wrapper,
     .fg-icons-picker-wrapper, …) est physiquement déplacé dans la popup
     (cf. _fgOpenGpsExpandPopup / _fgOpenRichtextExpandPopup /
     _fgOpenIconsColorExpandPopup, form_generator.js) : ces règles de
     structure/centrage sont écrites UNE SEULE FOIS via les classes
     génériques .fg-field-expand-lightbox-slide/-slot, posées par CHAQUE
     champ agrandissable en plus de sa propre classe spécifique — évite de
     dupliquer ce bloc à chaque nouveau champ "agrandissable" ajouté. */
  /* padding-top : espace réservé pour ne pas être recouvert par les
     boutons de contrôle GLightbox (fermer / plein écran), positionnés en
     haut de la popup. Cette réserve est déjà fournie par glightbox_min.css
     (padding-top:60px sur .gslide-inline, un ANCÊTRE de cette classe) — et
     elle fonctionne correctement sur desktop, donc on n'y touche pas ici :
     laisser le `padding: 4px` (raccourci ci-dessous) suffit, comme avant.
     Erreur du correctif précédent : un `padding-top: 60px` avait été ajouté
     directement sur CETTE classe, en plus de celui de l'ancêtre — les deux
     s'additionnaient (60 + 60 = 120px constatés), au lieu du second de
     compléter le premier. Corrigé ci-dessous : le rappel ne s'applique
     plus qu'en supplément, uniquement sous 700px (cf. media query),
     là où le rendu observé (capture d'écran) montrait un léger
     chevauchement — pas en base, où l'ancêtre suffit déjà seul. */
  .fg-field-expand-lightbox-slide {
    display: flex;
    width: 100%;
    height: 100%;
    box-sizing: border-box;
    padding: 4px;
  }
  /* Tablette/smartphone : les boutons GLightbox (touch, donc plus grands)
     débordent légèrement de la réserve de 60px de l'ancêtre — un
     complément mesuré sur la capture d'écran (~15-20px de chevauchement),
     pas une seconde réserve complète, suffit à les dégager. */
  @media (max-width: 700px) {
    .fg-field-expand-lightbox-slide {
      padding-top: 24px;
    }
  }
  .fg-field-expand-lightbox-slot {
    display: flex;
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
  }
  .fg-gps-wrapper.fg-gps-wrapper-expanded {
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
  }
  /* Filet de sécurité CSS : le bouton "Agrandir" n'a pas de sens une fois
     le champ déjà agrandi dans la popup qu'il a lui-même ouverte. Masqué
     en JS dès l'ouverture (cf. _fgSetGpsExpandBtnVisible dans
     form_generator.js, qui recalcule aussi le nombre de colonnes de
     .fg-gps-controls-row) ; cette règle ne fait que garantir qu'il reste
     invisible même si le JS n'a pas encore tourné. */
  .fg-gps-wrapper.fg-gps-wrapper-expanded .fg-gps-expand-btn {
    display: none;
  }
  /* La carte occupe tout l'espace restant sous la rangée de contrôles,
     au lieu de sa hauteur fixe habituelle (240px, cf. règle .fg-gps-map
     de base) — c'est tout l'intérêt de l'agrandissement. */
  .fg-gps-wrapper.fg-gps-wrapper-expanded .fg-gps-map {
    flex: 1 1 auto;
    height: auto;
    min-height: 0;
  }
  /* La rangée de contrôles garde EXACTEMENT les mêmes proportions
     (5fr/2fr/2fr + boutons) que hors popup, mais occupe désormais toute la
     largeur disponible (comme hors popup) plutôt que d'être bornée à
     900px : sur une popup pleine largeur (100vw), la borner artificiellement
     créait un vide inutile de part et d'autre, alors que le champ hors
     popup, lui, s'étire bord à bord dans son conteneur. */
  .fg-gps-wrapper.fg-gps-wrapper-expanded .fg-gps-controls-row {
    flex: 0 0 auto;
    width: 100%;
  }

  /* ── Etat "agrandi" du champ richtext (popup GLightbox) ──────────────────
     Même principe que .fg-gps-wrapper-expanded ci-dessus, appliqué à
     l'éditeur Quill : la toolbar garde sa hauteur naturelle (flex:0 0 auto),
     l'éditeur (.ql-container/.ql-editor) occupe tout l'espace vertical
     restant au lieu de sa min-height fixe habituelle (120px, cf. règle
     .ql-editor de base) — c'est tout l'intérêt de l'agrandissement : une
     grande zone de saisie confortable plutôt qu'un popup à moitié vide. */
  .fg-richtext-wrapper.fg-richtext-wrapper-expanded {
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
  }
  /* Filet de sécurité CSS, même principe que .fg-gps-expand-btn ci-dessus :
     le bouton "Agrandir" n'a pas de sens une fois le champ déjà agrandi
     dans la popup qu'il a lui-même ouverte. Masqué en JS dès l'ouverture
     (cf. _fgSetRichtextExpandBtnVisible) ; cette règle ne fait que garantir
     qu'il reste invisible même si le JS n'a pas encore tourné. */
  .fg-richtext-wrapper.fg-richtext-wrapper-expanded .fg-richtext-expand-btn {
    display: none;
  }
  .fg-richtext-wrapper.fg-richtext-wrapper-expanded .ql-toolbar {
    flex: 0 0 auto;
  }
  .fg-richtext-wrapper.fg-richtext-wrapper-expanded .ql-container {
    flex: 1 1 auto;
    min-height: 0;
  }
  .fg-richtext-wrapper.fg-richtext-wrapper-expanded .ql-editor {
    height: 100%;
    min-height: 0;
  }

  /* ── Etat "agrandi" du champ icons (popup GLightbox) ─────────────────────
     Même principe que .fg-gps-wrapper-expanded/.fg-richtext-wrapper-
     expanded ci-dessus : le picker occupe toute la hauteur de la popup en
     colonne flex, header (recherche + couleur) et swiper de catégories
     gardent leur hauteur naturelle (flex:0 0 auto), la grille d'icônes
     occupe tout l'espace vertical restant au lieu de sa max-height fixe
     habituelle (240px, cf. .fg-icons-inline-grid) — c'est tout l'intérêt de
     l'agrandissement : une grille confortable pour parcourir/sélectionner
     une icône au doigt plutôt qu'une popup à moitié vide autour d'un
     color-picker isolé. */
  .fg-icons-picker-wrapper.fg-icons-picker-wrapper-expanded {
    display: flex;
    flex-direction: column;
    box-sizing: border-box;
    width: 100%;
    height: 100%;
    border: 1px solid var(--fg-border);
    border-radius: var(--fg-radius);
  }
  /* Filet de sécurité CSS, même principe que .fg-gps-expand-btn/.fg-
     richtext-expand-btn ci-dessus : le bouton "Agrandir" n'a pas de sens
     une fois le champ déjà agrandi dans la popup qu'il a lui-même ouverte.
     Masqué en JS dès l'ouverture (cf. _fgSetIconsColorExpandBtnVisible) ;
     cette règle ne fait que garantir qu'il reste invisible même si le JS
     n'a pas encore tourné. */
  .fg-icons-picker-wrapper.fg-icons-picker-wrapper-expanded .fg-icons-color-expand-btn {
    display: none;
  }
  .fg-icons-picker-wrapper.fg-icons-picker-wrapper-expanded .fg-icons-picker-header {
    flex: 0 0 auto;
  }
  .fg-icons-picker-wrapper.fg-icons-picker-wrapper-expanded .fg-icon-swiper-section {
    flex: 0 0 auto;
  }
  .fg-icons-picker-wrapper.fg-icons-picker-wrapper-expanded .fg-icon-grid-container.fg-icons-inline-grid {
    flex: 1 1 auto;
    max-height: none;
    height: auto;
    min-height: 0;
  }
  /* Le color-picker lui-même profite aussi du surcroît d'espace du header
     agrandi : légèrement plus large et plus confortable au doigt que sa
     largeur compacte habituelle (130px, cf. .fg-icons-color-field), sans
     pour autant s'étirer de façon disproportionnée — plafonné à 200px
     (flex-grow:0) mais RÉTRÉCISSABLE (flex-shrink:1, plancher 84px,
     identique à l'ancien plancher mobile) si la popup GLightbox n'est pas
     assez large pour loger recherche + couleur à leur taille confortable.
     Un flex-shrink:0 ici (comme dans une version antérieure) rendait la
     couleur totalement rigide : elle gagnait alors mécaniquement en
     spécificité sur l'ancienne règle mobile (@640px) et ne rétrécissait
     plus jamais, forçant TOUT le manque de place sur la recherche
     seule — au point que la recherche finissait plus étroite que la
     couleur sur les popups pas assez larges (bug corrigé ici). */
  .fg-icons-picker-wrapper.fg-icons-picker-wrapper-expanded .fg-icons-color-field {
    flex: 0 1 200px;
    min-width: 84px;
  }
  /* Le champ recherche doit rester visuellement le plus large des deux
     (c'est lui l'élément principal de ce header, la couleur n'étant qu'un
     réglage secondaire) : flex-basis 260px (supérieur aux 200px de la
     couleur) + flex-shrink identique à la couleur (1), donc les deux se
     compressent ENSEMBLE à l'étroit plutôt que la couleur ne cède jamais —
     l'écart de base (260 vs 200) et les planchers respectifs (140px contre
     84px) garantissent que la recherche reste plus large que la couleur à
     toute largeur de popup, jusqu'au seuil où les deux passent en colonne
     (cf. flex-wrap sur le header, contraint en nowrap sous 640px, cf.
     media query plus bas). */
  .fg-icons-picker-wrapper.fg-icons-picker-wrapper-expanded .fg-icons-picker-header .fg-search-field-wrapper {
    flex: 1 1 260px;
    min-width: 140px;
  }

  /* ── Etat "agrandi" du dropdown icônes (popup GLightbox) ─────────────────
     Même principe que .fg-icons-picker-wrapper-expanded ci-dessus, appliqué
     au dropdown téléporté cette fois (cf. _fgOpenIconDropdownExpandPopup,
     form_generator.js) : le dropdown occupe toute la hauteur de la popup,
     header (recherche + couleur + bouton Agrandir) et swiper de catégories
     gardent leur hauteur naturelle — déjà garanti par la disposition en
     colonne de base de .fg-icon-dropdown (display:flex; flex-direction:
     column), seule la grille profite du surcroît d'espace vertical au lieu
     de sa max-height fixe habituelle (240px, cf. .fg-icon-grid-container)
     — c'est tout l'intérêt de l'agrandissement : une grille confortable
     pour parcourir/sélectionner une icône au doigt plutôt qu'un dropdown
     compact calé sous son champ déclencheur. */
  .fg-icon-dropdown.fg-icon-dropdown-expanded {
    width: 100%;
    height: 100%;
    max-width: none;
    box-sizing: border-box;
  }
  /* Filet de sécurité CSS, même principe que les autres boutons "Agrandir"
     ci-dessus : sans objet une fois le dropdown déjà agrandi dans la popup
     qu'il a lui-même ouverte. Masqué en JS dès l'ouverture (cf.
     _fgOpenIconDropdownExpandPopup) ; cette règle garantit qu'il reste
     invisible même si le JS n'a pas encore tourné. */
  .fg-icon-dropdown.fg-icon-dropdown-expanded .fg-icon-dropdown-expand-btn {
    display: none;
  }
  .fg-icon-dropdown.fg-icon-dropdown-expanded .fg-icon-dropdown-header,
  .fg-icon-dropdown.fg-icon-dropdown-expanded .fg-icon-categories {
    flex: 0 0 auto;
  }
  .fg-icon-dropdown.fg-icon-dropdown-expanded .fg-icon-grid-container {
    flex: 1 1 auto;
    max-height: none;
    height: auto;
    min-height: 0;
  }
  /* Correctif : le champ couleur du dropdown restait à sa largeur compacte
     (130px, cf. .fg-icon-color-row) une fois agrandi dans la popup
     GLightbox, alors que son équivalent du picker inline profite bien du
     surcroît d'espace pour passer à 200px (cf.
     .fg-icons-picker-wrapper-expanded .fg-icons-color-field ci-dessus).
     Règle symétrique, jusqu'ici absente, pour un comportement identique
     entre les deux popups GLightbox (inline agrandi / dropdown agrandi).
     flex-shrink:1 + plancher 84px (et non flex-shrink:0, rigide) : sur une
     popup pas assez large, la couleur doit pouvoir rétrécir comme la
     recherche, sans quoi elle devient plus large qu'elle une fois celle-ci
     comprimée en dessous (même bug, même correctif que pour le picker
     inline ci-dessus). */
  .fg-icon-dropdown.fg-icon-dropdown-expanded .fg-icon-color-row {
    flex: 0 1 200px;
    min-width: 84px;
  }
  /* Même garantie que pour le picker inline ci-dessus : le champ recherche
     doit rester le plus large des deux à toute largeur de popup — basis
     260px (> 200px de la couleur) et plancher 140px (> 84px de la
     couleur), les deux champs se compressant ensemble proportionnellement
     plutôt que la couleur ne cède jamais la place. */
  .fg-icon-dropdown.fg-icon-dropdown-expanded .fg-icon-dropdown-header .fg-icon-search-container {
    flex: 1 1 260px;
    min-width: 140px;
  }

  /* Masque les flèches de navigation "Suivant"/"Précédent" de GLightbox
     (.gnext/.gprev) spécifiquement pour les popups d'agrandissement de
     champ (GPS, richtext, …) : ces popups n'affichent jamais qu'une seule
     "slide" (le champ lui-même, cf. _fgOpenGpsExpandPopup /
     _fgOpenRichtextExpandPopup), donc naviguer n'a aucun sens.
     GLightbox pose déjà la classe .glightbox-button-hidden sur .gnext/
     .gprev quand il n'y a qu'un seul élément, mais celle-ci est
     malheureusement écrasée par la règle générique `.gclose,.gnext,.gprev
     {display:flex}` plus loin dans glightbox_min.css (même spécificité,
     déclarée après) : on la renforce donc ici, scoping via :has() sur le
     conteneur de la modale pour ne PAS impacter les autres popups
     GLightbox du formulaire (galerie de fichiers, PDF…), qui ont
     légitimement besoin de cette navigation avec plusieurs éléments. */
  .glightbox-container:has(.fg-field-expand-lightbox-slide) .gnext,
  .glightbox-container:has(.fg-field-expand-lightbox-slide) .gprev {
    display: none !important;
  }

  /* ── Centrage horizontal des boutons GLightbox de la popup GPS ──────────
     Par défaut (cf. règles .glightbox-clean .gclose / .glightbox-toolbar-
     extra plus haut, et leurs miroirs .glightbox-rtl plus bas dans ce
     fichier), ces boutons restent ancrés dans un coin (haut-droite en LTR,
     haut-gauche en RTL). Pour LA POPUP GPS spécifiquement — seule slide
     affichée, showRotation/showZoom/showCounter désactivés dans
     _fgOpenGpsExpandPopup, donc au plus deux boutons possibles ici
     (.gclose + éventuellement .glightbox-toolbar-extra pour le plein
     écran) — on les recentre en haut, dans les deux sens de lecture.

     Écart entre les deux boutons piloté par une variable plutôt que codé
     en dur deux fois : reprend l'écart RÉEL déjà produit par les offsets
     existants (10px du breakpoint par défaut jusqu'à ≥992px, 3px en
     dessous de 399px — cf. media query plus bas), pour un rendu identique
     à un simple recentrage de la disposition actuelle plutôt qu'une
     disposition inédite. Largeur de bouton (35px, skin 'clean') également
     en variable pour ne pas répéter le calcul.

     Deux cas de figure gérés via :has(), sans dépendre du JS :
       1. .glightbox-toolbar-extra absent (cfg.showExpandFullscreen: false,
          ou Fullscreen API indisponible) → .gclose seul, centré via
          transform (pas de calcul de demi-groupe).
       2. .glightbox-toolbar-extra présent → chaque bouton positionné à sa
          moitié du groupe centré, dans l'ordre déjà en vigueur de chaque
          côté (LTR : plein écran puis fermeture ; RTL : fermeture puis
          plein écran, symétrique du correctif RTL de la toolbar plus bas)
          — seul l'ancrage change (centre au lieu d'un coin), l'ordre
          relatif entre les deux boutons reste inchangé. */
  .glightbox-container:has(.fg-field-expand-lightbox-slide) {
    --fg-expand-glb-btn: 35px;
    --fg-expand-glb-gap: 10px;
  }
  @media (max-width: 399px) {
    .glightbox-container:has(.fg-field-expand-lightbox-slide) {
      --fg-expand-glb-gap: 3px;
    }
  }

  .glightbox-container:has(.fg-field-expand-lightbox-slide):not(:has(.glightbox-toolbar-extra)) .gclose {
    right: auto;
    left: 50%;
    transform: translateX(-50%);
  }

  .glightbox-container:has(.fg-field-expand-lightbox-slide):has(.glightbox-toolbar-extra) .glightbox-toolbar-extra {
    right: auto;
    left: calc(50% - var(--fg-expand-glb-btn) - (var(--fg-expand-glb-gap) / 2));
  }
  .glightbox-container:has(.fg-field-expand-lightbox-slide):has(.glightbox-toolbar-extra) .gclose {
    right: auto;
    left: calc(50% + (var(--fg-expand-glb-gap) / 2));
  }
  /* RTL : ordre inversé (fermeture désormais la plus proche du centre-gauche,
     plein écran la plus proche du centre-droit) — même principe que le
     correctif RTL général de .glightbox-toolbar-extra, appliqué ici au
     groupe centré plutôt qu'à un ancrage de coin. */
  .glightbox-container.glightbox-rtl:has(.fg-field-expand-lightbox-slide):has(.glightbox-toolbar-extra) .gclose {
    left: calc(50% - var(--fg-expand-glb-btn) - (var(--fg-expand-glb-gap) / 2));
  }
  .glightbox-container.glightbox-rtl:has(.fg-field-expand-lightbox-slide):has(.glightbox-toolbar-extra) .glightbox-toolbar-extra {
    left: calc(50% + (var(--fg-expand-glb-gap) / 2));
  }

  /* Autocomplétion Leaflet */
  .fg-gps-autocomplete {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--fg-dropdown-bg);
    border: 1px solid var(--fg-border-focus);
    border-top: none;
    border-radius: 0 0 var(--fg-radius) var(--fg-radius);
    z-index: 1000;
    max-height: 200px;
    overflow-y: auto;
    display: none;
    box-shadow: var(--fg-shadow);
    box-sizing: border-box;
  }
  .fg-gps-autocomplete.open { display: block; }
  .fg-gps-autocomplete-item {
    padding: 10px 14px;
    cursor: pointer;
    font-size: 13px;
    color: var(--fg-text-dim);
    border-bottom: 1px solid var(--fg-border);
    background: var(--fg-dropdown-bg);
    transition: background 0.12s, color 0.12s;
  }
  .fg-gps-autocomplete-item:last-child { border-bottom: none; }
  .fg-gps-autocomplete-item:hover,
  .fg-gps-autocomplete-item.focused {
    background: var(--fg-hover-bg);
    color: var(--fg-accent);
  }
  
  /* Icône de recherche centrée verticalement */
  .fg-search-icon {
    position: absolute;
    left: 12px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--fg-text-muted);
    pointer-events: none;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: color 0.15s;
    z-index: 1;
  }
  
  /* Mobile — le champ d'adresse occupe sa propre ligne pleine largeur, et le
     sous-groupe [Lat][Lng][LocBtn][ExpandBtn] (.fg-gps-coords-group) passe
     d'un mode "transparent" (display:contents, cf. règle desktop ci-dessus)
     à une rangée flex à part entière, affichée sur UNE SEULE ligne
     horizontale juste en dessous de l'adresse. */
  @media (max-width: 700px) {
    .fg-gps-controls-row {
      display: flex;
      flex-direction: column;
      grid-template-columns: none;
      height: auto;
      gap: 8px;
    }
    .fg-gps-search-container {
      height: var(--fg-field-h);
      width: 100%;
    }
    /* Le groupe redevient un vrai conteneur flex (il n'est plus "contents")
       pour porter lui-même la disposition en ligne de ses enfants. En RTL,
       aucune règle flex-direction dédiée n'est nécessaire : .fg-rtl pose déjà
       direction:rtl sur .fg-gps-wrapper (cf. plus bas), ce qui suffit à
       inverser naturellement l'ordre visuel d'un flex-row. */
    .fg-gps-coords-group {
      display: flex;
      flex-direction: row;
      align-items: stretch;
      gap: 8px;
      width: 100%;
      height: var(--fg-field-h);
    }
    /* Lat/Lng se partagent l'espace restant à parts égales une fois les
       boutons carrés déduits (cf. .fg-gps-btn ci-dessous). */
    .fg-gps-coord-input {
      flex: 1 1 0;
      min-width: 0;
      height: 100%;
      width: auto;
    }
    /* Boutons carrés de côté fixe (var(--fg-field-h)), ils ne rétrécissent
       pas au profit de lat/lng — cohérent avec leur rendu desktop. */
    .fg-gps-btn {
      flex: 0 0 var(--fg-field-h);
      width: var(--fg-field-h);
      height: 100%;
    }
    .fg-gps-separator {
      display: none;
    }
  }
  
  /* Date picker */
  .fg-date-wrapper {
    position: relative;
  }
  
  .fg-date-trigger {
    background: var(--fg-surface2);
    border: 1px solid var(--fg-border);
    border-radius: var(--fg-radius);
    color: var(--fg-text);
    font-family: var(--fg-font);
    font-size: 14px;
    padding: 11px 14px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    transition: border-color 0.18s, box-shadow 0.18s;
    user-select: none;
  }
  
  .fg-date-trigger:hover:not(.open) {
    border-color: color-mix(in srgb, var(--fg-border) 80%, #000);
    box-shadow: 0 3px 8px rgba(0,0,0,0.08);
  }

  .fg-date-trigger:focus,
  .fg-date-trigger.open {
    border-color: var(--fg-border-focus);
    box-shadow: 0 0 0 3px var(--fg-accent-ring);
  }
  
  .fg-date-cal {
    position: fixed;
    z-index: 9999;
    background: var(--fg-dropdown-bg);
    border: 1px solid var(--fg-border-focus);
    border-radius: var(--fg-radius);
    padding: 16px;
    box-shadow: var(--fg-shadow);
    min-width: 260px;
  }
  
  .fg-date-cal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
  }
  
  .fg-date-nav {
    background: transparent;
    border: none;
    color: var(--fg-text-dim);
    cursor: pointer;
    font-size: 16px;
    padding: 4px 8px;
    border-radius: 4px;
    transition: color 0.15s;
  }
  
  .fg-date-nav:hover {
    color: var(--fg-accent);
  }
  
  .fg-date-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 2px;
  }
  
  .fg-date-cell {
    text-align: center;
    padding: 6px 4px;
    font-size: 12px;
    cursor: pointer;
    border-radius: 4px;
    transition: background 0.15s, color 0.15s;
    color: var(--fg-text-dim);
  }
  
  .fg-date-cell:hover {
    background: var(--fg-hover-bg);
    color: var(--fg-accent);
  }
  
  .fg-date-cell.selected {
    background: var(--fg-accent);
    color: #fff;
  }
  
  .fg-date-cell.today {
    border: 1px solid var(--fg-accent);
    color: var(--fg-accent);
  }
  
  .fg-date-cell.other-month {
    opacity: 0.3;
  }
  
  .fg-date-cell.disabled {
    opacity: 0.2;
    pointer-events: none;
  }
  
  .fg-date-weekday {
    text-align: center;
    padding: 4px;
    font-size: 10px;
    color: var(--fg-text-muted);
    letter-spacing: 0.05em;
    text-transform: uppercase;
  }
  
  /* ============================================================
    DROPDOWN DE SÉLECTION D'ICÔNES
  ============================================================ */
  
  .fg-icon-dropdown {
    box-sizing: border-box; /* indispensable : le width est piloté en JS pour matcher le champ déclencheur (border+padding inclus) */
    width: 380px;
    max-width: 100vw; /* garde-fou d'urgence seulement — le vrai plafond, avec sa marge de sécurité, est calculé en JS (cf. reposition() dans form_generator.js) au plus près de l'espace réellement disponible plutôt qu'un pourcentage fixe du viewport. Ne pas ajouter de marge ici : ça re-plafonnerait en double sur la valeur déjà calculée en JS. */
    background: var(--fg-dropdown-bg, #161923);
    border: 1px solid var(--fg-border-focus, #4f6ef7);
    border-radius: var(--fg-radius, 10px);
    padding: 14px;
    box-shadow: var(--fg-shadow);
    color: var(--fg-text);
    font-family: var(--fg-font);
    display: flex;
    flex-direction: column;
    gap: 14px;
    position: relative;
    z-index: 10000;
    overflow: hidden;
  }

  /* En-tête : recherche + sélecteur de couleur côte à côte, mais capable de
     passer sur deux lignes si le champ déclencheur (donc le dropdown, qui
     épouse strictement sa largeur) est trop étroit pour les deux côte à côte. */
  .fg-icon-dropdown-header {
    display: flex;
    flex-wrap: wrap;
    gap: 8px; /* aligné sur .fg-icons-picker-header (picker inline) */
    align-items: stretch;
  }

  /* Champ couleur dans l'en-tête */
  .fg-icon-dropdown .fg-icon-color-field {
    width: 120px;
    flex-shrink: 0;
  }

  /* Séparateur visuel entre header et catégories */
  .fg-icon-categories {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding: 5px;
    border-radius: calc(var(--fg-radius) * 0.8);
    /*border: 1px solid var(--fg-border);*/
    background: var(--fg-surface2);
    margin: 5px 0 10px;
  }

  /* Grille d'icônes avec scroll */
  .fg-icon-grid-container {
    max-height: 240px;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: var(--fg-border) transparent;
    padding: 2px 0;
    border-radius: calc(var(--fg-radius) * 0.6);
  }

  .fg-icon-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, 50px);
    justify-content: space-between;
    gap: 10px;
    min-height: 40px;
    padding: 2px 2px 15px;
  }

  /* Footer : couleur + bouton Appliquer */
  .fg-icon-dropdown-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    border-top: 1px solid var(--fg-border);
    padding-top: 12px;
    margin-top: -2px;
  }
  
  /* Search */
  
  .fg-search-input {
    background: var(--fg-surface2);
    border: 1px solid var(--fg-border);
    border-radius: calc(var(--fg-radius) * 0.6);
    color: var(--fg-text);
    font-family: var(--fg-font);
    font-size: 13px;
    outline: none;
    width: 100%;
    min-width: 0;
    box-sizing: border-box;
    padding-left: 40px;
    padding-right: 40px;
    transition: border-color 0.18s;
  }
  
  .fg-search-input:focus {
    border-color: var(--fg-border-focus);
  }
  
  .fg-search-box {
    padding: 10px 12px;
    border-bottom: 1px solid var(--fg-border);
  }
  
  .fg-search-box .fg-search-input {
    padding: 10px;
  }
  
  .fg-search-clear {
    position: absolute;
    right: 12px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--fg-text-muted);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    transition: background 0.15s, color 0.15s;
    z-index: 2;
  }
  
  .fg-search-clear:hover {
    background: var(--fg-hover-bg);
    color: var(--fg-accent);
  }
  
  .fg-search-clear:focus-visible {
    outline: 2px solid var(--fg-accent);
    outline-offset: 2px;
  }
  
  
  /* ── Champ recherche dans l'en-tête du dropdown icônes ─────────────
     Reprend exactement le même rendu que .fg-search-field-wrapper
     utilisé dans le reste du formulaire : border, radius, height, focus-ring.
  ──────────────────────────────────────────────────────────────────── */
  .fg-icon-search-container {
    /* flex-basis 140px + min-width:0 : identique à .fg-icons-picker-header
       .fg-search-field-wrapper (picker inline) — auparavant un plancher
       rigide de 150px faisait basculer ce champ sur sa propre ligne à un
       seuil différent de celui du picker inline (qui, lui, se contracte
       librement jusqu'à 0 avant de wrapper), rendant le comportement du
       dropdown téléporté visuellement incohérent avec l'inline à largeur
       de champ déclencheur égale. */
    flex: 1 1 140px;
    min-width: 0;
    display: flex;
    align-items: stretch;
  }

  /* Le wrapper généré par _buildSearch() */
  .fg-icon-search-field-wrapper {
    width: 100%;
    height: var(--fg-field-h);
    background: var(--fg-surface2);
    border: 1px solid var(--fg-border);
    border-radius: var(--fg-radius);          /* identique aux fg-input */
    transition: border-color 0.18s, box-shadow 0.18s;
    overflow: hidden;
    display: flex;
    align-items: center;
    position: relative;
  }

  .fg-icon-search-field-wrapper:focus-within {
    border-color: var(--fg-border-focus);
    box-shadow: 0 0 0 3px var(--fg-accent-ring);
  }

  .fg-icon-search-field-wrapper:focus-within .fg-search-icon {
    color: var(--fg-accent);
  }

  /* Input à l'intérieur : sans border propre, transparent, hauteur pleine */
  .fg-icon-search-field-wrapper .fg-search-input {
    height: 100%;
    background: transparent;
    border: none !important;
    box-shadow: none !important;
    border-radius: 0 !important;
    font-size: 13px;
    color: var(--fg-text);
    font-family: var(--fg-font);
  }

  .fg-icon-search-field-wrapper .fg-search-icon {
    color: var(--fg-text-muted);
    transition: color 0.18s;
    pointer-events: none;
    flex-shrink: 0;
  }

  .fg-icon-search-field-wrapper .fg-search-clear:hover {
    background: var(--fg-hover-bg);
    color: var(--fg-accent);
  }

  /* ── Champ couleur dans l'en-tête du dropdown icônes ────────────────
     Le fg-color-wrapper est déjà stylé globalement (border, radius, focus-ring).
     On fixe uniquement width et height en px pour éviter toute déformation
     de la pastille ronde (qui serait elliptique si height venait d'un % flottant).
  ──────────────────────────────────────────────────────────────────── */
  .fg-icon-color-row {
    width: 130px;
    flex-shrink: 0;
    display: flex;
    align-items: stretch;
  }

  /* Hauteur explicite en px — empêche height:100% de se résoudre à 0 ou de déformer la pastille */
  .fg-icon-color-row .fg-color-wrapper {
    flex: 1;
    min-width: 0;
    height: var(--fg-field-h);  /* 44px fixe, pas de % */
  }

  /* Le champ picker occupe toute la hauteur du wrapper */
  .fg-icon-color-row .fg-color-picker-field {
    height: var(--fg-field-h);
  }

  /* fg-icon-color-field (ancienne classe — compat) */
  .fg-icon-dropdown .fg-icon-color-field { width: 130px; flex-shrink: 0; }
  
  /* fg-icon-categories → défini dans le bloc fg-icon-dropdown ci-dessus */
  
  .fg-icon-cat-btn {
    background: transparent;
    border: 1px solid var(--fg-border);
    border-radius: 99px;
    color: var(--fg-text-muted);
    font-size: 11px;
    padding: 4px 10px;
    cursor: pointer;
    transition: all 0.15s;
    font-family: inherit;
  }
  
  .fg-icon-cat-btn:hover {
    border-color: var(--fg-border-focus);
    color: var(--fg-accent);
  }
  
  .fg-icon-cat-btn.active {
    background: var(--fg-accent-glow);
    border-color: var(--fg-accent);
    color: var(--fg-accent);
  }
  
  .fg-icon-cat-btn.original {
    border-color: var(--fg-accent);
    border-style: dashed;
    color: var(--fg-accent);
    background: transparent;
  }
  
  /* Quand original ET active sont la même catégorie → style actif plein */
  .fg-icon-cat-btn.active.original,
  .fg-icon-cat-btn.active {
    border-style: solid;
    background: var(--fg-accent-glow);
    border-color: var(--fg-accent);
    color: var(--fg-accent);
    font-weight: 600;
  }
  
  /* Idem pour le swiper */
  .fg-icon-swiper .fg-icon-cat-btn.original {
    border-color: var(--fg-accent);
    border-style: dashed;
    color: var(--fg-accent);
  }
  .fg-icon-swiper .fg-icon-cat-btn.active.original,
  .fg-icon-swiper .fg-icon-cat-btn.active {
    border-style: solid;
    background: var(--fg-accent-glow);
    border-color: var(--fg-accent);
    color: var(--fg-accent);
  }
  
  /* fg-icon-grid-container / fg-icon-grid → définis dans le bloc fg-icon-dropdown ci-dessus */
  
  .fg-icon-item {
    /* Taille fixe 50×50px — ni plus, ni moins */
    width: 50px;
    height: 50px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--fg-border);
    border-radius: 8px;
    cursor: pointer;
    /* Icône légèrement plus grande pour occuper les 50px */
    font-size: 22px;
    background: var(--fg-surface2);
    position: relative;
    overflow: hidden;
    box-sizing: border-box;
    transition: border-color 0.15s, background 0.15s, color 0.15s,
                transform 0.15s, box-shadow 0.15s;
  }
  
  .fg-icon-item:hover {
    border-color: var(--fg-accent);
    background: var(--fg-accent-glow);
    transform: scale(1.05);
    box-shadow: 0 4px 14px var(--fg-accent-glow);
  }
  
  .fg-icon-item.selected {
    border-color: var(--fg-accent);
    background: var(--fg-accent-glow);
    color: var(--fg-accent);
    transform: scale(1.05);
    box-shadow: 0 0 0 2px var(--fg-accent-ring), 0 4px 12px var(--fg-accent-glow);
  }
  
  /* ── SVG cache icons (icons_cache.json) — taille dans la grille ── */
  /* Les icônes SVG n'héritent pas de font-size → taille explicite requise */
  .fg-icon-item svg {
    width: 26px;
    height: 26px;
    flex-shrink: 0;
    display: block;
    pointer-events: none;
  }

  /* fg-icon-dropdown-footer → défini dans le bloc fg-icon-dropdown ci-dessus */
  /* fg-icon-color-row → défini dans le bloc icon-search ci-dessus */

  .fg-icon-apply {
    padding: 6px 16px;
    font-size: 12px;
  }
  
  /* ════════════════════════════════════════════════════════
     fg-icon-wrapper — structure homogène (text+icon ET type:icon)
     fg-icon-wrapper
       button.fg-icon-preview          ← même tag/classe partout
       div.fg-icon-body                ← flex:1
         input.fg-input  OU  .fg-color-picker-field
         button.fg-copy-btn            ← visible hors focus seulement
  ════════════════════════════════════════════════════════ */
  .fg-icon-wrapper {
    display: flex;
    align-items: stretch;
    background: var(--fg-surface2);
    border: 1px solid var(--fg-border);
    border-radius: var(--fg-radius);
    overflow: hidden;
    height: var(--fg-field-h);
    min-width: 0;
    width: 100%;
    box-sizing: border-box;
    transition: border-color 0.18s, box-shadow 0.18s, background 0.18s;
  }

  .fg-icon-wrapper:hover:not(:focus-within) {
    border-color: color-mix(in srgb, var(--fg-border) 80%, #000);
    box-shadow: 0 3px 8px rgba(0,0,0,0.08);
  }

  .fg-icon-wrapper:focus-within {
    border-color: var(--fg-border-focus);
    box-shadow: 0 0 0 3px var(--fg-accent-ring);
    background: var(--fg-surface);
  }

  /* Bouton icône — identique dans les deux contextes */
  .fg-icon-preview {
    width: var(--fg-field-h);
    height: 100%;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 20px;
    cursor: pointer;
    border: none;
    border-right: 1px solid var(--fg-border);
    border-radius: 0;
    background: transparent;
    padding: 0;
    outline: none;
    transition: background 0.15s, color 0.15s;
  }
  .fg-icon-preview:hover        { background: var(--fg-hover-bg); }
  .fg-icon-preview:focus-visible { box-shadow: inset 0 0 0 2px var(--fg-border-focus); }

  /* SVG dans le bouton preview (champ type:icon) */
  .fg-icon-preview svg {
    width: 22px;
    height: 22px;
    flex-shrink: 0;
    display: block;
    pointer-events: none;
  }

  /* Alias compat — ne doit plus être généré */
  .fg-icon-btn {
    width: var(--fg-field-h);
    height: 100%;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 20px;
    cursor: pointer;
    border: none;
    border-right: 1px solid var(--fg-border);
    border-radius: 0;
    background: transparent;
    padding: 0;
    outline: none;
    color: var(--fg-accent);
    transition: background 0.15s;
  }
  .fg-icon-btn:hover { background: var(--fg-hover-bg); }

  /* Corps — occupe tout l'espace restant */
  .fg-icon-body {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: stretch;
    position: relative;
  }

  .fg-icon-wrapper .fg-input,
  .fg-icon-body .fg-input {
    flex: 1;
    min-width: 0;
    height: 100%;
    border: none !important;
    box-shadow: none !important;
    background: transparent !important;
    border-radius: 0 !important;
    /* padding-right laisse de la place au fg-copy-btn */
    padding-right: 34px;
  }

  /* Color picker dans fg-icon-body (type:icon) */
  .fg-icon-body .fg-color-picker-field {
    height: 100%;
  }
  
  /* ── Modale icônes générique (fg-icon-picker-modal) ────────── */
  .fg-icon-picker-modal {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.75);
    backdrop-filter: blur(4px);
    z-index: 100000;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  
  .fg-icon-picker-box {
    background: var(--fg-surface, #13161e);
    border: 1px solid var(--fg-border, #252936);
    border-radius: 16px;
    padding: 24px;
    width: min(560px, 95vw);
    max-height: 82vh;
    display: flex;
    flex-direction: column;
    gap: 14px;
    position: relative;
    box-shadow: 0 24px 64px rgba(0, 0, 0, 0.7);
  }
  
  /* Header */
  .fg-icon-picker-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
  }
  .fg-icon-picker-title {
    font-size: 14px;
    font-weight: 600;
    color: var(--fg-text, #e8eaf2);
    letter-spacing: .04em;
  }
  .fg-icon-picker-close {
    background: rgba(255,255,255,.06);
    border: 1px solid var(--fg-border, #252936);
    border-radius: 8px;
    color: var(--fg-text-muted, #9ca3af);
    font-size: 18px;
    width: 32px;
    height: 32px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background .15s, color .15s;
    line-height: 1;
  }
  .fg-icon-picker-close:hover {
    background: rgba(255,255,255,.12);
    color: var(--fg-text, #e8eaf2);
  }
  
  /* Ligne recherche + couleur */
  .fg-icon-picker-searchrow {
    display: flex;
    align-items: center;
    gap: 10px;
  }
  .fg-icon-picker-search {
    flex: 1;
    min-width: 0;
    height: 38px;
    background: var(--fg-surface2, #1a1e2a);
    border: 1px solid var(--fg-border, #252936);
    border-radius: 8px;
    color: var(--fg-text, #e8eaf2);
    font-size: 13px;
    padding: 0 12px;
    outline: none;
    transition: border-color .15s;
  }
  .fg-icon-picker-search:focus { border-color: var(--fg-border-focus, #4f6ef7); }
  
  .fg-icon-picker-swatch {
    width: 38px;
    height: 38px;
    border-radius: 8px;
    border: 1px solid var(--fg-border, #252936);
    cursor: pointer;
    flex-shrink: 0;
    transition: border-color .15s;
    position: relative;
  }
  .fg-icon-picker-swatch:hover { border-color: var(--fg-accent, #4f6ef7); }
  
  /* Catégories */
  .fg-icon-picker-cats {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
  }
  
  /* Grille scrollable */
  .fg-icon-picker-grid-wrap {
    overflow-y: auto;
    max-height: 340px;
    scrollbar-width: thin;
    scrollbar-color: var(--fg-border, #252936) transparent;
  }
  .fg-icon-picker-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(46px, 1fr));
    gap: 6px;
  }
  
  
  /* ── Icons picker inline (type:'icons') ─────────────────────── */
  .fg-icon-picker-inline {
    display: flex;
    flex-direction: column;
    gap: 12px;
  }
  
  /* ── Grille dans le picker inline ────────────────────────────── */
  .fg-icon-picker-inline .fg-icon-grid-container {
    max-height: 280px;
  }
  
  /* ── Pastille couleur dans la modale générique ───────────────── */
  .fg-icon-picker-swatch {
    width: 38px;
    height: 38px;
    border-radius: 8px;
    border: 1px solid var(--fg-border);
    cursor: pointer;
    flex-shrink: 0;
    transition: border-color .15s;
    position: relative;
    overflow: hidden;
  }
  .fg-icon-picker-swatch:hover {
    border-color: var(--fg-accent);
  }
  
  /* Ligne recherche + couleur */
  .fg-icon-picker-searchrow {
    display: flex;
    align-items: center;
    gap: 10px;
  }
  .fg-icon-picker-search {
    flex: 1;
    min-width: 0;
    height: 38px;
    background: var(--fg-surface2);
    border: 1px solid var(--fg-border);
    border-radius: var(--fg-radius);
    color: var(--fg-text);
    font-size: 13px;
    font-family: inherit;
    padding: 0 12px;
    outline: none;
    transition: border-color .15s;
  }
  .fg-icon-picker-search:focus {
    border-color: var(--fg-border-focus);
    box-shadow: 0 0 0 3px var(--fg-accent-ring);
  }
  
  /* Header de la modale */
  .fg-icon-picker-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
  }
  .fg-icon-picker-title {
    font-size: 14px;
    font-weight: 600;
    color: var(--fg-text);
    letter-spacing: .04em;
  }
  .fg-icon-picker-close {
    background: rgba(255,255,255,.06);
    border: 1px solid var(--fg-border);
    border-radius: 8px;
    color: var(--fg-text-muted);
    font-size: 18px;
    width: 32px;
    height: 32px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background .15s, color .15s;
    line-height: 1;
    padding: 0;
  }
  .fg-icon-picker-close:hover {
    background: rgba(255,255,255,.12);
    color: var(--fg-text);
  }
  
  /* Grille dans la modale */
  .fg-icon-picker-grid-wrap {
    overflow-y: auto;
    max-height: 340px;
    scrollbar-width: thin;
    scrollbar-color: var(--fg-border) transparent;
  }
  .fg-icon-picker-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(46px, 1fr));
    gap: 6px;
  }
  
  /* Catégories dans la modale */
  .fg-icon-picker-cats {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
  }
  
  /* Password */
  .fg-pwd-outer {
    display: flex;
    flex-direction: column;
    width: 100%;
    position: relative;
  }
  
  .fg-pwd-wrapper {
    display: flex;
    align-items: stretch;
    background: var(--fg-surface2);
    border: 1px solid var(--fg-border);
    border-radius: var(--fg-radius);
    overflow: hidden;
    transition: border-color 0.18s, box-shadow 0.18s, background 0.18s;
  }
  
  .fg-pwd-wrapper:hover:not(:focus-within) {
    border-color: color-mix(in srgb, var(--fg-border) 80%, #000);
    box-shadow: 0 3px 8px rgba(0,0,0,0.08);
  }

  .fg-pwd-wrapper:focus-within {
    border-color: var(--fg-border-focus);
    box-shadow: 0 0 0 3px var(--fg-accent-ring);
    background: var(--fg-surface);
  }
  
  .fg-pwd-wrapper .fg-input {
    border: none !important;
    box-shadow: none !important;
    background: transparent !important;
    border-radius: 0 !important;
    flex: 1;
    min-width: 0;
  }
  
  .fg-pwd-eye {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    flex-shrink: 0;
    font-size: 16px;
    cursor: pointer;
    border: none;
    outline: none;
    background: transparent;
    border-left: 1px solid var(--fg-border);
    color: var(--fg-text-muted);
    transition: color 0.15s, background 0.15s;
  }
  
  .fg-pwd-eye:hover {
    color: var(--fg-accent);
    background: var(--fg-hover-bg);
  }
  
  .fg-pwd-gen-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    flex-shrink: 0;
    font-size: 14px;
    cursor: pointer;
    border: none;
    outline: none;
    background: transparent;
    border-left: 1px solid var(--fg-border);
    color: var(--fg-text-muted);
    transition: color 0.15s, background 0.15s;
  }
  
  .fg-pwd-gen-btn:hover {
    color: var(--fg-accent);
    background: var(--fg-hover-bg);
  }
  
  .fg-pwd-strength-wrap {
    height: 4px;
    background: var(--fg-border);
    border-radius: 99px;
    overflow: hidden;
    margin-top: 6px;
  }
  
  .fg-pwd-strength-bar {
    height: 100%;
    border-radius: 99px;
    transition: width 0.35s, background 0.35s;
    width: 0;
  }
  
  .fg-pwd-strength-label {
    font-size: 10.5px;
    color: var(--fg-text-muted);
    margin-top: 4px;
    text-align: right;
    min-height: 16px;
    transition: color 0.3s;
  }
  
  .fg-pwd-gen-popup {
    position: absolute;
    left: 0;
    right: 0;
    top: calc(100% + 6px);
    background: var(--fg-surface);
    border: 1px solid var(--fg-border-focus);
    border-radius: var(--fg-radius);
    padding: 12px 14px;
    z-index: 500;
    box-shadow: var(--fg-shadow);
    display: none;
    flex-direction: column;
    gap: 10px;
  }
  
  .fg-pwd-gen-popup.open {
    display: flex;
  }
  
  .fg-pwd-gen-result {
    font-size: 12px;
    background: var(--fg-surface2);
    border: 1px solid var(--fg-border);
    border-radius: calc(var(--fg-radius) * 0.7);
    padding: 8px 12px;
    color: var(--fg-accent);
    letter-spacing: 0.07em;
    word-break: break-all;
    cursor: pointer;
    transition: background 0.15s;
    font-family: monospace;
  }
  
  .fg-pwd-gen-result:hover {
    background: var(--fg-hover-bg);
  }
  
  .fg-pwd-criteria {
    display: flex;
    flex-direction: column;
    gap: 5px;
  }
  
  .fg-pwd-crit-row {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    color: var(--fg-text-dim);
  }
  
  .fg-pwd-crit-check {
    width: 14px;
    height: 14px;
    border-radius: 3px;
    cursor: pointer;
    accent-color: var(--fg-accent);
    flex-shrink: 0;
  }
  
  .fg-pwd-len-row {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    color: var(--fg-text-dim);
  }
  
  .fg-pwd-len-inp {
    width: 52px;
    background: var(--fg-surface2);
    border: 1px solid var(--fg-border);
    border-radius: 4px;
    color: var(--fg-text);
    font-family: var(--fg-font);
    font-size: 12px;
    padding: 3px 6px;
    outline: none;
    text-align: center;
    -moz-appearance: textfield;
  }
  
  .fg-pwd-len-inp::-webkit-outer-spin-button,
  .fg-pwd-len-inp::-webkit-inner-spin-button {
    -webkit-appearance: none;
  }
  
  .fg-pwd-len-inp:focus {
    border-color: var(--fg-border-focus);
  }
  
  .fg-pwd-gen-actions {
    display: flex;
    gap: 6px;
    justify-content: flex-end;
  }
  
  .fg-pwd-gen-again {
    font-family: var(--fg-font);
    font-size: 11px;
    padding: 5px 12px;
    border-radius: 6px;
    border: 1px solid var(--fg-border);
    background: transparent;
    color: var(--fg-text-muted);
    cursor: pointer;
    transition: all 0.15s;
  }
  
  .fg-pwd-gen-again:hover {
    border-color: var(--fg-border-focus);
    color: var(--fg-accent);
  }
  
  .fg-pwd-gen-use {
    font-family: var(--fg-font);
    font-size: 11px;
    padding: 5px 12px;
    border-radius: 6px;
    border: none;
    background: var(--fg-accent);
    color: #fff;
    cursor: pointer;
    transition: opacity 0.15s;
  }
  
  .fg-pwd-gen-use:hover {
    opacity: 0.85;
  }
  
  /* Number wrapper */
  .fg-number-wrapper {
    display: flex;
    align-items: stretch;
    background: var(--fg-surface2);
    border: 1px solid var(--fg-border);
    border-radius: var(--fg-radius);
    overflow: hidden;
    transition: border-color 0.18s, box-shadow 0.18s;
  }
  
  .fg-number-wrapper:hover:not(:focus-within) {
    border-color: color-mix(in srgb, var(--fg-border) 80%, #000);
    box-shadow: 0 3px 8px rgba(0,0,0,0.08);
  }

  .fg-number-wrapper:focus-within {
    border-color: var(--fg-border-focus);
    box-shadow: 0 0 0 3px var(--fg-accent-ring);
  }
  
  .fg-number-wrapper .fg-input {
    border: none !important;
    box-shadow: none !important;
    background: transparent !important;
    border-radius: 0 !important;
    flex: 1;
    min-width: 0;
    text-align: center;
    -moz-appearance: textfield;
  }
  
  .fg-number-wrapper .fg-input::-webkit-outer-spin-button,
  .fg-number-wrapper .fg-input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
  }
  
  .fg-num-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    flex-shrink: 0;
    cursor: pointer;
    border: none;
    outline: none;
    background: var(--fg-surface);
    color: var(--fg-text-muted);
    font-size: 18px;
    font-weight: 600;
    transition: color 0.15s, background 0.15s;
    user-select: none;
    -webkit-user-select: none;
  }
  
  .fg-num-btn:hover {
    color: var(--fg-accent);
    background: var(--fg-hover-bg);
  }
  
  .fg-num-btn.minus {
    border-right: 1px solid var(--fg-border);
  }
  
  .fg-num-btn.plus {
    border-left: 1px solid var(--fg-border);
  }
  
  /* Choice indicator hidden */
  .fg-choice-indicator.hidden {
    display: none !important;
  }
  
  /* Avatars / icons */
  .fg-choice-avatar {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
  }
  
  .fg-choice-icon {
    font-size: 16px;
    flex-shrink: 0;
    width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-align: center;
  }

  /* Les icônes SVG (cache icons.json, clé 'svg-icon:<slug>') n'héritent
     pas de font-size comme un glyphe icofont ou un emoji → taille
     explicite requise, même principe que .fg-icon-preview svg / .fg-icon-item svg. */
  .fg-choice-icon svg {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    display: block;
    pointer-events: none;
  }
  
  .fg-option-avatar {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
  }
  
  .fg-option-icon {
    font-size: 14px;
    flex-shrink: 0;
    width: 20px;
    height: 20px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-align: center;
  }

  /* Les icônes SVG (cache icons.json, clé 'svg-icon:<slug>') n'héritent
     pas de font-size comme un glyphe icofont ou un emoji → taille
     explicite requise, même principe que .fg-choice-icon svg. */
  .fg-option-icon svg {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    display: block;
    pointer-events: none;
  }
  
  /* Action buttons */
  .fg-btn-group {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    align-items: center;
  }

  .fg-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    font-family: var(--fg-font);
    font-size: 13px;
    font-weight: 600;
    padding: 0 22px;
    height: 42px;
    border-radius: var(--fg-radius);
    border: none;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    user-select: none;
    letter-spacing: 0.04em;
    white-space: nowrap;
    transition: box-shadow 0.18s ease,
                filter 0.18s ease,
                background 0.18s ease,
                border-color 0.18s ease,
                transform 0.1s ease;
  }

  /* Shimmer au survol */
  .fg-btn::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(
      105deg,
      transparent 35%,
      rgba(255,255,255,0.18) 50%,
      transparent 65%
    );
    transform: translateX(-100%);
    transition: transform 0s;
    pointer-events: none;
  }
  .fg-btn:hover::before {
    transform: translateX(100%);
    transition: transform 0.45s ease;
  }

  /* Flash press */
  .fg-btn::after {
    content: '';
    position: absolute;
    inset: 0;
    background: rgba(0,0,0,0.1);
    opacity: 0;
    border-radius: inherit;
    transition: opacity 0.1s;
    pointer-events: none;
  }
  .fg-btn:active::after { opacity: 1; }

  .fg-btn:disabled {
    opacity: 0.4;
    pointer-events: none;
    filter: grayscale(0.25);
  }

  /* ── Primary ── */
  .fg-btn-primary {
    background: linear-gradient(135deg,
      var(--fg-accent) 0%,
      color-mix(in srgb, var(--fg-accent) 68%, #818cf8) 100%);
    color: #fff;
    box-shadow: 0 2px 6px color-mix(in srgb, var(--fg-accent) 45%, transparent),
                0 1px 2px rgba(0,0,0,0.15),
                inset 0 1px 0 rgba(255,255,255,0.16);
  }
  .fg-btn-primary:hover {
    filter: brightness(1.07);
    box-shadow: 0 3px 8px color-mix(in srgb, var(--fg-accent) 35%, transparent),
                0 1px 3px rgba(0,0,0,0.12),
                inset 0 1px 0 rgba(255,255,255,0.16);
  }
  .fg-btn-primary:active {
    transform: scale(0.97);
    filter: brightness(0.97);
    box-shadow: 0 1px 3px color-mix(in srgb, var(--fg-accent) 30%, transparent);
  }

  /* ── Secondary ── */
  .fg-btn-secondary {
    background: var(--fg-surface2);
    color: var(--fg-text);
    border: 1px solid var(--fg-border);
    box-shadow: 0 1px 3px rgba(0,0,0,0.08),
                inset 0 1px 0 rgba(255,255,255,0.05);
  }
  .fg-btn-secondary:hover {
    border-color: color-mix(in srgb, var(--fg-border) 80%, #000);
    background: var(--fg-surface);
    box-shadow: 0 2px 6px rgba(0,0,0,0.09);
  }
  .fg-btn-secondary:active {
    transform: scale(0.97);
    box-shadow: none;
  }

  /* ── Danger ── */
  .fg-btn-danger {
    background: linear-gradient(135deg,
      var(--fg-red) 0%,
      color-mix(in srgb, var(--fg-red) 72%, #7f1d1d) 100%);
    color: #fff;
    box-shadow: 0 2px 6px rgba(247,95,110,0.3),
                0 1px 2px rgba(0,0,0,0.15),
                inset 0 1px 0 rgba(255,255,255,0.14);
  }
  .fg-btn-danger:hover {
    filter: brightness(1.07);
    box-shadow: 0 3px 8px rgba(247,95,110,0.28),
                0 1px 3px rgba(0,0,0,0.12);
  }
  .fg-btn-danger:active {
    transform: scale(0.97);
    filter: brightness(0.97);
    box-shadow: 0 1px 3px rgba(247,95,110,0.25);
  }

  /* ── Ghost ── */
  .fg-btn-ghost {
    background: transparent;
    color: var(--fg-text-dim);
    border: 1px solid var(--fg-border);
  }
  .fg-btn-ghost:hover {
    color: var(--fg-text);
    border-color: color-mix(in srgb, var(--fg-border) 80%, #000);
    background: var(--fg-hover-bg);
    box-shadow: 0 1px 4px rgba(0,0,0,0.07);
  }
  .fg-btn-ghost:active {
    transform: scale(0.97);
    box-shadow: none;
  }

  /* ── Success ── */
  .fg-btn-success {
    background: linear-gradient(135deg,
      var(--fg-green) 0%,
      color-mix(in srgb, var(--fg-green) 72%, #064e3b) 100%);
    color: #fff;
    box-shadow: 0 2px 6px rgba(34,211,163,0.25),
                0 1px 2px rgba(0,0,0,0.12),
                inset 0 1px 0 rgba(255,255,255,0.14);
  }
  .fg-btn-success:hover {
    filter: brightness(1.07);
    box-shadow: 0 3px 8px rgba(34,211,163,0.22),
                0 1px 3px rgba(0,0,0,0.10);
  }
  .fg-btn-success:active {
    transform: scale(0.97);
    filter: brightness(0.97);
    box-shadow: 0 1px 3px rgba(34,211,163,0.2);
  }

  .fg-btn .fg-btn-icon {
    font-size: 15px;
    line-height: 1;
    flex-shrink: 0;
  }

  /* SVG dans l’icône d’un bouton (cfg.icon = "svg-icon:<slug>") */
  .fg-btn .fg-btn-icon svg {
    width: 15px;
    height: 15px;
    display: block;
    flex-shrink: 0;
  }
  
  /* Confirm popup (hors scope) */
  .fg-confirm-popup {
    position: fixed;
    z-index: 99999;
    padding: 16px 20px;
    min-width: 260px;
    max-width: 340px;
    display: none;
    flex-direction: column;
    gap: 12px;
    font-family: var(--fg-font, 'DM Mono', monospace);
    font-size: 14px;
    box-sizing: border-box;
    background: var(--fg-dropdown-bg);
    color: var(--fg-text);
    border: 1px solid var(--fg-border, transparent);
    border-radius: var(--fg-radius);
    box-shadow:
      0 8px 24px rgba(0, 0, 0, 0.18),
      0 20px 48px rgba(0, 0, 0, 0.22),
      0 0 0 1px rgba(0, 0, 0, 0.06);
    opacity: 0;
    transform: scale(0.96);
    transition: opacity 0.15s ease, transform 0.15s ease;
  }
  
  .fg-confirm-popup.open {
    display: flex;
    opacity: 1;
    transform: scale(1);
  }
  
  /* Flèche pointant vers le bouton déclencheur, positionnée dynamiquement
     via --fg-confirm-arrow-x / --fg-confirm-arrow-y (cf. positionPopup()
     dans _buildButton) pour rester alignée même si la popup a dû être
     décalée pour tenir dans le viewport. */
  .fg-confirm-popup::after {
    content: '';
    position: absolute;
    width: 0;
    height: 0;
    border: 8px solid transparent;
    pointer-events: none;
  }
  
  .fg-confirm-popup.fg-confirm-bottom::after {
    top: -8px;
    left: var(--fg-confirm-arrow-x, 20px);
    transform: translateX(-50%);
    border-top: none;
    border-bottom-color: var(--fg-dropdown-bg);
    filter: drop-shadow(0 -2px 2px rgba(0, 0, 0, 0.08));
  }
  
  .fg-confirm-popup.fg-confirm-top::after {
    bottom: -8px;
    left: var(--fg-confirm-arrow-x, 20px);
    transform: translateX(-50%);
    border-bottom: none;
    border-top-color: var(--fg-dropdown-bg);
    filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.08));
  }
  
  .fg-confirm-popup.fg-confirm-right::after {
    left: -8px;
    top: var(--fg-confirm-arrow-y, 20px);
    transform: translateY(-50%);
    border-left: none;
    border-right-color: var(--fg-dropdown-bg);
    filter: drop-shadow(-2px 0 2px rgba(0, 0, 0, 0.08));
  }
  
  .fg-confirm-popup.fg-confirm-left::after {
    right: -8px;
    top: var(--fg-confirm-arrow-y, 20px);
    transform: translateY(-50%);
    border-right: none;
    border-left-color: var(--fg-dropdown-bg);
    filter: drop-shadow(2px 0 2px rgba(0, 0, 0, 0.08));
  }
  
  .fg-confirm-msg {
    font-size: 13px;
    line-height: 1.6;
    color: var(--fg-text);
  }
  
  .fg-confirm-actions {
    display: flex;
    gap: 8px;
    justify-content: flex-end;
    flex-wrap: wrap;
    margin-top: 4px;
  }
  
  .fg-confirm-popup .fg-btn {
    font-family: var(--fg-font, 'DM Mono', monospace);
    font-size: 12px;
    font-weight: 500;
    padding: 7px 16px;
    border-radius: 8px;
    border: none;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    transition: all 0.15s;
    position: relative;
    overflow: hidden;
    letter-spacing: 0.02em;
  }
  
  .fg-confirm-popup .fg-btn-ghost {
    background: transparent;
    color: var(--fg-text);
    border: 1px solid var(--fg-border, currentColor);
  }
  
  .fg-confirm-popup .fg-btn-ghost:hover {
    background: var(--fg-border, rgba(128, 128, 128, 0.12));
  }
  
  .fg-confirm-popup .fg-btn-danger {
    box-shadow: 0 4px 12px rgba(247, 95, 110, 0.28);
  }
  
  .fg-confirm-popup .fg-btn-danger:hover {
    filter: brightness(1.1);
    transform: translateY(-1px);
  }
  
  /* Scrollbars */
  .fg-form ::-webkit-scrollbar {
    width: 5px;
    height: 5px;
  }
  
  .fg-form ::-webkit-scrollbar-track {
    background: transparent;
  }
  
  .fg-form ::-webkit-scrollbar-thumb {
    background: var(--fg-border);
    border-radius: 99px;
  }
  
  .fg-form ::-webkit-scrollbar-thumb:hover {
    background: var(--fg-border-focus);
  }
  
  .fg-options-list {
    scrollbar-width: thin;
    scrollbar-color: var(--fg-border) transparent;
  }
  
  .fg-gps-autocomplete {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--fg-dropdown-bg);
    border: 1px solid var(--fg-border-focus);
    border-top: none;
    border-radius: 0 0 var(--fg-radius) var(--fg-radius);
    z-index: 1000;
    max-height: 200px;
    overflow-y: auto;
    display: none;
    scrollbar-width: thin;
    scrollbar-color: var(--fg-border) transparent;
    box-shadow: var(--fg-shadow);
    margin-top: 0;
    box-sizing: border-box;
  }
  
  .fg-gps-autocomplete.open {
    display: block;
  }
  
  .fg-gps-autocomplete-item {
    padding: 10px 14px;
    cursor: pointer;
    font-size: 13px;
    color: var(--fg-text-dim);
    border-bottom: 1px solid var(--fg-border);
    transition: background 0.12s, color 0.12s;
    background: var(--fg-dropdown-bg);
  }
  
  .fg-gps-autocomplete-item:last-child {
    border-bottom: none;
  }
  
  .fg-gps-autocomplete-item:hover,
  .fg-gps-autocomplete-item.focused {
    background: var(--fg-hover-bg);
    color: var(--fg-accent);
  }
  
  /* ============================================================
     NICE SCROLL - Barres de défilement personnalisées
     Avec élargissement au survol
     ============================================================ */
  
  /* Pour tous les éléments avec overflow-y: auto dans le scope FormGenerator */
  .fg-form * {
    scrollbar-width: thin;
    scrollbar-color: var(--fg-border) transparent;
  }
  
  /* Webkit (Chrome, Edge, Safari) - Style de base */
  .fg-form *::-webkit-scrollbar {
    width: 6px;
    height: 6px;
    transition: width 0.2s ease, height 0.2s ease;
  }
  
  /* Élargissement au survol du conteneur */
  .fg-form *:hover::-webkit-scrollbar {
    width: 10px;
    height: 10px;
  }
  
  .fg-form *::-webkit-scrollbar-track {
    background: transparent;
    border-radius: 10px;
    margin: 4px 0;
  }
  
  .fg-form *::-webkit-scrollbar-thumb {
    background: var(--fg-border);
    border-radius: 10px;
    border: 2px solid transparent;
    background-clip: padding-box;
    transition: background 0.2s ease, border-width 0.2s ease;
  }
  
  /* Au survol du conteneur, le thumb s'adapte */
  .fg-form *:hover::-webkit-scrollbar-thumb {
    border-width: 1px;
  }
  
  .fg-form *::-webkit-scrollbar-thumb:hover {
    background: var(--fg-border-focus);
  }
  
  .fg-form *::-webkit-scrollbar-thumb:active {
    background: var(--fg-accent);
  }
  
  /* ============================================================
     ÉLÉMENTS TÉLÉPORTÉS (hors scope)
     ============================================================ */
  
  .fg-dropdown-teleport::-webkit-scrollbar {
    width: 6px;
    height: 6px;
    transition: width 0.2s ease;
  }
  
  .fg-dropdown-teleport:hover::-webkit-scrollbar {
    width: 10px;
  }
  
  .fg-dropdown-teleport::-webkit-scrollbar-track {
    background: transparent;
    border-radius: 10px;
    margin: 4px 0;
  }
  
  .fg-dropdown-teleport::-webkit-scrollbar-thumb {
    background: var(--fg-border, #252936);
    border-radius: 10px;
    border: 2px solid transparent;
    background-clip: padding-box;
    transition: background 0.2s ease, border-width 0.2s ease;
  }
  
  .fg-dropdown-teleport:hover::-webkit-scrollbar-thumb {
    border-width: 1px;
  }
  
  .fg-dropdown-teleport::-webkit-scrollbar-thumb:hover {
    background: var(--fg-border-focus, #4f6ef7);
  }
  
  /* ============================================================
     LISTES D'OPTIONS (SELECT)
     ============================================================ */
  
  .fg-options-list,
  .fg-dropdown-teleport .fg-options-list {
    scrollbar-width: thin;
    scrollbar-color: var(--fg-border) transparent;
  }
  
  .fg-options-list::-webkit-scrollbar,
  .fg-dropdown-teleport .fg-options-list::-webkit-scrollbar {
    width: 6px;
    transition: width 0.2s ease;
  }
  
  .fg-options-list:hover::-webkit-scrollbar,
  .fg-dropdown-teleport .fg-options-list:hover::-webkit-scrollbar {
    width: 10px;
  }
  
  .fg-options-list::-webkit-scrollbar-track,
  .fg-dropdown-teleport .fg-options-list::-webkit-scrollbar-track {
    background: transparent;
    border-radius: 10px;
  }
  
  .fg-options-list::-webkit-scrollbar-thumb,
  .fg-dropdown-teleport .fg-options-list::-webkit-scrollbar-thumb {
    background: var(--fg-border);
    border-radius: 10px;
    border: 2px solid transparent;
    background-clip: padding-box;
    transition: background 0.2s ease, border-width 0.2s ease;
  }
  
  .fg-options-list:hover::-webkit-scrollbar-thumb,
  .fg-dropdown-teleport .fg-options-list:hover::-webkit-scrollbar-thumb {
    border-width: 1px;
  }
  
  .fg-options-list::-webkit-scrollbar-thumb:hover,
  .fg-dropdown-teleport .fg-options-list::-webkit-scrollbar-thumb:hover {
    background: var(--fg-border-focus);
  }
  
  /* ============================================================
     DATE PICKER
     ============================================================ */
  
  .fg-date-cal {
    scrollbar-width: thin;
    scrollbar-color: var(--fg-border) transparent;
  }
  
  .fg-date-cal::-webkit-scrollbar {
    width: 6px;
    transition: width 0.2s ease;
  }
  
  .fg-date-cal:hover::-webkit-scrollbar {
    width: 10px;
  }
  
  .fg-date-cal::-webkit-scrollbar-track {
    background: transparent;
    border-radius: 10px;
  }
  
  .fg-date-cal::-webkit-scrollbar-thumb {
    background: var(--fg-border);
    border-radius: 10px;
    border: 2px solid transparent;
    background-clip: padding-box;
    transition: background 0.2s ease, border-width 0.2s ease;
  }
  
  .fg-date-cal:hover::-webkit-scrollbar-thumb {
    border-width: 1px;
  }
  
  .fg-date-cal::-webkit-scrollbar-thumb:hover {
    background: var(--fg-border-focus);
  }
  
  /* ============================================================
     MODALE D'ICÔNES
     ============================================================ */
  
  .fg-icon-picker-box {
    scrollbar-width: thin;
    scrollbar-color: var(--fg-border) transparent;
  }
  
  .fg-icon-picker-box::-webkit-scrollbar {
    width: 6px;
    transition: width 0.2s ease;
  }
  
  .fg-icon-picker-box:hover::-webkit-scrollbar {
    width: 10px;
  }
  
  .fg-icon-picker-box::-webkit-scrollbar-track {
    background: transparent;
    border-radius: 10px;
  }
  
  .fg-icon-picker-box::-webkit-scrollbar-thumb {
    background: var(--fg-border);
    border-radius: 10px;
    border: 2px solid transparent;
    background-clip: padding-box;
    transition: background 0.2s ease, border-width 0.2s ease;
  }
  
  .fg-icon-picker-box:hover::-webkit-scrollbar-thumb {
    border-width: 1px;
  }
  
  .fg-icon-picker-box::-webkit-scrollbar-thumb:hover {
    background: var(--fg-border-focus);
  }
  
  /* ============================================================
     POPUP DE CONFIRMATION
     ============================================================ */
  
  .fg-confirm-popup {
    scrollbar-width: thin;
    scrollbar-color: var(--fg-border, #252936) transparent;
  }
  
  .fg-confirm-popup::-webkit-scrollbar {
    width: 6px;
    transition: width 0.2s ease;
  }
  
  .fg-confirm-popup:hover::-webkit-scrollbar {
    width: 10px;
  }
  
  .fg-confirm-popup::-webkit-scrollbar-track {
    background: transparent;
    border-radius: 10px;
  }
  
  .fg-confirm-popup::-webkit-scrollbar-thumb {
    background: var(--fg-border, #252936);
    border-radius: 10px;
    border: 2px solid transparent;
    background-clip: padding-box;
    transition: background 0.2s ease, border-width 0.2s ease;
  }
  
  .fg-confirm-popup:hover::-webkit-scrollbar-thumb {
    border-width: 1px;
  }
  
  /* ============================================================
     AUTOCOMPLÉTION GPS
     ============================================================ */
  
  .fg-gps-autocomplete {
    scrollbar-width: thin;
    scrollbar-color: var(--fg-border) transparent;
  }
  
  .fg-gps-autocomplete::-webkit-scrollbar {
    width: 6px;
    transition: width 0.2s ease;
  }
  
  .fg-gps-autocomplete:hover::-webkit-scrollbar {
    width: 10px;
  }
  
  .fg-gps-autocomplete::-webkit-scrollbar-track {
    background: transparent;
    border-radius: 10px;
  }
  
  .fg-gps-autocomplete::-webkit-scrollbar-thumb {
    background: var(--fg-border);
    border-radius: 10px;
    border: 2px solid transparent;
    background-clip: padding-box;
    transition: background 0.2s ease, border-width 0.2s ease;
  }
  
  .fg-gps-autocomplete:hover::-webkit-scrollbar-thumb {
    border-width: 1px;
  }
  
  .fg-gps-autocomplete::-webkit-scrollbar-thumb:hover {
    background: var(--fg-border-focus);
  }
  
  /* ═══════════════════════════════════════════════════════════
     CAPTCHA — built-in & Google
     ═══════════════════════════════════════════════════════════ */
  
     .fg-captcha-wrapper {
      display: flex;
      flex-direction: column;
      gap: 5px;
      width: 100%;
    }
    
    /* Wrapper principal : même apparence que fg-input */
    .fg-captcha-field {
      display: flex;
      align-items: center;
      background: var(--fg-surface2);
      border: 1px solid var(--fg-border);
      border-radius: var(--fg-radius);
      transition: border-color 0.18s, box-shadow 0.18s;
      overflow: hidden;
      height: var(--fg-field-h);
    }

    /* Hover : même comportement que fg-input:hover (état neutre, hors focus) */
    .fg-captcha-field:hover:not(:focus-within) {
      border-color: color-mix(in srgb, var(--fg-border) 80%, #000);
      box-shadow: 0 3px 8px rgba(0,0,0,0.08);
    }
    
    /* Focus-within : même comportement que fg-input:focus */
    .fg-captcha-field:focus-within {
      border-color: var(--fg-border-focus);
      box-shadow: 0 0 0 3px var(--fg-accent-ring);
    }
    
    /* Bouton refresh — zone à gauche, sans bordure propre */
    .fg-captcha-refresh {
      display: flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      width: 40px;
      height: 100%;
      background: transparent;
      border: none;
      color: var(--fg-text-muted);
      cursor: pointer;
      transition: color 0.18s, background 0.18s;
      position: relative;
      overflow: hidden;
    }
    
    .fg-captcha-refresh:hover {
      color: var(--fg-accent);
      background: var(--fg-accent-glow);
    }
    
    .fg-captcha-refresh svg {
      transition: transform 0.4s cubic-bezier(.4,2,.6,1);
      flex-shrink: 0;
    }
    
    .fg-captcha-refresh.fg-captcha-spin svg {
      transform: rotate(360deg);
    }
    
    /* Séparateur vertical (même style que les dividers d'autres champs composites) */
    .fg-captcha-sep {
      display: block;
      width: 1px;
      height: 24px;
      background: var(--fg-border);
      flex-shrink: 0;
    }
    
    /* Canvas CAPTCHA — centré dans sa zone, sans bordure propre */
    .fg-captcha-canvas {
      display: block;
      flex-shrink: 0;
      user-select: none;
      -webkit-user-select: none;
      cursor: default;
      background: transparent;
      /* La hauteur est définie dynamiquement, on laisse le wrapper gérer */
      align-self: center;
      margin: 0 4px;
      border-radius: calc(var(--fg-radius) - 2px);
      height: 32px;   /* légèrement en retrait de la hauteur du wrapper */
      width: auto;
    }
    
    /* Champ de saisie — prend tout l'espace restant, sans bordure ni fond propres */
    .fg-captcha-input {
      flex: 1;
      min-width: 0;
      height: 100%;
      border: none;
      background: transparent;
      color: var(--fg-text);
      font-family: var(--fg-font);
      font-size: 14px;
      font-weight: 600;
      letter-spacing: 0.14em;
      text-transform: uppercase;
      padding: 0 12px;
      outline: none;
    }
    
    .fg-captcha-input::placeholder {
      color: var(--fg-placeholder);
      font-weight: 400;
      letter-spacing: 0;
      text-transform: none;
    }
    
    /* Icône de statut — à droite dans le wrapper */
    .fg-captcha-status {
      flex-shrink: 0;
      font-size: 12px;
      font-weight: 600;
      padding-right: 12px;
      white-space: nowrap;
      transition: color 0.2s;
      line-height: 1;
    }
    
    .fg-captcha-status.fg-captcha-valid {
      color: var(--fg-green);
    }
    
    .fg-captcha-status.fg-captcha-invalid {
      color: var(--fg-red);
    }
    
    /* Hint discret sous le wrapper */
    .fg-captcha-hint {
      font-size: 11px;
      color: var(--fg-text-muted);
      letter-spacing: 0.02em;
      padding-left: 2px;
    }
    
    /* Google reCAPTCHA */
    .fg-captcha-google-mount {
      display: inline-block;
    }
    
    /* Message d'erreur (siteKey manquante) */
    .fg-captcha-error-msg {
      font-size: 12px;
      color: var(--fg-red);
      padding: 8px 12px;
      border: 1px solid var(--fg-red);
      border-radius: var(--fg-radius);
      background: rgba(220, 53, 69, 0.06);
    }
  /* ══════════════════════════════════════════════════════════════
     ICON PICKER — SwiperJS Categories
  ══════════════════════════════════════════════════════════════ */
  
  /* Section contenant [prev] [swiper] [next] */
  .fg-icon-swiper-section {
    position: relative;
    display: flex;
    align-items: center;
    width: 100%;
    padding: 6px 0;
    background: transparent;
    border-bottom: none;
    box-sizing: border-box;
  }

  .fg-icon-swiper-section.fg-search-active {
    opacity: 0.4;
    pointer-events: none;
    transition: opacity .2s;
  }

  /* Boutons de navigation — positionnés aux extrêmes */
  .fg-icon-swiper-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
    flex-shrink: 0;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    border: 1px solid var(--fg-border);
    background: var(--fg-surface2);
    color: var(--fg-text-dim);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s, color 0.15s, border-color 0.15s, opacity 0.15s;
    padding: 0;
  }
  .fg-icon-swiper-nav.fg-icon-swiper-prev { left: 0; }
  .fg-icon-swiper-nav.fg-icon-swiper-next { right: 0; }

  .fg-icon-swiper-nav:not(.swiper-button-disabled):hover {
    background: var(--fg-accent);
    color: #fff;
    border-color: var(--fg-accent);
  }
  .fg-icon-swiper-nav.swiper-button-disabled {
    opacity: 0.25;
    cursor: default;
    pointer-events: none;
  }

  /* Conteneur Swiper — marges latérales pour ne pas passer sous les boutons nav */
  .fg-icon-swiper {
    flex: 1;
    overflow: hidden;
    min-width: 0;
    margin: 0 30px;
  }
  .fg-icon-swiper .swiper-wrapper {
    display: flex;
    align-items: center;
  }
  /* Fix 2 : espace entre les slides de catégories */
  .fg-icon-swiper .swiper-slide.fg-icon-cat-slide {
    width: auto !important;
    flex-shrink: 0;
    margin-right: 6px;
  }
  .fg-icon-swiper .swiper-slide.fg-icon-cat-slide:last-child {
    margin-right: 0;
  }
  
  /* Bouton catégorie dans le swiper */
  .fg-icon-swiper .fg-icon-cat-btn,
  .fg-icon-picker-cats .fg-icon-cat-btn {
    background: transparent;
    border: 1px solid var(--fg-border, #252936);
    color: var(--fg-text-muted, #6b7280);
    border-radius: 20px;
    padding: 4px 12px;
    font-size: 12px;
    font-family: var(--fg-font, inherit);
    cursor: pointer;
    white-space: nowrap;
    transition: all 0.15s;
  }
  .fg-icon-swiper .fg-icon-cat-btn:hover,
  .fg-icon-picker-cats .fg-icon-cat-btn:hover {
    border-color: var(--fg-accent, #4f6ef7);
    color: var(--fg-accent, #4f6ef7);
    background: rgba(79, 110, 247, 0.08);
  }
  .fg-icon-swiper .fg-icon-cat-btn.active,
  .fg-icon-picker-cats .fg-icon-cat-btn.active {
    background: var(--fg-accent, #4f6ef7);
    border-color: var(--fg-accent, #4f6ef7);
    color: #fff;
    font-weight: 600;
  }
  
  /* Modal — le conteneur catsEl utilisé dans _openIconModal est maintenant
     fg-icon-swiper-section directement intégré dans box */
  /* .fg-icon-picker-box .fg-icon-swiper-section — inherits transparent/no-border from base */
  
  /* Loading state pour select async */
  .fg-option-loading {
    padding: 10px 14px;
    color: var(--fg-text-muted);
    font-size: 13px;
    text-align: center;
    font-style: italic;
  }
  
  /* Loading state pour choices async */
  .fg-choices-loading {
    padding: 8px;
    color: var(--fg-text-muted);
    font-size: 13px;
    font-style: italic;
  }

  /* Loading state pour la liste "enfant" d'un champ cascading (wilaya→commune,
     etc.) — affiché pendant la résolution de l'endpoint de ce niveau, puis
     retiré dès que les options sont rendues (cf. _buildCascading). La
     direction du flex row s'inverse automatiquement en RTL via .fg-rtl
     (direction: rtl), sans règle dédiée nécessaire. */
  .fg-option-loading-cascading {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 14px;
    color: var(--fg-text-muted);
    font-size: 13px;
  }
  .fg-cascading-spinner {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    border: 2px solid var(--fg-border);
    border-top-color: var(--fg-accent, #4f6ef7);
    border-radius: 50%;
    animation: fg-spin 0.6s linear infinite;
  }
  /* État d'erreur : le spinner est retiré du DOM (cf. JS), seul le texte
     reste — on le distingue visuellement en rouge plutôt qu'en gris muet. */
  .fg-option-loading-cascading.fg-option-loading-error {
    color: var(--fg-red, #f75f6e);
  }
  
  /* ══════════════════════════════════════════════════════════════
     ICON GRID — grille inline (type:'icons')
  ══════════════════════════════════════════════════════════════ */

  .fg-icons-picker-wrapper {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--fg-border);
    border-radius: var(--fg-radius);
    background: var(--fg-surface2);
    overflow: hidden;
    min-width: 0;
    width: 100%;
    box-sizing: border-box;
    transition: border-color 0.18s, box-shadow 0.18s;
  }

  .fg-icons-picker-wrapper:focus-within {
    border-color: var(--fg-border-focus);
    box-shadow: 0 0 0 3px var(--fg-accent-ring);
  }

  /* En-tête : recherche + couleur */
  .fg-icons-picker-header {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    padding: 8px 10px;
    border-bottom: 1px solid var(--fg-border);
    background: var(--fg-surface);
    min-width: 0;
  }

  /* Nom de classe corrigé : _buildSearch() pose «fg-search-field-wrapper»
     (et non «fg-search-wrapper») — cette règle ne s'appliquait donc jamais.
     flex-basis:140px sert de largeur «préférée» pour un calcul de
     retour à la ligne correct (cf. flex-wrap ci-dessus) ; min-width:0 reste
     un filet de sécurité pour le cas intermédiaire ou la ligne est presque
     assez large. */
  .fg-icons-picker-header .fg-search-field-wrapper {
    flex: 1 1 140px;
    min-width: 0;
  }

  /* Couleur compacte dans le header */
  .fg-icons-color-field {
    flex: 0 0 130px;
    border: 1px solid var(--fg-border);
    border-radius: var(--fg-radius);
    height: var(--fg-field-h);
    box-sizing: border-box;
  }

  /* Bouton "Agrandir" (.fg-icons-color-expand-btn) du color-picker des
     icônes — posé en sibling de .fg-icons-color-field dans le header (cf.
     _buildIconsPicker, form_generator.js), pas en overlay enfant comme son
     équivalent richtext : sur ce champ compact (130px), un overlay
     recouvrirait la pastille ou le champ hex. Même teinte/style "outline"
     que .fg-gps-btn.fg-gps-expand-btn pour rester cohérent dans tout le
     formulaire : action d'affichage uniquement, distincte visuellement des
     actions qui modifient la valeur du champ (ex. la pastille elle-même). */
  .fg-icons-color-expand-btn {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Carré, comme .fg-gps-btn.fg-gps-expand-btn (width = height =
       var(--fg-field-h)) — auparavant 28px de large pour var(--fg-field-h)
       de haut, donc rectangulaire et visuellement incohérent avec son
       équivalent GPS. */
    width: var(--fg-field-h);
    height: var(--fg-field-h);
    box-sizing: border-box;
    border: 1px solid color-mix(in srgb, var(--fg-accent) 40%, var(--fg-border));
    border-radius: var(--fg-radius);
    background: color-mix(in srgb, var(--fg-accent) 12%, var(--fg-surface));
    color: var(--fg-accent);
    cursor: pointer;
    padding: 0;
    overflow: hidden; /* clippe l'animation .fg-ripple-host (_ripple()) */
    transition: background 0.15s, color 0.15s, opacity 0.22s cubic-bezier(0.22, 1, 0.36, 1);
  }
  .fg-icons-color-expand-btn svg {
    color: var(--fg-accent);
    stroke: var(--fg-accent);
  }
  .fg-icons-color-expand-btn:hover {
    background: color-mix(in srgb, var(--fg-accent) 22%, var(--fg-surface));
  }
  .fg-icons-color-expand-btn:focus-visible {
    box-shadow: inset 0 0 0 2px var(--fg-border-focus);
    outline: none;
  }

  /* Bouton "Agrandir" (.fg-icon-dropdown-expand-btn) du dropdown de
     sélection d'icône (cf. _buildIconDropdown/_fgOpenIconDropdownExpandPopup,
     form_generator.js) — posé en sibling du color-picker dans le header du
     dropdown, même style "outline" que .fg-icons-color-expand-btn/
     .fg-gps-btn.fg-gps-expand-btn pour rester cohérent dans tout le
     formulaire. */
  .fg-icon-dropdown-expand-btn {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: var(--fg-field-h);
    height: var(--fg-field-h);
    box-sizing: border-box;
    border: 1px solid color-mix(in srgb, var(--fg-accent) 40%, var(--fg-border));
    border-radius: var(--fg-radius);
    background: color-mix(in srgb, var(--fg-accent) 12%, var(--fg-surface));
    color: var(--fg-accent);
    cursor: pointer;
    padding: 0;
    overflow: hidden; /* clippe l'animation .fg-ripple-host (_ripple()) */
    transition: background 0.15s, color 0.15s, opacity 0.22s cubic-bezier(0.22, 1, 0.36, 1);
  }
  .fg-icon-dropdown-expand-btn svg {
    color: var(--fg-accent);
    stroke: var(--fg-accent);
  }
  .fg-icon-dropdown-expand-btn:hover {
    background: color-mix(in srgb, var(--fg-accent) 22%, var(--fg-surface));
  }
  .fg-icon-dropdown-expand-btn:focus-visible {
    box-shadow: inset 0 0 0 2px var(--fg-border-focus);
    outline: none;
  }

  /* ── Mobile : "Rechercher" + "Couleur" + bouton "Agrandir" sur UNE
     seule ligne ────────────────────────────────────────────────────
     Par défaut (règles desktop ci-dessus), .fg-icons-picker-header et
     .fg-icon-dropdown-header sont en flex-wrap:wrap : pensé pour un champ
     déclencheur ponctuellement étroit en desktop (ex. grille à colonnes
     serrées), ce comportement fait presque toujours passer le champ
     recherche seul à la ligne du dessous sur un écran de téléphone (sa
     largeur "confort" de 140px ne tient déjà quasiment jamais à côté
     des 130px de la couleur + 44px du bouton sur ~360px de large en
     tenant compte du padding du header).
     On force donc une seule ligne (nowrap) et on redéfinit les largeurs
     "confort" desktop comme de simples largeurs de départ, réellement
     compressibles :
       - recherche : min-width déjà à 0 en desktop pour les deux contextes
         (picker inline ET dropdown, cf. .fg-icons-picker-header .fg-search-
         field-wrapper / .fg-icon-search-container ci-dessus) — la règle
         mobile ci-dessous ne fait plus que le confirmer explicitement.
         C'est elle qui absorbe le manque de place en priorité, pas ses
         voisins.
       - couleur : 130px → 84px. La pastille + le début du code hex
         restent lisibles ; le hex défile nativement au focus si besoin.
       - bouton "Agrandir" : inchangé (flex:0 0 auto, déjà insensible au
         rétrécissement) — c'est une cible tactile, elle ne doit jamais
         se compresser. */
  @media (max-width: 640px) {
    .fg-icons-picker-header,
    .fg-icon-dropdown-header {
      flex-wrap: nowrap;
      gap: 6px;
    }
    .fg-icon-search-container {
      min-width: 0;
    }
    .fg-icons-color-field,
    .fg-icon-color-row {
      flex: 0 0 84px;
      width: 84px;
    }
  }

  /* ── Champ recherche élargi au focus (mobile ou champ <200px) ───────
     Classe .fg-icon-search-expanded posée par _fgWireIconSearchExpand()
     (form_generator.js) sur le header au focus de l'input recherche,
     retirée (avec un léger différé, le temps de l'animation de retour) au
     blur. position:relative sur le header sert d'ancrage pour l'enfant
     position:absolute que devient le champ recherche pendant l'agrandissement.
     Le champ recherche sort alors du flux flex normal du header mais
     s'arrête avant le champ couleur, qui reste visible et utilisable : seuls
     le champ recherche et le champ couleur sont donc visibles pendant
     l'agrandissement. Le bouton "Agrandir" s'efface entièrement et la
     couleur glisse jusqu'à l'extrémité qu'il libère — ces deux animations,
     comme la largeur/position de la recherche, sont entièrement pilotées en
     JS (opacity/left en style inline) plutôt qu'en CSS pur, pour rester
     synchronisées avec elle dans les deux sens (cf. expand()/collapse()
     dans _fgWireIconSearchExpand).
     Le positionnement précis (position/left/right/top/bottom/width/height)
     et l'animation d'agrandissement/rétrécissement sont entièrement pilotés
     en JS par _fgWireIconSearchExpand() : les coordonnées cible dépendent
     de la position réelle du champ couleur et du bouton "Agrandir"
     (variable selon le contexte inline/dropdown et le sens LTR/RTL), donc
     pas exprimables en simples valeurs CSS fixes. Cette règle ne porte donc
     plus que ce qui reste statique : la mise au premier plan pendant
     l'agrandissement. */
  .fg-icons-picker-header,
  .fg-icon-dropdown-header {
    position: relative;
  }

  .fg-icons-picker-header.fg-icon-search-expanded .fg-search-field-wrapper,
  .fg-icon-dropdown-header.fg-icon-search-expanded .fg-icon-search-container {
    z-index: 5;
    min-width: 0;
  }

  /* Léger effet de "soulèvement" pendant l'agrandissement — box-shadow
     est déjà transitionnable sur .fg-icon-search-field-wrapper (règle
     desktop plus haut : "transition: border-color 0.18s, box-shadow
     0.18s"). Ajouté explicitement ici pour .fg-search-field-wrapper
     (picker inline), qui n'a pas cette transition par défaut. */
  .fg-search-field-wrapper {
    transition: box-shadow 0.18s;
  }
  .fg-icons-picker-header.fg-icon-search-expanded .fg-search-field-wrapper,
  .fg-icon-dropdown-header.fg-icon-search-expanded .fg-icon-search-field-wrapper {
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
  }

  /* Swiper catégories */
  .fg-icons-picker-wrapper .fg-icon-swiper-section {
    padding: 6px 10px;
    border-bottom: 1px solid var(--fg-border);
    background: var(--fg-surface);
  }

  .fg-icons-picker-wrapper .fg-icon-swiper-prev {
    left: 10px;
  }
  .fg-icons-picker-wrapper .fg-icon-swiper-next {
    right: 10px;
  }

  /* Grille scrollable */
  .fg-icons-inline-grid {
    max-height: 240px;
    overflow-y: auto;
    padding: 10px;
  }

  .fg-icons-inline-grid .fg-icon-item:hover {
    border-color: var(--fg-accent);
    background: var(--fg-accent-glow);
    transform: scale(1.12);
    box-shadow: 0 4px 12px var(--fg-accent-glow);
  }

  .fg-icons-inline-grid .fg-icon-item.selected {
    border-color: var(--fg-accent);
    background: var(--fg-accent-glow);
    box-shadow: 0 0 0 2px var(--fg-accent-ring), 0 4px 12px var(--fg-accent-glow);
    transform: scale(1.08);
  }

  /* ── GPS wrapper — même style que fg-icons-picker-wrapper ── */
  .fg-gps-wrapper {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--fg-border);
    border-radius: var(--fg-radius);
    background: var(--fg-surface);
    overflow: hidden;
    transition: border-color 0.18s, box-shadow 0.18s;
    padding: 10px;
    gap: 8px;
  }
  .fg-gps-wrapper:focus-within {
    border-color: var(--fg-border-focus);
    box-shadow: 0 0 0 3px var(--fg-accent-ring);
  }
/* ══════════════════════════════════════════════════════════════════════════
   RTL — Droite à gauche (arabe, hébreu, persan, etc.)
   Appliqué via .fg-rtl posé sur le conteneur du formulaire
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 0. Direction globale ───────────────────────────────────────────────── */
.fg-rtl { direction: rtl; text-align: right; }
.fg-rtl .fg-label,
.fg-rtl .fg-hint,
.fg-rtl .fg-error { text-align: right; }
.fg-rtl .fg-required { margin-right: 2px; margin-left: 0; }

/* ── 1. Inputs / Textarea ───────────────────────────────────────────────── */
.fg-rtl .fg-input,
.fg-rtl .fg-textarea { direction: rtl; }
.fg-rtl .fg-input::placeholder,
.fg-rtl .fg-textarea::placeholder { text-align: right; }
/* number : toujours centré */
/*.fg-rtl .fg-input[type="number"] { direction: ltr; }*/
/* tel : ordre LTR mais aligné à droite (ex: +213 674 11 05 32) */
.fg-rtl .fg-input[type="tel"] { direction: ltr; text-align: right; }

/* ── 2. Bouton copier — à gauche (position:absolute) ────────────────────── */
.fg-rtl .fg-copy-btn {
  right: auto;
  left: 8px;
}
/* Bouton "Agrandir" du richtext : bascule à gauche en RTL, même bord que
   le bouton copier (cf. .fg-rtl .fg-copy-btn ci-dessus) — les deux
   overlays partagent donc désormais le même coin (8px), cf. note plus
   haut dans la règle de base sur le chevauchement possible avec le
   bouton copier lorsque les deux sont visibles simultanément. */
.fg-rtl .fg-richtext-expand-btn {
  right: auto;
  left: 8px;
}
.fg-rtl .fg-input-wrapper .fg-input {
  padding-right: 14px;
  padding-left: 34px;
}
.fg-rtl .fg-icon-body .fg-copy-btn {
  right: auto;
  left: 8px;
}
.fg-rtl .fg-icon-body .fg-input {
  padding-right: 14px;
  padding-left: 34px;
}

/* ── 3. Icône inline — à droite, body à gauche ──────────────────────────── */
/* .fg-icon-wrapper > .fg-icon-preview + .fg-icon-body                       */
/* row-reverse → preview bascule visuellement à droite                       */
/* Inverser le séparateur : border-right → border-left */
.fg-rtl .fg-icon-preview {
  border-right: none;
  border-left: 1px solid var(--fg-border);
}
/* Input dans le body : inverser le padding du copy btn */
.fg-rtl .fg-icon-wrapper .fg-input,
.fg-rtl .fg-icon-body .fg-input {
  padding-right: 14px;
  padding-left: 34px;
  text-align: right;
  direction: rtl;
}

/* ── 4. Mot de passe ────────────────────────────────────────────────────── */
/* Structure DOM LTR : [input][eye][gen-btn]                                 */
/* Structure visuelle RTL souhaitée : [input][eye][gen-btn]                 */
/*   → gen-btn à l'extrême droite, eye juste à sa gauche, input à gauche    */
/*   row-reverse + orders : input(order:2) | eye(order:1) | gen(order:0)    */
.fg-rtl .fg-pwd-wrapper {
  flex-direction: row-reverse;
}
.fg-rtl .fg-pwd-wrapper .fg-input {
  order: 2;
  border-radius: 0;
  text-align: right;
  direction: rtl;
  border-right: none;
  border-left: none;
}
/* L'œil est adjacent au générateur (à sa gauche en RTL) */
.fg-rtl .fg-pwd-eye {
  order: 1;
  border-radius: 0;
  border-left: 1px solid var(--fg-border);
  border-right: 1px solid var(--fg-border);
}
/* Le générateur est à l'extrême droite en RTL */
.fg-rtl .fg-pwd-gen-btn {
  order: 0;
  border-radius: 0 var(--fg-radius) var(--fg-radius) 0;
  border-right: none;
  border-left: none;
}
/* Premier enfant visible (input, ordre 2 → visuellement à gauche) */
.fg-rtl .fg-pwd-wrapper .fg-input:first-child {
  border-radius: var(--fg-radius) 0 0 var(--fg-radius);
}
/* Popup générateur : ouverte à droite (gérée en JS via style.right=0) */
.fg-rtl .fg-pwd-gen-popup {
  left: auto;
  right: 0;
}

/* ── 5. Recherche — loupe à droite, croix à gauche ─────────────────────── */
/* .fg-search-icon et .fg-search-clear sont en position:absolute            */
.fg-rtl .fg-search-icon {
  left: auto;
  right: 12px;
}
.fg-rtl .fg-search-clear {
  right: auto;
  left: 12px;
}
/*.fg-rtl .fg-search-input {
  padding-left: 40px;
  padding-right: 40px;
  text-align: right;
  direction: rtl;
}*/

/* ── 6. Richtext ────────────────────────────────────────────────────────── */
.fg-rtl .fg-richtext-wrapper,
.fg-rtl .ql-editor,
.fg-rtl .ql-container { direction: rtl; text-align: right; }

/* Verifie sur le vrai quill_snow.css : .ql-toolbar n'est pas un conteneur
   flex par defaut (les .ql-formats sont en inline-block, les boutons en
   float:left, clearfix via ::after aux deux niveaux).

   Point cle : flex-direction:row (valeur par defaut, implicite) N'EST PAS
   figee physiquement de gauche a droite — son axe principal suit le sens
   inline-start -> inline-end, lui-meme determine par `direction`. Or
   .ql-toolbar et .ql-formats HERITENT deja de `direction: rtl` (pose sur
   .fg-richtext-wrapper, cf. regle ci-dessus). Il suffit donc de les passer
   en display:flex : l'ordre des items se reordonne AUTOMATIQUEMENT de
   droite a gauche, sans flex-direction:row-reverse — qui annulerait cette
   inversion deja apportee par `direction:rtl` (double inversion = retour a
   un ordre visuellement LTR, d'ou le probleme observe). On applique ce
   display:flex aux DEUX niveaux pour un miroir complet (blocs ET icones
   dans l'ordre inverse) :
     - niveau 1 (.ql-toolbar)  : reordonne les groupes .ql-formats entre
       eux (header, premier en LTR => positionne a l'extreme droite).
     - niveau 2 (.ql-formats)  : reordonne les boutons/pickers a
       l'INTERIEUR de chaque groupe (ex. gras/italique/souligne/barre
       devient barre/souligne/italique/gras).
   Le contenu de chaque bouton (icone SVG) n'est jamais transforme : seule
   sa POSITION change via l'ordre flex, jamais son rendu interne — les
   icones restent donc lisibles, non deformees. Pas de transform:scaleX,
   donc aucun risque sur le containing-block des dropdowns Quill
   (position:absolute) ni sur le contexte d'empilement. */
.fg-rtl .fg-richtext-wrapper .ql-toolbar {
  display: flex;
}
.fg-rtl .fg-richtext-wrapper .ql-toolbar .ql-formats {
  display: flex;
  align-items: center;
}
/* Les clearfix ::after (clear:both, display:table) herites de
   quill.snow.css n'ont plus lieu d'etre a aucun des deux niveaux : en
   flex il n'y a plus de flottant a contenir (float ignore sur les
   enfants directs d'un conteneur flex, cf. spec CSS Flexbox). */
.fg-rtl .fg-richtext-wrapper .ql-toolbar::after,
.fg-rtl .fg-richtext-wrapper .ql-formats::after {
  display: none;
}
/* margin-right:15px (quill.snow.css) est une propriete PHYSIQUE : elle
   n'est jamais retournee automatiquement par `direction` ou flexbox,
   contrairement a l'ordre des items. Elle continue donc d'espacer chaque
   groupe de sa droite physique meme une fois l'ordre inverse par le flex
   RTL ci-dessus — cote desormais errone, puisque le groupe SUIVANT (en
   ordre visuel) se trouve maintenant a sa gauche. Sans ce swap, les
   groupes se retrouveraient colles a gauche avec un espace inutile a
   droite. */
.fg-rtl .fg-richtext-wrapper .ql-toolbar .ql-formats {
  margin-right: 0;
  margin-left: 15px;
}

/* Bloc "Titre" (header/police/taille) : quill.snow.css positionne le
   chevron SVG en dur via position:absolute + right:0, DANS une
   .ql-picker-label qui fait width:100% de son .ql-picker parent.
   Le correctif precedent se contentait d'inverser ce right:0 en left:0 —
   mais restant en position:absolute, le chevron reste ancre au bord de
   la boite width:100%, PAS a cote du texte. Des que le champ richtext
   s'agrandit (donc .ql-picker s'elargit), le chevron derive loin du
   texte et peut chevaucher .ql-picker-options, rendant son contenu
   illisible — c'est le bug rapporte.
   Solution robuste : abandonner position:absolute et utiliser la meme
   technique deja appliquee sur .ql-toolbar/.ql-formats plus haut —
   display:flex sur un conteneur qui herite deja de direction:rtl
   (.fg-richtext-wrapper) reordonne AUTOMATIQUEMENT ses enfants de droite
   a gauche. Le ::before (texte, genere avant les autres enfants) se
   retrouve donc a droite, le <svg> (enfant reel suivant dans le DOM) a
   gauche, colle au texte quelle que soit la largeur — plus de calcul de
   position en dur.
   Les pickers couleur/fond (.ql-color-picker) et le picker d'icones
   (.ql-icon-picker) sont traites separement juste apres, car leur
   contenu (pastille de couleur / icone d'apercu) differe du texte des
   pickers "Titre"/police/taille — mais suivent le meme principe. */
.fg-rtl .fg-richtext-wrapper .ql-picker:not(.ql-color-picker):not(.ql-icon-picker) .ql-picker-label {
  display: flex;
  align-items: center;
  gap: 4px;
  padding-left: 8px;
  padding-right: 8px;
}
.fg-rtl .fg-richtext-wrapper .ql-picker:not(.ql-color-picker):not(.ql-icon-picker) .ql-picker-label svg {
  position: static;
  right: auto;
  left: auto;
  margin-top: 0;
  flex-shrink: 0;
}

/* Pickers couleur/fond et icones : meme principe (flex + direction:rtl
   heritee => chevron automatiquement a gauche), sans toucher a leur
   grille interne de pastilles/icones (non impactee par ce display:flex,
   qui ne s'applique qu'a .ql-picker-label lui-meme). */
.fg-rtl .fg-richtext-wrapper .ql-color-picker .ql-picker-label,
.fg-rtl .fg-richtext-wrapper .ql-icon-picker .ql-picker-label {
  display: flex;
  align-items: center;
}
.fg-rtl .fg-richtext-wrapper .ql-color-picker .ql-picker-label svg,
.fg-rtl .fg-richtext-wrapper .ql-icon-picker .ql-picker-label svg {
  position: static;
  right: auto;
  left: auto;
  margin-top: 0;
  flex-shrink: 0;
}


/* Liste deroulante du picker (Normal / Titre 1 / Titre 2 / Titre 3...) :
   alignee et lue de droite a gauche comme le reste du champ. */
.fg-rtl .fg-richtext-wrapper .ql-picker-options,
.fg-rtl .fg-richtext-wrapper .ql-picker-item {
  text-align: right;
  direction: rtl;
}

/* ── 7. Select / Dropdown ───────────────────────────────────────────────── */
.fg-rtl .fg-select-trigger { flex-direction: row-reverse; }
.fg-rtl .fg-select-trigger .fg-select-value { text-align: right; flex: 1; }
.fg-rtl .fg-chevron { order: -1; margin: 0; }
.fg-dropdown-teleport.fg-rtl { direction: rtl; text-align: right; }
.fg-dropdown-teleport.fg-rtl .fg-options-list,
.fg-dropdown-teleport.fg-rtl .fg-no-results { text-align: right; direction: rtl; }
/*.fg-dropdown-teleport.fg-rtl .fg-option { flex-direction: row-reverse; text-align: right; }*/
.fg-dropdown-teleport.fg-rtl .fg-option-icon { margin-right: 0; margin-left: 8px; }
.fg-rtl .fg-multi-close-row { flex-direction: row-reverse; }

/* ── 8. Checkbox / Radio ────────────────────────────────────────────────── */
.fg-rtl .fg-choice-item { flex-direction: row-reverse; justify-content: flex-end; }
.fg-rtl .fg-choice-indicator { order: 1; margin-right: 0; margin-left: 0; }
.fg-rtl .fg-choice-icon { order: 0; margin-right: 6px; margin-left: 0; }
.fg-rtl .fg-choice-label { text-align: right; margin-right: 8px; margin-left: 0; order: -1; }

/* ── 9. Toggle ──────────────────────────────────────────────────────────── */
/* DOM : track (tête, fixe) puis desc (flex:1) - cf. _buildToggle/
   _buildToggleGroup. Contrairement à .fg-choice-item, PAS de
   flex-direction: row-reverse ici : le conteneur porte déjà dir="rtl"
   (cf. setDir()), et le "row" natif sous direction:rtl place tout seul le
   premier enfant DOM (track) à droite - un row-reverse en plus produirait
   un double-renversement et ramènerait le track à gauche (constaté à
   l'usage). Seul le text-align du texte doit encore être inversé. */
.fg-rtl .fg-toggle-desc { text-align: right; }

/* ── 10. Color — pastille à droite (position:absolute left→right) ────────── */
/* .fg-clr-swatch est en position:absolute !important ; left:10px !important */
.fg-rtl .fg-color-picker-field .fg-clr-swatch,
.fg-rtl .clr-field button.fg-clr-swatch {
  left: auto !important;
  right: 10px !important;
}
.fg-rtl .fg-color-picker-hex {
  padding-left: 12px;
  padding-right: 40px;
  text-align: right;  /* texte aligné à droite, collé à la pastille           */
  direction: ltr;     /* direction: rtl inverserait en FF0000# — interdit     */
  unicode-bidi: plaintext; /* assure que ltr prévaut même sous direction rtl  */
}

/* RTL — séparateur du côté droit */
.fg-rtl .fg-double-wrapper > .fg-field + .fg-field {
  border-left:  none;
  border-right: 1px solid var(--fg-border);
}

/* ── 11. Double — inversion de l'ordre ──────────────────────────────────── */
/*.fg-rtl .fg-double-wrapper { flex-direction: row-reverse; }*/
/* En RTL, dir='rtl' inverse automatiquement l'ordre visuel des champs */
.fg-rtl .fg-double-wrapper > .fg-field:has(.fg-btn) {
  border-left:  1px solid var(--fg-border);
  border-right: none;
  padding-left: 0;
  padding-right: 8px;
}

/* ── 12. Bouton / Action ─────────────────────────────────────────────────── */
.fg-rtl .fg-btn { flex-direction: row-reverse; }
.fg-rtl .fg-btn .fg-btn-icon { margin-left: 0; margin-right: 6px; order: 1; }

/* ── 13. GPS ────────────────────────────────────────────────────────────── */
.fg-rtl .fg-gps-wrapper { direction: rtl; }
.fg-rtl .fg-gps-controls-row { flex-direction: row-reverse; }

/* ── 14. File upload ────────────────────────────────────────────────────── */
.fg-rtl .fg-file-zone { direction: rtl; }
.fg-rtl .fg-file-swiper-section { direction: rtl; }
/* Colonne de boutons utilitaires (remove/like/view) — cf. .fg-file-card-actions
   en base (top:8px; right:8px;). C'est le CONTENEUR qui porte le positionnement
   absolu, pas les boutons pris individuellement : on doit donc bien flipper
   .fg-file-card-actions (et non .fg-file-card-remove, qui n'a pas de `right`
   en LTR — cibler ce sélecteur ne produit aucun effet). Partagé par les 3
   contextes : card locale (multiple), card distante (--remote) et card unique
   (.fg-file-zone > .fg-file-card), donc une seule règle suffit pour les trois. */
.fg-rtl .fg-file-card-actions { right: auto; left: 8px; }
.fg-rtl .fg-file-card-info { text-align: right; }
/* En RTL, align-self: flex-end collerait le statut à gauche (début physique)
   on le ramène à droite (fin physique) avec flex-start dans un contexte rtl */
.fg-rtl .fg-file-status-bar { direction: rtl; align-self: flex-start; }

/* ── 15. Icon picker ────────────────────────────────────────────────────── */
.fg-rtl .fg-icon-swiper-section { direction: rtl; }
.fg-rtl .fg-icons-picker-header,
.fg-rtl .fg-icon-dropdown-header { flex-direction: row-reverse; }

/* ── 16. Number — flèches ────────────────────────────────────────────────── */
/* Structure : [minus][input][plus] → en RTL : [plus][input][minus]          */
/* Number : DOM inversé en JS [+][input][−] — bordures adaptées */
.fg-rtl .fg-num-btn.minus { border-left:  1px solid var(--fg-border); border-right: none; }
.fg-rtl .fg-num-btn.plus  { border-right: 1px solid var(--fg-border); border-left:  none; }

.fg-rtl .fg-number-wrapper .fg-input {
  text-align: center;
  direction: ltr;
}

/* ── 17. Cascading ───────────────────────────────────────────────────────── */
.fg-rtl .fg-cascading-wrapper { direction: rtl; }

/* ── 20. GPS — barre de contrôles ──────────────────────────────────────── */
.fg-rtl .fg-gps-search-icon {
  left: auto;
  right: 12px;
}
.fg-rtl .fg-gps-search-container .fg-search-input {
  padding-left: 14px;
  padding-right: 40px;
}

/* ── 21. Confirm popup ──────────────────────────────────────────────────── */
/* Positionnée via JS (right:auto/left:auto selon _isRTL) */
.fg-rtl .fg-confirm-popup { direction: rtl; }
.fg-rtl .fg-confirm-actions { flex-direction: row-reverse; }

/* ── 22. Dropdown téléporté — options avec icône ────────────────────────── */
/* margin-left sur fg-option-icon (devenu "avant" l'icône en RTL) */
.fg-dropdown-teleport.fg-rtl .fg-option-avatar { margin-left: 8px; margin-right: 0; }
/* Badge multi-select */
.fg-rtl .fg-multi-badge { margin-right: 0; margin-left: 4px; }
.fg-rtl .fg-multi-close { margin-left: 0; margin-right: 4px; }

/* ── Groupes de champs — miroir RTL ──────────────────────────────────────── */
.fg-rtl .fg-group-legend { flex-direction: row-reverse; }
.fg-rtl .fg-group.fg-group-collapsed .fg-group-toggle { transform: rotate(90deg); }

/* ── Compteur "n / total" GLightbox ──────────────────────────────────────── */
/* Déplacé vers plugins/glightbox-counter.css (classe .glightbox-counter) :
   ce compteur est un utilitaire GLightbox générique (attachGLightboxCounter,
   cf. plugins/glightbox.js), pas une brique spécifique au formulaire.
   Charger plugins/glightbox-counter.css en plus de ce fichier partout où
   une galerie GLightbox avec compteur est utilisée. */