        :root {
            --cream:      #F2EAD8;
            --cream-dark: #EBE0C8;
            --orange:     #B84B0C;
            --orange-lt:  #C95A18;
            --text:       #1A1208;
            --text-muted: #7A6E62;
            --text-light: #A89D92;
            --border:     rgba(26,18,8,0.1);
            --border-md:  rgba(26,18,8,0.16);
            --white:      #FFFFFF;
            --card-bg:    #FAF6F0;
        }

        *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
        html { font-size: 16px; }

        body {
            font-family: 'Jost', sans-serif;
            background: var(--cream);
            color: var(--text);
            line-height: 1.6;
            background-image: radial-gradient(circle, rgba(26,18,8,0.09) 1px, transparent 1px);
            background-size: 28px 28px;
            padding-bottom: 90px;
            min-height: 100vh;
            display: flex;
            flex-direction: column;
        }

        h1, h2, h3 { font-family: 'Playfair Display', Georgia, serif; }

        /* ── APP NAVBAR ── */
        .app-nav {
            position: sticky;
            top: 0; z-index: 100;
            background: var(--white);
            border-bottom: 1px solid var(--border);
            display: flex;
            align-items: center;
            padding: 0 28px;
            height: 54px;
        }

        .app-logo {
            font-family: 'Jost', sans-serif;
            font-weight: 600;
            font-size: 0.95rem;
            color: var(--text);
            text-decoration: none;
            display: flex;
            align-items: center;
            gap: 5px;
            flex-shrink: 0;
        }
        .logo-star { color: var(--orange); }

        .app-nav__tabs {
            display: flex;
            align-items: center;
            flex: 1;
            justify-content: center;
            gap: 0;
        }

        .nav-tab {
            display: inline-flex;
            align-items: center;
            height: 54px;
            padding: 0 18px;
            font-size: 0.84rem;
            font-weight: 500;
            color: var(--text-muted);
            text-decoration: none;
            border-bottom: 2px solid transparent;
            transition: color 0.2s, border-color 0.2s;
        }
        .nav-tab:hover { color: var(--text); }
        .nav-tab.active {
            color: var(--orange);
            border-bottom-color: var(--orange);
            font-weight: 600;
        }

        .app-nav__right {
            display: flex;
            align-items: center;
            gap: 10px;
            flex-shrink: 0;
        }

        .nav-clock {
            width: 30px; height: 30px;
            display: flex; align-items: center; justify-content: center;
            color: var(--text-muted);
            font-size: 1rem;
            cursor: pointer;
        }

        .nav-user {
            display: flex;
            align-items: center;
            gap: 8px;
            cursor: pointer;
        }

        .user-avatar {
            width: 30px; height: 30px;
            border-radius: 50%;
            background: var(--orange);
            color: white;
            display: flex; align-items: center; justify-content: center;
            font-size: 0.65rem;
            font-weight: 700;
            letter-spacing: 0.03em;
        }

        .user-plan {
            font-size: 0.63rem;
            font-weight: 700;
            letter-spacing: 0.07em;
            text-transform: uppercase;
            color: var(--text-muted);
            background: var(--cream-dark);
            border: 1px solid var(--border-md);
            border-radius: 4px;
            padding: 3px 7px;
        }

        .user-arrow {
            font-size: 0.65rem;
            color: var(--text-light);
        }

        /* ── MAIN ── */
        .main {
            max-width: 700px;
            margin: 0 auto;
            padding: 28px 20px 16px;
            flex: 1 0 auto;
            /* CORRECTION CIBLÉE — même cause exacte que .type-shortcuts
               ci-dessous (voir son commentaire) : les marges horizontales
               auto (margin:0 auto) désactivent l'étirement flex habituel
               et font se dimensionner .main sur le contenu le plus large
               de tout son sous-arbre (shrink-to-fit), malgré
               overflow-x:auto plus bas dans l'arbre (carrousel). Un
               min-width:0 seul est sans effet ici : ce n'est pas un
               plancher qui bloque un rétrécissement, c'est le mode de
               calcul (shrink-to-fit) qui ignore la largeur disponible.
               width: min(100%, 700px) donne une valeur DÉFINIE (jamais
               "auto"), qui court-circuite ce calcul tout en conservant
               exactement le plafond de 700px déjà existant. */
            width: min(100%, 700px);
        }

        .page-title {
            font-size: 1.65rem;
            font-weight: 700;
            letter-spacing: -0.02em;
            margin-bottom: 4px;
        }

        .page-subtitle {
            font-size: 0.83rem;
            font-weight: 500;
            color: var(--text-muted);
            margin-bottom: 22px;
        }
        .page-subtitle em { color: var(--orange); font-style: normal; }

        /* ── PROGRESS ── */
        .progress-card {
            background: var(--white);
            border: 1px solid var(--border-md);
            border-radius: 10px;
            padding: 12px 16px 10px;
            margin-bottom: 16px;
        }

        .progress-top {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 8px;
        }

        .progress-label {
            font-size: 0.76rem;
            font-weight: 600;
            color: var(--orange);
        }

        .progress-plan {
            font-size: 0.6rem;
            font-weight: 700;
            letter-spacing: 0.07em;
            text-transform: uppercase;
            color: var(--text-muted);
            background: var(--cream-dark);
            border: 1px solid var(--border-md);
            border-radius: 4px;
            padding: 3px 8px;
        }

        .progress-track {
            height: 4px;
            background: rgba(26,18,8,0.08);
            border-radius: 2px;
            overflow: hidden;
            margin-bottom: 8px;
        }
        .progress-fill {
            height: 100%;
            width: 10%;
            background: var(--orange);
            border-radius: 2px;
        }

        .progress-diamond {
            text-align: center;
            font-size: 0.65rem;
            color: var(--orange);
        }

        /* ── SECTION CARD ── */
        .scard {
            background: var(--white);
            border: 1px solid var(--border-md);
            border-radius: 12px;
            padding: 18px 18px 18px;
            margin-bottom: 14px;
        }

        .slabel {
            font-size: 0.68rem;
            font-weight: 600;
            letter-spacing: 0.1em;
            text-transform: uppercase;
            color: var(--text-muted);
            margin-bottom: 12px;
        }

        /* ── SUJET ── */
        .sujet-input {
            width: 100%;
            border: 1.5px solid var(--border-md);
            border-radius: 8px;
            padding: 11px 13px;
            font-family: 'Jost', sans-serif;
            font-size: 0.86rem;
            color: var(--text);
            background: var(--white);
            outline: none;
            transition: border-color 0.2s, box-shadow 0.2s;
            margin-bottom: 8px;
        }
        .sujet-input:focus {
            border-color: var(--orange);
            box-shadow: 0 0 0 3px rgba(184,75,12,0.08);
        }
        .sujet-input::placeholder { color: var(--text-muted); }
        .input-error {
            border-color: #c0392b;
        }

        .sujet-hint {
            font-size: 0.76rem;
            font-weight: 500;
            color: var(--text-muted);
        }

        /* ── HISTORIQUE SUJETS ── */
        .subject-wrap { position: relative; }
        .subject-history {
            display: none;
            position: absolute;
            top: calc(100% + 2px); left: 0; right: 0;
            background: var(--white);
            border: 1px solid var(--border-md);
            border-radius: 10px;
            box-shadow: 0 6px 20px rgba(26,18,8,0.10);
            z-index: 150;
            overflow: hidden;
        }
        .subject-history.open { display: block; }
        .subject-history-item {
            padding: 9px 14px;
            font-size: 0.84rem;
            color: var(--text-muted);
            cursor: pointer;
            border-bottom: 1px solid var(--border);
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            transition: background 0.12s, color 0.12s;
        }
        .subject-history-item:last-child { border-bottom: none; }
        .subject-history-item:hover {
            background: rgba(184,75,12,0.04);
            color: var(--orange);
        }

        /* ── PHOTO ── */
        .photo-drop {
            border: 1.5px dashed var(--border-md);
            border-radius: 10px;
            padding: 36px 20px;
            text-align: center;
            cursor: pointer;
            transition: border-color 0.2s, background 0.2s;
        }
        .photo-drop:hover {
            border-color: var(--orange);
            background: rgba(184,75,12,0.02);
        }

        .photo-upload-icon {
            width: 38px; height: 38px;
            border-radius: 50%;
            border: 1.5px solid var(--border-md);
            display: flex; align-items: center; justify-content: center;
            margin: 0 auto 12px;
            font-size: 1rem;
            color: var(--text-muted);
        }

        .photo-main {
            font-size: 0.86rem;
            font-weight: 600;
            color: var(--text);
            margin-bottom: 4px;
        }

        .photo-cta {
            font-size: 0.83rem;
            color: var(--orange);
            font-weight: 500;
        }

        .photo-formats {
            font-size: 0.72rem;
            color: var(--text-muted);
            margin-top: 10px;
        }

        /* Masquage visuel accessible de #photoCaptureInput — technique
           validée par test-camera.html (test réel sur Android/Chrome) :
           le champ reste activable par son <label for="photoCaptureInput">,
           contrairement à display:none. Ne pas utiliser visibility:hidden
           ni disabled, qui désactiveraient l'activation native. */
        .visually-hidden-input {
            position: absolute;
            width: 1px;
            height: 1px;
            padding: 0;
            margin: -1px;
            overflow: hidden;
            clip: rect(0, 0, 0, 0);
            white-space: nowrap;
            border: 0;
        }

        /* Boutons mobiles « Choisir une photo » / « Prendre une photo » —
           masqués par défaut ; affichés uniquement sur téléphone via la
           media query @media (max-width: 480px) déjà utilisée par cette
           page. La zone de dépôt ordinateur n'est pas concernée. */
        .photo-mobile-actions {
            display: none;
            gap: 10px;
            margin-top: 14px;
            flex-wrap: wrap;
            justify-content: center;
        }
        .photo-mobile-btn {
            flex: 1 1 140px;
            max-width: 100%;
            padding: 12px 14px;
            border: 1.5px solid var(--orange);
            border-radius: 10px;
            background: var(--white);
            color: var(--orange);
            font-family: 'Jost', sans-serif;
            font-size: 0.83rem;
            font-weight: 600;
            cursor: pointer;
            transition: background 0.15s, color 0.15s;
        }
        .photo-mobile-btn:hover,
        .photo-mobile-btn:active {
            background: var(--orange);
            color: var(--white);
        }

        .photo-drop.drag-over {
            border-color: var(--orange);
            background: rgba(184,75,12,0.04);
        }
        #photoPreviewImg {
            max-width: 100%; max-height: 200px;
            border-radius: 8px; object-fit: contain;
            display: block; margin: 0 auto 10px;
        }
        .photo-preview-footer {
            display: flex; align-items: center;
            justify-content: space-between; gap: 8px;
        }
        .photo-filename {
            font-size: 0.78rem; color: var(--text-muted);
            overflow: hidden; text-overflow: ellipsis;
            white-space: nowrap; flex: 1;
        }
        .photo-remove {
            font-family: 'Jost', sans-serif;
            font-size: 0.7rem; font-weight: 600;
            width: 24px; height: 24px; border-radius: 50%;
            border: 1px solid var(--border-md);
            background: var(--cream-dark);
            color: var(--text-muted);
            cursor: pointer; flex-shrink: 0;
            display: flex; align-items: center; justify-content: center;
            transition: background 0.15s, color 0.15s, border-color 0.15s;
        }
        .photo-remove:hover {
            background: rgba(239,68,68,0.1);
            border-color: rgba(239,68,68,0.3);
            color: #b91c1c;
        }
        .photo-error {
            display: none;
            font-size: 0.78rem; font-weight: 600;
            color: #c0392b;
            background: rgba(192,57,43,0.08);
            border: 1px solid rgba(192,57,43,0.25);
            border-radius: 8px;
            padding: 9px 14px;
            margin-top: 8px;
        }

        /* ── PHOTOS SUPPLÉMENTAIRES (panneau repliable) ──
           Étape 1 : interface uniquement. Totalement indépendant de .photo-drop
           et de ses styles ci-dessus — aucun sélecteur partagé. */
        .extra-photos-toggle {
            display: flex;
            align-items: center;
            gap: 8px;
            width: 100%;
            border: none;
            background: var(--white);
            padding: 0;
            font-family: 'Jost', sans-serif;
            font-size: 0.86rem;
            font-weight: 600;
            color: var(--text);
            cursor: pointer;
            text-align: left;
            /* Neutralise le rendu natif (fond gris/noir) que certains
               navigateurs mobiles appliquent aux <button> non explicitement
               stylés, indépendamment du thème clair/sombre du site — sans
               ceci, un fond transparent ("none") laisse transparaître le
               thème système du téléphone plutôt que le fond réel de la
               carte. */
            appearance: none;
            -webkit-appearance: none;
        }
        .extra-photos-chevron {
            font-size: 0.7rem;
            color: var(--text-muted);
            flex-shrink: 0;
        }
        .extra-photos-count {
            color: var(--text-muted);
            font-weight: 500;
        }
        .extra-photos-panel {
            display: none;
            margin-top: 14px;
        }
        .extra-photos-panel.open {
            display: block;
        }
        .extra-photos-add-btn {
            padding: 10px 16px;
            border: 1.5px solid var(--orange);
            border-radius: 10px;
            background: var(--white);
            color: var(--orange);
            font-family: 'Jost', sans-serif;
            font-size: 0.83rem;
            font-weight: 600;
            cursor: pointer;
            transition: background 0.15s, color 0.15s;
            /* Même neutralisation du rendu natif mobile que .extra-photos-toggle
               ci-dessus — le fond/la bordure explicites définis plus haut
               doivent rester ceux de Flying Pub, jamais ceux du thème système
               du téléphone. */
            appearance: none;
            -webkit-appearance: none;
        }
        .extra-photos-add-btn:hover {
            background: var(--orange);
            color: var(--white);
        }
        /* Conteneur des miniatures — bande horizontale sur ordinateur et
           tablette (défilement si nécessaire). Sur téléphone, voir la
           media query ci-dessous : passage sur plusieurs lignes, sans
           défilement horizontal. */
        .extra-photos-thumbs {
            display: flex;
            gap: 10px;
            margin-top: 14px;
            overflow-x: auto;
        }
        /* Téléphone : suppression du défilement horizontal — la bande passe
           sur plusieurs lignes pour que toutes les miniatures restent
           visibles sans glisser latéralement, et pour ne pas entrer en
           conflit avec le défilement vertical de la page (geste tactile).
           Prépare aussi un futur réordonnancement au doigt plus confortable
           en disposition multi-lignes. Numérotation, suppression et taille
           des miniatures : strictement inchangées, seule la disposition
           change — CSS uniquement, aucune logique JavaScript concernée. */
        @media (max-width: 480px) {
            .extra-photos-thumbs {
                overflow-x: visible;
                flex-wrap: wrap;
            }
        }
        /* Message temporaire (jamais d'alert()) — même registre visuel que
           .photo-error ci-dessus, mais neutre/informatif plutôt que rouge. */
        .extra-photos-message {
            display: none;
            font-size: 0.78rem;
            font-weight: 500;
            color: var(--text-muted);
            background: var(--cream-dark);
            border: 1px solid var(--border-md);
            border-radius: 8px;
            padding: 9px 14px;
            margin-top: 14px;
        }
        .extra-photos-message.visible {
            display: block;
        }
        .extra-photo-thumb {
            display: flex;
            flex-direction: column;
            flex-shrink: 0;
            width: 72px;
        }
        .extra-photo-thumb-media {
            position: relative;
            width: 72px;
            height: 72px;
            border-radius: 10px;
            overflow: hidden;
            border: 1px solid var(--border-md);
        }
        .extra-photo-thumb-media img {
            width: 100%;
            height: 100%;
            object-fit: cover;
            display: block;
        }
        .extra-photo-thumb-number {
            position: absolute;
            top: 4px;
            left: 4px;
            min-width: 18px;
            height: 18px;
            padding: 0 4px;
            border-radius: 9px;
            background: rgba(26,18,8,0.65);
            color: var(--white);
            font-size: 0.68rem;
            font-weight: 600;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        .extra-photo-thumb-remove {
            position: absolute;
            top: 4px;
            right: 4px;
            width: 20px;
            height: 20px;
            border-radius: 50%;
            border: none;
            background: rgba(26,18,8,0.65);
            color: var(--white);
            font-size: 0.65rem;
            font-weight: 600;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            appearance: none;
            -webkit-appearance: none;
        }
        .extra-photo-thumb-remove:hover {
            background: #c0392b;
        }
        /* Poignée de déplacement — seul déclencheur du glisser (Pointer
           Events), jamais la photo elle-même ni le bouton de suppression.
           touch-action:none empêche le navigateur d'interpréter le geste
           comme un défilement de page ; user-select/-webkit-touch-callout
           empêchent la sélection de texte et le menu contextuel iOS sur
           appui prolongé. Cible tactile pleine largeur, hauteur dédiée
           distincte de la photo. */
        .extra-photo-thumb-handle {
            margin-top: 4px;
            height: 26px;
            border-radius: 8px;
            border: 1px solid var(--border-md);
            background: var(--cream-dark);
            color: var(--text-muted);
            font-size: 0.9rem;
            line-height: 1;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: grab;
            touch-action: none;
            user-select: none;
            -webkit-user-select: none;
            -webkit-touch-callout: none;
        }
        .extra-photo-thumb-handle.grabbing {
            cursor: grabbing;
            background: var(--orange);
            color: var(--white);
            border-color: var(--orange);
        }
        /* Retour visuel pendant le déplacement — sans animation : opacité
           réduite sur la miniature déplacée, contour net sur la cible de
           dépôt actuelle. */
        .extra-photo-thumb.dragging {
            opacity: 0.5;
        }
        .extra-photo-thumb.drop-target .extra-photo-thumb-media {
            outline: 2px solid var(--orange);
            outline-offset: 2px;
        }

        /* ── TYPE PUBLICATION ── */
        .type-grid {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 10px;
        }

        .type-card {
            border: 1.5px solid var(--border-md);
            border-radius: 10px;
            padding: 12px 10px 10px;
            text-align: center;
            cursor: pointer;
            position: relative;
            transition: border-color 0.2s, background 0.2s;
            background: var(--type-halo, none), var(--white);
            user-select: none;
        }
        .type-card:hover { border-color: var(--orange); }
        .type-card.active {
            border-color: var(--orange);
            background: var(--type-halo, none), rgba(184,75,12,0.04);
        }

        /* Dégradé par famille — occupe le tiers supérieur de la carte, part de
           la couleur réelle de la famille (celle déjà utilisée par les badges
           .style-badge--{type} de ce même fichier, section « Style de visuel »)
           puis s'estompe totalement vers le blanc avant .type-name/.type-desc.
           Stocké en variable (--type-halo) et combiné en second plan par
           .type-card/.type-card.active ci-dessus, afin qu'il reste visible
           aussi bien à l'état inactif qu'actif, sans dupliquer les règles de
           bordure/fond déjà existantes. */
        .type-card[data-type="actu"],
        .type-shortcut[data-type="actu"]          { --type-halo: linear-gradient(to bottom, rgba(184,75,12,0.22)  0%, rgba(184,75,12,0)  33%); }
        .type-card[data-type="mise-en-avant"],
        .type-shortcut[data-type="mise-en-avant"] { --type-halo: linear-gradient(to bottom, rgba(122,138,110,0.22) 0%, rgba(122,138,110,0) 33%); }
        .type-card[data-type="communique"],
        .type-shortcut[data-type="communique"]      { --type-halo: linear-gradient(to bottom, rgba(26,58,92,0.22)    0%, rgba(26,58,92,0)    33%); }
        .type-card[data-type="promo"],
        .type-shortcut[data-type="promo"]         { --type-halo: linear-gradient(to bottom, rgba(192,57,43,0.22)   0%, rgba(192,57,43,0)   33%); }
        .type-card[data-type="evenement"],
        .type-shortcut[data-type="evenement"]     { --type-halo: linear-gradient(to bottom, rgba(191,160,32,0.22)  0%, rgba(191,160,32,0)  33%); }
        .type-card[data-type="info"],
        .type-shortcut[data-type="info"]          { --type-halo: linear-gradient(to bottom, rgba(192,57,43,0.22)   0%, rgba(192,57,43,0)   33%); }
        .type-card[data-type="nouveaute"],
        .type-shortcut[data-type="nouveaute"]     { --type-halo: linear-gradient(to bottom, rgba(201,162,39,0.22)  0%, rgba(201,162,39,0)  33%); }

        .type-icon { font-size: 1.3rem; display: block; margin-bottom: 6px; }

        .type-name {
            font-size: 0.78rem;
            font-weight: 600;
            color: var(--text);
            margin-bottom: 3px;
        }
        .type-card.active .type-name { color: var(--orange); }

        .type-desc {
            font-size: 0.68rem;
            color: var(--text-muted);
            font-weight: 500;
            line-height: 1.4;
        }

        /* MODIFICATION CIBLÉE — raccourcis compacts "type de publication"
           (section "Style de visuel") : classe dédiée, jamais .type-card,
           pour ne pas hériter du dégradé de fond ni du gabarit volumineux
           des grandes cartes. Une seule ligne, jamais de retour à la ligne
           (flex-wrap:nowrap), défilement horizontal cantonné à ce seul
           conteneur (overflow-x:auto) — jamais toute la page. Scrollbar fine
           façon .templates-row (visuel.css), défilement tactile/pavé
           tactile natif, aucune conversion JS de la molette verticale. */
        .type-shortcuts {
            display: flex;
            flex-wrap: nowrap;
            align-items: stretch;
            gap: 8px;
            /* CORRECTION CIBLÉE — CAUSE RÉELLE ET CONFIRMÉE (isolation
               empirique) du débordement horizontal de toute la page sur
               téléphone : .main a des marges horizontales auto
               (margin:0 auto), ce qui désactive l'étirement flex habituel
               et le fait se dimensionner sur le contenu le plus large de
               tout son sous-arbre (shrink-to-fit). Avec width:100%, cette
               ligne contribuait sa largeur de CONTENU (7 boutons non
               tronqués, ~470px) à ce calcul — malgré overflow-x:auto — et
               élargissait .main, donc toute la page, bien au-delà de
               l'écran. width:0 empêche cette contribution (une valeur
               définie et non issue du contenu), min-width:100% restaure
               ensuite la pleine largeur normale une fois la page mise en
               page — aucun changement visuel, le défilement interne et
               les noms complets restent inchangés. Vérifié : plus aucun
               débordement de page, quel que soit l'élément. */
            width: 0;
            min-width: 100%;
            overflow-x: auto;
            overflow-y: hidden;
            margin: 10px 0 14px;
            padding-bottom: 6px;
            scrollbar-width: thin;
            scrollbar-color: var(--border-md) transparent;
            -webkit-overflow-scrolling: touch;
        }
        .type-shortcuts::-webkit-scrollbar { height: 5px; }
        .type-shortcuts::-webkit-scrollbar-track { background: transparent; }
        .type-shortcuts::-webkit-scrollbar-thumb { background: var(--border-md); border-radius: 3px; }

        /* flex:0 0 auto (jamais de flex-shrink/flex-basis relatif) :
           largeur NATURELLE selon le contenu (icône + nom complet), jamais
           une dimension fixe en pixels — le bouton "Mise en avant" reste
           donc plus large que "Info", exactement comme sur ordinateur.
           C'est ce qui garantit l'absence de rétrécissement et de retour à
           la ligne : le conteneur défile horizontalement (overflow-x:auto)
           dès que la somme des largeurs naturelles dépasse l'espace
           disponible. Aucune media query ne redéfinit ces deux classes
           nulle part dans ce fichier : la présentation doit rester
           identique à toutes les largeurs. */
        .type-shortcut {
            flex: 0 0 auto;
            display: flex;
            flex-direction: column;
            flex-wrap: nowrap;
            align-items: center;
            justify-content: center;
            gap: 3px;
            padding: 7px 10px 6px;
            border: 1.5px solid var(--border-md);
            border-radius: 10px;
            background: var(--type-halo, none), var(--white);
            cursor: pointer;
            font-family: inherit;
            transition: border-color 0.2s, background 0.2s;
        }
        .type-shortcut:hover { border-color: var(--orange); }
        .type-shortcut.active {
            border-color: var(--orange);
            background: var(--type-halo, none), rgba(184,75,12,0.04);
        }
        .type-shortcut-icon { font-size: 1.05rem; line-height: 1; flex-shrink: 0; }
        .type-shortcut-name {
            font-size: 0.62rem;
            font-weight: 600;
            color: var(--text);
            line-height: 1.2;
            white-space: nowrap;
        }
        .type-shortcut.active .type-shortcut-name { color: var(--orange); }

        /* MODIFICATION CIBLÉE — boutons "Style de visuel" pleine largeur,
           taille égale, une seule ligne sur desktop (les 7 grandes cartes
           "Quel type de publication ?" ont été retirées, ces boutons sont
           désormais l'unique sélecteur). Uniquement au-delà de 768px : en
           dessous, comportement mobile strictement inchangé (largeur
           naturelle par bouton + défilement horizontal existant, .type-
           shortcuts/.type-shortcut de base ci-dessus jamais modifiées). */
        @media (min-width: 769px) {
            .type-shortcut {
                flex: 1 1 0;
                min-width: 0;
            }
        }

        /* ── STYLE VISUEL ── */
        .style-note {
            font-size: 0.76rem;
            font-weight: 500;
            color: var(--text-muted);
            margin-bottom: 14px;
        }

        .style-preview-notice {
            width: 100%;
            box-sizing: border-box;
            margin: 8px 0 14px;
            padding: 10px 12px;
            border: 1px solid rgba(184, 75, 12, 0.45);
            border-left: 4px solid var(--orange);
            border-radius: 8px;
            background: rgba(184, 75, 12, 0.08);
            color: var(--text);
        }

        .style-preview-notice-title {
            margin-bottom: 3px;
            color: var(--orange);
            font-size: 0.84rem;
            font-weight: 700;
            line-height: 1.2;
        }

        .style-preview-notice-text {
            color: var(--text);
            font-size: 0.8rem;
            font-weight: 500;
            line-height: 1.4;
        }

        /* CARROUSEL — remplace uniquement la présentation (grille -> défilement
           horizontal avec ancrage). Aucun template, aucune option, aucune
           logique de sélection n'est concernée par ce bloc : .style-card/
           .style-thumb restent exactement les éléments déjà produits par
           renderStyles(), seule leur disposition change. */
        .style-carousel-wrap {
            position: relative;
        }
        /* CORRECTION CIBLÉE — toutes les cartes (active ou voisine) partagent
           désormais LA MÊME largeur, proche de celle du visuel principal :
           ce n'est plus une réduction des voisins qui crée l'effet de
           tranche, mais le cadrage (overflow) du carrousel lui-même, qui
           masque tout ce qui dépasse. --fp-carousel-card-width et le
           padding correspondant sont calculés par _fpCarouselApplyGeometry()
           (publier.html) à partir d'une SEULE mesure réelle de la largeur
           disponible (grid.clientWidth) — jamais un pourcentage de page
           imbriqué dans un autre, qui fausserait le calcul en cascade.
           Valeurs ci-dessous : repli visuel uniquement, avant ce calcul. */
        .style-grid {
            display: flex;
            gap: var(--fp-carousel-gap, 14px);
            overflow-x: auto;
            scroll-snap-type: x mandatory;
            -webkit-overflow-scrolling: touch;
            scrollbar-width: none;
            padding-block: 6px 16px;
            padding-inline: 10%;
            cursor: grab;
        }
        .style-grid::-webkit-scrollbar {
            display: none;
        }
        /* AJOUT — GLISSER AU CLIC GAUCHE (SOURIS), DESKTOP UNIQUEMENT.
           scroll-snap-type désactivé UNIQUEMENT pendant le glissement actif
           (sinon le snap CSS entre en concurrence avec le pilotage manuel
           de scrollLeft fait en JS) ; le recentrage/snap au relâchement est
           déjà assuré par le _fpCarouselOnScroll existant (JS), qui
           s'applique que le scroll vienne du swipe tactile ou de ce
           glissement souris — aucune duplication. user-select désactivé le
           temps du glissement pour éviter une sélection de texte parasite. */
        .style-grid.fp-carousel-dragging {
            cursor: grabbing;
            scroll-snap-type: none;
            user-select: none;
            -webkit-user-select: none;
        }

        .style-card {
            cursor: pointer;
            flex: 0 0 var(--fp-carousel-card-width, 80%);
            scroll-snap-align: center;
            opacity: 0.55;
            transition: opacity 0.2s;
        }
        .style-card.active {
            opacity: 1;
        }

        /* Flèches du carrousel — rondes et compactes, jamais un bloc carré
           encombrant. Un simple bouton, comme .fp-nav-arrow (theme.css),
           adapté à ce contexte flottant sur les côtés de la carte. */
        .style-carousel-arrow {
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            width: 34px;
            height: 34px;
            border-radius: 50%;
            border: none;
            background: var(--white);
            color: var(--text);
            font-size: 1.5rem;
            font-weight: 700;
            line-height: 1;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            box-shadow: 0 2px 8px rgba(26,18,8,0.18);
            z-index: 6;
            padding: 0;
        }
        .style-carousel-arrow--left  { left: 2px; }
        .style-carousel-arrow--right { right: 2px; }
        .style-carousel-arrow[hidden] {
            display: none;
        }
        .style-card:hover .style-thumb  { border-color: var(--border-md); }
        .style-card.active .style-thumb { border-color: var(--orange); }

        .style-thumb {
            width: 100%;
            /* CORRECTION CIBLÉE — ratio réel de la photo (source de vérité),
               au lieu du 5:8 fixe. --fp-thumb-h est fixée en JS (publier.html,
               _fpApplyPhotoRatioToThumbnails()) depuis naturalWidth/
               naturalHeight de la photo réellement chargée ; repli 1728
               (= 1080 × 8/5, ratio d'origine) tant qu'aucune photo n'est
               chargée — comportement actuel strictement inchangé dans ce cas.
               Les 5 cartes partagent cette même variable : même photo,
               donc même hauteur pour toutes. */
            aspect-ratio: 1080 / var(--fp-thumb-h, 1728);
            position: relative;
            overflow: hidden;
            border: 2px solid var(--border);
            border-radius: 6px;
            transition: border-color 0.2s;
            background: #1F1B14;
            background-size: cover;
            background-position: center;
            background-repeat: no-repeat;
            /* CORRECTION — INFOBAR PROMO 1 À 4 À LA TAILLE RÉELLE : la largeur
               de .style-thumb correspond toujours à 1080 unités (aspect-ratio
               ci-dessus, numérateur 1080 = largeur réelle de l'image publiée) ;
               ce conteneur de requête permet à .style-infobar-overlay
               (ci-dessous) d'exprimer ses dimensions en cqw, donc en
               proportion EXACTE et non approximative de ces 1080 unités,
               quelle que soit la taille réellement affichée de la miniature. */
            container-type: inline-size;
        }
        /* Carte Aucun : centrage flex.
           background-color (et non le raccourci background) : ne réinitialise
           jamais background-size/position/repeat hérités de .style-thumb,
           afin que PHOTO SIMPLE conserve exactement le même cadrage photo
           (cover/center/no-repeat) que promo-08 à promo-11. */
        .st-none {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            gap: 6px;
            background-color: var(--white);
        }
        /* Conteneur interne texte/icône de "Sans visuel" — masqué uniquement
           quand une photo est présente (prototype Promotion), jamais retiré du DOM */
        .st-none-content {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 6px;
        }
        .style-thumb--photo-preview .st-none-content {
            display: none;
        }
        .st-none-photo-label {
            display: none;
            position: absolute;
            left: 8px;
            right: 8px;
            bottom: 8px;
            padding: 5px 8px;
            border-radius: 6px;
            background: rgba(0, 0, 0, 0.72);
            color: #ffffff;
            font-size: 0.72rem;
            font-weight: 600;
            line-height: 1.2;
            text-align: center;
            pointer-events: none;
            z-index: 3;
        }
        .style-thumb--photo-preview .st-none-photo-label {
            display: block;
        }
        .style-thumb svg { display: block; width: 100%; height: 100%; }
        .style-thumb img {
            width: 100%;
            height: 100%;
            object-fit: contain;
            display: block;
        }

        /* Guide visuel Promotion — aide d'interface uniquement, jamais dans le rendu final */
        .style-guide-rect {
            position: absolute;
            pointer-events: none;
            box-sizing: border-box;
            background: rgba(255, 255, 255, 0.28);
            border: 2px solid #ffffff;
            border-radius: 6px;
            box-shadow:
                0 0 0 1px rgba(0, 0, 0, 0.75),
                0 2px 8px rgba(0, 0, 0, 0.55);
            overflow: hidden;
            z-index: 5;
        }

        /* Options remontées sous #style-grid (Promotion, Nouveauté — moteur commun) */
        .style-grid-options {
            margin-top: 16px;
        }

        /* ── PILOTE — Vue agrandie des visuels Actualité ──
           Présentation uniquement : aucune nouvelle source de vérité, la
           sélection reste .style-card.active + flyingpub_selected_template
           comme aujourd'hui. Le verrouillage réel du défilement est géré
           en JavaScript (_fpLockBodyScroll/_fpUnlockBodyScroll) ; inert
           est géré séparément (_fpStyleDetailNeutralize) — les deux sont
           complémentaires, ni l'un ni l'autre ne suffit seul. */
        /* Ligne combinant le bouton « ✓ Valider » (gauche) et le bouton
           Retour (droite). */
        .style-detail-action-row {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 8px;
            margin-bottom: 10px;
        }

        .style-detail-back {
            align-items: center;
            gap: 6px;
            padding: 8px 14px;
            border: 1.5px solid var(--border-md);
            border-radius: 20px;
            background: var(--white);
            color: var(--text);
            font-family: 'Jost', sans-serif;
            font-size: 0.83rem;
            font-weight: 500;
            cursor: pointer;
            flex-shrink: 0;
            /* Empêche le bouton de s'étirer sur toute la largeur de la
               carte : sans ceci, l'alignement par défaut (align-items:
               stretch, hérité de .scard--detail-fixed) en ferait une
               grande barre au lieu d'un petit bouton. */
            align-self: flex-start;
        }
        .style-detail-back:not([hidden]) {
            display: inline-flex;
        }
        .style-detail-back:hover {
            border-color: var(--orange);
            color: var(--orange);
        }

        /* État « validé » du bouton Valider — posé au clic (voir
           publier.html), retiré à chaque réouverture de la vue détaillée.
           Même forme/contour que .style-detail-back, seule la couleur
           change, pour un retour visuel clair sans rompre la cohérence
           graphique. */
        .style-detail-validate.is-validated {
            border-color: #2E7D4F;
            color: #2E7D4F;
            background: rgba(46, 125, 79, 0.08);
        }
        html.dark-mode .style-detail-validate.is-validated {
            border-color: #6FCF97;
            color: #6FCF97;
            background: rgba(111, 207, 151, 0.12);
        }

        /* Fond opaque temporaire, derrière la carte blanche : couvre tout
           l'écran (nav comprise) sans créer de copie de #scard-style-visuel.
           Activé uniquement par la classe posée sur <body> par
           _fpLockBodyScroll()/_fpUnlockBodyScroll(). */
        body.fp-style-detail-lock::before {
            content: '';
            position: fixed;
            inset: 0;
            z-index: 190;
            background: var(--cream);
        }

        /* CORRECTION CIBLÉE — masquage complet (au lieu du grisé) des
           options non compatibles avec le visuel actif, demandé pour tous
           les contextes (plus seulement l'ancienne vue détaillée,
           aujourd'hui neutralisée). Réutilise EXACTEMENT la même classe
           déjà posée par les fonctions _syncXxxFields() existantes —
           aucune nouvelle cartographie, aucun changement de logique
           métier, uniquement le retrait du préfixe .scard--detail-fixed
           qui limitait cet effet à la vue détaillée. Photo simple/Sans
           visuel n'est jamais concerné : chaque _syncXxxFields() retombe
           déjà sur un repli "tout actif" pour un templateId absent de sa
           table (ex. 'none'), donc cette classe n'y est jamais posée. */
        .opt-section--disabled {
            display: none;
        }

        /* Lignes/grilles/sections devenues entièrement vides une fois les
           options non compatibles masquées ci-dessus — classe posée par
           _fpStyleHideEmptyOptionGroups(), désormais appelée à chaque
           sélection (voir selectStyle()), plus seulement à l'ouverture de
           l'ancienne vue détaillée. */
        .fp-style-detail-empty {
            display: none;
        }

        /* #scard-style-visuel reste une carte blanche compacte, centrée
           par-dessus le fond ci-dessus — ses styles normaux (background,
           border, border-radius, padding hérités de .scard) ne sont pas
           remplacés, seuls le positionnement et les contraintes de taille
           sont ajoutés. */
        .scard--detail-fixed {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            margin: 0;
            z-index: 200;
            display: flex;
            flex-direction: column;
            width: min(660px, calc(100vw - 32px - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px)));
            max-height: calc(100dvh - 32px - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px));
            box-sizing: border-box;
            /* Défilement interne de secours, jamais actif en usage normal
               (le calcul flex ci-dessous fait tenir le contenu) : ne se
               déclenche que si le clavier virtuel réduit fortement la
               hauteur disponible (notamment iOS Safari, qui ne redimensionne
               pas toujours la mise en page). Reste strictement limité à
               cette carte — la page d'origine, elle, reste verrouillée par
               _fpLockBodyScroll(), et masquée par le fond ci-dessus. */
            overflow-y: auto;
        }
        .scard--detail-fixed > .slabel,
        .scard--detail-fixed > .style-preview-notice,
        .scard--detail-fixed > .style-detail-action-row,
        .scard--detail-fixed > .style-grid-options {
            flex-shrink: 0;
        }

        /* Zone contenant le visuel : ne grandit plus artificiellement
           (flex-grow:0) — sa hauteur suit uniquement le contenu réel de la
           carte, réduite seulement si l'espace vertical vient à manquer.
           overflow:visible : la vraie protection contre le dépassement est
           désormais le calcul de taille réel (_fpFitStyleDetail(), voir
           publier.html), jamais un recadrage silencieux par overflow. */
        .style-grid--detail-open {
            display: flex;
            flex: 0 1 auto;
            min-height: 0;
            align-items: center;
            justify-content: center;
            overflow: visible;
        }
        .style-grid--detail-open .style-card:not(.style-card--expanded) {
            display: none;
        }

        /* La carte (badge + miniature) ne s'étire plus dans le sens de la
           grille (flex:0 0 auto) : sa taille dépend uniquement de la
           hauteur naturelle du badge et de la taille de la miniature,
           elle-même calculée par _fpFitStyleDetail(). */
        .style-card--expanded {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 6px;
            max-width: 100%;
            flex: 0 0 auto;
        }
        .style-card--expanded .style-badge {
            flex-shrink: 0;
        }
        /* Dimensions calculées par _fpFitStyleDetail() (mesure réelle de
           l'espace disponible, jamais un budget estimé) et posées en
           variables CSS sur #scard-style-visuel — la miniature ne fait que
           les lire. Repli avant le premier calcul (un seul frame) : une
           taille modeste plutôt que 100 % de la carte, pour limiter tout
           effet visuel transitoire. aspect-ratio reste une garantie
           supplémentaire, pas le mécanisme principal de dimensionnement. */
        .style-card--expanded .style-thumb {
            flex: 0 0 auto;
            width: var(--fp-detail-thumb-width, min(100%, 220px));
            height: var(--fp-detail-thumb-height, auto);
            max-width: 100%;
            aspect-ratio: 5 / 8;
        }

        .style-badge {
            height: 22px;
            display: flex;
            align-items: center;
            justify-content: center;
            background: var(--orange);
            color: #ffffff;
            font-size: 0.58rem;
            font-weight: 700;
            letter-spacing: 1.2px;
            border-radius: 4px;
            margin-bottom: 4px;
        }
        .style-badge--hidden       { background: transparent; }
        .style-badge--promo        { background: #C0392B; }
        .style-badge--info         { background: #C0392B; }
        .style-badge--communique     { background: #1A3A5C; }
        .style-badge--evenement    { background: #BFA020; }
        .style-badge--nouveaute    { background: #C9A227; }
        .style-badge--mise-en-avant { background: #7a8a6e; }

        .style-infobar-overlay {
            position: absolute; bottom: 0; left: 0; right: 0;
            background: transparent;
            color: #fff;
            text-shadow: 0 2px 4px rgba(0,0,0,0.90);
            font-size: 0.40rem;
            padding: 5px 6px 8px;
            line-height: 1.6;
            letter-spacing: 0.02em;
            white-space: nowrap;
            overflow: hidden;
            pointer-events: none;
        }

        /* CORRECTION — INFOBAR PROMO 1 À 4 À LA TAILLE RÉELLE, CES 4 VISUELS
           UNIQUEMENT (sélecteur scopé par data-template, jamais la règle
           .style-infobar-overlay ci-dessus qui reste inchangée pour toutes
           les autres familles) : dimensions reprises EXACTEMENT de l'InfoBar
           réellement dessinée sur l'image publiée (visuel.html,
           FP_INFOBAR_FONT_SIZE/PAD_X/PAD_TOP + canonicalScale de
           _fpInfoBarSvg(), ligne ~2446 et ~5700 de visuel.html —
           desktopReferenceWidth = 624px, confirmé par .main (max-width
           700px, padding 20px) moins .scard (padding 18px) =
           700-20-20-18-18 = 624, canonicalScale = 1080/624) :
             - taille de texte  : round(13 × 1080/624)  = 23px → 23/1080 cqw
             - marge gauche/droite : round(14 × 1080/624) = 24px → 24/1080 cqw
             - marge haute (PAD_TOP) : round(5 × 1080/624)  = 9px  → 9/1080 cqw
             - marge basse (position dernière ligne, h - round(10×scale)=17px,
               approximée en padding-bottom) : 17/1080 cqw
           .style-thumb fait toujours 1080 unités de large (aspect-ratio
           ci-dessus) : ces valeurs en cqw sont donc la MÊME proportion que
           sur l'image finale réellement publiée, quelle que soit la taille
           d'affichage réelle de la miniature — jamais une estimation.
           Structure, icônes, couleurs, position (bas du visuel) et logique
           de _fpBuildPromoRealInfobar() strictement inchangées : seules les
           dimensions ci-dessous ont été recalculées. */
        .style-card[data-template="promo-08"] .style-infobar-overlay,
        .style-card[data-template="promo-09"] .style-infobar-overlay,
        .style-card[data-template="promo-10"] .style-infobar-overlay,
        .style-card[data-template="promo-11"] .style-infobar-overlay {
            font-size: 2.130cqw;
            padding: 0.833cqw 2.222cqw 1.574cqw;
            line-height: 1.3;
        }

        /* CORRECTION PILOTE — INFOBAR INFO 1 À 4 À LA TAILLE RÉELLE, CES 4
           VISUELS UNIQUEMENT — même calibrage EXACT que Promo 1-4 ci-dessus
           (mêmes constantes FP_INFOBAR_FONT_SIZE/PAD_X/PAD_TOP, même
           desktopReferenceWidth=624, même canonicalScale=1080/624 —
           valeurs cqw strictement identiques, pas une nouvelle estimation).
           .style-infobar-overlay--wrap (posée par _fpBuildInfoRealInfobar()
           dans publier.html, en plus de .style-infobar-overlay) autorise le
           texte à réellement revenir à la ligne quand le contenu réel
           l'exige — la règle générale ci-dessus reste white-space:nowrap
           pour toutes les autres familles, strictement inchangée. */
        .style-card[data-template="info-05"] .style-infobar-overlay,
        .style-card[data-template="info-06"] .style-infobar-overlay,
        .style-card[data-template="info-07"] .style-infobar-overlay,
        .style-card[data-template="info-08"] .style-infobar-overlay {
            font-size: 2.130cqw;
            padding: 0.833cqw 2.222cqw 1.574cqw;
            line-height: 1.3;
        }

        /* CORRECTION PILOTE — ALIGNEMENT PUBLIER/VISUEL (Nouveauté) : même
           calibrage EXACT que Promo/Info ci-dessus (mêmes constantes,
           mêmes valeurs cqw, aucune nouvelle estimation) — les 4 visuels
           Nouveauté reçoivent désormais aussi une InfoBar réelle
           (_fpBuildInfoRealInfobar(), publier.html), plus la démo fixe
           d'avant. */
        .style-card[data-template="nouveaute-05"] .style-infobar-overlay,
        .style-card[data-template="nouveaute-06"] .style-infobar-overlay,
        .style-card[data-template="nouveaute-07"] .style-infobar-overlay,
        .style-card[data-template="nouveaute-08"] .style-infobar-overlay {
            font-size: 2.130cqw;
            padding: 0.833cqw 2.222cqw 1.574cqw;
            line-height: 1.3;
        }
        /* CORRECTION — INFOBAR ÉVÉNEMENT 01 À 04 À LA TAILLE RÉELLE, CES 4
           VISUELS UNIQUEMENT — même calibrage EXACT que Promo/Info/Nouveauté
           ci-dessus (mêmes constantes FP_INFOBAR_FONT_SIZE/PAD_X/PAD_TOP,
           même desktopReferenceWidth=624, même canonicalScale=1080/624 —
           valeurs cqw strictement identiques, pas une nouvelle estimation).
           Manquait pour cette famille : la règle générique .style-infobar-overlay
           (font-size fixe 0.40rem, non proportionnelle à la miniature) restait
           donc appliquée, provoquant un chevauchement visuel avec le texte du
           template dans la carte de sélection (bloc éditorial "— ÉVÉNEMENT" +
           titre). Ne modifie ni le SVG, ni visuel.html, ni les autres familles. */
        .style-card[data-template="evenement-05"] .style-infobar-overlay,
        .style-card[data-template="evenement-06"] .style-infobar-overlay,
        .style-card[data-template="evenement-07"] .style-infobar-overlay,
        .style-card[data-template="evenement-08"] .style-infobar-overlay {
            font-size: 2.130cqw;
            padding: 0.833cqw 2.222cqw 1.574cqw;
            line-height: 1.3;
        }
        /* CORRECTION — INFOBAR ACTUALITÉ 01 À 04 À LA TAILLE RÉELLE, CES 4
           VISUELS UNIQUEMENT — même calibrage EXACT que Promo/Info/Nouveauté/
           Événement ci-dessus (mêmes constantes FP_INFOBAR_FONT_SIZE/PAD_X/
           PAD_TOP, même desktopReferenceWidth=624, même
           canonicalScale=1080/624 — valeurs cqw strictement identiques, pas
           une nouvelle estimation). Manquait pour cette famille : la règle
           générique .style-infobar-overlay (font-size fixe 0.40rem, non
           proportionnelle à la miniature) restait donc appliquée, risquant
           un chevauchement visuel avec le texte du template dans la carte
           de sélection. Ne modifie ni le SVG, ni visuel.html, ni les autres
           familles. */
        .style-card[data-template="actu-05"] .style-infobar-overlay,
        .style-card[data-template="actu-06"] .style-infobar-overlay,
        .style-card[data-template="actu-07"] .style-infobar-overlay,
        .style-card[data-template="actu-08"] .style-infobar-overlay {
            font-size: 2.130cqw;
            padding: 0.833cqw 2.222cqw 1.574cqw;
            line-height: 1.3;
        }
        /* CORRECTION — INFOBAR MISE EN AVANT 01 À 06 À LA TAILLE RÉELLE, CES 6
           VISUELS UNIQUEMENT — même calibrage EXACT que Promo/Info/Nouveauté/
           Événement/Actualité ci-dessus (mêmes constantes
           FP_INFOBAR_FONT_SIZE/PAD_X/PAD_TOP, même desktopReferenceWidth=624,
           même canonicalScale=1080/624 — valeurs cqw strictement identiques,
           pas une nouvelle estimation). Manquait pour cette famille : la
           règle générique .style-infobar-overlay (font-size fixe 0.40rem,
           non proportionnelle à la miniature) restait donc appliquée,
           risquant un chevauchement visuel avec le texte du template dans la
           carte de sélection. Ne modifie ni le SVG, ni visuel.html, ni les
           autres familles. */
        .style-card[data-template="mea-06"] .style-infobar-overlay,
        .style-card[data-template="mea-07"] .style-infobar-overlay,
        .style-card[data-template="mea-08"] .style-infobar-overlay,
        .style-card[data-template="mea-09"] .style-infobar-overlay {
            font-size: 2.130cqw;
            padding: 0.833cqw 2.222cqw 1.574cqw;
            line-height: 1.3;
        }
        /* CORRECTION — INFOBAR COMMUNIQUÉ (officiel) 01 À 04 À LA TAILLE
           RÉELLE, CES 4 VISUELS UNIQUEMENT — même calibrage EXACT que Promo/
           Info/Nouveauté/Événement/Actualité/Mise en avant ci-dessus (mêmes
           constantes FP_INFOBAR_FONT_SIZE/PAD_X/PAD_TOP, même
           desktopReferenceWidth=624, même canonicalScale=1080/624 — valeurs
           cqw strictement identiques, pas une nouvelle estimation, aucune
           variante propre à Communiqué). Manquait pour cette famille : la
           règle générique .style-infobar-overlay (font-size fixe 0.40rem,
           padding en px fixes, non proportionnels à la miniature) restait
           donc appliquée — seule famille dans ce cas, d'où l'écart de
           hauteur/épaisseur constaté à l'œil par rapport à Promotion/
           Événement. Ne modifie ni le SVG, ni visuel.html, ni les autres
           familles. */
        .style-card[data-template="communique-07"] .style-infobar-overlay,
        .style-card[data-template="communique-08"] .style-infobar-overlay,
        .style-card[data-template="communique-09"] .style-infobar-overlay,
        .style-card[data-template="communique-10"] .style-infobar-overlay {
            font-size: 2.130cqw;
            padding: 0.833cqw 2.222cqw 1.574cqw;
            line-height: 1.3;
        }
        .style-infobar-overlay--wrap {
            white-space: normal;
        }

        /* CSS templates miniatures étape 1 : à ajouter par template depuis spec SVG officielle */



        /* CSS templates promo : à ajouter par template depuis spec SVG officielle */

        /* ── OPTIONS AVANCÉES ── */
        .options-btn {
            width: 100%;
            display: flex;
            align-items: center;
            justify-content: space-between;
            background: none;
            border: none;
            cursor: pointer;
            font-family: 'Jost', sans-serif;
            font-size: 0.84rem;
            font-weight: 500;
            color: var(--text);
            padding: 0;
        }
        .options-arrow {
            font-size: 0.78rem;
            color: var(--text-light);
            transition: transform 0.25s;
        }
        .options-btn.open .options-arrow { transform: rotate(180deg); }

        .options-body {
            display: none;
            margin-top: 18px;
            border-top: 1px solid var(--border);
            padding-top: 18px;
        }
        .options-body.open { display: block; }

        .opt-section { margin-bottom: 20px; }
        .opt-section:last-child { margin-bottom: 0; }

        .opt-label {
            font-size: 0.65rem;
            font-weight: 600;
            letter-spacing: 0.1em;
            text-transform: uppercase;
            color: var(--text-muted);
            margin-bottom: 8px;
        }
        /* MISE EN PLACE — FAMILLE INFO / LIMITES DE CARACTÈRES : compteur
           "(n/max)" à côté du libellé Texte complémentaire. Vide (aucune
           classe couleur) tant qu'aucune limite n'est active (Mise en
           avant, Photo simple). Couleurs reprises de valeurs déjà
           utilisées ailleurs dans ce fichier : #2E7D4F (vert, déjà utilisé
           par .style-detail-validate.is-validated), #c0392b (rouge, déjà
           utilisé par .input-error) — aucune nouvelle couleur inventée.
           CORRECTION CIBLÉE — état orange (--warn) supprimé : seuls vert
           (0 à max-1) et rouge (max ou dépassement) subsistent. */
        .char-counter {
            letter-spacing: normal;
            text-transform: none;
        }
        .char-counter--ok     { color: #2E7D4F; }
        .char-counter--danger { color: #c0392b; }
        .opt-help-text {
            font-size: 0.76rem;
            color: var(--text-muted);
            font-style: italic;
            margin: 4px 0 10px;
            line-height: 1.5;
        }
        .opt-row {
            display: flex;
            gap: 16px;
        }
        .opt-row > .opt-section {
            flex: 1;
            min-width: 0;
            margin-bottom: 0;
        }

        .opt-hint {
            font-size: 0.75rem;
            color: var(--text);
            margin-bottom: 10px;
            line-height: 1.5;
        }

        /* Chips sélectionnables */
        .opt-chips {
            display: flex;
            flex-wrap: wrap;
            gap: 6px;
            margin-bottom: 10px;
        }
        .opt-chip {
            padding: 5px 13px;
            border-radius: 20px;
            border: 1px solid var(--border-md);
            background: var(--card-bg);
            font-family: 'Jost', sans-serif;
            font-size: 0.78rem;
            font-weight: 500;
            color: var(--text-muted);
            cursor: pointer;
            transition: all 0.15s;
        }
        .opt-chip:hover { border-color: var(--orange); color: var(--orange); }
        .opt-chip.active {
            background: var(--orange);
            border-color: var(--orange);
            color: white;
        }

        /* Input */
        .opt-input {
            width: 100%;
            padding: 9px 12px;
            background: var(--cream);
            border: 1px solid var(--border-md);
            border-radius: 8px;
            font-family: 'Jost', sans-serif;
            font-size: 0.82rem;
            color: var(--text);
            outline: none;
            transition: border-color 0.2s, box-shadow 0.2s;
        }
        .opt-input:focus {
            border-color: var(--orange);
            box-shadow: 0 0 0 3px rgba(184,75,12,0.08);
        }
        .opt-input::placeholder { color: var(--text-muted); }

        /* Date et heure */
        .opt-date-row {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 10px;
        }
        .opt-field-label {
            display: block;
            font-size: 0.65rem;
            font-weight: 600;
            letter-spacing: 0.08em;
            text-transform: uppercase;
            color: var(--text-muted);
            margin-bottom: 5px;
        }
        .opt-input--sm { padding: 8px 10px; font-size: 0.8rem; }

        /* Grille compacte 3 colonnes — Section Prix (Promo) : les 7 champs
           possibles (nouveau prix, ancien prix, pourcentage, compteur J-,
           jusqu'à, texte du coupon, texte de l'étiquette) sont des enfants
           directs de cette grille. _syncPromoFields() pose display:none sur
           ceux non pertinents pour le visuel actif : ils sortent alors du
           flux de la grille et les champs visibles se replacent
           naturellement, sans case vide. 2 colonnes dès 768px, y compris sur
           mobile (téléphone) — un champ isolé (nombre impair de champs
           visibles) reste seul en fin de grille sans forcer une pleine
           largeur, comportement natif de CSS Grid. */
        .opt-promo-fields-grid {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 10px 16px;
        }
        @media (max-width: 768px) {
            .opt-promo-fields-grid { grid-template-columns: 1fr 1fr; gap: 8px 10px; }
        }

        /* Champs prix désactivés (familles non-Promo) */
        .opt-input--disabled {
            opacity: 0.38;
            cursor: not-allowed;
            background-color: var(--border-md);
        }
        .opt-section--disabled .opt-label,
        .opt-section--disabled .opt-field-label {
            opacity: 0.38;
        }
        .opt-section--disabled .opt-addr-block {
            opacity: 0.38;
            pointer-events: none;
        }

        /* Grille 2 colonnes — Section Officiel */
        .opt-communique-grid {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 10px;
            margin-top: 10px;
            align-items: start;
        }
        @media (max-width: 480px) {
            .opt-communique-grid { grid-template-columns: 1fr; }
        }

        /* Adresse différente */
        .opt-addr-block {
            display: flex;
            align-items: center;
            gap: 12px;
            padding: 12px 14px;
            background: var(--card-bg);
            border: 1px solid var(--border-md);
            border-radius: 10px;
        }
        .opt-addr-field { margin-top: 8px; display: none; }
        .opt-addr-field.visible { display: block; }
        .opt-addr-icon {
            font-size: 1rem;
            flex-shrink: 0;
            color: var(--text-muted);
        }
        .opt-addr-content { flex: 1; }
        .opt-addr-title {
            font-size: 0.82rem;
            font-weight: 600;
            color: var(--text);
            margin-bottom: 2px;
        }
        .opt-addr-sub {
            font-size: 0.74rem;
            color: var(--text-muted);
            line-height: 1.4;
        }

        /* Switch */
        .opt-switch {
            position: relative;
            width: 40px;
            height: 23px;
            flex-shrink: 0;
            cursor: pointer;
            display: inline-block;
        }
        .opt-switch input { opacity: 0; width: 0; height: 0; position: absolute; }
        .opt-switch-track {
            position: absolute;
            inset: 0;
            background: rgba(26,18,8,0.14);
            border-radius: 12px;
            transition: background 0.2s;
        }
        .opt-switch-track::before {
            content: '';
            position: absolute;
            width: 17px; height: 17px;
            border-radius: 50%;
            background: white;
            top: 3px; left: 3px;
            transition: transform 0.2s;
            box-shadow: 0 1px 3px rgba(0,0,0,0.18);
        }
        .opt-switch input:checked + .opt-switch-track { background: var(--orange); }
        .opt-switch input:checked + .opt-switch-track::before { transform: translateX(17px); }

        /* Séparateur entre sections */
        .opt-sep {
            border: none;
            border-top: 1px solid var(--border);
            margin: 18px 0;
        }



        .pro-badge {
            background: var(--orange);
            color: white;
            font-size: 0.62rem;
            font-weight: 700;
            letter-spacing: 0.04em;
            padding: 4px 10px;
            border-radius: 5px;
            flex-shrink: 0;
            white-space: nowrap;
        }

        /* ── BOUTON GÉNÉRER ── */
        .generate-bar {
            max-width: 700px;
            margin: 0 auto 28px;
            padding: 0 20px;
        }

        .generate-btn {
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 10px;
            width: 100%;
            max-width: 520px;
            margin: 0 auto;
            background: var(--orange);
            color: white;
            border: none;
            border-radius: 10px;
            padding: 15px;
            font-family: 'Jost', sans-serif;
            font-size: 0.92rem;
            font-weight: 600;
            cursor: pointer;
            transition: background 0.2s;
            letter-spacing: 0.01em;
        }
        .generate-btn:hover { background: var(--orange-lt); }
        .generate-btn:active { transform: scale(0.99); }

        /* ── PUBLIER SUR — cartes de sélection ── */
        .pub-net-cards {
            display: flex;
            gap: 8px;
            flex-wrap: wrap;
        }
        .pub-net-card {
            display: flex;
            align-items: center;
            gap: 7px;
            padding: 7px 13px 7px 9px;
            border-radius: 8px;
            border: 1.5px solid var(--border-md);
            background: var(--white);
            cursor: pointer;
            transition: background 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.15s;
            user-select: none;
            font-size: 0.83rem;
            font-weight: 500;
            color: var(--text);
        }
        .pub-net-card:hover:not(.pub-net-card--disabled) {
            border-color: rgba(26,18,8,0.3);
            box-shadow: 0 2px 8px rgba(26,18,8,0.07);
        }
        /* Icône réseau */
        .pub-net-card__icon {
            width: 22px; height: 22px;
            border-radius: 5px;
            display: flex; align-items: center; justify-content: center;
            font-size: 0.72rem; font-weight: 700;
            color: white;
            flex-shrink: 0;
        }
        .pub-net-card__icon--fb { background: #1877F2; }
        .pub-net-card__icon--ig {
            background: linear-gradient(135deg, #833AB4 0%, #FD1D1D 50%, #FCB045 100%);
            font-style: italic;
        }
        .pub-net-card__icon--tt { background: #010101; }
        .pub-net-card__icon--li { background: #0A66C2; }
        /* Badge BIENTÔT */
        .pub-net-card__soon {
            font-size: 0.6rem; font-weight: 700;
            letter-spacing: 0.07em; text-transform: uppercase;
            color: var(--text-light);
            background: var(--cream-dark);
            border: 1px solid var(--border);
            border-radius: 3px;
            padding: 2px 5px; line-height: 1;
        }
        /* États actifs — couleurs officielles */
        .pub-net-card--active[data-network="facebook"] {
            background: #1877F2;
            border-color: #1877F2;
            color: #fff;
        }
        .pub-net-card--active[data-network="instagram"] {
            background: linear-gradient(135deg, #833AB4 0%, #FD1D1D 50%, #FCB045 100%);
            border-color: transparent;
            color: #fff;
        }
        .pub-net-card--active[data-network="linkedin"] {
            background: #0A66C2;
            border-color: #0A66C2;
            color: #fff;
        }
        /* ÉTAPE 2 TEST TIKTOK — état actif temporaire, le temps de tester la
           sélection de la carte ; à conserver ou retirer selon la décision
           prise lors de l'étape OAuth. */
        .pub-net-card--active[data-network="tiktok"] {
            background: #010101;
            border-color: #010101;
            color: #fff;
        }
        /* MODIFICATION CIBLÉE — réseaux personnels (Facebook/Instagram
           Personnel) : mêmes couleurs de marque officielles que leurs
           équivalents "Pro" ci-dessus, purement visuel — attribut
           data-personal-network, jamais data-network, donc aucune
           incidence sur la sélection à publication automatique. */
        .pub-net-card--active[data-personal-network="facebook-personal"] {
            background: #1877F2;
            border-color: #1877F2;
            color: #fff;
        }
        .pub-net-card--active[data-personal-network="instagram-personal"] {
            background: linear-gradient(135deg, #833AB4 0%, #FD1D1D 50%, #FCB045 100%);
            border-color: transparent;
            color: #fff;
        }
        /* Phrase de clarification (auto/personnel), même lisibilité que
           .extra-photos-label — texte noir/gras, jamais un texte
           secondaire gris. */
        .pub-net-note {
            font-size: 0.86rem;
            font-weight: 600;
            color: var(--text);
            line-height: 1.5;
            margin: 10px 0 0;
        }
        /* État désactivé */
        .pub-net-card--disabled {
            opacity: 0.42;
            cursor: not-allowed;
            pointer-events: none;
        }

        /* ── PUBLIER SUR — en-tête + indicateur récapitulatif ──
           Purement informatif (jamais un bouton) : reflète l'état déjà
           géré par toggleNetCard()/initSelectedNetworks(), sans logique
           propre. Réutilise les variables et couleurs de marque déjà
           définies ci-dessus, donc compatible mode sombre sans règle
           supplémentaire. */
        .pub-net-heading {
            display: flex;
            align-items: center;
            justify-content: flex-start;
            column-gap: 32px;
            row-gap: 8px;
            flex-wrap: wrap;
            margin-bottom: 8px;
        }
        .pub-net-heading .opt-label {
            margin-bottom: 0;
        }
        .pub-net-selection {
            display: flex;
            align-items: center;
            gap: 6px;
            flex-wrap: wrap;
            min-width: 0;
            font-size: 0.76rem;
            color: var(--text-muted);
        }
        .pub-net-selection__badge {
            width: 18px;
            height: 18px;
            font-size: 0.62rem;
            flex-shrink: 0;
        }

        /* ── LISIBILITÉ DES TEXTES SECONDAIRES ──
           Règle commune unique (jamais un style par élément) : renforce
           tous les petits textes explicatifs/descriptifs/libellés de
           cette page — jugés trop fins/trop pâles — en semi-gras +
           couleur de texte principale (var(--text), déjà utilisée par
           .pub-net-note pour le même besoin). var(--text) s'adapte
           nativement au mode sombre (theme.css) : AUCUNE règle
           html.dark-mode séparée n'est donc nécessaire ici, et l'ancienne
           surcharge sombre ci-dessous (couleur fixe plus terne que
           var(--text) en sombre) est retirée pour ne pas annuler ce
           renforcement en mode sombre. Ne touche ni taille, ni
           disposition, ni bordures, ni forme (.opt-chip conserve
           exactement son padding/bordure/fond) — uniquement le poids et
           la couleur du texte. */
        .opt-hint,
        .sujet-hint,
        .type-desc,
        .opt-chip,
        .opt-field-label,
        .opt-addr-sub,
        .photo-formats,
        .style-note,
        .opt-help-text,
        .page-subtitle {
            font-weight: 600;
            color: var(--text);
        }

        /* ── MODE SOMBRE — overrides spécifiques publier.html ── */
        html.dark-mode .photo-remove,
        html.dark-mode .lock-icon,
        html.dark-mode .progress-plan,
        html.dark-mode .user-plan {
            background: #302B22;
        }
        html.dark-mode .progress-track {
            background: rgba(237,229,216,0.10);
        }
        html.dark-mode .opt-switch-track {
            background: rgba(237,229,216,0.15);
        }

        /* ══════════════════════════════════════════════
           RESPONSIVE — TABLETTE (≤ 768px)
           Réduction des espacements horizontaux de la nav et des
           onglets uniquement. Ils restent sur une seule ligne.
           Aucun autre élément de la page n'est modifié.
        ══════════════════════════════════════════════ */
        @media (max-width: 768px) {
            .app-nav {
                padding: 0 16px;
            }
            .nav-tab {
                padding: 0 10px;
                font-size: 0.76rem;
            }
        }

        /* ══════════════════════════════════════════════
           RESPONSIVE — SMARTPHONE (≤ 480px)
           La nav passe sur deux lignes : logo + menu utilisateur
           (horloge/thème + compte) en haut, les 4 onglets en
           dessous, avec repli naturel en 2×2 si nécessaire.
           Aucun défilement horizontal, aucun élément masqué,
           aucun menu hamburger — uniquement flex-wrap/order/
           flex-basis sur la structure HTML existante.
        ══════════════════════════════════════════════ */
        @media (max-width: 480px) {
            .app-nav {
                flex-wrap: wrap;
                height: auto;
                padding: 10px 16px;
                row-gap: 8px;
            }
            .app-logo {
                order: 1;
            }
            .app-nav__right {
                order: 2;
                margin-left: auto;
            }
            .app-nav__tabs {
                order: 3;
                flex-basis: 100%;
                flex-wrap: wrap;
                gap: 4px;
            }
            .nav-tab {
                height: auto;
                padding: 8px 12px;
                font-size: 0.74rem;
            }

            /* Zone PHOTO — bascule vers les deux boutons dédiés
               (galerie / appareil photo) : .photo-cta redevient
               redondant et est masqué. La zone de dépôt, l'aperçu
               et la suppression restent strictement inchangés. */
            .photo-cta {
                display: none;
            }
            .photo-mobile-actions {
                display: flex;
            }
            .photo-mobile-btn {
                min-height: 44px;
            }

            /* Options de la famille active dans la vue fixe, toutes
               familles confondues : une seule colonne pour éviter les
               libellés/placeholders coupés constatés en deux colonnes sur
               téléphone. Strictement scopé à .scard--detail-fixed — la
               disposition normale de .style-grid-options hors vue fixe
               n'est pas concernée. Couvre Actualité, Promotion, Nouveauté,
               Événement (.opt-date-row). .opt-communique-grid n'est pas
               concernée : elle possède déjà sa propre règle responsive
               (ci-dessus) qui s'applique aussi bien dans la vue fixe.
               Ordre, identifiants, valeurs, événements inchangés. */
            .scard--detail-fixed .style-grid-options .opt-date-row {
                grid-template-columns: 1fr;
            }

            /* Mise en avant (.opt-row, structure flex distincte de
               .opt-date-row) : empilée verticalement dans la vue fixe
               uniquement, mêmes garanties que ci-dessus. */
            .scard--detail-fixed .style-grid-options .opt-row {
                flex-direction: column;
                align-items: stretch;
            }

            /* Bouton « Retour » de la vue détaillée — visible et confortable
               au toucher, uniquement sur téléphone et uniquement quand la
               vue détaillée est ouverte (.scard--detail-fixed). La règle de
               base .style-detail-back ci-dessus (hors media query) reste la
               seule appliquée sur tablette/ordinateur. Couleurs reprises du
               motif déjà utilisé par .generate-btn/.style-badge/.opt-chip.active
               (fond var(--orange), blanc véritable pour le texte plutôt que
               var(--white), redéfinie en teinte sombre par theme.css en mode
               sombre). La flèche (span sans couleur propre) hérite de
               `color`, donc devient blanche avec le texte sans règle
               séparée. */
            .scard--detail-fixed .style-detail-back {
                min-height: 44px;
                padding: 11px 16px;
                justify-content: center;
                border: none;
                background: var(--orange);
                color: #fff;
            }
            .scard--detail-fixed .style-detail-back:hover {
                background: var(--orange-lt);
                color: #fff;
            }
            .scard--detail-fixed .style-detail-back:active {
                background: var(--orange-lt);
                transform: scale(0.98);
            }
            .scard--detail-fixed .style-detail-back:focus-visible {
                outline: 2px solid #fff;
                outline-offset: 2px;
            }

            /* État « validé » du bouton Valider, aussi sur mobile : doit
               l'emporter sur le fond orange ci-dessus (même spécificité,
               règle placée après). */
            .scard--detail-fixed .style-detail-validate.is-validated {
                background: #2E7D4F;
                color: #fff;
            }
        }

        /* ══════════════════════════════════════════════
           CORRECTION ORTHOGRAPHIQUE PAR CHAMP
           Bloc de proposition affiché sous un champ, en flux
           normal (jamais en position absolue), généré par JS.
           Aucune proposition n'est appliquée automatiquement.
        ══════════════════════════════════════════════ */
        .spell-proposal {
            margin-top: 8px;
            padding: 10px 12px;
            background: var(--card-bg);
            border: 1px solid var(--border-md);
            border-radius: 8px;
        }
        .spell-proposal-status {
            font-size: 0.76rem;
            color: var(--text-muted);
            font-style: italic;
        }
        .spell-proposal-label {
            font-size: 0.65rem;
            font-weight: 600;
            letter-spacing: 0.08em;
            text-transform: uppercase;
            color: var(--text-muted);
            margin-bottom: 4px;
        }
        .spell-proposal-text {
            font-size: 0.84rem;
            color: var(--text);
            margin-bottom: 10px;
            line-height: 1.5;
            word-break: break-word;
        }
        /* Élément (mot/signe) modifié ou ajouté par rapport au texte original —
           discret, jamais interactif (aucun mot ne se clique individuellement). */
        .spell-diff {
            background: rgba(239,68,68,0.08);
            border-bottom: 1.5px solid rgba(239,68,68,0.55);
            border-radius: 2px;
            padding: 0 1px;
            cursor: text;
        }
        .spell-proposal-removed {
            font-size: 0.76rem;
            color: var(--text-muted);
            margin-bottom: 10px;
            line-height: 1.5;
            word-break: break-word;
        }
        .spell-proposal-actions {
            display: flex;
            flex-wrap: wrap;
            gap: 8px;
        }
        .spell-btn {
            font-family: 'Jost', sans-serif;
            font-size: 0.78rem;
            font-weight: 500;
            padding: 7px 14px;
            border-radius: 20px;
            border: 1px solid var(--border-md);
            background: var(--white);
            color: var(--text-muted);
            cursor: pointer;
            transition: all 0.15s;
        }
        .spell-btn:hover { border-color: var(--orange); color: var(--orange); }
        .spell-btn--accept {
            background: var(--orange);
            border-color: var(--orange);
            color: white;
        }
        .spell-btn--accept:hover { opacity: 0.88; color: white; }

        /* Évite qu'une proposition ajoutée dans une cellule de grille/flex
           (ligne2Actu, descriptionCommunique) n'étire visuellement la
           cellule voisine (signature, interrupteur "nom dans le sceau"). */
        #wrap-ligne2Actu,
        #wrap-descriptionCommunique {
            align-self: start;
        }

        @media (max-width: 480px) {
            .spell-proposal-actions {
                flex-direction: column;
            }
            .spell-btn {
                width: 100%;
                text-align: center;
            }
        }

        /* ══════════════════════════════════════════════════════════════
           OPTIONS COMPACTES — TOUTES FAMILLES (présentation uniquement) — v2
           UNE SEULE grille pour toutes les options affichées sous les
           visuels (.style-grid-options) : chaque champ (libellé + saisie)
           y occupe une case, jusqu'à 3 par ligne sur ordinateur (jamais
           une colonne sous 150 px), quelle que soit la section qui le
           contient — deux petits champs de sections différentes (ex. Texte
           complémentaire + Prix indicatif) peuvent donc se partager une
           ligne. Sections-conteneurs, rangées et grilles existantes fondues
           dans la grille (display: contents) ; leurs titres restent en
           pleine largeur.
           #section-info (Texte complémentaire) reste une vraie boîte (le JS
           l'utilise pour scrollIntoView) : une case quand elle ne contient
           que Texte complémentaire, sinon une sous-grille alignée sur les
           mêmes colonnes (Texte complémentaire + Date/Horaires côte à côte).
           Pleine largeur : titres de section, textes d'aide, zones de texte
           (textarea). Aucun changement HTML/JS : identifiants, listeners,
           compteurs, limites, repères, états et conditions d'affichage
           inchangés. Masquages respectés : style="display:none" posé par le
           JS, .opt-section--disabled et .fp-style-detail-empty ne sont jamais
           ré-affichés.
        ══════════════════════════════════════════════════════════════ */
        .style-grid-options:not([style*="none"]) {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(max(150px, calc((100% - 24px) / 3)), 1fr));
            gap: 8px 12px;
            align-items: end;
        }

        /* Conteneurs fondus dans la grille : sections sans champ direct
           (titre + groupes de champs), rangées et grilles existantes. */
        .style-grid-options .opt-section:not(:has(> :is(input, select, textarea))):not([style*="none"]):not(.opt-section--disabled):not(.fp-style-detail-empty),
        .style-grid-options #mea-options:not([style*="none"]),
        .style-grid-options :is(.opt-date-row, .opt-communique-grid, .opt-promo-fields-grid):not(.fp-style-detail-empty),
        .style-grid-options .opt-row:not([style*="none"]):not(.fp-style-detail-empty),
        .style-grid-options [id^="wrap-"]:has(> :is(.opt-date-row, .opt-communique-grid)):not([style*="none"]):not(.opt-section--disabled):not(.fp-style-detail-empty) {
            display: contents !important;
        }

        /* Groupes vides (option non compatible avec le visuel) : réellement
           retirés de la grille. */
        .style-grid-options .fp-style-detail-empty { display: none !important; }
        /* Séparateurs internes : sans objet quand les champs sont côte à côte. */
        .style-grid-options .opt-sep { display: none !important; }

        /* Cases : marges et flex en ligne neutralisés (espacement porté par
           la grille), libellé au-dessus de sa saisie. */
        .style-grid-options [id^="wrap-"],
        .style-grid-options .opt-section,
        .style-grid-options .opt-date-row > *,
        .style-grid-options .opt-communique-grid > * {
            margin: 0 !important;
            min-width: 0;
        }
        .style-grid-options :is(input, select):not([type="checkbox"]):not([type="radio"]) { max-width: 100%; }
        .style-grid-options .opt-label { margin-bottom: 4px; }
        .style-grid-options .opt-field-label { margin-bottom: 3px; }
        .style-grid-options .opt-field-label,
        .style-grid-options .opt-label { overflow-wrap: anywhere; }

        /* Pleine largeur : titres des sections fondues, textes d'aide,
           zones de texte, blocs à interrupteur (2 colonnes). */
        .style-grid-options .opt-section:not(:has(> :is(input, select, textarea))) > :is(.opt-label, .opt-hint, .opt-help-text),
        .style-grid-options #mea-options > :is(.opt-label, .opt-hint, .opt-help-text),
        .style-grid-options :is(.opt-hint, .opt-help-text),
        .style-grid-options :is([id^="wrap-"], .opt-section):has(textarea) {
            grid-column: 1 / -1;
        }
        .style-grid-options [id^="wrap-"]:has(.opt-addr-block) { grid-column: span 2; }
        .style-grid-options .opt-section:not(:has(> :is(input, select, textarea))) > .opt-label,
        .style-grid-options #mea-options > .opt-label { margin-bottom: 0; }

        /* #section-info avec d'autres champs visibles que Texte
           complémentaire : sous-grille pleine largeur, mêmes colonnes ;
           Texte complémentaire (libellé + saisie) en 1re case, les autres
           champs à côté (chacun sur 2 rangées : libellé + saisie). */
        .style-grid-options #section-info:not([style*="none"]):not(.opt-section--disabled):has(> div:is([id^="wrap-"]):not([style*="none"]):not(.fp-style-detail-empty)) {
            display: grid !important;
            grid-column: 1 / -1;
            grid-template-columns: subgrid;
            column-gap: 12px;
            row-gap: 0;
            align-items: end;
        }
        .style-grid-options #section-info:has(> div:is([id^="wrap-"]):not([style*="none"]):not(.fp-style-detail-empty)) > .opt-label { grid-column: 1; grid-row: 1; }
        .style-grid-options #section-info:has(> div:is([id^="wrap-"]):not([style*="none"]):not(.fp-style-detail-empty)) > :is(input, select) { grid-column: 1; grid-row: 2; align-self: start; }
        .style-grid-options #section-info:has(> div:is([id^="wrap-"]):not([style*="none"]):not(.fp-style-detail-empty)) :is([id^="wrap-"]:not(:has(> .opt-date-row)), .opt-date-row > *) {
            grid-row: span 2;
            align-self: end;
        }

        /* Téléphone, vue détaillée : une seule colonne, comme avant. */
        @media (max-width: 480px) {
            .scard--detail-fixed .style-grid-options:not([style*="none"]) {
                grid-template-columns: 1fr;
            }
        }
