/* holo/holo.css */
/* Card holo effects from simeydotme/pokemon-cards-css (https://github.com/simeydotme/pokemon-cards-css), GPL-3.0 — see /holo/LICENSE. Adapted: image paths, art-window clip. */

.card {

  --grain: url("/holo/img/grain.webp");
  --glitter: url("/holo/img/glitter.png");
  --glittersize: 25%;

  --space: 5%;
  --angle: 133deg;
  --imgsize: cover;

  --red: #f80e35;
  --yellow: #eedf10;
  --green: #21e985;
  --blue: #0dbde9;
  --violet: #c929f1;

  --clip: inset( 9.85% 8% 52.85% 8% );
  --clip-invert: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%, 0 47.15%, 91.5% 47.15%, 91.5% 9.85%, 8% 9.85%, 8% 47.15%, 0 50%);

  --clip-stage: polygon(91.5% 9.85%, 57% 9.85%, 54% 12%, 17% 12%, 16% 14%, 12% 16%, 8% 16%, 8% 47.15%, 92% 47.15%);
  --clip-stage-invert: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%, 0 47.15%, 91.5% 47.15%, 91.5% 9.85%, 57% 9.85%, 54% 12%, 17% 12%, 16% 14%, 12% 16%, 8% 16%, 8% 47.15%, 0 50%);

  --clip-trainer: inset(14.5% 8.5% 48.2% 8.5%);
  --clip-borders: inset(2.8% 4% round 2.55% / 1.5%);

}

.card__shine,
.card__glare {
  
  will-change: transform, opacity, background-image, background-size,
    background-position, background-blend-mode, filter;
 
}/*

  BASE STYLES / VARIABLES
*/







/*

  SHINE LAYERS

*/


:root {
  
  --card-aspect: 0.718;
  --card-radius: 4.55% / 3.5%;
  --card-edge: hsl(47, 100%, 78%);
  --card-back: hsl(205, 100%, 25%);
  --card-glow: hsl(175, 100%, 90%);

  --sunpillar-1: hsl(2, 100%, 73%);
  --sunpillar-2: hsl(53, 100%, 69%);
  --sunpillar-3: hsl(93, 100%, 69%);
  --sunpillar-4: hsl(176, 100%, 76%);
  --sunpillar-5: hsl(228, 100%, 74%);
  --sunpillar-6: hsl(283, 100%, 73%);

  --sunpillar-clr-1: var(--sunpillar-1);
  --sunpillar-clr-2: var(--sunpillar-2);
  --sunpillar-clr-3: var(--sunpillar-3);
  --sunpillar-clr-4: var(--sunpillar-4);
  --sunpillar-clr-5: var(--sunpillar-5);
  --sunpillar-clr-6: var(--sunpillar-6);

}

.card {

  /* place the card on a new transform layer and
  make sure it has hardward acceleration... we gun'need that! */
  -webkit-transform: translate3d(0px, 0px, 0.01px);
  transform: translate3d(0px, 0px, 0.01px);
  pointer-events: none;
  
  /* make sure the card is above others if it's scaled up */
  z-index: calc(var(--card-scale) * 2);
  
  /* every little helps! */
  will-change: transform, visibility, z-index;

  /* this prevents major problems in firefox, but also causes a bit of
  clipping as the card animates to/from active state. worth it. */
  -webkit-transform-style: preserve-3d;
  transform-style: preserve-3d;
}

.card,
.card * {
  /* outline is a little trick to anti-alias */
  outline: 1px solid transparent;
}

.card:not( .interactive ) .card__translater,
.card:not( .interactive ) .card__rotator,
.card:not( .interactive ) .card__shine,
.card:not( .interactive ) .card__glare {

  /* if this card is not in a framework, we can add simply
    hover effects when it's not "interactive" */
  transition: all 0.3s ease;

}
.card:not( .interactive ):hover {
  
  --pointer-x: 25% !important;
  --pointer-y: 10% !important;
  --card-scale: 1.1 !important;
  --card-opacity: 1 !important;
  --translate-x: 0px !important;
  --translate-y: -10px !important;
  --rotate-x: 7deg !important;
  --rotate-y: -19deg !important;
  --background-x: 44% !important;
  --background-y: 36% !important;
  --pointer-from-center: .9 !important;
  --pointer-from-top: .11 !important;
  --pointer-from-left: .25 !important;
  
}

.card.water       { --card-glow: hsl(192, 97%,  60%); }
.card.fire        { --card-glow: hsl(9,   81%,  59%); }
.card.grass       { --card-glow: hsl(96,  81%,  65%); }
.card.lightning   { --card-glow: hsl(54,  87%,  63%); }
.card.psychic     { --card-glow: hsl(281, 62%,  58%); }
.card.fighting    { --card-glow: rgb(145, 90, 39); }
.card.darkness    { --card-glow: hsl(189, 77%,  27%); }
.card.metal       { --card-glow: hsl(184, 20%,  70%); }
.card.dragon      { --card-glow: hsl(51, 60%, 35%); }
.card.fairy       { --card-glow: hsl(323, 100%, 89%); }

.card,
.card__rotator {
  aspect-ratio: var(--card-aspect);
  border-radius: var(--card-radius);
}

.card.interacting {
  z-index: calc(var(--card-scale) * 120);
}


.card.active .card__translater,
.card.active .card__rotator {
  /* prevent pinch/double-tap zooms on card */
  touch-action: none;
}

.card__translater,
.card__rotator {
  display: grid;
  perspective: 600px;
  will-change: transform, box-shadow;
  transform-origin: center;
  -webkit-transform-origin: center;
  transform-style: preserve-3d;
}

.card__translater {
  width: auto;
  position: relative;

  --translate-z: calc(var(--card-scale) * 150px + 0.01px); /* add 150px to the z-axis to ensure the card is always in front of the others */
  -webkit-transform: translate3d(var(--translate-x), var(--translate-y), var(--translate-z)) scale(var(--card-scale));
  transform: translate3d(var(--translate-x), var(--translate-y), var(--translate-z)) scale(var(--card-scale));
}

.card__rotator {
  -webkit-transform: rotateY(var(--rotate-x)) rotateX(var(--rotate-y));
  -webkit-transform-style: preserve-3d;
  transform-style: preserve-3d;
  transform: rotateY(var(--rotate-x)) rotateX(var(--rotate-y));
  
  /* performance */
  pointer-events: auto;
  /* overflow: hidden; <-- this improves perf on mobile, but breaks backface visibility. */
  /* isolation: isolate; <-- this improves perf, but breaks backface visibility on Chrome. */
}

button.card__rotator {
  /* because the card is a button, there's some default
    browser styles which need to be subdued */
  border: none;
  background: transparent;
  padding: 0;
  -webkit-appearance: none;
  appearance: none;
}

.card__rotator,
.card.active .card__rotator:focus {
  transition: box-shadow 0.4s ease, opacity .33s ease-out;
  box-shadow: 
    0 0 3px -1px transparent, 
    0 0 2px 1px transparent, 
    0 0 5px 0px transparent,
    0px 10px 20px -5px black, 
    0 2px 15px -5px black,
    0 0 20px 0px transparent;
}

.card.active .card__rotator,
.card__rotator:focus {
  box-shadow: 
    0 0 3px -1px white, 
    0 0 3px 1px var(--card-edge), 
    0 0 12px 2px var(--card-glow), 
    0px 10px 20px -5px black, 
    0 0 40px -30px var(--card-glow), 
    0 0 50px -20px var(--card-glow)
}

.card__rotator * {
  width: 100%;
  display: grid;
  grid-area: 1/1;
  aspect-ratio: var(--card-aspect);
  border-radius: var(--card-radius);
  image-rendering: optimizeQuality;
  -webkit-transform-style: preserve-3d;
  transform-style: preserve-3d;
  pointer-events: none;
  overflow: hidden;
}

.card__rotator img {
  height: auto;
}
.card__rotator img:not(.card__back) {
  -webkit-transform: translate3d(0px, 0px, 0.01px);
  transform: translate3d(0px, 0px, 0.01px);
}

.card__back {
  background-color: var(--card-back);
  -webkit-transform: rotateY(180deg) translateZ(1px);
  transform: rotateY(180deg) translateZ(1px);
  backface-visibility: visible;
}

.card__front,
.card__front * {
  backface-visibility: hidden;
}

.card__front {
  opacity: 1;
  transition: opacity 0.33s ease-out;
  -webkit-transform: translate3d(0px, 0px, 0.01px);
  transform: translate3d(0px, 0px, 0.01px);
}

.loading .card__front {
  opacity: 0;
}

.loading .card__back {
  -webkit-transform: rotateY(0deg);
  transform: rotateY(0deg);
}


/**
  
Shine & Glare Effects

**/

.card__shine {

  display: grid;
  transform: translateZ(1px);
  overflow: hidden;
  z-index: 3;

  background: transparent;
  background-size: cover;
  background-position: center;

  filter: brightness(.85) contrast(2.75) saturate(.65);
  mix-blend-mode: color-dodge;

  opacity: var(--card-opacity);

}

.card__shine:before,
.card__shine:after {

  --sunpillar-clr-1: var(--sunpillar-5);
  --sunpillar-clr-2: var(--sunpillar-6);
  --sunpillar-clr-3: var(--sunpillar-1);
  --sunpillar-clr-4: var(--sunpillar-2);
  --sunpillar-clr-5: var(--sunpillar-3);
  --sunpillar-clr-6: var(--sunpillar-4);

  grid-area: 1/1;
  transform: translateZ(1px);
  border-radius: var(--card-radius);

}

.card__shine:after {

  --sunpillar-clr-1: var( --sunpillar-6 );
  --sunpillar-clr-2: var( --sunpillar-1 ); 
  --sunpillar-clr-3: var( --sunpillar-2 );
  --sunpillar-clr-4: var( --sunpillar-3 );
  --sunpillar-clr-5: var( --sunpillar-4 );
  --sunpillar-clr-6: var( --sunpillar-5 );

  transform: translateZ(1.2px);
  
}

.card__glare {

  /* make sure the glare doesn't clip */
  transform: translateZ(1.41px);
  overflow: hidden;

  background-image: radial-gradient(
    farthest-corner circle at var(--pointer-x) var(--pointer-y),
    hsla(0, 0%, 100%, 0.8) 10%,
    hsla(0, 0%, 100%, 0.65) 20%,
    hsla(0, 0%, 0%, 0.5) 90%
  );

  opacity: var(--card-opacity);
  mix-blend-mode: overlay;
  
}






/**

  Masking Effects

**/

.card.masked .card__shine,
.card.masked .card__shine:before,
.card.masked .card__shine:after {

  /** masking image for cards which are masked **/
  -webkit-mask-image: var(--mask);
  mask-image: var(--mask);
	-webkit-mask-size: cover;
  mask-size: cover;
  -webkit-mask-position: center center;
  mask-position: center center;

}

.card[data-rarity="rare holo"] .card__glare:after,
.card[data-rarity="rare holo cosmos"] .card__glare:after,
.card[data-rarity$="reverse holo"] .card__glare:after {
  clip-path: var(--clip);
}

.card[data-rarity="rare holo"][data-subtypes^="stage"] .card__glare:after,
.card[data-rarity="rare holo cosmos"][data-subtypes^="stage"] .card__glare:after,
.card[data-rarity$="reverse holo"][data-subtypes^="stage"] .card__glare:after {
  clip-path: var(--clip-stage);
}

.card[data-rarity="rare holo"][data-supertype="trainer"] .card__glare:after,
.card[data-rarity="rare holo cosmos"][data-supertype="trainer"] .card__glare:after,
.card[data-rarity$="reverse holo"][data-supertype="trainer"] .card__glare:after {
  clip-path: var(--clip-trainer);
}
/*

  REGULAR HOLO

*/

.card[data-rarity="rare holo"][data-subtypes^="stage"] .card__shine,
.card[data-rarity="rare holo"][data-subtypes^="stage"] .card__glare:after {
  clip-path: var(--clip-stage);
}
.card[data-rarity="rare holo"][data-subtypes^="supporter"] .card__shine,
.card[data-rarity="rare holo"][data-subtypes^="supporter"] .card__glare:after,
.card[data-rarity="rare holo"][data-subtypes^="item"] .card__shine,
.card[data-rarity="rare holo"][data-subtypes^="item"] .card__glare:after {
  clip-path: var(--clip-trainer);
}






/*

  SHINE LAYERS

*/

.card[data-rarity="rare holo"] .card__shine {

  --scanlines-space: 1px;
  --scanlines-light: #666;
  --scanlines-dark: black;

  --bars: 3%;
  --bar-color: hsla(0, 0%, 70%, 1);
  --bar-bg: hsla(0, 0%, 0%, 1);

  clip-path: var(--clip);

  background-image: 
    repeating-linear-gradient( 110deg, 
      var(--violet), var(--blue), var(--green), var(--yellow), var(--red), 
      var(--violet), var(--blue), var(--green), var(--yellow), var(--red),
      var(--violet), var(--blue), var(--green), var(--yellow), var(--red)
    ),
    repeating-linear-gradient( 90deg, 
      var(--scanlines-dark) calc(var(--scanlines-space) * 0), var(--scanlines-dark) calc(var(--scanlines-space) * 2),
      var(--scanlines-light) calc(var(--scanlines-space) * 2), var(--scanlines-light) calc(var(--scanlines-space) * 4)
    );

  background-position: 
    calc(((50% - var(--background-x)) * 2.6) + 50%) calc(((50% - var(--background-y)) * 3.5) + 50%),
    center center;

  background-size: 
    400% 400%, 
    cover;

  background-blend-mode: overlay;
  filter: brightness(1.1) contrast(1.1) saturate(1.2);
  mix-blend-mode: color-dodge;

}

.card[data-rarity="rare holo"] .card__shine:before {
  
  content: "";

  background-image:
    repeating-linear-gradient( 90deg, 
      var(--bar-bg) calc(var(--bars)*2), 
      var(--bar-color) calc(var(--bars)*3), 
      var(--bar-bg) calc(var(--bars)*3.5), 
      var(--bar-color) calc(var(--bars)*4), 
      var(--bar-bg) calc(var(--bars)*5), 
      var(--bar-bg) calc(var(--bars)*14)
    ),
    repeating-linear-gradient( 90deg, 
      var(--bar-bg) calc(var(--bars)*2), 
      var(--bar-color) calc(var(--bars)*3), 
      var(--bar-bg) calc(var(--bars)*3.5), 
      var(--bar-color) calc(var(--bars)*4), 
      var(--bar-bg) calc(var(--bars)*5), 
      var(--bar-bg) calc(var(--bars)*10)
    );

  background-position: 
    calc((((50% - var(--background-x)) * 1.65) + 50% ) + (var(--background-y) * 0.5)) var(--background-x), 
    calc((((50% - var(--background-x)) * -0.9) + 50%) - (var(--background-y) * 0.75) ) var(--background-y);

  background-size: 
    200% 200%,
    200% 200%;

  background-blend-mode: screen;
  filter: brightness( 1.15 ) contrast( 1.1 );
  mix-blend-mode: hard-light;

}

.card[data-rarity="rare holo"] .card__shine:after {

  content: "";
    
  background-image: 
    radial-gradient( 
      farthest-corner circle 
        at var(--pointer-x) var(--pointer-y), 
        hsla(0, 0%, 90%, 0.8) 0%, 
        hsla(0, 0%, 78%, 0.1) 25%, 
        hsl(0, 0%, 0%) 90% 
    );
    
  background-position: 
    center center;

  background-size:
    cover;

  mix-blend-mode: luminosity; 
  filter: brightness(0.6) contrast(4);

}

@media screen and (max-width: 900px) {
  .card[data-rarity="rare holo"] .card__shine {
    --scanlines-space: .5px;
  }
}






/*

  GLARE LAYERS

*/

.card[data-rarity="rare holo"] .card__glare {

  opacity: calc( var(--card-opacity) * .8 );
  filter: brightness(0.8) contrast(1.5);
  mix-blend-mode: overlay;

}

.card[data-rarity="rare holo"] .card__glare:after {

  content: "";

  background-image: 
    radial-gradient( 
      farthest-corner circle at var(--pointer-x) var(--pointer-y), 
      hsl(180, 100%, 95%) 5%, 
      hsla(0, 0%, 39%, 0.25) 55%, 
      hsla(0, 0%, 0%, 0.36) 110% 
    );

  mix-blend-mode: overlay;
  filter: brightness(.6) contrast(3);

}










/*

  NO MASK

*/


/*

  RAINBOW (SECRET) HOLO

*/







/*

  SHINE LAYERS

*/

.card[data-rarity="rare rainbow"] .card__shine {

  --r-clr-1: hsl(0, 57%, 37%);
  --r-clr-2: hsl(40, 53%, 39%);
  --r-clr-3: hsl(90, 60%, 35%);
  --r-clr-4: hsl(180, 60%, 35%);
  --r-clr-5: hsl(180, 60%, 35%);
  --r-clr-6: hsl(210, 57%, 39%);
  --r-clr-7: hsl(280, 55%, 31%);

  background-image: 
    linear-gradient(-45deg, var(--r-clr-1), var(--r-clr-5)),
    var(--glitter),
    linear-gradient( -30deg, 
      var(--r-clr-1), var(--r-clr-2), var(--r-clr-3), var(--r-clr-4), var(--r-clr-5), var(--r-clr-6), var(--r-clr-7), 
      var(--r-clr-1), var(--r-clr-2), var(--r-clr-3), var(--r-clr-4), var(--r-clr-5), var(--r-clr-6), var(--r-clr-7), 
      var(--r-clr-1), var(--r-clr-2), var(--r-clr-3), var(--r-clr-4), var(--r-clr-5), var(--r-clr-6), var(--r-clr-7), 
      var(--r-clr-1)
    );

  background-blend-mode: luminosity, soft-light;

  background-size: 
    200% 200%, 
    var(--glittersize) var(--glittersize), 
    400% 400%;
  
  background-position: 
    calc( 25% + (50% * var(--pointer-from-left) )) calc( 25% + (50% * var(--pointer-from-top) )), 
    center center, 
    calc( 25% + (var(--pointer-x) / 2 ) ) calc( 25% + (var(--pointer-y) / 2 ) );
  
  filter: brightness(calc((var(--pointer-from-center)*0.25) + 0.6))  contrast(2.2) saturate(0.75);

}

.card[data-rarity="rare rainbow"] .card__shine:after {

  content: "";

  -webkit-mask-image: none !important;
  mask-image: none !important;

  background-image: 
    var(--glitter),
    linear-gradient( -60deg, 
        var(--r-clr-1), var(--r-clr-2), var(--r-clr-3), var(--r-clr-4), var(--r-clr-5), var(--r-clr-6), var(--r-clr-7), 
        var(--r-clr-1), var(--r-clr-2), var(--r-clr-3), var(--r-clr-4), var(--r-clr-5), var(--r-clr-6), var(--r-clr-7), 
        var(--r-clr-1), var(--r-clr-2), var(--r-clr-3), var(--r-clr-4), var(--r-clr-5), var(--r-clr-6), var(--r-clr-7), 
        var(--r-clr-1)
    );

    background-blend-mode: soft-light;
    background-size: var(--glittersize) var(--glittersize), 400% 400%;
    background-position: center center, var(--pointer-x) var(--pointer-y);

    filter: brightness(calc((var(--pointer-from-center)*0.3) + 0.55)) contrast(2) saturate(1);
    mix-blend-mode: color-dodge;

}

.card[data-rarity="rare rainbow"] .card__shine:before {

  content: "";

  background-image: var(--foil);
  background-size: var(--imgsize);
  background-position: center center;
  filter: brightness(2.5) contrast(1);

  opacity: calc((var(--pointer-from-center) + 0.4 ) * 0.6 );
  background-blend-mode: difference;
  mix-blend-mode: darken;

}






/*

  GLARE LAYERS

*/

.card[data-rarity="rare rainbow"] .card__glare {
	
	background-image: 
    radial-gradient( 
      farthest-corner circle at var(--pointer-x) var(--pointer-y), 
      hsl(0,0%,80%), 
      hsla(187, 10%, 85%, 0.25) 30%, 
      hsl(197, 6%, 25%) 120% 
    );

	filter: brightness(.9) contrast(1.75);
	opacity: calc( var(--pointer-from-center) * 0.9 );
  mix-blend-mode: hard-light;

}










/*

  NO MASK

*/


.card:not(.masked)[data-rarity="rare rainbow"] .card__shine {

  --foil: url("/holo/img/illusion-mask.png"); 
  --imgsize: 33%;

}/*

  SECRET RARE (GOLD)

*/




/*

  SHINE LAYERS

*/

.card[data-rarity="rare secret"] .card__shine,
.card[data-set="swshp"][data-number="swsh145"] .card__shine {

  --shift: 1px;
  --imgsize: cover;

  background-image:
    var(--glitter), 
    var(--glitter), 
    conic-gradient( 
      var(--sunpillar-clr-4), 
      var(--sunpillar-clr-5),
      var(--sunpillar-clr-6), 
      var(--sunpillar-clr-1), 
      var(--sunpillar-clr-4) 
    ), 
    radial-gradient( 
      farthest-corner circle at var(--pointer-x) var(--pointer-y), 
      hsla(150, 00%, 0%, .98) 10%, 
      hsla(0, 0%, 95%, .15) 90% 
    );

  background-size: var(--glittersize) var(--glittersize), var(--glittersize) var(--glittersize), cover, cover;
  background-position: 45% 45%, 55% 55%, center center, center center;
  background-blend-mode: soft-light, hard-light, overlay;
  mix-blend-mode: color-dodge;
  filter: brightness(calc( 0.4 + (var(--pointer-from-center) * 0.2) )) contrast(1) saturate(2.7);

}

.card[data-rarity="rare secret"] .card__shine:before,
.card[data-set="swshp"][data-number="swsh145"] .card__shine:before {
  
  content: "";
  -webkit-mask-image: none !important;
  mask-image: none !important;

  background-image:
    var(--foil), 
    linear-gradient( 45deg, hsl(46, 95%, 50%), hsl(52, 100%, 69%) ), 
    radial-gradient( 
      farthest-corner circle at var(--pointer-x) var(--pointer-y), 
      hsla(10, 20%, 90%, 0.95) 10%, 
      hsl(0, 0%, 0%) 70% 
    );

  background-size: var(--imgsize), cover, cover;
  background-position: center center, center center, center center;
  background-blend-mode: hard-light, multiply;

  mix-blend-mode: lighten;
  filter: brightness(1.25) contrast(1.25) saturate(0.35);
  opacity: .8;

}

.card[data-rarity="rare secret"] .card__shine:after,
.card[data-set="swshp"][data-number="swsh145"] .card__shine:after {

  content: "";

  -webkit-mask-image: none !important;
  mask-image: none !important;

  background-image: var(--glitter);
  background-size: var(--glittersize) var(--glittersize);
  background-position: calc(50% - ((var(--shift)*2) * var(--pointer-from-left)) + var(--shift)) calc(50% - ((var(--shift)*2) * var(--pointer-from-top)) + var(--shift));

  filter: brightness(calc((var(--pointer-from-center)*0.6) + 0.6)) contrast(1.5);
  mix-blend-mode: overlay;

}






/*

  GLARE LAYERS

*/

.card[data-rarity="rare secret"] .card__glare,
.card[data-set="swshp"][data-number="swsh145"] .card__glare {
	
	background-image: 
    radial-gradient( 
      farthest-corner circle at var(--pointer-x) var(--pointer-y), 
      hsla(45, 8%, 80%, 0.3) 0%, 
      hsl(22, 15%, 12%) 180%
    );

	filter: brightness(1.3) contrast(1.5);
  mix-blend-mode: hard-light;

}










/*

  NO MASK

*/


.card:not(.masked)[data-rarity="rare secret"] .card__shine,
.card:not(.masked)[data-set="swshp"][data-number="swsh145"] .card__shine {

  --foil: url("/holo/img/geometric.png"); 
  --imgsize: 33%;
  
  filter: brightness( calc( ( var( --pointer-from-center ) * 0.3 ) + 0.2 ) ) contrast(2) saturate(0.75);

}



























/* styles.css */
@charset "UTF-8";
:root {
  /* MemeCoin: an old gold, warmer and deeper than the UI's --gold and EXPERT's #f2b53a, so the currency never reads as either. */
  --coin-highlight: #fff1b8;
  --coin-light: #ffe7a0;
  --coin-base: #f0b83a;
  --coin-shade: #b87708;
  --coin-rim: #9a6208;
  --coin-ink: #6b3d00;
  /* The small seal: flat colours, one step deeper on the light theme so it holds on white. */
  --coin-glyph-rim: #9a6208;
  --coin-glyph-face: #f0b83a;
  --coin-glyph-ink: #6b3d00;
  --bg: #eef3ec;
  --ink: #3d4a45;
  --ink-soft: #6f7d77;
  --band-a: #c5f03c;
  --band-b: #35e0b0;
  --btn-a: #ff8a3d;
  --btn-b: #ffcf33;
  --accent: #19b88a;
  --title-a: #ff7a2f;
  --title-b: #f5b700;
  --tile: #ffffff;
  --common: #9aa7a1;
  --rare: #2f9bff;
  --epic: #a45bff;
  --legendary: #ff9f1a;
  --mythic: #3ff0c8;
  color-scheme: light;
}

* { box-sizing: border-box; }
/* A hidden element stays hidden: phone layouts give .pack-closed its own display, which used to beat [hidden] and left the
   closed booster on screen above the opened cards (app) or under "Welcome back" (home page). */
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 500 17px/1.6 "M PLUS Rounded 1c", "Nunito", system-ui, sans-serif;
  /* clip, not hidden: hidden turns body into a scroll container on iOS (sticky bars and momentum scrolling suffer). */
  overflow-x: clip;
  position: relative;
}

/* soft floating light spots */
body::before {
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background:
    radial-gradient(circle at 12% 28%, rgba(255,255,255,.95) 0 22px, transparent 40px),
    radial-gradient(circle at 88% 42%, rgba(255,255,255,.9) 0 16px, transparent 34px),
    radial-gradient(circle at 70% 78%, rgba(255,255,255,.85) 0 26px, transparent 46px),
    radial-gradient(circle at 22% 88%, rgba(255,255,255,.8) 0 14px, transparent 30px),
    radial-gradient(circle at 50% 60%, rgba(255,255,255,.6) 0 10px, transparent 24px);
  filter: blur(6px);
}
body > * { position: relative; z-index: 1; }

a { color: var(--accent); font-weight: 700; }

.wrap { max-width: 1080px; margin: 0 auto; padding: 0 16px; }

/* diagonal header band */
.band {
  background: linear-gradient(100deg, var(--band-a), var(--band-b));
  clip-path: polygon(0 0, 100% 0, 100% 38%, 0 100%);
  height: 190px; margin-bottom: -110px;
}
.band .wrap { display: flex; justify-content: space-between; align-items: flex-start; padding-top: 16px; }

.logo {
  display: inline-block; text-decoration: none; line-height: .95; text-align: center;
  font-weight: 900; font-size: 30px; letter-spacing: -.02em; color: #ffe14d;
  -webkit-text-stroke: 5px #1f6b3a; paint-order: stroke fill;
  transform: rotate(-4deg);
}
.logo small { display: block; font-size: 15px; color: #fff; -webkit-text-stroke: 3px #1f6b3a; letter-spacing: .02em; margin-top: 2px; }

.lang {
  background: #fff; color: var(--accent); border: 3px solid var(--band-b); border-radius: 999px;
  padding: 8px 24px; font-weight: 800; font-size: 18px; text-decoration: none;
  box-shadow: 0 8px 22px rgba(31,107,58,.18);
}

/* hero */
.hero { text-align: center; padding: 70px 0 10px; }
h1 {
  margin: 0; font-weight: 900; font-style: italic; line-height: 1.12;
  font-size: clamp(38px, 7vw, 68px); letter-spacing: -.01em;
  background: linear-gradient(90deg, var(--title-a), var(--title-b));
  -webkit-background-clip: text; background-clip: text; color: transparent;
  padding: 0 .18em .14em;
}
.hero .sub { font-size: clamp(22px, 3.4vw, 32px); font-weight: 800; color: #97a39e; margin: 6px 0 0; }
.lead { max-width: 36em; margin: 18px auto 0; color: var(--ink-soft); font-size: 18px; }
.rule { height: 6px; border-radius: 6px; margin: 34px 0; background: linear-gradient(90deg, var(--btn-a), var(--btn-b), var(--band-b)); }

/* fanned hero pack */
.fan { display: flex; justify-content: center; margin: 34px auto 0; height: 250px; max-width: 460px; position: relative; }
.fan .card { position: absolute; width: 150px; top: 20px; }
.fan .card:nth-child(1) { transform: translateX(-120px) rotate(-12deg); }
.fan .card:nth-child(2) { transform: translateY(-14px); z-index: 2; width: 168px; }
.fan .card:nth-child(3) { transform: translateX(120px) rotate(12deg); }

/* section titles */
h2 { text-align: center; font-weight: 900; color: #5b6863; font-size: clamp(30px, 5vw, 46px); line-height: 1.15; margin: 0 0 30px; }
h3 { font-weight: 800; color: var(--ink); font-size: 20px; margin: 22px 0 6px; }
main section { padding: 34px 0 20px; }

/* tiles */
.tile {
  position: relative; background: var(--tile); border-radius: 26px; padding: 10px 10px 16px;
  box-shadow: 0 14px 34px rgba(61,74,69,.12), 0 2px 0 rgba(255,255,255,.9) inset;
}
.tile-media { background: linear-gradient(180deg, #f4f7f2, #e9efe7); border-radius: 20px; padding: 18px 16px 26px; position: relative; display: grid; place-items: center; }
.tile-title { text-align: center; font-weight: 800; color: #5b6863; font-size: 18px; margin: 12px 6px 4px; line-height: 1.3; }
.tile-sub { text-align: center; color: var(--ink-soft); font-size: 14px; margin: 0 8px; line-height: 1.45; }
.chip { position: absolute; top: -12px; left: -6px; z-index: 3; background: #6f7d77; color: #fff; font-size: 13px; font-weight: 800; padding: 3px 12px; border-radius: 999px; box-shadow: 0 4px 10px rgba(0,0,0,.15); }
.pill { position: absolute; right: 10px; bottom: -12px; color: #fff; font-size: 13px; font-weight: 800; padding: 3px 12px; border-radius: 999px; background: var(--c); box-shadow: 0 4px 10px rgba(0,0,0,.12); }
.r-common { --c: var(--common); }
.r-rare { --c: linear-gradient(90deg, #52b6ff, #2f7bff); }
.r-epic { --c: linear-gradient(90deg, #c07bff, #8a3dff); }
.r-legendary { --c: linear-gradient(90deg, #ffc233, #ff8a1a); }
.r-mythic { --c: linear-gradient(90deg, #3ff0c8, #1a8cff 55%, #7a3dff); }

.grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 22px 18px; }

/* meme card face, layered under the holo shine/glare from /holo/holo.css */
.card {
  --pointer-x: 50%; --pointer-y: 50%; --pointer-from-center: 0; --pointer-from-top: .5; --pointer-from-left: .5;
  --card-opacity: 0; --card-scale: 1; --translate-x: 0px; --translate-y: 0px;
  --rotate-x: 0deg; --rotate-y: 0deg; --background-x: 50%; --background-y: 50%;
  /* the rarity frames are 1744 × 2336: the card box matches them so the artwork is never stretched */
  --card-aspect: .7466;
  --card-radius: 4.6% / 3.4%;
  /* the regular holo only shines on the art window */
  --clip: inset(10% 7% 47.9% 7% round 1%);
  width: 100%; max-width: 170px;
}
.card.f-legendary { --card-glow: hsl(42, 100%, 60%); --card-edge: hsl(47, 100%, 78%); }
.card.f-epic { --card-glow: hsl(280, 90%, 70%); }
.card__rotator { cursor: pointer; }
.card__rotator { touch-action: pan-y; }
/* cqw sizes inside the face follow the card width */
.card .card__front { container-type: inline-size; }

/* mythic, the rarity above legendary: its halo goes turquoise, blue, then violet */
.card.f-mythic { --card-glow: hsl(170, 85%, 62%); --card-edge: hsl(186, 100%, 82%); }
.card.f-mythic .card__rotator { animation: mythic-glow 2.8s ease-in-out infinite; }
@keyframes mythic-glow {
  0%, 100% { box-shadow: 0 0 16px rgba(63,240,200,.6), 0 0 34px rgba(26,140,255,.4), 0 10px 20px -8px rgba(0,0,0,.45); }
  50% { box-shadow: 0 0 26px rgba(122,61,255,.8), 0 0 56px rgba(63,240,200,.55), 0 10px 20px -8px rgba(0,0,0,.45); }
}

/* waitlist */
.join { max-width: 560px; margin: 0 auto; text-align: center; padding: 22px 20px 20px; }
.join .tag { display: inline-block; background: linear-gradient(90deg, #ff6fa8, #ff8a3d); color: #fff; font-weight: 800; font-size: 13px; padding: 3px 14px; border-radius: 999px; margin-bottom: 12px; }
.join p.what { margin: 0 0 16px; color: var(--ink-soft); font-weight: 700; }
.join input[type=email] {
  width: 100%; font: inherit; font-weight: 700; color: var(--ink); background: #f2f6f0; border: 2px solid #dfe7dc;
  border-radius: 999px; padding: 14px 20px; text-align: center;
}
.join input[type=email]:focus { outline: none; border-color: var(--band-b); background: #fff; }
.btn {
  display: block; width: 100%; margin-top: 12px; border: 0; border-radius: 999px; padding: 14px 20px; cursor: pointer;
  text-align: center;
  font: inherit; font-weight: 900; font-size: 22px; color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,.15);
  background: linear-gradient(90deg, var(--btn-a), var(--btn-b));
  box-shadow: 0 8px 20px rgba(255,138,61,.35);
}
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .65; cursor: progress; }
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.form-msg { min-height: 1.5em; margin: 10px 0 0; font-weight: 700; font-size: 15px; }
.form-msg.ok { color: var(--accent); }
.form-msg.err { color: #e5484d; }

/* how it works */
.steps { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; }
.step { text-align: center; padding: 24px 18px 20px; }
.step .num { width: 54px; height: 54px; margin: 0 auto 10px; border-radius: 50%; display: grid; place-items: center; font-weight: 900; font-size: 26px; color: #fff; background: linear-gradient(135deg, var(--band-a), var(--band-b)); box-shadow: 0 6px 14px rgba(53,224,176,.4); }
.step h3 { margin: 0 0 6px; }
.step p { margin: 0; color: var(--ink-soft); font-size: 15px; }
.tiers { display: flex; justify-content: center; flex-wrap: wrap; gap: 8px; margin: 22px 0 0; padding: 0; list-style: none; }
.tiers li { position: static; }

.prose-tile { max-width: 760px; margin: 0 auto; padding: 26px 28px; }
.prose-tile p, .prose-tile li { color: var(--ink-soft); }
.prose-tile > :first-child { margin-top: 0; }
.note { text-align: center; color: var(--ink-soft); font-size: 14px; margin-top: 22px; }

.faq { max-width: 760px; margin: 0 auto; display: grid; gap: 14px; }
.faq .tile { padding: 18px 22px; }
.faq h3 { margin: 0 0 4px; font-size: 18px; }
.faq p { margin: 0; color: var(--ink-soft); }

footer { text-align: center; color: var(--ink-soft); font-size: 14px; padding: 40px 16px 50px; }

@media (max-width: 760px) {
  .band { height: 150px; margin-bottom: -80px; }
  .logo { font-size: 24px; }
  .lang { padding: 6px 18px; font-size: 16px; }
  .hero { padding-top: 56px; }
  .fan { height: 200px; }
  .fan .card { width: 118px; }
  .fan .card:nth-child(2) { width: 132px; }
  .fan .card:nth-child(1) { transform: translateX(-92px) rotate(-12deg); }
  .fan .card:nth-child(3) { transform: translateX(92px) rotate(12deg); }
  .grid { gap: 18px 10px; }
  .tile { border-radius: 20px; padding: 6px 6px 12px; }
  .tile-media { padding: 12px 8px 20px; border-radius: 16px; }
  .tile-title { font-size: 14px; }
  .tile-sub { display: none; }
  .pill { font-size: 11px; padding: 2px 8px; right: 6px; }
  .steps { grid-template-columns: 1fr; }
  .prose-tile { padding: 22px 18px; }
}

/* rarity glow: legendary cards burn gold, rarer tiers get a fainter halo */
.card.f-rare .card__rotator { box-shadow: 0 0 10px rgba(47,155,255,.35), 0 0 20px rgba(47,155,255,.2), 0 10px 20px -8px rgba(0,0,0,.5); }
.card.f-epic .card__rotator { box-shadow: 0 0 12px rgba(164,91,255,.4), 0 0 24px rgba(164,91,255,.22), 0 10px 20px -8px rgba(0,0,0,.5); }
.card.f-legendary .card__rotator { animation: legend-glow 2.8s ease-in-out infinite; }
@keyframes legend-glow {
  0%, 100% { box-shadow: 0 0 16px rgba(255,170,0,.7), 0 0 34px rgba(255,140,0,.4), 0 10px 20px -8px rgba(0,0,0,.45); }
  50% { box-shadow: 0 0 26px rgba(255,190,20,.95), 0 0 56px rgba(255,150,0,.55), 0 10px 20px -8px rgba(0,0,0,.45); }
}
@media (prefers-reduced-motion: reduce) {
  .card.f-legendary .card__rotator, .card.f-mythic .card__rotator { animation: none; }
}

/* shiny: the grey variant any card can come in, like a shiny Pokémon; its face is in /cards/face.css */
.card.f-shiny .card__rotator { box-shadow: inset 0 0 0 1px rgba(233,193,90,.55), 0 0 14px rgba(233,193,90,.35), 0 0 30px rgba(0,0,0,.45), 0 10px 20px -8px rgba(0,0,0,.6); }
.pill.r-shiny, .tiers .r-shiny { --c: linear-gradient(90deg, #0d0e10, #2c2f34); color: #f3d27a; box-shadow: inset 0 0 0 1px #d7a93c, 0 0 10px rgba(233,193,90,.4); }

/* free pack */
.pack-stage { max-width: 620px; margin: 0 auto; padding: 26px 20px 22px; text-align: center; }
.pack-closed .what { color: var(--ink-soft); font-weight: 700; margin: 18px 0 14px; }
.pack-error { color: #e5484d; font-weight: 700; min-height: 1.4em; margin: 8px 0 0; }
.booster {
  display: block; margin: 0 auto; width: 190px; aspect-ratio: 508 / 718; border: 0; cursor: pointer; position: relative;
  background: none; padding: 0;
  filter: drop-shadow(0 16px 18px rgba(0,0,0,.35));
  transition: transform .2s ease;
  animation: booster-float 3.2s ease-in-out infinite;
}
.booster:hover { transform: translateY(-4px) rotate(-1.5deg); }
/* the glint only sweeps over the foil, never over the transparent corners of the image */
.booster::before {
  content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none; mix-blend-mode: soft-light;
  background: linear-gradient(115deg, transparent 30%, rgba(255,255,255,.9) 45%, transparent 60%); background-size: 250% 100%; animation: booster-shine 4.2s ease-in-out infinite;
  -webkit-mask: url(/pack-front.webp?v=7cc6581117) center / 100% 100% no-repeat; mask: url(/pack-front.webp?v=7cc6581117) center / 100% 100% no-repeat;
}
.booster.opening::before { opacity: 0; }
@keyframes booster-float { 0%, 100% { translate: 0 0; } 50% { translate: 0 -6px; } }
/* The glint fades in and out at the ends of its sweep, then rests: the loop never cuts it off mid-pack. */
@keyframes booster-shine {
  0% { background-position: 130% 0; opacity: 0; }
  8% { opacity: 1; }
  52% { opacity: 1; }
  60% { background-position: -130% 0; opacity: 0; }
  100% { background-position: -130% 0; opacity: 0; }
}

.pack-status { color: var(--ink-soft); font-weight: 700; margin: 0 0 12px; min-height: 1.2em; }
.viewer { display: flex; align-items: center; justify-content: center; gap: 14px; position: relative; }
/* While a finger drags the card, the browser must not also scroll the page under it (see pack.js's "locked"). */
.viewer.locked { touch-action: none; }
.slot { position: relative; width: 230px; display: grid; place-items: center; }
.slot .card { max-width: 230px; }
/* Same slide as the app's pack viewer (public/app/app.css): short, flat, transform/opacity only. A card leaving
   under a finger is only hidden, not removed (see pack.js's `drop`), so it keeps no layout space of its own. */
.viewer.sliding { overflow-x: clip; overflow-y: visible; overflow-clip-margin: 0; }
.viewer.sliding > .slot { will-change: transform, opacity; }
.slot.moving { position: absolute; inset-block-start: 0; inset-inline: 0; margin-inline: auto; will-change: transform, opacity; }
.slot.gone { position: absolute; inset-block-start: 0; inset-inline: 0; margin-inline: auto; opacity: 0 !important; pointer-events: none; }
.nav { width: 44px; height: 44px; border-radius: 50%; border: 0; background: #fff; box-shadow: 0 6px 16px rgba(61,74,69,.18); font-size: 26px; font-weight: 900; color: var(--accent); cursor: pointer; flex: none; }
.counter { font-weight: 800; color: var(--ink-soft); margin: 0 0 12px; }
/* The pack's counter: the position in big, then what is left to see, with an arrow that nudges towards the next. */
.counter { display: flex; align-items: center; justify-content: center; gap: 10px; min-height: 34px; }
.counter .ct-num { font-size: 26px; font-weight: 900; color: var(--heading, #fff); font-variant-numeric: tabular-nums; line-height: 1; }
.counter .ct-num span { font-size: 16px; color: var(--muted); margin-left: 1px; }
.counter .ct-left { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 999px; font-size: 15px; color: var(--on-gold, #1a1205); background: var(--gold-grad, #ffc93c); }
.counter .ct-left::after { content: "→"; animation: ct-nudge 1.1s ease-in-out infinite; }
.counter .ct-left.last { background: transparent; color: var(--gold-text, #ffc93c); box-shadow: inset 0 0 0 2px currentColor; }
.counter .ct-left.last::after { content: none; }
@keyframes ct-nudge { 50% { transform: translateX(4px); } }
@media (prefers-reduced-motion: reduce) { .counter .ct-left::after { animation: none; } }
.dots { display: flex; justify-content: center; gap: 8px; }
.pager { display: flex; align-items: center; justify-content: center; gap: 16px; margin-top: 18px; }
.nav:disabled { opacity: .35; cursor: default; box-shadow: none; }
.viewer { touch-action: pan-y; }
.dots button { width: 10px; height: 10px; border-radius: 50%; border: 0; padding: 0; background: #cfd8cc; cursor: pointer; }
.dots button[aria-current="true"] { background: var(--accent); transform: scale(1.3); }

/* the one flourish: Epic, Legendary and Shiny cards turn over slowly the first time */
.slot.reveal .card { animation: reveal-turn 1.5s cubic-bezier(.16,.8,.24,1) both; }
.slot.reveal-rare .card { animation-duration: .9s; }
.slot.reveal-epic .card { animation-duration: 1.3s; }
.slot.reveal-legendary .card, .slot.reveal-shiny .card { animation-duration: 1.8s; }
.slot.reveal-mythic .card { animation-duration: 2s; }
.slot.reveal-legendary .burst, .slot.reveal-shiny .burst, .slot.reveal-mythic .burst { animation-duration: 2s; }
.reveal-rare .burst { background: radial-gradient(circle, rgba(47,155,255,.6), transparent 62%); }

/* suspense: the card back glows in the tier's colour, swelling and trembling until it turns */
.slot.suspense { --aura: 47,155,255; }
.slot.suspense-epic { --aura: 164,91,255; }
.slot.suspense-legendary { --aura: 255,180,20; }
.slot.suspense-mythic { --aura: 63,240,200; }
.slot.suspense-shiny { --aura: 220,205,160; }
.card-back {
  width: 100%; aspect-ratio: 63 / 88; border-radius: 5% / 3.6%; position: relative; display: grid; place-items: center;
  background: repeating-linear-gradient(135deg, rgba(255,255,255,.05) 0 2px, transparent 2px 9px), linear-gradient(160deg, #2a2f3a, #12151c);
  box-shadow: inset 0 0 0 3px rgba(255,255,255,.12), 0 0 0 rgba(var(--aura), 0);
  animation: back-charge var(--suspense) cubic-bezier(.5,0,.9,.6) forwards, back-tremble .12s linear infinite;
}
.card-back .b-logo { font-weight: 900; font-size: 26px; line-height: .95; text-align: center; color: #ffe14d; -webkit-text-stroke: 4px #1f6b3a; paint-order: stroke fill; transform: rotate(-4deg); }
.card-back .b-logo small { display: block; font-size: 13px; color: #fff; -webkit-text-stroke: 3px #1f6b3a; }
@keyframes back-charge {
  from { box-shadow: inset 0 0 0 3px rgba(255,255,255,.12), 0 0 0 rgba(var(--aura), 0); filter: brightness(1); }
  to { box-shadow: inset 0 0 0 3px rgba(var(--aura), .9), 0 0 38px 10px rgba(var(--aura), .85); filter: brightness(1.35); }
}
@keyframes back-tremble { 0%, 100% { translate: 0 0; } 25% { translate: -1px .5px; } 75% { translate: 1px -.5px; } }
.slot .burst { position: absolute; inset: -30%; border-radius: 50%; opacity: 0; pointer-events: none; }
.slot.reveal .burst { animation: reveal-burst 1.6s ease-out both; }
.reveal-epic .burst { background: radial-gradient(circle, rgba(164,91,255,.75), transparent 62%); }
.reveal-legendary .burst { background: radial-gradient(circle, rgba(255,190,20,.85), transparent 62%); }
.reveal-mythic .burst { background: radial-gradient(circle, rgba(63,240,200,.85), rgba(122,61,255,.35) 45%, transparent 66%); }
.reveal-shiny .burst { background: radial-gradient(circle, rgba(230,210,150,.8), rgba(40,40,44,.35) 45%, transparent 65%); }
@keyframes reveal-turn {
  0% { transform: perspective(900px) rotateY(180deg) scale(.82); filter: brightness(.2); }
  55% { transform: perspective(900px) rotateY(20deg) scale(1.06); filter: brightness(1.8); }
  100% { transform: none; filter: none; }
}
@keyframes reveal-burst { 0% { opacity: 0; transform: scale(.4); } 45% { opacity: 1; } 100% { opacity: 0; transform: scale(1.3); } }

.claim { margin-top: 22px; padding-top: 18px; border-top: 1px dashed #dfe7dc; }
.claim p { margin: 0 0 12px; font-weight: 700; color: var(--ink); }
/* The Google button is a light-scheme iframe: on a dark page Chrome paints an opaque white box behind it unless its scheme matches. */
#g-btn { display: flex; justify-content: center; min-height: 44px; color-scheme: light; }
#g-btn[hidden], .claim[hidden] { display: none; }
.claim .claim-gift { margin: 0 auto 28px; }
.claim-msg { color: var(--accent) !important; min-height: 1.3em; margin: 10px 0 0 !important; }
/* The sign-in under the last card of the welcome pack: the moment a visitor has seen all five cards. The claim block
   below keeps only its message line meanwhile, so one sign-in shows at a time. */
.last-claim { margin: 16px auto 0; max-width: 420px; padding: 14px 16px 16px; border-radius: 18px; text-align: center;
  background: color-mix(in srgb, var(--gold) 12%, var(--surface)); box-shadow: inset 0 0 0 2px var(--gold); }
.last-claim b { display: block; margin-bottom: 12px; font-size: 18px; line-height: 1.3; color: var(--text); }
.last-claim[hidden] { display: none; }
/* Docked like the claim block: on a laptop screen it ran past the bottom, the e-mail button cut off. */
.hero-pack .last-claim { position: sticky; bottom: 12px; z-index: 6; }
#g-btn-last { display: flex; justify-content: center; min-height: 44px; color-scheme: light; }
/* Once the pack is open, the sign-in is docked at the bottom of the screen, under the card being looked at, instead
   of waiting below the fold for a visitor who does not know it is there. The gold callout says what it is worth, its
   arrow points at the Google button, and the e-mail way in sits right under it. */
.hero-pack .pack-open .claim { position: sticky; bottom: 0; z-index: 6; margin: 18px -18px -18px; padding: 14px 18px calc(12px + env(safe-area-inset-bottom));
  border-top: 0; border-radius: 22px 22px 0 0; background: var(--surface); box-shadow: 0 -1px 0 var(--line), 0 -14px 28px -10px rgba(0,0,0,.55); }
.hero-pack .pack-open .claim-msg:empty { display: none; }
.pack-open .claim .claim-gift { width: 100%; margin: 0 auto 20px; padding: 9px 12px 17px; }
.pack-open .claim .claim-gift b { font-size: 18px; white-space: nowrap; }
.pack-open .claim .claim-gift span { display: none; }
.pack-open .claim .email-btn { min-height: 40px; margin-top: 8px; padding: 9px 16px; font-size: 15px; }
/* The card gives way to the dock on a short screen: above it, the header, the title, the counter and the pager take
   about 340 px and the dock about 195; a card is 1.34 times as tall as it is wide. */
@media (min-width: 561px) {
  .hero-pack .pack-open .slot, .hero-pack .pack-open .slot .card { width: clamp(170px, calc((100vh - 535px) / 1.34), 230px); max-width: none; }
}
.at-last .claim, .hero-pack .pack-open.at-last .claim { margin-top: 0; padding: 0; border-top: 0; background: none; box-shadow: none; }
.at-last .claim > :not(.claim-msg), .at-last #g-btn { display: none; }
/* Phones: the card leaves the pager in view above the dock. On the last card the dock grows: the line
   about keeping these five cards comes back and the callout beats (the computer shows .last-claim there instead). */
@media (max-width: 560px) {
  .hero-pack .pack-stage { scroll-margin-top: 68px; }
  .hero-pack .pack-open .claim { margin: 12px -16px -14px; padding: 12px 14px calc(10px + env(safe-area-inset-bottom)); }
  .pack-open .claim .claim-gift b { font-size: clamp(15px, 4.6vw, 18px); }
  .pack-open.at-end .claim .claim-gift { padding: 12px 14px 20px; animation: ly-callout-in .45s cubic-bezier(.2,1.4,.4,1) both, claim-beat 1.6s ease-in-out .45s infinite; }
  .pack-open.at-end .claim .claim-gift b { font-size: 21px; white-space: normal; }
  /* The card gives way to the dock on a short screen: header, counter, pager and dock take about 376 px, and a card
     is 1.34 times as tall as it is wide. */
  .hero-pack .pack-open .slot, .hero-pack .pack-open .slot .card {
    width: clamp(130px, calc((100vh - 376px) / 1.34), 190px); max-width: none; }
  @supports (height: 100svh) {
    .hero-pack .pack-open .slot, .hero-pack .pack-open .slot .card { width: clamp(130px, calc((100svh - 376px) / 1.34), 190px); }
  }
  .pack-open.at-end .claim .claim-gift span { display: block; }
}
/* 375×560 (an iPhone SE under Safari's bars): the e-mail way in becomes a link, so the dock leaves the pager in view. */
@media (max-width: 560px) and (max-height: 620px) {
  .pack-open.at-end .claim .claim-gift span { display: none; }
  .pack-open .claim .claim-gift, .pack-open.at-end .claim .claim-gift { margin-bottom: 18px; padding: 7px 12px 15px; }
  .pack-open.at-end .claim .claim-gift b { font-size: clamp(15px, 4.6vw, 18px); white-space: nowrap; }
  .pack-open .claim .email-btn { min-height: 32px; margin-top: 2px; padding: 4px 12px; background: none; box-shadow: none;
    text-decoration: underline; text-underline-offset: 3px; }
}
@keyframes claim-beat { 50% { transform: scale(1.03); } }
@media (prefers-reduced-motion: reduce) { .pack-open.at-end .claim .claim-gift { animation: none; } }

/* market */
.market-intro { max-width: 640px; margin: -10px auto 26px; text-align: center; color: var(--ink-soft); font-size: 18px; }
.market-note { text-align: center; color: var(--ink-soft); font-size: 14px; margin-top: 18px; }
/* The MemeCoin seal ("Le Sceau") drawn around the letter M: face, inner ring, brown rim. Same geometry as COIN_SVG in /app/app.js (24-unit coin). */
/* "middle" centres the disc on the x-height of the sentence around it, at any font size. An inline-grid takes its
   baseline from the M inside it, so a baseline offset dropped the disc half a line below the words. */
/* Centred on the capitals of the words around it (« MemeCoins »): "middle" alone sits on the x-height and reads a
   little low next to a capital. The lift is in the coin's own em, so it scales with the text. */
.coin { display: inline-grid; place-items: center; width: 2em; height: 2em; font-size: .55em; font-weight: 900; line-height: 1; color: var(--coin-glyph-ink); vertical-align: middle; position: relative; top: -.19em; border-radius: 50%;
  background: radial-gradient(closest-side, var(--coin-glyph-face) 0 62.5%, color-mix(in srgb, #ffe7a0 70%, var(--coin-glyph-face)) 62.5% 70.8%, var(--coin-glyph-face) 70.8% 83.3%, var(--coin-glyph-rim) 83.3% 95.8%, transparent 95.8%); }

@media (max-width: 760px) {
  .slot, .slot .card { width: 190px; max-width: 190px; }
  .viewer { gap: 8px; }
  .nav { width: 38px; height: 38px; font-size: 22px; }
}
@media (prefers-reduced-motion: reduce) {
  .booster, .booster::before, .slot.reveal .card, .slot.reveal .burst, .card-back { animation: none; }
}

/* one image, cut in two along the tear line: the foil body and the crimped top strip */
.booster .b-body, .booster .b-top { position: absolute; inset: 0; background: url(/pack-front.webp?v=7cc6581117) center / 100% 100% no-repeat; }
/* the French home deals Memes FR: its booster wears the Memes FR sachet */
.booster.fr .b-body, .booster.fr .b-top { background-image: url(/pack-front-fr.webp?v=194a1166ad); }
.booster.fr::before { -webkit-mask-image: url(/pack-front-fr.webp?v=194a1166ad); mask-image: url(/pack-front-fr.webp?v=194a1166ad); }
.booster .b-body { z-index: 1; clip-path: polygon(0% 12.6%, 5% 11.4%, 10% 12.6%, 15% 11.4%, 20% 12.6%, 25% 11.4%, 30% 12.6%, 35% 11.4%, 40% 12.6%, 45% 11.4%, 50% 12.6%, 55% 11.4%, 60% 12.6%, 65% 11.4%, 70% 12.6%, 75% 11.4%, 80% 12.6%, 85% 11.4%, 90% 12.6%, 95% 11.4%, 100% 12.6%, 100% 100%, 0 100%); }
/* pack opening: a seam rips left to right, the jagged top strip peels off and flutters away like a scrap of foil */
.booster .b-top {
  z-index: 3; transform-origin: 4% 8%;
  clip-path: polygon(0 0, 100% 0, 100% 12.6%, 95% 11.4%, 90% 12.6%, 85% 11.4%, 80% 12.6%, 75% 11.4%, 70% 12.6%, 65% 11.4%, 60% 12.6%, 55% 11.4%, 50% 12.6%, 45% 11.4%, 40% 12.6%, 35% 11.4%, 30% 12.6%, 25% 11.4%, 20% 12.6%, 15% 11.4%, 10% 12.6%, 5% 11.4%, 0% 12.6%);
}
/* ===== Pack opening, about two seconds =====
   0.00s  charge: the pack lifts, trembles harder and harder, an aura swells behind it
   0.45s  a seam of light runs across and the crimped top strip tears off
   0.90s  light bursts out of the open mouth
   1.00s  five cards shoot out of the mouth, then swing in front of the pack as a fanned hand while the empty foil sinks away
   1.75s  a flash fills the stage and the first card is dealt (pack.js swaps the view) */
.booster::after { content: ""; position: absolute; left: 0; top: 12%; height: 2px; width: 0; z-index: 4; background: rgba(255,255,255,.95); box-shadow: 0 0 6px #fff, 0 0 14px #ffd76a; border-radius: 2px; }
.booster .b-aura, .booster .b-light, .booster .fly-card { position: absolute; pointer-events: none; opacity: 0; }
.booster .b-aura {
  z-index: -1; inset: -28% -45%; border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255,214,110,.95), rgba(190,90,255,.6) 45%, rgba(70,150,255,.25) 70%, transparent);
  filter: blur(6px);
}
.booster .b-light {
  z-index: 0; left: -40%; right: -40%; bottom: 86%; height: 110%; transform-origin: 50% 100%; mix-blend-mode: screen;
  /* a soft fan of light from a point inside the pack, fading out as it rises */
  background: radial-gradient(ellipse 34% 22% at 50% 100%, #fff, rgba(255,222,140,.7) 50%, transparent),
    conic-gradient(from -28deg at 50% 160%, transparent, rgba(210,140,255,.4) 10deg, rgba(255,228,150,.95) 21deg, #fff 28deg, rgba(255,228,150,.95) 35deg, rgba(210,140,255,.4) 46deg, transparent 56deg);
  -webkit-mask: linear-gradient(to top, #000 40%, transparent 98%); mask: linear-gradient(to top, #000 40%, transparent 98%);
}
.booster .fly-card {
  z-index: 0; left: 22%; width: 56%; top: 20%; aspect-ratio: 63 / 88; border-radius: 6% / 4.3%; transform-origin: 50% 110%;
  display: grid; place-items: center; container-type: inline-size;
  background: repeating-linear-gradient(135deg, rgba(255,255,255,.07) 0 2px, transparent 2px 8px), linear-gradient(160deg, #343a48, #12151c);
  box-shadow: inset 0 0 0 2px #e2b64d, inset 0 0 0 5px rgba(0,0,0,.35), 0 0 16px rgba(255,210,110,.75);
}
/* the same back as the cards in the viewer: the M / CARDS logo, scaled to the card's width */
.booster .fly-card .lg-icon { font-size: 19cqw; }
.booster.opening { animation: pack-charge .45s cubic-bezier(.5,0,1,.6) both, pack-jolt .24s .45s ease-out; }
.booster.opening::after { animation: pack-seam .3s .45s linear forwards; }
.booster.opening .b-top { animation: pack-peel .72s .55s cubic-bezier(.35,.1,.3,1) forwards; }
.booster.opening .b-aura { animation: aura-charge 1.75s ease-out forwards; }
.booster.opening .b-light { animation: light-burst .85s .88s ease-out forwards; }
.booster.opening .b-body { animation: body-sink .5s 1.25s cubic-bezier(.5,0,.8,.4) forwards; }
.booster.opening .fly-card { animation: card-fly .62s calc(1s + var(--i) * .07s) cubic-bezier(.2,.8,.3,1.1) forwards; }
.pack-closed.opening .what, .pack-closed.opening .open-pack { opacity: 0; transition: opacity .3s; }
@keyframes pack-charge {
  0% { transform: none; }
  20% { transform: translateY(-3px) scale(1.01) rotate(-.6deg); }
  35% { transform: translateY(-4px) scale(1.02) rotate(.9deg); }
  50% { transform: translateY(-6px) scale(1.03) rotate(-1.4deg); }
  62% { transform: translateY(-7px) scale(1.035) rotate(1.8deg); }
  72% { transform: translateY(-8px) scale(1.04) rotate(-2.2deg); }
  80% { transform: translateY(-9px) scale(1.05) rotate(2.4deg); }
  87% { transform: translateY(-9px) scale(1.05) rotate(-2.6deg); }
  94% { transform: translateY(-10px) scale(1.06) rotate(2.2deg); }
  100% { transform: translateY(-10px) scale(1.06); }
}
@keyframes pack-jolt { 0% { transform: translateY(-10px) scale(1.06); } 30% { transform: translateY(-4px) scale(1.1, 1.02); } 100% { transform: translateY(-10px) scale(1.06); } }
@keyframes pack-seam { 0% { width: 0; opacity: 1; } 90% { width: 100%; opacity: 1; } 100% { width: 100%; opacity: 0; } }
@keyframes pack-peel {
  0% { transform: none; opacity: 1; }
  30% { transform: rotate(-14deg) translate(2px, -4px); }
  55% { transform: translate(34px, -46px) rotate(-38deg); }
  80% { transform: translate(92px, -30px) rotate(-78deg); opacity: 1; }
  100% { transform: translate(130px, 20px) rotate(-120deg); opacity: 0; }
}
@keyframes aura-charge {
  0% { opacity: 0; transform: scale(.5); }
  26% { opacity: .75; transform: scale(.95); }
  52% { opacity: 1; transform: scale(1.3); }
  80% { opacity: .9; transform: scale(1.4); }
  100% { opacity: 0; transform: scale(1.6); }
}
@keyframes light-burst {
  0% { opacity: 0; transform: scaleX(.3) scaleY(0); }
  25% { opacity: 1; transform: scaleX(1) scaleY(1); }
  70% { opacity: .85; }
  100% { opacity: 0; transform: scaleX(1.2) scaleY(1.1); }
}
@keyframes body-sink { to { transform: translateY(28%) scale(.94); opacity: 0; filter: brightness(1.6); } }
/* out of the mouth behind the foil, then in front of it (z-index flips at the top of the jump) */
@keyframes card-fly {
  0% { opacity: 1; z-index: 0; transform: none; }
  42% { opacity: 1; z-index: 0; transform: translate(calc(var(--x) * .2), -88%) rotate(calc(var(--r) * .3)); }
  43% { z-index: 5; }
  100% { opacity: 1; z-index: 5; transform: translate(var(--x), var(--y)) rotate(var(--r)) scale(1.05); }
}
/* the flash that hides the swap from the closed pack to the first card */
.pack-stage::after { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; opacity: 0; z-index: 5; background: radial-gradient(circle at 50% 42%, #fff 0, rgba(255,236,190,.95) 30%, rgba(200,140,255,.55) 60%, transparent 85%); }
.pack-stage.flash::after { animation: stage-flash .65s ease-out; }
@keyframes stage-flash { 0% { opacity: 0; } 30% { opacity: 1; } 100% { opacity: 0; } }
.slot.deal .card { animation: card-deal .28s cubic-bezier(.2,.9,.3,1.2) both; }
@keyframes card-deal { from { transform: translateY(30px) scale(.86); opacity: 0; } to { transform: none; opacity: 1; } }
/* reduced motion: nothing moves, grows or shakes; only light and opacity change */
@media (prefers-reduced-motion: reduce) {
  .booster.opening, .booster.opening::after, .booster.opening .b-light, .slot.deal .card { animation: none; }
  .booster.opening .b-aura { animation: calm-aura 1.25s ease-out forwards; }
  .booster.opening .b-body, .booster.opening .b-top { animation: calm-fade .5s .4s ease forwards; }
  .booster.opening .fly-card { animation: calm-card .45s calc(.5s + var(--i) * .06s) ease-out forwards; }
}
@keyframes calm-aura { 0% { opacity: 0; } 40% { opacity: .9; } 75% { opacity: .9; } 100% { opacity: 0; } }
@keyframes calm-fade { to { opacity: 0; filter: brightness(1.8); } }
@keyframes calm-card {
  from { opacity: 0; z-index: 5; transform: translate(var(--x), var(--y)) rotate(var(--r)); }
  to { opacity: 1; z-index: 5; transform: translate(var(--x), var(--y)) rotate(var(--r)); }
}

/* ===== Themes: one set of colour tokens, dark by default, light on request ===== */
:root, :root[data-theme="dark"] {
  color-scheme: dark;
  --page: #08090d; --surface: #13151c; --surface-2: #0e1016; --line: #242833;
  --text: #eef1f5; --muted: #9aa2ae; --heading: #ffffff; --gold: #ffd84a;
  /* Gold as *text*: old gold (#b87708 and below) turns to brown mud on these near-black surfaces.
     Anything written in gold uses this token, never the coin's own shades. */
  --gold-text: #ffd84a; --gold-text-deep: #f2b53a; --gold-text-light: #fff3cc;
  --topbar: rgba(8,9,13,.86); --input: #0b0d12; --chip: #2a2f39;
  --active-bg: #ffd84a; --active-ink: #1a1300; --num-bg: linear-gradient(135deg, #ffe066, #f2b227); --num-ink: #1a1300;
  /* Ink and fill for anything painted in --gold: dark on the dark theme's yellow, white on the light theme's orange. */
  --on-gold: #1a1300; --gold-grad: linear-gradient(135deg, #ffe27a, #ffd84a);
  --hero-glow: rgba(140, 80, 255, .42); --hero-base: #140c2c;
}
:root[data-theme="light"] {
  color-scheme: light;
  --page: #f4f5f8; --surface: #ffffff; --surface-2: #eef0f4; --line: #e2e5eb;
  --text: #1c1f26; --muted: #5d6572; --heading: #14161c; --gold: #e8590c;
  --gold-text: #8a5200; --gold-text-deep: #5a3300; --gold-text-light: #c98a06;
  --topbar: rgba(255,255,255,.88); --input: #f4f5f8; --chip: #5d6572;
  --active-bg: #14161c; --active-ink: #ffffff; --num-bg: linear-gradient(135deg, #ff8a3d, #ffb020); --num-ink: #ffffff;
  /* Never dark ink on orange. */
  --on-gold: #ffffff; --gold-grad: linear-gradient(135deg, #f26a1b, #d9480f);
  --hero-glow: rgba(150, 100, 255, .22); --hero-base: #ece6ff;
}
body { background: var(--page); color: var(--text); }
body::before { display: none; }
a { color: var(--gold); }

/* header: everything reachable in one click */
.topbar {
  position: sticky; top: 0; z-index: 20; display: flex; align-items: center; gap: 22px; padding: 10px 20px;
  background: var(--topbar); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border-bottom: 1px solid var(--line);
}
.topbar .logo { font-size: 22px; flex: none; }
.links { display: flex; gap: 4px; flex: 1; }
.links a { color: var(--text); text-decoration: none; font-weight: 800; font-size: 15px; padding: 8px 12px; border-radius: 999px; white-space: nowrap; }
.links a:hover { background: var(--surface); color: var(--gold); }
.tools { display: flex; align-items: center; gap: 10px; flex: none; }
.lang-switch { display: flex; background: var(--surface); border: 1px solid var(--line); border-radius: 999px; padding: 3px; }
.lang-switch > * { font-weight: 900; font-size: 13px; padding: 5px 11px; border-radius: 999px; text-decoration: none; color: var(--muted); }
.lang-switch [aria-current] { background: var(--active-bg); color: var(--active-ink); }
.lang-switch a:hover { color: var(--text); }
.theme-toggle { width: 38px; height: 38px; border-radius: 50%; border: 1px solid var(--line); background: var(--surface); cursor: pointer; position: relative; }
.theme-toggle { display: grid; place-items: center; color: var(--gold); }
.theme-toggle svg { width: 20px; height: 20px; }
.theme-toggle .i-sun { fill: currentColor; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.theme-toggle .i-moon { fill: currentColor; }
/* both icons sit in the same spot; switching spins one out and bounces the other in */
.theme-toggle { overflow: hidden; }
.theme-toggle svg { position: absolute; transition: transform .5s cubic-bezier(.34,1.56,.64,1), opacity .3s ease; }
.theme-toggle .i-sun { transform: rotate(-120deg) scale(.3); opacity: 0; }
.theme-toggle .i-moon { transform: none; opacity: 1; }
:root[data-theme="light"] .theme-toggle .i-sun { transform: none; opacity: 1; }
:root[data-theme="light"] .theme-toggle .i-moon { transform: rotate(120deg) scale(.3); opacity: 0; }
.theme-toggle::after { content: ""; position: absolute; inset: 0; border-radius: 50%; background: var(--gold); opacity: 0; transform: scale(.2); }
.theme-toggle.pulse::after { animation: toggle-pulse .5s ease-out; }
@keyframes toggle-pulse { 0% { opacity: .35; transform: scale(.2); } 100% { opacity: 0; transform: scale(1.3); } }
@media (prefers-reduced-motion: reduce) { .theme-toggle svg { transition: none; } .theme-toggle.pulse::after { animation: none; } }


/* hero: copy on the left, the free pack on the right */
/* clip, not hidden: hidden makes the hero a scroll container, and the sign-in docked inside it (below) stops sticking. */
.hero { position: relative; overflow: hidden; overflow: clip; padding: 38px 0 34px; border-bottom: 1px solid var(--line); }
.hero-bg { position: absolute; inset: 0; background: radial-gradient(ellipse 60% 70% at 72% 40%, var(--hero-glow), transparent 70%), radial-gradient(ellipse 80% 90% at 70% 30%, var(--hero-base), var(--page) 75%); }
.hero-bg::before {
  content: ""; position: absolute; left: 72%; top: 42%; width: 160vmax; height: 160vmax; translate: -50% -50%;
  background: repeating-conic-gradient(from 0deg, rgba(255,230,170,.09) 0deg 4deg, transparent 4deg 18deg);
  -webkit-mask: radial-gradient(circle, #000 0%, transparent 30%); mask: radial-gradient(circle, #000 0%, transparent 30%);
  animation: rays-turn 90s linear infinite;
}
@keyframes rays-turn { to { rotate: 360deg; } }
.hero-grid { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 440px); gap: 40px; align-items: center; }
.hero-copy { text-align: left; }
.kicker { display: inline-block; background: var(--surface); border: 1px solid var(--line); color: var(--gold); font-weight: 900; font-size: 13px; letter-spacing: .05em; text-transform: uppercase; padding: 5px 12px; border-radius: 999px; margin-bottom: 14px; }
h1 { background: none; -webkit-background-clip: border-box; background-clip: border-box; color: var(--heading); font-size: clamp(34px, 5vw, 58px); line-height: 1.05; padding: 0; margin: 0; text-align: left; }
.hero .sub { color: var(--gold); font-style: italic; font-weight: 900; font-size: clamp(20px, 2.4vw, 26px); margin: 10px 0 0; }
.hero .lead { margin: 14px 0 0; max-width: 34em; color: var(--muted); }
.hero-pack h2 { font-size: 24px; margin: 0 0 14px; }
.hero-pack .pack-stage { max-width: none; padding: 20px 18px 18px; }
.hero-pack .booster { width: 180px; }

/* surfaces */
h2 { color: var(--heading); font-style: italic; }
h3, .tile-title { color: var(--heading); }
.tile { background: var(--surface); box-shadow: 0 0 0 1px var(--line), 0 14px 30px rgba(0,0,0,.18); }
.tile-media { background: var(--surface-2); }
.tile-sub, .note, .market-note, .market-intro, .prose-tile p, .prose-tile li, .faq p, .step p, .pack-closed .what, .pack-status, .counter, .join .what { color: var(--muted); }
.chip { background: var(--chip); }
.claim { border-top-color: var(--line); }
.claim p { color: var(--text); }
.join input[type=email] { background: var(--input); border-color: var(--line); color: var(--text); }
.join input[type=email]:focus { background: var(--input); border-color: var(--gold); }
.nav { background: var(--surface-2); color: var(--gold); box-shadow: 0 0 0 1px var(--line); }
.dots button { background: var(--line); }
.dots button[aria-current="true"] { background: var(--active-bg); }
.step .num { background: var(--num-bg); color: var(--num-ink); box-shadow: none; }
main section { padding: 44px 0 16px; }
footer { color: var(--muted); border-top: 1px solid var(--line); margin-top: 40px; }

@media (max-width: 860px) {
  .topbar { flex-wrap: wrap; gap: 8px 12px; padding: 8px 14px; }
  /* The whole menu fits a 360 px phone: the last link (the one that opens the game) was scrolled out of sight. */
  .links { order: 3; flex-basis: 100%; overflow-x: auto; scrollbar-width: none; margin: 0 -14px; padding: 0 6px; justify-content: space-between; }
  .links a { padding: 8px 6px; font-size: 14px; }
  .links::-webkit-scrollbar { display: none; }
  .tools { margin-left: auto; }
  .hero { padding: 22px 0 26px; }
  .hero-grid { grid-template-columns: 1fr; gap: 22px; }
  .hero-copy, h1 { text-align: center; }
  .hero .lead { margin-left: auto; margin-right: auto; font-size: 16px; }
  .hero-bg::before { left: 50%; top: 70%; }
}
@media (prefers-reduced-motion: reduce) { .hero-bg::before { animation: none; } }


/* ===== Mobile first ===== */
/* no double-tap zoom when tapping arrows and cards quickly; pinch zoom still works */
html { touch-action: manipulation; }
button, a, .card__rotator, .viewer { touch-action: manipulation; }
.viewer, .card__rotator { touch-action: pan-y; }
input, button { font-size: max(16px, 1em); }

@media (max-width: 560px) {
  .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px 12px; }
  .tile-sub { display: block; font-size: 13px; }
  .tile-title { font-size: 16px; }
  .grid .card { max-width: 150px; }
  /* the featured first card (the Shiny) spans the row, so 9 cards fill a 2-column grid */
  .grid > .tile:first-child { grid-column: 1 / -1; }
  .grid > .tile:first-child .card { max-width: 190px; }
  .steps { gap: 12px; }
  main section { padding: 34px 0 10px; }
  h2 { font-size: 28px; margin-bottom: 20px; }
  .prose-tile { padding: 18px 16px; }
  .faq .tile { padding: 16px; }
}

/* touch screens: keep only cheap, composited animations */
@media (hover: none) {
  .hero-bg::before { animation: none; }
  .card.f-legendary .card__rotator { animation: none; box-shadow: 0 0 18px rgba(255,170,0,.75), 0 0 36px rgba(255,140,0,.4); }
  .slot.reveal .card { animation-name: reveal-pop; }
  .card-back { animation: back-charge var(--suspense) cubic-bezier(.5,0,.9,.6) forwards; }
}
@keyframes reveal-pop {
  0% { transform: scale(.7); opacity: 0; filter: brightness(2.2); }
  60% { transform: scale(1.05); opacity: 1; filter: brightness(1.4); }
  100% { transform: none; filter: none; }
}

/* sticky "open my pack" button */
.sticky-cta {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30; padding: 14px 16px calc(12px + env(safe-area-inset-bottom));
  background: linear-gradient(180deg, transparent, var(--page) 40%); transition: transform .25s ease, opacity .25s ease;
}
.sticky-cta .btn { max-width: 460px; margin: 0 auto; }
.sticky-cta.is-hidden { transform: translateY(110%); opacity: 0; pointer-events: none; }
footer { padding-bottom: 110px; }

@media (max-width: 860px) {
  /* the header scrolls away on phones; the sticky button is the one thing that stays */
  .topbar { position: relative; backdrop-filter: none; -webkit-backdrop-filter: none; background: var(--page); }
}


/* ===== Logo: grey "My", big rounded "Meme", spaced "CARDS" underneath, tilted up ===== */
.logo { text-decoration: none; -webkit-text-stroke: 0; transform: none; line-height: 1; }
/* logo: a small "my" over MEME and CARDS, stacked at the same size, in a comic hand */
.lg { display: inline-grid; grid-template-columns: auto; grid-template-areas: "my" "meme" "cards"; justify-items: center; text-align: center; line-height: .92;
  font-family: "Comic Sans MS", "Comic Neue", "Chalkboard SE", cursive; font-weight: 700; color: var(--logo-ink, #f4f3ef); }
.lg-my { grid-area: my; font-size: .52em; text-transform: lowercase; margin: 0 0 -.04em; }
.lg-meme { grid-area: meme; font-size: 1em; text-transform: uppercase; letter-spacing: .01em; -webkit-text-stroke: .025em currentColor; }
.lg-cards { grid-area: cards; font-size: 1em; letter-spacing: .01em; -webkit-text-stroke: .025em currentColor; }
:root[data-theme="light"] { --logo-ink: #111214; --coin-glyph-rim: #7a4a00; --coin-glyph-face: #e9aa1c; --coin-glyph-ink: #5a3300; }
.topbar .logo { font-size: 22px; }
.lg-icon { grid-template-areas: "meme" "cards"; justify-items: center; font-size: 56px; color: #f4f3ef; }
.lg-icon .lg-meme { color: #f4f3ef; }
.lg-icon .lg-cards { color: #ffd23f; }
.card-back .lg-icon { font-size: 34px; transform: rotate(-4deg); }
@media (max-width: 860px) { .topbar .logo { font-size: 18px; } }

/* Cards are objects, not text: no selection highlight or long-press menu when tilting or swiping them. */
.card, .card-back, .booster, .app-booster, .viewer { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; }
/* Controls are not text either: a double tap on the arrows, the dots or a button must not paint a selection over them.
   -webkit-tap-highlight-color is the one that actually suppresses the blue flash on a fast tap; user-select alone
   only stops text selection and leaves the highlight showing (shared by every page through this base stylesheet,
   including /app, so a fix here does not need repeating per app-only component). */
button, .btn, [role="button"], [role="tab"], .pager, .dots, .chips, .nav, .tabbar, .pack-switch, .wait-tile, .prog { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; }
.nav:focus-visible, .dots button:focus-visible, .btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.play-btn { max-width: 320px; margin: 18px auto 0; text-align: center; text-decoration: none; }
/* One line, always: "Récupérer mes 10 packs →" at 22px broke in two on a phone. The label shrinks with the screen
   instead of wrapping (scripts/bouton_shots.mjs checks it down to 320px). */
.play-btn, .pack-back .back-play { white-space: nowrap; padding-inline: 14px; font-size: clamp(15px, 5.2vw, 22px); }
.play-btn[hidden] { display: none; }

/* full art: a rainbow holo laid over the face, rarer than Legendary and commoner than Shiny */
.card.f-fullart .card__rotator { box-shadow: 0 0 14px rgba(200,120,255,.55), 0 0 30px rgba(80,200,255,.35), 0 10px 20px -8px rgba(0,0,0,.5); }
.slot.suspense-fullart { --aura: 200,120,255; }
.slot.reveal-fullart .card { animation-duration: 1.6s; }
.pill.r-fullart, .tiers .r-fullart { --c: linear-gradient(90deg, #ff8ad8, #8f6bff, #3fd3ff); color: #fff; }

/* legal pages */
.legal h3 { margin: 22px 0 8px; }
.legal .lead-box { padding: 14px 16px; border-radius: 14px; background: var(--surface-2, rgba(127,127,127,.1)); }
.legal table.odds { width: 100%; border-collapse: collapse; margin: 10px 0 14px; font-weight: 700; }
.legal table.odds th, .legal table.odds td { text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--line); }
.legal table.odds th { color: var(--muted); font-size: 13px; text-transform: uppercase; letter-spacing: .04em; }
footer a { color: inherit; }
.odds-line { margin: 10px auto 0; max-width: 46ch; font-size: 12.5px; line-height: 1.45; color: var(--muted); text-wrap: balance; }
.odds-line a { color: inherit; font-weight: 800; }

/* Home page, signed-in player: a way back into the game instead of the free pack. */
.pack-back { display: grid; justify-items: center; gap: 16px; padding: 14px 8px 12px; text-align: center; }
.pack-back[hidden] { display: none; }
.pack-back p { margin: 0; max-width: 30ch; font-weight: 700; color: var(--muted, #97a39e); }
/* Three cards fanned out: the player's best ones once /api/me answers, the MemeCards card back until then. */
.back-fan { position: relative; width: 250px; height: 176px; margin: 0 auto; }
.back-fan > span { position: absolute; left: 50%; bottom: 0; width: 112px; aspect-ratio: 63 / 88; transform-origin: 50% 115%; }
.back-fan > span:nth-child(1) { transform: translateX(-50%) rotate(-15deg); }
.back-fan > span:nth-child(2) { transform: translateX(-50%) translateY(-8px); z-index: 1; }
.back-fan > span:nth-child(3) { transform: translateX(-50%) rotate(15deg); }
.fan-back { display: grid; place-items: center; border-radius: 10px; background: linear-gradient(160deg, #2c3342, #141821); box-shadow: 0 10px 24px rgba(0,0,0,.3), inset 0 0 0 3px #ffd23f; }
.fan-back .lg-icon { font-size: 22px; transform: rotate(-4deg); }
.fan-card { filter: drop-shadow(0 10px 18px rgba(0,0,0,.35)); }
.fan-card .card { width: 100%; max-width: none; pointer-events: none; }
/* The stock, the collection and the coins: three figures a returning player checks first. */
.back-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; width: min(100%, 340px); }
.back-stats a { display: grid; gap: 0; padding: 10px 4px; border-radius: 14px; background: var(--surface); box-shadow: 0 0 0 1px var(--line); color: var(--text); text-decoration: none; container-type: inline-size; min-width: 0; }
/* Sized from the tile's own width (cqw) so five digits fit down to 320px. */
.back-stats b { font-size: clamp(12px, 17cqw, 17px); font-weight: 900; font-variant-numeric: tabular-nums; white-space: nowrap; }
.back-stats b i { display: block; font-style: normal; font-size: .72em; font-weight: 800; color: var(--muted); }
.back-stats small { font-size: 12px; font-weight: 800; color: var(--muted); }
.pack-back .back-line { font-size: 17px; color: var(--text); }
.pack-back .back-line b { font-variant-numeric: tabular-nums; }
.pack-back .back-play { width: min(100%, 340px); text-decoration: none; }
/* Phones: the button comes before the three figures and the fan shrinks, so the way back into the game sits in
   the first screen down to 320×568 (scripts/boucle_shots.mjs checks it). */
@media (max-width: 560px) {
  .pack-back { gap: 12px; padding-top: 8px; }
  .back-fan { width: 190px; height: 118px; }
  .back-fan > span { width: 76px; }
  .fan-back .lg-icon { font-size: 16px; }
  .pack-back .back-line { font-size: 15.5px; }
  .pack-back .back-play { order: 1; min-height: 52px; }
  .back-stats { order: 2; }
}

/* ---- mobile & fluidity fixes (design audit) ---- */
/* Permanent will-change promoted ~5 layers per card (225 on a full collection grid): let the browser promote only
   the card being touched or animated. */
.card, .card__translater, .card__rotator, .card__shine, .card__glare { will-change: auto; }
/* Pinch-zoom stays possible on cards and viewers; only horizontal swipes are ours. */
.viewer, .card__rotator { touch-action: pan-y pinch-zoom; }
/* Inputs never drop under 16px, or iOS zooms into them. */
input, select, textarea { font-size: max(16px, 1em); }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-iteration-count: 1 !important; scroll-behavior: auto !important; }
  .booster, .booster::after { animation: none !important; }
}
.dots button { position: relative; }
.dots button::before { content: ""; position: absolute; inset: -12px -6px; }
/* No paragraph or heading broken into uneven lines. */
p, li, h1, h2, h3, small, .burn-warn { text-wrap: balance; }

/* ===== Phones: the "Open my pack" button sits in the first screen, without relying on the sticky button ===== */
@media (max-width: 560px) {
  .hero { padding: 14px 0 20px; }
  .hero-grid { gap: 10px; }
  .hero h1 { font-size: 30px; line-height: 1.05; margin: 8px 0 4px; }
  .hero .sub { font-size: 18px; margin: 0; }
  .hero .lead { display: none; }
  .hero-pack .pack-stage { padding: 16px 16px 14px; }
  .hero-pack .booster { width: 150px; }
  .pack-closed { display: flex; flex-direction: column; align-items: center; }
  .pack-closed .booster { order: 0; }
  .pack-closed .what { order: 1; margin: 14px 0 0; font-size: 16px; font-weight: 800; color: var(--text); }
  .pack-closed .free-note { order: 2; }
  .pack-closed .open-pack { order: 3; width: 100%; }
  .pack-closed .odds-btn { order: 4; }
  .pack-closed .pack-error { order: 5; }
}

/* ===== Phones: the homepage of docs/design-handoff §3.1 =====
   Everything below 560 px only. The computer layout is untouched: blocks written for the phone carry .m-only,
   blocks the phone drops carry .m-hide, and both stay in the DOM so search engines keep reading the whole page. */
@media (min-width: 561px) { .m-only { display: none !important; } }

/* The FAQ heading is a button at every width; on a computer it just looks like the heading it replaced. */
.faq-q { margin: 0 0 4px; }
.faq-q button { display: block; width: 100%; margin: 0; padding: 0; border: 0; background: none; font: inherit; color: inherit; text-align: left; }
.faq-i { display: none; }

/* The odds sheet is only ever opened from the phone layout. */
.odds-sheet { position: fixed; inset: 0; z-index: 40; display: grid; align-items: end; background: rgba(0,0,0,.55); }
.odds-sheet[hidden] { display: none; }
.odds-panel { background: var(--page); border-top: 1px solid var(--line); border-radius: 22px 22px 0 0; display: grid; gap: 10px;
  padding: 20px 18px calc(22px + env(safe-area-inset-bottom)); }
.odds-panel h2 { font-size: 24px; text-align: left; margin: 0; }
.odds-table { width: 100%; border-collapse: collapse; font-weight: 700; font-size: 15px; }
.odds-table td { padding: 9px 4px; border-bottom: 1px solid var(--line); }
.odds-table tr:last-child td { border-bottom: 0; }
.odds-table td:last-child { text-align: right; }
.odds-note { margin: 0; color: var(--muted); font-size: 14px; }
.btn.ghost { background: none; color: var(--text); text-shadow: none; box-shadow: 0 0 0 1px var(--line); }
body.sheet-open { overflow: hidden; }

@media (max-width: 560px) {
  .m-hide { display: none !important; }

  /* header on one line: the logo and the way into the game, both reachable with a thumb */
  .topbar { position: sticky; top: 0; flex-wrap: nowrap; justify-content: space-between; gap: 12px; padding: 8px 14px;
    background: var(--topbar); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); }
  .links, .topbar .tools { display: none; }
  .top-play { flex: none; width: auto; margin: 0; min-height: 44px; padding: 9px 20px; font-size: 17px; text-decoration: none;
    display: grid; place-items: center; }

  /* hero: the kicker and the lead leave, the pack and its button take the first screen */
  .hero .kicker, .hero-pack h2 { display: none; }
  .pack-closed .what-more { display: none; }
  .free-note { margin: 2px 0 0; font-weight: 700; font-size: 14px; color: var(--muted); }
  .pack-closed .odds-line { display: none; }
  .odds-btn { min-height: 44px; margin-top: 10px; padding: 0 12px; border: 0; background: none; font: inherit; font-weight: 800;
    font-size: 15px; color: var(--text); text-decoration: underline; text-underline-offset: 3px; }

  main section > h2 { font-size: 26px; margin-bottom: 16px; }

  /* cards: a carousel of six, one per rarity, instead of a two-column grid of nine */
  #cards > h2 { margin-bottom: 4px; }
  .swipe-hint { margin: 0 0 14px; text-align: center; color: var(--muted); font-weight: 700; font-size: 14px; }
  .grid { display: flex; gap: 14px; margin: 0 -16px; padding: 6px 16px 18px; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none;
    overscroll-behavior-x: contain; }
  .grid::-webkit-scrollbar { display: none; }
  /* The holo tilt claims every card with touch-action: pan-y, which swallowed the carousel's horizontal swipe:
     "Swipe to see more" moved nothing on a phone. Inside the carousel the finger belongs to the carousel. */
  .grid .card, .grid .card__translater, .grid .card__rotator { touch-action: pan-x pan-y pinch-zoom; }
  /* the card carries the whole tile on a phone (title and blurb are hidden): wide enough for its face to read */
  .grid > .tile { order: var(--mo, 9); flex: 0 0 246px; scroll-snap-align: center; padding: 10px; }
  .grid .card, .grid > .tile:first-child .card { max-width: 220px; }
  .grid .chip, .grid .tile-title, .grid .tile-sub { display: none; }
  .grid .tile-media { gap: 10px; padding: 14px 12px; }
  .grid .pill { position: static; font-size: 12px; }

  /* rarity follows fame: the real pull rates, as bars */
  .m-sub { margin: -10px 0 16px; text-align: center; color: var(--muted); font-size: 15px; }
  .m-rates { display: grid; gap: 12px; padding: 14px 16px; border-radius: 20px; }
  .m-rate { display: grid; grid-template-columns: 96px 1fr 46px; align-items: center; gap: 10px; }
  .m-rate .pill { position: static; font-size: 12px; padding: 3px 8px; text-align: center; }
  .m-rate b { text-align: right; font-size: 15px; }
  .m-bar { display: block; height: 8px; border-radius: 999px; background: var(--surface-2); }
  .m-bar > i { display: block; height: 100%; min-width: 4px; border-radius: inherit; background: var(--common); }
  .m-rate.r-rare .m-bar > i { background: linear-gradient(90deg, #52b6ff, #2f7bff); }
  .m-rate.r-epic .m-bar > i { background: linear-gradient(90deg, #c07bff, #8a3dff); }
  .m-rate.r-legendary .m-bar > i { background: linear-gradient(90deg, #ffc233, #ff8a1a); }
  .m-rate.r-mythic .m-bar > i { background: linear-gradient(90deg, #3ff0c8, #1a8cff 55%, #7a3dff); }
  .m-rate.r-fullart .m-bar > i { background: linear-gradient(90deg, #ff8ad8, #8f6bff, #3fd3ff); }
  .m-rate.r-shiny .m-bar > i { background: #e9c15a; }

  /* how it works: three lines instead of two blocks of three tiles */
  .m-rows { display: grid; gap: 10px; }
  .m-row { display: flex; align-items: center; gap: 14px; padding: 14px; border-radius: 18px; background: var(--surface); box-shadow: 0 0 0 1px var(--line); }
  .m-n { flex: none; width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center; font-weight: 900; font-size: 19px;
    background: var(--num-bg); color: var(--num-ink); }
  .m-txt { display: grid; gap: 2px; }
  .m-txt b { font-size: 16px; color: var(--heading); }
  .m-txt small { font-size: 14px; font-weight: 600; line-height: 1.4; color: var(--muted); }

  /* FAQ: five questions in an accordion, 56 px a line */
  .faq { display: flex; flex-direction: column; gap: 0; background: var(--surface); border-radius: 20px; box-shadow: 0 0 0 1px var(--line); overflow: hidden; }
  .faq .tile { order: var(--mo, 9); padding: 0; border-radius: 0; background: none; box-shadow: none;
    border-top: 1px solid var(--line); margin-top: -1px; }
  .faq-q { margin: 0; font-size: 16px; }
  .faq-q button { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 56px; padding: 12px 16px;
    font-weight: 800; color: var(--heading); cursor: pointer; }
  .faq-i { display: grid; flex: none; width: 28px; height: 28px; place-items: center; border-radius: 50%;
    background: var(--surface-2); color: var(--gold); font-weight: 900; }
  .faq-a { display: none; padding: 0 16px 16px; }
  .faq-item.is-open .faq-a { display: block; }
  .faq-a p { font-size: 15px; }

  /* the SEO prose falls to the end of the page, folded away, and stays in the DOM */
  main.wrap { display: flex; flex-direction: column; }
  .more-toggle, .prose-sec { order: 3; }
  .more-toggle { display: flex; align-items: center; justify-content: space-between; width: 100%; min-height: 48px; margin-top: 22px;
    padding: 12px 0; border: 0; border-top: 1px solid var(--line); background: none; font: inherit; font-weight: 800; font-size: 15px; color: var(--muted); }
  .prose-sec { display: none; padding-top: 6px; }
  main.more-open .prose-sec { display: block; }
  .prose-sec > h2 { font-size: 20px; margin-bottom: 12px; }
  .prose-sec .prose-tile { background: none; box-shadow: none; padding: 0; }
  .prose-sec .prose-tile p, .prose-sec .prose-tile li { font-size: 15px; }

  /* language and theme move to the footer, on 44 px targets */
  .foot-tools { display: flex; align-items: center; justify-content: center; gap: 10px; margin-bottom: 16px; }
  .foot-tools .theme-toggle { width: 44px; height: 44px; }
  .foot-tools .lang-switch > * { display: grid; place-items: center; min-height: 44px; padding: 0 16px; font-size: 14px; }
}

/* The home showcase on a computer: the card under the pointer grows (transform only, nothing moves) above its neighbours. */
@media (hover: hover) and (pointer: fine) {
  .grid .tile-media .card { transition: scale .2s ease-out; }
  .grid .tile:hover { position: relative; z-index: 8; }
  .grid .tile-media:hover .card { scale: 1.4; }
}
@media (prefers-reduced-motion: reduce) { .grid .tile-media .card { transition: none; } }

/* The email sign-up sheet (auth-email.js), shared by the home page and the game. Built on the same tokens as
   the odds sheet: a bottom sheet on a phone, a centred card from 900px up. */
.email-btn { display: block; width: 100%; min-height: 44px; margin-top: 10px; padding: 12px 20px; border: 0; border-radius: 999px;
  background: var(--surface); color: var(--text); box-shadow: 0 0 0 1px var(--line); font: inherit; font-weight: 800; font-size: 16px;
  cursor: pointer; }
.email-btn:active { transform: translateY(1px); }
.mmc-auth { position: fixed; inset: 0; z-index: 60; display: grid; align-items: end; justify-items: center;
  background: rgba(0,0,0,.6); animation: mmc-auth-in .18s ease-out; }
.mmc-auth-card { width: min(460px, 100%); max-height: 94vh; overflow: auto; background: var(--page);
  border: 1px solid var(--line); border-radius: 22px 22px 0 0; text-align: left; }
.mmc-auth-top { position: sticky; top: 0; z-index: 2; display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 16px 18px 8px; background: var(--page); border-radius: 21px 21px 0 0; }
.mmc-auth-top h2 { margin: 0; font-size: 24px; color: var(--heading); }
.mmc-auth-x { width: 44px; height: 44px; flex: none; display: grid; place-items: center; padding: 0; border: 0; border-radius: 50%;
  background: var(--surface-2); color: var(--text); font: inherit; font-size: 19px; font-weight: 900; line-height: 1; cursor: pointer; }
.mmc-auth-body { display: grid; gap: 12px; padding: 4px 18px calc(20px + env(safe-area-inset-bottom)); }
.mmc-auth-lead { margin: 0; font-weight: 700; font-size: 15px; color: var(--muted); }
.mmc-auth-field { display: grid; gap: 6px; font-weight: 800; font-size: 14px; color: var(--muted); }
.mmc-auth-field input { width: 100%; min-height: 48px; box-sizing: border-box; font: inherit; font-weight: 700; font-size: 17px;
  color: var(--text); background: var(--input); border: 1px solid var(--line); border-radius: 14px; padding: 12px 16px; }
.mmc-auth-field input:focus { outline: none; border-color: var(--gold); }
.mmc-auth-code { text-align: center; letter-spacing: .5em; text-indent: .5em; font-size: 26px !important; font-weight: 900 !important; }
.mmc-auth-hint { margin: -4px 0 0; font-size: 13px; font-weight: 700; color: var(--muted); }
.mmc-auth-go { margin-top: 4px; font-size: 19px; }
.mmc-auth-msg { min-height: 1.3em; margin: 0; font-weight: 700; font-size: 15px; color: var(--muted); }
.mmc-auth-msg.bad { color: #e5484d; }
.mmc-auth-link { min-height: 44px; padding: 0; border: 0; background: none; font: inherit; font-weight: 800; font-size: 15px;
  color: var(--text); text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.mmc-auth-link:disabled { color: var(--muted); text-decoration: none; cursor: default; }
@keyframes mmc-auth-in { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .mmc-auth { animation: none; } }
@media (min-width: 900px) { .mmc-auth { align-items: center; } .mmc-auth-card { border-radius: 22px; } }

/* Loyalty packs after the free pack: a gold callout right above the button, an arrow bouncing down onto it and a
   pulse on the button, so the next step (claim, open, then play) cannot be missed on a phone. */
.ly-callout { position: relative; display: grid; gap: 4px; width: min(100%, 340px); margin: 16px auto 0; padding: 14px 16px 22px; border-radius: 16px; text-align: center; background: linear-gradient(160deg, rgba(255,216,74,.2), rgba(255,140,40,.12)); box-shadow: 0 0 0 2px var(--gold, #ffd84a), 0 10px 26px -10px rgba(255,180,40,.55); animation: ly-callout-in .45s cubic-bezier(.2,1.4,.4,1) both; }
.ly-callout b { font-size: clamp(17px, 5.4vw, 21px); font-weight: 900; line-height: 1.2; color: var(--text); text-wrap: balance; }
.ly-callout span { font-size: 14px; font-weight: 700; line-height: 1.35; color: var(--muted, #97a39e); text-wrap: balance; }
.ly-callout .ly-arrow { position: absolute; left: 50%; bottom: -17px; display: grid; place-items: center; width: 30px; height: 30px; margin-left: -15px; border-radius: 50%; font-style: normal; font-size: 17px; font-weight: 900; color: var(--on-gold, #1b1400); background: var(--gold-grad, #ffc93c); box-shadow: 0 4px 12px rgba(255,170,30,.5); animation: ly-arrow-bob 1s ease-in-out infinite; z-index: 1; }
.play-btn.guided, .pack-back .back-play.guided { animation: ly-btn-pulse 1.6s ease-in-out infinite; }
.pack-open .ly-callout + .play-btn { margin-top: 24px; }
.pack-back .ly-callout { margin-top: 0; margin-bottom: 6px; }
@media (max-width: 560px) { .pack-back .ly-callout { order: 1; padding: 10px 12px 18px; } }
/* 320×568: the subline would push the button out of the first screen; the title and the arrow say enough. */
@media (max-width: 560px) and (max-height: 620px) { .ly-callout span { display: none; } }
@keyframes ly-callout-in { from { opacity: 0; transform: translateY(10px) scale(.96); } }
@keyframes ly-arrow-bob { 50% { transform: translateY(5px); } }
@keyframes ly-btn-pulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(255,200,50,.6); } 50% { box-shadow: 0 0 0 10px rgba(255,200,50,0); } }
@media (prefers-reduced-motion: reduce) {
  .ly-callout, .ly-callout .ly-arrow, .play-btn.guided, .pack-back .back-play.guided { animation: none !important; }
  .play-btn.guided, .pack-back .back-play.guided { outline: 3px solid var(--gold, #ffd84a); outline-offset: 3px; }
}

/* First-pack teaser (public/teaser.js): three Full Art cards shown before a new player's first booster tears. */
.teaser {
  position: fixed; inset: 0; z-index: 200; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(18px, 4vh, 36px); padding: 16px; cursor: pointer; overflow: hidden;
  background: radial-gradient(ellipse at 50% 55%, rgba(255, 200, 60, .28), transparent 60%), rgba(8, 10, 18, .9);
  opacity: 0; transition: opacity .3s ease;
}
.teaser.is-in { opacity: 1; }
.teaser.is-out { opacity: 0; transition-duration: .45s; }
.teaser-title {
  margin: 0; max-width: 26ch; text-align: center; color: #fff; font-weight: 900; line-height: 1.15;
  font-size: clamp(22px, 5.2vw, 34px); text-shadow: 0 2px 18px rgba(0, 0, 0, .6);
  transform: translateY(12px); transition: transform .5s ease;
}
.teaser.is-in .teaser-title { transform: none; }
.teaser-row { display: flex; align-items: center; justify-content: center; gap: clamp(8px, 2.5vw, 22px); perspective: 1200px; }
.teaser-slot { width: min(26vw, 190px); opacity: 0; transform: translateY(40px) rotateY(180deg) scale(.7); transition: transform .7s cubic-bezier(.2, 1.3, .4, 1), opacity .25s ease; }
.teaser-slot.is-main { width: min(36vw, 250px); }
.teaser-slot .card { max-width: none; }
.teaser-slot.is-in { opacity: 1; transform: rotate(-6deg); }
.teaser-slot.is-in:last-child { transform: rotate(6deg); }
.teaser-slot.is-main.is-in { transform: translateY(-4%) scale(1); filter: drop-shadow(0 0 28px rgba(255, 210, 80, .55)); }
.teaser.is-out .teaser-slot { transform: translateY(30vh) scale(.2); opacity: 0; transition: transform .45s cubic-bezier(.5, 0, .9, .4), opacity .45s ease; }
.teaser-skip { margin: 0; color: rgba(255, 255, 255, .6); font-size: 14px; font-weight: 700; }
/* Under an edition's one-of-a-kind headliner: what finding it is worth, then how unlikely that is. Gold on dark glass,
   never dark text on gold. Lands with the headliner (the last of the three beats). */
.teaser-prize {
  display: flex; flex-direction: column; align-items: center; gap: 4px; margin: 0; max-width: min(92vw, 460px);
  padding: 10px 16px; border-radius: 14px; text-align: center;
  background: rgba(20, 14, 2, .72); box-shadow: inset 0 0 0 1.5px rgba(255, 200, 60, .75), 0 0 28px rgba(255, 190, 40, .3);
  opacity: 0; transform: translateY(10px); transition: opacity .4s ease 1.3s, transform .5s ease 1.3s;
}
.teaser.is-in .teaser-prize { opacity: 1; transform: none; }
.teaser.is-out .teaser-prize { opacity: 0; transition-delay: 0s; }
.tp-main { color: #fff; font-weight: 800; font-size: clamp(15px, 3.9vw, 19px); line-height: 1.25; }
.tp-main b { color: #ffd45c; font-weight: 900; }
@media (prefers-reduced-motion: reduce) {
  .teaser-title, .teaser-slot, .teaser.is-out .teaser-slot, .teaser-prize { transform: none !important; transition: opacity .2s ease; }
}

/* cards/face.css */
/*
  Card face v1, approved on 2026-09-29 (prototype: data/memes/cartes-v1/card.css).
  Laid on top of the rarity frame at fixed percentages; sizes in cqw follow the card's own width
  (the container is .card__front, see styles.css). Classes are prefixed mk- so nothing collides
  with the older face or with /holo/holo.css.
  The reflections are the prototype's, but driven by the pointer variables /holo/holo.js already
  sets on .card (--pointer-x, --pointer-y, --card-opacity) instead of the prototype's own script.
*/

/*
  The typeface (2026-10-01): Gillius ADF, the free Gill Sans the Pokémon cards are set in (Arkandis Digital Foundry,
  GPL with font exception, fonts/COPYING). The condensed bold sets the name, the bold every label, the bold italic
  the type, the description and the set line. Where it has not arrived yet, Apple's own Gill Sans stands in.
  Its glyph widths are in face.js, which sizes the name, the type and the description from them: kerning is off,
  so what the browser draws is exactly what face.js measured. scripts/card_font_metrics.py builds both.
  The vertical metrics are pinned to the font's own (hhea) so Windows and Android set a line where macOS does.
*/
@font-face { font-family: "MMC Gill"; font-weight: 700; font-style: normal; font-display: swap; ascent-override: 95%; descent-override: 29.8%; line-gap-override: 0%; src: url(/cards/fonts/GilliusADF-Bold.woff2?v=cd396d95fe) format("woff2"); }
@font-face { font-family: "MMC Gill"; font-weight: 700; font-style: italic; font-display: swap; ascent-override: 95%; descent-override: 29.8%; line-gap-override: 0%; src: url(/cards/fonts/GilliusADF-BoldItalic.woff2?v=e119e443e8) format("woff2"); }
@font-face { font-family: "MMC Gill Cond"; font-weight: 700; font-style: normal; font-display: swap; ascent-override: 95%; descent-override: 29.8%; line-gap-override: 0%; src: url(/cards/fonts/GilliusADFCond-Bold.woff2?v=6d612d2018) format("woff2"); }

.mk {
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: inherit;
  background-size: 100% 100%;
  color: var(--mk-ink);
  font-family: "MMC Gill", "Gill Sans", "Gill Sans MT", system-ui, sans-serif;
  font-weight: 700; font-kerning: none; font-synthesis: none; letter-spacing: 0;
}
/* holo.css turns every descendant of the rotator into a full-size grid layer; undo that inside the face */
.mk * {
  display: block; grid-area: auto; width: auto; height: auto; aspect-ratio: auto;
  border-radius: 0; overflow: visible; transform-style: flat; min-width: 0;
}
.mk > span { position: absolute; display: flex; align-items: center; min-width: 0; }
.mk-top > span { display: flex; align-items: center; }

/*
  Legibility (2026-09-30 review): the frames are busy — a rainbow maze on rares, glitter on epics, an iridescent
  fingerprint on mythics — so every text sits on a panel. --mk-scrim is the light pill under the small labels (name,
  Fame, site), --mk-well the panel under the description; both take the rarity's hue, dark under a white ink
  (rare, epic, mythic) and pale under a dark one (common, legendary). Contrast, measured under each text with
  scripts/card_contrast.mjs: description >= 4.5:1, every other label >= 3:1, on every rarity.
*/
.mk-common { --mk-ink: #141a1c; --mk-soft: #141a1c; --mk-scrim: rgba(242, 247, 244, .8); --mk-well: rgba(242, 247, 244, .86); }
.mk-rare { --mk-ink: #ffffff; --mk-soft: #ffffff; --mk-scrim: rgba(5, 24, 66, .66); --mk-well: rgba(5, 24, 66, .78); }
.mk-epic { --mk-ink: #ffffff; --mk-soft: #ffffff; --mk-scrim: rgba(30, 6, 66, .68); --mk-well: rgba(30, 6, 66, .8); }
.mk-legendary { --mk-ink: #1d1200; --mk-soft: #1d1200; --mk-scrim: rgba(255, 247, 219, .82); --mk-well: rgba(255, 248, 224, .88); }
.mk-mythic { --mk-ink: #ffffff; --mk-soft: #ffffff; --mk-scrim: rgba(8, 16, 58, .7); --mk-well: rgba(8, 16, 58, .82); }
.mk-rare .mk-body, .mk-epic .mk-body, .mk-mythic .mk-body { text-shadow: 0 .2cqw .8cqw rgba(0, 0, 0, .45); }

/* The frame's own mid-tone under each one, painted before the image arrives: a card turned over on a cold cache
   shows its rarity's colour, never the dark card behind it. */
.mk-common { background-color: #cfd9d4; }
.mk-rare { background-color: #1f4fa8; }
.mk-epic { background-color: #5b2aa0; }
.mk-legendary { background-color: #e2b547; }
.mk-mythic { background-color: #22307a; }
.mk-common { background-image: url(/cards/frames/common.webp); }
.mk-rare { background-image: url(/cards/frames/rare.webp); }
.mk-epic { background-image: url(/cards/frames/epic.webp); }
.mk-legendary { background-image: url(/cards/frames/legendary.webp); }
.mk-mythic { background-image: url(/cards/frames/mythic.webp); }
.mk-logo-common { --mk-ar: 953 / 180; background-image: url(/cards/logos/common.webp); }
.mk-logo-rare { --mk-ar: 627 / 180; background-image: url(/cards/logos/rare.webp); }
.mk-logo-epic { --mk-ar: 612 / 180; background-image: url(/cards/logos/epic.webp); }
.mk-logo-legendary { --mk-ar: 858 / 180; background-image: url(/cards/logos/legendary.webp); }
.mk-logo-mythic { --mk-ar: 851 / 180; background-image: url(/cards/logos/mythic.webp); }
/* English wordmarks (the French ones above are the default, `mk-logo-fr` adds nothing). */
.mk-logo-en.mk-logo-common { --mk-ar: 953 / 180; background-image: url(/cards/logos/en/common.webp); }
.mk-logo-en.mk-logo-rare { --mk-ar: 627 / 180; background-image: url(/cards/logos/en/rare.webp); }
.mk-logo-en.mk-logo-epic { --mk-ar: 612 / 180; background-image: url(/cards/logos/en/epic.webp); }
.mk-logo-en.mk-logo-legendary { --mk-ar: 858 / 180; background-image: url(/cards/logos/en/legendary.webp); }
.mk-logo-en.mk-logo-mythic { --mk-ar: 851 / 180; background-image: url(/cards/logos/en/mythic.webp); }

/* top row: type pill, name, rarity logo, Fame, star circle */
/* The widths here are the ones face.js budgets the name with (MK_TOP, MK_TYPE, MK_LOGO_H, MK_FAME, MK_STAR). */
.mk-top { left: 6.4%; top: 3.3%; width: 87.4%; height: 6%; gap: 1.1cqw; }
.mk-type {
  position: static; flex: none; font-weight: 700; font-style: italic; font-size: 1.9cqw; line-height: 1; letter-spacing: .03em;
  text-transform: uppercase; color: #3b4148; white-space: nowrap; padding: .7cqw 1.35cqw .6cqw; border-radius: 99px;
  background: linear-gradient(180deg, #ffffff, #d7dbe1 55%, #f2f4f6);
  box-shadow: 0 0 0 .35cqw #8d949d, 0 .5cqw .8cqw rgba(0, 0, 0, .35);
}
/*
  The name: face.js has sized it to its room (font-size in the markup), on one line or, with .two, on two balanced
  ones. overflow stays hidden all the same, the last guard should a font come out wider than its measures.
*/
.mk-top > .mk-name {
  display: grid; align-content: center; flex: 0 1 auto; box-sizing: border-box; height: 7.4cqw; padding: 0 1.1cqw;
  font-family: "MMC Gill Cond", "Gill Sans", "Gill Sans MT", system-ui, sans-serif; font-weight: 700;
  line-height: 1; color: var(--mk-ink); white-space: nowrap; overflow: hidden;
  border-radius: 1.4cqw; background: var(--mk-scrim);
}
.mk-top > .mk-name.two { line-height: 1.04; white-space: normal; text-wrap: balance; overflow-wrap: anywhere; }
.mk-rare .mk-name, .mk-epic .mk-name, .mk-mythic .mk-name { text-shadow: 0 .3cqw 1cqw rgba(0, 0, 0, .5); }
.mk-top > .mk-logo {
  display: block; flex: none; align-self: center; height: 3.4cqw; aspect-ratio: var(--mk-ar); width: auto; margin-left: auto;
  background-position: center; background-size: contain; background-repeat: no-repeat;
  filter: drop-shadow(0 .3cqw .5cqw rgba(0, 0, 0, .35));
}
.mk-fame {
  flex: none; align-items: baseline; gap: .6cqw; color: var(--mk-ink); white-space: nowrap;
  padding: .4cqw 1cqw .2cqw; border-radius: 99px; background: var(--mk-scrim);
}
.mk-fame small { font-weight: 700; font-size: 2.3cqw; line-height: 1; }
.mk-fame b { font-weight: 700; font-size: 4.8cqw; line-height: 1; }
.mk-rare .mk-fame, .mk-epic .mk-fame, .mk-mythic .mk-fame { text-shadow: 0 .3cqw 1cqw rgba(0, 0, 0, .5); }
.mk-star {
  flex: none; width: 4.8cqw; height: 4.8cqw; justify-content: center; border-radius: 50%; font-size: 2.9cqw;
  font-family: system-ui, sans-serif;
  color: #1b1f24; background: radial-gradient(circle at 35% 30%, #ffffff, #d6dae0 60%, #aab1ba);
  box-shadow: 0 0 0 .35cqw #8d949d, 0 .5cqw .8cqw rgba(0, 0, 0, .35);
}

/* the meme art, in the frame's window; the dark ground shows through when the image is missing */
.mk-art { left: 7%; top: 10%; width: 86%; height: 42.1%; border-radius: .6cqw; overflow: hidden; background: #1c2029; }
/* Pinned to the window's four sides rather than sized in percent: a moving copy sits in a <picture> with
   display: contents, and Safari on iPhone resolved the img's 100% height against that box as auto, so a
   landscape animation drew as a band across a Full Art card (01/10/2026, Pop Cat). */
.mk-art img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.mk-art picture { display: contents; }
.mk-art[style*="background-image"] { background-size: cover; background-repeat: no-repeat; }
/* Full Art and Shiny stay recognisable: a badge over the art */
.mk-badge {
  position: absolute; left: 2cqw; top: 2cqw; font-size: 2.8cqw; font-weight: 700; color: #1a1300;
  background: #ffd84a; border-radius: 99px; padding: .3cqw 1.8cqw;
}

.mk-strip {
  left: 7%; top: 52.9%; width: 86%; height: 2.7%; justify-content: center; font-size: 3.1cqw; line-height: 1;
  color: #1f242b; white-space: nowrap; overflow: hidden;
}
.mk-body {
  box-sizing: border-box; left: 7%; top: 57.3%; width: 86%; height: 25.2%; padding: 2.6cqw 3.2cqw;
  border-radius: 2.4cqw; background: var(--mk-well); flex-direction: column; align-items: stretch;
  justify-content: flex-start; gap: 1.6cqw;
  box-shadow: inset 0 .7cqw 1.6cqw rgba(0, 0, 0, .28), inset 0 -.2cqw 0 rgba(255, 255, 255, .18), 0 .3cqw 0 rgba(255, 255, 255, .35);
}
/*
  The description, as the flavour text of a Pokémon card: bold italic, sized by face.js between 4.2 and 3.1 cqw to
  fill its well without leaving it (3.1 is 9.3 px on a 300 px card sheet), and cut at a sentence past that.
  The inner box is 79.6 × 29.6 cqw (MK_DESC in face.js): the well's 86% × 25.2% less its padding.
*/
.mk-desc {
  font-size: 3.8cqw; line-height: 1.24; font-style: italic; font-weight: 700; color: var(--mk-soft);
  overflow: hidden; overflow-wrap: anywhere; max-height: 100%;
}
/*
  « Proposée par @natsu »: the player who suggested the card. Same bold italic as the description (face.js fits
  them as one run), so nothing here may change a glyph's width: no size, no tracking, no extra character. The handle
  is a band of gold light sweeping across, on a slow loop; reduced motion keeps the gold, still.
*/
.mk-by, .mk-by b { display: inline; } /* `.mk *` makes every layer a block: the credit runs on with the text */
.mk-by b {
  font-weight: inherit; color: #ffd76a; text-shadow: none;
  background: linear-gradient(100deg, #ffb347 0%, #ffe9a8 22%, #fff 30%, #ffe9a8 38%, #ff7ab6 62%, #ffb347 100%);
  background-size: 250% 100%; -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 0 .9cqw rgba(255, 196, 92, .55));
  animation: mk-by-shine 3.2s ease-in-out infinite;
}
@keyframes mk-by-shine { 0% { background-position: 100% 0; } 60%, 100% { background-position: 0 0; } }
@media (prefers-reduced-motion: reduce) { .mk-by b { animation: none; background-position: 30% 0; } }
.mk-plate { top: 83.7%; height: 3.6%; justify-content: space-between; padding-inline: 2.6cqw 3.6cqw; color: #1a1f26; white-space: nowrap; }
.mk-plate small { font-size: 2.8cqw; font-weight: 700; }
.mk-plate b { font-size: 3cqw; font-weight: 700; }
.mk-pr b { font-family: system-ui, sans-serif; font-size: 2.6cqw; letter-spacing: .04em; }
.mk-pl { left: 6.8%; width: 40%; }
.mk-pr { left: 52.2%; width: 40%; }
.mk-site {
  left: 5%; top: 90.2%; width: 26%; height: 4%; justify-content: center; font-size: 2.6cqw; font-style: italic;
  color: var(--mk-ink); white-space: nowrap; overflow: hidden; border-radius: 99px; background: var(--mk-scrim);
}
.mk-set {
  left: 40%; top: 90.2%; width: 50%; height: 4%; justify-content: center; font-style: italic;
  font-size: 2.9cqw; color: #fff; white-space: nowrap; overflow: hidden; border-radius: 99px; background: rgba(8, 12, 26, .62);
}

/*
  Reflections. Two layers, and the pointer fades from one to the other:
  .mk::before is the prototype's shine per rarity, opened by --card-opacity, and .card__shine carries
  the resting shimmer of legendary and mythic cards, which closes as the shine opens.
  Shiny and Full Art define no --mk-shine: they keep their own treatment below.
*/
.mk::before, .mk::after {
  content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none; border-radius: inherit;
}
.mk::before {
  background-image: var(--mk-shine, none); background-size: 260% 260%;
  background-position: var(--pointer-x, 50%) var(--pointer-y, 50%);
  mix-blend-mode: soft-light; opacity: calc(var(--mk-shine-on, 0) * var(--card-opacity, 0));
}
.mk::after {
  background-image: radial-gradient(circle at var(--pointer-x, 50%) var(--pointer-y, 50%), rgba(255, 255, 255, .55), rgba(255, 255, 255, .1) 30%, rgba(0, 0, 0, .15) 75%);
  mix-blend-mode: overlay; opacity: calc(.75 * var(--card-opacity, 0));
}
.card.f-common .mk { --mk-shine-on: .5; --mk-shine: linear-gradient(115deg, rgba(255, 255, 255, 0) 30%, rgba(255, 255, 255, .8) 46%, rgba(255, 255, 255, 0) 58%); }
.card.f-rare .mk { --mk-shine-on: .6; --mk-shine: linear-gradient(115deg, rgba(255, 255, 255, 0) 28%, rgba(190, 225, 255, .85) 44%, rgba(255, 255, 255, .95) 48%, rgba(255, 255, 255, 0) 60%); }
.card.f-epic .mk { --mk-shine-on: .7; --mk-shine: repeating-linear-gradient(115deg, rgba(214, 164, 255, 0) 0%, rgba(230, 200, 255, .8) 3%, rgba(255, 255, 255, .9) 4.5%, rgba(138, 61, 255, 0) 8%); }
.card.f-legendary .mk { --mk-shine-on: .85; --mk-shine: repeating-linear-gradient(115deg, rgba(255, 227, 122, 0) 0%, rgba(255, 225, 120, .85) 4%, rgba(255, 255, 235, 1) 6%, rgba(255, 176, 32, .5) 8%, rgba(255, 227, 122, 0) 12%); }
.card.f-mythic .mk { --mk-shine-on: .9; --mk-shine: repeating-linear-gradient(115deg, #ff7eb3 0%, #ffe57a 5%, #7affc8 10%, #7ab8ff 15%, #c77aff 20%, #ff7eb3 25%); }
/* legendary and mythic shimmer at rest */
.card.f-legendary .card__shine, .card.f-mythic .card__shine {
  background-image: var(--mk-shine); background-size: 260% 260%; mix-blend-mode: soft-light;
  opacity: calc(.3 * (1 - var(--card-opacity, 0)));
}
@media (prefers-reduced-motion: no-preference) {
  .card.f-legendary .card__shine, .card.f-mythic .card__shine { animation: mk-sweep 7s ease-in-out infinite alternate; }
}
@keyframes mk-sweep { from { background-position: 0% 30%; } to { background-position: 100% 70%; } }

/*
  Shiny: the onyx card. The rarity frame disappears under a black plate engraved with gold rings
  (the two repeating radial gradients), the rim and the pills stay gold (styles.css), the meme art
  goes grey behind a gold ring, and the light follows the pointer variables holo.js sets on .card.
  The plate rides .mk-tex, which is free here: the per-rarity textures key off .card.f-<rarity>, and
  a shiny card carries .card.f-shiny instead. It is the face's first child, so it stays under the
  art and every text.
  No filter on .mk itself: it would drag the whole subtree, gold included, back to grey.
*/
.card.f-shiny .mk { --mk-ink: #f1f2f4; --mk-soft: #d4d8de; --mk-well: rgba(0, 0, 0, .5); --mk-scrim: rgba(0, 0, 0, .5); }
.card.f-shiny .mk-tex {
  background:
    repeating-radial-gradient(ellipse 140% 90% at 88% 12%, transparent 0 5.2cqw, rgba(233, 193, 90, .42) 5.2cqw 5.7cqw),
    repeating-radial-gradient(ellipse 110% 140% at 8% 98%, transparent 0 6.4cqw, rgba(233, 193, 90, .3) 6.4cqw 6.9cqw),
    linear-gradient(170deg, rgba(27, 28, 32, .95), rgba(10, 10, 12, .98) 70%);
}
.card.f-shiny .mk-art { box-shadow: inset 0 0 0 1.2cqw rgba(233, 193, 90, .5); filter: grayscale(1) contrast(1.15) brightness(.72); }
/* the rarity logo is a coloured image: grey it so it reads as engraved metal on the onyx */
.card.f-shiny .mk-logo { filter: grayscale(1) brightness(1.3) drop-shadow(0 .3cqw .5cqw rgba(0, 0, 0, .6)); }
.card.f-shiny .mk-type, .card.f-shiny .mk-star {
  color: #1a1508; box-shadow: 0 0 0 .35cqw #8a6a1c, 0 .5cqw .8cqw rgba(0, 0, 0, .5);
}
.card.f-shiny .mk-type { background: linear-gradient(180deg, #f7e3a6, #d7a93c 55%, #f0d489); }
.card.f-shiny .mk-star { background: radial-gradient(circle at 35% 30%, #fff6d8, #e9c15a 60%, #b98e2e); }
.card.f-shiny .mk-fame b, .card.f-shiny .mk-plate b, .card.f-shiny .mk-set { color: #f3d27a; }
.card.f-shiny .mk-strip, .card.f-shiny .mk-plate, .card.f-shiny .mk-fame small { color: #d4d8de; }
.card.f-shiny .mk-body {
  box-shadow: inset 0 0 0 .25cqw rgba(233, 193, 90, .3), inset 0 .7cqw 1.6cqw rgba(0, 0, 0, .5);
}
.card.f-shiny .mk-badge { background: #e9c15a; }
.card.f-shiny .mk::before {
  background: radial-gradient(circle at var(--pointer-x, 50%) var(--pointer-y, 50%), rgba(255, 248, 224, .5) 0%, rgba(233, 193, 90, .22) 20%, transparent 46%);
  mix-blend-mode: screen; opacity: 1;
}
.card.f-shiny .mk::after {
  background:
    radial-gradient(circle at 18% 22%, #ffefc0 0 1.2px, transparent 2px),
    radial-gradient(circle at 76% 14%, #fff 0 1px, transparent 1.8px),
    radial-gradient(circle at 64% 58%, #fff 0 1.4px, transparent 2.2px),
    radial-gradient(circle at 30% 80%, #ffefc0 0 1px, transparent 1.8px),
    radial-gradient(circle at 86% 86%, #fff 0 1.2px, transparent 2px);
  mix-blend-mode: normal; opacity: 1; animation: mk-twinkle 2.4s ease-in-out infinite alternate;
}
@keyframes mk-twinkle { from { opacity: .25; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .card.f-legendary .card__shine, .card.f-mythic .card__shine, .card.f-shiny .mk::after { animation: none; }
}

/*
  Small thumbnails (stakes, a staked card): under 130 px the description is under 5 px tall and the plates
  with it, so both go, and the lines around them. The name, the art and the rarity logo never do. Under
  110 px only they are left. A collection tile (150 px and up) keeps its whole face: bare plates read as broken.
*/
@container (max-width: 130px) {
  .mk > .mk-body, .mk > .mk-plate, .mk > .mk-strip, .mk > .mk-site, .mk > .mk-set, .mk-top > .mk-type { display: none; }
}
@container (max-width: 110px) {
  .mk-top > .mk-fame, .mk-top > .mk-star { display: none; }
}

/*
  Textures, one per rarity, taken from the holo patterns of the launch cards (/holo/img, GPL-3.0 like the rest of
  /holo): printed grain on commons, a rainbow maze on rares, glitter on epics and legendaries, an iridescent
  fingerprint on mythics. They sit on the frame, under the art and the text, and wake up with the pointer.
  Shiny and Full Art cards keep their own treatment.
*/
.mk-tex { position: absolute; inset: 0; pointer-events: none; border-radius: inherit; }
.card.f-common .mk-tex { background: url(/holo/img/grain.webp) 0 0 / 60cqw; mix-blend-mode: soft-light; opacity: .45; }
.card.f-rare .mk-tex {
  background-image: url(/holo/img/geometric.png), linear-gradient(115deg, #ff7eb3, #ffe57a, #7affc8, #7ab8ff, #c77aff, #ff7eb3); background-size: 16cqw, 300% 300%;
  background-position: 0 0, var(--pointer-x, 50%) var(--pointer-y, 50%); background-blend-mode: multiply;
  mix-blend-mode: color-dodge; opacity: calc(.28 + .27 * var(--card-opacity, 0));
}
.card.f-epic .mk-tex, .card.f-legendary .mk-tex {
  background-image: url(/holo/img/glitter.png), radial-gradient(circle at var(--pointer-x, 50%) var(--pointer-y, 50%), #fff8d8 0%, #ffe9a0 25%, #b08a40 60%, #3a2c10 100%);
  background-size: 45cqw, 100% 100%; background-blend-mode: multiply;
  mix-blend-mode: color-dodge; opacity: calc(.5 + .4 * var(--card-opacity, 0));
}
.card.f-mythic .mk-tex {
  background-image: url(/holo/img/illusion-mask.png), linear-gradient(115deg, #ff7eb3, #ffe57a, #7affc8, #7ab8ff, #c77aff, #ff7eb3); background-size: 70cqw, 300% 300%;
  background-position: center, var(--pointer-x, 50%) var(--pointer-y, 50%); background-blend-mode: multiply;
  mix-blend-mode: color-dodge; opacity: calc(.18 + .22 * var(--card-opacity, 0));
}

/*
  Full Art (variant 2, class mk-fa). The promise the home pages make — "the art covers the whole card" —
  taken literally: no rarity frame, no art window. Two layers of the same image, because the art is
  landscape (640×360) and the card portrait: .mk-tex blows it up, blurs it and darkens it to fill the card
  edge to edge, and .mk-art lays it sharp and nearly full width over that ground, at its own aspect ratio,
  so nothing of the meme is cropped away. The card's own background is the iridescent gradient of
  .pill.r-fullart, which the layers leave showing as a rim.
  Every text keeps the place it has on the normal face, on two panels of dark glass so it reads over any image.
*/
.mk.mk-fa {
  --mk-ink: #ffffff; --mk-soft: #eef2ff; --mk-scrim: transparent;
  background-image: linear-gradient(135deg, #ff8ad8, #8f6bff 45%, #3fd3ff);
}
/* the blurred ground: the pseudo-element carries the blur, so .mk-tex can clip its soft edges away */
.mk-fa > .mk-tex { inset: 1.1cqw; border-radius: 3.2cqw; overflow: hidden; }
.mk-fa > .mk-tex::after {
  content: ""; position: absolute; inset: 0;
  background: var(--mk-img) center / cover no-repeat;
  filter: blur(2.4cqw) saturate(1.3) brightness(.68);
  transform: scale(1.25);
}
/* the sharp art: 97.2% × 38% is the 640×360 ratio at this width, so `cover` crops next to nothing */
.mk-fa > .mk-art {
  left: 1.4%; top: 11.6%; width: 97.2%; height: 38%; border-radius: 2.4cqw; background: none;
  box-shadow: 0 .5cqw 2cqw rgba(0, 0, 0, .45);
}
.mk-fa .mk-badge { background: linear-gradient(90deg, #ff8ad8, #8f6bff, #3fd3ff); color: #fff; }

/* the two glass panels: the top row, and the band the strip, the description and the plates sit on */
.mk-fa > .mk-top, .mk-fa > .mk-fa-band {
  box-sizing: border-box; border-radius: 2.6cqw; background: rgba(8, 10, 18, .82);
  box-shadow: inset 0 0 0 .25cqw rgba(255, 255, 255, .16), 0 .4cqw 1.4cqw rgba(0, 0, 0, .3);
}
/* where backdrop-filter exists the glass thins out and lets the art through; the rule above is the fallback */
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .mk-fa > .mk-top, .mk-fa > .mk-fa-band {
    background: rgba(8, 10, 18, .68);
    -webkit-backdrop-filter: blur(1.6cqw) saturate(1.3); backdrop-filter: blur(1.6cqw) saturate(1.3);
  }
}
.mk-fa > .mk-top { left: 2.4%; top: 2.2%; width: 95.2%; height: 8.8%; padding-inline: 2.2cqw; }
.mk-fa > .mk-fa-band { left: 2.4%; top: 50.6%; width: 95.2%; height: 47.4%; }
.mk-fa > .mk-body { background: none; box-shadow: none; }
.mk-fa > .mk-strip { color: #e6eaff; }
.mk-fa > .mk-plate { color: #f2f5ff; }
.mk-fa > .mk-set { left: 30%; width: 62%; }
.mk-fa .mk-name, .mk-fa .mk-fame, .mk-fa > .mk-strip, .mk-fa .mk-desc, .mk-fa > .mk-plate, .mk-fa > .mk-site, .mk-fa > .mk-set {
  text-shadow: 0 .25cqw 1cqw rgba(0, 0, 0, .7);
}
/* the rainbow that follows the pointer, over the whole card (holo.js sets the variables on .card) */
.card.f-fullart .mk {
  --mk-shine-on: .8;
  --mk-shine: repeating-linear-gradient(115deg, #ff7eb3 0%, #ffe57a 5%, #7affc8 10%, #7ab8ff 15%, #c77aff 20%, #ff7eb3 25%);
}
/* a thumbnail that drops its lower texts has nothing to lay on the band: the art takes the room instead */
@container (max-width: 130px) {
  .mk-fa > .mk-fa-band { display: none; }
  .mk-fa > .mk-art { top: 13%; height: 62%; }
}

/*
  Full Art cards (class mk-full, `fullArt` in cards.json), drawn after a Pokémon Special Illustration Rare:
  the illustration is the card, and it stays readable because next to nothing is laid on it. No rarity frame,
  no art window, no description — two thin bands of glass and that is the whole face. Their heights add up to
  15% of the card, so the illustration is seen over 85% of it, and the glass is translucent even there.
  The markup is mmcFullArtFace in face.js, not the normal face: the classes below only ever meet its children.
*/
.mk.mk-full { --mk-ink: #ffffff; background-image: none; background-color: #0a0c12; }
/* the illustration, edge to edge, cropped at the card's own focus (the img carries object-position) */
.mk-full > .mk-art {
  left: 0; top: 0; width: 100%; height: 100%; border-radius: inherit; background-color: #0a0c12;
  box-shadow: inset 0 0 0 .5cqw rgba(255, 255, 255, .26);
}
/* the two bands: dark glass, so a white text reads over a pale illustration as well as a dark one */
.mk-full > .mk-top, .mk-full > .mk-foot {
  box-sizing: border-box; border-radius: 2.4cqw; background: rgba(6, 8, 14, .6);
  box-shadow: inset 0 0 0 .25cqw rgba(255, 255, 255, .18), 0 .4cqw 1.4cqw rgba(0, 0, 0, .35);
}
/* where backdrop-filter exists the glass thins out and lets the art through; the rule above is the fallback */
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .mk-full > .mk-top, .mk-full > .mk-foot {
    background: rgba(6, 8, 14, .54);
    -webkit-backdrop-filter: blur(1.4cqw) saturate(1.25); backdrop-filter: blur(1.4cqw) saturate(1.25);
  }
}
.mk-full > .mk-top { left: 3%; top: 2.4%; width: 94%; height: 8.6%; padding-inline: 2.6cqw; gap: 1.6cqw; }
/* MK_FULL in face.js: the band's 12 cqw less a margin, and the name as large as 5.4 */
.mk-full > .mk-top > .mk-name { height: 10.4cqw; padding: 0; background: none; }
/* the card's identity, one short line: N° 301/300 · Full Art · the set */
.mk-full > .mk-foot {
  left: 3%; top: 91%; width: 94%; height: 6.4%; justify-content: center; font-size: 2.6cqw;
  letter-spacing: .01em; color: #e9edff; white-space: nowrap; overflow: hidden;
}
/* the rarity is the card's own — FULL ART, never the base card's Commune or Rare — in gold turning iridescent */
.mk-full .mk-rar {
  flex: none; font-size: 2.8cqw; font-weight: 700; font-style: italic; letter-spacing: .06em; margin-left: auto;
  text-transform: uppercase; white-space: nowrap;
  background: linear-gradient(95deg, #ffe9a8, #ffc23d 28%, #ff9ee0 62%, #8fe8ff);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 .2cqw .5cqw rgba(0, 0, 0, .7));
}
.mk-full .mk-fame small { font-size: 2.2cqw; }
.mk-full .mk-fame b { font-size: 4.6cqw; }
.mk-full .mk-name, .mk-full .mk-fame, .mk-full > .mk-foot { text-shadow: 0 .25cqw 1cqw rgba(0, 0, 0, .8); }
/* a thumbnail: the identity line is under 6 px tall there, so the art takes the whole tile instead */
@container (max-width: 130px) {
  .mk-full > .mk-foot { display: none; }
}
/* under 110 px the top band keeps the name alone (the generic rule above already drops the Fame) */
@container (max-width: 110px) {
  .mk-full .mk-rar { display: none; }
}

/*
  A limited edition card (docs/editions-limitees.md, class mk-edi): the printing carries its own holographic
  frame, in every variant — a card pulled from an edition looks like one even when it is neither shiny nor Full
  Art. Two parts, and both ride the pointer variables holo.js already sets on .card, so an edition adds no
  animation loop of its own: the rarity shine layer (.mk::before) is repainted with a rainbow foil, and
  .mk-holo draws the rim. Nothing moves at rest — --card-opacity is 0 until a pointer touches the card, which
  is also what holo.js leaves for someone who asked for reduced motion.
  The rarity variables are set on `.card.f-<rarity> .mk`, so overriding them takes one class more.
*/
.card .mk.mk-edi {
  --mk-edi-foil: linear-gradient(115deg, #ff7eb3 0%, #ffe57a 18%, #7affc8 36%, #7ab8ff 54%, #c77aff 72%, #ff7eb3 90%);
  --mk-shine-on: .9;
  --mk-shine: repeating-linear-gradient(115deg, rgba(255, 126, 179, 0) 0%, rgba(255, 229, 122, .8) 4%, rgba(122, 255, 200, .9) 7%, rgba(122, 184, 255, .8) 10%, rgba(199, 122, 255, 0) 15%);
}
/*
  The rim. The foil fills the whole card and the mask keeps only the .9cqw ring the padding leaves, so the art
  underneath keeps its own colours; the ring slides with the tilt (--background-x/y) like the other foils.
*/
.mk-holo {
  position: absolute; inset: 0; z-index: 6; pointer-events: none; border-radius: inherit;
  padding: .9cqw;
  background: var(--mk-edi-foil);
  background-size: 260% 260%;
  background-position: var(--background-x, 50%) var(--background-y, 50%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  opacity: calc(.6 + .4 * var(--card-opacity, 0));
}
/* the set line names the edition: foil there too, so the printing reads on a still screenshot */
.mk-edi > .mk-set, .mk-edi > .mk-foot {
  background: var(--mk-edi-foil); -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 .2cqw .4cqw rgba(0, 0, 0, .7));
}
/* a thumbnail is barely 110 px of art: a .9cqw rim would eat the frame it is meant to draw */
@container (max-width: 130px) {
  .mk-holo { padding: .5cqw; }
}

/*
  The edition's one-of-a-kind card (`jackpot`, docs/editions-limitees.md): gold where the others are rainbow — the
  rim, the 1/1 plate and the foot line all read --mk-edi-foil — and a rim that turns on its own, slowly, so the
  card stands out on a still screen and in a grid. Nobody who asked for reduced motion sees it move.
*/
.card .mk.mk-jackpot {
  --mk-edi-foil: linear-gradient(115deg, #fff6c9 0%, #ffc23d 18%, #ff9a2e 32%, #fff6c9 48%, #ffd45c 64%, #c8901a 80%, #fff6c9 100%);
  --mk-shine: repeating-linear-gradient(115deg, rgba(255, 214, 92, 0) 0%, rgba(255, 246, 201, .85) 5%, rgba(255, 194, 61, .9) 8%, rgba(255, 154, 46, 0) 14%);
}
.mk-jackpot > .mk-holo {
  padding: 1.3cqw; opacity: 1;
  box-shadow: inset 0 0 2.4cqw rgba(255, 194, 61, .55);
  animation: mk-jackpot-rim 5s linear infinite;
}
@keyframes mk-jackpot-rim {
  from { background-position: 0% 50%; }
  to { background-position: 260% 50%; }
}
@media (prefers-reduced-motion: reduce) {
  .mk-jackpot > .mk-holo { animation: none; }
}
.mk-jackpot .mk-rar { background: var(--mk-edi-foil); -webkit-background-clip: text; background-clip: text; font-style: normal; letter-spacing: .02em; }
@container (max-width: 130px) {
  .mk-jackpot > .mk-holo { padding: .8cqw; }
}

/* app/app.css */
/* Game layout: sidebar on desktop, top bar + bottom tab bar on phones. Colours come from the theme tokens in /styles.css. */
/* Every :hover rule in this file sits behind @media (hover: hover). A finger has no hover: without the guard
   the browser hands the tapped element its hover state and keeps it until the reader taps somewhere else, so
   a tile stayed lifted and a chip stayed outlined long after the tap. Keyboard states stay outside the guard. */
body.app { min-height: 100vh; }
/* No double-tap zoom on app pages (the viewport meta blocks pinch); public pages keep both. */
body.app, body.app * { touch-action: manipulation; }
.side { display: none; }
.app-top { position: sticky; top: 0; z-index: 20; display: flex; align-items: center; justify-content: space-between; padding: 10px 16px; background: var(--page); border-bottom: 1px solid var(--line); }
.app-top .logo, .side .logo { font-size: 17px; }
/* The balance is also the way into the shop: a button, with a "+" reading as "add MemeCoins". */
.coins { font: inherit; font-weight: 900; color: var(--text); display: inline-flex; align-items: center; gap: 6px; background: rgba(255, 216, 74, .10); border: 1.5px solid rgba(255, 216, 74, .45); padding: 5px 8px 5px 12px; border-radius: 999px; cursor: pointer; -webkit-user-select: none; user-select: none; }
:root[data-theme="light"] .coins { background: #fff7e0; border-color: #f0d9a0; }
/* The "+" is not a second coin: no gold disc, a plain sign behind a hairline, in the text colour. */
.coins-plus { display: grid; place-items: center; align-self: stretch; margin: -5px 0 -5px 2px; padding: 0 2px 0 8px; border-left: 1.5px solid rgba(255, 216, 74, .35);
  font-style: normal; font-size: 18px; font-weight: 900; line-height: 1; color: var(--text); opacity: .7; transition: opacity .12s ease; }
:root[data-theme="light"] .coins-plus { border-left-color: #f0d9a0; }
.coins:focus-visible .coins-plus { opacity: 1; }
@media (hover: hover) { .coins:hover .coins-plus { opacity: 1; } }
/* Paywall off: the balance is only a balance, no "+" and nothing to click. */
.no-pay .coins { cursor: default; padding-right: 12px; }
.no-pay .coins-plus { display: none; }
/* The MemeCoin chip is sized in em and centred on the text's x-height ("middle"), so it holds the line at
   any font size — in running text, in a button, in a heading — instead of riding on a fixed offset. */
.coin-mark { display: inline-block; width: 1em; height: 1em; vertical-align: middle; flex: none; font-style: normal; }
.coin-mark .cm-rim { fill: var(--coin-glyph-rim); }
.coin-mark .cm-face { fill: var(--coin-glyph-face); }
.coin-mark .cm-ink { fill: var(--coin-glyph-ink); }
.amt { white-space: nowrap; display: inline-flex; align-items: center; gap: .18em; vertical-align: baseline; }
/* "Frappé": the number is never plain text. Tabular figures so counters don't jump when they change. */
/* The theme only swaps the fill and the shadow, never the background itself: a light-theme background-image
   would come back over the plain rules below and paint a brown block behind the figures. */
:root { --amt-fill: linear-gradient(180deg, var(--gold-text-light), var(--gold-text) 55%, var(--gold-text-deep)); --amt-shadow: none; }
:root[data-theme="light"] { --amt-fill: linear-gradient(180deg, var(--gold-text-light), var(--gold-text) 60%, var(--gold-text-deep)); }
/* Surfaces that stay dark in both themes (the Nombres spin overlay, the arcade boards): the light theme's deep gold
   read brown there, so they always take the dark theme's bright gold. --amt-fill is re-declared because a custom
   property built from var() is resolved where it is declared, not where it is used. */
.lucky-overlay, .ar-board { --gold-text: #ffd84a; --gold-text-deep: #f2b53a; --gold-text-light: #fff3cc;
  --amt-fill: linear-gradient(180deg, #fff3cc, #ffd84a 55%, #f2b53a); }
.amt-n { font-weight: 900; font-variant-numeric: tabular-nums;
  background: var(--amt-fill);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: var(--amt-shadow); }
/* Dense lists (auction history) keep the text colour; inside a coloured button or on an inverted surface (your rank,
   dark in light theme and yellow in dark theme) the figures take its ink, where gold would vanish; the seal stays gold. */
.amt.plain .amt-n, .hist .amt-n { background: none; color: inherit; filter: none; font-weight: inherit; }
.btn .amt-n, .rank-me .amt-n, .bet.on .amt-n { background: none; color: inherit; filter: none; }
.memecoin { display: block; }
/* light theme: deeper shadows on the hero coin so its edge holds on white */
:root[data-theme="light"] .memecoin .mc-shade { stop-color: #a86a00; }
:root[data-theme="light"] .memecoin .mc-rim { stop-color: #5a3300; }
:root[data-theme="light"] .memecoin .mc-mill { stroke: #5a3300; }
:root { --tabbar-h: calc(70px + env(safe-area-inset-bottom)); }
.view { padding: 18px 16px 110px; max-width: 1100px; margin: 0 auto; outline: none; }

.tabs, .tabbar { display: flex; }
.tabs a, .tabs button, .tabbar a, .tabbar button { display: flex; align-items: center; gap: 12px; text-decoration: none; color: var(--muted); font-weight: 800; }
.tabs button, .tabbar button { background: none; border: 0; font: inherit; font-weight: 800; cursor: pointer; }
.tabs svg, .tabbar svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; flex: none; }
.tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30; justify-content: space-around; background: var(--topbar);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border-top: 1px solid var(--line); padding: 6px 4px calc(6px + env(safe-area-inset-bottom));
  height: var(--tabbar-h); box-sizing: border-box;
}
.tabbar a, .tabbar button { flex-direction: column; gap: 3px; font-size: 11px; padding: 6px 8px; border-radius: 12px; min-width: 60px; }
.tabbar a[aria-current="page"], .tabbar button[aria-current="page"] { color: var(--gold); }

/* "Plus": every destination the bottom bar has no room for, as tiles a thumb cannot miss. */
.more-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.more-tile { display: flex; align-items: center; gap: 12px; min-height: 60px; padding: 12px 14px; border-radius: 18px; background: var(--surface); border: 1px solid var(--line);
  color: var(--text); font: inherit; font-weight: 800; font-size: 16px; text-decoration: none; text-align: left; cursor: pointer; position: relative; }
.more-tile:active { background: var(--surface-2); }
.more-ico { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 12px; background: var(--surface-2); flex: none; }
.more-ico svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
/* The name takes what is left and may wrap; the count sits in the corner, never pushed off the tile. */
.more-name { flex: 1; min-width: 0; }
/* Astride the tile's top edge, over the icon: at the right edge it covered the end of « Récompenses ». */
.more-dot { position: absolute; top: -8px; left: 34px; min-width: 22px; height: 22px; border-radius: 999px; background: #e5484d; color: #fff; font-style: normal; font-size: 12px; font-weight: 900; display: grid; place-items: center; padding: 0 6px; }
/* Phones (up to 440 px): a smaller icon and gap keep « Classement » and « Récompenses » inside the tile. */
@media (max-width: 440px) {
  .more-tile { gap: 8px; padding: 10px; }
  .more-ico { width: 32px; height: 32px; }
  .more-ico svg { width: 19px; height: 19px; }
  .more-name { font-size: 14px; }
  .more-dot { left: 26px; }
}
/* 320-px phones: the name goes under its icon rather than breaking mid-word. */
@media (max-width: 360px) {
  .more-tile { flex-direction: column; align-items: flex-start; gap: 6px; }
}

/* Collection and Echanges, two segments of one tab. */
.seg { display: flex; gap: 4px; padding: 4px; margin: 14px 0 12px; background: var(--surface); border: 1px solid var(--line); border-radius: 999px; }
.seg button { flex: 1; min-height: 44px; padding: 8px 10px; border: 0; border-radius: 999px; background: none; color: var(--muted); font: inherit; font-weight: 800; font-size: 15px; cursor: pointer;
  display: flex; align-items: center; justify-content: center; gap: 8px; }
.seg button[aria-selected="true"] { background: var(--page); color: var(--gold); box-shadow: inset 0 0 0 1px var(--line); }
.seg-dot { min-width: 20px; height: 20px; border-radius: 999px; background: #e5484d; color: #fff; font-style: normal; font-size: 12px; font-weight: 900; display: grid; place-items: center; padding: 0 5px; }
.seg-pane[hidden] { display: none; }

@media (min-width: 900px) {
  .more-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .seg { max-width: 420px; }
  /* A grid body left the 3D cards' view unpainted in Chrome; a fixed sidebar and a margin avoid it. */
  :root { --tabbar-h: 0px; }
  .app-top, .tabbar { display: none; }
  .view { margin-left: max(250px, calc((100vw - 1100px) / 2 + 125px)); }
  .side { display: flex; flex-direction: column; gap: 22px; position: fixed; left: 0; top: 0; bottom: 0; width: 250px; box-sizing: border-box; padding: 22px 16px; border-right: 1px solid var(--line); background: var(--page); }
  .side .logo { padding: 0 8px; }
  .tabs { flex-direction: column; gap: 4px; }
  .tabs a, .tabs button { padding: 12px 14px; border-radius: 14px; font-size: 16px; }
  /* La barre du bas porte « Plus » ; elle disparaît ici, et avec elle la seule porte vers les notifications
     et les réglages. Le menu latéral la reprend en dernière entrée. */
  .tabs button { width: 100%; box-sizing: border-box; text-align: left; }
  .tabs a:hover, .tabs button:hover { background: var(--surface); color: var(--text); }
  .tabs a[aria-current="page"] { background: var(--surface); color: var(--gold); box-shadow: inset 0 0 0 1px var(--line); }
  .side-foot { margin-top: auto; display: flex; flex-direction: column; border: 1px solid var(--line); border-radius: 16px; background: var(--surface); }
  /* Signed out, both rows are hidden: no empty frame. */
  .side-foot:not(:has(> :not([hidden]))) { display: none; }
  .view { padding: 30px 32px 60px; }
}

.panel h1 { font-size: clamp(26px, 4vw, 38px); margin: 0 0 6px; text-align: left; color: var(--heading); }
.panel.center { text-align: center; display: grid; justify-items: center; gap: 14px; }
.panel.center h1 { text-align: center; }
/* A centred grid item is sized from its content, and a card's cqw face has none: let the viewer take the row. */
.panel.center > .viewer { justify-self: stretch; }
.panel.center > .btn.ghost { width: auto; padding-inline: 34px; }
.muted { color: var(--muted); }
.small { font-size: 14px; }
.head-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }
.btn.ghost { background: var(--surface); color: var(--text); box-shadow: 0 0 0 1px var(--line); text-shadow: none; }
.btn.small-btn { width: auto; font-size: 16px; padding: 10px 18px; margin: 0; }
.btn:disabled { opacity: .45; cursor: default; }
.row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
input[type=number], input[type=text], input[type=search], input:not([type]) { font: inherit; font-weight: 700; color: var(--text); background: var(--input); border: 2px solid var(--line); border-radius: 12px; padding: 10px 12px; min-width: 0; }
input:focus { outline: none; border-color: var(--gold); }

/* packs */
.big-timer { font-family: "Anton", Impact, sans-serif; font-size: 64px; margin: 0; color: var(--gold); letter-spacing: .02em; }
.btn.open { max-width: 320px; }

/* collection */
.chips { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 18px; }
.chips button { font: inherit; font-weight: 800; font-size: 14px; border: 1px solid var(--line); background: var(--surface); color: var(--muted); padding: 7px 14px; border-radius: 999px; cursor: pointer; }
.chips button[aria-pressed="true"] { background: var(--active-bg); color: var(--active-ink); border-color: transparent; }
.coll-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 18px 14px; }
.coll-tile { position: relative; border: 0; background: none; padding: 0; cursor: pointer; display: grid; place-items: center; -webkit-user-select: none; user-select: none; -webkit-tap-highlight-color: transparent; touch-action: manipulation; }
.coll-tile:focus-visible { outline: 2px solid #fff; outline-offset: 2px; border-radius: 6px; }
.coll-tile .card { max-width: 170px; }
/* La pastille suit le bord de la carte, pas celui de la colonne : au-delà de 170 px la colonne est plus large
   que la vignette, et le compteur s'en allait flotter dans la gouttière, contre la carte voisine. */
.coll-tile .count { --w: min(100cqw, 170px); position: absolute; top: -6px; right: calc((100cqw - var(--w)) / 2 + 4px); z-index: 5; background: var(--active-bg); color: var(--active-ink); font-weight: 900; font-size: 13px; padding: 2px 9px; border-radius: 999px; }
.ghost-card { width: 100%; max-width: 170px; aspect-ratio: 63 / 88; border-radius: 12px; border: 2px dashed var(--line); display: grid; place-items: center; color: var(--muted); font-weight: 900; }

/* sheets */
.sheet { position: fixed; inset: 0; z-index: 50; background: rgba(0,0,0,.55); display: grid; place-items: end center; }
/* The sheet itself only scrolls; its contents live in .sheet-body. A sticky box is held inside its own grid
   area, so the close bar has to sit outside that grid to stay in sight while the body scrolls under it. */
.sheet-card { width: min(720px, 100%); max-height: 92vh; overflow: auto; background: var(--page); border: 1px solid var(--line); border-radius: 22px 22px 0 0; transition: transform .22s ease; }
.sheet-body { display: grid; gap: 14px; padding: 0 18px calc(18px + env(safe-area-inset-bottom)); }
/* The way out, always in sight: a tall sheet pushes its "Close" button below the fold. */
.sheet-top { position: sticky; top: 0; z-index: 6; display: flex; justify-content: flex-end; padding: 12px 14px 8px; background: var(--page); border-radius: 21px 21px 0 0; }
.sheet-x { width: 44px; height: 44px; flex: none; display: grid; place-items: center; padding: 0; border: 0; border-radius: 50%; background: var(--surface-2); color: var(--text); font: inherit; font-size: 19px; font-weight: 900; line-height: 1; cursor: pointer; }
.sheet-x:active { transform: scale(.92); }
@media (min-width: 900px) { .sheet { place-items: center; } .sheet-card { border-radius: 22px; } }
.sheet-card h2 { font-size: 26px; margin: 0; text-align: left; }
.sell { display: grid; gap: 10px; margin: 10px 0; }
.sell label { display: grid; gap: 6px; font-weight: 800; }
/* Six durées, deux rangées de trois : une puce seule sur sa ligne avait l'air oubliée. */
.durations { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.durations label { position: relative; }
.durations input { position: absolute; opacity: 0; }
.durations span { display: block; text-align: center; border: 1px solid var(--line); background: var(--surface); padding: 6px 12px; border-radius: 999px; font-weight: 800; font-size: 14px; cursor: pointer; }
.durations input:checked + span { background: var(--active-bg); color: var(--active-ink); border-color: transparent; }

/* market */
.market-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 16px; }
.lot { display: grid; grid-template-columns: 150px 1fr; gap: 14px; background: var(--surface); border: 1px solid var(--line); border-radius: 18px; padding: 12px; align-items: center; }
.lot .card { max-width: 150px; }
.lot-info p { margin: 0 0 6px; display: flex; justify-content: space-between; gap: 8px; }
.bid { display: flex; gap: 8px; }
.bid input { width: 90px; }
.bid .btn, .lot .btn { width: auto; font-size: 15px; padding: 9px 14px; margin: 0; }

/* trades */
.sub-h { font-size: 20px; text-align: left; margin: 20px 0 10px; }
.trade { background: var(--surface); border: 1px solid var(--line); border-radius: 18px; padding: 14px; margin-bottom: 12px; display: grid; gap: 10px; }
.trade-head { display: flex; justify-content: space-between; align-items: center; }
.status { font-weight: 800; font-size: 13px; padding: 3px 10px; border-radius: 999px; background: var(--surface-2); color: var(--muted); }
.s-accepted { color: #1db36b; }
.s-declined, .s-cancelled { color: #e5484d; }
.trade-sides { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.trade .btn { width: auto; font-size: 15px; padding: 9px 16px; margin: 0; }
.mini { display: inline-block; margin: 0 6px 6px 0; padding: 4px 10px; border-radius: 999px; font-weight: 800; font-size: 13px; color: #fff; background: var(--c, #6f7784); }
.mini.f-common { --c: #7f8a86; } .mini.f-rare { --c: #2f7bff; } .mini.f-epic { --c: #8a3dff; } .mini.f-legendary { --c: #e8950e; } .mini.f-mythic { --c: #16b8a0; } .mini.f-shiny { --c: #2a2d33; box-shadow: inset 0 0 0 1px #d7a93c; color: #f3d27a; }
.mini.f-fullart { background: linear-gradient(120deg, #ff8ad8, #8f6bff 45%, #3fd3ff); }
.coins-mini { background: var(--surface-2); color: var(--text); box-shadow: inset 0 0 0 1px var(--line); }
.trade-form { display: grid; gap: 10px; }
.trade-form h3 { margin: 8px 0 0; text-align: left; }
.trade-form label { display: grid; gap: 6px; font-weight: 800; }
.picks { display: flex; flex-wrap: wrap; }
.pick input { position: absolute; opacity: 0; }
.pick .mini { cursor: pointer; opacity: .55; }
.pick input:checked + .mini { opacity: 1; outline: 3px solid var(--gold); }

/* profile */
.profile { display: grid; gap: 14px; max-width: 640px; }
.who { display: flex; align-items: center; gap: 14px; }
.who img { width: 64px; height: 64px; border-radius: 50%; }
.who h1 { margin: 0; font-size: 24px; }
.pf-card { display: grid; gap: 14px; padding: 16px; border-radius: 22px; background: var(--surface); box-shadow: 0 0 0 1px var(--line); }
.pf-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.pf-stat { display: grid; gap: 6px; align-content: start; padding: 12px; border-radius: 14px; background: var(--page); border: 1px solid var(--line); }
.pf-stat span { color: var(--muted); font-size: 13px; font-weight: 700; }
.pf-stat b { font-size: 20px; }
.pf-bar { display: block; height: 6px; border-radius: 999px; background: var(--surface-2); overflow: hidden; }
.pf-bar i { display: block; height: 100%; border-radius: inherit; background: var(--gold); }
.pf-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 32px; }
.pf-head .sub-h { margin: 0; font-size: 18px; }
.pf-head .link-btn { font-size: 15px; padding: 10px 0; }
/* One surface, 56px rows: the whole line is the tap target. */
.pf-list { border-radius: 20px; background: var(--surface); box-shadow: 0 0 0 1px var(--line); overflow: hidden; }
.pf-list a { display: flex; align-items: center; gap: 12px; min-height: 56px; padding: 0 16px; text-decoration: none; color: var(--text); font-weight: 800; font-size: 16px; }
.pf-list a + a { border-top: 1px solid var(--line); }
.pf-list a > span:nth-child(2) { flex: 1; }
.pf-ico { display: grid; flex: none; color: var(--gold); }
.pf-ico svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.pf-chev { flex: none; color: var(--muted); font-weight: 900; }
.pf-row { display: flex; align-items: center; gap: 12px; width: 100%; box-sizing: border-box; min-height: 60px; padding: 0 16px; border: 0; border-radius: 20px; background: var(--surface); box-shadow: 0 0 0 1px var(--line); color: var(--text); font: inherit; text-align: left; cursor: pointer; }
.pf-row > span:first-child { flex: 1; display: grid; gap: 1px; }
.pf-row b { font-size: 16px; }
.pf-row small { color: var(--muted); font-weight: 700; font-size: 13px; }
.handle-form { display: flex; gap: 10px; align-items: end; flex-wrap: wrap; }
.handle-form label { display: grid; gap: 6px; font-weight: 800; flex: 1; }
.handle-form .btn { width: auto; margin: 0; }
/* First sign-in: the handle screen stands alone, without the tabs, the leaderboard or the coin pill. */
body.choosing .tabs, body.choosing .tabbar, body.choosing .top-right { display: none; }
.welcome { gap: 0; min-height: calc(100vh - 160px); align-content: center; max-width: 420px; margin: 0 auto; }
.welcome h1 { margin: 0; }
.welcome-sub { margin: 10px 0 24px; font-weight: 700; line-height: 1.45; text-wrap: balance; }
.welcome-gift { margin: -8px 0 22px; padding: 12px 14px; border-radius: 14px; font-weight: 800; line-height: 1.35; text-wrap: balance; background: linear-gradient(160deg, rgba(255,216,74,.2), rgba(255,140,40,.12)); box-shadow: 0 0 0 2px var(--gold, #ffd84a); }
.welcome-form { display: grid; justify-items: stretch; width: 100%; gap: 0; }
/* The @ sits inside the field, and the field is one big tap target: this is a phone's first screen of the game. */
.welcome-field { display: flex; align-items: center; gap: 4px; background: var(--input); border: 2px solid var(--line); border-radius: 16px; padding: 0 14px; }
.welcome-field:focus-within { border-color: var(--gold); }
.welcome-field i { font-style: normal; font-weight: 900; font-size: 24px; color: var(--muted); }
.welcome-field input { flex: 1; min-width: 0; border: 0; background: none; padding: 16px 0; font-size: 24px; font-weight: 900; border-radius: 0; }
.welcome-field input:focus { outline: none; }
.welcome-msg { margin: 10px 2px 18px; min-height: 2.6em; text-align: left; line-height: 1.3; }
.welcome-msg.bad { color: #e5484d; font-weight: 800; }
:root[data-theme="light"] .welcome-msg.bad { color: #c92a2d; }
.welcome-go { margin: 0; }
.welcome-form > .small:last-child { margin: 14px 0 0; }
@media (min-width: 900px) {
  body.choosing .side { display: none; }
  body.choosing .view { margin-left: auto; }
}

/* the Settings sheet: handle, language, theme, sign out */
.set-list { border-radius: 18px; background: var(--surface); box-shadow: 0 0 0 1px var(--line); overflow: hidden; }
.set-list > * + * { border-top: 1px solid var(--line); }
.set-row { display: flex; align-items: center; gap: 12px; width: 100%; box-sizing: border-box; min-height: 56px; padding: 0 16px; border: 0; background: none; color: var(--text); font: inherit; font-weight: 800; text-align: left; }
button.set-row { cursor: pointer; }
.set-row > span:first-child { flex: 1; }
.set-row .muted { font-weight: 700; }
/* A setting's explanation sits under its name, smaller, never glued on the same line. */
:is(.view, .sheet, body) .set-row > span:first-child > small { display: block; margin-top: 2px; font-size: 13px; line-height: 1.3; text-wrap: balance; }
.set-row:has(small) { padding-block: 10px; }
/* A two-line setting name splits evenly ("Confirmer les / grosses mises"), never one word left alone. */
.set-row > span:first-child { text-wrap: balance; }
/* A separator stays at the end of its line: the next line never starts with "·". */
.legal-links { text-wrap: balance; }
.legal-links .nw { white-space: nowrap; }
.set-row .lang-switch, .set-row .theme-switch { background: var(--page); }
.set-row .lang-switch > *, .set-row .theme-switch button { display: inline-flex; align-items: center; min-height: 44px; padding: 0 14px; }
.set-list .handle-form { display: grid; justify-items: start; gap: 10px; padding: 14px 16px; }
.set-list .handle-form label { width: 100%; }
.set-list .handle-form input { width: 100%; box-sizing: border-box; border-color: var(--gold); }
.sheet .legal-links { text-align: center; }
/* The E-mails sheet (mailSheet in app.js): the switch for all of them, then one row per category, dimmed while all are off. */
.mail-prefs { display: grid; gap: 14px; }
.mail-prefs .set-row .theme-switch { flex: none; }
.mail-prefs .mail-cats[aria-disabled="true"] { opacity: .45; }
.mail-prefs .theme-switch button:disabled { cursor: default; }
.mail-prefs .mail-off-note { margin: 0; text-wrap: balance; }

.toast { position: fixed; left: 50%; bottom: 90px; translate: -50% 20px; z-index: 60; background: var(--active-bg); color: var(--active-ink); font-weight: 800; padding: 10px 18px; border-radius: 999px; opacity: 0; transition: opacity .2s, translate .2s; pointer-events: none; }
.toast.show { opacity: 1; translate: -50% 0; }
.toast.bad { background: #e5484d; color: #fff; }
@media (min-width: 900px) { .toast { bottom: 30px; } }
.coll-tile.missing { cursor: default; opacity: .7; }
.sheet-body .close { justify-self: end; }

/* In holo.css the rotator is a grid item sized by its content, and the cqw container on the face has none,
   so it collapses to 0. As a block it takes the card's width and gets its height from aspect-ratio. */
#view .card__translater, .sheet .card__translater { display: block; }

.market-view h3 { margin: 6px 0; font-size: 16px; text-align: left; }
.spark { width: 100%; height: 60px; display: block; }
.spark polyline { fill: none; stroke: var(--gold); stroke-width: 2.5; vector-effect: non-scaling-stroke; stroke-linejoin: round; }
.locked-stat { display: inline-block; font-weight: 800; font-size: 14px; color: var(--gold-text); text-decoration: none; padding: 6px 12px; border-radius: 999px; border: 1px dashed color-mix(in srgb, var(--gold-text) 55%, transparent); }

/* packs: the home page booster, in a tile per pack type */
.packs .pack-stage { width: 100%; max-width: 420px; position: relative; }
.pack-name { margin: 0 0 12px; font-size: 24px; }
/* On a short phone the booster gives up height first, so the tile's name, the booster and its buttons fit together. */
.packs .booster { width: clamp(110px, calc((100svh - 440px) * .7), 170px); }
.pack-closed.empty .booster { filter: grayscale(.85) brightness(.75); animation: none; cursor: default; }

/* The tile's header: the pack's name, and its stock as one pip per pack the player can hold. */
.pk-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 10px; text-align: left; }
/* The name never breaks: when the stock does not fit beside it, the stock goes under it. */
.pk-title { white-space: nowrap; font-size: 20px; font-style: italic; font-weight: 900; color: var(--heading); }
.pk-stock { display: flex; align-items: center; gap: 8px; font-weight: 800; font-size: 14px; color: var(--muted); }
.pk-pips { display: flex; gap: 4px; }
.pk-pips i { width: 10px; height: 10px; border-radius: 999px; background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--line); }
.pk-pips i.on { background: var(--gold); box-shadow: none; }
/* An EXPERT holds ten packs: smaller pips keep the row beside the name at 360 px. */
.pk-pips.many { gap: 3px; }
.pk-pips.many i { width: 8px; height: 8px; }
.pk-count { font-variant-numeric: tabular-nums; white-space: nowrap; }
/* The bonus packs won on the loyalty card, spent after the timed stock: a gold ribbon on the tile that opens one. */
.pk-bonus { display: flex; align-items: center; gap: 10px; width: 100%; margin-top: 10px; padding: 10px 14px; border: 0; border-radius: 14px; background: var(--gold-grad); color: var(--on-gold); font: inherit; font-weight: 900; font-size: 16px; text-align: left; cursor: pointer; animation: bonus-pulse 1.6s ease-in-out infinite; }
.pk-bonus > span:nth-child(2) { flex: 1; }
.pk-bonus-gift { font-size: 22px; line-height: 1; }
.pk-bonus b { white-space: nowrap; font-size: 14px; }
@media (prefers-reduced-motion: reduce) { .pk-bonus, .tab-dot.bonus { animation: none; } }
.pk-body { padding: 14px 0 4px; }
.packs .pack-closed .what { margin: 10px 0 0; font-size: 15px; }
/* The buttons that open the pack stay under the thumb: pinned above the tab bar while the tile scrolls under them. */
.pk-actions { position: sticky; bottom: var(--tabbar-h); z-index: 2; display: grid; margin: 0 -4px; padding: 12px 4px 10px;
  background: linear-gradient(to bottom, transparent, var(--surface) 12px); }
.pk-actions .open-expert.waiting { justify-self: center; }
/* The landing's phone layout sends .open-pack to order 3: here it stays first, above the EXPERT pack. */
.pk-actions .open-pack { order: 0; }
/* On a 320 px phone « Pack EXPERT · 15 cartes » wrapped onto two lines and doubled the pinned block. */
@media (max-width: 359px) { .pk-actions .btn { font-size: 19px; padding-inline: 12px; } }
.pack-next { margin: 10px 0 0; font-weight: 700; font-size: 14px; color: var(--muted); min-height: 1.4em; }
.pack-next b { color: var(--text); font-variant-numeric: tabular-nums; }
.packs .odds-btn { display: inline-flex; align-items: center; margin-top: 6px; min-height: 44px; padding: 0 12px; font-size: 15px; }

/* Under 560 px the home page turns .pack-closed into a column and sends .open-pack to order 2, which is
   last on the landing but would jump over the wait line here. The app tile keeps its document order. */
@media (max-width: 560px) {
  /* The ":not([hidden])" keeps the opened pack's reveal and its CTA free of the closed tile's booster and
     EXPERT button once the pack opens: `[hidden]` alone loses to this rule's higher specificity. */
  .packs .pack-closed:not([hidden]) { display: block; }
}

/* Nothing left to open: the booster steps aside and the countdown becomes the page's answer. */
.pack-wait { display: none; }
.pack-closed.empty .pk-body { display: grid; grid-template-columns: 96px minmax(0, 1fr); align-items: center; gap: 14px; padding: 14px 0 2px; text-align: left; }
.pack-closed.empty .booster { width: 96px; }
.pack-closed.empty .what, .pack-closed.empty .open-pack, .pack-closed.empty .pack-next { display: none; }
.pack-closed.empty .pack-wait { display: grid; gap: 2px; }
.pw-label { font-weight: 800; font-size: 14px; color: var(--muted); }
.pack-wait .big-timer { display: block; line-height: 1; font-weight: 400; font-variant-numeric: tabular-nums; }
.pw-rule { font-weight: 700; font-size: 13px; color: var(--muted); }
/* Out of packs, the tile offers one thing to do now (empty-pack.js): the wait shrinks, the offer takes the width.
   A free round wears the same gold as the free Doge Road banner of the lobby. */
.ep-slot { display: none; }
.pack-closed.empty .ep-slot { display: block; margin: 12px 0 4px; }
.pack-closed.has-todo .pack-wait .big-timer { font-size: 38px; }
.ep-card { display: grid; gap: 3px; padding: 14px 16px; border-radius: 18px; text-align: left; text-decoration: none; color: var(--text); background: var(--surface); border: 1px solid var(--line); }
.ep-tag { font-size: 12px; font-weight: 900; letter-spacing: .06em; color: var(--gold); }
.ep-name { font-size: 20px; font-weight: 900; line-height: 1.15; }
.ep-sub { font-weight: 600; color: var(--muted); }
.ep-sub em { font-style: normal; font-weight: 900; color: var(--gold); }
.ep-cta { justify-self: start; margin-top: 8px; padding: 10px 16px; border-radius: 999px; font-weight: 900; background: var(--gold-grad); color: var(--on-gold); }
.ep-card.free { border: 0; background: linear-gradient(135deg, #ffe27a, #ffb938); color: #3b2500; box-shadow: 0 10px 24px rgba(255,185,56,.35); }
.ep-card.free .ep-tag, .ep-card.free .ep-sub, .ep-card.free .ep-sub em { color: #3b2500; }
.ep-card.free .ep-cta { background: #3b2500; color: #ffe27a; }
/* The referral pitch: EXPERT's three perks, the reward, the road to the next tier, one button to share. It has to
   hold whole on a 375×667 screen above the tab bar: one line per perk, the bar and the count side by side. */
.ep-card.ref { gap: 4px; border: 2px solid color-mix(in srgb, var(--gold) 55%, var(--line)); }
.ep-card.ref .ep-name { font-size: 19px; }
.ep-perks { list-style: none; margin: 4px 0; padding: 0; display: grid; gap: 3px; font-size: 15px; }
.ep-perks li { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 6px; min-width: 0; }
.ep-perks li::before { content: "✦"; color: var(--gold); font-weight: 900; }
.ep-perks b { font-weight: 900; }
.ep-perks small { color: var(--muted); font-weight: 600; font-size: 13px; }
.ep-card.ref .ep-sub { font-size: 14px; line-height: 1.3; }
.ep-how { font-size: 12.5px; line-height: 1.3; color: var(--muted); }
.ep-road { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 10px; margin-top: 4px; }
.ep-prog { display: block; height: 8px; border-radius: 999px; background: var(--line); overflow: hidden; }
.ep-prog i { display: block; width: var(--f); min-width: 8px; height: 100%; border-radius: inherit; background: var(--gold-grad); }
.ep-count { font-size: 13px; font-weight: 800; white-space: nowrap; }
.ep-acts { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; margin-top: 6px; }
.ep-acts .ep-cta { margin: 0; border: 0; font: inherit; font-weight: 900; cursor: pointer; }
.ep-more { font-size: 14px; font-weight: 800; color: var(--text); text-decoration: underline; text-underline-offset: 3px; }
/* The Jeux lobby's "À faire" list (objectives.js, lobbyTodo): the free round, the next step and the objective in
   one neutral panel, one row each. Only the first row's action is gold, so the screen never shows two gold buttons;
   the others are quiet pills. Rows are links as a whole: the whole line is the target on a phone. */
.todo-slot:empty { display: none; }
.todo-slot { margin: 0 0 12px; }
.todo { padding: 0; border-radius: 18px; background: var(--surface); border: 1px solid var(--line); overflow: hidden; }
.todo-head { display: flex; align-items: center; gap: 8px; margin: 0; padding: 12px 16px 4px; font-size: 12px; font-weight: 900; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.todo-head span { display: grid; place-items: center; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px; background: var(--surface-2); color: var(--text); font-size: 12px; letter-spacing: 0; }
.todo-list { display: grid; }
.todo-row { display: grid; grid-template-columns: 40px minmax(0, 1fr) auto; align-items: center; gap: 12px; min-height: 64px; padding: 10px 14px 10px 16px; color: var(--text); text-decoration: none; text-align: left; }
.todo-row + .todo-row { border-top: 1px solid var(--line); }
a.todo-row:active { background: var(--surface-2); }
.todo-ico { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 12px; background: var(--surface-2); font-size: 21px; line-height: 1; overflow: hidden; }
.todo-ico img { width: 100%; height: 100%; object-fit: cover; }
.todo-ico .pk-ico { height: 26px; margin: 0; vertical-align: 0; }
.todo-body { display: grid; gap: 2px; min-width: 0; }
.todo-title { font-size: 15px; font-weight: 800; line-height: 1.25; text-wrap: balance; }
.todo-sub { font-size: 13px; font-weight: 600; line-height: 1.3; color: var(--muted); text-wrap: balance; }
.todo-sub em { font-style: normal; font-weight: 800; color: var(--text); }
.todo-act { flex: none; padding: 8px 14px; border: 0; border-radius: 999px; font: inherit; font-size: 14px; font-weight: 900; white-space: nowrap; background: var(--surface-2); color: var(--text); cursor: pointer; }
.todo-list > .todo-row:first-child .todo-act { background: var(--gold-grad); color: var(--on-gold); }
.todo-act:disabled { opacity: .6; }
.obj-bar { display: block; height: 6px; margin-top: 6px; border-radius: 999px; background: var(--surface-2); overflow: hidden; }
.obj-bar i { display: block; height: 100%; border-radius: inherit; background: var(--gold); transition: width .4s; }
.obj-count { font-size: 14px; font-weight: 900; color: var(--muted); font-variant-numeric: tabular-nums; }
.obj-got { margin: 0; padding: 10px 16px 0; font-size: 14px; font-weight: 800; color: var(--text); }
@media (max-width: 380px) {
  .todo-row { grid-template-columns: 36px minmax(0, 1fr) auto; gap: 10px; padding: 10px 12px; }
  .todo-ico { width: 36px; height: 36px; font-size: 19px; }
  .todo-title { font-size: 14.5px; }
  .todo-act { padding: 7px 12px; font-size: 13.5px; }
}

/* "Recharger": two offers under the tile. Under an empty tile they carry the answer to the wait, so they get the
   full width (.wide); with packs still to open they stay a discreet strip that the "Ouvrir" button outranks. */
.recharge { margin: 12px 0 0; }
.recharge[hidden] { display: none; }
.rc-title { margin: 0 0 8px; font-weight: 800; font-size: 14px; color: var(--muted); }
.recharge:not(.wide) .rc-title { display: none; }
.rc-row { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; padding-top: 14px; }
.rc-btn { position: relative; display: grid; justify-items: center; gap: 2px; padding: 10px 8px; border: 2px solid var(--line); border-radius: 16px; background: var(--surface); color: var(--text); font: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: border-color .2s, box-shadow .2s, opacity .2s; }
.rc-btn.best { border-color: #2b4fd8; box-shadow: 0 8px 22px rgba(43, 79, 216, .22); }
.rc-btn:disabled { opacity: .55; cursor: default; }
.rc-btn.loading { opacity: .8; }
.rc-buy { font-weight: 800; font-size: 15px; line-height: 1.15; text-align: center; }
.rc-price { font-weight: 900; font-size: 18px; font-variant-numeric: tabular-nums; }
.rc-per { font-weight: 700; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
/* .view b sets text-wrap: balance further down, which would break "Meilleur prix" over two lines onto the pouch. */
.rc-btn .rc-badge { position: absolute; top: -14px; left: 50%; translate: -50% 0; padding: 2px 8px; border-radius: 999px; background: #2b4fd8; color: #fff; font-size: 11px; font-weight: 800; white-space: nowrap; text-wrap: nowrap; }
/* The pouch: the pack the player is buying, stacked. Three slips for the 3-pack, a thicker stack for the 10. */
.rc-thumb { display: flex; align-items: center; height: 42px; margin-bottom: 4px; }
.rc-thumb em { margin-left: 6px; font-style: normal; font-weight: 900; font-size: 15px; font-variant-numeric: tabular-nums; }
.rc-thumb i { width: 26px; aspect-ratio: 63 / 88; border-radius: 4px; background: url(/pack-front.webp?v=7cc6581117) center / 100% 100% no-repeat; box-shadow: 0 3px 8px rgba(0,0,0,.22); }
.rc-thumb i + i { margin-left: -16px; }
.recharge.fr .rc-thumb i { background-image: url(/pack-front-fr.webp?v=194a1166ad); }
/* Not wide: the strip shrinks to one line per offer, and the pouch steps aside. */
.recharge:not(.wide) .rc-btn { grid-template-columns: auto auto; justify-items: start; align-items: baseline; gap: 2px 6px; padding: 8px; }
.recharge:not(.wide) .rc-thumb, .recharge:not(.wide) .rc-badge, .recharge:not(.wide) .rc-verb { display: none; }
.recharge:not(.wide) .rc-row { padding-top: 0; }
.recharge:not(.wide) .rc-buy { font-size: 13px; }
.recharge:not(.wide) .rc-price { font-size: 15px; }
.recharge:not(.wide) .rc-per { grid-column: 1 / -1; }
@media (max-width: 360px) {
  .rc-buy { font-size: 14px; }
  .rc-thumb i + i { margin-left: -18px; }
}
@media (prefers-reduced-motion: reduce) { .rc-btn { transition: none; } }

/* While the stock refills: the two places where the wait is worth something. */
/* padding: 0 undoes the 34px "main section" rule of the landing sheet. */
.view .wait-more { width: 100%; max-width: 420px; margin: 4px auto 0; padding: 0; }
.wait-more[hidden] { display: none; }
.wait-more h3 { margin: 14px 2px 8px; font-size: 17px; text-align: left; }
.wait-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.wait-tile { display: grid; align-content: start; gap: 8px; padding: 14px; border-radius: 18px; background: var(--surface); border: 1px solid var(--line); color: var(--text); text-decoration: none; transition: transform .12s; }
.wait-tile:active { transform: scale(.97); }
.wt-ico { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 12px; background: var(--surface-2); color: var(--gold); }
.wt-ico svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.wait-tile b { font-size: 15px; }
.wait-tile small { font-weight: 700; font-size: 13px; color: var(--muted); }

/* Where the collection stands, right under the pack: the reason to open the next one. */
.prog { display: grid; gap: 10px; box-sizing: border-box; width: 100%; max-width: 420px; margin: 14px auto 0; padding: 14px; border-radius: 18px; background: var(--surface); border: 1px solid var(--line); color: var(--text); text-decoration: none; }
.prog-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 10px; min-width: 0; }
.prog-head > b { font-size: 15px; }
.prog-n { margin-left: auto; font-weight: 800; font-size: 14px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.prog-n b { color: var(--text); }
.prog-bar { display: block; height: 8px; border-radius: 999px; background: var(--surface-2); overflow: hidden; }
.prog-bar i { display: block; height: 100%; border-radius: inherit; background: var(--gold); }
.prog-go { display: block; min-height: 24px; font-weight: 800; font-size: 15px; }
/* On a computer the page column is the banner's width; the pack tile stays an object centred in it. */
@media (min-width: 900px) { .view .wait-more, .prog { max-width: 720px; } }
.booster.expert { filter: sepia(.5) saturate(1.8) hue-rotate(-12deg) drop-shadow(0 0 18px rgba(233,193,90,.55)); }
/* The Memes FR booster is /pack-front-fr.webp, its own sachet (Memes FR artwork, 30/09/2026); scripts/build_pack_fr.py made the old dyed one, inside
   the pouch's own silhouette: no CSS layer under the foil, so no rectangle or halo can show outside it. */
.booster.fr .b-body, .booster.fr .b-top { background-image: url(/pack-front-fr.webp?v=194a1166ad); }
.btn.expert-btn { background: linear-gradient(135deg, #ffe08a, #f2b53a 55%, #d18a12); color: #231600; text-shadow: none; box-shadow: 0 10px 24px rgba(242,181,58,.35); }
/* The pay button takes the colour of whichever plan is currently ticked, gold for the year and violet for the month. */
.btn.expert-btn.plan-month { background: linear-gradient(135deg, #c7b6ff, #8b5cf6 55%, #6d28d9); color: #fff; box-shadow: 0 10px 24px rgba(139,92,246,.35); }

/* MEMECARDS EXPERT: a paywall that reads in two seconds */
.xp { max-width: 560px; margin: 30px auto 0; padding: 0 !important; border-radius: 26px; background: var(--surface); border: 1px solid color-mix(in srgb, #f2b53a 55%, var(--line)); box-shadow: 0 24px 60px rgba(0,0,0,.25); text-align: center; }
.xp-hero { position: relative; border-radius: 25px 25px 0 0; padding: 18px 20px 16px; background: radial-gradient(120% 90% at 50% 0%, #fff3c4 0%, #ffd86b 45%, #f2b53a 100%); color: #2a1a00; }
.xp-badge { display: inline-block; font-weight: 900; font-size: 13px; letter-spacing: .12em; background: #2a1a00; color: #ffd86b; padding: 6px 14px; border-radius: 999px; }
.xp-hero h2 { margin: 10px 0 4px; font-size: clamp(25px, 6.6vw, 36px); line-height: 1.05; color: #2a1a00; text-align: center; }
.xp-hero p { margin: 0; font-weight: 800; font-size: 16px; color: #5a3b00; }
.xp-perks { list-style: none; margin: 0; padding: 14px 20px 2px; display: grid; gap: 10px; text-align: left; }
.xp-perks li { display: flex; gap: 12px; align-items: center; }
.xp-ico { flex: none; display: grid; place-items: center; width: 38px; height: 38px; border-radius: 12px; background: color-mix(in srgb, #f2b53a 18%, transparent); color: #f2b53a; }
.xp-ico svg { width: 21px; height: 21px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.xp-perks b { display: block; font-size: 16px; color: var(--text); }
.xp-perks small { display: block; font-size: 13px; color: var(--muted); font-weight: 700; }
.xp-body { padding: 8px 18px 0; }
.xp-body h3 { margin: 14px 0 8px; font-size: 16px; text-align: center; color: var(--heading); }
/* The two plans, stacked: one card to tick each, the way a subscription page lays out its offers. */
.xp-plans { display: grid; gap: 16px; margin-top: 18px; }
.plan input { position: absolute; opacity: 0; }
.plan-card { position: relative; display: grid; gap: 8px; box-sizing: border-box; padding: 16px; border-radius: 18px; cursor: pointer;
  background: var(--page); border: 2px solid var(--line); transition: border-color .15s, box-shadow .15s, background .15s, opacity .15s, transform .15s; }
.plan input:focus-visible + .plan-card { outline: 3px solid var(--gold); outline-offset: 2px; }
/* The ribbon rides the card's top-right corner, clear of the tick and of the price: solid, fixed colour per
   plan so the two offers read apart even before either is picked — that's the identity Théo asked for. */
.plan-tag { position: absolute; top: -11px; right: 12px; font-size: 11px; font-weight: 900; letter-spacing: .04em; text-transform: uppercase;
  padding: 3px 10px; border-radius: 999px; white-space: nowrap; }
.plan-year .plan-tag, .xp-up .plan-tag { background: linear-gradient(135deg, #ffe08a, #f2b53a); color: #2a1a00; }
.plan-month .plan-tag { background: linear-gradient(135deg, #c7b6ff, #8b5cf6); color: #1e1240; }
.plan-row { display: flex; align-items: flex-start; gap: 10px; min-height: 44px; }
.plan-mark { position: relative; flex: none; box-sizing: border-box; width: 24px; height: 24px; margin-top: 3px; border-radius: 50%; border: 2px solid var(--line); background: var(--card); }
.plan-mark::after { content: ""; position: absolute; inset: 0; opacity: 0; background: no-repeat center / 12px 12px
  url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%23fff' d='M6.2 11.6 2.6 8l1.4-1.4 2.2 2.2 5.8-5.8L13.4 4.4z'/%3E%3C/svg%3E"); }
/* Selection is legible on its own — 3 px border, filled dot with a check, a lift — before either colour is read. */
.plan-year input:checked + .plan-card, .xp-up.is-picked { border-width: 3px; border-color: #f2b53a; background: color-mix(in srgb, #f2b53a 10%, var(--page)); box-shadow: 0 10px 24px rgba(242,181,58,.28); transform: translateY(-1px); }
.plan-month input:checked + .plan-card { border-width: 3px; border-color: #8b5cf6; background: color-mix(in srgb, #8b5cf6 10%, var(--page)); box-shadow: 0 10px 24px rgba(139,92,246,.28); transform: translateY(-1px); }
.plan-year input:checked + .plan-card .plan-mark, .xp-up.is-picked .plan-mark { border-color: #f2b53a; background: #f2b53a; }
.plan-month input:checked + .plan-card .plan-mark { border-color: #8b5cf6; background: #8b5cf6; }
.plan input:checked + .plan-card .plan-mark::after, .xp-up.is-picked .plan-mark::after { opacity: 1; }
/* The card left unpicked steps back — same neutral border everyone starts from, no elevation, no tint — so the
   ticked one stands out even for someone who can't tell gold from violet apart. */
.xp-plans:has(.plan-year input:checked) .plan-month .plan-card, .xp-plans:has(.plan-month input:checked) .plan-year .plan-card { opacity: .72; }
.plan-txt { flex: 1; min-width: 0; text-align: left; }
.plan-name { display: block; font-weight: 900; font-size: 16px; line-height: 1.15; color: var(--text); }
/* The saving is the headline for the year plan: a pastille of its own, not just bold text among the rest. */
.plan-year .plan-name, .xp-up .plan-name { display: inline-block; white-space: nowrap; padding: 2px 10px; border-radius: 999px; background: color-mix(in srgb, #f2b53a 22%, var(--page)); color: var(--gold-text-deep); }
.plan-sub { display: block; margin-top: 2px; font-size: 12px; font-weight: 700; line-height: 1.3; color: var(--muted); }
.plan-cost { flex: none; display: grid; justify-items: end; text-align: right; }
.plan-was { font-size: 13px; font-weight: 800; color: var(--text); text-decoration: line-through; text-decoration-thickness: 2px; text-decoration-color: #e5484d; }
.plan-price { font-weight: 900; font-size: clamp(21px, 6.6vw, 30px); line-height: 1.05; white-space: nowrap; color: var(--text); }
.plan-price small, .xp-steps small { font-size: .5em; color: var(--muted); margin-left: 2px; }
.plan-per { font-size: 11px; font-weight: 800; white-space: nowrap; color: var(--muted); }
/* The gift as a pill nobody can miss: the booster itself, how many of it, and what it is. */
.plan-gift { display: flex; align-items: center; gap: 8px; justify-self: start; margin-left: 34px; padding: 4px 12px 4px 4px; border-radius: 999px;
  font-size: 13px; font-weight: 900; color: #2a1a00; background: linear-gradient(135deg, #fff1c2, #ffd86b 55%, #f2b53a); }
.plan-gift-pic { position: relative; flex: none; display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%; background: #2a1a00; }
.plan-gift-pic img { width: 20px; height: 27px; object-fit: contain; }
.plan-gift-pic i { position: absolute; right: -3px; bottom: -3px; padding: 0 4px; border-radius: 999px; font-style: normal; font-size: 10px; font-weight: 900;
  color: #2a1a00; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.35); }
.plan-code { margin-left: 34px; font-size: 12px; font-weight: 800; color: #0e8a52; }
/* Straight off the return from Stripe: what the server really credited, and the way to it. */
.xp-gift-done { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: 12px 0 4px; padding: 12px 14px; border-radius: 16px;
  text-decoration: none; color: #2a1a00; background: linear-gradient(135deg, #fff1c2, #ffd86b 55%, #f2b53a); }
.xp-gift-done b { flex: 1; text-align: left; font-size: 15px; font-weight: 900; line-height: 1.2; }
.xp-gift-done span { font-size: 13px; font-weight: 800; white-space: nowrap; }
@media (max-width: 359px) {
  .plan-gift, .plan-code { margin-left: 0; }
}
.xp-steps { list-style: none; margin: 0; padding: 0; display: flex; align-items: center; justify-content: center; gap: 4px; flex-wrap: wrap; }
/* The steps share the row, so the ladder lines up with the two plan cards above instead of floating in the middle. */
.xp-steps li:not(.arrow) { flex: 1; display: grid; justify-items: center; padding: 6px 10px; border-radius: 12px; background: var(--page); border: 1px solid var(--line); min-width: 58px; }
.xp-steps li.best { background: linear-gradient(135deg, #ffe08a, #f2b53a); border-color: transparent; }
.xp-steps li.best b, .xp-steps li.best span, .xp-steps li.best small { color: #2a1a00; }
.xp-steps li.on { outline: 3px solid #f2b53a; outline-offset: 2px; }
.xp-steps b { font-size: 15px; color: var(--text); white-space: nowrap; }
.xp-steps span { font-size: 11px; font-weight: 800; color: var(--muted); white-space: nowrap; }
.xp-steps .arrow { color: #f2b53a; font-weight: 900; font-size: 18px; }
.xp .btn { width: 100%; margin: 14px 0 0; }
/* "Ton abonnement": the plan in big letters, its state as a pill, the one date that matters next. */
.xp-me { display: grid; gap: 10px; margin: 14px 0 0; padding: 16px; border-radius: 18px; text-align: left; background: var(--page); border: 1px solid var(--line); }
.xp-me-k { font-size: 12px; font-weight: 900; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.xp-me-top { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 12px; }
.xp-me-plan { font-size: 24px; line-height: 1.1; font-weight: 900; color: var(--heading); }
.xp-pill { padding: 4px 12px; border-radius: 999px; font-size: 13px; font-weight: 900; }
.xp-pill.on { color: #0b6b3f; background: color-mix(in srgb, #1db36b 18%, var(--page)); }
.xp-pill.warn { color: #8a4b00; background: color-mix(in srgb, #f2b53a 28%, var(--page)); }
.xp-me-next { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 2px 12px; padding-top: 10px; border-top: 1px solid var(--line); }
.xp-me-next span { font-size: 13px; font-weight: 800; color: var(--muted); }
.xp-me-next b { font-size: 16px; font-weight: 900; color: var(--text); }
.xp-me small { font-size: 12px; font-weight: 700; color: var(--muted); }
/* The offer to pass to the year is a card ticked from the start: gold border, tick, tinted background — the
   .plan-year/.is-picked rules above already cover its colour, elevation and checkmark. */
.xp-up { margin-top: 14px; text-align: left; }
/* Manage and cancel: there, and quiet. The gold is for the one action in the bar. */
.xp-links { display: flex; flex-wrap: wrap; gap: 4px 20px; justify-content: center; margin-top: 12px; }
.link-btn { min-height: 44px; padding: 0 4px; border: 0; background: none; font: inherit; font-size: 14px; font-weight: 800; color: var(--muted); text-decoration: underline; cursor: pointer; }
/* What EXPERT gives is said once, and folds away. */
.xp-fold { margin-top: 14px; text-align: left; }
.xp-fold > summary { display: flex; align-items: center; justify-content: space-between; min-height: 44px; font-size: 16px; font-weight: 900; color: var(--heading); cursor: pointer; list-style: none; }
.xp-fold > summary::-webkit-details-marker { display: none; }
.xp-fold > summary::after { content: "›"; font-size: 22px; transition: transform .15s; transform: rotate(90deg); }
.xp-fold[open] > summary::after { transform: rotate(-90deg); }
.xp-fold .xp-perks { padding: 6px 0 2px; }
/* Keeping a gifted EXPERT: the same two plan cards as the offer, and when the first charge lands. */
.xp-keep { margin-top: 18px; text-align: left; }
.xp-keep > h3 { margin: 0; font-size: 17px; text-align: left; color: var(--heading); }
.xp-keep > p { margin: 4px 0 0; font-size: 13px; font-weight: 700; line-height: 1.4; color: var(--muted); }
.xp-keep .xp-promo { margin: 12px 0 0; }
.xp-acts { margin-top: 16px; padding-bottom: 8px; }
.xp-acts .xp-fine, .xp-up + .xp-acts { text-align: left; }
.xp-acts .btn { margin-top: 10px; }
.xp-body > .xp-fine { text-align: left; }
.xp .btn.ghost.manage { margin-bottom: 20px; }
.xp .expert-btn { display: grid; gap: 1px; line-height: 1.2; height: auto; min-height: 56px; padding: 10px 16px; font-size: 17px; white-space: normal; }
.xp .expert-btn small { font-size: .68em; font-weight: 800; opacity: .82; }
.xp-pay[hidden] { display: none; }
.xp-fine { margin: 8px 0 0; font-size: 12px; line-height: 1.35; color: var(--muted); font-weight: 600; }
/* The pay bar sticks to the bottom of whatever scrolls it: the page behind the tab bar, or the sheet. */
.xp-pay { position: sticky; bottom: var(--tabbar-h); z-index: 2; padding: 0 18px calc(12px + env(safe-area-inset-bottom));
  border-radius: 0 0 25px 25px; background: linear-gradient(to bottom, transparent, var(--surface) 26px); }
.xp-pay .btn { margin-top: 12px; }
/* In a sheet the overlay already covers the tab bar, so the bar sits on the sheet's own bottom edge. */
.sheet .xp-pay { bottom: 0; }
.xp { scroll-margin-top: 80px; }
/* The offer in a sheet: header and pay bar reach the sheet's edges, and the close rides the header. */
.sheet-card.pay .sheet-body { padding: 0; gap: 0; }
.sheet-card.pay .sheet-body > .xp { width: 100%; max-width: none; margin: 0; border: 0; box-shadow: none; border-radius: inherit; }
.sheet-card.pay .xp-hero, .sheet-card.pay .xp-pay { border-radius: inherit; }
.sheet-card.pay .xp-hero { border-end-start-radius: 0; border-end-end-radius: 0; }
.sheet-card.pay .xp-pay { border-start-start-radius: 0; border-start-end-radius: 0; }
.xp-hero .close { position: absolute; top: 10px; right: 10px; width: 36px; height: 36px; min-height: 0; padding: 0; margin: 0;
  display: grid; place-items: center; font-size: 17px; border-radius: 999px; background: rgba(42, 26, 0, .14); color: #2a1a00; border: 0; box-shadow: none; }
@media (hover: hover) { .xp-hero .close:hover { background: rgba(42, 26, 0, .24); } }
/* Four pillars and three arrows do not fit one phone line: the arrows go and the steps pair up. */
@media (max-width: 480px) {
  .xp-steps { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .xp-steps .arrow { display: none; }
}
.xp-perks s { text-decoration-thickness: 2px; text-decoration-color: #e5484d; color: var(--muted); }
.pack-open .viewer { width: 100%; }
.pack-open .open-again { margin-top: 16px; }
/* The end of an edition pack asks two things at once — buy another, or go back to the shelf — so they stay one
   group: side by side under the pager here, one strip pinned above the tab bar on a phone. */
.pack-open .ed-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin-top: 16px; }
.pack-open .ed-actions > * { margin: 0; }
.pack-open .ed-actions .btn { min-height: 44px; }
/* The reason the re-buy is grey belongs above the button it explains, on its own line. */
/* max-width: none undoes the 34ch cap .ed-poor gives a free-standing paragraph: capped, the line fits beside
   the buttons and flex never wraps it, which is what crushed them. */
.pack-open .ed-actions .ed-again-poor { order: -1; flex-basis: 100%; max-width: none; margin: 0; }
/* Hidden until the last card: an empty strip must not hold space, nor float over the cards on a phone. */
.pack-open .ed-actions:has(.open-again[hidden]) { display: none; }
.pack-open .ed-back[hidden] { display: none; }


/* amount: type freely, or tap a preset */
.amount { display: grid; gap: 8px; }
.amount input { width: 100%; box-sizing: border-box; font-size: 20px; font-weight: 800; }
.amount .quick { display: flex; gap: 8px; }
.amount .quick button { flex: 1; font: inherit; font-weight: 900; font-size: 15px; padding: 8px 0; border-radius: 999px; border: 1px solid var(--line); background: var(--surface); color: var(--text); cursor: pointer; }
@media (hover: hover) { .amount .quick button:hover { border-color: var(--gold); } }
.bid { display: grid; gap: 8px; }
.bid .btn { width: 100%; }
.lot { align-items: start; }
.lot-card { border: 0; padding: 0; background: none; cursor: pointer; }

/* card page history */
.history { margin-top: 6px; }
.history h3 { margin: 16px 0 8px; font-size: 17px; text-align: left; }
.hist { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.hist li { display: grid; grid-template-columns: 1fr auto; gap: 2px 10px; padding: 8px 12px; border-radius: 12px; background: var(--surface); border: 1px solid var(--line); }
.hist li > span { font-weight: 800; overflow-wrap: anywhere; }
.hist li small { grid-column: 1 / -1; color: var(--muted); font-weight: 700; font-size: 12px; }
.hist-lot { margin-bottom: 10px; }
.hist-lot p { margin: 0 0 6px; }

/* friends */
.friends-box { background: var(--surface); border: 1px solid var(--line); border-radius: 20px; padding: 6px 16px 14px; margin-bottom: 10px; }
.friends-box .sub-h { margin-top: 12px; }
.add-friend { display: flex; gap: 8px; margin-bottom: 10px; }
.add-friend input { flex: 1; min-width: 0; }
.add-friend .btn { margin: 0; }
.friends { list-style: none; margin: 0 0 8px; padding: 0; display: grid; gap: 8px; }
.friend { display: flex; align-items: center; gap: 10px; }
.friend img, .avatar-letter { width: 40px; height: 40px; border-radius: 50%; flex: none; }
.avatar-letter { display: grid; place-items: center; background: var(--active-bg); color: var(--active-ink); font-weight: 900; }
.who-txt { flex: 1; min-width: 0; display: grid; }
.who-txt small { color: var(--muted); font-weight: 700; overflow-wrap: anywhere; }
.friend .btn { margin: 0; padding: 8px 14px; font-size: 14px; width: auto; }
.icon-btn { border: 0; background: none; color: var(--muted); font-size: 16px; cursor: pointer; padding: 6px; }

/* trade sheet */
.sheet-card:has(.trade-sheet) { width: min(980px, 100%); }
.trade-sheet { display: grid; gap: 12px; }
.trade-sheet h2 .accent { color: var(--gold); }
.trade-sum { margin: 0; text-align: center; font-weight: 800; color: var(--muted); }
.tabs2 { display: grid; grid-template-columns: 1fr 1fr; border-bottom: 1px solid var(--line); }
.tabs2 button { font: inherit; font-weight: 900; font-size: 15px; background: none; border: 0; padding: 10px 4px; color: var(--muted); cursor: pointer; border-bottom: 3px solid transparent; }
.tabs2 button[aria-selected="true"] { color: var(--text); border-bottom-color: var(--gold); }
.tabs2 .badge { display: inline-grid; place-items: center; min-width: 20px; height: 20px; border-radius: 999px; background: var(--gold); color: var(--on-gold); font-size: 12px; }
.pick-grid, .pick-row { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 12px; }
.pick-row { margin-bottom: 6px; }
.pick-tile { position: relative; border: 0; background: none; padding: 0; cursor: pointer; border-radius: 12px; }
.pick-tile .card { max-width: 140px; margin: 0 auto; }
.pick-tile.on { outline: 3px solid var(--gold); outline-offset: 3px; }
.pick-tile .tick { position: absolute; top: -8px; right: -6px; z-index: 5; width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center; background: var(--gold); color: var(--on-gold); font-weight: 900; }
.coins-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.coins-row label { display: grid; gap: 6px; font-weight: 800; font-size: 14px; }
@media (max-width: 520px) { .coins-row { grid-template-columns: 1fr; } }

/* signed out: claim under the free pack */
.claim-box { margin-top: 18px; padding-top: 14px; border-top: 1px dashed var(--line); display: grid; justify-items: center; gap: 10px; }
.claim-box p { margin: 0; font-weight: 700; }
.friend { flex-wrap: wrap; }
.friend .btn { flex: none; }
.add-friend input { min-width: 120px; }

/* favourites: a star on each owned card */
.coll-tile .tile-open { border: 0; background: none; padding: 0; cursor: pointer; width: 100%; display: grid; place-items: center; }
/* the star sits in the art's top-right corner, like a stamp on the card; the tile is the
   container so the offsets follow the card width (min(100cqw, 170px)) */
.coll-tile { container-type: inline-size; }
.coll-tile .fav { --w: min(100cqw, 170px); position: absolute; z-index: 6; top: calc(var(--w) * .225); right: calc((100cqw - var(--w)) / 2 + var(--w) * .1);
  width: calc(var(--w) * .15); height: calc(var(--w) * .15); padding: 0; border: 0; background: none; cursor: pointer;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,.55)); transition: transform .15s; }
/* The same star on a card just pulled from a pack, at the same place on the card; it comes in once the card has turned. */
.pack-open .slot { container-type: inline-size; }
/* Sliding from one card to the next: the card leaving stays in the flow (it holds the viewer's height) and the one
   arriving rides over it, so only transforms move. The clip is on for the gesture alone — a reveal's burst and the
   corner tags must overflow freely once the card has landed. The padding keeps room for the odds badge, so the
   badge appearing after a reveal does not push the pager down. */
.pack-open .viewer { position: relative; padding-bottom: 30px; touch-action: pan-y; }
/* The swipe answers from the whole block — the card, the margins beside it, the site mark and the room down to the
   pager — so a finger that lands a little off still turns the card. The padding is the pager's old margin moved
   here: it gives that last strip to the gesture without moving anything on the screen. */
.pack-open .pull-zone { touch-action: pan-y; padding-bottom: 18px; }
/* The gesture has chosen the viewer: the page stops scrolling under the finger, which is what used to take the
   touch away mid-swipe. Off the gesture, pan-y keeps the page scrollable from the card itself. */
.pack-open .pull-zone.locked { touch-action: none; }
.pack-open .pager { margin-top: 0; }
/* On its way out while a finger is still down: off the screen, out of reach and out of the flow (a second card in
   the flow would double the viewer's height), removed at the next settle. */
.pack-open .slot.gone { position: absolute; inset-block-start: 0; inset-inline: 0; margin-inline: auto; opacity: 0 !important; pointer-events: none; }
.pack-open .slot { user-select: none; -webkit-user-select: none; -webkit-tap-highlight-color: transparent; }
.pack-open .viewer.sliding { overflow-x: clip; overflow-y: visible; overflow-clip-margin: 0; }
.pack-open .viewer.sliding > .slot { will-change: transform, opacity; }
.pack-open .slot.moving { position: absolute; inset-block-start: 0; inset-inline: 0; margin-inline: auto; will-change: transform, opacity; }
/* The odds of the card just pulled, under it: sober, and only once the reveal has played. */
.slot .odds-tag { position: absolute; top: calc(100% + 8px); left: 50%; translate: -50%; white-space: nowrap;
  padding: 3px 10px; border-radius: 99px; font-size: max(11px, 3.6cqw); font-weight: 700; letter-spacing: .01em;
  color: #e8dcc4; background: rgba(12,10,8,.72); box-shadow: inset 0 0 0 1px rgba(255,226,138,.35); animation: fav-in .3s ease-out both; }
.slot.reveal .odds-tag { animation-delay: 1.2s; }
/* The rate is the one of this exact card in this exact variant, never the pack's: the tag says so on a second line,
   because "1 chance sur 150 000" alone was read as the odds of any Full Art. */
.slot .odds-tag small { display: block; font-size: .78em; font-weight: 600; letter-spacing: 0; opacity: .72; }
.slot .fav { position: absolute; z-index: 6; top: 22.5cqw; right: 10cqw; width: 15cqw; height: 15cqw; padding: 0; border: 0; background: none; cursor: pointer;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,.55)); transition: transform .15s; animation: fav-in .3s ease-out both;
  -webkit-user-select: none; user-select: none; -webkit-tap-highlight-color: transparent; touch-action: manipulation; }
.slot.reveal .fav { animation-delay: 1.2s; }
@keyframes fav-in { from { opacity: 0; transform: scale(.6); } }
/* "NEW" on a card the player did not own before this pack: a sticker over the card's top-left corner. */
.slot .new-tag { position: absolute; z-index: 6; top: -1.5cqw; left: -2cqw; padding: 1.2cqw 3.4cqw; border-radius: 99px; rotate: -8deg;
  font-weight: 900; font-size: max(11px, 5cqw); letter-spacing: .06em; line-height: 1; color: #1a1300;
  background: linear-gradient(180deg, #fff27a, #ffc21a); box-shadow: 0 0 0 2px #1a1300, 0 4px 12px rgba(0,0,0,.4); animation: fav-in .3s ease-out both; }
.slot.reveal .new-tag { animation-delay: 1.2s; }
/* "DE RETOUR": a card already owned once, then staked, traded, sold or recycled, and pulled again. Blue, so a
   glance tells it from the gold "NOUVEAU", and a shade smaller since the word is longer. */
.slot .new-tag.back-tag { color: #04202e; background: linear-gradient(180deg, #b9ecff, #2fb0f0); box-shadow: 0 0 0 2px #04202e, 0 4px 12px rgba(0,0,0,.4);
  font-size: max(10px, 4.2cqw); }
.slot .fav::before { content: ""; position: absolute; inset: -11px; }
.coll-tile .fav svg, .slot .fav svg { display: block; width: 100%; height: 100%; overflow: visible; fill: none; stroke: #ffe08a; stroke-width: 2.2; stroke-linejoin: round; }
.coll-tile .fav:focus, .slot .fav:focus { outline: none; }
.coll-tile .fav:focus-visible, .slot .fav:focus-visible { outline: 2px solid #fff; outline-offset: 2px; border-radius: 6px; }
@media (hover: hover) { .coll-tile .fav:hover, .slot .fav:hover { transform: scale(1.15); } }
.coll-tile .fav.on svg, .slot .fav.on svg { fill: #ffd23f; stroke: #ffd23f; }

/* profile showcase */
.showcase { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 12px; align-items: start; }
.show-slot { position: relative; }
.show-slot .card { max-width: 140px; margin: 0 auto; }
.show-remove { position: absolute; top: -8px; right: -4px; z-index: 6; width: 28px; height: 28px; border-radius: 50%; border: 0; cursor: pointer; background: var(--active-bg); color: var(--active-ink); font-weight: 900; }
.show-add { aspect-ratio: 63 / 88; max-width: 140px; width: 100%; margin: 0 auto; border-radius: 12px; border: 2px dashed var(--line); background: none; color: var(--muted); font: inherit; font-weight: 900; cursor: pointer; display: grid; place-content: center; gap: 4px; }
.show-add span { font-size: 34px; line-height: 1; }
@media (hover: hover) { .show-add:hover { border-color: var(--gold); color: var(--gold); } }

/* the showcase picker sheet: sort and rarity chips over a grid of every card owned */
.show-pick { display: grid; gap: 12px; }
.show-pick .chips { margin-bottom: 0; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
.show-pick .chips::-webkit-scrollbar { display: none; }
.show-pick .chips button { flex: none; white-space: nowrap; }
/* Hundreds of card faces: the browser lays out and paints only the rows in view. The reserved height is a
   tile at its widest (140px of a 63/88 face), so the scrollbar does not jump as rows come into view. */
.show-pick .pick-tile { content-visibility: auto; contain-intrinsic-size: auto 196px; }
/* Under 130px the face hides its title and flavour bands: the picker asks for wider columns than the
   110px of the trade sheet, and a phone gets two columns instead of three cramped ones. */
.show-pick .pick-grid { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); }
@media (max-width: 519px) { .show-pick .pick-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.show-empty { grid-column: 1 / -1; margin: 0; }

/* market: tabs, search, sort */
.market-tabs { grid-template-columns: repeat(4, auto); justify-content: start; gap: 4px; overflow-x: auto; margin-bottom: 14px; }
.market-tabs button { white-space: nowrap; padding-inline: 12px; }
.market-tools { display: flex; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }
.market-search { flex: 1 1 200px; min-width: 0; }
.market-sort { font: inherit; font-weight: 800; color: var(--text); background: var(--input); border: 2px solid var(--line); border-radius: 12px; padding: 10px 12px; }
/* The edition filter sits next to the search and the sort, shaped like them: on a narrow phone the row wraps and
   it takes a line of its own. */
.market-edpick { display: inline-flex; align-items: center; gap: 6px; min-height: 42px; padding: 0 14px; border: 2px solid var(--line); border-radius: 12px; background: var(--input); color: var(--text); font: inherit; font-weight: 800; white-space: nowrap; cursor: pointer; touch-action: manipulation; }
.market-edpick[aria-pressed="true"] { border-color: transparent; background: var(--active-bg); color: var(--active-ink); }
.ends.soon { color: #e5484d; }
.bid-state { margin: 0 0 6px; font-weight: 800; }
.bid-state.lead { color: #1db36b; }
.bid-state.out { color: #e5484d; }

/* achievements */
.ach-badge { background: #1db36b; color: #fff; font-size: 13px; padding: 4px 10px; border-radius: 999px; }
.tabs a, .tabs button, .tabbar a, .tabbar button { position: relative; }
.tab-dot { position: absolute; top: 2px; right: 10px; min-width: 18px; height: 18px; border-radius: 999px; background: #e5484d; color: #fff; font-style: normal; font-size: 11px; font-weight: 900; display: grid; place-items: center; padding: 0 4px; }
.tabs .tab-dot { position: static; margin-left: auto; }
/* Bonus packs waiting: the Packs count turns gold, gift in front, and pulses so it is not read as one more red dot. */
.tab-dot.bonus { background: var(--gold-grad); color: var(--on-gold); gap: 2px; display: inline-flex; align-items: center; animation: bonus-pulse 1.6s ease-in-out infinite; }
.tab-dot.bonus span { font-size: 10px; }
@keyframes bonus-pulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(242,181,58,0); } 50% { box-shadow: 0 0 0 4px rgba(242,181,58,.5); } }
.ach-progress { background: var(--surface); border: 1px solid var(--line); border-radius: 18px; padding: 14px 18px; margin-bottom: 16px; }
.ach-progress > div:first-child { display: flex; justify-content: space-between; font-weight: 800; margin-bottom: 10px; color: var(--muted); }
.ach-progress b { color: #1db36b; }
.ach-bar { height: 6px; border-radius: 999px; background: var(--surface-2); overflow: hidden; margin: 6px 0 2px; }
.ach-bar.big { height: 10px; margin: 0; }
.ach-bar i { display: block; height: 100%; background: #1db36b; border-radius: inherit; }
.ach-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 12px; }
.ach { display: flex; gap: 14px; align-items: flex-start; padding: 14px 16px; border-radius: 18px; background: var(--surface); border: 1px solid var(--line); opacity: .55; filter: grayscale(.9); }
.ach.unlocked { opacity: 1; filter: none; }
.ach.unlocked:not(.claimed) { border-color: #1db36b; box-shadow: 0 0 0 1px #1db36b inset, 0 8px 24px rgba(29,179,107,.18); }
.ach-icon { font-size: 30px; line-height: 1; flex: none; }
.ach-body { flex: 1; min-width: 0; display: grid; gap: 2px; }
.ach-body b { font-size: 16px; }
.ach-body > span { color: var(--muted); font-size: 14px; font-weight: 600; }
.ach-body small { color: var(--muted); font-size: 12px; font-weight: 700; }
.ach-link { color: #1db36b; font-size: 13px; font-weight: 800; text-decoration: none; justify-self: start; }
.ach-check { display: inline-grid; place-items: center; width: 18px; height: 18px; border-radius: 5px; background: #1db36b; color: #fff; font-size: 12px; }
.ach .claim { flex: none; width: auto; margin: 0; padding: 9px 14px; font-size: 14px; align-self: center; }

/* LuckyMemes */
.burn-warn { margin: 0 0 16px; padding: 12px 16px; border-radius: 14px; font-weight: 800; background: color-mix(in srgb, #e5484d 12%, var(--surface)); border: 1px solid color-mix(in srgb, #e5484d 45%, var(--line)); }
.lucky-table { background: var(--surface); border: 1px solid var(--line); border-radius: 24px; padding: 18px; display: grid; gap: 18px; max-width: 720px; }
.lt-deal { display: grid; grid-template-columns: minmax(0, 1.2fr) auto minmax(0, 1fr); align-items: center; gap: 12px; }
.lt-slot { display: flex; align-items: center; gap: 6px; min-width: 0; touch-action: pan-y; padding-top: 12px; }
.lt-nav { flex: none; width: 42px; height: 42px; border-radius: 50%; border: 0; display: grid; place-items: center; padding: 0 0 3px; background: var(--active-bg); color: var(--active-ink); font-size: 28px; font-weight: 900; line-height: 1; cursor: pointer; box-shadow: 0 6px 16px rgba(0,0,0,.2); transition: transform .12s; z-index: 3; }
.lt-nav:active { transform: scale(.92); }
.lt-nav:disabled { opacity: .18; box-shadow: none; cursor: default; }
.lt-card { flex: 1; display: flex; align-items: center; gap: 12px; text-align: left; font: inherit; color: var(--text); background: var(--page); border: 2px solid var(--line); border-radius: 18px; padding: 10px; cursor: pointer; min-width: 0; }
.lt-thumb { position: relative; }
.lt-card-txt small { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.lt-copies { white-space: nowrap; font-style: normal; text-transform: none; letter-spacing: 0; font-size: 11px; padding: 1px 8px; border-radius: 999px; background: var(--surface-2); color: var(--muted); }
@media (hover: hover) { .lt-card:hover { box-shadow: 0 14px 32px rgba(0,0,0,.18); } }
.lt-thumb { width: 72px; flex: none; }
.lt-thumb.empty { aspect-ratio: 63 / 88; border-radius: 10px; background: var(--surface-2); display: grid; place-items: center; font-size: 30px; font-weight: 900; color: var(--muted); }
.lt-card-txt { display: grid; gap: 2px; min-width: 0; }
.lt-card-txt small { color: var(--muted); font-weight: 800; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; }
/* Two lines always held for the name (min-height): a short name no longer shrinks the card box and pulls the play
   button up; FindPepe shows the whole name, so a rare third line still shows rather than being cut. */
.lt-card-txt b { font-size: 16px; line-height: 1.2; overflow-wrap: anywhere; min-height: 2.4em; }
.lt-value { font-weight: 900; font-size: 20px; }
.lt-card-txt em { font-style: normal; font-size: 13px; font-weight: 800; color: var(--muted); text-decoration: underline; text-underline-offset: 3px; }
.lt-arrow { font-size: 28px; font-weight: 900; color: var(--muted); }
.lt-prize { display: grid; justify-items: center; text-align: center; gap: 2px; padding: 12px 8px; border-radius: 18px; background: color-mix(in srgb, #1db36b 10%, var(--page)); }
.lt-prize small { color: var(--muted); font-weight: 800; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; }
.lt-prize b { font-size: 28px; color: #1db36b; line-height: 1.1; }
@media (max-width: 520px) {
  .lt-deal { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .lt-arrow { display: none; }
  .lt-prize { grid-template-columns: auto 1fr; justify-items: start; text-align: left; padding: 10px 14px; column-gap: 12px; }
  .lt-prize b { justify-self: end; font-size: 26px; }
  .lt-thumb { width: 60px; }
}
.lt-label { margin: 0 0 8px; font-weight: 900; }
.lt-label small { color: var(--muted); }
.lt-bets .bet-outside { margin-bottom: 14px; }
.bet { font: inherit; font-weight: 900; font-size: 18px; padding: 14px 8px; border-radius: 14px; cursor: pointer; display: flex; justify-content: center; align-items: baseline; gap: 6px;
  color: var(--text); background: var(--page); border: 2px solid var(--line); transition: border-color .12s, background .12s; }
.bet small { font-size: 12px; color: var(--muted); }
@media (hover: hover) { .bet:hover { border-color: var(--active-bg); } }
.bet.on { background: var(--active-bg); color: var(--active-ink); border-color: var(--active-bg); }
.bet.on small { color: inherit; opacity: .8; }
.bet-outside { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
.bet-numbers { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; }
.bet.num { padding: 12px 0; font-size: 18px; }
.lucky-table .launch { margin: 0; }
.fast-draw { display: grid; grid-template-columns: auto 1fr; align-items: center; column-gap: 10px; row-gap: 0; padding: 10px 14px; border-radius: 14px; border: 1px solid rgba(128,128,128,.3); cursor: pointer; }
.fast-draw input { grid-row: span 2; width: 20px; height: 20px; accent-color: #f2b53a; }
.fast-draw span { font-weight: 800; }
.fast-draw small { opacity: .65; }
.reel-skip { justify-self: center; padding: 8px 18px; border-radius: 999px; border: 1px solid rgba(255,255,255,.25); background: rgba(255,255,255,.08); color: #fff; font: inherit; font-weight: 800; cursor: pointer; }
.reel-skip[hidden] { display: none; }
.lt-last { margin: -6px 0 0; text-align: center; font-weight: 700; min-height: 1.2em; }
.lt-last .win { color: #1db36b; font-weight: 900; }
.lt-last .lose { color: #e5484d; font-weight: 900; }
.lt-rules { margin-top: 10px; }
/* card picker sheet */
.stake-tile .count { position: absolute; top: -6px; right: -2px; z-index: 5; background: var(--active-bg); color: var(--active-ink); font-weight: 900; font-size: 12px; padding: 2px 8px; border-radius: 999px; }
/* The filters of the picker: one scrollable row each, within thumb reach above the grid. */
/* A grid item's automatic minimum is its content's width: without this the scrollable chip rows,
   wider than the phone, would stretch the whole sheet instead of scrolling inside it. */
.stake-pick { min-width: 0; }
.stake-pick h2 { margin-bottom: 2px; }
/* The row scrolls, the sheet does not: the end padding keeps the last chip off the edge once scrolled. */
/* The market average price: the number for an EXPERT, the "?" that opens the offer for everyone else. */
.avg-price { font-weight: 800; font-size: 13px; color: var(--muted); }
.avg-ask { display: inline-grid; place-items: center; min-width: 24px; min-height: 24px; padding: 0 7px; border: 1px solid var(--line); border-radius: 999px; background: var(--surface-2); color: var(--muted); font-weight: 900; font-size: 13px; cursor: pointer; }
.stake-pick .ask-row { display: flex; align-items: center; gap: 8px; box-sizing: border-box; width: 100%; min-height: 40px; padding: 0 12px; border-radius: 12px; font: inherit; font-weight: 800; font-size: 14px; margin-bottom: 10px; }
.stake-pick .ask-row span { display: grid; place-items: center; width: 22px; height: 22px; border-radius: 999px; background: var(--active-bg); color: var(--active-ink); }
.xp-price { display: grid; gap: 12px; text-align: center; }
.xp-price h2 { margin: 0; font-size: 20px; }
/* the draw: full-screen focus, gone by itself after the result */
.lucky-overlay { position: fixed; inset: 0; z-index: 70; display: grid; place-items: center; padding: 16px; background: rgba(6,7,10,.86); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); animation: lo-in .25s ease-out; }
.lucky-overlay.leaving { animation: lo-out .3s ease-in forwards; }
@keyframes lo-in { from { opacity: 0; } }
@keyframes lo-out { to { opacity: 0; } }
.lucky-stage { width: min(640px, 100%); display: grid; gap: 14px; text-align: center; color: #fff; }
.ls-deal { margin: 0; display: flex; align-items: center; justify-content: center; gap: 14px; font-size: 22px; }
.ls-deal b { font-size: 26px; }
.ls-deal .ls-goal { color: #3ddc8c; }
.ls-thumb { width: 64px; flex: none; }
.ls-thumb .card { max-width: 64px; }
.lucky-overlay .card__translater { display: block; }
.ls-bet { margin: 0; color: #b9bec9; font-weight: 700; }
.reel-window { position: relative; overflow: hidden; height: 120px; border-radius: 20px; background: #111318; box-shadow: inset 0 0 0 2px #2a2e38; transition: box-shadow .4s; }
/* the preview on the page: the same reel, rolling slowly on its own */
.reel-preview { display: grid; gap: 6px; text-align: center; }
.reel-preview p { margin: 0; }
.reel-window.idle { height: 104px; }
.reel-window.idle .reel-tile { width: 72px; height: 72px; font-size: 28px; }
.reel-window.idle .reel-strip { gap: 8px; animation: reel-idle 16s linear infinite; }
@keyframes reel-idle { to { transform: translateX(-800px); } }
@media (prefers-reduced-motion: reduce) { .reel-window.idle .reel-strip { animation: none; } }
.lucky-overlay.tense .reel-window { box-shadow: inset 0 0 0 2px #ffd23f, 0 0 40px rgba(255,210,63,.35); animation: tense-pulse .6s ease-in-out infinite; }
@keyframes tense-pulse { 50% { box-shadow: inset 0 0 0 2px #ffd23f, 0 0 60px rgba(255,210,63,.55); } }
.reel-window::before, .reel-window::after { content: ""; position: absolute; top: 0; bottom: 0; width: 18%; z-index: 2; pointer-events: none; }
.reel-window::before { left: 0; background: linear-gradient(90deg, #111318, transparent); }
.reel-window::after { right: 0; background: linear-gradient(270deg, #111318, transparent); }
.reel-strip { display: flex; gap: 8px; padding: 16px 0; will-change: transform; }
.reel-tile { flex: none; width: 88px; height: 88px; border-radius: 16px; display: grid; place-items: center; font: 900 36px "M PLUS Rounded 1c", system-ui, sans-serif; color: #fff; background: #1d2029; box-shadow: inset 0 0 0 2px #2f3441; }
.reel-tile.hit { background: linear-gradient(160deg, #fff3c4, #ffd86b 45%, #f2b53a); color: #2a1a00; box-shadow: 0 0 0 3px #fff, 0 0 34px rgba(255,210,63,.85); transform: scale(1.1); transition: transform .3s cubic-bezier(.3,1.6,.5,1), box-shadow .3s; }
.lucky-overlay.lost .reel-tile.hit { background: #3a3f4c; color: #fff; box-shadow: 0 0 0 3px #e5484d; }
.reel-line { position: absolute; top: 4px; bottom: 4px; left: 50%; width: 3px; margin-left: -1.5px; z-index: 3; background: #ffd23f; box-shadow: 0 0 10px #ffd23f; border-radius: 2px; }
.reel-result { min-height: 1.6em; margin: 4px 0 0; font-weight: 900; font-size: 24px; }
.reel-result.win { color: #3ddc8c; }
.reel-result.lose { color: #ff6b70; }
.lot { cursor: pointer; transition: border-color .15s, box-shadow .15s; }
@media (hover: hover) { .lot:hover { border-color: var(--gold); box-shadow: 0 6px 18px rgba(0,0,0,.08); } }
.lot .bid { cursor: auto; }

/* multipliers: the prize at a glance */
.lt-label { display: flex; align-items: center; gap: 10px; }
.mult { display: inline-grid; place-items: center; padding: 3px 12px; border-radius: 999px; font: 900 18px "M PLUS Rounded 1c", system-ui, sans-serif; color: #fff; letter-spacing: .02em;
  background: linear-gradient(135deg, #3ddc8c, #13a86a); box-shadow: 0 4px 14px rgba(29,179,107,.35); transform: rotate(-3deg); }
.mult.big { font-size: 22px; padding: 4px 14px; background: linear-gradient(135deg, #3ddc8c, #0f8f5a); box-shadow: 0 6px 18px rgba(29,179,107,.45); }
/* during the draw: your bet above the line, and the tiles that would win ringed */
.ls-pick { justify-self: center; display: grid; justify-items: center; gap: 0; margin-bottom: -6px; }
.ls-pick span { font-size: 12px; font-weight: 800; color: #b9bec9; text-transform: uppercase; letter-spacing: .06em; }
.ls-pick b { font: 900 30px "M PLUS Rounded 1c", system-ui, sans-serif; color: #fff; padding: 2px 18px; border-radius: 14px; background: #1d2029; box-shadow: 0 0 0 2px #ffd23f, 0 0 20px rgba(255,210,63,.35); }
.ls-pick i { font-style: normal; color: #ffd23f; font-size: 14px; line-height: 1.1; }
.reel-tile.mine { box-shadow: inset 0 0 0 3px #3ddc8c; color: #b8ffd9; }
.free-return { margin: 0; font-weight: 900; font-size: 18px; color: #ffd86b; animation: fr-in .5s cubic-bezier(.3,1.6,.5,1); }
@keyframes fr-in { from { opacity: 0; transform: scale(.8); } }
/* EXPERT promo under the game */
.xp-lucky { display: flex; align-items: center; gap: 14px; margin-top: 18px; padding: 16px 18px; border-radius: 20px; text-decoration: none; color: #2a1a00; max-width: 720px;
  background: radial-gradient(120% 140% at 0% 0%, #fff3c4, #ffd86b 55%, #f2b53a); box-shadow: 0 10px 26px rgba(242,181,58,.3); }
.xp-lucky-ico { font-size: 30px; flex: none; }
/* the same banner as a button: the whole offer opens in a sheet */
button.xp-lucky { width: 100%; max-width: none; border: 0; font: inherit; text-align: left; cursor: pointer; transition: transform .12s; }
button.xp-lucky:active { transform: scale(.98); }
.xp-banner .xp-lucky-ico { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 12px; background: rgba(42, 26, 0, .12); }
.xp-banner .xp-lucky-ico svg { width: 22px; height: 22px; fill: none; stroke: #2a1a00; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.xp-banner .xp-lucky-cta { min-height: 40px; display: flex; align-items: center; }
.xp-banner.on { display: flex; justify-content: space-between; font-weight: 900; font-size: 15px; min-height: 48px; }
.xp-lucky b { display: block; font-size: 17px; }
.xp-lucky small { display: block; font-weight: 700; font-size: 14px; color: #5a3b00; }
.xp-lucky-cta { margin-left: auto; flex: none; font-weight: 900; background: #2a1a00; color: #ffd86b; padding: 8px 14px; border-radius: 999px; white-space: nowrap; }
.xp-lucky.on { display: block; font-weight: 800; font-size: 14px; padding: 12px 16px; }
@media (max-width: 520px) { .xp-lucky { flex-wrap: wrap; } .xp-lucky-cta { margin-left: 44px; } }
.xp-banner > span:nth-child(2) { flex: 1 1 180px; }
@media (max-width: 520px) { .xp-banner .xp-lucky-cta { margin-left: 54px; } }

/* No ragged breaks anywhere: every text that wraps splits into lines of even width. `balance`, never `pretty`:
   pretty only saves a lone last word, and still leaves « on te dira ce / qui bouge. ».
   scripts/retours_ligne_scan.mjs finds the texts that still break unevenly. */
.view p, .view small, .view b, .view h1, .view h2, .view h3, .sheet p, .sheet h2, .lucky-overlay p { text-wrap: balance; }
/* Every other line of text too (achievement names, card names, buttons). The longhand only: it leaves
   white-space: nowrap wherever a rule sets it. */
.view, .sheet { text-wrap-style: balance; }
.view h1, .view h2, .view .sub-h, .xp-hero h2, .burn-warn { text-wrap: balance; }
.lt-open { display: inline-block; margin-top: 6px; padding: 6px 12px; border-radius: 999px; background: var(--btn-a, #ff8a3d); background: linear-gradient(90deg, #ff8a3d, #ffcf33); color: #fff; font-weight: 900; font-size: 13px; width: fit-content; text-shadow: 0 1px 0 rgba(0,0,0,.15); }
.lt-card-txt b { white-space: normal; }
.xp-lucky small { max-width: 44ch; }
.lt-slot.empty .lt-nav { display: none; }
.lt-open { white-space: nowrap; }
.lt-card-txt b { text-wrap: balance; }

/* the card in play: a deck you flip through, with the chosen card clearly marked */
.lt-stage { position: relative; flex: 1; min-width: 0; display: grid; touch-action: pan-y; }
.lt-stage .lt-card { position: relative; z-index: 2; border: 2px solid var(--active-bg); box-shadow: 0 12px 28px rgba(0,0,0,.14); padding-top: 18px; will-change: transform; }
.lt-slot.empty .lt-card { border: 2px dashed var(--line); box-shadow: none; padding-top: 10px; }
.lt-badge { position: absolute; top: -11px; left: 14px; z-index: 3; font-size: 12px; font-weight: 900; padding: 3px 10px; border-radius: 999px; background: var(--active-bg); color: var(--active-ink); box-shadow: 0 3px 10px rgba(0,0,0,.15); }
.lt-peek { position: absolute; top: 50%; z-index: 1; width: 54px; opacity: .5; pointer-events: none; }
.lt-peek.left { left: -14px; transform: translateY(-50%) rotate(-8deg); }
.lt-peek.right { right: -14px; transform: translateY(-50%) rotate(8deg); }
.lt-peek .card { max-width: 54px; }
.lt-peek .card__translater { display: block; }
.launch { white-space: nowrap; }
.reel-tile.mine.soft { box-shadow: inset 0 0 0 2px rgba(170, 225, 195, .28); color: #fff; }
.lt-card { touch-action: pan-y; user-select: none; -webkit-user-select: none; }
.open-again[hidden] { display: none; }
.open-again { animation: again-in .35s ease-out; }
@keyframes again-in { from { opacity: 0; transform: translateY(6px); } }

.link-btn { font: inherit; font-weight: 800; color: var(--text); background: none; border: 0; padding: 0; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.sheet table.odds { width: 100%; border-collapse: collapse; font-weight: 700; margin: 6px 0; }
.sheet table.odds th, .sheet table.odds td { text-align: left; padding: 8px 4px; font-size: 14px; border-bottom: 1px solid var(--line); }
/* One column per slot: cards 1 to 3, card 4, card 5. The rates read better against the right edge. */
.sheet table.odds th:not(:first-child), .sheet table.odds td:not(:first-child) { text-align: right; }
.sheet table.odds th { color: var(--muted); font-size: 12px; text-transform: uppercase; }
.sheet h3 { margin: 14px 0 2px; text-align: left; }
.xp-consent { display: flex; gap: 10px; align-items: flex-start; margin-top: 16px; font-size: 13px; font-weight: 700; color: var(--muted); text-align: left; cursor: pointer; }
.xp-consent input { width: 20px; height: 20px; flex: none; margin-top: 1px; accent-color: #2a1a00; }
.xp-consent a { color: inherit; }
.legal-links { margin: 8px 0 0; font-size: 13px; color: var(--muted); }
.legal-links a { color: inherit; }
.lt-rules a { color: inherit; font-weight: 800; }
.btn.claim-btn { background: linear-gradient(135deg, #3ddc8c, #13a86a); color: #fff; text-shadow: 0 1px 0 rgba(0,0,0,.15); box-shadow: 0 8px 20px rgba(29,179,107,.3); white-space: nowrap; }

/* friends page and player pages */
.friends-link { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 14px 16px; margin-bottom: 14px; border-radius: 16px; background: var(--surface); border: 1px solid var(--line); text-decoration: none; color: var(--text); font-weight: 800; }
.friends-link b { color: #1db36b; }
.friends-page .head-row .row { gap: 8px; }
.friends-page .head-row .btn { margin: 0; }
.friend-filter, .find-input { width: 100%; box-sizing: border-box; margin-bottom: 10px; }
.friend-list { list-style: none; margin: 0 0 8px; padding: 0; display: grid; gap: 8px; }
.friend-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 12px; border-radius: 16px; background: var(--surface); border: 1px solid var(--line); }
.friend-row[hidden] { display: none; }
.friend-main { display: flex; align-items: center; gap: 12px; text-decoration: none; color: var(--text); min-width: 0; }
.friend-main img, .friend-main .avatar-letter, .find-row img, .find-row .avatar-letter { width: 44px; height: 44px; border-radius: 50%; flex: none; }
.friend-actions { display: flex; gap: 8px; align-items: center; }
.friend-actions .btn { margin: 0; width: auto; padding: 8px 14px; font-size: 14px; text-decoration: none; }
.find-results { display: grid; gap: 8px; min-height: 120px; align-content: start; }
.find-row { display: flex; align-items: center; gap: 12px; padding: 8px 4px; }
.find-row .who-txt { flex: 1; text-decoration: none; color: var(--text); }
.find-row .btn { margin: 0; width: auto; padding: 8px 14px; font-size: 14px; }
.back-link { display: inline-block; margin-bottom: 12px; color: var(--muted); font-weight: 800; text-decoration: none; }
.player-tabs { margin-bottom: 14px; }
.player-body[hidden] { display: none; }
.player-body .pick-tile { cursor: default; position: relative; }
.player-body .count { position: absolute; top: -6px; right: 0; z-index: 5; background: var(--active-bg); color: var(--active-ink); font-weight: 900; font-size: 12px; padding: 2px 8px; border-radius: 999px; }

/* referrals (/app/friends), three blocks read top to bottom: what you get and the link to share, how a friend
   counts, the three tiers. The app's own type and tokens in both themes; gold marks the next tier and the main
   action, green what can be claimed or is done. */
.ref-box { display: grid; gap: 24px; margin-bottom: 28px; }
.ref-box h2, .ref-box h3 { text-align: left; margin: 0; }

/* ---- What you get, and the link: the whole card in the app's purple, with a slow light show behind it ---- */
.rf-hero { position: relative; isolation: isolate; overflow: hidden; display: grid; gap: 18px; padding: 22px 18px; border-radius: 24px;
  border: 1px solid color-mix(in srgb, var(--hero-glow) 70%, var(--line));
  background:
    radial-gradient(70% 90% at 100% 0, var(--hero-glow), transparent 70%),
    radial-gradient(60% 80% at 0 100%, color-mix(in srgb, var(--hero-glow) 75%, transparent), transparent 72%),
    linear-gradient(160deg, color-mix(in srgb, var(--hero-glow) 30%, var(--hero-base)), var(--hero-base));
  box-shadow: 0 18px 50px -24px var(--hero-glow); }
.rf-hero > :not(.rf-fx) { position: relative; z-index: 1; }
/* Two blurred lights drift across the card; six small cards float up behind the text. Decoration only. */
.rf-fx { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
.rf-fx b { position: absolute; width: 60%; aspect-ratio: 1; border-radius: 50%; filter: blur(40px); opacity: .55; will-change: transform; }
.rf-fx b:nth-of-type(1) { left: -15%; top: -40%; background: radial-gradient(closest-side, #9b5cff, transparent); animation: rf-drift 14s ease-in-out infinite alternate; }
.rf-fx b:nth-of-type(2) { right: -20%; bottom: -45%; background: radial-gradient(closest-side, #ff7ad9, transparent); opacity: .35; animation: rf-drift 18s ease-in-out -6s infinite alternate-reverse; }
.rf-fx i { position: absolute; bottom: -40px; width: 22px; aspect-ratio: 63 / 88; border-radius: 4px; opacity: 0;
  border: 1.5px solid color-mix(in srgb, #fff 55%, transparent);
  background: linear-gradient(150deg, color-mix(in srgb, #ffd84a 70%, transparent), color-mix(in srgb, #9b5cff 60%, transparent));
  box-shadow: 0 0 14px color-mix(in srgb, #ffd84a 40%, transparent); animation: rf-float 11s linear infinite; will-change: transform, opacity; }
.rf-fx i:nth-of-type(1) { left: 6%; animation-delay: 0s; }
.rf-fx i:nth-of-type(2) { left: 22%; width: 16px; animation-delay: -4s; animation-duration: 13s; }
.rf-fx i:nth-of-type(3) { left: 41%; width: 18px; animation-delay: -8s; animation-duration: 12s; }
.rf-fx i:nth-of-type(4) { left: 63%; width: 14px; animation-delay: -2s; animation-duration: 15s; }
.rf-fx i:nth-of-type(5) { left: 80%; width: 20px; animation-delay: -6s; }
.rf-fx i:nth-of-type(6) { left: 93%; width: 15px; animation-delay: -10s; animation-duration: 14s; }
@keyframes rf-drift { to { transform: translate(35%, 30%) scale(1.15); } }
@keyframes rf-float {
  0% { transform: translateY(0) rotate(-12deg); opacity: 0; }
  15% { opacity: .55; }
  80% { opacity: .35; }
  100% { transform: translateY(-460px) rotate(24deg); opacity: 0; }
}
.rf-pitch { display: grid; gap: 8px; min-width: 0; }
.rf-hero h2 { font-weight: 900; font-style: italic; font-size: clamp(28px, 7.4vw, 38px); line-height: 1.1; color: var(--heading); }
.rf-lead { margin: 0; max-width: 34em; font-weight: 700; font-size: 16px; line-height: 1.55; color: color-mix(in srgb, var(--heading) 78%, transparent); }
.rf-lead b { font-weight: 900; color: var(--heading); white-space: nowrap; }
.rf-nw { white-space: nowrap; }
.rf-lead .rf-nw b { background: linear-gradient(90deg, var(--gold-text), #ff9f43, var(--gold-text)) 0 0 / 200% 100%; -webkit-background-clip: text; background-clip: text; color: transparent; animation: rf-shine 4s linear infinite; }
@keyframes rf-shine { to { background-position: -200% 0; } }
.rs-i.rf-lead-i { display: inline-grid; vertical-align: -4px; width: 22px; height: 22px; margin: 0 2px 0 6px; font-size: 13px; color: var(--heading); background: color-mix(in srgb, var(--heading) 12%, transparent); border-color: color-mix(in srgb, var(--heading) 30%, transparent); }
/* `minmax(0, 1fr)` : sans elle, l'adresse du lien (une seule ligne, sans coupure possible) imposait sa
   largeur à la colonne, et le bouton « Copier » comme « Partager mon lien » sortaient de la carte. */
.rf-link { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; min-width: 0; }
.rf-label { font-weight: 800; font-size: 13px; color: color-mix(in srgb, var(--heading) 70%, transparent); }
.rf-copy { display: flex; align-items: center; gap: 8px; width: 100%; min-height: 52px; padding: 6px 6px 6px 14px; border-radius: 14px;
  border: 1px solid color-mix(in srgb, var(--hero-glow) 60%, var(--line)); background: color-mix(in srgb, var(--input) 82%, transparent); color: var(--text); font: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: border-color .15s; }
/* Le lien se lit en entier, quitte à passer sur deux lignes : une ellipsis en plein milieu d'une adresse
   qu'on vient copier ne dit rien à personne. */
.rc-url { flex: 1; min-width: 0; overflow-wrap: anywhere; text-align: left; font-weight: 700; font-size: 15px; }
.rc-act { flex: none; padding: 8px 14px; border-radius: 10px; font-weight: 900; font-size: 14px; color: var(--gold-text); background: color-mix(in srgb, var(--gold) 14%, transparent); }
@media (hover: hover) { .rf-copy:hover { border-color: color-mix(in srgb, var(--gold) 55%, var(--line)); } }
.rf-copy:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.rf-copy.done { border-color: #1db36b; }
.rf-copy.done .rc-act { color: #1db36b; background: color-mix(in srgb, #1db36b 14%, transparent); }
/* A light sweeps across the share button every few seconds: the one thing on the card to press. */
.btn.rf-share { position: relative; overflow: hidden; display: flex; align-items: center; justify-content: center; gap: 10px; margin: 0; font-size: 18px; }
.btn.rf-share::after { content: ""; position: absolute; inset: 0; background: linear-gradient(100deg, transparent 30%, rgba(255,255,255,.45) 50%, transparent 70%); transform: translateX(-120%); animation: rf-sweep 3.6s ease-in-out 1s infinite; pointer-events: none; }
@keyframes rf-sweep { 0%, 55% { transform: translateX(-120%); } 100% { transform: translateX(120%); } }
.rf-share .share-mark { width: 20px; height: 20px; }
.rf-preview { justify-self: center; padding: 2px 4px; font-weight: 800; font-size: 14px; color: color-mix(in srgb, var(--heading) 72%, transparent); text-decoration: none; }
@media (hover: hover) { .rf-preview:hover { color: var(--heading); text-decoration: underline; } }
.rf-welcome { display: flex; align-items: center; gap: 10px; margin: 0; padding: 12px 14px; border-radius: 16px; border: 1px solid var(--line); background: var(--surface); font-weight: 800; font-size: 14px; }
.rf-welcome .coin-mark { font-size: 22px; }

/* ---- Blocks: a title like the page's other sections, then their content ---- */
/* padding: 0 beats the landing page's `main section` padding, which reaches the app: the box's gap is the only spacing. */
.rf-block { display: grid; gap: 12px; padding: 0; }
.ref-box .rf-h { font-weight: 900; font-style: italic; font-size: 20px; line-height: 1.2; color: var(--heading); }

/* ---- How a friend counts: three numbered steps in one card ---- */
.rf-steps { list-style: none; margin: 0; padding: 0; display: grid; border-radius: 20px; border: 1px solid var(--line); background: var(--surface); overflow: hidden; }
.rf-steps li { display: flex; align-items: flex-start; gap: 12px; padding: 14px 16px; min-width: 0; }
.rf-steps li + li { border-top: 1px solid var(--line); }
.rs-n { flex: none; display: grid; place-items: center; width: 28px; height: 28px; border-radius: 50%; font-weight: 900; font-size: 14px; color: var(--on-gold); background: var(--gold-grad); }
.rf-steps li > span:last-child { display: grid; gap: 2px; min-width: 0; }
.rf-steps b { font-weight: 900; font-size: 16px; line-height: 1.3; color: var(--heading); }
.rf-steps small { font-weight: 700; font-size: 14px; line-height: 1.4; color: var(--muted); }

/* ---- The road to 100: one card, one line through the three tiers ----
   Phone: the line runs down the left, a dot per tier, the reward beside it. Computer: the line runs across the top,
   the dots at the middle of three equal columns. Each tier draws the half-line before its dot (.rt-a) and after it
   (.rt-b); --f is how much of that half is filled. */
.rf-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 12px; }
.rf-count { margin: 0; font-weight: 700; font-size: 14px; color: var(--muted); }
.rf-count b { font-weight: 900; color: var(--heading); font-variant-numeric: tabular-nums; }
.rf-tiers { --node: 40px; --node-y: 34px; list-style: none; margin: 0; padding: 0; display: grid; border-radius: 20px; border: 1px solid var(--line); background: var(--surface); overflow: hidden; }
.rf-tier { position: relative; display: grid; grid-template-columns: var(--node) minmax(0, 1fr); column-gap: 14px; min-width: 0; padding: 14px 16px; }
.rf-tier.next { background: color-mix(in srgb, var(--gold) 7%, transparent); }
.rf-tier.ready { background: color-mix(in srgb, #1db36b 8%, transparent); }
.rt-track { position: absolute; left: calc(16px + var(--node) / 2 - 2px); top: 0; bottom: 0; width: 4px; }
.rt-track i { position: absolute; left: 0; right: 0; background: color-mix(in srgb, var(--muted) 22%, transparent); overflow: hidden; }
.rt-a { top: 0; height: var(--node-y); }
.rt-b { top: var(--node-y); bottom: 0; }
.rt-track i::after { content: ""; position: absolute; left: 0; right: 0; top: 0; height: calc(var(--f) * 100%); background: var(--gold); }
.rf-tier:first-child .rt-a { top: 14px; height: calc(var(--node-y) - 14px); border-radius: 2px 2px 0 0; }
.rf-tier:last-child .rt-b { display: none; }
.rt-node { position: relative; z-index: 1; grid-row: 1; align-self: start; display: grid; place-items: center; width: var(--node); height: var(--node); margin-top: calc(var(--node-y) - 14px - var(--node) / 2);
  border-radius: 50%; font-weight: 900; font-size: 14px; font-variant-numeric: tabular-nums; color: var(--muted); background: var(--surface-2); border: 2px solid color-mix(in srgb, var(--muted) 30%, transparent); }
.rf-tier.next .rt-node { color: var(--gold-text); border-color: var(--gold); background: var(--surface); animation: rf-ping 2.4s ease-out infinite; }
.rf-tier.top .rt-node { width: calc(var(--node) + 6px); height: calc(var(--node) + 6px); margin-left: -3px; margin-top: calc(var(--node-y) - 17px - var(--node) / 2); }
.rf-tier:is(.ready, .claimed) .rt-node { color: #fff; border-color: #1db36b; background: #1db36b; }
.rf-tier.ready .rt-node { animation: rf-ping-ok 1.8s ease-out infinite; }
@keyframes rf-ping { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--gold) 55%, transparent); } 100% { box-shadow: 0 0 0 12px transparent; } }
@keyframes rf-ping-ok { 0% { box-shadow: 0 0 0 0 rgba(29, 179, 107, .6); } 100% { box-shadow: 0 0 0 12px transparent; } }
/* Green only for the stretch that led to a tier already reached; the stretch toward the next one stays gold. */
.rf-tier:is(.ready, .claimed) .rt-a::after, .rf-tier:has(+ .rf-tier:is(.ready, .claimed)) .rt-b::after { background: #1db36b; }
.rt-body { grid-column: 2; grid-row: 1; display: grid; gap: 4px; min-width: 0; }
.rt-goal { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 8px; min-height: 26px; font-weight: 800; font-size: 13px; color: var(--muted); }
.rt-goal em { padding: 2px 8px; border-radius: 999px; font-style: normal; font-weight: 900; font-size: 11px; letter-spacing: .05em; text-transform: uppercase; white-space: nowrap;
  color: var(--gold-text); background: color-mix(in srgb, var(--gold) 14%, transparent); }
.rt-prize { display: flex; align-items: center; gap: 10px; }
.rs-i { position: relative; flex: none; display: grid; place-items: center; width: 26px; height: 26px; padding: 0; border-radius: 50%;
  border: 1px solid var(--line); background: var(--surface-2); color: var(--muted); font: italic 800 14px/1 Georgia, serif; cursor: pointer; }
.rs-i::before { content: ""; position: absolute; inset: -9px; }
@media (hover: hover) { .rs-i:hover { color: var(--heading); border-color: var(--muted); } }
.rt-xp { font-weight: 900; font-size: 20px; line-height: 1.2; color: var(--heading); }
.rf-tier.top .rt-xp { background: linear-gradient(90deg, var(--gold-text), #ff9f43); -webkit-background-clip: text; background-clip: text; color: transparent; }
.rt-coins { justify-self: start; display: inline-flex; align-items: center; gap: 6px; font-weight: 800; font-size: 15px; color: var(--gold-text); }
.rt-coins .coin-mark { font-size: 18px; }
.rt-foot { display: flex; align-items: center; min-height: 28px; margin-top: 4px; }
.rt-foot small { font-weight: 800; font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.rt-foot .btn { margin: 0; padding: 0 18px; height: 38px; line-height: 38px; font-size: 15px; }
.rt-ok { font-weight: 900; font-size: 14px; color: #1db36b; }
.rf-fine { margin: 0; font-weight: 700; font-size: 13px; line-height: 1.45; color: var(--muted); }
@media (prefers-reduced-motion: reduce) {
  .rf-fx i, .rf-fx b, .rf-lead .rf-nw b, .btn.rf-share::after, .rf-tier .rt-node { animation: none; }
  .rf-fx i { display: none; }
}

.rf-people { padding: 12px 16px; border-radius: 16px; background: var(--surface); border: 1px solid var(--line); }
.rf-people summary { cursor: pointer; font-weight: 900; }
.rf-people ul { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 6px; }
.rf-people li { display: flex; justify-content: space-between; gap: 10px; font-size: 14px; }
.rf-people a { color: var(--text); font-weight: 800; text-decoration: none; }
.rf-people .ok { color: #1db36b; font-weight: 800; }

/* The tier sheet: what the tier gives, then what EXPERT is. No price, no button to buy it. */
.ref-sheet { display: grid; gap: 12px; }
.ref-sheet h3 { margin: 6px 0 0; font-size: 19px; text-align: left; }
.ref-sheet p { margin: 0; }
.rsh-gains { display: grid; gap: 8px; }
.rsh-gains > div { display: grid; grid-template-columns: 34px 1fr; column-gap: 10px; align-items: center; padding: 12px 14px; border-radius: 16px; color: var(--on-gold); background: var(--gold-grad); }
.rsh-gains span { grid-row: span 2; display: grid; place-items: center; font-size: 26px; line-height: 1; }
.rsh-gains .coin-mark { font-size: 32px; }
.rsh-gains b { font-weight: 900; font-size: 17px; }
.rsh-gains small { font-weight: 700; font-size: 13px; opacity: .82; }

/* Computer: the pitch beside the link, the steps and the tiers in three columns whose bars and feet line up. */
@media (min-width: 900px) {
  .rf-hero { grid-template-columns: minmax(0, 1.15fr) minmax(300px, 1fr); align-items: center; gap: 32px; padding: 28px; }
  .rf-steps { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .rf-steps li { padding: 16px 18px; }
  .rf-steps li + li { border-top: 0; border-left: 1px solid var(--line); }
  .rf-tiers { --node-y: 30px; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .rf-tier { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto 1fr; row-gap: 14px; padding: calc(var(--node-y) - var(--node) / 2) 20px 18px; text-align: center; }
  .rf-tier + .rf-tier { border-left: 1px solid var(--line); }
  .rf-tier.next { background: linear-gradient(180deg, color-mix(in srgb, var(--gold) 9%, transparent), transparent 75%); }
  .rt-track { left: 0; right: 0; top: calc(var(--node-y) - 2px); bottom: auto; width: auto; height: 4px; }
  .rt-a { top: 0; bottom: 0; left: 0; width: 50%; height: auto; }
  .rt-b { top: 0; bottom: 0; left: 50%; right: 0; }
  .rf-tier:first-child .rt-a { top: 0; height: auto; left: 20px; width: calc(50% - 20px); border-radius: 2px 0 0 2px; }
  .rt-track i::after { top: 0; bottom: 0; height: auto; width: calc(var(--f) * 100%); }
  .rt-node, .rf-tier.top .rt-node { grid-column: 1; justify-self: center; margin: 0; }
  .rf-tier.top .rt-node { margin-top: -3px; margin-bottom: -3px; }
  .rt-body { grid-column: 1; grid-row: 2; grid-template-rows: auto auto auto 1fr; justify-items: center; }
  .rt-goal, .rt-prize { justify-content: center; }
  .rt-coins { justify-self: center; }
  .rt-foot { align-self: end; justify-content: center; }
  .rsh-gains { grid-template-columns: 1fr 1fr; }
}
.info-dot { display: inline-grid; place-items: center; width: 16px; height: 16px; letter-spacing: 0; text-transform: none; margin-left: 4px; border-radius: 50%; vertical-align: 1px; font: 800 12px/1 Georgia, serif; font-style: italic; text-decoration: none; color: var(--page); background: var(--gold-text); }
@media (hover: hover) { .info-dot:hover { background: var(--gold-text-deep); } }

/* Grid tracks default to min-content, so a nowrap link or the card carousel widened the panel past a 375px screen. */
.lucky-table { grid-template-columns: minmax(0, 1fr); }
/* Six tabs do not fit a 320px phone at their comfortable sizes. */
@media (max-width: 359px) {
  .tabbar a, .tabbar button { min-width: 0; flex: 1; padding: 6px 2px; font-size: 10px; }
  .launch { white-space: normal; text-wrap: balance; font-size: 19px; }
}

/* avatars */
.av { --size: 44; position: relative; display: block; width: calc(var(--size) * 1px); height: calc(var(--size) * 1px); border-radius: 50%; overflow: hidden; flex: none; background: var(--surface-2); }
.av svg { display: block; width: 100%; height: 100%; }
.av-crop { position: absolute; inset: 0; pointer-events: none; }
/* The card keeps its natural 170px layout and is scaled, so its text doesn't reflow; --size is the avatar's width in px. */
.av-crop-in { --k: calc(var(--z) * var(--size) / 170); position: absolute; left: 0; top: 0; width: 170px; transform-origin: 0 0;
  transform: translate(calc((var(--size) / 2 - var(--x) * 170 * var(--k)) * 1px), calc((var(--size) / 2 - var(--y) * 237.5 * var(--k)) * 1px)) scale(var(--k)); }
.who-av { position: relative; padding: 0; border: 0; background: none; cursor: pointer; border-radius: 50%; }
.who-av .av { --size: 64; }
.who-av .avatar-letter { width: 64px; height: 64px; font-size: 23px; }
.who-av i { position: absolute; right: -2px; bottom: -2px; width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center; font-style: normal; font-size: 13px; background: var(--active-bg); color: var(--active-ink); box-shadow: 0 0 0 3px var(--surface); }
.av-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; margin: 8px 0 16px; }
.av-opt { padding: 0; border: 3px solid transparent; border-radius: 50%; overflow: hidden; aspect-ratio: 1; background: none; cursor: pointer; }
.av-opt:focus-visible { border-color: #1db36b; }
@media (hover: hover) { .av-opt:hover { border-color: #1db36b; } }
.av-opt svg { display: block; width: 100%; height: 100%; }
.av-expert { display: block; text-align: center; padding: 12px 14px; border-radius: 14px; font-weight: 900; text-decoration: none; color: #2a1a00; background: linear-gradient(135deg, #fff1c2, #ffd86b 55%, #f2b53a); }
.av-cropper { margin-top: 14px; display: grid; gap: 12px; }
.av-stage { display: grid; place-items: center; }
.av-big { --size: 200; touch-action: none; cursor: grab; box-shadow: 0 0 0 4px #ffd86b; }
.av-zoom { display: grid; gap: 6px; font-weight: 800; font-size: 13px; color: var(--muted); }
.av-save { margin: 0; }
.show-more { max-width: 140px; width: 100%; margin: 0 auto; display: grid; place-content: center; gap: 4px; text-align: center; aspect-ratio: 63 / 88; border-radius: 14px; text-decoration: none; font-size: 12px; font-weight: 800; color: #2a1a00; background: linear-gradient(135deg, #fff1c2, #ffd86b 55%, #f2b53a); }
.show-more b { font-size: 22px; }

/* collection: cards you don't have yet, as a faded preview with their number */
.coll-tile.missing { opacity: 1; cursor: pointer; }
.coll-tile.missing .tile-open { opacity: .22; filter: grayscale(1); transition: opacity .2s; }
@media (hover: hover) { .coll-tile.missing:hover .tile-open { opacity: .4; } }
.coll-tile.missing .card { pointer-events: none; }
.miss-num { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 3; padding: 4px 12px; border-radius: 999px; font-weight: 900; font-size: 15px; color: var(--text); background: color-mix(in srgb, var(--surface) 85%, transparent); box-shadow: 0 2px 10px rgba(0,0,0,.12); pointer-events: none; }
.coll-more { display: grid; place-items: center; margin-top: 18px; }
.coll-more .more-btn { width: auto; padding-left: 28px; padding-right: 28px; }
/*
  A full collection is six hundred cards, each a stack of blended layers: rendering the ones nobody is
  looking at held the page at 11 frames a second. The browser skips a thumbnail off screen and remembers
  the height it had, so the grid keeps its shape. The containment sits on the button, not on the tile:
  the "×N" badge and the star hang outside the tile and must not be clipped.
*/
.coll-grid .tile-open { content-visibility: auto; width: min(100%, 170px); aspect-ratio: 63 / 88; justify-self: center; }
/* The light grid tile: a card-shaped frame in the rarity colour, the art on top and the name under it. Flat colours
   and one image only: no blend, shadow, filter or animation per tile, so a screenful of them costs almost nothing. */
.coll-thumb { position: relative; display: block; box-sizing: border-box; width: 100%; height: 100%; overflow: hidden; border: 3px solid var(--c); border-radius: 12px; background: var(--surface-2); text-align: left; }
.coll-thumb img { display: block; position: absolute; inset: 14% 0 auto; width: 100%; height: auto; aspect-ratio: 1; object-fit: cover; background: var(--surface); }
.coll-thumb b { position: absolute; inset: auto 0 0; padding: 4px 6px 5px; color: var(--text); font-size: 11px; line-height: 1.15; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.coll-thumb i { position: absolute; top: 3px; left: 4px; padding: 1px 6px; border-radius: 999px; background: var(--active-bg); color: var(--active-ink); font-size: 10px; font-style: normal; font-weight: 900; }
.coll-thumb.t-shiny { border-color: #d7a93c; }
.coll-thumb.t-fullart { border-color: #ff7ad9; }
/* Show or hide the ghosts of the cards still missing */

/* admin panel */
.adm { max-width: 1200px; }
.adm-tabs { display: flex; gap: 6px; flex-wrap: wrap; margin: 8px 0 16px; }
.adm-tabs button { border: 1px solid var(--line); background: var(--surface); color: var(--muted); font: inherit; font-weight: 800; font-size: 14px; padding: 7px 14px; border-radius: 999px; cursor: pointer; }
.adm-tabs button[aria-current] { background: var(--active-bg); color: var(--active-ink); border-color: transparent; }
.adm-kpis { display: grid; grid-template-columns: repeat(auto-fill, minmax(195px, 1fr)); gap: 10px; margin-bottom: 14px; }
.adm-kpi { background: var(--surface); border: 1px solid var(--line); border-radius: 16px; padding: 12px 14px; display: grid; gap: 2px; min-width: 0; }
.adm-kpi small { color: var(--muted); font-weight: 800; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; }
/* Le badge passe sous la valeur quand la tuile est trop étroite pour les deux, au lieu de pousser
   la fin de la valeur à la ligne. Ce qui garde « 13 min 59 s » d'un bloc est l'espace insécable fine
   posée par admin.js, pas un nowrap : un nom de jeu doit, lui, pouvoir se replier entre ses mots. */
.adm-kpi b { font-size: 24px; line-height: 1.2; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 4px; }
.adm-kpi span { color: var(--muted); font-size: 12px; font-weight: 700; }
.adm-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr)); gap: 12px; margin-bottom: 12px; }
.adm-card { background: var(--surface); border: 1px solid var(--line); border-radius: 18px; padding: 14px 16px; margin-bottom: 12px; min-width: 0; }
.adm-grid .adm-card { margin-bottom: 0; }
.adm-paywall { display: flex; align-items: center; justify-content: space-between; gap: 12px 16px; flex-wrap: wrap; border-color: #e5484d; }
.adm-paywall.is-on { border-color: #30a46c; }
.adm-paywall h3 b { color: #e5484d; }
.adm-paywall.is-on h3 b { color: #30a46c; }
.adm-paywall p { margin: 0; }
.adm-card h3 { margin: 0 0 8px; font-size: 16px; }
.adm-chart svg { width: 100%; height: 140px; display: block; background: linear-gradient(var(--line) 1px, transparent 1px) 0 0 / 100% 25%; }
.adm-legend { display: flex; flex-wrap: wrap; gap: 12px; font-size: 13px; color: var(--muted); margin-bottom: 8px; }
.adm-legend i { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 5px; }
.adm-legend b { color: var(--text); }
.adm-axis { display: flex; justify-content: space-between; font-size: 11px; color: var(--muted); margin-top: 4px; }
.adm-table { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.adm-table table { width: 100%; border-collapse: collapse; font-size: 13px; }
.adm-table th { text-align: left; color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .04em; padding: 6px 8px; border-bottom: 1px solid var(--line); white-space: nowrap; }
.adm-table td { padding: 8px; border-bottom: 1px solid var(--line); vertical-align: middle; white-space: nowrap; }
.adm-table td small { display: block; color: var(--muted); font-size: 11px; }
.adm-table td .av, .adm-table td .avatar-letter { width: 32px; height: 32px; --size: 32; font-size: 13px; }
.adm-player { cursor: pointer; }
@media (hover: hover) { .adm-player:hover td { background: var(--surface-2); } }
.adm-filter { width: 100%; margin-bottom: 10px; }
.adm-gold { color: var(--gold-text); }
.adm-win { color: #1db36b; font-weight: 900; }

/* ---- mobile & fluidity fixes (design audit) ---- */
body.app { min-height: 100dvh; }
.sheet-card { max-height: 92dvh; overscroll-behavior: contain; }
.sheet, .lucky-overlay { overscroll-behavior: contain; }
body.sheet-open { overflow: hidden; }
.lt-slot, .lt-stage, .lt-card { touch-action: pan-y pinch-zoom; }
input[type=number], input[type=text], input[type=search], input:not([type]) { font-size: max(16px, 1em); }
.app-top { padding-left: max(16px, env(safe-area-inset-left)); padding-right: max(16px, env(safe-area-inset-right)); }
.view { padding-left: max(16px, env(safe-area-inset-left)); padding-right: max(16px, env(safe-area-inset-right)); }
.toast { bottom: calc(90px + env(safe-area-inset-bottom)); }
.trade-sides { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
@media (max-width: 430px) { .launch { white-space: normal; text-wrap: balance; } }
/* The blurred tab bar re-renders on every scroll frame: plain background on touch devices. */
@media (hover: none) { .tabbar { backdrop-filter: none; -webkit-backdrop-filter: none; background: var(--page); } }
/* Readable text on green: a deeper green under white text. */
.btn.claim-btn { background: linear-gradient(135deg, #17a563, #0b7d4a); }
.ach-badge { background: #0e8a52; }
/* Tap targets of at least 44px without changing the look. */
.coll-tile .fav::before { content: ""; position: absolute; inset: -11px; }
.lt-nav { min-width: 44px; min-height: 44px; }
/* The reel follows the theme instead of staying black on a white card. */
:root[data-theme="light"] .reel-window { background: #e9ecf2; box-shadow: inset 0 0 0 2px #d5dae3; }
:root[data-theme="light"] .reel-tile { background: #fff; color: #1d2029; box-shadow: inset 0 0 0 2px #d5dae3; }
/* Loading and error states between tabs. */
.view-loading { display: flex; justify-content: center; gap: 8px; padding: 60px 0; background: none; border: 0; }
.view-loading span { width: 10px; height: 10px; border-radius: 50%; background: var(--muted); animation: vl-dot 1s ease-in-out infinite; }
.view-loading span:nth-child(2) { animation-delay: .15s; }
.view-loading span:nth-child(3) { animation-delay: .3s; }
@keyframes vl-dot { 0%, 100% { opacity: .25; transform: translateY(0); } 50% { opacity: 1; transform: translateY(-4px); } }
.view-error { display: grid; justify-items: center; gap: 14px; padding: 40px 16px; text-align: center; }
.view-error .btn { width: auto; }
.theme-switch { display: inline-flex; border: 1px solid var(--line); border-radius: 999px; padding: 3px; background: var(--surface); }
.theme-switch button { border: 0; background: none; font: inherit; font-weight: 800; font-size: 14px; color: var(--muted); padding: 6px 12px; border-radius: 999px; cursor: pointer; }
.theme-switch button[aria-pressed="true"] { background: var(--active-bg); color: var(--active-ink); }
@media (prefers-reduced-motion: reduce) { .lucky-overlay.tense .reel-window { animation: none; } }
.adm-expert { margin: 0; display: grid; gap: 10px; }
.adm-expert h3 { margin: 0; }
.adm-xp-status { margin: 0; display: grid; gap: 2px; }
.adm-xp-status small { color: var(--muted); }
.adm-xp-days { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.adm-xp-days button { border: 1px solid var(--line); background: var(--surface); color: var(--text); font: inherit; font-weight: 800; font-size: 14px; padding: 8px 12px; border-radius: 999px; cursor: pointer; }
.adm-xp-days button[aria-pressed="true"] { background: var(--active-bg); color: var(--active-ink); border-color: transparent; }
.adm-xp-days label { display: flex; align-items: center; gap: 6px; color: var(--muted); font-weight: 700; }
.adm-xp-custom { width: 100px; }
.adm-xp-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.adm-xp-actions .btn { width: auto; margin: 0; flex: 1 1 160px; }
.adm-xp-note { margin: 0; }
/* Prize box: the label on the left, the gain on the right. */
.lt-prize b.lt-prize-empty { font-size: 15px; color: var(--muted); }
@media (max-width: 520px) {
  .lt-prize { grid-template-columns: minmax(0, 1fr) auto; align-items: center; row-gap: 6px; }
}
:root[data-theme="light"] .reel-window::before { background: linear-gradient(90deg, #e9ecf2, transparent); }
:root[data-theme="light"] .reel-window::after { background: linear-gradient(270deg, #e9ecf2, transparent); }

/* Pack switch: a two-position toggle, one pack type at a time. The thumb slides under the chosen label; it is
   the choice that decides what the reserve opens, so it is big enough for a thumb and reads at a glance. The
   EXPERT pack of the day sits apart, under it. */
.pack-switch { position: relative; display: grid; grid-template-columns: 1fr 1fr; width: 100%; max-width: 420px; box-sizing: border-box; margin: 0 auto 10px; padding: 4px; border-radius: 999px; background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--line); }
.pack-switch::before { content: ""; position: absolute; top: 4px; bottom: 4px; left: 4px; width: calc(50% - 4px); border-radius: 999px; background: var(--active-bg); box-shadow: 0 4px 12px rgba(0,0,0,.25); transition: transform .25s cubic-bezier(.22,1,.36,1); }
.pack-switch:has(button:nth-child(2)[aria-checked="true"])::before { transform: translateX(100%); }
.pack-switch:not(:has([aria-checked="true"]))::before { opacity: 0; }
.pack-switch button { position: relative; min-height: 48px; min-width: 0; padding: 0 6px; border: 0; border-radius: 999px; background: none; color: var(--muted); font: inherit; font-size: 15px; font-weight: 800; white-space: nowrap; cursor: pointer; transition: color .2s; -webkit-tap-highlight-color: transparent; }
.pack-switch button[aria-checked="true"] { color: var(--active-ink); }
.pack-stage[hidden] { display: none !important; }
/* The collection's tools are one panel, top to bottom in the order a collector decides: which pack, which filter,
   which card. The pack is a two-way switch that fills the row, so it cannot be mistaken for one more chip. */
.pk-flag { font-size: 18px; line-height: 1; }
[data-xp-timer] { font-variant-numeric: tabular-nums; }
/* Quick amounts: even chips; bid chips carry a small tag (MIN, +20 %, +50 %) over the amount. */
.amount .quick button { min-width: 0; white-space: nowrap; padding: 8px 4px; display: grid; place-items: center; gap: 1px; line-height: 1.1; transition: border-color .15s, background .15s, color .15s; }
.amount .quick button small { font-size: 10px; font-weight: 900; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.amount .quick button.on { border-color: var(--active-bg); background: var(--active-bg); color: var(--active-ink); }
.amount .quick button.on small { color: inherit; opacity: .75; }

/* Market lots: wide enough for the bid controls (one column on phones), labels never broken over two lines. */
.market-grid { grid-template-columns: repeat(auto-fill, minmax(min(100%, 340px), 1fr)); }
/* 150 px like a collection tile: under 130 px the face drops its texts and shows bare plates. */
.lot { grid-template-columns: 150px minmax(0, 1fr); gap: 12px; }
.lot .amount .quick { gap: 4px; }
.lot .amount .quick button { font-size: 14px; padding: 8px 2px; }
.lot-info { min-width: 0; }
/* A value too long for its row goes under its label instead of running out of the lot. */
.lot-info p { align-items: baseline; flex-wrap: wrap; column-gap: 8px; row-gap: 0; }
/* On a phone the card gives the info column its last 18 px. Its face drops its texts at 130 px and under (face.css
   asks max-width: 130px, which counts 130 itself), so the card stays just above. */
@media (max-width: 420px) {
  .lot { grid-template-columns: 132px minmax(0, 1fr); gap: 10px; }
  .lot .card { max-width: 132px; }
}
.lot-info p > span:first-child { white-space: nowrap; }
.lot-info p > b { white-space: nowrap; }
.lot form.bid { display: grid; gap: 8px; margin-top: 4px; }
.lot form.bid .amount { display: grid; gap: 8px; }
.lot form.bid input { width: 100%; }
.lot form.bid .btn { width: 100%; }
.amount .quick button small { white-space: nowrap; letter-spacing: .02em; }

/* ---- leaderboard ---- */
.ranking { max-width: 640px; margin: 0 auto; }
.rank-tabs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 4px; padding: 4px; border-radius: 999px; background: var(--surface-2); margin-bottom: 16px; }
.rank-tabs button { border: 0; background: none; font: inherit; font-weight: 800; font-size: 14px; color: var(--muted); padding: 9px 6px; border-radius: 999px; cursor: pointer; white-space: nowrap; }
.rank-tabs button[aria-selected="true"] { background: var(--surface); color: var(--text); box-shadow: 0 2px 8px rgba(0,0,0,.08); }
.rank-me { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 18px; border-radius: 20px; background: var(--active-bg); color: var(--active-ink); margin-bottom: 22px; }
.rm-pos { display: grid; line-height: 1.1; }
.rm-pos small, .rm-val small { font-size: 12px; font-weight: 800; opacity: .7; }
.rm-pos b { font-size: 34px; font-variant-numeric: tabular-nums; }
.rm-pos span { font-size: 12px; opacity: .7; font-weight: 700; }
.rm-hidden span { font-size: 16px; opacity: 1; font-weight: 800; }
.rm-val { display: grid; justify-items: end; text-align: right; gap: 2px; min-width: 0; }
.rm-val b { font-size: 22px; white-space: nowrap; }
.podium { list-style: none; margin: 0 0 18px; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; align-items: end; }
.podium a { display: grid; justify-items: center; gap: 4px; text-decoration: none; color: var(--text); min-width: 0; }
.podium .av, .podium .avatar-letter { --size: 56; width: 56px; height: 56px; font-size: 18px; box-shadow: 0 0 0 3px var(--surface), 0 6px 16px rgba(0,0,0,.15); }
.podium .p1 .av, .podium .p1 .avatar-letter { --size: 70; width: 70px; height: 70px; }
.podium b { font-size: 14px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pd-medal { font-size: 26px; line-height: 1; }
.pd-val { font-size: 13px; font-weight: 800; color: var(--muted); white-space: nowrap; }
.pd-step { width: 100%; display: grid; place-items: center; margin-top: 6px; border-radius: 14px 14px 6px 6px; font-weight: 900; font-size: 22px; color: #fff; }
.p1 .pd-step { height: 86px; background: linear-gradient(180deg, #ffd23f, #e8a310); }
.p2 .pd-step { height: 64px; background: linear-gradient(180deg, #c9d1db, #8f9aa8); }
.p3 .pd-step { height: 48px; background: linear-gradient(180deg, #e8a67a, #b8683a); }
.podium .me b { color: #0e8a52; }
.rank-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.rank-list a { display: flex; align-items: center; gap: 12px; padding: 10px 14px; border-radius: 16px; background: var(--surface); border: 1px solid var(--line); text-decoration: none; color: var(--text); }
.rank-list li.me a { border-color: #1db36b; box-shadow: 0 0 0 1px #1db36b inset; }
.rl-pos { width: 28px; flex: none; text-align: center; font-weight: 900; color: var(--muted); font-variant-numeric: tabular-nums; }
.rank-list .av, .rank-list .avatar-letter { --size: 36; width: 36px; height: 36px; font-size: 13px; }
.rl-who { flex: 1; min-width: 0; display: grid; }
.rl-who b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rl-who small { color: var(--muted); font-size: 12px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rl-val { flex: none; font-weight: 900; white-space: nowrap; }
.rank-how { margin-top: 16px; }
.handle-warn { margin: 6px 0 0; }
/* Changing the handle asks in the settings row itself: old → new, what it costs, and two plain answers. */
.handle-form[hidden] { display: none; }
.handle-ask { display: grid; gap: 8px; padding: 14px 16px; text-align: left; }
.handle-ask p { margin: 0; }
.handle-ask-swap { font-size: 17px; overflow-wrap: anywhere; }
.handle-ask-swap b { color: var(--heading); }
.handle-ask-btns { display: grid; gap: 8px; margin-top: 4px; }
.handle-ask-btns .btn { width: 100%; margin: 0; }
/* Light theme: the winning numbers keep a clear green mark (the plain light tile rule used to wipe it out). */
:root[data-theme="light"] .reel-tile.mine { background: #d9f4e6; color: #0b5e37; box-shadow: inset 0 0 0 3px #1db36b; }
:root[data-theme="light"] .reel-tile.mine.soft { background: #e3f6ec; color: #0b5e37; box-shadow: inset 0 0 0 2px #7fd1a8; }
:root[data-theme="light"] .reel-tile.hit { background: linear-gradient(160deg, #fff3c4, #ffd86b 45%, #f2b53a); color: #2a1a00; box-shadow: 0 0 0 3px #fff, 0 0 34px rgba(255,210,63,.85); }
:root[data-theme="light"] .lucky-overlay.lost .reel-tile.hit { background: #3a3f4c; color: #fff; box-shadow: 0 0 0 3px #e5484d; }

/* ---- games switcher ---- */

/* ---- FindPepe ---- */
.fp-wrap { display: grid; grid-template-columns: minmax(0, 320px) minmax(0, 1fr); gap: 18px; align-items: start; background: var(--surface); border: 1px solid var(--line); border-radius: 24px; padding: 16px; }
.fp-side { display: grid; gap: 12px; min-width: 0; }
.fp-label { margin: 4px 0 0; font-size: 12px; font-weight: 900; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.fp-card { display: flex; align-items: center; gap: 12px; width: 100%; padding: 8px 12px 8px 8px; border-radius: 16px; border: 2px solid var(--line); background: var(--page); font: inherit; color: var(--text); text-align: left; cursor: pointer; }
.fp-thumb { width: 54px; flex: none; }
.fp-thumb .card { pointer-events: none; }
.fp-card-txt { display: grid; gap: 2px; min-width: 0; }
.fp-card-txt b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fp-card-txt em { font-style: normal; font-size: 13px; font-weight: 800; color: var(--muted); text-decoration: underline; text-underline-offset: 3px; }
.fp-evils { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
.fp-evils button { display: grid; gap: 1px; place-items: center; padding: 8px 4px; border-radius: 14px; border: 2px solid var(--line); background: var(--page); color: var(--text); font: inherit; cursor: pointer; }
.fp-evils button b { font-size: 20px; line-height: 1.1; }
.fp-evils button small { font-size: 11px; font-weight: 800; color: #0e8a52; }
.fp-evils button[aria-pressed="true"] { border-color: #d2362c; background: color-mix(in srgb, #d2362c 10%, var(--page)); }
.fp-start { margin: 4px 0 0; }
.fp-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
.fp-stats div { display: grid; gap: 2px; padding: 10px 8px; border-radius: 14px; background: var(--page); text-align: center; min-width: 0; }
.fp-stats small { font-size: 11px; font-weight: 900; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.fp-stats b { font-size: 19px; white-space: nowrap; }
.fp-mult { color: #0e8a52; }
.fp-next { margin: 0; text-align: center; }
.fp-cash { margin: 0; width: 100%; font-size: 18px; }
.fp-result { display: grid; gap: 2px; padding: 12px 14px; border-radius: 16px; text-align: center; }
.fp-result b { font-size: 20px; }
.fp-result span { font-size: 13px; font-weight: 700; opacity: .8; }
.fp-result.lost { background: color-mix(in srgb, #d2362c 12%, var(--page)); color: #b3261e; }
.fp-result.cashed { background: color-mix(in srgb, #1db36b 12%, var(--page)); color: #0b6e45; }
.fp-life { margin: 0; font-size: 13px; font-weight: 700; color: var(--muted); }
.fp-life.on { color: #0e8a52; }
.fp-life.xp-promo { display: block; text-decoration: none; padding: 10px 12px; border-radius: 14px; color: #2a1a00; background: linear-gradient(135deg, #fff1c2, #ffd86b 55%, #f2b53a); }
.fp-board { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 8px; }
.fp-tile { position: relative; aspect-ratio: 1; border: 0; border-radius: 14px; padding: 0; background: #2f3a48; box-shadow: inset 0 -4px 0 rgba(0,0,0,.25); color: rgba(255,255,255,.35); font: 900 22px "M PLUS Rounded 1c", system-ui, sans-serif; cursor: default; overflow: hidden; transition: transform .12s, background .2s; }
.fp-board.live .fp-tile[data-tile] { cursor: pointer; }
@media (hover: hover) { .fp-board.live .fp-tile[data-tile]:hover { background: #3b4859; transform: translateY(-2px); } }
.fp-board.live .fp-tile[data-tile]:active { transform: scale(.94); }
.fp-tile.flipping { animation: fp-flip .35s ease-in-out infinite alternate; }
@keyframes fp-flip { to { transform: scale(.9); opacity: .7; } }
.fp-tile svg { position: absolute; inset: 10%; width: 80%; height: 80%; border-radius: 10px; }
.fp-tile.pepe { background: #d9f4e6; box-shadow: inset 0 0 0 3px #1db36b; animation: fp-pop .3s cubic-bezier(.3,1.6,.5,1); }
.fp-tile.evil { background: #3a1417; box-shadow: inset 0 0 0 2px #7a1a14; opacity: .8; }
.fp-tile.evil.hit { opacity: 1; background: #d2362c; box-shadow: 0 0 0 3px #fff, 0 0 26px rgba(210,54,44,.8); animation: fp-shake .45s; }
.fp-tile.saved { opacity: 1; box-shadow: inset 0 0 0 3px #ffd23f; }
.fp-tile.saved i { position: absolute; right: 4px; bottom: 2px; font-style: normal; font-size: 16px; }
.fp-board:not(.live) .fp-tile[data-tile] { opacity: .55; }
@keyframes fp-pop { from { transform: scale(.6); } to { transform: none; } }
@keyframes fp-shake { 20%, 60% { transform: translateX(-4px); } 40%, 80% { transform: translateX(4px); } }
:root[data-theme="light"] .fp-tile:not(.pepe):not(.evil) { background: #cfd6e0; color: rgba(0,0,0,.25); box-shadow: inset 0 -4px 0 rgba(0,0,0,.08); }
@media (hover: hover) { :root[data-theme="light"] .fp-board.live .fp-tile[data-tile]:hover { background: #bcc5d1; } }
@media (max-width: 720px) {
  .fp-wrap { grid-template-columns: minmax(0, 1fr); padding: 12px; }
  .fp-board { gap: 6px; }
  .fp-tile { border-radius: 11px; }
}
@media (prefers-reduced-motion: reduce) { .fp-tile, .fp-tile.pepe, .fp-tile.evil.hit, .fp-tile.flipping { animation: none; } }
.sheet-bid { display: grid; gap: 8px; margin: 10px 0 4px; }
.sheet-bid .amount { display: grid; gap: 8px; }
.sheet-bid input { width: 100%; }
.sheet-bid .btn { width: 100%; margin: 0; }
/* FindPepe sizing: a compact board that fits a phone screen with the controls, never a wall of tiles. */
.findpepe { max-width: 820px; }
.fp-wrap { grid-template-columns: minmax(0, 300px) minmax(0, 420px); justify-content: center; }
.fp-board { width: 100%; max-width: 420px; justify-self: center; gap: 7px; }
.fp-tile { border-radius: 12px; font-size: 18px; }
@media (max-width: 720px) {
  .fp-wrap { grid-template-columns: minmax(0, 1fr); }
  .fp-board { max-width: min(100%, 52dvh); gap: 6px; }
  .fp-tile { border-radius: 10px; font-size: 16px; }
  .findpepe .burn-warn { font-size: 14px; padding: 10px 12px; }
  .fp-side { gap: 10px; }
}
.fp-how { display: flex; align-items: center; gap: 10px; margin: 0; padding: 10px 12px; border-radius: 14px; background: color-mix(in srgb, #d2362c 8%, var(--page)); font-size: 14px; font-weight: 700; }
.fp-how svg { width: 34px; height: 34px; flex: none; border-radius: 8px; }
.fp-tile img { position: absolute; inset: 12%; width: 76%; height: 76%; border-radius: 8px; image-rendering: pixelated; }
.fp-how img { width: 34px; height: 34px; flex: none; border-radius: 8px; image-rendering: pixelated; }
.fp-pick { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 6px; }
.fp-pick .lt-nav { width: 44px; height: 44px; border-radius: 50%; border: 0; background: var(--active-bg); color: var(--active-ink); font-size: 24px; font-weight: 900; cursor: pointer; }
.fp-pick .lt-nav:disabled { background: var(--surface-2); color: var(--muted); opacity: .6; cursor: default; }
.fp-card { touch-action: pan-y; user-select: none; -webkit-user-select: none; }
.fp-card-txt small { font-size: 12px; font-weight: 800; color: var(--muted); }
/* FindPepe card picker: the card centred between the arrows, its details underneath, nothing truncated. */
.fp-pick { grid-template-columns: 44px minmax(0, 1fr) 44px; gap: 10px; }
.fp-card { display: grid; place-items: center; width: auto; justify-self: center; padding: 0; border: 0; background: none; border-radius: 12px; }
.fp-thumb { width: 104px; }
.fp-card-info { display: grid; justify-items: center; gap: 4px; text-align: center; }
.fp-card-info b { font-size: 17px; line-height: 1.2; text-wrap: balance; }
.fp-meta { display: flex; align-items: center; justify-content: center; gap: 8px; flex-wrap: wrap; font-size: 13px; font-weight: 800; color: var(--muted); font-variant-numeric: tabular-nums; }
.fp-chip { padding: 1px 8px; border-radius: 999px; background: var(--surface-2); }
.fp-val { color: var(--text); font-size: 15px; }
.fp-all { font-size: 13px; }

/* No paragraph or heading broken into uneven lines. */
p, li, h1, h2, h3, small, .burn-warn { text-wrap: balance; }
/* The "card is spent" reminder: a small red pill inside the game panel, as wide as its text. */
.fp-warn { justify-self: start; margin: 0; padding: 6px 12px; border-radius: 999px; font-size: 13px; font-weight: 800; color: #b3261e; background: color-mix(in srgb, #e5484d 10%, var(--page)); }
:root[data-theme="dark"] .fp-warn { color: #ff8a80; }
.fp-how { padding: 8px 12px; font-size: 13px; }
.fp-how img { width: 28px; height: 28px; }
/* The reminder sits right under the play button, as a plain line. */
.fp-warn { justify-self: center; margin: -4px 0 0; padding: 0; background: none; border-radius: 0; font-size: 13px; text-align: center; }
@media (min-width: 721px) {
  .findpepe { max-width: 860px; }
  .fp-wrap { grid-template-columns: minmax(0, 350px) minmax(0, 420px); }
}
.fp-warn { white-space: nowrap; }
@media (max-width: 380px) { .fp-warn { white-space: normal; } }
/* Prefixed so it outweighs `.view p { text-wrap: balance }` above. */
:is(.view, .sheet, body) :is(.fp-how span, .fp-life, .findpepe > p.muted, .games > p.muted, .xp-lucky, .rank-how) { text-wrap: balance; }

/* ---- FindPepe v3: stable layout ---- */
/* Board first on phones (it never moves while the controls under it change); controls on the left on wide screens. */
@media (min-width: 721px) { .fp-side { order: -1; } }
.fp-board-wrap { position: relative; width: 100%; max-width: 420px; justify-self: center; }
@media (max-width: 720px) { .fp-board-wrap { max-width: min(100%, 52dvh); } }
.fp-board-wrap .fp-board { max-width: none; }
/* Only the tile just found pops; the others stay still on every redraw. */
.fp-tile.pepe { animation: none; }
.fp-tile.pepe.new { animation: fp-pop .3s cubic-bezier(.3,1.6,.5,1); }
/* End of game: a card over the board, the board stays in place underneath. */
.fp-over { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: min(88%, 300px); display: grid; justify-items: center; gap: 6px; padding: 16px 16px 14px; border-radius: 20px; text-align: center; background: var(--surface); box-shadow: 0 18px 50px rgba(0,0,0,.25); animation: fp-over-in .25s ease-out; }
.fp-over b { font-size: 22px; line-height: 1.2; }
.fp-over span { font-size: 13px; font-weight: 700; color: var(--muted); text-wrap: balance; }
.fp-over.lost b { color: #b3261e; }
.fp-over.cashed b { color: #0b6e45; }
@keyframes fp-over-in { from { opacity: 0; transform: translate(-50%, -46%); } }
/* Stat labels in normal case so "Multiplicateur" fits its box. */
.fp-stats small { text-transform: none; letter-spacing: 0; font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: clip; }
.fp-stats div { padding: 10px 6px; }
.fp-rules { max-width: 640px; }
@media (prefers-reduced-motion: reduce) { .fp-over, .fp-tile.pepe.new { animation: none; } }
/* The "card is spent" banner: back as a red banner, inside the game panel so it is exactly as wide as the game. */
.game-warn { margin: 0; grid-column: 1 / -1; text-align: center; font-size: 15px; text-wrap: balance; }
@media (min-width: 721px) { .fp-wrap > .game-warn { order: -2; } }
/* Leaderboard shortcut in the phone top bar. */
.top-right { display: flex; align-items: center; gap: 8px; }
/* The leaderboard button carries the players-online count: one pill, trophy then « ● 12 », a single tap to the
   ranking. With no count yet it is the plain 44-px round button. */
.top-rank { display: inline-flex; align-items: center; justify-content: center; gap: 0; min-width: 44px; height: 44px; padding: 0 11px; box-sizing: border-box;
  border-radius: 999px; border: 1px solid var(--line); background: var(--surface); color: var(--text); text-decoration: none; }
.app-top .top-rank .online { height: auto; margin-left: 10px; padding: 0 3px 0 10px; border: 0; border-left: 1px solid var(--line); border-radius: 0; background: none; }
.top-rank svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.top-rank[aria-current="true"] { background: var(--active-bg); color: var(--active-ink); border-color: transparent; }
/* The players online, in the top bar and in the sidebar: a green dot that breathes, then the count. The digits are
   tabular and the slot holds three of them, so the bar never shifts when the number changes. */
.online { position: relative; display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 11px 0 10px; box-sizing: border-box; border-radius: 999px;
  border: 1px solid var(--line); background: var(--surface); color: var(--muted); font-weight: 800; font-size: 12.5px; white-space: nowrap; }
/* The pill is as wide as its content: a reserved 3-digit slot left a hole between the dot and « 1 ». */
.online-n { color: var(--text); font-variant-numeric: tabular-nums; }
.online-word { margin-left: -2px; }
/* In the phone's top bar it stands as tall as the trophy and the balance next to it (44 px), not as a small tag. */
.app-top .online { height: 44px; padding: 0 14px 0 13px; gap: 8px; font-size: 15px; }
.app-top .online-dot { width: 8px; height: 8px; }
/* In the sidebar the balance and the online count are one card, not two pills: the balance on top, the count as its footer row. */
.side-foot .coins { order: -1; width: 100%; min-height: 52px; box-sizing: border-box; justify-content: flex-start; padding: 0 0 0 14px; font-size: 19px;
  border: 0; border-radius: 15px 15px 0 0; background: rgba(255, 216, 74, .07); }
.side-foot .online[hidden] + .coins { border-radius: 15px; }
:root[data-theme="light"] .side-foot .coins { background: #fff7e0; }
@media (hover: hover) { .side-foot .coins:hover { background: rgba(255, 216, 74, .13); } :root[data-theme="light"] .side-foot .coins:hover { background: #ffefc2; } }
.no-pay .side-foot .coins:hover { background: rgba(255, 216, 74, .07); }
:root[data-theme="light"].no-pay .side-foot .coins:hover { background: #fff7e0; }
.side-foot .coins-plus { margin: 0 0 0 auto; padding: 0 16px; border-left-color: var(--line); }
.side-foot .online { height: 38px; padding: 0 14px; gap: 8px; font-size: 13px; border: 0; border-top: 1px solid var(--line); border-radius: 0 0 15px 15px; background: none; }
.side-foot:has(> .coins[hidden]) .online { border-top: 0; border-radius: 15px; }
.online-dot { flex: none; width: 7px; height: 7px; border-radius: 50%; background: #35d07f; animation: online-pulse 2.6s ease-out infinite; }
@keyframes online-pulse {
  0% { box-shadow: 0 0 0 0 rgba(53, 208, 127, .5); }
  70% { box-shadow: 0 0 0 6px rgba(53, 208, 127, 0); }
  100% { box-shadow: 0 0 0 0 rgba(53, 208, 127, 0); }
}
/* Someone arrives: the pill flashes green once and a « +1 » rises out of it (app.js, renderOnline). */
.online-boost { animation: online-boost 1.1s ease-out; }
.online-boost .online-n { animation: online-boost-n 1.1s ease-out; }
@keyframes online-boost {
  0% { border-color: #35d07f; box-shadow: 0 0 0 0 rgba(53, 208, 127, .55), 0 0 18px rgba(53, 208, 127, .45); }
  60% { box-shadow: 0 0 0 8px rgba(53, 208, 127, 0), 0 0 12px rgba(53, 208, 127, .2); }
  100% { box-shadow: 0 0 0 0 rgba(53, 208, 127, 0); }
}
@keyframes online-boost-n { 0%, 35% { color: #35d07f; transform: scale(1.3); } 100% { transform: none; } }
.online-n { display: inline-block; }
.online-plus { position: absolute; right: 6px; top: -4px; color: #35d07f; font-style: normal; font-weight: 900; font-size: 13px;
  pointer-events: none; animation: online-plus 1.4s ease-out forwards; }
@keyframes online-plus { 0% { opacity: 0; transform: translateY(6px) scale(.8); } 20% { opacity: 1; transform: translateY(-4px) scale(1.1); }
  100% { opacity: 0; transform: translateY(-22px); } }
@media (prefers-reduced-motion: reduce) { .online-dot { animation: none; } }
/* On the narrowest phones the logo, the count, the trophy and the balance share one row: the word goes, the number
   and its dot stay. */
@media (max-width: 420px) { .online-word { display: none; } }
/* 320–360 px: logo, trophy-and-count and balance share one row once the gaps and the pill tighten. */
@media (max-width: 360px) {
  .top-right { gap: 3px; }
  .top-rank { padding: 0 9px; }
  .app-top .top-rank .online { gap: 5px; margin-left: 7px; padding: 0 1px 0 7px; }
  .top-rank svg { width: 20px; height: 20px; }
  .app-top .logo { font-size: 14.5px; }
  .app-top { padding-left: max(10px, env(safe-area-inset-left)); padding-right: max(10px, env(safe-area-inset-right)); }
}
/* Achievements page: a section per theme, the ones to claim on top. */
.ach-cat { margin-top: 22px; }
.ach-cat h2 { font-size: 20px; margin: 0 0 10px; display: flex; align-items: baseline; gap: 8px; }
.ach-cat h2 small { font-size: 14px; color: var(--muted); font-weight: 800; }
/* The MemeCoin logotype: glyph at 1.2× the word, gap 0.4×, old-gold fill */
.memecoin-logo { display: inline-flex; align-items: center; gap: .4em; white-space: nowrap; line-height: 1; font-size: 18px; font-style: normal; align-self: center; }
.memecoin-logo .coin-mark { width: 1.2em; height: 1.2em; }
.memecoin-logo > span { font-weight: 900; letter-spacing: .14em; background: linear-gradient(180deg, var(--gold-text-light), var(--gold-text) 55%, var(--gold-text-deep)); -webkit-background-clip: text; background-clip: text; color: transparent; }
.ach-ready-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 10px; }
.ach-ready-head h2 { margin: 0; margin-right: auto; }
.ach-ready-head .memecoin { flex: none; filter: drop-shadow(0 6px 14px rgba(184, 119, 8, .35)); }
/* Open places down to 50: quiet dashed rows. */

/* Games lobby: a banner on what a round costs, Numbers on a wide tile, then the four other games in arcade
   colours whatever the theme. */
.lobby-note { display: flex; align-items: center; gap: 12px; margin: 0 0 12px; padding: 12px 14px; border-radius: 16px; background: var(--surface); border: 1px solid var(--line); }
.lobby-note-ico { flex: none; display: grid; place-items: center; width: 40px; height: 40px; border-radius: 12px; background: var(--surface-2); color: var(--gold); }
.lobby-note-ico svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.lobby-note > span { display: grid; gap: 1px; min-width: 0; }
/* The count arrives after the collection: the line keeps its height so the tiles never jump. */
.lobby-note b { font-size: 15px; min-height: 1.2em; }
.lobby-note small { font-weight: 700; font-size: 13px; color: var(--muted); }
.lobby { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.lobby-tile { position: relative; display: block; aspect-ratio: 4 / 5; border-radius: 18px; overflow: hidden; text-decoration: none; box-shadow: 0 10px 24px rgba(0,0,0,.22); transition: transform .12s; }
@media (hover: hover) { .lobby-tile:hover { transform: translateY(-4px); } }
.lobby-tile:active { transform: scale(.97); }
.lobby-tile:focus-visible { outline: 3px solid var(--gold); outline-offset: 3px; }
.lobby-tile img { position: absolute; z-index: 1; left: 50%; transform: translateX(-50%); }
/* The caption sits on the art: a gradient keeps the name readable over any illustration. */
.lobby-cap { position: absolute; left: 0; right: 0; bottom: 0; z-index: 2; display: grid; gap: 4px; padding: 16px 12px 12px; background: linear-gradient(transparent, rgba(0,0,0,.42)); color: #fff; }
.lobby-cap b { font: 900 18px / .95 "M PLUS Rounded 1c", system-ui, sans-serif; letter-spacing: -.01em; text-transform: uppercase; white-space: nowrap; text-shadow: 0 2px 0 rgba(0,0,0,.28); }
.lobby-cap small { font-weight: 800; font-size: 12px; }
.lobby-chip { justify-self: start; font-weight: 900; font-size: 11px; padding: 2px 8px; border-radius: 999px; background: rgba(0,0,0,.3); }
/* Numbers, in head: the art moves to a column of its own instead of sitting under the text. */
.lobby-tile.wide { aspect-ratio: auto; height: 170px; display: grid; grid-template-columns: minmax(0, 1fr) 44%; align-items: center; margin-bottom: 12px; }
.lobby-tile.wide .lobby-cap { order: -1; position: static; gap: 6px; padding: 0 0 0 18px; background: none; }
.lobby-tile.wide .lobby-cap b { font-size: 26px; white-space: normal; text-shadow: 0 3px 0 rgba(0,0,0,.28); }
.lobby-tile.wide .lobby-cap small { font-size: 13px; }
.lobby-tile.wide .lobby-chip { font-size: 12px; padding: 3px 10px; background: rgba(0,0,0,.28); }
.t-findpepe { background: linear-gradient(#2fb3a8, #11707a); }
.lobby-grid { position: absolute; inset: 7% 25% auto; display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
.lobby-grid i { position: relative; aspect-ratio: 1; border-radius: 8px; overflow: hidden; background: rgba(255,255,255,.16); }
.lobby-grid img { inset: 0; left: 0; transform: none; width: 100%; height: 100%; image-rendering: pixelated; }
.t-road { background: linear-gradient(#2fa84f, #136b33); }
.t-road::before { content: ""; position: absolute; inset: 0 16%; background: repeating-linear-gradient(transparent 0 16px, rgba(255,255,255,.4) 16px 30px) 50% 0 / 4px 100% no-repeat, rgba(0,0,0,.28); }
.t-road img { top: 4%; width: 44%; }
.t-plinko { background: linear-gradient(#2a52f0, #101f80); }
.t-plinko img { top: 16%; width: 56%; image-rendering: pixelated; }
.lobby-pegs { position: absolute; inset: 6% 10% 52%; background: radial-gradient(circle, rgba(255,255,255,.85) 0 3px, transparent 4px) 0 0 / 24px 24px; }
.t-stonks { background: linear-gradient(#8a3cf0, #c8274f); }
.t-stonks img { top: 4%; width: 42%; left: 34%; }
.lobby-arrow { position: absolute; right: 6%; top: 10%; width: 46%; fill: none; stroke: #fff; stroke-width: 6; stroke-linecap: round; stroke-linejoin: round; filter: drop-shadow(0 3px 0 rgba(0,0,0,.25)); }
.t-roulette { background: linear-gradient(120deg, #ff7a3d, #d9487d); }
.lobby-reel { display: flex; gap: 6px; padding-right: 16px; }
.lobby-reel i { flex: 1; aspect-ratio: 3 / 4; display: grid; place-items: center; border-radius: 12px; background: #fff; color: #2a1200; font: 900 20px "M PLUS Rounded 1c", system-ui, sans-serif; font-style: normal; box-shadow: inset 0 -4px 0 rgba(0,0,0,.12); }
.lobby-reel i:nth-child(2) { background: #ffd84a; transform: translateY(-8px); }
/* Numbers and Devine le mème share the top row half and half. On a phone each half is too narrow for text
   beside art, so the art goes on top and the caption under it, as on the arcade tiles below. */
.lobby-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-bottom: 12px; }
.lobby-pair .lobby-tile.wide { margin: 0; height: auto; min-height: 210px; grid-template-columns: minmax(0, 1fr); grid-template-rows: 1fr auto; align-items: center; }
.lobby-pair .lobby-tile.wide .lobby-cap { order: 0; gap: 4px; padding: 0 12px 12px; }
.lobby-pair .lobby-tile.wide .lobby-cap b { font-size: 20px; line-height: 1.05; }
.lobby-pair .lobby-tile.wide .lobby-cap small { font-size: 12px; }
.lobby-pair .lobby-tile.wide .lobby-chip { font-size: 11px; padding: 2px 8px; }
.lobby-pair .lobby-reel { padding: 18px 12px 0; }
.lobby-pair .lobby-reel i { font-size: 18px; }
.lobby-pair .lobby-guess { margin-top: 18px; width: min(56%, 110px); }
/* Wider than a phone: the tiles grow instead of multiplying, and the wide tile grows with them. */
@media (min-width: 560px) {
  .lobby { grid-template-columns: repeat(auto-fill, minmax(min(100%, 220px), 1fr)); gap: 16px; }
  .lobby-tile.wide { height: 210px; grid-template-columns: minmax(0, 1fr) min(44%, 300px); margin-bottom: 16px; }
  .lobby-tile.wide .lobby-cap { padding-left: 26px; }
  .lobby-tile.wide .lobby-cap b { font-size: 34px; }
  .lobby-cap b { font-size: clamp(18px, 2vw, 24px); }
  .lobby-cap small { font-size: 13px; }
  .lobby-reel { padding-right: 26px; }
  .lobby-pair { gap: 16px; margin-bottom: 16px; }
  .lobby-pair .lobby-tile.wide { height: 210px; min-height: 0; grid-template-columns: minmax(0, 1fr) 42%; grid-template-rows: none; }
  .lobby-pair .lobby-tile.wide .lobby-cap { order: -1; gap: 6px; padding: 0 0 0 24px; }
  .lobby-pair .lobby-tile.wide .lobby-cap b { font-size: clamp(24px, 2.6vw, 34px); }
  .lobby-pair .lobby-tile.wide .lobby-cap small { font-size: 13px; }
  .lobby-pair .lobby-tile.wide .lobby-chip { font-size: 12px; padding: 3px 10px; }
  .lobby-pair .lobby-reel { padding: 0 22px 0 0; }
  .lobby-pair .lobby-reel i { font-size: 20px; }
  .lobby-pair .lobby-guess { margin: 0 12px 0 0; width: min(78%, 150px); }
}
/* Short phones (iPhone SE and the like): the banner and the wide tile give back the pixels the second row needs. */
@media (max-width: 560px) and (max-height: 700px) {
  .games-lobby .head-row { margin-bottom: 8px; }
  .games-lobby h1 { font-size: 23px; }
  .lobby-note { gap: 10px; padding: 10px 12px; }
  .todo-row { min-height: 56px; padding-top: 8px; padding-bottom: 8px; }
  .lobby-tile.wide { height: 150px; }
  .lobby-pair .lobby-tile.wide { min-height: 180px; }
}
@media (prefers-reduced-motion: reduce) { .lobby-tile { transition: none; } }

/* Doge Road, Nyan Plinko, Stonks */
.ar-head h1 { margin: 0; }
.ar-head p { margin: 2px 0 14px; font-weight: 700; }
@media (max-width: 860px) { .ar-head p { margin-bottom: 8px; } }
.ar-game { display: grid; grid-template-columns: 290px minmax(0, 1fr); gap: 18px; align-items: start; background: var(--surface); border: 1px solid var(--line); border-radius: 24px; padding: 16px; }
@media (min-width: 861px) { .ar-game > .game-warn { order: -2; } }
/* The grid auto-places its children two by two, so Stonks' extra ticker row would push the chart into the controls'
   column: the three cells of a game that has a ticker are placed by hand instead. */
@media (min-width: 861px) {
  .ar-game:has(> .ar-tape) > .ar-controls { grid-column: 1; grid-row: 2 / span 2; }
  .ar-game > .ar-tape { grid-column: 2; grid-row: 2; align-self: end; }
  .ar-game:has(> .ar-tape) > .ar-board { grid-column: 2; grid-row: 3; }
}
/* On a phone the chart comes first; the ticker belongs just above it, not at the bottom under the tab bar. */
@media (max-width: 860px) { .ar-game { grid-template-columns: minmax(0, 1fr); gap: 10px; padding: 12px; }
  .ar-board { order: -1; } .ar-tape { order: -2; } }
/* The first Doge Road, on the house: a gold banner over the board, on a phone too, that says it costs nothing. */
.ar-free { grid-column: 1 / -1; order: -2; display: grid; justify-items: center; gap: 2px; margin: 0; padding: 12px 14px; border-radius: 18px; text-align: center;
  background: linear-gradient(135deg, #ffe27a, #ffb938); color: #3b2500; box-shadow: 0 10px 24px rgba(255,185,56,.35); animation: fr-in .5s cubic-bezier(.3,1.6,.5,1); }
.ar-free-badge { font-size: 22px; font-weight: 900; letter-spacing: .02em; }
.ar-free-gain { margin: 0; font-size: 17px; font-weight: 700; }
.ar-free-gain b { font-weight: 900; }
.ar-free-safe { margin: 0; font-size: 13px; opacity: .8; }
.ar-free-safe:empty { display: none; }
.ar-free-boosted { margin: 0; font-size: 13px; font-weight: 700; }
.ar-free-next { margin: 8px 0 2px; padding: 11px 20px; font-size: 16px; white-space: nowrap; text-decoration: none; background: #3b2500; color: #ffe27a; }
.ar-pick[hidden] { display: none; }
@media (max-width: 860px) { .ar-free { padding: 8px 10px; } .ar-free-badge { font-size: 19px; } .ar-free-gain { font-size: 15px; } }
/* The offered note has three lines on Stonks, the capped-gain one included. On a 390x844 phone it has to say all of
   that and still leave the cash-out button on screen, so here it says the same thing in less height. */
@media (max-width: 860px) {
  .ar-free.ar-offered { gap: 0; padding: 6px 10px; }
  .ar-free.ar-offered .ar-free-gain { font-size: 13px; }
  .ar-free.ar-offered .ar-free-safe { font-size: 11px; line-height: 1.3; }
}
.ar-controls { display: grid; gap: 10px; }
.ar-controls .btn { margin: 0; width: 100%; }
.ar-act { display: grid; gap: inherit; }
/* The amount inside a button changes while the game runs: a press always lands on the button itself, never on a
   piece of its content that could be replaced between press and release (the click would then be lost). */
.ar-controls .btn * { pointer-events: none; }
/* No double-tap zoom wait on phones: a tap on a game control acts at once. */
.ar-controls .btn, .ar-stake, .ar-verdict, .lobby-tile { touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
.ar-cash { background: linear-gradient(135deg, #3ddc8c, #13a86a); color: #fff; text-shadow: 0 1px 0 rgba(0,0,0,.15); box-shadow: 0 8px 20px rgba(29,179,107,.3); }
/* Stonks' two buttons carry dark ink: white text sat around 1.8:1 on the mint green and on the orange-to-yellow
   gradient, well under the 4.5:1 a sentence needs. Another mission is redoing the buttons everywhere, so this
   stays scoped to this board. The gradients are fixed colours, so both themes get the same ratio. */
.ar-game:has(.ar-stonks) .ar-act .ar-go { color: #2b1400; text-shadow: none; }
.ar-game:has(.ar-stonks) .ar-act .ar-cash { color: #042117; text-shadow: none; }
/* A disabled button keeps its contrast and loses its colour instead of its opacity: still readable, visibly inactive. */
.ar-game:has(.ar-stonks) .ar-act .btn:disabled { opacity: 1; filter: grayscale(1); box-shadow: none; }
.ar-stake { display: flex; align-items: center; gap: 12px; text-align: left; font: inherit; color: var(--text); background: var(--page); border: 2px solid var(--line); border-radius: 18px; padding: 10px; cursor: pointer; }
@media (hover: hover) { .ar-stake:hover:not(:disabled) { border-color: var(--gold); } }
/* The staked card between ‹ and ›: flip through your cards in place, the sheet stays one tap away on the card. */
.ar-pick { display: flex; align-items: stretch; gap: 6px; min-width: 0; }
.ar-pick .ar-stake { flex: 1; min-width: 0; }
.ar-nav { flex: none; width: 36px; border: 2px solid var(--line); border-radius: 14px; background: var(--page); color: var(--text);
  font: inherit; font-size: 26px; font-weight: 900; line-height: 1; cursor: pointer; touch-action: manipulation; -webkit-tap-highlight-color: transparent; -webkit-user-select: none; user-select: none; }
@media (hover: hover) { .ar-nav:hover:not(:disabled) { border-color: var(--gold); } }
@media (max-width: 899px) { .ar-nav { width: 44px; } }
.ar-nav:disabled { opacity: .35; cursor: default; }
.ar-stake:disabled { cursor: default; opacity: .7; }
.ar-thumb { width: 64px; flex: none; }
.ar-thumb.empty { aspect-ratio: 63 / 88; border-radius: 10px; background: var(--surface-2); display: grid; place-items: center; font-size: 28px; font-weight: 900; color: var(--muted); }
.ar-stake-txt { display: grid; gap: 2px; min-width: 0; font-weight: 900; }
.ar-stake-txt small { color: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: .04em; }
/* The card's name always takes two lines, no more, no less: a long name or a short one leaves the box the same
   height, so the button under it never moves between two plays (players tap it in a row). */
.ar-stake-txt b { font-size: 16px; line-height: 1.2; overflow-wrap: anywhere; height: 2.4em;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
.ar-stake-txt em { font-style: normal; font-size: 13px; color: var(--muted); text-decoration: underline; text-underline-offset: 3px; }
.ar-last { margin: 0; min-height: 1.4em; font-weight: 800; }
.ar-last .win { color: #1db36b; }
.ar-last .lose { color: #e5484d; }
/* Stonks' ticker: the last crash points, newest first. On a desktop it sits in the chart's column, just above it;
   on a phone it is the row above the chart, far from the sticky cash-out button that it must never come over. */
.ar-tape { display: flex; align-items: center; gap: 8px; min-width: 0; font-size: 13px; }
.ar-tape > b { flex: none; color: var(--muted); font-size: 11px; font-weight: 900; text-transform: uppercase; letter-spacing: .04em; }
.ar-tape ul { display: flex; gap: 6px; margin: 0; padding: 0; list-style: none; min-width: 0; overflow: hidden; }
/* Each tier carries its own solid background and dark ink, so a crash point reads the same in both themes. */
.ar-tape li { flex: none; padding: 2px 8px; border-radius: 999px; font-weight: 900; font-variant-numeric: tabular-nums;
  background: var(--surface); border: 1px solid var(--line); color: var(--muted); }
.ar-tape .t1 { border-color: transparent; background: #cfe2ff; color: #123a73; }
.ar-tape .t2 { border-color: transparent; background: #e0d4ff; color: #3b1f73; }
.ar-tape .t3 { border-color: transparent; background: #ffd1f0; color: #6d1049; }
.ar-tape .t4 { border-color: transparent; background: #ffeec2; color: #6b4300; }
.ar-tape .best { border-color: transparent; background: linear-gradient(135deg, #ffd84a, #ffb100); color: #3b2500; }
.ar-board { position: relative; border-radius: 18px; overflow: hidden; background: #0b0f1c; }
.ar-board canvas { display: block; width: 100%; height: auto; }
/* The Plinko board is taller than wide: capped so its slots stay on screen next to the controls. */
.ar-board.ar-plinko { width: 100%; max-width: 540px; }
.ar-rules { margin-top: 14px; }
/* The verdict replaces the chart instead of floating over it: the meme card on one side, the sentence on the other,
   over an opaque backdrop. Through the old translucent one the "NOT STONKS ×30,00" painted on the canvas read
   straight through the words explaining the round, and the stacked card sat on top of them on a phone's short board. */
.ar-verdict { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; gap: 16px; padding: 16px; text-align: center; color: #fff; background: #0a0c16; cursor: pointer; animation: ar-pop .28s ease-out; }
.ar-v-text { display: flex; flex-direction: column; justify-content: center; gap: 6px; min-width: 0; max-width: 36ch; }
.ar-meme { position: relative; overflow: hidden; flex: none; height: min(100%, 200px); aspect-ratio: 1; border-radius: 14px; padding: 10px 8px; display: flex; flex-direction: column; justify-content: space-between; background: var(--a); font-family: "Anton", Impact, sans-serif; font-size: 24px; line-height: 1; color: #fff; -webkit-text-stroke: 5px #000; paint-order: stroke fill; text-transform: uppercase; transform: rotate(-3deg); box-shadow: 0 18px 40px rgba(0,0,0,.5); }
.ar-meme > span { position: relative; z-index: 1; }
.ar-meme.has-img { background: #111; }
.ar-meme > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.ar-v-title { margin: 6px 0 0; font-family: "Anton", Impact, sans-serif; font-size: 30px; line-height: 1.05; text-transform: uppercase; }
.ar-v-title.win { color: #3ddc8c; }
.ar-v-title.lose { color: #ff6a6f; }
.ar-v-sub { margin: 0; font-weight: 700; max-width: 36ch; }
.ar-v-close { margin: 4px 0 0; font-size: 12px; color: rgba(255,255,255,.7); }
@keyframes ar-pop { from { opacity: 0; transform: scale(.96); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .ar-verdict { animation: none; } }


/* ================= phones: one screen per game, nothing left under the tab bar ================= */

/* What the fixed tab bar eats at the bottom of every app screen. */
:root { --bar: 70px; }

/* The landing page's `main section { padding: 34px 0 20px }` also styles the app shell and left a band of dead
   space under the top bar on every tab. The view's own padding is the spacing the app wants. */
@media (max-width: 899px) {
  .view > section { padding-top: 0; }
  .view > section + section { padding-top: 16px; }
}

/* Six tabs and their labels do not fit a 360 px phone at their comfortable width: the last one was cut off. */
@media (max-width: 420px) {
  .tabbar a { min-width: 0; flex: 1; padding: 6px 2px; }
}

/* A line of text is not a tap target: the back link and the plain-text buttons get a finger-sized hit area. */
@media (max-width: 899px) {
  .back-link { padding: 7px 4px; margin: 0 -4px 6px; }
  .link-btn { position: relative; }
  .link-btn::before { content: ""; position: absolute; left: -6px; right: -6px; top: 50%; height: 44px; transform: translateY(-50%); }
}
/* The pager arrows had shrunk to 38 px on phones. */
.pager .nav { width: 44px; height: 44px; }

/* ---- the arcade games (Doge Road, Nyan Plinko, Stonks) ---- */
@media (max-width: 860px) {
  .games .back-link { margin-bottom: 2px; }
  .ar-head h1 { font-size: 23px; }
  .ar-head p { margin: 0 0 6px; font-size: 13px; }
  .ar-game { gap: 8px; padding: 10px; }
  /* `display: contents` dissolves the controls into the game's grid, which is what makes the sticky action bar
     below work: a sticky box can never rise above its containing block, and inside .ar-controls the action bar
     sat at the very top — on a 678 px window it had nowhere to go and stayed under the tab bar. Its containing
     block is now the whole game card, so it floats above the bar and the board scrolls under it. */
  .ar-controls { display: contents; }
  /* The play and cash-out buttons stay above the tab bar: on a short phone the tab bar covered them, and a
     guide banner above the game pushed them further down. The card picker scrolls under them. */
  .ar-act { position: sticky; bottom: var(--tabbar-h); z-index: 3; margin: 0 -10px; padding: 8px 10px;
    background: var(--surface); transition: box-shadow .2s; }
  /* Floating over the game card (see window.mmcDock): what scrolls under the bar fades out well before its edge
     and a rule marks the bar. A 10 px fade inside the bar left a readable sliver of the warning, or of the top of
     the card picker, hanging just above the buttons — it read as a display bug. The last 24 px of this fade are
     plain surface, so nothing can ever be read right against the buttons; above them 32 px of gradient say the
     page goes on (scripts/barre_jeux_rien_ne_depasse.mjs measures both). The fade stops a px short of the bar so
     the rule stays visible: a fade opaque down to the bar's edge would paint over it. Back at the bottom of the
     page the bar drops the class and takes its normal place again. */
  .ar-act::before { content: ""; position: absolute; left: 0; right: 0; bottom: calc(100% + 1px); height: 56px;
    background: linear-gradient(to bottom, transparent, var(--surface) 32px); opacity: 0; transition: opacity .2s;
    pointer-events: none; }
  .ar-act.stuck { box-shadow: 0 -1px 0 var(--line); }
  .ar-act.stuck::before { opacity: 1; }
  .ar-controls .btn { font-size: 19px; padding: 11px 16px; }
  .ar-stake { padding: 8px; gap: 10px; }
  .ar-thumb { width: 48px; }
  .ar-stake-txt { gap: 0; line-height: 1.25; }
  .ar-stake-txt b { font-size: 15px; }
  .ar-stake-txt small, .ar-stake-txt em { font-size: 12px; }
  .ar-last { min-height: 0; font-size: 13px; }
  .ar-rules { margin-top: 10px; font-size: 13px; }
  /* The board takes what the rest of the screen leaves: --ar is the canvas ratio (set by the game) and --reserve
     is everything else between the top of the window and the tab bar. A game never pushes its own button away. */
  /* `.ar-board.ar-plinko` caps the width at 540 px on wide screens; this rule has to be at least as specific. */
  .ar-game .ar-board { max-width: min(100%, calc(var(--ar, 1.6) * max(120px, 100dvh - var(--reserve, 566px)))); margin-inline: auto; }
  /* Nyan Plinko has no cash-out button, so it can afford a taller board. */
  .ar-game .ar-plinko { --reserve: 520px; }
  /* Stonks pays for its ticker out of the chart, not out of the screen. */
  .ar-game .ar-stonks { --reserve: 600px; }
  /* A 390x844 phone has just enough height for the note, the ticker, the chart and the two buttons above the tab
     bar: the ticker gives back its last pixels so the cash-out button never ends up under them. */
  .ar-tape { font-size: 11px; gap: 6px; }
  .ar-tape li { padding: 1px 7px; }
  /* The verdict card follows the smaller board instead of spilling out of it. */
  .ar-verdict { padding: 10px; gap: 12px; }
  .ar-meme { height: min(100%, 128px); font-size: 16px; -webkit-text-stroke-width: 3px; }
  .ar-v-title { font-size: 21px; margin: 2px 0 0; }
  .ar-v-sub { font-size: 13px; }
  .ar-v-close { font-size: 11px; }
}
/* Short phones (an iPhone SE is 667 px tall): the flavour line and a few pixels everywhere buy back the board. */
@media (max-width: 860px) and (max-height: 760px) {
  .ar-head p { display: none; }
  .ar-head h1 { font-size: 21px; }
  .ar-controls .btn { font-size: 17px; padding: 9px 14px; }
  /* Play and cash-out side by side: stacked, they rose over the whole card picker and still ran under the tab bar. */
  .ar-act { grid-auto-flow: column; grid-auto-columns: auto; }
  .ar-act .btn { padding-inline: 8px; font-size: 16px; }
  .ar-stake { padding: 6px; }
  .ar-thumb { width: 42px; }
  .ar-game .ar-board { --reserve: 492px; }
  .ar-game .ar-plinko { --reserve: 500px; }
  .ar-verdict { padding: 8px; gap: 10px; }
  .ar-meme { height: min(100%, 110px); font-size: 14px; }
  .ar-v-title { font-size: 19px; }
  .ar-v-sub { font-size: 12px; }
}

/* The reminder that the card is spent, in every game: one compact line instead of a three-line block. */
@media (max-width: 860px) {
  .game-warn, .findpepe .burn-warn, .lucky-table .burn-warn {
    margin: 0; padding: 6px 10px; border-radius: 12px; font-size: 13px; line-height: 1.3;
  }
}
@media (max-width: 860px) and (max-height: 760px) {
  .game-warn, .findpepe .burn-warn, .lucky-table .burn-warn { font-size: 12px; padding: 5px 8px; }
}

/* ---- FindPepe ---- */
@media (max-width: 720px) {
  .findpepe .back-link { margin-bottom: 2px; }
  .findpepe .head-row { margin-bottom: 8px; }
  .findpepe h1 { font-size: 23px; }
  .fp-wrap { padding: 10px; gap: 8px; }
  .fp-side { gap: 6px; }
  .fp-board-wrap, .fp-board { max-width: min(90%, max(140px, 100dvh - var(--fp-reserve, 470px))); }
  .fp-thumb { width: 60px; }
  .fp-card-info { gap: 0; line-height: 1.25; }
  .fp-meta { font-size: 12px; }
  .fp-all { font-size: 12px; }
  .fp-card-info b { font-size: 15px; }
  .fp-pick .lt-nav { font-size: 22px; }
  .fp-stats div { padding: 8px 6px; }
  .fp-stats b { font-size: 17px; }
  .fp-cash, .fp-start { font-size: 19px; padding: 11px 16px; }
  .fp-life { font-size: 12px; }
  .fp-rules, .findpepe > p.muted { margin-top: 10px; font-size: 13px; }
}
@media (max-width: 720px) and (max-height: 760px) {
  .findpepe h1 { font-size: 21px; }
  .fp-board-wrap, .fp-board { --fp-reserve: 432px; max-width: min(76%, max(140px, 100dvh - var(--fp-reserve))); }
  .fp-thumb { width: 60px; }
  .fp-cash, .fp-start { font-size: 17px; padding: 9px 14px; }
}

/* ---- Nombres: the longest table of the five ---- */
@media (max-width: 860px) {
  .games .head-row { margin-bottom: 8px; }
  .games .head-row h1 { font-size: 23px; }
  .lucky-table { padding: 12px; gap: 10px; }
  .lt-thumb { width: 54px; }
  .lt-card-txt b { font-size: 15px; }
  .lt-value { font-size: 18px; }
  .lt-peek, .lt-peek .card { width: 38px; max-width: 38px; }
  .lt-label { margin-bottom: 6px; }
  .bet { padding: 10px 8px; font-size: 17px; min-height: 44px; box-sizing: border-box; }
  .bet.num { padding: 9px 0; font-size: 16px; }
  .bet-outside, .bet-numbers { gap: 7px; }
  /* The idle reel is a decoration; on a phone it was what pushed the numbers and the button off the screen.
     The sentence that explains the draw stays. */
  .reel-preview .reel-window.idle { display: none; }
  .lt-last { margin-top: 2px; font-size: 13px; }
  .lt-rules, .reel-preview p { font-size: 13px; }
  .xp-lucky { margin-top: 12px; }
}
@media (max-width: 860px) and (max-height: 760px) {
  .games .head-row h1 { font-size: 21px; }
  .lt-thumb { width: 46px; }
  .lt-card { padding: 6px; }
  .lt-card-txt { line-height: 1.2; }
  .lt-value { font-size: 16px; }
  .lt-label { margin-bottom: 4px; font-size: 15px; }
  .lt-prize { padding: 6px 12px; }
  .lucky-table { gap: 6px; padding: 10px; }
  .bet { padding: 8px; font-size: 16px; }
  .bet.num { padding: 7px 0; font-size: 15px; }
  .launch { font-size: 18px; padding: 10px 16px; }
}

/* ---- opening a pack: the card, its pager and the next-pack button in one screen ---- */
/* A laptop window is wide but not tall: at 1280x800 a full-width card pushed the pager and the end-of-pack
   buttons under the fold. The card gives up the height the rest of the screen needs, here too. */
@media (min-width: 900px) {
  .pack-open .slot, .pack-open .slot .card {
    width: min(300px, calc(max(180px, 100dvh - 520px) * 63 / 88));
    max-width: min(300px, calc(max(180px, 100dvh - 520px) * 63 / 88));
  }
  /* The guess above ignored the end-of-pack actions, and « Prochain pack dans » ended under the bottom of the
     window (Théo, 01/10/2026). --pull-room is the height showPull measured between the card's top and the
     window's bottom once the pager, the actions and the tile's edge are under it: it replaces the guess. */
  .packs .pack-open[style*="--pull-room"] .slot, .packs .pack-open[style*="--pull-room"] .slot .card {
    width: min(300px, calc(max(170px, var(--pull-room)) * 63 / 88));
    max-width: min(300px, calc(max(170px, var(--pull-room)) * 63 / 88));
  }
  /* Two buttons on one line: stacked, they alone pushed the way back 140px under the fold of a 1280x800 window.
     An opened pack takes the width it needs for that line — the closed tiles keep theirs. */
  .packs .pack-stage:has(.pack-open:not([hidden])) { max-width: 560px; }
  /* Shared out rather than laid end to end: whatever the labels measure, the line holds and never wraps. */
  .pack-open .ed-actions .btn { width: auto; flex: 1 1 0; min-width: 0; padding: 12px 18px; font-size: 16px; }
  .pack-open .ed-actions .open-again { flex-grow: 2; }
}
@media (max-width: 899px) {
  .pack-open .slot, .pack-open .slot .card {
    width: min(250px, 70vw, calc(max(170px, 100dvh - 420px) * 63 / 88));
    max-width: min(250px, 70vw, calc(max(170px, 100dvh - 420px) * 63 / 88));
  }
  /* The pack switcher sits above the tile: the card gives up that height. */
  .packs:has(.pack-switch) .pack-open .slot, .packs:has(.pack-switch) .pack-open .slot .card {
    width: min(250px, 70vw, calc(max(170px, 100dvh - 450px) * 63 / 88));
    max-width: min(250px, 70vw, calc(max(170px, 100dvh - 450px) * 63 / 88));
  }
  /* The guesses above miss what the page has grown since (the "missing meme" line, the switcher's countdown): at
     390x678 the arrows still ended under the tab bar. --pull-room is the height showPull measured for the card,
     between what sits above it and the site mark and pager under it, down to the bar: it replaces the guess. */
  .packs .pack-open[style*="--pull-room"] .slot, .packs .pack-open[style*="--pull-room"] .slot .card {
    width: min(250px, 70vw, calc(max(170px, var(--pull-room)) * 63 / 88));
    max-width: min(250px, 70vw, calc(max(170px, var(--pull-room)) * 63 / 88));
  }
  .pack-open .counter { margin-bottom: 6px; }
  .pack-open .pull-zone { padding-bottom: 10px; }
  .packs .tile { padding: 10px 8px 12px; }
}
/* The end-of-pack actions sat under the tab bar on a phone, out of reach, and the page scrolled behind a bare
   fixed button: a gold edge showed through. They now live in one dock fixed above the bar, with the page's own
   background under them and a short fade above, so nothing shows behind it and nothing sticks out. */
@media (max-width: 860px) {
  .pack-dock {
    position: fixed; z-index: 25; left: 0; right: 0;
    bottom: calc(var(--bar) + env(safe-area-inset-bottom));
    /* 14px under the last button, above the bar, whatever the safe area: the gap Théo asked for. */
    padding: 10px max(14px, env(safe-area-inset-left)) 14px max(14px, env(safe-area-inset-right));
    background: var(--page);
  }
  .pack-dock::before {
    content: ""; position: absolute; left: 0; right: 0; bottom: 100%; height: 28px; pointer-events: none;
    background: linear-gradient(180deg, transparent, var(--page));
  }
  /* Both actions keep their room from the first card: laid out and silent until they arm, so the dock never
     changes height and the page under it never jumps. */
  .pack-dock > .open-again[hidden] { display: block !important; }
  .pack-dock > .play-next[hidden] { display: flex !important; }
  .pack-dock > [hidden] { visibility: hidden; animation: none; pointer-events: none; }
  /* Until its action is out the dock is an empty box: painted, it laid a black band and its fade over the bottom
     of every card being turned, the pager and the odds included (Théo, 01/10/2026, 390x844 and smaller). It keeps
     its room, shows nothing and lets the taps through to the arrows under it. */
  .pack-dock:has(.open-again[hidden]) { background: none; pointer-events: none; }
  .pack-dock:has(.open-again[hidden])::before { content: none; }
  /* The reserve goes on the scroll tail, not on .pack-open: padding there sits above the collection progress that
     follows it, and the "see my cards" line stayed under the dock (measured 67px behind it). JS writes --dock-h on
     the root, so the tail is the dock's exact height over the bar; max() never shrinks the page's own 110px. */
  .view:has(.pack-dock) {
    padding-bottom: max(110px, calc(var(--dock-h, 96px) + var(--bar) + 8px + env(safe-area-inset-bottom)));
  }
  /* Inside the dock, the edition's strip reserves its room the same way: its two actions and their
     explanation only arm on the last card, and the dock must already be as tall as they make it. */
  .pack-dock .ed-actions { margin: 0; }
  .pack-dock .ed-actions:has(.open-again[hidden]) { display: grid; }
  .pack-dock .ed-actions > [hidden] { display: block !important; visibility: hidden; pointer-events: none; }
  /* Two actions on one line, the purchase wider than the way out. Their type is smaller than a lone button's:
     at the page's size, two labels side by side wrapped to three lines and the dock then ate the card. The dock
     carries the page's background, so neither button needs a shadow of its own any more. */
  /* A grid, not a flex line: as a flex line the explanation kept the 34ch cap of .ed-poor, so it fitted beside
     the two buttons instead of wrapping above them and crushed both into a 21px column with their labels cut
     (« Ret / aux / pac », 390x844 with a short balance). Two columns cannot be shared with anything else. */
  .pack-dock .ed-actions { display: grid; grid-template-columns: 1.6fr 1fr; gap: 8px; align-items: stretch; }
  .pack-dock .ed-actions .ed-again-poor { grid-column: 1 / -1; max-width: none; }
  .pack-dock .ed-actions .btn { min-width: 0; font-size: 15px; line-height: 1.2; padding: 12px 10px; }
}

/* An opening is a game frame, not a page. Scrolling one used to open a void under the cards, resize the card as
   the page moved under it, and slide the "5/5 · Dernière carte" badge up under the top bar (Théo, 01/10/2026).
   The frame fills what the top bar and the tab bar leave of the visible window — showPull writes --frame-top and
   --frame-h from the visual viewport — and holds the badge, the card, the pager and the dock, all at once. Being
   fixed, it is not clipped by the page it collapses behind it, and that page has nothing left to scroll. */
@media (max-width: 860px) {
  html:has(body.pack-framed), body.pack-framed { height: 100%; overflow: hidden; }
  body.pack-framed .view { height: 0; overflow: hidden; padding-bottom: 0; }
  .pack-open.framed {
    position: fixed; z-index: 18; left: 0; right: 0; top: var(--frame-top, 0px); height: var(--frame-h, 100dvh);
    display: flex; flex-direction: column; gap: 4px;
    padding: 6px max(16px, env(safe-area-inset-left)) 0 max(16px, env(safe-area-inset-right));
    background: var(--page);
    overflow: hidden; overscroll-behavior: contain; touch-action: manipulation;
  }
  /* The card's room is this row and only this row: whatever is left once the badge, the pager and the dock have
     taken theirs. fitPull measures it here, so no two cards of the pack can be given a different size. */
  .pack-open.framed .pull-zone { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; justify-content: center; padding-bottom: 0; }
  /* Every pixel this row does not spend on chrome is a pixel of card. The badge's own margin and the watermark
     line cost 33px of a 345px row on a 375x667 screen: the watermark belongs to the scrolling page and to the
     zoom view, not to a frame that has to choose between it and the card. The badge keeps 10px under it: that is
     where the "NOUVEAU" sticker hangs, and without it the sticker sat on the "5/5" on a 375x667 screen. */
  .pack-open.framed .counter { margin-bottom: 10px; }
  .pack-open.framed .site-mark { display: none; }
  /* In the frame the dock is simply its last row: fixed, it would have left it and gone back over the bar. */
  .pack-open.framed .pack-dock { position: static; padding: 8px 0 10px; background: none; }
  /* The card takes that whole row. The page's caps are guesses made for a scrolling layout; here the room is
     known exactly, and a card left at 250px wide would have hung in the middle of a half-empty frame.
     fitPull writes --pull-width: the width that makes the card exactly --pull-room tall at its own ratio. The
     63/88 of a printed card, and the 0.718 :root carries here, both left it short of its own row. */
  .packs .pack-open.framed .slot, .packs .pack-open.framed .slot .card {
    width: min(100%, var(--pull-width));
    max-width: min(100%, var(--pull-width));
  }
  /* A card that fills its row has no margin left for the "NOUVEAU" sticker to hang over: hung at its usual
     -1.5cqw it ran into the "5/5" counter and past the screen's left edge (390x844, 02/10/2026). In the frame
     it hangs over the top edge only, inside the card's width and above its title, at a size that no longer grows
     with a card this large. */
  .pack-open.framed .slot .new-tag { top: -2.5cqw; left: 3cqw; font-size: min(13px, max(11px, 5cqw)); }
}

/* The two long game pages — Nombres's bet table and FindPepe's board plus card picker — cannot show
   everything at once on a phone. Their action button leaves the flow and sits just above the tab bar, so it is
   reachable whatever the player has scrolled to. */
@media (max-width: 860px) {
  .lucky-table, .findpepe .fp-wrap { padding-bottom: calc(var(--bar) + 78px + env(safe-area-inset-bottom)); }
  .lucky-table .launch, .findpepe .fp-start, .findpepe .fp-cash {
    position: fixed; z-index: 25; margin: 0; width: auto;
    left: max(14px, env(safe-area-inset-left)); right: max(14px, env(safe-area-inset-right));
    bottom: calc(var(--bar) + 8px + env(safe-area-inset-bottom));
    box-shadow: 0 10px 30px rgba(0, 0, 0, .45);
  }
}

/* Small action buttons sat at 28-38 px: on a phone every one of them is a finger target. */
@media (max-width: 899px) {
  .btn.small-btn, .friend .btn, .friend-actions .btn, .find-row .btn, .rp-foot .btn, .lot .btn, .trade .btn, .ach .claim {
    min-height: 44px; padding-block: 0; display: inline-flex; align-items: center; justify-content: center;
  }
  .chips button, .adm-tabs button, .durations span, .theme-switch button, .rank-tabs button { min-height: 44px; }
  .theme-toggle { width: 44px; height: 44px; }
  /* A small round button keeps its look and gains the room around it. */
  .show-remove, .icon-btn { position: relative; }
  .show-remove::before, .icon-btn::before { content: ""; position: absolute; inset: -9px; }
  .coins { min-height: 44px; box-sizing: border-box; }
  /* The stars stay absolute (their own rules place them on the card) — made relative here, they fell under it. */
  .info-dot { position: relative; }
  .info-dot::before, .coll-tile .fav::before, .slot .fav::before {
    content: ""; position: absolute; left: 50%; top: 50%; width: 44px; height: 44px; transform: translate(-50%, -50%);
  }
}

/* The pinned button is translucent while it is disabled: a strip of page colour behind it keeps the text of the
   game from showing through, and separates it from what scrolls underneath. */
@media (max-width: 860px) {
  .lucky-table::after, .findpepe .fp-wrap::after {
    content: ""; position: fixed; left: 0; right: 0; z-index: 24; pointer-events: none;
    bottom: calc(var(--bar) + env(safe-area-inset-bottom));
    height: 80px;
    background: linear-gradient(180deg, transparent, var(--page) 34%);
  }
}

/* The market tabs scroll sideways on a phone: a faded right edge says there is more than "Parcourir". */
@media (max-width: 899px) {
  .market-tabs { -webkit-mask-image: linear-gradient(90deg, #000 86%, transparent); mask-image: linear-gradient(90deg, #000 86%, transparent); }
}

/* ---- collection: progress in the header, one sticky row of filters, and the card page (design handoff §3.3) ---- */
/* The row sticks right under the top bar of the phone layout; the desktop layout has a sidebar and no top bar. */
body.app { --app-top-h: 68px; }
@media (min-width: 900px) { body.app { --app-top-h: 0px; } }
.coll-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.coll-head h1 { margin: 0; }
.coll-count { font-weight: 800; font-size: 15px; color: var(--muted); white-space: nowrap; }
.coll-count b { color: var(--text); font-size: 20px; }
.coll-bar { display: block; height: 8px; margin-top: 10px; border-radius: 999px; background: var(--surface-2); overflow: hidden; }
.coll-bar i { display: block; height: 100%; border-radius: inherit; background: var(--gold); }
/* The search field and the filters travel together: one sticky block, so a phone keeps both within thumb reach. */
.coll-sticky { position: sticky; top: var(--app-top-h); z-index: 15; padding-bottom: 6px; background: var(--page); }
.coll-search { position: relative; display: flex; }
/* 16px is the floor: under it, iOS Safari zooms the page in when the field takes focus. */
.coll-search input {
  width: 100%; min-height: 44px; padding: 0 44px 0 16px; font: inherit; font-size: 16px; font-weight: 700;
  color: var(--text); background: var(--page); border: 1px solid var(--line); border-radius: 14px; -webkit-appearance: none; appearance: none;
}
.coll-search input::placeholder { color: var(--muted); font-weight: 700; }
.coll-search input::-webkit-search-cancel-button, .coll-search input::-webkit-search-decoration { -webkit-appearance: none; display: none; }
.coll-search .q-clear {
  position: absolute; right: 5px; top: 50%; transform: translateY(-50%);
  width: 34px; height: 34px; display: grid; place-items: center; font-size: 15px; font-weight: 900;
  color: var(--muted); background: none; border: 0; border-radius: 999px; cursor: pointer;
}
.coll-search .q-clear[hidden] { display: none; }
.chip-n { font-size: 12px; font-weight: 900; padding: 1px 7px; border-radius: 999px; background: var(--surface-2); color: var(--text); }
.chips button[aria-pressed="true"] .chip-n { background: rgba(0, 0, 0, .18); color: inherit; }
.stake-chips button[aria-pressed="true"] .chip-n { background: rgba(0, 0, 0, .18); color: inherit; }
/* The Collection's filters. Sticking under the top bar: the search, the count and the "Filtres" button, then one
   compact line that keeps the pack chips within reach and names, in pills, whatever filter is off its default.
   The rows themselves (which cards, rarity, missing) wait in a panel folded until "Filtres" opens it — unfolded
   they are a screenful of chips on a phone, and push every card under the fold. */
.coll-top { padding-top: 10px; }
.coll-top .coll-search { flex: 1; min-width: 0; }
/* One line, never two: what overflows slides sideways inside it instead of growing the sticky header. */
.coll-sum { display: flex; align-items: center; gap: 6px; margin-top: 6px; overflow-x: auto; scrollbar-width: none; }
.coll-sum::-webkit-scrollbar { display: none; }
.coll-sum .stake-chips { flex: none; flex-wrap: nowrap; }
.coll-sum .stake-chips button { min-height: 36px; }
.coll-pills { display: flex; flex: none; gap: 6px; }
.coll-pill { display: inline-flex; align-items: center; height: 28px; padding: 0 10px; border-radius: 999px; background: var(--surface-2); color: var(--muted); font-size: 12px; font-weight: 800; white-space: nowrap; }
.coll-filters.stake-filters { margin: 0; padding: 0 12px; max-height: 0; opacity: 0; overflow: hidden; transition: max-height .24s ease, opacity .16s ease, padding .24s ease, margin .24s ease; }
.coll-filters.stake-filters.open { margin: 6px 0 0; padding: 12px; max-height: 62vh; opacity: 1; overflow-y: auto; }
/* The rows scroll inside the panel, so Reinitialiser and Fermer stay on screen instead of ending up under
   the tab bar on a short phone. -12px swallows the panel's own bottom padding. */
.coll-filters .stake-ffoot { position: sticky; bottom: -12px; padding: 8px 0 12px; background: var(--surface-2); }
@media (prefers-reduced-motion: reduce) { .coll-filters.stake-filters { transition: none; } }
/* Under the sidebar breakpoint the panel is a sheet anchored above the tab bar: there it always has the room for
   its rows and its footer, whatever the banner and the title take at the top of the collection, and opening it
   no longer moves the cards it filters. */
@media (max-width: 899px) {
  .coll-filters.stake-filters { position: fixed; left: 8px; right: 8px; bottom: calc(var(--tabbar-h) + 8px); z-index: 29; box-shadow: 0 10px 30px rgb(0 0 0 / .35); }
  .coll-filters.stake-filters.open { margin: 0; max-height: 60dvh; }
}
/* Compact, on the same line as Reinitialiser rather than a full-width block of its own. */
.coll-close.btn { flex: none; width: auto; margin: 0; min-height: 40px; padding: 0 16px; font-size: 14px; }
.coll-filters .stake-chips button { min-height: 38px; padding: 0 13px; font-size: 14px; }
.coll-filters .stake-hide { min-height: 42px; }
/* With room to spare, each row's name holds a column of its own, so a second line of chips starts under the first
   chip, not under the name: the three rows read as a table. A phone keeps the name inline, as in the stake picker,
   where a column would cost a line per row. */
@media (min-width: 520px) {
  .coll-filters .stake-chips { position: relative; padding-left: 90px; }
  .coll-filters .stake-flabel { position: absolute; left: 0; top: 0; display: flex; align-items: center; width: 84px; height: 38px; margin: 0; }
}
/* "Ma collection" on one line: the three segments share the room by their length instead of in equal thirds. */
.coll > .seg button { flex: 1 1 auto; padding-inline: 8px; white-space: nowrap; }
.coll-packs .pk-flag { font-size: 15px; line-height: 1; }
/* The « Éditions ▾ » chip, third on the PACK row. The row already wraps, so at 320 px it drops under the two
   packs instead of running off the edge; an edition whose name is longer than the row cuts with an ellipsis
   rather than widening it. */
.coll-edpick, .market-edpick { max-width: 100%; }
.ed-chip-n { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.coll .coll-grid { margin-top: 18px; }

.card-sheet { display: grid; gap: 14px; }
/* The card page hides a step at a time; a display rule of its own would win over [hidden]. */
.card-sheet [hidden] { display: none; }
.sheet-visual { display: grid; justify-items: center; }
.sheet-visual .card { max-width: 260px; }
.sheet-visual.ghost { opacity: .35; filter: grayscale(1); }
.cs-title { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.cs-title h2 { font-size: 24px; }
.cs-title .mini { margin: 0; flex: none; }
.cs-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.cs-stats.four { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.cs-stats > div { display: grid; gap: 2px; padding: 10px 12px; border-radius: 14px; background: var(--surface); border: 1px solid var(--line); }
.cs-stats small { color: var(--muted); font-weight: 700; font-size: 12px; }
.cs-stats b { font-size: 18px; }
.cs-locked, .cs-empty { margin: 0; }
.cs-empty { font-weight: 700; text-align: center; }
.card-sheet .btn { margin: 0; text-decoration: none; }
/* Le 22 px du bouton de la page d'accueil faisait tenir « La trouver sur le marché » sur deux lignes à 320 px. */
.card-sheet .to-market { display: grid; place-items: center; min-height: 52px; padding: 12px 16px; font-size: 18px; }
.cs-actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.cs-actions .btn { min-height: 48px; font-size: 14px; padding: 10px 8px; text-wrap: balance; }
/* The whole history behind one row: auctions, sales and the EXPERT price chart. */
.cs-hist { display: flex; align-items: center; justify-content: space-between; gap: 10px; width: 100%; min-height: 48px; padding: 0;
  border: 0; border-top: 1px solid var(--line); background: none; color: var(--text); font: inherit; font-weight: 800; font-size: 15px; cursor: pointer; }
.cs-hist[aria-expanded="true"] .muted { color: var(--gold); }
.card-sheet .history { margin-top: 0; }

/* ===== Rewards: the Carte de Fidélité, a battle-pass track ===== */
/* Built for 375x667 first: one horizontal lane the thumb drags, big reward tiles, thin levels in between. */
:root, :root[data-theme="dark"] {
  --ly-bg: radial-gradient(130% 120% at 0% 0%, #2b2208 0%, #17150e 48%, #13151c 100%);
  --ly-edge: rgba(255, 216, 74, .32); --ly-rail: rgba(255, 255, 255, .13); --ly-num: #8a93a3;
  --ly-tile-line: rgba(255, 255, 255, .12); --ly-cell: rgba(255, 255, 255, .07); --ly-ring: #13151c; --ly-lost-bg: rgba(229, 72, 77, .12); --ly-lost-line: rgba(229, 72, 77, .38);
}
:root[data-theme="light"] {
  --ly-bg: radial-gradient(130% 120% at 0% 0%, #fff0c7 0%, #fff9ea 50%, #ffffff 100%);
  --ly-edge: #efd9a1; --ly-rail: #e3d7bb; --ly-num: #8b7f63;
  --ly-tile-line: rgba(0, 0, 0, .18); --ly-cell: rgba(0, 0, 0, .045); --ly-ring: #fffdf6; --ly-lost-bg: #fff0f0; --ly-lost-line: #f3b7b9;
}
.achievements > .head-row h1 { margin: 0; }
.ach-head { margin-top: 26px; }
.ach-head h2 { margin: 0 0 2px; font-size: 22px; color: var(--heading); text-align: left; }

/*
  The menu of the Récompenses page: the two panels, Carte de Fidélité and Succès, reachable without a scroll.
  It sticks right under the top bar so the choice stays in reach while a panel is read, on the phone above all,
  where the card alone is a whole screen. Desktop keeps the same menu: at 1280 the card already takes the panel's
  full width, so putting the two side by side would squeeze both instead of hiding neither.
*/
/* The menu and the claim bar stick together as one block, so the bar needs no knowledge of the menu's height. */
.ach-sticky { position: sticky; top: var(--app-top-h); z-index: 15; background: var(--page); }
.ach-sticky .ach-seg { position: static; }
.ach-seg { position: sticky; top: var(--app-top-h); z-index: 15; background: var(--page); }
/* « Tout réclamer » at the head of the panel, never under the fold: what is owed and the button on one row. */
.ach-claim-bar { display: flex; align-items: center; gap: 10px; margin: 0 0 10px; padding: 8px 10px; border-radius: 14px;
  border: 2px solid var(--gold-text); background: linear-gradient(160deg, rgba(240, 185, 11, .20), rgba(240, 185, 11, .08)); }
.ach-claim-bar[hidden] { display: none; }
.ach-claim-n { display: flex; align-items: center; gap: 6px; font-size: 14px; font-weight: 800; color: var(--muted); }
.ach-claim-n b { font-size: 18px; font-weight: 900; color: var(--heading); }
.ach-claim-bar .claim-all { width: auto; margin: 0 0 0 auto; padding: 10px 16px; font-size: 16px; }
@media (max-width: 360px) { .ach-claim-n { font-size: 13px; } .ach-claim-bar .claim-all { padding: 10px 12px; font-size: 15px; } }
.ach-seg .seg { margin: 10px 0; }
.ach-seg .seg button { white-space: nowrap; }
.ach-seg .seg button small { font-size: 13px; font-weight: 800; color: var(--muted); }
.ach-seg .seg button[aria-selected="true"] small { color: inherit; }
/* The themes, scrolled through with a thumb: the row scrolls on its own, the page never sideways. */
.ach-jump { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin-bottom: 6px; padding-inline-end: 18px; }
.ach-jump::-webkit-scrollbar { display: none; }
.ach-jump button { flex: none; min-height: 44px; white-space: nowrap; }
/* A chip lands its theme under the sticky menu, not behind it. */
.ach-cat { scroll-margin-top: calc(var(--app-top-h) + 76px); }
/* With the claim bar riding along, a theme has that much more to clear before it is read. */
.achievements:has(.ach-claim-bar:not([hidden])) .ach-cat { scroll-margin-top: calc(var(--app-top-h) + 136px); }
.ly {
  position: relative; display: grid; gap: 12px; padding: 14px 14px 12px; border-radius: 22px; background: var(--ly-bg); border: 1px solid var(--ly-edge);
  box-shadow: 0 14px 34px rgba(0, 0, 0, .18); overflow: hidden; }
.ly-top, .ly-hero, .ly-pass, .ly-info, .ly-bonus { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }

/* the compact header: the card's name, the (i) that opens the rules, the bonus packs waiting */
.ly-top { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.ly-kicker { font-size: 12px; font-weight: 900; letter-spacing: .12em; text-transform: uppercase; color: var(--gold); }
.ly-info { width: 24px; height: 24px; padding: 0; border: 0; font-size: 15px; cursor: pointer; flex: none; }
.ly-bonus { flex: 1 1 100%; display: inline-flex; justify-content: center; align-items: center; gap: 6px; padding: 6px 10px; border-radius: 999px; background: var(--surface-2); border: 1px solid var(--line);
  color: var(--text); text-decoration: none; font-size: 13px; font-weight: 800; }
.ly-bonus b { color: var(--gold); }
.ly-pk { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; flex: none; }
/* The header, read like a battle pass level: the streak in a badge, one line, a bar to the next reward. */
.ly-hero { display: flex; align-items: center; gap: 12px; }
.ly-badge { position: relative; flex: none; display: grid; place-items: center; width: 60px; height: 60px; border-radius: 18px;
  background: linear-gradient(160deg, #ffb347 0%, #ff6a1a 55%, #d9360f 100%); box-shadow: 0 6px 16px rgba(217, 54, 15, .35), inset 0 1px 0 rgba(255, 255, 255, .35); }
.ly-n { font-family: "Anton", Impact, sans-serif; font-weight: 400; font-size: 32px; line-height: 1; color: #fff; font-variant-numeric: tabular-nums; text-shadow: 0 2px 0 rgba(120, 30, 0, .45); }
.ly-flame { position: absolute; top: -10px; right: -8px; font-size: 22px; transform-origin: 50% 90%; animation: ly-flame 2.4s ease-in-out infinite; }
@keyframes ly-flame { 0%, 100% { transform: rotate(-4deg) scale(1); } 50% { transform: rotate(4deg) scale(1.08); } }
.ly-head { display: grid; gap: 7px; min-width: 0; flex: 1; }
.ly-head-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ly-headline { font-size: 19px; font-weight: 900; line-height: 1.15; color: var(--heading); }
.ly-chip { display: inline-flex; align-items: center; gap: 4px; padding: 3px 9px; border-radius: 999px; font-size: 12px; font-weight: 900; white-space: nowrap; }
.ly-chip.ok { background: rgba(29, 179, 107, .14); color: #11875a; }
:root[data-theme="dark"] .ly-chip.ok { color: #4ade80; }
.ly-chip.warn { background: rgba(255, 106, 26, .14); color: #c2410c; }
.ly-chip.next { background: rgba(255, 106, 26, .10); color: #9a3412; }
:root[data-theme="dark"] .ly-chip.next { color: #fdba74; }
.ly-chip b { font-variant-numeric: tabular-nums; }
.ly-chip svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 3.2; stroke-linecap: round; stroke-linejoin: round; }
.ly-goal small { font-size: 13px; font-weight: 800; color: var(--muted); }
/* The (i) of the card: neutral ink, not the brown gold of the other info dots. */
.ly .ly-info { background: rgba(0, 0, 0, .08); color: var(--text); font-size: 13px; }
:root[data-theme="dark"] .ly .ly-info { background: rgba(255, 255, 255, .12); }

/* The battle pass track, and the rule the whole layout serves: it fits the card's width whole, from 320px to 1440px,
   so the day-30 jackpot at its right end is seen without a swipe and without guessing there is one. The five tiles
   share the width in equal columns — equal, not proportional to the days, or 1-3-5 would pile up on the left — and
   the line under them carries the 30 days, each segment holding its own intermediate days. Nothing here scrolls. */
.ly-pass { display: grid; gap: 6px; }
.ly-aim { margin: 0; font-size: 12.5px; font-weight: 800; line-height: 1.35; color: var(--muted); }
.ly-aim b { font-size: 14.5px; color: var(--gold); }

/* the reward tiles: the pack, how many of them, the state of the tier. One column each, the last one the biggest. */
.ly-tiles { list-style: none; margin: 0; padding: 0; display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; align-items: end; }
.ly-tile { justify-self: center; width: calc(100% - 6px); max-width: 64px; }
.ly-art { position: relative; display: grid; place-items: center; aspect-ratio: 1 / 1.1; border-radius: 12px; overflow: hidden;
  border: 1px solid var(--ly-tile-line); background: linear-gradient(160deg, #3a4150, #232833); box-shadow: 0 5px 14px rgba(0, 0, 0, .28); }
.ly-tile.r-rare .ly-art { background: linear-gradient(160deg, #1f5a86, #142a41); }
.ly-tile.r-epic .ly-art { background: linear-gradient(160deg, #5f2c90, #2a1445); }
.ly-tile.r-mythic .ly-art { background: linear-gradient(160deg, #b23a2c, #3c1511); }
/* the last tier, the legendary one: the widest tile of the row, gold, swept by a slow light — the objective */
.ly-tile.r-legend { width: 100%; max-width: 82px; }
.ly-tile.r-legend .ly-art { aspect-ratio: 1 / 1.3; border: 2px solid #ffe79a; background: linear-gradient(160deg, #fff0ad, #f5b120 42%, #a86608);
  box-shadow: 0 8px 22px rgba(240, 176, 30, .42); }
.ly-tile.r-legend .ly-art::after { content: ""; position: absolute; inset: -40%; pointer-events: none;
  background: linear-gradient(70deg, transparent 42%, rgba(255, 255, 255, .55) 50%, transparent 58%); animation: ly-sweep 3.4s linear infinite; }
@keyframes ly-sweep { 0% { transform: translateX(-60%); } 100% { transform: translateX(60%); } }
.ly-pack { width: 54%; aspect-ratio: 63 / 88; background: url(/pack-front.webp?v=7cc6581117) center / 100% 100% no-repeat; filter: drop-shadow(0 4px 9px rgba(0, 0, 0, .5)); margin-bottom: 10%; }
.ly-x { position: absolute; top: 3px; right: 5px; font-family: "Anton", Impact, sans-serif; font-weight: 400; font-size: clamp(13px, 4.2vw, 18px); line-height: 1;
  color: #fff; text-shadow: 0 2px 5px rgba(0, 0, 0, .75); }
.ly-tile.r-legend .ly-x { color: #3a2400; text-shadow: 0 1px 0 rgba(255, 255, 255, .6); }
.ly-ribbon { position: absolute; left: 0; right: 0; bottom: 0; padding: 3px 1px; display: flex; align-items: center; justify-content: center; gap: 2px;
  text-align: center; font-size: clamp(8px, 2.5vw, 10px); font-weight: 900;
  letter-spacing: .04em; text-transform: uppercase; color: #fff; background: rgba(19, 168, 106, .94); }
.ly-ribbon svg { width: 10px; height: 10px; flex: none; fill: none; stroke: currentColor; stroke-width: 3.4; stroke-linecap: round; stroke-linejoin: round; }
/* The tiers owed call for the one button above, they are not buttons themselves. */
.ly-tile.ready .ly-ribbon { background: rgba(61, 220, 140, .96); color: #06301d; }
.ly-tile.locked .ly-art { filter: grayscale(.72) brightness(.62); box-shadow: none; }
/* The jackpot never dims: locked or not, it is the objective the player is walking towards, so it keeps its gold. */
.ly-tile.r-legend.locked .ly-art { filter: none; box-shadow: 0 8px 22px rgba(240, 176, 30, .42); }
.ly-tile.claimed .ly-art { opacity: .6; }
.ly-tile.gone .ly-art, .ly-tile.held .ly-art { filter: grayscale(1); opacity: .45; }
.ly-tile.gone .ly-ribbon { background: rgba(229, 72, 77, .92); }
.ly-tile.held .ly-ribbon { background: rgba(120, 120, 120, .92); }
.ly-tile.ready .ly-art { box-shadow: 0 0 0 2px #3ddc8c, 0 8px 22px rgba(29, 179, 107, .45); animation: ly-glow 1.9s ease-in-out infinite; }
@keyframes ly-glow { 50% { box-shadow: 0 0 0 3px #3ddc8c, 0 10px 28px rgba(29, 179, 107, .7); } }
.ly-lock { position: absolute; left: 5px; top: 5px; width: 14px; height: 14px; fill: none; stroke: #fff; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; opacity: .72; }

/* the line of the 30 days: it runs from the centre of the first tile to the centre of the last, half a column in on
   each side — hence 50% / the number of tiers, which the view hands over as --ly-cols. */
.ly-rail-in { position: relative; height: 22px; margin-inline: calc(50% / var(--ly-cols, 5)); }
.ly-line { position: absolute; left: 0; right: 0; top: 50%; height: 6px; transform: translateY(-50%); border-radius: 999px; background: var(--ly-rail); overflow: hidden; }
.ly-line i { display: block; height: 100%; border-radius: inherit; background: linear-gradient(90deg, #ffd44a, #ffb01f); }
.ly-days { list-style: none; margin: 0; padding: 0; position: absolute; inset: 0; }
/* one graduation a day: small between the tiers, a node on a tier day, red on a day missed */
.ly-day { position: absolute; top: 50%; width: 4px; height: 4px; margin: -2px 0 0 -2px; border-radius: 50%; background: var(--ly-num); opacity: .5; }
.ly-day.on { background: #8a5400; opacity: .9; }
.ly-day.stop { width: 11px; height: 11px; margin: -5.5px 0 0 -5.5px; opacity: 1; border: 2px solid var(--ly-ring); background: var(--ly-num); }
.ly-day.stop.on { background: #b8720a; }
.ly-day.missed { width: 9px; height: 9px; margin: -4.5px 0 0 -4.5px; opacity: 1; background: #e5484d; }
.ly-cursor { position: absolute; top: 50%; z-index: 2; transform: translate(-50%, -50%); display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%;
  background: var(--ly-ring); border: 2px solid var(--gold); box-shadow: 0 2px 9px rgba(255, 176, 31, .55); }
.ly-cursor b { font-size: 11.5px; font-weight: 900; line-height: 1; color: #8a5400; font-variant-numeric: tabular-nums; }
.ly-cursor.ly-in { animation: ly-pop .6s cubic-bezier(.2, 1.4, .4, 1) both; }
@keyframes ly-pop { 0% { transform: translate(-50%, -50%) scale(2.2); opacity: 0; } 60% { transform: translate(-50%, -50%) scale(.9); opacity: 1; } 100% { transform: translate(-50%, -50%) scale(1); } }

/* the day of each tier, under its tile, on the same columns */
.ly-marks { list-style: none; margin: 0; padding: 0; display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; }
.ly-marks li { text-align: center; font-size: 10.5px; font-weight: 900; color: var(--ly-num); white-space: nowrap; font-variant-numeric: tabular-nums; }
.ly-marks li:last-child { color: var(--gold); }

/* what is owed, at the top of the card: the one block the eye must land on, and the only place the claim buttons
   live. It holds its own height on a 678px tall phone, so the button is never the thing below the fold. */
.ly-cash { display: grid; gap: 8px; padding: 12px; border-radius: 16px; border: 2px solid #3ddc8c;
  background: linear-gradient(160deg, rgba(61, 220, 140, .18), rgba(19, 168, 106, .10)); box-shadow: 0 8px 22px rgba(19, 168, 106, .22); }
.ly-cash-line { margin: 0; display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 2px 10px; }
.ly-cash-ico { grid-row: span 2; font-size: 26px; line-height: 1; }
.ly-cash-line b { font-size: 18px; font-weight: 900; line-height: 1.15; color: var(--heading); }
.ly-cash-line small { font-size: 13px; font-weight: 800; color: var(--muted); }
.ly-cash .ly-claim-all { animation: ly-cash-call 2.2s ease-in-out infinite; }
@keyframes ly-cash-call { 0%, 100% { box-shadow: 0 0 0 0 rgba(61, 220, 140, .55); } 55% { box-shadow: 0 0 0 7px rgba(61, 220, 140, 0); } }

.ly-lock { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.ly-tile.just-claimed .ly-art { animation: ly-claimed .6s ease-out both; }
@keyframes ly-claimed { 0% { transform: scale(1); } 35% { transform: scale(1.06); } 100% { transform: scale(1); opacity: .75; } }
.ly-claim-all { margin: 0; width: 100%; min-height: 56px; font-size: 17px; }
.ly-older { margin: 0; font-size: 13px; font-weight: 700; color: var(--muted); display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.ly-t-mini { border-radius: 999px; padding: 4px 10px; font-size: 12px; font-weight: 900; color: #fff; background: #13a86a; }
.ly-note { margin: 0; font-size: 12px; font-weight: 700; color: var(--muted); }
.ly-rules { margin: 0; font-size: 15px; font-weight: 700; color: var(--text); }

/* a streak lost, or saveable with the EXPERT second chance */
.ly-alert { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; padding: 10px 12px; border-radius: 14px; }
.ly-alert > span:nth-child(2) { flex: 1 1 180px; display: grid; gap: 1px; }
.ly-alert b { font-size: 15px; color: var(--heading); }
.ly-alert small { font-size: 13px; font-weight: 700; color: var(--muted); }
.ly-alert small b { font-size: inherit; font-variant-numeric: tabular-nums; }
.ly-alert-ico { font-size: 24px; line-height: 1; flex: none; }
.ly-alert.lost { background: var(--ly-lost-bg); border: 1px solid var(--ly-lost-line); }
.ly-alert.rescue { background: rgba(255, 216, 74, .1); border: 1px solid var(--ly-edge); }
.ly-alert .ly-rescue { flex: 1 1 100%; margin: 2px 0 0; padding-inline: 8px; font-size: 14.5px; }
.ly .ly-xp { margin-top: 0; padding: 10px 12px; gap: 10px; border-radius: 16px; }
.ly .ly-xp b { font-size: 14.5px; }
.ly .ly-xp small { font-size: 12.5px; }
.ly .xp-lucky-ico { font-size: 22px; width: 30px; height: 30px; border-radius: 9px; }
.ly .xp-lucky-cta { min-height: 34px; margin-left: 40px; padding: 6px 12px; font-size: 13px; }

/* A 320px phone: the card gives its padding back to the tiles, which stay above 48px wide and keep their five columns. */
@media (max-width: 360px) { .ly { padding: 12px 10px 10px; } .ly-badge { width: 54px; height: 54px; } .ly-n { font-size: 28px; } .ly-headline { font-size: 17px; }
  .ly-tile { width: calc(100% - 4px); } .ly-marks li { font-size: 9.5px; } .ly-cursor { width: 24px; height: 24px; } }
/* A short screen (an iPhone SE, a 390x678 window): the streak header gives its height to the claim block above it. */
@media (max-height: 700px) {
  .ly { gap: 10px; }
  .ly-badge { width: 48px; height: 48px; border-radius: 14px; } .ly-n { font-size: 25px; } .ly-flame { font-size: 18px; top: -8px; }
  .ly-headline { font-size: 17px; }
  .ly-cash { padding: 10px; } .ly-cash-line b { font-size: 17px; }
}
@media (min-width: 700px) {
  .ly { padding: 20px 22px 18px; gap: 14px; }
  .ly-bonus { flex: 0 0 auto; margin-left: auto; }
  .ly-badge { width: 72px; height: 72px; border-radius: 20px; } .ly-n { font-size: 38px; } .ly-headline { font-size: 22px; }
  .ly-pass { gap: 8px; }
  .ly-aim { font-size: 14px; } .ly-aim b { font-size: 17px; }
  .ly-tile { max-width: 104px; } .ly-tile.r-legend { max-width: 132px; }
  .ly-rail-in { height: 28px; } .ly-line { height: 8px; }
  .ly-cursor { width: 32px; height: 32px; } .ly-cursor b { font-size: 14px; }
  .ly-marks li { font-size: 13px; }
  .ly-cash { padding: 14px 16px; } .ly-cash-line b { font-size: 20px; }
}
/* the phone tab bar's badge sits on its icon */
.tabbar a { position: relative; }
@media (prefers-reduced-motion: reduce) {
  .ly-flame, .ly-cursor.ly-in, .ly-tile.r-legend .ly-art::after, .ly-tile.ready .ly-art, .ly-tile.just-claimed .ly-art,
  .ly-cash .ly-claim-all { animation: none; }
}
/* ---------- shop: MemeCoin packs sold like a game currency (League of Legends, Fortnite) ---------- */
.shop-head { text-align: center; display: grid; gap: 6px; }
.shop-head h1 { margin: 0; font-size: clamp(28px, 8vw, 36px); color: var(--heading); text-align: center; }
.shop-what { margin: 0 auto; max-width: 42ch; font-size: 14px; font-weight: 700; color: var(--muted); text-wrap: balance; }
/* Phone first: the best pack is the hero across the top, the four others two by two under it — no hole. A computer
   lines the five up from the smallest to the biggest. */
.shop-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-top: 18px; }
.offer.hero { grid-column: 1 / -1; order: -1; }
@media (min-width: 900px) { .shop-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 12px; } .offer.hero { grid-column: auto; order: 0; } }
/* The cards are dark in both themes, like a game's shop: each step up the ladder gets a richer colour. */
.offer { --bg1: #2a3140; --bg2: #151922; --edge: rgba(255, 255, 255, .10); --glow: transparent;
  position: relative; overflow: hidden; display: grid; justify-items: center; align-content: start; gap: 6px; padding: 30px 10px 10px; min-height: 236px;
  border-radius: 20px; border: 1.5px solid var(--edge); color: #fff; font: inherit; cursor: pointer; -webkit-user-select: none; user-select: none;
  background: radial-gradient(120% 90% at 50% 18%, var(--bg1) 0%, var(--bg2) 72%); box-shadow: 0 10px 26px rgba(0, 0, 0, .18), inset 0 0 40px var(--glow);
  transition: transform .14s ease, box-shadow .14s ease; }
.offer.tier-2 { --bg1: #135b6e; --bg2: #0b2129; --edge: rgba(94, 214, 240, .28); }
.offer.tier-3 { --bg1: #4a2f9c; --bg2: #160f2e; --edge: rgba(170, 140, 255, .34); }
.offer.tier-4 { --bg1: #8a2a6f; --bg2: #220b1d; --edge: rgba(255, 130, 210, .38); }
.offer.tier-5 { --bg1: #9a6a06; --bg2: #241700; --edge: rgba(255, 216, 74, .7); --glow: rgba(255, 200, 60, .18); min-height: 260px; }
.offer:focus-visible { transform: translateY(-3px); box-shadow: 0 16px 34px rgba(0, 0, 0, .28), inset 0 0 40px var(--glow); }
@media (hover: hover) { .offer:hover { transform: translateY(-3px); box-shadow: 0 16px 34px rgba(0, 0, 0, .28), inset 0 0 40px var(--glow); } }
.offer:disabled { opacity: .55; cursor: default; transform: none; }
/* A slow sheen crosses the best pack, and only that one. */
.offer.tier-5::after { content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(105deg, transparent 35%, rgba(255, 240, 190, .22) 50%, transparent 65%) -200% 0 / 200% 100% no-repeat;
  animation: of-sheen 3.6s ease-in-out infinite; }
@keyframes of-sheen { 0%, 40% { background-position: -200% 0; } 100% { background-position: 200% 0; } }
@media (prefers-reduced-motion: reduce) { .offer { transition: none; } .offer.tier-5::after { animation: none; } }
/* Ribbons: the bonus in green on the left, the badge on the right. */
.of-ribbon, .of-badge { position: absolute; top: 10px; z-index: 1; font-size: 11px; font-weight: 900; letter-spacing: .02em; line-height: 1; padding: 5px 8px; border-radius: 999px; }
.of-ribbon { left: 10px; background: #22c55e; color: #052e14; }
.of-badge { right: 10px; background: rgba(255, 255, 255, .14); color: #fff; }
.of-badge.best { background: linear-gradient(135deg, #ffe08a, #f2b53a); color: #2a1a00; }
/* The treasure: the struck MemeCoin in front of coin stacks that grow with the pack. */
.of-pile { position: relative; display: flex; align-items: flex-end; justify-content: center; width: 100%; height: 112px; }
.offer.hero .of-pile { height: 124px; }
@media (max-width: 440px) { .of-pile { --spread: .74; } .offer.hero .of-pile { --spread: 1; } }
.of-pile .memecoin { position: relative; z-index: 2; filter: drop-shadow(0 8px 14px rgba(0, 0, 0, .45)); }
/* Stacks sit either side of the coin, right then left then further out, so each one added stays in sight. */
.of-stack { position: absolute; bottom: 6px; left: 50%; width: 30px; height: calc(var(--h) * 7px + 8px); border-radius: 15px / 5px; z-index: 1;
  transform: translateX(calc(-50% + var(--x) * var(--spread, 1)));
  background: repeating-linear-gradient(to bottom, #f7c948 0 4px, #a86b06 4px 6px); box-shadow: 0 6px 10px rgba(0, 0, 0, .35); }
.of-stack::before { content: ""; position: absolute; left: 0; right: 0; top: -1px; height: 10px; border-radius: 50%; background: radial-gradient(circle at 40% 40%, #fff1b8, #f0b83a 60%, #b87708); }
.of-total { display: inline-flex; align-items: center; gap: .18em; font-size: clamp(24px, 7vw, 30px); font-weight: 900; line-height: 1; letter-spacing: -.01em; color: #fff; }
.offer.hero .of-total { font-size: clamp(30px, 9vw, 38px); }
.of-total .coin-mark { width: .8em; height: .8em; }
.of-detail { font-size: 12px; font-weight: 800; color: rgba(255, 255, 255, .62); text-align: center; }
.of-detail em { font-style: normal; color: #4ade80; }
/* The price is on the button, at the bottom of every card, the way a game shop asks you to pay. */
.of-buy { align-self: end; margin-top: 4px; width: 100%; padding: 10px 8px; border-radius: 14px; font-size: 18px; font-weight: 900; line-height: 1;
  color: #2a1a00; background: linear-gradient(180deg, #ffe08a, #f2b53a); box-shadow: 0 4px 0 #a86b06; }
.offer:active .of-buy { transform: translateY(2px); box-shadow: 0 2px 0 #a86b06; }
.shop-fine { margin: 18px 4px 0; text-align: center; font-size: 11px; font-weight: 600; color: var(--muted); opacity: .85; text-wrap: balance; }

@media (prefers-reduced-motion: reduce) { .slot .odds-tag { animation-duration: .2s; } }
/* No sideways page scroll on a phone, whatever a decoration does: the booster's aura (opacity 0 at rest) ran 2 px past
   a 320-px screen and let the whole page slide. */
html:has(body.app) { overflow-x: clip; }
/* ---------- the second chance, staged (public/app/angel.js) ----------
   A full-screen scene in the middle of the phone: a golden sky opens, rays turn behind an angel that comes down
   with its halo and its wings, feathers fall, and the round says what it gives back. Everything that moves is a
   transform or an opacity, so the page underneath is never laid out again while it plays. */
/* One cell the size of the screen: the rays (up to 620 px) are wider than a phone, and an auto track would grow to
   fit them and push the whole scene off to the right. */
.angel { position: fixed; inset: 0; z-index: 90; display: grid; place-items: center; grid-template: "s" minmax(0, 1fr) / minmax(0, 1fr);
  padding: 24px; overflow: hidden; background: radial-gradient(120% 90% at 50% 38%, rgba(70, 52, 8, .9), rgba(8, 6, 2, .95) 62%, rgba(4, 3, 1, .98));
  animation: ang-in .28s ease-out both; -webkit-tap-highlight-color: transparent; }
.angel.leaving { animation: ang-out .26s ease-in both; }
.angel > * { grid-area: s; }
@keyframes ang-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes ang-out { to { opacity: 0; } }

.ang-sky { width: min(78vw, 340px); aspect-ratio: 1; border-radius: 50%; justify-self: center; align-self: center;
  background: radial-gradient(circle, rgba(255, 246, 214, .95), rgba(255, 216, 74, .55) 38%, rgba(255, 176, 32, 0) 70%);
  transform: scale(.2); animation: ang-halo 1.1s cubic-bezier(.2, .8, .3, 1) both; }
@keyframes ang-halo { 0% { transform: scale(.2); opacity: 0; } 55% { transform: scale(1.06); opacity: 1; } 100% { transform: scale(1); opacity: .92; } }
.ang-rays { width: min(150vw, 620px); aspect-ratio: 1; justify-self: center; align-self: center; opacity: 0;
  background: repeating-conic-gradient(from 0deg, rgba(255, 232, 150, .22) 0deg 7deg, transparent 7deg 20deg);
  mask: radial-gradient(circle, #000 12%, rgba(0, 0, 0, .35) 45%, transparent 72%);
  animation: ang-rays 2.6s linear both; }
@keyframes ang-rays { 0% { opacity: 0; transform: rotate(0deg) scale(.6); } 30% { opacity: 1; } 100% { opacity: .55; transform: rotate(38deg) scale(1); } }

.ang-feathers { width: 100%; height: 100%; pointer-events: none; }
.ang-feather { position: absolute; top: -8%; left: var(--x); width: 10px; height: 16px; border-radius: 60% 60% 70% 70% / 80% 80% 40% 40%;
  background: linear-gradient(180deg, #fffaf0, #ffe6a6); opacity: 0; transform: scale(var(--s));
  animation: ang-fall 2.4s cubic-bezier(.35, .1, .5, 1) var(--d) both; }
@keyframes ang-fall {
  0% { opacity: 0; transform: translate3d(0, 0, 0) rotate(-20deg) scale(var(--s)); }
  12% { opacity: .95; }
  100% { opacity: 0; transform: translate3d(22px, 105vh, 0) rotate(260deg) scale(var(--s)); }
}

.ang-stage { justify-self: center; max-width: 100%; text-align: center; color: #fff8e6; animation: ang-rise .5s cubic-bezier(.2, .8, .3, 1) both; }
@keyframes ang-rise { from { opacity: 0; transform: translate3d(0, 14px, 0); } to { opacity: 1; transform: none; } }
.ang-figure { position: relative; display: block; width: 132px; height: 132px; margin: 0 auto 10px;
  animation: ang-descend .9s cubic-bezier(.2, .9, .25, 1) both, ang-float 2.6s ease-in-out .9s infinite; }
@keyframes ang-descend { from { opacity: 0; transform: translate3d(0, -46vh, 0) scale(.7); } to { opacity: 1; transform: none; } }
@keyframes ang-float { 0%, 100% { transform: translate3d(0, 0, 0); } 50% { transform: translate3d(0, -7px, 0); } }
.ang-face { position: absolute; inset: 0; display: grid; place-items: center; font-size: 74px; line-height: 1;
  filter: drop-shadow(0 6px 16px rgba(255, 190, 60, .55)); }
.ang-ring { position: absolute; top: 2px; left: 50%; width: 62px; height: 18px; margin-left: -31px; border-radius: 50%;
  border: 4px solid #ffe07a; box-shadow: 0 0 16px rgba(255, 224, 122, .9); animation: ang-ring 1.8s ease-in-out infinite; }
@keyframes ang-ring { 0%, 100% { transform: scaleX(1); opacity: .95; } 50% { transform: scaleX(.88); opacity: 1; } }
.ang-wing { position: absolute; top: 34px; width: 56px; height: 62px; background: linear-gradient(160deg, #fffdf6, #ffe9b8);
  border-radius: 70% 20% 60% 30% / 70% 40% 60% 30%; box-shadow: 0 0 22px rgba(255, 238, 190, .6); }
.ang-wing.l { left: -34px; transform-origin: 100% 50%; animation: ang-flap 1.1s ease-in-out infinite; }
/* The right wing is drawn mirrored by its corners, not by scaleX(-1): flipped around its left edge it folded back
   over the face. */
.ang-wing.r { right: -34px; transform-origin: 0 50%; border-radius: 20% 70% 30% 60% / 40% 70% 30% 60%; animation: ang-flap-r 1.1s ease-in-out infinite; }
@keyframes ang-flap { 0%, 100% { transform: rotate(-8deg) scale(1); } 50% { transform: rotate(10deg) scale(.92); } }
@keyframes ang-flap-r { 0%, 100% { transform: rotate(8deg) scale(1); } 50% { transform: rotate(-10deg) scale(.92); } }

.ang-title { margin: 6px 0 0; font-size: 30px; font-weight: 900; letter-spacing: -.5px;
  background: linear-gradient(180deg, #fff6d6, #ffd84a 55%, #f2b53a); -webkit-background-clip: text; background-clip: text; color: transparent;
  animation: ang-pop .5s cubic-bezier(.2, 1.4, .4, 1) .25s both; }
@keyframes ang-pop { from { opacity: 0; transform: scale(.82); } to { opacity: 1; transform: none; } }
.ang-detail { margin: 8px 0 0; font-size: 16px; font-weight: 800; color: #fff3cf; text-wrap: balance;
  animation: ang-rise .45s ease-out .4s both; }
.ang-skip { align-self: end; justify-self: center; margin: 0 0 12px; font-size: 12px; font-weight: 700; color: rgba(255, 244, 214, .7);
  animation: ang-rise .4s ease-out .9s both; }
.angel.giving .ang-skip { display: none; }
/* The offer says it all: the title and what came back fade out rather than sit half under the card. */
.angel.giving .ang-title, .angel.giving .ang-detail { animation: ang-fade .25s ease-in both; }
@keyframes ang-fade { to { opacity: 0; } }

/* Once the angel has landed, the offer rises under it: what the gift was, the player's own code, the way to EXPERT. */
.angel.giving .ang-stage { animation: ang-lift .4s cubic-bezier(.2, .8, .3, 1) both; }
@keyframes ang-lift { from { transform: none; } to { transform: translate3d(0, -26vh, 0) scale(.82); } }
.ang-gift { justify-self: center; align-self: end; width: min(100%, 360px); margin-bottom: 4vh; padding: 16px;
  border-radius: 20px; text-align: center; background: rgba(18, 14, 6, .97); border: 1px solid rgba(255, 216, 74, .45);
  box-shadow: 0 18px 40px rgba(0, 0, 0, .5); animation: ang-rise .45s cubic-bezier(.2, .8, .3, 1) both; }
.ang-gift-lead { margin: 0; font-size: 17px; font-weight: 900; color: #fff3cf; text-wrap: balance; }
.ang-gift-sell { margin: 6px 0 0; font-size: 14px; font-weight: 700; color: rgba(255, 243, 207, .82); text-wrap: balance; }
.ang-code { display: grid; gap: 2px; margin: 12px 0; padding: 10px; border-radius: 14px;
  background: linear-gradient(180deg, rgba(255, 216, 74, .16), rgba(255, 216, 74, .06)); border: 1px dashed rgba(255, 216, 74, .6); }
.ang-code small { font-size: 11px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: rgba(255, 243, 207, .75); }
.ang-code b { font-size: 28px; font-weight: 900; letter-spacing: .12em; color: #ffd84a; }
.ang-code span { font-size: 12px; font-weight: 700; color: rgba(255, 243, 207, .8); }
.ang-cta { display: block; text-decoration: none; white-space: nowrap; font-size: clamp(16px, 5vw, 20px); }
.ang-later { margin-top: 8px; color: rgba(255, 243, 207, .7); }

/* Less movement asked for: the same scene, without the flight, the flapping or the falling feathers. */
@media (prefers-reduced-motion: reduce) {
  .angel, .angel * { animation-duration: .2s !important; animation-iteration-count: 1 !important; }
  .ang-figure, .ang-wing, .ang-ring, .ang-rays { animation: none; }
  .angel.giving .ang-stage { transform: translate3d(0, -26vh, 0) scale(.82); animation: none; }
}

/* The code on the EXPERT page: the same dashed gold ticket, in the page's own colours. */
.xp-promo { margin: 0 12px 12px; padding: 12px; border-radius: 16px; text-align: center;
  background: linear-gradient(180deg, rgba(255, 216, 74, .16), rgba(255, 216, 74, .06)); border: 1px dashed rgba(242, 181, 58, .7); }
.xp-promo small { display: block; font-size: 11px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.xp-promo b { display: block; margin: 2px 0; font-size: 26px; font-weight: 900; letter-spacing: .12em; color: var(--gold); }
.xp-promo span { display: block; font-size: 12px; font-weight: 700; color: var(--muted); }

/* "Il manque ton meme ?": the encart under the boosters, its form, and the answers the team gave. */
.sugg { display: grid; gap: 12px; box-sizing: border-box; width: 100%; max-width: 420px; margin: 14px auto 0; padding: 16px; border-radius: 18px;
  background: var(--surface); border: 1px dashed var(--line); }
.sugg h3 { margin: 0 0 4px; font-size: 17px; }
.sugg p { margin: 0; font-weight: 700; font-size: 14px; color: var(--muted); }
.sugg-do { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.sugg-do .btn { width: auto; margin: 0; font-size: 16px; padding: 12px 18px; }
.sugg-form { display: grid; gap: 12px; margin: 14px 0 16px; text-align: left; }
.sugg-form label { display: grid; gap: 6px; font-weight: 800; font-size: 14px; }
.sugg-form input, .sugg-form textarea { font: inherit; font-weight: 700; color: var(--text); background: var(--input); border: 2px solid var(--line);
  border-radius: 12px; padding: 10px 12px; min-width: 0; }
.sugg-form textarea { resize: vertical; }
.sugg-packs { display: flex; gap: 16px; flex-wrap: wrap; margin: 0; padding: 12px; border: 1px solid var(--line); border-radius: 14px; }
.sugg-packs legend { padding: 0 6px; font-weight: 800; font-size: 14px; }
.sugg-packs label { display: flex; align-items: center; gap: 6px; font-weight: 800; font-size: 15px; }
.sugg-err { margin: 0; font-weight: 800; font-size: 14px; color: #e0457b; }
.sugg-done { display: grid; gap: 8px; justify-items: center; padding: 18px 0 8px; text-align: center; }
.sugg-done-ico { font-size: 42px; line-height: 1; }
.sugg-done h3 { margin: 0; font-size: 19px; }
.sugg-done .btn { width: auto; margin-top: 8px; }
.sugg-list { display: grid; gap: 10px; margin: 12px 0 0; padding: 0; list-style: none; }
.sugg-row { display: grid; gap: 6px; padding: 14px; border-radius: 16px; background: var(--surface); border: 1px solid var(--line); text-align: left; }
.sugg-row-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.sugg-row p { margin: 0; }
.sugg-why { font-weight: 700; font-size: 14px; }
.sugg-pill { flex: none; padding: 4px 10px; border-radius: 999px; background: var(--surface-2); color: var(--muted); font-weight: 800; font-size: 12px; }
.sugg-row.st-accepted .sugg-pill, .sugg-row.st-done .sugg-pill { background: rgba(29, 179, 107, .16); color: #1db36b; }
.sugg-answer { padding: 10px 12px; border-radius: 12px; background: var(--surface-2); font-weight: 700; font-size: 14px; }
.sugg-answer b { display: block; font-size: 12px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.sugg-row.st-answered .sugg-pill { background: rgba(29, 179, 107, .16); color: #1db36b; }
.sugg-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
.sugg-actions .btn { width: auto; margin: 0; }
.fb-kinds { display: grid; gap: 8px; margin: 0; padding: 12px; border: 1px solid var(--line); border-radius: 14px; }
.fb-kinds legend { padding: 0 6px; font-weight: 800; font-size: 14px; }
.fb-kinds label { display: flex; align-items: center; gap: 8px; font-weight: 800; font-size: 15px; }
.fb-text { white-space: pre-line; overflow-wrap: anywhere; }
.fb-mine h2 { margin: 0; }
@media (min-width: 900px) { .view .sugg { max-width: 720px; } }

/* The Propositions tab of the admin panel: the pending count on the tab, the search, the answer buttons. */
.adm-tabs button i { display: inline-grid; place-items: center; min-width: 18px; height: 18px; margin-left: 6px; padding: 0 5px; border-radius: 999px;
  background: #e0457b; color: #fff; font-size: 11px; font-style: normal; font-weight: 900; }
.adm-tabs button i[hidden] { display: none; }
.adm-sug-filters { margin: 0 0 10px; }
.adm-sug-search { width: 100%; box-sizing: border-box; margin: 0 0 12px; }
.adm-sug small { display: block; color: var(--muted); font-weight: 800; font-size: 12px; }
.adm-sug-do { min-width: 200px; }
.adm-table td.adm-fb-msg { min-width: 240px; max-width: 380px; white-space: pre-line; overflow-wrap: anywhere; }
.adm-fb-msg small { display: block; white-space: normal; margin-top: 4px; }
.adm-sug-note { width: 100%; box-sizing: border-box; margin-bottom: 6px; font-size: 13px; padding: 6px 8px; }
.adm-sug-do span { display: flex; gap: 6px; flex-wrap: wrap; }
.adm-sug-do button { border: 1px solid var(--line); background: var(--surface-2); color: var(--text); font: inherit; font-weight: 800; font-size: 12px;
  padding: 6px 10px; border-radius: 999px; cursor: pointer; }
.adm-sug-do button:disabled { opacity: .5; cursor: default; }
.adm-sug-pages { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
.adm-sug-pages button { border: 1px solid var(--line); background: var(--surface); color: var(--muted); font: inherit; font-weight: 800; font-size: 13px;
  padding: 6px 12px; border-radius: 999px; cursor: pointer; }
.adm-sug-pages button[aria-current] { background: var(--active-bg); color: var(--active-ink); border-color: transparent; }
/* « Il manque ton meme ? » : one light line above the packs, text only, no box. */
/* A hint, not a headline: it sat in a 120px band above the switcher on a computer (the landing page's section
   padding under it) and took 65px of a phone's height before the packs (Théo, 01/10/2026). It now hugs the top of
   the view and the switcher; the tap target keeps 32px. */
/* The achievements waiting, said on the home page: one row above everything else on the Packs page. */
.ach-home { display: flex; align-items: center; gap: 10px; max-width: 1100px; margin: 10px auto 0; padding: 10px 12px; box-sizing: border-box;
  border-radius: 16px; border: 2px solid var(--gold); background: var(--surface); color: var(--heading); text-decoration: none;
  box-shadow: 0 8px 20px rgba(0, 0, 0, .16); }
.ach-home:active { transform: scale(.99); }
.ach-home-ico { font-size: 22px; line-height: 1; }
.ach-home b { flex: 1; font-size: 15px; font-weight: 900; }
.ach-home-cta { flex: none; padding: 7px 14px; border-radius: 999px; font-size: 14px; font-weight: 900; background: var(--gold-grad); color: var(--on-gold); }

/* The same reminder while a game is played: small, in a corner ach-nudge.js checked is free of game buttons. It is
   the only fixed thing of the page that takes a tap, so it stays under the sheets (z-index 60) and over the board. */
.ach-nudge { position: fixed; z-index: 30; display: flex; align-items: center; gap: 4px; padding: 4px; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--gold); box-shadow: 0 8px 20px rgba(0, 0, 0, .3);
  animation: guide-in .3s ease-out; }
.ach-nudge-go { display: flex; align-items: center; gap: 6px; padding: 4px 6px; color: var(--heading); text-decoration: none; font-size: 13px; }
.ach-nudge-go b { font-weight: 900; }
.ach-nudge-ico { font-size: 16px; line-height: 1; }
.ach-nudge-cta { padding: 4px 10px; border-radius: 999px; font-weight: 900; background: var(--gold-grad); color: var(--on-gold); }
.ach-nudge-x { flex: none; width: 32px; height: 32px; border: 0; border-radius: 999px; background: var(--surface-2); color: var(--muted);
  font: inherit; font-size: 13px; line-height: 1; cursor: pointer; }
@media (prefers-reduced-motion: reduce) { .ach-nudge { animation: none; } }

.sugg-line { margin: -10px auto 2px; text-align: center; }
.sugg-line .sugg-open { font: inherit; font-size: 13px; font-weight: 700; color: var(--muted); opacity: .75; background: none; border: 0; padding: 7px 6px; min-height: 32px; cursor: pointer; }
.view > .sugg-line + section { padding-top: 0; }
@media (min-width: 900px) {
  .sugg-line { margin-top: -18px; }
  /* Under a guide banner the line keeps its distance from it, and stays nearer the switcher than the banner. */
  .guide + .view > .sugg-line { margin-top: -6px; }
}
.sugg-line .sugg-open u { text-underline-offset: 2px; }
@media (hover: hover) { .sugg-line .sugg-open:hover { opacity: 1; } }
/* The site's address under a card just pulled and under a card's page: a screenshot of either always carries it. */
.site-mark { margin: 6px 0 0; text-align: center; font-size: 13px; font-weight: 900; letter-spacing: .08em; color: var(--muted); opacity: .85; user-select: none; }
.site-mark::before { content: "✦ "; color: #f2b53a; }
.site-mark::after { content: " ✦"; color: #f2b53a; }
/* A 15-card EXPERT pack: fifteen 10-px dots pushed the « › » arrow off a phone. Past 8 cards the dots shrink and
   the row may give way; the arrows keep their size. */
.pack-open .pager { max-width: 100%; box-sizing: border-box; }
.pack-open .dots { min-width: 0; flex: 0 1 auto; }
.pack-open .dots:has(button:nth-child(9)) { gap: 4px; }
.pack-open .dots:has(button:nth-child(9)) button { width: 6px; height: 6px; }

/* Blocked cards: a lock beside each stake tile (a sibling button, so it never steals the selection tap) */
.stake-cell { position: relative; }
.stake-cell .stake-tile { width: 100%; box-sizing: border-box; }
/* The padlock: a small frosted chip in the card's corner, quiet on a free card, dark and plain on a blocked one. */
.stake-lock { position: absolute; z-index: 7; right: -6px; bottom: -8px; width: 44px; height: 44px; display: grid; place-items: center; border: 0; background: none; padding: 0; cursor: pointer; color: var(--muted); }
.stake-lock::before { content: ""; position: absolute; inset: 9px; border-radius: 999px; background: var(--surface); box-shadow: inset 0 0 0 1px var(--line); z-index: -1; transition: background .15s; }
.stake-lock .lock-ico { width: 14px; height: 14px; }
.stake-cell.blocked .stake-lock::before { background: #16171d; box-shadow: inset 0 0 0 1.5px #f2b53a; }
.stake-cell.blocked .stake-lock .lock-ico { opacity: 1; color: #f2b53a; }
@media (hover: hover) { .stake-lock:hover { color: var(--text); } }
.lock-ico { display: inline-block; width: 1em; height: 1em; vertical-align: -.12em; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.lock-ico circle { fill: currentColor; stroke: none; }
.stake-cell.blocked .stake-tile { opacity: .45; filter: grayscale(1); cursor: not-allowed; }
.coll-tile .lock-badge { display: none; position: absolute; z-index: 6; left: 8px; bottom: 8px; width: 26px; height: 26px; place-items: center; border-radius: 999px; background: #16171d; color: #f2b53a; box-shadow: inset 0 0 0 1.5px #f2b53a; pointer-events: none; }
.coll-tile .lock-badge .lock-ico { width: 14px; height: 14px; }
.coll-tile.blocked .lock-badge { display: grid; }
.cs-actions .block-toggle, .cs-actions .cs-blocked-why { grid-column: 1 / -1; }
.cs-blocked-why, .cs-blocked-note { margin: 0; }

/* "Choisis ta carte": one sticky bar of filters over a grid of light thumbnails */
.stake-bar { grid-template-columns: minmax(0, 1fr); position: sticky; top: 58px; z-index: 5; display: grid; gap: 6px; padding: 6px 0 8px; background: var(--page); border-bottom: 1px solid var(--line); }
.stake-search { box-sizing: border-box; width: 100%; min-height: 44px; }
.stake-top { display: flex; align-items: center; gap: 10px; }
.stake-top .stake-search { flex: 1; min-width: 0; width: auto; }
.stake-count { white-space: nowrap; font-weight: 800; font-size: 13px; color: var(--muted); }
.stake-sortrow { display: flex; gap: 6px; }
.stake-seg { flex: 1; min-width: 0; display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 2px; padding: 3px; border-radius: 14px; background: var(--surface-2); }
.stake-seg button { min-width: 0; min-height: 38px; padding: 0 2px; border: 0; border-radius: 11px; background: none; color: var(--muted); font: inherit; font-weight: 800; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer; touch-action: manipulation; }
.stake-seg button[aria-pressed="true"] { background: var(--active-bg); color: var(--active-ink); }
.stake-dir { flex: none; width: 44px; min-height: 44px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 14px; background: var(--active-bg); color: var(--active-ink); cursor: pointer; touch-action: manipulation; }
.stake-dir .dir-ico { transition: transform .18s; }
.stake-dir[data-desc="true"] .dir-ico { transform: rotate(180deg); }
/* Every filter stays in sight: one row per filter, led by its name, whose chips wrap instead of hiding off the edge. */
.stake-filters { display: grid; gap: 8px; margin: 8px 0 12px; padding: 10px; border-radius: 14px; background: var(--surface-2); }
.stake-flabel { align-self: center; margin-right: 2px; font-size: 11px; font-weight: 900; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }
.stake-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.stake-chips button { display: inline-flex; align-items: center; gap: 6px; min-height: 34px; padding: 0 11px; white-space: nowrap; border: 1px solid var(--line); border-radius: 999px; background: var(--surface); color: var(--text); font: inherit; font-weight: 800; font-size: 13px; cursor: pointer; touch-action: manipulation; }
.stake-chips button[aria-pressed="true"] { background: var(--active-bg); color: var(--active-ink); border-color: transparent; }
.s-rarity button:not([data-k="all"])::before { content: ""; flex: none; width: 9px; height: 9px; border-radius: 50%; background: var(--dot); }
.s-rarity [data-k="common"] { --dot: #7f8a86; } .s-rarity [data-k="rare"] { --dot: #2f7bff; } .s-rarity [data-k="epic"] { --dot: #8a3dff; }
.s-rarity [data-k="legendary"] { --dot: #e8950e; } .s-rarity [data-k="mythic"] { --dot: #16b8a0; } .s-rarity [data-k="shiny"] { --dot: #d7a93c; }
.s-rarity [data-k="fullart"] { --dot: conic-gradient(#ff5a5a, #ffd23f, #3fd97a, #2f7bff, #b04dff, #ff5a5a); }
.stake-ffoot { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.stake-ffoot:not(:has(> :not([hidden]))) { display: none; }
.stake-hide { display: inline-flex; align-items: center; gap: 10px; box-sizing: border-box; min-height: 40px; padding: 0 14px 0 10px; border-radius: 999px; border: 1px solid var(--line); background: var(--surface); color: var(--text); font: inherit; font-weight: 800; font-size: 13px; cursor: pointer; touch-action: manipulation; }
.stake-hide .sw { position: relative; flex: none; width: 34px; height: 20px; border-radius: 999px; background: var(--line); transition: background .15s; }
.stake-hide .sw::after { content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.3); transition: translate .15s; }
.stake-hide[aria-pressed="true"] .sw { background: var(--active-bg); }
.stake-hide[aria-pressed="true"] .sw::after { translate: 14px 0; }
.stake-reset { margin-left: auto; min-height: 40px; padding: 0 12px; border: 0; background: none; color: var(--text); font: inherit; font-weight: 800; font-size: 14px; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.stake-filters [hidden] { display: none; }
.stake-up { flex: none; display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 0 14px; border: 0; border-radius: 12px; background: var(--active-bg); color: var(--active-ink); font: inherit; font-weight: 800; font-size: 13px; cursor: pointer; touch-action: manipulation; }
.stake-up[hidden] { display: none; }
.stake-up b { min-width: 20px; height: 20px; display: grid; place-items: center; padding: 0 5px; box-sizing: border-box; border-radius: 999px; background: var(--active-ink); color: var(--active-bg); font-size: 12px; }
.stake-up b[hidden] { display: none; }
.stake-top:not(.coll-top):has(.stake-up:not([hidden])) .stake-count { display: none; }
/* With room to spare, the names line up in one column. */
@media (min-width: 520px) { .stake-flabel { width: 84px; } }
.stake-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); gap: 12px 10px; }
.stake-grid > p { grid-column: 1 / -1; }
.stake-cell { position: relative; content-visibility: auto; contain-intrinsic-size: 88px 140px; }
.stake-tile { position: relative; display: grid; gap: 4px; width: 100%; box-sizing: border-box; padding: 3px; border: 0; border-radius: 14px; background: none; color: inherit; cursor: pointer; touch-action: manipulation; }
@media (hover: hover) { .stake-tile:hover { background: var(--surface-2); } }
.stake-tile.on { box-shadow: 0 0 0 3px var(--active-bg); }
.stake-thumb { position: relative; display: block; aspect-ratio: 1; overflow: hidden; border: 3px solid var(--c); border-radius: 10px; background: var(--surface-2); }
.stake-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.stake-thumb b { position: absolute; inset: auto 0 0; padding: 12px 4px 3px; background: linear-gradient(transparent, rgba(0, 0, 0, .78)); color: #fff; font-size: 11px; line-height: 1.15; text-align: left; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.stake-thumb i { position: absolute; top: 3px; right: 3px; padding: 1px 5px; border-radius: 999px; background: var(--active-bg); color: var(--active-ink); font-size: 10px; font-style: normal; font-weight: 900; }
.stake-tile .count { position: absolute; top: 6px; right: 6px; z-index: 5; background: var(--active-bg); color: var(--active-ink); font-weight: 900; font-size: 12px; padding: 2px 8px; border-radius: 999px; }
.stake-val { display: inline-flex; align-items: center; justify-content: center; gap: 4px; min-height: 24px; font-weight: 900; font-size: 14px; color: var(--text); }
.stake-lock { position: absolute; z-index: 7; top: 0; left: 0; width: 44px; height: 44px; display: grid; place-items: center; border: 0; background: none; padding: 0; font-size: 16px; cursor: pointer; touch-action: manipulation; }
.stake-lock::before { content: ""; position: absolute; inset: 8px; border-radius: 999px; background: var(--surface-2); z-index: -1; }
.stake-cell.blocked .stake-tile { opacity: .45; filter: grayscale(1); cursor: not-allowed; }
.stake-more { height: 1px; }
/* ---------- looking closer at a card ---------- */
/* The magnifier sits in the bottom-left of the art window, clear of the favourite star (top right). */
.zoom-btn { position: absolute; z-index: 7; left: 9%; top: 56%; width: 28px; height: 28px; padding: 0; border: 0; border-radius: 50%; cursor: zoom-in; display: grid; place-items: center; background: rgba(12, 16, 28, .62); box-shadow: 0 0 0 1px rgba(255, 255, 255, .35); opacity: .88; transition: opacity .15s, scale .15s; }
.zoom-btn::before { content: ""; position: absolute; inset: -8px; }
.zoom-btn svg { width: 62%; height: 62%; fill: none; stroke: #fff; stroke-width: 2.2; stroke-linecap: round; }
.zoom-btn:focus { outline: none; }
.zoom-btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
@media (hover: hover) { .zoom-btn:hover { opacity: 1; scale: 1.12; } }

/* Full-screen view: the card as large as the screen allows, proportions kept, the site mark under it. */
.zoom-view { position: fixed; inset: 0; z-index: 80; display: flex; flex-direction: column; justify-content: center; align-items: center; padding: 14px 10px calc(12px + env(safe-area-inset-bottom)); background: rgba(6, 8, 14, .94); overscroll-behavior: contain; touch-action: none; animation: zoom-in .18s ease-out; }
@keyframes zoom-in { from { opacity: 0; } }
.zoom-x { position: absolute; z-index: 2; top: calc(10px + env(safe-area-inset-top)); right: 12px; width: 44px; height: 44px; border-radius: 50%; border: 0; background: rgba(255, 255, 255, .14); color: #fff; font-size: 20px; font-weight: 900; cursor: pointer; }
.zoom-stage { min-height: 0; display: grid; place-items: center; }
.zoom-pan { display: grid; place-items: center; transform-origin: center; will-change: transform; }
.zoom-pan.settle { transition: transform .2s ease-out; }
/* .7466 is the frame's real width/height (63/88 plus its border): the width is whichever of the screen's two limits bites first. */
.zoom-view .card { width: min(94vw, calc((100dvh - 96px) * .7466), 760px); max-width: none; }
.zoom-view .card__rotator { touch-action: none; cursor: zoom-out; }
.zoom-view .site-mark { margin: 8px 0 0; color: #d9dde6; font-size: 14px; }
@media (prefers-reduced-motion: reduce) { .zoom-view { animation: none; } .zoom-pan.settle { transition: none; } }

/* Per place: the button follows the card's width like the favourite star does (cqw of the container). */
.zoom-btn { width: 28px; height: 28px; }
.slot .zoom-btn { left: 10cqw; top: 60cqw; }
.coll-tile .zoom-btn { --w: min(100cqw, 170px); left: calc((100cqw - var(--w)) / 2 + var(--w) * .1); top: calc(var(--w) * .6); }
/* Room above the card: tilted, it rises past its box and slid under the sticky sheet header (top edge cut). */
.sheet-visual { position: relative; container-type: inline-size; padding-top: 16px; }
/* On the card, bottom-left of its art: the sheet is wider than the card (260 px at most), so place it from the card. */
.sheet-visual .zoom-btn { --w: min(100cqw, 260px); left: calc((100cqw - var(--w)) / 2 + var(--w) * .1); top: calc(var(--w) * .6); }
.stake-cell { container-type: inline-size; }
/* Under the count badge, clear of the lock (top left) and the name (bottom). */
.stake-cell .zoom-btn { left: auto; right: 8px; top: 38px; }
.stake-cell.blocked .zoom-btn { display: none; }
.coll-tile.missing .zoom-btn { display: none; }

/* A computer: the tile under the pointer grows by a transform only (no layout moves) and rises above its neighbours.
   The tile is scaled, not .tile-open, whose content-visibility would clip the overflow. */
@media (hover: hover) and (pointer: fine) {
  .coll-tile:not(.missing), .stake-cell { transition: scale .2s ease-out; }
  .coll-tile:not(.missing):hover { scale: 1.4; z-index: 12; }
  .stake-cell:hover { scale: 1.35; z-index: 12; }
}
@media (prefers-reduced-motion: reduce) { .coll-tile, .stake-cell { transition: none; } }
/* The Memes FR pack opens with its own colours: gold is EXPERT's alone. */
.btn.fr-btn { background: linear-gradient(135deg, #2b4fd8, #1f3fbf 55%, #16308f); color: #fff; box-shadow: 0 10px 24px rgba(31, 63, 191, .35); }
.btn.fr-btn:disabled { opacity: .55; }

/* The padlock sits beside the price under the card, never over its name or its art. */
.stake-cell { position: relative; }
/* « Ouvrir un pack → » in the small card slot of the games: one line, the arrow never alone under the words. */
.lt-open { white-space: nowrap; }
/* The sort direction says itself in words, the arrow beside them. */
.stake-dir { width: auto; grid-auto-flow: column; gap: 6px; padding: 0 12px; font: inherit; font-weight: 800; font-size: 13px; white-space: nowrap; }
@media (max-width: 400px) { .stake-dir .dir-word { display: none; } .stake-dir { padding: 0; width: 44px; } }

/* The EXPERT pack of the day, in the tile of the pack shown: its state (ready, or when it is back) is the button's own text. */
.pack-stage .open-expert { margin-top: 10px; white-space: normal; line-height: 1.2; min-height: 52px; font-variant-numeric: tabular-nums; }
.pack-stage .open-expert:disabled { opacity: .6; }
/* Not EXPERT: one quiet line to the offer, never a block. */
.xp-link { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; margin-top: 6px; padding: 0 8px; font-size: 14px; font-weight: 800; color: var(--muted); text-decoration: underline; text-underline-offset: 3px; }

/* « Tu es EXPERT » : a compact gold pill, not a band across the whole page on a computer. */
@media (min-width: 700px) {
  .xp-banner.on { width: fit-content; max-width: 100%; margin-inline: auto; padding: 10px 22px; min-height: 44px; border-radius: 999px; gap: 10px; }
}

/* ---------- shop: packs bought outright, in the pack the player picks ---------- */
.shop-sec { display: grid; gap: 4px; margin: 22px 0 0; text-align: center; }
.shop-sec h2 { margin: 0; font-size: clamp(20px, 5.5vw, 24px); color: var(--heading); }
.shop-sec .shop-what { margin: 0 auto; }
.shop-packs .pack-switch { margin-top: 14px; }
.pk-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; width: 100%; max-width: 440px; margin: 0 auto; }
.pk-offer { min-height: 220px; }
/* The sachet is the one of the pack chosen above, so the card shows what it sells. */
.pk-pile { display: flex; align-items: flex-end; justify-content: center; height: 108px; }
.pk-pile i { width: 62px; aspect-ratio: 63 / 88; border-radius: 6px; background: url(/pack-front.webp?v=7cc6581117) center / 100% 100% no-repeat; box-shadow: 0 6px 12px rgba(0, 0, 0, .4); }
.shop-packs.fr .pk-pile i { background-image: url(/pack-front-fr.webp?v=194a1166ad); }
.pk-pile i + i { margin-left: -44px; }
.pk-pile i:nth-child(odd):not(:only-child) { translate: 0 -6px; }
.shop-got { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 12px auto 0; max-width: 440px; padding: 10px 12px; border-radius: 14px; background: #14351f; border: 1.5px solid #22c55e; color: #fff; font-weight: 800; font-size: 14px; text-decoration: none; }
.shop-got b { flex: none; padding: 7px 12px; border-radius: 999px; background: #22c55e; color: #052e14; font-size: 13px; }
/* The EXPERT pack still to come: one small line, gold text on no fill, the timer in tabular figures. */
.pack-stage .open-expert.waiting { min-height: 36px; margin-top: 8px; padding: 6px 14px; width: auto; justify-self: center; display: inline-flex; align-items: center; gap: 6px;
  background: none; box-shadow: none; border: 1.5px solid rgba(242, 181, 58, .55); border-radius: 999px; color: #b07a12; font-size: 14px; font-weight: 800; opacity: 1; white-space: nowrap; }
:root[data-theme="dark"] .pack-stage .open-expert.waiting { color: #f2c35a; }
/* The glint follows the outline of the sachet it sweeps. */
.booster.fr::before { -webkit-mask-image: url(/pack-front-fr.webp?v=194a1166ad); mask-image: url(/pack-front-fr.webp?v=194a1166ad); }

/* The Funnel tab of the admin panel: one bar per step, all measured against the widest one. */
.adm-fun { display: grid; gap: 16px; }
.adm-fun h3 { margin: 0; }
.adm-fun-step { display: grid; gap: 6px; }
.adm-fun-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 10px; }
.adm-fun-head b { font-size: 30px; line-height: 1; }
.adm-fun-head span { font-weight: 800; }
.adm-fun-head em { margin-left: auto; font-style: normal; font-size: 12px; font-weight: 800; color: var(--muted); }
.adm-fun-bar { height: 14px; border-radius: 999px; background: var(--line); overflow: hidden; }
.adm-fun-bar i { display: block; height: 100%; border-radius: 999px; background: linear-gradient(90deg, #6c8cff, #1db36b); }
.adm-fun-step > small { color: var(--muted); font-weight: 700; font-size: 13px; }
.adm-fun-split { display: flex; gap: 4px; }
.adm-fun-split > span { min-width: max-content; padding: 4px 8px; border-radius: 8px; background: var(--line); }
.adm-fun-split > span + span { background: rgba(108, 140, 255, .18); }
.adm-fun-err { color: var(--muted); font-weight: 700; padding-left: 10px; }
.adm-fun-badge { display: inline-block; margin-left: 6px; padding: 2px 8px; border-radius: 999px; background: #e8590c; color: #fff; font-size: 11px; font-weight: 900; text-transform: uppercase; letter-spacing: .04em; vertical-align: middle; }

/* The guide: one banner above the page naming the next reward of the first session (see renderGuide). It sits in
   the same column as .view, so its edges line up with the page under it on a phone and beside the sidebar. */
.guide { display: flex; flex-wrap: wrap; align-items: stretch; gap: 8px; max-width: 1100px; margin: 12px auto -6px; padding: 0 16px; box-sizing: border-box; animation: guide-in .35s ease-out; }
/* Neutral like the page's own cards: the only gold is the button, so it never competes with a gold action below. */
.guide-go { flex: 1; display: flex; align-items: center; gap: 12px; min-height: 48px; padding: 10px 12px 10px 16px; border-radius: 16px; text-decoration: none;
  color: var(--text); background: var(--surface); border: 1px solid var(--line); }
.guide-go:active { transform: scale(.985); }
:is(.view, .sheet, body) .guide-text { flex: 1; font-weight: 800; font-size: 14.5px; line-height: 1.3; text-wrap: balance; }
.guide-cta { flex: none; font-weight: 900; font-size: 14px; background: var(--gold-grad); color: var(--on-gold); padding: 8px 14px; border-radius: 999px; white-space: nowrap; }
.guide-x { flex: none; width: 44px; border: 0; border-radius: 12px; background: var(--surface-2); color: var(--muted); font: inherit; font-size: 20px; line-height: 1; cursor: pointer; }
/* The reminder of the achievements when no corner of a game was free: a second line of the same banner, never a
   floating pill over it (Théo, 02/10/2026). Full width, so it reads as one banner saying two things. */
.ach-nudge-line { flex: 1 1 100%; display: flex; align-items: center; gap: 10px; min-height: 44px; padding: 8px 10px 8px 14px;
  border-radius: 16px; text-decoration: none; color: var(--text); background: var(--surface); border: 1px solid var(--line); }
.ach-nudge-line b { flex: 1; font-weight: 800; font-size: 14px; line-height: 1.25; }
/* Narrow phones: the text gets the whole width and the button drops under it, so the banner stays two short rows. */
@media (max-width: 420px) {
  .guide { gap: 6px; padding: 0 12px; }
  .guide-go { flex-wrap: wrap; row-gap: 6px; column-gap: 10px; padding: 9px 10px 9px 14px; }
  :is(.view, .sheet, body) .guide-text { flex: 1 1 100%; font-size: 14px; line-height: 1.25; }
  .guide-cta { padding: 6px 12px; font-size: 13.5px; }
}
@keyframes guide-in { from { opacity: 0; transform: translateY(-6px); } }
@media (prefers-reduced-motion: reduce) { .guide { animation: none; } }
@media (min-width: 900px) {
  .guide { margin: 24px 0 -14px max(250px, calc((100vw - 1100px) / 2 + 125px)); padding: 0 32px; }
}

/* Admin « Visiteurs »: each person's journey, grouped by hour/day/week/month. */
.adm-vis-bar-top { display: flex; flex-wrap: wrap; gap: 0 16px; }
.adm-vis-bar { cursor: pointer; }
.adm-vis-bar:hover rect:nth-child(2), .adm-vis-bar.adm-vis-on rect:nth-child(2) { fill: var(--ink, #fff); opacity: .55; }
.adm-table tr.adm-vis-on > * { background: var(--active-bg); color: var(--active-ink); }
.adm-vis-list-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin-bottom: 8px; }
.adm-vis-list-head h3 { margin: 0; flex: 1 1 auto; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.adm-vis-list-head .adm-vis-search { flex: 1 1 260px; margin: 0; }
.adm-vis-list-head .adm-sug-filters { margin: 0; }
.adm-vis-path { max-width: 260px; overflow-wrap: anywhere; }
.adm-table td small, .adm-table th small { display: block; color: var(--muted); font-weight: 600; font-size: 11px; }
.adm-vis-sheet code, .adm-table code { font-size: 12px; }
.sheet-card:has(.adm-vis-sheet) { width: min(1040px, 100%); }
.adm-vis-sheet { display: grid; gap: 14px; min-width: 0; }
.adm-vis-sheet > * { min-width: 0; }
.adm-vis-sheet .adm-table td small[title] { white-space: normal; max-width: 280px; overflow-wrap: anywhere; }
.adm-vis-session { border-top: 1px solid var(--line); padding: 8px 0; }
.adm-vis-session summary { cursor: pointer; font-size: 13px; line-height: 1.5; }
.adm-vis-session ol { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 2px; }
.adm-vis-ev { display: grid; grid-template-columns: 70px 64px 1fr; gap: 8px; align-items: baseline; font-size: 13px; padding: 3px 0; }
.adm-vis-ev time { color: var(--muted); font-variant-numeric: tabular-nums; }
.adm-vis-ev b { overflow-wrap: anywhere; }
.adm-vis-ev small { display: block; color: var(--muted); font-size: 11px; overflow-wrap: anywhere; }
.adm-vis-kind { font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; border-radius: 6px; padding: 1px 4px; text-align: center; background: var(--surface); border: 1px solid var(--line); }
.adm-vis-click .adm-vis-kind { background: #1db36b22; border-color: #1db36b66; }
.adm-vis-moved { color: #d98a00 !important; }
.adm-vis-error .adm-vis-kind, .adm-vis-api_error .adm-vis-kind, .adm-vis-rage .adm-vis-kind { background: #e5484d22; border-color: #e5484d66; }
.adm-vis-action .adm-vis-kind, .adm-vis-submit .adm-vis-kind { background: #3e8bff22; border-color: #3e8bff66; }
.adm-vis-scroll, .adm-vis-leave, .adm-vis-hidden, .adm-vis-visible { opacity: .72; }
.adm-vis-status { display: inline-block; font-size: 11px; font-weight: 800; border-radius: 6px; padding: 0 5px; background: var(--surface); border: 1px solid var(--line); }
.adm-vis-status.bad { color: #e5484d; border-color: #e5484d66; background: #e5484d14; }

/* ---------- guidance: claim → open → play, said by the banner and by the wizard's bubble ---------- */
/* Nothing marks a tab: a ring or an arrow on an icon says "press here" without saying what for (Théo,
   02/10/2026). What has to be said is written, in the banner above the view or in the bubble. */
@keyframes guided-pulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(242,181,58,0); } 50% { box-shadow: 0 0 0 3px rgba(242,181,58,.55); } }

/* The wizard's bubble: it floats over the page at coordinates coach.js computes, and it lets every tap through
   except on itself, so the tap that dismisses it also presses the button it points at. */
.coach { position: fixed; z-index: 60; max-width: min(300px, calc(100vw - 16px)); display: grid; gap: 8px; padding: 12px 14px;
  border-radius: 16px; background: var(--surface); border: 2px solid var(--gold); color: var(--heading);
  box-shadow: 0 16px 38px rgba(0, 0, 0, .34); animation: guide-in .3s ease-out; }
.coach-text { margin: 0; font-size: 15px; font-weight: 800; line-height: 1.3; }
.coach-ok { justify-self: end; min-height: 36px; border: 0; border-radius: 999px; padding: 6px 14px; font: inherit; font-size: 14px; font-weight: 900;
  background: var(--gold-grad); color: var(--on-gold); cursor: pointer; }
/* The arrow points at the button: down when the bubble is above it, up when it had to go under. */
.coach::after { content: ""; position: absolute; left: var(--coach-arrow, 50%); margin-left: -7px; width: 0; height: 0; border: 7px solid transparent; }
.coach:not(.coach-under)::after { top: 100%; border-top-color: var(--gold); }
.coach-under::after { bottom: 100%; border-bottom-color: var(--gold); }
/* The button being pointed at, lit without moving: an outline, never a transform, so its box stays where the
   bubble and the tests expect it. */
.coach-on { position: relative; z-index: 2; outline: 3px solid var(--gold); outline-offset: 3px; animation: guided-pulse 1.6s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .coach { animation: none; } .coach-on { animation: none; } }
/* Once every pack is open, the next step is a game: gold and first, "open another" steps back beside it.
   Same token pair as the other primary CTAs (.btn.expert-btn, .guide-cta): --gold-grad with --on-gold, so
   dark theme reads dark ink on gold and light theme reads white on orange - never dark ink on orange. */
.pack-open .play-next { position: relative; overflow: hidden; color: var(--on-gold); text-shadow: none;
  background: var(--gold-grad); box-shadow: 0 10px 24px rgba(242,181,58,.35);
  margin-top: 16px; width: 100%; font-size: 17px; animation: again-in .35s ease-out; display: flex; flex-direction: column; align-items: center; gap: 2px; height: auto; line-height: 1.2; padding-block: 10px; white-space: normal; text-decoration: none; }
.pack-open .play-next::after { content: ""; position: absolute; inset: 0; background: linear-gradient(100deg, transparent 30%, rgba(255,255,255,.5) 50%, transparent 70%); transform: translateX(-120%); animation: rf-sweep 3.6s ease-in-out 1s infinite; pointer-events: none; }
.pack-open .play-next:active { transform: translateY(1px); box-shadow: 0 5px 14px rgba(242,181,58,.3); }
.pack-open .play-next small { font-size: 13px; font-weight: 800; opacity: .8; }
.pack-open .play-next[hidden] { display: none; }
.pack-dock.out .open-again { margin-top: 10px; }
@media (max-width: 860px) {
  /* In the dock the buttons' flow margins give way to its own padding; .pack-dock.out keeps the 10px between
     the two actions. */
  .pack-dock > .open-again, .pack-dock > .play-next { margin-top: 0; }
  /* The wait is a quiet readable line under "Jouer", and it stays tappable (it brings the closed tile and its
     timer back). It is never under the bar: the dock's padding keeps it above it. */
  .pack-dock.out .open-again {
    background: none; box-shadow: none; border: 0; color: var(--muted);
    font-size: 14.5px; font-weight: 800; min-height: 44px; padding: 12px 0;
  }
}
/* On a computer the actions stay in the flow under the pager, and they hold their room from the first card: the
   card was sized with them under it, and the tile never grows under the pointer when they come out. */
@media (min-width: 861px) {
  .pack-dock { margin-top: 14px; }
  .pack-dock > .open-again, .pack-dock > .play-next { margin-top: 0; }
  .pack-dock > .open-again[hidden] { display: block !important; }
  .pack-dock > .play-next[hidden] { display: flex !important; }
  .pack-dock > [hidden] { visibility: hidden; animation: none; pointer-events: none; }
  .pack-dock .ed-actions { margin: 0; }
  .pack-dock .ed-actions:has(.open-again[hidden]) { display: flex; }
  .pack-dock .ed-actions > [hidden] { display: block !important; visibility: hidden; pointer-events: none; }
  /* « Jouer » and the wait on one line: stacked, the wait was a second big boxed button and the one cut off by
     the window's bottom. It reads as a quiet line beside the gold button, still a button (it brings the timer back). */
  .pack-dock.out { display: flex; align-items: center; gap: 14px; }
  .pack-dock.out > .play-next { flex: 1 1 auto; width: auto; min-width: 0; }
  .pack-dock.out .open-again {
    flex: 0 0 auto; width: auto; margin: 0; padding: 10px 4px; min-height: 44px;
    background: none; box-shadow: none; border: 0; color: var(--muted); font-size: 15px; font-weight: 800; white-space: nowrap;
  }
  @media (hover: hover) { .pack-dock.out .open-again:hover { color: var(--text); } }
}
/* The sheet after a loyalty claim: what was added, and the one button that leads to it. */
.ly-added { display: grid; gap: 10px; text-align: center; justify-items: center; }
.ly-added h2 { margin: 0; }
.ly-added p { margin: 0; max-width: 34ch; color: var(--muted); font-weight: 700; text-wrap: balance; }
.ly-added-icon { font-size: 56px; line-height: 1; animation: ly-added-pop .5s cubic-bezier(.2,1.6,.4,1); }
/* Up to three real sachets fanned out: "+3 packs" looks like three packs, not a parcel. */
.pk-fan { display: flex; justify-content: center; height: 104px; margin: 4px 0 2px; }
.pk-fan i { width: 72px; aspect-ratio: 63 / 88; background: url(/pack-front.webp?v=7cc6581117) center / 100% 100% no-repeat; filter: drop-shadow(0 6px 12px rgba(0,0,0,.45)); transform-origin: 50% 100%; }
.pk-fan i + i { margin-left: -34px; }
.pk-fan i:nth-child(1):not(:only-child) { transform: rotate(-12deg) translateY(6px); }
.pk-fan i:nth-child(2) { transform: translateY(-4px); z-index: 1; }
.pk-fan i:nth-child(2):last-child { transform: rotate(10deg) translateY(2px); }
.pk-fan i:nth-child(3) { transform: rotate(12deg) translateY(6px); z-index: 2; }
/* The same sachet at text size, wherever a line counts packs (guide bar, "Ouvrir mes packs"). */
.pk-ico { display: inline-block; flex: none; height: 1.35em; aspect-ratio: 63 / 88; vertical-align: -.3em; margin-right: .4em; background: url(/pack-front.webp?v=7cc6581117) center / 100% 100% no-repeat; transform: rotate(-8deg); filter: drop-shadow(0 1px 2px rgba(0,0,0,.35)); }
.ly-added .ly-open-now { width: 100%; min-height: 56px; font-size: 17px; margin-top: 6px; animation: guided-pulse 1.6s ease-in-out infinite; }
/* After a MemeCoins claim: the gain, the balance, then one big button to the next move. The sheet's own
   "Fermer" gives way to "Plus tard", under the button. */
.nm { display: grid; gap: 8px; text-align: center; justify-items: center; }
.sheet-body:has(.nm) > .close:last-child { display: none; }
.nm-coin { animation: ly-added-pop .5s cubic-bezier(.2,1.6,.4,1); filter: drop-shadow(0 8px 18px rgba(240,184,58,.35)); }
.nm-gain { margin: 0; font-size: 34px; font-variant-numeric: tabular-nums; color: var(--gold-text); }
.nm-bal { margin: 0; font-weight: 700; }
.nm-next { display: grid; gap: 8px; width: 100%; margin-top: 10px; padding-top: 14px; border-top: 1px solid var(--line); }
.nm-q { margin: 0; font-weight: 900; font-size: 18px; }
.nm-go { width: 100%; min-height: 56px; font-size: 17px; display: flex; align-items: center; justify-content: center; gap: 8px; text-align: center; text-decoration: none; animation: guided-pulse 1.6s ease-in-out infinite; }
/* The arrow stays on the line of the last word, never alone on its own line. */
.nm-go .nm-arrow { flex: none; }
.nm-go .pk-ico { flex: none; }
.nm-why, .nm-wait { margin: 0; max-width: 36ch; justify-self: center; text-wrap: balance; }
.nm-later { width: 100%; margin-top: 4px; }
@keyframes ly-added-pop { from { transform: scale(.4) rotate(-12deg); opacity: 0; } }
/* Les écrans du parcours : à quoi servent les MemeCoins, plus de doublons, le pack surprise du jour. Même mise en
   page que .nm, et le paquet du cadeau remue tant qu'il n'est pas ouvert. */
.parcours { display: grid; gap: 10px; text-align: center; justify-items: center; }
.parcours h2 { margin: 0; }
.parcours p { margin: 0; max-width: 36ch; text-wrap: balance; }
.parcours .btn { width: 100%; min-height: 52px; display: flex; align-items: center; justify-content: center; gap: 8px; text-decoration: none; }
.parcours .expert-btn { background: var(--gold-grad); color: var(--on-gold); animation: guided-pulse 1.6s ease-in-out infinite; }
.sp-gift { font-size: 72px; line-height: 1; animation: sp-shake 1.8s ease-in-out infinite; }
.sp-gift.open { animation: ly-added-pop .5s cubic-bezier(.2,1.6,.4,1); }
@keyframes sp-shake { 0%, 60%, 100% { transform: none; } 70% { transform: rotate(-9deg) scale(1.06); } 80% { transform: rotate(9deg) scale(1.06); } 90% { transform: rotate(-4deg); } }
@media (prefers-reduced-motion: reduce) {
  .sp-gift, .parcours .expert-btn { animation: none; }
  .ly-added-icon, .ly-added .ly-open-now, .pack-open .play-next, .pack-open .play-next::after, .nm-coin, .nm-go { animation: none; }
}

/* Several cards on one round (EXPERT). The switch sits above the filters; once on, a tap adds a card, the stepper
   under it sets how many copies, and the footer with the sum and the stake button stays pinned to the sheet's
   bottom, so the player never scrolls back up to confirm. */
.stake-multi { display: flex; align-items: center; gap: 12px; box-sizing: border-box; width: 100%; min-height: 52px; margin-bottom: 10px; padding: 8px 14px; border: 2px solid var(--line); border-radius: 14px; background: var(--surface); color: var(--text); font: inherit; text-align: left; cursor: pointer; touch-action: manipulation; }
.stake-multi > span:last-child { display: grid; gap: 1px; min-width: 0; }
.stake-multi b { font-size: 15px; }
.stake-multi small { color: var(--muted); font-weight: 700; font-size: 12px; }
.sm-box { flex: none; width: 24px; height: 24px; border-radius: 7px; border: 2px solid var(--muted); display: grid; place-items: center; transition: background .12s, border-color .12s; }
.stake-multi[aria-pressed="true"] { border-color: var(--active-bg); }
.stake-multi[aria-pressed="true"] .sm-box { background: var(--active-bg); border-color: var(--active-bg); }
.stake-multi[aria-pressed="true"] .sm-box::after { content: "✓"; color: var(--active-ink); font-weight: 900; font-size: 15px; line-height: 1; }
.stake-cell.picked .stake-tile { box-shadow: 0 0 0 3px var(--active-bg); background: color-mix(in srgb, var(--active-bg) 12%, transparent); }
.pick-n { position: absolute; z-index: 6; top: 6px; left: 6px; padding: 2px 8px; border-radius: 999px; background: var(--active-bg); color: var(--active-ink); font-weight: 900; font-size: 12px; box-shadow: 0 2px 8px rgba(0,0,0,.3); }
.stake-step { display: grid; grid-template-columns: 36px 1fr 36px; align-items: center; gap: 2px; margin-top: 4px; padding: 2px; border-radius: 12px; background: var(--surface-2); }
.stake-step button { min-height: 36px; padding: 0; border: 0; border-radius: 10px; background: var(--active-bg); color: var(--active-ink); font: inherit; font-weight: 900; font-size: 18px; line-height: 1; cursor: pointer; touch-action: manipulation; }
.stake-step button:disabled { opacity: .3; cursor: default; }
.stake-step output { text-align: center; font-weight: 900; font-size: 13px; }
/* In multi mode a picked card grows no bigger on hover: the stepper under it has to stay where the pointer is. */
.stake-pick.multi .stake-cell:hover { scale: 1; }
.stake-foot { position: sticky; bottom: 0; z-index: 8; display: flex; align-items: center; gap: 10px; margin: 0 -18px; padding: 10px 18px calc(10px + env(safe-area-inset-bottom)); background: var(--page); border-top: 1px solid var(--line); box-shadow: 0 -10px 24px rgba(0,0,0,.18); }
.stake-foot[hidden] { display: none; }
.sf-sum { flex: 1; min-width: 0; font-weight: 700; font-size: 14px; color: var(--muted); }
.sf-sum b { color: var(--text); font-weight: 900; }
.sf-go { flex: none; margin: 0; min-height: 48px; white-space: nowrap; }
.sf-go:disabled { opacity: .45; }
@media (max-width: 400px) { .stake-foot { flex-wrap: wrap; } .sf-go { flex: 1 1 100%; } }

/* Several staked cards in the slot the single card fills: up to three, fanned. */
.mp-stack { position: relative; display: block; width: 72px; aspect-ratio: 63 / 88; flex: none; }
.mp-thumb { position: absolute; inset: 0; transform: translateX(calc(var(--i) * 8px)) rotate(calc((var(--i) - 1) * 7deg)); transform-origin: 50% 90%; z-index: calc(3 - var(--i)); }
.mp-thumb .card { max-width: 100%; }
.multi-pick { display: flex; align-items: center; gap: 18px; width: 100%; box-sizing: border-box; padding: 10px 14px 10px 10px; border: 2px solid var(--active-bg); border-radius: 16px; background: var(--page); color: var(--text); font: inherit; text-align: left; cursor: pointer; }
.multi-pick .mp-stack { width: 56px; }
.mp-txt { display: grid; gap: 2px; min-width: 0; }
.mp-txt b { font-size: 17px; }
.mp-txt .fp-val { font-weight: 900; }
.mp-txt em { font-style: normal; font-size: 13px; font-weight: 800; color: var(--muted); text-decoration: underline; text-underline-offset: 3px; }
.lt-card.multi, .ar-stake.multi { border-color: var(--active-bg); gap: 18px; }
.lt-thumb.mp-stack { width: 60px; }
.ar-thumb.mp-stack { width: 52px; }
.ls-thumb.mp-stack { width: 56px; }

/* Wider than a phone, the play buttons stay in the flow but stick to the window's bottom edge: on a short laptop
   screen the board and bets push them below the fold otherwise. */
@media (min-width: 861px) {
  .lucky-table .launch, .findpepe .fp-start, .findpepe .fp-cash { position: sticky; bottom: 12px; z-index: 5; box-shadow: 0 10px 30px rgba(0, 0, 0, .35); }
}

/* The question asked before a card of value burns (askStake in app.js). It rides the app's sheet, so the bottom
   sheet on a phone, the centred dialog past 900px and both themes come from .sheet-card above. */
.stake-ask { display: grid; gap: 12px; text-align: left; }
.stake-ask p { margin: 0; }
/* The card as a thumbnail beside what it is: the whole window, "Ne plus afficher" included, holds on one phone
   screen without scrolling. */
.stake-ask-head { display: grid; grid-template-columns: 96px 1fr; gap: 14px; align-items: center; }
.stake-ask-card .card { width: 100%; margin: 0; }
.stake-ask-what { display: grid; gap: 4px; }
.stake-ask-what b { color: var(--heading); font-size: 17px; }
.stake-ask-warn { font-size: 14px; }
/* Two full-width buttons: on a phone the thumb must not have to aim. */
.stake-ask-btns { display: grid; gap: 8px; }
.stake-ask-btns .btn { width: 100%; min-height: 44px; margin: 0; }
.stake-ask-off { display: flex; align-items: center; gap: 8px; min-height: 44px; font-size: 14px; color: var(--muted); cursor: pointer; }
.stake-ask-off input { width: 18px; height: 18px; accent-color: var(--active-bg); }
.stake-ask-tip { display: grid; gap: 8px; padding: 12px; border-radius: 14px; background: color-mix(in srgb, var(--line) 35%, transparent); font-size: 13px; color: var(--muted); }
.stake-ask .stake-block { justify-self: start; min-height: 40px; margin: 0; padding-inline: 14px; font-size: 14px; }
/* Les premières mises : la carte en grand, au-dessus du texte, parce que la fenêtre sert à la montrer. */
.stake-ask.is-learn .stake-ask-head { grid-template-columns: 1fr; justify-items: center; text-align: center; }
.stake-ask.is-learn .stake-ask-what { justify-items: center; }
/* La carte en grand, mais pas au point de manger la fenêtre : sur un iPhone SE sa hauteur commande. */
.stake-ask.is-learn .stake-ask-card { width: min(62vw, 220px, 26dvh); }
/* La leçon est plus haute qu'un iPhone SE : « Jouer cette carte » tombait sous le pli de la feuille, et il faut
   savoir qu'on peut faire défiler pour le trouver. Il reste collé au bas de la feuille, qui défile dessous. */
.stake-ask.is-learn .stake-ask-btns { position: sticky; bottom: 0; z-index: 5; padding-bottom: calc(6px + env(safe-area-inset-bottom)); background: var(--page); }
.stake-ask-learn { font-size: 14px; color: var(--muted); }
@media (min-width: 900px) { .stake-ask-head { grid-template-columns: 120px 1fr; } }

/* Admin « En ce moment »: where the people on the site are right now, page by page. */
.adm-live h3 small { display: block; font-size: 12px; font-weight: 700; margin-top: 2px; }
.adm-live-pages { display: grid; gap: 4px; margin-bottom: 8px; }
.adm-live-page { display: grid; grid-template-columns: minmax(120px, 220px) 1fr 36px 64px; align-items: center; gap: 10px; border: 0; background: none; color: inherit; font: inherit; font-size: 13px; text-align: left; padding: 4px 6px; border-radius: 8px; cursor: pointer; }
.adm-live-page.is-on { background: var(--active-bg); color: var(--active-ink); }
@media (hover: hover) { .adm-live-page:not(.is-on):hover { background: var(--surface-2); } }
.adm-live-name { font-weight: 800; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.adm-live-bar { display: flex; height: 12px; border-radius: 6px; background: var(--line); overflow: hidden; }
.adm-live-page b { text-align: right; font-size: 15px; }
.adm-live-page small { color: var(--muted); font-size: 11px; }
.adm-live-page.is-on small { color: inherit; }
i.adm-live-on, .adm-live-state.adm-live-on { background: #30a46c; }
i.adm-live-bg, .adm-live-state.adm-live-bg { background: #f5a623; }
i.adm-live-gone, .adm-live-state.adm-live-gone { background: #8b8d98; }
.adm-live-state { display: inline-block; color: #fff; font-size: 11px; font-weight: 800; border-radius: 6px; padding: 1px 6px; }
.adm-live-trail { max-width: 340px; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 560px) { .adm-live-page { grid-template-columns: minmax(0, 1fr) 70px 28px 52px; } }

/* ---------- limited editions: the third tile of /app/packs, and the shelf of /app/editions ---------- */
/* The switcher was built for two packs and slides a pill over them; an edition makes a third column, and the pill
   is one column wide either way, so the same translate moves it one step. */
.pack-switch:has(button:nth-child(3)) { grid-template-columns: 1fr 1fr 1fr; }
.pack-switch:has(button:nth-child(3))::before { width: calc((100% - 8px) / 3); }
.pack-switch:has(button:nth-child(3)[aria-checked="true"])::before { transform: translateX(200%); }
.pack-switch .ed-pick { font-size: 14px; }
/* On /app/packs each choice stacks its emoji over its name, so « Édition limitée » wraps instead of being cut at
   320 px; the edition adds its clock under its name, and turns the thumb violet when it is the one chosen. */
.packs .pack-switch { border-radius: 20px; }
.packs .pack-switch::before { border-radius: 16px; }
.packs .pack-switch button { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; min-height: 64px; padding: 8px 4px; border-radius: 16px; font-size: 14px; line-height: 1.15; white-space: normal; }
.packs .pack-switch .sw-ico { font-size: 20px; line-height: 1; }
.packs .pack-switch .sw-lab { text-wrap: balance; }
.packs .pack-switch .sw-timer { margin-top: 2px; padding: 3px 7px; border-radius: 999px; background: linear-gradient(135deg, #8b5cf6, #6d28d9); color: #fff; font-size: 11px; font-weight: 900; line-height: 1.2; font-variant-numeric: tabular-nums; white-space: nowrap; }
.packs .pack-switch:has(.ed-pick[aria-checked="true"])::before { background: linear-gradient(135deg, #8b5cf6, #6d28d9); box-shadow: 0 6px 16px rgba(109, 40, 217, .4); }
.packs .pack-switch .ed-pick[aria-checked="true"] { color: #fff; }
.packs .pack-switch .ed-pick[aria-checked="true"] .sw-timer { background: rgba(255, 255, 255, .22); }

/* The edition booster: its own sachet (Théo's artwork, 01/10/2026), « ÉDITION LIMITÉE CHATS » in French and
   « LIMITED EDITION CATS » in English, lit from behind in violet. Same pouch silhouette as the other two, so the
   glint's mask is the sachet itself. */
.booster.edition { filter: drop-shadow(0 0 22px rgba(139, 92, 246, .55)); }
.booster.edition .b-body, .booster.edition .b-top { background-image: url(/pack-front-chats-s1.webp?v=1d98247934); }
.booster.edition::before { -webkit-mask-image: url(/pack-front-chats-s1.webp?v=1d98247934); mask-image: url(/pack-front-chats-s1.webp?v=1d98247934); }
:root[lang="en"] .booster.edition .b-body, :root[lang="en"] .booster.edition .b-top { background-image: url(/pack-front-chats-s1-en.webp?v=2bd9770f7b); }
:root[lang="en"] .booster.edition::before { -webkit-mask-image: url(/pack-front-chats-s1-en.webp?v=2bd9770f7b); mask-image: url(/pack-front-chats-s1-en.webp?v=2bd9770f7b); }
.edition-stage { border-color: color-mix(in srgb, #8b5cf6 55%, var(--line)); }
/* An edition's name is longer than « Memes FR »: it wraps rather than pushing the badge out of the tile. */
.edition-stage .pk-title { white-space: normal; text-wrap: balance; color: var(--heading); }
/* « Pack exclusif et temporaire »: a violet chip. */
.ed-badge { flex: none; padding: 6px 12px; border-radius: 999px; background: color-mix(in srgb, #8b5cf6 22%, transparent); color: #6d28d9; font-size: 12px; font-weight: 800; line-height: 1.2; }
:root[data-theme="dark"] .ed-badge { color: #ddd0ff; }
/* On a card page, between the name and the rarity: « Édition limitée », smaller, so the three fit one line. */
.cs-ed { padding: 4px 9px; font-size: 11px; }
/* The edition picker of the collection and of the market: one line per edition, its name, where it stands and
   how far the player is into it. A list, not a row of chips — a new edition comes out every week. */
.edp-h { margin: 0; font-size: 20px; }
/* `minmax(0, 1fr)` and `min-width: 0` all the way down: the sheet is a grid, and a grid item is as wide as its
   content by default, so at 320 px a long edition name pushed the whole list past the right edge. */
.edp-list { display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; min-width: 0; margin: 12px 0 0; padding: 0; list-style: none; }
.edp-list li { min-width: 0; }
.edp-list button { display: grid; grid-template-columns: minmax(0, 1fr); gap: 4px; width: 100%; padding: 11px 13px; border: 1px solid var(--line); border-radius: 14px; background: var(--surface); color: var(--text); font: inherit; font-weight: 800; text-align: left; cursor: pointer; touch-action: manipulation; }
.edp-list button[aria-pressed="true"] { border-color: transparent; background: var(--active-bg); color: var(--active-ink); }
/* An announced edition has never been sold: it says it is coming and cannot be picked. */
.edp-list button[disabled] { opacity: .55; cursor: default; }
.edp-list small { font-weight: 700; opacity: .75; }
.edp-head { display: flex; align-items: center; gap: 8px; }
.edp-head b { flex: 1; min-width: 0; overflow-wrap: anywhere; text-wrap: balance; }
.edp-st { flex: none; font-size: 12px; font-weight: 900; text-transform: uppercase; letter-spacing: .04em; opacity: .8; }
@media (hover: hover) {
  .edp-list button:not([disabled]):hover { border-color: var(--accent); }
}
/* The clock is the tile's headline: days, hours, minutes and seconds, each in its own block, ticking to the second. */
.ed-clock { display: grid; justify-items: center; gap: 8px; margin: 16px 0 2px; }
.ec-cap { font-size: 13px; font-weight: 900; letter-spacing: .06em; text-transform: uppercase; color: #6d28d9; }
:root[data-theme="dark"] .ec-cap { color: #c4b5fd; }
.ec-units { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; width: 100%; max-width: 340px; }
.ec-u { display: grid; justify-items: center; gap: 4px; padding: 10px 0 8px; border-radius: 14px; background: linear-gradient(160deg, #8b5cf6, #6d28d9); color: #fff; box-shadow: 0 8px 18px rgba(109, 40, 217, .28), inset 0 1px 0 rgba(255, 255, 255, .25); }
.ec-u b { font-size: clamp(24px, 8vw, 32px); font-weight: 900; line-height: 1; font-variant-numeric: tabular-nums; }
.ec-u small { font-size: 10px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; opacity: .85; }
.ed-clock.over .ec-units { display: none; }
.ed-clock.over .ec-cap { font-size: 15px; letter-spacing: 0; text-transform: none; }
/* On the shelf the same clock, smaller and set left, under the edition's name. */
.ed-clock.mini { justify-items: start; gap: 6px; margin: 2px 0 4px; }
.ed-clock.mini .ec-cap { font-size: 11px; }
.ed-clock.mini .ec-units { max-width: 260px; gap: 6px; }
.ed-clock.mini .ec-u { gap: 2px; padding: 7px 0 6px; border-radius: 10px; box-shadow: none; }
.ed-clock.mini .ec-u b { font-size: 20px; }
.ed-clock.mini .ec-u small { font-size: 9px; }
.edition-stage .pk-body { padding-top: 10px; }
.packs .edition-stage .pack-closed .what { max-width: 32ch; margin: 12px auto 0; line-height: 1.45; }
/* What the clock means, said once, in a soft violet box with room around the words. */
.ed-fomo { margin: 14px 0 0; padding: 12px 14px; border-radius: 14px; background: color-mix(in srgb, #8b5cf6 12%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, #8b5cf6 30%, transparent); font-size: 14px; font-weight: 700; line-height: 1.45; color: #6d28d9; text-wrap: balance; }
:root[data-theme="dark"] .ed-fomo { color: #ddd0ff; }
.btn.ed-btn { background: linear-gradient(135deg, #c7b6ff, #8b5cf6 55%, #6d28d9); color: #fff; box-shadow: 0 10px 24px rgba(139, 92, 246, .35); }
/* Said, not shown: what the four ticking blocks mean, for a screen reader. */
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
.ed-poor { margin: 10px auto 0; max-width: 34ch; font-size: 14px; font-weight: 700; line-height: 1.45; color: var(--muted); }
.ed-poor a { color: #7c3aed; font-weight: 800; }
.ed-all { display: block; margin-top: 10px; font-size: 14px; font-weight: 800; color: var(--muted); text-decoration: none; }

.editions h2 { margin: 22px 0 8px; font-size: clamp(19px, 5vw, 22px); color: var(--heading); }
.ed-list { display: grid; gap: 12px; margin: 0; padding: 0; list-style: none; }
.ed-row { display: grid; gap: 8px; padding: 16px; border-radius: 18px; background: var(--surface-2); text-align: left; }
.ed-row.ed-running { box-shadow: inset 0 0 0 1.5px color-mix(in srgb, #8b5cf6 60%, transparent); }
/* An ended edition is kept readable, not greyed out: its cards are still the player's, and the count still matters. */
.ed-row.ed-ended { opacity: .85; }
.ed-row-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 10px; }
.ed-row-head b { font-size: 17px; color: var(--heading); }
.ed-row p { margin: 0; }
.ed-prog-n { font-size: 14px; font-weight: 800; color: var(--heading); font-variant-numeric: tabular-nums; }
.ed-row .ed-btn { justify-self: start; margin-top: 4px; width: auto; padding: 10px 18px; text-decoration: none; }

/* The edition's one-of-a-kind card (Keyboard Cat), beside its booster: the card itself, moving, over what finding
   it is worth. Side by side down to 320 px — the booster gives up a little width for it — and gone once found. */
.packs .edition-stage.has-jackpot .pk-body { display: grid; grid-template-columns: auto minmax(0, max-content); justify-content: center; align-items: center; gap: 14px; }
.packs .edition-stage.has-jackpot .booster { width: clamp(100px, min(calc((100svh - 440px) * .7), 38vw), 160px); margin: 0; }
.ed-jackpot { display: grid; justify-items: center; gap: 6px; width: clamp(104px, 30vw, 136px); text-align: center; }
.ej-tag { padding: 4px 10px; border-radius: 999px; background: #1c1405; color: #ffd76a; box-shadow: inset 0 0 0 1px rgba(255, 215, 106, .55); font-size: 11px; font-weight: 900; letter-spacing: .04em; text-transform: uppercase; white-space: nowrap; }
.ej-card { width: 100%; filter: drop-shadow(0 0 14px rgba(255, 196, 64, .45)); }
.ej-prize { display: grid; justify-items: center; gap: 1px; margin: 2px 0 0; line-height: 1.2; }
.ej-prize .ej-ico { font-size: 18px; line-height: 1; }
.ej-prize b { font-size: 14px; font-weight: 900; color: var(--gold-text); }
.ej-prize span:last-child { font-size: 12px; font-weight: 700; color: var(--muted); }

/* Pulled: what the card wins, said once it has turned over. Gold on dark, never dark on gold. */
.jp-won { display: grid; justify-items: center; gap: 10px; padding: 18px 16px; border-radius: 18px; background: radial-gradient(120% 90% at 50% 0%, #3a2a06, #120d02); color: #fff; text-align: center; box-shadow: inset 0 0 0 1.5px rgba(255, 215, 106, .6); }
.jp-won .jp-ok { margin-top: 4px; }
.jp-won .jp-ico { margin: 0; font-size: 44px; line-height: 1; }
.jp-won h2 { margin: 0; font-size: clamp(20px, 6vw, 24px); color: #ffd76a; text-align: center; text-wrap: balance; }
/* Its own button closes it: the sheet's generic « Fermer » under it would say the same thing twice. */
.sheet-body:has(.jp-won) > .close:last-child { display: none; }
.jp-won p { margin: 0; max-width: 34ch; font-size: 15px; line-height: 1.5; }

/* The admin, full page (/app/admin/…): its own menu on the left, a sticky header, one period bar for the sections that
   count something. body.adm-mode (set by route()) puts the game's own menus, top bar and guide away. */
body.adm-mode { --tabbar-h: 0px; }
body.adm-mode .side, body.adm-mode .app-top, body.adm-mode .tabbar, body.adm-mode .guide, body.adm-mode .coach,
body.adm-mode .ach-nudge { display: none !important; }
body.adm-mode .view { margin: 0; padding: 0; max-width: none; }
body.adm-mode .view > .panel.adm { max-width: 640px; margin: 40px auto; padding: 0 16px; }
.adm-refused { gap: 8px; flex-wrap: wrap; }
.adm.adm-app { max-width: none; min-height: 100vh; min-height: 100dvh; }
.adm-side { position: fixed; z-index: 40; top: 0; bottom: 0; left: 0; width: 260px; box-sizing: border-box; display: flex; flex-direction: column; gap: 14px;
  padding: max(18px, env(safe-area-inset-top)) 12px max(14px, env(safe-area-inset-bottom)) max(12px, env(safe-area-inset-left));
  background: var(--page); border-right: 1px solid var(--line); }
.adm-brand { font-weight: 900; font-size: 17px; color: var(--heading); text-decoration: none; padding: 0 8px; }
.adm-brand b { color: var(--gold-text); }
.adm-find input { width: 100%; box-sizing: border-box; font-size: 14px; padding: 8px 12px; border-radius: 12px; }
.adm-menu { display: grid; gap: 14px; }
.adm-menu-group { display: grid; gap: 2px; }
.adm-menu-group > small { color: var(--muted); font-size: 11px; font-weight: 900; text-transform: uppercase; letter-spacing: .06em; padding: 0 10px 4px; }
.adm-menu a { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 10px; color: var(--text); text-decoration: none; font-weight: 700; font-size: 14px; }
.adm-menu a:hover { background: var(--surface); }
.adm-menu a[aria-current] { background: var(--active-bg); color: var(--active-ink); }
.adm-menu svg { width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; opacity: .85; }
.adm-menu a span { flex: 1; min-width: 0; }
.adm-menu a i { font-style: normal; font-size: 11px; font-weight: 900; min-width: 18px; height: 18px; padding: 0 5px; box-sizing: border-box; border-radius: 999px;
  display: inline-grid; place-items: center; background: #e0457b; color: #fff; }
.adm-menu a i[hidden] { display: none; }
.adm-side-foot { margin-top: auto; display: grid; grid-template-columns: 1fr 1fr; gap: 6px; padding-top: 10px; border-top: 1px solid var(--line); }
.adm-side-row { grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; gap: 8px; white-space: nowrap; }
.adm-side-row .adm-pw { padding-inline: 6px; }
.adm-side-foot .btn { width: 100%; justify-content: center; font-size: 13px; padding: 7px 8px; border-radius: 10px; white-space: nowrap; text-decoration: none; }
.adm-textbtn { background: none; border: 0; padding: 4px 6px; font: inherit; font-size: 12px; font-weight: 800; color: var(--muted); cursor: pointer; }
.adm-textbtn:hover { color: var(--text); }
/* A laptop screen (800 px tall) shows the whole menu down to Réglages: tighter rows, the foot's buttons two by two. */
@media (min-width: 900px) and (max-height: 920px) {
  .adm-side { gap: 8px; padding-top: 12px; padding-bottom: 10px; }
  .adm-find input { padding: 6px 10px; font-size: 13px; }
  .adm-menu { gap: 6px; }
  .adm-menu-group { gap: 0; }
  .adm-menu a { padding: 3px 10px; font-size: 13px; line-height: 18px; }
  .adm-menu svg { width: 16px; height: 16px; }
  .adm-menu-group > small { font-size: 10px; line-height: 12px; padding-bottom: 2px; }
  .adm-side-foot { padding-top: 8px; }
}
.adm-pw { font-size: 12px; font-weight: 800; color: var(--muted); text-decoration: none; padding: 4px 10px; }
.adm-pw::before { content: "●"; margin-right: 6px; color: var(--muted); }
.adm-pw.is-on::before { color: #1db36b; }
.adm-scrim { display: none; }
.adm-main { min-width: 0; padding: 0 max(16px, env(safe-area-inset-right)) 60px max(16px, env(safe-area-inset-left)); }
.adm-head { position: sticky; top: 0; z-index: 30; display: flex; align-items: center; gap: 12px; margin: 0 -16px 12px; padding: max(10px, env(safe-area-inset-top)) 16px 10px;
  background: var(--page); border-bottom: 1px solid var(--line); }
.adm-title { flex: 1; min-width: 0; }
.adm-title small { display: block; color: var(--muted); font-size: 11px; font-weight: 900; text-transform: uppercase; letter-spacing: .06em; }
.adm-title h1 { margin: 0; font-size: 22px; line-height: 1.2; color: var(--heading); text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.adm-online { flex: none; font-size: 13px; font-weight: 800; color: var(--text); text-decoration: none; padding: 6px 12px; border-radius: 999px; border: 1px solid var(--line); background: var(--surface); }
.adm-online::before { content: "●"; color: #1db36b; margin-right: 6px; }
.adm-burger { display: none; flex: none; width: 40px; height: 40px; border-radius: 12px; border: 1px solid var(--line); background: var(--surface); color: var(--text); font-size: 18px; cursor: pointer; }
@media (min-width: 900px) {
  .adm-main { margin-left: 260px; padding: 0 32px 60px; }
  .adm-head { margin: 0 -32px 14px; padding: 14px 32px; }
}
@media (max-width: 899px) {
  .adm-side { transform: translateX(-102%); transition: transform .2s ease; box-shadow: none; }
  .adm-app.adm-drawer .adm-side { transform: none; box-shadow: 0 0 40px rgba(0, 0, 0, .35); }
  .adm-app.adm-drawer .adm-scrim { display: block; position: fixed; inset: 0; z-index: 35; background: rgba(0, 0, 0, .45); }
  .adm-burger { display: grid; place-items: center; }
  .adm-title h1 { font-size: 18px; }
}
.adm-periodbar { margin: 0 0 14px; }
.adm-periodbar[hidden] { display: none; }
/* La barre de periode. Le panneau du calendrier est en position absolue au-dessus
   de la page : ouvrir les dates ne pousse aucun bloc de la section. */
.adm-period { position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; }
.adm-period-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; width: 100%; }
.adm-period-group { margin-left: auto; }
.adm-seg { display: inline-flex; flex-wrap: wrap; gap: 2px; padding: 3px; border-radius: 12px; background: var(--surface); border: 1px solid var(--line); }
.adm-seg button { border: 0; background: none; color: var(--muted); font: inherit; font-size: 13px; font-weight: 800; min-height: 34px; padding: 6px 12px; border-radius: 9px; cursor: pointer; }
.adm-seg button[aria-pressed="true"] { background: var(--active-bg); color: var(--active-ink); }
.adm-seg button:disabled { opacity: .45; cursor: default; }
.adm-step { flex: none; width: 40px; height: 40px; border-radius: 12px; border: 1px solid var(--line); background: var(--surface); color: var(--text); font-size: 18px; font-weight: 900; cursor: pointer; }
.adm-step:disabled { color: var(--muted); opacity: .45; cursor: default; }
.adm-pick { display: inline-flex; align-items: center; gap: 8px; min-height: 40px; padding: 0 14px; border-radius: 12px; border: 1px solid var(--line); background: var(--surface); color: var(--text); font: inherit; font-size: 14px; font-weight: 800; cursor: pointer; }
.adm-pick[aria-expanded="true"] { border-color: var(--active-bg); }
.adm-pick-len { color: var(--muted); font-size: 13px; font-weight: 700; }
.adm-pick-len::before { content: "\00b7"; margin-right: 7px; }
.adm-pick-caret { color: var(--muted); }
.adm-period-vs { color: var(--muted); font-size: 12px; font-weight: 700; }
.adm-cal { position: absolute; z-index: 40; top: calc(100% + 6px); left: 0; }
.adm-cal-box { display: flex; background: var(--surface); border: 1px solid var(--line); border-radius: 16px; box-shadow: 0 18px 44px rgba(0,0,0,.38); overflow: hidden; }
.adm-cal-quick { display: flex; flex-direction: column; gap: 2px; min-width: 178px; padding: 10px; background: var(--surface-2); border-right: 1px solid var(--line); }
.adm-cal-quick button { border: 0; background: none; color: var(--text); font: inherit; font-size: 13px; font-weight: 800; text-align: left; min-height: 40px; padding: 0 12px; border-radius: 10px; cursor: pointer; }
.adm-cal-quick button[aria-pressed="true"] { background: var(--active-bg); color: var(--active-ink); }
.adm-cal-pick { position: relative; padding: 10px 14px 12px; }
.adm-cal-nav { position: absolute; top: 10px; right: 14px; display: flex; gap: 6px; }
.adm-cal-months { display: flex; gap: 20px; }
.adm-cal-month h4 { margin: 6px 0 8px; font-size: 14px; text-transform: capitalize; }
.adm-cal-dows, .adm-cal-grid { display: grid; grid-template-columns: repeat(7, 40px); }
.adm-cal-dows span { padding-bottom: 4px; color: var(--muted); font-size: 11px; font-weight: 800; text-align: center; }
.adm-cal-day { height: 40px; border: 0; border-radius: 10px; background: none; color: var(--text); font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; }
.adm-cal-day:disabled { color: var(--muted); opacity: .4; cursor: default; }
.adm-cal-day.is-in { border-radius: 0; background: color-mix(in srgb, var(--active-bg) 20%, var(--surface)); }
.adm-cal-day.is-on { background: var(--active-bg); color: var(--active-ink); font-weight: 900; }
.adm-cal-day.is-today { outline: 1.5px solid var(--muted); outline-offset: -3px; }
@media (hover: hover) { .adm-cal-day:not(:disabled):not(.is-on):hover { background: var(--surface-2); } }
.adm-cal-foot { display: flex; align-items: center; gap: 10px; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); }
.adm-cal-sel { margin-right: auto; color: var(--muted); font-size: 12px; font-weight: 800; white-space: nowrap; }
/* `.btn` est un bouton de page pleine largeur : dans la barre il se tient a son texte. */
.adm-cal-foot .btn { flex: none; width: auto; margin-top: 0; min-height: 40px; padding: 0 16px; font-size: 14px; }
/* Deux mois demandent ~800 px : en dessous, un seul, et la boite ne deborde jamais de l'ecran. */
.adm-cal-box { max-width: calc(100vw - 32px); }
@media (max-width: 1180px) { .adm-cal-month + .adm-cal-month { display: none; } }
/* Sur telephone : une feuille qui monte du bas, un seul mois, les raccourcis en ligne. */
@media (max-width: 560px) {
  /* Les deux fleches encadrent la periode sur une ligne ; le regroupement prend la suivante. */
  .adm-period-group { margin-left: 0; flex-basis: 100%; }
  .adm-pick { flex: 1; min-width: 0; justify-content: center; gap: 6px; padding: 0 10px; }
  .adm-pick-when { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* Pas la place des deux : la plage passe avant le nombre de jours, que la ligne « vs » redit. */
  .adm-pick-len { display: none; }
  .adm-cal { position: fixed; inset: 0; top: 0; z-index: 60; display: flex; align-items: flex-end; background: rgba(0,0,0,.5); }
  .adm-cal-box { flex-direction: column; width: 100%; max-height: 92vh; overflow: auto; border-width: 1px 0 0; border-radius: 20px 20px 0 0; }
  .adm-cal-quick { flex-direction: row; min-width: 0; overflow-x: auto; border-right: 0; border-bottom: 1px solid var(--line); }
  .adm-cal-quick button { white-space: nowrap; }
  .adm-cal-months { display: block; }
  .adm-cal-month + .adm-cal-month { display: none; }
  .adm-cal-dows, .adm-cal-grid { grid-template-columns: repeat(7, 1fr); }
  /* 390 px ne tient pas la plage et les deux boutons sur une ligne : le resume passe au-dessus. */
  .adm-cal-foot { flex-wrap: wrap; }
  .adm-cal-sel { margin-right: 0; flex-basis: 100%; white-space: normal; }
  .adm-cal-foot .btn { flex: 1; }
}
.adm-tabs a { border: 1px solid var(--line); background: var(--surface); color: var(--muted); font-weight: 800; font-size: 14px; padding: 7px 14px; border-radius: 999px; text-decoration: none; }
.adm-tabs a[aria-current] { background: var(--active-bg); color: var(--active-ink); border-color: transparent; }
a.adm-kpi { color: inherit; text-decoration: none; transition: border-color .15s; }
a.adm-kpi:hover { border-color: var(--gold); }
.adm-kpi b em, .adm-strip em { font-style: normal; font-size: 13px; font-weight: 900; margin-left: 4px; color: var(--muted); }
.adm-kpi b em { margin-left: 0; }
/* Sur un téléphone, les tuiles restent deux par ligne : la valeur y tient encore. */
@media (max-width: 899px) { .adm-kpis { grid-template-columns: repeat(auto-fill, minmax(min(100%, 165px), 1fr)); } }
.adm-kpi b em.adm-up { color: #1db36b; }
.adm-kpi b em.adm-down, b.adm-down { color: #e0457b; }
.adm-strip { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; margin-bottom: 14px; }
.adm-strip a { display: grid; gap: 1px; padding: 10px 12px; border-radius: 14px; background: var(--surface-2); color: inherit; text-decoration: none; border: 1px solid transparent; }
.adm-strip a:hover { border-color: var(--line); }
.adm-strip small { color: var(--muted); font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; }
.adm-strip b { font-size: 20px; }
.adm-strip span { color: var(--muted); font-size: 12px; font-weight: 700; }
.adm-note { margin: -4px 0 12px; }
.adm-h2 { font-size: 16px; margin: 22px 0 10px; color: var(--heading); }
.adm-tag { font-size: 11px; font-weight: 800; color: var(--muted); background: var(--surface-2); padding: 2px 8px; border-radius: 999px; vertical-align: middle; margin-left: 6px; }
.adm-chart g.adm-zoomable { cursor: zoom-in; }
.adm-chart g.adm-zoomable:hover rect:first-child { fill: rgba(127, 127, 127, .12); }
.adm-loading { display: grid; gap: 10px; margin: 6px 0 14px; }
.adm-loading span { height: 64px; border-radius: 16px; background: linear-gradient(90deg, var(--surface) 0%, var(--surface-2) 50%, var(--surface) 100%); background-size: 200% 100%; animation: adm-shimmer 1.2s linear infinite; }
.adm-loading span:nth-child(2) { height: 180px; }
@keyframes adm-shimmer { to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .adm-loading span { animation: none; } }
.adm-empty { display: grid; gap: 6px; justify-items: start; }
.adm-pager { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 12px; }
.adm-toolbar { display: grid; gap: 4px; margin-bottom: 10px; }
.adm-filter { width: 100%; max-width: 520px; box-sizing: border-box; font-size: 14px; padding: 8px 12px; border-radius: 12px; margin: 0 0 8px; }
.adm-sort { color: inherit; text-decoration: none; }
.adm-sort.is-on { color: var(--text); }
.adm-table tr[data-go] { cursor: pointer; }
.adm-table tr.adm-day th { background: var(--surface-2); color: var(--text); font-size: 12px; text-transform: none; letter-spacing: 0; padding: 6px 8px; }
.adm-table td.adm-wrap { white-space: normal; min-width: 180px; max-width: 520px; }
.adm-table td a { color: var(--text); font-weight: 800; }
.adm-back { display: inline-block; margin-bottom: 10px; color: var(--muted); font-weight: 800; text-decoration: none; font-size: 14px; }
.adm-ph { display: flex; align-items: center; gap: 14px; margin-bottom: 12px; }
.adm-ph .av, .adm-ph .avatar-letter { width: 56px; height: 56px; --size: 56; font-size: 22px; flex: none; }
.adm-ph h2 { margin: 0; font-size: 22px; color: var(--heading); text-align: left; }
.adm-ph p { margin: 2px 0 0; overflow-wrap: anywhere; }
.adm-subnav { display: flex; gap: 4px; overflow-x: auto; margin: 0 0 14px; padding-bottom: 2px; border-bottom: 1px solid var(--line); scrollbar-width: none; }
.adm-subnav a { flex: none; padding: 9px 12px; color: var(--muted); font-weight: 800; font-size: 14px; text-decoration: none; border-bottom: 2px solid transparent; margin-bottom: -1px; }
.adm-subnav a[aria-current] { color: var(--text); border-bottom-color: var(--gold); }
.adm-more { font-size: 13px; font-weight: 800; color: var(--muted); }
.adm-older { margin-top: 10px; }
.adm-heat { display: grid; grid-template-rows: repeat(7, 11px); grid-auto-flow: column; grid-auto-columns: 11px; gap: 3px; overflow-x: auto; padding-bottom: 4px; }
.adm-heat i { border-radius: 3px; background: var(--surface-2); }
.adm-heat i.on { background: #1db36b; }
.adm-chip { display: inline-block; margin: 2px 4px 2px 0; padding: 2px 8px; border-radius: 999px; font-size: 12px; font-weight: 800; background: var(--surface-2); border: 1px solid var(--line); white-space: nowrap; }
.adm-chip.r-rare { border-color: #2f7bff; color: #2f7bff; }
.adm-chip.r-epic { border-color: #7b5cff; color: #7b5cff; }
.adm-chip.r-legendary { border-color: #f5a524; color: var(--gold-text); }
.adm-chip.r-mythic { border-color: #e0457b; color: #e0457b; }
.adm-chip.r-fullart { border-color: #ff7ad9; color: #d23ca8; }
.adm-chip.r-shiny { border-color: #d7a93c; background: linear-gradient(90deg, rgba(215, 169, 60, .18), rgba(255, 122, 217, .18)); }
.adm-expert .adm-xp-days, .adm-expert .adm-xp-actions { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin: 8px 0; }
.adm-expert [data-days] { border: 1px solid var(--line); background: var(--surface-2); color: var(--text); font: inherit; font-weight: 800; font-size: 13px; padding: 7px 12px; border-radius: 999px; cursor: pointer; }
.adm-expert [data-days][aria-pressed="true"] { background: var(--active-bg); color: var(--active-ink); border-color: transparent; }
.adm-expert .adm-xp-custom { width: 90px; font-size: 13px; padding: 6px 8px; }
.adm-xp-status small { display: block; color: var(--muted); }
/* Engagement: bars of a distribution, the retention curve, cohorts tinted by their rate, the week × hour grid, a replayed session. */
.adm-hbars { display: grid; gap: 6px; }
.adm-hbar { display: grid; grid-template-columns: minmax(84px, 34%) 1fr auto; gap: 10px; align-items: center; font-size: 13px; }
.adm-hbar > span { overflow-wrap: anywhere; font-weight: 700; }
.adm-hbar > i { display: grid; gap: 2px; height: 14px; align-content: center; background: var(--surface-2); border-radius: 999px; overflow: hidden; }
.adm-hbar > i b { display: block; height: 10px; border-radius: 999px; min-width: 2px; }
.adm-hbar > i b.adm-hbar-2 { height: 4px; }
.adm-hbar > em { font-style: normal; font-weight: 800; text-align: right; font-variant-numeric: tabular-nums; min-width: 64px; }
.adm-hbar > em small { display: block; color: var(--muted); font-weight: 600; font-size: 11px; }
/* Les classements de joueurs : le rang devant le pseudo, les onglets de la carte en petit. */
.adm-board .adm-tabs { margin: 0 0 10px; font-size: 12px; }
.adm-board-rank { display: inline-block; min-width: 1.7em; color: var(--muted); font-weight: 700; }
.adm-board-all { margin: 10px 0 0; text-align: right; font-size: 12px; }
.adm-curve svg { height: 180px; }
.adm-curve-axis { position: relative; height: 14px; display: block; }
.adm-curve-axis span { position: absolute; transform: translateX(-50%); white-space: nowrap; }
.adm-curve-axis span:first-child { transform: none; }
.adm-curve-axis span:last-child { transform: translateX(-100%); }
.adm-table td.adm-coh { text-align: center; font-variant-numeric: tabular-nums; background: rgba(29, 179, 107, calc(var(--a, 0) * .75)); }
.adm-table td.adm-coh-na { color: var(--muted); background: none; }
.adm-hours { display: grid; grid-template-columns: 34px repeat(24, minmax(10px, 1fr)); gap: 2px; align-items: center; overflow-x: auto; }
.adm-hours small { font-size: 10px; color: var(--muted); white-space: nowrap; }
.adm-hours i { display: block; height: 16px; border-radius: 3px; background: var(--surface-2); background-image: linear-gradient(rgba(47, 123, 255, var(--a, 0)), rgba(47, 123, 255, var(--a, 0))); }
.adm-replay h3 { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; justify-content: space-between; }
.adm-replay-list { list-style: none; margin: 0; padding: 0; max-height: 520px; overflow-y: auto; }
.adm-vis-ev.adm-last, .adm-table tr.adm-last > * { background: rgba(224, 69, 123, .1); }
.adm-vis-ev.adm-last { border-radius: 6px; padding-left: 4px; }
.adm-vis-pack .adm-vis-kind, .adm-vis-game .adm-vis-kind { color: var(--gold-text); font-weight: 800; }
.adm-table tr.adm-dim > * { color: var(--muted); }
@media (max-width: 600px) {
  .adm-hbar { grid-template-columns: minmax(70px, 38%) 1fr auto; gap: 6px; }
  .adm-hours { grid-template-columns: 28px repeat(24, 9px); }
}

/* En-tête, onglets de la section et barre de période ne forment qu'un bloc collant : changer
   d'onglet ou de période ne demande jamais de remonter la page. */
.adm-sticky { position: sticky; top: 0; z-index: 30; margin: 0 -16px 14px; padding: 0 16px; background: var(--page); border-bottom: 1px solid var(--line); }
.adm-sticky .adm-head { position: static; margin: 0 -16px; border-bottom: 0; }
.adm-sticky .adm-periodbar { margin: 0 0 10px; }
.adm-subbar { display: flex; align-items: center; gap: 2px; overflow-x: auto; scrollbar-width: none; padding-bottom: 6px; }
.adm-subbar::-webkit-scrollbar { display: none; }
.adm-subbar[hidden] { display: none; }
.adm-subbar a { flex: none; padding: 7px 12px; color: var(--muted); font-size: 14px; font-weight: 800; text-decoration: none; white-space: nowrap; border-bottom: 2px solid transparent; border-radius: 8px 8px 0 0; }
.adm-subbar a:hover { color: var(--text); background: var(--surface); }
.adm-subbar a[aria-current] { color: var(--heading); border-bottom-color: var(--gold); }
.adm-h2-link { font-size: 12px; font-weight: 800; color: var(--muted); text-decoration: none; white-space: nowrap; }
.adm-h2-link:hover { color: var(--text); }
/* Le regroupement est un menu ▾ : la barre de période tient sur une ligne sur ordinateur. */
.adm-grp { position: relative; margin-left: auto; }
.adm-menu-pop { position: absolute; z-index: 45; top: calc(100% + 6px); right: 0; min-width: 180px; display: grid; gap: 2px; padding: 6px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 14px; box-shadow: 0 18px 44px rgba(0, 0, 0, .38); }
.adm-menu-pop button { border: 0; background: none; color: var(--text); font: inherit; font-size: 13px; font-weight: 800; text-align: left; min-height: 38px; padding: 0 12px; border-radius: 10px; cursor: pointer; }
.adm-menu-pop button[aria-checked="true"] { background: var(--active-bg); color: var(--active-ink); }
.adm-menu-pop button:disabled { color: var(--muted); opacity: .5; cursor: default; }
.adm-cmp { flex: none; min-height: 40px; padding: 0 14px; border-radius: 12px; border: 1px dashed var(--line); background: none; color: var(--muted);
  font: inherit; font-size: 13px; font-weight: 800; white-space: nowrap; cursor: pointer; }
.adm-cmp[aria-pressed="true"] { border-style: solid; background: var(--surface); color: var(--text); }
@media (min-width: 900px) { .adm-period-row { flex-wrap: nowrap; } }
@media (max-width: 899px) { .adm-grp { margin-left: 0; } }
/* Les puces de période d'un classement tiennent dans la carte : à 320 px de colonne, « Tout » ne
   tient pas sur une ligne, donc elles passent à la ligne (flex-wrap: wrap de .adm-seg) au lieu de
   sortir de la carte. max-width: 100% tient le cadre dans la carte. */
.adm-board-seg { max-width: 100%; margin-bottom: 10px; }
.adm-board-seg button { min-height: 28px; padding: 3px 9px; font-size: 12px; white-space: nowrap; }
/* Tableau de bord : les chiffres et la courbe à gauche, le top du jour à droite, sans défiler. */
.adm-dash { display: grid; gap: 0 18px; }
.adm-dash-main { min-width: 0; }
.adm-dash-side { min-width: 0; }
.adm-dash-side .adm-card { margin-bottom: 0; }
@media (min-width: 1100px) { .adm-dash { grid-template-columns: minmax(0, 1fr) 320px; } }
/* Le menu de gauche ne défile jamais de côté, et son pied reste entier. La liste des entrées est la
   seule zone qui défile : sans cela, flex écrase la liste sous sa hauteur et les entrées du bas
   passent sous le pied (chevauchement visible dès que l'écran est court). */
.adm-side { overflow: hidden; }
.adm-side-top { display: flex; align-items: center; gap: 8px; flex: none; }
.adm-side-top .adm-brand { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.adm-collapse { flex: none; font-size: 14px; }
.adm-find { flex: none; }
.adm-side-foot { flex: none; }
.adm-menu { flex: 1 1 auto; min-height: 0; overflow: hidden auto; overscroll-behavior: contain; }
/* Réduit, le menu ne montre que les icônes ; le titre des groupes et les libellés s'effacent. */
.adm-thin .adm-side { width: 68px; }
.adm-thin .adm-main { margin-left: 68px; }
.adm-thin .adm-brand, .adm-thin .adm-find, .adm-thin .adm-menu-group > small, .adm-thin .adm-menu a span, .adm-thin .adm-side-row, .adm-thin .adm-side-foot .btn span { display: none; }
.adm-thin .adm-collapse { transform: rotate(180deg); }
.adm-thin .adm-side-top { justify-content: center; }
.adm-thin .adm-menu a { justify-content: center; padding: 8px 0; }
.adm-thin .adm-menu a i { position: absolute; margin-left: 22px; }
.adm-thin .adm-menu a { position: relative; }
.adm-thin .adm-side-foot { grid-template-columns: 1fr; }
.adm-thin .adm-side-foot .btn { padding: 7px 0; font-size: 11px; overflow: hidden; }
@media (max-width: 899px) {
  .adm-collapse { display: none; }
  .adm-thin .adm-side { width: 260px; }
  .adm-thin .adm-main { margin-left: 0; }
  .adm-thin .adm-brand, .adm-thin .adm-find, .adm-thin .adm-menu-group > small, .adm-thin .adm-menu a span, .adm-thin .adm-side-row { display: revert; }
  .adm-thin .adm-menu a { justify-content: flex-start; padding: 8px 10px; }
  .adm-thin .adm-side-foot { grid-template-columns: 1fr 1fr; }
}
/* La liste de joueurs défile dans son cadre, en-têtes figés, la colonne Joueur assez large. */
.adm-plist .adm-table { max-height: min(70vh, 720px); overflow: auto; border: 1px solid var(--line); border-radius: 14px; }
.adm-plist .adm-table thead th { position: sticky; top: 0; z-index: 1; background: var(--page); }
.adm-plist .adm-table th:nth-child(2), .adm-plist .adm-table td:nth-child(2) { min-width: 170px; }

/*
  Le sachet est l'image du premier écran et pesait 253 ko pour un booster large de 170 px au plus : voici une version
  400 px (≤ 80 ko), soit 2,3x la taille rendue. Tous ses emplacements sont repris, booster compris (sa règle de base
  est dans styles.css, chargé avant celui-ci), pour qu'un téléphone ne télécharge jamais la grande image.
*/
@media (max-width: 820px) {
  .booster .b-body, .booster .b-top { background-image: url(/pack-front-mobile.webp?v=1f349fff50); }
  .booster::before { -webkit-mask-image: url(/pack-front-mobile.webp?v=1f349fff50); mask-image: url(/pack-front-mobile.webp?v=1f349fff50); }
  .booster.fr .b-body, .booster.fr .b-top { background-image: url(/pack-front-fr-mobile.webp?v=bf80eb1553); }
  .booster.fr::before { -webkit-mask-image: url(/pack-front-fr-mobile.webp?v=bf80eb1553); mask-image: url(/pack-front-fr-mobile.webp?v=bf80eb1553); }
  .rc-thumb i, .ly-pack, .pk-pile i, .pk-fan i, .pk-ico { background-image: url(/pack-front-mobile.webp?v=1f349fff50); }
  .recharge.fr .rc-thumb i, .shop-packs.fr .pk-pile i { background-image: url(/pack-front-fr-mobile.webp?v=bf80eb1553); }
}
