@layer layout{
  /* ── En-tête ──
     Barre PLATE : un filet, pas de liseré dégradé, pas de relief. Une console
     d'infrastructure garde son chrome silencieux pour que la couleur, rare,
     serve au contenu. L'identité tient au logo, à l'accent et aux icônes. */
  /* FIXE, pas « sticky » : un sticky se décolle silencieusement dès qu'un
     ancêtre porte overflow ou transform - ce qui arrive dans les vues qui
     montent leur propre conteneur. `fixed` ne dépend d'aucun ancêtre.
     La barre ne prenant plus de place dans le flux, `main` la réserve via
     --hh-bar (hauteur du contenu + les deux paddings + le filet). */
  body>header{position:fixed;top:0;left:0;right:0;z-index:20;backdrop-filter:blur(10px);
    background:var(--header-bg);border-bottom:1px solid var(--line);
    /* Le fond et le filet du bas traversent l'écran, le CONTENU se cale dans le
       canal : la barre reste une barre, sans flotter au milieu du vide. */
    padding-block:var(--sp-8);
    padding-inline:max(18px,calc((100% - var(--canal,980px))/2 + var(--canal-pad,18px)));
    display:flex;align-items:center;gap:var(--sp-14)}
  .brand{display:flex;align-items:center;gap:var(--sp-6);flex:1 1 0;min-width:0}
  /* Marque « Pilote » : version compacte (3 anneaux) car sous 32 px les six
     anneaux de la version complete se referment. Neutre : elle prend --txt.
     Posée dans une TUILE (fond + filet + rayon court) : le signe se lit comme
     l'icône d'une application, pas comme un pictogramme flottant dans la barre.
     Le glyphe garde ~20 px utiles, la tuile fait la hauteur des contrôles. */
  /* La tuile de marque : fond blanc LÉGÈREMENT teinté de la couleur principale
     (le même `--chrome-bg` que les pilules — une seule recette pour une seule
     intention), filet gris clair incliné vers l'accent, et AUCUNE ombre : la
     teinte et le filet suffisent à poser le signe. */
  /* Le calage retenait la galaxie : 6 px de marge sur 40 ne lui laissaient que
     28 px, et un système d'orbites est large mais PLAT — il disparaît vite.
     Ramené à 2 px, le glyphe occupe 36 px.
     Le fond est plus clair que celui des pilules (5 % d'accent contre 12) :
     une tuile de marque n'est pas un contrôle, elle doit se faire oublier
     derrière le signe. D'où aussi un filet à opacité réduite. */
  .brand-mark{width:var(--hh-brand);height:var(--hh-brand);flex:none;padding:var(--sp-2);box-sizing:border-box;
    color:var(--txt);border-radius:var(--radius);
    /* Filet d'un demi-pixel : sur un écran à densité doublée il tombe sur un
       pixel physique et donne un trait vraiment fin. Sur un écran classique le
       navigateur l'arrondit — le filet reste dessiné, simplement pas plus fin
       qu'un pixel. Aucun risque de disparition. */
    border:.5px solid color-mix(in srgb,color-mix(in srgb,var(--accent) 14%,var(--line)) 45%,transparent);
    background:color-mix(in srgb,var(--accent) 5%,var(--card));
    box-shadow:none}
  .brand .logo{width:34px;height:34px;border-radius:var(--radius-sm);background:linear-gradient(135deg,#3a3a40,#161619);
    display:grid;place-items:center}
  .logo-mark{width:19px;height:19px;fill:none;stroke:var(--on-solid);stroke-width:2.6;stroke-linecap:round;stroke-linejoin:round}
  .brand-txt{display:flex;align-items:center;gap:var(--sp-10)}
  body>header h1{font-size:var(--fs-lg);margin:0;font-weight:var(--fw-bold);letter-spacing:var(--ls-tight)}
  body>header h1 span{color:var(--accent)}
  .env-pill{display:inline-flex;align-items:center;gap:var(--sp-6);font-size:var(--fs-xs);font-weight:var(--fw-medium);
    font-family:var(--font-mono);color:var(--mut);background:var(--card2);
    border:1px solid var(--line);padding:var(--sp-2) var(--sp-8);border-radius:var(--radius-pill)}
  .env-led{width:7px;height:7px;border-radius:50%;background:var(--ok);
    box-shadow:0 0 0 3px color-mix(in srgb,var(--ok) 25%,transparent)}
  @media (prefers-reduced-motion:no-preference){ .env-led{animation:pulse 2.4s ease-in-out infinite} }
  @keyframes pulse{0%,100%{opacity:1}50%{opacity:.45}}
  body>header .sub{color:var(--mut);font-size:var(--fs-md);flex:1}
  /* ── Système d'en-tête harmonisé ──
     Tous les contrôles d'en-tête partagent une même grammaire : hauteur 40px,
     « pilule » de regroupement identique (.island & .view-toggle), boutons-icônes
     carrés de 40px pour la paire IA (Pilote · Live), même teintes partout.
     Réglage central : --hh (hauteur contrôle) / --hr (rayon pilule) /
     --hsq (rayon des boutons carrés du centre). */
  /* `--hr-in` : rayon intérieur CONCENTRIQUE (extérieur moins le padding).
     Sans lui, chaque élément de la pilule inventait son arrondi (4 px pour les
     vues, 6 px pour la pastille) et les courbes ne se répondaient pas. */
  body>header{--hh:34px;--hr:9px;--hsq:7px;--hpad:4px;--hr-in:calc(var(--hr) - var(--hpad))}
  /* La réserve dérive des MÊMES termes que la barre (hauteur de contrôle +
     les deux paddings + le filet). Le padding était écrit en dur : la barre ne
     suivait donc pas la densité alors que la réserve, elle, la suivait — 3,2 px
     d'écart en mode aéré, et le contenu qui remontait sous la barre. */
  :root{--hh-ctl:34px;--hh-brand:36px;
    /* La barre est aussi haute que son plus grand objet : les contrôles OU la
       marque. `max()` évite d'avoir à retenir lequel gagne — agrandir la
       marque suffit, la réserve suit. */
    --hh-bar:calc(max(var(--hh-ctl),var(--hh-brand)) + var(--sp-8) * 2 + 1px)}
  body>header{--hh-ctl:34px}
  /* Réservé sur BODY et non sur `main` : `.wrap` pose déjà un padding et,
     plus spécifique, il l'emportait - le contenu passait sous la barre. */
  body{padding-top:var(--hh-bar)}
  /* Zone centrale - « island bar » flottant qui regroupe les outils (discussions,
     imprimante, alchimie, mode résultat, factory). Centrée quelles que soient les
     largeurs des zones gauche/droite (les deux côtés ont flex:1). */
  .hcenter{display:flex;align-items:center;justify-content:center;gap:var(--sp-8);flex:0 0 auto}
  /* Pilule de regroupement commune (centre + bascule de vues à droite). */
  .island,.view-toggle{display:inline-flex;align-items:center;gap:var(--sp-2);height:var(--hh);padding:var(--hpad);
    /* Le groupe doit se LIRE comme un groupe : sur fond clair, un fond à 4 %
       et un filet pâle disparaissaient dans la barre, et les boutons semblaient
       posés au hasard. Le contenant se voit, sans peser. */
    background:color-mix(in srgb,var(--txt) 5%,transparent);
    border:1px solid var(--line);border-radius:var(--hr)}
  .island>button.icon,.island>.icon{width:calc(var(--hh) - var(--hpad)*2);height:calc(var(--hh) - var(--hpad)*2);
    border:0;background:transparent;border-radius:calc(var(--hsq) - 3px);color:var(--mut);
    transition:background .15s ease,color .15s ease,transform .12s ease}
  .island>button.icon svg.ic,.island>.icon svg.ic{width:18px;height:18px}
  .island>button.icon:hover,.island>.icon:hover{background:var(--card);color:var(--txt)}
  .island>button.icon:active,.island>.icon:active{transform:scale(.94)}
  .hactions{display:flex;align-items:center;gap:var(--sp-8);flex:1 1 0;justify-content:flex-end}
  .hsep{width:1px;height:22px;background:var(--line)}
  /* Paire IA (Pilote · Live) - boutons ronds « vedette », à gauche de l'island
     centrale, dans la zone centrale (.hcenter).
     flex:none → ne se déforment jamais en ellipse quand la rangée se resserre. */
  .hcenter>.cockpit-btn{flex:none;width:var(--hh);height:var(--hh);border-radius:var(--hsq)}
  /* Pilote : c'est L'action de l'en-tête, pas une icône de plus - il porte son
     libellé et prend la forme d'une pilule. Sa géométrie vit dans 09-ai.css
     (couche `modules`, celle qui possède .brain-btn) : la poser ici serait
     écrasée par la cascade de couches. */
  .hcenter>.brain-btn{flex:none;height:var(--hh)}
  /* Pilule centrale (outils) - coins assortis aux boutons carrés qu'elle contient. */
  .hcenter .island{border-radius:calc(var(--hsq) + 2px)}
  /* CTA accent - même hauteur, coins assortis aux pilules. */
  .hactions>.primary{flex:none;height:var(--hh);border-radius:var(--hr);padding-inline:14px;font-weight:var(--fw-strong)}
  /* Bouton « Installer » PWA (cf. CDC_PWA.md, Lot 5) - caché tant que non installable. */
  .install-btn[hidden]{display:none}
  .view-toggle .vt-seg[hidden]{display:none}
  .island[hidden]{display:none}
  .install-btn svg.ic{color:var(--accent)}
  .install-btn:hover{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 8%,var(--card))}
  /* Bascule de vues (en-tête) - Accueil · Discovery · Paramètres.
     Segmented control compact : track de fond discret (effet « rail ») dérivé du
     texte → s'adapte à tout thème, + pastille active surélevée qui glisse. */
  /* ── Bascule de droite : un rail, pas une barre transparente ──
     Même grammaire que la bascule de l'accueil (.grp-seg) : un track teinté
     + un filet clair, sur lequel glisse la pastille active. Teinte plus légère
     ici (6 % contre 10 %) : posé sur l'en-tête BLANC, le même gris pesait plus
     que sur le fond de page.
     En `--card`, le groupe se confondait avec l'en-tête blanc et les trois
     boutons semblaient posés au hasard - le rail les rassemble. */
  /* Le GROUPE porte la teinte d'accent (et non plus un gris neutre) ; la
     pastille du segment actif devient claire. L'accent dit « ce rail est
     actif », le blanc dit « c'est ici que vous êtes » - deux informations,
     deux traitements, au lieu d'un accent qui servait aux deux. */
  /* `--hh`/`--hr`/`--hpad`/`--hr-in` redéclarées ici (pas seulement sur `header`) :
     le composant est aussi posé hors en-tête (Paramètres…) et n'hériterait sinon
     de rien, `header` n'étant pas un ancêtre de ces panneaux. */
  .view-toggle{--hh:34px;--hr:9px;--hpad:4px;--hr-in:calc(var(--hr) - var(--hpad));
    position:relative;gap:var(--sp-4);
    background:var(--chrome-bg);
    border:0}
  .view-toggle .vt-sep{display:none}
  /* Pastille surélevée qui glisse derrière le segment actif (positionnée + révélée en JS,
     dhSegSlide). Seul `transform` s'anime (la largeur part d'un scaleX, voir 45-view-toggle.js) :
     une transition de `width` calait sur le fil principal pendant le rendu des Paramètres.
     220 ms, courbe qui démarre franc et se pose doucement : le proprio voulait « un vrai
     projecteur qui se déplace proprement » (2026-10-08). */
  .view-toggle .vt-ind{position:absolute;top:var(--hpad);left:0;height:calc(100% - var(--hpad)*2);width:0;
    border-radius:var(--hr-in);background:var(--on-solid);
    box-shadow:var(--shadow-sm);
    opacity:0;pointer-events:none;z-index:0;transform-origin:0 0;will-change:transform;
    transition:transform .22s cubic-bezier(.25,.8,.25,1),opacity .16s}
  @media (prefers-reduced-motion:reduce){ .view-toggle .vt-ind{transition:none} }
  /* Encre de la pilule : l'accent MÊLÉ à l'encre, pas un gris neutre. Le gris
     jurait avec le fond teinté ; ce mélange donne un bleu profond en thème
     clair et son pendant clair en sombre ; et le contraste y gagne (8,9:1
     contre 6,1 en clair). Hover sans transition : demandé instantané. */
  .view-toggle .vt-seg{position:relative;z-index:1;border:0;background:transparent;color:var(--chrome-ink);
    font-weight:var(--fw-label);font-size:var(--fs-sm);padding:0 var(--sp-10);height:calc(var(--hh) - var(--hpad)*2);
    border-radius:var(--hr-in);gap:var(--sp-6);white-space:nowrap;transition:none}
  .view-toggle .vt-seg svg.ic{width:15px;height:15px;opacity:.8;transition:opacity .16s ease}
  /* Survol : une teinte de l'encre, JAMAIS le blanc du projecteur. En `--card` (blanc en
     clair, comme la pastille), le segment survolé devenait blanc d'un coup, puis ce blanc
     s'éteignait au clic pendant que la pastille arrivait : deux fonds blancs, l'effet
     d'un fond qui saute (capture du proprio, 2026-10-08). */
  .view-toggle .vt-seg:hover{color:var(--chrome-ink);background:color-mix(in srgb,var(--chrome-ink) 9%,transparent)}
  .view-toggle .vt-seg.active:hover{background:transparent}
  /* Le projecteur est TOUJOURS blanc (--on-solid), quel que soit le thème : l'encre active se fonce donc
     d'un tiers vers le noir. L'accent pur ne tenait pas sur ce blanc (bleu #3583fc : 3,62:1, mesuré au banc
     de la bascule le 2026-10-08) ; foncé, il passe 5,5:1 et plus pour toutes les teintes du nuancier.
     Décision de l'agent, révocable : revenir à var(--accent) si le proprio préfère la teinte pure. */
  .view-toggle .vt-seg.active{color:color-mix(in srgb,var(--accent) 72%,#000);font-weight:var(--fw-label)}
  .view-toggle .vt-seg.active svg.ic{opacity:1}
  @media(max-width:900px){ .view-toggle .vt-seg span{display:none} .view-toggle .vt-seg{padding:var(--sp-4) var(--sp-8)} }

  /* ── Actions logées dans la pilule (Nouvelle création · Infrastructure) ──
     La barre alignait trois objets flottants côte à côte (un CTA plein, un
     bouton nu, la pilule des vues). Tout tient maintenant dans une seule
     pilule : les actions à gauche, un filet, les vues à droite. L'indicateur
     glissant ne les vise jamais (il ne suit que les segments à `data-view`). */
  .view-toggle .vt-act{position:relative;z-index:1;display:inline-flex;align-items:center;gap:var(--sp-6);
    border:0;background:transparent;color:var(--chrome-ink);cursor:pointer;font:inherit;
    font-size:var(--fs-sm);font-weight:var(--fw-label);white-space:nowrap;
    height:calc(var(--hh) - var(--hpad)*2);padding:0 var(--sp-10);
    border-radius:var(--hr-in);transition:none}
  .view-toggle .vt-act svg.ic{width:15px;height:15px;opacity:.8}
  .view-toggle .vt-act:hover{color:var(--chrome-ink);background:var(--card)}
  .view-toggle .vt-act:hover svg.ic{opacity:1}
  .view-toggle .vt-act:focus-visible{outline:none;box-shadow:var(--focus)}
  /* Le seul aplat d'accent de la barre : créer est l'action première. */
  /* Un invité ne crée pas de création ; sans la case « pilote », pas de Pilote (CDC_INVITES I5). */
  .dh-invite .view-toggle .vt-cta{display:none}
  .view-toggle .vt-cta{background:var(--accent);color:var(--on-solid);font-weight:var(--fw-label);
    box-shadow:none}
  .view-toggle .vt-cta svg.ic{opacity:1}
  .view-toggle .vt-cta:hover{background:var(--accent-h);color:var(--on-solid)}
  .view-toggle .vt-sep{width:1px;height:16px;align-self:center;margin-inline:5px;
    background:color-mix(in srgb,var(--txt) 14%,transparent);flex:none}
  /* Libellés compacts : les actions suivent la même règle que les vues.
     Étendu à `header` : `.view-toggle` est réutilisé hors en-tête (Paramètres…)
     et ce mode « icônes seules » n'a de sens QUE dans la barre, faute de place -
     ailleurs, sans lui, le composant se comprimait en carrés en gardant son
     texte visible (rien ne l'y masquait), le libellé débordait de sa case. */
  html[data-labels="icons"] body>header .view-toggle .vt-act>span{display:none}
  /* Carrés : largeur = hauteur, contenu centré. Un padding horizontal laissait
     des rectangles d'largeurs différentes selon la largeur de chaque icône. */
  html[data-labels="icons"] body>header .view-toggle .vt-act,
  html[data-labels="icons"] body>header .view-toggle .vt-seg{
    width:calc(var(--hh) - var(--hpad)*2);padding:0;justify-content:center}
  @media(max-width:1100px){ .view-toggle .vt-act:not(.vt-cta) span{display:none}
    .view-toggle .vt-act:not(.vt-cta){padding:0 var(--sp-8)} }
  /* Libellés compacts (Paramètres › Application › Densité) : boutons d'en-tête réduits à
     leur icône, le libellé passe en infobulle (data-tooltip). */
  html[data-labels="icons"] .hactions .install-btn>span[data-i18n],
  html[data-labels="icons"] .hactions>.primary>span[data-i18n],
  html[data-labels="icons"] .hactions>button>span,
  html[data-labels="icons"] body>header .view-toggle .vt-seg>span{display:none}
  html[data-labels="icons"] .hactions .install-btn{padding-inline:9px}
  /* En mode « icônes seules », le CTA n'a plus de libellé → bouton carré (40×40),
     cohérent avec les autres contrôles d'en-tête (au lieu d'un rectangle). */
  html[data-labels="icons"] .hactions>.primary{width:var(--hh);padding-inline:0;justify-content:center}
  html[data-labels="icons"] body>header .view-toggle .vt-seg{padding:var(--sp-4) var(--sp-8)}

  /* Bouton Cockpit (« Live ») - visière maison en trait simple (currentColor), identité propre.
     Pas de fond blanc au survol : teinte accent discrète + lentille qui s'accentue. */
  .cockpit-btn{position:relative;color:var(--mut);border-color:transparent;background:transparent}
  .cockpit-btn[hidden]{display:none!important}
  .cockpit-btn svg.ic.ck-vp{width:22px;height:22px}
  .cockpit-btn .ck-vp .ck-visor{fill:none;stroke:currentColor;stroke-width:1.9;stroke-linejoin:round}
  .cockpit-btn .ck-vp .ck-strap{fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;opacity:.85}
  .cockpit-btn .ck-vp .ck-lens{fill:currentColor;stroke:none;opacity:.55;transition:opacity .18s}
  .cockpit-btn:hover{border-color:transparent;color:var(--accent);
    background:color-mix(in srgb,var(--accent) 12%,transparent)}
  .cockpit-btn:hover .ck-vp .ck-lens{opacity:1}
  .cockpit-btn .ck-dot{position:absolute;top:6px;right:6px;width:6px;height:6px;border-radius:50%;
    background:transparent;transition:background .18s}
  .cockpit-btn.active{color:var(--accent);border-color:transparent;
    background:color-mix(in srgb,var(--accent) 16%,transparent)}
  .cockpit-btn.active .ck-vp .ck-lens{opacity:1}
  /* Pastille « en direct » : visible + pulsation seulement quand la fenêtre Cockpit est ouverte. */
  .cockpit-btn.active .ck-dot{background:var(--ok);box-shadow:0 0 0 2px var(--card);animation:ckPulse 1.6s ease-in-out infinite}
  @keyframes ckPulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.5;transform:scale(.78)}}
  @media(prefers-reduced-motion:reduce){ .cockpit-btn.active .ck-dot{animation:none} }
  @media(max-width:680px){ body>header .sub,.env-pill{display:none} }
  /* Téléphone : « Installer » garde son icône (nom et infobulle restent) ; avec son libellé, la barre
     dépassait de 6 px à 375 px et rognait le segment Paramètres (banc de la bascule, 2026-10-08). Le
     bouton n'apparaît que là où le navigateur propose l'installation (Chrome Android, pas Safari). */
  @media(max-width:480px){ body>header .install-btn>span{display:none} }

  /* ── Canal central ──
     Le contenu vit dans une colonne bornée, tenue par un filet de chaque côté
     qui court du haut de la page jusqu'en bas : sur un écran large, une rangée
     étalée sur 1900 px éloigne le nom d'une création de ses environnements au
     point qu'il faut balayer des yeux pour relier les deux. L'en-tête se cale
     sur la MÊME colonne (voir `header` plus haut) : les deux textes s'alignent.
     `--canal` est la largeur totale, bordures comprises (box-sizing: border-box). */
  /* 2026-10-16 (proprio : « les marges sur les côtés sont trop grandes, divise-les par deux ») : sur un écran de 1 470 px,
     245 px de marge par côté avec 980 ; 1 220 en laisse 125. La densité suit (Paramètres › Dispositions › Densité) : Compact
     élargit encore le canal (1 340), Aérée le resserre (1 100) ; le rembourrage du canal suit le pas de la trame (18 px en Normale). */
  :root{--canal:1220px;--canal-pad:calc(var(--sp-u) * 9);--wrap-pad-y:16px}
  html[data-density="compact"]{--canal:1340px} html[data-density="aere"]{--canal:1100px}
  /* La reserve verticale vient de --hh-bar, le terme qui SERT deja a decaler le
     body. `--header-h` n'a jamais ete defini nulle part : le repli de 51 px
     sous-estimait la barre de 5 px, l'application debordait donc en permanence
     d'une poignee de pixels et l'en-tete comme le rail des Parametres se
     decollaient au moindre coup de molette. Un seul terme, plus de repli. */
  .wrap{max-width:var(--canal);margin:0 auto;padding:var(--wrap-pad-y) var(--canal-pad);
    border-inline:1px solid var(--line);
    min-height:calc(100dvh - var(--hh-bar))}
  .grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(440px,1fr));gap:var(--sp-14)}
  @media(max-width:520px){ .grid{grid-template-columns:1fr} }

  /* ── Carte projet ── */
  .card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;
    display:flex;flex-direction:column}
  .ptop{padding:var(--sp-10) var(--sp-14);border-bottom:1px solid var(--line);display:flex;align-items:center;gap:var(--sp-10)}
  .ptop h2{font-size:var(--fs-base);margin:0;flex:1;font-weight:var(--fw-strong);letter-spacing:-.01em}
  .ver{font-size:var(--fs-sm);color:var(--mut);font-variant-numeric:tabular-nums;background:var(--bg2);
    border:1px solid var(--line);padding:var(--sp-2) var(--sp-8);border-radius:var(--radius-pill)}
  .badge{font-size:var(--fs-xs);padding:var(--sp-2) var(--sp-8);border-radius:var(--radius-pill);border:1px solid var(--line);color:var(--mut);text-transform:lowercase}

  .envs{padding:var(--sp-8) var(--sp-10);display:flex;flex-direction:column;gap:var(--sp-6)}
  .env{background:var(--card2);border:1px solid var(--line);border-radius:var(--radius);padding:var(--sp-8) var(--sp-10)}
  .ehead{display:flex;align-items:center;gap:var(--sp-8);flex-wrap:wrap}
  /* Étiquette d'environnement. La couleur du type arrive en `--k` (posée en
     ligne par le JS) : elle TEINTE l'étiquette au lieu de la remplir - un
     tableau de bord d'infrastructure se lit d'un coup d'œil parce que la
     couleur y est rare, pas parce qu'elle est partout. Même grammaire que
     .ov-er-pill : point + fond à 13 %. */
  .etag{--k:var(--mut);display:inline-flex;align-items:center;gap:var(--sp-4);
    font-size:var(--fs-2xs);font-weight:var(--fw-bold);padding:var(--sp-2) 0;border-radius:var(--radius-sm);
    text-transform:uppercase;letter-spacing:.04em;
    color:var(--k);background:none;
    border:0}   /* sans filet (le proprio, 2026-10-18 : « retire la bordure »), puis sans fond (2026-11-02 : « supprime la couleur de fond, garde la couleur du texte ») : la teinte du texte dit le type */
  .etag::before{content:none}   /* sans point : le libellé et sa teinte disent le type (le proprio, 2026-10-18 : « retire le cercle dans les badges ») */
  /* Les couleurs de type (`--k`) sont calibrées pour le fond sombre : posées
     telles quelles sur du blanc, elles délavent. On fonce le texte et on
     éclaircit le fond, pour tenir le contraste dans les deux thèmes. */
  html[data-theme=light] .etag{color:color-mix(in srgb,var(--k) 72%,#000);background:none}
  .ename{font-weight:var(--fw-strong)}
  .edef{font-size:var(--fs-2xs);color:var(--ok);border:1px solid var(--ok);border-radius:var(--radius-sm);padding:var(--sp-1) var(--sp-6);font-weight:var(--fw-strong)}
  .eurl{font-size:var(--fs-sm);color:var(--mut);margin:var(--sp-6) 0;word-break:break-all;font-family:var(--font-mono)}
  .miss{color:var(--warn);font-size:var(--fs-sm);margin:var(--sp-4) 0;display:flex;gap:var(--sp-6);align-items:flex-start}
  .pacts{margin-left:auto;display:flex;gap:var(--sp-6)}

  .acts{display:flex;gap:var(--sp-6);flex-wrap:wrap;margin-top:var(--sp-8)}
  button{font:inherit;font-size:var(--fs-md);border:1px solid var(--line);background:var(--card);color:var(--txt);
    padding:var(--sp-6) var(--sp-12);border-radius:var(--radius-sm);cursor:pointer;font-weight:var(--fw-medium);display:inline-flex;align-items:center;gap:var(--sp-6)}
  button:hover{border-color:var(--mut2);background:var(--line2)}
  /* 2026-10-16 : un aplat sous une encre blanche prend --accent-plein (F2, CDC_CONFIGURATION_SOLUTION_2) : en clair il vaut l'accent,
     en sombre il s'assombrit assez pour l'encre (le violet par défaut donnait 3,99:1 ; vu par le banc de la fiche de stockage). */
  button.primary{background:var(--accent-plein);border-color:var(--accent-plein);color:var(--on-solid)}
  button.primary:hover{background:color-mix(in srgb,var(--accent-plein) 88%,#000);border-color:color-mix(in srgb,var(--accent-plein) 88%,#000)}
  button.danger{border-color:color-mix(in srgb,var(--err) 40%,var(--line));color:var(--err);background:transparent}
  button.danger:hover{background:var(--err);color:var(--on-solid);border-color:var(--err)}
  button.mini{padding:var(--sp-4) var(--sp-8);font-size:var(--fs-sm)}
  /* U2 - .icon découplé du tag <button> : même rendu sur a/span/div (usages JS).
     :where() = spécificité 0 → n'écrase jamais les variantes existantes (.cockpit-btn,
     .brain-btn, .island>…) ; sur <button>, le socle button{} ci-dessus reprend la main. */
  :where(.icon){font:inherit;font-size:var(--fs-md);border:1px solid var(--line);background:var(--card);
    color:var(--txt);cursor:pointer;font-weight:var(--fw-medium);display:inline-flex;align-items:center;
    text-decoration:none;user-select:none}
  :where(.icon:hover){border-color:var(--mut2);background:var(--line2)}
  button.icon,.icon{padding:var(--sp-6);width:34px;height:34px;justify-content:center;border-radius:var(--radius-sm)}
  button:disabled{opacity:.4;cursor:not-allowed}
  /* 2026-11-04 (ICONES L1, modèle « Point d'accent ») : le trait vaut --ico-trait (1,5) en pixels D'ÉCRAN à toutes les
     tailles, par non-scaling-stroke sur les formes (la propriété ne s'hérite pas) ; une forme qui porte son propre
     stroke-width le garde, compté lui aussi à l'écran. 2 sur la grille jusque-là : 1,33 px à 16 px, 2 px à 24. */
  svg.ic{width:16px;height:16px;flex:none;stroke:currentColor;fill:none;stroke-width:var(--ico-trait,1.5);
    stroke-linecap:round;stroke-linejoin:round;display:inline-block;vertical-align:-.2em}
  svg.ic :where(path,circle,rect,line,polyline,polygon,ellipse){vector-effect:non-scaling-stroke}
  /* Duotone maison : surface remplie en currentColor à --ic-duo, posée derrière le trait. Éteinte depuis le
     2026-11-04 (--ic-duo:0, 01-tokens) ; la règle reste, le jeton la rallume (D2, révocable). */
  svg.ic .du{fill:currentColor;fill-opacity:var(--ic-duo,0);stroke:none}
  /* D3 : le détail d'accent repasse à l'encre là où la couleur dirait autre chose : sur un aplat d'accent (bouton principal),
     dans un élément déjà coloré parce qu'actif, choisi ou survolé, désactivé, dans une infobulle. Un :hover sur un ancêtre
     quelconque (body) éteindrait toute la page, et un panneau « .active » toutes ses icônes : seuls les contrôles le portent. */
  :where(button, a, [role=button], [role=tab], [role=option], [role=menuitem], [role=menuitemradio], li):where(.primary, .on, .active, .sel,
    [aria-pressed="true"], [aria-selected="true"], [aria-current]:not([aria-current="false"]), :hover, :disabled, [aria-disabled="true"]),
    :where([role=tooltip], .tooltip, .tip){--ico-accent:currentColor}
  .mini svg.ic{width:14px;height:14px}
  /* Icônes posées dans d'anciens « slots » de glyphe (onglets de section, notes, puces) :
     elles épousent la taille du conteneur au lieu du 16px par défaut. */
  .at-nav-ic svg.ic,.at-cat-ic svg.ic,.smed-nav-ic svg.ic,.fig-nav-ic svg.ic,
  .wiz-feat-ic svg.ic,.bc-ico svg.ic,.cmp-stars svg.ic,.dsc-th-chan svg.ic{
    width:1.05em;height:1.05em;vertical-align:-.15em}
  /* Titres : l'icône épouse la taille du titre */
  .fx-title svg.ic,.dsc-title svg.ic,.alch-title svg.ic{width:1em;height:1em;vertical-align:-.1em}
  /* Badges/slots à taille fixe des modules Discussions/Alchimie */
  .dsc-av-ch svg.ic{width:13px;height:13px}
  .dsc-thread-empty-ic svg.ic,.dsc-alch-g svg.ic,.dsc-att-ic svg.ic,.alch-chip-g svg.ic{
    width:1em;height:1em;vertical-align:-.12em}
  .alch-card-flask svg.ic{width:20px;height:20px}
  .alch-flask svg.ic{width:1.05em;height:1.05em;vertical-align:-.12em}

  .st{display:block;font-size:var(--fs-md);margin-top:var(--sp-8);min-height:1px}
  .st-ok{color:var(--ok)} .st-warn{color:var(--warn)} .st-err{color:var(--err)}
  .log{margin-top:var(--sp-8);font-family:var(--font-mono);font-size:var(--fs-xs);white-space:pre-wrap;
    background:var(--bg2);border:1px solid var(--line);border-radius:var(--radius-sm);padding:var(--sp-10);max-height:200px;overflow:auto;display:none}
  .addbar{padding:0 var(--sp-12) var(--sp-14);margin-top:auto}
  a{color:var(--link)}
  .small{font-size:var(--fs-sm);color:var(--mut)}

  /* ── État vide ── */
  .empty{grid-column:1/-1;text-align:center;padding:var(--sp-56) var(--sp-20);border:1px dashed var(--line);
    border-radius:var(--radius);background:var(--card2)}
  .empty h2{margin:0 0 var(--sp-6);font-size:var(--fs-lg)}
  .empty p{color:var(--mut);margin:0 0 var(--sp-18)}
  /* L'accueil sans dossier (2026-10-19, 11-render.js homeVideHtml) : l'illustration et le premier geste, puis l'assistant. */
  .home-vide{grid-column:1/-1;display:flex;flex-direction:column;gap:var(--sp-16);max-width:760px;margin:var(--sp-24) auto 0;width:100%}
  .hv-tete{text-align:center;padding:var(--sp-40) var(--sp-20) var(--sp-32);border:1px solid var(--line);border-radius:var(--radius);
    background:var(--card)}
  .hv-tete h2{margin:var(--sp-14) 0 var(--sp-6);font-size:var(--fs-xl);letter-spacing:var(--ls-tight)}
  .hv-tete p{color:var(--mut);margin:0 auto var(--sp-20);max-width:460px;line-height:var(--lh-normal)}
  .hv-svg{width:260px;max-width:100%;height:auto;display:block;margin:0 auto}
  .hv-halo{fill:color-mix(in srgb,var(--accent) 8%,transparent)}
  .hv-orbite{fill:none;stroke:color-mix(in srgb,var(--accent) 30%,transparent);stroke-width:1.2;stroke-dasharray:3 5}
  .hv-astre{fill:var(--accent)} .hv-astre-p{fill:color-mix(in srgb,var(--accent) 55%,var(--card))}
  .hv-ombre{fill:color-mix(in srgb,var(--txt) 7%,transparent)}
  .hv-dos{fill:color-mix(in srgb,var(--accent) 22%,var(--card2));stroke:color-mix(in srgb,var(--accent) 40%,var(--line));stroke-width:1.2}
  .hv-feuille{fill:var(--card);stroke:var(--line);stroke-width:1.2}
  .hv-ligne{stroke:color-mix(in srgb,var(--mut2) 55%,transparent);stroke-width:3;stroke-linecap:round;fill:none}
  .hv-bloc{fill:color-mix(in srgb,var(--accent) 14%,var(--card));stroke:color-mix(in srgb,var(--accent) 35%,transparent);stroke-width:1}
  .hv-face{fill:color-mix(in srgb,var(--accent) 12%,var(--card));stroke:color-mix(in srgb,var(--accent) 45%,var(--line));stroke-width:1.2}
  .hv-plus-fond{fill:var(--accent)}
  .hv-plus{stroke:var(--on-solid);stroke-width:2.4;stroke-linecap:round}
  .hv-eclat{stroke:color-mix(in srgb,var(--accent) 60%,transparent);stroke-width:1.6;stroke-linecap:round}
  .hv-assistant{padding:var(--sp-20);border:1px solid var(--line);border-radius:var(--radius);background:var(--card)}
  .hv-a-tete{display:flex;gap:var(--sp-14);align-items:flex-start}
  .hv-a-ic{flex:none;width:40px;height:40px;border-radius:var(--radius-sm);display:grid;place-items:center;
    background:color-mix(in srgb,var(--accent) 12%,var(--card2));color:var(--accent)}
  .hv-a-ic svg{width:20px;height:20px}
  .hv-a-tete h3{margin:0 0 var(--sp-4);font-size:var(--fs-md);font-weight:var(--fw-strong)}
  .hv-a-tete p{margin:0;color:var(--mut);font-size:var(--fs-sm);line-height:var(--lh-normal)}
  .hv-a-saisie{display:flex;gap:var(--sp-8);margin-top:var(--sp-16)}
  .hv-a-saisie input{flex:1;min-width:0}
  .hv-a-exemples{display:flex;flex-wrap:wrap;gap:var(--sp-6);margin-top:var(--sp-10)}
  .hv-a-ex{border:1px solid var(--line);background:var(--card2);color:var(--mut);font:inherit;font-size:var(--fs-sm);
    padding:var(--sp-4) var(--sp-10);border-radius:var(--radius-pill);cursor:pointer;text-align:left}
  .hv-a-ex:hover{color:var(--txt);border-color:color-mix(in srgb,var(--accent) 40%,var(--line))}
  @media (max-width:640px){.hv-a-saisie{flex-direction:column}.hv-tete{padding:var(--sp-28) var(--sp-16) var(--sp-24)}}

  /* ── Vue liste ── */
  .section-title{font-size:var(--fs-xl);font-weight:var(--fw-bold);margin:0 0 var(--sp-4);letter-spacing:var(--ls-tight)}
  .section-sub{color:var(--mut);margin:0 0 var(--sp-16);font-size:var(--fs-base)}
  .plist{display:flex;flex-direction:column;gap:var(--sp-6);max-width:none}
  /* ── Carte de création ─────────────────────────────────────────────────
     Densité assumée : une création tient sur UNE ligne. Tout ce qui poussait
     la hauteur a été mis à plat - les environnements en pastilles alignées au
     lieu de trois lignes empilées, l'aperçu réduit, l'étiquette au-dessus de
     l'aperçu supprimée (elle répétait la pastille d'environnement).
     Chaque zone borne son contenu (`min-width:0` + ellipse) : sinon un nom long
     pousse par-dessus l'aperçu au lieu de se réduire. */
  .prow{display:flex;align-items:center;gap:var(--sp-12);width:100%;min-height:42px;text-align:left;font:inherit;
    background:var(--card);border:1px solid var(--line2);border-radius:var(--radius-sm);
    padding:var(--sp-4) var(--sp-10);cursor:pointer;
    transition:border-color var(--dur-1),background var(--dur-1)}
  .prow:hover{border-color:color-mix(in srgb,var(--accent) 50%,var(--line));
    background:color-mix(in srgb,var(--accent) 4%,var(--card))}
  .prow:focus-visible{outline:none;box-shadow:var(--focus)}

  .prow-id{flex:1;min-width:0;display:flex;align-items:center;gap:var(--sp-8)}
  .prow-txt{min-width:0;display:flex;align-items:center;gap:var(--sp-8)}
  .prow .pname{font-weight:var(--fw-strong);font-size:var(--fs-md);letter-spacing:-.01em;line-height:var(--lh-tight);
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

  /* Compléments actifs : six icônes TEINTÉES par rangée faisaient une quinzaine
     de couleurs concurrentes dans la liste, pour une information d'identité -
     jamais d'état. Elles se tiennent en gris et ne reprennent leur teinte qu'au
     survol de LEUR rangée, là où l'œil s'est déjà posé. La couleur arrive en
     `--pc` (posée en ligne par le JS), jamais en `color:` : sinon le style en
     ligne battrait la règle de repos. */
  .pplugs{display:flex;align-items:center;gap:var(--sp-2);flex:none}
  .pplug{display:inline-flex;align-items:center;justify-content:center;width:17px;height:17px;
    border-radius:var(--radius-sm);color:var(--mut2);transition:color var(--dur-1)}
  .pplug svg.ic{width:12px;height:12px;color:currentColor}
  .prow:hover .pplug{color:var(--pc,var(--accent))}
  .pplug-more{font-size:var(--fs-2xs);font-weight:var(--fw-strong)}
  .prow:hover .pplug-more{color:var(--mut)}

  /* Sort d'une création (H1) : un badge sobre, en gris comme les compléments -
     c'est une information de registre, pas une alerte. « archivée » est barré
     pour qu'on ne la prenne pas pour un chantier. */
  .psort{flex:none;font-size:var(--fs-2xs);font-weight:var(--fw-strong);text-transform:uppercase;letter-spacing:.04em;
    padding:1px 6px;border-radius:var(--radius-sm);border:1px solid var(--line);color:var(--mut)}
  .psort-archivee{text-decoration:line-through;opacity:.7}

  /* ── Bande d'environnements ──
     Une seule chose est à faire d'un coup d'œil : repérer ce qui est EN RETARD
     sur la version locale. Le tri (JS) met ces cellules en tête ; le style leur
     donne le seul relief de la bande - fond teinté et version en clair. Tout le
     reste se tait : « à jour » n'est qu'un mot gris, « jamais
     publié » s'estompe, et au-delà de trois cellules un jeton « +N » ramasse
     la queue de liste. Une création à dix environnements tient donc sur la même
     ligne qu'une création à deux.
     Le fond ne s'allume que pour un ÉTAT : la couleur reste rare et signifiante.
     Un filet « | » entre deux cellules (le proprio, 2026-10-25 : « entre chaque badge, mets un séparateur ») :
     sans point ni bordure, les mots se suivaient sans dire où finit l'un. Posé dans le blanc entre elles,
     hors du fond ambré d'une cellule en retard. */
  .prow-envs{flex:none;min-width:0;display:flex;align-items:center;gap:var(--sp-8);flex-wrap:wrap;
    justify-content:flex-end}
  .penv+.penv::before{content:'';position:absolute;inset-inline-start:calc(-1 * var(--sp-4) - .5px);
    top:4px;bottom:4px;width:1px;background:var(--line)}
  .penv{position:relative;display:inline-flex;align-items:center;gap:var(--sp-4);height:19px;padding:0 var(--sp-6);
    border:0;background:none;border-radius:var(--radius-sm);
    font-size:var(--fs-2xs);line-height:var(--lh-flat);white-space:nowrap}
  /* Ni point ni bordure (le proprio, 2026-10-25, sur capture : « pas de bordure aux badges, et retire les
     cercles ») : le mot et son poids disent l'état (gras foncé = publié, estompé = jamais), le fond ambré dit
     le retard. Le point de couleur du type, son halo vert et le cercle vide du « jamais » redoublaient le mot. */
  .penv-k{font-weight:var(--fw-bold);letter-spacing:.05em;color:var(--mut)}
  .penv-v{font-family:var(--font-mono);font-size:var(--fs-2xs);color:var(--txt);font-variant-numeric:tabular-nums}
  .penv-w{display:inline-flex;flex:none}
  .penv svg.ic{width:10px;height:10px;color:var(--warn);flex:none}

  /* En retard : LA cellule qui demande une action. C'est la seule à porter un
     fond, et donc la seule que l'œil trouve sans chercher. */
  .penv-behind{background:color-mix(in srgb,var(--warn) 13%,transparent)}
  .penv-behind .penv-k{color:color-mix(in srgb,var(--warn) 62%,var(--txt))}
  .penv-behind .penv-v{color:color-mix(in srgb,var(--warn) 55%,var(--txt))}
  /* Le chevron dit « une version attend » sans coûter un mot. */
  .penv-behind::after{content:'';width:0;height:0;flex:none;
    border-inline:3.2px solid transparent;border-bottom:4.4px solid currentColor;
    color:color-mix(in srgb,var(--warn) 70%,var(--txt))}
  /* Version en ligne illisible : ni alarme ni feu vert. */
  .penv-unknown .penv-v{color:var(--mut2)}
  /* Jamais publié : présent mais effacé - il n'a rien à jouer dans la liste. */
  /* Sur ses enfants, pas sur la cellule : le filet qui la précède garde sa teinte. */
  .penv-never>*{opacity:.42}
  .penv-never .penv-k{font-weight:var(--fw-strong)}
  /* Débordement : un jeton neutre, jamais un signal. L'infobulle porte le détail. */
  .penv-more{font-weight:var(--fw-strong);color:var(--mut2);background:color-mix(in srgb,var(--txt) 6%,transparent);
    padding:0 var(--sp-6);font-variant-numeric:tabular-nums}
  .prow:hover .penv-more{color:var(--mut);background:color-mix(in srgb,var(--txt) 10%,transparent)}
  /* …sauf s'il cache des retards : le compteur reprend alors la teinte d'alerte,
     pour ne pas faire passer du travail en attente pour de la queue de liste. */
  .penv-more-late,.prow:hover .penv-more-late{background:color-mix(in srgb,var(--warn) 13%,transparent);
    color:color-mix(in srgb,var(--warn) 62%,var(--txt))}

  /* Col 3 : le résumé du dossier (vue Détaillée) + chevron. Plus de maquette de tablette avec la page du site dans un cadre
     (2026-10-25, le proprio : « retire les fenêtres de rendu sur la droite, ça consomme trop ») : 26 dossiers, 26 pages chargées. */
  .pcol3{flex:none;display:flex;align-items:center;gap:var(--sp-10)}
  .prow-resume{display:none;flex-wrap:wrap;justify-content:flex-end;gap:var(--sp-4) var(--sp-10);max-width:420px;
    font-size:var(--fs-xs);color:var(--mut2);font-variant-numeric:tabular-nums}
  html[data-card-view="detailed"] .prow-resume{display:flex}
  .prow-resume b{color:var(--txt);font-weight:var(--fw-medium)}
  /* À droite, une colonne (le proprio, 2026-10-25 : « en deux lignes : les badges d'abord, puis les données des apps du
     Studio ; les cartes seront plus grandes ») : les badges d'environnement, puis le résumé, qui passe à la ligne s'il le faut.
     En vue Carte, le résumé est caché : la colonne n'a que les badges, comme avant. */
  .prow-droite{flex:none;min-width:0;display:flex;flex-direction:column;align-items:flex-end;gap:var(--sp-4)}
  html[data-card-view="detailed"] .prow{padding-block:var(--sp-8)}
  .prow-resume .vide{font-style:italic}
  .prow .chev{color:var(--mut2);flex:none;opacity:0;
    transition:transform var(--dur-1),color var(--dur-1),opacity var(--dur-1)}
  .prow .chev svg.ic{width:14px;height:14px}
  .prow:hover .chev,.prow:focus-visible .chev{color:var(--accent);opacity:1;transform:translateX(2px)}

  /* Écran étroit : l'aperçu coûte un quart de la largeur pour peu d'information. */
  @media (max-width:640px){
    .prow{gap:var(--sp-10);padding:var(--sp-6) var(--sp-10);flex-wrap:wrap}
    html[data-card-view] .prow-resume{display:none}   /* placée après la règle Détaillée, même poids : elle l'emporte */
    /* Écran étroit : la bande passe sous le nom, sur toute la largeur. */
    .prow-droite{width:100%;order:3;align-items:flex-start}
    .prow-envs{width:100%;justify-content:flex-start;gap:var(--sp-8)}   /* la place du filet « | » */
  }

  /* « Carte » et « Ligne » ne se distinguaient plus (2026-10-25, le proprio : « unifie car c'est la même chose ») : un seul
     affichage simple ; un ancien réglage « line » est ramené à « card » (03-settings.js). */
  /* Icône projet */
  .picon{display:block;position:relative;width:26px;height:26px;border-radius:var(--radius-sm);overflow:hidden;
    border:1px solid var(--line);background:var(--card2)}
  .picon img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;background:var(--paper)}
  .picon-mono{position:absolute;inset:0;display:grid;place-items:center;color:var(--on-solid);font-weight:var(--fw-bold);font-size:var(--fs-sm)}
  .ptop .picon{width:34px;height:34px}
  .pill{display:inline-flex;align-items:center;gap:var(--sp-4);padding:var(--sp-2) var(--sp-8);border-radius:var(--radius-pill);
    border:1px solid var(--line);font-size:var(--fs-xs)}
  .pill.warn{color:var(--warn);border-color:var(--warn)}
  .pill.warn svg.ic{width:12px;height:12px}

  /* ── Vue détail ── */
  .back{margin-bottom:var(--sp-18);color:var(--mut);border:0;background:transparent;box-shadow:none;padding-left:0}   /* 2026-10-15 (proprio) : un retour en texte, ni bordure ni fond */
  .back:hover,.back:focus-visible{color:var(--txt);background:transparent;box-shadow:none}
  .back:hover{color:var(--txt)}
  .detail{max-width:840px}

  /* ── Split view : le contenu, sur toute la largeur ──
     Le panneau « Vue d'ensemble » de droite a été retiré : il redisait ce que
     les rangées portent déjà (état des environnements, version, action), au
     prix d'un tiers de la largeur et d'un sondage toutes les 30 secondes. */
  .split{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--sp-24);align-items:start}
  .col-main{min-width:0}
  .col-profile[hidden]{display:none!important}

  /* ── Vue d'ensemble (panneau de droite) ─────────────────────────────────
     Même vocabulaire que la liste de gauche : rangées basses, une seule teinte
     d'accent, la couleur réservée à ce qui demande une action. */
  .report{background:var(--card);border:1px solid var(--line2);border-radius:var(--radius);overflow:hidden}
  .report-head{padding:var(--sp-10) var(--sp-14);border-bottom:1px solid var(--line2);display:flex;align-items:center;gap:var(--sp-8)}
  .report-head h2{font-size:var(--fs-md);margin:0;flex:1;font-weight:var(--fw-strong);display:flex;align-items:center;gap:var(--sp-8);
    letter-spacing:-.01em}
  .report-head .led{width:7px;height:7px;border-radius:50%;background:var(--ok);
    box-shadow:0 0 0 3px color-mix(in srgb,var(--ok) 20%,transparent)}
  .report-head .led.pending{background:var(--warn);box-shadow:0 0 0 3px color-mix(in srgb,var(--warn) 20%,transparent)}

  /* Indicateurs : tuiles plates, chiffres de même couleur. L'ambre n'apparaît
     que sur ce qui appelle une action. */
  .kpis{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-1);background:var(--line2);
    border-bottom:1px solid var(--line2)}
  .kpi{background:var(--card);padding:var(--sp-10) var(--sp-14)}
  .kpi .n{font-size:var(--fs-lg);font-weight:var(--fw-strong);font-variant-numeric:tabular-nums;line-height:1.15;
    letter-spacing:var(--ls-tight);color:var(--txt)}
  .kpi .n-txt{font-size:var(--fs-md);font-weight:var(--fw-strong);padding-top:var(--sp-4);letter-spacing:var(--ls-none)}
  .kpi .l{font-size:var(--fs-2xs);color:var(--mut2);margin-top:var(--sp-2);line-height:var(--lh-snug)}
  .kpi.warn .n{color:var(--warn)}

  .report-body{padding:var(--sp-10);display:flex;flex-direction:column;gap:var(--sp-6);max-height:62vh;overflow:auto}
  .report-empty{padding:var(--sp-24) var(--sp-14);text-align:center;color:var(--mut2);font-size:var(--fs-sm)}
  .report-empty .led{display:inline-block;margin-bottom:var(--sp-8)}

  /* Une création en attente : en-tête cliquable + une ligne par environnement. */
  /* flex:none — le conteneur est borné (max-height + overflow) : sans cela les
     items se COMPRESSENT au lieu de faire défiler, et `overflow:hidden` rogne
     leurs lignes d'environnement. C'est ce qui masquait les actions. */
  .ritem{flex:none;border:1px solid var(--line2);border-radius:var(--radius-sm);overflow:hidden}
  .ritem .rh{display:flex;align-items:center;gap:var(--sp-8);padding:var(--sp-6) var(--sp-8);background:transparent;
    border-bottom:1px solid var(--line2);cursor:pointer;transition:background var(--dur-1)}
  .ritem .rh:hover{background:color-mix(in srgb,var(--accent) 5%,transparent)}
  .ritem .rh .picon{width:22px;height:22px;border-radius:var(--radius-sm)}
  .ritem .rh .picon-mono{font-size:var(--fs-xs)}
  .ritem .rname{font-weight:var(--fw-strong);font-size:var(--fs-sm);flex:1;min-width:0;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .ritem .rh .badge{font-size:var(--fs-2xs);color:var(--mut2);padding:var(--sp-1) var(--sp-6);border-radius:var(--radius-pill);
    border:1px solid var(--line2)}
  .renv{display:flex;align-items:center;gap:var(--sp-8);padding:var(--sp-6) var(--sp-8)}
  .renv+.renv{border-top:1px solid var(--line2)}
  .renv .etag{display:inline-flex;align-items:center;font-size:8.5px;font-weight:var(--fw-bold);letter-spacing:.05em;
    color:var(--on-solid);border-radius:var(--radius-pill);padding:var(--sp-2) var(--sp-6);text-transform:uppercase;flex:none;white-space:nowrap}
  .renv .rinfo{flex:1;min-width:0;font-size:var(--fs-xs);color:var(--mut);font-variant-numeric:tabular-nums;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .renv .rinfo b{color:var(--txt);font-weight:var(--fw-strong)}
  .renv .stat-update{color:var(--warn)} .renv .stat-never{color:var(--mut2)} .renv .stat-online{color:var(--ok)}
  .renv button{padding:var(--sp-2) var(--sp-8);font-size:var(--fs-xs);flex:none}
  .renv button svg.ic{width:11px;height:11px}
  .verflow{font-family:var(--font-mono)}

  /* ── Environnements : vue liste ── */
  .env-list-view{padding:var(--sp-16) var(--sp-20) var(--sp-24)}
  .env-list-hd{display:flex;align-items:center;justify-content:space-between;
    margin-bottom:var(--sp-20);gap:var(--sp-12);padding-bottom:var(--sp-14);border-bottom:1px solid var(--line)}
  .env-grid{display:flex;flex-direction:column;gap:var(--sp-10)}
  .env-card{display:flex;align-items:stretch;background:var(--card);border:1px solid var(--line);
    border-radius:var(--radius);overflow:hidden;cursor:pointer;width:100%;text-align:left;
    transition:border-color .15s,box-shadow .15s,background .15s}
  .env-card:hover,.env-card:focus{outline:none;border-color:var(--accent);
    box-shadow:0 0 0 1px var(--accent) inset,0 3px 10px rgba(0,0,0,.07)}
  .ec-stripe{width:4px;flex:none}
  .ec-body{flex:1;padding:var(--sp-12) var(--sp-16);min-width:0}
  .ec-head{display:flex;align-items:center;gap:var(--sp-8);flex-wrap:wrap}
  .ec-name{font-weight:var(--fw-strong);font-size:var(--fs-base)}
  .ec-miss-ic{color:var(--warn);display:inline-flex;opacity:.85}
  .ec-url{font-size:var(--fs-sm);color:var(--mut);font-family:var(--font-mono);
    margin:var(--sp-4) 0 var(--sp-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .ec-foot{margin-top:var(--sp-1)}
  .ec-st{font-size:var(--fs-sm);font-weight:var(--fw-strong)}
  .ec-st-ok{color:var(--ok)} .ec-st-warn{color:var(--warn)} .ec-st-muted{color:var(--mut)} .ec-st-err{color:var(--err)}
  .ec-st svg.ic{width:12px;height:12px;vertical-align:-1px}
  .env-card-vise{outline:2px solid var(--accent);outline-offset:2px}
  /* Un seul cadre pour la liste, des séparateurs entre les environnements (2026-10-25, le proprio : « une bordure qui englobe et
     des séparateurs entre les environnements ») ; le liseré de couleur de chaque environnement reste. */
  .env-liste{gap:0;border:.5px solid var(--line);border-radius:var(--radius);overflow:hidden;background:var(--card)}
  .env-liste>.env-card{border:0;border-radius:0;box-shadow:none}
  .env-liste>.env-card+.env-card{border-top:.5px solid var(--line2)}
  .env-liste>.env-card:hover,.env-liste>.env-card:focus{box-shadow:none;background:var(--card2)}
  .env-liste>.env-glisse{opacity:.4}   /* la ligne qu'on glisse (12f-env-ordre.js, 2026-11-04) */
  .env-list-view .inst-dossier-sec{margin:0 0 var(--sp-20)}   /* la carte où mène une ligne de la Vue d'ensemble (2026-10-18) */
  .ec-arr{display:flex;align-items:center;padding:0 var(--sp-14);color:var(--mut);opacity:.5}
  .env-empty{padding:var(--sp-32) var(--sp-20);text-align:center;background:var(--bg2);
    border:1px dashed var(--line);border-radius:var(--radius);color:var(--mut)}

  /* ── Sélecteur de type d'environnement ── */
  .env-kind-picker{display:flex;flex-direction:column;gap:var(--sp-10)}
  .ekp-card{display:flex;flex-direction:column;gap:var(--sp-4);text-align:left;
    background:var(--bg2);border:1.5px solid var(--line);border-radius:var(--radius);
    padding:var(--sp-16) var(--sp-18);cursor:pointer;transition:border-color .15s,box-shadow .15s}
  .ekp-card:hover{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent) inset}
  .ekp-icon{font-size:var(--fs-lg);margin-bottom:var(--sp-4);display:inline-flex;color:var(--accent)}
  .ekp-title{font-weight:var(--fw-strong);font-size:var(--fs-base)}
  .ekp-sub{font-size:var(--fs-sm);color:var(--mut);line-height:1.4}

  /* ── Bac à sable : hero ── */
  .sbx-hero{display:flex;align-items:center;gap:var(--sp-14);padding:var(--sp-14) var(--sp-16) var(--sp-14) var(--sp-20);
    background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
    margin:0 0 var(--sp-16);border-left:3px solid var(--ec,var(--accent))}
  .sbx-hero-icon{font-size:var(--fs-2xl);flex:none;color:var(--accent);display:flex}
  .sbx-hero-info{flex:1;min-width:0}
  .sbx-path{display:block;font-size:var(--fs-sm);color:var(--mut);font-family:var(--font-mono);
    word-break:break-all;margin-bottom:var(--sp-8)}
  .sbx-hero-btns{display:flex;gap:var(--sp-6);flex-wrap:wrap}

  /* ── Bac à sable : KPIs (3 col) ── */
  .ed-kpis-3{grid-template-columns:repeat(3,1fr)!important}
  @media(max-width:560px){.ed-kpis-3{grid-template-columns:repeat(2,1fr)!important}}
  .ed-kv-sm{font-size:var(--fs-md);font-weight:var(--fw-strong)}

  /* ── Bac à sable : éditeurs ── */
  .sbx-editors{margin:0 0 var(--sp-20)}
  .sbx-ed-title{font-size:var(--fs-xs);font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:.06em;
    color:var(--mut);margin-bottom:var(--sp-10)}
  .sbx-ed-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--sp-8)}
  @media(max-width:560px){.sbx-ed-grid{grid-template-columns:repeat(2,1fr)}}
  .sbx-ed-btn{display:flex;flex-direction:column;align-items:center;gap:var(--sp-4);
    background:var(--bg2);border:1px solid var(--line);border-radius:var(--radius);
    padding:var(--sp-14) var(--sp-8);cursor:pointer;text-align:center;font-size:var(--fs-sm);
    transition:border-color .15s,background .15s;color:var(--txt)}
  .sbx-ed-btn:hover{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 8%,var(--bg2))}
  .sbx-ed-btn span{font-weight:var(--fw-strong)}
  .sbx-ed-btn small{font-size:var(--fs-2xs);color:var(--mut);line-height:1.3}

  /* ── Bac à sable : liste de fichiers ── */
  .sbx-files-section{margin:0 0 var(--sp-20)}
  .sbx-files-hd{display:flex;align-items:center;justify-content:space-between;
    padding-bottom:var(--sp-8);border-bottom:1px solid var(--line);margin-bottom:var(--sp-10);
    font-size:var(--fs-md);font-weight:var(--fw-strong)}
  .sbx-file-list{display:flex;flex-direction:column;gap:var(--sp-2)}
  .sbx-file-row{display:flex;align-items:center;gap:var(--sp-10);padding:var(--sp-6) var(--sp-8);
    border-radius:var(--radius);font-size:var(--fs-md);transition:background .1s}
  .sbx-file-row:hover{background:var(--bg2)}
  .sbx-file-ic{font-size:var(--fs-base);flex:none;width:22px;text-align:center}
  .sbx-file-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .sbx-file-sz{color:var(--mut);font-size:var(--fs-xs);flex:none}
  .sbx-file-dt{color:var(--mut);font-size:var(--fs-xs);flex:none;min-width:52px;text-align:right}

  /* ── Environnements : vue détail ── */
  .env-detail{padding:0 var(--sp-20) var(--sp-32)}
  .ed-nav{display:flex;align-items:center;gap:var(--sp-8);flex-wrap:wrap;
    padding:var(--sp-14) 0 var(--sp-16);border-bottom:1px solid var(--line);margin-bottom:var(--sp-20)}
  .ed-back-btn{border:1px solid transparent;background:transparent;color:var(--mut);
    padding:var(--sp-4) var(--sp-8);font-size:var(--fs-md);cursor:pointer;font-weight:var(--fw-medium);gap:var(--sp-4);border-radius:var(--radius-sm)}
  .ed-back-btn:hover{color:var(--txt);background:var(--line2);border-color:var(--line)}
  .ed-sep{color:var(--line2);font-size:var(--fs-lg);line-height:var(--lh-flat)}
  .ed-env-name{font-weight:var(--fw-strong);font-size:var(--fs-base)}
  .ed-miss{margin:0 0 var(--sp-16)}
  .ed-url-row{margin:0 0 var(--sp-20)}
  .ed-url-code{display:block;font-size:var(--fs-sm);color:var(--mut);font-family:var(--font-mono);
    background:var(--bg2);border:1px solid var(--line);border-radius:var(--radius);
    padding:var(--sp-8) var(--sp-12);word-break:break-all}
  .ed-kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--sp-1);margin:0 0 var(--sp-20);
    background:var(--line);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}
  .ed-kpi{background:var(--card);padding:var(--sp-14) var(--sp-12);text-align:center}
  .ed-kv{font-size:var(--fs-lg);font-weight:var(--fw-bold);letter-spacing:var(--ls-tight);font-variant-numeric:tabular-nums}
  .ed-kl{font-size:var(--fs-xs);color:var(--mut);margin-top:var(--sp-2);line-height:1.3}
  @media(max-width:560px){.ed-kpis{grid-template-columns:repeat(2,1fr)}}
  .ed-acts{margin:var(--sp-18) 0 0;display:flex;gap:var(--sp-6);flex-wrap:wrap}

  /* ── Deploy steps ── */
  .deploy-zone{margin:var(--sp-20) 0;background:var(--card2);border:1px solid var(--line);
    border-radius:var(--radius);padding:var(--sp-16) var(--sp-20)}
  .ds-title{font-size:var(--fs-xs);font-weight:var(--fw-bold);color:var(--mut);text-transform:uppercase;
    letter-spacing:.07em;margin-bottom:var(--sp-14)}
  .deploy-steps{display:flex;flex-direction:column;gap:0}
  .ds-step{display:flex;align-items:flex-start;gap:var(--sp-12);padding:var(--sp-10) 0;position:relative}
  .ds-step:not(:last-child)::after{content:'';position:absolute;left:9px;top:32px;
    width:1px;height:calc(100% - 18px);background:var(--line)}
  /* ring = cercle extérieur animé ; dot = cercle intérieur masque */
  .ds-ring{width:20px;height:20px;border-radius:50%;flex:none;margin-top:var(--sp-1);
    position:relative;z-index:1;display:flex;align-items:center;justify-content:center;
    background:var(--line);transition:background .25s}
  .ds-dot{width:12px;height:12px;border-radius:50%;background:var(--bg2);
    display:flex;align-items:center;justify-content:center;
    font-size:8px;font-weight:var(--fw-bold);color:var(--on-solid);transition:background .2s}
  .ds-body{flex:1;min-width:0;padding-top:var(--sp-2)}
  .ds-lbl{font-size:var(--fs-md);font-weight:var(--fw-medium);line-height:1.3;transition:color .2s}
  .ds-sub{font-size:var(--fs-xs);color:var(--mut);margin-top:var(--sp-2);line-height:1.4;transition:opacity .2s}
  .ds-det{font-size:var(--fs-xs);color:var(--mut);margin-top:var(--sp-4);font-family:var(--font-mono);
    word-break:break-all;display:none}
  .ds-det:not(:empty){display:block}
  /* pending */
  .ds-pending .ds-ring{background:var(--line)}
  .ds-pending .ds-dot{background:var(--bg2)}
  .ds-pending .ds-lbl{color:var(--mut);font-weight:var(--fw-regular)}
  .ds-pending .ds-sub{opacity:.4}
  /* active : conic-gradient qui avance de 0° → 360° */
  @property --ds-angle{syntax:'<angle>';inherits:false;initial-value:0deg}
  @keyframes dsRing{0%{--ds-angle:0deg}100%{--ds-angle:360deg}}
  .ds-active .ds-ring{
    background:conic-gradient(var(--accent) var(--ds-angle),color-mix(in srgb,var(--accent) 18%,var(--line)) 0deg);
    animation:dsRing 1.1s linear infinite}
  .ds-active .ds-dot{background:var(--card,var(--bg))}
  .ds-active .ds-lbl{color:var(--fg)}
  .ds-active .ds-sub{opacity:.7}
  /* ok */
  .ds-ok .ds-ring{background:var(--ok)}
  .ds-ok .ds-dot{background:transparent}
  .ds-ok .ds-dot::before{content:'✓';font-size:8px;font-weight:var(--fw-bold);color:var(--on-solid)}
  /* err */
  .ds-err .ds-ring{background:var(--err)}
  .ds-err .ds-dot{background:transparent}
  .ds-err .ds-dot::before{content:'✗';font-size:8px;font-weight:var(--fw-bold);color:var(--on-solid)}
  .ds-err .ds-lbl{color:var(--err)}
  .ds-err .ds-sub{color:var(--err);opacity:.65}

  /* ── History timeline ── */
  .ed-hist{margin-top:var(--sp-28)}
  .ed-hist-hd{display:flex;align-items:center;gap:var(--sp-8);margin-bottom:var(--sp-14);
    padding-bottom:var(--sp-10);border-bottom:1px solid var(--line)}
  .hist-loading,.hist-empty{color:var(--mut);font-size:var(--fs-md);padding:var(--sp-10) 0;
    display:flex;align-items:center;gap:var(--sp-8)}
  .hist-timeline{display:flex;flex-direction:column}
  .hist-entry{display:flex;align-items:flex-start;gap:var(--sp-14);padding:var(--sp-10) 0;
    border-bottom:1px solid var(--line2)}
  .hist-entry:last-child{border-bottom:none}
  .he-dot{width:10px;height:10px;border-radius:50%;flex:none;margin-top:var(--sp-4);border:2px solid var(--line)}
  .he-ok .he-dot{border-color:var(--ok);background:var(--ok)}
  .he-err .he-dot{border-color:var(--err);background:color-mix(in srgb,var(--err) 30%,transparent)}
  .he-body{flex:1;min-width:0}
  .he-head{display:flex;align-items:center;gap:var(--sp-6);flex-wrap:wrap;line-height:1.4}
  .he-action{font-size:var(--fs-md);font-weight:var(--fw-strong)}
  .he-code{font-size:var(--fs-xs);font-family:var(--font-mono);
    background:var(--bg2);border:1px solid var(--line);border-radius:var(--radius-xs);padding:var(--sp-1) var(--sp-4);color:var(--mut)}
  .he-code-err{color:var(--err);border-color:color-mix(in srgb,var(--err) 30%,var(--line))}
  .he-ver{font-size:var(--fs-xs);font-family:var(--font-mono);color:var(--mut)}
  .he-files,.he-size{font-size:var(--fs-xs);color:var(--mut)}
  .he-date{font-size:var(--fs-xs);color:var(--mut);margin-top:var(--sp-2)}


/* ── LED (partagé hero + santé) ── */
.ed-led{width:9px;height:9px;border-radius:50%;flex:none;transition:background .3s}
.ed-led-unknown{background:var(--mut);opacity:.35}
.ed-led-ping{background:var(--warn);animation:ledP .6s ease-in-out infinite}
.ed-led-ok{background:var(--ok);animation:ledP 2.4s ease-in-out infinite}
.ed-led-warn{background:var(--warn);animation:ledP 1.5s ease-in-out infinite}
.ed-led-err{background:var(--err)}
@keyframes ledP{0%,100%{opacity:.35}50%{opacity:1}}

/* ── Hero card ── */
.ed-hero{display:flex;align-items:center;gap:var(--sp-14);padding:var(--sp-14) var(--sp-16) var(--sp-14) var(--sp-20);
  background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  margin:0 0 var(--sp-16);border-left:3px solid var(--ec,var(--accent));flex-wrap:wrap}
.ed-hero-left{display:flex;align-items:center;gap:var(--sp-10);flex:1;min-width:0;flex-wrap:wrap}
.ed-hero-url-block{display:flex;flex-direction:column;gap:var(--sp-2);flex:1;min-width:0}
.ed-hero-url{font-size:var(--fs-sm);color:var(--mut);font-family:var(--font-mono);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block}
.ed-hero-st{font-size:var(--fs-sm);color:var(--mut);line-height:1.3}
.ed-hero-btns{display:flex;gap:var(--sp-6);flex-shrink:0}
.ed-hero-ctas{display:flex;flex-direction:column;gap:var(--sp-6);flex-shrink:0}
.ed-cta-hero{padding:var(--sp-8) var(--sp-22);font-size:var(--fs-base);font-weight:var(--fw-strong);gap:var(--sp-8);
  white-space:nowrap;border-radius:var(--radius-sm)}
.ed-cta-env{font-weight:var(--fw-medium);opacity:.8;font-size:var(--fs-md)}
.ed-promote-btn{padding:var(--sp-6) var(--sp-16);font-size:var(--fs-md);font-weight:var(--fw-strong);gap:var(--sp-6);white-space:nowrap;
  border-radius:var(--radius-sm);background:color-mix(in srgb,var(--accent) 15%,var(--card));
  color:var(--accent);border:1px solid color-mix(in srgb,var(--accent) 30%,transparent)}
.ed-promote-btn:hover{background:color-mix(in srgb,var(--accent) 22%,var(--card))}

/* ── KPI grid 5 colonnes ── */
.ed-kpis-5{grid-template-columns:repeat(5,1fr)!important}
@media(max-width:700px){.ed-kpis-5{grid-template-columns:repeat(3,1fr)!important}}
@media(max-width:480px){.ed-kpis-5{grid-template-columns:repeat(2,1fr)!important}}
.ed-kpi-icon{font-size:var(--fs-base);margin-bottom:var(--sp-6);opacity:.45;line-height:var(--lh-flat)}
.ed-kpi-icon svg{width:16px;height:16px}
.ed-kv-ok{color:var(--ok)}
.ed-kv-warn{color:var(--warn)}
.ed-kv-muted{color:var(--mut)}
.ed-kpi-ok{background:color-mix(in srgb,var(--ok) 6%,var(--card))!important}
.ed-kpi-ok .ed-kpi-icon{opacity:1;color:var(--ok)}
.ed-kpi-warn{background:color-mix(in srgb,var(--warn) 8%,var(--card))!important}
.ed-kpi-warn .ed-kpi-icon{opacity:1;color:var(--warn)}

/* ── Barre actions secondaires ── */
.ed-sec-bar{display:flex;gap:var(--sp-8);flex-wrap:wrap;margin:0 0 var(--sp-6)}

/* ── Héros statut texte ── */
.ed-hero .st{font-size:var(--fs-sm);margin:0;min-height:0}

/* ── Détail d'un environnement, refait le 2026-11-01 (le proprio : « propre, moderne, compact, minimaliste ») : une carte
   (adresse, état, geste), une rangée de faits séparés par des filets, puis le suivi ; l'installation repliée en bas. ── */
.ed2 .ed-nav{padding:var(--sp-10) 0 var(--sp-12);margin-bottom:var(--sp-14)}
.ed2-nav-acts{display:flex;align-items:center;gap:var(--sp-4);margin-left:auto;flex-shrink:0}
.ed2-nav-acts .mini.icon-only,.ed2-gestes .mini.icon-only{width:28px;height:28px;padding:0;justify-content:center}
.ed2-carte{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}
.ed2-tete{display:flex;align-items:center;gap:var(--sp-12);padding:var(--sp-12) var(--sp-14) var(--sp-12) var(--sp-16);flex-wrap:wrap}
.ed2-adr{display:flex;flex-direction:column;gap:1px;flex:1;min-width:180px}
.ed2-url{font-size:var(--fs-md);font-weight:var(--fw-strong);color:var(--txt);text-decoration:none;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
a.ed2-url:hover{color:var(--accent-texte,var(--accent));text-decoration:underline}
.ed2-url.muted{color:var(--mut);font-weight:var(--fw-medium)}
.ed2 .ed2-st{font-size:var(--fs-xs);color:var(--mut);margin:0;min-height:0;line-height:1.3}
.ed2-st:empty{display:none}
.ed2-gestes{display:flex;align-items:center;gap:var(--sp-6);flex-shrink:0;flex-wrap:wrap}
.ed2-cta{gap:var(--sp-6);white-space:nowrap;font-weight:var(--fw-strong)}
.ed2-faits{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));margin:0;border-top:1px solid var(--line)}
.ed2-fait{padding:var(--sp-10) var(--sp-16);min-width:0}
.ed2-fait + .ed2-fait{border-left:1px solid var(--line)}
.ed2-fait dt{font-size:var(--fs-2xs);color:var(--mut);margin:0 0 var(--sp-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ed2-fait dd{margin:0;font-size:var(--fs-md);font-weight:var(--fw-strong);font-variant-numeric:tabular-nums;color:var(--txt);
  display:flex;align-items:center;gap:var(--sp-4);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ed2-fait dd svg.ic{width:13px;height:13px;flex:none}
.ed2-fait dd.ed2-maj{color:var(--mut);font-weight:var(--fw-regular)}
@media(max-width:760px){.ed2-faits{grid-template-columns:repeat(2,minmax(0,1fr))}
  .ed2-fait + .ed2-fait{border-left:0}.ed2-fait:nth-child(even){border-left:1px solid var(--line)}
  .ed2-fait:nth-child(n+3){border-top:1px solid var(--line)}}
.ed2 .ed-monitor{margin-top:var(--sp-16)}
.ed2 .ed-mon-tabs{align-items:center}
.ed2 .ed-mon-tab{padding:var(--sp-8) var(--sp-12);font-size:var(--fs-sm)}
.ed2-outils{display:flex;gap:var(--sp-4);margin-left:auto;padding:0 var(--sp-8);flex:none}
.ed2-serveur{margin-top:var(--sp-16);border:1px solid var(--line);border-radius:var(--radius);background:var(--card)}
.ed2-serveur > summary{display:flex;align-items:center;gap:var(--sp-8);padding:var(--sp-10) var(--sp-14);cursor:pointer;list-style:none;
  font-size:var(--fs-sm);font-weight:var(--fw-strong);color:var(--mut)}
.ed2-serveur > summary::-webkit-details-marker{display:none}
.ed2-serveur > summary svg.ic{width:14px;height:14px}
.ed2-serveur > summary .snav-car{margin-left:auto;display:flex;transition:transform .15s}
.ed2-serveur[open] > summary .snav-car{transform:rotate(90deg)}
.ed2-serveur[open] > summary{border-bottom:1px solid var(--line)}
.ed2-serveur .inst-env-sec{padding:var(--sp-12) var(--sp-14)}
.ed2-serveur .inst-env-sec > .ov-sec{display:none}

/* ── Panneau monitoring (onglets) ── */
.ed-monitor{margin-top:var(--sp-24);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}
.ed-mon-tabs{display:flex;border-bottom:1px solid var(--line);background:var(--card2);
  overflow-x:auto;scrollbar-width:none}
.ed-mon-tabs::-webkit-scrollbar{display:none}
.ed-mon-tab{padding:var(--sp-10) var(--sp-16);font-size:var(--fs-md);font-weight:var(--fw-medium);border:none;border-radius:0;
  background:transparent;color:var(--mut);cursor:pointer;white-space:nowrap;
  border-bottom:2px solid transparent;gap:var(--sp-6);flex:none;display:inline-flex;align-items:center}
.ed-mon-tab:hover{color:var(--txt);background:var(--line2)}
.ed-mon-tab.on{color:var(--accent);border-bottom-color:var(--accent)}
.ed-mon-pane{padding:var(--sp-18) var(--sp-20);min-height:100px}

/* ── Santé ── */
  /* L'état du site au fil des relevés (onglet Santé, 2026-10-19 : « État de vos sites » venu des Paramètres) */
  /* Le détail du développement local (2026-10-19) : son adresse, puis « Ce dossier sur votre poste » (répertoire, état, alertes). */
  .loc-carte{display:flex;align-items:center;gap:var(--sp-12);flex-wrap:wrap;padding:var(--sp-14) var(--sp-16);margin-bottom:var(--sp-12);
    border:1px solid var(--line);border-radius:var(--radius);background:var(--card)}
  .loc-url{font-weight:var(--fw-strong)}
  .loc-gestes{display:flex;gap:var(--sp-6);margin-left:auto}
  .loc-dossier{padding:var(--sp-14) var(--sp-16);border:1px solid var(--line);border-radius:var(--radius);background:var(--card)}
  .loc-chemin,.loc-sort{display:flex;align-items:center;gap:var(--sp-10);flex-wrap:wrap;margin-bottom:var(--sp-10)}
  .loc-k{min-width:90px;color:var(--mut);font-size:var(--fs-sm)}
  .loc-chemin code{flex:1;min-width:0;font-size:var(--fs-sm);word-break:break-all}
  .loc-absent{color:var(--err);font-size:var(--fs-sm)}
  .loc-d{color:var(--mut);font-size:var(--fs-sm)}
  .loc-alertes{list-style:none;margin:var(--sp-6) 0 0;padding:0;display:grid;gap:var(--sp-6)}
  .loc-alertes li{display:flex;gap:var(--sp-8);align-items:flex-start;color:var(--warn);font-size:var(--fs-sm)}
  .loc-alertes li span{color:var(--txt)}
  .loc-ranger{margin:var(--sp-10) 0 0}
  .em-releve{padding:var(--sp-14) var(--sp-16);margin-bottom:var(--sp-12);border:1px solid var(--line);border-radius:var(--radius);background:var(--card)}
  .em-rel-tete{display:flex;align-items:center;gap:var(--sp-10);flex-wrap:wrap}
  .em-rel-etat{font-weight:var(--fw-strong);font-size:var(--fs-sm);padding:var(--sp-2) var(--sp-10);border-radius:var(--radius-xs)}
  .em-rel-ok{color:var(--ok);background:color-mix(in srgb,var(--ok) 12%,transparent)}
  .em-rel-lent{color:var(--warn);background:color-mix(in srgb,var(--warn) 12%,transparent)}
  .em-rel-hors{color:var(--err);background:color-mix(in srgb,var(--err) 12%,transparent)}
  .em-rel-jamais{color:var(--mut);background:var(--card2)}
  .em-rel-url{font-family:var(--font-mono,monospace);font-size:var(--fs-sm);color:var(--mut);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .em-rel-mesures{display:flex;flex-wrap:wrap;gap:var(--sp-14);margin-top:var(--sp-10);font-size:var(--fs-sm);color:var(--mut)}
  .em-rel-mesures b{color:var(--txt)}
  .em-rel-vide{margin:var(--sp-8) 0 0;font-size:var(--fs-sm);color:var(--mut)}
  .em-rel-barres{display:flex;gap:var(--sp-2);align-items:flex-end;height:22px;margin-top:var(--sp-12)}
  .em-rel-b{flex:1;max-width:10px;height:100%;border-radius:var(--radius-xs)}
  .em-rel-b.em-rel-ok{background:color-mix(in srgb,var(--ok) 70%,transparent)}
  .em-rel-b.em-rel-lent{background:color-mix(in srgb,var(--warn) 75%,transparent)}
  .em-rel-b.em-rel-hors{background:color-mix(in srgb,var(--err) 75%,transparent)}
  .em-rel-leg{margin-top:var(--sp-4);font-size:var(--fs-2xs);color:var(--mut2)}
.em-health{}
.em-h-status{display:flex;align-items:center;gap:var(--sp-10);margin-bottom:var(--sp-16);
  padding:var(--sp-12) var(--sp-14);border-radius:var(--radius);background:var(--bg2);border:1px solid var(--line)}
.em-h-led{width:9px;height:9px;border-radius:50%;flex:none}
.em-hs-ok .em-h-led{background:var(--ok);animation:ledP 2.4s ease-in-out infinite}
.em-hs-ok{border-color:color-mix(in srgb,var(--ok) 30%,var(--line))}
.em-hs-err .em-h-led{background:var(--err)}
.em-hs-err{border-color:color-mix(in srgb,var(--err) 30%,var(--line))}
.em-h-status strong{font-size:var(--fs-base);font-weight:var(--fw-strong)}
.em-h-ver{font-size:var(--fs-xs);color:var(--mut);font-family:var(--font-mono);margin-left:auto}
.em-h-kpis{display:grid;grid-template-columns:repeat(auto-fill,minmax(100px,1fr));gap:var(--sp-10)}
.em-h-kpi{background:var(--bg2);border:1px solid var(--line);border-radius:var(--radius);padding:var(--sp-10) var(--sp-12)}
.em-hv{font-size:var(--fs-base);font-weight:var(--fw-bold);font-variant-numeric:tabular-nums}
.em-hl{font-size:var(--fs-xs);color:var(--mut);margin-top:var(--sp-2)}
.em-health-unsupported{display:flex;align-items:center;gap:var(--sp-16);color:var(--mut);
  padding:var(--sp-4) 0;font-size:var(--fs-md)}
.em-health-unsupported strong{color:var(--txt);display:block;margin-bottom:var(--sp-2)}

/* ── Aperçu iframe ── */
.em-preview{display:flex;flex-direction:column;gap:var(--sp-10)}
.em-prev-bar{display:flex;align-items:center;gap:var(--sp-8);flex-wrap:wrap}
.em-prev-url{font-size:var(--fs-xs);color:var(--mut);font-family:var(--font-mono);
  flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.em-prev-note{font-size:var(--fs-xs);color:var(--mut);background:var(--bg2);
  border:1px solid var(--line);border-radius:var(--radius-sm);padding:var(--sp-6) var(--sp-10);
  display:flex;align-items:center;gap:var(--sp-6)}
.em-prev-frame{width:100%;height:380px;border:1px solid var(--line);border-radius:var(--radius);
  background:var(--bg)}

/* ── Logs ── */
.em-logs-count{font-size:var(--fs-xs);color:var(--mut);margin-bottom:var(--sp-10)}
.em-logs-pre{font-size:var(--fs-xs);font-family:var(--font-mono);
  background:var(--bg2);border:1px solid var(--line);border-radius:var(--radius);
  padding:var(--sp-12) var(--sp-14);overflow:auto;max-height:300px;white-space:pre-wrap;
  color:var(--warn);margin:0;line-height:1.6}

/* ── Panneau Claude (complément) ── */
.cl-pane{display:flex;flex-direction:column;gap:0;height:100%}
.cl-detect{display:flex;align-items:center;gap:var(--sp-10);padding:var(--sp-8) var(--sp-12);
  border-radius:var(--radius);font-size:var(--fs-sm);background:var(--bg2);border:1px solid var(--line);
  margin-bottom:var(--sp-10);flex-wrap:wrap}
.cl-detect-dot{width:8px;height:8px;border-radius:50%;flex:none;background:var(--mut);opacity:.4}
.cl-detect-ok .cl-detect-dot{background:var(--ok);animation:ledP 2.4s ease-in-out infinite;opacity:1}
.cl-detect-err .cl-detect-dot{background:var(--err);opacity:1}
.cl-detect-ok{border-color:color-mix(in srgb,var(--ok) 25%,var(--line))}
.cl-detect-err{border-color:color-mix(in srgb,var(--err) 25%,var(--line))}

/* Mode buttons + toolbar */
.cl-toolbar{display:flex;align-items:center;gap:var(--sp-8);margin-bottom:var(--sp-10);flex-wrap:wrap}
.cl-mode-grp{display:flex;gap:0;border:1px solid var(--line);border-radius:var(--radius-sm);overflow:hidden;flex-shrink:0}
.cl-mode-btn{padding:var(--sp-6) var(--sp-12);font-size:var(--fs-sm);font-weight:var(--fw-medium);border:none;background:transparent;
  color:var(--mut);cursor:pointer;display:inline-flex;align-items:center;gap:var(--sp-4);
  border-right:1px solid var(--line);white-space:nowrap}
.cl-mode-btn:last-child{border-right:none}
.cl-mode-btn:hover{background:var(--line2);color:var(--txt)}
.cl-mode-btn.on{background:var(--accent);color:var(--on-solid)}
.cl-file-in{font-size:var(--fs-sm);padding:var(--sp-4) var(--sp-8);border:1px solid var(--line);border-radius:var(--radius-sm);
  background:var(--bg2);color:var(--txt);font-family:var(--font-mono);flex:1}

/* Chat log */
.cl-log{flex:1;overflow-y:auto;display:flex;flex-direction:column;gap:var(--sp-12);
  padding:var(--sp-4) 0 var(--sp-8);min-height:120px;max-height:44vh}
.cl-row{display:flex;align-items:flex-start;gap:var(--sp-10)}
.cl-av{width:26px;height:26px;border-radius:50%;background:var(--accent);color:var(--on-solid);
  display:flex;align-items:center;justify-content:center;font-size:var(--fs-md);flex:none;margin-top:var(--sp-2)}
.cl-av-spin{animation:ledP .8s ease-in-out infinite}
.cl-bubble{padding:var(--sp-10) var(--sp-12);border-radius:var(--radius);font-size:var(--fs-md);line-height:1.55;
  white-space:pre-wrap;word-break:break-word;max-width:88%;display:flex;flex-direction:column}
.cl-me{align-self:flex-end;background:var(--accent);color:var(--on-solid);border-radius:var(--radius) var(--radius) var(--radius-xs) var(--radius);margin-left:auto}
.cl-ai{background:var(--card2);border:1px solid var(--line);border-radius:var(--radius-xs) var(--radius) var(--radius) var(--radius)}
.cl-ai-err{border-color:color-mix(in srgb,var(--err) 30%,var(--line));
  background:color-mix(in srgb,var(--err) 6%,var(--card2))}
.cl-bubble-body{white-space:pre-wrap;word-break:break-word}
.cl-think{font-size:var(--fs-md);color:var(--mut);padding:var(--sp-8) var(--sp-12);background:var(--card2);
  border:1px solid var(--line);border-radius:var(--radius);display:flex;align-items:center;gap:var(--sp-8)}

/* Compose row */
.cl-compose{display:flex;gap:var(--sp-8);align-items:flex-end;margin-top:var(--sp-10);
  border-top:1px solid var(--line);padding-top:var(--sp-10)}
.cl-compose-ta{flex:1;min-height:56px;max-height:140px;resize:vertical;font:inherit;font-size:var(--fs-md);
  padding:var(--sp-8) var(--sp-12);border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--bg2);
  color:var(--txt);line-height:var(--lh-normal)}
.cl-compose-ta:focus{outline:none;border-color:var(--accent)}
.cl-compose-send{padding:var(--sp-8) var(--sp-16);font-size:var(--fs-md);font-weight:var(--fw-strong);gap:var(--sp-6);white-space:nowrap;align-self:flex-end}

/* ── Recherche accueil (lot U4) ── */
/* Enveloppes de filtre : transparentes pour la mise en page (flex/grid intactes). */
.plist>[data-pname]{display:contents}
.plist>[data-pname][hidden]{display:none!important}
.plist-none{color:var(--mut);padding:var(--sp-14) 0}

}

/* ── Bandeau de tête de l'accueil ───────────────────────────────────────────
   Hors de la couche `layout` À DESSEIN : `components` y déclare un `input{}`
   générique (padding 9px 11px, font 14px) qui bat toute règle de `layout`,
   spécificité comprise - l'ordre des couches prime. Le champ de recherche
   compact n'existe donc qu'à partir de `modules`. */
@layer modules{
/* Titre + compteur à gauche, outils à droite, sur UNE ligne. Le sous-titre
   explicatif ne subsiste qu'en mode Kids/Ado : en usage courant il répétait ce
   que la liste montre déjà, tout en coûtant une rangée entière. */
/* Bandeau de tête : une BARRE D'OUTILS, pas une affiche. Tous les contrôles
   partagent la même hauteur (28 px) et le même rayon, le titre descend à la
   taille d'un intitulé de section, et un filet ferme la barre : ce qui suit est
   le contenu. Le compteur perd sa gélule grise - c'est un nombre, pas un état. */
.home-top{display:flex;align-items:center;gap:var(--sp-14);flex-wrap:wrap;
  margin:0 0 var(--sp-12);padding-bottom:var(--sp-10);border-bottom:1px solid var(--line2)}
.home-ttl{display:flex;align-items:baseline;gap:var(--sp-8);min-width:0}
.home-ttl .section-title{margin:0;font-size:var(--fs-base);font-weight:var(--fw-bold);letter-spacing:var(--ls-tight)}
.home-count{font-size:var(--fs-xs);font-weight:var(--fw-strong);color:var(--mut2);font-variant-numeric:tabular-nums;
  padding:0;background:none}
.home-tools{margin-inline-start:auto;display:flex;align-items:center;gap:var(--sp-6);flex-wrap:wrap}

/* Champ de recherche : une surface, pas une boîte. Le contour n'apparaît qu'au
   survol et au focus - au repos, seul le texte gris signale l'entrée. */
.home-search{position:relative;display:flex;align-items:center;flex:none}
.home-search svg.ic{position:absolute;inset-inline-start:9px;top:50%;width:13px;height:13px;transform:translateY(-50%);
  color:var(--mut2);pointer-events:none}   /* centrée sur la hauteur du champ (2026-10-25 : elle tombait sous la ligne du texte) */
/* Champ POSÉ sur la page : surface `--card` (blanc en clair) + filet `--line2`,
   plus clair que le filet standard. Le champ se détache du fond sans peser ;
   le contour ne se renforce qu'au survol et au focus. */
.home-search-inp{flex:none;width:180px;height:28px;padding:0 var(--sp-10) 0 var(--sp-26);font-size:var(--fs-sm);color:var(--txt);
  background:var(--card);
  border:1px solid var(--line2);border-radius:var(--radius-sm);
  transition:width var(--dur-2),border-color var(--dur-1),background var(--dur-1)}
[dir="rtl"] .home-search-inp{padding:0 var(--sp-26) 0 var(--sp-10)}
.home-search-inp::placeholder{color:var(--mut2)}
.home-search-inp:hover{border-color:var(--line)}
.home-search-inp:focus{outline:none;width:230px;background:var(--card);
  border-color:var(--accent);box-shadow:var(--focus)}
.home-search-inp::-webkit-search-cancel-button{filter:grayscale(1);opacity:.5}
@media (max-width:720px){
  .home-tools{margin-inline-start:0;width:100%}
  .home-search{flex:1}
  .home-search-inp,.home-search-inp:focus{width:100%}
}
}

/* La marque EST l'icône animée du Pilote (orbites + comètes) : le signe vivant
   de l'application. `.bic` (couche `modules`) impose 24 px et l'ordre des
   couches lui donne raison sur `layout` quelle que soit la spécificité — d'où
   cette règle en couche `overrides`, la dernière déclarée. */
/* ══ Onglets des dossiers (CDC_ONGLETS, 2026-10-25) ══ Dans un cadre, l'atelier n'a ni en-tête ni Pilote (l'hôte les porte).
   Sur l'hôte, un onglet actif remplace la page sous l'en-tête ; l'accueil garde à gauche le panneau des dossiers ouverts, 230 px au
   plus (le proprio : 250, puis « plus compact, 20 px de moins », 2026-10-25), collé sous l'en-tête pendant que la liste défile. En couche overrides : .brain et header sont posés plus haut. */
@layer overrides{
  html.dh-onglet{--hh-bar:0px}
  html.dh-onglet body>header,html.dh-onglet #brain,html.dh-onglet .skip,html.dh-onglet button.brain-btn{display:none}
  body.in-onglet main.wrap{display:none}
  /* Les onglets ne quittent jamais l'affichage (le proprio, 2026-10-25 : « quand je navigue entre les onglets ouverts il y a un
     temps de chargement ; ils doivent déjà être ouverts et fonctionner en parallèle ») : un cadre en display:none voit Chrome
     suspendre ses images d'animation et son rendu, et se remettre en page au retour. Les cadres restent donc posés à leur taille
     réelle, l'un sur l'autre, sous l'en-tête ; ceux qu'on ne regarde pas sont invisibles et ne prennent pas la souris. */
  #dh-onglets{position:fixed;top:var(--hh-bar);left:0;right:0;bottom:0;visibility:hidden;pointer-events:none}
  body.in-onglet #dh-onglets{visibility:visible;pointer-events:auto}
  /* Point M (2026-10-28) : l'onglet montré a son application ouverte, l'en-tête de l'hôte s'efface et le cadre prend tout l'écran. */
  html.dh-app-plein body>header{display:none}
  html.dh-app-plein #dh-onglets{top:0}
  .ong-cadre{position:absolute;inset:0;display:block;width:100%;height:100%;border:0;background:var(--bg)}
  .ong-cadre[hidden]{display:block;visibility:hidden;pointer-events:none}
  .split.ong-on{grid-template-columns:minmax(170px,230px) minmax(0,1fr)}
  .ong-panneau{position:sticky;top:calc(var(--hh-bar) + var(--sp-16));max-height:calc(100dvh - var(--hh-bar) - var(--sp-32));overflow:auto;
    border:.5px solid var(--line);border-radius:var(--radius);background:var(--card)}
  /* Retouches du proprio (2026-10-25) : le titre d'un pixel plus petit, le nom en 550, le détail d'un pixel plus petit en 400 et
     en gris ; au survol, aucun délai, aucun arrondi, le nom souligné. */
  .ong-tete{display:flex;align-items:center;gap:var(--sp-6);padding:var(--sp-8) var(--sp-10);font-size:calc(var(--fs-xs) - 1px);font-weight:var(--fw-strong);
    letter-spacing:.04em;text-transform:uppercase;color:var(--mut);border-bottom:.5px solid var(--line)}
  .ong-ul{list-style:none;margin:0;padding:0}
  .ong-li{display:flex;align-items:center;position:relative}
  .ong-li+.ong-li{border-top:.5px solid var(--line)}
  .ong-ouvrir{flex:1;min-width:0;display:flex;align-items:center;gap:var(--sp-8);padding:var(--sp-6) var(--sp-10);background:none;border:0;
    text-align:start;color:inherit;cursor:pointer;border-radius:0;transition:none}
  .ong-ouvrir:hover{background:var(--card2)}
  .ong-ouvrir:hover .ong-nom{text-decoration:underline}
  .ong-ouvrir .picon{flex:none;width:22px;height:22px}
  .ong-tx{display:flex;flex-direction:column;min-width:0}
  .ong-nom{font-size:var(--fs-sm);font-weight:var(--fw-nom);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .ong-act{font-size:calc(var(--fs-xs) - 1px);font-weight:var(--fw-regular);color:var(--mut);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .ong-fermer{flex:none;display:grid;place-items:center;width:24px;height:24px;margin-inline-end:var(--sp-8);padding:0;border:0;border-radius:0;
    background:none;color:var(--mut);cursor:pointer;transition:none}
  .ong-fermer:hover{background:var(--card2);color:var(--txt)}
  .ong-fermer svg{width:14px;height:14px}
  @media(max-width:880px){ .split.ong-on{grid-template-columns:1fr} .ong-panneau{position:static;max-height:none} }
}

@layer overrides{
  .brand-mark.bic{width:var(--hh-brand);height:var(--hh-brand)}
}
