/* Adjugé! — front. Extrait de app.css (Détail (fiche, galerie, questions)).
   Les app.*.css sont chargés DANS L'ORDRE (la cascade en dépend) ;
   ne pas réordonner les <link>. */
/* ---------- Détail ---------- */
#screen-detail { position: relative; height: 100dvh; overflow: hidden; }
.detail-scroll { height: 100%; overflow: auto; padding-bottom: 150px; }
.d-photo {
  /* L'image domine l'écran (façon Vinted) : ~60 % de la hauteur visible,
     recadrée en cover. Portrait → on montre largement la photo ; le reste
     de la fiche défile en dessous. */
  position: relative; height: 60dvh;
  display: flex; align-items: center; justify-content: center;
}
/* Rail de diapos (façon Instagram) : défilement HORIZONTAL natif avec
   scroll-snap — le doigt fait glisser la photo et la cale sur la voisine. Le
   navigateur gère le suivi de la pulpe et l'inertie (comme la lightbox), au
   lieu d'un saut instantané au relâchement. Imbriqué dans le scroll VERTICAL de
   la fiche : le navigateur disambigue l'axe du geste tout seul. */
.d-photo-track {
  position: absolute; inset: 0;
  display: flex; overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
}
.d-photo-track::-webkit-scrollbar { display: none; }
/* Glissement souris en cours (desktop) : on COUPE le scroll-snap le temps du
   geste ET de l'animation de recalage — sinon le `mandatory` « téléporte »
   instantanément à l'accrochage au relâchement (le rendu doux est porté par le
   scrollTo behavior:smooth dans app.detail.js). */
.d-photo-track.dragging { scroll-snap-type: none; }
.d-slide {
  position: relative;
  flex: 0 0 100%; width: 100%; height: 100%;
  scroll-snap-align: start; scroll-snap-stop: always;
  background-size: cover; background-position: center; background-repeat: no-repeat;
}
/* Libellé de repli (annonce sans photo) : centré AU-DESSUS du rail (le rail
   couvre toute la boîte), invisible quand vide. */
#d-img-label {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  display: flex; align-items: center; justify-content: center;
}
/* Vidéo courte (façon eBay/Vinted) = PREMIÈRE diapo de la galerie : posée en
   absolu pour remplir .d-photo (même hauteur que les photos → pas de saut au
   swipe), letterboxée sur fond noir. z-index auto + placée AVANT les boutons
   flottants/points dans le DOM → ceux-ci restent cliquables par-dessus. */
.d-video {
  position: absolute; inset: 0; width: 100%; height: 100%;
  background: #000; object-fit: contain;
}
.float-btn {
  position: absolute; top: calc(14px + var(--sat)); right: 14px;
  width: 38px; height: 38px; border-radius: 999px; background: rgba(255,255,255,0.94);
  display: flex; align-items: center; justify-content: center; font-size: 17px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.08); transition: transform 0.1s;
}
.float-btn:active { transform: scale(0.94); }
/* Retour (haut gauche) + Partager (haut droite) PERSISTANTS : enfants directs de
   #screen-detail (hors .detail-scroll) → toujours visibles au scroll, façon
   Instagram. */
.float-btn.back { left: 14px; right: auto; font-size: 24px; line-height: 1; padding-bottom: 3px; z-index: 30; }
.float-btn.share { right: 14px; z-index: 30; }
/* Flèches de navigation de la galerie : MASQUÉES par défaut (mobile = swipe au
   doigt), réactivées uniquement sur desktop par app.desktop.css. */
.float-btn.d-nav { display: none; }
/* Badge favori de la fiche (cœur + nombre) en bas à droite de l'image — plus
   gros que sur les cartes ; le style commun vit dans .fav-badge (app.base.css). */
.d-fav-badge { bottom: 14px; right: 14px; padding: 8px 13px; font-size: 14.5px; }
/* Diapo vidéo active : le badge favori RESTE en bas à droite (choix produit),
   quitte à chevaucher le bouton plein écran des contrôles vidéo natifs — on
   privilégie l'accès au favori. La classe .on-video sert d'ancrage pour le
   reste de la galerie. */
.d-fav-badge .fav-heart { font-size: 18px; }
.d-body { padding: 16px 18px 0; }
.d-chips { display: flex; align-items: center; gap: 6px; }
.chip {
  padding: 4px 10px; border-radius: 999px; background: var(--chip-bg);
  font-size: 11px; font-weight: 700; color: var(--chip-ink);
}
.muted-count { font-size: 12px; font-weight: 600; color: var(--muted2); }
#screen-detail h1 {
  margin-top: 10px; font-size: 21px; font-weight: 700;
  letter-spacing: -0.3px; line-height: 1.25;
}

.timerbox {
  margin-top: 14px; border-radius: 16px; padding: 14px 16px; background: var(--ink);
  display: flex; flex-direction: column; align-items: flex-start; gap: 5px;
}
.timerbox.urgent { background: var(--red); animation: urgentPulse 1s ease-in-out infinite; }
.timerbox.over { background: #9A8D7D; }
.t-left { display: flex; align-items: center; gap: 8px; }
.livedot {
  width: 7px; height: 7px; border-radius: 999px; background: #FFFFFF;
  animation: livePulse 1.4s ease-in-out infinite;
}
.t-caption {
  font-size: 11px; font-weight: 700; letter-spacing: 1.2px;
  text-transform: uppercase; color: rgba(255,255,255,0.75);
}
.t-time {
  font-size: 26px; font-weight: 900; color: #FFFFFF;
  font-variant-numeric: tabular-nums; letter-spacing: -0.5px; line-height: 1.1;
}
/* En toutes lettres (« 3 jours et 2 heures ») : police réduite pour tenir,
   le compte à rebours MM:SS de la dernière heure garde son gros format. */
.t-time.verbose { font-size: 18px; letter-spacing: 0; }
#d-urgent.urgent { margin-top: 9px; }
.u-track { height: 4px; border-radius: 999px; background: #F2DFD9; overflow: hidden; }
.u-bar {
  height: 100%; border-radius: 999px; background: var(--red);
  width: 100%; transition: width 1s linear;
}
.u-label {
  margin-top: 6px; font-size: 11px; font-weight: 800; color: var(--red);
  letter-spacing: 1px; text-transform: uppercase;
}

.cur-label {
  margin-top: 18px; font-size: 11px; font-weight: 700; letter-spacing: 1.4px;
  text-transform: uppercase; color: var(--muted2);
}
.d-price {
  margin-top: 5px; font-size: 46px; font-weight: 900; letter-spacing: -1.5px;
  line-height: 1.05; font-variant-numeric: tabular-nums;
  transform-origin: left center;
}
.d-price.pulse { animation: pricePulse 0.55s cubic-bezier(0.2,0.9,0.3,1) both; }
/* Célébration « j'ai placé mon enchère » : pop plus marqué que .pulse, vire
   au vert (« vous êtes en tête »). La salve de confettis (.bid-burst) est
   injectée/retirée par celebrateBid(). */
.d-price.celebrate { animation: priceCelebrate 0.95s cubic-bezier(0.18,0.9,0.28,1.2) both; }
@keyframes priceCelebrate {
  0%   { transform: scale(1); }
  30%  { transform: scale(1.22); color: var(--green); }
  55%  { transform: scale(0.98); color: var(--green); }
  75%  { transform: scale(1.05); color: var(--green); }
  100% { transform: scale(1); }
}
/* Fête de confettis PLEIN ÉCRAN à l'enchère (canons + pluie + halo) : couche
   fixe au-dessus du contenu (sous le toast à 9999), non cliquable. Chaque
   particule est animée en JS (Web Animations API : la CSP stricte interdit les
   variables/keyframes de trajectoire en inline) ; taille/forme/couleur/position
   posées inline. PERF (anti-jank mobile) : pas de `perspective` ni de `rotateX`
   3D (le scintillement se fait en `scaleX` 2D, qui n'oblige pas le compositeur à
   layeriser chaque particule), pas d'`overflow:hidden` (clip inutile, les
   particules sortent volontairement de l'écran), et `will-change` posé EN JS au
   lancement de chaque particule puis retiré avec elle (`onfinish`) — JAMAIS en
   CSS permanent (sinon ~N couches GPU promues sont gardées vivantes ~5 s et
   saturent la VRAM d'un GPU mobile modeste → freeze de la WebView). Le NOMBRE de
   particules est borné et adapté à l'appareil dans celebrateBid(). */
.bid-burst {
  position: fixed; inset: 0; z-index: 90;
  pointer-events: none;
}
.bid-spark {
  position: absolute; width: 9px; height: 6px; border-radius: 1px;
}
/* Onde lumineuse qui se dilate derrière le prix au moment du pop. */
.bid-halo {
  position: absolute; width: 180px; height: 180px; border-radius: 50%;
  pointer-events: none;
  background: radial-gradient(circle, rgba(47,158,68,0.5) 0%, rgba(47,158,68,0.18) 45%, rgba(47,158,68,0) 70%);
}
/* Flash de fond festif (coup d'envoi) : aplat chaud uni plein écran (PAS un
   radial-gradient — un dégradé plein cadre se re-rasterise par pixel sous
   pression mémoire ; un aplat se mixe en alpha sans recalcul). */
.bid-flash {
  position: absolute; inset: 0;
  background: rgba(255,212,59,0.16);
}
/* Paillettes scintillantes (petits éclats dorés). */
.bid-sparkle {
  position: absolute; width: 12px; height: 12px; border-radius: 50%;
  background: radial-gradient(circle, #fff 0%, #FFE066 45%, rgba(255,224,102,0) 70%);
}
/* Pendant la fête (classe posée sur <body> par celebrateBid, retirée à la fin),
   on NEUTRALISE les effets concurrents les plus coûteux qui se composent avec
   les confettis qui bougent au-dessus : le `backdrop-filter: blur` de la .bidbar
   en bas (toujours visible sur une enchère live) doit reflouter sa zone à CHAQUE
   frame dès qu'un pixel bouge dessus = le produit blur × confettis sature le
   compositeur mobile. On rend le fond opaque le temps de la fête (lisibilité
   conservée) et on coupe `urgentPulse` (box-shadow animée infinie, repaint cher,
   active dans le pire cas : relance < 60 s de la fin). */
body.celebrating .bidbar {
  backdrop-filter: none; -webkit-backdrop-filter: none;
  background: rgba(250,245,239,0.98);
}
body.celebrating .timerbox.urgent { animation: none; }
/* Bannière « hero » centrale « Vous êtes en tête ! » : pastille verte, au-dessus
   des confettis. Le centrage (translate -50%,-50%) vit dans les keyframes JS
   (le transform y est animé) — ici, pas de transform pour ne pas l'écraser. */
.bid-banner {
  position: absolute; left: 50%; top: 40%; z-index: 4;
  display: flex; align-items: center; gap: 9px;
  padding: 15px 26px; border-radius: 999px; white-space: nowrap;
  background: linear-gradient(135deg, #34A853 0%, #1E7A36 100%);
  color: #fff; font-size: 19px; font-weight: 900; letter-spacing: -0.3px;
  box-shadow: 0 18px 42px rgba(30,122,54,0.45), 0 0 0 4px rgba(255,255,255,0.20);
}
.bid-banner-emoji { font-size: 25px; line-height: 1; }
/* « 11,20 € protection acheteurs incluse » (façon Vinted) : sous le prix,
   discret, cliquable (ouvre la feuille explicative). */
.d-price-incl {
  margin-top: 4px; display: inline-flex; align-items: center; gap: 4px;
  font-size: 13px; font-weight: 600; color: var(--muted);
  background: none; border: 0; padding: 0; cursor: pointer;
  font-variant-numeric: tabular-nums; text-align: left;
}
.d-price-incl::after { content: 'ⓘ'; font-size: 12px; color: var(--muted2); }
.lead-row { display: flex; align-items: center; gap: 8px; margin-top: 11px; flex-wrap: wrap; }
.lead-chip {
  display: flex; align-items: center; gap: 7px; padding: 7px 12px;
  border-radius: 999px; background: var(--chip-bg);
  font-size: 12.5px; font-weight: 700; color: var(--chip-ink);
}
.lead-chip.me { background: var(--green-bg); color: var(--green-ink); }
.lead-dot { width: 7px; height: 7px; border-radius: 999px; background: #B9AA94; }
.lead-chip.me .lead-dot { background: var(--green); }
/* Prix de réserve (façon eBay) : badge PUBLIC « atteinte / non atteinte »
   — jamais la valeur. Non atteinte = ambre (un nudge « montez encore »),
   atteinte = vert (l'objet est vendable). La ligne vendeur en dessous
   (#d-reserve-seller) montre LA VALEUR, à lui seul, en discret. */
.reserve-badge {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 11px;
  padding: 7px 12px; border-radius: 999px;
  font-size: 12.5px; font-weight: 700;
  background: #FDEEE3; color: var(--orange-dark);
}
.reserve-badge.met { background: var(--green-bg); color: var(--green-ink); }
.reserve-seller {
  margin-top: 7px; font-size: 12.5px; font-weight: 600; color: var(--muted);
}
/* Mise en avant payante (« boost ») : badge PUBLIC « ⭐ Annonce à la une »,
   doré, affiché à TOUS tant qu'elle est active (jamais le prix payé). */
.boost-badge {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 11px;
  padding: 7px 12px; border-radius: 999px;
  font-size: 12.5px; font-weight: 800; color: #FFFFFF;
  background: linear-gradient(135deg, #F6A623, #E8830F);
  box-shadow: 0 2px 8px rgba(232,131,15,0.35);
}
/* Achat immédiat (Buy It Now, façon eBay). Bouton ACHETEUR « Acheter
   maintenant » : plein, SOMBRE (contraste avec l'orange « Enchérir » de la
   barre du bas), deux lignes (prix + total protection acheteur incluse). */
.buynow-cta {
  margin-top: 12px; width: 100%;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 12px 16px; border-radius: 16px;
  background: var(--ink); color: var(--bg); border: 0; cursor: pointer;
  box-shadow: 0 8px 18px rgba(34,26,18,0.22); transition: transform 0.1s;
}
.buynow-cta:active { transform: scale(0.98); }
.bn-main { font-size: 15.5px; font-weight: 800; letter-spacing: 0.2px; }
.bn-sub { font-size: 11.5px; font-weight: 600; opacity: 0.82; }
/* Côté VENDEUR : prix d'achat immédiat actuel + « Modifier » et « Retirer »
   (baisser / monter / supprimer), ou « Ajouter » s'il n'y en a pas. */
.buynow-seller {
  margin-top: 11px; display: flex; align-items: center; gap: 8px;
  padding: 9px 9px 9px 13px; border-radius: 14px;
  background: #FFFFFF; border: 1px solid var(--card-line);
}
.bns-line { flex: 1; min-width: 0; font-size: 12.5px; font-weight: 700; color: var(--chip-ink); }
/* Barre boost « à la une » : durée restante (forte) au-dessus de l'échéance. */
.bns-stack { display: flex; flex-direction: column; gap: 1px; }
.bns-strong { font-weight: 800; }
.bns-sub { font-weight: 600; font-size: 11px; color: var(--muted); }
.bns-btn {
  flex: none; padding: 7px 14px; border-radius: 999px; background: var(--ink);
  color: var(--bg); font-size: 12px; font-weight: 800; border: 0; cursor: pointer;
  transition: transform 0.1s;
}
.bns-btn:active { transform: scale(0.96); }
/* « Retirer » : style discret (contour) pour ne pas concurrencer « Modifier ». */
.bns-btn-rm { background: #FFFFFF; color: var(--red); border: 1px solid var(--card-line); }
.auto-chip {
  padding: 7px 12px; border-radius: 999px; background: #FDEEE3;
  border: 1px solid #F5CDAA; font-size: 12px; font-weight: 700;
  color: var(--orange-dark);
}
/* « Faire une offre » (négociation prix fixe, façon Vinted). Bouton ACHETEUR
   SECONDAIRE (contour) sous le « Acheter » sombre — il ne lui fait pas
   concurrence. */
.offer-cta {
  margin-top: 10px; width: 100%; padding: 11px 16px; border-radius: 14px;
  background: #FFFFFF; color: var(--ink); border: 1.5px solid var(--ink);
  font-size: 14px; font-weight: 800; cursor: pointer; transition: transform 0.1s;
}
.offer-cta:active { transform: scale(0.98); }
/* (La NÉGOCIATION elle-même se déroule dans l'onglet Messages — fil d'offre
   #screen-offer-thread, stylé dans app.messages.css — pas sur la fiche.) */
/* « Retirer ma mise » : action SECONDAIRE dans la barre d'action du bas, à
   gauche du « Enchérir » orange. Contour discret (ne concurrence pas le CTA
   principal), même hauteur (54) pour s'aligner, largeur au contenu (flex:none
   → « Enchérir » garde son flex:1). */
.bb-retract {
  flex: none; height: 54px; padding: 0 16px; border-radius: 999px;
  background: #FFFFFF; border: 1px solid var(--card-line); color: var(--red);
  font-size: 14px; font-weight: 800; white-space: nowrap; cursor: pointer;
  transition: transform 0.1s;
}
.bb-retract:active { transform: scale(0.97); }
.bb-retract:disabled { opacity: 0.5; }
/* Pastille « Vous avez été dépassé ! » : visible UNIQUEMENT pour qui est sur la
   fiche au moment où une enchère adverse lui passe devant (posée dans le
   handler du watch, app.detail.js). Entrée qui « pop » PUIS une petite secousse
   d'attention juste après — on réveille l'œil sans agressivité (façon
   notification). Les deux keyframes animent transform : la secousse est listée
   en second → elle l'emporte pendant le bref recouvrement, sans à-coup
   (elle démarre et finit à translateX(0)). */
.outbid {
  margin-top: 14px; padding: 12px 14px; border-radius: 14px; background: #FBE7EA;
  border: 1px solid #F2C4CC;
  animation: outbidIn 0.5s cubic-bezier(0.2,0.9,0.3,1) both,
             outbidShake 0.55s 0.42s ease-in-out both;
}
@keyframes outbidIn {
  0%   { opacity: 0; transform: translateY(-10px) scale(0.96); }
  60%  { opacity: 1; transform: translateY(0) scale(1.02); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes outbidShake {
  0%, 100% { transform: translateX(0); }
  15% { transform: translateX(-6px); }
  30% { transform: translateX(5px); }
  45% { transform: translateX(-4px); }
  60% { transform: translateX(3px); }
  75% { transform: translateX(-2px); }
}
/* « Réduire les animations » : on garde une entrée discrète, sans secousse. */
@media (prefers-reduced-motion: reduce) {
  .outbid { animation: outbidIn 0.3s ease both; }
}
.ob-title { font-size: 13.5px; font-weight: 800; color: #C01B30; }
.ob-sub { font-size: 12px; color: #A04B58; margin-top: 2px; }

.seller-card {
  margin-top: 18px; background: #FFFFFF; border: 1px solid var(--card-line);
  border-radius: 16px; padding: 13px 14px; display: flex; align-items: center; gap: 12px;
  width: 100%; text-align: left; transition: opacity 0.1s;
}
.seller-card:active { opacity: 0.85; }
.avatar {
  width: 42px; height: 42px; border-radius: 999px; background: var(--ink);
  color: var(--bg); display: flex; align-items: center; justify-content: center;
  font-size: 14px; font-weight: 800; flex-shrink: 0;
}
.avatar.big { width: 62px; height: 62px; font-size: 20px; }
.seller-info { flex: 1; display: flex; flex-direction: column; gap: 3px; }
.seller-name { font-size: 13.5px; font-weight: 700; }
.seller-meta { font-size: 11.5px; color: var(--muted); }
/* Note vendeur en étoiles (façon Vinted) sur la carte fiche : barre d'étoiles
   compacte alignée au texte « N ventes ». */
.seller-meta .stars-bar { font-size: 13px; letter-spacing: 1px; vertical-align: -2px; }
.seller-rate-num { font-weight: 700; color: var(--ink-soft); margin-left: 4px; }
.badge {
  padding: 3px 8px; border-radius: 999px; background: var(--chip-bg);
  font-size: 10px; font-weight: 700; color: var(--chip-ink);
}
.chev { font-size: 20px; color: var(--faint); }
.d-h2 { margin-top: 20px; font-size: 13.5px; font-weight: 800; }
.d-desc {
  margin-top: 6px; font-size: 13px; line-height: 1.6; color: #5C5347;
  text-wrap: pretty;
}

.hist-head { display: flex; align-items: center; gap: 8px; margin: 22px 0 10px; }
.hist-title { font-size: 14px; font-weight: 800; }
.reddot {
  width: 7px; height: 7px; border-radius: 999px; background: var(--red);
  animation: livePulse 1.2s ease-in-out infinite;
}
.history { display: flex; flex-direction: column; gap: 8px; }
.bid-row {
  display: flex; align-items: center; gap: 11px; padding: 11px 13px;
  border-radius: 14px; background: #FFFFFF; border: 1px solid var(--card-line);
  animation: bidIn 0.45s cubic-bezier(0.2,0.9,0.3,1) both;
}
.bid-row.mine { background: #FDEEE3; border-color: #F5CDAA; }
.bid-row.clickable { cursor: pointer; }
.bid-row.clickable:active { background: var(--chip-bg); }
.bid-row.mine.clickable:active { background: #F8E0CE; }
.bid-avatar {
  width: 30px; height: 30px; border-radius: 999px; background: #EADBC6;
  color: var(--chip-ink); display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 800; flex-shrink: 0;
}
.bid-row.mine .bid-avatar { background: var(--orange); color: #FFFFFF; }
.bid-main { flex: 1; min-width: 0; }
.bid-name { font-size: 13px; font-weight: 600; display: flex; align-items: center; gap: 6px; }
.bid-row.mine .bid-name { font-weight: 800; }
.auto-tag {
  font-size: 9px; font-weight: 800; letter-spacing: 0.5px; padding: 2px 6px;
  border-radius: 999px; background: var(--chip-bg); color: var(--muted);
  text-transform: uppercase;
}
.bid-when { font-size: 11px; color: var(--muted2); margin-top: 1px; }
.bid-amount { font-size: 15px; font-weight: 900; font-variant-numeric: tabular-nums; }
.bid-row.top .bid-amount { color: var(--orange); }

/* Barre d'enchère collée en bas */
.bidbar {
  position: absolute; bottom: 0; left: 0; right: 0; z-index: 25;
  padding: 12px 16px calc(20px + var(--sab));
  background: rgba(250,245,239,0.95); backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-top: 1px solid var(--line);
  display: flex; align-items: center; gap: 14px;
}
.bb-cur { display: flex; flex-direction: column; }
.bb-label {
  font-size: 10.5px; font-weight: 700; letter-spacing: 1px;
  text-transform: uppercase; color: var(--muted2);
}
.bb-price { font-size: 20px; font-weight: 900; font-variant-numeric: tabular-nums; }
.cta {
  flex: 1; height: 54px; border-radius: 999px; background: var(--orange);
  color: #FFFFFF; display: flex; align-items: center; justify-content: center;
  font-size: 16.5px; font-weight: 800; letter-spacing: 0.2px;
  box-shadow: 0 8px 18px rgba(232,89,12,0.35); transition: transform 0.1s;
}
.cta:active { transform: scale(0.97); }
.cta.dark { background: var(--ink); color: var(--bg); box-shadow: none; }
.cta.wide { width: 100%; flex: none; }
.ended-pill {
  flex: 1; height: 54px; border-radius: 999px; background: #E5DBCC;
  color: var(--muted); display: flex; align-items: center; justify-content: center;
  font-size: 15.5px; font-weight: 800;
}
.linklike {
  margin-top: 16px; font-size: 13px; font-weight: 700; color: var(--muted);
  text-decoration: underline;
}
.linklike.small { margin: 0; font-size: 12px; }
/* Action destructive (« Supprimer mon compte ») : rouge, sous la déconnexion. */
.linklike.danger { color: #c0392b; margin-top: 10px; }

/* ---------- Squelettes de chargement (fiche ouverte instantanément) ----------
   Au tap d'une annonce, l'écran fiche s'affiche TOUT DE SUITE : si la donnée est
   déjà en cache (carte du feed/recherche/profil) la fiche est peinte en entier
   et seules les sections « live » (enchères, questions) chauffent en squelette ;
   sinon (lien profond, notification) un voile plein écran #d-skeleton tient la
   place le temps de la requête. Le scintillement reste neutre pour les écrans à
   mouvement réduit. */
.skel {
  background: linear-gradient(100deg, var(--chip-bg) 28%, #F8F2E9 50%, var(--chip-bg) 72%);
  background-size: 220% 100%;
  animation: adjShimmer 1.25s ease-in-out infinite;
  border-radius: 8px;
}
@keyframes adjShimmer {
  0% { background-position: 160% 0; }
  100% { background-position: -160% 0; }
}
@media (prefers-reduced-motion: reduce) { .skel { animation: none; } }

/* Voile plein écran (ouverture SANS donnée en cache). Couvre la barre du bas
   (z-index 25) et la barre sticky (z-index 20) — seul son propre bouton retour
   reste tapable par-dessus. */
#d-skeleton {
  position: absolute; inset: 0; z-index: 30;
  background: var(--bg); overflow: hidden;
}
#d-skeleton .sk-photo { height: 60dvh; border-radius: 0; }
#d-skeleton .sk-body { padding: 18px; display: flex; flex-direction: column; gap: 13px; }
#d-skeleton .sk-chips { display: flex; gap: 8px; }
#d-skeleton .sk-chips span { width: 64px; height: 22px; border-radius: 999px; }
#d-skeleton .sk-bar { height: 16px; width: 100%; }
#d-skeleton .sk-bar--title { height: 24px; width: 78%; }
#d-skeleton .sk-bar--short { width: 46%; }
#d-skeleton .sk-bar--price { height: 30px; width: 38%; margin-top: 4px; }
#d-skeleton .sk-box { height: 58px; border-radius: 16px; margin: 4px 0; }

/* Lignes squelettes pour l'historique d'enchères et les questions (la fiche est
   déjà peinte, ces sections arrivent un instant après par leur propre requête). */
.bid-skel {
  display: flex; align-items: center; gap: 11px; padding: 11px 13px;
  border-radius: 14px; background: #FFFFFF; border: 1px solid var(--card-line);
}
.bid-skel .sk-av { width: 30px; height: 30px; border-radius: 999px; flex-shrink: 0; }
.bid-skel .sk-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.bid-skel .sk-l1 { height: 12px; width: 42%; }
.bid-skel .sk-l2 { height: 10px; width: 28%; }
.bid-skel .sk-amt { width: 56px; height: 16px; }
.q-skel { padding: 12px 0; display: flex; flex-direction: column; gap: 8px; }
.q-skel .sk-l1 { height: 12px; width: 35%; }
.q-skel .sk-l2 { height: 12px; width: 88%; }

