/* MISE-EN-PAGE — colonnes, barre laterale, onglets, selecteur de scenario
 *
 * Tranche 02 de public/styles.css, decoupe le 2026-08-24. Les fichiers sont
 * NUMEROTES parce que l'ordre de chargement compte : une regle plus bas l'emporte sur une
 * regle de meme portee plus haut. Ne pas reordonner les <link> de index.html.
 */
/* Pas de `padding-bottom` ici : `.app-shell` fait deja `min-height: 100vh`, donc la moindre
   marge basse portait la page a `100vh + marge` et le navigateur affichait une barre de
   defilement verticale sur TOUS les ecrans, meme vides (constate le 2026-08-26). Le contenu
   a deja sa propre respiration par `.app-content`. */
body {
  margin: 0;
  background: var(--bg); color: var(--text);
  transition: background-color 0.15s ease, color 0.15s ease;
}
.app-shell { display: flex; align-items: stretch; min-height: 100vh; }
/* `display: flex` d'auteur l'emporterait sur le `[hidden] { display: none }` du navigateur
   (même piège que `.kpi-row[hidden]`) : sans cette garde, masquer `#app-shell` pendant l'écran
   de connexion (socle/auth.js) ne masquerait rien. */
.app-shell[hidden] { display: none !important; }

/* La marge de gauche prend la couleur de la page et n a plus de trait de separation : les
   onglets flottent sur le meme fond que le contenu, la seule chose qui les distingue est la
   pastille de l onglet actif. */
.sidebar {
  flex: 0 0 var(--sidebar-width);
  position: sticky; top: 0; align-self: flex-start; height: 100vh; overflow-y: auto;
  background: var(--barre-laterale-fond); border-right: 1px solid var(--border);
  display: flex; flex-direction: column;
  padding: var(--space-4) var(--space-3);
}
.sidebar-brand { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2) var(--space-2) var(--space-4); }
.sidebar-logo {
  width: 2.1rem; height: 2.1rem; flex: 0 0 auto; object-fit: contain;
}
/* Le vrai nom du produit (2026-09-22, identite de la landing page) : Newsreader + degrade
   or -> vert en `background-clip: text`, exactement le traitement du logo de la landing.
   `.topbar-titre` (02, plus bas) n'est PAS ce logo : il rejoue le titre de la PAGE active
   (`onglets.js`), qui reste en Newsreader uni pour la meme raison que `.page-head h1`. */
.sidebar-title {
  font-family: var(--font-serif); font-size: 1.2rem; font-weight: 500; letter-spacing: -0.005em;
  background: linear-gradient(100deg, var(--gold), var(--accent));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}

/* Le sélecteur de scénario vit dans la barre du haut (2026-09-05), à côté du titre de
   l'onglet actif — plus dans la sidebar : c'est là qu'on regarde en premier pour savoir
   « dans quel scénario suis-je ». Ramené le 2026-08-26 à ce qui ne fait pas doublon : la
   liste, une icône de réglages, les pastilles, une ligne d'état qui n'apparaît QUE pendant
   une bascule ou en cas d'échec de chargement. `.scenario-picker-label` reste dans le DOM
   pour le lecteur d'écran (`<label for="scenario-select">`) mais ne s'affiche pas : la
   position dans la barre du haut dit déjà « c'est le scénario », l'écrire une deuxième fois
   ferait doublon avec le nom même du panneau. */
/* Une seule ligne, alignée sur le titre et la cloche (2026-10-13) : la pastille passe à gauche de
   la liste au lieu d'en dessous, où elle faisait monter la liste plus haut que le titre. La ligne
   d'état, rare, se pose sous la liste sans la déplacer. */
.scenario-picker { position: relative; display: flex; align-items: center; gap: 0.5rem; margin-left: auto; }
.scenario-picker-badges { order: -1; }
.scenario-picker-label {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
/* La liste et l'icône de réglages sur une seule ligne, à la MÊME hauteur.
   `height: 2rem` sur les deux, et pas seulement `align-items: center` : la liste n'avait
   aucun habillage (elle restait au dessin brut du navigateur, 19 px de haut) tandis que
   l'icône en faisait 30, ce qui donnait deux boîtes visiblement inégales côte à côte.
   Une hauteur explicite les rend identiques quelle que soit la police du système.
   `min-width: 0` sur la liste : sans lui, un nom de scénario long élargit la barre du haut
   au lieu d'être tronqué. */
.scenario-picker-row { display: flex; align-items: center; gap: 0.35rem; }
.scenario-picker-row select {
  flex: 1 1 auto; min-width: 0; max-width: 12rem; height: 2rem;
  color: var(--text-strong); padding: 0 0.4rem; font-size: 0.82rem;
}
.scenario-picker-reglages {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem; padding: 0;
  background: transparent; border: 1px solid var(--border); border-radius: var(--radius-btn);
  color: var(--muted); cursor: pointer;
  transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease;
}
.scenario-picker-reglages:hover { color: var(--text-strong); background: var(--bg-hover); border-color: var(--border-strong); }
.scenario-picker-reglages:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
/* Ligne d'ÉTAT, pas d'identité : « Activation… » pendant la bascule (qui refait un
   aller-retour serveur complet, d'où l'accusé de réception) ou le message d'échec de
   chargement. Vide le reste du temps, et alors invisible — sinon elle laisserait un blanc
   permanent sous la liste. */
.scenario-picker-actif {
  position: absolute; top: 100%; right: 0;
  margin: 0.1rem 0 0; font-size: 0.72rem; color: var(--muted); text-align: right;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.scenario-picker-actif:empty { display: none; }
/* Pastilles « trajectoire réelle » / « isolé » sous le sélecteur — visibles sans ouvrir
   la fenêtre de gestion, pour qu'on sache toujours quel scénario alimente la file « À
   confirmer » sans avoir à s'en souvenir. */
.scenario-picker-badges { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 0.3rem; margin: 0; }
.scenario-badge {
  font-size: 0.65rem; font-weight: 600; letter-spacing: 0.02em;
  padding: 0.12rem 0.5rem; border-radius: 999px; white-space: nowrap;
}
.scenario-badge.is-reference { color: var(--gold-text, var(--text-strong)); background: var(--gold-soft); }
.scenario-badge.is-isole { color: var(--muted); background: var(--bg-inset); }
/* --- L'INDICATEUR D'ENREGISTREMENT (socle/indicateur-enregistrement.js) ------------
   DANS LA LIGNE, a cote de ce qu'on vient de modifier : le bandeau flottant du bas est
   reserve aux erreurs qu'il faut lire puis fermer.

   SANS `data-etat`, IL N'EXISTE PAS. Les quatre <span> qu'il remplace occupaient leur place
   en permanence pour un message de trois secondes, et `.params-autosave` allait jusqu'a
   s'imposer un `min-height: 1.2em` : une bande vide reservee au vide. */
.enregistrement { display: none; }
.enregistrement[data-etat] {
  display: inline-flex; align-items: center; gap: 0.35rem;
  /* `.modal-actions` et `.params-actions` sont des rangees flex SANS `align-items` : sans
     cette ligne la pastille s'etirait a la hauteur du bouton voisin. */
  align-self: center;
  padding: 0.15rem 0.55rem; border-radius: 999px;
  background: var(--bg-inset); color: var(--muted);
  font-size: 0.75rem; font-weight: 500; line-height: 1.5;
}
/* La pastille dit l'etat avant qu'on ait lu le mot. */
.enregistrement[data-etat]::before {
  content: ''; flex: none; width: 6px; height: 6px; border-radius: 50%; background: currentColor;
}
.enregistrement[data-etat="cours"]::before { animation: pouls 1.1s ease-in-out infinite; --pouls-min: 0.25; }
.enregistrement[data-etat="ok"] { color: var(--accent-text); background: color-mix(in srgb, var(--accent) 14%, transparent); }
.enregistrement[data-etat="propose"] { color: var(--warn); background: color-mix(in srgb, var(--warn) 14%, transparent); }
.enregistrement[data-etat="echec"],
.enregistrement[data-etat="conflit"],
.enregistrement[data-etat="incomplet"] { color: var(--red-text); background: color-mix(in srgb, var(--red) 14%, transparent); }
@media (prefers-reduced-motion: reduce) {
  .enregistrement[data-etat="cours"]::before { animation: none; }
}
/* Parametres : l'indicateur y est seul, sans bouton a cote. Il porte donc lui-meme sa marge
   haute, plutot qu'un conteneur qui dessinerait une bande meme au repos.
   `flex-start` et non `center` : le panneau est une colonne flex, ou l'axe transversal est
   l'horizontale — la valeur heritee ci-dessus y aurait centre la pastille dans la page, et
   sans elle la pastille s'etirait sur toute la largeur (vu a l'ecran). */
.enregistrement-bloc[data-etat] { margin-top: 1rem; align-self: flex-start; }

.sidebar-nav { display: flex; flex-direction: column; gap: var(--space-1); }
/* Porte la marge automatique à la place du pied : les deux restent collés en bas. */
.sidebar-synchro {
  margin-top: auto; padding-top: var(--space-4);
  display: flex; flex-direction: column; align-items: stretch; gap: var(--space-1);
}
.sidebar-synchro-etat { font-size: 0.7rem; color: var(--muted); text-align: center; }
/* Le bouton garde un libellé en texte pur : la synchro le remplace par « Synchronisation… » puis le
   rétablit (`lancerSynchro`), une icône dans son contenu serait perdue. L'icône est donc un
   pseudo-élément, qui tourne tant que le bouton est désactivé, c'est-à-dire en cours de synchro. */
.btn-synchro {
  display: flex; align-items: center; justify-content: center; gap: var(--space-2);
  width: 100%; padding: 0.5rem var(--space-3); cursor: pointer; font: inherit;
  font-size: 0.82rem; font-weight: 600; color: var(--text-strong);
  background: linear-gradient(135deg, var(--gold-soft), var(--accent-soft));
  border: 1px solid color-mix(in srgb, var(--gold) 45%, var(--border));
  border-radius: var(--radius-btn); box-shadow: var(--shadow-btn);
  transition: box-shadow 0.15s ease, transform 0.15s ease, border-color 0.15s ease;
}
.btn-synchro::before { content: '\21BB'; font-size: 1.05rem; line-height: 1; color: var(--gold-strong); }
.btn-synchro:hover:not(:disabled) { box-shadow: var(--shadow-btn-hover); transform: translateY(-1px); border-color: var(--gold); }
.btn-synchro:disabled { cursor: progress; opacity: 0.85; }
.btn-synchro:disabled::before { animation: tourne 1s linear infinite; }
.btn-synchro:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
@keyframes tourne { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .btn-synchro:disabled::before { animation: none; } }
.sidebar-synchro-etat:empty { display: none; }
.sidebar-footer { padding-top: var(--space-4);
  display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap;
}

/* Le bouton du compte : toute la largeur de la marge, « Se déconnecter » dessous.
   `min-width: 0` + ellipse : un long prénom se coupe, il n'élargit pas la barre. */
.btn-compte {
  flex: 1 1 100%; min-width: 0;
  display: flex; align-items: center; gap: var(--space-2);
  padding: 0.4rem var(--space-3); cursor: pointer;
  background: var(--bg-inset); color: var(--text-strong);
  border: 1px solid var(--border); border-radius: var(--radius-btn);
  font: inherit; font-size: 0.85rem; font-weight: 600; text-align: left;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}
.btn-compte[hidden] { display: none !important; }
.btn-compte:hover { background: var(--bg-hover); border-color: var(--border-strong); }
.btn-compte.active { border-color: var(--gold); background: var(--gold-soft); }
.btn-compte-initiale {
  flex: none; width: 1.5rem; height: 1.5rem; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--gold-soft); color: var(--gold-strong);
  font-size: 0.75rem; font-weight: 700;
}
/* Au-dessus du compte, discret comme « Se déconnecter » : toujours là, jamais en avant. */
.btn-retour {
  flex: 1 1 100%; background: transparent; border: none; cursor: pointer; font: inherit;
  font-size: 0.75rem; color: var(--muted); padding: 0.25rem var(--space-3); text-align: left;
  border-radius: var(--radius-btn);
}
.btn-retour[hidden] { display: none !important; }
.btn-retour::before { content: '\270E'; margin-right: var(--space-2); }
.btn-retour:hover { color: var(--gold-strong); background: var(--bg-hover); }
.btn-deconnexion {
  flex: 1 1 100%; background: transparent; border: none; cursor: pointer; font: inherit;
  font-size: 0.75rem; color: var(--muted); padding: 0.25rem var(--space-3); text-align: left;
  border-radius: var(--radius-btn);
}
.btn-deconnexion[hidden] { display: none !important; }
.btn-deconnexion::before { content: '\23FB'; margin-right: var(--space-2); }
.btn-deconnexion:hover { color: var(--red-text); background: var(--bg-hover); }
.btn-compte-nom { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.tab {
  position: relative;
  display: flex; align-items: center; gap: var(--space-3);
  width: 100%; text-align: left; background: transparent; border: none;
  color: var(--muted); padding: 0.55rem var(--space-3); cursor: pointer;
  font-size: 0.85rem; font-weight: 500; letter-spacing: 0.01em;
  border-radius: var(--radius-btn);
  transition: color 0.15s ease, background-color 0.15s ease;
}
.tab-icon { width: 18px; height: 18px; flex: 0 0 auto; }
.tab:hover { color: var(--text-strong); background: var(--bg-hover); }
.tab.active {
  color: var(--text-strong); font-weight: 600;
  background: var(--gold-soft);
}
.tab.active::before {
  content: ''; position: absolute; left: -0.75rem; top: 20%; bottom: 20%;
  width: 3px; border-radius: 0 3px 3px 0;
  background: linear-gradient(180deg, var(--gold), var(--accent));
}


.app-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }

.app-content { flex: 1 1 auto; width: 100%; padding: var(--space-6) var(--space-6) var(--space-6); }
.panel { display: none; }
.panel.active { display: flex; flex-direction: column; gap: var(--ecart-blocs); }
/* Les cartes apparaissent en fondu, légèrement décalées, à chaque bascule d'onglet — pas
   à chaque recalcul du tableau de bord : le passage display:none -> flex ci-dessus est ce
   qui rejoue l'animation, une seule fois par bascule (chantier 2 - animations, 2026-08-30).
   nth-of-type compte par groupe de frères, pas dans tout le panneau : l'effet de décalage
   porte surtout sur les cartes voisines d'une même rangée, ce qui reste le cas le plus vu. */
@keyframes carte-apparait {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}
.panel.active .card { animation: carte-apparait 0.4s ease both; }
.panel.active .card:nth-of-type(2) { animation-delay: 0.05s; }
.panel.active .card:nth-of-type(3) { animation-delay: 0.1s; }
.panel.active .card:nth-of-type(4) { animation-delay: 0.15s; }
.panel.active .card:nth-of-type(5) { animation-delay: 0.2s; }
.panel.active .card:nth-of-type(6) { animation-delay: 0.25s; }
.event-modal-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border); margin-bottom: 12px; }
.event-modal-tab { padding: 8px 12px; border: none; background: none; color: var(--muted); cursor: pointer; }
.event-modal-tab[disabled] { opacity: 0.35; cursor: not-allowed; }
.event-modal-tab.active { color: var(--text-strong); border-bottom: 2px solid var(--gold); font-weight: 600; }
.event-modal-panel[hidden] { display: none; }
h2 { font-size: 1.05rem; font-weight: 600; letter-spacing: -0.005em; margin: 0 0 0.5rem; color: var(--text-strong); }
.hint { font-size: 0.75rem; color: var(--muted); line-height: 1.45; margin: 0 0 0.5rem; }
.section-head-row .info-tip { margin-left: 0.35rem; }
.info-tip {
  display: inline-flex; align-items: center; justify-content: center;
  width: 15px; height: 15px; border-radius: 50%; flex: 0 0 auto;
  background: var(--bg-inset); color: var(--muted);
  font-size: 0.62rem; font-style: normal; font-weight: 700; line-height: 1;
  cursor: help; position: relative; vertical-align: middle;
}
.info-tip:hover, .info-tip:focus { color: var(--accent-text); outline: none; }
/* Cachée par défaut : `public/socle/info-tip.js` en pilote seul l'affichage (classe
   `.info-tip-bubble-active`), jamais `:hover`/`:focus`. Sélecteur de classe seul, PAS
   `.info-tip .info-tip-bubble` : au survol, la bulle est détachée dans `<body>` (elle n'est
   alors plus descendante de `.info-tip`), et son style ne doit rien à sa position dans le
   document, sans quoi il disparaîtrait avec elle au détachement.
   `top`/`left` ici ne servent qu'avant la première ouverture (jamais visibles). */
.info-tip-bubble {
  display: none; position: absolute; z-index: 20; top: 135%; left: 0;
  width: max-content; max-width: 260px; background: var(--card); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius-input);
  box-shadow: var(--shadow-card); padding: 0.5rem 0.65rem;
  font-size: 0.72rem; font-weight: 400; font-style: normal; line-height: 1.4; white-space: normal;
  cursor: default;
}
/* `position: fixed` : ne peut plus être coupée par le `overflow` d'un conteneur défilant
   (fiche, modale…), quel qu'il soit — c'est tout le problème que ce chantier corrige.
   `top`/`left` posés en JS, calés sur l'icône par `info-tip.js` ; `max-height`/`overflow-y`
   en filet de sécurité pour un texte plus long que l'écran n'est haut. */
.info-tip-bubble-active {
  display: block; position: fixed; top: 0; left: 0; z-index: 500;
  max-height: 60vh; overflow-y: auto;
}
.card {
  background: var(--card); box-shadow: var(--shadow-card);
  border-radius: var(--radius-card); padding: 1rem;
}
/* Sur un telephone, la marge de page (2rem) + le padding de chaque carte (1rem de chaque
   cote) mangeaient a eux seuls pres du quart des 375px disponibles — juste pour des coins
   arrondis et une ombre. La carte s'aplatit : plus de coin arrondi ni d'ombre, un simple
   trait pour marquer la place d'une carte a l'autre plutot qu'un espace + une ombre. */
@media (max-width: 900px) {
  .app-content { padding: var(--space-3); }
  .panel.active { gap: 0; }
  /* Les cartes se touchent, mais une rangée qui n'en est pas une garde l'écart que le
     panneau ne donne plus ici. */
  .subtabs-row, .kpi-row, .choix-affichage-rangee { margin-bottom: var(--ecart-blocs); }
  .card {
    box-shadow: none; border-radius: 0; padding: var(--space-3) var(--space-2);
    border-bottom: 1px solid var(--border);
  }
}
.card.inner { background: var(--card-inner); box-shadow: none; }
.kpi-row {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  background: var(--card); box-shadow: var(--shadow-card-sm); border-radius: var(--radius-card);
  padding: 0.3rem 0; overflow: hidden;
}
/* display:grid l'emporte sur la règle UA [hidden] — même piège que .subtabs[hidden] /
   .modal-overlay[hidden] : sans ce !important, une kpi-row vide reste visible comme un
   bloc carte vide. */
.kpi-row[hidden] { display: none !important; }


/* === UNE BANDE VIDE NE SE DESSINE PAS =============================================
   Le defaut est toujours le meme : un conteneur porte son trait de separation, sa marge ou
   son fond DANS SA REGLE DE BASE, et les dessine donc meme quand il n'a rien a montrer. Le
   pied du graphique Patrimoine laissait ainsi un trait et une bande de vide des que la sante
   de tresorerie manquait ; la barre collante d'Evenements reservait 4,5 rem pour un message
   de trois secondes (traitee au Bloc 1, `.scenario-sticky-bar`).

   La convention, en un seul endroit : le conteneur disparait quand il est vide. `:empty`
   ajoute une classe de specificite, donc cette regle l'emporte sur la regle de base meme
   quand celle-ci vit dans une feuille chargee plus tard.

   ATTENTION : `:empty` compte les espaces comme du contenu. Un rendu qui vide un conteneur
   doit ecrire `innerHTML = ''`, jamais un gabarit reduit a un saut de ligne. */
.hint:empty,
.chart-footnote:empty,
.endettement-mini:empty,
.alertes:empty,
.hyp-legend:empty,
.kpi-row:empty,
.catalog-segments:empty,
.catalog-wizard-fields:empty,
.comparer-grid:empty,
.flux-dated-list:empty,
.computed-net:empty,
.structure-titre:empty,
.axe-conteneur:empty,
.scenario-picker-badges:empty { display: none; }

/* --- Barre du haut : titre de l'onglet + sélecteur de scénario, toujours visible --------- */
/* Sur TOUS les formats (2026-09-05) : c'est ici qu'on regarde en premier pour savoir dans
   quel scénario on se trouve, à côté du nom de l'onglet ouvert. Seul le bouton qui ouvre le
   tiroir se cache au-dessus de 900px, la sidebar restant fixe et visible à cette largeur. */
.topbar {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  /* env(safe-area-inset-top) : encoche/barre de statut d'une coquille Capacitor (edge-to-edge
     imposé par Android à partir de l'API 35, cf. android/variables.gradle targetSdkVersion=36).
     Vaut 0 sur le web, où viewport-fit=cover (index.html) ne change rien sans appareil à encoche. */
  padding-top: max(var(--space-3), env(safe-area-inset-top));
  position: sticky; top: 0; z-index: 10; background: var(--bg);
}
.topbar-menu { flex: 0 0 auto; display: flex; align-items: center; justify-content: center; width: 2rem; height: 2rem; padding: 0; border: none; background: transparent; color: var(--text); }
.topbar-aide { flex: 0 0 auto; display: flex; }
.topbar-aide:empty { display: none; }
.topbar-titre { flex: 0 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin: 0; font-family: var(--font-serif); font-size: 1.2rem; font-weight: 500; color: var(--text-strong); }
@media (min-width: 901px) {
  .topbar-menu { display: none; }
}

/* --- Navigation mobile : tiroir off-canvas ------------------------------------------ */
/* Au-dessus de 900px, rien ne change ici : cet element reste invisible, la sidebar garde son
   comportement fixe habituel (regles plus haut dans ce fichier). */
.tiroir-fond { display: none; }

@media (max-width: 900px) {
  .sidebar {
    position: fixed; inset: 0 auto 0 0; width: min(80vw, 300px); z-index: 90;
    padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom);
    box-sizing: border-box;
    transform: translateX(-100%); transition: transform 0.2s ease;
  }
  .app-shell.tiroir-ouvert .sidebar { transform: translateX(0); }

  .tiroir-fond {
    display: block; position: fixed; inset: 0; z-index: 89; background: var(--overlay);
    opacity: 0; pointer-events: none; transition: opacity 0.2s ease;
  }
  .app-shell.tiroir-ouvert .tiroir-fond { opacity: 1; pointer-events: auto; }

  .topbar { padding: var(--space-3); gap: var(--space-2); }
  /* Pas la place à côté de la liste sur téléphone : la pastille se pose dessous, hors du flux,
     pour que la liste reste alignée sur le titre et la cloche. */
  .scenario-picker-badges { position: absolute; top: 100%; right: 0; margin-top: 0.15rem; }
  .topbar:has(.scenario-picker-badges:not(:empty)) { padding-bottom: var(--space-5); }
  .scenario-picker-row select { max-width: 8rem; }
}

/* La cloche (ce qui attend une réponse), juste avant le choix du scénario : elle prend la
   place libre de la barre, le sélecteur se colle à elle. */
.cloche-zone { position: relative; margin-left: auto; flex: 0 0 auto; }
.cloche-zone + .scenario-picker { margin-left: 0; }
.cloche {
  position: relative; display: flex; align-items: center; justify-content: center;
  width: 2.1rem; height: 2.1rem; padding: 0; border: 1px solid var(--border); border-radius: 999px;
  background: var(--card); color: var(--text);
}
.cloche:hover { color: var(--text-strong); background: var(--bg-hover); border-color: var(--border-strong); }
.cloche:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.cloche-nombre {
  position: absolute; top: -0.3rem; right: -0.3rem; min-width: 1.1rem; height: 1.1rem; padding: 0 0.25rem;
  border-radius: 999px; background: var(--gold); color: var(--btn-primary-text);
  font-size: 0.7rem; font-weight: 600; line-height: 1.1rem; text-align: center;
}
.cloche-nombre:empty { display: none; }
.cloche-liste {
  position: absolute; top: calc(100% + 0.4rem); right: 0; z-index: 20;
  width: min(22rem, calc(100vw - 2rem)); max-height: 70vh; overflow-y: auto;
  padding: var(--space-3); border: 1px solid var(--border); border-radius: var(--radius-card);
  background: var(--card); box-shadow: var(--shadow-card);
}
.cloche-liste[hidden] { display: none !important; }
.cloche-liste h2 { margin: 0 0 var(--space-2); font-size: 0.85rem; font-weight: 600; color: var(--muted); }
.cloche-liste ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.cloche-ligne { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-2); border-radius: var(--radius-input); background: var(--gold-soft); }
.cloche-ligne p { margin: 0; display: flex; flex-direction: column; gap: 0.15rem; font-size: 0.85rem; color: var(--text); }
.cloche-ligne strong { color: var(--text-strong); }
.cloche-gestes { display: flex; gap: var(--space-2); justify-content: flex-end; }
.cloche-vide { margin: 0; font-size: 0.85rem; color: var(--muted); }
/* Sur un téléphone, la cloche n'est pas au bord : la liste prend la largeur de l'écran. */
@media (max-width: 640px) {
  .cloche-liste { position: fixed; top: 4.2rem; left: 16px; right: 16px; width: auto; }
}
/* Une image en couleur à l'arrière-plan (illustrations.js) : à droite, très transparente,
   effacée vers le texte. Calée sur la LARGEUR du bloc et non sa hauteur : un bloc est bas, et
   l'image réduite à sa hauteur devenait une vignette. Un masque et non un dégradé de couleur :
   il efface vers le vrai fond, clair comme sombre ; l'image est sur fond transparent pour la
   même raison. Un masque ne lit que l'opacité : la couleur pleine du dégradé n'est pas
   affichée. */
.illustre { position: relative; isolation: isolate; overflow: hidden; }
.illustre::before {
  content: ''; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: var(--illustration) right center / min(60%, 28rem) auto no-repeat;
  opacity: 0.3;
  /* Le fondu couvre l'image et non le bloc : calé sur le bloc, un paysage peint jusqu'aux
     bords montrait son bord gauche en coupure nette. */
  -webkit-mask: linear-gradient(to right, transparent, var(--text-strong) 60%) right center / min(60%, 28rem) 100% no-repeat;
  mask: linear-gradient(to right, transparent, var(--text-strong) 60%) right center / min(60%, 28rem) 100% no-repeat;
}
