/* Boutique — page membre.

   Volontairement séparée du panel : ce n'est pas le même public, et le staff ne
   doit pas hériter d'un style pensé pour une vitrine (ni l'inverse).

   Le parti pris est le **verre** : des surfaces translucides posées sur un fond
   coloré vivant, avec un liseré clair en haut de chaque plaque et une ombre
   portée sous elle. Ce n'est pas de la décoration gratuite — c'est ce qui donne
   une profondeur : les cartes flottent au-dessus du fond au lieu d'être des
   rectangles peints dessus, et l'œil comprend tout de suite ce qui est
   au-dessus de quoi.

   Trois règles tiennent tout le fichier :
   - le flou n'est jamais seul. Une plaque de verre, c'est un flou **plus** un
     liseré clair au-dessus **plus** une ombre en dessous. Sans les deux
     derniers, on n'obtient qu'une tache floue ;
   - le contenu ne baigne jamais dans le verre. Les visuels de produit sont
     posés sur un fond sombre franc, sinon le fond coloré transparaît dedans et
     fausse les couleurs de ce qu'on achète ;
   - la couleur vient du produit. Le fond et les plaques sont neutres ; ce sont
     la rareté d'un skin et le genre d'un article qui apportent la teinte. */

:root {
  --fond: #07080c;
  --texte: #f2f4f9;
  --doux: #99a0b2;
  --tres-doux: #6d7488;
  --accent: #6470ff;
  --accent-clair: #99a2ff;
  --promo: #4ade80;

  /* Verre : la plaque, son liseré, son ombre. Les trois vont ensemble. */
  --verre: linear-gradient(158deg, rgba(255, 255, 255, 0.075), rgba(255, 255, 255, 0.028));
  --verre-fort: linear-gradient(158deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.05));
  --verre-survol: linear-gradient(158deg, rgba(255, 255, 255, 0.13), rgba(255, 255, 255, 0.05));
  --bord: rgba(255, 255, 255, 0.09);
  --bord-vif: rgba(255, 255, 255, 0.2);
  --liseré: inset 0 1px 0 rgba(255, 255, 255, 0.16);
  --ombre: 0 18px 40px -24px rgba(0, 0, 0, 0.9);
  --ombre-haute: 0 30px 60px -28px rgba(0, 0, 0, 0.95);
  --flou: saturate(150%) blur(20px);

  /* Fond des visuels : franc et sombre, pour ne pas teinter les produits. */
  --scene: #0a0b11;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--fond);
  color: var(--texte);
  font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
}

/* Aurore : trois taches de couleur très floues, fixes derrière la page. C'est
   elle qui donne au verre quelque chose à filtrer — sur un fond uni, une
   plaque translucide est indiscernable d'une plaque opaque. */
body::before {
  content: '';
  position: fixed;
  inset: -25vh -10vw;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(46vw 46vw at 10% 2%, rgba(100, 112, 255, 0.42), transparent 62%),
    radial-gradient(40vw 40vw at 92% 10%, rgba(190, 80, 255, 0.3), transparent 64%),
    radial-gradient(50vw 50vw at 58% 78%, rgba(0, 175, 205, 0.24), transparent 66%),
    radial-gradient(34vw 34vw at 30% 48%, rgba(255, 120, 180, 0.14), transparent 68%);
  filter: blur(30px);
}

/* Grain très léger : sans lui, les grands aplats de dégradé montrent des
   bandes de couleur sur les écrans 8 bits. */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.5;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='b'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23b)' opacity='.035'/%3E%3C/svg%3E");
}

/* Emoji de serveur : une image, alignée sur le texte qui l'accompagne. */
.emoji { width: 1.15em; height: 1.15em; vertical-align: -0.2em; }

/* --- Chargement --------------------------------------------------------
   Des plaques vides à la bonne forme plutôt qu'un mot. On voit tout de suite
   que la page est une grille de produits, et l'arrivée des vraies cartes ne
   fait pas sauter la mise en page. */

.chargement {
  max-width: 1240px;
  margin: 0 auto;
  padding: 96px 28px 60px;
  display: grid;
  gap: 18px;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
.chargement i {
  display: block;
  height: 250px;
  border-radius: 18px;
  background: var(--verre);
  border: 1px solid var(--bord);
  box-shadow: var(--liseré);
  animation: respire 1.6s ease-in-out infinite;
}
.chargement i:nth-child(2) { animation-delay: 0.15s; }
.chargement i:nth-child(3) { animation-delay: 0.3s; }
.chargement i:nth-child(4) { animation-delay: 0.45s; }
@keyframes respire { 0%, 100% { opacity: 0.45; } 50% { opacity: 0.9; } }

/* --- En-tête ------------------------------------------------------------ */

.entete {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 28px;
  position: sticky;
  top: 0;
  z-index: 5;
  background: linear-gradient(180deg, rgba(10, 11, 17, 0.82), rgba(10, 11, 17, 0.55));
  border-bottom: 1px solid var(--bord);
  box-shadow: var(--liseré), 0 12px 30px -26px #000;
  backdrop-filter: var(--flou);
  -webkit-backdrop-filter: var(--flou);
}
.entete .avatar {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: 1px solid var(--bord-vif);
  box-shadow: 0 0 0 3px rgba(100, 112, 255, 0.16);
}
.entete .qui { display: flex; flex-direction: column; line-height: 1.35; font-weight: 700; }
.entete .qui span { color: var(--doux); font-size: 13px; font-weight: 500; }
.entete .soldes { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }

.pastille {
  background: var(--verre);
  border: 1px solid var(--bord);
  box-shadow: var(--liseré);
  border-radius: 999px;
  padding: 8px 15px;
  font-weight: 700;
  font-size: 14px;
  white-space: nowrap;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.pastille.promo {
  color: var(--promo);
  border-color: rgba(74, 222, 128, 0.32);
  background: linear-gradient(158deg, rgba(74, 222, 128, 0.16), rgba(74, 222, 128, 0.05));
}

/* --- Sections ----------------------------------------------------------- */

main { max-width: 1240px; margin: 0 auto; padding: 34px 28px 72px; }

.titre { margin-bottom: 22px; }
.titre.second { margin-top: 58px; }
.titre h1 {
  margin: 0 0 8px;
  font-size: 27px;
  letter-spacing: -0.015em;
  /* Le titre s'éteint vers le bas : il pèse moins lourd que les produits, qui
     sont ce qu'on est venu voir. */
  background: linear-gradient(180deg, #ffffff, #b9c0d6);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.titre p { margin: 0; color: var(--doux); line-height: 1.65; max-width: 660px; font-size: 14.5px; }
.titre code {
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid var(--bord);
  border-radius: 6px;
  padding: 1px 6px;
  font-size: 0.92em;
}

.grille {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 18px;
}

/* --- Carte produit ------------------------------------------------------ */

.carte {
  position: relative;
  background: var(--verre);
  border: 1px solid var(--bord);
  box-shadow: var(--liseré), var(--ombre);
  border-radius: 18px;
  padding: 0;
  overflow: hidden;
  cursor: pointer;
  color: inherit;
  font: inherit;
  text-align: left;
  display: flex;
  flex-direction: column;
  backdrop-filter: var(--flou);
  -webkit-backdrop-filter: var(--flou);
  transition: transform 0.22s cubic-bezier(0.2, 0.7, 0.3, 1), box-shadow 0.22s, border-color 0.22s, background 0.22s;
}

/* Reflet spéculaire qui suit le pointeur. `--x`/`--y` sont posées en JavaScript
   au survol ; sans pointeur (tactile, clavier) la carte reste simplement mate,
   rien ne dépend de cet effet. */
.carte::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.25s;
  background: radial-gradient(220px 220px at var(--x, 50%) var(--y, 0%), rgba(255, 255, 255, 0.14), transparent 70%);
}
.carte:hover {
  background: var(--verre-survol);
  border-color: var(--bord-vif);
  transform: translateY(-4px);
  box-shadow: var(--liseré), var(--ombre-haute);
}
.carte:hover::after { opacity: 1; }
.carte:focus-visible { outline: 2px solid var(--accent-clair); outline-offset: 3px; }

/* Filet de rareté en haut de carte. Il tient dans deux pixels, et c'est
   pourtant lui qui fait qu'on repère un mythique en balayant la grille du
   regard : la couleur arrive avant qu'on ait lu l'étiquette. */
.carte[style*='--rarete']::before {
  content: '';
  position: absolute;
  top: 0;
  left: 12%;
  right: 12%;
  height: 2px;
  z-index: 1;
  border-radius: 0 0 3px 3px;
  background: linear-gradient(90deg, transparent, var(--rarete), transparent);
  opacity: 0.85;
}
.carte[style*='--rarete']:hover { border-color: color-mix(in srgb, var(--rarete) 45%, transparent); }

/* Skin porté : une bordure teintée et une lueur, pour le retrouver d'un coup
   d'œil dans une grille de douze. */
.carte.porte {
  border-color: rgba(100, 112, 255, 0.55);
  box-shadow: var(--liseré), var(--ombre), 0 0 0 1px rgba(100, 112, 255, 0.25), 0 0 34px -14px rgba(100, 112, 255, 0.8);
}

/* Le visuel est posé sur un fond sombre **opaque** : le fond coloré de la page
   transparaîtrait sinon dans l'image du produit et en fausserait les couleurs. */
.visuel {
  position: relative;
  background: var(--scene);
  padding: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 16 / 11;
  border-bottom: 1px solid var(--bord);
}
.visuel img { width: 100%; height: 100%; object-fit: contain; border-radius: 9px; display: block; }
/* Illustration déposée par le staff : même cadre que les vignettes de skin,
   pour que les deux sections s'alignent. `contain` plutôt que `cover` — une
   image rognée couperait le texte que le staff a mis dessus. */
.visuel.photo { aspect-ratio: 16 / 11; padding: 0; }
.visuel.photo img { border-radius: 0; }

.etiq {
  position: absolute;
  top: 11px;
  right: 11px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 5px 10px;
  border-radius: 999px;
  border: 1px solid transparent;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.etiq.possede { background: rgba(59, 165, 93, 0.26); color: #7ff0ae; border-color: rgba(59, 165, 93, 0.4); }
.etiq.porte { background: rgba(100, 112, 255, 0.3); color: #c3c9ff; border-color: rgba(100, 112, 255, 0.5); }

/* Article du serveur sans illustration : le genre tient la place du visuel.
   Inventer une vignette ferait croire à un aperçu de ce qu'on achète. */
.visuel.genre {
  aspect-ratio: 16 / 11;
  font-size: 15px;
  font-weight: 700;
  text-align: center;
  padding: 18px;
  flex-direction: column;
  gap: 4px;
}
/* Un rôle et un objet ne s'achètent pas pour les mêmes raisons : la couleur les
   sépare d'un coup d'œil, sans avoir à lire l'étiquette. */
.visuel.genre.role {
  color: #d2d7ff;
  background:
    radial-gradient(120% 100% at 50% 0%, rgba(120, 132, 255, 0.55), transparent 68%),
    linear-gradient(180deg, #1b1e3d, #10111d);
  box-shadow: inset 0 -1px 0 rgba(120, 132, 255, 0.32);
}
.visuel.genre.objet {
  color: #ffe4b3;
  background:
    radial-gradient(120% 100% at 50% 0%, rgba(240, 178, 74, 0.45), transparent 68%),
    linear-gradient(180deg, #2c2317, #17130f);
  box-shadow: inset 0 -1px 0 rgba(240, 178, 74, 0.3);
}

.infos { padding: 13px 15px 15px; display: flex; flex-direction: column; gap: 5px; flex: 1; }
.infos .prix { margin-top: auto; padding-top: 6px; }
.rarete { font-size: 10.5px; font-weight: 800; letter-spacing: 0.09em; text-transform: uppercase; }
.nom { font-weight: 700; font-size: 15.5px; letter-spacing: -0.01em; }
.carte.article .desc {
  color: var(--doux);
  font-size: 12.5px;
  line-height: 1.45;
  /* Deux lignes au plus : au-delà, les cartes de la grille n'ont plus la même
     hauteur et l'alignement des prix se perd. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.prix { display: inline-flex; align-items: center; gap: 6px; font-weight: 800; font-size: 15.5px; }
.prix.gros { font-size: 21px; }
.prix.offert { color: var(--promo); font-weight: 700; }
.prix s { color: var(--tres-doux); font-weight: 400; }
.prix .promo {
  color: var(--promo);
  font-style: normal;
  font-size: 0.76em;
  font-weight: 800;
  background: rgba(74, 222, 128, 0.14);
  border: 1px solid rgba(74, 222, 128, 0.3);
  border-radius: 999px;
  padding: 2px 7px;
}

/* --- Fenêtre de détail -------------------------------------------------- */

.fenetre { position: fixed; inset: 0; z-index: 30; display: flex; align-items: center; justify-content: center; padding: 20px; }
/* `display: flex` l'emporte sur l'attribut `hidden` : sans cette règle, la
   fenêtre fermée reste étendue sur tout l'écran et avale les clics de la
   grille — invisible, mais posée par-dessus tout. */
.fenetre[hidden] { display: none; }
.voile {
  position: absolute;
  inset: 0;
  background: rgba(4, 5, 9, 0.62);
  backdrop-filter: blur(14px) saturate(120%);
  -webkit-backdrop-filter: blur(14px) saturate(120%);
  animation: apparait 0.2s ease-out;
}

.panneau {
  position: relative;
  background: var(--verre-fort);
  border: 1px solid var(--bord-vif);
  box-shadow: var(--liseré), 0 40px 80px -30px rgba(0, 0, 0, 0.95);
  border-radius: 22px;
  padding: 26px;
  width: min(680px, 100%);
  max-height: calc(100vh - 40px);
  overflow: auto;
  backdrop-filter: var(--flou);
  -webkit-backdrop-filter: var(--flou);
  animation: monte 0.26s cubic-bezier(0.2, 0.8, 0.3, 1);
}
.panneau.etroit { width: min(460px, 100%); }
.panneau h2 { margin: 4px 0 6px; font-size: 24px; letter-spacing: -0.02em; }
.panneau .desc { margin: 0 0 18px; color: var(--doux); line-height: 1.65; }
.panneau .apercu {
  width: 100%;
  border-radius: 14px;
  display: block;
  background: var(--scene);
  border: 1px solid var(--bord);
  min-height: 140px;
}
.panneau .legende { margin: 12px 0 0; color: var(--tres-doux); font-size: 12.5px; text-align: center; }
.panneau .actions { display: flex; align-items: center; gap: 14px; margin-top: 20px; flex-wrap: wrap; }
.panneau .actions .prix { margin-right: auto; }

/* Illustration d'un article dans sa fenêtre : elle vient avant le texte, comme
   sur la carte, pour qu'on reconnaisse tout de suite ce qu'on a cliqué. */
.apercu-article {
  width: 100%;
  border-radius: 14px;
  display: block;
  margin-bottom: 16px;
  border: 1px solid var(--bord);
  background: var(--scene);
}

@keyframes apparait { from { opacity: 0; } }
@keyframes monte { from { opacity: 0; transform: translateY(14px) scale(0.98); } }

.fermer {
  position: absolute;
  top: 14px;
  right: 14px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--bord);
  color: var(--doux);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  padding: 8px 11px;
  border-radius: 10px;
  transition: background 0.15s, color 0.15s;
}
.fermer:hover { background: rgba(255, 255, 255, 0.12); color: var(--texte); }

/* --- Boutons ------------------------------------------------------------ */

.btn {
  position: relative;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 12px;
  padding: 12px 24px;
  font-weight: 700;
  font-size: 15px;
  cursor: pointer;
  color: #fff;
  background: linear-gradient(180deg, #7b85ff, #5560f0);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 10px 24px -14px rgba(100, 112, 255, 0.9);
  transition: transform 0.15s, box-shadow 0.15s, filter 0.15s;
}
.btn:hover { filter: brightness(1.08); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.34), 0 14px 30px -14px rgba(100, 112, 255, 1); }
.btn:active { transform: translateY(1px); }
.btn.secondaire {
  background: var(--verre-fort);
  color: var(--texte);
  border-color: var(--bord-vif);
  box-shadow: var(--liseré);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.btn:disabled { opacity: 0.45; cursor: not-allowed; filter: none; transform: none; }

/* --- Connexion et messages ---------------------------------------------- */

.connexion {
  max-width: 480px;
  margin: 13vh auto;
  text-align: center;
  padding: 38px 32px;
  background: var(--verre);
  border: 1px solid var(--bord);
  box-shadow: var(--liseré), var(--ombre-haute);
  border-radius: 22px;
  backdrop-filter: var(--flou);
  -webkit-backdrop-filter: var(--flou);
}
.connexion h1 { margin: 0 0 12px; font-size: 27px; letter-spacing: -0.02em; }
.connexion p { color: var(--doux); line-height: 1.7; margin: 0; }
.connexion .btn { display: inline-block; margin-top: 24px; text-decoration: none; }

.vide {
  grid-column: 1 / -1;
  padding: 40px 24px;
  text-align: center;
  color: var(--doux);
  background: var(--verre);
  border: 1px dashed var(--bord-vif);
  border-radius: 18px;
}

.toast {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translateX(-50%);
  background: var(--verre-fort);
  border: 1px solid var(--bord-vif);
  box-shadow: var(--liseré), var(--ombre-haute);
  border-radius: 14px;
  padding: 13px 22px;
  font-weight: 600;
  z-index: 40;
  max-width: min(90vw, 560px);
  backdrop-filter: var(--flou);
  -webkit-backdrop-filter: var(--flou);
  animation: monte 0.22s ease-out;
}
.toast.erreur { border-color: rgba(224, 57, 59, 0.6); background: linear-gradient(158deg, rgba(224, 57, 59, 0.22), rgba(224, 57, 59, 0.08)); }

@media (max-width: 620px) {
  .entete { padding: 12px 16px; gap: 10px; }
  .entete .avatar { width: 36px; height: 36px; }
  main { padding: 24px 16px 56px; }
  .titre h1 { font-size: 22px; }
  .titre.second { margin-top: 40px; }
  .grille { grid-template-columns: repeat(auto-fill, minmax(158px, 1fr)); gap: 12px; }
  .infos { padding: 11px 12px 13px; }
  .nom { font-size: 14px; }
  .prix { font-size: 14px; }
  .panneau { padding: 20px; border-radius: 18px; }
}

/* Le verre coûte cher à dessiner. Là où le navigateur ne sait pas flouter un
   fond, mieux vaut une plaque franchement opaque qu'une plaque transparente
   posée sur une aurore : le texte y deviendrait illisible. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .carte, .panneau, .toast, .connexion, .pastille { background: #14161f; }
  .entete { background: #0c0e15; }
  .voile { background: rgba(4, 5, 9, 0.92); }
}

/* Mouvement réduit : on garde les changements d'état, on retire les
   déplacements. Une carte qui saute sous le pointeur peut donner la nausée. */
@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
  .carte:hover { transform: none; }
}
