:root {
  --bg: #f6f5f2;
  --surface: #ffffff;
  --surface-2: #efeeea;
  --border: #dcd9d2;
  --text: #1e1c19;
  --muted: #6c6862;
  --accent: #8a4b2a;
  --accent-soft: #f0e2d8;
  --ok: #2f6b45;
  --warn: #9a6212;
  --err: #9c3128;
  --radius: 10px;
  --shadow: 0 1px 2px rgba(0,0,0,.06), 0 4px 14px rgba(0,0,0,.05);

  /* Couleurs de série des graphiques, attribuées dans un ordre fixe et jamais
     recyclées. Écarts vérifiés sur TOUTES les paires, pas seulement les voisines :
     une quatrième teinte ne passait plus le seuil de lisibilité, d'où le choix de
     replier la queue des séries dans « autres » plutôt que d'en ajouter une. */
  --serie-1: #a8451a;
  --serie-2: #1b5fbe;
  --serie-3: #0d7d5e;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #16150f;
    --surface: #201e18;
    --surface-2: #2a2721;
    --border: #3a362d;
    --text: #ece8df;
    --muted: #a09a8e;
    --accent: #d4915f;
    --accent-soft: #38291d;
    --ok: #7ec48f;
    --warn: #d9a441;
    --err: #e08174;
    --shadow: 0 1px 2px rgba(0,0,0,.4), 0 4px 14px rgba(0,0,0,.3);
    /* Le mode sombre a ses propres pas, choisis contre son fond — jamais un
       simple éclaircissement des couleurs du mode clair. */
    --serie-1: #c4762f;
    --serie-2: #4a90e2;
    --serie-3: #3fa07a;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font: 15px/1.55 "Segoe UI", system-ui, -apple-system, sans-serif;
  background: var(--bg);
  color: var(--text);
}

/* --- Barre supérieure ----------------------------------------------------- */
.topbar {
  display: flex; align-items: center; gap: 24px;
  padding: 10px 20px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 30;
}
.brand {
  display: flex; align-items: center; gap: 10px;
  color: inherit; text-decoration: none;
}
.crest { width: 27px; height: 27px; color: var(--accent); flex: none; }
.brand strong { display: block; font-size: 15px; }
.brand small { color: var(--muted); font-size: 12px; }

/* Cinq entrées seulement : une par question que se pose un habitant. */
.tabs { display: flex; gap: 4px; flex: 1; }
.tabs a {
  padding: 7px 14px; border-radius: var(--radius);
  color: var(--muted); text-decoration: none;
  cursor: pointer; white-space: nowrap;
}
.tabs a:hover { background: var(--surface-2); color: var(--text); }
.tabs a.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }

/* Recherche permanente : elle n'est pas un sujet, c'est un outil — sa place
   est dans le bandeau, pas dans la rangée des sujets. */
.quicksearch { display: flex; gap: 6px; }
.quicksearch input { padding: 6px 11px; font-size: 13.5px; width: 170px; }
.quicksearch button { padding: 6px 11px; font-size: 13.5px; }

/* Menu d'administration, derrière le compte : gérer n'est pas lire. */
.menu { position: relative; }
.menu > summary {
  list-style: none; cursor: pointer; padding: 5px 10px;
  border: 1px solid var(--border); border-radius: var(--radius);
  color: var(--muted); white-space: nowrap;
}
.menu > summary::-webkit-details-marker { display: none; }
.menu > summary:hover { border-color: var(--accent); color: var(--text); }
.menu[open] > summary { border-color: var(--accent); color: var(--accent); }
.menu-liste {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 40;
  display: flex; flex-direction: column; min-width: 190px; padding: 5px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow);
}
.menu-liste a {
  padding: 8px 11px; border-radius: 5px;
  color: var(--text); text-decoration: none; font-size: 13.5px;
}
.menu-liste a:hover { background: var(--surface-2); }

.status { font-size: 13px; color: var(--muted); min-width: 200px; text-align: right; }
.status:empty { min-width: 0; }
.status .bar {
  display: block; height: 3px; background: var(--surface-2);
  border-radius: 2px; margin-top: 4px; overflow: hidden;
}
.status .bar i { display: block; height: 100%; background: var(--accent); transition: width .3s; }

/* --- Compte connecté ------------------------------------------------------ */
.account {
  display: flex; align-items: center; gap: 8px;
  font-size: 13px; color: var(--muted); white-space: nowrap;
}
.account button { padding: 5px 10px; font-size: 13px; }

/* Pastille d'alerte : signalements en attente, sur l'onglet d'administration. */
.pastille {
  display: inline-block; margin-left: 7px; min-width: 18px; padding: 0 5px;
  background: var(--err); color: #fff; border-radius: 9px;
  font-size: 11px; font-weight: 700; line-height: 18px; text-align: center;
}

/* Formulaire de signalement : champs empilés, libellés au-dessus. */
#formReport { display: flex; flex-direction: column; gap: 14px; max-width: 62ch; }
#formReport label { display: flex; flex-direction: column; gap: 5px; }
#formReport label > span { font-size: 13.5px; font-weight: 600; }
#formReport label em { font-weight: 400; color: var(--muted); font-style: normal; }
#formReport textarea {
  font: inherit; padding: 9px 12px; resize: vertical;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); color: var(--text);
}

/* Case de droit accordé au cas par cas, dans la gestion des comptes. */
.droit {
  display: flex; align-items: center; gap: 6px;
  font-size: 13px; color: var(--muted); white-space: nowrap; cursor: pointer;
}
.droit input { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; }
.droit input:disabled { cursor: default; opacity: .55; }

dialog {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); color: var(--text);
  padding: 22px 24px; box-shadow: var(--shadow); min-width: 320px;
}
dialog::backdrop { background: rgba(0, 0, 0, .45); }
dialog form { display: flex; flex-direction: column; gap: 10px; }
/* Dans une boîte de dialogue, le titre nomme l'action en cours : il n'a rien à
   séparer et ne doit pas écraser les deux champs qu'il surmonte. */
dialog h3 {
  color: var(--text); font-size: 17px; letter-spacing: 0;
  margin: 0 0 4px; padding-top: 0; border-top: 0;
}

/* --- Structure ------------------------------------------------------------ */
main { padding: 20px; max-width: 1600px; margin: 0 auto; }
.view { display: none; }
.view.active { display: block; }

/* Volets d'une séance : tout ce qui la concerne tient sous un seul en-tête,
   au lieu d'être redemandé dans quatre menus déroulants. */
.volets {
  display: flex; gap: 2px; margin: 18px 0 20px;
  border-bottom: 1px solid var(--border); overflow-x: auto;
  scrollbar-width: none;
}
.volets::-webkit-scrollbar { display: none; }
.volets a {
  padding: 9px 15px; margin-bottom: -1px;
  border-bottom: 2px solid transparent;
  color: var(--muted); text-decoration: none;
  cursor: pointer; white-space: nowrap; font-size: 14px;
}
.volets a:hover { color: var(--text); }
.volets a.active { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }
.volet { display: none; }
.volet.active { display: block; }

/* Lien qui se présente comme un bouton : l'action est une navigation, donc
   une adresse — elle doit rester copiable et ouvrable dans un onglet. */
.bouton {
  display: inline-block; padding: 8px 12px; text-decoration: none;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); color: var(--text); font-size: 15px;
}
.bouton:hover { border-color: var(--accent); }
.bouton.primary { background: var(--accent); color: #fff; border-color: var(--accent); }
.bouton.primary:hover { filter: brightness(1.08); }

/* Échange écrit avec la mairie, sous l'agrégat qu'il éclaire. */
.echange { margin: 18px 0 6px; }
.echange > summary {
  display: flex; align-items: baseline; gap: 12px;
  padding: 10px 14px; cursor: pointer; list-style: none;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius);
}
.echange > summary::-webkit-details-marker { display: none; }
.echange > summary:hover { border-color: var(--accent); }
.echange-corps { padding: 4px 2px 0; max-width: 82ch; }
.message {
  margin: 14px 0; padding: 12px 16px;
  border-left: 3px solid var(--border); background: var(--surface);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.message .head {
  display: flex; gap: 10px; align-items: baseline;
  flex-wrap: wrap; margin-bottom: 6px;
}
.message p { margin: 8px 0; }
.message p:last-child { margin-bottom: 0; }

/* Relevé de vérification : le verdict tient dans le bord et dans le badge, pas
   dans le ton du texte. */
.message.verifie .head { gap: 12px; }
.message.verifie .head b { flex: 1; min-width: 0; }
.sources { margin-top: 8px; }
.sources a { color: var(--accent); }

/* La bulle de vérification.
 *
 * Partout ailleurs, la page rapporte : des chiffres publiés par l'État, des
 * propos réellement tenus. Ici, c'est le site lui-même qui parle et qui
 * apprécie. Ce changement de nature doit se voir avant d'être lu — sinon le
 * lecteur prend une appréciation pour un fait. D'où un registre à part : fond
 * teinté de la couleur de la marque, contour continu, angles très arrondis.
 * Une fois ce code appris sur un agrégat, il vaut pour tous les autres.
 */
.analyse {
  margin: 26px 0 8px;
  padding: 4px 20px 20px;
  background: var(--accent-soft);
  /* En thème clair, la teinte ne s'écarte du fond de page que de 17 points de
     luminance : c'est le contour qui fait le gros du travail. */
  border: 2px solid color-mix(in srgb, var(--accent) 42%, transparent);
  border-radius: 18px;
}
.analyse > summary {
  background: none; border: 0; border-radius: 0;
  padding: 14px 0 8px; gap: 10px; flex-wrap: wrap;
}
.analyse > summary:hover { border: 0; color: var(--accent); }
.analyse > summary .year-label { font-size: 16px; }
.analyse .echange-corps { padding: 0; max-width: 78ch; }
/* Les fiches remontent sur le fond clair : dans la bulle, elles doivent rester
   les éléments lisibles, pas se fondre dans la teinte. */
.analyse .message { background: var(--surface); border-left-width: 4px; }
.analyse .notes { color: var(--muted); }

/* Marque du registre, visible même quand la bulle est repliée. */
.badge.marque {
  background: var(--accent); color: var(--bg);
  letter-spacing: .06em;
}
@media (max-width: 760px) {
  .analyse { padding: 4px 13px 14px; border-radius: 14px; }
}

/* Sommaire des Finances : neuf chapitres qu'on doit pouvoir survoler et citer. */
.sommaire {
  margin: 20px 0 8px; padding: 14px 16px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius);
}
.sommaire > b { font-size: 13px; color: var(--muted); }
.sommaire-liens {
  display: grid; gap: 4px 18px; margin-top: 10px;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
}
.sommaire-liens a {
  display: flex; justify-content: space-between; gap: 12px; align-items: baseline;
  padding: 5px 8px; border-radius: 5px;
  color: var(--text); text-decoration: none; font-size: 13.5px;
}
.sommaire-liens a:hover { background: var(--surface-2); }
.sommaire-liens small {
  color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap;
}

.page-foot {
  margin: 46px 0 10px; padding-top: 16px;
  border-top: 1px solid var(--border); font-size: 13px;
}
.page-foot a { color: var(--muted); }

/* Titre de page. Il doit rester au-dessus des titres de section, qui sont
   volontairement grands : sans cela, une section paraîtrait dominer la page
   qui la contient. */
h2 { margin: 0; font-size: 34px; line-height: 1.15; letter-spacing: -.01em; }

/* Titre de section.
 *
 * Il était gris et de la taille du texte courant : sur une page qui aligne
 * neuf chapitres — Finances — ou quatre — Élus —, on ne voyait pas où l'un
 * finissait et où le suivant commençait. Un filet et un blanc franc au-dessus
 * font le découpage ; le corps double le rend repérable au défilement, sans
 * qu'on ait à lire pour savoir qu'on change de sujet.
 */
h3 {
  font-size: 30px; line-height: 1.2; letter-spacing: -.01em;
  color: var(--text); font-weight: 600;
  margin: 52px 0 18px; padding-top: 24px;
  border-top: 2px solid var(--border);
}
/* Le premier titre d'un bloc n'a rien à séparer de ce qui le précède. */
h3:first-child { margin-top: 6px; padding-top: 0; border-top: 0; }

/* Dans une grille de colonnes, ces titres étiquettent un bloc et non une
   section de la page : les grandir les ferait passer pour des chapitres. */
.split h3 {
  font-size: 15px; color: var(--muted); font-weight: 600;
  letter-spacing: 0; margin: 0 0 10px;
}

.toolbar {
  display: flex; gap: 12px; align-items: center;
  flex-wrap: wrap; margin-bottom: 18px;
}
.inline-form { display: flex; gap: 8px; }
.inline-form input { min-width: 260px; }

input, select, button {
  font: inherit; padding: 8px 12px;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); color: var(--text);
}
button { cursor: pointer; }
button:hover:not(:disabled) { border-color: var(--accent); }
button:disabled { opacity: .5; cursor: not-allowed; }
button.primary { background: var(--accent); color: #fff; border-color: var(--accent); }
button.primary:hover:not(:disabled) { filter: brightness(1.08); }
button.ghost { background: none; border-color: transparent; color: var(--muted); }
button.ghost:hover { background: var(--surface-2); color: var(--text); }

.muted { color: var(--muted); font-size: 13px; }

/* --- Cartes --------------------------------------------------------------- */
.cards { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); }
.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 14px; box-shadow: var(--shadow);
  display: flex; flex-direction: column; gap: 10px;
}
.card h4 { margin: 0; font-size: 15px; line-height: 1.35; }
.card .meta { color: var(--muted); font-size: 13px; }
.card .row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.card video { width: 100%; border-radius: 6px; background: #000; }

.badge {
  font-size: 11px; padding: 2px 8px; border-radius: 20px;
  background: var(--surface-2); color: var(--muted); font-weight: 600;
  text-transform: uppercase; letter-spacing: .04em;
}
.badge.done { background: color-mix(in srgb, var(--ok) 18%, transparent); color: var(--ok); }
.badge.err  { background: color-mix(in srgb, var(--err) 18%, transparent); color: var(--err); }
.badge.warn { background: color-mix(in srgb, var(--warn) 20%, transparent); color: var(--warn); }

.progress { height: 4px; background: var(--surface-2); border-radius: 2px; overflow: hidden; }
.progress i { display: block; height: 100%; background: var(--accent); transition: width .4s; }

/* --- Dossiers par année --------------------------------------------------- */
.year { margin-bottom: 10px; }
.year > summary {
  display: flex; align-items: baseline; gap: 12px;
  padding: 10px 14px; cursor: pointer; list-style: none;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); user-select: none;
}
.year > summary:hover { border-color: var(--accent); }
.year[open] > summary { margin-bottom: 12px; }
.year > summary::-webkit-details-marker { display: none; }
/* Chevron dessiné en CSS : il pivote à l'ouverture du dossier. */
.year > summary::before {
  content: '›'; font-size: 18px; line-height: 1; color: var(--muted);
  transition: transform .15s; display: inline-block;
}
.year[open] > summary::before { transform: rotate(90deg); }
.year-label { font-size: 17px; font-weight: 700; font-variant-numeric: tabular-nums; }
.year > .cards { margin: 0 0 22px 14px; }

/* Même dossier, teinté par le groupe politique. */
.year.group > summary { border-left: 4px solid var(--tone, var(--border)); }
.year.group > summary .year-label { font-size: 15px; }

/* Dossiers imbriqués : séance > groupe > élus, ou compte > séance > demandes.
   Chaque niveau se décale, et n'emprunte pas la taille de titre du premier. */
.year .year { margin: 0 0 8px 14px; }
.year .year > summary { padding: 8px 12px; background: var(--surface-2); }
.year .year > summary .year-label { font-size: 14px; font-weight: 600; }
.year[open] > .year:last-child { margin-bottom: 20px; }

/* --- Graphiques ----------------------------------------------------------- */
.chart {
  width: 100%; height: auto; max-width: 900px;
  margin: 6px 0 26px; overflow: visible;
}
.chart .grid { stroke: var(--border); stroke-width: 1; }
.chart .tick { fill: var(--muted); font-size: 11px; }
.chart .bar-name { fill: var(--text); font-size: 13px; }
.chart .bar-figure {
  fill: var(--muted); font-size: 12px;
  font-variant-numeric: tabular-nums; dominant-baseline: middle;
}
.chart rect { transition: opacity .15s; }
.chart rect:hover { opacity: .78; }

/* Bande de mandat, en fond du graphique chronologique. */
.chart .mandat { fill: var(--surface-2); opacity: .5; }
.chart .mandat-nom { fill: var(--muted); font-size: 12px; font-weight: 600; }
.chart .frise { fill: var(--surface-2); }
/* Trait au sol marquant un exercice à zéro constaté. */
.chart .zero { stroke: var(--warn); stroke-width: 3; stroke-linecap: round; }
.chart .valeur {
  fill: var(--text); font-size: 12px; font-weight: 600;
  paint-order: stroke; stroke: var(--surface); stroke-width: 3px;
}

/* --- Colonnes interactives ------------------------------------------------ */
.chart-frame { position: relative; max-width: 940px; margin-bottom: 8px; }
.chart .cible { fill: transparent; }
.chart .colonne { cursor: default; outline: none; }
.chart .colonne .barre { transition: opacity .12s; }
.chart .colonne:hover .cible,
.chart .colonne:focus-visible .cible { fill: var(--surface-2); opacity: .6; }
.chart .colonne:focus-visible .barre { stroke: var(--text); stroke-width: 2; }

.tip {
  position: absolute; top: 8px; right: 8px; pointer-events: none;
  display: flex; flex-direction: column; gap: 1px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 9px 13px; box-shadow: var(--shadow);
  font-size: 12.5px; color: var(--muted); max-width: 260px;
}
.tip b { font-size: 17px; color: var(--text); font-weight: 700; }

/* --- Vue tabulaire -------------------------------------------------------- */
.table-view { margin: 4px 0 26px; }
.table-view > summary {
  cursor: pointer; color: var(--muted); font-size: 13px;
  padding: 6px 0; width: fit-content;
}
.table-view > summary:hover { color: var(--accent); }
.table-view table { border-collapse: collapse; font-size: 13.5px; margin-top: 6px; }
.table-view th, .table-view td {
  text-align: left; padding: 5px 16px 5px 0;
  border-bottom: 1px solid var(--border);
}
.table-view th { color: var(--muted); font-weight: 600; }
.table-view td.nombre { font-variant-numeric: tabular-nums; }

/* --- Page de texte suivi --------------------------------------------------- */
.prose { max-width: 74ch; }
.prose h2 { margin-bottom: 4px; }
.prose h3 { margin-top: 52px; color: var(--text); }
.prose p { line-height: 1.65; margin: 0 0 14px; }
.prose .chapeau {
  font-size: 17px; line-height: 1.6; color: var(--muted);
  border-left: 3px solid var(--accent); padding-left: 16px; margin: 14px 0 26px;
}
.prose a { color: var(--accent); }

.notes { max-width: 82ch; padding-left: 20px; margin: 0 0 24px; }
.notes li { margin-bottom: 9px; line-height: 1.5; }
.notes b { color: var(--text); }

.legend { display: flex; flex-wrap: wrap; gap: 16px; margin-bottom: 26px; }
.legend > span { display: flex; align-items: center; gap: 7px; font-size: 13px; color: var(--muted); }
.legend i { width: 12px; height: 12px; border-radius: 3px; display: inline-block; }

/* --- Résumé de séance ----------------------------------------------------- */
.figures { display: flex; flex-wrap: wrap; gap: 10px; margin: 16px 0 4px; }
.figure {
  flex: 1 1 130px; display: flex; flex-direction: column; gap: 2px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 12px 14px; box-shadow: var(--shadow);
}
.figure b { font-size: 25px; line-height: 1.1; font-variant-numeric: tabular-nums; }
.figure span { color: var(--muted); font-size: 12.5px; }

.narrative { max-width: 78ch; margin-top: 18px; }
.narrative p { margin: 0 0 14px; text-align: justify; hyphens: auto; }

.highlights { display: flex; flex-direction: column; gap: 2px; }
.highlight {
  display: grid; grid-template-columns: 84px 1fr; gap: 12px;
  padding: 9px 12px; border-radius: 8px; align-items: baseline;
}
.highlight:hover { background: var(--surface-2); }

.split { display: grid; gap: 8px 32px; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.bars { display: flex; flex-direction: column; gap: 6px; }
.bar-row { display: grid; grid-template-columns: 1fr 100px 34px; gap: 10px; align-items: center; font-size: 13.5px; }
.bar-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar-track { height: 8px; background: var(--surface-2); border-radius: 4px; overflow: hidden; }
.bar-track i { display: block; height: 100%; background: var(--accent); }
.bar-value { color: var(--muted); text-align: right; font-variant-numeric: tabular-nums; }

/* Résultats d'un scrutin : une ligne par liste, la barre à l'échelle des voix,
   et les sièges à part — c'est le chiffre qui décide, pas le pourcentage. */
.tour-titre {
  display: flex; align-items: baseline; gap: 12px;
  margin: 26px 0 10px; font-size: 15px;
}
.tour-titre small { color: var(--muted); font-weight: 400; font-size: 13px; }
.bars.scrutin { margin-top: 4px; gap: 10px; }
.bar-row.scrutin-ligne { grid-template-columns: minmax(0, 1fr) 150px 150px 78px; }
.scrutin-ligne .bar-label {
  display: flex; flex-direction: column; gap: 1px;
  min-width: 0; overflow: hidden; white-space: normal;
}
.scrutin-ligne .bar-label b { font-weight: 600; line-height: 1.3; }
.scrutin-ligne .bar-label small { color: var(--muted); font-size: 12px; }
.scrutin-ligne .bar-value { white-space: nowrap; }
.scrutin-ligne .sieges {
  text-align: right; font-variant-numeric: tabular-nums;
  font-weight: 600; white-space: nowrap; font-size: 13.5px;
}
@media (max-width: 760px) {
  /* En colonne étroite la barre passe sous le nom, plutôt que de comprimer
     les deux jusqu'à l'illisible. */
  .bar-row.scrutin-ligne { grid-template-columns: minmax(0, 1fr) auto; gap: 4px 12px; }
  .scrutin-ligne .bar-track { grid-column: 1 / -1; order: 3; }
  .scrutin-ligne .bar-value { text-align: right; }
}

/* --- Espace de travail ---------------------------------------------------- */
.detail-head { display: flex; align-items: center; gap: 14px; margin-bottom: 16px; }
.detail-titre { flex: 1; min-width: 0; }
.detail-titre h2 { margin-bottom: 3px; }

/* Le titre d'une séance consultable est un lien : c'est la porte d'entrée. */
.card h4 a { color: inherit; text-decoration: none; }
.card h4 a:hover { color: var(--accent); }
.card.ouvrable:hover { border-color: var(--accent); }

/* Renvoi à la seconde exacte de la vidéo — le fondement du site. */
.passage, .highlight .passage {
  color: var(--accent); text-decoration: none; font-size: 13px;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.passage:hover { text-decoration: underline; }

.workspace {
  display: grid; grid-template-columns: minmax(400px, 45%) 1fr;
  gap: 18px; align-items: start;
}
/* Le passage en colonne unique ne se limite pas à cette ligne : il demande de
   revoir le lecteur collant et les hauteurs. La suite est regroupée après les
   règles de base, plus bas — à spécificité égale, c'est la dernière déclaration
   qui l'emporte, et un bloc placé ici serait écrasé par ce qui le suit. */
@media (max-width: 1100px) { .workspace { grid-template-columns: 1fr; } }

.player-pane { position: sticky; top: 76px; display: flex; flex-direction: column; gap: 12px; }
#player { width: 100%; border-radius: var(--radius); background: #000; aspect-ratio: 16/9; }

.speakers { display: flex; flex-direction: column; gap: 6px; max-height: 40vh; overflow-y: auto; }
.speaker {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 10px; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius);
}
.speaker .dot { width: 10px; height: 10px; border-radius: 50%; flex: none; }
.speaker .who { flex: 1; min-width: 0; }
.speaker .who b { display: block; font-size: 14px; }
.speaker .who small { color: var(--muted); font-size: 12px; }
.speaker select { padding: 5px 8px; font-size: 13px; max-width: 190px; flex: none; }

/* --- Transcription -------------------------------------------------------- */
.transcript-pane {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); overflow: hidden;
}
.transcript-tools {
  display: flex; gap: 10px; align-items: center; padding: 10px;
  border-bottom: 1px solid var(--border); background: var(--surface-2);
  flex-wrap: wrap;
}
.transcript-tools input[type=search] { flex: 1; min-width: 160px; }
.follow { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--muted); white-space: nowrap; }

.transcript { max-height: calc(100vh - 220px); overflow-y: auto; padding: 6px; }

/* --- Colonne unique (sous 1100 px) ----------------------------------------
   Le lecteur n'est plus À CÔTÉ de la transcription mais AU-DESSUS d'elle.
   Étant collant, il lui faut alors un fond opaque et un plan de superposition :
   les lignes de transcription sont positionnées — position: relative, pour
   loger les outils d'extrait — et viennent après dans le DOM, si bien qu'à
   z-index égal elles se peignaient par-dessus la vidéo et la liste des voix.
   Le texte défilait littéralement à travers l'image.

   Ce bloc doit rester APRÈS les règles de base qu'il corrige : elles ont la
   même spécificité, et seul l'ordre les départage. */
@media (max-width: 1100px) {
  .player-pane {
    position: sticky; top: 76px; z-index: 20;
    background: var(--bg); padding-bottom: 8px;
  }
  /* Sur toute la largeur, un 16/9 de 900 px ferait 500 px de haut : collé en
     tête, il ne laisserait presque rien à lire. */
  #player { max-height: 42vh; object-fit: contain; }
  /* Plus de zone de défilement propre à la transcription : ce serait une
     seconde barre imbriquée dans celle de la page, sous un lecteur qui en
     masque déjà le haut. C'est la page qui défile, et le suivi de lecture s'y
     adapte de lui-même (voir centrerLigne dans app.js). */
  .speakers { max-height: none; }
  .transcript { max-height: none; }
}

.line {
  display: grid; grid-template-columns: 74px 1fr; gap: 10px;
  padding: 7px 10px; border-radius: 8px; position: relative;
}
.line:hover { background: var(--surface-2); }
.line.current { background: var(--accent-soft); }
.line.in-range { box-shadow: inset 3px 0 0 var(--accent); }
.line .time {
  color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums;
  cursor: pointer; padding-top: 3px;
}
.line .time:hover { color: var(--accent); text-decoration: underline; }
.line .who { font-size: 12px; font-weight: 700; margin-bottom: 2px; }
.line .txt { cursor: pointer; }
.line .tools {
  position: absolute; right: 8px; top: 5px; display: none; gap: 3px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 6px; padding: 2px;
}
.line:hover .tools { display: flex; }
.line .tools button {
  padding: 2px 7px; font-size: 12px; border: none; background: none;
  border-radius: 4px; color: var(--muted);
}
.line .tools button:hover { background: var(--accent-soft); color: var(--accent); }
mark { background: color-mix(in srgb, var(--accent) 28%, transparent); color: inherit; border-radius: 3px; }

/* --- Barre d'extrait ------------------------------------------------------ */
.clipbar {
  position: fixed; bottom: 0; left: 0; right: 0; z-index: 25;
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  padding: 12px 20px; background: var(--surface);
  border-top: 1px solid var(--border); box-shadow: 0 -4px 20px rgba(0,0,0,.1);
  flex-wrap: wrap;
}
.clipbar.hidden { display: none; }
.clip-range { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.clip-preview {
  color: var(--muted); font-size: 13px; font-style: italic;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 60ch;
}
.clip-controls { display: flex; gap: 10px; align-items: center; }
.clip-controls label { display: flex; align-items: center; gap: 6px; font-size: 13px; }

/* --- Affirmations et résultats -------------------------------------------- */
.claims { display: flex; flex-direction: column; gap: 10px; }
.claim {
  background: var(--surface); border: 1px solid var(--border);
  border-left: 3px solid var(--accent); border-radius: var(--radius); padding: 12px 14px;
}
.claim .head { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; margin-bottom: 6px; }
.claim .head b { font-size: 14px; }
.claim blockquote {
  margin: 8px 0 0; padding-left: 12px; border-left: 2px solid var(--border);
  color: var(--muted); font-style: italic; font-size: 14px;
}
.claim a { color: var(--accent); text-decoration: none; font-size: 13px; }
.claim a:hover { text-decoration: underline; }

.contradiction { border-left-color: var(--err); }
.contradiction .pair { display: grid; gap: 10px; grid-template-columns: 1fr 1fr; margin-top: 8px; }
@media (max-width: 800px) { .contradiction .pair { grid-template-columns: 1fr; } }
.contradiction .side {
  background: var(--surface-2); border-radius: 8px; padding: 10px; font-size: 14px;
}

.empty { color: var(--muted); padding: 40px; text-align: center; }

/* --- Extraits, toutes séances réunies -------------------------------------- */
.extrait-seance { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
.extrait-seance a { color: inherit; text-decoration: none; }
.extrait-seance a:hover { color: var(--accent); }

/* Deux formats coexistent, 16:9 et 9:16. Une grille qui étirerait toutes les
   cartes à la même hauteur écraserait les portraits : chaque vignette porte
   donc son propre rapport, et la grille s'aligne sur le haut des cartes. */
.cards.extraits {
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  align-items: start;
}

.extrait-scene {
  position: relative; aspect-ratio: 16 / 9;
  background: #000; border-radius: 6px; overflow: hidden;
}
.extrait-scene.portrait { aspect-ratio: 9 / 16; }
.extrait-video { width: 100%; height: 100%; object-fit: contain; display: block; }

/* Le bouton occupe toute la vignette. La vidéo n'est demandée qu'au clic : le
   serveur ne tolère que deux flux par adresse, et une page qui en ouvrirait un
   par extrait se saborderait elle-même. */
.extrait-lire {
  position: absolute; inset: 0; width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  background: transparent; border: 0; cursor: pointer;
  color: #fff; font-size: 15px; font-weight: 600; letter-spacing: .02em;
}
.extrait-lire:hover { background: color-mix(in srgb, var(--accent) 22%, transparent); }
.extrait-lire:focus-visible { outline: 2px solid var(--accent); outline-offset: -3px; }

.extrait-qui { font-weight: 600; font-size: 15px; }
.extrait-titre {
  color: var(--muted); font-size: 13px; line-height: 1.4;
  /* Les titres sont tirés de la transcription et courent parfois sur dix
     lignes : au-delà de trois, la vignette ne se lit plus. */
  display: -webkit-box; -webkit-line-clamp: 3; line-clamp: 3;
  -webkit-box-orient: vertical; overflow: hidden;
}
/* Les commandes tombent en bas de carte, alignées d'une vignette à l'autre
   quel que soit le nombre de lignes du titre. */
.extrait-actions { margin-top: auto; }
.extrait-actions .bouton { font-size: 14px; padding: 6px 10px; }

/* --- Écrans étroits ------------------------------------------------------- */
/*
 * Le bandeau supérieur était le seul vrai obstacle : marque, huit onglets,
 * statut et compte sur une même ligne imposaient 1 211 pixels de large, et donc
 * un défilement horizontal de toute la page sur un téléphone. Il passe ici sur
 * deux rangs, et la barre d'onglets défile pour elle-même.
 */
/*
 * Le bandeau supérieur cède bien avant le téléphone : dès qu'il n'a plus la
 * place d'aligner la marque, les cinq onglets, la recherche, l'état des
 * traitements et le compte, il impose une largeur de page que rien ne
 * rattrape. Il passe donc sur plusieurs rangs dès la tablette, et la barre
 * d'onglets défile pour elle-même.
 */
@media (max-width: 960px) {
  .topbar { flex-wrap: wrap; gap: 10px 14px; padding: 9px 14px; }
  .brand { order: 1; flex: 1; min-width: 0; }
  .account { order: 2; }
  .status { order: 3; flex-basis: 100%; text-align: left; min-width: 0; }
  .status:empty { display: none; }

  .tabs {
    order: 4; flex-basis: 100%; flex-wrap: nowrap;
    overflow-x: auto; scrollbar-width: none;
    /* Les onglets débordent volontairement du cadre : on les fait défiler du
       doigt plutôt que de les empiler sur quatre lignes. */
    margin: 0 -14px; padding: 2px 14px;
    scroll-snap-type: x proximity;
  }
  .tabs::-webkit-scrollbar { display: none; }
  .tabs a { flex: none; scroll-snap-align: start; padding: 8px 12px; }

  .quicksearch { order: 5; flex-basis: 100%; }
  .quicksearch input { flex: 1; width: auto; }
}

@media (max-width: 760px) {
  /* Le bandeau ne colle plus : sur un écran haut de 812 pixels, deux barres
     collantes superposées — celle-ci et le lecteur vidéo — ne laisseraient plus
     de place au texte. On le fait défiler avec la page. */
  .topbar { position: static; }

  main { padding: 14px; }
  /* La même échelle, resserrée : sur 375 px, un titre de 30 px occuperait trois
     lignes avant que le premier chiffre n'apparaisse. */
  h2 { font-size: 23px; }
  h3 { font-size: 21px; margin: 38px 0 14px; padding-top: 18px; }
  .prose h3 { margin-top: 38px; }

  /* Une grille de cartes à 340 px minimum forçait la page à s'élargir. */
  .cards { grid-template-columns: 1fr; }
  .figures { gap: 8px; }
  .figure { flex-basis: calc(50% - 4px); padding: 10px 12px; }
  .figure b { font-size: 21px; }

  .toolbar { gap: 8px; }
  .toolbar select, .toolbar input { max-width: 100%; }
  .inline-form { flex-wrap: wrap; }
  .inline-form input { min-width: 0; flex: 1; }

  /* En colonne unique, un lecteur qui défile hors de l'écran rend la
     transcription muette : on touche une ligne, la vidéo se déplace là où
     personne ne la voit. Il reste donc collé sous le bandeau, en hauteur
     limitée pour laisser le texte respirer. La liste des voix, elle, passe
     dessous : elle sert à nommer, pas à suivre. */
  .player-pane {
    position: sticky; top: 0; z-index: 20;
    background: var(--bg); padding-bottom: 8px; gap: 8px;
  }
  #player { max-height: 34vh; object-fit: contain; }
  .speakers { max-height: none; }
  .transcript { max-height: none; }
  .line { grid-template-columns: 58px 1fr; padding: 7px 4px; }
  /* Les outils d'extrait n'apparaissent qu'au survol, geste absent au doigt. */
  .line .tools { display: flex; position: static; margin-top: 6px; }

  .speaker { flex-wrap: wrap; }
  .speaker select { max-width: 100%; width: 100%; }

  .clipbar { padding: 10px 14px; gap: 10px; }
  .clip-preview { max-width: 100%; }
  .clip-controls { width: 100%; }
  .clip-controls select { flex: 1; }

  .year > summary { padding: 9px 11px; }
  .year .year { margin-left: 8px; }
  .year > .cards { margin-left: 8px; }

  .highlight { grid-template-columns: 1fr; gap: 2px; padding: 9px 4px; }
  .bar-row, .bar-row.presence { grid-template-columns: 1fr 64px 40px; }
  .bar-row.presence .muted { display: none; }
  .prose .chapeau { font-size: 15.5px; padding-left: 12px; }

  dialog { min-width: 0; width: calc(100vw - 32px); padding: 18px; }
}

/*
 * Un graphique de seize exercices réduit à 375 pixels donnerait des colonnes de
 * 23 pixels et des étiquettes illisibles. On lui laisse sa largeur utile et on
 * le fait défiler à l'intérieur de son cadre : mieux vaut un geste horizontal
 * qu'une figure indéchiffrable. Le reste de la page, lui, ne défile pas.
 */
@media (max-width: 860px) {
  .chart-frame { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .chart-frame .chart { min-width: 660px; }
  .tip { position: sticky; top: 8px; right: auto; left: 8px; width: fit-content; }
}

/* Un tableau large ne doit pas élargir la page non plus. */
.table-view { overflow-x: auto; }

/* --- Notification --------------------------------------------------------- */
.toast {
  position: fixed; bottom: 24px; left: 50%; transform: translate(-50%, 200%);
  background: var(--text); color: var(--bg);
  padding: 11px 20px; border-radius: var(--radius);
  box-shadow: var(--shadow); z-index: 100; transition: transform .3s;
  max-width: 80vw;
}
.toast.show { transform: translate(-50%, 0); }
.toast.error { background: var(--err); color: #fff; }
