  :root {
    --gold: #c9a55a; --gold-dim: #8a7038;
    --panel: #16151a; --panel-2: #1e1c22;
    --ink: #e8e0cf; --ink-dim: #9a917e; --danger: #c05545;
    --r-red:#c05545; --r-orange:#d08a3e; --r-green:#7aa35e; --r-blue:#6ea3c9; --r-grey:#777;
  }
  * { margin:0; padding:0; box-sizing:border-box; user-select:none; }
  body {
    font-family: Georgia, 'Times New Roman', serif;
    background:#0b0a0e; color:var(--ink);
    display:flex; flex-direction:column; align-items:center;
    min-height:100vh; padding:12px 12px 30px;
  }
  #wrap { position:relative; width:1240px; max-width:100%; }
  #gameFrame {
    position:relative; border:1px solid var(--gold-dim); outline:1px solid #000;
    box-shadow:0 0 0 3px #16151a, 0 12px 40px rgba(0,0,0,.7); overflow:hidden;
  }
  canvas { display:block; width:100%; height:auto; }

  /* petite icône du monstre de la zone en cours, en haut à gauche — demande explicite du 2026-07-07 */
  #zoneMobIcon { position:absolute; top:8px; left:10px; width:34px; height:34px; border-radius:50%;
    border:1.5px solid var(--gold-dim); background:rgba(10,9,14,.55); box-shadow:0 2px 6px rgba(0,0,0,.5); }
  #zoneTitle { position:absolute; top:10px; left:52px; font-size:15px; letter-spacing:2px; text-shadow:0 1px 3px #000; }
  #zoneTitle small { display:block; font-size:10px; letter-spacing:3px; color:var(--gold); text-transform:uppercase; }
  #zoneBadge { display:inline-block; font-size:10px; letter-spacing:1px; padding:1px 8px; border:1px solid; margin-top:3px; }
  #ztReq { display:block; font-size:10.5px; letter-spacing:.5px; margin-top:4px; color:var(--ink-dim); text-transform:none; }
  /* état du Compendium affiché dans la zone de farm — demande explicite du 2026-07-08 */
  #ztCompendium { display:inline-block; font-size:9.5px; letter-spacing:.5px; margin-top:3px; color:var(--ink-dim); text-transform:none; cursor:pointer; }
  #ztCompendium.complete { color:var(--gold); font-weight:bold; }
  #ztReq .ok { color:#8fc98a; } #ztReq .bad { color:var(--danger); }
  #silverBox {
    position:absolute; top:10px; right:14px; background:rgba(10,9,12,.72);
    border:1px solid var(--gold-dim); padding:5px 12px; font-size:14px;
    display:flex; align-items:center; gap:7px;
  }
  #silverBox .coin { width:12px; height:12px; border-radius:50%;
    background:radial-gradient(circle at 35% 30%, #fdf3d0, #c9a55a 60%, #8a7038);
    box-shadow:0 0 4px rgba(201,165,90,.6); }
  #shRate { position:absolute; top:44px; right:14px; font-size:11px; color:var(--ink-dim); text-shadow:0 1px 2px #000; }
  #lootTicker {
    position:absolute; bottom:14px; right:14px; text-align:right;
    font-size:11px; color:var(--ink-dim); max-height:250px; overflow:hidden;
    text-shadow:0 1px 2px #000; line-height:1.5;
    /* corrigé le 2026-07-07 : column-reverse faisait en réalité apparaître les NOUVELLES entrées
       en haut (déjà fondues par le masque) et les anciennes en bas (bien visibles juste avant
       d'être supprimées) — l'inverse de ce qui était voulu. "column" simple + appendChild place
       chaque nouvelle entrée tout en bas (nette), qui pousse les précédentes vers le haut où elles
       s'estompent avant d'être retirées. */
    display:flex; flex-direction:column;
    -webkit-mask-image:linear-gradient(to bottom, transparent, rgba(0,0,0,.15) 25%, black 65%);
    mask-image:linear-gradient(to bottom, transparent, rgba(0,0,0,.15) 25%, black 65%);
  }
  #lootTicker .trashLoot { color:#fff; }
  #lootTicker .matLoot { color:#6ea3c9; }
  #lootTicker .rare { color:#b48ce8; }
  #lootTicker .jackpot { color:#e8b84a; font-weight:bold; }
  /* effet visuel pour le butin rare et au-delà (rare/jackpot) : flash doré à l'apparition + lueur
     douce en continu, pour que ces lignes sautent vraiment aux yeux dans le flux de loot */
  #lootTicker .rare, #lootTicker .jackpot { animation:lootRarePop .5s ease-out, lootRareGlow 1.8s ease-in-out .5s infinite; }
  @keyframes lootRarePop { 0% { transform:scale(1.35); opacity:0; } 100% { transform:scale(1); opacity:1; } }
  @keyframes lootRareGlow {
    0%,100% { text-shadow:0 1px 2px #000, 0 0 6px rgba(180,140,232,.5); }
    50% { text-shadow:0 1px 2px #000, 0 0 12px rgba(180,140,232,.95); }
  }
  #lootTicker .jackpot { animation-name:lootRarePop, lootJackpotGlow; }
  @keyframes lootJackpotGlow {
    0%,100% { text-shadow:0 1px 2px #000, 0 0 6px rgba(232,184,74,.6); }
    50% { text-shadow:0 1px 2px #000, 0 0 14px rgba(232,184,74,1); }
  }

  #invFullBanner {
    position:absolute; top:10px; left:50%; transform:translateX(-50%);
    background:rgba(192,85,69,.92); color:#fff; font-size:12px; font-weight:bold;
    padding:6px 16px; letter-spacing:.5px; display:none; z-index:20;
    box-shadow:0 4px 14px rgba(0,0,0,.5); animation:invFullPulse 1.4s infinite;
  }
  #invFullBanner.show { display:block; }
  @keyframes invFullPulse { 0%,100% { opacity:1; } 50% { opacity:.65; } }
  #deathBanner {
    position:absolute; top:44px; left:50%; transform:translateX(-50%);
    background:rgba(20,10,10,.94); border:1px solid var(--danger); color:#e8a89f; font-size:12px; font-weight:bold;
    padding:8px 18px; letter-spacing:.3px; display:none; z-index:21; text-align:center; max-width:80%;
    box-shadow:0 4px 14px rgba(0,0,0,.6);
  }
  #deathBanner.show { display:block; }
  /* alerte de zone dangereuse (2026-07-05, demande explicite) : rappelle en permanence que le
     ralenti/l'accélération des monstres est en cours -- s'empile sous invFullBanner/deathBanner */
  #dangerBanner {
    position:absolute; top:78px; left:50%; transform:translateX(-50%);
    background:rgba(192,85,69,.92); color:#fff; font-size:11.5px; font-weight:bold;
    padding:5px 14px; letter-spacing:.3px; display:none; z-index:19; text-align:center; max-width:85%;
    box-shadow:0 4px 14px rgba(0,0,0,.5); animation:invFullPulse 1.4s infinite;
  }
  #dangerBanner.show { display:block; }

  /* bannière d'annonce importante (ex: reset complet des comptes) — demande explicite du
     2026-07-06 : "restylise le bien avec de la couleur" */
  .resetNoticeOverlay {
    position:fixed; inset:0; background:rgba(8,7,10,.85); -webkit-backdrop-filter:blur(3px); backdrop-filter:blur(3px);
    display:none; align-items:center; justify-content:center; z-index:900;
  }
  .resetNoticeOverlay.show { display:flex; }
  .resetNoticeCard {
    max-width:480px; margin:20px; padding:26px 24px; border-radius:12px;
    background:linear-gradient(160deg, #2a2440 0%, #1a1f38 55%, #241a2e 100%);
    border:1px solid var(--gold-dim); box-shadow:0 0 50px rgba(201,165,90,.25), 0 12px 40px rgba(0,0,0,.6);
    text-align:center; animation:resetNoticeIn .35s ease;
  }
  @keyframes resetNoticeIn { from{opacity:0; transform:scale(.92) translateY(10px);} to{opacity:1; transform:scale(1) translateY(0);} }
  .resetNoticeIcon { font-size:40px; margin-bottom:10px; filter:drop-shadow(0 0 10px rgba(201,165,90,.5)); }
  .resetNoticeTitle {
    font-size:17px; font-weight:bold; margin-bottom:14px; line-height:1.3;
    background:linear-gradient(90deg,#e8c96a,#8cc8ff); -webkit-background-clip:text; background-clip:text; color:transparent;
  }
  .resetNoticeBody { font-size:13px; line-height:1.6; color:var(--ink); text-align:left; margin-bottom:20px; }
  .resetNoticeBody b { color:var(--gold); }
  #resetNoticeClose {
    width:auto; padding:10px 28px; background:linear-gradient(90deg,#c9a55a,#8cc8ff);
    border:none; color:#141319; font-weight:bold; border-radius:6px; font-size:13px;
  }
  #resetNoticeClose:hover { filter:brightness(1.08); }

  /* bandeau "N notes non lues" DANS le panneau des notes de version lui-même (2026-07-06,
     demande explicite : "enleve la pastille en haut de l'ecran... je veux que tu la mette dans
     note de version directement pour appel au scroll vers le haut") -- remplace l'ancienne
     pastille flottante en haut de page, qui chevauchait le panneau. Collé en haut du contenu
     défilant (position:sticky) : reste visible pendant le défilement, cliquer scrolle en haut
     où sont les entrées non lues. */
  #patchUnreadBanner {
    display:none; position:sticky; top:0; z-index:5; cursor:pointer;
    align-items:center; gap:8px; margin:-16px -18px 12px; padding:8px 18px;
    background:var(--panel-2); border-bottom:1px solid var(--danger); color:var(--ink);
    font-size:11.5px; box-shadow:0 4px 10px rgba(0,0,0,.4); animation:patchHalo 1.6s infinite;
  }
  #patchUnreadBanner.show { display:flex; }
  #patchUnreadBannerNum {
    background:var(--danger); color:#fff; font-weight:bold; font-size:10.5px;
    min-width:16px; height:16px; border-radius:8px; display:flex; align-items:center; justify-content:center;
    flex-shrink:0;
  }
  #updateToast {
    position:fixed; top:18px; left:50%; transform:translateX(-50%) translateY(-20px);
    background:var(--panel-2); border:1px solid var(--gold); color:var(--ink);
    padding:12px 16px; display:none; align-items:center; gap:14px;
    box-shadow:0 8px 28px rgba(0,0,0,.6); z-index:200; font-size:13px;
    opacity:0; transition:opacity .25s ease, transform .25s ease;
  }
  #updateToast.show { display:flex; opacity:1; transform:translateX(-50%) translateY(0); }
  #updateToast .updVer { color:var(--gold); font-weight:bold; }

  /* un seul carré pour "en ligne" + "inscrits" (demande explicite du 2026-07-06 : "fais un seul
     carré avec en ligne et inscrit juste en dessous") -- avant, 2 boîtes distinctes empilées */
  #onlineStatsBox {
    background:rgba(10,9,12,.6); border:1px solid #2c2a33; padding:8px 14px;
    text-align:center; display:flex; flex-direction:column; gap:3px;
  }
  #onlineCounter { font-size:11px; color:var(--ink-dim); letter-spacing:.3px; }
  #onlineCounter b { color:#8fc98a; }
  #onlineGuests { color:var(--ink-dim); }
  #registeredCounter { font-size:10.5px; color:var(--ink-dim); letter-spacing:.3px; }
  #registeredCounter b { color:#9cc9e8; }
  #updateToast button {
    background:var(--gold); color:#1a1712; border:none; font-weight:bold;
    padding:7px 14px; letter-spacing:.5px; cursor:pointer; font-family:inherit; font-size:12.5px;
  }
  #updateToast button:hover { background:#e0bc72; }

  #aiState {
    position:absolute; top:10px; left:50%; transform:translateX(-50%);
    font-size:10px; letter-spacing:3px; text-transform:uppercase;
    color:#9cc9e8; background:rgba(10,9,12,.6); border:1px solid #2c3a4a;
    padding:4px 14px; white-space:nowrap;
  }
  #aiSkill { color:var(--gold); }
  #farmModeBtn {
    position:absolute; top:10px; left:calc(50% + 165px);
    font-size:10px; letter-spacing:1px; text-transform:uppercase; cursor:pointer;
    color:var(--gold); background:rgba(10,9,12,.6); border:1px solid var(--gold-dim);
    padding:4px 10px; white-space:nowrap; border-radius:3px;
  }
  #farmModeBtn:hover { background:rgba(201,165,90,.15); }

  #skillBar { position:absolute; bottom:10px; left:50%; transform:translateX(-50%); display:flex; gap:5px; }
  /* barre d'incantation (2026-07-05, demande explicite : "----------o----------", la matière se
     retire des 2 côtés vers le centre, le sort part quand elle a disparu) -- juste au-dessus de
     la barre de sorts, cachée hors incantation (voir renderCastBar()) */
  #castBar {
    display:none; position:absolute; bottom:58px; left:50%; transform:translateX(-50%);
    align-items:center; width:220px; height:8px;
  }
  #castBar.show { display:flex; }
  #castBarLeft, #castBarRight { flex:1; height:2px; background:var(--gold); }
  #castBarLeft { transform-origin:right center; }
  #castBarRight { transform-origin:left center; }
  #castBarCenter {
    width:7px; height:7px; border-radius:50%; background:var(--gold); flex-shrink:0;
    box-shadow:0 0 6px rgba(201,165,90,.85); margin:0 -1px; z-index:1;
  }
  #castBarLabel {
    position:absolute; top:-13px; left:50%; transform:translateX(-50%);
    font-size:9px; color:var(--gold); white-space:nowrap; letter-spacing:.3px;
  }
  /* bouton de repli de la barre de sorts — invisible sur ordinateur (voir media query mobile),
     n'a de sens que sur petit écran où la place manque (2026-07-05, demande explicite) */
  #skillBarToggle { display:none; }
  .sk {
    width:42px; height:42px; position:relative;
    background:linear-gradient(180deg,#22202a,#161419);
    border:1px solid var(--gold-dim); overflow:hidden;
    display:flex; flex-direction:column; align-items:center; justify-content:center;
  }
  .sk .ic { font-size:15px; line-height:1; z-index:2; }
  .sk .nm { font-size:7px; letter-spacing:.4px; color:var(--ink-dim); z-index:2; margin-top:2px; text-align:center; }
  .sk .cd { position:absolute; left:0; bottom:0; width:100%; background:rgba(0,0,0,.72); z-index:1; }
  .sk.cast { border-color:#9cc9e8; box-shadow:0 0 8px rgba(140,200,255,.5); }
  .sk.buffed { border-color:var(--gold); box-shadow:0 0 8px rgba(201,165,90,.5); }

  #hpPotWrap { position:absolute; bottom:12px; left:14px; display:flex; align-items:center; gap:8px; }
  /* PV au-dessus de la mana, potion de PV au-dessus de la potion de mana (2026-07-05,
     demande explicite) -- 2 colonnes plutôt qu'une rangée qui déborderait sur mobile */
  #hpMpStack, #potStack { display:flex; flex-direction:column; gap:4px; }
  /* niveau + % d'XP déplacés à côté de la barre de PV, plus dans l'inventaire (2026-07-06,
     demande explicite : "aligne le niveau et le % a coté de la barre de vie" -- remplace l'ancien
     empilement au-dessus). Agrandi façon BDO (capture à l'appui) : niveau et % aussi gros l'un que
     l'autre, empilés dans leur propre colonne étroite, juste à gauche des barres PV/mana. */
  #lvlHpCol { display:flex; flex-direction:row; align-items:center; gap:8px; }
  #lvlHpCol #lvlXpRow {
    display:flex; flex-direction:column; width:auto; margin:0; padding:2px 6px; border:1px solid transparent; border-radius:4px;
    transition:border-color .25s, box-shadow .25s, background-color .25s;
  }
  /* s'illumine brièvement à chaque gain d'XP (2026-07-10, demande explicite) — voir flashXpGain()
     dans gainXp() (game-core.js) */
  #lvlHpCol #lvlXpRow.xpFlash {
    border-color:var(--gold); box-shadow:0 0 10px 2px rgba(201,165,90,.7); background-color:rgba(201,165,90,.14);
  }
  #lvlXpTop { display:flex; align-items:baseline; gap:5px; text-shadow:0 1px 3px #000; }
  #lvlXpLbl { font-size:12px; color:var(--ink-dim); font-weight:normal; }
  #lvlHpCol #lvlXpRow b { color:#fff; font-size:22px; font-weight:bold; line-height:1; }
  #lvlHpCol #invXpPct { color:var(--gold); font-variant-numeric:tabular-nums; font-size:22px; font-weight:bold; line-height:1; text-shadow:0 1px 3px #000; }
  #hpBar, #mpBar { width:170px; height:13px; background:rgba(0,0,0,.65); border:1px solid #444; position:relative; }
  #hpFill { height:100%; width:100%; background:linear-gradient(90deg,#a33d34,#c05545); transition:width .15s; }
  /* barre de mana (2026-07-05, demande explicite) : même gabarit que la barre de PV, juste en dessous */
  #mpBar { width:170px; height:10px; }
  #mpFill { height:100%; width:100%; background:linear-gradient(90deg,#2f5c8a,#4a8fc8); transition:width .15s; }
  #hpPct, #mpPct {
    position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
    font-size:9.5px; font-weight:bold; color:#fff; text-shadow:0 1px 2px #000; font-variant-numeric:tabular-nums;
  }
  #mpPct { font-size:8.5px; }
  /* case unique vie+mana (2026-07-08) : remplace les 2 cases séparées #potSlot/#manaPotSlot --
     le clic ouvre un seul panneau pour les 2 potions, chaque moitié suit son propre CD */
  #potSlot { width:44px; height:34px; position:relative; border:1px solid var(--gold-dim);
    background:#191720; display:flex; align-items:center; justify-content:center; overflow:hidden; cursor:pointer; }
  #potSlot:hover { border-color:var(--gold); }
  #potDualIcon { width:100%; height:100%; display:flex; }
  #potDualIcon svg { width:100%; height:100%; }
  #potCd { position:absolute; left:0; bottom:0; width:50%; background:rgba(0,0,0,.75); }
  #manaPotCd { position:absolute; right:0; bottom:0; width:50%; background:rgba(0,0,0,.75); }
  #potSelect {
    display:none; position:absolute; bottom:52px; left:14px; z-index:30; width:210px;
    background:rgba(12,10,15,.95); border:1px solid var(--gold-dim); border-radius:6px; padding:6px;
    box-shadow:0 8px 24px rgba(0,0,0,.6);
  }
  #potSelect.show { display:block; }
  #potSelect .psRow {
    display:flex; align-items:center; gap:8px; padding:6px 5px; cursor:pointer; border-radius:4px; font-size:11px;
  }
  #potSelect .psRow:hover { background:rgba(201,165,90,.12); }
  #potSelect .psRow.sel { background:rgba(201,165,90,.18); border:1px solid var(--gold-dim); }
  #potSelect .psRow.locked { opacity:.45; cursor:not-allowed; }
  #potSelect .psRow.locked:hover { background:transparent; }
  #potSelect .psRow.locked .psCost { color:var(--ink-dim); }
  #potSelect .psIcon { font-size:16px; width:20px; text-align:center; flex-shrink:0; }
  #potSelect .psInfo { flex:1; min-width:0; }
  #potSelect .psName { color:var(--ink); }
  #potSelect .psHeal { color:#8fc98a; font-size:10px; }
  #potSelect .psCost { color:var(--gold); font-variant-numeric:tabular-nums; flex-shrink:0; font-size:10.5px; }
  /* panneau vie+mana fusionné (2026-07-08) : sépare visuellement les 2 sections, la ligne mana
     est purement informative (pas de choix de taille, elle boit automatiquement sous 30% mana) */
  #potSelect .psSectionLabel { font-size:9.5px; letter-spacing:.5px; text-transform:uppercase; color:var(--ink-dim);
    padding:6px 5px 3px; border-top:1px solid #2c2a33; margin-top:2px; }
  #potSelect .psSectionLabel:first-child { border-top:none; margin-top:0; }
  #potSelect .psRow.psRowInfo { cursor:default; }
  #potSelect .psRow.psRowInfo:hover { background:transparent; }
  #potSelect .psRow.psRowInfo .psIcon { color:#8fc4e6; }
  #potThreshRow { display:flex; align-items:center; gap:7px; padding:4px 5px 8px; border-bottom:1px solid #2c2a33; margin-bottom:4px; font-size:10.5px; color:var(--ink-dim); }
  #potThreshRow input[type=range] { flex:1; accent-color:var(--gold); }
  #potThreshVal { color:var(--gold); font-variant-numeric:tabular-nums; width:32px; text-align:right; flex-shrink:0; }

  #panel {
    margin-top:8px; background:var(--panel);
    border:1px solid #2c2a31; border-top:1px solid var(--gold-dim);
    display:grid; grid-template-columns:repeat(3, 1fr); gap:8px; padding:8px;
  }
  .card { background:var(--panel-2); border:1px solid #2c2a31; padding:7px 10px; }
  .card h3 { font-size:9.5px; letter-spacing:2.5px; text-transform:uppercase; color:var(--gold);
    font-weight:normal; margin-bottom:5px; border-bottom:1px solid #2c2a31; padding-bottom:4px; }
  #btnLifeskillToggle {
    width:auto; margin:0 0 0 6px; padding:1px 6px; font-size:12px; background:transparent;
    border:1px solid var(--gold-dim); vertical-align:middle;
  }
  .cell.catHidden { display:none; }
  .invCatEmpty { grid-column:1/-1; text-align:center; color:var(--ink-dim); font-style:italic; font-size:11px; padding:14px 0; }
  .row { display:flex; justify-content:space-between; align-items:center; margin:2.5px 0; font-size:11.5px; }
  /* onglet "Recommandations" de la carte Statistiques (2026-07-09, demande explicite) : chaque
     ligne (meilleur silver/xp/kills) mène directement à la zone concernée */
  .statsRecoRow { cursor:pointer; padding:3px 4px; border-radius:3px; }
  .statsRecoRow:hover { background:rgba(201,165,90,.12); }
  .statSep {
    margin:8px 0 5px; padding-top:6px; border-top:1px solid #2c2a33;
    font-size:9px; letter-spacing:1.5px; text-transform:uppercase; color:var(--gold);
  }
  .row .v { color:var(--gold); } .row .v.blue { color:#9cc9e8; }
  .row .v.ok { color:#8fc98a; } .row .v.bad { color:var(--danger); }
  button {
    font-family:inherit; width:100%; background:linear-gradient(180deg,#26232b,#191720);
    color:var(--ink); border:1px solid var(--gold-dim); padding:6px 9px; font-size:11.5px;
    cursor:pointer; margin-top:4px; transition:border-color .12s, transform .12s;
  }
  button:hover:not(:disabled) { border-color:var(--gold); transform:translateY(-1px); }
  button:disabled { opacity:.38; cursor:default; }
  button .cost { color:var(--gold); }
  button:focus-visible { outline:2px solid var(--gold); outline-offset:2px; }
  #enhName { font-size:14px; margin-bottom:2px; } #enhName b { color:var(--gold); }
  #enhChance { font-size:11.5px; color:var(--ink-dim); margin-bottom:4px; }
  #enhResult { font-size:11.5px; min-height:15px; margin-top:4px; letter-spacing:1px; }
  #enhResult.ok { color:#8fc98a; } #enhResult.fail { color:var(--danger); }
  .shake { animation:shake .35s; }
  @keyframes shake { 25%{transform:translateX(-4px);} 50%{transform:translateX(4px);} 75%{transform:translateX(-2px);} }

  /* liste des zones */
  /* la grille #panel étire par défaut toutes les cartes d'une même rangée à la hauteur de la plus
     haute (CSS grid, align-items:stretch) — ça créait un grand vide sous une liste plus courte que
     sa voisine de rangée. Corrigé le 2026-07-06 (demande explicite : "pas que ça laisse des zones
     vides") avec align-self:start : ces 2 cartes ne s'étirent plus pour matcher leurs voisines,
     leur hauteur suit leur PROPRE contenu (plafonnée par max-height, avec défilement au-delà). */
  #zonesCard, #lootCard, #statsCard { display:flex; flex-direction:column; align-self:start; }
  /* corrigé le 2026-07-05 : avec 16 zones (contre 12 avant), la liste dépassait largement la
     hauteur des cartes voisines au lieu de s'arrêter et défiler -- plafond dur pour toujours
     garder un défilement interne au-delà d'une hauteur raisonnable */
  #zoneList { min-height:150px; max-height:60vh; overflow-y:auto; }
  #zoneList::-webkit-scrollbar { width:6px; }
  #zoneList::-webkit-scrollbar-thumb { background:#3a3742; }
  /* même traitement pour la carte Loot (2026-07-05, demande explicite : "refais la découpe de
     carte et rajoute le scroll") -- la table de loot peut aussi devenir longue (Trésor de Velia,
     vue condensée de toutes les zones à Velia...) sans plafond ni défilement jusqu'ici */
  #lootTable { min-height:150px; max-height:60vh; overflow-y:auto; padding-right:2px; }
  #lootTable::-webkit-scrollbar { width:6px; }
  #lootTable::-webkit-scrollbar-thumb { background:#3a3742; }
  .zRow {
    display:flex; align-items:center; gap:6px; padding:4px 5px;
    border-bottom:1px solid #232128; border-left:2px solid transparent; font-size:10.5px; cursor:pointer;
  }
  /* en-tête de groupe de zones par palier de stuff (couleur = couleur du stuff dans l'inventaire) */
  .zTierHead { display:flex; align-items:center; gap:5px; padding:6px 5px 2px; font-size:9.5px;
    letter-spacing:.5px; text-transform:uppercase; color:var(--ink-dim); }
  .zTierDot { width:7px; height:7px; border-radius:50%; flex-shrink:0; }
  .zRow:hover { background:#232028; }
  .zRow.current { background:#26232e; border-left:2px solid var(--gold); }
  .zRow .zname { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  /* largeur fixe = colonne PA/PD toujours alignée d'une ligne à l'autre, quelle que soit la longueur du nom de zone */
  .zRow .zreq { font-size:9.5px; color:var(--ink-dim); width:78px; flex-shrink:0; white-space:nowrap; }
  .zRow .zreq .ok { color:#8fc98a; } .zRow .zreq .bad { color:var(--danger); }
  .zBtnView {
    flex-shrink:0; width:auto; margin:0; padding:2px 7px; font-size:12px; line-height:1.4;
    background:transparent; border:1px solid var(--gold-dim);
  }
  .zBtnView.active { border-color:var(--gold); box-shadow:0 0 6px 2px rgba(201,165,90,.55); }
  /* Velia : ville paisible épinglée en haut de la liste des zones — pas de farm, juste le tutoriel */
  .zRow.veliaRow { background:rgba(140,201,138,.07); border-left:2px solid #8fc98a; }
  .zRow.veliaRow:hover { background:rgba(140,201,138,.14); }
  .zRow.veliaRow .zBadge { color:#8fc98a; border-color:#8fc98a; }
  .zBadge { font-size:9px; letter-spacing:.5px; padding:1px 6px; border:1px solid; white-space:nowrap; flex-shrink:0; }
  /* icône ⬆️ : cette zone offre un meilleur socle (vide ou palier supérieur) que le stuff actuel
     (2026-07-09, demande explicite) — même logique visibility que zPlayerCount juste en dessous,
     pour ne jamais faire bouger le reste de la ligne */
  .zUpgradeIcon { font-size:10px; flex-shrink:0; width:14px; text-align:center; }
  /* nombre de joueurs actuellement sur cette zone (2026-07-06, demande explicite) */
  /* largeur fixe + visibility (jamais display:none) : le bouton 👁 reste TOUJOURS aligné à la même
     position d'une ligne à l'autre, que la zone ait des joueurs ou non (demande explicite du
     2026-07-06 : "en aucun cas le compteur de joueurs dois faire bouger le texte") */
  .zPlayerCount { font-size:9px; color:var(--ink-dim); white-space:nowrap; flex-shrink:0; width:26px; text-align:right; }
  .b-red { color:var(--r-red); border-color:var(--r-red); }
  .b-orange { color:var(--r-orange); border-color:var(--r-orange); }
  .b-green { color:var(--r-green); border-color:var(--r-green); }
  .b-blue { color:var(--r-blue); border-color:var(--r-blue); }
  .b-grey { color:var(--r-grey); border-color:var(--r-grey); }

  @media (prefers-reduced-motion:reduce){ .shake{animation:none;} button{transition:none;} }
  @media (max-width:860px){ #panel{grid-template-columns:1fr 1fr;} }

  /* ===== paperdoll équipement (permanent) ===== */
  /* niveau/XP fusionnés sur la même ligne que PA/PD/GS (demande explicite du 2026-07-06) --
     flex-wrap en secours si la carte est trop étroite (mobile) pour les 5 sur une seule ligne */
  #equipSummary {
    display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:2px 8px;
    border:1px solid var(--gold-dim); border-radius:4px; padding:5px 10px; margin-bottom:6px;
    font-size:11px; color:var(--gold); font-weight:bold; background:rgba(201,165,90,.05);
  }
  #eqSumLvl { color:#fff; }
  #eqSumXp { color:var(--gold); }
  #eqSumGs { color:#9cc9e8; }
  #paperdoll { display:flex; align-items:center; justify-content:space-between; gap:2px; margin-bottom:6px; }
  .pdCol { display:flex; flex-direction:column; gap:5px; }
  /* pdRight est passé de 6 à 9 emplacements (2 artéfacts + 1 pierre, demande du 2026-07-07) —
     wrap en colonnes de 3 pour rester compact plutôt qu'une seule colonne trop haute */
  #pdRight { flex-direction:column; flex-wrap:wrap; max-height:153px; gap:5px; }
  .pdCenter { flex:1; display:flex; align-items:center; justify-content:center; min-width:0; }
  .pdCenter canvas { width:70px; height:auto; }
  .pdSlot {
    width:46px; height:46px; border:1px solid #3a3742; background:rgba(20,19,26,.9);
    display:flex; align-items:center; justify-content:center; font-size:20px;
    cursor:pointer; position:relative;
  }
  .pdSlot:hover { border-color:var(--gold); }
  .pdSlot.filled { border-color:var(--gold-dim); background:#231f16; }
  .pdSlot.empty { opacity:.42; filter:grayscale(1); }
  /* niveau d'optimisation affiché EN GROS sur l'image, façon BDO : pastille en haut à gauche */
  .pdSlot .enh {
    position:absolute; top:-4px; left:-4px; min-width:16px; text-align:center;
    font-size:11px; font-weight:bold; line-height:1.35; padding:0 3px; border-radius:3px;
    background:#1a2a14; color:#8fe07a; border:1px solid #4a7a38; box-shadow:0 1px 3px rgba(0,0,0,.6);
  }
  .pdSlot .enh.pri { background:#2a1a14; color:#e6cf7a; border-color:#8a6a3a; } /* PRI+ en doré */
  /* PA/PD grossis (2026-07-09, demande explicite "grossit le numero sur tout les stuff") et
     TOUJOURS en bas-gauche (même pour la PD des armures, demande explicite "sur l'armure met la
     dp en bas a gauche") -- AP et PD ne coexistent jamais sur le même objet (voir GEAR_ROLE), donc
     partager la position ne crée aucun chevauchement ; libère le bas-droite pour ✕ ci-dessous */
  .pdSlot .pdAp, .pdSlot .pdDp {
    position:absolute; bottom:-3px; left:-3px; font-size:11px; font-weight:bold; padding:0 3px; border-radius:2px;
    background:rgba(10,9,12,.9); text-shadow:none;
  }
  .pdSlot .pdAp { color:#e0a86e; }
  .pdSlot .pdDp { color:#8fc9c9; }
  /* croix de déséquipement en bas-droite (2026-07-09, demande explicite) */
  .pdSlot .pdUnequipBtn {
    position:absolute; bottom:-4px; right:-4px; width:15px; height:15px; line-height:14px;
    text-align:center; font-size:10px; font-weight:bold; border-radius:50%; background:#1a1822;
    border:1px solid #7a3a3a; color:#d98a8a; box-shadow:0 1px 3px rgba(0,0,0,.6); cursor:pointer;
  }
  .pdSlot .pdUnequipBtn:hover { background:#2a1616; border-color:var(--danger); color:#fff; transform:scale(1.15); }
  /* raccourci(s) directement sur la case, coin haut-droit, EMPILÉS verticalement (2026-07-05 :
     🔧 optimiser ; 2026-07-09, demande explicite "opti en haut à droite, upgrade sous l'icone
     d'opti" : ⬆️ zone pour améliorer une case remplie OU vide (même icône dans les 2 cas, demande
     explicite du 2026-07-09) / 🔒 slot sans source, chacun sous 🔧 s'il est présent) */
  .pdSlot .pdCorner { position:absolute; top:-4px; right:-4px; display:flex; flex-direction:column; align-items:flex-end; gap:2px; }
  .pdSlot .pdOptBtn, .pdSlot .pdUpgradeBtn, .pdSlot .pdFarmBtn, .pdSlot .pdLockBtn {
    width:15px; height:15px; line-height:14px;
    text-align:center; font-size:9px; border-radius:50%; background:#1a1822;
    border:1px solid var(--gold-dim); box-shadow:0 1px 3px rgba(0,0,0,.6); cursor:pointer;
  }
  .pdSlot .pdUpgradeBtn, .pdSlot .pdFarmBtn { border-color:#6ea3c9; }
  .pdSlot .pdLockBtn { cursor:default; border-color:#5a5666; opacity:.85; }
  .pdSlot .pdOptBtn:hover, .pdSlot .pdUpgradeBtn:hover, .pdSlot .pdFarmBtn:hover { background:#2a2416; border-color:var(--gold); transform:scale(1.15); }
  .gicon { width:1.55em; height:1.55em; vertical-align:middle; flex-shrink:0; }
  #pdWeapons { display:flex; justify-content:center; gap:6px; padding:6px 0; border-top:1px solid #2c2a33; border-bottom:1px solid #2c2a33; margin-bottom:2px; }
  #pdWeapons .pdSlot { width:48px; height:48px; }
  #pdWeapons .pdGroupLbl { position:absolute; top:-12px; left:0; right:0; text-align:center; font-size:7px; letter-spacing:.5px; color:var(--ink-dim); }
  #pdBook { display:flex; justify-content:center; padding:5px 0 7px; }
  .lsGrid { display:flex; flex-wrap:wrap; gap:8px; margin-bottom:10px; }
  .lsSlot {
    width:40px; height:40px; border:1px solid #3a3742; background:rgba(20,19,26,.9);
    display:flex; align-items:center; justify-content:center; font-size:18px;
  }
  .lsSlot.filled { border-color:var(--gold-dim); background:#231f16; }
  .lsSlot.empty { opacity:.42; filter:grayscale(1); }
  #pdBook .pdSlot { width:34px; height:34px; font-size:14px; }
  #btnEquipBest, #btnSellWorse { margin-top:8px; font-size:11px; }
  #equipBestMsg { font-size:10.5px; text-align:center; margin-top:4px; min-height:14px; color:var(--ink-dim); }
  #equipBestMsg.ok { color:#8fc98a; }
  /* mis en évidence quand un meilleur objet traîne dans le sac depuis plus de 15s sans être équipé
     (2026-07-09, demande explicite) — pulsation dorée, discrète mais visible */
  #btnEquipBest.hasUpgrade { border-color:var(--gold); box-shadow:0 0 6px 1px rgba(201,165,90,.6); animation:eqBestPulse 1.4s ease-in-out infinite; }
  @keyframes eqBestPulse {
    0%, 100% { box-shadow:0 0 6px 1px rgba(201,165,90,.6); }
    50% { box-shadow:0 0 12px 4px rgba(201,165,90,.95); }
  }

  .statBlock { padding-top:8px; border-top:1px solid #2c2a33; }
  .statBlock .srow { display:flex; justify-content:space-between; font-size:12px; margin:3px 0; }
  .statBlock .srow b { color:var(--gold); }
  .statBlock .big b { color:#9cc9e8; font-size:14px; }

  /* ===== inventaire (permanent) ===== */
  .invTools { display:flex; gap:5px; margin-bottom:7px; }
  .invTools > button { margin:0; font-size:10.5px; padding:5px 4px; flex:1; }
  /* Rangée "Équiper meilleur" / "Vendre" : 50/50 STRICT, les 2 boutons doivent faire exactement la
     même taille (demande explicite du 2026-07-08, après plusieurs itérations). "Racheter" (↩️) est
     une icône superposée en ABSOLU sur le coin droit de "Vendre" (ne mange plus sur sa largeur —
     sinon "Vendre" paraissait plus étroit qu'"Équiper meilleur" alors que le groupe fait bien 50%). */
  .invToolsMain > button, .invToolsMain > .sellWorseGroup { flex:0 0 50%; min-width:0; }
  /* corrigé le 2026-07-05 (demande explicite : "les deux boutons droits") : .sellWorseGroup avait
     un margin-top DIFFÉRENT (4px) de celui de #btnEquipBest (8px), et #btnSellWorse un font-size/
     padding différents de #btnEquipBest -- 2 causes cumulées d'un décalage vertical visible entre
     les 2 boutons de la rangée. Uniformisé pour un alignement pixel-perfect. */
  .sellWorseGroup { position:relative; display:block; margin-top:8px; }
  .sellWorseGroup #btnSellWorse { width:100%; margin:0; font-size:11px; padding:5px 4px; min-width:0;
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .sellWorseGroup #btnBuyBackWorse { position:absolute; top:0; right:0; bottom:0; width:15%;
    margin:0; padding:0; font-size:10px; border:1px solid var(--gold-dim); border-left:none;
    background:rgba(20,19,26,.9); display:flex; align-items:center; justify-content:center; }
  .sellWorseGroup #btnBuyBackWorse:hover:not(:disabled) { border-color:var(--gold); background:rgba(201,165,90,.12); }
  #invGrid, .admInvGrid {
    display:grid; grid-template-columns:repeat(8, 1fr); gap:3px;
    overflow-y:auto; max-height:188px; align-content:start; padding-right:2px;
  }
  .admInvGrid { max-height:none; }
  #invGrid::-webkit-scrollbar { width:7px; }
  #invGrid::-webkit-scrollbar-thumb { background:#3a3742; }
  /* panneau de craft du Trésor de Velia (onglet "Trésors" uniquement) — demande explicite du 2026-07-08 */
  .craftPanelTitle { font-size:10px; letter-spacing:1px; text-transform:uppercase; color:var(--ink-dim); margin-bottom:4px; }
  .craftRecipes { display:flex; flex-direction:column; gap:4px; margin-bottom:8px; }
  .craftRecipeBtn { width:100%; margin:0; padding:6px 8px; font-size:10.5px; text-align:left;
    border-color:#3a3742; color:var(--ink-dim); }
  .craftRecipeBtn.ready { border-color:var(--gold); color:var(--ink); }
  .craftRecipeBtn.ready:hover { background:rgba(201,165,90,.12); }
  /* Compendium (2026-07-08) : objets cliquables (halo sur les zones qui les lootent) */
  .compItem { cursor:pointer; }
  .compItem:hover { text-decoration:underline; color:var(--gold); }
  .compZoneRow.compHalo { border-left-color:var(--gold); background:rgba(201,165,90,.14);
    box-shadow:0 0 10px 1px rgba(201,165,90,.35); animation:patchHalo 1.6s infinite; }
  .compZonePicker { font-size:11px; color:var(--ink-dim); margin-bottom:8px; min-height:14px; }
  .compGoZoneBtn { width:auto; display:inline-block; margin:2px 4px 2px 0; padding:3px 9px; font-size:10.5px; }
  /* socle d'équipement vide : halo sur la/les zone(s) qui lootent l'objet manquant (2026-07-06) */
  .zRow.eqFarmHalo { border-left-color:var(--gold); background:rgba(201,165,90,.14);
    box-shadow:0 0 10px 1px rgba(201,165,90,.35); animation:patchHalo 1.6s infinite; }
  .eqFarmZoneBtn { width:auto; display:inline-block; margin:2px 4px 2px 0; padding:3px 9px; font-size:10.5px; }
  /* Compendium spécial "Maîtrise PEN" (2026-07-08) : grille compacte, pas de halo/clic ici (pur suivi) */
  .compPenGrid { display:grid; grid-template-columns:repeat(auto-fill, minmax(140px, 1fr)); gap:6px 10px; padding-top:6px; }
  .compPenItem { cursor:default; font-size:11px; }
  .compPenItem:hover { text-decoration:none; color:inherit; }
  .compPenItem.done { color:#8fc98a; }
  /* sac "Compendium" (2026-07-08) : grille identique au sac principal, avec un bouton "renvoyer" par case */
  .compBagGrid { max-height:260px; margin-top:8px; }
  .compBagCell { font-size:15px; }
  .compBagReturnBtn { position:absolute; bottom:1px; right:1px; width:auto; margin:0; padding:0 2px;
    font-size:9px; line-height:1.4; border:none; background:rgba(10,9,14,.85); }
  .compBagReturnBtn:hover { background:rgba(201,165,90,.3); }
  .cell {
    aspect-ratio:1; background:rgba(20,19,26,.6); border:1px solid #262430;
    position:relative; display:flex; align-items:center; justify-content:center;
    font-size:15px;
  }
  .cell.has { cursor:pointer; }
  .cell.has:hover { border-color:var(--gold); }
  .cell:not(.has) { cursor:pointer; }
  .cell:not(.has):hover { border-color:#3a3742; }
  .cell.k-trash.has { background:#20201c; }
  .cell.k-material.has { background:#1a2028; }
  .cell.k-jackpot.has { background:#252012; border-color:var(--gold-dim); }
  .cell.k-craft.has { background:#221c2a; border-color:#4a3a5a; }
  .cell.k-gear.has { background:#26200f; border-color:var(--gold-dim); }
  .cell.k-treasure.has { background:#221c14; border-color:#4a3a28; }
  /* réorganisé le 2026-07-09 (demande explicite) pour ne plus superposer qty et cellDp qui
     partageaient tous les deux bottom-right : coins logiques identiques à la poupée d'équipement
     (haut-gauche = équipé, haut-droit = quantité, bas-gauche = PA, bas-droit = PD) */
  .cell .qty {
    position:absolute; top:1px; right:2px; font-size:9px; color:var(--ink);
    text-shadow:0 0 3px #000,0 0 3px #000; font-family:Arial;
  }
  .cell .eqd { position:absolute; top:1px; left:2px; font-size:8px; color:#7aa35e; }
  .cell .cellAp { position:absolute; bottom:-1px; left:2px; font-size:8px; color:#e0a86e; text-shadow:0 0 3px #000,0 0 3px #000; }
  .cell .cellDp { position:absolute; bottom:-1px; right:2px; font-size:8px; color:#8fc9c9; text-shadow:0 0 3px #000,0 0 3px #000; }
  /* niveau d'enchantement visible sur le sac ET le sac protégé du Compendium (2026-07-09, demande
     explicite) — même coin (haut-droit) que .qty, jamais en conflit : le gear/bijou enchanté n'est
     jamais stackable (qty toujours 1, jamais affiché), et un stack (trash/matériau) n'a jamais
     enhLv. Même palette que le badge équivalent de la poupée d'équipement (.pdSlot .enh). */
  .cell .cellEnh {
    position:absolute; top:1px; right:2px; font-size:8px; font-weight:bold; padding:0 2px; border-radius:2px;
    background:#1a2a14; color:#8fe07a; text-shadow:none;
  }
  .cell .cellEnh.pri { background:#2a1a14; color:#e6cf7a; }
  .invFoot { margin-top:8px; padding-top:7px; border-top:1px solid #2c2a33; font-size:12px; }
  .invFoot .frow { display:flex; align-items:center; gap:8px; margin:4px 0; }
  .invFoot .bar { flex:1; height:8px; background:#0d0c11; border:1px solid #333; overflow:hidden; }
  .invFoot .bar.wbar > div { height:100%; background:linear-gradient(90deg,#5a6b8a,#8fb0c9); }
  .invFoot .bar.wbar > div.over { background:linear-gradient(90deg,#8a3a30,var(--danger)); }
  #wTxt.bad { color:var(--danger); font-weight:bold; }
  .invFoot .money { display:flex; align-items:center; gap:6px; color:var(--gold); margin-top:6px; }

  /* tooltip / actions contextuelles */
  #itemPop {
    position:fixed; z-index:60; display:none; min-width:180px; max-width:230px;
    background:#14131a; border:1px solid var(--gold-dim); padding:10px; font-size:12px;
    box-shadow:0 8px 24px rgba(0,0,0,.7);
  }
  #itemPop .ipName { font-size:13px; margin-bottom:4px; }
  #itemPop .ipName.jackpot, #itemPop .ipName.gear { color:var(--gold); } #itemPop .ipName.craft { color:#b48ce8; }
  #itemPop .ipDesc { color:var(--ink-dim); margin-bottom:8px; line-height:1.4; }
  #itemPop .ipDelta { font-size:11px; margin:-4px 0 8px; line-height:1.5; }
  #itemPop .statGain { color:#8fc98a; margin-right:6px; }
  #itemPop .statLoss { color:var(--danger); margin-right:6px; }
  #itemPop button { margin:4px 0 0; font-size:11px; padding:5px; }
  #itemPop button .psIcon { margin-right:2px; }

  #itemTooltip {
    position:fixed; z-index:65; display:none; min-width:140px; max-width:210px;
    background:#14131a; border:1px solid #3a3742; padding:7px 9px; font-size:11px;
    box-shadow:0 6px 18px rgba(0,0,0,.6); pointer-events:none;
  }
  #itemTooltip .ipName { font-size:12px; margin-bottom:3px; }
  #itemTooltip .ipName.jackpot, #itemTooltip .ipName.gear { color:var(--gold); }
  #itemTooltip .ipName.craft { color:#b48ce8; }
  #itemTooltip .ipDesc { color:var(--ink-dim); line-height:1.35; }

  /* ===== loot de la zone ===== */
  .lootRow { display:flex; align-items:center; gap:8px; padding:5px 0; border-bottom:1px solid #232128; font-size:12px; }
  .lootRow:last-child { border-bottom:none; }
  .lootIcon { width:26px; height:26px; display:flex; align-items:center; justify-content:center;
    background:rgba(20,19,26,.8); border:1px solid #2c2a33; font-size:13px; flex-shrink:0; cursor:help; }
  /* aperçu agrandi au survol d'une icône de loot (2026-07-08, demande explicite : "qu'on puisse
     agrandir l'icone pour mieux la voir en tooltip en auto en passant dessus") -- position:fixed
     pour échapper au overflow-y:auto de #lootTable, rempli/positionné en JS (voir lootIconZoomInit) */
  #lootIconZoom { position:fixed; width:96px; height:96px; padding:6px; background:var(--panel-2);
    border:1px solid var(--gold-dim); border-radius:6px; box-shadow:0 6px 20px rgba(0,0,0,.6);
    display:none; align-items:center; justify-content:center; z-index:9999; pointer-events:none; }
  #lootIconZoom.show { display:flex; }
  #lootIconZoom svg { width:100%; height:100%; }
  .lootIcon.k-trash { color:#a08464; } .lootIcon.k-material { color:#8fb0c9; }
  .lootIcon.k-jackpot { color:#e8b84a; border-color:var(--gold-dim); } .lootIcon.k-craft { color:#b48ce8; }
  .lootIcon.k-gear { color:#c9a55a; border-color:var(--gold-dim); }
  .lootIcon.k-treasure { color:#e8c96a; }
  /* en-tête de catégorie EXPÉRIMENTALE dans la table de loot (ex: "Trésor de Velia") */
  .lootCatHead { font-size:9.5px; letter-spacing:.6px; text-transform:uppercase; color:#e8975a;
    border:1px dashed #4a3a28; padding:3px 6px; margin:8px 0 4px; text-align:center; }
  .lootInfo { flex:1; min-width:0; }
  .lootInfo .ln { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .lootInfo .lv { color:var(--ink-dim); font-size:10.5px; }
  /* récapitulatif condensé de Velia (2026-07-08) : 1 ligne/zone repliée, dépliable au clic */
  .lootZoneCompact { cursor:pointer; }
  .lootZoneCompact:hover { background:rgba(255,255,255,.03); }
  .lootExpandHint { color:var(--ink-dim); margin-left:2px; display:inline-block; transition:transform .15s; }
  .lootZoneCompact.expanded .lootExpandHint { transform:rotate(180deg); }
  .lootZoneDetail { padding:0 0 6px 8px; border-bottom:1px solid #232128; }
  .lootZoneDetail .lootRow:last-child { border-bottom:none; }
  .lootPct { color:var(--gold); font-size:12px; text-align:right; min-width:48px; }

  /* ===== optimisation (enchantement) ===== */
  #optCard .optRow { display:flex; align-items:center; gap:10px; margin-bottom:8px; }
  #optItem, #optMat {
    width:44px; height:44px; background:rgba(20,19,26,.85); border:1px solid var(--gold-dim);
    display:flex; align-items:center; justify-content:center; font-size:18px; flex-shrink:0; position:relative;
  }
  #optArrow { color:var(--ink-dim); font-size:16px; }
  #optMat.empty { opacity:.35; border-style:dashed; }
  #optMat .matQty { position:absolute; bottom:-1px; right:1px; font-size:9px; color:var(--ink); text-shadow:0 0 2px #000; }
  /* Pierre de Cron : case dédiée à droite du matériau, plus consommée en silence (2026-07-06,
     demande explicite : "s'utilise sur choix du joueur avec nouvelle case... et une case utiliser
     cron ou non") */
  #optCronSlot {
    width:44px; height:44px; background:rgba(20,19,26,.85); border:1px solid #4ecdc4;
    display:flex; align-items:center; justify-content:center; font-size:18px; flex-shrink:0; position:relative;
    margin-left:auto; cursor:pointer;
  }
  #optCronSlot.empty { opacity:.35; border-style:dashed; cursor:default; }
  /* la case sert elle-meme de bouton on/off (2026-07-08) : grisee/desaturee quand desactivee,
     meme quand une pierre est en sac -- remplace l'ancienne case a cocher separee */
  #optCronSlot.off { filter:grayscale(1); opacity:.45; border-color:#666; }
  #optCronQty { position:absolute; bottom:-1px; right:1px; font-size:9px; color:var(--ink); text-shadow:0 0 2px #000; }
  #optLevelLbl { font-size:13px; } #optLevelLbl b { color:var(--gold); }
  #optChanceWrap { margin:8px 0; }
  #optChanceBar { height:7px; background:#0d0c11; border:1px solid #333; overflow:hidden; display:flex; }
  #optChanceFill { height:100%; background:linear-gradient(90deg,#8a7038,#c9a55a); }
  #optChanceFillFS { height:100%; background:linear-gradient(90deg,#3d6b8a,#8fc9e8); }
  #optChanceTxt { font-size:11.5px; color:var(--ink-dim); margin-top:3px; }
  #optResult { font-size:11.5px; min-height:15px; margin-top:5px; letter-spacing:.5px; }
  #optResult.ok { color:#8fc98a; } #optResult.fail { color:var(--danger); }
  .optShake { animation:shake .35s; }
  #optAutoModeRow { margin-top:6px; }
  #optAutoModeRow select { width:100%; background:#191720; color:var(--ink); border:1px solid var(--gold-dim); padding:5px; font-family:inherit; font-size:11px; }
  #optAutoRow { display:flex; gap:6px; margin-top:6px; }
  #optAutoRow select { flex:1; background:#191720; color:var(--ink); border:1px solid var(--gold-dim); padding:5px; font-family:inherit; font-size:11px; }
  #optAutoRow button { width:auto; margin:0; font-size:11px; padding:5px 10px; white-space:nowrap; }
  #optAutoGainTxt { font-size:10.5px; color:var(--gold-dim); margin-top:3px; letter-spacing:.3px; min-height:13px; }
  #btnOptAuto.running { border-color:var(--danger); color:#e8a89f; }
  #capConvertRow { display:flex; align-items:center; justify-content:space-between; gap:8px; margin-top:8px; padding-top:8px; border-top:1px solid #2c2a33; }
  #capConvertLbl { font-size:10.5px; color:var(--ink-dim); }
  #capConvertRow button { width:auto; margin:0; font-size:10.5px; padding:5px 9px; white-space:nowrap; }
  #optTarget {
    width:100%; background:#191720; color:var(--ink); border:1px solid var(--gold-dim);
    font-family:inherit; font-size:11px; padding:5px 6px;
  }
  #optSuggest { margin-top:8px; padding-top:7px; border-top:1px solid #2c2a33; font-size:10.5px; color:var(--ink-dim); line-height:1.5; }
  #optFailstack { font-size:11px; color:var(--ink-dim); margin-top:6px; }
  #naderrLbl { font-size:9.5px; letter-spacing:1.5px; text-transform:uppercase; color:var(--ink-dim); margin-top:9px; }
  #naderrBand { display:flex; gap:3px; margin-top:4px; }
  .ndSlot {
    width:19px; height:19px; display:flex; align-items:center; justify-content:center;
    font-size:9.5px; background:rgba(20,19,26,.85); border:1px solid #3a3742; color:var(--ink-dim);
  }
  .ndSlot.on { border-color:var(--gold); color:var(--gold); background:#231f16; }
  .ndSlot.locked { opacity:.4; font-size:8px; border-style:dashed; }

  /* ===== authentification ===== */
  #authOverlay {
    position:fixed; inset:0; background:radial-gradient(ellipse at center, #1a1822, #08070a);
    display:flex; align-items:center; justify-content:center; z-index:100;
  }
  #authOverlay.hidden { display:none; }
  #authBox {
    position:relative; width:320px; max-width:92vw; background:var(--panel); border:1px solid var(--gold-dim);
    padding:28px 26px; text-align:center; box-shadow:0 20px 60px rgba(0,0,0,.7);
  }
  #closeAuth {
    position:absolute; top:8px; right:8px; width:auto; margin:0; padding:4px 9px;
    background:none; border:none; font-size:16px; color:var(--ink-dim);
  }
  #authBox h1 { font-size:20px; letter-spacing:2px; color:var(--gold); margin-bottom:4px; }
  /* badge "compatible mobile/tablette" sur l'écran de connexion/création de compte (2026-07-05,
     demande explicite) — annonce la nouvelle adaptation mobile (V152-V157) dès l'arrivée sur le
     jeu, avant même de se connecter, avec le même style pulsant que le tag "NEW" des notes de
     version pour attirer l'œil sans être une simple étiquette statique */
  #authMobileBadge {
    display:inline-block; background:rgba(201,165,90,.12); color:var(--gold); border:1px solid var(--gold-dim);
    font-size:10px; font-weight:bold; letter-spacing:.5px; padding:3px 10px; border-radius:10px;
    margin-bottom:10px; animation:patchNewFade 1.6s infinite;
  }
  .authSub { font-size:11.5px; color:var(--ink-dim); margin-bottom:8px; }
  #demoBadge {
    display:inline-block; background:var(--danger); color:#fff; font-size:10px; font-weight:bold;
    letter-spacing:2px; padding:3px 10px; margin-bottom:10px; border-radius:2px;
  }
  .demoNote {
    font-size:10.5px; color:#e8b84a; background:rgba(201,165,90,.1); border:1px solid var(--gold-dim);
    padding:7px 9px; margin-bottom:16px; line-height:1.4; text-align:left;
  }
  #authBox input {
    width:100%; background:#191720; border:1px solid #3a3742; color:var(--ink);
    font-family:inherit; font-size:13px; padding:9px 10px; margin-bottom:9px;
  }
  #authBox input:focus { outline:none; border-color:var(--gold); }
  #authBox button { margin-top:4px; }
  #authBox button.ghost { background:transparent; border:1px solid #3a3742; }
  #btnForgotPass { font-size:11px; padding:6px 10px; color:var(--ink-dim); }
  #authError { color:var(--danger); font-size:11.5px; min-height:14px; margin:6px 0; }
  #authStatus { color:var(--ink-dim); font-size:11px; margin-top:10px; }
  #authLangRow { display:flex; justify-content:center; gap:6px; margin-bottom:12px; }
  .authLangBtn {
    width:auto; margin:0; padding:4px 10px; font-size:11px; background:transparent;
    border:1px solid #3a3742; color:var(--ink-dim);
  }
  .authLangBtn.active { border-color:var(--gold); color:var(--gold); }

  /* ===== menu latéral (fusion topBar + userBar en une colonne) ===== */
  #sideMenu {
    position:fixed; top:14px; left:14px; z-index:40;
    display:flex; flex-direction:column; gap:10px; width:210px;
  }
  #gameBar, #userBar, #metaBar {
    display:flex; flex-direction:column; gap:7px;
    background:rgba(10,9,12,.88); border:1px solid #2c2a33; padding:10px;
  }
  #userBar { display:none; }
  #userBar.show { display:flex; }
  #gameBar button, #userBar button, #metaBar button {
    width:100%; margin:0; padding:11px 14px; font-size:13.5px; text-align:left;
  }
  #userBarTop { display:flex; align-items:center; gap:8px; font-size:12px; color:var(--ink-dim); padding:0 2px; }
  #userEmail { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  /* dernier élément du flux : son texte variable (vide / "✓ sauvegardé" / ...) ne fait
     donc jamais bouger les boutons au-dessus, seule la hauteur du panneau varie légèrement */
  #saveStatus { font-size:10.5px; color:#7aa35e; padding:0 2px; min-height:12px; }
  #demoTag {
    background:var(--danger); color:#fff; font-size:9px; font-weight:bold;
    letter-spacing:1px; padding:2px 6px; border-radius:2px; flex-shrink:0;
  }
  #userPseudo { color:var(--gold); font-weight:bold; font-size:11.5px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  #uuidRow { display:flex; align-items:center; gap:5px; font-size:9.5px; color:var(--ink-dim); margin-top:2px; }
  /* toute la case UUID est un bouton "copier" cliquable — l'UUID lui-même n'est plus affiché,
     seul le clic copie sa valeur réelle dans le presse-papiers (voir btnCopyUuid.onclick) */
  #btnCopyUuid {
    display:flex; align-items:center; justify-content:center; gap:6px; flex:1; min-width:0; width:auto; margin:0;
    padding:5px 7px; font-size:10.5px; text-align:center; cursor:pointer;
  }
  #uuidCopyHint { flex-shrink:0; color:var(--gold); font-weight:bold; white-space:nowrap; }
  #btnResetDemo, #btnResetAllQuests { border-color:var(--danger) !important; color:#e8a89f; }
  #btnResetDemo:hover, #btnResetAllQuests:hover { background:rgba(192,85,69,.15); }

  /* juste le bouton qui ouvre le panneau Admin — les actions vivent maintenant dedans (voir .admActions) */
  #adminBox { margin-top:2px; }
  /* rafraîchi le 2026-07-07 : cartes avec ombre légère + léger survol, pour bien séparer visuellement
     chaque bloc d'action dans un panneau qui contient désormais beaucoup de sections */
  .admSection { margin-bottom:16px; padding:11px 12px 11px 13px; border:1px solid #2c2a33; border-left-width:3px;
    border-radius:6px; background:rgba(255,255,255,.025); box-shadow:0 2px 6px rgba(0,0,0,.22); transition:background .15s; }
  .admSection:hover { background:rgba(255,255,255,.04); }
  /* code couleur par niveau de risque, pour repérer d'un coup d'oeil ce qui est réversible/perso
     vs ce qui touche TOUS les joueurs — demande explicite du 2026-07-06 (panneau "plus compréhensible") */
  .admSection.riskSafe { border-left-color:#5a8fc8; }
  .admSection.riskGlobal { border-left-color:var(--danger); }
  .admSection.riskMgmt { border-left-color:#7aa35e; }
  .admRiskLegend { display:flex; flex-wrap:wrap; gap:14px; font-size:10.5px; color:var(--ink-dim); margin-bottom:12px; padding-bottom:10px; border-bottom:1px solid #2c2a33; }
  .admRiskLegend span { display:flex; align-items:center; gap:5px; }
  .admRiskLegend i { display:inline-block; width:8px; height:8px; border-radius:50%; }
  .admSectionTitle { font-size:12px; font-weight:bold; letter-spacing:.5px; color:var(--gold); margin-bottom:3px; }
  .admSectionSub { font-size:10.5px; color:var(--ink-dim); margin-bottom:9px; line-height:1.4; }
  .admSection .admActions { border-bottom:none; padding-bottom:0; margin-bottom:8px; }
  .admSection .admBossSpawn { border-bottom:none; padding-bottom:0; margin-bottom:0; }
  .admHint { font-size:10px; color:var(--ink-dim); font-style:italic; }
  .admHint.warn { color:var(--danger); }
  .modRow { display:flex; align-items:center; gap:8px; padding:4px 2px; border-bottom:1px solid #232128; font-size:11px; }
  .modPseudo { color:var(--gold); font-weight:bold; flex-shrink:0; }
  .modUuid { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-family:monospace; font-size:9.5px; color:var(--ink-dim); }
  .modRemBtn { width:auto; margin:0; padding:2px 8px; font-size:10px; flex-shrink:0; border-color:var(--danger); color:#e8a89f; }
  .roleBadges { flex-shrink:0; font-size:10.5px; white-space:nowrap; }
  .admActions { display:flex; flex-wrap:wrap; gap:6px; margin-bottom:12px; padding-bottom:12px; border-bottom:1px solid #2c2a33; }
  .admActions button { width:auto; flex:1; min-width:140px; margin:0; }
  .admActions input[type=text] {
    flex:1; min-width:140px; background:#191720; color:var(--ink); border:1px solid var(--gold-dim);
    font-family:inherit; font-size:12px; padding:0 9px; margin:0;
  }
  .admSection.riskSingle { border-left-color:#c9955a; }
  .admBossSpawn { display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin-bottom:12px; padding-bottom:12px; border-bottom:1px solid #2c2a33; font-size:12px; }
  .admBossSpawn select { background:#0d0c11; border:1px solid #333; color:var(--ink); padding:5px 7px; font-family:inherit; font-size:12px; border-radius:3px; }
  .admBossSpawn button { width:auto; margin:0; padding:6px 14px; }

  #sideMenu.onRight { left:auto; right:14px; }
  #btnCollapseMenu {
    width:auto; align-self:flex-start; margin:0; padding:6px 10px; font-size:13px;
    background:rgba(10,9,12,.88); border:1px solid #2c2a33; color:var(--ink-dim);
  }
  #btnCollapseMenu:hover { border-color:var(--gold); color:var(--gold); }
  /* corrigé le 2026-07-05 (adaptation mobile) : #clientVersion (numéro de version, tout en bas du
     menu) n'était PAS masqué par le repli — seuls #topBar/#userBar l'étaient — donc replier le menu
     laissait ce texte flotter tout seul, hors de tout cadre, chevauchant le contenu du dessous */
  #sideMenu.collapsed #gameBar, #sideMenu.collapsed #userBar, #sideMenu.collapsed #metaBar, #sideMenu.collapsed #clientVersion { display:none; }
  /* replié : la largeur fixe de 210px ne se réduisait jamais (seuls les ENFANTS étaient masqués),
     donc le menu "replié" gardait la même emprise qu'ouvert — sans conséquence sur grand écran
     (assez de place), mais ça faisait chevaucher les encarts de droite sur mobile/tablette une fois
     réduit (2026-07-05, adaptation mobile) */
  #sideMenu.collapsed { width:auto; }
  /* déplié sur un petit écran, le menu (tous ses boutons + compte + version) peut être plus haut
     que la fenêtre elle-même — jusqu'ici impossible d'atteindre les derniers boutons (Discord,
     Admin...) : on scrolle DANS le menu plutôt que de le laisser déborder hors de l'écran */
  #sideMenu:not(.collapsed) { max-height:calc(100vh - 28px); overflow-y:auto; }

  #btnDiscord {
    display:block; width:100%; box-sizing:border-box; padding:11px 14px; font-size:13.5px;
    background:rgba(88,101,242,.18); border:1px solid #5865F2; color:#c9cdff;
    text-decoration:none; text-align:left; font-family:inherit;
  }
  #btnDiscord:hover { background:rgba(88,101,242,.32); }
  .discordBtn {
    background:rgba(88,101,242,.18) !important; border:1px solid #5865F2 !important; color:#c9cdff !important;
  }
  .discordBtn:hover { background:rgba(88,101,242,.32) !important; }

  /* slider position du menu (gauche/droite) */
  #menuSideToggle {
    position:relative; display:flex; width:100%; height:34px;
    background:rgba(10,9,12,.6); border:1px solid #2c2a33; cursor:pointer; user-select:none;
  }
  #menuSideToggle:hover { border-color:var(--gold); }
  .menuSideOpt {
    flex:1; display:flex; align-items:center; justify-content:center;
    font-size:10px; font-weight:bold; letter-spacing:.3px; color:var(--ink-dim); z-index:2;
    transition:color .2s ease;
  }
  .menuSideOpt.active { color:#1a1712; }
  #menuSideThumb {
    position:absolute; top:2px; left:2px; width:calc(50% - 2px); height:calc(100% - 4px);
    background:var(--gold); transition:left .2s ease;
  }
  #menuSideThumb.right { left:calc(50% + 0px); }

  #clientVersion {
    font-size:10px; color:var(--ink-dim); text-align:center; padding:6px 0 0;
    letter-spacing:.3px;
  }
  #clientVersionNum { color:var(--gold); font-weight:bold; }

  /* ===== footer légal ===== */
  #siteFooter {
    position:fixed; bottom:0; left:0; right:0; z-index:35;
    background:rgba(6,5,9,.92); border-top:1px solid #2c2a33;
    padding:6px 14px; text-align:center; font-size:9.5px; color:var(--ink-dim);
    line-height:1.4;
  }
  #devBanner {
    background-image:repeating-linear-gradient(45deg,#3a2f0f,#3a2f0f 10px,#241c0a 10px,#241c0a 20px);
    color:var(--gold); font-weight:bold; font-size:10.5px; letter-spacing:.5px;
    padding:4px 14px; text-align:center; border-bottom:1px solid var(--gold-dim);
    margin:-6px -14px 6px; /* annule le padding de #siteFooter pour border-to-border */
  }

  /* ===== hôtel des ventes ===== */
  #marketOverlay {
    position:fixed; inset:0; background:rgba(6,5,9,.8); z-index:90;
    display:none; align-items:center; justify-content:center;
  }
  #marketOverlay.open { display:flex; }
  #marketBox {
    width:640px; max-width:94vw; max-height:80vh; display:flex; flex-direction:column;
    background:var(--panel); border:1px solid var(--gold-dim); box-shadow:0 20px 60px rgba(0,0,0,.7);
  }
  #marketHead {
    display:flex; align-items:center; gap:14px; padding:12px 16px;
    background:linear-gradient(180deg,#26313a,#1b232a); border-bottom:1px solid var(--gold-dim);
  }
  #marketHead h2 { font-size:15px; letter-spacing:1px; margin:0; }
  /* rappel clair "en construction" dans le panneau lui-même (2026-07-06, demande explicite :
     "faut que les gens comprennent que c'est peu fonctionnel et en construction") */
  #marketConstructionBanner, .constructionBanner {
    background-image:repeating-linear-gradient(45deg,#3a2f0f,#3a2f0f 10px,#241c0a 10px,#241c0a 20px);
    color:var(--gold); font-weight:bold; font-size:10.5px; letter-spacing:.3px;
    padding:5px 16px; text-align:center; border-bottom:1px solid var(--gold-dim);
  }
  /* variante autonome (pas dans un bandeau de panneau) : coins arrondis + marge, utilisée dans les
     cartes (ex: onglet Recommandations de Statistiques, 2026-07-09, demande explicite) */
  .constructionBanner { border:1px solid var(--gold-dim); border-radius:4px; margin-bottom:8px; }
  #marketTabs { display:flex; gap:6px; flex:1; }
  .mtab {
    width:auto; margin:0; padding:6px 12px; font-size:11.5px;
    background:transparent; border:1px solid #3a3742;
  }
  .mtab.active { border-color:var(--gold); color:var(--gold); }
  #closeMarket { width:auto; margin:0; padding:4px 9px; background:none; border:none; font-size:16px; color:var(--ink-dim); }

  .marketPane { padding:14px 16px; overflow-y:auto; flex:1; }
  #marketList, #marketMineList { display:flex; flex-direction:column; gap:6px; }
  .mRow {
    display:flex; align-items:center; gap:10px; padding:8px 10px;
    background:var(--panel-2); border:1px solid #2c2a31; font-size:12.5px;
  }
  .mIcon { width:30px; height:30px; display:flex; align-items:center; justify-content:center;
    background:rgba(0,0,0,.3); border:1px solid #2c2a31; font-size:15px; flex-shrink:0; }
  .mInfo { flex:1; min-width:0; }
  .mInfo .mName { }
  .mInfo .mSub { color:var(--ink-dim); font-size:10.5px; }
  .mPrice { color:var(--gold); font-size:13px; white-space:nowrap; }
  .mRow button { width:auto; margin:0; padding:6px 12px; font-size:11.5px; }
  .mEmpty { color:var(--ink-dim); font-size:12px; text-align:center; padding:30px 0; }

  /* ===== marché commun (matériaux, prix flottant) ===== */
  #marketCommonList { display:flex; flex-direction:column; gap:6px; }
  .cmRow { display:flex; align-items:center; gap:10px; padding:8px 10px;
    background:var(--panel-2); border:1px solid #2c2a31; font-size:12.5px; }
  .cmInfo { flex:1; min-width:0; }
  .cmInfo .cmOwned { color:var(--ink-dim); font-size:10.5px; }
  .cmPrice { font-size:13px; white-space:nowrap; text-align:right; width:80px; }
  .cmPrice.low { color:#8fc98a; } .cmPrice.mid { color:var(--gold); } .cmPrice.high { color:var(--danger); }
  /* carnet d'ordres v2 (2026-07-07) : résumé meilleur achat/vente à côté de chaque objet */
  .cmBook { font-size:10.5px; text-align:right; white-space:nowrap; flex-shrink:0; line-height:1.5; }
  .cmBid { color:#8fc98a; } .cmAsk { color:#e8a89f; }
  .cmActions { display:flex; align-items:center; gap:4px; flex-shrink:0; }
  .cmQty { width:44px; background:#191720; color:var(--ink); border:1px solid #3a3742;
    font-family:inherit; font-size:11.5px; padding:5px 4px; text-align:center; }
  .cmPriceInput { width:64px; background:#191720; color:var(--ink); border:1px solid #3a3742;
    font-family:inherit; font-size:11.5px; padding:5px 4px; text-align:center; }
  .cmActions button { width:auto; margin:0; padding:6px 10px; font-size:11px; }
  #cmMyOrders { display:flex; flex-direction:column; gap:6px; margin-top:6px; }
  #cmSellItemSelect { width:100%; background:#191720; color:var(--ink); border:1px solid var(--gold-dim);
    font-family:inherit; font-size:12px; padding:8px 9px; margin-bottom:8px; }
  #cmSellPriceInput { width:100%; background:#191720; color:var(--ink); border:1px solid #3a3742;
    font-family:inherit; font-size:12px; padding:8px 9px; margin-bottom:8px; }

  /* ===== marché commun v2 : vitrine "parcourir" (inspirée d'une référence visuelle fournie par
     l'utilisateur le 2026-07-07) — cartes d'objets en vente + panneau de détail avec comparaison ===== */
  .cmSubTabs { display:flex; gap:6px; margin-bottom:10px; border-bottom:1px solid #2c2a33; padding-bottom:8px; }
  .cmSubTab { width:auto; margin:0; padding:6px 12px; font-size:11.5px; background:transparent; border:1px solid #3a3742; }
  .cmSubTab.active { border-color:var(--gold); color:var(--gold); background:rgba(201,165,90,.08); }
  /* solde bien visible en haut de la vitrine (façon référence BDO), et arbre de catégories façon
     Marché Central au lieu de simples pastilles — demande explicite du 2026-07-07 */
  .cmWalletBar { display:flex; align-items:center; justify-content:space-between; gap:8px;
    background:rgba(201,165,90,.06); border:1px solid var(--gold-dim); border-radius:4px;
    padding:8px 12px; margin-bottom:10px; }
  .cmWalletLbl { font-size:11px; color:var(--ink-dim); }
  .cmWalletVal { font-size:15px; color:var(--gold); font-weight:bold; }
  .cmFilterBar { display:flex; flex-wrap:wrap; gap:8px; align-items:center; margin-bottom:10px; }
  #cmSearch { flex:1; min-width:120px; background:#191720; color:var(--ink); border:1px solid #3a3742;
    font-family:inherit; font-size:11.5px; padding:6px 9px; }
  #cmSort { background:#191720; color:var(--ink); border:1px solid #3a3742; font-family:inherit; font-size:11.5px; padding:6px 8px; }
  .cmBrowseLayout { display:flex; gap:10px; align-items:flex-start; }
  .cmCategoryTree { flex:0 0 130px; display:flex; flex-direction:column; gap:2px; max-height:420px; overflow-y:auto; }
  .cmCatBtn { width:100%; text-align:left; margin:0; padding:7px 9px; font-size:11px; background:transparent;
    border:1px solid transparent; border-left:3px solid transparent; color:var(--ink-dim); border-radius:0; }
  .cmCatBtn:hover { background:rgba(255,255,255,.03); color:var(--ink); }
  .cmCatBtn.active { border-left-color:var(--gold); color:var(--gold); background:rgba(201,165,90,.08); }
  .cmBackBtn { width:auto; margin-bottom:8px; padding:5px 12px; font-size:11px; }
  .cmListingsList { flex:1.4; min-width:0; display:flex; flex-direction:column; gap:6px; max-height:420px; overflow-y:auto; }
  .cmDetailPanel { flex:1; min-width:0; position:sticky; top:0; background:var(--panel-2);
    border:1px solid #2c2a31; padding:12px; max-height:420px; overflow-y:auto; }
  .cmListCard { display:flex; align-items:center; gap:9px; padding:8px 10px; background:var(--panel-2);
    border:1px solid #2c2a31; border-left-width:3px; cursor:pointer; font-size:12px; }
  .cmListCard:hover { background:#232028; }
  .cmListCard.selected { border-color:var(--gold); background:rgba(201,165,90,.06); }
  .cmListIcon { width:32px; height:32px; display:flex; align-items:center; justify-content:center;
    background:rgba(0,0,0,.3); border:1px solid #2c2a31; flex-shrink:0; }
  .cmListInfo { flex:1; min-width:0; }
  .cmListName { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .cmListSub { color:var(--ink-dim); font-size:10px; }
  .cmListPrice { text-align:right; flex-shrink:0; }
  .cmListPrice .price { color:var(--gold); font-size:12.5px; white-space:nowrap; }
  .cmListPrice button { width:auto; margin:3px 0 0; padding:3px 10px; font-size:10.5px; }
  .cmDetailTitle { font-size:13px; margin-bottom:2px; }
  .cmDetailSub { color:var(--ink-dim); font-size:10.5px; margin-bottom:10px; }
  .cmDetailIcon { width:64px; height:64px; margin:0 auto 10px; display:flex; align-items:center; justify-content:center;
    background:rgba(0,0,0,.3); border:2px solid #2c2a31; border-radius:6px; }
  .cmDetailIcon svg { width:40px; height:40px; }
  .cmDetailStats { margin-bottom:10px; }
  .cmDetailStats .srow { display:flex; justify-content:space-between; font-size:11.5px; margin:3px 0; }
  .cmCompareTable { width:100%; border-collapse:collapse; font-size:10.5px; margin-top:6px; }
  .cmCompareTable th { text-align:left; color:var(--ink-dim); font-weight:normal; padding:3px 4px; border-bottom:1px solid #2c2a31; }
  .cmCompareTable td { padding:3px 4px; border-bottom:1px solid #232128; }
  .cmDelta.up { color:#8fc98a; } .cmDelta.down { color:var(--danger); }
  #cmDetailPanel .btnBuyListing { width:100%; margin-top:8px; padding:9px; font-size:12px; }

  .mHint { color:var(--ink-dim); font-size:11.5px; margin-bottom:10px; }
  #sellItemSelect {
    width:100%; background:#191720; color:var(--ink); border:1px solid var(--gold-dim);
    font-family:inherit; font-size:12px; padding:8px 9px; margin-bottom:8px;
  }
  #sellPriceInput {
    width:100%; background:#191720; color:var(--ink); border:1px solid var(--gold-dim);
    font-family:inherit; font-size:12px; padding:8px 9px; margin-bottom:8px;
  }
  #sellMsg { font-size:11.5px; margin-top:8px; min-height:14px; }
  #sellMsg.ok { color:#8fc98a; } #sellMsg.fail { color:var(--danger); }

  /* ===== panneau Mon compte / parrainage ===== */
  #refCodeBox {
    background:#191720; border:1px dashed var(--gold-dim); color:var(--gold);
    font-size:16px; font-weight:bold; letter-spacing:3px; text-align:center;
    padding:10px; margin-bottom:8px;
  }
  #refCodeInput {
    width:100%; background:#191720; color:var(--ink); border:1px solid var(--gold-dim);
    font-family:inherit; font-size:12px; padding:8px 9px; margin:8px 0; text-transform:uppercase;
  }
  #refMsg { font-size:11.5px; margin-top:8px; min-height:14px; }
  #refMsg.ok { color:#8fc98a; } #refMsg.fail { color:var(--danger); }
  #pseudoInput {
    width:100%; background:#191720; color:var(--ink); border:1px solid var(--gold-dim);
    font-family:inherit; font-size:12px; padding:8px 9px; margin-bottom:8px;
  }
  #pseudoMsg { font-size:11.5px; margin-top:4px; margin-bottom:8px; min-height:14px; }
  #pseudoMsg.ok { color:#8fc98a; } #pseudoMsg.fail { color:var(--danger); }
  .refRules { list-style:none; margin:12px 0 0; padding:0; font-size:10.5px; color:var(--ink-dim); }
  .refRules li { padding-left:14px; position:relative; margin-bottom:4px; line-height:1.4; }
  .refRules li::before { content:'—'; position:absolute; left:0; color:var(--gold-dim); }

  #gameBar button, #metaBar button { background:rgba(10,9,12,.6); border:1px solid #2c2a33; }
  #gameBar button:hover, #metaBar button:hover { border-color:var(--gold); }
  #btnPatch { position:relative; }

  /* slider FR/EN */
  #langToggle {
    position:relative; display:flex; width:100%; height:38px;
    background:rgba(10,9,12,.6); border:1px solid #2c2a33; cursor:pointer; user-select:none;
  }
  #langToggle:hover { border-color:var(--gold); }
  .langOpt {
    flex:1; display:flex; align-items:center; justify-content:center;
    font-size:11px; font-weight:bold; letter-spacing:.5px; color:var(--ink-dim); z-index:2;
    transition:color .2s ease;
  }
  .langOpt.active { color:#1a1712; }
  #langThumb {
    position:absolute; top:2px; left:2px; width:calc(50% - 2px); height:calc(100% - 4px);
    background:var(--gold); transition:left .2s ease;
  }
  #langThumb.en { left:calc(50% + 0px); }
  #btnPatch.hasNew { border-color:var(--gold); animation:patchHalo 1.6s infinite; }
  @keyframes patchHalo {
    0%,100% { box-shadow:0 0 0 0 rgba(201,165,90,.55); }
    50% { box-shadow:0 0 8px 3px rgba(201,165,90,.55); }
  }
  #patchBadge, #questBadge, #mailBadge, #notifBadge {
    display:none; align-items:center; justify-content:center;
    min-width:15px; height:15px; padding:0 3px; margin-left:5px;
    background:var(--danger); color:#fff; font-size:9px; font-weight:bold;
    border-radius:8px; vertical-align:middle;
  }
  #patchBadge.show, #questBadge.show, #mailBadge.show, #notifBadge.show { display:inline-flex; }
  #btnNotifCenter.hasNew { border-color:var(--gold); animation:patchHalo 1.6s infinite; }
  /* centre de notifications — refait proprement le 2026-07-07 : sections par importance
     (Important/Réussites/Activité) au lieu d'une liste plate, avec un accent de couleur par
     catégorie pour distinguer d'un coup d'oeil ce qui compte vraiment. Rafraîchi le 2026-07-08 :
     liste défilante (20 dernières entrées, persistantes 7 jours) + bouton de suppression par ligne. */
  .notifSummary { font-size:10.5px; color:var(--ink-dim); margin-bottom:10px; padding-bottom:8px; border-bottom:1px solid #2c2a33; }
  .notifScroll { max-height:420px; overflow-y:auto; padding-right:2px; }
  .notifScroll::-webkit-scrollbar { width:7px; }
  .notifScroll::-webkit-scrollbar-thumb { background:#3a3742; border-radius:4px; }
  .notifSectionTitle { font-size:9.5px; letter-spacing:1px; text-transform:uppercase; color:var(--ink-dim);
    margin:12px 0 4px; display:flex; align-items:center; gap:6px; }
  .notifSectionTitle:first-of-type { margin-top:0; }
  .notifSectionCount { background:#232128; color:var(--ink-dim); font-size:9px; padding:1px 6px; border-radius:8px; }
  .notifRow { display:flex; align-items:flex-start; gap:9px; padding:8px 8px; margin-bottom:4px;
    border-left:3px solid #3a3742; border-radius:0 5px 5px 0; background:rgba(255,255,255,.015);
    transition:background .15s; }
  .notifRow:hover { background:rgba(255,255,255,.045); }
  .notifRow.important { border-left-color:var(--danger); background:rgba(192,85,69,.06); }
  .notifRow.success { border-left-color:var(--gold); background:rgba(201,165,90,.05); }
  .notifRow.info { border-left-color:#5a8fc8; }
  .notifIcon { font-size:18px; flex-shrink:0; width:24px; text-align:center; }
  .notifBody { flex:1; min-width:0; }
  .notifTitle { font-size:11px; color:var(--gold); font-weight:bold; }
  .notifRow.important .notifTitle { color:#e8a89f; }
  .notifText { font-size:11.5px; color:var(--ink); }
  .notifTime { font-size:9.5px; color:var(--ink-dim); flex-shrink:0; white-space:nowrap; margin-top:1px; }
  .notifDelBtn { width:auto; flex-shrink:0; margin:0; padding:2px 6px; font-size:10px; align-self:center;
    background:transparent; border:1px solid transparent; color:var(--ink-dim); opacity:0; transition:opacity .15s; }
  .notifRow:hover .notifDelBtn { opacity:1; }
  .notifDelBtn:hover { border-color:var(--danger); color:#e8a89f; }
  .betaTag {
    display:inline-block; background:#3a6ea8; color:#fff; font-size:8px; font-weight:bold;
    letter-spacing:.5px; padding:1px 5px; margin-left:5px; border-radius:8px; vertical-align:middle;
  }
  .patchNewTag {
    display:inline-block; background:var(--danger); color:#fff; font-size:8.5px; font-weight:bold;
    letter-spacing:.5px; padding:2px 6px; border-radius:2px; vertical-align:middle;
    animation:patchNewFade 1.6s infinite;
  }
  @keyframes patchNewFade { 0%,100% { opacity:1; } 50% { opacity:.55; } }
  /* badge "1" sur Wiki/Compendium/Codex/Succès après une modification de contenu, retiré dès que
     CE joueur ouvre le panneau (2026-07-06, demande explicite : "un numero qui s'enleve une fois
     lu") -- même style que #questBadge/#notifBadge, masqué par défaut (voir refreshContentNewBadges) */
  .contentNewBadge {
    display:none; align-items:center; justify-content:center;
    min-width:15px; height:15px; padding:0 3px; margin-left:5px;
    background:var(--danger); color:#fff; font-size:9px; font-weight:bold;
    border-radius:8px; vertical-align:middle;
  }
  .contentNewBadge.show { display:inline-flex; }
  /* mise en évidence de ce qui a changé, en haut du panneau, tant qu'il n'a pas encore été ouvert
     depuis ce changement (demande explicite : "a l'interieur met en évidence ce qui a été modifié") */
  .contentNewCallout {
    background:rgba(201,165,90,.12); border:1px solid var(--gold-dim); border-radius:4px;
    padding:7px 10px; margin-bottom:10px; font-size:11.5px; color:var(--gold);
  }

  /* ===== modal générique (wiki / patch notes) ===== */
  #infoOverlay {
    position:fixed; inset:0; background:rgba(6,5,9,.8); z-index:95;
    display:none; align-items:center; justify-content:center;
  }
  #infoOverlay.open { display:flex; }
  #infoBox {
    width:640px; max-width:94vw; max-height:82vh; display:flex; flex-direction:column;
    background:var(--panel); border:1px solid var(--gold-dim); box-shadow:0 20px 60px rgba(0,0,0,.7);
  }
  #infoHead {
    display:flex; align-items:center; gap:14px; padding:12px 16px;
    background:linear-gradient(180deg,#26313a,#1b232a); border-bottom:1px solid var(--gold-dim);
  }
  #infoHead h2 { font-size:15px; letter-spacing:1px; margin:0; flex:1; }
  #closeInfo { width:auto; margin:0; padding:4px 9px; background:none; border:none; font-size:16px; color:var(--ink-dim); }
  #infoBody { padding:16px 18px; overflow-y:auto; font-size:12.5px; line-height:1.6; color:var(--ink); }
  #infoBody h3 { color:var(--gold); font-size:13px; letter-spacing:.5px; margin:16px 0 6px; }

  /* comparateur avant/après des notes de version (2026-07-05, demande explicite) : s'affiche
     PAR-DESSUS le panneau des notes de version -- z-index supérieur, même famille visuelle */
  #patchImgOverlay {
    position:fixed; inset:0; background:rgba(6,5,9,.88); z-index:105;
    display:none; align-items:center; justify-content:center;
  }
  #patchImgOverlay.open { display:flex; }
  #patchImgBox {
    width:900px; max-width:96vw; max-height:92vh; display:flex; flex-direction:column;
    background:var(--panel); border:1px solid var(--gold-dim); box-shadow:0 20px 60px rgba(0,0,0,.7);
  }
  #closePatchImg { width:auto; margin:0; padding:4px 9px; background:none; border:none; font-size:16px; color:var(--ink-dim); }
  #patchImgBody { display:flex; gap:12px; padding:16px; overflow:auto; }
  .patchImgCol { flex:1; min-width:0; display:flex; flex-direction:column; gap:8px; }
  .patchImgLbl {
    text-align:center; font-size:11px; font-weight:bold; letter-spacing:1px; text-transform:uppercase;
    color:var(--gold); padding:4px; border:1px solid var(--gold-dim); border-radius:4px;
  }
  .patchImgCol img { width:100%; height:auto; border:1px solid #2c2a33; border-radius:4px; background:#0d0c11; }
  @media (max-width:700px) { #patchImgBody { flex-direction:column; } }
  #infoBody h3:first-child { margin-top:0; }
  #infoBody p { color:var(--ink-dim); margin-bottom:6px; }
  #infoBody ul { margin:4px 0 10px 18px; color:var(--ink-dim); }
  #infoBody li { margin-bottom:3px; }
  #infoBody .patchEntry ul { margin:0; padding:0; list-style:none; }

  #infoBody .patchEntry {
    border-left:2px solid #2c2a33; padding:12px 14px 12px 16px; margin-bottom:10px; position:relative;
    background:rgba(255,255,255,.02); border-radius:0 6px 6px 0; transition:background .15s;
  }
  #infoBody .patchEntry:hover { background:rgba(255,255,255,.035); }
  #infoBody .patchEntry::before {
    content:''; position:absolute; left:-5px; top:16px; width:8px; height:8px;
    border-radius:50%; background:#3a3742; border:2px solid var(--panel);
  }
  #infoBody .patchEntry.latest {
    border-left-color:var(--gold-dim); background:rgba(232,184,74,.06);
    box-shadow:inset 0 0 0 1px rgba(232,184,74,.12);
  }
  #infoBody .patchEntry.latest::before { background:var(--gold); }
  #infoBody .patchEntryHead {
    display:flex; align-items:baseline; flex-wrap:wrap; gap:8px; margin-bottom:9px;
    padding-bottom:8px; border-bottom:1px solid rgba(255,255,255,.06);
  }
  #infoBody .patchVer { color:var(--gold); font-weight:bold; font-size:15px; letter-spacing:.5px; }
  #infoBody .patchName { font-size:12.5px; font-style:italic; color:var(--ink); opacity:.85; }
  #infoBody .patchDate { margin-left:auto; font-size:10px; color:var(--ink-dim); font-variant-numeric:tabular-nums; }
  #infoBody .patchEntry li {
    display:flex; flex-direction:column; gap:5px; margin-bottom:9px; line-height:1.55;
    padding-bottom:9px; border-bottom:1px dashed rgba(255,255,255,.05);
  }
  #infoBody .patchEntry li:last-child { margin-bottom:0; padding-bottom:0; border-bottom:none; }
  #infoBody .patchEntry li.patchLineRemoved { opacity:.5; text-decoration:line-through; }
  #infoBody .patchLineMain { display:flex; align-items:flex-start; gap:9px; }
  /* pastille de gravité (2026-07-05, demande explicite) : déplacée dans la ligne d'infos du bas
     (comme les autres badges) pour ne plus décaler le texte de la ligne -- petit point coloré
     inline devant son libellé, à l'intérieur du badge .patchCat */
  #infoBody .patchSevDot {
    display:inline-block; width:6px; height:6px; border-radius:50%; margin-right:4px;
    vertical-align:middle; box-shadow:0 0 3px rgba(0,0,0,.5);
  }
  #infoBody .patchLineText { flex:1; color:var(--ink); }
  /* bouton avant/après (2026-07-05, demande explicite) : petite icône image, inline avec le texte */
  #infoBody .patchImgBtn {
    flex-shrink:0; width:auto; margin:0; padding:1px 6px; font-size:11px; line-height:1.4;
    background:rgba(255,255,255,.04); border:1px solid rgba(255,255,255,.14); border-radius:4px;
  }
  #infoBody .patchImgBtn:hover { border-color:var(--gold); background:rgba(201,165,90,.12); }
  #infoBody .patchLineExtra { display:flex; flex-wrap:wrap; gap:6px; margin-left:0; padding-left:2px; opacity:.9; }
  /* groupe de lignes par catégorie (2026-07-05, demande explicite) : liseré DORÉ constant entre
     chaque sous-catégorie, quelle que soit sa couleur de texte -- toutes les lignes d'un groupe
     s'alignent à la même hauteur, sous l'en-tête, plutôt qu'un badge répété par ligne */
  #infoBody .patchGroup { margin-bottom:14px; }
  #infoBody .patchGroup + .patchGroup { padding-top:10px; border-top:2px solid var(--gold-dim); }
  #infoBody .patchGroup:last-child { margin-bottom:0; }
  #infoBody .patchGroupHead { font-size:11px; font-weight:bold; letter-spacing:.4px; margin-bottom:8px; cursor:help; width:fit-content; }
  #infoBody .patchSub {
    flex-shrink:0; font-size:9px; letter-spacing:.2px; color:var(--ink-dim); cursor:help;
    border:1px solid rgba(255,255,255,.14); border-radius:10px; padding:1.5px 8px; white-space:nowrap;
  }
  #infoBody .patchCat {
    flex-shrink:0; font-size:9px; font-weight:bold; letter-spacing:.3px; cursor:help;
    border:1px solid; border-radius:10px; padding:2px 8px; white-space:nowrap; margin-top:1px;
    background:rgba(255,255,255,.04);
  }
  #infoBody .patchRemoved {
    flex-shrink:0; font-size:9px; font-weight:bold; letter-spacing:.3px; text-decoration:none;
    color:var(--danger); border:1px solid var(--danger); border-radius:10px; padding:2px 8px;
    white-space:nowrap; margin-left:auto; background:rgba(232,80,80,.08);
  }

  /* ===== tableau de bord admin ===== */
  .admBars { display:flex; flex-direction:column; gap:3px; margin-bottom:6px; }
  .admBarRow { display:flex; align-items:center; gap:8px; font-size:10.5px; }
  .admBarLbl { width:80px; flex-shrink:0; color:var(--ink-dim); }
  .admBarTrack { flex:1; height:11px; background:#0d0c11; border:1px solid #2c2a33; overflow:hidden; }
  .admBar { height:100%; background:linear-gradient(90deg,#8a7038,#c9a55a); }
  .admBarVal { width:64px; flex-shrink:0; text-align:right; color:var(--gold); }
  .admTable { width:100%; border-collapse:collapse; font-size:11px; margin-bottom:4px; }
  .admTable th { text-align:left; color:var(--ink-dim); font-weight:normal; font-size:9.5px;
    letter-spacing:.5px; text-transform:uppercase; padding:4px 6px; border-bottom:1px solid #2c2a33; }
  .admTable td { padding:4px 6px; border-bottom:1px solid #201f26; color:var(--ink); }
  .admTable tr.admTop td { color:var(--gold); font-weight:bold; }
  .admTable tr.admPlayerRow { cursor:pointer; transition:background .15s; }
  .admTable tr.admPlayerRow:hover { background:rgba(201,165,90,.1); }
  .admTable tr.isYou td { color:var(--gold); font-weight:bold; position:relative; }
  .plNameLink { cursor:pointer; text-decoration:underline dotted; text-underline-offset:2px; }
  .plNameLink:hover { color:var(--gold); }
  .admTable tr.isYou { box-shadow:inset 0 0 0 1px var(--gold), 0 0 8px 1px rgba(201,165,90,.45); }
  .catTabs { display:flex; gap:6px; flex-wrap:wrap; margin-bottom:8px; }
  .catTab { width:auto; margin:0; padding:6px 11px; font-size:11px; background:transparent; border:1px solid #3a3742; }
  .catTab.active { border-color:var(--gold); color:var(--gold); }
  .catTab.locked { opacity:.45; cursor:not-allowed; }
  /* bascule Inventaire/Assemblage en haut de la carte Inventaire (2026-07-06, demande explicite) */
  .invModeTabs { display:flex; gap:6px; margin-bottom:8px; }
  .invModeTab { flex:1; margin:0; padding:6px 11px; font-size:11.5px; background:transparent; border:1px solid #3a3742; }
  .invModeTab.active { border-color:var(--gold); color:var(--gold); background:rgba(201,165,90,.08); }
  .admEmpty { color:var(--ink-dim); font-style:italic; text-align:center; padding:10px 0; }
  .admSummary { font-size:11px; color:var(--ink-dim); margin-bottom:8px; }
  .admSummary b { color:var(--gold); }
  /* bouton "?" du tutoriel Compendium (2026-07-08) : en haut à droite du panneau, toujours visible
     quel que soit l'onglet actif — #infoBody passe en position:relative pour lui servir d'ancre */
  #infoBody { position:relative; }
  .compTutoBtn {
    position:absolute; top:0; right:0; width:22px; height:22px; padding:0; margin:0;
    border-radius:50%; border:1px solid var(--gold-dim); background:rgba(201,165,90,.1);
    color:var(--gold); font-size:12px; font-weight:bold; line-height:20px; text-align:center;
  }
  .compTutoBtn:hover { background:rgba(201,165,90,.22); }
  /* graphique économie (moyenne/total de silver) côté admin */
  .admStatTiles { display:flex; gap:10px; margin-bottom:12px; }
  .admStatTile { flex:1; background:rgba(201,165,90,.06); border:1px solid var(--gold-dim); border-radius:5px; padding:9px 12px; }
  .admStatTile .astLbl { font-size:9.5px; letter-spacing:1px; text-transform:uppercase; color:var(--ink-dim); margin-bottom:3px; }
  .admStatTile .astVal { font-size:17px; color:var(--gold); font-weight:bold; }
  .admHistBars { display:flex; align-items:flex-end; gap:6px; height:110px; margin-bottom:6px; padding-top:6px; }
  .admHistBar { flex:1; display:flex; flex-direction:column; align-items:center; justify-content:flex-end; height:100%; }
  .admHistBar .ahbFill { width:100%; background:linear-gradient(180deg,#c9a55a,#8a7038); border-radius:2px 2px 0 0; min-height:2px; }
  .admHistBar .ahbCount { font-size:10px; color:var(--gold); margin-bottom:2px; }
  .admHistBar .ahbLbl { font-size:9px; color:var(--ink-dim); margin-top:4px; text-align:center; }
  .staleTag { font-size:10px; cursor:help; }
  /* registre de silver (onglet Silver, 2026-07-10, demande explicite : "je dois pouvoir traquer le
     moindre silver") : gagné en vert, dépensé en rouge, même code couleur partout (tableau par
     catégorie + graphique horaire) */
  .admGain { color:#8fc98a; }
  .admLoss { color:#e08a6e; }
  .admBar.admBarNeg { background:linear-gradient(90deg,#a85a42,#e08a6e); }

  /* ===== succès & quêtes journalières ===== */
  .achSummary { font-size:12px; color:var(--gold); font-weight:bold; margin-bottom:8px; }
  .achCatTab { display:inline-flex; align-items:center; gap:5px; }
  .achFilterBtn { width:auto; margin:0 0 8px; padding:4px 10px; font-size:10.5px; background:transparent; border:1px solid #3a3742; }
  .achFilterBtn.on { border-color:var(--gold); color:var(--gold); }
  .qwAllDone { color:var(--gold); font-size:11px; font-weight:bold; text-align:center; }
  .codexRow { display:flex; align-items:center; gap:10px; padding:6px 4px; border-bottom:1px solid #201f26; }
  .codexIcon { font-size:20px; width:28px; text-align:center; flex-shrink:0; }
  .codexName { font-size:12px; font-weight:bold; color:var(--ink); }
  .codexDesc { font-size:10.5px; color:var(--ink-dim); }
  .wikiTab { display:inline-flex; align-items:center; gap:4px; }
  .achRow {
    display:flex; align-items:center; gap:10px; padding:8px 6px;
    border-bottom:1px solid #201f26; opacity:.72;
  }
  .achRow.done { opacity:1; }
  .achIcon { font-size:20px; width:28px; text-align:center; flex-shrink:0; }
  .achInfo { flex:1; min-width:0; }
  .achName { font-weight:bold; color:var(--ink); font-size:12px; }
  .achDesc { font-size:10.5px; color:var(--ink-dim); margin:1px 0 4px; }
  .achBarWrap { height:5px; background:#201f26; border-radius:3px; overflow:hidden; }
  .achBar { height:100%; background:linear-gradient(90deg,#8a7038,#c9a55a); }
  .achProgress { font-size:10px; color:var(--ink-dim); margin-top:2px; }
  .achReward { flex-shrink:0; font-size:11px; color:var(--gold); font-weight:bold; white-space:nowrap; }
  /* Compendium (2026-07-08) : petites puces d'objets par zone, dans une carte .achRow réutilisée */
  .compItems { display:flex; flex-wrap:wrap; gap:4px 8px; }
  .compItem { font-size:9.5px; color:var(--ink-dim); }
  .compItem.done { color:#8fc98a; }
  .questClaimBtn {
    flex-shrink:0; width:auto; margin:0; background:var(--gold); color:#1a1712; border:none; border-radius:3px;
    padding:3px 8px; font-size:9.5px; font-weight:bold; cursor:pointer; white-space:nowrap;
  }
  .questClaimBtn:hover { background:#e0bc72; }
  /* petit bouton claim compact dans l'encart de suivi */
  .qwClaimBtn {
    flex-shrink:0; width:auto; margin:0; background:var(--gold); color:#1a1712; border:none; border-radius:3px;
    padding:2px 6px; font-size:9px; font-weight:bold; cursor:pointer; white-space:nowrap;
  }
  .qwClaimBtn:hover { background:#e0bc72; }

  /* toasts en haut à GAUCHE : l'encart de suivi (timers/succès/quêtes suivies) occupe désormais
     tout le haut-à-droite en permanence, on évite qu'ils se chevauchent */
  #achToastStack {
    position:fixed; top:14px; left:14px; z-index:400;
    display:flex; flex-direction:column; gap:6px; pointer-events:none;
  }
  .achToast {
    display:flex; align-items:center; gap:8px; background:#1c1a22; border:1px solid var(--gold-dim);
    border-radius:6px; padding:8px 12px; box-shadow:0 4px 14px rgba(0,0,0,.5);
    opacity:0; transform:translateX(20px); transition:opacity .3s ease, transform .3s ease;
    max-width:260px;
  }
  .achToast.show { opacity:1; transform:translateX(0); }
  .achToastIcon { font-size:22px; }
  .achToastTitle { font-size:9.5px; letter-spacing:.5px; text-transform:uppercase; color:var(--gold); }
  .achToastName { font-size:12px; font-weight:bold; color:var(--ink); }
  .achToastReward { font-size:11px; color:var(--gold); }
  .questSection { margin-bottom:4px; }
  .questSectionTitle {
    font-size:9.5px; letter-spacing:2px; text-transform:uppercase; color:var(--gold);
    font-weight:normal; margin:10px 0 4px; border-bottom:1px solid #2c2a33; padding-bottom:4px;
    cursor:pointer; user-select:none;
  }
  .questSection:first-child .questSectionTitle { margin-top:0; }
  .achRow.inactive { opacity:.4; }
  .achRow.inactive .achReward { font-size:9.5px; color:var(--ink-dim); font-weight:normal; }
  .qScopeTab { display:inline-flex; align-items:center; gap:5px; }
  .qCountBadge {
    display:inline-flex; align-items:center; justify-content:center; min-width:16px; height:16px;
    padding:0 4px; border-radius:8px; font-size:9px; font-weight:bold;
    background:#2c2a33; color:var(--ink-dim);
  }
  .qCountBadge.ready { background:var(--gold); color:#1a1712; }
  .qCountBadge.done { background:transparent; color:#7aa35e; }

  #rightWidgets {
    position:fixed; top:14px; right:14px; z-index:300;
    display:flex; flex-direction:column; gap:8px; align-items:flex-end; max-width:290px;
  }
  .floatWidget {
    width:100%; background:#1c1a22; border:1px solid var(--gold-dim); border-radius:6px;
    padding:8px 10px; font-size:11px; box-shadow:0 4px 14px rgba(0,0,0,.5);
  }
  /* l'encart de suivi des quêtes est volontairement plus grand/lisible que le reste (demande
     explicite : chiffres nécessaires bien visibles, pas juste un nom de quête vague) */
  #questTrackerWidget { padding:11px 13px; font-size:12.5px; }
  #questTrackerWidget .qwTitle { font-size:11px; }
  .floatWidget:empty { display:none; }
  .qwHeaderRow { display:flex; justify-content:space-between; align-items:center; gap:8px; }
  .qwHeaderRow .qwTitle { font-size:9.5px; letter-spacing:1px; text-transform:uppercase; color:var(--gold); }
  .qwFoldBtn {
    width:auto; margin:0; padding:0 5px; font-size:10px; line-height:1.6; background:transparent;
    border:1px solid var(--gold-dim); flex-shrink:0;
  }
  .qwBody { margin-top:6px; }
  .qwRow { display:flex; justify-content:space-between; align-items:center; gap:10px; margin:2px 0; }
  .qwLbl { color:var(--ink-dim); }
  .qwSep { margin:6px 0 3px; padding-top:5px; border-top:1px solid #2c2a33; font-size:9px; letter-spacing:1px; text-transform:uppercase; color:var(--gold); }
  .qwTimer { color:var(--gold); font-variant-numeric:tabular-nums; }
  .qwNext { display:flex; align-items:center; gap:7px; margin-top:6px; padding-top:6px; border-top:1px solid #2c2a33; }
  .qwNextIcon { font-size:16px; }
  .qwNextInfo { flex:1; min-width:0; }
  .qwNextName { font-size:10.5px; color:var(--ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .qwTrackRow { display:flex; align-items:center; gap:9px; margin:8px 0; }
  .qwTrackIcon { font-size:19px; flex-shrink:0; }
  .qwTrackInfo { flex:1; min-width:0; }
  .qwTrackName { font-size:12px; font-weight:bold; color:var(--ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .qwTrackNum { font-size:11px; color:var(--gold); margin:2px 0 3px; font-variant-numeric:tabular-nums; }
  .qwScopeLbl { font-size:9px; letter-spacing:1px; text-transform:uppercase; color:var(--ink-dim); margin:8px 0 2px; }
  .qwScopeLbl:first-child { margin-top:0; }
  .qwEmpty { font-size:10.5px; color:var(--ink-dim); font-style:italic; margin-top:4px; }
  #btnToggleTracker { margin-bottom:8px; }

  /* ===== chat (mondial/trade/annonce) — bas à droite, thème sombre/or comme le reste ===== */
  #chatWidget {
    position:fixed; bottom:14px; right:14px; z-index:300; width:440px;
    background:#1c1a22; border:1px solid var(--gold-dim); border-radius:6px;
    padding:10px 13px; font-size:12px; box-shadow:0 4px 14px rgba(0,0,0,.5);
  }
  #chatWidget .catTabs { margin-bottom:6px; gap:4px; }
  #chatWidget .catTab { padding:4px 9px; font-size:10.5px; }
  .catTab.chan-mondial.active { border-color:#9cc9e8; color:#9cc9e8; }
  .catTab.chan-trade.active { border-color:#8fc98a; color:#8fc98a; }
  .catTab.chan-english.active { border-color:#c9a0e8; color:#c9a0e8; }
  .catTab.chan-annonce.active { border-color:var(--gold); color:var(--gold); }
  /* halo "non lu" sur l'onglet d'un canal qu'on ne regarde pas actuellement */
  #chatWidget .catTab.unread { border-color:#e0a840; animation:chatTabHalo 1.3s ease-in-out infinite; }
  @keyframes chatTabHalo {
    0%,100% { box-shadow:0 0 4px 1px rgba(224,168,64,.5); }
    50% { box-shadow:0 0 9px 3px rgba(224,168,64,.9); }
  }
  /* halo temporaire sur un message tout juste arrivé (pas encore "digéré" par le prochain fetch) */
  .chatMsg.newMsg { animation:chatMsgHalo 1.3s ease-in-out infinite; border-radius:3px; }
  @keyframes chatMsgHalo {
    0%,100% { box-shadow:0 0 3px 1px rgba(224,168,64,.35); }
    50% { box-shadow:0 0 8px 2px rgba(224,168,64,.8); }
  }
  #chatMessages {
    height:400px; overflow-y:auto; display:flex; flex-direction:column; gap:4px;
    padding-right:2px; margin-bottom:6px;
  }
  #chatMessages::-webkit-scrollbar { width:5px; }
  #chatMessages::-webkit-scrollbar-thumb { background:#3a3742; }
  .chatMsg { font-size:12.5px; line-height:1.4; word-break:break-word; position:relative; padding-right:16px; }
  .chatMsg .chatPseudo { font-weight:bold; }
  .chatMsg.chan-mondial .chatPseudo { color:#9cc9e8; }
  .chatMsg.chan-trade .chatPseudo { color:#8fc98a; }
  .chatMsg.chan-english .chatPseudo { color:#c9a0e8; }
  .chatMsg.chan-annonce .chatPseudo { color:var(--gold); }
  .chatMsg.chan-annonce .chatText { color:var(--danger); font-weight:bold; }
  .chatMsg .chatText { color:var(--ink); }
  .chatMsg .chatTime { font-size:9.5px; color:var(--ink-dim); margin-left:5px; }
  .chatBadge { font-size:8px; font-weight:bold; letter-spacing:.5px; padding:1px 4px; border-radius:3px; margin:0 3px; vertical-align:middle; }
  .chatBadge.admin { background:var(--gold); color:#1a1712; }
  .chatBadge.mod { background:#3a6ea8; color:#fff; }
  .chatDelBtn {
    position:absolute; top:0; right:0; width:auto; margin:0; padding:0 3px; font-size:11px;
    line-height:1.2; background:none; border:none; color:var(--ink-dim); cursor:pointer; opacity:.5;
  }
  .chatDelBtn:hover { opacity:1; color:var(--danger); }
  .modMsg { padding-right:0; border-bottom:1px solid #2c2a33; padding-bottom:5px; }
  .modTop { display:flex; align-items:baseline; gap:6px; justify-content:space-between; }
  .modChan { font-size:9px; color:var(--ink-dim); }
  .modUuidLine { display:block; font-family:monospace; font-size:9px; color:var(--ink-dim); margin:1px 0 2px; word-break:break-all; }
  .modRestoreBtn {
    width:auto; margin:0; padding:2px 7px; font-size:9.5px; flex-shrink:0;
    background:none; border:1px solid var(--gold-dim); color:var(--gold);
  }
  .modRestoreBtn:hover { background:rgba(201,165,90,.12); }
  .modDeletedAt { font-size:9px; color:var(--ink-dim); }
  .chatEmpty { font-size:11px; color:var(--ink-dim); font-style:italic; }
  /* barre dorée de séparation entre les jours du chat — demande explicite du 2026-07-07 */
  .chatDaySep { display:flex; align-items:center; gap:8px; margin:6px 0 4px; cursor:pointer; user-select:none; }
  .chatDaySep.current { cursor:default; }
  .chatDaySepLine { flex:1; height:1px; background:linear-gradient(90deg, transparent, var(--gold-dim), transparent); }
  .chatDaySep.current .chatDaySepLine { background:linear-gradient(90deg, transparent, var(--gold), transparent); }
  .chatDaySepLabel { font-size:9.5px; letter-spacing:.8px; text-transform:uppercase; color:var(--gold);
    white-space:nowrap; flex-shrink:0; }
  .chatDaySep:not(.current):hover .chatDaySepLabel { color:#e6cf7a; }
  #chatInputRow { display:flex; gap:5px; position:relative; }
  #chatInput {
    flex:1; background:#0d0c11; border:1px solid #333; color:var(--ink); padding:5px 7px;
    font-size:11px; font-family:inherit; border-radius:3px;
  }
  #chatSendBtn { width:auto; margin:0; padding:5px 10px; flex-shrink:0; }
  #chatNote { font-size:10px; color:var(--ink-dim); font-style:italic; margin-top:4px; }

  /* mentions @joueur (2026-07-05, demande explicite) : liste de suggestions au-dessus du champ */
  #chatMentionList {
    display:none; position:absolute; left:0; right:0; bottom:100%; margin-bottom:4px;
    background:#1c1a22; border:1px solid var(--gold-dim); border-radius:4px; max-height:160px;
    overflow-y:auto; box-shadow:0 -4px 14px rgba(0,0,0,.5); z-index:10;
  }
  #chatMentionList.show { display:block; }
  .chatMentionItem { padding:5px 9px; font-size:11px; cursor:pointer; color:var(--ink); }
  .chatMentionItem:hover, .chatMentionItem.active { background:rgba(201,165,90,.15); color:var(--gold); }
  /* mention @joueur en couleur dans un message envoyé/reçu */
  .chatMention { color:var(--gold); font-weight:bold; }
  /* message qui ME mentionne : fond distinct pour bien le repérer dans le flux */
  .chatMsg.pingedMe { background:rgba(224,168,64,.14); border-radius:4px; padding-left:4px; }
  /* attention sur le widget replié quand on est mentionné (2026-07-05, demande explicite :
     "couleur/vibration/agrandissement du chat pour faire ouvrir") -- se retire toute seule après
     quelques secondes ou dès que le joueur déplie/interagit avec le chat */
  /* infinie (2026-07-05, demande explicite : "doit s'illuminer et bouger en permanence tant qu'on
     n'a pas lu") -- retirée par JS dès que le joueur déplie le chat, voir toggleChatFold() */
  #chatWidget.pinged { animation:chatPingAttention 2.4s ease-in-out infinite; }
  @keyframes chatPingAttention {
    0%,100% { transform:scale(1); border-color:var(--gold-dim); box-shadow:0 4px 14px rgba(0,0,0,.5); }
    50% { transform:scale(1.035); border-color:var(--gold); box-shadow:0 0 22px 4px rgba(224,168,64,.75); }
  }

  /* ===== barre d'activités (au-dessus du farm) ===== */
  /* header au-dessus de la zone de farm */
  #activitiesBar {
    display:flex; align-items:center; gap:12px; margin-bottom:8px; padding:7px 10px;
    background:var(--panel); border:1px solid #2c2a31; border-bottom:1px solid var(--gold-dim);
  }
  /* liste de pages dans le header : Zone / Boss / activités verrouillées */
  #activityTabs { display:flex; flex-wrap:wrap; gap:5px; flex:1; }
  .actTab {
    width:auto; margin:0; padding:5px 11px; font-size:11.5px; font-weight:bold;
    background:transparent; border:1px solid #3a3742;
  }
  .actTab.active { border-color:var(--gold); color:var(--gold); background:rgba(201,165,90,.08); }
  .actTab.locked { opacity:.4; cursor:not-allowed; }
  #nextBossMini { font-size:11px; color:var(--ink-dim); flex-shrink:0; }
  #nextBossMini b { color:var(--gold); }
  #nextBossMini .live { color:var(--danger); font-weight:bold; animation:patchNewFade 1.2s infinite; }

  /* tuiles du menu Activités */
  .actGrid { display:grid; grid-template-columns:repeat(2,1fr); gap:10px; }
  .actTile {
    display:flex; flex-direction:column; align-items:center; gap:6px; padding:16px 10px;
    border:1px solid #3a3742; background:var(--panel-2); cursor:pointer; text-align:center;
    transition:border-color .12s, transform .12s;
  }
  .actTile:hover:not(.locked) { border-color:var(--gold); transform:translateY(-2px); }
  .actTile.locked { opacity:.45; cursor:not-allowed; filter:grayscale(.6); }
  .actTileIcon { font-size:30px; }
  .actTileName { font-size:12px; font-weight:bold; color:var(--ink); }
  .actTileSub { font-size:10px; color:var(--ink-dim); }
  .actTile.locked .actTileSub { color:var(--danger); }

  /* panneau boss : prochain + calendrier hebdo */
  .bossNext {
    display:flex; align-items:center; gap:12px; padding:12px; margin-bottom:12px;
    border:1px solid var(--gold-dim); background:rgba(201,165,90,.07); border-radius:4px;
  }
  .bossNextIcon { font-size:34px; }
  .bossNextInfo { flex:1; }
  .bossNextName { font-size:14px; font-weight:bold; color:var(--gold); }
  .bossNextTime { font-size:12px; color:var(--ink); }
  .bossNextCountdown { font-size:20px; font-weight:bold; color:var(--ink); font-variant-numeric:tabular-nums; }
  .bossNextCountdown.live { color:var(--danger); animation:patchNewFade 1.2s infinite; }
  .bossFightBtn { margin-top:0; }
  .bossFightBtn:disabled { opacity:.4; cursor:not-allowed; }
  .bossSchedRow { display:flex; align-items:center; gap:8px; padding:5px 10px; border-bottom:1px solid #232128; font-size:11.5px; }
  .bossSchedRow.soon { background:rgba(201,165,90,.08); }
  .bossSchedName { flex:1; }
  .bossSchedTime { color:var(--gold); font-variant-numeric:tabular-nums; }
  .bossDay { border-bottom:1px solid #2c2a33; }
  .bossDaySummary {
    cursor:pointer; user-select:none; padding:7px 4px; font-size:12px; color:var(--ink);
    text-transform:capitalize; display:flex; align-items:center; gap:8px;
  }
  .bossDaySummary::-webkit-details-marker { color:var(--gold); }
  .bossDayCount { margin-left:auto; font-size:10px; color:var(--ink-dim); background:#2c2a33; border-radius:8px; padding:1px 7px; }
  /* grille calendrier hebdomadaire des boss (jours × heures) */
  .bossCal { display:grid; gap:2px; margin-bottom:8px; }
  .bcCorner { background:transparent; }
  .bcHead { text-align:center; font-size:9.5px; text-transform:capitalize; color:var(--ink-dim); padding:3px 1px; background:#201f26; border-radius:3px; line-height:1.25; }
  .bcHead.bcToday { color:var(--gold); background:rgba(201,165,90,.12); font-weight:bold; }
  .bcHead .bcDate { display:block; font-size:8.5px; opacity:.7; }
  .bcTime { display:flex; align-items:center; justify-content:center; font-size:10px; color:var(--gold); font-variant-numeric:tabular-nums; }
  .bcCell { min-height:30px; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:1px; background:#1a1920; border-radius:3px; font-size:14px; }
  .bcCell.bcEmpty { background:#141319; }
  .bcCell .bcName { font-size:7px; color:var(--ink-dim); text-align:center; line-height:1; max-width:100%; overflow:hidden; }
  .bcCell.bcLive { background:rgba(224,80,80,.2); box-shadow:inset 0 0 0 1px var(--danger); }
  .bcCell.bcLive .bcName { color:var(--danger); font-weight:bold; }
  .bcLegendRow { display:flex; flex-wrap:wrap; gap:10px; margin-bottom:6px; }
  .bcLegend { font-size:10.5px; color:var(--ink-dim); }

  /* ===== salle de boss plein écran ===== */
  /* le boss est DANS le flux du jeu, juste sous le header (qui reste donc toujours visible),
     et remplit le reste de la hauteur de l'écran — pas sur les côtés, dans la colonne du jeu */
  #bossRoom {
    display:none; width:100%; background:#141018; border:1px solid #2c2a31;
    flex-direction:column; height:calc(100vh - 62px); min-height:440px;
  }
  #bossRoom.open { display:flex; }
  #bossLobby { display:none; flex-direction:column; height:100%; overflow-y:auto; }
  #bossRoom.lobby #bossLobby { display:flex; }
  #bossRoom.lobby #bossArena { display:none; }
  #bossRoom.fight #bossLobby { display:none; }
  #bossArena { display:flex; flex-direction:column; height:100%; }
  #bossLobbyHead {
    display:flex; align-items:center; justify-content:space-between; padding:12px 18px;
    background:linear-gradient(180deg,#26313a,#1b232a); border-bottom:1px solid var(--gold-dim);
  }
  #bossLobbyHead h2 { font-size:16px; margin:0; }
  #bossLobbyClose { width:auto; margin:0; padding:4px 10px; font-size:16px; background:none; border:none; color:var(--ink-dim); }
  #bossLobbyBody { padding:16px 18px; }
  #bossTopBar {
    display:flex; align-items:center; gap:12px; padding:10px 16px; background:rgba(0,0,0,.5);
    border-bottom:1px solid var(--gold-dim);
  }
  #bossName { font-size:16px; font-weight:bold; color:var(--danger); letter-spacing:1px; flex-shrink:0; }
  #bossHpBarWrap {
    flex:1; height:22px; background:#1a0d0d; border:1px solid #5a2020; border-radius:4px;
    position:relative; overflow:hidden; box-shadow:inset 0 2px 5px rgba(0,0,0,.6), 0 0 10px rgba(224,64,64,.15);
  }
  #bossHpBar {
    height:100%; width:100%; background:linear-gradient(90deg,#6e1616,#e04040 55%,#ff7a5a);
    transition:width .2s linear, box-shadow .3s ease; position:relative;
    box-shadow:0 0 10px rgba(224,64,64,.6) inset;
  }
  #bossHpBar.low { animation:bossHpLowPulse 1.1s ease-in-out infinite; }
  @keyframes bossHpLowPulse {
    0%,100% { filter:brightness(1); box-shadow:0 0 10px rgba(255,60,40,.7) inset; }
    50% { filter:brightness(1.35); box-shadow:0 0 20px rgba(255,90,40,.95) inset; }
  }
  #bossHpBar::after {
    content:''; position:absolute; inset:0;
    background:linear-gradient(180deg,rgba(255,255,255,.28),rgba(255,255,255,0) 45%);
  }
  #bossHpTicks { position:absolute; inset:0; display:flex; pointer-events:none; }
  #bossHpTicks span { flex:1; border-right:1px solid rgba(0,0,0,.35); }
  #bossHpTicks span:last-child { border-right:none; }
  #bossHpTxt {
    position:absolute; inset:0; display:flex; align-items:center; justify-content:center; gap:6px;
    font-size:11px; font-weight:bold; color:#fff; text-shadow:0 1px 3px #000; font-variant-numeric:tabular-nums;
  }
  #bossHpTxt .bhpPct { font-size:13px; color:#ffd9c8; }
  #bossHpTxt .bhpNum { color:rgba(255,255,255,.75); font-size:9.5px; }
  #bossTimer { font-size:15px; font-weight:bold; color:var(--gold); font-variant-numeric:tabular-nums; flex-shrink:0; }
  #bossLeaveBtn { width:auto; margin:0; padding:4px 10px; font-size:15px; flex-shrink:0; background:none; border:none; color:var(--ink-dim); }
  #bossCv { flex:1; width:100%; min-height:0; display:block; }
  #bossPlayerHpWrap {
    position:relative; height:16px; margin:0 16px 10px; background:#0d0c11; border:1px solid #333;
    border-radius:3px; overflow:hidden;
  }
  #bossPlayerHp { height:100%; width:100%; background:linear-gradient(90deg,#5a8a3a,#8fc98a); transition:width .15s linear; }
  #bossPlayerHpTxt { position:absolute; inset:0; display:flex; align-items:center; justify-content:center; font-size:10px; color:#fff; text-shadow:0 1px 1px #000; }
  #bossResult {
    display:none; position:absolute; inset:0; align-items:center; justify-content:center;
    flex-direction:column; gap:14px; background:rgba(0,0,0,.72); text-align:center; padding:20px;
  }
  #bossResult.show { display:flex; }
  #bossResult .brTitle { font-size:28px; font-weight:bold; letter-spacing:2px; }
  #bossResult .brTitle.win { color:var(--gold); }
  #bossResult .brRewards { font-size:14px; color:var(--ink); }
  #bossResult button { width:auto; padding:8px 24px; font-size:13px; }
  /* roue de récompense rare (2026-07-08) : tourne toute seule en fin de combat, révèle le lot déjà tiré */
  .bossWheelWrap { position:relative; width:180px; height:180px; margin:4px auto; }
  .bossWheelPointer { position:absolute; top:-14px; left:50%; transform:translateX(-50%); font-size:20px; color:var(--gold); z-index:2; }
  .bossWheel { width:100%; height:100%; border-radius:50%; border:4px solid var(--gold-dim);
    box-shadow:0 0 16px rgba(0,0,0,.5); position:relative; transition:transform 3.5s cubic-bezier(.12,.65,.16,1); }
  .bwIcon { position:absolute; top:50%; left:50%; width:26px; height:26px; margin:-13px; font-size:19px;
    display:flex; align-items:center; justify-content:center; }
  .bossWheelResult { font-size:12.5px; color:var(--ink-dim); min-height:18px; }

  /* ===== tutoriel d'arrivée (Velia) : encadré + flèche pointant vers l'élément expliqué ===== */
  #tutorialOverlay { display:none; position:fixed; inset:0; z-index:900; }
  #tutorialOverlay.open { display:block; }
  #tutorialHighlight {
    position:fixed; z-index:901; border-radius:6px; pointer-events:none;
    box-shadow:0 0 0 9999px rgba(8,7,10,.72), 0 0 0 3px var(--gold), 0 0 18px 3px rgba(201,165,90,.6);
    /* pas de transition : la position est recalculée à chaque frame (voir tutorialTrackLoop) pour
       un suivi pixel perfect de la cible, y compris pendant un scroll — une transition CSS créerait
       un décalage/lag visible pendant le scroll */
  }
  #tutorialHighlight.center { box-shadow:0 0 0 9999px rgba(8,7,10,.72); }
  #tutorialBox {
    position:fixed; z-index:902; width:280px; background:#1c1a22; border:1px solid var(--gold);
    border-radius:8px; padding:14px 16px; box-shadow:0 6px 24px rgba(0,0,0,.6);
  }
  #tutorialBox .tutStep { font-size:9.5px; color:var(--gold); letter-spacing:1px; text-transform:uppercase; margin-bottom:4px; }
  #tutorialBox h4 { margin:0 0 8px; font-size:14px; color:var(--gold); }
  #tutorialBox p { margin:0 0 12px; font-size:12px; line-height:1.5; color:var(--ink); }
  #tutorialBox .tutBtns { display:flex; justify-content:space-between; gap:8px; }
  #tutorialBox .tutSkip { width:auto; margin:0; padding:6px 10px; font-size:11px; background:none; border:none; color:var(--ink-dim); }
  #tutorialBox .tutPrev { width:auto; margin:0; padding:6px 10px; font-size:11px; background:none; border:1px solid var(--gold-dim); color:var(--ink-dim); }
  #tutorialBox .tutPrev:disabled { opacity:.3; }
  #tutorialBox .tutNext { width:auto; margin:0; padding:6px 16px; font-size:12px; font-weight:bold; }
  #tutorialArrow { position:fixed; z-index:902; width:0; height:0; pointer-events:none; }
  #tutorialArrow.top    { border-left:9px solid transparent; border-right:9px solid transparent; border-bottom:11px solid var(--gold); }
  #tutorialArrow.bottom { border-left:9px solid transparent; border-right:9px solid transparent; border-top:11px solid var(--gold); }
  #tutorialArrow.left   { border-top:9px solid transparent; border-bottom:9px solid transparent; border-right:11px solid var(--gold); }
  #tutorialArrow.right  { border-top:9px solid transparent; border-bottom:9px solid transparent; border-left:11px solid var(--gold); }
  /* indice "il faut défiler" (2026-07-05, demande explicite) : caché par défaut, affiché par
     positionTutorialStep() SEULEMENT quand la cible de l'étape en cours est hors du champ visible
     (au-dessus ou en-dessous de l'écran). Icône souris/molette sur ordinateur, doigt sur mobile/
     tablette (même seuil que isMobileViewport(), 1024px) — jamais les deux en même temps. */
  #tutorialScrollHint {
    display:none; position:fixed; z-index:903; left:50%; transform:translateX(-50%);
    flex-direction:column; align-items:center; gap:2px; pointer-events:none;
    font-size:26px; text-shadow:0 2px 6px rgba(0,0,0,.7);
    animation:tutHintBounce 1.1s ease-in-out infinite;
  }
  #tutorialScrollHint.show { display:flex; }
  #tutorialScrollHint.up { animation-name:tutHintBounceUp; }
  #tutorialScrollHint .tutHintArrow { font-size:20px; color:var(--gold); }
  #tutorialScrollHint.up .tutHintArrow { transform:rotate(180deg); }
  #tutorialScrollHint .tutHintFinger { display:none; }
  @media (max-width:1024px) {
    #tutorialScrollHint .tutHintMouse { display:none; }
    #tutorialScrollHint .tutHintFinger { display:inline; }
  }
  @keyframes tutHintBounce { 0%,100% { transform:translateX(-50%) translateY(0); } 50% { transform:translateX(-50%) translateY(8px); } }
  @keyframes tutHintBounceUp { 0%,100% { transform:translateX(-50%) translateY(0); } 50% { transform:translateX(-50%) translateY(-8px); } }
  /* classement de contribution du world boss partagé (top 10 en direct) */
  #bossTopPanel {
    /* repoussé plus bas (52px → 78px) pour ne plus jamais chevaucher la croix "✕" de sortie du
       combat, qui vit dans la rangée d'en-tête juste au-dessus — demande explicite du 2026-07-08 */
    display:none; position:absolute; top:78px; right:10px; width:200px; max-height:calc(60% - 26px);
    background:rgba(10,8,14,.82); border:1px solid var(--gold-dim); border-radius:6px;
    padding:8px; overflow-y:auto; z-index:5;
  }
  #bossTopPanel.show { display:block; }
  #bossTopPanel h4 { margin:0 0 6px; font-size:11px; color:var(--gold); letter-spacing:.5px; }
  #bossTopPanel .btpLive { display:flex; align-items:center; gap:5px; font-size:10px; color:#8fc98a; margin-bottom:6px; }
  #bossTopPanel .btpLiveDot { width:6px; height:6px; border-radius:50%; background:#8fc98a; box-shadow:0 0 5px #8fc98a; animation:btpPulse 1.4s infinite; }
  @keyframes btpPulse { 0%,100% { opacity:1; } 50% { opacity:.3; } }
  #bossTopPanel .btpRow { display:flex; align-items:center; gap:6px; font-size:10.5px; padding:2px 0; }
  #bossTopPanel .btpRow.me { color:var(--gold); font-weight:bold; }
  #bossTopPanel .btpRank { flex-shrink:0; width:16px; color:var(--ink-dim); }
  #bossTopPanel .btpPseudo { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; display:flex; align-items:center; gap:4px; }
  #bossTopPanel .btpActiveDot { width:5px; height:5px; border-radius:50%; background:#8fc98a; flex-shrink:0; box-shadow:0 0 4px #8fc98a; }
  #bossTopPanel .btpPct { flex-shrink:0; color:var(--gold); font-variant-numeric:tabular-nums; width:38px; text-align:right; }
  #bossTopPanel .btpDmg { flex-shrink:0; color:var(--ink-dim); font-variant-numeric:tabular-nums; }

  /* ===== Adaptation tablette/téléphone (2026-07-05, demande explicite) =====
     Le layout desktop suppose un écran large : #sideMenu (haut-gauche), #rightWidgets (haut-droite)
     et #chatWidget (bas-droite) flottent en position:fixed au-dessus du contenu, avec assez de marge
     de chaque côté du bloc de jeu centré (#wrap, 1240px) pour ne jamais le recouvrir. Sous 1024px de
     large (couvre aussi l'iPad en paysage, 1024×768, où le menu déplié touchait déjà le bord du
     canvas de jeu), cette marge disparaît et ces 3 panneaux flottants finissent par se chevaucher
     entre eux ET par recouvrir le jeu — confirmé en testant à 390×844 (iPhone) et 1024×768 (iPad
     paysage) avant ce correctif. Rien n'est changé au-dessus de 1024px : la version ordinateur/
     laptop reste identique à l'existant. Placé en toute fin de
     feuille de style pour être sûr de l'emporter sur les règles non-conditionnelles définies plus
     haut (même sélecteur + media query active = priorité à l'ordre d'apparition, pas au media). */
  @media (max-width:1024px) {
    /* le menu de gauche et les encarts de droite passent en repli par défaut sur mobile (voir le
       JS d'initialisation isMobileViewport()) ; ces règles gèrent le cas où l'un des deux est quand
       même ouvert, pour qu'il reste lisible sans déborder de l'écran ni écraser l'autre */
    #sideMenu { max-width:calc(100vw - 20px) !important; }
    /* le menu peut être basculé à droite (préférence perso, voir menuSide) — sur mobile ça le fait
       entrer en collision avec les encarts de suivi (aussi à droite) une fois les deux repliés en
       petites pastilles compactes ; forcé à gauche sur petit écran pour éviter ce chevauchement,
       la préférence "droite" reste respectée telle quelle au-dessus de 1024px */
    #sideMenu.onRight { left:14px !important; right:auto !important; }
    #gameBar, #userBar, #metaBar { width:min(210px, calc(100vw - 20px)); }
    #rightWidgets { max-width:min(260px, calc(100vw - 20px)) !important; }
    /* le chat gardait une largeur fixe de 440px, bien plus large que n'importe quel téléphone */
    #chatWidget { width:min(400px, calc(100vw - 20px)) !important; }
  }
  @media (max-width:600px) {
    /* sur téléphone, 1 seule colonne pour les cartes (stats/inventaire/optimisation/etc.), plus
       lisible qu'une grille à 2 colonnes trop étroites pour leur contenu (tableaux, boutons) */
    #panel { grid-template-columns:1fr !important; }
    #wrap { padding:0 2px; }
    body { padding:8px 4px 20px; }
    /* #activitiesBar met les 8 onglets (#activityTabs, flex:1) ET le texte "Prochain boss : ..."
       (#nextBossMini, assez long) côte à côte sur UNE seule ligne — sur téléphone ce texte écrase
       toute la largeur dispo pour les onglets, qui se retrouvent forcés à 1 seul par ligne (8 lignes
       de haut, confirmé sur un vrai téléphone). Empilés à la place : les onglets ont toute la
       largeur pour se répartir sur 3-4 par ligne, le texte passe en dessous. */
    #activitiesBar { flex-direction:column; align-items:stretch; gap:6px; }
    #nextBossMini { text-align:center; }
    /* #sideMenu replié (icône ◀/▶ seule) est en position:fixed tout en haut à gauche de l'écran,
       PAR-DESSUS le contenu de #wrap qui démarre au même endroit — sur téléphone, le premier onglet
       de #activitiesBar se retrouvait donc caché sous ce bouton (confirmé sur un vrai téléphone).
       Le contenu est repoussé sous l'emprise du bouton replié pour ne plus jamais le chevaucher. */
    #wrap { margin-top:46px; }
    /* La zone de jeu (canvas) est déjà responsive (width:100%), mais toute sa surcouche HTML
       (textes/icônes positionnés en absolu par-dessus) est calibrée en pixels fixes pour un canvas
       ~1240px de large — une fois le canvas réduit à la largeur d'un téléphone (~360-380px), ces
       éléments se chevauchent et débordent (confirmé sur un vrai téléphone) :
       - #aiState (centré, "IA : ...") recouvrait #zoneTitle (aligné à gauche) → décalé plus bas
       - #skillBar (9 icônes de 42px + espaces ≈ 418px de large, centré) dépassait des 2 côtés du
         cadre de jeu, coupant les icônes de bord → icônes réduites pour tenir dans la largeur */
    /* le cadre de jeu devient très bas sur téléphone (son ratio suit la largeur, ~135px de haut à
       390px de large) : pas la place d'empiler proprement #zoneTitle, #aiState et #skillBar sans
       chevauchement. #aiState n'est qu'un indicatif ("IA : SearchPack · Bolide"), pas essentiel au
       jeu (le combat reste automatique) — masqué sur téléphone plutôt que de le caser de force */
    #aiState { display:none; }
    /* barre de sorts repliée par défaut sur mobile/tablette (demande explicite du 2026-07-05) :
       purement indicative (aucun clic requis, le combat est automatique), donc pas indispensable
       en permanence — le bouton ⚡ la déplie/replie à la demande, sans jamais gêner la vue */
    #skillBar { display:none; gap:3px; }
    #skillBar.expanded { display:flex; }
    #skillBar .sk { width:30px; height:30px; }
    #skillBar .sk .ic { font-size:11px; }
    #skillBar .sk .nm { font-size:5.5px; margin-top:1px; }
    #skillBarToggle {
      display:flex; align-items:center; justify-content:center; position:absolute;
      bottom:10px; left:50%; transform:translateX(-50%); width:30px; height:30px;
      margin:0; padding:0; border-radius:50%; font-size:14px; z-index:2;
    }
    #skillBarToggle.expanded { border-color:var(--gold); color:var(--gold); }
    /* la potion (soin auto) est ce qui compte vraiment à surveiller en jeu — mise en avant sur
       mobile/tablette (demande explicite) : agrandie, halo doré, au lieu d'être réduite comme le
       reste du HUD. La barre de vie reste lisible (le % exact suffit, le détail est de toute façon
       dans la carte Statistiques en dessous) */
    #hpBar, #mpBar { width:100px; }
    #mpBar { height:8px; }
    #lvlXpLbl { font-size:10px; }
    #lvlHpCol #lvlXpRow b { font-size:16px; }
    #lvlHpCol #invXpPct { font-size:16px; }
    #potSlot {
      width:58px; height:46px; border-color:var(--gold); border-width:2px;
      box-shadow:0 0 10px rgba(201,165,90,.5);
    }
    /* #invFullBanner ("Sac plein"), #deathBanner et #dangerBanner sont centrés en haut, à la même
       hauteur que #zoneTitle (aligné à gauche, 2-3 lignes) — ils se recouvraient sur un cadre de
       jeu aussi bas (confirmé sur un vrai téléphone : la bannière rouge cachait le nom de zone ET
       les PA/PD). Repoussés sous #zoneTitle, avec un texte plus compact pour tenir sur la largeur
       réduite. */
    #invFullBanner { top:112px; font-size:10px; padding:4px 10px; max-width:calc(100% - 20px); }
    #deathBanner { top:112px; font-size:10px; padding:5px 12px; }
    #dangerBanner { top:146px; font-size:9.5px; padding:4px 10px; max-width:calc(100% - 20px); }
    /* barre d'incantation : au-dessus du bouton replié de la barre de sorts plutôt que de la
       barre déployée (qui est masquée par défaut sur mobile, voir #skillBar.expanded) */
    #castBar { bottom:46px; width:160px; }
    /* silverBox/shRate (haut-droite) et lootTicker (bas-droite) se marchent aussi dessus sur un
       cadre aussi bas — lootTicker moins haut et un peu plus petit pour laisser plus de respiration
       au silver/taux au-dessus */
    #silverBox { font-size:12px; padding:4px 9px; }
    #shRate { font-size:9.5px; }
    #lootTicker { font-size:9.5px; max-height:70px; }
  }
