
:root{
  color-scheme:light dark;
  --bg:oklch(0.985 0.004 210);
  --surface:oklch(1 0 0);
  --surface-2:oklch(0.972 0.005 210);
  --accent:oklch(0.906 0.008 215);
  --accent-hover:oklch(0.872 0.010 215);
  --line:oklch(0.906 0.008 215);
  --line-soft:oklch(0.945 0.006 215);
  --ink:oklch(0.24 0.018 220);
  --ink-2:oklch(0.40 0.018 220);
  --mut:oklch(0.475 0.017 220);
  --brand:oklch(0.44 0.078 205);
  /* ⚠️ L'encre POSÉE SUR la marque, pas à côté : en clair la marque est
     sombre, en sombre elle est claire. Une seule couleur de texte pour
     les deux rendrait l'avatar illisible dans l'un des deux thèmes. */
  --brand-on:oklch(0.985 0.004 205);
  --brand-ink:oklch(0.33 0.075 205);
  --brand-wash:oklch(0.955 0.017 205);
  --up:oklch(0.505 0.132 155);
  --up-wash:oklch(0.945 0.045 155);
  --down:oklch(0.525 0.185 26);
  --down-wash:oklch(0.955 0.035 26);
  --warn:oklch(0.60 0.13 75);
  --warn-wash:oklch(0.962 0.045 85);
  /* --r-sm était consommé par .tip, .crange input[type=date] et .crange button
     sans avoir jamais été déclaré : les trois border-radius étaient invalides et
     retombaient à 0. Champs et boutons se posent à 4 px (échelle Carbon), les
     surfaces flottantes à 8. */
  --r-sm:8px; --r-fld:4px; --r:10px; --r-lg:14px;
  --shadow:0 1px 2px oklch(0.24 0.018 220/.05), 0 1px 3px oklch(0.24 0.018 220/.04);
  --pad:clamp(14px,2.2vw,20px);
  --ease:cubic-bezier(.22,1,.36,1);
}
@media (prefers-color-scheme:dark){
  :root:not([data-theme=light]){
    --bg:oklch(0.178 0.014 222);
    --surface:oklch(0.216 0.016 222);
    --surface-2:oklch(0.247 0.017 222);
    --accent:oklch(0.315 0.018 222);
    --accent-hover:oklch(0.352 0.019 222);
    --line:oklch(0.315 0.018 222);
    --line-soft:oklch(0.272 0.016 222);
    --ink:oklch(0.945 0.008 220);
    --ink-2:oklch(0.83 0.012 220);
    --mut:oklch(0.715 0.017 220);
    --brand:oklch(0.76 0.075 200);
    --brand-on:oklch(0.19 0.02 205);
    --brand-ink:oklch(0.85 0.06 200);
    --brand-wash:oklch(0.30 0.035 205);
    --up:oklch(0.78 0.105 158);
    --up-wash:oklch(0.30 0.055 158);
    --down:oklch(0.74 0.115 26);
    --down-wash:oklch(0.30 0.06 27);
    --warn:oklch(0.79 0.12 82);
    --warn-wash:oklch(0.32 0.05 82);
    --shadow:0 1px 2px oklch(0 0 0/.30), 0 1px 3px oklch(0 0 0/.22);
  }
}
:root[data-theme=dark]{
  --bg:oklch(0.178 0.014 222); --surface:oklch(0.216 0.016 222);
  --surface-2:oklch(0.247 0.017 222);
  --accent:oklch(0.315 0.018 222); --accent-hover:oklch(0.352 0.019 222);
  --line:oklch(0.315 0.018 222);
  --line-soft:oklch(0.272 0.016 222); --ink:oklch(0.945 0.008 220);
  --ink-2:oklch(0.83 0.012 220); --mut:oklch(0.715 0.017 220);
  --brand:oklch(0.76 0.075 200); --brand-ink:oklch(0.85 0.06 200);
  --brand-on:oklch(0.19 0.02 205);
  --brand-wash:oklch(0.30 0.035 205);
  --up:oklch(0.78 0.105 158); --up-wash:oklch(0.30 0.055 158);
  --down:oklch(0.74 0.115 26); --down-wash:oklch(0.30 0.06 27);
  --warn:oklch(0.79 0.12 82); --warn-wash:oklch(0.32 0.05 82);
  --shadow:0 1px 2px oklch(0 0 0/.30), 0 1px 3px oklch(0 0 0/.22);
}

*,*::before,*::after{box-sizing:border-box}
/* ⚠️ Toute règle de classe qui pose `display` bat le `[hidden]` de l'agent
   utilisateur : `#uadmin[hidden]` portait `.uitem{display:flex}` et le lien
   « Administration » restait affiché — et cliquable — pour un visiteur anonyme.
   Le défaut avait déjà été rustiné deux fois au cas par cas (`.umenu[hidden]`,
   `.panel[hidden]`) ; la garde vit ici une bonne fois. Le `!important` de
   l'impression garde le dessus, sa spécificité est plus forte. */
[hidden]{display:none!important}
/* ⚠️ **La gouttière de défilement est RÉSERVÉE.** Sans elle, une page assez
   courte pour tenir dans l'écran n'a pas d'ascenseur et une autre en a un : le
   contenu — barre de recherche comprise — se décale de dix pixels d'une page à
   la suivante. Le saut se voit surtout dans l'en-tête, qui est le seul élément
   que l'œil retrouve au même endroit d'une page à l'autre. */
html{-webkit-text-size-adjust:100%;scrollbar-gutter:stable}
body{margin:0;background:var(--bg);color:var(--ink);
 font-family:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
 font-size:14px;line-height:20px;letter-spacing:.16px;font-variant-numeric:tabular-nums;
 -webkit-font-smoothing:antialiased}
a{color:var(--brand-ink)}
:focus-visible{outline:2px solid var(--brand);outline-offset:2px;border-radius:4px}
.skip{position:absolute;left:-9999px;top:0;background:var(--surface);color:var(--ink);
 padding:10px 14px;border-radius:0 0 var(--r) 0;z-index:60}
.skip:focus{left:0}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
 clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ---------- header ---------- */
.top{position:sticky;top:0;z-index:30;background:color-mix(in oklab,var(--bg) 88%,transparent);
 -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-bottom:1px solid var(--line)}
.top-in{max-width:var(--page-w);margin:0 auto;padding:10px var(--page-pad);
 display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.brand{display:flex;align-items:center;gap:9px;color:var(--brand);text-decoration:none;flex:0 0 auto}
.brand-txt{display:flex;flex-direction:column;line-height:1.05}
.brand-txt b{font-size:19px;font-weight:640;letter-spacing:-.025em;color:var(--ink)}
.brand-txt i{font-style:normal;font-size:11px;color:var(--mut);letter-spacing:.02em}
.top-meta{margin-inline-start:auto;display:flex;align-items:center;gap:8px;flex-wrap:wrap;
 font-size:12.5px;color:var(--mut)}
.pill{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--line);
 background:var(--surface);border-radius:99px;padding:3px 10px;font-size:12.5px;color:var(--ink-2)}
.pill .dot{width:7px;height:7px;border-radius:50%;background:var(--up)}
.pill.stale{border-color:color-mix(in oklab,var(--warn) 45%,var(--line));
 background:var(--warn-wash);color:var(--ink)}
.pill.stale .dot{background:var(--warn)}
/* Horodatage du rafraîchissement : même gabarit que les autres pastilles, mais
   teinté marque — c'est l'information qu'on vient vérifier en premier. */
.pill.fresh{border-color:color-mix(in oklab,var(--brand) 32%,var(--line));
 color:var(--brand-ink);background:color-mix(in oklab,var(--brand) 6%,transparent);
 font-variant-numeric:tabular-nums}
.pill.fresh .i-clock{width:13px;height:13px;flex:0 0 auto;opacity:.85}
.brand+em{font-style:normal;font-size:12px;color:var(--mut);align-self:center}
.langs{display:flex;gap:2px;align-items:center}
.lang{font-size:12px;color:var(--mut);text-decoration:none;padding:3px 7px;border-radius:99px;
 border:1px solid transparent;white-space:nowrap}
.lang:hover{color:var(--ink);background:var(--surface-2)}
.lang.on{color:var(--brand-ink);border-color:var(--line);background:var(--surface)}

/* --- Avatar et menu du compte -------------------------------------------
   Repris de SURUS (pastille ronde, initiales) et de MRiguel (le menu qui
   porte langue, apparence et compte).

   ⚠️ LEÇON DE MRIGUEL, PAYÉE EN PRODUCTION : « il y en avait deux ». Les
   initiales de la barre haute ouvraient un menu, et le bas du rail répétait la
   même identité dans une autre surface — sans que rien ne dise laquelle savait
   quoi. Ici le sélecteur de langue et le bouton de thème ont QUITTÉ la barre
   pour entrer dans ce menu. Ils n'existent plus ailleurs. */

/* --- la modale du compte ------------------------------------------------
   Le compte, les alertes et le portefeuille s'ouvrent PAR-DESSUS la page :
   on ne perd pas le marché qu'on était en train de lire. */
/* ⚠️ HAUTEUR AJUSTÉE AU CONTENU, plafonnée — et non figée à 88 % de l'écran.
   Une confirmation de trois lignes s'affichait dans une boîte de 792 px : sept
   cents pixels de vide sous le texte, et le lecteur cherche ce qu'il a manqué.
   La hauteur réelle est posée au chargement par le script, qui seul connaît le
   contenu ; ce `min-height` n'est que le repli le temps de la mesure. */
/* ⚠️ **`inset:0` ÉTIRE une boîte de hauteur automatique.** Le dialogue est en
   `position:fixed` ; avec `top` ET `bottom` à 0, `height:auto` ne se calcule pas
   sur le contenu, elle remplit l'espace disponible puis bute sur `max-height`.
   La fenêtre faisait donc 88 % de l'écran quoi qu'elle contienne — y compris
   après être passée en `height:auto`, ce qui donnait l'illusion du correctif.
   Mesuré : 792 px pour 442 px de contenu. On ne borne QUE par le haut, et on
   centre par `transform` plutôt que par un `inset` symétrique. */
.modale{width:min(960px,calc(100vw - 32px));height:auto;
  max-width:none;max-height:min(88vh,900px);
  inset:auto;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;
  padding:0;border:1px solid var(--line);border-radius:16px;
  background:var(--surface);color:var(--ink);overflow:hidden}
.modale::backdrop{background:rgb(0 0 0/.5);backdrop-filter:blur(2px)}
.modale[open]{display:flex;flex-direction:column}
/* L'entrée, discrète : elle dit d'où vient la fenêtre. Coupée pour qui a
   demandé moins d'animation — la préférence est un réglage d'accessibilité,
   pas un goût. */
@media (prefers-reduced-motion:no-preference){
  .modale[open]{animation:modale-entre .16s ease-out}
  .modale[open]::backdrop{animation:modale-fond .16s ease-out}
}
@keyframes modale-entre{
  from{opacity:0;transform:translate(-50%,-50%) translateY(6px) scale(.99)}
  to{opacity:1;transform:translate(-50%,-50%)}}
@keyframes modale-fond{from{opacity:0}}
.modale-tete{display:flex;align-items:center;gap:6px;
  padding:8px 8px 8px 16px;border-bottom:1px solid var(--line);
  background:var(--surface-2)}
.modale-tete b{flex:1;min-width:0;font-weight:600;font-size:15px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.modale-plein{flex:0 0 auto;font-size:13px;color:var(--mut);
  text-decoration:none;padding:8px 10px;border-radius:8px}
.modale-plein:hover{color:var(--ink);background:var(--surface)}
/* ⚠️ 44 px : la croix est la seule sortie visible à la souris. Une cible de
   24 px se rate, et l'on croit la fenêtre bloquée. */
.modale-x{width:44px;height:44px;flex:0 0 auto;border:0;border-radius:8px;
  background:none;color:var(--mut);font-size:26px;line-height:1;cursor:pointer}
.modale-x:hover{background:var(--surface);color:var(--ink)}
/* ⚠️ Un anneau de focus VISIBLE. Les deux commandes de la barre n'en avaient
   aucun (`outline-style:none` mesuré) : au clavier, on ne savait pas laquelle
   on tenait — et la croix est la sortie. */
.modale-x:focus-visible,.modale-plein:focus-visible{
  outline:2px solid var(--brand);outline-offset:-2px;color:var(--ink)}
.modale iframe{flex:1 1 auto;width:100%;min-height:220px;border:0;display:block;
  background:var(--surface)}
/* Sur téléphone, la modale prend l'écran : une fenêtre de 90 % dans 375 px
   n'est pas une fenêtre, c'est une page avec des bords perdus. */
@media (max-width:640px){
  /* Plein écran : on revient à l'`inset`, et le centrage n'a plus d'objet. */
  .modale{width:100vw;height:100dvh;max-height:none;border:0;border-radius:0;
    inset:0;transform:none}
  .modale iframe{height:auto!important}
  /* Plein écran : « ouvrir en page » n'ouvrirait rien de plus. */
  .modale-plein{display:none}
}
/* La newsletter : POUSSÉE EN BAS de la colonne, icône et libellé dans la
   couleur de la marque.

   ⚠️ `margin-top:auto` la colle en bas — mais il faut que la liste soit une
   colonne flex ET qu'elle occupe la hauteur, sinon `auto` ne pousse rien et
   l'entrée reste simplement la dernière du flux.

   ⚠️ La couleur ne porte PAS l'information à elle seule : l'entrée garde son
   nom, son icône et sa place. Qui ne distingue pas les teintes lit la même
   navigation. */
/* ⚠️ La marge automatique est ICI, sur la PREMIÈRE entrée du bas — le
   portefeuille — et non sur la lettre. Portée par la lettre, elle laissait le
   portefeuille en haut, à la fin des rubriques de marché, à une colonne de
   distance de l'entrée qui lui ressemble le plus. */
.side-bas{margin-top:auto;padding-top:10px;
  border-top:1px solid var(--line-soft)}
/* ⚠️ `.side .side-fort>a` et non `.side-fort>a` : `.side a{color:var(--ink-2)}`
   a la MÊME spécificité (0,1,1) et il est déclaré plus bas — à égalité, c'est
   l'ordre qui tranche, et il gagnait. Le libellé restait gris pendant que
   l'icône, elle, prenait la couleur : mesuré au `getComputedStyle`, invisible
   à l'œil sur un mot de dix lettres. */
.side .side-fort>a{color:var(--brand);font-weight:600}
.side .side-fort>a svg{stroke:var(--brand)}
.side .side-fort>a:hover{background:var(--brand-wash);color:var(--brand-ink)}
.side .side-fort>a:hover svg{stroke:var(--brand-ink)}

.avat{display:grid;place-items:center;width:30px;height:30px;flex:0 0 auto;
  border-radius:99px;border:1px solid var(--line);background:var(--brand);
  color:var(--brand-on);font:700 11px/1 var(--sans);letter-spacing:.02em;
  cursor:pointer;user-select:none;padding:0}
.avat:hover{filter:brightness(1.08)}
.avat svg{width:17px;height:17px;stroke:currentColor;fill:none;stroke-width:1.9}
/* Non connecté, la pastille est neutre : afficher des initiales à un visiteur
   anonyme lui ferait croire qu'il est quelqu'un. */
.avat[data-anon=1]{background:var(--surface-2);color:var(--mut)}

.umenu{position:fixed;z-index:60;width:288px;max-width:calc(100vw - 16px);
  background:var(--surface);border:1px solid var(--line);border-radius:14px;
  box-shadow:0 18px 44px -12px rgb(0 0 0/.28),0 2px 8px rgb(0 0 0/.06);
  overflow:hidden}
.umenu[hidden]{display:none}
.umenu .ugrp{padding:12px 14px;border-bottom:1px solid var(--line)}
.umenu .ugrp:last-child{border-bottom:0}
.umenu .utitre{font:600 11px/1 var(--sans);letter-spacing:.07em;
  text-transform:uppercase;color:var(--mut);margin:0 0 10px}
.umenu .urow{display:flex;align-items:center;justify-content:space-between;
  gap:10px;margin-bottom:9px}
.umenu .urow:last-child{margin-bottom:0}
.umenu .ulab{font-size:13px;color:var(--mut)}
.umenu .useg{display:flex;gap:3px}
.umenu .useg>*{font:600 12px/1 var(--sans);padding:6px 9px;border-radius:8px;
  border:1px solid transparent;background:none;color:var(--mut);cursor:pointer;
  text-decoration:none}
.umenu .useg>*:hover{background:var(--surface-2);color:var(--ink)}
.umenu .useg>[aria-checked=true]{background:var(--surface-2);color:var(--ink);
  border-color:var(--line)}
.umenu .uident{padding:12px 14px;border-bottom:1px solid var(--line)}
.umenu .uident b{display:block;font-size:13.5px;color:var(--ink)}
.umenu .uident span{display:block;font-size:12px;color:var(--mut);
  overflow:hidden;text-overflow:ellipsis}
/* ---------- Boutons d'abonnement (flux, agenda) ----------
   Dans l'en-tête de section, à droite du titre — là où l'œil arrive après avoir
   lu de quoi parle la section, et non avant. */
.abo{display:inline-flex;align-items:center;gap:7px;flex:0 0 auto;
 font-size:13px;font-weight:600;text-decoration:none;color:var(--brand);
 border:1px solid var(--line);border-radius:8px;padding:7px 11px;
 min-height:32px;transition:border-color .14s var(--ease)}
.abo:hover{border-color:var(--brand);background:var(--surface-2)}
.abo svg{width:16px;height:16px;flex:0 0 auto}
/* ⚠️ Le libellé reste AFFICHÉ sur téléphone. Le réflexe est de le masquer pour
   gagner de la place ; ce site a déjà payé cette économie — un visiteur réel a
   traversé toute sa session en croyant que mizen.cloud n'avait qu'une page,
   parce que sa navigation tenait dans un pictogramme muet. Deux mots coûtent
   moins qu'un abonnement que personne ne trouve. */

/* ---------- Sommaire du guide ----------
   Une carte par article, et la carte ENTIÈRE est le lien : sur téléphone, la
   cible d'un doigt c'est la carte, pas les trois mots du titre. */
.g-liste{display:grid;gap:12px;grid-template-columns:1fr}
@media (min-width:720px){.g-liste{grid-template-columns:1fr 1fr}}
.g-art{display:flex;flex-direction:column;gap:6px;text-decoration:none;
 color:inherit;transition:border-color .14s var(--ease),transform .14s var(--ease)}
.g-art:hover{border-color:var(--brand)}
.g-art b{font-size:16px;line-height:1.3}
.g-art .g-go{font-size:13px;color:var(--brand);font-weight:600;margin-top:2px}

/* ⚠️ **Plancher de lisibilité sur téléphone.** 84 textes secondaires tombaient à
   11,5 px à 390 px de large — mesuré le 03/09/2026. Sous 12 px, un texte gris
   sur fond clair n'est plus lu, il est deviné. La règle ne touche QUE le petit
   écran : sur un grand, la hiérarchie de tailles fait son travail. */
@media (max-width:640px){
 .sub,.nm,.pill,.d,.k,.legende,.foot,footer,figcaption{font-size:12px}
}

/* ---------- Simulateur de fiscalité ----------
   Deux colonnes sur écran large — l'intitulé puis le champ — et une seule sur
   téléphone : un formulaire à deux colonnes de 160 px y devient illisible. */
.tx-grid{display:grid;grid-template-columns:1fr;gap:8px 14px;align-items:center}
.tx-grid label{font-size:13px;color:var(--ink-2)}
.tx-grid input,.tx-grid select{font:inherit;font-size:14px;padding:7px 10px;
 border:1px solid var(--line);border-radius:8px;background:var(--surface);
 color:var(--ink);width:100%;min-width:0}
.tx-grid input[type=checkbox]{width:18px;height:18px;accent-color:var(--brand)}
.tx-grid input:focus-visible,.tx-grid select:focus-visible{border-color:var(--brand)}
@media (min-width:560px){.tx-grid{grid-template-columns:minmax(0,1fr) minmax(0,180px)}}
.tx-out{margin-top:14px}
/* Une saisie impossible : les résultats se retirent au lieu de mentir. Le tiret
   suffit à le dire ; la couleur seule ne le dirait pas à qui ne la voit pas. */
.tx-out .flou{color:var(--mut)}
/* La ligne « rien trouvé » d'un tableau filtré. Elle vit DANS le tableau : elle
   suit donc son défilement horizontal et la largeur de ses colonnes. */
tr.rien td{padding:22px 14px;text-align:center;color:var(--mut);font-size:14px}
tr.rien .rien-x{margin-inline-start:10px;font:inherit;font-size:13px;cursor:pointer;
 padding:4px 10px;border:1px solid var(--line);border-radius:8px;
 background:var(--surface);color:var(--brand)}
tr.rien .rien-x:hover{border-color:var(--brand)}
tr.rien .rien-x:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.tx-grid input[aria-invalid=true]{border-color:var(--down)}
/* La ligne qui porte la réponse se distingue de celles qui y mènent. */
.tx-out .tx-net td{border-top:2px solid var(--line);font-size:15px;
 padding-top:10px;color:var(--ink)}

/* ---------- Recherche d'en-tête ----------
   Elle passe AVANT les pastilles de date dans la rangée : sur téléphone la
   rangée se replie, et c'est le champ qu'on veut sur la première ligne — pas
   l'horodatage. `min-width:0` sans quoi un `input` refuse de rétrécir sous sa
   taille intrinsèque et pousse l'avatar hors du cadre. */
.rech{flex:1 1 150px;min-width:0;max-width:230px}
.rech input{font:inherit;font-size:13px;width:100%;min-width:0;
 padding:6px 10px;border:1px solid var(--line);border-radius:8px;
 background:var(--surface);color:var(--ink)}
.rech input::placeholder{color:var(--mut)}
.rech input:focus-visible{border-color:var(--brand)}
/* ---------- La liste de la recherche ----------
   ⚠️ Le `<datalist>` reste dans le document : sans JavaScript, c'est LUI qui
   déroule la liste, et la recherche continue de marcher. Ce panneau le remplace
   quand le script tourne — un `<datalist>` ne se met pas en forme, aucun
   navigateur ne l'expose au CSS, et sa liste ne montrait que « CODE — Nom » en
   une seule ligne grise.
   ⚠️ Il se construit À PARTIR des `<option>` déjà là : pas un octet de plus dans
   la page. C'est la même contrainte qui avait fait retirer `data-k` et `data-h`
   des options, mesurés à +2,47 ko comprimés PAR PAGE. */
.rech{position:relative}
/* ⚠️ `fixed` : la liste sert AUSSI des champs de formulaire, qui n'ont pas
   d'ancre positionnee autour d'eux. Position et largeur sont posees par le
   script, sur le rectangle reel du champ. */
.rech-l{position:fixed;z-index:61;left:0;top:0;
 max-height:min(56vh,392px);overflow-y:auto;overscroll-behavior:contain;
 margin:0;padding:4px;list-style:none;
 background:var(--surface);border:1px solid var(--line);
 border-radius:var(--r);box-shadow:var(--shadow),0 12px 32px oklch(0.24 0.018 220/.16)}
.rech-l[hidden]{display:none}
/* Une ligne = une pastille de code et un nom. La pastille est celle du reste du
   site : le lecteur a déjà appris que c'est ainsi qu'on écrit un mnémonique. */
.rech-o{display:flex;align-items:center;gap:10px;padding:7px 8px;
 border-radius:var(--r-sm);cursor:pointer;color:var(--ink);scroll-margin:4px}
.rech-o .cd{flex:0 0 auto;min-width:58px;text-align:center;
 padding:2px 7px;border-radius:var(--r-fld);font-size:11.5px;font-weight:600;
 background:var(--brand-wash);color:var(--brand-ink)}
.rech-o .nm2{flex:1 1 auto;min-width:0;font-size:12.5px;line-height:1.35;
 color:var(--mut);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* ⚠️ La ligne visée se marque au FOND, pas à la couleur du texte : la liste
   défile au clavier, et un simple changement de teinte se perd sur une ligne
   déjà grise. */
.rech-o[aria-selected=true]{background:var(--accent)}
.rech-o[aria-selected=true] .nm2{color:var(--ink)}
@media (hover:hover){.rech-o:hover{background:var(--accent)}}
/* Ce qui a été tapé, souligné dans le résultat — c'est ce qui explique pourquoi
   la ligne est là. Jamais un surlignage jaune : la couleur est déjà prise. */
.rech-o mark{background:none;color:var(--brand-ink);font-weight:700;
 text-decoration:underline;text-underline-offset:2px}
.rech-o .cd mark{color:inherit;text-decoration:none}
.rech-v{padding:14px 10px;text-align:center;font-size:12.5px;color:var(--mut)}
/* Le compte, quand la liste est longue : il dit qu'on peut continuer à taper. */
.rech-n{padding:6px 9px 4px;font-size:11px;letter-spacing:.04em;
 text-transform:uppercase;color:var(--mut)}
/* ⚠️ **La largeur ne suffit pas : le panneau est ancré au CHAMP, pas à l'écran.**
   `width:min(360px, 100vw - 20px)` le dimensionnait bien par rapport à l'écran,
   mais il commence au bord du champ — à 52 px du bord sur un téléphone. Il
   finissait donc à 412 px sur un écran de 390, et la page se mettait à défiler
   latéralement : exactement ce que le site s'interdit partout ailleurs. Sous
   720 px, le panneau prend la largeur du champ et ne peut plus dépasser. */

@media (prefers-reduced-motion:no-preference){
 .rech-l{animation:rech-in .12s var(--ease)}
 @keyframes rech-in{from{opacity:0;transform:translateY(-4px)}}
}
/* ⚠️ Sur téléphone le champ PARTAGE la ligne de l'avatar — il ne prend pas la
   sienne. `flex-basis:100%` la lui donnait : l'en-tête passait de 114 à 154 px,
   soit 40 px de chrome COLLANT confisqués sur chaque page. C'est exactement ce
   que la rangée de sections a fui en sortant de `.top`. Mesuré : 118 px avec
   une base de 140 px, et un champ qui fait tout de même 275 px de large à
   390 px d'écran. `order:-1` le pose en tête de rangée — c'est lui qu'on veut
   voir en premier, pas l'horodatage. */
@media (max-width:520px){.rech{flex-basis:140px;max-width:none;order:-1}}

.umenu .uitem{display:flex;align-items:center;gap:10px;width:100%;
  padding:10px 14px;font:400 13px/1.3 var(--sans);color:var(--ink);
  background:none;border:0;text-align:start;text-decoration:none;cursor:pointer}
.umenu .uitem:hover{background:var(--surface-2)}
.umenu .uitem svg{width:16px;height:16px;flex:0 0 auto;stroke:var(--mut);
  fill:none;stroke-width:1.8}
.umenu .uitem.udanger{color:var(--down)}
.umenu .uitem.udanger svg{stroke:var(--down)}
/* Le focus se DÉPLACE à la flèche sans jamais passer par un clic : sans anneau
   visible on ne sait plus sur quelle entrée on est. */
.umenu :focus-visible,.avat:focus-visible{outline:2px solid var(--brand);
  outline-offset:-2px}

.iconbtn{border:1px solid var(--line);background:var(--surface);color:var(--ink-2);
 border-radius:99px;width:32px;height:32px;display:grid;place-items:center;cursor:pointer;
 transition:background .18s var(--ease),color .18s var(--ease)}
.iconbtn:hover{background:var(--surface-2);color:var(--ink)}
.iconbtn svg{width:16px;height:16px}
:root[data-theme=dark] .i-sun,.i-moon{display:none}
:root[data-theme=dark] .i-moon{display:block}
@media (prefers-color-scheme:dark){:root:not([data-theme=light]) .i-sun{display:none}
 :root:not([data-theme=light]) .i-moon{display:block}}

/* ---------- tabs ---------- */
.tabs{display:flex;gap:2px;overflow-x:auto;scrollbar-width:none;
 border-top:1px solid var(--line-soft);background:var(--bg)}
.tabs::-webkit-scrollbar{display:none}
.tabs-in{max-width:var(--page-w);margin:0 auto;padding:0 var(--page-pad);display:flex;gap:2px}
.tab{appearance:none;border:0;background:none;color:var(--mut);cursor:pointer;
 text-decoration:none;display:inline-block;
 padding:11px 14px;font:inherit;font-size:14px;font-weight:520;white-space:nowrap;
 border-bottom:2px solid transparent;transition:color .18s var(--ease),border-color .18s var(--ease)}
.tab:hover{color:var(--ink)}
.tab[aria-current]{color:var(--brand-ink);border-bottom-color:var(--brand)}
/* Césure entre le volet marché et le volet change : un trait, pas un titre —
   la barre reste une seule ligne scrollable sur mobile. */
.tabsep{flex:0 0 auto;align-self:center;width:1px;height:16px;
 margin-inline:10px 8px;background:var(--line)}

/* ---------- panneau de navigation ----------
   Header + panneau gauche (motif Carbon) : le header porte les liens SYSTÈME
   (langue, thème, fraîcheur) à droite, le panneau porte les liens PRODUIT à
   gauche. Ce que la barre d'onglets ne pouvait pas faire : nommer ses groupes.

   Le panneau se replie, parce qu'il prend 256 px sur un écran de sélection à
   seize colonnes. Un seul mécanisme à toutes les largeurs — le même bouton
   ouvre et ferme ; au-dessus de 1056 px il pousse le contenu, en dessous il
   recouvre. L'état est mémorisé. */
:root{--nav-w:256px;--rail-w:48px;--top-h:48px;
 /* Largeur du contenu, lue par l'en-tête, les onglets, le contenu et le pied :
    quatre valeurs séparées finissaient toujours par se désaligner d'un pixel. */
 --page-w:1180px;--page-pad:clamp(12px,2.5vw,24px)}
/* Le bouton commande la barre latérale : il se tient AU-DESSUS d'elle, dans sa
   propre colonne, et n'en bouge plus. Posé dans le flux de l'en-tête, il suivait
   le bloc centré à `max-width:1180px` et flottait à 150 px de la barre qu'il
   replie. `position:fixed` le sort du rembourrage de `body` — c'est le seul
   moyen d'atteindre la colonne du rail, que ce rembourrage réserve justement. */
.navbtn{position:fixed;inset-block-start:0;inset-inline-start:0;z-index:31;
 width:var(--rail-w);height:var(--top-h);display:grid;place-items:center;
 border:0;background:none;color:var(--ink-2);cursor:pointer}
.navbtn:hover{background:var(--surface-2);color:var(--ink)}
.navbtn svg{width:21px;height:21px}
/* Au-dessus de 1056 px, le bouton se loge dans le rembourrage que `body` réserve
   déjà au rail. En dessous il n'y a plus de rembourrage : sans cette réserve,
   le bouton fixe recouvrirait le logo. */
@media (max-width:1055.98px){.top-in{padding-inline-start:calc(var(--rail-w) + 4px)}}
/* Le chevron pousse vers l'extérieur quand le panneau est ouvert, vers
   l'intérieur quand il est replié — et se retourne de lui-même en arabe. */
.navbtn .chev{transition:transform .18s var(--ease);transform-origin:15.5px 12px}
:root[data-nav=full] .navbtn .chev{transform:scaleX(-1)}
[dir=rtl] .navbtn .chev{transform:scaleX(-1)}
[dir=rtl]:root[data-nav=full] .navbtn .chev{transform:none}
@media (prefers-reduced-motion:reduce){.navbtn .chev{transition:none}}

.side{position:fixed;inset-block:var(--top-h) 0;inset-inline-start:0;z-index:25;
 width:var(--nav-w);background:var(--surface);border-inline-end:1px solid var(--line);
 overflow-y:auto;overscroll-behavior:contain;padding:var(--s-nav,12px) 0;
 transition:transform .18s var(--ease)}
/* La liste est une COLONNE FLEX pleine hauteur : c'est ce qui permet à
   la newsletter d'être poussée en bas par `margin-top:auto`. */
.side ul{list-style:none;margin:0;padding:0;display:flex;
 flex-direction:column;min-height:100%}
.side a{display:flex;align-items:center;gap:12px;padding:10px 16px;font-size:14px;
 letter-spacing:.16px;color:var(--ink-2);text-decoration:none;
 border-inline-start:3px solid transparent;white-space:nowrap}
.side a svg{width:20px;height:20px;flex:0 0 auto}
.side a:hover{background:var(--surface-2);color:var(--ink)}
.side a[aria-current]{background:var(--brand-wash);color:var(--brand-ink);
 font-weight:600;border-inline-start-color:var(--brand)}
.side-grp{padding:14px 16px 4px;font-size:11.5px;font-weight:600;letter-spacing:.06em;
 text-transform:uppercase;color:var(--mut)}
.side-grp:first-child{padding-top:4px}

/* ---------- rail : la navigation en 48 px ----------
   Le libellé sort de l'oeil mais reste dans le DOM — c'est le nom accessible du
   lien. L'infobulle le reprend telle quelle, au survol ET au focus clavier :
   une navigation en icônes qu'on ne peut lire qu'à la souris n'est pas navigable. */
/* overflow visible en rail : un conteneur qui defile decoupe l'infobulle, et
   elle est posee HORS du panneau de 48 px. Les neuf entrees tiennent sans
   defilement — c'est ce qui rend le compromis acceptable. */
:root[data-nav=rail] .side{width:var(--rail-w);overflow:visible}
:root[data-nav=rail] .side a{justify-content:center;padding:10px 0;gap:0;
 border-inline-start-width:2px}
:root[data-nav=rail] .side-l{position:absolute;width:1px;height:1px;padding:0;
 margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
/* La ligne de groupe devient un filet : à 48 px un intitulé ne tient pas, mais la
   coupure entre le volet marché et le volet change doit rester lisible. */
:root[data-nav=rail] .side-grp{height:0;padding:0;margin:8px 12px;overflow:hidden;
 border-top:1px solid var(--line)}
:root[data-nav=rail] .side-grp:first-child{margin-top:0;border-top:0}
/* Infobulle : posée par le conteneur, jamais par title= — un title met une seconde
   à paraître et ne se déclenche pas au clavier. */
:root[data-nav=rail] .side a{position:relative}
:root[data-nav=rail] .side a::after{content:attr(data-lbl);position:absolute;
 inset-inline-start:calc(100% + 8px);top:50%;transform:translateY(-50%);
 background:var(--ink);color:var(--bg);font-size:12.5px;letter-spacing:.16px;
 padding:5px 10px;border-radius:var(--r-fld);white-space:nowrap;pointer-events:none;
 opacity:0;visibility:hidden;transition:opacity .1s var(--ease);z-index:40}
:root[data-nav=rail] .side a:hover::after,
:root[data-nav=rail] .side a:focus-visible::after{opacity:1;visibility:visible}
@media (prefers-reduced-motion:reduce){:root[data-nav=rail] .side a::after{transition:none}}
.side-veil{position:fixed;inset:var(--top-h) 0 0;z-index:24;
 background:oklch(0.24 0.018 220/.45)}

/* ⚠️ Une carte est presque toujours l'enfant d'une grille ou d'un flex, et un
   enfant de grille garde par défaut la largeur de son CONTENU : un tableau de
   616 px imposait sa largeur à la piste, donc à la page. Résultat mesuré à
   390 px : `change.html` débordait de 238 px et `banques.html` de 102 px — la
   page entière glissait latéralement, et le `.scroll` intérieur, jamais
   contraint, ne servait à rien. Même piège que `.cmp-pick>*`, ailleurs. */
.card{min-width:0}

/* ---------- rangée de sections : la navigation qu'on n'a pas à chercher ----
   Sous 1056 px le tiroir part fermé et RIEN à l'écran ne disait qu'il existait
   d'autres vues : un visiteur a cru que le site tenait en une page. Au-dessus
   de 1056 px le rail nomme déjà les sections en permanence — la rangée y est
   inutile et disparaît. */
.navrow{display:none}
@media (max-width:1055.98px){
 .navrow{display:block;background:var(--bg);border-bottom:1px solid var(--line);
  overflow-x:auto;overscroll-behavior-x:contain;scrollbar-width:none}
 .navrow::-webkit-scrollbar{display:none}
 .navrow ul{display:flex;gap:2px;list-style:none;margin:0;
  padding:4px var(--page-pad) 5px}
 .navrow a{display:block;white-space:nowrap;text-decoration:none;
  padding:10px 12px;border-radius:var(--r-fld);font-size:13px;letter-spacing:.16px;
  color:var(--ink-2);border:1px solid transparent}
 .navrow a:hover{background:var(--surface-2);color:var(--ink)}
 /* La page courante se nomme : sans elle la rangée aurait l'air de ne pas
    concerner la page qu'on lit. Teintes de marque — jamais --up/--down, qui
    disent la hausse et la baisse, pas la navigation. */
 .navrow a[aria-current]{background:var(--brand-wash);color:var(--brand-ink);
  border-color:var(--brand);font-weight:600}
}

/* Replié : le panneau sort du flux, le contenu récupère toute la largeur. */
:root[data-nav=off] .side{transform:translateX(calc(-1 * var(--nav-w)))}
:root[dir=rtl][data-nav=off] .side{transform:translateX(var(--nav-w))}
@media (max-width:1055.98px){:root[data-nav=rail] .side{width:var(--nav-w)}}
@media (min-width:1056px){.side-veil{display:none}}
/* Sous 1056 px le panneau recouvre : il part replié et le voile le ferme. */
@media (max-width:1055.98px){
  .side{transform:translateX(calc(-1 * var(--nav-w)));box-shadow:var(--shadow)}
  :root[dir=rtl] .side{transform:translateX(var(--nav-w))}
  /* `full` et non `on` : le JS n'a jamais écrit `on`, il pose off/rail/full.
     La feuille attendait un état que rien ne produisait — le tiroir restait
     donc à -256 px, invisible, et le voile masqué : le menu ne s'ouvrait pas
     du tout sous 1056 px. */
  :root[data-nav=full] .side{transform:none}
  :root:not([data-nav=full]) .side-veil{display:none}
}
@media (prefers-reduced-motion:reduce){.side{transition:none}}

/* ---------- breadcrumb ---------- */
.crumb{display:flex;gap:8px;align-items:center;font-size:12.5px;color:var(--mut);
 margin:0 0 16px}
.crumb a{color:var(--mut);text-decoration:none}
.crumb a:hover{color:var(--brand-ink);text-decoration:underline}

/* ---------- shell ---------- */
/* ⚠ `main.wrap`, jamais `.wrap` seul : le nom sert AUSSI de modificateur de
   cellule (`td.wrap`, plus bas). Non borné, le gabarit de page posait ses
   30/72 px de marge dans chaque cellule qui portait la classe — invisible dans
   un tableau `.dense`, qui redéclare le padding, et une rangée de 121 px de
   haut partout ailleurs. Un nom, deux emplois : on borne celui qui a un
   élément propre. */
/* --- Flottant : la part qui s'échange, face au reste du capital -------- */
.cap-bar{display:flex;height:14px;border-radius:7px;overflow:hidden;
  background:var(--accent)}
.cap-bar span{display:block;background:var(--brand);height:100%}
.cap-leg{display:flex;gap:18px;flex-wrap:wrap;margin-top:10px;
  font-size:.8125rem;color:var(--mut)}
.cap-leg i{display:inline-block;width:10px;height:10px;border-radius:3px;
  background:var(--brand);margin-inline-end:6px;vertical-align:-1px}
.cap-leg i.off{background:var(--accent)}

/* Marque discrète accolée à un mnémonique — « suspendue » dans la cote. */
.tag{display:inline-block;font-size:.6875rem;font-weight:600;line-height:1;
  padding:3px 6px;border-radius:4px;margin-left:6px;vertical-align:1px;
  background:var(--accent);color:var(--mut);white-space:nowrap}
.tag.warn{background:var(--warn-wash);color:var(--warn)}

/* --- Formulaires de la lettre — les deux seuls du site ------------------- */
.nl-form{display:flex;flex-direction:column;gap:8px;max-width:26rem}
.nl-lab{font-size:.8125rem;color:var(--mut)}
.nl-in{font:inherit;color:var(--ink);background:var(--surface);
  border:1px solid var(--line);border-radius:var(--r-fld);padding:11px 12px;
  width:100%}
.nl-in:focus-visible{outline:2px solid var(--brand);outline-offset:1px;
  border-color:var(--brand)}
.nl-btn{align-self:flex-start;font-weight:600;font-size:.9375rem;line-height:1;color:#fff;
  background:var(--brand);border:0;border-radius:var(--r-sm);padding:13px 22px;
  cursor:pointer;transition:background .15s var(--ease)}
.nl-btn:hover{background:var(--brand-ink)}
.nl-btn-off{background:var(--mut)}
.nl-btn-off:hover{background:var(--ink)}
/* Piege a robots. `position:absolute` + `left:-9999px` plutot que
   `display:none` : plusieurs automates ignorent les champs non affiches, mais
   remplissent ceux qui sont simplement hors cadre. */
.nl-pot{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
main.wrap{max-width:var(--page-w);margin:0 auto;
 padding:clamp(18px,3vw,30px) var(--page-pad) 72px}
.panel[hidden]{display:none}
section{margin:0 0 clamp(24px,3.4vw,40px)}
h2{font-size:20px;line-height:28px;font-weight:400;letter-spacing:0;
 margin:0 0 4px;color:var(--ink)}
h3{font-size:14px;line-height:18px;font-weight:600;letter-spacing:.16px;
 margin:0 0 8px;color:var(--ink)}
.sub{font-size:14px;line-height:20px;letter-spacing:.16px;color:var(--ink-2);
 margin:0 0 16px}
.head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;
 flex-wrap:wrap;margin-bottom:12px}
.head .sub{margin:0}

/* ---------- hero ---------- */
.hero{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
 box-shadow:var(--shadow);overflow:hidden}
.hero-top{display:flex;flex-wrap:wrap;gap:clamp(16px,3vw,40px);
 padding:var(--pad) var(--pad) 6px;align-items:flex-end}
.hero-main{flex:1 1 240px;min-width:0}
.hero-k{font-size:12px;color:var(--mut);letter-spacing:.02em}
.hero-v{font-size:clamp(30px,5.2vw,42px);font-weight:660;letter-spacing:-.03em;
 line-height:1.05;margin:2px 0 4px}
.hero-d{font-size:14px;font-weight:560;white-space:nowrap}
.hero-side{display:flex;gap:clamp(16px,3vw,32px);flex-wrap:wrap;padding-bottom:4px}
.stat .k{font-size:11.5px;color:var(--mut)}
.stat .v{font-size:17px;font-weight:600;letter-spacing:-.02em}
.stat .d{font-size:12.5px}
.chart{display:block;width:100%;height:auto}
.chart .ln{fill:none;stroke:var(--brand);stroke-width:1.6;vector-effect:non-scaling-stroke}
/* le dégradé porte un identifiant par graphique : la règle ne fixe que le trait,
   sinon elle écraserait l'attribut fill et tous les graphiques partageraient un id */
.chart .ar{stroke:none}
.chart .gr{stroke:var(--line-soft);stroke-width:1;vector-effect:non-scaling-stroke}
.chart .pt{fill:var(--brand)}
.chart-x{display:flex;justify-content:space-between;padding:0 var(--pad) 12px;
 font-size:11.5px;color:var(--mut)}

/* ---------- carte de la cote : l'aire dit le poids, la couleur la séance ----
   Pavés positionnés en pourcentages : la carte se redimensionne sans qu'aucun
   calcul ne soit refait au chargement. `aspect-ratio` lui garde une forme
   lisible, et le rapport s'aplatit sur mobile où la largeur commande. */
/* Plus large que haute : la carte ne doit pas pousser le reste de la page sous
   la ligne de flottaison. Les tuiles y perdent en hauteur, d'où une étiquette
   plus grande pour compenser — mieux vaut vingt noms lisibles que cinquante
   qu'on devine. */
.hm{position:relative;width:100%;aspect-ratio:64/21;border-radius:var(--r-sm);
 overflow:hidden;background:var(--line)}
@media (max-width:1055.98px){.hm{aspect-ratio:16/9}}
@media (max-width:720px){.hm{aspect-ratio:3/4}}
.hm-t{position:absolute;display:flex;flex-direction:column;align-items:center;
 justify-content:center;gap:1px;overflow:hidden;text-decoration:none;
 color:var(--ink);outline:1px solid var(--bg);outline-offset:-1px;
 font-size:13.5px;line-height:1.15;padding:1px}
.hm-t b{font-weight:640;letter-spacing:-.01em;max-width:100%;overflow:hidden;
 text-overflow:ellipsis;white-space:nowrap}
.hm-t i{font-style:normal;font-size:12px;color:var(--ink-2)}
/* La tuile se mesure elle-même : une étiquette tronquée en « SOT… » vaut moins
   que pas d'étiquette du tout, et le seuil ne peut pas se calculer au rendu —
   la carte est en 16/9 sur écran large et en 4/5 sur téléphone. */
/* Carte des secteurs : une douzaine de pavés au lieu de soixante-dix-sept, donc
   plus plate et le nom en toutes lettres — un libellé de secteur ne s'abrège
   pas comme un mnémonique. */
.hm-ix{aspect-ratio:64/13}
@media (max-width:1055.98px){.hm-ix{aspect-ratio:16/7}}
@media (max-width:720px){.hm-ix{aspect-ratio:3/4}}
.hm-ix .hm-t{font-size:13px;padding:2px 4px}
.hm-ix .hm-t b{white-space:normal;text-align:center;line-height:1.15;
 display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}

.hm-t{container-type:size}
@container (max-height:36px){.hm-t i{display:none}}
@container (max-width:60px){.hm-t i{display:none}}
@container (max-height:20px){.hm-t b{display:none}}
@container (max-width:40px){.hm-t b{display:none}}
.hm-t:hover,.hm-t:focus-visible{outline:2px solid var(--brand);outline-offset:-2px;
 z-index:2}
/* Pas d'échange : hachures. Le gris seul disait « stable » pour une valeur dont
   on ne sait rien de la séance. */
.hm-x{background-image:repeating-linear-gradient(45deg,transparent 0 4px,
 color-mix(in oklab,var(--mut) 22%,transparent) 4px 5px)}
.hm-x b,.hm-x i{color:var(--mut)}
.hm-leg{display:flex;align-items:center;justify-content:center;gap:2px;
 margin-top:10px;font-size:11.5px;color:var(--mut)}
.hm-leg span{display:inline-flex;align-items:center;gap:5px}
.hm-leg i{width:26px;height:11px;border-radius:2px;display:inline-block}

/* ---------- graphiques interactifs : survol daté, bornes, export ---------- */
.ichart{position:relative}
.ichart .cxl{stroke:var(--brand);stroke-width:1;stroke-dasharray:3 3;
 vector-effect:non-scaling-stroke;opacity:.55}
.ichart .cxd{fill:var(--surface);stroke:var(--brand);stroke-width:2;
 vector-effect:non-scaling-stroke}
.ichart .cx{transition:opacity .12s ease-out;pointer-events:none}
.ichart .chart{touch-action:pan-y}
/* Détachements de dividende : le repère doit se lire sans jamais concurrencer
   la courbe — trait ténu, fanion à l'axe, et le titre natif porte le montant. */
.dvm line{stroke:var(--mut);stroke-width:1;stroke-dasharray:2 4;opacity:.45;
 vector-effect:non-scaling-stroke}
.dvm path{fill:var(--mut);opacity:.75}
.dvm:hover line,.dvm:focus line{opacity:.9;stroke:var(--brand)}
.dvm:hover path,.dvm:focus path{fill:var(--brand);opacity:1}
/* Quatre familles, quatre FORMES — la couleur reste neutre. Un repère de
   navigation dans l'histoire d'un cours n'est ni une hausse ni une baisse :
   `--up` et `--down` ne s'y appliquent pas. La croix de « cotation » est un
   trait, pas une surface : elle se peint en `stroke`. */
.dvm.evt-cot path{fill:none;stroke:var(--mut);stroke-width:1.6;opacity:.8}
.dvm.evt-cot:hover path,.dvm.evt-cot:focus path{stroke:var(--brand);opacity:1}
.dvm.evt-ag path{opacity:.6}
/* Légende des repères, sous le graphique. */
.evt-leg{display:flex;flex-wrap:wrap;gap:10px;margin-top:6px;font-size:11.5px;
 color:var(--mut);align-items:center}
.evt-leg i{display:inline-block;width:9px;height:9px;margin-inline-end:4px;
 background:var(--mut);opacity:.75;vertical-align:-1px}
.evt-leg .k-div i{clip-path:polygon(50% 0,100% 100%,0 100%)}
.evt-leg .k-cap i{clip-path:polygon(50% 0,100% 50%,50% 100%,0 50%)}
/* ⚠️ Sur UNE ligne : une barre oblique en fin de ligne n'est pas une
   continuation en CSS, elle démarre une séquence d'échappement. */
.evt-leg .k-cot i{clip-path:polygon(0 18%,18% 0,50% 32%,82% 0,100% 18%,68% 50%,100% 82%,82% 100%,50% 68%,18% 100%,0 82%,32% 50%)}
.tip{position:absolute;top:8px;z-index:2;pointer-events:none;
 background:var(--surface);border:1px solid var(--line);border-radius:var(--r-sm);
 box-shadow:var(--shadow);padding:6px 10px;font-size:12.5px;line-height:1.45;
 white-space:nowrap;transform:translateX(-50%)}
.tip b{font-size:14px;letter-spacing:-.01em}
.tip .tip-d{color:var(--mut);font-size:11.5px}
.crange{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
 padding:0 var(--pad) 12px;font-size:12.5px;color:var(--mut)}
.crange label{display:inline-flex;align-items:center;gap:6px}
.crange input[type=date]{font:inherit;color:var(--ink);background:var(--surface);
 border:1px solid var(--line);border-radius:var(--r-fld);padding:4px 8px;
 min-height:32px;color-scheme:light dark}
.crange button{font:inherit;color:var(--ink);background:var(--surface);cursor:pointer;
 border:1px solid var(--line);border-radius:var(--r-fld);padding:5px 12px;min-height:32px}
.crange button:hover{border-color:var(--brand);color:var(--brand)}
.crange .cr-x{font-weight:600}
.crange .cr-n{margin-inline-start:auto;font-variant-numeric:tabular-nums}
.crange .cr-n[data-empty]{color:var(--down)}
@media (max-width:720px){
 .crange{font-size:12px;gap:6px}
 .crange .cr-n{margin-inline-start:0;flex-basis:100%}
}
@media (prefers-reduced-motion:reduce){.ichart .cx{transition:none}}

/* ---------- surfaces ---------- */
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
 box-shadow:var(--shadow)}
.card-pad{padding:var(--pad)}
/* ⚠️ `min(…,100%)` et non un plancher fixe. `minmax(480px,1fr)` interdit à la
   piste de descendre sous 480 px : `auto-fit` ne replie pas, il DÉBORDE. Sur
   `banques.html` à 390 px, la page glissait de 102 px sur le côté — et le
   coupable n'est pas la carte (dont le `min-width` est bien à 0) mais la piste
   qui l'héberge. Le `min()` ramène le plancher à la largeur disponible dès que
   l'écran est plus étroit que lui. */
.split{display:grid;gap:14px;
 grid-template-columns:repeat(auto-fit,minmax(min(310px,100%),1fr))}
.split.wide{grid-template-columns:repeat(auto-fit,minmax(min(480px,100%),1fr))}
.scroll{overflow-x:auto;-webkit-overflow-scrolling:touch}
/* En-tête collant : `overflow-x:auto` fait calculer `overflow-y:auto`, donc
   .scroll DEVIENT le port de défilement du th{position:sticky;top:0}. Sans
   hauteur, ce port ne défile jamais et l'en-tête ne colle à rien : mesuré sur
   cotes.html, le <th> était à −647 px après 900 px de défilement de page.
   .scroll-y borne la hauteur, ce qui rend le port réel et l'en-tête effectif.
   Réservé aux tableaux longs — ailleurs, un défilement imbriqué serait pire
   que le mal. */
.scroll-y{max-block-size:calc(100dvh - 15rem);min-block-size:22rem;overflow-y:auto}
@supports not (height:100dvh){.scroll-y{max-block-size:calc(100vh - 15rem)}}

/* ---------- barres de défilement ----------
   La barre native de Windows est épaisse et grise : dans une liste de valeurs
   haute de dix lignes, elle pèse plus que son contenu. On la ramène à un trait
   qui suit les couleurs du thème, sans la faire disparaître — une barre
   invisible ne dit plus qu'il y a quelque chose à faire défiler.
   Les deux syntaxes coexistent : la standard (Firefox, Chrome ≥ 121) et celle
   de WebKit, encore seule sur Safari.

   ⚠️ **La liste de la recherche n'y était pas.** Cette règle énumérait ses
   surfaces à la main — `.scroll` et `.cmp-sugg` — et le panneau de recherche,
   ajouté après, gardait la barre grise du système au milieu d'un panneau qui
   suit le thème. Une énumération tenue à la main ne prévient jamais qu'il lui
   manque quelqu'un : c'est le lecteur qui l'a vu.

   ⚠️ `:is()` plutôt que six listes recopiées. La version d'avant répétait ses
   sélecteurs dans chacune des six règles : ajouter une surface demandait six
   modifications, et il suffisait d'en oublier une pour qu'un curseur garde la
   couleur du système au survol. Une seule liste, ici. */
:is(.scroll,.scroll-y,.cmp-sugg,.rech-l,.side){
 scrollbar-width:thin;scrollbar-color:var(--line) transparent}
:is(.scroll,.scroll-y,.cmp-sugg,.rech-l,.side)::-webkit-scrollbar{width:10px;height:10px}
:is(.scroll,.scroll-y,.cmp-sugg,.rech-l,.side)::-webkit-scrollbar-track{background:transparent}
/* ⚠️ Le liseré prend la couleur de LA SURFACE, pas du fond de page : posé sur
   `--bg`, il dessinait un rail plus clair que le panneau sur lequel il flotte.
   Le curseur doit sembler posé sur ce qu'il fait défiler. */
:is(.scroll,.scroll-y,.cmp-sugg,.rech-l,.side)::-webkit-scrollbar-thumb{
 background:var(--line);border-radius:99px;border:3px solid var(--surface)}
:is(.scroll,.scroll-y,.cmp-sugg,.rech-l,.side):hover::-webkit-scrollbar-thumb{
 background:color-mix(in oklab,var(--mut) 55%,transparent)}
:is(.scroll,.scroll-y,.cmp-sugg,.rech-l,.side)::-webkit-scrollbar-thumb:hover{background:var(--mut)}
:is(.scroll,.scroll-y,.cmp-sugg,.rech-l,.side)::-webkit-scrollbar-corner{background:transparent}
/* Le panneau de la recherche a 4 px de marge intérieure et des coins arrondis :
   un liseré de 3 px y mangerait l'arrondi. */
.rech-l::-webkit-scrollbar{width:8px}
.rech-l::-webkit-scrollbar-thumb{border-width:2px}

/* ---------- stat row (no card grid) ---------- */
.statrow{display:flex;flex-wrap:wrap;gap:0;background:var(--surface);border:1px solid var(--line);
 border-radius:var(--r-lg);box-shadow:var(--shadow);overflow:hidden}
.statrow>div{flex:1 1 170px;padding:14px var(--pad);border-inline-end:1px solid var(--line-soft)}
.statrow>div:last-child{border-inline-end:0}
.statrow .k{font-size:11.5px;color:var(--mut)}
.statrow .v{font-size:clamp(19px,2.6vw,23px);font-weight:640;letter-spacing:-.025em;margin:1px 0}
.statrow .d{font-size:12.5px;color:var(--mut)}

/* ---------- tables ---------- */
table{width:100%;border-collapse:collapse;font-size:14px}
caption{text-align:start;font-size:12.5px;color:var(--mut);padding:0 0 8px}
/* Le filet bas est une ombre interne et non un border-bottom : sur un th
   collant, Chrome laisse la bordure au fil du tableau et elle disparaît dès que
   l'en-tête décolle. */
th{text-align:start;font-size:12px;line-height:16px;font-weight:600;color:var(--ink);
 letter-spacing:.32px;height:32px;padding:0 10px;
 box-shadow:inset 0 -1px 0 var(--line);
 white-space:nowrap;position:sticky;top:0;background:var(--accent);z-index:1}
th.s:hover{background:var(--accent-hover)}
td{height:32px;padding:6px 10px;line-height:20px;
 border-bottom:1px solid var(--line-soft);white-space:nowrap}
table.prose td{white-space:normal}
/* ⚠️ `.pile` dit « cette table porte des PHRASES » — pas seulement sur
   téléphone. Mesuré à 1440 px : le tableau des frais du guide débordait
   encore de 252 px de sa carte, parce que `td{white-space:nowrap}` refuse
   de replier une explication. Le repli mobile ne suffisait donc pas : le
   défaut vivait aux deux largeurs, et seule l'étroite se voyait. */
table.pile td{white-space:normal}
/* Un taux ne se coupe pas entre son nombre et son signe : « 0,26 » d'un
   côté, « % » de l'autre. */
table.pile td.num{white-space:nowrap}
/* Colonne de texte long (intitulé d'une publication) : elle se replie au lieu
   d'obliger à faire défiler le tableau — sur un téléphone c'est la seule
   colonne qu'on vient lire. */
td.wrap{white-space:normal;min-width:20ch;max-width:70ch;line-height:1.35}
/* Tableau de lecture, pas de chiffres : beaucoup de lignes courtes, donc moins
   d'air que dans les tableaux de cotes. */
/* Marque d'une date rectifiée : discrète, mais visible et survolable. */
abbr.fix{margin-inline-start:6px;font-size:11px;color:var(--mut);
 border-bottom:1px dotted var(--mut);cursor:help;text-decoration:none;white-space:nowrap}
table.dense td{padding:5px 10px}
table.dense th{padding:6px 10px}
table.prose td:first-child{width:26%;font-weight:520;vertical-align:top}
tbody tr:last-child td{border-bottom:0}
tbody tr{transition:background .14s var(--ease)}
tbody tr:hover{background:var(--surface-2)}
.num{text-align:end;font-variant-numeric:tabular-nums}
.tk{font-weight:600}
.nm{color:var(--mut);font-size:12.5px;font-weight:400;margin-inline-start:7px}
th.s{cursor:pointer;user-select:none}
th.s:hover{color:var(--ink)}
th.s::after{content:"";opacity:.28;margin-inline-start:5px;font-size:10px}
th.s[aria-sort=ascending]::after{content:"▲";opacity:.85}
th.s[aria-sort=descending]::after{content:"▼";opacity:.85}
.up{color:var(--up)}.down{color:var(--down)}.flat{color:var(--mut)}
.chip{display:inline-block;padding:1px 7px;border-radius:var(--r-fld);font-size:11.5px;
 font-weight:600;white-space:nowrap;
 background:var(--brand-wash);color:var(--brand-ink)}
.chip.up{background:var(--up-wash);color:var(--up)}
.chip.down{background:var(--down-wash);color:var(--down)}
/* Familles de nature des publications. Trois teintes, pas vingt-neuf : coder
   chaque nature ferait un nuancier, pas une aide à la lecture. Le reste garde
   la pastille neutre. Aucune ne réutilise --up/--down : une nature n'est ni une
   hausse ni une baisse. */
.chip.nat{font-weight:500;background:var(--surface-2);color:var(--ink-2);
 border:1px solid var(--line-soft)}
.chip.nat.fam-cotation{background:var(--warn-wash);color:var(--ink);
 border-color:color-mix(in oklab,var(--warn) 45%,var(--line))}
.chip.nat.fam-comptes{background:var(--brand-wash);color:var(--brand-ink);
 border-color:color-mix(in oklab,var(--brand) 30%,var(--line))}
.chip.nat.fam-capital{background:var(--accent);color:var(--ink);border-color:var(--line)}

/* ---------- comparateur : habillage replié ---------- */
.cmp-more{margin-top:6px}
.cmp-more>summary{display:flex;align-items:center;gap:8px;cursor:pointer;
 list-style:none;width:max-content;padding:5px 11px;border:1px solid var(--line);
 border-radius:var(--r-fld);background:var(--surface);font-size:12.5px;
 color:var(--ink-2);min-height:32px}
.cmp-more>summary::-webkit-details-marker{display:none}
.cmp-more>summary::before{content:"";width:0;height:0;flex:0 0 auto;
 border-inline-start:5px solid currentColor;border-block:4px solid transparent;
 transition:transform .14s var(--ease)}
[dir=rtl] .cmp-more>summary::before{transform:scaleX(-1)}
.cmp-more[open]>summary::before{transform:rotate(90deg)}
[dir=rtl] .cmp-more[open]>summary::before{transform:scaleX(-1) rotate(-90deg)}
.cmp-more>summary:hover{border-color:var(--brand);color:var(--ink)}
.cmp-more>summary .sm-t{font-weight:600}
.cmp-more[open]>summary{margin-bottom:6px}
@media (prefers-reduced-motion:reduce){.cmp-more>summary::before{transition:none}}

/* ---------- rail d'ancres d'une fiche ----------
   Collant sous la barre d'onglets. Horizontal et non en colonne : il se miroite
   seul en arabe, tient sous 672 px, et ne touche pas à la grille de la page.
   scroll-padding-top empêche l'ancre d'atterrir sous le chrome collant. */
.rail{position:sticky;top:var(--rail-top,0);z-index:20;display:flex;gap:2px;
 overflow-x:auto;scrollbar-width:none;margin:0 0 clamp(24px,3.4vw,40px);
 padding:6px 0;background:color-mix(in oklab,var(--bg) 92%,transparent);
 -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-bottom:1px solid var(--line-soft)}
.rail::-webkit-scrollbar{display:none}
.rail a{flex:0 0 auto;padding:6px 12px;border-radius:var(--r-fld);
 font-size:12.5px;color:var(--mut);text-decoration:none;white-space:nowrap;
 transition:background .14s var(--ease),color .14s var(--ease)}
.rail a:hover{background:var(--surface-2);color:var(--ink)}
@media (prefers-reduced-motion:no-preference){html{scroll-behavior:smooth}}

/* ---------- ratios d'une fiche : quatre groupes, une médiane ---------- */
/* Une rangée de groupe est un en-tête de portée, pas une ligne de données :
   elle porte scope=colgroup et se distingue par la couche, pas par une couleur. */
table.ratios tr.grp-row th{position:static;height:32px;text-align:start;
 background:var(--surface-2);color:var(--mut);font-size:11.5px;font-weight:600;
 letter-spacing:.06em;text-transform:uppercase;padding:0 10px;
 box-shadow:inset 0 -1px 0 var(--line)}
table.ratios tr.grp-row:first-child th{box-shadow:inset 0 -1px 0 var(--line)}
table.ratios td:first-child{width:46%}
table.ratios td:nth-child(2){font-weight:600;color:var(--ink)}
/* La colonne de comparaison reste en retrait : c'est un repère, pas la donnée
   de la ligne. Le chevron dit le sens, jamais la couleur — « au-dessus de la
   médiane » n'est ni une hausse ni une bonne nouvelle en soi. */
table.ratios td:last-child{width:26%;color:var(--mut)}
table.ratios .ecart{font-size:10px;opacity:.75;margin-inline-end:2px}
table.ratios thead th{height:auto;padding-bottom:4px;background:none;
 box-shadow:none;font-size:11.5px;color:var(--mut);text-transform:none;letter-spacing:.02em}
/* La sparkline se cale sur la ligne du texte : a 22 px elle imposait une
   rangee de 35 px la ou l'en-tete en fait 32, ce que Carbon interdit
   (l'en-tete et le corps ont la meme taille de rangee). Le viewBox
   redimensionne, le trace n'est pas deforme. */
.spark{width:74px;height:20px;display:block}

/* ---------- diverging bars (the beam) ---------- */
.beam{display:grid;gap:1px}
.dv{display:grid;grid-template-columns:minmax(96px,1.1fr) minmax(120px,3fr) 64px;
 gap:12px;align-items:center;padding:4px 0}
.dv-l{font-size:13px;color:var(--ink-2);overflow:hidden;text-overflow:ellipsis}
.dv-t{position:relative;height:16px}
.dv-t::before{content:"";position:absolute;left:50%;top:-2px;bottom:-2px;width:1px;
 background:var(--line)}
.dv-t i{position:absolute;top:3px;height:10px;border-radius:2px;display:block;
 animation:grow .5s var(--ease) both}
.dv-t i.up{left:50%;background:var(--up)}
.dv-t i.down{right:50%;background:var(--down)}
.dv-t.mag::before{left:0}
.dv-t.mag i{left:0;background:var(--brand);transform-origin:left}
.dv-v{font-size:12.5px;text-align:end}
@keyframes grow{from{transform:scaleX(0)}to{transform:scaleX(1)}}
.dv-t i.up{transform-origin:left}
.dv-t i.down{transform-origin:right}

/* ---------- feeds ---------- */
.feed{list-style:none;margin:0;padding:0}
.feed li{display:flex;gap:10px;align-items:baseline;padding:9px var(--pad);
 border-bottom:1px solid var(--line-soft)}
.feed li:last-child{border-bottom:0}
.feed .dt{color:var(--mut);font-size:12px;flex:0 0 auto;min-width:38px}
.feed a{color:var(--ink);text-decoration:none;text-decoration-color:var(--line)}
.feed a:hover{color:var(--brand-ink);text-decoration:underline}
.feed .tks{flex:0 0 auto}

/* ---------- listes de prose ---------- */
/* Même mesure de lecture que les paragraphes : sans cela, dans une même carte,
   la prose s'arrêtait à 589 px pendant que les puces couraient sur 1 070 —
   deux longueurs de ligne pour un seul texte, et une carte à moitié vide. */
.bullets{margin:10px 0 0;padding-inline-start:20px;color:var(--mut);font-size:13.5px;
 line-height:1.65}
.bullets li{margin-bottom:7px}
.bullets li b{color:var(--ink-2)}
.card-pad p.sub+p.sub{margin-top:10px}
/* Le texte occupe la largeur qu'on lui donne. La mesure de lecture de 78ch
   laissait, dans une carte de 1 132 px, cinq cents pixels de vide à sa droite :
   un paragraphe qui s'arrête au tiers d'un cadre se lit comme un défaut
   d'alignement, pas comme une colonne. Tableaux et graphiques, eux, gardent
   leur cadre — c'est le texte seul qui s'étirait mal. */

/* ---------- notice ---------- */
.notice{display:flex;gap:11px;align-items:flex-start;padding:12px 14px;border-radius:var(--r);
 border:1px solid color-mix(in oklab,var(--warn) 40%,var(--line));background:var(--warn-wash);
 font-size:13.5px;margin-bottom:18px}
.notice b{font-weight:620}
.notice svg{flex:0 0 auto;width:17px;height:17px;color:var(--warn);margin-top:1px}

/* ---------- filter ---------- */
.filter{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-bottom:12px}
.filter input,.filter select{font:inherit;font-size:13.5px;color:var(--ink);
 background:var(--surface);border:1px solid var(--line);border-radius:99px;padding:7px 13px}
.filter input{min-width:190px}
.filter input::placeholder{color:var(--mut)}
.count{font-size:12.5px;color:var(--mut)}
/* Jeux de colonnes : trois familles qui s'échangent, le reste du tableau ne
   bouge pas. Un seul contrôle segmenté, pas un menu — les trois options se
   lisent d'un coup et l'active se voit sans l'ouvrir. */
.views{display:inline-flex;border:1px solid var(--line);border-radius:var(--r-fld);
 overflow:hidden;background:var(--surface)}
.views button{font:inherit;font-size:12.5px;color:var(--mut);background:none;border:0;
 padding:6px 12px;min-height:32px;cursor:pointer;white-space:nowrap;
 border-inline-end:1px solid var(--line);transition:background .14s var(--ease)}
.views button:last-child{border-inline-end:0}
.views button:hover{background:var(--surface-2);color:var(--ink)}
.views button[aria-pressed=true]{background:var(--brand);color:var(--brand-on);font-weight:600}

/* Rangée de familles : elle se cale SOUS elle-même dans le port de défilement,
   donc la seconde rangée d'en-têtes doit descendre d'autant. 32 px = la hauteur
   d'une rangée. */
tr.grps th{height:32px;top:0;z-index:3;background:var(--surface-2);color:var(--mut);
 font-size:11.5px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
 text-align:center;box-shadow:inset 0 -1px 0 var(--line)}
tr.grps th:first-child{text-align:start}
tr.grps+tr th{top:32px;z-index:2}
th.grp[data-g]{border-inline-start:1px solid var(--line)}
/* Le score est l'argument du site : il ne peut pas finir hors écran. Il se fige
   au bord de fin du port de défilement, comme la colonne d'identité se fige au
   bord de début. Un filet le détache du reste. */
td.sc,th.sc{position:sticky;inset-inline-end:0;z-index:2;
 box-shadow:inset 1px 0 0 var(--line)}
td.sc{background:var(--surface)}
th.sc{background:var(--accent);z-index:4}

/* ⚠️ **La colonne d'identité se fige au bord de début, à toutes les largeurs.**
   Le commentaire du score l'annonçait déjà — « comme la colonne d'identité se
   fige au bord de début » — mais la règle vivait dans le bloc `max-width:720px`
   et ne valait donc que sur téléphone. Sur écran, la cote défile pourtant dès
   1 440 px (1 192 px de tableau pour 1 120 de boîte) : on partait chercher le
   PER ou le ROE, et on perdait de vue DE QUELLE société on lisait la ligne.
   Les deux bords tiennent maintenant, et seules les colonnes du milieu
   défilent. */
/* ⚠️ `table.sortable` et non `.scroll table` : le figement ne vaut que pour les
   tableaux de MARCHÉ, larges et triables, ceux où l'on défile pour comparer.
   Mesuré : posée sur toutes les tables du site, la règle dessinait un filet
   vertical et un fond opaque sur des tableaux qui ne défilent pas du tout —
   le guide, les ratios d'une fiche — c'est-à-dire une colonne figée sans rien
   à figer. */
.scroll table.sortable td:first-child,
.scroll table.sortable th:first-child{position:sticky;inset-inline-start:0;
 box-shadow:inset -1px 0 0 var(--line)}
/* ⚠️ Chaque rangée garde SON fond : un `background` unique aurait posé la
   couleur du corps sur l'en-tête, et la première colonne serait ressortie plus
   claire que le reste de sa propre ligne d'en-tête. */
.scroll table.sortable td:first-child{background:var(--surface);z-index:2}
.scroll table.sortable th:first-child{background:var(--accent);z-index:4}
.scroll table.sortable tr.grps th:first-child{background:var(--surface-2);z-index:5}
/* Sans cela, la colonne figée reste blanche quand le reste de sa ligne
   s'assombrit au survol : la ligne se couperait en deux. */
.scroll table.sortable tbody tr:hover td:first-child{background:var(--surface-2)}
tr.grps th:last-child{position:sticky;inset-inline-end:0;z-index:5;
 background:var(--surface-2);box-shadow:inset 1px 0 0 var(--line)}
tbody tr:hover td.sc{background:var(--surface-2)}
td.sc b,th.sc{color:var(--ink)}
/* La raison sociale ne pousse pas la table : elle se tronque proprement. */
td .nm{display:inline-block;max-width:26ch;overflow:hidden;text-overflow:ellipsis;
 vertical-align:bottom}

/* ---------- comparateur ----------
   Palette d'identité d'Okabe-Ito : six teintes conçues pour rester distinctes
   en vision dichromate. Un premier essai en teintes régulièrement espacées
   confondait la troisième et la sixième — deux violets voisins — alors que la
   couleur ne dit rien ici sinon « c'est cette valeur-là ». Les teintes sont
   éclaircies en sombre, l'écart entre elles est conservé. */
:root{--c1:oklch(52% .12 250);--c2:oklch(72% .14 75);--c3:oklch(58% .12 165);
 --c4:oklch(60% .11 350);--c5:oklch(55% .16 45);--c6:oklch(68% .10 235)}
@media (prefers-color-scheme:dark){:root:not([data-theme=light]){
 --c1:oklch(70% .13 250);--c2:oklch(82% .14 75);--c3:oklch(72% .13 165);
 --c4:oklch(74% .11 350);--c5:oklch(70% .16 45);--c6:oklch(80% .10 235)}}
:root[data-theme=dark]{--c1:oklch(70% .13 250);--c2:oklch(82% .14 75);
 --c3:oklch(72% .13 165);--c4:oklch(74% .11 350);--c5:oklch(70% .16 45);
 --c6:oklch(80% .10 235)}
.cmp-bar{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-bottom:12px}
.cmp-bar .seg{display:inline-flex;border:1px solid var(--line);border-radius:99px;
 overflow:hidden;background:var(--surface)}
.cmp-bar .seg button{font:inherit;font-size:12.5px;color:var(--mut);background:none;
 border:0;padding:6px 11px;cursor:pointer;white-space:nowrap}
.cmp-bar .cmp-x,.cmp-all{white-space:nowrap;font:inherit;font-size:12.5px;color:var(--ink);
 background:var(--surface);border:1px solid var(--line);border-radius:99px;
 padding:6px 13px;cursor:pointer}
.cmp-bar .cmp-x:hover,.cmp-all:hover:not(:disabled){border-color:var(--brand)}
.cmp-all:disabled{opacity:.4;cursor:default}
.cmp-ost{font-size:12px;color:var(--mut);margin-top:6px}
.cmp-ost b{color:var(--ink-2);font-weight:600}
/* ⚠️ `--brand-on`, jamais du blanc en dur : en sombre la marque devient CLAIRE
   et un texte blanc dessus tombe à 2,08:1 — sous le minimum lisible. Le
   comparateur écrivait le blanc à la main là où `.views` avait déjà sa
   correction ; les deux passent maintenant par le même jeton. */
.cmp-bar .seg button[aria-pressed=true]{background:var(--brand);color:var(--brand-on)}
/* Deux colonnes, deux rangées : les en-têtes en haut, la liste et le graphique
   dessous. `display:contents` fait entrer les quatre blocs dans la même grille,
   si bien que la rangée des en-têtes prend la hauteur du plus grand et que la
   liste et le graphique démarrent au même endroit — sans hauteur écrite en dur,
   qui aurait cédé à la première traduction plus longue.
   ⚠️ Remplissage par COLONNES : en rangées, la liste se plaçait à côté de son
   propre en-tête. Les quatre blocs arrivent dans l'ordre en-tête gauche, liste,
   en-tête droit, graphique — soit exactement deux colonnes de deux. */
/* Plus de grille à deux colonnes : le choix des valeurs tient sur une barre, et
   le graphique prend toute la largeur — c'est lui qu'on vient regarder. */
.cmp-pick{display:block}
.cmp-col{display:block}
/* Les deux en-têtes n'ont pas le même nombre de rangées : les répartir sur la
   hauteur commune les fait se répondre, plutôt que de coller les plus courtes
   en bas de leur bande. */
.cmp-hd{display:flex;flex-direction:column;justify-content:space-between;gap:8px}
/* Un enfant de grille garde par défaut la largeur de son contenu : sans ce
   min-width:0, les raisons sociales longues élargissaient toute la page sur
   téléphone (490 px de large pour 375 px de fenêtre). */
.cmp-pick>*{min-width:0}
@media (max-width:720px){
  /* Une seule colonne : les blocs reprennent leur ordre naturel, et le
     graphique passe devant — personne ne veut faire défiler soixante cases à
     cocher pour voir la courbe. */
  .cmp-saisie{flex:1 1 100%}
  /* Le tracé garderait sinon son rapport 1000:320, soit 91 px de haut sur un
     téléphone : illisible. `preserveAspectRatio=none` lui permet d'être étiré. */
  .cmp-chart{height:240px}
  /* Le groupe de boutons ne peut pas se replier dans une pastille unique : il
     débordait, et « 3 ans » comme « Tout » étaient rognés. Sous 720 px, chaque
     bouton devient sa propre pastille et la ligne se replie. */
  .cmp-bar .seg{flex-wrap:wrap;gap:6px;border:0;background:none;overflow:visible}
  .cmp-bar .seg button{border:1px solid var(--line);border-radius:99px;
   background:var(--surface)}
  .cmp-bar .seg button[aria-pressed=true]{border-color:var(--brand)}
}
/* La liste occupe toute la rangée : elle finit donc exactement où finit la
   carte du graphique, au lieu de s'arrêter cent pixels plus haut.
   ⚠️ Elle est posée en absolu dans son cadre, sinon ses 77 lignes dictent la
   hauteur de la rangée — le graphique se retrouvait étiré sur 2 100 px. C'est
   donc le graphique qui commande, et la liste s'y ajuste. */
/* Le choix des valeurs : UN champ. Les jetons vivent dans la boîte de saisie,
   comme les destinataires d'un courriel — la sélection et l'ajout ne sont plus
   deux rangées mais un seul objet, qui se comporte comme un champ de texte. */
.cmp-champ{position:relative;display:flex;flex-wrap:wrap;align-items:center;gap:6px;
 padding:7px 8px;border:1px solid var(--line);border-radius:var(--r-sm);
 background:var(--surface);cursor:text;transition:border-color .15s var(--ease)}
.cmp-champ:focus-within{border-color:var(--brand);
 box-shadow:0 0 0 3px color-mix(in oklab,var(--brand) 14%,transparent)}
.cmp-jetons{display:contents}
.cmp-jeton{display:inline-flex;align-items:center;gap:6px;font:inherit;font-size:12.5px;
 padding:3px 4px 3px 8px;border:0;border-radius:99px;cursor:pointer;
 background:var(--surface-2);color:var(--ink)}
.cmp-jeton i{width:8px;height:8px;border-radius:50%;flex:0 0 auto}
.cmp-jeton b{font-weight:600;letter-spacing:-.01em}
/* La croix ne s'affiche qu'au survol : douze jetons portant chacun leur croix
   font un mur de bruit, alors que la cible reste le jeton entier. */
.cmp-jeton span{width:14px;text-align:center;color:var(--mut);font-size:14px;
 line-height:1;opacity:0;transition:opacity .12s var(--ease)}
.cmp-jeton:hover,.cmp-jeton:focus-visible{background:color-mix(in oklab,var(--down) 12%,var(--surface-2));
 color:var(--down)}
.cmp-jeton:hover span,.cmp-jeton:focus-visible span{opacity:1;color:var(--down)}
.cmp-champ .cmp-q{flex:1 1 12ch;min-width:12ch;border:0;background:none;padding:3px 2px;
 font:inherit;font-size:13px;color:var(--ink);outline:none}
.cmp-champ .cmp-q::placeholder{color:var(--mut)}
/* Vider : discret, et seulement quand il y a quelque chose à vider. */
.cmp-clear{border:0;background:none;color:var(--mut);font-size:16px;line-height:1;
 cursor:pointer;padding:2px 4px;border-radius:var(--r-fld);margin-inline-start:auto}
.cmp-clear:hover{color:var(--down);background:var(--surface-2)}
.cmp-champ.vide .cmp-clear{display:none}
.cmp-sugg{position:absolute;z-index:20;inset-inline:0;top:calc(100% + 4px);margin:0;
 padding:4px;list-style:none;max-height:300px;overflow:auto;background:var(--surface);
 border:1px solid var(--line);border-radius:var(--r-sm);box-shadow:var(--shadow)}
.cmp-sugg li{display:flex;gap:8px;align-items:baseline;padding:6px 8px;border-radius:8px;
 cursor:pointer;font-size:13px}
.cmp-sugg li:hover,.cmp-sugg li[aria-selected=true]{background:var(--surface-2)}
.cmp-sugg li b{font-weight:600;min-width:6ch}
.cmp-sugg li span{color:var(--mut);font-size:12px;overflow:hidden;
 text-overflow:ellipsis;white-space:nowrap}
/* Un secteur n'est pas une valeur : il ajoute une poignée de courbes d'un coup,
   et se distingue donc de ce qui n'en ajoute qu'une. */
.cmp-sug-sec b{color:var(--brand)}
.cmp-sug-sec{border-bottom:1px solid transparent}
/* Le pied du graphique : base de calcul, export, et rien d'autre. */
.cmp-pied{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:10px}
.cmp-pied .cmp-trn{margin:0;flex:1 1 auto}
.cmp-chart{width:100%;height:auto;display:block;direction:ltr;touch-action:pan-y}
.cmp-wrap{position:relative;display:grid;grid-template-columns:1fr auto;gap:8px}
/* Chaque graduation est posée à la hauteur exacte de sa ligne de grille : une
   colonne en `space-between` les répartissait sur toute la boîte, décalées de
   la marge interne du tracé. */
.cmp-y{position:relative;font-size:11px;color:var(--mut);
 font-variant-numeric:tabular-nums;min-width:5ch}
.cmp-y span{position:absolute;inset-inline-end:0;transform:translateY(-50%);
 white-space:nowrap}
/* L'axe des dates suit le tracé, donc l'ordre chronologique de gauche à droite,
   y compris en RTL. Chaque date reste isolée pour que l'arabe s'y écrive dans
   son propre sens sans réordonner la ligne. */
.cmp-dates{display:flex;justify-content:space-between;font-size:11px;color:var(--mut);
 margin-top:4px;direction:ltr}
.cmp-dates span{unicode-bidi:isolate}
.cmp-leg{display:flex;gap:6px;flex-wrap:wrap;margin-top:8px;font-size:12.5px}
.cmp-l{display:inline-flex;gap:6px;align-items:center;font:inherit;font-size:12.5px;
 color:var(--ink);background:none;border:1px solid transparent;border-radius:99px;
 padding:3px 9px;cursor:pointer}
.cmp-l:hover{background:var(--surface-2)}
.cmp-l[aria-pressed=true]{border-color:var(--line);background:var(--surface-2)}
.cmp-clear{font:inherit;font-size:15px;line-height:1;color:var(--mut);
 background:var(--surface);border:1px solid var(--line);border-radius:99px;
 padding:5px 11px;cursor:pointer}
.cmp-clear:hover{color:var(--down);border-color:var(--down)}
.cmp-l i,.cmp-d{width:10px;height:10px;border-radius:3px;display:inline-block}
.cmp-d{margin-inline-end:7px;vertical-align:-1px}
.cmp-lv{color:var(--mut);font-variant-numeric:tabular-nums}
.cmp-tip{position:absolute;top:6px;transform:translateX(-50%);pointer-events:none;
 background:var(--surface);border:1px solid var(--line);border-radius:10px;padding:7px 10px;
 font-size:12px;box-shadow:0 6px 20px rgba(0,0,0,.13);white-space:nowrap;z-index:3}
.cmp-tip i{width:9px;height:9px;border-radius:2px;display:inline-block;margin-inline-end:5px}
.cmp-tip .tip-d{color:var(--mut);margin-bottom:3px}
.cmp-note{font-size:12px;color:var(--mut);margin-top:6px}
.cmp-bar2{margin-top:-4px}
.cmp-bar2 .lbl{font-size:12px;color:var(--mut)}
.cmp-bar .seg-mm button,.cmp-bar .seg-outils button{min-width:38px;text-align:center}
.cmp-wipe{font:inherit;font-size:12.5px;color:var(--mut);background:none;border:0;
 padding:6px 8px;cursor:pointer;text-decoration:underline;text-underline-offset:3px}
.cmp-wipe:hover{color:var(--down)}
.cmp-dess .dr{stroke:var(--brand);stroke-width:1.6;vector-effect:non-scaling-stroke}
.cmp-dess .dr-tmp{stroke-dasharray:4 3;opacity:.7}
.cmp-dess .dr-fib{stroke-width:1;opacity:.6}
.cmp-chart .il{font-size:10px;fill:var(--mut)}
.cmp-tip .up{color:var(--up)} .cmp-tip .down{color:var(--down)}
.cmp-grid .gr{stroke:var(--line-soft);stroke-width:1;vector-effect:non-scaling-stroke}
.cmp-grid .gr0{stroke:var(--mut);stroke-width:1;vector-effect:non-scaling-stroke;opacity:.55}
.cmp-cx{stroke:var(--brand);stroke-width:1;stroke-dasharray:3 3;
 vector-effect:non-scaling-stroke;opacity:0}
table.corr th{font-weight:560}
table.corr td[data-c]{font-weight:600}

/* ---------- pagination ----------
   La page porte ses 2 500 lignes ; sans cette règle le navigateur les met
   toutes en page avant que le script de fin de document n'en cache 2 480, et
   le tableau se réajuste sous les yeux pendant une à deux secondes. La règle
   ne s'applique que si le script du <head> a posé `js` : sans JavaScript, le
   tableau reste entier et lisible, faute de pagination pour le parcourir.
   Le seuil suit `data-page="20"` — l'autotest vérifie qu'ils ne divergent pas. */
html.js table.pg-init tbody tr:nth-child(n+21){display:none}

/* ---------- pagination ---------- */
.pager{display:flex;gap:8px;align-items:center;justify-content:flex-end;
 margin-top:10px;font-size:12.5px;color:var(--mut)}
.pager button{font:inherit;font-size:15px;line-height:1;color:var(--ink);
 background:var(--surface);border:1px solid var(--line);border-radius:99px;
 padding:5px 12px;cursor:pointer}
.pager button:hover:not(:disabled){border-color:var(--brand)}
.pager button:disabled{opacity:.35;cursor:default}
.pager .pg-info{min-width:11ch;text-align:center;font-variant-numeric:tabular-nums}
.pager select{font:inherit;font-size:12.5px;color:var(--ink);background:var(--surface);
 border:1px solid var(--line);border-radius:99px;padding:4px 9px}
/* Les flèches suivent le sens de lecture : en RTL, « précédent » pointe à droite. */
[dir=rtl] .pager button{transform:scaleX(-1)}

/* ---------- footer ---------- */
footer{max-width:var(--page-w);margin:0 auto;padding:26px var(--page-pad) 44px;
 border-top:1px solid var(--line);color:var(--mut);font-size:12.5px;line-height:1.65}
footer a{color:var(--mut)}

/* ---------- arabe, sens de lecture inversé ----------
   La mise en page se retourne d'elle-même grâce aux propriétés logiques
   (text-align:start/end, margin-inline, inset-inline). Deux exceptions :
   les courbes, où le temps va toujours de gauche à droite, et les nombres,
   qu'il faut isoler pour que « -1,05 % » ne soit pas réordonné par l'algorithme
   bidirectionnel. */
[dir=rtl] .chart,[dir=rtl] .spark,[dir=rtl] .dv-t{direction:ltr}
[dir=rtl] .num,[dir=rtl] .hero-v,[dir=rtl] .kpi-value,[dir=rtl] .statrow .v,
[dir=rtl] .stat .v,[dir=rtl] .dv-v,[dir=rtl] .dt{unicode-bidi:plaintext}
[dir=rtl] .tk{unicode-bidi:isolate}
[dir=rtl] .crumb span[aria-hidden]{transform:scaleX(-1);display:inline-block}
[dir=rtl] .skip{left:auto;right:-9999px}
[dir=rtl] .skip:focus{right:0}
[dir=rtl] .bullets{padding-inline-start:20px}

/* ---------- mobile ----------
   Les tableaux de données sont larges par nature. Plutôt que de tout comprimer,
   on hiérarchise : les colonnes marquées .opt disparaissent sous 720 px, la
   première colonne reste figée pendant le défilement horizontal, et une ombre
   au bord droit signale qu'il reste du contenu — sans cet indice, personne ne
   découvre le défilement. */
@media (max-width:720px){
  .scroll{background-image:
      linear-gradient(to right,var(--surface),transparent 12px),
      linear-gradient(to left,var(--surface),transparent 12px),
      /* .10 était invisible sur fond clair : le liseré existait sans rien dire. */
      linear-gradient(to right,oklch(0.5 0 0/.20),transparent 14px),
      linear-gradient(to left,oklch(0.5 0 0/.20),transparent 14px);
    background-position:left center,right center,left center,right center;
    background-repeat:no-repeat;background-size:24px 100%,24px 100%,10px 100%,10px 100%;
    background-attachment:local,local,scroll,scroll}
  table{font-size:13.5px}
  td,th{padding:7px 8px}
  .nm{display:block;margin-inline-start:0;font-size:11.5px}
  .spark{width:56px}
  /* En dernier et qualifié : .nm{display:block} ci-dessus l'emporterait sinon sur
     les cellules qui portent les deux classes. */
  td.opt,th.opt,span.opt,.opt{display:none}
}
/* ---------- les tableaux de marché en CARTES sous 720 px -----------------
   Un écran de 390 px ne peut pas montrer un tableau de marché. Chaque ligne
   devient une carte : identité à gauche, chiffre de tête et variation du jour
   à droite, puis chaque autre colonne en paire « intitulé — valeur ».
   ⚠️ Le DOM ne change PAS — ce sont toujours des `tr`/`td`, sans quoi le tri
   (`cells[i]`), le filtre et la pagination (qui masquent des `tr`) casseraient
   d'un coup. Seule la mise en forme change ; un script pose `data-l` sur
   chaque cellule en le lisant dans l'en-tête, donc traduit sans duplication.
   ⚠️ Repères SÉMANTIQUES (`.c-val`, `.c-chg`) et non des `nth-child` : la
   colonne du cours est la 3e sur la cote et la 2e sur les indices. Une règle
   positionnelle aurait mis le niveau d'un indice à la place de son nom. */
.tri-mob{display:none}
@media (max-width:720px){
  .tri-mob{display:inline-flex;align-items:center;flex:1 1 100%}
  .tri-mob select{width:100%}

  table.cartes,table.cartes tbody{display:block;width:auto;min-width:0}
  table.cartes thead{display:none}

  table.cartes tbody tr{display:grid;grid-template-columns:1fr auto;
   gap:2px 10px;align-items:baseline;padding:11px 12px;
   border-bottom:1px solid var(--line)}
  table.cartes tbody tr:last-child{border-bottom:0}

  table.cartes tbody td{display:flex;justify-content:space-between;gap:12px;
   grid-column:1 / -1;padding:3px 0;border:0;border-top:1px solid var(--line-soft);
   text-align:start;font-size:13px;white-space:normal;color:var(--ink-2)}
  table.cartes tbody td::before{content:attr(data-l);color:var(--mut);
   font-size:12px;font-weight:400}

  /* Tête de carte : identité à gauche, chiffre et variation à droite. */
  table.cartes tbody td:first-child{grid-column:1;grid-row:1;display:block;
   border-top:0;font-size:15px;font-weight:600;color:var(--ink)}
  table.cartes tbody td:first-child::before{content:none}
  table.cartes tbody td:first-child .nm{display:block;font-size:12px;
   font-weight:400;color:var(--mut);max-width:none;overflow:visible;
   text-overflow:clip;white-space:normal;margin-inline-start:0}

  /* ⚠️ **La carte entière ouvre la valeur.** Mesuré à 390 px : le seul point
     d'entrée vers une société était son mnémonique — un lien de **17 × 20 px**
     dans une carte de 158, sur une liste de 77 — et la raison sociale posée
     juste dessous, la chose qu'on essaie de toucher, n'était cliquable NULLE
     PART. Le `::after` du lien couvre le `tr` positionné : la cible passe de
     340 px² à près de 54 000.
     ⚠️ Sûr ICI et seulement ici : chaque ligne de la cote et des indices porte
     EXACTEMENT un lien (vérifié, 77 et 14 lignes). Deux liens sous la même
     nappe, et le second devient inatteignable — c'est pourquoi la règle vise
     `table.cartes` et pas `table` : le tableau des publications, lui, porte le
     lien de la valeur ET celui du document. */
  table.cartes tbody tr{position:relative}
  table.cartes tbody td:first-child a::after{content:"";position:absolute;
   inset:0;z-index:1}
  /* Sans retour tactile, rien ne dit que la carte est devenue un bouton. */
  table.cartes tbody tr:active{background:var(--surface-2)}
  table.cartes tbody td.c-val{grid-column:2;grid-row:1;display:block;
   border-top:0;text-align:end;font-size:16px;font-weight:600;color:var(--ink);
   font-variant-numeric:tabular-nums}
  table.cartes tbody td.c-val::before,table.cartes tbody td.c-chg::before{content:none}
  table.cartes tbody td.c-chg{grid-column:2;grid-row:2;display:block;
   border-top:0;text-align:end;font-size:13px;font-weight:600}

  table.cartes tbody td.sc{font-weight:700;color:var(--ink)}
  /* ⚠️ **Aucune cellule COLLANTE en mode carte.** Deux raisons, et la seconde
     s'est payée : (1) figée au bord, elle se détacherait du bloc ; (2) une
     cellule `position:sticky` est un élément POSITIONNÉ, donc c'est ELLE que
     prend pour référence le `inset:0` du lien étiré ci-dessus — mesuré 255×32
     au lieu des 339×158 de la carte. La règle ne visait que `td.sc` ; la
     cellule d'identité de la cote, collante elle aussi, portait le même défaut
     une colonne plus loin. Elle les relâche maintenant TOUTES.
     ⚠️ Et il faut au moins la spécificité de la règle qui colle :
     `.scroll table td:first-child` pèse (0,2,2), `table.cartes tbody td`
     seulement (0,1,3) — écrite ainsi, la règle ne mordait pas et la mesure le
     disait : le lien restait enfermé dans 255×32.
     ⚠️ **Et la spécificité se rejoue à chaque fois.** Écrite
     `table.cartes tbody td:first-child` (0,2,3), cette neutralisation battait
     `.scroll table td:first-child` (0,2,2). Le jour où le figement de la
     colonne d'identité est passé à `.scroll table.sortable td:first-child`
     (0,3,2), il est repassé DEVANT : la cellule redevenait collante en mode
     carte, et la nappe du lien étiré retombait à 255 × 32 au lieu de 339 × 156
     — la carte cessait d'être cliquable, sans que rien ne casse. Mesuré, pas
     deviné. Le `.scroll` de tête remet la neutralisation en tête (0,3,3). */
  table.cartes tbody td,
  .scroll table.cartes tbody td,
  .scroll table.cartes tbody td:first-child{position:static;
   inset-inline-start:auto;inset-inline-end:auto;background:none;box-shadow:none}
  /* ⚠️ RÉAFFIRMER le masquage : `table.cartes tbody td{display:flex}` a une
     spécificité supérieure à `.opt{display:none}` et ressuscitait toutes les
     colonnes qu'on avait pris soin d'écarter. */
  table.cartes tbody td.opt,table.cartes tbody td[hidden]{display:none}
}

/* ---------- tables « intitulé → valeur » sur téléphone ----------
   ⚠️ Ces tables n'ont pas de colonnes à comparer : elles apparient un libellé
   et une valeur. Les tenir en colonnes sur un écran de 390 px oblige la valeur
   à rester sur une ligne insécable — la gouvernance d'une fiche valeur cachait
   ainsi **1 134 px** de défilement horizontal, onze noms d'administrateurs
   hors de l'écran, sans que rien ne le signale.
   Empilées, elles ne cachent plus rien. Placé APRÈS le bloc 720 px ci-dessus :
   `.nm{display:block}` y sortait déjà la cellule d'intitulé du tableau, sans
   traiter la cellule de valeur restée seule et large. */
/* La consigne de défilement : discrète, mais lisible — et jamais affichée
   quand le tableau tient dans l'écran (c'est le JS qui la pose). */
.swipe{margin:0 0 6px;font-size:12px;color:var(--mut);display:flex;gap:6px;
 align-items:center}
.swipe::before{content:"↔";font-size:14px;color:var(--brand)}

@media (max-width:720px){
  /* ⚠️ `td .nm` en ligne (règle L818, plus spécifique) maintenait la raison
     sociale À CÔTÉ du mnémonique : la colonne d'identité de la cote pesait
     289 px sur 339 disponibles. Repliée dessous, elle en rend près de 200. */
  td .nm{display:block;max-width:16ch;margin-inline-start:0}
  /* ⚠️ Une pastille de mnémonique DANS un lien fait 22 px de haut : trop peu
     pour un doigt, et c'est la porte d'entrée vers la valeur depuis la liste
     des publications. La ligne fait déjà 83 px, la place est là. Qualifié par
     `a` : les mêmes pastilles servent ailleurs de simples étiquettes, et une
     étiquette n'a pas à grossir. */
  td a .chip{display:inline-block;padding:6px 9px}
  /* L'en-tête mangeait 208 px avant le premier contenu — un quart d'un écran
     de 844. « indices du … » répète la date de la pastille de séance, et
     l'horodatage de régénération est déjà en toutes lettres dans le pied de
     page : sur téléphone ils coûtent deux rangées pour rien. */
  .top-meta>span{display:none}
  .top-meta .pill.fresh{display:none}

  table.kv,table.kv tbody,table.kv tr,table.kv td{display:block;width:auto}
  table.kv tr{padding:8px 0;border-bottom:1px solid var(--line)}
  table.kv tr:last-child{border-bottom:0}
  table.kv td{white-space:normal;padding:0;border:0}
  table.kv td.nm{font-size:12px;margin-bottom:2px}

  /* ⚠️ **Une PHRASE dans une cellule de tableau** — le défaut déjà payé sur la
     console d'administration, puis sur la gouvernance d'une fiche, et servi une
     troisième fois par les tables du guide fiscal. Mesuré à 390 px : le tableau
     des frais faisait 1 161 px dans une boîte de 349 (on en voyait 30 %), celui
     des plus-values 834. La cause est la même : la colonne porte un cas
     (« Actions cotées souscrites ou acquises avant le 1ᵉʳ janvier 2011… ») ou
     une explication, pas une valeur — rien à comparer en colonnes, donc rien à
     garder en colonnes. Elles empilent, comme `.kv` le fait depuis toujours.
     La hiérarchie est portée par `.pile` et non par `.kv` : sur une fiche, la
     première cellule est un intitulé DISCRET (`td.nm`), ici c'est la donnée
     principale. Une seule règle pour les deux aurait rendu l'une des deux
     fausse. */
  table.kv thead{display:none}
  table.pile td:first-child{font-weight:600;color:var(--ink);margin-bottom:2px}
  /* Empilé, un nombre aligné à droite se détache de son intitulé : il revient
     au bord du texte, et grossit — c'est le chiffre qu'on est venu lire. */
  table.pile td.num{text-align:start;font-size:15px;font-weight:600;
   font-variant-numeric:tabular-nums}
  table.pile td:not(:first-child):not(.num){font-size:12.5px;color:var(--mut)}
}
@media (max-width:640px){
  .dv{grid-template-columns:minmax(82px,1fr) minmax(70px,2fr) 58px;gap:8px}
  .statrow>div{flex:1 1 50%;border-bottom:1px solid var(--line-soft)}
  .hero-top{gap:14px}
  .hero-side{gap:16px}
  .stat .v{font-size:15px}
  .filter input,.filter select{flex:1 1 100%;min-width:0}
  .feed li{flex-wrap:wrap;gap:6px}
  .feed li a{flex:1 1 100%}
  /* ⚠️ La RÉSERVE du bouton doit être réaffirmée ici. Le raccourci `padding`
     remet `padding-inline-start` à 12 px et annulait, sans le dire, la réserve
     de `var(--rail-w) + 4px` posée plus haut : mesuré à 390 px, le bouton fixe
     (0→48 px) recouvrait le bloc de marque, qui démarre à 12 px. C'est cette
     superposition qui le faisait lire comme une partie du logo au lieu d'un
     contrôle. */
  .top-in{gap:8px;padding:9px 12px;padding-inline-start:calc(var(--rail-w) + 4px)}
  .top-meta{width:100%;margin-inline-start:0;font-size:11.5px;gap:6px}
  .brand-txt b{font-size:17px}
  footer{font-size:11.5px}
}
@media (max-width:420px){
  .statrow>div{flex:1 1 100%}
  .dv{grid-template-columns:minmax(72px,1fr) minmax(50px,1.4fr) 52px}
}
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;transition-duration:.001ms!important}
}
@media print{
  .top,.tabs,.iconbtn{display:none}
  .panel[hidden]{display:block!important}
  body{background:#fff}
  .card,.hero,.statrow{break-inside:avoid;box-shadow:none}
}

/* ---------- decalage du contenu par le panneau ----------
   Le decalage est pose sur le CONTENEUR, pas sur chaque bloc.

   Premiere version : `margin-inline-start` sur `.wrap` et `footer>*`. Elle
   ecrasait le `margin:0 auto` de ces blocs, donc le contenu se collait au rail
   pendant que l'en-tete, lui, restait centre — mesure sur un ecran de 2560 px :
   en-tete a 683 du bord, contenu a 48, pied a 755. Trois alignements pour une
   meme page, et un vide de 1332 px a droite du tableau.

   `padding-inline-start` sur `body` decale l'en-tete, le contenu et le pied
   ensemble ; chacun garde son `margin:0 auto` et se recentre dans la largeur
   restante. Le panneau est en `position:fixed` : il se loge exactement dans le
   rembourrage. */
@media (min-width:1056px){
  body{padding-inline-start:var(--nav-w);
   transition:padding-inline-start .18s var(--ease)}
  :root[data-nav=rail] body{padding-inline-start:var(--rail-w)}
  :root[data-nav=off] body{padding-inline-start:0}
}
@media (prefers-reduced-motion:reduce){body{transition:none}}
