/* gloppr·crypto — feuille de style
   Palette divergente validée (blue #2a78d6 ↔ red #e34948, midpoint gris).
   Les deux modes sont choisis, pas dérivés par inversion automatique. */

/* IBM Plex Sans — recommandée par la base UI/UX pour « banques, finance,
   assurance, investissement ». Hébergée localement, sous-ensemble latin :
   la règle de la maison interdit toute ressource externe au chargement, et
   un appel à Google Fonts trahirait aussi le visiteur. Trois graisses
   (~86 Ko au total). Piège corrigé le 4 août 2026 : les fichiers 600 et 700
   étaient des copies du Regular — tout le gras du site était synthétisé par
   le navigateur. Vérifier `usWeightClass` avant de remplacer un woff2.
   `swap` : le texte s'affiche immédiatement dans la police système. */
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/plex-400.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/plex-600.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fonts/plex-700.woff2') format('woff2');
}

:root {
  color-scheme: light;
  --surface-1:      #fcfcfb;
  --surface-page:   #f9f9f7;
  --text-primary:   #0b0b0b;
  --text-secondary: #52514e;
  --text-muted:     #898781;
  --gridline:       #e1e0d9;
  --baseline:       #c3c2b7;

  /* Pôles divergents + midpoint neutre. */
  --pole-buy:       #2a78d6;
  --pole-sell:      #e34948;
  --pole-neutral:   #898781;
  --midpoint:       #f0efec;

  /* Échelle d'élévation (base UI/UX, « Dimensional Layering »). Quatre
     niveaux plutôt qu'un filet unique : sans profondeur, tous les blocs
     pèsent pareil et l'œil n'a aucun point d'entrée. */
  --elev-1: 0 1px 2px rgb(0 0 0 / .05), 0 1px 3px rgb(0 0 0 / .07);
  --elev-2: 0 2px 4px rgb(0 0 0 / .05), 0 4px 10px rgb(0 0 0 / .07);
  --elev-3: 0 4px 8px rgb(0 0 0 / .06), 0 12px 28px rgb(0 0 0 / .10);

  --radius: 10px;
  --font: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) {
    color-scheme: dark;
    --surface-1:      #1a1a19;
    --surface-page:   #0d0d0d;
    --text-primary:   #ffffff;
    --text-secondary: #c3c2b7;
    --text-muted:     #898781;
    --gridline:       #2c2c2a;
    --baseline:       #383835;
    --pole-buy:       #3987e5;
    --pole-sell:      #e66767;
    --pole-neutral:   #898781;
    --midpoint:       #383835;
  --elev-1: 0 1px 2px rgb(0 0 0 / .5), inset 0 1px 0 rgb(255 255 255 / .03);
  --elev-2: 0 4px 12px rgb(0 0 0 / .55), inset 0 1px 0 rgb(255 255 255 / .04);
  --elev-3: 0 12px 32px rgb(0 0 0 / .6), inset 0 1px 0 rgb(255 255 255 / .05);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --surface-1:      #1a1a19;
  --surface-page:   #0d0d0d;
  --text-primary:   #ffffff;
  --text-secondary: #c3c2b7;
  --text-muted:     #898781;
  --gridline:       #2c2c2a;
  --baseline:       #383835;
  --pole-buy:       #3987e5;
  --pole-sell:      #e66767;
  --pole-neutral:   #898781;
  --midpoint:       #383835;
  --elev-1: 0 1px 2px rgb(0 0 0 / .5), inset 0 1px 0 rgb(255 255 255 / .03);
  --elev-2: 0 4px 12px rgb(0 0 0 / .55), inset 0 1px 0 rgb(255 255 255 / .04);
  --elev-3: 0 12px 32px rgb(0 0 0 / .6), inset 0 1px 0 rgb(255 255 255 / .05);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--font);
  background: var(--surface-page);
  color: var(--text-primary);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

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

/* En-tête collant. `sticky` plutôt que `fixed` : l'élément garde sa place
   dans le flux, donc rien à compenser en haut de page et aucun saut au
   chargement. Le fond doit être opaque — le contenu défile dessous. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 90;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 1rem 1.5rem;
  border-bottom: 1px solid var(--gridline);
  background: var(--surface-1);
  transition: box-shadow .18s ease;
}

/* Ombre portée seulement une fois décollé du haut : au repos, la barre doit
   rester à plat, sinon elle paraît flotter sur une page non défilée. */
.site-header.est-colle { box-shadow: var(--elev-2); }

/* Les ancres (#signaux, #methode) atterrissaient sous la barre : la réserve
   évite de scroller à la main après chaque clic. */
html { scroll-padding-top: 5.5rem; }

/* Écran bas : une barre collante mangerait trop de hauteur utile. */
@media (max-height: 480px) {
  .site-header { position: static; }
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font-weight: 650;
  font-size: 1.05rem;
  letter-spacing: -.01em;
  color: var(--text-primary);
  text-decoration: none;
}

.brand-mark { color: var(--pole-buy); }

/* Le symbole est en dégradé turquoise : lisible sur les deux thèmes, il ne
   demande aucune variante. Dimensions fixées en HTML pour réserver la place
   et éviter le décalage de mise en page au chargement. */
.brand-logo { display: block; width: 26px; height: 26px; object-fit: contain; }
.brand-accent { color: var(--text-muted); font-weight: 500; }

.site-header nav { display: flex; gap: 1.25rem; }

.site-header nav a {
  color: var(--text-secondary);
  text-decoration: none;
  font-size: .9rem;
}

.site-header nav a:hover { color: var(--text-primary); }

/* Page courante : texte plein + soulignement bleu, sans décaler la ligne. */
.site-header nav a[aria-current="page"] {
  color: var(--text-primary);
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: var(--pole-buy);
  text-decoration-thickness: 2px;
  text-underline-offset: 6px;
}

/* ---------- Sous-menu de l'espace personnel ----------
   Trois pages qui forment un même espace : une seule entrée dans la barre,
   le détail au déroulé. Le panneau s'ouvre au survol, au focus clavier
   (`:focus-within`) et au clic — cette dernière voie étant la seule qui
   existe au tactile. */

.nav-group { position: relative; display: inline-flex; }

.nav-group-btn {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: .9rem;
  color: var(--text-secondary);
  cursor: pointer;
}

.nav-group-btn:hover { color: var(--text-primary); }

/* Section courante : même traitement que nav a[aria-current], pour que la
   barre ne parle qu'un seul langage. */
.nav-group-active .nav-group-btn {
  color: var(--text-primary);
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: var(--pole-buy);
  text-decoration-thickness: 2px;
  text-underline-offset: 6px;
}

.nav-submenu {
  position: absolute;
  top: calc(100% + .55rem);
  left: 0;
  z-index: 70;
  display: none;
  flex-direction: column;
  min-width: 12rem;
  padding: .35rem;
  background: var(--surface-1);
  border: 1px solid var(--gridline);
  border-radius: var(--radius);
  box-shadow: 0 8px 28px rgb(0 0 0 / .14);
}

.nav-group:hover .nav-submenu,
.nav-group:focus-within .nav-submenu,
.nav-group.is-open .nav-submenu { display: flex; }

/* Zone de rattrapage : sans elle, le curseur traverse le vide entre le bouton
   et le panneau, et le menu se referme en cours de route. */
.nav-group::after {
  content: '';
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  height: .6rem;
}

.nav-submenu a {
  padding: .45rem .6rem;
  border-radius: 6px;
  font-size: .88rem;
  white-space: nowrap;
}

.nav-submenu a:hover { background: var(--midpoint); color: var(--text-primary); }

/* Dans le panneau, la page courante se marque par un fond, pas par un
   soulignement : trois entrées soulignées côte à côte deviennent illisibles. */
.nav-submenu a[aria-current="page"] {
  background: color-mix(in srgb, var(--pole-buy) 12%, transparent);
  color: var(--text-primary);
  font-weight: 600;
  text-decoration: none;
}

/* Barre d'onglets en tête des trois pages de l'espace. */

/* ---------- Interrupteur de thème ---------- */

.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  margin: -.35rem 0;              /* n'épaissit pas la barre de navigation */
  padding: 0;
  border: 1px solid var(--gridline);
  border-radius: 50%;
  background: none;
  color: var(--text-secondary);
  cursor: pointer;
}

.theme-toggle:hover { color: var(--text-primary); border-color: var(--baseline); }

/* En clair on propose la lune (passer au sombre), en sombre le soleil. */
.theme-toggle .icon-sun { display: none; }

@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) .theme-toggle .icon-sun { display: block; }
  :root:where(:not([data-theme="light"])) .theme-toggle .icon-moon { display: none; }
}

:root[data-theme="dark"] .theme-toggle .icon-sun { display: block; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: none; }

/* ---------- Focus clavier ---------- */

/* Les champs de formulaire ont déjà leur style de focus ; ici, tout ce qui
   se navigue au clavier sans être un champ. */
a:focus-visible,
button:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--pole-buy);
  outline-offset: 2px;
  border-radius: 3px;
}

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

main {
  max-width: 1120px;
  margin: 0 auto;
  padding: 2rem 1.5rem 3rem;
}

.page-head { margin-bottom: 1.75rem; }

.page-head h1 {
  margin: 0 0 .35rem;
  font-size: 1.6rem;
  letter-spacing: -.02em;
}

.page-head p {
  margin: 0;
  color: var(--text-secondary);
  font-size: .92rem;
}

/* Note factuelle sous l'introduction : discrète, jamais promotionnelle. */
.page-head .page-note {
  margin-top: .45rem;
  font-size: .8rem;
  color: var(--text-muted);
}

/* ---------- Landing institutionnelle (refonte du 3 août 2026) ----------
   Motif « Trust & Authority » : mission, preuve chiffrée, méthode, limites.
   Retenue assumée : pas de titre géant façon agence — une institution parle
   bas. L'échelle typographique reste bornée (clamp 2 → 3,1 rem), l'accent
   coloré est réservé au CTA et à un seul segment de titre. */

/* Le héros pose un fond distinct du reste de la page : sans lui, la landing
   n'était qu'une pile de blocs sur une surface uniforme, sans point d'entrée
   pour l'œil. Le dégradé reste très léger — on cherche une assise, pas un
   effet. */
.lp-hero {
  position: relative;
  max-width: 46rem;
  margin: 0 auto 4rem;
  padding: 3rem 1.5rem 3.25rem;
  text-align: center;
}

.lp-hero::before {
  content: '';
  position: absolute;
  inset: 0 -50vw;
  z-index: -1;
  background:
    radial-gradient(60% 80% at 50% 0%,
      color-mix(in srgb, var(--pole-buy) 7%, transparent), transparent 70%),
    var(--surface-1);
  border-bottom: 1px solid var(--gridline);
}

/* Héros en deux colonnes quand un graphique vedette est disponible : le
   produit se montre au lieu de se décrire. Sans données (cache vide), le
   héros retombe sur la version centrée d'origine — d'où la variante. */
.lp-hero.has-chart { max-width: 76rem; text-align: left; }

.lp-hero-grid {
  display: grid;
  grid-template-columns: 1fr 1.15fr;
  gap: 2.5rem;
  align-items: center;
}

.lp-hero.has-chart .lp-lede,
.lp-hero.has-chart .lp-hook { margin-left: 0; margin-right: 0; }
.lp-hero.has-chart .lp-actions { justify-content: flex-start; }

/* Carte graphique vedette : mêmes conventions que partout — bleu monte,
   rouge descend, prix en mono. Le SVG est rendu côté serveur depuis le
   cache de clôtures, aucun script requis. */
.chart-card {
  background: var(--surface-1);
  border: 1px solid var(--gridline);
  border-radius: var(--radius);
  box-shadow: var(--elev-2);
  padding: 1rem 1.1rem .55rem;
}

.chart-top { display: flex; align-items: center; gap: .6rem; }
.chart-top .chart-nom { font-weight: 700; line-height: 1.25; }
.chart-top .chart-sym { color: var(--text-muted); font-size: .78rem; }
.chart-px { margin-left: auto; text-align: right; }
.chart-px .chart-val {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-size: 1.12rem;
}

.chart-svg { display: block; width: 100%; height: auto; margin-top: .35rem; }

.chart-meta {
  display: flex;
  align-items: center;
  gap: .9rem;
  flex-wrap: wrap;
  font-size: .74rem;
  color: var(--text-muted);
  padding-top: .5rem;
  margin-top: .3rem;
  border-top: 1px solid var(--gridline);
}
.chart-meta b { color: var(--text-secondary); font-weight: 600; }

.lp-eyebrow {
  margin: 0 0 1rem;
  font-size: .74rem;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.lp-title {
  margin: 0 0 1.25rem;
  font-size: clamp(2.2rem, 5.6vw, 3.9rem);
  line-height: 1.08;
  letter-spacing: -.035em;
  font-weight: 700;
}

.lp-title-accent { color: var(--pole-buy); }

.lp-lede {
  margin: 0 auto 2rem;
  max-width: 40rem;
  font-size: 1.02rem;
  line-height: 1.68;
  color: var(--text-secondary);
}

/* L'accroche : la seule phrase que le visiteur retiendra s'il ne lit rien
   d'autre. Filets au-dessus et en dessous plutôt qu'un encadré — un cadre
   se lit comme un avertissement. */
.lp-hook {
  margin: 0 auto 2rem;
  padding: .9rem 0;
  max-width: 38rem;
  border-top: 1px solid var(--gridline);
  border-bottom: 1px solid var(--gridline);
  font-size: .95rem;
  line-height: 1.6;
  color: var(--text-secondary);
}

.lp-hook strong { color: var(--text-primary); }

.lp-actions {
  display: flex;
  gap: .7rem;
  justify-content: center;
  flex-wrap: wrap;
}

.lp-note {
  margin: 1rem 0 0;
  font-size: .78rem;
  color: var(--text-muted);
}

/* ---------- Bandeau de cours ----------
   Une ligne de tickers sous l'en-tête, à la TradingView : logo, code, prix,
   variation — les 32 instruments analysés, en boucle.

   Ce bandeau était fixe, et son commentaire disait pourquoi : « les cours
   sont relevés à heures fixes, un mouvement mentirait ». L'objection visait
   le fait de suggérer un flux temps réel, pas le défilement en soi. Elle est
   traitée plutôt qu'écartée — vitesse CONSTANTE et lente (3 s par actif), donc
   lisible comme un carrousel et non comme un tic de marché ; et rien ne clignote
   ni ne se met à jour. Ce qui bouge est la fenêtre, jamais les valeurs.

   Trois gardes, chacune contre un défaut réel de ce motif :
   - la piste s'arrête au survol ET au focus clavier, sinon une cible qui se
     dérobe rend les liens impossibles à cliquer — et impossibles à atteindre
     au clavier, ce qui serait une régression d'accessibilité ;
   - `prefers-reduced-motion` rend le défilement manuel d'origine, intact ;
   - la copie de la liste est `aria-hidden` côté HTML : un lecteur d'écran ne
     doit pas énoncer trente-deux actifs deux fois. */

.tape {
  display: flex;
  overflow-x: hidden;
  scrollbar-width: none;
  background: var(--surface-1);
  border-bottom: 1px solid var(--gridline);
  margin-bottom: 0;
}
.tape::-webkit-scrollbar { display: none; }

/* La piste porte les deux exemplaires ; l'animation la ramène à zéro quand la
   copie occupe exactement la place de l'original, d'où la boucle sans couture.
   -50 % et non une largeur en pixels : la piste s'adapte au nombre d'actifs. */
.tape-piste {
  display: flex;
  flex: 0 0 auto;
  animation-name: tape-defile;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  will-change: transform;
}
.tape-copie { display: flex; }
.tape:hover .tape-piste,
.tape:focus-within .tape-piste { animation-play-state: paused; }

@keyframes tape-defile {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
  .tape { overflow-x: auto; }
  .tape-piste { animation: none; }
  .tape-copie { display: none; }
}

.tape a {
  display: flex;
  align-items: center;
  gap: .45rem;
  padding: .45rem .85rem;
  flex: 0 0 auto;
  border-right: 1px solid var(--gridline);
  font-size: .8rem;
  text-decoration: none;
  color: inherit;
}
.tape a:hover { background: var(--midpoint); }
.tape .tape-sym { font-weight: 600; }
.tape .tape-px {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--text-secondary);
}

/* Pastille de variation, partagée par le bandeau, la table et les tuiles. */
.pct-chip {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: .74rem;
  font-weight: 600;
  padding: .08rem .38rem;
  border-radius: 5px;
  white-space: nowrap;
}
.pct-chip.up   { color: var(--pole-buy);  background: color-mix(in srgb, var(--pole-buy) 12%, transparent); }
.pct-chip.down { color: var(--pole-sell); background: color-mix(in srgb, var(--pole-sell) 12%, transparent); }

/* Pastille de tonalité d'article (−10…+10) : même langage que .pct-chip.
   Rendue par tone_chip() seulement — ne pas la recomposer à la main. */
.tone-chip {
  display: inline-block;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: .72rem;
  font-weight: 700;
  padding: .08rem .4rem;
  border-radius: 5px;
  white-space: nowrap;
}
.tone-chip.tone-up   { color: var(--pole-buy);  background: color-mix(in srgb, var(--pole-buy) 12%, transparent); }
.tone-chip.tone-down { color: var(--pole-sell); background: color-mix(in srgb, var(--pole-sell) 12%, transparent); }
.tone-chip.tone-flat { color: var(--text-secondary); background: var(--midpoint); }
.tone-chip.tone-na   { color: var(--text-muted); border: 1px dashed var(--baseline); font-weight: 600; }

.why-news .tone-chip { margin-right: .4rem; min-width: 3.2em; text-align: center; }

/* ---------- Tête de section partagée ---------- */

.sec-head {
  display: flex;
  align-items: baseline;
  gap: .75rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}
.sec-head h2 { margin: 0; font-size: 1.4rem; letter-spacing: -.02em; }
.sec-head .sec-sub { font-size: .8rem; color: var(--text-muted); }
.sec-head .sec-more {
  margin-left: auto;
  font-size: .82rem;
  font-weight: 600;
  color: var(--pole-buy);
  text-decoration: none;
  white-space: nowrap;
}
.sec-head .sec-more:hover { text-decoration: underline; }

/* Pastille de fraîcheur : le seul point de couleur « vivante » de la page.
   Pas d'animation — un clignotement suggérerait un flux en temps réel, or
   les avis sont produits à heures fixes. */
.sec-dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--pole-buy);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--pole-buy) 18%, transparent);
}

/* ---------- Table des signaux (screener) ----------
   Le produit montré en table dense plutôt qu'en cartes : une ligne par
   actif, balayable, triable. Les colonnes de confort disparaissent sur
   petit écran (.col-opt), l'essentiel — actif, prix, 24 h, signal — reste. */

.screener-sec {
  margin-bottom: 3.5rem;
  scroll-margin-top: 3.5rem;   /* l'ancre #signaux ne colle pas à l'en-tête collant */
}

.screener {
  background: var(--surface-1);
  border: 1px solid var(--gridline);
  border-radius: var(--radius);
  box-shadow: var(--elev-1);
  overflow-x: auto;
}

.screener table { width: 100%; border-collapse: collapse; font-size: .88rem; }

.screener th {
  text-align: left;
  font-size: .7rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--text-muted);
  font-weight: 600;
  padding: .6rem .9rem;
  border-bottom: 1px solid var(--gridline);
  white-space: nowrap;
}

.screener td {
  padding: .55rem .9rem;
  border-bottom: 1px solid var(--gridline);
  vertical-align: middle;
}

.screener tbody tr { transition: background .12s ease; cursor: pointer; }
.screener tbody tr:hover { background: var(--midpoint); }
.screener tbody tr:last-child td { border-bottom: 0; }
.screener tr[hidden] { display: none; }

.scr-asset {
  display: flex;
  align-items: center;
  gap: .65rem;
  text-decoration: none;
  color: inherit;
  min-width: 0;
}
.scr-asset .scr-nom { font-weight: 600; }
.scr-asset .scr-code { color: var(--text-muted); font-size: .76rem; margin-left: .3rem; }

.screener td.num, .screener th.num {
  text-align: right;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

.scr-score { font-weight: 600; }

.scr-spark { display: block; }

.scr-conf { display: flex; align-items: center; gap: .5rem; min-width: 110px; }
.scr-conf .scr-conf-bar {
  flex: 1;
  height: 4px;
  border-radius: 2px;
  background: var(--midpoint);
  overflow: hidden;
}
.scr-conf .scr-conf-bar i { display: block; height: 100%; border-radius: 2px; }
.scr-conf .scr-conf-val {
  font-family: var(--mono);
  font-size: .74rem;
  color: var(--text-secondary);
  min-width: 2.6em;
  text-align: right;
}

.scr-note {
  margin: .9rem 0 0;
  font-size: .82rem;
  color: var(--text-secondary);
}

/* ---------- Carte de marché ----------
   Tuiles teintées par la variation 24 h, aux pôles du site — bleu monte,
   rouge descend, jamais le vert/rouge d'ailleurs. L'intensité suit
   l'amplitude ; le chiffre reste, la couleur n'est qu'un renfort. */

.heat-sec { margin-bottom: 3.5rem; }

.heat {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: .5rem;
}

.heat a {
  border-radius: 8px;
  padding: .65rem .75rem;
  border: 1px solid var(--gridline);
  background: var(--surface-1);
  display: flex;
  flex-direction: column;
  gap: .1rem;
  text-decoration: none;
  color: inherit;
  transition: transform .12s ease, box-shadow .12s ease;
}
.heat a:hover { transform: translateY(-2px); box-shadow: var(--elev-1); }
.heat .heat-sym { font-weight: 700; font-size: .85rem; display: flex; align-items: center; gap: .4rem; }
.heat .heat-pc {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: .78rem;
}

/* Trois usages concrets, avant toute explication de fonctionnement. */
.lp-uses {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 1.5rem 2rem;
  margin-bottom: 3.5rem;
}

.lp-uses article {
  display: flex;
  flex-direction: column;
  gap: .5rem;
  padding: 1.25rem;
  background: var(--surface-1);
  border: 1px solid var(--gridline);
  border-top: 2px solid var(--pole-buy);
  border-radius: var(--radius);
  box-shadow: var(--elev-1);
  transition: box-shadow .18s ease, transform .18s ease;
}

.lp-uses article:hover { box-shadow: var(--elev-3); transform: translateY(-2px); }

.lp-uses h3 {
  margin: 0;
  font-size: 1.02rem;
  letter-spacing: -.015em;
}

.lp-uses p {
  margin: 0;
  font-size: .88rem;
  line-height: 1.6;
  color: var(--text-secondary);
  flex: 1;
}

.lp-uses-link {
  font-size: .83rem;
  font-weight: 600;
  color: var(--pole-buy);
  text-decoration: none;
}

.lp-uses-link:hover { text-decoration: underline; }

/* Bande de preuve : filets fins, chiffres en chasse fixe. Le grid s'adapte
   au nombre réel de cellules — une donnée absente retire la sienne. */
.lp-proof {
  margin: 0 0 3.5rem;
  padding: 1.6rem 0;
  border-top: 1px solid var(--gridline);
  border-bottom: 1px solid var(--gridline);
}

.lp-proof dl {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 1.4rem 1rem;
  margin: 0;
  text-align: center;
}

.lp-proof dt {
  font-family: var(--mono);
  font-size: 1.85rem;
  font-weight: 600;
  letter-spacing: -.02em;
  line-height: 1.1;
}

.lp-proof .lp-unit { font-size: .95rem; color: var(--text-muted); font-weight: 400; }

.lp-proof dd {
  margin: .4rem 0 0;
  font-size: .8rem;
  color: var(--text-muted);
  line-height: 1.4;
}

/* Méthode : titre de section centré, puis les quatre temps. */
.lp-method { margin-bottom: 3.5rem; }

.lp-method-head {
  max-width: 40rem;
  margin: 0 auto 1.8rem;
  text-align: center;
}

.lp-method-head h2 {
  margin: 0 0 .6rem;
  font-size: 1.5rem;
  letter-spacing: -.02em;
}

.lp-method-head p {
  margin: 0;
  color: var(--text-secondary);
  font-size: .92rem;
}

.lp-method .home-pipeline ol {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 1.6rem 2rem;
}

/* ---------- Vitrine d'actualités sur la landing ----------
   Le visuel est le logo de l'actif traité, pas une image d'article : aucune
   n'est stockée, et une photo d'illustration de presse crypto n'informe de
   toute façon jamais sur le contenu. */

.lp-news { margin-bottom: 3.5rem; }

.lp-news-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.2rem;
}

.lp-news-head h2 { margin: 0; font-size: 1.5rem; letter-spacing: -.02em; }

.lp-news-head a {
  font-size: .85rem;
  font-weight: 600;
  color: var(--pole-buy);
  text-decoration: none;
  white-space: nowrap;
}

.lp-news-head a:hover { text-decoration: underline; }

.lp-news-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1rem;
}

.lp-news-card {
  display: flex;
  flex-direction: column;
  background: var(--surface-1);
  border: 1px solid var(--gridline);
  border-radius: var(--radius);
  box-shadow: var(--elev-1);
  overflow: hidden;
  transition: box-shadow .18s ease, transform .18s ease;
}

.lp-news-card:hover { box-shadow: var(--elev-2); transform: translateY(-2px); }

/* Bandeau visuel : fond teinté à la couleur de marque de l'actif traité,
   logo centré. La teinte identifie l'actif, elle ne porte aucun sens
   directionnel — le ton de l'article, lui, reste chiffré à côté du code. */
.lp-news-visuel {
  flex: 0 0 auto;
  height: 96px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.lp-news-corps { min-width: 0; padding: .8rem 1rem 1rem; }

.lp-news-actifs {
  display: flex;
  align-items: center;
  gap: .4rem;
  margin: 0 0 .35rem;
  flex-wrap: wrap;
}

.lp-news-code {
  font-family: var(--mono);
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--text-muted);
}


.lp-news-titre {
  display: block;
  font-size: .92rem;
  font-weight: 600;
  line-height: 1.4;
  color: var(--text-primary);
  text-decoration: none;
}

.lp-news-titre:hover { text-decoration: underline; }

.lp-news-resume {
  margin: .4rem 0 0;
  font-size: .8rem;
  line-height: 1.5;
  color: var(--text-secondary);
}

.lp-news-meta {
  margin: .5rem 0 0;
  font-size: .72rem;
  color: var(--text-muted);
}

.lp-news-note {
  margin: 1.1rem 0 0;
  font-size: .78rem;
  color: var(--text-muted);
  max-width: 46rem;
}

/* Limites : le bloc de crédibilité. Filet à gauche plutôt qu'un cadre —
   une mise en garde encadrée se lit comme une alerte, or ce n'en est pas
   une : c'est une définition du périmètre. */
.lp-limits {
  margin-bottom: 3.5rem;
  padding: 1.6rem 0 1.6rem 1.5rem;
  border-left: 2px solid var(--baseline);
}

.lp-limits h2 {
  margin: 0 0 1.1rem;
  font-size: 1.25rem;
  letter-spacing: -.02em;
}

.lp-limits ul {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1rem 2.2rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.lp-limits li {
  font-size: .89rem;
  line-height: 1.6;
  color: var(--text-secondary);
}

.lp-limits li strong { color: var(--text-primary); }

@media (max-width: 640px) {
  .lp-hero { margin-bottom: 2.5rem; }
  .lp-proof dt { font-size: 1.55rem; }
  .lp-limits { padding-left: 1rem; }
}

/* ---------- Accueil visiteur ---------- */

.home-hero {
  display: grid;
  grid-template-columns: 1.1fr .9fr;
  gap: 2.5rem;
  align-items: start;
  margin: 1rem 0 2rem;
}

.home-intro h1 {
  margin: 0 0 .8rem;
  font-size: 2rem;
  line-height: 1.2;
  letter-spacing: -.02em;
  /* Autorise la pleine largeur du bloc, contrairement au h1 des pages internes. */
  max-width: 22ch;
}

.home-tagline {
  margin: 0 0 1.4rem;
  color: var(--text-secondary);
  font-size: 1rem;
  line-height: 1.6;
  max-width: 46ch;
}

.home-ctas { display: flex; gap: .75rem; flex-wrap: wrap; margin-bottom: 1.6rem; }

.home-stats {
  display: flex;
  gap: 2rem;
  flex-wrap: wrap;
  margin: 0;
  padding-top: 1.1rem;
  border-top: 1px solid var(--gridline);
}

.home-stats dt {
  font-family: var(--mono);
  font-size: 1.25rem;
  font-weight: 650;
  letter-spacing: -.01em;
}

.home-stats dd {
  margin: .1rem 0 0;
  font-size: .78rem;
  color: var(--text-muted);
}

.home-pipeline h2 { margin-top: 0; }

.home-pipeline ol {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1rem;
}

.home-pipeline li {
  display: flex;
  gap: .8rem;
  font-size: .88rem;
  color: var(--text-secondary);
  line-height: 1.55;
}

.home-pipeline li strong { color: var(--text-primary); }

.step-badge {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.7rem;
  height: 1.7rem;
  margin-top: .05rem;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--pole-buy) 45%, transparent);
  background: color-mix(in srgb, var(--pole-buy) 8%, transparent);
  color: var(--pole-buy);
}

.step-badge svg { width: .95rem; height: .95rem; }

/* L'aperçu marché en cartes sparklines (.home-market/.mkt-*) a été remplacé
   le 4 août 2026 par la carte de marché en tuiles (.heat) et les sparklines
   de la table screener — voir plus haut. */

/* Les limites assumées : le bloc le plus important de la page, pas le plus
   voyant. Trois faits, sans pictogramme ni couleur d'alerte. */
.home-truths {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
  margin-bottom: 2.25rem;
}

.home-truths > div {
  background: var(--surface-1);
  border: 1px solid var(--gridline);
  border-radius: var(--radius);
  padding: 1rem 1.15rem;
}

.home-truths h3 {
  margin: 0 0 .4rem;
  font-size: .85rem;
  letter-spacing: .01em;
}

.home-truths p {
  margin: 0;
  font-size: .82rem;
  color: var(--text-secondary);
  line-height: 1.55;
}

@media (max-width: 860px) {
  .home-hero { grid-template-columns: 1fr; gap: 1.5rem; }
  .home-truths { grid-template-columns: 1fr; }
  .home-intro h1 { font-size: 1.6rem; }
}

/* La grille de cartes d'actifs (.asset-grid/.asset-card) a été remplacée le
   4 août 2026 par la table screener (.screener) — le score et le résumé du
   modèle restent lisibles sur la fiche de chaque actif. */

.asset-symbol {
  display: block;
  font-size: .75rem;
  color: var(--text-muted);
  font-family: var(--mono);
  letter-spacing: .02em;
}

.change-up   { color: var(--pole-buy); }
.change-down { color: var(--pole-sell); }

/* ---------- Badge de signal ----------
   La couleur double toujours un libellé et une flèche : jamais seule. */

.signal-badge {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .28rem .6rem;
  border-radius: 999px;
  font-size: .8rem;
  font-weight: 600;
  border: 1px solid transparent;
}

.sig-buy {
  color: var(--pole-buy);
  border-color: color-mix(in srgb, var(--pole-buy) 40%, transparent);
  background: color-mix(in srgb, var(--pole-buy) 10%, transparent);
}

.sig-sell {
  color: var(--pole-sell);
  border-color: color-mix(in srgb, var(--pole-sell) 40%, transparent);
  background: color-mix(in srgb, var(--pole-sell) 10%, transparent);
}

.sig-neutral {
  color: var(--text-secondary);
  border-color: var(--baseline);
  background: var(--midpoint);
}

.signal-arrow { font-size: .7rem; }

/* Confiance sous 50 % : le badge se fait discret — fond retiré, trait
   pointillé. Le doute du modèle doit se voir, pas se deviner. */
.sig-low {
  background: transparent;
  border-style: dashed;
  opacity: .75;
}

/* ---------- Filtre et tri de la table des signaux ---------- */

.grid-tools[hidden] { display: none; }
.grid-tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  margin-bottom: 1rem;
}

.filter-group { display: flex; flex-wrap: wrap; gap: .4rem; }

.chip {
  padding: .3rem .75rem;
  border-radius: 999px;
  border: 1px solid var(--gridline);
  background: var(--surface-1);
  color: var(--text-secondary);
  font: inherit;
  font-size: .82rem;
  cursor: pointer;
}

.chip:hover { color: var(--text-primary); border-color: var(--baseline); }

.chip.is-active {
  color: var(--text-primary);
  border-color: var(--baseline);
  background: var(--midpoint);
  font-weight: 600;
}

.sort-label {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font-size: .82rem;
  color: var(--text-secondary);
}

.sort-label select {
  font: inherit;
  font-size: .82rem;
  color: var(--text-primary);
  background: var(--surface-1);
  border: 1px solid var(--gridline);
  border-radius: 6px;
  padding: .3rem .5rem;
}

/* ---------- Page d'aide ----------
   Créée le 4 août 2026. Sobre : la page explique, elle ne vend pas. Les
   paramètres cités viennent du code réel — voir le commentaire de help.php. */

.help-toc {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem;
  margin-bottom: 2rem;
}

.help-toc a {
  padding: .3rem .75rem;
  border-radius: 999px;
  border: 1px solid var(--gridline);
  background: var(--surface-1);
  color: var(--text-secondary);
  font-size: .82rem;
  text-decoration: none;
}
.help-toc a:hover { color: var(--text-primary); border-color: var(--baseline); }

.help-sec { max-width: 46rem; margin-bottom: 3rem; scroll-margin-top: 3.5rem; }
.help-sec h2 { font-size: 1.3rem; letter-spacing: -.02em; margin: 0 0 .8rem; }
.help-sec p, .help-sec li { color: var(--text-secondary); line-height: 1.65; font-size: .92rem; }
.help-sec li { margin-bottom: .5rem; }
.help-sec strong { color: var(--text-primary); }
/* Sous-titres des pages légales : plus discrets que h2, sinon la politique de
   confidentialité se lit comme une succession de chapitres de même poids. */
.help-sec h3 {
  font-size: 1rem;
  letter-spacing: -.01em;
  margin: 1.6rem 0 .55rem;
  color: var(--text-primary);
}
.help-sec code {
  font-family: var(--mono);
  font-size: .86em;
  padding: .1em .35em;
  border-radius: 4px;
  background: var(--surface-1);
  border: 1px solid var(--gridline);
}
.help-mark { font-family: var(--mono); }

/* ---------- Macro ---------- */

.macro-graph {
  display: block;
  width: 100%;
  height: auto;
  margin: 1rem 0 1.25rem;
}

.macro-figures {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 1.75rem;
  margin: 1.1rem 0 .3rem;
}
.macro-fig { display: flex; flex-direction: column; gap: .15rem; }
.macro-fig-val {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 1.75rem;
  font-weight: 600;
  letter-spacing: -.02em;
  color: var(--text-primary);
}
.macro-fig-lab {
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--text-muted);
}
.macro-fig-note {
  flex: 1 1 15rem;
  margin: 0;
  font-size: .8rem !important;
  color: var(--text-muted) !important;
}

/* Légende des deux fenêtres : le trait, pas une pastille pleine — c'est une
   courbe qu'il désigne, et la forme doit dire laquelle. */
.macro-key { display: inline-flex; align-items: center; gap: .35rem; margin-left: .9rem; }
.macro-swatch { display: inline-block; width: 15px; height: 0; border-top-width: 2px; border-top-style: solid; }
.macro-swatch-30 { border-top-color: var(--pole-buy); opacity: .75; }
.macro-swatch-90 { border-top-color: var(--text-muted); }

/* Verdict de mesure : un constat, pas un filtre cliquable — d'où une forme
   distincte de .chip, qui porte un état interactif. */
.macro-verdict {
  display: inline-block;
  padding: .12rem .5rem;
  border: 1px dashed var(--gridline);
  border-radius: 999px;
  font-size: .72rem;
  color: var(--text-muted);
  white-space: nowrap;
}

.help-card {
  background: var(--surface-1);
  border: 1px solid var(--gridline);
  border-radius: var(--radius);
  padding: 1rem 1.15rem;
  margin-bottom: .8rem;
}
.help-card h3 { margin: 0 0 .4rem; font-size: .95rem; }
.help-card p { margin: 0; font-size: .88rem; }

.help-tablewrap { overflow-x: auto; margin: 1rem 0; }

.help-table {
  width: 100%;
  border-collapse: collapse;
  font-size: .86rem;
  background: var(--surface-1);
  border: 1px solid var(--gridline);
  border-radius: var(--radius);
}
.help-table th {
  text-align: left;
  font-size: .7rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--text-muted);
  padding: .55rem .8rem;
  border-bottom: 1px solid var(--gridline);
}
.help-table td { padding: .5rem .8rem; border-bottom: 1px solid var(--gridline); color: var(--text-secondary); }
.help-table tr:last-child td { border-bottom: 0; }
.help-table td.num, .help-table th.num {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.help-gloss { margin: 0; }
.help-gloss dt {
  font-weight: 600;
  color: var(--text-primary);
  margin-top: 1rem;
  font-size: .92rem;
}
.help-gloss dd {
  margin: .2rem 0 0;
  color: var(--text-secondary);
  font-size: .88rem;
  line-height: 1.6;
}

/* ---------- Page « Why this call » ---------- */

/* Le repli technique se signale avant tout le reste : expliquer un
   raisonnement qui n'a pas eu lieu serait le défaut central de cette page. */
.why-fallback { border-left: 3px solid var(--pole-neutral); }

.why-link {
  margin-left: .6rem;
  font-size: .82rem;
  font-weight: 600;
  color: var(--pole-buy);
  text-decoration: none;
  white-space: nowrap;
}
.why-link:hover { text-decoration: underline; }

.why-derive { color: var(--text-muted); font-size: .8em; }

.why-news { list-style: none; margin: 0 0 1rem; padding: 0; }
.why-news li { padding: .7rem 0; border-bottom: 1px solid var(--gridline); }
.why-news li:last-child { border-bottom: 0; }
.why-news a { color: var(--text-primary); font-weight: 600; text-decoration: none; font-size: .92rem; }
.why-news a:hover { text-decoration: underline; }

/* (rendu de tonalité remplacé par tone_chip() le 4 août 2026) */

.why-news-resume { margin: .25rem 0 0; font-size: .84rem; color: var(--text-secondary); }
.why-news-meta { margin: .25rem 0 0; font-size: .74rem; color: var(--text-muted); }

/* Sankey de réallocation (why-strategy.php). Aucune teinte propre : les
   rubans reprennent les pôles du site, la légende ne fait que les rappeler. */
.strat-sankey { display: block; width: 100%; height: auto; margin: .6rem 0 .3rem; }

.sankey-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .35rem 1.1rem;
  margin: 0 0 .8rem;
  font-size: .78rem;
  color: var(--text-muted);
}
.sk-key {
  display: inline-block;
  width: .8rem;
  height: .55rem;
  border-radius: 2px;
  margin-right: .3rem;
  vertical-align: -1px;
}
/* Sankey d'évolution (history.php) : deux catégories de nœuds seulement —
   exposé ou stable. Huit teintes d'actifs ont échoué au validateur. */
.hebdo-sankey { display: block; width: 100%; height: auto; margin: .6rem 0 .4rem; }

/*
 * Remplissages des deux Sankey, en un seul endroit.
 *
 * Les opacités DIFFÈRENT d'un thème à l'autre, et c'est la raison d'être de
 * ces classes : portées par un attribut `opacity` dans le SVG, elles ne
 * pourraient pas varier. Mesuré au validateur du skill dataviz plutôt que
 * jugé à l'œil — les valeurs calibrées sur le fond clair, composées sur le
 * fond sombre, donnaient des rubans à 2,1:1 de contraste et ΔE 14 entre
 * « vendu » et « conservé ». Aux valeurs ci-dessous, la paire vendu/acheté
 * passe les six contrôles dans les deux thèmes (ΔE normal 28,5 en clair,
 * 24,6 en sombre ; contraste ≥ 3:1).
 *
 * Le neutre « conservé » reste volontairement en dessous de 3:1 : ce n'est
 * pas une série pair des deux autres, c'est le fond sur lequel elles se
 * lisent. Le relief exigé dans ce cas est présent — code d'actif écrit à
 * chaque colonne et infobulle sur chaque ruban.
 */
.sk-r-keep, .sk-r-out, .sk-r-in,
.sk-n-line, .sk-n-pool, .sk-n-expo, .sk-n-stable { stroke: none; }

.sk-r-keep   { fill: var(--text-muted);   opacity: .28; }
.sk-r-out    { fill: var(--pole-sell);    opacity: .88; }
.sk-r-in     { fill: var(--pole-buy);     opacity: .88; }
.sk-n-line   { fill: var(--text-secondary); opacity: .75; }
.sk-n-pool   { fill: var(--text-primary); opacity: .8; }
.sk-n-expo   { fill: var(--pole-buy);     opacity: .85; }
.sk-n-stable { fill: var(--text-muted);   opacity: .6; }

/* `:where()` comme partout ailleurs dans ce fichier : sans lui la règle du
   thème système pèserait autant que le choix manuel, et l'utilisateur qui
   force le thème clair depuis un système sombre garderait ces opacités. */
@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) .sk-r-keep { opacity: .42; }
  :root:where(:not([data-theme="light"])) .sk-r-out,
  :root:where(:not([data-theme="light"])) .sk-r-in   { opacity: .82; }
  :root:where(:not([data-theme="light"])) .sk-n-pool { opacity: .85; }
}
:root[data-theme="dark"] .sk-r-keep { opacity: .42; }
:root[data-theme="dark"] .sk-r-out,
:root[data-theme="dark"] .sk-r-in   { opacity: .82; }
:root[data-theme="dark"] .sk-n-pool { opacity: .85; }

/* Puces de légende : mêmes teintes, en HTML. */
.sk-keep   { background: var(--text-muted); opacity: .28; }
.sk-out    { background: var(--pole-sell);  opacity: .88; }
.sk-in     { background: var(--pole-buy);   opacity: .88; }
.sk-expo   { background: var(--pole-buy);   opacity: .85; }
.sk-stable { background: var(--text-muted); opacity: .6; }

.help-sec-note { font-size: .8rem; color: var(--text-muted); }

/* ---------- Fiche détaillée ---------- */

.detail-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
  padding-bottom: 1.25rem;
  border-bottom: 1px solid var(--gridline);
  margin-bottom: 1.5rem;
}

.detail-price {
  font-family: var(--mono);
  font-size: 2rem;
  font-weight: 650;
  letter-spacing: -.02em;
}

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

.panel h2 {
  margin: 0 0 .9rem;
  font-size: .78rem;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--text-muted);
  font-weight: 620;
}

.panel p { margin: 0 0 .75rem; }
.panel p:last-child { margin-bottom: 0; }

.risk-list { margin: 0; padding-left: 1.1rem; color: var(--text-secondary); font-size: .9rem; }
.risk-list li { margin-bottom: .35rem; }

/* ---------- Table d'indicateurs ---------- */

.indicator-table {
  width: 100%;
  border-collapse: collapse;
  font-size: .875rem;
}

.indicator-table th,
.indicator-table td {
  text-align: left;
  padding: .55rem .5rem;
  border-bottom: 1px solid var(--gridline);
}

.indicator-table th {
  color: var(--text-muted);
  font-weight: 550;
  width: 45%;
}

.indicator-table td {
  font-family: var(--mono);
  text-align: right;
  color: var(--text-primary);
}

.indicator-table tr:last-child th,
.indicator-table tr:last-child td { border-bottom: none; }

/* ---------- Graphique ---------- */

.chart-wrap { overflow-x: auto; }
.chart { display: block; width: 100%; height: auto; min-width: 280px; }
.chart-grid { stroke: var(--gridline); stroke-width: 1; }
.chart-zero { stroke: var(--baseline); stroke-width: 1; }
.chart-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart-label { fill: var(--text-muted); font-size: 10px; font-family: var(--font); }

/* ---------- Niveaux ---------- */

.levels {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}

.level-box {
  border: 1px solid var(--gridline);
  border-radius: 8px;
  padding: .8rem;
}

.level-label {
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text-muted);
  margin-bottom: .25rem;
}

.level-value { font-family: var(--mono); font-size: 1.05rem; font-weight: 600; }

/* ---------- États ---------- */

.empty-state {
  background: var(--surface-1);
  border: 1px dashed var(--baseline);
  border-radius: var(--radius);
  padding: 2.5rem 1.5rem;
  text-align: center;
  color: var(--text-secondary);
}

.empty-state h2 { margin: 0 0 .5rem; font-size: 1.1rem; color: var(--text-primary); }
.empty-state code {
  font-family: var(--mono);
  font-size: .82rem;
  background: var(--midpoint);
  padding: .15rem .4rem;
  border-radius: 4px;
}

.source-tag {
  display: inline-block;
  font-size: .68rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--text-muted);
  border: 1px solid var(--gridline);
  border-radius: 4px;
  padding: .1rem .35rem;
}

.back-link {
  display: inline-block;
  margin-bottom: 1rem;
  color: var(--text-secondary);
  text-decoration: none;
  font-size: .875rem;
}

.back-link:hover { color: var(--text-primary); }

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

.site-footer {
  border-top: 1px solid var(--gridline);
  background: var(--surface-1);
  padding: 1.75rem 1.5rem;
}

.disclaimer {
  max-width: 1120px;
  margin: 0 auto 1rem;
  font-size: .8rem;
  color: var(--text-secondary);
  line-height: 1.6;
}

.footer-meta {
  max-width: 1120px;
  margin: 0 auto;
  font-size: .75rem;
  color: var(--text-muted);
}

.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: 1.1rem;
  max-width: 1120px;
  margin: .55rem auto 0;
  font-size: .75rem;
}
.footer-links a { color: var(--text-muted); text-decoration: none; }
.footer-links a:hover { color: var(--text-primary); text-decoration: underline; }

/* ---------- Prose ---------- */

.prose { max-width: 68ch; }
.prose h2 { font-size: 1.05rem; margin: 1.75rem 0 .6rem; }
.prose h2:first-child { margin-top: 0; }
.prose p { color: var(--text-secondary); margin: 0 0 .85rem; }
.prose ul { color: var(--text-secondary); padding-left: 1.2rem; }
.prose li { margin-bottom: .4rem; }
.prose strong { color: var(--text-primary); }

@media (max-width: 560px) {
  main { padding: 1.5rem 1rem 2.5rem; }
  .levels { grid-template-columns: 1fr; }
  .detail-price { font-size: 1.6rem; }
}

/* ================= Backend : authentification & portefeuille ================= */

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

.auth-wrap { max-width: 420px; margin: 2rem auto; }

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

.field-label {
  display: block;
  font-size: .8rem;
  color: var(--text-secondary);
  margin-bottom: .3rem;
  font-weight: 550;
}

.field input[type="text"],
.field input[type="password"],
.field select {
  width: 100%;
  padding: .55rem .7rem;
  font-size: .95rem;
  font-family: inherit;
  color: var(--text-primary);
  background: var(--surface-page);
  border: 1px solid var(--baseline);
  border-radius: 8px;
}

.field input:focus,
.field select:focus {
  outline: 2px solid var(--pole-buy);
  outline-offset: 1px;
  border-color: var(--pole-buy);
}

/* `text-decoration: none` ici et non sur chaque variante : la regle vivait
   dans `.btn-google` seul, donc tout AUTRE lien stylé en bouton héritait du
   soulignement des liens — visible sur la modale Telegram, et sur les autres
   depuis toujours. */
.btn {
  display: inline-block;
  text-decoration: none;
  padding: .58rem 1.1rem;
  font-size: .92rem;
  font-family: inherit;
  font-weight: 580;
  border-radius: 8px;
  border: 1px solid transparent;
  cursor: pointer;
}

.btn-primary { background: var(--pole-buy); color: #fff; }
.btn-primary:hover { filter: brightness(1.08); }
.btn-block { width: 100%; }

/* Bouton Google. Fond neutre et bordure visible dans les deux thèmes : le
   logo est multicolore, il ne peut pas porter le contraste tout seul. Les
   couleurs du logo sont imposées par Google — seule exception à la palette. */
.btn-google {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .6rem;
  text-decoration: none;
  background: var(--surface);
  border-color: var(--gridline);
  color: var(--text-primary);
}
.btn-google:hover { background: var(--surface-alt, var(--surface)); border-color: var(--text-muted); }
.btn-google svg { flex: 0 0 auto; }

/* Séparateur « or » : un trait qui traverse, le mot posé dessus. */
.auth-sep {
  display: flex;
  align-items: center;
  gap: .75rem;
  margin: 1.05rem 0;
  color: var(--text-muted);
  font-size: .8rem;
}
.auth-sep::before,
.auth-sep::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--gridline);
}

.btn-inline {
  background: none;
  border: 1px solid var(--gridline);
  border-radius: 6px;
  color: var(--text-muted);
  cursor: pointer;
  font-size: .8rem;
  padding: .2rem .45rem;
  margin-left: .3rem;
}

.btn-inline:hover { color: var(--pole-buy); border-color: var(--pole-buy); }

.btn-icon {
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  font-size: 1.15rem;
  line-height: 1;
  padding: .1rem .35rem;
  border-radius: 5px;
}

.btn-icon:hover { color: var(--pole-sell); background: color-mix(in srgb, var(--pole-sell) 12%, transparent); }

/* ---------- Messages ---------- */

.alert {
  padding: .7rem .9rem;
  border-radius: 8px;
  font-size: .88rem;
  margin-bottom: 1rem;
  color: var(--pole-sell);
  border: 1px solid color-mix(in srgb, var(--pole-sell) 40%, transparent);
  background: color-mix(in srgb, var(--pole-sell) 8%, transparent);
}

.alert-ok {
  color: var(--pole-buy);
  border-color: color-mix(in srgb, var(--pole-buy) 40%, transparent);
  background: color-mix(in srgb, var(--pole-buy) 8%, transparent);
}

/* ---------- Chiffre principal ---------- */

.hero-panel { text-align: center; padding: 1.75rem 1.25rem; }

.hero-label {
  font-size: .78rem;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--text-muted);
  font-weight: 620;
  margin-bottom: .5rem;
}

.hero-value {
  font-family: var(--mono);
  font-size: 2.4rem;
  font-weight: 680;
  letter-spacing: -.03em;
  line-height: 1.1;
}

.hero-unit { font-size: 1.1rem; font-weight: 500; color: var(--text-muted); }
.hero-meta { font-size: .8rem; color: var(--text-muted); margin-top: .5rem; }

/* Repères de stratégies sous l'axe du graphique : discrets au repos,
   francs au survol, colorés quand la courbe est affichée. */
.strat-marker { cursor: pointer; }

.strat-marker-dot {
  fill: var(--baseline);
  opacity: .8;
  transition: opacity .15s ease, fill .15s ease;
}

.strat-marker:hover .strat-marker-dot,
.strat-marker:focus .strat-marker-dot {
  fill: var(--text-secondary);
  opacity: 1;
}

/* La chaîne hebdomadaire : cercles, plus petits et plus resserrés que les
   losanges des stratégies ponctuelles — une série, pas des événements. */
.strat-marker-chain {
  fill: var(--baseline);
  opacity: .7;
  transition: opacity .15s ease, fill .15s ease;
}

.strat-marker:hover .strat-marker-chain,
.strat-marker:focus .strat-marker-chain {
  fill: var(--text-secondary);
  opacity: 1;
}

/* Puce de la politique hebdomadaire dans le panneau de comparaison. */
.tab-hebdo .tag { margin-left: .35rem; }

/* ---------- Positions en petits multiples ---------- */

.pos-note {
  font-size: .8rem;
  color: var(--text-muted);
  margin: 0 0 1rem;
}

.pos-tri-demo {
  display: inline-block;
  width: 0; height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  vertical-align: middle;
}

.pos-tri-buy  { border-bottom: 8px solid var(--pole-buy); }
.pos-tri-sell { border-top: 8px solid var(--pole-sell); }

/* Pendant de la légende pour le retour au neutre. */
.pos-carre-demo {
  display: inline-block;
  width: 7px;
  height: 7px;
  background: var(--pole-neutral);
  vertical-align: middle;
}

/* Liste dépliable de toutes les recommandations d'une période. */
.reco-list { margin-top: 1rem; }

.reco-list summary {
  cursor: pointer;
  font-size: .82rem;
  color: var(--text-secondary);
}

.reco-list summary:hover { color: var(--text-primary); }

.reco-list .table-wrap { margin-top: .7rem; }

.reco-badge { font-size: .72rem; padding: .15rem .5rem; }

.pos-filter { margin-bottom: 1rem; }

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

.pos-card[hidden] { display: none; }

.pos-card {
  display: block;
  border: 1px solid var(--gridline);
  border-radius: var(--radius);
  padding: .9rem 1rem .7rem;
  text-decoration: none;
  color: inherit;
  transition: border-color .15s ease;
}

.pos-card:hover { border-color: var(--baseline); }

.pos-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: .6rem;
  margin-bottom: .5rem;
}

.pos-name { font-size: .88rem; font-weight: 620; }

.pos-perf { font-family: var(--mono); font-size: .85rem; font-weight: 600; }

.pos-spark { display: block; width: 100%; height: 88px; }

.pos-base {
  stroke: var(--baseline);
  stroke-width: 1;
  stroke-dasharray: 3 4;
}

.pos-foot {
  display: flex;
  justify-content: space-between;
  gap: .6rem;
  margin-top: .4rem;
  font-size: .7rem;
  color: var(--text-muted);
}

/* Référence achat-conservation BTC : le rendement sans décision. */
.hero-btc {
  font-size: .78rem;
  color: var(--text-muted);
  margin-top: .55rem;
  padding-top: .55rem;
  border-top: 1px dashed var(--gridline);
}

/* Variation ponctuelle d'une valeur rafraîchie. */
@keyframes tick-up   { from { color: var(--pole-buy); }  to { color: inherit; } }
@keyframes tick-down { from { color: var(--pole-sell); } to { color: inherit; } }
.tick-up   { animation: tick-up 1.2s ease-out; }
.tick-down { animation: tick-down 1.2s ease-out; }

@media (prefers-reduced-motion: reduce) {
  .tick-up, .tick-down { animation: none; }
}

/* ---------- Dialogue de confirmation ----------
   `<dialog>` natif : le navigateur fournit le fond bloquant, le piège de
   focus, Échap et le retour du focus. On n'habille que l'apparence. */

.dlg {
  width: min(24rem, calc(100vw - 2rem));
  padding: 1.5rem;
  border: 1px solid var(--gridline);
  border-radius: var(--radius);
  background: var(--surface-1);
  color: var(--text-primary);
  box-shadow: var(--elev-3);
}

.dlg::backdrop { background: rgb(0 0 0 / .45); }

.dlg h2 {
  margin: 0 0 .6rem;
  font-size: 1.1rem;
  letter-spacing: -.015em;
}

.dlg-corps { margin: 0 0 1rem; font-size: .92rem; color: var(--text-secondary); }

.dlg-detail {
  margin: 0 0 1rem;
  padding: .7rem .85rem;
  background: var(--surface-page);
  border-radius: 8px;
  font-size: .82rem;
}

.dlg-detail > div {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
}

.dlg-detail > div + div { margin-top: .3rem; }
.dlg-detail dt { color: var(--text-muted); }
.dlg-detail dd { margin: 0; font-weight: 550; }

.dlg-note {
  margin: 0 0 1.25rem;
  font-size: .76rem;
  line-height: 1.5;
  color: var(--text-muted);
}

.dlg-actions {
  display: flex;
  gap: .6rem;
  justify-content: flex-end;
  flex-wrap: wrap;
}

/* Le bouton destructeur porte le rouge des ventes : le site n'a qu'un seul
   vocabulaire de couleur, on ne lui en invente pas un second. */
.btn-danger {
  background: var(--pole-sell);
  border: 1px solid var(--pole-sell);
  color: #fff;
}

.btn-danger:hover { filter: brightness(1.08); }

/* ---------- Sommaire du portefeuille ----------
   Valeur, évolution et répartition dans un seul panneau : trois informations
   qui se lisent ensemble occupaient auparavant deux panneaux et une pleine
   hauteur d'écran. */

.pf-sommaire {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: 2rem;
  align-items: start;
}

.pf-sommaire-chiffre { min-width: 0; }

.pf-courbe { margin-top: 1.4rem; }

.pf-courbe-tete {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .8rem;
  margin-bottom: .3rem;
  font-size: .78rem;
  color: var(--text-muted);
}

.pf-courbe-tete strong { font-family: var(--mono); font-size: .85rem; }

/* Hauteur fixe : la place est réservée avant le rendu, la page ne saute pas. */
.pf-courbe-svg { display: block; width: 100%; height: 68px; }

.pf-courbe-lien {
  display: inline-block;
  margin-top: .5rem;
  font-size: .78rem;
  font-weight: 600;
  color: var(--pole-buy);
  text-decoration: none;
}

.pf-courbe-lien:hover { text-decoration: underline; }

.pf-courbe-vide {
  margin: 1.2rem 0 0;
  font-size: .8rem;
  color: var(--text-muted);
}

/* Anneau : tracé en arcs par stroke-dasharray, sans bibliothèque. */
.pf-sommaire-anneau {
  display: flex;
  gap: 1.2rem;
  align-items: center;
  min-width: 0;
}

.pf-anneau-wrap { position: relative; flex: 0 0 140px; }
.pf-anneau { display: block; width: 140px; height: 140px; }

.pf-anneau-centre {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

.pf-anneau-n {
  font-family: var(--mono);
  font-size: 1.5rem;
  font-weight: 600;
  line-height: 1;
}

.pf-anneau-lbl { font-size: .72rem; color: var(--text-muted); }

.pf-anneau-legende {
  list-style: none;
  margin: 0;
  padding: 0;
  min-width: 0;
  flex: 1;
}

.pf-anneau-legende li {
  display: flex;
  align-items: center;
  gap: .45rem;
  padding: .18rem 0;
  font-size: .8rem;
}

.pf-legende-nom {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pf-legende-pct {
  font-family: var(--mono);
  font-size: .76rem;
  color: var(--text-muted);
}

@media (max-width: 780px) {
  .pf-sommaire { grid-template-columns: 1fr; gap: 1.5rem; }
  .pf-sommaire-anneau { padding-top: 1.2rem; border-top: 1px solid var(--gridline); }
}

@media (max-width: 420px) {
  .pf-sommaire-anneau { flex-direction: column; align-items: flex-start; }
  .pf-anneau-legende { width: 100%; }
}

/* ---------- Répartition ---------- */

.alloc-bar {
  display: flex;
  height: 26px;
  border-radius: 6px;
  overflow: hidden;
  gap: 2px;               /* séparation nette entre segments */
  background: var(--midpoint);
}

.alloc-seg { min-width: 2px; }

.alloc-legend {
  display: flex;
  flex-wrap: wrap;
  gap: .35rem 1.1rem;
  margin-top: .8rem;
  font-size: .82rem;
  color: var(--text-secondary);
}

.legend-item { display: inline-flex; align-items: center; gap: .4rem; }

.legend-dot {
  width: 9px; height: 9px;
  border-radius: 2px;
  display: inline-block;
  flex-shrink: 0;
}

.legend-pct { color: var(--text-muted); font-family: var(--mono); font-size: .78rem; }

/* ---------- Table des positions ---------- */

.table-wrap { overflow-x: auto; }

.holdings-table {
  width: 100%;
  border-collapse: collapse;
  font-size: .88rem;
  min-width: 640px;
}

.holdings-table th {
  text-align: left;
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--text-muted);
  font-weight: 600;
  padding: .5rem .55rem;
  border-bottom: 1px solid var(--gridline);
  white-space: nowrap;
}

.holdings-table td {
  padding: .65rem .55rem;
  border-bottom: 1px solid var(--gridline);
  vertical-align: middle;
}

.holdings-table tr:last-child td { border-bottom: none; }
.holdings-table .num { text-align: right; }
.holdings-table .mono { font-family: var(--mono); white-space: nowrap; }

.holding-name {
  color: var(--text-primary);
  text-decoration: none;
  font-weight: 570;
  display: block;
}

.holding-name:hover { color: var(--pole-buy); }

.qty-form { display: inline-flex; align-items: center; justify-content: flex-end; }

.qty-input {
  width: 8.5rem;
  padding: .28rem .45rem;
  font-family: var(--mono);
  font-size: .85rem;
  text-align: right;
  color: var(--text-primary);
  background: var(--surface-page);
  border: 1px solid var(--gridline);
  border-radius: 6px;
}

.qty-input:focus {
  outline: 2px solid var(--pole-buy);
  outline-offset: 1px;
  border-color: var(--pole-buy);
}

/* ---------- Lecture agrégée ---------- */

.assess-head {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}

.assess-score { font-size: .9rem; color: var(--text-secondary); }
.assess-score strong { font-family: var(--mono); color: var(--text-primary); }

/* ---------- Ajout ---------- */

.add-form {
  display: flex;
  align-items: flex-end;
  gap: .9rem;
  flex-wrap: wrap;
}

.field-inline { margin-bottom: 0; flex: 1 1 190px; }

/* ---------- Navigation utilisateur ---------- */

.nav-user {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font-size: .82rem;
  color: var(--text-muted);
}

.nav-sep { color: var(--gridline); }

@media (max-width: 560px) {
  .hero-value { font-size: 1.9rem; }
  .add-form { flex-direction: column; align-items: stretch; }
  .field-inline { flex: 1 1 auto; }
}

/* ---------- Catalogue : recherche, filtres, pagination ---------- */

.filter-row {
  display: flex;
  gap: .6rem;
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: .9rem;
}

.search-input {
  flex: 1 1 260px;
  padding: .55rem .75rem;
  font-size: .95rem;
  font-family: inherit;
  color: var(--text-primary);
  background: var(--surface-page);
  border: 1px solid var(--baseline);
  border-radius: 8px;
}

.search-input:focus {
  outline: 2px solid var(--pole-buy);
  outline-offset: 1px;
  border-color: var(--pole-buy);
}

.btn-ghost {
  background: none;
  border: 1px solid var(--gridline);
  color: var(--text-secondary);
  text-decoration: none;
}

.btn-ghost:hover { border-color: var(--baseline); color: var(--text-primary); }

/* Action secondaire en fin de ligne de tableau : discrète, mais atteignable. */
.btn-mini {
  padding: .22rem .6rem;
  font-size: .74rem;
  white-space: nowrap;
}

.filter-tabs {
  display: flex;
  gap: .4rem;
  flex-wrap: wrap;
  border-top: 1px solid var(--gridline);
  padding-top: .8rem;
}

.tab {
  padding: .3rem .7rem;
  border-radius: 999px;
  font-size: .82rem;
  text-decoration: none;
  color: var(--text-secondary);
  border: 1px solid var(--gridline);
}

.tab:hover { border-color: var(--baseline); color: var(--text-primary); }

.tab-active {
  color: var(--pole-buy);
  border-color: color-mix(in srgb, var(--pole-buy) 45%, transparent);
  background: color-mix(in srgb, var(--pole-buy) 10%, transparent);
  font-weight: 570;
}

.tag {
  display: inline-block;
  font-size: .72rem;
  padding: .16rem .45rem;
  border-radius: 5px;
  border: 1px solid var(--gridline);
  color: var(--text-muted);
  white-space: nowrap;
}

.tag-analysed {
  color: var(--pole-buy);
  border-color: color-mix(in srgb, var(--pole-buy) 40%, transparent);
  background: color-mix(in srgb, var(--pole-buy) 8%, transparent);
}

.tag-owned {
  color: var(--text-primary);
  border-color: var(--baseline);
  background: var(--midpoint);
  font-weight: 550;
}

.pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--gridline);
}

.pager-info { font-size: .82rem; color: var(--text-muted); }

/* ---------- Graphique d'historique ---------- */

.chart-wrap { position: relative; }
.chart-history { min-width: 320px; }

.chart-cross {
  stroke: var(--baseline);
  stroke-width: 1;
  stroke-dasharray: 3 3;
  pointer-events: none;
}

.chart-dot {
  fill: var(--surface-1);
  stroke: var(--pole-buy);
  stroke-width: 2.5;
  pointer-events: none;
}

.chart-tip {
  position: absolute;
  z-index: 5;
  pointer-events: none;
  background: var(--surface-1);
  border: 1px solid var(--baseline);
  border-radius: 8px;
  padding: .5rem .7rem;
  font-size: .8rem;
  line-height: 1.4;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .12);
  white-space: nowrap;
}

.tip-date { color: var(--text-muted); font-size: .72rem; margin-bottom: .15rem; }
.tip-value { font-family: var(--mono); font-weight: 650; font-size: .95rem; }
.tip-delta { font-size: .75rem; font-weight: 550; margin-top: .1rem; }

.chart-foot {
  display: flex;
  gap: 1.5rem;
  flex-wrap: wrap;
  margin-top: .8rem;
  padding-top: .8rem;
  border-top: 1px solid var(--gridline);
  font-size: .78rem;
  color: var(--text-muted);
}

.chart-foot strong { color: var(--text-primary); font-family: var(--mono); font-weight: 600; }

.source-badge {
  display: inline-block;
  font-size: .68rem;
  padding: .1rem .4rem;
  border-radius: 4px;
  border: 1px solid var(--gridline);
  color: var(--text-muted);
  margin-left: .4rem;
}

/* ---------- Actualités ---------- */

.news-list { list-style: none; margin: 0; padding: 0; }

.news-item {
  padding: .85rem 0;
  border-bottom: 1px solid var(--gridline);
}

.news-item:first-child { padding-top: 0; }
.news-item:last-child { border-bottom: none; padding-bottom: 0; }

.news-title {
  display: block;
  color: var(--text-primary);
  text-decoration: none;
  font-weight: 570;
  font-size: .95rem;
  line-height: 1.4;
}

.news-title:hover { color: var(--pole-buy); }

.news-snippet {
  margin: .3rem 0 0;
  font-size: .84rem;
  color: var(--text-secondary);
  line-height: 1.5;
}

.news-meta {
  display: flex;
  flex-wrap: wrap;
  gap: .3rem .9rem;
  margin-top: .35rem;
  font-size: .74rem;
  color: var(--text-muted);
}

.news-meta span + span::before {
  content: "·";
  margin-right: .55rem;
  color: var(--gridline);
}

.news-compact .news-item { padding: .6rem 0; }
.news-compact .news-title { font-size: .88rem; }

/* ---------- Logos d'actifs ---------- */

.coin-logo {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  overflow: hidden;
  flex-shrink: 0;
  vertical-align: middle;
}

/* Lettre de repli, visible si l'image ne charge pas. */
.coin-letter {
  font-size: .68rem;
  font-weight: 700;
  color: #fff;
  line-height: 1;
  user-select: none;
}

.coin-logo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: var(--surface-1);
}

.coin-logo-none { background: var(--baseline) !important; }

/* Variante image locale : le PNG est déjà un disque, pas de fond ni de
   rognage à imposer. `object-fit` protège si un fichier non carré entre. */
.coin-img { object-fit: contain; background: transparent; }

.logo-link { display: inline-flex; text-decoration: none; }

/* Article avec logos : deux colonnes. */
.news-item-logo {
  display: flex;
  gap: .75rem;
  align-items: flex-start;
}

.news-logos {
  display: flex;
  flex-direction: column;
  gap: .25rem;
  padding-top: .1rem;
  flex-shrink: 0;
}

.news-body { flex: 1; min-width: 0; }

.news-meta .asset-symbol {
  display: inline;
  font-size: .7rem;
  color: var(--text-secondary);
  font-weight: 600;
}

/* ---------- Voile d'attente ----------
   Une génération de stratégie dure une trentaine de secondes en POST
   synchrone : sans retour visuel la page paraît morte, et l'utilisateur
   soumet une seconde fois. Aucune barre de progression : le serveur ne
   renvoie rien avant la fin, une progression affichée serait inventée. */

.wait-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  background: color-mix(in srgb, var(--surface-page) 86%, transparent);
  backdrop-filter: blur(3px);
}

.wait-overlay[data-open="1"] { display: flex; }

.wait-card {
  width: min(440px, 100%);
  max-height: 90vh;
  overflow-y: auto;
  background: var(--surface-1);
  border: 1px solid var(--gridline);
  border-radius: var(--radius);
  padding: 1.7rem 1.5rem 1.4rem;
  text-align: center;
  box-shadow: 0 12px 34px rgba(0, 0, 0, .16);
}

.wait-spinner {
  width: 38px;
  height: 38px;
  margin: 0 auto 1rem;
  border-radius: 50%;
  border: 3px solid var(--gridline);
  border-top-color: var(--pole-buy);
  animation: wait-spin .9s linear infinite;
}

@keyframes wait-spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .wait-spinner { animation-duration: 2.8s; }
}

.wait-card h2 {
  margin: 0 0 .35rem;
  font-size: 1.05rem;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text-primary);
}

.wait-scope {
  margin: 0 0 1.1rem;
  font-size: .85rem;
  color: var(--text-secondary);
  line-height: 1.5;
}

.wait-steps {
  list-style: none;
  margin: 0 0 1.1rem;
  padding: .8rem 0 0;
  border-top: 1px solid var(--gridline);
  text-align: left;
  font-size: .82rem;
  color: var(--text-secondary);
}

.wait-steps li {
  padding: .22rem 0 .22rem 1.05rem;
  position: relative;
  line-height: 1.45;
}

.wait-steps li::before {
  content: "·";
  position: absolute;
  left: .2rem;
  color: var(--baseline);
  font-weight: 700;
}

.wait-elapsed {
  margin: 0;
  font-family: var(--mono);
  font-size: .78rem;
  color: var(--text-muted);
}

/* ---------- Tonalité d'un article ----------
   Échelle divergente de -10 à +10, neutre au centre. Le chiffre est toujours
   écrit à côté : la couleur ne porte jamais l'information seule. */

/* Un article promotionnel reste visible mais s'efface : il est écarté de
   l'analyse, le lecteur doit pouvoir le constater plutôt que le deviner. */
.news-item-promo .news-title,
.news-item-promo .news-snippet { color: var(--text-muted); }

.news-tag {
  display: inline-block;
  padding: .06rem .4rem;
  border-radius: 4px;
  border: 1px solid var(--gridline);
  background: var(--midpoint);
  font-size: .68rem;
  font-weight: 600;
  color: var(--text-secondary);
}

/* Courbes de stratégies superposées à l'historique réel. */
.chart-line-alt { stroke-width: 1.6; stroke-dasharray: 5 3; opacity: .9; }
.chart-cut { stroke-width: 1.5; stroke-dasharray: 2 3; opacity: .7; }

/* ---------- Bannière comparative réel / hypothétique ---------- */

.hero-compare {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 0;
  padding: 1.5rem 1rem;
  text-align: left;
}

.hero-col {
  flex: 1 1 240px;
  min-width: 220px;
  padding: 0 1.5rem;
}

/* Séparateur entre colonnes, sans bordure sur la première. */
.hero-compare .hero-col + .hero-col {
  border-left: 1px solid var(--gridline);
}

.hero-compare .hero-label {
  display: flex;
  align-items: center;
  gap: .4rem;
  justify-content: flex-start;
}

.hero-compare .hero-value { font-size: 1.9rem; }

.hero-diff {
  margin-top: .7rem;
  padding-top: .6rem;
  border-top: 1px solid var(--gridline);
  display: flex;
  align-items: baseline;
  gap: .5rem;
  flex-wrap: wrap;
}

.hero-diff-value {
  font-family: var(--mono);
  font-size: 1rem;
  font-weight: 650;
}

.hero-diff-pts { font-size: .75rem; color: var(--text-secondary); }

.hero-strat-title {
  font-size: .72rem;
  color: var(--text-muted);
  margin-top: .5rem;
  line-height: 1.35;
}

@media (max-width: 720px) {
  .hero-compare { padding: 1.25rem .75rem; }
  .hero-compare .hero-col + .hero-col {
    border-left: 0;
    border-top: 1px solid var(--gridline);
    padding-top: 1.1rem;
    margin-top: 1.1rem;
  }
  .hero-compare .hero-value { font-size: 1.6rem; }
}

/* ---------- Sélection des lignes à analyser ---------- */

.pick-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: .55rem;
}

/* Tuile-bouton : la case à cocher reste dans l'arbre d'accessibilité mais
   l'état se lit sur la tuile entière — bordure, pastille, filigrane. */
.pick-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .65rem .75rem;
  border: 1px solid var(--gridline);
  border-radius: 10px;
  cursor: pointer;
  background: var(--surface-page);
  overflow: hidden;
  user-select: none;
  transition: border-color .15s ease, box-shadow .15s ease;
}

.pick-item:hover { border-color: var(--baseline); }

.pick-item input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  pointer-events: none;
}

/* Filigrane : le logo en grand, débordant à droite, assez pâle pour ne pas
   gêner la lecture. S'il ne charge pas, il ne laisse aucune trace. */
.pick-fond {
  position: absolute;
  top: 50%;
  right: -14px;
  width: 74px;
  height: 74px;
  transform: translateY(-50%);
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  opacity: .12;
  filter: grayscale(1);
  pointer-events: none;
}

/* Le contenu passe au-dessus du filigrane. */
.pick-item > .coin-logo,
.pick-body,
.pick-coche { position: relative; }

.pick-body { display: flex; flex-direction: column; min-width: 0; }
.pick-name { font-size: .85rem; font-weight: 570; }
.pick-meta { font-size: .72rem; color: var(--text-muted); font-family: var(--mono); }

/* Pastille d'état en bout de tuile : cercle vide ou coche pleine. */
.pick-coche {
  margin-left: auto;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  border: 1.5px solid var(--baseline);
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: .68rem;
  color: #fff;
  transition: background .15s ease, border-color .15s ease;
}

.pick-item:has(input:checked) {
  border-color: color-mix(in srgb, var(--pole-buy) 45%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--pole-buy) 25%, transparent);
}
.pick-item:has(input:checked) .pick-fond { filter: none; opacity: .16; }
.pick-item:has(input:checked) .pick-coche {
  background: var(--pole-buy);
  border-color: var(--pole-buy);
}
.pick-item:has(input:checked) .pick-coche::after { content: "✓"; }

/* Ligne écartée : logo éteint, texte en retrait — l'état se voit sans lire. */
.pick-item:not(:has(input:checked)) .coin-logo { filter: grayscale(1); opacity: .55; }
.pick-item:not(:has(input:checked)) .pick-name { color: var(--text-secondary); }

/* La case étant masquée, le contour de focus clavier passe sur la tuile. */
.pick-item:has(input:focus-visible) {
  outline: 2px solid var(--pole-buy);
  outline-offset: 2px;
}

/* ---------- Infobulle de statistiques longues (page stratégie) ----------
   La mini-courbe dans le tableau est le déclencheur ; l'infobulle porte la
   courbe complète et les chiffres que les justifications citent. */

.stat-trigger {
  display: inline-flex;
  align-items: center;
  margin-top: .15rem;
  padding: .2rem .35rem;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--text-muted);
  cursor: pointer;
}

.stat-trigger:hover, .stat-trigger[aria-expanded="true"] {
  color: var(--text-secondary);
  background: var(--midpoint);
}

.stat-pop {
  position: fixed;
  z-index: 60;
  width: 268px;
  padding: .8rem .9rem;
  background: var(--surface-1);
  border: 1px solid var(--gridline);
  border-radius: var(--radius);
  box-shadow: 0 6px 24px rgb(0 0 0 / .14);
}

.stat-pop-head {
  margin: 0 0 .5rem;
  font-size: .78rem;
  color: var(--text-secondary);
}

.stat-pop-spark {
  color: var(--text-secondary);
  border-bottom: 1px solid var(--gridline);
  padding-bottom: .5rem;
  margin-bottom: .5rem;
}

.stat-pop-grid {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: .22rem .8rem;
  margin: 0;
  font-size: .78rem;
}

.stat-pop-grid dt { color: var(--text-muted); }
.stat-pop-grid dd { margin: 0; text-align: right; }

/* ---------- Graphique unique des 180 jours (page stratégie) ----------
   Huit séries : l'identité passe par l'étiquette directe et la surbrillance,
   jamais par huit couleurs — la palette validée n'en offre pas autant. */

/* `relative` : référentiel de l'infobulle ancrée (.pos-tip-ancree). Sans
   décalage, il ne change rien au rendu des autres pages. */
.strat-chart { position: relative; }
.strat-chart svg { width: 100%; height: auto; display: block; }

.sc-grid   { stroke: var(--gridline); stroke-width: 1; }
.sc-zero   { stroke: var(--baseline); stroke-width: 1.2; }
.sc-ylab, .sc-xlab { fill: var(--text-muted); font-size: 10.5px; font-family: var(--mono); }

.sc-ligne {
  stroke: var(--text-secondary);
  stroke-width: 1.4;
  opacity: .55;
  transition: opacity .12s ease, stroke .12s ease;
}

/* Bande invisible large : cible de survol confortable sans épaissir le trait. */
.sc-hit { stroke: transparent; stroke-width: 12; cursor: pointer; }

.sc-lab {
  fill: var(--text-secondary);
  font-size: 10.5px;
  font-family: var(--mono);
  cursor: pointer;
}

/* Étiquette-lien vers la fiche de l'actif : soulignée au survol seulement,
   pour ne pas alourdir un graphique qui en porte huit. */
.sc-lab-lien { cursor: pointer; }
.sc-lab-lien:hover .sc-lab { text-decoration: underline; fill: var(--pole-buy); }
.sc-lab-lien:focus-visible { outline: 2px solid var(--pole-buy); outline-offset: 1px; }

.pos-liens {
  margin: .7rem 0 0;
  font-size: .78rem;
  color: var(--text-muted);
}

.pos-liens a { color: var(--text-secondary); }

/* Une courbe isolée : elle prend le bleu, les autres s'estompent. */
.sc-isole .sc-ligne          { opacity: .18; }
.sc-isole .sc-ligne.sc-actif { opacity: 1; stroke: var(--pole-buy); stroke-width: 2.2; }
.sc-isole .sc-lab            { opacity: .35; }
.sc-isole .sc-lab.sc-actif   { opacity: 1; fill: var(--pole-buy); font-weight: 700; }

.sc-curseur { stroke: var(--baseline); stroke-width: 1; stroke-dasharray: 3 3; }

/* Variante ancrée (history.php) : absolue dans le conteneur du graphique,
   elle défile avec lui — un élément `fixed` restait planté à l'écran après
   un défilement, au-dessus d'un contenu étranger. `pointer-events: none` :
   l'infobulle ne doit jamais intercepter la souris qu'elle suit. */
.pos-tip-ancree {
  position: absolute !important;
  pointer-events: none;
}

.strat-chart-tip[hidden] { display: none; }
.strat-chart-tip {
  position: fixed;
  z-index: 60;
  display: grid;
  grid-template-columns: auto auto;
  gap: .1rem .7rem;
  padding: .55rem .7rem;
  background: var(--surface-1);
  border: 1px solid var(--gridline);
  border-radius: 8px;
  box-shadow: 0 6px 24px rgb(0 0 0 / .14);
  font-size: .74rem;
  font-family: var(--mono);
  pointer-events: none;
}

.strat-chart-tip strong { grid-column: 1 / -1; font-family: var(--font); }
.strat-chart-tip span:nth-child(even) { text-align: right; }

.hero-warn {
  margin-top: .6rem;
  padding: .5rem .6rem;
  border-radius: 6px;
  border: 1px solid color-mix(in srgb, var(--pole-sell) 35%, transparent);
  background: color-mix(in srgb, var(--pole-sell) 7%, transparent);
  font-size: .72rem;
  line-height: 1.45;
  color: var(--text-secondary);
}

.tip-alt {
  display: flex;
  align-items: center;
  gap: .35rem;
  font-family: var(--mono);
  font-size: .78rem;
  margin-top: .2rem;
  color: var(--text-secondary);
}

.zoom-info { color: var(--text-muted); }
#pf-hit { touch-action: pan-y; }

.alert-info {
  color: var(--text-secondary);
  border-color: var(--baseline);
  background: var(--midpoint);
}

.hero-strat-start {
  font-size: .72rem;
  color: var(--text-muted);
  margin-top: .5rem;
  line-height: 1.4;
}

/* Mouvement réduit — les nouvelles cartes en relief. Les translations
   disparaissent, l'élévation reste : elle porte de l'information
   hiérarchique, pas de l'animation. Les deux règles existantes plus haut
   ne couvrent que les clignotements de cours et le voile d'attente. */
@media (prefers-reduced-motion: reduce) {
  .lp-uses article:hover,
  .lp-news-card:hover,
  .heat a:hover { transform: none; }
}

/* ---------- Refonte du 4 août 2026 : réactivité des nouveaux blocs ---------- */

@media (max-width: 960px) {
  .lp-hero-grid { grid-template-columns: 1fr; gap: 1.8rem; }
  .heat { grid-template-columns: repeat(3, 1fr); }
  /* Colonnes de confort de la table : 30 j, sparkline, score, confiance. */
  .screener .col-opt { display: none; }
}

@media (max-width: 480px) {
  .heat { grid-template-columns: repeat(2, 1fr); }
}

/* ---------- Couverture de presse contre cours (news.php) ----------
   Ajouté le 4 août 2026. Le graphique est descriptif : la mesure imprimée
   à côté dit que la tonalité colle au mouvement DÉJÀ survenu (+0,36 le jour
   même) et n'a aucun lien avec la suite (−0,02 le lendemain). Ne pas retirer
   ce tableau : sans lui, le dessin suggère l'inverse de ce qui est mesuré. */

.news-graph { display: block; width: 100%; height: auto; margin: .4rem 0 .2rem; }

.ng-lede {
  font-size: .87rem;
  color: var(--text-secondary);
  margin: 0 0 .3rem;
  max-width: 52rem;
  line-height: 1.6;
}

.ng-mesure {
  margin-top: 1rem;
  padding-top: .9rem;
  border-top: 1px solid var(--gridline);
}

.ng-mesure-titre {
  margin: 0 0 .5rem;
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--text-muted);
  font-weight: 600;
}

.ng-verdict {
  font-size: .88rem;
  color: var(--text-secondary);
  line-height: 1.6;
  margin: .6rem 0 .4rem;
  max-width: 52rem;
}

.ng-verdict strong { color: var(--text-primary); }

.ng-note {
  font-size: .78rem;
  color: var(--text-muted);
  margin: 0;
  max-width: 52rem;
}

/* Deux sorties depuis la fiche d'une stratégie : l'atelier et l'inventaire. */
.detail-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 1.2rem;
  align-items: baseline;
  margin-bottom: .3rem;
}

/* ---------- Sélecteur de courbes de stratégies (history.php) ----------
   Refondu le 4 août 2026 : il occupait tout le haut de page avec quatorze
   pavés de titres. Les réelles restent visibles, les backtests passent
   derrière un <details> natif — replié par défaut, ouvert d'office si l'un
   d'eux est tracé. La ségrégation réel / rétrospectif est une exigence du
   produit, pas un choix graphique. */

.strat-picker {
  margin: .2rem 0 1rem;
  padding: .8rem .9rem;
  background: var(--midpoint);
  border-radius: var(--radius);
}

.sp-tete {
  display: flex;
  align-items: baseline;
  gap: .75rem;
  margin-bottom: .55rem;
}

.sp-titre {
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--text-muted);
  font-weight: 600;
}

.sp-reset {
  margin-left: auto;
  font-size: .76rem;
  color: var(--pole-buy);
  text-decoration: none;
  font-weight: 600;
}
.sp-reset:hover { text-decoration: underline; }

.sp-vide { font-size: .82rem; color: var(--text-muted); }

/* Puce de backtest : la date suffit à l'identifier, le titre complet vit
   dans l'infobulle. Trait pointillé — même langage que les avis
   reconstitués de la fiche actif : la forme dit « jamais émis en réel ». */
.tab-retro {
  border-style: dashed;
  font-family: var(--mono);
  font-size: .78rem;
}

.sp-retro { margin-top: .6rem; }

.sp-retro > summary {
  cursor: pointer;
  font-size: .8rem;
  color: var(--text-secondary);
  list-style-position: inside;
}
.sp-retro > summary::marker { color: var(--text-muted); }
.sp-retro > summary:hover { color: var(--text-primary); }

.sp-retro-note {
  color: var(--text-muted);
  font-size: .76rem;
}

.sp-note {
  margin: .7rem 0 0;
  font-size: .76rem;
  color: var(--text-muted);
  max-width: 46rem;
}

/* ---------- Réglages ---------- */

/* Case à cocher et son explication : la case reste native (accessibilité,
   focus clavier), c'est l'alignement qui est repris. */
.check-row {
  display: flex;
  align-items: flex-start;
  gap: .7rem;
  cursor: pointer;
  line-height: 1.45;
}
.check-row input[type="checkbox"] {
  flex: 0 0 auto;
  margin-top: .2rem;
  width: 1rem;
  height: 1rem;
  accent-color: var(--pole-buy);
  cursor: pointer;
}
.check-row strong { color: var(--text-primary); font-weight: 580; }

/* ---------------------------------------------------------------------------
   Barre « voir comme » : un administrateur regarde le site avec les yeux d'un
   autre compte. Fixée en bas plutôt qu'en haut — l'en-tête y est déjà collé, et
   deux éléments à `top: 0` se recouvrent. Aucun moyen de la masquer : c'est le
   seul indice que les chiffres à l'écran ne sont pas les siens.
   Teinte neutre volontaire : le bleu et le rouge du site portent un avis de
   marché, les recycler pour un état de session brouillerait ce langage.
   --------------------------------------------------------------------------- */
.view-as-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 120;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: .5rem 1rem;
  padding: .6rem 1rem;
  font-size: .85rem;
  color: var(--text-primary);
  background: var(--surface-1);
  border-top: 2px solid var(--text-muted);
  box-shadow: var(--elev-3);
}

.view-as-bar strong { font-weight: 600; }

.view-as-bar form { margin: 0; }

.view-as-bar button {
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  padding: .3rem .8rem;
  border-radius: 6px;
  color: var(--surface-page);
  background: var(--text-primary);
  border: 1px solid var(--text-primary);
}

.view-as-bar button:hover { opacity: .85; }

/* Réserve de la hauteur de la barre : sans elle, la fin de chaque page passe
   dessous. Elle n'est rendue que pendant une observation. */
.view-as-reserve { height: 3.6rem; }

@media (max-width: 32rem) {
  .view-as-bar { font-size: .8rem; }
  .view-as-reserve { height: 5rem; }
}

/* ================= Editorial — grille de presse =================
   Patron « Editorial Grid / Magazine » : grille asymétrique, une tête
   d'affiche par rubrique, hiérarchie portée par la typographie plutôt que
   par des boîtes.

   Aucune couleur nouvelle et aucune police téléchargée : la palette du site
   est validée au ΔE, et la règle « aucune ressource externe » interdit un
   Google Font. Le signal éditorial vient d'une pile SERIF SYSTÈME, présente
   partout, qui ne coûte aucune requête. IBM Plex Sans reste la police de
   l'interface — kickers, méta, badges — pour que le site reste le site. */

:root {
  --font-serif: Charter, "Bitstream Charter", "Iowan Old Style", Georgia,
                "Times New Roman", ui-serif, serif;

  /* Encres de texte des pôles. MESURÉES, pas choisies à vue : en thème clair
     les pôles eux-mêmes échouent au contraste dès qu'ils servent de couleur
     de TEXTE sur le fond de page — bleu 4,19:1, rouge 3,75:1, encre atténuée
     3,41:1, pour un seuil de 4,5:1. Ils passent comme fond d'un badge plein
     (c'est ainsi que .signal-badge les emploie), pas comme encre.
     Ces deux variantes sont les plus proches des pôles qui franchissent le
     seuil : bleu 6,25:1 (ΔE 14,3 du pôle), rouge 5,30:1 (ΔE 10,5) — même
     famille de teinte, simplement assombries. */
  --ink-buy:  #1f5da8;
  --ink-sell: #c03330;

  /* Confirmation d'un post par le marché. Une dimension DIFFÉRENTE de la
     direction du cours : un post baissier confirmé va avec une baisse. Réutiliser
     le bleu de --ink-buy rendrait le rouge ambigu — « le cours a baissé » ou
     « le post est contredit » ? Le vert lève cette ambiguïté.
     Mesuré, pas choisi : #1f9c72 (la teinte de strat_palette) rend 3,02:1 comme
     encre en clair, sous le seuil de 4,5 — un ton validé pour une COURBE ne
     l'est pas comme texte. #177a59 rend 4,61:1 en clair, #35c496 rend 5,31:1
     sur le fond sombre du bloc. ΔE vert/rouge : 94,5 en vision normale.
     Vert et rouge restent le pire couple pour le daltonisme : l'encodage
     secondaire est ici le texte lui-même — « moved WITH » / « moved AGAINST ». */
  --ink-with:    #177a59;
  --ink-against: #c03330;
}

/* En thème sombre les pôles passent déjà (5,34:1 et 4,92:1) : on les reprend
   tels quels plutôt que d'assombrir une encre sur un fond noir. */
@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) {
    --ink-buy:  var(--pole-buy);
    --ink-sell: var(--pole-sell);
    --ink-with:    #35c496;
    --ink-against: var(--pole-sell);
  }
}

:root[data-theme="dark"] {
  --ink-buy:  var(--pole-buy);
  --ink-sell: var(--pole-sell);
  --ink-with:    #35c496;
  --ink-against: var(--pole-sell);
}

/* ---- Bandeau de tête ---- */

.edito-masthead {
  border-bottom: 3px solid var(--text-primary);
  padding-bottom: .9rem;
  margin-bottom: 2.25rem;
}

.edito-masthead h1 {
  font-family: var(--font-serif);
  font-size: clamp(2.4rem, 6vw, 3.6rem);
  line-height: 1;
  letter-spacing: -.02em;
  margin: 0 0 .35rem;
  color: var(--text-primary);
}

.edito-dateline {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  font-size: .78rem;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.edito-standfirst {
  font-family: var(--font-serif);
  font-size: 1.06rem;
  line-height: 1.55;
  color: var(--text-secondary);
  max-width: 60ch;
  margin: 1rem 0 0;
}

/* ---- Rubrique ---- */

.edito-rub { margin: 0 0 3.25rem; }

.edito-rub-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  border-top: 1px solid var(--text-primary);
  padding-top: .55rem;
  margin-bottom: 1.4rem;
}

.edito-kicker {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  text-decoration: none;
  color: inherit;
}

.edito-kicker-nom {
  font-family: var(--font-serif);
  font-size: 1.35rem;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--text-primary);
}

.edito-kicker:hover .edito-kicker-nom { text-decoration: underline; }

.edito-kicker-code {
  font-size: .7rem;
  letter-spacing: .1em;
  color: var(--text-muted);
}

.edito-rub-call {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
  font-size: .74rem;
  color: var(--text-muted);
}

.edito-rub-call .edito-call-label {
  letter-spacing: .08em;
  text-transform: uppercase;
}

/* ---- Grille asymétrique : tête d'affiche + colonnes ---- */

.edito-grid {
  display: grid;
  grid-template-columns: 1.6fr 1fr;
  gap: 1.75rem 2.25rem;
  align-items: start;
}

.edito-cols {
  display: grid;
  gap: 1.1rem;
}

.edito-item {
  display: block;
  text-decoration: none;
  color: inherit;
}

.edito-item:hover .edito-titre { text-decoration: underline; }

.edito-item + .edito-item {
  border-top: 1px solid var(--gridline);
  padding-top: 1.1rem;
}

.edito-titre {
  font-family: var(--font-serif);
  font-weight: 700;
  letter-spacing: -.015em;
  color: var(--text-primary);
  margin: .3rem 0 0;
}

.edito-lead .edito-titre { font-size: clamp(1.5rem, 3.4vw, 2.05rem); line-height: 1.15; }
.edito-cols .edito-titre { font-size: 1.02rem; line-height: 1.3; }

.edito-lead .edito-chapo {
  font-family: var(--font-serif);
  font-size: 1.02rem;
  line-height: 1.6;
  color: var(--text-secondary);
  margin: .6rem 0 0;
  max-width: 56ch;
}

.edito-meta {
  display: flex;
  align-items: center;
  gap: .45rem;
  flex-wrap: wrap;
  margin: .5rem 0 0;
  font-size: .72rem;
  letter-spacing: .04em;
  color: var(--text-muted);
}

/* Étiquette de lecture : reprend le vocabulaire des signaux, en plus discret
   qu'un badge plein — un article n'est pas un verdict du site. */
.edito-read {
  display: inline-flex;
  align-items: center;
  gap: .25rem;
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  padding: .12rem .42rem;
  border-radius: 3px;
  border: 1px solid currentColor;
}

.edito-read.sig-buy     { color: var(--ink-buy); }
.edito-read.sig-sell    { color: var(--ink-sell); }
/* --text-secondary (7,53:1), pas --text-muted (3,41:1) : ce badge est du
   petit texte, il lui faut PLUS de contraste, pas moins. */
.edito-read.sig-neutral { color: var(--text-secondary); }

/* ---- Vue article ---- */

.edito-article { max-width: 68ch; margin: 0 auto; }

.edito-back {
  display: inline-block;
  font-size: .78rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 1.4rem;
}

.edito-art-kicker {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  text-decoration: none;
  font-size: .76rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-buy);
  margin-bottom: .5rem;
}

.edito-art-kicker:hover { text-decoration: underline; }

.edito-art-titre {
  font-family: var(--font-serif);
  font-size: clamp(1.85rem, 4.6vw, 2.7rem);
  line-height: 1.1;
  letter-spacing: -.02em;
  margin: 0 0 .7rem;
  color: var(--text-primary);
}

.edito-art-chapo {
  font-family: var(--font-serif);
  font-size: 1.16rem;
  line-height: 1.55;
  color: var(--text-secondary);
  margin: 0 0 1.1rem;
}

.edito-art-meta {
  display: flex;
  align-items: center;
  gap: .55rem;
  flex-wrap: wrap;
  padding: .55rem 0;
  border-top: 1px solid var(--gridline);
  border-bottom: 1px solid var(--gridline);
  font-size: .76rem;
  color: var(--text-muted);
  margin-bottom: 1.6rem;
}

.edito-corps p {
  font-family: var(--font-serif);
  font-size: 1.08rem;
  /* 1,7 : la fourchette de lecture longue est 1,5–1,75. */
  line-height: 1.7;
  color: var(--text-primary);
  margin: 0 0 1.15rem;
}

/* Lettrine : signal de presse imprimée, deux lignes, sans fioriture. */
.edito-corps p:first-of-type::first-letter {
  float: left;
  font-family: var(--font-serif);
  font-size: 3.1rem;
  line-height: .84;
  font-weight: 700;
  padding: .07em .09em 0 0;
  color: var(--text-primary);
}

/* ---- Les deux lectures, côte à côte et nommées ---- */

.edito-calls {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 1rem;
  margin: 2rem 0 1rem;
  padding: 1.1rem 1.2rem;
  background: var(--surface-1);
  border: 1px solid var(--gridline);
  border-radius: var(--radius);
}

.edito-call-t {
  display: block;
  font-size: .68rem;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: .45rem;
}

.edito-call-v {
  display: flex;
  align-items: center;
  gap: .45rem;
  flex-wrap: wrap;
}

.edito-call-note {
  font-size: .78rem;
  line-height: 1.55;
  color: var(--text-muted);
  margin: .3rem 0 0;
}

/* ---- Suite de rubrique ---- */

.edito-suite { margin-top: 2.5rem; padding-top: 1rem; border-top: 3px solid var(--text-primary); }

.edito-suite h2 {
  font-family: var(--font-serif);
  font-size: 1.15rem;
  margin: 0 0 .8rem;
}

.edito-suite ul { list-style: none; margin: 0; padding: 0; }

.edito-suite li + li { border-top: 1px solid var(--gridline); }

.edito-suite a {
  display: block;
  padding: .6rem 0;
  text-decoration: none;
  font-family: var(--font-serif);
  font-size: .98rem;
  line-height: 1.35;
  color: var(--text-primary);
}

.edito-suite a:hover { text-decoration: underline; }

/* ---- Responsive : 1024, 768, 375 ---- */

@media (max-width: 64rem) {
  .edito-grid { grid-template-columns: 1fr; gap: 1.4rem; }
  .edito-cols {
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: 1.2rem 1.75rem;
  }
  /* En colonnes côte à côte, le filet du dessus ne veut plus rien dire. */
  .edito-item + .edito-item { border-top: 0; padding-top: 0; }
  .edito-cols { border-top: 1px solid var(--gridline); padding-top: 1.2rem; }
}

@media (max-width: 32rem) {
  .edito-masthead { border-bottom-width: 2px; }
  .edito-cols { grid-template-columns: 1fr; }
  .edito-item + .edito-item { border-top: 1px solid var(--gridline); padding-top: 1.1rem; }
  .edito-corps p:first-of-type::first-letter { font-size: 2.6rem; }
}

/* ── Observation des sources sociales (admin-social.php) ───────────────────────────
   Aucun code couleur par PORTÉE : la couleur encode la direction et rien
   d'autre sur ce site, et inventer un second vocabulaire l'affaiblirait.
   La portée se lit sur sa puce écrite ; la tonalité garde `tone-chip`.
   Seule atténuation admise : le hors-sujet passe en retrait, comme un badge
   de signal sous 50 % de confiance — c'est un encodage de pertinence, pas
   de sens. */
.soc-muted { color: var(--text-muted); font-size: .85rem; }

.soc-filters { display: flex; flex-wrap: wrap; gap: .4rem; margin: 1rem 0 1.25rem; }
.soc-filters .chip { text-decoration: none; }

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

.soc-item {
  border: 1px solid var(--gridline);
  border-radius: var(--radius);
  background: var(--surface-1);
  padding: .85rem 1rem;
}

.soc-item.soc-hors-sujet { opacity: .58; }

.soc-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .4rem;
  margin-bottom: .5rem;
  font-size: .8rem;
}

.soc-meta .chip { cursor: default; padding: .18rem .55rem; font-size: .76rem; }
.soc-canal { font-weight: 600; color: var(--text-primary); }

.soc-resume { margin: .3rem 0 .45rem; font-size: .95rem; color: var(--text-primary); }
.soc-texte  { margin: 0 0 .5rem; font-size: .84rem; color: var(--text-secondary); }
.soc-item .soc-muted { text-decoration: none; }

@media (max-width: 640px) {
  .soc-meta { font-size: .75rem; }
}

/* Ce que le marché a fait après un message.
   Les pôles servent ici d'ENCRE : `--ink-buy` / `--ink-sell` et non
   `--pole-*`, qui ne franchissent le seuil de contraste que comme fond de
   badge — un pôle validé en fond n'est pas validé en encre, le contraste se
   recalcule à chaque changement de rôle. */
.soc-apres {
  margin: .6rem 0 .45rem;
  padding: .55rem .75rem;
  /* `--text-muted` et non `--baseline` : mesuré au contraste, la barre doit
     se détacher de la CARTE (seuil 3:1, WCAG 1.4.11 — un séparateur est un
     élément non textuel). --baseline rend 1,75:1 en clair et 1,48:1 en sombre,
     --gridline pire encore ; --text-muted donne 3,50:1 et 4,85:1. C est la
     barre qui porte la distinction, pas le fond : le fond reste neutre parce
     que la couleur encode la direction et rien d autre. */
  border-left: 4px solid var(--text-muted);
  background: var(--midpoint);
  border-radius: 0 var(--radius) var(--radius) 0;
}

/* Le bloc s'annonce : sans étiquette, une rangée de pourcentages sous un post
   se lit comme une donnée du post lui-même. */
.soc-apres-titre {
  display: block;
  margin-bottom: .35rem;
  font-size: .7rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.soc-apres-ligne { display: flex; flex-wrap: wrap; align-items: baseline; gap: .55rem; }
.soc-apres-ligne + .soc-apres-ligne { margin-top: .3rem; }

.soc-apres-sym {
  font-family: var(--mono);
  font-size: .78rem;
  color: var(--text-muted);
  min-width: 5.5rem;
}

.soc-apres-h { font-size: .84rem; color: var(--text-secondary); }
.soc-apres-h strong { font-family: var(--mono); font-size: .9rem; }
.soc-apres-h small { font-size: .72rem; color: var(--text-muted); }
.soc-apres-h.soc-up   strong { color: var(--ink-buy); }
.soc-apres-h.soc-down strong { color: var(--ink-sell); }
.soc-apres-h.soc-flat strong { color: var(--text-secondary); }
.soc-apres-vide { color: var(--text-muted); }

.soc-apres-note {
  margin: .45rem 0 0;
  font-size: .76rem;
  color: var(--text-muted);
  line-height: 1.45;
}

/* Verdict en clair. La couleur reprend les pôles du site EN ENCRE — elle
   encode ici une direction (le marché est allé dans le sens du post, ou
   contre), ce qui est son rôle légitime. Le cas non jugeable reste neutre :
   lui donner une teinte inventerait un troisième pôle. */
.soc-verdict {
  margin: .1rem 0 .25rem;
  font-size: .82rem;
  font-weight: 600;
}
.soc-verdict-sub { font-weight: 400; color: var(--text-muted); font-size: .78rem; }
.soc-v-confirme  { color: var(--ink-with); }
.soc-v-contredit { color: var(--ink-against); }
.soc-v-neutre,
.soc-v-na        { color: var(--text-secondary); font-weight: 500; }

/* Barre du bloc de mesure, colorée par le verdict.
   Elle ne prend une couleur que si TOUS les instruments concordent : un bloc
   macro juge à la fois ^GSPC et BTCUSDT, et les deux peuvent diverger. Une
   barre unique sur des verdicts opposés affirmerait ce que la mesure ne dit
   pas — elle reste alors neutre. */
.soc-apres.soc-bar-confirme  { border-left-color: var(--ink-with); }
.soc-apres.soc-bar-contredit { border-left-color: var(--ink-against); }
/* Graphique en forêt des scores de canaux (admin-social.php).
   MONOCHROME par construction : le validateur du skill dataviz rend ΔE 3,9
   entre le gris « neutre » et le rouge en protanopie sur fond sombre — un
   protanope confondrait les deux. La géométrie porte donc le sens : une barre
   qui coupe la ligne des 50 % dit « indistinguable du hasard ». Une teinte
   n'apparaît que lorsqu'un intervalle cesse de la couper, et elle est alors
   doublée du texte de lecture. */
.soc-forest { width: 100%; height: auto; display: block; margin: 1.25rem 0 .5rem; }

.soc-f-grid   { stroke: var(--gridline); stroke-width: 1; }
.soc-f-tick,
.soc-f-nom,
.soc-f-val    { fill: var(--text-muted); font-size: 11px; font-family: var(--font); }
.soc-f-nom    { text-anchor: end; fill: var(--text-secondary); font-size: 12px; }
.soc-f-val    { font-family: var(--mono); font-size: 11px; }
.soc-f-tick   { text-anchor: middle; }

/* La ligne du hasard est la référence de lecture : plus marquée que la grille,
   et nommée — une ligne de référence anonyme n'est qu'un trait de plus. */
.soc-f-chance     { stroke: var(--text-muted); stroke-width: 1.5; stroke-dasharray: 4 3; }
.soc-f-chance-lab { fill: var(--text-muted); font-size: 10px; font-family: var(--font);
                   letter-spacing: .04em; }

.soc-f-ic  { stroke: var(--text-secondary); stroke-width: 2; }
.soc-f-cap { stroke: var(--text-secondary); stroke-width: 2; }
.soc-f-pt  { fill: var(--text-primary); stroke: var(--surface-1); stroke-width: 2; }

/* Cas où un canal se détacherait : jamais rencontré à ce jour. */
.soc-f-ic.soc-f-seul,
.soc-f-cap.soc-f-seul { stroke: var(--ink-with); }
.soc-f-pt.soc-f-seul  { fill: var(--ink-with); }

.soc-tabs { margin: 0 0 1.5rem; }

/* En-têtes de tri (admin-sources.php).
   Un lien dans un `th` hérite du bleu souligné et casse la ligne des petites
   capitales grises : il doit porter le style de l'EN-TÊTE, pas celui d'un lien.
   L'affordance passe par le survol et par la flèche de la colonne active —
   pas par une couleur qui hurle. `nowrap` empêche la flèche de tomber à la
   ligne, ce qui décalait la hauteur des cellules voisines. */
.help-table th a {
  color: inherit;
  text-decoration: none;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: .25rem;
  border-bottom: 1px solid transparent;
  transition: color .12s, border-color .12s;
}

.help-table th a:hover,
.help-table th a:focus-visible {
  color: var(--text-primary);
  border-bottom-color: var(--baseline);
}

/* Colonne active : c'est l'encre qui la marque, la flèche ne fait que
   rappeler le sens. */
.help-table th a.is-sorted { color: var(--text-primary); font-weight: 600; }
.help-table th a .soc-arrow { font-size: .85em; opacity: .75; }

/* ── Editorial refondu — 29 août 2026 ─────────────────────────────────────
   La première version alignait douze blocs au gabarit identique : une liste,
   pas un magazine. Trois tiers la remplacent — une une, un fil transversal,
   les rubriques compactées.

   Le site n'a PAS d'images : « aucune ressource externe » interdit de charger
   les illustrations de presse, et les billets n'en portent pas. Le repère
   visuel vient donc du LOGO local de l'actif et de sa COULEUR DE MARQUE, la
   réponse déjà retenue pour l'accueil et les cartes d'actualité. `--marque`
   n'encadre jamais un texte : elle ne sert que de filet et de fond très
   dilué, parce qu'elle n'est validée à aucun contraste d'encre. */

.edito-kick {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .2rem .55rem .2rem .3rem;
  border-radius: 999px;
  border: 1px solid var(--gridline);
  background: color-mix(in srgb, var(--marque, var(--gridline)) 10%, transparent);
  font-size: .74rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-secondary);
  text-decoration: none;
}
.edito-kick:hover { color: var(--text-primary); border-color: var(--baseline); }
.edito-kick img { border-radius: 50%; }

/* ── La une ── */
.edito-une {
  border-top: 3px solid var(--text-primary);
  border-bottom: 1px solid var(--gridline);
  padding: 1.1rem 0 1.5rem;
  margin-bottom: 2rem;
}
.edito-une-titre {
  font-family: var(--font-serif);
  font-size: clamp(1.7rem, 4.2vw, 2.6rem);
  line-height: 1.14;
  letter-spacing: -.015em;
  margin: .7rem 0 .6rem;
}
.edito-une-titre a { color: var(--text-primary); text-decoration: none; }
.edito-une-titre a:hover { text-decoration: underline; text-underline-offset: .18em; }
.edito-une-chapo {
  font-family: var(--font-serif);
  font-size: 1.06rem;
  line-height: 1.55;
  color: var(--text-secondary);
  max-width: 46rem;
  margin: 0 0 .9rem;
}
.edito-une-meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: .5rem;
  font-size: .78rem; color: var(--text-muted); margin: 0;
}
.edito-src { font-style: italic; }

/* ── Titres de section : la règle typographique, pas une boîte ── */
.edito-sec-titre {
  font-size: .78rem;
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--text-muted);
  border-bottom: 1px solid var(--text-primary);
  padding-bottom: .35rem;
  margin: 0 0 1rem;
}

/* ── Le fil transversal ── */
.edito-fil { margin-bottom: 2.5rem; }
.edito-fil-liste { list-style: none; margin: 0; padding: 0; }
.edito-fil-liste li {
  display: grid;
  grid-template-columns: minmax(7rem, auto) 1fr auto;
  align-items: baseline;
  gap: .75rem;
  padding: .6rem 0;
  border-bottom: 1px solid var(--gridline);
}
.edito-fil-titre {
  font-family: var(--font-serif);
  font-size: 1.02rem;
  line-height: 1.35;
  color: var(--text-primary);
  text-decoration: none;
}
.edito-fil-titre:hover { text-decoration: underline; text-underline-offset: .16em; }
.edito-fil-liste time { font-size: .75rem; color: var(--text-muted); white-space: nowrap; }

/* ── Les rubriques, compactées ── */
.edito-rubs {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(19rem, 1fr));
  gap: 1.1rem;
}
.edito-rubs .edito-sec-titre { grid-column: 1 / -1; }

.edito-rub-carte {
  border: 1px solid var(--gridline);
  border-top: 3px solid var(--marque, var(--baseline));
  border-radius: var(--radius);
  background: var(--surface-1);
  padding: .85rem 1rem 1rem;
  display: flex;
  flex-direction: column;
}
.edito-rub-tete {
  display: flex; align-items: center; gap: .5rem;
  padding-bottom: .55rem; margin-bottom: .5rem;
  border-bottom: 1px solid var(--gridline);
}
.edito-rub-nom {
  display: inline-flex; align-items: center; gap: .45rem;
  font-weight: 600; color: var(--text-primary); text-decoration: none;
}
.edito-rub-nom img { border-radius: 50%; }
.edito-rub-call { margin-left: auto; text-decoration: none; }
.edito-rub-n { font-size: .72rem; color: var(--text-muted); font-family: var(--mono); }

.edito-rub-liste { list-style: none; margin: 0 0 .7rem; padding: 0; flex: 1; }
.edito-rub-liste li { padding: .35rem 0; }
.edito-rub-liste li + li { border-top: 1px solid var(--gridline); }
.edito-rub-liste a {
  font-family: var(--font-serif);
  font-size: .93rem; line-height: 1.35;
  color: var(--text-primary); text-decoration: none;
}
.edito-rub-liste a:hover { text-decoration: underline; text-underline-offset: .14em; }
.edito-rub-liste time { display: block; font-size: .7rem; color: var(--text-muted); margin-top: .12rem; }

.edito-rub-plus {
  font-size: .76rem; color: var(--text-secondary);
  text-decoration: none; border-top: 1px solid var(--gridline); padding-top: .55rem;
}
.edito-rub-plus:hover { color: var(--text-primary); }

@media (max-width: 560px) {
  .edito-fil-liste li { grid-template-columns: 1fr auto; }
  .edito-fil-liste li .edito-kick { grid-column: 1 / -1; }
}

/* Courbes de l'éditorial : ce sont elles qui tiennent le rôle des vignettes.
   `preserveAspectRatio="none"` étant hérité de spark_svg, chaque conteneur
   fixe sa hauteur et laisse la largeur suivre — sans quoi la courbe se
   déformerait différemment selon la colonne. */
.edito-une-courbe {
  margin: 0 0 .9rem;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface-page);
}
.edito-une-courbe svg { display: block; width: 100%; height: clamp(90px, 14vw, 150px); }

.edito-fil-courbe { display: inline-block; width: 74px; }
.edito-fil-courbe svg { display: block; width: 74px; height: 24px; }

.edito-rub-courbe {
  margin: 0 0 .6rem;
  border-radius: calc(var(--radius) / 2);
  overflow: hidden;
  background: var(--surface-page);
}
.edito-rub-courbe svg { display: block; width: 100%; height: 44px; }

/* Le fil gagne une quatrième colonne pour sa vignette. */
.edito-fil-liste li { grid-template-columns: minmax(7rem, auto) 1fr auto auto; }

@media (max-width: 560px) {
  .edito-fil-liste li { grid-template-columns: 1fr auto; }
  .edito-fil-liste li .edito-kick { grid-column: 1 / -1; }
  .edito-fil-courbe { display: none; }
}

/* Graphique technique (lib/view.php chart_tech).
   Les étiquettes portent des tokens de TEXTE, jamais la couleur de la série :
   un chiffre reste lisible quel que soit le sens du marché, et la couleur ne
   sert qu'à la courbe. */
.chart-tech { width: 100%; height: auto; display: block; }
.ct-grid { stroke: var(--gridline); stroke-width: 1; }
.ct-lab  { fill: var(--text-muted); font-size: 10px; font-family: var(--font); }
.ct-mm   { fill: none; stroke: var(--text-muted); stroke-width: 1.2;
           stroke-dasharray: 4 3; opacity: .75; }
.ct-var  { font-size: 12px; font-weight: 600; font-family: var(--mono); }
.ct-up   { fill: var(--ink-buy); }
.ct-down { fill: var(--ink-sell); }

/* Bandeau de marché en tête d'éditorial : douze tuiles, chacune une courbe et
   sa variation. Le chiffre porte le pôle EN ENCRE (--ink-*, mesurés au
   contraste), la courbe porte le pôle en trait — jamais l'inverse : un pôle
   validé comme trait ne l'est pas comme texte. */
.edito-board {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
  gap: .5rem;
  margin: 0 0 1.75rem;
}
.edito-board-tuile {
  display: block;
  padding: .5rem .6rem .35rem;
  border: 1px solid var(--gridline);
  border-radius: var(--radius);
  background: var(--surface-1);
  text-decoration: none;
  transition: border-color .12s;
}
.edito-board-tuile:hover { border-color: var(--baseline); }
.edito-board-tete {
  display: flex; align-items: center; gap: .35rem;
  margin-bottom: .2rem; font-size: .74rem;
}
.edito-board-tete img { border-radius: 50%; }
.edito-board-code { font-weight: 600; color: var(--text-primary); font-family: var(--mono); }
.edito-board-chg  { margin-left: auto; font-family: var(--mono); font-size: .72rem; font-weight: 600; }
.edito-board-tuile svg { display: block; width: 100%; height: 30px; }

/* Le fil : courbe + variation chiffrée, empilées dans la même colonne. */
.edito-fil-courbe { display: flex; flex-direction: column; align-items: flex-end; gap: .1rem; width: 88px; }
.edito-fil-courbe svg { display: block; width: 88px; height: 26px; }
.edito-fil-chg { font-family: var(--mono); font-size: .68rem; font-weight: 600; }

/* Logos de rubrique doublés : ils portent l'identité que les vignettes
   photographiques tiendraient ailleurs. */
.edito-rub-nom img { border-radius: 50%; }
.edito-rub-nom { font-size: 1.02rem; }

@media (max-width: 560px) {
  .edito-board { grid-template-columns: repeat(auto-fill, minmax(7rem, 1fr)); }
}

/* Vue chronologique : la liste du fil, coupée par journée. */
.edito-chrono li:not(.edito-chrono-jour) { grid-template-columns: minmax(7rem,auto) 1fr auto auto; }
.edito-chrono-jour {
  display: block !important;
  border-bottom: 1px solid var(--text-primary) !important;
  padding: 1.4rem 0 .35rem !important;
  font-size: .74rem; text-transform: uppercase; letter-spacing: .12em;
  color: var(--text-muted);
}
.edito-chrono-jour:first-child { padding-top: 0 !important; }

/* Le lien « view all » vit dans le titre de section, aligné à droite. */
.edito-sec-titre { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
.edito-voir {
  font-size: .72rem; letter-spacing: .06em; text-transform: none;
  color: var(--text-secondary); text-decoration: none; white-space: nowrap;
}
.edito-voir:hover { color: var(--text-primary); text-decoration: underline; }

/* Chargement continu : l'état est discret et la sentinelle invisible. */
.edito-sentinelle { height: 1px; }
.edito-chargement {
  text-align: center; padding: 1.2rem 0 .4rem;
  font-size: .78rem; color: var(--text-muted);
}

/* Gestion des flux (admin-flux.php). */
.flux-form { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; margin: 1rem 0 .6rem; }
.flux-url { flex: 1 1 22rem; }
.flux-form input, .flux-form select {
  padding: .45rem .6rem; border: 1px solid var(--gridline);
  border-radius: var(--radius); background: var(--surface-1);
  color: var(--text-primary); font: inherit; font-size: .88rem;
}
.flux-actions { white-space: nowrap; }
.flux-actions .btn { padding: .25rem .6rem; font-size: .78rem; }
/* Un flux en pause reste lisible : il est en retrait, pas effacé — on doit
   pouvoir le retrouver pour le réactiver. */
.flux-pause td { opacity: .55; }
.flux-on { color: var(--ink-with); font-weight: 600; font-size: .82rem; }

/* ── Administration : barre de navigation et cartes ────────────────────── */

/* Les cinq pages d'administration se sont ajoutées une à une, chacune
   atteignable seulement depuis admin.php. La barre les relie entre elles.
   `color: inherit` est indispensable : un <a> stylé en .chip hériterait
   sinon du bleu souligné des liens et casserait la ligne — le défaut déjà
   payé sur les en-têtes de tri d'admin-sources. */
.admin-nav {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem;
  margin: 0 0 1.6rem;
}

.admin-nav .chip {
  color: var(--text-secondary);
  text-decoration: none;
  white-space: nowrap;
}

.admin-nav .chip:hover { color: var(--text-primary); }

.admin-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: .75rem;
  margin: 0 0 2.5rem;
}

/* La carte ENTIÈRE est le lien, pas son titre : une cible de la taille du
   cadre ne se rate pas, et le survol dit sans ambiguïté ce qui est cliquable.
   Grille en lignes plutôt que flux : les chiffres s'alignent d'une carte à
   l'autre même quand les descriptions ont des longueurs différentes. */
.admin-card {
  display: grid;
  grid-template-rows: auto auto auto 1fr;
  gap: .15rem;
  padding: 1rem 1.05rem 1.1rem;
  border: 1px solid var(--gridline);
  border-radius: 10px;
  background: var(--surface-1);
  color: inherit;
  text-decoration: none;
  transition: border-color .15s, background .15s, transform .15s;
}

.admin-card:hover {
  border-color: var(--baseline);
  background: var(--midpoint);
  transform: translateY(-1px);
}

.admin-card:focus-visible {
  outline: 2px solid var(--pole-buy);
  outline-offset: 2px;
  border-radius: 10px;
}

.admin-card-t {
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

/* Chiffres tabulaires : sans eux les valeurs d'une carte à l'autre ne
   s'alignent pas verticalement, et une grille de chiffres qui titube se lit
   comme un défaut de rendu. */
.admin-card-n {
  font-size: 1.75rem;
  font-weight: 600;
  line-height: 1.1;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

.admin-card-u {
  font-size: .78rem;
  color: var(--text-secondary);
  margin-bottom: .5rem;
}

.admin-card-d {
  font-size: .8rem;
  line-height: 1.45;
  color: var(--text-secondary);
}

.admin-h2 {
  font-size: 1.15rem;
  margin: 0 0 .35rem;
}

/* Le tableau des sources confronté au hasard. Encadré plutôt que fondu dans
   la prose : c'est la lecture qui doit précéder toutes les autres, et un
   paragraphe de plus se saute. Pas de couleur directionnelle — ce panneau ne
   dit ni bien ni mal, il dit « indistinguable ». */
.soc-hasard {
  margin: 1.6rem 0 0;
  padding: 1.1rem 1.2rem .4rem;
  border: 1px solid var(--gridline);
  border-left: 3px solid var(--baseline);
  border-radius: 8px;
  background: var(--surface-1);
}

.soc-hasard h3 {
  margin: 0 0 .8rem;
  font-size: 1rem;
}

.soc-hasard p {
  font-size: .86rem;
  line-height: 1.55;
  color: var(--text-secondary);
}

.soc-hasard-t { margin-bottom: 1rem; }

/* ── Comparaison de modèles (admin) ────────────────────────────────────── */

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

/* Deux teintes validées au ΔE, la troisième distinguée par le MOTIF de trait.
   Inventer une troisième couleur échouerait au validateur — l'ambre rend 3,5
   et le violet 5,2 contre le seuil de 15. */
.mdl-line { fill: none; stroke-width: 2; stroke-linejoin: round; }
.mdl-a { stroke: var(--pole-buy); }
.mdl-b { stroke: var(--pole-sell); }

.mdl-tag { font-size: 11px; font-weight: 600; }
.mdl-tag.mdl-a { fill: var(--ink-buy); stroke: none; }
.mdl-tag.mdl-b { fill: var(--ink-sell); stroke: none; }

/* Les références sont en encre neutre : elles ne portent aucune direction,
   elles servent d'étalon. Trois motifs distincts, aucune couleur en plus. */
.mdl-ref { fill: none; stroke: var(--text-secondary); stroke-width: 1.4; opacity: .75; }
.mdl-ref-cash   { stroke-dasharray: 2 3; }
.mdl-ref-btc    { stroke-dasharray: 8 4; }
.mdl-ref-panier { stroke-dasharray: 1 4; }

.mdl-legend { display: flex; flex-wrap: wrap; gap: 1rem; font-size: .82rem;
              color: var(--text-secondary); margin: .5rem 0 0; }
.mdl-key { display: inline-flex; align-items: center; gap: .4rem; }
.mdl-key::before { content: ''; width: 22px; height: 0;
                   border-top: 1.4px dashed var(--text-secondary); }

.mdl-refrow td { color: var(--text-secondary); }

/* ── Filtres de courbes de simulation.php ─────────────────────────────── */

.simu-filtres {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .4rem;
  margin: 0 0 .8rem;
}

.simu-filtres-k {
  font-size: .68rem;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--text-secondary);
  margin-right: .2rem;
}

/* Pastille des étalons : creuse et pointillée, comme leur tracé. Une légende
   qui montrerait un aplat plein pour une courbe en pointillé mentirait sur
   le dessin qu'elle décrit. */
.legend-dot-ref {
  background: transparent;
  border: 1.5px dashed var(--text-secondary);
}

/* ── Ajout d'instruments au socle (admin) ────────────────────────────── */

.socle-ajouts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1rem;
  margin-top: 1.4rem;
}

/* Deux cartes plutôt qu'une rangée de champs : les deux gestes n'ouvrent pas
   la même chaîne d'analyse ni le même coût, et la forme doit le dire avant
   que l'opérateur ne clique. */
.socle-carte {
  padding: 1rem 1.1rem 1.1rem;
  border: 1px solid var(--gridline);
  border-radius: 10px;
  background: var(--surface-1);
}

.socle-carte-t {
  margin: 0 0 .3rem;
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.socle-carte-d {
  margin: 0 0 .9rem;
  font-size: .82rem;
  line-height: 1.45;
  color: var(--text-secondary);
}

/* ── Tuiles de chiffres-clés (fiche actif) ───────────────────────────── */

.kpi-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: .7rem;
  margin: 1.2rem 0 1.4rem;
}

.kpi {
  padding: .85rem 1rem .95rem;
  border: 1px solid var(--gridline);
  border-radius: 10px;
  background: var(--surface-1);
  display: grid;
  gap: .12rem;
}

.kpi-k {
  font-size: .68rem;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

/* Chiffres tabulaires : sans eux les valeurs d'une tuile à l'autre ne
   s'alignent pas, et une rangée de chiffres qui titube se lit comme un
   défaut de rendu. */
.kpi-v {
  font-size: 1.45rem;
  font-weight: 600;
  line-height: 1.15;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  letter-spacing: -.015em;
}

.kpi-s {
  font-size: .78rem;
  color: var(--text-secondary);
}

/* ============================================================ chat de lecture
   Bulle flottante du back-office (admin seulement). Rendue par render_foot(),
   donc présente sur toutes les pages sans les modifier une par une.

   Aucune couleur inventée : uniquement les variables du thème, qui sont déjà
   validées au ΔE. La bulle est ancrée en `fixed` — c'est le seul cas légitime
   sur ce site, parce qu'elle n'appartient à aucun conteneur (contrairement à
   l'infobulle du graphique des positions, qui devait être ancrée en absolu).
   Elle laisse la place à la bannière « view as », qui occupe déjà le bas. */

.chatbot {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 900;                    /* sous la bannière view-as, qui est à 1000 */
  font-family: var(--font);
}

/* Le bouton d'ouverture. */
.chatbot-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 18px;
  border: 1px solid var(--gridline);
  border-radius: 999px;
  background: var(--surface-1);
  color: var(--text-primary);
  box-shadow: var(--elev-2);
  cursor: pointer;
  font-size: 0.9rem;
  font-weight: 600;
  transition: box-shadow 0.15s, transform 0.15s;
}
.chatbot-toggle:hover { box-shadow: var(--elev-3); transform: translateY(-1px); }
.chatbot-toggle svg { width: 18px; height: 18px; flex: none; }

/* Le panneau. Hauteur bornée par la fenêtre : sur un portable, une hauteur
   fixe déborderait sans que rien ne le signale. */
.chatbot-panel {
  display: flex;
  flex-direction: column;
  width: min(420px, calc(100vw - 40px));
  height: min(560px, calc(100vh - 120px));
  border: 1px solid var(--gridline);
  border-radius: var(--radius);
  background: var(--surface-page);
  box-shadow: var(--elev-3);
  overflow: hidden;
}

.chatbot-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--gridline);
  background: var(--surface-1);
}
.chatbot-title { font-size: 0.9rem; font-weight: 600; }
.chatbot-sub {
  display: block;
  font-size: 0.72rem;
  font-weight: 400;
  color: var(--text-muted);
  margin-top: 2px;
}
.chatbot-actions { display: flex; gap: 4px; }
.chatbot-icon {
  border: 0; background: none; cursor: pointer;
  color: var(--text-muted); padding: 4px 8px; border-radius: 6px;
  font-size: 0.95rem; line-height: 1;
}
.chatbot-icon:hover { background: var(--midpoint); color: var(--text-primary); }

.chatbot-log {
  flex: 1;
  overflow-y: auto;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-size: 0.85rem;
  line-height: 1.5;
}

.chatbot-msg { max-width: 92%; }
.chatbot-msg.user {
  align-self: flex-end;
  background: var(--midpoint);
  padding: 8px 12px;
  border-radius: 12px 12px 2px 12px;
}
.chatbot-msg.bot {
  align-self: flex-start;
  color: var(--text-primary);
}
.chatbot-msg.bot strong { font-weight: 600; }
.chatbot-msg.bot ul { margin: 6px 0; padding-left: 18px; }
.chatbot-msg.bot li { margin: 3px 0; }
.chatbot-msg.bot code {
  font-family: var(--mono); font-size: 0.9em;
  background: var(--midpoint); padding: 1px 4px; border-radius: 3px;
}
.chatbot-msg.bot h3 {
  font-size: 0.85rem; font-weight: 600; margin: 10px 0 4px;
  color: var(--text-secondary);
}

/* La provenance : quels outils ont répondu. Elle n'est pas décorative — elle
   dit au lecteur d'où vient chaque chiffre, donc ce qu'il peut aller vérifier
   sur le site. Un résumé dont on ignore la source n'est pas vérifiable. */
.chatbot-src {
  font-size: 0.7rem;
  color: var(--text-muted);
  font-family: var(--mono);
  margin-top: 4px;
}

.chatbot-err {
  align-self: stretch;
  font-size: 0.8rem;
  color: var(--ink-sell);
  border-left: 2px solid var(--pole-sell);
  padding-left: 10px;
}

/* Attente. Trois points, sans animation coûteuse. */
.chatbot-wait { color: var(--text-muted); font-size: 0.8rem; }
.chatbot-wait::after {
  content: '';
  animation: chatbot-dots 1.2s steps(4, end) infinite;
}
@keyframes chatbot-dots {
  0%   { content: ''; }
  25%  { content: '.'; }
  50%  { content: '..'; }
  75%  { content: '...'; }
}
@media (prefers-reduced-motion: reduce) {
  .chatbot-wait::after { animation: none; content: '...'; }
}

.chatbot-form {
  display: flex;
  gap: 8px;
  padding: 10px;
  border-top: 1px solid var(--gridline);
  background: var(--surface-1);
}
.chatbot-input {
  flex: 1;
  border: 1px solid var(--gridline);
  border-radius: 8px;
  padding: 9px 11px;
  background: var(--surface-page);
  color: var(--text-primary);
  font-family: var(--font);
  font-size: 0.85rem;
  resize: none;
  max-height: 90px;
}
.chatbot-input:focus-visible { outline: 2px solid var(--pole-buy); outline-offset: 1px; }
.chatbot-send {
  border: 0; border-radius: 8px; padding: 0 14px;
  background: var(--pole-buy); color: #fff;
  cursor: pointer; font-weight: 600; font-size: 0.85rem;
}
.chatbot-send:disabled { opacity: 0.5; cursor: not-allowed; }

/* Suggestions de départ : elles montrent ce que l'outil sait faire. Un champ
   vide n'apprend rien à personne. */
.chatbot-hints { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.chatbot-hint {
  border: 1px solid var(--gridline); border-radius: 999px;
  background: none; color: var(--text-secondary);
  padding: 5px 11px; font-size: 0.75rem; cursor: pointer;
  font-family: var(--font);
}
.chatbot-hint:hover { background: var(--midpoint); color: var(--text-primary); }

/* Sur petit écran, la bulle ne doit pas manger la page. */
@media (max-width: 520px) {
  .chatbot { right: 12px; bottom: 12px; }
  .chatbot-panel { height: min(70vh, calc(100vh - 100px)); }
}

/* -------------------------------------------------- journal du chat (admin)
   Le fil d'une conversation. La question et la réponse se distinguent par
   l'indentation et un filet, pas par une couleur : ce ne sont pas deux
   directions opposées mais deux rôles, et les pôles du site encodent la
   direction — les recycler ici les rendrait ambigus ailleurs. */

.chatlog-msg { margin: 0 0 18px; }
.chatlog-user { border-left: 3px solid var(--gridline); padding-left: 12px; }
.chatlog-assistant { padding-left: 12px; }

.chatlog-meta {
  font-size: 0.75rem;
  color: var(--text-muted);
  margin: 0 0 5px;
}
.chatlog-meta code { font-family: var(--mono); font-size: 0.95em; }

.chatlog-body {
  font-size: 0.88rem;
  line-height: 1.55;
  color: var(--text-primary);
  white-space: normal;
}
.chatlog-user .chatlog-body { color: var(--text-secondary); }

.chatlog-err {
  font-size: 0.82rem;
  color: var(--ink-sell);
  margin: 0;
}

/* ------------------------------------------------ avatar de Gloppr (l'agent)
   SVG inline, donc aucune requête réseau et aucun fichier à servir. Il porte
   le ◈ de la marque sur un disque, avec dessous une micro-courbe : l'agent LIT
   des séries, il n'en produit pas. Ses couleurs viennent des variables du
   thème, donc il suit le clair et le sombre sans seconde version. */

.chatbot-ava { flex: none; display: block; border-radius: 50%; }

/* En-tête : avatar et titre alignés. */
.chatbot-ident { display: flex; align-items: center; gap: 10px; min-width: 0; }

/* Message du bot : avatar à gauche, texte à droite, alignés en haut. */
.chatbot-msg.bot {
  display: flex;
  gap: 9px;
  align-items: flex-start;
  max-width: 100%;
}
.chatbot-txt { min-width: 0; }
.chatbot-txt > p:first-child { margin-top: 0; }
.chatbot-txt > p:last-child  { margin-bottom: 0; }

/* Attente : même gabarit, pour que le texte ne saute pas quand la réponse
   arrive — un décalage de mise en page se lit comme un défaut. */
.chatbot-wait {
  display: flex;
  align-items: center;
  gap: 9px;
}

/* Le bouton fermé porte l'avatar à la place d'une icône générique. */
.chatbot-toggle { padding-left: 12px; }

/* Une image déposée est recadrée en cercle et centrée : elle arrivera dans
   n'importe quel rapport, et un avatar ovale ou déformé se voit. */
img.chatbot-ava { object-fit: cover; border-radius: 50%; }

/* `display: flex` ci-dessus a la même spécificité que la règle `[hidden]` du
   navigateur, et l'auteur l'emporte : sans ces deux lignes, `el.hidden = true`
   ne cache RIEN — le bouton et le panneau restaient affichés ensemble, et la
   croix de fermeture paraissait morte. Même parade que `.pos-card[hidden]`. */
.chatbot-toggle[hidden],
.chatbot-panel[hidden] { display: none !important; }

/* ------------------------------------------------- régime de marché (accueil)
   Descriptif : il encadre la lecture des signaux, il n'en est pas un. D'où un
   traitement sobre — pas de pastille colorée qui le ferait lire comme un
   verdict. La teinte vient des pôles du site, atténuée. */
.regime {
  border: 1px solid var(--gridline);
  border-left: 3px solid var(--pole-neutral);
  border-radius: var(--radius);
  background: var(--surface-1);
  padding: .85rem 1.05rem;
  margin: 0 0 1.2rem;
  display: flex; flex-direction: column; gap: .5rem;
}
.regime[data-regime="risk-on"]  { border-left-color: var(--pole-buy); }
.regime[data-regime="risk-off"] { border-left-color: var(--pole-sell); }

.regime-head { display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap; }
.regime-k {
  font-family: var(--mono); font-size: .68rem; letter-spacing: .07em;
  text-transform: uppercase; color: var(--text-muted);
}
.regime-v { font-size: .95rem; font-weight: 650; letter-spacing: .02em; }
.regime[data-regime="risk-on"]  .regime-v { color: var(--ink-buy); }
.regime[data-regime="risk-off"] .regime-v { color: var(--ink-sell); }
.regime-n { font-size: .72rem; color: var(--text-muted); margin-left: auto; }

.regime-list {
  margin: 0; padding: 0; list-style: none;
  display: flex; flex-wrap: wrap; gap: .3rem .9rem;
  font-size: .8rem; color: var(--text-secondary);
}
.regime-list li { position: relative; padding-left: .7rem; }
.regime-list li::before {
  content: '·'; position: absolute; left: 0; color: var(--text-muted);
}
.regime-note { margin: 0; font-size: .72rem; color: var(--text-muted); }

/* ---------- Market Watch ----------
   Pas de teinte inventée : les pôles du site portent le sens (bon/mauvais),
   le neutre reste neutre. La lecture doit tenir sur un téléphone, d'où des
   listes en flex plutôt qu'un tableau pour les blocs à deux colonnes. */
.mw-tete { margin-bottom: 1.6rem; }
.mw-maj { font-size: .82rem; color: var(--text-muted); margin: .35rem 0 0; }
.mw-stale { color: var(--ink-sell); }

.mw-bandeau {
  border-left: 3px solid var(--pole-sell);
  background: var(--surface-1);
  padding: .9rem 1.1rem; border-radius: 0 8px 8px 0; margin-bottom: 1.4rem;
  display: flex; flex-direction: column; gap: .25rem;
}
.mw-bandeau strong { color: var(--ink-sell); }
.mw-bandeau span { font-size: .88rem; color: var(--text-secondary); }

.mw-bloc {
  background: var(--surface-1); border: 1px solid var(--gridline);
  border-radius: var(--radius); padding: 1.2rem 1.3rem; margin-bottom: 1.1rem;
}
.mw-bloc h2 {
  font-size: .78rem; letter-spacing: .09em; text-transform: uppercase;
  color: var(--text-muted); margin: 0 0 .9rem;
}
.mw-etat { font-size: 1.5rem; font-weight: 600; margin: 0; letter-spacing: -.01em; }
.mw-sous { color: var(--text-secondary); margin: .5rem 0 0; max-width: 62ch; }
.mw-note { font-size: .84rem; color: var(--text-muted); margin: 0 0 .9rem; max-width: 62ch; }
.mw-rien { color: var(--text-muted); margin: 0; }

.mw-pastille {
  display: inline-block; padding: .12rem .55rem; border-radius: 999px;
  font-size: .78rem; font-weight: 600; border: 1px solid var(--gridline);
}
.mw-bon    { color: var(--ink-buy); }
.mw-mauv   { color: var(--ink-sell); }
.mw-neutre { color: var(--text-secondary); }
.mw-fl { font-size: .7rem; margin-left: .3rem; }

.mw-lead { list-style: none; margin: 0; padding: 0; }
.mw-lead li {
  display: flex; justify-content: space-between; align-items: center; gap: 1rem;
  padding: .55rem 0; border-bottom: 1px solid var(--gridline);
}
.mw-lead li:last-child { border-bottom: none; }
.mw-classe { color: var(--text-primary); }

.mw-scroll { overflow-x: auto; }
.mw-table { width: 100%; border-collapse: collapse; font-size: .9rem; }
.mw-table th {
  text-align: left; font-size: .72rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-muted); font-weight: 500; padding-bottom: .5rem;
  border-bottom: 1px solid var(--baseline);
}
.mw-table td { padding: .55rem .8rem .55rem 0; border-bottom: 1px solid var(--gridline); }
.mw-table tr:last-child td { border-bottom: none; }
.mw-sym { font-family: var(--mono); font-weight: 600; white-space: nowrap; }
.mw-com { color: var(--text-secondary); font-size: .85rem; }

.mw-hist { list-style: none; margin: 0; padding: 0; max-height: 15rem; overflow-y: auto; }
.mw-hist li { padding: .45rem 0; border-bottom: 1px solid var(--gridline); font-size: .9rem; }
.mw-hist li:last-child { border-bottom: none; }
.mw-quand { font-family: var(--mono); font-size: .78rem; color: var(--text-muted); margin-right: .6rem; }

.mw-conflits { margin: .4rem 0 0; padding-left: 1.1rem; color: var(--text-secondary); font-size: .88rem; }
.mw-conflits li { margin-bottom: .3rem; }
.mw-methode p { font-size: .85rem; color: var(--text-secondary); max-width: 66ch; margin: 0 0 .6rem; }
.mw-methode p:last-child { margin-bottom: 0; }

@media (max-width: 640px) {
  .mw-table th:nth-child(3), .mw-table td:nth-child(3) { display: none; }
  .mw-etat { font-size: 1.25rem; }
  .mw-lead li { flex-wrap: wrap; gap: .3rem; }
}

/* ---------- Market Watch : grille et graphiques ----------
   Barres horizontales, jamais de radar : la comparaison y est plus précise et
   la lecture mobile meilleure. Chaque état porte un TEXTE et une direction —
   la couleur ne fait que l'appuyer, jamais le porter seule (accessibilité). */
.mw-hero {
  display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-end;
  gap: 1rem; margin-bottom: 1.4rem;
}
.mw-hero h1 { margin: 0; }
.mw-baseline { color: var(--text-secondary); margin: .25rem 0 0; }

.mw-grille { display: grid; grid-template-columns: 1fr; gap: 1.1rem; }
@media (min-width: 900px) {
  .mw-grille {
    grid-template-columns: 2fr 1fr;
    grid-template-areas:
      "regime  changed"
      "lead    risk"
      "shifts  shifts"
      "events  events";
  }
  .mw-c-regime  { grid-area: regime; }
  .mw-c-changed { grid-area: changed; }
  .mw-c-lead    { grid-area: lead; }
  .mw-c-risk    { grid-area: risk; }
  .mw-c-shifts  { grid-area: shifts; }
  .mw-c-events  { grid-area: events; }
}
.mw-bloc { margin-bottom: 0; }

.mw-mini { display: flex; flex-wrap: wrap; gap: .5rem 1.4rem; margin-top: 1rem;
           padding-top: .9rem; border-top: 1px solid var(--gridline); }
.mw-mini-i { display: flex; flex-direction: column; gap: .25rem; }
.mw-mini-t { font-size: .72rem; letter-spacing: .05em; text-transform: uppercase; color: var(--text-muted); }

/* Barres divergentes autour d'un centre neutre. */
.mw-bars { list-style: none; margin: 0; padding: 0; }
.mw-bars li {
  display: grid; grid-template-columns: 8.5rem 1fr auto auto; align-items: center;
  gap: .7rem; padding: .5rem 0; border-bottom: 1px solid var(--gridline);
}
.mw-risk li { grid-template-columns: 9.5rem 1fr auto; }
.mw-bars li:last-child { border-bottom: none; }
.mw-piste { position: relative; height: 10px; background: var(--midpoint); border-radius: 5px; }
.mw-axe { position: absolute; left: 50%; top: -3px; bottom: -3px; width: 1px; background: var(--baseline); }
.mw-barre { position: absolute; top: 0; bottom: 0; border-radius: 5px; min-width: 2px; }
.mw-b-bon    { background: var(--pole-buy); }
.mw-b-mauv   { background: var(--pole-sell); }
.mw-b-neutre { background: var(--pole-neutral); }

.mw-spark { display: block; }
.mw-spark polyline { fill: none; stroke: var(--text-muted); stroke-width: 1.4; }
.mw-s-bon polyline  { stroke: var(--pole-buy); }
.mw-s-mauv polyline { stroke: var(--pole-sell); }

/* Cartes de pré-signaux. */
.mw-cartes { display: grid; grid-template-columns: repeat(auto-fill, minmax(215px, 1fr)); gap: .8rem; }
.mw-carte {
  display: flex; flex-direction: column; gap: .45rem; text-decoration: none;
  border: 1px solid var(--gridline); border-radius: var(--radius);
  padding: .8rem .9rem; background: var(--surface-page); color: inherit;
}
.mw-carte:hover { border-color: var(--baseline); }
.mw-carte-t { display: flex; justify-content: space-between; align-items: baseline; gap: .5rem; }
.mw-duree { font-family: var(--mono); font-size: .72rem; color: var(--text-muted); }

.mw-events { list-style: none; margin: 0; padding: 0; }
.mw-events li { display: flex; flex-direction: column; gap: .2rem; padding: .6rem 0;
                border-bottom: 1px solid var(--gridline); }
.mw-events li:last-child { border-bottom: none; }
.mw-ev-t { font-weight: 600; }
.mw-ev-m { font-size: .78rem; color: var(--text-muted); }

/* Echelle nommee sous les barres de leadership : la lecture passe par des
   mots, jamais par un chiffre — la vue publique ne porte aucune valeur. */
.mw-echelle { display: flex; justify-content: space-between; margin: .55rem 0 0;
              font-size: .7rem; letter-spacing: .05em; text-transform: uppercase;
              color: var(--text-muted); }

/* Risques : quatre crans, parce que le niveau sous-jacent EST discret.
   Une barre continue suggererait une precision que la mesure n a pas. */
.mw-crans { display: grid; grid-template-columns: repeat(4, 1fr); gap: 3px; }
.mw-cran { height: 9px; border-radius: 2px; background: var(--gridline); }
.mw-cran.mw-b-bon    { background: var(--ink-with, var(--pole-buy)); }
.mw-cran.mw-b-neutre { background: var(--text-muted); }
.mw-cran.mw-b-mauv   { background: var(--pole-sell); }

@media (max-width: 640px) {
  .mw-bars li { grid-template-columns: 1fr auto; }
  .mw-bars .mw-piste, .mw-bars .mw-spark { grid-column: 1 / -1; }
  .mw-cartes { grid-template-columns: 1fr; }
}

/* ---------- Tables larges : sortir du gabarit de LECTURE ----------
 *
 * `main` est plafonné à 1120 px parce que c'est une largeur de lecture : au-delà,
 * une ligne de prose devient pénible à suivre. Une table de dix colonnes n'est pas
 * de la prose, et ce plafond la coupait — `overflow-x` la rendait défilable, donc
 * techniquement complète et pratiquement illisible.
 *
 * Le débordement est réservé aux écrans qui ont la place (>= 1240 px) et borné à
 * 1560 px : au-delà, l'œil perd la ligne entre la première et la dernière colonne.
 * En dessous du seuil, rien ne change et le défilement reprend son rôle.
 */
/*
 * La section doit d abord CESSER de contraindre : `.help-sec` est plafonnee
 * a 46rem sans `margin: auto`, donc collee a gauche dans `main`. Centrer la
 * table sur ce bloc la decalait de 400 px — le symptome vu a l ecran.
 * Une fois la section rendue a la largeur de `main`, qui est centre, la
 * table se centre sur la fenetre par simple arithmetique.
 */
.help-sec.is-large { max-width: none; }

@media (min-width: 1240px) {
  .help-tablewrap.is-large {
    width: min(1560px, calc(100vw - 3rem));
    margin-left: calc((100% - min(1560px, 100vw - 3rem)) / 2);
  }
}

/*
 * Optimisation de la table large : les colonnes chiffrees ne doivent jamais
 * revenir a la ligne — un nombre coupe en deux se relit mal — et la colonne
 * de lecture, seule a porter du texte, absorbe la largeur restante.
 */
.help-table.is-dense th, .help-table.is-dense td { padding: .45rem .7rem; }
.help-table.is-dense td:not(:first-child):not(:last-child) { white-space: nowrap; }
.help-table.is-dense td:last-child { width: 1%; white-space: nowrap; }
.help-table.is-dense td:first-child { min-width: 12rem; }

/* Icône de carte d'administration. Elle accompagne le titre, elle ne le
   remplace pas : posée en ligne, alignée sur la ligne de base du texte, et
   volontairement discrète — une icône plus contrastée que son libellé
   attirerait l'œil sur le dessin plutôt que sur le sujet. */
.admin-card-i {
  flex: none;
  margin-right: .5rem;
  color: var(--text-muted);
  vertical-align: -.22em;
}
.admin-card:hover .admin-card-i,
.admin-card:focus-visible .admin-card-i { color: var(--pole-buy); }

/* Texte réservé aux lecteurs d'écran. Le badge de crédits n'affiche qu'un
   nombre : « 999 » sans son unité ne veut rien dire à qui écoute la page.
   `clip-path` plutôt que `display:none`, qui retirerait aussi le texte de
   l'arbre d'accessibilité — c'est-à-dire l'inverse du but. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Solde de crédits dans la barre de navigation. Discret par défaut — c'est un
   compteur, pas une alerte — et il ne prend la couleur de vente qu'une fois
   épuisé, moment où il devient une information à agir. */
.nav-credits {
  display: inline-flex;
  align-items: center;
  gap: .22rem;
  margin-left: .35rem;
  padding: .05rem .38rem;
  border: 1px solid var(--gridline);
  border-radius: 999px;
  font-size: .68rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1.5;
  color: var(--text-muted);
}
.nav-credits-vide {
  color: var(--ink-sell);
  border-color: var(--ink-sell);
}

/* Invitation à ouvrir un compte, là où la prose du modèle est réservée.
   Pas un bandeau ni une superposition : le visiteur voit ce qu'il obtient
   (verdict, confiance, cours, graphiques) et lit une phrase qui dit ce qui
   manque. Une pastille floutée sur un texte illisible serait une frustration
   déguisée en argument. */
.lock-note {
  margin: 0;
  padding: .85rem 1rem;
  border: 1px dashed var(--gridline);
  border-radius: var(--radius);
  font-size: .88rem;
  line-height: 1.55;
  color: var(--text-muted);
}
.lock-note a { color: var(--pole-buy); }

/* Invitation à suivre le canal Telegram. Une bande sobre, pas une bannière :
   le site vend une lecture mesurée, une accroche criarde le contredirait avant
   qu'on l'ait lue. Le bouton porte l'adresse en clair — un « Rejoindre » nu
   oblige à cliquer pour savoir où l'on va. */
.lp-canal { margin: 2.5rem 0; }
.lp-canal-in {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem 1.6rem;
  max-width: 1120px;
  margin: 0 auto;
  padding: 1.3rem 1.5rem;
  border: 1px solid var(--gridline);
  border-radius: var(--radius);
  background: var(--surface-1);
}
.lp-canal h2 { margin: 0 0 .3rem; font-size: 1.05rem; letter-spacing: -.01em; }
.lp-canal p  { margin: 0; font-size: .88rem; color: var(--text-secondary); max-width: 46rem; }
.lp-canal-cta { display: inline-flex; align-items: center; gap: .45rem; flex: none; }

/* Invitation au canal, en modale. Sobre : le site vend une lecture mesurée,
   une popup criarde le contredirait avant qu'on l'ait lue. */
/* `display: flex` ECRASE l attribut `hidden` : sans cette regle la modale ne
   se cache jamais, s affiche des le chargement, et le bouton de fermeture ne
   peut rien faire — `hidden` est une declaration du navigateur, toute regle
   d auteur qui pose un `display` la bat. Constate en production. */
.tg-modal[hidden] { display: none; }

.tg-modal {
  position: fixed;
  inset: 0;
  /* Au-dessus de TOUT : l en-tete collant est a 90, un sous-menu a 70. A 60
     la modale serait passee sous l en-tete — un voile qui ne voile pas. */
  z-index: 120;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.2rem;
  background: rgba(0, 0, 0, .45);
}
.tg-modal-box {
  position: relative;
  width: 100%;
  max-width: 27rem;
  padding: 1.6rem 1.7rem 1.5rem;
  border: 1px solid var(--gridline);
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow: 0 18px 48px rgba(0, 0, 0, .28);
}
.tg-modal-box { text-align: center; }
.tg-modal-box h2 { margin: 0 0 .5rem; font-size: 1.12rem; letter-spacing: -.01em; }
.tg-modal-box > p { margin: 0 0 1.2rem; font-size: .9rem; color: var(--text-secondary); }
.tg-modal-grid {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  text-align: center;
}
/* Le QR garde TOUJOURS un fond blanc et des modules sombres, quel que soit le
   thème : une trame inversée n'est pas lue par tous les lecteurs. */
.tg-modal-grid img {
  flex: none;
  width: 150px; height: 150px;
  padding: 6px;
  background: #fff;
  border-radius: 8px;
  image-rendering: pixelated;
}
.tg-modal-hint { margin: .6rem 0 0; font-size: .78rem; color: var(--text-muted); }
.tg-modal-x {
  position: absolute;
  top: .5rem; right: .6rem;
  border: 0; background: none;
  font-size: 1.5rem; line-height: 1;
  color: var(--text-muted);
  cursor: pointer;
  padding: .2rem .4rem;
}
.tg-modal-x:hover, .tg-modal-x:focus-visible { color: var(--text-primary); }
@media (max-width: 420px) {
  .tg-modal-grid { justify-content: center; text-align: center; }
}
@media (prefers-reduced-motion: no-preference) {
  .tg-modal-box { animation: tg-in .18s ease-out; }
  @keyframes tg-in { from { opacity: 0; transform: translateY(6px); } }
}

/* ---------- Vitre : la page se devine, elle ne se lit pas ----------
 *
 * Le voile est un LIEN qui couvre toute la zone : un clic n'importe où mène à
 * la connexion. Un `pointer-events: none` sur le contenu aurait suffi à
 * empêcher l'interaction, mais pas à offrir une destination — un visiteur qui
 * clique sans rien obtenir croit la page cassée.
 */
.mw-vitre { position: relative; }
.mw-floute {
  filter: blur(5px) saturate(.85);
  /* `user-select` en plus du flou : un texte flou reste sélectionnable et
     copiable, donc lisible dans le presse-papiers. */
  user-select: none;
  pointer-events: none;
}
.mw-vitre-voile {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: block;
  border-radius: var(--radius);
  /* Le voile porte la teinte du fond, pas du noir : sur le thème sombre un
     voile noir écraserait le contenu au lieu de l'estomper. */
  background: color-mix(in srgb, var(--bg) 45%, transparent);
}
.mw-vitre-cta {
  position: absolute;
  z-index: 3;
  top: 3.5rem;
  left: 50%;
  transform: translateX(-50%);
  width: min(24rem, calc(100% - 2rem));
  padding: 1.5rem 1.6rem;
  text-align: center;
  border: 1px solid var(--gridline);
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow: 0 14px 40px rgba(0, 0, 0, .22);
}
.mw-vitre-cta h2 { margin: 0 0 .5rem; font-size: 1.1rem; letter-spacing: -.01em; }
.mw-vitre-cta p  { margin: 0 0 1rem; font-size: .88rem; color: var(--text-secondary); }

/* Encart « exemple » : la trajectoire du compte de démonstration.
   Deux colonnes sur large, empilé en dessous. Le chiffre est mis en avant,
   mais sa RÉFÉRENCE est sur la même ligne, en plus petit — un rendement isolé
   se lit comme une promesse, accolé à son repère il redevient une mesure. */
.lp-demo { margin: 2.5rem 0; }

/* Halo de l'encart de démonstration (demande utilisateur, 3 septembre 2026).

   Le halo est bâti sur --pole-buy, la teinte déjà validée au ΔE du site : une
   couleur d'ambiance inventée ici entrerait en collision avec les courbes, le
   défaut mesuré de l'orange à ΔE 3,5 du rouge du portefeuille.

   Les deux thèmes reçoivent des intensités DIFFÉRENTES, jamais déduites l'une
   de l'autre : un halo composé sur fond clair se voit à 12 % d'opacité et
   disparaît sur fond sombre à la même valeur — c'est la leçon des rubans du
   Sankey, calibrés en clair puis tombés à 2,1:1 de contraste en sombre.

   Aucune information n'est portée par ce halo : il attire l'œil sur une
   invitation, il n'encode ni performance ni direction. Un encart qui brillerait
   en vert quand la courbe monte inventerait un signal. */
.lp-demo-in {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.4rem;
  max-width: 1120px;
  margin: 0 auto;
  padding: 1.5rem 1.6rem;
  border: 1px solid color-mix(in srgb, var(--pole-buy) 28%, var(--gridline));
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--pole-buy) 10%, transparent),
    0 2px 10px color-mix(in srgb, var(--pole-buy) 10%, transparent),
    0 12px 38px color-mix(in srgb, var(--pole-buy) 14%, transparent);
  transition: box-shadow .25s ease, border-color .25s ease;
}
.lp-demo-in:hover {
  border-color: color-mix(in srgb, var(--pole-buy) 42%, var(--gridline));
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--pole-buy) 16%, transparent),
    0 2px 12px color-mix(in srgb, var(--pole-buy) 14%, transparent),
    0 16px 48px color-mix(in srgb, var(--pole-buy) 20%, transparent);
}

/* Sur fond sombre le halo doit être plus dense pour exister, et la bordure
   plus franche — un liseré à 28 % se noie dans un gris déjà sombre. */
@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) .lp-demo-in {
    border-color: color-mix(in srgb, var(--pole-buy) 40%, var(--gridline));
    box-shadow:
      0 0 0 1px color-mix(in srgb, var(--pole-buy) 18%, transparent),
      0 2px 14px color-mix(in srgb, var(--pole-buy) 20%, transparent),
      0 16px 54px color-mix(in srgb, var(--pole-buy) 26%, transparent);
  }
  :root:where(:not([data-theme="light"])) .lp-demo-in:hover {
    border-color: color-mix(in srgb, var(--pole-buy) 55%, var(--gridline));
    box-shadow:
      0 0 0 1px color-mix(in srgb, var(--pole-buy) 26%, transparent),
      0 2px 16px color-mix(in srgb, var(--pole-buy) 26%, transparent),
      0 20px 64px color-mix(in srgb, var(--pole-buy) 34%, transparent);
  }
}
:root[data-theme="dark"] .lp-demo-in {
  border-color: color-mix(in srgb, var(--pole-buy) 40%, var(--gridline));
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--pole-buy) 18%, transparent),
    0 2px 14px color-mix(in srgb, var(--pole-buy) 20%, transparent),
    0 16px 54px color-mix(in srgb, var(--pole-buy) 26%, transparent);
}
:root[data-theme="dark"] .lp-demo-in:hover {
  border-color: color-mix(in srgb, var(--pole-buy) 55%, var(--gridline));
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--pole-buy) 26%, transparent),
    0 2px 16px color-mix(in srgb, var(--pole-buy) 26%, transparent),
    0 20px 64px color-mix(in srgb, var(--pole-buy) 34%, transparent);
}

/* Une transition sur une surface aussi large est exactement ce que
   `prefers-reduced-motion` existe pour éteindre. */
@media (prefers-reduced-motion: reduce) {
  .lp-demo-in { transition: none; }
}
@media (min-width: 900px) {
  .lp-demo-in { grid-template-columns: minmax(0, 20rem) minmax(0, 1fr); align-items: center; }
}
.lp-demo h2 { margin: 0 0 .5rem; font-size: 1.15rem; letter-spacing: -.01em; }
.lp-demo p  { margin: 0 0 .8rem; font-size: .9rem; color: var(--text-secondary); }
.lp-demo-chiffres { display: flex; flex-wrap: wrap; align-items: baseline; gap: .2rem .7rem; }
.lp-demo-perf {
  font-size: 1.9rem;
  font-weight: 650;
  letter-spacing: -.02em;
  color: var(--ink-buy);
  font-variant-numeric: tabular-nums;
}
.lp-demo-ref { font-size: .8rem; color: var(--text-muted); }
.lp-demo-reserve {
  font-size: .78rem !important;
  line-height: 1.5;
  color: var(--text-muted) !important;
  padding-top: .7rem;
  border-top: 1px solid var(--gridline);
}
.lp-demo-graph svg { width: 100%; height: auto; display: block; }

/* Page « exemple ». Les chiffres en ligne, la RÉFÉRENCE au même rang que la
   performance : la hiérarchiser aurait suggéré qu'elle compte moins, alors
   qu'elle est ce qui rend le premier chiffre lisible. */
.ex-chiffres {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 1rem 1.4rem;
  margin: .3rem 0 1.2rem;
}
.ex-chiffres > div { display: flex; flex-direction: column; gap: .2rem; }
.ex-k {
  font-size: .72rem;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.ex-v {
  font-size: 1.35rem;
  font-weight: 620;
  letter-spacing: -.01em;
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
}
.ink-up   { color: var(--ink-buy); }
.ink-down { color: var(--ink-sell); }
.ex-note {
  font-size: .82rem;
  line-height: 1.55;
  color: var(--text-muted);
  padding-top: .8rem;
  border-top: 1px solid var(--gridline);
}

/* ---------- Connexion et inscription (3 septembre 2026) ----------
   Maquette validée par l'utilisateur : une carte centrée, précédée d'un panneau
   visuel sur grand écran. `.auth-wrap` sert encore `password.php` — les deux
   cohabitent, elles ne se remplacent pas.

   Le panneau visuel DISPARAÎT sous 940 px, et ce n'est pas un repli paresseux :
   sur un téléphone, la seule chose qui compte est le champ de saisie, et une
   illustration de 94 Ko poussée avant lui retarde ce pour quoi la page existe.
   `aria-hidden` côté HTML dit la même chose aux lecteurs d'écran. */

.auth-split {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  align-items: center;
  max-width: 1120px;
  margin: 2rem auto 3rem;
  padding: 0 1rem;
}
@media (min-width: 940px) {
  .auth-split { grid-template-columns: minmax(0, 1fr) minmax(0, 25rem); gap: 3rem; }
}

.auth-visuel { display: none; position: relative; }
@media (min-width: 940px) { .auth-visuel { display: block; } }

.auth-visuel img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius);
  border: 1px solid var(--gridline);
}

/* Bandeau de texte en pied d'image. Le dégradé n'est pas décoratif : posé
   directement, du texte clair sur une illustration chargée devient illisible
   dès que le motif est pâle — un contraste qui dépend du pixel qu'il recouvre
   n'est pas un contraste. Le voile le rend indépendant de l'image.
   Les teintes sont FIXES et non tokenisées : elles se composent sur une
   photographie, pas sur le fond du thème. */
.auth-visuel-txt {
  position: absolute;
  inset: auto 0 0 0;
  padding: 3rem 1.4rem 1.3rem;
  border-radius: 0 0 var(--radius) var(--radius);
  background: linear-gradient(to top, rgba(6, 12, 24, .92), rgba(6, 12, 24, 0));
}
.auth-visuel-t {
  margin: 0 0 .3rem;
  font-size: 1.05rem;
  font-weight: 600;
  line-height: 1.35;
  color: #fff;
  text-wrap: balance;
}
.auth-visuel-s { margin: 0; font-size: .85rem; color: rgba(255, 255, 255, .78); }

.auth-card {
  padding: 1.7rem 1.6rem;
  border: 1px solid var(--gridline);
  border-radius: var(--radius);
  background: var(--surface-1);
}
.auth-h   { margin: 0 0 .35rem; font-size: 1.35rem; letter-spacing: -.01em; }
.auth-sub { margin: 0 0 1.3rem; font-size: .9rem; color: var(--text-secondary); line-height: 1.5; }

.auth-liens {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: .45rem;
  margin: 1.1rem 0 0;
  font-size: .85rem;
  color: var(--text-secondary);
}
.auth-liens span { color: var(--text-muted); }

.auth-note {
  margin: 1.1rem 0 0;
  font-size: .78rem;
  line-height: 1.5;
  color: var(--text-muted);
}

/* Aides de champ. `.field-aide` est un <span> dans le <label> : il hérite donc
   de l'étiquette et se lit avec le champ, là où un texte posé à côté serait
   annoncé séparément — ou pas du tout. */
.field-opt  { font-weight: 400; color: var(--text-muted); }
.field-aide {
  display: block;
  margin-top: .3rem;
  font-size: .78rem;
  color: var(--text-muted);
}

/* Trois chiffres du site, lus en base. Séparateur en bordure plutôt qu'en
   caractère : il ne se lit pas à voix haute et ne se copie pas avec le texte. */
.auth-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: .6rem;
  margin-top: 1.4rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--gridline);
  text-align: center;
}
.auth-stat + .auth-stat { border-left: 1px solid var(--gridline); }
.auth-stat b {
  display: block;
  font-size: 1.05rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
}
.auth-stat span {
  display: block;
  margin-top: .1rem;
  font-size: .72rem;
  line-height: 1.3;
  color: var(--text-muted);
}

/* ---------- Bande « appels du jour + carte de marché » (3 septembre 2026) ----
   Les deux sections s'empilaient sur toute la largeur ; la table laissait un
   vide à sa droite et la carte repoussait tout le reste d'un écran.

   Le seuil est à 1200 px, pas au point de rupture habituel : sous cette
   largeur la table a déjà renoncé à ses colonnes `col-opt` (960 px), et lui
   retirer encore un tiers de place la rendrait illisible sans rien gagner.

   `align-items: start` compte : sans lui, les deux colonnes s'étireraient à la
   hauteur de la plus longue et la carte de marché se retrouverait avec des
   tuiles distendues. */
.lp-band { display: grid; gap: 1.6rem; }
@media (min-width: 1200px) {
  .lp-band {
    grid-template-columns: minmax(0, 1.85fr) minmax(0, 1fr);
    gap: 2rem;
    align-items: start;
  }
  /* Les marges verticales des sections viennent de leur propre règle ; dans la
     bande, c'est `gap` qui espace. Les neutraliser évite le décalage d'une
     colonne par rapport à l'autre. */
  .lp-band > .screener-sec,
  .lp-band > .heat-sec { margin-top: 0; }
}
