/* ============================================================
   SHOP — sommaire des boutiques + pages boutique dédiées
   Préfixe .sx-  ·  s'appuie sur css/db.css (.db-page, .db-section, .db-breadcrumb)
   ============================================================ */

/* ============================================================
   Largeur de page — À NE PAS RETIRER
   `body:not(.hub-body)` est en `display:flex` (héritage des pages calculateur avec sidebar).
   Sans largeur explicite, `.db-page` est un flex item dimensionné par son CONTENU : sa largeur
   ne suit plus l'écran, et `repeat(auto-fill, …)` — qui a besoin d'une largeur connue — retombe
   sur une seule colonne. Le nombre de colonnes dépendait alors des polices du système : 3 sous
   Linux, 1 sous Windows, à code identique. On fixe la largeur, `max-width` fait le reste.
   Portée limitée aux pages Boutique : shop.css n'est chargé que par elles.
   ============================================================ */
body:not(.hub-body) .db-page { width: 100%; min-width: 0; }

/* ---------- sommaire : sections ---------- */
.sx-section { margin: 34px 0 0; }
.sx-section > h2 {
  color: var(--accent); font-size: 16px; text-transform: uppercase; letter-spacing: .03em;
  margin: 0 0 4px; border-bottom: 1px solid var(--border); padding-bottom: 8px;
  display: flex; align-items: baseline; gap: 10px;
}
.sx-section > h2 .sx-count { font-size: 12px; color: var(--text-muted); font-weight: 400; letter-spacing: 0; text-transform: none; }
.sx-section-sub { color: var(--text-muted); font-size: 13px; margin: 0 0 16px; line-height: 1.5; }

/* ---------- sommaire : grille de cartes ---------- */
.sx-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 16px; }

/* ---------- sommaire : « Voir plus » par catégorie ----------
   DEUX LIGNES de vignettes par défaut, le reste derrière un bouton. Le nombre de colonnes
   vient de `auto-fill` : il change avec la largeur, donc le plafond doit changer avec lui,
   sinon « 2 lignes » coupe au milieu d'une ligne. Plafonds = 2 × le nombre de colonnes :

     < 576px   1 colonne   -> 4   (deux lignes n'en montreraient que 2 : trop peu, on garde 4)
     576-883   2 colonnes  -> 4
     884-1159  3 colonnes  -> 6
     >= 1160   4 colonnes  -> 8

   Les trois seuils sont ceux de la grille elle-même (minmax(260px,1fr) + gap 16px), relevés
   au navigateur. Les déplacer sans les remesurer redonne des lignes coupées.

   Découpe au nombre de cartes, pas à la hauteur : une `max-height` supposerait des lignes de
   même hauteur, alors qu'une ligne s'aligne sur sa carte la plus haute (les noms de boutique
   ne font pas tous une ligne). Et pas de dégradé de fondu sur la coupe : elle tombe pile
   entre deux lignes, un fondu laisserait croire qu'une ligne est à moitié cachée.

   TOUT LE BLOC EST SOUS `@supports selector(:has(*))`, découpe comprise, et ce n'est pas
   un détail de confort. C'est `:has()` qui fait apparaître le bouton ; un navigateur qui
   l'ignore jette ces règles-là mais applique quand même la découpe — cartes masquées, plus
   aucun bouton pour les révéler, 7 boutiques sur 15 injoignables depuis leur seul lien
   interne. Liées, les deux disparaissent ensemble : la grille s'affiche entière, comme
   avant. Même repli que le <noscript> de shop_calc.html, pour la même raison. */
.sx-more { display: none; }

@supports selector(:has(*)) {
  /* SIGNAL À DESTINATION DU JS, et la seule chose qui l'autorise à replier quoi que ce
     soit. Le site n'a pas de cache-busting : un visiteur de retour peut très bien recevoir
     ce CSS neuf avec un `shop_calc.js` encore en cache. La découpe s'appliquait alors sans
     que rien ne branche le bouton — cartes masquées, bouton inerte, boutiques injoignables
     (le <noscript> ne rattrape rien, le JS est actif, juste périmé). Le JS lit donc cette
     variable AVANT de replier : elle n'existe que dans la feuille qui sait replier, et
     seulement là où `:has()` répond. Ne jamais la déclarer hors de ce bloc. */
  .sx-grid { --sx-fold: 1; }

  /* `hidden` sur la case et le libellé, levé ICI seulement : avec une feuille en cache,
     les deux restent invisibles et rien n'est replié — la grille d'avant, à l'identique.
     La case reste FOCUSABLE (elle n'est plus `display:none`), c'est elle qui reçoit le
     clavier ; le libellé porte le focus à l'écran. */
  .sx-more-cb[hidden] {
    display: block; position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }

  .sx-grid.is-clamped > .sx-card:nth-child(n+5) { display: none; }
  @media (min-width: 884px) {
    .sx-grid.is-clamped > .sx-card:nth-child(n+5) { display: flex; }
    .sx-grid.is-clamped > .sx-card:nth-child(n+7) { display: none; }
  }
  @media (min-width: 1160px) {
    .sx-grid.is-clamped > .sx-card:nth-child(n+7) { display: flex; }
    .sx-grid.is-clamped > .sx-card:nth-child(n+9) { display: none; }
  }
  /* Case cochée = tout est montré. La case précède la grille, d'où `~`. */
  .sx-more-cb:checked ~ .sx-grid.is-clamped > .sx-card { display: flex; }

  /* Le bouton n'existe que si la catégorie DÉPASSE son plafond : à 8 boutiques sur 4 colonnes
     il n'y a rien à révéler, donc rien à afficher. `:has()` le décide au même endroit et aux
     mêmes seuils que la découpe — une catégorie qui grossit fait apparaître son bouton sans
     qu'on touche à quoi que ce soit. La n-ième carte existe = il y en a plus de n-1. */
  .sx-section:has(.sx-grid > .sx-card:nth-child(5)) .sx-more[hidden] { display: flex; }
  @media (min-width: 884px) {
    .sx-section:has(.sx-grid > .sx-card:nth-child(5)) .sx-more[hidden] { display: none; }
    .sx-section:has(.sx-grid > .sx-card:nth-child(7)) .sx-more[hidden] { display: flex; }
  }
  @media (min-width: 1160px) {
    .sx-section:has(.sx-grid > .sx-card:nth-child(7)) .sx-more[hidden] { display: none; }
    .sx-section:has(.sx-grid > .sx-card:nth-child(9)) .sx-more[hidden] { display: flex; }
  }
}

/* Vocabulaire de `.sx-btn`, en pastille centrée sous la grille : c'est la fin d'une section,
   pas une commande de barre d'outils. 44px de haut = la cible tactile minimale.
   Bloc centré par `margin:auto` plutôt qu'un conteneur flex : sans bouton à montrer, le
   `display:none` ci-dessus fait tout disparaître, marge comprise — un conteneur, lui,
   laisserait 16px de vide sous les catégories qui n'ont rien à replier. */
.sx-more {
  width: fit-content; margin: 16px auto 0;
  align-items: center; justify-content: center; gap: 8px; min-height: 44px; padding: 6px 20px;
  /* --text-light, pas --text-muted : le gris sourd du site tient 4,39:1 sur ce fond, sous le
     seuil de 4,5:1, et c'est ici un CONTRÔLE, pas une légende. Même couleur que `.sx-btn`. */
  background: var(--control-bg); color: var(--text-light);
  border: 1px solid var(--border); border-radius: 999px;
  font-size: 13px; font-weight: 600; font-family: inherit; cursor: pointer;
  transition: border-color .15s, color .15s, background .15s;
}
/* Au survol, l'or va sur la BORDURE, pas sur le texte. `.sx-btn` dore les deux, mais l'or du
   thème clair (var(--accent)) sur ce fond ne tient que 2,55:1 — illisible au moment précis où on
   pointe le bouton. La bordure suffit à dire que ça réagit. */
.sx-more:hover { border-color: var(--accent); }
/* Le focus clavier arrive sur la CASE (invisible) : c'est le libellé qui doit le montrer. */
.sx-more-cb:focus-visible ~ .sx-more { outline: 2px solid var(--accent); outline-offset: 2px; }
.sx-more:active { transform: translateY(1px); }

/* Chevron dessiné en CSS plutôt qu'un emoji : il doit tourner, et suivre la couleur du texte. */
.sx-more-chev {
  width: 8px; height: 8px; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: translateY(-2px) rotate(45deg); transition: transform .2s;
}
.sx-more-cb:checked ~ .sx-more .sx-more-chev { transform: translateY(2px) rotate(225deg); }
.sx-more-less { display: none; }
.sx-more-cb:checked ~ .sx-more .sx-more-all { display: none; }
.sx-more-cb:checked ~ .sx-more .sx-more-less { display: inline; }

/* Nom de la catégorie : lu, jamais vu — « Voir plus de boutiques d'événement ». Les trois
   boutons diraient sinon « Voir plus » à l'identique, et rien ne dirait lequel déplie quoi.
   Découpe à 1px plutôt que `display:none`, qui le sortirait aussi de l'arbre d'accessibilité
   — c'est exactement ce qu'on ne veut pas ici (à l'inverse du libellé replié juste au-dessus,
   lui bel et bien à taire). */
.sx-more-cat {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  .sx-more, .sx-more-chev { transition: none; }
}

.sx-card {
  position: relative; display: flex; flex-direction: column; overflow: hidden;
  background: var(--bg-panel); border: 1px solid var(--border); border-top: 3px solid var(--accent);
  border-radius: 12px; text-decoration: none; color: var(--text-light);
  transition: transform .2s, box-shadow .2s, border-color .2s;
}
/* Signature maison : reflet doré qui balaie la carte au survol (cf. .hub-card). */
.sx-card::before {
  content: ""; position: absolute; inset: 0 auto 0 -100%; width: 100%; z-index: 2; pointer-events: none;
  background: linear-gradient(90deg, transparent, rgba(245,184,64,.08), transparent);
  transition: left .6s;
}
.sx-card:hover { transform: translateY(-5px); box-shadow: 0 6px 20px var(--shadow); }
.sx-card:hover::before { left: 100%; }
.sx-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Place RÉSERVÉE à la vignette, en attendant que le JS la remplace par la vraie.
   Sans elle, `.sx-thumb-slot` est un span vide de hauteur nulle : à l'arrivée des données,
   chaque carte gagnait d'un coup la hauteur d'une image et poussait toute la page vers le
   bas — un décalage de mise en page mesuré à 0,68 sur mobile, très au-dessus du 0,1 que
   Google considère comme bon. Même `aspect-ratio` que `.sx-thumb` : la place prise avant
   et après est exactement la même, donc plus rien ne bouge. */
.sx-thumb-slot { display: block; aspect-ratio: 16 / 9; border-bottom: 1px solid var(--border); }

/* ---------- vignette : photo si elle existe, sinon mosaïque des 4 meilleurs objets ---------- */
.sx-thumb {
  position: relative; display: block; aspect-ratio: 16 / 9; overflow: hidden;
  background: linear-gradient(135deg, var(--control-bg), var(--bg-panel));
  border-bottom: 1px solid var(--border);
}
.sx-mosaic { position: absolute; inset: 0; display: grid; grid-template-columns: 1fr 1fr; grid-auto-rows: 1fr; }
.sx-tile {
  background-size: 54%; background-repeat: no-repeat; background-position: center;
  background-color: color-mix(in srgb, var(--cat) 12%, transparent);
  box-shadow: inset 0 0 0 1px rgba(127,127,127,.10);
}
/* Les captures in-game portent le nom de la boutique et son décor en HAUT de l'image ; le bas
   n'est que la grille d'objets, que notre tableau détaille bien mieux. On cadre donc sur le haut
   plutôt qu'au centre, pour garder le titre visible quel que soit le format de la capture. */
.sx-photo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center top; z-index: 1; }

/* ---------- badges de statut sur la vignette ---------- */
.sx-badge {
  position: absolute; top: 8px; right: 8px; z-index: 3;
  font-size: 11px; font-weight: 700; padding: 3px 9px; border-radius: 9px;
  background: rgba(0,0,0,.72); color: #fff; border: 1px solid rgba(255,255,255,.18);
  backdrop-filter: blur(2px);
}
.sx-badge.live    { background: var(--success); color: #04211f; border-color: transparent; }
.sx-badge.urgent  { background: var(--warning); color: #241000; border-color: transparent; }
.sx-badge.ended   { background: var(--control-bg); color: var(--text-muted); border-color: var(--border); }
[data-theme="light"] .sx-badge.live { color: #fff; }

/* ---------- corps de la carte ---------- */
.sx-body { display: flex; flex-direction: column; gap: 5px; padding: 12px 14px 14px; }
.sx-name { font-size: 15px; font-weight: 700; line-height: 1.25; }
.sx-meta { font-size: 12px; color: var(--text-muted); display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.sx-meta .sx-dot { opacity: .5; }
.sx-cur { color: var(--accent); font-weight: 600; }

/* ---------- événement terminé : grisé mais toujours cliquable ---------- */
.sx-card.is-ended { border-top-color: var(--border); }
.sx-card.is-ended .sx-thumb { filter: grayscale(1); opacity: .55; }
.sx-card.is-ended .sx-name { color: var(--text-muted); }
.sx-card.is-ended:hover { border-color: var(--accent); }
.sx-card.is-ended:hover .sx-thumb { filter: grayscale(.4); opacity: .8; }

/* ---------- carte « référentiel des valeurs » ----------
   Ce n'est pas une boutique : format bandeau compact, hors grille, pour qu'elle se lise
   comme un accès transverse et non comme une quatrième famille. */
.sx-card.sx-ref { flex-direction: row; align-items: stretch; border-top-color: var(--success); }
.sx-card.sx-ref .sx-thumb {
  width: 92px; flex: 0 0 92px; aspect-ratio: auto; align-self: stretch;
  display: flex; align-items: center; justify-content: center;
  border-bottom: none; border-right: 1px solid var(--border);
  background: linear-gradient(135deg, color-mix(in srgb, var(--success) 16%, transparent), var(--bg-panel));
}
.sx-card.sx-ref .sx-body { justify-content: center; }
.sx-ref-glyph { font-size: 30px; line-height: 1; filter: drop-shadow(0 2px 6px rgba(0,0,0,.35)); }

/* ---------- vignette d'objet en tableau (reprise de l'ancien <style> de shop_calc.html) ---------- */
.sc-item-img {
  width: 34px; height: 34px; border-radius: 6px;
  background-size: contain; background-position: center; background-repeat: no-repeat;
  border: 1px solid var(--border);
}

/* ---------- barre d'outils (recherche + filtre + action) ----------
   Les .table-input/.table-select du site sont en width:100% : sans base flex explicite,
   chacun réclame toute la ligne et la barre se casse en trois étages. */
.shop-toolbar { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin: 18px 0 12px; }
.shop-toolbar > * { flex: 0 0 auto; width: auto; }
.shop-toolbar > input { flex: 1 1 220px; min-width: 180px; }
.shop-toolbar > select { flex: 0 1 200px; min-width: 160px; }

/* ============================================================
   PAGE BOUTIQUE
   ============================================================ */
.sx-hero { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; margin: 0 0 6px; }
.sx-hero-thumb {
  width: 132px; flex: 0 0 132px; aspect-ratio: 16 / 9; border-radius: 10px; overflow: hidden;
  border: 1px solid var(--border);
}
.sx-hero-thumb .sx-thumb { border-bottom: none; height: 100%; }
.sx-hero-text { min-width: 0; }
.sx-hero-text h1 { margin: 0 0 4px; }
.sx-facts { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; font-size: 13px; color: var(--text-muted); }
.sx-fact {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--control-bg); border: 1px solid var(--border);
  padding: 4px 10px; border-radius: 999px; white-space: nowrap;
}
.sx-fact b { color: var(--text-light); font-weight: 600; }
.sx-fact.live b   { color: var(--success); }
.sx-fact.urgent b { color: var(--warning); }
.sx-fact.ended    { opacity: .75; }

/* Bandeau d'archive des événements terminés */
.sx-archive {
  display: flex; gap: 10px; align-items: flex-start;
  margin: 16px 0 0; padding: 12px 14px; border-radius: 8px;
  background: var(--control-bg); border: 1px solid var(--border); border-left: 3px solid var(--text-muted);
  color: var(--text-muted); font-size: 13px; line-height: 1.5;
}

/* ============================================================
   TABLEAU DE BOUTIQUE — une ligne par objet
   S'appuie sur table.db-table (db.css) ; .sx-table ne pose que les spécificités.
   ============================================================ */
/* Les fiches BDD calent volontairement leurs tables sur le contenu
   (style.css : `.db-section table.db-table { width:auto }`). Une liste de boutique, elle,
   doit tenir la largeur : sinon une boutique à 6 colonnes laisse la moitié de la page vide.
   Le nom de l'objet absorbe l'espace restant, les colonnes chiffrées restent serrées. */
body.has-app-header .db-section table.sx-table { width: 100%; }
.sx-table td.c-name, .sx-table th:nth-child(2) { width: 100%; }
.sx-table th { white-space: nowrap; }
.sx-table th.srt { cursor: pointer; user-select: none; }
.sx-table th.srt:hover { color: var(--accent); }
.sx-table th.ctr, .sx-table td.ctr { text-align: center; }
.sx-table th.rgt, .sx-table td.rgt { text-align: right; }
.sx-table td.ctr, .sx-table td.rgt { font-variant-numeric: tabular-nums; }

/* Chaque ligne porte la couleur de catégorie de son objet en liseré + fond très léger. */
.sx-table tbody tr { border-left: 4px solid var(--cat); background: color-mix(in srgb, var(--cat) 7%, transparent); }
.sx-table tbody tr:hover { background: color-mix(in srgb, var(--cat) 14%, transparent); }
.sx-table td.c-img { width: 40px; padding-right: 0; }
.sx-ico {
  display: block; width: 30px; height: 30px; border-radius: 6px;
  background-size: contain; background-position: center; background-repeat: no-repeat;
  background-color: color-mix(in srgb, var(--cat) 18%, transparent);
}
.sx-table td.c-name { white-space: normal; min-width: 190px; font-weight: 600; line-height: 1.3; }
.sx-table td.gem { color: var(--success); font-weight: 600; }
.sx-table td.muted { color: var(--text-muted); }
.sx-table td.ok b { color: var(--success); }
.sx-rst { color: var(--success); }

/* Tables "Objets en €" et "Valeurs gemmes" (shop/items-euro.html, shop/items.html) : la couleur de catégorie reste un liseré +
   une pastille, jamais la couleur du texte (A11Y-16 : du texte coloré tombait à 1,5:1
   en thème clair). Le nom de catégorie garde la couleur de texte normale du thème. */
.ie-cat-row { border-left: 4px solid var(--cat); background: color-mix(in srgb, var(--cat) 8%, transparent); }
.ie-cat-row .sc-item-img { background-color: color-mix(in srgb, var(--cat) 20%, transparent); }
.ie-cat-label { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; font-size: 12px; color: var(--text-light); }
.ie-cat-label::before { content: ""; width: 9px; height: 9px; border-radius: 50%; background: var(--cat); flex: 0 0 auto; }

/* Meilleur ratio de la boutique */
.sx-table tbody tr.is-top { background: rgba(59,130,246,.14); box-shadow: inset 0 0 0 1px rgba(59,130,246,.35); border-left-color: #3B82F6; }
.sx-table tbody tr.is-top:hover { background: rgba(59,130,246,.20); }
.sx-table tr.is-top td.c-ratio b { color: #3B82F6; }
.sx-table tr.is-top .sx-bar > span { background: #3B82F6; }
.sx-tag {
  display: inline-block; margin-left: 6px; vertical-align: 1px;
  background: #3B82F6; color: #fff; font-size: 10px; font-weight: 700;
  padding: 1px 6px; border-radius: 8px; letter-spacing: .02em;
}

/* Ratio : valeur + barre de comparaison à la meilleure ligne */
.sx-table td.c-ratio { min-width: 118px; }
.sx-table td.c-ratio b { font-variant-numeric: tabular-nums; margin-right: 7px; }
.sx-table td.c-bar { width: 120px; }
.sx-bar {
  display: inline-block; vertical-align: middle; width: 62px; height: 6px;
  background: var(--control-bg); border-radius: 3px; overflow: hidden;
}
.sx-bar > span { display: block; height: 100%; background: var(--accent); }

/* Séparateur devant le bloc stock / panier */
.sx-table th.sep, .sx-table td.sep { border-left: 1px solid var(--border); }
/* Une ligne non retenue affiche « — » plutôt qu'un 0 : le tableau reste lisible et la
   sélection ressort seule (idée reprise de l'écran de référence). */
.sx-table td.dash, .sx-table .dash { color: var(--text-muted); opacity: .55; }
.sx-sub { display: block; font-size: 10px; color: var(--text-muted); line-height: 1.3; margin-top: 1px; }

/* ---------- pastille de palier ----------
   Certaines boutiques d'événement vendent le MÊME objet à plusieurs prix, repérés en jeu
   par la couleur de fond de la carte. On garde les trois teintes du jeu (or, améthyste,
   azur) pour que le joueur retrouve ses repères, mais le numéro est écrit dans la pastille :
   la couleur seule ne porte jamais l'information. Les valeurs du thème clair sont assombries
   pour tenir 4,5:1 sur fond pâle (les teintes du thème sombre y tombaient à 3,1:1). */
.sx-tier {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 1px 8px 1px 6px; border-radius: 999px;
  font-size: 11px; font-weight: 700; line-height: 1.6;
  font-variant-numeric: tabular-nums;
  color: var(--tier);
  background: color-mix(in srgb, var(--tier) 18%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--tier) 42%, transparent);
}
.sx-tier > i { width: 7px; height: 7px; border-radius: 50%; background: var(--tier); flex: none; }
.sx-tier.t1 { --tier: var(--accent); }   /* or       — le moins cher, s'épuise en premier */
.sx-tier.t2 { --tier: #b98cdd; }   /* améthyste */
.sx-tier.t3 { --tier: #5aa9e6; }   /* azur     — le plus cher */
[data-theme="light"] .sx-tier.t1 { --tier: #7d5600; }
[data-theme="light"] .sx-tier.t2 { --tier: #6b3499; }
[data-theme="light"] .sx-tier.t3 { --tier: #16548c; }
.sx-table td.c-tier { width: 1%; white-space: nowrap; }
/* Sur le podium la pastille suit le nom : elle dit à quel prix le ratio a été calculé. */
.sx-pod-name .sx-tier { margin-left: 6px; vertical-align: 1px; }

/* ---------- tuiles de bilan du panier ---------- */
.sx-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; margin: 16px 0 0; }
.sx-kpi {
  display: flex; flex-direction: column; gap: 2px;
  padding: 12px 14px; border-radius: 10px;
  background: var(--control-bg); border: 1px solid var(--border);
}
.sx-kpi-lbl { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); }
.sx-kpi-val { font-size: 22px; font-weight: 700; color: var(--text-light); font-variant-numeric: tabular-nums; line-height: 1.15; }
.sx-kpi-sub { font-size: 11px; color: var(--text-muted); }
.sx-kpi-hero { border-width: 2px; }
.sx-kpi.good { border-color: color-mix(in srgb, var(--success) 55%, transparent); }
.sx-kpi.good .sx-kpi-val { color: var(--success); }
.sx-kpi.bad { border-color: #e5484d; }
.sx-kpi.bad .sx-kpi-val, .sx-kpi.bad .sx-kpi-sub { color: #e5484d; }
.sx-kpi.gemtile .sx-kpi-val { color: var(--accent); font-size: 19px; }

/* ---------- colonne « Je prends » ---------- */
.sx-table th.c-take, .sx-table td.c-take { white-space: nowrap; width: 1%; }
.sx-take {
  display: inline-flex; align-items: stretch; vertical-align: middle;
  border: 1px solid var(--border); border-radius: 6px; overflow: hidden; background: var(--input-bg);
}
.sx-take.on { border-color: var(--accent); }
.sx-take button {
  width: 24px; border: none; background: var(--control-bg); color: var(--text-light);
  font-size: 14px; line-height: 1; cursor: pointer; padding: 0;
}
.sx-take button:hover:not(:disabled) { background: var(--accent); color: var(--on-accent); }
.sx-take button:disabled { opacity: .35; cursor: default; }
.sx-table .sx-take input[type="number"] {
  width: 44px; border: none; border-left: 1px solid var(--border); border-right: 1px solid var(--border);
  border-radius: 0; text-align: center; padding: 3px 2px; background: var(--input-bg);
}
.sx-table .sx-take input[type="number"]:focus { outline: none; background: var(--control-bg); }
.sx-maxbtn {
  margin-left: 5px; padding: 3px 7px; font-size: 10px; font-weight: 700; letter-spacing: .03em;
  background: transparent; color: var(--text-muted);
  border: 1px solid var(--border); border-radius: 5px; cursor: pointer; vertical-align: middle;
}
.sx-maxbtn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.sx-maxbtn:disabled { opacity: .3; cursor: default; }

/* Ligne retenue au panier */
.sx-table tbody tr.in-cart { background: color-mix(in srgb, var(--accent) 12%, transparent); }
.sx-table tbody tr.in-cart:hover { background: color-mix(in srgb, var(--accent) 18%, transparent); }
.sx-table tbody tr.in-cart td.c-name { font-weight: 700; }

/* Récapitulatif du panier — collé en bas de l'écran tant qu'on est sur le tableau, pour
   garder le solde sous les yeux pendant qu'on choisit. Hors du <table> à dessein : le sticky
   sur un <tfoot> n'est pas fiable, et une barre reste lisible même si le tableau déborde. */
.sx-cartbar {
  position: sticky; bottom: 0; z-index: 4;
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px;
  margin-top: -1px; padding: 11px 16px;
  background: var(--table-header); border: 1px solid var(--border); border-top: 2px solid var(--accent);
  border-radius: 0 0 8px 8px; box-shadow: 0 -4px 14px var(--shadow);
  font-size: 13px; color: var(--text-muted);
}
/* Contenu aligné à gauche : `.backup-fab` est en position:fixed à droite avec z-index 9000,
   il passera toujours devant. On lui laisse le champ libre plutôt que de rivaliser. */
.sx-cartbar > * { flex: 0 0 auto; }
.sx-cartbar-lbl { color: var(--accent); font-weight: 700; text-transform: uppercase; letter-spacing: .03em; font-size: 12px; }
.sx-cartbar-item { white-space: nowrap; font-variant-numeric: tabular-nums; }
.sx-cartbar-item b { color: var(--text-light); font-size: 14px; }
.sx-cartbar-item.gem b { color: var(--accent); }
.sx-cartbar-left {
  white-space: nowrap; padding: 3px 12px; border-radius: 999px;
  background: var(--control-bg); border: 1px solid color-mix(in srgb, var(--success) 45%, transparent);
}
.sx-cartbar-left b { color: var(--success); font-size: 14px; font-variant-numeric: tabular-nums; }
.sx-cartbar-left.bad { border-color: #e5484d; }
.sx-cartbar-left.bad b { color: #e5484d; }
@media (max-width: 560px) {
  .sx-cartbar { gap: 6px 12px; padding: 9px 12px; font-size: 12px; }
}
.sx-table tfoot tr.sx-total td.c-name { font-weight: 700; color: var(--accent); text-transform: uppercase; letter-spacing: .03em; font-size: 12px; }
.sx-table tfoot b { font-size: 14px; }

/* ============================================================
   CALCULATEUR DE RENTABILITÉ (.sr-)
   Le Hall of Heroes partage les composants de boutique (tables, steppers,
   pastilles), mais son parcours est une suite d'étapes. Ces règles posent ce
   rythme sans changer l'apparence des boutiques permanentes.
   ============================================================ */
.sr-section { margin-top: 18px; }
#sr-root > h2 { margin: 0 0 6px; }
.sr-intro, .sr-step-sub, .sr-note { max-width: 78ch; color: var(--text-muted); line-height: 1.55; }
.sr-intro { margin: 0 0 20px; }
.sr-step { margin: 22px 0; padding: 18px; background: var(--bg-panel); border: 1px solid var(--border); border-radius: 10px; }
.sr-step > h3 { margin: 0 0 4px; color: var(--text-light); font-size: 16px; }
.sr-step-sub { margin: 0 0 14px; font-size: 13px; }
.sr-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(175px, 1fr)); gap: 10px; }
.sr-field { display: flex; min-width: 0; min-height: 78px; flex-direction: column; justify-content: center; gap: 5px; padding: 10px 12px; background: var(--control-bg); border: 1px solid var(--border); border-radius: 8px; }
.sr-field.is-total { border-color: color-mix(in srgb, var(--accent) 55%, var(--border)); }
.sr-field-lbl { color: var(--text-muted); font-size: 12px; font-weight: 600; }
.sr-field-sub, .sx-sub { color: var(--text-muted); font-size: 11px; line-height: 1.35; }
.sr-field-row { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.sr-big { color: var(--accent); font-size: 20px; font-weight: 800; font-variant-numeric: tabular-nums; }
.sr-num { width: 100%; box-sizing: border-box; padding: 6px 8px; background: var(--input-bg); color: var(--text-light); border: 1px solid var(--border); border-radius: 5px; font: inherit; font-variant-numeric: tabular-nums; }
.sr-num:focus { outline: none; border-color: var(--accent); }
.sr-gemcost { color: var(--accent); font-size: 12px; white-space: nowrap; }
.sr-toolbar { margin: 14px 0 10px; }
.sr-toolbar .sx-fact { margin-right: auto; }
.sr-chips { display: flex; flex-wrap: wrap; gap: 4px; min-width: 220px; }
.sr-chip { display: inline-flex; align-items: center; gap: 3px; min-height: 23px; padding: 1px 5px; background: var(--control-bg); border: 1px solid var(--border); border-radius: 999px; font-size: 11px; }
.sr-chip.is-mark { color: var(--accent); }
.sr-chip-ico { width: 17px; height: 17px; flex: 0 0 17px; background-position: center; background-repeat: no-repeat; background-size: contain; }
.sr-mark-icon { display: inline-block; width: 1.15em; height: 1.15em; object-fit: contain; vertical-align: -.22em; }
.sr-chip-ico .sr-mark-icon { width: 17px; height: 17px; vertical-align: 0; }
.sr-packs, .sr-ladder { width: 100%; }
.sr-packs .c-pack { min-width: 100px; }
.sr-c-content { min-width: 230px; }
.sr-val { white-space: nowrap; }
.sr-use { display: flex; align-items: center; gap: 7px; cursor: pointer; }
.sr-use input { accent-color: var(--accent); }
.sr-shop tr.sr-off { opacity: .48; }
.sr-tier { display: inline-block; min-width: 38px; padding: 2px 6px; border-radius: 999px; text-align: center; font-weight: 800; font-variant-numeric: tabular-nums; }
.sr-t-bad { color: #e5484d; background: color-mix(in srgb, #e5484d 14%, transparent); }
.sr-t-warn { color: #b7791f; background: color-mix(in srgb, #d69e2e 16%, transparent); }
.sr-t-good { color: var(--success); background: color-mix(in srgb, var(--success) 14%, transparent); }
.sr-t-great { color: var(--accent); background: color-mix(in srgb, var(--accent) 16%, transparent); }
.sr-detail { margin: 18px 0; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.sr-detail > summary { padding: 11px 14px; cursor: pointer; color: var(--text-light); font-weight: 700; background: var(--control-bg); }
.sr-detail .table-container { border: 0; border-radius: 0; }
.sr-h4 { margin: 18px 0 8px; font-size: 14px; }
.sr-note { margin: 16px 0; font-size: 12px; }
.sr-bar { margin-top: 18px; }
.sr-goals { display: flex; flex-direction: column; gap: 10px; }
.sr-goal-row { display: grid; grid-template-columns: minmax(220px, 1fr) 150px auto; gap: 10px; align-items: stretch; }
.sr-goal-row .sr-field { min-height: 0; }
.sr-goal-remove { align-self: center; white-space: nowrap; }
@media (max-width: 560px) {
  .sr-step { margin: 16px -2px; padding: 13px; }
  .sr-fields { grid-template-columns: 1fr 1fr; }
  .sr-fields .sr-field:nth-child(3) { grid-column: span 2; }
  .sr-chips { min-width: 175px; }
  .sr-goal-row { grid-template-columns: 1fr auto; }
  .sr-goal-row .sr-field:first-child { grid-column: span 2; }
}

/* ---------- mode édition ---------- */
.sx-table input[type="number"] {
  width: 64px; padding: 3px 5px; text-align: right;
  background: var(--input-bg); color: var(--text-light);
  border: 1px solid var(--border); border-radius: 4px; font-size: 13px;
  font-variant-numeric: tabular-nums;
}
.sx-table td.ctr input[type="number"] { text-align: center; width: 58px; }
.sx-table input[type="number"]:focus { outline: none; border-color: var(--accent); }
/* La colonne de suppression reste collée au bord droit : sur un tableau large, une action
   qui part hors champ au scroll horizontal est une action perdue. */
.sx-table th.c-act, .sx-table td.c-act {
  width: 42px; text-align: center; padding-left: 4px; padding-right: 8px;
  position: sticky; right: 0; z-index: 1;
  background: var(--bg-panel); box-shadow: -1px 0 0 var(--border);
}
.sx-table thead th.c-act { z-index: 3; }
.sx-table tbody tr.is-top td.c-act { background: color-mix(in srgb, #3B82F6 16%, var(--bg-panel)); }
.sx-del {
  background: transparent; border: 1px solid var(--border); color: var(--text-muted);
  border-radius: 5px; padding: 2px 7px; cursor: pointer; font-size: 12px; line-height: 1.4;
}
.sx-del:hover { border-color: #e5484d; color: #e5484d; }
.table-container.is-editing { box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--accent) 45%, transparent); border-radius: 8px; }
/* En édition, les colonnes calculées passent en retrait : l'oeil doit aller aux champs. */
.table-container.is-editing .sx-table td.muted,
.table-container.is-editing .sx-table td.rgt:not(.gem) { opacity: .75; }

/* Barre d'action (monnaie + crayon) */
.sx-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 18px 0 0; }
.sx-cur-field { gap: 8px; }
.sx-cur-field input {
  width: 110px; padding: 3px 8px; text-align: right;
  background: var(--input-bg); color: var(--text-light);
  border: 1px solid var(--border); border-radius: 4px; font-size: 13px;
  font-variant-numeric: tabular-nums;
}
.sx-cur-field input:focus { outline: none; border-color: var(--accent); }
.sx-btn {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--control-bg); color: var(--text-light);
  border: 1px solid var(--border); border-radius: 999px;
  padding: 6px 14px; font-size: 13px; font-weight: 600; cursor: pointer;
  transition: border-color .15s, background .15s, color .15s;
}
.sx-btn:hover { border-color: var(--accent); color: var(--accent); }
.sx-btn.on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.sx-btn.on:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: var(--on-accent); }
.sx-btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.sx-btn.primary:hover { background: var(--accent-hover); color: var(--on-accent); }
.sx-edit-hint { flex: 1 1 240px; font-size: 12px; color: var(--text-muted); line-height: 1.45; }

/* Formulaire d'ajout (mode édition) */
.sx-add {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  margin-top: 10px; padding: 12px; border-radius: 8px;
  background: var(--control-bg); border: 1px dashed var(--border);
}
.sx-add input[type="text"], .sx-add input:not([type]), .sx-add input[type="number"] {
  background: var(--input-bg); color: var(--text-light);
  border: 1px solid var(--border); border-radius: 4px; padding: 5px 8px; font-size: 13px;
}
.sx-add .sx-add-item { flex: 1 1 200px; min-width: 160px; }
.sx-add .sx-add-item.bad { border-color: #e5484d; }
.sx-add input[type="number"] { width: 84px; text-align: right; font-variant-numeric: tabular-nums; }
.sx-add-daily-lbl { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; color: var(--text-muted); white-space: nowrap; }

/* Podium des meilleures affaires */
.sx-podium { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; }
.sx-pod {
  display: flex; align-items: center; gap: 12px; padding: 12px 14px;
  background: var(--control-bg); border: 1px solid var(--border); border-radius: 10px;
  border-left: 4px solid var(--cat);
}
.sx-pod-rank { font-size: 18px; font-weight: 800; color: var(--text-muted); min-width: 22px; }
.sx-pod:first-child .sx-pod-rank { color: var(--accent); }
.sx-pod-img { width: 44px; height: 44px; flex: 0 0 44px; background-size: contain; background-repeat: no-repeat; background-position: center; }
.sx-pod-txt { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.sx-pod-name { font-size: 13px; font-weight: 600; line-height: 1.25; }
.sx-pod-val { font-size: 12px; color: var(--text-muted); }
.sx-pod-val b { color: var(--accent); font-size: 14px; }

/* ---------- responsive ---------- */
@media (max-width: 560px) {
  .sx-grid { grid-template-columns: 1fr; }
  .sx-hero-thumb { width: 100px; flex-basis: 100px; }
}

/* Sous 820px le tableau défile horizontalement, l'objet reste visible : la colonne du nom
   est figée à gauche (l'icône, purement décorative, disparaît pour lui laisser la place). */
@media (max-width: 820px) {
  .sx-table td.c-img, .sx-table th.c-img { display: none; }
  .sx-table td.c-name, .sx-table th:nth-child(2) {
    position: sticky; left: 0; z-index: 1;
    background: var(--bg-panel); box-shadow: 1px 0 0 var(--border);
    min-width: 150px; max-width: 190px;
  }
  .sx-table tbody tr.is-top td.c-name { background: color-mix(in srgb, #3B82F6 16%, var(--bg-panel)); }
  .sx-table td.c-ratio { min-width: 92px; }
  .sx-bar { width: 40px; }
  .sx-edit-hint { flex-basis: 100%; }
}

/* Sur un écran étroit, la colonne figée mange déjà la moitié de la largeur : on rend la place
   en resserrant le nom et en abandonnant la barre du ratio, dont le chiffre dit la même chose. */
@media (max-width: 560px) {
  .sx-table td.c-name, .sx-table th:nth-child(2) { min-width: 128px; max-width: 148px; }
  .sx-table .sx-bar { display: none; }
  .sx-table td.c-ratio { min-width: 58px; }
  .sx-table td.c-ratio b { margin-right: 0; }
  .sx-table th, .sx-table td { padding-left: 8px; padding-right: 8px; }
}

/* ============================================================
   RACCOURCIS VERS LES RÉFÉRENTIELS (.sx-reflinks) — bas de page boutique
   Le joueur qui doute d'un chiffre du tableau trouve, juste au-dessus de la
   navigation entre boutiques, d'où ce chiffre vient. Les deux pastilles portent
   les couleurs des deux lectures de la page — turquoise pour les gemmes, or pour
   les euros — donc la destination se reconnaît avant même d'être lue.
   Le filet du bas de page est porté ici : la nav qui suit perd le sien
   (.sx-reflinks + .db-switch.footer), sinon deux traits se suivraient.
   ============================================================ */
.sx-reflinks { margin-top: 28px; border-top: 1px solid var(--border); padding-top: 18px; }
.sx-reflinks-lead { margin: 0 0 10px; color: var(--text-muted); font-size: 13px; }
.sx-reflinks-row { display: flex; flex-wrap: wrap; gap: 10px; }
.sx-reflink {
  display: inline-flex; align-items: center; gap: 9px;
  /* Le site ne pose pas box-sizing globalement : sans ce rappel, min-height s'ajoute
     aux 16 px de padding et la pastille monte à 60 px, deux fois la hauteur des
     pastilles de boutique juste en dessous. 44 px = la cible tactile minimale. */
  box-sizing: border-box; min-height: 44px; padding: 8px 16px 8px 8px;
  border: 1px solid var(--border); border-radius: 999px;
  background: var(--control-bg); color: var(--text-light);
  text-decoration: none; font-size: 13.5px; font-weight: 600;
  transition: border-color .15s, background .15s;
}
.sx-reflink-glyph {
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 24px; width: 24px; height: 24px; border-radius: 50%;
  font-size: 13px; line-height: 1;
  background: color-mix(in srgb, var(--success) 18%, transparent); color: var(--success);
}
.sx-reflink:hover { border-color: var(--success); background: color-mix(in srgb, var(--success) 10%, var(--control-bg)); }
.sx-reflink:focus-visible { outline: 2px solid var(--success); outline-offset: 2px; }
.sx-reflink.is-eur .sx-reflink-glyph { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); }
.sx-reflink.is-eur:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, var(--control-bg)); }
.sx-reflink.is-eur:focus-visible { outline-color: var(--accent); }
/* Un seul filet pour tout le bas de page : celui de .sx-reflinks. */
.sx-reflinks + .db-switch.footer { margin-top: 22px; border-top: none; padding-top: 0; }
/* Sur mobile les deux pastilles prennent la ligne entière : côte à côte, le libellé
   « Prix réel des objets » se casse en deux et la pastille perd sa forme. */
@media (max-width: 520px) {
  .sx-reflinks-row { flex-direction: column; align-items: stretch; }
  .sx-reflink { justify-content: flex-start; }
}

/* ============================================================
   VALORISATION EN EUROS — seconde lecture des boutiques
   Les deux lectures ne coexistent jamais à l'écran : la bascule SUBSTITUE
   les colonnes (Valeur gemmes -> Valeur €, Ratio -> Ratio), elle n'en ajoute
   aucune. Le tableau garde donc sa largeur et son comportement mobile.
   ============================================================ */

/* Bascule de lecture et sélecteur de devise : mêmes pastilles que la navigation
   entre boutiques (.db-switch-item), pour ne pas inventer un second vocabulaire. */
.sx-actions .db-switch { margin: 0; }
.sx-actions .sx-cur .db-switch-item { min-width: 34px; text-align: center; }
/* Le sélecteur de devise est un contrôle DISTINCT des onglets de lecture : sans filet,
   les quatre pastilles se lisent comme un seul groupe de quatre choix. */
.sx-actions .sx-cur { padding-left: 12px; border-left: 1px solid var(--border); }
/* Âge du serveur du joueur : un réglage, séparé des pastilles de lecture par le même filet. */
.sx-actions .sx-stage {
  display: inline-flex; align-items: center; gap: 7px; padding-left: 12px;
  border-left: 1px solid var(--border); color: var(--text-muted);
  font-size: 12px; font-weight: 700; white-space: nowrap;
}
.sx-actions .sx-stage select { width: auto; min-width: 130px; }
@media (max-width: 620px) {
  .sx-actions .sx-stage { flex: 1 1 100%; padding-left: 0; border-left: 0; }
}
/* La note de provenance prend sa propre ligne : c'est une mention, pas un contrôle. */
.sx-eurnote { flex: 1 1 100%; }

/* Valeur en euros : l'or de la charte, distinct du turquoise des gemmes —
   les deux lectures ne doivent jamais se confondre d'un coup d'oeil. */
.sx-table td.eur { color: var(--accent); font-weight: 600; }
.sx-kpi.eurtile .sx-kpi-val { color: var(--accent); font-size: 19px; }
.sx-cartbar-item.eur b { color: var(--accent); }

/* Bouton d'origine du prix, à côté de la valeur € (js/shop-page.js `spSrcBtn`).
   Remplace l'ancien `title` sur la <td>, invisible au clavier et au tactile. Cible tactile
   ≥ 24px sans élargir la colonne au-delà du nécessaire : le débordement de la zone cliquable
   se fait par la taille du bouton lui-même, l'icône qu'il porte reste petite.
   Centré sur le texte, avec des marges verticales négatives : sans elles, ses 24px
   agrandissaient la ligne et remontaient la valeur au-dessus du centre de la rangée. */
.sx-src {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; margin: -6px 0 -6px 2px; padding: 0; vertical-align: middle;
  color: var(--text-muted); background: none; border: 0; border-radius: 50%;
  cursor: pointer; transition: color .15s, background-color .15s;
}
.sx-src:hover, .sx-src:focus-visible { color: var(--accent); background: color-mix(in srgb, var(--accent) 16%, transparent); }
.sx-src:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* Un ratio en euros descend jusqu'à 6 décimales (Arène, Magasin des Marées) :
   la colonne doit tenir le chiffre entier sans rejeter la barre à la ligne. */
.sx-table.is-eur td.c-ratio { min-width: 148px; }
@media (max-width: 820px) { .sx-table.is-eur td.c-ratio { min-width: 116px; } }
/* Sous 560 px la barre est masquée : il ne reste que le chiffre, qui doit rester entier. */
@media (max-width: 560px) { .sx-table.is-eur td.c-ratio { min-width: 74px; } }

/* ---------- Prix réel des objets (shop/items-euro.html) ----------
   Cette page utilise .db-table (comme le référentiel gemmes) et n'hérite donc d'aucun
   style .sx-table : la couleur de la valeur est à redonner ici. */
table.db-table td.eur {
  color: var(--accent); font-weight: 600;
  text-align: right; font-variant-numeric: tabular-nums;
}
table.db-table td .dash { color: var(--text-muted); opacity: .55; font-style: italic; }
/* Les noms Gen 2 restent dans le cadre du tableau, avec retour à la ligne. */
table.db-table:has(#ie-tbody) { table-layout: fixed; width: 100%; }
table.db-table:has(#ie-tbody) th:nth-child(2) { width: 32%; }
table.db-table:has(#ie-tbody) th:nth-child(3) { width: 15%; }
table.db-table:has(#ie-tbody) th:nth-child(4) { width: 12%; }
table.db-table:has(#ie-tbody) :is(th, td) { white-space: normal; overflow-wrap: anywhere; }
#ie-tbody .ie-pack { min-width: 0; white-space: normal; text-align: left; }
@media (max-width: 1279px) {
  table.db-table:has(#ie-tbody) { min-width: 760px; }
}
/* Pastilles de devise dans la barre d'outils, au même niveau que la recherche et le filtre. */
.shop-toolbar .db-switch { margin: 0; }
.shop-toolbar .db-switch-item { min-width: 34px; text-align: center; }
.shop-toolbar .ie-stage-control {
  display: inline-flex; align-items: center; gap: 7px; color: var(--text-muted);
  font-size: 12px; font-weight: 700; white-space: nowrap;
}
.shop-toolbar .ie-stage-control select { min-width: 150px; }
@media (max-width: 620px) {
  .shop-toolbar .ie-stage-control { flex: 1 1 100%; justify-content: space-between; }
  .shop-toolbar .ie-stage-control select { flex: 1 1 auto; max-width: 220px; }
}
/* Nom du pack : déclencheur de l'aperçu. Le soulignement pointillé et l'icône disent
   qu'il y a quelque chose à voir — un nom nu ne s'annonce pas. */
.ie-pack { color: var(--text-light); }
button.ie-pack {
  font: inherit; color: var(--text-light); background: none; border: 0; padding: 0;
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  text-decoration: underline dotted var(--border); text-underline-offset: 3px;
  transition: color .15s;
}
button.ie-pack:hover, button.ie-pack:focus-visible { color: var(--accent); text-decoration-color: var(--accent); }
button.ie-pack:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }
button.ie-pack .ic-img { opacity: .5; flex: 0 0 auto; transition: opacity .15s; }
button.ie-pack:hover .ic-img, button.ie-pack:focus-visible .ic-img { opacity: 1; }

/* Aperçu : en `fixed` et attaché au <body>, il échappe au conteneur qui défile
   horizontalement — sinon il serait rogné dès que le tableau déborde. */
.ie-preview {
  position: fixed; z-index: 60; max-width: 300px; padding: 6px;
  background: var(--bg-panel); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 10px 30px var(--shadow);
  opacity: 0; transform: translateY(-4px); pointer-events: none;
  transition: opacity .16s ease, transform .16s ease;
}
.ie-preview.on { opacity: 1; transform: none; }
.ie-preview img { display: block; width: 100%; height: auto; border-radius: 6px; }
/* Image manquante : on garde la légende plutôt qu'une bulle vide. */
.ie-preview.is-broken img { display: none; }
.ie-preview-cap { display: block; margin-top: 6px; font-size: 11px; color: var(--text-muted); text-align: center; line-height: 1.35; }
@media (prefers-reduced-motion: reduce) { .ie-preview { transition: none; transform: none; } }
/* Carte d'accès au prix réel : l'or de la valorisation €, face au turquoise du référentiel gemmes. */
.sx-card.sx-ref-eur { border-top-color: var(--accent); }
.sx-card.sx-ref-eur .sx-thumb {
  background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 16%, transparent), var(--bg-panel));
  border-right-color: var(--border);
}
.sx-card.sx-ref-eur .sx-ref-glyph { color: var(--accent); }
/* « Multipack » n'est pas un nom de pack mais un état : plusieurs packs à égalité,
   donc aucune image à montrer. On le distingue visuellement des vrais noms ; son survol
   ouvre la bulle en mode liste, qui nomme les packs. */
.ie-pack.is-multi, button.ie-pack.is-multi { color: var(--text-muted); font-style: italic; }
button.ie-pack.is-multi:hover, button.ie-pack.is-multi:focus-visible { color: var(--accent); }
.ie-preview.is-list { padding: 8px 12px; max-width: min(340px, calc(100vw - 20px)); }
.ie-preview-title { display: block; font-size: 12px; color: var(--text-muted); margin-bottom: 4px; }
.ie-preview-list { margin: 0; padding-left: 18px; font-size: 13px; line-height: 1.45; color: var(--text-light); }

/* Bulle du bouton d'origine du prix (js/shop-page.js) : même boîte flottante que
   l'aperçu Multipack ci-dessus, en variante texte seul plutôt qu'image ou liste. */
.ie-preview.is-src {
  padding: 8px 12px; max-width: min(300px, calc(100vw - 20px));
  font-size: 13px; line-height: 1.5; color: var(--text-light); text-align: left;
}

/* Cellule « Pack d'origine » : le pack, puis les pastilles des règles qui ont décidé du prix.
   Elles s'enroulent plutôt que d'élargir la colonne — le tableau défile déjà sur mobile. */
.ie-src { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

/* Pastilles de règle. Elles disent que le chiffre affiché ne se déduit PAS du pack à côté :
   la nuance change la confiance qu'on accorde au prix, elle doit se voir d'un coup d'œil au
   milieu de 55 noms de packs. Une seule famille visuelle, trois poids selon ce que la règle
   fait : l'or pour celles qui REMPLACENT l'origine du prix (« Calculé » plein, puisque aucun
   pack ne le justifie ; « Barème » en contour, le pack existe mais ne fixe pas le prix), le
   gris pour « ×0,25 » qui ne fait que PONDÉRER un prix déjà établi. Inertes comme
   « Multipack » : seule une valeur calculée ou un barème permet de rejoindre sa ligne de
   détail sous le tableau. */
.ie-tag {
  display: inline-block; padding: 1px 8px; border-radius: 999px;
  font-size: 12px; font-weight: 600; white-space: nowrap; cursor: help;
  border: 1px solid transparent;
}
button.ie-rule-link {
  font: inherit; line-height: inherit; cursor: pointer; appearance: none; background: transparent;
  transition: background-color .15s, border-color .15s, box-shadow .15s;
}
button.ie-rule-link:hover { border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 16%, transparent); }
button.ie-rule-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ie-tag.is-derived {
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
}
.ie-tag.is-scaled {
  border-color: color-mix(in srgb, var(--accent) 38%, transparent);
  color: color-mix(in srgb, var(--accent) 88%, var(--text-light));
}
.ie-tag.is-weighted {
  border-color: var(--border); color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

/* Encadré des valeurs calculées, sous le tableau. PERMANENT et déplié : une valeur qu'aucun
   pack ne justifie doit pouvoir se vérifier sans interaction — l'info-bulle de la pastille
   n'existe pas au toucher. Liseré or à gauche, comme les autres blocs « à lire » du site. */
.ie-derived {
  margin: 18px 0 22px; padding: 14px 16px;
  border: 1px solid var(--border); border-left: 3px solid var(--accent);
  border-radius: 10px; background: var(--control-bg);
}
.ie-derived-h { margin: 0 0 6px; font-size: 15px; color: var(--accent); }
.ie-derived-intro { margin: 0 0 10px; font-size: 13px; color: var(--text-muted); line-height: 1.5; }
.ie-derived-list { margin: 0; padding-left: 18px; font-size: 13px; color: var(--text-light); line-height: 1.6; }
.ie-derived-list li + li { margin-top: 8px; }
.ie-rule-target { scroll-margin-top: var(--header-offset, 80px); border-radius: 5px; }
.ie-rule-target.is-target { animation: ie-rule-target 2.2s ease-out; }
@keyframes ie-rule-target {
  0%, 55% { background: color-mix(in srgb, var(--accent) 22%, transparent); box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 13%, transparent); }
  100% { background: transparent; box-shadow: none; }
}
@media (prefers-reduced-motion: reduce) { .ie-rule-target.is-target { animation: none; background: color-mix(in srgb, var(--accent) 16%, transparent); } }
/* Plusieurs règles = plusieurs sections dans le même encadré : un filet les sépare, sinon la
   liste de l'une se lit comme la suite de l'autre. */
.ie-derived-list + .ie-derived-h {
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border);
}
/* Le calcul chiffré passe à la ligne : collé au texte il se lisait comme sa fin de phrase. */
.ie-derived-sum {
  display: block; margin-top: 3px; color: var(--accent);
  font-weight: 600; font-variant-numeric: tabular-nums;
}

/* ============================================================
   VALORISATION D'ÉVÉNEMENT (.sxe-) — section « ce que l'événement m'a rapporté »
   Rendue par js/shop-event.js sur les seules boutiques qui ont un
   data/events/<slug>.json. Réutilise les tuiles .sx-kpi du panier : c'est le
   même geste de lecture (un chiffre, son libellé, sa réserve), on n'invente
   pas un second vocabulaire visuel.
   ============================================================ */

.sxe-section { margin-top: 30px; }
.sxe-kpis { margin-bottom: 4px; }
.sxe-kpis .sx-kpi-val small { font-size: 15px; font-weight: 600; margin-left: 1px; }

/* Crans de valorisation. La couleur ne porte JAMAIS l'information seule : le libellé
   sous le chiffre (« Mauvaise affaire » … « Excellent ») dit la même chose en toutes
   lettres, pour les daltonismes comme pour une capture en noir et blanc.
   Chaque teinte a sa variante claire : l'or et les verts vifs de la charte sombre
   tombent sous 4,5:1 sur le fond clair (#f0f4fa). */
/* Le rouge #e5484d du reste de la page ne tient que 4,2:1 sur le fond sombre : il passe
   pour le chiffre (22px gras = grand texte, 3:1 suffit) mais pas pour la réserve en 11px.
   D'où une teinte propre à ce bloc, éclaircie jusqu'à 4,9:1. */
.sxe-t-bad   { border-color: #ec5c60; }
.sxe-t-bad   .sx-kpi-val, .sxe-t-bad   .sx-kpi-sub { color: #ec5c60; }
.sxe-t-warn  { border-color: var(--warning); }
.sxe-t-warn  .sx-kpi-val, .sxe-t-warn  .sx-kpi-sub { color: var(--warning); }
.sxe-t-mid   { border-color: var(--border); }
.sxe-t-mid   .sx-kpi-val { color: var(--text-light); }
.sxe-t-good  { border-color: #8fd14f; }
.sxe-t-good  .sx-kpi-val, .sxe-t-good  .sx-kpi-sub { color: #8fd14f; }
.sxe-t-great { border-color: #34d17a; }
.sxe-t-great .sx-kpi-val, .sxe-t-great .sx-kpi-sub { color: #34d17a; }
.sxe-t-f2p   { border-color: var(--success); }
.sxe-t-f2p   .sx-kpi-val { color: var(--success); font-size: 19px; }
[data-theme="light"] .sxe-t-bad   { border-color: #c0272d; }
[data-theme="light"] .sxe-t-bad   .sx-kpi-val, [data-theme="light"] .sxe-t-bad .sx-kpi-sub { color: #c0272d; }
/* Même raison en thème clair pour l'orange : --warning (#e65100) n'y vaut que 3,4:1. */
[data-theme="light"] .sxe-t-warn  { border-color: #b23c00; }
[data-theme="light"] .sxe-t-warn  .sx-kpi-val, [data-theme="light"] .sxe-t-warn .sx-kpi-sub { color: #b23c00; }
[data-theme="light"] .sxe-t-good  { border-color: #4a7c14; }
[data-theme="light"] .sxe-t-good  .sx-kpi-val, [data-theme="light"] .sxe-t-good .sx-kpi-sub { color: #4a7c14; }
[data-theme="light"] .sxe-t-great { border-color: #0f7a3d; }
[data-theme="light"] .sxe-t-great .sx-kpi-val, [data-theme="light"] .sxe-t-great .sx-kpi-sub { color: #0f7a3d; }

/* Bouton « Utiliser comme budget » : dans la tuile, sous la réserve. Report EXPLICITE
   vers « Ma monnaie » du tableau — jamais automatique, une saisie du joueur ne
   s'écrase pas en silence. */
.sxe-budget { margin-top: 8px; align-self: flex-start; font-size: 11px; padding: 4px 9px; }
.sxe-budget.ok { border-color: color-mix(in srgb, var(--success) 55%, transparent); color: var(--success); }
.sxe-budget:disabled { cursor: default; opacity: .85; }

/* Panneau dépliable des achats : replié, la section tient en quatre tuiles. */
.sxe-panel, .sxe-detail {
  margin-top: 14px; border: 1px solid var(--border); border-radius: 10px;
  background: var(--bg-panel);
}
.sxe-panel > summary, .sxe-detail > summary {
  cursor: pointer; padding: 11px 14px; font-weight: 600; font-size: 14px;
  color: var(--accent); list-style: none; display: flex; align-items: center; gap: 8px;
}
.sxe-panel > summary::-webkit-details-marker, .sxe-detail > summary::-webkit-details-marker { display: none; }
.sxe-panel > summary::before, .sxe-detail > summary::before {
  content: '▸'; font-size: 11px; transition: transform .15s;
}
.sxe-panel[open] > summary::before, .sxe-detail[open] > summary::before { transform: rotate(90deg); }
.sxe-panel > summary:focus-visible, .sxe-detail > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: 10px; }
.sxe-detail { margin: 14px; background: var(--control-bg); }

.sxe-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 0 14px 12px; }
/* Une pastille d'outil ne doit jamais forcer la PAGE à défiler. `.sx-fact` porte
   `white-space: nowrap`, utile dans l'en-tête de boutique où les faits sont
   courts ; ici le plus long (« Amulettes Fantaisie dépensées » et son compteur)
   dépasse à lui seul la largeur d'un téléphone, et un élément flex ne rétrécit
   pas sous son contenu — d'où 52 px de débordement horizontal sur la page du
   Théâtre, 18 sur le Stand d'Aventure. On lève le `nowrap` dans la barre d'outils
   seulement : la pastille se replie au lieu de pousser la page.
   Sans effet sur grand écran, où elles tiennent déjà sur une ligne. */
.sxe-toolbar .sx-fact { white-space: normal; flex-wrap: wrap; max-width: 100%; }
.sxe-toolbar .sx-take input[type="text"] {
  width: 40px; text-align: center; border: none;
  border-left: 1px solid var(--border); border-right: 1px solid var(--border);
  background: var(--input-bg); color: var(--text-light); padding: 3px 2px;
  font-variant-numeric: tabular-nums;
}
/* Les amulettes se comptent en milliers : 40 px tronquerait la saisie. */
.sxe-toolbar .sx-take.sxe-explore input[type="text"] { width: 64px; }
.sxe-toolbar .sx-take input[type="text"]:focus { outline: none; background: var(--control-bg); }

/* Grille des achats : 1 ligne par pack, 1 colonne par jour. Elle défile
   horizontalement dans sa boîte (même parti que les tableaux BDD sur mobile),
   la colonne du pack restant figée — sans elle, on coche à l'aveugle. */
.sxe-gridbox { overflow-x: auto; margin: 0 14px 4px; border: 1px solid var(--border); border-radius: 8px; }
/* `margin: 0` n'est pas décoratif : `style.css` donne 20 px de marge basse à
   TOUTE table, ce qui creusait une bande vide sous la dernière ligne, à
   l'intérieur du cadre — on aurait juré une ligne blanche de trop. */
.sxe-grid { width: 100%; border-collapse: collapse; font-size: 13px; margin: 0; }
.sxe-grid th, .sxe-grid td { padding: 7px 10px; border-bottom: 1px solid var(--border); white-space: nowrap; }
.sxe-grid thead th { background: var(--table-header); font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); font-weight: 600; }
.sxe-grid tbody tr:hover { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.sxe-grid th.ctr, .sxe-grid td.ctr { text-align: center; }
.sxe-grid th.rgt, .sxe-grid td.rgt { text-align: right; font-variant-numeric: tabular-nums; }
.sxe-grid td.c-pack { white-space: normal; min-width: 165px; line-height: 1.25; }
.sxe-grid td.sxe-price { color: var(--text-muted); }
.sxe-grid td.c-tot { color: var(--accent); font-weight: 600; }
.sxe-grid .dash { color: var(--text-muted); opacity: .55; }
.sxe-grid tfoot .sxe-foot { background: var(--table-header); font-size: 12px; color: var(--text-muted); }
.sxe-grid tfoot .sxe-foot b { color: var(--accent); font-size: 14px; }
/* Colonne du pack figée pendant le défilement horizontal. */
.sxe-grid th.c-pack, .sxe-grid td.c-pack { position: sticky; left: 0; z-index: 1; background: var(--bg-panel); box-shadow: 1px 0 0 var(--border); }
.sxe-grid thead th.c-pack { z-index: 3; background: var(--table-header); }
.sxe-grid tbody tr:hover td.c-pack { background: color-mix(in srgb, var(--accent) 6%, var(--bg-panel)); }
/* Le fond opaque de la colonne figée est à même spécificité que la bande du pied et
   déclaré après : sans cette règle, la 1ʳᵉ cellule du pied trancherait sur le reste. */
.sxe-grid tfoot td.c-pack { background: var(--table-header); }

/* Cellule d'achat : compteur cyclique (0 → 1 → … → 0). L'état coché se lit au
   symbole (✓ ou ×N) autant qu'à la couleur. 44 px de haut sur mobile. */
.sxe-cell {
  width: 34px; height: 30px; padding: 0; cursor: pointer;
  background: var(--input-bg); color: var(--text-muted);
  border: 1px solid var(--border); border-radius: 6px;
  font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums;
  transition: background .12s, color .12s, border-color .12s;
}
.sxe-cell:hover { border-color: var(--accent); color: var(--accent); }
.sxe-cell.on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.sxe-cell:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sxe-info { color: var(--text-muted); cursor: help; font-size: 12px; }

.sxe-note { margin: 8px 14px 12px; font-size: 12px; color: var(--text-muted); line-height: 1.5; }
.sxe-detail > summary + .table-container { margin: 0 12px 12px; }
/* JAMAIS de `display:flex` sur un <td> ici. Chromium enveloppe alors la cellule dans
   une boîte anonyme : sa hauteur s'arrondit indépendamment de ses voisines, et sur les
   lignes dont le contenu tombe sur une hauteur fractionnaire (un nom qui passe à la
   ligne) la bordure collapsée se peint 1px plus haut que dans les autres colonnes —
   d'où une marche visible sous la ligne. L'icône s'aligne en inline-block ; la cellule
   reste une vraie cellule de tableau. Mesuré au pixel : 1px d'écart avant, 0 après. */
.sxe-rewards td.c-name { vertical-align: middle; }
/* Le flex vit sur un <span> INTÉRIEUR : icône et nom restent côte à côte (un nom sur
   deux lignes ne repasse pas sous l'icône) sans que le <td> quitte le modèle tableau. */
.sxe-rewards td.c-name .sxe-name { display: flex; align-items: center; gap: 8px; }
.sxe-rewards td.c-name .sx-ico { flex: 0 0 auto; }
/* Lignes « monnaie » et objets non valorisés : présents dans le détail, jamais chiffrés. */
.sxe-rewards tbody tr.sxe-cur-row { background: transparent; border-left-color: var(--border); }
.sxe-rewards tbody tr.sxe-cur-row td.c-name { color: var(--text-muted); font-weight: 600; }

@media (max-width: 560px) {
  .sxe-gridbox, .sxe-toolbar, .sxe-note { margin-left: 10px; margin-right: 10px; }
  .sxe-detail { margin: 10px; }
  /* Cible tactile : 44 px de haut, 8 px d'écart — un doigt ne vise pas 30 px. */
  .sxe-cell { height: 44px; width: 42px; }
  .sxe-grid th, .sxe-grid td { padding: 5px 7px; }
  .sxe-grid td.c-pack { min-width: 126px; max-width: 140px; font-size: 12px; }
}
@media (prefers-reduced-motion: reduce) {
  .sxe-cell, .sxe-panel > summary::before, .sxe-detail > summary::before { transition: none; }
}

/* Colonne « Provenance » du détail des gains : deux pastilles au plus, le reste replié
   dans un « +n » et le détail complet en info-bulle. Objectif explicite : expliquer une
   quantité sans transformer la ligne en paragraphe. */
/* PIÈGE : `.sx-table` élargit sa DEUXIÈME colonne à 100% — dans une boutique c'est le
   nom de l'objet (la 1re est l'image). Ici la 2e colonne est « Qté » : sans ce correctif
   elle absorbe toute la largeur, la colonne Provenance se retrouve à ~120px et ses
   pastilles s'empilent une par ligne, triplant la hauteur de chaque ligne. C'est donc à
   la Provenance de prendre la largeur restante. */
.sxe-rewards td.c-name, .sxe-rewards th:nth-child(1),
.sxe-rewards th:nth-child(2), .sxe-rewards td.ctr { width: 1%; }
.sxe-rewards th.c-src, .sxe-rewards td.sxe-src { width: 100%; }
.sxe-rewards th.c-src { white-space: nowrap; }
.sxe-rewards td.sxe-src { white-space: normal; line-height: 1.6; padding-top: 5px; padding-bottom: 5px; }
.sxe-chip {
  display: inline-block; margin: 1px 4px 1px 0; padding: 1px 7px;
  background: var(--control-bg); border: 1px solid var(--border); border-radius: 999px;
  font-size: 11px; color: var(--text-muted); white-space: nowrap;
}
.sxe-chip b { color: var(--text-light); font-weight: 600; font-variant-numeric: tabular-nums; }
/* Le « +n » ne se lit pas comme une source de plus : bordure tiretée, pas de chiffre gras. */
.sxe-chip.is-more { border-style: dashed; font-style: italic; }
.sxe-rewards td.sxe-src.dash { white-space: nowrap; }
@media (max-width: 820px) {
  .sxe-rewards td.sxe-src { max-width: 190px; }
  .sxe-chip { font-size: 10px; padding: 1px 5px; }
}

/* Cases à cocher du détail : chaque objet compte, sauf si le joueur le décoche — il
   sort alors du total ET de la valorisation. La ligne reste visible, grisée et barrée :
   on doit voir ce qu'on a écarté pour pouvoir le reprendre d'un clic. */
.sxe-rewards th.c-chk, .sxe-rewards td.c-chk { width: 30px; text-align: center; padding-left: 8px; padding-right: 2px; }
.sxe-rewards .sxe-chk { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; vertical-align: middle; }
.sxe-rewards tr.sxe-off td:not(.c-chk) { opacity: .45; }
.sxe-rewards tr.sxe-off td.gem, .sxe-rewards tr.sxe-off td.eur { text-decoration: line-through; }
/* Ligne de total, EN TÊTE du tableau : même bande que l'en-tête, chiffres pleins.
   Le soulignement doré est un box-shadow INTERNE plutôt qu'un border-bottom : peint
   dans la cellule, il ne participe pas à la résolution des bordures collapsées et
   reste rectiligne quoi qu'il arrive aux lignes voisines. */
.sxe-rewards tr.sxe-total-row td { background: var(--table-header); box-shadow: inset 0 -2px 0 var(--accent); }
.sxe-rewards tr.sxe-total-row td.c-name { font-weight: 700; color: var(--accent); text-transform: uppercase; letter-spacing: .03em; font-size: 12px; }
.sxe-rewards tr.sxe-total-row td.c-name .sx-sub { text-transform: none; letter-spacing: 0; font-weight: 400; }
.sxe-rewards tr.sxe-total-row td.gem, .sxe-rewards tr.sxe-total-row td.eur { font-size: 14px; font-weight: 700; }

/* Pack à stock d'événement : saisie libre par jour (pas de plafond journalier), d'où un
   champ plutôt que le compteur cyclique des packs quotidiens. */
.sxe-num {
  width: 40px; height: 30px; padding: 0 4px; text-align: center;
  background: var(--input-bg); color: var(--text-light);
  border: 1px solid var(--border); border-radius: 6px;
  font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.sxe-num:focus { outline: none; border-color: var(--accent); }
.sxe-num.on { border-color: var(--accent); color: var(--accent); }
.sxe-num::placeholder { color: var(--text-muted); opacity: .5; font-weight: 400; }
/* Case « mission validée » : une pastille de la barre d'outils, cliquable en entier. */
.sxe-chk-fact { cursor: pointer; gap: 7px; }
.sxe-chk-fact .sxe-chk { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; }
@media (max-width: 560px) { .sxe-num { height: 44px; width: 44px; } }

/* ==========================================================================
   MAGASIN DU THÉÂTRE (.stx-) — « ce que valent tes amulettes »
   Prolonge la section événement (js/shop-theater.js), branché par seExtras.
   Réutilise tout le vocabulaire visuel de .sxe- : seuls les éléments que la
   valorisation d'événement ne connaît pas ont leurs propres règles ici.
   ========================================================================== */
/* Dans `.sxe-panel`, chaque enfant porte SON retrait horizontal (14 px) : la
   grille, les notes, le détail des gains. Sans le même, titres, texte et
   bandeaux de ce bloc se collaient au bord du panneau pendant que ses tableaux,
   eux, étaient en retrait — deux alignements dans la même section.
   On le pose donc une fois sur le bloc, et on annule celui des éléments
   empruntés à la boutique, sinon il se cumulerait. */
.stx-root { margin: 22px 14px 0; padding-top: 18px; border-top: 1px solid var(--border); }
.stx-root .sxe-gridbox, .stx-root .sxe-note { margin-left: 0; margin-right: 0; }
.stx-root .sxe-toolbar { padding-left: 0; padding-right: 0; }
.stx-root h2 { font-size: 17px; margin: 0 0 4px; }
.stx-root h3 { font-size: 14px; margin: 22px 0 4px; color: var(--accent); }

/* Barème de jetons : replié par défaut, il ne se touche qu'une fois. */
.stx-toks { margin-top: 12px; }
.stx-tok-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 8px; padding: 12px 14px 0; }
.stx-tok { display: flex; align-items: center; justify-content: space-between; gap: 8px;
  font-size: 12px; color: var(--text-muted); }
.stx-tok input { width: 84px; min-height: 34px; padding: 4px 8px; text-align: right;
  background: var(--input-bg); border: 1px solid var(--border); color: var(--text-light);
  border-radius: 4px; font-family: inherit; font-size: 13px; font-variant-numeric: tabular-nums;
  outline: none; transition: border-color .2s; }
.stx-tok input:focus { border-color: var(--accent); }
/* Le dernier étage n'existe qu'en Forteresse : un filet le détache des autres. */
.stx-tok-fort { grid-column: 1 / -1; padding-top: 8px; border-top: 1px dashed var(--border); }

.stx-verdict { margin-top: 14px; padding: 12px 14px; background: var(--control-bg);
  border: 1px solid var(--border); border-left: 3px solid var(--accent); border-radius: 6px; }
.stx-verdict p { margin: 0 0 8px; font-size: 13.5px; color: var(--text-muted); line-height: 1.55; }
.stx-verdict p:last-child { margin-bottom: 0; }
.stx-verdict strong { color: var(--text-light); }
.stx-claim { color: var(--success) !important; }
.stx-push { color: var(--accent) !important; }

/* Jauge de probabilité : une piste de largeur fixe, remplie à hauteur de la
   chance, puis la valeur. L'ancienne version peignait une barre en fond de
   cellule pendant que le pourcentage restait centré : à 100 % la barre passait
   derrière le texte, à 30 % les deux ne se touchaient plus. */
.stx-odds { white-space: nowrap; }
.stx-meter {
  display: inline-block; width: 110px; height: 8px; vertical-align: middle;
  background: var(--control-bg); border: 1px solid var(--border);
  border-radius: 999px; overflow: hidden;
}
.stx-meter > span { display: block; height: 100%; background: var(--accent); border-radius: 999px; }
.stx-odds-v { display: inline-block; min-width: 46px; margin-left: 10px; text-align: right;
  font-variant-numeric: tabular-nums; }

/* La ligne « Meilleure ». Deux règles la contrariaient, et il faut les deux.
   1. `style.css` raye TOUTES les tables : `tbody tr:nth-child(even)` (0,1,2) bat un
      simple `.stx-best` (0,1,0). La consigne mise en avant tombant sur une ligne
      paire, la teinte ne s'affichait pas du tout. On qualifie donc comme le fait
      déjà le survol juste au-dessus — `.sxe-grid tbody tr…` (0,2,2) l'emporte.
   2. La 1re colonne est `position: sticky` avec un fond OPAQUE : aucun fond de
      ligne ne passe dessous, d'où une bande qui démarrait une colonne trop loin.
      Même parade que `tbody tr:hover td.c-pack`, à la même teinte. */
.sxe-grid tbody tr.stx-best { background: color-mix(in srgb, var(--success) 10%, transparent); }
.sxe-grid tbody tr.stx-best td.c-pack { background: color-mix(in srgb, var(--success) 10%, var(--bg-panel)); }
.sxe-grid tbody tr.stx-best:hover { background: color-mix(in srgb, var(--success) 16%, transparent); }
.sxe-grid tbody tr.stx-best:hover td.c-pack { background: color-mix(in srgb, var(--success) 16%, var(--bg-panel)); }
.stx-ratio { font-weight: 700; color: var(--accent); }
/* Le lot d'une exploration ratée est un GAIN au milieu d'un tableau de coûts :
   sans la couleur du succès, la colonne se lisait comme une dépense de plus. */
.stx-lot { color: var(--success); }
.stx-tag { display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: 20px;
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em;
  background: color-mix(in srgb, var(--success) 16%, transparent); color: var(--success); }

/* Rapprochement du budget : la seule ligne de la section qui se compare
   directement au jeu. Discrète tant que le compte tombe juste, franche sinon. */
.stx-recon { margin: 10px 0 0; font-size: 12.5px; color: var(--text-muted); line-height: 1.5; }
.stx-recon em { opacity: .85; }
.stx-recon-bad {
  padding: 10px 12px; border-radius: 6px; border-left: 3px solid var(--warning);
  background: color-mix(in srgb, var(--warning) 8%, transparent); color: var(--text-light);
}

/* Actions du Théâtre : « je viens de… ». Trois boutons qui reportent en une fois
   l'étage, le compteur de garantie et les amulettes dépensées.
   Le groupe reprend `.sx-take`, l'idiome des steppers voisins : même bordure,
   même rayon, même hauteur, segments accolés. Seule la largeur change — les
   boutons de `.sx-take` font 24 px, taillés pour un « − » ou un « + », pas pour
   un mot. Sans quoi le bloc ressemblait à un widget étranger posé dans la barre. */
.stx-acts button { width: auto; min-height: 21px; padding: 0 10px; font-size: 12px; white-space: nowrap; }
.stx-acts button + button { border-left: 1px solid var(--border); }
.stx-acts button:disabled { opacity: .35; cursor: default; }
.stx-acts button:disabled:hover { background: var(--control-bg); color: var(--text-light); }

/* Retrait mobile, à la même valeur que les éléments voisins de la section.
   Il vit ICI, après `.stx-root`, et pas dans la requête média plus haut : à
   spécificité égale (une classe de chaque côté, une requête média n'en ajoute
   pas), c'est l'ordre du fichier qui tranche — et le raccourci `margin` de
   `.stx-root` écrasait l'override en le suivant. Le bloc restait à 14 px pendant
   que ses propres tableaux passaient à 10. */
@media (max-width: 560px) {
  .stx-root { margin-left: 10px; margin-right: 10px; }
}

/* ---- Butin du Boucanier : coffres d'exploration, piste de points, pass ----
   Sections écrites en dur par tools/build_pages.py (bloc `exploration` / `drill` de
   data/shopcalc_recurring.json). Tableaux db-table sans défilement vertical propre
   (règle 10) ; seules les cellules de récompenses passent à la ligne. */
.bb-lead, .bb-note { color: var(--text-muted); font-size: 14px; line-height: 1.5; margin: 0 0 14px; }
.bb-note { margin-top: 12px; }
.bb-sub { font-size: 15px; margin: 18px 0 8px; color: var(--text-light); }
.bb-rate { color: var(--text-muted); font-weight: 400; }
.bb-ico { width: 28px; height: 28px; vertical-align: middle; margin-right: 6px; border-radius: 6px; }
.bb-lot .bb-ico { margin-right: 2px; }
body.has-app-header .db-section table.bb-table { width: 100%; }
.db-page table.bb-table th.num, .db-page table.bb-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.db-page table.bb-table thead th { white-space: normal; vertical-align: bottom; }
.db-page table.bb-table td { white-space: normal; }
.db-page table.bb-table tbody tr.bb-avg { background: color-mix(in srgb, var(--accent) 8%, transparent); font-weight: 600; }
.bb-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 0 18px; }
.bb-lot { display: inline-flex; align-items: center; gap: 4px; min-height: 28px; vertical-align: middle; white-space: nowrap; margin: 2px 14px 2px 0; }
.bb-x2 { margin-left: 4px; color: var(--accent); font-size: 12px; }
.bb-lots { font-size: 14px; line-height: 1.6; margin: 0 0 8px; }
/* Carte du Harbor Tome : prix, récompenses immédiates, gains doublés */
.bb-tome { background: var(--bg-panel); border: 1px solid var(--border); border-radius: 12px; padding: 14px 18px 16px; margin: 18px 0 14px; box-shadow: 0 1px 3px var(--shadow); }
.bb-tome-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; margin-bottom: 4px; }
.bb-tome-head .bb-sub { margin: 0 6px 0 0; }
.bb-badge { display: inline-flex; align-items: center; padding: 3px 10px; border-radius: 999px; font-size: 13px; font-weight: 600; border: 1px solid var(--border); color: var(--text-muted); white-space: nowrap; }
.bb-badge.bb-price { border-color: var(--accent); color: var(--accent); font-weight: 700; background: color-mix(in srgb, var(--accent) 8%, transparent); }
.bb-tome-cap { margin: 12px 0 8px; font-size: 12px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--text-muted); }
.bb-rewards { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 8px; }
.bb-reward { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 2px; padding: 10px 8px; border: 1px solid var(--border); border-radius: 10px; background: color-mix(in srgb, var(--text-muted) 5%, transparent); }
.bb-reward .bb-ico { width: 40px; height: 40px; margin: 0 0 4px; }
.bb-reward-q { font-size: 16px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--accent); line-height: 1.1; }
.bb-reward-n { font-size: 12px; line-height: 1.3; color: var(--text-muted); overflow-wrap: anywhere; }
.bb-chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.bb-chip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 12px 4px 4px; border: 1px solid var(--border); border-radius: 999px; font-size: 14px; }
.bb-chip.no-ico { padding-left: 12px; min-height: 34px; }
.bb-chip .bb-ico { width: 26px; height: 26px; margin: 0; }
.bb-chip .bb-x2 { margin-left: 2px; padding: 1px 6px; border-radius: 6px; background: var(--accent); color: var(--bg-panel); font-size: 11px; }
@media (max-width: 560px) {
  .bb-tome { padding: 12px 10px 14px; }
  .bb-rewards { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
  .bb-reward { padding: 8px 4px; }
  .bb-reward .bb-ico { width: 34px; height: 34px; }
  .bb-reward-q { font-size: 15px; }
  .bb-reward-n { font-size: 11px; }
}
.bb-unsure { color: var(--text-muted); font-size: 12px; font-style: italic; }

/* ---- Prime du Pirate : calculateur de dépense (js/buccaneer-planner.js) ---- */
   Deux cartes (situation, objectif) puis le résultat. Jetons du thème uniquement :
   les deux thèmes suivent sans règle propre. */
.bb-planner .bb-lead { max-width: 900px; }
.bb-card { background: var(--bg-panel); border: 1px solid var(--border); border-radius: 12px; padding: 16px 18px; margin: 0 0 14px; box-shadow: 0 1px 3px var(--shadow); }
.bb-card-h { font-size: 15px; margin: 0 0 12px; color: var(--text-light); }
.bb-card-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.bb-card-top .bb-card-h { margin: 0; }
.bb-card > .bb-hint { margin: 4px 0 10px; }
.bb-form { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 14px 20px; align-items: start; }
.bb-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.bb-lbl { display: flex; align-items: center; gap: 6px; font-weight: 600; font-size: 14px; color: var(--text-light); min-height: 28px; }
.bb-lbl .bb-ico { width: 24px; height: 24px; margin: 0; }
.bb-input { display: flex; align-items: stretch; border: 1px solid var(--border); border-radius: 8px; background: var(--input-bg); overflow: hidden; max-width: 260px; transition: border-color .15s, box-shadow .15s; }
.bb-input:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent); }
.bb-input input { flex: 1 1 auto; min-width: 0; width: 100%; border: 0; background: transparent; color: var(--text-light); font: inherit; font-size: 18px; font-weight: 700; font-variant-numeric: tabular-nums; padding: 8px 10px; outline: none; -moz-appearance: textfield; }
.bb-input input::-webkit-outer-spin-button, .bb-input input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.bb-unit { display: flex; align-items: center; padding: 0 10px; color: var(--text-muted); font-size: 13px; background: var(--control-bg); white-space: nowrap; }
.bb-input.is-stepper input { text-align: center; }
.bb-step { flex: 0 0 44px; border: 0; background: var(--control-bg); color: var(--text-light); font: inherit; font-size: 20px; font-weight: 700; cursor: pointer; }
.bb-step:hover:not(:disabled) { background: color-mix(in srgb, var(--accent) 16%, var(--control-bg)); color: var(--accent); }
.bb-step:disabled { opacity: .4; cursor: default; }
.bb-step:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.bb-hint { color: var(--text-muted); font-size: 12px; line-height: 1.45; margin: 0; }
.bb-switch { display: flex; align-items: center; gap: 12px; margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border); cursor: pointer; }
.bb-switch input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.bb-switch-ui { flex: 0 0 auto; width: 44px; height: 26px; border-radius: 999px; background: var(--control-bg); border: 1px solid var(--border); position: relative; transition: background .15s; }
.bb-switch-ui::after { content: ""; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 50%; background: var(--text-muted); transition: transform .15s, background .15s; }
.bb-switch input:checked + .bb-switch-ui { background: var(--accent); border-color: var(--accent); }
.bb-switch input:checked + .bb-switch-ui::after { transform: translateX(18px); background: var(--on-accent); }
.bb-switch input:focus-visible + .bb-switch-ui { outline: 2px solid var(--accent); outline-offset: 2px; }
.bb-switch-txt { display: flex; flex-direction: column; gap: 2px; font-size: 14px; }
.bb-reset { font: inherit; font-size: 12px; padding: 6px 12px; border: 1px solid var(--border); border-radius: 999px; background: transparent; color: var(--accent); cursor: pointer; min-height: 32px; }
.bb-reset:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.db-page table.bb-goal .bb-lot { white-space: normal; }
.db-page table.bb-goal tbody tr.is-on { background: color-mix(in srgb, var(--accent) 10%, transparent); }
.db-page table.bb-goal tbody tr.is-on td:first-child { box-shadow: inset 3px 0 0 var(--accent); }
.bb-goal input.bb-qty { width: 90px; font: inherit; font-weight: 700; text-align: right; padding: 6px 8px; border: 1px solid var(--border); border-radius: 6px; background: var(--input-bg); color: var(--text-light); }
.bb-goal input.bb-qty:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.bb-goal tfoot td { font-weight: 700; border-bottom: 0; }
.bb-goal-sum .bb-ico { width: 22px; height: 22px; }
.bb-result { margin-top: 4px; }
.bb-empty { color: var(--text-muted); font-style: italic; padding: 12px 0; }
.bb-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin-bottom: 14px; }
.bb-tile { position: relative; border: 1px solid var(--border); border-radius: 12px; padding: 12px 14px; background: var(--bg-panel); display: flex; flex-direction: column; gap: 2px; min-height: 64px; justify-content: center; }
.bb-tile.has-ico { padding-left: 52px; }
.bb-tile .bb-ico { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); width: 30px; height: 30px; margin: 0; }
.bb-tile-v { font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--accent); line-height: 1.1; }
.bb-tile-l { font-size: 12px; color: var(--text-muted); }
.bb-reco { border: 1px solid var(--accent); border-left-width: 5px; border-radius: 12px; padding: 14px 18px; margin-bottom: 8px; background: color-mix(in srgb, var(--accent) 6%, var(--bg-panel)); }
.bb-reco.is-ko { border-color: var(--warning); }
.bb-reco-h { margin: 0 0 8px; font-weight: 700; font-size: 15px; color: var(--accent); }
.bb-reco p { margin: 6px 0 0; }
.bb-plan { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.bb-plan li { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; padding: 8px 12px; border-radius: 8px; background: var(--bg-panel); border: 1px solid var(--border); }
.bb-plan .bb-day { font-weight: 700; }
.bb-plan li.bb-step-tome { border-color: var(--accent); }
.bb-plan .bb-day-tot { margin-left: auto; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--accent); white-space: nowrap; }
.bb-reco p.bb-balance { margin-top: 10px; font-size: 14px; }
.bb-reco-sum { display: flex; flex-wrap: wrap; gap: 6px 24px; margin-top: 12px; padding-top: 10px; border-top: 1px dashed var(--border); font-size: 14px; }
.bb-reco-sum b { font-size: 17px; color: var(--accent); margin-left: 4px; }
.db-page table.bb-table th.is-best, .db-page table.bb-table td.is-best { background: color-mix(in srgb, var(--accent) 8%, transparent); }
@media (max-width: 560px) {
  .bb-input { max-width: none; }
  .db-page table.bb-goal th, .db-page table.bb-goal td { padding-left: 5px; padding-right: 5px; }
  .bb-goal input.bb-qty { width: 50px; padding-left: 4px; padding-right: 4px; }
  .db-page table.bb-goal { font-size: 13px; }
  .db-page table.bb-goal .bb-lot { overflow-wrap: anywhere; }
  .bb-goal .bb-lot .bb-ico { width: 22px; height: 22px; margin-right: 2px; }
  .bb-card { padding: 12px 10px; }
  /* Le maximum reste porté par le champ (attribut max) : la colonne cède la place au nom. */
  .db-page table.bb-goal .c-max { display: none; }
}

/* ---- Consortium Impérial (shop/imperial-consortium.html, js/imperial-consortium.js) ----
   Chiffres clés en tuiles, cartes de palier à la couleur du cadre en jeu (bleu, violet, or),
   tuiles d'objets reprises du Harbor Tome (.bb-rewards). Les teintes de cadre ne servent
   qu'au liseré : le texte reste sur les jetons du thème, lisible en clair comme en sombre. */
.ic-hero-img { display: block; width: 100%; height: 100%; object-fit: cover; }
.ic-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 10px; margin: 0 0 6px; }
.ic-stat { display: flex; flex-direction: column; gap: 2px; padding: 12px 14px; background: var(--bg-panel); border: 1px solid var(--border); border-radius: 10px; box-shadow: 0 1px 3px var(--shadow); }
.ic-stat strong { font-size: 20px; line-height: 1.2; color: var(--accent); font-variant-numeric: tabular-nums; }
.ic-stat > span, .ic-stat > strong + span { font-size: 13px; color: var(--text-muted); line-height: 1.35; }
.ic-stats-tight { margin: 4px 0 0; }
.db-page table.ic-table tbody tr.ic-best { background: color-mix(in srgb, var(--success) 12%, transparent); }
.db-page table.ic-table tbody tr.ic-best b { color: var(--success); }
.ic-stop .ic-stop-field { display: inline-flex; align-items: center; gap: 10px; font-weight: 600; margin: 0 0 10px; flex-wrap: wrap; }
.ic-stop select { width: auto; min-width: 80px; }
.ic-tiers { display: grid; gap: 16px; }
.ic-tier { --ic-frame: #3f6fa8; background: var(--bg-panel); border: 1px solid var(--border); border-left: 6px solid var(--ic-frame); border-radius: 12px; padding: 12px 16px 14px; box-shadow: 0 1px 3px var(--shadow); }
.ic-tier.ic-frame-purple { --ic-frame: #7d55b0; }
.ic-tier.ic-frame-gold { --ic-frame: #c08a1e; }
.ic-tier-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; margin: 0 0 8px; }
.ic-tier-head .bb-sub { margin: 0 6px 0 0; }
.ic-blocks { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr); gap: 12px; }
.ic-block { min-width: 0; }
.ic-block-h { margin: 0 0 6px; font-size: 12px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--text-muted); }
.ic-paid .ic-block-h { color: var(--accent); }
.ic-rewards { grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); }
.ic-worth { margin: 6px 0 0; font-size: 12px; color: var(--text-muted); }
.ic-tile-val { margin-top: 3px; padding-top: 3px; border-top: 1px solid var(--border); width: 100%; font-size: 12px; font-weight: 600; color: var(--text-light); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.ic-tier-val { margin: 12px 0 0; padding-top: 10px; border-top: 1px dashed var(--border); font-size: 14px; color: var(--text-muted); }
.ic-tier-val b { color: var(--text-light); }
.ic-rules { margin: 0; padding-left: 20px; color: var(--text-muted); font-size: 14px; line-height: 1.55; }
.ic-rules li + li { margin-top: 6px; }
@media (max-width: 900px) {
  .ic-blocks { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .ic-paid { grid-column: 1 / -1; }
}
@media (max-width: 560px) {
  .ic-tier { padding: 10px 10px 12px; }
  .ic-blocks { grid-template-columns: minmax(0, 1fr); }
  .ic-rewards { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .ic-stat strong { font-size: 18px; }
}
