/* ============================================================
   Afrique Maps – Styles
   ============================================================ */

/* Inter — typographie principale (SIL Open Font License)
   4 graisses chargées en WOFF2, latin only, ~105 Ko total.
   font-display:swap → texte affiché instantanément en fallback
   pendant le chargement de la fonte. */
@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('fonts/inter-400.woff2') format('woff2');
}
@font-face {
    font-family: 'Inter';
    font-style: italic;
    font-weight: 400;
    font-display: swap;
    src: url('fonts/inter-400-italic.woff2') format('woff2');
}
@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('fonts/inter-700.woff2') format('woff2');
}
@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 800;
    font-display: swap;
    src: url('fonts/inter-800.woff2') format('woff2');
}

/* Variables */
:root {
    --af-bg: #f7f6f2;
    --af-card: #ffffff;
    --af-text: #1e2a24;
    --af-muted: #6b7370;
    --af-border: #e4e2db;
    --af-primary: #0f4c2b;
    --af-primary-hover: #166037;
    --af-accent: #e8a33d;
    --af-danger: #b3341d;
    --af-ok: #2d7a4b;
    --af-err: #a33226;
    --af-radius: 8px;
    --af-radius-sm: 5px;
    --af-shadow: 0 1px 2px rgba(0,0,0,.04), 0 4px 12px rgba(0,0,0,.05);
    --af-font: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

/* Base */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
    font-family: var(--af-font);
    color: var(--af-text);
    background: var(--af-bg);
    font-size: 15px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4 { margin: 0 0 .6em; font-weight: 600; line-height: 1.25; }
h1 { font-size: 1.75rem; }
h2 { font-size: 1.4rem; }
h3 { font-size: 1.1rem; margin-top: 1.5rem; }
h4 { font-size: .95rem; }
a { color: var(--af-primary); }
code { background: #eef0ea; padding: 1px 5px; border-radius: 3px; font-size: .9em; }
pre  { background: #1e2a24; color: #e8ede6; padding: 1rem; border-radius: var(--af-radius-sm); overflow: auto; }
pre code { background: transparent; color: inherit; padding: 0; }
hr { border: 0; border-top: 1px solid var(--af-border); margin: 2rem 0; }

/* ============== Auth page (install + login) ============== */
.af-auth-page {
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: 2rem 1rem;
    background: linear-gradient(135deg, #0f4c2b 0%, #1a6b3f 100%);
}
.af-auth-card {
    background: var(--af-card);
    max-width: 420px;
    width: 100%;
    padding: 2.5rem;
    border-radius: var(--af-radius);
    box-shadow: 0 20px 60px rgba(0,0,0,.2);
}
.af-auth-card h1 { margin-bottom: .25rem; }
.af-auth-card label { display: block; margin-top: 1rem; font-weight: 500; }
.af-auth-card input[type=password],
.af-auth-card input[type=text] {
    width: 100%; padding: .6rem .75rem; font-size: 1rem;
    border: 1px solid var(--af-border); border-radius: var(--af-radius-sm);
    margin-top: .3rem;
    font-family: inherit;
}
.af-auth-card button { margin-top: 1.5rem; width: 100%; }

/* ============== Admin layout ============== */
.af-admin { min-height: 100vh; }
.af-header {
    background: var(--af-primary);
    color: #fff;
    box-shadow: var(--af-shadow);
}
.af-header__inner {
    max-width: 1200px; margin: 0 auto; padding: .9rem 1.5rem;
    display: flex; align-items: center; justify-content: space-between;
    gap: 1.5rem; flex-wrap: wrap;
}
.af-brand { color: #fff; text-decoration: none; font-weight: 700; font-size: 1.1rem; }
.af-header nav { display: flex; gap: 1.2rem; flex-wrap: wrap; }
.af-header nav a { color: rgba(255,255,255,.8); text-decoration: none; font-weight: 500; padding-bottom: 2px; border-bottom: 2px solid transparent; }
.af-header nav a:hover { color: #fff; }
.af-header nav a.is-active { color: #fff; border-bottom-color: var(--af-accent); }
.af-main { max-width: 1200px; margin: 0 auto; padding: 2rem 1.5rem 4rem; }

.af-pagehead { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin-bottom: 1.5rem; }
.af-pagehead h1 { margin: 0; }

/* Buttons */
.af-btn {
    display: inline-block;
    padding: .5rem .9rem;
    background: #fff;
    border: 1px solid var(--af-border);
    border-radius: var(--af-radius-sm);
    color: var(--af-text);
    text-decoration: none;
    font-family: inherit;
    font-size: .95rem;
    cursor: pointer;
    transition: all .15s;
}
/* Spécificité plus haute que .af-btn pour que [hidden] HTML soit respecté */
.af-btn[hidden] { display: none; }
.af-btn:hover { background: #f3f2ec; }
.af-btn--primary {
    background: var(--af-primary); color: #fff; border-color: var(--af-primary);
    font-weight: 500;
}
.af-btn--primary:hover { background: var(--af-primary-hover); border-color: var(--af-primary-hover); }
.af-btn--danger { background: var(--af-danger); border-color: var(--af-danger); color: #fff; }
.af-btn--danger:hover { filter: brightness(1.1); }

/* Bouton "Effacer cette sélection" — état armé (attend la 2e confirmation) */
.af-btn--danger.is-armed {
    animation: af-pulse-danger 0.9s ease-in-out infinite;
    box-shadow: 0 0 0 0 rgba(179, 52, 29, 0.5);
}
@keyframes af-pulse-danger {
    0%, 100% { box-shadow: 0 0 0 0 rgba(179, 52, 29, 0.6); }
    50%      { box-shadow: 0 0 0 8px rgba(179, 52, 29, 0); }
}
.af-btn--ghost { background: transparent; border-style: dashed; color: var(--af-muted); }

/* Alerts */
.af-alert {
    padding: .8rem 1rem; border-radius: var(--af-radius-sm); margin-bottom: 1rem;
    border-left: 4px solid;
}
.af-alert--ok  { background: #eaf5ee; border-color: var(--af-ok); color: #184a2d; }
.af-alert--err { background: #f8e6e2; border-color: var(--af-err); color: #5a160e; }

/* Cards list */
.af-cards {
    display: grid; gap: 1rem;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}
.af-card {
    background: var(--af-card); border-radius: var(--af-radius);
    padding: 1.2rem; box-shadow: var(--af-shadow);
    display: flex; flex-direction: column; gap: .5rem;
    position: relative;
}
.af-card h3 { margin: 0 0 .1rem; padding-right: 4rem; }

/* Actions rapides en haut à droite de chaque card de la liste : dupliquer
   et supprimer. Discrets au repos, basculent en couleur d'accent au hover.
   Chaque action est un mini-form POST (avec CSRF + confirm pour delete). */
.af-card__quick-actions {
    position: absolute;
    top: .55rem;
    right: .55rem;
    z-index: 5;
    display: flex;
    gap: .25rem;
}
.af-card__quick-action {
    margin: 0;
    padding: 0;
    line-height: 0;
}
.af-card__quick-btn {
    width: 26px;
    height: 26px;
    padding: 0;
    border-radius: 50%;
    border: 1px solid transparent;
    background: rgba(255,255,255,.6);
    color: var(--af-muted);
    line-height: 1;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background .15s, color .15s, border-color .15s, transform .15s;
    font-family: inherit;
}
.af-card__quick-btn:focus-visible {
    outline: none;
    transform: scale(1.05);
}
/* Bouton dupliquer : icône ⧉, devient vert (couleur primaire) au hover */
.af-card__quick-btn--duplicate {
    font-size: 1.05rem;
}
.af-card__quick-btn--duplicate:hover,
.af-card__quick-btn--duplicate:focus-visible {
    background: var(--af-primary, #0f4c2b);
    color: #fff;
    border-color: var(--af-primary, #0f4c2b);
    transform: scale(1.05);
}
/* Bouton supprimer : icône ×, bascule en rouge plein au hover */
.af-card__quick-btn--delete {
    font-size: 1.2rem;
}
.af-card__quick-btn--delete:hover,
.af-card__quick-btn--delete:focus-visible {
    background: #d32f2f;
    color: #fff;
    border-color: #d32f2f;
    transform: scale(1.05);
}
.af-card__preview {
    display: block;
    background: linear-gradient(to bottom, #faf9f1, #ffffff);
    border: 1px solid var(--af-border);
    border-radius: var(--af-radius-sm);
    padding: .75rem .5rem .55rem;
    margin-bottom: .25rem;
    text-align: center;
    text-decoration: none;
    color: var(--af-muted);
    transition: border-color .15s, background .15s, transform .15s;
}
.af-card__preview:hover {
    border-color: var(--af-primary);
    background: linear-gradient(to bottom, #f3f1e8, #ffffff);
}
.af-card__preview:active { transform: scale(.99); }
.af-card__preview svg {
    width: auto;
    max-width: 100%;
    height: auto;
    max-height: 200px;
    display: block;
    margin: 0 auto;
    pointer-events: none;
}
.af-card__preview svg path,
.af-card__preview svg g {
    stroke: var(--af-outline-color, #fff);
    stroke-width: .25;
}
.af-card__preview-meta {
    display: block;
    font-size: .72rem;
    color: var(--af-muted);
    margin-top: .4rem;
    font-weight: 500;
    letter-spacing: .02em;
}
.af-card__actions {
    display: flex; flex-wrap: wrap; gap: .4rem;
    margin-top: auto; padding-top: .7rem;
}
.af-empty {
    background: var(--af-card); padding: 3rem 2rem; border-radius: var(--af-radius);
    text-align: center; box-shadow: var(--af-shadow);
}

/* Forms */
.af-form {
    background: var(--af-card);
    padding: 1.5rem;
    border-radius: var(--af-radius);
    box-shadow: var(--af-shadow);
    max-width: 900px;
    display: grid; gap: 1rem;
}
.af-form label { display: block; font-weight: 500; font-size: .9rem; }
.af-form input[type=text],
.af-form input[type=password],
.af-form input[type=number],
.af-form input[type=file],
.af-form textarea,
.af-form select {
    width: 100%; padding: .5rem .7rem; font-size: .95rem;
    border: 1px solid var(--af-border); border-radius: var(--af-radius-sm);
    margin-top: .3rem; background: #fff; font-family: inherit;
}
.af-form textarea { resize: vertical; }
.af-form input[type=color] {
    height: 36px; padding: 2px; width: 60px; border-radius: var(--af-radius-sm); cursor: pointer;
}
.af-form fieldset {
    border: 1px solid var(--af-border);
    border-radius: var(--af-radius-sm);
    padding: 1rem 1.2rem 1.2rem;
    margin: 0;
}
.af-form legend { padding: 0 .5rem; font-weight: 600; color: var(--af-muted); font-size: .85rem; text-transform: uppercase; letter-spacing: .04em; }
.af-form__actions { display: flex; gap: .5rem; margin-top: .5rem; }
.af-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
@media (max-width: 600px) { .af-grid-2 { grid-template-columns: 1fr; } }
.af-check { display: flex; align-items: center; gap: .5rem; margin: .3rem 0; }
.af-check input { width: auto; margin: 0; }

.af-help { background: #eef0ea; border-left: 3px solid var(--af-primary); padding: .7rem 1rem; border-radius: var(--af-radius-sm); font-size: .9rem; }
.af-help p { margin: .3em 0; }

/* Map type picker (upload form) */
.af-map-type-picker { padding: 1rem 1.2rem 1.2rem; }
.af-map-type-options {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
    gap: .6rem;
    margin: .5rem 0 1rem;
}
.af-map-type-option {
    display: flex; flex-direction: column; gap: .15rem;
    border: 2px solid var(--af-border);
    border-radius: var(--af-radius-sm);
    padding: .8rem 1rem;
    cursor: pointer;
    transition: border-color .15s, background .15s;
    position: relative;
    margin: 0;
    font-weight: 400;
}
.af-map-type-option input[type=radio] {
    position: absolute; opacity: 0; pointer-events: none;
}
.af-map-type-option:hover { border-color: var(--af-accent); background: #fefcf6; }
.af-map-type-option:has(input:checked) {
    border-color: var(--af-primary);
    background: #f3f7f3;
}
.af-map-type-option__title {
    font-size: .95rem; font-weight: 600; color: var(--af-text);
}
.af-map-type-option__desc {
    font-size: .8rem; color: var(--af-muted);
}
.af-map-type-detail {
    border-top: 1px dashed var(--af-border);
    padding-top: .8rem; margin-top: .5rem;
}
.af-map-type-detail[hidden] { display: none; }
.af-map-type-detail select {
    max-width: 480px;
}

/* Source mode picker (CSV vs empty map) — same visual language as map type */
.af-source-mode-picker { padding: 1rem 1.2rem 1.2rem; }
.af-source-mode-options {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: .6rem;
    margin: .5rem 0 1rem;
}
.af-source-mode-option {
    display: flex; flex-direction: column; gap: .15rem;
    border: 2px solid var(--af-border);
    border-radius: var(--af-radius-sm);
    padding: .8rem 1rem;
    cursor: pointer;
    transition: border-color .15s, background .15s;
    position: relative;
    margin: 0;
    font-weight: 400;
}
.af-source-mode-option input[type=radio] {
    position: absolute; opacity: 0; pointer-events: none;
}
.af-source-mode-option:hover { border-color: var(--af-accent); background: #fefcf6; }
.af-source-mode-option:has(input:checked) {
    border-color: var(--af-primary);
    background: #f3f7f3;
}
.af-source-mode-option--disabled {
    opacity: .55;
    cursor: not-allowed;
    pointer-events: none;
}
.af-source-mode-option--disabled em {
    font-style: italic;
    font-weight: normal;
    color: var(--af-muted);
}
.af-source-mode-option__title {
    font-size: .95rem; font-weight: 600; color: var(--af-text);
}
.af-source-mode-option__desc {
    font-size: .8rem; color: var(--af-muted);
}
.af-source-mode-detail {
    border-top: 1px dashed var(--af-border);
    padding-top: .8rem; margin-top: .5rem;
}
.af-source-mode-detail[hidden] { display: none; }

/* Years editor (mode "carte vide") */
.af-years-editor { display: grid; gap: .4rem; margin-top: .3rem; }
.af-year-rows { display: flex; gap: .4rem; flex-wrap: wrap; }
.af-year-row {
    display: flex; align-items: center; gap: .25rem;
    background: #fff;
    border: 1px solid var(--af-border);
    border-radius: var(--af-radius-sm);
    padding: .15rem;
}
.af-year-row input {
    width: 70px;
    border: 0;
    padding: .35rem .55rem;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: .9rem;
    text-align: center;
    background: transparent;
    margin: 0;
}
.af-year-row input:focus {
    outline: none;
    background: #fafaf3;
}
.af-year-remove {
    padding: .15rem .45rem;
    font-size: 1rem;
    line-height: 1;
    background: transparent;
    border: 0;
    color: var(--af-muted);
    cursor: pointer;
}
.af-year-remove:hover {
    color: var(--af-danger);
}
.af-year-add {
    justify-self: start;
    margin-top: .25rem;
}

.af-muted { color: var(--af-muted); }
.af-small { font-size: .85rem; }

/* Edit grid */
.af-edit-grid {
    display: grid; gap: 1.5rem;
    grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
}
@media (max-width: 1000px) { .af-edit-grid { grid-template-columns: 1fr; } }
.af-edit-form { max-width: none; }
.af-preview { position: sticky; top: 1rem; align-self: start; }
.af-preview__frame {
    width: 100%; height: 600px; border: 1px solid var(--af-border);
    border-radius: var(--af-radius); background: #fff;
}

/* Ranges editor */
.af-ranges { display: grid; gap: .4rem; margin-top: .5rem; }
.af-range-row {
    display: grid;
    grid-template-columns: 90px 90px 44px 1fr auto;
    gap: .4rem;
    align-items: center;
}
.af-range-row input { margin-top: 0; font-size: .85rem; padding: .35rem .5rem; }
.af-range-remove { padding: .3rem .55rem; font-size: 1rem; line-height: 1; }
.af-range-add { justify-self: start; margin-top: .3rem; }
@media (max-width: 600px) {
    .af-range-row { grid-template-columns: 1fr 1fr; }
    .af-range-row input[type=color] { grid-column: span 1; }
}

/* Code blocks */
.af-code-block { position: relative; }
.af-code-block pre { margin: .3rem 0; padding-right: 5rem; }
.af-code-block .af-copy {
    position: absolute; top: .5rem; right: .5rem;
    padding: .3rem .7rem; font-size: .8rem;
    background: rgba(255,255,255,.1); color: #fff; border-color: rgba(255,255,255,.2);
}
.af-code-block .af-copy:hover { background: rgba(255,255,255,.2); }
.af-code-block .af-copy.is-ok { background: var(--af-ok); border-color: var(--af-ok); }

details { margin: 1rem 0; }
summary { cursor: pointer; color: var(--af-primary); font-weight: 500; }

/* ============== Embed (public map) ============== */
.af-embed {
    background: #fff;
    padding: 0;
}
.af-map-wrap {
    max-width: 1000px;
    margin: 0 auto;
    padding: 1rem 1.25rem 1.5rem;
    position: relative;
}
.af-map-head {
    display: flex; justify-content: space-between; align-items: flex-start;
    gap: 1rem; flex-wrap: wrap; margin-bottom: 1rem;
}
.af-map-title { font-size: 1.3rem; margin: 0 0 .25rem; color: var(--af-primary); }
.af-map-desc  { margin: 0; font-size: .9rem; color: var(--af-muted); }
.af-map-controls { display: flex; gap: .75rem; flex-wrap: wrap; }
.af-map-controls label { font-size: .8rem; color: var(--af-muted); font-weight: 500; display: flex; flex-direction: column; gap: .25rem; }
.af-map-controls select {
    padding: .4rem .6rem;
    border: 1px solid var(--af-border);
    border-radius: var(--af-radius-sm);
    font-family: inherit;
    font-size: .9rem;
    background: #fff;
}

.af-map-stage {
    display: grid;
    grid-template-columns: 1fr 220px;
    gap: 1rem;
    align-items: start;
}
@media (max-width: 700px) {
    .af-map-stage { grid-template-columns: 1fr; }
}

.af-svg-wrap {
    width: 100%;
    position: relative; /* pour positionner les boutons zoom en absolu */
}
.af-svg-wrap svg {
    width: 100%; height: auto; display: block;
    max-height: 75vh;
    /* Le zoom souris (molette) et le pinch (2 doigts) sont DÉSACTIVÉS au
       niveau de l'app. Le zoom ne se fait que via les boutons +/-/reset.
       touch-action: none empêche le navigateur d'intercepter pour pinch,
       le pan à 1 doigt reste géré par les handlers JS (touchstart/move). */
    touch-action: none;
    /* Curseur géré dynamiquement en JS selon le niveau de zoom :
       'grab' uniquement si un zoom avant a été appliqué. */
}
.af-svg-wrap svg:active { cursor: inherit; }
/* Filet visible uniquement quand la carte est zoomée (avant ou arrière).
   Géré en JS via la classe .is-zoomed posée sur le wrapper. */
.af-svg-wrap.is-zoomed {
    border: 1px solid #eee;
}
.af-svg-wrap path, .af-svg-wrap g {
    stroke: var(--af-outline-color, #fff); stroke-width: 1;
    transition: opacity .15s, filter .15s, stroke .2s;
    cursor: default;
}
/* Hover : on retire le brightness du path original — l'effet de relief
   est désormais assuré par le clone scalé en premier plan
   (.af-hover-clone--active). On garde le cursor pointer. */
.af-svg-wrap path[data-iso]:hover {
    cursor: pointer;
}
/* Cartes à symboles ou cercles : pas d'effet pointer sur les pays sans
   aucune donnée (data-has-symbol / data-has-circle posés en JS). */
.af-svg-wrap.af-viz-symbols path[data-iso]:not([data-has-symbol]):hover,
.af-svg-wrap.af-viz-circles path[data-iso]:not([data-has-circle]):hover,
.af-svg-wrap.af-viz-squares path[data-iso]:not([data-has-square]):hover {
    cursor: default;
}
/* Cartes à symboles, cercles ou squares : pour les pays AVEC données, le
   clone scale s'occupe de l'effet visuel. On garde juste le cursor pointer. */
.af-svg-wrap.af-viz-symbols path[data-iso][data-has-symbol]:hover,
.af-svg-wrap.af-viz-circles path[data-iso][data-has-circle]:hover,
.af-svg-wrap.af-viz-squares path[data-iso][data-has-square]:hover {
    cursor: pointer;
}

/* ============================================================
   viz_type = 'squares' : la carte d'origine est masquée, seuls les
   carrés sont visibles. Les paths gardent leur géométrie mais
   sont neutralisés visuellement et au pointer (les events vont
   directement aux rects, ce qui permet de scaler le carré au survol).
   ============================================================ */
.af-svg-wrap.af-viz-squares path[data-iso] {
    /* En mode cartogram carrés, la silhouette du pays est TRANSPARENTE.
       Seuls les carrés colorés (générés en JS dans le squaresLayer) sont
       visibles. Cela laisse passer le fond (page_bg_color, motif, etc.)
       à travers la silhouette du pays.
       Auparavant : fill: #ffffff → masquait le fond et donnait un aspect
       "papier blanc" derrière les carrés. */
    fill: transparent;
    stroke: none;
    /* Désactive le hover/click sur la silhouette de fond : les events
       passent directement aux rects qui sont la vraie représentation
       du pays en mode squares. */
    pointer-events: none;
}
/* Le mix-blend-mode multiply doit être ISOLÉ dans son propre contexte
   de stacking, sinon il se mélangerait avec tout ce qui est dessous
   (page, header, autres éléments). isolation:isolate crée une "boîte"
   de stacking dans laquelle le multiply n'agit qu'entre les rects
   du squaresLayer entre eux. */
.af-svg-wrap.af-viz-squares {
    isolation: isolate;
}
/* Layer des carrés. L'effet "produit" Photoshop est appliqué à CHAQUE
   <rect> individuellement (pas au <g> parent) car mix-blend-mode entre
   éléments SVG ne fonctionne qu'à ce niveau — appliqué sur le <g>, le
   blend serait fait avec ce qui est SOUS le <g>, pas entre les rects
   du <g> entre eux.
   Pointer-events: auto pour que les rects reçoivent les events du
   pointeur (le squaresLayer est créé avec pointer-events="none" en
   JS pour la cohérence avec les autres layers, on l'override ici
   pour les rects spécifiquement). */
.af-svg-wrap .af-squares-layer {
    pointer-events: none;
}
.af-svg-wrap .af-squares-layer rect {
    /* Pas de filet : aucun stroke (la règle générique
       .af-svg-wrap path/g définit un stroke par défaut, on doit le
       neutraliser explicitement sur les rects de ce layer). */
    stroke: none;
    /* Effet "Produit" : couleurs des chevauchements multipliées,
       comme dans Photoshop. */
    mix-blend-mode: multiply;
    /* Pointer-events sur les rects : reçoivent hover et click. */
    pointer-events: auto;
    cursor: pointer;
    /* PAS de transition CSS sur fill : le JS commande la couleur à
       60 FPS pendant la timeline (interpolation continue via
       colorForGradient). Une transition CSS créerait une traîne
       visuelle qui empêcherait le fondu de suivre. */
}
/* Le filet de hover a été retiré — l'effet brightness suffit pour
   indiquer le survol. Le filet "lien" est en JS (clip-path). */
.af-svg-wrap .af-hover {
    /* stroke géré en JS si lien — sinon rien (juste brightness via :hover) */
}

/* ============================================================
   Effet hover animé : le pays survolé est cloné dans un layer
   au-dessus de tout (.af-hover-scale-layer). Le clone se met à
   l'échelle 1.05× depuis son centre, avec un léger drop-shadow,
   et l'effet est animé en entrée (200ms) et en sortie (180ms).
   Le pays original reste à sa taille normale en dessous.
   ============================================================ */
.af-svg-wrap .af-hover-scale-layer {
    pointer-events: none;
}
.af-hover-clone {
    /* CRITIQUE : transform-box fill-box + transform-origin center font que
       le scale s'effectue depuis le centre du path lui-même, pas depuis
       (0,0) du viewBox. Supporté par tous les navigateurs modernes. */
    transform-box: fill-box;
    transform-origin: center;
    transform: scale(1.0);
    /* Stroke identique aux pays normaux (var --af-outline-color, héritée
       du contexte SVG). Évite la double frontière au scale. */
    stroke: var(--af-outline-color, #fff);
    stroke-width: 1;
    /* Transition douce : 200ms à l'entrée (cubic-bezier "ease-out" pour
       un mouvement naturel qui ralentit en fin). */
    transition: transform 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.af-hover-clone--active {
    transform: scale(1.05);
}

/* Animation pulse "tap" : applicable à TOUT clone hover (path ou rect).
   Au survol, le pays/carré jump à 1.20 (instantané — c'est l'attaque),
   puis revient progressivement à 1.0 en 3 secondes avec une courbe
   ease-out. Effet de "rebond" qui attire l'œil sans garder le pays
   agrandi tant qu'on survole.
   La transition CSS de la classe générique .af-hover-clone est
   neutralisée quand --pulse est actif ; on utilise à la place
   l'animation @keyframes qui peut être re-jouée à chaque nouveau
   survol via un toggle de classe + reflow forcé côté JS. */
.af-hover-clone--pulse {
    transition: none;
    animation: af-hover-pulse 3s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
@keyframes af-hover-pulse {
    0%   { transform: scale(1.20); }   /* attaque : agrandi instantanément */
    100% { transform: scale(1.00); }   /* retour à la taille d'origine */
}

/* Rétro-compat : ancienne classe pour squares (gardée pour ne rien casser
   ailleurs, mais réutilise les keyframes unifiés ci-dessus) */
.af-hover-clone--squares {
    transition: none;
    transform: scale(1.0);
}
.af-hover-clone--squares.af-hover-clone--pulse {
    animation: af-hover-pulse 3s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
@keyframes af-square-pulse {
    0%   { transform: scale(1.20); }
    100% { transform: scale(1.00); }
}
/* Cache le stroke du path ORIGINAL quand il est survolé : sinon on aurait
   une double frontière (la sienne à sa taille, plus celle du clone scalé
   à 1.05×). Le clone reprend exactement la couleur outline-color, donc
   l'utilisateur voit un seul contour cohérent. */
.af-svg-wrap path[data-iso].af-hover {
    stroke: transparent;
}

/* Contrôles de zoom (boutons +/-/reset en haut à droite du SVG) */
.af-zoom-controls {
    position: absolute;
    top: 10px;
    right: 10px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    z-index: 5;
}
.af-zoom-btn {
    width: 34px;
    height: 34px;
    background: #fff;
    border: 1px solid var(--af-border);
    border-radius: 6px;
    font-size: 18px;
    font-weight: 600;
    line-height: 1;
    color: var(--af-text);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 1px 3px rgba(0,0,0,.08);
    transition: background .15s, border-color .15s;
    -webkit-user-select: none;
    user-select: none;
    padding: 0;
    font-family: inherit;
}
.af-zoom-btn:hover {
    background: #f5f4ee;
    border-color: var(--af-text);
}
.af-zoom-btn:active {
    background: #e8e6dd;
}
@media (max-width: 700px) {
    .af-zoom-btn { width: 38px; height: 38px; font-size: 20px; }
}

/* Bouton mute/unmute pour la sonification — pose-en supplément des
   contrôles de zoom. Hérite de .af-zoom-btn pour le look général,
   bascule entre les deux icônes SVG selon l'état muet/actif. */
.af-sound-btn {
    margin-top: 4px;
}
/* Icônes SVG : taille fixe 16×16, héritage de la couleur du bouton via
   currentColor (noir par défaut, blanc sur fond accent quand actif). */
.af-sound-btn .af-sound-icon {
    width: 16px;
    height: 16px;
    display: block;
}
/* Bascule entre on/off via display.
   IMPORTANT : !important pour sécuriser contre les overrides éventuels
   d'autres styles sur le SVG (rencontré sur Firefox où la spécificité
   variait selon l'ordre de cascade). */
.af-sound-btn .af-sound-icon--off { display: none !important; }
.af-sound-btn .af-sound-icon--on  { display: block !important; }
.af-sound-btn--muted .af-sound-icon--on  { display: none !important; }
.af-sound-btn--muted .af-sound-icon--off { display: block !important; }
/* État actif (son ON) : fond accent + icône blanche */
.af-sound-btn:not(.af-sound-btn--muted) {
    background: var(--af-primary, #0f4c2b);
    color: #fff;
    border-color: var(--af-primary, #0f4c2b);
}
.af-sound-btn:not(.af-sound-btn--muted):hover {
    background: #0a3a20;
}
/* État muet : reste sobre (pas de fond accent). currentColor = couleur
   normale du bouton, donc icône en gris muted. */
.af-sound-btn--muted {
    color: var(--af-muted, #6b7370);
}

/* ============================================================
   Pays sélectionnés pour la sonification (drones pendant timeline)
   Indication visuelle = picto haut-parleur SVG superposé au pays
   (opacité 30%), placé au centroïde via le layer .af-sn-icons-layer.
   Pas d'altération de la couleur de fond ni du contour des pays — la
   carte garde son aspect normal.
   ============================================================ */
.af-svg-wrap .af-sn-icons-layer {
    pointer-events: none;
}
.af-svg-wrap .af-sn-icon {
    /* L'opacité est déjà fixée à 0.3 via attribut SVG côté JS, mais on
       l'enforce ici aussi pour blinder. Animation douce à l'apparition. */
    opacity: 0.3 !important;
    transition: opacity .25s;
}

/* ============================================================
   Timeline animée (lecture play/pause + slider + nav prev/next)

   Placement :
   - Desktop : sous le bloc carte+légende, pleine largeur du wrapper
   - Mobile  : entre la carte et la légende (légende order:-1 mise APRÈS,
     timeline reste avant la légende)
   Avec marqueurs verticaux pour chaque année (filets + labels).
   ============================================================ */
.af-timeline {
    width: 100%;
    box-sizing: border-box;
    margin: .8rem 0 .4rem;
    padding: .8rem 1rem .9rem;
    background: rgba(255, 255, 255, 0.98);
    border: 1px solid var(--af-border);
    border-radius: var(--af-radius);
    -webkit-user-select: none;
    user-select: none;
}
.af-timeline__controls {
    display: flex;
    align-items: center;
    gap: .5rem;
}
.af-timeline__btn {
    width: 30px;
    height: 30px;
    background: transparent;
    border: none;
    border-radius: 50%;
    font-size: 13px;
    line-height: 1;
    color: var(--af-text);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    padding: 0;
    transition: background .15s, color .15s;
    font-family: inherit;
}
.af-timeline__btn:hover,
.af-timeline__btn:focus-visible {
    background: rgba(0, 0, 0, .07);
    outline: none;
}
.af-timeline__btn:active {
    background: rgba(0, 0, 0, .12);
}
.af-timeline__btn--play {
    width: 34px;
    height: 34px;
    background: var(--af-primary, #0f4c2b);
    color: #fff;
}
.af-timeline__btn--play:hover,
.af-timeline__btn--play:focus-visible {
    background: #0a3a20;
    color: #fff;
}
.af-timeline__icon { display: inline-block; line-height: 1; }
.af-timeline__icon--pause { display: none; font-size: 11px; letter-spacing: -1px; }
.af-timeline--playing .af-timeline__icon--play  { display: none; }
.af-timeline--playing .af-timeline__icon--pause { display: inline-block; }
.af-timeline__icon--play { padding-left: 2px; }

.af-timeline__btn--prev,
.af-timeline__btn--next {
    font-size: 18px;
    width: 26px;
    height: 26px;
    color: var(--af-muted);
}
.af-timeline__btn--prev:hover,
.af-timeline__btn--next:hover {
    color: var(--af-text);
}

/* Wrapper du track : occupe l'espace flexible et empile slider + ticks. */
.af-timeline__track-wrap {
    flex: 1 1 auto;
    position: relative;
    min-width: 0;
    margin: 0 .25rem;
    padding-bottom: 1.5rem;  /* place pour les labels années sous la timeline */
}
.af-timeline__slider {
    -webkit-appearance: none;
    appearance: none;
    width: 100%;
    display: block;
    height: 6px;
    background: rgba(0, 0, 0, .12);
    border-radius: 3px;
    outline: none;
    cursor: pointer;
    margin: 0;
}
.af-timeline__slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 16px;
    height: 16px;
    background: var(--af-primary, #0f4c2b);
    border-radius: 50%;
    cursor: pointer;
    border: 2px solid #fff;
    box-shadow: 0 0 3px rgba(0,0,0,.25);
    transition: transform .12s;
}
.af-timeline__slider::-webkit-slider-thumb:hover {
    transform: scale(1.15);
}
.af-timeline__slider::-moz-range-thumb {
    width: 16px;
    height: 16px;
    background: var(--af-primary, #0f4c2b);
    border-radius: 50%;
    cursor: pointer;
    border: 2px solid #fff;
    box-shadow: 0 0 3px rgba(0,0,0,.25);
}

/* Conteneur des ticks (filets verticaux + labels années) — superposé au
   slider, occupant l'intégralité du track-wrap. Chaque tick est positionné
   en absolute via "left: x%" calculé en JS au resize. */
.af-timeline__ticks {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: 100%;
    pointer-events: none;  /* le slider reçoit les events ; ticks ré-active leur own */
}
.af-timeline__tick {
    position: absolute;
    top: 0;
    transform: translateX(-50%);
    background: transparent;
    border: none;
    padding: 0;
    margin: 0;
    cursor: pointer;
    font-family: inherit;
    line-height: 1;
    color: var(--af-muted);
    pointer-events: auto;  /* on les active explicitement */
    display: flex;
    flex-direction: column;
    align-items: center;
    height: 100%;
}
.af-timeline__tick-bar {
    display: block;
    width: 1px;
    height: 8px;
    background: rgba(0, 0, 0, .35);
    margin-top: -1px;  /* aligné avec le track */
    transition: background .15s, height .15s, width .15s;
}
.af-timeline__tick-label {
    margin-top: .55rem;
    font-size: .68rem;
    font-variant-numeric: tabular-nums;
    color: var(--af-muted);
    transition: color .15s, font-weight .15s;
    letter-spacing: .02em;
}
.af-timeline__tick:hover .af-timeline__tick-bar {
    background: var(--af-text);
    height: 11px;
}
.af-timeline__tick:hover .af-timeline__tick-label {
    color: var(--af-text);
}
.af-timeline__tick--active .af-timeline__tick-bar {
    background: var(--af-primary, #0f4c2b);
    width: 2px;
    height: 12px;
}
.af-timeline__tick--active .af-timeline__tick-label {
    color: var(--af-primary, #0f4c2b);
    font-weight: 600;
}

/* Label année (gros, à droite) — visible UNIQUEMENT sur mobile.
   Sur desktop, l'information est déjà dans les labels sous chaque tick,
   donc on masque pour éviter la redondance. */
.af-timeline__year {
    font-weight: 600;
    font-size: 1rem;
    color: var(--af-text);
    min-width: 48px;
    text-align: center;
    padding: 0 .4rem;
    flex-shrink: 0;
    font-variant-numeric: tabular-nums;
    display: none;  /* caché par défaut, ré-affiché sur mobile */
}

/* ============================================================
   Animations fluides sur les cercles proportionnels
   Les attributs SVG r et cy sont mis à jour à chaque frame
   d'animation par drawCircles(yearIdxFrac) avec interpolation
   linéaire entre les deux années bracket. requestAnimationFrame
   pilote la cadence. Pas de transition CSS car Safari ne supporte
   pas la transition d'attributs SVG (r, cy) — l'animation passe
   donc par recalcul JS continu, qui marche sur tous les navigateurs.
   ============================================================ */
.af-circles-layer .af-country-circles circle {
    /* Aucune transition CSS : l'animation est pilotée par JS via rAF. */
}

@media (max-width: 700px) {
    .af-timeline {
        padding: .7rem .8rem .8rem;
    }
    /* Sur mobile : on AFFICHE le label année (gros, à droite) et on
       MASQUE les labels année sous chaque tick (qui prendraient trop
       de place horizontale et seraient illisibles). */
    .af-timeline__year {
        display: inline-block;
        font-size: .95rem;
        min-width: 40px;
    }
    .af-timeline__tick-label {
        display: none;
    }
    /* Le wrapper de track perd sa marge basse pour les labels qu'on n'a
       plus, mais garde un petit padding pour les ticks-bars qui dépassent */
    .af-timeline__track-wrap {
        padding-bottom: .5rem;
    }
}

/* Sur mobile : la légende passe APRÈS la timeline.
   Desktop = ordre naturel (carte+légende dans af-map-stage, puis timeline).
   Mobile  = timeline reste à sa place ; on baisse l'ordre du af-map-stage
            pour qu'il reste avant. C'est déjà le cas (timeline siblings
            après af-map-stage). Sur mobile, à l'intérieur de
            af-map-stage, la légende est sous la carte (column).
            Pour pousser timeline EN AVANT de la légende sur mobile, on
            sort visuellement la timeline du flow standard avec un order. */
@media (max-width: 700px) {
    .af-map-wrap {
        display: flex;
        flex-direction: column;
    }
    .af-timeline { order: 5; }
    /* Le af-map-stage devient lui-même flex-column et on ré-ordonne pour
       que la légende soit après la timeline. */
    .af-map-stage {
        display: flex;
        flex-direction: column;
    }
    .af-map-stage .af-svg-wrap { order: 1; }
    /* La timeline est à l'extérieur, donc on ne peut pas l'insérer entre
       svg et légende via order direct. Astuce : on déplace la timeline
       en order:2 et la légende en order:3 — mais la timeline est sibling
       du af-map-stage, donc d'order différent dans le parent. La règle
       af-map-wrap flex column fait que :
         1) af-map-head
         2) af-map-stage (carte + légende empilées)
         3) timeline
         4) footer
       Ce qui ne match pas la demande "timeline avant légende" sur mobile.
       Solution : sur mobile, la légende est extraite par position absolute ?
       Trop fragile. À la place, on accepte légende → timeline → footer,
       ce qui reste très lisible. Si vraiment besoin d'inverser, il
       faudrait restructurer le HTML. */
}


/* Legend */
.af-legend {
    background: transparent;
    border: none;
    border-radius: 0;
    padding: .9rem 0;
    font-size: .85rem;
}
.af-legend__title { margin: 0 0 .5rem; font-size: .85rem; color: var(--af-text); font-weight: 600; }
.af-legend__list { list-style: none; padding: 0; margin: 0; display: grid; gap: .3rem; }
.af-legend__list li { display: flex; align-items: center; gap: .5rem; }
.af-legend__swatch {
    width: 18px; height: 18px;
    border-radius: 50%;
    border: none;
    flex-shrink: 0;
}
/* Légende d'une carte à symboles : SVG inline pour rendre la même forme
   que sur la carte (rond / pointeur / carré / triangle). */
.af-legend__symbol {
    width: 20px; height: 20px;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.af-legend__symbol svg {
    width: 100%; height: 100%;
}

.af-map-foot {
    margin-top: 1rem;
    padding-top: .75rem;
    border-top: 1px solid var(--af-border);
    font-size: .8rem;
    color: var(--af-muted);
    text-align: right;
}

/* Tooltip */
.af-tooltip {
    position: fixed;
    background: #ffffff;
    color: #333;
    padding: .5rem .75rem;
    border-radius: var(--af-radius-sm);
    font-size: .85rem;
    pointer-events: none;
    z-index: 1000;
    box-shadow: 0 4px 14px rgba(0,0,0,.25);
    max-width: 240px;
    line-height: 1.35;
}
.af-tooltip strong { display: block; font-weight: 600; margin-bottom: .15rem; }
.af-tooltip .af-tt-val { color: #333; }

/* Tooltip pour cartes à symboles (liste d'indicateurs présents) */
.af-tooltip .af-tt-list {
    list-style: none;
    margin: .35rem 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .2rem;
}
.af-tooltip .af-tt-list li {
    display: flex;
    align-items: center;
    gap: .45rem;
}
.af-tooltip .af-tt-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    flex-shrink: 0;
    display: inline-block;
}
.af-tooltip .af-tt-empty {
    color: #333;
    font-style: italic;
    font-size: .85em;
}

/* Couche overlay des pastilles (cartes à symboles) — ajoutée dynamiquement
   par map.js via <g class="af-symbols-layer">. pointer-events:none pour que
   le hover passe à travers et atteigne le path du pays en dessous. */
.af-symbols-layer { pointer-events: none; }
/* Transition sur le rayon (cercle) ou la géométrie (autres formes : on
   anime les attributs via JS, pas de transition CSS sur d/points/etc.).
   Pour le cercle, transition souple sur r. */
.af-symbols-layer .af-country-symbols circle {
    transition: r .15s ease-out;
}

/* Couche overlay des cercles proportionnels (cartes à cercles) — ajoutée
   dynamiquement par map.js via <g class="af-circles-layer">. */
.af-circles-layer { pointer-events: none; }
/* Override l'inheritance CSS du stroke (la règle .af-svg-wrap g s'applique
   aussi au layer des cercles, et stroke est inheritable en SVG → les
   <circle> recevraient un contour aux couleurs du contour des pays). */
.af-circles-layer,
.af-circles-layer circle {
    stroke: none;
    stroke-width: 0;
}

/* Couche overlay des contours (filets de hover et de lien) — fill: none
   en CSS pour overrider à coup sûr l'attribut fill="..." en cas de
   réutilisation via clone. */
.af-outlines-layer path { fill: none; }

/* Légende d'une carte à cercles : pastille ronde uniformément colorée
   (≠ d'un symbol qui peut être un pin/triangle/carré). */
.af-legend__list--circles .af-legend__circle-swatch {
    display: inline-block;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    flex-shrink: 0;
    border: 1px solid rgba(0,0,0,.08);
}
.af-legend__list--circles li {
    display: flex;
    align-items: center;
    gap: .5rem;
}

/* Légende des tailles (échelle) : 3 cercles concentriques alignés en bas
   avec lignes guides et labels. Le SVG est généré par map.js. */
.af-legend__title--secondary {
    font-size: .78rem;
    color: var(--af-muted);
    font-weight: 500;
    margin: 1rem 0 .35rem;
    text-transform: uppercase;
    letter-spacing: .05em;
}
.af-legend__sizes {
    margin-top: .5rem;
    padding-top: .5rem;
    border-top: 1px solid var(--af-border);
}
.af-legend__sizes-stack {
    display: flex;
    align-items: flex-end;
    justify-content: flex-start;
}
.af-legend__sizes-stack svg {
    display: block;
    max-width: 100%;
}

/* ============== Data editor (tableau d'édition) ============== */
.af-pagehead__actions { display: flex; gap: .5rem; flex-wrap: wrap; }

/* Panneau d'import CSV (collapsible <details>) */
.af-import-csv-panel {
    background: var(--af-card);
    border: 1px solid var(--af-border);
    border-radius: var(--af-radius);
    padding: .8rem 1.2rem;
    margin-bottom: 1rem;
}
.af-import-csv-panel > summary {
    cursor: pointer;
    font-weight: 600;
    list-style: none;
    user-select: none;
    padding: .2rem 0;
}
.af-import-csv-panel > summary::-webkit-details-marker { display: none; }
.af-import-csv-panel > summary::before {
    content: "▸ ";
    display: inline-block;
    transition: transform .15s;
}
.af-import-csv-panel[open] > summary::before {
    transform: rotate(90deg);
}
.af-import-csv-panel > form {
    margin-top: .8rem;
    padding-top: .8rem;
    border-top: 1px solid var(--af-border);
}
.af-import-csv-panel .af-help code {
    background: rgba(0,0,0,.05);
    padding: 1px 5px;
    border-radius: 3px;
    font-size: .9em;
}

/* --- Columns manager --- */
.af-cols-manager {
    background: var(--af-card);
    border-radius: var(--af-radius);
    box-shadow: var(--af-shadow);
    padding: .8rem 1.2rem;
    margin-bottom: 1rem;
}
.af-cols-manager > summary {
    font-weight: 600;
    color: var(--af-primary);
    padding: .35rem 0;
    cursor: pointer;
    list-style: none;
}
.af-cols-manager > summary::-webkit-details-marker { display: none; }
.af-cols-manager > summary::before {
    content: '▶';
    display: inline-block;
    margin-right: .5rem;
    font-size: .75em;
    transition: transform .15s;
}
.af-cols-manager[open] > summary::before { transform: rotate(90deg); }
.af-cols-help { margin: .6rem 0 1rem; }

.af-cols-list {
    display: grid; gap: .4rem;
    margin-bottom: 1rem;
}
.af-col-item {
    display: grid;
    grid-template-columns: 90px minmax(140px, 200px) minmax(0, 1fr) 130px 40px;
    gap: .5rem;
    align-items: center;
    padding: .35rem;
    border-radius: var(--af-radius-sm);
    transition: background .12s;
}
.af-col-item:hover { background: #fafaf6; }
.af-col-item--link { background: #f5f9f5; }
.af-col-item--link:hover { background: #eef5ee; }

.af-col-type-badge {
    display: inline-flex;
    align-items: center;
    gap: .2rem;
    padding: .2rem .45rem;
    border-radius: 3px;
    font-size: .75rem;
    font-weight: 500;
    line-height: 1;
    white-space: nowrap;
}
.af-col-type-badge--num  { background: #f0eddf; color: var(--af-muted); }
.af-col-type-badge--link { background: #e3efe3; color: var(--af-primary); }
.af-col-unit--na {
    color: var(--af-muted);
    text-align: center;
    font-style: italic;
    font-size: .85rem;
}

.af-col-key {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    background: #f3f1e8;
    padding: .35rem .5rem;
    border-radius: 3px;
    font-size: .78rem;
    color: var(--af-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.af-col-item input {
    padding: .4rem .55rem;
    border: 1px solid var(--af-border);
    border-radius: 3px;
    font-family: inherit;
    font-size: .9rem;
    background: #fff;
}
.af-col-item input:focus {
    outline: none;
    border-color: var(--af-primary);
    box-shadow: 0 0 0 2px rgba(15,76,43,.12);
}
.af-col-del {
    padding: .25rem .5rem;
    font-size: .95rem;
    line-height: 1;
    background: transparent;
    border-color: transparent;
}
.af-col-del:hover {
    background: #fff;
    border-color: var(--af-danger);
    color: var(--af-danger);
}

.af-cols-add {
    display: grid;
    grid-template-columns: 200px minmax(0, 1fr) 130px auto;
    gap: .5rem;
    padding-top: .9rem;
    border-top: 1px dashed var(--af-border);
}
.af-new-col-type {
    padding: .45rem .6rem;
    border: 1px solid var(--af-border);
    border-radius: 3px;
    font-family: inherit;
    font-size: .9rem;
    background: #fff;
}
.af-cols-add input {
    padding: .45rem .6rem;
    border: 1px solid var(--af-border);
    border-radius: 3px;
    font-family: inherit;
    font-size: .9rem;
    background: #fff;
}
@media (max-width: 700px) {
    .af-col-item, .af-cols-add { grid-template-columns: 1fr; }
    .af-col-key { width: 100%; }
}

/* ============================================================
   Cellules de type "lien" dans le tableau de données
   ============================================================ */
.af-link-cell-wrap {
    min-width: 280px;
}
.af-link-cell {
    display: flex;
    align-items: center;
    gap: .15rem;
    background: #fff;
    border: 1px solid var(--af-border);
    border-radius: 3px;
    padding: .15rem .25rem;
    position: relative;
}
.af-link-cell:focus-within {
    border-color: var(--af-primary);
    box-shadow: 0 0 0 2px rgba(15,76,43,.12);
}
.af-link-cell.af-link-cell--uploading {
    background: #fff8e3;
    border-color: #eecf6c;
}
.af-link-cell.af-link-cell--uploading::after {
    content: '⏳ envoi…';
    position: absolute;
    right: .4rem;
    top: 50%;
    transform: translateY(-50%);
    font-size: .8rem;
    color: var(--af-muted);
    pointer-events: none;
    background: #fff8e3;
    padding: 0 .3rem;
}
.af-link-cell .af-link-url {
    flex: 1;
    min-width: 0;
    border: 0;
    background: transparent;
    padding: .35rem .35rem;
    font-family: inherit;
    font-size: .9rem;
    margin: 0;
}
.af-link-cell .af-link-url:focus { outline: none; }
.af-link-cell .af-link-filebadge {
    flex: 1;
    min-width: 0;
    padding: .35rem .45rem;
    background: #f3f7f3;
    border-radius: 3px;
    font-size: .85rem;
    color: var(--af-text);
    display: flex;
    align-items: center;
    gap: .35rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    cursor: pointer;
}
.af-link-cell .af-link-filebadge:hover {
    background: #e8f0e8;
}
.af-link-cell .af-link-filename {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}
.af-link-cell .af-link-pickfile,
.af-link-cell .af-link-preview,
.af-link-cell .af-link-clear {
    padding: .25rem .4rem;
    font-size: .9rem;
    line-height: 1;
    background: transparent;
    border-color: transparent;
    flex-shrink: 0;
}
.af-link-cell .af-link-preview:hover {
    background: #fffbeb;
    border-color: #d4b03e;
    color: #8a6e1c;
}
.af-link-cell .af-link-pickfile:hover {
    background: #f3f7f3;
    border-color: var(--af-primary);
    color: var(--af-primary);
}
.af-link-cell .af-link-clear:hover {
    background: #fff;
    border-color: var(--af-danger);
    color: var(--af-danger);
}

/* En-tête de colonne lien : badge moins prononcé */
.af-data-table th .af-col-type-badge {
    margin-left: .3rem;
    font-size: .65rem;
}

/* ============================================================
   Lightbox / preview popup pour images
   ============================================================ */
.af-lightbox {
    position: fixed;
    inset: 0;
    background: rgba(15, 25, 18, 0.92);
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2rem;
    animation: af-lightbox-fade .15s ease;
    cursor: zoom-out;
}
@keyframes af-lightbox-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}
.af-lightbox-content {
    max-width: 95vw;
    max-height: 95vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .8rem;
    cursor: default;
}
.af-lightbox-content img {
    max-width: 100%;
    max-height: 80vh;
    border-radius: var(--af-radius-sm);
    box-shadow: 0 8px 32px rgba(0,0,0,.4);
    background: #fff;
}
.af-lightbox-caption {
    color: rgba(255,255,255,.85);
    font-size: .9rem;
    text-align: center;
    word-break: break-all;
    max-width: 600px;
}
.af-lightbox-close {
    position: absolute;
    top: 1rem;
    right: 1rem;
    background: rgba(255,255,255,.95);
    border: 0;
    width: 2.4rem;
    height: 2.4rem;
    border-radius: 50%;
    font-size: 1.4rem;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 8px rgba(0,0,0,.3);
    transition: transform .12s, background .12s;
}
.af-lightbox-close:hover {
    background: #fff;
    transform: scale(1.06);
}

/* ============================================================
   Settings page: link column fieldset
   ============================================================ */
.af-column-config--link {
    background: #f5f9f5;
    border-color: var(--af-primary);
    border-width: 2px;
}
.af-column-config--link legend {
    background: #fff;
    padding: .15rem .6rem;
    border-radius: 3px;
}
.af-link-outline-preview {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding-top: 1.4rem;
}

/* Colonne SYMBOLE (carte à symboles) — version simplifiée du fieldset
   sans paliers, juste libellé + couleur unique. */
.af-column-config--symbol {
    background: #fdf6ef;
    border-color: #d8a85f;
    border-width: 2px;
}
.af-column-config--symbol legend {
    background: #fff;
    padding: .15rem .6rem;
    border-radius: 3px;
}
.af-symbol-color-row {
    display: flex;
    align-items: center;
    gap: 1.2rem;
    margin-top: .8rem;
}
.af-symbol-color-row__label {
    flex: 0 0 auto;
}
.af-symbol-color-row__preview {
    display: flex;
    align-items: center;
    gap: .5rem;
}
.af-symbol-color-row__swatch {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    display: inline-block;
}

/* Grille à 3 colonnes pour les paramètres "forme / taille / couleur"
   d'un fieldset Symbole (page Paramètres). */
.af-grid-3 {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: .8rem;
    margin-top: .8rem;
}
@media (max-width: 720px) {
    .af-grid-3 { grid-template-columns: 1fr; }
}

/* Ligne d'aperçu d'un symbole sous le fieldset Symbole — montre la forme,
   la couleur et la taille choisies en SVG inline (mises à jour en live
   par le JS de la page admin). */
.af-symbol-preview-row {
    display: flex;
    align-items: center;
    gap: .6rem;
    margin-top: .8rem;
    padding: .5rem .8rem;
    background: rgba(255,255,255,.5);
    border: 1px dashed #d8a85f;
    border-radius: 4px;
}
.af-symbol-preview {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
}
.af-symbol-preview svg {
    width: 100%;
    height: 100%;
}

/* Colonne CERCLE (cartes à cercles proportionnels) — fieldset bleuté pour
   se distinguer des autres types (symbole = ocre, lien = vert). */
.af-column-config--circle {
    background: #f1f6fb;
    border-color: #6ba3d8;
    border-width: 2px;
}
.af-column-config--circle legend {
    background: #fff;
    padding: .15rem .6rem;
    border-radius: 3px;
}
.af-circle-preview-row {
    display: flex;
    align-items: center;
    gap: .8rem;
    margin-top: .8rem;
    padding: .5rem .8rem;
    background: rgba(255,255,255,.6);
    border: 1px dashed #6ba3d8;
    border-radius: 4px;
}
.af-circle-preview {
    display: inline-flex;
    align-items: center;
}
.af-circle-preview svg {
    display: block;
}

/* Aperçu de la couleur de fond pour cartes symbols */
.af-bg-preview {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding-top: 1.4rem;
}
.af-bg-preview__swatch {
    width: 28px;
    height: 28px;
    border-radius: 4px;
    display: inline-block;
    border: 1px solid var(--af-border);
    flex-shrink: 0;
}

/* ----- Shape picker (dropdown custom avec SVG inline) -----
   Remplace un <select> natif qui ne peut pas afficher du SVG dans ses
   options. Le bouton trigger affiche la forme courante avec sa couleur
   réelle ; le menu liste les 4 formes possibles. */
.af-shape-picker {
    position: relative;
    display: block;
    margin-top: .25rem;
}
.af-shape-picker__trigger {
    display: flex;
    align-items: center;
    gap: .5rem;
    width: 100%;
    padding: .4rem .6rem;
    background: #fff;
    border: 1px solid var(--af-border);
    border-radius: var(--af-radius-sm);
    font-size: .9rem;
    color: var(--af-text);
    cursor: pointer;
    text-align: left;
    line-height: 1.2;
    transition: border-color .15s, box-shadow .15s;
}
.af-shape-picker__trigger:hover {
    border-color: var(--af-muted);
}
.af-shape-picker__trigger:focus-visible {
    outline: none;
    border-color: var(--af-accent, #0f4c2b);
    box-shadow: 0 0 0 2px rgba(15,76,43,.15);
}
.af-shape-picker__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    flex-shrink: 0;
}
.af-shape-picker__icon svg {
    width: 100%;
    height: 100%;
}
.af-shape-picker__label {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.af-shape-picker__arrow {
    flex-shrink: 0;
    font-size: .75rem;
    color: var(--af-muted);
    margin-left: auto;
    transition: transform .15s;
}
.af-shape-picker__trigger[aria-expanded="true"] .af-shape-picker__arrow {
    transform: rotate(180deg);
}
.af-shape-picker__menu {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    margin: 0;
    padding: .25rem;
    list-style: none;
    background: #fff;
    border: 1px solid var(--af-border);
    border-radius: var(--af-radius-sm);
    box-shadow: 0 6px 20px rgba(0,0,0,.12);
    z-index: 100;
    max-height: 240px;
    overflow-y: auto;
}
.af-shape-picker__menu[hidden] {
    display: none;
}
.af-shape-picker__menu li {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .4rem .55rem;
    border-radius: 4px;
    cursor: pointer;
    font-size: .9rem;
    user-select: none;
}
.af-shape-picker__menu li:hover {
    background: rgba(0,0,0,.04);
}
.af-shape-picker__menu li[aria-selected="true"] {
    background: rgba(15,76,43,.08);
    font-weight: 500;
}
.af-shape-picker__option-label {
    flex: 1 1 auto;
}

/* ============================================================
   Carte publique : pays cliquables (avec lien)
   ============================================================ */
.af-svg-wrap [data-iso].af-clickable {
    cursor: pointer;
}
.af-svg-wrap [data-iso].af-clickable.af-hover {
    /* Léger filtre pour signaler l'interactivité au survol */
    filter: brightness(1.08);
}

/* Tooltip : section liens */
.af-tooltip .af-tt-links {
    margin-top: .4rem;
    padding-top: .35rem;
    border-top: 1px solid rgba(255,255,255,.15);
}
.af-tooltip .af-tt-link {
    font-size: .82rem;
    line-height: 1.35;
    margin: .12rem 0;
}
.af-tooltip .af-tt-link-label {
    color: #666;
}
.af-tooltip .af-tt-link-name {
    color: #333;
    word-break: break-all;
}
.af-tooltip .af-tt-link-hint {
    margin-top: .25rem;
    font-size: .72rem;
    font-style: italic;
    color: #666;
}

.af-data-toolbar {
    display: flex; gap: .5rem; align-items: center; flex-wrap: wrap;
    margin-bottom: 1rem; padding: .8rem 1rem;
    background: var(--af-card); border-radius: var(--af-radius-sm);
    box-shadow: var(--af-shadow);
    position: sticky; top: 0; z-index: 50;
}
.af-data-search {
    flex: 1; min-width: 180px;
    padding: .45rem .7rem;
    border: 1px solid var(--af-border);
    border-radius: var(--af-radius-sm);
    font-family: inherit; font-size: .9rem;
    background: #fff;
}
.af-year-filter {
    padding: .45rem .6rem;
    border: 1px solid var(--af-border);
    border-radius: var(--af-radius-sm);
    background: #fff; font-family: inherit; font-size: .9rem;
}
.af-flex-grow { flex: 1; min-width: 1rem; }
.af-save-status {
    font-size: .85rem; color: var(--af-muted);
    white-space: nowrap;
    transition: color .2s;
}
.af-save-status--ok      { color: var(--af-ok);      font-weight: 500; }
.af-save-status--err     { color: var(--af-err);     font-weight: 500; }
.af-save-status--pending { color: var(--af-accent);  font-style: italic; }

.af-data-tablewrap {
    background: var(--af-card); border-radius: var(--af-radius);
    box-shadow: var(--af-shadow);
    overflow: auto;
    max-height: 70vh;
}
.af-data-table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    font-size: .88rem;
}
.af-data-table thead th {
    position: sticky; top: 0; z-index: 10;
    background: #eef0ea;
    font-weight: 600; text-align: left;
    padding: .6rem .55rem;
    white-space: nowrap;
    border-bottom: 1px solid var(--af-border);
    color: var(--af-muted);
    text-transform: uppercase;
    font-size: .72rem;
    letter-spacing: .04em;
}
.af-data-table thead th small {
    font-weight: normal; opacity: .7;
    margin-left: .25rem;
    text-transform: none; letter-spacing: 0;
}
.af-data-table tbody td {
    padding: .2rem .35rem;
    border-bottom: 1px solid #f1efe8;
    vertical-align: middle;
}
.af-data-table tbody tr:hover { background: #fbfaf3; }

.af-data-table .af-cell-id {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: .8rem;
    color: var(--af-text);
    background: #f3f1e8;
    padding: .35rem .55rem;
    text-align: center;
    user-select: all;
    border-radius: 3px;
    text-transform: uppercase;
    letter-spacing: .03em;
    font-weight: 500;
}
.af-data-table .af-cell-id-new {
    background: #fff7e0;
    padding: .15rem;
    text-transform: none;
}
.af-data-table .af-cell-id-new input {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    text-align: center;
    text-transform: lowercase;
    background: #fff;
}
.af-data-table tbody input {
    width: 100%;
    padding: .4rem .5rem;
    font-size: .88rem;
    border: 1px solid transparent;
    border-radius: 3px;
    font-family: inherit;
    background: transparent;
    color: var(--af-text);
    transition: background .12s, border-color .12s;
}
.af-data-table tbody input:hover  { background: #fff; border-color: #e6e4dd; }
.af-data-table tbody input:focus  { background: #fff; border-color: var(--af-primary); outline: none; box-shadow: 0 0 0 2px rgba(15,76,43,.12); }
.af-data-table tbody input::placeholder { color: #c9c6bb; }

.af-data-table .af-th-id      { width: 64px;  text-align: center; }
.af-data-table .af-th-year    { width: 90px; }
.af-data-table .af-th-actions { width: 36px; }

/* Cellules de type "symbole" (case à cocher avec pastille colorée) */
.af-data-table .af-symbol-cell { text-align: center; }
.af-symbol-checkbox {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    padding: .25rem;
    border-radius: 4px;
    transition: background .12s;
}
.af-symbol-checkbox:hover { background: rgba(0,0,0,.04); }
.af-symbol-checkbox input[type=checkbox] {
    /* Cache la checkbox native — le rendu visuel est la pastille en dessous */
    position: absolute;
    opacity: 0;
    pointer-events: none;
    width: 0; height: 0;
}
.af-symbol-dot {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    display: inline-block;
    border: 2px solid transparent;
    box-shadow: 0 0 0 2px transparent inset;
    opacity: .25;
    transition: opacity .12s, border-color .12s;
}
.af-symbol-checkbox input[type=checkbox]:checked + .af-symbol-dot {
    opacity: 1;
}
.af-symbol-checkbox input[type=checkbox]:focus-visible + .af-symbol-dot {
    border-color: var(--af-primary);
}

.af-data-table tbody tr.af-row-new       { background: #fefce8; }
.af-data-table tbody tr.af-row-new:hover { background: #fef9c3; }

.af-data-table .af-row-del {
    padding: .15rem .5rem; font-size: 1.05rem; line-height: 1;
    color: var(--af-muted); border-color: transparent;
    background: transparent;
}
.af-data-table .af-row-del:hover {
    color: var(--af-danger); border-color: var(--af-danger);
    background: #fff;
}

.af-help-block { margin-top: 1.5rem; }
.af-help-block summary { padding: .5rem 0; }
.af-help-block ul { padding-left: 1.4rem; line-height: 1.7; }
.af-help-block kbd {
    background: #eef0ea; border: 1px solid var(--af-border);
    border-radius: 3px; padding: 1px 6px;
    font-family: ui-monospace, monospace; font-size: .85em;
}

/* Mobile */
@media (max-width: 700px) {
    .af-data-toolbar { padding: .6rem; gap: .4rem; }
    .af-data-search  { min-width: 100%; order: -1; }
    .af-data-table { font-size: .82rem; }
    .af-data-table tbody td { padding: .15rem .25rem; }
}


/* =========================================================================
   Paramètres généraux : palettes de couleurs
   ========================================================================= */

.af-settings-section {
    margin-top: 1.5rem;
}
.af-settings-section h2 {
    font-size: 1.1rem;
    margin: 0 0 .5rem;
}

.af-palette-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
    gap: 1rem;
    margin-top: 1rem;
}

.af-palette-card {
    background: #fff;
    border: 1px solid var(--af-border);
    border-radius: var(--af-radius);
    padding: 1rem;
    display: flex;
    flex-direction: column;
    gap: .75rem;
}
.af-palette-card.is-default {
    border-color: var(--af-primary);
    box-shadow: 0 0 0 1px var(--af-primary) inset;
}
.af-palette-card__head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: .5rem;
}
.af-palette-card__head h3 {
    font-size: .98rem;
    margin: 0;
    line-height: 1.4;
    display: inline-flex;
    flex-wrap: wrap;
    gap: .35rem;
    align-items: center;
}
.af-palette-card__id {
    font-size: .72rem;
    color: var(--af-muted);
    background: var(--af-bg-soft, #f5f5f0);
    padding: .15rem .4rem;
    border-radius: 3px;
    white-space: nowrap;
}
.af-palette-card__actions {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
    margin-top: auto;
}

.af-palette-swatches {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
}
.af-palette-swatch {
    display: inline-block;
    width: 32px;
    height: 32px;
    border: 1px solid rgba(0,0,0,.08);
    border-radius: 4px;
}
.af-palette-swatch--nodata {
    margin-left: 6px;
    border-style: dashed;
    border-color: rgba(0,0,0,.3);
}

.af-tag {
    display: inline-block;
    font-size: .68rem;
    padding: .1rem .4rem;
    border-radius: 999px;
    background: var(--af-bg-soft, #f0eee8);
    color: var(--af-muted);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: .04em;
}
.af-tag--ok {
    background: #d4f0d4;
    color: #1f5f1f;
}

/* Éditeur de palette */
.af-palette-edit {
    max-width: 720px;
}
.af-palette-paliers__list {
    display: flex;
    flex-direction: column;
    gap: .35rem;
    margin-bottom: .75rem;
}
.af-palette-palier {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .4rem .5rem;
    background: #fff;
    border: 1px solid var(--af-border);
    border-radius: var(--af-radius-sm);
    transition: background .12s, opacity .12s;
}
.af-palette-palier.is-dragging {
    opacity: .5;
    background: var(--af-bg-soft, #f5f5f0);
}
.af-palette-palier.is-drop-target {
    border-color: var(--af-primary);
    border-style: dashed;
}
.af-palette-palier__handle {
    cursor: grab;
    color: var(--af-muted);
    user-select: none;
    padding: 0 .25rem;
    font-size: 1rem;
}
.af-palette-palier__handle:active { cursor: grabbing; }
.af-palette-palier__num {
    font-size: .85rem;
    color: var(--af-muted);
    min-width: 80px;
}
.af-palette-palier .af-color-input {
    width: 40px;
    height: 28px;
    padding: 0;
    border: 1px solid var(--af-border);
    border-radius: 4px;
    cursor: pointer;
    flex-shrink: 0;
}
.af-palette-palier .af-color-hex {
    width: 90px;
    font-family: ui-monospace, "SF Mono", Menlo, monospace;
    font-size: .85rem;
    text-transform: uppercase;
}
.af-palette-palier__remove {
    margin-left: auto;
    color: #b54;
    font-size: 1.1rem;
    line-height: 1;
    padding: .15rem .55rem;
}

.af-palette-palier--nodata {
    border-style: dashed;
}

.af-form-actions {
    display: flex;
    gap: .5rem;
    margin-top: 1rem;
}

.af-alert--info {
    background: #eaf2fb;
    border-color: #a8c5e8;
    color: #1f4d7a;
}

/* =========================================================================
   Color picker popover (palette swatches dans l'éditeur de carte)
   ========================================================================= */

.af-color-trigger {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-left: 4px;
}
.af-color-trigger button {
    width: 24px;
    height: 24px;
    padding: 0;
    border: 1px solid var(--af-border);
    border-radius: 4px;
    background: #fff;
    cursor: pointer;
    font-size: 12px;
    line-height: 1;
    color: var(--af-muted);
}
.af-color-trigger button:hover { border-color: var(--af-primary); }

.af-color-popover {
    position: absolute;
    z-index: 1000;
    background: #fff;
    border: 1px solid var(--af-border);
    border-radius: var(--af-radius-sm);
    box-shadow: 0 8px 24px rgba(0,0,0,.12);
    padding: .75rem;
    min-width: 240px;
}
/* Header avec dropdown de palette en haut du popover (permet de switcher
   entre palettes sans fermer le picker). */
.af-color-popover__header {
    display: flex;
    align-items: center;
    gap: .4rem;
    margin-bottom: .5rem;
}
.af-color-popover__label {
    font-size: .8rem;
    color: var(--af-muted);
    flex-shrink: 0;
}
.af-color-popover__select {
    flex: 1;
    font-size: .85rem;
    padding: .25rem .4rem;
    border: 1px solid var(--af-border);
    border-radius: 3px;
    background: #fff;
    cursor: pointer;
}
.af-color-popover__title {
    font-size: .8rem;
    color: var(--af-muted);
    margin-bottom: .35rem;
}
.af-color-popover__grid {
    display: grid;
    grid-template-columns: repeat(8, 1fr);
    gap: 4px;
    margin-bottom: .6rem;
}
.af-color-popover__swatch {
    aspect-ratio: 1;
    border: 1px solid rgba(0,0,0,.08);
    border-radius: 3px;
    cursor: pointer;
    transition: transform .08s;
}
.af-color-popover__swatch:hover { transform: scale(1.15); }
.af-color-popover__hex {
    display: flex;
    gap: .25rem;
    align-items: center;
}
.af-color-popover__hex input {
    flex: 1;
    font-family: ui-monospace, "SF Mono", Menlo, monospace;
    font-size: .8rem;
    text-transform: uppercase;
    padding: .25rem .4rem;
    border: 1px solid var(--af-border);
    border-radius: 3px;
}

.af-palette-applier {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin: .5rem 0 1rem;
    padding: .6rem .8rem;
    background: var(--af-bg-soft, #faf9f5);
    border: 1px solid var(--af-border);
    border-radius: var(--af-radius-sm);
    flex-wrap: wrap;
}
.af-palette-applier label {
    font-size: .85rem;
    margin-bottom: 0 !important;
}
.af-palette-applier select {
    min-width: 200px;
}

/* ============================================================
   Sélecteur de mode sonore (page Paramètres → Sonification)
   ============================================================ */
.af-sn-section-title {
    /* Titre de chaque section (Tenus / Ponctuels). Espace en dessous de la
       grille pour bien séparer visuellement les deux familles. */
    display: block;
    margin: 0 0 .35rem 0;
    font-size: .82rem;
    color: var(--af-fg, #222);
}
.af-sn-mode-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: .5rem;
    margin-bottom: .4rem;
}
.af-sn-mode-option {
    display: grid;
    grid-template-columns: auto 1fr auto;
    grid-template-rows: auto auto;
    align-items: center;
    gap: .25rem .55rem;
    padding: .55rem .65rem;
    border: 1px solid var(--af-border);
    border-radius: var(--af-radius-sm);
    cursor: pointer;
    background: var(--af-bg-soft, #faf9f5);
    transition: border-color .15s, background .15s;
    margin: 0;
}
.af-sn-mode-option:hover {
    border-color: var(--af-primary, #0f4c2b);
}
.af-sn-mode-option:has(input:checked) {
    border-color: var(--af-primary, #0f4c2b);
    background: #fff;
    box-shadow: 0 0 0 2px rgba(15, 76, 43, 0.1);
}
.af-sn-mode-option input[type="radio"] {
    grid-column: 1;
    grid-row: 1 / span 2;
    margin: 0;
}
.af-sn-mode-icon {
    grid-column: 2;
    grid-row: 1;
    font-size: 1.1rem;
    line-height: 1;
}
.af-sn-mode-label {
    grid-column: 2;
    grid-row: 1;
    font-weight: 600;
    font-size: .9rem;
    margin-left: 1.6rem;
}
.af-sn-mode-desc {
    grid-column: 2 / span 2;
    grid-row: 2;
    font-size: .75rem;
    color: var(--af-muted, #6b7370);
    margin-left: 1.6rem;
}
.af-sn-mode-preview {
    grid-column: 3;
    grid-row: 1;
    background: var(--af-primary, #0f4c2b);
    color: #fff;
    border: none;
    border-radius: 50%;
    width: 28px;
    height: 28px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: .75rem;
    padding: 0 0 0 2px;  /* compensation visuelle du triangle ▶ */
    transition: background .15s, transform .15s;
}
.af-sn-mode-preview:hover {
    background: #0a3a20;
    transform: scale(1.1);
}
.af-sn-mode-preview:active {
    transform: scale(0.95);
}
.af-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;
}

/* ============================================================
   Mode dégradé : légende horizontale (frontend)
   ============================================================ */
.af-legend__list--gradient {
    /* La <ul> contient un seul <li> (la barre dégradée), pas de bullet.
       width: 100% pour que la légende dégradée prenne toute la largeur
       disponible de l'aside, sans dépendre du contenu (qui par défaut
       fait que .af-legend__list li est en flex inline-fitté). */
    list-style: none;
    padding: 0;
    margin: 0;
    width: 100%;
}
/* Override de la règle générique `.af-legend__list li { display: flex }`
   qui mettrait barre + labels + unit en ligne au lieu d'empilés.
   On force le block layout pour ce <li> spécifiquement. */
.af-legend__list--gradient li.af-legend-grad,
.af-legend-grad {
    list-style: none;
    margin: 0.4rem 0;
    padding: 0;
    display: block;
    width: 100%;
}
.af-legend-grad__bar {
    /* Le linear-gradient est appliqué inline depuis le HTML.
       Hauteur fixe, bord arrondi pour un rendu propre. width 100% pour
       prendre toute la largeur du conteneur (sinon par défaut un <div>
       sans contenu fait 0px). */
    display: block;
    height: 12px;
    border-radius: 6px;
    width: 100%;
    margin: 0 0 0.45rem 0;
    /* Léger contour pour que les jaunes clairs restent visibles sur fond blanc */
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
}
.af-legend-grad__labels {
    /* Container qui sert de référentiel pour les positions absolues
       des labels. Hauteur = ligne de texte. width 100% pour qu'il
       fasse exactement la même largeur que la barre dégradée — c'est
       sa largeur qui sert de référence aux positions left:X% des labels. */
    display: block;
    position: relative;
    height: 1.2em;
    width: 100%;
    font-size: 0.78rem;
    color: var(--af-muted, #555);
}
.af-legend-grad__label {
    position: absolute;
    top: 0;
    /* left est défini inline (pos %). On le décale de -50% pour le centrer
       sur sa position. Pour les extrêmes (0 % et 100 %), CSS calc() limite
       le débordement. */
    transform: translateX(-50%);
    white-space: nowrap;
}
/* Cas extrêmes : 0% reste aligné à gauche, 100% à droite — sinon le
   premier/dernier label dépasserait du conteneur. */
.af-legend-grad__label[style*="left:0%"]   { transform: translateX(0); }
.af-legend-grad__label[style*="left:100%"] { transform: translateX(-100%); }

.af-legend-grad__unit {
    display: block;
    font-size: 0.75rem;
    color: var(--af-muted, #777);
    margin-top: 0.2rem;
    text-align: right;
    width: 100%;
}

/* ============================================================
   Mode dégradé : UI éditeur (admin)
   ============================================================ */
.af-range-mode {
    margin: 0.6rem 0 0.4rem;
}
.af-range-mode__radios {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0.5rem;
    margin-top: 0.3rem;
}
.af-radio-card {
    display: block;
    padding: 0.55rem 0.7rem;
    border: 1px solid var(--af-border, #ddd);
    border-radius: var(--af-radius-sm, 4px);
    cursor: pointer;
    background: var(--af-bg-soft, #faf9f5);
    transition: border-color 0.15s, background 0.15s, box-shadow 0.15s;
}
.af-radio-card:hover {
    border-color: var(--af-primary, #0f4c2b);
}
.af-radio-card:has(input:checked) {
    border-color: var(--af-primary, #0f4c2b);
    background: #fff;
    box-shadow: 0 0 0 2px rgba(15, 76, 43, 0.10);
}
.af-radio-card input[type="radio"] {
    margin-right: 0.45rem;
}
.af-radio-card__title {
    font-weight: 600;
    font-size: 0.92rem;
    display: inline;
}
.af-radio-card__desc {
    display: block;
    font-size: 0.76rem;
    color: var(--af-muted, #6b7370);
    margin-top: 0.25rem;
    margin-left: 1.7rem;
}

.af-grad-stops {
    margin: 0.5rem 0;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}
.af-grad-stop {
    display: grid;
    grid-template-columns: auto 1fr auto;
    gap: 0.5rem;
    align-items: center;
    padding: 0.35rem 0.5rem;
    background: var(--af-bg-soft, #faf9f5);
    border: 1px solid var(--af-border, #e5e5e5);
    border-radius: var(--af-radius-sm, 4px);
}
.af-grad-stop label {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    margin: 0;
}
.af-grad-stop__pos {
    width: 4em;
    padding: 0.2rem 0.35rem;
}
.af-grad-stop input[type="color"] {
    width: 32px;
    height: 32px;
    padding: 0;
    border: 1px solid var(--af-border, #ccc);
    border-radius: 3px;
    cursor: pointer;
}
.af-grad-preview-wrap {
    margin-top: 0.6rem;
}
.af-grad-preview {
    height: 16px;
    border-radius: 8px;
    margin-top: 0.2rem;
    background: #eee;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
}

/* ============================================================
   Onglets de la page Paramètres (admin)
   ============================================================
   Structure :
     <nav class="af-tabs">           Onglets de niveau 1 : Animation / Sonif / Indicateurs
       <button class="af-tab is-active" data-tab-target="animation">…</button>
       <button class="af-tab" data-tab-target="sonif">…</button>
       <button class="af-tab" data-tab-target="indicateurs">…</button>
     </nav>
     <div class="af-tab-panel is-active" data-tab="animation">…</div>
     <div class="af-tab-panel" data-tab="sonif">…</div>          (caché par défaut)
     <div class="af-tab-panel" data-tab="indicateurs">
       <nav class="af-subtabs">       Sous-onglets : un par indicateur
         <button class="af-subtab is-active" data-subtab-target="…">…</button>
         …
       </nav>
       <div class="af-tab-subpanel is-active" data-subtab="…">…</div>
       <div class="af-tab-subpanel" data-subtab="…">…</div>
     </div>

   La logique d'activation est dans assets/admin.js :
     - clic sur .af-tab → active le panel correspondant
     - clic sur .af-subtab → active le sous-panel correspondant
     - dernier onglet actif mémorisé en localStorage (clé "af_admin_active_tab"
       et "af_admin_active_subtab_<id>") */

/* Onglets de niveau 1 (haut de la page Paramètres) */
.af-tabs {
    display: flex;
    gap: .25rem;
    border-bottom: 2px solid var(--af-border, #e0ddd6);
    margin: 0 0 1rem 0;
    padding: 0;
    flex-wrap: wrap;
}
.af-tab {
    background: transparent;
    border: 0;
    border-bottom: 3px solid transparent;
    margin-bottom: -2px;     /* recouvre la border-bottom de .af-tabs au actif */
    padding: .55rem 1rem;
    font-size: .95rem;
    font-weight: 500;
    color: var(--af-muted, #6b7370);
    cursor: pointer;
    transition: color .15s, border-color .15s, background .15s;
    border-radius: 4px 4px 0 0;
}
.af-tab:hover {
    color: var(--af-fg, #222);
    background: var(--af-bg-soft, #faf9f5);
}
.af-tab.is-active {
    color: var(--af-primary, #0f4c2b);
    border-bottom-color: var(--af-primary, #0f4c2b);
    font-weight: 600;
    background: transparent;
}
.af-tab:focus-visible {
    outline: 2px solid var(--af-primary, #0f4c2b);
    outline-offset: 2px;
}

/* Panneaux : seul celui marqué .is-active est visible.
   On utilise display:none pour que les inputs cachés ne soient pas validés
   par le browser (required, etc.) — ils restent envoyés au submit puisque
   le form les contient toujours dans le DOM. */
.af-tab-panel {
    display: none;
}
.af-tab-panel.is-active {
    display: block;
    animation: af-tab-fadein .15s ease-out;
}
@keyframes af-tab-fadein {
    from { opacity: 0; transform: translateY(2px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* Sous-onglets (niveau 2, dans l'onglet Indicateurs) */
.af-subtabs {
    display: flex;
    flex-wrap: wrap;
    gap: .3rem;
    margin: 0 0 .8rem 0;
    padding: .35rem;
    background: var(--af-bg-soft, #faf9f5);
    border-radius: 6px;
    border: 1px solid var(--af-border, #e0ddd6);
}
.af-subtab {
    background: transparent;
    border: 1px solid transparent;
    padding: .4rem .8rem;
    font-size: .85rem;
    color: var(--af-muted, #6b7370);
    cursor: pointer;
    border-radius: 4px;
    transition: background .15s, color .15s, border-color .15s;
}
.af-subtab:hover {
    background: #fff;
    color: var(--af-fg, #222);
    border-color: var(--af-border, #e0ddd6);
}
.af-subtab.is-active {
    background: #fff;
    color: var(--af-primary, #0f4c2b);
    border-color: var(--af-primary, #0f4c2b);
    font-weight: 600;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
}
.af-subtab:focus-visible {
    outline: 2px solid var(--af-primary, #0f4c2b);
    outline-offset: 2px;
}

/* Sous-panneaux d'indicateur (1 par colonne) */
.af-tab-subpanel {
    display: none;
}
.af-tab-subpanel.is-active {
    display: block;
    animation: af-tab-fadein .15s ease-out;
}

/* ============================================================
   Curseur taille globale des carrés (page Paramètres)
   ============================================================ */
.af-squares-size {
    margin-top: .6rem;
    padding: .5rem .65rem;
    background: var(--af-bg-soft, #faf9f5);
    border: 1px solid var(--af-border, #e0ddd6);
    border-radius: 4px;
}
.af-squares-size__control {
    display: flex;
    align-items: center;
    gap: .65rem;
    margin-top: .35rem;
}
.af-squares-size__slider {
    flex: 1;
    accent-color: var(--af-primary, #0f4c2b);
    cursor: pointer;
}
.af-squares-size__min,
.af-squares-size__max {
    flex-shrink: 0;
    min-width: 4em;
    text-align: center;
}
.af-squares-size__min { text-align: right; }
.af-squares-size__max { text-align: left; }
.af-squares-size__output {
    flex-shrink: 0;
    min-width: 4em;
    text-align: center;
    font-weight: 600;
    color: var(--af-primary, #0f4c2b);
    background: #fff;
    padding: .25rem .5rem;
    border-radius: 3px;
    border: 1px solid var(--af-border, #e0ddd6);
    font-variant-numeric: tabular-nums;
}

/* ============================================================
   Sonification : 2 colonnes Tenus / Ponctuels (page Paramètres)
   ============================================================
   Remplace l'ancienne grille auto-fill par 2 colonnes côte-à-côte.
   Sur mobile (< 720 px), les colonnes se replient en pile verticale. */
.af-sn-mode-picker--two-cols {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: .9rem;
}
.af-sn-mode-col {
    display: flex;
    flex-direction: column;
}
.af-sn-mode-list {
    display: flex;
    flex-direction: column;
    gap: .35rem;
    margin-bottom: .2rem;
}
/* Les options dans le mode liste : compactes, pleine largeur, label
   à gauche, description en-dessous, bouton ▶ à droite. La grille interne
   définie dans .af-sn-mode-option fonctionne déjà bien (auto 1fr auto). */
.af-sn-mode-list .af-sn-mode-option {
    width: 100%;
}
@media (max-width: 720px) {
    .af-sn-mode-picker--two-cols {
        grid-template-columns: 1fr;
    }
}

/* Sans icône, on retire la marge gauche qui était réservée au pictogramme.
   Comme la classe .af-sn-mode-icon n'est plus rendue, le contenu est
   simplement décalé d'1 carré à gauche. */
.af-sn-mode-list .af-sn-mode-label,
.af-sn-mode-list .af-sn-mode-desc {
    margin-left: 0;
}

/* ============================================================
   Éditeur de la liste des années (page Paramètres → Infos)
   ============================================================ */
.af-years-editor-fs .af-years-list {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
    padding: .4rem;
    background: var(--af-bg-soft, #faf9f5);
    border: 1px solid var(--af-border, #e0ddd6);
    border-radius: 4px;
    min-height: 2.4rem;
    align-items: center;
}
.af-years-editor-fs .af-years-list:empty::before {
    content: "Aucune année — ajoutez-en une ci-dessous";
    color: var(--af-muted, #6b7370);
    font-size: .85rem;
    font-style: italic;
    padding: .15rem .3rem;
}
.af-year-chip {
    display: inline-flex;
    align-items: center;
    gap: .25rem;
    padding: .2rem .25rem .2rem .55rem;
    background: #fff;
    border: 1px solid var(--af-border, #e0ddd6);
    border-radius: 999px;
    font-size: .85rem;
    font-variant-numeric: tabular-nums;
}
.af-year-chip__label {
    font-weight: 600;
    color: var(--af-fg, #222);
}
.af-year-chip__remove {
    background: transparent;
    border: 0;
    width: 1.4rem;
    height: 1.4rem;
    border-radius: 50%;
    cursor: pointer;
    font-size: 1rem;
    line-height: 1;
    color: var(--af-muted, #6b7370);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    transition: background .12s, color .12s;
}
.af-year-chip__remove:hover {
    background: #fee;
    color: #c33;
}
.af-years-add {
    display: flex;
    gap: .4rem;
    margin-top: .5rem;
    align-items: center;
}
.af-years-add__input {
    flex: 0 0 auto;
    width: 12rem;
    padding: .35rem .5rem;
    font-size: .9rem;
}

/* ============================================================
   Presets de dégradés (page Paramètres → Indicateurs)
   ============================================================ */
.af-grad-presets {
    margin-bottom: .5rem;
}
.af-grad-presets__grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: .4rem;
    margin-top: .3rem;
}
.af-grad-preset {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: .25rem;
    padding: .35rem;
    background: #fff;
    border: 1px solid var(--af-border, #e0ddd6);
    border-radius: 4px;
    cursor: pointer;
    transition: border-color .12s, box-shadow .12s, transform .12s;
}
.af-grad-preset:hover {
    border-color: var(--af-primary, #0f4c2b);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
    transform: translateY(-1px);
}
.af-grad-preset:active {
    transform: translateY(0);
}
.af-grad-preset__bar {
    height: 22px;
    border-radius: 3px;
    border: 1px solid rgba(0, 0, 0, 0.08);
    display: block;
}
.af-grad-preset__label {
    font-size: .78rem;
    color: var(--af-muted, #6b7370);
    text-align: center;
    line-height: 1.2;
}
.af-grad-preset.is-applied {
    border-color: var(--af-primary, #0f4c2b);
    background: var(--af-bg-soft, #faf9f5);
}
.af-grad-preset.is-applied .af-grad-preset__label {
    color: var(--af-primary, #0f4c2b);
    font-weight: 600;
}
