  :root{
    --bg:#131019; --bg2:#0f0d15; --surface:#1b1724; --surface2:#211c2e;
    --border:#2c2638; --border2:#38314a;
    --text:#e7e3f0; --muted:#8f889f; --faint:#645d76;
    --violet:#a78bfa; --violet2:#8b5cf6; --violet-dim:#4c3d7a;
    --green:#5ed69a; --amber:#e0b64d; --red:#f0757a; --blue:#6fb2f0;
    --mono:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
    --sans:Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif;
    /* Everything below used to be hard-coded further down the sheet, where a
       theme swap could not reach it (C3). */
    --text2:#d7d2e2; --code-text:#cfc9dd; --on-accent:#120e1c; --red-soft:#f0b8ba;
    --avatar1:#3a3350; --avatar2:#564a78;
    --shadow:rgba(0,0,0,.5); --shadow-lg:rgba(0,0,0,.6); --shadow-sm:rgba(0,0,0,.4);
    --overlay:rgba(10,8,16,.7); --overlay-soft:rgba(10,8,16,.55);
    /* J2 (mesure J1) : la couleur etait entierement tokenisee (zero litteral
       hors definition de token, mesure) et la GEOMETRIE ne l etait pas du
       tout : 27 valeurs d espacement distinctes, 14 rayons, 17 tailles de
       texte dont SIX a demi-pixel. Une echelle nommee ne rend pas l ecran
       different, elle rend la prochaine decision reproductible. */
    --s1:4px; --s2:6px; --s3:8px; --s4:12px; --s5:16px; --s6:20px;
    --s7:24px; --s8:32px; --s9:48px;
    --r1:6px; --r2:9px; --r3:12px; --r4:16px; --rpill:999px;
    --fs-xs:11px; --fs-sm:12px; --fs-md:13px; --fs-lg:15px; --fs-xl:19px;
    /* Un seul anneau de focus pour toute l app, derive de l accent : il suit
       les cinq themes sans une regle de plus. */
    --focus:var(--violet);
    /* K2/K10: ONE width for both rails. The left one grew 10 pct (248 ->
       273) and the right one shrank to meet it, which is what folding its
       cards down to their titles was for. */
    --rail:273px;
  }

  /* Light palette (C3). Three states, like every themed page: an explicit
     choice stamps data-theme on <html> and wins; with nothing stamped, the
     system preference decides. The dark set above stays the base, so a token
     that is not redefined here simply keeps its dark value rather than
     disappearing — and a missed token shows up as a contrast bug, not a blank. */
  @media (prefers-color-scheme: light) {
    :root:not([data-theme="dark"]) {
      --bg:#faf9fc; --bg2:#f2f0f7; --surface:#ffffff; --surface2:#eeebf5;
      --border:#e0dbea; --border2:#cfc8dd;
      --text:#1d1926; --muted:#645d76; --faint:#8f889f;
      --violet:#4f46e5; --violet2:#4338ca; --violet-dim:#c7d2fe;
      --green:#1f8f57; --amber:#a3760e; --red:#c0393f; --blue:#1e6fbd;
      --text2:#2c2638; --code-text:#3a3350; --on-accent:#ffffff; --red-soft:#8c2b31;
      --avatar1:#d8d1ea; --avatar2:#b9aede;
      --shadow:rgba(40,30,60,.14); --shadow-lg:rgba(40,30,60,.18);
      --shadow-sm:rgba(40,30,60,.10);
      --overlay:rgba(30,24,44,.35); --overlay-soft:rgba(30,24,44,.25);
    }
  }
  :root[data-theme="light"] {
    --bg:#faf9fc; --bg2:#f2f0f7; --surface:#ffffff; --surface2:#eeebf5;
    --border:#e0dbea; --border2:#cfc8dd;
    --text:#1d1926; --muted:#645d76; --faint:#8f889f;
    --violet:#4f46e5; --violet2:#4338ca; --violet-dim:#c7d2fe;
    --green:#1f8f57; --amber:#a3760e; --red:#c0393f; --blue:#1e6fbd;
    --text2:#2c2638; --code-text:#3a3350; --on-accent:#ffffff; --red-soft:#8c2b31;
    --avatar1:#d8d1ea; --avatar2:#b9aede;
    --shadow:rgba(40,30,60,.14); --shadow-lg:rgba(40,30,60,.18);
    --shadow-sm:rgba(40,30,60,.10);
    --overlay:rgba(30,24,44,.35); --overlay-soft:rgba(30,24,44,.25);
  }
  /* D1: named dark themes (2026-08-30). Tokens only, zero layout change.
     "dark" (Amethyste) is the :root base above; these swap the full token set.
     --violet* is the historical name of the ACCENT tokens: it carries blue in
     Abysse and green in Foret. Renaming it everywhere is churn for another day. */
  :root[data-theme="abysse"] {
    --bg:#0c1220; --bg2:#090e19; --surface:#141c2e; --surface2:#1a2438;
    --border:#223048; --border2:#2c3c5a;
    --text:#e3e8f0; --muted:#8b96a8; --faint:#5f6a7e;
    --violet:#6fb2f0; --violet2:#4a9ae8; --violet-dim:#2c4d74;
    --text2:#d3dae6; --code-text:#c8d2e0; --on-accent:#0a1220; --red-soft:#f0b8ba;
    --avatar1:#2c3a52; --avatar2:#3d5273;
    --shadow:rgba(0,0,0,.5); --shadow-lg:rgba(0,0,0,.6); --shadow-sm:rgba(0,0,0,.4);
    --overlay:rgba(6,10,18,.7); --overlay-soft:rgba(6,10,18,.55);
  }
  :root[data-theme="foret"] {
    --bg:#0e1512; --bg2:#0a100d; --surface:#16211c; --surface2:#1c2a23;
    --border:#24352c; --border2:#2e4438;
    --text:#e3efe8; --muted:#8ba396; --faint:#5f7468;
    --violet:#5ed69a; --violet2:#3dbb7f; --violet-dim:#2c5d46;
    --text2:#d3e4da; --code-text:#c8dcd0; --on-accent:#0a140f; --red-soft:#f0b8ba;
    --avatar1:#2c4237; --avatar2:#3d5c4c;
    --shadow:rgba(0,0,0,.5); --shadow-lg:rgba(0,0,0,.6); --shadow-sm:rgba(0,0,0,.4);
    --overlay:rgba(8,14,11,.7); --overlay-soft:rgba(8,14,11,.55);
  }
  /* K14 (seconde passe d usage reel, 2026-08-31). Cinq crans de plus entre le
     sombre (Amethyste, `:root`) et le clair, pour faire UNE echelle de
     luminosite : nuit, ardoise, fumee, brume, ivoire. Abysse et Foret restent
     a part -- ce sont des ambiances, pas des degres.

     CES BLOCS SONT GENERES. Ne les editer a la main serait les desynchroniser
     de leurs deux extremites : `python3 tests/k14-scale.py` les reimprime,
     `--check` verifie que la feuille les porte encore, et
     `tests/front-k14.test.js` fait echouer le banc s ils divergent.

     Le generateur interpole en OKLab, prend l ENCRE a l extremite qui
     contraste (le fond monte pendant que l encre descend : les interpoler
     ensemble les ferait se croiser au milieu, a 1:1), et MESURE le contraste
     de chaque token contre le fond de son cran avant de l ecrire. Il leve
     plutot que de rendre un theme sous le plancher. */
  /* cran 1/5 */
  :root[data-theme="nuit"] {
    --bg:#303034; --bg2:#2c2c31; --surface:#38393e; --surface2:#3b3c44;
    --border:#42434b; --border2:#4a4b56;
    --text:#e4e5eb; --muted:#a9aab5; --faint:#9697a3;
    --violet:#7f94d6; --violet2:#5d74c8; --violet-dim:#525d7f;
    --green:#54ca8f; --amber:#d6ab44; --red:#e86b70; --blue:#62a7e8;
    --text2:#d4d4dc; --code-text:#cbccd5; --on-accent:#0f0f14; --red-soft:#e0a1a2;
    --avatar1:#4d4f5c; --avatar2:#5e6175;
    --shadow:rgba(7,5,10,0.44); --shadow-lg:rgba(7,5,10,0.53); --shadow-sm:rgba(7,5,10,0.35);
    --overlay:rgba(13,11,21,0.64); --overlay-soft:rgba(13,11,21,0.5);
  }
  /* cran 2/5 */
  :root[data-theme="ardoise"] {
    --bg:#414145; --bg2:#3d3d41; --surface:#494a4f; --surface2:#4a4b53;
    --border:#505159; --border2:#565762;
    --text:#e4e5eb; --muted:#c0c0cc; --faint:#acadb9;
    --violet:#798fd3; --violet2:#6e88dc; --violet-dim:#5d6889;
    --green:#4fc489; --amber:#d1a63f; --red:#e4676b; --blue:#5ca1e3;
    --text2:#d4d4dc; --code-text:#cbccd5; --on-accent:#0f0f14; --red-soft:#d89596;
    --avatar1:#595b68; --avatar2:#66687d;
    --shadow:rgba(10,7,15,0.41); --shadow-lg:rgba(10,7,15,0.5); --shadow-sm:rgba(10,7,15,0.33);
    --overlay:rgba(15,12,23,0.61); --overlay-soft:rgba(15,12,23,0.48);
  }
  /* cran 3/5 */
  :root[data-theme="fumee"] {
    --bg:#515155; --bg2:#4c4c50; --surface:#58585e; --surface2:#575860;
    --border:#5c5d65; --border2:#60616c;
    --text:#f0f1f7; --muted:#d8d8e4; --faint:#c2c3d0;
    --violet:#869ee6; --violet2:#829ef4; --violet-dim:#667191;
    --green:#4bbf84; --amber:#cca13c; --red:#fa797c; --blue:#5fa5e8;
    --text2:#e1e1e9; --code-text:#d6d7e0; --on-accent:#0f0f14; --red-soft:#d48e8f;
    --avatar1:#646572; --avatar2:#6d6f84;
    --shadow:rgba(13,9,19,0.39); --shadow-lg:rgba(13,9,19,0.47); --shadow-sm:rgba(13,9,19,0.31);
    --overlay:rgba(16,13,25,0.59); --overlay-soft:rgba(16,13,25,0.46);
  }
  /* cran 4/5 */
  :root[data-theme="brume"] {
    --bg:#a9aaac; --bg2:#a2a2a6; --surface:#b0b1b3; --surface2:#a6a7ad;
    --border:#a0a1a8; --border2:#9999a4;
    --text:#1b1b21; --muted:#2d2e38; --faint:#3d3d47;
    --violet:#3a559f; --violet2:#3a55a1; --violet-dim:#9ba7c3;
    --green:#006733; --amber:#7a5100; --red:#a92632; --blue:#015aa1;
    --text2:#282931; --code-text:#30313d; --on-accent:#ffffff; --red-soft:#903e42;
    --avatar1:#9fa1ad; --avatar2:#9295aa;
    --shadow:rgba(28,21,42,0.25); --shadow-lg:rgba(28,21,42,0.31); --shadow-sm:rgba(28,21,42,0.19);
    --overlay:rgba(24,19,35,0.46); --overlay-soft:rgba(24,19,35,0.34);
  }
  /* cran 5/5 */
  :root[data-theme="ivoire"] {
    --bg:#dddddf; --bg2:#d5d5d8; --surface:#e3e3e4; --surface2:#d3d3d8;
    --border:#c7c7cf; --border2:#b9b9c3;
    --text:#1b1b21; --muted:#4f505b; --faint:#61616b;
    --violet:#4768b9; --violet2:#3956a3; --violet-dim:#b8c4de;
    --green:#1b8e57; --amber:#a17505; --red:#c54045; --blue:#2876c3;
    --text2:#282931; --code-text:#363744; --on-accent:#ffffff; --red-soft:#973b3f;
    --avatar1:#c0c2cd; --avatar2:#a7a9bf;
    --shadow:rgba(36,27,54,0.18); --shadow-lg:rgba(36,27,54,0.23); --shadow-sm:rgba(36,27,54,0.13);
    --overlay:rgba(28,22,41,0.39); --overlay-soft:rgba(28,22,41,0.28);
  }
  *{box-sizing:border-box;margin:0;padding:0}
  html,body{height:100%}
  body{font-family:var(--sans);background:var(--bg);color:var(--text);font-size:14px;line-height:1.5;overflow:hidden}
  /* K33 (bug d usage iPhone, MESURE du 2026-09-01). `100dvh` est le viewport
     de MISE EN PAGE, et sur iOS ce n est pas ce que la personne voit : Safari
     peint sa chrome PAR-DESSUS le bas de cette boite, et le clavier reduit la
     zone visible sans toucher a dvh du tout. Tout l ecart est pris au BAS du
     shell, donc au composer puis a la barre d etat. Mesure a 390x844 : un ecart
     de 96 px coupe 64 px du composer et sort la barre d etat entiere de l
     ecran ; un ecart de 336 px (clavier) sort le composer entier.
     `--vvh` porte la hauteur VISIBLE, publiee par bindViewport() depuis
     visualViewport, la seule source qui la donne dans les trois cas. L echelle
     d unites derriere elle est ce qui s applique avant que le script tourne :
     `100svh` est le PLUS PETIT viewport, donc jamais plus haut que ce qui est
     montre, la ou `100dvh` l est regulierement. Le `@supports` garde Safari 15
     (var oui, svh non) sur l ancien repli plutot que sur une hauteur invalide. */
  #app,.app{height:100vh}
  @supports (height:100svh){#app,.app{height:100svh;height:var(--vvh,100svh)}}
  .app{display:grid;grid-template-columns:var(--rail) 1fr}
  .app.hide-side{grid-template-columns:1fr}
  .app.hide-side>.side{display:none}
  .side{background:var(--bg2);border-right:1px solid var(--border);display:flex;flex-direction:column;min-height:0}
  /* side-head matches .topbar height exactly; side-foot matches .status. */
  .side-head{height:46px;padding:0 8px 0 14px;display:flex;align-items:center;gap:4px;border-bottom:1px solid var(--border);flex-shrink:0}
  /* V7: the "A" tile and the standalone "Nouvelle conversation" button are
     gone. The header is now the site name, a home button and a magnifier --
     three things, one row, in that order. Home replaces the button it removed:
     the destination was always "/" anyway. */
  .brand{font-weight:600;font-size:13px;margin-right:auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .sh-btn{width:28px;height:28px;flex-shrink:0;display:grid;place-items:center;border:none;background:none;color:var(--muted);cursor:pointer;border-radius:7px;font-size:14px;font-family:inherit;line-height:1}
  .sh-btn:hover{background:var(--surface2);color:var(--text)}
  .sh-btn.on{color:var(--violet)}
  /* Inline SVG on currentColor rather than emoji: an emoji is rendered by the
     OS font in full colour and ignores the theme, so a house and a magnifier
     sat in the header as two coloured stickers on a muted bar. */
  .sh-btn svg{display:block}
  .newbtn{margin:12px;padding:9px 12px;border:1px solid var(--border2);border-radius:9px;background:var(--surface);color:var(--text);font-size:13px;font-weight:500;cursor:pointer;display:flex;align-items:center;gap:8px}
  .newbtn:hover{background:var(--surface2);border-color:var(--violet-dim)}
  .newbtn .plus{color:var(--violet)}
  .side-scroll{flex:1;overflow-y:auto;padding:6px 8px 12px}
  .grp-t{font-size:10px;text-transform:uppercase;letter-spacing:.7px;color:var(--faint);padding:10px 8px 4px}
  .thread{padding:8px 10px;border-radius:7px;color:var(--muted);font-size:13px;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:flex;align-items:center;gap:8px}
  .thread:hover{background:var(--surface);color:var(--text)}
  .thread.active{background:var(--surface2);color:var(--text)}
  /* K27 : la pastille tient desormais un sigle et non deux lettres. Le cadre
     ne change pas de role -- il separe la surface du titre -- mais il se cale
     sur le dessin : carre, centre, et infroissable quand la ligne retrecit. */
  .thread .tag{display:inline-flex;align-items:center;justify-content:center;padding:2px;border-radius:5px;border:1px solid var(--border2);color:var(--faint);flex-shrink:0}
  .thread .tag svg{display:block}
  .thread .tag.cowork{color:var(--violet);border-color:var(--violet-dim)}
  .side-foot{border-top:1px solid var(--border);height:45px;padding:0 14px;display:flex;align-items:center;gap:10px;color:var(--muted);font-size:13px;flex-shrink:0;cursor:pointer}
  .side-foot:hover{background:var(--surface)}
  .avatar{width:27px;height:27px;border-radius:50%;background:linear-gradient(135deg,var(--avatar1),var(--avatar2));display:grid;place-items:center;font-size:13px;flex-shrink:0}
  .foot-n{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

  .main{display:flex;flex-direction:column;min-width:0;min-height:0;background:var(--bg)}
  .topbar{height:46px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:12px;padding:0 18px;flex-shrink:0}
  .ttl{font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* K5: the top-right chip named the model, and the status bar already
     names it next to the context gauge. Two places for one fact is one
     place too many; what the corner is for is whether the thing is up. */
  .pill{margin-left:auto;font-size:11px;color:var(--muted);border:1px solid var(--border2);border-radius:var(--rpill);padding:3px 10px;display:flex;align-items:center;gap:6px;flex-shrink:0}
  .dot{width:6px;height:6px;border-radius:50%;background:var(--green)}

  .stream{flex:1;overflow-y:auto;padding:24px 0}
  .main.blank .stream{display:flex;flex-direction:column;justify-content:flex-end;overflow:visible}
  .blank-sp{flex:1;min-height:0}
  .msg{max-width:940px;margin:0 auto;padding:0 32px 22px}
  .role{display:flex;align-items:center;gap:9px;margin-bottom:6px;min-height:0}
  /* U10 : user on the right in a bubble, assistant plain on the left */
  .msg.u{display:flex;flex-direction:column;align-items:flex-end}
  .msg.u .bubble{max-width:72%;background:var(--bg2);border:0;border-radius:14px;padding:6px 12px;font-size:13.5px;line-height:1.5}
  .acts{display:flex;gap:6px;justify-content:flex-end;margin-top:4px;min-height:0}
  .acts .copybtn{margin-left:0}
  .msg.u .acts{justify-content:flex-end}
  .turn .acts{justify-content:flex-start}
  .bubble{color:var(--text2);font-size:14px;line-height:1.6;white-space:pre-wrap;word-wrap:break-word}
  .bubble.cur::after{content:"";display:inline-block;width:7px;height:15px;background:var(--violet);vertical-align:text-bottom;margin-left:2px;animation:blink 1s steps(2) infinite}
  @keyframes blink{50%{opacity:0}}

  .composer{max-width:940px;margin:0 auto;width:100%;padding:0 32px 12px;flex-shrink:0}
  /* R4: the chain is broken and the composer says so BEFORE a turn is spent on
     it. Amber when a non-essential link is missing (the turn still runs, some
     tools will not), red when the model itself is unreachable (nothing can
     run). Neither is a toast: a message that disappears is a message that was
     not read. */
  .ready-w{display:flex;align-items:center;gap:9px;margin:0 0 8px;padding:8px 12px;border-radius:10px;font-size:13px;line-height:1.45;border:1px solid var(--amber);color:var(--amber);background:color-mix(in srgb,var(--amber) 10%,transparent)}
  .ready-w.blocking{border-color:var(--red);color:var(--red);background:color-mix(in srgb,var(--red) 10%,transparent)}
  .ready-w .rw-d{width:7px;height:7px;border-radius:50%;background:currentColor;flex-shrink:0}
  .ready-w b{font-weight:600}
  /* An in-thread notice for a retry in flight: the status line is transient and
     a turn that paused 20 s with nothing said reads as a hang. */
  .retry-n{margin:6px 0;padding:7px 11px;border-left:2px solid var(--amber);color:var(--muted);font-size:13px}
  /* R1/R2: an interruption is not an error -- nothing went wrong, a process
     went away. Amber, and carrying the one action that continues the work. */
  .intcard{border:1px solid var(--amber);border-radius:11px;padding:12px 14px;background:color-mix(in srgb,var(--amber) 8%,transparent);display:flex;flex-direction:column;gap:7px;align-items:flex-start}
  .intcard .int-t{color:var(--amber);font-size:13px;font-weight:600}
  .intcard .int-s{color:var(--muted);font-size:13px;line-height:1.5}
  .intcard .set-btn{margin-left:0}
  /* M1 : l interrupteur segmente de L2 vivait ici. Il a disparu avec les modes,
     et ses neuf regles avec lui : le routage est desormais entierement serveur,
     lu sur la demande. */
  .box{border:1px solid var(--border2);border-radius:12px;background:var(--surface);padding:11px 14px 9px}
  .box textarea{width:100%;background:transparent;border:none;color:var(--text);font-family:var(--sans);font-size:15px;resize:none;outline:none;max-height:180px}
  .box textarea::placeholder{color:var(--faint)}
  /* On a page with no conversation yet (chat and cowork entries), the input is
     the whole page: the greeting reads as a title, the input text is a size
     up, the box is three lines tall and more open (sized on the Claude
     client's entry, same family, same tokens). The autosize keeps growing
     the box from there; a thread keeps the one-line box and its 15px. */
  .main.blank .greet{font-size:28px;line-height:1.25;font-weight:600;color:var(--text);text-align:center;letter-spacing:-.01em;margin-bottom:6px}
  .main.blank .box{padding:16px 18px 12px;border-radius:16px}
  .main.blank .box textarea{font-size:18px;line-height:1.4;min-height:72px}
  .main.blank .row{margin-top:10px}
  .main.blank .send{height:32px;font-size:14px;padding:0 18px}
  /* Composer chips, aligned on the Claude client: fixed height, icon and label
     on ONE line, ellipsis rather than an overflow, and the row wraps instead of
     squeezing (the Cowork row overflowed its icons at narrow widths). */
  .row{display:flex;align-items:center;gap:8px;margin-top:8px;flex-wrap:wrap}
  /* inline-block, not inline-flex: text-overflow:ellipsis only applies to a
     block container, and a flex chip clipped its label with a hard cut. */
  .approval{display:inline-block;height:28px;line-height:26px;box-sizing:border-box;
    font-size:12px;color:var(--muted);border:1px solid var(--border);border-radius:8px;
    padding:0 10px;background:var(--bg2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
    max-width:210px;vertical-align:middle}
  .approval.plus{font-size:17px;font-weight:600;padding:0;width:28px;text-align:center;color:var(--text)}
  .approval.mic{padding:0;width:28px;display:inline-grid;place-items:center}
  .approval.mic svg{display:block}
  /* K34. Le sigle d approbation est dans le DOM en permanence et masque ici :
     le desktop rend exactement ce qu il rendait, et la requete mobile n a qu a
     l allumer. */
  .approval .k34-ic{display:none}
  .pillwrap{margin-left:auto}
  .box.drop{border-color:var(--violet);box-shadow:0 0 0 1px var(--violet-dim) inset}
  .popwrap{position:relative;display:inline-flex;align-items:center}
  .pop{display:none;position:absolute;bottom:calc(100% + 8px);left:0;z-index:40;min-width:196px;
    background:var(--surface2);border:1px solid var(--border2);border-radius:10px;padding:6px;
    box-shadow:0 12px 34px var(--shadow)}
  .pop.on{display:block}
  .pillwrap .pop{left:auto;right:0;min-width:238px}
  .pop-s{font-size:10px;text-transform:uppercase;letter-spacing:.5px;color:var(--faint);padding:7px 9px 4px}
  .pop-i{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--text);padding:7px 9px;
    border-radius:7px;cursor:pointer;white-space:nowrap}
  .pop-i:hover{background:var(--bg2)}
  .pop-i.on{color:var(--violet);background:var(--bg2)}
  .pop-n{font-weight:600}
  .pop-c{margin-left:auto;font-size:11px;color:var(--faint)}
  .eopt.on::after{content:"\2713";margin-left:auto;font-size:11px}
  .send{background:linear-gradient(135deg,var(--violet2),var(--violet));color:var(--on-accent);font-weight:600;border:none;border-radius:9px;padding:0 16px;height:28px;cursor:pointer;font-size:13px}
  .send:disabled{opacity:.5;cursor:default}

  .status{display:flex;align-items:center;height:45px;border-top:1px solid var(--border);background:var(--bg2);font-family:var(--mono);font-size:11px;color:var(--muted);flex-shrink:0}
  .st-i{padding:0 14px;height:100%;display:flex;align-items:center;gap:7px;border-right:1px solid var(--border)}
  .st-i .k{color:var(--faint)} .st-i .v{color:var(--text)} .st-i.acc .v{color:var(--violet)}
  /* V1: the gauge IS the button. The breakdown popover was reachable only from
     the Monitor block, i.e. only on the one surface that has a Monitor; the
     gauge is on every surface and was already the thing being pointed at. */
  .st-ctx{margin-left:auto;padding:0 14px;border-left:1px solid var(--border);cursor:pointer}
  .st-ctx:hover{background:var(--surface)}
  .st-ctx:hover .v{color:var(--violet)}

  /* entry chooser */
  .entry{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;gap:22px;padding:24px}
  .entry h1{font-size:22px;font-weight:600}
  .entry .sub{color:var(--muted);font-size:13px;margin-top:-12px}
  .cards{display:flex;gap:18px;flex-wrap:wrap;justify-content:center}
  .card{width:280px;border:1px solid var(--border2);border-radius:14px;background:var(--surface);padding:20px;cursor:pointer;transition:border-color .15s,transform .15s}
  .card:hover{border-color:var(--violet);transform:translateY(-2px)}
  .card .ic{width:36px;height:36px;border-radius:9px;display:grid;place-items:center;font-size:18px;background:var(--surface2);margin-bottom:12px}
  .card h3{font-size:16px;font-weight:600;margin-bottom:6px}
  .card p{color:var(--muted);font-size:13px;line-height:1.5}
  .core-toast{position:fixed;left:50%;bottom:26px;transform:translateX(-50%) translateY(20px);background:var(--surface2);border:1px solid var(--border2);color:var(--text);padding:9px 16px;border-radius:9px;font-size:13px;opacity:0;pointer-events:none;transition:.2s}
  .core-toast.on{opacity:1;transform:translateX(-50%) translateY(0)}
  .core-toast.err{border-color:var(--red);color:var(--red-soft)}
  ::-webkit-scrollbar{width:10px;height:10px}
  ::-webkit-scrollbar-thumb{background:var(--border2);border-radius:6px;border:2px solid var(--bg)}

  .bubble h3,.bubble h4{font-weight:600;margin:14px 0 8px;color:var(--text)}
  .bubble h3{font-size:16px} .bubble h4{font-size:15px}
  .bubble ul,.bubble ol{margin:0 0 10px 22px} .bubble li{margin:3px 0}
  .bubble strong{color:var(--text);font-weight:600}
  .bubble a{color:var(--violet)}
  .bubble pre.cb{background:var(--bg2);border:1px solid var(--border);border-radius:9px;padding:11px 13px;margin:8px 0 12px;overflow-x:auto}
  .bubble pre.cb code{background:none;padding:0;color:var(--code-text);font-size:13px;line-height:1.6;display:block}
  /* markdown tables (U3). The wrapper scrolls, not the page: a wide table
     must never push the whole conversation sideways. */
  /* settings page (C1). Two columns on desktop, stacked on mobile — the nav
     stays a list rather than becoming a drawer, because it is three entries. */
  .main.settings{overflow-y:auto}
  /* V3: the page used to sit in 920px whatever the screen, so on a desktop it
     read as a 25%-wide column of settings with three quarters of empty page
     beside it. It is now fluid up to 1320px and keeps a comfortable reading
     measure by widening the NAV and the gutters rather than only the text. */
  /* K21 (verdict de l oeil, 2026-08-31) : le bloc etait centre horizontalement
     (`margin:0 auto`) et pose en haut d une page qui a de la place en bas. Il
     est cale a GAUCHE, comme la colonne de conversation qu il remplace.
  
     K22 (retour du 2026-08-31, meme oeil) : la PREMIERE version centrait aussi
     verticalement, par `margin-block:auto` dans un conteneur flex. C etait un
     defaut : le centrage depend de la HAUTEUR DU CONTENU, donc le titre
     changeait de place a chaque onglet. Mesure sur la prod : « Parametres » a
     y=264 sur Journal, y=307 sur Personnalisation, y=366 sur Affichage -- cent
     pixels de saut entre deux clics de la meme page.

     K22b : la correction avait d abord fige ce decalage a 30vh, en croyant
     reproduire la position de Personnalisation que l oeil avait approuvee.
     C etait sur-interpreter : ce qui etait approuve, c etait la STABILITE, pas
     la hauteur. Verdict du 2026-08-31 sur capture : « parametre devrait etre en
     haut a gauche, la c est centre verticalement ». Le bloc est donc en HAUT,
     comme toute page qui se lit de haut en bas, et a GAUCHE (K21). */
  .set-wrap{width:100%;max-width:1320px;margin:0 auto 0 0;
            padding:32px clamp(22px,4vw,56px) 64px}
  .set-head{display:flex;align-items:center;gap:12px;margin-bottom:24px}
  .set-head h1{font-size:22px;font-weight:600;color:var(--text)}
  /* K20 : la fleche de retour, a gauche du titre. Un cran plus grande que les
     boutons du bandeau lateral parce qu elle est seule de son cote. */
  .set-back{width:32px;height:32px;margin-left:-6px}
  /* K19 : la loupe finit la ligne, la barre se deploie entre le titre et elle
     -- donc a droite du titre, comme demande. */
  .set-mag{margin-left:auto}
  .set-grid{display:grid;grid-template-columns:236px minmax(0,1fr);gap:clamp(22px,3vw,40px);align-items:start}
  .set-nav{display:flex;flex-direction:column;gap:2px;position:sticky;top:0}
  .set-navi{display:flex;align-items:center;gap:9px;padding:9px 12px;border-radius:9px;cursor:pointer;color:var(--faint);font-size:14px}
  .set-navi:hover{background:var(--bg2);color:var(--text)}
  .set-navi.on{background:var(--bg2);color:var(--text);font-weight:600}
  .set-navic{font-size:14px}
  .set-h2{font-size:16px;font-weight:600;color:var(--text);margin:0 0 12px}
  .set-card{border:1px solid var(--border);background:var(--bg2);border-radius:12px;padding:18px 20px}
  .set-card+.set-card{margin-top:14px}
  /* Settings accordion (D3). A nav that selects a panel needs a column to put
     the panel in; a phone has none, so on mobile the sections stack and open in
     place. Same sections, same builders -- only the container changes. */
  /* R7: dense on purpose. A journal you scroll is a journal you read; one row
     per line, monospace on the time and the target so columns line up. */
  .set-acc{display:flex;flex-direction:column;gap:8px}
  .set-accd{border:1px solid var(--border);border-radius:11px;background:var(--bg2);overflow:hidden}
  .set-accs{display:flex;align-items:center;gap:10px;min-height:48px;padding:0 14px;cursor:pointer;font-size:14px;font-weight:600;color:var(--text);list-style:none}
  .set-accs::-webkit-details-marker{display:none}
  .set-accs::after{content:"\203a";margin-left:auto;color:var(--faint);font-size:19px;transform:rotate(90deg);transition:transform .15s ease}
  .set-accd[open] .set-accs::after{transform:rotate(-90deg)}
  .set-accb{padding:0 12px 12px}
  .set-accb .set-card{border:none;background:transparent;padding:0}
  /* D3: ONE mobile breakpoint. This used to be 760 while the shell used 768,
     so an 8px band rendered a desktop settings grid inside a mobile shell. */
  @media (max-width:768px){
    .set-grid{grid-template-columns:1fr}
    .set-nav{flex-direction:row;overflow-x:auto;position:static;gap:6px;padding-bottom:4px}
    .set-navi{white-space:nowrap}
  }
  .bubble .tbl-wrap{overflow-x:auto;margin:8px 0 12px}
  .bubble table.md-tbl{border-collapse:collapse;font-size:12.5px;min-width:min(100%,420px)}
  .bubble table.md-tbl th,.bubble table.md-tbl td{border:1px solid var(--border);padding:6px 11px;text-align:left;vertical-align:top}
  .bubble table.md-tbl th{background:var(--bg2);color:var(--text);font-weight:600;white-space:nowrap}
  .bubble table.md-tbl tbody tr:nth-child(even) td{background:color-mix(in srgb,var(--bg2) 45%,transparent)}

  .tcard{display:flex;align-items:center;gap:9px;max-width:940px;margin:0 auto;border:1px solid var(--border2);background:var(--bg2);border-radius:10px;padding:9px 13px;font-family:var(--mono);font-size:13px}
  .tcard.risky{border-color:var(--amber)}
  .tc-ic{color:var(--violet)} .tc-nm{color:var(--blue)} .tc-st{margin-left:auto;color:var(--faint)} .tc-st.ok{color:var(--green)}
  /* tool cards: one strip per uninterrupted run of calls, so the compact
     verbosity lays them out side by side without regrouping the DOM. */
  .tstrip{max-width:940px;margin:0 auto;display:flex;flex-direction:column;gap:8px}
  .tc-wrap{width:100%;cursor:pointer}
  .tc-wrap .tcard{max-width:none;margin:0}
  .tc-wrap:hover .tcard{border-color:var(--violet-dim)}
  .tc-dt{color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:330px}
  .tc-ca{color:var(--faint);font-size:9px;transition:transform .12s}
  .tc-wrap.open .tc-ca{transform:rotate(90deg)}
  .tc-panel{display:none;margin:5px 0 0;border:1px solid var(--border);border-radius:9px;
            background:var(--bg2);padding:9px 12px;font-family:var(--mono);font-size:12px}
  .tc-wrap.open .tc-panel,.stream.tv-detail .tc-panel{display:block}
  .tc-sec{color:var(--faint);font-size:11px;letter-spacing:.6px;text-transform:uppercase;margin:0 0 5px}
  .tc-row{margin:0 0 5px} .tc-k{color:var(--blue)} .tc-v{color:var(--muted);white-space:pre-wrap;word-break:break-word}
  .tc-res{margin:0;white-space:pre-wrap;word-break:break-word;color:var(--muted);max-height:260px;overflow:auto}
  .stream.tv-compact .tstrip{flex-direction:row;flex-wrap:wrap;gap:6px;align-items:flex-start}
  .stream.tv-compact .tc-wrap{width:auto}
  .stream.tv-compact .tc-wrap.open{width:100%}
  .stream.tv-compact .tcard{border-radius:999px;padding:3px 11px;font-size:11px;gap:7px}
  .stream.tv-compact .tc-dt{display:none}
  .stream.tv-compact .tc-st{margin-left:0}
  .fcard{display:flex;align-items:center;gap:12px;max-width:940px;margin:0 auto;border:1px solid var(--border2);background:var(--surface);border-radius:10px;padding:10px 13px;text-decoration:none;color:var(--text)}
  .fcard:hover{border-color:var(--violet)}
  .fcard.superseded{opacity:.45;filter:grayscale(.6)}
  .fcard.superseded:hover{border-color:var(--border2)}
  .fthumb{width:44px;height:56px;object-fit:cover;border-radius:5px;border:1px solid var(--border)}
  .fic{width:44px;height:56px;display:grid;place-items:center;font-size:22px;background:var(--surface2);border-radius:5px}
  .fname{font-weight:600;font-size:14px} .fsub{color:var(--muted);font-size:12px}

  /* --- J2 : l etat clavier, mesure absent -------------------------------
     J1 a compte 36 selecteurs avec :hover contre 4 avec :focus, et 33
     controles cliquables sur des balises qu aucun clavier n atteignait. La
     souris avait toute l interface. `el()` rend maintenant tout controle
     focusable (core.js) et CETTE regle lui donne le meme anneau partout :
     :focus-visible, donc un clic a la souris ne le declenche pas. */
  :focus-visible { outline:2px solid var(--focus); outline-offset:2px;
                   border-radius:3px; }
  .icw { display:inline-flex; align-items:center; justify-content:center;
         vertical-align:-2px; }
  .icw svg, svg.ic { display:block; }
  /* U5 : la palette */
  .pal-ov{position:fixed;inset:0;background:var(--overlay);display:flex;
          align-items:flex-start;justify-content:center;padding:12vh var(--s5) var(--s5);z-index:70}
  .pal{width:min(620px,100%);background:var(--surface);border:1px solid var(--border2);
       border-radius:var(--r3);box-shadow:0 24px 60px var(--shadow-lg);overflow:hidden}
  .pal-in{width:100%;border:0;border-bottom:1px solid var(--border2);background:transparent;
          color:var(--text);font:inherit;font-size:15px;padding:var(--s4) var(--s5);outline:none}
  .pal-list{max-height:52vh;overflow:auto;padding:var(--s2)}
  .pal-i{display:flex;justify-content:space-between;gap:var(--s4);align-items:center;
         padding:var(--s2) var(--s4);border-radius:var(--r1);cursor:pointer;font-size:13px}
  .pal-i.on,.pal-i:hover{background:var(--surface2)}
  .pal-k{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .pal-s{color:var(--muted);font-size:11px;flex:0 0 auto}
  .pal-none{padding:var(--s4) var(--s5);color:var(--muted);font-size:13px}
  /* U9 : un tour = un bloc ; la bande d activite */
  .turn .think summary{display:none}
  .turn .think{margin:0 0 8px}
  /* folded, the card is nothing: the chip is its handle */
  .turn .think:not([open]){display:none}
  .think-chip{display:inline-flex;align-items:center;gap:4px;margin-left:2px;padding:1px 8px;border-radius:999px;
    border:1px solid var(--border2);background:transparent;color:var(--muted);font:inherit;font-size:11px;cursor:pointer}
  .think-chip:hover,.think-chip.on{color:var(--text);background:var(--bg2)}
  .think-chip.live .icw{animation:livepulse 1s ease-in-out infinite}
  .turn .statusline{margin:0;font-size:11.5px;color:var(--muted);font-style:normal}
  .turn .statusline::before{background:var(--faint)}
  .act{display:flex;flex-direction:column;gap:2px;margin:0 0 6px}
  .act:empty,.deliv:empty{display:none}
  .act-h{display:flex;align-items:center;gap:6px;width:100%;background:none;border:0;padding:3px 0;
    color:var(--muted);font:inherit;font-size:12px;cursor:pointer;text-align:left}
  .act-h:hover{color:var(--text)}
  .act-h .act-l{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .act-h .act-s{margin-left:auto;color:var(--faint);font-size:11px;white-space:nowrap}
  .act-h .act-s.ok{color:var(--green)} .act-h .act-s.ko{color:var(--red)} .act-h .act-s.live{color:var(--violet)}
  .act-g .tstrip{display:none;margin:2px 0 8px 6px;max-width:none;gap:1px;padding-left:12px;border-left:2px solid var(--border)}
  /* the calls of a group are lines, not boxes: icon, name, detail, state */
  .act-g .tcard{border:0;background:transparent;border-radius:6px;padding:2px 6px;gap:8px;font-family:inherit;font-size:12px}
  .act-g .tc-wrap:hover .tcard{background:var(--bg2);border-color:transparent}
  .act-g .tc-ic{color:var(--faint)} .act-g .tc-ic svg{width:12px;height:12px}
  .act-g .tc-nm{color:var(--muted);font-family:var(--mono);font-size:11px;flex:0 0 auto}
  .act-g .tc-dt{color:var(--text2);max-width:none;flex:1;min-width:0}
  .act-g .tc-st{font-size:11px;color:var(--faint);display:inline-flex;align-items:center;gap:4px}
  .act-g .tc-st.ok{color:var(--green)} .act-g .tc-st.ko{color:var(--red)}
  .tc-dot{width:7px;height:7px;border-radius:50%;background:var(--violet);animation:livepulse 1s ease-in-out infinite}
  .tc-pct{color:var(--muted);font-variant-numeric:tabular-nums}
  .act-g .tc-ca{opacity:0} .act-g .tc-wrap:hover .tc-ca,.act-g .tc-wrap.open .tc-ca{opacity:1}
  .act-g .tc-panel{margin:3px 0 6px 26px}
  .stream.tv-compact .act-g .tcard{background:var(--bg2);padding:2px 10px}
  .act-g.open .tstrip,.stream.tv-detail .act-g .tstrip{display:flex}
  .act-n{color:var(--muted);font-size:13px;line-height:1.5;padding:2px 0 2px 10px;border-left:2px solid var(--border);margin:2px 0 4px}
  .act-n p{margin:0 0 6px}
  .deliv{display:flex;flex-direction:column;gap:2px;margin:0 0 8px}
  .deliv > .msg{padding:0}
  /* U6 : le bloc d appels d outil */
  .tg-head{display:none}
  .tstrip.grouped .tg-head{display:inline-flex;align-items:center;gap:4px;background:none;
    border:0;color:var(--muted);font:inherit;font-size:12px;cursor:pointer;padding:0 0 var(--s1)}
  .tstrip.grouped .tg-head:hover{color:var(--text)}
  .tstrip.grouped.folded .tc-wrap{display:none}
  /* U7 : la pastille de retour au fil */
  .main.pos{position:relative}
  .tail-pill{position:absolute;left:50%;transform:translateX(-50%);bottom:118px;z-index:8;
    display:inline-flex;align-items:center;gap:5px;padding:6px 13px;border-radius:var(--rpill);
    border:1px solid var(--border2);background:var(--surface);color:var(--text);
    font:inherit;font-size:12px;cursor:pointer;box-shadow:0 6px 18px var(--shadow)}
  .tail-pill:hover{border-color:var(--violet)}
  /* K38 : la pastille d une generation qui continue AILLEURS. Elle se pose en
     HAUT du fil, pour ne pas se confondre avec « revenir en bas », et elle est
     tout ce qu une autre conversation a le droit d ecrire dans cette page. */
  .fg-pill{bottom:auto;top:14px}
  /* U8 : epingles et renommage en ligne */
  .thread.pinned .th-t{font-weight:600}
  .th-edit{width:100%;background:var(--bg);border:1px solid var(--violet);border-radius:var(--r1);
           color:var(--text);font:inherit;font-size:13px;padding:1px 5px;outline:none}
  /* C4 : la recherche des parametres */
  .set-q{flex:1;max-width:320px;margin:0}
  .set-q.hid{display:none}
  .sk-q{margin-bottom:var(--s4)}
  .sk-grp{font-size:11px;font-weight:700;letter-spacing:1.1px;text-transform:uppercase;
          color:var(--muted);margin:var(--s4) 0 var(--s2)}
  .sk-grp:first-child{margin-top:0}
  .sk-row.off{opacity:.55}
  .sk-chips{display:flex;gap:var(--s1);flex-wrap:wrap}
  .sk-chip{font-size:10px;padding:2px 7px;border-radius:var(--rpill);border:1px solid var(--border2);
           color:var(--muted);white-space:nowrap}
  .sk-chip.on{border-color:var(--violet);color:var(--violet)}
  .sk-chip.warn{border-color:var(--amber);color:var(--amber)}
  .sk-chip.off{border-color:var(--faint);color:var(--faint)}
  .sk-cwrap{display:flex;flex-direction:column;gap:var(--s1)}
  .sk-cwrap .set-ta{min-height:220px}
  .sk-meter{align-self:flex-end;font-size:11px;color:var(--muted);font-family:var(--mono)}
  .sk-meter.over{color:var(--red)}
  .sk-ov{position:fixed;inset:0;background:var(--overlay);display:flex;align-items:flex-start;
         justify-content:center;padding:var(--s9) var(--s5);z-index:60;overflow:auto}
  .sk-modal{background:var(--surface);border:1px solid var(--border2);border-radius:var(--r4);
            width:min(860px,100%);padding:var(--s6);box-shadow:0 24px 60px var(--shadow-lg)}
  .sk-mh{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--s5)}
  .sk-mh h2{font-size:17px;font-weight:650}
  /* K31. Supprimer une conversation passait par un `confirm()` natif : une
     boite du SYSTEME, ancree en haut de la fenetre, qui ne connait ni les
     themes ni le dictionnaire. Celle-ci est CENTREE et tiree des memes
     tokens que le reste ; le bouton destructeur reutilise `.set-btn.danger`
     de la maison, pour que les quatre themes le tiennent sans couleur en
     dur. Sa raison d etre est le TEXTE : une confirmation qui ne nomme pas
     ce qui part ne fait que poser deux fois la meme question (doctrine K25). */
  .cf-ov{position:fixed;inset:0;background:var(--overlay);display:flex;align-items:center;
         justify-content:center;padding:var(--s5);z-index:70}
  .cf-box{background:var(--surface);border:1px solid var(--border2);border-radius:var(--r4);
          width:min(420px,100%);padding:var(--s6);box-shadow:0 24px 60px var(--shadow-lg);
          display:flex;flex-direction:column;gap:var(--s3)}
  .cf-t{font-size:16px;font-weight:650;color:var(--text)}
  .cf-b{font-size:13px;color:var(--muted);line-height:1.55}
  .cf-a{display:flex;justify-content:flex-end;gap:var(--s2);margin-top:var(--s2)}
  .cf-a .set-btn{margin-left:0}
  .cf-no{background:var(--surface2);color:var(--text);border:1px solid var(--border2)}
  .sk-probe{margin-top:var(--s3);display:flex;flex-direction:column;gap:var(--s1)}
  .sk-io{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}
  .sk-iohint{color:var(--muted);font-size:12px;flex:1;min-width:200px}
  .sk-report{margin-top:var(--s4);border-top:1px solid var(--border2);padding-top:var(--s3);
             display:flex;flex-direction:column;gap:var(--s1)}
  .sk-rhead{font-weight:600;font-size:13px;margin-bottom:var(--s1)}
  .sk-rline{font-size:12px;color:var(--muted);font-family:var(--mono)}
  .sk-rline.ko{color:var(--red)}
  .fview{display:flex;align-items:center;gap:5px;max-width:940px;margin:5px auto 0;
         background:none;border:0;padding:0;color:var(--muted);font:inherit;font-size:12px;
         cursor:pointer;text-decoration:underline dotted}
  .fview:hover{color:var(--text)}
  .vw-ov{position:fixed;inset:0;background:var(--overlay);display:flex;align-items:center;
         justify-content:center;padding:var(--s6);z-index:80}
  .vw{width:min(1100px,100%);height:min(86vh,100%);background:var(--surface);
      border:1px solid var(--border2);border-radius:var(--r3);display:flex;
      flex-direction:column;overflow:hidden;box-shadow:0 24px 60px var(--shadow-lg)}
  .vw-h{display:flex;align-items:center;gap:var(--s3);padding:var(--s3) var(--s5);
        border-bottom:1px solid var(--border2)}
  .vw-n{flex:1;font-size:13px;font-weight:600;overflow:hidden;text-overflow:ellipsis;
        white-space:nowrap}
  .vw-frame{flex:1;width:100%;border:0;background:var(--bg)}
  .vw-img{flex:1;min-height:0;object-fit:contain;background:var(--bg);padding:var(--s4)}
  .fvers{max-width:940px;margin:4px auto 0}
  .fvers-b{background:none;border:0;padding:0;color:var(--muted);font:inherit;font-size:12px;cursor:pointer;text-decoration:underline dotted}
  .fvers-b:hover{color:var(--text)}
  .fvers-l{display:flex;flex-direction:column;gap:3px;margin-top:5px;padding-left:2px}
  .fvers-i{color:var(--muted);font-size:12px;text-decoration:none}
  .fvers-i:hover{color:var(--text);text-decoration:underline}

  .live-dot{width:8px;height:8px;border-radius:50%;background:var(--green);box-shadow:0 0 6px var(--green);flex-shrink:0;animation:livepulse 1.2s ease-in-out infinite}
  @keyframes livepulse{0%,100%{opacity:1}50%{opacity:.25}}
  .statusline{font-size:12px;color:var(--violet);font-style:italic;margin-bottom:6px;display:flex;align-items:center;gap:7px}
  .statusline::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--violet);animation:livepulse 1s ease-in-out infinite}
  /* Activite du tour (2026-09-02) : la ligne de statut se deplie en journal. */
  .st-more{background:none;border:0;color:var(--muted);cursor:pointer;padding:0 var(--s1,4px);font-size:14px;line-height:1;transition:transform .15s}
  .st-more.open{transform:rotate(90deg)}
  .actfold{font-size:12px;color:var(--muted);border-left:2px solid var(--border);margin:2px 0 8px 2px;padding:2px 10px;display:flex;flex-direction:column;gap:2px}
  .actfold .act-l.live{color:var(--violet)}
  .approval.sel{cursor:pointer;user-select:none}
  .approval.sel:hover{border-color:var(--violet-dim);color:var(--text)}
  /* Approval lines sit in the turn's deliverables column: full width, left,
     one under the other at the same size (a centered shrink-to-fit line per
     command read as a staircase). */
  .deliv > .msg.ap{margin:0;width:100%}
  .apline{border-color:var(--amber);overflow:hidden;max-width:none;margin:0}
  .apline.resolved-ok{border-color:var(--green)} .apline.resolved-no{border-color:var(--red);opacity:.7}
  .apline .tc-dt{max-width:none;flex:1;min-width:0}
  .ap-ic{color:var(--amber)}
  .ap-risk{font-size:9px;text-transform:uppercase;letter-spacing:.4px;color:var(--amber);border:1px solid var(--amber);border-radius:4px;padding:1px 5px;flex-shrink:0}
  .ap-row{display:inline-flex;gap:6px;align-items:center;margin-left:auto;flex-shrink:0;font-size:12px;color:var(--muted);font-family:var(--sans)}
  .ap-ok,.ap-no{border:1px solid var(--border2);border-radius:7px;padding:3px 10px;cursor:pointer;font-size:12px;font-weight:600;font-family:var(--sans)}
  .ap-ok{background:var(--violet2);color:var(--on-accent);border-color:var(--violet)} .ap-no{background:var(--surface2);color:var(--text)}
  .anno-tray{display:flex;align-items:center;gap:10px;margin-bottom:8px;font-size:12px;color:var(--muted)}
  .anno-c{color:var(--violet)}
  .anno-send{background:var(--violet2);color:var(--on-accent);border:none;border-radius:8px;padding:6px 12px;font-size:12px;font-weight:600;cursor:pointer}
  .anno-x{background:transparent;border:1px solid var(--border2);color:var(--muted);border-radius:8px;padding:5px 9px;cursor:pointer;line-height:1}
  .anno-add{background:var(--violet2);color:var(--on-accent);border:none;border-radius:7px;padding:5px 10px;font-size:12px;font-weight:600;cursor:pointer;box-shadow:0 2px 8px var(--shadow-sm)}
  .anno-inp{background:var(--surface2);border:1px solid var(--violet-dim);border-radius:7px;padding:6px 10px;color:var(--text);font-size:13px;font-family:var(--sans);outline:none;width:260px}
  .imgwrap{display:block;max-width:940px;margin:0 auto;padding:0 32px}
  .imgcard{max-width:min(360px,100%);border-radius:10px;border:1px solid var(--border2);display:block}
  .attach{cursor:pointer;user-select:none} .attach:hover{border-color:var(--violet-dim);color:var(--text)}
  .img-tray{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:8px}
  .img-chip{position:relative;display:inline-block}
  .img-chip img{width:46px;height:46px;object-fit:cover;border-radius:7px;border:1px solid var(--border2)}
  .img-x{position:absolute;top:-6px;right:-6px;background:var(--surface2);border:1px solid var(--border2);color:var(--text);border-radius:50%;width:18px;height:18px;line-height:1;cursor:pointer;font-size:12px;padding:0}
  .gcard{max-width:940px;margin:0 auto;border:1px solid var(--violet-dim);background:var(--surface);border-radius:10px;padding:11px 14px}
  .g-h{font-size:12px;color:var(--violet);font-weight:600;margin-bottom:7px}
  .g-b{font-size:14px;color:var(--text2);line-height:1.55}
  .g-b ul,.g-b ol{margin:0 0 6px 20px} .g-b p{margin:0 0 6px}
  .approval.guard.on{color:var(--green);border-color:var(--green)}
  .approval.think-t.on{color:var(--violet);border-color:var(--violet)}
  .approval.lvl{opacity:.85}
  .sacard{max-width:940px;margin:0 auto;border:1px solid var(--border2);background:var(--bg2);border-radius:10px;padding:11px 14px}
  .sa-h{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--violet);font-weight:600;margin-bottom:6px}
  .sa-st{margin-left:auto;color:var(--faint);font-weight:400} .sa-st.ok{color:var(--green)}
  .sa-task{font-size:13px;color:var(--muted);font-style:italic;margin-bottom:7px}
  .sa-b{font-size:14px;color:var(--text2);line-height:1.55}
  .sa-b ul,.sa-b ol{margin:0 0 6px 20px} .sa-b p{margin:0 0 6px}
  .sa-inj{font-size:12px;color:var(--blue);margin:4px 0;font-family:var(--mono)}

  /* search, thread menu, stop, export, think, stt */
  /* V5: hidden until the magnifier is clicked. display:none rather than a
     height animation, because a collapsed-but-present field still takes the
     focus ring and still answers document.querySelector -- which is how a
     "closed" search box keeps eating keystrokes. */
  .side-search{margin:6px 12px;padding:7px 10px;border:1px solid var(--border);border-radius:8px;background:var(--surface);color:var(--text);font-size:13px;outline:none}
  .side-search.hid{display:none}
  .side-search::placeholder{color:var(--faint)}
  .side-search:focus{border-color:var(--violet-dim)}
  /* K2: min-width:0 est ce qui laisse le titre PROFITER de la largeur
     rendue par une barre plus large. Un item flex garde sinon la taille
     minimale de son contenu, et elargir la colonne ne change rien a ce
     qui est lisible : la meme troncature, dans plus large. */
  .th-t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}
  .th-dots{opacity:0;color:var(--faint);padding:0 2px;border-radius:5px;flex-shrink:0}
  .thread:hover .th-dots{opacity:1} .th-dots:hover{color:var(--text);background:var(--surface2)}
  /* K25 : la meme regle de survol que la ligne de conversation. Sans elle le
     « ... » du projet restait a opacity:0 pour toujours, et le menu (renommer,
     supprimer) n avait aucun chemin a la souris. */
  .grp-n{margin-left:auto;color:var(--faint);font-size:9px}
  /* K15 : les trois sigles etaient EPARS -- deux colles au mot « Conversations »,
     le troisieme jete a l autre bout par un margin-left:auto qui vivait sur
     lui. Ils forment desormais UN groupe, a droite du mot, avec la meme cible,
     le meme espacement et le meme survol pour les trois. Le margin-left:auto
     remonte donc sur le GROUPE : laisse sur un membre, il aurait continue de
     pousser ce membre seul. */
  .grp-acts{margin-left:auto;display:inline-flex;align-items:center;gap:var(--s1)}
  .fnew{cursor:pointer;color:var(--faint);font-size:11px;display:inline-flex;align-items:center;
        padding:0 3px;border-radius:5px}
  .fnew:hover{color:var(--text);background:var(--surface2)}
  /* K7: the card head carries the three skill actions as ICONS. A label
     each cost a row of its own and said nothing the icon and its title do
     not. */
  .bg-head{display:flex;align-items:center;gap:8px;margin-bottom:9px}
  .bg-acts{margin-left:auto;display:flex;gap:6px}
  .bg-ico{width:30px;height:30px;display:grid;place-items:center;cursor:pointer;border:1px solid var(--border2);border-radius:8px;background:var(--bg2);color:var(--muted);text-decoration:none}
  .bg-ico:hover{color:var(--violet);border-color:var(--violet-dim)}
  /* The stacked bar: one segment per component, widths PROPORTIONAL to the
     measured characters. Colour is the only thing that is decoration. */
  /* K24 : le fond est la PART LIBRE de la fenetre, pas un simple cadre. En
     --surface2 il se confondait avec la carte et la barre semblait pleine. */
  .bg-stack{display:flex;height:14px;border-radius:var(--r1);overflow:hidden;background:var(--border);margin:2px 0 9px}
  .bg-seg{height:100%;min-width:2px}
  .bg-seg.k-system{background:var(--violet-dim)}
  .bg-seg.k-doctrine{background:var(--violet2)}
  .bg-seg.k-tools{background:var(--violet)}
  .bg-seg.k-skills{background:var(--amber)}
  .bg-seg.k-rest{background:var(--border2)}
  .bg-leg{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--muted);padding:3px 0;border-bottom:1px solid var(--border2)}
  .bg-leg:last-child{border-bottom:0}
  .bg-sw{width:9px;height:9px;border-radius:3px;flex-shrink:0}
  .bg-leg .bg-nm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .bg-leg .bg-ch{font-family:var(--mono);font-size:11px;color:var(--faint);white-space:nowrap}
  .bg-sel{display:flex;gap:6px;margin-bottom:9px}
  .popmenu{position:fixed;z-index:80;background:var(--surface2);border:1px solid var(--border2);border-radius:9px;padding:5px;min-width:180px;box-shadow:0 8px 24px var(--shadow);font-size:13px}
  .pm-item{padding:7px 11px;border-radius:6px;cursor:pointer;color:var(--text)}
  .pm-item:hover{background:var(--surface)}
  .pm-item.danger{color:var(--red)}
  .pm-sep{height:1px;background:var(--border);margin:4px 6px}
  .send.stop{background:var(--surface2);color:var(--red);border:1px solid var(--red)}
  .tb-btn{cursor:pointer;color:var(--muted);font-size:14px;border:1px solid var(--border2);border-radius:8px;padding:3px 9px;user-select:none}
  .tb-btn:hover{color:var(--text);border-color:var(--violet-dim)}
  .ecard{max-width:940px;margin:0 auto;border:1px solid var(--red);background:var(--bg2);border-radius:9px;padding:8px 12px;color:var(--red-soft);font-size:13px;font-family:var(--mono)}
  .stopcard{max-width:940px;margin:0 auto;color:var(--faint);font-size:12px;font-family:var(--mono);padding:2px 0}
  .tcard.failed{border-color:var(--red)}
  .think{max-width:940px;margin:0 0 8px;border:1px solid var(--border);border-radius:9px;background:var(--bg2);font-size:13px;color:var(--muted)}
  .think summary{padding:6px 11px;cursor:pointer;color:var(--faint);font-size:12px;user-select:none}
  .think-b{padding:0 11px 9px;white-space:pre-wrap;line-height:1.5}
  .copybtn{margin-left:auto;opacity:0;background:transparent;border:1px solid var(--border2);color:var(--muted);border-radius:6px;padding:1px 7px;cursor:pointer;font-size:11px}
  .msg:hover .copybtn{opacity:1} .copybtn:hover{color:var(--text);border-color:var(--violet-dim)}
  .mic.recording{color:var(--red);border-color:var(--red);animation:livepulse 1s ease-in-out infinite}
  .main{position:relative}
  .gcard.tool{border-color:var(--amber)}

  /* v0.10 : sidebar Claude-like, filtres, archives, code blocks, mermaid */
  .grp-t.sec{font-size:11px;color:var(--muted);padding-top:14px}
  .grp-t.row{display:flex;align-items:center}
  .filterbtn{cursor:pointer;color:var(--faint);font-size:12px;padding:0 3px;border-radius:5px}
  .filterbtn:hover{color:var(--text);background:var(--surface2)}
  .thread.arch{opacity:.55}
  .cb-copy{position:absolute;top:6px;right:8px;opacity:0;background:var(--surface2);border:1px solid var(--border2);color:var(--muted);border-radius:6px;padding:1px 7px;cursor:pointer;font-size:11px}
  .bubble pre.cb{position:relative}
  .bubble pre.cb:hover .cb-copy{opacity:1}
  .cb-copy:hover{color:var(--text);border-color:var(--violet-dim)}
  .cb-lang{position:absolute;bottom:6px;right:10px;font-size:10px;color:var(--faint);text-transform:uppercase;letter-spacing:.5px}
  .mmd-box{background:var(--bg2);border:1px solid var(--border);border-radius:9px;padding:14px;margin:8px 0 12px;overflow-x:auto}
  .mmd-box svg{max-width:100%;height:auto}

  /* v0.11 : settings modal (prefs + skills), retry */
  .modal-bg{position:fixed;inset:0;background:var(--overlay);z-index:90;display:grid;place-items:center}
  .modal{width:min(620px,92vw);max-height:82vh;background:var(--bg2);border:1px solid var(--border2);border-radius:14px;display:flex;flex-direction:column;box-shadow:0 18px 60px var(--shadow-lg)}
  .modal-h{padding:13px 18px;font-weight:600;border-bottom:1px solid var(--border);display:flex;align-items:center}
  .modal-b{padding:16px 18px;overflow-y:auto}
  /* V3: sections had their own ad-hoc spacing and their labels were inline, so
     a two-word label and a ten-word one pushed their controls to different
     columns and nothing lined up down the page. One rhythm (18px between
     sections) and one row gabarit (a fixed label column) fix both at once. */
  .set-sec{font-size:11px;text-transform:uppercase;letter-spacing:.7px;color:var(--faint);margin:18px 0 9px}
  .set-sec:first-child{margin-top:0}
  .set-ta,.set-in{width:100%;background:var(--surface);border:1px solid var(--border2);border-radius:9px;padding:9px 11px;color:var(--text);font-size:13px;font-family:var(--sans);outline:none;margin-bottom:8px;resize:vertical}
  .set-ta:focus,.set-in:focus{border-color:var(--violet-dim)}
  /* One width, not one per longest option: two selects sized on their own text
     start at the same x and end at different ones, which is half of what
     "aucun sous-menu n est aligne" was pointing at. `.tight` is for the rows
     carrying three controls behind one label (Programme). */
  .set-sel{background:var(--surface);border:1px solid var(--border2);border-radius:8px;padding:7px 9px;color:var(--text);font-size:13px;outline:none;width:210px}
  .set-sel.tight{width:auto}
  /* V3: the label gets a FIXED column so every control in every section starts
     at the same x -- which is all "nothing is aligned" was about. It stays a
     flex row on purpose: a real grid with three named columns broke the
     Programme row, where one label is followed by THREE selects (hour, days,
     surface) and the third wrapped onto a line of its own. A flex basis
     aligns the same way and does not care how many controls follow. */
  /* Capped so the Save button stays NEXT TO the control it saves. Now that the
     card is full width, margin-left:auto would park it 700px away from the
     select, which reads as an unrelated button. The textarea above keeps the
     whole card width -- it is the one field that gains from it. */
  .set-row{display:flex;align-items:center;gap:12px;margin-bottom:10px;flex-wrap:wrap;max-width:940px}
  .set-lb{font-size:13px;color:var(--muted);flex:0 0 170px}
  .set-btn{background:var(--violet2);color:var(--on-accent);border:none;border-radius:8px;padding:7px 14px;font-size:13px;font-weight:600;cursor:pointer;margin-left:auto}
  .set-btn.sm{padding:4px 10px;font-size:12px;margin-left:auto}
  /* K18 : la phrase qui dit ce qu un reglage NE change pas. */
  .set-hint{color:var(--muted);font-size:var(--fs-sm);line-height:1.55;margin:0 0 var(--s5)}
  .set-btn.danger{background:var(--surface2);color:var(--red);border:1px solid var(--red)}
  .set-btn.retry{margin-left:10px}
  .set-chk{display:flex;align-items:center;gap:7px;font-size:13px;color:var(--muted);margin-bottom:8px}
  .sk-list{display:flex;flex-direction:column;gap:6px}
  .sk-row{display:flex;align-items:center;gap:10px;border:1px solid var(--border);border-radius:9px;padding:8px 11px;background:var(--surface)}
  .sk-row .set-chk{margin:0}
  .sk-nm{font-weight:600;font-size:13px;display:flex;align-items:center;gap:7px}
  .sk-pin{font-size:9px;text-transform:uppercase;color:var(--violet);border:1px solid var(--violet-dim);border-radius:4px;padding:1px 5px}
  .sk-ds{flex:1;color:var(--faint);font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .sk-form{border:1px solid var(--violet-dim);border-radius:10px;padding:11px;background:var(--bg)}
  .sk-actions{display:flex;gap:8px}
  .sk-empty{color:var(--faint);font-size:13px;padding:6px 2px}
  .set-in.tm{width:auto;min-width:0;margin-bottom:0}
  .set-row .set-sel{margin-bottom:0}

  .img-note{max-width:940px;margin:4px auto 0;padding:0 32px;font-size:12px;color:var(--faint);font-style:italic}

  /* v0.13 : attachments, tts, edit/regen */
  .atcard{display:flex;align-items:center;gap:12px;max-width:940px;margin:0 auto;border:1px dashed var(--border2);background:var(--bg2);border-radius:10px;padding:8px 13px;color:var(--text)}
  .fic.sm{width:34px;height:40px;font-size:17px}
  .copybtn.tts,.copybtn.act-edit,.copybtn.act-regen{margin-left:6px}
  .msg:hover .act-edit,.msg:hover .act-regen{opacity:1}
  .act-edit,.act-regen{opacity:0}

  /* v0.12 : nav, mobile drawer */
  .navlist{padding:0 8px 4px}
  .navitem{padding:7px 10px;border-radius:7px;color:var(--muted);font-size:13px;cursor:pointer;display:flex;align-items:center;gap:8px}
  .navitem:hover{background:var(--surface);color:var(--text)}
  .burger{display:none;cursor:pointer;color:var(--muted);font-size:17px;padding:2px 8px;border-radius:7px}
  .burger:hover{color:var(--text);background:var(--surface)}
  .side-ov{position:fixed;inset:0;background:var(--overlay-soft);z-index:44}


  /* --- sidebar filters (D5) ------------------------------------------------
     ONE entry point at the head of the list, each line showing its current
     value on the right and opening its choices in place. It replaces a menu
     whose "Type" / "Statut" / "Grouper par" lines LOOKED like headers but were
     clickable no-ops that closed the menu -- three taps that did nothing. */
  .fpop{position:fixed;z-index:60;width:284px;max-height:72vh;overflow-y:auto;background:var(--surface);border:1px solid var(--border2);border-radius:11px;box-shadow:0 12px 34px var(--shadow-lg);padding:6px}
  .fp-row{display:flex;align-items:center;gap:8px;min-height:31px;padding:0 10px;border-radius:8px;cursor:pointer;font-size:13px;color:var(--text);line-height:1.25;white-space:nowrap;overflow:hidden}
  .fp-row:hover{background:var(--surface2)}
  .fp-v{margin-left:auto;display:flex;align-items:center;gap:6px;color:var(--muted);font-size:12px;min-width:0;overflow:hidden}
  .fp-v>:first-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .fp-ca{color:var(--faint);font-size:13px;transition:transform .12s;display:inline-block}
  .fp-row.open .fp-ca{transform:rotate(90deg)}
  .fp-opts{display:none;padding:1px 0 5px}
  .fp-opts.open{display:block}
  .fp-opt{display:flex;align-items:center;gap:7px;min-height:28px;padding:0 10px 0 12px;border-radius:8px;cursor:pointer;font-size:13px;line-height:1.25;color:var(--muted)}
  .fp-opt:hover{background:var(--surface2);color:var(--text)}
  .fp-opt.on{color:var(--violet)}
  .fp-opt .tick{width:13px;flex-shrink:0}
  .fp-sep{height:1px;background:var(--border);margin:5px 8px}
  .fp-reset{display:flex;align-items:center;min-height:31px;line-height:1.25;padding:0 10px;border-radius:8px;cursor:pointer;font-size:13px;color:var(--muted)}
  .fp-reset:hover{background:var(--surface2);color:var(--text)}
  .fp-reset.off{opacity:.45;cursor:default}
  .fp-reset.off:hover{background:none;color:var(--muted)}
  /* A filtered list that hides everything must not read as an empty account. */
  .side-empty{color:var(--faint);font-size:12px;padding:8px 10px;line-height:1.5}
  .side-empty b{display:block;color:var(--violet);cursor:pointer;font-weight:400;margin-top:5px}
  .filterbtn.on{color:var(--violet)}
  /* --- Monitor panel (D4a, D-D4) -------------------------------------------
     A COLUMN of the app grid, not an overlay: a monitor that hides what it
     monitors is a monitor nobody leaves open. Every figure it shows already
     exists elsewhere -- U1 tool events, the run row, the tree the exec runner
     returns, /api/prompt-budget -- so the panel invents nothing and needs no
     backend of its own beyond the single `mon` aggregation event.
     Palette: theme tokens only. --violet* is the ACCENT token, so this panel
     is blue in Abysse and green in Foret, like everything else (D-D1). */
  /* Discreet on purpose: it is an affordance, not a control to look at.
     It only gains contrast on hover and on keyboard focus. */
  /* Context popover: the breakdown of what a turn costs, à la Claude client.
     Fixed-positioned so it escapes the panel's own overflow container. */
  .ctx-pop{position:fixed;z-index:60;width:312px;max-height:70vh;overflow-y:auto;background:var(--surface);border:1px solid var(--border2);border-radius:11px;box-shadow:0 12px 34px var(--shadow-lg);padding:12px 13px}
  .ctx-pop h4{font-size:12px;font-weight:600;color:var(--text);margin:0 0 3px}
  .ctx-pop .sub{font-size:11px;color:var(--faint);margin-bottom:9px;line-height:1.5}
  .ctx-pp{display:flex;align-items:center;gap:7px;font-size:12px;padding:3px 0}
  .ctx-pp .sw{width:8px;height:8px;border-radius:2px;flex-shrink:0}
  .ctx-pp .nm{color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .ctx-pp .tk{margin-left:auto;font-family:var(--mono);font-size:11px;color:var(--muted);flex-shrink:0}
  .ctx-stack{display:flex;height:8px;border-radius:4px;overflow:hidden;margin:7px 0 10px;background:var(--border)}
  .ctx-stack i{display:block;height:100%}
  /* --- mobile pass (D3, D-D3 perimetre etendu) -----------------------------
     Two rules drive almost everything here and neither is cosmetic:
     16px on any focusable field, because iOS zooms the page when a focused
     input is smaller and never zooms back out; and 44px on anything meant to
     be tapped, because the 28px pills that are right for a mouse are a
     coin-flip for a thumb. safe-area padding keeps the composer and the status
     bar clear of the home indicator. */
  @media (max-width: 768px){
    .main.blank .greet{font-size:22px}
    .main.blank .box textarea{font-size:17px;min-height:60px}
    .app{grid-template-columns:1fr}
    /* K37. Sur un telephone la hauteur est la ressource rare. La barre du haut
       tombe de 46 a 40 px et ses cibles de 40/44 a 38, qui reste le plancher
       que le banc garde : le pouce touche toujours, et le fil gagne 6 px. La
       barre de tete du volet suit, elle est cadree sur la barre du haut. */
    .topbar{height:40px;padding:0 12px}
    .side-head{height:40px}
    /* Et le fil n a pas besoin de 24 px de marge au-dessus du premier message
       quand l ecran en fait 390 de large : 14 px de plus pour le contenu. */
    .stream{padding:10px 0}
    .side{position:fixed;top:0;bottom:0;left:0;width:min(86vw,300px);z-index:45;transform:translateX(-100%);transition:transform .18s ease;padding-bottom:env(safe-area-inset-bottom)}
    .side.open{transform:translateX(0)}
    .burger{display:inline-flex;align-items:center;justify-content:center;min-width:38px;height:38px;font-size:19px;padding:0}
    .msg{padding:0 14px 20px}
    .msg.u .bubble{max-width:92%}
    .imgwrap,.img-note{padding:0 14px}
    /* K37 (MESURE du 2026-09-01). Le composer n est PAS le dernier element de
       la colonne : la barre d etat l est, et c est elle qui degage le home
       indicator. Le padding de safe-area pose ici s ajoutait donc EN PLEIN
       MILIEU de la colonne, 34 px perdus sur un iPhone 14/15, entre le
       composer et la barre d etat. Rendus au fil. */
    .composer{padding:0 12px 10px}
    .box{padding:10px 12px 8px}
    /* THE iOS rule: under 16px, focusing zooms the page and it stays zoomed. */
    .box textarea,.set-ta,.set-in,.set-sel{font-size:16px}
    /* Touch targets. 44px is the smallest a thumb hits reliably; the pills go
       to 38px + spacing rather than 44 so the composer row still fits one
       line on a 360px screen, and the row itself gets the breathing space. */
    .send,.approval{height:38px;line-height:36px;font-size:14px}
    .send{padding:0 18px}
    .approval.plus{width:38px;line-height:36px}
    .row{gap:8px;margin-top:10px}
    .tb-btn{min-width:38px;height:38px;display:inline-flex;align-items:center;justify-content:center;padding:0}
    .navitem{min-height:44px}
    .set-navi{min-height:44px}
    .approval{max-width:150px}
    .pillwrap{margin-left:auto}
    /* Tool cards: full width of the thread, and the detail line stops fighting
       the 330px cap it was given for a desktop column. */
    .tcard,.fcard,.atcard,.gcard,.sacard,.ecard{min-width:0}
    .tc-dt{max-width:none;flex:1;min-width:0}
    .tc-nm{flex-shrink:0}
    /* Status bar: the labels go, the figures stay. */
    .status{height:calc(32px + env(safe-area-inset-bottom));align-items:flex-start;padding-bottom:env(safe-area-inset-bottom)}
    .st-i{padding:0 10px;height:32px}
    .st-i .k{display:none}
    .st-ctx .k{display:inline}
    .thread{padding:11px 10px;min-height:44px;white-space:normal}
    .th-dots{opacity:1;min-width:38px;height:38px;display:flex;align-items:center;justify-content:center;padding:0}
    /* Skills rows wrap instead of squeezing the description to nothing. */
    .fpop{width:min(92vw,300px)}
    .fp-row,.fp-reset{min-height:44px}
    .fp-opt{min-height:40px}
    .sk-row{flex-wrap:wrap;min-height:48px}
    .sk-ds{flex:1 0 100%;white-space:normal;order:3}
    .set-btn{padding:9px 16px;font-size:13px}
    .set-btn.sm{padding:7px 12px;font-size:13px}
    .set-row{flex-wrap:wrap;gap:9px}
    /* K33. Le geste qui fait defiler le fil est aussi celui qui replie la
       chrome de Safari : sans `contain`, le depassement se propage au document
       et ce chainage fait bouger la chrome pendant la lecture. Identifie a l
       inspection, NON MESURE : aucune emulation ne rejoue l inertie tactile. */
    .stream,.side-scroll{overscroll-behavior:contain}
    /* K34. La rangee du composer est ce qui manque de place a 390 px, et ces
       deux chips sont les plus longues (210 px et 137 px mesurees). Elles
       tombent a l icone seule ; le libelle complet reste dans l infobulle et
       dans aria-label. */
    .approval.k34{padding:0;width:38px;display:inline-grid;place-items:center}
    .approval.k34 .k34-ic{display:block}
    .approval.k34 .lab{display:none}
    /* K35. Le titre de la conversation est deja dans la barre laterale ; la
       barre du haut garde le burger et les actions. */
    .topbar .ttl{display:none}
  }
