/* vie-politique.fr — feuille de style unique.
 *
 * Tokens repris des maquettes (docs/maquettes/README.md). Ils sont
 * TOUS déclarés ici, en un seul endroit : changer la police ou la
 * couleur d'accent du site doit rester une modification d'une ligne,
 * jamais une recherche-remplacement à travers les gabarits.
 *
 * Mobile d'abord : les règles de base valent pour un téléphone, les
 * media queries n'ajoutent que ce qu'un écran large permet en plus.
 */

/* Polices auto-hébergées (fichiers dans `polices/`, copiés tels quels
 * par `src/site/executer.py`) — remplace les balises `<link>` vers
 * fonts.googleapis.com/fonts.gstatic.com qui envoyaient l'IP de
 * chaque visiteur à Google à chaque page, sans lien avec un script de
 * suivi mais hors de propos pour un site qui affirme n'en charger
 * aucun (cf. politique de confidentialité). Revue RGPD/CNIL du
 * 2026-09-06. Fichiers extraits de Google Fonts (mêmes graisses,
 * mêmes rendus), sous-ensembles latin/latin-ext seulement — le site
 * n'a pas de contenu cyrillique ni vietnamien.
 *
 * Fraunces, Public Sans et Space Grotesk sont des polices à axes
 * variables chez Google Fonts : un seul fichier par sous-ensemble
 * couvre déjà toute la plage de graisse (vérifié par comparaison
 * d'empreintes — les fichiers déclarés pour 400/600/700 sont
 * identiques), d'où `font-weight: 400 700` (une plage, pas une valeur
 * fixe) plutôt que trois déclarations dupliquées vers le même fichier.
 * IBM Plex Mono, elle, est réellement statique : un fichier distinct
 * par graisse. */
@font-face {
  font-family: "Fraunces"; font-style: normal; font-weight: 400 700; font-display: swap;
  src: url("polices/fraunces-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2122, U+2191, U+2193, U+2212, U+2215;
}
@font-face {
  font-family: "Fraunces"; font-style: normal; font-weight: 400 700; font-display: swap;
  src: url("polices/fraunces-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-024F, U+1E00-1EFF, U+2020, U+20A0-20AB, U+2113;
}
@font-face {
  font-family: "Space Grotesk"; font-style: normal; font-weight: 400 700; font-display: swap;
  src: url("polices/space-grotesk-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2122, U+2191, U+2193, U+2212, U+2215;
}
@font-face {
  font-family: "Space Grotesk"; font-style: normal; font-weight: 400 700; font-display: swap;
  src: url("polices/space-grotesk-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-024F, U+1E00-1EFF, U+2020, U+20A0-20AB, U+2113;
}
@font-face {
  font-family: "Public Sans"; font-style: normal; font-weight: 400 700; font-display: swap;
  src: url("polices/public-sans-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2122, U+2191, U+2193, U+2212, U+2215;
}
@font-face {
  font-family: "Public Sans"; font-style: normal; font-weight: 400 700; font-display: swap;
  src: url("polices/public-sans-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-024F, U+1E00-1EFF, U+2020, U+20A0-20AB, U+2113;
}
@font-face {
  font-family: "IBM Plex Mono"; font-style: normal; font-weight: 400; font-display: swap;
  src: url("polices/ibm-plex-mono-400-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2122, U+2191, U+2193, U+2212, U+2215;
}
@font-face {
  font-family: "IBM Plex Mono"; font-style: normal; font-weight: 400; font-display: swap;
  src: url("polices/ibm-plex-mono-400-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-024F, U+1E00-1EFF, U+2020, U+20A0-20AB, U+2113;
}
@font-face {
  font-family: "IBM Plex Mono"; font-style: normal; font-weight: 500; font-display: swap;
  src: url("polices/ibm-plex-mono-500-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2122, U+2191, U+2193, U+2212, U+2215;
}
@font-face {
  font-family: "IBM Plex Mono"; font-style: normal; font-weight: 500; font-display: swap;
  src: url("polices/ibm-plex-mono-500-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-024F, U+1E00-1EFF, U+2020, U+20A0-20AB, U+2113;
}
@font-face {
  font-family: "IBM Plex Mono"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("polices/ibm-plex-mono-600-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2122, U+2191, U+2193, U+2212, U+2215;
}
@font-face {
  font-family: "IBM Plex Mono"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("polices/ibm-plex-mono-600-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-024F, U+1E00-1EFF, U+2020, U+20A0-20AB, U+2113;
}

:root {
  --bg: oklch(97.5% 0.006 85);
  --bg-alt: oklch(94% 0.008 85);
  --surface: oklch(100% 0 0);
  --border: oklch(88% 0.008 85);
  --border-strong: oklch(78% 0.01 85);
  --fg: oklch(18% 0.012 260);
  --fg-muted: oklch(44% 0.012 260);
  --fg-faint: oklch(52% 0.01 260);
  --accent: oklch(38% 0.09 255);
  --accent-strong: oklch(30% 0.09 255);
  --accent-soft: oklch(93% 0.025 255);
  --accent-contrast: oklch(99% 0.004 255);
  --teal: oklch(40% 0.07 195);
  --teal-soft: oklch(93% 0.03 195);
  --violet: oklch(40% 0.09 320);
  --violet-soft: oklch(93% 0.03 320);
  --warn: oklch(46% 0.14 55);
  --warn-soft: oklch(93% 0.045 60);
  --positive: oklch(45% 0.1 155);
  --negative: oklch(45% 0.13 25);

  /* Trio éditorial (choisi le 2026-08-31, remplace le point de départ
     initial) : Fraunces pour les titres (serif expressif, pensé pour le
     long-form, évite l'effet « SaaS générique »), Space Grotesk pour les
     sous-titres (grotesque géométrique à l'allure technique/data, fait
     contraste avec le serif), Public Sans pour le corps de texte
     (US Web Design System — lisible en petit corps, neutre, cohérent
     avec une plateforme civique). Le mono reste IBM Plex Mono, non
     concerné par ce choix : rôle distinct (alignement tabulaire des
     nombres), pas une police de lecture.
     Trois variables ⇒ trois rôles, jamais recopiées ailleurs dans ce
     fichier — changer une police reste une modification d'une ligne. */
  --font-titre: "Fraunces", Georgia, "Times New Roman", serif;
  --font-sous-titre: "Space Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-sans: "Public Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --largeur-max: 1140px;
  --rayon: 12px;
}

/* Thème sombre : suit `prefers-color-scheme` par défaut (aucun choix
   explicite mémorisé), un choix explicite (bouton de bascule,
   `theme.js`) posant `data-theme` sur `<html>` l'emporte dans les deux
   sens — d'où les deux blocs ci-dessous plutôt qu'un seul. Mêmes rôles
   de teinte qu'en clair (accent bleu, teal, violet, warn...), lightness
   et chroma réajustés pour rester lisibles sur fond sombre plutôt
   qu'une simple inversion. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: oklch(20% 0.012 260);
    --bg-alt: oklch(25% 0.014 260);
    --surface: oklch(23% 0.013 260);
    --border: oklch(32% 0.014 260);
    --border-strong: oklch(42% 0.016 260);
    --fg: oklch(93% 0.006 85);
    --fg-muted: oklch(74% 0.012 260);
    --fg-faint: oklch(60% 0.01 260);
    --accent: oklch(78% 0.09 255);
    --accent-strong: oklch(85% 0.08 255);
    --accent-soft: oklch(30% 0.05 255);
    --accent-contrast: oklch(18% 0.02 255);
    --teal: oklch(75% 0.09 195);
    --teal-soft: oklch(28% 0.05 195);
    --violet: oklch(78% 0.1 320);
    --violet-soft: oklch(30% 0.05 320);
    --warn: oklch(78% 0.13 60);
    --warn-soft: oklch(30% 0.06 60);
    --positive: oklch(75% 0.13 155);
    --negative: oklch(72% 0.15 25);
  }
}

:root[data-theme="dark"] {
  --bg: oklch(20% 0.012 260);
  --bg-alt: oklch(25% 0.014 260);
  --surface: oklch(23% 0.013 260);
  --border: oklch(32% 0.014 260);
  --border-strong: oklch(42% 0.016 260);
  --fg: oklch(93% 0.006 85);
  --fg-muted: oklch(74% 0.012 260);
  --fg-faint: oklch(60% 0.01 260);
  --accent: oklch(78% 0.09 255);
  --accent-strong: oklch(85% 0.08 255);
  --accent-soft: oklch(30% 0.05 255);
  --accent-contrast: oklch(18% 0.02 255);
  --teal: oklch(75% 0.09 195);
  --teal-soft: oklch(28% 0.05 195);
  --violet: oklch(78% 0.1 320);
  --violet-soft: oklch(30% 0.05 320);
  --warn: oklch(78% 0.13 60);
  --warn-soft: oklch(30% 0.06 60);
  --positive: oklch(75% 0.13 155);
  --negative: oklch(72% 0.15 25);
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.6;
  /* Empêche tout débordement latéral : un site qui défile
     horizontalement sur mobile est cassé, pas « responsive ». */
  overflow-x: hidden;
}

a { color: var(--accent); }
a:hover { color: var(--accent-strong); }

/* h1 porte le serif éditorial (Fraunces) ; h2/h3 basculent sur le
   grotesque (Space Grotesk) — c'est ce contraste titre/sous-titre qui
   est recherché, pas une simple déclinaison de tailles d'une même
   police. */
h1, h2, h3 { font-weight: 600; line-height: 1.2; margin: 0; }
h1 { font-family: var(--font-titre); font-size: 1.85rem; letter-spacing: -0.01em; }
h2, h3 { font-family: var(--font-sous-titre); }
h2 { font-size: 1.2rem; }
h3 { font-size: 1.02rem; }

@media (min-width: 700px) {
  h1 { font-size: 2.4rem; }
  h2 { font-size: 1.4rem; }
}

.mono { font-family: var(--font-mono); }
.muted { color: var(--fg-muted); }
.faint { color: var(--fg-faint); }
.petit { font-size: 0.8rem; }

/* ---------- Structure ---------- */

.conteneur {
  width: 100%;
  max-width: var(--largeur-max);
  margin: 0 auto;
  padding: 0 16px;
}

@media (min-width: 900px) { .conteneur { padding: 0 32px; } }

main { padding: 24px 0 48px; }

/* ---------- En-tête ---------- */

.entete {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 20;
}

.entete-interne {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 56px;
  gap: 12px;
}

.marque {
  display: flex;
  align-items: center;
  gap: 9px;
  text-decoration: none;
  color: var(--fg);
  font-family: var(--font-titre);
  font-weight: 600;
  font-size: 1rem;
  white-space: nowrap;
}

.marque-logo {
  width: 26px; height: 26px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}

.marque .fr { color: var(--accent); }

.nav-bureau { display: none; }

/* Cible tactile de 44px minimum — norme d'accessibilité tactile.
   Déclaré AVANT la media query : une règle de même spécificité placée
   après l'écraserait, et le bouton resterait visible sur desktop. */
.bouton-menu {
  width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  background: none; border: none; color: var(--fg); cursor: pointer;
  padding: 0;
}

/* Bascule clair/sombre : visible à toutes les largeurs (contrairement
   à `.bouton-menu`, propre au mobile) — la préférence de thème n'a pas
   de raison de dépendre de la taille d'écran. Les deux icônes
   coexistent dans le DOM, une seule visible à la fois via l'attribut
   `data-theme` (posé par `theme.js`) ou, à défaut, `prefers-color-
   scheme` — jamais de bascule d'icône en JS, seulement l'attribut. */
.bouton-theme {
  width: 44px; height: 44px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: none; border: none; color: var(--fg); cursor: pointer;
  padding: 0;
}

.bouton-theme .icone-lune { display: none; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .bouton-theme .icone-soleil { display: none; }
  :root:not([data-theme="light"]) .bouton-theme .icone-lune { display: block; }
}

:root[data-theme="dark"] .bouton-theme .icone-soleil { display: none; }
:root[data-theme="dark"] .bouton-theme .icone-lune { display: block; }
:root[data-theme="light"] .bouton-theme .icone-soleil { display: block; }
:root[data-theme="light"] .bouton-theme .icone-lune { display: none; }

@media (min-width: 900px) {
  .nav-bureau { display: flex; align-items: center; gap: 24px; font-size: 0.92rem; font-weight: 500; }
  .nav-bureau a { color: var(--fg-muted); text-decoration: none; }
  .nav-bureau a:hover, .nav-bureau a[aria-current] { color: var(--fg); }
  .nav-bureau a.mise-en-avant {
    color: var(--accent); font-weight: 600;
    background: var(--accent-soft); padding: 7px 12px; border-radius: 7px;
  }
  .bouton-menu { display: none; }

  /* Onglet de tête avec sous-menu : le lien parent reste cliquable,
     le sous-menu s'ouvre au survol ou au focus clavier (jamais en JS —
     cf. l'en-tête du fichier, la nav du site est volontairement sans
     dépendance JS). */
  .nav-groupe { position: relative; display: flex; align-items: center; height: 56px; }
  .nav-sous-menu {
    display: none;
    position: absolute; top: 100%; left: 50%; transform: translateX(-50%);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--rayon);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
    padding: 6px;
    min-width: 180px;
    flex-direction: column;
    gap: 2px;
    z-index: 30;
  }
  .nav-groupe:hover .nav-sous-menu,
  .nav-groupe:focus-within .nav-sous-menu {
    display: flex;
  }
  .nav-sous-menu a {
    padding: 8px 10px;
    border-radius: 6px;
    white-space: nowrap;
  }
  .nav-sous-menu a:hover, .nav-sous-menu a[aria-current] { background: var(--accent-soft); color: var(--fg); }
}

.nav-mobile {
  display: none;
  border-top: 1px solid var(--border);
  background: var(--surface);
  padding: 8px 0 16px;
}
.nav-mobile.ouvert { display: block; }
@media (min-width: 900px) { .nav-mobile.ouvert { display: none; } }

.nav-mobile a {
  display: flex; align-items: center;
  min-height: 52px;
  padding: 0 16px;
  text-decoration: none;
  color: var(--fg);
  font-weight: 500;
  border-bottom: 1px solid var(--border);
}
.nav-mobile a.mise-en-avant {
  background: var(--accent); color: var(--accent-contrast);
  border-radius: var(--rayon); margin: 8px 16px; border-bottom: none;
  font-weight: 600;
}
.nav-mobile a.nav-mobile-enfant {
  padding-left: 32px;
  min-height: 44px;
  font-weight: 400;
  color: var(--fg-muted);
}

/* ---------- Recherche ---------- */

.recherche { position: relative; width: 100%; max-width: 680px; margin: 0 auto; }

.recherche-champ {
  display: flex; align-items: center; gap: 11px;
  background: var(--surface);
  border: 1.5px solid var(--border-strong);
  border-radius: var(--rayon);
  padding: 0 15px;
  height: 52px;
}
.recherche-champ:focus-within {
  border-color: var(--accent);
  /* L'input perd son outline natif (ci-dessous) : ce halo sur le
     conteneur reste l'unique indicateur de focus visible, il doit donc
     être net (pas seulement un changement de couleur de bordure, trop
     ténu pour la basse vision) — cf. WCAG 2.4.7/2.4.11. */
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.recherche-champ input {
  flex: 1; min-width: 0;
  border: none; outline: none; background: transparent;
  /* 16px minimum : en dessous, iOS zoome automatiquement au focus. */
  font-size: 16px;
  font-family: var(--font-sans);
  color: var(--fg);
}

.suggestions {
  position: absolute; top: calc(100% + 8px); left: 0; right: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--rayon);
  box-shadow: 0 10px 28px rgba(20, 20, 30, 0.1);
  overflow: hidden;
  z-index: 30;
  max-height: 60vh; overflow-y: auto;
}
.suggestions:empty { display: none; }

.suggestion {
  display: flex; align-items: center; gap: 12px;
  min-height: 58px; padding: 10px 15px;
  text-decoration: none; color: var(--fg);
  border-bottom: 1px solid var(--border);
}
.suggestion:last-child { border-bottom: none; }
.suggestion:hover, .suggestion.actif { background: var(--bg-alt); }
.suggestion-texte { flex: 1; min-width: 0; }
/* display:block obligatoire : sans lui, nom et sous-titre se collent
   sur une seule ligne (ce sont des <span>). */
.suggestion-nom { display: block; font-weight: 600; font-size: 0.92rem; }
.suggestion-sous { display: block; font-size: 0.78rem; color: var(--fg-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- Badges ---------- */

.badge {
  font-family: var(--font-mono);
  font-size: 0.63rem; font-weight: 600;
  letter-spacing: 0.03em; text-transform: uppercase;
  padding: 4px 8px; border-radius: 5px;
  /* `nowrap` convenait aux libellés courts de l'Assemblée (« RN »,
     « LFI-NFP »...), mais un badge de groupe politique européen peut
     porter un nom officiel complet (« Groupe de l'Alliance progressiste
     des socialistes et démocrates au Parlement européen ») qui déborde
     alors de l'écran sur mobile plutôt que de passer à la ligne —
     signalé par un utilisateur le 2026-09-01, capture d'écran à
     l'appui. `max-width` + `overflow-wrap` bornent le badge à son
     conteneur dans tous les cas, y compris un mot unique trop long. */
  white-space: normal; max-width: 100%; overflow-wrap: break-word;
}
.badge-elu { color: var(--accent); background: var(--accent-soft); }
.badge-groupe { color: var(--violet); background: var(--violet-soft); }
.badge-parti { color: var(--teal); background: var(--teal-soft); }
.badge-alerte { color: var(--warn); background: var(--warn-soft); }

/* ---------- Cartes et grilles ---------- */

.carte {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--rayon);
  padding: 18px 16px;
}

@media (min-width: 700px) { .carte { padding: 24px; } }

.grille { display: grid; gap: 12px; grid-template-columns: 1fr; }
@media (min-width: 700px) { .grille-2 { grid-template-columns: 1fr 1fr; } }
@media (min-width: 700px) { .grille-4 { grid-template-columns: repeat(4, 1fr); } }
@media (max-width: 699px) { .grille-4 { grid-template-columns: 1fr 1fr; } }

.pile { display: flex; flex-direction: column; gap: 20px; }
.pile-serree { display: flex; flex-direction: column; gap: 10px; }
.ligne { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* ---------- Statistiques ---------- */

.stat-valeur { font-family: var(--font-mono); font-size: 1.7rem; font-weight: 600; line-height: 1.1; }
.stat-libelle { font-size: 0.8rem; color: var(--fg-muted); }

.cite {
  font-family: var(--font-mono);
  font-size: 0.6rem; font-weight: 600;
  color: var(--accent); background: var(--accent-soft);
  padding: 1px 5px; border-radius: 4px;
  margin-left: 3px; vertical-align: super;
  text-decoration: none;
}
.cite:hover { background: var(--accent); color: var(--accent-contrast); }

.barre { display: flex; height: 12px; border-radius: 6px; overflow: hidden; background: var(--bg-alt); }
.barre span { display: block; height: 100%; }
.barre-pour { background: var(--positive); }
.barre-contre { background: var(--negative); }
.barre-abstention { background: var(--border-strong); }

.jauge { height: 8px; border-radius: 4px; background: var(--bg-alt); overflow: hidden; }
.jauge span { display: block; height: 100%; background: var(--accent); }

/* Garde-fou global : un `display` posé par une classe (`.encart`,
   `.ligne`…) prime sur le `display: none` que le navigateur applique
   par défaut à `[hidden]`, ce qui rend l'attribut inopérant dès qu'il
   est combiné à l'une de ces classes. Restaure le comportement attendu
   partout, plutôt que de corriger chaque classe une par une. */
[hidden] { display: none !important; }

/* ---------- Encarts ---------- */

.encart {
  display: flex; gap: 12px;
  padding: 16px;
  border-radius: 10px;
  font-size: 0.85rem;
  line-height: 1.6;
}
.encart-info { background: var(--bg-alt); color: var(--fg-muted); }
.encart-alerte { background: var(--warn-soft); border: 1px solid oklch(88% 0.05 60); }
.encart-vide { border: 1.5px dashed var(--border-strong); background: var(--bg-alt); }
.encart svg { flex-shrink: 0; margin-top: 2px; }

/* ---------- Sources ---------- */

.sources { border: 1px solid var(--border); border-radius: var(--rayon); background: var(--surface); overflow: hidden; }
.source { display: flex; gap: 11px; padding: 13px 15px; border-bottom: 1px solid var(--border); font-size: 0.8rem; line-height: 1.5; }
.source:last-child { border-bottom: none; }
.source-num { font-family: var(--font-mono); font-weight: 600; color: var(--accent); flex-shrink: 0; }
.source:target { background: var(--accent-soft); }

/* ---------- Tables / listes de membres ---------- */

.liste-liens { display: flex; flex-wrap: wrap; gap: 8px; }
.liste-interventions {
  display: flex; flex-direction: column; gap: 8px;
  list-style: none; padding: 0; margin: 0;
}
.liste-interventions li { padding: 8px 0; border-bottom: 1px solid var(--border); }
.liste-interventions li:last-child { border-bottom: none; }

/* Facade « cliquer pour charger » d'une intervention vidéo intégrée
   (un <a> classique, cf. video-embed.js) : rien n'est chargé depuis
   videos.assemblee-nationale.fr tant que la personne n'a pas
   explicitement demandé à regarder. */
.intervention-video-facade {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 8px 4px;
  cursor: pointer; text-decoration: none;
  font-family: var(--font-sans); color: var(--fg);
}
.intervention-video-facade:hover .intervention-video-icone { background: var(--accent-strong); }
.intervention-video-icone {
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0; width: 32px; height: 32px; border-radius: 50%;
  background: var(--accent); color: var(--accent-contrast);
}
.intervention-video-titre { font-weight: 600; font-size: 0.92rem; }
.intervention-video-cadre {
  position: relative; width: 100%; aspect-ratio: 16 / 9;
  border-radius: 8px; overflow: hidden; background: var(--bg-alt);
  margin: 4px 0;
}
.intervention-video-cadre iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.puce-lien {
  display: inline-flex; align-items: center;
  min-height: 36px; padding: 6px 12px;
  background: var(--bg-alt); border-radius: 18px;
  text-decoration: none; color: var(--fg); font-size: 0.82rem;
}
.puce-lien:hover { background: var(--accent-soft); color: var(--accent-strong); }

/* ---------- Comparateur ---------- */

.comparaison { display: flex; flex-direction: column; gap: 12px; }
.comparaison-entete {
  position: sticky; top: 56px; z-index: 10;
  display: flex; gap: 10px;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--rayon);
  padding: 12px;
}
.comparaison-colonne { flex: 1; min-width: 0; text-align: center; }
.comparaison-ligne { display: flex; gap: 12px; }
.comparaison-ligne > div { flex: 1; min-width: 0; }
.comparaison-ligne > div + div { padding-left: 12px; border-left: 1px solid var(--border); }

/* ---------- Articles ---------- */

.article-entete { text-align: center; padding: 8px 0 4px; }
.article-chapo {
  font-size: 1.05rem; line-height: 1.6;
  border-left: 3px solid var(--accent);
  padding-left: 18px; margin: 8px 0 4px;
}
.article-illustration { width: 100%; margin: 4px 0; }
.article-illustration svg { display: block; width: 100%; height: auto; }
.article-illustration figcaption {
  font-family: var(--font-mono); font-size: 0.72rem; color: var(--fg-faint);
  text-align: center; margin-top: 6px;
}
.article-schema {
  background: var(--bg-alt); border: 1px solid var(--border);
  border-radius: var(--rayon); padding: 18px;
}
.article-schema svg { display: block; width: 100%; height: auto; }
.article-schema figcaption {
  font-family: var(--font-mono); font-size: 0.72rem; color: var(--fg-faint);
  text-align: center; margin-top: 8px;
}
.article-carte { display: flex; gap: 16px; align-items: flex-start; }
h2 .num { font-family: var(--font-mono); font-size: 0.85rem; font-weight: 500; color: var(--accent); }
.article-carte .stat-valeur { min-width: 2.4em; }
.article-carte p { margin: 0; font-size: 0.9rem; color: var(--fg-muted); }
.articles-grille { display: grid; gap: 14px; grid-template-columns: 1fr; }
@media (min-width: 700px) { .articles-grille { grid-template-columns: 1fr 1fr; } }
.article-vignette { display: block; text-decoration: none; color: inherit; }
.article-vignette:hover { border-color: var(--border-strong); }
.article-vignette h2 { margin: 6px 0; }
.article-vignette p { margin: 0; }

/* ---------- Pied de page ---------- */

.pied {
  border-top: 1px solid var(--border);
  padding: 24px 0 32px;
  font-size: 0.8rem;
  color: var(--fg-faint);
}
.pied a { color: var(--fg-faint); text-decoration: none; }
.pied a:hover { color: var(--fg-muted); }
.pied-liens { display: flex; flex-wrap: wrap; gap: 16px; margin-bottom: 12px; }

/* Sélecteur de langue : rendu uniquement sur les pages traduites
   (cf. src/site/i18n) — six codes courts, pas de menu déroulant JS. */
.selecteur-langue {
  display: flex; flex-wrap: wrap; gap: 10px;
  margin-bottom: 12px; font-family: var(--font-mono);
  font-size: 0.72rem; letter-spacing: .02em;
}
.selecteur-langue a[aria-current="true"] {
  color: var(--accent); font-weight: 600;
}

/* ---------- Formulaire (contact / correction) ---------- */

.champ-formulaire { display: flex; flex-direction: column; gap: 6px; }
.champ-formulaire label { font-size: 0.85rem; font-weight: 600; }
.champ-formulaire input,
.champ-formulaire textarea {
  border: 1.5px solid var(--border-strong);
  border-radius: var(--rayon);
  padding: 12px 14px;
  background: var(--surface);
  color: var(--fg);
  font-family: var(--font-sans);
  /* 16px minimum : en dessous, iOS zoome automatiquement au focus. */
  font-size: 16px;
  resize: vertical;
}
.champ-formulaire input:focus,
.champ-formulaire textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* Piège à robots : invisible pour une personne, rempli par la plupart
   des scripts de spam qui remplissent tous les champs d'un formulaire.
   `aria-hidden` + retiré de l'ordre de tabulation : jamais rencontré
   par un lecteur d'écran. */
.champ-piege {
  position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden;
}

/* ---------- Divers ---------- */

.bouton {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 46px; padding: 12px 20px;
  border-radius: 9px; border: 1.5px solid var(--border-strong);
  background: var(--surface); color: var(--fg);
  font-family: var(--font-sans); font-size: 0.9rem; font-weight: 600;
  text-decoration: none; cursor: pointer;
}
.bouton-principal { background: var(--accent); color: var(--accent-contrast); border-color: var(--accent); }

.bouton-integrer {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; height: fit-content;
  border-radius: 7px; border: 1.5px solid var(--border-strong);
  background: var(--surface); color: var(--fg-muted);
  font-family: var(--font-sans); font-size: 0.78rem; font-weight: 600;
  cursor: pointer;
}
.bouton-integrer:hover { color: var(--fg); border-color: var(--accent); }

.popover-integrer {
  position: fixed; inset: 0; z-index: 50;
  display: flex; align-items: center; justify-content: center;
  background: rgba(20, 20, 30, 0.35); padding: 16px;
}
.popover-integrer-corps {
  width: 100%; max-width: 480px;
  background: var(--surface); border-radius: var(--rayon);
  border: 1px solid var(--border); box-shadow: 0 20px 50px rgba(20, 20, 30, 0.25);
  padding: 18px;
}
.bouton-fermer {
  border: none; background: none; cursor: pointer;
  font-size: 1.3rem; line-height: 1; color: var(--fg-faint); padding: 2px 6px;
}

/* Infobulle des diagrammes « ronds colorés » (/organisation) : posée
   par diagramme.js au survol d'un cercle, en repli sur le <title> SVG
   natif si JS est indisponible — cf. sa docstring. Position fixe,
   ignore le flux (créée une seule fois, déplacée par transform). */
.diagramme-infobulle {
  position: fixed; top: 0; left: 0; z-index: 40;
  pointer-events: none;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 10px 28px rgba(20, 20, 30, 0.14);
  padding: 8px 12px;
  max-width: 240px;
  font-family: var(--font-sans);
  transition: opacity .08s ease;
}
.diagramme-infobulle[hidden] { display: none; }
.diagramme-infobulle-nom {
  font-weight: 600; font-size: 0.86rem; color: var(--fg);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.diagramme-infobulle-groupe {
  display: flex; align-items: center; gap: 6px;
  font-size: 0.76rem; color: var(--fg-muted); margin-top: 2px;
}
.diagramme-infobulle-puce {
  width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0;
}
[data-diagramme] circle { cursor: pointer; transition: opacity .08s ease; }
[data-diagramme] circle:hover, [data-diagramme] circle.survol {
  opacity: 0.72;
}

/* Icône de portefeuille dans l'organigramme du gouvernement
   (/organisation) — cf. src/publication/icones_ministeres.py. */
.icone-ministere { flex-shrink: 0; opacity: 0.85; }

/* Lignes de hiérarchie de l'organigramme du gouvernement, tracées par
   organigramme.js sur grand écran uniquement (cf. sa docstring pour la
   limite de donnée qui justifie de ne relier que « Premier ministre →
   chaque ministre », jamais un ministre délégué à un ministre précis).
   `pointer-events: none` : le tracé ne doit jamais intercepter le clic
   sur une tuile qu'il chevauche visuellement. */
.organigramme-liens {
  position: absolute; inset: 0; width: 100%; height: 100%;
  z-index: -1; pointer-events: none;
}
.organigramme-liens path {
  fill: none; stroke: var(--border-strong); stroke-width: 1.5;
}
[data-organigramme-tuile] { position: relative; }

.fil { font-size: 0.78rem; color: var(--fg-faint); margin-bottom: 14px; }
.fil a { color: var(--fg-faint); text-decoration: none; }

.frise { display: flex; flex-direction: column; }
.frise-entree { display: flex; gap: 14px; }
.frise-marqueur { display: flex; flex-direction: column; align-items: center; padding-top: 6px; }
.frise-point { width: 11px; height: 11px; border-radius: 50%; background: var(--fg-faint); flex-shrink: 0; }
.frise-point.actif { background: var(--accent); }
.frise-trait { width: 2px; flex: 1; background: var(--border); margin: 4px 0; min-height: 12px; }
.frise-contenu { padding-bottom: 18px; }

table.donnees { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
table.donnees th, table.donnees td { text-align: left; padding: 10px 8px; border-bottom: 1px solid var(--border); }
table.donnees th { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--fg-muted); }

/* Toute zone qui ne peut pas être restructurée défile dans son propre
   cadre, jamais en poussant la page entière. */
.defilement-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }

.saut-contenu {
  position: absolute; left: -9999px;
  background: var(--accent); color: var(--accent-contrast);
  padding: 12px 18px; border-radius: 0 0 8px 0; z-index: 100;
}
.saut-contenu:focus { left: 0; top: 0; position: fixed; }

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* ---------- Accessibilité ---------- */

/* Anneau de focus explicite, cohérent sur tout le site (liens, boutons,
   cartes cliquables, éléments interactifs personnalisés) — ne dépend
   pas du rendu par défaut du navigateur, très variable en netteté
   d'un moteur à l'autre (Safari en particulier). `:focus-visible`
   plutôt que `:focus` : n'apparaît qu'au clavier, pas au clic souris,
   conforme à l'usage attendu. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Contraste renforcé : épaissit les bordures normalement fines pour
   les lecteurs qui ont explicitement demandé plus de contraste au
   niveau système (Windows « contraste élevé », réglages navigateur). */
@media (prefers-contrast: more) {
  .carte, .encart, .sources, .recherche-champ, .suggestions,
  .champ-formulaire input, .champ-formulaire textarea, .badge {
    border-width: 2px;
  }
}

/* ---------- Graphe des votes (/votes/) ----------
   Identifiants/classes préfixés `gv-` : page composée entièrement côté
   client (graphe-votes.js), isolée du reste du CSS du site. Couleurs de
   position alignées sur les tokens déjà utilisés pour un résultat de
   scrutin ailleurs sur le site (--positive/--negative), pas une palette
   propre à cette page. `--gv-pour-doux`/`--gv-contre-doux` : version
   pastel, réservée aux points/marqueurs représentant individuellement
   les élu·e·s qui votent (demandé par l'utilisateur, 2026-09-06) —
   jamais au texte, dont le contraste sur fond clair resterait sous le
   seuil WCAG AA avec ces teintes plus claires. Synchronisé avec
   `RGB_POUR`/`RGB_CONTRE` dans graphe-votes.js. */
.gv {
  --gv-pour: var(--positive);
  --gv-contre: var(--negative);
  --gv-pour-doux: #7FC49A;
  --gv-contre-doux: #E2938C;
  --gv-abstention: var(--warn);
  --gv-absent: var(--border-strong);
  margin-top: 16px;
  border: 1px solid var(--border);
  border-radius: var(--rayon);
  background: var(--surface);
  overflow: hidden;
}

.gv-entete {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
}
.gv-entete select, .gv-entete button {
  background: var(--surface);
  color: var(--fg);
  border: 1.5px solid var(--border-strong);
  border-radius: 8px;
  padding: 7px 10px;
  font-family: var(--font-sans);
  font-size: 0.85rem;
}
.gv-entete select#gv-scrutin { flex: 1; min-width: 220px; }
.gv-entete button { cursor: pointer; font-weight: 600; }
.gv-entete button:hover { border-color: var(--accent); color: var(--accent); }
.gv-entete button.gv-actif { background: var(--accent); color: var(--accent-contrast); border-color: var(--accent); }

.gv-bandeau {
  padding: 10px 16px;
  text-align: center;
  border-bottom: 1px solid var(--border);
  background: var(--bg-alt);
}
.gv-ligne1 { display: flex; align-items: center; justify-content: center; gap: 10px; }
.gv-date { color: var(--fg-faint); font-size: 0.78rem; }
.gv-badge {
  font-family: var(--font-sous-titre);
  font-size: 0.68rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
  padding: 2px 9px; border-radius: 999px;
}
.gv-badge.gv-adopte { background: color-mix(in oklch, var(--positive) 20%, white); color: var(--positive); }
.gv-badge.gv-rejete { background: color-mix(in oklch, var(--negative) 20%, white); color: var(--negative); }
.gv-badge.gv-autre { background: var(--border); color: var(--fg-muted); }
.gv-titre-texte {
  font-family: var(--font-titre);
  font-size: 0.95rem;
  margin-top: 4px;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 900px;
  margin-left: auto;
  margin-right: auto;
}
.gv-titre-texte::after {
  content: " · lire";
  font-family: var(--font-sans);
  font-size: 0.7rem;
  color: var(--accent);
}
.gv-titre-texte.gv-deplie { white-space: normal; text-overflow: clip; }
.gv-titre-texte.gv-deplie::after { content: ""; }

.gv-scene-conteneur { position: relative; height: 560px; }
#gv-scene { width: 100%; height: 100%; display: block; }

.gv-zone-etiquette {
  font-family: var(--font-sous-titre);
  font-size: 0.8rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
}
.gv-zone-etiquette.gv-pour { fill: var(--gv-pour); }
.gv-zone-etiquette.gv-contre { fill: var(--gv-contre); }
.gv-zone-etiquette.gv-neutre { fill: var(--fg-faint); }
.gv-groupe-label { font-family: var(--font-sous-titre); font-size: 9px; font-weight: 600; fill: var(--fg-muted); }
.gv-depute { stroke: var(--surface); stroke-width: 0.5; }

.gv-resultat {
  position: absolute; bottom: 10px; left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; gap: 18px;
  font-family: var(--font-mono); font-size: 0.8rem; font-weight: 600;
  z-index: 2;
  background: color-mix(in oklch, var(--surface) 88%, transparent);
  padding: 6px 12px; border-radius: 999px;
  white-space: nowrap;
}
.gv-resultat .gv-pour { color: var(--gv-pour); }
.gv-resultat .gv-contre { color: var(--gv-contre); }
.gv-resultat .gv-abstention { color: var(--gv-abstention); }
.gv-toggle-composition {
  font-family: var(--font-sans); font-size: 0.75rem; font-weight: 600;
  color: var(--accent);
  background: var(--accent-soft);
  border: none; border-radius: 999px;
  padding: 5px 12px;
  cursor: pointer;
}
.gv-toggle-composition:hover { background: var(--accent); color: var(--accent-contrast); }

.gv-tooltip {
  position: absolute; pointer-events: none;
  background: var(--fg); color: var(--surface);
  border-radius: 8px; padding: 8px 11px;
  font-family: var(--font-sans); font-size: 0.75rem;
  line-height: 1.5;
  display: none; z-index: 6;
  max-width: 220px;
}
.gv-tooltip.gv-ouvert { display: block; pointer-events: auto; }
.gv-tooltip strong { display: block; font-size: 0.8rem; }
.gv-tooltip a {
  display: inline-block; margin-top: 4px;
  color: var(--accent-soft); text-decoration: underline;
}
.gv-tooltip a:hover { color: var(--surface); }

/* Vue mobile (< 820px, cf. graphe-votes.js) : liste de barres empilées
   plutôt qu'un nuage de points illisible sur un écran étroit — voir la
   docstring de `dessinerVoteMobile` dans le script. */
.gv-mobile-liste { position: relative; height: 100%; overflow-y: auto; padding: 12px 14px 24px; }
.gv-mobile-zones {
  display: flex; justify-content: space-between; align-items: center;
  padding: 0 2px 6px; position: sticky; top: 0; background: var(--surface); z-index: 1;
}
/* Police explicite plutôt qu'une inheritance sur plusieurs niveaux
   (`.gv-mobile-zones` → `.gv-mobile-liste` → `.gv` → `body`) : même
   traitement typographique que `.gv-groupe-label`/`.gv-nom`
   (sous-titre, pas le texte courant), demandé explicitement par
   l'utilisateur (2026-09-06) pour que la légende et le nom des
   groupes restent visuellement cohérents dans tous les moteurs. */
.gv-etiquette {
  font-family: var(--font-sous-titre); font-weight: 700;
  font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em;
}
.gv-mobile-zones .gv-etiquette.gv-pour { color: var(--gv-pour); }
.gv-mobile-zones .gv-etiquette.gv-contre { color: var(--gv-contre); }
.gv-legende {
  display: flex; gap: 8px; font-family: var(--font-sous-titre);
  font-size: 0.68rem; color: var(--fg-faint);
}
.gv-puce { display: inline-block; width: 8px; height: 8px; border-radius: 2px; margin-right: 3px; }
.gv-puce-pour { background: var(--gv-pour-doux); }
.gv-puce-contre { background: var(--gv-contre-doux); }
.gv-puce-abstention { background: var(--gv-abstention); }
.gv-puce-absent { background: var(--gv-absent); }

.gv-ligne-groupe { position: absolute; left: 14px; right: 14px; height: 64px; }
.gv-ligne-groupe .gv-nom {
  display: flex; justify-content: space-between; align-items: baseline;
  font-family: var(--font-sous-titre); font-size: 0.75rem; font-weight: 600;
  color: var(--fg-muted); margin-bottom: 4px;
}
.gv-ligne-groupe .gv-effectif { font-weight: 400; color: var(--fg-faint); font-family: var(--font-mono); }
.gv-barre-empilee { display: flex; height: 20px; border-radius: 5px; overflow: hidden; }
.gv-barre-empilee .gv-segment { height: 100%; flex: 0 0 auto; }

/* Piste + marqueur de majorité : le groupe reste sur sa ligne (jamais
   de réordonnancement vertical, cf. graphe-votes.js), seul ce marqueur
   se déplace horizontalement entre le bord « Pour » (gauche) et le
   bord « Contre » (droite) — mouvement demandé par l'utilisateur en
   remplacement du réordonnancement vertical, illisible sur petit
   écran. */
.gv-piste-majorite {
  position: relative;
  height: 4px;
  margin-top: 8px;
  border-radius: 2px;
  background: linear-gradient(to right, var(--gv-pour-doux), var(--border) 15%, var(--border) 85%, var(--gv-contre-doux));
  opacity: 0.55;
}
.gv-marqueur-majorite {
  position: absolute;
  top: 50%;
  width: 12px; height: 12px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  box-shadow: 0 0 0 2px var(--surface);
}

@media (max-width: 640px) {
  .gv-scene-conteneur { height: 70vh; }
  .gv-resultat {
    flex-wrap: wrap; justify-content: center;
    white-space: normal; gap: 6px 12px;
    width: calc(100% - 24px);
    font-size: 0.72rem;
  }
  .gv-toggle-composition { flex-basis: 100%; text-align: center; }
}
