@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&family=IBM+Plex+Sans:wght@500;600;700&display=swap');

/* ===== Design tokens ===== */
:root {
  color-scheme: light dark;
  /* Thème « Encre & Laiton » (2026).
     Le sujet de cette app, c'est la MESURE : des cours, des poids, des écarts.
     Le thème est donc construit comme un instrument, pas comme une brochure —
     plan de fond neutre-froid (encre sur papier technique), filets d'un pixel,
     chiffres en monospace, et UNE couleur chaude qui sert de repère.

     ⚠️ Règle de lisibilité inchangée : l'ACCENT (chrome : nav, boutons, liens)
     est un LAITON — une teinte tierce, volontairement HORS du vert/rouge
     sémantiques. Ainsi le vert (--pos) reste réservé aux GAINS et le rouge
     (--neg) aux PERTES : dans une app boursière, la décoration ne doit jamais
     se confondre avec un signal de performance.

     Le prédécesseur (« Or & Graphite ») posait un fond crème chaud (#f7f5ef).
     Le crème tire vers le papier vieilli : joli, mais il réchauffe les rouges
     et écrase la lisibilité des teintes froides des graphiques. Le plan est
     désormais neutre-froid, ce qui laisse le laiton être la seule chose chaude
     de l'écran — donc la seule qui attire l'œil. */
  --bg: #eceff3;
  --bg-tint: radial-gradient(120% 90% at 50% -10%, rgba(138, 101, 18, 0.05), transparent 60%);
  --surface: #ffffff;
  --surface-2: #f4f6f9;
  --surface-3: #e6ebf1;
  --text: #10151b;
  --text-muted: #5b6875;
  --border: #dce2e9;
  --border-strong: #bcc7d3;
  --accent: #8a6512;
  --accent-hover: #6d500a;
  --accent-weak: rgba(138, 101, 18, 0.12);
  /* Texte POSÉ SUR l'accent. Longtemps codé en dur à #fff : lisible en clair
     mais catastrophique en sombre, où l'accent s'éclaircit — blanc sur laiton
     tombe sous le seuil 3:1 des composants d'interface. Le défaut ne se voyait
     qu'APRÈS bascule de thème, d'où sa longévité. */
  --on-accent: #fdfbf6;
  --pos: #0d7a45;
  --pos-weak: rgba(13, 122, 69, 0.12);
  --neg: #c02b26;
  --neg-weak: rgba(192, 43, 38, 0.11);
  --warn: #9a5c08;

  --shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.05);
  --shadow: 0 1px 3px rgba(16, 24, 40, 0.07), 0 1px 2px rgba(16, 24, 40, 0.04);
  --shadow-lg: 0 12px 32px -8px rgba(16, 24, 40, 0.18), 0 4px 10px rgba(16, 24, 40, 0.06);
  --shadow-pop: 0 20px 50px -12px rgba(16, 24, 40, 0.28);

  /* Rayons resserrés (7/12/16 -> 5/9/13). Un instrument de mesure a des angles
     nets ; les grands arrondis lisaient « application grand public ». */
  --radius-sm: 5px;
  --radius: 9px;
  --radius-lg: 13px;

  /* Rythme d'espacement : tout dérive de cette échelle, plus de valeurs au hasard */
  --s1: 0.25rem;
  --s2: 0.5rem;
  --s3: 0.75rem;
  --s4: 1rem;
  --s5: 1.5rem;
  --s6: 2rem;

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --fast: 0.14s var(--ease);
  --med: 0.24s var(--ease);

  /* Typographie — le pari du thème.
     Le corps reste sur la pile système (aucun reflow des tableaux, chargement
     instantané). Deux faces s'ajoutent, chacune pour un rôle :
       --font-display : IBM Plex Sans, grotesque technique, pour les TITRES.
       --font-mono    : IBM Plex Mono, pour tout ce qui est un NOMBRE — valeur
                        héros, tuiles de KPI, tickers, graduations d'axes.
     C'est le geste signature : dans un terminal de marché, un chiffre se lit en
     chasse fixe. Les colonnes s'alignent d'elles-mêmes, les ordres de grandeur
     se comparent à l'œil, et un « 1 » ne fait plus la moitié d'un « 8 ».
     Space Grotesk (prédécesseur) faisait les deux à la fois et ne faisait bien
     ni l'un ni l'autre : trop typé pour un tableau, pas assez pour un titre. */
  --font-display: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  --fs-display: clamp(2.3rem, 4.6vw, 3.2rem);
  --fs-xl: 1.55rem;
  --fs-lg: 1.15rem;
  --fs-md: 0.95rem;
  --fs-sm: 0.82rem;
  --fs-xs: 0.72rem;
  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;

  /* ===== Palette catégorielle (donuts, barres, légendes) =====
     REFAITE et VALIDÉE (skill dataviz, `scripts/validate_palette.js`).
     L'ancienne (or/bleu/violet/turquoise…) échouait dès 4 teintes ensemble :
     --c2 et --c3 mesuraient ΔE 1,5 en vision deutan (seuil : 8) et AUCUNE
     n'atteignait 3:1 contre le fond. Concrètement, deux secteurs d'un donut
     étaient indiscernables pour ~8 % des hommes, et pâles pour tout le monde.

     Le passage validé, 8 fentes, ORDRE COMPRIS (l'ordre est le mécanisme de
     sécurité daltonienne : ce sont les paires ADJACENTES qui se retrouvent
     côte à côte dans un empilement ou une légende) :
       clair (fond #ffffff) : tous les contrôles PASS —
         bande de clarté, plancher de chroma, séparation CVD (pire paire
         adjacente violet↔cyan ΔE 9,3 deutan), vision normale (pire paire
         ΔE 16,8), contraste ≥ 3:1 sur les 8.
       sombre (fond #16181b) : tous les contrôles PASS —
         pire paire adjacente ΔE 8,6 deutan, vision normale ΔE 16,3,
         contraste ≥ 3:1 sur les 8.

     Le VERT et le ROUGE en sont toujours absents : réservés aux gains/pertes.
     L'OR aussi, désormais : il était la 1re teinte, donc le plus gros segment
     de chaque donut portait exactement la couleur du chrome (boutons, liens,
     onglet actif) — impossible de savoir si une pastille dorée désignait une
     catégorie ou un élément d'interface. Le laiton ne dit plus qu'une chose.

     Au-delà de 8 catégories, on NE génère PAS une 9e teinte : le reste se
     replie dans « Autres » (--c-other, neutre, hors palette). */
  --c1: #2b62c9;   /* bleu */
  --c2: #dd6a12;   /* orange */
  --c3: #0f92ae;   /* cyan */
  --c4: #8a4fc0;   /* violet */
  --c5: #d95093;   /* magenta */
  --c6: #4a92dc;   /* azur */
  --c7: #b5732f;   /* terre */
  --c8: #6f5bd6;   /* indigo */
  --c-other: #7b8794;
  /* Compat : deux fichiers référencent encore --c9/--c10 (badges de source).
     Ce sont des NEUTRES, pas des fentes catégorielles — ne pas les ajouter à
     une palette de graphique, elles n'ont pas passé la validation. */
  --c9: #6b7684;
  --c10: #8d7a5c;
}

/* Le mode sombre est CHOISI, pas déduit : les teintes catégorielles y sont
   re-pas-à-pas contre le fond sombre (#16181b) et re-validées comme un jeu, ce
   n'est pas un éclaircissement automatique des valeurs claires.
   Deux portées, volontairement : le media query couvre le réglage système, le
   sélecteur [data-theme] couvre la bascule manuelle de l'app (header.js). */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0d0f12;
    --bg-tint: radial-gradient(120% 90% at 50% -10%, rgba(217, 169, 78, 0.09), transparent 60%);
    --surface: #16181b;
    --surface-2: #1d2126;
    --surface-3: #262b31;
    --text: #e9edf1;
    --text-muted: #949fac;
    --border: #262b31;
    --border-strong: #39414a;
    --accent: #d9a94e;
    --accent-hover: #eec473;
    --accent-weak: rgba(217, 169, 78, 0.16);
    --on-accent: #0d0f12;   /* le blanc sur laiton clair tombait à 2,17:1 */
    --pos: #35c07f;
    --pos-weak: rgba(53, 192, 127, 0.15);
    --neg: #f0685e;
    --neg-weak: rgba(240, 104, 94, 0.14);
    --warn: #e0973a;
    --c1: #4d80e2;
    --c2: #d7701e;
    --c3: #149ab6;
    --c4: #9a5fdb;
    --c5: #e05f9b;
    --c6: #4f91d8;
    --c7: #b57c31;
    --c8: #7b6ade;
    --c-other: #7f8a97;
    --c9: #8a95a3;
    --c10: #a08c68;
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
    --shadow-lg: 0 12px 32px -8px rgba(0, 0, 0, 0.7);
    --shadow-pop: 0 20px 50px -12px rgba(0, 0, 0, 0.8);
  }
}

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

* {
  box-sizing: border-box;
}

/* Visible des seuls lecteurs d'écran. Sert à donner un nom à un champ dont
   l'étiquette visuelle serait redondante (un `placeholder` n'est PAS une
   étiquette : il disparaît à la saisie et n'est pas toujours annoncé). */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  max-width: 1440px;
  margin: 0 auto;
  padding: 0 1.5rem 3rem;
  background: var(--bg);
  color: var(--text);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

h1 {
  font-size: 1.6rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 0.5rem 0 1.25rem;
}

h2 {
  font-size: 1.15rem;
  font-weight: 650;
}

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

/* Bandeau marché (header global) */
.market-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 0.4rem 0;
  border-bottom: 1px solid var(--border);
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
}

.indices {
  display: flex;
  gap: 1.1rem;
  flex-wrap: wrap;
}

.idx b {
  color: var(--text-muted);
  font-weight: 600;
  margin-right: 0.25rem;
}

.idx-loading {
  color: var(--text-muted);
}

.market-status {
  color: var(--text-muted);
  white-space: nowrap;
}

.market-status .dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-right: 0.3rem;
}

.market-status .dot.open {
  background: var(--pos);
}

.market-status .dot.closed {
  background: var(--neg);
}

.market-status .hours {
  opacity: 0.7;
}

tr.clickable-row,
tr.prospect-row {
  cursor: pointer;
}

.ai-text h4 {
  margin: 0.6rem 0 0.3rem;
  font-size: 0.95rem;
}

.ai-text p,
.ai-text li {
  font-size: 0.9rem;
  line-height: 1.55;
}

/* ===== Navigation ===== */
.topnav {
  display: flex;
  gap: 0.25rem;
  padding: 0.6rem 0;
  margin-bottom: 1.5rem;
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  background: var(--bg);
  z-index: 10;
}

.topnav a {
  padding: 0.5rem 1rem;
  text-decoration: none;
  color: var(--text-muted);
  font-weight: 550;
  border-radius: 8px;
  transition: background 0.15s, color 0.15s;
}

.topnav a:hover {
  background: var(--surface-2);
  color: var(--text);
}

.topnav a.active {
  color: var(--accent);
  background: var(--accent-weak);
}

/* ===== KPI / summary tiles ===== */
.summary {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin: 0 0 1.75rem;
}

.summary > div {
  flex: 1;
  min-width: 160px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.9rem 1.1rem;
  box-shadow: var(--shadow);
  color: var(--text-muted);
  font-size: 0.82rem;
}

.summary strong {
  display: block;
  margin-top: 0.25rem;
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--text);
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}

/* ===== Forms ===== */
.form-section {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem 1.25rem;
  margin-bottom: 1.75rem;
  box-shadow: var(--shadow);
}

.form-section h2 {
  margin: 0 0 0.75rem;
}

#position-form,
#prospect-form,
#etf-form {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  align-items: center;
}

input,
select,
button {
  font-family: inherit;
  font-size: 0.9rem;
  color: var(--text);
}

input,
select {
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  background: var(--surface);
  min-height: 38px;
}

input::placeholder {
  color: var(--text-muted);
}

input:focus,
select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-weak);
}

button[type="submit"] {
  padding: 0.5rem 1.1rem;
  border: none;
  border-radius: 8px;
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 600;
  cursor: pointer;
  min-height: 38px;
  transition: filter 0.15s;
}

button[type="submit"]:hover {
  filter: brightness(1.08);
}

/* ===== Toolbar ===== */
.toolbar {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  margin: 0 0 0.75rem;
}

#filter-input {
  min-width: 260px;
}

.toolbar button,
button.secondary {
  padding: 0.45rem 0.85rem;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  font-weight: 550;
  min-height: 38px;
}

.toolbar button:hover {
  background: var(--surface-2);
}

/* ===== Tables ===== */
.table-wrap {
  overflow-x: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.5rem 1rem 1rem;
  margin-bottom: 1.75rem;
  box-shadow: var(--shadow);
}

.table-title {
  margin: 0.5rem 0 0.75rem;
  font-size: 1.05rem;
}

table {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}

th,
td {
  text-align: right;
  padding: 0.55rem 0.6rem;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

thead th {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-muted);
  font-weight: 600;
  border-bottom: 1px solid var(--border-strong);
  position: sticky;
  top: 0;
}

th:first-child,
td:first-child {
  text-align: left;
}

tbody tr:hover td {
  background: var(--surface-2);
}

.pos {
  color: var(--pos);
}

.neg {
  color: var(--neg);
}

/* Titre : nom + ticker · secteur */
.title-cell {
  text-align: left;
  /* La colonne « Titre » est STICKY (voir plus bas) : elle occupe donc en
     permanence de la largeur visible, quelle que soit la position du défilement
     horizontal. Mesurée à 433 px sur 1158 disponibles — 37 % de l'écran pour un
     libellé, à cause d'un seul nom long (« International Business Machines
     Corporation »). Bridée ici, les colonnes d'argent tiennent sans défiler. */
  max-width: 280px;
  /* Certaines pages (/markets) mettent du TEXTE NU dans cette cellule, sans
     `.title-main` pour porter la troncature : sans ces trois lignes, le
     `max-width` ci-dessus coupait le nom net, sans ellipsis. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.title-main,
.title-sub {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Le `ƒx` est un bouton, pas du texte : l'ellipsis ne doit pas l'avaler. */
.title-sub { display: flex; align-items: center; gap: var(--s1); }
.title-sub .ind-btn { flex: none; }

.title-main {
  font-weight: 600;
}

.title-sub {
  font-size: 0.72rem;
  color: var(--text-muted);
}

/* En-têtes triables */
th.sortable {
  cursor: pointer;
  user-select: none;
}

th.sortable:hover {
  color: var(--text);
}

/* Le libellé triable est un vrai <button> : un <th> n'est pas focusable, donc
   le tri — la fonction principale du screener — était hors d'atteinte au
   clavier. Le bouton est dépouillé de son apparence native mais garde son
   comportement, et son anneau de focus reste VISIBLE : c'est le seul repère
   dont dispose quelqu'un qui navigue à la tabulation. */
th .th-sort {
  all: unset;
  display: inline;
  cursor: pointer;
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
}
th .th-sort:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 3px;
}

/* Même exigence pour les infobulles, devenues focusables (tabindex=0) afin
   d'être atteignables au clavier et au tap — elles portent la méthode de calcul
   des indices, seule justification des scores affichés. */
.has-tip:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 3px;
}

th.sort-asc::after {
  content: " ▲";
  font-size: 0.65em;
  color: var(--accent);
}

th.sort-desc::after {
  content: " ▼";
  font-size: 0.65em;
  color: var(--accent);
}

/* Groupes */
.group-header td {
  font-weight: 650;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-muted);
  background: var(--surface-2);
  padding-top: 0.6rem;
  padding-bottom: 0.4rem;
  border-bottom: none;
  text-align: left;
}

.group-header td,
tbody tr:hover .group-header td {
  background: var(--surface-2);
}

.group-subtotal td {
  font-weight: 650;
  border-top: 1px solid var(--border-strong);
  border-bottom: 2px solid var(--border-strong);
}

.group-subtotal td:first-child {
  color: var(--text-muted);
  font-weight: 500;
}

tbody tr.group-subtotal:hover td {
  background: transparent;
}

/* Dividendes : cellules + accordéon */
.div-cell {
  white-space: nowrap;
}

.div-total {
  display: block;
}

.div-unit {
  display: block;
  font-size: 0.7rem;
  color: var(--text-muted);
}

.h-div-last,
td.div-first {
  border-left: 1px solid var(--border-strong);
}

body.hide-div .div-col {
  display: none;
}

button.delete {
  background: none;
  border: none;
  color: var(--neg);
  cursor: pointer;
  font-size: 0.9rem;
  opacity: 0.6;
  transition: opacity 0.15s;
}

button.delete:hover {
  opacity: 1;
}

.refresh-note {
  color: var(--text-muted);
  font-size: 0.85rem;
}

/* ===== Synthèse par compte ===== */
.summary-table {
  max-width: 960px;
}

/* ===== Dashboard ===== */
.dash-grid {
  display: grid;
  /* `auto-fit`, pas `auto-fill` : à 1158 px de large, `auto-fill` réservait
     TROIS pistes de 360 px alors que la page n'a jamais que deux cartes par
     rangée — la troisième restait vide et les graphiques se serraient sur les
     deux tiers gauche de l'écran. `auto-fit` réduit la piste vide à zéro et
     laisse les cartes occuper la largeur. */
  grid-template-columns: repeat(auto-fit, minmax(360px, 1fr));
  gap: 1.25rem;
}

.chart-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.1rem 1.25rem;
  box-shadow: var(--shadow);
}

.chart-card.wide {
  grid-column: span 2;
}

.chart-card h3 {
  margin: 0 0 1rem;
  font-size: 0.95rem;
  font-weight: 650;
}

.chart-body {
  display: flex;
  gap: 1.25rem;
  align-items: center;
  flex-wrap: wrap;
}

.donut {
  width: 160px;
  height: 160px;
  flex: 0 0 auto;
}

.legend {
  flex: 1;
  min-width: 170px;
  font-size: 0.85rem;
}

.legend-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.2rem 0;
}

.legend-label {
  flex: 1;
}

.legend-dot {
  width: 10px;
  height: 10px;
  border-radius: 3px;
  flex: 0 0 auto;
}

.legend-item b {
  font-variant-numeric: tabular-nums;
}

.legend-pct {
  color: var(--text-muted);
  min-width: 46px;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.mgr-ticker {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: var(--text);
  cursor: pointer;
  text-align: left;
}

.mgr-ticker:hover,
.mgr-ticker:focus-visible {
  color: var(--accent);
  text-decoration: underline;
}

.mgr-period {
  float: right;
  margin-left: 0.75rem;
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--text-muted);
}

.bars {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}

.bar-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-size: 0.85rem;
}

.bar-label {
  flex: 0 0 140px;
}

.bar-track {
  flex: 1;
  height: 16px;
  background: var(--surface-2);
  border-radius: 4px;
  overflow: hidden;
}

.bar-fill {
  display: block;
  height: 100%;
  border-radius: 4px;
}

/* 96 px suffisaient tant qu'une barre ne portait qu'un montant. La colonne de
   concentration en affiche deux (« 9,3 k€ · 17,1% ») : quatre lignes sur dix
   passaient à la ligne, leur hauteur doublait, et l'échelle de barres cessait
   d'être une échelle — c'est le défaut le plus visible d'un graphe en barres,
   des rangs qui n'ont pas le même pas. Largeur fixe (donc pistes de même
   longueur d'une ligne à l'autre, ce qui est la condition pour comparer) et
   `nowrap` pour que le débordement se voie au lieu de se replier en silence. */
.bar-value {
  flex: 0 0 112px;
  text-align: right;
  font-weight: 600;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

@media (max-width: 760px) {
  .chart-card.wide {
    grid-column: span 1;
  }
}

/* ===== Prospects ===== */
.prospect-layout {
  display: flex;
  gap: 1.5rem;
  align-items: flex-start;
}

.prospect-list-wrap {
  flex: 0 0 260px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.5rem 0.75rem;
  box-shadow: var(--shadow);
}

.recap-panel {
  flex: 1;
  min-width: 0;
}

.prospect-row {
  cursor: pointer;
}

.prospect-row:hover td {
  background: var(--surface-2);
}

.prospect-row.selected td {
  background: var(--accent-weak);
}

.recap-empty {
  color: var(--text-muted);
  padding: 2rem 0;
}

.recap-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--border);
}

.recap-header h2 {
  margin: 0;
}

.recap-sub {
  color: var(--text-muted);
  font-size: 0.85rem;
  margin-top: 0.15rem;
}

.recap-price {
  font-size: 1.7rem;
  font-weight: 700;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.recap-summary {
  font-size: 0.88rem;
  line-height: 1.6;
  color: var(--text-muted);
  max-width: 75ch;
}

.recap-web {
  font-size: 0.85rem;
}

.recap-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 1rem;
  margin-top: 1rem;
}

.recap-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.9rem 1.1rem;
  box-shadow: var(--shadow);
}

.recap-card h3 {
  margin: 0 0 0.6rem;
  font-size: 0.9rem;
  font-weight: 650;
  color: var(--accent);
}

.recap-item {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.28rem 0;
  border-bottom: 1px solid var(--border);
  font-size: 0.85rem;
}

.recap-item:last-child {
  border-bottom: none;
}

.recap-label {
  color: var(--text-muted);
}

.recap-value {
  font-weight: 600;
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* ===== ETF ===== */
.badge {
  font-size: 0.68rem;
  padding: 0.05rem 0.45rem;
  border-radius: 999px;
  background: var(--accent-weak);
  color: var(--accent);
  font-weight: 600;
  vertical-align: middle;
}

.etf-name {
  text-align: left;
  font-size: 0.85rem;
  color: var(--text-muted);
  white-space: normal;
}

/* Résultats de recherche (prospects) */
#search-results {
  margin-top: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.search-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface-2);
}

.search-row > span:first-child {
  flex: 1;
}

.search-meta {
  font-size: 0.8rem;
  color: var(--text-muted);
}

.add-btn {
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--accent);
  border-radius: 6px;
  background: var(--accent-weak);
  color: var(--accent);
  cursor: pointer;
  font-weight: 600;
}

.add-btn:hover {
  background: var(--accent);
  color: var(--on-accent);
}

.toolbar label {
  font-size: 0.85rem;
  color: var(--text-muted);
}

/* ===== Modale ===== */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 3rem 1rem;
  z-index: 100;
  overflow-y: auto;
}

.modal {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
  width: 100%;
  max-width: 760px;
  position: relative;
  padding: 1.5rem;
}

.modal.modal-chart {
  max-width: 780px;
}

.modal-close {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  border: none;
  background: var(--surface-2);
  color: var(--text);
  width: 30px;
  height: 30px;
  border-radius: 50%;
  cursor: pointer;
  font-size: 0.9rem;
}

.modal-close:hover {
  background: var(--border);
}

/* Bouton graphique dans les tableaux */
button.chart-btn {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 0.95rem;
  opacity: 0.7;
}

button.chart-btn:hover {
  opacity: 1;
}

/* Graphique de cours */
.chart-title {
  margin: 0 2rem 0.75rem 0;
  font-size: 1.15rem;
}

.chart-sym {
  color: var(--text-muted);
  font-size: 0.85rem;
  font-weight: 400;
}

.range-tabs {
  display: flex;
  gap: 0.35rem;
  margin-bottom: 0.75rem;
}

.range-tabs button {
  padding: 0.3rem 0.8rem;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  font-weight: 550;
  font-size: 0.85rem;
}

.range-tabs button.active {
  background: var(--accent);
  color: var(--on-accent);
  border-color: var(--accent);
}

.chart-wrap {
  position: relative;
}

.price-chart {
  width: 100%;
  height: auto;
  display: block;
}

.price-chart .grid {
  stroke: var(--border);
  stroke-width: 1;
}

.price-chart .axis-label {
  fill: var(--text-muted);
  font-size: 11px;
}

.price-chart .crosshair {
  stroke: var(--text-muted);
  stroke-width: 1;
  stroke-dasharray: 3 3;
}

.chart-tooltip {
  position: absolute;
  pointer-events: none;
  background: var(--text);
  color: var(--bg);
  padding: 0.25rem 0.5rem;
  border-radius: 6px;
  font-size: 0.78rem;
  white-space: nowrap;
  display: flex;
  flex-direction: column;
  line-height: 1.3;
}

.chart-caption {
  color: var(--text-muted);
  font-size: 0.78rem;
  margin-top: 0.35rem;
}

.chart-sub-note {
  font-size: 0.75rem;
  font-weight: 400;
  color: var(--text-muted);
}

.line-legends {
  display: flex;
  gap: 1.25rem;
  flex-wrap: wrap;
  margin-bottom: 0.5rem;
  font-size: 0.85rem;
}

.line-legend {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

.tx-badge {
  font-size: 0.72rem;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  font-weight: 600;
}

.tx-badge.buy {
  background: rgba(26, 127, 75, 0.15);
  color: var(--pos);
}

.tx-badge.sell {
  background: rgba(209, 59, 59, 0.15);
  color: var(--neg);
}

/* ===== Indicateurs quantitatifs ===== */
button.ind-btn {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 0.9rem;
  opacity: 0.7;
  padding: 0 0.15rem;
}

button.ind-btn:hover {
  opacity: 1;
}

.cur-tag {
  font-size: 0.68rem;
  color: var(--text-muted);
  font-weight: 500;
}

.fx-warn {
  color: var(--neg);
  cursor: help;
}

.has-tip {
  cursor: help;
  border-bottom: 1px dotted var(--text-muted);
}

.tip-mark {
  display: inline-block;
  margin-left: 0.25rem;
  font-size: 0.62rem;
  font-weight: 700;
  color: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 50%;
  width: 12px;
  height: 12px;
  line-height: 11px;
  text-align: center;
}

.tip-box {
  position: fixed;
  z-index: 200;
  max-width: 340px;
  background: var(--text);
  color: var(--bg);
  padding: 0.6rem 0.75rem;
  border-radius: 8px;
  font-size: 0.78rem;
  line-height: 1.5;
  white-space: pre-line;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
  pointer-events: none;
}

.ind-note {
  display: block;
  font-size: 0.7rem;
  font-weight: 400;
  color: var(--text-muted);
  white-space: normal;
  max-width: 220px;
  text-align: right;
}

/* ===== Onglets ===== */
.tabs {
  display: flex;
  gap: 0.4rem;
  border-bottom: 1px solid var(--border);
  margin-bottom: 1.25rem;
  /* Quatre onglets (« Décisions / Mesure / Positions / Drops détectés ») font
     382 px : ils débordaient d'un écran de 366 px et faisaient défiler la PAGE
     entière latéralement. Ils défilent maintenant entre eux, et la page ne
     bouge plus. */
  overflow-x: auto;
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tabs .tab { flex: none; white-space: nowrap; }
.tabs .tab {
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  color: var(--text-muted);
  font-size: 0.92rem;
  font-weight: 600;
  padding: 0.6rem 0.9rem;
  cursor: pointer;
  border-radius: 0;
}
.tabs .tab:hover {
  color: var(--text);
}
.tabs .tab.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}
.tab-badge {
  display: inline-block;
  margin-left: 0.35rem;
  padding: 0.05rem 0.4rem;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: 0.72rem;
}

/* ===== Annuaire ETF ===== */
.filter-actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-top: 0.85rem;
  flex-wrap: wrap;
}
.check-inline {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.85rem;
  color: var(--text-muted);
}
.match-count {
  margin-left: auto;
  font-size: 0.82rem;
  color: var(--text-muted);
}
.muted-cell {
  color: var(--text-muted);
  font-size: 0.8rem;
}
.repl {
  font-size: 0.78rem;
  color: var(--text-muted);
}
.sep {
  color: var(--text-muted);
  margin: 0 0.15rem;
}
.pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  margin: 1.25rem 0 2rem;
}
.pager-info {
  font-size: 0.85rem;
  color: var(--text-muted);
}
.pager button[disabled] {
  opacity: 0.4;
  cursor: not-allowed;
}

/* ===== Screener ===== */
.score-pill {
  display: inline-block;
  min-width: 42px;
  padding: 0.2rem 0.45rem;
  border-radius: 999px;
  font-weight: 700;
  font-size: 0.82rem;
  text-align: center;
  border-bottom: none;
}
.score-hi {
  background: rgba(31, 122, 77, 0.15);
  color: var(--pos);
  border: 1px solid rgba(31, 122, 77, 0.4);
}
.score-mid {
  background: var(--surface-2, rgba(128, 128, 128, 0.12));
  color: var(--text);
  border: 1px solid var(--border);
}
.score-lo {
  background: rgba(220, 38, 38, 0.13);
  color: var(--neg);
  border: 1px solid rgba(220, 38, 38, 0.35);
}
.score-na {
  color: var(--text-muted);
  font-size: 0.8rem;
}
.filter-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem 1.25rem;
  margin-bottom: 1.25rem;
  box-shadow: var(--shadow);
}

.filter-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 0.6rem;
}

.f-item {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  font-size: 0.75rem;
  color: var(--text-muted);
}

.f-item input {
  min-height: 32px;
}

.filter-actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-top: 0.85rem;
  flex-wrap: wrap;
}

.chk {
  font-size: 0.85rem;
  color: var(--text-muted);
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

.match-count {
  margin-left: auto;
  font-size: 0.85rem;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

/* Avertissement méthodo + encadré backtest */
.warn-box {
  border: 1px solid var(--border-strong);
  border-left: 3px solid var(--accent);
  border-radius: 8px;
  padding: 0.85rem 1rem;
  font-size: 0.85rem;
  line-height: 1.6;
  color: var(--text-muted);
  background: var(--surface);
  margin-bottom: 1rem;
}

.bt-meta {
  font-size: 0.85rem;
  color: var(--text-muted);
  margin: 1rem 0 0.75rem;
}

.callout {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem 1.25rem;
  margin-bottom: 1.25rem;
  box-shadow: var(--shadow);
}

.callout h3 {
  margin: 0 0 0.5rem;
  font-size: 1rem;
}

.callout p {
  margin: 0.3rem 0;
  font-size: 0.9rem;
}

.callout-nums {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  flex-wrap: wrap;
  font-size: 1rem !important;
  margin-top: 0.6rem !important;
}

.callout-nums b {
  font-size: 1.25rem;
}

.callout-nums .arrow {
  color: var(--text-muted);
  font-size: 1.2rem;
}

.decay {
  font-weight: 700;
  font-size: 0.9rem;
}

.callout-note {
  color: var(--text-muted);
  font-style: italic;
  margin-top: 0.5rem !important;
}

tr.ref-row td {
  color: var(--text-muted);
  background: var(--surface-2);
}

.recap-cards .recap-card.wide {
  grid-column: 1 / -1;
}

.piotroski-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 0.2rem 1rem;
}

.pio-item {
  font-size: 0.8rem;
  color: var(--text-muted);
  padding: 0.15rem 0;
}

.pio-item span {
  font-weight: 700;
  margin-right: 0.35rem;
}

.ind-inputs {
  margin-top: 1rem;
  border-top: 1px solid var(--border);
  padding-top: 0.75rem;
}

.ind-inputs h4 {
  margin: 0 0 0.4rem;
  font-size: 0.9rem;
}

.ind-inputs ul {
  margin: 0;
  padding-left: 1.1rem;
  font-size: 0.8rem;
  color: var(--text-muted);
  line-height: 1.6;
}

/* Boutons d'action dans la modale récap */
.recap-actions {
  display: flex;
  gap: 0.5rem;
  margin: 0.75rem 0;
  flex-wrap: wrap;
}

.recap-actions button {
  padding: 0.45rem 0.9rem;
  border-radius: 8px;
  border: 1px solid var(--accent);
  background: var(--accent-weak);
  color: var(--accent);
  font-weight: 600;
  cursor: pointer;
}

.recap-actions button:hover {
  background: var(--accent);
  color: var(--on-accent);
}

.ai-analysis {
  margin-top: 1rem;
  border-top: 1px solid var(--border);
  padding-top: 1rem;
}

.ai-analysis h3 {
  margin: 0 0 0.5rem;
}

.ai-analysis .disclaimer {
  font-size: 0.78rem;
  color: var(--text-muted);
  font-style: italic;
  margin-top: 0.75rem;
}

.similar-list {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-top: 0.5rem;
}

.similar-item {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.5rem 0.75rem;
  font-size: 0.85rem;
}

.similar-item b {
  cursor: pointer;
  color: var(--accent);
}

.trap-mark {
  margin-left: 0.3rem;
  color: var(--neg);
  font-size: 0.85rem;
  cursor: help;
}

/* ===== Graphique technique ===== */
.chart-controls {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 0.5rem;
}
.layer-tabs {
  display: flex;
  gap: 0.3rem;
  flex-wrap: wrap;
}
.layer-tabs button {
  padding: 0.3rem 0.6rem;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-muted);
  font-size: 0.76rem;
  font-weight: 600;
  cursor: pointer;
}
.layer-tabs button:hover {
  color: var(--text);
}
.layer-tabs button.active {
  background: var(--accent-weak);
  border-color: var(--accent);
  color: var(--accent);
}
.sub-panel {
  margin-top: 0.4rem;
  border-top: 1px solid var(--border);
  padding-top: 0.2rem;
}
.sub-label {
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--text-muted);
  padding-left: 52px;
}
.legend-cloud {
  background: linear-gradient(90deg, var(--pos), var(--neg));
  opacity: 0.5;
}
.legend-tri {
  display: inline-block;
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-bottom: 8px solid var(--pos);
  margin-right: 0.35rem;
}
.signal polygon {
  fill: var(--pos);
}
.signal.sig-divergence polygon {
  fill: var(--accent);
}
.signal {
  cursor: help;
}
.signal:hover polygon {
  transform-box: fill-box;
  transform-origin: center;
  transform: scale(1.3);
}
.sig-detail {
  display: block;
  max-width: 240px;
  white-space: normal;
  line-height: 1.4;
  margin-top: 0.2rem;
  opacity: 0.85;
}

.recap-grid-outer > .recap-card { margin-bottom: 0.75rem; }
.etf-sheet-actions {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.75rem;
  flex-wrap: wrap;
}
.etf-sheet-actions button {
  padding: 0.45rem 0.9rem;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
  font-weight: 600;
  cursor: pointer;
}
.etf-sheet-actions button.secondary {
  background: var(--surface);
  color: var(--text);
  border-color: var(--border-strong);
}
.etf-sheet-actions button[disabled] { opacity: 0.6; cursor: default; }

/* ============================================================
   PASSE UX/UI — surcharges volontairement en fin de fichier
   ============================================================ */

body {
  background-color: var(--bg);
  background-image: var(--bg-tint);
  background-repeat: no-repeat;
  background-attachment: fixed;
  font-size: 14px;
  letter-spacing: -0.006em;
  max-width: 1560px;
  padding: 0 var(--s5) var(--s6);
}

h1 {
  font-size: 1.75rem;
  font-weight: 750;
  letter-spacing: -0.028em;
  margin: var(--s5) 0 var(--s4);
}
h2 { letter-spacing: -0.018em; }
h3 { letter-spacing: -0.012em; }

::selection { background: var(--accent-weak); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* ===== Bandeau marché ===== */
.market-header {
  padding: var(--s2) 0;
  border-bottom: 1px solid var(--border);
  gap: var(--s3) var(--s4);
}
/* La liste d'indices cède la place à la recherche quand la fenêtre se resserre :
   c'est la recherche qui doit rester à taille utilisable, pas l'inverse. */
.indices { flex: 1 1 auto; min-width: 0; overflow: hidden; }
.idx { transition: color var(--fast); }
.market-status .dot { box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 18%, transparent); }
.market-status .dot.open { background: var(--accent); color: var(--accent); animation: pulse 2.4s ease-in-out infinite; }
/* Ni la place FERMÉE ni la place OUVERTE ne sont un gain ou une perte. Le rouge
   disait « moins-value » à côté de « New York » alors qu'il ne disait que « il
   est 3 h du matin là-bas » — mais le vert d'en face disait « plus-value » avec
   exactement autant de tort, et il le disait À CÔTÉ des variations d'indices,
   elles bel et bien vertes ou rouges au sens propre. Les deux passent hors du
   couple sémantique (CLAUDE.md § 3) : point éteint pour fermé, laiton pulsé
   pour ouvert — l'accent est justement la teinte tierce prévue pour ça. */
.market-status .dot.closed { background: var(--text-muted); color: var(--text-muted); opacity: 0.55; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }

/* ===== Navigation ===== */
.topnav {
  gap: var(--s1);
  padding: var(--s2) 0;
  margin-bottom: var(--s5);
  backdrop-filter: saturate(180%) blur(12px);
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  overflow-x: auto;
  scrollbar-width: none;
}
.topnav::-webkit-scrollbar { display: none; }
.topnav a {
  position: relative;
  padding: 0.45rem 0.85rem;
  border-radius: 999px;
  font-size: 0.86rem;
  font-weight: 600;
  white-space: nowrap;
  transition: background var(--fast), color var(--fast), transform var(--fast);
}
.topnav a:hover { transform: translateY(-1px); }
.topnav a.active { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 30%, transparent); }

/* ===== Cartes & sections ===== */
.summary > div,
.form-section,
.table-wrap,
.filter-panel,
.chart-card {
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  transition: box-shadow var(--med), border-color var(--med);
}
.summary > div {
  position: relative;
  overflow: hidden;
  padding: var(--s4) var(--s4) var(--s4) 1.15rem;
}
/* Liseré d'accent : hiérarchise les tuiles sans ajouter de bruit */
.summary > div::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--accent);
  opacity: 0.55;
}
.summary > div:hover { box-shadow: var(--shadow-lg); }
.summary strong {
  font-size: 1.6rem;
  font-weight: 720;
  letter-spacing: -0.03em;
  margin-top: var(--s1);
}

/* ===== Formulaires ===== */
input, select, button { transition: border-color var(--fast), box-shadow var(--fast), background var(--fast), transform var(--fast); }
input:hover, select:hover { border-color: var(--border-strong); }
button { border-radius: var(--radius-sm); }
button:not(:disabled):active { transform: translateY(1px); }
button[type="submit"] {
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
}
button[type="submit"]:hover { background: var(--accent-hover); filter: none; }

/* ===== Tableaux ===== */
.table-wrap { padding: var(--s2) var(--s4) var(--s4); }
thead th {
  background: var(--surface);
  z-index: 2;
  padding-top: var(--s3);
  padding-bottom: var(--s2);
  font-size: 0.68rem;
  letter-spacing: 0.05em;
}
tbody tr { transition: background var(--fast); }
tbody tr:hover td { background: var(--surface-2); }
tbody tr:last-child td { border-bottom: none; }
td { padding: 0.6rem; }
tr.clickable-row td, tr.prospect-row td { cursor: pointer; }
tr.clickable-row:hover .title-main, tr.prospect-row:hover .title-main { color: var(--accent); }

.badge {
  display: inline-block;
  padding: 0.05rem 0.4rem;
  border-radius: 999px;
  background: var(--accent-weak);
  color: var(--accent);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.02em;
}

button.delete {
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-muted);
  border-radius: var(--radius-sm);
  width: 26px; height: 26px;
  line-height: 1;
  cursor: pointer;
  opacity: 0;
}
tr:hover button.delete, button.delete:focus-visible { opacity: 1; }
button.delete:hover { background: var(--neg-weak); color: var(--neg); border-color: color-mix(in srgb, var(--neg) 30%, transparent); }

.ind-btn {
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text-muted);
  border-radius: 5px;
  font-size: 0.62rem;
  padding: 0 0.25rem;
  margin-left: 0.3rem;
  cursor: pointer;
}
.ind-btn:hover { color: var(--accent); border-color: var(--accent); }

/* ===== Squelettes de chargement ===== */
/* Une page qui se dessine paraît plus rapide qu'un mot « Chargement… ». */
.skel-row td { padding: 0.7rem 0.6rem; }
.skel {
  display: block;
  height: 11px;
  border-radius: 6px;
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 37%, var(--surface-2) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.3s ease-in-out infinite;
}
.skel.w40 { width: 40%; }
.skel.w60 { width: 60%; }
.skel.w80 { width: 80%; }
.skel + .skel { margin-top: 6px; }
@keyframes shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* ===== Toasts ===== */
#toasts {
  position: fixed;
  right: var(--s5);
  bottom: var(--s5);
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  z-index: 300;
  pointer-events: none;
}
.toast {
  display: flex;
  align-items: center;
  gap: var(--s2);
  padding: 0.6rem 0.85rem;
  border-radius: var(--radius-sm);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  font-size: 0.85rem;
  font-weight: 550;
  animation: toast-in 0.26s var(--ease);
  pointer-events: auto;
}
.toast.leaving { animation: toast-out 0.2s var(--ease) forwards; }
.toast::before { content: "✓"; color: var(--pos); font-weight: 800; }
.toast.err::before { content: "!"; color: var(--neg); }
.toast.err { border-color: color-mix(in srgb, var(--neg) 35%, var(--border)); }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px) scale(0.97); } }
@keyframes toast-out { to { opacity: 0; transform: translateY(4px); } }

/* ===== Modales ===== */
.modal-overlay {
  backdrop-filter: blur(4px);
  animation: fade 0.18s var(--ease);
}
.modal {
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-pop);
  animation: modal-in 0.24s var(--ease);
}
@keyframes fade { from { opacity: 0; } }
@keyframes modal-in { from { opacity: 0; transform: translateY(10px) scale(0.985); } }
.modal-close { transition: background var(--fast), transform var(--fast); }
.modal-close:hover { transform: rotate(90deg); }

/* ===== Divers ===== */
.recap-empty { color: var(--text-muted); text-align: center; padding: var(--s5) var(--s4); }
.import-errors { margin: var(--s2) 0 0; padding-left: 1.2rem; color: var(--text-muted); font-size: var(--fs-sm); }
.import-errors li { margin: 2px 0; }
.filter-panel { padding: var(--s4) var(--s5); }
.f-item { display: flex; flex-direction: column; gap: 0.3rem; font-size: 0.76rem; color: var(--text-muted); font-weight: 550; }
.tabs .tab { transition: color var(--fast), border-color var(--fast); }
.score-pill { transition: transform var(--fast); }
tr:hover .score-pill { transform: scale(1.06); }

@media (max-width: 720px) {
  body { padding: 0 var(--s3) var(--s5); }
  h1 { font-size: 1.4rem; }
  .summary > div { min-width: 140px; }
  #toasts { right: var(--s3); left: var(--s3); bottom: var(--s3); }
}

/* Grille KPI : `flex:1` + wrap laissait une tuile seule sur sa ligne.
   auto-fit répartit les tuiles à égalité quel qu'en soit le nombre. */
.summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--s3);
  margin-bottom: var(--s5);
}
.summary > div {
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.summary strong {
  font-size: 1.45rem;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Le P&L porte sa variation entre parenthèses : on la met en second niveau
   plutôt que de la laisser casser la ligne du montant. */
.summary strong small {
  display: block;
  font-size: 0.82rem;
  font-weight: 600;
  opacity: 0.85;
  margin-top: 2px;
}

/* Vues du screener */
.view-tabs { display: flex; gap: var(--s1); margin-bottom: var(--s3); flex-wrap: wrap; }
.view-tabs button {
  padding: 0.35rem 0.8rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-muted);
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
}
.view-tabs button:hover { color: var(--text); border-color: var(--border-strong); }
.view-tabs button.active { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }

/* ===== Screener : navigation par objectif ===== */
.mode-tabs { display: flex; gap: var(--s2); margin-bottom: var(--s3); flex-wrap: wrap; }
.mode-tabs button {
  padding: 0.5rem 1rem;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  color: var(--text-muted);
  font-size: 0.9rem;
  font-weight: 640;
  cursor: pointer;
  transition: color var(--fast), border-color var(--fast), background var(--fast);
}
.mode-tabs button:hover { color: var(--text); border-color: var(--border-strong); }
.mode-tabs button.active { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }

.mode-blurb {
  margin: 0 0 var(--s3);
  font-size: 0.86rem;
  line-height: 1.5;
  color: var(--text-muted);
}
.mode-blurb b { color: var(--text); font-weight: 640; }
.mode-blurb i { color: var(--text-muted); }

.preset-chips { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; margin-bottom: var(--s3); }
.preset-chips:empty { display: none; }
.chips-label { font-size: 0.76rem; color: var(--text-muted); font-weight: 600; }
.chip-preset {
  padding: 0.28rem 0.7rem;
  border: 1px dashed var(--border-strong);
  border-radius: 999px;
  background: transparent;
  color: var(--text);
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
}
.chip-preset:hover { border-style: solid; border-color: var(--accent); }
.chip-preset.on { background: var(--accent); border-color: var(--accent); border-style: solid; color: var(--on-accent); }

.adv-filters { margin-bottom: var(--s3); }
.adv-filters > summary {
  cursor: pointer;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text-muted);
  list-style-position: inside;
  user-select: none;
}
.adv-filters > summary:hover { color: var(--text); }
.adv-filters[open] > summary { margin-bottom: var(--s3); }

/* Croissance portée surtout par les attentes analystes (à tempérer) */
.soft-mark {
  margin-left: 0.3rem;
  color: var(--warn);
  font-size: 0.9rem;
  font-weight: 700;
  cursor: help;
}

/* PEG reconstruit à partir des attentes analystes (et non du bénéfice passé) */
.peg-fwd {
  font-size: 0.68rem;
  color: var(--text-muted);
  font-style: italic;
  cursor: help;
}

/* ============================================================
   REFONTE — navigation latérale, hero, sparklines
   ============================================================ */

body.has-sidebar {
  max-width: none;
  margin: 0;
  padding: 0 var(--s5) var(--s6) calc(232px + var(--s5));
}
/* La transition ne s'active qu'après le 1er rendu (classe posée en JS) : sinon
   un léger glissement se produirait au chargement quand l'état replié est lu. */
body.nav-ready { transition: padding-left var(--med); }
body.has-sidebar.nav-collapsed { padding-left: calc(66px + var(--s4)); }
body.has-sidebar > .market-header { max-width: 1500px; margin: 0 auto; }
body.has-sidebar > *:not(.sidebar):not(#toasts):not(.modal-overlay) { max-width: 1500px; margin-left: auto; margin-right: auto; }

.sidebar {
  position: fixed;
  left: 0; top: 0; bottom: 0;
  width: 232px;
  padding: var(--s4) var(--s3);
  background: var(--surface);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  z-index: 50;
  overflow-y: auto;
  transition: width var(--med);
}
.sidebar.collapsed { width: 66px; padding-left: var(--s2); padding-right: var(--s2); }

/* Pied de sidebar : compte connecté + déconnexion */
.sb-foot { margin-top: auto; padding-top: var(--s3); border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: var(--s2); }
.sb-user {
  font-size: 0.74rem; color: var(--text-muted); padding: 0 var(--s2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sb-logout {
  display: flex; align-items: center; gap: var(--s2);
  background: none; border: none; cursor: pointer; width: 100%;
  padding: 0.45rem var(--s2); border-radius: 8px;
  color: var(--text-muted); font-size: 0.84rem; font-weight: 550; text-align: left;
}
.sb-logout svg { width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.sb-logout:hover { background: var(--surface-2); color: var(--neg); }
.sidebar.collapsed .sb-user { display: none; }
.sidebar.collapsed .sb-logout span { display: none; }
.sidebar.collapsed .sb-logout { justify-content: center; }

.sb-head { display: flex; align-items: center; gap: var(--s2); padding: 0 var(--s2) var(--s3); border-bottom: 1px solid var(--border); }
.sb-logo {
  width: 26px; height: 26px; flex: none;
  border-radius: 8px;
  /* Dégradé dérivé de l'accent (le violet en dur datait du thème bleu). */
  background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 55%, var(--c4)));
  box-shadow: 0 3px 10px -2px color-mix(in srgb, var(--accent) 60%, transparent);
}
.sb-title { font-weight: 750; letter-spacing: -0.02em; font-size: 0.98rem; }
.sidebar.collapsed .sb-title { display: none; }
.sb-toggle {
  margin-left: auto; flex: none;
  width: 24px; height: 24px;
  display: grid; place-items: center;
  border: none; background: transparent; cursor: pointer;
  border-radius: 6px; color: var(--text-muted);
}
.sb-toggle:hover { background: var(--surface-2); color: var(--text); }
.sb-toggle svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; transition: transform var(--med); }
.sidebar.collapsed .sb-toggle { margin: 0 auto; }
.sidebar.collapsed .sb-toggle svg { transform: rotate(180deg); }

/* Densité : 16 entrées + 4 intitulés + en-tête + pied débordaient sur un écran
   de portable (~768 px). Interlignes resserrés pour que tout tienne sans scroll. */
.sb-group + .sb-group { margin-top: var(--s3); }
.sb-group-label {
  font-size: 0.63rem;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  font-weight: 700;
  color: var(--text-muted);
  padding: 0 var(--s2) var(--s1);
  opacity: 0.75;
}
.sidebar.collapsed .sb-group-label { opacity: 0; height: 8px; overflow: hidden; }

.sidebar nav a {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: 0.3rem var(--s2);
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  text-decoration: none;
  font-size: 0.85rem;
  font-weight: 600;
  white-space: nowrap;
  transition: background var(--fast), color var(--fast);
}
.sidebar nav a svg {
  width: 17px; height: 17px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}
.sidebar nav a:hover { background: var(--surface-2); color: var(--text); }
/* Item actif : surlignage gris clair neutre (pas de teinte verte) ; le repère
   vert reste porté par la barre ::before en accent sapin. */
.sidebar nav a.active { background: var(--surface-3); color: var(--text); font-weight: 600; }
.sidebar nav a.active::before {
  content: ""; position: absolute; left: -var(--s3); left: -12px;
  top: 50%; transform: translateY(-50%);
  width: 3px; height: 18px; border-radius: 0 3px 3px 0;
  background: var(--accent);
}
.sidebar.collapsed nav a { justify-content: center; padding: 0.55rem 0; }
.sidebar.collapsed nav a span { display: none; }

@media (max-width: 900px) {
  .sidebar { width: 66px; padding-left: var(--s2); padding-right: var(--s2); }
  .sidebar .sb-title, .sidebar nav a span, .sidebar .sb-toggle { display: none; }
  .sidebar nav a { justify-content: center; }
  .sidebar .sb-group-label { opacity: 0; height: 8px; overflow: hidden; }
  body.has-sidebar { padding-left: calc(66px + var(--s3)); padding-right: var(--s3); }
}

/* ===== Hero ===== */
.hero {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s5);
  flex-wrap: wrap;
  padding: var(--s5) var(--s5) var(--s4);
  margin-bottom: var(--s4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  position: relative;
  overflow: hidden;
}
.hero::after {
  content: "";
  position: absolute; inset: 0;
  background: radial-gradient(90% 140% at 100% 0%, var(--accent-weak), transparent 55%);
  pointer-events: none;
}
.hero-label { font-size: 0.76rem; font-weight: 650; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.07em; }
/* La valeur héros en CHASSE FIXE : c'est le geste signature du thème.
   Un montant de portefeuille est une mesure, pas un titre — en monospace il se
   lit chiffre par chiffre, et l'animation de compteur (`animateValue`, ui.js)
   ne fait plus danser la largeur du nombre à chaque image. */
.hero-value {
  font-family: var(--font-mono);
  font-size: var(--fs-display);
  font-weight: var(--fw-medium);
  letter-spacing: -0.045em;
  line-height: 1.02;
  margin: var(--s2) 0 var(--s1);
  font-variant-numeric: tabular-nums;
}
.hero-delta { display: flex; align-items: center; gap: var(--s2); font-size: 0.92rem; font-weight: 650; }
.hero-delta .chip {
  padding: 0.12rem 0.45rem;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 700;
}
.hero-delta .chip.pos { background: var(--pos-weak); color: var(--pos); }
.hero-delta .chip.neg { background: var(--neg-weak); color: var(--neg); }
.hero-delta .muted { color: var(--text-muted); font-weight: 500; }
.hero-side {
  flex: 1 1 340px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(138px, 1fr));
  gap: var(--s3);
  position: relative; z-index: 1;
}
/* Rembourrage resserré depuis le passage des chiffres en chasse fixe : le
   monospace est ~15 % plus large que la pile système, et « 11 142,15 € »
   passait à la ligne en coupant son symbole monétaire du nombre. */
.hero-stat {
  background: color-mix(in srgb, var(--surface-2) 65%, transparent);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--s3);
  transition: border-color var(--fast), transform var(--fast);
}
.hero-stat:hover { border-color: var(--border-strong); transform: translateY(-1px); }
/* Deux étiquettes sur cinq tiennent sur deux lignes (« Rendement dividendes »,
   « Rendement global ») : leurs chiffres descendaient d'une ligne et la rangée
   de KPI cessait d'avoir une ligne de base commune — c'est ce qui la faisait
   lire comme cinq cartes empilées au lieu d'une rangée. On réserve deux lignes
   à TOUTES, plutôt que de raccourcir les libellés qui disent ce qu'ils disent. */
.hero-stat .hero-label { font-size: var(--fs-xs); display: block; min-height: 2.4em; }
.hero-stat b {
  display: block;
  font-family: var(--font-mono);
  font-size: 1.02rem;
  font-weight: var(--fw-medium);
  letter-spacing: -0.045em;
  margin-top: 4px;
  font-variant-numeric: tabular-nums;
}
.hero-main { position: relative; z-index: 1; align-self: flex-start; }
h1, .table-title { font-family: var(--font-display); letter-spacing: -0.02em; }

/* Chasse fixe partout où l'élément EST un nombre ou un code (ticker, raccourci,
   graduation d'axe). Volontairement PAS sur les `td` : les tableaux du
   portefeuille ont 19 colonnes, la chasse fixe les ferait déborder — ils
   s'alignent déjà par `font-variant-numeric: tabular-nums`. */
.mmap-sym, .mmap-day, .mono-pill, .traj-perf, .rot-tick, .ini-tick,
kbd, .chart-sym, .sd-tile-value, .reg-tile-value, .rk-v, .acct-v {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}
@media (max-width: 720px) { .hero { padding: var(--s4); } }

/* Trajectoire du portefeuille : aire remplie (moment « héros ») */
.traj-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: var(--s4) var(--s5) var(--s3);
  margin-bottom: var(--s4); box-shadow: var(--shadow); overflow: hidden;
}
.traj-loading { color: var(--text-muted); font-size: var(--fs-sm); padding: var(--s5) 0; text-align: center; }
.traj-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s3); flex-wrap: wrap; }
.traj-label { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.07em; color: var(--text-muted); font-weight: var(--fw-semibold); }
.traj-perf { font-family: var(--font-display); font-size: var(--fs-xl); font-weight: var(--fw-semibold); letter-spacing: -0.02em; font-variant-numeric: tabular-nums; margin-top: 3px; }
.traj-perf.pos { color: var(--pos); } .traj-perf.neg { color: var(--neg); }
.traj-perf span { font-size: var(--fs-xs); font-weight: 500; color: var(--text-muted); margin-left: var(--s2); letter-spacing: 0; }
.traj-ranges { display: flex; gap: 4px; }
.traj-range { font-size: var(--fs-xs); font-weight: 600; padding: 0.25rem 0.6rem; border-radius: var(--radius-sm); border: 1px solid var(--border); background: var(--surface-2); color: var(--text-muted); cursor: pointer; transition: color var(--fast), border-color var(--fast), background var(--fast); }
.traj-range:hover { border-color: var(--border-strong); color: var(--text); }
.traj-range.on { background: var(--accent-weak); border-color: color-mix(in srgb, var(--accent) 40%, transparent); color: var(--accent); }
.traj-svg { width: 100%; height: 150px; display: block; margin-top: var(--s2); }

/* Carte du portefeuille (treemap : taille = poids, couleur = variation du jour) */
.mmap-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: var(--s4) var(--s5) var(--s5);
  margin-bottom: var(--s4); box-shadow: var(--shadow);
}
.mmap-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3); margin-bottom: var(--s3); flex-wrap: wrap; }
.mmap-head h2 { font-size: var(--fs-lg); margin: 0; }
.mmap-hint { font-size: var(--fs-xs); color: var(--text-muted); }
.mmap { position: relative; width: 100%; height: clamp(240px, 33vh, 360px); }
.mmap-tile {
  position: absolute; border: 1.5px solid var(--surface); border-radius: 6px;
  padding: 5px 7px; overflow: hidden; cursor: pointer; text-align: left;
  display: flex; flex-direction: column; justify-content: space-between;
  color: var(--text); transition: filter var(--fast), transform var(--fast);
}
.mmap-tile:hover { filter: brightness(1.14); z-index: 2; }
.mmap-sym { font-family: var(--font-display); font-weight: var(--fw-semibold); font-size: 0.9rem; letter-spacing: -0.01em; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35); line-height: 1.1; }
.mmap-sym.sm { font-size: 0.66rem; }
.mmap-day { font-size: 0.72rem; font-weight: 600; opacity: 0.9; font-variant-numeric: tabular-nums; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35); }
@media (max-width: 720px) { .mmap { height: clamp(280px, 50vh, 420px); } }

/* Monogramme coloré par société (ancrage visuel dans les tableaux) */
.title-row { display: flex; align-items: center; gap: var(--s3); }
.title-txt { min-width: 0; }
.mono-pill {
  flex: none; width: 30px; height: 30px; border-radius: 8px;
  display: grid; place-items: center;
  font-family: var(--font-display); font-weight: var(--fw-semibold);
  font-size: 0.72rem; letter-spacing: -0.02em;
  border: 1px solid color-mix(in srgb, currentColor 28%, transparent);
}

/* ===== Sparklines ===== */
.spark { width: 88px; height: 26px; display: block; }
td.spark-cell { width: 96px; padding-right: var(--s2); }
tr:hover .spark { filter: saturate(1.35); }

.spark-head { width: 96px; }

/* ============================================================
   MODALES — refonte
   ============================================================ */

.modal-overlay {
  background: color-mix(in srgb, #05070c 62%, transparent);
  align-items: center;
  padding: var(--s5);
}
@media (max-width: 720px) { .modal-overlay { padding: 0; align-items: flex-end; } }

.modal {
  /* Corps scrollable, en-tête figé : sur une fiche longue le titre restait
     inaccessible dès qu'on descendait. */
  display: flex;
  flex-direction: column;
  max-height: 88vh;
  max-width: 900px;
  padding: 0;
  border: 1px solid var(--border-strong);
  overflow: hidden;
}
.modal.modal-chart { max-width: 960px; }
@media (max-width: 720px) {
  .modal { max-height: 92vh; border-radius: var(--radius-lg) var(--radius-lg) 0 0; }
}

.modal-content {
  overflow-y: auto;
  padding: var(--s5);
  scrollbar-width: thin;
}
.modal-content::-webkit-scrollbar { width: 10px; }
.modal-content::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 99px; border: 3px solid var(--surface); }

.modal-close {
  top: var(--s4);
  right: var(--s4);
  z-index: 4;
  width: 32px; height: 32px;
  background: color-mix(in srgb, var(--surface-2) 85%, transparent);
  backdrop-filter: blur(8px);
  border: 1px solid var(--border);
  color: var(--text-muted);
}
.modal-close:hover { background: var(--surface-3); color: var(--text); }

/* En-tête de fiche : collant, avec un fond opaque pour ne pas laisser
   le contenu défiler visiblement dessous. */
.recap-header {
  position: sticky;
  top: calc(var(--s5) * -1);
  z-index: 3;
  margin: calc(var(--s5) * -1) calc(var(--s5) * -1) var(--s4);
  padding: var(--s4) var(--s5) var(--s3);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  align-items: flex-start;
  padding-right: 3.4rem;
}
.recap-header::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -14px; height: 14px;
  background: linear-gradient(var(--surface), transparent);
  pointer-events: none;
}
.recap-header h2 { font-size: 1.28rem; font-weight: 730; letter-spacing: -0.025em; }
.recap-sub { font-size: 0.8rem; }

.modal .chart-title {
  position: sticky;
  top: calc(var(--s5) * -1);
  z-index: 3;
  margin: calc(var(--s5) * -1) calc(var(--s5) * -1) var(--s3);
  padding: var(--s4) 3.4rem var(--s3) var(--s5);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  font-size: 1.2rem;
  font-weight: 730;
  letter-spacing: -0.02em;
}
.chart-sym { color: var(--text-muted); font-weight: 550; font-size: 0.82rem; margin-left: var(--s2); }
.chart-perf { font-weight: 730; font-size: 0.95rem; margin-left: var(--s3); font-variant-numeric: tabular-nums; }

/* Cartes : la grille rend mieux en 2 colonnes serrées qu'en 300px minimum */
.recap-cards { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: var(--s3); margin-top: var(--s3); }
.recap-card {
  background: var(--surface-2);
  border-color: transparent;
  box-shadow: none;
  padding: var(--s3) var(--s4);
  border-radius: var(--radius);
  transition: background var(--fast);
}
.recap-card:hover { background: var(--surface-3); }
.recap-card h3 {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  margin-bottom: var(--s2);
}
.recap-item {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s3);
  padding: 0.3rem 0;
  font-size: 0.84rem;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 55%, transparent);
}
.recap-item:last-child { border-bottom: none; }
.recap-label { color: var(--text-muted); }
.recap-value { font-weight: 650; font-variant-numeric: tabular-nums; text-align: right; }

/* ============================================================
   THÈME FORÇABLE — le media query seul ne laisse aucun choix.
   [data-theme] doit gagner dans les deux sens.
   ============================================================ */
:root[data-theme="dark"] {
  --bg: #0d0f12;
  --bg-tint: radial-gradient(120% 90% at 50% -10%, rgba(217, 169, 78, 0.09), transparent 60%);
  --surface: #16181b; --surface-2: #1d2126; --surface-3: #262b31;
  --text: #e9edf1; --text-muted: #949fac;
  --border: #262b31; --border-strong: #39414a;
  --accent: #d9a94e; --accent-hover: #eec473; --accent-weak: rgba(217, 169, 78, 0.16);
  --on-accent: #0d0f12;
  --pos: #35c07f; --pos-weak: rgba(53, 192, 127, 0.15);
  --neg: #f0685e; --neg-weak: rgba(240, 104, 94, 0.14);
  --warn: #e0973a;
  /* Mêmes 8 fentes catégorielles, re-pas-à-pas pour le fond sombre — validées
     comme un JEU contre #16181b, pas éclaircies une à une. */
  --c1: #4d80e2; --c2: #d7701e; --c3: #149ab6; --c4: #9a5fdb;
  --c5: #e05f9b; --c6: #4f91d8; --c7: #b57c31; --c8: #7b6ade;
  --c-other: #7f8a97; --c9: #8a95a3; --c10: #a08c68;
  --shadow-sm: 0 1px 2px rgba(0,0,0,.4); --shadow: 0 1px 3px rgba(0,0,0,.5);
  --shadow-lg: 0 12px 32px -8px rgba(0,0,0,.7); --shadow-pop: 0 20px 50px -12px rgba(0,0,0,.8);
  color-scheme: dark;
}
/* Forcer le CLAIR sur une machine en sombre : il faut réécrire toutes les
   valeurs, sinon le media query ci-dessus gagne encore. */
:root[data-theme="light"] {
  --bg: #eceff3;
  --bg-tint: radial-gradient(120% 90% at 50% -10%, rgba(138, 101, 18, 0.05), transparent 60%);
  --surface: #ffffff; --surface-2: #f4f6f9; --surface-3: #e6ebf1;
  --text: #10151b; --text-muted: #5b6875;
  --border: #dce2e9; --border-strong: #bcc7d3;
  --accent: #8a6512; --accent-hover: #6d500a; --accent-weak: rgba(138, 101, 18, 0.12);
  --on-accent: #fdfbf6;
  --pos: #0d7a45; --pos-weak: rgba(13, 122, 69, 0.12);
  --neg: #c02b26; --neg-weak: rgba(192, 43, 38, 0.11);
  --warn: #9a5c08;
  --c1: #2b62c9; --c2: #dd6a12; --c3: #0f92ae; --c4: #8a4fc0;
  --c5: #d95093; --c6: #4a92dc; --c7: #b5732f; --c8: #6f5bd6;
  --c-other: #7b8794; --c9: #6b7684; --c10: #8d7a5c;
  --shadow-sm: 0 1px 2px rgba(16,24,40,.05); --shadow: 0 1px 3px rgba(16,24,40,.07), 0 1px 2px rgba(16,24,40,.04);
  --shadow-lg: 0 12px 32px -8px rgba(16,24,40,.18), 0 4px 10px rgba(16,24,40,.06);
  --shadow-pop: 0 20px 50px -12px rgba(16,24,40,.28);
  color-scheme: light;
}

/* ===== Palette de commandes ===== */
.pal-overlay {
  position: fixed; inset: 0; z-index: 400;
  background: color-mix(in srgb, #05070c 55%, transparent);
  backdrop-filter: blur(5px);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 12vh var(--s4) var(--s4);
  animation: fade 0.14s var(--ease);
}
.pal {
  width: 100%; max-width: 600px;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-pop);
  overflow: hidden;
  animation: modal-in 0.2s var(--ease);
}
.pal-input-row { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) var(--s4); border-bottom: 1px solid var(--border); }
.pal-icon { width: 16px; height: 16px; flex: none; fill: none; stroke: var(--text-muted); stroke-width: 2; stroke-linecap: round; }
#pal-input { flex: 1; border: none; background: none; padding: 0.35rem 0; font-size: 1rem; min-height: 0; }
#pal-input:focus { outline: none; box-shadow: none; }
.pal-list { max-height: 46vh; overflow-y: auto; padding: var(--s2); }
.pal-item {
  display: grid; grid-template-columns: 72px 1fr auto;
  align-items: center; gap: var(--s3);
  padding: 0.5rem var(--s3);
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 0.88rem;
}
.pal-item.sel { background: var(--accent-weak); }
.pal-item.sel .pal-label { color: var(--accent); }
.pal-kind {
  font-size: 0.62rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--text-muted); background: var(--surface-2);
  padding: 0.1rem 0.35rem; border-radius: 999px; text-align: center;
}
.pal-label { font-weight: 640; }
.pal-sub { color: var(--text-muted); font-size: 0.76rem; text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 260px; }
.pal-empty, .pal-foot { color: var(--text-muted); font-size: 0.78rem; }
.pal-empty { padding: var(--s5); text-align: center; }
.pal-foot { padding: var(--s2) var(--s4); border-top: 1px solid var(--border); display: flex; gap: var(--s1); align-items: center; }
kbd {
  font-family: inherit; font-size: 0.68rem; font-weight: 650;
  padding: 0.08rem 0.32rem; border-radius: 5px;
  background: var(--surface-2); border: 1px solid var(--border);
  color: var(--text-muted);
}

/* ===== Header : déclencheur de recherche + thème ===== */
.hdr-actions { display: flex; align-items: center; gap: var(--s2); }
/* Déclencheur de recherche : dessiné comme un CHAMP, pas comme un bouton.
   L'affordance fait tout le travail — on tape dans les champs, on ne devine pas
   les boutons. Il occupe le centre du bandeau et grandit avec la fenêtre. */
.hdr-search {
  flex: 1 1 320px;
  max-width: 460px;
  display: flex; align-items: center; gap: var(--s2);
  padding: 0.34rem var(--s2) 0.34rem var(--s3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-muted);
  font-size: 0.8rem; font-weight: 500;
  text-align: left;
  cursor: text; min-height: 0;
  transition: border-color var(--fast), box-shadow var(--fast), color var(--fast);
}
.hdr-search-txt { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hdr-search:hover, .hdr-search:focus-visible {
  border-color: var(--accent);
  color: var(--text);
  box-shadow: 0 0 0 3px var(--accent-weak);
}
.hdr-search svg { width: 15px; height: 15px; flex: none; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.hdr-search kbd { flex: none; }
/* Sous 900px, le bandeau passe sur deux lignes : la recherche prend toute la
   largeur de la seconde plutôt que de se réduire à une pastille illisible. */
@media (max-width: 900px) {
  .hdr-search { order: 3; flex-basis: 100%; max-width: none; }
}
.theme-btn {
  width: 28px; height: 28px; flex: none;
  display: grid; place-items: center;
  border: 1px solid var(--border); border-radius: 999px;
  background: var(--surface); color: var(--text-muted);
  cursor: pointer; min-height: 0;
}
.theme-btn:hover { color: var(--text); border-color: var(--border-strong); }
.theme-btn svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* ============================================================
   MODALE : dévoilement progressif + en-têtes de page
   ============================================================ */

/* Bandeau essentiel : 4 chiffres lisibles valent mieux que 48 illisibles */
.recap-key {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: var(--s2);
  margin: var(--s4) 0;
  padding: var(--s3) 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.rk { display: flex; flex-direction: column; gap: 1px; }
.rk-l { font-size: 0.66rem; font-weight: 650; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); }
.rk-v { font-size: 1.3rem; font-weight: 730; letter-spacing: -0.028em; font-variant-numeric: tabular-nums; line-height: 1.15; }
.rk-s { font-size: 0.76rem; font-weight: 640; }

/* Onglets : une famille de chiffres à la fois */
.rtabs { display: flex; gap: var(--s1); flex-wrap: wrap; margin: var(--s4) 0 var(--s3); border-bottom: 1px solid var(--border); }
.rtabs button {
  border: none; background: none; cursor: pointer;
  padding: 0.4rem 0.7rem;
  margin-bottom: -1px;
  border-bottom: 2px solid transparent;
  color: var(--text-muted);
  font-size: 0.82rem; font-weight: 640;
  border-radius: 0;
}
.rtabs button:hover { color: var(--text); }
.rtabs button.active { color: var(--accent); border-bottom-color: var(--accent); }

/* Une seule famille affichée : la carte occupe la largeur, en 2 colonnes de lignes */
#rpanel { grid-template-columns: 1fr; }
#rpanel .recap-card { background: none; padding: 0; }
#rpanel .recap-card h3 { display: none; }
/* Exception : la carte ROIC/WACC n'est pas la seule famille de l'onglet
   Rentabilité (marges/ROE/ROA au-dessus), son titre reste donc utile. */
#rpanel .recap-card.wide h3 { display: block; margin-top: var(--s4); }
#rpanel .recap-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 0 var(--s5); }
#rpanel .recap-item { padding: 0.42rem 0; font-size: 0.86rem; }
#rpanel .recap-value { font-size: 0.92rem; }

/* Résumé : pavé anglais de 1000+ caractères, replié à 3 lignes par défaut */
.recap-sum-wrap { margin: var(--s3) 0 0; }
.recap-summary {
  margin: 0;
  font-size: 0.84rem;
  line-height: 1.6;
  color: var(--text-muted);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.recap-summary.open { -webkit-line-clamp: unset; }
.link-btn {
  border: none; background: none; cursor: pointer;
  color: var(--accent); font-size: 0.78rem; font-weight: 650;
  padding: 0.25rem 0 0;
}
.link-btn:hover { text-decoration: underline; }

.recap-price { font-size: 1.35rem; font-weight: 740; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; white-space: nowrap; }
.recap-web { margin: var(--s2) 0 0; font-size: 0.78rem; }
.recap-actions { display: flex; gap: var(--s2); margin: var(--s4) 0 0; flex-wrap: wrap; }

/* ===== Boutons ===== */
.btn-primary, .btn-ghost {
  display: inline-flex; align-items: center; gap: var(--s2);
  padding: 0.45rem 0.9rem;
  border-radius: var(--radius-sm);
  font-weight: 640; font-size: 0.84rem;
  cursor: pointer; min-height: 36px;
  border: 1px solid transparent;
}
.btn-primary { background: var(--accent); color: var(--on-accent); box-shadow: var(--shadow-sm); }
.btn-primary:hover { background: var(--accent-hover); }
.btn-ghost { background: var(--surface-2); color: var(--text); border-color: var(--border); }
.btn-ghost:hover { background: var(--surface-3); }
.btn-primary svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; }

/* ===== En-tête de page ===== */
.page-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s4);
  flex-wrap: wrap;
  margin: var(--s5) 0 var(--s4);
}
.page-head h1 { margin: 0; }
.page-sub { color: var(--text-muted); font-size: 0.86rem; margin-top: 2px; }
.page-actions { display: flex; gap: var(--s2); flex-wrap: wrap; }

/* Formulaire déplacé en modale : il retrouve une grille propre */
.modal-form .modal-content { padding-top: var(--s3); }
.modal-form .form-section {
  background: none; border: none; box-shadow: none; padding: 0; margin: 0;
}
.modal-form form {
  display: grid !important;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--s3) !important;
  align-items: end;
}
.modal-form form button[type="submit"] { grid-column: 1 / -1; justify-self: end; min-width: 140px; }
.modal-form .modal-slot { padding-bottom: var(--s2); }

/* ===== Simulateur « et si » ===== */
.modal.modal-sim { max-width: 620px; }
.sim-inputs { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3); margin-bottom: var(--s4); }
.sim-key {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: var(--s3);
  padding: var(--s3) 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.sim-block { margin-top: var(--s4); }
.sim-block h4 {
  margin: 0 0 var(--s2);
  font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-muted);
  display: flex; justify-content: space-between; align-items: baseline; gap: var(--s3);
}
.sim-hint { text-transform: none; letter-spacing: 0; font-weight: 500; font-size: 0.68rem; opacity: 0.8; }

.sim-row {
  display: grid;
  grid-template-columns: 108px 1fr 48px 44px;
  align-items: center; gap: var(--s3);
  padding: 0.28rem 0;
  font-size: 0.82rem;
}
.sim-lab { color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Les deux barres se superposent : la pâle (avant) reste visible derrière la
   pleine (après), l'écart se lit d'un coup d'œil sans légende. */
.sim-track { position: relative; height: 8px; background: var(--surface-2); border-radius: 99px; overflow: hidden; }
.sim-fill { position: absolute; inset: 0 auto 0 0; border-radius: 99px; transition: width var(--med); }
.sim-fill.before { background: var(--accent); opacity: 0.24; }
.sim-fill.after { background: var(--accent); opacity: 0.9; height: 4px; top: 2px; }
.sim-pct { text-align: right; font-variant-numeric: tabular-nums; font-weight: 640; }
.sim-delta { text-align: right; font-variant-numeric: tabular-nums; font-size: 0.76rem; font-weight: 650; color: var(--text-muted); }
.sim-warn { margin: var(--s4) 0 0; font-size: 0.74rem; color: var(--text-muted); line-height: 1.5; }
@media (max-width: 560px) { .sim-inputs { grid-template-columns: 1fr; } .sim-row { grid-template-columns: 84px 1fr 44px 40px; } }

/* ---------- Échéancier obligataire (simulation jusqu'à l'échéance) ----------
   Variante de `.sim-row` : la 4e colonne porte ici un CUMUL (« cumul 12 480 $ »),
   pas un delta de 3 caractères — d'où une colonne large et alignée à droite.
   La barre suit le cumul encaissé, pas le coupon de l'année : sur un titre à
   30 ans, 30 barres identiques ne diraient rien, la montée du cumul si. */
.bond-yr { grid-template-columns: 132px 1fr 76px minmax(120px, 168px); }
.bond-yr-n { font-size: 0.68rem; opacity: 0.65; font-weight: 600; }
.bond-yr-cum {
  text-align: right; font-size: 0.7rem; color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* L'année du remboursement doit sauter aux yeux : c'est la seule ligne où le
   principal revient, et de loin le plus gros flux de tout l'échéancier. */
.bond-yr-princ { display: block; color: var(--accent); font-weight: 700; }

/* Les trois rendements côte à côte : c'est leur COMPARAISON qui informe
   (courant vs actuariel vs total sans réinvestissement), pas chacun isolé. */
.bond-yields { margin-top: var(--s3); border-top: 1px dashed var(--border); padding-top: var(--s3); }
.bond-yields .rk-v.accent { color: var(--accent); }

@media (max-width: 560px) {
  /* Sur téléphone le cumul passe sous la ligne plutôt que de tasser la barre */
  .bond-yr { grid-template-columns: 92px 1fr 68px; }
  .bond-yr .bond-yr-cum { grid-column: 1 / -1; text-align: left; padding-bottom: var(--s2); }
}

/* Jauge "pastèque" ROIC vs WACC : dégradé rouge → jaune → vert recentré sur
   le WACC (calculé en JS par indicateur), avec le ROIC positionné dessus. */
.wmelon { margin-top: var(--s3); padding-top: var(--s3); border-top: 1px dashed var(--border); }
.wmelon-track {
  position: relative;
  height: 10px;
  border-radius: 99px;
  overflow: visible;
}
.wmelon-wacc {
  position: absolute;
  top: -3px;
  bottom: -3px;
  width: 2px;
  background: var(--text);
  opacity: 0.55;
  transform: translateX(-50%);
}
.wmelon-thumb {
  position: absolute;
  top: 50%;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--surface);
  border: 3px solid var(--text);
  transform: translate(-50%, -50%);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
}
.wmelon-scale {
  position: relative;
  display: flex;
  justify-content: space-between;
  margin-top: var(--s2);
  font-size: 0.68rem;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
.wmelon-wacc-label {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
  white-space: nowrap;
}
.wmelon-caption {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s3);
  margin-top: var(--s4);
  font-size: 0.82rem;
  font-weight: 650;
}
.wmelon-caption .good { color: var(--pos); }
.wmelon-caption .mid { color: var(--warn); }
.wmelon-caption .bad { color: var(--neg); }
.wmelon-spread { color: var(--text-muted); font-weight: 500; font-size: 0.78rem; }

/* ===== Profil factoriel (onglet Indices de la fiche) ===== */
.factor-profile { display: flex; flex-direction: column; gap: 2px; }
.fp-row {
  display: grid;
  grid-template-columns: 172px 1fr 40px;
  align-items: center;
  gap: var(--s3);
  padding: 0.3rem 0;
}
.fp-lab { font-size: 0.84rem; font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fp-track { position: relative; height: 9px; background: var(--surface-2); border-radius: 99px; overflow: hidden; }
.fp-fill { position: absolute; inset: 0 auto 0 0; border-radius: 99px; transition: width var(--med); }
.fp-fill.hi { background: var(--pos); }
.fp-fill.mid { background: var(--accent); }
.fp-fill.lo { background: var(--neg); }
/* Repère de médiane (100) : la moitié de l'échelle 60–140 */
.fp-median { position: absolute; left: 50%; top: -2px; bottom: -2px; width: 1px; background: var(--text); opacity: 0.35; z-index: 1; }
.fp-val { text-align: right; font-variant-numeric: tabular-nums; font-weight: 700; font-size: 0.9rem; }
.fp-val.hi { color: var(--pos); }
.fp-val.mid { color: var(--text); }
.fp-val.lo { color: var(--neg); }
.fp-na { text-align: right; color: var(--text-muted); font-size: 0.8rem; cursor: help; }
.fp-drivers { grid-column: 1 / -1; display: flex; gap: var(--s4); flex-wrap: wrap; font-size: 0.72rem; margin: -0.15rem 0 0.35rem; padding-left: 172px; }
.fp-drivers .pos { color: var(--pos); }
.fp-drivers .neg { color: var(--neg); }
.fp-legend { margin: var(--s4) 0 0; font-size: 0.74rem; color: var(--text-muted); line-height: 1.5; }
@media (max-width: 560px) {
  .fp-row { grid-template-columns: 120px 1fr 36px; }
  .fp-drivers { padding-left: 0; }
}

/* Fourchette de risque du simulateur */
.sim-band { display: flex; flex-direction: column; gap: 2px; }
.sb-row { display: grid; grid-template-columns: 130px 1fr auto; align-items: baseline; gap: var(--s3); padding: 0.3rem 0; font-size: 0.82rem; }
.sb-k { color: var(--text-muted); }
.sb-v { font-variant-numeric: tabular-nums; font-weight: 650; }
.sb-d { font-variant-numeric: tabular-nums; font-size: 0.78rem; color: var(--text-muted); font-weight: 640; }
.sim-src { margin: var(--s2) 0 0; font-size: 0.72rem; color: var(--text-muted); }
.sim-coh {
  margin: var(--s3) 0 0; padding: var(--s2) var(--s3);
  background: var(--accent-weak); border-radius: var(--radius-sm);
  font-size: 0.78rem; line-height: 1.5;
}
@media (max-width: 560px) { .sb-row { grid-template-columns: 100px 1fr; } }

/* ============================================================
   VIVANT — le cours qui tique, le chiffre qui se pose
   ============================================================ */

/* Flash au changement de cours (rafraîchissement toutes les 15 s).
   Volontairement bref et discret : un tableau qui clignote en permanence
   fatigue et finit par masquer l'information au lieu de la servir. */
.px-cell { position: relative; border-radius: var(--radius-sm); }
.tick-up { animation: tick-up 1.1s var(--ease); }
.tick-down { animation: tick-down 1.1s var(--ease); }
@keyframes tick-up {
  0% { background: var(--pos-weak); color: var(--pos); }
  100% { background: transparent; }
}
@keyframes tick-down {
  0% { background: var(--neg-weak); color: var(--neg); }
  100% { background: transparent; }
}

.hero-value { font-variant-numeric: tabular-nums; }

/* ===== Typographie plus affirmée ===== */
body {
  font-family: "SF Pro Display", -apple-system, BlinkMacSystemFont, "Segoe UI Variable", "Segoe UI", Roboto, sans-serif;
  font-feature-settings: "kern" 1, "liga" 1, "cv11" 1;
  text-rendering: optimizeLegibility;
}
.hero-value, .rk-v, .sb-v, .summary strong {
  font-feature-settings: "tnum" 1, "kern" 1;
}

/* La barre latérale respire quand on l'ouvre */
.sidebar nav a svg { transition: transform var(--fast); }
.sidebar nav a:hover svg { transform: scale(1.12); }
.sb-logo { transition: transform var(--med), box-shadow var(--med); }
.sidebar:hover .sb-logo { transform: rotate(-6deg) scale(1.06); box-shadow: 0 5px 16px -2px color-mix(in srgb, var(--accent) 70%, transparent); }

/* États vides : centrés, aérés, avec une vraie phrase */
.recap-empty { max-width: 44ch; margin-inline: auto; line-height: 1.6; }

/* ============================================================
   MODE SOMBRE — refonte sur la règle d'élévation par la LUMINOSITÉ
   ============================================================
   Diagnostic mesuré : ma base était à L* 3,9 et mes cartes à L* 8,6, alors que
   la règle veut base ~10 et cartes 14-16. Tout était écrasé au fond de
   l'échelle. Et comme une ombre noire sur fond noir ne produit AUCUN contraste,
   il ne restait plus le moindre signal d'élévation : d'où l'effet plat.

   Corrigé : chaque palier gagne ~4 points de L*, l'élévation passe par la
   luminosité de surface (pas par l'ombre), et un liseré clair en haut des
   cartes simule la lumière — c'est ce qui remplace l'ombre en sombre.

   ⚠️ Les VALEURS de cette échelle vivent désormais en un seul endroit, en haut
   du fichier (§ Design tokens). Elles étaient recopiées ici et dans le bloc
   « THÈME FORÇABLE » : trois copies de la même échelle, dont deux se sont
   désynchronisées au fil des retouches. Il ne reste ici que les RÈGLES
   d'élévation, qui elles ne sont pas des couleurs. */

/* L'ombre ne servant à rien en sombre, l'élévation se joue autrement :
   un filet clair sur l'arête haute = la lumière qui frappe le bord. */
/* `:root:not([data-theme="light"])` : sans ce garde, forcer le thème CLAIR sur
   une machine réglée en sombre laissait les liserés blancs d'élévation posés
   sur des cartes blanches — un trait clair sur clair, invisible mais qui
   mangeait 1 px du haut de chaque carte. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) :is(.summary > div, .form-section, .table-wrap, .filter-panel, .chart-card,
  .hero, .modal, .pal, .toast, .sidebar) {
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
  }
  :root:not([data-theme="light"]) :is(.modal, .pal) { box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08), 0 24px 60px -12px rgba(0, 0, 0, 0.75); }
  :root:not([data-theme="light"]) .hero { background: linear-gradient(180deg, var(--surface-2), var(--surface)); }
  :root:not([data-theme="light"]) .recap-card { background: var(--surface-2); }
  :root:not([data-theme="light"]) .modal { background: var(--surface); }
  :root:not([data-theme="light"]) .sidebar { background: color-mix(in srgb, var(--surface) 70%, var(--bg)); }
}
:root[data-theme="dark"] .summary > div,
:root[data-theme="dark"] .form-section,
:root[data-theme="dark"] .table-wrap,
:root[data-theme="dark"] .filter-panel,
:root[data-theme="dark"] .chart-card,
:root[data-theme="dark"] .hero,
:root[data-theme="dark"] .toast,
:root[data-theme="dark"] .sidebar {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
:root[data-theme="dark"] .modal,
:root[data-theme="dark"] .pal {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08), 0 24px 60px -12px rgba(0, 0, 0, 0.75);
}
:root[data-theme="dark"] .hero { background: linear-gradient(180deg, var(--surface-2), var(--surface)); }
:root[data-theme="dark"] .recap-card { background: var(--surface-2); }
:root[data-theme="dark"] .sidebar { background: color-mix(in srgb, var(--surface) 70%, var(--bg)); }

/* Plus d'air : la densité était le second grief */
.table-wrap { padding: var(--s3) var(--s5) var(--s5); }
th, td { padding: 0.7rem 0.7rem; }
.hero { padding: var(--s6) var(--s6) var(--s5); }
.hero-value { font-size: 3.2rem; }

/* ===== Répartition par compte (Dashboard) ===== */
/* L'ancienne version était un tableau de 7 colonnes de chiffres nus. Ici chaque
   compte est une ligne-carte dont le FOND matérialise son poids : la hiérarchie
   se voit avant de se lire. */
.acct-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3); margin: var(--s5) 0 var(--s3); }
.acct-head h2 { margin: 0; font-size: 1.05rem; }
.acct-sub { color: var(--text-muted); font-size: 0.8rem; }
.acct-list { display: flex; flex-direction: column; gap: 2px; }
.acct {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 130px 150px 150px;
  align-items: center; gap: var(--s3);
  padding: 0.7rem var(--s4);
  border-radius: var(--radius-sm);
  background: var(--surface);
  overflow: hidden;
  font-variant-numeric: tabular-nums;
}
.acct-bar {
  position: absolute; inset: 0 auto 0 0;
  background: var(--accent-weak);
  border-right: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  pointer-events: none;
}
.acct > *:not(.acct-bar) { position: relative; z-index: 1; }
.acct-name { font-weight: 640; display: flex; align-items: baseline; gap: var(--s2); }
.acct-w { font-size: 0.72rem; color: var(--text-muted); font-weight: 550; }
.acct-v { text-align: right; font-weight: 650; }
.acct-p, .acct-d { text-align: right; font-weight: 640; }
.acct-p span, .acct-d span { display: block; font-size: 0.72rem; font-weight: 550; opacity: 0.75; }
.acct-d { color: var(--text-muted); }
.acct.total { background: var(--surface-2); font-weight: 700; margin-top: var(--s2); }
.acct.total .acct-name { font-weight: 720; }
@media (max-width: 780px) {
  .acct { grid-template-columns: 1fr auto; row-gap: var(--s1); }
  .acct-d { display: none; }
}

/* ============================================================
   HEADER — refonte
   ============================================================
   C'était une ligne de texte brut où les indices, le statut du marché et les
   actions se disputaient le même poids visuel. Les indices deviennent des
   pastilles lisibles, les places de marché des puces avec leur horaire EN HEURE
   LOCALE, et le tout tient sur une ligne. */
.market-header {
  padding: var(--s2) 0;
  gap: var(--s4);
  border-bottom: 1px solid var(--border);
  font-size: 0.78rem;
}
.indices { gap: var(--s1); }
.idx {
  display: inline-flex; align-items: baseline; gap: 0.35rem;
  padding: 0.22rem 0.5rem;
  border-radius: var(--radius-sm);
  transition: background var(--fast);
}
.idx:hover { background: var(--surface-2); }
.idx b { font-size: 0.7rem; font-weight: 650; color: var(--text-muted); margin: 0; letter-spacing: -0.01em; }
.idx .v { font-weight: 640; font-variant-numeric: tabular-nums; }
.idx .c { font-size: 0.72rem; font-weight: 650; font-variant-numeric: tabular-nums; }

/* Places de marché */
.market-status { display: flex; gap: var(--s1); white-space: nowrap; }
.mk {
  display: inline-flex; align-items: center; gap: 0.35rem;
  padding: 0.22rem 0.55rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  font-size: 0.72rem;
  color: var(--text-muted);
  cursor: default;
}
.mk b { font-weight: 640; color: var(--text-muted); }
.mk.is-open { border-color: color-mix(in srgb, var(--accent) 40%, transparent); background: var(--accent-weak); }
/* Le NOM de la place reste en pleine encre : mesuré, le laiton clair tombe à
   3,96:1 sur son propre fond pâle, sous le seuil AA d'un texte de 0,72 rem.
   C'est le point pulsé qui porte le statut (3,96:1 suffit pour un élément
   non textuel, seuil 3:1), pas le mot « New York ». */
.mk.is-open b { color: var(--text); }
.mk-h { opacity: 0.7; font-variant-numeric: tabular-nums; }
.mk .dot { width: 6px; height: 6px; margin: 0; }

/* ============================================================
   TABLEAUX — lisibilité
   ============================================================
   Griefs : trop de colonnes de chiffres identiques, l'oeil perd sa ligne, et
   rien ne distingue une donnée importante d'une donnée de contexte. */
.table-wrap table { font-size: 0.84rem; }

/* Zébrure très légère : suffit à tenir la ligne sur 18 colonnes, sans quadriller */
tbody tr:nth-child(even) td { background: color-mix(in srgb, var(--surface-2) 45%, transparent); }
tbody tr:hover td { background: var(--surface-2); }
tbody tr:nth-child(even):hover td { background: var(--surface-2); }

/* Le titre reste lisible et accroché à gauche quand on défile horizontalement */
.table-wrap td.title-cell:first-child,
.table-wrap th:first-child {
  position: sticky; left: 0; z-index: 1;
  background: var(--surface);
  box-shadow: 1px 0 0 var(--border);
}
tbody tr:nth-child(even) td.title-cell:first-child { background: color-mix(in srgb, var(--surface-2) 45%, var(--surface)); }
tbody tr:hover td.title-cell:first-child { background: var(--surface-2); }

/* Hiérarchie : les chiffres de contexte s'effacent, les décisifs ressortent */
td { color: var(--text-muted); }
td.title-cell, td .pos, td .neg { color: inherit; }
.title-main { color: var(--text); font-size: 0.88rem; }
.title-sub { font-size: 0.7rem; opacity: 0.85; }
.div-col { font-size: 0.78rem; }

thead th {
  font-size: 0.65rem;
  letter-spacing: 0.07em;
  color: var(--text-muted);
  padding-bottom: var(--s2);
  border-bottom: 1px solid var(--border-strong);
  background: var(--surface);
}
.group-header td {
  background: var(--surface-2) !important;
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  padding: 0.45rem var(--s3);
}

/* Bascule courbe / bougies */
.type-tabs { display: inline-flex; gap: 2px; padding: 2px; background: var(--surface-2); border-radius: 999px; }
.type-tabs button {
  display: inline-flex; align-items: center; gap: 0.35rem;
  padding: 0.28rem 0.6rem;
  border: none; background: none; border-radius: 999px;
  color: var(--text-muted); font-size: 0.76rem; font-weight: 640; cursor: pointer;
}
.type-tabs button svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.type-tabs button:hover { color: var(--text); }
.type-tabs button.active { background: var(--surface); color: var(--accent); box-shadow: var(--shadow-sm); }
.chart-controls { gap: var(--s2); }

/* La place du bandeau marché est réservée dès le CSS : header.js l'insère en
   `defer`, donc après la peinture — sans hauteur réservée, tout le contenu
   sautait vers le bas à son arrivée. */
body.has-sidebar { padding-top: 0; }
.market-header { min-height: 34px; }
#indices-bar { min-height: 20px; }

/* ============================================================
   FLUIDITÉ — transitions de page & réglages fins
   ============================================================ */

/* Transition native entre pages : lisse le flash blanc du rechargement complet.
   Ignoré par les navigateurs qui ne la supportent pas — dégradation propre. */
@view-transition { navigation: auto; }
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) { animation: vt-out 0.16s var(--ease); }
  ::view-transition-new(root) { animation: vt-in 0.22s var(--ease); }
}
@keyframes vt-out { to { opacity: 0; } }
@keyframes vt-in { from { opacity: 0; transform: translateY(6px); } }

/* La sidebar ne doit PAS participer à la transition : elle est identique d'une
   page à l'autre, l'animer donnerait un scintillement. On la fige. */
.sidebar { view-transition-name: sidebar; }
::view-transition-group(sidebar) { animation: none; }

/* Apparition douce du contenu au premier chargement (hors transition de vue) */
.hero, .table-wrap, .filter-panel, .dash-grid, .acct-list, .page-head {
  animation: rise 0.4s var(--ease) both;
}
@keyframes rise { from { opacity: 0; transform: translateY(8px); } }

/* Défilement lissé quand on clique une ancre ou qu'on remonte */
html { scroll-behavior: smooth; }

/* Le focus clavier doit rester net et cohérent partout */
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Zones cliquables : curseur explicite, pas d'ambiguïté */
.sortable, .tab, .rtabs button, .view-tabs button, .type-tabs button,
.range-tabs button, .layer-tabs button, .sb-toggle { cursor: pointer; }

/* Les liens de la sidebar passent en douceur */
.sidebar nav a { transition: background var(--fast), color var(--fast), padding-left var(--fast); }
.sidebar nav a:hover { padding-left: calc(var(--s2) + 3px); }

/* Scrollbars discrètes et cohérentes avec le thème */
* { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 99px; border: 3px solid transparent; background-clip: padding-box; }
*::-webkit-scrollbar-thumb:hover { background: var(--text-muted); background-clip: padding-box; }

/* ============================================================
   NEWSFEED
   ============================================================ */
.news-list { display: flex; flex-direction: column; gap: var(--s2); }
.news-card {
  display: grid;
  grid-template-columns: 128px 1fr;
  gap: var(--s4);
  padding: var(--s3);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  text-decoration: none;
  color: inherit;
  transition: background var(--fast), border-color var(--fast), transform var(--fast);
}
.news-card:hover { background: var(--surface-2); border-color: var(--border-strong); transform: translateY(-1px); }
.news-thumb {
  width: 128px; height: 84px;
  border-radius: var(--radius-sm);
  object-fit: cover;
  background: var(--surface-2);
  flex: none;
}
.news-thumb-empty { background: linear-gradient(135deg, var(--surface-2), var(--surface-3)); }
.news-body { min-width: 0; display: flex; flex-direction: column; gap: 0.3rem; }
.news-tags { display: flex; gap: 0.3rem; flex-wrap: wrap; }
.news-tag {
  font-size: 0.65rem; font-weight: 700; letter-spacing: 0.03em;
  padding: 0.08rem 0.4rem; border-radius: 999px;
  background: var(--surface-2); color: var(--text-muted);
}
.news-tag.held { background: var(--accent-weak); color: var(--accent); }
.news-title { font-weight: 650; font-size: 0.94rem; line-height: 1.35; color: var(--text); }
.news-summary {
  font-size: 0.82rem; color: var(--text-muted); line-height: 1.5;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.news-meta { font-size: 0.74rem; color: var(--text-muted); display: flex; gap: 0.35rem; }
.skel-card { pointer-events: none; }
.skel-card .news-thumb { background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 37%, var(--surface-2) 63%); background-size: 400% 100%; animation: shimmer 1.3s ease-in-out infinite; }
@media (max-width: 640px) {
  .news-card { grid-template-columns: 1fr; }
  .news-thumb { width: 100%; height: 140px; }
}

/* ============================================================
   CALENDRIER
   ============================================================ */
.cal-toolbar { display: flex; align-items: center; justify-content: space-between; gap: var(--s4); flex-wrap: wrap; }
.cal-nav { display: flex; align-items: center; gap: var(--s2); }
.cal-nav .btn-ghost { padding: 0.4rem; min-height: 32px; }
.cal-nav .btn-ghost svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.cal-label { font-weight: 700; font-size: 1.05rem; text-transform: capitalize; min-width: 140px; text-align: center; }
.cal-legend { display: flex; align-items: center; gap: 0.4rem; font-size: 0.76rem; color: var(--text-muted); flex-wrap: wrap; }
.leg-item {
  display: inline-flex; align-items: center; gap: 0.3rem;
  border: 1px solid var(--border); background: var(--surface);
  border-radius: 999px; padding: 0.15rem 0.55rem; cursor: pointer;
  font-size: 0.76rem; color: var(--text-muted); transition: opacity var(--fast);
}
.leg-item:hover { border-color: var(--border-strong); color: var(--text); }
.leg-item:not(.active) { opacity: 0.4; text-decoration: line-through; }

.cal-dot {
  display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  background: var(--text-muted); margin-right: 2px;
}
.cal-dot.earnings { background: var(--accent); }
.cal-dot.ex_dividend { background: var(--warn); }
.cal-dot.dividend_pay { background: var(--pos); }
.cal-dot.dividend_paid { background: var(--text-muted); }
.cal-dot.custom { background: var(--c3); }
.cal-dot.ipo { background: var(--c5); }

/* Événement saisi à la main : badge + bouton de suppression dans l'agenda */
.badge.manual { background: color-mix(in srgb, var(--c3) 20%, transparent); color: var(--c3); }

/* Éligibilité PEA : estimation par siège social (app/pea.py) — vert = éligible,
   neutre = hors PEA, pas de rouge (ne pas laisser croire à une erreur). */
.badge.pea-yes { background: var(--pos-weak); color: var(--pos); }
.badge.pea-no { background: var(--surface-2); color: var(--text-muted); }
.mev-del {
  margin-left: 0.4rem; border: none; background: none; color: var(--text-muted);
  cursor: pointer; font-size: 0.8rem; padding: 0 0.2rem;
}
.mev-del:hover { color: var(--neg); }
.inline-form { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; }

/* Statuts d'IPO */
.ipo-status { font-size: 0.76rem; font-weight: 600; padding: 0.15rem 0.5rem; border-radius: 999px; white-space: nowrap; }
.ipo-status.s-expected, .ipo-status.s-filed { background: var(--pos-weak); color: var(--pos); }
.ipo-status.s-priced { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); }
.ipo-status.s-withdrawn { background: var(--neg-weak); color: var(--neg); }
.ipo-status.s-none { color: var(--text-muted); }
.ipo-sector { font-size: 0.76rem; color: var(--text-muted); background: var(--surface-2); padding: 0.12rem 0.45rem; border-radius: 6px; }

/* ===== Page de connexion ===== */
.login-body {
  display: flex; align-items: center; justify-content: center;
  min-height: 100vh; padding: var(--s5); margin: 0;
}
.login-card {
  width: 100%; max-width: 380px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 16px; padding: var(--s6, 2rem) var(--s5);
}
.login-brand { display: flex; align-items: center; gap: var(--s3); margin-bottom: var(--s2); }
.login-logo {
  width: 32px; height: 32px; border-radius: 9px; flex: none;
  background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 55%, #000));
}
.login-brand h1 { margin: 0; font-size: 1.3rem; }
.login-sub { margin: 0 0 var(--s5); color: var(--text-muted); font-size: 0.86rem; line-height: 1.5; }
.login-field { display: flex; flex-direction: column; gap: 0.3rem; margin-bottom: var(--s4); font-size: 0.8rem; color: var(--text-muted); font-weight: 600; }
.login-field input { width: 100%; }
.login-error {
  margin: 0 0 var(--s3); font-size: 0.82rem; color: var(--neg);
  background: var(--neg-weak); border-radius: 8px; padding: 0.5rem 0.65rem;
}
#login-submit { width: 100%; }

/* ===== Page Sources & méthodes ===== */
.prov-legend { display: flex; flex-wrap: wrap; gap: var(--s2); margin-bottom: var(--s4); }
.src-badge {
  font-size: 0.72rem; font-weight: 640; padding: 0.16rem 0.5rem; border-radius: 999px;
  background: var(--surface-2); color: var(--text-muted); border: 1px solid var(--border); white-space: nowrap;
}
/* Badges de source : basculés sur la palette CATÉGORIELLE (--c1..--c10), qui
   exclut délibérément le vert et le rouge — réservés aux gains et aux pertes
   (voir le commentaire des tokens en tête de fichier).
   Ils utilisaient une palette étrangère codée en dur, comprenant un vert
   (#10b981 sur justETF) et un rouge (#ea4335 sur Google News) : un badge de
   SOURCE se lisait donc comme un signal de PERFORMANCE. Pire, `.s-calc`
   employait `var(--pos)` directement, c'est-à-dire le vert des gains lui-même.
   Aucune de ces couleurs n'avait de variante sombre ; les tokens, si. */
.src-badge.s-yfinance { color: var(--c3);  border-color: color-mix(in srgb, var(--c3) 34%, transparent); }
.src-badge.s-eodhd    { color: var(--c2);  border-color: color-mix(in srgb, var(--c2) 34%, transparent); }
.src-badge.s-finnhub  { color: var(--c6);  border-color: color-mix(in srgb, var(--c6) 34%, transparent); }
.src-badge.s-wikipedia{ color: var(--text); border-color: var(--border-strong); }
.src-badge.s-bce      { color: var(--c9);  border-color: color-mix(in srgb, var(--c9) 34%, transparent); }
.src-badge.s-fred     { color: var(--c9);  border-color: color-mix(in srgb, var(--c9) 34%, transparent); }
.src-badge.s-gnews    { color: var(--c5);  border-color: color-mix(in srgb, var(--c5) 34%, transparent); }
.src-badge.s-justetf  { color: var(--c4);  border-color: color-mix(in srgb, var(--c4) 34%, transparent); }
.src-badge.s-anthropic{ color: var(--c10); border-color: color-mix(in srgb, var(--c10) 34%, transparent); }
.src-badge.s-calc     { color: var(--c7);  border-color: color-mix(in srgb, var(--c7) 34%, transparent); }
.src-badge.s-manual   { color: var(--text-muted); }
.src-badge.s-sec      { color: var(--c1);  border-color: color-mix(in srgb, var(--c1) 34%, transparent); }
.src-badge.s-congres  { color: var(--c8);  border-color: color-mix(in srgb, var(--c8) 34%, transparent); }
/* AMF partage --c9 avec BCE/FRED : même famille « régulateur/institution
   officielle », précédent déjà posé par BCE et FRED elles-mêmes. */
.src-badge.s-amf      { color: var(--c9);  border-color: color-mix(in srgb, var(--c9) 34%, transparent); }

.prov-card { background: var(--surface); border: 1px solid var(--border); border-radius: 14px; padding: var(--s4) var(--s5); margin-bottom: var(--s4); }
.prov-card h2 { margin: 0 0 var(--s2); font-size: 1.02rem; }
.prov-note { margin: 0 0 var(--s3); font-size: 0.82rem; color: var(--text-muted); line-height: 1.5; }
.prov-rows { display: flex; flex-direction: column; }
.prov-row {
  display: grid; grid-template-columns: 1.4fr 0.9fr 2fr; gap: var(--s3);
  align-items: start; padding: 0.5rem 0; border-top: 1px solid var(--border);
}
.prov-row:first-child { border-top: none; }
.prov-data { font-weight: 600; font-size: 0.86rem; }
.prov-method { font-size: 0.82rem; color: var(--text-muted); line-height: 1.45; }
@media (max-width: 640px) {
  .prov-row { grid-template-columns: 1fr; gap: 2px; }
  .prov-src { margin: 2px 0; }
}

/* ===== Veille sectorielle ===== */
.sector-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
  gap: var(--s4);
}
.sector-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius, 14px);
  padding: var(--s4) var(--s5);
}
.sec-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3); }
.sec-head h2 { margin: 0; font-size: 1.05rem; }
.sec-count { font-size: 0.78rem; color: var(--text-muted); white-space: nowrap; }
.sec-chips { display: flex; flex-wrap: wrap; gap: var(--s2); margin: var(--s3) 0; }
.sec-chip {
  font-size: 0.76rem; font-weight: 600; padding: 0.2rem 0.55rem; border-radius: 999px;
  background: var(--surface-2); color: var(--text-muted); border: 1px solid var(--border);
}
.sec-chip.pos { color: var(--pos); border-color: color-mix(in srgb, var(--pos) 30%, transparent); }
.sec-chip.neg { color: var(--neg); border-color: color-mix(in srgb, var(--neg) 30%, transparent); }
.sec-block-label {
  font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-muted); font-weight: 700; margin: var(--s3) 0 var(--s2);
}
/* Taille d'échantillon dans l'étiquette du bloc plutôt qu'en note dessous :
   « 62 % au-dessus de leur MM200 » ne dit pas la même chose sur 8 valeurs que
   sur 60, donc l'information reste — mais elle qualifie le chiffre au lieu
   d'avoir l'air d'un avertissement. */
.sec-block-n { text-transform: none; letter-spacing: 0; font-weight: 500; opacity: 0.85; margin-left: 0.4em; }
.sec-tops { display: flex; flex-direction: column; gap: 2px; }
.sec-top {
  display: flex; justify-content: space-between; gap: var(--s3); align-items: center;
  background: none; border: none; text-align: left; cursor: pointer;
  padding: 0.32rem 0.4rem; border-radius: 8px; color: var(--text); font-size: 0.86rem;
}
.sec-top:hover { background: var(--surface-2); }
.sec-top-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sec-top-cap { color: var(--text-muted); font-variant-numeric: tabular-nums; font-size: 0.8rem; white-space: nowrap; }
.sec-newslist { display: flex; flex-direction: column; gap: var(--s2); }
.sec-news { display: block; text-decoration: none; color: var(--text); }
.sec-news:hover .sec-news-title { color: var(--accent); }
.sec-news-title { display: block; font-size: 0.84rem; line-height: 1.35; }
.sec-news-meta { display: block; font-size: 0.72rem; color: var(--text-muted); margin-top: 1px; }
@media (max-width: 560px) { .sector-grid { grid-template-columns: 1fr; } }

/* ===== Veille de marché : régime + heatmap de leadership ===== */
#market-root { margin-top: var(--s4); }

.regime-banner {
  display: grid; grid-template-columns: 1.4fr 1fr; gap: var(--s5);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: var(--s5); margin-bottom: var(--s5);
}
.regime-phase-label, .reg-tile-label {
  font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-muted); font-weight: 700;
}
.regime-phase { margin: 0.2rem 0 var(--s2); font-size: 1.5rem; line-height: 1.15; }
.regime-desc { margin: 0; color: var(--text-muted); font-size: 0.9rem; line-height: 1.5; }
.reg-favs { margin-top: var(--s3); font-size: 0.82rem; }
.reg-favs-label { color: var(--text-muted); }
.reg-fav {
  display: inline-block; margin: 2px 3px 0 0; padding: 0.12rem 0.5rem; border-radius: 999px;
  background: var(--accent-weak); color: var(--accent); font-weight: 600; font-size: 0.78rem;
}
/* 3 tuiles EMPILÉES dans une colonne étroite prenaient toute la hauteur de la
   bannière, alors que le texte de gauche (phase + description courte)
   s'arrêtait bien avant : la moitié basse de la carte restait vide. En rangée
   horizontale, les tuiles font à peu près la hauteur du texte de gauche. */
.regime-tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s3); align-content: start; }
.reg-tile {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius); padding: var(--s3) var(--s4);
}
.reg-tile-value { font-size: 1.15rem; font-weight: 700; font-variant-numeric: tabular-nums; margin-top: 2px; }
.reg-tile-sub { font-size: 0.76rem; color: var(--text-muted); margin-top: 1px; }

.lead-wrap {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: var(--s3) var(--s4) var(--s4); overflow-x: auto;
}
.lead-table { width: 100%; border-collapse: collapse; font-size: 0.86rem; }
.lead-table th {
  text-align: right; font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--text-muted); font-weight: 700; padding: var(--s2) 0.5rem; white-space: nowrap;
  border-bottom: 1px solid var(--border);
}
.lead-table th:nth-child(2) { text-align: left; }
.lead-table td { padding: 0.45rem 0.5rem; border-bottom: 1px solid var(--border); text-align: right; font-variant-numeric: tabular-nums; }
.lead-row { cursor: pointer; transition: background var(--fast); }
.lead-row:hover, .lead-row:focus-visible { background: var(--surface-2); outline: none; }
.lead-rank { color: var(--text-muted); font-weight: 700; width: 2ch; }
.lead-name { text-align: left; }
.lead-sector { font-weight: 600; }
.lead-etf { color: var(--text-muted); font-size: 0.74rem; margin-left: 0.4rem; }
.lead-score { font-weight: 700; }
td.heat { border-radius: 0; font-variant-numeric: tabular-nums; }
.cycle-tag {
  display: inline-block; padding: 0.08rem 0.45rem; border-radius: 999px; font-size: 0.72rem; font-weight: 600;
  border: 1px solid var(--border);
}
.cycle-tag.cyc { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 35%, transparent); }
.cycle-tag.def { color: var(--text-muted); }
.lead-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--border-strong); }
.lead-dot.on { background: var(--pos); }
.lead-dot.down { background: var(--neg); }
.lead-dot.off { background: var(--border-strong); opacity: 0.5; }
.held-badge { background: var(--accent-weak); color: var(--accent); border: none; }
/* `.lead-legend` a disparu : la phrase répétait ce que les en-têtes de colonnes
   disent déjà (elles portent désormais leur propre infobulle) et invitait à
   « cliquer un secteur » alors que la ligne entière est un bouton au survol. */

/* ===== Rotation sectorielle : élément signature de la page ===== */
/* La page n'avait qu'un tableau de chiffres pour tout repère visuel : ce
   graphique (Relative Rotation Graph, le format standard de l'analyse de
   leadership sectoriel) montre en un coup d'œil qui mène le marché ET si ça
   s'accélère ou s'essouffle — deux dimensions qu'il fallait sinon reconstruire
   colonne par colonne. Cadrans en fond très atténué : l'information vit dans
   la POSITION des points, le fond ne fait qu'orienter l'œil. */
.rotation-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: var(--s4) var(--s5) var(--s5);
  margin-bottom: var(--s5);
}
.rotation-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--s2) var(--s4); margin-bottom: var(--s3); }
/* Clé de lecture : deux repères, pas un paragraphe. Ce que la phrase
   « Cadrans dans le sens de rotation habituel… » demandait de retenir est
   désormais écrit sur les axes eux-mêmes (`.rot-axis-dir`). */
.rotation-key { display: flex; gap: var(--s4); flex-wrap: wrap; font-size: var(--fs-xs); color: var(--text-muted); }
.rk-item { display: inline-flex; align-items: center; gap: 6px; }
.rk-disc {
  width: 13px; height: 13px; border-radius: 50%; flex: none;
  background: color-mix(in srgb, var(--text-muted) 40%, var(--surface));
  box-shadow: 0 0 0 1px var(--border) inset;
}
.rk-held {
  width: 13px; height: 13px; border-radius: 50%; flex: none;
  background: color-mix(in srgb, var(--text-muted) 20%, var(--surface));
  border: 2.5px solid var(--accent);
}
/* Pas de `max-height` : la hauteur bornée + le ratio du viewBox faisaient
   « letterboxer » le SVG, qui se dessinait au centre entre deux bandes vides
   de 200 px. Le graphique est plafonné en LARGEUR et centré — il occupe alors
   toute la boîte qu'il déclare. */
.rotation-svg {
  display: block; width: 100%; max-width: 940px; height: auto;
  margin-inline: auto; overflow: visible;
}
.rot-zone { opacity: 1; }
/* Teintes remontées de 6-7 % à 11-13 % : à la première intensité, les quatre
   cadrans étaient quasi indiscernables du fond — le graphique se lisait comme
   un nuage de points sur rectangle uni plutôt que comme quatre zones. */
.rot-lead    { fill: color-mix(in srgb, var(--pos) 12%, var(--surface)); }
.rot-improve { fill: color-mix(in srgb, var(--accent) 13%, var(--surface)); }
.rot-weak    { fill: color-mix(in srgb, var(--warn) 11%, var(--surface)); }
.rot-lag     { fill: color-mix(in srgb, var(--neg) 11%, var(--surface)); }
.rot-axis { stroke: var(--border-strong); stroke-width: 1.4; }
/* Graduations chiffrées (absentes jusqu'ici — seuls les cadrans étaient
   nommés, aucune valeur n'ancrait l'échelle) : même idiome que `.cv-grid` /
   `.cv-axis` de la courbe des taux, décliné sur les deux axes. */
.rot-grid { stroke: var(--border); stroke-width: 1; stroke-dasharray: 2 3; }
.rot-tick { fill: var(--text-muted); font-size: 9.5px; font-variant-numeric: tabular-nums; }
/* Titres d'axes : c'est ce qui manquait. Un nuage de points dont on ne sait
   pas ce que mesurent le haut et la droite n'est pas un graphique. Le SENS de
   chaque demi-axe est écrit à ses deux extrémités — on n'a plus à retenir
   l'ordre d'un cycle pour lire la position d'un secteur. */
.rot-axis-title { fill: var(--text-muted); font-size: 10px; font-weight: 600; letter-spacing: 0.01em; }
.rot-axis-dir { fill: var(--text-muted); font-size: 9px; font-weight: 600; letter-spacing: 0.04em; opacity: 0.8; }
/* Noms de cadrans DANS leur zone, très clairs : ils orientent sans disputer
   la lecture aux points, qui sont peints par-dessus. */
.rot-quad-label {
  font-size: 9.5px; font-weight: 700; letter-spacing: 0.08em;
  fill: var(--text-muted); text-transform: uppercase; opacity: 0.55;
}
.rot-dot { cursor: pointer; }
.rot-dot circle {
  fill: color-mix(in srgb, var(--pos) 55%, var(--surface));
  stroke: var(--surface); stroke-width: 1.5;
  transition: r var(--fast), opacity var(--fast);
}
.rot-dot.neg circle { fill: color-mix(in srgb, var(--neg) 55%, var(--surface)); }
.rot-dot.held circle { stroke: var(--accent); stroke-width: 2.5; }
.rot-dot:hover circle, .rot-dot:focus-visible circle { opacity: 0.85; }
.rot-dot:focus-visible { outline: none; }
.rot-dot:focus-visible circle { stroke: var(--accent); stroke-width: 2.5; }
.rot-label {
  font-size: 10.5px; font-weight: 600; fill: var(--text);
  paint-order: stroke; stroke: var(--surface); stroke-width: 3px;
}
.rot-skel {
  height: 340px; border-radius: var(--radius); margin-top: var(--s3);
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 37%, var(--surface-2) 63%);
  background-size: 400% 100%; animation: shimmer 1.3s ease-in-out infinite;
}
@media (max-width: 720px) {
  .rot-label { font-size: 9px; }
  .rot-quad-label { font-size: 7.5px; }
}

/* ===== Fiche détaillée d'un secteur (modale) ===== */
.modal.modal-wide { max-width: 940px; }
.sector-detail .sd-head { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
.sector-detail .sd-head h2 { margin: 0; font-size: 1.3rem; }
.sd-etf { color: var(--text-muted); font-size: 0.8rem; }
.sd-tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s3); margin: var(--s4) 0; }
.sd-tile { background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius); padding: var(--s3) var(--s4); }
.sd-tile-label { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); font-weight: 700; }
.sd-tile-value { font-size: 1.2rem; font-weight: 700; font-variant-numeric: tabular-nums; margin-top: 2px; }
.sd-tile-sub { font-size: 0.74rem; color: var(--text-muted); margin-top: 1px; }
.sd-cols { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s5); margin-top: var(--s3); }
.sd-gauges { display: flex; flex-direction: column; gap: var(--s3); }
.sd-gauge-head { display: flex; justify-content: space-between; font-size: 0.82rem; margin-bottom: 3px; }
.sd-gauge-bar { height: 8px; background: var(--surface-2); border-radius: 999px; overflow: hidden; }
.sd-gauge-bar > span { display: block; height: 100%; background: var(--accent); border-radius: 999px; }
.sd-note, .sd-foot { font-size: 0.74rem; color: var(--text-muted); margin: var(--s2) 0 0; line-height: 1.5; }
.sd-inds { display: flex; flex-direction: column; gap: var(--s3); }
.sd-ind-head { display: flex; justify-content: space-between; gap: var(--s2); font-size: 0.82rem; }
.sd-ind-name { font-weight: 600; }
.sd-ind-cap { color: var(--text-muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.sd-ind-bar { height: 6px; background: var(--surface-2); border-radius: 999px; overflow: hidden; margin-top: 3px; }
.sd-ind-bar > span { display: block; height: 100%; background: color-mix(in srgb, var(--accent) 65%, transparent); }
.sd-ind-sub { font-size: 0.72rem; color: var(--text-muted); margin-top: 2px; }
.trend-tags { display: flex; flex-wrap: wrap; gap: var(--s2); }
.trend-tag {
  display: inline-flex; align-items: center; gap: 5px; padding: 0.15rem 0.5rem; border-radius: 999px;
  background: var(--surface-2); border: 1px solid var(--border); font-size: 0.78rem;
}
.trend-tag i { font-style: normal; color: var(--text-muted); font-size: 0.7rem; font-variant-numeric: tabular-nums; }
@media (max-width: 720px) {
  .regime-banner { grid-template-columns: 1fr; }
  .regime-tiles { grid-template-columns: 1fr; }
  .sd-cols { grid-template-columns: 1fr; }
  .sd-tiles { grid-template-columns: repeat(2, 1fr); }
}

/* ===== Taux & Obligations ===== */
#bonds-root { margin-top: var(--s4); display: flex; flex-direction: column; gap: var(--s5); }
.bond-top { display: grid; grid-template-columns: 1.3fr 1fr; gap: var(--s5); }
.bond-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: var(--s5);
}
.bond-card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); margin-bottom: var(--s3); }
.bond-card-head h2 { margin: 0; font-size: 1.1rem; }
.bond-note { margin: var(--s3) 0 0; font-size: 0.74rem; color: var(--text-muted); line-height: 1.5; }

.curve-svg { width: 100%; height: auto; display: block; }
.cv-grid { stroke: var(--border); stroke-width: 1; }
.cv-axis { fill: var(--text-muted); font-size: 11px; font-variant-numeric: tabular-nums; }
.cv-line { stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.cv-now { stroke: var(--accent); stroke-width: 2.6; }
.cv-3m { stroke: var(--text-muted); stroke-opacity: 0.65; }
.cv-1y { stroke: var(--border-strong); stroke-dasharray: 4 4; }
.cv-dot { fill: var(--accent); }
.cv-val { fill: var(--text); font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums; }
.cv-legend { display: flex; gap: var(--s4); flex-wrap: wrap; margin-top: var(--s2); font-size: 0.76rem; color: var(--text-muted); }
.cv-leg { display: inline-flex; align-items: center; gap: 6px; }
.cv-swatch { width: 16px; height: 3px; border-radius: 2px; display: inline-block; }
.cv-swatch.cv-now { background: var(--accent); }
.cv-swatch.cv-3m { background: var(--text-muted); opacity: 0.65; }
.cv-swatch.cv-1y { background: var(--border-strong); }

/* ===== Histogramme des gains cumulés (simulation d'obligation) ===== */
.bh-svg { width: 100%; height: auto; display: block; }
.bh-grid { stroke: var(--border); stroke-width: 1; }
.bh-axis { fill: var(--text-muted); font-size: 11px; font-variant-numeric: tabular-nums; }
/* Avant le seuil de rentabilité (cumul < capital investi) : ton atténué —
   l'argent n'est pas encore rentré. Après : l'accent, la couleur du gain
   assumé sur cette page (voir header des obligations). */
.bh-bar { fill: color-mix(in srgb, var(--text-muted) 45%, transparent); transition: fill var(--fast); }
.bh-bar.past { fill: var(--accent); }
.bh-bar-g:hover .bh-bar { fill: var(--accent); }
/* Le principal remboursé à l'échéance est un remboursement de CAPITAL, pas un
   revenu : empilé sur la barre dans une teinte distincte plutôt que noyé dans
   le cumul des coupons, sinon le saut final se lirait comme un coupon géant. */
.bh-principal { fill: var(--c2); opacity: 0.85; }
.bh-invested { stroke: var(--neg); stroke-width: 1.5; stroke-dasharray: 5 4; }
.bh-invested-lab { fill: var(--neg); font-size: 10.5px; font-weight: 600; }
.bh-legend { display: flex; gap: var(--s4); flex-wrap: wrap; margin-top: var(--s2); font-size: 0.76rem; color: var(--text-muted); }
.bh-leg { display: inline-flex; align-items: center; gap: 5px; }
.bh-swatch { width: 11px; height: 11px; border-radius: 3px; display: inline-block; }
.bh-swatch-before { background: color-mix(in srgb, var(--text-muted) 45%, transparent); }
.bh-swatch-after { background: var(--accent); }
.bh-swatch-principal { background: var(--c2); opacity: 0.85; }
.cv-flag { font-size: 0.74rem; font-weight: 600; padding: 0.15rem 0.55rem; border-radius: 999px; background: var(--surface-2); border: 1px solid var(--border); color: var(--text-muted); }
.cv-flag.pos { color: var(--pos); border-color: color-mix(in srgb, var(--pos) 30%, transparent); }
.cv-flag.neg { color: var(--neg); border-color: color-mix(in srgb, var(--neg) 30%, transparent); }
.cv-slopes { display: flex; gap: var(--s5); flex-wrap: wrap; margin-top: var(--s3); font-size: 0.86rem; font-variant-numeric: tabular-nums; }

.credit-yields { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s3); }
.credit-appetite { display: flex; justify-content: space-between; gap: var(--s4); flex-wrap: wrap; margin-top: var(--s4);
  padding-top: var(--s3); border-top: 1px solid var(--border); }
.credit-app-val { font-size: 1.05rem; font-weight: 700; margin-top: 2px; }
.credit-app-nums { display: flex; flex-direction: column; gap: 2px; font-size: 0.82rem; text-align: right; font-variant-numeric: tabular-nums; }

.seg-tag { display: inline-block; padding: 0.08rem 0.5rem; border-radius: 999px; font-size: 0.74rem; font-weight: 600;
  background: var(--surface-2); border: 1px solid var(--border); color: var(--text-muted); white-space: nowrap; }
.dur-tag { display: inline-block; padding: 0.08rem 0.5rem; border-radius: 999px; font-size: 0.72rem; font-weight: 600; white-space: nowrap; border: 1px solid var(--border); }
.dur-court { color: var(--pos); border-color: color-mix(in srgb, var(--pos) 30%, transparent); }
.dur-mid { color: var(--text-muted); }
.dur-long { color: var(--neg); border-color: color-mix(in srgb, var(--neg) 30%, transparent); }
.bond-region, .bond-yield { color: var(--text-muted); font-variant-numeric: tabular-nums; }
/* Le « Terme » (30-Year…) est le tenor à l'ÉMISSION, pas le temps restant : un
   titre auctionné en 1996 est un CUSIP réel, toujours en circulation, mais à
   quelques mois de son échéance. Sans ce repère, le choisir ouvre un
   simulateur presque vide qui se lit comme un bug plutôt que comme le titre
   qu'on a réellement sélectionné. */
.bond-yr-left { display: block; font-size: 0.68rem; color: var(--warn); font-weight: 600; }
.bond-yield { color: var(--text); font-weight: 600; }
@media (max-width: 820px) {
  .bond-top { grid-template-columns: 1fr; }
}

.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
  margin-top: var(--s4);
}
.cal-dow { text-align: center; font-size: 0.68rem; font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.05em; padding-bottom: 0.3rem; }
.cal-cell {
  min-height: 74px;
  border-radius: var(--radius-sm);
  background: var(--surface);
  border: 1px solid var(--border);
  padding: 0.4rem;
  display: flex; flex-direction: column; gap: 0.3rem;
}
.cal-cell.empty { background: none; border-color: transparent; }
.cal-cell.has-events { cursor: pointer; transition: background var(--fast), border-color var(--fast); }
.cal-cell.has-events:hover { background: var(--surface-2); border-color: var(--border-strong); }
.cal-cell.today { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.cal-daynum { font-size: 0.78rem; font-weight: 640; color: var(--text-muted); }
.cal-cell.today .cal-daynum { color: var(--accent); font-weight: 750; }
.cal-dots { display: flex; gap: 3px; flex-wrap: wrap; margin-top: auto; }

.cal-agenda-day { padding: var(--s3) 0; border-bottom: 1px solid var(--border); border-radius: var(--radius-sm); transition: background var(--med); }
.cal-agenda-day:last-child { border-bottom: none; }
.cal-agenda-day.flash { background: var(--accent-weak); }
.cal-agenda-day h4 { margin: 0 0 var(--s2); font-size: 0.82rem; font-weight: 700; text-transform: capitalize; color: var(--text-muted); }
.cal-agenda-row {
  display: grid; grid-template-columns: 14px 1fr auto auto;
  align-items: center; gap: var(--s3);
  padding: 0.3rem 0;
  font-size: 0.86rem;
}
.cal-agenda-name { font-weight: 600; }
.cal-agenda-type { font-size: 0.76rem; color: var(--text-muted); }
.cal-agenda-amount { font-variant-numeric: tabular-nums; font-weight: 640; text-align: right; min-width: 70px; }
@media (max-width: 720px) {
  .cal-cell { min-height: 52px; }
  .cal-agenda-row { grid-template-columns: 10px 1fr; row-gap: 2px; }
  .cal-agenda-type, .cal-agenda-amount { grid-column: 2; text-align: left; }
}

/* ===== Page Administration des comptes ===== */
.nu-row { display: flex; flex-wrap: wrap; gap: var(--s3); align-items: center; }
.nu-row input, .nu-row select { min-width: 0; }
.nu-row #nu-email { flex: 2 1 220px; }
.nu-row #nu-pass { flex: 1 1 200px; }
.u-actions { display: flex; gap: var(--s2); white-space: nowrap; }
.u-actions button {
  font-size: var(--fs-xs); padding: 0.3rem 0.6rem; border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong); background: var(--surface-2); color: var(--text);
  cursor: pointer; transition: border-color var(--fast), color var(--fast);
}
.u-actions button:hover { border-color: var(--accent); }
.u-actions .u-del:hover { border-color: var(--neg); color: var(--neg); }
.u-tier { font-size: var(--fs-sm); padding: 0.25rem 0.5rem; }

/* ===== Fondamentaux officiels (SEC EDGAR) dans la fiche ===== */
.sec-fund {
  border: 1px solid color-mix(in srgb, var(--accent) 30%, var(--border));
  border-radius: var(--radius); background: var(--surface-2);
  padding: var(--s3) var(--s4); margin: var(--s3) 0;
}
.sec-fund-head {
  font-family: var(--font-mono, monospace); font-size: var(--fs-xs);
  text-transform: uppercase; letter-spacing: 0.05em; color: var(--accent);
  font-weight: var(--fw-semibold); display: flex; justify-content: space-between;
  gap: var(--s2); flex-wrap: wrap; margin-bottom: var(--s3);
}
.sec-fund-head span { color: var(--text-muted); font-weight: 500; letter-spacing: 0; text-transform: none; }
.sec-fund-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s3); }
.sf-tile { min-width: 0; }
.sf-label { font-size: var(--fs-xs); color: var(--text-muted); }
.sf-val { font-family: var(--font-display, inherit); font-size: var(--fs-lg); font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; margin-top: 2px; }
.sf-yoy { font-size: 0.72rem; font-weight: 600; font-family: var(--font-sans, inherit); margin-left: 4px; }
.sf-yoy.pos { color: var(--pos); } .sf-yoy.neg { color: var(--neg); }
@media (max-width: 560px) { .sec-fund-grid { grid-template-columns: repeat(2, 1fr); } }

/* ===== Transactions d'initiés (SEC Form 4) dans la fiche ===== */
.insiders { border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-2); padding: var(--s3) var(--s4); margin: var(--s3) 0; }
.insiders-head { font-family: var(--font-mono, monospace); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); font-weight: var(--fw-semibold); margin-bottom: var(--s3); }
.ins-list { display: flex; flex-direction: column; }
.ins-row { display: grid; grid-template-columns: 80px 1fr auto; grid-template-areas: "date who type" "date detail detail"; gap: 1px var(--s3); align-items: baseline; padding: var(--s2) 0; border-bottom: 1px solid var(--border); }
.ins-row:last-child { border-bottom: 0; }
.ins-date { grid-area: date; font-size: var(--fs-xs); color: var(--text-muted); font-variant-numeric: tabular-nums; }
.ins-who { grid-area: who; min-width: 0; }
.ins-who b { font-size: var(--fs-sm); font-weight: var(--fw-semibold); }
.ins-who i { font-style: normal; color: var(--text-muted); font-size: var(--fs-xs); margin-left: var(--s2); }
.ins-type { grid-area: type; font-size: var(--fs-xs); font-weight: 700; padding: 0.1rem 0.45rem; border-radius: 999px; white-space: nowrap; }
.ins-type.pos { color: var(--pos); background: var(--pos-weak); }
.ins-type.neg { color: var(--neg); background: var(--neg-weak); }
.ins-detail { grid-area: detail; font-size: var(--fs-xs); color: var(--text-muted); font-variant-numeric: tabular-nums; }
.ins-foot { font-size: 0.68rem; color: var(--text-muted); margin-top: var(--s2); line-height: 1.4; }

/* ============================================================
   PAGE INITIÉS & ÉLUS — le registre des déclarations
   ============================================================
   Trois sources, DEUX régimes de précision : le STOCK Act n'impose au Congrès
   qu'une TRANCHE (« 1 001 – 15 000 $ »), là où un Form 4 ou une déclaration AMF
   porte un montant exact. L'ancienne page les rangeait dans la même colonne avec
   une infobulle pour prévenir — une infobulle ne se lit pas.
   D'où le parti pris : le montant est DESSINÉ sur une échelle log commune.
   Trait plein = mesuré, travée = déclaré entre deux bornes. L'imprécision se
   voit, et rien n'oblige plus à inventer un milieu de fourchette.

   Second défaut corrigé ici : la page était un <table> de 8 colonnes qui
   mesurait 1 726 px dans un conteneur de 1 158 — « Titre », « Sens » et
   « Montant » vivaient hors écran. Le registre est en grid : il se replie. */

/* --- Champ de recherche --- */
/* C'était un `<input>` nu, sans icône ni étiquette visible, posé au-dessus de
   la page : rien ne disait qu'il fouille TOUT l'historique (42 526 lignes,
   2012-2026) et pas seulement les lignes affichées. La portée est maintenant
   écrite dans le champ. */
.ini-search {
  display: flex; align-items: center; gap: var(--s3);
  max-width: 620px; margin-bottom: var(--s4);
  padding: 0 var(--s3);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  transition: border-color var(--fast), box-shadow var(--fast);
}
.ini-search:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-weak); }
.ini-search svg { width: 16px; height: 16px; flex: none; fill: none; stroke: var(--text-muted); stroke-width: 2; stroke-linecap: round; }
#ini-filter {
  flex: 1; min-width: 0; margin: 0;
  border: none; background: none; box-shadow: none;
  padding: 0.55rem 0; font-size: var(--fs-md);
}
#ini-filter:focus { outline: none; }
.ini-search-scope {
  flex: none; font-family: var(--font-mono); font-size: var(--fs-xs);
  color: var(--text-muted); padding-left: var(--s3);
  border-left: 1px solid var(--border);
}
@media (max-width: 560px) { .ini-search-scope { display: none; } }

/* --- Les deux annuaires, côte à côte --- */
.ini-dirs { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s5); margin-bottom: var(--s5); }
@media (max-width: 900px) { .ini-dirs { grid-template-columns: 1fr; gap: var(--s4); } }
.ini-dir-col .ini-people { grid-template-columns: 1fr; margin-bottom: 0; }
.ini-col-head, .ini-ledger-head h2 {
  margin: 0 0 var(--s3); font-size: var(--fs-lg);
  font-family: var(--font-display); letter-spacing: -0.018em;
}
.ini-col-n {
  display: block; margin-top: 2px;
  font-size: var(--fs-xs); font-weight: var(--fw-regular);
  color: var(--text-muted); letter-spacing: 0;
}
.ini-ledger-head { margin: var(--s5) 0 var(--s3); }
.ini-controls-sep { width: 1px; align-self: stretch; background: var(--border); }
.ini-controls .ini-sources { margin: 0 0 0 auto; }

.ini-block-label {
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-muted); font-weight: var(--fw-semibold);
  margin: var(--s5) 0 var(--s2);
  display: flex; align-items: baseline; gap: var(--s2);
}

/* --- Barres de filtres --- */
.ini-controls { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5); align-items: center; margin-bottom: var(--s3); }
.ini-cat-tabs, .ini-dir-tabs { margin: 0; }
.ini-tab-n { opacity: 0.6; font-variant-numeric: tabular-nums; font-weight: 600; }

/* --- Les plus actifs --- */
.ini-people {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(215px, 1fr));
  gap: var(--s2); margin-bottom: var(--s3);
}
.ini-person {
  text-align: left; background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: var(--s3) var(--s4); cursor: pointer;
  transition: border-color var(--fast), transform var(--fast);
  display: flex; flex-direction: column; gap: 4px;
}
.ini-person:hover { border-color: var(--accent); transform: translateY(-1px); }
.ini-person:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ini-p-name {
  font-family: var(--font-display); font-weight: var(--fw-semibold); font-size: var(--fs-md);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ini-p-role {
  font-size: 0.68rem; color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Le rapport achats/ventes en barre : « 17▲ 15▼ » imposait une division
   mentale sur chacune des dix cartes. */
/* Décollée du mandat : posée juste au-dessus, la barre se lisait comme un
   soulignement du texte plutôt que comme une proportion. */
.ini-p-mix { display: block; height: 4px; border-radius: 2px; background: var(--neg); overflow: hidden; margin-top: var(--s2); }
.ini-p-buy { display: block; height: 100%; background: var(--pos); }
.ini-p-stats {
  font-size: var(--fs-xs); color: var(--text-muted);
  font-variant-numeric: tabular-nums; display: flex; align-items: baseline; gap: var(--s2);
}
.ini-p-stats b { font-weight: 700; }
.ini-p-val { margin-left: auto; }

/* ============ Le registre ============ */
.ini-ledger {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden;
}

/* Colonnes partagées par l'en-tête d'échelle et chaque ligne : une seule
   définition, sinon la graduation cesse d'être alignée sur les barres — et une
   échelle décalée est pire que pas d'échelle. */
.ini-scale-head, .ini-row {
  display: grid;
  grid-template-columns: minmax(180px, 1.5fr) minmax(150px, 1.4fr) 118px minmax(210px, 1.6fr) 104px;
  gap: var(--s3);
  align-items: center;
  padding: 0 var(--s5);
}

.ini-scale-head {
  height: 40px; border-bottom: 1px solid var(--border);
  background: var(--surface-2);
  font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-muted); font-weight: var(--fw-semibold);
}
/* L'étiquette occupe les 3 premières colonnes, l'axe se cale sur la 4e —
   celle des barres. */
.ini-scale-label { grid-column: 1 / 4; }
.ini-scale-axis { grid-column: 4; position: relative; height: 100%; }
.ini-grad {
  position: absolute; top: 50%; transform: translate(-50%, -50%);
  font-variant-numeric: tabular-nums; white-space: nowrap;
  padding-top: 9px;
}
/* Un repère de graduation, pas une décoration : il marque la position exacte. */
.ini-grad::before {
  content: ""; position: absolute; top: 0; left: 50%;
  width: 1px; height: 6px; background: var(--border-strong);
}

/* --- Journée --- */
.ini-day + .ini-day { border-top: 1px solid var(--border); }
.ini-day-head {
  display: flex; align-items: baseline; gap: var(--s3);
  margin: 0; padding: var(--s3) var(--s5) var(--s2);
  background: color-mix(in srgb, var(--surface-2) 55%, var(--surface));
  font-size: var(--fs-xs); font-weight: var(--fw-semibold);
  text-transform: uppercase; letter-spacing: 0.05em;
  position: sticky; top: 0; z-index: 2;
}
.ini-day-date { color: var(--text); }
.ini-day-n { color: var(--text-muted); font-weight: var(--fw-regular); letter-spacing: 0; text-transform: none; }

/* --- Ligne --- */
.ini-row {
  min-height: 54px; padding-top: var(--s2); padding-bottom: var(--s2);
  border-top: 1px solid color-mix(in srgb, var(--border) 55%, transparent);
  font-size: var(--fs-sm);
}
.ini-day-rows > .ini-row:first-child { border-top: none; }
.ini-row:hover { background: var(--surface-2); }
/* Le sens ne se dit pas par la couleur du texte (voir iniLigne) mais par un
   liseré discret en bord de ligne : présent, non bavard, et hors du couple
   sémantique vert/rouge des colonnes de chiffres. */
.ini-row { box-shadow: inset 2px 0 0 transparent; }
.ini-row[data-sens="pos"] { box-shadow: inset 2px 0 0 color-mix(in srgb, var(--pos) 55%, transparent); }
.ini-row[data-sens="neg"] { box-shadow: inset 2px 0 0 color-mix(in srgb, var(--neg) 55%, transparent); }

.ini-c-who { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ini-name {
  font-family: var(--font-display); font-weight: var(--fw-semibold);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ini-role {
  font-size: 0.68rem; color: var(--text-muted);
  display: flex; align-items: center; gap: var(--s1); min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Catégorie : teintes CATÉGORIELLES, jamais le vert/rouge — ceux-là disent
   achat/vente sur cette page et ne doivent pas dire autre chose. */
.ini-cat {
  flex: none; font-size: 0.6rem; font-weight: 700; padding: 0.05rem 0.4rem;
  border-radius: 999px; white-space: nowrap;
  border: 1px solid var(--border); color: var(--text-muted);
}
.ini-cat.us_corp { color: var(--c2); border-color: color-mix(in srgb, var(--c2) 40%, transparent); }
.ini-cat.fr_corp { color: var(--c3); border-color: color-mix(in srgb, var(--c3) 40%, transparent); }
.ini-cat.us_gov  { color: var(--c4); border-color: color-mix(in srgb, var(--c4) 40%, transparent); }
/* Sénat distingué de la Chambre (toutes deux `us_gov`) : deux chambres, deux
   flux de données séparés (voir us_congress.py) — même logique de couleur
   propre que Dirigeants US/FR juste au-dessus. */
.ini-cat.us_gov.senat { color: var(--c5); border-color: color-mix(in srgb, var(--c5) 40%, transparent); }
/* Conjoint / enfant à charge : l'élu déclare aussi pour son foyer. L'omettre
   laisserait croire que la transaction est toujours la sienne. */
.ini-owner {
  flex: none; font-size: 0.6rem; font-weight: 700; padding: 0.05rem 0.4rem;
  border-radius: 999px; white-space: nowrap;
  color: var(--warn); border: 1px solid color-mix(in srgb, var(--warn) 40%, transparent);
}
/* Seul le mandat se laisse tronquer : c'est la partie la plus prévisible. */
.ini-role-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }

.ini-c-what { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.ini-c-what.clickable { cursor: pointer; border-radius: var(--radius-sm); }
.ini-c-what.clickable .ini-tick { color: var(--accent); }
.ini-c-what.clickable:hover .ini-corp { color: var(--text); }
.ini-c-what:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ini-tick { font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--fs-sm); }
.ini-corp {
  font-size: 0.68rem; color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ini-corp.seul { font-size: var(--fs-sm); color: var(--text); }

.ini-c-dir { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.ini-sens {
  font-size: var(--fs-xs); font-weight: 700; padding: 0.1rem 0.45rem;
  border-radius: 999px; white-space: nowrap;
  color: var(--text-muted); background: var(--surface-3);
}
.ini-sens.pos { color: var(--pos); background: var(--pos-weak); }
.ini-sens.neg { color: var(--neg); background: var(--neg-weak); }
.ini-shares { font-size: 0.66rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }

/* ===== La signature de la page : le montant dessiné ===== */
.ini-c-amt { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.ini-amt { font-size: var(--fs-xs); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Un montant MESURÉ s'affirme : chiffres pleins, couleur du texte. */
.ini-amt.exact { color: var(--text); font-weight: var(--fw-semibold); }
/* Une TRANCHE reste une tranche : soulignée en pointillé, ton atténué. Elle se
   lit comme ce qu'elle est — une obligation déclarative, pas une mesure. */
.ini-amt.tranche {
  color: var(--text-muted); border-bottom: 1px dotted currentColor;
  align-self: flex-start; cursor: help;
}
.ini-amt.nul { color: var(--text-muted); font-style: italic; }

.ini-bar {
  position: relative; display: block; height: 7px; width: 100%;
  border-radius: 4px; background: color-mix(in srgb, var(--surface-3) 70%, transparent);
}
/* Montant exact -> un TRAIT unique posé à sa valeur. */
.ini-exact {
  position: absolute; top: -2px; width: 3px; height: 11px; border-radius: 2px;
  transform: translateX(-1.5px); background: var(--text-muted);
}
/* Fourchette -> une TRAVÉE entre les deux bornes déclarées, fermée par un
   montant à chaque extrémité. On ne dessine rien entre les deux qu'on ne sache. */
.ini-span {
  position: absolute; top: 0; height: 100%; border-radius: 4px;
  background: color-mix(in srgb, currentColor 28%, transparent);
  border-left: 2px solid currentColor; border-right: 2px solid currentColor;
}
.ini-bar.pos { color: var(--pos); }
.ini-bar.neg { color: var(--neg); }
.ini-bar.neutre, .ini-bar.vide { color: var(--text-muted); }
.ini-bar.pos .ini-exact { background: var(--pos); }
.ini-bar.neg .ini-exact { background: var(--neg); }

/* `min-width: 0` sur chaque colonne : sans lui, un contenu `nowrap` plus large
   que sa piste POUSSE la grille et le registre entier déborde. C'est ce qui
   arrivait avec « Chambre des représentants » dans une colonne de 104 px. */
.ini-row > * { min-width: 0; }
.ini-c-src { text-align: right; }
.ini-ext { margin-left: 3px; opacity: 0.7; }
.ini-c-src a {
  color: var(--text-muted); font-size: 0.68rem; white-space: nowrap;
  border-bottom: 1px solid transparent;
}
.ini-c-src a:hover { color: var(--accent); border-bottom-color: currentColor; }

/* --- Pagination --- */
.ini-more {
  display: flex; align-items: center; justify-content: center; gap: var(--s2);
  width: 100%; padding: var(--s4); border: none; border-top: 1px solid var(--border);
  background: var(--surface-2); color: var(--accent);
  font-size: var(--fs-sm); font-weight: var(--fw-semibold); cursor: pointer;
}
.ini-more:hover { background: var(--surface-3); }
.ini-more-n { color: var(--text-muted); font-weight: var(--fw-regular); font-size: var(--fs-xs); }

/* Le nom d'un déclarant, dans le registre, ouvre son profil. */
.ini-name.clickable { cursor: pointer; border-radius: 3px; }
.ini-name.clickable:hover { color: var(--accent); }
.ini-name.clickable:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ===== Profils investisseur / entreprise (donut de répartition) =====
   Le donut (voir `iniDonut` dans inities.js) réutilise `.donut`/`.legend` du
   thème (déjà utilisées par le donut patrimoine) : la légende texte, ici
   CLIQUABLE, a besoin de ses propres états visuels que la version statique
   n'avait jamais eus. */
.legend-item.clickable { cursor: pointer; border-radius: var(--radius-sm); }
.legend-item.clickable:hover { background: var(--surface-2); }
.legend-item.clickable:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.ini-loading { color: var(--text-muted); font-size: var(--fs-sm); margin: var(--s3) 0; }
.ini-loading .muted-cell { display: block; font-size: var(--fs-xs); margin-top: 2px; }
.skel-ini { pointer-events: none; }

/* Provenance : repliée par défaut, mais jamais absente — une source muette et
   une source sans déclaration ne doivent pas se ressembler à l'écran. */
.ini-sources { margin: var(--s3) 0; font-size: var(--fs-xs); color: var(--text-muted); }
.ini-sources summary { cursor: pointer; font-weight: var(--fw-semibold); }
.ini-sources summary:hover { color: var(--text); }
.ini-sources ul { margin: var(--s2) 0 0; padding-left: var(--s4); display: grid; gap: var(--s2); }
.ini-sources li { line-height: 1.5; text-wrap: pretty; }
.ini-sources li::marker { color: var(--text-muted); }
.ini-src-ok::marker { content: "\2713  "; color: var(--pos); }
.ini-src-ko::marker { content: "\2717  "; color: var(--neg); }
.ini-src-na::marker { content: "\2014  "; }
.ini-sources a { color: var(--accent); }

/* --- Repli : sous 1080 px la travée de montant passe sous la ligne, plutôt
   que d'écraser les colonnes de texte jusqu'à l'illisible. --- */
@media (max-width: 1080px) {
  .ini-scale-head { display: none; }
  .ini-row {
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1.2fr) 110px 96px;
    row-gap: var(--s2);
  }
  .ini-c-amt { grid-column: 1 / -1; flex-direction: row; align-items: center; gap: var(--s3); }
  .ini-c-amt .ini-bar { flex: 1; }
  .ini-amt { flex: none; min-width: 96px; }
}
@media (max-width: 680px) {
  .ini-scale-head, .ini-row { padding-left: var(--s4); padding-right: var(--s4); }
  .ini-row { grid-template-columns: 1fr auto; row-gap: var(--s1); padding-top: var(--s3); padding-bottom: var(--s3); }
  .ini-c-who { grid-column: 1; }
  .ini-c-dir { grid-column: 2; align-items: flex-end; }
  .ini-c-what { grid-column: 1 / -1; flex-direction: row; align-items: baseline; gap: var(--s2); }
  .ini-c-src { grid-column: 1 / -1; text-align: left; }
  .ini-day-head { padding-left: var(--s4); padding-right: var(--s4); }
}


/* ===== Mobile : navigation en tiroir (off-canvas) + adaptations ===== */
.nav-burger {
  display: none; position: fixed; top: 0.55rem; left: 0.6rem; z-index: 61;
  width: 42px; height: 42px; place-items: center; background: var(--surface);
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  cursor: pointer; box-shadow: var(--shadow); color: var(--text);
}
.nav-burger svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.nav-overlay { display: none; }

@media (max-width: 640px) {
  /* Contenu pleine largeur : plus de réservation d'espace pour la sidebar */
  body.has-sidebar,
  body.has-sidebar.nav-collapsed { padding: 0 var(--s3) var(--s6); }
  body.has-sidebar > *:not(.sidebar):not(#toasts):not(.modal-overlay):not(.nav-burger):not(.nav-overlay) { max-width: 100%; }

  /* Sidebar -> tiroir off-canvas (annule le mode « rail 66px » du bloc 900px) */
  .sidebar {
    width: min(82vw, 300px); padding: var(--s4) var(--s3);
    transform: translateX(-100%); transition: transform 0.24s var(--ease);
    box-shadow: var(--shadow-lg); z-index: 60;
  }
  body.nav-open .sidebar { transform: translateX(0); }
  .sidebar .sb-title { display: inline; }
  .sidebar nav a { justify-content: flex-start; padding: 0.55rem var(--s3); }
  .sidebar nav a span { display: inline; }
  .sidebar .sb-group-label { opacity: 1; height: auto; overflow: visible; }
  .sidebar .sb-toggle { display: none; }
  .sidebar .sb-user { display: block; }
  .sidebar .sb-logout { justify-content: flex-start; }
  .sidebar .sb-logout span { display: inline; }

  /* Hamburger + overlay */
  .nav-burger { display: grid; }
  .nav-overlay { display: block; position: fixed; inset: 0; background: rgba(0, 0, 0, 0.5); z-index: 55; }
  body:not(.nav-open) .nav-overlay { display: none; }

  /* Header : place pour le hamburger. Le ruban d'indices défile SEUL.
     Avant, c'était `.market-header` entier qui était `overflow-x: auto` : les
     indices passaient à la ligne (3 lignes) ET poussaient les actions hors du
     cadre, si bien que le bouton « Rechercher » était coupé en plein mot sur
     les 18 pages. Coupé net, ça se lit comme un bug, pas comme une invitation
     à faire défiler. Un ruban de cotations qui défile sur UNE ligne est au
     contraire l'idiome attendu ; les actions restent entières en dessous. */
  body.has-sidebar > .market-header { padding-left: 52px; }
  .market-header { flex-direction: column; align-items: stretch; gap: var(--s2); }
  /* `min-width: 0` est INDISPENSABLE ici : la taille minimale automatique d'un
     élément flex vaut son `min-content`, donc un ruban en `nowrap` de 949 px
     imposait cette largeur à son parent — et c'est la PAGE entière qui
     défilait latéralement, sur les 18 pages. Sans cette ligne, `overflow-x`
     n'a aucun effet. */
  .market-header { min-width: 0; }
  #indices-bar {
    flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch;
    scrollbar-width: none; padding-bottom: 2px;
    min-width: 0; max-width: 100%;
  }
  #indices-bar::-webkit-scrollbar { display: none; }
  .idx { flex: none; }
  .hdr-actions { flex-wrap: wrap; justify-content: flex-start; }

  /* Densité : titres et cartes plus compacts, jamais de min-width qui déborde */
  h1 { font-size: 1.55rem; }
  .hero { padding: var(--s4); }
  .summary > div, .reg-tile, .hero-stat, .sd-tile, .stat { min-width: 0; }
  .page-actions { flex-wrap: wrap; }

  /* Barres d'outils : le champ filtre ne force plus 260px (débordait de 9px et
     gonflait le viewport, ce qui décalait aussi les modales). Il prend toute la
     ligne, les boutons passent en dessous. */
  .toolbar { flex-wrap: wrap; }
  #filter-input { min-width: 0; flex: 1 1 100%; }

  /* Garde-fou : aucune page ne doit scroller latéralement (le tiroir est fixed,
     donc non affecté). Le raccourci clavier ⌘K n'a pas de sens sur mobile. */
  body { overflow-x: hidden; }
  .hdr-search kbd, .market-header kbd { display: none; }
}

/* ============================================================
   REFONTE MOBILE — 2e passe
   ============================================================
   La 1re passe (viewport + tiroir) a rendu l'app *non cassée* sur téléphone,
   pas *utilisable* : le portefeuille reste un tableau de 19 colonnes qu'on
   balaie latéralement, on perd sa ligne, et rien ne se compare. Cette passe
   attaque le fond :

   1. Les tableaux denses deviennent des CARTES (opt-in `.cards-sm`), avec les
      chiffres décisifs seulement ; le détail vit déjà dans la fiche récap
      qu'un tap ouvre. Modèle Boursorama / Trade Republic.
   2. Navigation au POUCE : barre d'onglets en bas (4 destinations + « Plus »),
      qui remplace le hamburger en haut à gauche — le coin le plus difficile
      à atteindre d'une main.
   3. Encoches & barre d'accueil iPhone : `env(safe-area-inset-*)` était
      totalement absent, donc le bas de page passait SOUS la barre d'accueil.
   4. Cibles tactiles : 44px (les boutons 📈/✕ faisaient ~24px).
   ============================================================ */

/* ---------- Barre d'onglets basse (mobile uniquement) ---------- */
.tabbar {
  display: none; /* activée dans le bloc mobile ci-dessous */
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 58; /* sous le tiroir (60) et son overlay (55 < 58 : voir bloc mobile) */
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: blur(12px);
  border-top: 1px solid var(--border);
  /* La barre d'accueil de l'iPhone mange ~34px : on rembourre en plus */
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.tabbar-inner {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  align-items: stretch;
}
.tabbar a, .tabbar button {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px;
  /* 44px de cible tactile minimum (skill make-interfaces-feel-better) */
  min-height: 52px;
  padding: var(--s2) 2px;
  border: none; background: none;
  color: var(--text-muted);
  font-family: inherit;
  font-size: 0.64rem;
  font-weight: 640;
  letter-spacing: -0.01em;
  text-decoration: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition-property: color, background-color;
  transition-duration: 140ms;
  transition-timing-function: var(--ease);
}
.tabbar svg {
  width: 21px; height: 21px;
  fill: none; stroke: currentColor; stroke-width: 1.9;
  stroke-linecap: round; stroke-linejoin: round;
}
/* L'onglet actif se signale par la couleur ET un trait : la couleur seule
   exclut les daltoniens (le pendant visuel de `aria-current`). */
.tabbar a { position: relative; }
.tabbar a.active { color: var(--accent); }
.tabbar a.active::before {
  content: "";
  position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  width: 26px; height: 2px; border-radius: 0 0 2px 2px;
  background: var(--accent);
}
/* Retour tactile : le pressé doit se sentir, sans gesticuler */
.tabbar a:active, .tabbar button:active { background: var(--surface-2); }
.tabbar .tb-label {
  max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---------- Tableaux -> cartes (opt-in par `.cards-sm`) ----------
   Système de créneaux explicite : chaque <td> qui doit apparaître sur mobile
   porte un `data-m` nommant sa place. Les cellules NON marquées disparaissent.
   Volontairement opt-in : les pages non encore migrées (screener, marchés,
   ETF, bot…) gardent le défilement horizontal plutôt que de rendre des
   cartes vides. `data-label` fournit l'intitulé, l'en-tête étant masqué. */
@media (max-width: 640px) {
  table.cards-sm { display: block; border-collapse: separate; }
  table.cards-sm thead { display: none; }
  table.cards-sm tbody { display: flex; flex-direction: column; gap: var(--s3); }

  /* La carte. Rayon concentrique : le rayon extérieur absorbe le padding
     (principe du skill), donc on reste sur --radius avec un padding modéré. */
  table.cards-sm tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: baseline;
    gap: 3px var(--s3);
    padding: var(--s3) var(--s4);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
  }
  table.cards-sm tr:active { background: var(--surface-2); }
  /* Annule la zébrure et le figeage de colonne du mode tableau */
  table.cards-sm tbody tr:nth-child(even) td,
  table.cards-sm tbody tr:hover td { background: none; }
  table.cards-sm td {
    display: none;
    padding: 0; border: none; background: none;
    text-align: left; white-space: normal;
  }
  table.cards-sm td.title-cell:first-child,
  table.cards-sm th:first-child { position: static; box-shadow: none; }
  table.cards-sm td[data-m] { display: block; }

  /* `order` est indispensable : la grille place les cellules dans l'ordre du
     DOM, or celui-ci suit l'ordre des COLONNES du tableau (où un « Marché »
     peut précéder le cours). L'ordre visuel de la carte est donc explicite. */
  table.cards-sm td[data-m="title"]   { order: 1; }
  table.cards-sm td[data-m="price"]   { order: 2; }
  table.cards-sm td[data-m="change"]  { order: 2; }
  table.cards-sm td[data-m="kv"]      { order: 3; }

  /* Créneau « titre » : nom + ticker + badges. Colonne 1 seulement — les
     actions occupent la colonne 2 de la même ligne. */
  table.cards-sm td[data-m="title"] { grid-column: 1; margin-bottom: 2px; }
  table.cards-sm td[data-m="title"] .title-main { font-size: 0.98rem; font-weight: 700; text-wrap: balance; }
  table.cards-sm td[data-m="title"] .title-sub { font-size: 0.74rem; }

  /* Créneaux « cours » / « variation » : la ligne qui saute aux yeux */
  table.cards-sm td[data-m="price"],
  table.cards-sm td[data-m="change"] {
    font-size: 1.12rem; font-weight: 700; letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
    color: var(--text);
    padding-top: 2px;
  }
  table.cards-sm td[data-m="change"] { grid-column: 2; text-align: right; }

  /* Créneaux « clé -> valeur » : un par ligne, intitulé à gauche */
  table.cards-sm td[data-m="kv"] {
    grid-column: 1 / -1;
    display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3);
    font-size: 0.86rem;
    font-variant-numeric: tabular-nums;
  }
  table.cards-sm td[data-m="kv"]::before {
    content: attr(data-label);
    color: var(--text-muted);
    font-size: 0.78rem; font-weight: 600;
    flex: none;
  }
  /* Séparateur avant le 1er couple clé/valeur : sépare l'identité des chiffres */
  table.cards-sm td[data-m="kv"].kv-first {
    margin-top: var(--s2); padding-top: var(--s2);
    border-top: 1px solid var(--border);
  }

  /* Créneau « actions » : boutons à 44px, calés en haut à droite de la carte.
     Placement EXPLICITE (ligne 1, colonne 2) : il sort du flux automatique,
     donc sa position dans le DOM du tableau n'a aucune importance. */
  table.cards-sm td[data-m="actions"] {
    grid-column: 2; grid-row: 1;
    display: flex; gap: var(--s1); justify-content: flex-end; align-self: start;
  }

  /* En-tête de groupe (compte) et sous-total : des bandeaux, pas des cartes */
  table.cards-sm tr.group-header,
  table.cards-sm tr.group-subtotal {
    display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3);
    background: none; border: none; border-radius: 0; padding: var(--s2) var(--s1) 0;
  }
  table.cards-sm tr.group-header { margin-top: var(--s2); }
  table.cards-sm tr.group-header td {
    display: block;
    font-size: 0.7rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--text-muted);
  }
  table.cards-sm tr.group-subtotal {
    border-top: 1px solid var(--border-strong);
    padding-top: var(--s2); margin-top: calc(var(--s2) * -1);
    font-size: 0.86rem; font-variant-numeric: tabular-nums;
  }
  table.cards-sm tr.group-subtotal td[data-m] { display: block; font-weight: 700; }
  table.cards-sm tr.group-subtotal td[data-m="kv"] { display: flex; }
  /* Sous-total : un intitulé à gauche, les montants à droite */
  table.cards-sm td[data-m="sub-label"] {
    display: block;
    color: var(--text-muted); font-weight: 700;
    font-size: 0.72rem; letter-spacing: 0.06em; text-transform: uppercase;
  }
  table.cards-sm td[data-m="sub-val"] { display: block; margin-left: auto; padding-left: var(--s3); }

  /* ⚠️ Lignes qui ne sont PAS des données : état vide, message d'erreur et
     squelette de chargement. Leurs <td> n'ont pas de `data-m` (il n'y a rien à
     ranger dans un créneau), donc la règle « on masque les cellules non
     marquées » les faisait disparaître : la carte restait vide, et le message
     « aucune position » devenait invisible sur mobile. On les réaffiche
     explicitement, en pleine largeur. */
  table.cards-sm td.recap-empty { display: block; grid-column: 1 / -1; text-align: center; }
  table.cards-sm tr.skel-row { grid-template-columns: 1fr; }
  table.cards-sm tr.skel-row td { display: none; }
  /* Deux barres suffisent à signaler « ça charge » : une carte de 11 barres
     grises ne dit rien de plus et fait 11 fois la hauteur. */
  table.cards-sm tr.skel-row td:nth-child(1),
  table.cards-sm tr.skel-row td:nth-child(2) { display: block; }

  /* Une carte n'a pas besoin du cadre de la section par-dessus */
  .table-wrap:has(table.cards-sm) { padding: 0; background: none; border: none; box-shadow: none; }
  .table-wrap:has(table.cards-sm) .table-title { padding: 0 var(--s1); }
}

/* ---------- Bloc mobile principal ---------- */
@media (max-width: 640px) {
  /* La barre basse remplace le hamburger : elle est atteignable au pouce.
     Le tiroir reste la porte des 19 destinations, via « Plus ». */
  .tabbar { display: block; }
  .nav-burger { display: none !important; }
  body.has-sidebar > .market-header { padding-left: 0; }

  /* Place pour la barre basse : hauteur + encoche du bas. Sans ça le dernier
     élément de chaque page est inatteignable, caché sous la barre. */
  body.has-sidebar,
  body.has-sidebar.nav-collapsed {
    padding-bottom: calc(56px + env(safe-area-inset-bottom, 0px) + var(--s5));
  }
  /* L'overlay du tiroir doit couvrir la barre basse (z 58) */
  .nav-overlay { z-index: 59; }
  /* Le tiroir respecte l'encoche du bas lui aussi */
  .sidebar { padding-bottom: calc(var(--s4) + env(safe-area-inset-bottom, 0px)); }

  /* Cibles tactiles : 44px partout où on tape. Les boutons de ligne faisaient
     ~24px — infiniment ratables au pouce (skill : 44x44 recommandé). */
  button.chart-btn, button.delete, .ind-btn, .mev-del, .u-actions button {
    min-width: 44px; min-height: 44px;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 1rem;
  }
  /* Le ✕ de suppression reste discret mais tapable, et toujours visible
     (pas de :hover sur un écran tactile). */
  button.delete { opacity: 1; }
  .toolbar input, .toolbar select, .toolbar button,
  .page-actions button, .btn-primary, .btn-ghost {
    min-height: 44px;
  }
  /* iOS zoome sur tout champ dont la police est < 16px : ça décale la page
     entière et on ne revient jamais au bon niveau de zoom. */
  input, select, textarea { font-size: 16px; }

  /* Modales en feuille : elles montent du bas, respectent l'encoche, et se
     ferment d'un pouce. Le bouton fermer passe lui aussi à 44px. */
  .modal { padding-bottom: calc(var(--s5) + env(safe-area-inset-bottom, 0px)); }
  .modal-close { min-width: 44px; min-height: 44px; display: grid; place-items: center; }

  /* Les onglets de la fiche récap défilent au doigt plutôt que de se tasser */
  .recap-tabs, .range-tabs, .layer-tabs, .type-tabs {
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    flex-wrap: nowrap; scrollbar-width: none;
  }
  .recap-tabs::-webkit-scrollbar, .range-tabs::-webkit-scrollbar,
  .layer-tabs::-webkit-scrollbar, .type-tabs::-webkit-scrollbar { display: none; }
  .range-tabs button, .layer-tabs button { min-height: 40px; white-space: nowrap; }

  /* Confort de lecture : titres qui ne cassent pas n'importe où, chiffres
     alignés, pas de surlignage bleu au tap. */
  h1, h2, .title-main { text-wrap: balance; }
  .recap-summary, .sec-news-title, .news-title { text-wrap: pretty; }
  a, button, .clickable-row, .prospect-row { -webkit-tap-highlight-color: transparent; }
  /* Le rebond élastique de Safari sous une position:fixed donne un effet cassé */
  body { overscroll-behavior-y: none; }
}

/* Contenu réservé au mobile : sur téléphone certaines colonnes disparaissent
   (secteur, place, badge PEA) et leur information doit remonter dans le bloc
   titre de la carte — sans pour autant la DUPLIQUER sur desktop, où la colonne
   existe toujours. */
.only-sm { display: none; }
@media (max-width: 640px) {
  .only-sm { display: inline; }
  /* Un conteneur de bloc (ex. .title-sub) doit rester un bloc, pas devenir inline */
  div.only-sm, .title-sub.only-sm { display: block; }
}

/* Lissage des polices sur macOS/iOS : sans ça le texte fin paraît gras et sale */
html { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }

/* Squelette du hero : mêmes gabarits que le hero réel, pour que le
   remplacement ne fasse pas sauter la mise en page (pas de saut cumulé). */
.hero-skel .hero-side > div { display: flex; flex-direction: column; gap: 2px; }
.hero-skel .skel { height: 12px; }

/* ============================================================
   REFONTE 2026 — panneaux repliables, tiroir d'import, filtres
   ============================================================ */

/* ===== Panneau repliable (<details class="panel">) =====
   Le motif structurant de la refonte : ce qui ne répond pas à la question
   qu'on se pose EN ARRIVANT se replie. Fermé, un panneau coûte une ligne. */
.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: var(--s4);
  overflow: hidden;
}
.panel-head {
  display: flex; align-items: baseline; gap: var(--s3); flex-wrap: wrap;
  padding: var(--s3) var(--s4);
  cursor: pointer;
  list-style: none;
  user-select: none;
  transition: background var(--fast);
}
.panel-head::-webkit-details-marker { display: none; }
.panel-head:hover { background: var(--surface-2); }
.panel-head::before {
  content: "";
  width: 7px; height: 7px; flex: none; align-self: center;
  border-right: 1.6px solid var(--text-muted);
  border-bottom: 1.6px solid var(--text-muted);
  transform: rotate(-45deg);
  transition: transform var(--fast);
}
.panel[open] > .panel-head::before { transform: rotate(45deg); }
.panel-title { font-family: var(--font-display); font-weight: var(--fw-semibold); font-size: var(--fs-md); letter-spacing: -0.015em; }
.panel-hint { font-size: var(--fs-xs); color: var(--text-muted); }
.panel-body { padding: var(--s4); border-top: 1px solid var(--border); }
.panel-head:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* ===== Tiroir d'import =====
   Le formulaire à gauche, le format attendu à droite : la question « quelles
   colonnes ? » se posait au moment de choisir le fichier, pas avant. */
.import-body { display: grid; grid-template-columns: minmax(240px, 1fr) minmax(300px, 1.15fr); gap: var(--s5); align-items: start; }
@media (max-width: 860px) { .import-body { grid-template-columns: 1fr; } }
.import-form-col form { display: flex; gap: var(--s3); flex-wrap: wrap; align-items: center; }
.import-form-col input[type="file"] { flex: 1 1 200px; font-size: var(--fs-sm); }
.import-note { font-size: var(--fs-xs); color: var(--text-muted); margin: var(--s3) 0 0; max-width: 46ch; line-height: 1.55; }
.import-spec-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); flex-wrap: wrap; margin-bottom: var(--s3); }
.import-spec-head h3 { margin: 0; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.07em; color: var(--text-muted); }
.import-spec-head .btn-ghost { text-decoration: none; }
.import-spec-head .btn-ghost svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.spec-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.spec-table th {
  text-align: left; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-muted); font-weight: var(--fw-semibold);
  padding: 0 var(--s3) var(--s2) 0; border-bottom: 1px solid var(--border);
}
.spec-table td { padding: 0.4rem var(--s3) 0.4rem 0; border-bottom: 1px solid color-mix(in srgb, var(--border) 55%, transparent); vertical-align: top; }
.spec-table code { font-family: var(--font-mono); font-size: 0.85em; color: var(--text); }
.spec-table td span { display: block; font-size: var(--fs-xs); color: var(--text-muted); }
.spec-table td:last-child { font-family: var(--font-mono); font-size: 0.82em; color: var(--text-muted); }
.import-errors { margin: var(--s2) 0 0; padding-left: 1.1rem; font-size: var(--fs-sm); color: var(--text-muted); }
#go-import svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }

/* La carte du portefeuille vit dans un panneau : plus de double cadre. */
#market-map .mmap { height: clamp(220px, 30vh, 320px); }

/* ===== Filtres du tableau de bord ===== */
.dash-filters {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3) var(--s5);
  padding: var(--s3) var(--s4);
  margin-bottom: var(--s4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.dash-filters:empty { display: none; }
.dash-filter-group { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
.dash-filter-label {
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.07em;
  color: var(--text-muted); font-weight: var(--fw-semibold);
}
.dash-reset { margin-left: auto; }
.chart-sub {
  display: block; margin-top: 2px;
  font-size: var(--fs-xs); font-weight: var(--fw-regular);
  color: var(--text-muted); letter-spacing: 0;
}
.donut-total { font-family: var(--font-mono); font-size: 17px; font-weight: 500; fill: var(--text); }
.donut-total-l { font-size: 9px; fill: var(--text-muted); letter-spacing: 0.06em; text-transform: uppercase; }
.bar-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ============================================================
   SIMULATEUR DE DIVIDENDES — la seule section de l'app dont les
   chiffres ne sont PAS des mesures. Le badge est permanent, pas
   une infobulle : une hypothèse qu'il faut survoler pour voir
   n'existe pas.
   ============================================================ */
.sim-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--s5);
  margin-bottom: var(--s4);
  box-shadow: var(--shadow);
}
.sim-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s4); flex-wrap: wrap; }
.sim-head h2 { margin: 0; font-size: var(--fs-xl); }
.sim-sub { margin: 4px 0 0; color: var(--text-muted); font-size: var(--fs-sm); max-width: 60ch; }
.badge-sim {
  flex: none;
  font-size: var(--fs-xs); font-weight: var(--fw-bold);
  text-transform: uppercase; letter-spacing: 0.1em;
  padding: 0.22rem 0.6rem; border-radius: 999px;
  color: var(--accent);
  background: var(--accent-weak);
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  cursor: help;
}

.sim-controls {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--s4);
  margin: var(--s5) 0;
  padding: var(--s4) 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.sim-ctrl { display: flex; flex-direction: column; gap: 6px; }
.sim-ctrl-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s2); font-size: var(--fs-sm); }
.sim-ctrl-head b { font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--accent); }
.sim-ctrl-aide { font-size: var(--fs-xs); color: var(--text-muted); line-height: 1.35; }
.sim-ctrl input[type="range"] { width: 100%; accent-color: var(--accent); cursor: pointer; }
.sim-ranges { display: flex; gap: 4px; flex-wrap: wrap; }
.sim-range {
  font-size: var(--fs-xs); font-weight: 600; padding: 0.25rem 0.55rem;
  border-radius: var(--radius-sm); border: 1px solid var(--border);
  background: var(--surface-2); color: var(--text-muted); cursor: pointer; min-height: 0;
}
.sim-range:hover { border-color: var(--border-strong); color: var(--text); }
.sim-range.on { background: var(--accent-weak); border-color: color-mix(in srgb, var(--accent) 40%, transparent); color: var(--accent); }

.sim-key { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: var(--s3); margin-bottom: var(--s5); }
.sim-key .rk {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius); padding: var(--s3) var(--s4);
}
.rk-l { display: block; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.07em; color: var(--text-muted); font-weight: var(--fw-semibold); }
.rk-v { display: block; font-size: var(--fs-lg); font-weight: var(--fw-medium); letter-spacing: -0.03em; margin-top: 4px; }
.rk-s { display: block; font-size: var(--fs-xs); color: var(--text-muted); margin-top: 2px; }

/* Graphique : capital et trésorerie, UN SEUL axe (deux cumuls en euros). */
.sim-chart { position: relative; }
.sim-svg { width: 100%; height: clamp(200px, 30vh, 280px); display: block; overflow: visible; }
.sim-grid { stroke: var(--border); stroke-width: 1; vector-effect: non-scaling-stroke; }
.sim-tick { font-size: 10px; fill: var(--text-muted); font-family: var(--font-mono); }
.sim-area.cap { fill: color-mix(in srgb, var(--c1) 20%, transparent); }
.sim-area.tre { fill: color-mix(in srgb, var(--c3) 22%, transparent); }
.sim-line { fill: none; stroke-width: 2; vector-effect: non-scaling-stroke; stroke-linejoin: round; stroke-linecap: round; }
.sim-line.cap { stroke: var(--c1); }
.sim-line.tre { stroke: var(--c3); }
/* Étiquettes de fin de courbe : cernées de la couleur de surface (`paint-order:
   stroke`) pour rester lisibles quand elles passent sur l'aire remplie. */
.sim-end {
  font-family: var(--font-mono); font-size: 11px; font-weight: 500;
  paint-order: stroke; stroke: var(--surface); stroke-width: 3px;
}
.sim-end.cap { fill: var(--c1); }
.sim-end.tre { fill: var(--c3); }
.sim-cross { stroke: var(--text-muted); stroke-width: 1; stroke-dasharray: 3 3; vector-effect: non-scaling-stroke; pointer-events: none; }
.sim-hit { fill: transparent; cursor: crosshair; }
.sim-hit:hover { fill: color-mix(in srgb, var(--text) 4%, transparent); }
.sim-tip {
  position: absolute; top: 4px; transform: translateX(-50%);
  background: var(--surface); border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-lg);
  padding: var(--s2) var(--s3); font-size: var(--fs-xs);
  display: flex; flex-direction: column; gap: 2px; pointer-events: none; z-index: 3;
  white-space: nowrap;
}
/* `display: flex` bat l'attribut `hidden` (qui n'est qu'un `display: none` de
   la feuille de l'agent, moins spécifique) : l'infobulle restait donc affichée,
   vide, en haut du graphique — un rectangle blanc que j'ai d'abord pris pour un
   pastille de légende cassée. Il faut le dire explicitement. */
.sim-tip[hidden] { display: none; }
.sim-tip > b { font-family: var(--font-mono); }
.sim-tip span { display: flex; align-items: center; gap: 6px; color: var(--text-muted); }
.sim-tip span b { color: var(--text); font-family: var(--font-mono); margin-left: auto; }

.sim-legend { display: flex; gap: var(--s4); flex-wrap: wrap; font-size: var(--fs-xs); color: var(--text-muted); margin-bottom: var(--s2); }
.sim-key-item { display: inline-flex; align-items: center; gap: 6px; }
.sim-swatch { width: 10px; height: 10px; border-radius: 3px; flex: none; display: inline-block; }
.sim-swatch.cap, .sim-swatch.reinv { background: var(--c1); }
.sim-swatch.tre, .sim-swatch.cash { background: var(--c3); }

.sim-bars-card { margin-top: var(--s5); }
.sim-bars { display: flex; flex-direction: column; gap: 5px; }
.sim-bar-row { display: grid; grid-template-columns: 46px 1fr auto; align-items: center; gap: var(--s3); font-size: var(--fs-sm); }
.sim-bar-an { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--text-muted); }
.sim-bar-track { display: flex; height: 14px; background: var(--surface-2); border-radius: 4px; overflow: hidden; }
/* 2px de SURFACE entre les deux segments : la frontière reste lisible même si
   la couleur ne sépare pas (daltonisme, impression noir et blanc). */
.sim-bar-seg + .sim-bar-seg { border-left: 2px solid var(--surface); }
.sim-bar-seg.reinv { background: var(--c1); }
.sim-bar-seg.cash { background: var(--c3); }
.sim-bar-seg:first-child { border-radius: 4px 0 0 4px; }
.sim-bar-seg:last-child { border-radius: 0 4px 4px 0; }
.sim-bar-val { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--text); min-width: 68px; text-align: right; }

.sim-hypo { margin-top: var(--s5); padding-top: var(--s4); border-top: 1px solid var(--border); }
.sim-hypo-form { display: flex; gap: var(--s3); flex-wrap: wrap; align-items: center; }
.sim-hypo-form input { flex: 0 1 180px; }
.sim-chips { display: flex; gap: var(--s2); flex-wrap: wrap; margin-top: var(--s3); }
.sim-chip {
  display: inline-flex; align-items: center; gap: var(--s2);
  padding: 0.22rem 0.3rem 0.22rem 0.6rem;
  border: 1px dashed color-mix(in srgb, var(--accent) 55%, transparent);
  border-radius: 999px; background: var(--accent-weak);
  font-size: var(--fs-xs);
}
/* Bordure POINTILLÉE, à dessein : ces lignes n'existent pas dans le
   portefeuille. Le trait discontinu dit « provisoire » sans un mot. */
.sim-chip b { font-family: var(--font-mono); }
.sim-chip span { color: var(--text-muted); }
.sim-chip-x {
  border: none; background: none; color: var(--text-muted); cursor: pointer;
  font-size: 1rem; line-height: 1; padding: 0 4px; min-height: 0;
}
.sim-chip-x:hover { color: var(--neg); }
.sim-echecs { margin: var(--s2) 0 0; padding-left: 1.1rem; font-size: var(--fs-xs); color: var(--warn); }
.sim-sources { margin: var(--s4) 0 0; font-size: var(--fs-xs); color: var(--warn); line-height: 1.5; }
.sim-foot { margin: var(--s3) 0 0; font-size: var(--fs-xs); color: var(--text-muted); line-height: 1.55; max-width: 92ch; }
@media (max-width: 720px) { .sim-card { padding: var(--s4); } }
