@charset "UTF-8";
/* =========================================================================
   LE MODE SHINY DE LA COLLECTION

   Feuille SEPAREE, chargee par `profil-shiny.html` seulement. Tant que la
   refonte n'est pas validee, `profil.html` continue de tourner sans une seule
   ligne de changement : les deux pages cohabitent, on compare, on tranche.

   La technique est celle du Scriptorium, portee telle quelle et pas
   reconstruite dans l'esprit de. Un rappel de son principe, parce que c'est
   contre-intuitif et que le refaire a l'envers coute une demi-journee :

   UNE PAILLETTE NE SE DEPLACE PAS. Une feuille holographique a ses paillettes
   solidaires du support ; ce qui change quand on l'incline, c'est la couleur
   que chacune renvoie. Donc le pochoir de paillettes reste IMMOBILE et c'est
   un degrade qui defile dessous. Faire glisser la texture donne un decalque
   qui se promene sur le dessin, ce que l'oeil refuse aussitot.

   Les variables (--rx --ry --px --py --pr --ang) sont ecrites par
   `holo-vivant.js`, jamais par cette feuille.
   ========================================================================= */

/* ── LE MUR DES SHINY ───────────────────────────────────────────────────── */
/* Une vitrine, pas un filtre cache. Ces pieces sont les seules qui meritent
   qu'on s'arrete, donc elles sont plus grandes que dans la grille. Vide, le
   mur montre ce qu'on n'a pas encore : c'est la sa fonction principale. */
.shiny-mur{
  margin:0 0 18px; padding:14px 16px 16px;
  border:1px solid rgba(201,168,76,.28); border-radius:8px;
  background:
    radial-gradient(ellipse 70% 120% at 50% -20%, rgba(201,168,76,.10), transparent 70%),
    rgba(0,0,0,.16);
}
.shiny-mur-entete{
  display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; margin-bottom:12px;
}
.shiny-mur-titre{
  margin:0; font-family:var(--font-title, 'Cinzel', serif);
  font-size:1rem; letter-spacing:.06em; color:#c9a84c;
}
.shiny-mur-compte{ margin:2px 0 0; font-size:.82rem; color:#a99a8c }
.shiny-mur-compte b{ color:#e7d7c1 }

/* LE BANDEAU DES SHINY. Le compte et l'interrupteur qui filtre les shiny
   disaient la meme chose a deux endroits de la page, dont l'un au bout du champ
   de recherche, ou il passait inapercu. Une seule ligne, lisible. */
.shiny-bandeau{
  position:relative; display:flex; align-items:center; gap:14px; flex-wrap:wrap;
}
.shiny-bandeau-mots{ flex:1 1 200px; min-width:0 }
.shiny-mur--nu{ margin-bottom:14px }
.shiny-mur--nu .shiny-bandeau{ margin:0 }
.shiny-mur .shiny-bandeau + .shiny-mur-grille{ margin-top:14px }
/* L'interrupteur devient l'element saillant du bandeau : c'est l'action. */
.shiny-bandeau .coll-shiny-seul{
  flex:none; padding:7px 14px; border-radius:999px; color:#e7d7c1;
  border:1px solid rgba(201,168,76,.34); background:rgba(201,168,76,.10);
  transition:background .18s, border-color .18s;
}
.shiny-bandeau .coll-shiny-seul:hover{ background:rgba(201,168,76,.2); border-color:#c9a84c }

/* L'explication, en bulle. Elle ne sert qu'une fois : permanente, elle occupait
   trois lignes sous un compte a zero. */
.shiny-aide{
  position:absolute; left:0; right:0; top:calc(100% + 8px); z-index:5;
  margin:0; padding:9px 13px; border-radius:6px;
  background:rgba(12,2,6,.97); border:1px solid rgba(201,168,76,.3);
  font-size:.8rem; font-style:italic; line-height:1.55; color:#d8c8b4;
  opacity:0; visibility:hidden; transform:translateY(-4px);
  transition:opacity .18s, transform .18s, visibility .18s;
  box-shadow:0 12px 26px rgba(0,0,0,.5);
}
.shiny-bandeau:hover .shiny-aide,
.shiny-bandeau:focus-within .shiny-aide{ opacity:1; visibility:visible; transform:none }
/* Sans survol, une bulle ne s'atteint jamais : elle redevient une ligne. */
@media (hover: none){
  .shiny-aide{
    position:static; opacity:1; visibility:visible; transform:none;
    margin-top:10px; box-shadow:none; flex:1 1 100%;
  }
}
.shiny-mur-grille{
  display:grid; grid-template-columns:repeat(auto-fill, minmax(86px, 1fr)); gap:12px;
}
/* min-width:0 a chaque etage : un enfant de grille vaut `auto` et refuse de
   descendre sous la largeur de son contenu. Sans cela la grille deborde sur
   telephone au lieu de se reorganiser. */
.shiny-mur-grille > *{ min-width:0 }

/* ── UNE PIECE SHINY ────────────────────────────────────────────────────── */
.shiny-piece{
  position:relative; aspect-ratio:1; display:grid; place-items:center;
  padding:8px; border-radius:7px; cursor:zoom-in; min-width:0;
  background:rgba(201,168,76,.07); border:1px solid rgba(201,168,76,.34);
  /* La courbe est celle du titre de shinysticker.app : le retour au repos
     compte autant que la poursuite, c'est lui qui donne le ressort. */
  transform:perspective(var(--persp, 220px))
            rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg))
            scale(calc(1 + var(--pr, 0) * .04));
  transition:transform .22s cubic-bezier(.2, .8, .3, 1),
             box-shadow .22s cubic-bezier(.2, .8, .3, 1);
  transform-style:preserve-3d;
}
/* L'ombre part du cote OPPOSE a l'inclinaison : c'est elle qui dit a l'oeil
   qu'un bord s'est souleve, plus surement que la rotation seule. */
.shiny-piece.hv-actif{
  z-index:4;
  box-shadow:calc(var(--mx, 0) * -9px) calc(var(--my, 0) * -9px + 7px) 18px rgba(0,0,0,.5);
}
.shiny-piece img{ max-width:100%; max-height:100%; object-fit:contain;
                  position:relative; z-index:1; pointer-events:none }

/* Calque 1 : la couleur qui court DANS les paillettes. Deux masques se
   croisent, la forme du dessin et la forme des paillettes ; seul le fond
   bouge, le pochoir jamais. --gx et --gy decalent le grain par piece, donc
   deux shiny cote a cote n'ont pas leurs paillettes au meme endroit. */
.shiny-piece::before{
  content:''; position:absolute; inset:8px; z-index:2; pointer-events:none;
  background-image:
    radial-gradient(circle at var(--px, 50%) var(--py, 50%),
      rgba(255,255,255,.9), rgba(255,255,255,0) 38%),
    repeating-linear-gradient(calc(var(--ang, 0deg) + 90deg),
      #ff3a74 0%,  #ffd640 7%,  #56ec8e 14%,
      #3ac4ff 21%, #9e5cff 28%, #ff3a74 35%);
  background-size:auto, 260% 260%;
  background-position:0 0, calc(var(--px, 50%) * 2.1) calc(var(--py, 50%) * 2.1);
  -webkit-mask-image:var(--img), url('../img/holo-flocons.webp');
  mask-image:var(--img), url('../img/holo-flocons.webp');
  -webkit-mask-size:contain, 26px 26px; mask-size:contain, 26px 26px;
  -webkit-mask-repeat:no-repeat, repeat; mask-repeat:no-repeat, repeat;
  -webkit-mask-position:center, var(--gx, 0px) var(--gy, 0px);
  mask-position:center, var(--gx, 0px) var(--gy, 0px);
  -webkit-mask-composite:source-in; mask-composite:intersect;
  mix-blend-mode:color-dodge;
  opacity:calc(.42 + var(--pr, 0) * .35);
  transition:opacity .22s cubic-bezier(.2, .8, .3, 1);
}
/* Calque 2 : le relief des facettes, strictement immobile. C'est justement
   son immobilite qui en fait une matiere : un relief qui bouge est un reflet. */
.shiny-piece::after{
  content:''; position:absolute; inset:8px; z-index:3; pointer-events:none;
  background-image:url('../img/holo-flocons.webp');
  background-size:26px 26px;
  background-position:var(--gx, 0px) var(--gy, 0px);
  -webkit-mask-image:var(--img); mask-image:var(--img);
  -webkit-mask-size:contain; mask-size:contain;
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
  -webkit-mask-position:center; mask-position:center;
  mix-blend-mode:soft-light; opacity:.5;
}

/* L'emplacement vide du mur : ce qu'on n'a pas encore. Il ne montre rien du
   dessin, sinon il vaudrait recompense. */
.shiny-creux{
  aspect-ratio:1; border-radius:7px; min-width:0;
  /* Un CREUX, pas un contour en pointilles : filet plein a peine visible et
     ombre interieure, l'emplacement se lit en negatif. */
  border:1px solid rgba(201,168,76,.12); background:rgba(0,0,0,.2);
  box-shadow:inset 0 1px 7px rgba(0,0,0,.5);
  display:grid; place-items:center; color:rgba(201,168,76,.3); font-size:1.3rem;
}

/* ── DANS LA GRILLE ORDINAIRE ───────────────────────────────────────────── */
/* Une piece possedee en deux versions porte un repere dore. Le clic bascule
   la vignette d'une version a l'autre : on compare sans quitter la grille, et
   c'est la comparaison qui donne sa valeur a la variante. */
.coll-piece--ashiny{ border-color:rgba(201,168,76,.5) }
/* LA PASTILLE. Deux versions ecartees avant celle-ci : un rond rouge en
   degrade, qui se lisait comme une interdiction, puis une etincelle seule,
   dont personne ne devinait qu'elle se cliquait. Un signe qui n'annonce pas
   son geste n'est pas un bouton, c'est une decoration.
   Elle porte donc un MOT, un fond et une bordure : trois indices qui disent
   « ceci se clique » sans avoir a l'apprendre. */
.coll-repere{
  position:absolute; top:2px; right:2px; z-index:4;
  display:flex; align-items:center; gap:2px;
  padding:1px 4px 1px 3px; border-radius:20px;
  font:inherit; font-size:7.5px; letter-spacing:.06em; text-transform:uppercase;
  line-height:1.35; cursor:pointer;
  color:#ffe08a; background:rgba(32,6,18,.86);
  border:1px solid rgba(255,208,90,.5);
  box-shadow:0 1px 3px rgba(0,0,0,.5);
  transition:background .14s, color .14s, transform .14s, top .18s;
}
.coll-repere i{ font-style:normal; font-size:8.5px; line-height:1 }
/* Au repos, le mot s'efface : mesure a l'appui, « shiny » ecrit en clair
   occupe 42 px sur une tuile de 60, soit 70 % de sa largeur, et couvre le
   dessin qu'il signale. Il revient sous la souris, en meme temps que l'effet
   lui-meme : on voit le resultat et son bouton d'un seul geste.
   `max-width` plutot que `display` : une largeur s'anime, pas une apparition. */
.coll-repere span{
  max-width:0; overflow:hidden; white-space:nowrap;
  transition:max-width .18s cubic-bezier(.2, .8, .3, 1);
}
.coll-piece--ashiny:hover .coll-repere span,
.coll-piece--montre .coll-repere span{ max-width:40px }
/* Deployee, elle remonte AU-DESSUS du bord. Posee dans la tuile elle couvrait
   le haut du dessin, c'est-a-dire ce qu'on vient regarder. Il faut alors que
   la tuile cesse de rogner ce qui depasse et passe devant ses voisines. */
.coll-piece--ashiny{ overflow:visible }
.coll-piece--ashiny:hover, .coll-piece--montre{ z-index:5 }
.coll-piece--ashiny:hover .coll-repere,
.coll-piece--montre .coll-repere{ top:-9px; right:-3px }
.coll-repere:hover{ background:rgba(90,24,52,.95); color:#fff5d2; transform:scale(1.06) }
/* Figee en shiny, la pastille s'allume : on sait laquelle des deux versions
   on regarde sans avoir a s'en souvenir. */
.coll-piece--montre .coll-repere{
  color:#0d0409; background:linear-gradient(100deg, #ffd85c, #ff9ad0 55%, #7fe6ff);
  border-color:rgba(255,255,255,.7);
}

/* LE SURVOL SUFFIT. La vignette passe en shiny quand la souris la traverse :
   aucun geste a deviner, et la comparaison des deux versions se fait par un
   mouvement qu'on fait deja pour lire la grille. Le clic sur la pastille ne
   sert plus qu'a FIGER l'etat, ce qui reste le seul moyen sur un ecran
   tactile, ou le survol n'existe pas. */
.coll-piece--ashiny{ position:relative }

/* La case de report, quand le mur est plein. Elle ne montre aucune piece :
   son role est de renvoyer au detail, pas de faire une seconde vitrine. */
.shiny-report{
  aspect-ratio:1; border-radius:7px; min-width:0; cursor:pointer;
  border:1px solid rgba(201,168,76,.34); background:rgba(201,168,76,.07);
  color:#c9a84c; font:inherit; display:grid; place-items:center; gap:2px;
  transition:background .14s;
}
.shiny-report:hover{ background:rgba(201,168,76,.18) }
.shiny-report b{ font-size:1.05rem; line-height:1 }
.shiny-report span{ font-size:.66rem; color:#a99a8c }
.coll-piece--montre{ position:relative }
/* La vignette basculee en shiny reutilise exactement les memes calques, a la
   taille de la grille. Rien n'est duplique : seules les tailles changent. */
.coll-piece--ashiny:hover::before, .coll-piece--ashiny:hover::after,
.coll-piece--montre::before, .coll-piece--montre::after{
  content:''; position:absolute; inset:4px; pointer-events:none;
}
.coll-piece--ashiny:hover::before, .coll-piece--montre::before{
  z-index:2;
  background-image:
    radial-gradient(circle at var(--px, 50%) var(--py, 50%),
      rgba(255,255,255,.9), rgba(255,255,255,0) 38%),
    repeating-linear-gradient(calc(var(--ang, 0deg) + 90deg),
      #ff3a74 0%,  #ffd640 7%,  #56ec8e 14%,
      #3ac4ff 21%, #9e5cff 28%, #ff3a74 35%);
  background-size:auto, 260% 260%;
  background-position:0 0, calc(var(--px, 50%) * 2.1) calc(var(--py, 50%) * 2.1);
  -webkit-mask-image:var(--img), url('../img/holo-flocons.webp');
  mask-image:var(--img), url('../img/holo-flocons.webp');
  -webkit-mask-size:contain, 22px 22px; mask-size:contain, 22px 22px;
  -webkit-mask-repeat:no-repeat, repeat; mask-repeat:no-repeat, repeat;
  -webkit-mask-position:center, var(--gx, 0px) var(--gy, 0px);
  mask-position:center, var(--gx, 0px) var(--gy, 0px);
  -webkit-mask-composite:source-in; mask-composite:intersect;
  mix-blend-mode:color-dodge; opacity:calc(.42 + var(--pr, 0) * .35);
}
.coll-piece--ashiny:hover::after, .coll-piece--montre::after{
  z-index:3;
  background-image:url('../img/holo-flocons.webp');
  background-size:22px 22px;
  background-position:var(--gx, 0px) var(--gy, 0px);
  -webkit-mask-image:var(--img); mask-image:var(--img);
  -webkit-mask-size:contain; mask-size:contain;
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
  -webkit-mask-position:center; mask-position:center;
  mix-blend-mode:soft-light; opacity:.5;
}

/* ── LE FILTRE ──────────────────────────────────────────────────────────── */
.coll-shiny-seul{
  display:inline-flex; align-items:center; gap:8px; cursor:pointer;
  font-size:.8rem; color:#a99a8c; user-select:none;
  /* 44 px de haut : la ligne entiere est la cible, pas la seule case. */
  min-height:44px;
}
/* La case native est blanche et carree, seule chose de la page a ne pas suivre
   la charte. Reecrite en interrupteur, comme dans l'atelier. */
.coll-shiny-seul input{
  appearance:none; -webkit-appearance:none; margin:0;
  width:34px; height:18px; border-radius:20px; cursor:pointer; position:relative;
  background:rgba(0,0,0,.42); border:1px solid rgba(167,138,127,.35);
  transition:background .16s, border-color .16s; flex:none;
}
.coll-shiny-seul input::after{
  content:''; position:absolute; top:2px; left:2px; width:12px; height:12px;
  border-radius:50%; background:#a99a8c; transition:transform .16s, background .16s;
}
.coll-shiny-seul input:checked{ background:rgba(201,168,76,.34); border-color:#c9a84c }
.coll-shiny-seul input:checked::after{ transform:translateX(16px); background:#c9a84c }
.coll-shiny-seul input:focus-visible{ outline:2px solid #c9a84c; outline-offset:3px }

/* ── L'APERCU D'UNE PIECE ORDINAIRE ─────────────────────────────────────── */
/* Meme boite que la loupe, image plate : une piece ordinaire rendue par le
   moteur holo passerait pour une shiny, et c'est cette difference qui donne sa
   valeur a la variante. */
/* Ni largeur ni hauteur imposees : `max-width` est pose par le script, a la
   resolution reelle de l'image, et `max-height` empeche une piece haute de
   sortir de l'ecran. Le navigateur garde le rapport. */
/* L'ombre portee vient de `.hv-objet`, qui la fait suivre le pointeur : la
   redire ici la doublerait. L'image ne porte plus que le gris du verrou. */
.coll-apercu-img{ display:block; width:auto; height:auto; max-height:70vh }
.coll-apercu--verrou .coll-apercu-img{ filter:grayscale(1) brightness(.5) }
.coll-apercu .hv-rare{
  color:#a99a8c; text-transform:none; letter-spacing:.02em; font-size:.78rem;
  font-style:italic;
}
.coll-apercu .hv-rare:empty{ display:none }
/* Une vignette qui s'ouvre l'annonce par son curseur. Jamais `help`, qui pose
   un point d'interrogation et se lit comme une aide. */
.coll-piece{ cursor:zoom-in }

/* ── LA LOUPE ───────────────────────────────────────────────────────────── */
/* Le balisage vient de `holo-vivant.js`, partage avec le Scriptorium. Seules
   les couleurs sont redites ici, la page n'ayant pas les memes variables. */
.hv-loupe{ position:fixed; inset:0; z-index:9000; display:none; place-items:center; padding:20px }
.hv-loupe.hv-ouverte{ display:grid }
.hv-voile{
  position:absolute; inset:0; cursor:zoom-out;
  background:radial-gradient(ellipse at 50% 40%, rgba(63,4,24,.72), rgba(8,2,5,.93) 70%);
  backdrop-filter:blur(3px);
}
.hv-cadre{
  position:relative; display:flex; flex-direction:column; align-items:center; gap:14px;
  animation:hv-entree .32s cubic-bezier(.2, .8, .3, 1) both;
}
@keyframes hv-entree{ from{ opacity:0; transform:translateY(14px) scale(.94) } }
/* La perspective vit sur la SCENE : posee sur l'objet, elle se recalculerait a
   chaque rotation et le point de fuite paraitrait glisser. */
.hv-scene{ perspective:1100px }
.hv-objet{
  position:relative; transform-style:preserve-3d; cursor:grab;
  transform:rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg))
            scale(calc(1 + var(--pr, 0) * .03));
  transition:transform .22s cubic-bezier(.2, .8, .3, 1);
  filter:drop-shadow(calc(var(--mx, 0) * -18px) calc(var(--my, 0) * -18px + 16px) 26px rgba(0,0,0,.6));
}
.hv-toile{ display:block; position:relative; z-index:1 }
.hv-rayons, .hv-reflet{
  position:absolute; inset:0; pointer-events:none;
  -webkit-mask-image:var(--img); mask-image:var(--img);
  -webkit-mask-size:var(--mw, 100%) var(--mh, 100%);
  mask-size:var(--mw, 100%) var(--mh, 100%);
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
  -webkit-mask-position:center; mask-position:center;
}
.hv-rayons{
  z-index:2; transform:translateZ(14px);
  background:repeating-linear-gradient(calc(var(--ang, 0deg) + 90deg),
    rgba(255,58,116,.30) 0%,  rgba(255,214,64,.26) 6%,
    rgba(86,236,142,.26) 12%, rgba(58,196,255,.30) 18%,
    rgba(158,92,255,.26) 24%, rgba(255,58,116,.30) 30%);
  background-size:260% 260%;
  background-position:calc(var(--px, 50%) * 2.2) calc(var(--py, 50%) * 2.2);
  mix-blend-mode:color-dodge; opacity:calc(.10 + var(--pr, 0) * .30);
  transition:opacity .22s cubic-bezier(.2, .8, .3, 1);
}
.hv-reflet{
  z-index:3; transform:translateZ(22px);
  background:radial-gradient(ellipse 46% 34% at var(--px, 50%) var(--py, 50%),
    rgba(255,255,255,.42), rgba(255,255,255,0) 66%);
  mix-blend-mode:screen; opacity:calc(.35 + var(--pr, 0) * .5);
}
.hv-pied{ text-align:center; color:#e7d7c1 }
.hv-titre{ font-family:var(--font-title, 'Cinzel', serif); font-size:1.05rem; letter-spacing:.04em }
.hv-rare{
  display:block; font-style:normal; font-size:.72rem; letter-spacing:.14em;
  text-transform:uppercase; color:#c9a84c; margin-top:3px;
}
.hv-actions{ display:flex; gap:9px; justify-content:center; margin-top:11px }
.hv-actions button{
  font:inherit; font-size:.82rem; padding:7px 15px; border-radius:4px; cursor:pointer;
  border:1px solid rgba(201,168,76,.45); background:rgba(201,168,76,.12); color:#e7d7c1;
}
.hv-actions button:hover{ background:rgba(201,168,76,.26) }

/* SUR UN APPAREIL SANS SURVOL, la pastille cesse d'etre un bouton : elle
   redevient une marque, et c'est la vignette entiere qui ouvre la loupe. On ne
   garde pas un geste impossible en esperant qu'il passe, on le remplace par
   celui qui existe. La cible passe de 18 px a toute la tuile. */
@media (hover: none){
  .coll-repere{ pointer-events:none }
  /* Le mot ne sortira jamais faute de survol : la marque reste l'etincelle. */
  .coll-repere span{ max-width:0 }
  .coll-piece--ashiny{ cursor:zoom-in }
}

/* Le clavier compte autant que la souris : sans ce liseré, on ne sait plus ou
   l'on est des qu'on quitte le pointeur. */
.shiny-piece:focus-visible, .coll-piece--ashiny:focus-visible,
.coll-repere:focus-visible, .shiny-report:focus-visible{
  outline:2px solid #ffd85c; outline-offset:2px;
}

/* Une inclinaison qui poursuit la souris est exactement ce qu'un reglage
   « moins d'animations » demande de taire. Le fond, lui, reste. */
@media (prefers-reduced-motion: reduce){
  .shiny-piece, .coll-piece--ashiny, .hv-objet, .coll-repere{
    transition:none !important; transform:none !important;
  }
}

@media (max-width: 520px){
  .shiny-mur-grille{ grid-template-columns:repeat(auto-fill, minmax(70px, 1fr)); gap:9px }
  .shiny-mur{ padding:12px }
}
