/* SanctiMaps — feuille de style unique, sans dépendance externe. */

:root {
  --ink: #24201b;
  --ink-soft: #6b6155;
  --paper: #f7f2e8;
  --panel: #fffdf8;
  --line: #ded3c0;
  --sea: #cddbe4;
  --sea-deep: #b4c8d6;
  --land: #ebe3d4;
  --land-hover: #e0d5c0;
  --land-saints: #d8b45c;
  --land-saints-hover: #c9a03f;
  --selected: #b9863a;
  --accent: #8c2230;
  --accent-soft: #f3e2e4;
  --city: #4a5a68;
  --city-soft: #6d7f8e;
  --birth: #a3162a;
  --user: #2f6b4f;
  --pending: #b4741d;
  --shadow: 0 10px 30px rgb(36 32 27 / 18%);
  --radius: 10px;
  --panel-width: 22.5rem;
  --font: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif;
  --font-ui: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

/* Le thème suit le navigateur par défaut ; un choix explicite l'emporte, dans
   les deux sens, d'où les deux blocs qui suivent. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ink: #ece5da;
    --ink-soft: #a79c8c;
    --paper: #161c23;
    --panel: #1d242c;
    --line: #333d48;
    --sea: #101820;
    --sea-deep: #0a0f15;
    --land: #2a333d;
    --land-hover: #35404c;
    --land-saints: #8a6b23;
    --land-saints-hover: #a5811f;
    --selected: #d8b45c;
    --accent: #c9505f;
    --accent-soft: #33222a;
    --city: #9fb2c2;
    --city-soft: #7d8fa0;
    --birth: #e2685c;
    --user: #63b58c;
    --pending: #d9a441;
    --shadow: 0 10px 30px rgb(0 0 0 / 45%);
  }
}

:root[data-theme="dark"] {
  --ink: #ece5da;
  --ink-soft: #a79c8c;
  --paper: #161c23;
  --panel: #1d242c;
  --line: #333d48;
  --sea: #101820;
  --sea-deep: #0a0f15;
  --land: #2a333d;
  --land-hover: #35404c;
  --land-saints: #8a6b23;
  --land-saints-hover: #a5811f;
  --selected: #d8b45c;
  --accent: #c9505f;
  --accent-soft: #33222a;
  --city: #9fb2c2;
  --city-soft: #7d8fa0;
  --birth: #e2685c;
  --user: #63b58c;
  --pending: #d9a441;
  --shadow: 0 10px 30px rgb(0 0 0 / 45%);
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
}

body {
  background: var(--sea-deep);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 15px;
  line-height: 1.5;
  overflow: hidden;
  /* Le bandeau de titre en haut, la carte dessous : une colonne, où la carte
     prend tout ce qui reste. `min-height: 0` sur la carte, sans quoi son
     contenu l'empêcherait de se réduire et la page déborderait. */
  display: flex;
  flex-direction: column;
}

button, input, select, textarea { font: inherit; color: inherit; }

.app {
  display: flex;
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
}

/* ------------------------------------------------- Bandeau de présentation */

/* Ce que la page dit d'elle-même avant que le code s'exécute : le titre, une
   phrase, et les trois portes vers les pages de saints. Il reste mince — la
   carte est le sujet —, mais il est du texte, lisible par un moteur de
   recherche comme par un lecteur sans JavaScript. */
.intro {
  flex: 0 0 auto;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
}

.intro__in {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.15rem 0.9rem;
  padding: 0.5rem 1rem;
}

.intro__title {
  margin: 0;
  font-family: var(--font);
  font-size: 1.15rem;
  line-height: 1.3;
  letter-spacing: 0.01em;
}

.intro__text {
  margin: 0;
  flex: 1 1 20rem;
  min-width: 0;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

.intro__nav {
  display: flex;
  gap: 0.9rem;
  margin-inline-start: auto;
  font-size: 0.85rem;
}

.intro__nav a { color: var(--accent); }

/* La seconde ligne du bandeau : les pays les mieux pourvus, en petit. Un trait
   la sépare de la première pour qu'on lise deux choses et non une phrase
   longue. */
.intro__in--second {
  padding-top: 0;
  padding-bottom: 0.4rem;
  gap: 0.15rem 0.75rem;
}

.intro__sub {
  margin: 0;
  font-family: var(--font);
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ink-soft);
}

.intro__pays {
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem 0.75rem;
  font-size: 0.82rem;
}

.intro__pays a { color: var(--accent); }

/* Les chiffres du corpus, chacun menant à son index : ce que le site couvre,
   dit avant le premier clic. */
.intro__chiffres {
  margin: 0;
  flex-basis: 100%;
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem 1.1rem;
  font-size: 0.82rem;
  color: var(--ink-soft);
}

.intro__chiffres a { color: inherit; text-decoration: none; }
.intro__chiffres a:hover { color: var(--accent); }
.intro__chiffres b { color: var(--ink); font-weight: 700; }

/* Sur un téléphone, la phrase passe sous le titre et la carte garde sa
   place : trois lignes de bandeau mangeraient la moitié de l'écran. */
@media (max-width: 40rem) {
  .intro__in { padding: 0.4rem 0.75rem; }
  .intro__title { font-size: 1rem; }
  .intro__text { font-size: 0.8rem; flex-basis: 100%; }
  .intro__nav { margin-inline-start: 0; flex-basis: 100%; }
  /* Sur un téléphone, la carte prime : la seconde ligne du bandeau lui
     prendrait le quart de l'écran pour des liens que « Par pays » donne déjà
     à une touche de là. */
  .intro__in--second { display: none; }
}

/* --------------------------------------------------------------- La carte */

.stage {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
}

.map-host {
  position: absolute;
  inset: 0;
  touch-action: none;
}

.map {
  width: 100%;
  height: 100%;
  display: block;
  cursor: grab;
}

.map-host.is-picking .map { cursor: crosshair; }
.map:active { cursor: grabbing; }

/* Le fond du monde se distingue légèrement du hors-carte. */
.sheet { fill: var(--sea); }

.country {
  fill: var(--land);
  stroke: var(--sea);
  stroke-width: 0.6;
  transition: fill 180ms ease, opacity 180ms ease;
}

.country.has-saints { fill: var(--land-saints); }
.country:hover { fill: var(--land-hover); }
.country.has-saints:hover { fill: var(--land-saints-hover); }

.country.is-muted {
  opacity: 0.42;
  pointer-events: auto;
}

/* Une fois entré dans un pays, les voisins redeviennent de la terre pleine.
   Délavés, ils se confondaient avec la mer : la France flottait comme une
   découpe posée sur une table, au lieu de tenir dans un continent. On garde
   la teinte neutre du sol — la couleur qui compte les saints reste au pays
   ouvert, et c'est elle qui doit ressortir.

   Quatre classes dans le sélecteur, contre deux à « .country.has-saints » :
   c'est ce qu'il faut pour l'emporter sur la teinte thématique. */
.map-host[data-mode="country"] .country.is-muted {
  opacity: 1;
  fill: var(--land);
}

.map-host[data-mode="country"] .country.is-muted:hover { fill: var(--land-hover); }

/* Le pays ouvert garde la couleur qui dit s'il compte des saints : seul son
   contour s'épaissit. Lui donner une teinte propre effacerait, au moment même
   où on l'ouvre, l'information que la carte venait de donner. */
.country.is-selected,
.country-detail {
  stroke: var(--ink);
  stroke-width: 1.3;
  opacity: 1;
}

.country-detail {
  pointer-events: auto;
  fill: var(--land);
}

.country-detail.has-saints { fill: var(--land-saints); }

/* ------------------------------------------- Étiquettes et points, non zoomés */

.overlay { pointer-events: none; }

.label__text {
  font-family: var(--font);
  fill: var(--ink);
  paint-order: stroke;
  stroke: var(--paper);
  stroke-width: 3.5;
  stroke-linejoin: round;
}

.label--country .label__text { font-size: 0.8rem; }
.label--country.has-saints .label__text { font-weight: 700; }

.label__count {
  font-size: 0.68rem;
  fill: var(--accent);
  font-family: var(--font-ui);
  paint-order: stroke;
  stroke: var(--paper);
  stroke-width: 3;
}

.label.is-crowded { opacity: 0; }

.marker { pointer-events: auto; cursor: pointer; }

.marker__label {
  font-size: 0.7rem;
  fill: var(--ink);
  transform: translateY(1.55em);
  paint-order: stroke;
  stroke: var(--paper);
  stroke-width: 3;
  stroke-linejoin: round;
  transition: opacity 150ms ease;
}

/* Le nom ne se clique pas : posé sous son repère, il déborde volontiers sur
   le médaillon du voisin, et happait alors le clic destiné à celui-ci —
   on visait un groupe de six et l'on ouvrait un saint isolé. Seule la croix
   répond, ce qui fait une cible franche de vingt et un pixels. */
.marker__label { pointer-events: none; }

.marker.is-crowded .marker__label { opacity: 0; }
.marker:hover .marker__label,
.marker:focus-visible .marker__label { opacity: 1; }

.marker--city { pointer-events: none; }
.marker--city .marker__dot { fill: var(--city); }
.marker--city .marker__label { fill: var(--city); font-style: italic; }

/* Le rang de la localité se lit à la taille et à la teinte du nom, comme sur
   une carte d'état-major : une préfecture ne s'écrit pas comme un hameau.

   Surtout pas à l'opacité : « .marker--city.marker--village .marker__label »
   pèse exactement autant que « .marker.is-crowded .marker__label », et venant
   après elle l'emportait — les villages et les hameaux ne se masquaient donc
   jamais quand ils se gênaient, et la carte se couvrait de noms superposés
   dès que le zoom les faisait apparaître. L'opacité d'une étiquette ne se
   règle plus qu'à un seul endroit : l'encombrement. */
.marker--city.marker--town .marker__label { font-size: 0.64rem; }
.marker--city.marker--village .marker__label { font-size: 0.58rem; fill: var(--city-soft); }
.marker--city.marker--hamlet .marker__label { font-size: 0.54rem; fill: var(--city-soft); }
.marker--city.marker--village .marker__dot,
.marker--city.marker--hamlet .marker__dot { fill: var(--city-soft); }

/* Le lieu de naissance porte une croix, non un point : elle se reconnaît d'un
   coup d'œil parmi les repères d'une carte, et dit ce qu'elle marque sans
   recourir à la légende. Le disque clair la détache d'un fond quelconque —
   ochre au niveau du pays, photographie de rues au zoom rapproché. */
.marker--saint .marker__ring {
  fill: var(--panel);
  stroke: var(--line);
  stroke-width: 1;
}

.marker--saint .marker__badge {
  fill: var(--birth);
  transition: fill 150ms ease;
}

.marker--saint .marker__cross { fill: var(--panel); }

.marker--saint .marker__halo {
  fill: var(--birth);
  opacity: 0;
  transition: opacity 150ms ease;
}

.marker--saint .marker__label { transform: translateY(2.5em); font-weight: 600; }

.marker--saint.is-user .marker__badge { fill: var(--user); }
.marker--saint.is-user .marker__halo { fill: var(--user); }

.marker--saint:hover .marker__halo,
.marker--saint.is-active .marker__halo { opacity: 0.3; }
.marker--saint.is-active .marker__ring { stroke: var(--ink); stroke-width: 1.8; }
.marker--saint.is-active .marker__label { opacity: 1; font-weight: 700; }
.marker:focus-visible { outline: none; }
.marker:focus-visible .marker__halo { opacity: 0.45; }

/* ------------------------------------------------------ Bandeau et légende */

.topbar {
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  padding: 0.9rem 1rem 1.4rem;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 1rem;
  background: linear-gradient(to bottom, rgb(0 0 0 / 12%), transparent);
  pointer-events: none;
}

.topbar > * { pointer-events: auto; }

.trail {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.25rem 0.5rem;
  box-shadow: var(--shadow);
}

.crumb {
  border: 0;
  background: none;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  cursor: pointer;
  font-family: var(--font);
  font-size: 0.95rem;
}

.crumb:hover { background: var(--accent-soft); }
.crumb.is-current { font-weight: 700; cursor: default; }
.crumb__sep { color: var(--ink-soft); }

.hint {
  margin: 0;
  font-size: 0.85rem;
  color: var(--panel);
  background: rgb(36 32 27 / 72%);
  padding: 0.2rem 0.7rem;
  border-radius: 999px;
}

/* Cartouche de couverture : combien de saints, dans combien de pays. */
.tally {
  margin: 0;
  font-size: 0.8rem;
  color: var(--panel);
  background: rgb(36 32 27 / 82%);
  padding: 0.2rem 0.7rem;
  border-radius: 999px;
  font-variant-numeric: tabular-nums;
}

.continents {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-inline-start: auto;
}

/* ------------------------------------------- Choix parmi plusieurs saints */

/* Cinq saints sont nés à Alexandrie, cinq à Londres : leurs croix se posent au
   même endroit. Une pastille dit combien le repère en cache, et le clic ouvre
   cette liste plutôt que d'en tirer un au hasard. */
.marker__countdot {
  fill: var(--ink);
  stroke: var(--panel);
  stroke-width: 1.5;
}

.marker__count {
  fill: var(--panel);
  font-family: var(--font-ui);
  font-size: 8.5px;
  font-weight: 700;
  transform: translate(9px, -6.2px);
}

.marker--group .marker__label { font-style: italic; }

.picker {
  position: absolute;
  z-index: 40;
  min-width: 12rem;
  max-width: min(18rem, calc(100% - 1rem));
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 0.4rem;
  display: grid;
  gap: 0.1rem;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 120ms ease, transform 120ms ease;
}

.picker.is-open { opacity: 1; transform: none; }

.picker__head {
  margin: 0.1rem 0.4rem 0.3rem;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
}

.picker__item {
  display: grid;
  gap: 0.05rem;
  text-align: start;
  width: 100%;
  border: 0;
  background: none;
  border-radius: 6px;
  padding: 0.4rem 0.45rem;
  cursor: pointer;
}

.picker__item:hover { background: var(--accent-soft); }
.picker__item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.picker__name { font-family: var(--font); font-size: 0.95rem; }
.picker__meta { font-size: 0.74rem; color: var(--ink-soft); }

/* ------------------------------------------------------ Fond de tuiles */

/* Chaque tuile paraît en fondu : sans cela, la carte clignoterait à chaque
   cran de zoom, les images n'arrivant pas toutes en même temps. */
.tile {
  opacity: 0;
  transition: opacity 240ms ease;
}

.tile.is-loaded { opacity: 1; }

/* Les tuiles du niveau précédent restent dessous le temps que les nouvelles
   arrivent : mieux vaut un fond un peu flou qu'un trou blanc. */
.tile.is-stale { opacity: 0.75; }

/* Sous les tuiles, l'aplat du pays s'efface : il cacherait les rues. Seul son
   contour demeure, pour qu'on sache toujours où l'on est. La couleur qui dit
   « ce pays compte des saints » a déjà été lue aux échelles précédentes. */
.map-host.has-tiles .country-detail { fill: none; }
.map-host.has-tiles .country { opacity: 0; }

/* Les tuiles sont claires quel que soit le thème choisi : en thème sombre, le
   contre-lettrage des noms et le trait de frontière y disparaîtraient, l'un
   étant sombre sur clair et l'autre clair sur clair. Sur un fond qu'on ne
   maîtrise pas, on fixe les deux. */
:root[data-tiles="on"] .marker--saint .marker__label {
  fill: #1c1c1c;
  stroke: #fff;
}

:root[data-tiles="on"] .country-detail { stroke: #33302b; }

/* Rien de tout cela ne se clique. Les tuiles happeraient chaque tapotement et
   le prendraient pour un clic « à côté » ; les pays voisins, devenus
   invisibles, seraient des cibles qu'on ne voit pas. On change de pays en
   remontant au continent, et seules les croix des saints répondent. */
.tile,
.map-host.has-tiles .country,
.map-host.has-tiles .country-detail { pointer-events: none; }

.attribution {
  position: absolute;
  inset-block-end: 4.3rem;
  inset-inline-start: 1rem;
  z-index: 20;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.15rem 0.5rem;
  font-size: 0.68rem;
  color: var(--ink-soft);
  text-decoration: none;
  box-shadow: var(--shadow);
}

.attribution:hover { color: var(--accent); }
.attribution[hidden] { display: none; }

/* ------------------------------------------------- Commandes de zoom */

/* Sur le flanc de la carte, à hauteur de main, et seulement là où le zoom
   existe : une fois un pays ouvert. */
.zoom {
  position: absolute;
  inset-block-start: 50%;
  inset-inline-end: 1rem;
  transform: translateY(-50%);
  z-index: 20;
  display: grid;
  gap: 0.35rem;
}

/* `display: grid` l'emporte sur la feuille du navigateur : sans cette règle,
   l'attribut `hidden` ne cacherait rien et le zoom s'afficherait au monde,
   là où il n'existe pas. */
.zoom[hidden],
.scale[hidden] { display: none; }

.zoom__btn {
  width: 2.5rem;
  height: 2.5rem;
  font-size: 1.25rem;
  line-height: 1;
}

.zoom__fit { font-size: 1rem; }

.zoom__btn:disabled {
  opacity: 0.4;
  cursor: default;
}

.zoom__btn:disabled:hover { background: var(--panel); }

/* Barre d'échelle : elle dit à quelle distance on regarde, ce qu'un niveau
   de zoom en chiffres ne dirait pas. */
.scale {
  position: absolute;
  inset-block-end: 1rem;
  inset-inline-start: 1rem;
  z-index: 20;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 0.3rem 0.55rem 0.4rem;
  display: grid;
  justify-items: start;
  gap: 0.2rem;
}

.scale__text {
  font-size: 0.7rem;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}

.scale__rule {
  height: 0.4rem;
  border: 1px solid var(--ink-soft);
  border-block-start: 0;
  transition: width 120ms ease;
}

.legend {
  position: absolute;
  inset-block-end: 1rem;
  inset-inline-end: 1rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.6rem 0.8rem;
  box-shadow: var(--shadow);
  font-size: 0.78rem;
  max-width: 14rem;
}

.legend__title {
  margin: 0 0 0.35rem;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ink-soft);
}

.legend__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.25rem;
}

.legend__list li {
  display: flex;
  align-items: center;
  gap: 0.45rem;
}

:root[data-tiles="on"] .legend__city { display: none; }

.swatch {
  width: 0.85rem;
  height: 0.85rem;
  border-radius: 3px;
  border: 1px solid var(--line);
  flex: none;
}

.swatch--saints { background: var(--land-saints); }
.swatch--plain { background: var(--land); }
.swatch--city { background: var(--city); border-radius: 50%; width: 0.55rem; height: 0.55rem; margin: 0 0.15rem; }
.swatch--birth {
  background: var(--birth);
  border-radius: 4px;
  position: relative;
}

/* La légende montre le repère tel qu'il est sur la carte : une croix. */
.swatch--birth::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--panel);
  clip-path: polygon(42% 8%, 58% 8%, 58% 34%, 84% 34%, 84% 50%, 58% 50%, 58% 92%, 42% 92%, 42% 50%, 16% 50%, 16% 34%, 42% 34%);
}

/* -------------------------------------------------------- Panneau latéral */

.panel {
  order: -1;
  flex: 0 0 var(--panel-width);
  width: var(--panel-width);
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border-inline-end: 1px solid var(--line);
  box-shadow: var(--shadow);
  z-index: 20;
  transition: margin-inline-start 260ms ease;
}

.panel:not(.is-open) {
  margin-inline-start: calc(-1 * var(--panel-width));
  visibility: hidden;
}

.panel__header {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  padding: 1rem 1rem 0.5rem;
}

.panel__title {
  margin: 0;
  font-family: var(--font);
  font-size: 1.35rem;
  letter-spacing: 0.02em;
}

.panel__tagline {
  margin: 0.1rem 0 0;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.panel__close { margin-inline-start: auto; }

/* --------------------------------------------------- Sommaire du tiroir */

/* Le fil de retour : d'où l'on vient, et où l'on est. Absent au sommaire. */
.panel__crumb {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0.35rem 1rem 0.5rem;
  border-bottom: 1px solid var(--line);
}

.panel__crumb:empty { display: none; }

.panel__back {
  border: 0;
  background: none;
  padding: 0.2rem 0.4rem 0.2rem 0;
  cursor: pointer;
  color: var(--ink-soft);
  display: flex;
  align-items: baseline;
  gap: 0.3rem;
  font-size: 0.85rem;
}

.panel__back:hover { color: var(--accent); }

.panel__where {
  font-family: var(--font);
  font-weight: 700;
  font-size: 1.05rem;
}

.menu {
  display: grid;
  gap: 0.2rem;
  margin: -0.4rem -0.4rem 0;
}

/* Une ligne pleine largeur, cliquable de bout en bout : sur un téléphone, le
   pouce ne vise pas un mot de huit lettres. */
.menu__item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  width: 100%;
  padding: 0.7rem 0.5rem;
  border: 0;
  border-radius: var(--radius);
  background: none;
  cursor: pointer;
  text-align: start;
}

.menu__item:hover { background: var(--accent-soft); }
.menu__item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.menu__glyph {
  flex: 0 0 auto;
  width: 1.9rem;
  height: 1.9rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--paper);
  border: 1px solid var(--line);
  color: var(--ink-soft);
  font-size: 0.95rem;
}

.menu__label {
  flex: 1 1 auto;
  min-width: 0;
  display: grid;
}

.menu__name {
  font-family: var(--font);
  font-size: 1.02rem;
}

.menu__hint {
  font-size: 0.76rem;
  color: var(--ink-soft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.menu__chevron { color: var(--ink-soft); }

/* Le retour à la carte n'est pas une partie de plus : il se détache. */
.menu__item--back {
  margin-top: 0.4rem;
  border-top: 1px solid var(--line);
  border-radius: 0;
  padding-top: 0.8rem;
}

.menu__item--back .menu__glyph { background: none; border-color: transparent; }
.menu__item--back .menu__name { color: var(--ink-soft); }

/* Langue et thème vivent maintenant dans leur propre partie. */
.settings { display: grid; gap: 0.9rem; }

.panel__body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 0.9rem 1rem 1.5rem;
}

.panel-toggle {
  position: absolute;
  inset-block-start: 0.9rem;
  inset-inline-start: 0.9rem;
  z-index: 30;
}

.panel-toggle.is-hidden { display: none; }

.icon-btn {
  border: 1px solid var(--line);
  background: var(--panel);
  border-radius: var(--radius);
  width: 2.2rem;
  height: 2.2rem;
  display: grid;
  place-items: center;
  cursor: pointer;
  font-size: 1.1rem;
  box-shadow: var(--shadow);
}

.icon-btn:hover { background: var(--accent-soft); }

/* ------------------------------------------------------------ Formulaires */

.field {
  display: block;
  margin-bottom: 0.7rem;
}

.field--inline {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0;
}

.field--inline .control { flex: 1 1 auto; }

.field__label {
  display: block;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
  margin-bottom: 0.2rem;
}

.field__hint {
  display: block;
  font-size: 0.75rem;
  color: var(--ink-soft);
  margin-top: 0.15rem;
}

.control {
  width: 100%;
  padding: 0.42rem 0.55rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--paper);
}

.control:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.control--area { resize: vertical; }

.filters__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.6rem;
  align-items: end;
}

.filters__reset { margin-bottom: 0.7rem; }

.group {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.6rem 0.7rem;
  margin: 0 0 0.7rem;
}

.group__legend {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
  padding: 0 0.3rem;
}

.checks {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
  gap: 0.15rem 0.5rem;
  max-height: 9rem;
  overflow-y: auto;
}

.check {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.82rem;
}

.btn {
  border: 1px solid var(--line);
  background: var(--paper);
  border-radius: var(--radius);
  padding: 0.42rem 0.8rem;
  cursor: pointer;
}

.btn:hover { background: var(--accent-soft); }

.btn--primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  width: 100%;
  font-weight: 600;
}

/* `.btn:hover` porte une pseudo-classe : sans ce rappel du fond, il l'emporte
   en spécificité et repeint le bouton principal en clair, texte blanc compris. */
.btn--primary:hover {
  background: var(--accent);
  filter: brightness(1.1);
}
.btn--ghost { background: none; }
.btn--ghost.is-active { border-color: var(--accent); color: var(--accent); }
.btn--danger { border-color: var(--accent); color: var(--accent); background: none; }

.chip {
  display: inline-block;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.1rem 0.6rem;
  font-size: 0.75rem;
  background: var(--paper);
}

.chip--action {
  cursor: pointer;
  box-shadow: var(--shadow);
  background: var(--panel);
}

.chip--action:hover { background: var(--accent-soft); }

.chip--action.is-active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.chips {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  padding: 0;
  margin: 0.5rem 0;
}

.notice {
  border-radius: 8px;
  padding: 0.4rem 0.6rem;
  font-size: 0.85rem;
  margin: 0 0 0.7rem;
}

.notice--error { background: var(--accent-soft); color: var(--accent); }
.notice--ok { background: color-mix(in srgb, var(--user) 18%, transparent); }
.notice--mine { background: color-mix(in srgb, var(--user) 18%, transparent); }

/* --------------------------------------------------------------- Résultats */

.results__summary {
  margin: 0.4rem 0 0.5rem;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

/* L'export suit la recherche : il porte sur la liste affichée, et se tait
   quand elle est vide. */
.btn--calendar {
  width: 100%;
  margin-bottom: 0.6rem;
  font-size: 0.8rem;
}

.btn--calendar:disabled {
  opacity: 0.45;
  cursor: default;
}

.results {
  display: grid;
  gap: 0.35rem;
}

.result {
  display: grid;
  gap: 0.1rem;
  text-align: start;
  border: 1px solid transparent;
  border-bottom-color: var(--line);
  background: none;
  padding: 0.5rem 0.4rem;
  border-radius: 8px;
  cursor: pointer;
}

.result:hover { background: var(--accent-soft); border-color: var(--line); }

.result__name {
  font-family: var(--font);
  font-size: 1.02rem;
}

.result--user .result__name::after {
  content: " ●";
  color: var(--user);
  font-size: 0.7em;
}

.result__meta, .result__dates {
  font-size: 0.78rem;
  color: var(--ink-soft);
}

.result__dates { display: flex; gap: 0.6rem; }
.result__feast { color: var(--accent); }
.results__empty { color: var(--ink-soft); font-size: 0.88rem; }

/* ------------------------------------------------------------ Fiche saint */

.detail__back { margin-bottom: 0.6rem; }

.detail__name {
  font-family: var(--font);
  font-size: 1.5rem;
  margin: 0 0 0.2rem;
}

.detail__aka {
  margin: 0 0 0.5rem;
  font-size: 0.78rem;
  color: var(--ink-soft);
}

.detail__desc {
  font-family: var(--font);
  font-size: 1rem;
  margin: 0.6rem 0;
}

/* La notice tient en une phrase ; la biographie est un texte suivi, qu'on lit
   plutôt qu'on ne parcourt : elle mérite des lignes plus aérées. */
.detail__bio {
  margin: 0.6rem 0;
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--ink);
  white-space: pre-line;
}

.sheet {
  display: grid;
  gap: 0.25rem;
  margin: 0.8rem 0;
}

.sheet__row {
  display: grid;
  grid-template-columns: 8rem 1fr;
  gap: 0.5rem;
  border-bottom: 1px dotted var(--line);
  padding-bottom: 0.2rem;
}

.sheet__key {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
}

.sheet__value { margin: 0; }

.detail__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 0.8rem;
}

/* ------------------------------------------------------ Chargement, divers */

.loader {
  position: fixed;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 0.6rem;
  background: var(--paper);
  color: var(--ink);
  z-index: 100;
}

.loader__mark {
  font-size: 2.4rem;
  color: var(--accent);
  animation: pulse 1.6s ease-in-out infinite;
}

.loader.is-error .loader__mark { animation: none; }
.loader__text { margin: 0; }

@keyframes pulse {
  0%, 100% { opacity: 0.35; }
  50% { opacity: 1; }
}

.noscript {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  margin: 0;
  padding: 1rem;
  background: var(--accent);
  color: #fff;
  text-align: center;
  z-index: 200;
}

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

/* ------------------------------------------------------------ Petits écrans */

@media (max-width: 899px) {
  :root { --panel-width: min(90vw, 22.5rem); }

  .panel {
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    height: 100%;
  }

  .panel:not(.is-open) { margin-inline-start: 0; transform: translateX(-100%); }
  .panel:not(.is-open):dir(rtl) { transform: translateX(100%); }

  .topbar { padding-inline-start: 3.6rem; }
  .legend { display: none; }

  /* Sur un téléphone, les boutons de zoom descendent au coin, à portée du
     pouce, et l'échelle passe au-dessus d'eux plutôt que sous le panneau. */
  .zoom {
    inset-block-start: auto;
    inset-block-end: 1rem;
    transform: none;
  }

  /* `display: grid` l'emporte sur la feuille du navigateur : sans cette règle,
   l'attribut `hidden` ne cacherait rien et le zoom s'afficherait au monde,
   là où il n'existe pas. */
.zoom[hidden],
.scale[hidden] { display: none; }

.zoom__btn { width: 2.9rem; height: 2.9rem; }
  .scale { inset-block-end: 0.6rem; }

  /* Les continents défilent sur une seule ligne plutôt que d'empiler
     trois rangées de puces au-dessus de la carte. */
  .continents {
    margin-inline-start: 0;
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    max-width: 100%;
    padding-bottom: 0.2rem;
  }

  .continents::-webkit-scrollbar { display: none; }
  .chip--action { white-space: nowrap; }

  .label--country .label__text { font-size: 0.72rem; }
}

/* ------------------------------------------------- Recherche et jetons */

.search__bar { margin-bottom: 0.35rem; }
.search__input { font-size: 1rem; }

.search__help {
  margin: 0 0 0.5rem;
  font-size: 0.78rem;
  color: var(--ink-soft);
}

.tokens {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
}

.tokens:not(:empty) { margin-bottom: 0.4rem; }

.chip--token {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  cursor: pointer;
  border-color: var(--accent);
  color: var(--accent);
}

.chip--token:hover { background: var(--accent-soft); }
.chip__x { font-weight: 700; }
.chip--country { border-color: var(--selected); color: var(--selected); }

/* Quel service répond : lu d'un coup d'œil avant de lancer un appel. */
.chip--provider {
  display: block;
  margin: 0.5rem 0;
  font-size: 0.72rem;
  background: var(--accent-soft);
  border-color: var(--accent);
}

.chip--pending { border-color: var(--pending); color: var(--pending); }
.chip--rejected { border-color: var(--accent); color: var(--accent); }
/* Le lieu retenu parmi les homonymes se distingue du premier coup d'œil. */
.result.is-active {
  border-color: var(--accent);
  background: var(--accent-soft);
}

/* La provenance d'une fiche tirée d'Internet, et sa licence. */
.expert__sources a,
.detail__sources a {
  color: var(--accent);
  text-underline-offset: 2px;
}

.detail__sources {
  font-size: 0.8rem;
  color: var(--ink-soft);
  margin: 0.6rem 0 0;
}

/* L'état des lieux ferme l'atelier : il dit où porter l'effort suivant. */
.expert__survey {
  margin-top: 1rem;
  padding-top: 0.7rem;
  border-top: 1px solid var(--line);
}

.result--draft { border-inline-start: 3px solid var(--pending); }

/* Réglages et compte partagent un écran : un filet sépare les blocs, faute de
   quoi la liste des rôles semble appartenir au réglage du fond de carte. */
.settings-view > * + * {
  margin-top: 1.2rem;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
}

.reminder .check { margin-top: 0.6rem; }
.reminder .btn--primary { margin-top: 0.4rem; }

/* ------------------------------------------- Saint du jour */

/* La date est le sujet de la page : elle se lit avant tout le reste, et la
   majuscule initiale vient d'ici, le navigateur rendant « samedi 30 août ». */
.daily__date {
  font-family: var(--font);
  font-size: 1.35rem;
  line-height: 1.2;
  margin: 0.1rem 0 0.6rem;
  color: var(--ink);
}

.daily__date::first-letter { text-transform: uppercase; }

.daily__nav {
  display: flex;
  gap: 0.4rem;
  margin-bottom: 0.8rem;
}

.daily__nav .btn { flex: 1; }

/* La couverture du calendrier ferme la page : elle dit où en est le corpus. */
.daily__coverage {
  margin-top: 1rem;
  padding-top: 0.7rem;
  border-top: 1px solid var(--line);
}

/* Un jour sans fête ne doit pas être un cul-de-sac : la sortie est visible. */
.daily__next {
  margin-top: 0.8rem;
  padding-top: 0.7rem;
  border-top: 1px solid var(--line);
  display: grid;
  gap: 0.5rem;
  justify-items: start;
}

/* ------------------------------------------- Modération et assistant */

.panel__section {
  font-family: var(--font);
  font-size: 1.15rem;
  margin: 0.2rem 0 0.4rem;
}

.panel__subsection {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
  margin: 0.9rem 0 0.3rem;
}

.review {
  display: grid;
  gap: 0.2rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.5rem 0.6rem;
}

.review--bad { border-style: dashed; opacity: 0.85; }

.review__open {
  display: grid;
  gap: 0.1rem;
  text-align: start;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

.review__open:hover .result__name { text-decoration: underline; }

.review__actions {
  display: flex;
  gap: 0.35rem;
  margin-top: 0.35rem;
}

.checks-list {
  list-style: none;
  margin: 0.3rem 0 0;
  padding: 0;
  display: grid;
  gap: 0.15rem;
}

.check { font-size: 0.76rem; }
.check--ok { color: var(--user); }
.check--bad { color: var(--accent); }

.tab__badge {
  display: inline-block;
  margin-inline-start: 0.3rem;
  min-width: 1.2em;
  padding: 0 0.3em;
  border-radius: 999px;
  background: var(--accent);
  color: #fff;
  font-size: 0.7rem;
  text-align: center;
}

.stats {
  list-style: none;
  display: flex;
  gap: 0.6rem;
  margin: 0 0 0.5rem;
  padding: 0;
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
}

/* --------------------------------------------------------------- Compte */

.account__current {
  margin: 0.4rem 0;
  font-weight: 600;
}

.rights {
  list-style: none;
  margin: 0 0 0.7rem;
  padding: 0;
  display: grid;
  gap: 0.25rem;
  font-size: 0.82rem;
  color: var(--ink-soft);
}

.btn--go {
  border-color: var(--user);
  color: var(--user);
  background: none;
}

.notice--pending { background: color-mix(in srgb, var(--pending) 20%, transparent); }
.notice--rejected { background: var(--accent-soft); color: var(--accent); }

/* Les villages n'apparaissent qu'une fois la carte fortement agrandie. */
.marker--small .marker__label { font-size: 0.62rem; opacity: 0.9; }

/* ------------------------------------------------ Sources de l'assistant */

.segmented {
  display: flex;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  margin: 0 0 0.7rem;
}

.segmented__btn {
  flex: 1 1 0;
  border: 0;
  background: none;
  padding: 0.4rem 0.6rem;
  cursor: pointer;
  color: var(--ink-soft);
}

.segmented__btn + .segmented__btn { border-inline-start: 1px solid var(--line); }
.segmented__btn:hover { background: var(--accent-soft); }

.segmented__btn.is-active {
  background: var(--accent);
  color: #fff;
  font-weight: 600;
}

.review__desc {
  margin: 0.25rem 0;
  font-family: var(--font);
  font-size: 0.9rem;
}

/* Certitude que le modèle s'attribue lui-même : une indication, pas une garantie. */
.check--high { color: var(--user); }
.check--medium { color: var(--pending); }
.check--low { color: var(--accent); }

.btn[disabled] { opacity: 0.5; cursor: default; }
