@charset "UTF-8";
/* ═══════════════════════════════════════════════════════════════════════
   PIPSTER · RADAR D'INTÉGRITÉ DE MARCHÉ — habillage du panneau
   ═══════════════════════════════════════════════════════════════════════

   La règle @charset ci-dessus doit rester le TOUT PREMIER OCTET du fichier :
   un commentaire avant elle et elle est ignorée en silence. Le serveur rend
   `content-type: text/css` SANS charset, et cette feuille pose un `content:`
   non-ASCII (le chevron « ▸ » des sections dépliables) — sans la déclaration,
   le navigateur retombe sur un jeu 8 bits et l'affiche « â–¸ ».
   `tests/gold-classic.test.php` vérifie cet accord dans les deux sens.

   TOUT est préfixé `.mir-`, et ce n'est pas une coquetterie.

   Cette feuille est injectée dans le bloc <head> AVANT style.css. À
   spécificité égale, c'est donc style.css qui gagne. Un nom de classe
   générique (`.bar`, `.head`, `.score`) serait silencieusement écrasé, ou
   pire, écraserait quelqu'un d'autre. Le préfixe est la seule protection —
   c'est la règle que Risk Pulse s'est déjà écrite avec `.rp-`.

   Les couleurs passent par les jetons du terminal (--up, --dn, --muted,
   --line…) pour suivre le thème clair/sombre ET les peaux sans être
   retouchées. Aucune valeur en dur qui ne soit une nuance de ces jetons.

   Sévérité : on monte en couleur, on ne clignote jamais. Un panneau de
   surveillance qui pulse en rouge cesse d'être lu au bout d'une heure — et
   le cahier des charges l'interdit explicitement.
   ═══════════════════════════════════════════════════════════════════════ */

#mirPanel {
  display: flex;
  flex-direction: column;
  gap: 10px;
  /* `min-width:0` partout dans le terminal : sans lui, une piste de grille
     refuse de descendre sous la largeur de son contenu et déborde sur
     téléphone. La note est déjà dans la feuille responsive. */
  min-width: 0;
}

/* ── Bandeau ──────────────────────────────────────────────────────────── */
.mir-head {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas: 'dial info' 'text text';
  align-items: start;
  gap: 6px 10px;
  min-width: 0;
}
.mir-gaugewrap { grid-area: dial; display: block; }
.mir-headtxt   { grid-area: text; text-align: center; }
.mir-info      { grid-area: info; }

/* ── LA JAUGE : UN CADRAN, PAS UN DISQUE ──────────────────────────────
   Demi-cercle de 180°, anneau segmenté par les seuils réels, aiguille.
   Tout est en SVG écrit à la main : le projet n'a aucune dépendance
   externe et n'en gagnera pas une pour un dessin.

   Le cadran occupe SA PROPRE LIGNE, pleine largeur : un instrument se lit
   de face. Le coincer dans une colonne de 56 px à côté du texte aurait
   rendu l'aiguille illisible, qui est pourtant tout l'intérêt. */
.mir-gauge {
  width: 100%;
  max-width: 190px;
  margin: 0 auto;
  display: block;
}
.mir-gauge-svg { width: 100%; height: auto; display: block; overflow: visible; }

/* L'anneau de fond : ce qui reste à parcourir. */
.mir-band-bg {
  fill: none;
  stroke: var(--panel-2, rgba(127, 127, 127, .16));
  stroke-width: 13;
  stroke-linecap: butt;
}

/* Les cinq bandes. Mêmes teintes que partout ailleurs dans le module —
   un vert qui vire à l'orange puis au rouge, sans jamais clignoter. */
.mir-band { fill: none; stroke-width: 13; stroke-linecap: butt; }
.mir-band.is-ok    { stroke: var(--up, #26a69a); }
.mir-band.is-watch { stroke: var(--muted, #8b949e); }
.mir-band.is-susp  { stroke: #d9a441; }
.mir-band.is-high  { stroke: #e0863a; }
.mir-band.is-crit  { stroke: var(--dn, #ef5350); }

/* La bande est ATTÉNUÉE tant que l'aiguille n'y est pas : le cadran doit
   dire où l'on est, pas éblouir avec cinq couleurs à parts égales. */
.mir-gauge .mir-band { opacity: .3; transition: opacity .3s ease; }
.mir-gauge[data-state="ok"]    .mir-band.is-ok,
.mir-gauge[data-state="watch"] .mir-band.is-watch,
.mir-gauge[data-state="susp"]  .mir-band.is-susp,
.mir-gauge[data-state="high"]  .mir-band.is-high,
.mir-gauge[data-state="crit"]  .mir-band.is-crit { opacity: 1; }

.mir-tick { stroke: var(--panel, #101418); stroke-width: 1.6; opacity: .85; }

.mir-needle { fill: var(--fg, #e6edf3); }

.mir-gv {
  fill: var(--fg);
  font-size: 26px;
  font-weight: 700;
  text-anchor: middle;
  font-variant-numeric: tabular-nums;
}
.mir-gauge[data-state="ok"]    .mir-gv { fill: var(--up, #26a69a); }
.mir-gauge[data-state="susp"]  .mir-gv { fill: #d9a441; }
.mir-gauge[data-state="high"]  .mir-gv { fill: #e0863a; }
.mir-gauge[data-state="crit"]  .mir-gv { fill: var(--dn, #ef5350); }
.mir-gauge[data-state="na"]    .mir-gv,
.mir-gauge[data-state="unknown"] .mir-gv { fill: var(--muted); }

/* `direction: ltr` sur les textes du cadran : en arabe, l'algorithme bidi
   réordonnait « /100 » en « 100/ ». Une unité de mesure n'est pas de la
   prose — elle garde son sens de lecture dans toutes les langues, comme les
   chiffres qu'elle qualifie. */
.mir-gu   { fill: var(--muted); font-size: 9px; text-anchor: middle; direction: ltr; }
.mir-gend { fill: var(--muted); font-size: 8px; text-anchor: middle; opacity: .6; direction: ltr; }
.mir-gv   { direction: ltr; }

.mir-headtxt { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.mir-state {
  font-size: .74rem;
  font-weight: 650;
  letter-spacing: .02em;
  color: var(--fg);
  /* Le classement peut être long en allemand ; il se coupe plutôt que de
     pousser la jauge hors du panneau. */
  overflow-wrap: anywhere;
}
.mir-sub {
  font-size: .68rem;
  color: var(--muted);
  overflow-wrap: anywhere;
}

.mir-info {
  flex: 0 0 auto;
  width: 26px; height: 26px;
  display: grid; place-items: center;
  border: 0; padding: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--muted);
  cursor: help;
}
.mir-info:hover { color: var(--fg); background: var(--panel-2, rgba(127,127,127,.1)); }
.mir-info svg { width: 15px; height: 15px; }

/* ── Sens ─────────────────────────────────────────────────────────────── */
.mir-dirs {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 9px;
  min-width: 0;
}
.mir-dir { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.mir-dir-k { font-size: .6rem; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.mir-dir-v { font-size: .74rem; font-weight: 600; color: var(--fg); overflow-wrap: anywhere; }
.mir-dir-v.up { color: var(--up, #26a69a); }
.mir-dir-v.dn { color: var(--dn, #ef5350); }

/* ── Barres du radar ──────────────────────────────────────────────────── */
.mir-bars { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.mir-bar {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(60px, 90px) 26px;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.mir-bar-k {
  font-size: .68rem;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.mir-bar-t {
  height: 5px;
  border-radius: 3px;
  background: var(--panel-2, rgba(127,127,127,.14));
  overflow: hidden;
}
.mir-bar-f {
  display: block;
  height: 100%;
  border-radius: 3px;
  transition: width .35s ease;
}
.mir-bar-f.is-low  { background: var(--muted, #8b949e); }
.mir-bar-f.is-mid  { background: #d9a441; }
.mir-bar-f.is-high { background: var(--dn, #ef5350); }
.mir-bar-v {
  font-size: .66rem;
  font-variant-numeric: tabular-nums;
  color: var(--fg);
  text-align: right;
}

.mir-empty { font-size: .68rem; color: var(--muted); margin: 2px 0; }

/* ── Détecteurs éteints / preuves ─────────────────────────────────────── */
.mir-off, .mir-why {
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 7px 10px;
  min-width: 0;
}
.mir-off > summary, .mir-why > summary {
  font-size: .68rem;
  color: var(--muted);
  cursor: pointer;
  list-style: none;
}
.mir-off > summary::-webkit-details-marker,
.mir-why > summary::-webkit-details-marker { display: none; }
.mir-off > summary::before, .mir-why > summary::before {
  content: '▸';
  display: inline-block;
  margin-inline-end: 6px;
  transition: transform .15s ease;
}
.mir-off[open] > summary::before, .mir-why[open] > summary::before { transform: rotate(90deg); }

.mir-off-list, .mir-ev { list-style: none; margin: 7px 0 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.mir-off-list li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: 8px;
  font-size: .64rem;
  min-width: 0;
}
.mir-off-k { color: var(--muted); overflow-wrap: anywhere; }
.mir-off-r { color: var(--line-strong, var(--muted)); opacity: .8; overflow-wrap: anywhere; }

.mir-ev li {
  font-size: .66rem;
  color: var(--fg);
  padding-inline-start: 10px;
  position: relative;
  overflow-wrap: anywhere;
}
/* `inset-inline-start` et non `left` : en arabe la puce doit passer à
   droite toute seule. Une marge posée en `left` reste à gauche en RTL —
   la note est déjà dans la feuille du calendrier. */
.mir-ev li::before {
  content: '';
  position: absolute;
  inset-inline-start: 0;
  top: .5em;
  width: 4px; height: 4px;
  border-radius: 50%;
  background: var(--muted);
}

/* ── Sources ──────────────────────────────────────────────────────────── */
.mir-src { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.mir-src-rows { display: flex; flex-direction: column; gap: 3px; }
.mir-src-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, auto);
  align-items: baseline;
  gap: 8px;
  font-size: .64rem;
  min-width: 0;
}
.mir-src-k { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mir-src-v { font-variant-numeric: tabular-nums; color: var(--fg); font-weight: 600; }
.mir-src-n { color: var(--muted); font-size: .6rem; text-align: end; overflow-wrap: anywhere; }
.mir-src-row.is-warn .mir-src-n { color: #d9a441; }
.mir-src-row.is-off  .mir-src-v,
.mir-src-row.is-off  .mir-src-n { color: var(--dn, #ef5350); opacity: .85; }

/* Les réserves, repliées par défaut. Elles restent à un clic, et le fait
   qu'elles qualifient — « différé de 602 s », « non souscrit » — reste écrit
   sur la ligne de la source elle-même, toujours visible. */
.mir-caveats > summary {
  font-size: .6rem;
  color: var(--muted);
  cursor: pointer;
  list-style: none;
  opacity: .75;
}
.mir-caveats > summary::-webkit-details-marker { display: none; }
.mir-caveats > summary::before {
  content: '▸';
  display: inline-block;
  margin-inline-end: 5px;
  transition: transform .15s ease;
}
.mir-caveats[open] > summary::before { transform: rotate(90deg); }
.mir-caveats > .mir-notice { margin-top: 6px; }

.mir-notice {
  margin: 0;
  font-size: .6rem;
  line-height: 1.45;
  color: var(--muted);
  padding: 6px 8px;
  border-inline-start: 2px solid var(--line);
  background: var(--panel-2, rgba(127,127,127,.06));
  border-radius: 0 6px 6px 0;
}
[dir="rtl"] .mir-notice { border-radius: 6px 0 0 6px; }

.mir-foot {
  margin: 0;
  font-size: .58rem;
  line-height: 1.45;
  color: var(--muted);
  opacity: .8;
}

/* ── Pastille du dock ─────────────────────────────────────────────────── */
.bt-meta.mir-meta-crit { color: var(--dn, #ef5350); }
.bt-meta.mir-meta-high { color: #e0863a; }
.bt-meta.mir-meta-susp { color: #d9a441; }

/* ── Téléphone ────────────────────────────────────────────────────────
   Le panneau devient un tiroir du bas sous 1024 px : la place verticale y
   est comptée, on resserre. */
@media (max-width: 700px) {
  /* Le cadran n'est PLUS un carré : il garde sa largeur et se contente
     d'un plafond plus bas. La règle héritée du disque (48×48) l'écrasait
     en vignette illisible — et elle s'appliquait même hors téléphone,
     parce qu'un onglet d'arrière-plan répond `innerWidth: 0`, ce que
     `max-width` interprète comme un très petit écran. Le codebase s'était
     déjà écrit cette note dans tool-rail.js. */
  .mir-gauge { max-width: 160px; }
  .mir-dirs { grid-template-columns: 1fr; }
  .mir-bar { grid-template-columns: minmax(0, 1fr) minmax(48px, 70px) 24px; }
}

/* ── MARKET DATA : l'état des sources, en tête ─────────────────────────
   Trois pastilles compactes. Elles ne clignotent pas et ne prennent pas
   plus d'une ligne : c'est un bandeau d'état de salle de marché, pas une
   alerte. Le code technique reste en majuscules (LIVE / DELAYED), lisible
   dans les six langues sans traduction mot à mot. */
.mir-feeds {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  min-width: 0;
}
.mir-feed {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  padding: 3px 7px;
  border-radius: 6px;
  border: 1px solid var(--line);
  font-size: .58rem;
  line-height: 1.2;
  white-space: nowrap;
}
.mir-feed b { font-weight: 650; color: var(--muted); letter-spacing: .03em; }
.mir-feed i { font-style: normal; font-weight: 600; }
.mir-feed.is-ok   i { color: var(--up, #26a69a); }
.mir-feed.is-warn i { color: #d9a441; }
.mir-feed.is-off  i { color: var(--dn, #ef5350); }
.mir-feed.is-off  { border-color: color-mix(in oklab, var(--dn, #ef5350) 35%, var(--line)); }

/* ── Les deux couches + confiance + couverture ───────────────────────── */
.mir-layers {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  align-items: start;
  gap: 6px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 9px;
  min-width: 0;
}
.mir-l { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
/* LE LIBELLÉ PASSE À LA LIGNE, IL NE SE TRONQUE PAS.
   Dans une colonne de ~60 px, « MICROSTRUCTURE » ne tient sur aucune ligne :
   l'ellipse rendait « ANOMALIE D... », c'est-à-dire un chiffre dont on ne
   sait plus ce qu'il mesure. Deux lignes courtes valent mieux qu'une ligne
   coupée. La hauteur est réservée pour que les quatre colonnes restent
   alignées quelle que soit la longueur du mot dans chaque langue. */
.mir-l-k {
  font-size: .5rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .02em;
  line-height: 1.15;
  min-height: 2.3em;
  overflow-wrap: anywhere;
  hyphens: auto;
}
.mir-l-v {
  /* `anywhere` coupait « MOYENNE » en « MOYEN / NE ». Un libellé d'état se
     lit d'un bloc ou pas du tout : on interdit la coupure et on réduit le
     corps pour que le mot le plus long des six langues tienne. */
  font-size: .68rem;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  color: var(--fg);
  overflow-wrap: normal;
  word-break: keep-all;
  hyphens: none;
  line-height: 1.2;
}
.mir-l.is-ok   .mir-l-v { color: var(--up, #26a69a); }
.mir-l.is-warn .mir-l-v { color: #d9a441; }
/* « N/A » est GRIS, jamais rouge : ce n'est pas une anomalie, c'est une
   absence de mesure — et la nuance est tout le sujet de ce module. */
.mir-l.is-off  .mir-l-v { color: var(--muted); opacity: .75; }

/* ── Détail par état ─────────────────────────────────────────────────── */
.mir-off-list li {
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: baseline;
}
.mir-off-s {
  font-size: .55rem;
  text-transform: uppercase;
  letter-spacing: .03em;
  padding: 1px 5px;
  border-radius: 4px;
  white-space: nowrap;
  background: var(--panel-2, rgba(127,127,127,.12));
}
.mir-off-list li.is-ok   .mir-off-s { color: var(--up, #26a69a); }
.mir-off-list li.is-warn .mir-off-s { color: #d9a441; }
.mir-off-list li.is-wait .mir-off-s { color: var(--muted); }
.mir-off-list li.is-off  .mir-off-s { color: var(--dn, #ef5350); opacity: .85; }

@media (max-width: 700px) {
  .mir-layers { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .mir-off-list li { grid-template-columns: minmax(0, 1fr) auto; }
  .mir-off-list li .mir-off-r { grid-column: 1 / -1; }
}

/* Ce que mesure le chiffre, sous la jauge. Volontairement petit et gris :
   c'est une légende, pas un titre — mais elle doit être là, parce qu'un
   nombre nu sur 100 invite à la mauvaise lecture. */
/* LA LÉGENDE VIT SOUS LE DISQUE, PAS DEDANS.
   Placée à l'intérieur d'un cercle de 56 px, « ANOMALIE PRIX » débordait sur
   le tracé de la jauge. On sort donc le bandeau en colonne : le disque, puis
   son étiquette, alignés sur la même largeur. */
.mir-gaugewrap { display: block; }
.mir-score-label {
  display: block;
  margin-top: -2px;
  font-size: .5rem;
  letter-spacing: .04em;
  color: var(--muted);
  text-transform: uppercase;
  text-align: center;
  line-height: 1.1;
}

/* ── PANNEAU VERROUILLÉ : ON NE MONTRE QUE L'OFFRE ─────────────────────
   `lockModulePanel()` AJOUTE sa cartouche, il ne retire rien — c'est à
   chaque panneau de masquer son propre contenu. La règle existe pour
   #ladderPanel et #btPanel ; elle manquait ici, si bien qu'un visiteur
   voyait la jauge, les deux colonnes de sens et l'avertissement au-dessus
   du bouton d'achat.

   Deux raisons de la poser, et la seconde compte plus que la première :
   ce n'est pas seulement inesthétique, c'est donner à lire un module
   qu'on facture 15 €/mois. Le sélecteur cible les enfants DIRECTS et
   épargne la cartouche. */
#mirPanel.saas-lock-mode > *:not(.saas-lockpanel) { display: none !important; }

/* Le panneau verrouillé n'a plus de contenu à espacer : sans cela, le
   `gap: 10px` de la colonne laissait une bande vide au-dessus du cadenas. */
#mirPanel.saas-lock-mode { gap: 0; }
