/* Reverse album -- tcg.playrpg.com.br */

:root {
  --bg: #0d1016;
  --bg2: #141924;
  --line: #242c3b;
  --ink: #e8ecf4;
  --dim: #8b96ac;
  --accent: #ffcb3d;
  --accent2: #3d7dff;
  --radius: 14px;
  --gap: 14px;
}

* { box-sizing: border-box; }

/* The lightbox and the login sheet are laid out with `display: grid`, and a
   class selector outranks the user agent's `[hidden] { display: none }` -- so
   without this they are both permanently on screen. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.5 "Segoe UI", system-ui, -apple-system, Roboto, sans-serif;
  -webkit-text-size-adjust: 100%;
}

body {
  /* A faint binder-page texture so the grid does not float on flat black. */
  background-image:
    radial-gradient(ellipse at 50% -10%, #1b2334 0%, transparent 60%);
  background-attachment: fixed;
  min-height: 100vh;
}

a { color: inherit; }

/* ------------------------------------------------------------------ chrome */

.bar {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 16px;
  background: rgba(13, 16, 22, .82);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}

.brand {
  display: flex;
  align-items: center;
  gap: 9px;
  font-weight: 700;
  letter-spacing: .3px;
  text-decoration: none;
}

.brand em { color: var(--accent); font-style: normal; }

.pip {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: linear-gradient(#ef4a4a 0 49%, #fff 49% 51%, #e9edf5 51% 100%);
  border: 2px solid #0d1016;
  box-shadow: 0 0 0 1px #4a556b;
}

.who { font-size: 14px; color: var(--dim); display: flex; align-items: center; gap: 10px; }
.who b { color: var(--ink); }

button { font: inherit; cursor: pointer; }

.ghost {
  background: transparent;
  border: 1px solid var(--line);
  color: var(--dim);
  border-radius: 9px;
  padding: 5px 11px;
  font-size: 13px;
}

.ghost:hover { color: var(--ink); border-color: #3a465e; }

.go {
  background: var(--accent);
  color: #20180a;
  border: 0;
  border-radius: 9px;
  padding: 9px 20px;
  font-weight: 700;
}

main { padding: 26px 16px 70px; max-width: 1400px; margin: 0 auto; }

/* ------------------------------------------------------------------ picker */

.picker h1 { margin: 6px 0 8px; font-size: 30px; letter-spacing: -.4px; }
.lead { color: var(--dim); max-width: 60ch; margin: 0 0 22px; }

.tabs { display: flex; gap: 8px; margin-bottom: 12px; }

.tab {
  background: var(--bg2);
  border: 1px solid var(--line);
  color: var(--dim);
  border-radius: 999px;
  padding: 8px 18px;
}

.tab.on { background: var(--accent); border-color: var(--accent); color: #20180a; font-weight: 600; }

.search {
  width: 100%;
  max-width: 520px;
  background: var(--bg2);
  border: 1px solid var(--line);
  color: var(--ink);
  border-radius: 11px;
  padding: 12px 15px;
  font: inherit;
  margin-bottom: 18px;
}

.search:focus { outline: 2px solid var(--accent2); outline-offset: 1px; }

.facets {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(215px, 1fr));
  gap: 8px;
}

.facet {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  background: var(--bg2);
  border: 1px solid var(--line);
  border-radius: 11px;
  padding: 11px 14px;
  text-decoration: none;
  transition: border-color .12s, transform .12s;
}

.facet:hover { border-color: var(--accent); transform: translateY(-1px); }
.facet span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.facet i { font-style: normal; color: var(--dim); font-size: 13px; flex: none; }

.more { grid-column: 1 / -1; text-align: center; color: var(--dim); padding: 14px; }
.foot { color: #58627a; font-size: 13px; margin-top: 26px; }

/* ------------------------------------------------------------------- album */

.albumhead { margin-bottom: 20px; }
.back { color: var(--dim); text-decoration: none; font-size: 14px; }
.back:hover { color: var(--ink); }
.album h1 { margin: 8px 0 14px; font-size: 30px; letter-spacing: -.4px; }

.progress { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }

.meter {
  flex: 1;
  max-width: 420px;
  height: 7px;
  background: var(--bg2);
  border: 1px solid var(--line);
  border-radius: 999px;
  overflow: hidden;
}

.meter i { display: block; height: 100%; width: 0; background: var(--accent); transition: width .3s ease; }
.progress span { font-size: 14px; color: var(--dim); font-variant-numeric: tabular-nums; }

.tools { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.chk { font-size: 14px; color: var(--dim); display: flex; align-items: center; gap: 7px; cursor: pointer; }
.viewing { color: var(--accent); font-size: 14px; margin: 12px 0 0; }

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: var(--gap);
}

/* The card itself. Colored is the default state; .got is the "collected" one
   -- this is a reverse album, so marking a card takes the colour out of it. */
.slot {
  position: relative;
  aspect-ratio: 245 / 342;
  border-radius: var(--radius);
  background: #10141d;
  border: 1px dashed var(--line);
  overflow: hidden;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.slot > img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--radius);
  transition: filter .45s ease, opacity .45s ease, transform .15s ease;
}

.slot.got > img {
  filter: grayscale(1) contrast(.82) brightness(.72);
  opacity: .5;
}

.slot.got { border-style: solid; }

/* ------------------------------------------------- the wave
 *
 * Marking a card runs a circle of desaturation out from the point that was
 * clicked. The moving part is a single custom property, --wave, which is the
 * radius of that circle as a percentage of the distance to the card's farthest
 * corner; registering it with @property is what makes it animatable at all,
 * since an unregistered custom property flips from one value to the next with
 * no interpolation.
 *
 * The wash is a second, greyed copy of the artwork revealed through that mask.
 * The obvious implementation -- one image, with `backdrop-filter: grayscale(1)`
 * on a masked overlay -- does not work: masking an element makes it its own
 * backdrop root, so there is no longer any backdrop behind it to filter and
 * Chromium silently paints nothing. Each half works alone (an unmasked
 * backdrop-filter greys the card; a masked solid colour draws the disc), which
 * is exactly why it is worth writing down. The copy is built on first click and
 * kept, so an untouched grid still carries one image per card.
 *
 * The wash must be opaque, because it replaces the card rather than tinting it:
 * a dark base matching .slot, then the grey art at the same .5 opacity the
 * settled .got state uses, so the handover at the end is invisible. */

@property --wave {
  syntax: '<percentage>';
  inherits: true;
  initial-value: 0%;
}

.slot {
  --wave: 0%;
  --x: 50%;
  --y: 50%;
}

.slot .glitter {
  position: absolute;
  inset: 0;
  display: none;
  border-radius: var(--radius);
  pointer-events: none;
  z-index: 2;
}

/* Only the cards that would actually sparkle, and only while pointed at. */
.slot.lit[data-foil="2"]:not(.got) .glitter,
.slot.lit[data-foil="3"]:not(.got) .glitter { display: block; }

/* The specks flare near the cursor and vanish elsewhere, which is what real
   glitter does -- it is a mirror, so it only catches you at the right angle.
   pokebox gets this with pow(spotlight, 2.0); here the spotlight is multiplied
   into the texture as a second background layer, and since the composite is
   color-dodge, the black falloff leaves the card untouched. Doing it with a
   mask instead would be the obvious route and is a trap: a mask makes the
   element its own backdrop root, which is what silently killed the first
   version of the wave. */
.glitter {
  background-image:
    radial-gradient(circle at var(--mx, 50%) var(--my, 50%),
      #ffffff 0%, #9aa0aa 16%, #2b2f36 34%, #000000 52%),
    url(/glitter.svg);
  background-size: auto, 32% auto;
  background-repeat: no-repeat, repeat;
  background-blend-mode: multiply;
  mix-blend-mode: color-dodge;
  opacity: calc(.55 + var(--hyp, 0) * .45);
}

.slot .wash,
.slot .ring {
  position: absolute;
  inset: 0;
  display: none;
  border-radius: var(--radius);
  pointer-events: none;
}

.slot.waving .wash,
.slot.waving .ring { display: block; }

.wash { background: #10141d; overflow: hidden; }

.wash img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1) contrast(.82) brightness(.72);
  opacity: .5;
  transition: none;
}

/* Collecting: the grey disc grows out from the click. The soft trailing edge is
   what reads as a wave rather than a hard-edged hole. */
.slot.waving.to-grey .wash {
  mask-image: radial-gradient(circle at var(--x) var(--y),
    #000 0 var(--wave), transparent calc(var(--wave) + 24%));
  -webkit-mask-image: radial-gradient(circle at var(--x) var(--y),
    #000 0 var(--wave), transparent calc(var(--wave) + 24%));
}

/* Un-collecting runs the same circle inverted: colour comes back inside it and
   the card stays grey outside, so the card is never briefly whole. */
.slot.waving.to-colour .wash {
  mask-image: radial-gradient(circle at var(--x) var(--y),
    transparent 0 var(--wave), #000 calc(var(--wave) + 24%));
  -webkit-mask-image: radial-gradient(circle at var(--x) var(--y),
    transparent 0 var(--wave), #000 calc(var(--wave) + 24%));
}

/* The disintegration edge. A narrow band of the greyed artwork riding the wave
 * front, masked a second time by a noise texture so it breaks into flecks
 * rather than sweeping past as a clean arc.
 *
 * It is a separate layer from the wash on purpose. Compositing the noise into
 * the wash itself would punch holes right through the settled grey as well, so
 * the colour would show through where the card is supposed to be spent -- the
 * hole would read as the colour coming back. Here the wash keeps a clean soft
 * edge and the ash rides just ahead of it, which is what sells the crumble. */
.ash {
  position: absolute;
  inset: 0;
  display: none;
  border-radius: var(--radius);
  pointer-events: none;
  background-size: cover;
  background-position: center;
  filter: grayscale(1) contrast(.9) brightness(.85);
  opacity: .85;
  z-index: 1;
}

.slot.waving.to-grey .ash { display: block; }

.slot.waving.to-grey .ash {
  mask-image:
    radial-gradient(circle at var(--x) var(--y),
      transparent 0 calc(var(--wave) - 3%),
      #000 calc(var(--wave) + 4%),
      #000 calc(var(--wave) + 13%),
      transparent calc(var(--wave) + 30%)),
    url(/dissolve.svg);
  mask-size: auto, 30% auto;
  mask-repeat: no-repeat, repeat;
  mask-composite: intersect;
  -webkit-mask-image:
    radial-gradient(circle at var(--x) var(--y),
      transparent 0 calc(var(--wave) - 3%),
      #000 calc(var(--wave) + 4%),
      #000 calc(var(--wave) + 13%),
      transparent calc(var(--wave) + 30%)),
    url(/dissolve.svg);
  -webkit-mask-size: auto, 30% auto;
  -webkit-mask-repeat: no-repeat, repeat;
  -webkit-mask-composite: source-in;
}

/* A bright rim riding the front of the wave. Purely decorative, and screen
   blending keeps it from muddying the artwork it passes over. */
.ring {
  mix-blend-mode: screen;
  background: radial-gradient(circle at var(--x) var(--y),
    transparent 0 calc(var(--wave) - 2%),
    rgba(255, 203, 61, .38) calc(var(--wave) + 1%),
    rgba(255, 255, 255, .28) calc(var(--wave) + 3%),
    transparent calc(var(--wave) + 7%));
}

/* Slow and fairly even, so it reads as the card crumbling away rather than a
   transition playing. The old curve front-loaded almost all the travel into
   the first third, which made it a flick. */
.slot.waving {
  animation: wave var(--wave-ms, 1400ms) cubic-bezier(.32, .12, .45, .96) forwards;
}

@keyframes wave {
  from { --wave: 0%; }
  to   { --wave: 118%; }
}

/* A collected card gets a struck corner tick, so the state reads at a glance
   on a phone where the desaturation alone is easy to miss. */
.slot .tick {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--accent);
  color: #20180a;
  display: grid;
  place-items: center;
  font-size: 15px;
  font-weight: 800;
  opacity: 0;
  transform: scale(.4);
  transition: opacity .2s, transform .2s cubic-bezier(.2, 1.6, .4, 1);
  pointer-events: none;
}

.slot.got .tick { opacity: 1; transform: scale(1); }

.slot .zoom {
  position: absolute;
  bottom: 8px;
  right: 8px;
  width: 28px;
  height: 28px;
  border-radius: 8px;
  border: 0;
  background: rgba(13, 16, 22, .72);
  color: var(--ink);
  font-size: 14px;
  opacity: 0;
  transition: opacity .15s;
}

.slot:hover .zoom, .slot:focus-within .zoom { opacity: 1; }

.cap {
  margin: 6px 2px 0;
  font-size: 12px;
  color: var(--dim);
  line-height: 1.35;
}

.cap b { color: #b9c2d4; font-weight: 600; display: block; }

.cell.hidden { display: none; }

.empty { color: var(--dim); padding: 40px 0; }

/* --------------------------------------------------------------- lightbox */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(6, 8, 12, .93);
  display: grid;
  place-content: center;
  gap: 14px;
  padding: 24px;
  cursor: zoom-out;
}

.lightbox img { max-width: min(92vw, 520px); max-height: 78vh; border-radius: 18px; }
.lbmeta { color: var(--dim); text-align: center; font-size: 14px; }

/* ------------------------------------------------------------------ login */

.sheet {
  position: fixed;
  inset: 0;
  z-index: 70;
  background: rgba(6, 8, 12, .8);
  display: grid;
  place-items: center;
  padding: 20px;
}

.card-panel {
  width: min(420px, 100%);
  background: var(--bg2);
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 24px;
}

.card-panel h2 { margin: 0 0 8px; font-size: 21px; }
.card-panel p { color: var(--dim); font-size: 14px; margin: 0 0 18px; }
.card-panel label { display: block; font-size: 13px; color: var(--dim); margin-bottom: 12px; }

.card-panel input {
  display: block;
  width: 100%;
  margin-top: 5px;
  background: #0d1016;
  border: 1px solid var(--line);
  color: var(--ink);
  border-radius: 9px;
  padding: 10px 12px;
  font: inherit;
}

.err { color: #ff7a7a !important; }
.row { display: flex; gap: 10px; justify-content: flex-end; align-items: center; }

@media (max-width: 560px) {
  .grid { grid-template-columns: repeat(auto-fill, minmax(148px, 1fr)); gap: 10px; }
  .picker h1, .album h1 { font-size: 24px; }
  main { padding: 18px 12px 60px; }
}

/* Handing over from the wash to the plain .got filter must not cross-fade, or
   the card greys a second time after the wave has already passed. */
.slot.snap > img { transition: none; }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
  .slot .wash, .slot .ring { display: none !important; }
}

/* ------------------------------------------------- the card in the hand
 *
 * Hovering tilts the card towards the cursor, lights the point you are
 * pointing at, and — only on cards that are actually foil in real life — drags
 * a spectrum across the surface. The pointer writes four variables and CSS does
 * the rest: --rx/--ry are the tilt, --mx/--my the cursor in percent, and --hyp
 * how far from centre it is (0 at the middle, 1 at the edge), which is what
 * makes the shine strengthen towards the corners the way real foil does.
 *
 * The lit layers cost blend-mode compositing, so they only exist while a card
 * is actually under the cursor -- .lit is added on enter and dropped on leave.
 * A 213-card album otherwise pays for 426 blended layers nobody is looking at. */

.cell { perspective: 900px; }

.slot {
  transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) scale(var(--sc, 1));
  transform-style: preserve-3d;
  transition: transform .4s cubic-bezier(.2, .8, .3, 1), box-shadow .4s ease;
}

/* No transition while the pointer is on the card: the tilt must track the
   cursor exactly, not chase it. The easing is for the spring back on leave. */
.slot.lit {
  transition: none;
  z-index: 3;
  /* The shadow falls away from the cursor, so the light has a direction. This
     sells the 3D far harder than the rotation does on its own -- a tilted card
     with a shadow stuck underneath it still reads as flat. The inset hairline
     is the card's bevel catching the same light. */
  box-shadow:
    var(--shx, 0px) var(--shy, 16px) 34px rgba(0, 0, 0, .6),
    inset 0 0 0 1px rgba(255, 255, 255, .10);
}

/* pokebox runs a brightness/contrast/saturation pass (baseAdjust) on every
   card. A small lift on the one under the cursor makes it look lit rather
   than merely bigger. Collected cards keep their grey -- they are spent. */
.slot.lit:not(.got) > img { filter: contrast(1.06) saturate(1.12) brightness(1.03); }

.cell:has(.slot.lit) { z-index: 3; position: relative; }

.slot .glare,
.slot .foil {
  position: absolute;
  inset: 0;
  display: none;
  border-radius: var(--radius);
  pointer-events: none;
  z-index: 2;
}

.slot.lit .glare { display: block; }
.slot.lit[data-foil]:not(.got) .foil { display: block; }

/* The light you are pointing at. A broad, gentle falloff rather than a tight
   disc -- a small hotspot is what made the old version read as a hard edge
   sliding around under the cursor. */
.glare {
  background: radial-gradient(farthest-corner circle at var(--mx, 50%) var(--my, 50%),
    rgba(255, 255, 255, .42) 0%,
    rgba(255, 255, 255, .16) 35%,
    rgba(0, 0, 0, .12) 72%,
    rgba(0, 0, 0, .28) 100%);
  mix-blend-mode: soft-light;
  opacity: calc(.55 + var(--hyp, 0) * .45);
}

/* Foil, following the approach in selop/pokebox (MIT) -- specifically its
 * reverse-holo/holo-shine fragment shaders, ported from GLSL to a CSS gradient
 * stack. Four things in there are what the first attempt got wrong:
 *
 *   1. It blends with OVERLAY, not color-dodge. Overlay keeps the card's own
 *      luminance, so the foil sits on the art; color-dodge clips to white and
 *      turns every band edge into a hard line.
 *   2. Its palette (`sunpillarGradient`) is six *pastel* colours -- all around
 *      70-76% lightness -- not saturated primaries. Saturated stops band.
 *   3. The gradient is cyclic: colour six interpolates back into colour one.
 *      A repeating-linear-gradient whose last stop is not the first has a seam
 *      at every repeat, which is the line that appeared under the cursor.
 *   4. The pointer shifts the spectrum's PHASE and multiplies a wide, soft
 *      spotlight over it (`rainbow *= spotlight`, ~0.5 to 0.875 across the
 *      whole card). It does not paint a local hotspot.
 *
 * There is one thing that cannot be ported: pokebox ships a per-card mask
 * texture so holo appears only where the card is actually foil. There are no
 * masks for 20k cards here, so the foil covers the whole card and leans on the
 * rarity tier for strength instead. */
.foil {
  background-image:
    /* the spotlight, multiplied over the spectrum */
    radial-gradient(farthest-corner circle at var(--mx, 50%) var(--my, 50%),
      rgba(255, 255, 255, 1) 0%,
      rgba(255, 255, 255, .78) 38%,
      rgba(255, 255, 255, .55) 100%),
    /* the spectrum; the seventh stop repeats the first so the cycle closes */
    repeating-linear-gradient(101deg,
      hsl(2, 100%, 73%)   calc(var(--sp, 0) * 1% + 0%),
      hsl(53, 100%, 69%)  calc(var(--sp, 0) * 1% + 3.7%),
      hsl(93, 100%, 69%)  calc(var(--sp, 0) * 1% + 7.3%),
      hsl(176, 100%, 76%) calc(var(--sp, 0) * 1% + 11%),
      hsl(228, 100%, 74%) calc(var(--sp, 0) * 1% + 14.7%),
      hsl(283, 100%, 73%) calc(var(--sp, 0) * 1% + 18.3%),
      hsl(2, 100%, 73%)   calc(var(--sp, 0) * 1% + 22%));
  background-blend-mode: multiply;
  mix-blend-mode: overlay;
  opacity: calc(var(--foil-max, .4) * (.55 + var(--hyp, 0) * .45));
}

/* How loud the foil is, by what the card actually is. A Common has none; a
   Rare Holo shimmers; a Rainbow Rare is supposed to be obnoxious. */
.slot[data-foil="1"] { --foil-max: .50; }
.slot[data-foil="2"] { --foil-max: .72; }
.slot[data-foil="3"] { --foil-max: .95; }

/* Tilting a card is a pointing-device idea. On a touch screen the same handlers
   would fight the scroll, and there is no hover to leave. */
@media (hover: none), (pointer: coarse) {
  .slot { transform: none; }
  .slot .glare, .slot .foil { display: none !important; }
}

@media (prefers-reduced-motion: reduce) {
  .slot { transform: none !important; transition: none !important; }
}

/* Printing label on a split card. The API has one scan per card, not one per
   printing, so a reverse holo shows the same art -- the tag is what tells the
   two slots apart, and it has to be legible enough to do that job. */
.vtag {
  font-style: normal;
  font-weight: 600;
  font-size: 11px;
  letter-spacing: .2px;
  color: var(--accent);
  border: 1px solid rgba(255, 203, 61, .35);
  border-radius: 5px;
  padding: 0 5px;
  margin-left: 5px;
  white-space: nowrap;
}

/* A card the CDN has no scan for. Deliberately looks like an empty binder
   pocket rather than a broken image -- the slot is real, the picture is not. */
.slot.noart {
  display: grid;
  place-items: center;
  background:
    repeating-linear-gradient(45deg, #11161f 0 8px, #0e131b 8px 16px);
  border-style: dashed;
}

.noart-msg {
  color: #5f6a82;
  font-size: 12px;
  text-align: center;
  line-height: 1.5;
  padding: 8px;
}

.noart-msg small { color: #46506a; font-size: 11px; }


#mine { margin-bottom: 38px; }

/* Once you have albums of your own, the catalogue below is a lookup, not the
   headline -- so it is demoted rather than removed. */
#mine:not([hidden]) ~ #pickhead { font-size: 20px; color: var(--dim); }

/* Toggle buttons in the album toolbar, replacing the checkboxes. A checkbox
   reads as a form; these read as a view you are currently in. */

.seg {
  display: inline-flex;
  background: var(--bg2);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 3px;
  gap: 2px;
}

.segb {
  background: transparent;
  border: 0;
  color: var(--dim);
  border-radius: 999px;
  padding: 6px 14px;
  font-size: 13px;
  white-space: nowrap;
  transition: background .12s, color .12s;
}

.segb:hover { color: var(--ink); }
.segb.on { background: var(--accent); color: #20180a; font-weight: 600; }

/* The on state has to be unmistakable, because with it off the album simply
   looks like it has fewer cards in it. */
.toggle {
  background: var(--bg2);
  border: 1px solid var(--line);
  color: var(--dim);
  border-radius: 999px;
  padding: 7px 15px;
  font-size: 13px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  transition: background .12s, color .12s, border-color .12s;
}

.toggle::before {
  content: "";
  width: 26px;
  height: 15px;
  flex: none;
  border-radius: 999px;
  background: #0d1016;
  border: 1px solid var(--line);
  box-shadow: inset 11px 0 0 -8px var(--dim);
  transition: box-shadow .16s ease, background .16s;
}

.toggle:hover { color: var(--ink); border-color: #3a465e; }

.toggle.on { color: #20180a; background: var(--accent); border-color: var(--accent); font-weight: 600; }
.toggle.on::before { background: #7a5f12; border-color: #7a5f12; box-shadow: inset -11px 0 0 -8px #fff; }

.segb:focus-visible, .toggle:focus-visible { outline: 2px solid var(--accent2); outline-offset: 2px; }

@media (max-width: 560px) {
  .segb { padding: 6px 10px; font-size: 12px; }
  .toggle { padding: 6px 12px; font-size: 12px; }
}

/* Tag on a search result when the one box is searching Pokemon and
   illustrators at the same time -- "Aggron" and "Ken Sugimori" otherwise look
   like the same kind of thing. */
.facet .kind {
  display: block;
  font-style: normal;
  font-size: 11px;
  color: #5f6a82;
  letter-spacing: .3px;
}

/* ------------------------------------------------- album cards
 *
 * The tiles for albums you have started. They carry a card out of the album
 * itself -- one you own where possible -- because "Pikachu" and "Ken Sugimori"
 * as plain text tiles are indistinguishable at a glance, while the artwork is
 * recognisable instantly. The art is dimmed hard and overlaid, since it is
 * scenery: the number is the content. */

#minelist {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 14px;
}

.album-card {
  position: relative;
  display: block;
  min-height: 148px;
  border-radius: 16px;
  border: 1px solid var(--line);
  background: var(--bg2);
  overflow: hidden;
  text-decoration: none;
  isolation: isolate;
  transition: transform .16s cubic-bezier(.2,.8,.3,1), border-color .16s, box-shadow .16s;
}

.album-card:hover {
  transform: translateY(-3px);
  border-color: var(--accent);
  box-shadow: 0 14px 30px rgba(0, 0, 0, .5);
}

/* Two stacked art layers. The tile rotates through the cards in the album, and
   painting the hidden layer before swapping which one is visible is what makes
   that a cross-fade instead of a flicker through the bare background. */
.album-card { --art-op: .5; }
.album-card:hover { --art-op: .64; }

.album-card .art {
  position: absolute;
  inset: 0;
  z-index: 0;
  /* Framed on the card's illustration window rather than centred: a card scan
     is mostly text box, and the top third is the part worth showing. */
  background-size: 165%;
  background-position: 50% 14%;
  filter: saturate(1.15);
  opacity: var(--art-op);
  transition: opacity .85s ease, transform .5s ease;
}

.album-card .art.alt { opacity: 0; }
.album-card.flip .art:not(.alt) { opacity: 0; }
.album-card.flip .art.alt { opacity: var(--art-op); }

.album-card:hover .art { transform: scale(1.07); }

.album-card .shade {
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(105deg, rgba(13,16,22,.97) 30%, rgba(13,16,22,.70) 62%, rgba(13,16,22,.32) 100%),
    linear-gradient(to top, rgba(13,16,22,.92), transparent 55%);
}

.album-card .body {
  position: relative;
  z-index: 2;
  display: block;
  padding: 14px 16px 15px;
}

.kindtag {
  display: block;
  font-style: normal;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 1.1px;
  color: var(--dim);
  margin-bottom: 3px;
}

.album-card .name {
  display: block;
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -.2px;
  color: var(--ink);
  line-height: 1.2;
  margin-bottom: 12px;
  text-shadow: 0 1px 10px rgba(0,0,0,.7);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.statline {
  display: flex;
  align-items: baseline;
  gap: 9px;
  margin-bottom: 9px;
}

.pct {
  font-size: 30px;
  font-weight: 800;
  line-height: 1;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  text-shadow: 0 2px 14px rgba(255, 203, 61, .3);
}

.pct small { font-size: 14px; font-weight: 700; margin-left: 1px; }

.of { font-size: 12.5px; color: var(--dim); font-variant-numeric: tabular-nums; }

/* Named .pbar, not .bar: the site header is <header class="bar">, and with
   box-sizing:border-box its padding:10px 16px collapsed this element's content
   box to zero height, so the fill's height:100% resolved to 0 and the bar
   rendered empty at 21px tall. */
.album-card .pbar {
  display: block;
  height: 5px;
  border-radius: 999px;
  background: rgba(0, 0, 0, .55);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.06);
  overflow: hidden;
}

.album-card .pbar i {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, #ffb01f, var(--accent));
  box-shadow: 0 0 12px rgba(255, 203, 61, .55);
  transition: width .4s ease;
}

/* A finished album should be unmistakable across the page. */
.album-card.done { border-color: var(--accent); }
.album-card.done .pbar i { background: linear-gradient(90deg, #6ee787, #ffcb3d); }

.ribbon {
  position: absolute;
  z-index: 3;
  top: 11px;
  right: -30px;
  transform: rotate(35deg);
  background: var(--accent);
  color: #20180a;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .8px;
  text-transform: uppercase;
  padding: 3px 34px;
  box-shadow: 0 3px 10px rgba(0,0,0,.5);
}

@media (max-width: 560px) {
  #minelist { grid-template-columns: repeat(auto-fill, minmax(215px, 1fr)); }
  .album-card { min-height: 132px; }
  .pct { font-size: 25px; }
  .album-card .name { font-size: 17px; }
}

/* Follow an album you own nothing from. Same pill as the other tools, but the
   star carries the state so it reads at a glance next to them. */
.ghost.star { display: inline-flex; align-items: center; gap: 7px; padding: 7px 14px; }
.ghost.star .ic { font-size: 14px; line-height: 1; }
.ghost.star.on { color: var(--accent); border-color: rgba(255, 203, 61, .55); background: rgba(255, 203, 61, .08); }

/* Save failures have to be visible. A card that shows as marked but never
   reached the server looks like it worked, and the loss only surfaces on the
   next reload -- which is exactly how it gets reported as "nothing saved". */
.toast {
  position: fixed;
  left: 50%;
  bottom: 26px;
  transform: translateX(-50%);
  z-index: 90;
  max-width: min(90vw, 460px);
  background: var(--bg2);
  border: 1px solid var(--line);
  border-radius: 11px;
  padding: 11px 17px;
  font-size: 14px;
  color: var(--ink);
  box-shadow: 0 12px 30px rgba(0, 0, 0, .6);
}

.toast.bad { border-color: #ff7a7a; color: #ffd9d9; }

#mineview { margin: 2px 0 12px; }
#minelead b { color: var(--accent); font-weight: 600; }
